Releases: enisdenjo/graphql-ws
v6.0.0
Major Changes
-
b668b30
Thanks @enisdenjo! - @fastify/websocket WebSocket in the context extra has been renamed fromconnection
tosocket
Migrating from v5 to v6
import { makeHandler } from 'graphql-ws/use/@fastify/websocket'; makeHandler({ schema(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, context(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, onConnect(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, onDisconnect(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, onClose(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, onSubscribe(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, onOperation(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, onError(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, onNext(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, onComplete(ctx) { - const websocket = ctx.extra.connection; + const websocket = ctx.extra.socket; }, });
-
#613
3f11aba
Thanks @enisdenjo! - Drop support forws
v7ws
v7 has been deprecated. Please upgrade and use v8. -
#613
3f11aba
Thanks @enisdenjo! - Drop support for deprecatedfastify-websocket
fastify-websocket
has been deprecated since v4.3.0.. Please upgrade and use@fastify/websocket
. -
#613
3f11aba
Thanks @enisdenjo! - The/lib/
part from imports has been removed, for examplegraphql-ws/lib/use/ws
becomesgraphql-ws/use/ws
Migrating from v5 to v6
Simply remove the
/lib/
part from your graphql-ws imports that use a handler.ws
- import { useServer } from 'graphql-ws/lib/use/ws'; + import { useServer } from 'graphql-ws/use/ws';
uWebSockets.js
- import { makeBehavior } from 'graphql-ws/lib/use/uWebSockets'; + import { makeBehavior } from 'graphql-ws/use/uWebSockets';
@fastify/websocket
- import { makeHandler } from 'graphql-ws/lib/use/@fastify/websocket'; + import { makeHandler } from 'graphql-ws/use/@fastify/websocket';
Bun
- import { handleProtocols, makeHandler } from 'graphql-ws/lib/use/bun'; + import { handleProtocols, makeHandler } from 'graphql-ws/use/bun';
Deno
- import { makeHandler } from 'https://esm.sh/graphql-ws/lib/use/deno'; + import { makeHandler } from 'https://esm.sh/graphql-ws/use/deno';
-
#613
3f11aba
Thanks @enisdenjo! -ErrorMessage
uses andonError
returnsGraphQLFormattedError
(instead ofGraphQLError
) -
#613
3f11aba
Thanks @enisdenjo! - Least supported Node version is v20Node v10 has been deprecated for years now. There is no reason to support it. Bumping the engine to the current LTS (v20) also allows the code to be leaner and use less polyfills.
-
#613
3f11aba
Thanks @enisdenjo! - Least supportedgraphql
peer dependency is ^15.10.1 and ^16Users are advised to use the latest of
graphql
because of various improvements in performance and security. -
#613
3f11aba
Thanks @enisdenjo! -NextMessage
uses andonNext
returnsFormattedExecutionResult
(instead ofExecutionResult
) -
#613
3f11aba
Thanks @enisdenjo! -schema
,context
,onSubscribe
,onOperation
,onError
,onNext
andonComplete
hooks don't have the full accompanying message anymore, only the ID and the relevant part from the messageThere is really no need to pass the full
SubscribeMessage
to theonSubscribe
hook. The only relevant parts from the message are theid
and thepayload
, thetype
is useless since the hook inherently has it (onNext
isnext
type,onError
iserror
type, etc).The actual techincal reason for not having the full message is to avoid serialising results and errors twice. Both
onNext
andonError
allow the user to augment the result and return it to be used instead.onNext
originally had theNextMessage
argument which already has theFormattedExecutionResult
, andonError
originally had theErrorMessage
argument which already has theGraphQLFormattedError
, and they both also returnedFormattedExecutionResult
andGraphQLFormattedError
respectivelly - meaning, if the user serialised the results - the serialisation would happen twice.Additionally, the
onOperation
,onError
,onNext
andonComplete
now have thepayload
which is theSubscribeMessage.payload
(SubscribePayload
) for easier access to the original query as well as execution params extensions.Migrating from v5 to v6
schema
import { ExecutionArgs } from 'graphql'; import { ServerOptions, SubscribePayload } from 'graphql-ws'; const opts: ServerOptions = { - schema(ctx, message, argsWithoutSchema: Omit<ExecutionArgs, 'schema'>) { - const messageId = message.id; - const messagePayload: SubscribePayload = message.payload; - }, + schema(ctx, id, payload) { + const messageId = id; + const messagePayload: SubscribePayload = payload; + }, };
context
import { ExecutionArgs } from 'graphql'; import { ServerOptions, SubscribePayload } from 'graphql-ws'; const opts: ServerOptions = { - context(ctx, message, args: ExecutionArgs) { - const messageId = message.id; - const messagePayload: SubscribePayload = message.payload; - }, + context(ctx, id, payload, args: ExecutionArgs) { + const messageId = id; + const messagePayload: SubscribePayload = payload; + }, };
onSubscribe
import { ServerOptions, SubscribePayload } from 'graphql-ws'; const opts: ServerOptions = { - onSubscribe(ctx, message) { - const messageId = message.id; - const messagePayload: SubscribePayload = message.payload; - }, + onSubscribe(ctx, id, payload) { + const messageId = id; + const messagePayload: SubscribePayload = payload; + }, };
onOperation
The
SubscribeMessage.payload
is not useful here at all, thepayload
has been parsed to ready-to-use graphql execution args and should be used instead.import { ExecutionArgs } from 'graphql'; import { ServerOptions, SubscribePayload, OperationResult } from 'graphql-ws'; const opts: ServerOptions = { - onOperation(ctx, message, args: ExecutionArgs, result: OperationResult) { - const messageId = message.id; - const messagePayload: SubscribePayload = message.payload; - }, + onOperation(ctx, id, payload, args: ExecutionArgs, result: OperationResult) { + const messageId = id; + const messagePayload: SubscribePayload = payload; + }, };
onError
The
ErrorMessage.payload
(GraphQLFormattedError[]
) is not useful here at all, the user has access toGraphQLError[]
that are true instances of the error containing object references tooriginalError
s and other properties. The user can always convert and returnGraphQLFormattedError[]
by using the.toJSON()
method.import { GraphQLError, GraphQLFormattedError } from 'graphql'; import { ServerOptions, SubscribePayload } from 'graphql-ws'; const opts: ServerOptions = { - onError(ctx, message, errors) { - const messageId = message.id; - const graphqlErrors: readonly GraphQLError[] = errors; - const errorMessagePayload: readonly GraphQLFormattedError[]...
v5.16.2
Patch Changes
-
#611
6a5fde1
Thanks @enisdenjo! - No more workspacesThis version does not contain any code changes.
v5.16.1
Patch Changes
-
#607
a629ec7
Thanks @enisdenjo! - Release with changesetsThis version does not contain any code changes.
v5.16.0
v5.15.0
v5.14.3
v5.14.2
v5.14.1
v5.14.0
5.14.0 (2023-06-22)
Features
Examples
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;
}
})();