srvx 0.6.0 → 0.7.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/dist/node.mjs ADDED
@@ -0,0 +1,813 @@
1
+ import { FastURL, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions } from "./_url.mjs";
2
+ import { wrapFetch } from "./_middleware.mjs";
3
+ import { errorPlugin } from "./_plugins.mjs";
4
+ import { splitSetCookieString } from "cookie-es";
5
+
6
+ //#region src/adapters/_node/send.ts
7
+ async function sendNodeResponse(nodeRes, webRes) {
8
+ if (!webRes) {
9
+ nodeRes.statusCode = 500;
10
+ return endNodeResponse(nodeRes);
11
+ }
12
+ if (webRes.nodeResponse) {
13
+ const res = webRes.nodeResponse();
14
+ writeHead(nodeRes, res.status, res.statusText, res.headers.flat());
15
+ if (res.body) {
16
+ if (res.body instanceof ReadableStream) return streamBody(res.body, nodeRes);
17
+ else if (typeof res.body?.pipe === "function") {
18
+ res.body.pipe(nodeRes);
19
+ return new Promise((resolve) => nodeRes.on("close", resolve));
20
+ }
21
+ nodeRes.write(res.body);
22
+ }
23
+ return endNodeResponse(nodeRes);
24
+ }
25
+ const headerEntries = [];
26
+ for (const [key, value] of webRes.headers) if (key === "set-cookie") for (const setCookie of splitSetCookieString(value)) headerEntries.push(["set-cookie", setCookie]);
27
+ else headerEntries.push([key, value]);
28
+ writeHead(nodeRes, webRes.status, webRes.statusText, headerEntries.flat());
29
+ return webRes.body ? streamBody(webRes.body, nodeRes) : endNodeResponse(nodeRes);
30
+ }
31
+ function writeHead(nodeRes, status, statusText, headers) {
32
+ if (!nodeRes.headersSent) if (nodeRes.req?.httpVersion === "2.0") nodeRes.writeHead(status, headers.flat());
33
+ else nodeRes.writeHead(status, statusText, headers.flat());
34
+ }
35
+ function endNodeResponse(nodeRes) {
36
+ return new Promise((resolve) => nodeRes.end(resolve));
37
+ }
38
+ function streamBody(stream, nodeRes) {
39
+ if (nodeRes.destroyed) {
40
+ stream.cancel();
41
+ return;
42
+ }
43
+ const reader = stream.getReader();
44
+ function streamCancel(error) {
45
+ reader.cancel(error).catch(() => {});
46
+ if (error) nodeRes.destroy(error);
47
+ }
48
+ function streamHandle({ done, value }) {
49
+ try {
50
+ if (done) nodeRes.end();
51
+ else if (nodeRes.write(value)) reader.read().then(streamHandle, streamCancel);
52
+ else nodeRes.once("drain", () => reader.read().then(streamHandle, streamCancel));
53
+ } catch (error) {
54
+ streamCancel(error instanceof Error ? error : void 0);
55
+ }
56
+ }
57
+ nodeRes.on("close", streamCancel);
58
+ nodeRes.on("error", streamCancel);
59
+ reader.read().then(streamHandle, streamCancel);
60
+ return reader.closed.finally(() => {
61
+ nodeRes.off("close", streamCancel);
62
+ nodeRes.off("error", streamCancel);
63
+ });
64
+ }
65
+
66
+ //#endregion
67
+ //#region src/adapters/_node/_common.ts
68
+ const kNodeInspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
69
+
70
+ //#endregion
71
+ //#region src/adapters/_node/headers.ts
72
+ const NodeRequestHeaders = /* @__PURE__ */ (() => {
73
+ const _Headers = class Headers$1 {
74
+ _node;
75
+ constructor(nodeCtx) {
76
+ this._node = nodeCtx;
77
+ }
78
+ append(name, value) {
79
+ name = validateHeader(name);
80
+ const _headers = this._node.req.headers;
81
+ const _current = _headers[name];
82
+ if (_current) if (Array.isArray(_current)) _current.push(value);
83
+ else _headers[name] = [_current, value];
84
+ else _headers[name] = value;
85
+ }
86
+ delete(name) {
87
+ name = validateHeader(name);
88
+ this._node.req.headers[name] = void 0;
89
+ }
90
+ get(name) {
91
+ name = validateHeader(name);
92
+ const rawValue = this._node.req.headers[name];
93
+ if (rawValue === void 0) return null;
94
+ return _normalizeValue(this._node.req.headers[name]);
95
+ }
96
+ getSetCookie() {
97
+ const setCookie = this._node.req.headers["set-cookie"];
98
+ if (!setCookie || setCookie.length === 0) return [];
99
+ return splitSetCookieString(setCookie);
100
+ }
101
+ has(name) {
102
+ name = validateHeader(name);
103
+ return !!this._node.req.headers[name];
104
+ }
105
+ set(name, value) {
106
+ name = validateHeader(name);
107
+ this._node.req.headers[name] = value;
108
+ }
109
+ get count() {
110
+ throw new Error("Method not implemented.");
111
+ }
112
+ getAll(_name) {
113
+ throw new Error("Method not implemented.");
114
+ }
115
+ toJSON() {
116
+ const _headers = this._node.req.headers;
117
+ const result = {};
118
+ for (const key in _headers) if (_headers[key]) result[key] = _normalizeValue(_headers[key]);
119
+ return result;
120
+ }
121
+ forEach(cb, thisArg) {
122
+ const _headers = this._node.req.headers;
123
+ for (const key in _headers) if (_headers[key]) cb.call(thisArg, _normalizeValue(_headers[key]), key, this);
124
+ }
125
+ *entries() {
126
+ const headers = this._node.req.headers;
127
+ const isHttp2 = this._node.req.httpVersion === "2.0";
128
+ for (const key in headers) if (!isHttp2 || key[0] !== ":") yield [key, _normalizeValue(headers[key])];
129
+ }
130
+ *keys() {
131
+ const keys = Object.keys(this._node.req.headers);
132
+ for (const key of keys) yield key;
133
+ }
134
+ *values() {
135
+ const values = Object.values(this._node.req.headers);
136
+ for (const value of values) yield _normalizeValue(value);
137
+ }
138
+ [Symbol.iterator]() {
139
+ return this.entries()[Symbol.iterator]();
140
+ }
141
+ get [Symbol.toStringTag]() {
142
+ return "Headers";
143
+ }
144
+ [kNodeInspect]() {
145
+ return Object.fromEntries(this.entries());
146
+ }
147
+ };
148
+ Object.setPrototypeOf(_Headers.prototype, globalThis.Headers.prototype);
149
+ return _Headers;
150
+ })();
151
+ const NodeResponseHeaders = /* @__PURE__ */ (() => {
152
+ const _Headers = class Headers$1 {
153
+ _node;
154
+ constructor(nodeCtx) {
155
+ this._node = nodeCtx;
156
+ }
157
+ append(name, value) {
158
+ this._node.res.appendHeader(name, value);
159
+ }
160
+ delete(name) {
161
+ this._node.res.removeHeader(name);
162
+ }
163
+ get(name) {
164
+ const rawValue = this._node.res.getHeader(name);
165
+ if (rawValue === void 0) return null;
166
+ return _normalizeValue(rawValue);
167
+ }
168
+ getSetCookie() {
169
+ const setCookie = _normalizeValue(this._node.res.getHeader("set-cookie"));
170
+ if (!setCookie) return [];
171
+ return splitSetCookieString(setCookie);
172
+ }
173
+ has(name) {
174
+ return this._node.res.hasHeader(name);
175
+ }
176
+ set(name, value) {
177
+ this._node.res.setHeader(name, value);
178
+ }
179
+ get count() {
180
+ throw new Error("Method not implemented.");
181
+ }
182
+ getAll(_name) {
183
+ throw new Error("Method not implemented.");
184
+ }
185
+ toJSON() {
186
+ const _headers = this._node.res.getHeaders();
187
+ const result = {};
188
+ for (const key in _headers) if (_headers[key]) result[key] = _normalizeValue(_headers[key]);
189
+ return result;
190
+ }
191
+ forEach(cb, thisArg) {
192
+ const _headers = this._node.res.getHeaders();
193
+ for (const key in _headers) if (_headers[key]) cb.call(thisArg, _normalizeValue(_headers[key]), key, this);
194
+ }
195
+ *entries() {
196
+ const _headers = this._node.res.getHeaders();
197
+ for (const key in _headers) yield [key, _normalizeValue(_headers[key])];
198
+ }
199
+ *keys() {
200
+ const keys = this._node.res.getHeaderNames();
201
+ for (const key of keys) yield key;
202
+ }
203
+ *values() {
204
+ const values = Object.values(this._node.res.getHeaders());
205
+ for (const value of values) yield _normalizeValue(value);
206
+ }
207
+ [Symbol.iterator]() {
208
+ return this.entries()[Symbol.iterator]();
209
+ }
210
+ get [Symbol.toStringTag]() {
211
+ return "Headers";
212
+ }
213
+ [kNodeInspect]() {
214
+ return Object.fromEntries(this.entries());
215
+ }
216
+ };
217
+ Object.setPrototypeOf(_Headers.prototype, globalThis.Headers.prototype);
218
+ return _Headers;
219
+ })();
220
+ function _normalizeValue(value) {
221
+ if (Array.isArray(value)) return value.join(", ");
222
+ return typeof value === "string" ? value : String(value ?? "");
223
+ }
224
+ function validateHeader(name) {
225
+ if (name[0] === ":") throw new TypeError("Invalid header name");
226
+ return name.toLowerCase();
227
+ }
228
+
229
+ //#endregion
230
+ //#region src/adapters/_node/url.ts
231
+ const NodeRequestURL = /* @__PURE__ */ (() => {
232
+ const _URL = class URL {
233
+ _node;
234
+ _hash = "";
235
+ _username = "";
236
+ _password = "";
237
+ _protocol;
238
+ _hostname;
239
+ _port;
240
+ _pathname;
241
+ _search;
242
+ _searchParams;
243
+ constructor(nodeCtx) {
244
+ this._node = nodeCtx;
245
+ }
246
+ get hash() {
247
+ return this._hash;
248
+ }
249
+ set hash(value) {
250
+ this._hash = value;
251
+ }
252
+ get username() {
253
+ return this._username;
254
+ }
255
+ set username(value) {
256
+ this._username = value;
257
+ }
258
+ get password() {
259
+ return this._password;
260
+ }
261
+ set password(value) {
262
+ this._password = value;
263
+ }
264
+ get host() {
265
+ return this._node.req.headers.host || this._node.req.headers[":authority"] || "";
266
+ }
267
+ set host(value) {
268
+ this._hostname = void 0;
269
+ this._port = void 0;
270
+ this._node.req.headers.host = value;
271
+ }
272
+ get hostname() {
273
+ if (this._hostname === void 0) {
274
+ const [hostname, port] = parseHost(this._node.req.headers.host);
275
+ if (this._port === void 0 && port) this._port = String(Number.parseInt(port) || "");
276
+ this._hostname = hostname || "localhost";
277
+ }
278
+ return this._hostname;
279
+ }
280
+ set hostname(value) {
281
+ this._hostname = value;
282
+ }
283
+ get port() {
284
+ if (this._port === void 0) {
285
+ const [hostname, port] = parseHost(this._node.req.headers.host);
286
+ if (this._hostname === void 0 && hostname) this._hostname = hostname;
287
+ this._port = port || String(this._node.req.socket?.localPort || "");
288
+ }
289
+ return this._port;
290
+ }
291
+ set port(value) {
292
+ this._port = String(Number.parseInt(value) || "");
293
+ }
294
+ get pathname() {
295
+ if (this._pathname === void 0) {
296
+ const [pathname, search] = parsePath(this._node.req.url || "/");
297
+ this._pathname = pathname;
298
+ if (this._search === void 0) this._search = search;
299
+ }
300
+ return this._pathname;
301
+ }
302
+ set pathname(value) {
303
+ if (value[0] !== "/") value = "/" + value;
304
+ if (value === this._pathname) return;
305
+ this._pathname = value;
306
+ this._node.req.url = value + this.search;
307
+ }
308
+ get search() {
309
+ if (this._search === void 0) {
310
+ const [pathname, search] = parsePath(this._node.req.url || "/");
311
+ this._search = search;
312
+ if (this._pathname === void 0) this._pathname = pathname;
313
+ }
314
+ return this._search;
315
+ }
316
+ set search(value) {
317
+ if (value === "?") value = "";
318
+ else if (value && value[0] !== "?") value = "?" + value;
319
+ if (value === this._search) return;
320
+ this._search = value;
321
+ this._searchParams = void 0;
322
+ this._node.req.url = this.pathname + value;
323
+ }
324
+ get searchParams() {
325
+ if (!this._searchParams) this._searchParams = new URLSearchParams(this.search);
326
+ return this._searchParams;
327
+ }
328
+ set searchParams(value) {
329
+ this._searchParams = value;
330
+ this._search = value.toString();
331
+ }
332
+ get protocol() {
333
+ if (!this._protocol) this._protocol = this._node.req.socket?.encrypted || this._node.req.headers["x-forwarded-proto"] === "https" ? "https:" : "http:";
334
+ return this._protocol;
335
+ }
336
+ set protocol(value) {
337
+ this._protocol = value;
338
+ }
339
+ get origin() {
340
+ return `${this.protocol}//${this.host}`;
341
+ }
342
+ set origin(_value) {}
343
+ get href() {
344
+ return `${this.protocol}//${this.host}${this.pathname}${this.search}`;
345
+ }
346
+ set href(value) {
347
+ const _url = new globalThis.URL(value);
348
+ this._protocol = _url.protocol;
349
+ this.username = _url.username;
350
+ this.password = _url.password;
351
+ this._hostname = _url.hostname;
352
+ this._port = _url.port;
353
+ this.pathname = _url.pathname;
354
+ this.search = _url.search;
355
+ this.hash = _url.hash;
356
+ }
357
+ toString() {
358
+ return this.href;
359
+ }
360
+ toJSON() {
361
+ return this.href;
362
+ }
363
+ get [Symbol.toStringTag]() {
364
+ return "URL";
365
+ }
366
+ [kNodeInspect]() {
367
+ return this.href;
368
+ }
369
+ };
370
+ Object.setPrototypeOf(_URL.prototype, globalThis.URL.prototype);
371
+ return _URL;
372
+ })();
373
+ function parsePath(input) {
374
+ const url = (input || "/").replace(/\\/g, "/");
375
+ const qIndex = url.indexOf("?");
376
+ if (qIndex === -1) return [url, ""];
377
+ return [url.slice(0, qIndex), url.slice(qIndex)];
378
+ }
379
+ function parseHost(host) {
380
+ const s = (host || "").split(":");
381
+ return [s[0], String(Number.parseInt(s[1]) || "")];
382
+ }
383
+
384
+ //#endregion
385
+ //#region src/adapters/_node/request.ts
386
+ const NodeRequest = /* @__PURE__ */ (() => {
387
+ const _Request = class Request {
388
+ #url;
389
+ #headers;
390
+ #bodyUsed = false;
391
+ #abortSignal;
392
+ #hasBody;
393
+ #bodyBytes;
394
+ #blobBody;
395
+ #formDataBody;
396
+ #jsonBody;
397
+ #textBody;
398
+ #bodyStream;
399
+ _node;
400
+ runtime;
401
+ constructor(nodeCtx) {
402
+ this._node = nodeCtx;
403
+ this.runtime = {
404
+ name: "node",
405
+ node: nodeCtx
406
+ };
407
+ }
408
+ get ip() {
409
+ return this._node.req.socket?.remoteAddress;
410
+ }
411
+ get headers() {
412
+ if (!this.#headers) this.#headers = new NodeRequestHeaders(this._node);
413
+ return this.#headers;
414
+ }
415
+ clone() {
416
+ return new _Request({ ...this._node });
417
+ }
418
+ get _url() {
419
+ if (!this.#url) this.#url = new NodeRequestURL(this._node);
420
+ return this.#url;
421
+ }
422
+ get url() {
423
+ return this._url.href;
424
+ }
425
+ get method() {
426
+ return this._node.req.method || "GET";
427
+ }
428
+ get signal() {
429
+ if (!this.#abortSignal) this.#abortSignal = new AbortController();
430
+ return this.#abortSignal.signal;
431
+ }
432
+ get bodyUsed() {
433
+ return this.#bodyUsed;
434
+ }
435
+ get _hasBody() {
436
+ if (this.#hasBody !== void 0) return this.#hasBody;
437
+ const method = this._node.req.method?.toUpperCase();
438
+ if (!method || !(method === "PATCH" || method === "POST" || method === "PUT" || method === "DELETE")) {
439
+ this.#hasBody = false;
440
+ return false;
441
+ }
442
+ if (!Number.parseInt(this._node.req.headers["content-length"] || "")) {
443
+ const isChunked = (this._node.req.headers["transfer-encoding"] || "").split(",").map((e) => e.trim()).filter(Boolean).includes("chunked");
444
+ if (!isChunked) {
445
+ this.#hasBody = false;
446
+ return false;
447
+ }
448
+ }
449
+ this.#hasBody = true;
450
+ return true;
451
+ }
452
+ get body() {
453
+ if (!this._hasBody) return null;
454
+ if (!this.#bodyStream) {
455
+ this.#bodyUsed = true;
456
+ this.#bodyStream = new ReadableStream({ start: (controller) => {
457
+ this._node.req.on("data", (chunk) => {
458
+ controller.enqueue(chunk);
459
+ }).once("error", (error) => {
460
+ controller.error(error);
461
+ this.#abortSignal?.abort();
462
+ }).once("close", () => {
463
+ this.#abortSignal?.abort();
464
+ }).once("end", () => {
465
+ controller.close();
466
+ });
467
+ } });
468
+ }
469
+ return this.#bodyStream;
470
+ }
471
+ bytes() {
472
+ if (!this.#bodyBytes) {
473
+ const _bodyStream = this.body;
474
+ this.#bodyBytes = _bodyStream ? _readStream(_bodyStream) : Promise.resolve(new Uint8Array());
475
+ }
476
+ return this.#bodyBytes;
477
+ }
478
+ arrayBuffer() {
479
+ return this.bytes().then((buff) => {
480
+ return buff.buffer.slice(buff.byteOffset, buff.byteOffset + buff.byteLength);
481
+ });
482
+ }
483
+ blob() {
484
+ if (!this.#blobBody) this.#blobBody = this.bytes().then((bytes) => {
485
+ return new Blob([bytes], { type: this._node.req.headers["content-type"] });
486
+ });
487
+ return this.#blobBody;
488
+ }
489
+ formData() {
490
+ if (!this.#formDataBody) this.#formDataBody = new Response(this.body, { headers: this.headers }).formData();
491
+ return this.#formDataBody;
492
+ }
493
+ text() {
494
+ if (!this.#textBody) this.#textBody = this.bytes().then((bytes) => {
495
+ return new TextDecoder().decode(bytes);
496
+ });
497
+ return this.#textBody;
498
+ }
499
+ json() {
500
+ if (!this.#jsonBody) this.#jsonBody = this.text().then((txt) => {
501
+ return JSON.parse(txt);
502
+ });
503
+ return this.#jsonBody;
504
+ }
505
+ get [Symbol.toStringTag]() {
506
+ return "Request";
507
+ }
508
+ [kNodeInspect]() {
509
+ return {
510
+ method: this.method,
511
+ url: this.url,
512
+ headers: this.headers
513
+ };
514
+ }
515
+ };
516
+ Object.setPrototypeOf(_Request.prototype, globalThis.Request.prototype);
517
+ return _Request;
518
+ })();
519
+ async function _readStream(stream) {
520
+ const chunks = [];
521
+ await stream.pipeTo(new WritableStream({ write(chunk) {
522
+ chunks.push(chunk);
523
+ } }));
524
+ return Buffer.concat(chunks);
525
+ }
526
+
527
+ //#endregion
528
+ //#region src/adapters/_node/response.ts
529
+ /**
530
+ * Fast Response for Node.js runtime
531
+ *
532
+ * It is faster because in most cases it doesn't create a full Response instance.
533
+ */
534
+ const NodeResponse = /* @__PURE__ */ (() => {
535
+ const CONTENT_TYPE = "content-type";
536
+ const JSON_TYPE = "application/json";
537
+ const JSON_HEADER = [[CONTENT_TYPE, JSON_TYPE]];
538
+ const _Response = class Response$1 {
539
+ #body;
540
+ #init;
541
+ constructor(body, init) {
542
+ this.#body = body;
543
+ this.#init = init;
544
+ }
545
+ static json(data, init) {
546
+ if (init?.headers) {
547
+ if (!init.headers[CONTENT_TYPE]) {
548
+ const initHeaders = new Headers(init.headers);
549
+ if (!initHeaders.has(CONTENT_TYPE)) initHeaders.set(CONTENT_TYPE, JSON_TYPE);
550
+ init = {
551
+ ...init,
552
+ headers: initHeaders
553
+ };
554
+ }
555
+ } else {
556
+ init = init ? { ...init } : {};
557
+ init.headers = JSON_HEADER;
558
+ }
559
+ return new _Response(JSON.stringify(data), init);
560
+ }
561
+ static error() {
562
+ return globalThis.Response.error();
563
+ }
564
+ static redirect(url, status) {
565
+ return globalThis.Response.redirect(url, status);
566
+ }
567
+ /**
568
+ * Prepare Node.js response object
569
+ */
570
+ nodeResponse() {
571
+ const status = this.#init?.status ?? 200;
572
+ const statusText = this.#init?.statusText ?? "";
573
+ const headers = [];
574
+ const headersInit = this.#init?.headers;
575
+ if (headersInit) {
576
+ const headerEntries = Array.isArray(headersInit) ? headersInit : headersInit.entries ? headersInit.entries() : Object.entries(headersInit);
577
+ for (const [key, value] of headerEntries) if (key === "set-cookie") for (const setCookie of splitSetCookieString(value)) headers.push(["set-cookie", setCookie]);
578
+ else headers.push([key, value]);
579
+ }
580
+ if (this.#headersObj) for (const [key, value] of this.#headersObj) if (key === "set-cookie") for (const setCookie of splitSetCookieString(value)) headers.push(["set-cookie", setCookie]);
581
+ else headers.push([key, value]);
582
+ const bodyInit = this.#body;
583
+ let body;
584
+ if (bodyInit) if (typeof bodyInit === "string") body = bodyInit;
585
+ else if (bodyInit instanceof ReadableStream) body = bodyInit;
586
+ else if (bodyInit instanceof ArrayBuffer) body = Buffer.from(bodyInit);
587
+ else if (bodyInit instanceof Uint8Array) body = Buffer.from(bodyInit);
588
+ else if (bodyInit instanceof DataView) body = Buffer.from(bodyInit.buffer);
589
+ else if (bodyInit instanceof Blob) {
590
+ body = bodyInit.stream();
591
+ if (bodyInit.type) headers.push(["content-type", bodyInit.type]);
592
+ } else if (typeof bodyInit.pipe === "function") body = bodyInit;
593
+ else {
594
+ const res = new globalThis.Response(bodyInit);
595
+ body = res.body;
596
+ for (const [key, value] of res.headers) headers.push([key, value]);
597
+ }
598
+ this.#body = void 0;
599
+ this.#init = void 0;
600
+ return {
601
+ status,
602
+ statusText,
603
+ headers,
604
+ body
605
+ };
606
+ }
607
+ /** Lazy initialized response instance */
608
+ #responseObj;
609
+ /** Lazy initialized headers instance */
610
+ #headersObj;
611
+ clone() {
612
+ if (this.#responseObj) return this.#responseObj.clone();
613
+ return new globalThis.Response(this.#body, this.#init);
614
+ }
615
+ get #response() {
616
+ if (!this.#responseObj) {
617
+ this.#responseObj = new globalThis.Response(this.#body, this.#init);
618
+ this.#body = void 0;
619
+ this.#init = void 0;
620
+ this.#headersObj = void 0;
621
+ }
622
+ return this.#responseObj;
623
+ }
624
+ get headers() {
625
+ if (this.#responseObj) return this.#responseObj.headers;
626
+ if (!this.#headersObj) this.#headersObj = new Headers(this.#init?.headers);
627
+ return this.#headersObj;
628
+ }
629
+ get ok() {
630
+ if (this.#responseObj) return this.#responseObj.ok;
631
+ const status = this.#init?.status ?? 200;
632
+ return status >= 200 && status < 300;
633
+ }
634
+ get redirected() {
635
+ if (this.#responseObj) return this.#responseObj.redirected;
636
+ return false;
637
+ }
638
+ get status() {
639
+ if (this.#responseObj) return this.#responseObj.status;
640
+ return this.#init?.status ?? 200;
641
+ }
642
+ get statusText() {
643
+ if (this.#responseObj) return this.#responseObj.statusText;
644
+ return this.#init?.statusText ?? "";
645
+ }
646
+ get type() {
647
+ if (this.#responseObj) return this.#responseObj.type;
648
+ return "default";
649
+ }
650
+ get url() {
651
+ if (this.#responseObj) return this.#responseObj.url;
652
+ return "";
653
+ }
654
+ #fastBody(as) {
655
+ const bodyInit = this.#body;
656
+ if (bodyInit === null || bodyInit === void 0) return null;
657
+ if (bodyInit instanceof as) return bodyInit;
658
+ return false;
659
+ }
660
+ get body() {
661
+ if (this.#responseObj) return this.#responseObj.body;
662
+ const fastBody = this.#fastBody(ReadableStream);
663
+ if (fastBody !== false) return fastBody;
664
+ return this.#response.body;
665
+ }
666
+ get bodyUsed() {
667
+ if (this.#responseObj) return this.#responseObj.bodyUsed;
668
+ return false;
669
+ }
670
+ arrayBuffer() {
671
+ if (this.#responseObj) return this.#responseObj.arrayBuffer();
672
+ const fastBody = this.#fastBody(ArrayBuffer);
673
+ if (fastBody !== false) return Promise.resolve(fastBody || new ArrayBuffer(0));
674
+ return this.#response.arrayBuffer();
675
+ }
676
+ blob() {
677
+ if (this.#responseObj) return this.#responseObj.blob();
678
+ const fastBody = this.#fastBody(Blob);
679
+ if (fastBody !== false) return Promise.resolve(fastBody || new Blob());
680
+ return this.#response.blob();
681
+ }
682
+ bytes() {
683
+ if (this.#responseObj) return this.#responseObj.bytes();
684
+ const fastBody = this.#fastBody(Uint8Array);
685
+ if (fastBody !== false) return Promise.resolve(fastBody || new Uint8Array());
686
+ return this.#response.bytes();
687
+ }
688
+ formData() {
689
+ if (this.#responseObj) return this.#responseObj.formData();
690
+ const fastBody = this.#fastBody(FormData);
691
+ if (fastBody !== false) return Promise.resolve(fastBody || new FormData());
692
+ return this.#response.formData();
693
+ }
694
+ text() {
695
+ if (this.#responseObj) return this.#responseObj.text();
696
+ const bodyInit = this.#body;
697
+ if (bodyInit === null || bodyInit === void 0) return Promise.resolve("");
698
+ if (typeof bodyInit === "string") return Promise.resolve(bodyInit);
699
+ return this.#response.text();
700
+ }
701
+ json() {
702
+ if (this.#responseObj) return this.#responseObj.json();
703
+ return this.text().then((text) => JSON.parse(text));
704
+ }
705
+ };
706
+ Object.setPrototypeOf(_Response.prototype, globalThis.Response.prototype);
707
+ return _Response;
708
+ })();
709
+
710
+ //#endregion
711
+ //#region src/adapters/node.ts
712
+ function serve(options) {
713
+ return new NodeServer(options);
714
+ }
715
+ function toNodeHandler(fetchHandler) {
716
+ return (nodeReq, nodeRes) => {
717
+ const request = new NodeRequest({
718
+ req: nodeReq,
719
+ res: nodeRes
720
+ });
721
+ const res = fetchHandler(request);
722
+ return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
723
+ };
724
+ }
725
+ var NodeServer = class {
726
+ runtime = "node";
727
+ options;
728
+ node;
729
+ serveOptions;
730
+ fetch;
731
+ #isSecure;
732
+ #listeningPromise;
733
+ constructor(options) {
734
+ this.options = {
735
+ ...options,
736
+ middleware: [...options.middleware || []]
737
+ };
738
+ for (const plugin of options.plugins || []) plugin(this);
739
+ errorPlugin(this);
740
+ const fetchHandler = this.fetch = wrapFetch(this);
741
+ const handler = (nodeReq, nodeRes) => {
742
+ const request = new NodeRequest({
743
+ req: nodeReq,
744
+ res: nodeRes
745
+ });
746
+ const res = fetchHandler(request);
747
+ return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
748
+ };
749
+ const tls = resolveTLSOptions(this.options);
750
+ const { port, hostname: host } = resolvePortAndHost(this.options);
751
+ this.serveOptions = {
752
+ port,
753
+ host,
754
+ exclusive: !this.options.reusePort,
755
+ ...tls ? {
756
+ cert: tls.cert,
757
+ key: tls.key,
758
+ passphrase: tls.passphrase
759
+ } : {},
760
+ ...this.options.node
761
+ };
762
+ let server;
763
+ this.#isSecure = !!this.serveOptions.cert && this.options.protocol !== "http";
764
+ const isHttp2 = this.options.node?.http2 ?? this.#isSecure;
765
+ if (isHttp2) if (this.#isSecure) {
766
+ const { createSecureServer } = process.getBuiltinModule("node:http2");
767
+ server = createSecureServer({
768
+ allowHTTP1: true,
769
+ ...this.serveOptions
770
+ }, handler);
771
+ } else throw new Error("node.http2 option requires tls certificate!");
772
+ else if (this.#isSecure) {
773
+ const { createServer } = process.getBuiltinModule("node:https");
774
+ server = createServer(this.serveOptions, handler);
775
+ } else {
776
+ const { createServer } = process.getBuiltinModule("node:http");
777
+ server = createServer(this.serveOptions, handler);
778
+ }
779
+ this.node = {
780
+ server,
781
+ handler
782
+ };
783
+ if (!options.manual) this.serve();
784
+ }
785
+ serve() {
786
+ if (this.#listeningPromise) return Promise.resolve(this.#listeningPromise).then(() => this);
787
+ this.#listeningPromise = new Promise((resolve) => {
788
+ this.node.server.listen(this.serveOptions, () => {
789
+ printListening(this.options, this.url);
790
+ resolve();
791
+ });
792
+ });
793
+ }
794
+ get url() {
795
+ const addr = this.node?.server?.address();
796
+ if (!addr) return;
797
+ return typeof addr === "string" ? addr : fmtURL(addr.address, addr.port, this.#isSecure);
798
+ }
799
+ ready() {
800
+ return Promise.resolve(this.#listeningPromise).then(() => this);
801
+ }
802
+ close(closeAll) {
803
+ return new Promise((resolve, reject) => {
804
+ const server = this.node?.server;
805
+ if (!server) return resolve();
806
+ if (closeAll && "closeAllConnections" in server) server.closeAllConnections();
807
+ server.close((error) => error ? reject(error) : resolve());
808
+ });
809
+ }
810
+ };
811
+
812
+ //#endregion
813
+ export { NodeResponse as FastResponse, FastURL, NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders, serve, toNodeHandler };