Skip to content

Latest commit

 

History

History
1394 lines (873 loc) · 74.4 KB

CHANGELOG.md

File metadata and controls

1394 lines (873 loc) · 74.4 KB

graphql-ws

6.0.1

Patch Changes

6.0.0

Major Changes

  • b668b30 Thanks @enisdenjo! - @fastify/websocket WebSocket in the context extra has been renamed from connection to socket

    Migrating from v5 to v6

    import { makeHandler } from 'graphql-ws/use/@fastify/websocket';
    
    makeHandler({
      schema(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
      context(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
      onConnect(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
      onDisconnect(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
      onClose(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
      onSubscribe(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
      onOperation(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
      onError(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
      onNext(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
      onComplete(ctx) {
    -   const websocket = ctx.connection;
    +   const websocket = ctx.socket;
      },
    });
  • #613 3f11aba Thanks @enisdenjo! - Drop support for ws v7

    ws v7 has been deprecated. Please upgrade and use v8.

  • #613 3f11aba Thanks @enisdenjo! - Drop support for deprecated fastify-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 example graphql-ws/lib/use/ws becomes graphql-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 and onError returns GraphQLFormattedError (instead of GraphQLError)

    Thanks @benjie for working on this in #599

  • #613 3f11aba Thanks @enisdenjo! - Least supported Node version is v20

    Node 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 supported graphql peer dependency is ^15.10.1 and ^16

    Users are advised to use the latest of graphql because of various improvements in performance and security.

  • #613 3f11aba Thanks @enisdenjo! - NextMessage uses and onNext returns FormattedExecutionResult (instead of ExecutionResult)

  • #613 3f11aba Thanks @enisdenjo! - schema, context, onSubscribe, onOperation, onError, onNext and onComplete hooks don't have the full accompanying message anymore, only the ID and the relevant part from the message

    There is really no need to pass the full SubscribeMessage to the onSubscribe hook. The only relevant parts from the message are the id and the payload, the type is useless since the hook inherently has it (onNext is next type, onError is error type, etc).

    The actual techincal reason for not having the full message is to avoid serialising results and errors twice. Both onNext and onError allow the user to augment the result and return it to be used instead. onNext originally had the NextMessage argument which already has the FormattedExecutionResult, and onError originally had the ErrorMessage argument which already has the GraphQLFormattedError, and they both also returned FormattedExecutionResult and GraphQLFormattedError respectivelly - meaning, if the user serialised the results - the serialisation would happen twice.

    Additionally, the onOperation, onError, onNext and onComplete now have the payload which is the SubscribeMessage.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, the payload 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 to GraphQLError[] that are true instances of the error containing object references to originalErrors and other properties. The user can always convert and return GraphQLFormattedError[] 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());
    + },
    };

    onNext

    The NextMessage.payload (FormattedExecutionResult) is not useful here at all, the user has access to ExecutionResult that contains actual object references to error instances. The user can always convert and return FormattedExecutionResult by serialising the errors with GraphQLError.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()) };
    + },
    };

    onComplete

    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 3f11aba Thanks @enisdenjo! - Errors thrown from subscription iterables will be caught and reported through the ErrorMessage

    Compared 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 with errors field 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 3f11aba Thanks @enisdenjo! - Remove deprecated isMessage, use validateMessage instead

    Migrating from v5 to v6

    Replace all ocurrances of isMessage with validateMessage. Note that validateMessage throws if the message is not valid, compared with isMessage that 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 3f11aba Thanks @enisdenjo! - Removed deprecated isFatalConnectionProblem, use shouldRetry instead

    Migrating from v5 to v6

    Replace all ocurrances of isFatalConnectionProblem with shouldRetry. Note that the result is inverted, where you returned false in isFatalConnectionProblem you should return true in shouldRetry.

    import { createClient } from 'graphql-ws';
    
    const client = createClient({
      url: 'ws://localhost:4000/graphql',
    - isFatalConnectionProblem: () => false,
    + shouldRetry: () => true,
    });

Minor Changes

  • #613 3f11aba Thanks @enisdenjo! - Client is truly zero-dependency, not even a peer dependency on graphql

    In non-browser environments, you can use only the client and not even depend on graphql by importing from graphql-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 browser package.json field), you don't have to import from graphql-ws/client - simply importing from graphql-ws will only have the createClient available.

  • #615 29dd26a Thanks @enisdenjo! - Define optional peer dependencies and least supported versions

    Using the peerDependencies in combination with peerDependenciesMeta configuration in package.json.

5.16.2

Patch Changes

5.16.1

Patch 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

  • server: Close code and reason are optional (6ae6e6f), closes #547

5.15.0 (2024-02-12)

Bug Fixes

  • client: Use TerminatedCloseEvent class extending an Error for 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

  • server: Add is retry flag to connect events (#507) (9ad853f)

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

  • client: correct close code for Bad Gateway reason (#512) (0438650)

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

  • client: Async iterator for subscriptions (#486) (fb4b967)

5.13.1 (2023-05-15)

Bug Fixes

  • Remove unnecessary bun-types directives (e9a56f7), closes #478

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

  • Reorder types paths in package.json for better import resolution (#406) (37263c5)

5.11.1 (2022-09-16)

Bug Fixes

  • server: Shouldn't send a complete message if client sent it (331fe47), closes #403

5.11.0 (2022-09-16)

Features

  • client: Provide subscribe payload in generateID (d0bc6e1), closes #398

5.10.2 (2022-09-12)

Performance Improvements

5.10.1 (2022-08-19)

Bug Fixes

  • client: Debounce close by lazyCloseTimeout (c332837), closes #388

5.10.0 (2022-08-09)

Features

5.9.1 (2022-07-01)

Bug Fixes

  • Add types path to package.json exports (#375) (9f394d7)

5.9.0 (2022-06-09)

Features

  • Descriptive invalid message errors (b46379e), closes #366

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: isFatalConnectionProblem defaults to undefined for using shouldRetry (9d5c573)

5.8.0 (2022-04-25)

Features

  • client: Deprecate isFatalConnectionProblem option in favour of shouldRetry (d8dcf21)

5.7.0 (2022-04-07)

Features

  • client: Terminate the WebSocket abruptly and immediately (53ad515), closes #290

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 connectionParams took too long and the server kicked the client off (1e94e45), closes #331

5.6.2 (2022-02-23)

Bug Fixes

  • server: handleProtocols accepts 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-Protocol header if none supported (9bae064)

5.6.0 (2022-02-19)

Features

  • TypeScript generic for connection init payload (connectionParams) (#311) (e67cf80)

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 Complete message 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

  • client: Add connectionAckWaitTimeout option (#228) (35ce054)

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 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

  • Centralise expected close codes in CloseCode enum (d10a75c)
  • server: Add support for ws@v8 (9119153)

5.3.0 (2021-06-23)

Bug Fixes

  • client: ConnectionInit payload is absent if connectionParams returns nothing (98f8265)

Features

  • client: connectionParams can return undefined (a543187)
  • client: Add opened event for when a WebSocket opens (9053224)

5.2.0 (2021-06-21)

Features

  • server: Optional onPing and onPong message 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

  • server: Return ping's payload through the response pong (47730a9), closes #117

5.1.0 (2021-06-09)

Features

  • client: disablePong option for when implementing a custom pinger (6510360), closes #117
  • Optional payload for ping/pong message types (2fe0345), closes #117

5.0.0 (2021-06-08)

Features

  • Bidirectional ping/pong message types (#201) (1efaf83)
  • client: Rename keepAlive option to lazyCloseTimeout (3c1f13c)
  • uWebSockets: Drop deprecated request context 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 request context extra field has been dropped because it is stack allocated and cannot be used ouside the internal upgrade callback.
  • client: Client keepAlive option has been renamed to lazyCloseTimeout in 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 persistedRequest to context extra and deprecate uWS's stack allocated request (#196) (736e6ed)

4.7.0 (2021-05-31)

Features

  • Add extensions field to the subscribe message payload (d86a8e4)

4.6.0 (2021-05-30)

Features

  • use: Generic for extending the context extras (401cd4c), closes #189

4.5.2 (2021-05-28)

Bug Fixes

  • uWebSockets: Handle premature and abrupt socket closes (9d3ff52), closes #186

4.5.1 (2021-05-18)

Bug Fixes

  • server: Init context first on connection open (a80e753), closes #181

4.5.0 (2021-04-29)

Features

  • Support custom JSON message reviver and replacer (#172) (0a9894e)

4.4.4 (2021-04-28)

Bug Fixes

  • client: complete should not be called after subscription error (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

  • client: Connection locks dont increment on retries (1e7bd97), closes #153

4.3.2 (2021-03-29)

Bug Fixes

  • server: Async iterator must implement return (d99982b), closes #149

Performance Improvements

  • client: Focus subscription message listeners on id (#150) (32c2268)

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 subscribe or onOperation didnt resolve yet (4700154)

Features

  • client: url option accepts a function or a Promise (#143) (76f522f), closes #145 #146
  • server: execute and subscribe are optional (#148) (af748b0)
  • server: Dynamic schema support by accepting a function or a Promise (#147) (6a0bf94), closes #127
  • server: Use validate option for custom GraphQL validation (b68d56c)

4.2.3 (2021-03-23)

Bug Fixes

  • client: Reduce WebSocket event listeners and add new client message event (#104) (68d0e20), closes #102

4.2.2 (2021-03-17)

Bug Fixes

  • server: return instead of break at switch case ends (e9447e4), closes #140

4.2.1 (2021-03-11)

Bug Fixes

  • client: New error event listener for handling connection errors (#136) (127b69f), closes #135

4.2.0 (2021-02-25)

Bug Fixes

  • Only UMD build has side effects (66ed43f)

Features

  • client: isFatalConnectionProblem option 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 exports is just "." (8f70b02)

4.1.4 (2021-02-12)

Bug Fixes

  • Define entry points through the exports field and use .mjs suffixed ESM imports (#110) (4196238)

4.1.3 (2021-02-08)

Bug Fixes

  • client: Should emit closed event when disposing (5800de8), closes #108
  • client: Shouldn’t send the Complete message 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: onDisconnect is called exclusively if the connection is acknowledged (33ed5f2)

Features

  • server: Add onClose callback 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 onDisconnect callback (#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 the onDisconnect callback.
  • server: The Context.subscriptions record value can be either an AsyncIterator or a Promise.

3.2.0 (2020-12-17)

Features

3.1.0 (2020-12-11)

Bug Fixes

  • client: Time retries and socket change waits (7c707db), closes #85

Features

  • client: onNonLazyError allows 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

  • client: Retry with randomised exponential backoff or provide your own strategy (#84) (d3e7a17)

BREAKING CHANGES

  • client: Client retryTimeout option has been replaced with the new retryWait.

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

  • client: Close event's wasClean is not necessary (2c65f0e), closes #81

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 request in 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 more createServer)

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 extra field in the Context for 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

  • server: context may return a promise (cd5c2f8), closes #74

1.13.1 (2020-11-14)

Bug Fixes

  • client: Some close events are not worth retrying (4d9134b)
  • message: Allow data field to be of any type (533248e), closes #72
  • message: Allow payload field to be of any type for NextMessage (7cebbfe), closes #72
  • Use ID type 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: connectionParams may 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

  • Send optional payload with the ConnectionAck message (#60) (1327e77)

1.11.0 (2020-11-04)

Bug Fixes

  • Node 10 is the min supported version (19844d7)
  • Support more graphql versions (de69b4e)
  • server: Close socket if onSubscribe returns invalid array (#53) (0464a54)
  • server: Consistently set rootValue and contextValue, 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

  • cjs, esm and umd builds with minification and compression for the browser (#58) (ebb8dfe)

Performance Improvements

  • Reduce runtime prototype traversal for hasOwnProperty (#52) (1bb9218)

1.10.0 (2020-11-03)

Features

  • Subscribe message query must be a string (#45) (60d9cd5)
  • server: For dynamic usage, context option 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 onSubscribe result exclusively (51fdb7c)
  • Export useful types (e4cc4d4)
  • client: Accept nullish values for operationName and variables (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

  • server: More callbacks, clearer differences and higher extensibility (#40) (507a222)

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 Context and the SubscribeMessage
  • Now returns nothing,ExecutionArgs or an array of GraphQLErrors
    • Returning void (or nothing) will leave the execution args preparation and validation to the library
    • Returned ExecutionArgs will 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 the ErrorMessage

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 this scope (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

  • server: Support returning multiple results from execute (#28) (dbbd88b)

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: subscription operations are distinct on the message ID (#24) (dfffb05)

Features

  • client: Optional generateID to provide subscription IDs (#22) (9a3f54a), closes #21

1.6.0 (2020-09-28)

⚠️ Deprecated

Package has been renamed from graphql-transport-ws to graphql-ws.

Features

  • client: Support providing custom WebSocket implementations (#18) (1515fe2)

1.5.0 (2020-09-18)

⚠️ Deprecated

Package has been renamed from graphql-transport-ws to graphql-ws.

Bug Fixes

  • server: Use subscribe from the config (6fbd47c)

Features

  • server: Define execution/subscription context in creation options (5b3d253), closes #13

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 ConnectionInit message 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 query is 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, connected and closed (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

  • client: introduce Socky 🧦 - the nifty internal socket state manager (#8) (a4bee6f)

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.reason after 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 types file 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