Changelog
Every GraphQL over WebSocket release with its changes and the pull requests behind them.
6.2.1
Patch Changes
- #660
61731f0Thanks @fkaempfer! - Fix typings for WebSocketServer
6.2.0
Minor Changes
6.1.1
Patch Changes
-
#680
3fdd82fThanks @kkhys! - Disposing of a client event listener twice no longer removes an unrelated listenerThe unsubscribe function returned by
client.onspliced atindexOf(listener)without checking for-1, so removing an already-removed listener wouldsplice(-1, 1)and silently drop the most recently registered listener of the same event. This happens in practice without any double-dispose by the user: emits iterate over a copy of the listeners, so a one-shot internal listener that already unlistened itself during a nested emit (e.g. whenclient.terminate()is called from within aclosed/errorlistener) is re-invoked from the copy and unlistens again, knocking out registeredclosed/errorlisteners.
6.1.0
Minor Changes
- #672
afb7a8aThanks @andreisergiu98! - Add support forgraphql@17
6.0.8
Patch Changes
-
#667
fc03004Thanks @endigma! - Fix the server sending aCompletemessage after anErrormessage for subscriptions.Previously, when a subscription’s async iterable threw an error, the server would send:
{"id":"1","type":"error","payload":[{"message":"..."}]} {"id":"1","type":"complete"}Per the protocol spec:
Error: This message terminates the operation and no further messages will be sent.
Complete (Server → Client): If the server dispatched the
Errormessage relative to the originalSubscribemessage, noCompletemessage will be emitted.The server now correctly sends only the
Errormessage:{"id":"1","type":"error","payload":[{"message":"..."}]}Clients that correctly follow the spec should be unaffected, as they are expected to ignore messages for operations they consider already completed.
6.0.7
Patch Changes
-
#665
5536292Thanks @enisdenjo! - Remove uWebSockets.js from peer dependencies in package.jsonIt does not exist on NPM anymore and could lead to weird behavior when installing dependencies with
npm. Nothing else changes, usinggraphql-wswith uWebSockets.js still works.
6.0.6
Patch Changes
- #648
1f53bb4Thanks @enisdenjo! - Fix building issues causing CJS type definitions referencing ESM modules
6.0.5
Patch Changes
6.0.4
Patch Changes
- #625
b4a656dThanks @HermanBilous! - Use Math.pow for retry delay calculation
6.0.3
Patch Changes
-
747c01cThanks @enisdenjo! - DropExecutionPatchResultandFormattedExecutionPatchResulttypesNeither of the types are officially supported (yet) and the future versions of graphql-js adding support for stream/defer will a different signature for the incremental execution result.
6.0.2
Patch Changes
6.0.1
Patch Changes
-
#618
6be34c7Thanks @enisdenjo! - Remove exports for CommonJS for Deno exports in package.json -
#618
6be34c7Thanks @enisdenjo! - Define exports for CommonJS TypeScript definitions in package.json
6.0.0
Major Changes
-
b668b30Thanks @enisdenjo! - @fastify/websocket WebSocket in the context extra has been renamed fromconnectiontosocketMigrating 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
3f11abaThanks @enisdenjo! - Drop support forwsv7wsv7 has been deprecated. Please upgrade and use v8. -
#613
3f11abaThanks @enisdenjo! - Drop support for deprecatedfastify-websocketfastify-websockethas been deprecated since v4.3.0.. Please upgrade and use@fastify/websocket. -
#613
3f11abaThanks @enisdenjo! - The/lib/part from imports has been removed, for examplegraphql-ws/lib/use/wsbecomesgraphql-ws/use/wsMigrating 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
3f11abaThanks @enisdenjo! -ErrorMessageuses andonErrorreturnsGraphQLFormattedError(instead ofGraphQLError)Thanks @benjie for working on this in #599
-
#613
3f11abaThanks @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
3f11abaThanks @enisdenjo! - Least supportedgraphqlpeer dependency is ^15.10.1 and ^16Users are advised to use the latest of
graphqlbecause of various improvements in performance and security. -
#613
3f11abaThanks @enisdenjo! -NextMessageuses andonNextreturnsFormattedExecutionResult(instead ofExecutionResult) -
#613
3f11abaThanks @enisdenjo! -schema,context,onSubscribe,onOperation,onError,onNextandonCompletehooks 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
SubscribeMessageto theonSubscribehook. The only relevant parts from the message are theidand thepayload, thetypeis useless since the hook inherently has it (onNextisnexttype,onErroriserrortype, etc).The actual techincal reason for not having the full message is to avoid serialising results and errors twice. Both
onNextandonErrorallow the user to augment the result and return it to be used instead.onNextoriginally had theNextMessageargument which already has theFormattedExecutionResult, andonErrororiginally had theErrorMessageargument which already has theGraphQLFormattedError, and they both also returnedFormattedExecutionResultandGraphQLFormattedErrorrespectivelly - meaning, if the user serialised the results - the serialisation would happen twice.Additionally, the
onOperation,onError,onNextandonCompletenow have thepayloadwhich is theSubscribeMessage.payload(SubscribePayload) for easier access to the original query as well as execution params extensions.Migrating from v5 to v6
schemaimport { 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; + }, };contextimport { 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; + }, };onSubscribeimport { 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; + }, };onOperationThe
SubscribeMessage.payloadis not useful here at all, thepayloadhas 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; + }, };onErrorThe
ErrorMessage.payload(GraphQLFormattedError[]) is not useful here at all, the user has access toGraphQLError[]that are true instances of the error containing object references tooriginalErrors 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[] = message.payload; - }, + onError(ctx, id, payload, errors) { + const messageId = id; + const graphqlErrors: readonly GraphQLError[] = errors; + const subscribeMessagePayload: SubscribePayload = payload; + const errorMessagePayload: readonly GraphQLFormattedError[] = errors.map((e) => e.toJSON()); + }, };onNextThe
NextMessage.payload(FormattedExecutionResult) is not useful here at all, the user has access toExecutionResultthat contains actual object references to error instances. The user can always convert and returnFormattedExecutionResultby serialising the errors withGraphQLError.toJSON()method.import { ExecutionArgs, ExecutionResult, FormattedExecutionResult } from 'graphql'; import { ServerOptions, SubscribePayload } from 'graphql-ws'; const opts: ServerOptions = { - onNext(ctx, message, args: ExecutionArgs, result: ExecutionResult) { - const messageId = message.id; - const nextMessagePayload: FormattedExecutionResult = message.payload; - }, + onNext(ctx, id, payload, args: ExecutionArgs, result: ExecutionResult) { + const messageId = id; + const subscribeMessagePayload: SubscribePayload = payload; + const nextMessagePayload: FormattedExecutionResult = { ...result, errors: result.errors?.map((e) => e.toJSON()) }; + }, };onCompleteimport { ServerOptions, SubscribePayload } from 'graphql-ws'; const opts: ServerOptions = { - onComplete(ctx, message) { - const messageId = message.id; - }, + onComplete(ctx, id, payload) { + const messageId = id; + const subscribeMessagePayload: SubscribePayload = payload; + }, }; -
#613
3f11abaThanks @enisdenjo! - Errors thrown from subscription iterables will be caught and reported through theErrorMessageCompared to the behaviour before, which terminated the whole WebSocket connection - those errors are now gracefully reported and terminate only the specific subscription that threw the error.
There’s been an editorial change in the GraphQL Spec suggesting this being the correct approach.
Also, if you’d like to get involved and ideally drop your opinion about whether iterable errors should be reported as errors or
ExecutionResults witherrorsfield set, please read more here.Migrating from v5 to v6
If you had used the suggested “ws server usage with custom subscribe method that gracefully handles thrown errors” recipe, you can simply remove it since this behaviour is now baked in.
import { subscribe } from 'graphql'; import { useServer } from 'graphql-ws/use/ws'; import { WebSocketServer } from 'ws'; // yarn add ws const wsServer = new WebSocketServer({ port: 4000, path: '/graphql', }); useServer( { schema, - async subscribe(...args) { - const result = await subscribe(...args); - if ('next' in result) { - // is an async iterable, augment the next method to handle thrown errors - const originalNext = result.next; - result.next = async () => { - try { - return await originalNext(); - } catch (err) { - // gracefully handle the error thrown from the next method - return { value: { errors: [err] } }; - } - }; - } - return result; - }, }, wsServer, ); -
#613
3f11abaThanks @enisdenjo! - Remove deprecatedisMessage, usevalidateMessageinsteadMigrating from v5 to v6
Replace all ocurrances of
isMessagewithvalidateMessage. Note thatvalidateMessagethrows if the message is not valid, compared withisMessagethat simply returned true/false.- import { isMessage } from 'graphql-ws'; + import { validateMessage } from 'graphql-ws'; function isGraphQLWSMessage(val) { - return isMessage(val); + try { + validateMessage(val); + return true; + } catch { + return false; + } } -
#613
3f11abaThanks @enisdenjo! - Removed deprecatedisFatalConnectionProblem, useshouldRetryinsteadMigrating from v5 to v6
Replace all ocurrances of
isFatalConnectionProblemwithshouldRetry. Note that the result is inverted, where you returnedfalseinisFatalConnectionProblemyou should returntrueinshouldRetry.import { createClient } from 'graphql-ws'; const client = createClient({ url: 'ws://localhost:4000/graphql', - isFatalConnectionProblem: () => false, + shouldRetry: () => true, });
Minor Changes
-
#613
3f11abaThanks @enisdenjo! - Client is truly zero-dependency, not even a peer dependency ongraphqlIn non-browser environments, you can use only the client and not even depend on
graphqlby importing fromgraphql-ws/client.import { createClient } from 'graphql-ws/client'; const client = createClient({ url: 'ws://localhost:4000/graphql', });Note that, in browser envirments (and of course having your bundler use the
browserpackage.json field), you don’t have to import fromgraphql-ws/client- simply importing fromgraphql-wswill only have thecreateClientavailable. -
#615
29dd26aThanks @enisdenjo! - Define optional peer dependencies and least supported versionsUsing the
peerDependenciesin combination withpeerDependenciesMetaconfiguration inpackage.json.
5.16.2
Patch Changes
-
#611
6a5fde1Thanks @enisdenjo! - No more workspacesThis version does not contain any code changes.
5.16.1
Patch Changes
-
#607
a629ec7Thanks @enisdenjo! - Release with changesetsThis version does not contain any code changes.
5.16.0 (2024-03-27)
Bug Fixes
- server: Return all subscriptions regardless of the return invocation order (f442288)
- server: should not send error messages if socket closes before onSubscribe hooks resolves (db47a66), closes #539
Features
5.15.0 (2024-02-12)
Bug Fixes
- client: Use
TerminatedCloseEventclass extending anErrorfor rejecting promises when terminating (74b4ceb), closes #531 - server: Dispose of subscriptions on close even if added late to the subscriptions list (#534) (e45d6b1), closes #532
Features
5.14.3 (2023-12-20)
Bug Fixes
- client: Use closures instead of bindings (with
this) (812129d) - remove package.json workspaces entry in release (63a831e), closes #524
5.14.2 (2023-10-23)
Bug Fixes
5.14.1 (2023-09-28)
Bug Fixes
- server: Acknowledge connection before notifying the client to avoid race conditions with slow sends (#506) (8cb82bd), closes #501
5.14.0 (2023-06-22)
Features
5.13.1 (2023-05-15)
Bug Fixes
5.13.0 (2023-05-12)
Features
5.12.1 (2023-03-31)
Bug Fixes
- Add file extensions to imports/exports in ESM type definitions (48775be)
5.12.0 (2023-03-06)
Features
5.11.3 (2023-02-01)
Bug Fixes
- ws,uWebSockets,@fastify/websocket: Handle internal errors that are not instances of
Error(#442) (9884889), closes #441
5.11.2 (2022-09-21)
Bug Fixes
5.11.1 (2022-09-16)
Bug Fixes
5.11.0 (2022-09-16)
Features
5.10.2 (2022-09-12)
Performance Improvements
- Easier message parser (d44c6f1)
5.10.1 (2022-08-19)
Bug Fixes
5.10.0 (2022-08-09)
Features
5.9.1 (2022-07-01)
Bug Fixes
5.9.0 (2022-06-09)
Features
5.8.2 (2022-05-12)
Bug Fixes
- server: Should clean up subscription reservations on abrupt errors without relying on connection close (611c223)
5.8.1 (2022-04-25)
Bug Fixes
- client:
isFatalConnectionProblemdefaults to undefined for usingshouldRetry(9d5c573)
5.8.0 (2022-04-25)
Features
- client: Deprecate
isFatalConnectionProblemoption in favour ofshouldRetry(d8dcf21)
5.7.0 (2022-04-07)
Features
5.6.4 (2022-03-24)
Bug Fixes
- Warn about subscriptions-transport-ws clients and provide migration link (e080739), closes #339 #325
5.6.3 (2022-03-13)
Bug Fixes
- client: Stop execution if
connectionParamstook too long and the server kicked the client off (1e94e45), closes #331
5.6.2 (2022-02-23)
Bug Fixes
- server:
handleProtocolsaccepts arrays too and gracefully rejects other types (98dec1a), closes #318
5.6.1 (2022-02-21)
Bug Fixes
- server: Handle upgrade requests with multiple subprotocols and omit
Sec-WebSocket-Protocolheader if none supported (9bae064)
5.6.0 (2022-02-19)
Features
5.5.5 (2021-10-29)
Bug Fixes
- client: Limit client emitted error close message size (2d959f6)
- client: Report close causing internal errors to error listeners (4e7e389)
5.5.4 (2021-10-27)
Bug Fixes
- fastify-websocket: Handle connection and socket emitted errors (71e9586)
- fastify-websocket: Handle server emitted errors (3fa17a7)
- ws: Handle socket emitted errors (a22c00f)
- ws: Limit server emitted error close message size (50620df)
- ws: Log server emitted errors to the console (0826b0a)
5.5.3 (2021-10-20)
Bug Fixes
- client: Distinguish client connection closes (ed4d9db)
5.5.2 (2021-10-20)
Bug Fixes
- client: Don’t complete after connection error (5f829c3)
- client: Report close error even if
Completemessage followed (27754b2), closes #245
5.5.1 (2021-10-19)
Bug Fixes
- server: Limit internal server error close message size (8479f76)
- server: Log internal errors to the console (6ddf0d1)
- ws,fastify-websocket: Send only on ready socket (8d13c9e)
5.5.0 (2021-09-08)
Bug Fixes
- Define graphql execution results (a64c91b)
- server: Operation result can be async generator or iterable (b1fb883)
Features
5.4.1 (2021-08-26)
Bug Fixes
- Add support for
graphql@v16(ad5aea2) - Sink’s next callback always receives an
ExecutionResult(045b402)
5.4.0 (2021-08-21)
Bug Fixes
- client: Specify and fail on fatal internal WebSocket close codes (a720125)
- Use
4406close code for unsupported subprotocol (1002is an internal WebSocket close code) (df85281) - Use
4500close code for internal server errors (1011is an internal WebSocket close code) (3c0316d)
Features
5.3.0 (2021-06-23)
Bug Fixes
- client:
ConnectionInitpayload is absent ifconnectionParamsreturns nothing (98f8265)
Features
- client:
connectionParamscan returnundefined(a543187) - client: Add
openedevent for when a WebSocket opens (9053224)
5.2.0 (2021-06-21)
Features
- server: Optional
onPingandonPongmessage type listeners (f36066f)
5.1.2 (2021-06-09)
Bug Fixes
- client: Return ping’s payload through the response pong (ee6193a)
5.1.1 (2021-06-09)
Bug Fixes
5.1.0 (2021-06-09)
Features
- client:
disablePongoption for when implementing a custom pinger (6510360), closes #117 - Optional
payloadfor ping/pong message types (2fe0345), closes #117
5.0.0 (2021-06-08)
Features
- Bidirectional ping/pong message types (#201) (1efaf83)
- client: Rename
keepAliveoption tolazyCloseTimeout(3c1f13c) - uWebSockets: Drop deprecated
requestcontext extra (02ea5ee)
BREAKING CHANGES
- Because of the Protocol’s strictness, an instant connection termination will happen whenever an invalid message is identified; meaning, all previous implementations will fail when receiving the new subprotocol ping/pong messages.
Beware, the client will NOT ping the server by default. Please make sure to upgrade your stack in order to support the new ping/pong message types.
A simple recipe showcasing a client that times out if no pong is received and measures latency, looks like this:
import { createClient } from 'graphql-ws';
let activeSocket,
timedOut,
pingSentAt = 0,
latency = 0;
createClient({
url: 'ws://i.time.out:4000/and-measure/latency',
keepAlive: 10_000, // ping server every 10 seconds
on: {
connected: (socket) => (activeSocket = socket),
ping: (received) => {
if (!received /* sent */) {
pingSentAt = Date.now();
timedOut = setTimeout(() => {
if (activeSocket.readyState === WebSocket.OPEN)
activeSocket.close(4408, 'Request Timeout');
}, 5_000); // wait 5 seconds for the pong and then close the connection
}
},
pong: (received) => {
if (received) {
latency = Date.now() - pingSentAt;
clearTimeout(timedOut); // pong is received, clear connection close timeout
}
},
},
});
- uWebSockets: The deprecated uWebSockets
requestcontext extra field has been dropped because it is stack allocated and cannot be used ouside the internalupgradecallback. - client: Client
keepAliveoption has been renamed tolazyCloseTimeoutin order to eliminate ambiguity with the client to server pings keep-alive option.
4.9.0 (2021-06-06)
Features
4.8.0 (2021-06-03)
Features
- uWebSockets: Add
persistedRequestto context extra and deprecate uWS’s stack allocatedrequest(#196) (736e6ed)
4.7.0 (2021-05-31)
Features
- Add
extensionsfield to the subscribe message payload (d86a8e4)
4.6.0 (2021-05-30)
Features
4.5.2 (2021-05-28)
Bug Fixes
4.5.1 (2021-05-18)
Bug Fixes
4.5.0 (2021-04-29)
Features
4.4.4 (2021-04-28)
Bug Fixes
- client:
completeshould not be called after subscriptionerror(1fba419) - client: Subscription can be disposed only once (abd9c28), closes #170
4.4.3 (2021-04-27)
Bug Fixes
- client: Subscribes even if socket is in CLOSING state due to all subscriptions being completed (3e3b8b7), closes #173 #170
4.4.2 (2021-04-22)
Bug Fixes
- client: Lazy connects after successful reconnects are not retries (99b85a3)
- client: Shouldn’t reconnect if all subscriptions complete while waiting for retry (2826c10), closes #163
4.4.1 (2021-04-14)
Bug Fixes
4.4.0 (2021-04-11)
Features
4.3.4 (2021-04-11)
Bug Fixes
- client: Subscriptions acquire locks (eb6cb2a)
4.3.3 (2021-04-11)
Bug Fixes
4.3.2 (2021-03-29)
Bug Fixes
Performance Improvements
4.3.1 (2021-03-25)
Bug Fixes
- Close the details tag in the README (84144c4)
4.3.0 (2021-03-25)
Bug Fixes
- server: Respect completed subscriptions even if
subscribeoronOperationdidnt resolve yet (4700154)
Features
- client:
urloption accepts a function or a Promise (#143) (76f522f), closes #145 #146 - server:
executeandsubscribeare optional (#148) (af748b0) - server: Dynamic
schemasupport by accepting a function or a Promise (#147) (6a0bf94), closes #127 - server: Use
validateoption for custom GraphQL validation (b68d56c)
4.2.3 (2021-03-23)
Bug Fixes
- client: Reduce WebSocket event listeners and add new client
messageevent (#104) (68d0e20), closes #102
4.2.2 (2021-03-17)
Bug Fixes
4.2.1 (2021-03-11)
Bug Fixes
4.2.0 (2021-02-25)
Bug Fixes
- Only UMD build has side effects (66ed43f)
Features
- client:
isFatalConnectionProblemoption for deciding if the connect error should be immediately reported or the connection retried (#126) (8115871), closes #122
4.1.6 (2021-02-18)
Bug Fixes
4.1.5 (2021-02-12)
Bug Fixes
- Main entrypoint in
exportsis just"."(8f70b02)
4.1.4 (2021-02-12)
Bug Fixes
4.1.3 (2021-02-08)
Bug Fixes
- client: Should emit
closedevent when disposing (5800de8), closes #108 - client: Shouldn’t send the
Completemessage if socket is not open (cd12024)
4.1.2 (2021-01-24)
Bug Fixes
4.1.1 (2021-01-19)
Bug Fixes
- client: Export relevant elements from the browser bundle (b106dbe), closes #97
- client: Wait for server acknowledgement indefinitely (a4bd602), closes #98
4.1.0 (2021-01-13)
Bug Fixes
- server:
onDisconnectis called exclusively if the connection is acknowledged (33ed5f2)
Features
- server: Add
onClosecallback for closures at any point in time (dd0d4fa)
4.0.0 (2021-01-13)
Bug Fixes
- server: Client can complete/cancel any operation (0ad1c4c)
- server: Enforce ID uniqueness across all operations and during the whole subscription life (#96) (65d1bfa)
Features
- server: Add
onDisconnectcallback (#94) (2a61268) - server: Log a warning for unsupported subprotocols (88a12ef), closes #92
BREAKING CHANGES
- server: The return function of
server.opened(closed) now requires the close event code and reason for reporting to theonDisconnectcallback. - server: The
Context.subscriptionsrecord value can be either anAsyncIteratoror aPromise.
3.2.0 (2020-12-17)
Features
3.1.0 (2020-12-11)
Bug Fixes
Features
- client:
onNonLazyErrorallows you to catch errors reported in non-lazy mode (cd1e7df)
3.0.2 (2020-12-10)
Bug Fixes
- client: No retries when disposed (0d5e6c2)
3.0.1 (2020-12-10)
Performance Improvements
- client: Await timeouts only in recursive connects (55c8fc8)
3.0.0 (2020-12-09)
Features
BREAKING CHANGES
- client: Client
retryTimeoutoption has been replaced with the newretryWait.
retryWait allows you to control the retry timeout strategy by resolving the returned promise when ready. The default implements the randomised exponential backoff like so:
// this is the default
const retryWait = async function randomisedExponentialBackoff(retries: number) {
let retryDelay = 1000; // start with 1s delay
for (let i = 0; i < retries; i++) {
retryDelay *= 2; // square `retries` times
}
await new Promise((resolve) =>
setTimeout(
// resolve pending promise with added random timeout from 300ms to 3s
resolve,
retryDelay + Math.floor(Math.random() * (3000 - 300) + 300),
),
);
};
2.0.1 (2020-12-03)
Bug Fixes
2.0.0 (2020-11-20)
Features
BREAKING CHANGES
- server: You now “make” a ready-to-use server that can be used with any WebSocket implementation!
Summary of breaking changes:
- No more
keepAlive. The user should provide its own keep-alive implementation. (I highly recommend WebSocket Ping and Pongs) - No more HTTP
requestin the server context. - No more WebSocket in the server context (you’re the one that creates it).
- You use your own WebSocket server
- Server exports only
makeServer(no morecreateServer)
Benefits
- You’re responsible for the server (any optimisation or adjustment can be applied)
- Any WebSocket server can be used (or even mocked if necessary)
- You control the disposal of the server (close or transfer clients however you wish)
- New
extrafield in theContextfor storing custom values useful for callbacks - Full control of authentication flow
- Full control over error handling
- True zero-dependency
Migrating from v1
Only the server has to be migrated. Since this release allows you to use your favourite WebSocket library (or your own implementation), using ws is just one way of using graphql-ws. This is how to use the implementation shipped with the lib:
/**
* ❌ instead of the lib creating a WebSocket server internally with the provided arguments
*/
import https from 'https';
import { createServer } from 'graphql-ws';
const server = https.createServer(...);
createServer(
{
onConnect(ctx) {
// were previously directly on the context
ctx.request as IncomingRequest
ctx.socket as WebSocket
},
...rest,
},
{
server,
path: '/graphql',
},
);
/**
* ✅ you have to supply the server yourself
*/
import https from 'https';
import ws from 'ws'; // yarn add ws
import { useServer } from 'graphql-ws/lib/use/ws'; // notice the import path
const server = https.createServer(...);
const wsServer = new ws.Server({
server,
path: '/graphql',
});
useServer(
{
onConnect(ctx) {
// are now in the `extra` field
ctx.extra.request as IncomingRequest
ctx.extra.socket as WebSocket
},
...rest,
},
wsServer,
// optional keepAlive with ping pongs (defaults to 12 seconds)
);
1.14.0 (2020-11-15)
Features
1.13.1 (2020-11-14)
Bug Fixes
- client: Some close events are not worth retrying (4d9134b)
- message: Allow
datafield to be of any type (533248e), closes #72 - message: Allow
payloadfield to be of any type forNextMessage(7cebbfe), closes #72 - Use
IDtype for message id field (87ebd35)
1.13.0 (2020-11-12)
Bug Fixes
- client: One cleanup per subscription (#67) (5a5ae4d)
- Stop sending messages after receiving complete (#65) (3f4f836)
Features
- client:
connectionParamsmay return a promise (#71) (33f210c) - client: Allow keeping the connection alive for some time before lazy closing (#69) (555c2c3)
1.12.0 (2020-11-07)
Bug Fixes
- client: Close with error message during connecting issues (f8ecdd7)
Features
1.11.0 (2020-11-04)
Bug Fixes
- Node 10 is the min supported version (19844d7)
- Support more
graphqlversions (de69b4e) - server: Close socket if
onSubscribereturns invalid array (#53) (0464a54) - server: Consistently set
rootValueandcontextValue, if not overridden (#49) (7aa3bcd) - server: Distribute server error to all clients even if one error listener throws (#56) (b96dbb9)
- server: Don’t surface bad request error details in production (#55) (70317b2)
Features
Performance Improvements
1.10.0 (2020-11-03)
Features
- Subscribe message
querymust be a string (#45) (60d9cd5) - server: For dynamic usage,
contextoption can be a function too (#46) (149b582)
1.9.3 (2020-10-31)
Bug Fixes
- Drop TypeScript DOM lib dependency (a81e8c1)
- Support more Node versions by not using
globalThis(79c2ed2)
1.9.2 (2020-10-31)
Bug Fixes
- server: Make sure to use
onSubscriberesult exclusively (51fdb7c) - Export useful types (e4cc4d4)
- client: Accept nullish values for
operationNameandvariables(2d60dda)
1.9.1 (2020-10-25)
Features
- Package rename
graphql-transport-ws👉graphql-ws. (#43)
1.9.0 (2020-10-24)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Features
BREAKING CHANGES
Should’ve been a major release but semantic-release didn’t detect the breaking changes of the 507a222 commit, so here we are…
This time we come with a few breaking changes that will open doors for all sorts of enhancements. Check the linked PR for more details.
Server option onSubscribe
- Now executes before any other subscribe message processing
- Now takes 2 arguments, the
Contextand theSubscribeMessage - Now returns nothing,
ExecutionArgsor an array ofGraphQLErrors- Returning
void(or nothing) will leave the execution args preparation and validation to the library - Returned
ExecutionArgswill be used directly for the GraphQL operation execution (preparations and validation should be done by you in this case) - Returned array of
GraphQLErrors will be reported to the client through theErrorMessage
- Returning
Server option validationRules
Dropped in favour of applying custom validation rules in the onSubscribe callback. Find the recipe in the readme!
Server option formatExecutionResult
Dropped in favour of using the return value of onNext callback.
1.8.2 (2020-10-22)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- server: No need to bind
thisscope (f76ac73)
1.8.1 (2020-10-22)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- yarn engine is not required (#34) (89484b8)
- server: Hide internal server error messages from the client in production (36fe405), closes #31
1.8.0 (2020-10-19)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Features
1.7.0 (2020-10-01)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- client: Dispose of subscription on complete or error messages (#23) (fb4d8e9)
- server:
subscriptionoperations are distinct on the message ID (#24) (dfffb05)
Features
1.6.0 (2020-09-28)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Features
1.5.0 (2020-09-18)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- server: Use
subscribefrom the config (6fbd47c)
Features
1.4.2 (2020-09-16)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- server: Receiving more than one
ConnectionInitmessage closes the socket immediately (757c6e9)
1.4.1 (2020-09-11)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Performance Improvements
- client: Memoize message parsing for each subscriber (2a7ba46)
1.4.0 (2020-09-10)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- client: Only
queryis required in the subscribe payload (e892530)
Features
- server: Pass roots for operation fields as an option (dcb5ed4)
1.3.0 (2020-09-10)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Features
- WebSocket Ping and Pong as keep-alive (#11) (16ae316)
- client: Emit events for
connecting,connectedandclosed(627775b) - client: Implement silent-reconnects (c6f7872), closes #7
- client: Lazy option can be changed (fb0ec14)
1.2.0 (2020-09-04)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Features
- Package rename
@enisdenjo/graphql-transport-ws👉graphql-transport-ws. (494f676)
1.1.1 (2020-08-28)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- add the sink to the subscribed map AFTER emitting a subscribe message (814f46c)
- notify only relevant sinks about errors or completions (62155ba)
1.1.0 (2020-08-28)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- server: allow skipping init message wait with zero values (a7419df)
- server: use subscription specific formatter for queries and mutations too (5672a04)
Features
1.0.2 (2020-08-26)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- correctly detect WebSocket server (eab29dc)
1.0.1 (2020-08-26)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Bug Fixes
- reset connected/connecting state when disconnecting and disposing (2eb3cd5)
- client: cant read the
CloseEvent.reasonafter bundling so just pass the whole event to the sink error and let the user handle it (9ccb46b) - client: send complete message and close only if socket is still open (49b75ce)
- http and ws have no default exports (5c01ed9)
- include
typesfile holding important types (f3e4edf) - server: scoped execution result formatter from
onConnect(f91fadb) - export both the client and the server from index (29923b1)
- server: store the intial request in the context (6927ee0)
1.0.0 (2020-08-17)
⚠️ Deprecated
Package has been renamed from graphql-transport-ws to graphql-ws.
Features
- client: Re-implement following the new transport protocol (#6) (5191a35)
- server: Implement following the new transport protocol (#1) (a412d25)
- Rewrite GraphQL over WebSocket Protocol (#2) (42045c5)
BREAKING CHANGES
- This lib is no longer compatible with
subscriptions-transport-ws. It follows a redesigned transport protocol aiming to improve security, stability and reduce ambiguity.