srvx 0.1.4 → 0.2.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/adapters/bun.d.mts +22 -0
- package/dist/adapters/bun.mjs +51 -0
- package/dist/adapters/cloudflare.d.mts +9 -0
- package/dist/adapters/cloudflare.mjs +44 -0
- package/dist/adapters/deno.d.mts +23 -0
- package/dist/adapters/deno.mjs +67 -0
- package/dist/adapters/node.d.mts +48 -0
- package/dist/{shared/srvx.DNp8_Fs3.mjs → adapters/node.mjs} +365 -141
- package/dist/shared/srvx.DhN4g5wJ.mjs +76 -0
- package/dist/shared/srvx.PbkQy9Ck.mjs +18 -0
- package/dist/types.d.mts +90 -95
- package/package.json +33 -30
- package/dist/bun.d.mts +0 -8
- package/dist/bun.d.ts +0 -8
- package/dist/bun.mjs +0 -42
- package/dist/deno.d.mts +0 -8
- package/dist/deno.d.ts +0 -8
- package/dist/deno.mjs +0 -56
- package/dist/node-utils/index.d.mts +0 -138
- package/dist/node-utils/index.d.ts +0 -138
- package/dist/node-utils/index.mjs +0 -229
- package/dist/node.d.mts +0 -8
- package/dist/node.d.ts +0 -8
- package/dist/node.mjs +0 -70
- package/dist/shared/srvx.-ZdI-RlW.mjs +0 -112
- package/dist/types.d.ts +0 -175
- package/dist/types.mjs +0 -1
|
@@ -1,7 +1,80 @@
|
|
|
1
|
+
import NodeHttp from 'node:http';
|
|
1
2
|
import { splitSetCookieString } from 'cookie-es';
|
|
3
|
+
import { r as resolvePort, f as fmtURL } from '../shared/srvx.PbkQy9Ck.mjs';
|
|
4
|
+
import { w as wrapFetch } from '../shared/srvx.DhN4g5wJ.mjs';
|
|
5
|
+
|
|
6
|
+
async function sendNodeResponse(nodeRes, webRes) {
|
|
7
|
+
if (!webRes) {
|
|
8
|
+
nodeRes.statusCode = 500;
|
|
9
|
+
return endNodeResponse(nodeRes);
|
|
10
|
+
}
|
|
11
|
+
if (webRes.nodeResponse) {
|
|
12
|
+
const res = webRes.nodeResponse();
|
|
13
|
+
nodeRes.writeHead(res.status, res.statusText, res.headers);
|
|
14
|
+
if (res.body instanceof ReadableStream) {
|
|
15
|
+
return streamBody(res.body, nodeRes);
|
|
16
|
+
}
|
|
17
|
+
nodeRes.write(res.body);
|
|
18
|
+
return endNodeResponse(nodeRes);
|
|
19
|
+
}
|
|
20
|
+
const headerEntries = [];
|
|
21
|
+
for (const [key, value] of webRes.headers) {
|
|
22
|
+
if (key === "set-cookie") {
|
|
23
|
+
for (const setCookie of splitSetCookieString(value)) {
|
|
24
|
+
headerEntries.push(["set-cookie", setCookie]);
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
headerEntries.push([key, value]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
nodeRes.writeHead(webRes.status || 200, webRes.statusText, headerEntries);
|
|
31
|
+
return webRes.body ? streamBody(webRes.body, nodeRes) : endNodeResponse(nodeRes);
|
|
32
|
+
}
|
|
33
|
+
function endNodeResponse(nodeRes) {
|
|
34
|
+
return new Promise((resolve) => nodeRes.end(resolve));
|
|
35
|
+
}
|
|
36
|
+
function streamBody(stream, nodeRes) {
|
|
37
|
+
if (nodeRes.destroyed) {
|
|
38
|
+
stream.cancel();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const reader = stream.getReader();
|
|
42
|
+
function streamCancel(error) {
|
|
43
|
+
reader.cancel(error).catch(() => {
|
|
44
|
+
});
|
|
45
|
+
if (error) {
|
|
46
|
+
nodeRes.destroy(error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function streamHandle({
|
|
50
|
+
done,
|
|
51
|
+
value
|
|
52
|
+
}) {
|
|
53
|
+
try {
|
|
54
|
+
if (done) {
|
|
55
|
+
nodeRes.end();
|
|
56
|
+
} else if (nodeRes.write(value)) {
|
|
57
|
+
reader.read().then(streamHandle, streamCancel);
|
|
58
|
+
} else {
|
|
59
|
+
nodeRes.once(
|
|
60
|
+
"drain",
|
|
61
|
+
() => reader.read().then(streamHandle, streamCancel)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
} catch (error) {
|
|
65
|
+
streamCancel(error instanceof Error ? error : void 0);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
nodeRes.on("close", streamCancel);
|
|
69
|
+
nodeRes.on("error", streamCancel);
|
|
70
|
+
reader.read().then(streamHandle, streamCancel);
|
|
71
|
+
return reader.closed.finally(() => {
|
|
72
|
+
nodeRes.off("close", streamCancel);
|
|
73
|
+
nodeRes.off("error", streamCancel);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
2
76
|
|
|
3
77
|
const kNodeReq = /* @__PURE__ */ Symbol.for("srvx.node.request");
|
|
4
|
-
const kNodeRes = /* @__PURE__ */ Symbol.for("srvx.node.response");
|
|
5
78
|
const kNodeInspect = /* @__PURE__ */ Symbol.for(
|
|
6
79
|
"nodejs.util.inspect.custom"
|
|
7
80
|
);
|
|
@@ -26,7 +99,7 @@ const NodeReqHeadersProxy = /* @__PURE__ */ (() => class NodeReqHeadersProxy {
|
|
|
26
99
|
}
|
|
27
100
|
delete(name) {
|
|
28
101
|
name = name.toLowerCase();
|
|
29
|
-
this[kNodeReq].headers[name] =
|
|
102
|
+
this[kNodeReq].headers[name] = void 0;
|
|
30
103
|
}
|
|
31
104
|
get(name) {
|
|
32
105
|
name = name.toLowerCase();
|
|
@@ -47,6 +120,12 @@ const NodeReqHeadersProxy = /* @__PURE__ */ (() => class NodeReqHeadersProxy {
|
|
|
47
120
|
name = name.toLowerCase();
|
|
48
121
|
this[kNodeReq].headers[name] = value;
|
|
49
122
|
}
|
|
123
|
+
get count() {
|
|
124
|
+
throw new Error("Method not implemented.");
|
|
125
|
+
}
|
|
126
|
+
getAll(_name) {
|
|
127
|
+
throw new Error("Method not implemented.");
|
|
128
|
+
}
|
|
50
129
|
toJSON() {
|
|
51
130
|
const _headers = this[kNodeReq].headers;
|
|
52
131
|
const result = {};
|
|
@@ -98,73 +177,6 @@ const NodeReqHeadersProxy = /* @__PURE__ */ (() => class NodeReqHeadersProxy {
|
|
|
98
177
|
return Object.fromEntries(this.entries());
|
|
99
178
|
}
|
|
100
179
|
})();
|
|
101
|
-
const NodeResHeadersProxy = /* @__PURE__ */ (() => class NodeResHeadersProxy {
|
|
102
|
-
constructor(res) {
|
|
103
|
-
this[kNodeRes] = res;
|
|
104
|
-
}
|
|
105
|
-
append(name, value) {
|
|
106
|
-
this[kNodeRes].appendHeader(name, value);
|
|
107
|
-
}
|
|
108
|
-
delete(name) {
|
|
109
|
-
this[kNodeRes].removeHeader(name);
|
|
110
|
-
}
|
|
111
|
-
get(name) {
|
|
112
|
-
return _normalizeValue(this[kNodeRes].getHeader(name));
|
|
113
|
-
}
|
|
114
|
-
getSetCookie() {
|
|
115
|
-
const setCookie = _normalizeValue(this[kNodeRes].getHeader("set-cookie"));
|
|
116
|
-
if (!setCookie) {
|
|
117
|
-
return [];
|
|
118
|
-
}
|
|
119
|
-
return splitSetCookieString(setCookie);
|
|
120
|
-
}
|
|
121
|
-
has(name) {
|
|
122
|
-
return this[kNodeRes].hasHeader(name);
|
|
123
|
-
}
|
|
124
|
-
set(name, value) {
|
|
125
|
-
this[kNodeRes].setHeader(name, value);
|
|
126
|
-
}
|
|
127
|
-
forEach(cb, thisArg) {
|
|
128
|
-
const _headers = this[kNodeRes].getHeaders();
|
|
129
|
-
for (const key in _headers) {
|
|
130
|
-
if (_headers[key]) {
|
|
131
|
-
cb.call(
|
|
132
|
-
thisArg,
|
|
133
|
-
_normalizeValue(_headers[key]),
|
|
134
|
-
key,
|
|
135
|
-
this
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
*entries() {
|
|
141
|
-
const _headers = this[kNodeRes].getHeaders();
|
|
142
|
-
for (const key in _headers) {
|
|
143
|
-
yield [key, _normalizeValue(_headers[key])];
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
*keys() {
|
|
147
|
-
const keys = this[kNodeRes].getHeaderNames();
|
|
148
|
-
for (const key of keys) {
|
|
149
|
-
yield key;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
*values() {
|
|
153
|
-
const values = Object.values(this[kNodeRes].getHeaders());
|
|
154
|
-
for (const value of values) {
|
|
155
|
-
yield _normalizeValue(value);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
[(Symbol.iterator)]() {
|
|
159
|
-
return this.entries()[Symbol.iterator]();
|
|
160
|
-
}
|
|
161
|
-
get [Symbol.toStringTag]() {
|
|
162
|
-
return "Headers";
|
|
163
|
-
}
|
|
164
|
-
[kNodeInspect]() {
|
|
165
|
-
return Object.fromEntries(this.entries());
|
|
166
|
-
}
|
|
167
|
-
})();
|
|
168
180
|
function _normalizeValue(value) {
|
|
169
181
|
if (Array.isArray(value)) {
|
|
170
182
|
return value.join(", ");
|
|
@@ -184,15 +196,15 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => class _NodeReqURLProxy {
|
|
|
184
196
|
return this[kNodeReq].headers.host || "";
|
|
185
197
|
}
|
|
186
198
|
set host(value) {
|
|
187
|
-
this._hostname =
|
|
188
|
-
this._port =
|
|
199
|
+
this._hostname = void 0;
|
|
200
|
+
this._port = void 0;
|
|
189
201
|
this[kNodeReq].headers.host = value;
|
|
190
202
|
}
|
|
191
203
|
// hostname
|
|
192
204
|
get hostname() {
|
|
193
|
-
if (this._hostname ===
|
|
205
|
+
if (this._hostname === void 0) {
|
|
194
206
|
const [hostname, port] = parseHost(this[kNodeReq].headers.host);
|
|
195
|
-
if (this._port ===
|
|
207
|
+
if (this._port === void 0 && port) {
|
|
196
208
|
this._port = String(Number.parseInt(port) || "");
|
|
197
209
|
}
|
|
198
210
|
this._hostname = hostname || "localhost";
|
|
@@ -204,9 +216,9 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => class _NodeReqURLProxy {
|
|
|
204
216
|
}
|
|
205
217
|
// port
|
|
206
218
|
get port() {
|
|
207
|
-
if (this._port ===
|
|
219
|
+
if (this._port === void 0) {
|
|
208
220
|
const [hostname, port] = parseHost(this[kNodeReq].headers.host);
|
|
209
|
-
if (this._hostname ===
|
|
221
|
+
if (this._hostname === void 0 && hostname) {
|
|
210
222
|
this._hostname = hostname;
|
|
211
223
|
}
|
|
212
224
|
this._port = port || String(this[kNodeReq].socket?.localPort || "");
|
|
@@ -218,10 +230,10 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => class _NodeReqURLProxy {
|
|
|
218
230
|
}
|
|
219
231
|
// pathname
|
|
220
232
|
get pathname() {
|
|
221
|
-
if (this._pathname ===
|
|
233
|
+
if (this._pathname === void 0) {
|
|
222
234
|
const [pathname, search] = parsePath(this[kNodeReq].url || "/");
|
|
223
235
|
this._pathname = pathname;
|
|
224
|
-
if (this._search ===
|
|
236
|
+
if (this._search === void 0) {
|
|
225
237
|
this._search = search;
|
|
226
238
|
}
|
|
227
239
|
}
|
|
@@ -239,10 +251,10 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => class _NodeReqURLProxy {
|
|
|
239
251
|
}
|
|
240
252
|
// search
|
|
241
253
|
get search() {
|
|
242
|
-
if (this._search ===
|
|
254
|
+
if (this._search === void 0) {
|
|
243
255
|
const [pathname, search] = parsePath(this[kNodeReq].url || "/");
|
|
244
256
|
this._search = search;
|
|
245
|
-
if (this._pathname ===
|
|
257
|
+
if (this._pathname === void 0) {
|
|
246
258
|
this._pathname = pathname;
|
|
247
259
|
}
|
|
248
260
|
}
|
|
@@ -258,7 +270,7 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => class _NodeReqURLProxy {
|
|
|
258
270
|
return;
|
|
259
271
|
}
|
|
260
272
|
this._search = value;
|
|
261
|
-
this._searchParams =
|
|
273
|
+
this._searchParams = void 0;
|
|
262
274
|
this[kNodeReq].url = this.pathname + value;
|
|
263
275
|
}
|
|
264
276
|
// searchParams
|
|
@@ -353,7 +365,7 @@ const NodeRequestProxy = /* @__PURE__ */ (() => class NodeRequestProxy2 {
|
|
|
353
365
|
#jsonBody;
|
|
354
366
|
#textBody;
|
|
355
367
|
#bodyStream;
|
|
356
|
-
get
|
|
368
|
+
get remoteAddress() {
|
|
357
369
|
return this[kNodeReq].socket?.remoteAddress;
|
|
358
370
|
}
|
|
359
371
|
clone() {
|
|
@@ -372,7 +384,7 @@ const NodeRequestProxy = /* @__PURE__ */ (() => class NodeRequestProxy2 {
|
|
|
372
384
|
return this.#abortSignal.signal;
|
|
373
385
|
}
|
|
374
386
|
get _hasBody() {
|
|
375
|
-
if (this.#hasBody !==
|
|
387
|
+
if (this.#hasBody !== void 0) {
|
|
376
388
|
return this.#hasBody;
|
|
377
389
|
}
|
|
378
390
|
const method = this[kNodeReq].method?.toUpperCase();
|
|
@@ -484,75 +496,287 @@ async function _readStream(stream) {
|
|
|
484
496
|
return Buffer.concat(chunks);
|
|
485
497
|
}
|
|
486
498
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
499
|
+
const NodeFastResponse = /* @__PURE__ */ (() => (
|
|
500
|
+
/**
|
|
501
|
+
* Fast Response for Node.js runtime
|
|
502
|
+
*
|
|
503
|
+
* It is faster because in most cases it doesn't create a full Response instance.
|
|
504
|
+
*/
|
|
505
|
+
class NodeFastResponse {
|
|
506
|
+
#body;
|
|
507
|
+
#init;
|
|
508
|
+
constructor(body, init) {
|
|
509
|
+
this.#body = body;
|
|
510
|
+
this.#init = init;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Prepare Node.js response object
|
|
514
|
+
*/
|
|
515
|
+
nodeResponse() {
|
|
516
|
+
const status = this.#init?.status ?? 200;
|
|
517
|
+
const statusText = this.#init?.statusText ?? "";
|
|
518
|
+
const headers = [];
|
|
519
|
+
let headersInit = this.#init?.headers;
|
|
520
|
+
if (headersInit) {
|
|
521
|
+
if (typeof headersInit === "object") {
|
|
522
|
+
headersInit = Object.entries(headersInit);
|
|
523
|
+
}
|
|
524
|
+
for (const [key, value] of headersInit) {
|
|
525
|
+
if (key === "set-cookie") {
|
|
526
|
+
for (const setCookie of splitSetCookieString(value)) {
|
|
527
|
+
headers.push(["set-cookie", setCookie]);
|
|
528
|
+
}
|
|
529
|
+
} else {
|
|
530
|
+
headers.push([key, value]);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
const bodyInit = this.#body;
|
|
535
|
+
let body;
|
|
536
|
+
if (bodyInit) {
|
|
537
|
+
if (typeof bodyInit === "string") {
|
|
538
|
+
body = bodyInit;
|
|
539
|
+
} else if (bodyInit instanceof ReadableStream) {
|
|
540
|
+
body = bodyInit;
|
|
541
|
+
} else if (bodyInit instanceof ArrayBuffer) {
|
|
542
|
+
body = Buffer.from(bodyInit);
|
|
543
|
+
} else if (bodyInit instanceof Uint8Array) {
|
|
544
|
+
body = Buffer.from(bodyInit);
|
|
545
|
+
} else if (bodyInit instanceof DataView) {
|
|
546
|
+
body = Buffer.from(bodyInit.buffer);
|
|
547
|
+
} else if (bodyInit instanceof Blob) {
|
|
548
|
+
body = bodyInit.stream();
|
|
549
|
+
if (bodyInit.type) {
|
|
550
|
+
headers.push(["content-type", bodyInit.type]);
|
|
551
|
+
}
|
|
552
|
+
} else {
|
|
553
|
+
const res = new Response(bodyInit);
|
|
554
|
+
body = res.body;
|
|
555
|
+
for (const [key, value] of res.headers) {
|
|
556
|
+
headers.push([key, value]);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
this.#body = void 0;
|
|
561
|
+
this.#init = void 0;
|
|
562
|
+
return {
|
|
563
|
+
status,
|
|
564
|
+
statusText,
|
|
565
|
+
headers,
|
|
566
|
+
body
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
// ... the rest is for interface compatibility only and usually not to be used ...
|
|
570
|
+
/** Lazy initialized response instance */
|
|
571
|
+
#responseObj;
|
|
572
|
+
/** Lazy initialized headers instance */
|
|
573
|
+
#headersObj;
|
|
574
|
+
clone() {
|
|
575
|
+
if (this.#responseObj) {
|
|
576
|
+
return this.#responseObj.clone();
|
|
577
|
+
}
|
|
578
|
+
return new Response(this.#body, this.#init);
|
|
579
|
+
}
|
|
580
|
+
get #response() {
|
|
581
|
+
if (!this.#responseObj) {
|
|
582
|
+
this.#responseObj = new Response(this.#body, this.#init);
|
|
583
|
+
this.#body = void 0;
|
|
584
|
+
this.#init = void 0;
|
|
585
|
+
this.#headersObj = void 0;
|
|
586
|
+
}
|
|
587
|
+
return this.#responseObj;
|
|
497
588
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const headerEntries = [];
|
|
502
|
-
for (const [key, value] of webRes.headers) {
|
|
503
|
-
if (key === "set-cookie") {
|
|
504
|
-
for (const setCookie of splitSetCookieString(value)) {
|
|
505
|
-
headerEntries.push(["set-cookie", setCookie]);
|
|
589
|
+
get headers() {
|
|
590
|
+
if (this.#responseObj) {
|
|
591
|
+
return this.#responseObj.headers;
|
|
506
592
|
}
|
|
507
|
-
|
|
508
|
-
|
|
593
|
+
if (!this.#headersObj) {
|
|
594
|
+
this.#headersObj = new Headers(this.#init?.headers);
|
|
595
|
+
}
|
|
596
|
+
return this.#headersObj;
|
|
597
|
+
}
|
|
598
|
+
get ok() {
|
|
599
|
+
if (this.#responseObj) {
|
|
600
|
+
return this.#responseObj.ok;
|
|
601
|
+
}
|
|
602
|
+
const status = this.#init?.status ?? 200;
|
|
603
|
+
return status >= 200 && status < 300;
|
|
604
|
+
}
|
|
605
|
+
get redirected() {
|
|
606
|
+
if (this.#responseObj) {
|
|
607
|
+
return this.#responseObj.redirected;
|
|
608
|
+
}
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
get status() {
|
|
612
|
+
if (this.#responseObj) {
|
|
613
|
+
return this.#responseObj.status;
|
|
614
|
+
}
|
|
615
|
+
return this.#init?.status ?? 200;
|
|
616
|
+
}
|
|
617
|
+
get statusText() {
|
|
618
|
+
if (this.#responseObj) {
|
|
619
|
+
return this.#responseObj.statusText;
|
|
620
|
+
}
|
|
621
|
+
return this.#init?.statusText ?? "";
|
|
622
|
+
}
|
|
623
|
+
get type() {
|
|
624
|
+
if (this.#responseObj) {
|
|
625
|
+
return this.#responseObj.type;
|
|
626
|
+
}
|
|
627
|
+
return "default";
|
|
628
|
+
}
|
|
629
|
+
get url() {
|
|
630
|
+
if (this.#responseObj) {
|
|
631
|
+
return this.#responseObj.url;
|
|
632
|
+
}
|
|
633
|
+
return "";
|
|
634
|
+
}
|
|
635
|
+
// --- body ---
|
|
636
|
+
#fastBody(as) {
|
|
637
|
+
const bodyInit = this.#body;
|
|
638
|
+
if (bodyInit === null || bodyInit === void 0) {
|
|
639
|
+
return null;
|
|
640
|
+
}
|
|
641
|
+
if (bodyInit instanceof as) {
|
|
642
|
+
return bodyInit;
|
|
643
|
+
}
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
get body() {
|
|
647
|
+
if (this.#responseObj) {
|
|
648
|
+
return this.#responseObj.body;
|
|
649
|
+
}
|
|
650
|
+
const fastBody = this.#fastBody(ReadableStream);
|
|
651
|
+
if (fastBody !== false) {
|
|
652
|
+
return fastBody;
|
|
653
|
+
}
|
|
654
|
+
return this.#response.body;
|
|
655
|
+
}
|
|
656
|
+
get bodyUsed() {
|
|
657
|
+
if (this.#responseObj) {
|
|
658
|
+
return this.#responseObj.bodyUsed;
|
|
659
|
+
}
|
|
660
|
+
return false;
|
|
661
|
+
}
|
|
662
|
+
arrayBuffer() {
|
|
663
|
+
if (this.#responseObj) {
|
|
664
|
+
return this.#responseObj.arrayBuffer();
|
|
665
|
+
}
|
|
666
|
+
const fastBody = this.#fastBody(ArrayBuffer);
|
|
667
|
+
if (fastBody !== false) {
|
|
668
|
+
return Promise.resolve(fastBody || new ArrayBuffer(0));
|
|
669
|
+
}
|
|
670
|
+
return this.#response.arrayBuffer();
|
|
671
|
+
}
|
|
672
|
+
blob() {
|
|
673
|
+
if (this.#responseObj) {
|
|
674
|
+
return this.#responseObj.blob();
|
|
675
|
+
}
|
|
676
|
+
const fastBody = this.#fastBody(Blob);
|
|
677
|
+
if (fastBody !== false) {
|
|
678
|
+
return Promise.resolve(fastBody || new Blob());
|
|
679
|
+
}
|
|
680
|
+
return this.#response.blob();
|
|
681
|
+
}
|
|
682
|
+
bytes() {
|
|
683
|
+
if (this.#responseObj) {
|
|
684
|
+
return this.#responseObj.bytes();
|
|
685
|
+
}
|
|
686
|
+
const fastBody = this.#fastBody(Uint8Array);
|
|
687
|
+
if (fastBody !== false) {
|
|
688
|
+
return Promise.resolve(fastBody || new Uint8Array());
|
|
689
|
+
}
|
|
690
|
+
return this.#response.bytes();
|
|
691
|
+
}
|
|
692
|
+
formData() {
|
|
693
|
+
if (this.#responseObj) {
|
|
694
|
+
return this.#responseObj.formData();
|
|
695
|
+
}
|
|
696
|
+
const fastBody = this.#fastBody(FormData);
|
|
697
|
+
if (fastBody !== false) {
|
|
698
|
+
return Promise.resolve(fastBody || new FormData());
|
|
699
|
+
}
|
|
700
|
+
return this.#response.formData();
|
|
701
|
+
}
|
|
702
|
+
text() {
|
|
703
|
+
if (this.#responseObj) {
|
|
704
|
+
return this.#responseObj.text();
|
|
705
|
+
}
|
|
706
|
+
const bodyInit = this.#body;
|
|
707
|
+
if (bodyInit === null || bodyInit === void 0) {
|
|
708
|
+
return Promise.resolve("");
|
|
709
|
+
}
|
|
710
|
+
if (typeof bodyInit === "string") {
|
|
711
|
+
return Promise.resolve(bodyInit);
|
|
712
|
+
}
|
|
713
|
+
return this.#response.text();
|
|
714
|
+
}
|
|
715
|
+
json() {
|
|
716
|
+
if (this.#responseObj) {
|
|
717
|
+
return this.#responseObj.json();
|
|
718
|
+
}
|
|
719
|
+
return this.text().then((text) => JSON.parse(text));
|
|
509
720
|
}
|
|
510
721
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
return new Promise((resolve) => nodeRes.end(resolve));
|
|
722
|
+
))();
|
|
723
|
+
|
|
724
|
+
function serve(options) {
|
|
725
|
+
return new NodeServer(options);
|
|
516
726
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
727
|
+
class NodeServer {
|
|
728
|
+
constructor(options) {
|
|
729
|
+
this.runtime = "node";
|
|
730
|
+
this.options = options;
|
|
731
|
+
const fetchHandler = wrapFetch(this, this.options.fetch);
|
|
732
|
+
this.fetch = fetchHandler;
|
|
733
|
+
const handler = (nodeReq, nodeRes) => {
|
|
734
|
+
const request = new NodeRequestProxy(nodeReq);
|
|
735
|
+
request.node = { req: nodeReq, res: nodeRes };
|
|
736
|
+
const res = fetchHandler(request);
|
|
737
|
+
return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
|
|
738
|
+
};
|
|
739
|
+
this.serveOptions = {
|
|
740
|
+
port: resolvePort(this.options.port, globalThis.process?.env.PORT),
|
|
741
|
+
host: this.options.hostname,
|
|
742
|
+
exclusive: !this.options.reusePort,
|
|
743
|
+
...this.options.node
|
|
744
|
+
};
|
|
745
|
+
const server = NodeHttp.createServer(this.serveOptions, handler);
|
|
746
|
+
this.node = { server, handler };
|
|
747
|
+
if (!options.manual) {
|
|
748
|
+
this.serve();
|
|
749
|
+
}
|
|
521
750
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
751
|
+
#listeningPromise;
|
|
752
|
+
serve() {
|
|
753
|
+
if (this.#listeningPromise) {
|
|
754
|
+
return Promise.resolve(this.#listeningPromise).then(() => this);
|
|
755
|
+
}
|
|
756
|
+
this.#listeningPromise = new Promise((resolve) => {
|
|
757
|
+
this.node.server.listen(this.serveOptions, () => resolve());
|
|
525
758
|
});
|
|
526
|
-
|
|
527
|
-
|
|
759
|
+
}
|
|
760
|
+
get url() {
|
|
761
|
+
const addr = this.node?.server?.address();
|
|
762
|
+
if (!addr) {
|
|
763
|
+
return;
|
|
528
764
|
}
|
|
765
|
+
return typeof addr === "string" ? addr : fmtURL(addr.address, addr.port);
|
|
529
766
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (
|
|
536
|
-
|
|
537
|
-
} else if (nodeRes.write(value)) {
|
|
538
|
-
reader.read().then(streamHandle, streamCancel);
|
|
539
|
-
} else {
|
|
540
|
-
nodeRes.once(
|
|
541
|
-
"drain",
|
|
542
|
-
() => reader.read().then(streamHandle, streamCancel)
|
|
543
|
-
);
|
|
767
|
+
ready() {
|
|
768
|
+
return Promise.resolve(this.#listeningPromise).then(() => this);
|
|
769
|
+
}
|
|
770
|
+
close(closeAll) {
|
|
771
|
+
return new Promise((resolve, reject) => {
|
|
772
|
+
if (closeAll) {
|
|
773
|
+
this.node?.server?.closeAllConnections?.();
|
|
544
774
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
775
|
+
this.node?.server?.close(
|
|
776
|
+
(error) => error ? reject(error) : resolve()
|
|
777
|
+
);
|
|
778
|
+
});
|
|
548
779
|
}
|
|
549
|
-
nodeRes.on("close", streamCancel);
|
|
550
|
-
nodeRes.on("error", streamCancel);
|
|
551
|
-
reader.read().then(streamHandle, streamCancel);
|
|
552
|
-
return reader.closed.finally(() => {
|
|
553
|
-
nodeRes.off("close", streamCancel);
|
|
554
|
-
nodeRes.off("error", streamCancel);
|
|
555
|
-
});
|
|
556
780
|
}
|
|
557
781
|
|
|
558
|
-
export {
|
|
782
|
+
export { NodeFastResponse as Response, serve };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
function wrapFetch(server, fetchHandler) {
|
|
2
|
+
const plugins = server.options.plugins;
|
|
3
|
+
if (!plugins?.length) {
|
|
4
|
+
return fetchHandler;
|
|
5
|
+
}
|
|
6
|
+
const requestHooks = [];
|
|
7
|
+
const responseHooks = [];
|
|
8
|
+
for (const ctor of plugins) {
|
|
9
|
+
const plugin = typeof ctor === "function" ? ctor(server) : ctor;
|
|
10
|
+
if (plugin.request) {
|
|
11
|
+
requestHooks.push(plugin.request);
|
|
12
|
+
}
|
|
13
|
+
if (plugin.response) {
|
|
14
|
+
responseHooks.push(plugin.response);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const hasRequestHooks = requestHooks.length > 0;
|
|
18
|
+
const hasResponseHooks = responseHooks.length > 0;
|
|
19
|
+
if (!hasRequestHooks && !hasResponseHooks) {
|
|
20
|
+
return fetchHandler;
|
|
21
|
+
}
|
|
22
|
+
return (request) => {
|
|
23
|
+
let resValue;
|
|
24
|
+
let resPromise;
|
|
25
|
+
if (hasRequestHooks) {
|
|
26
|
+
for (const reqHook of requestHooks) {
|
|
27
|
+
if (resPromise) {
|
|
28
|
+
resPromise = resPromise.then((res) => res || reqHook(request));
|
|
29
|
+
} else {
|
|
30
|
+
const res = reqHook(request);
|
|
31
|
+
if (res) {
|
|
32
|
+
if (res instanceof Promise) {
|
|
33
|
+
resPromise = res;
|
|
34
|
+
} else {
|
|
35
|
+
return res;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (resPromise) {
|
|
42
|
+
resPromise = resPromise.then((res) => res || fetchHandler(request));
|
|
43
|
+
} else {
|
|
44
|
+
const res = fetchHandler(request);
|
|
45
|
+
if (res instanceof Promise) {
|
|
46
|
+
resPromise = res;
|
|
47
|
+
} else {
|
|
48
|
+
resValue = res;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (hasResponseHooks) {
|
|
52
|
+
for (const resHook of responseHooks) {
|
|
53
|
+
if (resPromise) {
|
|
54
|
+
resPromise = resPromise.then((res) => {
|
|
55
|
+
if (res) {
|
|
56
|
+
resValue = res;
|
|
57
|
+
}
|
|
58
|
+
return resHook(request, resValue);
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
const res = resHook(request, resValue);
|
|
62
|
+
if (res) {
|
|
63
|
+
if (res instanceof Promise) {
|
|
64
|
+
resPromise = res;
|
|
65
|
+
} else {
|
|
66
|
+
resValue = res;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return resPromise ? resPromise.then((res) => res || resValue) : resValue;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { wrapFetch as w };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function resolvePort(portOptions, portEnv) {
|
|
2
|
+
const portInput = portOptions ?? portEnv;
|
|
3
|
+
if (portInput === void 0) {
|
|
4
|
+
return 3e3;
|
|
5
|
+
}
|
|
6
|
+
return typeof portInput === "number" ? portInput : Number.parseInt(portInput, 10);
|
|
7
|
+
}
|
|
8
|
+
function fmtURL(host, port, ssl) {
|
|
9
|
+
if (!host || !port) {
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
if (host.includes(":")) {
|
|
13
|
+
host = `[${host}]`;
|
|
14
|
+
}
|
|
15
|
+
return `http${""}://${host}:${port}/`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { fmtURL as f, resolvePort as r };
|