Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version Packages #4

Merged
merged 1 commit into from
Mar 20, 2023
Merged

Version Packages #4

merged 1 commit into from
Mar 20, 2023

Conversation

github-actions[bot]
Copy link

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to master, this PR will be updated.

Releases

@ilijanl/graphql-ws-graphqless@5.14.0

Minor Changes

  • 9313717: Simplify subscription payload

Features

  • Remove graphql dependency (bc2465c)

1.0.0 (2023-03-16)

Bug Fixes

  • Add browser export map (ea306db)
  • Add package.json to exports map (#119) (1f09863), closes #118
  • Add uWebSockets exports path (36247cb), closes #155
  • Add support for graphql@v16 (ad5aea2)
  • add the sink to the subscribed map AFTER emitting a subscribe message (814f46c)
  • Add types path to package.json exports (#375) (9f394d7)
  • client: complete should not be called after subscription error (1fba419)
  • client: ConnectionInit payload is absent if connectionParams returns nothing (98f8265)
  • client: isFatalConnectionProblem defaults to undefined for using shouldRetry (9d5c573)
  • client: Accept nullish values for operationName and variables (2d60dda)
  • 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: Close event's wasClean is not necessary (2c65f0e), closes #81
  • client: Close with error message during connecting issues (f8ecdd7)
  • client: Connection locks dont increment on retries (1e7bd97), closes #153
  • client: Debounce close by lazyCloseTimeout (c332837), closes #388
  • client: Dispose of subscription on complete or error messages (#23) (fb4d8e9)
  • client: Distinguish client connection closes (ed4d9db)
  • client: Don't complete after connection error (5f829c3)
  • client: Export relevant elements from the browser bundle (b106dbe), closes #97
  • client: Lazy connects after successful reconnects are not retries (99b85a3)
  • client: Limit client emitted error close message size (2d959f6)
  • client: New error event listener for handling connection errors (#136) (127b69f), closes #135
  • client: No retries when disposed (0d5e6c2)
  • client: One cleanup per subscription (#67) (5a5ae4d)
  • client: Only query is required in the subscribe payload (e892530)
  • client: Reduce WebSocket event listeners and add new client message event (#104) (68d0e20), closes #102
  • client: Report close causing internal errors to error listeners (4e7e389)
  • client: Report close error even if Complete message followed (27754b2), closes #245
  • client: Return ping's payload through the response pong (ee6193a)
  • client: send complete message and close only if socket is still open (49b75ce)
  • client: Should emit closed event when disposing (5800de8), closes #108
  • client: Shouldn't reconnect if all subscriptions complete while waiting for retry (2826c10), closes #163
  • client: Shouldn’t send the Complete message if socket is not open (cd12024)
  • client: Some close events are not worth retrying (4d9134b)
  • client: Specify and fail on fatal internal WebSocket close codes (a720125)
  • client: Stabilize and simplify internals (#100) (5ff8f1d), closes #99 #85
  • client: Stop execution if connectionParams took too long and the server kicked the client off (1e94e45), closes #331
  • client: Subscribes even if socket is in CLOSING state due to all subscriptions being completed (3e3b8b7), closes #173 #170
  • client: Subscription can be disposed only once (abd9c28), closes #170
  • client: Subscriptions acquire locks (eb6cb2a)
  • client: Time retries and socket change waits (7c707db), closes #85
  • client: Wait for server acknowledgement indefinitely (a4bd602), closes #98
  • Close the details tag in the README (84144c4)
  • correctly detect WebSocket server (eab29dc)
  • Define entry points through the exports field and use .mjs suffixed ESM imports (#110) (4196238)
  • Define graphql execution results (a64c91b)
  • Drop TypeScript DOM lib dependency (a81e8c1)
  • export both the client and the server from index (29923b1)
  • Export useful types (e4cc4d4)
  • fastify-websocket: Handle connection and socket emitted errors (71e9586)
  • fastify-websocket: Handle server emitted errors (3fa17a7)
  • http and ws have no default exports (5c01ed9)
  • include types file holding important types (f3e4edf)
  • Main entrypoint in exports is just "." (8f70b02)
  • 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
  • Node 10 is the min supported version (19844d7)
  • notify only relevant sinks about errors or completions (62155ba)
  • Only UMD build has side effects (66ed43f)
  • Reorder types paths in package.json for better import resolution (#406) (37263c5)
  • reset connected/connecting state when disconnecting and disposing (2eb3cd5)
  • server: handleProtocols accepts arrays too and gracefully rejects other types (98dec1a), closes #318
  • server: onDisconnect is called exclusively if the connection is acknowledged (33ed5f2)
  • server: return instead of break at switch case ends (e9447e4), closes #140
  • server: subscription operations are distinct on the message ID (#24) (dfffb05)
  • server: allow skipping init message wait with zero values (a7419df)
  • server: Async iterator must implement return (d99982b), closes #149
  • server: Client can complete/cancel any operation (0ad1c4c)
  • 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)
  • server: Enforce ID uniqueness across all operations and during the whole subscription life (#96) (65d1bfa)
  • server: Handle upgrade requests with multiple subprotocols and omit Sec-WebSocket-Protocol header if none supported (9bae064)
  • server: Hide internal server error messages from the client in production (36fe405), closes #31
  • server: Init context first on connection open (a80e753), closes #181
  • server: Limit internal server error close message size (8479f76)
  • server: Log internal errors to the console (6ddf0d1)
  • server: Make sure to use onSubscribe result exclusively (51fdb7c)
  • server: No need to bind this scope (f76ac73)
  • server: Operation result can be async generator or iterable (b1fb883)
  • server: Receiving more than one ConnectionInit message closes the socket immediately (757c6e9)
  • server: Respect completed subscriptions even if subscribe or onOperation didnt resolve yet (4700154)
  • server: Return ping's payload through the response pong (47730a9), closes #117
  • server: scoped execution result formatter from onConnect (f91fadb)
  • server: Should clean up subscription reservations on abrupt errors without relying on connection close (611c223)
  • server: Shouldn't send a complete message if client sent it (331fe47), closes #403
  • server: store the intial request in the context (6927ee0)
  • server: Use subscribe from the config (6fbd47c)
  • server: use subscription specific formatter for queries and mutations too (5672a04)
  • Sink's next callback always receives an ExecutionResult (045b402)
  • Stop sending messages after receiving complete (#65) (3f4f836)
  • Support more graphql versions (de69b4e)
  • Support more Node versions by not using globalThis (79c2ed2)
  • 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)
  • Use ID type for message id field (87ebd35)
  • uWebSockets: Handle premature and abrupt socket closes (9d3ff52), closes #186
  • Warn about subscriptions-transport-ws clients and provide migration link (e080739), closes #339 #325
  • ws,fastify-websocket: Send only on ready socket (8d13c9e)
  • ws,uWebSockets,@fastify/websocket: Handle internal errors that are not instances of Error (#442) (9884889), closes #441
  • ws: Handle socket emitted errors (a22c00f)
  • ws: Limit server emitted error close message size (50620df)
  • ws: Log server emitted errors to the console (0826b0a)
  • yarn engine is not required (#34) (89484b8)

Features

  • cjs, esm and umd builds with minification and compression for the browser (#58) (ebb8dfe)
  • Add extensions field to the subscribe message payload (d86a8e4)
  • Allow null payloads in messages (#456) (eeb0265), closes #455
  • Bidirectional ping/pong message types (#201) (1efaf83)
  • Centralise expected close codes in CloseCode enum (d10a75c)
  • client: connectionParams can return undefined (a543187)
  • client: connectionParams may return a promise (#71) (33f210c)
  • client: disablePong option for when implementing a custom pinger (6510360), closes #117
  • client: isFatalConnectionProblem option for deciding if the connect error should be immediately reported or the connection retried (#126) (8115871), closes #122
  • client: onNonLazyError allows you to catch errors reported in non-lazy mode (cd1e7df)
  • client: url option accepts a function or a Promise (#143) (76f522f), closes #145 #146
  • client: Add connectionAckWaitTimeout option (#228) (35ce054)
  • client: Add opened event for when a WebSocket opens (9053224)
  • client: Allow keeping the connection alive for some time before lazy closing (#69) (555c2c3)
  • client: Deprecate isFatalConnectionProblem option in favour of shouldRetry (d8dcf21)
  • client: Emit events for connecting, connected and closed (627775b)
  • client: Implement silent-reconnects (c6f7872), closes #7
  • client: introduce Socky 🧦 - the nifty internal socket state manager (#8) (a4bee6f)
  • client: Lazy option can be changed (fb0ec14)
  • client: Optional generateID to provide subscription IDs (#22) (9a3f54a), closes #21
  • client: Provide subscribe payload in generateID (d0bc6e1), closes #398
  • client: Re-implement following the new transport protocol (#6) (5191a35)
  • client: Rename keepAlive option to lazyCloseTimeout (3c1f13c)
  • client: Retry with randomised exponential backoff or provide your own strategy (#84) (d3e7a17)
  • client: Support providing custom WebSocket implementations (#18) (1515fe2)
  • client: Terminate the WebSocket abruptly and immediately (53ad515), closes #290
  • Descriptive invalid message errors (b46379e), closes #366
  • Optional payload for ping/pong message types (2fe0345), closes #117
  • Package ECMAScript Modules too (#87) (2108174)
  • Package rename @enisdenjo/graphql-transport-ws 👉 graphql-transport-ws. (494f676)
  • Rewrite GraphQL over WebSocket Protocol (#2) (42045c5)
  • Send optional payload with the ConnectionAck message (#60) (1327e77)
  • server: context may return a promise (cd5c2f8), closes #74
  • server: execute and subscribe are optional (#148) (af748b0)
  • server: Add onClose callback for closures at any point in time (dd0d4fa)
  • server: Add onDisconnect callback (#94) (2a61268)
  • server: Add support for ws@v8 (9119153)
  • server: Define execution/subscription context in creation options (5b3d253), closes #13
  • server: Dynamic schema support by accepting a function or a Promise (#147) (6a0bf94), closes #127
  • server: For dynamic usage, context option can be a function too (#46) (149b582)
  • server: Implement following the new transport protocol (#1) (a412d25)
  • server: Log a warning for unsupported subprotocols (88a12ef), closes #92
  • server: Make and use with your own flavour (#64) (38bde87), closes #61 #73 #75
  • server: More callbacks, clearer differences and higher extensibility (#40) (507a222)
  • server: Optional onPing and onPong message type listeners (f36066f)
  • server: Pass roots for operation fields as an option (dcb5ed4)
  • server: Support returning multiple results from execute (#28) (dbbd88b)
  • server: Use @fastify/websocket (#382) (dd755b0), closes #381
  • server: Use fastify-websocket (#200) (b62fc95)
  • server: Use validate option for custom GraphQL validation (b68d56c)
  • server: Use uWebSockets (#89) (45d08fc), closes #61
  • Subscribe message query must be a string (#45) (60d9cd5)
  • Support custom JSON message reviver and replacer (#172) (0a9894e)
  • TypeScript generic for connection init payload (connectionParams) (#311) (e67cf80)
  • use: Generic for extending the context extras (401cd4c), closes #189
  • uWebSockets: Add persistedRequest to context extra and deprecate uWS's stack allocated request (#196) (736e6ed)
  • uWebSockets: Drop deprecated request context extra (02ea5ee)
  • WebSocket Ping and Pong as keep-alive (#11) (16ae316)

Performance Improvements

  • client: Await timeouts only in recursive connects (55c8fc8)
  • client: Focus subscription message listeners on id (#150) (32c2268)
  • client: Memoize message parsing for each subscriber (2a7ba46)
  • Easier message parser (d44c6f1)
  • Reduce runtime prototype traversal for hasOwnProperty (#52) (1bb9218)

Reverts

  • Revert "refactor: emit client connect in next tick during testing" (c10d0bf)

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.
  • 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.
  • 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),
    ),
  );
};
  • 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)
);
  • This lib is no longer compatible with subscriptions-transport-ws. It follows a redesigned transport protocol aiming to improve security, stability and reduce ambiguity.

5.12.0 (2023-03-06)

Features

@github-actions github-actions bot force-pushed the changeset-release/master branch from 6b19e8e to f17fea5 Compare March 20, 2023 09:36
@ilijaNL ilijaNL merged commit 059a2fc into master Mar 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

graphql-transport-ws rejection specification
1 participant