or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

client.mdcommon.mdindex.mdserver-adapters.mdserver.md
tile.json

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
      });
  }
}