Skip to content

Commit

Permalink
feat(server): Use @fastify/websocket (enisdenjo#382)
Browse files Browse the repository at this point in the history
  • Loading branch information
enisdenjo committed Aug 9, 2022
1 parent 09151cf commit dd755b0
Show file tree
Hide file tree
Showing 18 changed files with 604 additions and 349 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/benchmark.yml
Expand Up @@ -76,8 +76,8 @@ jobs:
run: |
NODE_ENV=production node benchmark/servers/ws8.mjs &
SERVER=ws8 ./k6 run benchmark/k6.mjs
fastify-websocket_ws8:
name: fastify-websocket_ws8
fastify-websocket:
name: '@fastify/websocket'
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand All @@ -96,8 +96,8 @@ jobs:
run: yarn run build:esm
- name: Run
run: |
NODE_ENV=production node benchmark/servers/fastify-websocket_ws8.mjs &
SERVER=fastify-websocket_ws8 ./k6 run benchmark/k6.mjs
NODE_ENV=production node benchmark/servers/fastify-websocket.mjs &
SERVER="@fastify/websocket" ./k6 run benchmark/k6.mjs
legacy_ws7:
name: legacy_ws7
runs-on: ubuntu-latest
Expand Down
35 changes: 31 additions & 4 deletions README.md
Expand Up @@ -99,18 +99,20 @@ uWS
});
```

##### With [fastify-websocket](https://github.com/fastify/fastify-websocket)
##### With [@fastify/websocket](https://github.com/fastify/fastify-websocket)

```ts
import Fastify from 'fastify'; // yarn add fastify
import fastifyWebsocket from 'fastify-websocket'; // yarn add fastify-websocket
import { makeHandler } from 'graphql-ws/lib/use/fastify-websocket';
import fastifyWebsocket from '@fastify/websocket'; // yarn add @fastify/websocket
import { makeHandler } from 'graphql-ws/lib/use/@fastify/websocket';
import { schema } from './previous-step';

const fastify = Fastify();
fastify.register(fastifyWebsocket);

fastify.get('/graphql', { websocket: true }, makeHandler({ schema }));
fastify.register(async (fastify) => {
fastify.get('/graphql', { websocket: true }, makeHandler({ schema }));
});

fastify.listen(4000, (err) => {
if (err) {
Expand Down Expand Up @@ -1322,6 +1324,31 @@ httpServer.listen(4000);

</details>

<details id="deprecated-fastify-websocket">
<summary><a href="#deprecated-fastify-websocket">🔗</a> <a href="https://github.com/websockets/ws">ws</a> server usage with <a href="https://www.npmjs.com/package/fastify-websocket">deprecated fastify-websocket</a></summary>

```typescript
import Fastify from 'fastify'; // yarn add fastify@^3
import fastifyWebsocket from 'fastify-websocket'; // yarn add fastify-websocket@4.2.2
import { makeHandler } from 'graphql-ws/lib/use/fastify-websocket';
import { schema } from './previous-step';

const fastify = Fastify();
fastify.register(fastifyWebsocket);

fastify.get('/graphql', { websocket: true }, makeHandler({ schema }));

fastify.listen(4000, (err) => {
if (err) {
fastify.log.error(err);
return process.exit(1);
}
console.log('Listening to port 4000');
});
```

</details>

<details id="ws-backwards-compat">
<summary><a href="#ws-backwards-compat">🔗</a> <a href="https://github.com/websockets/ws">ws</a> server usage with <a href="https://github.com/apollographql/subscriptions-transport-ws">subscriptions-transport-ws</a> backwards compatibility</summary>

Expand Down
21 changes: 21 additions & 0 deletions benchmark/servers/fastify-websocket.mjs
@@ -0,0 +1,21 @@
import Fastify from 'fastify';
import fastifyWebsocket from '@fastify/websocket';
import { ports } from './ports.mjs';
import { makeHandler } from '../../lib/use/@fastify/websocket.mjs';
import { schema } from './schema.mjs';

const fastify = Fastify();
fastify.register(fastifyWebsocket);
fastify.register(async (fastify) => {
fastify.get('/graphql', { websocket: true }, makeHandler({ schema }));
});

fastify.listen({ port: ports['@fastify/websocket'] }, (err) => {
if (err) {
fastify.log.error(err);
return process.exit(1);
}
console.log(
`@fastify/websocket - listening on port ${ports['@fastify/websocket']}...`,
);
});
20 changes: 0 additions & 20 deletions benchmark/servers/fastify-websocket_ws8.mjs

This file was deleted.

2 changes: 1 addition & 1 deletion benchmark/servers/index.mjs
@@ -1,5 +1,5 @@
import './uWebSockets.mjs';
import './ws8.mjs';
import './ws7.mjs';
import './fastify-websocket_ws8.mjs';
import './fastify-websocket.mjs';
import './legacy_ws7.mjs';
2 changes: 1 addition & 1 deletion benchmark/servers/ports.mjs
Expand Up @@ -3,5 +3,5 @@ export const ports = {
ws7: 6543,
uWebSockets: 6541,
legacy_ws7: 6542,
'fastify-websocket_ws8': 6544,
'@fastify/websocket': 6544,
};
1 change: 1 addition & 0 deletions docs/README.md
Expand Up @@ -9,6 +9,7 @@ graphql-ws
- [client](modules/client.md)
- [common](modules/common.md)
- [server](modules/server.md)
- [use/@fastify/websocket](modules/use__fastify_websocket.md)
- [use/fastify-websocket](modules/use_fastify_websocket.md)
- [use/uWebSockets](modules/use_uWebSockets.md)
- [use/ws](modules/use_ws.md)
32 changes: 32 additions & 0 deletions docs/interfaces/use__fastify_websocket.Extra.md
@@ -0,0 +1,32 @@
[graphql-ws](../README.md) / [use/@fastify/websocket](../modules/use__fastify_websocket.md) / Extra

# Interface: Extra

[use/@fastify/websocket](../modules/use__fastify_websocket.md).Extra

The extra that will be put in the `Context`.

## Table of contents

### Properties

- [connection](use__fastify_websocket.Extra.md#connection)
- [request](use__fastify_websocket.Extra.md#request)

## Properties

### connection

`Readonly` **connection**: `SocketStream`

The underlying socket connection between the server and the client.
The WebSocket socket is located under the `socket` parameter.

___

### request

`Readonly` **request**: `FastifyRequest`<`RouteGenericInterface`, `Server`, `IncomingMessage`, `FastifySchema`, `FastifyTypeProviderDefault`, `unknown`, `FastifyBaseLogger`, `ResolveFastifyRequestType`<`FastifyTypeProviderDefault`, `FastifySchema`, `RouteGenericInterface`\>\>

The initial HTTP upgrade request before the actual
socket and connection is established.
6 changes: 5 additions & 1 deletion docs/interfaces/use_fastify_websocket.Extra.md
Expand Up @@ -6,6 +6,10 @@

The extra that will be put in the `Context`.

**`Deprecated`**

Use `@fastify/websocket` instead.

## Table of contents

### Properties
Expand All @@ -26,7 +30,7 @@ ___

### request

`Readonly` **request**: `FastifyRequest`<`RouteGenericInterface`, `Server`, `IncomingMessage`, `unknown`, `FastifyLoggerInstance`\>
`Readonly` **request**: `FastifyRequest`<`RouteGenericInterface`, `Server`, `IncomingMessage`, `FastifySchema`, `FastifyTypeProviderDefault`, `unknown`, `FastifyBaseLogger`, `ResolveFastifyRequestType`<`FastifyTypeProviderDefault`, `FastifySchema`, `RouteGenericInterface`\>\>

The initial HTTP upgrade request before the actual
socket and connection is established.
40 changes: 40 additions & 0 deletions docs/modules/use__fastify_websocket.md
@@ -0,0 +1,40 @@
[graphql-ws](../README.md) / use/@fastify/websocket

# Module: use/@fastify/websocket

## Table of contents

### Interfaces

- [Extra](../interfaces/use__fastify_websocket.Extra.md)

### Functions

- [makeHandler](use__fastify_websocket.md#makehandler)

## Server/@fastify/websocket

### makeHandler

**makeHandler**<`P`, `E`\>(`options`, `keepAlive?`): `fastifyWebsocket.WebsocketHandler`

Make a handler to use on a [@fastify/websocket](https://github.com/fastify/fastify-websocket) route.
This is a basic starter, feel free to copy the code over and adjust it to your needs

#### Type parameters

| Name | Type |
| :------ | :------ |
| `P` | extends `undefined` \| `Record`<`string`, `unknown`\> = `undefined` \| `Record`<`string`, `unknown`\> |
| `E` | extends `Record`<`PropertyKey`, `unknown`\> = `Record`<`PropertyKey`, `never`\> |

#### Parameters

| Name | Type | Default value |
| :------ | :------ | :------ |
| `options` | [`ServerOptions`](../interfaces/server.ServerOptions.md)<`P`, [`Extra`](../interfaces/use__fastify_websocket.Extra.md) & `Partial`<`E`\>\> | `undefined` |
| `keepAlive` | `number` | `12_000` |

#### Returns

`fastifyWebsocket.WebsocketHandler`
4 changes: 4 additions & 0 deletions docs/modules/use_fastify_websocket.md
Expand Up @@ -21,6 +21,10 @@
Make a handler to use on a [fastify-websocket](https://github.com/fastify/fastify-websocket) route.
This is a basic starter, feel free to copy the code over and adjust it to your needs

**`Deprecated`**

Use `@fastify/websocket` instead.

#### Type parameters

| Name | Type |
Expand Down
8 changes: 7 additions & 1 deletion package.json
Expand Up @@ -48,6 +48,11 @@
"import": "./lib/use/uWebSockets.mjs",
"types": "./lib/use/uWebSockets.d.ts"
},
"./lib/use/@fastify/websocket": {
"require": "./lib/use/@fastify/websocket.js",
"import": "./lib/use/@fastify/websocket.mjs",
"types": "./lib/use/@fastify/websocket.d.ts"
},
"./lib/use/fastify-websocket": {
"require": "./lib/use/fastify-websocket.js",
"import": "./lib/use/fastify-websocket.mjs",
Expand Down Expand Up @@ -93,6 +98,7 @@
"@babel/plugin-proposal-optional-chaining": "^7.18.6",
"@babel/preset-env": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@fastify/websocket": "^7.0.0",
"@rollup/plugin-typescript": "^8.3.3",
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/git": "^10.0.1",
Expand All @@ -104,7 +110,7 @@
"eslint": "^8.18.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"fastify": "^3.29.0",
"fastify": "^4.4.0",
"fastify-websocket": "4.2.2",
"glob": "^8.0.3",
"graphql": "^16.5.0",
Expand Down
8 changes: 4 additions & 4 deletions src/__tests__/__snapshots__/use.ts.snap
@@ -1,12 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`fastify-websocket should limit the server emitted error message size 1`] = `"Internal error emitted on the WebSocket server. Please check your implementation."`;
exports[`@fastify/websocket should limit the server emitted error message size 1`] = `"Internal error emitted on the WebSocket server. Please check your implementation."`;

exports[`fastify-websocket should limit the socket emitted error message size 1`] = `"Internal error emitted on a WebSocket socket. Please check your implementation."`;
exports[`@fastify/websocket should limit the socket emitted error message size 1`] = `"Internal error emitted on a WebSocket socket. Please check your implementation."`;

exports[`fastify-websocket should report server emitted errors to clients by closing the connection 1`] = `"Internal error emitted on the WebSocket server. Please check your implementation."`;
exports[`@fastify/websocket should report server emitted errors to clients by closing the connection 1`] = `"Internal error emitted on the WebSocket server. Please check your implementation."`;

exports[`fastify-websocket should report socket emitted errors to clients by closing the connection 1`] = `"Internal error emitted on a WebSocket socket. Please check your implementation."`;
exports[`@fastify/websocket should report socket emitted errors to clients by closing the connection 1`] = `"Internal error emitted on a WebSocket socket. Please check your implementation."`;

exports[`ws should limit the server emitted error message size 1`] = `"Internal error emitted on the WebSocket server. Please check your implementation."`;

Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/use.ts
Expand Up @@ -147,15 +147,15 @@ for (const { tServer, skipUWS, startTServer } of tServers) {
expect((ctx.extra as WSExtra).request).toBeInstanceOf(
http.IncomingMessage,
);
} else if (tServer === 'fastify-websocket') {
} else if (tServer === '@fastify/websocket') {
expect((ctx.extra as FastifyExtra).connection).toBeInstanceOf(
stream.Duplex,
);
expect(
(ctx.extra as FastifyExtra).connection.socket,
).toBeInstanceOf(ws);
expect((ctx.extra as FastifyExtra).request.constructor.name).toBe(
'Request',
'_Request',
);
} else {
fail('Missing test case for ' + tServer);
Expand Down

0 comments on commit dd755b0

Please sign in to comment.