better-call 0.3.3 → 1.0.0-beta.3
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/client.cjs.map +1 -1
- package/dist/client.d.cts +4 -4
- package/dist/client.d.ts +4 -4
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +785 -865
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -125
- package/dist/index.d.ts +4 -125
- package/dist/index.js +771 -855
- 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 +14 -0
- package/dist/node.d.ts +14 -0
- package/dist/node.js +147 -0
- package/dist/node.js.map +1 -0
- package/dist/router-DNpkEV0c.d.cts +1209 -0
- package/dist/router-DNpkEV0c.d.ts +1209 -0
- package/package.json +30 -15
- package/dist/router-DtwxtvxY.d.cts +0 -426
- package/dist/router-DtwxtvxY.d.ts +0 -426
package/dist/index.js
CHANGED
|
@@ -1,250 +1,216 @@
|
|
|
1
|
-
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
// src/error.ts
|
|
2
|
+
var _statusCode = {
|
|
3
|
+
OK: 200,
|
|
4
|
+
CREATED: 201,
|
|
5
|
+
ACCEPTED: 202,
|
|
6
|
+
NO_CONTENT: 204,
|
|
7
|
+
MULTIPLE_CHOICES: 300,
|
|
8
|
+
MOVED_PERMANENTLY: 301,
|
|
9
|
+
FOUND: 302,
|
|
10
|
+
SEE_OTHER: 303,
|
|
11
|
+
NOT_MODIFIED: 304,
|
|
12
|
+
TEMPORARY_REDIRECT: 307,
|
|
13
|
+
BAD_REQUEST: 400,
|
|
14
|
+
UNAUTHORIZED: 401,
|
|
15
|
+
PAYMENT_REQUIRED: 402,
|
|
16
|
+
FORBIDDEN: 403,
|
|
17
|
+
NOT_FOUND: 404,
|
|
18
|
+
METHOD_NOT_ALLOWED: 405,
|
|
19
|
+
NOT_ACCEPTABLE: 406,
|
|
20
|
+
PROXY_AUTHENTICATION_REQUIRED: 407,
|
|
21
|
+
REQUEST_TIMEOUT: 408,
|
|
22
|
+
CONFLICT: 409,
|
|
23
|
+
GONE: 410,
|
|
24
|
+
LENGTH_REQUIRED: 411,
|
|
25
|
+
PRECONDITION_FAILED: 412,
|
|
26
|
+
PAYLOAD_TOO_LARGE: 413,
|
|
27
|
+
URI_TOO_LONG: 414,
|
|
28
|
+
UNSUPPORTED_MEDIA_TYPE: 415,
|
|
29
|
+
RANGE_NOT_SATISFIABLE: 416,
|
|
30
|
+
EXPECTATION_FAILED: 417,
|
|
31
|
+
"I'M_A_TEAPOT": 418,
|
|
32
|
+
MISDIRECTED_REQUEST: 421,
|
|
33
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
34
|
+
LOCKED: 423,
|
|
35
|
+
FAILED_DEPENDENCY: 424,
|
|
36
|
+
TOO_EARLY: 425,
|
|
37
|
+
UPGRADE_REQUIRED: 426,
|
|
38
|
+
PRECONDITION_REQUIRED: 428,
|
|
39
|
+
TOO_MANY_REQUESTS: 429,
|
|
40
|
+
REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
|
|
41
|
+
UNAVAILABLE_FOR_LEGAL_REASONS: 451,
|
|
42
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
43
|
+
NOT_IMPLEMENTED: 501,
|
|
44
|
+
BAD_GATEWAY: 502,
|
|
45
|
+
SERVICE_UNAVAILABLE: 503,
|
|
46
|
+
GATEWAY_TIMEOUT: 504,
|
|
47
|
+
HTTP_VERSION_NOT_SUPPORTED: 505,
|
|
48
|
+
VARIANT_ALSO_NEGOTIATES: 506,
|
|
49
|
+
INSUFFICIENT_STORAGE: 507,
|
|
50
|
+
LOOP_DETECTED: 508,
|
|
51
|
+
NOT_EXTENDED: 510,
|
|
52
|
+
NETWORK_AUTHENTICATION_REQUIRED: 511
|
|
10
53
|
};
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
54
|
+
var APIError = class extends Error {
|
|
55
|
+
constructor(status = "INTERNAL_SERVER_ERROR", body = void 0, headers = {}, statusCode = typeof status === "number" ? status : _statusCode[status]) {
|
|
56
|
+
super(body?.message);
|
|
57
|
+
this.status = status;
|
|
58
|
+
this.body = body;
|
|
59
|
+
this.headers = headers;
|
|
60
|
+
this.statusCode = statusCode;
|
|
61
|
+
this.name = "APIError";
|
|
62
|
+
this.status = status;
|
|
63
|
+
this.headers = headers;
|
|
64
|
+
this.statusCode = statusCode;
|
|
65
|
+
this.body = body ? {
|
|
66
|
+
code: body?.message?.toUpperCase().replace(/ /g, "_").replace(/[^A-Z0-9_]/g, ""),
|
|
67
|
+
...body
|
|
68
|
+
} : void 0;
|
|
69
|
+
this.stack = "";
|
|
16
70
|
}
|
|
17
|
-
return to;
|
|
18
71
|
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
28
72
|
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
var cookie = {
|
|
57
|
-
name,
|
|
58
|
-
value
|
|
59
|
-
};
|
|
60
|
-
parts.forEach(function(part) {
|
|
61
|
-
var sides = part.split("=");
|
|
62
|
-
var key = sides.shift().trimLeft().toLowerCase();
|
|
63
|
-
var value2 = sides.join("=");
|
|
64
|
-
if (key === "expires") {
|
|
65
|
-
cookie.expires = new Date(value2);
|
|
66
|
-
} else if (key === "max-age") {
|
|
67
|
-
cookie.maxAge = parseInt(value2, 10);
|
|
68
|
-
} else if (key === "secure") {
|
|
69
|
-
cookie.secure = true;
|
|
70
|
-
} else if (key === "httponly") {
|
|
71
|
-
cookie.httpOnly = true;
|
|
72
|
-
} else if (key === "samesite") {
|
|
73
|
-
cookie.sameSite = value2;
|
|
74
|
-
} else if (key === "partitioned") {
|
|
75
|
-
cookie.partitioned = true;
|
|
76
|
-
} else {
|
|
77
|
-
cookie[key] = value2;
|
|
78
|
-
}
|
|
73
|
+
// src/to-response.ts
|
|
74
|
+
function isJSONSerializable(value) {
|
|
75
|
+
if (value === void 0) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const t = typeof value;
|
|
79
|
+
if (t === "string" || t === "number" || t === "boolean" || t === null) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
if (t !== "object") {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
if (Array.isArray(value)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
if (value.buffer) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function";
|
|
92
|
+
}
|
|
93
|
+
function toResponse(data, init) {
|
|
94
|
+
if (data instanceof Response) {
|
|
95
|
+
if (init?.headers instanceof Headers) {
|
|
96
|
+
init.headers.forEach((value, key) => {
|
|
97
|
+
data.headers.set(key, value);
|
|
79
98
|
});
|
|
80
|
-
return cookie;
|
|
81
99
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
value = nameValueArr.join("=");
|
|
89
|
-
} else {
|
|
90
|
-
value = nameValuePairStr;
|
|
91
|
-
}
|
|
92
|
-
return { name, value };
|
|
93
|
-
}
|
|
94
|
-
function parse2(input, options) {
|
|
95
|
-
options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions;
|
|
96
|
-
if (!input) {
|
|
97
|
-
if (!options.map) {
|
|
98
|
-
return [];
|
|
99
|
-
} else {
|
|
100
|
-
return {};
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (input.headers) {
|
|
104
|
-
if (typeof input.headers.getSetCookie === "function") {
|
|
105
|
-
input = input.headers.getSetCookie();
|
|
106
|
-
} else if (input.headers["set-cookie"]) {
|
|
107
|
-
input = input.headers["set-cookie"];
|
|
108
|
-
} else {
|
|
109
|
-
var sch = input.headers[Object.keys(input.headers).find(function(key) {
|
|
110
|
-
return key.toLowerCase() === "set-cookie";
|
|
111
|
-
})];
|
|
112
|
-
if (!sch && input.headers.cookie && !options.silent) {
|
|
113
|
-
console.warn(
|
|
114
|
-
"Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning."
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
input = sch;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (!Array.isArray(input)) {
|
|
121
|
-
input = [input];
|
|
122
|
-
}
|
|
123
|
-
if (!options.map) {
|
|
124
|
-
return input.filter(isNonEmptyString).map(function(str) {
|
|
125
|
-
return parseString(str, options);
|
|
126
|
-
});
|
|
127
|
-
} else {
|
|
128
|
-
var cookies = {};
|
|
129
|
-
return input.filter(isNonEmptyString).reduce(function(cookies2, str) {
|
|
130
|
-
var cookie = parseString(str, options);
|
|
131
|
-
cookies2[cookie.name] = cookie;
|
|
132
|
-
return cookies2;
|
|
133
|
-
}, cookies);
|
|
134
|
-
}
|
|
100
|
+
return data;
|
|
101
|
+
}
|
|
102
|
+
if (data?._flag === "json") {
|
|
103
|
+
const routerResponse = data.routerResponse;
|
|
104
|
+
if (routerResponse instanceof Response) {
|
|
105
|
+
return routerResponse;
|
|
135
106
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
var nextStart;
|
|
149
|
-
var cookiesSeparatorFound;
|
|
150
|
-
function skipWhitespace() {
|
|
151
|
-
while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
|
|
152
|
-
pos += 1;
|
|
153
|
-
}
|
|
154
|
-
return pos < cookiesString.length;
|
|
155
|
-
}
|
|
156
|
-
function notSpecialChar() {
|
|
157
|
-
ch = cookiesString.charAt(pos);
|
|
158
|
-
return ch !== "=" && ch !== ";" && ch !== ",";
|
|
159
|
-
}
|
|
160
|
-
while (pos < cookiesString.length) {
|
|
161
|
-
start = pos;
|
|
162
|
-
cookiesSeparatorFound = false;
|
|
163
|
-
while (skipWhitespace()) {
|
|
164
|
-
ch = cookiesString.charAt(pos);
|
|
165
|
-
if (ch === ",") {
|
|
166
|
-
lastComma = pos;
|
|
167
|
-
pos += 1;
|
|
168
|
-
skipWhitespace();
|
|
169
|
-
nextStart = pos;
|
|
170
|
-
while (pos < cookiesString.length && notSpecialChar()) {
|
|
171
|
-
pos += 1;
|
|
172
|
-
}
|
|
173
|
-
if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") {
|
|
174
|
-
cookiesSeparatorFound = true;
|
|
175
|
-
pos = nextStart;
|
|
176
|
-
cookiesStrings.push(cookiesString.substring(start, lastComma));
|
|
177
|
-
start = pos;
|
|
178
|
-
} else {
|
|
179
|
-
pos = lastComma + 1;
|
|
180
|
-
}
|
|
181
|
-
} else {
|
|
182
|
-
pos += 1;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
if (!cookiesSeparatorFound || pos >= cookiesString.length) {
|
|
186
|
-
cookiesStrings.push(cookiesString.substring(start, cookiesString.length));
|
|
187
|
-
}
|
|
107
|
+
return toResponse(data.body, {
|
|
108
|
+
headers: data.headers,
|
|
109
|
+
status: data.status
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (data instanceof APIError) {
|
|
113
|
+
return toResponse(data.body, {
|
|
114
|
+
status: data.statusCode,
|
|
115
|
+
statusText: data.status.toString(),
|
|
116
|
+
headers: {
|
|
117
|
+
...data.headers instanceof Headers ? Object.fromEntries(data.headers.entries()) : data?.headers,
|
|
118
|
+
...init?.headers instanceof Headers ? Object.fromEntries(init.headers.entries()) : init?.headers
|
|
188
119
|
}
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
module.exports = parse2;
|
|
192
|
-
module.exports.parse = parse2;
|
|
193
|
-
module.exports.parseString = parseString;
|
|
194
|
-
module.exports.splitCookiesString = splitCookiesString2;
|
|
120
|
+
});
|
|
195
121
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
122
|
+
let body = data;
|
|
123
|
+
let headers = new Headers(init?.headers);
|
|
124
|
+
if (!data) {
|
|
125
|
+
headers.set("content-type", "application/json");
|
|
126
|
+
} else if (typeof data === "string") {
|
|
127
|
+
body = data;
|
|
128
|
+
headers.set("Content-Type", "text/plain");
|
|
129
|
+
} else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
|
|
130
|
+
body = data;
|
|
131
|
+
headers.set("Content-Type", "application/octet-stream");
|
|
132
|
+
} else if (data instanceof Blob) {
|
|
133
|
+
body = data;
|
|
134
|
+
headers.set("Content-Type", data.type || "application/octet-stream");
|
|
135
|
+
} else if (data instanceof FormData) {
|
|
136
|
+
body = data;
|
|
137
|
+
} else if (data instanceof URLSearchParams) {
|
|
138
|
+
body = data;
|
|
139
|
+
headers.set("Content-Type", "application/x-www-form-urlencoded");
|
|
140
|
+
} else if (data instanceof ReadableStream) {
|
|
141
|
+
body = data;
|
|
142
|
+
headers.set("Content-Type", "application/octet-stream");
|
|
143
|
+
} else if (isJSONSerializable(data)) {
|
|
144
|
+
body = JSON.stringify(data);
|
|
145
|
+
headers.set("Content-Type", "application/json");
|
|
146
|
+
}
|
|
147
|
+
return new Response(body, {
|
|
148
|
+
...init,
|
|
149
|
+
headers
|
|
150
|
+
});
|
|
151
|
+
}
|
|
200
152
|
|
|
201
|
-
// src/
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
this.headers = headers ?? new Headers();
|
|
215
|
-
if (!this.headers.has("Content-Type")) {
|
|
216
|
-
this.headers.set("Content-Type", "application/json");
|
|
153
|
+
// src/validator.ts
|
|
154
|
+
async function runValidation(options, context = {}) {
|
|
155
|
+
let request = {
|
|
156
|
+
body: context.body,
|
|
157
|
+
query: context.query
|
|
158
|
+
};
|
|
159
|
+
if (options.body) {
|
|
160
|
+
const result = await options.body["~standard"].validate(context.body);
|
|
161
|
+
if (result.issues) {
|
|
162
|
+
return {
|
|
163
|
+
data: null,
|
|
164
|
+
error: fromError(result.issues, "body")
|
|
165
|
+
};
|
|
217
166
|
}
|
|
218
|
-
|
|
167
|
+
request.body = result.value;
|
|
168
|
+
}
|
|
169
|
+
if (options.query) {
|
|
170
|
+
const result = await options.query["~standard"].validate(context.query);
|
|
171
|
+
if (result.issues) {
|
|
172
|
+
return {
|
|
173
|
+
data: null,
|
|
174
|
+
error: fromError(result.issues, "query")
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
request.query = result.value;
|
|
178
|
+
}
|
|
179
|
+
if (options.requireHeaders && !context.headers) {
|
|
180
|
+
return {
|
|
181
|
+
data: null,
|
|
182
|
+
error: { message: "Headers is required" }
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (options.requireRequest && !context.request) {
|
|
186
|
+
return {
|
|
187
|
+
data: null,
|
|
188
|
+
error: { message: "Request is required" }
|
|
189
|
+
};
|
|
219
190
|
}
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
// src/helper.ts
|
|
223
|
-
var json = (body, option) => {
|
|
224
191
|
return {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
status: option?.status ?? 200,
|
|
228
|
-
statusText: option?.statusText ?? "OK",
|
|
229
|
-
headers: option?.headers
|
|
230
|
-
},
|
|
231
|
-
body,
|
|
232
|
-
_flag: "json"
|
|
192
|
+
data: request,
|
|
193
|
+
error: null
|
|
233
194
|
};
|
|
234
|
-
}
|
|
195
|
+
}
|
|
196
|
+
function fromError(error, validating) {
|
|
197
|
+
const errorMessages = [];
|
|
198
|
+
for (const issue of error) {
|
|
199
|
+
const message = issue.message;
|
|
200
|
+
errorMessages.push(message);
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
message: `Invalid ${validating} parameters`
|
|
204
|
+
};
|
|
205
|
+
}
|
|
235
206
|
|
|
236
|
-
// src/
|
|
207
|
+
// src/crypto.ts
|
|
237
208
|
import { subtle } from "uncrypto";
|
|
238
209
|
var algorithm = { name: "HMAC", hash: "SHA-256" };
|
|
239
210
|
var getCryptoKey = async (secret) => {
|
|
240
211
|
const secretBuf = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
|
|
241
212
|
return await subtle.importKey("raw", secretBuf, algorithm, false, ["sign", "verify"]);
|
|
242
213
|
};
|
|
243
|
-
var makeSignature = async (value, secret) => {
|
|
244
|
-
const key = await getCryptoKey(secret);
|
|
245
|
-
const signature = await subtle.sign(algorithm.name, key, new TextEncoder().encode(value));
|
|
246
|
-
return btoa(String.fromCharCode(...new Uint8Array(signature)));
|
|
247
|
-
};
|
|
248
214
|
var verifySignature = async (base64Signature, value, secret) => {
|
|
249
215
|
try {
|
|
250
216
|
const signatureBinStr = atob(base64Signature);
|
|
@@ -257,54 +223,54 @@ var verifySignature = async (base64Signature, value, secret) => {
|
|
|
257
223
|
return false;
|
|
258
224
|
}
|
|
259
225
|
};
|
|
260
|
-
var
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return pairs.reduce((parsedCookie, pairStr) => {
|
|
265
|
-
pairStr = pairStr.trim();
|
|
266
|
-
const valueStartPos = pairStr.indexOf("=");
|
|
267
|
-
if (valueStartPos === -1) {
|
|
268
|
-
return parsedCookie;
|
|
269
|
-
}
|
|
270
|
-
const cookieName = pairStr.substring(0, valueStartPos).trim();
|
|
271
|
-
if (name && name !== cookieName || !validCookieNameRegEx.test(cookieName)) {
|
|
272
|
-
return parsedCookie;
|
|
273
|
-
}
|
|
274
|
-
let cookieValue = pairStr.substring(valueStartPos + 1).trim();
|
|
275
|
-
if (cookieValue.startsWith('"') && cookieValue.endsWith('"')) {
|
|
276
|
-
cookieValue = cookieValue.slice(1, -1);
|
|
277
|
-
}
|
|
278
|
-
if (validCookieValueRegEx.test(cookieValue)) {
|
|
279
|
-
parsedCookie[cookieName] = decodeURIComponent(cookieValue);
|
|
280
|
-
}
|
|
281
|
-
return parsedCookie;
|
|
282
|
-
}, {});
|
|
226
|
+
var makeSignature = async (value, secret) => {
|
|
227
|
+
const key = await getCryptoKey(secret);
|
|
228
|
+
const signature = await subtle.sign(algorithm.name, key, new TextEncoder().encode(value));
|
|
229
|
+
return btoa(String.fromCharCode(...new Uint8Array(signature)));
|
|
283
230
|
};
|
|
284
|
-
var
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
231
|
+
var signCookieValue = async (value, secret) => {
|
|
232
|
+
const signature = await makeSignature(value, secret);
|
|
233
|
+
value = `${value}.${signature}`;
|
|
234
|
+
value = encodeURIComponent(value);
|
|
235
|
+
return value;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// src/cookies.ts
|
|
239
|
+
var getCookieKey = (key, prefix) => {
|
|
240
|
+
let finalKey = key;
|
|
241
|
+
if (prefix) {
|
|
242
|
+
if (prefix === "secure") {
|
|
243
|
+
finalKey = "__Secure-" + key;
|
|
244
|
+
} else if (prefix === "host") {
|
|
245
|
+
finalKey = "__Host-" + key;
|
|
246
|
+
} else {
|
|
247
|
+
return void 0;
|
|
296
248
|
}
|
|
297
|
-
const isVerified = await verifySignature(signature, signedValue, secretKey);
|
|
298
|
-
parsedCookie[key] = isVerified ? signedValue : false;
|
|
299
249
|
}
|
|
300
|
-
return
|
|
250
|
+
return finalKey;
|
|
301
251
|
};
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
252
|
+
function parseCookies(cookieHeader) {
|
|
253
|
+
const cookies = cookieHeader.split(";");
|
|
254
|
+
const cookieMap = /* @__PURE__ */ new Map();
|
|
255
|
+
cookies.forEach((cookie) => {
|
|
256
|
+
const [name, value] = cookie.trim().split("=");
|
|
257
|
+
cookieMap.set(name, decodeURIComponent(value));
|
|
258
|
+
});
|
|
259
|
+
return cookieMap;
|
|
260
|
+
}
|
|
261
|
+
var _serialize = (key, value, opt = {}) => {
|
|
262
|
+
let cookie;
|
|
263
|
+
if (opt?.prefix === "secure") {
|
|
264
|
+
cookie = `${`__Secure-${key}`}=${value}`;
|
|
265
|
+
} else if (opt?.prefix === "host") {
|
|
266
|
+
cookie = `${`__Host-${key}`}=${value}`;
|
|
267
|
+
} else {
|
|
268
|
+
cookie = `${key}=${value}`;
|
|
269
|
+
}
|
|
270
|
+
if (key.startsWith("__Secure-") && !opt.secure) {
|
|
305
271
|
opt.secure = true;
|
|
306
272
|
}
|
|
307
|
-
if (
|
|
273
|
+
if (key.startsWith("__Host-")) {
|
|
308
274
|
if (!opt.secure) {
|
|
309
275
|
opt.secure = true;
|
|
310
276
|
}
|
|
@@ -348,111 +314,209 @@ var _serialize = (name, value, opt = {}) => {
|
|
|
348
314
|
}
|
|
349
315
|
if (opt.partitioned) {
|
|
350
316
|
if (!opt.secure) {
|
|
351
|
-
|
|
317
|
+
opt.secure = true;
|
|
352
318
|
}
|
|
353
319
|
cookie += "; Partitioned";
|
|
354
320
|
}
|
|
355
321
|
return cookie;
|
|
356
322
|
};
|
|
357
|
-
var
|
|
323
|
+
var serializeCookie = (key, value, opt) => {
|
|
358
324
|
value = encodeURIComponent(value);
|
|
359
|
-
return _serialize(
|
|
325
|
+
return _serialize(key, value, opt);
|
|
360
326
|
};
|
|
361
|
-
var
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
value = encodeURIComponent(value);
|
|
365
|
-
return _serialize(name, value, opt);
|
|
366
|
-
};
|
|
367
|
-
var signCookieValue = async (value, secret) => {
|
|
368
|
-
const signature = await makeSignature(value, secret);
|
|
369
|
-
value = `${value}.${signature}`;
|
|
370
|
-
value = encodeURIComponent(value);
|
|
371
|
-
return value;
|
|
327
|
+
var serializeSignedCookie = async (key, value, secret, opt) => {
|
|
328
|
+
value = await signCookieValue(value, secret);
|
|
329
|
+
return _serialize(key, value, opt);
|
|
372
330
|
};
|
|
373
331
|
|
|
374
|
-
// src/
|
|
375
|
-
var
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
} else {
|
|
386
|
-
return void 0;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
const obj = parse(cookie, finalKey);
|
|
390
|
-
return obj[finalKey];
|
|
391
|
-
};
|
|
392
|
-
var setCookie = (header, name, value, opt) => {
|
|
393
|
-
const existingCookies = header.get("Set-Cookie");
|
|
394
|
-
if (existingCookies) {
|
|
395
|
-
const cookies = existingCookies.split(", ");
|
|
396
|
-
const updatedCookies = cookies.filter((cookie2) => !cookie2.startsWith(`${name}=`));
|
|
397
|
-
header.delete("Set-Cookie");
|
|
398
|
-
updatedCookies.forEach((cookie2) => header.append("Set-Cookie", cookie2));
|
|
399
|
-
}
|
|
400
|
-
let cookie;
|
|
401
|
-
if (opt?.prefix === "secure") {
|
|
402
|
-
cookie = serialize("__Secure-" + name, value, { path: "/", ...opt, secure: true });
|
|
403
|
-
} else if (opt?.prefix === "host") {
|
|
404
|
-
cookie = serialize("__Host-" + name, value, {
|
|
405
|
-
...opt,
|
|
406
|
-
path: "/",
|
|
407
|
-
secure: true,
|
|
408
|
-
domain: void 0
|
|
332
|
+
// src/context.ts
|
|
333
|
+
var createInternalContext = async (context, {
|
|
334
|
+
options,
|
|
335
|
+
path
|
|
336
|
+
}) => {
|
|
337
|
+
const headers = new Headers();
|
|
338
|
+
const { data, error } = await runValidation(options, context);
|
|
339
|
+
if (error) {
|
|
340
|
+
throw new APIError(400, {
|
|
341
|
+
message: error.message,
|
|
342
|
+
code: "VALIDATION_ERROR"
|
|
409
343
|
});
|
|
410
|
-
} else {
|
|
411
|
-
cookie = serialize(name, value, { path: "/", ...opt });
|
|
412
344
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
345
|
+
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;
|
|
346
|
+
const requestCookies = requestHeaders?.get("cookie");
|
|
347
|
+
const parsedCookies = requestCookies ? parseCookies(requestCookies) : void 0;
|
|
348
|
+
const internalContext = {
|
|
349
|
+
...context,
|
|
350
|
+
body: data.body,
|
|
351
|
+
query: data.query,
|
|
352
|
+
path: context.path || path,
|
|
353
|
+
context: "context" in context && context.context ? context.context : {},
|
|
354
|
+
returned: void 0,
|
|
355
|
+
headers: context?.headers,
|
|
356
|
+
request: context?.request,
|
|
357
|
+
params: "params" in context ? context.params : void 0,
|
|
358
|
+
method: context.method,
|
|
359
|
+
setHeader: (key, value) => {
|
|
360
|
+
headers.set(key, value);
|
|
361
|
+
},
|
|
362
|
+
getHeader: (key) => {
|
|
363
|
+
if (!requestHeaders) return null;
|
|
364
|
+
return requestHeaders.get(key);
|
|
365
|
+
},
|
|
366
|
+
getCookie: (key, prefix) => {
|
|
367
|
+
const finalKey = getCookieKey(key, prefix);
|
|
368
|
+
if (!finalKey) {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
return parsedCookies?.get(finalKey) || null;
|
|
372
|
+
},
|
|
373
|
+
getSignedCookie: async (key, secret, prefix) => {
|
|
374
|
+
const finalKey = getCookieKey(key, prefix);
|
|
375
|
+
if (!finalKey) {
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
const value = parsedCookies?.get(finalKey);
|
|
379
|
+
if (!value) {
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
const signatureStartPos = value.lastIndexOf(".");
|
|
383
|
+
if (signatureStartPos < 1) {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
const signedValue = value.substring(0, signatureStartPos);
|
|
387
|
+
const signature = value.substring(signatureStartPos + 1);
|
|
388
|
+
if (signature.length !== 44 || !signature.endsWith("=")) {
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
const secretKey = await getCryptoKey(secret);
|
|
392
|
+
const isVerified = await verifySignature(signature, signedValue, secretKey);
|
|
393
|
+
return isVerified ? signedValue : false;
|
|
394
|
+
},
|
|
395
|
+
setCookie: (key, value, options2) => {
|
|
396
|
+
const cookie = serializeCookie(key, value, options2);
|
|
397
|
+
headers.append("set-cookie", cookie);
|
|
398
|
+
return cookie;
|
|
399
|
+
},
|
|
400
|
+
setSignedCookie: async (key, value, secret, options2) => {
|
|
401
|
+
const cookie = await serializeSignedCookie(key, value, secret, options2);
|
|
402
|
+
headers.append("set-cookie", cookie);
|
|
403
|
+
return cookie;
|
|
404
|
+
},
|
|
405
|
+
redirect: (url) => {
|
|
406
|
+
headers.set("location", url);
|
|
407
|
+
return new APIError("FOUND", void 0, headers);
|
|
408
|
+
},
|
|
409
|
+
error: (status, body, headers2) => {
|
|
410
|
+
return new APIError(status, body, headers2);
|
|
411
|
+
},
|
|
412
|
+
json: (json, routerResponse) => {
|
|
413
|
+
if (!context.asResponse) {
|
|
414
|
+
return json;
|
|
415
|
+
}
|
|
416
|
+
return {
|
|
417
|
+
body: routerResponse?.body || json,
|
|
418
|
+
routerResponse,
|
|
419
|
+
_flag: "json"
|
|
420
|
+
};
|
|
421
|
+
},
|
|
422
|
+
responseHeaders: headers
|
|
423
|
+
};
|
|
424
|
+
for (const middleware of options.use || []) {
|
|
425
|
+
const response = await middleware({
|
|
426
|
+
...internalContext,
|
|
427
|
+
returnHeaders: true,
|
|
428
|
+
asResponse: false
|
|
429
429
|
});
|
|
430
|
-
|
|
431
|
-
|
|
430
|
+
if (response.response) {
|
|
431
|
+
Object.assign(internalContext.context, response.response);
|
|
432
|
+
}
|
|
433
|
+
if (response.headers) {
|
|
434
|
+
response.headers.forEach((value, key) => {
|
|
435
|
+
internalContext.responseHeaders.set(key, value);
|
|
436
|
+
});
|
|
437
|
+
}
|
|
432
438
|
}
|
|
433
|
-
|
|
439
|
+
return internalContext;
|
|
434
440
|
};
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
441
|
+
|
|
442
|
+
// src/middleware.ts
|
|
443
|
+
function createMiddleware(optionsOrHandler, handler) {
|
|
444
|
+
const internalHandler = async (inputCtx) => {
|
|
445
|
+
const context = inputCtx;
|
|
446
|
+
const _handler = typeof optionsOrHandler === "function" ? optionsOrHandler : handler;
|
|
447
|
+
const options = typeof optionsOrHandler === "function" ? {} : optionsOrHandler;
|
|
448
|
+
const internalContext = await createInternalContext(context, {
|
|
449
|
+
options,
|
|
450
|
+
path: "/"
|
|
451
|
+
});
|
|
452
|
+
if (!_handler) {
|
|
453
|
+
throw new Error("handler must be defined");
|
|
454
|
+
}
|
|
455
|
+
const response = await _handler(internalContext);
|
|
456
|
+
const headers = internalContext.responseHeaders;
|
|
457
|
+
return context.returnHeaders ? {
|
|
458
|
+
headers,
|
|
459
|
+
response
|
|
460
|
+
} : response;
|
|
461
|
+
};
|
|
462
|
+
internalHandler.options = typeof optionsOrHandler === "function" ? {} : optionsOrHandler;
|
|
463
|
+
return internalHandler;
|
|
464
|
+
}
|
|
465
|
+
createMiddleware.create = (opts) => {
|
|
466
|
+
function fn(optionsOrHandler, handler) {
|
|
467
|
+
if (typeof optionsOrHandler === "function") {
|
|
468
|
+
return createMiddleware(
|
|
469
|
+
{
|
|
470
|
+
use: opts?.use
|
|
471
|
+
},
|
|
472
|
+
optionsOrHandler
|
|
473
|
+
);
|
|
446
474
|
}
|
|
475
|
+
if (!handler) {
|
|
476
|
+
throw new Error("Middleware handler is required");
|
|
477
|
+
}
|
|
478
|
+
const middleware = createMiddleware(
|
|
479
|
+
{
|
|
480
|
+
...optionsOrHandler,
|
|
481
|
+
method: "*",
|
|
482
|
+
use: [...opts?.use || [], ...optionsOrHandler.use || []]
|
|
483
|
+
},
|
|
484
|
+
handler
|
|
485
|
+
);
|
|
486
|
+
return middleware;
|
|
447
487
|
}
|
|
448
|
-
|
|
449
|
-
return obj[finalKey];
|
|
488
|
+
return fn;
|
|
450
489
|
};
|
|
451
490
|
|
|
452
491
|
// src/endpoint.ts
|
|
453
|
-
|
|
492
|
+
var createEndpoint2 = (path, options, handler) => {
|
|
493
|
+
const internalHandler = async (...inputCtx) => {
|
|
494
|
+
const context = inputCtx[0] || {};
|
|
495
|
+
const internalContext = await createInternalContext(context, {
|
|
496
|
+
options,
|
|
497
|
+
path
|
|
498
|
+
});
|
|
499
|
+
const response = await handler(internalContext).catch((e) => {
|
|
500
|
+
if (e instanceof APIError && context.asResponse) {
|
|
501
|
+
return e;
|
|
502
|
+
}
|
|
503
|
+
throw e;
|
|
504
|
+
});
|
|
505
|
+
const headers = internalContext.responseHeaders;
|
|
506
|
+
return context.asResponse ? toResponse(response, {
|
|
507
|
+
headers
|
|
508
|
+
}) : context.returnHeaders ? {
|
|
509
|
+
headers,
|
|
510
|
+
response
|
|
511
|
+
} : response;
|
|
512
|
+
};
|
|
513
|
+
internalHandler.options = options;
|
|
514
|
+
internalHandler.path = path;
|
|
515
|
+
return internalHandler;
|
|
516
|
+
};
|
|
517
|
+
createEndpoint2.create = (opts) => {
|
|
454
518
|
return (path, options, handler) => {
|
|
455
|
-
return
|
|
519
|
+
return createEndpoint2(
|
|
456
520
|
path,
|
|
457
521
|
{
|
|
458
522
|
...options,
|
|
@@ -461,152 +525,300 @@ function createEndpointCreator(opts) {
|
|
|
461
525
|
handler
|
|
462
526
|
);
|
|
463
527
|
};
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// src/router.ts
|
|
531
|
+
import { createRouter as createRou3Router, addRoute, findRoute, findAllRoutes } from "rou3";
|
|
532
|
+
|
|
533
|
+
// src/openapi.ts
|
|
534
|
+
import { ZodObject, ZodOptional, ZodSchema } from "zod";
|
|
535
|
+
var paths = {};
|
|
536
|
+
function getTypeFromZodType(zodType) {
|
|
537
|
+
switch (zodType.constructor.name) {
|
|
538
|
+
case "ZodString":
|
|
539
|
+
return "string";
|
|
540
|
+
case "ZodNumber":
|
|
541
|
+
return "number";
|
|
542
|
+
case "ZodBoolean":
|
|
543
|
+
return "boolean";
|
|
544
|
+
case "ZodObject":
|
|
545
|
+
return "object";
|
|
546
|
+
case "ZodArray":
|
|
547
|
+
return "array";
|
|
548
|
+
default:
|
|
549
|
+
return "string";
|
|
550
|
+
}
|
|
464
551
|
}
|
|
465
|
-
function
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
552
|
+
function getParameters(options) {
|
|
553
|
+
const parameters = [];
|
|
554
|
+
if (options.metadata?.openAPI?.parameters) {
|
|
555
|
+
parameters.push(...options.metadata.openAPI.parameters);
|
|
556
|
+
return parameters;
|
|
557
|
+
}
|
|
558
|
+
if (options.query instanceof ZodObject) {
|
|
559
|
+
Object.entries(options.query.shape).forEach(([key, value]) => {
|
|
560
|
+
if (value instanceof ZodSchema) {
|
|
561
|
+
parameters.push({
|
|
562
|
+
name: key,
|
|
563
|
+
in: "query",
|
|
564
|
+
schema: {
|
|
565
|
+
type: getTypeFromZodType(value),
|
|
566
|
+
..."minLength" in value && value.minLength ? {
|
|
567
|
+
minLength: value.minLength
|
|
568
|
+
} : {},
|
|
569
|
+
description: value.description
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
return parameters;
|
|
576
|
+
}
|
|
577
|
+
function getRequestBody(options) {
|
|
578
|
+
if (options.metadata?.openAPI?.requestBody) {
|
|
579
|
+
return options.metadata.openAPI.requestBody;
|
|
580
|
+
}
|
|
581
|
+
if (!options.body) return void 0;
|
|
582
|
+
if (options.body instanceof ZodObject || options.body instanceof ZodOptional) {
|
|
583
|
+
const shape = options.body.shape;
|
|
584
|
+
if (!shape) return void 0;
|
|
585
|
+
const properties = {};
|
|
586
|
+
const required = [];
|
|
587
|
+
Object.entries(shape).forEach(([key, value]) => {
|
|
588
|
+
if (value instanceof ZodSchema) {
|
|
589
|
+
properties[key] = {
|
|
590
|
+
type: getTypeFromZodType(value),
|
|
591
|
+
description: value.description
|
|
592
|
+
};
|
|
593
|
+
if (!(value instanceof ZodOptional)) {
|
|
594
|
+
required.push(key);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
return {
|
|
599
|
+
required: options.body instanceof ZodOptional ? false : options.body ? true : false,
|
|
600
|
+
content: {
|
|
601
|
+
"application/json": {
|
|
602
|
+
schema: {
|
|
603
|
+
type: "object",
|
|
604
|
+
properties,
|
|
605
|
+
required
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
return void 0;
|
|
612
|
+
}
|
|
613
|
+
function getResponse(responses) {
|
|
614
|
+
return {
|
|
615
|
+
"400": {
|
|
616
|
+
content: {
|
|
617
|
+
"application/json": {
|
|
618
|
+
schema: {
|
|
619
|
+
type: "object",
|
|
620
|
+
properties: {
|
|
621
|
+
message: {
|
|
622
|
+
type: "string"
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
required: ["message"]
|
|
626
|
+
}
|
|
627
|
+
}
|
|
480
628
|
},
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
629
|
+
description: "Bad Request. Usually due to missing parameters, or invalid parameters."
|
|
630
|
+
},
|
|
631
|
+
"401": {
|
|
632
|
+
content: {
|
|
633
|
+
"application/json": {
|
|
634
|
+
schema: {
|
|
635
|
+
type: "object",
|
|
636
|
+
properties: {
|
|
637
|
+
message: {
|
|
638
|
+
type: "string"
|
|
639
|
+
}
|
|
640
|
+
},
|
|
641
|
+
required: ["message"]
|
|
642
|
+
}
|
|
485
643
|
}
|
|
486
|
-
const cookie = getSignedCookie(header, secret, key, prefix);
|
|
487
|
-
return cookie;
|
|
488
644
|
},
|
|
489
|
-
|
|
490
|
-
|
|
645
|
+
description: "Unauthorized. Due to missing or invalid authentication."
|
|
646
|
+
},
|
|
647
|
+
"403": {
|
|
648
|
+
content: {
|
|
649
|
+
"application/json": {
|
|
650
|
+
schema: {
|
|
651
|
+
type: "object",
|
|
652
|
+
properties: {
|
|
653
|
+
message: {
|
|
654
|
+
type: "string"
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
491
659
|
},
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
660
|
+
description: "Forbidden. You do not have permission to access this resource or to perform this action."
|
|
661
|
+
},
|
|
662
|
+
"404": {
|
|
663
|
+
content: {
|
|
664
|
+
"application/json": {
|
|
665
|
+
schema: {
|
|
666
|
+
type: "object",
|
|
667
|
+
properties: {
|
|
668
|
+
message: {
|
|
669
|
+
type: "string"
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
495
674
|
},
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
middleware
|
|
510
|
-
});
|
|
511
|
-
continue;
|
|
675
|
+
description: "Not Found. The requested resource was not found."
|
|
676
|
+
},
|
|
677
|
+
"429": {
|
|
678
|
+
content: {
|
|
679
|
+
"application/json": {
|
|
680
|
+
schema: {
|
|
681
|
+
type: "object",
|
|
682
|
+
properties: {
|
|
683
|
+
message: {
|
|
684
|
+
type: "string"
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
512
688
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
689
|
+
},
|
|
690
|
+
description: "Too Many Requests. You have exceeded the rate limit. Try again later."
|
|
691
|
+
},
|
|
692
|
+
"500": {
|
|
693
|
+
content: {
|
|
694
|
+
"application/json": {
|
|
695
|
+
schema: {
|
|
696
|
+
type: "object",
|
|
697
|
+
properties: {
|
|
698
|
+
message: {
|
|
699
|
+
type: "string"
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
524
703
|
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
704
|
+
},
|
|
705
|
+
description: "Internal Server Error. This is a problem with the server that you cannot fix."
|
|
706
|
+
},
|
|
707
|
+
...responses
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
async function generator(endpoints, config) {
|
|
711
|
+
const components = {
|
|
712
|
+
schemas: {}
|
|
713
|
+
};
|
|
714
|
+
Object.entries(endpoints).forEach(([_, value]) => {
|
|
715
|
+
const options = value.options;
|
|
716
|
+
if (options.metadata?.SERVER_ONLY) return;
|
|
717
|
+
if (options.method === "GET") {
|
|
718
|
+
paths[value.path] = {
|
|
719
|
+
get: {
|
|
720
|
+
tags: ["Default", ...options.metadata?.openAPI?.tags || []],
|
|
721
|
+
description: options.metadata?.openAPI?.description,
|
|
722
|
+
operationId: options.metadata?.openAPI?.operationId,
|
|
723
|
+
security: [
|
|
724
|
+
{
|
|
725
|
+
bearerAuth: []
|
|
726
|
+
}
|
|
727
|
+
],
|
|
728
|
+
parameters: getParameters(options),
|
|
729
|
+
responses: getResponse(options.metadata?.openAPI?.responses)
|
|
535
730
|
}
|
|
536
731
|
};
|
|
537
732
|
}
|
|
538
|
-
|
|
539
|
-
const body = options
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
733
|
+
if (options.method === "POST") {
|
|
734
|
+
const body = getRequestBody(options);
|
|
735
|
+
paths[value.path] = {
|
|
736
|
+
post: {
|
|
737
|
+
tags: ["Default", ...options.metadata?.openAPI?.tags || []],
|
|
738
|
+
description: options.metadata?.openAPI?.description,
|
|
739
|
+
operationId: options.metadata?.openAPI?.operationId,
|
|
740
|
+
security: [
|
|
741
|
+
{
|
|
742
|
+
bearerAuth: []
|
|
743
|
+
}
|
|
744
|
+
],
|
|
745
|
+
parameters: getParameters(options),
|
|
746
|
+
...body ? { requestBody: body } : {
|
|
747
|
+
requestBody: {
|
|
748
|
+
//set body none
|
|
749
|
+
content: {
|
|
750
|
+
"application/json": {
|
|
751
|
+
schema: {
|
|
752
|
+
type: "object",
|
|
753
|
+
properties: {}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
},
|
|
759
|
+
responses: getResponse(options.metadata?.openAPI?.responses)
|
|
760
|
+
}
|
|
546
761
|
};
|
|
547
|
-
internalCtx.query = options.query ? options.query.parse(internalCtx.query) : internalCtx.query;
|
|
548
|
-
} catch (e) {
|
|
549
|
-
if (e instanceof ZodError) {
|
|
550
|
-
throw new APIError("BAD_REQUEST", {
|
|
551
|
-
message: e.message,
|
|
552
|
-
details: e.errors
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
throw e;
|
|
556
|
-
}
|
|
557
|
-
if (options.requireHeaders && !internalCtx.headers) {
|
|
558
|
-
throw new APIError("BAD_REQUEST", {
|
|
559
|
-
message: "Headers are required"
|
|
560
|
-
});
|
|
561
762
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
if (res._flag === "json" && internalCtx._flag === "router") {
|
|
575
|
-
const h = res.response.headers;
|
|
576
|
-
Object.keys(h || {}).forEach((key) => {
|
|
577
|
-
responseHeader.set(key, h[key]);
|
|
578
|
-
});
|
|
579
|
-
responseHeader.set("Content-Type", "application/json");
|
|
580
|
-
actualResponse = new Response(JSON.stringify(res.response.body), {
|
|
581
|
-
status: res.response.status ?? 200,
|
|
582
|
-
statusText: res.response.statusText,
|
|
583
|
-
headers: responseHeader
|
|
584
|
-
});
|
|
585
|
-
} else {
|
|
586
|
-
actualResponse = res.body;
|
|
587
|
-
}
|
|
763
|
+
});
|
|
764
|
+
const res = {
|
|
765
|
+
openapi: "3.1.1",
|
|
766
|
+
info: {
|
|
767
|
+
title: "Better Auth",
|
|
768
|
+
description: "API Reference for your Better Auth Instance",
|
|
769
|
+
version: "1.1.0"
|
|
770
|
+
},
|
|
771
|
+
components,
|
|
772
|
+
security: [
|
|
773
|
+
{
|
|
774
|
+
apiKeyCookie: []
|
|
588
775
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
responseHeader.set("Content-Type", "application/json");
|
|
594
|
-
e.headers = responseHeader;
|
|
595
|
-
responseHeader = new Headers();
|
|
596
|
-
throw e;
|
|
776
|
+
],
|
|
777
|
+
servers: [
|
|
778
|
+
{
|
|
779
|
+
url: config?.url
|
|
597
780
|
}
|
|
598
|
-
|
|
599
|
-
|
|
781
|
+
],
|
|
782
|
+
tags: [
|
|
783
|
+
{
|
|
784
|
+
name: "Default",
|
|
785
|
+
description: "Default endpoints that are included with Better Auth by default. These endpoints are not part of any plugin."
|
|
786
|
+
}
|
|
787
|
+
],
|
|
788
|
+
paths
|
|
600
789
|
};
|
|
601
|
-
|
|
602
|
-
handle.options = options;
|
|
603
|
-
handle.method = options.method;
|
|
604
|
-
handle.headers = responseHeader;
|
|
605
|
-
return handle;
|
|
790
|
+
return res;
|
|
606
791
|
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
792
|
+
var getHTML = (apiReference, config) => `<!doctype html>
|
|
793
|
+
<html>
|
|
794
|
+
<head>
|
|
795
|
+
<title>Scalar API Reference</title>
|
|
796
|
+
<meta charset="utf-8" />
|
|
797
|
+
<meta
|
|
798
|
+
name="viewport"
|
|
799
|
+
content="width=device-width, initial-scale=1" />
|
|
800
|
+
</head>
|
|
801
|
+
<body>
|
|
802
|
+
<script
|
|
803
|
+
id="api-reference"
|
|
804
|
+
type="application/json">
|
|
805
|
+
${JSON.stringify(apiReference)}
|
|
806
|
+
</script>
|
|
807
|
+
<script>
|
|
808
|
+
var configuration = {
|
|
809
|
+
favicon: ${config?.logo ? `data:image/svg+xml;utf8,${encodeURIComponent(config.logo)}` : void 0} ,
|
|
810
|
+
theme: ${config?.theme || "saturn"},
|
|
811
|
+
metaData: {
|
|
812
|
+
title: ${config?.title || "Open API Reference"},
|
|
813
|
+
description: ${config?.description || "Better Call Open API"},
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
document.getElementById('api-reference').dataset.configuration =
|
|
817
|
+
JSON.stringify(configuration)
|
|
818
|
+
</script>
|
|
819
|
+
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
|
|
820
|
+
</body>
|
|
821
|
+
</html>`;
|
|
610
822
|
|
|
611
823
|
// src/utils.ts
|
|
612
824
|
async function getBody(request) {
|
|
@@ -648,180 +860,89 @@ async function getBody(request) {
|
|
|
648
860
|
}
|
|
649
861
|
return await request.text();
|
|
650
862
|
}
|
|
651
|
-
function shouldSerialize(body) {
|
|
652
|
-
return typeof body === "object" && body !== null && !(body instanceof Blob) && !(body instanceof FormData);
|
|
653
|
-
}
|
|
654
|
-
var statusCode = {
|
|
655
|
-
OK: 200,
|
|
656
|
-
CREATED: 201,
|
|
657
|
-
ACCEPTED: 202,
|
|
658
|
-
NO_CONTENT: 204,
|
|
659
|
-
MULTIPLE_CHOICES: 300,
|
|
660
|
-
MOVED_PERMANENTLY: 301,
|
|
661
|
-
FOUND: 302,
|
|
662
|
-
SEE_OTHER: 303,
|
|
663
|
-
NOT_MODIFIED: 304,
|
|
664
|
-
TEMPORARY_REDIRECT: 307,
|
|
665
|
-
BAD_REQUEST: 400,
|
|
666
|
-
UNAUTHORIZED: 401,
|
|
667
|
-
PAYMENT_REQUIRED: 402,
|
|
668
|
-
FORBIDDEN: 403,
|
|
669
|
-
NOT_FOUND: 404,
|
|
670
|
-
METHOD_NOT_ALLOWED: 405,
|
|
671
|
-
NOT_ACCEPTABLE: 406,
|
|
672
|
-
PROXY_AUTHENTICATION_REQUIRED: 407,
|
|
673
|
-
REQUEST_TIMEOUT: 408,
|
|
674
|
-
CONFLICT: 409,
|
|
675
|
-
GONE: 410,
|
|
676
|
-
LENGTH_REQUIRED: 411,
|
|
677
|
-
PRECONDITION_FAILED: 412,
|
|
678
|
-
PAYLOAD_TOO_LARGE: 413,
|
|
679
|
-
URI_TOO_LONG: 414,
|
|
680
|
-
UNSUPPORTED_MEDIA_TYPE: 415,
|
|
681
|
-
RANGE_NOT_SATISFIABLE: 416,
|
|
682
|
-
EXPECTATION_FAILED: 417,
|
|
683
|
-
"I'M_A_TEAPOT": 418,
|
|
684
|
-
MISDIRECTED_REQUEST: 421,
|
|
685
|
-
UNPROCESSABLE_ENTITY: 422,
|
|
686
|
-
LOCKED: 423,
|
|
687
|
-
FAILED_DEPENDENCY: 424,
|
|
688
|
-
TOO_EARLY: 425,
|
|
689
|
-
UPGRADE_REQUIRED: 426,
|
|
690
|
-
PRECONDITION_REQUIRED: 428,
|
|
691
|
-
TOO_MANY_REQUESTS: 429,
|
|
692
|
-
REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
|
|
693
|
-
UNAVAILABLE_FOR_LEGAL_REASONS: 451,
|
|
694
|
-
INTERNAL_SERVER_ERROR: 500,
|
|
695
|
-
NOT_IMPLEMENTED: 501,
|
|
696
|
-
BAD_GATEWAY: 502,
|
|
697
|
-
SERVICE_UNAVAILABLE: 503,
|
|
698
|
-
GATEWAY_TIMEOUT: 504,
|
|
699
|
-
HTTP_VERSION_NOT_SUPPORTED: 505,
|
|
700
|
-
VARIANT_ALSO_NEGOTIATES: 506,
|
|
701
|
-
INSUFFICIENT_STORAGE: 507,
|
|
702
|
-
LOOP_DETECTED: 508,
|
|
703
|
-
NOT_EXTENDED: 510,
|
|
704
|
-
NETWORK_AUTHENTICATION_REQUIRED: 511
|
|
705
|
-
};
|
|
706
863
|
|
|
707
864
|
// src/router.ts
|
|
708
865
|
var createRouter = (endpoints, config) => {
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
866
|
+
if (!config?.openAPI?.disabled) {
|
|
867
|
+
const openAPI = {
|
|
868
|
+
path: "/api/reference",
|
|
869
|
+
...config?.openAPI
|
|
870
|
+
};
|
|
871
|
+
endpoints["openAPI"] = createEndpoint2(
|
|
872
|
+
openAPI.path,
|
|
873
|
+
{
|
|
874
|
+
method: "GET"
|
|
875
|
+
},
|
|
876
|
+
async (c) => {
|
|
877
|
+
const schema = await generator(endpoints);
|
|
878
|
+
return new Response(getHTML(schema, openAPI.scalar), {
|
|
879
|
+
headers: {
|
|
880
|
+
"Content-Type": "text/html"
|
|
881
|
+
}
|
|
882
|
+
});
|
|
716
883
|
}
|
|
717
|
-
|
|
718
|
-
addRoute(router, endpoint.options.method, endpoint.path, endpoint);
|
|
719
|
-
}
|
|
884
|
+
);
|
|
720
885
|
}
|
|
886
|
+
const router = createRou3Router();
|
|
721
887
|
const middlewareRouter = createRou3Router();
|
|
722
|
-
for (const
|
|
723
|
-
|
|
888
|
+
for (const endpoint of Object.values(endpoints)) {
|
|
889
|
+
if (!endpoint.options) {
|
|
890
|
+
continue;
|
|
891
|
+
}
|
|
892
|
+
if (endpoint.options?.metadata?.SERVER_ONLY) continue;
|
|
893
|
+
const methods = Array.isArray(endpoint.options?.method) ? endpoint.options.method : [endpoint.options?.method];
|
|
894
|
+
for (const method of methods) {
|
|
895
|
+
addRoute(router, method, endpoint.path, endpoint);
|
|
896
|
+
}
|
|
724
897
|
}
|
|
725
|
-
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
if (config?.basePath) {
|
|
729
|
-
path = path.split(config.basePath)[1];
|
|
898
|
+
if (config?.routerMiddleware?.length) {
|
|
899
|
+
for (const { path, middleware } of config.routerMiddleware) {
|
|
900
|
+
addRoute(middlewareRouter, "*", path, middleware);
|
|
730
901
|
}
|
|
902
|
+
}
|
|
903
|
+
const processRequest = async (request) => {
|
|
904
|
+
const url = new URL(request.url);
|
|
905
|
+
const path = config?.basePath ? url.pathname.split(config.basePath)[1] : url.pathname;
|
|
731
906
|
if (!path?.length) {
|
|
732
|
-
config?.onError?.(new
|
|
733
|
-
|
|
734
|
-
`[better-call]: Make sure the URL has the basePath (${config?.basePath}).`
|
|
735
|
-
);
|
|
736
|
-
return new Response(null, {
|
|
737
|
-
status: 404,
|
|
738
|
-
statusText: "Not Found"
|
|
739
|
-
});
|
|
907
|
+
config?.onError?.(new Error("NOT_FOUND"));
|
|
908
|
+
return new Response(null, { status: 404, statusText: "Not Found" });
|
|
740
909
|
}
|
|
741
|
-
const
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
const body = await getBody(request);
|
|
745
|
-
const headers = request.headers;
|
|
746
|
-
const query = Object.fromEntries(url.searchParams);
|
|
747
|
-
const routerMiddleware = findAllRoutes(middlewareRouter, "*", path);
|
|
748
|
-
if (!handler2) {
|
|
749
|
-
return new Response(null, {
|
|
750
|
-
status: 404,
|
|
751
|
-
statusText: "Not Found"
|
|
752
|
-
});
|
|
910
|
+
const route = findRoute(router, request.method, path);
|
|
911
|
+
if (!route?.data) {
|
|
912
|
+
return new Response(null, { status: 404, statusText: "Not Found" });
|
|
753
913
|
}
|
|
914
|
+
const handler = route.data;
|
|
915
|
+
const context = {
|
|
916
|
+
path,
|
|
917
|
+
method: request.method,
|
|
918
|
+
headers: request.headers,
|
|
919
|
+
params: route.params,
|
|
920
|
+
request,
|
|
921
|
+
body: await getBody(handler.options.cloneRequest ? request.clone() : request),
|
|
922
|
+
query: Object.fromEntries(url.searchParams),
|
|
923
|
+
_flag: "router",
|
|
924
|
+
asResponse: true,
|
|
925
|
+
context: config?.routerContext
|
|
926
|
+
};
|
|
754
927
|
try {
|
|
755
|
-
|
|
756
|
-
if (
|
|
757
|
-
for (const
|
|
758
|
-
const middleware = route2.data;
|
|
928
|
+
const middlewareRoutes = findAllRoutes(middlewareRouter, "*", path);
|
|
929
|
+
if (middlewareRoutes?.length) {
|
|
930
|
+
for (const { data: middleware, params } of middlewareRoutes) {
|
|
759
931
|
const res = await middleware({
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
params: route2?.params,
|
|
764
|
-
request,
|
|
765
|
-
body,
|
|
766
|
-
query,
|
|
767
|
-
context: {
|
|
768
|
-
...config?.extraContext
|
|
769
|
-
}
|
|
932
|
+
...context,
|
|
933
|
+
params,
|
|
934
|
+
asResponse: false
|
|
770
935
|
});
|
|
771
|
-
if (res instanceof Response)
|
|
772
|
-
return res;
|
|
773
|
-
}
|
|
774
|
-
if (res?._flag === "json") {
|
|
775
|
-
return new Response(JSON.stringify(res), {
|
|
776
|
-
headers: res.headers
|
|
777
|
-
});
|
|
778
|
-
}
|
|
779
|
-
if (res) {
|
|
780
|
-
middlewareContext = {
|
|
781
|
-
...res,
|
|
782
|
-
...middlewareContext
|
|
783
|
-
};
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
const handlerRes = await handler2({
|
|
788
|
-
path,
|
|
789
|
-
method,
|
|
790
|
-
headers,
|
|
791
|
-
params: route?.params,
|
|
792
|
-
request,
|
|
793
|
-
body,
|
|
794
|
-
query,
|
|
795
|
-
_flag: "router",
|
|
796
|
-
context: {
|
|
797
|
-
...middlewareContext,
|
|
798
|
-
...config?.extraContext
|
|
799
|
-
}
|
|
800
|
-
});
|
|
801
|
-
if (handlerRes instanceof Response) {
|
|
802
|
-
return handlerRes;
|
|
803
|
-
}
|
|
804
|
-
const resBody = shouldSerialize(handlerRes) ? JSON.stringify(handlerRes) : handlerRes;
|
|
805
|
-
return new Response(resBody, {
|
|
806
|
-
headers: handler2.headers
|
|
807
|
-
});
|
|
808
|
-
} catch (e) {
|
|
809
|
-
if (config?.onError) {
|
|
810
|
-
const onErrorRes = await config.onError(e);
|
|
811
|
-
if (onErrorRes instanceof Response) {
|
|
812
|
-
return onErrorRes;
|
|
936
|
+
if (res instanceof Response) return res;
|
|
813
937
|
}
|
|
814
938
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
if (config?.throwError) {
|
|
823
|
-
throw e;
|
|
939
|
+
const response = await handler(context);
|
|
940
|
+
return response;
|
|
941
|
+
} catch (error) {
|
|
942
|
+
if (error instanceof APIError) {
|
|
943
|
+
return toResponse(error);
|
|
824
944
|
}
|
|
945
|
+
console.error(`# SERVER_ERROR: `, error);
|
|
825
946
|
return new Response(null, {
|
|
826
947
|
status: 500,
|
|
827
948
|
statusText: "Internal Server Error"
|
|
@@ -835,7 +956,7 @@ var createRouter = (endpoints, config) => {
|
|
|
835
956
|
return onReq;
|
|
836
957
|
}
|
|
837
958
|
const req = onReq instanceof Request ? onReq : request;
|
|
838
|
-
const res = await
|
|
959
|
+
const res = await processRequest(req);
|
|
839
960
|
const onRes = await config?.onResponse?.(res);
|
|
840
961
|
if (onRes instanceof Response) {
|
|
841
962
|
return onRes;
|
|
@@ -845,224 +966,19 @@ var createRouter = (endpoints, config) => {
|
|
|
845
966
|
endpoints
|
|
846
967
|
};
|
|
847
968
|
};
|
|
848
|
-
|
|
849
|
-
// src/middleware.ts
|
|
850
|
-
function createMiddleware(optionsOrHandler, handler) {
|
|
851
|
-
if (typeof optionsOrHandler === "function") {
|
|
852
|
-
return createEndpoint(
|
|
853
|
-
"*",
|
|
854
|
-
{
|
|
855
|
-
method: "*"
|
|
856
|
-
},
|
|
857
|
-
optionsOrHandler
|
|
858
|
-
);
|
|
859
|
-
}
|
|
860
|
-
if (!handler) {
|
|
861
|
-
throw new Error("Middleware handler is required");
|
|
862
|
-
}
|
|
863
|
-
const endpoint = createEndpoint(
|
|
864
|
-
"*",
|
|
865
|
-
{
|
|
866
|
-
...optionsOrHandler,
|
|
867
|
-
method: "*"
|
|
868
|
-
},
|
|
869
|
-
handler
|
|
870
|
-
);
|
|
871
|
-
return endpoint;
|
|
872
|
-
}
|
|
873
|
-
var createMiddlewareCreator = (opts) => {
|
|
874
|
-
function fn(optionsOrHandler, handler) {
|
|
875
|
-
if (typeof optionsOrHandler === "function") {
|
|
876
|
-
return createEndpoint(
|
|
877
|
-
"*",
|
|
878
|
-
{
|
|
879
|
-
method: "*"
|
|
880
|
-
},
|
|
881
|
-
optionsOrHandler
|
|
882
|
-
);
|
|
883
|
-
}
|
|
884
|
-
if (!handler) {
|
|
885
|
-
throw new Error("Middleware handler is required");
|
|
886
|
-
}
|
|
887
|
-
const endpoint = createEndpoint(
|
|
888
|
-
"*",
|
|
889
|
-
{
|
|
890
|
-
...optionsOrHandler,
|
|
891
|
-
method: "*"
|
|
892
|
-
},
|
|
893
|
-
handler
|
|
894
|
-
);
|
|
895
|
-
return endpoint;
|
|
896
|
-
}
|
|
897
|
-
return fn;
|
|
898
|
-
};
|
|
899
|
-
|
|
900
|
-
// src/types.ts
|
|
901
|
-
import "zod";
|
|
902
|
-
|
|
903
|
-
// src/adapter/request.ts
|
|
904
|
-
var set_cookie_parser = __toESM(require_set_cookie(), 1);
|
|
905
|
-
function get_raw_body(req, body_size_limit) {
|
|
906
|
-
const h = req.headers;
|
|
907
|
-
if (!h["content-type"]) return null;
|
|
908
|
-
const content_length = Number(h["content-length"]);
|
|
909
|
-
if (req.httpVersionMajor === 1 && isNaN(content_length) && h["transfer-encoding"] == null || content_length === 0) {
|
|
910
|
-
return null;
|
|
911
|
-
}
|
|
912
|
-
let length = content_length;
|
|
913
|
-
if (body_size_limit) {
|
|
914
|
-
if (!length) {
|
|
915
|
-
length = body_size_limit;
|
|
916
|
-
} else if (length > body_size_limit) {
|
|
917
|
-
throw Error(
|
|
918
|
-
`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
|
|
919
|
-
);
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
if (req.destroyed) {
|
|
923
|
-
const readable = new ReadableStream();
|
|
924
|
-
readable.cancel();
|
|
925
|
-
return readable;
|
|
926
|
-
}
|
|
927
|
-
let size = 0;
|
|
928
|
-
let cancelled = false;
|
|
929
|
-
return new ReadableStream({
|
|
930
|
-
start(controller) {
|
|
931
|
-
req.on("error", (error) => {
|
|
932
|
-
cancelled = true;
|
|
933
|
-
controller.error(error);
|
|
934
|
-
});
|
|
935
|
-
req.on("end", () => {
|
|
936
|
-
if (cancelled) return;
|
|
937
|
-
controller.close();
|
|
938
|
-
});
|
|
939
|
-
req.on("data", (chunk) => {
|
|
940
|
-
if (cancelled) return;
|
|
941
|
-
size += chunk.length;
|
|
942
|
-
if (size > length) {
|
|
943
|
-
cancelled = true;
|
|
944
|
-
controller.error(
|
|
945
|
-
new Error(
|
|
946
|
-
`request body size exceeded ${content_length ? "'content-length'" : "BODY_SIZE_LIMIT"} of ${length}`
|
|
947
|
-
)
|
|
948
|
-
);
|
|
949
|
-
return;
|
|
950
|
-
}
|
|
951
|
-
controller.enqueue(chunk);
|
|
952
|
-
if (controller.desiredSize === null || controller.desiredSize <= 0) {
|
|
953
|
-
req.pause();
|
|
954
|
-
}
|
|
955
|
-
});
|
|
956
|
-
},
|
|
957
|
-
pull() {
|
|
958
|
-
req.resume();
|
|
959
|
-
},
|
|
960
|
-
cancel(reason) {
|
|
961
|
-
cancelled = true;
|
|
962
|
-
req.destroy(reason);
|
|
963
|
-
}
|
|
964
|
-
});
|
|
965
|
-
}
|
|
966
|
-
function getRequest({
|
|
967
|
-
request,
|
|
968
|
-
base,
|
|
969
|
-
bodySizeLimit
|
|
970
|
-
}) {
|
|
971
|
-
return new Request(base + request.url, {
|
|
972
|
-
// @ts-expect-error
|
|
973
|
-
duplex: "half",
|
|
974
|
-
method: request.method,
|
|
975
|
-
body: get_raw_body(request, bodySizeLimit),
|
|
976
|
-
headers: request.headers
|
|
977
|
-
});
|
|
978
|
-
}
|
|
979
|
-
async function setResponse(res, response) {
|
|
980
|
-
for (const [key, value] of response.headers) {
|
|
981
|
-
try {
|
|
982
|
-
res.setHeader(
|
|
983
|
-
key,
|
|
984
|
-
key === "set-cookie" ? set_cookie_parser.splitCookiesString(response.headers.get(key)) : value
|
|
985
|
-
);
|
|
986
|
-
} catch (error) {
|
|
987
|
-
res.getHeaderNames().forEach((name) => res.removeHeader(name));
|
|
988
|
-
res.writeHead(500).end(String(error));
|
|
989
|
-
return;
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
res.writeHead(response.status);
|
|
993
|
-
if (!response.body) {
|
|
994
|
-
res.end();
|
|
995
|
-
return;
|
|
996
|
-
}
|
|
997
|
-
if (response.body.locked) {
|
|
998
|
-
res.end(
|
|
999
|
-
"Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()')."
|
|
1000
|
-
);
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
const reader = response.body.getReader();
|
|
1004
|
-
if (res.destroyed) {
|
|
1005
|
-
reader.cancel();
|
|
1006
|
-
return;
|
|
1007
|
-
}
|
|
1008
|
-
const cancel = (error) => {
|
|
1009
|
-
res.off("close", cancel);
|
|
1010
|
-
res.off("error", cancel);
|
|
1011
|
-
reader.cancel(error).catch(() => {
|
|
1012
|
-
});
|
|
1013
|
-
if (error) res.destroy(error);
|
|
1014
|
-
};
|
|
1015
|
-
res.on("close", cancel);
|
|
1016
|
-
res.on("error", cancel);
|
|
1017
|
-
next();
|
|
1018
|
-
async function next() {
|
|
1019
|
-
try {
|
|
1020
|
-
for (; ; ) {
|
|
1021
|
-
const { done, value } = await reader.read();
|
|
1022
|
-
if (done) break;
|
|
1023
|
-
if (!res.write(value)) {
|
|
1024
|
-
res.once("drain", next);
|
|
1025
|
-
return;
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
res.end();
|
|
1029
|
-
} catch (error) {
|
|
1030
|
-
cancel(error instanceof Error ? error : new Error(String(error)));
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
// src/adapter/node.ts
|
|
1036
|
-
function toNodeHandler(handler) {
|
|
1037
|
-
return async (req, res) => {
|
|
1038
|
-
const protocol = req.headers["x-forwarded-proto"] || (req.socket.encrypted ? "https" : "http");
|
|
1039
|
-
const base = `${protocol}://${req.headers[":authority"] || req.headers.host}`;
|
|
1040
|
-
const response = await handler(getRequest({ base, request: req }));
|
|
1041
|
-
setResponse(res, response);
|
|
1042
|
-
};
|
|
1043
|
-
}
|
|
1044
969
|
export {
|
|
1045
970
|
APIError,
|
|
1046
|
-
|
|
1047
|
-
|
|
971
|
+
_statusCode,
|
|
972
|
+
createEndpoint2 as createEndpoint,
|
|
973
|
+
createInternalContext,
|
|
1048
974
|
createMiddleware,
|
|
1049
|
-
createMiddlewareCreator,
|
|
1050
975
|
createRouter,
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
serialize,
|
|
1059
|
-
serializeSigned,
|
|
1060
|
-
setCookie,
|
|
1061
|
-
setResponse,
|
|
1062
|
-
setSignedCookie,
|
|
1063
|
-
shouldSerialize,
|
|
1064
|
-
signCookieValue,
|
|
1065
|
-
statusCode,
|
|
1066
|
-
toNodeHandler
|
|
976
|
+
generator,
|
|
977
|
+
getCookieKey,
|
|
978
|
+
getHTML,
|
|
979
|
+
parseCookies,
|
|
980
|
+
serializeCookie,
|
|
981
|
+
serializeSignedCookie,
|
|
982
|
+
toResponse
|
|
1067
983
|
};
|
|
1068
984
|
//# sourceMappingURL=index.js.map
|