8000 Use pkgroll, bump Node, remove deprecations, improve, shorter paths, … · enisdenjo/graphql-ws@3f11aba · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 3f11aba

Browse files
enisdenjobenjie
andauthored
Use pkgroll, bump Node, remove deprecations, improve, shorter paths, and friends (#613)
Co-authored-by: Benjie <benjie@jemjie.com>
1 parent 08915c4 commit 3f11aba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2199
-2238
lines changed

.changeset/clean-seas-work.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'graphql-ws': major
3+
---
4+
5+
Drop support for `ws` v7
6+
7+
`ws` v7 has been deprecated. Please upgrade and use v8.

.changeset/friendly-cats-sing.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'graphql-ws': major
3+
---
4+
5+
Drop support for deprecated `fastify-websocket`
6+
7+
[`fastify-websocket` has been deprecated since v4.3.0.](https://www.npmjs.com/package/fastify-websocket). Please upgrade and use [`@fastify/websocket`](https://github.com/fastify/fastify-websocket).

.changeset/lemon-dolls-check.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
'graphql-ws': major
3+
---
4+
5+
The `/lib/` part from imports has been removed, for example `graphql-ws/lib/use/ws` becomes `graphql-ws/use/ws`
6+
7+
### Migrating from v5 to v6
8+
9+
Simply remove the `/lib/` part from your graphql-ws imports that use a handler.
10+
11+
#### ws
12+
13+
```diff
14+
- import { useServer } from 'graphql-ws/lib/use/ws';
15+
+ import { useServer } from 'graphql-ws/use/ws';
16+
```
17+
18+
#### uWebSockets.js
19+
20+
```diff
21+
- import { makeBehavior } from 'graphql-ws/lib/use/uWebSockets';
22+
+ import { makeBehavior } from 'graphql-ws/use/uWebSockets';
23+
```
24+
25+
#### @fastify/websocket
26+
27+
```diff
28+
- import { makeHandler } from 'graphql-ws/lib/use/@fastify/websocket';
29+
+ import { makeHandler } from 'graphql-ws/use/@fastify/websocket';
30+
```
31+
32+
#### Bun
33+
34+
```diff
35+
- import { handleProtocols, makeHandler } from 'graphql-ws/lib/use/bun';
36+
+ import { handleProtocols, makeHandler } from 'graphql-ws/use/bun';
37+
```
38+
39+
#### Deno
40+
41+
```diff
42+
- import { makeHandler } from 'https://esm.sh/graphql-ws/lib/use/deno';
43+
+ import { makeHandler } from 'https://esm.sh/graphql-ws/use/deno';
44+
```

.changeset/long-glasses-drive.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'graphql-ws': major
3+
---
4+
5+
`ErrorMessage` uses and `onError` returns `GraphQLFormattedError` (instead of `GraphQLError`)

.changeset/nervous-peaches-hide.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'graphql-ws': major
3+
---
4+
5+
Least supported Node version is v20
6+
7+
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.

.changeset/shaggy-geese-learn.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'graphql-ws': major
3+
---
4+
5+
Least supported `graphql` peer dependency is ^15.10.0 and ^16.10.0
6+
7+
Users are advised to use the latest of `graphql` because of various improvements in performance and security.

.changeset/stale-tomatoes-deny.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'graphql-ws': major
3+
---
4+
5+
`NextMessage` uses and `onNext` returns `FormattedExecutionResult` (instead of `ExecutionResult`)

.changeset/strange-ties-mix.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
< 6B28 div class="diff-text-inner color-fg-muted">@@ -0,0 +1,107 @@
1+
---
2+
'graphql-ws': major
3+
---
4+
5+
`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
6+
7+
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).
8+
9+
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**.
10+
11+
### Migrating from v5 to v6
12+
13+
#### `onSubscribe`
14+
15+
```diff
16+
import { ServerOptions, SubscribePayload } from 'graphql-ws';
17+
18+
const opts: ServerOptions = {
19+
- onSubscribe(ctx, message) {
20+
- const messageId = message.id;
21+
- const messagePayload: SubscribePayload = message.payload;
22+
- },
23+
+ onSubscribe(ctx, id, payload) {
24+
+ const messageId = id;
25+
+ const messagePayload: SubscribePayload = payload;
26+
+ },
27+
};
28+
```
29+
30+
#### `onOperation`
31+
32+
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.
33+
34+
```diff
35+
import { ExecutionArgs } from 'graphql';
36+
import { ServerOptions, SubscribePayload } from 'graphql-ws';
37+
38+
const opts: ServerOptions = {
39+
- onOperation(ctx, message) {
40+
- const messageId = message.id;
41+
- const messagePayload: SubscribePayload = message.payload;
42+
- },
43+
+ onOperation(ctx, id, args) {
44+
+ const messageId = id;
45+
+ const executionArgs: ExecutionArgs = args;
46+
+ },
47+
};
48+
```
49+
50+
#### `onError`
51+
52+
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 `originalError`s and other properties. The user can always convert and return `GraphQLFormattedError[]` by using the `.toJSON()` method.
53+
54+
```diff
55+
import { GraphQLError, GraphQLFormattedError } from 'graphql';
56+
import { ServerOptions } from 'graphql-ws';
57+
58+
const opts: ServerOptions = {
59+
- onError(ctx, message, errors) {
60+
- const messageId = message.id;
61+
- const graphqlErrors: readonly GraphQLError[] = errors;
62+
- const messagePayload: readonly GraphQLFormattedError[] = message.payload;
63+
- },
64+
+ onError(ctx, id, errors) {
65+
+ const messageId = id;
66+
+ const graphqlErrors: readonly GraphQLError[] = errors;
67+
+ const messagePayload: readonly GraphQLFormattedError[] = errors.map((e) => e.toJSON());
68+
+ },
69+
};
70+
```
71+
72+
#### `onNext`
73+
74+
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.
75+
76+
```diff
77+
import { ExecutionResult, FormattedExecutionResult } from 'graphql';
78+
import { ServerOptions } from 'graphql-ws';
79+
80+
const opts: ServerOptions = {
81+
- onNext(ctx, message, result) {
82+
- const messageId = message.id;
83+
- const graphqlResult: ExecutionResult = result;
84+
- const messagePayload: FormattedExecutionResult = message.payload;
85+
- },
86+
+ onNext(ctx, id, result) {
87+
+ const messageId = id;
88+
+ const graphqlResult: ExecutionResult = result;
89+
+ const messagePayload: FormattedExecutionResult = { ...result, errors: result.errors?.map((e) => e.toJSON()) };
90+
+ },
91+
};
92+
```
93+
94+
#### `onComplete`
95+
96+
```diff
97+
import { ServerOptions } from 'graphql-ws';
98+
99+
const opts: ServerOptions = {
100+
- onComplete(ctx, message) {
101+
- const messageId = message.id;
102+
- },
103+
+ onComplete(ctx, id) {
104+
+ const messageId = id;
105+
+ },
106+
};
107+
```

.changeset/tiny-worms-fry.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
'graphql-ws': major
3+
---
4+
5+
Errors thrown from subscription iterables will be caught and reported through the `ErrorMessage`
6+
7+
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.
8+
9+
There's been [an editorial change in the GraphQL Spec suggesting this being the correct approach](https://github.com/graphql/graphql-spec/pull/1099).
10+
11+
Also, if you'd like to get involved and ideally drop your opinion about whether iterable errors should be reported as errors or `ExecutionResult`s with `errors` field set, [please read more here](https://github.com/graphql/graphql-spec/pull/1127).
12+
13+
### Migrating from v5 to v6
14+
15+
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.
16+
17+
```diff
18+
import { subscribe } from 'graphql';
19+
import { useServer } from 'graphql-ws/use/ws';
20+
import { WebSocketServer } from 'ws'; // yarn add ws
21+
22+
const wsServer = new WebSocketServer({
23+
port: 4000,
24+
path: '/graphql',
25+
});
26+
27+
useServer(
28+
{
29+
schema,
30+
- async subscribe(...args) {
31+
- const result = await subscribe(...args);
32+
- if ('next' in result) {
33+
- // is an async iterable, augment the next method to handle thrown errors
34+
- const originalNext = result.next;
35+
- result.next = async () => {
36+
- try {
37+
- return await originalNext();
38+
- } catch (err) {
39+
- // gracefully handle the error thrown from the next method
40+
- return { value: { errors: [err] } };
41+
- }
42+
- };
43+
- }
44+
- return result;
45+
- },
46+
},
47+
wsServer,
48+
);
49+
```

0 commit comments

Comments
 (0)
0