next-ws 0.2.4 → 0.2.5-next.28f252e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -11
- package/package.json +15 -4
- package/server/index.d.ts +1 -0
- package/server/setup.js +3 -3
- package/server/utilities/next.js +34 -11
- package/server/utilities/ws.d.ts +7 -0
- package/server/utilities/ws.js +13 -0
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ This module is inspired by the now outdated `next-plugin-websocket`, if you are
|
|
|
45
45
|
In order to setup a WebSocket server, Next WS needs to patch your local Next.js installation. Next WS provides a CLI command to do this for you, it will automatically detect your Next.js version and patch it accordingly, however a minimum version of Next.js 13.1.1 is required.
|
|
46
46
|
|
|
47
47
|
```sh
|
|
48
|
-
npx next-ws-cli patch
|
|
48
|
+
npx next-ws-cli@latest patch
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
> If at any point your local Next.js installation is changed or updated you will need to re-run the patch command.
|
|
@@ -56,6 +56,16 @@ Once the patch is complete, you will need to install the Next WS package into yo
|
|
|
56
56
|
npm install next-ws
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
### 🚓 Verify Patch
|
|
60
|
+
|
|
61
|
+
It is recommended to add the following code to the top level of your `next.config.js`.
|
|
62
|
+
|
|
63
|
+
This will verify that Next WS has been patched correctly, and throw an error if it has not. Preventing you from accidentally deploying a broken setup.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
require('next-ws/server').verifyPatch();
|
|
67
|
+
```
|
|
68
|
+
|
|
59
69
|
---
|
|
60
70
|
|
|
61
71
|
## 🚀 Usage
|
|
@@ -76,16 +86,6 @@ export function SOCKET(
|
|
|
76
86
|
|
|
77
87
|
With this straightforward setup, you can fully leverage the capabilities of Next WS and efficiently handle WebSocket connections within your Next.js application.
|
|
78
88
|
|
|
79
|
-
### 🚓 Verify Patch
|
|
80
|
-
|
|
81
|
-
It is recommended to add the following code to the top level of your `next.config.js`.
|
|
82
|
-
|
|
83
|
-
This will verify that Next WS has been patched correctly, and throw an error if it has not. Preventing you from accidentally deploying a broken setup.
|
|
84
|
-
|
|
85
|
-
```ts
|
|
86
|
-
require('next-ws/server').verifyPatch();
|
|
87
|
-
```
|
|
88
|
-
|
|
89
89
|
---
|
|
90
90
|
|
|
91
91
|
## 🌀 Example
|
|
@@ -135,6 +135,8 @@ export default function Layout() {
|
|
|
135
135
|
}
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
+
To make it easier to connect to your new WebSocker server, Next WS also provides some client-side utilities. These are completely optional, you can use your own implementation if you wish.
|
|
139
|
+
|
|
138
140
|
The following is the props interface for the `WebSocketProvider` component, containing all the available options.
|
|
139
141
|
|
|
140
142
|
```ts
|
package/package.json
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-ws",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5-next.28f252e",
|
|
4
4
|
"description": "Add support for WebSockets in Next.js 13 app directory",
|
|
5
|
-
"keywords": [
|
|
5
|
+
"keywords": [
|
|
6
|
+
"next",
|
|
7
|
+
"websocket",
|
|
8
|
+
"ws",
|
|
9
|
+
"server",
|
|
10
|
+
"client"
|
|
11
|
+
],
|
|
6
12
|
"license": "MIT",
|
|
7
13
|
"homepage": "https://github.com/apteryxxyz/next-ws#readme",
|
|
8
14
|
"repository": {
|
|
@@ -13,7 +19,12 @@
|
|
|
13
19
|
"bugs": {
|
|
14
20
|
"url": "https://github.com/apteryxxyz/next-ws/issues"
|
|
15
21
|
},
|
|
16
|
-
"files": [
|
|
22
|
+
"files": [
|
|
23
|
+
"index.js",
|
|
24
|
+
"index.d.ts",
|
|
25
|
+
"client",
|
|
26
|
+
"server"
|
|
27
|
+
],
|
|
17
28
|
"main": "./index.js",
|
|
18
29
|
"types": "./index.d.ts",
|
|
19
30
|
"scripts": {
|
|
@@ -43,4 +54,4 @@
|
|
|
43
54
|
"rimraf": "^5.0.1",
|
|
44
55
|
"typescript": "<5.1.0"
|
|
45
56
|
}
|
|
46
|
-
}
|
|
57
|
+
}
|
package/server/index.d.ts
CHANGED
package/server/setup.js
CHANGED
|
@@ -3,14 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.hookNextNodeServer = exports.setupWebSocketServer = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const Log = tslib_1.__importStar(require("next/dist/build/output/log"));
|
|
6
|
-
const ws_1 = require("ws");
|
|
7
6
|
const next_1 = require("./utilities/next");
|
|
7
|
+
const ws_1 = require("./utilities/ws");
|
|
8
8
|
function setupWebSocketServer(nextServer) {
|
|
9
9
|
const httpServer = (0, next_1.getHttpServer)(nextServer);
|
|
10
|
-
const wsServer =
|
|
10
|
+
const wsServer = (0, ws_1.getWsServer)();
|
|
11
11
|
Log.ready('[next-ws] websocket server started successfully');
|
|
12
12
|
httpServer.on('upgrade', async (request, socket, head) => {
|
|
13
|
-
const url = new URL(request.url ?? '', '
|
|
13
|
+
const url = new URL(request.url ?? '', 'ws://next');
|
|
14
14
|
const pathname = url.pathname;
|
|
15
15
|
if (pathname.startsWith('/_next'))
|
|
16
16
|
return;
|
package/server/utilities/next.js
CHANGED
|
@@ -13,7 +13,7 @@ const next_server_1 = tslib_1.__importDefault(require("next/dist/server/next-ser
|
|
|
13
13
|
function getHttpServer(nextServer) {
|
|
14
14
|
if (!nextServer || !(nextServer instanceof next_server_1.default))
|
|
15
15
|
throw new Error('Next WS is missing access to the NextNodeServer');
|
|
16
|
-
// @ts-expect-error serverOptions is protected
|
|
16
|
+
// @ts-expect-error - serverOptions is protected
|
|
17
17
|
const httpServer = nextServer.serverOptions?.httpServer;
|
|
18
18
|
if (!httpServer || !(httpServer instanceof node_http_1.Server))
|
|
19
19
|
throw new Error('Next WS is missing access to the http.Server');
|
|
@@ -29,18 +29,41 @@ exports.getHttpServer = getHttpServer;
|
|
|
29
29
|
async function resolvePathname(nextServer, pathname) {
|
|
30
30
|
if (pathname.startsWith('/_next'))
|
|
31
31
|
return null;
|
|
32
|
+
const pathParts = pathname.split('/');
|
|
32
33
|
const appRoutes = {
|
|
33
|
-
// @ts-expect-error appPathRoutes is protected
|
|
34
|
+
// @ts-expect-error - appPathRoutes is protected
|
|
34
35
|
...nextServer.appPathRoutes,
|
|
35
|
-
// @ts-expect-error getAppPathRoutes is protected
|
|
36
|
+
// @ts-expect-error - getAppPathRoutes is protected
|
|
36
37
|
...nextServer.getAppPathRoutes(),
|
|
37
38
|
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
for (const [key, [path]] of Object.entries(appRoutes)) {
|
|
40
|
+
const hasDynamic = key.includes('[') && key.includes(']');
|
|
41
|
+
if (hasDynamic) {
|
|
42
|
+
const keyParts = key.split('/');
|
|
43
|
+
if (keyParts.length !== pathParts.length)
|
|
44
|
+
continue;
|
|
45
|
+
for (let i = 0; i < keyParts.length; i++) {
|
|
46
|
+
const keyPart = keyParts[i];
|
|
47
|
+
const pathPart = pathParts[i];
|
|
48
|
+
const isDynamic = keyPart.includes('[') && keyPart.includes(']');
|
|
49
|
+
if (isDynamic)
|
|
50
|
+
keyParts[i] = pathPart;
|
|
51
|
+
if (keyParts[i] !== pathParts[i])
|
|
52
|
+
break;
|
|
53
|
+
if (i === keyParts.length - 1) {
|
|
54
|
+
if (!path?.endsWith('/route'))
|
|
55
|
+
return null;
|
|
56
|
+
return path;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
if (key !== pathname)
|
|
62
|
+
continue;
|
|
63
|
+
if (!path?.endsWith('/route'))
|
|
64
|
+
return null;
|
|
65
|
+
return path;
|
|
66
|
+
}
|
|
44
67
|
}
|
|
45
68
|
return null;
|
|
46
69
|
}
|
|
@@ -52,12 +75,12 @@ exports.resolvePathname = resolvePathname;
|
|
|
52
75
|
* @returns The page module.
|
|
53
76
|
*/
|
|
54
77
|
async function getPageModule(nextServer, filename) {
|
|
55
|
-
// @ts-expect-error
|
|
78
|
+
// @ts-expect-error - hotReloader is private
|
|
56
79
|
await nextServer.hotReloader?.ensurePage({
|
|
57
80
|
page: filename,
|
|
58
81
|
clientOnly: false,
|
|
59
82
|
});
|
|
60
|
-
// @ts-expect-error getPagePath is protected
|
|
83
|
+
// @ts-expect-error - getPagePath is protected
|
|
61
84
|
const builtPagePath = nextServer.getPagePath(filename);
|
|
62
85
|
return require(builtPagePath);
|
|
63
86
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="ws" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/**
|
|
4
|
+
* Get the WebSocketServer instance.
|
|
5
|
+
* @returns The WebSocketServer instance.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getWsServer(): import("ws").Server<typeof import("ws"), typeof import("http").IncomingMessage>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getWsServer = void 0;
|
|
4
|
+
const ws_1 = require("ws");
|
|
5
|
+
/**
|
|
6
|
+
* Get the WebSocketServer instance.
|
|
7
|
+
* @returns The WebSocketServer instance.
|
|
8
|
+
*/
|
|
9
|
+
// prettier-ignore
|
|
10
|
+
function getWsServer() {
|
|
11
|
+
return new ws_1.WebSocketServer({ noServer: true });
|
|
12
|
+
}
|
|
13
|
+
exports.getWsServer = getWsServer;
|