almostnode 0.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.
Files changed (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +731 -0
  3. package/dist/__sw__.js +394 -0
  4. package/dist/ai-chatbot-demo-entry.d.ts +6 -0
  5. package/dist/ai-chatbot-demo-entry.d.ts.map +1 -0
  6. package/dist/ai-chatbot-demo.d.ts +42 -0
  7. package/dist/ai-chatbot-demo.d.ts.map +1 -0
  8. package/dist/assets/runtime-worker-D9x_Ddwz.js +60543 -0
  9. package/dist/assets/runtime-worker-D9x_Ddwz.js.map +1 -0
  10. package/dist/convex-app-demo-entry.d.ts +6 -0
  11. package/dist/convex-app-demo-entry.d.ts.map +1 -0
  12. package/dist/convex-app-demo.d.ts +68 -0
  13. package/dist/convex-app-demo.d.ts.map +1 -0
  14. package/dist/cors-proxy.d.ts +46 -0
  15. package/dist/cors-proxy.d.ts.map +1 -0
  16. package/dist/create-runtime.d.ts +42 -0
  17. package/dist/create-runtime.d.ts.map +1 -0
  18. package/dist/demo.d.ts +6 -0
  19. package/dist/demo.d.ts.map +1 -0
  20. package/dist/dev-server.d.ts +97 -0
  21. package/dist/dev-server.d.ts.map +1 -0
  22. package/dist/frameworks/next-dev-server.d.ts +202 -0
  23. package/dist/frameworks/next-dev-server.d.ts.map +1 -0
  24. package/dist/frameworks/vite-dev-server.d.ts +85 -0
  25. package/dist/frameworks/vite-dev-server.d.ts.map +1 -0
  26. package/dist/index.cjs +14965 -0
  27. package/dist/index.cjs.map +1 -0
  28. package/dist/index.d.ts +71 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.mjs +14867 -0
  31. package/dist/index.mjs.map +1 -0
  32. package/dist/next-demo.d.ts +49 -0
  33. package/dist/next-demo.d.ts.map +1 -0
  34. package/dist/npm/index.d.ts +71 -0
  35. package/dist/npm/index.d.ts.map +1 -0
  36. package/dist/npm/registry.d.ts +66 -0
  37. package/dist/npm/registry.d.ts.map +1 -0
  38. package/dist/npm/resolver.d.ts +52 -0
  39. package/dist/npm/resolver.d.ts.map +1 -0
  40. package/dist/npm/tarball.d.ts +29 -0
  41. package/dist/npm/tarball.d.ts.map +1 -0
  42. package/dist/runtime-interface.d.ts +90 -0
  43. package/dist/runtime-interface.d.ts.map +1 -0
  44. package/dist/runtime.d.ts +103 -0
  45. package/dist/runtime.d.ts.map +1 -0
  46. package/dist/sandbox-helpers.d.ts +43 -0
  47. package/dist/sandbox-helpers.d.ts.map +1 -0
  48. package/dist/sandbox-runtime.d.ts +65 -0
  49. package/dist/sandbox-runtime.d.ts.map +1 -0
  50. package/dist/server-bridge.d.ts +89 -0
  51. package/dist/server-bridge.d.ts.map +1 -0
  52. package/dist/shims/assert.d.ts +51 -0
  53. package/dist/shims/assert.d.ts.map +1 -0
  54. package/dist/shims/async_hooks.d.ts +37 -0
  55. package/dist/shims/async_hooks.d.ts.map +1 -0
  56. package/dist/shims/buffer.d.ts +20 -0
  57. package/dist/shims/buffer.d.ts.map +1 -0
  58. package/dist/shims/child_process-browser.d.ts +92 -0
  59. package/dist/shims/child_process-browser.d.ts.map +1 -0
  60. package/dist/shims/child_process.d.ts +93 -0
  61. package/dist/shims/child_process.d.ts.map +1 -0
  62. package/dist/shims/chokidar.d.ts +55 -0
  63. package/dist/shims/chokidar.d.ts.map +1 -0
  64. package/dist/shims/cluster.d.ts +52 -0
  65. package/dist/shims/cluster.d.ts.map +1 -0
  66. package/dist/shims/crypto.d.ts +122 -0
  67. package/dist/shims/crypto.d.ts.map +1 -0
  68. package/dist/shims/dgram.d.ts +34 -0
  69. package/dist/shims/dgram.d.ts.map +1 -0
  70. package/dist/shims/diagnostics_channel.d.ts +80 -0
  71. package/dist/shims/diagnostics_channel.d.ts.map +1 -0
  72. package/dist/shims/dns.d.ts +87 -0
  73. package/dist/shims/dns.d.ts.map +1 -0
  74. package/dist/shims/domain.d.ts +25 -0
  75. package/dist/shims/domain.d.ts.map +1 -0
  76. package/dist/shims/esbuild.d.ts +105 -0
  77. package/dist/shims/esbuild.d.ts.map +1 -0
  78. package/dist/shims/events.d.ts +37 -0
  79. package/dist/shims/events.d.ts.map +1 -0
  80. package/dist/shims/fs.d.ts +115 -0
  81. package/dist/shims/fs.d.ts.map +1 -0
  82. package/dist/shims/fsevents.d.ts +67 -0
  83. package/dist/shims/fsevents.d.ts.map +1 -0
  84. package/dist/shims/http.d.ts +217 -0
  85. package/dist/shims/http.d.ts.map +1 -0
  86. package/dist/shims/http2.d.ts +81 -0
  87. package/dist/shims/http2.d.ts.map +1 -0
  88. package/dist/shims/https.d.ts +36 -0
  89. package/dist/shims/https.d.ts.map +1 -0
  90. package/dist/shims/inspector.d.ts +25 -0
  91. package/dist/shims/inspector.d.ts.map +1 -0
  92. package/dist/shims/module.d.ts +22 -0
  93. package/dist/shims/module.d.ts.map +1 -0
  94. package/dist/shims/net.d.ts +100 -0
  95. package/dist/shims/net.d.ts.map +1 -0
  96. package/dist/shims/os.d.ts +159 -0
  97. package/dist/shims/os.d.ts.map +1 -0
  98. package/dist/shims/path.d.ts +72 -0
  99. package/dist/shims/path.d.ts.map +1 -0
  100. package/dist/shims/perf_hooks.d.ts +50 -0
  101. package/dist/shims/perf_hooks.d.ts.map +1 -0
  102. package/dist/shims/process.d.ts +93 -0
  103. package/dist/shims/process.d.ts.map +1 -0
  104. package/dist/shims/querystring.d.ts +23 -0
  105. package/dist/shims/querystring.d.ts.map +1 -0
  106. package/dist/shims/readdirp.d.ts +52 -0
  107. package/dist/shims/readdirp.d.ts.map +1 -0
  108. package/dist/shims/readline.d.ts +62 -0
  109. package/dist/shims/readline.d.ts.map +1 -0
  110. package/dist/shims/rollup.d.ts +34 -0
  111. package/dist/shims/rollup.d.ts.map +1 -0
  112. package/dist/shims/sentry.d.ts +163 -0
  113. package/dist/shims/sentry.d.ts.map +1 -0
  114. package/dist/shims/stream.d.ts +181 -0
  115. package/dist/shims/stream.d.ts.map +1 -0
  116. package/dist/shims/tls.d.ts +53 -0
  117. package/dist/shims/tls.d.ts.map +1 -0
  118. package/dist/shims/tty.d.ts +30 -0
  119. package/dist/shims/tty.d.ts.map +1 -0
  120. package/dist/shims/url.d.ts +64 -0
  121. package/dist/shims/url.d.ts.map +1 -0
  122. package/dist/shims/util.d.ts +106 -0
  123. package/dist/shims/util.d.ts.map +1 -0
  124. package/dist/shims/v8.d.ts +73 -0
  125. package/dist/shims/v8.d.ts.map +1 -0
  126. package/dist/shims/vfs-adapter.d.ts +126 -0
  127. package/dist/shims/vfs-adapter.d.ts.map +1 -0
  128. package/dist/shims/vm.d.ts +45 -0
  129. package/dist/shims/vm.d.ts.map +1 -0
  130. package/dist/shims/worker_threads.d.ts +66 -0
  131. package/dist/shims/worker_threads.d.ts.map +1 -0
  132. package/dist/shims/ws.d.ts +66 -0
  133. package/dist/shims/ws.d.ts.map +1 -0
  134. package/dist/shims/zlib.d.ts +161 -0
  135. package/dist/shims/zlib.d.ts.map +1 -0
  136. package/dist/transform.d.ts +24 -0
  137. package/dist/transform.d.ts.map +1 -0
  138. package/dist/virtual-fs.d.ts +226 -0
  139. package/dist/virtual-fs.d.ts.map +1 -0
  140. package/dist/vite-demo.d.ts +35 -0
  141. package/dist/vite-demo.d.ts.map +1 -0
  142. package/dist/vite-sw.js +132 -0
  143. package/dist/worker/runtime-worker.d.ts +8 -0
  144. package/dist/worker/runtime-worker.d.ts.map +1 -0
  145. package/dist/worker-runtime.d.ts +50 -0
  146. package/dist/worker-runtime.d.ts.map +1 -0
  147. package/package.json +85 -0
  148. package/src/ai-chatbot-demo-entry.ts +244 -0
  149. package/src/ai-chatbot-demo.ts +509 -0
  150. package/src/convex-app-demo-entry.ts +1107 -0
  151. package/src/convex-app-demo.ts +1316 -0
  152. package/src/cors-proxy.ts +81 -0
  153. package/src/create-runtime.ts +147 -0
  154. package/src/demo.ts +304 -0
  155. package/src/dev-server.ts +274 -0
  156. package/src/frameworks/next-dev-server.ts +2224 -0
  157. package/src/frameworks/vite-dev-server.ts +702 -0
  158. package/src/index.ts +101 -0
  159. package/src/next-demo.ts +1784 -0
  160. package/src/npm/index.ts +347 -0
  161. package/src/npm/registry.ts +152 -0
  162. package/src/npm/resolver.ts +385 -0
  163. package/src/npm/tarball.ts +209 -0
  164. package/src/runtime-interface.ts +103 -0
  165. package/src/runtime.ts +1046 -0
  166. package/src/sandbox-helpers.ts +173 -0
  167. package/src/sandbox-runtime.ts +252 -0
  168. package/src/server-bridge.ts +426 -0
  169. package/src/shims/assert.ts +664 -0
  170. package/src/shims/async_hooks.ts +86 -0
  171. package/src/shims/buffer.ts +75 -0
  172. package/src/shims/child_process-browser.ts +217 -0
  173. package/src/shims/child_process.ts +463 -0
  174. package/src/shims/chokidar.ts +313 -0
  175. package/src/shims/cluster.ts +67 -0
  176. package/src/shims/crypto.ts +830 -0
  177. package/src/shims/dgram.ts +47 -0
  178. package/src/shims/diagnostics_channel.ts +196 -0
  179. package/src/shims/dns.ts +172 -0
  180. package/src/shims/domain.ts +58 -0
  181. package/src/shims/esbuild.ts +805 -0
  182. package/src/shims/events.ts +195 -0
  183. package/src/shims/fs.ts +803 -0
  184. package/src/shims/fsevents.ts +63 -0
  185. package/src/shims/http.ts +904 -0
  186. package/src/shims/http2.ts +96 -0
  187. package/src/shims/https.ts +86 -0
  188. package/src/shims/inspector.ts +30 -0
  189. package/src/shims/module.ts +82 -0
  190. package/src/shims/net.ts +359 -0
  191. package/src/shims/os.ts +195 -0
  192. package/src/shims/path.ts +199 -0
  193. package/src/shims/perf_hooks.ts +92 -0
  194. package/src/shims/process.ts +346 -0
  195. package/src/shims/querystring.ts +97 -0
  196. package/src/shims/readdirp.ts +228 -0
  197. package/src/shims/readline.ts +110 -0
  198. package/src/shims/rollup.ts +80 -0
  199. package/src/shims/sentry.ts +133 -0
  200. package/src/shims/stream.ts +1126 -0
  201. package/src/shims/tls.ts +95 -0
  202. package/src/shims/tty.ts +64 -0
  203. package/src/shims/url.ts +171 -0
  204. package/src/shims/util.ts +312 -0
  205. package/src/shims/v8.ts +113 -0
  206. package/src/shims/vfs-adapter.ts +402 -0
  207. package/src/shims/vm.ts +83 -0
  208. package/src/shims/worker_threads.ts +111 -0
  209. package/src/shims/ws.ts +382 -0
  210. package/src/shims/zlib.ts +289 -0
  211. package/src/transform.ts +313 -0
  212. package/src/types/external.d.ts +67 -0
  213. package/src/virtual-fs.ts +903 -0
  214. package/src/vite-demo.ts +577 -0
  215. package/src/worker/runtime-worker.ts +128 -0
  216. package/src/worker-runtime.ts +145 -0
@@ -0,0 +1,382 @@
1
+ /**
2
+ * ws (WebSocket) shim for browser environment
3
+ * Used by Vite for HMR (Hot Module Replacement)
4
+ */
5
+
6
+ import { EventEmitter } from './events';
7
+
8
+ // Polyfill for CloseEvent (not available in Node.js)
9
+ const CloseEventPolyfill = typeof CloseEvent !== 'undefined' ? CloseEvent : class CloseEvent extends Event {
10
+ code: number;
11
+ reason: string;
12
+ wasClean: boolean;
13
+ constructor(type: string, init?: { code?: number; reason?: string; wasClean?: boolean }) {
14
+ super(type);
15
+ this.code = init?.code ?? 1000;
16
+ this.reason = init?.reason ?? '';
17
+ this.wasClean = init?.wasClean ?? true;
18
+ }
19
+ };
20
+
21
+ // Polyfill for MessageEvent (not available in Node.js)
22
+ const MessageEventPolyfill = typeof MessageEvent !== 'undefined' ? MessageEvent : class MessageEvent extends Event {
23
+ data: unknown;
24
+ constructor(type: string, init?: { data?: unknown }) {
25
+ super(type);
26
+ this.data = init?.data;
27
+ }
28
+ };
29
+
30
+ // Message channel for communication between WebSocket server and clients
31
+ let messageChannel: BroadcastChannel | null = null;
32
+ try {
33
+ messageChannel = new BroadcastChannel('vite-ws-channel');
34
+ } catch {
35
+ // BroadcastChannel not available in some environments
36
+ }
37
+
38
+ // Track all server instances
39
+ const servers = new Map<string, WebSocketServer>();
40
+ let clientIdCounter = 0;
41
+
42
+ export class WebSocket extends EventEmitter {
43
+ static readonly CONNECTING = 0;
44
+ static readonly OPEN = 1;
45
+ static readonly CLOSING = 2;
46
+ static readonly CLOSED = 3;
47
+
48
+ readonly CONNECTING = WebSocket.CONNECTING;
49
+ readonly OPEN = WebSocket.OPEN;
50
+ readonly CLOSING = WebSocket.CLOSING;
51
+ readonly CLOSED = WebSocket.CLOSED;
52
+
53
+ readyState: number = WebSocket.CONNECTING;
54
+ url: string;
55
+ protocol: string = '';
56
+ extensions: string = '';
57
+ bufferedAmount: number = 0;
58
+ binaryType: 'blob' | 'arraybuffer' = 'blob';
59
+
60
+ private _id: string;
61
+ private _server: WebSocketServer | null = null;
62
+
63
+ // Event handler properties
64
+ onopen: ((event: Event) => void) | null = null;
65
+ onclose: ((event: CloseEvent) => void) | null = null;
66
+ onerror: ((event: Event) => void) | null = null;
67
+ onmessage: ((event: MessageEvent) => void) | null = null;
68
+
69
+ constructor(url: string, protocols?: string | string[]) {
70
+ super();
71
+ this.url = url;
72
+ this._id = `client-${++clientIdCounter}`;
73
+
74
+ if (protocols) {
75
+ this.protocol = Array.isArray(protocols) ? protocols[0] : protocols;
76
+ }
77
+
78
+ // Connect asynchronously
79
+ setTimeout(() => this._connect(), 0);
80
+ }
81
+
82
+ private _connect(): void {
83
+ // For internal WebSocket connections (from server to client), connect immediately
84
+ if (this.url.startsWith('internal://')) {
85
+ this.readyState = WebSocket.OPEN;
86
+ this.emit('open');
87
+ if (this.onopen) this.onopen(new Event('open'));
88
+ return;
89
+ }
90
+
91
+ // If no BroadcastChannel, act as if connected
92
+ if (!messageChannel) {
93
+ setTimeout(() => {
94
+ this.readyState = WebSocket.OPEN;
95
+ this.emit('open');
96
+ if (this.onopen) this.onopen(new Event('open'));
97
+ }, 0);
98
+ return;
99
+ }
100
+
101
+ // Try to connect to a server via BroadcastChannel
102
+ messageChannel.postMessage({
103
+ type: 'connect',
104
+ clientId: this._id,
105
+ url: this.url,
106
+ });
107
+
108
+ // Listen for responses
109
+ const channel = messageChannel;
110
+ const handler = (event: MessageEvent) => {
111
+ const data = event.data;
112
+
113
+ if (data.targetClient !== this._id) return;
114
+
115
+ switch (data.type) {
116
+ case 'connected':
117
+ this.readyState = WebSocket.OPEN;
118
+ this.emit('open');
119
+ if (this.onopen) this.onopen(new Event('open'));
120
+ break;
121
+
122
+ case 'message':
123
+ const msgEvent = new MessageEventPolyfill('message', { data: data.payload });
124
+ this.emit('message', msgEvent);
125
+ if (this.onmessage) this.onmessage(msgEvent as unknown as MessageEvent);
126
+ break;
127
+
128
+ case 'close':
129
+ this.readyState = WebSocket.CLOSED;
130
+ const closeEvent = new CloseEventPolyfill('close', {
131
+ code: data.code || 1000,
132
+ reason: data.reason || '',
133
+ wasClean: true,
134
+ });
135
+ this.emit('close', closeEvent);
136
+ if (this.onclose) this.onclose(closeEvent as unknown as CloseEvent);
137
+ channel.removeEventListener('message', handler);
138
+ break;
139
+
140
+ case 'error':
141
+ const errorEvent = new Event('error');
142
+ this.emit('error', errorEvent);
143
+ if (this.onerror) this.onerror(errorEvent);
144
+ break;
145
+ }
146
+ };
147
+
148
+ channel.addEventListener('message', handler);
149
+
150
+ // Connection timeout
151
+ setTimeout(() => {
152
+ if (this.readyState === WebSocket.CONNECTING) {
153
+ // No server responded, act as if connected (for standalone client use)
154
+ this.readyState = WebSocket.OPEN;
155
+ this.emit('open');
156
+ if (this.onopen) this.onopen(new Event('open'));
157
+ }
158
+ }, 100);
159
+ }
160
+
161
+ send(data: string | ArrayBuffer | Uint8Array): void {
162
+ if (this.readyState !== WebSocket.OPEN) {
163
+ throw new Error('WebSocket is not open');
164
+ }
165
+
166
+ // If connected to internal server
167
+ if (this._server) {
168
+ this._server._handleClientMessage(this, data);
169
+ return;
170
+ }
171
+
172
+ // Send via BroadcastChannel
173
+ if (messageChannel) {
174
+ messageChannel.postMessage({
175
+ type: 'message',
176
+ clientId: this._id,
177
+ url: this.url,
178
+ payload: data,
179
+ });
180
+ }
181
+ }
182
+
183
+ close(code?: number, reason?: string): void {
184
+ if (this.readyState === WebSocket.CLOSED || this.readyState === WebSocket.CLOSING) {
185
+ return;
186
+ }
187
+
188
+ this.readyState = WebSocket.CLOSING;
189
+
190
+ if (messageChannel) {
191
+ messageChannel.postMessage({
192
+ type: 'disconnect',
193
+ clientId: this._id,
194
+ url: this.url,
195
+ code,
196
+ reason,
197
+ });
198
+ }
199
+
200
+ setTimeout(() => {
201
+ this.readyState = WebSocket.CLOSED;
202
+ const closeEvent = new CloseEventPolyfill('close', {
203
+ code: code || 1000,
204
+ reason: reason || '',
205
+ wasClean: true,
206
+ });
207
+ this.emit('close', closeEvent);
208
+ if (this.onclose) this.onclose(closeEvent as unknown as CloseEvent);
209
+ }, 0);
210
+ }
211
+
212
+ ping(): void {
213
+ // No-op in browser
214
+ }
215
+
216
+ pong(): void {
217
+ // No-op in browser
218
+ }
219
+
220
+ terminate(): void {
221
+ this.close(1006, 'Connection terminated');
222
+ }
223
+
224
+ // For internal server use
225
+ _setServer(server: WebSocketServer): void {
226
+ this._server = server;
227
+ }
228
+
229
+ _receiveMessage(data: unknown): void {
230
+ const msgEvent = new MessageEventPolyfill('message', { data });
231
+ this.emit('message', msgEvent);
232
+ if (this.onmessage) this.onmessage(msgEvent as unknown as MessageEvent);
233
+ }
234
+ }
235
+
236
+ export interface ServerOptions {
237
+ host?: string;
238
+ port?: number;
239
+ server?: unknown; // HTTP server
240
+ noServer?: boolean;
241
+ path?: string;
242
+ clientTracking?: boolean;
243
+ perMessageDeflate?: boolean | object;
244
+ maxPayload?: number;
245
+ }
246
+
247
+ export class WebSocketServer extends EventEmitter {
248
+ clients: Set<WebSocket> = new Set();
249
+ options: ServerOptions;
250
+ private _path: string;
251
+ private _channelHandler: ((event: MessageEvent) => void) | null = null;
252
+
253
+ constructor(options: ServerOptions = {}) {
254
+ super();
255
+ this.options = options;
256
+ this._path = options.path || '/';
257
+
258
+ // If not noServer, set up listening
259
+ if (!options.noServer) {
260
+ this._setupListener();
261
+ }
262
+
263
+ // Register server
264
+ servers.set(this._path, this);
265
+ }
266
+
267
+ private _setupListener(): void {
268
+ if (!messageChannel) return;
269
+
270
+ const channel = messageChannel;
271
+ this._channelHandler = (event: MessageEvent) => {
272
+ const data = event.data;
273
+
274
+ if (data.type === 'connect') {
275
+ // Create a new WebSocket for this client
276
+ const ws = new WebSocket('internal://' + this._path);
277
+ ws._setServer(this);
278
+ (ws as unknown as { _clientId: string })._clientId = data.clientId;
279
+ this.clients.add(ws);
280
+
281
+ // Notify client of connection
282
+ channel.postMessage({
283
+ type: 'connected',
284
+ targetClient: data.clientId,
285
+ });
286
+
287
+ // Emit connection event
288
+ this.emit('connection', ws, { url: data.url });
289
+ }
290
+
291
+ if (data.type === 'message') {
292
+ // Find the client and deliver the message
293
+ for (const client of this.clients) {
294
+ if ((client as unknown as { _clientId: string })._clientId === data.clientId) {
295
+ client._receiveMessage(data.payload);
296
+ break;
297
+ }
298
+ }
299
+ }
300
+
301
+ if (data.type === 'disconnect') {
302
+ for (const client of this.clients) {
303
+ if ((client as unknown as { _clientId: string })._clientId === data.clientId) {
304
+ client.close(data.code, data.reason);
305
+ this.clients.delete(client);
306
+ break;
307
+ }
308
+ }
309
+ }
310
+ };
311
+
312
+ channel.addEventListener('message', this._channelHandler);
313
+ }
314
+
315
+ _handleClientMessage(client: WebSocket, data: unknown): void {
316
+ // Broadcast to server-side handlers
317
+ const msgEvent = new MessageEventPolyfill('message', { data });
318
+ client.emit('message', msgEvent);
319
+ }
320
+
321
+ handleUpgrade(
322
+ request: unknown,
323
+ socket: unknown,
324
+ head: unknown,
325
+ callback: (ws: WebSocket, request: unknown) => void
326
+ ): void {
327
+ // Create WebSocket for this upgrade
328
+ const ws = new WebSocket('internal://' + this._path);
329
+ ws._setServer(this);
330
+
331
+ if (this.options.clientTracking !== false) {
332
+ this.clients.add(ws);
333
+ }
334
+
335
+ // Async callback
336
+ setTimeout(() => {
337
+ callback(ws, request);
338
+ this.emit('connection', ws, request);
339
+ }, 0);
340
+ }
341
+
342
+ close(callback?: () => void): void {
343
+ // Close all clients
344
+ for (const client of this.clients) {
345
+ client.close(1001, 'Server shutting down');
346
+ }
347
+ this.clients.clear();
348
+
349
+ // Remove from registry
350
+ servers.delete(this._path);
351
+
352
+ // Remove channel listener
353
+ if (this._channelHandler && messageChannel) {
354
+ messageChannel.removeEventListener('message', this._channelHandler);
355
+ this._channelHandler = null;
356
+ }
357
+
358
+ this.emit('close');
359
+
360
+ if (callback) {
361
+ setTimeout(callback, 0);
362
+ }
363
+ }
364
+
365
+ address(): { port: number; family: string; address: string } | null {
366
+ return {
367
+ port: this.options.port || 0,
368
+ family: 'IPv4',
369
+ address: this.options.host || '0.0.0.0',
370
+ };
371
+ }
372
+
373
+ }
374
+
375
+ // Export WebSocket and Server
376
+ export default WebSocket;
377
+ export const Server = WebSocketServer;
378
+
379
+ // Additional exports for compatibility
380
+ export const createWebSocketStream = () => {
381
+ throw new Error('createWebSocketStream is not supported in browser');
382
+ };
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Node.js zlib module shim
3
+ * Provides basic compression utilities
4
+ */
5
+
6
+ import { Buffer } from './stream';
7
+ import pako from 'pako';
8
+
9
+ // Brotli WASM instance - loaded lazily
10
+ type BrotliModule = { compress: (data: Uint8Array) => Uint8Array; decompress: (data: Uint8Array) => Uint8Array };
11
+ let brotliModule: BrotliModule | null = null;
12
+ let brotliLoadPromise: Promise<BrotliModule | null> | null = null;
13
+
14
+ async function loadBrotli(): Promise<BrotliModule | null> {
15
+ if (brotliModule) return brotliModule;
16
+ if (!brotliLoadPromise) {
17
+ brotliLoadPromise = (async () => {
18
+ try {
19
+ // Dynamic import - brotli-wasm handles environment detection automatically
20
+ // In Node.js: returns sync module
21
+ // In browser: returns promise that resolves after WASM init
22
+ const brotliWasmModule = await import('brotli-wasm');
23
+ // The default export is a promise that resolves to the module
24
+ brotliModule = await brotliWasmModule.default;
25
+ console.log('[zlib] brotli-wasm loaded successfully');
26
+ return brotliModule;
27
+ } catch (error) {
28
+ console.error('[zlib] Failed to load brotli-wasm:', error);
29
+ return null;
30
+ }
31
+ })();
32
+ }
33
+ return brotliLoadPromise;
34
+ }
35
+
36
+ export function gzip(
37
+ buffer: Buffer | string,
38
+ callback: (error: Error | null, result: Buffer) => void
39
+ ): void {
40
+ try {
41
+ const input = typeof buffer === 'string' ? Buffer.from(buffer) : buffer;
42
+ const result = pako.gzip(input);
43
+ callback(null, Buffer.from(result));
44
+ } catch (error) {
45
+ callback(error as Error, Buffer.alloc(0));
46
+ }
47
+ }
48
+
49
+ export function gunzip(
50
+ buffer: Buffer,
51
+ callback: (error: Error | null, result: Buffer) => void
52
+ ): void {
53
+ try {
54
+ const result = pako.ungzip(buffer);
55
+ callback(null, Buffer.from(result));
56
+ } catch (error) {
57
+ callback(error as Error, Buffer.alloc(0));
58
+ }
59
+ }
60
+
61
+ export function deflate(
62
+ buffer: Buffer | string,
63
+ callback: (error: Error | null, result: Buffer) => void
64
+ ): void {
65
+ try {
66
+ const input = typeof buffer === 'string' ? Buffer.from(buffer) : buffer;
67
+ const result = pako.deflate(input);
68
+ callback(null, Buffer.from(result));
69
+ } catch (error) {
70
+ callback(error as Error, Buffer.alloc(0));
71
+ }
72
+ }
73
+
74
+ export function inflate(
75
+ buffer: Buffer,
76
+ callback: (error: Error | null, result: Buffer) => void
77
+ ): void {
78
+ try {
79
+ const result = pako.inflate(buffer);
80
+ callback(null, Buffer.from(result));
81
+ } catch (error) {
82
+ callback(error as Error, Buffer.alloc(0));
83
+ }
84
+ }
85
+
86
+ export function deflateRaw(
87
+ buffer: Buffer | string,
88
+ callback: (error: Error | null, result: Buffer) => void
89
+ ): void {
90
+ try {
91
+ const input = typeof buffer === 'string' ? Buffer.from(buffer) : buffer;
92
+ const result = pako.deflateRaw(input);
93
+ callback(null, Buffer.from(result));
94
+ } catch (error) {
95
+ callback(error as Error, Buffer.alloc(0));
96
+ }
97
+ }
98
+
99
+ export function inflateRaw(
100
+ buffer: Buffer,
101
+ callback: (error: Error | null, result: Buffer) => void
102
+ ): void {
103
+ try {
104
+ const result = pako.inflateRaw(buffer);
105
+ callback(null, Buffer.from(result));
106
+ } catch (error) {
107
+ callback(error as Error, Buffer.alloc(0));
108
+ }
109
+ }
110
+
111
+ // Brotli compression using brotli-wasm
112
+ export function brotliCompress(
113
+ buffer: Buffer | string,
114
+ options: unknown,
115
+ callback: (error: Error | null, result: Buffer) => void
116
+ ): void {
117
+ // Handle overload where options is the callback
118
+ if (typeof options === 'function') {
119
+ callback = options as (error: Error | null, result: Buffer) => void;
120
+ }
121
+
122
+ loadBrotli().then(brotli => {
123
+ if (!brotli) {
124
+ callback(new Error('Brotli WASM failed to load'), Buffer.alloc(0));
125
+ return;
126
+ }
127
+ try {
128
+ const input = typeof buffer === 'string' ? Buffer.from(buffer) : buffer;
129
+ const result = brotli.compress(new Uint8Array(input));
130
+ callback(null, Buffer.from(result));
131
+ } catch (error) {
132
+ callback(error as Error, Buffer.alloc(0));
133
+ }
134
+ }).catch(error => {
135
+ callback(error as Error, Buffer.alloc(0));
136
+ });
137
+ }
138
+
139
+ export function brotliDecompress(
140
+ buffer: Buffer,
141
+ options: unknown,
142
+ callback: (error: Error | null, result: Buffer) => void
143
+ ): void {
144
+ // Handle overload where options is the callback
145
+ if (typeof options === 'function') {
146
+ callback = options as (error: Error | null, result: Buffer) => void;
147
+ }
148
+
149
+ loadBrotli().then(brotli => {
150
+ if (!brotli) {
151
+ callback(new Error('Brotli WASM failed to load'), Buffer.alloc(0));
152
+ return;
153
+ }
154
+ try {
155
+ const result = brotli.decompress(new Uint8Array(buffer));
156
+ callback(null, Buffer.from(result));
157
+ } catch (error) {
158
+ callback(error as Error, Buffer.alloc(0));
159
+ }
160
+ }).catch(error => {
161
+ callback(error as Error, Buffer.alloc(0));
162
+ });
163
+ }
164
+
165
+ export function brotliCompressSync(buffer: Buffer | string, _options?: unknown): Buffer {
166
+ if (!brotliModule) {
167
+ throw new Error('Brotli WASM not loaded. Call brotliCompress first to initialize.');
168
+ }
169
+ const input = typeof buffer === 'string' ? Buffer.from(buffer) : buffer;
170
+ return Buffer.from(brotliModule.compress(new Uint8Array(input)));
171
+ }
172
+
173
+ export function brotliDecompressSync(buffer: Buffer, _options?: unknown): Buffer {
174
+ if (!brotliModule) {
175
+ throw new Error('Brotli WASM not loaded. Call brotliDecompress first to initialize.');
176
+ }
177
+ return Buffer.from(brotliModule.decompress(new Uint8Array(buffer)));
178
+ }
179
+
180
+ // Sync versions
181
+ export function gzipSync(buffer: Buffer | string): Buffer {
182
+ const input = typeof buffer === 'string' ? Buffer.from(buffer) : buffer;
183
+ return Buffer.from(pako.gzip(input));
184
+ }
185
+
186
+ export function gunzipSync(buffer: Buffer): Buffer {
187
+ return Buffer.from(pako.ungzip(buffer));
188
+ }
189
+
190
+ export function deflateSync(buffer: Buffer | string): Buffer {
191
+ const input = typeof buffer === 'string' ? Buffer.from(buffer) : buffer;
192
+ return Buffer.from(pako.deflate(input));
193
+ }
194
+
195
+ export function inflateSync(buffer: Buffer): Buffer {
196
+ return Buffer.from(pako.inflate(buffer));
197
+ }
198
+
199
+ export function deflateRawSync(buffer: Buffer | string): Buffer {
200
+ const input = typeof buffer === 'string' ? Buffer.from(buffer) : buffer;
201
+ return Buffer.from(pako.deflateRaw(input));
202
+ }
203
+
204
+ export function inflateRawSync(buffer: Buffer): Buffer {
205
+ return Buffer.from(pako.inflateRaw(buffer));
206
+ }
207
+
208
+ // Constants
209
+ export const constants = {
210
+ Z_NO_FLUSH: 0,
211
+ Z_PARTIAL_FLUSH: 1,
212
+ Z_SYNC_FLUSH: 2,
213
+ Z_FULL_FLUSH: 3,
214
+ Z_FINISH: 4,
215
+ Z_BLOCK: 5,
216
+ Z_OK: 0,
217
+ Z_STREAM_END: 1,
218
+ Z_NEED_DICT: 2,
219
+ Z_ERRNO: -1,
220
+ Z_STREAM_ERROR: -2,
221
+ Z_DATA_ERROR: -3,
222
+ Z_MEM_ERROR: -4,
223
+ Z_BUF_ERROR: -5,
224
+ Z_VERSION_ERROR: -6,
225
+ Z_NO_COMPRESSION: 0,
226
+ Z_BEST_SPEED: 1,
227
+ Z_BEST_COMPRESSION: 9,
228
+ Z_DEFAULT_COMPRESSION: -1,
229
+ Z_FILTERED: 1,
230
+ Z_HUFFMAN_ONLY: 2,
231
+ Z_RLE: 3,
232
+ Z_FIXED: 4,
233
+ Z_DEFAULT_STRATEGY: 0,
234
+ ZLIB_VERNUM: 4784,
235
+ Z_MIN_WINDOWBITS: 8,
236
+ Z_MAX_WINDOWBITS: 15,
237
+ Z_DEFAULT_WINDOWBITS: 15,
238
+ Z_MIN_CHUNK: 64,
239
+ Z_MAX_CHUNK: Infinity,
240
+ Z_DEFAULT_CHUNK: 16384,
241
+ Z_MIN_MEMLEVEL: 1,
242
+ Z_MAX_MEMLEVEL: 9,
243
+ Z_DEFAULT_MEMLEVEL: 8,
244
+ Z_MIN_LEVEL: -1,
245
+ Z_MAX_LEVEL: 9,
246
+ Z_DEFAULT_LEVEL: -1,
247
+ // Brotli constants
248
+ BROTLI_DECODE: 0,
249
+ BROTLI_ENCODE: 1,
250
+ BROTLI_OPERATION_PROCESS: 0,
251
+ BROTLI_OPERATION_FLUSH: 1,
252
+ BROTLI_OPERATION_FINISH: 2,
253
+ BROTLI_OPERATION_EMIT_METADATA: 3,
254
+ BROTLI_PARAM_MODE: 0,
255
+ BROTLI_MODE_GENERIC: 0,
256
+ BROTLI_MODE_TEXT: 1,
257
+ BROTLI_MODE_FONT: 2,
258
+ BROTLI_PARAM_QUALITY: 1,
259
+ BROTLI_MIN_QUALITY: 0,
260
+ BROTLI_MAX_QUALITY: 11,
261
+ BROTLI_DEFAULT_QUALITY: 11,
262
+ BROTLI_PARAM_LGWIN: 2,
263
+ BROTLI_MIN_WINDOW_BITS: 10,
264
+ BROTLI_MAX_WINDOW_BITS: 24,
265
+ BROTLI_DEFAULT_WINDOW: 22,
266
+ BROTLI_PARAM_LGBLOCK: 3,
267
+ BROTLI_MIN_INPUT_BLOCK_BITS: 16,
268
+ BROTLI_MAX_INPUT_BLOCK_BITS: 24,
269
+ };
270
+
271
+ export default {
272
+ gzip,
273
+ gunzip,
274
+ deflate,
275
+ inflate,
276
+ deflateRaw,
277
+ inflateRaw,
278
+ gzipSync,
279
+ gunzipSync,
280
+ deflateSync,
281
+ inflateSync,
282
+ deflateRawSync,
283
+ inflateRawSync,
284
+ brotliCompress,
285
+ brotliDecompress,
286
+ brotliCompressSync,
287
+ brotliDecompressSync,
288
+ constants,
289
+ };