CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-graphql-ws

Coherent, zero-dependency, lazy, simple, GraphQL over WebSocket Protocol compliant server and client

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

server-adapters.mddocs/

Server Adapters

GraphQL-WS provides specialized adapters for integrating with different WebSocket server implementations across multiple JavaScript runtimes. Each adapter handles the specifics of the underlying WebSocket library while providing a consistent GraphQL over WebSocket experience.

Capabilities

ws Adapter

Integration with the popular ws WebSocket library for Node.js applications.

/**
 * Use GraphQL-WS server with ws WebSocket server
 * @param options - Server options with ws-specific context
 * @param ws - WebSocket server instance from ws library
 * @param keepAlive - Optional keep-alive ping interval in milliseconds
 * @returns Disposable for cleanup
 */
function useServer<P = Record<string, unknown>, E = unknown>(
  options: ServerOptions<P, Extra & Partial<E>>,
  ws: WebSocketServer,
  keepAlive?: number
): Disposable;

interface Extra {
  /** The WebSocket connection from ws library */
  socket: WebSocket;
  /** Initial HTTP upgrade request */
  request: http.IncomingMessage;
}

type WebSocketServer = import("ws").WebSocketServer;
type WebSocket = import("ws").WebSocket;

Usage Examples:

import { WebSocketServer } from "ws";
import { useServer } from "graphql-ws/use/ws";

const wsServer = new WebSocketServer({ port: 4000, path: "/graphql" });

const cleanup = useServer(
  {
    schema: mySchema,
    onConnect: (ctx) => {
      console.log("Connected:", ctx.extra.request.url);
      return { ip: ctx.extra.request.socket.remoteAddress };
    },
  },
  wsServer,
  30000 // 30s keep-alive
);

// Later cleanup
process.on("SIGTERM", cleanup);

uWebSockets.js Adapter

High-performance integration with uWebSockets.js for maximum throughput applications.

/**
 * Make WebSocket behavior for uWebSockets.js server
 * @param options - Server options with uWS-specific context
 * @param behavior - Optional existing behavior to extend
 * @param keepAlive - Optional keep-alive ping interval in milliseconds  
 * @returns WebSocket behavior object
 */
function makeBehavior<P = Record<string, unknown>, E = unknown>(
  options: ServerOptions<P, Extra & Partial<E>>,
  behavior?: uWS.WebSocketBehavior<unknown>,
  keepAlive?: number
): uWS.WebSocketBehavior<unknown>;

interface Extra extends UpgradeData {
  /** uWebSockets.js WebSocket with upgrade data */
  socket: uWS.WebSocket<unknown> & UpgradeData;
}

interface UpgradeData {
  /** Persisted HTTP request information */
  persistedRequest: PersistedRequest;
}

interface PersistedRequest {
  /** HTTP method */
  method: string;
  /** Request URL */
  url: string;
  /** Raw query string */
  query: string;
  /** HTTP headers */
  headers: http.IncomingHttpHeaders;
}

Usage Examples:

import uWS from "uWebSockets.js";
import { makeBehavior } from "graphql-ws/use/uWebSockets";

const app = uWS.App({
  // SSL config if needed
}).ws("/graphql", makeBehavior({
  schema: mySchema,
  onConnect: (ctx) => {
    const req = ctx.extra.persistedRequest;
    console.log("uWS connection:", req.method, req.url);
    return { userAgent: req.headers["user-agent"] };
  },
}, {
  // Additional uWS behavior
  maxBackpressure: 64 * 1024,
  maxCompressedSize: 64 * 1024,
})).listen(4000, (token) => {
  if (token) {
    console.log("uWebSockets server listening on port 4000");
  }
});

Fastify WebSocket Adapter

Integration with Fastify's WebSocket plugin for Fastify-based applications.

/**
 * Make WebSocket handler for @fastify/websocket route
 * @param options - Server options with Fastify-specific context
 * @param keepAlive - Optional keep-alive ping interval in milliseconds
 * @returns WebSocket handler function
 */
function makeHandler<P = Record<string, unknown>, E = unknown>(
  options: ServerOptions<P, Extra & Partial<E>>,
  keepAlive?: number
): WebsocketHandler;

interface Extra {
  /** WebSocket connection */
  socket: WebSocket;
  /** Fastify request object */
  request: FastifyRequest;
}

type WebsocketHandler = import("@fastify/websocket").WebsocketHandler;
type FastifyRequest = import("fastify").FastifyRequest;

Usage Examples:

import Fastify from "fastify";
import { makeHandler } from "graphql-ws/use/@fastify/websocket";

const fastify = Fastify();
await fastify.register(require("@fastify/websocket"));

fastify.register(async function (fastify) {
  fastify.get("/graphql", { websocket: true }, makeHandler({
    schema: mySchema,
    onConnect: (ctx) => {
      console.log("Fastify WebSocket:", ctx.extra.request.url);
      return { user: ctx.extra.request.user };
    },
  }));
});

await fastify.listen({ port: 4000 });

Bun Adapter

Native integration with Bun's built-in WebSocket server for Bun runtime applications.

/**
 * Make WebSocket handler for Bun WebSocket server
 * @param options - Server options with Bun-specific context
 * @returns WebSocket handler function
 */
function makeHandler<P = Record<string, unknown>, E = unknown>(
  options: ServerOptions<P, Extra & Partial<E>>
): WebSocketHandler;

interface Extra {
  /** Bun ServerWebSocket instance */
  socket: ServerWebSocket;
}

type WebSocketHandler = import("bun").WebSocketHandler;
type ServerWebSocket = import("bun").ServerWebSocket;

// Re-exported utility
function handleProtocols(protocols: Set<string> | string[] | string): string | false;

Usage Examples:

import { makeHandler, handleProtocols } from "graphql-ws/use/bun";

const server = Bun.serve({
  port: 4000,
  fetch(req, server) {
    const url = new URL(req.url);
    if (url.pathname === "/graphql") {
      const success = server.upgrade(req, {
        headers: {
          "Sec-WebSocket-Protocol": handleProtocols(
            req.headers.get("Sec-WebSocket-Protocol") || ""
          ) || "",
        },
      });
      if (success) return undefined;
    }
    return new Response("Not found", { status: 404 });
  },
  websocket: makeHandler({
    schema: mySchema,
    onConnect: (ctx) => {
      console.log("Bun WebSocket connection established");
      return true;
    },
  }),
});

crossws Adapter

Integration with crossws for universal WebSocket handling across different JavaScript runtimes.

/**
 * Make hooks for crossws universal WebSocket handling
 * @param options - Server options with crossws-specific context and production flag
 * @returns crossws hooks object
 */
function makeHooks<P = Record<string, unknown>, E = unknown>(
  options: ServerOptions<P, Extra & Partial<E>> & { isProd?: boolean }
): ReturnType<typeof defineHooks>;

interface Extra {
  /** crossws WebSocket peer connection */
  socket: Peer['websocket'];
}

type Peer = import("crossws").Peer;

Usage Examples:

import { defineHooks } from "crossws";
import { makeHooks } from "graphql-ws/use/crossws";

export default defineHooks(makeHooks({
  schema: mySchema,
  isProd: process.env.NODE_ENV === "production",
  onConnect: (ctx) => {
    console.log("crossws connection established");
    return true;
  },
}));

// In your web framework (Nitro, Nuxt, etc.)
// The hooks will be automatically used

Deno Adapter

Native integration with Deno's WebSocket API for Deno runtime applications.

/**
 * Make WebSocket handler for Deno WebSocket server
 * @param options - Server options with Deno-specific context
 * @returns WebSocket handler function
 */
function makeHandler<P = Record<string, unknown>, E = unknown>(
  options: ServerOptions<P, Extra & Partial<E>>
): (socket: WebSocket) => void;

interface Extra {
  /** Deno WebSocket instance */
  socket: WebSocket;
}

// Re-exported constant
const GRAPHQL_TRANSPORT_WS_PROTOCOL = "graphql-transport-ws";

Usage Examples:

import { makeHandler, GRAPHQL_TRANSPORT_WS_PROTOCOL } from "graphql-ws/use/deno";

const handler = makeHandler({
  schema: mySchema,
  onConnect: (ctx) => {
    console.log("Deno WebSocket connection");
    return true;
  },
});

Deno.serve({ port: 4000 }, (req) => {
  if (req.headers.get("upgrade") === "websocket") {
    const { socket, response } = Deno.upgradeWebSocket(req, {
      protocol: GRAPHQL_TRANSPORT_WS_PROTOCOL,
    });
    
    handler(socket);
    return response;
  }
  
  return new Response("GraphQL over WebSocket", { status: 426 });
});

Adapter Selection Guide

Performance Considerations

  • uWebSockets.js: Highest performance, lowest latency, ideal for high-throughput applications
  • Bun: Native Bun runtime performance, good for Bun-based applications
  • ws: Good performance, most mature, wide ecosystem support
  • Fastify: Integrates with Fastify's performance optimizations
  • crossws: Universal compatibility, good for multi-runtime applications
  • Deno: Native Deno performance, good for Deno-based applications

Runtime Compatibility

  • Node.js: ws, uWebSockets.js, Fastify
  • Bun: Bun adapter (native), also supports ws and uWebSockets.js
  • Deno: Deno adapter (native)
  • Universal: crossws (works across Node.js, Bun, Deno, Cloudflare Workers)

Integration Patterns

// Framework-agnostic server setup
function createGraphQLWebSocketServer(runtime: "node" | "bun" | "deno") {
  const serverOptions = {
    schema: mySchema,
    onConnect: (ctx) => ({ timestamp: Date.now() }),
  };

  switch (runtime) {
    case "node":
      const { WebSocketServer } = await import("ws");
      const { useServer } = await import("graphql-ws/use/ws");
      const wsServer = new WebSocketServer({ port: 4000 });
      return useServer(serverOptions, wsServer);
      
    case "bun":
      const { makeHandler } = await import("graphql-ws/use/bun");
      return Bun.serve({
        port: 4000,  
        websocket: makeHandler(serverOptions),
        // ... fetch handler
      });
      
    case "deno":
      const { makeHandler: denoHandler } = await import("graphql-ws/use/deno");
      return Deno.serve({ port: 4000 }, (req) => {
        // ... upgrade logic with denoHandler
      });
  }
}

docs

client.md

common.md

index.md

server-adapters.md

server.md

tile.json