better-call 1.1.6 → 1.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +35 -0
  2. package/dist/_virtual/rolldown_runtime.cjs +29 -0
  3. package/dist/adapters/node/request.cjs +125 -0
  4. package/dist/adapters/node/request.cjs.map +1 -0
  5. package/dist/{node.d.ts → adapters/node/request.d.cts} +2 -6
  6. package/dist/adapters/node/request.d.mts +16 -0
  7. package/dist/{node.js → adapters/node/request.mjs} +2 -13
  8. package/dist/adapters/node/request.mjs.map +1 -0
  9. package/dist/client.cjs +2 -2
  10. package/dist/client.d.cts +11 -13
  11. package/dist/client.d.mts +53 -0
  12. package/dist/{client.js → client.mjs} +2 -2
  13. package/dist/client.mjs.map +1 -0
  14. package/dist/context.cjs +102 -0
  15. package/dist/context.cjs.map +1 -0
  16. package/dist/context.d.cts +340 -0
  17. package/dist/context.d.mts +340 -0
  18. package/dist/context.mjs +102 -0
  19. package/dist/context.mjs.map +1 -0
  20. package/dist/cookies.cjs +87 -0
  21. package/dist/cookies.cjs.map +1 -0
  22. package/dist/cookies.d.cts +103 -0
  23. package/dist/cookies.d.mts +103 -0
  24. package/dist/cookies.mjs +84 -0
  25. package/dist/cookies.mjs.map +1 -0
  26. package/dist/crypto.cjs +39 -0
  27. package/dist/crypto.cjs.map +1 -0
  28. package/dist/crypto.mjs +36 -0
  29. package/dist/crypto.mjs.map +1 -0
  30. package/dist/endpoint.cjs +70 -0
  31. package/dist/endpoint.cjs.map +1 -0
  32. package/dist/endpoint.d.cts +428 -0
  33. package/dist/endpoint.d.mts +428 -0
  34. package/dist/endpoint.mjs +70 -0
  35. package/dist/endpoint.mjs.map +1 -0
  36. package/dist/error.cjs +140 -7
  37. package/dist/error.cjs.map +1 -0
  38. package/dist/error.d.cts +103 -2
  39. package/dist/{error2.d.ts → error.d.mts} +5 -59
  40. package/dist/{error2.js → error.mjs} +2 -2
  41. package/dist/{error2.js.map → error.mjs.map} +1 -1
  42. package/dist/helper.d.cts +12 -0
  43. package/dist/helper.d.mts +12 -0
  44. package/dist/index.cjs +19 -829
  45. package/dist/index.d.cts +11 -15
  46. package/dist/index.d.mts +11 -0
  47. package/dist/index.mjs +10 -0
  48. package/dist/middleware.cjs +39 -0
  49. package/dist/middleware.cjs.map +1 -0
  50. package/dist/middleware.d.cts +123 -0
  51. package/dist/middleware.d.mts +123 -0
  52. package/dist/middleware.mjs +39 -0
  53. package/dist/middleware.mjs.map +1 -0
  54. package/dist/node.cjs +4 -151
  55. package/dist/node.cjs.map +1 -1
  56. package/dist/node.d.cts +2 -13
  57. package/dist/node.d.mts +9 -0
  58. package/dist/node.mjs +15 -0
  59. package/dist/node.mjs.map +1 -0
  60. package/dist/openapi.cjs +191 -0
  61. package/dist/openapi.cjs.map +1 -0
  62. package/dist/openapi.d.cts +113 -0
  63. package/dist/openapi.d.mts +113 -0
  64. package/dist/openapi.mjs +189 -0
  65. package/dist/openapi.mjs.map +1 -0
  66. package/dist/router.cjs +117 -0
  67. package/dist/router.cjs.map +1 -0
  68. package/dist/router.d.cts +3 -1088
  69. package/dist/router.d.mts +97 -0
  70. package/dist/router.mjs +116 -0
  71. package/dist/router.mjs.map +1 -0
  72. package/dist/standard-schema.d.cts +59 -0
  73. package/dist/standard-schema.d.mts +59 -0
  74. package/dist/to-response.cjs +96 -0
  75. package/dist/to-response.cjs.map +1 -0
  76. package/dist/to-response.d.cts +12 -0
  77. package/dist/to-response.d.mts +12 -0
  78. package/dist/to-response.mjs +96 -0
  79. package/dist/to-response.mjs.map +1 -0
  80. package/dist/utils.cjs +77 -0
  81. package/dist/utils.cjs.map +1 -0
  82. package/dist/utils.mjs +74 -0
  83. package/dist/utils.mjs.map +1 -0
  84. package/dist/validator.cjs +58 -0
  85. package/dist/validator.cjs.map +1 -0
  86. package/dist/validator.mjs +57 -0
  87. package/dist/validator.mjs.map +1 -0
  88. package/package.json +15 -15
  89. package/dist/client.d.ts +0 -55
  90. package/dist/client.js.map +0 -1
  91. package/dist/error.d.ts +0 -2
  92. package/dist/error.js +0 -3
  93. package/dist/error2.cjs +0 -171
  94. package/dist/error2.cjs.map +0 -1
  95. package/dist/error2.d.cts +0 -157
  96. package/dist/index.cjs.map +0 -1
  97. package/dist/index.d.ts +0 -15
  98. package/dist/index.js +0 -819
  99. package/dist/index.js.map +0 -1
  100. package/dist/node.js.map +0 -1
  101. package/dist/router.d.ts +0 -1182
@@ -0,0 +1,97 @@
1
+ import { Middleware } from "./middleware.mjs";
2
+ import { Endpoint } from "./endpoint.mjs";
3
+
4
+ //#region src/router.d.ts
5
+ interface RouterConfig {
6
+ throwError?: boolean;
7
+ onError?: (e: unknown) => void | Promise<void> | Response | Promise<Response>;
8
+ basePath?: string;
9
+ routerMiddleware?: Array<{
10
+ path: string;
11
+ middleware: Middleware;
12
+ }>;
13
+ /**
14
+ * additional Context that needs to passed to endpoints
15
+ *
16
+ * this will be available on `ctx.context` on endpoints
17
+ */
18
+ routerContext?: Record<string, any>;
19
+ /**
20
+ * A callback to run before any response
21
+ */
22
+ onResponse?: (res: Response) => any | Promise<any>;
23
+ /**
24
+ * A callback to run before any request
25
+ */
26
+ onRequest?: (req: Request) => any | Promise<any>;
27
+ /**
28
+ * List of allowed media types (MIME types) for the router
29
+ *
30
+ * if provided, only the media types in the list will be allowed to be passed in the body.
31
+ *
32
+ * If an endpoint has allowed media types, it will override the router's allowed media types.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const router = createRouter({
37
+ * allowedMediaTypes: ["application/json", "application/x-www-form-urlencoded"],
38
+ * })
39
+ */
40
+ allowedMediaTypes?: string[];
41
+ /**
42
+ * Skip trailing slashes
43
+ *
44
+ * @default false
45
+ */
46
+ skipTrailingSlashes?: boolean;
47
+ /**
48
+ * Open API route configuration
49
+ */
50
+ openapi?: {
51
+ /**
52
+ * Disable openapi route
53
+ *
54
+ * @default false
55
+ */
56
+ disabled?: boolean;
57
+ /**
58
+ * A path to display open api using scalar
59
+ *
60
+ * @default "/api/reference"
61
+ */
62
+ path?: string;
63
+ /**
64
+ * Scalar Configuration
65
+ */
66
+ scalar?: {
67
+ /**
68
+ * Title
69
+ * @default "Open API Reference"
70
+ */
71
+ title?: string;
72
+ /**
73
+ * Description
74
+ *
75
+ * @default "Better Call Open API Reference"
76
+ */
77
+ description?: string;
78
+ /**
79
+ * Logo URL
80
+ */
81
+ logo?: string;
82
+ /**
83
+ * Scalar theme
84
+ * @default "saturn"
85
+ */
86
+ theme?: string;
87
+ };
88
+ };
89
+ }
90
+ declare const createRouter: <E extends Record<string, Endpoint>, Config extends RouterConfig>(endpoints: E, config?: Config) => {
91
+ handler: (request: Request) => Promise<Response>;
92
+ endpoints: E;
93
+ };
94
+ type Router = ReturnType<typeof createRouter>;
95
+ //#endregion
96
+ export { Router, RouterConfig, createRouter };
97
+ //# sourceMappingURL=router.d.mts.map
@@ -0,0 +1,116 @@
1
+ import { getBody, isAPIError } from "./utils.mjs";
2
+ import { toResponse } from "./to-response.mjs";
3
+ import { createEndpoint } from "./endpoint.mjs";
4
+ import { generator, getHTML } from "./openapi.mjs";
5
+ import { addRoute, createRouter, findAllRoutes, findRoute } from "rou3";
6
+
7
+ //#region src/router.ts
8
+ const createRouter$1 = (endpoints, config) => {
9
+ if (!config?.openapi?.disabled) {
10
+ const openapi = {
11
+ path: "/api/reference",
12
+ ...config?.openapi
13
+ };
14
+ endpoints["openapi"] = createEndpoint(openapi.path, { method: "GET" }, async (c) => {
15
+ const schema = await generator(endpoints);
16
+ return new Response(getHTML(schema, openapi.scalar), { headers: { "Content-Type": "text/html" } });
17
+ });
18
+ }
19
+ const router = createRouter();
20
+ const middlewareRouter = createRouter();
21
+ for (const endpoint of Object.values(endpoints)) {
22
+ if (!endpoint.options || !endpoint.path) continue;
23
+ if (endpoint.options?.metadata?.SERVER_ONLY) continue;
24
+ const methods = Array.isArray(endpoint.options?.method) ? endpoint.options.method : [endpoint.options?.method];
25
+ for (const method of methods) addRoute(router, method, endpoint.path, endpoint);
26
+ }
27
+ if (config?.routerMiddleware?.length) for (const { path, middleware } of config.routerMiddleware) addRoute(middlewareRouter, "*", path, middleware);
28
+ const processRequest = async (request) => {
29
+ const url = new URL(request.url);
30
+ const pathname = url.pathname;
31
+ const path = config?.basePath && config.basePath !== "/" ? pathname.split(config.basePath).reduce((acc, curr, index) => {
32
+ if (index !== 0) if (index > 1) acc.push(`${config.basePath}${curr}`);
33
+ else acc.push(curr);
34
+ return acc;
35
+ }, []).join("") : url.pathname;
36
+ if (!path?.length) return new Response(null, {
37
+ status: 404,
38
+ statusText: "Not Found"
39
+ });
40
+ if (/\/{2,}/.test(path)) return new Response(null, {
41
+ status: 404,
42
+ statusText: "Not Found"
43
+ });
44
+ const route = findRoute(router, request.method, path);
45
+ if (path.endsWith("/") !== route?.data?.path?.endsWith("/") && !config?.skipTrailingSlashes) return new Response(null, {
46
+ status: 404,
47
+ statusText: "Not Found"
48
+ });
49
+ if (!route?.data) return new Response(null, {
50
+ status: 404,
51
+ statusText: "Not Found"
52
+ });
53
+ const query = {};
54
+ url.searchParams.forEach((value, key) => {
55
+ if (key in query) if (Array.isArray(query[key])) query[key].push(value);
56
+ else query[key] = [query[key], value];
57
+ else query[key] = value;
58
+ });
59
+ const handler = route.data;
60
+ try {
61
+ const allowedMediaTypes = handler.options.metadata?.allowedMediaTypes || config?.allowedMediaTypes;
62
+ const context = {
63
+ path,
64
+ method: request.method,
65
+ headers: request.headers,
66
+ params: route.params ? JSON.parse(JSON.stringify(route.params)) : {},
67
+ request,
68
+ body: handler.options.disableBody ? void 0 : await getBody(handler.options.cloneRequest ? request.clone() : request, allowedMediaTypes),
69
+ query,
70
+ _flag: "router",
71
+ asResponse: true,
72
+ context: config?.routerContext
73
+ };
74
+ const middlewareRoutes = findAllRoutes(middlewareRouter, "*", path);
75
+ if (middlewareRoutes?.length) for (const { data: middleware, params } of middlewareRoutes) {
76
+ const res = await middleware({
77
+ ...context,
78
+ params,
79
+ asResponse: false
80
+ });
81
+ if (res instanceof Response) return res;
82
+ }
83
+ return await handler(context);
84
+ } catch (error) {
85
+ if (config?.onError) try {
86
+ const errorResponse = await config.onError(error);
87
+ if (errorResponse instanceof Response) return toResponse(errorResponse);
88
+ } catch (error$1) {
89
+ if (isAPIError(error$1)) return toResponse(error$1);
90
+ throw error$1;
91
+ }
92
+ if (config?.throwError) throw error;
93
+ if (isAPIError(error)) return toResponse(error);
94
+ console.error(`# SERVER_ERROR: `, error);
95
+ return new Response(null, {
96
+ status: 500,
97
+ statusText: "Internal Server Error"
98
+ });
99
+ }
100
+ };
101
+ return {
102
+ handler: async (request) => {
103
+ const onReq = await config?.onRequest?.(request);
104
+ if (onReq instanceof Response) return onReq;
105
+ const res = await processRequest(onReq instanceof Request ? onReq : request);
106
+ const onRes = await config?.onResponse?.(res);
107
+ if (onRes instanceof Response) return onRes;
108
+ return res;
109
+ },
110
+ endpoints
111
+ };
112
+ };
113
+
114
+ //#endregion
115
+ export { createRouter$1 as createRouter };
116
+ //# sourceMappingURL=router.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.mjs","names":["createRouter","createRou3Router","query: Record<string, string | string[]>","error"],"sources":["../src/router.ts"],"sourcesContent":["import { addRoute, createRouter as createRou3Router, findAllRoutes, findRoute } from \"rou3\";\nimport { type Endpoint, createEndpoint } from \"./endpoint\";\nimport type { Middleware } from \"./middleware\";\nimport { generator, getHTML } from \"./openapi\";\nimport { toResponse } from \"./to-response\";\nimport { getBody, isAPIError } from \"./utils\";\n\nexport interface RouterConfig {\n\tthrowError?: boolean;\n\tonError?: (e: unknown) => void | Promise<void> | Response | Promise<Response>;\n\tbasePath?: string;\n\trouterMiddleware?: Array<{\n\t\tpath: string;\n\t\tmiddleware: Middleware;\n\t}>;\n\t/**\n\t * additional Context that needs to passed to endpoints\n\t *\n\t * this will be available on `ctx.context` on endpoints\n\t */\n\trouterContext?: Record<string, any>;\n\t/**\n\t * A callback to run before any response\n\t */\n\tonResponse?: (res: Response) => any | Promise<any>;\n\t/**\n\t * A callback to run before any request\n\t */\n\tonRequest?: (req: Request) => any | Promise<any>;\n\t/**\n\t * List of allowed media types (MIME types) for the router\n\t *\n\t * if provided, only the media types in the list will be allowed to be passed in the body.\n\t *\n\t * If an endpoint has allowed media types, it will override the router's allowed media types.\n\t *\n\t * @example\n\t * ```ts\n\t * const router = createRouter({\n\t * \t\tallowedMediaTypes: [\"application/json\", \"application/x-www-form-urlencoded\"],\n\t * \t})\n\t */\n\tallowedMediaTypes?: string[];\n\t/**\n\t * Skip trailing slashes\n\t *\n\t * @default false\n\t */\n\tskipTrailingSlashes?: boolean;\n\t/**\n\t * Open API route configuration\n\t */\n\topenapi?: {\n\t\t/**\n\t\t * Disable openapi route\n\t\t *\n\t\t * @default false\n\t\t */\n\t\tdisabled?: boolean;\n\t\t/**\n\t\t * A path to display open api using scalar\n\t\t *\n\t\t * @default \"/api/reference\"\n\t\t */\n\t\tpath?: string;\n\t\t/**\n\t\t * Scalar Configuration\n\t\t */\n\t\tscalar?: {\n\t\t\t/**\n\t\t\t * Title\n\t\t\t * @default \"Open API Reference\"\n\t\t\t */\n\t\t\ttitle?: string;\n\t\t\t/**\n\t\t\t * Description\n\t\t\t *\n\t\t\t * @default \"Better Call Open API Reference\"\n\t\t\t */\n\t\t\tdescription?: string;\n\t\t\t/**\n\t\t\t * Logo URL\n\t\t\t */\n\t\t\tlogo?: string;\n\t\t\t/**\n\t\t\t * Scalar theme\n\t\t\t * @default \"saturn\"\n\t\t\t */\n\t\t\ttheme?: string;\n\t\t};\n\t};\n}\n\nexport const createRouter = <E extends Record<string, Endpoint>, Config extends RouterConfig>(\n\tendpoints: E,\n\tconfig?: Config,\n) => {\n\tif (!config?.openapi?.disabled) {\n\t\tconst openapi = {\n\t\t\tpath: \"/api/reference\",\n\t\t\t...config?.openapi,\n\t\t};\n\t\t//@ts-expect-error\n\t\tendpoints[\"openapi\"] = createEndpoint(\n\t\t\topenapi.path,\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t},\n\t\t\tasync (c) => {\n\t\t\t\tconst schema = await generator(endpoints);\n\t\t\t\treturn new Response(getHTML(schema, openapi.scalar), {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"text/html\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\tconst router = createRou3Router();\n\tconst middlewareRouter = createRou3Router();\n\n\tfor (const endpoint of Object.values(endpoints)) {\n\t\tif (!endpoint.options || !endpoint.path) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (endpoint.options?.metadata?.SERVER_ONLY) continue;\n\n\t\tconst methods = Array.isArray(endpoint.options?.method)\n\t\t\t? endpoint.options.method\n\t\t\t: [endpoint.options?.method];\n\n\t\tfor (const method of methods) {\n\t\t\taddRoute(router, method, endpoint.path, endpoint);\n\t\t}\n\t}\n\n\tif (config?.routerMiddleware?.length) {\n\t\tfor (const { path, middleware } of config.routerMiddleware) {\n\t\t\taddRoute(middlewareRouter, \"*\", path, middleware);\n\t\t}\n\t}\n\n\tconst processRequest = async (request: Request) => {\n\t\tconst url = new URL(request.url);\n\t\tconst pathname = url.pathname;\n\t\tconst path =\n\t\t\tconfig?.basePath && config.basePath !== \"/\"\n\t\t\t\t? pathname\n\t\t\t\t\t\t.split(config.basePath)\n\t\t\t\t\t\t.reduce((acc, curr, index) => {\n\t\t\t\t\t\t\tif (index !== 0) {\n\t\t\t\t\t\t\t\tif (index > 1) {\n\t\t\t\t\t\t\t\t\tacc.push(`${config.basePath}${curr}`);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tacc.push(curr);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn acc;\n\t\t\t\t\t\t}, [] as string[])\n\t\t\t\t\t\t.join(\"\")\n\t\t\t\t: url.pathname;\n\t\tif (!path?.length) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\t// Reject paths with consecutive slashes\n\t\tif (/\\/{2,}/.test(path)) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\tconst route = findRoute(router, request.method, path) as {\n\t\t\tdata: Endpoint & { path: string };\n\t\t\tparams: Record<string, string>;\n\t\t};\n\t\tconst hasTrailingSlash = path.endsWith(\"/\");\n\t\tconst routeHasTrailingSlash = route?.data?.path?.endsWith(\"/\");\n\n\t\t// If the path has a trailing slash and the route doesn't have a trailing slash and skipTrailingSlashes is not set, return 404\n\t\tif (hasTrailingSlash !== routeHasTrailingSlash && !config?.skipTrailingSlashes) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\t\tif (!route?.data) return new Response(null, { status: 404, statusText: \"Not Found\" });\n\n\t\tconst query: Record<string, string | string[]> = {};\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tif (key in query) {\n\t\t\t\tif (Array.isArray(query[key])) {\n\t\t\t\t\t(query[key] as string[]).push(value);\n\t\t\t\t} else {\n\t\t\t\t\tquery[key] = [query[key] as string, value];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tquery[key] = value;\n\t\t\t}\n\t\t});\n\n\t\tconst handler = route.data as Endpoint;\n\n\t\ttry {\n\t\t\t// Determine which allowedMediaTypes to use: endpoint-level overrides router-level\n\t\t\tconst allowedMediaTypes =\n\t\t\t\thandler.options.metadata?.allowedMediaTypes || config?.allowedMediaTypes;\n\t\t\tconst context = {\n\t\t\t\tpath,\n\t\t\t\tmethod: request.method as \"GET\",\n\t\t\t\theaders: request.headers,\n\t\t\t\tparams: route.params ? (JSON.parse(JSON.stringify(route.params)) as any) : {},\n\t\t\t\trequest: request,\n\t\t\t\tbody: handler.options.disableBody\n\t\t\t\t\t? undefined\n\t\t\t\t\t: await getBody(\n\t\t\t\t\t\t\thandler.options.cloneRequest ? request.clone() : request,\n\t\t\t\t\t\t\tallowedMediaTypes,\n\t\t\t\t\t\t),\n\t\t\t\tquery,\n\t\t\t\t_flag: \"router\" as const,\n\t\t\t\tasResponse: true,\n\t\t\t\tcontext: config?.routerContext,\n\t\t\t};\n\t\t\tconst middlewareRoutes = findAllRoutes(middlewareRouter, \"*\", path);\n\t\t\tif (middlewareRoutes?.length) {\n\t\t\t\tfor (const { data: middleware, params } of middlewareRoutes) {\n\t\t\t\t\tconst res = await (middleware as Endpoint)({\n\t\t\t\t\t\t...context,\n\t\t\t\t\t\tparams,\n\t\t\t\t\t\tasResponse: false,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (res instanceof Response) return res;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst response = (await handler(context)) as Response;\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tif (config?.onError) {\n\t\t\t\ttry {\n\t\t\t\t\tconst errorResponse = await config.onError(error);\n\n\t\t\t\t\tif (errorResponse instanceof Response) {\n\t\t\t\t\t\treturn toResponse(errorResponse);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (isAPIError(error)) {\n\t\t\t\t\t\treturn toResponse(error);\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config?.throwError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (isAPIError(error)) {\n\t\t\t\treturn toResponse(error);\n\t\t\t}\n\n\t\t\tconsole.error(`# SERVER_ERROR: `, error);\n\t\t\treturn new Response(null, {\n\t\t\t\tstatus: 500,\n\t\t\t\tstatusText: \"Internal Server Error\",\n\t\t\t});\n\t\t}\n\t};\n\n\treturn {\n\t\thandler: async (request: Request) => {\n\t\t\tconst onReq = await config?.onRequest?.(request);\n\t\t\tif (onReq instanceof Response) {\n\t\t\t\treturn onReq;\n\t\t\t}\n\t\t\tconst req = onReq instanceof Request ? onReq : request;\n\t\t\tconst res = await processRequest(req);\n\t\t\tconst onRes = await config?.onResponse?.(res);\n\t\t\tif (onRes instanceof Response) {\n\t\t\t\treturn onRes;\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\tendpoints,\n\t};\n};\n\nexport type Router = ReturnType<typeof createRouter>;\n"],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ //#region src/standard-schema.d.ts
2
+ /** The Standard Schema interface. */
3
+ interface StandardSchemaV1<Input = unknown, Output = Input> {
4
+ /** The Standard Schema properties. */
5
+ readonly "~standard": StandardSchemaV1.Props<Input, Output>;
6
+ }
7
+ declare namespace StandardSchemaV1 {
8
+ /** The Standard Schema properties interface. */
9
+ interface Props<Input = unknown, Output = Input> {
10
+ /** The version number of the standard. */
11
+ readonly version: 1;
12
+ /** The vendor name of the schema library. */
13
+ readonly vendor: string;
14
+ /** Validates unknown input values. */
15
+ readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
16
+ /** Inferred types associated with the schema. */
17
+ readonly types?: Types<Input, Output> | undefined;
18
+ }
19
+ /** The result interface of the validate function. */
20
+ type Result<Output> = SuccessResult<Output> | FailureResult;
21
+ /** The result interface if validation succeeds. */
22
+ interface SuccessResult<Output> {
23
+ /** The typed output value. */
24
+ readonly value: Output;
25
+ /** The non-existent issues. */
26
+ readonly issues?: undefined;
27
+ }
28
+ /** The result interface if validation fails. */
29
+ interface FailureResult {
30
+ /** The issues of failed validation. */
31
+ readonly issues: ReadonlyArray<Issue>;
32
+ }
33
+ /** The issue interface of the failure output. */
34
+ interface Issue {
35
+ /** The error message of the issue. */
36
+ readonly message: string;
37
+ /** The path of the issue, if any. */
38
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
39
+ }
40
+ /** The path segment interface of the issue. */
41
+ interface PathSegment {
42
+ /** The key representing a path segment. */
43
+ readonly key: PropertyKey;
44
+ }
45
+ /** The Standard Schema types interface. */
46
+ interface Types<Input = unknown, Output = Input> {
47
+ /** The input type of the schema. */
48
+ readonly input: Input;
49
+ /** The output type of the schema. */
50
+ readonly output: Output;
51
+ }
52
+ /** Infers the input type of a Standard Schema. */
53
+ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
54
+ /** Infers the output type of a Standard Schema. */
55
+ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
56
+ }
57
+ //#endregion
58
+ export { StandardSchemaV1 };
59
+ //# sourceMappingURL=standard-schema.d.cts.map
@@ -0,0 +1,59 @@
1
+ //#region src/standard-schema.d.ts
2
+ /** The Standard Schema interface. */
3
+ interface StandardSchemaV1<Input = unknown, Output = Input> {
4
+ /** The Standard Schema properties. */
5
+ readonly "~standard": StandardSchemaV1.Props<Input, Output>;
6
+ }
7
+ declare namespace StandardSchemaV1 {
8
+ /** The Standard Schema properties interface. */
9
+ interface Props<Input = unknown, Output = Input> {
10
+ /** The version number of the standard. */
11
+ readonly version: 1;
12
+ /** The vendor name of the schema library. */
13
+ readonly vendor: string;
14
+ /** Validates unknown input values. */
15
+ readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
16
+ /** Inferred types associated with the schema. */
17
+ readonly types?: Types<Input, Output> | undefined;
18
+ }
19
+ /** The result interface of the validate function. */
20
+ type Result<Output> = SuccessResult<Output> | FailureResult;
21
+ /** The result interface if validation succeeds. */
22
+ interface SuccessResult<Output> {
23
+ /** The typed output value. */
24
+ readonly value: Output;
25
+ /** The non-existent issues. */
26
+ readonly issues?: undefined;
27
+ }
28
+ /** The result interface if validation fails. */
29
+ interface FailureResult {
30
+ /** The issues of failed validation. */
31
+ readonly issues: ReadonlyArray<Issue>;
32
+ }
33
+ /** The issue interface of the failure output. */
34
+ interface Issue {
35
+ /** The error message of the issue. */
36
+ readonly message: string;
37
+ /** The path of the issue, if any. */
38
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
39
+ }
40
+ /** The path segment interface of the issue. */
41
+ interface PathSegment {
42
+ /** The key representing a path segment. */
43
+ readonly key: PropertyKey;
44
+ }
45
+ /** The Standard Schema types interface. */
46
+ interface Types<Input = unknown, Output = Input> {
47
+ /** The input type of the schema. */
48
+ readonly input: Input;
49
+ /** The output type of the schema. */
50
+ readonly output: Output;
51
+ }
52
+ /** Infers the input type of a Standard Schema. */
53
+ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
54
+ /** Infers the output type of a Standard Schema. */
55
+ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
56
+ }
57
+ //#endregion
58
+ export { StandardSchemaV1 };
59
+ //# sourceMappingURL=standard-schema.d.mts.map
@@ -0,0 +1,96 @@
1
+ require('./error.cjs');
2
+ const require_utils = require('./utils.cjs');
3
+
4
+ //#region src/to-response.ts
5
+ function isJSONSerializable(value) {
6
+ if (value === void 0) return false;
7
+ const t = typeof value;
8
+ if (t === "string" || t === "number" || t === "boolean" || t === null) return true;
9
+ if (t !== "object") return false;
10
+ if (Array.isArray(value)) return true;
11
+ if (value.buffer) return false;
12
+ return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function";
13
+ }
14
+ function safeStringify(obj, replacer, space) {
15
+ let id = 0;
16
+ const seen = /* @__PURE__ */ new WeakMap();
17
+ const safeReplacer = (key, value) => {
18
+ if (typeof value === "bigint") return value.toString();
19
+ if (typeof value === "object" && value !== null) {
20
+ if (seen.has(value)) return `[Circular ref-${seen.get(value)}]`;
21
+ seen.set(value, id++);
22
+ }
23
+ if (replacer) return replacer(key, value);
24
+ return value;
25
+ };
26
+ return JSON.stringify(obj, safeReplacer, space);
27
+ }
28
+ function isJSONResponse(value) {
29
+ if (!value || typeof value !== "object") return false;
30
+ return "_flag" in value && value._flag === "json";
31
+ }
32
+ function toResponse(data, init) {
33
+ if (data instanceof Response) {
34
+ if (init?.headers instanceof Headers) init.headers.forEach((value, key) => {
35
+ data.headers.set(key, value);
36
+ });
37
+ return data;
38
+ }
39
+ if (isJSONResponse(data)) {
40
+ const body$1 = data.body;
41
+ const routerResponse = data.routerResponse;
42
+ if (routerResponse instanceof Response) return routerResponse;
43
+ const headers$1 = new Headers();
44
+ if (routerResponse?.headers) {
45
+ const headers$2 = new Headers(routerResponse.headers);
46
+ for (const [key, value] of headers$2.entries()) headers$2.set(key, value);
47
+ }
48
+ if (data.headers) for (const [key, value] of new Headers(data.headers).entries()) headers$1.set(key, value);
49
+ if (init?.headers) for (const [key, value] of new Headers(init.headers).entries()) headers$1.set(key, value);
50
+ headers$1.set("Content-Type", "application/json");
51
+ return new Response(JSON.stringify(body$1), {
52
+ ...routerResponse,
53
+ headers: headers$1,
54
+ status: data.status ?? init?.status ?? routerResponse?.status,
55
+ statusText: init?.statusText ?? routerResponse?.statusText
56
+ });
57
+ }
58
+ if (require_utils.isAPIError(data)) return toResponse(data.body, {
59
+ status: init?.status ?? data.statusCode,
60
+ statusText: data.status.toString(),
61
+ headers: init?.headers || data.headers
62
+ });
63
+ let body = data;
64
+ let headers = new Headers(init?.headers);
65
+ if (!data) {
66
+ if (data === null) body = JSON.stringify(null);
67
+ headers.set("content-type", "application/json");
68
+ } else if (typeof data === "string") {
69
+ body = data;
70
+ headers.set("Content-Type", "text/plain");
71
+ } else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
72
+ body = data;
73
+ headers.set("Content-Type", "application/octet-stream");
74
+ } else if (data instanceof Blob) {
75
+ body = data;
76
+ headers.set("Content-Type", data.type || "application/octet-stream");
77
+ } else if (data instanceof FormData) body = data;
78
+ else if (data instanceof URLSearchParams) {
79
+ body = data;
80
+ headers.set("Content-Type", "application/x-www-form-urlencoded");
81
+ } else if (data instanceof ReadableStream) {
82
+ body = data;
83
+ headers.set("Content-Type", "application/octet-stream");
84
+ } else if (isJSONSerializable(data)) {
85
+ body = safeStringify(data);
86
+ headers.set("Content-Type", "application/json");
87
+ }
88
+ return new Response(body, {
89
+ ...init,
90
+ headers
91
+ });
92
+ }
93
+
94
+ //#endregion
95
+ exports.toResponse = toResponse;
96
+ //# sourceMappingURL=to-response.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-response.cjs","names":["body","headers","isAPIError"],"sources":["../src/to-response.ts"],"sourcesContent":["import { APIError } from \"./error\";\nimport { isAPIError } from \"./utils\";\n\nfunction isJSONSerializable(value: any) {\n\tif (value === undefined) {\n\t\treturn false;\n\t}\n\tconst t = typeof value;\n\tif (t === \"string\" || t === \"number\" || t === \"boolean\" || t === null) {\n\t\treturn true;\n\t}\n\tif (t !== \"object\") {\n\t\treturn false;\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn true;\n\t}\n\tif (value.buffer) {\n\t\treturn false;\n\t}\n\treturn (\n\t\t(value.constructor && value.constructor.name === \"Object\") ||\n\t\ttypeof value.toJSON === \"function\"\n\t);\n}\n\nfunction safeStringify(\n\tobj: any,\n\treplacer?: (key: string, value: any) => any,\n\tspace?: string | number,\n): string {\n\tlet id = 0;\n\tconst seen = new WeakMap<object, number>(); // ref -> counter\n\n\tconst safeReplacer = (key: string, value: any) => {\n\t\t// Handle bigint first\n\t\tif (typeof value === \"bigint\") {\n\t\t\treturn value.toString();\n\t\t}\n\n\t\t// Then handle circular references\n\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\tif (seen.has(value)) {\n\t\t\t\treturn `[Circular ref-${seen.get(value)}]`;\n\t\t\t}\n\t\t\tseen.set(value, id++);\n\t\t}\n\n\t\t// Finally apply any custom replacer\n\t\tif (replacer) {\n\t\t\treturn replacer(key, value);\n\t\t}\n\n\t\treturn value;\n\t};\n\n\treturn JSON.stringify(obj, safeReplacer, space);\n}\n\nexport type JSONResponse = {\n\tbody: Record<string, any>;\n\trouterResponse: ResponseInit | undefined;\n\tstatus?: number;\n\theaders?: Record<string, string> | Headers;\n\t_flag: \"json\";\n};\n\nfunction isJSONResponse(value: any): value is JSONResponse {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\treturn \"_flag\" in value && value._flag === \"json\";\n}\n\nexport function toResponse(data?: any, init?: ResponseInit): Response {\n\tif (data instanceof Response) {\n\t\tif (init?.headers instanceof Headers) {\n\t\t\tinit.headers.forEach((value, key) => {\n\t\t\t\tdata.headers.set(key, value);\n\t\t\t});\n\t\t}\n\t\treturn data;\n\t}\n\tconst isJSON = isJSONResponse(data);\n\tif (isJSON) {\n\t\tconst body = data.body;\n\t\tconst routerResponse = data.routerResponse;\n\t\tif (routerResponse instanceof Response) {\n\t\t\treturn routerResponse;\n\t\t}\n\t\tconst headers = new Headers();\n\t\tif (routerResponse?.headers) {\n\t\t\tconst headers = new Headers(routerResponse.headers);\n\t\t\tfor (const [key, value] of headers.entries()) {\n\t\t\t\theaders.set(key, value);\n\t\t\t}\n\t\t}\n\t\tif (data.headers) {\n\t\t\tfor (const [key, value] of new Headers(data.headers).entries()) {\n\t\t\t\theaders.set(key, value);\n\t\t\t}\n\t\t}\n\t\tif (init?.headers) {\n\t\t\tfor (const [key, value] of new Headers(init.headers).entries()) {\n\t\t\t\theaders.set(key, value);\n\t\t\t}\n\t\t}\n\n\t\theaders.set(\"Content-Type\", \"application/json\");\n\t\treturn new Response(JSON.stringify(body), {\n\t\t\t...routerResponse,\n\t\t\theaders,\n\t\t\tstatus: data.status ?? init?.status ?? routerResponse?.status,\n\t\t\tstatusText: init?.statusText ?? routerResponse?.statusText,\n\t\t});\n\t}\n\tif (isAPIError(data)) {\n\t\treturn toResponse(data.body, {\n\t\t\tstatus: init?.status ?? data.statusCode,\n\t\t\tstatusText: data.status.toString(),\n\t\t\theaders: init?.headers || data.headers,\n\t\t});\n\t}\n\tlet body = data;\n\tlet headers = new Headers(init?.headers);\n\tif (!data) {\n\t\tif (data === null) {\n\t\t\tbody = JSON.stringify(null);\n\t\t}\n\t\theaders.set(\"content-type\", \"application/json\");\n\t} else if (typeof data === \"string\") {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", \"text/plain\");\n\t} else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", \"application/octet-stream\");\n\t} else if (data instanceof Blob) {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", data.type || \"application/octet-stream\");\n\t} else if (data instanceof FormData) {\n\t\tbody = data;\n\t} else if (data instanceof URLSearchParams) {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", \"application/x-www-form-urlencoded\");\n\t} else if (data instanceof ReadableStream) {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", \"application/octet-stream\");\n\t} else if (isJSONSerializable(data)) {\n\t\tbody = safeStringify(data);\n\t\theaders.set(\"Content-Type\", \"application/json\");\n\t}\n\n\treturn new Response(body, {\n\t\t...init,\n\t\theaders,\n\t});\n}\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ //#region src/to-response.d.ts
2
+ type JSONResponse = {
3
+ body: Record<string, any>;
4
+ routerResponse: ResponseInit | undefined;
5
+ status?: number;
6
+ headers?: Record<string, string> | Headers;
7
+ _flag: "json";
8
+ };
9
+ declare function toResponse(data?: any, init?: ResponseInit): Response;
10
+ //#endregion
11
+ export { JSONResponse, toResponse };
12
+ //# sourceMappingURL=to-response.d.cts.map
@@ -0,0 +1,12 @@
1
+ //#region src/to-response.d.ts
2
+ type JSONResponse = {
3
+ body: Record<string, any>;
4
+ routerResponse: ResponseInit | undefined;
5
+ status?: number;
6
+ headers?: Record<string, string> | Headers;
7
+ _flag: "json";
8
+ };
9
+ declare function toResponse(data?: any, init?: ResponseInit): Response;
10
+ //#endregion
11
+ export { JSONResponse, toResponse };
12
+ //# sourceMappingURL=to-response.d.mts.map
@@ -0,0 +1,96 @@
1
+ import "./error.mjs";
2
+ import { isAPIError } from "./utils.mjs";
3
+
4
+ //#region src/to-response.ts
5
+ function isJSONSerializable(value) {
6
+ if (value === void 0) return false;
7
+ const t = typeof value;
8
+ if (t === "string" || t === "number" || t === "boolean" || t === null) return true;
9
+ if (t !== "object") return false;
10
+ if (Array.isArray(value)) return true;
11
+ if (value.buffer) return false;
12
+ return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function";
13
+ }
14
+ function safeStringify(obj, replacer, space) {
15
+ let id = 0;
16
+ const seen = /* @__PURE__ */ new WeakMap();
17
+ const safeReplacer = (key, value) => {
18
+ if (typeof value === "bigint") return value.toString();
19
+ if (typeof value === "object" && value !== null) {
20
+ if (seen.has(value)) return `[Circular ref-${seen.get(value)}]`;
21
+ seen.set(value, id++);
22
+ }
23
+ if (replacer) return replacer(key, value);
24
+ return value;
25
+ };
26
+ return JSON.stringify(obj, safeReplacer, space);
27
+ }
28
+ function isJSONResponse(value) {
29
+ if (!value || typeof value !== "object") return false;
30
+ return "_flag" in value && value._flag === "json";
31
+ }
32
+ function toResponse(data, init) {
33
+ if (data instanceof Response) {
34
+ if (init?.headers instanceof Headers) init.headers.forEach((value, key) => {
35
+ data.headers.set(key, value);
36
+ });
37
+ return data;
38
+ }
39
+ if (isJSONResponse(data)) {
40
+ const body$1 = data.body;
41
+ const routerResponse = data.routerResponse;
42
+ if (routerResponse instanceof Response) return routerResponse;
43
+ const headers$1 = new Headers();
44
+ if (routerResponse?.headers) {
45
+ const headers$2 = new Headers(routerResponse.headers);
46
+ for (const [key, value] of headers$2.entries()) headers$2.set(key, value);
47
+ }
48
+ if (data.headers) for (const [key, value] of new Headers(data.headers).entries()) headers$1.set(key, value);
49
+ if (init?.headers) for (const [key, value] of new Headers(init.headers).entries()) headers$1.set(key, value);
50
+ headers$1.set("Content-Type", "application/json");
51
+ return new Response(JSON.stringify(body$1), {
52
+ ...routerResponse,
53
+ headers: headers$1,
54
+ status: data.status ?? init?.status ?? routerResponse?.status,
55
+ statusText: init?.statusText ?? routerResponse?.statusText
56
+ });
57
+ }
58
+ if (isAPIError(data)) return toResponse(data.body, {
59
+ status: init?.status ?? data.statusCode,
60
+ statusText: data.status.toString(),
61
+ headers: init?.headers || data.headers
62
+ });
63
+ let body = data;
64
+ let headers = new Headers(init?.headers);
65
+ if (!data) {
66
+ if (data === null) body = JSON.stringify(null);
67
+ headers.set("content-type", "application/json");
68
+ } else if (typeof data === "string") {
69
+ body = data;
70
+ headers.set("Content-Type", "text/plain");
71
+ } else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
72
+ body = data;
73
+ headers.set("Content-Type", "application/octet-stream");
74
+ } else if (data instanceof Blob) {
75
+ body = data;
76
+ headers.set("Content-Type", data.type || "application/octet-stream");
77
+ } else if (data instanceof FormData) body = data;
78
+ else if (data instanceof URLSearchParams) {
79
+ body = data;
80
+ headers.set("Content-Type", "application/x-www-form-urlencoded");
81
+ } else if (data instanceof ReadableStream) {
82
+ body = data;
83
+ headers.set("Content-Type", "application/octet-stream");
84
+ } else if (isJSONSerializable(data)) {
85
+ body = safeStringify(data);
86
+ headers.set("Content-Type", "application/json");
87
+ }
88
+ return new Response(body, {
89
+ ...init,
90
+ headers
91
+ });
92
+ }
93
+
94
+ //#endregion
95
+ export { toResponse };
96
+ //# sourceMappingURL=to-response.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-response.mjs","names":["body","headers"],"sources":["../src/to-response.ts"],"sourcesContent":["import { APIError } from \"./error\";\nimport { isAPIError } from \"./utils\";\n\nfunction isJSONSerializable(value: any) {\n\tif (value === undefined) {\n\t\treturn false;\n\t}\n\tconst t = typeof value;\n\tif (t === \"string\" || t === \"number\" || t === \"boolean\" || t === null) {\n\t\treturn true;\n\t}\n\tif (t !== \"object\") {\n\t\treturn false;\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn true;\n\t}\n\tif (value.buffer) {\n\t\treturn false;\n\t}\n\treturn (\n\t\t(value.constructor && value.constructor.name === \"Object\") ||\n\t\ttypeof value.toJSON === \"function\"\n\t);\n}\n\nfunction safeStringify(\n\tobj: any,\n\treplacer?: (key: string, value: any) => any,\n\tspace?: string | number,\n): string {\n\tlet id = 0;\n\tconst seen = new WeakMap<object, number>(); // ref -> counter\n\n\tconst safeReplacer = (key: string, value: any) => {\n\t\t// Handle bigint first\n\t\tif (typeof value === \"bigint\") {\n\t\t\treturn value.toString();\n\t\t}\n\n\t\t// Then handle circular references\n\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\tif (seen.has(value)) {\n\t\t\t\treturn `[Circular ref-${seen.get(value)}]`;\n\t\t\t}\n\t\t\tseen.set(value, id++);\n\t\t}\n\n\t\t// Finally apply any custom replacer\n\t\tif (replacer) {\n\t\t\treturn replacer(key, value);\n\t\t}\n\n\t\treturn value;\n\t};\n\n\treturn JSON.stringify(obj, safeReplacer, space);\n}\n\nexport type JSONResponse = {\n\tbody: Record<string, any>;\n\trouterResponse: ResponseInit | undefined;\n\tstatus?: number;\n\theaders?: Record<string, string> | Headers;\n\t_flag: \"json\";\n};\n\nfunction isJSONResponse(value: any): value is JSONResponse {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\treturn \"_flag\" in value && value._flag === \"json\";\n}\n\nexport function toResponse(data?: any, init?: ResponseInit): Response {\n\tif (data instanceof Response) {\n\t\tif (init?.headers instanceof Headers) {\n\t\t\tinit.headers.forEach((value, key) => {\n\t\t\t\tdata.headers.set(key, value);\n\t\t\t});\n\t\t}\n\t\treturn data;\n\t}\n\tconst isJSON = isJSONResponse(data);\n\tif (isJSON) {\n\t\tconst body = data.body;\n\t\tconst routerResponse = data.routerResponse;\n\t\tif (routerResponse instanceof Response) {\n\t\t\treturn routerResponse;\n\t\t}\n\t\tconst headers = new Headers();\n\t\tif (routerResponse?.headers) {\n\t\t\tconst headers = new Headers(routerResponse.headers);\n\t\t\tfor (const [key, value] of headers.entries()) {\n\t\t\t\theaders.set(key, value);\n\t\t\t}\n\t\t}\n\t\tif (data.headers) {\n\t\t\tfor (const [key, value] of new Headers(data.headers).entries()) {\n\t\t\t\theaders.set(key, value);\n\t\t\t}\n\t\t}\n\t\tif (init?.headers) {\n\t\t\tfor (const [key, value] of new Headers(init.headers).entries()) {\n\t\t\t\theaders.set(key, value);\n\t\t\t}\n\t\t}\n\n\t\theaders.set(\"Content-Type\", \"application/json\");\n\t\treturn new Response(JSON.stringify(body), {\n\t\t\t...routerResponse,\n\t\t\theaders,\n\t\t\tstatus: data.status ?? init?.status ?? routerResponse?.status,\n\t\t\tstatusText: init?.statusText ?? routerResponse?.statusText,\n\t\t});\n\t}\n\tif (isAPIError(data)) {\n\t\treturn toResponse(data.body, {\n\t\t\tstatus: init?.status ?? data.statusCode,\n\t\t\tstatusText: data.status.toString(),\n\t\t\theaders: init?.headers || data.headers,\n\t\t});\n\t}\n\tlet body = data;\n\tlet headers = new Headers(init?.headers);\n\tif (!data) {\n\t\tif (data === null) {\n\t\t\tbody = JSON.stringify(null);\n\t\t}\n\t\theaders.set(\"content-type\", \"application/json\");\n\t} else if (typeof data === \"string\") {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", \"text/plain\");\n\t} else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", \"application/octet-stream\");\n\t} else if (data instanceof Blob) {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", data.type || \"application/octet-stream\");\n\t} else if (data instanceof FormData) {\n\t\tbody = data;\n\t} else if (data instanceof URLSearchParams) {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", \"application/x-www-form-urlencoded\");\n\t} else if (data instanceof ReadableStream) {\n\t\tbody = data;\n\t\theaders.set(\"Content-Type\", \"application/octet-stream\");\n\t} else if (isJSONSerializable(data)) {\n\t\tbody = safeStringify(data);\n\t\theaders.set(\"Content-Type\", \"application/json\");\n\t}\n\n\treturn new Response(body, {\n\t\t...init,\n\t\theaders,\n\t});\n}\n"],"mappings":"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"}