better-call 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,79 +3,79 @@ import { Endpoint } from "./endpoint.cjs";
3
3
  type OpenAPISchemaType = "string" | "number" | "integer" | "boolean" | "array" | "object";
4
4
  interface OpenAPIParameter {
5
5
  in: "query" | "path" | "header" | "cookie";
6
- name?: string;
7
- description?: string;
8
- required?: boolean;
6
+ name?: string | undefined;
7
+ description?: string | undefined;
8
+ required?: boolean | undefined;
9
9
  schema?: {
10
10
  type: OpenAPISchemaType;
11
11
  format?: string | undefined;
12
12
  items?: {
13
13
  type: OpenAPISchemaType;
14
- };
15
- enum?: string[];
16
- minLength?: number;
14
+ } | undefined;
15
+ enum?: string[] | undefined;
16
+ minLength?: number | undefined;
17
17
  description?: string | undefined;
18
18
  default?: string | undefined;
19
19
  example?: string | undefined;
20
- };
20
+ } | undefined;
21
21
  }
22
22
  interface Path {
23
23
  get?: {
24
- tags?: string[];
25
- operationId?: string;
26
- description?: string;
24
+ tags?: string[] | undefined;
25
+ operationId?: string | undefined;
26
+ description?: string | undefined;
27
27
  security?: [{
28
28
  bearerAuth: string[];
29
- }];
30
- parameters?: OpenAPIParameter[];
29
+ }] | undefined;
30
+ parameters?: OpenAPIParameter[] | undefined;
31
31
  responses?: { [key in string]: {
32
- description?: string;
32
+ description?: string | undefined;
33
33
  content: {
34
34
  "application/json": {
35
35
  schema: {
36
- type?: OpenAPISchemaType;
37
- properties?: Record<string, any>;
38
- required?: string[];
39
- $ref?: string;
36
+ type?: OpenAPISchemaType | undefined;
37
+ properties?: Record<string, any> | undefined;
38
+ required?: string[] | undefined;
39
+ $ref?: string | undefined;
40
40
  };
41
41
  };
42
42
  };
43
- }; };
44
- };
43
+ }; } | undefined;
44
+ } | undefined;
45
45
  post?: {
46
- tags?: string[];
47
- operationId?: string;
48
- description?: string;
46
+ tags?: string[] | undefined;
47
+ operationId?: string | undefined;
48
+ description?: string | undefined;
49
49
  security?: [{
50
50
  bearerAuth: string[];
51
- }];
52
- parameters?: OpenAPIParameter[];
51
+ }] | undefined;
52
+ parameters?: OpenAPIParameter[] | undefined;
53
53
  requestBody?: {
54
54
  content: {
55
55
  "application/json": {
56
56
  schema: {
57
- type?: OpenAPISchemaType;
58
- properties?: Record<string, any>;
59
- required?: string[];
60
- $ref?: string;
57
+ type?: OpenAPISchemaType | undefined;
58
+ properties?: Record<string, any> | undefined;
59
+ required?: string[] | undefined;
60
+ $ref?: string | undefined;
61
61
  };
62
62
  };
63
63
  };
64
- };
64
+ } | undefined;
65
65
  responses?: { [key in string]: {
66
- description?: string;
66
+ description?: string | undefined;
67
67
  content: {
68
68
  "application/json": {
69
69
  schema: {
70
- type?: OpenAPISchemaType;
71
- properties?: Record<string, any>;
72
- required?: string[];
73
- $ref?: string;
70
+ type?: OpenAPISchemaType | undefined;
71
+ properties?: Record<string, any> | undefined;
72
+ required?: string[] | undefined;
73
+ $ref?: string | undefined;
74
74
  };
75
75
  };
76
76
  };
77
- }; };
78
- };
77
+ }; } | undefined;
78
+ } | undefined;
79
79
  }
80
80
  declare function generator(endpoints: Record<string, Endpoint>, config?: {
81
81
  url: string;
@@ -3,79 +3,79 @@ import { Endpoint } from "./endpoint.mjs";
3
3
  type OpenAPISchemaType = "string" | "number" | "integer" | "boolean" | "array" | "object";
4
4
  interface OpenAPIParameter {
5
5
  in: "query" | "path" | "header" | "cookie";
6
- name?: string;
7
- description?: string;
8
- required?: boolean;
6
+ name?: string | undefined;
7
+ description?: string | undefined;
8
+ required?: boolean | undefined;
9
9
  schema?: {
10
10
  type: OpenAPISchemaType;
11
11
  format?: string | undefined;
12
12
  items?: {
13
13
  type: OpenAPISchemaType;
14
- };
15
- enum?: string[];
16
- minLength?: number;
14
+ } | undefined;
15
+ enum?: string[] | undefined;
16
+ minLength?: number | undefined;
17
17
  description?: string | undefined;
18
18
  default?: string | undefined;
19
19
  example?: string | undefined;
20
- };
20
+ } | undefined;
21
21
  }
22
22
  interface Path {
23
23
  get?: {
24
- tags?: string[];
25
- operationId?: string;
26
- description?: string;
24
+ tags?: string[] | undefined;
25
+ operationId?: string | undefined;
26
+ description?: string | undefined;
27
27
  security?: [{
28
28
  bearerAuth: string[];
29
- }];
30
- parameters?: OpenAPIParameter[];
29
+ }] | undefined;
30
+ parameters?: OpenAPIParameter[] | undefined;
31
31
  responses?: { [key in string]: {
32
- description?: string;
32
+ description?: string | undefined;
33
33
  content: {
34
34
  "application/json": {
35
35
  schema: {
36
- type?: OpenAPISchemaType;
37
- properties?: Record<string, any>;
38
- required?: string[];
39
- $ref?: string;
36
+ type?: OpenAPISchemaType | undefined;
37
+ properties?: Record<string, any> | undefined;
38
+ required?: string[] | undefined;
39
+ $ref?: string | undefined;
40
40
  };
41
41
  };
42
42
  };
43
- }; };
44
- };
43
+ }; } | undefined;
44
+ } | undefined;
45
45
  post?: {
46
- tags?: string[];
47
- operationId?: string;
48
- description?: string;
46
+ tags?: string[] | undefined;
47
+ operationId?: string | undefined;
48
+ description?: string | undefined;
49
49
  security?: [{
50
50
  bearerAuth: string[];
51
- }];
52
- parameters?: OpenAPIParameter[];
51
+ }] | undefined;
52
+ parameters?: OpenAPIParameter[] | undefined;
53
53
  requestBody?: {
54
54
  content: {
55
55
  "application/json": {
56
56
  schema: {
57
- type?: OpenAPISchemaType;
58
- properties?: Record<string, any>;
59
- required?: string[];
60
- $ref?: string;
57
+ type?: OpenAPISchemaType | undefined;
58
+ properties?: Record<string, any> | undefined;
59
+ required?: string[] | undefined;
60
+ $ref?: string | undefined;
61
61
  };
62
62
  };
63
63
  };
64
- };
64
+ } | undefined;
65
65
  responses?: { [key in string]: {
66
- description?: string;
66
+ description?: string | undefined;
67
67
  content: {
68
68
  "application/json": {
69
69
  schema: {
70
- type?: OpenAPISchemaType;
71
- properties?: Record<string, any>;
72
- required?: string[];
73
- $ref?: string;
70
+ type?: OpenAPISchemaType | undefined;
71
+ properties?: Record<string, any> | undefined;
72
+ required?: string[] | undefined;
73
+ $ref?: string | undefined;
74
74
  };
75
75
  };
76
76
  };
77
- }; };
78
- };
77
+ }; } | undefined;
78
+ } | undefined;
79
79
  }
80
80
  declare function generator(endpoints: Record<string, Endpoint>, config?: {
81
81
  url: string;
@@ -1 +1 @@
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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"}
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 | undefined;\n\tdescription?: string | undefined;\n\trequired?: boolean | undefined;\n\tschema?:\n\t\t| {\n\t\t\t\ttype: OpenAPISchemaType;\n\t\t\t\tformat?: string | undefined;\n\t\t\t\titems?:\n\t\t\t\t\t| {\n\t\t\t\t\t\t\ttype: OpenAPISchemaType;\n\t\t\t\t\t }\n\t\t\t\t\t| undefined;\n\t\t\t\tenum?: string[] | undefined;\n\t\t\t\tminLength?: number | undefined;\n\t\t\t\tdescription?: string | undefined;\n\t\t\t\tdefault?: string | undefined;\n\t\t\t\texample?: string | undefined;\n\t\t }\n\t\t| undefined;\n}\n\nexport interface Path {\n\tget?:\n\t\t| {\n\t\t\t\ttags?: string[] | undefined;\n\t\t\t\toperationId?: string | undefined;\n\t\t\t\tdescription?: string | undefined;\n\t\t\t\tsecurity?: [{ bearerAuth: string[] }] | undefined;\n\t\t\t\tparameters?: OpenAPIParameter[] | undefined;\n\t\t\t\tresponses?:\n\t\t\t\t\t| {\n\t\t\t\t\t\t\t[key in string]: {\n\t\t\t\t\t\t\t\tdescription?: string | undefined;\n\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\ttype?: OpenAPISchemaType | undefined;\n\t\t\t\t\t\t\t\t\t\t\tproperties?: Record<string, any> | undefined;\n\t\t\t\t\t\t\t\t\t\t\trequired?: string[] | undefined;\n\t\t\t\t\t\t\t\t\t\t\t$ref?: string | undefined;\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\t }\n\t\t\t\t\t| undefined;\n\t\t }\n\t\t| undefined;\n\tpost?:\n\t\t| {\n\t\t\t\ttags?: string[] | undefined;\n\t\t\t\toperationId?: string | undefined;\n\t\t\t\tdescription?: string | undefined;\n\t\t\t\tsecurity?: [{ bearerAuth: string[] }] | undefined;\n\t\t\t\tparameters?: OpenAPIParameter[] | undefined;\n\t\t\t\trequestBody?:\n\t\t\t\t\t| {\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype?: OpenAPISchemaType | undefined;\n\t\t\t\t\t\t\t\t\t\tproperties?: Record<string, any> | undefined;\n\t\t\t\t\t\t\t\t\t\trequired?: string[] | undefined;\n\t\t\t\t\t\t\t\t\t\t$ref?: string | undefined;\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\t }\n\t\t\t\t\t| undefined;\n\t\t\t\tresponses?:\n\t\t\t\t\t| {\n\t\t\t\t\t\t\t[key in string]: {\n\t\t\t\t\t\t\t\tdescription?: string | undefined;\n\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\ttype?: OpenAPISchemaType | undefined;\n\t\t\t\t\t\t\t\t\t\t\tproperties?: Record<string, any> | undefined;\n\t\t\t\t\t\t\t\t\t\t\trequired?: string[] | undefined;\n\t\t\t\t\t\t\t\t\t\t\t$ref?: string | undefined;\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\t }\n\t\t\t\t\t| undefined;\n\t\t }\n\t\t| undefined;\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":";;AAuGA,MAAM,QAA8B,CAAC;AAErC,SAAS,mBAAmB,SAAuB;CAClD,QAAQ,QAAQ,YAAY,MAA5B;EACC,KAAK,aACJ,OAAO;EACR,KAAK,aACJ,OAAO;EACR,KAAK,cACJ,OAAO;EACR,KAAK,aACJ,OAAO;EACR,KAAK,YACJ,OAAO;EACR,SACC,OAAO;CACT;AACD;AAEA,SAAS,cAAc,SAA0B;CAChD,MAAM,aAAiC,CAAC;CACxC,IAAI,QAAQ,UAAU,SAAS,YAAY;EAC1C,WAAW,KAAK,GAAG,QAAQ,SAAS,QAAQ,UAAU;EACtD,OAAO;CACR;CACA,IAAI,QAAQ,iBAAiB,WAC5B,OAAO,QAAQ,QAAQ,MAAM,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,WAAW;EAC7D,IAAI,iBAAiB,WACpB,WAAW,KAAK;GACf,MAAM;GACN,IAAI;GACJ,QAAQ;IACP,MAAM,mBAAmB,KAAK;IAC9B,GAAI,eAAe,SAAS,MAAM,YAC/B,EACA,WAAW,MAAM,UAClB,IACC,CAAC;IACJ,aAAa,MAAM;GACpB;EACD,CAAC;CAEH,CAAC;CAEF,OAAO;AACR;AAEA,SAAS,eAAe,SAA+B;CACtD,IAAI,QAAQ,UAAU,SAAS,aAC9B,OAAO,QAAQ,SAAS,QAAQ;CAEjC,IAAI,CAAC,QAAQ,MAAM,OAAO,KAAA;CAC1B,IACC,QAAQ,gBAAgB,aACxB,QAAQ,gBAAgB,aACvB;EAED,MAAM,QAAQ,QAAQ,KAAK;EAC3B,IAAI,CAAC,OAAO,OAAO,KAAA;EACnB,MAAM,aAAkC,CAAC;EACzC,MAAM,WAAqB,CAAC;EAC5B,OAAO,QAAQ,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,WAAW;GAC/C,IAAI,iBAAiB,WAAW;IAC/B,WAAW,OAAO;KACjB,MAAM,mBAAmB,KAAK;KAC9B,aAAa,MAAM;IACpB;IACA,IAAI,EAAE,iBAAiB,cACtB,SAAS,KAAK,GAAG;GAEnB;EACD,CAAC;EACD,OAAO;GACN,UACC,QAAQ,gBAAgB,cACrB,QACA,QAAQ,OACP,OACA;GACL,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN;IACA;GACD,EACD,EACD;EACD;CACD;AAED;AAEA,SAAS,YAAY,WAAiC;CACrD,OAAO;EACN,OAAO;GACN,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY,EACX,SAAS,EACR,MAAM,SACP,EACD;IACA,UAAU,CAAC,SAAS;GACrB,EACD,EACD;GACA,aACC;EACF;EACA,OAAO;GACN,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY,EACX,SAAS,EACR,MAAM,SACP,EACD;IACA,UAAU,CAAC,SAAS;GACrB,EACD,EACD;GACA,aAAa;EACd;EACA,OAAO;GACN,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY,EACX,SAAS,EACR,MAAM,SACP,EACD;GACD,EACD,EACD;GACA,aACC;EACF;EACA,OAAO;GACN,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY,EACX,SAAS,EACR,MAAM,SACP,EACD;GACD,EACD,EACD;GACA,aAAa;EACd;EACA,OAAO;GACN,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY,EACX,SAAS,EACR,MAAM,SACP,EACD;GACD,EACD,EACD;GACA,aACC;EACF;EACA,OAAO;GACN,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY,EACX,SAAS,EACR,MAAM,SACP,EACD;GACD,EACD,EACD;GACA,aACC;EACF;EACA,GAAG;CACJ;AACD;AAEA,eAAsB,UACrB,WACA,QAGC;CACD,MAAM,aAAa,EAClB,SAAS,CAAC,EACX;CAEA,OAAO,QAAQ,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,WAAW;EACjD,MAAM,UAAU,MAAM;EACtB,IAAI,CAAC,MAAM,QAAQ,QAAQ,UAAU,aAAa;EAClD,IAAI,QAAQ,WAAW,OACtB,MAAM,MAAM,QAAQ,EACnB,KAAK;GACJ,MAAM,CAAC,WAAW,GAAI,QAAQ,UAAU,SAAS,QAAQ,CAAC,CAAE;GAC5D,aAAa,QAAQ,UAAU,SAAS;GACxC,aAAa,QAAQ,UAAU,SAAS;GACxC,UAAU,CACT,EACC,YAAY,CAAC,EACd,CACD;GACA,YAAY,cAAc,OAAO;GACjC,WAAW,YAAY,QAAQ,UAAU,SAAS,SAAS;EAC5D,EACD;EAGD,IAAI,QAAQ,WAAW,QAAQ;GAC9B,MAAM,OAAO,eAAe,OAAO;GACnC,MAAM,MAAM,QAAQ,EACnB,MAAM;IACL,MAAM,CAAC,WAAW,GAAI,QAAQ,UAAU,SAAS,QAAQ,CAAC,CAAE;IAC5D,aAAa,QAAQ,UAAU,SAAS;IACxC,aAAa,QAAQ,UAAU,SAAS;IACxC,UAAU,CACT,EACC,YAAY,CAAC,EACd,CACD;IACA,YAAY,cAAc,OAAO;IACjC,GAAI,OACD,EAAE,aAAa,KAAK,IACpB,EACA,aAAa,EAEZ,SAAS,EACR,oBAAoB,EACnB,QAAQ;KACP,MAAM;KACN,YAAY,CAAC;IACd,EACD,EACD,EACD,EACD;IACF,WAAW,YAAY,QAAQ,UAAU,SAAS,SAAS;GAC5D,EACD;EACD;CACD,CAAC;CA6BD,OAAO;EA1BN,SAAS;EACT,MAAM;GACL,OAAO;GACP,aAAa;GACb,SAAS;EACV;EACA;EACA,UAAU,CACT,EACC,cAAc,CAAC,EAChB,CACD;EACA,SAAS,CACR,EACC,KAAK,QAAQ,IACd,CACD;EACA,MAAM,CACL;GACC,MAAM;GACN,aACC;EACF,CACD;EACA;CAEQ;AACV;AAEA,MAAa,WACZ,cACA,WAMI;;;;;;;;;;;;;MAaC,KAAK,UAAU,YAAY,EAAE;;;;eAIpB,QAAQ,OAAO,2BAA2B,mBAAmB,OAAO,IAAI,MAAM,KAAA,EAAU;cACzF,QAAQ,SAAS,SAAS;;YAE5B,QAAQ,SAAS,qBAAqB;kBAChC,QAAQ,eAAe,uBAAuB"}
@@ -115,11 +115,13 @@ function toResponse(data, init) {
115
115
  copyHeaders(headers, safeHeaders);
116
116
  }
117
117
  headers.set("Content-Type", "application/json");
118
+ const status = data.status ?? init?.status ?? routerResponse?.status;
119
+ const statusText = init?.statusText ?? routerResponse?.statusText;
118
120
  return new Response(JSON.stringify(body), {
119
121
  ...routerResponse,
120
122
  headers,
121
- status: data.status ?? init?.status ?? routerResponse?.status,
122
- statusText: init?.statusText ?? routerResponse?.statusText
123
+ ...status === void 0 ? {} : { status },
124
+ ...statusText === void 0 ? {} : { statusText }
123
125
  });
124
126
  }
125
127
  if (require_utils.isAPIError(data)) return toResponse(data.body, {
@@ -1 +1 @@
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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"}
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\tconst status = data.status ?? init?.status ?? routerResponse?.status;\n\t\tconst statusText = init?.statusText ?? routerResponse?.statusText;\n\t\treturn new Response(JSON.stringify(body), {\n\t\t\t...routerResponse,\n\t\t\theaders,\n\t\t\t...(status === undefined ? {} : { status }),\n\t\t\t...(statusText === undefined ? {} : { 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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"}
@@ -115,11 +115,13 @@ function toResponse(data, init) {
115
115
  copyHeaders(headers, safeHeaders);
116
116
  }
117
117
  headers.set("Content-Type", "application/json");
118
+ const status = data.status ?? init?.status ?? routerResponse?.status;
119
+ const statusText = init?.statusText ?? routerResponse?.statusText;
118
120
  return new Response(JSON.stringify(body), {
119
121
  ...routerResponse,
120
122
  headers,
121
- status: data.status ?? init?.status ?? routerResponse?.status,
122
- statusText: init?.statusText ?? routerResponse?.statusText
123
+ ...status === void 0 ? {} : { status },
124
+ ...statusText === void 0 ? {} : { statusText }
123
125
  });
124
126
  }
125
127
  if (isAPIError(data)) return toResponse(data.body, {
@@ -1 +1 @@
1
- {"version":3,"file":"to-response.mjs","names":[],"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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"}
1
+ {"version":3,"file":"to-response.mjs","names":[],"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\tconst status = data.status ?? init?.status ?? routerResponse?.status;\n\t\tconst statusText = init?.statusText ?? routerResponse?.statusText;\n\t\treturn new Response(JSON.stringify(body), {\n\t\t\t...routerResponse,\n\t\t\theaders,\n\t\t\t...(status === undefined ? {} : { status }),\n\t\t\t...(statusText === undefined ? {} : { 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-call",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",