Skip to content

Commit 96da289

Browse files
committed
update documents
1 parent 1243c9e commit 96da289

File tree

1 file changed

+38
-115
lines changed

1 file changed

+38
-115
lines changed

website/src/pages/recipes.mdx

Lines changed: 38 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ if (supported) {
594594
</html>
595595
```
596596

597-
Client usage in Node
597+
## Client usage in Node
598598

599599
```ts
600600
const ws = require('ws'); // yarn add ws
@@ -694,13 +694,11 @@ const unlisten = client.onReconnected(() => {
694694
});
695695
```
696696

697-
## Server usage with [ws](https://github.com/websockets/ws)
697+
## Server usage with manual implementation of [ws](https://github.com/websockets/ws)
698698

699699
```ts
700-
// minimal version of `import { useServer } from 'graphql-ws/use/ws';`
700+
// minimal version of `useServer` from `graphql-ws/use/ws`
701701

702-
// import ws from 'ws'; yarn add ws@7
703-
// const WebSocketServer = ws.Server;
704702
import { CloseCode, makeServer } from 'graphql-ws';
705703
import { WebSocketServer } from 'ws'; // yarn add ws
706704

@@ -753,11 +751,9 @@ wsServer.on('connection', (socket, request) => {
753751
## Server usage with [ws](https://github.com/websockets/ws) and custom auth handling
754752

755753
```ts
756-
// check extended implementation at `{ useServer } from 'graphql-ws/use/ws'`
754+
// check extended implementation at `useServer` from `graphql-ws/use/ws`
757755

758756
import http from 'http';
759-
// import ws from 'ws'; yarn add ws@7
760-
// const WebSocketServer = ws.Server;
761757
import { CloseCode, makeServer } from 'graphql-ws';
762758
import { WebSocketServer } from 'ws'; // yarn add ws
763759

@@ -847,8 +843,6 @@ wsServer.on('connection', (socket, request) => {
847843
## Server usage with [ws](https://github.com/websockets/ws) and subprotocol pings and pongs
848844

849845
```ts
850-
// import ws from 'ws'; yarn add ws@7
851-
// const WebSocketServer = ws.Server;
852846
import {
853847
CloseCode,
854848
makeServer,
@@ -959,20 +953,20 @@ useServer(
959953
{
960954
execute: (args: any) => args.rootValue.execute(args),
961955
subscribe: (args: any) => args.rootValue.subscribe(args),
962-
onSubscribe: async (ctx, msg) => {
956+
onSubscribe: async (ctx, _id, payload) => {
963957
const { schema, execute, subscribe, contextFactory, parse, validate } =
964958
yoga.getEnveloped({
965959
...ctx,
966960
req: ctx.extra.request,
967961
socket: ctx.extra.socket,
968-
params: msg.payload,
962+
params: payload,
969963
});
970964

971965
const args = {
972966
schema,
973-
operationName: msg.payload.operationName,
974-
document: parse(msg.payload.query),
975-
variableValues: msg.payload.variables,
967+
operationName: payload.operationName,
968+
document: parse(payload.query),
969+
variableValues: payload.variables,
976970
contextValue: await contextFactory(),
977971
rootValue: {
978972
execute,
@@ -996,8 +990,6 @@ server.listen(4000, () => {
996990
## [ws](https://github.com/websockets/ws) server usage with [Express GraphQL](https://github.com/graphql/express-graphql)
997991

998992
```typescript
999-
// import ws from 'ws'; yarn add ws@7
1000-
// const WebSocketServer = ws.Server;
1001993
import express from 'express';
1002994
import { graphqlHTTP } from 'express-graphql';
1003995
import { useServer } from 'graphql-ws/use/ws';
@@ -1156,8 +1148,6 @@ fastify.listen(4000, (err) => {
11561148

11571149
```ts
11581150
import http from 'http';
1159-
// import ws from 'ws'; yarn add ws@7
1160-
// const WebSocketServer = ws.Server;
11611151
import { execute, subscribe } from 'graphql';
11621152
import { GRAPHQL_TRANSPORT_WS_PROTOCOL } from 'graphql-ws';
11631153
import { useServer } from 'graphql-ws/use/ws';
@@ -1215,8 +1205,6 @@ server.listen(4000);
12151205
## [ws](https://github.com/websockets/ws) server usage with console logging
12161206

12171207
```typescript
1218-
// import ws from 'ws'; yarn add ws@7
1219-
// const WebSocketServer = ws.Server;
12201208
import { useServer } from 'graphql-ws/use/ws';
12211209
import { WebSocketServer } from 'ws'; // yarn add ws
12221210

@@ -1233,17 +1221,17 @@ useServer(
12331221
onConnect: (ctx) => {
12341222
console.log('Connect', ctx);
12351223
},
1236-
onSubscribe: (ctx, msg) => {
1237-
console.log('Subscribe', { ctx, msg });
1224+
onSubscribe: (ctx, id, payload) => {
1225+
console.log('Subscribe', { ctx, id, payload });
12381226
},
1239-
onNext: (ctx, msg, args, result) => {
1240-
console.debug('Next', { ctx, msg, args, result });
1227+
onNext: (ctx, id, args, result) => {
1228+
console.debug('Next', { ctx, id, args, result });
12411229
},
1242-
onError: (ctx, msg, errors) => {
1243-
console.error('Error', { ctx, msg, errors });
1230+
onError: (ctx, id, errors) => {
1231+
console.error('Error', { ctx, id, errors });
12441232
},
1245-
onComplete: (ctx, msg) => {
1246-
console.log('Complete', { ctx, msg });
1233+
onComplete: (ctx, id) => {
1234+
console.log('Complete', { ctx, id });
12471235
},
12481236
},
12491237
wsServer,
@@ -1254,8 +1242,6 @@ useServer(
12541242

12551243
```typescript
12561244
import http from 'http';
1257-
// import ws from 'ws'; yarn add ws@7
1258-
// const WebSocketServer = ws.Server;
12591245
import url from 'url';
12601246
import { useServer } from 'graphql-ws/use/ws';
12611247
import { WebSocketServer } from 'ws'; // yarn add ws
@@ -1308,8 +1294,6 @@ server.listen(4000);
13081294
## [ws](https://github.com/websockets/ws) server usage with custom context value
13091295

13101296
```typescript
1311-
// import ws from 'ws'; yarn add ws@7
1312-
// const WebSocketServer = ws.Server;
13131297
import { useServer } from 'graphql-ws/use/ws';
13141298
import { WebSocketServer } from 'ws'; // yarn add ws
13151299

@@ -1322,8 +1306,8 @@ const wsServer = new WebSocketServer({
13221306

13231307
useServer(
13241308
{
1325-
context: (ctx, msg, args) => {
1326-
return getDynamicContext(ctx, msg, args);
1309+
context: (ctx, id, args) => {
1310+
return getDynamicContext(ctx, id, args);
13271311
}, // or static context by supplying the value direcly
13281312
schema,
13291313
},
@@ -1334,8 +1318,6 @@ useServer(
13341318
## [ws](https://github.com/websockets/ws) server usage with dynamic schema
13351319

13361320
```typescript
1337-
// import ws from 'ws'; yarn add ws@7
1338-
// const WebSocketServer = ws.Server;
13391321
import { useServer } from 'graphql-ws/use/ws';
13401322
import { WebSocketServer } from 'ws'; // yarn add ws
13411323

@@ -1348,14 +1330,14 @@ const wsServer = new WebSocketServer({
13481330

13491331
useServer(
13501332
{
1351-
schema: async (ctx, msg, executionArgsWithoutSchema) => {
1333+
schema: async (ctx, id, executionArgsWithoutSchema) => {
13521334
// will be called on every subscribe request
13531335
// allowing you to dynamically supply the schema
13541336
// using the depending on the provided arguments.
13551337
// throwing an error here closes the socket with
13561338
// the `Error` message in the close event reason
13571339
const isAdmin = await checkIsAdmin(ctx.request);
1358-
if (isAdmin) return getDebugSchema(ctx, msg, executionArgsWithoutSchema);
1340+
if (isAdmin) return getDebugSchema(ctx, id, executionArgsWithoutSchema);
13591341
return schema;
13601342
},
13611343
},
@@ -1367,8 +1349,6 @@ useServer(
13671349

13681350
```typescript
13691351
import { validate } from 'graphql';
1370-
// import ws from 'ws'; yarn add ws@7
1371-
// const WebSocketServer = ws.Server;
13721352
import { useServer } from 'graphql-ws/use/ws';
13731353
import { WebSocketServer } from 'ws'; // yarn add ws
13741354

@@ -1392,8 +1372,6 @@ useServer(
13921372

13931373
```typescript
13941374
import { parse, validate } from 'graphql';
1395-
// import ws from 'ws'; yarn add ws@7
1396-
// const WebSocketServer = ws.Server;
13971375
import { useServer } from 'graphql-ws/use/ws';
13981376
import { WebSocketServer } from 'ws'; // yarn add ws
13991377

@@ -1406,12 +1384,12 @@ const wsServer = new WebSocketServer({
14061384

14071385
useServer(
14081386
{
1409-
onSubscribe: (ctx, msg) => {
1387+
onSubscribe: (ctx, _id, payload) => {
14101388
const args = {
14111389
schema,
1412-
operationName: msg.payload.operationName,
1413-
document: parse(msg.payload.query),
1414-
variableValues: msg.payload.variables,
1390+
operationName: payload.operationName,
1391+
document: parse(payload.query),
1392+
variableValues: payload.variables,
14151393
};
14161394

14171395
// dont forget to validate when returning custom execution args!
@@ -1427,58 +1405,10 @@ useServer(
14271405
);
14281406
```
14291407

1430-
## [ws](https://github.com/websockets/ws) server usage with custom subscribe method that gracefully handles thrown errors
1431-
1432-
`graphql-js` does not catch errors thrown from async iterables ([see issue](https://github.com/graphql/graphql-js/issues/4001)). This will bubble the error to the WebSocket server and abruptly exit the process because no error should be uncaught.
1433-
1434-
Note that `graphql-ws` will NOT offer built-in handling of internal errors because there's no one-glove-fits-all. Errors are important and should be handled with care, exactly to the needs of the user - not the library author.
1435-
1436-
Therefore, you may instead implement your own `subscribe` function that gracefully handles thrown errors.
1437-
1438-
```typescript
1439-
import { subscribe } from 'graphql';
1440-
// import ws from 'ws'; yarn add ws@7
1441-
// const WebSocketServer = ws.Server;
1442-
import { useServer } from 'graphql-ws/use/ws';
1443-
import { WebSocketServer } from 'ws'; // yarn add ws
1444-
1445-
import { myValidationRules, schema } from './my-graphql';
1446-
1447-
const wsServer = new WebSocketServer({
1448-
port: 4000,
1449-
path: '/graphql',
1450-
});
1451-
1452-
useServer(
1453-
{
1454-
schema,
1455-
async subscribe(...args) {
1456-
const result = await subscribe(...args);
1457-
if ('next' in result) {
1458-
// is an async iterable, augment the next method to handle thrown errors
1459-
const originalNext = result.next;
1460-
result.next = async () => {
1461-
try {
1462-
return await originalNext();
1463-
} catch (err) {
1464-
// gracefully handle the error thrown from the next method
1465-
return { value: { errors: [err] } };
1466-
}
1467-
};
1468-
}
1469-
return result;
1470-
},
1471-
},
1472-
wsServer,
1473-
);
1474-
```
1475-
14761408
## [ws](https://github.com/websockets/ws) server usage accepting only subscription operations
14771409

14781410
```typescript
14791411
import { getOperationAST, GraphQLError, parse, validate } from 'graphql';
1480-
// import ws from 'ws'; yarn add ws@7
1481-
// const WebSocketServer = ws.Server;
14821412
import { useServer } from 'graphql-ws/use/ws';
14831413
import { WebSocketServer } from 'ws'; // yarn add ws
14841414

@@ -1491,13 +1421,13 @@ const wsServer = new WebSocketServer({
14911421

14921422
useServer(
14931423
{
1494-
onSubscribe: (_ctx, msg) => {
1424+
onSubscribe: (_ctx, _id, payload) => {
14951425
// construct the execution arguments
14961426
const args = {
14971427
schema,
1498-
operationName: msg.payload.operationName,
1499-
document: parse(msg.payload.query),
1500-
variableValues: msg.payload.variables,
1428+
operationName: payload.operationName,
1429+
document: parse(payload.query),
1430+
variableValues: payload.variables,
15011431
};
15021432

15031433
const operationAST = getOperationAST(args.document, args.operationName);
@@ -1536,8 +1466,6 @@ useServer(
15361466
// 🛸 server
15371467

15381468
import { ExecutionArgs, parse } from 'graphql';
1539-
// import ws from 'ws'; yarn add ws@7
1540-
// const WebSocketServer = ws.Server;
15411469
import { useServer } from 'graphql-ws/use/ws';
15421470
import { WebSocketServer } from 'ws'; // yarn add ws
15431471

@@ -1562,13 +1490,12 @@ const wsServer = new WebSocketServer({
15621490

15631491
useServer(
15641492
{
1565-
onSubscribe: (_ctx, msg) => {
1566-
const persistedQuery =
1567-
queriesStore[msg.payload.extensions?.persistedQuery];
1493+
onSubscribe: (_ctx, _id, payload) => {
1494+
const persistedQuery = queriesStore[payload.extensions?.persistedQuery];
15681495
if (persistedQuery) {
15691496
return {
15701497
...persistedQuery,
1571-
variableValues: msg.payload.variables, // use the variables from the client
1498+
variableValues: payload.variables, // use the variables from the client
15721499
};
15731500
}
15741501

@@ -1622,8 +1549,6 @@ const client = createClient({
16221549
// 🛸 server
16231550

16241551
import { CloseCode } from 'graphql-ws';
1625-
// import ws from 'ws'; yarn add ws@7
1626-
// const WebSocketServer = ws.Server;
16271552
import { useServer } from 'graphql-ws/use/ws';
16281553
import { WebSocketServer } from 'ws'; // yarn add ws
16291554

@@ -1720,8 +1645,6 @@ const client = createClient({
17201645
```ts
17211646
// 🛸 server
17221647

1723-
// import ws from 'ws'; yarn add ws@7
1724-
// const WebSocketServer = ws.Server;
17251648
import { MessageType, stringifyMessage } from 'graphql-ws';
17261649
import { useServer } from 'graphql-ws/use/ws';
17271650
import { WebSocketServer } from 'ws';
@@ -1740,11 +1663,11 @@ useServer<undefined, { ackWaiters: Record<string, () => void> }>(
17401663
// intentionally in context extra to avoid memory leaks when clients disconnect
17411664
ctx.extra.ackWaiters = {};
17421665
},
1743-
onSubscribe: (ctx, msg) => {
1744-
const ackId = msg.payload.extensions?.ackId;
1666+
onSubscribe: (ctx, id, payload) => {
1667+
const ackId = payload.extensions?.ackId;
17451668
if (typeof ackId === 'string') {
17461669
// if acknowledgment ID is present, create an acknowledger that will be executed when operation succeeds
1747-
ctx.extra.ackWaiters![msg.id] = () => {
1670+
ctx.extra.ackWaiters![id] = () => {
17481671
ctx.extra.socket.send(
17491672
stringifyMessage({
17501673
type: MessageType.Ping,
@@ -1756,10 +1679,10 @@ useServer<undefined, { ackWaiters: Record<string, () => void> }>(
17561679
};
17571680
}
17581681
},
1759-
onOperation: (ctx, msg) => {
1682+
onOperation: (ctx, id) => {
17601683
// acknowledge operation success and remove waiter
1761-
ctx.extra.ackWaiters![msg.id]?.();
1762-
delete ctx.extra.ackWaiters![msg.id];
1684+
ctx.extra.ackWaiters![id]?.();
1685+
delete ctx.extra.ackWaiters![id];
17631686
},
17641687
},
17651688
wsServer,

0 commit comments

Comments
 (0)