@scelar/nodepod 1.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.
Files changed (134) hide show
  1. package/LICENSE +43 -0
  2. package/README.md +240 -0
  3. package/dist/child_process-BJOMsZje.js +8233 -0
  4. package/dist/child_process-BJOMsZje.js.map +1 -0
  5. package/dist/child_process-Cj8vOcuc.cjs +7434 -0
  6. package/dist/child_process-Cj8vOcuc.cjs.map +1 -0
  7. package/dist/index-Cb1Cgdnd.js +35308 -0
  8. package/dist/index-Cb1Cgdnd.js.map +1 -0
  9. package/dist/index-DsMGS-xc.cjs +37195 -0
  10. package/dist/index-DsMGS-xc.cjs.map +1 -0
  11. package/dist/index.cjs +65 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.mjs +59 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/package.json +95 -0
  16. package/src/__tests__/smoke.test.ts +11 -0
  17. package/src/constants/cdn-urls.ts +18 -0
  18. package/src/constants/config.ts +236 -0
  19. package/src/cross-origin.ts +26 -0
  20. package/src/engine-factory.ts +176 -0
  21. package/src/engine-types.ts +56 -0
  22. package/src/helpers/byte-encoding.ts +39 -0
  23. package/src/helpers/digest.ts +9 -0
  24. package/src/helpers/event-loop.ts +96 -0
  25. package/src/helpers/wasm-cache.ts +133 -0
  26. package/src/iframe-sandbox.ts +141 -0
  27. package/src/index.ts +192 -0
  28. package/src/isolation-helpers.ts +148 -0
  29. package/src/memory-volume.ts +941 -0
  30. package/src/module-transformer.ts +368 -0
  31. package/src/packages/archive-extractor.ts +248 -0
  32. package/src/packages/browser-bundler.ts +284 -0
  33. package/src/packages/installer.ts +396 -0
  34. package/src/packages/registry-client.ts +131 -0
  35. package/src/packages/version-resolver.ts +411 -0
  36. package/src/polyfills/assert.ts +384 -0
  37. package/src/polyfills/async_hooks.ts +144 -0
  38. package/src/polyfills/buffer.ts +628 -0
  39. package/src/polyfills/child_process.ts +2288 -0
  40. package/src/polyfills/chokidar.ts +336 -0
  41. package/src/polyfills/cluster.ts +106 -0
  42. package/src/polyfills/console.ts +136 -0
  43. package/src/polyfills/constants.ts +123 -0
  44. package/src/polyfills/crypto.ts +885 -0
  45. package/src/polyfills/dgram.ts +87 -0
  46. package/src/polyfills/diagnostics_channel.ts +76 -0
  47. package/src/polyfills/dns.ts +134 -0
  48. package/src/polyfills/domain.ts +68 -0
  49. package/src/polyfills/esbuild.ts +854 -0
  50. package/src/polyfills/events.ts +276 -0
  51. package/src/polyfills/fs.ts +2888 -0
  52. package/src/polyfills/fsevents.ts +79 -0
  53. package/src/polyfills/http.ts +1449 -0
  54. package/src/polyfills/http2.ts +199 -0
  55. package/src/polyfills/https.ts +76 -0
  56. package/src/polyfills/inspector.ts +62 -0
  57. package/src/polyfills/lightningcss.ts +105 -0
  58. package/src/polyfills/module.ts +191 -0
  59. package/src/polyfills/net.ts +353 -0
  60. package/src/polyfills/os.ts +238 -0
  61. package/src/polyfills/path.ts +206 -0
  62. package/src/polyfills/perf_hooks.ts +102 -0
  63. package/src/polyfills/process.ts +690 -0
  64. package/src/polyfills/punycode.ts +159 -0
  65. package/src/polyfills/querystring.ts +93 -0
  66. package/src/polyfills/quic.ts +118 -0
  67. package/src/polyfills/readdirp.ts +229 -0
  68. package/src/polyfills/readline.ts +692 -0
  69. package/src/polyfills/repl.ts +134 -0
  70. package/src/polyfills/rollup.ts +119 -0
  71. package/src/polyfills/sea.ts +33 -0
  72. package/src/polyfills/sqlite.ts +78 -0
  73. package/src/polyfills/stream.ts +1620 -0
  74. package/src/polyfills/string_decoder.ts +25 -0
  75. package/src/polyfills/tailwindcss-oxide.ts +309 -0
  76. package/src/polyfills/test.ts +197 -0
  77. package/src/polyfills/timers.ts +32 -0
  78. package/src/polyfills/tls.ts +105 -0
  79. package/src/polyfills/trace_events.ts +50 -0
  80. package/src/polyfills/tty.ts +71 -0
  81. package/src/polyfills/url.ts +174 -0
  82. package/src/polyfills/util.ts +559 -0
  83. package/src/polyfills/v8.ts +126 -0
  84. package/src/polyfills/vm.ts +132 -0
  85. package/src/polyfills/volume-registry.ts +15 -0
  86. package/src/polyfills/wasi.ts +44 -0
  87. package/src/polyfills/worker_threads.ts +326 -0
  88. package/src/polyfills/ws.ts +595 -0
  89. package/src/polyfills/zlib.ts +881 -0
  90. package/src/request-proxy.ts +716 -0
  91. package/src/script-engine.ts +3375 -0
  92. package/src/sdk/nodepod-fs.ts +93 -0
  93. package/src/sdk/nodepod-process.ts +86 -0
  94. package/src/sdk/nodepod-terminal.ts +350 -0
  95. package/src/sdk/nodepod.ts +509 -0
  96. package/src/sdk/types.ts +70 -0
  97. package/src/shell/commands/bun.ts +121 -0
  98. package/src/shell/commands/directory.ts +297 -0
  99. package/src/shell/commands/file-ops.ts +525 -0
  100. package/src/shell/commands/git.ts +2142 -0
  101. package/src/shell/commands/node.ts +80 -0
  102. package/src/shell/commands/npm.ts +198 -0
  103. package/src/shell/commands/pm-types.ts +45 -0
  104. package/src/shell/commands/pnpm.ts +82 -0
  105. package/src/shell/commands/search.ts +264 -0
  106. package/src/shell/commands/shell-env.ts +352 -0
  107. package/src/shell/commands/text-processing.ts +1152 -0
  108. package/src/shell/commands/yarn.ts +84 -0
  109. package/src/shell/shell-builtins.ts +19 -0
  110. package/src/shell/shell-helpers.ts +250 -0
  111. package/src/shell/shell-interpreter.ts +514 -0
  112. package/src/shell/shell-parser.ts +429 -0
  113. package/src/shell/shell-types.ts +85 -0
  114. package/src/syntax-transforms.ts +561 -0
  115. package/src/threading/engine-worker.ts +64 -0
  116. package/src/threading/inline-worker.ts +372 -0
  117. package/src/threading/offload-types.ts +112 -0
  118. package/src/threading/offload-worker.ts +383 -0
  119. package/src/threading/offload.ts +271 -0
  120. package/src/threading/process-context.ts +92 -0
  121. package/src/threading/process-handle.ts +275 -0
  122. package/src/threading/process-manager.ts +956 -0
  123. package/src/threading/process-worker-entry.ts +854 -0
  124. package/src/threading/shared-vfs.ts +352 -0
  125. package/src/threading/sync-channel.ts +135 -0
  126. package/src/threading/task-queue.ts +177 -0
  127. package/src/threading/vfs-bridge.ts +231 -0
  128. package/src/threading/worker-pool.ts +233 -0
  129. package/src/threading/worker-protocol.ts +358 -0
  130. package/src/threading/worker-vfs.ts +218 -0
  131. package/src/types/externals.d.ts +38 -0
  132. package/src/types/fs-streams.ts +142 -0
  133. package/src/types/manifest.ts +17 -0
  134. package/src/worker-sandbox.ts +90 -0
@@ -0,0 +1,1449 @@
1
+ // HTTP polyfill -- IncomingMessage, ServerResponse, Server, ClientRequest (fetch-backed),
2
+ // createServer, request, get, Agent, STATUS_CODES, WebSocket upgrade bridging.
3
+ // Uses function constructors (not classes) for pre-ES6 inheritance compat.
4
+
5
+ import { EventEmitter, type EventHandler } from "./events";
6
+ import { Readable, Writable } from "./stream";
7
+ import { Buffer } from "./buffer";
8
+ import { TcpSocket, TcpServer, type NetAddress } from "./net";
9
+ import { createHash } from "./crypto";
10
+ import { ref as _elRef, unref as _elUnref } from "../helpers/event-loop";
11
+ import { TIMEOUTS } from "../constants/config";
12
+
13
+ // capture real browser WebSocket before any bundled lib can overwrite it
14
+ const _runningInBrowser =
15
+ typeof window !== "undefined" && typeof window.document !== "undefined";
16
+ const _NativeWebSocket: typeof globalThis.WebSocket | null =
17
+ _runningInBrowser && typeof globalThis.WebSocket === "function"
18
+ ? globalThis.WebSocket
19
+ : null;
20
+
21
+ // Types
22
+
23
+ export type HttpHandler = (
24
+ incoming: IncomingMessage,
25
+ outgoing: ServerResponse,
26
+ ) => void | Promise<void>;
27
+
28
+ export interface ConnectionOptions {
29
+ method?: string;
30
+ path?: string;
31
+ headers?: Record<string, string | string[]>;
32
+ hostname?: string;
33
+ host?: string;
34
+ port?: number;
35
+ }
36
+
37
+ export interface CompletedResponse {
38
+ statusCode: number;
39
+ statusMessage: string;
40
+ headers: Record<string, string>;
41
+ body: Buffer;
42
+ }
43
+
44
+ // IncomingMessage
45
+
46
+ export interface IncomingMessage extends Readable {
47
+ httpVersion: string;
48
+ httpVersionMajor: number;
49
+ httpVersionMinor: number;
50
+ complete: boolean;
51
+ headers: Record<string, string | string[] | undefined>;
52
+ rawHeaders: string[];
53
+ trailers: Record<string, string | undefined>;
54
+ rawTrailers: string[];
55
+ method?: string;
56
+ url?: string;
57
+ statusCode?: number;
58
+ statusMessage?: string;
59
+ aborted: boolean;
60
+ socket: TcpSocket;
61
+ connection: TcpSocket;
62
+ setTimeout(ms: number, handler?: () => void): this;
63
+ destroy(err?: Error): this;
64
+ _injectBody(raw: Buffer | string | null): void;
65
+ }
66
+
67
+ export interface IncomingMessageConstructor {
68
+ new (sock?: TcpSocket): IncomingMessage;
69
+ (this: any, sock?: TcpSocket): void;
70
+ prototype: any;
71
+ build(
72
+ verb: string,
73
+ target: string,
74
+ hdrs: Record<string, string>,
75
+ payload?: Buffer | string,
76
+ ): IncomingMessage;
77
+ }
78
+
79
+ export const IncomingMessage = function IncomingMessage(this: any, sock?: TcpSocket) {
80
+ if (!this) return;
81
+ Readable.call(this);
82
+
83
+ this.httpVersion = "1.1";
84
+ this.httpVersionMajor = 1;
85
+ this.httpVersionMinor = 1;
86
+ this.complete = false;
87
+ this.headers = {};
88
+ this.rawHeaders = [];
89
+ this.trailers = {};
90
+ this.rawTrailers = [];
91
+ this.method = undefined;
92
+ this.url = undefined;
93
+ this.statusCode = undefined;
94
+ this.statusMessage = undefined;
95
+ this.aborted = false;
96
+ this._payload = null;
97
+ this.socket = sock ?? new TcpSocket();
98
+ this.connection = this.socket;
99
+ } as unknown as IncomingMessageConstructor;
100
+
101
+ Object.setPrototypeOf(IncomingMessage.prototype, Readable.prototype);
102
+
103
+ IncomingMessage.prototype.setTimeout = function setTimeout(ms: number, handler?: () => void): any {
104
+ if (handler) this.once("timeout", handler);
105
+ return this;
106
+ };
107
+
108
+ IncomingMessage.prototype.destroy = function destroy(err?: Error): any {
109
+ Readable.prototype.destroy.call(this, err);
110
+ return this;
111
+ };
112
+
113
+ IncomingMessage.prototype._injectBody = function _injectBody(raw: Buffer | string | null): void {
114
+ if (raw === null) {
115
+ this._payload = null;
116
+ } else {
117
+ this._payload = typeof raw === "string" ? Buffer.from(raw) : raw;
118
+ }
119
+ // Defer push to next microtask so that stream consumers (body-parser, raw-body)
120
+ // can attach 'data'/'end' listeners before the stream is marked as ended.
121
+ // Without this, push(null) sets readable=false immediately and raw-body
122
+ // bails out with "stream is not readable".
123
+ const self = this;
124
+ queueMicrotask(() => {
125
+ if (self._payload) self.push(self._payload);
126
+ self.push(null);
127
+ self.complete = true;
128
+ });
129
+ };
130
+
131
+ IncomingMessage.build = function build(
132
+ verb: string,
133
+ target: string,
134
+ hdrs: Record<string, string>,
135
+ payload?: Buffer | string,
136
+ ): IncomingMessage {
137
+ const sock = new TcpSocket();
138
+ sock.remoteAddress = "127.0.0.1";
139
+ sock.remotePort = 0;
140
+ sock.remoteFamily = "IPv4";
141
+ const msg = new IncomingMessage(sock);
142
+ msg.method = verb;
143
+ msg.url = target;
144
+ // Node.js always lowercases header keys in req.headers
145
+ const lowerHdrs: Record<string, string> = {};
146
+ for (const [k, v] of Object.entries(hdrs)) {
147
+ lowerHdrs[k.toLowerCase()] = v;
148
+ msg.rawHeaders.push(k, v);
149
+ }
150
+ msg.headers = lowerHdrs;
151
+ if (payload) {
152
+ msg._injectBody(payload);
153
+ } else {
154
+ // Defer end signal for bodyless requests too, for consistent behavior
155
+ queueMicrotask(() => {
156
+ msg.push(null);
157
+ msg.complete = true;
158
+ });
159
+ }
160
+ return msg;
161
+ };
162
+
163
+ // ServerResponse
164
+
165
+ export interface ServerResponse extends Writable {
166
+ statusCode: number;
167
+ statusMessage: string;
168
+ headersSent: boolean;
169
+ finished: boolean;
170
+ sendDate: boolean;
171
+ socket: TcpSocket | null;
172
+ req: IncomingMessage;
173
+ connection: TcpSocket | null;
174
+ _onComplete(fn: (r: CompletedResponse) => void): void;
175
+ assignSocket(socket: TcpSocket): void;
176
+ detachSocket(socket: TcpSocket): void;
177
+ setHeader(key: string, val: string | string[] | number): this;
178
+ getHeader(key: string): string | string[] | undefined;
179
+ getHeaders(): Record<string, string | string[]>;
180
+ getHeaderNames(): string[];
181
+ hasHeader(key: string): boolean;
182
+ appendHeader(key: string, val: string | string[]): this;
183
+ removeHeader(key: string): void;
184
+ flushHeaders(): void;
185
+ writeContinue(): void;
186
+ writeProcessing(): void;
187
+ writeEarlyHints(hints: Record<string, string | string[]>, cb?: () => void): void;
188
+ writeHead(code: number, msgOrHdrs?: any, extraHdrs?: any): this;
189
+ write(data: any, encOrCb?: any, cb?: any): boolean;
190
+ end(dataOrCb?: any, encOrCb?: any, cb?: any): this;
191
+ send(payload: string | Buffer | object): this;
192
+ setTimeout(ms: number, handler?: () => void): this;
193
+ json(obj: unknown): this;
194
+ status(c: number): this;
195
+ redirect(target: string | number, loc?: string): void;
196
+ addTrailers(headers: Record<string, string>): void;
197
+ _collectedBody(): Buffer;
198
+ _collectedBodyText(): string;
199
+ }
200
+
201
+ export interface ServerResponseConstructor {
202
+ new (incoming: IncomingMessage): ServerResponse;
203
+ (this: any, incoming: IncomingMessage): void;
204
+ prototype: any;
205
+ }
206
+
207
+ export const ServerResponse = function ServerResponse(this: any, incoming: any) {
208
+ if (!this) return;
209
+ Writable.call(this);
210
+
211
+ this.statusCode = 200;
212
+ this.statusMessage = "OK";
213
+ this.headersSent = false;
214
+ this.finished = false;
215
+ this.sendDate = true;
216
+ this.socket = incoming.socket;
217
+ this.connection = incoming.socket;
218
+ this.req = incoming;
219
+ this._hdrs = new Map();
220
+ this._chunks = [];
221
+ this._completionCallback = undefined;
222
+ } as unknown as ServerResponseConstructor;
223
+
224
+ Object.setPrototypeOf(ServerResponse.prototype, Writable.prototype);
225
+
226
+ ServerResponse.prototype._onComplete = function _onComplete(fn: (r: CompletedResponse) => void): void {
227
+ this._completionCallback = fn;
228
+ };
229
+
230
+ ServerResponse.prototype.assignSocket = function assignSocket(socket: TcpSocket): void {
231
+ this.socket = socket;
232
+ this.connection = socket;
233
+ };
234
+
235
+ ServerResponse.prototype.detachSocket = function detachSocket(_socket: TcpSocket): void {
236
+ this.socket = null;
237
+ this.connection = null;
238
+ };
239
+
240
+ ServerResponse.prototype.setHeader = function setHeader(key: string, val: string | string[] | number): any {
241
+ if (this.headersSent) throw new Error("Headers already dispatched");
242
+ this._hdrs.set(key.toLowerCase(), String(val));
243
+ return this;
244
+ };
245
+
246
+ ServerResponse.prototype.getHeader = function getHeader(key: string): string | string[] | undefined {
247
+ return this._hdrs.get(key.toLowerCase());
248
+ };
249
+
250
+ ServerResponse.prototype.getHeaders = function getHeaders(): Record<string, string | string[]> {
251
+ const out: Record<string, string | string[]> = {};
252
+ this._hdrs.forEach((v: string | string[], k: string) => {
253
+ out[k] = v;
254
+ });
255
+ return out;
256
+ };
257
+
258
+ ServerResponse.prototype.getHeaderNames = function getHeaderNames(): string[] {
259
+ return [...this._hdrs.keys()];
260
+ };
261
+
262
+ ServerResponse.prototype.hasHeader = function hasHeader(key: string): boolean {
263
+ return this._hdrs.has(key.toLowerCase());
264
+ };
265
+
266
+ ServerResponse.prototype.appendHeader = function appendHeader(key: string, val: string | string[]): any {
267
+ const lk = key.toLowerCase();
268
+ const existing = this._hdrs.get(lk);
269
+ if (existing === undefined) {
270
+ this._hdrs.set(lk, Array.isArray(val) ? val.join(", ") : val);
271
+ } else {
272
+ const append = Array.isArray(val) ? val.join(", ") : val;
273
+ const cur = Array.isArray(existing) ? existing.join(", ") : existing;
274
+ this._hdrs.set(lk, cur + ", " + append);
275
+ }
276
+ return this;
277
+ };
278
+
279
+ ServerResponse.prototype.removeHeader = function removeHeader(key: string): void {
280
+ if (this.headersSent) throw new Error("Headers already dispatched");
281
+ this._hdrs.delete(key.toLowerCase());
282
+ };
283
+
284
+ ServerResponse.prototype.flushHeaders = function flushHeaders(): void {
285
+ this.headersSent = true;
286
+ };
287
+
288
+ ServerResponse.prototype.writeContinue = function writeContinue(): void {
289
+ // No-op in polyfill
290
+ };
291
+
292
+ ServerResponse.prototype.writeProcessing = function writeProcessing(): void {
293
+ // No-op in polyfill
294
+ };
295
+
296
+ ServerResponse.prototype.writeEarlyHints = function writeEarlyHints(
297
+ _hints: Record<string, string | string[]>,
298
+ _cb?: () => void,
299
+ ): void {
300
+ if (_cb) queueMicrotask(_cb);
301
+ };
302
+
303
+ ServerResponse.prototype.writeHead = function writeHead(
304
+ code: number,
305
+ msgOrHdrs?: string | Record<string, string | string[] | number> | string[],
306
+ extraHdrs?: Record<string, string | string[] | number> | string[],
307
+ ): any {
308
+ this.statusCode = code;
309
+ if (typeof msgOrHdrs === "string") {
310
+ this.statusMessage = msgOrHdrs;
311
+ if (extraHdrs) {
312
+ if (Array.isArray(extraHdrs)) {
313
+ for (let i = 0; i < extraHdrs.length; i += 2) {
314
+ this.setHeader(extraHdrs[i] as string, extraHdrs[i + 1] as string);
315
+ }
316
+ } else {
317
+ for (const [k, v] of Object.entries(extraHdrs)) this.setHeader(k, v);
318
+ }
319
+ }
320
+ } else if (Array.isArray(msgOrHdrs)) {
321
+ for (let i = 0; i < msgOrHdrs.length; i += 2) {
322
+ this.setHeader(msgOrHdrs[i] as string, msgOrHdrs[i + 1] as string);
323
+ }
324
+ } else if (msgOrHdrs) {
325
+ for (const [k, v] of Object.entries(msgOrHdrs)) this.setHeader(k, v);
326
+ }
327
+ return this;
328
+ };
329
+
330
+ ServerResponse.prototype.write = function write(
331
+ data: Uint8Array | string,
332
+ encOrCb?: BufferEncoding | ((err?: Error | null) => void),
333
+ cb?: (err?: Error | null) => void,
334
+ ): boolean {
335
+ this.headersSent = true;
336
+ const buf = typeof data === "string" ? Buffer.from(data) : data;
337
+ this._chunks.push(buf);
338
+ const fn = typeof encOrCb === "function" ? encOrCb : cb;
339
+ if (fn) queueMicrotask(() => fn(null));
340
+ return true;
341
+ };
342
+
343
+ ServerResponse.prototype.end = function end(
344
+ dataOrCb?: Uint8Array | string | (() => void),
345
+ encOrCb?: BufferEncoding | (() => void),
346
+ cb?: () => void,
347
+ ): any {
348
+ if (typeof dataOrCb === "function") {
349
+ cb = dataOrCb;
350
+ } else if (dataOrCb !== undefined) {
351
+ this.write(dataOrCb as Uint8Array | string);
352
+ }
353
+ if (typeof encOrCb === "function") cb = encOrCb;
354
+
355
+ this.headersSent = true;
356
+ this.finished = true;
357
+ this.writableEnded = true;
358
+ this.writableFinished = true;
359
+
360
+ if (this._completionCallback) {
361
+ const flatHdrs: Record<string, string> = {};
362
+ this._hdrs.forEach((v: string | string[], k: string) => {
363
+ flatHdrs[k] = Array.isArray(v) ? v.join(", ") : v;
364
+ });
365
+ this._completionCallback({
366
+ statusCode: this.statusCode,
367
+ statusMessage: this.statusMessage,
368
+ headers: flatHdrs,
369
+ body: Buffer.concat(this._chunks),
370
+ });
371
+ }
372
+
373
+ const self = this;
374
+ queueMicrotask(() => {
375
+ self.emit("finish");
376
+ if (cb) cb();
377
+ });
378
+ return this;
379
+ };
380
+
381
+ ServerResponse.prototype.send = function send(payload: string | Buffer | object): any {
382
+ if (typeof payload === "object" && !Buffer.isBuffer(payload)) {
383
+ this.setHeader("Content-Type", "application/json");
384
+ payload = JSON.stringify(payload);
385
+ }
386
+ if (!this.hasHeader("Content-Type")) {
387
+ this.setHeader("Content-Type", "text/html");
388
+ }
389
+ this.write(typeof payload === "string" ? payload : payload);
390
+ return this.end();
391
+ };
392
+
393
+ ServerResponse.prototype.setTimeout = function setTimeout(ms: number, handler?: () => void): any {
394
+ if (handler) this.once("timeout", handler);
395
+ return this;
396
+ };
397
+
398
+ ServerResponse.prototype.json = function json(obj: unknown): any {
399
+ this.setHeader("Content-Type", "application/json");
400
+ return this.end(JSON.stringify(obj));
401
+ };
402
+
403
+ ServerResponse.prototype.status = function status(c: number): any {
404
+ this.statusCode = c;
405
+ return this;
406
+ };
407
+
408
+ ServerResponse.prototype.redirect = function redirect(target: string | number, loc?: string): void {
409
+ if (typeof target === "number") {
410
+ this.statusCode = target;
411
+ this.setHeader("Location", loc!);
412
+ } else {
413
+ this.statusCode = 302;
414
+ this.setHeader("Location", target);
415
+ }
416
+ this.end();
417
+ };
418
+
419
+ ServerResponse.prototype.addTrailers = function addTrailers(_headers: Record<string, string>): void {
420
+ // No-op
421
+ };
422
+
423
+ ServerResponse.prototype._collectedBody = function _collectedBody(): Buffer {
424
+ return Buffer.concat(this._chunks);
425
+ };
426
+
427
+ ServerResponse.prototype._collectedBodyText = function _collectedBodyText(): string {
428
+ return this._collectedBody().toString("utf8");
429
+ };
430
+
431
+ // Server
432
+
433
+ export interface Server extends EventEmitter {
434
+ listening: boolean;
435
+ maxHeadersCount: number | null;
436
+ timeout: number;
437
+ keepAliveTimeout: number;
438
+ headersTimeout: number;
439
+ requestTimeout: number;
440
+ maxRequestsPerSocket: number | null;
441
+ listen(portOrOpts?: any, hostOrCb?: any, cb?: any): this;
442
+ close(cb?: (err?: Error) => void): this;
443
+ address(): NetAddress | null;
444
+ setTimeout(ms?: number, handler?: () => void): this;
445
+ ref(): this;
446
+ unref(): this;
447
+ closeAllConnections(): void;
448
+ closeIdleConnections(): void;
449
+ dispatchUpgrade(target: string, hdrs: Record<string, string>): { req: IncomingMessage; socket: TcpSocket };
450
+ dispatchRequest(verb: string, target: string, hdrs: Record<string, string>, payload?: Buffer | string): Promise<CompletedResponse>;
451
+ }
452
+
453
+ export interface ServerConstructor {
454
+ new (optsOrHandler?: Record<string, unknown> | HttpHandler, handler?: HttpHandler): Server;
455
+ (this: any, optsOrHandler?: Record<string, unknown> | HttpHandler, handler?: HttpHandler): void;
456
+ prototype: any;
457
+ }
458
+
459
+ export const Server = function Server(
460
+ this: any,
461
+ optsOrHandler?: Record<string, unknown> | HttpHandler,
462
+ handler?: HttpHandler,
463
+ ) {
464
+ if (!this) return;
465
+ EventEmitter.call(this);
466
+
467
+ if (typeof optsOrHandler === "function") {
468
+ this._handler = optsOrHandler;
469
+ } else {
470
+ this._handler = handler;
471
+ }
472
+ this._tcp = new TcpServer();
473
+
474
+ this.listening = false;
475
+ this.maxHeadersCount = null;
476
+ this.timeout = 0;
477
+ this.keepAliveTimeout = TIMEOUTS.HTTP_KEEP_ALIVE;
478
+ this.headersTimeout = TIMEOUTS.HTTP_HEADERS;
479
+ this.requestTimeout = 0;
480
+ this.maxRequestsPerSocket = null;
481
+
482
+ const self = this;
483
+ this._tcp.on("listening", function onListening() {
484
+ self.listening = true;
485
+ self.emit("listening");
486
+ });
487
+ this._tcp.on("close", function onClose() {
488
+ self.listening = false;
489
+ self.emit("close");
490
+ });
491
+ this._tcp.on("error", function onError(e: unknown) { self.emit("error", e); });
492
+ } as unknown as ServerConstructor;
493
+
494
+ Object.setPrototypeOf(Server.prototype, EventEmitter.prototype);
495
+
496
+ Server.prototype.listen = function listen(
497
+ portOrOpts?: number | { port?: number; host?: string },
498
+ hostOrCb?: string | (() => void),
499
+ cb?: () => void,
500
+ ): any {
501
+ let port: number | undefined;
502
+ let host: string | undefined;
503
+ let done: (() => void) | undefined;
504
+
505
+ if (typeof portOrOpts === "number") {
506
+ port = portOrOpts;
507
+ if (typeof hostOrCb === "string") {
508
+ host = hostOrCb;
509
+ done = cb;
510
+ } else done = hostOrCb;
511
+ } else if (portOrOpts) {
512
+ port = portOrOpts.port;
513
+ host = portOrOpts.host;
514
+ done = typeof hostOrCb === "function" ? hostOrCb : cb;
515
+ }
516
+
517
+ const self = this;
518
+ const origDone = done;
519
+ done = function onBound() {
520
+ const addr = self._tcp.address();
521
+ if (addr) _addServer(addr.port, self);
522
+ if (origDone) origDone();
523
+ };
524
+
525
+ this._tcp.listen(port, host, done);
526
+ return this;
527
+ };
528
+
529
+ Server.prototype.close = function close(cb?: (err?: Error) => void): any {
530
+ const addr = this._tcp.address();
531
+ if (addr) _removeServer(addr.port);
532
+ this._tcp.close(cb);
533
+ return this;
534
+ };
535
+
536
+ Server.prototype.address = function address(): NetAddress | null {
537
+ return this._tcp.address();
538
+ };
539
+
540
+ Server.prototype.setTimeout = function setTimeout(ms?: number, handler?: () => void): any {
541
+ this.timeout = ms || 0;
542
+ if (handler) this.on("timeout", handler);
543
+ return this;
544
+ };
545
+
546
+ Server.prototype.ref = function ref(): any {
547
+ this._tcp.ref();
548
+ return this;
549
+ };
550
+
551
+ Server.prototype.unref = function unref(): any {
552
+ this._tcp.unref();
553
+ return this;
554
+ };
555
+
556
+ Server.prototype.closeAllConnections = function closeAllConnections(): void {
557
+ // No-op
558
+ };
559
+
560
+ Server.prototype.closeIdleConnections = function closeIdleConnections(): void {
561
+ // No-op
562
+ };
563
+
564
+ Server.prototype.dispatchUpgrade = function dispatchUpgrade(
565
+ target: string,
566
+ hdrs: Record<string, string>,
567
+ ): { req: IncomingMessage; socket: TcpSocket } {
568
+ const socket = new TcpSocket();
569
+ (socket as any).cork = () => {};
570
+ (socket as any).uncork = () => {};
571
+ (socket as any)._readableState = { endEmitted: false };
572
+ (socket as any)._writableState = { finished: false, errorEmitted: false };
573
+
574
+ const req = new IncomingMessage(socket);
575
+ req.method = "GET";
576
+ req.url = target;
577
+ req.headers = {
578
+ ...hdrs,
579
+ upgrade: "websocket",
580
+ connection: "Upgrade",
581
+ };
582
+ for (const [k, v] of Object.entries(req.headers)) {
583
+ if (typeof v === "string") req.rawHeaders.push(k, v);
584
+ }
585
+ req.push(null);
586
+ req.complete = true;
587
+
588
+ const self = this;
589
+ queueMicrotask(() => {
590
+ self.emit("upgrade", req, socket, Buffer.alloc(0));
591
+ });
592
+
593
+ return { req, socket };
594
+ };
595
+
596
+ Server.prototype.dispatchRequest = async function dispatchRequest(
597
+ verb: string,
598
+ target: string,
599
+ hdrs: Record<string, string>,
600
+ payload?: Buffer | string,
601
+ ): Promise<CompletedResponse> {
602
+ const self = this;
603
+ return new Promise((resolve, reject) => {
604
+ const req = IncomingMessage.build(verb, target, hdrs, payload);
605
+ const res = new ServerResponse(req);
606
+ res._onComplete(resolve);
607
+
608
+ const timeoutMs = self.timeout || TIMEOUTS.HTTP_DISPATCH_SAFETY;
609
+ const timer = setTimeout(() => {
610
+ reject(
611
+ new Error(
612
+ `dispatchRequest timed out after ${timeoutMs}ms for ${verb} ${target}`,
613
+ ),
614
+ );
615
+ }, timeoutMs);
616
+
617
+ res.on("finish", () => {
618
+ clearTimeout(timer);
619
+ });
620
+
621
+ try {
622
+ self.emit("request", req, res);
623
+ if (typeof self._handler === "function") {
624
+ const result = self._handler(req, res);
625
+ if (result && typeof (result as any).then === "function") {
626
+ (result as Promise<unknown>).catch((err) => {
627
+ clearTimeout(timer);
628
+ console.error("[DEBUG] dispatchRequest async error:", (err as Error)?.message || err, (err as Error)?.stack?.split("\n").slice(0, 5).join("\n"));
629
+ if (!res.headersSent) {
630
+ try {
631
+ res.statusCode = 500;
632
+ res.end("Internal Server Error");
633
+ } catch { /* ignore */ }
634
+ } else {
635
+ try { res.end(); } catch { /* ignore */ }
636
+ }
637
+ });
638
+ }
639
+ }
640
+ } catch (err) {
641
+ clearTimeout(timer);
642
+ console.error("[DEBUG] dispatchRequest sync error:", (err as Error)?.message || err, (err as Error)?.stack?.split("\n").slice(0, 5).join("\n"));
643
+ if (!res.headersSent) {
644
+ try {
645
+ res.statusCode = 500;
646
+ res.end("Internal Server Error");
647
+ } catch { /* ignore */ }
648
+ }
649
+ reject(err);
650
+ }
651
+ });
652
+ };
653
+
654
+ // createServer
655
+
656
+ export function createServer(
657
+ optsOrHandler?: Record<string, unknown> | HttpHandler,
658
+ handler?: HttpHandler,
659
+ ): Server {
660
+ return new Server(optsOrHandler, handler);
661
+ }
662
+
663
+ // STATUS_CODES & METHODS
664
+
665
+ export const STATUS_CODES: Record<number, string> = {
666
+ 100: "Continue",
667
+ 101: "Switching Protocols",
668
+ 200: "OK",
669
+ 201: "Created",
670
+ 202: "Accepted",
671
+ 204: "No Content",
672
+ 301: "Moved Permanently",
673
+ 302: "Found",
674
+ 304: "Not Modified",
675
+ 400: "Bad Request",
676
+ 401: "Unauthorized",
677
+ 403: "Forbidden",
678
+ 404: "Not Found",
679
+ 405: "Method Not Allowed",
680
+ 408: "Request Timeout",
681
+ 409: "Conflict",
682
+ 410: "Gone",
683
+ 413: "Payload Too Large",
684
+ 415: "Unsupported Media Type",
685
+ 422: "Unprocessable Entity",
686
+ 429: "Too Many Requests",
687
+ 500: "Internal Server Error",
688
+ 501: "Not Implemented",
689
+ 502: "Bad Gateway",
690
+ 503: "Service Unavailable",
691
+ 504: "Gateway Timeout",
692
+ };
693
+
694
+ export const METHODS = [
695
+ "GET",
696
+ "POST",
697
+ "PUT",
698
+ "DELETE",
699
+ "PATCH",
700
+ "HEAD",
701
+ "OPTIONS",
702
+ "CONNECT",
703
+ "TRACE",
704
+ ];
705
+
706
+ // CORS proxy helper
707
+
708
+ function fetchProxy(): string | null {
709
+ try {
710
+ return typeof localStorage !== "undefined"
711
+ ? (localStorage.getItem("__corsProxyUrl") ?? null)
712
+ : null;
713
+ } catch {
714
+ return null;
715
+ }
716
+ }
717
+
718
+ // ClientRequest (fetch-backed)
719
+
720
+ export interface ClientRequest extends Writable {
721
+ method: string;
722
+ path: string;
723
+ headers: Record<string, string>;
724
+ finished: boolean;
725
+ aborted: boolean;
726
+ reusedSocket: boolean;
727
+ maxHeadersCount: number | null;
728
+ readonly socket: TcpSocket;
729
+ readonly connection: TcpSocket;
730
+ setHeader(k: string, v: string): void;
731
+ getHeader(k: string): string | undefined;
732
+ removeHeader(k: string): void;
733
+ write(chunk: any, encOrCb?: any, cb?: any): boolean;
734
+ end(dataOrCb?: any, encOrCb?: any, cb?: any): this;
735
+ abort(): void;
736
+ setTimeout(ms: number, handler?: () => void): this;
737
+ flushHeaders(): void;
738
+ setNoDelay(noDelay?: boolean): void;
739
+ setSocketKeepAlive(enable?: boolean, initialDelay?: number): void;
740
+ }
741
+
742
+ export interface ClientRequestConstructor {
743
+ new (opts: ConnectionOptions, proto?: "http" | "https"): ClientRequest;
744
+ (this: any, opts: ConnectionOptions, proto?: "http" | "https"): void;
745
+ prototype: any;
746
+ }
747
+
748
+ export const ClientRequest = function ClientRequest(
749
+ this: any,
750
+ opts: ConnectionOptions,
751
+ proto?: "http" | "https",
752
+ ) {
753
+ if (!this) return;
754
+ Writable.call(this);
755
+
756
+ this._opts = opts;
757
+ this._proto = proto || "http";
758
+ this.method = opts.method ?? "GET";
759
+ this.path = opts.path ?? "/";
760
+ this.headers = {};
761
+ this._pending = [];
762
+ this._cancelled = false;
763
+ this._waitMs = null;
764
+ this._waitTimer = null;
765
+ this._sealed = false;
766
+ this._socket = new TcpSocket();
767
+ this.finished = false;
768
+ this.aborted = false;
769
+ this.reusedSocket = false;
770
+ this.maxHeadersCount = null;
771
+
772
+ if (opts.headers) {
773
+ for (const [k, v] of Object.entries(opts.headers)) {
774
+ this.headers[k.toLowerCase()] = Array.isArray(v) ? v.join(", ") : v;
775
+ }
776
+ }
777
+ // Emit socket event async
778
+ const self = this;
779
+ queueMicrotask(() => self.emit("socket", self._socket));
780
+ } as unknown as ClientRequestConstructor;
781
+
782
+ Object.setPrototypeOf(ClientRequest.prototype, Writable.prototype);
783
+
784
+ // Getters for socket/connection
785
+ Object.defineProperty(ClientRequest.prototype, "socket", {
786
+ get: function (this: any) { return this._socket; },
787
+ configurable: true,
788
+ });
789
+
790
+ Object.defineProperty(ClientRequest.prototype, "connection", {
791
+ get: function (this: any) { return this._socket; },
792
+ configurable: true,
793
+ });
794
+
795
+ ClientRequest.prototype.setHeader = function setHeader(k: string, v: string): void {
796
+ this.headers[k.toLowerCase()] = v;
797
+ };
798
+
799
+ ClientRequest.prototype.getHeader = function getHeader(k: string): string | undefined {
800
+ return this.headers[k.toLowerCase()];
801
+ };
802
+
803
+ ClientRequest.prototype.removeHeader = function removeHeader(k: string): void {
804
+ delete this.headers[k.toLowerCase()];
805
+ };
806
+
807
+ ClientRequest.prototype.write = function write(
808
+ chunk: Uint8Array | string,
809
+ encOrCb?: BufferEncoding | ((err?: Error | null) => void),
810
+ cb?: (err?: Error | null) => void,
811
+ ): boolean {
812
+ const buf = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
813
+ this._pending.push(buf);
814
+ const fn = typeof encOrCb === "function" ? encOrCb : cb;
815
+ if (fn) queueMicrotask(() => fn(null));
816
+ return true;
817
+ };
818
+
819
+ ClientRequest.prototype.end = function end(
820
+ dataOrCb?: Uint8Array | string | (() => void),
821
+ encOrCb?: BufferEncoding | (() => void),
822
+ cb?: () => void,
823
+ ): any {
824
+ if (this._sealed) return this;
825
+ this._sealed = true;
826
+ this.finished = true;
827
+
828
+ let finalCb = cb;
829
+ if (typeof dataOrCb === "function") {
830
+ finalCb = dataOrCb;
831
+ } else if (dataOrCb !== undefined) {
832
+ this.write(dataOrCb as Uint8Array | string);
833
+ }
834
+ if (typeof encOrCb === "function") finalCb = encOrCb;
835
+
836
+ const self = this;
837
+ self._dispatch()
838
+ .then(() => {
839
+ if (finalCb) finalCb();
840
+ })
841
+ .catch((err: Error) => self.emit("error", err));
842
+
843
+ return this;
844
+ };
845
+
846
+ ClientRequest.prototype.abort = function abort(): void {
847
+ this._cancelled = true;
848
+ this.aborted = true;
849
+ if (this._waitTimer) clearTimeout(this._waitTimer);
850
+ this.emit("abort");
851
+ };
852
+
853
+ ClientRequest.prototype.setTimeout = function setTimeout(ms: number, handler?: () => void): any {
854
+ this._waitMs = ms;
855
+ if (handler) this.once("timeout", handler);
856
+ return this;
857
+ };
858
+
859
+ ClientRequest.prototype.flushHeaders = function flushHeaders(): void {
860
+ // No-op
861
+ };
862
+
863
+ ClientRequest.prototype.setNoDelay = function setNoDelay(_noDelay?: boolean): void {
864
+ // No-op
865
+ };
866
+
867
+ ClientRequest.prototype.setSocketKeepAlive = function setSocketKeepAlive(
868
+ _enable?: boolean,
869
+ _initialDelay?: number,
870
+ ): void {
871
+ // No-op
872
+ };
873
+
874
+ /* ---------- ClientRequest internal dispatch ---------- */
875
+
876
+ ClientRequest.prototype._dispatch = async function _dispatch(): Promise<void> {
877
+ if (this._cancelled) return;
878
+
879
+ try {
880
+ const scheme = this._proto === "https" ? "https:" : "http:";
881
+ let hostname = this._opts.hostname ?? "";
882
+ let portSuffix = this._opts.port ? `:${this._opts.port}` : "";
883
+ if (!hostname && this._opts.host) {
884
+ const parts = this._opts.host.split(":");
885
+ hostname = parts[0];
886
+ if (!portSuffix && parts[1]) portSuffix = `:${parts[1]}`;
887
+ }
888
+ if (!hostname) hostname = "localhost";
889
+ const endpoint = `${scheme}//${hostname}${portSuffix}${this._opts.path ?? "/"}`;
890
+
891
+ // WebSocket upgrade -- delegate to native browser WS
892
+ if (this.headers["upgrade"]?.toLowerCase() === "websocket") {
893
+ this._bridgeWebSocket(endpoint);
894
+ return;
895
+ }
896
+
897
+ // Route requests to virtual servers through the registry instead of fetch
898
+ const isLocal = hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0";
899
+ const port = Number(this._opts.port) || (this._proto === "https" ? 443 : 80);
900
+ if (isLocal) {
901
+ const vServer = _registry.get(port);
902
+ if (vServer) {
903
+ const body = this._pending.length > 0 ? Buffer.concat(this._pending) : undefined;
904
+ try {
905
+ const result = await vServer.dispatchRequest(
906
+ this.method,
907
+ this._opts.path ?? "/",
908
+ this.headers,
909
+ body,
910
+ );
911
+ if (this._cancelled) return;
912
+ const incoming = new IncomingMessage();
913
+ incoming.statusCode = result.statusCode;
914
+ incoming.statusMessage = result.statusMessage;
915
+ for (const [k, v] of Object.entries(result.headers)) {
916
+ incoming.headers[k.toLowerCase()] = v;
917
+ incoming.rawHeaders.push(k, v);
918
+ }
919
+ incoming._injectBody(result.body);
920
+ this.emit("response", incoming);
921
+ } catch (err) {
922
+ this.emit("error", err);
923
+ }
924
+ return;
925
+ }
926
+ // No virtual server on this port — emit ECONNREFUSED
927
+ const err = new Error(`connect ECONNREFUSED ${hostname}:${port}`) as NodeJS.ErrnoException;
928
+ err.code = "ECONNREFUSED";
929
+ err.errno = -111;
930
+ (err as any).syscall = "connect";
931
+ (err as any).address = hostname;
932
+ (err as any).port = port;
933
+ this.emit("error", err);
934
+ return;
935
+ }
936
+
937
+ const proxy = fetchProxy();
938
+ const targetUrl = proxy ? proxy + encodeURIComponent(endpoint) : endpoint;
939
+
940
+ const init: RequestInit = { method: this.method, headers: this.headers };
941
+ if (
942
+ this._pending.length > 0 &&
943
+ this.method !== "GET" &&
944
+ this.method !== "HEAD"
945
+ ) {
946
+ init.body = Buffer.concat(this._pending);
947
+ }
948
+
949
+ const ac = new AbortController();
950
+ init.signal = ac.signal;
951
+
952
+ if (this._waitMs) {
953
+ this._waitTimer = setTimeout(() => {
954
+ ac.abort();
955
+ this.emit("timeout");
956
+ }, this._waitMs);
957
+ }
958
+
959
+ const resp = await fetch(targetUrl, init);
960
+ if (this._waitTimer) {
961
+ clearTimeout(this._waitTimer);
962
+ this._waitTimer = null;
963
+ }
964
+ if (this._cancelled) return;
965
+
966
+ const incoming = await this._mapResponse(resp);
967
+ this.emit("response", incoming);
968
+ } catch (err) {
969
+ if (this._waitTimer) clearTimeout(this._waitTimer);
970
+ if (this._cancelled) return;
971
+ if (err instanceof Error && err.name === "AbortError") return;
972
+ this.emit("error", err);
973
+ }
974
+ };
975
+
976
+ ClientRequest.prototype._mapResponse = async function _mapResponse(resp: Response): Promise<IncomingMessage> {
977
+ const msg = new IncomingMessage();
978
+ msg.statusCode = resp.status;
979
+ msg.statusMessage = resp.statusText || STATUS_CODES[resp.status] || "";
980
+ resp.headers.forEach((v: string, k: string) => {
981
+ msg.headers[k.toLowerCase()] = v;
982
+ msg.rawHeaders.push(k, v);
983
+ });
984
+ const raw = await resp.arrayBuffer();
985
+ msg._injectBody(Buffer.from(raw));
986
+ return msg;
987
+ };
988
+
989
+ /* ---------- WebSocket upgrade bridge ---------- */
990
+
991
+ ClientRequest.prototype._bridgeWebSocket = function _bridgeWebSocket(url: string): void {
992
+ const wsUrl = url.replace(/^https:/, "wss:").replace(/^http:/, "ws:");
993
+ const wsKey = this.headers["sec-websocket-key"] ?? "";
994
+ const WS = _NativeWebSocket;
995
+
996
+ if (!WS) {
997
+ const self = this;
998
+ setTimeout(
999
+ () => self.emit("error", new TypeError("No WebSocket available")),
1000
+ 0,
1001
+ );
1002
+ return;
1003
+ }
1004
+
1005
+ const WS_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
1006
+ const acceptDigest = createHash("sha1")
1007
+ .update(wsKey + WS_GUID)
1008
+ .digest("base64") as string;
1009
+
1010
+ let ws: globalThis.WebSocket;
1011
+ try {
1012
+ ws = new WS(wsUrl);
1013
+ ws.binaryType = "arraybuffer";
1014
+ } catch (e) {
1015
+ const self = this;
1016
+ setTimeout(
1017
+ () => self.emit("error", e instanceof Error ? e : new Error(String(e))),
1018
+ 0,
1019
+ );
1020
+ return;
1021
+ }
1022
+
1023
+ const pipe = new TcpSocket();
1024
+ (pipe as any).cork = () => {};
1025
+ (pipe as any).uncork = () => {};
1026
+ (pipe as any)._readableState = { endEmitted: false };
1027
+ (pipe as any)._writableState = { finished: false, errorEmitted: false };
1028
+
1029
+ let outboundBuf = new Uint8Array(0);
1030
+
1031
+ pipe.write = ((
1032
+ chunk: Uint8Array | string,
1033
+ encOrCb?: BufferEncoding | ((err?: Error | null) => void),
1034
+ cb?: (err?: Error | null) => void,
1035
+ ): boolean => {
1036
+ const raw =
1037
+ typeof chunk === "string" ? Buffer.from(chunk) : new Uint8Array(chunk);
1038
+ const fn = typeof encOrCb === "function" ? encOrCb : cb;
1039
+
1040
+ const merged = new Uint8Array(outboundBuf.length + raw.length);
1041
+ merged.set(outboundBuf, 0);
1042
+ merged.set(raw, outboundBuf.length);
1043
+ outboundBuf = merged;
1044
+
1045
+ while (outboundBuf.length >= 2) {
1046
+ const frame = decodeFrame(outboundBuf);
1047
+ if (!frame) break;
1048
+ outboundBuf = outboundBuf.slice(frame.consumed);
1049
+
1050
+ if (ws.readyState !== WS.OPEN) continue;
1051
+
1052
+ switch (frame.op) {
1053
+ case 0x08:
1054
+ ws.close();
1055
+ break;
1056
+ case 0x09:
1057
+ ws.send(frame.data);
1058
+ break;
1059
+ case 0x0a:
1060
+ break; // pong -- ignore
1061
+ case 0x01:
1062
+ ws.send(new TextDecoder().decode(frame.data));
1063
+ break;
1064
+ case 0x02:
1065
+ ws.send(frame.data);
1066
+ break;
1067
+ }
1068
+ }
1069
+
1070
+ if (fn) queueMicrotask(() => fn(null));
1071
+ return true;
1072
+ }) as any;
1073
+
1074
+ const self = this;
1075
+
1076
+ ws.onopen = () => {
1077
+ const fakeResp = new IncomingMessage(pipe);
1078
+ fakeResp.statusCode = 101;
1079
+ fakeResp.statusMessage = "Switching Protocols";
1080
+ fakeResp.headers = {
1081
+ upgrade: "websocket",
1082
+ connection: "Upgrade",
1083
+ "sec-websocket-accept": acceptDigest,
1084
+ };
1085
+ fakeResp.complete = true;
1086
+ fakeResp.push(null);
1087
+ self.emit("upgrade", fakeResp, pipe, Buffer.alloc(0));
1088
+ };
1089
+
1090
+ ws.onmessage = (ev: MessageEvent) => {
1091
+ let payload: Uint8Array;
1092
+ let op: number;
1093
+ if (typeof ev.data === "string") {
1094
+ payload = new TextEncoder().encode(ev.data);
1095
+ op = 0x01;
1096
+ } else if (ev.data instanceof ArrayBuffer) {
1097
+ payload = new Uint8Array(ev.data);
1098
+ op = 0x02;
1099
+ } else {
1100
+ return;
1101
+ }
1102
+ const frame = encodeFrame(op, payload, false);
1103
+ pipe._feedData(Buffer.from(frame));
1104
+ };
1105
+
1106
+ ws.onclose = (ev: CloseEvent) => {
1107
+ const code = ev.code || 1000;
1108
+ const closeBuf = new Uint8Array(2);
1109
+ closeBuf[0] = (code >> 8) & 0xff;
1110
+ closeBuf[1] = code & 0xff;
1111
+ const frame = encodeFrame(0x08, closeBuf, false);
1112
+ pipe._feedData(Buffer.from(frame));
1113
+ setTimeout(() => {
1114
+ (pipe as any)._readableState.endEmitted = true;
1115
+ pipe._feedEnd();
1116
+ pipe.emit("close", false);
1117
+ }, 10);
1118
+ };
1119
+
1120
+ ws.onerror = () => {
1121
+ pipe.emit("error", new Error("WebSocket transport error"));
1122
+ pipe.destroy();
1123
+ };
1124
+
1125
+ const origDestroy = pipe.destroy.bind(pipe);
1126
+ pipe.destroy = ((e?: Error): TcpSocket => {
1127
+ if (ws.readyState === WS.OPEN || ws.readyState === WS.CONNECTING)
1128
+ ws.close();
1129
+ return origDestroy(e);
1130
+ }) as any;
1131
+ };
1132
+
1133
+ // Argument parsing helper
1134
+
1135
+ function dissectArgs(
1136
+ first: string | URL | ConnectionOptions,
1137
+ second?: ConnectionOptions | ((r: IncomingMessage) => void),
1138
+ third?: (r: IncomingMessage) => void,
1139
+ ): { opts: ConnectionOptions; cb?: (r: IncomingMessage) => void } {
1140
+ let opts: ConnectionOptions;
1141
+ let cb = third;
1142
+
1143
+ if (typeof first === "string" || first instanceof URL) {
1144
+ const parsed = new URL(first.toString());
1145
+ opts = {
1146
+ hostname: parsed.hostname,
1147
+ port: parsed.port ? parseInt(parsed.port, 10) : undefined,
1148
+ path: parsed.pathname + parsed.search,
1149
+ method: "GET",
1150
+ };
1151
+ if (typeof second === "function") cb = second;
1152
+ else if (second) opts = { ...opts, ...second };
1153
+ } else {
1154
+ opts = first;
1155
+ if (typeof second === "function") cb = second;
1156
+ }
1157
+
1158
+ return { opts, cb };
1159
+ }
1160
+
1161
+ // request / get
1162
+
1163
+ export function request(
1164
+ first: string | URL | ConnectionOptions,
1165
+ second?: ConnectionOptions | ((r: IncomingMessage) => void),
1166
+ third?: (r: IncomingMessage) => void,
1167
+ ): ClientRequest {
1168
+ const { opts, cb } = dissectArgs(first, second, third);
1169
+ const cr = new ClientRequest(opts, "http");
1170
+ if (cb) cr.once("response", cb as unknown as EventHandler);
1171
+ return cr;
1172
+ }
1173
+
1174
+ export function get(
1175
+ first: string | URL | ConnectionOptions,
1176
+ second?: ConnectionOptions | ((r: IncomingMessage) => void),
1177
+ third?: (r: IncomingMessage) => void,
1178
+ ): ClientRequest {
1179
+ const { opts, cb } = dissectArgs(first, second, third);
1180
+ const cr = new ClientRequest({ ...opts, method: "GET" }, "http");
1181
+ if (cb) cr.once("response", cb as unknown as EventHandler);
1182
+ cr.end();
1183
+ return cr;
1184
+ }
1185
+
1186
+ export function _buildClientRequest(
1187
+ first: string | URL | ConnectionOptions,
1188
+ second: ConnectionOptions | ((r: IncomingMessage) => void) | undefined,
1189
+ third: ((r: IncomingMessage) => void) | undefined,
1190
+ proto: "http" | "https",
1191
+ ): ClientRequest {
1192
+ const { opts, cb } = dissectArgs(first, second, third);
1193
+ const cr = new ClientRequest(opts, proto);
1194
+ if (cb) cr.once("response", cb as unknown as EventHandler);
1195
+ return cr;
1196
+ }
1197
+
1198
+ // Server registry (global, for server bridge routing)
1199
+
1200
+ export type RegistryHook = (port: number, srv: Server) => void;
1201
+
1202
+ const _registry = new Map<number, Server>();
1203
+ const _serverOwnership = new Map<number, number>(); // port → pid
1204
+ let _onBind: RegistryHook | null = null;
1205
+ let _onUnbind: ((port: number) => void) | null = null;
1206
+
1207
+ function _addServer(port: number, srv: Server, ownerPid?: number): void {
1208
+ _registry.set(port, srv);
1209
+ if (ownerPid !== undefined) _serverOwnership.set(port, ownerPid);
1210
+ _elRef(); // server keeps the process alive
1211
+ if (_onBind) _onBind(port, srv);
1212
+ }
1213
+
1214
+ function _removeServer(port: number): void {
1215
+ if (_registry.has(port)) _elUnref(); // server no longer keeps process alive
1216
+ _registry.delete(port);
1217
+ _serverOwnership.delete(port);
1218
+ if (_onUnbind) _onUnbind(port);
1219
+ }
1220
+
1221
+ export function getServer(port: number): Server | undefined {
1222
+ return _registry.get(port);
1223
+ }
1224
+
1225
+ export function getAllServers(): Map<number, Server> {
1226
+ return new Map(_registry);
1227
+ }
1228
+
1229
+ export function closeAllServers(): void {
1230
+ for (const [, srv] of _registry) {
1231
+ try { srv.close(); } catch { /* best effort */ }
1232
+ }
1233
+ _registry.clear();
1234
+ _serverOwnership.clear();
1235
+ }
1236
+
1237
+ export function closeServersByPid(pid: number): void {
1238
+ for (const [port, ownerPid] of _serverOwnership) {
1239
+ if (ownerPid === pid) {
1240
+ const srv = _registry.get(port);
1241
+ if (srv) {
1242
+ try { srv.close(); } catch { /* best effort */ }
1243
+ }
1244
+ _registry.delete(port);
1245
+ _serverOwnership.delete(port);
1246
+ }
1247
+ }
1248
+ }
1249
+
1250
+ export function getServerOwner(port: number): number | undefined {
1251
+ return _serverOwnership.get(port);
1252
+ }
1253
+
1254
+ export function setServerListenCallback(fn: RegistryHook | null): void {
1255
+ _onBind = fn;
1256
+ }
1257
+
1258
+ export function setServerCloseCallback(
1259
+ fn: ((port: number) => void) | null,
1260
+ ): void {
1261
+ _onUnbind = fn;
1262
+ }
1263
+
1264
+ // Agent
1265
+
1266
+ export interface AgentConfig {
1267
+ keepAlive?: boolean;
1268
+ keepAliveMsecs?: number;
1269
+ maxSockets?: number;
1270
+ maxTotalSockets?: number;
1271
+ maxFreeSockets?: number;
1272
+ scheduling?: "fifo" | "lifo";
1273
+ timeout?: number;
1274
+ }
1275
+
1276
+ export interface Agent extends EventEmitter {
1277
+ maxSockets: number;
1278
+ maxFreeSockets: number;
1279
+ maxTotalSockets: number;
1280
+ sockets: Record<string, TcpSocket[]>;
1281
+ freeSockets: Record<string, TcpSocket[]>;
1282
+ requests: Record<string, IncomingMessage[]>;
1283
+ options: AgentConfig;
1284
+ createConnection(cfg: Record<string, unknown>, done?: (err: Error | null, sock: TcpSocket) => void): TcpSocket;
1285
+ getName(o: { host?: string; port?: number; localAddress?: string }): string;
1286
+ addRequest(r: ClientRequest, o: Record<string, unknown>): void;
1287
+ destroy(): void;
1288
+ }
1289
+
1290
+ export interface AgentConstructor {
1291
+ new (cfg?: AgentConfig): Agent;
1292
+ (this: any, cfg?: AgentConfig): void;
1293
+ prototype: any;
1294
+ }
1295
+
1296
+ export const Agent = function Agent(this: any, cfg?: AgentConfig) {
1297
+ if (!this) return;
1298
+ EventEmitter.call(this);
1299
+
1300
+ this.options = cfg ?? {};
1301
+ this.maxSockets = cfg?.maxSockets ?? Infinity;
1302
+ this.maxFreeSockets = cfg?.maxFreeSockets ?? 256;
1303
+ this.maxTotalSockets = cfg?.maxTotalSockets ?? Infinity;
1304
+ this.sockets = {};
1305
+ this.freeSockets = {};
1306
+ this.requests = {};
1307
+ } as unknown as AgentConstructor;
1308
+
1309
+ Object.setPrototypeOf(Agent.prototype, EventEmitter.prototype);
1310
+
1311
+ Agent.prototype.createConnection = function createConnection(
1312
+ _cfg: Record<string, unknown>,
1313
+ done?: (err: Error | null, sock: TcpSocket) => void,
1314
+ ): TcpSocket {
1315
+ const sock = new TcpSocket();
1316
+ if (done) done(null, sock);
1317
+ return sock;
1318
+ };
1319
+
1320
+ Agent.prototype.getName = function getName(
1321
+ o: { host?: string; port?: number; localAddress?: string },
1322
+ ): string {
1323
+ return `${o.host ?? "localhost"}:${o.port ?? 80}:${o.localAddress ?? ""}`;
1324
+ };
1325
+
1326
+ Agent.prototype.addRequest = function addRequest(
1327
+ _r: ClientRequest,
1328
+ _o: Record<string, unknown>,
1329
+ ): void {};
1330
+
1331
+ Agent.prototype.destroy = function destroy(): void {
1332
+ this.sockets = {};
1333
+ this.freeSockets = {};
1334
+ this.requests = {};
1335
+ };
1336
+
1337
+ export const globalAgent = new Agent();
1338
+
1339
+ // WebSocket frame codec
1340
+
1341
+ export function decodeFrame(raw: Uint8Array): {
1342
+ op: number;
1343
+ data: Uint8Array;
1344
+ consumed: number;
1345
+ } | null {
1346
+ if (raw.length < 2) return null;
1347
+
1348
+ const op = raw[0] & 0x0f;
1349
+ const isMasked = (raw[1] & 0x80) !== 0;
1350
+ let len = raw[1] & 0x7f;
1351
+ let cursor = 2;
1352
+
1353
+ if (len === 126) {
1354
+ if (raw.length < 4) return null;
1355
+ len = (raw[2] << 8) | raw[3];
1356
+ cursor = 4;
1357
+ } else if (len === 127) {
1358
+ if (raw.length < 10) return null;
1359
+ len = (raw[6] << 24) | (raw[7] << 16) | (raw[8] << 8) | raw[9];
1360
+ cursor = 10;
1361
+ }
1362
+
1363
+ if (isMasked) {
1364
+ if (raw.length < cursor + 4 + len) return null;
1365
+ const mask = raw.slice(cursor, cursor + 4);
1366
+ cursor += 4;
1367
+ const payload = new Uint8Array(len);
1368
+ for (let i = 0; i < len; i++) payload[i] = raw[cursor + i] ^ mask[i & 3];
1369
+ return { op, data: payload, consumed: cursor + len };
1370
+ }
1371
+
1372
+ if (raw.length < cursor + len) return null;
1373
+ return { op, data: raw.slice(cursor, cursor + len), consumed: cursor + len };
1374
+ }
1375
+
1376
+ export function encodeFrame(
1377
+ op: number,
1378
+ payload: Uint8Array,
1379
+ masked: boolean,
1380
+ ): Uint8Array {
1381
+ const pLen = payload.length;
1382
+ let headerLen = 2;
1383
+ if (pLen > 125 && pLen <= 0xffff) headerLen += 2;
1384
+ else if (pLen > 0xffff) headerLen += 8;
1385
+ if (masked) headerLen += 4;
1386
+
1387
+ const frame = new Uint8Array(headerLen + pLen);
1388
+ frame[0] = 0x80 | op;
1389
+
1390
+ let pos = 2;
1391
+ if (pLen <= 125) {
1392
+ frame[1] = (masked ? 0x80 : 0) | pLen;
1393
+ } else if (pLen <= 0xffff) {
1394
+ frame[1] = (masked ? 0x80 : 0) | 126;
1395
+ frame[2] = (pLen >> 8) & 0xff;
1396
+ frame[3] = pLen & 0xff;
1397
+ pos = 4;
1398
+ } else {
1399
+ frame[1] = (masked ? 0x80 : 0) | 127;
1400
+ frame[2] = 0;
1401
+ frame[3] = 0;
1402
+ frame[4] = 0;
1403
+ frame[5] = 0;
1404
+ frame[6] = (pLen >> 24) & 0xff;
1405
+ frame[7] = (pLen >> 16) & 0xff;
1406
+ frame[8] = (pLen >> 8) & 0xff;
1407
+ frame[9] = pLen & 0xff;
1408
+ pos = 10;
1409
+ }
1410
+
1411
+ if (masked) {
1412
+ const maskKey = new Uint8Array(4);
1413
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
1414
+ crypto.getRandomValues(maskKey);
1415
+ } else {
1416
+ for (let i = 0; i < 4; i++) maskKey[i] = Math.floor(Math.random() * 256);
1417
+ }
1418
+ frame.set(maskKey, pos);
1419
+ pos += 4;
1420
+ for (let i = 0; i < pLen; i++) frame[pos + i] = payload[i] ^ maskKey[i & 3];
1421
+ } else {
1422
+ frame.set(payload, pos);
1423
+ }
1424
+
1425
+ return frame;
1426
+ }
1427
+
1428
+ // Default export
1429
+
1430
+ export default {
1431
+ Server,
1432
+ IncomingMessage,
1433
+ ServerResponse,
1434
+ ClientRequest,
1435
+ createServer,
1436
+ request,
1437
+ get,
1438
+ STATUS_CODES,
1439
+ METHODS,
1440
+ getServer,
1441
+ getAllServers,
1442
+ setServerListenCallback,
1443
+ setServerCloseCallback,
1444
+ _buildClientRequest,
1445
+ Agent,
1446
+ globalAgent,
1447
+ decodeFrame,
1448
+ encodeFrame,
1449
+ };