next-ws 2.0.13 → 2.1.0
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 -14
- package/dist/cli.cjs +946 -19
- package/dist/client/index.cjs +4 -5
- package/dist/server/index.cjs +184 -126
- package/dist/server/index.d.ts +43 -21
- package/package.json +25 -20
- package/dist/chunk-3RG5ZIWI.js +0 -10
- package/dist/client/index.d.cts +0 -27
- package/dist/client/index.js +0 -38
- package/dist/server/index.d.cts +0 -32
- package/dist/server/index.js +0 -186
package/dist/server/index.js
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
__require
|
|
3
|
-
} from "../chunk-3RG5ZIWI.js";
|
|
4
|
-
|
|
5
|
-
// src/server/setup.ts
|
|
6
|
-
import * as logger3 from "next/dist/build/output/log.js";
|
|
7
|
-
import { WebSocketServer } from "ws";
|
|
8
|
-
|
|
9
|
-
// src/server/helpers/persistent.ts
|
|
10
|
-
import * as logger from "next/dist/build/output/log.js";
|
|
11
|
-
function getEnvironmentMeta() {
|
|
12
|
-
const isCustomServer = !process.title.startsWith("next-");
|
|
13
|
-
const isMainProcess = process.env.NEXT_WS_MAIN_PROCESS === "1";
|
|
14
|
-
const isDevelopment = process.env.NODE_ENV === "development";
|
|
15
|
-
return { isCustomServer, isMainProcess, isDevelopment };
|
|
16
|
-
}
|
|
17
|
-
function mainProcessOnly(fnName) {
|
|
18
|
-
if (process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK === "1") return;
|
|
19
|
-
const meta = getEnvironmentMeta();
|
|
20
|
-
if (!meta.isMainProcess) {
|
|
21
|
-
throw new Error(
|
|
22
|
-
`[next-ws] Attempt to invoke '${fnName}' outside the main process.
|
|
23
|
-
You may be attempting to interact with the WebSocket server outside of a SOCKET handler. This will fail in production, as Next.js employs a worker process for routing, which do not have access to the WebSocket server on the main process.
|
|
24
|
-
You can resolve this by using a custom server.`
|
|
25
|
-
);
|
|
26
|
-
} else if (!meta.isCustomServer) {
|
|
27
|
-
logger.warnOnce(
|
|
28
|
-
`[next-ws] Caution: The function '${fnName}' was invoked without a custom server.
|
|
29
|
-
This could lead to unintended behaviour, especially if you're attempting to interact with the WebSocket server outside of a SOCKET handler.
|
|
30
|
-
Please note, while such configurations might function during development, they will fail in production. This is because Next.js employs a worker process for routing in production, which do not have access to the WebSocket server on the main process.
|
|
31
|
-
You can resolve this by using a custom server.`
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
var NextWsHttpServer = Symbol.for("NextWs_HttpServer");
|
|
36
|
-
function setHttpServer(server) {
|
|
37
|
-
Reflect.set(globalThis, NextWsHttpServer, server);
|
|
38
|
-
}
|
|
39
|
-
function getHttpServer() {
|
|
40
|
-
mainProcessOnly("getHttpServer");
|
|
41
|
-
return Reflect.get(globalThis, NextWsHttpServer);
|
|
42
|
-
}
|
|
43
|
-
function useHttpServer(server) {
|
|
44
|
-
const existing = getHttpServer();
|
|
45
|
-
if (existing) return existing;
|
|
46
|
-
if (server) setHttpServer(server);
|
|
47
|
-
return server;
|
|
48
|
-
}
|
|
49
|
-
var NextWsWebSocketServer = Symbol.for("NextWs_WebSocketServer");
|
|
50
|
-
function setWebSocketServer(wsServer) {
|
|
51
|
-
Reflect.set(globalThis, NextWsWebSocketServer, wsServer);
|
|
52
|
-
}
|
|
53
|
-
function getWebSocketServer() {
|
|
54
|
-
mainProcessOnly("getWebSocketServer");
|
|
55
|
-
return Reflect.get(globalThis, NextWsWebSocketServer);
|
|
56
|
-
}
|
|
57
|
-
function useWebSocketServer(wsServer) {
|
|
58
|
-
const existing = getWebSocketServer();
|
|
59
|
-
if (existing) return existing;
|
|
60
|
-
if (wsServer) setWebSocketServer(wsServer);
|
|
61
|
-
return wsServer;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// src/server/helpers/route.ts
|
|
65
|
-
import { pathToFileURL } from "node:url";
|
|
66
|
-
import * as logger2 from "next/dist/build/output/log.js";
|
|
67
|
-
function createRouteRegex(routePattern) {
|
|
68
|
-
const escapedPattern = routePattern.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
69
|
-
const paramRegex = escapedPattern.replace(/\\\[([a-zA-Z0-9_]+)\\\]/g, "(?<$1>[^/]+)").replace(/\\\[(?:\\\.){3}([a-zA-Z0-9_]+)\\\]/g, "(?<rest_$1>.+)");
|
|
70
|
-
return new RegExp(`^${paramRegex}$`);
|
|
71
|
-
}
|
|
72
|
-
function getRouteParams(routePattern, routePath) {
|
|
73
|
-
const routeRegex = createRouteRegex(routePattern);
|
|
74
|
-
const match = routePath.replace(/\/+$/, "").match(routeRegex);
|
|
75
|
-
if (!match) return null;
|
|
76
|
-
if (!match.groups) return {};
|
|
77
|
-
const params = {};
|
|
78
|
-
for (let [k, v] of Object.entries(match.groups)) {
|
|
79
|
-
if (k.startsWith("rest_")) {
|
|
80
|
-
k = k.slice(5);
|
|
81
|
-
v = v.split("/");
|
|
82
|
-
}
|
|
83
|
-
Reflect.set(params, k, v);
|
|
84
|
-
}
|
|
85
|
-
return params;
|
|
86
|
-
}
|
|
87
|
-
function resolvePathToRoute(nextServer, requestPath) {
|
|
88
|
-
const basePath = nextServer.serverOptions.conf.basePath;
|
|
89
|
-
const routes = {
|
|
90
|
-
// @ts-expect-error - appPathRoutes is protected
|
|
91
|
-
...nextServer.appPathRoutes,
|
|
92
|
-
// @ts-expect-error - getAppPathRoutes is protected
|
|
93
|
-
...nextServer.getAppPathRoutes()
|
|
94
|
-
};
|
|
95
|
-
let pathToRoute = null;
|
|
96
|
-
for (const [routePath, [filePath]] of Object.entries(routes)) {
|
|
97
|
-
const realPath = `${basePath}${routePath}`;
|
|
98
|
-
const routeParams = getRouteParams(realPath, requestPath);
|
|
99
|
-
if (routeParams) pathToRoute = { filePath, routeParams };
|
|
100
|
-
}
|
|
101
|
-
return pathToRoute || null;
|
|
102
|
-
}
|
|
103
|
-
async function importRouteModule(nextServer, filePath) {
|
|
104
|
-
try {
|
|
105
|
-
if ("hotReloader" in nextServer) {
|
|
106
|
-
await nextServer.hotReloader?.ensurePage({
|
|
107
|
-
page: filePath,
|
|
108
|
-
clientOnly: false
|
|
109
|
-
});
|
|
110
|
-
} else if ("ensurePage" in nextServer) {
|
|
111
|
-
await nextServer.ensurePage({ page: filePath, clientOnly: false });
|
|
112
|
-
} else {
|
|
113
|
-
logger2.warnOnce(
|
|
114
|
-
"[next-ws] unable to ensure page, you may need to open the route in your browser first so Next.js compiles it"
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
} catch {
|
|
118
|
-
}
|
|
119
|
-
const buildPagePath = nextServer.getPagePath(filePath);
|
|
120
|
-
return importModule(buildPagePath);
|
|
121
|
-
}
|
|
122
|
-
async function importModule(modulePath) {
|
|
123
|
-
const moduleUrl = pathToFileURL(modulePath).toString();
|
|
124
|
-
try {
|
|
125
|
-
return import(moduleUrl);
|
|
126
|
-
} catch (requireError) {
|
|
127
|
-
try {
|
|
128
|
-
return __require(modulePath);
|
|
129
|
-
} catch (requireError2) {
|
|
130
|
-
console.error(`Both import and require failed for ${modulePath}`);
|
|
131
|
-
throw requireError2;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
async function getSocketHandler(routeModule) {
|
|
136
|
-
if (routeModule.default instanceof Promise)
|
|
137
|
-
return getSocketHandler(await routeModule.default);
|
|
138
|
-
return routeModule?.default?.routeModule?.userland?.SOCKET ?? routeModule?.routeModule?.userland?.SOCKET ?? routeModule?.default?.handlers?.SOCKET ?? routeModule?.handlers?.SOCKET;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// src/server/setup.ts
|
|
142
|
-
function setupWebSocketServer(nextServer) {
|
|
143
|
-
process.env.NEXT_WS_MAIN_PROCESS = String(1);
|
|
144
|
-
process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK = String(1);
|
|
145
|
-
const httpServer = useHttpServer(nextServer.serverOptions?.httpServer);
|
|
146
|
-
const wsServer = useWebSocketServer(new WebSocketServer({ noServer: true }));
|
|
147
|
-
process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK = String(0);
|
|
148
|
-
if (!httpServer)
|
|
149
|
-
return logger3.error("[next-ws] was not able to find the HTTP server");
|
|
150
|
-
if (!wsServer)
|
|
151
|
-
return logger3.error("[next-ws] was not able to find the WebSocket server");
|
|
152
|
-
logger3.ready("[next-ws] has started the WebSocket server");
|
|
153
|
-
httpServer.on("upgrade", async (request, socket, head) => {
|
|
154
|
-
const url = new URL(request.url ?? "", "ws://next");
|
|
155
|
-
const pathname = url.pathname;
|
|
156
|
-
if (pathname.includes("/_next")) return;
|
|
157
|
-
const routeInfo = resolvePathToRoute(nextServer, pathname);
|
|
158
|
-
if (!routeInfo) {
|
|
159
|
-
logger3.error(`[next-ws] could not find module for page ${pathname}`);
|
|
160
|
-
return socket.destroy();
|
|
161
|
-
}
|
|
162
|
-
const routeModule = await importRouteModule(nextServer, routeInfo.filePath);
|
|
163
|
-
if (!routeModule) {
|
|
164
|
-
logger3.error(`[next-ws] could not find module for page ${pathname}`);
|
|
165
|
-
return socket.destroy();
|
|
166
|
-
}
|
|
167
|
-
const socketHandler = await getSocketHandler(routeModule);
|
|
168
|
-
if (!socketHandler || typeof socketHandler !== "function") {
|
|
169
|
-
logger3.error(`[next-ws] ${pathname} does not export a SOCKET handler`);
|
|
170
|
-
return socket.destroy();
|
|
171
|
-
}
|
|
172
|
-
return wsServer.handleUpgrade(request, socket, head, async (c, r) => {
|
|
173
|
-
const routeContext = { params: routeInfo.routeParams };
|
|
174
|
-
const handleClose = await socketHandler(c, r, wsServer, routeContext);
|
|
175
|
-
if (typeof handleClose === "function")
|
|
176
|
-
c.once("close", () => handleClose());
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
export {
|
|
181
|
-
getHttpServer,
|
|
182
|
-
getWebSocketServer,
|
|
183
|
-
setHttpServer,
|
|
184
|
-
setWebSocketServer,
|
|
185
|
-
setupWebSocketServer
|
|
186
|
-
};
|