elit 2.0.1 → 3.0.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 +275 -128
- package/dist/build.d.mts +10 -1
- package/dist/build.d.ts +10 -1
- package/dist/build.js +670 -1
- package/dist/build.mjs +641 -1
- package/dist/chokidar.d.mts +134 -0
- package/dist/chokidar.d.ts +134 -0
- package/dist/chokidar.js +240 -0
- package/dist/chokidar.mjs +221 -0
- package/dist/cli.js +2792 -495
- package/dist/dom.d.mts +10 -3
- package/dist/dom.d.ts +10 -3
- package/dist/dom.js +676 -1
- package/dist/dom.mjs +647 -1
- package/dist/el.d.mts +16 -36
- package/dist/el.d.ts +16 -36
- package/dist/el.js +789 -1
- package/dist/el.mjs +583 -1
- package/dist/fs.d.mts +255 -0
- package/dist/fs.d.ts +255 -0
- package/dist/fs.js +513 -0
- package/dist/fs.mjs +469 -0
- package/dist/hmr.js +112 -1
- package/dist/hmr.mjs +91 -1
- package/dist/http.d.mts +163 -0
- package/dist/http.d.ts +163 -0
- package/dist/http.js +632 -0
- package/dist/http.mjs +605 -0
- package/dist/https.d.mts +108 -0
- package/dist/https.d.ts +108 -0
- package/dist/https.js +907 -0
- package/dist/https.mjs +901 -0
- package/dist/index.d.mts +613 -33
- package/dist/index.d.ts +613 -33
- package/dist/index.js +2589 -1
- package/dist/index.mjs +2312 -1
- package/dist/mime-types.d.mts +48 -0
- package/dist/mime-types.d.ts +48 -0
- package/dist/mime-types.js +197 -0
- package/dist/mime-types.mjs +166 -0
- package/dist/path.d.mts +163 -0
- package/dist/path.d.ts +163 -0
- package/dist/path.js +350 -0
- package/dist/path.mjs +310 -0
- package/dist/router.d.mts +3 -1
- package/dist/router.d.ts +3 -1
- package/dist/router.js +830 -1
- package/dist/router.mjs +801 -1
- package/dist/runtime.d.mts +97 -0
- package/dist/runtime.d.ts +97 -0
- package/dist/runtime.js +43 -0
- package/dist/runtime.mjs +15 -0
- package/dist/server.d.mts +5 -1
- package/dist/server.d.ts +5 -1
- package/dist/server.js +3267 -1
- package/dist/server.mjs +3241 -1
- package/dist/state.d.mts +3 -1
- package/dist/state.d.ts +3 -1
- package/dist/state.js +1036 -1
- package/dist/state.mjs +992 -1
- package/dist/style.d.mts +47 -1
- package/dist/style.d.ts +47 -1
- package/dist/style.js +551 -1
- package/dist/style.mjs +483 -1
- package/dist/{types-DOAdFFJB.d.ts → types-C0nGi6MX.d.mts} +29 -13
- package/dist/{types-DOAdFFJB.d.mts → types-Du6kfwTm.d.ts} +29 -13
- package/dist/types.d.mts +452 -3
- package/dist/types.d.ts +452 -3
- package/dist/types.js +18 -1
- package/dist/ws.d.mts +195 -0
- package/dist/ws.d.ts +195 -0
- package/dist/ws.js +380 -0
- package/dist/ws.mjs +358 -0
- package/dist/wss.d.mts +108 -0
- package/dist/wss.d.ts +108 -0
- package/dist/wss.js +1306 -0
- package/dist/wss.mjs +1300 -0
- package/package.json +53 -6
- package/dist/client.d.mts +0 -9
- package/dist/client.d.ts +0 -9
- package/dist/client.js +0 -1
- package/dist/client.mjs +0 -1
package/dist/ws.d.ts
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { IncomingMessage } from './http.js';
|
|
3
|
+
import 'node:events';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* WebSocket module with unified API across runtimes
|
|
7
|
+
* Pure implementation without external dependencies
|
|
8
|
+
* - Node.js: uses native 'ws' module (built-in WebSocket implementation)
|
|
9
|
+
* - Bun: uses native WebSocket
|
|
10
|
+
* - Deno: uses native WebSocket
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* WebSocket ready state
|
|
15
|
+
*/
|
|
16
|
+
declare enum ReadyState {
|
|
17
|
+
CONNECTING = 0,
|
|
18
|
+
OPEN = 1,
|
|
19
|
+
CLOSING = 2,
|
|
20
|
+
CLOSED = 3
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* WebSocket close codes
|
|
24
|
+
*/
|
|
25
|
+
declare const CLOSE_CODES: {
|
|
26
|
+
readonly NORMAL: 1000;
|
|
27
|
+
readonly GOING_AWAY: 1001;
|
|
28
|
+
readonly PROTOCOL_ERROR: 1002;
|
|
29
|
+
readonly UNSUPPORTED_DATA: 1003;
|
|
30
|
+
readonly NO_STATUS: 1005;
|
|
31
|
+
readonly ABNORMAL: 1006;
|
|
32
|
+
readonly INVALID_DATA: 1007;
|
|
33
|
+
readonly POLICY_VIOLATION: 1008;
|
|
34
|
+
readonly MESSAGE_TOO_BIG: 1009;
|
|
35
|
+
readonly EXTENSION_REQUIRED: 1010;
|
|
36
|
+
readonly INTERNAL_ERROR: 1011;
|
|
37
|
+
readonly SERVICE_RESTART: 1012;
|
|
38
|
+
readonly TRY_AGAIN_LATER: 1013;
|
|
39
|
+
readonly BAD_GATEWAY: 1014;
|
|
40
|
+
readonly TLS_HANDSHAKE_FAIL: 1015;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* WebSocket data types
|
|
44
|
+
*/
|
|
45
|
+
type Data = string | Buffer | ArrayBuffer | Buffer[];
|
|
46
|
+
/**
|
|
47
|
+
* WebSocket send options
|
|
48
|
+
*/
|
|
49
|
+
interface SendOptions {
|
|
50
|
+
binary?: boolean;
|
|
51
|
+
compress?: boolean;
|
|
52
|
+
fin?: boolean;
|
|
53
|
+
mask?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* WebSocket server options
|
|
57
|
+
*/
|
|
58
|
+
interface ServerOptions {
|
|
59
|
+
host?: string;
|
|
60
|
+
port?: number;
|
|
61
|
+
backlog?: number;
|
|
62
|
+
server?: any;
|
|
63
|
+
verifyClient?: VerifyClientCallback;
|
|
64
|
+
handleProtocols?: (protocols: Set<string>, request: IncomingMessage) => string | false;
|
|
65
|
+
path?: string;
|
|
66
|
+
noServer?: boolean;
|
|
67
|
+
clientTracking?: boolean;
|
|
68
|
+
perMessageDeflate?: boolean | object;
|
|
69
|
+
maxPayload?: number;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Verify client callback
|
|
73
|
+
*/
|
|
74
|
+
type VerifyClientCallback = (info: {
|
|
75
|
+
origin: string;
|
|
76
|
+
secure: boolean;
|
|
77
|
+
req: IncomingMessage;
|
|
78
|
+
}, callback?: (result: boolean, code?: number, message?: string) => void) => boolean | void;
|
|
79
|
+
/**
|
|
80
|
+
* WebSocket class - Pure implementation
|
|
81
|
+
*/
|
|
82
|
+
declare class WebSocket extends EventEmitter {
|
|
83
|
+
readyState: ReadyState;
|
|
84
|
+
url: string;
|
|
85
|
+
protocol: string;
|
|
86
|
+
extensions: string;
|
|
87
|
+
binaryType: 'nodebuffer' | 'arraybuffer' | 'fragments';
|
|
88
|
+
/** @internal */
|
|
89
|
+
_socket: any;
|
|
90
|
+
constructor(address: string | URL, protocols?: string | string[], _options?: any);
|
|
91
|
+
private _setupNativeSocket;
|
|
92
|
+
/**
|
|
93
|
+
* Send data through WebSocket
|
|
94
|
+
*/
|
|
95
|
+
send(data: Data, options?: SendOptions | ((err?: Error) => void), callback?: (err?: Error) => void): void;
|
|
96
|
+
/**
|
|
97
|
+
* Close the WebSocket connection
|
|
98
|
+
*/
|
|
99
|
+
close(code?: number, reason?: string | Buffer): void;
|
|
100
|
+
/**
|
|
101
|
+
* Pause the socket (no-op for native WebSocket)
|
|
102
|
+
*/
|
|
103
|
+
pause(): void;
|
|
104
|
+
/**
|
|
105
|
+
* Resume the socket (no-op for native WebSocket)
|
|
106
|
+
*/
|
|
107
|
+
resume(): void;
|
|
108
|
+
/**
|
|
109
|
+
* Send a ping frame (no-op for native WebSocket)
|
|
110
|
+
*/
|
|
111
|
+
ping(_data?: Data, _mask?: boolean, callback?: (err?: Error) => void): void;
|
|
112
|
+
/**
|
|
113
|
+
* Send a pong frame (no-op for native WebSocket)
|
|
114
|
+
*/
|
|
115
|
+
pong(_data?: Data, _mask?: boolean, callback?: (err?: Error) => void): void;
|
|
116
|
+
/**
|
|
117
|
+
* Terminate the connection
|
|
118
|
+
*/
|
|
119
|
+
terminate(): void;
|
|
120
|
+
/**
|
|
121
|
+
* Get buffered amount
|
|
122
|
+
*/
|
|
123
|
+
get bufferedAmount(): number;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* WebSocket Server - Server-side WebSocket implementation
|
|
127
|
+
*/
|
|
128
|
+
declare class WebSocketServer extends EventEmitter {
|
|
129
|
+
clients: Set<WebSocket>;
|
|
130
|
+
options: ServerOptions;
|
|
131
|
+
path: string;
|
|
132
|
+
private _httpServer;
|
|
133
|
+
constructor(options?: ServerOptions, callback?: () => void);
|
|
134
|
+
private _setupUpgradeHandler;
|
|
135
|
+
/**
|
|
136
|
+
* Handle HTTP upgrade for WebSocket
|
|
137
|
+
*/
|
|
138
|
+
handleUpgrade(request: IncomingMessage, socket: any, _head: Buffer, callback: (client: WebSocket) => void): void;
|
|
139
|
+
private _createClientFromSocket;
|
|
140
|
+
private _parseFrame;
|
|
141
|
+
private _createFrame;
|
|
142
|
+
/**
|
|
143
|
+
* Close the server
|
|
144
|
+
*/
|
|
145
|
+
close(callback?: (err?: Error) => void): void;
|
|
146
|
+
/**
|
|
147
|
+
* Check if server should handle request
|
|
148
|
+
*/
|
|
149
|
+
shouldHandle(request: IncomingMessage): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Get server address
|
|
152
|
+
*/
|
|
153
|
+
address(): {
|
|
154
|
+
port: number;
|
|
155
|
+
family: string;
|
|
156
|
+
address: string;
|
|
157
|
+
} | null;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Create WebSocket server
|
|
161
|
+
*/
|
|
162
|
+
declare function createWebSocketServer(options?: ServerOptions, callback?: () => void): WebSocketServer;
|
|
163
|
+
/**
|
|
164
|
+
* Get current runtime
|
|
165
|
+
*/
|
|
166
|
+
declare function getRuntime(): 'node' | 'bun' | 'deno';
|
|
167
|
+
/**
|
|
168
|
+
* Default export
|
|
169
|
+
*/
|
|
170
|
+
declare const _default: {
|
|
171
|
+
WebSocket: typeof WebSocket;
|
|
172
|
+
WebSocketServer: typeof WebSocketServer;
|
|
173
|
+
createWebSocketServer: typeof createWebSocketServer;
|
|
174
|
+
ReadyState: typeof ReadyState;
|
|
175
|
+
CLOSE_CODES: {
|
|
176
|
+
readonly NORMAL: 1000;
|
|
177
|
+
readonly GOING_AWAY: 1001;
|
|
178
|
+
readonly PROTOCOL_ERROR: 1002;
|
|
179
|
+
readonly UNSUPPORTED_DATA: 1003;
|
|
180
|
+
readonly NO_STATUS: 1005;
|
|
181
|
+
readonly ABNORMAL: 1006;
|
|
182
|
+
readonly INVALID_DATA: 1007;
|
|
183
|
+
readonly POLICY_VIOLATION: 1008;
|
|
184
|
+
readonly MESSAGE_TOO_BIG: 1009;
|
|
185
|
+
readonly EXTENSION_REQUIRED: 1010;
|
|
186
|
+
readonly INTERNAL_ERROR: 1011;
|
|
187
|
+
readonly SERVICE_RESTART: 1012;
|
|
188
|
+
readonly TRY_AGAIN_LATER: 1013;
|
|
189
|
+
readonly BAD_GATEWAY: 1014;
|
|
190
|
+
readonly TLS_HANDSHAKE_FAIL: 1015;
|
|
191
|
+
};
|
|
192
|
+
getRuntime: typeof getRuntime;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export { CLOSE_CODES, type Data, ReadyState, type SendOptions, type ServerOptions, type VerifyClientCallback, WebSocket, WebSocketServer, createWebSocketServer, _default as default, getRuntime };
|
package/dist/ws.js
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/ws.ts
|
|
21
|
+
var ws_exports = {};
|
|
22
|
+
__export(ws_exports, {
|
|
23
|
+
CLOSE_CODES: () => CLOSE_CODES,
|
|
24
|
+
ReadyState: () => ReadyState,
|
|
25
|
+
WebSocket: () => WebSocket,
|
|
26
|
+
WebSocketServer: () => WebSocketServer,
|
|
27
|
+
createWebSocketServer: () => createWebSocketServer,
|
|
28
|
+
default: () => ws_default,
|
|
29
|
+
getRuntime: () => getRuntime
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(ws_exports);
|
|
32
|
+
var import_events = require("events");
|
|
33
|
+
|
|
34
|
+
// src/runtime.ts
|
|
35
|
+
var runtime = (() => {
|
|
36
|
+
if (typeof Deno !== "undefined") return "deno";
|
|
37
|
+
if (typeof Bun !== "undefined") return "bun";
|
|
38
|
+
return "node";
|
|
39
|
+
})();
|
|
40
|
+
|
|
41
|
+
// src/ws.ts
|
|
42
|
+
var ReadyState = /* @__PURE__ */ ((ReadyState2) => {
|
|
43
|
+
ReadyState2[ReadyState2["CONNECTING"] = 0] = "CONNECTING";
|
|
44
|
+
ReadyState2[ReadyState2["OPEN"] = 1] = "OPEN";
|
|
45
|
+
ReadyState2[ReadyState2["CLOSING"] = 2] = "CLOSING";
|
|
46
|
+
ReadyState2[ReadyState2["CLOSED"] = 3] = "CLOSED";
|
|
47
|
+
return ReadyState2;
|
|
48
|
+
})(ReadyState || {});
|
|
49
|
+
var CLOSE_CODES = {
|
|
50
|
+
NORMAL: 1e3,
|
|
51
|
+
GOING_AWAY: 1001,
|
|
52
|
+
PROTOCOL_ERROR: 1002,
|
|
53
|
+
UNSUPPORTED_DATA: 1003,
|
|
54
|
+
NO_STATUS: 1005,
|
|
55
|
+
ABNORMAL: 1006,
|
|
56
|
+
INVALID_DATA: 1007,
|
|
57
|
+
POLICY_VIOLATION: 1008,
|
|
58
|
+
MESSAGE_TOO_BIG: 1009,
|
|
59
|
+
EXTENSION_REQUIRED: 1010,
|
|
60
|
+
INTERNAL_ERROR: 1011,
|
|
61
|
+
SERVICE_RESTART: 1012,
|
|
62
|
+
TRY_AGAIN_LATER: 1013,
|
|
63
|
+
BAD_GATEWAY: 1014,
|
|
64
|
+
TLS_HANDSHAKE_FAIL: 1015
|
|
65
|
+
};
|
|
66
|
+
function queueCallback(callback, error) {
|
|
67
|
+
if (callback) {
|
|
68
|
+
queueMicrotask(() => callback(error));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function createNativeWebSocket(url, protocols) {
|
|
72
|
+
if (runtime === "node" && typeof globalThis.WebSocket === "undefined") {
|
|
73
|
+
throw new Error("WebSocket is not available. Please use Node.js 18+ or install ws package.");
|
|
74
|
+
}
|
|
75
|
+
return new globalThis.WebSocket(url, protocols);
|
|
76
|
+
}
|
|
77
|
+
var WebSocket = class extends import_events.EventEmitter {
|
|
78
|
+
constructor(address, protocols, _options) {
|
|
79
|
+
super();
|
|
80
|
+
this.readyState = 0 /* CONNECTING */;
|
|
81
|
+
this.protocol = "";
|
|
82
|
+
this.extensions = "";
|
|
83
|
+
this.binaryType = "nodebuffer";
|
|
84
|
+
this.url = typeof address === "string" ? address : address.toString();
|
|
85
|
+
const protocolsArray = Array.isArray(protocols) ? protocols : protocols ? [protocols] : void 0;
|
|
86
|
+
this._socket = createNativeWebSocket(this.url, protocolsArray);
|
|
87
|
+
this._setupNativeSocket();
|
|
88
|
+
}
|
|
89
|
+
_setupNativeSocket() {
|
|
90
|
+
this._socket.onopen = () => {
|
|
91
|
+
this.readyState = 1 /* OPEN */;
|
|
92
|
+
this.emit("open");
|
|
93
|
+
};
|
|
94
|
+
this._socket.onmessage = (event) => {
|
|
95
|
+
const isBinary = event.data instanceof ArrayBuffer || event.data instanceof Blob;
|
|
96
|
+
this.emit("message", event.data, isBinary);
|
|
97
|
+
};
|
|
98
|
+
this._socket.onclose = (event) => {
|
|
99
|
+
this.readyState = 3 /* CLOSED */;
|
|
100
|
+
this.emit("close", event.code, event.reason);
|
|
101
|
+
};
|
|
102
|
+
this._socket.onerror = () => {
|
|
103
|
+
this.emit("error", new Error("WebSocket error"));
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Send data through WebSocket
|
|
108
|
+
*/
|
|
109
|
+
send(data, options, callback) {
|
|
110
|
+
const cb = typeof options === "function" ? options : callback;
|
|
111
|
+
if (this.readyState !== 1 /* OPEN */) {
|
|
112
|
+
return queueCallback(cb, new Error("WebSocket is not open"));
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
this._socket.send(data);
|
|
116
|
+
queueCallback(cb);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
queueCallback(cb, error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Close the WebSocket connection
|
|
123
|
+
*/
|
|
124
|
+
close(code, reason) {
|
|
125
|
+
if (this.readyState === 3 /* CLOSED */ || this.readyState === 2 /* CLOSING */) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
this.readyState = 2 /* CLOSING */;
|
|
129
|
+
this._socket.close(code, typeof reason === "string" ? reason : reason?.toString());
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Pause the socket (no-op for native WebSocket)
|
|
133
|
+
*/
|
|
134
|
+
pause() {
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Resume the socket (no-op for native WebSocket)
|
|
138
|
+
*/
|
|
139
|
+
resume() {
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Send a ping frame (no-op for native WebSocket)
|
|
143
|
+
*/
|
|
144
|
+
ping(_data, _mask, callback) {
|
|
145
|
+
queueCallback(callback);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Send a pong frame (no-op for native WebSocket)
|
|
149
|
+
*/
|
|
150
|
+
pong(_data, _mask, callback) {
|
|
151
|
+
queueCallback(callback);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Terminate the connection
|
|
155
|
+
*/
|
|
156
|
+
terminate() {
|
|
157
|
+
this._socket.close();
|
|
158
|
+
this.readyState = 3 /* CLOSED */;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get buffered amount
|
|
162
|
+
*/
|
|
163
|
+
get bufferedAmount() {
|
|
164
|
+
return this._socket.bufferedAmount || 0;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
var WebSocketServer = class extends import_events.EventEmitter {
|
|
168
|
+
constructor(options, callback) {
|
|
169
|
+
super();
|
|
170
|
+
this.clients = /* @__PURE__ */ new Set();
|
|
171
|
+
this.options = options || {};
|
|
172
|
+
this.path = options?.path || "/";
|
|
173
|
+
if (runtime === "node") {
|
|
174
|
+
if (options?.server) {
|
|
175
|
+
this._httpServer = options.server;
|
|
176
|
+
this._setupUpgradeHandler();
|
|
177
|
+
} else if (options?.noServer) {
|
|
178
|
+
} else {
|
|
179
|
+
const http = require("http");
|
|
180
|
+
this._httpServer = http.createServer();
|
|
181
|
+
this._setupUpgradeHandler();
|
|
182
|
+
if (options?.port) {
|
|
183
|
+
this._httpServer.listen(options.port, options.host, callback);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
queueCallback(callback);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
_setupUpgradeHandler() {
|
|
191
|
+
this._httpServer.on("upgrade", (request, socket, head) => {
|
|
192
|
+
console.log("[WebSocket] Upgrade request:", request.url, "Expected:", this.path);
|
|
193
|
+
if (this.path && this.path !== "/" && request.url !== this.path) {
|
|
194
|
+
console.log("[WebSocket] Path mismatch, ignoring");
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
this.handleUpgrade(request, socket, head, (client) => {
|
|
198
|
+
console.log("[WebSocket] Client connected");
|
|
199
|
+
this.emit("connection", client, request);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Handle HTTP upgrade for WebSocket
|
|
205
|
+
*/
|
|
206
|
+
handleUpgrade(request, socket, _head, callback) {
|
|
207
|
+
const key = request.headers["sec-websocket-key"];
|
|
208
|
+
if (!key) {
|
|
209
|
+
socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const crypto = require("crypto");
|
|
213
|
+
const acceptKey = crypto.createHash("sha1").update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64");
|
|
214
|
+
const headers = [
|
|
215
|
+
"HTTP/1.1 101 Switching Protocols",
|
|
216
|
+
"Upgrade: websocket",
|
|
217
|
+
"Connection: Upgrade",
|
|
218
|
+
`Sec-WebSocket-Accept: ${acceptKey}`,
|
|
219
|
+
"",
|
|
220
|
+
""
|
|
221
|
+
];
|
|
222
|
+
socket.write(headers.join("\r\n"));
|
|
223
|
+
const client = this._createClientFromSocket(socket);
|
|
224
|
+
if (this.options.clientTracking !== false) {
|
|
225
|
+
this.clients.add(client);
|
|
226
|
+
client.on("close", () => {
|
|
227
|
+
this.clients.delete(client);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
callback(client);
|
|
231
|
+
}
|
|
232
|
+
_createClientFromSocket(socket) {
|
|
233
|
+
const client = Object.create(WebSocket.prototype);
|
|
234
|
+
import_events.EventEmitter.call(client);
|
|
235
|
+
client.readyState = 1 /* OPEN */;
|
|
236
|
+
client.url = "ws://localhost";
|
|
237
|
+
client.protocol = "";
|
|
238
|
+
client.extensions = "";
|
|
239
|
+
client.binaryType = "nodebuffer";
|
|
240
|
+
client._socket = socket;
|
|
241
|
+
socket.on("data", (data) => {
|
|
242
|
+
try {
|
|
243
|
+
const message = this._parseFrame(data);
|
|
244
|
+
if (message) {
|
|
245
|
+
client.emit("message", message, false);
|
|
246
|
+
}
|
|
247
|
+
} catch (error) {
|
|
248
|
+
client.emit("error", error);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
socket.on("end", () => {
|
|
252
|
+
client.readyState = 3 /* CLOSED */;
|
|
253
|
+
client.emit("close", CLOSE_CODES.NORMAL, "");
|
|
254
|
+
});
|
|
255
|
+
socket.on("error", (error) => {
|
|
256
|
+
client.emit("error", error);
|
|
257
|
+
});
|
|
258
|
+
client.send = (data, _options, callback) => {
|
|
259
|
+
try {
|
|
260
|
+
const frame = this._createFrame(data);
|
|
261
|
+
socket.write(frame);
|
|
262
|
+
queueCallback(callback);
|
|
263
|
+
} catch (error) {
|
|
264
|
+
queueCallback(callback, error);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
client.close = (_code, _reason) => {
|
|
268
|
+
socket.end();
|
|
269
|
+
client.readyState = 3 /* CLOSED */;
|
|
270
|
+
};
|
|
271
|
+
return client;
|
|
272
|
+
}
|
|
273
|
+
_parseFrame(data) {
|
|
274
|
+
if (data.length < 2) return null;
|
|
275
|
+
const firstByte = data[0];
|
|
276
|
+
const secondByte = data[1];
|
|
277
|
+
const opcode = firstByte & 15;
|
|
278
|
+
const isMasked = (secondByte & 128) === 128;
|
|
279
|
+
let payloadLength = secondByte & 127;
|
|
280
|
+
let offset = 2;
|
|
281
|
+
if (payloadLength === 126) {
|
|
282
|
+
payloadLength = data.readUInt16BE(2);
|
|
283
|
+
offset = 4;
|
|
284
|
+
} else if (payloadLength === 127) {
|
|
285
|
+
payloadLength = Number(data.readBigUInt64BE(2));
|
|
286
|
+
offset = 10;
|
|
287
|
+
}
|
|
288
|
+
let payload = data.subarray(offset);
|
|
289
|
+
if (isMasked) {
|
|
290
|
+
const maskKey = data.subarray(offset, offset + 4);
|
|
291
|
+
payload = data.subarray(offset + 4, offset + 4 + payloadLength);
|
|
292
|
+
for (let i = 0; i < payload.length; i++) {
|
|
293
|
+
payload[i] ^= maskKey[i % 4];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (opcode === 1) {
|
|
297
|
+
return payload.toString("utf8");
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
_createFrame(data) {
|
|
302
|
+
const payload = typeof data === "string" ? Buffer.from(data) : data;
|
|
303
|
+
const payloadLength = Buffer.isBuffer(payload) ? payload.length : 0;
|
|
304
|
+
let frame;
|
|
305
|
+
let offset = 2;
|
|
306
|
+
if (payloadLength < 126) {
|
|
307
|
+
frame = Buffer.allocUnsafe(2 + payloadLength);
|
|
308
|
+
frame[1] = payloadLength;
|
|
309
|
+
} else if (payloadLength < 65536) {
|
|
310
|
+
frame = Buffer.allocUnsafe(4 + payloadLength);
|
|
311
|
+
frame[1] = 126;
|
|
312
|
+
frame.writeUInt16BE(payloadLength, 2);
|
|
313
|
+
offset = 4;
|
|
314
|
+
} else {
|
|
315
|
+
frame = Buffer.allocUnsafe(10 + payloadLength);
|
|
316
|
+
frame[1] = 127;
|
|
317
|
+
frame.writeBigUInt64BE(BigInt(payloadLength), 2);
|
|
318
|
+
offset = 10;
|
|
319
|
+
}
|
|
320
|
+
frame[0] = 129;
|
|
321
|
+
if (Buffer.isBuffer(payload)) {
|
|
322
|
+
payload.copy(frame, offset);
|
|
323
|
+
}
|
|
324
|
+
return frame;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Close the server
|
|
328
|
+
*/
|
|
329
|
+
close(callback) {
|
|
330
|
+
this.clients.forEach((client) => client.close());
|
|
331
|
+
this.clients.clear();
|
|
332
|
+
if (this._httpServer) {
|
|
333
|
+
this._httpServer.close(callback);
|
|
334
|
+
} else {
|
|
335
|
+
this.emit("close");
|
|
336
|
+
queueCallback(callback);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Check if server should handle request
|
|
341
|
+
*/
|
|
342
|
+
shouldHandle(request) {
|
|
343
|
+
if (this.path && request.url !== this.path) {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Get server address
|
|
350
|
+
*/
|
|
351
|
+
address() {
|
|
352
|
+
if (this._httpServer && this._httpServer.address) {
|
|
353
|
+
return this._httpServer.address();
|
|
354
|
+
}
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
function createWebSocketServer(options, callback) {
|
|
359
|
+
return new WebSocketServer(options, callback);
|
|
360
|
+
}
|
|
361
|
+
function getRuntime() {
|
|
362
|
+
return runtime;
|
|
363
|
+
}
|
|
364
|
+
var ws_default = {
|
|
365
|
+
WebSocket,
|
|
366
|
+
WebSocketServer,
|
|
367
|
+
createWebSocketServer,
|
|
368
|
+
ReadyState,
|
|
369
|
+
CLOSE_CODES,
|
|
370
|
+
getRuntime
|
|
371
|
+
};
|
|
372
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
373
|
+
0 && (module.exports = {
|
|
374
|
+
CLOSE_CODES,
|
|
375
|
+
ReadyState,
|
|
376
|
+
WebSocket,
|
|
377
|
+
WebSocketServer,
|
|
378
|
+
createWebSocketServer,
|
|
379
|
+
getRuntime
|
|
380
|
+
});
|