Integration with µWebSockets.js

µWebSockets.js is an HTTP/WebSocket server for Node.js.

µWebSockets.js is an alternative to Node.js's built-in HTTP server implementation. It is much faster than Node.js's http module as you can see in the benchmarks in the GitHub repo. Despite its name, it is not a WebSocket-only server, it does HTTP as well.

Since Hive Gateway is framework and environment agnostic, it supports µWebSockets.js out of the box with a simple configuration.

Example

import { App, HttpRequest, HttpResponse } from "uWebSockets.js";
import { createGatewayRuntime } from "@graphql-hive/gateway-runtime";

interface ServerContext {
  req: HttpRequest;
  res: HttpResponse;
}

export const gatewayRuntime =
  createGatewayRuntime<ServerContext>(/* Your configuration */);

App()
  .any("/*", gatewayRuntime)
  .listen("localhost", 4000, () => {
    console.log(`Server is running on http://localhost:4000`);
  });

Subscriptions with WebSockets

You can also use WebSockets instead of SSE with graphql-ws;

npm i graphql-ws
import { execute, ExecutionArgs, subscribe } from "graphql";
import { makeBehavior } from "graphql-ws/lib/use/uWebSockets";
import { App, HttpRequest, HttpResponse } from "uWebSockets.js";
import { createGatewayRuntime } from "@graphql-hive/gateway-runtime";

interface ServerContext {
  req: HttpRequest;
  res: HttpResponse;
}

export const serveRuntime =
  createGatewayRuntime<ServerContext>(/* Your configuration */);

// Hive Gateway's envelop may augment the `execute` and `subscribe` operations
// so we need to make sure we always use the freshest instance
type EnvelopedExecutionArgs = ExecutionArgs & {
  rootValue: {
    execute: typeof execute;
    subscribe: typeof subscribe;
  };
};

const wsHandler = makeBehavior({
  execute: (args) => (args as EnvelopedExecutionArgs).rootValue.execute(args),
  subscribe: (args) =>
    (args as EnvelopedExecutionArgs).rootValue.subscribe(args),
  onSubscribe: async (ctx, msg) => {
    const { schema, execute, subscribe, contextFactory, parse, validate } =
      serveRuntime.getEnveloped(ctx);

    const args: EnvelopedExecutionArgs = {
      schema,
      operationName: msg.payload.operationName,
      document: parse(msg.payload.query),
      variableValues: msg.payload.variables,
      contextValue: await contextFactory(),
      rootValue: {
        execute,
        subscribe,
      },
    };

    const errors = validate(args.schema, args.document);
    if (errors.length) return errors;
    return args;
  },
});

App()
  .any("/*", gatewayRuntime)
  .ws(gatewayRuntime.graphqlEndpoint, wsHandler)
  .listen(() => {
    console.log(`Server is running on http://localhost:4000`);
  });