0.5.1 • Published 4 years ago

graphyne-ws v0.5.1

Weekly downloads
6
License
MIT
Repository
github
Last release
4 years ago

GraphQL Subscriptions over WebSocket for Graphyne

npm ci codecov PRs Welcome

This package is highly experimental and may be changed or removed at any time!

WebSocket support implementing GraphQL over WebSocket Protocol.

For now, this package is exclusively used with Graphyne.

Install

Since graphyne-ws uses ws under the hood, you must also install it if you haven't already.

npm i graphyne-ws ws
// or
yarn add graphyne-ws ws

Usage

Example

Create a WebSocket.Server instance and uses wsHandler to handle its connection event.

With graphyne-server

const http = require('http');
const { GraphQL, httpHandler } = require('graphyne-server');
const { wsHandler } = require('graphyne-ws');

// Create a Graphyne instance
const GQL = new GraphQL(options);
const server = http.createServer(httpHandler(GQL));

// Create a WebSocket.Server from the `ws` package
const wss = new WebSocket.Server({ path: '/graphql', server });

// Attach wsHandler to WebSocket.Server `connection` event
// See https://github.com/websockets/ws/blob/master/doc/ws.md#event-connection
wss.on('connection', wsHandler(GQL, options));

server.listen(3000, () => {
  console.log(`🚀  Server ready at http://localhost:3000/graphql`);
});

Without graphyne-server

graphyne-ws also exports GraphQL constructor to be used without graphyne-server.

const { GraphQL, wsHandler } = require('graphyne-ws');

// Create a Graphyne instance
const GQL = new GraphQL(options);

// Create a WebSocket.Server from the `ws` package (Use options.port to create a HTTP server internally)
const wss = new WebSocket.Server({ path: '/graphql', port: 3000 }, () => {
  console.log(`🚀  WebSocket Server ready at ws://localhost:3000/graphql`);
})

// Attach wsHandler to WebSocket.Server `connection` event
// See https://github.com/websockets/ws/blob/master/doc/ws.md#event-connection
wss.on('connection', wsHandler(GQL, options));

See more examples here.

API

wsHandler(GQL, options)

Create a handler for incoming WebSocket connection (from wss.on('connection')) and execute GraphQL based on GraphQL over WebSocket Protocol.

GQL is an instance of GraphQL.

options accepts the following:

  • context: An object or function called to creates a context shared across resolvers per connection. The function receives an object with the following:
  • onSubscriptionConnection: (Experimental) A function to called with the SubscriptionConnection instance whenever one is created (on every websocket connection).

Class: SubscriptionConnection

This class represents an internal subscription connection that handles incoming message (ws.on('message')) via SubscriptionConnection#handleMessage. See /packages/graphyne-worker/src/handler.ts for its usage.

This class, along with onSubscriptionConnection, are experimental and may suffer breaking changes at any time.

SubscriptionConnection#socket

SubscriptionConnection exposes socket which is the same WebSocket from wss.on('connection').

This is helpful if you want to implement something like a "heartbeat" to detect broken connections according to RFC 6455 Ping-Pong:

const HEARTBEAT_INTERVAL = 10000; // 10 sec

const wss = new WebSocket.Server({ path: '/graphql', server });

wss.on('connection', wsHandler(GQL, {
  onSubscriptionConnection: (connection) => {
    connection.socket.isAlive = true;
    connection.socket.on('pong', () => {
      connection.socket.isAlive = true;
    });
  }
}));

const wssPingPong = setInterval(() => {
  wss.clients.forEach((ws) => {
    if (ws.isAlive === false) {
      ws.terminate();
      return;
    }]
    ws.isAlive = false;
    ws.ping();
  });
}, HEARTBEAT_INTERVAL);

wss.on('close', function close() {
  clearInterval(wssPingPong);
});

Events

An instance of SubscriptionConnection extends EventEmitter.

It emits several events upon connection acknowledged, subscription started or stopped, and connection terminated.

import { wsHandler } from "graphyne-ws";

wsHandler(GQL, wss, {
  onSubscriptionConnection: (connection) => {
    // called after the connection is initialized and acknowledged
    connection.on('connection_init', (connectionParams) => {
      // optional parameters that the client specifies in connectionParams
    });

    // called after a subscription operation has been started
    connection.on('subscription_start', (id, payload, context) => {
      // id is the GraphQL operation ID
      // payload is the GQL payload with `query`, `variables`, and `operationName`.
      // context is the resolved context from options.context
    });

    // called after the operation has been stopped
    connection.on('subscription_stop', (id) => {
      // id is the GraphQL operation ID that was stopped
    });

    // called after the connection is terminated
    connection.on('connection_terminate', () => {
      // This event has no argument
    });

  },
});

Contributing

Please see my contributing.md.

License

MIT

0.5.1

4 years ago

0.5.0

4 years ago

0.4.2

4 years ago

0.4.0

4 years ago

0.3.0

4 years ago

0.3.0-alpha.0

4 years ago

0.2.0

4 years ago

0.1.15

4 years ago

0.1.14

4 years ago

0.1.13

4 years ago

0.1.12

4 years ago

0.1.11

4 years ago

0.1.10

4 years ago

0.1.8

4 years ago

0.1.9

4 years ago

0.1.7

4 years ago

0.1.6

4 years ago

0.1.5

4 years ago

0.1.4

4 years ago

0.1.3

4 years ago

0.1.2

4 years ago

0.1.0

4 years ago

0.1.1

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago