better-call 0.2.13-beta.8 → 0.2.13

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,187 +1,297 @@
1
- 'use strict';
2
-
3
- const crypto = require('uncrypto');
4
- const zodToOpenapi = require('@asteasolutions/zod-to-openapi');
5
- const zod = require('zod');
6
- const rou3 = require('rou3');
7
-
8
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
9
-
10
- const crypto__default = /*#__PURE__*/_interopDefaultCompat(crypto);
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);
11
34
 
12
- function runValidation(options, context) {
13
- let request = {
14
- body: void 0,
15
- query: void 0
16
- };
17
- if (options.body) {
18
- const result = options.body.safeParse(context.body);
19
- if (result.error) {
20
- return {
21
- data: null,
22
- error: fromError(result.error)
23
- };
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
43
+ };
44
+ function isNonEmptyString(str) {
45
+ return typeof str === "string" && !!str.trim();
24
46
  }
25
- request.body = result.data;
26
- }
27
- if (options.query) {
28
- const result = options.query.safeParse(context.query);
29
- if (result.error) {
30
- return {
31
- data: null,
32
- error: fromError(result.error)
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
33
65
  };
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;
34
87
  }
35
- request.query = result.data;
36
- }
37
- if (options.requireHeaders && !(context.headers instanceof Headers)) {
38
- return {
39
- data: null,
40
- error: { message: "Validation Error: Headers are required" }
41
- };
42
- }
43
- if (options.requireRequest && !context.request) {
44
- return {
45
- data: null,
46
- error: { message: "Validation Error: Request is required" }
47
- };
48
- }
49
- return {
50
- data: request,
51
- error: null
52
- };
53
- }
54
- function fromError(error) {
55
- const errorMessages = [];
56
- for (const issue of error.issues) {
57
- const path = issue.path.join(".");
58
- const message = issue.message;
59
- if (path) {
60
- errorMessages.push(`${message} at "${path}"`);
61
- } else {
62
- errorMessages.push(message);
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 };
63
99
  }
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
+ }
142
+ }
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;
197
+ }
198
+ module2.exports = parse2;
199
+ module2.exports.parse = parse2;
200
+ module2.exports.parseString = parseString;
201
+ module2.exports.splitCookiesString = splitCookiesString2;
64
202
  }
65
- return {
66
- message: `Validation error: ${errorMessages.join(", ")}`
67
- };
68
- }
203
+ });
69
204
 
70
- function createSetHeader(headers) {
71
- return (key, value) => {
72
- headers.set(key, value);
73
- };
74
- }
75
- function createGetHeader(headers) {
76
- return (key) => {
77
- return headers.get(key);
78
- };
79
- }
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);
80
230
 
81
- const _statusCode = {
82
- OK: 200,
83
- CREATED: 201,
84
- ACCEPTED: 202,
85
- NO_CONTENT: 204,
86
- MULTIPLE_CHOICES: 300,
87
- MOVED_PERMANENTLY: 301,
88
- FOUND: 302,
89
- SEE_OTHER: 303,
90
- NOT_MODIFIED: 304,
91
- TEMPORARY_REDIRECT: 307,
92
- BAD_REQUEST: 400,
93
- UNAUTHORIZED: 401,
94
- PAYMENT_REQUIRED: 402,
95
- FORBIDDEN: 403,
96
- NOT_FOUND: 404,
97
- METHOD_NOT_ALLOWED: 405,
98
- NOT_ACCEPTABLE: 406,
99
- PROXY_AUTHENTICATION_REQUIRED: 407,
100
- REQUEST_TIMEOUT: 408,
101
- CONFLICT: 409,
102
- GONE: 410,
103
- LENGTH_REQUIRED: 411,
104
- PRECONDITION_FAILED: 412,
105
- PAYLOAD_TOO_LARGE: 413,
106
- URI_TOO_LONG: 414,
107
- UNSUPPORTED_MEDIA_TYPE: 415,
108
- RANGE_NOT_SATISFIABLE: 416,
109
- EXPECTATION_FAILED: 417,
110
- "I'M_A_TEAPOT": 418,
111
- MISDIRECTED_REQUEST: 421,
112
- UNPROCESSABLE_ENTITY: 422,
113
- LOCKED: 423,
114
- FAILED_DEPENDENCY: 424,
115
- TOO_EARLY: 425,
116
- UPGRADE_REQUIRED: 426,
117
- PRECONDITION_REQUIRED: 428,
118
- TOO_MANY_REQUESTS: 429,
119
- REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
120
- UNAVAILABLE_FOR_LEGAL_REASONS: 451,
121
- INTERNAL_SERVER_ERROR: 500,
122
- NOT_IMPLEMENTED: 501,
123
- BAD_GATEWAY: 502,
124
- SERVICE_UNAVAILABLE: 503,
125
- GATEWAY_TIMEOUT: 504,
126
- HTTP_VERSION_NOT_SUPPORTED: 505,
127
- VARIANT_ALSO_NEGOTIATES: 506,
128
- INSUFFICIENT_STORAGE: 507,
129
- LOOP_DETECTED: 508,
130
- NOT_EXTENDED: 510,
131
- NETWORK_AUTHENTICATION_REQUIRED: 511
132
- };
133
- class APIError extends Error {
134
- constructor(status = "INTERNAL_SERVER_ERROR", body = void 0, headers = {}, statusCode = _statusCode[status]) {
135
- super(body?.message || status);
136
- this.status = status;
137
- this.body = body;
138
- this.headers = headers;
139
- this.statusCode = statusCode;
140
- this.name = "APIError";
231
+ // src/endpoint.ts
232
+ var import_zod = require("zod");
233
+
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");
141
243
  this.status = status;
142
- this.headers = headers;
143
- this.statusCode = statusCode;
244
+ this.body = body ?? {};
144
245
  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";
145
251
  }
146
- }
252
+ };
147
253
 
148
- const algorithm = { name: "HMAC", hash: "SHA-256" };
149
- const getCryptoKey = async (secret) => {
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
+ };
267
+
268
+ // src/cookie.ts
269
+ var import_uncrypto = require("uncrypto");
270
+ var algorithm = { name: "HMAC", hash: "SHA-256" };
271
+ var getCryptoKey = async (secret) => {
150
272
  const secretBuf = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
151
- return await crypto__default.subtle.importKey("raw", secretBuf, algorithm, false, [
152
- "sign",
153
- "verify"
154
- ]);
273
+ return await import_uncrypto.subtle.importKey("raw", secretBuf, algorithm, false, ["sign", "verify"]);
155
274
  };
156
- const makeSignature = async (value, secret) => {
275
+ var makeSignature = async (value, secret) => {
157
276
  const key = await getCryptoKey(secret);
158
- const signature = await crypto__default.subtle.sign(
159
- algorithm.name,
160
- key,
161
- new TextEncoder().encode(value)
162
- );
277
+ const signature = await import_uncrypto.subtle.sign(algorithm.name, key, new TextEncoder().encode(value));
163
278
  return btoa(String.fromCharCode(...new Uint8Array(signature)));
164
279
  };
165
- const verifySignature = async (base64Signature, value, secret) => {
280
+ var verifySignature = async (base64Signature, value, secret) => {
166
281
  try {
167
282
  const signatureBinStr = atob(base64Signature);
168
283
  const signature = new Uint8Array(signatureBinStr.length);
169
284
  for (let i = 0, len = signatureBinStr.length; i < len; i++) {
170
285
  signature[i] = signatureBinStr.charCodeAt(i);
171
286
  }
172
- return await crypto__default.subtle.verify(
173
- algorithm,
174
- secret,
175
- signature,
176
- new TextEncoder().encode(value)
177
- );
287
+ return await import_uncrypto.subtle.verify(algorithm, secret, signature, new TextEncoder().encode(value));
178
288
  } catch (e) {
179
289
  return false;
180
290
  }
181
291
  };
182
- const validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
183
- const validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/;
184
- const parse = (cookie, name) => {
292
+ var validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
293
+ var validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/;
294
+ var parse = (cookie, name) => {
185
295
  const pairs = cookie.trim().split(";");
186
296
  return pairs.reduce((parsedCookie, pairStr) => {
187
297
  pairStr = pairStr.trim();
@@ -203,7 +313,7 @@ const parse = (cookie, name) => {
203
313
  return parsedCookie;
204
314
  }, {});
205
315
  };
206
- const parseSigned = async (cookie, secret, name) => {
316
+ var parseSigned = async (cookie, secret, name) => {
207
317
  const parsedCookie = {};
208
318
  const secretKey = await getCryptoKey(secret);
209
319
  for (const [key, value] of Object.entries(parse(cookie, name))) {
@@ -221,7 +331,7 @@ const parseSigned = async (cookie, secret, name) => {
221
331
  }
222
332
  return parsedCookie;
223
333
  };
224
- const _serialize = (name, value, opt = {}) => {
334
+ var _serialize = (name, value, opt = {}) => {
225
335
  let cookie = `${name}=${value}`;
226
336
  if (name.startsWith("__Secure-") && !opt.secure) {
227
337
  opt.secure = true;
@@ -276,18 +386,19 @@ const _serialize = (name, value, opt = {}) => {
276
386
  }
277
387
  return cookie;
278
388
  };
279
- const serialize = (name, value, opt) => {
389
+ var serialize = (name, value, opt) => {
280
390
  value = encodeURIComponent(value);
281
391
  return _serialize(name, value, opt);
282
392
  };
283
- const serializeSigned = async (name, value, secret, opt = {}) => {
393
+ var serializeSigned = async (name, value, secret, opt = {}) => {
284
394
  const signature = await makeSignature(value, secret);
285
395
  value = `${value}.${signature}`;
286
396
  value = encodeURIComponent(value);
287
397
  return _serialize(name, value, opt);
288
398
  };
289
399
 
290
- const getCookie = (cookie, key, prefix) => {
400
+ // src/cookie-utils.ts
401
+ var getCookie = (cookie, key, prefix) => {
291
402
  if (!cookie) {
292
403
  return void 0;
293
404
  }
@@ -304,23 +415,17 @@ const getCookie = (cookie, key, prefix) => {
304
415
  const obj = parse(cookie, finalKey);
305
416
  return obj[finalKey];
306
417
  };
307
- const setCookie = (header, name, value, opt) => {
418
+ var setCookie = (header, name, value, opt) => {
308
419
  const existingCookies = header.get("Set-Cookie");
309
420
  if (existingCookies) {
310
421
  const cookies = existingCookies.split(", ");
311
- const updatedCookies = cookies.filter(
312
- (cookie2) => !cookie2.startsWith(`${name}=`)
313
- );
422
+ const updatedCookies = cookies.filter((cookie2) => !cookie2.startsWith(`${name}=`));
314
423
  header.delete("Set-Cookie");
315
424
  updatedCookies.forEach((cookie2) => header.append("Set-Cookie", cookie2));
316
425
  }
317
426
  let cookie;
318
427
  if (opt?.prefix === "secure") {
319
- cookie = serialize("__Secure-" + name, value, {
320
- path: "/",
321
- ...opt,
322
- secure: true
323
- });
428
+ cookie = serialize("__Secure-" + name, value, { path: "/", ...opt, secure: true });
324
429
  } else if (opt?.prefix === "host") {
325
430
  cookie = serialize("__Host-" + name, value, {
326
431
  ...opt,
@@ -333,7 +438,7 @@ const setCookie = (header, name, value, opt) => {
333
438
  }
334
439
  header.append("Set-Cookie", cookie);
335
440
  };
336
- const setSignedCookie = async (header, name, value, secret, opt) => {
441
+ var setSignedCookie = async (header, name, value, secret, opt) => {
337
442
  let cookie;
338
443
  if (opt?.prefix === "secure") {
339
444
  cookie = await serializeSigned("__Secure-" + name, value, secret, {
@@ -353,7 +458,7 @@ const setSignedCookie = async (header, name, value, secret, opt) => {
353
458
  }
354
459
  header.append("Set-Cookie", cookie);
355
460
  };
356
- const getSignedCookie = async (header, secret, key, prefix) => {
461
+ var getSignedCookie = async (header, secret, key, prefix) => {
357
462
  const cookie = header.get("cookie");
358
463
  if (!cookie) {
359
464
  return void 0;
@@ -370,204 +475,163 @@ const getSignedCookie = async (header, secret, key, prefix) => {
370
475
  return obj[finalKey];
371
476
  };
372
477
 
373
- function paramToZod(path) {
374
- const parts = path.split("/");
375
- const params = parts.filter((part) => part.startsWith(":"));
376
- const zod$1 = zod.z.object({});
377
- for (const param of params) {
378
- zod$1.merge(zod.z.object({ [param.slice(1)]: zod.z.string() }));
379
- }
380
- return zod$1;
381
- }
382
-
383
- zodToOpenapi.extendZodWithOpenApi(zod.z);
384
- const createResponse = (handlerResponse, response) => {
385
- if (handlerResponse instanceof Response) {
386
- response.headers.forEach((value, key) => {
387
- handlerResponse.headers.set(key, value);
388
- });
389
- return handlerResponse;
390
- } else if (handlerResponse?._flag === "json") {
391
- const responseObj = new Response(
392
- JSON.stringify(
393
- handlerResponse.routerResponse?.body || handlerResponse.body
394
- ),
478
+ // src/endpoint.ts
479
+ function createEndpointCreator(opts) {
480
+ return (path, options, handler) => {
481
+ return createEndpoint(
482
+ path,
395
483
  {
396
- status: handlerResponse.routerResponse?.status || 200,
397
- headers: handlerResponse.routerResponse?.headers
398
- }
399
- );
400
- response.headers.forEach((value, key) => {
401
- responseObj.headers.set(key, value);
402
- });
403
- return responseObj;
404
- } else {
405
- const responseObj = new Response(
406
- handlerResponse ? JSON.stringify(handlerResponse) : void 0
407
- );
408
- response.headers.forEach((value, key) => {
409
- responseObj.headers.set(key, value);
410
- });
411
- return responseObj;
412
- }
413
- };
414
- const runMiddleware = async (options, context) => {
415
- let finalContext = {};
416
- for (const middleware of options.use || []) {
417
- const result = await middleware(context);
418
- if (result?.context && result._flag === "context") {
419
- context = { ...context, ...result.context };
420
- } else {
421
- finalContext = { ...result, ...finalContext };
422
- context.context = finalContext;
423
- }
424
- }
425
- return finalContext;
426
- };
427
- const createEndpoint = (path, options, handler) => {
428
- const internalHandler = async (...inputCtx) => {
429
- let response = new Response();
430
- const { asResponse, ...ctx } = inputCtx[0] || {};
431
- const { data, error } = runValidation(options, ctx);
432
- if (error) {
433
- throw new APIError("BAD_REQUEST", {
434
- message: error.message
435
- });
436
- }
437
- const context = {
438
- json: (json, routerResponse) => {
439
- if (!asResponse) {
440
- return json;
441
- }
442
- return {
443
- body: json,
444
- routerResponse,
445
- _flag: "json"
446
- };
484
+ ...options,
485
+ use: [...options?.use || [], ...opts?.use || []]
447
486
  },
448
- body: "body" in data ? data.body : void 0,
449
- path,
450
- method: "method" in ctx ? ctx.method : void 0,
451
- query: "query" in data ? data.query : void 0,
452
- params: "params" in ctx ? ctx.params : void 0,
453
- headers: "headers" in ctx ? ctx.headers : void 0,
454
- request: "request" in ctx ? ctx.request : void 0,
455
- setHeader: createSetHeader(response.headers),
456
- getHeader: (key) => {
457
- const requestHeaders = "headers" in ctx && ctx.headers instanceof Headers ? ctx.headers : "request" in ctx && ctx.request instanceof Request ? ctx.request.headers : null;
458
- if (!requestHeaders)
459
- return null;
460
- return requestHeaders.get(key);
487
+ handler
488
+ );
489
+ };
490
+ }
491
+ function createEndpoint(path, options, handler) {
492
+ let responseHeader = new Headers();
493
+ const handle = async (...ctx) => {
494
+ let internalCtx = {
495
+ setHeader(key, value) {
496
+ responseHeader.set(key, value);
461
497
  },
462
- setCookie: (name, value, options2) => {
463
- setCookie(response.headers, name, value, options2);
498
+ setCookie(key, value, options2) {
499
+ setCookie(responseHeader, key, value, options2);
464
500
  },
465
501
  getCookie(key, prefix) {
466
- const headers = context.headers?.get("cookie");
467
- if (!headers)
468
- return void 0;
469
- return getCookie(headers, key, prefix);
502
+ const header = ctx[0]?.headers;
503
+ const cookieH = header?.get("cookie");
504
+ const cookie = getCookie(cookieH || "", key, prefix);
505
+ return cookie;
470
506
  },
471
- setSignedCookie(key, value, secret, options2) {
472
- return setSignedCookie(response.headers, key, value, secret, options2);
507
+ getSignedCookie(key, secret, prefix) {
508
+ const header = ctx[0]?.headers;
509
+ if (!header) {
510
+ throw new TypeError("Headers are required");
511
+ }
512
+ const cookie = getSignedCookie(header, secret, key, prefix);
513
+ return cookie;
473
514
  },
474
- async getSignedCookie(key, secret, prefix) {
475
- const headers = context.headers;
476
- if (!headers)
477
- return void 0;
478
- return getSignedCookie(headers, secret, key, prefix);
515
+ async setSignedCookie(key, value, secret, options2) {
516
+ await setSignedCookie(responseHeader, key, value, secret, options2);
479
517
  },
480
- redirect: (url) => {
481
- const apiError = new APIError("FOUND", void 0, {
482
- Location: url,
483
- ...response.headers
484
- });
485
- return apiError;
518
+ redirect(url) {
519
+ responseHeader.set("Location", url);
520
+ return new APIError("FOUND");
486
521
  },
487
- context: {}
522
+ json,
523
+ context: ctx[0]?.context || {},
524
+ _flag: ctx[0]?.asResponse ? "router" : ctx[0]?._flag,
525
+ responseHeader,
526
+ path,
527
+ ...ctx[0] || {}
488
528
  };
489
- const finalContext = await runMiddleware(options, context);
490
- context.context = finalContext;
491
- const handlerResponse = await handler(context).catch((e) => {
492
- if (e instanceof APIError && asResponse) {
493
- const headers = response.headers;
494
- for (const [key, value] of Object.entries(e.headers)) {
495
- headers.set(key, value);
529
+ if (options.use?.length) {
530
+ let middlewareContexts = {};
531
+ let middlewareBody = {};
532
+ for (const middleware of options.use) {
533
+ if (typeof middleware !== "function") {
534
+ console.warn("Middleware is not a function", {
535
+ middleware
536
+ });
537
+ continue;
538
+ }
539
+ const res = await middleware(internalCtx);
540
+ if (res) {
541
+ const body = res.options?.body ? res.options.body.parse(internalCtx.body) : void 0;
542
+ middlewareContexts = {
543
+ ...middlewareContexts,
544
+ ...res
545
+ };
546
+ middlewareBody = {
547
+ ...middlewareBody,
548
+ ...body
549
+ };
496
550
  }
497
- return new Response(null, {
498
- status: e.statusCode,
499
- headers
500
- });
501
551
  }
502
- throw e;
503
- });
504
- response = createResponse(handlerResponse, response);
505
- const res = asResponse ? response : handlerResponse;
506
- return res;
507
- };
508
- internalHandler.path = path;
509
- internalHandler.options = options;
510
- const registry = new zodToOpenapi.OpenAPIRegistry();
511
- registry.registerPath({
512
- path,
513
- method: Array.isArray(options.method) ? options.method[0].toLowerCase() : options.method.toLowerCase(),
514
- request: {
515
- ...options.body ? {
552
+ internalCtx = {
553
+ ...internalCtx,
516
554
  body: {
517
- content: {
518
- "application/json": {
519
- schema: options.body
520
- }
521
- }
522
- }
523
- } : {},
524
- ...options.query ? {
525
- query: options.query
526
- } : {},
527
- params: paramToZod(path)
528
- },
529
- responses: {
530
- 200: {
531
- description: "Successful response",
532
- content: {
533
- "application/json": {
534
- schema: zod.z.record(zod.z.unknown())
535
- }
555
+ ...middlewareBody,
556
+ ...internalCtx.body
557
+ },
558
+ context: {
559
+ ...internalCtx.context || {},
560
+ ...middlewareContexts
536
561
  }
537
- },
538
- 400: {
539
- description: "Bad request",
540
- content: {
541
- "application/json": {
542
- schema: zod.z.object({
543
- message: zod.z.string()
544
- })
545
- }
562
+ };
563
+ }
564
+ try {
565
+ const body = options.body ? options.body.parse(internalCtx.body) : internalCtx.body;
566
+ internalCtx = {
567
+ ...internalCtx,
568
+ body: body ? {
569
+ ...body,
570
+ ...internalCtx.body
571
+ } : internalCtx.body
572
+ };
573
+ internalCtx.query = options.query ? options.query.parse(internalCtx.query) : internalCtx.query;
574
+ } catch (e) {
575
+ if (e instanceof import_zod.ZodError) {
576
+ throw new APIError("BAD_REQUEST", {
577
+ message: e.message,
578
+ details: e.errors
579
+ });
580
+ }
581
+ throw e;
582
+ }
583
+ if (options.requireHeaders && !internalCtx.headers) {
584
+ throw new APIError("BAD_REQUEST", {
585
+ message: "Headers are required"
586
+ });
587
+ }
588
+ if (options.requireRequest && !internalCtx.request) {
589
+ throw new APIError("BAD_REQUEST", {
590
+ message: "Request is required"
591
+ });
592
+ }
593
+ try {
594
+ let res = await handler(internalCtx);
595
+ let actualResponse = res;
596
+ if (res && typeof res === "object" && "_flag" in res) {
597
+ if (res._flag === "json" && internalCtx._flag === "router") {
598
+ const h = res.response.headers;
599
+ Object.keys(h || {}).forEach((key) => {
600
+ responseHeader.set(key, h[key]);
601
+ });
602
+ responseHeader.set("Content-Type", "application/json");
603
+ actualResponse = new Response(JSON.stringify(res.response.body), {
604
+ status: res.response.status ?? 200,
605
+ statusText: res.response.statusText,
606
+ headers: responseHeader
607
+ });
608
+ } else {
609
+ actualResponse = res.body;
546
610
  }
547
- },
548
- ...options.openAPI?.responses
611
+ }
612
+ responseHeader = new Headers();
613
+ return actualResponse;
614
+ } catch (e) {
615
+ if (e instanceof APIError) {
616
+ responseHeader.set("Content-Type", "application/json");
617
+ e.headers = responseHeader;
618
+ responseHeader = new Headers();
619
+ throw e;
620
+ }
621
+ throw e;
549
622
  }
550
- });
551
- internalHandler.openAPI = {
552
- definitions: registry.definitions
553
- };
554
- return internalHandler;
555
- };
556
- function createEndpointCreator(opts) {
557
- return (path, options, handler) => {
558
- const res = createEndpoint(
559
- path,
560
- {
561
- ...options,
562
- use: [...options?.use || [], ...opts?.use || []]
563
- },
564
- handler
565
- );
566
- return res;
567
623
  };
624
+ handle.path = path;
625
+ handle.options = options;
626
+ handle.method = options.method;
627
+ handle.headers = responseHeader;
628
+ return handle;
568
629
  }
569
- createEndpoint.creator = createEndpointCreator;
570
630
 
631
+ // src/router.ts
632
+ var import_rou3 = require("rou3");
633
+
634
+ // src/utils.ts
571
635
  async function getBody(request) {
572
636
  const contentType = request.headers.get("content-type") || "";
573
637
  if (!request.body) {
@@ -607,22 +671,79 @@ async function getBody(request) {
607
671
  }
608
672
  return await request.text();
609
673
  }
674
+ function shouldSerialize(body) {
675
+ return typeof body === "object" && body !== null && !(body instanceof Blob) && !(body instanceof FormData);
676
+ }
677
+ var statusCode = {
678
+ OK: 200,
679
+ CREATED: 201,
680
+ ACCEPTED: 202,
681
+ NO_CONTENT: 204,
682
+ MULTIPLE_CHOICES: 300,
683
+ MOVED_PERMANENTLY: 301,
684
+ FOUND: 302,
685
+ SEE_OTHER: 303,
686
+ NOT_MODIFIED: 304,
687
+ TEMPORARY_REDIRECT: 307,
688
+ BAD_REQUEST: 400,
689
+ UNAUTHORIZED: 401,
690
+ PAYMENT_REQUIRED: 402,
691
+ FORBIDDEN: 403,
692
+ NOT_FOUND: 404,
693
+ METHOD_NOT_ALLOWED: 405,
694
+ NOT_ACCEPTABLE: 406,
695
+ PROXY_AUTHENTICATION_REQUIRED: 407,
696
+ REQUEST_TIMEOUT: 408,
697
+ CONFLICT: 409,
698
+ GONE: 410,
699
+ LENGTH_REQUIRED: 411,
700
+ PRECONDITION_FAILED: 412,
701
+ PAYLOAD_TOO_LARGE: 413,
702
+ URI_TOO_LONG: 414,
703
+ UNSUPPORTED_MEDIA_TYPE: 415,
704
+ RANGE_NOT_SATISFIABLE: 416,
705
+ EXPECTATION_FAILED: 417,
706
+ "I'M_A_TEAPOT": 418,
707
+ MISDIRECTED_REQUEST: 421,
708
+ UNPROCESSABLE_ENTITY: 422,
709
+ LOCKED: 423,
710
+ FAILED_DEPENDENCY: 424,
711
+ TOO_EARLY: 425,
712
+ UPGRADE_REQUIRED: 426,
713
+ PRECONDITION_REQUIRED: 428,
714
+ TOO_MANY_REQUESTS: 429,
715
+ REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
716
+ UNAVAILABLE_FOR_LEGAL_REASONS: 451,
717
+ INTERNAL_SERVER_ERROR: 500,
718
+ NOT_IMPLEMENTED: 501,
719
+ BAD_GATEWAY: 502,
720
+ SERVICE_UNAVAILABLE: 503,
721
+ GATEWAY_TIMEOUT: 504,
722
+ HTTP_VERSION_NOT_SUPPORTED: 505,
723
+ VARIANT_ALSO_NEGOTIATES: 506,
724
+ INSUFFICIENT_STORAGE: 507,
725
+ LOOP_DETECTED: 508,
726
+ NOT_EXTENDED: 510,
727
+ NETWORK_AUTHENTICATION_REQUIRED: 511
728
+ };
610
729
 
611
- const createRouter = (endpoints, config) => {
730
+ // src/router.ts
731
+ var createRouter = (endpoints, config) => {
612
732
  const _endpoints = Object.values(endpoints);
613
- const router = rou3.createRouter();
733
+ const router = (0, import_rou3.createRouter)();
614
734
  for (const endpoint of _endpoints) {
735
+ if (endpoint.options.metadata?.SERVER_ONLY) continue;
615
736
  if (Array.isArray(endpoint.options?.method)) {
616
737
  for (const method of endpoint.options.method) {
617
- rou3.addRoute(router, method, endpoint.path, endpoint);
738
+ (0, import_rou3.addRoute)(router, method, endpoint.path, endpoint);
618
739
  }
619
740
  } else {
620
- rou3.addRoute(router, endpoint.options.method, endpoint.path, endpoint);
741
+ (0, import_rou3.addRoute)(router, endpoint.options.method, endpoint.path, endpoint);
621
742
  }
622
743
  }
623
- const middlewareRouter = rou3.createRouter();
744
+ const middlewareRouter = (0, import_rou3.createRouter)();
624
745
  for (const route of config?.routerMiddleware || []) {
625
- rou3.addRoute(middlewareRouter, "*", route.path, route.middleware);
746
+ (0, import_rou3.addRoute)(middlewareRouter, "*", route.path, route.middleware);
626
747
  }
627
748
  const handler = async (request) => {
628
749
  const url = new URL(request.url);
@@ -641,12 +762,12 @@ const createRouter = (endpoints, config) => {
641
762
  });
642
763
  }
643
764
  const method = request.method;
644
- const route = rou3.findRoute(router, method, path);
765
+ const route = (0, import_rou3.findRoute)(router, method, path);
645
766
  const handler2 = route?.data;
646
767
  const body = await getBody(request);
647
768
  const headers = request.headers;
648
769
  const query = Object.fromEntries(url.searchParams);
649
- const routerMiddleware = rou3.findAllRoutes(middlewareRouter, "*", path);
770
+ const routerMiddleware = (0, import_rou3.findAllRoutes)(middlewareRouter, "*", path);
650
771
  if (!handler2) {
651
772
  return new Response(null, {
652
773
  status: 404,
@@ -694,17 +815,18 @@ const createRouter = (endpoints, config) => {
694
815
  request,
695
816
  body,
696
817
  query,
818
+ _flag: "router",
697
819
  context: {
698
820
  ...middlewareContext,
699
821
  ...config?.extraContext
700
- },
701
- asResponse: true
822
+ }
702
823
  });
703
824
  if (handlerRes instanceof Response) {
704
825
  return handlerRes;
705
826
  }
706
- return new Response(handlerRes ? JSON.stringify(handlerRes) : void 0, {
707
- status: 200
827
+ const resBody = shouldSerialize(handlerRes) ? JSON.stringify(handlerRes) : handlerRes;
828
+ return new Response(resBody, {
829
+ headers: handler2.headers
708
830
  });
709
831
  } catch (e) {
710
832
  if (config?.onError) {
@@ -715,7 +837,8 @@ const createRouter = (endpoints, config) => {
715
837
  }
716
838
  if (e instanceof APIError) {
717
839
  return new Response(e.body ? JSON.stringify(e.body) : null, {
718
- status: e.statusCode,
840
+ status: statusCode[e.status],
841
+ statusText: e.status,
719
842
  headers: e.headers
720
843
  });
721
844
  }
@@ -729,11 +852,24 @@ const createRouter = (endpoints, config) => {
729
852
  }
730
853
  };
731
854
  return {
732
- handler,
855
+ handler: async (request) => {
856
+ const onReq = await config?.onRequest?.(request);
857
+ if (onReq instanceof Response) {
858
+ return onReq;
859
+ }
860
+ const req = onReq instanceof Request ? onReq : request;
861
+ const res = await handler(req);
862
+ const onRes = await config?.onResponse?.(res);
863
+ if (onRes instanceof Response) {
864
+ return onRes;
865
+ }
866
+ return res;
867
+ },
733
868
  endpoints
734
869
  };
735
870
  };
736
871
 
872
+ // src/middleware.ts
737
873
  function createMiddleware(optionsOrHandler, handler) {
738
874
  if (typeof optionsOrHandler === "function") {
739
875
  return createEndpoint(
@@ -757,34 +893,202 @@ function createMiddleware(optionsOrHandler, handler) {
757
893
  );
758
894
  return endpoint;
759
895
  }
760
- function createMiddlewareCreator(opts) {
761
- return (handler) => {
762
- const res = createMiddleware(
896
+ var createMiddlewareCreator = (opts) => {
897
+ function fn(optionsOrHandler, handler) {
898
+ if (typeof optionsOrHandler === "function") {
899
+ return createEndpoint(
900
+ "*",
901
+ {
902
+ method: "*"
903
+ },
904
+ optionsOrHandler
905
+ );
906
+ }
907
+ if (!handler) {
908
+ throw new Error("Middleware handler is required");
909
+ }
910
+ const endpoint = createEndpoint(
911
+ "*",
763
912
  {
764
- method: "*",
765
- use: opts.use
913
+ ...optionsOrHandler,
914
+ method: "*"
766
915
  },
767
916
  handler
768
917
  );
769
- return res;
918
+ return endpoint;
919
+ }
920
+ return fn;
921
+ };
922
+
923
+ // src/types.ts
924
+ var import_zod2 = require("zod");
925
+
926
+ // src/adapter/node.ts
927
+ var import_node_http2 = require("http");
928
+
929
+ // src/adapter/request.ts
930
+ var import_node_http = require("http");
931
+ var set_cookie_parser = __toESM(require_set_cookie(), 1);
932
+ function get_raw_body(req, body_size_limit) {
933
+ const h = req.headers;
934
+ if (!h["content-type"]) return null;
935
+ const content_length = Number(h["content-length"]);
936
+ if (req.httpVersionMajor === 1 && isNaN(content_length) && h["transfer-encoding"] == null || content_length === 0) {
937
+ return null;
938
+ }
939
+ let length = content_length;
940
+ if (body_size_limit) {
941
+ if (!length) {
942
+ length = body_size_limit;
943
+ } else if (length > body_size_limit) {
944
+ throw Error(
945
+ `Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
946
+ );
947
+ }
948
+ }
949
+ if (req.destroyed) {
950
+ const readable = new ReadableStream();
951
+ readable.cancel();
952
+ return readable;
953
+ }
954
+ let size = 0;
955
+ let cancelled = false;
956
+ return new ReadableStream({
957
+ start(controller) {
958
+ req.on("error", (error) => {
959
+ cancelled = true;
960
+ controller.error(error);
961
+ });
962
+ req.on("end", () => {
963
+ if (cancelled) return;
964
+ controller.close();
965
+ });
966
+ req.on("data", (chunk) => {
967
+ if (cancelled) return;
968
+ size += chunk.length;
969
+ if (size > length) {
970
+ cancelled = true;
971
+ controller.error(
972
+ new Error(
973
+ `request body size exceeded ${content_length ? "'content-length'" : "BODY_SIZE_LIMIT"} of ${length}`
974
+ )
975
+ );
976
+ return;
977
+ }
978
+ controller.enqueue(chunk);
979
+ if (controller.desiredSize === null || controller.desiredSize <= 0) {
980
+ req.pause();
981
+ }
982
+ });
983
+ },
984
+ pull() {
985
+ req.resume();
986
+ },
987
+ cancel(reason) {
988
+ cancelled = true;
989
+ req.destroy(reason);
990
+ }
991
+ });
992
+ }
993
+ function getRequest({
994
+ request,
995
+ base,
996
+ bodySizeLimit
997
+ }) {
998
+ return new Request(base + request.url, {
999
+ // @ts-expect-error
1000
+ duplex: "half",
1001
+ method: request.method,
1002
+ body: get_raw_body(request, bodySizeLimit),
1003
+ headers: request.headers
1004
+ });
1005
+ }
1006
+ async function setResponse(res, response) {
1007
+ for (const [key, value] of response.headers) {
1008
+ try {
1009
+ res.setHeader(
1010
+ key,
1011
+ key === "set-cookie" ? set_cookie_parser.splitCookiesString(response.headers.get(key)) : value
1012
+ );
1013
+ } catch (error) {
1014
+ res.getHeaderNames().forEach((name) => res.removeHeader(name));
1015
+ res.writeHead(500).end(String(error));
1016
+ return;
1017
+ }
1018
+ }
1019
+ res.writeHead(response.status);
1020
+ if (!response.body) {
1021
+ res.end();
1022
+ return;
1023
+ }
1024
+ if (response.body.locked) {
1025
+ res.end(
1026
+ "Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()')."
1027
+ );
1028
+ return;
1029
+ }
1030
+ const reader = response.body.getReader();
1031
+ if (res.destroyed) {
1032
+ reader.cancel();
1033
+ return;
1034
+ }
1035
+ const cancel = (error) => {
1036
+ res.off("close", cancel);
1037
+ res.off("error", cancel);
1038
+ reader.cancel(error).catch(() => {
1039
+ });
1040
+ if (error) res.destroy(error);
770
1041
  };
1042
+ res.on("close", cancel);
1043
+ res.on("error", cancel);
1044
+ next();
1045
+ async function next() {
1046
+ try {
1047
+ for (; ; ) {
1048
+ const { done, value } = await reader.read();
1049
+ if (done) break;
1050
+ if (!res.write(value)) {
1051
+ res.once("drain", next);
1052
+ return;
1053
+ }
1054
+ }
1055
+ res.end();
1056
+ } catch (error) {
1057
+ cancel(error instanceof Error ? error : new Error(String(error)));
1058
+ }
1059
+ }
771
1060
  }
772
- createMiddleware.creator = createMiddlewareCreator;
773
1061
 
774
- exports.APIError = APIError;
775
- exports._statusCode = _statusCode;
776
- exports.createEndpoint = createEndpoint;
777
- exports.createGetHeader = createGetHeader;
778
- exports.createMiddleware = createMiddleware;
779
- exports.createRouter = createRouter;
780
- exports.createSetHeader = createSetHeader;
781
- exports.fromError = fromError;
782
- exports.getCookie = getCookie;
783
- exports.getSignedCookie = getSignedCookie;
784
- exports.parse = parse;
785
- exports.parseSigned = parseSigned;
786
- exports.runValidation = runValidation;
787
- exports.serialize = serialize;
788
- exports.serializeSigned = serializeSigned;
789
- exports.setCookie = setCookie;
790
- exports.setSignedCookie = setSignedCookie;
1062
+ // src/adapter/node.ts
1063
+ function toNodeHandler(handler) {
1064
+ return async (req, res) => {
1065
+ const protocol = req.connection?.encrypted ? "https" : "http";
1066
+ const base = `${protocol}://${req.headers[":authority"] || req.headers.host}`;
1067
+ const response = await handler(getRequest({ base, request: req }));
1068
+ setResponse(res, response);
1069
+ };
1070
+ }
1071
+ // Annotate the CommonJS export names for ESM import in node:
1072
+ 0 && (module.exports = {
1073
+ APIError,
1074
+ createEndpoint,
1075
+ createEndpointCreator,
1076
+ createMiddleware,
1077
+ createMiddlewareCreator,
1078
+ createRouter,
1079
+ getBody,
1080
+ getCookie,
1081
+ getRequest,
1082
+ getSignedCookie,
1083
+ parse,
1084
+ parseSigned,
1085
+ serialize,
1086
+ serializeSigned,
1087
+ setCookie,
1088
+ setResponse,
1089
+ setSignedCookie,
1090
+ shouldSerialize,
1091
+ statusCode,
1092
+ toNodeHandler
1093
+ });
1094
+ //# sourceMappingURL=index.cjs.map