Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# 1.0.0 (2023-03-16) ### Bug Fixes * Add `browser` export map ([ea306db](ea306db)) * Add `package.json` to exports map ([enisdenjo#119](https://github.com/ilijaNL/graphql-ws/issues/119)) ([1f09863](1f09863)), closes [enisdenjo#118](https://github.com/ilijaNL/graphql-ws/issues/118) * Add `uWebSockets` exports path ([36247cb](36247cb)), closes [enisdenjo#155](https://github.com/ilijaNL/graphql-ws/issues/155) * Add support for `graphql@v16` ([ad5aea2](ad5aea2)) * add the sink to the subscribed map AFTER emitting a subscribe message ([814f46c](814f46c)) * Add types path to package.json `exports` ([enisdenjo#375](https://github.com/ilijaNL/graphql-ws/issues/375)) ([9f394d7](9f394d7)) * **client:** `complete` should not be called after subscription `error` ([1fba419](1fba419)) * **client:** `ConnectionInit` payload is absent if `connectionParams` returns nothing ([98f8265](98f8265)) * **client:** `isFatalConnectionProblem` defaults to undefined for using `shouldRetry` ([9d5c573](9d5c573)) * **client:** Accept nullish values for `operationName` and `variables` ([2d60dda](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](9ccb46b)) * **client:** Close event's `wasClean` is not necessary ([2c65f0e](2c65f0e)), closes [enisdenjo#81](https://github.com/ilijaNL/graphql-ws/issues/81) * **client:** Close with error message during connecting issues ([f8ecdd7](f8ecdd7)) * **client:** Connection locks dont increment on retries ([1e7bd97](1e7bd97)), closes [enisdenjo#153](https://github.com/ilijaNL/graphql-ws/issues/153) * **client:** Debounce close by `lazyCloseTimeout` ([c332837](c332837)), closes [enisdenjo#388](https://github.com/ilijaNL/graphql-ws/issues/388) * **client:** Dispose of subscription on complete or error messages ([enisdenjo#23](https://github.com/ilijaNL/graphql-ws/issues/23)) ([fb4d8e9](fb4d8e9)) * **client:** Distinguish client connection closes ([ed4d9db](ed4d9db)) * **client:** Don't complete after connection error ([5f829c3](5f829c3)) * **client:** Export relevant elements from the browser bundle ([b106dbe](b106dbe)), closes [enisdenjo#97](https://github.com/ilijaNL/graphql-ws/issues/97) * **client:** Lazy connects after successful reconnects are not retries ([99b85a3](99b85a3)) * **client:** Limit client emitted error close message size ([2d959f6](2d959f6)) * **client:** New `error` event listener for handling connection errors ([enisdenjo#136](https://github.com/ilijaNL/graphql-ws/issues/136)) ([127b69f](127b69f)), closes [enisdenjo#135](https://github.com/ilijaNL/graphql-ws/issues/135) * **client:** No retries when disposed ([0d5e6c2](0d5e6c2)) * **client:** One cleanup per subscription ([enisdenjo#67](https://github.com/ilijaNL/graphql-ws/issues/67)) ([5a5ae4d](5a5ae4d)) * **client:** Only `query` is required in the subscribe payload ([e892530](e892530)) * **client:** Reduce WebSocket event listeners and add new client `message` event ([enisdenjo#104](https://github.com/ilijaNL/graphql-ws/issues/104)) ([68d0e20](68d0e20)), closes [enisdenjo#102](https://github.com/ilijaNL/graphql-ws/issues/102) * **client:** Report close causing internal errors to error listeners ([4e7e389](4e7e389)) * **client:** Report close error even if `Complete` message followed ([27754b2](27754b2)), closes [enisdenjo#245](https://github.com/ilijaNL/graphql-ws/issues/245) * **client:** Return ping's payload through the response pong ([ee6193a](ee6193a)) * **client:** send complete message and close only if socket is still open ([49b75ce](49b75ce)) * **client:** Should emit `closed` event when disposing ([5800de8](5800de8)), closes [enisdenjo#108](https://github.com/ilijaNL/graphql-ws/issues/108) * **client:** Shouldn't reconnect if all subscriptions complete while waiting for retry ([2826c10](2826c10)), closes [enisdenjo#163](https://github.com/ilijaNL/graphql-ws/issues/163) * **client:** Shouldn’t send the `Complete` message if socket is not open ([cd12024](cd12024)) * **client:** Some close events are not worth retrying ([4d9134b](4d9134b)) * **client:** Specify and fail on fatal internal WebSocket close codes ([a720125](a720125)) * **client:** Stabilize and simplify internals ([enisdenjo#100](https://github.com/ilijaNL/graphql-ws/issues/100)) ([5ff8f1d](5ff8f1d)), closes [enisdenjo#99](https://github.com/ilijaNL/graphql-ws/issues/99) [enisdenjo#85](https://github.com/ilijaNL/graphql-ws/issues/85) * **client:** Stop execution if `connectionParams` took too long and the server kicked the client off ([1e94e45](1e94e45)), closes [enisdenjo#331](https://github.com/ilijaNL/graphql-ws/issues/331) * **client:** Subscribes even if socket is in CLOSING state due to all subscriptions being completed ([3e3b8b7](3e3b8b7)), closes [enisdenjo#173](https://github.com/ilijaNL/graphql-ws/issues/173) [enisdenjo#170](https://github.com/ilijaNL/graphql-ws/issues/170) * **client:** Subscription can be disposed only once ([abd9c28](abd9c28)), closes [enisdenjo#170](https://github.com/ilijaNL/graphql-ws/issues/170) * **client:** Subscriptions acquire locks ([eb6cb2a](eb6cb2a)) * **client:** Time retries and socket change waits ([7c707db](7c707db)), closes [enisdenjo#85](https://github.com/ilijaNL/graphql-ws/issues/85) * **client:** Wait for server acknowledgement indefinitely ([a4bd602](a4bd602)), closes [enisdenjo#98](https://github.com/ilijaNL/graphql-ws/issues/98) * Close the details tag in the README ([84144c4](84144c4)) * correctly detect WebSocket server ([eab29dc](eab29dc)) * Define entry points through the `exports` field and use `.mjs` suffixed ESM imports ([enisdenjo#110](https://github.com/ilijaNL/graphql-ws/issues/110)) ([4196238](4196238)) * Define graphql execution results ([a64c91b](a64c91b)) * Drop TypeScript DOM lib dependency ([a81e8c1](a81e8c1)) * export both the client and the server from index ([29923b1](29923b1)) * Export useful types ([e4cc4d4](e4cc4d4)) * **fastify-websocket:** Handle connection and socket emitted errors ([71e9586](71e9586)) * **fastify-websocket:** Handle server emitted errors ([3fa17a7](3fa17a7)) * http and ws have no default exports ([5c01ed9](5c01ed9)) * include `types` file holding important types ([f3e4edf](f3e4edf)) * Main entrypoint in `exports` is just `"."` ([8f70b02](8f70b02)) * **message:** Allow `data` field to be of any type ([533248e](533248e)), closes [enisdenjo#72](https://github.com/ilijaNL/graphql-ws/issues/72) * **message:** Allow `payload` field to be of any type for `NextMessage` ([7cebbfe](7cebbfe)), closes [enisdenjo#72](https://github.com/ilijaNL/graphql-ws/issues/72) * Node 10 is the min supported version ([19844d7](19844d7)) * notify only relevant sinks about errors or completions ([62155ba](62155ba)) * Only UMD build has side effects ([66ed43f](66ed43f)) * Reorder types paths in package.json for better import resolution ([enisdenjo#406](https://github.com/ilijaNL/graphql-ws/issues/406)) ([37263c5](37263c5)) * reset connected/connecting state when disconnecting and disposing ([2eb3cd5](2eb3cd5)) * **server:** `handleProtocols` accepts arrays too and gracefully rejects other types ([98dec1a](98dec1a)), closes [enisdenjo#318](https://github.com/ilijaNL/graphql-ws/issues/318) * **server:** `onDisconnect` is called exclusively if the connection is acknowledged ([33ed5f2](33ed5f2)) * **server:** `return` instead of `break` at switch case ends ([e9447e4](e9447e4)), closes [enisdenjo#140](https://github.com/ilijaNL/graphql-ws/issues/140) * **server:** `subscription` operations are distinct on the message ID ([enisdenjo#24](https://github.com/ilijaNL/graphql-ws/issues/24)) ([dfffb05](dfffb05)) * **server:** allow skipping init message wait with zero values ([a7419df](a7419df)) * **server:** Async iterator must implement `return` ([d99982b](d99982b)), closes [enisdenjo#149](https://github.com/ilijaNL/graphql-ws/issues/149) * **server:** Client can complete/cancel any operation ([0ad1c4c](0ad1c4c)) * **server:** Close socket if `onSubscribe` returns invalid array ([enisdenjo#53](https://github.com/ilijaNL/graphql-ws/issues/53)) ([0464a54](0464a54)) * **server:** Consistently set `rootValue` and `contextValue`, if not overridden ([enisdenjo#49](https://github.com/ilijaNL/graphql-ws/issues/49)) ([7aa3bcd](7aa3bcd)) * **server:** Distribute server error to all clients even if one error listener throws ([enisdenjo#56](https://github.com/ilijaNL/graphql-ws/issues/56)) ([b96dbb9](b96dbb9)) * **server:** Don't surface bad request error details in production ([enisdenjo#55](https://github.com/ilijaNL/graphql-ws/issues/55)) ([70317b2](70317b2)) * **server:** Enforce ID uniqueness across all operations and during the whole subscription life ([enisdenjo#96](https://github.com/ilijaNL/graphql-ws/issues/96)) ([65d1bfa](65d1bfa)) * **server:** Handle upgrade requests with multiple subprotocols and omit `Sec-WebSocket-Protocol` header if none supported ([9bae064](9bae064)) * **server:** Hide internal server error messages from the client in production ([36fe405](36fe405)), closes [enisdenjo#31](https://github.com/ilijaNL/graphql-ws/issues/31) * **server:** Init context first on connection open ([a80e753](a80e753)), closes [enisdenjo#181](https://github.com/ilijaNL/graphql-ws/issues/181) * **server:** Limit internal server error close message size ([8479f76](8479f76)) * **server:** Log internal errors to the console ([6ddf0d1](6ddf0d1)) * **server:** Make sure to use `onSubscribe` result exclusively ([51fdb7c](51fdb7c)) * **server:** No need to bind `this` scope ([f76ac73](f76ac73)) * **server:** Operation result can be async generator or iterable ([b1fb883](b1fb883)) * **server:** Receiving more than one `ConnectionInit` message closes the socket immediately ([757c6e9](757c6e9)) * **server:** Respect completed subscriptions even if `subscribe` or `onOperation` didnt resolve yet ([4700154](4700154)) * **server:** Return ping's payload through the response pong ([47730a9](47730a9)), closes [enisdenjo#117](https://github.com/ilijaNL/graphql-ws/issues/117) * **server:** scoped execution result formatter from `onConnect` ([f91fadb](f91fadb)) * **server:** Should clean up subscription reservations on abrupt errors without relying on connection close ([611c223](611c223)) * **server:** Shouldn't send a complete message if client sent it ([331fe47](331fe47)), closes [enisdenjo#403](https://github.com/ilijaNL/graphql-ws/issues/403) * **server:** store the intial request in the context ([6927ee0](6927ee0)) * **server:** Use `subscribe` from the config ([6fbd47c](6fbd47c)) * **server:** use subscription specific formatter for queries and mutations too ([5672a04](5672a04)) * Sink's next callback always receives an `ExecutionResult` ([045b402](045b402)) * Stop sending messages after receiving complete ([enisdenjo#65](https://github.com/ilijaNL/graphql-ws/issues/65)) ([3f4f836](3f4f836)) * Support more `graphql` versions ([de69b4e](de69b4e)) * Support more Node versions by not using `globalThis` ([79c2ed2](79c2ed2)) * Use `4406` close code for unsupported subprotocol (`1002` is an internal WebSocket close code) ([df85281](df85281)) * Use `4500` close code for internal server errors (`1011` is an internal WebSocket close code) ([3c0316d](3c0316d)) * Use `ID` type for message id field ([87ebd35](87ebd35)) * **uWebSockets:** Handle premature and abrupt socket closes ([9d3ff52](9d3ff52)), closes [enisdenjo#186](https://github.com/ilijaNL/graphql-ws/issues/186) * Warn about subscriptions-transport-ws clients and provide migration link ([e080739](e080739)), closes [enisdenjo#339](https://github.com/ilijaNL/graphql-ws/issues/339) [enisdenjo#325](https://github.com/ilijaNL/graphql-ws/issues/325) * **ws,fastify-websocket:** Send only on ready socket ([8d13c9e](8d13c9e)) * **ws,uWebSockets,@fastify/websocket:** Handle internal errors that are not instances of `Error` ([enisdenjo#442](https://github.com/ilijaNL/graphql-ws/issues/442)) ([9884889](9884889)), closes [enisdenjo#441](https://github.com/ilijaNL/graphql-ws/issues/441) * **ws:** Handle socket emitted errors ([a22c00f](a22c00f)) * **ws:** Limit server emitted error close message size ([50620df](50620df)) * **ws:** Log server emitted errors to the console ([0826b0a](0826b0a)) * yarn engine is not required ([enisdenjo#34](https://github.com/ilijaNL/graphql-ws/issues/34)) ([89484b8](89484b8)) ### Features * `cjs`, `esm` and `umd` builds with minification and compression for the browser ([enisdenjo#58](https://github.com/ilijaNL/graphql-ws/issues/58)) ([ebb8dfe](ebb8dfe)) * Add `extensions` field to the subscribe message payload ([d86a8e4](d86a8e4)) * Allow null payloads in messages ([enisdenjo#456](https://github.com/ilijaNL/graphql-ws/issues/456)) ([eeb0265](eeb0265)), closes [enisdenjo#455](https://github.com/ilijaNL/graphql-ws/issues/455) * Bidirectional ping/pong message types ([enisdenjo#201](https://github.com/ilijaNL/graphql-ws/issues/201)) ([1efaf83](1efaf83)) * Centralise expected close codes in `CloseCode` enum ([d10a75c](d10a75c)) * **client:** `connectionParams` can return `undefined` ([a543187](a543187)) * **client:** `connectionParams` may return a promise ([enisdenjo#71](https://github.com/ilijaNL/graphql-ws/issues/71)) ([33f210c](33f210c)) * **client:** `disablePong` option for when implementing a custom pinger ([6510360](6510360)), closes [enisdenjo#117](https://github.com/ilijaNL/graphql-ws/issues/117) * **client:** `isFatalConnectionProblem` option for deciding if the connect error should be immediately reported or the connection retried ([enisdenjo#126](https://github.com/ilijaNL/graphql-ws/issues/126)) ([8115871](8115871)), closes [enisdenjo#122](https://github.com/ilijaNL/graphql-ws/issues/122) * **client:** `onNonLazyError` allows you to catch errors reported in non-lazy mode ([cd1e7df](cd1e7df)) * **client:** `url` option accepts a function or a Promise ([enisdenjo#143](https://github.com/ilijaNL/graphql-ws/issues/143)) ([76f522f](76f522f)), closes [enisdenjo#145](https://github.com/ilijaNL/graphql-ws/issues/145) [enisdenjo#146](https://github.com/ilijaNL/graphql-ws/issues/146) * **client:** Add `connectionAckWaitTimeout` option ([enisdenjo#228](https://github.com/ilijaNL/graphql-ws/issues/228)) ([35ce054](35ce054)) * **client:** Add `opened` event for when a WebSocket opens ([9053224](9053224)) * **client:** Allow keeping the connection alive for some time before lazy closing ([enisdenjo#69](https://github.com/ilijaNL/graphql-ws/issues/69)) ([555c2c3](555c2c3)) * **client:** Deprecate `isFatalConnectionProblem` option in favour of `shouldRetry` ([d8dcf21](d8dcf21)) * **client:** Emit events for `connecting`, `connected` and `closed` ([627775b](627775b)) * **client:** Implement silent-reconnects ([c6f7872](c6f7872)), closes [enisdenjo#7](https://github.com/ilijaNL/graphql-ws/issues/7) * **client:** introduce Socky 🧦 - the nifty internal socket state manager ([enisdenjo#8](https://github.com/ilijaNL/graphql-ws/issues/8)) ([a4bee6f](a4bee6f)) * **client:** Lazy option can be changed ([fb0ec14](fb0ec14)) * **client:** Optional `generateID` to provide subscription IDs ([enisdenjo#22](https://github.com/ilijaNL/graphql-ws/issues/22)) ([9a3f54a](9a3f54a)), closes [enisdenjo#21](https://github.com/ilijaNL/graphql-ws/issues/21) * **client:** Provide subscribe payload in `generateID` ([d0bc6e1](d0bc6e1)), closes [enisdenjo#398](https://github.com/ilijaNL/graphql-ws/issues/398) * **client:** Re-implement following the new transport protocol ([#6](#6)) ([5191a35](5191a35)) * **client:** Rename `keepAlive` option to `lazyCloseTimeout` ([3c1f13c](3c1f13c)) * **client:** Retry with randomised exponential backoff or provide your own strategy ([enisdenjo#84](https://github.com/ilijaNL/graphql-ws/issues/84)) ([d3e7a17](d3e7a17)) * **client:** Support providing custom WebSocket implementations ([enisdenjo#18](https://github.com/ilijaNL/graphql-ws/issues/18)) ([1515fe2](1515fe2)) * **client:** Terminate the WebSocket abruptly and immediately ([53ad515](53ad515)), closes [enisdenjo#290](https://github.com/ilijaNL/graphql-ws/issues/290) * Descriptive invalid message errors ([b46379e](b46379e)), closes [enisdenjo#366](https://github.com/ilijaNL/graphql-ws/issues/366) * Optional `payload` for ping/pong message types ([2fe0345](2fe0345)), closes [enisdenjo#117](https://github.com/ilijaNL/graphql-ws/issues/117) * Package ECMAScript Modules too ([enisdenjo#87](https://github.com/ilijaNL/graphql-ws/issues/87)) ([2108174](2108174)) * Package rename `@enisdenjo/graphql-transport-ws` 👉 `graphql-transport-ws`. ([494f676](494f676)) * Rewrite GraphQL over WebSocket Protocol ([#2](#2)) ([42045c5](42045c5)) * Send optional payload with the `ConnectionAck` message ([enisdenjo#60](https://github.com/ilijaNL/graphql-ws/issues/60)) ([1327e77](1327e77)) * **server:** `context` may return a promise ([cd5c2f8](cd5c2f8)), closes [enisdenjo#74](https://github.com/ilijaNL/graphql-ws/issues/74) * **server:** `execute` and `subscribe` are optional ([enisdenjo#148](https://github.com/ilijaNL/graphql-ws/issues/148)) ([af748b0](af748b0)) * **server:** Add `onClose` callback for closures at _any_ point in time ([dd0d4fa](dd0d4fa)) * **server:** Add `onDisconnect` callback ([enisdenjo#94](https://github.com/ilijaNL/graphql-ws/issues/94)) ([2a61268](2a61268)) * **server:** Add support for `ws@v8` ([9119153](9119153)) * **server:** Define execution/subscription `context` in creation options ([5b3d253](5b3d253)), closes [enisdenjo#13](https://github.com/ilijaNL/graphql-ws/issues/13) * **server:** Dynamic `schema` support by accepting a function or a Promise ([enisdenjo#147](https://github.com/ilijaNL/graphql-ws/issues/147)) ([6a0bf94](6a0bf94)), closes [enisdenjo#127](https://github.com/ilijaNL/graphql-ws/issues/127) * **server:** For dynamic usage, `context` option can be a function too ([enisdenjo#46](https://github.com/ilijaNL/graphql-ws/issues/46)) ([149b582](149b582)) * **server:** Implement following the new transport protocol ([#1](#1)) ([a412d25](a412d25)) * **server:** Log a warning for unsupported subprotocols ([88a12ef](88a12ef)), closes [enisdenjo#92](https://github.com/ilijaNL/graphql-ws/issues/92) * **server:** Make and use with your own flavour ([enisdenjo#64](https://github.com/ilijaNL/graphql-ws/issues/64)) ([38bde87](38bde87)), closes [enisdenjo#61](https://github.com/ilijaNL/graphql-ws/issues/61) [enisdenjo#73](https://github.com/ilijaNL/graphql-ws/issues/73) [enisdenjo#75](https://github.com/ilijaNL/graphql-ws/issues/75) * **server:** More callbacks, clearer differences and higher extensibility ([enisdenjo#40](https://github.com/ilijaNL/graphql-ws/issues/40)) ([507a222](507a222)) * **server:** Optional `onPing` and `onPong` message type listeners ([f36066f](f36066f)) * **server:** Pass roots for operation fields as an option ([dcb5ed4](dcb5ed4)) * **server:** Support returning multiple results from `execute` ([enisdenjo#28](https://github.com/ilijaNL/graphql-ws/issues/28)) ([dbbd88b](dbbd88b)) * **server:** Use `@fastify/websocket` ([enisdenjo#382](https://github.com/ilijaNL/graphql-ws/issues/382)) ([dd755b0](dd755b0)), closes [enisdenjo#381](https://github.com/ilijaNL/graphql-ws/issues/381) * **server:** Use `fastify-websocket` ([enisdenjo#200](https://github.com/ilijaNL/graphql-ws/issues/200)) ([b62fc95](b62fc95)) * **server:** Use `validate` option for custom GraphQL validation ([b68d56c](b68d56c)) * **server:** Use uWebSockets ([enisdenjo#89](https://github.com/ilijaNL/graphql-ws/issues/89)) ([45d08fc](45d08fc)), closes [enisdenjo#61](https://github.com/ilijaNL/graphql-ws/issues/61) * Subscribe message `query` must be a string ([enisdenjo#45](https://github.com/ilijaNL/graphql-ws/issues/45)) ([60d9cd5](60d9cd5)) * Support custom JSON message `reviver` and `replacer` ([enisdenjo#172](https://github.com/ilijaNL/graphql-ws/issues/172)) ([0a9894e](0a9894e)) * TypeScript generic for connection init payload (`connectionParams`) ([enisdenjo#311](https://github.com/ilijaNL/graphql-ws/issues/311)) ([e67cf80](e67cf80)) * **use:** Generic for extending the context extras ([401cd4c](401cd4c)), closes [enisdenjo#189](https://github.com/ilijaNL/graphql-ws/issues/189) * **uWebSockets:** Add `persistedRequest` to context extra and deprecate uWS's stack allocated `request` ([enisdenjo#196](https://github.com/ilijaNL/graphql-ws/issues/196)) ([736e6ed](736e6ed)) * **uWebSockets:** Drop deprecated `request` context extra ([02ea5ee](02ea5ee)) * WebSocket Ping and Pong as keep-alive ([enisdenjo#11](https://github.com/ilijaNL/graphql-ws/issues/11)) ([16ae316](16ae316)) ### Performance Improvements * **client:** Await timeouts only in recursive connects ([55c8fc8](55c8fc8)) * **client:** Focus subscription message listeners on `id` ([enisdenjo#150](https://github.com/ilijaNL/graphql-ws/issues/150)) ([32c2268](32c2268)) * **client:** Memoize message parsing for each subscriber ([2a7ba46](2a7ba46)) * Easier message parser ([d44c6f1](d44c6f1)) * Reduce runtime prototype traversal for hasOwnProperty ([enisdenjo#52](https://github.com/ilijaNL/graphql-ws/issues/52)) ([1bb9218](1bb9218)) ### Reverts * Revert "refactor: emit client connect in next tick during testing" ([c10d0bf](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: ```js 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: ```ts // 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](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#Pings_and_Pongs_The_Heartbeat_of_WebSockets))_ - 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](https://github.com/websockets/ws) is just one way of using `graphql-ws`. This is how to use the implementation shipped with the lib: ```ts /** * ❌ 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`](https://github.com/apollographql/subscriptions-transport-ws). It follows a redesigned transport protocol aiming to improve security, stability and reduce ambiguity.
- Loading branch information