Get Started

Get Started

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

For detailed documentation and API reference, check out the documentation page. If you need short and concise code snippets for starting with common use-cases, the recipes page is the right place for you.

Install

npm i graphql-ws

Create a GraphQL schema

import { GraphQLSchema, GraphQLObjectType, GraphQLString } from 'graphql';
 
/**
 * Construct a GraphQL schema and define the necessary resolvers.
 *
 * type Query {
 *   hello: String
 * }
 * type Subscription {
 *   greetings: String
 * }
 */
export const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'Query',
    fields: {
      hello: {
        type: GraphQLString,
        resolve: () => 'world',
      },
    },
  }),
  subscription: new GraphQLObjectType({
    name: 'Subscription',
    fields: {
      greetings: {
        type: GraphQLString,
        subscribe: async function* () {
          for (const hi of ['Hi', 'Bonjour', 'Hola', 'Ciao', 'Zdravo']) {
            yield { greetings: hi };
          }
        },
      },
    },
  }),
});

Start the server

With ws

import { WebSocketServer } from 'ws'; // yarn add ws
// import ws from 'ws'; yarn add ws@7
// const WebSocketServer = ws.Server;
import { useServer } from 'graphql-ws/lib/use/ws';
import { schema } from './previous-step';
 
const server = new WebSocketServer({
  port: 4000,
  path: '/graphql',
});
 
useServer({ schema }, server);
 
console.log('Listening to port 4000');

With uWebSockets.js

import uWS from 'uWebSockets.js'; // yarn add uWebSockets.js@uNetworking/uWebSockets.js#<tag>
import { makeBehavior } from 'graphql-ws/lib/use/uWebSockets';
import { schema } from './previous-step';
 
uWS
  .App()
  .ws('/graphql', makeBehavior({ schema }))
  .listen(4000, (listenSocket) => {
    if (listenSocket) {
      console.log('Listening to port 4000');
    }
  });

With @fastify/websocket

import Fastify from 'fastify'; // yarn add fastify
import fastifyWebsocket from '@fastify/websocket'; // yarn add @fastify/websocket
import { makeHandler } from 'graphql-ws/lib/use/@fastify/websocket';
import { schema } from './previous-step';
 
const fastify = Fastify();
fastify.register(fastifyWebsocket);
 
fastify.register(async (fastify) => {
  fastify.get('/graphql', { websocket: true }, makeHandler({ schema }));
});
 
fastify.listen(4000, (err) => {
  if (err) {
    fastify.log.error(err);
    return process.exit(1);
  }
  console.log('Listening to port 4000');
});

With Bun

import { makeHandler, handleProtocols } from 'graphql-ws/lib/use/bun';
import { schema } from './previous-step';
 
Bun.serve({
  fetch(req, server) {
    const [path, _search] = req.url.split('?');
    if (!path.endsWith('/graphql')) {
      return new Response('Not Found', { status: 404 });
    }
    if (req.headers.get('upgrade') != 'websocket') {
      return new Response('Upgrade Required', { status: 426 });
    }
    if (!handleProtocols(req.headers.get('sec-websocket-protocol') || '')) {
      return new Response('Bad Request', { status: 404 });
    }
    if (!server.upgrade(req)) {
      return new Response('Internal Server Error', { status: 500 });
    }
    return new Response();
  },
  websocket: makeHandler({ schema }),
  port: 4000,
});
 
console.log('Listening to port 4000');

With Deno

import { serve } from 'https://deno.land/std/http/mod.ts';
import {
  makeHandler,
  GRAPHQL_TRANSPORT_WS_PROTOCOL,
} from 'https://esm.sh/graphql-ws/lib/use/deno';
import { schema } from './previous-step.ts';
 
const handler = makeHandler({ schema });
 
serve(
  (req: Request) => {
    const [path, _search] = req.url.split('?');
    if (!path.endsWith('/graphql')) {
      return new Response('Not Found', { status: 404 });
    }
    if (req.headers.get('upgrade') != 'websocket') {
      return new Response('Upgrade Required', { status: 426 });
    }
    const { socket, response } = Deno.upgradeWebSocket(req, {
      protocol: GRAPHQL_TRANSPORT_WS_PROTOCOL,
      idleTimeout: 12_000,
    });
    handler(socket);
    return response;
  },
  { port: 4000 },
);

Use the client

import { createClient } from 'graphql-ws';
 
const client = createClient({
  url: 'ws://localhost:4000/graphql',
});
 
// query
(async () => {
  const query = client.iterate({
    query: '{ hello }',
  });
 
  const { value } = await query.next();
  expect(value).toEqual({ hello: 'world' });
})();
 
// subscription
(async () => {
  const subscription = client.iterate({
    query: 'subscription { greetings }',
  });
 
  for await (const event of subscription) {
    expect(event).toEqual({ greetings: 'Hi' });
 
    // complete a running subscription by breaking the iterator loop
    break;
  }
})();