Releases: enisdenjo/graphql-ws
Releases · enisdenjo/graphql-ws
v5.5.3
v5.5.2
v5.5.1
v5.5.0
v5.4.1
v5.4.0
5.4.0 (2021-08-21)
Bug Fixes
- client: Specify and fail on fatal internal WebSocket close codes (a720125)
- Use
4406
close code for unsupported subprotocol (1002
is an internal WebSocket close code) (df85281) - Use
4500
close code for internal server errors (1011
is an internal WebSocket close code) (3c0316d)
Features
v5.3.0
v5.2.0
5.2.0 (2021-06-21)
Features
- server: Optional
onPing
andonPong
message type listeners (f36066f)
Server usage with ws and subprotocol pings and pongs
import ws from 'ws'; // yarn add ws
import { makeServer, stringifyMessage, MessageType, CloseCode } from 'graphql-ws';
import { schema } from './my-graphql-schema';
// make
const server = makeServer({ schema });
// create websocket server
const wsServer = new ws.Server({
port: 4000,
path: '/graphql',
});
// implement
wsServer.on('connection', (socket, request) => {
// subprotocol pinger because WS level ping/pongs might not be available
let pinger, pongWait;
function ping() {
if (socket.readyState === socket.OPEN) {
// send the subprotocol level ping message
socket.send(stringifyMessage({ type: MessageType.Ping }));
// wait for the pong for 6 seconds and then terminate
pongWait = setTimeout(() => {
clearInterval(pinger);
socket.close();
}, 6_000);
}
}
// ping the client on an interval every 12 seconds
pinger = setInterval(() => ping(), 12_000);
// a new socket opened, let graphql-ws take over
const closed = server.opened(
{
protocol: socket.protocol, // will be validated
send: (data) => socket.send(data),
close: (code, reason) => socket.close(code, reason),
onMessage: (cb) =>
socket.on('message', async (event) => {
try {
// wait for the the operation to complete
// - if init message, waits for connect
// - if query/mutation, waits for result
// - if subscription, waits for complete
await cb(event.toString());
} catch (err) {
// all errors that could be thrown during the
// execution of operations will be caught here
socket.close(CloseCode.InternalServerError, err.message);
}
}),
// pong received, clear termination timeout
onPong: () => clearTimeout(pongWait),
},
// pass values to the `extra` field in the context
{ socket, request },
);
// notify server that the socket closed and stop the pinger
socket.once('close', (code, reason) => {
clearTimeout(pongWait);
clearInterval(pinger);
closed(code, reason);
});
});