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.
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);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");
}
});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 });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;
},
}),
});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 usedNative 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 });
});// 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
});
}
}