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.
- package/README.md +862 -0
- package/dist/_virtual/_rolldown/runtime.cjs +7 -13
- package/dist/adapters/node/request.cjs +3 -4
- package/dist/adapters/node/request.cjs.map +1 -1
- package/dist/adapters/node/request.d.cts +1 -6
- package/dist/adapters/node/request.d.mts +1 -6
- package/dist/adapters/node/request.mjs +1 -2
- package/dist/adapters/node/request.mjs.map +1 -1
- package/dist/client.cjs +3 -5
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +5 -6
- package/dist/client.d.mts +5 -6
- package/dist/client.mjs +1 -2
- package/dist/client.mjs.map +1 -1
- package/dist/context.cjs +6 -7
- package/dist/context.cjs.map +1 -1
- package/dist/context.d.cts +8 -12
- package/dist/context.d.mts +8 -12
- package/dist/context.mjs +3 -4
- package/dist/context.mjs.map +1 -1
- package/dist/cookies.cjs +3 -4
- package/dist/cookies.cjs.map +1 -1
- package/dist/cookies.mjs +2 -3
- package/dist/cookies.mjs.map +1 -1
- package/dist/crypto.cjs +2 -4
- package/dist/crypto.cjs.map +1 -1
- package/dist/crypto.mjs +2 -3
- package/dist/crypto.mjs.map +1 -1
- package/dist/endpoint.cjs +5 -6
- package/dist/endpoint.cjs.map +1 -1
- package/dist/endpoint.d.cts +4 -8
- package/dist/endpoint.d.mts +4 -8
- package/dist/endpoint.mjs +2 -3
- package/dist/endpoint.mjs.map +1 -1
- package/dist/error.cjs +8 -3
- package/dist/error.cjs.map +1 -1
- package/dist/error.d.cts +0 -1
- package/dist/error.d.mts +0 -1
- package/dist/error.mjs +7 -1
- package/dist/error.mjs.map +1 -1
- package/dist/helper.d.cts +4 -4
- package/dist/helper.d.mts +4 -4
- package/dist/index.cjs +10 -11
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -3
- package/dist/middleware.cjs +4 -6
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.d.cts +0 -1
- package/dist/middleware.d.mts +0 -1
- package/dist/middleware.mjs +1 -3
- package/dist/middleware.mjs.map +1 -1
- package/dist/node.cjs +3 -4
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +1 -2
- package/dist/node.d.mts +1 -2
- package/dist/node.mjs +1 -2
- package/dist/node.mjs.map +1 -1
- package/dist/openapi.cjs +1 -3
- package/dist/openapi.cjs.map +1 -1
- package/dist/openapi.d.cts +2 -3
- package/dist/openapi.d.mts +2 -3
- package/dist/openapi.mjs +1 -2
- package/dist/openapi.mjs.map +1 -1
- package/dist/router.cjs +5 -7
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts +0 -1
- package/dist/router.d.mts +0 -1
- package/dist/router.mjs +1 -2
- package/dist/router.mjs.map +1 -1
- package/dist/to-response.cjs +3 -5
- package/dist/to-response.cjs.map +1 -1
- package/dist/to-response.mjs +2 -4
- package/dist/to-response.mjs.map +1 -1
- package/dist/utils.cjs +2 -3
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.mjs +1 -2
- package/dist/utils.mjs.map +1 -1
- package/dist/validator.cjs +2 -3
- package/dist/validator.cjs.map +1 -1
- package/dist/validator.mjs +2 -2
- package/dist/validator.mjs.map +1 -1
- package/package.json +9 -10
package/dist/node.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { getRequest, setResponse } from "./adapters/node/request.mjs";
|
|
2
1
|
import { Router } from "./router.mjs";
|
|
2
|
+
import { getRequest, setResponse } from "./adapters/node/request.mjs";
|
|
3
3
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
4
|
-
|
|
5
4
|
//#region src/adapters/node/index.d.ts
|
|
6
5
|
declare function toNodeHandler(handler: Router["handler"]): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
7
6
|
//#endregion
|
package/dist/node.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { getRequest, setResponse } from "./adapters/node/request.mjs";
|
|
2
|
-
|
|
3
2
|
//#region src/adapters/node/index.ts
|
|
4
3
|
function toNodeHandler(handler) {
|
|
5
4
|
return async (req, res) => {
|
|
@@ -9,7 +8,7 @@ function toNodeHandler(handler) {
|
|
|
9
8
|
})));
|
|
10
9
|
};
|
|
11
10
|
}
|
|
12
|
-
|
|
13
11
|
//#endregion
|
|
14
12
|
export { getRequest, setResponse, toNodeHandler };
|
|
13
|
+
|
|
15
14
|
//# sourceMappingURL=node.mjs.map
|
package/dist/node.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.mjs","names":[],"sources":["../src/adapters/node/index.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\
|
|
1
|
+
{"version":3,"file":"node.mjs","names":[],"sources":["../src/adapters/node/index.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { Router } from \"../../router.js\";\nimport { getRequest, setResponse } from \"./request\";\n\nexport function toNodeHandler(handler: Router[\"handler\"]) {\n\treturn async (req: IncomingMessage, res: ServerResponse) => {\n\t\tconst protocol =\n\t\t\treq.headers[\"x-forwarded-proto\"] ||\n\t\t\t((req.socket as any).encrypted ? \"https\" : \"http\");\n\t\tconst base = `${protocol}://${req.headers[\":authority\"] || req.headers.host}`;\n\t\tconst response = await handler(getRequest({ base, request: req }));\n\t\treturn setResponse(res, response);\n\t};\n}\n\nexport { getRequest, setResponse };\n"],"mappings":";;AAIA,SAAgB,cAAc,SAA4B;CACzD,OAAO,OAAO,KAAsB,QAAwB;EAM3D,OAAO,YAAY,KAAK,MADD,QAAQ,WAAW;GAAE,MAAA,GAH3C,IAAI,QAAQ,yBACV,IAAI,OAAe,YAAY,UAAU,QACnB,KAAK,IAAI,QAAQ,iBAAiB,IAAI,QAAQ;GACrB,SAAS;EAAI,CAAC,CAAC,CACjC;CACjC;AACD"}
|
package/dist/openapi.cjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
1
|
let zod = require("zod");
|
|
3
|
-
|
|
4
2
|
//#region src/openapi.ts
|
|
5
3
|
const paths = {};
|
|
6
4
|
function getTypeFromZodType(zodType) {
|
|
@@ -184,8 +182,8 @@ const getHTML = (apiReference, config) => `<!doctype html>
|
|
|
184
182
|
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
185
183
|
</body>
|
|
186
184
|
</html>`;
|
|
187
|
-
|
|
188
185
|
//#endregion
|
|
189
186
|
exports.generator = generator;
|
|
190
187
|
exports.getHTML = getHTML;
|
|
188
|
+
|
|
191
189
|
//# sourceMappingURL=openapi.cjs.map
|
package/dist/openapi.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.cjs","names":["ZodObject","ZodOptional"],"sources":["../src/openapi.ts"],"sourcesContent":["import { ZodObject, ZodOptional, ZodType } from \"zod\";\nimport type { Endpoint, EndpointOptions } from \"./endpoint\";\n\nexport type OpenAPISchemaType =\n\t| \"string\"\n\t| \"number\"\n\t| \"integer\"\n\t| \"boolean\"\n\t| \"array\"\n\t| \"object\";\n\nexport interface OpenAPIParameter {\n\tin: \"query\" | \"path\" | \"header\" | \"cookie\";\n\tname?: string;\n\tdescription?: string;\n\trequired?: boolean;\n\tschema?: {\n\t\ttype: OpenAPISchemaType;\n\t\tformat?: string | undefined;\n\t\titems?: {\n\t\t\ttype: OpenAPISchemaType;\n\t\t};\n\t\tenum?: string[];\n\t\tminLength?: number;\n\t\tdescription?: string | undefined;\n\t\tdefault?: string | undefined;\n\t\texample?: string | undefined;\n\t};\n}\n\nexport interface Path {\n\tget?: {\n\t\ttags?: string[];\n\t\toperationId?: string;\n\t\tdescription?: string;\n\t\tsecurity?: [{ bearerAuth: string[] }];\n\t\tparameters?: OpenAPIParameter[];\n\t\tresponses?: {\n\t\t\t[key in string]: {\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent: {\n\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t};\n\tpost?: {\n\t\ttags?: string[];\n\t\toperationId?: string;\n\t\tdescription?: string;\n\t\tsecurity?: [{ bearerAuth: string[] }];\n\t\tparameters?: OpenAPIParameter[];\n\t\trequestBody?: {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t\tresponses?: {\n\t\t\t[key in string]: {\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent: {\n\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t};\n}\nconst paths: Record<string, Path> = {};\n\nfunction getTypeFromZodType(zodType: ZodType<any>) {\n\tswitch (zodType.constructor.name) {\n\t\tcase \"ZodString\":\n\t\t\treturn \"string\";\n\t\tcase \"ZodNumber\":\n\t\t\treturn \"number\";\n\t\tcase \"ZodBoolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"ZodObject\":\n\t\t\treturn \"object\";\n\t\tcase \"ZodArray\":\n\t\t\treturn \"array\";\n\t\tdefault:\n\t\t\treturn \"string\";\n\t}\n}\n\nfunction getParameters(options: EndpointOptions) {\n\tconst parameters: OpenAPIParameter[] = [];\n\tif (options.metadata?.openapi?.parameters) {\n\t\tparameters.push(...options.metadata.openapi.parameters);\n\t\treturn parameters;\n\t}\n\tif (options.query instanceof ZodObject) {\n\t\tObject.entries(options.query.shape).forEach(([key, value]) => {\n\t\t\tif (value instanceof ZodObject) {\n\t\t\t\tparameters.push({\n\t\t\t\t\tname: key,\n\t\t\t\t\tin: \"query\",\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: getTypeFromZodType(value),\n\t\t\t\t\t\t...(\"minLength\" in value && value.minLength\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tminLength: value.minLength as number,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\tdescription: value.description,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\treturn parameters;\n}\n\nfunction getRequestBody(options: EndpointOptions): any {\n\tif (options.metadata?.openapi?.requestBody) {\n\t\treturn options.metadata.openapi.requestBody;\n\t}\n\tif (!options.body) return undefined;\n\tif (\n\t\toptions.body instanceof ZodObject ||\n\t\toptions.body instanceof ZodOptional\n\t) {\n\t\t// @ts-ignore\n\t\tconst shape = options.body.shape;\n\t\tif (!shape) return undefined;\n\t\tconst properties: Record<string, any> = {};\n\t\tconst required: string[] = [];\n\t\tObject.entries(shape).forEach(([key, value]) => {\n\t\t\tif (value instanceof ZodObject) {\n\t\t\t\tproperties[key] = {\n\t\t\t\t\ttype: getTypeFromZodType(value),\n\t\t\t\t\tdescription: value.description,\n\t\t\t\t};\n\t\t\t\tif (!(value instanceof ZodOptional)) {\n\t\t\t\t\trequired.push(key);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn {\n\t\t\trequired:\n\t\t\t\toptions.body instanceof ZodOptional\n\t\t\t\t\t? false\n\t\t\t\t\t: options.body\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: false,\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\trequired,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\treturn undefined;\n}\n\nfunction getResponse(responses?: Record<string, any>) {\n\treturn {\n\t\t\"400\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"message\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Bad Request. Usually due to missing parameters, or invalid parameters.\",\n\t\t},\n\t\t\"401\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"message\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription: \"Unauthorized. Due to missing or invalid authentication.\",\n\t\t},\n\t\t\"403\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Forbidden. You do not have permission to access this resource or to perform this action.\",\n\t\t},\n\t\t\"404\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription: \"Not Found. The requested resource was not found.\",\n\t\t},\n\t\t\"429\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Too Many Requests. You have exceeded the rate limit. Try again later.\",\n\t\t},\n\t\t\"500\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Internal Server Error. This is a problem with the server that you cannot fix.\",\n\t\t},\n\t\t...responses,\n\t} as any;\n}\n\nexport async function generator(\n\tendpoints: Record<string, Endpoint>,\n\tconfig?: {\n\t\turl: string;\n\t},\n) {\n\tconst components = {\n\t\tschemas: {},\n\t};\n\n\tObject.entries(endpoints).forEach(([_, value]) => {\n\t\tconst options = value.options as EndpointOptions;\n\t\tif (!value.path || options.metadata?.SERVER_ONLY) return;\n\t\tif (options.method === \"GET\") {\n\t\t\tpaths[value.path] = {\n\t\t\t\tget: {\n\t\t\t\t\ttags: [\"Default\", ...(options.metadata?.openapi?.tags || [])],\n\t\t\t\t\tdescription: options.metadata?.openapi?.description,\n\t\t\t\t\toperationId: options.metadata?.openapi?.operationId,\n\t\t\t\t\tsecurity: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbearerAuth: [],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparameters: getParameters(options),\n\t\t\t\t\tresponses: getResponse(options.metadata?.openapi?.responses),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tif (options.method === \"POST\") {\n\t\t\tconst body = getRequestBody(options);\n\t\t\tpaths[value.path] = {\n\t\t\t\tpost: {\n\t\t\t\t\ttags: [\"Default\", ...(options.metadata?.openapi?.tags || [])],\n\t\t\t\t\tdescription: options.metadata?.openapi?.description,\n\t\t\t\t\toperationId: options.metadata?.openapi?.operationId,\n\t\t\t\t\tsecurity: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbearerAuth: [],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparameters: getParameters(options),\n\t\t\t\t\t...(body\n\t\t\t\t\t\t? { requestBody: body }\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\trequestBody: {\n\t\t\t\t\t\t\t\t\t//set body none\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\tresponses: getResponse(options.metadata?.openapi?.responses),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t});\n\n\tconst res = {\n\t\topenapi: \"3.1.1\",\n\t\tinfo: {\n\t\t\ttitle: \"Better Auth\",\n\t\t\tdescription: \"API Reference for your Better Auth Instance\",\n\t\t\tversion: \"1.1.0\",\n\t\t},\n\t\tcomponents,\n\t\tsecurity: [\n\t\t\t{\n\t\t\t\tapiKeyCookie: [],\n\t\t\t},\n\t\t],\n\t\tservers: [\n\t\t\t{\n\t\t\t\turl: config?.url,\n\t\t\t},\n\t\t],\n\t\ttags: [\n\t\t\t{\n\t\t\t\tname: \"Default\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Default endpoints that are included with Better Auth by default. These endpoints are not part of any plugin.\",\n\t\t\t},\n\t\t],\n\t\tpaths,\n\t};\n\treturn res;\n}\n\nexport const getHTML = (\n\tapiReference: Record<string, any>,\n\tconfig?: {\n\t\tlogo?: string;\n\t\ttheme?: string;\n\t\ttitle?: string;\n\t\tdescription?: string;\n\t},\n) => `<!doctype html>\n<html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\">\n ${JSON.stringify(apiReference)}\n </script>\n\t <script>\n var configuration = {\n\t \tfavicon: ${config?.logo ? `data:image/svg+xml;utf8,${encodeURIComponent(config.logo)}` : undefined} ,\n\t \ttheme: ${config?.theme || \"saturn\"},\n metaData: {\n\t\t\ttitle: ${config?.title || \"Open API Reference\"},\n\t\t\tdescription: ${config?.description || \"Better Call Open API\"},\n\t\t}\n }\n document.getElementById('api-reference').dataset.configuration =\n JSON.stringify(configuration)\n </script>\n\t <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>`;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"openapi.cjs","names":["ZodObject","ZodOptional"],"sources":["../src/openapi.ts"],"sourcesContent":["import type { ZodType } from \"zod\";\nimport { ZodObject, ZodOptional } from \"zod\";\nimport type { Endpoint, EndpointOptions } from \"./endpoint\";\n\nexport type OpenAPISchemaType =\n\t| \"string\"\n\t| \"number\"\n\t| \"integer\"\n\t| \"boolean\"\n\t| \"array\"\n\t| \"object\";\n\nexport interface OpenAPIParameter {\n\tin: \"query\" | \"path\" | \"header\" | \"cookie\";\n\tname?: string;\n\tdescription?: string;\n\trequired?: boolean;\n\tschema?: {\n\t\ttype: OpenAPISchemaType;\n\t\tformat?: string | undefined;\n\t\titems?: {\n\t\t\ttype: OpenAPISchemaType;\n\t\t};\n\t\tenum?: string[];\n\t\tminLength?: number;\n\t\tdescription?: string | undefined;\n\t\tdefault?: string | undefined;\n\t\texample?: string | undefined;\n\t};\n}\n\nexport interface Path {\n\tget?: {\n\t\ttags?: string[];\n\t\toperationId?: string;\n\t\tdescription?: string;\n\t\tsecurity?: [{ bearerAuth: string[] }];\n\t\tparameters?: OpenAPIParameter[];\n\t\tresponses?: {\n\t\t\t[key in string]: {\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent: {\n\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t};\n\tpost?: {\n\t\ttags?: string[];\n\t\toperationId?: string;\n\t\tdescription?: string;\n\t\tsecurity?: [{ bearerAuth: string[] }];\n\t\tparameters?: OpenAPIParameter[];\n\t\trequestBody?: {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t\tresponses?: {\n\t\t\t[key in string]: {\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent: {\n\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t};\n}\nconst paths: Record<string, Path> = {};\n\nfunction getTypeFromZodType(zodType: ZodType<any>) {\n\tswitch (zodType.constructor.name) {\n\t\tcase \"ZodString\":\n\t\t\treturn \"string\";\n\t\tcase \"ZodNumber\":\n\t\t\treturn \"number\";\n\t\tcase \"ZodBoolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"ZodObject\":\n\t\t\treturn \"object\";\n\t\tcase \"ZodArray\":\n\t\t\treturn \"array\";\n\t\tdefault:\n\t\t\treturn \"string\";\n\t}\n}\n\nfunction getParameters(options: EndpointOptions) {\n\tconst parameters: OpenAPIParameter[] = [];\n\tif (options.metadata?.openapi?.parameters) {\n\t\tparameters.push(...options.metadata.openapi.parameters);\n\t\treturn parameters;\n\t}\n\tif (options.query instanceof ZodObject) {\n\t\tObject.entries(options.query.shape).forEach(([key, value]) => {\n\t\t\tif (value instanceof ZodObject) {\n\t\t\t\tparameters.push({\n\t\t\t\t\tname: key,\n\t\t\t\t\tin: \"query\",\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: getTypeFromZodType(value),\n\t\t\t\t\t\t...(\"minLength\" in value && value.minLength\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tminLength: value.minLength as number,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\tdescription: value.description,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\treturn parameters;\n}\n\nfunction getRequestBody(options: EndpointOptions): any {\n\tif (options.metadata?.openapi?.requestBody) {\n\t\treturn options.metadata.openapi.requestBody;\n\t}\n\tif (!options.body) return undefined;\n\tif (\n\t\toptions.body instanceof ZodObject ||\n\t\toptions.body instanceof ZodOptional\n\t) {\n\t\t// @ts-expect-error\n\t\tconst shape = options.body.shape;\n\t\tif (!shape) return undefined;\n\t\tconst properties: Record<string, any> = {};\n\t\tconst required: string[] = [];\n\t\tObject.entries(shape).forEach(([key, value]) => {\n\t\t\tif (value instanceof ZodObject) {\n\t\t\t\tproperties[key] = {\n\t\t\t\t\ttype: getTypeFromZodType(value),\n\t\t\t\t\tdescription: value.description,\n\t\t\t\t};\n\t\t\t\tif (!(value instanceof ZodOptional)) {\n\t\t\t\t\trequired.push(key);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn {\n\t\t\trequired:\n\t\t\t\toptions.body instanceof ZodOptional\n\t\t\t\t\t? false\n\t\t\t\t\t: options.body\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: false,\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\trequired,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\treturn undefined;\n}\n\nfunction getResponse(responses?: Record<string, any>) {\n\treturn {\n\t\t\"400\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"message\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Bad Request. Usually due to missing parameters, or invalid parameters.\",\n\t\t},\n\t\t\"401\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"message\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription: \"Unauthorized. Due to missing or invalid authentication.\",\n\t\t},\n\t\t\"403\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Forbidden. You do not have permission to access this resource or to perform this action.\",\n\t\t},\n\t\t\"404\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription: \"Not Found. The requested resource was not found.\",\n\t\t},\n\t\t\"429\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Too Many Requests. You have exceeded the rate limit. Try again later.\",\n\t\t},\n\t\t\"500\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Internal Server Error. This is a problem with the server that you cannot fix.\",\n\t\t},\n\t\t...responses,\n\t} as any;\n}\n\nexport async function generator(\n\tendpoints: Record<string, Endpoint>,\n\tconfig?: {\n\t\turl: string;\n\t},\n) {\n\tconst components = {\n\t\tschemas: {},\n\t};\n\n\tObject.entries(endpoints).forEach(([_, value]) => {\n\t\tconst options = value.options as EndpointOptions;\n\t\tif (!value.path || options.metadata?.SERVER_ONLY) return;\n\t\tif (options.method === \"GET\") {\n\t\t\tpaths[value.path] = {\n\t\t\t\tget: {\n\t\t\t\t\ttags: [\"Default\", ...(options.metadata?.openapi?.tags || [])],\n\t\t\t\t\tdescription: options.metadata?.openapi?.description,\n\t\t\t\t\toperationId: options.metadata?.openapi?.operationId,\n\t\t\t\t\tsecurity: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbearerAuth: [],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparameters: getParameters(options),\n\t\t\t\t\tresponses: getResponse(options.metadata?.openapi?.responses),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tif (options.method === \"POST\") {\n\t\t\tconst body = getRequestBody(options);\n\t\t\tpaths[value.path] = {\n\t\t\t\tpost: {\n\t\t\t\t\ttags: [\"Default\", ...(options.metadata?.openapi?.tags || [])],\n\t\t\t\t\tdescription: options.metadata?.openapi?.description,\n\t\t\t\t\toperationId: options.metadata?.openapi?.operationId,\n\t\t\t\t\tsecurity: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbearerAuth: [],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparameters: getParameters(options),\n\t\t\t\t\t...(body\n\t\t\t\t\t\t? { requestBody: body }\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\trequestBody: {\n\t\t\t\t\t\t\t\t\t//set body none\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\tresponses: getResponse(options.metadata?.openapi?.responses),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t});\n\n\tconst res = {\n\t\topenapi: \"3.1.1\",\n\t\tinfo: {\n\t\t\ttitle: \"Better Auth\",\n\t\t\tdescription: \"API Reference for your Better Auth Instance\",\n\t\t\tversion: \"1.1.0\",\n\t\t},\n\t\tcomponents,\n\t\tsecurity: [\n\t\t\t{\n\t\t\t\tapiKeyCookie: [],\n\t\t\t},\n\t\t],\n\t\tservers: [\n\t\t\t{\n\t\t\t\turl: config?.url,\n\t\t\t},\n\t\t],\n\t\ttags: [\n\t\t\t{\n\t\t\t\tname: \"Default\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Default endpoints that are included with Better Auth by default. These endpoints are not part of any plugin.\",\n\t\t\t},\n\t\t],\n\t\tpaths,\n\t};\n\treturn res;\n}\n\nexport const getHTML = (\n\tapiReference: Record<string, any>,\n\tconfig?: {\n\t\tlogo?: string;\n\t\ttheme?: string;\n\t\ttitle?: string;\n\t\tdescription?: string;\n\t},\n) => `<!doctype html>\n<html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\">\n ${JSON.stringify(apiReference)}\n </script>\n\t <script>\n var configuration = {\n\t \tfavicon: ${config?.logo ? `data:image/svg+xml;utf8,${encodeURIComponent(config.logo)}` : undefined} ,\n\t \ttheme: ${config?.theme || \"saturn\"},\n metaData: {\n\t\t\ttitle: ${config?.title || \"Open API Reference\"},\n\t\t\tdescription: ${config?.description || \"Better Call Open API\"},\n\t\t}\n }\n document.getElementById('api-reference').dataset.configuration =\n JSON.stringify(configuration)\n </script>\n\t <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>`;\n"],"mappings":"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"}
|
package/dist/openapi.d.cts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Endpoint } from "./endpoint.cjs";
|
|
2
|
-
|
|
3
2
|
//#region src/openapi.d.ts
|
|
4
3
|
type OpenAPISchemaType = "string" | "number" | "integer" | "boolean" | "array" | "object";
|
|
5
4
|
interface OpenAPIParameter {
|
|
@@ -41,7 +40,7 @@ interface Path {
|
|
|
41
40
|
};
|
|
42
41
|
};
|
|
43
42
|
};
|
|
44
|
-
} };
|
|
43
|
+
}; };
|
|
45
44
|
};
|
|
46
45
|
post?: {
|
|
47
46
|
tags?: string[];
|
|
@@ -75,7 +74,7 @@ interface Path {
|
|
|
75
74
|
};
|
|
76
75
|
};
|
|
77
76
|
};
|
|
78
|
-
} };
|
|
77
|
+
}; };
|
|
79
78
|
};
|
|
80
79
|
}
|
|
81
80
|
declare function generator(endpoints: Record<string, Endpoint>, config?: {
|
package/dist/openapi.d.mts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Endpoint } from "./endpoint.mjs";
|
|
2
|
-
|
|
3
2
|
//#region src/openapi.d.ts
|
|
4
3
|
type OpenAPISchemaType = "string" | "number" | "integer" | "boolean" | "array" | "object";
|
|
5
4
|
interface OpenAPIParameter {
|
|
@@ -41,7 +40,7 @@ interface Path {
|
|
|
41
40
|
};
|
|
42
41
|
};
|
|
43
42
|
};
|
|
44
|
-
} };
|
|
43
|
+
}; };
|
|
45
44
|
};
|
|
46
45
|
post?: {
|
|
47
46
|
tags?: string[];
|
|
@@ -75,7 +74,7 @@ interface Path {
|
|
|
75
74
|
};
|
|
76
75
|
};
|
|
77
76
|
};
|
|
78
|
-
} };
|
|
77
|
+
}; };
|
|
79
78
|
};
|
|
80
79
|
}
|
|
81
80
|
declare function generator(endpoints: Record<string, Endpoint>, config?: {
|
package/dist/openapi.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ZodObject, ZodOptional } from "zod";
|
|
2
|
-
|
|
3
2
|
//#region src/openapi.ts
|
|
4
3
|
const paths = {};
|
|
5
4
|
function getTypeFromZodType(zodType) {
|
|
@@ -183,7 +182,7 @@ const getHTML = (apiReference, config) => `<!doctype html>
|
|
|
183
182
|
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
184
183
|
</body>
|
|
185
184
|
</html>`;
|
|
186
|
-
|
|
187
185
|
//#endregion
|
|
188
186
|
export { generator, getHTML };
|
|
187
|
+
|
|
189
188
|
//# sourceMappingURL=openapi.mjs.map
|
package/dist/openapi.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.mjs","names":[],"sources":["../src/openapi.ts"],"sourcesContent":["import { ZodObject, ZodOptional, ZodType } from \"zod\";\nimport type { Endpoint, EndpointOptions } from \"./endpoint\";\n\nexport type OpenAPISchemaType =\n\t| \"string\"\n\t| \"number\"\n\t| \"integer\"\n\t| \"boolean\"\n\t| \"array\"\n\t| \"object\";\n\nexport interface OpenAPIParameter {\n\tin: \"query\" | \"path\" | \"header\" | \"cookie\";\n\tname?: string;\n\tdescription?: string;\n\trequired?: boolean;\n\tschema?: {\n\t\ttype: OpenAPISchemaType;\n\t\tformat?: string | undefined;\n\t\titems?: {\n\t\t\ttype: OpenAPISchemaType;\n\t\t};\n\t\tenum?: string[];\n\t\tminLength?: number;\n\t\tdescription?: string | undefined;\n\t\tdefault?: string | undefined;\n\t\texample?: string | undefined;\n\t};\n}\n\nexport interface Path {\n\tget?: {\n\t\ttags?: string[];\n\t\toperationId?: string;\n\t\tdescription?: string;\n\t\tsecurity?: [{ bearerAuth: string[] }];\n\t\tparameters?: OpenAPIParameter[];\n\t\tresponses?: {\n\t\t\t[key in string]: {\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent: {\n\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t};\n\tpost?: {\n\t\ttags?: string[];\n\t\toperationId?: string;\n\t\tdescription?: string;\n\t\tsecurity?: [{ bearerAuth: string[] }];\n\t\tparameters?: OpenAPIParameter[];\n\t\trequestBody?: {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t\tresponses?: {\n\t\t\t[key in string]: {\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent: {\n\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t};\n}\nconst paths: Record<string, Path> = {};\n\nfunction getTypeFromZodType(zodType: ZodType<any>) {\n\tswitch (zodType.constructor.name) {\n\t\tcase \"ZodString\":\n\t\t\treturn \"string\";\n\t\tcase \"ZodNumber\":\n\t\t\treturn \"number\";\n\t\tcase \"ZodBoolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"ZodObject\":\n\t\t\treturn \"object\";\n\t\tcase \"ZodArray\":\n\t\t\treturn \"array\";\n\t\tdefault:\n\t\t\treturn \"string\";\n\t}\n}\n\nfunction getParameters(options: EndpointOptions) {\n\tconst parameters: OpenAPIParameter[] = [];\n\tif (options.metadata?.openapi?.parameters) {\n\t\tparameters.push(...options.metadata.openapi.parameters);\n\t\treturn parameters;\n\t}\n\tif (options.query instanceof ZodObject) {\n\t\tObject.entries(options.query.shape).forEach(([key, value]) => {\n\t\t\tif (value instanceof ZodObject) {\n\t\t\t\tparameters.push({\n\t\t\t\t\tname: key,\n\t\t\t\t\tin: \"query\",\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: getTypeFromZodType(value),\n\t\t\t\t\t\t...(\"minLength\" in value && value.minLength\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tminLength: value.minLength as number,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\tdescription: value.description,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\treturn parameters;\n}\n\nfunction getRequestBody(options: EndpointOptions): any {\n\tif (options.metadata?.openapi?.requestBody) {\n\t\treturn options.metadata.openapi.requestBody;\n\t}\n\tif (!options.body) return undefined;\n\tif (\n\t\toptions.body instanceof ZodObject ||\n\t\toptions.body instanceof ZodOptional\n\t) {\n\t\t// @ts-ignore\n\t\tconst shape = options.body.shape;\n\t\tif (!shape) return undefined;\n\t\tconst properties: Record<string, any> = {};\n\t\tconst required: string[] = [];\n\t\tObject.entries(shape).forEach(([key, value]) => {\n\t\t\tif (value instanceof ZodObject) {\n\t\t\t\tproperties[key] = {\n\t\t\t\t\ttype: getTypeFromZodType(value),\n\t\t\t\t\tdescription: value.description,\n\t\t\t\t};\n\t\t\t\tif (!(value instanceof ZodOptional)) {\n\t\t\t\t\trequired.push(key);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn {\n\t\t\trequired:\n\t\t\t\toptions.body instanceof ZodOptional\n\t\t\t\t\t? false\n\t\t\t\t\t: options.body\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: false,\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\trequired,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\treturn undefined;\n}\n\nfunction getResponse(responses?: Record<string, any>) {\n\treturn {\n\t\t\"400\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"message\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Bad Request. Usually due to missing parameters, or invalid parameters.\",\n\t\t},\n\t\t\"401\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"message\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription: \"Unauthorized. Due to missing or invalid authentication.\",\n\t\t},\n\t\t\"403\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Forbidden. You do not have permission to access this resource or to perform this action.\",\n\t\t},\n\t\t\"404\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription: \"Not Found. The requested resource was not found.\",\n\t\t},\n\t\t\"429\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Too Many Requests. You have exceeded the rate limit. Try again later.\",\n\t\t},\n\t\t\"500\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Internal Server Error. This is a problem with the server that you cannot fix.\",\n\t\t},\n\t\t...responses,\n\t} as any;\n}\n\nexport async function generator(\n\tendpoints: Record<string, Endpoint>,\n\tconfig?: {\n\t\turl: string;\n\t},\n) {\n\tconst components = {\n\t\tschemas: {},\n\t};\n\n\tObject.entries(endpoints).forEach(([_, value]) => {\n\t\tconst options = value.options as EndpointOptions;\n\t\tif (!value.path || options.metadata?.SERVER_ONLY) return;\n\t\tif (options.method === \"GET\") {\n\t\t\tpaths[value.path] = {\n\t\t\t\tget: {\n\t\t\t\t\ttags: [\"Default\", ...(options.metadata?.openapi?.tags || [])],\n\t\t\t\t\tdescription: options.metadata?.openapi?.description,\n\t\t\t\t\toperationId: options.metadata?.openapi?.operationId,\n\t\t\t\t\tsecurity: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbearerAuth: [],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparameters: getParameters(options),\n\t\t\t\t\tresponses: getResponse(options.metadata?.openapi?.responses),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tif (options.method === \"POST\") {\n\t\t\tconst body = getRequestBody(options);\n\t\t\tpaths[value.path] = {\n\t\t\t\tpost: {\n\t\t\t\t\ttags: [\"Default\", ...(options.metadata?.openapi?.tags || [])],\n\t\t\t\t\tdescription: options.metadata?.openapi?.description,\n\t\t\t\t\toperationId: options.metadata?.openapi?.operationId,\n\t\t\t\t\tsecurity: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbearerAuth: [],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparameters: getParameters(options),\n\t\t\t\t\t...(body\n\t\t\t\t\t\t? { requestBody: body }\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\trequestBody: {\n\t\t\t\t\t\t\t\t\t//set body none\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\tresponses: getResponse(options.metadata?.openapi?.responses),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t});\n\n\tconst res = {\n\t\topenapi: \"3.1.1\",\n\t\tinfo: {\n\t\t\ttitle: \"Better Auth\",\n\t\t\tdescription: \"API Reference for your Better Auth Instance\",\n\t\t\tversion: \"1.1.0\",\n\t\t},\n\t\tcomponents,\n\t\tsecurity: [\n\t\t\t{\n\t\t\t\tapiKeyCookie: [],\n\t\t\t},\n\t\t],\n\t\tservers: [\n\t\t\t{\n\t\t\t\turl: config?.url,\n\t\t\t},\n\t\t],\n\t\ttags: [\n\t\t\t{\n\t\t\t\tname: \"Default\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Default endpoints that are included with Better Auth by default. These endpoints are not part of any plugin.\",\n\t\t\t},\n\t\t],\n\t\tpaths,\n\t};\n\treturn res;\n}\n\nexport const getHTML = (\n\tapiReference: Record<string, any>,\n\tconfig?: {\n\t\tlogo?: string;\n\t\ttheme?: string;\n\t\ttitle?: string;\n\t\tdescription?: string;\n\t},\n) => `<!doctype html>\n<html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\">\n ${JSON.stringify(apiReference)}\n </script>\n\t <script>\n var configuration = {\n\t \tfavicon: ${config?.logo ? `data:image/svg+xml;utf8,${encodeURIComponent(config.logo)}` : undefined} ,\n\t \ttheme: ${config?.theme || \"saturn\"},\n metaData: {\n\t\t\ttitle: ${config?.title || \"Open API Reference\"},\n\t\t\tdescription: ${config?.description || \"Better Call Open API\"},\n\t\t}\n }\n document.getElementById('api-reference').dataset.configuration =\n JSON.stringify(configuration)\n </script>\n\t <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>`;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"openapi.mjs","names":[],"sources":["../src/openapi.ts"],"sourcesContent":["import type { ZodType } from \"zod\";\nimport { ZodObject, ZodOptional } from \"zod\";\nimport type { Endpoint, EndpointOptions } from \"./endpoint\";\n\nexport type OpenAPISchemaType =\n\t| \"string\"\n\t| \"number\"\n\t| \"integer\"\n\t| \"boolean\"\n\t| \"array\"\n\t| \"object\";\n\nexport interface OpenAPIParameter {\n\tin: \"query\" | \"path\" | \"header\" | \"cookie\";\n\tname?: string;\n\tdescription?: string;\n\trequired?: boolean;\n\tschema?: {\n\t\ttype: OpenAPISchemaType;\n\t\tformat?: string | undefined;\n\t\titems?: {\n\t\t\ttype: OpenAPISchemaType;\n\t\t};\n\t\tenum?: string[];\n\t\tminLength?: number;\n\t\tdescription?: string | undefined;\n\t\tdefault?: string | undefined;\n\t\texample?: string | undefined;\n\t};\n}\n\nexport interface Path {\n\tget?: {\n\t\ttags?: string[];\n\t\toperationId?: string;\n\t\tdescription?: string;\n\t\tsecurity?: [{ bearerAuth: string[] }];\n\t\tparameters?: OpenAPIParameter[];\n\t\tresponses?: {\n\t\t\t[key in string]: {\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent: {\n\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t};\n\tpost?: {\n\t\ttags?: string[];\n\t\toperationId?: string;\n\t\tdescription?: string;\n\t\tsecurity?: [{ bearerAuth: string[] }];\n\t\tparameters?: OpenAPIParameter[];\n\t\trequestBody?: {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t\tresponses?: {\n\t\t\t[key in string]: {\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent: {\n\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype?: OpenAPISchemaType;\n\t\t\t\t\t\t\tproperties?: Record<string, any>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t\t$ref?: string;\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t};\n}\nconst paths: Record<string, Path> = {};\n\nfunction getTypeFromZodType(zodType: ZodType<any>) {\n\tswitch (zodType.constructor.name) {\n\t\tcase \"ZodString\":\n\t\t\treturn \"string\";\n\t\tcase \"ZodNumber\":\n\t\t\treturn \"number\";\n\t\tcase \"ZodBoolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"ZodObject\":\n\t\t\treturn \"object\";\n\t\tcase \"ZodArray\":\n\t\t\treturn \"array\";\n\t\tdefault:\n\t\t\treturn \"string\";\n\t}\n}\n\nfunction getParameters(options: EndpointOptions) {\n\tconst parameters: OpenAPIParameter[] = [];\n\tif (options.metadata?.openapi?.parameters) {\n\t\tparameters.push(...options.metadata.openapi.parameters);\n\t\treturn parameters;\n\t}\n\tif (options.query instanceof ZodObject) {\n\t\tObject.entries(options.query.shape).forEach(([key, value]) => {\n\t\t\tif (value instanceof ZodObject) {\n\t\t\t\tparameters.push({\n\t\t\t\t\tname: key,\n\t\t\t\t\tin: \"query\",\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: getTypeFromZodType(value),\n\t\t\t\t\t\t...(\"minLength\" in value && value.minLength\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tminLength: value.minLength as number,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\tdescription: value.description,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\treturn parameters;\n}\n\nfunction getRequestBody(options: EndpointOptions): any {\n\tif (options.metadata?.openapi?.requestBody) {\n\t\treturn options.metadata.openapi.requestBody;\n\t}\n\tif (!options.body) return undefined;\n\tif (\n\t\toptions.body instanceof ZodObject ||\n\t\toptions.body instanceof ZodOptional\n\t) {\n\t\t// @ts-expect-error\n\t\tconst shape = options.body.shape;\n\t\tif (!shape) return undefined;\n\t\tconst properties: Record<string, any> = {};\n\t\tconst required: string[] = [];\n\t\tObject.entries(shape).forEach(([key, value]) => {\n\t\t\tif (value instanceof ZodObject) {\n\t\t\t\tproperties[key] = {\n\t\t\t\t\ttype: getTypeFromZodType(value),\n\t\t\t\t\tdescription: value.description,\n\t\t\t\t};\n\t\t\t\tif (!(value instanceof ZodOptional)) {\n\t\t\t\t\trequired.push(key);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn {\n\t\t\trequired:\n\t\t\t\toptions.body instanceof ZodOptional\n\t\t\t\t\t? false\n\t\t\t\t\t: options.body\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: false,\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\trequired,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\treturn undefined;\n}\n\nfunction getResponse(responses?: Record<string, any>) {\n\treturn {\n\t\t\"400\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"message\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Bad Request. Usually due to missing parameters, or invalid parameters.\",\n\t\t},\n\t\t\"401\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: [\"message\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription: \"Unauthorized. Due to missing or invalid authentication.\",\n\t\t},\n\t\t\"403\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Forbidden. You do not have permission to access this resource or to perform this action.\",\n\t\t},\n\t\t\"404\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription: \"Not Found. The requested resource was not found.\",\n\t\t},\n\t\t\"429\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Too Many Requests. You have exceeded the rate limit. Try again later.\",\n\t\t},\n\t\t\"500\": {\n\t\t\tcontent: {\n\t\t\t\t\"application/json\": {\n\t\t\t\t\tschema: {\n\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t\"Internal Server Error. This is a problem with the server that you cannot fix.\",\n\t\t},\n\t\t...responses,\n\t} as any;\n}\n\nexport async function generator(\n\tendpoints: Record<string, Endpoint>,\n\tconfig?: {\n\t\turl: string;\n\t},\n) {\n\tconst components = {\n\t\tschemas: {},\n\t};\n\n\tObject.entries(endpoints).forEach(([_, value]) => {\n\t\tconst options = value.options as EndpointOptions;\n\t\tif (!value.path || options.metadata?.SERVER_ONLY) return;\n\t\tif (options.method === \"GET\") {\n\t\t\tpaths[value.path] = {\n\t\t\t\tget: {\n\t\t\t\t\ttags: [\"Default\", ...(options.metadata?.openapi?.tags || [])],\n\t\t\t\t\tdescription: options.metadata?.openapi?.description,\n\t\t\t\t\toperationId: options.metadata?.openapi?.operationId,\n\t\t\t\t\tsecurity: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbearerAuth: [],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparameters: getParameters(options),\n\t\t\t\t\tresponses: getResponse(options.metadata?.openapi?.responses),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tif (options.method === \"POST\") {\n\t\t\tconst body = getRequestBody(options);\n\t\t\tpaths[value.path] = {\n\t\t\t\tpost: {\n\t\t\t\t\ttags: [\"Default\", ...(options.metadata?.openapi?.tags || [])],\n\t\t\t\t\tdescription: options.metadata?.openapi?.description,\n\t\t\t\t\toperationId: options.metadata?.openapi?.operationId,\n\t\t\t\t\tsecurity: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbearerAuth: [],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparameters: getParameters(options),\n\t\t\t\t\t...(body\n\t\t\t\t\t\t? { requestBody: body }\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\trequestBody: {\n\t\t\t\t\t\t\t\t\t//set body none\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\tresponses: getResponse(options.metadata?.openapi?.responses),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t});\n\n\tconst res = {\n\t\topenapi: \"3.1.1\",\n\t\tinfo: {\n\t\t\ttitle: \"Better Auth\",\n\t\t\tdescription: \"API Reference for your Better Auth Instance\",\n\t\t\tversion: \"1.1.0\",\n\t\t},\n\t\tcomponents,\n\t\tsecurity: [\n\t\t\t{\n\t\t\t\tapiKeyCookie: [],\n\t\t\t},\n\t\t],\n\t\tservers: [\n\t\t\t{\n\t\t\t\turl: config?.url,\n\t\t\t},\n\t\t],\n\t\ttags: [\n\t\t\t{\n\t\t\t\tname: \"Default\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Default endpoints that are included with Better Auth by default. These endpoints are not part of any plugin.\",\n\t\t\t},\n\t\t],\n\t\tpaths,\n\t};\n\treturn res;\n}\n\nexport const getHTML = (\n\tapiReference: Record<string, any>,\n\tconfig?: {\n\t\tlogo?: string;\n\t\ttheme?: string;\n\t\ttitle?: string;\n\t\tdescription?: string;\n\t},\n) => `<!doctype html>\n<html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\">\n ${JSON.stringify(apiReference)}\n </script>\n\t <script>\n var configuration = {\n\t \tfavicon: ${config?.logo ? `data:image/svg+xml;utf8,${encodeURIComponent(config.logo)}` : undefined} ,\n\t \ttheme: ${config?.theme || \"saturn\"},\n metaData: {\n\t\t\ttitle: ${config?.title || \"Open API Reference\"},\n\t\t\tdescription: ${config?.description || \"Better Call Open API\"},\n\t\t}\n }\n document.getElementById('api-reference').dataset.configuration =\n JSON.stringify(configuration)\n </script>\n\t <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>`;\n"],"mappings":"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"}
|
package/dist/router.cjs
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const require_openapi = require('./openapi.cjs');
|
|
1
|
+
const require_utils = require("./utils.cjs");
|
|
2
|
+
const require_to_response = require("./to-response.cjs");
|
|
3
|
+
const require_endpoint = require("./endpoint.cjs");
|
|
4
|
+
const require_openapi = require("./openapi.cjs");
|
|
6
5
|
let rou3 = require("rou3");
|
|
7
|
-
|
|
8
6
|
//#region src/router.ts
|
|
9
7
|
const createRouter = (endpoints, config) => {
|
|
10
8
|
if (!config?.openapi?.disabled) {
|
|
@@ -112,7 +110,7 @@ const createRouter = (endpoints, config) => {
|
|
|
112
110
|
endpoints
|
|
113
111
|
};
|
|
114
112
|
};
|
|
115
|
-
|
|
116
113
|
//#endregion
|
|
117
114
|
exports.createRouter = createRouter;
|
|
115
|
+
|
|
118
116
|
//# sourceMappingURL=router.cjs.map
|
package/dist/router.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.cjs","names":["createEndpoint","generator","getHTML","getBody","toResponse","isAPIError","isRequest"],"sources":["../src/router.ts"],"sourcesContent":["import {\n\taddRoute,\n\tcreateRouter as createRou3Router,\n\tfindAllRoutes,\n\tfindRoute,\n} 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, isRequest } from \"./utils\";\n\nexport interface RouterConfig {\n\tthrowError?: boolean;\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?: (response: Response, request: Request) => any | Promise<any>;\n\t/**\n\t * A callback to run before any request\n\t */\n\tonRequest?: (request: Request) => any | Promise<any>;\n\t/**\n\t * A callback to run when an error is thrown in the router or middleware.\n\t *\n\t * @param error - the error that was thrown in the router or middleware.\n\t * @returns a Response object that will be returned to the client.\n\t */\n\tonError?: (\n\t\terror: unknown,\n\t\trequest: Request,\n\t) => void | Promise<void> | Response | Promise<Response>;\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 = <\n\tE extends Record<string, Endpoint>,\n\tConfig extends RouterConfig,\n>(\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\t// Normalize the configured base path once. `basePath` is configuration, not\n\t// per-request input, so trailing-slash normalization belongs here rather than\n\t// in the request hot path. An empty result (unset, \"/\", or all slashes) means\n\t// \"no base path\": route on the full pathname.\n\tconst basePath =\n\t\tconfig?.basePath && config.basePath !== \"/\"\n\t\t\t? config.basePath.replace(/\\/+$/, \"\")\n\t\t\t: \"\";\n\n\tconst processRequest = async (request: Request) => {\n\t\tconst url = new URL(request.url);\n\t\tconst pathname = url.pathname;\n\t\t// Strip `basePath` only when it is a leading, \"/\"-boundary prefix of the\n\t\t// request pathname. A pathname that does not start with the configured\n\t\t// basePath is outside this router and resolves to a 404, so a path like\n\t\t// \"/x/api/test\" never reaches \"/test\". The \"/\" boundary also rejects a\n\t\t// path where basePath is only a leading substring, not a full segment.\n\t\t// The previous implementation stripped basePath wherever it occurred\n\t\t// (`pathname.split(basePath)`).\n\t\tlet path: string;\n\t\tif (basePath) {\n\t\t\tif (!pathname.startsWith(`${basePath}/`)) {\n\t\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t\t}\n\t\t\tpath = pathname.slice(basePath.length);\n\t\t} else {\n\t\t\tpath = pathname;\n\t\t}\n\n\t\t// Reject empty paths and paths with consecutive slashes.\n\t\tif (path.length === 0 || /\\/{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 (\n\t\t\thasTrailingSlash !== routeHasTrailingSlash &&\n\t\t\t!config?.skipTrailingSlashes\n\t\t) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\t\tif (!route?.data)\n\t\t\treturn 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 ||\n\t\t\t\tconfig?.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\n\t\t\t\t\t? (JSON.parse(JSON.stringify(route.params)) as any)\n\t\t\t\t\t: {},\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, request);\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 = isRequest(onReq) ? onReq : request;\n\t\t\tconst res = await processRequest(req);\n\t\t\tconst onRes = await config?.onResponse?.(res, req);\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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"}
|
|
1
|
+
{"version":3,"file":"router.cjs","names":["createEndpoint","generator","getHTML","getBody","toResponse","isAPIError","isRequest"],"sources":["../src/router.ts"],"sourcesContent":["import {\n\taddRoute,\n\tcreateRouter as createRou3Router,\n\tfindAllRoutes,\n\tfindRoute,\n} from \"rou3\";\nimport type { Endpoint } from \"./endpoint\";\nimport { createEndpoint } from \"./endpoint\";\nimport type { Middleware } from \"./middleware\";\nimport { generator, getHTML } from \"./openapi\";\nimport { toResponse } from \"./to-response\";\nimport { getBody, isAPIError, isRequest } from \"./utils\";\n\nexport interface RouterConfig {\n\tthrowError?: boolean;\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?: (response: Response, request: Request) => any | Promise<any>;\n\t/**\n\t * A callback to run before any request\n\t */\n\tonRequest?: (request: Request) => any | Promise<any>;\n\t/**\n\t * A callback to run when an error is thrown in the router or middleware.\n\t *\n\t * @param error - the error that was thrown in the router or middleware.\n\t * @returns a Response object that will be returned to the client.\n\t */\n\tonError?: (\n\t\terror: unknown,\n\t\trequest: Request,\n\t) => void | Promise<void> | Response | Promise<Response>;\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 = <\n\tE extends Record<string, Endpoint>,\n\tConfig extends RouterConfig,\n>(\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\t// Normalize the configured base path once. `basePath` is configuration, not\n\t// per-request input, so trailing-slash normalization belongs here rather than\n\t// in the request hot path. An empty result (unset, \"/\", or all slashes) means\n\t// \"no base path\": route on the full pathname.\n\tconst basePath =\n\t\tconfig?.basePath && config.basePath !== \"/\"\n\t\t\t? config.basePath.replace(/\\/+$/, \"\")\n\t\t\t: \"\";\n\n\tconst processRequest = async (request: Request) => {\n\t\tconst url = new URL(request.url);\n\t\tconst pathname = url.pathname;\n\t\t// Strip `basePath` only when it is a leading, \"/\"-boundary prefix of the\n\t\t// request pathname. A pathname that does not start with the configured\n\t\t// basePath is outside this router and resolves to a 404, so a path like\n\t\t// \"/x/api/test\" never reaches \"/test\". The \"/\" boundary also rejects a\n\t\t// path where basePath is only a leading substring, not a full segment.\n\t\t// The previous implementation stripped basePath wherever it occurred\n\t\t// (`pathname.split(basePath)`).\n\t\tlet path: string;\n\t\tif (basePath) {\n\t\t\tif (!pathname.startsWith(`${basePath}/`)) {\n\t\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t\t}\n\t\t\tpath = pathname.slice(basePath.length);\n\t\t} else {\n\t\t\tpath = pathname;\n\t\t}\n\n\t\t// Reject empty paths and paths with consecutive slashes.\n\t\tif (path.length === 0 || /\\/{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 (\n\t\t\thasTrailingSlash !== routeHasTrailingSlash &&\n\t\t\t!config?.skipTrailingSlashes\n\t\t) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\t\tif (!route?.data)\n\t\t\treturn 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 ||\n\t\t\t\tconfig?.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\n\t\t\t\t\t? (JSON.parse(JSON.stringify(route.params)) as any)\n\t\t\t\t\t: {},\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, request);\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 = isRequest(onReq) ? onReq : request;\n\t\t\tconst res = await processRequest(req);\n\t\t\tconst onRes = await config?.onResponse?.(res, req);\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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"}
|
package/dist/router.d.cts
CHANGED
package/dist/router.d.mts
CHANGED
package/dist/router.mjs
CHANGED
|
@@ -3,7 +3,6 @@ import { toResponse } from "./to-response.mjs";
|
|
|
3
3
|
import { createEndpoint } from "./endpoint.mjs";
|
|
4
4
|
import { generator, getHTML } from "./openapi.mjs";
|
|
5
5
|
import { addRoute, createRouter, findAllRoutes, findRoute } from "rou3";
|
|
6
|
-
|
|
7
6
|
//#region src/router.ts
|
|
8
7
|
const createRouter$1 = (endpoints, config) => {
|
|
9
8
|
if (!config?.openapi?.disabled) {
|
|
@@ -111,7 +110,7 @@ const createRouter$1 = (endpoints, config) => {
|
|
|
111
110
|
endpoints
|
|
112
111
|
};
|
|
113
112
|
};
|
|
114
|
-
|
|
115
113
|
//#endregion
|
|
116
114
|
export { createRouter$1 as createRouter };
|
|
115
|
+
|
|
117
116
|
//# sourceMappingURL=router.mjs.map
|
package/dist/router.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.mjs","names":["createRouter","createRou3Router"],"sources":["../src/router.ts"],"sourcesContent":["import {\n\taddRoute,\n\tcreateRouter as createRou3Router,\n\tfindAllRoutes,\n\tfindRoute,\n} 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, isRequest } from \"./utils\";\n\nexport interface RouterConfig {\n\tthrowError?: boolean;\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?: (response: Response, request: Request) => any | Promise<any>;\n\t/**\n\t * A callback to run before any request\n\t */\n\tonRequest?: (request: Request) => any | Promise<any>;\n\t/**\n\t * A callback to run when an error is thrown in the router or middleware.\n\t *\n\t * @param error - the error that was thrown in the router or middleware.\n\t * @returns a Response object that will be returned to the client.\n\t */\n\tonError?: (\n\t\terror: unknown,\n\t\trequest: Request,\n\t) => void | Promise<void> | Response | Promise<Response>;\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 = <\n\tE extends Record<string, Endpoint>,\n\tConfig extends RouterConfig,\n>(\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\t// Normalize the configured base path once. `basePath` is configuration, not\n\t// per-request input, so trailing-slash normalization belongs here rather than\n\t// in the request hot path. An empty result (unset, \"/\", or all slashes) means\n\t// \"no base path\": route on the full pathname.\n\tconst basePath =\n\t\tconfig?.basePath && config.basePath !== \"/\"\n\t\t\t? config.basePath.replace(/\\/+$/, \"\")\n\t\t\t: \"\";\n\n\tconst processRequest = async (request: Request) => {\n\t\tconst url = new URL(request.url);\n\t\tconst pathname = url.pathname;\n\t\t// Strip `basePath` only when it is a leading, \"/\"-boundary prefix of the\n\t\t// request pathname. A pathname that does not start with the configured\n\t\t// basePath is outside this router and resolves to a 404, so a path like\n\t\t// \"/x/api/test\" never reaches \"/test\". The \"/\" boundary also rejects a\n\t\t// path where basePath is only a leading substring, not a full segment.\n\t\t// The previous implementation stripped basePath wherever it occurred\n\t\t// (`pathname.split(basePath)`).\n\t\tlet path: string;\n\t\tif (basePath) {\n\t\t\tif (!pathname.startsWith(`${basePath}/`)) {\n\t\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t\t}\n\t\t\tpath = pathname.slice(basePath.length);\n\t\t} else {\n\t\t\tpath = pathname;\n\t\t}\n\n\t\t// Reject empty paths and paths with consecutive slashes.\n\t\tif (path.length === 0 || /\\/{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 (\n\t\t\thasTrailingSlash !== routeHasTrailingSlash &&\n\t\t\t!config?.skipTrailingSlashes\n\t\t) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\t\tif (!route?.data)\n\t\t\treturn 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 ||\n\t\t\t\tconfig?.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\n\t\t\t\t\t? (JSON.parse(JSON.stringify(route.params)) as any)\n\t\t\t\t\t: {},\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, request);\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 = isRequest(onReq) ? onReq : request;\n\t\t\tconst res = await processRequest(req);\n\t\t\tconst onRes = await config?.onResponse?.(res, req);\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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"}
|
|
1
|
+
{"version":3,"file":"router.mjs","names":["createRouter","createRou3Router"],"sources":["../src/router.ts"],"sourcesContent":["import {\n\taddRoute,\n\tcreateRouter as createRou3Router,\n\tfindAllRoutes,\n\tfindRoute,\n} from \"rou3\";\nimport type { Endpoint } from \"./endpoint\";\nimport { createEndpoint } from \"./endpoint\";\nimport type { Middleware } from \"./middleware\";\nimport { generator, getHTML } from \"./openapi\";\nimport { toResponse } from \"./to-response\";\nimport { getBody, isAPIError, isRequest } from \"./utils\";\n\nexport interface RouterConfig {\n\tthrowError?: boolean;\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?: (response: Response, request: Request) => any | Promise<any>;\n\t/**\n\t * A callback to run before any request\n\t */\n\tonRequest?: (request: Request) => any | Promise<any>;\n\t/**\n\t * A callback to run when an error is thrown in the router or middleware.\n\t *\n\t * @param error - the error that was thrown in the router or middleware.\n\t * @returns a Response object that will be returned to the client.\n\t */\n\tonError?: (\n\t\terror: unknown,\n\t\trequest: Request,\n\t) => void | Promise<void> | Response | Promise<Response>;\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 = <\n\tE extends Record<string, Endpoint>,\n\tConfig extends RouterConfig,\n>(\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\t// Normalize the configured base path once. `basePath` is configuration, not\n\t// per-request input, so trailing-slash normalization belongs here rather than\n\t// in the request hot path. An empty result (unset, \"/\", or all slashes) means\n\t// \"no base path\": route on the full pathname.\n\tconst basePath =\n\t\tconfig?.basePath && config.basePath !== \"/\"\n\t\t\t? config.basePath.replace(/\\/+$/, \"\")\n\t\t\t: \"\";\n\n\tconst processRequest = async (request: Request) => {\n\t\tconst url = new URL(request.url);\n\t\tconst pathname = url.pathname;\n\t\t// Strip `basePath` only when it is a leading, \"/\"-boundary prefix of the\n\t\t// request pathname. A pathname that does not start with the configured\n\t\t// basePath is outside this router and resolves to a 404, so a path like\n\t\t// \"/x/api/test\" never reaches \"/test\". The \"/\" boundary also rejects a\n\t\t// path where basePath is only a leading substring, not a full segment.\n\t\t// The previous implementation stripped basePath wherever it occurred\n\t\t// (`pathname.split(basePath)`).\n\t\tlet path: string;\n\t\tif (basePath) {\n\t\t\tif (!pathname.startsWith(`${basePath}/`)) {\n\t\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t\t}\n\t\t\tpath = pathname.slice(basePath.length);\n\t\t} else {\n\t\t\tpath = pathname;\n\t\t}\n\n\t\t// Reject empty paths and paths with consecutive slashes.\n\t\tif (path.length === 0 || /\\/{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 (\n\t\t\thasTrailingSlash !== routeHasTrailingSlash &&\n\t\t\t!config?.skipTrailingSlashes\n\t\t) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\t\tif (!route?.data)\n\t\t\treturn 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 ||\n\t\t\t\tconfig?.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\n\t\t\t\t\t? (JSON.parse(JSON.stringify(route.params)) as any)\n\t\t\t\t\t: {},\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, request);\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 = isRequest(onReq) ? onReq : request;\n\t\t\tconst res = await processRequest(req);\n\t\t\tconst onRes = await config?.onResponse?.(res, req);\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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"}
|
package/dist/to-response.cjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
require(
|
|
2
|
-
const require_utils = require('./utils.cjs');
|
|
3
|
-
|
|
1
|
+
const require_utils = require("./utils.cjs");
|
|
4
2
|
//#region src/to-response.ts
|
|
5
3
|
function isJSONSerializable(value) {
|
|
6
4
|
if (value === void 0) return false;
|
|
@@ -53,7 +51,7 @@ function isJSONResponse(value) {
|
|
|
53
51
|
* - RFC 6265 §5.4 (Cookie)
|
|
54
52
|
* - RFC 6454 (Origin)
|
|
55
53
|
*/
|
|
56
|
-
const REQUEST_ONLY_HEADERS = new Set([
|
|
54
|
+
const REQUEST_ONLY_HEADERS = /* @__PURE__ */ new Set([
|
|
57
55
|
"host",
|
|
58
56
|
"user-agent",
|
|
59
57
|
"referer",
|
|
@@ -160,7 +158,7 @@ function toResponse(data, init) {
|
|
|
160
158
|
headers
|
|
161
159
|
});
|
|
162
160
|
}
|
|
163
|
-
|
|
164
161
|
//#endregion
|
|
165
162
|
exports.toResponse = toResponse;
|
|
163
|
+
|
|
166
164
|
//# sourceMappingURL=to-response.cjs.map
|
package/dist/to-response.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-response.cjs","names":["isAPIError"],"sources":["../src/to-response.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"to-response.cjs","names":["isAPIError"],"sources":["../src/to-response.ts"],"sourcesContent":["import { 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(obj: unknown): string {\n\tconst parents = new WeakMap<object, object>();\n\tconst ids = new WeakMap<object, number>();\n\tlet id = 0;\n\n\tconst isAncestor = (value: object, holder: object): boolean => {\n\t\tlet curr: object | undefined = holder;\n\t\twhile (curr) {\n\t\t\tif (curr === value) return true;\n\t\t\tcurr = parents.get(curr);\n\t\t}\n\t\treturn false;\n\t};\n\n\treturn JSON.stringify(obj, function (this: any, _key, value) {\n\t\tif (typeof value === \"bigint\") return value.toString();\n\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\tif (isAncestor(value, this)) {\n\t\t\t\treturn `[Circular ref-${ids.get(value)}]`;\n\t\t\t}\n\t\t\tparents.set(value, this);\n\t\t\tif (!ids.has(value)) ids.set(value, id++);\n\t\t}\n\t\treturn value;\n\t});\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\n/**\n * Headers that MUST be stripped when building an HTTP response from\n * arbitrary header input. These are request-only, hop-by-hop, or\n * transport-managed headers that cause protocol violations when present\n * on responses (e.g. Content-Length mismatch → net::ERR_CONTENT_LENGTH_MISMATCH).\n *\n * Sources:\n * - RFC 9110 §10.1 (Request Context Fields)\n * - RFC 9110 §7.6.1 (Connection / hop-by-hop)\n * - RFC 9110 §11.6-7 (Authentication credentials)\n * - RFC 9110 §12.5 (Content negotiation)\n * - RFC 9110 §13.1 (Conditional request headers)\n * - RFC 9110 §14.2 (Range requests)\n * - RFC 6265 §5.4 (Cookie)\n * - RFC 6454 (Origin)\n */\nconst REQUEST_ONLY_HEADERS = new Set([\n\t// Request context (RFC 9110 §10.1)\n\t\"host\", // §7.2\n\t\"user-agent\", // §10.1.5\n\t\"referer\", // §10.1.3\n\t\"from\", // §10.1.2\n\t\"expect\", // §10.1.1\n\n\t// Authentication credentials (RFC 9110 §11.6-7)\n\t\"authorization\", // §11.6.2\n\t\"proxy-authorization\", // §11.7.2\n\t\"cookie\", // RFC 6265 §5.4\n\t\"origin\", // RFC 6454\n\n\t// Content negotiation (RFC 9110 §12.5)\n\t\"accept-charset\", // §12.5.2 (deprecated)\n\t\"accept-encoding\", // §12.5.3\n\t\"accept-language\", // §12.5.4\n\n\t// Conditional requests (RFC 9110 §13.1)\n\t\"if-match\", // §13.1.1\n\t\"if-none-match\", // §13.1.2\n\t\"if-modified-since\", // §13.1.3\n\t\"if-unmodified-since\", // §13.1.4\n\t\"if-range\", // §13.1.5\n\n\t// Range requests (RFC 9110 §14.2)\n\t\"range\", // §14.2\n\n\t// Forwarding control (RFC 9110 §7.6)\n\t\"max-forwards\", // §7.6.2\n\n\t// Hop-by-hop (RFC 9110 §7.6.1)\n\t\"connection\", // §7.6.1\n\t\"keep-alive\",\n\t\"transfer-encoding\",\n\t\"te\", // §10.1.4\n\t\"upgrade\",\n\t\"trailer\",\n\t\"proxy-connection\", // non-standard\n\n\t// Valid on responses but WRONG if copied from request (RFC 9110 §8.6)\n\t\"content-length\",\n]);\n\nfunction stripRequestOnlyHeaders(headers: Headers): void {\n\tfor (const name of REQUEST_ONLY_HEADERS) {\n\t\theaders.delete(name);\n\t}\n}\n\n/**\n * Copy headers from `source` into `target`. `Set-Cookie` is appended (one\n * header per cookie) because RFC 9110 §5.3 notes it cannot be combined\n * into a single comma-separated value; other headers are set (replace).\n */\nfunction copyHeaders(target: Headers, source: HeadersInit | undefined): void {\n\tif (!source) return;\n\tfor (const [key, value] of new Headers(source).entries()) {\n\t\tif (key.toLowerCase() === \"set-cookie\") {\n\t\t\ttarget.append(key, value);\n\t\t} else {\n\t\t\ttarget.set(key, value);\n\t\t}\n\t}\n}\n\nexport function toResponse(data?: any, init?: ResponseInit): Response {\n\tif (data instanceof Response) {\n\t\tif (init?.headers) {\n\t\t\tconst safeHeaders = new Headers(init.headers);\n\t\t\tstripRequestOnlyHeaders(safeHeaders);\n\t\t\tcopyHeaders(data.headers, safeHeaders);\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\tcopyHeaders(headers, routerResponse?.headers);\n\t\tcopyHeaders(headers, data.headers);\n\t\tif (init?.headers) {\n\t\t\tconst safeHeaders = new Headers(init.headers);\n\t\t\tstripRequestOnlyHeaders(safeHeaders);\n\t\t\tcopyHeaders(headers, safeHeaders);\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\tconst headers = new Headers(init?.headers);\n\tstripRequestOnlyHeaders(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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"}
|
package/dist/to-response.mjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import "./error.mjs";
|
|
2
1
|
import { isAPIError } from "./utils.mjs";
|
|
3
|
-
|
|
4
2
|
//#region src/to-response.ts
|
|
5
3
|
function isJSONSerializable(value) {
|
|
6
4
|
if (value === void 0) return false;
|
|
@@ -53,7 +51,7 @@ function isJSONResponse(value) {
|
|
|
53
51
|
* - RFC 6265 §5.4 (Cookie)
|
|
54
52
|
* - RFC 6454 (Origin)
|
|
55
53
|
*/
|
|
56
|
-
const REQUEST_ONLY_HEADERS = new Set([
|
|
54
|
+
const REQUEST_ONLY_HEADERS = /* @__PURE__ */ new Set([
|
|
57
55
|
"host",
|
|
58
56
|
"user-agent",
|
|
59
57
|
"referer",
|
|
@@ -160,7 +158,7 @@ function toResponse(data, init) {
|
|
|
160
158
|
headers
|
|
161
159
|
});
|
|
162
160
|
}
|
|
163
|
-
|
|
164
161
|
//#endregion
|
|
165
162
|
export { toResponse };
|
|
163
|
+
|
|
166
164
|
//# sourceMappingURL=to-response.mjs.map
|