better-call 1.1.6 → 1.1.7
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 +35 -0
- package/dist/_virtual/rolldown_runtime.cjs +29 -0
- package/dist/adapters/node/request.cjs +125 -0
- package/dist/adapters/node/request.cjs.map +1 -0
- package/dist/{node.d.ts → adapters/node/request.d.cts} +2 -6
- package/dist/adapters/node/request.d.mts +16 -0
- package/dist/{node.js → adapters/node/request.mjs} +2 -13
- package/dist/adapters/node/request.mjs.map +1 -0
- package/dist/client.cjs +2 -2
- package/dist/client.d.cts +11 -13
- package/dist/client.d.mts +53 -0
- package/dist/{client.js → client.mjs} +2 -2
- package/dist/client.mjs.map +1 -0
- package/dist/context.cjs +102 -0
- package/dist/context.cjs.map +1 -0
- package/dist/context.d.cts +340 -0
- package/dist/context.d.mts +340 -0
- package/dist/context.mjs +102 -0
- package/dist/context.mjs.map +1 -0
- package/dist/cookies.cjs +87 -0
- package/dist/cookies.cjs.map +1 -0
- package/dist/cookies.d.cts +103 -0
- package/dist/cookies.d.mts +103 -0
- package/dist/cookies.mjs +84 -0
- package/dist/cookies.mjs.map +1 -0
- package/dist/crypto.cjs +39 -0
- package/dist/crypto.cjs.map +1 -0
- package/dist/crypto.mjs +36 -0
- package/dist/crypto.mjs.map +1 -0
- package/dist/endpoint.cjs +70 -0
- package/dist/endpoint.cjs.map +1 -0
- package/dist/endpoint.d.cts +428 -0
- package/dist/endpoint.d.mts +428 -0
- package/dist/endpoint.mjs +70 -0
- package/dist/endpoint.mjs.map +1 -0
- package/dist/error.cjs +140 -7
- package/dist/error.cjs.map +1 -0
- package/dist/error.d.cts +103 -2
- package/dist/{error2.d.ts → error.d.mts} +5 -59
- package/dist/{error2.js → error.mjs} +2 -2
- package/dist/{error2.js.map → error.mjs.map} +1 -1
- package/dist/helper.d.cts +12 -0
- package/dist/helper.d.mts +12 -0
- package/dist/index.cjs +19 -829
- package/dist/index.d.cts +11 -15
- package/dist/index.d.mts +11 -0
- package/dist/index.mjs +10 -0
- package/dist/middleware.cjs +39 -0
- package/dist/middleware.cjs.map +1 -0
- package/dist/middleware.d.cts +123 -0
- package/dist/middleware.d.mts +123 -0
- package/dist/middleware.mjs +39 -0
- package/dist/middleware.mjs.map +1 -0
- package/dist/node.cjs +4 -151
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +2 -13
- package/dist/node.d.mts +9 -0
- package/dist/node.mjs +15 -0
- package/dist/node.mjs.map +1 -0
- package/dist/openapi.cjs +191 -0
- package/dist/openapi.cjs.map +1 -0
- package/dist/openapi.d.cts +113 -0
- package/dist/openapi.d.mts +113 -0
- package/dist/openapi.mjs +189 -0
- package/dist/openapi.mjs.map +1 -0
- package/dist/router.cjs +117 -0
- package/dist/router.cjs.map +1 -0
- package/dist/router.d.cts +3 -1088
- package/dist/router.d.mts +97 -0
- package/dist/router.mjs +116 -0
- package/dist/router.mjs.map +1 -0
- package/dist/standard-schema.d.cts +59 -0
- package/dist/standard-schema.d.mts +59 -0
- package/dist/to-response.cjs +96 -0
- package/dist/to-response.cjs.map +1 -0
- package/dist/to-response.d.cts +12 -0
- package/dist/to-response.d.mts +12 -0
- package/dist/to-response.mjs +96 -0
- package/dist/to-response.mjs.map +1 -0
- package/dist/utils.cjs +77 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.mjs +74 -0
- package/dist/utils.mjs.map +1 -0
- package/dist/validator.cjs +58 -0
- package/dist/validator.cjs.map +1 -0
- package/dist/validator.mjs +57 -0
- package/dist/validator.mjs.map +1 -0
- package/package.json +15 -15
- package/dist/client.d.ts +0 -55
- package/dist/client.js.map +0 -1
- package/dist/error.d.ts +0 -2
- package/dist/error.js +0 -3
- package/dist/error2.cjs +0 -171
- package/dist/error2.cjs.map +0 -1
- package/dist/error2.d.cts +0 -157
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -15
- package/dist/index.js +0 -819
- package/dist/index.js.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/router.d.ts +0 -1182
package/README.md
CHANGED
|
@@ -158,6 +158,41 @@ const createItem = createEndpoint("/item", {
|
|
|
158
158
|
})
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
+
#### Method
|
|
162
|
+
|
|
163
|
+
You can specify a single HTTP method or an array of methods for an endpoint.
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
// Single method
|
|
167
|
+
const getItem = createEndpoint("/item", {
|
|
168
|
+
method: "GET",
|
|
169
|
+
}, async (ctx) => {
|
|
170
|
+
return { item: "data" }
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
// Multiple methods
|
|
174
|
+
const itemEndpoint = createEndpoint("/item", {
|
|
175
|
+
method: ["GET", "POST"],
|
|
176
|
+
}, async (ctx) => {
|
|
177
|
+
if (ctx.method === "POST") {
|
|
178
|
+
// handle POST - create/update
|
|
179
|
+
return { created: true }
|
|
180
|
+
}
|
|
181
|
+
// handle GET - read only
|
|
182
|
+
return { item: "data" }
|
|
183
|
+
})
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
When calling an endpoint with multiple methods directly (not through HTTP), the `method` parameter is **optional** and defaults to the **first method** in the array:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
// Defaults to "GET" (first in array)
|
|
190
|
+
const result = await itemEndpoint({ headers })
|
|
191
|
+
|
|
192
|
+
// Explicitly specify POST
|
|
193
|
+
const result = await itemEndpoint({ headers, method: "POST" })
|
|
194
|
+
```
|
|
195
|
+
|
|
161
196
|
#### Media types
|
|
162
197
|
|
|
163
198
|
By default, all media types are accepted, but only a handful of them have a built-in support:
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
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 __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
+
value: mod,
|
|
24
|
+
enumerable: true
|
|
25
|
+
}) : target, mod));
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
|
|
29
|
+
exports.__toESM = __toESM;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let set_cookie_parser = require("set-cookie-parser");
|
|
3
|
+
set_cookie_parser = require_rolldown_runtime.__toESM(set_cookie_parser);
|
|
4
|
+
|
|
5
|
+
//#region src/adapters/node/request.ts
|
|
6
|
+
function get_raw_body(req, body_size_limit) {
|
|
7
|
+
const h = req.headers;
|
|
8
|
+
if (!h["content-type"]) return null;
|
|
9
|
+
const content_length = Number(h["content-length"]);
|
|
10
|
+
if (req.httpVersionMajor === 1 && isNaN(content_length) && h["transfer-encoding"] == null || content_length === 0) return null;
|
|
11
|
+
let length = content_length;
|
|
12
|
+
if (body_size_limit) {
|
|
13
|
+
if (!length) length = body_size_limit;
|
|
14
|
+
else if (length > body_size_limit) throw Error(`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`);
|
|
15
|
+
}
|
|
16
|
+
if (req.destroyed) {
|
|
17
|
+
const readable = new ReadableStream();
|
|
18
|
+
readable.cancel();
|
|
19
|
+
return readable;
|
|
20
|
+
}
|
|
21
|
+
let size = 0;
|
|
22
|
+
let cancelled = false;
|
|
23
|
+
return new ReadableStream({
|
|
24
|
+
start(controller) {
|
|
25
|
+
req.on("error", (error) => {
|
|
26
|
+
cancelled = true;
|
|
27
|
+
controller.error(error);
|
|
28
|
+
});
|
|
29
|
+
req.on("end", () => {
|
|
30
|
+
if (cancelled) return;
|
|
31
|
+
controller.close();
|
|
32
|
+
});
|
|
33
|
+
req.on("data", (chunk) => {
|
|
34
|
+
if (cancelled) return;
|
|
35
|
+
size += chunk.length;
|
|
36
|
+
if (size > length) {
|
|
37
|
+
cancelled = true;
|
|
38
|
+
controller.error(/* @__PURE__ */ new Error(`request body size exceeded ${content_length ? "'content-length'" : "BODY_SIZE_LIMIT"} of ${length}`));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
controller.enqueue(chunk);
|
|
42
|
+
if (controller.desiredSize === null || controller.desiredSize <= 0) req.pause();
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
pull() {
|
|
46
|
+
req.resume();
|
|
47
|
+
},
|
|
48
|
+
cancel(reason) {
|
|
49
|
+
cancelled = true;
|
|
50
|
+
req.destroy(reason);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function getRequest({ request, base, bodySizeLimit }) {
|
|
55
|
+
const baseUrl = request?.baseUrl;
|
|
56
|
+
const fullPath = baseUrl ? baseUrl + request.url : request.url;
|
|
57
|
+
const maybeConsumedReq = request;
|
|
58
|
+
let body = void 0;
|
|
59
|
+
const method = request.method;
|
|
60
|
+
if (method !== "GET" && method !== "HEAD") if (maybeConsumedReq.body !== void 0) {
|
|
61
|
+
const bodyContent = typeof maybeConsumedReq.body === "string" ? maybeConsumedReq.body : JSON.stringify(maybeConsumedReq.body);
|
|
62
|
+
body = new ReadableStream({ start(controller) {
|
|
63
|
+
controller.enqueue(new TextEncoder().encode(bodyContent));
|
|
64
|
+
controller.close();
|
|
65
|
+
} });
|
|
66
|
+
} else body = get_raw_body(request, bodySizeLimit);
|
|
67
|
+
return new Request(base + fullPath, {
|
|
68
|
+
duplex: "half",
|
|
69
|
+
method: request.method,
|
|
70
|
+
body,
|
|
71
|
+
headers: request.headers
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async function setResponse(res, response) {
|
|
75
|
+
for (const [key, value] of response.headers) try {
|
|
76
|
+
res.setHeader(key, key === "set-cookie" ? set_cookie_parser.splitCookiesString(response.headers.get(key)) : value);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
res.getHeaderNames().forEach((name) => res.removeHeader(name));
|
|
79
|
+
res.writeHead(500).end(String(error));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
res.writeHead(response.status);
|
|
83
|
+
if (!response.body) {
|
|
84
|
+
res.end();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (response.body.locked) {
|
|
88
|
+
res.end("Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()').");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const reader = response.body.getReader();
|
|
92
|
+
if (res.destroyed) {
|
|
93
|
+
reader.cancel();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const cancel = (error) => {
|
|
97
|
+
res.off("close", cancel);
|
|
98
|
+
res.off("error", cancel);
|
|
99
|
+
reader.cancel(error).catch(() => {});
|
|
100
|
+
if (error) res.destroy(error);
|
|
101
|
+
};
|
|
102
|
+
res.on("close", cancel);
|
|
103
|
+
res.on("error", cancel);
|
|
104
|
+
next();
|
|
105
|
+
async function next() {
|
|
106
|
+
try {
|
|
107
|
+
for (;;) {
|
|
108
|
+
const { done, value } = await reader.read();
|
|
109
|
+
if (done) break;
|
|
110
|
+
if (!res.write(value)) {
|
|
111
|
+
res.once("drain", next);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
res.end();
|
|
116
|
+
} catch (error) {
|
|
117
|
+
cancel(error instanceof Error ? error : new Error(String(error)));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
exports.getRequest = getRequest;
|
|
124
|
+
exports.setResponse = setResponse;
|
|
125
|
+
//# sourceMappingURL=request.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.cjs","names":[],"sources":["../../../src/adapters/node/request.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\t// In Express sub-routers, `request.url` is relative to the mount path (e.g., '/auth/xxx'),\n\t// and `request.baseUrl` holds the mount path (e.g., '/api').\n\t// Build the full path as baseUrl + url when available to preserve the full route.\n\tconst baseUrl = (request as any)?.baseUrl as string | undefined;\n\tconst fullPath = baseUrl ? baseUrl + request.url : request.url;\n\n\t// Check if body has already been parsed by Express middleware\n\tconst maybeConsumedReq = request as any;\n\tlet body = undefined;\n\n\tconst method = request.method;\n\t// Request with GET/HEAD method cannot have body.\n\tif (method !== \"GET\" && method !== \"HEAD\") {\n\t\t// If body was already parsed by Express body-parser middleware\n\t\tif (maybeConsumedReq.body !== undefined) {\n\t\t\t// Convert parsed body back to a ReadableStream\n\t\t\tconst bodyContent =\n\t\t\t\ttypeof maybeConsumedReq.body === \"string\"\n\t\t\t\t\t? maybeConsumedReq.body\n\t\t\t\t\t: JSON.stringify(maybeConsumedReq.body);\n\n\t\t\tbody = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tcontroller.enqueue(new TextEncoder().encode(bodyContent));\n\t\t\t\t\tcontroller.close();\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\t// Otherwise, get the raw body stream\n\t\t\tbody = get_raw_body(request, bodySizeLimit);\n\t\t}\n\t}\n\n\treturn new Request(base + fullPath, {\n\t\t// @ts-expect-error\n\t\tduplex: \"half\",\n\t\tmethod: request.method,\n\t\tbody,\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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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { t as Router } from "./router.js";
|
|
2
1
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
3
2
|
|
|
4
3
|
//#region src/adapters/node/request.d.ts
|
|
@@ -13,8 +12,5 @@ declare function getRequest({
|
|
|
13
12
|
}): Request;
|
|
14
13
|
declare function setResponse(res: ServerResponse, response: Response): Promise<void>;
|
|
15
14
|
//#endregion
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//#endregion
|
|
19
|
-
export { getRequest, setResponse, toNodeHandler };
|
|
20
|
-
//# sourceMappingURL=node.d.ts.map
|
|
15
|
+
export { getRequest, setResponse };
|
|
16
|
+
//# sourceMappingURL=request.d.cts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/node/request.d.ts
|
|
4
|
+
declare function getRequest({
|
|
5
|
+
request,
|
|
6
|
+
base,
|
|
7
|
+
bodySizeLimit
|
|
8
|
+
}: {
|
|
9
|
+
base: string;
|
|
10
|
+
bodySizeLimit?: number;
|
|
11
|
+
request: IncomingMessage;
|
|
12
|
+
}): Request;
|
|
13
|
+
declare function setResponse(res: ServerResponse, response: Response): Promise<void>;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { getRequest, setResponse };
|
|
16
|
+
//# sourceMappingURL=request.d.mts.map
|
|
@@ -118,16 +118,5 @@ async function setResponse(res, response) {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
//#endregion
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return async (req, res) => {
|
|
124
|
-
return setResponse(res, await handler(getRequest({
|
|
125
|
-
base: `${req.headers["x-forwarded-proto"] || (req.socket.encrypted ? "https" : "http")}://${req.headers[":authority"] || req.headers.host}`,
|
|
126
|
-
request: req
|
|
127
|
-
})));
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
//#endregion
|
|
132
|
-
export { getRequest, setResponse, toNodeHandler };
|
|
133
|
-
//# sourceMappingURL=node.js.map
|
|
121
|
+
export { getRequest, setResponse };
|
|
122
|
+
//# sourceMappingURL=request.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.mjs","names":[],"sources":["../../../src/adapters/node/request.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\t// In Express sub-routers, `request.url` is relative to the mount path (e.g., '/auth/xxx'),\n\t// and `request.baseUrl` holds the mount path (e.g., '/api').\n\t// Build the full path as baseUrl + url when available to preserve the full route.\n\tconst baseUrl = (request as any)?.baseUrl as string | undefined;\n\tconst fullPath = baseUrl ? baseUrl + request.url : request.url;\n\n\t// Check if body has already been parsed by Express middleware\n\tconst maybeConsumedReq = request as any;\n\tlet body = undefined;\n\n\tconst method = request.method;\n\t// Request with GET/HEAD method cannot have body.\n\tif (method !== \"GET\" && method !== \"HEAD\") {\n\t\t// If body was already parsed by Express body-parser middleware\n\t\tif (maybeConsumedReq.body !== undefined) {\n\t\t\t// Convert parsed body back to a ReadableStream\n\t\t\tconst bodyContent =\n\t\t\t\ttypeof maybeConsumedReq.body === \"string\"\n\t\t\t\t\t? maybeConsumedReq.body\n\t\t\t\t\t: JSON.stringify(maybeConsumedReq.body);\n\n\t\t\tbody = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tcontroller.enqueue(new TextEncoder().encode(bodyContent));\n\t\t\t\t\tcontroller.close();\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\t// Otherwise, get the raw body stream\n\t\t\tbody = get_raw_body(request, bodySizeLimit);\n\t\t}\n\t}\n\n\treturn new Request(base + fullPath, {\n\t\t// @ts-expect-error\n\t\tduplex: \"half\",\n\t\tmethod: request.method,\n\t\tbody,\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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"}
|
package/dist/client.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_error = require('./error.cjs');
|
|
3
3
|
let __better_fetch_fetch = require("@better-fetch/fetch");
|
|
4
4
|
|
|
5
5
|
//#region src/client.ts
|
package/dist/client.d.cts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { HasRequiredKeys, UnionToIntersection } from "./helper.cjs";
|
|
2
|
+
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes } from "./error.cjs";
|
|
3
|
+
import { Endpoint } from "./endpoint.cjs";
|
|
4
|
+
import { Router } from "./router.cjs";
|
|
3
5
|
import { BetterFetchOption, BetterFetchResponse } from "@better-fetch/fetch";
|
|
4
6
|
|
|
5
7
|
//#region src/client.d.ts
|
|
6
|
-
type HasRequired<T extends {
|
|
8
|
+
type HasRequired<T$1 extends {
|
|
7
9
|
body?: any;
|
|
8
10
|
query?: any;
|
|
9
11
|
params?: any;
|
|
10
|
-
}> = T["body"] extends object ? HasRequiredKeys<T["body"]> extends true ? true : T["query"] extends object ? HasRequiredKeys<T["query"]> extends true ? true : T["params"] extends object ? HasRequiredKeys<T["params"]> : false : T["params"] extends object ? HasRequiredKeys<T["params"]> : false : T["query"] extends object ? HasRequiredKeys<T["query"]> extends true ? true : T["params"] extends object ? HasRequiredKeys<T["params"]> : false : T["params"] extends object ? HasRequiredKeys<T["params"]> : false;
|
|
11
|
-
type InferContext<T> = T extends ((ctx: infer Ctx) => any) ? Ctx extends object ? Ctx : never : never;
|
|
12
|
+
}> = T$1["body"] extends object ? HasRequiredKeys<T$1["body"]> extends true ? true : T$1["query"] extends object ? HasRequiredKeys<T$1["query"]> extends true ? true : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["query"] extends object ? HasRequiredKeys<T$1["query"]> extends true ? true : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false;
|
|
13
|
+
type InferContext<T$1> = T$1 extends ((ctx: infer Ctx) => any) ? Ctx extends object ? Ctx : never : never;
|
|
12
14
|
interface ClientOptions extends BetterFetchOption {
|
|
13
15
|
baseURL: string;
|
|
14
16
|
}
|
|
15
|
-
type WithRequired<T, K> = T & { [P in K extends string ? K : never]-?: T[P extends keyof T ? P : never] };
|
|
16
|
-
type InferClientRoutes<T extends Record<string, Endpoint>> = { [K in keyof T]: T[K] extends Endpoint<any, infer O> ? O extends {
|
|
17
|
+
type WithRequired<T$1, K$1> = T$1 & { [P in K$1 extends string ? K$1 : never]-?: T$1[P extends keyof T$1 ? P : never] };
|
|
18
|
+
type InferClientRoutes<T$1 extends Record<string, Endpoint>> = { [K in keyof T$1]: T$1[K] extends Endpoint<any, infer O> ? O extends {
|
|
17
19
|
metadata: {
|
|
18
20
|
scope: "http";
|
|
19
21
|
};
|
|
@@ -29,7 +31,7 @@ type InferClientRoutes<T extends Record<string, Endpoint>> = { [K in keyof T]: T
|
|
|
29
31
|
metadata: {
|
|
30
32
|
isAction: false;
|
|
31
33
|
};
|
|
32
|
-
} ? never : T[K] : T[K] };
|
|
34
|
+
} ? never : T$1[K] : T$1[K] };
|
|
33
35
|
type RequiredOptionKeys<C extends {
|
|
34
36
|
body?: any;
|
|
35
37
|
query?: any;
|
|
@@ -45,11 +47,7 @@ declare const createClient: <R extends Router | Router["endpoints"]>(options: Cl
|
|
|
45
47
|
endpoints: Record<string, Endpoint>;
|
|
46
48
|
} ? R["endpoints"] : R> extends {
|
|
47
49
|
[key: string]: infer T_1;
|
|
48
|
-
} ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1 } : {} : {}> extends infer T ? { [K_1 in keyof T]:
|
|
49
|
-
endpoints: Record<string, Endpoint>;
|
|
50
|
-
} ? R["endpoints"] : R> extends {
|
|
51
|
-
[key: string]: infer T_1;
|
|
52
|
-
} ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1 } : {} : {}>[K_1] } : never), K extends keyof OPT, C extends InferContext<OPT[K]>>(path: K, ...options: HasRequired<C> extends true ? [WithRequired<BetterFetchOption<C["body"], C["query"], C["params"]>, keyof RequiredOptionKeys<C>>] : [BetterFetchOption<C["body"], C["query"], C["params"]>?]) => Promise<BetterFetchResponse<Awaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>>>;
|
|
50
|
+
} ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1 } : {} : {}> extends infer T ? { [K_1 in keyof T]: T[K_1] } : never), K$1 extends keyof OPT, C extends InferContext<OPT[K$1]>>(path: K$1, ...options: HasRequired<C> extends true ? [WithRequired<BetterFetchOption<C["body"], C["query"], C["params"]>, keyof RequiredOptionKeys<C>>] : [BetterFetchOption<C["body"], C["query"], C["params"]>?]) => Promise<BetterFetchResponse<Awaited<ReturnType<OPT[K$1] extends Endpoint ? OPT[K$1] : never>>>>;
|
|
53
51
|
//#endregion
|
|
54
52
|
export { APIError, BetterCallError, ClientOptions, RequiredOptionKeys, Status, ValidationError, createClient, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes };
|
|
55
53
|
//# sourceMappingURL=client.d.cts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { HasRequiredKeys, UnionToIntersection } from "./helper.mjs";
|
|
2
|
+
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
3
|
+
import { Endpoint } from "./endpoint.mjs";
|
|
4
|
+
import { Router } from "./router.mjs";
|
|
5
|
+
import { BetterFetchOption, BetterFetchResponse } from "@better-fetch/fetch";
|
|
6
|
+
|
|
7
|
+
//#region src/client.d.ts
|
|
8
|
+
type HasRequired<T$1 extends {
|
|
9
|
+
body?: any;
|
|
10
|
+
query?: any;
|
|
11
|
+
params?: any;
|
|
12
|
+
}> = T$1["body"] extends object ? HasRequiredKeys<T$1["body"]> extends true ? true : T$1["query"] extends object ? HasRequiredKeys<T$1["query"]> extends true ? true : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["query"] extends object ? HasRequiredKeys<T$1["query"]> extends true ? true : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false;
|
|
13
|
+
type InferContext<T$1> = T$1 extends ((ctx: infer Ctx) => any) ? Ctx extends object ? Ctx : never : never;
|
|
14
|
+
interface ClientOptions extends BetterFetchOption {
|
|
15
|
+
baseURL: string;
|
|
16
|
+
}
|
|
17
|
+
type WithRequired<T$1, K$1> = T$1 & { [P in K$1 extends string ? K$1 : never]-?: T$1[P extends keyof T$1 ? P : never] };
|
|
18
|
+
type InferClientRoutes<T$1 extends Record<string, Endpoint>> = { [K in keyof T$1]: T$1[K] extends Endpoint<any, infer O> ? O extends {
|
|
19
|
+
metadata: {
|
|
20
|
+
scope: "http";
|
|
21
|
+
};
|
|
22
|
+
} | {
|
|
23
|
+
metadata: {
|
|
24
|
+
scope: "server";
|
|
25
|
+
};
|
|
26
|
+
} | {
|
|
27
|
+
metadata: {
|
|
28
|
+
SERVER_ONLY: true;
|
|
29
|
+
};
|
|
30
|
+
} | {
|
|
31
|
+
metadata: {
|
|
32
|
+
isAction: false;
|
|
33
|
+
};
|
|
34
|
+
} ? never : T$1[K] : T$1[K] };
|
|
35
|
+
type RequiredOptionKeys<C extends {
|
|
36
|
+
body?: any;
|
|
37
|
+
query?: any;
|
|
38
|
+
params?: any;
|
|
39
|
+
}> = (undefined extends C["body"] ? {} : {
|
|
40
|
+
body: true;
|
|
41
|
+
}) & (undefined extends C["query"] ? {} : {
|
|
42
|
+
query: true;
|
|
43
|
+
}) & (undefined extends C["params"] ? {} : {
|
|
44
|
+
params: true;
|
|
45
|
+
});
|
|
46
|
+
declare const createClient: <R extends Router | Router["endpoints"]>(options: ClientOptions) => <OPT extends (UnionToIntersection<InferClientRoutes<R extends {
|
|
47
|
+
endpoints: Record<string, Endpoint>;
|
|
48
|
+
} ? R["endpoints"] : R> extends {
|
|
49
|
+
[key: string]: infer T_1;
|
|
50
|
+
} ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1 } : {} : {}> extends infer T ? { [K_1 in keyof T]: T[K_1] } : never), K$1 extends keyof OPT, C extends InferContext<OPT[K$1]>>(path: K$1, ...options: HasRequired<C> extends true ? [WithRequired<BetterFetchOption<C["body"], C["query"], C["params"]>, keyof RequiredOptionKeys<C>>] : [BetterFetchOption<C["body"], C["query"], C["params"]>?]) => Promise<BetterFetchResponse<Awaited<ReturnType<OPT[K$1] extends Endpoint ? OPT[K$1] : never>>>>;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { APIError, BetterCallError, ClientOptions, RequiredOptionKeys, Status, ValidationError, createClient, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes };
|
|
53
|
+
//# sourceMappingURL=client.d.mts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { APIError, BetterCallError, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
2
2
|
import { createFetch } from "@better-fetch/fetch";
|
|
3
3
|
|
|
4
4
|
//#region src/client.ts
|
|
@@ -11,4 +11,4 @@ const createClient = (options) => {
|
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
13
|
export { APIError, BetterCallError, ValidationError, createClient, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes };
|
|
14
|
-
//# sourceMappingURL=client.
|
|
14
|
+
//# sourceMappingURL=client.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.mjs","names":["options"],"sources":["../src/client.ts"],"sourcesContent":["import { type BetterFetchOption, type BetterFetchResponse, createFetch } from \"@better-fetch/fetch\";\nimport type { Router } from \"./router\";\nimport type { HasRequiredKeys, Prettify, UnionToIntersection } from \"./helper\";\nimport type { Endpoint } from \"./endpoint\";\n\ntype HasRequired<\n\tT extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = T[\"body\"] extends object\n\t? HasRequiredKeys<T[\"body\"]> extends true\n\t\t? true\n\t\t: T[\"query\"] extends object\n\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t? true\n\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t: false\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t: T[\"query\"] extends object\n\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t? true\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t\t: T[\"params\"] extends object\n\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t: false;\n\ntype InferContext<T> = T extends (ctx: infer Ctx) => any\n\t? Ctx extends object\n\t\t? Ctx\n\t\t: never\n\t: never;\n\nexport interface ClientOptions extends BetterFetchOption {\n\tbaseURL: string;\n}\n\ntype WithRequired<T, K> = T & {\n\t[P in K extends string ? K : never]-?: T[P extends keyof T ? P : never];\n};\n\ntype InferClientRoutes<T extends Record<string, Endpoint>> = {\n\t[K in keyof T]: T[K] extends Endpoint<any, infer O>\n\t\t? O extends\n\t\t\t\t| { metadata: { scope: \"http\" } }\n\t\t\t\t| { metadata: { scope: \"server\" } }\n\t\t\t\t| { metadata: { SERVER_ONLY: true } }\n\t\t\t\t| { metadata: { isAction: false } }\n\t\t\t? never\n\t\t\t: T[K]\n\t\t: T[K];\n};\n\nexport type RequiredOptionKeys<\n\tC extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = (undefined extends C[\"body\"]\n\t? {}\n\t: {\n\t\t\tbody: true;\n\t\t}) &\n\t(undefined extends C[\"query\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tquery: true;\n\t\t\t}) &\n\t(undefined extends C[\"params\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tparams: true;\n\t\t\t});\n\nexport const createClient = <R extends Router | Router[\"endpoints\"]>(options: ClientOptions) => {\n\tconst fetch = createFetch(options);\n\ttype API = InferClientRoutes<\n\t\tR extends { endpoints: Record<string, Endpoint> } ? R[\"endpoints\"] : R\n\t>;\n\ttype Options = API extends {\n\t\t[key: string]: infer T;\n\t}\n\t\t? T extends Endpoint\n\t\t\t? {\n\t\t\t\t\t[key in T[\"options\"][\"method\"] extends \"GET\"\n\t\t\t\t\t\t? T[\"path\"]\n\t\t\t\t\t\t: `@${T[\"options\"][\"method\"] extends string ? Lowercase<T[\"options\"][\"method\"]> : never}${T[\"path\"]}`]: T;\n\t\t\t\t}\n\t\t\t: {}\n\t\t: {};\n\n\ttype O = Prettify<UnionToIntersection<Options>>;\n\treturn async <OPT extends O, K extends keyof OPT, C extends InferContext<OPT[K]>>(\n\t\tpath: K,\n\t\t...options: HasRequired<C> extends true\n\t\t\t? [\n\t\t\t\t\tWithRequired<\n\t\t\t\t\t\tBetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t\t\t\t\t\tkeyof RequiredOptionKeys<C>\n\t\t\t\t\t>,\n\t\t\t\t]\n\t\t\t: [BetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>?]\n\t): Promise<\n\t\tBetterFetchResponse<Awaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>>\n\t> => {\n\t\treturn (await fetch(path as string, {\n\t\t\t...options[0],\n\t\t})) as any;\n\t};\n};\n\nexport * from \"./error\";\n"],"mappings":";;;;AAiFA,MAAa,gBAAwD,YAA2B;CAC/F,MAAM,QAAQ,YAAY,QAAQ;AAiBlC,QAAO,OACN,MACA,GAAGA,cAUC;AACJ,SAAQ,MAAM,MAAM,MAAgB,EACnC,GAAGA,UAAQ,IACX,CAAC"}
|
package/dist/context.cjs
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const require_error = require('./error.cjs');
|
|
2
|
+
const require_validator = require('./validator.cjs');
|
|
3
|
+
const require_crypto = require('./crypto.cjs');
|
|
4
|
+
const require_cookies = require('./cookies.cjs');
|
|
5
|
+
|
|
6
|
+
//#region src/context.ts
|
|
7
|
+
const createInternalContext = async (context, { options, path }) => {
|
|
8
|
+
const headers = new Headers();
|
|
9
|
+
let responseStatus = void 0;
|
|
10
|
+
const { data, error } = await require_validator.runValidation(options, context);
|
|
11
|
+
if (error) throw new require_error.ValidationError(error.message, error.issues);
|
|
12
|
+
const requestHeaders = "headers" in context ? context.headers instanceof Headers ? context.headers : new Headers(context.headers) : "request" in context && context.request instanceof Request ? context.request.headers : null;
|
|
13
|
+
const requestCookies = requestHeaders?.get("cookie");
|
|
14
|
+
const parsedCookies = requestCookies ? require_cookies.parseCookies(requestCookies) : void 0;
|
|
15
|
+
const internalContext = {
|
|
16
|
+
...context,
|
|
17
|
+
body: data.body,
|
|
18
|
+
query: data.query,
|
|
19
|
+
path: context.path || path || "virtual:",
|
|
20
|
+
context: "context" in context && context.context ? context.context : {},
|
|
21
|
+
returned: void 0,
|
|
22
|
+
headers: context?.headers,
|
|
23
|
+
request: context?.request,
|
|
24
|
+
params: "params" in context ? context.params : void 0,
|
|
25
|
+
method: context.method ?? (Array.isArray(options.method) ? options.method[0] : options.method === "*" ? "GET" : options.method),
|
|
26
|
+
setHeader: (key, value) => {
|
|
27
|
+
headers.set(key, value);
|
|
28
|
+
},
|
|
29
|
+
getHeader: (key) => {
|
|
30
|
+
if (!requestHeaders) return null;
|
|
31
|
+
return requestHeaders.get(key);
|
|
32
|
+
},
|
|
33
|
+
getCookie: (key, prefix) => {
|
|
34
|
+
const finalKey = require_cookies.getCookieKey(key, prefix);
|
|
35
|
+
if (!finalKey) return null;
|
|
36
|
+
return parsedCookies?.get(finalKey) || null;
|
|
37
|
+
},
|
|
38
|
+
getSignedCookie: async (key, secret, prefix) => {
|
|
39
|
+
const finalKey = require_cookies.getCookieKey(key, prefix);
|
|
40
|
+
if (!finalKey) return null;
|
|
41
|
+
const value = parsedCookies?.get(finalKey);
|
|
42
|
+
if (!value) return null;
|
|
43
|
+
const signatureStartPos = value.lastIndexOf(".");
|
|
44
|
+
if (signatureStartPos < 1) return null;
|
|
45
|
+
const signedValue = value.substring(0, signatureStartPos);
|
|
46
|
+
const signature = value.substring(signatureStartPos + 1);
|
|
47
|
+
if (signature.length !== 44 || !signature.endsWith("=")) return null;
|
|
48
|
+
return await require_crypto.verifySignature(signature, signedValue, await require_crypto.getCryptoKey(secret)) ? signedValue : false;
|
|
49
|
+
},
|
|
50
|
+
setCookie: (key, value, options$1) => {
|
|
51
|
+
const cookie = require_cookies.serializeCookie(key, value, options$1);
|
|
52
|
+
headers.append("set-cookie", cookie);
|
|
53
|
+
return cookie;
|
|
54
|
+
},
|
|
55
|
+
setSignedCookie: async (key, value, secret, options$1) => {
|
|
56
|
+
const cookie = await require_cookies.serializeSignedCookie(key, value, secret, options$1);
|
|
57
|
+
headers.append("set-cookie", cookie);
|
|
58
|
+
return cookie;
|
|
59
|
+
},
|
|
60
|
+
redirect: (url) => {
|
|
61
|
+
headers.set("location", url);
|
|
62
|
+
return new require_error.APIError("FOUND", void 0, headers);
|
|
63
|
+
},
|
|
64
|
+
error: (status, body, headers$1) => {
|
|
65
|
+
return new require_error.APIError(status, body, headers$1);
|
|
66
|
+
},
|
|
67
|
+
setStatus: (status) => {
|
|
68
|
+
responseStatus = status;
|
|
69
|
+
},
|
|
70
|
+
json: (json, routerResponse) => {
|
|
71
|
+
if (!context.asResponse) return json;
|
|
72
|
+
return {
|
|
73
|
+
body: routerResponse?.body || json,
|
|
74
|
+
routerResponse,
|
|
75
|
+
_flag: "json"
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
responseHeaders: headers,
|
|
79
|
+
get responseStatus() {
|
|
80
|
+
return responseStatus;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
for (const middleware of options.use || []) {
|
|
84
|
+
const response = await middleware({
|
|
85
|
+
...internalContext,
|
|
86
|
+
returnHeaders: true,
|
|
87
|
+
asResponse: false
|
|
88
|
+
});
|
|
89
|
+
if (response.response) Object.assign(internalContext.context, response.response);
|
|
90
|
+
/**
|
|
91
|
+
* Apply headers from the middleware to the endpoint headers
|
|
92
|
+
*/
|
|
93
|
+
if (response.headers) response.headers.forEach((value, key) => {
|
|
94
|
+
internalContext.responseHeaders.set(key, value);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return internalContext;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
//#endregion
|
|
101
|
+
exports.createInternalContext = createInternalContext;
|
|
102
|
+
//# sourceMappingURL=context.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.cjs","names":["responseStatus: Status | undefined","runValidation","ValidationError","requestHeaders: Headers | null","parseCookies","getCookieKey","verifySignature","getCryptoKey","serializeCookie","options","serializeSignedCookie","APIError","headers"],"sources":["../src/context.ts"],"sourcesContent":["import type { EndpointOptions } from \"./endpoint\";\nimport { type statusCodes, APIError, ValidationError, type Status } from \"./error\";\nimport type {\n\tInferParamPath,\n\tInferParamWildCard,\n\tIsEmptyObject,\n\tPrettify,\n\tUnionToIntersection,\n} from \"./helper\";\nimport type { Middleware, MiddlewareContext, MiddlewareOptions } from \"./middleware\";\nimport { runValidation } from \"./validator\";\nimport {\n\tgetCookieKey,\n\tparseCookies,\n\tserializeCookie,\n\tserializeSignedCookie,\n\ttype CookieOptions,\n\ttype CookiePrefixOptions,\n} from \"./cookies\";\nimport { getCryptoKey, verifySignature } from \"./crypto\";\nimport type { StandardSchemaV1 } from \"./standard-schema\";\n\nexport type HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\nexport type Method = HTTPMethod | \"*\";\n\nexport type InferBodyInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tBody = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer B;\n\t\t};\n\t}\n\t\t? B\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"body\"]>\n\t\t\t: undefined,\n> = undefined extends Body\n\t? {\n\t\t\tbody?: Body;\n\t\t}\n\t: {\n\t\t\tbody: Body;\n\t\t};\n\nexport type InferBody<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer Body;\n\t\t};\n\t}\n\t\t? Body\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"body\"]>\n\t\t\t: any;\n\nexport type InferQueryInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tQuery = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined,\n> = undefined extends Query\n\t? {\n\t\t\tquery?: Query;\n\t\t}\n\t: {\n\t\t\tquery: Query;\n\t\t};\n\nexport type InferQuery<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined;\n\nexport type InferMethod<Options extends EndpointOptions> = Options[\"method\"] extends Array<Method>\n\t? Options[\"method\"][number]\n\t: Options[\"method\"] extends \"*\"\n\t\t? HTTPMethod\n\t\t: Options[\"method\"];\n\nexport type InferInputMethod<\n\tOptions extends EndpointOptions,\n\tMethod = Options[\"method\"] extends Array<any>\n\t\t? Options[\"method\"][number] | undefined\n\t\t: Options[\"method\"] extends \"*\"\n\t\t\t? HTTPMethod\n\t\t\t: Options[\"method\"] | undefined,\n> = undefined extends Method\n\t? {\n\t\t\tmethod?: Method;\n\t\t}\n\t: {\n\t\t\tmethod: Method;\n\t\t};\n\nexport type InferParam<Path extends string> = [Path] extends [never]\n\t? Record<string, any> | undefined\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? Record<string, any> | undefined\n\t\t: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\nexport type InferParamInput<Path extends string> = [Path] extends [never]\n\t? { params?: Record<string, any> }\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? {\n\t\t\t\tparams?: Record<string, any>;\n\t\t\t}\n\t\t: {\n\t\t\t\tparams: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\t\t\t};\n\nexport type InferRequest<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true ? Request : Request | undefined;\n\nexport type InferRequestInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true\n\t\t? {\n\t\t\t\trequest: Request;\n\t\t\t}\n\t\t: {\n\t\t\t\trequest?: Request;\n\t\t\t};\n\nexport type InferHeaders<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true ? Headers : Headers | undefined;\n\nexport type InferHeadersInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true\n\t\t? {\n\t\t\t\theaders: HeadersInit;\n\t\t\t}\n\t\t: {\n\t\t\t\theaders?: HeadersInit;\n\t\t\t};\n\nexport type InferUse<Opts extends EndpointOptions[\"use\"]> = Opts extends Middleware[]\n\t? UnionToIntersection<Awaited<ReturnType<Opts[number]>>>\n\t: {};\n\nexport type InferMiddlewareBody<Options extends MiddlewareOptions> =\n\tOptions[\"body\"] extends StandardSchemaV1<infer T> ? T : any;\n\nexport type InferMiddlewareQuery<Options extends MiddlewareOptions> =\n\tOptions[\"query\"] extends StandardSchemaV1<infer T> ? T : Record<string, any> | undefined;\n\nexport type InputContext<\n\tPath extends string,\n\tOptions extends EndpointOptions,\n> = InferBodyInput<Options> &\n\tInferInputMethod<Options> &\n\tInferQueryInput<Options> &\n\tInferParamInput<Path> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\treturnStatus?: boolean;\n\t\tuse?: Middleware[];\n\t\tpath?: string;\n\t};\n\nexport const createInternalContext = async (\n\tcontext: InputContext<any, any>,\n\t{\n\t\toptions,\n\t\tpath,\n\t}: {\n\t\toptions: EndpointOptions;\n\t\tpath?: string;\n\t},\n) => {\n\tconst headers = new Headers();\n\tlet responseStatus: Status | undefined = undefined;\n\n\tconst { data, error } = await runValidation(options, context);\n\tif (error) {\n\t\tthrow new ValidationError(error.message, error.issues);\n\t}\n\tconst requestHeaders: Headers | null =\n\t\t\"headers\" in context\n\t\t\t? context.headers instanceof Headers\n\t\t\t\t? context.headers\n\t\t\t\t: new Headers(context.headers)\n\t\t\t: \"request\" in context && context.request instanceof Request\n\t\t\t\t? context.request.headers\n\t\t\t\t: null;\n\tconst requestCookies = requestHeaders?.get(\"cookie\");\n\tconst parsedCookies = requestCookies ? parseCookies(requestCookies) : undefined;\n\n\tconst internalContext = {\n\t\t...context,\n\t\tbody: data.body,\n\t\tquery: data.query,\n\t\tpath: context.path || path || \"virtual:\",\n\t\tcontext: \"context\" in context && context.context ? context.context : {},\n\t\treturned: undefined as any,\n\t\theaders: context?.headers,\n\t\trequest: context?.request,\n\t\tparams: \"params\" in context ? context.params : undefined,\n\t\tmethod:\n\t\t\tcontext.method ??\n\t\t\t(Array.isArray(options.method)\n\t\t\t\t? options.method[0]\n\t\t\t\t: options.method === \"*\"\n\t\t\t\t\t? \"GET\"\n\t\t\t\t\t: options.method),\n\t\tsetHeader: (key: string, value: string) => {\n\t\t\theaders.set(key, value);\n\t\t},\n\t\tgetHeader: (key: string) => {\n\t\t\tif (!requestHeaders) return null;\n\t\t\treturn requestHeaders.get(key);\n\t\t},\n\t\tgetCookie: (key: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn parsedCookies?.get(finalKey) || null;\n\t\t},\n\t\tgetSignedCookie: async (key: string, secret: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst value = parsedCookies?.get(finalKey);\n\t\t\tif (!value) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signatureStartPos = value.lastIndexOf(\".\");\n\t\t\tif (signatureStartPos < 1) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signedValue = value.substring(0, signatureStartPos);\n\t\t\tconst signature = value.substring(signatureStartPos + 1);\n\t\t\tif (signature.length !== 44 || !signature.endsWith(\"=\")) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst secretKey = await getCryptoKey(secret);\n\t\t\tconst isVerified = await verifySignature(signature, signedValue, secretKey);\n\t\t\treturn isVerified ? signedValue : false;\n\t\t},\n\t\tsetCookie: (key: string, value: string, options?: CookieOptions) => {\n\t\t\tconst cookie = serializeCookie(key, value, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tsetSignedCookie: async (\n\t\t\tkey: string,\n\t\t\tvalue: string,\n\t\t\tsecret: string,\n\t\t\toptions?: CookieOptions,\n\t\t) => {\n\t\t\tconst cookie = await serializeSignedCookie(key, value, secret, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tredirect: (url: string) => {\n\t\t\theaders.set(\"location\", url);\n\t\t\treturn new APIError(\"FOUND\", undefined, headers);\n\t\t},\n\t\terror: (\n\t\t\tstatus: keyof typeof statusCodes | Status,\n\t\t\tbody?:\n\t\t\t\t| {\n\t\t\t\t\t\tmessage?: string;\n\t\t\t\t\t\tcode?: string;\n\t\t\t\t }\n\t\t\t\t| undefined,\n\t\t\theaders?: HeadersInit,\n\t\t) => {\n\t\t\treturn new APIError(status, body, headers);\n\t\t},\n\t\tsetStatus: (status: Status) => {\n\t\t\tresponseStatus = status;\n\t\t},\n\t\tjson: (\n\t\t\tjson: Record<string, any>,\n\t\t\trouterResponse?:\n\t\t\t\t| {\n\t\t\t\t\t\tstatus?: number;\n\t\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\t\tresponse?: Response;\n\t\t\t\t\t\tbody?: Record<string, any>;\n\t\t\t\t }\n\t\t\t\t| Response,\n\t\t) => {\n\t\t\tif (!context.asResponse) {\n\t\t\t\treturn json;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbody: routerResponse?.body || json,\n\t\t\t\trouterResponse,\n\t\t\t\t_flag: \"json\",\n\t\t\t};\n\t\t},\n\t\tresponseHeaders: headers,\n\t\tget responseStatus() {\n\t\t\treturn responseStatus;\n\t\t},\n\t};\n\t//if context was shimmed through the input we want to apply it\n\tfor (const middleware of options.use || []) {\n\t\tconst response = (await middleware({\n\t\t\t...internalContext,\n\t\t\treturnHeaders: true,\n\t\t\tasResponse: false,\n\t\t})) as {\n\t\t\tresponse?: any;\n\t\t\theaders?: Headers;\n\t\t};\n\t\tif (response.response) {\n\t\t\tObject.assign(internalContext.context, response.response);\n\t\t}\n\t\t/**\n\t\t * Apply headers from the middleware to the endpoint headers\n\t\t */\n\t\tif (response.headers) {\n\t\t\tresponse.headers.forEach((value, key) => {\n\t\t\t\tinternalContext.responseHeaders.set(key, value);\n\t\t\t});\n\t\t}\n\t}\n\treturn internalContext;\n};\n"],"mappings":"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"}
|