- #660
61731f0Thanks @fkaempfer! - Fix typings for WebSocketServer
-
#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.
- #672
afb7a8aThanks @andreisergiu98! - Add support forgraphql@17
-
#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.
-
#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.
- #648
1f53bb4Thanks @enisdenjo! - Fix building issues causing CJS type definitions referencing ESM modules
- #625
b4a656dThanks @HermanBilous! - Use Math.pow for retry delay calculation
-
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.
-
#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
-
b668b30Thanks @enisdenjo! - @fastify/websocket WebSocket in the context extra has been renamed fromconnectiontosocketimport { 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/wsSimply remove the
/lib/part from your graphql-ws imports that use a handler.- import { useServer } from 'graphql-ws/lib/use/ws'; + import { useServer } from 'graphql-ws/use/ws';
- import { makeBehavior } from 'graphql-ws/lib/use/uWebSockets'; + import { makeBehavior } from 'graphql-ws/use/uWebSockets';
- import { makeHandler } from 'graphql-ws/lib/use/@fastify/websocket'; + import { makeHandler } from 'graphql-ws/use/@fastify/websocket';
- import { handleProtocols, makeHandler } from 'graphql-ws/lib/use/bun'; + import { handleProtocols, makeHandler } from 'graphql-ws/use/bun';
- 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.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; + }, };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; + }, };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; + }, };The
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; + }, };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 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()); + }, };The
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()) }; + }, };import { 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.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, usevalidateMessageinsteadReplace 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, useshouldRetryinsteadReplace 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, });
-
#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.
-
#611
6a5fde1Thanks @enisdenjo! - No more workspacesThis version does not contain any code changes.
-
#607
a629ec7Thanks @enisdenjo! - Release with changesetsThis version does not contain any code changes.
5.16.0 (2024-03-27)
- 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
5.15.0 (2024-02-12)
- 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
5.14.3 (2023-12-20)
- 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)
5.14.1 (2023-09-28)
- server: Acknowledge connection before notifying the client to avoid race conditions with slow sends (#506) (8cb82bd), closes #501
5.14.0 (2023-06-22)
5.13.1 (2023-05-15)
5.13.0 (2023-05-12)
5.12.1 (2023-03-31)
- Add file extensions to imports/exports in ESM type definitions (48775be)
5.12.0 (2023-03-06)
5.11.3 (2023-02-01)
- ws,uWebSockets,@fastify/websocket: Handle internal errors that are not instances of
Error(#442) (9884889), closes #441
5.11.2 (2022-09-21)
5.11.1 (2022-09-16)
5.11.0 (2022-09-16)
5.10.2 (2022-09-12)
- Easier message parser (d44c6f1)
5.10.1 (2022-08-19)
5.10.0 (2022-08-09)
5.9.1 (2022-07-01)
5.9.0 (2022-06-09)
5.8.2 (2022-05-12)
- server: Should clean up subscription reservations on abrupt errors without relying on connection close (611c223)
5.8.1 (2022-04-25)
- client:
isFatalConnectionProblemdefaults to undefined for usingshouldRetry(9d5c573)
5.8.0 (2022-04-25)
- client: Deprecate
isFatalConnectionProblemoption in favour ofshouldRetry(d8dcf21)
5.7.0 (2022-04-07)
5.6.4 (2022-03-24)
- Warn about subscriptions-transport-ws clients and provide migration link (e080739), closes #339 #325
5.6.3 (2022-03-13)
- client: Stop execution if
connectionParamstook too long and the server kicked the client off (1e94e45), closes #331
5.6.2 (2022-02-23)
- server:
handleProtocolsaccepts arrays too and gracefully rejects other types (98dec1a), closes #318
5.6.1 (2022-02-21)
- server: Handle upgrade requests with multiple subprotocols and omit
Sec-WebSocket-Protocolheader if none supported (9bae064)
5.6.0 (2022-02-19)
5.5.5 (2021-10-29)
- 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)
- 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)
- client: Distinguish client connection closes (ed4d9db)
5.5.2 (2021-10-20)
- 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)
- 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)
- Define graphql execution results (a64c91b)
- server: Operation result can be async generator or iterable (b1fb883)
5.4.1 (2021-08-26)
- Add support for
graphql@v16(ad5aea2) - Sink's next callback always receives an
ExecutionResult(045b402)
5.4.0 (2021-08-21)
- 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)
5.3.0 (2021-06-23)
- client:
ConnectionInitpayload is absent ifconnectionParamsreturns nothing (98f8265)
- client:
connectionParamscan returnundefined(a543187) - client: Add
openedevent for when a WebSocket opens (9053224)
5.2.0 (2021-06-21)
- server: Optional
onPingandonPongmessage type listeners (f36066f)
5.1.2 (2021-06-09)
- client: Return ping's payload through the response pong (ee6193a)
5.1.1 (2021-06-09)
5.1.0 (2021-06-09)
- 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)
- Bidirectional ping/pong message types (#201) (1efaf83)
- client: Rename
keepAliveoption tolazyCloseTimeout(3c1f13c) - uWebSockets: Drop deprecated
requestcontext extra (02ea5ee)
- 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)
4.8.0 (2021-06-03)
- uWebSockets: Add
persistedRequestto context extra and deprecate uWS's stack allocatedrequest(#196) (736e6ed)
4.7.0 (2021-05-31)
- Add
extensionsfield to the subscribe message payload (d86a8e4)
4.6.0 (2021-05-30)
4.5.2 (2021-05-28)
4.5.1 (2021-05-18)
4.5.0 (2021-04-29)
4.4.4 (2021-04-28)
- client:
completeshould not be called after subscriptionerror(1fba419) - client: Subscription can be disposed only once (abd9c28), closes #170
4.4.3 (2021-04-27)
- 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)
- 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)
4.4.0 (2021-04-11)
4.3.4 (2021-04-11)
- client: Subscriptions acquire locks (eb6cb2a)
4.3.3 (2021-04-11)
4.3.2 (2021-03-29)
4.3.1 (2021-03-25)
- Close the details tag in the README (84144c4)
4.3.0 (2021-03-25)
- server: Respect completed subscriptions even if
subscribeoronOperationdidnt resolve yet (4700154)
- 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)
- client: Reduce WebSocket event listeners and add new client
messageevent (#104) (68d0e20), closes #102
4.2.2 (2021-03-17)
4.2.1 (2021-03-11)
4.2.0 (2021-02-25)
- Only UMD build has side effects (66ed43f)
- 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)
4.1.5 (2021-02-12)
- Main entrypoint in
exportsis just"."(8f70b02)
4.1.4 (2021-02-12)
4.1.3 (2021-02-08)
- 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)
4.1.1 (2021-01-19)
- 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)
- server:
onDisconnectis called exclusively if the connection is acknowledged (33ed5f2)
- server: Add
onClosecallback for closures at any point in time (dd0d4fa)
4.0.0 (2021-01-13)
- server: Client can complete/cancel any operation (0ad1c4c)
- server: Enforce ID uniqueness across all operations and during the whole subscription life (#96) (65d1bfa)
- server: Add
onDisconnectcallback (#94) (2a61268) - server: Log a warning for unsupported subprotocols (88a12ef), closes #92
- 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)
3.1.0 (2020-12-11)
- client:
onNonLazyErrorallows you to catch errors reported in non-lazy mode (cd1e7df)
3.0.2 (2020-12-10)
- client: No retries when disposed (0d5e6c2)
3.0.1 (2020-12-10)
- client: Await timeouts only in recursive connects (55c8fc8)
3.0.0 (2020-12-09)
- 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)
2.0.0 (2020-11-20)
- 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)
- 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
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)
1.13.1 (2020-11-14)
- 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)
- client: One cleanup per subscription (#67) (5a5ae4d)
- Stop sending messages after receiving complete (#65) (3f4f836)
- 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)
- client: Close with error message during connecting issues (f8ecdd7)
1.11.0 (2020-11-04)
- 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)
1.10.0 (2020-11-03)
- 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)
- Drop TypeScript DOM lib dependency (a81e8c1)
- Support more Node versions by not using
globalThis(79c2ed2)
1.9.2 (2020-10-31)
- 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)
- Package rename
graphql-transport-ws👉graphql-ws. (#43)
1.9.0 (2020-10-24)
Package has been renamed from graphql-transport-ws to graphql-ws.
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.
- 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
Dropped in favour of applying custom validation rules in the onSubscribe callback. Find the recipe in the readme!
Dropped in favour of using the return value of onNext callback.
1.8.2 (2020-10-22)
Package has been renamed from graphql-transport-ws to graphql-ws.
- server: No need to bind
thisscope (f76ac73)
1.8.1 (2020-10-22)
Package has been renamed from graphql-transport-ws to graphql-ws.
- 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)
Package has been renamed from graphql-transport-ws to graphql-ws.
1.7.0 (2020-10-01)
Package has been renamed from graphql-transport-ws to graphql-ws.
- client: Dispose of subscription on complete or error messages (#23) (fb4d8e9)
- server:
subscriptionoperations are distinct on the message ID (#24) (dfffb05)
1.6.0 (2020-09-28)
Package has been renamed from graphql-transport-ws to graphql-ws.
1.5.0 (2020-09-18)
Package has been renamed from graphql-transport-ws to graphql-ws.
- server: Use
subscribefrom the config (6fbd47c)
1.4.2 (2020-09-16)
Package has been renamed from graphql-transport-ws to graphql-ws.
- server: Receiving more than one
ConnectionInitmessage closes the socket immediately (757c6e9)
1.4.1 (2020-09-11)
Package has been renamed from graphql-transport-ws to graphql-ws.
- client: Memoize message parsing for each subscriber (2a7ba46)
1.4.0 (2020-09-10)
Package has been renamed from graphql-transport-ws to graphql-ws.
- client: Only
queryis required in the subscribe payload (e892530)
- server: Pass roots for operation fields as an option (dcb5ed4)
1.3.0 (2020-09-10)
Package has been renamed from graphql-transport-ws to graphql-ws.
- 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)
Package has been renamed from graphql-transport-ws to graphql-ws.
- Package rename
@enisdenjo/graphql-transport-ws👉graphql-transport-ws. (494f676)
1.1.1 (2020-08-28)
Package has been renamed from graphql-transport-ws to graphql-ws.
- 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)
Package has been renamed from graphql-transport-ws to graphql-ws.
- server: allow skipping init message wait with zero values (a7419df)
- server: use subscription specific formatter for queries and mutations too (5672a04)
1.0.2 (2020-08-26)
Package has been renamed from graphql-transport-ws to graphql-ws.
- correctly detect WebSocket server (eab29dc)
1.0.1 (2020-08-26)
Package has been renamed from graphql-transport-ws to graphql-ws.
- 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)
Package has been renamed from graphql-transport-ws to graphql-ws.
- 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)
- This lib is no longer compatible with
subscriptions-transport-ws. It follows a redesigned transport protocol aiming to improve security, stability and reduce ambiguity.