next-ws 1.0.1 → 1.1.0-next.1
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/dist/chunk-6VWOYYWX.mjs +11 -0
- package/dist/chunk-6VWOYYWX.mjs.map +1 -0
- package/dist/chunk-PFW3KWBF.cjs +14 -0
- package/dist/chunk-PFW3KWBF.cjs.map +1 -0
- package/dist/client/index.cjs +34 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +25 -0
- package/dist/client/index.d.ts +25 -0
- package/dist/client/index.mjs +29 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/server/index.cjs +159 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +38 -0
- package/dist/server/index.d.ts +38 -0
- package/dist/server/index.mjs +131 -0
- package/dist/server/index.mjs.map +1 -0
- package/package.json +27 -36
- package/readme.md +241 -0
- package/README.md +0 -198
- package/client/context.d.ts +0 -24
- package/client/context.js +0 -43
- package/client/index.d.ts +0 -1
- package/client/index.js +0 -4
- package/index.d.ts +0 -1
- package/index.js +0 -3
- package/server/index.d.ts +0 -3
- package/server/index.js +0 -5
- package/server/setup.d.ts +0 -3
- package/server/setup.js +0 -42
- package/server/utilities/next.d.ts +0 -31
- package/server/utilities/next.js +0 -106
- package/server/utilities/patch.d.ts +0 -13
- package/server/utilities/patch.js +0 -37
- package/server/utilities/server.d.ts +0 -33
- package/server/utilities/server.js +0 -50
- package/server/utilities/workspace.d.ts +0 -1
- package/server/utilities/workspace.js +0 -44
- package/server/utilities/ws.d.ts +0 -15
- package/server/utilities/ws.js +0 -13
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: !0 }), __require = /* @__PURE__ */ ((x) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require < "u" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require < "u") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export { __name, __require };
|
|
10
|
+
//# sourceMappingURL=out.js.map
|
|
11
|
+
//# sourceMappingURL=chunk-6VWOYYWX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","sourcesContent":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: !0 }), __require = /* @__PURE__ */ ((x) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(x, {
|
|
5
|
+
get: (a, b) => (typeof require < "u" ? require : a)[b]
|
|
6
|
+
}) : x)(function(x) {
|
|
7
|
+
if (typeof require < "u") return require.apply(this, arguments);
|
|
8
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
exports.__name = __name;
|
|
12
|
+
exports.__require = __require;
|
|
13
|
+
//# sourceMappingURL=out.js.map
|
|
14
|
+
//# sourceMappingURL=chunk-PFW3KWBF.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","sourcesContent":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkPFW3KWBF_cjs = require('../chunk-PFW3KWBF.cjs');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
|
|
6
|
+
var WebSocketContext = react.createContext(null);
|
|
7
|
+
WebSocketContext.displayName = "WebSocketContext";
|
|
8
|
+
var WebSocketConsumer = WebSocketContext.Consumer;
|
|
9
|
+
function WebSocketProvider(p) {
|
|
10
|
+
let client = react.useMemo(() => {
|
|
11
|
+
if (typeof window > "u") return null;
|
|
12
|
+
let client2 = new WebSocket(p.url, p.protocols);
|
|
13
|
+
return p.binaryType && (client2.binaryType = p.binaryType), client2;
|
|
14
|
+
}, [p.url, p.protocols, p.binaryType]);
|
|
15
|
+
return react.useEffect(() => {
|
|
16
|
+
if (client?.readyState === WebSocket.OPEN)
|
|
17
|
+
return () => client.close();
|
|
18
|
+
}, [client]), /* @__PURE__ */ React.createElement(WebSocketContext.Provider, { value: client }, p.children);
|
|
19
|
+
}
|
|
20
|
+
chunkPFW3KWBF_cjs.__name(WebSocketProvider, "WebSocketProvider");
|
|
21
|
+
function useWebSocket() {
|
|
22
|
+
let context = react.useContext(WebSocketContext);
|
|
23
|
+
if (context === void 0)
|
|
24
|
+
throw new Error("useWebSocket must be used within a WebSocketProvider");
|
|
25
|
+
return context;
|
|
26
|
+
}
|
|
27
|
+
chunkPFW3KWBF_cjs.__name(useWebSocket, "useWebSocket");
|
|
28
|
+
|
|
29
|
+
exports.WebSocketConsumer = WebSocketConsumer;
|
|
30
|
+
exports.WebSocketContext = WebSocketContext;
|
|
31
|
+
exports.WebSocketProvider = WebSocketProvider;
|
|
32
|
+
exports.useWebSocket = useWebSocket;
|
|
33
|
+
//# sourceMappingURL=out.js.map
|
|
34
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/context.tsx"],"names":["client"],"mappings":";;;;;AAGA,SAAS,eAAe,YAAY,WAAW,eAAe;AAEvD,IAAM,mBAAmB,cAAgC,IAAI;AACpE,iBAAiB,cAAc;AACxB,IAAM,oBAAoB,iBAAiB;AAQ3C,SAAS,kBACd,GAQA;AACA,MAAM,SAAS,QAAQ,MAAM;AAC3B,QAAI,OAAO,SAAW,IAAa,QAAO;AAC1C,QAAMA,UAAS,IAAI,UAAU,EAAE,KAAK,EAAE,SAAS;AAC/C,WAAI,EAAE,eAAYA,QAAO,aAAa,EAAE,aACjCA;AAAA,EACT,GAAG,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,CAAC;AAErC,mBAAU,MAAM;AACd,QAAI,QAAQ,eAAe,UAAU;AACrC,aAAO,MAAM,OAAO,MAAM;AAAA,EAC5B,GAAG,CAAC,MAAM,CAAC,GAGT,oCAAC,iBAAiB,UAAjB,EAA0B,OAAO,UAC/B,EAAE,QACL;AAEJ;AA3BgB;AAiCT,SAAS,eAAe;AAC7B,MAAM,UAAU,WAAW,gBAAgB;AAC3C,MAAI,YAAY;AACd,UAAM,IAAI,MAAM,sDAAsD;AACxE,SAAO;AACT;AALgB","sourcesContent":["'use client';\n\nimport type React from 'react';\nimport { createContext, useContext, useEffect, useMemo } from 'react';\n\nexport const WebSocketContext = createContext<WebSocket | null>(null);\nWebSocketContext.displayName = 'WebSocketContext';\nexport const WebSocketConsumer = WebSocketContext.Consumer;\n\n/**\n * Provides a WebSocket client to its children via context,\n * allowing for easy access to the WebSocket from anywhere in the app.\n * @param props WebSocket parameters and children.\n * @returns JSX Element\n */\nexport function WebSocketProvider(\n p: React.PropsWithChildren<{\n /** The URL for the WebSocket to connect to. */\n url: string;\n /** The subprotocols to use. */\n protocols?: string[] | string;\n /** The binary type to use. */\n binaryType?: BinaryType;\n }>,\n) {\n const client = useMemo(() => {\n if (typeof window === 'undefined') return null;\n const client = new WebSocket(p.url, p.protocols);\n if (p.binaryType) client.binaryType = p.binaryType;\n return client;\n }, [p.url, p.protocols, p.binaryType]);\n\n useEffect(() => {\n if (client?.readyState !== WebSocket.OPEN) return;\n return () => client.close();\n }, [client]);\n\n return (\n <WebSocketContext.Provider value={client}>\n {p.children}\n </WebSocketContext.Provider>\n );\n}\n\n/**\n * Access the websocket from anywhere in the app, so long as it's wrapped in a WebSocketProvider.\n * @returns WebSocket client when connected, null when disconnected.\n */\nexport function useWebSocket() {\n const context = useContext(WebSocketContext);\n if (context === undefined)\n throw new Error('useWebSocket must be used within a WebSocketProvider');\n return context;\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
declare const WebSocketContext: React.Context<WebSocket | null>;
|
|
4
|
+
declare const WebSocketConsumer: React.Consumer<WebSocket | null>;
|
|
5
|
+
/**
|
|
6
|
+
* Provides a WebSocket client to its children via context,
|
|
7
|
+
* allowing for easy access to the WebSocket from anywhere in the app.
|
|
8
|
+
* @param props WebSocket parameters and children.
|
|
9
|
+
* @returns JSX Element
|
|
10
|
+
*/
|
|
11
|
+
declare function WebSocketProvider(p: React.PropsWithChildren<{
|
|
12
|
+
/** The URL for the WebSocket to connect to. */
|
|
13
|
+
url: string;
|
|
14
|
+
/** The subprotocols to use. */
|
|
15
|
+
protocols?: string[] | string;
|
|
16
|
+
/** The binary type to use. */
|
|
17
|
+
binaryType?: BinaryType;
|
|
18
|
+
}>): React.JSX.Element;
|
|
19
|
+
/**
|
|
20
|
+
* Access the websocket from anywhere in the app, so long as it's wrapped in a WebSocketProvider.
|
|
21
|
+
* @returns WebSocket client when connected, null when disconnected.
|
|
22
|
+
*/
|
|
23
|
+
declare function useWebSocket(): WebSocket | null;
|
|
24
|
+
|
|
25
|
+
export { WebSocketConsumer, WebSocketContext, WebSocketProvider, useWebSocket };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
declare const WebSocketContext: React.Context<WebSocket | null>;
|
|
4
|
+
declare const WebSocketConsumer: React.Consumer<WebSocket | null>;
|
|
5
|
+
/**
|
|
6
|
+
* Provides a WebSocket client to its children via context,
|
|
7
|
+
* allowing for easy access to the WebSocket from anywhere in the app.
|
|
8
|
+
* @param props WebSocket parameters and children.
|
|
9
|
+
* @returns JSX Element
|
|
10
|
+
*/
|
|
11
|
+
declare function WebSocketProvider(p: React.PropsWithChildren<{
|
|
12
|
+
/** The URL for the WebSocket to connect to. */
|
|
13
|
+
url: string;
|
|
14
|
+
/** The subprotocols to use. */
|
|
15
|
+
protocols?: string[] | string;
|
|
16
|
+
/** The binary type to use. */
|
|
17
|
+
binaryType?: BinaryType;
|
|
18
|
+
}>): React.JSX.Element;
|
|
19
|
+
/**
|
|
20
|
+
* Access the websocket from anywhere in the app, so long as it's wrapped in a WebSocketProvider.
|
|
21
|
+
* @returns WebSocket client when connected, null when disconnected.
|
|
22
|
+
*/
|
|
23
|
+
declare function useWebSocket(): WebSocket | null;
|
|
24
|
+
|
|
25
|
+
export { WebSocketConsumer, WebSocketContext, WebSocketProvider, useWebSocket };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { __name } from '../chunk-6VWOYYWX.mjs';
|
|
2
|
+
import { createContext, useMemo, useEffect, useContext } from 'react';
|
|
3
|
+
|
|
4
|
+
var WebSocketContext = createContext(null);
|
|
5
|
+
WebSocketContext.displayName = "WebSocketContext";
|
|
6
|
+
var WebSocketConsumer = WebSocketContext.Consumer;
|
|
7
|
+
function WebSocketProvider(p) {
|
|
8
|
+
let client = useMemo(() => {
|
|
9
|
+
if (typeof window > "u") return null;
|
|
10
|
+
let client2 = new WebSocket(p.url, p.protocols);
|
|
11
|
+
return p.binaryType && (client2.binaryType = p.binaryType), client2;
|
|
12
|
+
}, [p.url, p.protocols, p.binaryType]);
|
|
13
|
+
return useEffect(() => {
|
|
14
|
+
if (client?.readyState === WebSocket.OPEN)
|
|
15
|
+
return () => client.close();
|
|
16
|
+
}, [client]), /* @__PURE__ */ React.createElement(WebSocketContext.Provider, { value: client }, p.children);
|
|
17
|
+
}
|
|
18
|
+
__name(WebSocketProvider, "WebSocketProvider");
|
|
19
|
+
function useWebSocket() {
|
|
20
|
+
let context = useContext(WebSocketContext);
|
|
21
|
+
if (context === void 0)
|
|
22
|
+
throw new Error("useWebSocket must be used within a WebSocketProvider");
|
|
23
|
+
return context;
|
|
24
|
+
}
|
|
25
|
+
__name(useWebSocket, "useWebSocket");
|
|
26
|
+
|
|
27
|
+
export { WebSocketConsumer, WebSocketContext, WebSocketProvider, useWebSocket };
|
|
28
|
+
//# sourceMappingURL=out.js.map
|
|
29
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/context.tsx"],"names":["client"],"mappings":";;;;;AAGA,SAAS,eAAe,YAAY,WAAW,eAAe;AAEvD,IAAM,mBAAmB,cAAgC,IAAI;AACpE,iBAAiB,cAAc;AACxB,IAAM,oBAAoB,iBAAiB;AAQ3C,SAAS,kBACd,GAQA;AACA,MAAM,SAAS,QAAQ,MAAM;AAC3B,QAAI,OAAO,SAAW,IAAa,QAAO;AAC1C,QAAMA,UAAS,IAAI,UAAU,EAAE,KAAK,EAAE,SAAS;AAC/C,WAAI,EAAE,eAAYA,QAAO,aAAa,EAAE,aACjCA;AAAA,EACT,GAAG,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,CAAC;AAErC,mBAAU,MAAM;AACd,QAAI,QAAQ,eAAe,UAAU;AACrC,aAAO,MAAM,OAAO,MAAM;AAAA,EAC5B,GAAG,CAAC,MAAM,CAAC,GAGT,oCAAC,iBAAiB,UAAjB,EAA0B,OAAO,UAC/B,EAAE,QACL;AAEJ;AA3BgB;AAiCT,SAAS,eAAe;AAC7B,MAAM,UAAU,WAAW,gBAAgB;AAC3C,MAAI,YAAY;AACd,UAAM,IAAI,MAAM,sDAAsD;AACxE,SAAO;AACT;AALgB","sourcesContent":["'use client';\n\nimport type React from 'react';\nimport { createContext, useContext, useEffect, useMemo } from 'react';\n\nexport const WebSocketContext = createContext<WebSocket | null>(null);\nWebSocketContext.displayName = 'WebSocketContext';\nexport const WebSocketConsumer = WebSocketContext.Consumer;\n\n/**\n * Provides a WebSocket client to its children via context,\n * allowing for easy access to the WebSocket from anywhere in the app.\n * @param props WebSocket parameters and children.\n * @returns JSX Element\n */\nexport function WebSocketProvider(\n p: React.PropsWithChildren<{\n /** The URL for the WebSocket to connect to. */\n url: string;\n /** The subprotocols to use. */\n protocols?: string[] | string;\n /** The binary type to use. */\n binaryType?: BinaryType;\n }>,\n) {\n const client = useMemo(() => {\n if (typeof window === 'undefined') return null;\n const client = new WebSocket(p.url, p.protocols);\n if (p.binaryType) client.binaryType = p.binaryType;\n return client;\n }, [p.url, p.protocols, p.binaryType]);\n\n useEffect(() => {\n if (client?.readyState !== WebSocket.OPEN) return;\n return () => client.close();\n }, [client]);\n\n return (\n <WebSocketContext.Provider value={client}>\n {p.children}\n </WebSocketContext.Provider>\n );\n}\n\n/**\n * Access the websocket from anywhere in the app, so long as it's wrapped in a WebSocketProvider.\n * @returns WebSocket client when connected, null when disconnected.\n */\nexport function useWebSocket() {\n const context = useContext(WebSocketContext);\n if (context === undefined)\n throw new Error('useWebSocket must be used within a WebSocketProvider');\n return context;\n}\n"]}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkPFW3KWBF_cjs = require('../chunk-PFW3KWBF.cjs');
|
|
4
|
+
var logger3 = require('next/dist/build/output/log');
|
|
5
|
+
var ws = require('ws');
|
|
6
|
+
|
|
7
|
+
function _interopNamespace(e) {
|
|
8
|
+
if (e && e.__esModule) return e;
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var logger3__namespace = /*#__PURE__*/_interopNamespace(logger3);
|
|
26
|
+
|
|
27
|
+
function getEnvironmentMeta() {
|
|
28
|
+
let isCustomServer = !process.title.startsWith("next-"), isMainProcess = process.env.NEXT_WS_MAIN_PROCESS === "1", isDevelopment = process.env.NODE_ENV === "development";
|
|
29
|
+
return { isCustomServer, isMainProcess, isDevelopment };
|
|
30
|
+
}
|
|
31
|
+
chunkPFW3KWBF_cjs.__name(getEnvironmentMeta, "getEnvironmentMeta");
|
|
32
|
+
function resolveFilename(nextServer, pathname) {
|
|
33
|
+
let pathParts = pathname.split("/"), appRoutes = {
|
|
34
|
+
// @ts-expect-error - appPathRoutes is protected
|
|
35
|
+
...nextServer.appPathRoutes,
|
|
36
|
+
// @ts-expect-error - getAppPathRoutes is protected
|
|
37
|
+
...nextServer.getAppPathRoutes()
|
|
38
|
+
};
|
|
39
|
+
for (let [key, [path]] of Object.entries(appRoutes))
|
|
40
|
+
if (key.includes("[") && key.includes("]")) {
|
|
41
|
+
let keyParts = key.split("/");
|
|
42
|
+
if (keyParts.length !== pathParts.length) continue;
|
|
43
|
+
for (let i = 0; i < keyParts.length; i++) {
|
|
44
|
+
let keyPart = keyParts[i], pathPart = pathParts[i];
|
|
45
|
+
if (keyPart.includes("[") && keyPart.includes("]") && (keyParts[i] = pathPart), keyParts[i] !== pathParts[i]) break;
|
|
46
|
+
if (i === keyParts.length - 1 && !path?.endsWith("/route"))
|
|
47
|
+
return path;
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
if (key !== pathname) continue;
|
|
51
|
+
return path?.endsWith("/route") ? path : null;
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
chunkPFW3KWBF_cjs.__name(resolveFilename, "resolveFilename");
|
|
56
|
+
async function getPageModule(nextServer, filename) {
|
|
57
|
+
try {
|
|
58
|
+
"hotReloader" in nextServer ? await nextServer.hotReloader?.ensurePage({
|
|
59
|
+
page: filename,
|
|
60
|
+
clientOnly: !1
|
|
61
|
+
}) : "ensurePage" in nextServer ? await nextServer.ensurePage({ page: filename, clientOnly: !1 }) : logger3__namespace.warnOnce(
|
|
62
|
+
"[next-ws] unable to ensure page, you may need to open the route in your browser first so Next.js compiles it"
|
|
63
|
+
);
|
|
64
|
+
} catch {
|
|
65
|
+
}
|
|
66
|
+
let buildPagePath = nextServer.getPagePath(filename);
|
|
67
|
+
return chunkPFW3KWBF_cjs.__require(buildPagePath);
|
|
68
|
+
}
|
|
69
|
+
chunkPFW3KWBF_cjs.__name(getPageModule, "getPageModule");
|
|
70
|
+
function mainProcessOnly(fnName) {
|
|
71
|
+
if (process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK === "1") return;
|
|
72
|
+
let meta = getEnvironmentMeta();
|
|
73
|
+
if (meta.isMainProcess)
|
|
74
|
+
meta.isCustomServer || logger3__namespace.warnOnce(
|
|
75
|
+
`[next-ws] Caution: The function '${fnName}' was invoked without a custom server.
|
|
76
|
+
This could lead to unintended behaviour, especially if you're attempting to interact with the WebSocket server outside of a SOCKET handler. Please note, while such configurations might function during development, they are likely to fail in production environments. 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.`
|
|
77
|
+
);
|
|
78
|
+
else throw new Error(
|
|
79
|
+
`[next-ws] Attempt to invoke '${fnName}' outside the main process.
|
|
80
|
+
You may be attempting to interact with the WebSocket server outside of a SOCKET handler. This is likely to fail in production environments, as Next.js employs a worker process for routing in production, which do not have access to the WebSocket server on the main process.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
chunkPFW3KWBF_cjs.__name(mainProcessOnly, "mainProcessOnly");
|
|
84
|
+
var NextWsHttpServer = Symbol.for("NextWs_HttpServer");
|
|
85
|
+
function setHttpServer(server) {
|
|
86
|
+
Reflect.set(globalThis, NextWsHttpServer, server);
|
|
87
|
+
}
|
|
88
|
+
chunkPFW3KWBF_cjs.__name(setHttpServer, "setHttpServer");
|
|
89
|
+
function getHttpServer() {
|
|
90
|
+
return mainProcessOnly("getHttpServer"), Reflect.get(globalThis, NextWsHttpServer);
|
|
91
|
+
}
|
|
92
|
+
chunkPFW3KWBF_cjs.__name(getHttpServer, "getHttpServer");
|
|
93
|
+
function useHttpServer(server) {
|
|
94
|
+
let existing = getHttpServer();
|
|
95
|
+
return existing || (server && setHttpServer(server), server);
|
|
96
|
+
}
|
|
97
|
+
chunkPFW3KWBF_cjs.__name(useHttpServer, "useHttpServer");
|
|
98
|
+
var NextWsWebSocketServer = Symbol.for("NextWs_WebSocketServer");
|
|
99
|
+
function setWebSocketServer(wsServer) {
|
|
100
|
+
Reflect.set(globalThis, NextWsWebSocketServer, wsServer);
|
|
101
|
+
}
|
|
102
|
+
chunkPFW3KWBF_cjs.__name(setWebSocketServer, "setWebSocketServer");
|
|
103
|
+
function getWebSocketServer() {
|
|
104
|
+
return mainProcessOnly("getWebSocketServer"), Reflect.get(globalThis, NextWsWebSocketServer);
|
|
105
|
+
}
|
|
106
|
+
chunkPFW3KWBF_cjs.__name(getWebSocketServer, "getWebSocketServer");
|
|
107
|
+
function useWebSocketServer(wsServer) {
|
|
108
|
+
let existing = getWebSocketServer();
|
|
109
|
+
return existing || (wsServer && setWebSocketServer(wsServer), wsServer);
|
|
110
|
+
}
|
|
111
|
+
chunkPFW3KWBF_cjs.__name(useWebSocketServer, "useWebSocketServer");
|
|
112
|
+
|
|
113
|
+
// src/server/setup.ts
|
|
114
|
+
function setupWebSocketServer(nextServer) {
|
|
115
|
+
process.env.NEXT_WS_MAIN_PROCESS = String(1), process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK = String(1);
|
|
116
|
+
let httpServer = useHttpServer(nextServer.serverOptions?.httpServer), wsServer = useWebSocketServer(new ws.WebSocketServer({ noServer: !0 }));
|
|
117
|
+
if (delete process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK, !httpServer)
|
|
118
|
+
return logger3__namespace.error("[next-ws] was not able to find the HTTP server");
|
|
119
|
+
if (!wsServer)
|
|
120
|
+
return logger3__namespace.error("[next-ws] was not able to find the WebSocket server");
|
|
121
|
+
logger3__namespace.ready("[next-ws] has started the WebSocket server"), httpServer.on("upgrade", async (request, socket, head) => {
|
|
122
|
+
let pathname = new URL(request.url ?? "", "ws://next").pathname;
|
|
123
|
+
if (pathname.startsWith("/_next")) return;
|
|
124
|
+
let filename = resolveFilename(nextServer, pathname);
|
|
125
|
+
if (!filename)
|
|
126
|
+
return logger3__namespace.error(`[next-ws] could not find module for page ${pathname}`), socket.destroy();
|
|
127
|
+
let pageModule = await getPageModule(nextServer, filename);
|
|
128
|
+
if (!pageModule)
|
|
129
|
+
return logger3__namespace.error(`[next-ws] could not find module for page ${pathname}`), socket.destroy();
|
|
130
|
+
let socketHandler = pageModule?.routeModule?.userland?.SOCKET;
|
|
131
|
+
return !socketHandler || typeof socketHandler != "function" ? (logger3__namespace.error(`[next-ws] ${pathname} does not export a SOCKET handler`), socket.destroy()) : wsServer.handleUpgrade(request, socket, head, (c, r) => {
|
|
132
|
+
let dispose = socketHandler(c, r, wsServer);
|
|
133
|
+
typeof dispose == "function" && c.once("close", () => dispose());
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
chunkPFW3KWBF_cjs.__name(setupWebSocketServer, "setupWebSocketServer");
|
|
138
|
+
function hookNextNodeServer() {
|
|
139
|
+
setupWebSocketServer(this);
|
|
140
|
+
}
|
|
141
|
+
chunkPFW3KWBF_cjs.__name(hookNextNodeServer, "hookNextNodeServer");
|
|
142
|
+
|
|
143
|
+
// src/server/index.ts
|
|
144
|
+
function verifyPatch() {
|
|
145
|
+
throw new Error(
|
|
146
|
+
"The 'verifyPatch' function has been deprecated in favour of the `npx next-ws-cli@latest verify` command."
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
chunkPFW3KWBF_cjs.__name(verifyPatch, "verifyPatch");
|
|
150
|
+
|
|
151
|
+
exports.getHttpServer = getHttpServer;
|
|
152
|
+
exports.getWebSocketServer = getWebSocketServer;
|
|
153
|
+
exports.hookNextNodeServer = hookNextNodeServer;
|
|
154
|
+
exports.setHttpServer = setHttpServer;
|
|
155
|
+
exports.setWebSocketServer = setWebSocketServer;
|
|
156
|
+
exports.setupWebSocketServer = setupWebSocketServer;
|
|
157
|
+
exports.verifyPatch = verifyPatch;
|
|
158
|
+
//# sourceMappingURL=out.js.map
|
|
159
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/setup.ts","../../src/server/helpers/next.ts","../../src/server/helpers/persistent.ts","../../src/server/index.ts"],"names":["logger"],"mappings":"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","sourcesContent":["import * as logger from 'next/dist/build/output/log';\nimport type NextNodeServer from 'next/dist/server/next-server';\nimport { WebSocketServer } from 'ws';\nimport { getPageModule, resolveFilename } from './helpers/next';\nimport { useHttpServer, useWebSocketServer } from './helpers/persistent';\n\nexport function setupWebSocketServer(nextServer: NextNodeServer) {\n process.env.NEXT_WS_MAIN_PROCESS = String(1);\n\n process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK = String(1);\n // @ts-expect-error - serverOptions is protected\n const httpServer = useHttpServer(nextServer.serverOptions?.httpServer);\n const wsServer = useWebSocketServer(new WebSocketServer({ noServer: true }));\n // biome-ignore lint/performance/noDelete: <explanation>\n delete process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK;\n\n if (!httpServer)\n return logger.error('[next-ws] was not able to find the HTTP server');\n if (!wsServer)\n return logger.error('[next-ws] was not able to find the WebSocket server');\n\n logger.ready('[next-ws] has started the WebSocket server');\n\n httpServer.on('upgrade', async (request, socket, head) => {\n const url = new URL(request.url ?? '', 'ws://next');\n const pathname = url.pathname;\n if (pathname.startsWith('/_next')) return;\n\n const filename = resolveFilename(nextServer, pathname);\n if (!filename) {\n logger.error(`[next-ws] could not find module for page ${pathname}`);\n return socket.destroy();\n }\n\n const pageModule = await getPageModule(nextServer, filename);\n if (!pageModule) {\n logger.error(`[next-ws] could not find module for page ${pathname}`);\n return socket.destroy();\n }\n\n const socketHandler = pageModule?.routeModule?.userland?.SOCKET;\n if (!socketHandler || typeof socketHandler !== 'function') {\n logger.error(`[next-ws] ${pathname} does not export a SOCKET handler`);\n return socket.destroy();\n }\n\n return wsServer.handleUpgrade(request, socket, head, (c, r) => {\n const dispose = socketHandler(c, r, wsServer);\n if (typeof dispose === 'function') c.once('close', () => dispose());\n });\n });\n}\n\n// Next WS versions below 0.2.0 used a different method of setup\n// This remains for backwards compatibility, but may be removed in a future version\nexport function hookNextNodeServer(this: NextNodeServer) {\n setupWebSocketServer(this);\n}\n","import * as logger from 'next/dist/build/output/log';\nimport type NextNodeServer from 'next/dist/server/next-server';\nimport type { SocketHandler } from './persistent';\n\n/**\n * Get the environment metadata.\n * @returns The environment metadata.\n */\nexport function getEnvironmentMeta() {\n const isCustomServer = !process.title.startsWith('next-');\n const isMainProcess = process.env.NEXT_WS_MAIN_PROCESS === '1';\n const isDevelopment = process.env.NODE_ENV === 'development';\n return { isCustomServer, isMainProcess, isDevelopment };\n}\n\n/**\n * Resolve a filename to a page.\n * @param nextServer The NextNodeServer instance.\n * @param pathname The pathname to resolve.\n * @returns The resolved page filename, or null if the page could not be resolved.\n */\nexport function resolveFilename(nextServer: NextNodeServer, pathname: string) {\n const pathParts = pathname.split('/');\n const appRoutes = {\n // @ts-expect-error - appPathRoutes is protected\n ...nextServer.appPathRoutes,\n // @ts-expect-error - getAppPathRoutes is protected\n ...nextServer.getAppPathRoutes(),\n };\n\n for (const [key, [path]] of Object.entries(appRoutes)) {\n const hasDynamic = key.includes('[') && key.includes(']');\n\n if (hasDynamic) {\n const keyParts = key.split('/');\n if (keyParts.length !== pathParts.length) continue;\n\n for (let i = 0; i < keyParts.length; i++) {\n const keyPart = keyParts[i]!;\n const pathPart = pathParts[i]!;\n\n const isDynamic = keyPart.includes('[') && keyPart.includes(']');\n if (isDynamic) keyParts[i] = pathPart;\n if (keyParts[i] !== pathParts[i]) break;\n\n if (i === keyParts.length - 1)\n if (!path?.endsWith('/route')) return path;\n }\n } else {\n if (key !== pathname) continue;\n if (!path?.endsWith('/route')) return null;\n return path;\n }\n }\n\n return null;\n}\n\n/**\n * Get the page module for a page.\n * @param nextServer The NextNodeServer instance.\n * @param filename The filename of the page.\n * @returns The page module.\n */\nexport async function getPageModule(\n nextServer: NextNodeServer,\n filename: string,\n) {\n try {\n // In Next.js 14, hotReloader was removed and ensurePage was moved to NextNodeServer\n if ('hotReloader' in nextServer) {\n // @ts-expect-error - hotReloader only exists in Next.js 13\n await nextServer.hotReloader?.ensurePage({\n page: filename,\n clientOnly: false,\n });\n } else if ('ensurePage' in nextServer) {\n // ensurePage throws an error in production, so we need to catch it\n // @ts-expect-error - ensurePage is protected\n await nextServer.ensurePage({ page: filename, clientOnly: false });\n } else {\n // Future-proofing\n logger.warnOnce(\n '[next-ws] unable to ensure page, you may need to open the route in your browser first so Next.js compiles it',\n );\n }\n } catch {}\n\n // @ts-expect-error - getPageModule is protected\n const buildPagePath = nextServer.getPagePath(filename);\n return require(buildPagePath) as PageModule;\n}\n\nexport interface PageModule {\n routeModule?: {\n userland?: {\n SOCKET?: SocketHandler;\n };\n };\n}\n","import * as logger from 'next/dist/build/output/log';\nimport { getEnvironmentMeta } from './next';\n\nfunction mainProcessOnly(fnName: string) {\n if (process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK === '1') return;\n\n const meta = getEnvironmentMeta();\n if (!meta.isMainProcess) {\n throw new Error(\n `[next-ws] Attempt to invoke '${fnName}' outside the main process.\nYou may be attempting to interact with the WebSocket server outside of a SOCKET handler. This is likely to fail in production environments, as Next.js employs a worker process for routing in production, which do not have access to the WebSocket server on the main process.`,\n );\n } else if (!meta.isCustomServer) {\n logger.warnOnce(\n `[next-ws] Caution: The function '${fnName}' was invoked without a custom server.\nThis could lead to unintended behaviour, especially if you're attempting to interact with the WebSocket server outside of a SOCKET handler. Please note, while such configurations might function during development, they are likely to fail in production environments. 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.`,\n );\n }\n}\n\n// ========== HTTP Server ==========\n\nimport type { Server as HttpServer } from 'node:http';\nexport const NextWsHttpServer = Symbol.for('NextWs_HttpServer');\n\n/**\n * Set the HTTP server that the WebSocket server should listen on, must be called before the WebSocket server is created.\n * @param server The HTTP server.\n */\nexport function setHttpServer(server: HttpServer) {\n Reflect.set(globalThis, NextWsHttpServer, server);\n}\n\n/**\n * Get the HTTP server that the WebSocket server is listening on.\n * @remark If you want to access the HTTP server outside of a SOCKET handler, you must be using a custom server.\n * @returns The HTTP server.\n * @throws If attempting to access the HTTP server outside of the main process.\n */\nexport function getHttpServer() {\n mainProcessOnly('getHttpServer');\n return Reflect.get(globalThis, NextWsHttpServer) as HttpServer;\n}\n\nexport function useHttpServer(server?: HttpServer) {\n const existing = getHttpServer();\n if (existing) return existing;\n if (server) setHttpServer(server);\n return server;\n}\n\n// ========== WebSocket Server ==========\n\nimport type { WebSocketServer } from 'ws';\nexport const NextWsWebSocketServer = Symbol.for('NextWs_WebSocketServer');\n\n/**\n * Set the WebSocket server that the WebSocket server should listen on, must be called before the WebSocket server is created.\n * @param wsServer The WebSocket server.\n */\nexport function setWebSocketServer(wsServer: WebSocketServer) {\n Reflect.set(globalThis, NextWsWebSocketServer, wsServer);\n}\n\n/**\n * Get the WebSocket server that the WebSocket server is listening on.\n * @remark If you want to access the WebSocket server outside of a SOCKET handler, you must be using a custom server.\n * @returns The WebSocket server.\n * @throws If attempting to access the WebSocket server outside of the main process.\n */\nexport function getWebSocketServer() {\n mainProcessOnly('getWebSocketServer');\n return Reflect.get(globalThis, NextWsWebSocketServer) as WebSocketServer;\n}\n\nexport function useWebSocketServer(wsServer?: WebSocketServer) {\n const existing = getWebSocketServer();\n if (existing) return existing;\n if (wsServer) setWebSocketServer(wsServer);\n return wsServer;\n}\n\n/** A function that handles a WebSocket connection. */\nexport type SocketHandler = (\n /** The WebSocket client that connected. */\n client: import('ws').WebSocket,\n /** The HTTP request that initiated the WebSocket connection. */\n request: import('http').IncomingMessage,\n /** The WebSocket server. */\n server: import('ws').WebSocketServer,\n) => unknown | (() => void);\n","export * from './setup';\nexport {\n setHttpServer,\n getHttpServer,\n setWebSocketServer,\n getWebSocketServer,\n} from './helpers/persistent';\n\n/**\n * @deprecated\n */\nexport function verifyPatch() {\n throw new Error(\n \"The 'verifyPatch' function has been deprecated in favour of the `npx next-ws-cli@latest verify` command.\",\n );\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import NextNodeServer from 'next/dist/server/next-server';
|
|
2
|
+
import { WebSocketServer } from 'ws';
|
|
3
|
+
import { Server } from 'node:http';
|
|
4
|
+
|
|
5
|
+
declare function setupWebSocketServer(nextServer: NextNodeServer): void;
|
|
6
|
+
declare function hookNextNodeServer(this: NextNodeServer): void;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Set the HTTP server that the WebSocket server should listen on, must be called before the WebSocket server is created.
|
|
10
|
+
* @param server The HTTP server.
|
|
11
|
+
*/
|
|
12
|
+
declare function setHttpServer(server: Server): void;
|
|
13
|
+
/**
|
|
14
|
+
* Get the HTTP server that the WebSocket server is listening on.
|
|
15
|
+
* @remark If you want to access the HTTP server outside of a SOCKET handler, you must be using a custom server.
|
|
16
|
+
* @returns The HTTP server.
|
|
17
|
+
* @throws If attempting to access the HTTP server outside of the main process.
|
|
18
|
+
*/
|
|
19
|
+
declare function getHttpServer(): Server;
|
|
20
|
+
/**
|
|
21
|
+
* Set the WebSocket server that the WebSocket server should listen on, must be called before the WebSocket server is created.
|
|
22
|
+
* @param wsServer The WebSocket server.
|
|
23
|
+
*/
|
|
24
|
+
declare function setWebSocketServer(wsServer: WebSocketServer): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get the WebSocket server that the WebSocket server is listening on.
|
|
27
|
+
* @remark If you want to access the WebSocket server outside of a SOCKET handler, you must be using a custom server.
|
|
28
|
+
* @returns The WebSocket server.
|
|
29
|
+
* @throws If attempting to access the WebSocket server outside of the main process.
|
|
30
|
+
*/
|
|
31
|
+
declare function getWebSocketServer(): WebSocketServer;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @deprecated
|
|
35
|
+
*/
|
|
36
|
+
declare function verifyPatch(): void;
|
|
37
|
+
|
|
38
|
+
export { getHttpServer, getWebSocketServer, hookNextNodeServer, setHttpServer, setWebSocketServer, setupWebSocketServer, verifyPatch };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import NextNodeServer from 'next/dist/server/next-server';
|
|
2
|
+
import { WebSocketServer } from 'ws';
|
|
3
|
+
import { Server } from 'node:http';
|
|
4
|
+
|
|
5
|
+
declare function setupWebSocketServer(nextServer: NextNodeServer): void;
|
|
6
|
+
declare function hookNextNodeServer(this: NextNodeServer): void;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Set the HTTP server that the WebSocket server should listen on, must be called before the WebSocket server is created.
|
|
10
|
+
* @param server The HTTP server.
|
|
11
|
+
*/
|
|
12
|
+
declare function setHttpServer(server: Server): void;
|
|
13
|
+
/**
|
|
14
|
+
* Get the HTTP server that the WebSocket server is listening on.
|
|
15
|
+
* @remark If you want to access the HTTP server outside of a SOCKET handler, you must be using a custom server.
|
|
16
|
+
* @returns The HTTP server.
|
|
17
|
+
* @throws If attempting to access the HTTP server outside of the main process.
|
|
18
|
+
*/
|
|
19
|
+
declare function getHttpServer(): Server;
|
|
20
|
+
/**
|
|
21
|
+
* Set the WebSocket server that the WebSocket server should listen on, must be called before the WebSocket server is created.
|
|
22
|
+
* @param wsServer The WebSocket server.
|
|
23
|
+
*/
|
|
24
|
+
declare function setWebSocketServer(wsServer: WebSocketServer): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get the WebSocket server that the WebSocket server is listening on.
|
|
27
|
+
* @remark If you want to access the WebSocket server outside of a SOCKET handler, you must be using a custom server.
|
|
28
|
+
* @returns The WebSocket server.
|
|
29
|
+
* @throws If attempting to access the WebSocket server outside of the main process.
|
|
30
|
+
*/
|
|
31
|
+
declare function getWebSocketServer(): WebSocketServer;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @deprecated
|
|
35
|
+
*/
|
|
36
|
+
declare function verifyPatch(): void;
|
|
37
|
+
|
|
38
|
+
export { getHttpServer, getWebSocketServer, hookNextNodeServer, setHttpServer, setWebSocketServer, setupWebSocketServer, verifyPatch };
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { __name, __require } from '../chunk-6VWOYYWX.mjs';
|
|
2
|
+
import * as logger3 from 'next/dist/build/output/log';
|
|
3
|
+
import { WebSocketServer } from 'ws';
|
|
4
|
+
|
|
5
|
+
function getEnvironmentMeta() {
|
|
6
|
+
let isCustomServer = !process.title.startsWith("next-"), isMainProcess = process.env.NEXT_WS_MAIN_PROCESS === "1", isDevelopment = process.env.NODE_ENV === "development";
|
|
7
|
+
return { isCustomServer, isMainProcess, isDevelopment };
|
|
8
|
+
}
|
|
9
|
+
__name(getEnvironmentMeta, "getEnvironmentMeta");
|
|
10
|
+
function resolveFilename(nextServer, pathname) {
|
|
11
|
+
let pathParts = pathname.split("/"), appRoutes = {
|
|
12
|
+
// @ts-expect-error - appPathRoutes is protected
|
|
13
|
+
...nextServer.appPathRoutes,
|
|
14
|
+
// @ts-expect-error - getAppPathRoutes is protected
|
|
15
|
+
...nextServer.getAppPathRoutes()
|
|
16
|
+
};
|
|
17
|
+
for (let [key, [path]] of Object.entries(appRoutes))
|
|
18
|
+
if (key.includes("[") && key.includes("]")) {
|
|
19
|
+
let keyParts = key.split("/");
|
|
20
|
+
if (keyParts.length !== pathParts.length) continue;
|
|
21
|
+
for (let i = 0; i < keyParts.length; i++) {
|
|
22
|
+
let keyPart = keyParts[i], pathPart = pathParts[i];
|
|
23
|
+
if (keyPart.includes("[") && keyPart.includes("]") && (keyParts[i] = pathPart), keyParts[i] !== pathParts[i]) break;
|
|
24
|
+
if (i === keyParts.length - 1 && !path?.endsWith("/route"))
|
|
25
|
+
return path;
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
if (key !== pathname) continue;
|
|
29
|
+
return path?.endsWith("/route") ? path : null;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
__name(resolveFilename, "resolveFilename");
|
|
34
|
+
async function getPageModule(nextServer, filename) {
|
|
35
|
+
try {
|
|
36
|
+
"hotReloader" in nextServer ? await nextServer.hotReloader?.ensurePage({
|
|
37
|
+
page: filename,
|
|
38
|
+
clientOnly: !1
|
|
39
|
+
}) : "ensurePage" in nextServer ? await nextServer.ensurePage({ page: filename, clientOnly: !1 }) : logger3.warnOnce(
|
|
40
|
+
"[next-ws] unable to ensure page, you may need to open the route in your browser first so Next.js compiles it"
|
|
41
|
+
);
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
let buildPagePath = nextServer.getPagePath(filename);
|
|
45
|
+
return __require(buildPagePath);
|
|
46
|
+
}
|
|
47
|
+
__name(getPageModule, "getPageModule");
|
|
48
|
+
function mainProcessOnly(fnName) {
|
|
49
|
+
if (process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK === "1") return;
|
|
50
|
+
let meta = getEnvironmentMeta();
|
|
51
|
+
if (meta.isMainProcess)
|
|
52
|
+
meta.isCustomServer || logger3.warnOnce(
|
|
53
|
+
`[next-ws] Caution: The function '${fnName}' was invoked without a custom server.
|
|
54
|
+
This could lead to unintended behaviour, especially if you're attempting to interact with the WebSocket server outside of a SOCKET handler. Please note, while such configurations might function during development, they are likely to fail in production environments. 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.`
|
|
55
|
+
);
|
|
56
|
+
else throw new Error(
|
|
57
|
+
`[next-ws] Attempt to invoke '${fnName}' outside the main process.
|
|
58
|
+
You may be attempting to interact with the WebSocket server outside of a SOCKET handler. This is likely to fail in production environments, as Next.js employs a worker process for routing in production, which do not have access to the WebSocket server on the main process.`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
__name(mainProcessOnly, "mainProcessOnly");
|
|
62
|
+
var NextWsHttpServer = Symbol.for("NextWs_HttpServer");
|
|
63
|
+
function setHttpServer(server) {
|
|
64
|
+
Reflect.set(globalThis, NextWsHttpServer, server);
|
|
65
|
+
}
|
|
66
|
+
__name(setHttpServer, "setHttpServer");
|
|
67
|
+
function getHttpServer() {
|
|
68
|
+
return mainProcessOnly("getHttpServer"), Reflect.get(globalThis, NextWsHttpServer);
|
|
69
|
+
}
|
|
70
|
+
__name(getHttpServer, "getHttpServer");
|
|
71
|
+
function useHttpServer(server) {
|
|
72
|
+
let existing = getHttpServer();
|
|
73
|
+
return existing || (server && setHttpServer(server), server);
|
|
74
|
+
}
|
|
75
|
+
__name(useHttpServer, "useHttpServer");
|
|
76
|
+
var NextWsWebSocketServer = Symbol.for("NextWs_WebSocketServer");
|
|
77
|
+
function setWebSocketServer(wsServer) {
|
|
78
|
+
Reflect.set(globalThis, NextWsWebSocketServer, wsServer);
|
|
79
|
+
}
|
|
80
|
+
__name(setWebSocketServer, "setWebSocketServer");
|
|
81
|
+
function getWebSocketServer() {
|
|
82
|
+
return mainProcessOnly("getWebSocketServer"), Reflect.get(globalThis, NextWsWebSocketServer);
|
|
83
|
+
}
|
|
84
|
+
__name(getWebSocketServer, "getWebSocketServer");
|
|
85
|
+
function useWebSocketServer(wsServer) {
|
|
86
|
+
let existing = getWebSocketServer();
|
|
87
|
+
return existing || (wsServer && setWebSocketServer(wsServer), wsServer);
|
|
88
|
+
}
|
|
89
|
+
__name(useWebSocketServer, "useWebSocketServer");
|
|
90
|
+
|
|
91
|
+
// src/server/setup.ts
|
|
92
|
+
function setupWebSocketServer(nextServer) {
|
|
93
|
+
process.env.NEXT_WS_MAIN_PROCESS = String(1), process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK = String(1);
|
|
94
|
+
let httpServer = useHttpServer(nextServer.serverOptions?.httpServer), wsServer = useWebSocketServer(new WebSocketServer({ noServer: !0 }));
|
|
95
|
+
if (delete process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK, !httpServer)
|
|
96
|
+
return logger3.error("[next-ws] was not able to find the HTTP server");
|
|
97
|
+
if (!wsServer)
|
|
98
|
+
return logger3.error("[next-ws] was not able to find the WebSocket server");
|
|
99
|
+
logger3.ready("[next-ws] has started the WebSocket server"), httpServer.on("upgrade", async (request, socket, head) => {
|
|
100
|
+
let pathname = new URL(request.url ?? "", "ws://next").pathname;
|
|
101
|
+
if (pathname.startsWith("/_next")) return;
|
|
102
|
+
let filename = resolveFilename(nextServer, pathname);
|
|
103
|
+
if (!filename)
|
|
104
|
+
return logger3.error(`[next-ws] could not find module for page ${pathname}`), socket.destroy();
|
|
105
|
+
let pageModule = await getPageModule(nextServer, filename);
|
|
106
|
+
if (!pageModule)
|
|
107
|
+
return logger3.error(`[next-ws] could not find module for page ${pathname}`), socket.destroy();
|
|
108
|
+
let socketHandler = pageModule?.routeModule?.userland?.SOCKET;
|
|
109
|
+
return !socketHandler || typeof socketHandler != "function" ? (logger3.error(`[next-ws] ${pathname} does not export a SOCKET handler`), socket.destroy()) : wsServer.handleUpgrade(request, socket, head, (c, r) => {
|
|
110
|
+
let dispose = socketHandler(c, r, wsServer);
|
|
111
|
+
typeof dispose == "function" && c.once("close", () => dispose());
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
__name(setupWebSocketServer, "setupWebSocketServer");
|
|
116
|
+
function hookNextNodeServer() {
|
|
117
|
+
setupWebSocketServer(this);
|
|
118
|
+
}
|
|
119
|
+
__name(hookNextNodeServer, "hookNextNodeServer");
|
|
120
|
+
|
|
121
|
+
// src/server/index.ts
|
|
122
|
+
function verifyPatch() {
|
|
123
|
+
throw new Error(
|
|
124
|
+
"The 'verifyPatch' function has been deprecated in favour of the `npx next-ws-cli@latest verify` command."
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
__name(verifyPatch, "verifyPatch");
|
|
128
|
+
|
|
129
|
+
export { getHttpServer, getWebSocketServer, hookNextNodeServer, setHttpServer, setWebSocketServer, setupWebSocketServer, verifyPatch };
|
|
130
|
+
//# sourceMappingURL=out.js.map
|
|
131
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/setup.ts","../../src/server/helpers/next.ts","../../src/server/helpers/persistent.ts","../../src/server/index.ts"],"names":["logger"],"mappings":"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","sourcesContent":["import * as logger from 'next/dist/build/output/log';\nimport type NextNodeServer from 'next/dist/server/next-server';\nimport { WebSocketServer } from 'ws';\nimport { getPageModule, resolveFilename } from './helpers/next';\nimport { useHttpServer, useWebSocketServer } from './helpers/persistent';\n\nexport function setupWebSocketServer(nextServer: NextNodeServer) {\n process.env.NEXT_WS_MAIN_PROCESS = String(1);\n\n process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK = String(1);\n // @ts-expect-error - serverOptions is protected\n const httpServer = useHttpServer(nextServer.serverOptions?.httpServer);\n const wsServer = useWebSocketServer(new WebSocketServer({ noServer: true }));\n // biome-ignore lint/performance/noDelete: <explanation>\n delete process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK;\n\n if (!httpServer)\n return logger.error('[next-ws] was not able to find the HTTP server');\n if (!wsServer)\n return logger.error('[next-ws] was not able to find the WebSocket server');\n\n logger.ready('[next-ws] has started the WebSocket server');\n\n httpServer.on('upgrade', async (request, socket, head) => {\n const url = new URL(request.url ?? '', 'ws://next');\n const pathname = url.pathname;\n if (pathname.startsWith('/_next')) return;\n\n const filename = resolveFilename(nextServer, pathname);\n if (!filename) {\n logger.error(`[next-ws] could not find module for page ${pathname}`);\n return socket.destroy();\n }\n\n const pageModule = await getPageModule(nextServer, filename);\n if (!pageModule) {\n logger.error(`[next-ws] could not find module for page ${pathname}`);\n return socket.destroy();\n }\n\n const socketHandler = pageModule?.routeModule?.userland?.SOCKET;\n if (!socketHandler || typeof socketHandler !== 'function') {\n logger.error(`[next-ws] ${pathname} does not export a SOCKET handler`);\n return socket.destroy();\n }\n\n return wsServer.handleUpgrade(request, socket, head, (c, r) => {\n const dispose = socketHandler(c, r, wsServer);\n if (typeof dispose === 'function') c.once('close', () => dispose());\n });\n });\n}\n\n// Next WS versions below 0.2.0 used a different method of setup\n// This remains for backwards compatibility, but may be removed in a future version\nexport function hookNextNodeServer(this: NextNodeServer) {\n setupWebSocketServer(this);\n}\n","import * as logger from 'next/dist/build/output/log';\nimport type NextNodeServer from 'next/dist/server/next-server';\nimport type { SocketHandler } from './persistent';\n\n/**\n * Get the environment metadata.\n * @returns The environment metadata.\n */\nexport function getEnvironmentMeta() {\n const isCustomServer = !process.title.startsWith('next-');\n const isMainProcess = process.env.NEXT_WS_MAIN_PROCESS === '1';\n const isDevelopment = process.env.NODE_ENV === 'development';\n return { isCustomServer, isMainProcess, isDevelopment };\n}\n\n/**\n * Resolve a filename to a page.\n * @param nextServer The NextNodeServer instance.\n * @param pathname The pathname to resolve.\n * @returns The resolved page filename, or null if the page could not be resolved.\n */\nexport function resolveFilename(nextServer: NextNodeServer, pathname: string) {\n const pathParts = pathname.split('/');\n const appRoutes = {\n // @ts-expect-error - appPathRoutes is protected\n ...nextServer.appPathRoutes,\n // @ts-expect-error - getAppPathRoutes is protected\n ...nextServer.getAppPathRoutes(),\n };\n\n for (const [key, [path]] of Object.entries(appRoutes)) {\n const hasDynamic = key.includes('[') && key.includes(']');\n\n if (hasDynamic) {\n const keyParts = key.split('/');\n if (keyParts.length !== pathParts.length) continue;\n\n for (let i = 0; i < keyParts.length; i++) {\n const keyPart = keyParts[i]!;\n const pathPart = pathParts[i]!;\n\n const isDynamic = keyPart.includes('[') && keyPart.includes(']');\n if (isDynamic) keyParts[i] = pathPart;\n if (keyParts[i] !== pathParts[i]) break;\n\n if (i === keyParts.length - 1)\n if (!path?.endsWith('/route')) return path;\n }\n } else {\n if (key !== pathname) continue;\n if (!path?.endsWith('/route')) return null;\n return path;\n }\n }\n\n return null;\n}\n\n/**\n * Get the page module for a page.\n * @param nextServer The NextNodeServer instance.\n * @param filename The filename of the page.\n * @returns The page module.\n */\nexport async function getPageModule(\n nextServer: NextNodeServer,\n filename: string,\n) {\n try {\n // In Next.js 14, hotReloader was removed and ensurePage was moved to NextNodeServer\n if ('hotReloader' in nextServer) {\n // @ts-expect-error - hotReloader only exists in Next.js 13\n await nextServer.hotReloader?.ensurePage({\n page: filename,\n clientOnly: false,\n });\n } else if ('ensurePage' in nextServer) {\n // ensurePage throws an error in production, so we need to catch it\n // @ts-expect-error - ensurePage is protected\n await nextServer.ensurePage({ page: filename, clientOnly: false });\n } else {\n // Future-proofing\n logger.warnOnce(\n '[next-ws] unable to ensure page, you may need to open the route in your browser first so Next.js compiles it',\n );\n }\n } catch {}\n\n // @ts-expect-error - getPageModule is protected\n const buildPagePath = nextServer.getPagePath(filename);\n return require(buildPagePath) as PageModule;\n}\n\nexport interface PageModule {\n routeModule?: {\n userland?: {\n SOCKET?: SocketHandler;\n };\n };\n}\n","import * as logger from 'next/dist/build/output/log';\nimport { getEnvironmentMeta } from './next';\n\nfunction mainProcessOnly(fnName: string) {\n if (process.env.NEXT_WS_SKIP_ENVIRONMENT_CHECK === '1') return;\n\n const meta = getEnvironmentMeta();\n if (!meta.isMainProcess) {\n throw new Error(\n `[next-ws] Attempt to invoke '${fnName}' outside the main process.\nYou may be attempting to interact with the WebSocket server outside of a SOCKET handler. This is likely to fail in production environments, as Next.js employs a worker process for routing in production, which do not have access to the WebSocket server on the main process.`,\n );\n } else if (!meta.isCustomServer) {\n logger.warnOnce(\n `[next-ws] Caution: The function '${fnName}' was invoked without a custom server.\nThis could lead to unintended behaviour, especially if you're attempting to interact with the WebSocket server outside of a SOCKET handler. Please note, while such configurations might function during development, they are likely to fail in production environments. 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.`,\n );\n }\n}\n\n// ========== HTTP Server ==========\n\nimport type { Server as HttpServer } from 'node:http';\nexport const NextWsHttpServer = Symbol.for('NextWs_HttpServer');\n\n/**\n * Set the HTTP server that the WebSocket server should listen on, must be called before the WebSocket server is created.\n * @param server The HTTP server.\n */\nexport function setHttpServer(server: HttpServer) {\n Reflect.set(globalThis, NextWsHttpServer, server);\n}\n\n/**\n * Get the HTTP server that the WebSocket server is listening on.\n * @remark If you want to access the HTTP server outside of a SOCKET handler, you must be using a custom server.\n * @returns The HTTP server.\n * @throws If attempting to access the HTTP server outside of the main process.\n */\nexport function getHttpServer() {\n mainProcessOnly('getHttpServer');\n return Reflect.get(globalThis, NextWsHttpServer) as HttpServer;\n}\n\nexport function useHttpServer(server?: HttpServer) {\n const existing = getHttpServer();\n if (existing) return existing;\n if (server) setHttpServer(server);\n return server;\n}\n\n// ========== WebSocket Server ==========\n\nimport type { WebSocketServer } from 'ws';\nexport const NextWsWebSocketServer = Symbol.for('NextWs_WebSocketServer');\n\n/**\n * Set the WebSocket server that the WebSocket server should listen on, must be called before the WebSocket server is created.\n * @param wsServer The WebSocket server.\n */\nexport function setWebSocketServer(wsServer: WebSocketServer) {\n Reflect.set(globalThis, NextWsWebSocketServer, wsServer);\n}\n\n/**\n * Get the WebSocket server that the WebSocket server is listening on.\n * @remark If you want to access the WebSocket server outside of a SOCKET handler, you must be using a custom server.\n * @returns The WebSocket server.\n * @throws If attempting to access the WebSocket server outside of the main process.\n */\nexport function getWebSocketServer() {\n mainProcessOnly('getWebSocketServer');\n return Reflect.get(globalThis, NextWsWebSocketServer) as WebSocketServer;\n}\n\nexport function useWebSocketServer(wsServer?: WebSocketServer) {\n const existing = getWebSocketServer();\n if (existing) return existing;\n if (wsServer) setWebSocketServer(wsServer);\n return wsServer;\n}\n\n/** A function that handles a WebSocket connection. */\nexport type SocketHandler = (\n /** The WebSocket client that connected. */\n client: import('ws').WebSocket,\n /** The HTTP request that initiated the WebSocket connection. */\n request: import('http').IncomingMessage,\n /** The WebSocket server. */\n server: import('ws').WebSocketServer,\n) => unknown | (() => void);\n","export * from './setup';\nexport {\n setHttpServer,\n getHttpServer,\n setWebSocketServer,\n getWebSocketServer,\n} from './helpers/persistent';\n\n/**\n * @deprecated\n */\nexport function verifyPatch() {\n throw new Error(\n \"The 'verifyPatch' function has been deprecated in favour of the `npx next-ws-cli@latest verify` command.\",\n );\n}\n"]}
|