better-call 1.3.7 → 1.3.8

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.
Files changed (83) hide show
  1. package/README.md +862 -0
  2. package/dist/_virtual/_rolldown/runtime.cjs +7 -13
  3. package/dist/adapters/node/request.cjs +3 -4
  4. package/dist/adapters/node/request.cjs.map +1 -1
  5. package/dist/adapters/node/request.d.cts +1 -6
  6. package/dist/adapters/node/request.d.mts +1 -6
  7. package/dist/adapters/node/request.mjs +1 -2
  8. package/dist/adapters/node/request.mjs.map +1 -1
  9. package/dist/client.cjs +3 -5
  10. package/dist/client.cjs.map +1 -1
  11. package/dist/client.d.cts +5 -6
  12. package/dist/client.d.mts +5 -6
  13. package/dist/client.mjs +1 -2
  14. package/dist/client.mjs.map +1 -1
  15. package/dist/context.cjs +6 -7
  16. package/dist/context.cjs.map +1 -1
  17. package/dist/context.d.cts +8 -12
  18. package/dist/context.d.mts +8 -12
  19. package/dist/context.mjs +3 -4
  20. package/dist/context.mjs.map +1 -1
  21. package/dist/cookies.cjs +3 -4
  22. package/dist/cookies.cjs.map +1 -1
  23. package/dist/cookies.mjs +2 -3
  24. package/dist/cookies.mjs.map +1 -1
  25. package/dist/crypto.cjs +2 -4
  26. package/dist/crypto.cjs.map +1 -1
  27. package/dist/crypto.mjs +2 -3
  28. package/dist/crypto.mjs.map +1 -1
  29. package/dist/endpoint.cjs +5 -6
  30. package/dist/endpoint.cjs.map +1 -1
  31. package/dist/endpoint.d.cts +4 -8
  32. package/dist/endpoint.d.mts +4 -8
  33. package/dist/endpoint.mjs +2 -3
  34. package/dist/endpoint.mjs.map +1 -1
  35. package/dist/error.cjs +8 -3
  36. package/dist/error.cjs.map +1 -1
  37. package/dist/error.d.cts +0 -1
  38. package/dist/error.d.mts +0 -1
  39. package/dist/error.mjs +7 -1
  40. package/dist/error.mjs.map +1 -1
  41. package/dist/helper.d.cts +4 -4
  42. package/dist/helper.d.mts +4 -4
  43. package/dist/index.cjs +10 -11
  44. package/dist/index.d.cts +3 -3
  45. package/dist/index.d.mts +3 -3
  46. package/dist/index.mjs +2 -3
  47. package/dist/middleware.cjs +4 -6
  48. package/dist/middleware.cjs.map +1 -1
  49. package/dist/middleware.d.cts +0 -1
  50. package/dist/middleware.d.mts +0 -1
  51. package/dist/middleware.mjs +1 -3
  52. package/dist/middleware.mjs.map +1 -1
  53. package/dist/node.cjs +3 -4
  54. package/dist/node.cjs.map +1 -1
  55. package/dist/node.d.cts +1 -2
  56. package/dist/node.d.mts +1 -2
  57. package/dist/node.mjs +1 -2
  58. package/dist/node.mjs.map +1 -1
  59. package/dist/openapi.cjs +1 -3
  60. package/dist/openapi.cjs.map +1 -1
  61. package/dist/openapi.d.cts +2 -3
  62. package/dist/openapi.d.mts +2 -3
  63. package/dist/openapi.mjs +1 -2
  64. package/dist/openapi.mjs.map +1 -1
  65. package/dist/router.cjs +5 -7
  66. package/dist/router.cjs.map +1 -1
  67. package/dist/router.d.cts +0 -1
  68. package/dist/router.d.mts +0 -1
  69. package/dist/router.mjs +1 -2
  70. package/dist/router.mjs.map +1 -1
  71. package/dist/to-response.cjs +3 -5
  72. package/dist/to-response.cjs.map +1 -1
  73. package/dist/to-response.mjs +2 -4
  74. package/dist/to-response.mjs.map +1 -1
  75. package/dist/utils.cjs +2 -3
  76. package/dist/utils.cjs.map +1 -1
  77. package/dist/utils.mjs +1 -2
  78. package/dist/utils.mjs.map +1 -1
  79. package/dist/validator.cjs +2 -3
  80. package/dist/validator.cjs.map +1 -1
  81. package/dist/validator.mjs +2 -2
  82. package/dist/validator.mjs.map +1 -1
  83. package/package.json +9 -10
@@ -6,16 +6,12 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") {
10
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
- key = keys[i];
12
- if (!__hasOwnProp.call(to, key) && key !== except) {
13
- __defProp(to, key, {
14
- get: ((k) => from[k]).bind(null, key),
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- });
17
- }
18
- }
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
19
15
  }
20
16
  return to;
21
17
  };
@@ -23,7 +19,5 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
19
  value: mod,
24
20
  enumerable: true
25
21
  }) : target, mod));
26
-
27
22
  //#endregion
28
-
29
- exports.__toESM = __toESM;
23
+ exports.__toESM = __toESM;
@@ -1,7 +1,6 @@
1
- const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
1
+ const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
2
2
  let set_cookie_parser = require("set-cookie-parser");
3
- set_cookie_parser = require_runtime.__toESM(set_cookie_parser);
4
-
3
+ set_cookie_parser = require_runtime.__toESM(set_cookie_parser, 1);
5
4
  //#region src/adapters/node/request.ts
6
5
  const getFirstHeaderValue = (header) => {
7
6
  if (Array.isArray(header)) return header[0];
@@ -174,8 +173,8 @@ async function setResponse(res, response) {
174
173
  }
175
174
  }
176
175
  }
177
-
178
176
  //#endregion
179
177
  exports.getRequest = getRequest;
180
178
  exports.setResponse = setResponse;
179
+
181
180
  //# sourceMappingURL=request.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"request.cjs","names":[],"sources":["../../../src/adapters/node/request.ts"],"sourcesContent":["import type {\n\tIncomingHttpHeaders,\n\tIncomingMessage,\n\tServerResponse,\n} from \"node:http\";\nimport * as set_cookie_parser from \"set-cookie-parser\";\n\ntype NodeRequestWithBody = IncomingMessage & {\n\tbody?: unknown;\n};\n\nconst getFirstHeaderValue = (\n\theader: IncomingHttpHeaders[string],\n): string | undefined => {\n\tif (Array.isArray(header)) {\n\t\treturn header[0];\n\t}\n\treturn header;\n};\n\nconst hasFormUrlEncodedContentType = (\n\theaders: IncomingHttpHeaders,\n): boolean => {\n\tconst contentType = getFirstHeaderValue(headers[\"content-type\"]);\n\tif (!contentType) {\n\t\treturn false;\n\t}\n\treturn contentType\n\t\t.toLowerCase()\n\t\t.startsWith(\"application/x-www-form-urlencoded\");\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n\tif (typeof value !== \"object\" || value === null) {\n\t\treturn false;\n\t}\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n};\n\nconst appendFormValue = (\n\tparams: URLSearchParams,\n\tkey: string,\n\tvalue: unknown,\n) => {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) {\n\t\t\tappendFormValue(params, key, item);\n\t\t}\n\t\treturn;\n\t}\n\tif (value === null) {\n\t\tparams.append(key, \"\");\n\t\treturn;\n\t}\n\tif (isPlainObject(value)) {\n\t\tparams.append(key, JSON.stringify(value));\n\t\treturn;\n\t}\n\tparams.append(key, `${value}`);\n};\n\nconst toFormUrlEncodedBody = (\n\tbody: Readonly<Record<string, unknown>>,\n): string => {\n\tconst params = new URLSearchParams();\n\tfor (const [key, value] of Object.entries(body)) {\n\t\tappendFormValue(params, key, value);\n\t}\n\treturn params.toString();\n};\n\nconst canReadRawBody = (request: IncomingMessage): boolean => {\n\treturn (\n\t\t!request.destroyed && request.readableEnded !== true && request.readable\n\t);\n};\n\nconst serializeParsedBody = (\n\tparsedBody: unknown,\n\tisFormUrlEncoded: boolean,\n): string => {\n\tif (typeof parsedBody === \"string\") {\n\t\treturn parsedBody;\n\t}\n\tif (parsedBody instanceof URLSearchParams) {\n\t\treturn parsedBody.toString();\n\t}\n\tif (isFormUrlEncoded && isPlainObject(parsedBody)) {\n\t\treturn toFormUrlEncodedBody(parsedBody);\n\t}\n\treturn JSON.stringify(parsedBody);\n};\n\nfunction get_raw_body(req: IncomingMessage, body_size_limit?: number) {\n\tconst h = req.headers;\n\n\tif (!h[\"content-type\"]) return null;\n\n\tconst content_length = Number(h[\"content-length\"]);\n\n\t// check if no request body\n\tif (\n\t\t(req.httpVersionMajor === 1 &&\n\t\t\tisNaN(content_length) &&\n\t\t\th[\"transfer-encoding\"] == null) ||\n\t\tcontent_length === 0\n\t) {\n\t\treturn null;\n\t}\n\n\tlet length = content_length;\n\n\tif (body_size_limit) {\n\t\tif (!length) {\n\t\t\tlength = body_size_limit;\n\t\t} else if (length > body_size_limit) {\n\t\t\tthrow Error(\n\t\t\t\t`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (req.destroyed) {\n\t\tconst readable = new ReadableStream();\n\t\treadable.cancel();\n\t\treturn readable;\n\t}\n\n\tlet size = 0;\n\tlet cancelled = false;\n\n\treturn new ReadableStream({\n\t\tstart(controller) {\n\t\t\treq.on(\"error\", (error) => {\n\t\t\t\tcancelled = true;\n\t\t\t\tcontroller.error(error);\n\t\t\t});\n\n\t\t\treq.on(\"end\", () => {\n\t\t\t\tif (cancelled) return;\n\t\t\t\tcontroller.close();\n\t\t\t});\n\n\t\t\treq.on(\"data\", (chunk) => {\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\tsize += chunk.length;\n\n\t\t\t\tif (size > length) {\n\t\t\t\t\tcancelled = true;\n\n\t\t\t\t\tcontroller.error(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`request body size exceeded ${\n\t\t\t\t\t\t\t\tcontent_length ? \"'content-length'\" : \"BODY_SIZE_LIMIT\"\n\t\t\t\t\t\t\t} of ${length}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontroller.enqueue(chunk);\n\n\t\t\t\tif (controller.desiredSize === null || controller.desiredSize <= 0) {\n\t\t\t\t\treq.pause();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\tpull() {\n\t\t\treq.resume();\n\t\t},\n\n\t\tcancel(reason) {\n\t\t\tcancelled = true;\n\t\t\treq.destroy(reason);\n\t\t},\n\t});\n}\n\nfunction constructRelativeUrl(\n\treq: IncomingMessage & { baseUrl?: string; originalUrl?: string },\n) {\n\tconst baseUrl = req.baseUrl;\n\tconst originalUrl = req.originalUrl;\n\n\tif (!baseUrl || !originalUrl) {\n\t\t// In express.js sub-routers `req.url` is relative to the mount\n\t\t// path (e.g., '/auth/xxx'), and `req.baseUrl` will hold the mount\n\t\t// path (e.g., '/api'). Build the full path as baseUrl + url when\n\t\t// available to preserve the full route. For application level routes\n\t\t// baseUrl will be an empty string\n\t\treturn baseUrl ? baseUrl + req.url : req.url;\n\t}\n\n\tif (baseUrl + req.url === originalUrl) {\n\t\treturn baseUrl + req.url;\n\t}\n\n\t// For certain subroutes or when mounting wildcard middlewares in express\n\t// it is possible `baseUrl + req.url` will result in a url constructed\n\t// which has a trailing forward slash the original url did not have.\n\t// Checking the `req.originalUrl` path ending can prevent this issue.\n\n\tconst originalPathEnding = originalUrl.split(\"?\")[0]!.at(-1);\n\treturn originalPathEnding === \"/\" ? baseUrl + req.url : baseUrl;\n}\n\nexport function getRequest({\n\trequest,\n\tbase,\n\tbodySizeLimit,\n}: {\n\tbase: string;\n\tbodySizeLimit?: number;\n\trequest: IncomingMessage;\n}) {\n\t// Check if body has already been parsed by Express middleware\n\tconst maybeConsumedReq = request as NodeRequestWithBody;\n\tconst isFormUrlEncoded = hasFormUrlEncodedContentType(request.headers);\n\tlet body = undefined;\n\n\tconst method = request.method;\n\t// Request with GET/HEAD method cannot have body.\n\tif (method !== \"GET\" && method !== \"HEAD\") {\n\t\t// Raw-first strategy: prefer consuming the original request stream whenever it is still readable.\n\t\tif (canReadRawBody(request)) {\n\t\t\tbody = get_raw_body(request, bodySizeLimit);\n\t\t} else if (maybeConsumedReq.body !== undefined) {\n\t\t\tconst parsedBody = maybeConsumedReq.body;\n\n\t\t\tconst bodyContent = serializeParsedBody(parsedBody, isFormUrlEncoded);\n\t\t\tbody = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tcontroller.enqueue(new TextEncoder().encode(bodyContent));\n\t\t\t\t\tcontroller.close();\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\treturn new Request(base + constructRelativeUrl(request), {\n\t\t// @ts-expect-error\n\t\tduplex: \"half\",\n\t\tmethod: request.method,\n\t\tbody,\n\t\theaders: request.headers as Record<string, string>,\n\t});\n}\n\nexport async function setResponse(res: ServerResponse, response: Response) {\n\tfor (const [key, value] of response.headers as any) {\n\t\ttry {\n\t\t\tres.setHeader(\n\t\t\t\tkey,\n\t\t\t\tkey === \"set-cookie\"\n\t\t\t\t\t? set_cookie_parser.splitCookiesString(\n\t\t\t\t\t\t\tresponse.headers.get(key) as string,\n\t\t\t\t\t\t)\n\t\t\t\t\t: value,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tres.getHeaderNames().forEach((name) => res.removeHeader(name));\n\t\t\tres.writeHead(500).end(String(error));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tres.statusCode = response.status;\n\tres.writeHead(response.status);\n\n\tif (!response.body) {\n\t\tres.end();\n\t\treturn;\n\t}\n\n\tif (response.body.locked) {\n\t\tres.end(\n\t\t\t\"Fatal error: Response body is locked. \" +\n\t\t\t\t\"This can happen when the response was already read (for example through 'response.json()' or 'response.text()').\",\n\t\t);\n\t\treturn;\n\t}\n\n\tconst reader = response.body.getReader();\n\n\tif (res.destroyed) {\n\t\treader.cancel();\n\t\treturn;\n\t}\n\n\tconst cancel = (error?: Error) => {\n\t\tres.off(\"close\", cancel);\n\t\tres.off(\"error\", cancel);\n\n\t\t// If the reader has already been interrupted with an error earlier,\n\t\t// then it will appear here, it is useless, but it needs to be catch.\n\t\treader.cancel(error).catch(() => {});\n\t\tif (error) res.destroy(error);\n\t};\n\n\tres.on(\"close\", cancel);\n\tres.on(\"error\", cancel);\n\n\tnext();\n\tasync function next() {\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read();\n\n\t\t\t\tif (done) break;\n\n\t\t\t\tconst writeResult = res.write(value);\n\t\t\t\tif (!writeResult) {\n\t\t\t\t\t// In AWS Lambda/serverless environments, drain events may not work properly\n\t\t\t\t\t// Check if we're in a Lambda-like environment and handle differently\n\t\t\t\t\tif (\n\t\t\t\t\t\tprocess.env.AWS_LAMBDA_FUNCTION_NAME ||\n\t\t\t\t\t\tprocess.env.LAMBDA_TASK_ROOT\n\t\t\t\t\t) {\n\t\t\t\t\t\t// In Lambda, continue without waiting for drain\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Standard Node.js behavior\n\t\t\t\t\t\tres.once(\"drain\", next);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tres.end();\n\t\t} catch (error) {\n\t\t\tcancel(error instanceof Error ? error : new Error(String(error)));\n\t\t}\n\t}\n}\n"],"mappings":";;;;;AAWA,MAAM,uBACL,WACwB;AACxB,KAAI,MAAM,QAAQ,OAAO,CACxB,QAAO,OAAO;AAEf,QAAO;;AAGR,MAAM,gCACL,YACa;CACb,MAAM,cAAc,oBAAoB,QAAQ,gBAAgB;AAChE,KAAI,CAAC,YACJ,QAAO;AAER,QAAO,YACL,aAAa,CACb,WAAW,oCAAoC;;AAGlD,MAAM,iBAAiB,UAAqD;AAC3E,KAAI,OAAO,UAAU,YAAY,UAAU,KAC1C,QAAO;CAER,MAAM,YAAY,OAAO,eAAe,MAAM;AAC9C,QAAO,cAAc,OAAO,aAAa,cAAc;;AAGxD,MAAM,mBACL,QACA,KACA,UACI;AACJ,KAAI,UAAU,OACb;AAED,KAAI,MAAM,QAAQ,MAAM,EAAE;AACzB,OAAK,MAAM,QAAQ,MAClB,iBAAgB,QAAQ,KAAK,KAAK;AAEnC;;AAED,KAAI,UAAU,MAAM;AACnB,SAAO,OAAO,KAAK,GAAG;AACtB;;AAED,KAAI,cAAc,MAAM,EAAE;AACzB,SAAO,OAAO,KAAK,KAAK,UAAU,MAAM,CAAC;AACzC;;AAED,QAAO,OAAO,KAAK,GAAG,QAAQ;;AAG/B,MAAM,wBACL,SACY;CACZ,MAAM,SAAS,IAAI,iBAAiB;AACpC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,CAC9C,iBAAgB,QAAQ,KAAK,MAAM;AAEpC,QAAO,OAAO,UAAU;;AAGzB,MAAM,kBAAkB,YAAsC;AAC7D,QACC,CAAC,QAAQ,aAAa,QAAQ,kBAAkB,QAAQ,QAAQ;;AAIlE,MAAM,uBACL,YACA,qBACY;AACZ,KAAI,OAAO,eAAe,SACzB,QAAO;AAER,KAAI,sBAAsB,gBACzB,QAAO,WAAW,UAAU;AAE7B,KAAI,oBAAoB,cAAc,WAAW,CAChD,QAAO,qBAAqB,WAAW;AAExC,QAAO,KAAK,UAAU,WAAW;;AAGlC,SAAS,aAAa,KAAsB,iBAA0B;CACrE,MAAM,IAAI,IAAI;AAEd,KAAI,CAAC,EAAE,gBAAiB,QAAO;CAE/B,MAAM,iBAAiB,OAAO,EAAE,kBAAkB;AAGlD,KACE,IAAI,qBAAqB,KACzB,MAAM,eAAe,IACrB,EAAE,wBAAwB,QAC3B,mBAAmB,EAEnB,QAAO;CAGR,IAAI,SAAS;AAEb,KAAI,iBACH;MAAI,CAAC,OACJ,UAAS;WACC,SAAS,gBACnB,OAAM,MACL,8BAA8B,OAAO,0BAA0B,gBAAgB,SAC/E;;AAIH,KAAI,IAAI,WAAW;EAClB,MAAM,WAAW,IAAI,gBAAgB;AACrC,WAAS,QAAQ;AACjB,SAAO;;CAGR,IAAI,OAAO;CACX,IAAI,YAAY;AAEhB,QAAO,IAAI,eAAe;EACzB,MAAM,YAAY;AACjB,OAAI,GAAG,UAAU,UAAU;AAC1B,gBAAY;AACZ,eAAW,MAAM,MAAM;KACtB;AAEF,OAAI,GAAG,aAAa;AACnB,QAAI,UAAW;AACf,eAAW,OAAO;KACjB;AAEF,OAAI,GAAG,SAAS,UAAU;AACzB,QAAI,UAAW;AAEf,YAAQ,MAAM;AAEd,QAAI,OAAO,QAAQ;AAClB,iBAAY;AAEZ,gBAAW,sBACV,IAAI,MACH,8BACC,iBAAiB,qBAAqB,kBACtC,MAAM,SACP,CACD;AACD;;AAGD,eAAW,QAAQ,MAAM;AAEzB,QAAI,WAAW,gBAAgB,QAAQ,WAAW,eAAe,EAChE,KAAI,OAAO;KAEX;;EAGH,OAAO;AACN,OAAI,QAAQ;;EAGb,OAAO,QAAQ;AACd,eAAY;AACZ,OAAI,QAAQ,OAAO;;EAEpB,CAAC;;AAGH,SAAS,qBACR,KACC;CACD,MAAM,UAAU,IAAI;CACpB,MAAM,cAAc,IAAI;AAExB,KAAI,CAAC,WAAW,CAAC,YAMhB,QAAO,UAAU,UAAU,IAAI,MAAM,IAAI;AAG1C,KAAI,UAAU,IAAI,QAAQ,YACzB,QAAO,UAAU,IAAI;AAStB,QAD2B,YAAY,MAAM,IAAI,CAAC,GAAI,GAAG,GAAG,KAC9B,MAAM,UAAU,IAAI,MAAM;;AAGzD,SAAgB,WAAW,EAC1B,SACA,MACA,iBAKE;CAEF,MAAM,mBAAmB;CACzB,MAAM,mBAAmB,6BAA6B,QAAQ,QAAQ;CACtE,IAAI,OAAO;CAEX,MAAM,SAAS,QAAQ;AAEvB,KAAI,WAAW,SAAS,WAAW,QAElC;MAAI,eAAe,QAAQ,CAC1B,QAAO,aAAa,SAAS,cAAc;WACjC,iBAAiB,SAAS,QAAW;GAC/C,MAAM,aAAa,iBAAiB;GAEpC,MAAM,cAAc,oBAAoB,YAAY,iBAAiB;AACrE,UAAO,IAAI,eAAe,EACzB,MAAM,YAAY;AACjB,eAAW,QAAQ,IAAI,aAAa,CAAC,OAAO,YAAY,CAAC;AACzD,eAAW,OAAO;MAEnB,CAAC;;;AAIJ,QAAO,IAAI,QAAQ,OAAO,qBAAqB,QAAQ,EAAE;EAExD,QAAQ;EACR,QAAQ,QAAQ;EAChB;EACA,SAAS,QAAQ;EACjB,CAAC;;AAGH,eAAsB,YAAY,KAAqB,UAAoB;AAC1E,MAAK,MAAM,CAAC,KAAK,UAAU,SAAS,QACnC,KAAI;AACH,MAAI,UACH,KACA,QAAQ,eACL,kBAAkB,mBAClB,SAAS,QAAQ,IAAI,IAAI,CACzB,GACA,MACH;UACO,OAAO;AACf,MAAI,gBAAgB,CAAC,SAAS,SAAS,IAAI,aAAa,KAAK,CAAC;AAC9D,MAAI,UAAU,IAAI,CAAC,IAAI,OAAO,MAAM,CAAC;AACrC;;AAIF,KAAI,aAAa,SAAS;AAC1B,KAAI,UAAU,SAAS,OAAO;AAE9B,KAAI,CAAC,SAAS,MAAM;AACnB,MAAI,KAAK;AACT;;AAGD,KAAI,SAAS,KAAK,QAAQ;AACzB,MAAI,IACH,yJAEA;AACD;;CAGD,MAAM,SAAS,SAAS,KAAK,WAAW;AAExC,KAAI,IAAI,WAAW;AAClB,SAAO,QAAQ;AACf;;CAGD,MAAM,UAAU,UAAkB;AACjC,MAAI,IAAI,SAAS,OAAO;AACxB,MAAI,IAAI,SAAS,OAAO;AAIxB,SAAO,OAAO,MAAM,CAAC,YAAY,GAAG;AACpC,MAAI,MAAO,KAAI,QAAQ,MAAM;;AAG9B,KAAI,GAAG,SAAS,OAAO;AACvB,KAAI,GAAG,SAAS,OAAO;AAEvB,OAAM;CACN,eAAe,OAAO;AACrB,MAAI;AACH,YAAS;IACR,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAE3C,QAAI,KAAM;AAGV,QAAI,CADgB,IAAI,MAAM,MAAM,CAInC,KACC,QAAQ,IAAI,4BACZ,QAAQ,IAAI,iBAGZ;SACM;AAEN,SAAI,KAAK,SAAS,KAAK;AACvB;;;AAIH,OAAI,KAAK;WACD,OAAO;AACf,UAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"request.cjs","names":[],"sources":["../../../src/adapters/node/request.ts"],"sourcesContent":["import type {\n\tIncomingHttpHeaders,\n\tIncomingMessage,\n\tServerResponse,\n} from \"node:http\";\nimport * as set_cookie_parser from \"set-cookie-parser\";\n\ntype NodeRequestWithBody = IncomingMessage & {\n\tbody?: unknown;\n};\n\nconst getFirstHeaderValue = (\n\theader: IncomingHttpHeaders[string],\n): string | undefined => {\n\tif (Array.isArray(header)) {\n\t\treturn header[0];\n\t}\n\treturn header;\n};\n\nconst hasFormUrlEncodedContentType = (\n\theaders: IncomingHttpHeaders,\n): boolean => {\n\tconst contentType = getFirstHeaderValue(headers[\"content-type\"]);\n\tif (!contentType) {\n\t\treturn false;\n\t}\n\treturn contentType\n\t\t.toLowerCase()\n\t\t.startsWith(\"application/x-www-form-urlencoded\");\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n\tif (typeof value !== \"object\" || value === null) {\n\t\treturn false;\n\t}\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n};\n\nconst appendFormValue = (\n\tparams: URLSearchParams,\n\tkey: string,\n\tvalue: unknown,\n) => {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) {\n\t\t\tappendFormValue(params, key, item);\n\t\t}\n\t\treturn;\n\t}\n\tif (value === null) {\n\t\tparams.append(key, \"\");\n\t\treturn;\n\t}\n\tif (isPlainObject(value)) {\n\t\tparams.append(key, JSON.stringify(value));\n\t\treturn;\n\t}\n\tparams.append(key, `${value}`);\n};\n\nconst toFormUrlEncodedBody = (\n\tbody: Readonly<Record<string, unknown>>,\n): string => {\n\tconst params = new URLSearchParams();\n\tfor (const [key, value] of Object.entries(body)) {\n\t\tappendFormValue(params, key, value);\n\t}\n\treturn params.toString();\n};\n\nconst canReadRawBody = (request: IncomingMessage): boolean => {\n\treturn (\n\t\t!request.destroyed && request.readableEnded !== true && request.readable\n\t);\n};\n\nconst serializeParsedBody = (\n\tparsedBody: unknown,\n\tisFormUrlEncoded: boolean,\n): string => {\n\tif (typeof parsedBody === \"string\") {\n\t\treturn parsedBody;\n\t}\n\tif (parsedBody instanceof URLSearchParams) {\n\t\treturn parsedBody.toString();\n\t}\n\tif (isFormUrlEncoded && isPlainObject(parsedBody)) {\n\t\treturn toFormUrlEncodedBody(parsedBody);\n\t}\n\treturn JSON.stringify(parsedBody);\n};\n\nfunction get_raw_body(req: IncomingMessage, body_size_limit?: number) {\n\tconst h = req.headers;\n\n\tif (!h[\"content-type\"]) return null;\n\n\tconst content_length = Number(h[\"content-length\"]);\n\n\t// check if no request body\n\tif (\n\t\t(req.httpVersionMajor === 1 &&\n\t\t\tisNaN(content_length) &&\n\t\t\th[\"transfer-encoding\"] == null) ||\n\t\tcontent_length === 0\n\t) {\n\t\treturn null;\n\t}\n\n\tlet length = content_length;\n\n\tif (body_size_limit) {\n\t\tif (!length) {\n\t\t\tlength = body_size_limit;\n\t\t} else if (length > body_size_limit) {\n\t\t\tthrow Error(\n\t\t\t\t`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (req.destroyed) {\n\t\tconst readable = new ReadableStream();\n\t\treadable.cancel();\n\t\treturn readable;\n\t}\n\n\tlet size = 0;\n\tlet cancelled = false;\n\n\treturn new ReadableStream({\n\t\tstart(controller) {\n\t\t\treq.on(\"error\", (error) => {\n\t\t\t\tcancelled = true;\n\t\t\t\tcontroller.error(error);\n\t\t\t});\n\n\t\t\treq.on(\"end\", () => {\n\t\t\t\tif (cancelled) return;\n\t\t\t\tcontroller.close();\n\t\t\t});\n\n\t\t\treq.on(\"data\", (chunk) => {\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\tsize += chunk.length;\n\n\t\t\t\tif (size > length) {\n\t\t\t\t\tcancelled = true;\n\n\t\t\t\t\tcontroller.error(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`request body size exceeded ${\n\t\t\t\t\t\t\t\tcontent_length ? \"'content-length'\" : \"BODY_SIZE_LIMIT\"\n\t\t\t\t\t\t\t} of ${length}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontroller.enqueue(chunk);\n\n\t\t\t\tif (controller.desiredSize === null || controller.desiredSize <= 0) {\n\t\t\t\t\treq.pause();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\tpull() {\n\t\t\treq.resume();\n\t\t},\n\n\t\tcancel(reason) {\n\t\t\tcancelled = true;\n\t\t\treq.destroy(reason);\n\t\t},\n\t});\n}\n\nfunction constructRelativeUrl(\n\treq: IncomingMessage & { baseUrl?: string; originalUrl?: string },\n) {\n\tconst baseUrl = req.baseUrl;\n\tconst originalUrl = req.originalUrl;\n\n\tif (!baseUrl || !originalUrl) {\n\t\t// In express.js sub-routers `req.url` is relative to the mount\n\t\t// path (e.g., '/auth/xxx'), and `req.baseUrl` will hold the mount\n\t\t// path (e.g., '/api'). Build the full path as baseUrl + url when\n\t\t// available to preserve the full route. For application level routes\n\t\t// baseUrl will be an empty string\n\t\treturn baseUrl ? baseUrl + req.url : req.url;\n\t}\n\n\tif (baseUrl + req.url === originalUrl) {\n\t\treturn baseUrl + req.url;\n\t}\n\n\t// For certain subroutes or when mounting wildcard middlewares in express\n\t// it is possible `baseUrl + req.url` will result in a url constructed\n\t// which has a trailing forward slash the original url did not have.\n\t// Checking the `req.originalUrl` path ending can prevent this issue.\n\n\tconst originalPathEnding = originalUrl.split(\"?\")[0]!.at(-1);\n\treturn originalPathEnding === \"/\" ? baseUrl + req.url : baseUrl;\n}\n\nexport function getRequest({\n\trequest,\n\tbase,\n\tbodySizeLimit,\n}: {\n\tbase: string;\n\tbodySizeLimit?: number;\n\trequest: IncomingMessage;\n}) {\n\t// Check if body has already been parsed by Express middleware\n\tconst maybeConsumedReq = request as NodeRequestWithBody;\n\tconst isFormUrlEncoded = hasFormUrlEncodedContentType(request.headers);\n\tlet body = undefined;\n\n\tconst method = request.method;\n\t// Request with GET/HEAD method cannot have body.\n\tif (method !== \"GET\" && method !== \"HEAD\") {\n\t\t// Raw-first strategy: prefer consuming the original request stream whenever it is still readable.\n\t\tif (canReadRawBody(request)) {\n\t\t\tbody = get_raw_body(request, bodySizeLimit);\n\t\t} else if (maybeConsumedReq.body !== undefined) {\n\t\t\tconst parsedBody = maybeConsumedReq.body;\n\n\t\t\tconst bodyContent = serializeParsedBody(parsedBody, isFormUrlEncoded);\n\t\t\tbody = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tcontroller.enqueue(new TextEncoder().encode(bodyContent));\n\t\t\t\t\tcontroller.close();\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\treturn new Request(base + constructRelativeUrl(request), {\n\t\t// @ts-expect-error\n\t\tduplex: \"half\",\n\t\tmethod: request.method,\n\t\tbody,\n\t\theaders: request.headers as Record<string, string>,\n\t});\n}\n\nexport async function setResponse(res: ServerResponse, response: Response) {\n\tfor (const [key, value] of response.headers as any) {\n\t\ttry {\n\t\t\tres.setHeader(\n\t\t\t\tkey,\n\t\t\t\tkey === \"set-cookie\"\n\t\t\t\t\t? set_cookie_parser.splitCookiesString(\n\t\t\t\t\t\t\tresponse.headers.get(key) as string,\n\t\t\t\t\t\t)\n\t\t\t\t\t: value,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tres.getHeaderNames().forEach((name) => res.removeHeader(name));\n\t\t\tres.writeHead(500).end(String(error));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tres.statusCode = response.status;\n\tres.writeHead(response.status);\n\n\tif (!response.body) {\n\t\tres.end();\n\t\treturn;\n\t}\n\n\tif (response.body.locked) {\n\t\tres.end(\n\t\t\t\"Fatal error: Response body is locked. \" +\n\t\t\t\t\"This can happen when the response was already read (for example through 'response.json()' or 'response.text()').\",\n\t\t);\n\t\treturn;\n\t}\n\n\tconst reader = response.body.getReader();\n\n\tif (res.destroyed) {\n\t\treader.cancel();\n\t\treturn;\n\t}\n\n\tconst cancel = (error?: Error) => {\n\t\tres.off(\"close\", cancel);\n\t\tres.off(\"error\", cancel);\n\n\t\t// If the reader has already been interrupted with an error earlier,\n\t\t// then it will appear here, it is useless, but it needs to be catch.\n\t\treader.cancel(error).catch(() => {});\n\t\tif (error) res.destroy(error);\n\t};\n\n\tres.on(\"close\", cancel);\n\tres.on(\"error\", cancel);\n\n\tvoid next();\n\tasync function next() {\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read();\n\n\t\t\t\tif (done) break;\n\n\t\t\t\tconst writeResult = res.write(value);\n\t\t\t\tif (!writeResult) {\n\t\t\t\t\t// In AWS Lambda/serverless environments, drain events may not work properly\n\t\t\t\t\t// Check if we're in a Lambda-like environment and handle differently\n\t\t\t\t\tif (\n\t\t\t\t\t\tprocess.env.AWS_LAMBDA_FUNCTION_NAME ||\n\t\t\t\t\t\tprocess.env.LAMBDA_TASK_ROOT\n\t\t\t\t\t) {\n\t\t\t\t\t\t// In Lambda, continue without waiting for drain\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Standard Node.js behavior\n\t\t\t\t\t\tres.once(\"drain\", next);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tres.end();\n\t\t} catch (error) {\n\t\t\tcancel(error instanceof Error ? error : new Error(String(error)));\n\t\t}\n\t}\n}\n"],"mappings":"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"}
@@ -1,11 +1,6 @@
1
1
  import { IncomingMessage, ServerResponse } from "node:http";
2
-
3
2
  //#region src/adapters/node/request.d.ts
4
- declare function getRequest({
5
- request,
6
- base,
7
- bodySizeLimit
8
- }: {
3
+ declare function getRequest({ request, base, bodySizeLimit }: {
9
4
  base: string;
10
5
  bodySizeLimit?: number;
11
6
  request: IncomingMessage;
@@ -1,11 +1,6 @@
1
1
  import { IncomingMessage, ServerResponse } from "node:http";
2
-
3
2
  //#region src/adapters/node/request.d.ts
4
- declare function getRequest({
5
- request,
6
- base,
7
- bodySizeLimit
8
- }: {
3
+ declare function getRequest({ request, base, bodySizeLimit }: {
9
4
  base: string;
10
5
  bodySizeLimit?: number;
11
6
  request: IncomingMessage;
@@ -1,5 +1,4 @@
1
1
  import * as set_cookie_parser from "set-cookie-parser";
2
-
3
2
  //#region src/adapters/node/request.ts
4
3
  const getFirstHeaderValue = (header) => {
5
4
  if (Array.isArray(header)) return header[0];
@@ -172,7 +171,7 @@ async function setResponse(res, response) {
172
171
  }
173
172
  }
174
173
  }
175
-
176
174
  //#endregion
177
175
  export { getRequest, setResponse };
176
+
178
177
  //# sourceMappingURL=request.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"request.mjs","names":[],"sources":["../../../src/adapters/node/request.ts"],"sourcesContent":["import type {\n\tIncomingHttpHeaders,\n\tIncomingMessage,\n\tServerResponse,\n} from \"node:http\";\nimport * as set_cookie_parser from \"set-cookie-parser\";\n\ntype NodeRequestWithBody = IncomingMessage & {\n\tbody?: unknown;\n};\n\nconst getFirstHeaderValue = (\n\theader: IncomingHttpHeaders[string],\n): string | undefined => {\n\tif (Array.isArray(header)) {\n\t\treturn header[0];\n\t}\n\treturn header;\n};\n\nconst hasFormUrlEncodedContentType = (\n\theaders: IncomingHttpHeaders,\n): boolean => {\n\tconst contentType = getFirstHeaderValue(headers[\"content-type\"]);\n\tif (!contentType) {\n\t\treturn false;\n\t}\n\treturn contentType\n\t\t.toLowerCase()\n\t\t.startsWith(\"application/x-www-form-urlencoded\");\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n\tif (typeof value !== \"object\" || value === null) {\n\t\treturn false;\n\t}\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n};\n\nconst appendFormValue = (\n\tparams: URLSearchParams,\n\tkey: string,\n\tvalue: unknown,\n) => {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) {\n\t\t\tappendFormValue(params, key, item);\n\t\t}\n\t\treturn;\n\t}\n\tif (value === null) {\n\t\tparams.append(key, \"\");\n\t\treturn;\n\t}\n\tif (isPlainObject(value)) {\n\t\tparams.append(key, JSON.stringify(value));\n\t\treturn;\n\t}\n\tparams.append(key, `${value}`);\n};\n\nconst toFormUrlEncodedBody = (\n\tbody: Readonly<Record<string, unknown>>,\n): string => {\n\tconst params = new URLSearchParams();\n\tfor (const [key, value] of Object.entries(body)) {\n\t\tappendFormValue(params, key, value);\n\t}\n\treturn params.toString();\n};\n\nconst canReadRawBody = (request: IncomingMessage): boolean => {\n\treturn (\n\t\t!request.destroyed && request.readableEnded !== true && request.readable\n\t);\n};\n\nconst serializeParsedBody = (\n\tparsedBody: unknown,\n\tisFormUrlEncoded: boolean,\n): string => {\n\tif (typeof parsedBody === \"string\") {\n\t\treturn parsedBody;\n\t}\n\tif (parsedBody instanceof URLSearchParams) {\n\t\treturn parsedBody.toString();\n\t}\n\tif (isFormUrlEncoded && isPlainObject(parsedBody)) {\n\t\treturn toFormUrlEncodedBody(parsedBody);\n\t}\n\treturn JSON.stringify(parsedBody);\n};\n\nfunction get_raw_body(req: IncomingMessage, body_size_limit?: number) {\n\tconst h = req.headers;\n\n\tif (!h[\"content-type\"]) return null;\n\n\tconst content_length = Number(h[\"content-length\"]);\n\n\t// check if no request body\n\tif (\n\t\t(req.httpVersionMajor === 1 &&\n\t\t\tisNaN(content_length) &&\n\t\t\th[\"transfer-encoding\"] == null) ||\n\t\tcontent_length === 0\n\t) {\n\t\treturn null;\n\t}\n\n\tlet length = content_length;\n\n\tif (body_size_limit) {\n\t\tif (!length) {\n\t\t\tlength = body_size_limit;\n\t\t} else if (length > body_size_limit) {\n\t\t\tthrow Error(\n\t\t\t\t`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (req.destroyed) {\n\t\tconst readable = new ReadableStream();\n\t\treadable.cancel();\n\t\treturn readable;\n\t}\n\n\tlet size = 0;\n\tlet cancelled = false;\n\n\treturn new ReadableStream({\n\t\tstart(controller) {\n\t\t\treq.on(\"error\", (error) => {\n\t\t\t\tcancelled = true;\n\t\t\t\tcontroller.error(error);\n\t\t\t});\n\n\t\t\treq.on(\"end\", () => {\n\t\t\t\tif (cancelled) return;\n\t\t\t\tcontroller.close();\n\t\t\t});\n\n\t\t\treq.on(\"data\", (chunk) => {\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\tsize += chunk.length;\n\n\t\t\t\tif (size > length) {\n\t\t\t\t\tcancelled = true;\n\n\t\t\t\t\tcontroller.error(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`request body size exceeded ${\n\t\t\t\t\t\t\t\tcontent_length ? \"'content-length'\" : \"BODY_SIZE_LIMIT\"\n\t\t\t\t\t\t\t} of ${length}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontroller.enqueue(chunk);\n\n\t\t\t\tif (controller.desiredSize === null || controller.desiredSize <= 0) {\n\t\t\t\t\treq.pause();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\tpull() {\n\t\t\treq.resume();\n\t\t},\n\n\t\tcancel(reason) {\n\t\t\tcancelled = true;\n\t\t\treq.destroy(reason);\n\t\t},\n\t});\n}\n\nfunction constructRelativeUrl(\n\treq: IncomingMessage & { baseUrl?: string; originalUrl?: string },\n) {\n\tconst baseUrl = req.baseUrl;\n\tconst originalUrl = req.originalUrl;\n\n\tif (!baseUrl || !originalUrl) {\n\t\t// In express.js sub-routers `req.url` is relative to the mount\n\t\t// path (e.g., '/auth/xxx'), and `req.baseUrl` will hold the mount\n\t\t// path (e.g., '/api'). Build the full path as baseUrl + url when\n\t\t// available to preserve the full route. For application level routes\n\t\t// baseUrl will be an empty string\n\t\treturn baseUrl ? baseUrl + req.url : req.url;\n\t}\n\n\tif (baseUrl + req.url === originalUrl) {\n\t\treturn baseUrl + req.url;\n\t}\n\n\t// For certain subroutes or when mounting wildcard middlewares in express\n\t// it is possible `baseUrl + req.url` will result in a url constructed\n\t// which has a trailing forward slash the original url did not have.\n\t// Checking the `req.originalUrl` path ending can prevent this issue.\n\n\tconst originalPathEnding = originalUrl.split(\"?\")[0]!.at(-1);\n\treturn originalPathEnding === \"/\" ? baseUrl + req.url : baseUrl;\n}\n\nexport function getRequest({\n\trequest,\n\tbase,\n\tbodySizeLimit,\n}: {\n\tbase: string;\n\tbodySizeLimit?: number;\n\trequest: IncomingMessage;\n}) {\n\t// Check if body has already been parsed by Express middleware\n\tconst maybeConsumedReq = request as NodeRequestWithBody;\n\tconst isFormUrlEncoded = hasFormUrlEncodedContentType(request.headers);\n\tlet body = undefined;\n\n\tconst method = request.method;\n\t// Request with GET/HEAD method cannot have body.\n\tif (method !== \"GET\" && method !== \"HEAD\") {\n\t\t// Raw-first strategy: prefer consuming the original request stream whenever it is still readable.\n\t\tif (canReadRawBody(request)) {\n\t\t\tbody = get_raw_body(request, bodySizeLimit);\n\t\t} else if (maybeConsumedReq.body !== undefined) {\n\t\t\tconst parsedBody = maybeConsumedReq.body;\n\n\t\t\tconst bodyContent = serializeParsedBody(parsedBody, isFormUrlEncoded);\n\t\t\tbody = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tcontroller.enqueue(new TextEncoder().encode(bodyContent));\n\t\t\t\t\tcontroller.close();\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\treturn new Request(base + constructRelativeUrl(request), {\n\t\t// @ts-expect-error\n\t\tduplex: \"half\",\n\t\tmethod: request.method,\n\t\tbody,\n\t\theaders: request.headers as Record<string, string>,\n\t});\n}\n\nexport async function setResponse(res: ServerResponse, response: Response) {\n\tfor (const [key, value] of response.headers as any) {\n\t\ttry {\n\t\t\tres.setHeader(\n\t\t\t\tkey,\n\t\t\t\tkey === \"set-cookie\"\n\t\t\t\t\t? set_cookie_parser.splitCookiesString(\n\t\t\t\t\t\t\tresponse.headers.get(key) as string,\n\t\t\t\t\t\t)\n\t\t\t\t\t: value,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tres.getHeaderNames().forEach((name) => res.removeHeader(name));\n\t\t\tres.writeHead(500).end(String(error));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tres.statusCode = response.status;\n\tres.writeHead(response.status);\n\n\tif (!response.body) {\n\t\tres.end();\n\t\treturn;\n\t}\n\n\tif (response.body.locked) {\n\t\tres.end(\n\t\t\t\"Fatal error: Response body is locked. \" +\n\t\t\t\t\"This can happen when the response was already read (for example through 'response.json()' or 'response.text()').\",\n\t\t);\n\t\treturn;\n\t}\n\n\tconst reader = response.body.getReader();\n\n\tif (res.destroyed) {\n\t\treader.cancel();\n\t\treturn;\n\t}\n\n\tconst cancel = (error?: Error) => {\n\t\tres.off(\"close\", cancel);\n\t\tres.off(\"error\", cancel);\n\n\t\t// If the reader has already been interrupted with an error earlier,\n\t\t// then it will appear here, it is useless, but it needs to be catch.\n\t\treader.cancel(error).catch(() => {});\n\t\tif (error) res.destroy(error);\n\t};\n\n\tres.on(\"close\", cancel);\n\tres.on(\"error\", cancel);\n\n\tnext();\n\tasync function next() {\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read();\n\n\t\t\t\tif (done) break;\n\n\t\t\t\tconst writeResult = res.write(value);\n\t\t\t\tif (!writeResult) {\n\t\t\t\t\t// In AWS Lambda/serverless environments, drain events may not work properly\n\t\t\t\t\t// Check if we're in a Lambda-like environment and handle differently\n\t\t\t\t\tif (\n\t\t\t\t\t\tprocess.env.AWS_LAMBDA_FUNCTION_NAME ||\n\t\t\t\t\t\tprocess.env.LAMBDA_TASK_ROOT\n\t\t\t\t\t) {\n\t\t\t\t\t\t// In Lambda, continue without waiting for drain\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Standard Node.js behavior\n\t\t\t\t\t\tres.once(\"drain\", next);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tres.end();\n\t\t} catch (error) {\n\t\t\tcancel(error instanceof Error ? error : new Error(String(error)));\n\t\t}\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"request.mjs","names":[],"sources":["../../../src/adapters/node/request.ts"],"sourcesContent":["import type {\n\tIncomingHttpHeaders,\n\tIncomingMessage,\n\tServerResponse,\n} from \"node:http\";\nimport * as set_cookie_parser from \"set-cookie-parser\";\n\ntype NodeRequestWithBody = IncomingMessage & {\n\tbody?: unknown;\n};\n\nconst getFirstHeaderValue = (\n\theader: IncomingHttpHeaders[string],\n): string | undefined => {\n\tif (Array.isArray(header)) {\n\t\treturn header[0];\n\t}\n\treturn header;\n};\n\nconst hasFormUrlEncodedContentType = (\n\theaders: IncomingHttpHeaders,\n): boolean => {\n\tconst contentType = getFirstHeaderValue(headers[\"content-type\"]);\n\tif (!contentType) {\n\t\treturn false;\n\t}\n\treturn contentType\n\t\t.toLowerCase()\n\t\t.startsWith(\"application/x-www-form-urlencoded\");\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n\tif (typeof value !== \"object\" || value === null) {\n\t\treturn false;\n\t}\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n};\n\nconst appendFormValue = (\n\tparams: URLSearchParams,\n\tkey: string,\n\tvalue: unknown,\n) => {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) {\n\t\t\tappendFormValue(params, key, item);\n\t\t}\n\t\treturn;\n\t}\n\tif (value === null) {\n\t\tparams.append(key, \"\");\n\t\treturn;\n\t}\n\tif (isPlainObject(value)) {\n\t\tparams.append(key, JSON.stringify(value));\n\t\treturn;\n\t}\n\tparams.append(key, `${value}`);\n};\n\nconst toFormUrlEncodedBody = (\n\tbody: Readonly<Record<string, unknown>>,\n): string => {\n\tconst params = new URLSearchParams();\n\tfor (const [key, value] of Object.entries(body)) {\n\t\tappendFormValue(params, key, value);\n\t}\n\treturn params.toString();\n};\n\nconst canReadRawBody = (request: IncomingMessage): boolean => {\n\treturn (\n\t\t!request.destroyed && request.readableEnded !== true && request.readable\n\t);\n};\n\nconst serializeParsedBody = (\n\tparsedBody: unknown,\n\tisFormUrlEncoded: boolean,\n): string => {\n\tif (typeof parsedBody === \"string\") {\n\t\treturn parsedBody;\n\t}\n\tif (parsedBody instanceof URLSearchParams) {\n\t\treturn parsedBody.toString();\n\t}\n\tif (isFormUrlEncoded && isPlainObject(parsedBody)) {\n\t\treturn toFormUrlEncodedBody(parsedBody);\n\t}\n\treturn JSON.stringify(parsedBody);\n};\n\nfunction get_raw_body(req: IncomingMessage, body_size_limit?: number) {\n\tconst h = req.headers;\n\n\tif (!h[\"content-type\"]) return null;\n\n\tconst content_length = Number(h[\"content-length\"]);\n\n\t// check if no request body\n\tif (\n\t\t(req.httpVersionMajor === 1 &&\n\t\t\tisNaN(content_length) &&\n\t\t\th[\"transfer-encoding\"] == null) ||\n\t\tcontent_length === 0\n\t) {\n\t\treturn null;\n\t}\n\n\tlet length = content_length;\n\n\tif (body_size_limit) {\n\t\tif (!length) {\n\t\t\tlength = body_size_limit;\n\t\t} else if (length > body_size_limit) {\n\t\t\tthrow Error(\n\t\t\t\t`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (req.destroyed) {\n\t\tconst readable = new ReadableStream();\n\t\treadable.cancel();\n\t\treturn readable;\n\t}\n\n\tlet size = 0;\n\tlet cancelled = false;\n\n\treturn new ReadableStream({\n\t\tstart(controller) {\n\t\t\treq.on(\"error\", (error) => {\n\t\t\t\tcancelled = true;\n\t\t\t\tcontroller.error(error);\n\t\t\t});\n\n\t\t\treq.on(\"end\", () => {\n\t\t\t\tif (cancelled) return;\n\t\t\t\tcontroller.close();\n\t\t\t});\n\n\t\t\treq.on(\"data\", (chunk) => {\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\tsize += chunk.length;\n\n\t\t\t\tif (size > length) {\n\t\t\t\t\tcancelled = true;\n\n\t\t\t\t\tcontroller.error(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`request body size exceeded ${\n\t\t\t\t\t\t\t\tcontent_length ? \"'content-length'\" : \"BODY_SIZE_LIMIT\"\n\t\t\t\t\t\t\t} of ${length}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontroller.enqueue(chunk);\n\n\t\t\t\tif (controller.desiredSize === null || controller.desiredSize <= 0) {\n\t\t\t\t\treq.pause();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\tpull() {\n\t\t\treq.resume();\n\t\t},\n\n\t\tcancel(reason) {\n\t\t\tcancelled = true;\n\t\t\treq.destroy(reason);\n\t\t},\n\t});\n}\n\nfunction constructRelativeUrl(\n\treq: IncomingMessage & { baseUrl?: string; originalUrl?: string },\n) {\n\tconst baseUrl = req.baseUrl;\n\tconst originalUrl = req.originalUrl;\n\n\tif (!baseUrl || !originalUrl) {\n\t\t// In express.js sub-routers `req.url` is relative to the mount\n\t\t// path (e.g., '/auth/xxx'), and `req.baseUrl` will hold the mount\n\t\t// path (e.g., '/api'). Build the full path as baseUrl + url when\n\t\t// available to preserve the full route. For application level routes\n\t\t// baseUrl will be an empty string\n\t\treturn baseUrl ? baseUrl + req.url : req.url;\n\t}\n\n\tif (baseUrl + req.url === originalUrl) {\n\t\treturn baseUrl + req.url;\n\t}\n\n\t// For certain subroutes or when mounting wildcard middlewares in express\n\t// it is possible `baseUrl + req.url` will result in a url constructed\n\t// which has a trailing forward slash the original url did not have.\n\t// Checking the `req.originalUrl` path ending can prevent this issue.\n\n\tconst originalPathEnding = originalUrl.split(\"?\")[0]!.at(-1);\n\treturn originalPathEnding === \"/\" ? baseUrl + req.url : baseUrl;\n}\n\nexport function getRequest({\n\trequest,\n\tbase,\n\tbodySizeLimit,\n}: {\n\tbase: string;\n\tbodySizeLimit?: number;\n\trequest: IncomingMessage;\n}) {\n\t// Check if body has already been parsed by Express middleware\n\tconst maybeConsumedReq = request as NodeRequestWithBody;\n\tconst isFormUrlEncoded = hasFormUrlEncodedContentType(request.headers);\n\tlet body = undefined;\n\n\tconst method = request.method;\n\t// Request with GET/HEAD method cannot have body.\n\tif (method !== \"GET\" && method !== \"HEAD\") {\n\t\t// Raw-first strategy: prefer consuming the original request stream whenever it is still readable.\n\t\tif (canReadRawBody(request)) {\n\t\t\tbody = get_raw_body(request, bodySizeLimit);\n\t\t} else if (maybeConsumedReq.body !== undefined) {\n\t\t\tconst parsedBody = maybeConsumedReq.body;\n\n\t\t\tconst bodyContent = serializeParsedBody(parsedBody, isFormUrlEncoded);\n\t\t\tbody = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tcontroller.enqueue(new TextEncoder().encode(bodyContent));\n\t\t\t\t\tcontroller.close();\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\treturn new Request(base + constructRelativeUrl(request), {\n\t\t// @ts-expect-error\n\t\tduplex: \"half\",\n\t\tmethod: request.method,\n\t\tbody,\n\t\theaders: request.headers as Record<string, string>,\n\t});\n}\n\nexport async function setResponse(res: ServerResponse, response: Response) {\n\tfor (const [key, value] of response.headers as any) {\n\t\ttry {\n\t\t\tres.setHeader(\n\t\t\t\tkey,\n\t\t\t\tkey === \"set-cookie\"\n\t\t\t\t\t? set_cookie_parser.splitCookiesString(\n\t\t\t\t\t\t\tresponse.headers.get(key) as string,\n\t\t\t\t\t\t)\n\t\t\t\t\t: value,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tres.getHeaderNames().forEach((name) => res.removeHeader(name));\n\t\t\tres.writeHead(500).end(String(error));\n\t\t\treturn;\n\t\t}\n\t}\n\n\tres.statusCode = response.status;\n\tres.writeHead(response.status);\n\n\tif (!response.body) {\n\t\tres.end();\n\t\treturn;\n\t}\n\n\tif (response.body.locked) {\n\t\tres.end(\n\t\t\t\"Fatal error: Response body is locked. \" +\n\t\t\t\t\"This can happen when the response was already read (for example through 'response.json()' or 'response.text()').\",\n\t\t);\n\t\treturn;\n\t}\n\n\tconst reader = response.body.getReader();\n\n\tif (res.destroyed) {\n\t\treader.cancel();\n\t\treturn;\n\t}\n\n\tconst cancel = (error?: Error) => {\n\t\tres.off(\"close\", cancel);\n\t\tres.off(\"error\", cancel);\n\n\t\t// If the reader has already been interrupted with an error earlier,\n\t\t// then it will appear here, it is useless, but it needs to be catch.\n\t\treader.cancel(error).catch(() => {});\n\t\tif (error) res.destroy(error);\n\t};\n\n\tres.on(\"close\", cancel);\n\tres.on(\"error\", cancel);\n\n\tvoid next();\n\tasync function next() {\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst { done, value } = await reader.read();\n\n\t\t\t\tif (done) break;\n\n\t\t\t\tconst writeResult = res.write(value);\n\t\t\t\tif (!writeResult) {\n\t\t\t\t\t// In AWS Lambda/serverless environments, drain events may not work properly\n\t\t\t\t\t// Check if we're in a Lambda-like environment and handle differently\n\t\t\t\t\tif (\n\t\t\t\t\t\tprocess.env.AWS_LAMBDA_FUNCTION_NAME ||\n\t\t\t\t\t\tprocess.env.LAMBDA_TASK_ROOT\n\t\t\t\t\t) {\n\t\t\t\t\t\t// In Lambda, continue without waiting for drain\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Standard Node.js behavior\n\t\t\t\t\t\tres.once(\"drain\", next);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tres.end();\n\t\t} catch (error) {\n\t\t\tcancel(error instanceof Error ? error : new Error(String(error)));\n\t\t}\n\t}\n}\n"],"mappings":"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"}
package/dist/client.cjs CHANGED
@@ -1,8 +1,6 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
3
- const require_error = require('./error.cjs');
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_error = require("./error.cjs");
4
3
  let _better_fetch_fetch = require("@better-fetch/fetch");
5
-
6
4
  //#region src/client.ts
7
5
  const createClient = (options) => {
8
6
  const fetch = (0, _better_fetch_fetch.createFetch)(options ?? {});
@@ -10,7 +8,6 @@ const createClient = (options) => {
10
8
  return await fetch(path, { ...callOptions[0] });
11
9
  };
12
10
  };
13
-
14
11
  //#endregion
15
12
  exports.APIError = require_error.APIError;
16
13
  exports.BetterCallError = require_error.BetterCallError;
@@ -20,4 +17,5 @@ exports.hideInternalStackFrames = require_error.hideInternalStackFrames;
20
17
  exports.kAPIErrorHeaderSymbol = require_error.kAPIErrorHeaderSymbol;
21
18
  exports.makeErrorForHideStackFrame = require_error.makeErrorForHideStackFrame;
22
19
  exports.statusCodes = require_error.statusCodes;
20
+
23
21
  //# sourceMappingURL=client.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.cjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import {\n\ttype BetterFetchOption,\n\ttype BetterFetchResponse,\n\tcreateFetch,\n} from \"@better-fetch/fetch\";\nimport type { Router } from \"./router\";\nimport type { HasRequiredKeys, Prettify, UnionToIntersection } from \"./helper\";\nimport type { Endpoint } from \"./endpoint\";\n\nexport type HasRequired<T extends object> = T extends {}\n\t? false\n\t: T extends {\n\t\t\t\tbody?: any;\n\t\t\t\tquery?: any;\n\t\t\t\tparams?: any;\n\t\t\t}\n\t\t? T[\"body\"] extends object\n\t\t\t? HasRequiredKeys<T[\"body\"]> extends true\n\t\t\t\t? true\n\t\t\t\t: T[\"query\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t\t: false\n\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t: false\n\t\t\t: T[\"query\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t\t? true\n\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t: false\n\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t: false\n\t\t: false;\n\ntype InferContext<T> = T extends (ctx: infer Ctx) => any\n\t? Ctx extends object\n\t\t? Ctx\n\t\t: never\n\t: never;\n\nexport interface ClientOptions extends BetterFetchOption {\n\tbaseURL?: string;\n}\n\ntype WithRequired<T, K> = T & {\n\t[P in K extends string ? K : never]-?: T[P extends keyof T ? P : never];\n};\n\ntype InferClientRoutes<T extends Record<string, Endpoint>> = {\n\t[K in keyof T]: T[K] extends Endpoint<any, infer O>\n\t\t? O extends\n\t\t\t\t| { metadata: { scope: \"http\" } }\n\t\t\t\t| { metadata: { scope: \"server\" } }\n\t\t\t\t| { metadata: { SERVER_ONLY: true } }\n\t\t\t\t| { metadata: { isAction: false } }\n\t\t\t? never\n\t\t\t: T[K]\n\t\t: T[K];\n};\n\nexport type RequiredOptionKeys<\n\tC extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = (undefined extends C[\"body\"]\n\t? {}\n\t: {\n\t\t\tbody: true;\n\t\t}) &\n\t(undefined extends C[\"query\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tquery: true;\n\t\t\t}) &\n\t(undefined extends C[\"params\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tparams: true;\n\t\t\t});\n\nexport const createClient = <\n\tR extends Router | Router[\"endpoints\"],\n\tGlobalOpts extends ClientOptions = ClientOptions,\n>(\n\toptions?: GlobalOpts,\n) => {\n\tconst fetch = createFetch(options ?? {});\n\ttype API = InferClientRoutes<\n\t\tR extends { endpoints: Record<string, Endpoint> } ? R[\"endpoints\"] : R\n\t>;\n\ttype Options = API extends {\n\t\t[key: string]: infer T;\n\t}\n\t\t? T extends Endpoint\n\t\t\t? {\n\t\t\t\t\t[key in T[\"options\"][\"method\"] extends \"GET\"\n\t\t\t\t\t\t? T[\"path\"]\n\t\t\t\t\t\t: `@${T[\"options\"][\"method\"] extends string ? Lowercase<T[\"options\"][\"method\"]> : never}${T[\"path\"]}`]: T;\n\t\t\t\t}\n\t\t\t: {}\n\t\t: {};\n\n\ttype O = Prettify<UnionToIntersection<Options>>;\n\treturn async <\n\t\tOPT extends O,\n\t\tK extends keyof OPT,\n\t\tC extends InferContext<OPT[K]>,\n\t\tCallOpts extends BetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t>(\n\t\tpath: K,\n\t\t...callOptions: HasRequired<C> extends true\n\t\t\t? [\n\t\t\t\t\tWithRequired<\n\t\t\t\t\t\tBetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t\t\t\t\t\tkeyof RequiredOptionKeys<C>\n\t\t\t\t\t>,\n\t\t\t\t]\n\t\t\t: [CallOpts?]\n\t): Promise<\n\t\tBetterFetchResponse<\n\t\t\tAwaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>,\n\t\t\tunknown,\n\t\t\tCallOpts[\"throw\"] extends boolean\n\t\t\t\t? CallOpts[\"throw\"]\n\t\t\t\t: GlobalOpts[\"throw\"] extends true\n\t\t\t\t\t? true\n\t\t\t\t\t: false\n\t\t>\n\t> => {\n\t\treturn (await fetch(path as string, {\n\t\t\t...callOptions[0],\n\t\t})) as any;\n\t};\n};\n\nexport * from \"./error\";\n"],"mappings":";;;;;;AAuFA,MAAa,gBAIZ,YACI;CACJ,MAAM,6CAAoB,WAAW,EAAE,CAAC;AAiBxC,QAAO,OAMN,MACA,GAAG,gBAkBC;AACJ,SAAQ,MAAM,MAAM,MAAgB,EACnC,GAAG,YAAY,IACf,CAAC"}
1
+ {"version":3,"file":"client.cjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import type {\n\tBetterFetchOption,\n\tBetterFetchResponse,\n} from \"@better-fetch/fetch\";\nimport { createFetch } from \"@better-fetch/fetch\";\nimport type { Endpoint } from \"./endpoint\";\nimport type { HasRequiredKeys, Prettify, UnionToIntersection } from \"./helper\";\nimport type { Router } from \"./router\";\n\nexport type HasRequired<T extends object> = T extends {}\n\t? false\n\t: T extends {\n\t\t\t\tbody?: any;\n\t\t\t\tquery?: any;\n\t\t\t\tparams?: any;\n\t\t\t}\n\t\t? T[\"body\"] extends object\n\t\t\t? HasRequiredKeys<T[\"body\"]> extends true\n\t\t\t\t? true\n\t\t\t\t: T[\"query\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t\t: false\n\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t: false\n\t\t\t: T[\"query\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t\t? true\n\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t: false\n\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t: false\n\t\t: false;\n\ntype InferContext<T> = T extends (ctx: infer Ctx) => any\n\t? Ctx extends object\n\t\t? Ctx\n\t\t: never\n\t: never;\n\nexport interface ClientOptions extends BetterFetchOption {\n\tbaseURL?: string;\n}\n\ntype WithRequired<T, K> = T & {\n\t[P in K extends string ? K : never]-?: T[P extends keyof T ? P : never];\n};\n\ntype InferClientRoutes<T extends Record<string, Endpoint>> = {\n\t[K in keyof T]: T[K] extends Endpoint<any, infer O>\n\t\t? O extends\n\t\t\t\t| { metadata: { scope: \"http\" } }\n\t\t\t\t| { metadata: { scope: \"server\" } }\n\t\t\t\t| { metadata: { SERVER_ONLY: true } }\n\t\t\t\t| { metadata: { isAction: false } }\n\t\t\t? never\n\t\t\t: T[K]\n\t\t: T[K];\n};\n\nexport type RequiredOptionKeys<\n\tC extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = (undefined extends C[\"body\"]\n\t? {}\n\t: {\n\t\t\tbody: true;\n\t\t}) &\n\t(undefined extends C[\"query\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tquery: true;\n\t\t\t}) &\n\t(undefined extends C[\"params\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tparams: true;\n\t\t\t});\n\nexport const createClient = <\n\tR extends Router | Router[\"endpoints\"],\n\tGlobalOpts extends ClientOptions = ClientOptions,\n>(\n\toptions?: GlobalOpts,\n) => {\n\tconst fetch = createFetch(options ?? {});\n\ttype API = InferClientRoutes<\n\t\tR extends { endpoints: Record<string, Endpoint> } ? R[\"endpoints\"] : R\n\t>;\n\ttype Options = API extends {\n\t\t[key: string]: infer T;\n\t}\n\t\t? T extends Endpoint\n\t\t\t? {\n\t\t\t\t\t[key in T[\"options\"][\"method\"] extends \"GET\"\n\t\t\t\t\t\t? T[\"path\"]\n\t\t\t\t\t\t: `@${T[\"options\"][\"method\"] extends string ? Lowercase<T[\"options\"][\"method\"]> : never}${T[\"path\"]}`]: T;\n\t\t\t\t}\n\t\t\t: {}\n\t\t: {};\n\n\ttype O = Prettify<UnionToIntersection<Options>>;\n\treturn async <\n\t\tOPT extends O,\n\t\tK extends keyof OPT,\n\t\tC extends InferContext<OPT[K]>,\n\t\tCallOpts extends BetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t>(\n\t\tpath: K,\n\t\t...callOptions: HasRequired<C> extends true\n\t\t\t? [\n\t\t\t\t\tWithRequired<\n\t\t\t\t\t\tBetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t\t\t\t\t\tkeyof RequiredOptionKeys<C>\n\t\t\t\t\t>,\n\t\t\t\t]\n\t\t\t: [CallOpts?]\n\t): Promise<\n\t\tBetterFetchResponse<\n\t\t\tAwaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>,\n\t\t\tunknown,\n\t\t\tCallOpts[\"throw\"] extends boolean\n\t\t\t\t? CallOpts[\"throw\"]\n\t\t\t\t: GlobalOpts[\"throw\"] extends true\n\t\t\t\t\t? true\n\t\t\t\t\t: false\n\t\t>\n\t> => {\n\t\treturn (await fetch(path as string, {\n\t\t\t...callOptions[0],\n\t\t})) as any;\n\t};\n};\n\nexport * from \"./error\";\n"],"mappings":";;;;AAuFA,MAAa,gBAIZ,YACI;CACJ,MAAM,SAAA,GAAA,oBAAA,YAAA,CAAoB,WAAW,CAAC,CAAC;CAiBvC,OAAO,OAMN,MACA,GAAG,gBAkBC;EACJ,OAAQ,MAAM,MAAM,MAAgB,EACnC,GAAG,YAAY,GAChB,CAAC;CACF;AACD"}
package/dist/client.d.cts CHANGED
@@ -1,9 +1,8 @@
1
- import { HasRequiredKeys, UnionToIntersection } from "./helper.cjs";
2
1
  import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes } from "./error.cjs";
2
+ import { HasRequiredKeys, UnionToIntersection } from "./helper.cjs";
3
3
  import { Endpoint } from "./endpoint.cjs";
4
4
  import { Router } from "./router.cjs";
5
5
  import { BetterFetchOption, BetterFetchResponse } from "@better-fetch/fetch";
6
-
7
6
  //#region src/client.d.ts
8
7
  type HasRequired<T extends object> = T extends {} ? false : T extends {
9
8
  body?: any;
@@ -14,7 +13,7 @@ type InferContext<T> = T extends ((ctx: infer Ctx) => any) ? Ctx extends object
14
13
  interface ClientOptions extends BetterFetchOption {
15
14
  baseURL?: string;
16
15
  }
17
- type WithRequired<T, K> = T & { [P in K extends string ? K : never]-?: T[P extends keyof T ? P : never] };
16
+ type WithRequired<T, K> = T & { [P in K extends string ? K : never]-?: T[P extends keyof T ? P : never]; };
18
17
  type InferClientRoutes<T extends Record<string, Endpoint>> = { [K in keyof T]: T[K] extends Endpoint<any, infer O> ? O extends {
19
18
  metadata: {
20
19
  scope: "http";
@@ -31,7 +30,7 @@ type InferClientRoutes<T extends Record<string, Endpoint>> = { [K in keyof T]: T
31
30
  metadata: {
32
31
  isAction: false;
33
32
  };
34
- } ? never : T[K] : T[K] };
33
+ } ? never : T[K] : T[K]; };
35
34
  type RequiredOptionKeys<C extends {
36
35
  body?: any;
37
36
  query?: any;
@@ -43,11 +42,11 @@ type RequiredOptionKeys<C extends {
43
42
  }) & (undefined extends C["params"] ? {} : {
44
43
  params: true;
45
44
  });
46
- declare const createClient: <R extends Router | Router["endpoints"], GlobalOpts extends ClientOptions = ClientOptions>(options?: GlobalOpts) => <OPT extends (UnionToIntersection<InferClientRoutes<R extends {
45
+ declare const createClient: <R extends Router | Router["endpoints"], GlobalOpts extends ClientOptions = ClientOptions>(options?: GlobalOpts) => <OPT extends UnionToIntersection<InferClientRoutes<R extends {
47
46
  endpoints: Record<string, Endpoint>;
48
47
  } ? R["endpoints"] : R> extends {
49
48
  [key: string]: infer T_1;
50
- } ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1 } : {} : {}> extends infer T ? { [K_1 in keyof T]: T[K_1] } : never), K extends keyof OPT, C extends InferContext<OPT[K]>, CallOpts extends BetterFetchOption<C["body"], C["query"], C["params"]>>(path: K, ...callOptions: HasRequired<C> extends true ? [WithRequired<BetterFetchOption<C["body"], C["query"], C["params"]>, keyof RequiredOptionKeys<C>>] : [CallOpts?]) => Promise<BetterFetchResponse<Awaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>, unknown, CallOpts["throw"] extends boolean ? CallOpts["throw"] : GlobalOpts["throw"] extends true ? true : false>>;
49
+ } ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1; } : {} : {}> extends (infer T) ? { [K_1 in keyof T]: T[K_1]; } : never, K extends keyof OPT, C extends InferContext<OPT[K]>, CallOpts extends BetterFetchOption<C["body"], C["query"], C["params"]>>(path: K, ...callOptions: HasRequired<C> extends true ? [WithRequired<BetterFetchOption<C["body"], C["query"], C["params"]>, keyof RequiredOptionKeys<C>>] : [CallOpts?]) => Promise<BetterFetchResponse<Awaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>, unknown, CallOpts["throw"] extends boolean ? CallOpts["throw"] : GlobalOpts["throw"] extends true ? true : false>>;
51
50
  //#endregion
52
51
  export { APIError, BetterCallError, ClientOptions, HasRequired, RequiredOptionKeys, Status, ValidationError, createClient, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes };
53
52
  //# sourceMappingURL=client.d.cts.map
package/dist/client.d.mts CHANGED
@@ -1,9 +1,8 @@
1
- import { HasRequiredKeys, UnionToIntersection } from "./helper.mjs";
2
1
  import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
2
+ import { HasRequiredKeys, UnionToIntersection } from "./helper.mjs";
3
3
  import { Endpoint } from "./endpoint.mjs";
4
4
  import { Router } from "./router.mjs";
5
5
  import { BetterFetchOption, BetterFetchResponse } from "@better-fetch/fetch";
6
-
7
6
  //#region src/client.d.ts
8
7
  type HasRequired<T extends object> = T extends {} ? false : T extends {
9
8
  body?: any;
@@ -14,7 +13,7 @@ type InferContext<T> = T extends ((ctx: infer Ctx) => any) ? Ctx extends object
14
13
  interface ClientOptions extends BetterFetchOption {
15
14
  baseURL?: string;
16
15
  }
17
- type WithRequired<T, K> = T & { [P in K extends string ? K : never]-?: T[P extends keyof T ? P : never] };
16
+ type WithRequired<T, K> = T & { [P in K extends string ? K : never]-?: T[P extends keyof T ? P : never]; };
18
17
  type InferClientRoutes<T extends Record<string, Endpoint>> = { [K in keyof T]: T[K] extends Endpoint<any, infer O> ? O extends {
19
18
  metadata: {
20
19
  scope: "http";
@@ -31,7 +30,7 @@ type InferClientRoutes<T extends Record<string, Endpoint>> = { [K in keyof T]: T
31
30
  metadata: {
32
31
  isAction: false;
33
32
  };
34
- } ? never : T[K] : T[K] };
33
+ } ? never : T[K] : T[K]; };
35
34
  type RequiredOptionKeys<C extends {
36
35
  body?: any;
37
36
  query?: any;
@@ -43,11 +42,11 @@ type RequiredOptionKeys<C extends {
43
42
  }) & (undefined extends C["params"] ? {} : {
44
43
  params: true;
45
44
  });
46
- declare const createClient: <R extends Router | Router["endpoints"], GlobalOpts extends ClientOptions = ClientOptions>(options?: GlobalOpts) => <OPT extends (UnionToIntersection<InferClientRoutes<R extends {
45
+ declare const createClient: <R extends Router | Router["endpoints"], GlobalOpts extends ClientOptions = ClientOptions>(options?: GlobalOpts) => <OPT extends UnionToIntersection<InferClientRoutes<R extends {
47
46
  endpoints: Record<string, Endpoint>;
48
47
  } ? R["endpoints"] : R> extends {
49
48
  [key: string]: infer T_1;
50
- } ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1 } : {} : {}> extends infer T ? { [K_1 in keyof T]: T[K_1] } : never), K extends keyof OPT, C extends InferContext<OPT[K]>, CallOpts extends BetterFetchOption<C["body"], C["query"], C["params"]>>(path: K, ...callOptions: HasRequired<C> extends true ? [WithRequired<BetterFetchOption<C["body"], C["query"], C["params"]>, keyof RequiredOptionKeys<C>>] : [CallOpts?]) => Promise<BetterFetchResponse<Awaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>, unknown, CallOpts["throw"] extends boolean ? CallOpts["throw"] : GlobalOpts["throw"] extends true ? true : false>>;
49
+ } ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1; } : {} : {}> extends (infer T) ? { [K_1 in keyof T]: T[K_1]; } : never, K extends keyof OPT, C extends InferContext<OPT[K]>, CallOpts extends BetterFetchOption<C["body"], C["query"], C["params"]>>(path: K, ...callOptions: HasRequired<C> extends true ? [WithRequired<BetterFetchOption<C["body"], C["query"], C["params"]>, keyof RequiredOptionKeys<C>>] : [CallOpts?]) => Promise<BetterFetchResponse<Awaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>, unknown, CallOpts["throw"] extends boolean ? CallOpts["throw"] : GlobalOpts["throw"] extends true ? true : false>>;
51
50
  //#endregion
52
51
  export { APIError, BetterCallError, ClientOptions, HasRequired, RequiredOptionKeys, Status, ValidationError, createClient, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes };
53
52
  //# sourceMappingURL=client.d.mts.map
package/dist/client.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import { APIError, BetterCallError, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
2
2
  import { createFetch } from "@better-fetch/fetch";
3
-
4
3
  //#region src/client.ts
5
4
  const createClient = (options) => {
6
5
  const fetch = createFetch(options ?? {});
@@ -8,7 +7,7 @@ const createClient = (options) => {
8
7
  return await fetch(path, { ...callOptions[0] });
9
8
  };
10
9
  };
11
-
12
10
  //#endregion
13
11
  export { APIError, BetterCallError, ValidationError, createClient, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes };
12
+
14
13
  //# sourceMappingURL=client.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import {\n\ttype BetterFetchOption,\n\ttype BetterFetchResponse,\n\tcreateFetch,\n} from \"@better-fetch/fetch\";\nimport type { Router } from \"./router\";\nimport type { HasRequiredKeys, Prettify, UnionToIntersection } from \"./helper\";\nimport type { Endpoint } from \"./endpoint\";\n\nexport type HasRequired<T extends object> = T extends {}\n\t? false\n\t: T extends {\n\t\t\t\tbody?: any;\n\t\t\t\tquery?: any;\n\t\t\t\tparams?: any;\n\t\t\t}\n\t\t? T[\"body\"] extends object\n\t\t\t? HasRequiredKeys<T[\"body\"]> extends true\n\t\t\t\t? true\n\t\t\t\t: T[\"query\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t\t: false\n\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t: false\n\t\t\t: T[\"query\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t\t? true\n\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t: false\n\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t: false\n\t\t: false;\n\ntype InferContext<T> = T extends (ctx: infer Ctx) => any\n\t? Ctx extends object\n\t\t? Ctx\n\t\t: never\n\t: never;\n\nexport interface ClientOptions extends BetterFetchOption {\n\tbaseURL?: string;\n}\n\ntype WithRequired<T, K> = T & {\n\t[P in K extends string ? K : never]-?: T[P extends keyof T ? P : never];\n};\n\ntype InferClientRoutes<T extends Record<string, Endpoint>> = {\n\t[K in keyof T]: T[K] extends Endpoint<any, infer O>\n\t\t? O extends\n\t\t\t\t| { metadata: { scope: \"http\" } }\n\t\t\t\t| { metadata: { scope: \"server\" } }\n\t\t\t\t| { metadata: { SERVER_ONLY: true } }\n\t\t\t\t| { metadata: { isAction: false } }\n\t\t\t? never\n\t\t\t: T[K]\n\t\t: T[K];\n};\n\nexport type RequiredOptionKeys<\n\tC extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = (undefined extends C[\"body\"]\n\t? {}\n\t: {\n\t\t\tbody: true;\n\t\t}) &\n\t(undefined extends C[\"query\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tquery: true;\n\t\t\t}) &\n\t(undefined extends C[\"params\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tparams: true;\n\t\t\t});\n\nexport const createClient = <\n\tR extends Router | Router[\"endpoints\"],\n\tGlobalOpts extends ClientOptions = ClientOptions,\n>(\n\toptions?: GlobalOpts,\n) => {\n\tconst fetch = createFetch(options ?? {});\n\ttype API = InferClientRoutes<\n\t\tR extends { endpoints: Record<string, Endpoint> } ? R[\"endpoints\"] : R\n\t>;\n\ttype Options = API extends {\n\t\t[key: string]: infer T;\n\t}\n\t\t? T extends Endpoint\n\t\t\t? {\n\t\t\t\t\t[key in T[\"options\"][\"method\"] extends \"GET\"\n\t\t\t\t\t\t? T[\"path\"]\n\t\t\t\t\t\t: `@${T[\"options\"][\"method\"] extends string ? Lowercase<T[\"options\"][\"method\"]> : never}${T[\"path\"]}`]: T;\n\t\t\t\t}\n\t\t\t: {}\n\t\t: {};\n\n\ttype O = Prettify<UnionToIntersection<Options>>;\n\treturn async <\n\t\tOPT extends O,\n\t\tK extends keyof OPT,\n\t\tC extends InferContext<OPT[K]>,\n\t\tCallOpts extends BetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t>(\n\t\tpath: K,\n\t\t...callOptions: HasRequired<C> extends true\n\t\t\t? [\n\t\t\t\t\tWithRequired<\n\t\t\t\t\t\tBetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t\t\t\t\t\tkeyof RequiredOptionKeys<C>\n\t\t\t\t\t>,\n\t\t\t\t]\n\t\t\t: [CallOpts?]\n\t): Promise<\n\t\tBetterFetchResponse<\n\t\t\tAwaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>,\n\t\t\tunknown,\n\t\t\tCallOpts[\"throw\"] extends boolean\n\t\t\t\t? CallOpts[\"throw\"]\n\t\t\t\t: GlobalOpts[\"throw\"] extends true\n\t\t\t\t\t? true\n\t\t\t\t\t: false\n\t\t>\n\t> => {\n\t\treturn (await fetch(path as string, {\n\t\t\t...callOptions[0],\n\t\t})) as any;\n\t};\n};\n\nexport * from \"./error\";\n"],"mappings":";;;;AAuFA,MAAa,gBAIZ,YACI;CACJ,MAAM,QAAQ,YAAY,WAAW,EAAE,CAAC;AAiBxC,QAAO,OAMN,MACA,GAAG,gBAkBC;AACJ,SAAQ,MAAM,MAAM,MAAgB,EACnC,GAAG,YAAY,IACf,CAAC"}
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import type {\n\tBetterFetchOption,\n\tBetterFetchResponse,\n} from \"@better-fetch/fetch\";\nimport { createFetch } from \"@better-fetch/fetch\";\nimport type { Endpoint } from \"./endpoint\";\nimport type { HasRequiredKeys, Prettify, UnionToIntersection } from \"./helper\";\nimport type { Router } from \"./router\";\n\nexport type HasRequired<T extends object> = T extends {}\n\t? false\n\t: T extends {\n\t\t\t\tbody?: any;\n\t\t\t\tquery?: any;\n\t\t\t\tparams?: any;\n\t\t\t}\n\t\t? T[\"body\"] extends object\n\t\t\t? HasRequiredKeys<T[\"body\"]> extends true\n\t\t\t\t? true\n\t\t\t\t: T[\"query\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t\t: false\n\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t: false\n\t\t\t: T[\"query\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t\t? true\n\t\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t\t: false\n\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t: false\n\t\t: false;\n\ntype InferContext<T> = T extends (ctx: infer Ctx) => any\n\t? Ctx extends object\n\t\t? Ctx\n\t\t: never\n\t: never;\n\nexport interface ClientOptions extends BetterFetchOption {\n\tbaseURL?: string;\n}\n\ntype WithRequired<T, K> = T & {\n\t[P in K extends string ? K : never]-?: T[P extends keyof T ? P : never];\n};\n\ntype InferClientRoutes<T extends Record<string, Endpoint>> = {\n\t[K in keyof T]: T[K] extends Endpoint<any, infer O>\n\t\t? O extends\n\t\t\t\t| { metadata: { scope: \"http\" } }\n\t\t\t\t| { metadata: { scope: \"server\" } }\n\t\t\t\t| { metadata: { SERVER_ONLY: true } }\n\t\t\t\t| { metadata: { isAction: false } }\n\t\t\t? never\n\t\t\t: T[K]\n\t\t: T[K];\n};\n\nexport type RequiredOptionKeys<\n\tC extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = (undefined extends C[\"body\"]\n\t? {}\n\t: {\n\t\t\tbody: true;\n\t\t}) &\n\t(undefined extends C[\"query\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tquery: true;\n\t\t\t}) &\n\t(undefined extends C[\"params\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tparams: true;\n\t\t\t});\n\nexport const createClient = <\n\tR extends Router | Router[\"endpoints\"],\n\tGlobalOpts extends ClientOptions = ClientOptions,\n>(\n\toptions?: GlobalOpts,\n) => {\n\tconst fetch = createFetch(options ?? {});\n\ttype API = InferClientRoutes<\n\t\tR extends { endpoints: Record<string, Endpoint> } ? R[\"endpoints\"] : R\n\t>;\n\ttype Options = API extends {\n\t\t[key: string]: infer T;\n\t}\n\t\t? T extends Endpoint\n\t\t\t? {\n\t\t\t\t\t[key in T[\"options\"][\"method\"] extends \"GET\"\n\t\t\t\t\t\t? T[\"path\"]\n\t\t\t\t\t\t: `@${T[\"options\"][\"method\"] extends string ? Lowercase<T[\"options\"][\"method\"]> : never}${T[\"path\"]}`]: T;\n\t\t\t\t}\n\t\t\t: {}\n\t\t: {};\n\n\ttype O = Prettify<UnionToIntersection<Options>>;\n\treturn async <\n\t\tOPT extends O,\n\t\tK extends keyof OPT,\n\t\tC extends InferContext<OPT[K]>,\n\t\tCallOpts extends BetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t>(\n\t\tpath: K,\n\t\t...callOptions: HasRequired<C> extends true\n\t\t\t? [\n\t\t\t\t\tWithRequired<\n\t\t\t\t\t\tBetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t\t\t\t\t\tkeyof RequiredOptionKeys<C>\n\t\t\t\t\t>,\n\t\t\t\t]\n\t\t\t: [CallOpts?]\n\t): Promise<\n\t\tBetterFetchResponse<\n\t\t\tAwaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>,\n\t\t\tunknown,\n\t\t\tCallOpts[\"throw\"] extends boolean\n\t\t\t\t? CallOpts[\"throw\"]\n\t\t\t\t: GlobalOpts[\"throw\"] extends true\n\t\t\t\t\t? true\n\t\t\t\t\t: false\n\t\t>\n\t> => {\n\t\treturn (await fetch(path as string, {\n\t\t\t...callOptions[0],\n\t\t})) as any;\n\t};\n};\n\nexport * from \"./error\";\n"],"mappings":";;;AAuFA,MAAa,gBAIZ,YACI;CACJ,MAAM,QAAQ,YAAY,WAAW,CAAC,CAAC;CAiBvC,OAAO,OAMN,MACA,GAAG,gBAkBC;EACJ,OAAQ,MAAM,MAAM,MAAgB,EACnC,GAAG,YAAY,GAChB,CAAC;CACF;AACD"}
package/dist/context.cjs CHANGED
@@ -1,9 +1,8 @@
1
- const require_error = require('./error.cjs');
2
- const require_utils = require('./utils.cjs');
3
- const require_validator = require('./validator.cjs');
4
- const require_crypto = require('./crypto.cjs');
5
- const require_cookies = require('./cookies.cjs');
6
-
1
+ const require_crypto = require("./crypto.cjs");
2
+ const require_error = require("./error.cjs");
3
+ const require_utils = require("./utils.cjs");
4
+ const require_cookies = require("./cookies.cjs");
5
+ const require_validator = require("./validator.cjs");
7
6
  //#region src/context.ts
8
7
  const createInternalContext = async (context, { options, path }) => {
9
8
  const headers = new Headers();
@@ -97,7 +96,7 @@ const createInternalContext = async (context, { options, path }) => {
97
96
  }
98
97
  return internalContext;
99
98
  };
100
-
101
99
  //#endregion
102
100
  exports.createInternalContext = createInternalContext;
101
+
103
102
  //# sourceMappingURL=context.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.cjs","names":["runValidation","ValidationError","isRequest","parseCookies","getCookieKey","verifySignature","getCryptoKey","serializeCookie","serializeSignedCookie","APIError"],"sources":["../src/context.ts"],"sourcesContent":["import type { EndpointOptions } from \"./endpoint\";\nimport {\n\ttype statusCodes,\n\tAPIError,\n\tValidationError,\n\ttype Status,\n} from \"./error\";\nimport type {\n\tInferParamPath,\n\tInferParamWildCard,\n\tIsEmptyObject,\n\tPrettify,\n\tUnionToIntersection,\n} from \"./helper\";\nimport type {\n\tMiddleware,\n\tMiddlewareContext,\n\tMiddlewareOptions,\n} from \"./middleware\";\nimport { runValidation } from \"./validator\";\nimport {\n\tgetCookieKey,\n\tparseCookies,\n\tserializeCookie,\n\tserializeSignedCookie,\n\ttype CookieOptions,\n\ttype CookiePrefixOptions,\n} from \"./cookies\";\nimport { getCryptoKey, verifySignature } from \"./crypto\";\nimport type { StandardSchemaV1 } from \"./standard-schema\";\nimport { isRequest } from \"./utils\";\n\nexport type HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\nexport type Method = HTTPMethod | \"*\";\n\nexport type InferBodyInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tBody = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer B;\n\t\t};\n\t}\n\t\t? B\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"body\"]>\n\t\t\t: undefined,\n> = undefined extends Body\n\t? {\n\t\t\tbody?: Body;\n\t\t}\n\t: {\n\t\t\tbody: Body;\n\t\t};\n\nexport type InferBody<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer Body;\n\t\t};\n\t}\n\t\t? Body\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"body\"]>\n\t\t\t: any;\n\nexport type InferQueryInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tQuery = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined,\n> = undefined extends Query\n\t? {\n\t\t\tquery?: Query;\n\t\t}\n\t: {\n\t\t\tquery: Query;\n\t\t};\n\nexport type InferQuery<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined;\n\nexport type InferMethod<Options extends EndpointOptions> =\n\tOptions[\"method\"] extends Array<Method>\n\t\t? Options[\"method\"][number]\n\t\t: Options[\"method\"] extends \"*\"\n\t\t\t? HTTPMethod\n\t\t\t: Options[\"method\"];\n\nexport type InferInputMethod<\n\tOptions extends EndpointOptions,\n\tMethod = Options[\"method\"] extends Array<any>\n\t\t? Options[\"method\"][number] | undefined\n\t\t: Options[\"method\"] extends \"*\"\n\t\t\t? HTTPMethod\n\t\t\t: Options[\"method\"] | undefined,\n> = undefined extends Method\n\t? {\n\t\t\tmethod?: Method;\n\t\t}\n\t: {\n\t\t\tmethod: Method;\n\t\t};\n\nexport type InferParam<Path extends string> = [Path] extends [never]\n\t? Record<string, any> | undefined\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? Record<string, any> | undefined\n\t\t: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\nexport type InferParamInput<Path extends string> = [Path] extends [never]\n\t? { params?: Record<string, any> }\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? {\n\t\t\t\tparams?: Record<string, any>;\n\t\t\t}\n\t\t: {\n\t\t\t\tparams: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\t\t\t};\n\nexport type InferRequest<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true ? Request : Request | undefined;\n\nexport type InferRequestInput<\n\tOption extends EndpointOptions | MiddlewareOptions,\n> = Option[\"requireRequest\"] extends true\n\t? {\n\t\t\trequest: Request;\n\t\t}\n\t: {\n\t\t\trequest?: Request;\n\t\t};\n\nexport type InferHeaders<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true ? Headers : Headers | undefined;\n\nexport type InferHeadersInput<\n\tOption extends EndpointOptions | MiddlewareOptions,\n> = Option[\"requireHeaders\"] extends true\n\t? {\n\t\t\theaders: HeadersInit;\n\t\t}\n\t: {\n\t\t\theaders?: HeadersInit;\n\t\t};\n\nexport type InferUse<Opts extends EndpointOptions[\"use\"]> =\n\tOpts extends Middleware[]\n\t\t? UnionToIntersection<Awaited<ReturnType<Opts[number]>>>\n\t\t: {};\n\nexport type InferMiddlewareBody<Options extends MiddlewareOptions> =\n\tOptions[\"body\"] extends StandardSchemaV1<infer T> ? T : any;\n\nexport type InferMiddlewareQuery<Options extends MiddlewareOptions> =\n\tOptions[\"query\"] extends StandardSchemaV1<infer T>\n\t\t? T\n\t\t: Record<string, any> | undefined;\n\nexport type InputContext<\n\tPath extends string,\n\tOptions extends EndpointOptions,\n> = InferBodyInput<Options> &\n\tInferInputMethod<Options> &\n\tInferQueryInput<Options> &\n\tInferParamInput<Path> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\treturnStatus?: boolean;\n\t\tuse?: Middleware[];\n\t\tpath?: string;\n\t\tcontext?: Record<string, any>;\n\t};\n\nexport const createInternalContext = async (\n\tcontext: InputContext<any, any>,\n\t{\n\t\toptions,\n\t\tpath,\n\t}: {\n\t\toptions: EndpointOptions;\n\t\tpath?: string;\n\t},\n) => {\n\tconst headers = new Headers();\n\tlet responseStatus: Status | undefined = undefined;\n\n\tconst { data, error } = await runValidation(options, context);\n\tif (error) {\n\t\tthrow new ValidationError(error.message, error.issues);\n\t}\n\tconst requestHeaders: Headers | null =\n\t\t\"headers\" in context\n\t\t\t? context.headers instanceof Headers\n\t\t\t\t? context.headers\n\t\t\t\t: new Headers(context.headers)\n\t\t\t: \"request\" in context && isRequest(context.request)\n\t\t\t\t? context.request.headers\n\t\t\t\t: null;\n\tconst requestCookies = requestHeaders?.get(\"cookie\");\n\tconst parsedCookies = requestCookies\n\t\t? parseCookies(requestCookies)\n\t\t: undefined;\n\n\tconst internalContext = {\n\t\t...context,\n\t\tbody: data.body,\n\t\tquery: data.query,\n\t\tpath: context.path || path || \"virtual:\",\n\t\tcontext: \"context\" in context && context.context ? context.context : {},\n\t\treturned: undefined as any,\n\t\theaders: context?.headers,\n\t\trequest: context?.request,\n\t\tparams: \"params\" in context ? context.params : undefined,\n\t\tmethod:\n\t\t\tcontext.method ??\n\t\t\t(Array.isArray(options.method)\n\t\t\t\t? options.method[0]\n\t\t\t\t: options.method === \"*\"\n\t\t\t\t\t? \"GET\"\n\t\t\t\t\t: options.method),\n\t\tsetHeader: (key: string, value: string) => {\n\t\t\theaders.set(key, value);\n\t\t},\n\t\tgetHeader: (key: string) => {\n\t\t\tif (!requestHeaders) return null;\n\t\t\treturn requestHeaders.get(key);\n\t\t},\n\t\tgetCookie: (key: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn parsedCookies?.get(finalKey) || null;\n\t\t},\n\t\tgetSignedCookie: async (\n\t\t\tkey: string,\n\t\t\tsecret: string,\n\t\t\tprefix?: CookiePrefixOptions,\n\t\t) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst value = parsedCookies?.get(finalKey);\n\t\t\tif (!value) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signatureStartPos = value.lastIndexOf(\".\");\n\t\t\tif (signatureStartPos < 1) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signedValue = value.substring(0, signatureStartPos);\n\t\t\tconst signature = value.substring(signatureStartPos + 1);\n\t\t\tif (signature.length !== 44 || !signature.endsWith(\"=\")) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst secretKey = await getCryptoKey(secret);\n\t\t\tconst isVerified = await verifySignature(\n\t\t\t\tsignature,\n\t\t\t\tsignedValue,\n\t\t\t\tsecretKey,\n\t\t\t);\n\t\t\treturn isVerified ? signedValue : false;\n\t\t},\n\t\tsetCookie: (key: string, value: string, options?: CookieOptions) => {\n\t\t\tconst cookie = serializeCookie(key, value, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tsetSignedCookie: async (\n\t\t\tkey: string,\n\t\t\tvalue: string,\n\t\t\tsecret: string,\n\t\t\toptions?: CookieOptions,\n\t\t) => {\n\t\t\tconst cookie = await serializeSignedCookie(key, value, secret, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tredirect: (url: string) => {\n\t\t\theaders.set(\"location\", url);\n\t\t\treturn new APIError(\"FOUND\", undefined, headers);\n\t\t},\n\t\terror: (\n\t\t\tstatus: keyof typeof statusCodes | Status,\n\t\t\tbody?:\n\t\t\t\t| {\n\t\t\t\t\t\tmessage?: string;\n\t\t\t\t\t\tcode?: string;\n\t\t\t\t }\n\t\t\t\t| undefined,\n\t\t\theaders?: HeadersInit,\n\t\t) => {\n\t\t\treturn new APIError(status, body, headers);\n\t\t},\n\t\tsetStatus: (status: Status) => {\n\t\t\tresponseStatus = status;\n\t\t},\n\t\tjson: (\n\t\t\tjson: Record<string, any>,\n\t\t\trouterResponse?:\n\t\t\t\t| {\n\t\t\t\t\t\tstatus?: number;\n\t\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\t\tresponse?: Response;\n\t\t\t\t\t\tbody?: Record<string, any>;\n\t\t\t\t }\n\t\t\t\t| Response,\n\t\t) => {\n\t\t\tif (!context.asResponse) {\n\t\t\t\treturn json;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbody: routerResponse?.body || json,\n\t\t\t\trouterResponse,\n\t\t\t\t_flag: \"json\",\n\t\t\t};\n\t\t},\n\t\tresponseHeaders: headers,\n\t\tget responseStatus() {\n\t\t\treturn responseStatus;\n\t\t},\n\t};\n\t//if context was shimmed through the input we want to apply it\n\tfor (const middleware of options.use || []) {\n\t\tconst response = (await middleware({\n\t\t\t...internalContext,\n\t\t\treturnHeaders: true,\n\t\t\tasResponse: false,\n\t\t})) as {\n\t\t\tresponse?: any;\n\t\t\theaders?: Headers;\n\t\t};\n\t\tif (response.response) {\n\t\t\tObject.assign(internalContext.context, response.response);\n\t\t}\n\t\t/**\n\t\t * Apply headers from the middleware to the endpoint headers\n\t\t */\n\t\tif (response.headers) {\n\t\t\tresponse.headers.forEach((value, key) => {\n\t\t\t\tinternalContext.responseHeaders.set(key, value);\n\t\t\t});\n\t\t}\n\t}\n\treturn internalContext;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"context.cjs","names":["runValidation","ValidationError","isRequest","parseCookies","getCookieKey","verifySignature","getCryptoKey","serializeCookie","serializeSignedCookie","APIError"],"sources":["../src/context.ts"],"sourcesContent":["import type { CookieOptions, CookiePrefixOptions } from \"./cookies\";\nimport {\n\tgetCookieKey,\n\tparseCookies,\n\tserializeCookie,\n\tserializeSignedCookie,\n} from \"./cookies\";\nimport { getCryptoKey, verifySignature } from \"./crypto\";\nimport type { EndpointOptions } from \"./endpoint\";\nimport type { Status, statusCodes } from \"./error\";\nimport { APIError, ValidationError } from \"./error\";\nimport type {\n\tInferParamPath,\n\tInferParamWildCard,\n\tIsEmptyObject,\n\tPrettify,\n\tUnionToIntersection,\n} from \"./helper\";\nimport type { Middleware, MiddlewareOptions } from \"./middleware\";\nimport type { StandardSchemaV1 } from \"./standard-schema\";\nimport { isRequest } from \"./utils\";\nimport { runValidation } from \"./validator\";\n\nexport type HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\nexport type Method = HTTPMethod | \"*\";\n\nexport type InferBodyInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tBody = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer B;\n\t\t};\n\t}\n\t\t? B\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"body\"]>\n\t\t\t: undefined,\n> = undefined extends Body\n\t? {\n\t\t\tbody?: Body;\n\t\t}\n\t: {\n\t\t\tbody: Body;\n\t\t};\n\nexport type InferBody<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer Body;\n\t\t};\n\t}\n\t\t? Body\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"body\"]>\n\t\t\t: any;\n\nexport type InferQueryInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tQuery = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined,\n> = undefined extends Query\n\t? {\n\t\t\tquery?: Query;\n\t\t}\n\t: {\n\t\t\tquery: Query;\n\t\t};\n\nexport type InferQuery<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined;\n\nexport type InferMethod<Options extends EndpointOptions> =\n\tOptions[\"method\"] extends Array<Method>\n\t\t? Options[\"method\"][number]\n\t\t: Options[\"method\"] extends \"*\"\n\t\t\t? HTTPMethod\n\t\t\t: Options[\"method\"];\n\nexport type InferInputMethod<\n\tOptions extends EndpointOptions,\n\tMethod = Options[\"method\"] extends Array<any>\n\t\t? Options[\"method\"][number] | undefined\n\t\t: Options[\"method\"] extends \"*\"\n\t\t\t? HTTPMethod\n\t\t\t: Options[\"method\"] | undefined,\n> = undefined extends Method\n\t? {\n\t\t\tmethod?: Method;\n\t\t}\n\t: {\n\t\t\tmethod: Method;\n\t\t};\n\nexport type InferParam<Path extends string> = [Path] extends [never]\n\t? Record<string, any> | undefined\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? Record<string, any> | undefined\n\t\t: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\nexport type InferParamInput<Path extends string> = [Path] extends [never]\n\t? { params?: Record<string, any> }\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? {\n\t\t\t\tparams?: Record<string, any>;\n\t\t\t}\n\t\t: {\n\t\t\t\tparams: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\t\t\t};\n\nexport type InferRequest<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true ? Request : Request | undefined;\n\nexport type InferRequestInput<\n\tOption extends EndpointOptions | MiddlewareOptions,\n> = Option[\"requireRequest\"] extends true\n\t? {\n\t\t\trequest: Request;\n\t\t}\n\t: {\n\t\t\trequest?: Request;\n\t\t};\n\nexport type InferHeaders<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true ? Headers : Headers | undefined;\n\nexport type InferHeadersInput<\n\tOption extends EndpointOptions | MiddlewareOptions,\n> = Option[\"requireHeaders\"] extends true\n\t? {\n\t\t\theaders: HeadersInit;\n\t\t}\n\t: {\n\t\t\theaders?: HeadersInit;\n\t\t};\n\nexport type InferUse<Opts extends EndpointOptions[\"use\"]> =\n\tOpts extends Middleware[]\n\t\t? UnionToIntersection<Awaited<ReturnType<Opts[number]>>>\n\t\t: {};\n\nexport type InferMiddlewareBody<Options extends MiddlewareOptions> =\n\tOptions[\"body\"] extends StandardSchemaV1<infer T> ? T : any;\n\nexport type InferMiddlewareQuery<Options extends MiddlewareOptions> =\n\tOptions[\"query\"] extends StandardSchemaV1<infer T>\n\t\t? T\n\t\t: Record<string, any> | undefined;\n\nexport type InputContext<\n\tPath extends string,\n\tOptions extends EndpointOptions,\n> = InferBodyInput<Options> &\n\tInferInputMethod<Options> &\n\tInferQueryInput<Options> &\n\tInferParamInput<Path> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\treturnStatus?: boolean;\n\t\tuse?: Middleware[];\n\t\tpath?: string;\n\t\tcontext?: Record<string, any>;\n\t};\n\nexport const createInternalContext = async (\n\tcontext: InputContext<any, any>,\n\t{\n\t\toptions,\n\t\tpath,\n\t}: {\n\t\toptions: EndpointOptions;\n\t\tpath?: string;\n\t},\n) => {\n\tconst headers = new Headers();\n\tlet responseStatus: Status | undefined = undefined;\n\n\tconst { data, error } = await runValidation(options, context);\n\tif (error) {\n\t\tthrow new ValidationError(error.message, error.issues);\n\t}\n\tconst requestHeaders: Headers | null =\n\t\t\"headers\" in context\n\t\t\t? context.headers instanceof Headers\n\t\t\t\t? context.headers\n\t\t\t\t: new Headers(context.headers)\n\t\t\t: \"request\" in context && isRequest(context.request)\n\t\t\t\t? context.request.headers\n\t\t\t\t: null;\n\tconst requestCookies = requestHeaders?.get(\"cookie\");\n\tconst parsedCookies = requestCookies\n\t\t? parseCookies(requestCookies)\n\t\t: undefined;\n\n\tconst internalContext = {\n\t\t...context,\n\t\tbody: data.body,\n\t\tquery: data.query,\n\t\tpath: context.path || path || \"virtual:\",\n\t\tcontext: \"context\" in context && context.context ? context.context : {},\n\t\treturned: undefined as any,\n\t\theaders: context?.headers,\n\t\trequest: context?.request,\n\t\tparams: \"params\" in context ? context.params : undefined,\n\t\tmethod:\n\t\t\tcontext.method ??\n\t\t\t(Array.isArray(options.method)\n\t\t\t\t? options.method[0]\n\t\t\t\t: options.method === \"*\"\n\t\t\t\t\t? \"GET\"\n\t\t\t\t\t: options.method),\n\t\tsetHeader: (key: string, value: string) => {\n\t\t\theaders.set(key, value);\n\t\t},\n\t\tgetHeader: (key: string) => {\n\t\t\tif (!requestHeaders) return null;\n\t\t\treturn requestHeaders.get(key);\n\t\t},\n\t\tgetCookie: (key: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn parsedCookies?.get(finalKey) || null;\n\t\t},\n\t\tgetSignedCookie: async (\n\t\t\tkey: string,\n\t\t\tsecret: string,\n\t\t\tprefix?: CookiePrefixOptions,\n\t\t) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst value = parsedCookies?.get(finalKey);\n\t\t\tif (!value) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signatureStartPos = value.lastIndexOf(\".\");\n\t\t\tif (signatureStartPos < 1) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signedValue = value.substring(0, signatureStartPos);\n\t\t\tconst signature = value.substring(signatureStartPos + 1);\n\t\t\tif (signature.length !== 44 || !signature.endsWith(\"=\")) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst secretKey = await getCryptoKey(secret);\n\t\t\tconst isVerified = await verifySignature(\n\t\t\t\tsignature,\n\t\t\t\tsignedValue,\n\t\t\t\tsecretKey,\n\t\t\t);\n\t\t\treturn isVerified ? signedValue : false;\n\t\t},\n\t\tsetCookie: (key: string, value: string, options?: CookieOptions) => {\n\t\t\tconst cookie = serializeCookie(key, value, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tsetSignedCookie: async (\n\t\t\tkey: string,\n\t\t\tvalue: string,\n\t\t\tsecret: string,\n\t\t\toptions?: CookieOptions,\n\t\t) => {\n\t\t\tconst cookie = await serializeSignedCookie(key, value, secret, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tredirect: (url: string) => {\n\t\t\theaders.set(\"location\", url);\n\t\t\treturn new APIError(\"FOUND\", undefined, headers);\n\t\t},\n\t\terror: (\n\t\t\tstatus: keyof typeof statusCodes | Status,\n\t\t\tbody?:\n\t\t\t\t| {\n\t\t\t\t\t\tmessage?: string;\n\t\t\t\t\t\tcode?: string;\n\t\t\t\t }\n\t\t\t\t| undefined,\n\t\t\theaders?: HeadersInit,\n\t\t) => {\n\t\t\treturn new APIError(status, body, headers);\n\t\t},\n\t\tsetStatus: (status: Status) => {\n\t\t\tresponseStatus = status;\n\t\t},\n\t\tjson: (\n\t\t\tjson: Record<string, any>,\n\t\t\trouterResponse?:\n\t\t\t\t| {\n\t\t\t\t\t\tstatus?: number;\n\t\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\t\tresponse?: Response;\n\t\t\t\t\t\tbody?: Record<string, any>;\n\t\t\t\t }\n\t\t\t\t| Response,\n\t\t) => {\n\t\t\tif (!context.asResponse) {\n\t\t\t\treturn json;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbody: routerResponse?.body || json,\n\t\t\t\trouterResponse,\n\t\t\t\t_flag: \"json\",\n\t\t\t};\n\t\t},\n\t\tresponseHeaders: headers,\n\t\tget responseStatus() {\n\t\t\treturn responseStatus;\n\t\t},\n\t};\n\t//if context was shimmed through the input we want to apply it\n\tfor (const middleware of options.use || []) {\n\t\tconst response = (await middleware({\n\t\t\t...internalContext,\n\t\t\treturnHeaders: true,\n\t\t\tasResponse: false,\n\t\t})) as {\n\t\t\tresponse?: any;\n\t\t\theaders?: Headers;\n\t\t};\n\t\tif (response.response) {\n\t\t\tObject.assign(internalContext.context, response.response);\n\t\t}\n\t\t/**\n\t\t * Apply headers from the middleware to the endpoint headers\n\t\t */\n\t\tif (response.headers) {\n\t\t\tresponse.headers.forEach((value, key) => {\n\t\t\t\tinternalContext.responseHeaders.set(key, value);\n\t\t\t});\n\t\t}\n\t}\n\treturn internalContext;\n};\n"],"mappings":"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"}
@@ -1,18 +1,17 @@
1
- import { InferParamPath, InferParamWildCard, IsEmptyObject, Prettify, UnionToIntersection } from "./helper.cjs";
1
+ import { CookieOptions, CookiePrefixOptions } from "./cookies.cjs";
2
2
  import { StandardSchemaV1 } from "./standard-schema.cjs";
3
3
  import { Status, statusCodes } from "./error.cjs";
4
- import { CookieOptions, CookiePrefixOptions } from "./cookies.cjs";
4
+ import { InferParamPath, InferParamWildCard, IsEmptyObject, Prettify, UnionToIntersection } from "./helper.cjs";
5
5
  import { Middleware, MiddlewareOptions } from "./middleware.cjs";
6
6
  import { EndpointOptions } from "./endpoint.cjs";
7
-
8
7
  //#region src/context.d.ts
9
8
  type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
10
9
  type Method = HTTPMethod | "*";
11
- type InferBodyInput<Options extends EndpointOptions | MiddlewareOptions, Body = (Options["metadata"] extends {
10
+ type InferBodyInput<Options extends EndpointOptions | MiddlewareOptions, Body = Options["metadata"] extends {
12
11
  $Infer: {
13
12
  body: infer B;
14
13
  };
15
- } ? B : Options["body"] extends StandardSchemaV1 ? StandardSchemaV1.InferInput<Options["body"]> : undefined)> = undefined extends Body ? {
14
+ } ? B : Options["body"] extends StandardSchemaV1 ? StandardSchemaV1.InferInput<Options["body"]> : undefined> = undefined extends Body ? {
16
15
  body?: Body;
17
16
  } : {
18
17
  body: Body;
@@ -22,11 +21,11 @@ type InferBody<Options extends EndpointOptions | MiddlewareOptions> = Options["m
22
21
  body: infer Body;
23
22
  };
24
23
  } ? Body : Options["body"] extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<Options["body"]> : any;
25
- type InferQueryInput<Options extends EndpointOptions | MiddlewareOptions, Query = (Options["metadata"] extends {
24
+ type InferQueryInput<Options extends EndpointOptions | MiddlewareOptions, Query = Options["metadata"] extends {
26
25
  $Infer: {
27
26
  query: infer Query;
28
27
  };
29
- } ? Query : Options["query"] extends StandardSchemaV1 ? StandardSchemaV1.InferInput<Options["query"]> : Record<string, any> | undefined)> = undefined extends Query ? {
28
+ } ? Query : Options["query"] extends StandardSchemaV1 ? StandardSchemaV1.InferInput<Options["query"]> : Record<string, any> | undefined> = undefined extends Query ? {
30
29
  query?: Query;
31
30
  } : {
32
31
  query: Query;
@@ -37,7 +36,7 @@ type InferQuery<Options extends EndpointOptions | MiddlewareOptions> = Options["
37
36
  };
38
37
  } ? Query : Options["query"] extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<Options["query"]> : Record<string, any> | undefined;
39
38
  type InferMethod<Options extends EndpointOptions> = Options["method"] extends Array<Method> ? Options["method"][number] : Options["method"] extends "*" ? HTTPMethod : Options["method"];
40
- type InferInputMethod<Options extends EndpointOptions, Method = (Options["method"] extends Array<any> ? Options["method"][number] | undefined : Options["method"] extends "*" ? HTTPMethod : Options["method"] | undefined)> = undefined extends Method ? {
39
+ type InferInputMethod<Options extends EndpointOptions, Method = Options["method"] extends Array<any> ? Options["method"][number] | undefined : Options["method"] extends "*" ? HTTPMethod : Options["method"] | undefined> = undefined extends Method ? {
41
40
  method?: Method;
42
41
  } : {
43
42
  method: Method;
@@ -73,10 +72,7 @@ type InputContext<Path extends string, Options extends EndpointOptions> = InferB
73
72
  path?: string;
74
73
  context?: Record<string, any>;
75
74
  };
76
- declare const createInternalContext: (context: InputContext<any, any>, {
77
- options,
78
- path
79
- }: {
75
+ declare const createInternalContext: (context: InputContext<any, any>, { options, path }: {
80
76
  options: EndpointOptions;
81
77
  path?: string;
82
78
  }) => Promise<{