better-call 0.2.11 → 0.2.13-beta.2

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/index.cjs CHANGED
@@ -1,294 +1,137 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __commonJS = (cb, mod) => function __require() {
10
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
- };
12
- var __export = (target, all) => {
13
- for (var name in all)
14
- __defProp(target, name, { get: all[name], enumerable: true });
15
- };
16
- var __copyProps = (to, from, except, desc) => {
17
- if (from && typeof from === "object" || typeof from === "function") {
18
- for (let key of __getOwnPropNames(from))
19
- if (!__hasOwnProp.call(to, key) && key !== except)
20
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
- }
22
- return to;
23
- };
24
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
- // If the importer is in node compatibility mode or this is not an ESM
26
- // file that has been converted to a CommonJS file using a Babel-
27
- // compatible transform (i.e. "__esModule" has not been set), then set
28
- // "default" to the CommonJS "module.exports" for node compatibility.
29
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
- mod
31
- ));
32
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1
+ 'use strict';
2
+
3
+ const crypto = require('uncrypto');
4
+ const rou3 = require('rou3');
5
+
6
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
34
7
 
35
- // node_modules/set-cookie-parser/lib/set-cookie.js
36
- var require_set_cookie = __commonJS({
37
- "node_modules/set-cookie-parser/lib/set-cookie.js"(exports2, module2) {
38
- "use strict";
39
- var defaultParseOptions = {
40
- decodeValues: true,
41
- map: false,
42
- silent: false
8
+ const crypto__default = /*#__PURE__*/_interopDefaultCompat(crypto);
9
+
10
+ function createJSON({
11
+ asResponse,
12
+ response
13
+ }) {
14
+ return async function json(json, routerResponse) {
15
+ if (!asResponse) {
16
+ return json;
17
+ }
18
+ return {
19
+ body: json,
20
+ routerResponse,
21
+ _flag: "json"
43
22
  };
44
- function isNonEmptyString(str) {
45
- return typeof str === "string" && !!str.trim();
46
- }
47
- function parseString(setCookieValue, options) {
48
- var parts = setCookieValue.split(";").filter(isNonEmptyString);
49
- var nameValuePairStr = parts.shift();
50
- var parsed = parseNameValuePair(nameValuePairStr);
51
- var name = parsed.name;
52
- var value = parsed.value;
53
- options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions;
54
- try {
55
- value = options.decodeValues ? decodeURIComponent(value) : value;
56
- } catch (e) {
57
- console.error(
58
- "set-cookie-parser encountered an error while decoding a cookie with value '" + value + "'. Set options.decodeValues to false to disable this feature.",
59
- e
60
- );
61
- }
62
- var cookie = {
63
- name,
64
- value
23
+ };
24
+ }
25
+ function runValidation(options, context) {
26
+ let request = {
27
+ body: void 0,
28
+ query: void 0
29
+ };
30
+ if (options.body) {
31
+ const result = options.body.safeParse(context.body);
32
+ if (result.error) {
33
+ return {
34
+ data: null,
35
+ error: fromError(result.error)
65
36
  };
66
- parts.forEach(function(part) {
67
- var sides = part.split("=");
68
- var key = sides.shift().trimLeft().toLowerCase();
69
- var value2 = sides.join("=");
70
- if (key === "expires") {
71
- cookie.expires = new Date(value2);
72
- } else if (key === "max-age") {
73
- cookie.maxAge = parseInt(value2, 10);
74
- } else if (key === "secure") {
75
- cookie.secure = true;
76
- } else if (key === "httponly") {
77
- cookie.httpOnly = true;
78
- } else if (key === "samesite") {
79
- cookie.sameSite = value2;
80
- } else if (key === "partitioned") {
81
- cookie.partitioned = true;
82
- } else {
83
- cookie[key] = value2;
84
- }
85
- });
86
- return cookie;
87
- }
88
- function parseNameValuePair(nameValuePairStr) {
89
- var name = "";
90
- var value = "";
91
- var nameValueArr = nameValuePairStr.split("=");
92
- if (nameValueArr.length > 1) {
93
- name = nameValueArr.shift();
94
- value = nameValueArr.join("=");
95
- } else {
96
- value = nameValuePairStr;
97
- }
98
- return { name, value };
99
37
  }
100
- function parse2(input, options) {
101
- options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions;
102
- if (!input) {
103
- if (!options.map) {
104
- return [];
105
- } else {
106
- return {};
107
- }
108
- }
109
- if (input.headers) {
110
- if (typeof input.headers.getSetCookie === "function") {
111
- input = input.headers.getSetCookie();
112
- } else if (input.headers["set-cookie"]) {
113
- input = input.headers["set-cookie"];
114
- } else {
115
- var sch = input.headers[Object.keys(input.headers).find(function(key) {
116
- return key.toLowerCase() === "set-cookie";
117
- })];
118
- if (!sch && input.headers.cookie && !options.silent) {
119
- console.warn(
120
- "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."
121
- );
122
- }
123
- input = sch;
124
- }
125
- }
126
- if (!Array.isArray(input)) {
127
- input = [input];
128
- }
129
- options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions;
130
- if (!options.map) {
131
- return input.filter(isNonEmptyString).map(function(str) {
132
- return parseString(str, options);
133
- });
134
- } else {
135
- var cookies = {};
136
- return input.filter(isNonEmptyString).reduce(function(cookies2, str) {
137
- var cookie = parseString(str, options);
138
- cookies2[cookie.name] = cookie;
139
- return cookies2;
140
- }, cookies);
141
- }
38
+ request.body = result.data;
39
+ }
40
+ if (options.query) {
41
+ const result = options.query.safeParse(context.query);
42
+ if (result.error) {
43
+ return {
44
+ data: null,
45
+ error: fromError(result.error)
46
+ };
142
47
  }
143
- function splitCookiesString2(cookiesString) {
144
- if (Array.isArray(cookiesString)) {
145
- return cookiesString;
146
- }
147
- if (typeof cookiesString !== "string") {
148
- return [];
149
- }
150
- var cookiesStrings = [];
151
- var pos = 0;
152
- var start;
153
- var ch;
154
- var lastComma;
155
- var nextStart;
156
- var cookiesSeparatorFound;
157
- function skipWhitespace() {
158
- while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
159
- pos += 1;
160
- }
161
- return pos < cookiesString.length;
162
- }
163
- function notSpecialChar() {
164
- ch = cookiesString.charAt(pos);
165
- return ch !== "=" && ch !== ";" && ch !== ",";
166
- }
167
- while (pos < cookiesString.length) {
168
- start = pos;
169
- cookiesSeparatorFound = false;
170
- while (skipWhitespace()) {
171
- ch = cookiesString.charAt(pos);
172
- if (ch === ",") {
173
- lastComma = pos;
174
- pos += 1;
175
- skipWhitespace();
176
- nextStart = pos;
177
- while (pos < cookiesString.length && notSpecialChar()) {
178
- pos += 1;
179
- }
180
- if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") {
181
- cookiesSeparatorFound = true;
182
- pos = nextStart;
183
- cookiesStrings.push(cookiesString.substring(start, lastComma));
184
- start = pos;
185
- } else {
186
- pos = lastComma + 1;
187
- }
188
- } else {
189
- pos += 1;
190
- }
191
- }
192
- if (!cookiesSeparatorFound || pos >= cookiesString.length) {
193
- cookiesStrings.push(cookiesString.substring(start, cookiesString.length));
194
- }
195
- }
196
- return cookiesStrings;
48
+ request.query = result.data;
49
+ }
50
+ if (options.requireHeaders && !(context.headers instanceof Headers)) {
51
+ return {
52
+ data: null,
53
+ error: { message: "Validation Error: Headers are required" }
54
+ };
55
+ }
56
+ if (options.requireRequest && !context.request) {
57
+ return {
58
+ data: null,
59
+ error: { message: "Validation Error: Request is required" }
60
+ };
61
+ }
62
+ return {
63
+ data: request,
64
+ error: null
65
+ };
66
+ }
67
+ function fromError(error) {
68
+ const errorMessages = [];
69
+ for (const issue of error.issues) {
70
+ const path = issue.path.join(".");
71
+ const message = issue.message;
72
+ if (path) {
73
+ errorMessages.push(`${message} at "${path}"`);
74
+ } else {
75
+ errorMessages.push(message);
197
76
  }
198
- module2.exports = parse2;
199
- module2.exports.parse = parse2;
200
- module2.exports.parseString = parseString;
201
- module2.exports.splitCookiesString = splitCookiesString2;
202
77
  }
203
- });
204
-
205
- // src/index.ts
206
- var src_exports = {};
207
- __export(src_exports, {
208
- APIError: () => APIError,
209
- createEndpoint: () => createEndpoint,
210
- createEndpointCreator: () => createEndpointCreator,
211
- createMiddleware: () => createMiddleware,
212
- createMiddlewareCreator: () => createMiddlewareCreator,
213
- createRouter: () => createRouter,
214
- getBody: () => getBody,
215
- getCookie: () => getCookie,
216
- getRequest: () => getRequest,
217
- getSignedCookie: () => getSignedCookie,
218
- parse: () => parse,
219
- parseSigned: () => parseSigned,
220
- serialize: () => serialize,
221
- serializeSigned: () => serializeSigned,
222
- setCookie: () => setCookie,
223
- setResponse: () => setResponse,
224
- setSignedCookie: () => setSignedCookie,
225
- shouldSerialize: () => shouldSerialize,
226
- statusCode: () => statusCode,
227
- toNodeHandler: () => toNodeHandler
228
- });
229
- module.exports = __toCommonJS(src_exports);
78
+ return {
79
+ message: `Validation error: ${errorMessages.join(", ")}`
80
+ };
81
+ }
230
82
 
231
- // src/endpoint.ts
232
- var import_zod = require("zod");
83
+ function createSetHeader(headers) {
84
+ return (key, value) => {
85
+ headers.set(key, value);
86
+ };
87
+ }
88
+ function createGetHeader(headers) {
89
+ return (key) => {
90
+ return headers.get(key);
91
+ };
92
+ }
233
93
 
234
- // src/error.ts
235
- var APIError = class extends Error {
236
- constructor(status, body, headers) {
237
- super(`API Error: ${status} ${body?.message ?? ""}`, {
238
- cause: body
239
- });
240
- __publicField(this, "status");
241
- __publicField(this, "headers");
242
- __publicField(this, "body");
94
+ class APIError extends Error {
95
+ constructor(message, status = 500, code = "INTERNAL_SERVER_ERROR", headers = {}) {
96
+ super(message);
97
+ this.message = message;
98
+ this.status = status;
99
+ this.code = code;
100
+ this.headers = headers;
101
+ this.name = "APIError";
102
+ this.message = message;
243
103
  this.status = status;
244
- this.body = body ?? {};
104
+ this.code = code;
105
+ this.headers = headers;
245
106
  this.stack = "";
246
- this.headers = headers ?? new Headers();
247
- if (!this.headers.has("Content-Type")) {
248
- this.headers.set("Content-Type", "application/json");
249
- }
250
- this.name = "BetterCallAPIError";
251
107
  }
252
- };
253
-
254
- // src/helper.ts
255
- var json = (body, option) => {
256
- return {
257
- response: {
258
- body: option?.body ?? body,
259
- status: option?.status ?? 200,
260
- statusText: option?.statusText ?? "OK",
261
- headers: option?.headers
262
- },
263
- body,
264
- _flag: "json"
265
- };
266
- };
108
+ }
267
109
 
268
- // src/cookie.ts
269
- var import_uncrypto = __toESM(require("uncrypto"), 1);
270
- var algorithm = { name: "HMAC", hash: "SHA-256" };
271
- var getCryptoKey = async (secret) => {
110
+ const algorithm = { name: "HMAC", hash: "SHA-256" };
111
+ const getCryptoKey = async (secret) => {
272
112
  const secretBuf = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
273
- return await import_uncrypto.default.subtle.importKey("raw", secretBuf, algorithm, false, ["sign", "verify"]);
113
+ return await crypto__default.subtle.importKey("raw", secretBuf, algorithm, false, [
114
+ "sign",
115
+ "verify"
116
+ ]);
274
117
  };
275
- var makeSignature = async (value, secret) => {
118
+ const makeSignature = async (value, secret) => {
276
119
  const key = await getCryptoKey(secret);
277
- const signature = await import_uncrypto.default.subtle.sign(
120
+ const signature = await crypto__default.subtle.sign(
278
121
  algorithm.name,
279
122
  key,
280
123
  new TextEncoder().encode(value)
281
124
  );
282
125
  return btoa(String.fromCharCode(...new Uint8Array(signature)));
283
126
  };
284
- var verifySignature = async (base64Signature, value, secret) => {
127
+ const verifySignature = async (base64Signature, value, secret) => {
285
128
  try {
286
129
  const signatureBinStr = atob(base64Signature);
287
130
  const signature = new Uint8Array(signatureBinStr.length);
288
131
  for (let i = 0, len = signatureBinStr.length; i < len; i++) {
289
132
  signature[i] = signatureBinStr.charCodeAt(i);
290
133
  }
291
- return await import_uncrypto.default.subtle.verify(
134
+ return await crypto__default.subtle.verify(
292
135
  algorithm,
293
136
  secret,
294
137
  signature,
@@ -298,9 +141,9 @@ var verifySignature = async (base64Signature, value, secret) => {
298
141
  return false;
299
142
  }
300
143
  };
301
- var validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
302
- var validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/;
303
- var parse = (cookie, name) => {
144
+ const validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
145
+ const validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/;
146
+ const parse = (cookie, name) => {
304
147
  const pairs = cookie.trim().split(";");
305
148
  return pairs.reduce((parsedCookie, pairStr) => {
306
149
  pairStr = pairStr.trim();
@@ -322,7 +165,7 @@ var parse = (cookie, name) => {
322
165
  return parsedCookie;
323
166
  }, {});
324
167
  };
325
- var parseSigned = async (cookie, secret, name) => {
168
+ const parseSigned = async (cookie, secret, name) => {
326
169
  const parsedCookie = {};
327
170
  const secretKey = await getCryptoKey(secret);
328
171
  for (const [key, value] of Object.entries(parse(cookie, name))) {
@@ -340,7 +183,7 @@ var parseSigned = async (cookie, secret, name) => {
340
183
  }
341
184
  return parsedCookie;
342
185
  };
343
- var _serialize = (name, value, opt = {}) => {
186
+ const _serialize = (name, value, opt = {}) => {
344
187
  let cookie = `${name}=${value}`;
345
188
  if (name.startsWith("__Secure-") && !opt.secure) {
346
189
  opt.secure = true;
@@ -395,19 +238,18 @@ var _serialize = (name, value, opt = {}) => {
395
238
  }
396
239
  return cookie;
397
240
  };
398
- var serialize = (name, value, opt) => {
241
+ const serialize = (name, value, opt) => {
399
242
  value = encodeURIComponent(value);
400
243
  return _serialize(name, value, opt);
401
244
  };
402
- var serializeSigned = async (name, value, secret, opt = {}) => {
245
+ const serializeSigned = async (name, value, secret, opt = {}) => {
403
246
  const signature = await makeSignature(value, secret);
404
247
  value = `${value}.${signature}`;
405
248
  value = encodeURIComponent(value);
406
249
  return _serialize(name, value, opt);
407
250
  };
408
251
 
409
- // src/cookie-utils.ts
410
- var getCookie = (cookie, key, prefix) => {
252
+ const getCookie = (cookie, key, prefix) => {
411
253
  if (!cookie) {
412
254
  return void 0;
413
255
  }
@@ -424,17 +266,23 @@ var getCookie = (cookie, key, prefix) => {
424
266
  const obj = parse(cookie, finalKey);
425
267
  return obj[finalKey];
426
268
  };
427
- var setCookie = (header, name, value, opt) => {
269
+ const setCookie = (header, name, value, opt) => {
428
270
  const existingCookies = header.get("Set-Cookie");
429
271
  if (existingCookies) {
430
272
  const cookies = existingCookies.split(", ");
431
- const updatedCookies = cookies.filter((cookie2) => !cookie2.startsWith(`${name}=`));
273
+ const updatedCookies = cookies.filter(
274
+ (cookie2) => !cookie2.startsWith(`${name}=`)
275
+ );
432
276
  header.delete("Set-Cookie");
433
277
  updatedCookies.forEach((cookie2) => header.append("Set-Cookie", cookie2));
434
278
  }
435
279
  let cookie;
436
280
  if (opt?.prefix === "secure") {
437
- cookie = serialize("__Secure-" + name, value, { path: "/", ...opt, secure: true });
281
+ cookie = serialize("__Secure-" + name, value, {
282
+ path: "/",
283
+ ...opt,
284
+ secure: true
285
+ });
438
286
  } else if (opt?.prefix === "host") {
439
287
  cookie = serialize("__Host-" + name, value, {
440
288
  ...opt,
@@ -447,7 +295,7 @@ var setCookie = (header, name, value, opt) => {
447
295
  }
448
296
  header.append("Set-Cookie", cookie);
449
297
  };
450
- var setSignedCookie = async (header, name, value, secret, opt) => {
298
+ const setSignedCookie = async (header, name, value, secret, opt) => {
451
299
  let cookie;
452
300
  if (opt?.prefix === "secure") {
453
301
  cookie = await serializeSigned("__Secure-" + name, value, secret, {
@@ -467,7 +315,7 @@ var setSignedCookie = async (header, name, value, secret, opt) => {
467
315
  }
468
316
  header.append("Set-Cookie", cookie);
469
317
  };
470
- var getSignedCookie = async (header, secret, key, prefix) => {
318
+ const getSignedCookie = async (header, secret, key, prefix) => {
471
319
  const cookie = header.get("cookie");
472
320
  if (!cookie) {
473
321
  return void 0;
@@ -484,163 +332,127 @@ var getSignedCookie = async (header, secret, key, prefix) => {
484
332
  return obj[finalKey];
485
333
  };
486
334
 
487
- // src/endpoint.ts
488
- function createEndpointCreator(opts) {
489
- return (path, options, handler) => {
490
- return createEndpoint(
491
- path,
335
+ const createResponse = (handlerResponse, response) => {
336
+ if (handlerResponse instanceof Response) {
337
+ response.headers.forEach((value, key) => {
338
+ handlerResponse.headers.set(key, value);
339
+ });
340
+ return handlerResponse;
341
+ } else if (handlerResponse?._flag === "json") {
342
+ const responseObj = new Response(
343
+ JSON.stringify(
344
+ handlerResponse.routerResponse?.body || handlerResponse.body
345
+ ),
492
346
  {
493
- ...options,
494
- use: [...options?.use || [], ...opts?.use || []]
495
- },
496
- handler
347
+ status: handlerResponse.routerResponse?.status || 200,
348
+ headers: handlerResponse.routerResponse?.headers
349
+ }
497
350
  );
498
- };
499
- }
500
- function createEndpoint(path, options, handler) {
501
- let responseHeader = new Headers();
502
- const handle = async (...ctx) => {
503
- let internalCtx = {
504
- setHeader(key, value) {
505
- responseHeader.set(key, value);
351
+ response.headers.forEach((value, key) => {
352
+ responseObj.headers.set(key, value);
353
+ });
354
+ return responseObj;
355
+ } else {
356
+ const responseObj = new Response(
357
+ handlerResponse ? JSON.stringify(handlerResponse) : void 0
358
+ );
359
+ response.headers.forEach((value, key) => {
360
+ responseObj.headers.set(key, value);
361
+ });
362
+ return responseObj;
363
+ }
364
+ };
365
+ const runMiddleware = async (options, context) => {
366
+ let finalContext = {};
367
+ for (const middleware of options.use || []) {
368
+ const result = await middleware(context);
369
+ if (result?.context && result._flag === "context") {
370
+ context = { ...context, ...result.context };
371
+ } else {
372
+ finalContext = { ...result, ...finalContext };
373
+ context.context = finalContext;
374
+ }
375
+ }
376
+ return finalContext;
377
+ };
378
+ const createEndpoint = (path, options, handler) => {
379
+ const internalHandler = async (...inputCtx) => {
380
+ let response = new Response();
381
+ const { asResponse, ...ctx } = inputCtx[0] || {};
382
+ const { data, error } = runValidation(options, ctx);
383
+ if (error) {
384
+ throw new APIError(error.message, 400);
385
+ }
386
+ const context = {
387
+ json: createJSON({
388
+ asResponse,
389
+ response
390
+ }),
391
+ body: "body" in data ? data.body : void 0,
392
+ path,
393
+ method: "method" in ctx ? ctx.method : void 0,
394
+ query: "query" in data ? data.query : void 0,
395
+ params: "params" in ctx ? ctx.params : void 0,
396
+ headers: "headers" in ctx ? ctx.headers : void 0,
397
+ request: "request" in ctx ? ctx.request : void 0,
398
+ setHeader: createSetHeader(response.headers),
399
+ getHeader: (key) => {
400
+ const requestHeaders = "headers" in ctx && ctx.headers instanceof Headers ? ctx.headers : "request" in ctx && ctx.request instanceof Request ? ctx.request.headers : null;
401
+ if (!requestHeaders)
402
+ return null;
403
+ return requestHeaders.get(key);
506
404
  },
507
- setCookie(key, value, options2) {
508
- setCookie(responseHeader, key, value, options2);
405
+ setCookie: (name, value, options2) => {
406
+ setCookie(response.headers, name, value, options2);
509
407
  },
510
408
  getCookie(key, prefix) {
511
- const header = ctx[0]?.headers;
512
- const cookieH = header?.get("cookie");
513
- const cookie = getCookie(cookieH || "", key, prefix);
514
- return cookie;
409
+ const headers = context.headers?.get("cookie");
410
+ if (!headers)
411
+ return void 0;
412
+ return getCookie(headers, key, prefix);
515
413
  },
516
- getSignedCookie(key, secret, prefix) {
517
- const header = ctx[0]?.headers;
518
- if (!header) {
519
- throw new TypeError("Headers are required");
520
- }
521
- const cookie = getSignedCookie(header, secret, key, prefix);
522
- return cookie;
414
+ setSignedCookie(key, value, secret, options2) {
415
+ return setSignedCookie(response.headers, key, value, secret, options2);
523
416
  },
524
- async setSignedCookie(key, value, secret, options2) {
525
- await setSignedCookie(responseHeader, key, value, secret, options2);
417
+ async getSignedCookie(key, secret, prefix) {
418
+ const headers = context.headers;
419
+ if (!headers)
420
+ return void 0;
421
+ return getSignedCookie(headers, secret, key, prefix);
526
422
  },
527
- redirect(url) {
528
- responseHeader.set("Location", url);
529
- return new APIError("FOUND");
423
+ redirect: (url) => {
424
+ const apiError = new APIError("Redirecting", 302, "FOUND", {
425
+ Location: url,
426
+ ...response.headers
427
+ });
428
+ return apiError;
530
429
  },
531
- json,
532
- context: ctx[0]?.context || {},
533
- _flag: ctx[0]?.asResponse ? "router" : ctx[0]?._flag,
534
- responseHeader,
535
- path,
536
- ...ctx[0] || {}
430
+ context: {}
537
431
  };
538
- if (options.use?.length) {
539
- let middlewareContexts = {};
540
- let middlewareBody = {};
541
- for (const middleware of options.use) {
542
- if (typeof middleware !== "function") {
543
- console.warn("Middleware is not a function", {
544
- middleware
545
- });
546
- continue;
547
- }
548
- const res = await middleware(internalCtx);
549
- if (res) {
550
- const body = res.options?.body ? res.options.body.parse(internalCtx.body) : void 0;
551
- middlewareContexts = {
552
- ...middlewareContexts,
553
- ...res
554
- };
555
- middlewareBody = {
556
- ...middlewareBody,
557
- ...body
558
- };
559
- }
560
- }
561
- internalCtx = {
562
- ...internalCtx,
563
- body: {
564
- ...middlewareBody,
565
- ...internalCtx.body
566
- },
567
- context: {
568
- ...internalCtx.context || {},
569
- ...middlewareContexts
432
+ const finalContext = await runMiddleware(options, context);
433
+ context.context = finalContext;
434
+ const handlerResponse = await handler(context).catch((e) => {
435
+ if (e instanceof APIError && asResponse) {
436
+ const headers = response.headers;
437
+ for (const [key, value] of Object.entries(e.headers)) {
438
+ headers.set(key, value);
570
439
  }
571
- };
572
- }
573
- try {
574
- const body = options.body ? options.body.parse(internalCtx.body) : internalCtx.body;
575
- internalCtx = {
576
- ...internalCtx,
577
- body: body ? {
578
- ...body,
579
- ...internalCtx.body
580
- } : internalCtx.body
581
- };
582
- internalCtx.query = options.query ? options.query.parse(internalCtx.query) : internalCtx.query;
583
- } catch (e) {
584
- if (e instanceof import_zod.ZodError) {
585
- throw new APIError("BAD_REQUEST", {
586
- message: e.message,
587
- details: e.errors
440
+ return new Response(null, {
441
+ status: e.status,
442
+ headers
588
443
  });
589
444
  }
590
445
  throw e;
591
- }
592
- if (options.requireHeaders && !internalCtx.headers) {
593
- throw new APIError("BAD_REQUEST", {
594
- message: "Headers are required"
595
- });
596
- }
597
- if (options.requireRequest && !internalCtx.request) {
598
- throw new APIError("BAD_REQUEST", {
599
- message: "Request is required"
600
- });
601
- }
602
- try {
603
- let res = await handler(internalCtx);
604
- let actualResponse = res;
605
- if (res && typeof res === "object" && "_flag" in res) {
606
- if (res._flag === "json" && internalCtx._flag === "router") {
607
- const h = res.response.headers;
608
- Object.keys(h || {}).forEach((key) => {
609
- responseHeader.set(key, h[key]);
610
- });
611
- responseHeader.set("Content-Type", "application/json");
612
- actualResponse = new Response(JSON.stringify(res.response.body), {
613
- status: res.response.status ?? 200,
614
- statusText: res.response.statusText,
615
- headers: responseHeader
616
- });
617
- } else {
618
- actualResponse = res.body;
619
- }
620
- }
621
- responseHeader = new Headers();
622
- return actualResponse;
623
- } catch (e) {
624
- if (e instanceof APIError) {
625
- responseHeader.set("Content-Type", "application/json");
626
- e.headers = responseHeader;
627
- responseHeader = new Headers();
628
- throw e;
629
- }
630
- throw e;
631
- }
446
+ });
447
+ response = createResponse(handlerResponse, response);
448
+ const res = asResponse ? response : handlerResponse;
449
+ return res;
632
450
  };
633
- handle.path = path;
634
- handle.options = options;
635
- handle.method = options.method;
636
- handle.headers = responseHeader;
637
- return handle;
638
- }
639
-
640
- // src/router.ts
641
- var import_rou3 = require("rou3");
451
+ internalHandler.path = path;
452
+ internalHandler.options = options;
453
+ return internalHandler;
454
+ };
642
455
 
643
- // src/utils.ts
644
456
  async function getBody(request) {
645
457
  const contentType = request.headers.get("content-type") || "";
646
458
  if (!request.body) {
@@ -680,78 +492,22 @@ async function getBody(request) {
680
492
  }
681
493
  return await request.text();
682
494
  }
683
- function shouldSerialize(body) {
684
- return typeof body === "object" && body !== null && !(body instanceof Blob) && !(body instanceof FormData);
685
- }
686
- var statusCode = {
687
- OK: 200,
688
- CREATED: 201,
689
- ACCEPTED: 202,
690
- NO_CONTENT: 204,
691
- MULTIPLE_CHOICES: 300,
692
- MOVED_PERMANENTLY: 301,
693
- FOUND: 302,
694
- SEE_OTHER: 303,
695
- NOT_MODIFIED: 304,
696
- TEMPORARY_REDIRECT: 307,
697
- BAD_REQUEST: 400,
698
- UNAUTHORIZED: 401,
699
- PAYMENT_REQUIRED: 402,
700
- FORBIDDEN: 403,
701
- NOT_FOUND: 404,
702
- METHOD_NOT_ALLOWED: 405,
703
- NOT_ACCEPTABLE: 406,
704
- PROXY_AUTHENTICATION_REQUIRED: 407,
705
- REQUEST_TIMEOUT: 408,
706
- CONFLICT: 409,
707
- GONE: 410,
708
- LENGTH_REQUIRED: 411,
709
- PRECONDITION_FAILED: 412,
710
- PAYLOAD_TOO_LARGE: 413,
711
- URI_TOO_LONG: 414,
712
- UNSUPPORTED_MEDIA_TYPE: 415,
713
- RANGE_NOT_SATISFIABLE: 416,
714
- EXPECTATION_FAILED: 417,
715
- "I'M_A_TEAPOT": 418,
716
- MISDIRECTED_REQUEST: 421,
717
- UNPROCESSABLE_ENTITY: 422,
718
- LOCKED: 423,
719
- FAILED_DEPENDENCY: 424,
720
- TOO_EARLY: 425,
721
- UPGRADE_REQUIRED: 426,
722
- PRECONDITION_REQUIRED: 428,
723
- TOO_MANY_REQUESTS: 429,
724
- REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
725
- UNAVAILABLE_FOR_LEGAL_REASONS: 451,
726
- INTERNAL_SERVER_ERROR: 500,
727
- NOT_IMPLEMENTED: 501,
728
- BAD_GATEWAY: 502,
729
- SERVICE_UNAVAILABLE: 503,
730
- GATEWAY_TIMEOUT: 504,
731
- HTTP_VERSION_NOT_SUPPORTED: 505,
732
- VARIANT_ALSO_NEGOTIATES: 506,
733
- INSUFFICIENT_STORAGE: 507,
734
- LOOP_DETECTED: 508,
735
- NOT_EXTENDED: 510,
736
- NETWORK_AUTHENTICATION_REQUIRED: 511
737
- };
738
495
 
739
- // src/router.ts
740
- var createRouter = (endpoints, config) => {
496
+ const createRouter = (endpoints, config) => {
741
497
  const _endpoints = Object.values(endpoints);
742
- const router = (0, import_rou3.createRouter)();
498
+ const router = rou3.createRouter();
743
499
  for (const endpoint of _endpoints) {
744
500
  if (Array.isArray(endpoint.options?.method)) {
745
501
  for (const method of endpoint.options.method) {
746
- (0, import_rou3.addRoute)(router, method, endpoint.path, endpoint);
502
+ rou3.addRoute(router, method, endpoint.path, endpoint);
747
503
  }
748
504
  } else {
749
- (0, import_rou3.addRoute)(router, endpoint.options.method, endpoint.path, endpoint);
505
+ rou3.addRoute(router, endpoint.options.method, endpoint.path, endpoint);
750
506
  }
751
507
  }
752
- const middlewareRouter = (0, import_rou3.createRouter)();
508
+ const middlewareRouter = rou3.createRouter();
753
509
  for (const route of config?.routerMiddleware || []) {
754
- (0, import_rou3.addRoute)(middlewareRouter, "*", route.path, route.middleware);
510
+ rou3.addRoute(middlewareRouter, "*", route.path, route.middleware);
755
511
  }
756
512
  const handler = async (request) => {
757
513
  const url = new URL(request.url);
@@ -770,12 +526,12 @@ var createRouter = (endpoints, config) => {
770
526
  });
771
527
  }
772
528
  const method = request.method;
773
- const route = (0, import_rou3.findRoute)(router, method, path);
529
+ const route = rou3.findRoute(router, method, path);
774
530
  const handler2 = route?.data;
775
531
  const body = await getBody(request);
776
532
  const headers = request.headers;
777
533
  const query = Object.fromEntries(url.searchParams);
778
- const routerMiddleware = (0, import_rou3.findAllRoutes)(middlewareRouter, "*", path);
534
+ const routerMiddleware = rou3.findAllRoutes(middlewareRouter, "*", path);
779
535
  if (!handler2) {
780
536
  return new Response(null, {
781
537
  status: 404,
@@ -823,18 +579,17 @@ var createRouter = (endpoints, config) => {
823
579
  request,
824
580
  body,
825
581
  query,
826
- _flag: "router",
827
582
  context: {
828
583
  ...middlewareContext,
829
584
  ...config?.extraContext
830
- }
585
+ },
586
+ asResponse: true
831
587
  });
832
588
  if (handlerRes instanceof Response) {
833
589
  return handlerRes;
834
590
  }
835
- const resBody = shouldSerialize(handlerRes) ? JSON.stringify(handlerRes) : handlerRes;
836
- return new Response(resBody, {
837
- headers: handler2.headers
591
+ return new Response(handlerRes ? JSON.stringify(handlerRes) : void 0, {
592
+ status: 200
838
593
  });
839
594
  } catch (e) {
840
595
  if (config?.onError) {
@@ -844,11 +599,16 @@ var createRouter = (endpoints, config) => {
844
599
  }
845
600
  }
846
601
  if (e instanceof APIError) {
847
- return new Response(e.body ? JSON.stringify(e.body) : null, {
848
- status: statusCode[e.status],
849
- statusText: e.status,
850
- headers: e.headers
851
- });
602
+ return new Response(
603
+ e.message ? JSON.stringify({
604
+ message: e.message,
605
+ code: e.code
606
+ }) : null,
607
+ {
608
+ status: e.status,
609
+ headers: e.headers
610
+ }
611
+ );
852
612
  }
853
613
  if (config?.throwError) {
854
614
  throw e;
@@ -860,24 +620,11 @@ var createRouter = (endpoints, config) => {
860
620
  }
861
621
  };
862
622
  return {
863
- handler: async (request) => {
864
- const onReq = await config?.onRequest?.(request);
865
- if (onReq instanceof Response) {
866
- return onReq;
867
- }
868
- const req = onReq instanceof Request ? onReq : request;
869
- const res = await handler(req);
870
- const onRes = await config?.onResponse?.(res);
871
- if (onRes instanceof Response) {
872
- return onRes;
873
- }
874
- return res;
875
- },
623
+ handler,
876
624
  endpoints
877
625
  };
878
626
  };
879
627
 
880
- // src/middleware.ts
881
628
  function createMiddleware(optionsOrHandler, handler) {
882
629
  if (typeof optionsOrHandler === "function") {
883
630
  return createEndpoint(
@@ -901,202 +648,20 @@ function createMiddleware(optionsOrHandler, handler) {
901
648
  );
902
649
  return endpoint;
903
650
  }
904
- var createMiddlewareCreator = (opts) => {
905
- function fn(optionsOrHandler, handler) {
906
- if (typeof optionsOrHandler === "function") {
907
- return createEndpoint(
908
- "*",
909
- {
910
- method: "*"
911
- },
912
- optionsOrHandler
913
- );
914
- }
915
- if (!handler) {
916
- throw new Error("Middleware handler is required");
917
- }
918
- const endpoint = createEndpoint(
919
- "*",
920
- {
921
- ...optionsOrHandler,
922
- method: "*"
923
- },
924
- handler
925
- );
926
- return endpoint;
927
- }
928
- return fn;
929
- };
930
-
931
- // src/types.ts
932
- var import_zod2 = require("zod");
933
-
934
- // src/adapter/node.ts
935
- var import_node_http2 = require("http");
936
-
937
- // src/adapter/request.ts
938
- var import_node_http = require("http");
939
- var set_cookie_parser = __toESM(require_set_cookie(), 1);
940
- function get_raw_body(req, body_size_limit) {
941
- const h = req.headers;
942
- if (!h["content-type"]) return null;
943
- const content_length = Number(h["content-length"]);
944
- if (req.httpVersionMajor === 1 && isNaN(content_length) && h["transfer-encoding"] == null || content_length === 0) {
945
- return null;
946
- }
947
- let length = content_length;
948
- if (body_size_limit) {
949
- if (!length) {
950
- length = body_size_limit;
951
- } else if (length > body_size_limit) {
952
- throw Error(
953
- `Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
954
- );
955
- }
956
- }
957
- if (req.destroyed) {
958
- const readable = new ReadableStream();
959
- readable.cancel();
960
- return readable;
961
- }
962
- let size = 0;
963
- let cancelled = false;
964
- return new ReadableStream({
965
- start(controller) {
966
- req.on("error", (error) => {
967
- cancelled = true;
968
- controller.error(error);
969
- });
970
- req.on("end", () => {
971
- if (cancelled) return;
972
- controller.close();
973
- });
974
- req.on("data", (chunk) => {
975
- if (cancelled) return;
976
- size += chunk.length;
977
- if (size > length) {
978
- cancelled = true;
979
- controller.error(
980
- new Error(
981
- `request body size exceeded ${content_length ? "'content-length'" : "BODY_SIZE_LIMIT"} of ${length}`
982
- )
983
- );
984
- return;
985
- }
986
- controller.enqueue(chunk);
987
- if (controller.desiredSize === null || controller.desiredSize <= 0) {
988
- req.pause();
989
- }
990
- });
991
- },
992
- pull() {
993
- req.resume();
994
- },
995
- cancel(reason) {
996
- cancelled = true;
997
- req.destroy(reason);
998
- }
999
- });
1000
- }
1001
- function getRequest({
1002
- request,
1003
- base,
1004
- bodySizeLimit
1005
- }) {
1006
- return new Request(base + request.url, {
1007
- // @ts-expect-error
1008
- duplex: "half",
1009
- method: request.method,
1010
- body: get_raw_body(request, bodySizeLimit),
1011
- headers: request.headers
1012
- });
1013
- }
1014
- async function setResponse(res, response) {
1015
- for (const [key, value] of response.headers) {
1016
- try {
1017
- res.setHeader(
1018
- key,
1019
- key === "set-cookie" ? set_cookie_parser.splitCookiesString(response.headers.get(key)) : value
1020
- );
1021
- } catch (error) {
1022
- res.getHeaderNames().forEach((name) => res.removeHeader(name));
1023
- res.writeHead(500).end(String(error));
1024
- return;
1025
- }
1026
- }
1027
- res.writeHead(response.status);
1028
- if (!response.body) {
1029
- res.end();
1030
- return;
1031
- }
1032
- if (response.body.locked) {
1033
- res.end(
1034
- "Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()')."
1035
- );
1036
- return;
1037
- }
1038
- const reader = response.body.getReader();
1039
- if (res.destroyed) {
1040
- reader.cancel();
1041
- return;
1042
- }
1043
- const cancel = (error) => {
1044
- res.off("close", cancel);
1045
- res.off("error", cancel);
1046
- reader.cancel(error).catch(() => {
1047
- });
1048
- if (error) res.destroy(error);
1049
- };
1050
- res.on("close", cancel);
1051
- res.on("error", cancel);
1052
- next();
1053
- async function next() {
1054
- try {
1055
- for (; ; ) {
1056
- const { done, value } = await reader.read();
1057
- if (done) break;
1058
- if (!res.write(value)) {
1059
- res.once("drain", next);
1060
- return;
1061
- }
1062
- }
1063
- res.end();
1064
- } catch (error) {
1065
- cancel(error instanceof Error ? error : new Error(String(error)));
1066
- }
1067
- }
1068
- }
1069
651
 
1070
- // src/adapter/node.ts
1071
- function toNodeHandler(handler) {
1072
- return async (req, res) => {
1073
- const protocol = req.connection?.encrypted ? "https" : "http";
1074
- const base = `${protocol}://${req.headers[":authority"] || req.headers.host}`;
1075
- const response = await handler(getRequest({ base, request: req }));
1076
- setResponse(res, response);
1077
- };
1078
- }
1079
- // Annotate the CommonJS export names for ESM import in node:
1080
- 0 && (module.exports = {
1081
- APIError,
1082
- createEndpoint,
1083
- createEndpointCreator,
1084
- createMiddleware,
1085
- createMiddlewareCreator,
1086
- createRouter,
1087
- getBody,
1088
- getCookie,
1089
- getRequest,
1090
- getSignedCookie,
1091
- parse,
1092
- parseSigned,
1093
- serialize,
1094
- serializeSigned,
1095
- setCookie,
1096
- setResponse,
1097
- setSignedCookie,
1098
- shouldSerialize,
1099
- statusCode,
1100
- toNodeHandler
1101
- });
1102
- //# sourceMappingURL=index.cjs.map
652
+ exports.createEndpoint = createEndpoint;
653
+ exports.createGetHeader = createGetHeader;
654
+ exports.createJSON = createJSON;
655
+ exports.createMiddleware = createMiddleware;
656
+ exports.createRouter = createRouter;
657
+ exports.createSetHeader = createSetHeader;
658
+ exports.fromError = fromError;
659
+ exports.getCookie = getCookie;
660
+ exports.getSignedCookie = getSignedCookie;
661
+ exports.parse = parse;
662
+ exports.parseSigned = parseSigned;
663
+ exports.runValidation = runValidation;
664
+ exports.serialize = serialize;
665
+ exports.serializeSigned = serializeSigned;
666
+ exports.setCookie = setCookie;
667
+ exports.setSignedCookie = setSignedCookie;