better-call 0.3.3 → 1.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +3 -4
- package/dist/client.d.ts +3 -4
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +4684 -875
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -125
- package/dist/index.d.ts +3 -125
- package/dist/index.js +4665 -860
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +186 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +13 -0
- package/dist/node.d.ts +13 -0
- package/dist/node.js +147 -0
- package/dist/node.js.map +1 -0
- package/dist/router-CyNMWgsC.d.cts +1263 -0
- package/dist/router-CyNMWgsC.d.ts +1263 -0
- package/package.json +28 -14
- package/dist/router-DtwxtvxY.d.cts +0 -426
- package/dist/router-DtwxtvxY.d.ts +0 -426
package/dist/node.cjs
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/adapters/node/index.ts
|
|
31
|
+
var node_exports = {};
|
|
32
|
+
__export(node_exports, {
|
|
33
|
+
getRequest: () => getRequest,
|
|
34
|
+
setResponse: () => setResponse,
|
|
35
|
+
toNodeHandler: () => toNodeHandler
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(node_exports);
|
|
38
|
+
|
|
39
|
+
// src/adapters/node/request.ts
|
|
40
|
+
var set_cookie_parser = __toESM(require("set-cookie-parser"), 1);
|
|
41
|
+
function get_raw_body(req, body_size_limit) {
|
|
42
|
+
const h = req.headers;
|
|
43
|
+
if (!h["content-type"]) return null;
|
|
44
|
+
const content_length = Number(h["content-length"]);
|
|
45
|
+
if (req.httpVersionMajor === 1 && isNaN(content_length) && h["transfer-encoding"] == null || content_length === 0) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
let length = content_length;
|
|
49
|
+
if (body_size_limit) {
|
|
50
|
+
if (!length) {
|
|
51
|
+
length = body_size_limit;
|
|
52
|
+
} else if (length > body_size_limit) {
|
|
53
|
+
throw Error(
|
|
54
|
+
`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (req.destroyed) {
|
|
59
|
+
const readable = new ReadableStream();
|
|
60
|
+
readable.cancel();
|
|
61
|
+
return readable;
|
|
62
|
+
}
|
|
63
|
+
let size = 0;
|
|
64
|
+
let cancelled = false;
|
|
65
|
+
return new ReadableStream({
|
|
66
|
+
start(controller) {
|
|
67
|
+
req.on("error", (error) => {
|
|
68
|
+
cancelled = true;
|
|
69
|
+
controller.error(error);
|
|
70
|
+
});
|
|
71
|
+
req.on("end", () => {
|
|
72
|
+
if (cancelled) return;
|
|
73
|
+
controller.close();
|
|
74
|
+
});
|
|
75
|
+
req.on("data", (chunk) => {
|
|
76
|
+
if (cancelled) return;
|
|
77
|
+
size += chunk.length;
|
|
78
|
+
if (size > length) {
|
|
79
|
+
cancelled = true;
|
|
80
|
+
controller.error(
|
|
81
|
+
new Error(
|
|
82
|
+
`request body size exceeded ${content_length ? "'content-length'" : "BODY_SIZE_LIMIT"} of ${length}`
|
|
83
|
+
)
|
|
84
|
+
);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
controller.enqueue(chunk);
|
|
88
|
+
if (controller.desiredSize === null || controller.desiredSize <= 0) {
|
|
89
|
+
req.pause();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
pull() {
|
|
94
|
+
req.resume();
|
|
95
|
+
},
|
|
96
|
+
cancel(reason) {
|
|
97
|
+
cancelled = true;
|
|
98
|
+
req.destroy(reason);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function getRequest({
|
|
103
|
+
request,
|
|
104
|
+
base,
|
|
105
|
+
bodySizeLimit
|
|
106
|
+
}) {
|
|
107
|
+
return new Request(base + request.url, {
|
|
108
|
+
// @ts-expect-error
|
|
109
|
+
duplex: "half",
|
|
110
|
+
method: request.method,
|
|
111
|
+
body: get_raw_body(request, bodySizeLimit),
|
|
112
|
+
headers: request.headers
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async function setResponse(res, response) {
|
|
116
|
+
for (const [key, value] of response.headers) {
|
|
117
|
+
try {
|
|
118
|
+
res.setHeader(
|
|
119
|
+
key,
|
|
120
|
+
key === "set-cookie" ? set_cookie_parser.splitCookiesString(response.headers.get(key)) : value
|
|
121
|
+
);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
res.getHeaderNames().forEach((name) => res.removeHeader(name));
|
|
124
|
+
res.writeHead(500).end(String(error));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
res.writeHead(response.status);
|
|
129
|
+
if (!response.body) {
|
|
130
|
+
res.end();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (response.body.locked) {
|
|
134
|
+
res.end(
|
|
135
|
+
"Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()')."
|
|
136
|
+
);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const reader = response.body.getReader();
|
|
140
|
+
if (res.destroyed) {
|
|
141
|
+
reader.cancel();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const cancel = (error) => {
|
|
145
|
+
res.off("close", cancel);
|
|
146
|
+
res.off("error", cancel);
|
|
147
|
+
reader.cancel(error).catch(() => {
|
|
148
|
+
});
|
|
149
|
+
if (error) res.destroy(error);
|
|
150
|
+
};
|
|
151
|
+
res.on("close", cancel);
|
|
152
|
+
res.on("error", cancel);
|
|
153
|
+
next();
|
|
154
|
+
async function next() {
|
|
155
|
+
try {
|
|
156
|
+
for (; ; ) {
|
|
157
|
+
const { done, value } = await reader.read();
|
|
158
|
+
if (done) break;
|
|
159
|
+
if (!res.write(value)) {
|
|
160
|
+
res.once("drain", next);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
res.end();
|
|
165
|
+
} catch (error) {
|
|
166
|
+
cancel(error instanceof Error ? error : new Error(String(error)));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// src/adapters/node/index.ts
|
|
172
|
+
function toNodeHandler(handler) {
|
|
173
|
+
return async (req, res) => {
|
|
174
|
+
const protocol = req.headers["x-forwarded-proto"] || (req.socket.encrypted ? "https" : "http");
|
|
175
|
+
const base = `${protocol}://${req.headers[":authority"] || req.headers.host}`;
|
|
176
|
+
const response = await handler(getRequest({ base, request: req }));
|
|
177
|
+
setResponse(res, response);
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
181
|
+
0 && (module.exports = {
|
|
182
|
+
getRequest,
|
|
183
|
+
setResponse,
|
|
184
|
+
toNodeHandler
|
|
185
|
+
});
|
|
186
|
+
//# sourceMappingURL=node.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/node/index.ts","../src/adapters/node/request.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport { getRequest, setResponse } from \"./request\";\nimport type { Router } from \"../../router.js\";\n\nexport function toNodeHandler(handler: Router[\"handler\"]) {\n\treturn async (req: IncomingMessage, res: ServerResponse) => {\n\t\tconst protocol =\n\t\t\treq.headers[\"x-forwarded-proto\"] || ((req.socket as any).encrypted ? \"https\" : \"http\");\n\t\tconst base = `${protocol}://${req.headers[\":authority\"] || req.headers.host}`;\n\t\tconst response = await handler(getRequest({ base, request: req }));\n\t\tsetResponse(res, response);\n\t};\n}\n\nexport { getRequest, setResponse };\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport * as set_cookie_parser from \"set-cookie-parser\";\n\nfunction get_raw_body(req: IncomingMessage, body_size_limit?: number) {\n\tconst h = req.headers;\n\n\tif (!h[\"content-type\"]) return null;\n\n\tconst content_length = Number(h[\"content-length\"]);\n\n\t// check if no request body\n\tif (\n\t\t(req.httpVersionMajor === 1 && isNaN(content_length) && h[\"transfer-encoding\"] == null) ||\n\t\tcontent_length === 0\n\t) {\n\t\treturn null;\n\t}\n\n\tlet length = content_length;\n\n\tif (body_size_limit) {\n\t\tif (!length) {\n\t\t\tlength = body_size_limit;\n\t\t} else if (length > body_size_limit) {\n\t\t\tthrow Error(\n\t\t\t\t`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (req.destroyed) {\n\t\tconst readable = new ReadableStream();\n\t\treadable.cancel();\n\t\treturn readable;\n\t}\n\n\tlet size = 0;\n\tlet cancelled = false;\n\n\treturn new ReadableStream({\n\t\tstart(controller) {\n\t\t\treq.on(\"error\", (error) => {\n\t\t\t\tcancelled = true;\n\t\t\t\tcontroller.error(error);\n\t\t\t});\n\n\t\t\treq.on(\"end\", () => {\n\t\t\t\tif (cancelled) return;\n\t\t\t\tcontroller.close();\n\t\t\t});\n\n\t\t\treq.on(\"data\", (chunk) => {\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\tsize += chunk.length;\n\n\t\t\t\tif (size > length) {\n\t\t\t\t\tcancelled = true;\n\n\t\t\t\t\tcontroller.error(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`request body size exceeded ${\n\t\t\t\t\t\t\t\tcontent_length ? \"'content-length'\" : \"BODY_SIZE_LIMIT\"\n\t\t\t\t\t\t\t} of ${length}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontroller.enqueue(chunk);\n\n\t\t\t\tif (controller.desiredSize === null || controller.desiredSize <= 0) {\n\t\t\t\t\treq.pause();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\tpull() {\n\t\t\treq.resume();\n\t\t},\n\n\t\tcancel(reason) {\n\t\t\tcancelled = true;\n\t\t\treq.destroy(reason);\n\t\t},\n\t});\n}\n\nexport function getRequest({\n\trequest,\n\tbase,\n\tbodySizeLimit,\n}: {\n\tbase: string;\n\tbodySizeLimit?: number;\n\trequest: IncomingMessage;\n}) {\n\treturn new Request(base + request.url, {\n\t\t// @ts-expect-error\n\t\tduplex: \"half\",\n\t\tmethod: request.method,\n\t\tbody: get_raw_body(request, bodySizeLimit),\n\t\theaders: request.headers as Record<string, string>,\n\t});\n}\n\nexport async function setResponse(res: ServerResponse, response: Response) {\n\tfor (const [key, value] of response.headers as any) {\n\t\ttry {\n\t\t\tres.setHeader(\n\t\t\t\tkey,\n\t\t\t\tkey === \"set-cookie\"\n\t\t\t\t\t? set_cookie_parser.splitCookiesString(response.headers.get(key) as string)\n\t\t\t\t\t: value,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tres.getHeaderNames().forEach((name) => res.removeHeader(name));\n\t\t\tres.writeHead(500).end(String(error));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tres.writeHead(response.status);\n\n\tif (!response.body) {\n\t\tres.end();\n\t\treturn;\n\t}\n\n\tif (response.body.locked) {\n\t\tres.end(\n\t\t\t\"Fatal error: Response body is locked. \" +\n\t\t\t\t\"This can happen when the response was already read (for example through 'response.json()' or 'response.text()').\",\n\t\t);\n\t\treturn;\n\t}\n\n\tconst reader = response.body.getReader();\n\n\tif (res.destroyed) {\n\t\treader.cancel();\n\t\treturn;\n\t}\n\n\tconst cancel = (error?: Error) => {\n\t\tres.off(\"close\", cancel);\n\t\tres.off(\"error\", cancel);\n\n\t\t// If the reader has already been interrupted with an error earlier,\n\t\t// then it will appear here, it is useless, but it needs to be catch.\n\t\treader.cancel(error).catch(() => {});\n\t\tif (error) res.destroy(error);\n\t};\n\n\tres.on(\"close\", cancel);\n\tres.on(\"error\", cancel);\n\n\tnext();\n\tasync function next() {\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read();\n\n\t\t\t\tif (done) break;\n\n\t\t\t\tif (!res.write(value)) {\n\t\t\t\t\tres.once(\"drain\", next);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tres.end();\n\t\t} catch (error) {\n\t\t\tcancel(error instanceof Error ? error : new Error(String(error)));\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
|
package/dist/node.d.cts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { j as Router } from './router-CyNMWgsC.cjs';
|
|
3
|
+
|
|
4
|
+
declare function getRequest({ request, base, bodySizeLimit, }: {
|
|
5
|
+
base: string;
|
|
6
|
+
bodySizeLimit?: number;
|
|
7
|
+
request: IncomingMessage;
|
|
8
|
+
}): Request;
|
|
9
|
+
declare function setResponse(res: ServerResponse, response: Response): Promise<void>;
|
|
10
|
+
|
|
11
|
+
declare function toNodeHandler(handler: Router["handler"]): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
12
|
+
|
|
13
|
+
export { getRequest, setResponse, toNodeHandler };
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { j as Router } from './router-CyNMWgsC.js';
|
|
3
|
+
|
|
4
|
+
declare function getRequest({ request, base, bodySizeLimit, }: {
|
|
5
|
+
base: string;
|
|
6
|
+
bodySizeLimit?: number;
|
|
7
|
+
request: IncomingMessage;
|
|
8
|
+
}): Request;
|
|
9
|
+
declare function setResponse(res: ServerResponse, response: Response): Promise<void>;
|
|
10
|
+
|
|
11
|
+
declare function toNodeHandler(handler: Router["handler"]): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
12
|
+
|
|
13
|
+
export { getRequest, setResponse, toNodeHandler };
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// src/adapters/node/request.ts
|
|
2
|
+
import * as set_cookie_parser from "set-cookie-parser";
|
|
3
|
+
function get_raw_body(req, body_size_limit) {
|
|
4
|
+
const h = req.headers;
|
|
5
|
+
if (!h["content-type"]) return null;
|
|
6
|
+
const content_length = Number(h["content-length"]);
|
|
7
|
+
if (req.httpVersionMajor === 1 && isNaN(content_length) && h["transfer-encoding"] == null || content_length === 0) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
let length = content_length;
|
|
11
|
+
if (body_size_limit) {
|
|
12
|
+
if (!length) {
|
|
13
|
+
length = body_size_limit;
|
|
14
|
+
} else if (length > body_size_limit) {
|
|
15
|
+
throw Error(
|
|
16
|
+
`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (req.destroyed) {
|
|
21
|
+
const readable = new ReadableStream();
|
|
22
|
+
readable.cancel();
|
|
23
|
+
return readable;
|
|
24
|
+
}
|
|
25
|
+
let size = 0;
|
|
26
|
+
let cancelled = false;
|
|
27
|
+
return new ReadableStream({
|
|
28
|
+
start(controller) {
|
|
29
|
+
req.on("error", (error) => {
|
|
30
|
+
cancelled = true;
|
|
31
|
+
controller.error(error);
|
|
32
|
+
});
|
|
33
|
+
req.on("end", () => {
|
|
34
|
+
if (cancelled) return;
|
|
35
|
+
controller.close();
|
|
36
|
+
});
|
|
37
|
+
req.on("data", (chunk) => {
|
|
38
|
+
if (cancelled) return;
|
|
39
|
+
size += chunk.length;
|
|
40
|
+
if (size > length) {
|
|
41
|
+
cancelled = true;
|
|
42
|
+
controller.error(
|
|
43
|
+
new Error(
|
|
44
|
+
`request body size exceeded ${content_length ? "'content-length'" : "BODY_SIZE_LIMIT"} of ${length}`
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
controller.enqueue(chunk);
|
|
50
|
+
if (controller.desiredSize === null || controller.desiredSize <= 0) {
|
|
51
|
+
req.pause();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
pull() {
|
|
56
|
+
req.resume();
|
|
57
|
+
},
|
|
58
|
+
cancel(reason) {
|
|
59
|
+
cancelled = true;
|
|
60
|
+
req.destroy(reason);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function getRequest({
|
|
65
|
+
request,
|
|
66
|
+
base,
|
|
67
|
+
bodySizeLimit
|
|
68
|
+
}) {
|
|
69
|
+
return new Request(base + request.url, {
|
|
70
|
+
// @ts-expect-error
|
|
71
|
+
duplex: "half",
|
|
72
|
+
method: request.method,
|
|
73
|
+
body: get_raw_body(request, bodySizeLimit),
|
|
74
|
+
headers: request.headers
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
async function setResponse(res, response) {
|
|
78
|
+
for (const [key, value] of response.headers) {
|
|
79
|
+
try {
|
|
80
|
+
res.setHeader(
|
|
81
|
+
key,
|
|
82
|
+
key === "set-cookie" ? set_cookie_parser.splitCookiesString(response.headers.get(key)) : value
|
|
83
|
+
);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
res.getHeaderNames().forEach((name) => res.removeHeader(name));
|
|
86
|
+
res.writeHead(500).end(String(error));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
res.writeHead(response.status);
|
|
91
|
+
if (!response.body) {
|
|
92
|
+
res.end();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (response.body.locked) {
|
|
96
|
+
res.end(
|
|
97
|
+
"Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()')."
|
|
98
|
+
);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const reader = response.body.getReader();
|
|
102
|
+
if (res.destroyed) {
|
|
103
|
+
reader.cancel();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const cancel = (error) => {
|
|
107
|
+
res.off("close", cancel);
|
|
108
|
+
res.off("error", cancel);
|
|
109
|
+
reader.cancel(error).catch(() => {
|
|
110
|
+
});
|
|
111
|
+
if (error) res.destroy(error);
|
|
112
|
+
};
|
|
113
|
+
res.on("close", cancel);
|
|
114
|
+
res.on("error", cancel);
|
|
115
|
+
next();
|
|
116
|
+
async function next() {
|
|
117
|
+
try {
|
|
118
|
+
for (; ; ) {
|
|
119
|
+
const { done, value } = await reader.read();
|
|
120
|
+
if (done) break;
|
|
121
|
+
if (!res.write(value)) {
|
|
122
|
+
res.once("drain", next);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
res.end();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
cancel(error instanceof Error ? error : new Error(String(error)));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/adapters/node/index.ts
|
|
134
|
+
function toNodeHandler(handler) {
|
|
135
|
+
return async (req, res) => {
|
|
136
|
+
const protocol = req.headers["x-forwarded-proto"] || (req.socket.encrypted ? "https" : "http");
|
|
137
|
+
const base = `${protocol}://${req.headers[":authority"] || req.headers.host}`;
|
|
138
|
+
const response = await handler(getRequest({ base, request: req }));
|
|
139
|
+
setResponse(res, response);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
getRequest,
|
|
144
|
+
setResponse,
|
|
145
|
+
toNodeHandler
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/node/request.ts","../src/adapters/node/index.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport * as set_cookie_parser from \"set-cookie-parser\";\n\nfunction get_raw_body(req: IncomingMessage, body_size_limit?: number) {\n\tconst h = req.headers;\n\n\tif (!h[\"content-type\"]) return null;\n\n\tconst content_length = Number(h[\"content-length\"]);\n\n\t// check if no request body\n\tif (\n\t\t(req.httpVersionMajor === 1 && isNaN(content_length) && h[\"transfer-encoding\"] == null) ||\n\t\tcontent_length === 0\n\t) {\n\t\treturn null;\n\t}\n\n\tlet length = content_length;\n\n\tif (body_size_limit) {\n\t\tif (!length) {\n\t\t\tlength = body_size_limit;\n\t\t} else if (length > body_size_limit) {\n\t\t\tthrow Error(\n\t\t\t\t`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (req.destroyed) {\n\t\tconst readable = new ReadableStream();\n\t\treadable.cancel();\n\t\treturn readable;\n\t}\n\n\tlet size = 0;\n\tlet cancelled = false;\n\n\treturn new ReadableStream({\n\t\tstart(controller) {\n\t\t\treq.on(\"error\", (error) => {\n\t\t\t\tcancelled = true;\n\t\t\t\tcontroller.error(error);\n\t\t\t});\n\n\t\t\treq.on(\"end\", () => {\n\t\t\t\tif (cancelled) return;\n\t\t\t\tcontroller.close();\n\t\t\t});\n\n\t\t\treq.on(\"data\", (chunk) => {\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\tsize += chunk.length;\n\n\t\t\t\tif (size > length) {\n\t\t\t\t\tcancelled = true;\n\n\t\t\t\t\tcontroller.error(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`request body size exceeded ${\n\t\t\t\t\t\t\t\tcontent_length ? \"'content-length'\" : \"BODY_SIZE_LIMIT\"\n\t\t\t\t\t\t\t} of ${length}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontroller.enqueue(chunk);\n\n\t\t\t\tif (controller.desiredSize === null || controller.desiredSize <= 0) {\n\t\t\t\t\treq.pause();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\tpull() {\n\t\t\treq.resume();\n\t\t},\n\n\t\tcancel(reason) {\n\t\t\tcancelled = true;\n\t\t\treq.destroy(reason);\n\t\t},\n\t});\n}\n\nexport function getRequest({\n\trequest,\n\tbase,\n\tbodySizeLimit,\n}: {\n\tbase: string;\n\tbodySizeLimit?: number;\n\trequest: IncomingMessage;\n}) {\n\treturn new Request(base + request.url, {\n\t\t// @ts-expect-error\n\t\tduplex: \"half\",\n\t\tmethod: request.method,\n\t\tbody: get_raw_body(request, bodySizeLimit),\n\t\theaders: request.headers as Record<string, string>,\n\t});\n}\n\nexport async function setResponse(res: ServerResponse, response: Response) {\n\tfor (const [key, value] of response.headers as any) {\n\t\ttry {\n\t\t\tres.setHeader(\n\t\t\t\tkey,\n\t\t\t\tkey === \"set-cookie\"\n\t\t\t\t\t? set_cookie_parser.splitCookiesString(response.headers.get(key) as string)\n\t\t\t\t\t: value,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tres.getHeaderNames().forEach((name) => res.removeHeader(name));\n\t\t\tres.writeHead(500).end(String(error));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tres.writeHead(response.status);\n\n\tif (!response.body) {\n\t\tres.end();\n\t\treturn;\n\t}\n\n\tif (response.body.locked) {\n\t\tres.end(\n\t\t\t\"Fatal error: Response body is locked. \" +\n\t\t\t\t\"This can happen when the response was already read (for example through 'response.json()' or 'response.text()').\",\n\t\t);\n\t\treturn;\n\t}\n\n\tconst reader = response.body.getReader();\n\n\tif (res.destroyed) {\n\t\treader.cancel();\n\t\treturn;\n\t}\n\n\tconst cancel = (error?: Error) => {\n\t\tres.off(\"close\", cancel);\n\t\tres.off(\"error\", cancel);\n\n\t\t// If the reader has already been interrupted with an error earlier,\n\t\t// then it will appear here, it is useless, but it needs to be catch.\n\t\treader.cancel(error).catch(() => {});\n\t\tif (error) res.destroy(error);\n\t};\n\n\tres.on(\"close\", cancel);\n\tres.on(\"error\", cancel);\n\n\tnext();\n\tasync function next() {\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read();\n\n\t\t\t\tif (done) break;\n\n\t\t\t\tif (!res.write(value)) {\n\t\t\t\t\tres.once(\"drain\", next);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tres.end();\n\t\t} catch (error) {\n\t\t\tcancel(error instanceof Error ? error : new Error(String(error)));\n\t\t}\n\t}\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport { getRequest, setResponse } from \"./request\";\nimport type { Router } from \"../../router.js\";\n\nexport function toNodeHandler(handler: Router[\"handler\"]) {\n\treturn async (req: IncomingMessage, res: ServerResponse) => {\n\t\tconst protocol =\n\t\t\treq.headers[\"x-forwarded-proto\"] || ((req.socket as any).encrypted ? \"https\" : \"http\");\n\t\tconst base = `${protocol}://${req.headers[\":authority\"] || req.headers.host}`;\n\t\tconst response = await handler(getRequest({ base, request: req }));\n\t\tsetResponse(res, response);\n\t};\n}\n\nexport { getRequest, setResponse };\n"],"mappings":"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","names":[]}
|