better-call 1.1.7 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +2 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +4 -4
- package/dist/client.d.mts +4 -4
- package/dist/client.mjs +3 -3
- package/dist/client.mjs.map +1 -1
- package/dist/context.cjs +2 -1
- package/dist/context.cjs.map +1 -1
- package/dist/context.mjs +2 -1
- package/dist/context.mjs.map +1 -1
- package/dist/error.cjs +2 -0
- package/dist/error.cjs.map +1 -1
- package/dist/error.d.cts +2 -1
- package/dist/error.d.mts +2 -1
- package/dist/error.mjs +2 -1
- package/dist/error.mjs.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/middleware.cjs +19 -6
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.mjs +19 -6
- package/dist/middleware.mjs.map +1 -1
- package/dist/router.cjs +1 -1
- package/dist/router.cjs.map +1 -1
- package/dist/router.mjs +2 -2
- package/dist/router.mjs.map +1 -1
- package/dist/utils.cjs +9 -0
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.mjs +9 -1
- package/dist/utils.mjs.map +1 -1
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -4,7 +4,7 @@ let __better_fetch_fetch = require("@better-fetch/fetch");
|
|
|
4
4
|
|
|
5
5
|
//#region src/client.ts
|
|
6
6
|
const createClient = (options) => {
|
|
7
|
-
const fetch = (0, __better_fetch_fetch.createFetch)(options);
|
|
7
|
+
const fetch = (0, __better_fetch_fetch.createFetch)(options ?? {});
|
|
8
8
|
return async (path, ...options$1) => {
|
|
9
9
|
return await fetch(path, { ...options$1[0] });
|
|
10
10
|
};
|
|
@@ -16,6 +16,7 @@ exports.BetterCallError = require_error.BetterCallError;
|
|
|
16
16
|
exports.ValidationError = require_error.ValidationError;
|
|
17
17
|
exports.createClient = createClient;
|
|
18
18
|
exports.hideInternalStackFrames = require_error.hideInternalStackFrames;
|
|
19
|
+
exports.kAPIErrorHeaderSymbol = require_error.kAPIErrorHeaderSymbol;
|
|
19
20
|
exports.makeErrorForHideStackFrame = require_error.makeErrorForHideStackFrame;
|
|
20
21
|
exports.statusCodes = require_error.statusCodes;
|
|
21
22
|
//# sourceMappingURL=client.cjs.map
|
package/dist/client.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.cjs","names":["options"],"sources":["../src/client.ts"],"sourcesContent":["import { type BetterFetchOption, type BetterFetchResponse, createFetch } from \"@better-fetch/fetch\";\nimport type { Router } from \"./router\";\nimport type { HasRequiredKeys, Prettify, UnionToIntersection } from \"./helper\";\nimport type { Endpoint } from \"./endpoint\";\n\ntype HasRequired<\n\tT extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = T[\"body\"] extends object\n\t? HasRequiredKeys<T[\"body\"]> extends true\n\t\t? true\n\t\t: T[\"query\"] extends object\n\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t? true\n\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t: false\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t: T[\"query\"] extends object\n\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t? true\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t\t: T[\"params\"] extends object\n\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t: false;\n\ntype InferContext<T> = T extends (ctx: infer Ctx) => any\n\t? Ctx extends object\n\t\t? Ctx\n\t\t: never\n\t: never;\n\nexport interface ClientOptions extends BetterFetchOption {\n\tbaseURL
|
|
1
|
+
{"version":3,"file":"client.cjs","names":["options"],"sources":["../src/client.ts"],"sourcesContent":["import { type BetterFetchOption, type BetterFetchResponse, createFetch } from \"@better-fetch/fetch\";\nimport type { Router } from \"./router\";\nimport type { HasRequiredKeys, Prettify, UnionToIntersection } from \"./helper\";\nimport type { Endpoint } from \"./endpoint\";\n\ntype HasRequired<\n\tT extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = T[\"body\"] extends object\n\t? HasRequiredKeys<T[\"body\"]> extends true\n\t\t? true\n\t\t: T[\"query\"] extends object\n\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t? true\n\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t: false\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t: T[\"query\"] extends object\n\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t? true\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t\t: T[\"params\"] extends object\n\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t: false;\n\ntype InferContext<T> = T extends (ctx: infer Ctx) => any\n\t? Ctx extends object\n\t\t? Ctx\n\t\t: never\n\t: never;\n\nexport interface ClientOptions extends BetterFetchOption {\n\tbaseURL?: string;\n}\n\ntype WithRequired<T, K> = T & {\n\t[P in K extends string ? K : never]-?: T[P extends keyof T ? P : never];\n};\n\ntype InferClientRoutes<T extends Record<string, Endpoint>> = {\n\t[K in keyof T]: T[K] extends Endpoint<any, infer O>\n\t\t? O extends\n\t\t\t\t| { metadata: { scope: \"http\" } }\n\t\t\t\t| { metadata: { scope: \"server\" } }\n\t\t\t\t| { metadata: { SERVER_ONLY: true } }\n\t\t\t\t| { metadata: { isAction: false } }\n\t\t\t? never\n\t\t\t: T[K]\n\t\t: T[K];\n};\n\nexport type RequiredOptionKeys<\n\tC extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = (undefined extends C[\"body\"]\n\t? {}\n\t: {\n\t\t\tbody: true;\n\t\t}) &\n\t(undefined extends C[\"query\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tquery: true;\n\t\t\t}) &\n\t(undefined extends C[\"params\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tparams: true;\n\t\t\t});\n\nexport const createClient = <R extends Router | Router[\"endpoints\"]>(options?: ClientOptions) => {\n\tconst fetch = createFetch(options ?? {});\n\ttype API = InferClientRoutes<\n\t\tR extends { endpoints: Record<string, Endpoint> } ? R[\"endpoints\"] : R\n\t>;\n\ttype Options = API extends {\n\t\t[key: string]: infer T;\n\t}\n\t\t? T extends Endpoint\n\t\t\t? {\n\t\t\t\t\t[key in T[\"options\"][\"method\"] extends \"GET\"\n\t\t\t\t\t\t? T[\"path\"]\n\t\t\t\t\t\t: `@${T[\"options\"][\"method\"] extends string ? Lowercase<T[\"options\"][\"method\"]> : never}${T[\"path\"]}`]: T;\n\t\t\t\t}\n\t\t\t: {}\n\t\t: {};\n\n\ttype O = Prettify<UnionToIntersection<Options>>;\n\treturn async <OPT extends O, K extends keyof OPT, C extends InferContext<OPT[K]>>(\n\t\tpath: K,\n\t\t...options: HasRequired<C> extends true\n\t\t\t? [\n\t\t\t\t\tWithRequired<\n\t\t\t\t\t\tBetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t\t\t\t\t\tkeyof RequiredOptionKeys<C>\n\t\t\t\t\t>,\n\t\t\t\t]\n\t\t\t: [BetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>?]\n\t): Promise<\n\t\tBetterFetchResponse<Awaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>>\n\t> => {\n\t\treturn (await fetch(path as string, {\n\t\t\t...options[0],\n\t\t})) as any;\n\t};\n};\n\nexport * from \"./error\";\n"],"mappings":";;;;;AAiFA,MAAa,gBAAwD,YAA4B;CAChG,MAAM,8CAAoB,WAAW,EAAE,CAAC;AAiBxC,QAAO,OACN,MACA,GAAGA,cAUC;AACJ,SAAQ,MAAM,MAAM,MAAgB,EACnC,GAAGA,UAAQ,IACX,CAAC"}
|
package/dist/client.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HasRequiredKeys, UnionToIntersection } from "./helper.cjs";
|
|
2
|
-
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes } from "./error.cjs";
|
|
2
|
+
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes } from "./error.cjs";
|
|
3
3
|
import { Endpoint } from "./endpoint.cjs";
|
|
4
4
|
import { Router } from "./router.cjs";
|
|
5
5
|
import { BetterFetchOption, BetterFetchResponse } from "@better-fetch/fetch";
|
|
@@ -12,7 +12,7 @@ type HasRequired<T$1 extends {
|
|
|
12
12
|
}> = T$1["body"] extends object ? HasRequiredKeys<T$1["body"]> extends true ? true : T$1["query"] extends object ? HasRequiredKeys<T$1["query"]> extends true ? true : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["query"] extends object ? HasRequiredKeys<T$1["query"]> extends true ? true : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false;
|
|
13
13
|
type InferContext<T$1> = T$1 extends ((ctx: infer Ctx) => any) ? Ctx extends object ? Ctx : never : never;
|
|
14
14
|
interface ClientOptions extends BetterFetchOption {
|
|
15
|
-
baseURL
|
|
15
|
+
baseURL?: string;
|
|
16
16
|
}
|
|
17
17
|
type WithRequired<T$1, K$1> = T$1 & { [P in K$1 extends string ? K$1 : never]-?: T$1[P extends keyof T$1 ? P : never] };
|
|
18
18
|
type InferClientRoutes<T$1 extends Record<string, Endpoint>> = { [K in keyof T$1]: T$1[K] extends Endpoint<any, infer O> ? O extends {
|
|
@@ -43,11 +43,11 @@ type RequiredOptionKeys<C extends {
|
|
|
43
43
|
}) & (undefined extends C["params"] ? {} : {
|
|
44
44
|
params: true;
|
|
45
45
|
});
|
|
46
|
-
declare const createClient: <R extends Router | Router["endpoints"]>(options
|
|
46
|
+
declare const createClient: <R extends Router | Router["endpoints"]>(options?: ClientOptions) => <OPT extends (UnionToIntersection<InferClientRoutes<R extends {
|
|
47
47
|
endpoints: Record<string, Endpoint>;
|
|
48
48
|
} ? R["endpoints"] : R> extends {
|
|
49
49
|
[key: string]: infer T_1;
|
|
50
50
|
} ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1 } : {} : {}> extends infer T ? { [K_1 in keyof T]: T[K_1] } : never), K$1 extends keyof OPT, C extends InferContext<OPT[K$1]>>(path: K$1, ...options: HasRequired<C> extends true ? [WithRequired<BetterFetchOption<C["body"], C["query"], C["params"]>, keyof RequiredOptionKeys<C>>] : [BetterFetchOption<C["body"], C["query"], C["params"]>?]) => Promise<BetterFetchResponse<Awaited<ReturnType<OPT[K$1] extends Endpoint ? OPT[K$1] : never>>>>;
|
|
51
51
|
//#endregion
|
|
52
|
-
export { APIError, BetterCallError, ClientOptions, RequiredOptionKeys, Status, ValidationError, createClient, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes };
|
|
52
|
+
export { APIError, BetterCallError, ClientOptions, RequiredOptionKeys, Status, ValidationError, createClient, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes };
|
|
53
53
|
//# sourceMappingURL=client.d.cts.map
|
package/dist/client.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HasRequiredKeys, UnionToIntersection } from "./helper.mjs";
|
|
2
|
-
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
2
|
+
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
3
3
|
import { Endpoint } from "./endpoint.mjs";
|
|
4
4
|
import { Router } from "./router.mjs";
|
|
5
5
|
import { BetterFetchOption, BetterFetchResponse } from "@better-fetch/fetch";
|
|
@@ -12,7 +12,7 @@ type HasRequired<T$1 extends {
|
|
|
12
12
|
}> = T$1["body"] extends object ? HasRequiredKeys<T$1["body"]> extends true ? true : T$1["query"] extends object ? HasRequiredKeys<T$1["query"]> extends true ? true : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["query"] extends object ? HasRequiredKeys<T$1["query"]> extends true ? true : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false : T$1["params"] extends object ? HasRequiredKeys<T$1["params"]> : false;
|
|
13
13
|
type InferContext<T$1> = T$1 extends ((ctx: infer Ctx) => any) ? Ctx extends object ? Ctx : never : never;
|
|
14
14
|
interface ClientOptions extends BetterFetchOption {
|
|
15
|
-
baseURL
|
|
15
|
+
baseURL?: string;
|
|
16
16
|
}
|
|
17
17
|
type WithRequired<T$1, K$1> = T$1 & { [P in K$1 extends string ? K$1 : never]-?: T$1[P extends keyof T$1 ? P : never] };
|
|
18
18
|
type InferClientRoutes<T$1 extends Record<string, Endpoint>> = { [K in keyof T$1]: T$1[K] extends Endpoint<any, infer O> ? O extends {
|
|
@@ -43,11 +43,11 @@ type RequiredOptionKeys<C extends {
|
|
|
43
43
|
}) & (undefined extends C["params"] ? {} : {
|
|
44
44
|
params: true;
|
|
45
45
|
});
|
|
46
|
-
declare const createClient: <R extends Router | Router["endpoints"]>(options
|
|
46
|
+
declare const createClient: <R extends Router | Router["endpoints"]>(options?: ClientOptions) => <OPT extends (UnionToIntersection<InferClientRoutes<R extends {
|
|
47
47
|
endpoints: Record<string, Endpoint>;
|
|
48
48
|
} ? R["endpoints"] : R> extends {
|
|
49
49
|
[key: string]: infer T_1;
|
|
50
50
|
} ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1 } : {} : {}> extends infer T ? { [K_1 in keyof T]: T[K_1] } : never), K$1 extends keyof OPT, C extends InferContext<OPT[K$1]>>(path: K$1, ...options: HasRequired<C> extends true ? [WithRequired<BetterFetchOption<C["body"], C["query"], C["params"]>, keyof RequiredOptionKeys<C>>] : [BetterFetchOption<C["body"], C["query"], C["params"]>?]) => Promise<BetterFetchResponse<Awaited<ReturnType<OPT[K$1] extends Endpoint ? OPT[K$1] : never>>>>;
|
|
51
51
|
//#endregion
|
|
52
|
-
export { APIError, BetterCallError, ClientOptions, RequiredOptionKeys, Status, ValidationError, createClient, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes };
|
|
52
|
+
export { APIError, BetterCallError, ClientOptions, RequiredOptionKeys, Status, ValidationError, createClient, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes };
|
|
53
53
|
//# sourceMappingURL=client.d.mts.map
|
package/dist/client.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { APIError, BetterCallError, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
1
|
+
import { APIError, BetterCallError, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
2
2
|
import { createFetch } from "@better-fetch/fetch";
|
|
3
3
|
|
|
4
4
|
//#region src/client.ts
|
|
5
5
|
const createClient = (options) => {
|
|
6
|
-
const fetch = createFetch(options);
|
|
6
|
+
const fetch = createFetch(options ?? {});
|
|
7
7
|
return async (path, ...options$1) => {
|
|
8
8
|
return await fetch(path, { ...options$1[0] });
|
|
9
9
|
};
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
|
-
export { APIError, BetterCallError, ValidationError, createClient, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes };
|
|
13
|
+
export { APIError, BetterCallError, ValidationError, createClient, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes };
|
|
14
14
|
//# sourceMappingURL=client.mjs.map
|
package/dist/client.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.mjs","names":["options"],"sources":["../src/client.ts"],"sourcesContent":["import { type BetterFetchOption, type BetterFetchResponse, createFetch } from \"@better-fetch/fetch\";\nimport type { Router } from \"./router\";\nimport type { HasRequiredKeys, Prettify, UnionToIntersection } from \"./helper\";\nimport type { Endpoint } from \"./endpoint\";\n\ntype HasRequired<\n\tT extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = T[\"body\"] extends object\n\t? HasRequiredKeys<T[\"body\"]> extends true\n\t\t? true\n\t\t: T[\"query\"] extends object\n\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t? true\n\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t: false\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t: T[\"query\"] extends object\n\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t? true\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t\t: T[\"params\"] extends object\n\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t: false;\n\ntype InferContext<T> = T extends (ctx: infer Ctx) => any\n\t? Ctx extends object\n\t\t? Ctx\n\t\t: never\n\t: never;\n\nexport interface ClientOptions extends BetterFetchOption {\n\tbaseURL
|
|
1
|
+
{"version":3,"file":"client.mjs","names":["options"],"sources":["../src/client.ts"],"sourcesContent":["import { type BetterFetchOption, type BetterFetchResponse, createFetch } from \"@better-fetch/fetch\";\nimport type { Router } from \"./router\";\nimport type { HasRequiredKeys, Prettify, UnionToIntersection } from \"./helper\";\nimport type { Endpoint } from \"./endpoint\";\n\ntype HasRequired<\n\tT extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = T[\"body\"] extends object\n\t? HasRequiredKeys<T[\"body\"]> extends true\n\t\t? true\n\t\t: T[\"query\"] extends object\n\t\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t\t? true\n\t\t\t\t: T[\"params\"] extends object\n\t\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t\t: false\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t: T[\"query\"] extends object\n\t\t? HasRequiredKeys<T[\"query\"]> extends true\n\t\t\t? true\n\t\t\t: T[\"params\"] extends object\n\t\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t\t: false\n\t\t: T[\"params\"] extends object\n\t\t\t? HasRequiredKeys<T[\"params\"]>\n\t\t\t: false;\n\ntype InferContext<T> = T extends (ctx: infer Ctx) => any\n\t? Ctx extends object\n\t\t? Ctx\n\t\t: never\n\t: never;\n\nexport interface ClientOptions extends BetterFetchOption {\n\tbaseURL?: string;\n}\n\ntype WithRequired<T, K> = T & {\n\t[P in K extends string ? K : never]-?: T[P extends keyof T ? P : never];\n};\n\ntype InferClientRoutes<T extends Record<string, Endpoint>> = {\n\t[K in keyof T]: T[K] extends Endpoint<any, infer O>\n\t\t? O extends\n\t\t\t\t| { metadata: { scope: \"http\" } }\n\t\t\t\t| { metadata: { scope: \"server\" } }\n\t\t\t\t| { metadata: { SERVER_ONLY: true } }\n\t\t\t\t| { metadata: { isAction: false } }\n\t\t\t? never\n\t\t\t: T[K]\n\t\t: T[K];\n};\n\nexport type RequiredOptionKeys<\n\tC extends {\n\t\tbody?: any;\n\t\tquery?: any;\n\t\tparams?: any;\n\t},\n> = (undefined extends C[\"body\"]\n\t? {}\n\t: {\n\t\t\tbody: true;\n\t\t}) &\n\t(undefined extends C[\"query\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tquery: true;\n\t\t\t}) &\n\t(undefined extends C[\"params\"]\n\t\t? {}\n\t\t: {\n\t\t\t\tparams: true;\n\t\t\t});\n\nexport const createClient = <R extends Router | Router[\"endpoints\"]>(options?: ClientOptions) => {\n\tconst fetch = createFetch(options ?? {});\n\ttype API = InferClientRoutes<\n\t\tR extends { endpoints: Record<string, Endpoint> } ? R[\"endpoints\"] : R\n\t>;\n\ttype Options = API extends {\n\t\t[key: string]: infer T;\n\t}\n\t\t? T extends Endpoint\n\t\t\t? {\n\t\t\t\t\t[key in T[\"options\"][\"method\"] extends \"GET\"\n\t\t\t\t\t\t? T[\"path\"]\n\t\t\t\t\t\t: `@${T[\"options\"][\"method\"] extends string ? Lowercase<T[\"options\"][\"method\"]> : never}${T[\"path\"]}`]: T;\n\t\t\t\t}\n\t\t\t: {}\n\t\t: {};\n\n\ttype O = Prettify<UnionToIntersection<Options>>;\n\treturn async <OPT extends O, K extends keyof OPT, C extends InferContext<OPT[K]>>(\n\t\tpath: K,\n\t\t...options: HasRequired<C> extends true\n\t\t\t? [\n\t\t\t\t\tWithRequired<\n\t\t\t\t\t\tBetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>,\n\t\t\t\t\t\tkeyof RequiredOptionKeys<C>\n\t\t\t\t\t>,\n\t\t\t\t]\n\t\t\t: [BetterFetchOption<C[\"body\"], C[\"query\"], C[\"params\"]>?]\n\t): Promise<\n\t\tBetterFetchResponse<Awaited<ReturnType<OPT[K] extends Endpoint ? OPT[K] : never>>>\n\t> => {\n\t\treturn (await fetch(path as string, {\n\t\t\t...options[0],\n\t\t})) as any;\n\t};\n};\n\nexport * from \"./error\";\n"],"mappings":";;;;AAiFA,MAAa,gBAAwD,YAA4B;CAChG,MAAM,QAAQ,YAAY,WAAW,EAAE,CAAC;AAiBxC,QAAO,OACN,MACA,GAAGA,cAUC;AACJ,SAAQ,MAAM,MAAM,MAAgB,EACnC,GAAGA,UAAQ,IACX,CAAC"}
|
package/dist/context.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_error = require('./error.cjs');
|
|
2
|
+
const require_utils = require('./utils.cjs');
|
|
2
3
|
const require_validator = require('./validator.cjs');
|
|
3
4
|
const require_crypto = require('./crypto.cjs');
|
|
4
5
|
const require_cookies = require('./cookies.cjs');
|
|
@@ -9,7 +10,7 @@ const createInternalContext = async (context, { options, path }) => {
|
|
|
9
10
|
let responseStatus = void 0;
|
|
10
11
|
const { data, error } = await require_validator.runValidation(options, context);
|
|
11
12
|
if (error) throw new require_error.ValidationError(error.message, error.issues);
|
|
12
|
-
const requestHeaders = "headers" in context ? context.headers instanceof Headers ? context.headers : new Headers(context.headers) : "request" in context && context.request
|
|
13
|
+
const requestHeaders = "headers" in context ? context.headers instanceof Headers ? context.headers : new Headers(context.headers) : "request" in context && require_utils.isRequest(context.request) ? context.request.headers : null;
|
|
13
14
|
const requestCookies = requestHeaders?.get("cookie");
|
|
14
15
|
const parsedCookies = requestCookies ? require_cookies.parseCookies(requestCookies) : void 0;
|
|
15
16
|
const internalContext = {
|
package/dist/context.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.cjs","names":["responseStatus: Status | undefined","runValidation","ValidationError","requestHeaders: Headers | null","parseCookies","getCookieKey","verifySignature","getCryptoKey","serializeCookie","options","serializeSignedCookie","APIError","headers"],"sources":["../src/context.ts"],"sourcesContent":["import type { EndpointOptions } from \"./endpoint\";\nimport { type statusCodes, APIError, ValidationError, type Status } from \"./error\";\nimport type {\n\tInferParamPath,\n\tInferParamWildCard,\n\tIsEmptyObject,\n\tPrettify,\n\tUnionToIntersection,\n} from \"./helper\";\nimport type { Middleware, MiddlewareContext, MiddlewareOptions } from \"./middleware\";\nimport { runValidation } from \"./validator\";\nimport {\n\tgetCookieKey,\n\tparseCookies,\n\tserializeCookie,\n\tserializeSignedCookie,\n\ttype CookieOptions,\n\ttype CookiePrefixOptions,\n} from \"./cookies\";\nimport { getCryptoKey, verifySignature } from \"./crypto\";\nimport type { StandardSchemaV1 } from \"./standard-schema\";\n\nexport type HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\nexport type Method = HTTPMethod | \"*\";\n\nexport type InferBodyInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tBody = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer B;\n\t\t};\n\t}\n\t\t? B\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"body\"]>\n\t\t\t: undefined,\n> = undefined extends Body\n\t? {\n\t\t\tbody?: Body;\n\t\t}\n\t: {\n\t\t\tbody: Body;\n\t\t};\n\nexport type InferBody<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer Body;\n\t\t};\n\t}\n\t\t? Body\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"body\"]>\n\t\t\t: any;\n\nexport type InferQueryInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tQuery = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined,\n> = undefined extends Query\n\t? {\n\t\t\tquery?: Query;\n\t\t}\n\t: {\n\t\t\tquery: Query;\n\t\t};\n\nexport type InferQuery<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined;\n\nexport type InferMethod<Options extends EndpointOptions> = Options[\"method\"] extends Array<Method>\n\t? Options[\"method\"][number]\n\t: Options[\"method\"] extends \"*\"\n\t\t? HTTPMethod\n\t\t: Options[\"method\"];\n\nexport type InferInputMethod<\n\tOptions extends EndpointOptions,\n\tMethod = Options[\"method\"] extends Array<any>\n\t\t? Options[\"method\"][number] | undefined\n\t\t: Options[\"method\"] extends \"*\"\n\t\t\t? HTTPMethod\n\t\t\t: Options[\"method\"] | undefined,\n> = undefined extends Method\n\t? {\n\t\t\tmethod?: Method;\n\t\t}\n\t: {\n\t\t\tmethod: Method;\n\t\t};\n\nexport type InferParam<Path extends string> = [Path] extends [never]\n\t? Record<string, any> | undefined\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? Record<string, any> | undefined\n\t\t: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\nexport type InferParamInput<Path extends string> = [Path] extends [never]\n\t? { params?: Record<string, any> }\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? {\n\t\t\t\tparams?: Record<string, any>;\n\t\t\t}\n\t\t: {\n\t\t\t\tparams: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\t\t\t};\n\nexport type InferRequest<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true ? Request : Request | undefined;\n\nexport type InferRequestInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true\n\t\t? {\n\t\t\t\trequest: Request;\n\t\t\t}\n\t\t: {\n\t\t\t\trequest?: Request;\n\t\t\t};\n\nexport type InferHeaders<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true ? Headers : Headers | undefined;\n\nexport type InferHeadersInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true\n\t\t? {\n\t\t\t\theaders: HeadersInit;\n\t\t\t}\n\t\t: {\n\t\t\t\theaders?: HeadersInit;\n\t\t\t};\n\nexport type InferUse<Opts extends EndpointOptions[\"use\"]> = Opts extends Middleware[]\n\t? UnionToIntersection<Awaited<ReturnType<Opts[number]>>>\n\t: {};\n\nexport type InferMiddlewareBody<Options extends MiddlewareOptions> =\n\tOptions[\"body\"] extends StandardSchemaV1<infer T> ? T : any;\n\nexport type InferMiddlewareQuery<Options extends MiddlewareOptions> =\n\tOptions[\"query\"] extends StandardSchemaV1<infer T> ? T : Record<string, any> | undefined;\n\nexport type InputContext<\n\tPath extends string,\n\tOptions extends EndpointOptions,\n> = InferBodyInput<Options> &\n\tInferInputMethod<Options> &\n\tInferQueryInput<Options> &\n\tInferParamInput<Path> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\treturnStatus?: boolean;\n\t\tuse?: Middleware[];\n\t\tpath?: string;\n\t};\n\nexport const createInternalContext = async (\n\tcontext: InputContext<any, any>,\n\t{\n\t\toptions,\n\t\tpath,\n\t}: {\n\t\toptions: EndpointOptions;\n\t\tpath?: string;\n\t},\n) => {\n\tconst headers = new Headers();\n\tlet responseStatus: Status | undefined = undefined;\n\n\tconst { data, error } = await runValidation(options, context);\n\tif (error) {\n\t\tthrow new ValidationError(error.message, error.issues);\n\t}\n\tconst requestHeaders: Headers | null =\n\t\t\"headers\" in context\n\t\t\t? context.headers instanceof Headers\n\t\t\t\t? context.headers\n\t\t\t\t: new Headers(context.headers)\n\t\t\t: \"request\" in context && context.request instanceof Request\n\t\t\t\t? context.request.headers\n\t\t\t\t: null;\n\tconst requestCookies = requestHeaders?.get(\"cookie\");\n\tconst parsedCookies = requestCookies ? parseCookies(requestCookies) : undefined;\n\n\tconst internalContext = {\n\t\t...context,\n\t\tbody: data.body,\n\t\tquery: data.query,\n\t\tpath: context.path || path || \"virtual:\",\n\t\tcontext: \"context\" in context && context.context ? context.context : {},\n\t\treturned: undefined as any,\n\t\theaders: context?.headers,\n\t\trequest: context?.request,\n\t\tparams: \"params\" in context ? context.params : undefined,\n\t\tmethod:\n\t\t\tcontext.method ??\n\t\t\t(Array.isArray(options.method)\n\t\t\t\t? options.method[0]\n\t\t\t\t: options.method === \"*\"\n\t\t\t\t\t? \"GET\"\n\t\t\t\t\t: options.method),\n\t\tsetHeader: (key: string, value: string) => {\n\t\t\theaders.set(key, value);\n\t\t},\n\t\tgetHeader: (key: string) => {\n\t\t\tif (!requestHeaders) return null;\n\t\t\treturn requestHeaders.get(key);\n\t\t},\n\t\tgetCookie: (key: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn parsedCookies?.get(finalKey) || null;\n\t\t},\n\t\tgetSignedCookie: async (key: string, secret: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst value = parsedCookies?.get(finalKey);\n\t\t\tif (!value) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signatureStartPos = value.lastIndexOf(\".\");\n\t\t\tif (signatureStartPos < 1) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signedValue = value.substring(0, signatureStartPos);\n\t\t\tconst signature = value.substring(signatureStartPos + 1);\n\t\t\tif (signature.length !== 44 || !signature.endsWith(\"=\")) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst secretKey = await getCryptoKey(secret);\n\t\t\tconst isVerified = await verifySignature(signature, signedValue, secretKey);\n\t\t\treturn isVerified ? signedValue : false;\n\t\t},\n\t\tsetCookie: (key: string, value: string, options?: CookieOptions) => {\n\t\t\tconst cookie = serializeCookie(key, value, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tsetSignedCookie: async (\n\t\t\tkey: string,\n\t\t\tvalue: string,\n\t\t\tsecret: string,\n\t\t\toptions?: CookieOptions,\n\t\t) => {\n\t\t\tconst cookie = await serializeSignedCookie(key, value, secret, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tredirect: (url: string) => {\n\t\t\theaders.set(\"location\", url);\n\t\t\treturn new APIError(\"FOUND\", undefined, headers);\n\t\t},\n\t\terror: (\n\t\t\tstatus: keyof typeof statusCodes | Status,\n\t\t\tbody?:\n\t\t\t\t| {\n\t\t\t\t\t\tmessage?: string;\n\t\t\t\t\t\tcode?: string;\n\t\t\t\t }\n\t\t\t\t| undefined,\n\t\t\theaders?: HeadersInit,\n\t\t) => {\n\t\t\treturn new APIError(status, body, headers);\n\t\t},\n\t\tsetStatus: (status: Status) => {\n\t\t\tresponseStatus = status;\n\t\t},\n\t\tjson: (\n\t\t\tjson: Record<string, any>,\n\t\t\trouterResponse?:\n\t\t\t\t| {\n\t\t\t\t\t\tstatus?: number;\n\t\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\t\tresponse?: Response;\n\t\t\t\t\t\tbody?: Record<string, any>;\n\t\t\t\t }\n\t\t\t\t| Response,\n\t\t) => {\n\t\t\tif (!context.asResponse) {\n\t\t\t\treturn json;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbody: routerResponse?.body || json,\n\t\t\t\trouterResponse,\n\t\t\t\t_flag: \"json\",\n\t\t\t};\n\t\t},\n\t\tresponseHeaders: headers,\n\t\tget responseStatus() {\n\t\t\treturn responseStatus;\n\t\t},\n\t};\n\t//if context was shimmed through the input we want to apply it\n\tfor (const middleware of options.use || []) {\n\t\tconst response = (await middleware({\n\t\t\t...internalContext,\n\t\t\treturnHeaders: true,\n\t\t\tasResponse: false,\n\t\t})) as {\n\t\t\tresponse?: any;\n\t\t\theaders?: Headers;\n\t\t};\n\t\tif (response.response) {\n\t\t\tObject.assign(internalContext.context, response.response);\n\t\t}\n\t\t/**\n\t\t * Apply headers from the middleware to the endpoint headers\n\t\t */\n\t\tif (response.headers) {\n\t\t\tresponse.headers.forEach((value, key) => {\n\t\t\t\tinternalContext.responseHeaders.set(key, value);\n\t\t\t});\n\t\t}\n\t}\n\treturn internalContext;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"context.cjs","names":["responseStatus: Status | undefined","runValidation","ValidationError","requestHeaders: Headers | null","isRequest","parseCookies","getCookieKey","verifySignature","getCryptoKey","serializeCookie","options","serializeSignedCookie","APIError","headers"],"sources":["../src/context.ts"],"sourcesContent":["import type { EndpointOptions } from \"./endpoint\";\nimport { type statusCodes, APIError, ValidationError, type Status } from \"./error\";\nimport type {\n\tInferParamPath,\n\tInferParamWildCard,\n\tIsEmptyObject,\n\tPrettify,\n\tUnionToIntersection,\n} from \"./helper\";\nimport type { Middleware, MiddlewareContext, MiddlewareOptions } from \"./middleware\";\nimport { runValidation } from \"./validator\";\nimport {\n\tgetCookieKey,\n\tparseCookies,\n\tserializeCookie,\n\tserializeSignedCookie,\n\ttype CookieOptions,\n\ttype CookiePrefixOptions,\n} from \"./cookies\";\nimport { getCryptoKey, verifySignature } from \"./crypto\";\nimport type { StandardSchemaV1 } from \"./standard-schema\";\nimport { isRequest } from \"./utils\";\n\nexport type HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\nexport type Method = HTTPMethod | \"*\";\n\nexport type InferBodyInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tBody = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer B;\n\t\t};\n\t}\n\t\t? B\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"body\"]>\n\t\t\t: undefined,\n> = undefined extends Body\n\t? {\n\t\t\tbody?: Body;\n\t\t}\n\t: {\n\t\t\tbody: Body;\n\t\t};\n\nexport type InferBody<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer Body;\n\t\t};\n\t}\n\t\t? Body\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"body\"]>\n\t\t\t: any;\n\nexport type InferQueryInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tQuery = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined,\n> = undefined extends Query\n\t? {\n\t\t\tquery?: Query;\n\t\t}\n\t: {\n\t\t\tquery: Query;\n\t\t};\n\nexport type InferQuery<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined;\n\nexport type InferMethod<Options extends EndpointOptions> = Options[\"method\"] extends Array<Method>\n\t? Options[\"method\"][number]\n\t: Options[\"method\"] extends \"*\"\n\t\t? HTTPMethod\n\t\t: Options[\"method\"];\n\nexport type InferInputMethod<\n\tOptions extends EndpointOptions,\n\tMethod = Options[\"method\"] extends Array<any>\n\t\t? Options[\"method\"][number] | undefined\n\t\t: Options[\"method\"] extends \"*\"\n\t\t\t? HTTPMethod\n\t\t\t: Options[\"method\"] | undefined,\n> = undefined extends Method\n\t? {\n\t\t\tmethod?: Method;\n\t\t}\n\t: {\n\t\t\tmethod: Method;\n\t\t};\n\nexport type InferParam<Path extends string> = [Path] extends [never]\n\t? Record<string, any> | undefined\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? Record<string, any> | undefined\n\t\t: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\nexport type InferParamInput<Path extends string> = [Path] extends [never]\n\t? { params?: Record<string, any> }\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? {\n\t\t\t\tparams?: Record<string, any>;\n\t\t\t}\n\t\t: {\n\t\t\t\tparams: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\t\t\t};\n\nexport type InferRequest<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true ? Request : Request | undefined;\n\nexport type InferRequestInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true\n\t\t? {\n\t\t\t\trequest: Request;\n\t\t\t}\n\t\t: {\n\t\t\t\trequest?: Request;\n\t\t\t};\n\nexport type InferHeaders<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true ? Headers : Headers | undefined;\n\nexport type InferHeadersInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true\n\t\t? {\n\t\t\t\theaders: HeadersInit;\n\t\t\t}\n\t\t: {\n\t\t\t\theaders?: HeadersInit;\n\t\t\t};\n\nexport type InferUse<Opts extends EndpointOptions[\"use\"]> = Opts extends Middleware[]\n\t? UnionToIntersection<Awaited<ReturnType<Opts[number]>>>\n\t: {};\n\nexport type InferMiddlewareBody<Options extends MiddlewareOptions> =\n\tOptions[\"body\"] extends StandardSchemaV1<infer T> ? T : any;\n\nexport type InferMiddlewareQuery<Options extends MiddlewareOptions> =\n\tOptions[\"query\"] extends StandardSchemaV1<infer T> ? T : Record<string, any> | undefined;\n\nexport type InputContext<\n\tPath extends string,\n\tOptions extends EndpointOptions,\n> = InferBodyInput<Options> &\n\tInferInputMethod<Options> &\n\tInferQueryInput<Options> &\n\tInferParamInput<Path> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\treturnStatus?: boolean;\n\t\tuse?: Middleware[];\n\t\tpath?: string;\n\t};\n\nexport const createInternalContext = async (\n\tcontext: InputContext<any, any>,\n\t{\n\t\toptions,\n\t\tpath,\n\t}: {\n\t\toptions: EndpointOptions;\n\t\tpath?: string;\n\t},\n) => {\n\tconst headers = new Headers();\n\tlet responseStatus: Status | undefined = undefined;\n\n\tconst { data, error } = await runValidation(options, context);\n\tif (error) {\n\t\tthrow new ValidationError(error.message, error.issues);\n\t}\n\tconst requestHeaders: Headers | null =\n\t\t\"headers\" in context\n\t\t\t? context.headers instanceof Headers\n\t\t\t\t? context.headers\n\t\t\t\t: new Headers(context.headers)\n\t\t\t: \"request\" in context && isRequest(context.request)\n\t\t\t\t? context.request.headers\n\t\t\t\t: null;\n\tconst requestCookies = requestHeaders?.get(\"cookie\");\n\tconst parsedCookies = requestCookies ? parseCookies(requestCookies) : undefined;\n\n\tconst internalContext = {\n\t\t...context,\n\t\tbody: data.body,\n\t\tquery: data.query,\n\t\tpath: context.path || path || \"virtual:\",\n\t\tcontext: \"context\" in context && context.context ? context.context : {},\n\t\treturned: undefined as any,\n\t\theaders: context?.headers,\n\t\trequest: context?.request,\n\t\tparams: \"params\" in context ? context.params : undefined,\n\t\tmethod:\n\t\t\tcontext.method ??\n\t\t\t(Array.isArray(options.method)\n\t\t\t\t? options.method[0]\n\t\t\t\t: options.method === \"*\"\n\t\t\t\t\t? \"GET\"\n\t\t\t\t\t: options.method),\n\t\tsetHeader: (key: string, value: string) => {\n\t\t\theaders.set(key, value);\n\t\t},\n\t\tgetHeader: (key: string) => {\n\t\t\tif (!requestHeaders) return null;\n\t\t\treturn requestHeaders.get(key);\n\t\t},\n\t\tgetCookie: (key: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn parsedCookies?.get(finalKey) || null;\n\t\t},\n\t\tgetSignedCookie: async (key: string, secret: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst value = parsedCookies?.get(finalKey);\n\t\t\tif (!value) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signatureStartPos = value.lastIndexOf(\".\");\n\t\t\tif (signatureStartPos < 1) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signedValue = value.substring(0, signatureStartPos);\n\t\t\tconst signature = value.substring(signatureStartPos + 1);\n\t\t\tif (signature.length !== 44 || !signature.endsWith(\"=\")) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst secretKey = await getCryptoKey(secret);\n\t\t\tconst isVerified = await verifySignature(signature, signedValue, secretKey);\n\t\t\treturn isVerified ? signedValue : false;\n\t\t},\n\t\tsetCookie: (key: string, value: string, options?: CookieOptions) => {\n\t\t\tconst cookie = serializeCookie(key, value, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tsetSignedCookie: async (\n\t\t\tkey: string,\n\t\t\tvalue: string,\n\t\t\tsecret: string,\n\t\t\toptions?: CookieOptions,\n\t\t) => {\n\t\t\tconst cookie = await serializeSignedCookie(key, value, secret, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tredirect: (url: string) => {\n\t\t\theaders.set(\"location\", url);\n\t\t\treturn new APIError(\"FOUND\", undefined, headers);\n\t\t},\n\t\terror: (\n\t\t\tstatus: keyof typeof statusCodes | Status,\n\t\t\tbody?:\n\t\t\t\t| {\n\t\t\t\t\t\tmessage?: string;\n\t\t\t\t\t\tcode?: string;\n\t\t\t\t }\n\t\t\t\t| undefined,\n\t\t\theaders?: HeadersInit,\n\t\t) => {\n\t\t\treturn new APIError(status, body, headers);\n\t\t},\n\t\tsetStatus: (status: Status) => {\n\t\t\tresponseStatus = status;\n\t\t},\n\t\tjson: (\n\t\t\tjson: Record<string, any>,\n\t\t\trouterResponse?:\n\t\t\t\t| {\n\t\t\t\t\t\tstatus?: number;\n\t\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\t\tresponse?: Response;\n\t\t\t\t\t\tbody?: Record<string, any>;\n\t\t\t\t }\n\t\t\t\t| Response,\n\t\t) => {\n\t\t\tif (!context.asResponse) {\n\t\t\t\treturn json;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbody: routerResponse?.body || json,\n\t\t\t\trouterResponse,\n\t\t\t\t_flag: \"json\",\n\t\t\t};\n\t\t},\n\t\tresponseHeaders: headers,\n\t\tget responseStatus() {\n\t\t\treturn responseStatus;\n\t\t},\n\t};\n\t//if context was shimmed through the input we want to apply it\n\tfor (const middleware of options.use || []) {\n\t\tconst response = (await middleware({\n\t\t\t...internalContext,\n\t\t\treturnHeaders: true,\n\t\t\tasResponse: false,\n\t\t})) as {\n\t\t\tresponse?: any;\n\t\t\theaders?: Headers;\n\t\t};\n\t\tif (response.response) {\n\t\t\tObject.assign(internalContext.context, response.response);\n\t\t}\n\t\t/**\n\t\t * Apply headers from the middleware to the endpoint headers\n\t\t */\n\t\tif (response.headers) {\n\t\t\tresponse.headers.forEach((value, key) => {\n\t\t\t\tinternalContext.responseHeaders.set(key, value);\n\t\t\t});\n\t\t}\n\t}\n\treturn internalContext;\n};\n"],"mappings":"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"}
|
package/dist/context.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { APIError, ValidationError } from "./error.mjs";
|
|
2
|
+
import { isRequest } from "./utils.mjs";
|
|
2
3
|
import { runValidation } from "./validator.mjs";
|
|
3
4
|
import { getCryptoKey, verifySignature } from "./crypto.mjs";
|
|
4
5
|
import { getCookieKey, parseCookies, serializeCookie, serializeSignedCookie } from "./cookies.mjs";
|
|
@@ -9,7 +10,7 @@ const createInternalContext = async (context, { options, path }) => {
|
|
|
9
10
|
let responseStatus = void 0;
|
|
10
11
|
const { data, error } = await runValidation(options, context);
|
|
11
12
|
if (error) throw new ValidationError(error.message, error.issues);
|
|
12
|
-
const requestHeaders = "headers" in context ? context.headers instanceof Headers ? context.headers : new Headers(context.headers) : "request" in context && context.request
|
|
13
|
+
const requestHeaders = "headers" in context ? context.headers instanceof Headers ? context.headers : new Headers(context.headers) : "request" in context && isRequest(context.request) ? context.request.headers : null;
|
|
13
14
|
const requestCookies = requestHeaders?.get("cookie");
|
|
14
15
|
const parsedCookies = requestCookies ? parseCookies(requestCookies) : void 0;
|
|
15
16
|
const internalContext = {
|
package/dist/context.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.mjs","names":["responseStatus: Status | undefined","requestHeaders: Headers | null","options","headers"],"sources":["../src/context.ts"],"sourcesContent":["import type { EndpointOptions } from \"./endpoint\";\nimport { type statusCodes, APIError, ValidationError, type Status } from \"./error\";\nimport type {\n\tInferParamPath,\n\tInferParamWildCard,\n\tIsEmptyObject,\n\tPrettify,\n\tUnionToIntersection,\n} from \"./helper\";\nimport type { Middleware, MiddlewareContext, MiddlewareOptions } from \"./middleware\";\nimport { runValidation } from \"./validator\";\nimport {\n\tgetCookieKey,\n\tparseCookies,\n\tserializeCookie,\n\tserializeSignedCookie,\n\ttype CookieOptions,\n\ttype CookiePrefixOptions,\n} from \"./cookies\";\nimport { getCryptoKey, verifySignature } from \"./crypto\";\nimport type { StandardSchemaV1 } from \"./standard-schema\";\n\nexport type HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\nexport type Method = HTTPMethod | \"*\";\n\nexport type InferBodyInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tBody = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer B;\n\t\t};\n\t}\n\t\t? B\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"body\"]>\n\t\t\t: undefined,\n> = undefined extends Body\n\t? {\n\t\t\tbody?: Body;\n\t\t}\n\t: {\n\t\t\tbody: Body;\n\t\t};\n\nexport type InferBody<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer Body;\n\t\t};\n\t}\n\t\t? Body\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"body\"]>\n\t\t\t: any;\n\nexport type InferQueryInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tQuery = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined,\n> = undefined extends Query\n\t? {\n\t\t\tquery?: Query;\n\t\t}\n\t: {\n\t\t\tquery: Query;\n\t\t};\n\nexport type InferQuery<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined;\n\nexport type InferMethod<Options extends EndpointOptions> = Options[\"method\"] extends Array<Method>\n\t? Options[\"method\"][number]\n\t: Options[\"method\"] extends \"*\"\n\t\t? HTTPMethod\n\t\t: Options[\"method\"];\n\nexport type InferInputMethod<\n\tOptions extends EndpointOptions,\n\tMethod = Options[\"method\"] extends Array<any>\n\t\t? Options[\"method\"][number] | undefined\n\t\t: Options[\"method\"] extends \"*\"\n\t\t\t? HTTPMethod\n\t\t\t: Options[\"method\"] | undefined,\n> = undefined extends Method\n\t? {\n\t\t\tmethod?: Method;\n\t\t}\n\t: {\n\t\t\tmethod: Method;\n\t\t};\n\nexport type InferParam<Path extends string> = [Path] extends [never]\n\t? Record<string, any> | undefined\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? Record<string, any> | undefined\n\t\t: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\nexport type InferParamInput<Path extends string> = [Path] extends [never]\n\t? { params?: Record<string, any> }\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? {\n\t\t\t\tparams?: Record<string, any>;\n\t\t\t}\n\t\t: {\n\t\t\t\tparams: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\t\t\t};\n\nexport type InferRequest<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true ? Request : Request | undefined;\n\nexport type InferRequestInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true\n\t\t? {\n\t\t\t\trequest: Request;\n\t\t\t}\n\t\t: {\n\t\t\t\trequest?: Request;\n\t\t\t};\n\nexport type InferHeaders<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true ? Headers : Headers | undefined;\n\nexport type InferHeadersInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true\n\t\t? {\n\t\t\t\theaders: HeadersInit;\n\t\t\t}\n\t\t: {\n\t\t\t\theaders?: HeadersInit;\n\t\t\t};\n\nexport type InferUse<Opts extends EndpointOptions[\"use\"]> = Opts extends Middleware[]\n\t? UnionToIntersection<Awaited<ReturnType<Opts[number]>>>\n\t: {};\n\nexport type InferMiddlewareBody<Options extends MiddlewareOptions> =\n\tOptions[\"body\"] extends StandardSchemaV1<infer T> ? T : any;\n\nexport type InferMiddlewareQuery<Options extends MiddlewareOptions> =\n\tOptions[\"query\"] extends StandardSchemaV1<infer T> ? T : Record<string, any> | undefined;\n\nexport type InputContext<\n\tPath extends string,\n\tOptions extends EndpointOptions,\n> = InferBodyInput<Options> &\n\tInferInputMethod<Options> &\n\tInferQueryInput<Options> &\n\tInferParamInput<Path> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\treturnStatus?: boolean;\n\t\tuse?: Middleware[];\n\t\tpath?: string;\n\t};\n\nexport const createInternalContext = async (\n\tcontext: InputContext<any, any>,\n\t{\n\t\toptions,\n\t\tpath,\n\t}: {\n\t\toptions: EndpointOptions;\n\t\tpath?: string;\n\t},\n) => {\n\tconst headers = new Headers();\n\tlet responseStatus: Status | undefined = undefined;\n\n\tconst { data, error } = await runValidation(options, context);\n\tif (error) {\n\t\tthrow new ValidationError(error.message, error.issues);\n\t}\n\tconst requestHeaders: Headers | null =\n\t\t\"headers\" in context\n\t\t\t? context.headers instanceof Headers\n\t\t\t\t? context.headers\n\t\t\t\t: new Headers(context.headers)\n\t\t\t: \"request\" in context && context.request instanceof Request\n\t\t\t\t? context.request.headers\n\t\t\t\t: null;\n\tconst requestCookies = requestHeaders?.get(\"cookie\");\n\tconst parsedCookies = requestCookies ? parseCookies(requestCookies) : undefined;\n\n\tconst internalContext = {\n\t\t...context,\n\t\tbody: data.body,\n\t\tquery: data.query,\n\t\tpath: context.path || path || \"virtual:\",\n\t\tcontext: \"context\" in context && context.context ? context.context : {},\n\t\treturned: undefined as any,\n\t\theaders: context?.headers,\n\t\trequest: context?.request,\n\t\tparams: \"params\" in context ? context.params : undefined,\n\t\tmethod:\n\t\t\tcontext.method ??\n\t\t\t(Array.isArray(options.method)\n\t\t\t\t? options.method[0]\n\t\t\t\t: options.method === \"*\"\n\t\t\t\t\t? \"GET\"\n\t\t\t\t\t: options.method),\n\t\tsetHeader: (key: string, value: string) => {\n\t\t\theaders.set(key, value);\n\t\t},\n\t\tgetHeader: (key: string) => {\n\t\t\tif (!requestHeaders) return null;\n\t\t\treturn requestHeaders.get(key);\n\t\t},\n\t\tgetCookie: (key: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn parsedCookies?.get(finalKey) || null;\n\t\t},\n\t\tgetSignedCookie: async (key: string, secret: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst value = parsedCookies?.get(finalKey);\n\t\t\tif (!value) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signatureStartPos = value.lastIndexOf(\".\");\n\t\t\tif (signatureStartPos < 1) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signedValue = value.substring(0, signatureStartPos);\n\t\t\tconst signature = value.substring(signatureStartPos + 1);\n\t\t\tif (signature.length !== 44 || !signature.endsWith(\"=\")) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst secretKey = await getCryptoKey(secret);\n\t\t\tconst isVerified = await verifySignature(signature, signedValue, secretKey);\n\t\t\treturn isVerified ? signedValue : false;\n\t\t},\n\t\tsetCookie: (key: string, value: string, options?: CookieOptions) => {\n\t\t\tconst cookie = serializeCookie(key, value, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tsetSignedCookie: async (\n\t\t\tkey: string,\n\t\t\tvalue: string,\n\t\t\tsecret: string,\n\t\t\toptions?: CookieOptions,\n\t\t) => {\n\t\t\tconst cookie = await serializeSignedCookie(key, value, secret, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tredirect: (url: string) => {\n\t\t\theaders.set(\"location\", url);\n\t\t\treturn new APIError(\"FOUND\", undefined, headers);\n\t\t},\n\t\terror: (\n\t\t\tstatus: keyof typeof statusCodes | Status,\n\t\t\tbody?:\n\t\t\t\t| {\n\t\t\t\t\t\tmessage?: string;\n\t\t\t\t\t\tcode?: string;\n\t\t\t\t }\n\t\t\t\t| undefined,\n\t\t\theaders?: HeadersInit,\n\t\t) => {\n\t\t\treturn new APIError(status, body, headers);\n\t\t},\n\t\tsetStatus: (status: Status) => {\n\t\t\tresponseStatus = status;\n\t\t},\n\t\tjson: (\n\t\t\tjson: Record<string, any>,\n\t\t\trouterResponse?:\n\t\t\t\t| {\n\t\t\t\t\t\tstatus?: number;\n\t\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\t\tresponse?: Response;\n\t\t\t\t\t\tbody?: Record<string, any>;\n\t\t\t\t }\n\t\t\t\t| Response,\n\t\t) => {\n\t\t\tif (!context.asResponse) {\n\t\t\t\treturn json;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbody: routerResponse?.body || json,\n\t\t\t\trouterResponse,\n\t\t\t\t_flag: \"json\",\n\t\t\t};\n\t\t},\n\t\tresponseHeaders: headers,\n\t\tget responseStatus() {\n\t\t\treturn responseStatus;\n\t\t},\n\t};\n\t//if context was shimmed through the input we want to apply it\n\tfor (const middleware of options.use || []) {\n\t\tconst response = (await middleware({\n\t\t\t...internalContext,\n\t\t\treturnHeaders: true,\n\t\t\tasResponse: false,\n\t\t})) as {\n\t\t\tresponse?: any;\n\t\t\theaders?: Headers;\n\t\t};\n\t\tif (response.response) {\n\t\t\tObject.assign(internalContext.context, response.response);\n\t\t}\n\t\t/**\n\t\t * Apply headers from the middleware to the endpoint headers\n\t\t */\n\t\tif (response.headers) {\n\t\t\tresponse.headers.forEach((value, key) => {\n\t\t\t\tinternalContext.responseHeaders.set(key, value);\n\t\t\t});\n\t\t}\n\t}\n\treturn internalContext;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"context.mjs","names":["responseStatus: Status | undefined","requestHeaders: Headers | null","options","headers"],"sources":["../src/context.ts"],"sourcesContent":["import type { EndpointOptions } from \"./endpoint\";\nimport { type statusCodes, APIError, ValidationError, type Status } from \"./error\";\nimport type {\n\tInferParamPath,\n\tInferParamWildCard,\n\tIsEmptyObject,\n\tPrettify,\n\tUnionToIntersection,\n} from \"./helper\";\nimport type { Middleware, MiddlewareContext, MiddlewareOptions } from \"./middleware\";\nimport { runValidation } from \"./validator\";\nimport {\n\tgetCookieKey,\n\tparseCookies,\n\tserializeCookie,\n\tserializeSignedCookie,\n\ttype CookieOptions,\n\ttype CookiePrefixOptions,\n} from \"./cookies\";\nimport { getCryptoKey, verifySignature } from \"./crypto\";\nimport type { StandardSchemaV1 } from \"./standard-schema\";\nimport { isRequest } from \"./utils\";\n\nexport type HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\nexport type Method = HTTPMethod | \"*\";\n\nexport type InferBodyInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tBody = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer B;\n\t\t};\n\t}\n\t\t? B\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"body\"]>\n\t\t\t: undefined,\n> = undefined extends Body\n\t? {\n\t\t\tbody?: Body;\n\t\t}\n\t: {\n\t\t\tbody: Body;\n\t\t};\n\nexport type InferBody<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tbody: infer Body;\n\t\t};\n\t}\n\t\t? Body\n\t\t: Options[\"body\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"body\"]>\n\t\t\t: any;\n\nexport type InferQueryInput<\n\tOptions extends EndpointOptions | MiddlewareOptions,\n\tQuery = Options[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferInput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined,\n> = undefined extends Query\n\t? {\n\t\t\tquery?: Query;\n\t\t}\n\t: {\n\t\t\tquery: Query;\n\t\t};\n\nexport type InferQuery<Options extends EndpointOptions | MiddlewareOptions> =\n\tOptions[\"metadata\"] extends {\n\t\t$Infer: {\n\t\t\tquery: infer Query;\n\t\t};\n\t}\n\t\t? Query\n\t\t: Options[\"query\"] extends StandardSchemaV1\n\t\t\t? StandardSchemaV1.InferOutput<Options[\"query\"]>\n\t\t\t: Record<string, any> | undefined;\n\nexport type InferMethod<Options extends EndpointOptions> = Options[\"method\"] extends Array<Method>\n\t? Options[\"method\"][number]\n\t: Options[\"method\"] extends \"*\"\n\t\t? HTTPMethod\n\t\t: Options[\"method\"];\n\nexport type InferInputMethod<\n\tOptions extends EndpointOptions,\n\tMethod = Options[\"method\"] extends Array<any>\n\t\t? Options[\"method\"][number] | undefined\n\t\t: Options[\"method\"] extends \"*\"\n\t\t\t? HTTPMethod\n\t\t\t: Options[\"method\"] | undefined,\n> = undefined extends Method\n\t? {\n\t\t\tmethod?: Method;\n\t\t}\n\t: {\n\t\t\tmethod: Method;\n\t\t};\n\nexport type InferParam<Path extends string> = [Path] extends [never]\n\t? Record<string, any> | undefined\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? Record<string, any> | undefined\n\t\t: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\nexport type InferParamInput<Path extends string> = [Path] extends [never]\n\t? { params?: Record<string, any> }\n\t: IsEmptyObject<InferParamPath<Path> & InferParamWildCard<Path>> extends true\n\t\t? {\n\t\t\t\tparams?: Record<string, any>;\n\t\t\t}\n\t\t: {\n\t\t\t\tparams: Prettify<InferParamPath<Path> & InferParamWildCard<Path>>;\n\t\t\t};\n\nexport type InferRequest<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true ? Request : Request | undefined;\n\nexport type InferRequestInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireRequest\"] extends true\n\t\t? {\n\t\t\t\trequest: Request;\n\t\t\t}\n\t\t: {\n\t\t\t\trequest?: Request;\n\t\t\t};\n\nexport type InferHeaders<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true ? Headers : Headers | undefined;\n\nexport type InferHeadersInput<Option extends EndpointOptions | MiddlewareOptions> =\n\tOption[\"requireHeaders\"] extends true\n\t\t? {\n\t\t\t\theaders: HeadersInit;\n\t\t\t}\n\t\t: {\n\t\t\t\theaders?: HeadersInit;\n\t\t\t};\n\nexport type InferUse<Opts extends EndpointOptions[\"use\"]> = Opts extends Middleware[]\n\t? UnionToIntersection<Awaited<ReturnType<Opts[number]>>>\n\t: {};\n\nexport type InferMiddlewareBody<Options extends MiddlewareOptions> =\n\tOptions[\"body\"] extends StandardSchemaV1<infer T> ? T : any;\n\nexport type InferMiddlewareQuery<Options extends MiddlewareOptions> =\n\tOptions[\"query\"] extends StandardSchemaV1<infer T> ? T : Record<string, any> | undefined;\n\nexport type InputContext<\n\tPath extends string,\n\tOptions extends EndpointOptions,\n> = InferBodyInput<Options> &\n\tInferInputMethod<Options> &\n\tInferQueryInput<Options> &\n\tInferParamInput<Path> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\treturnStatus?: boolean;\n\t\tuse?: Middleware[];\n\t\tpath?: string;\n\t};\n\nexport const createInternalContext = async (\n\tcontext: InputContext<any, any>,\n\t{\n\t\toptions,\n\t\tpath,\n\t}: {\n\t\toptions: EndpointOptions;\n\t\tpath?: string;\n\t},\n) => {\n\tconst headers = new Headers();\n\tlet responseStatus: Status | undefined = undefined;\n\n\tconst { data, error } = await runValidation(options, context);\n\tif (error) {\n\t\tthrow new ValidationError(error.message, error.issues);\n\t}\n\tconst requestHeaders: Headers | null =\n\t\t\"headers\" in context\n\t\t\t? context.headers instanceof Headers\n\t\t\t\t? context.headers\n\t\t\t\t: new Headers(context.headers)\n\t\t\t: \"request\" in context && isRequest(context.request)\n\t\t\t\t? context.request.headers\n\t\t\t\t: null;\n\tconst requestCookies = requestHeaders?.get(\"cookie\");\n\tconst parsedCookies = requestCookies ? parseCookies(requestCookies) : undefined;\n\n\tconst internalContext = {\n\t\t...context,\n\t\tbody: data.body,\n\t\tquery: data.query,\n\t\tpath: context.path || path || \"virtual:\",\n\t\tcontext: \"context\" in context && context.context ? context.context : {},\n\t\treturned: undefined as any,\n\t\theaders: context?.headers,\n\t\trequest: context?.request,\n\t\tparams: \"params\" in context ? context.params : undefined,\n\t\tmethod:\n\t\t\tcontext.method ??\n\t\t\t(Array.isArray(options.method)\n\t\t\t\t? options.method[0]\n\t\t\t\t: options.method === \"*\"\n\t\t\t\t\t? \"GET\"\n\t\t\t\t\t: options.method),\n\t\tsetHeader: (key: string, value: string) => {\n\t\t\theaders.set(key, value);\n\t\t},\n\t\tgetHeader: (key: string) => {\n\t\t\tif (!requestHeaders) return null;\n\t\t\treturn requestHeaders.get(key);\n\t\t},\n\t\tgetCookie: (key: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn parsedCookies?.get(finalKey) || null;\n\t\t},\n\t\tgetSignedCookie: async (key: string, secret: string, prefix?: CookiePrefixOptions) => {\n\t\t\tconst finalKey = getCookieKey(key, prefix);\n\t\t\tif (!finalKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst value = parsedCookies?.get(finalKey);\n\t\t\tif (!value) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signatureStartPos = value.lastIndexOf(\".\");\n\t\t\tif (signatureStartPos < 1) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst signedValue = value.substring(0, signatureStartPos);\n\t\t\tconst signature = value.substring(signatureStartPos + 1);\n\t\t\tif (signature.length !== 44 || !signature.endsWith(\"=\")) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst secretKey = await getCryptoKey(secret);\n\t\t\tconst isVerified = await verifySignature(signature, signedValue, secretKey);\n\t\t\treturn isVerified ? signedValue : false;\n\t\t},\n\t\tsetCookie: (key: string, value: string, options?: CookieOptions) => {\n\t\t\tconst cookie = serializeCookie(key, value, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tsetSignedCookie: async (\n\t\t\tkey: string,\n\t\t\tvalue: string,\n\t\t\tsecret: string,\n\t\t\toptions?: CookieOptions,\n\t\t) => {\n\t\t\tconst cookie = await serializeSignedCookie(key, value, secret, options);\n\t\t\theaders.append(\"set-cookie\", cookie);\n\t\t\treturn cookie;\n\t\t},\n\t\tredirect: (url: string) => {\n\t\t\theaders.set(\"location\", url);\n\t\t\treturn new APIError(\"FOUND\", undefined, headers);\n\t\t},\n\t\terror: (\n\t\t\tstatus: keyof typeof statusCodes | Status,\n\t\t\tbody?:\n\t\t\t\t| {\n\t\t\t\t\t\tmessage?: string;\n\t\t\t\t\t\tcode?: string;\n\t\t\t\t }\n\t\t\t\t| undefined,\n\t\t\theaders?: HeadersInit,\n\t\t) => {\n\t\t\treturn new APIError(status, body, headers);\n\t\t},\n\t\tsetStatus: (status: Status) => {\n\t\t\tresponseStatus = status;\n\t\t},\n\t\tjson: (\n\t\t\tjson: Record<string, any>,\n\t\t\trouterResponse?:\n\t\t\t\t| {\n\t\t\t\t\t\tstatus?: number;\n\t\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\t\tresponse?: Response;\n\t\t\t\t\t\tbody?: Record<string, any>;\n\t\t\t\t }\n\t\t\t\t| Response,\n\t\t) => {\n\t\t\tif (!context.asResponse) {\n\t\t\t\treturn json;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbody: routerResponse?.body || json,\n\t\t\t\trouterResponse,\n\t\t\t\t_flag: \"json\",\n\t\t\t};\n\t\t},\n\t\tresponseHeaders: headers,\n\t\tget responseStatus() {\n\t\t\treturn responseStatus;\n\t\t},\n\t};\n\t//if context was shimmed through the input we want to apply it\n\tfor (const middleware of options.use || []) {\n\t\tconst response = (await middleware({\n\t\t\t...internalContext,\n\t\t\treturnHeaders: true,\n\t\t\tasResponse: false,\n\t\t})) as {\n\t\t\tresponse?: any;\n\t\t\theaders?: Headers;\n\t\t};\n\t\tif (response.response) {\n\t\t\tObject.assign(internalContext.context, response.response);\n\t\t}\n\t\t/**\n\t\t * Apply headers from the middleware to the endpoint headers\n\t\t */\n\t\tif (response.headers) {\n\t\t\tresponse.headers.forEach((value, key) => {\n\t\t\t\tinternalContext.responseHeaders.set(key, value);\n\t\t\t});\n\t\t}\n\t}\n\treturn internalContext;\n};\n"],"mappings":"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"}
|
package/dist/error.cjs
CHANGED
|
@@ -129,6 +129,7 @@ var BetterCallError = class extends Error {
|
|
|
129
129
|
this.name = "BetterCallError";
|
|
130
130
|
}
|
|
131
131
|
};
|
|
132
|
+
const kAPIErrorHeaderSymbol = Symbol.for("better-call:api-error-headers");
|
|
132
133
|
const APIError = makeErrorForHideStackFrame(InternalAPIError, Error);
|
|
133
134
|
|
|
134
135
|
//#endregion
|
|
@@ -136,6 +137,7 @@ exports.APIError = APIError;
|
|
|
136
137
|
exports.BetterCallError = BetterCallError;
|
|
137
138
|
exports.ValidationError = ValidationError;
|
|
138
139
|
exports.hideInternalStackFrames = hideInternalStackFrames;
|
|
140
|
+
exports.kAPIErrorHeaderSymbol = kAPIErrorHeaderSymbol;
|
|
139
141
|
exports.makeErrorForHideStackFrame = makeErrorForHideStackFrame;
|
|
140
142
|
exports.statusCodes = statusCodes;
|
|
141
143
|
//# sourceMappingURL=error.cjs.map
|
package/dist/error.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.cjs","names":["#hiddenStack","status: keyof typeof statusCodes | Status","body:\n\t\t\t| ({\n\t\t\t\t\tmessage?: string;\n\t\t\t\t\tcode?: string;\n\t\t\t\t\tcause?: unknown;\n\t\t\t } & Record<string, any>)\n\t\t\t| undefined","headers: HeadersInit","message: string","issues: readonly StandardSchemaV1.Issue[]"],"sources":["../src/error.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"./standard-schema\";\n// https://github.com/nodejs/node/blob/360f7cc7867b43344aac00564286b895e15f21d7/lib/internal/errors.js#L246C1-L261C2\nfunction isErrorStackTraceLimitWritable() {\n\tconst desc = Object.getOwnPropertyDescriptor(Error, \"stackTraceLimit\");\n\tif (desc === undefined) {\n\t\treturn Object.isExtensible(Error);\n\t}\n\n\treturn Object.prototype.hasOwnProperty.call(desc, \"writable\")\n\t\t? desc.writable\n\t\t: desc.set !== undefined;\n}\n\n/**\n * Hide internal stack frames from the error stack trace.\n */\nexport function hideInternalStackFrames(stack: string): string {\n\tconst lines = stack.split(\"\\n at \");\n\tif (lines.length <= 1) {\n\t\treturn stack;\n\t}\n\tlines.splice(1, 1);\n\treturn lines.join(\"\\n at \");\n}\n\n// https://github.com/nodejs/node/blob/360f7cc7867b43344aac00564286b895e15f21d7/lib/internal/errors.js#L411-L432\n/**\n * Creates a custom error class that hides stack frames.\n */\nexport function makeErrorForHideStackFrame<B extends new (...args: any[]) => Error>(\n\tBase: B,\n\tclazz: any,\n): {\n\tnew (...args: ConstructorParameters<B>): InstanceType<B> & { errorStack: string | undefined };\n} {\n\tclass HideStackFramesError extends Base {\n\t\t#hiddenStack: string | undefined;\n\n\t\tconstructor(...args: any[]) {\n\t\t\tif (isErrorStackTraceLimitWritable()) {\n\t\t\t\tconst limit = Error.stackTraceLimit;\n\t\t\t\tError.stackTraceLimit = 0;\n\t\t\t\tsuper(...args);\n\t\t\t\tError.stackTraceLimit = limit;\n\t\t\t} else {\n\t\t\t\tsuper(...args);\n\t\t\t}\n\t\t\tconst stack = new Error().stack;\n\t\t\tif (stack) {\n\t\t\t\tthis.#hiddenStack = hideInternalStackFrames(stack.replace(/^Error/, this.name));\n\t\t\t}\n\t\t}\n\n\t\t// use `getter` here to avoid the stack trace being captured by loggers\n\t\tget errorStack() {\n\t\t\treturn this.#hiddenStack;\n\t\t}\n\t}\n\n\t// This is a workaround for wpt tests that expect that the error\n\t// constructor has a `name` property of the base class.\n\tObject.defineProperty(HideStackFramesError.prototype, \"constructor\", {\n\t\tget() {\n\t\t\treturn clazz;\n\t\t},\n\t\tenumerable: false,\n\t\tconfigurable: true,\n\t});\n\n\treturn HideStackFramesError as any;\n}\n\nexport const statusCodes = {\n\tOK: 200,\n\tCREATED: 201,\n\tACCEPTED: 202,\n\tNO_CONTENT: 204,\n\tMULTIPLE_CHOICES: 300,\n\tMOVED_PERMANENTLY: 301,\n\tFOUND: 302,\n\tSEE_OTHER: 303,\n\tNOT_MODIFIED: 304,\n\tTEMPORARY_REDIRECT: 307,\n\tBAD_REQUEST: 400,\n\tUNAUTHORIZED: 401,\n\tPAYMENT_REQUIRED: 402,\n\tFORBIDDEN: 403,\n\tNOT_FOUND: 404,\n\tMETHOD_NOT_ALLOWED: 405,\n\tNOT_ACCEPTABLE: 406,\n\tPROXY_AUTHENTICATION_REQUIRED: 407,\n\tREQUEST_TIMEOUT: 408,\n\tCONFLICT: 409,\n\tGONE: 410,\n\tLENGTH_REQUIRED: 411,\n\tPRECONDITION_FAILED: 412,\n\tPAYLOAD_TOO_LARGE: 413,\n\tURI_TOO_LONG: 414,\n\tUNSUPPORTED_MEDIA_TYPE: 415,\n\tRANGE_NOT_SATISFIABLE: 416,\n\tEXPECTATION_FAILED: 417,\n\t\"I'M_A_TEAPOT\": 418,\n\tMISDIRECTED_REQUEST: 421,\n\tUNPROCESSABLE_ENTITY: 422,\n\tLOCKED: 423,\n\tFAILED_DEPENDENCY: 424,\n\tTOO_EARLY: 425,\n\tUPGRADE_REQUIRED: 426,\n\tPRECONDITION_REQUIRED: 428,\n\tTOO_MANY_REQUESTS: 429,\n\tREQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n\tUNAVAILABLE_FOR_LEGAL_REASONS: 451,\n\tINTERNAL_SERVER_ERROR: 500,\n\tNOT_IMPLEMENTED: 501,\n\tBAD_GATEWAY: 502,\n\tSERVICE_UNAVAILABLE: 503,\n\tGATEWAY_TIMEOUT: 504,\n\tHTTP_VERSION_NOT_SUPPORTED: 505,\n\tVARIANT_ALSO_NEGOTIATES: 506,\n\tINSUFFICIENT_STORAGE: 507,\n\tLOOP_DETECTED: 508,\n\tNOT_EXTENDED: 510,\n\tNETWORK_AUTHENTICATION_REQUIRED: 511,\n};\n\nexport type Status =\n\t| 100\n\t| 101\n\t| 102\n\t| 103\n\t| 200\n\t| 201\n\t| 202\n\t| 203\n\t| 204\n\t| 205\n\t| 206\n\t| 207\n\t| 208\n\t| 226\n\t| 300\n\t| 301\n\t| 302\n\t| 303\n\t| 304\n\t| 305\n\t| 306\n\t| 307\n\t| 308\n\t| 400\n\t| 401\n\t| 402\n\t| 403\n\t| 404\n\t| 405\n\t| 406\n\t| 407\n\t| 408\n\t| 409\n\t| 410\n\t| 411\n\t| 412\n\t| 413\n\t| 414\n\t| 415\n\t| 416\n\t| 417\n\t| 418\n\t| 421\n\t| 422\n\t| 423\n\t| 424\n\t| 425\n\t| 426\n\t| 428\n\t| 429\n\t| 431\n\t| 451\n\t| 500\n\t| 501\n\t| 502\n\t| 503\n\t| 504\n\t| 505\n\t| 506\n\t| 507\n\t| 508\n\t| 510\n\t| 511;\n\nclass InternalAPIError extends Error {\n\tconstructor(\n\t\tpublic status: keyof typeof statusCodes | Status = \"INTERNAL_SERVER_ERROR\",\n\t\tpublic body:\n\t\t\t| ({\n\t\t\t\t\tmessage?: string;\n\t\t\t\t\tcode?: string;\n\t\t\t\t\tcause?: unknown;\n\t\t\t } & Record<string, any>)\n\t\t\t| undefined = undefined,\n\t\tpublic headers: HeadersInit = {},\n\t\tpublic statusCode = typeof status === \"number\" ? status : statusCodes[status],\n\t) {\n\t\tsuper(\n\t\t\tbody?.message,\n\t\t\tbody?.cause\n\t\t\t\t? {\n\t\t\t\t\t\tcause: body.cause,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t);\n\t\tthis.name = \"APIError\";\n\t\tthis.status = status;\n\t\tthis.headers = headers;\n\t\tthis.statusCode = statusCode;\n\t\tthis.body = body\n\t\t\t? {\n\t\t\t\t\tcode: body?.message\n\t\t\t\t\t\t?.toUpperCase()\n\t\t\t\t\t\t.replace(/ /g, \"_\")\n\t\t\t\t\t\t.replace(/[^A-Z0-9_]/g, \"\"),\n\t\t\t\t\t...body,\n\t\t\t\t}\n\t\t\t: undefined;\n\t}\n}\n\nexport class ValidationError extends InternalAPIError {\n\tconstructor(\n\t\tpublic message: string,\n\t\tpublic issues: readonly StandardSchemaV1.Issue[],\n\t) {\n\t\tsuper(400, {\n\t\t\tmessage: message,\n\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t});\n\n\t\tthis.issues = issues;\n\t}\n}\n\nexport class BetterCallError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"BetterCallError\";\n\t}\n}\n\nexport type APIError = InstanceType<typeof InternalAPIError>;\nexport const APIError = makeErrorForHideStackFrame(InternalAPIError, Error);\n"],"mappings":";;AAEA,SAAS,iCAAiC;CACzC,MAAM,OAAO,OAAO,yBAAyB,OAAO,kBAAkB;AACtE,KAAI,SAAS,OACZ,QAAO,OAAO,aAAa,MAAM;AAGlC,QAAO,OAAO,UAAU,eAAe,KAAK,MAAM,WAAW,GAC1D,KAAK,WACL,KAAK,QAAQ;;;;;AAMjB,SAAgB,wBAAwB,OAAuB;CAC9D,MAAM,QAAQ,MAAM,MAAM,YAAY;AACtC,KAAI,MAAM,UAAU,EACnB,QAAO;AAER,OAAM,OAAO,GAAG,EAAE;AAClB,QAAO,MAAM,KAAK,YAAY;;;;;AAO/B,SAAgB,2BACf,MACA,OAGC;CACD,MAAM,6BAA6B,KAAK;EACvC;EAEA,YAAY,GAAG,MAAa;AAC3B,OAAI,gCAAgC,EAAE;IACrC,MAAM,QAAQ,MAAM;AACpB,UAAM,kBAAkB;AACxB,UAAM,GAAG,KAAK;AACd,UAAM,kBAAkB;SAExB,OAAM,GAAG,KAAK;GAEf,MAAM,yBAAQ,IAAI,OAAO,EAAC;AAC1B,OAAI,MACH,OAAKA,cAAe,wBAAwB,MAAM,QAAQ,UAAU,KAAK,KAAK,CAAC;;EAKjF,IAAI,aAAa;AAChB,UAAO,MAAKA;;;AAMd,QAAO,eAAe,qBAAqB,WAAW,eAAe;EACpE,MAAM;AACL,UAAO;;EAER,YAAY;EACZ,cAAc;EACd,CAAC;AAEF,QAAO;;AAGR,MAAa,cAAc;CAC1B,IAAI;CACJ,SAAS;CACT,UAAU;CACV,YAAY;CACZ,kBAAkB;CAClB,mBAAmB;CACnB,OAAO;CACP,WAAW;CACX,cAAc;CACd,oBAAoB;CACpB,aAAa;CACb,cAAc;CACd,kBAAkB;CAClB,WAAW;CACX,WAAW;CACX,oBAAoB;CACpB,gBAAgB;CAChB,+BAA+B;CAC/B,iBAAiB;CACjB,UAAU;CACV,MAAM;CACN,iBAAiB;CACjB,qBAAqB;CACrB,mBAAmB;CACnB,cAAc;CACd,wBAAwB;CACxB,uBAAuB;CACvB,oBAAoB;CACpB,gBAAgB;CAChB,qBAAqB;CACrB,sBAAsB;CACtB,QAAQ;CACR,mBAAmB;CACnB,WAAW;CACX,kBAAkB;CAClB,uBAAuB;CACvB,mBAAmB;CACnB,iCAAiC;CACjC,+BAA+B;CAC/B,uBAAuB;CACvB,iBAAiB;CACjB,aAAa;CACb,qBAAqB;CACrB,iBAAiB;CACjB,4BAA4B;CAC5B,yBAAyB;CACzB,sBAAsB;CACtB,eAAe;CACf,cAAc;CACd,iCAAiC;CACjC;AAmED,IAAM,mBAAN,cAA+B,MAAM;CACpC,YACC,AAAOC,SAA4C,yBACnD,AAAOC,OAMQ,QACf,AAAOC,UAAuB,EAAE,EAChC,AAAO,aAAa,OAAO,WAAW,WAAW,SAAS,YAAY,SACrE;AACD,QACC,MAAM,SACN,MAAM,QACH,EACA,OAAO,KAAK,OACZ,GACA,OACH;EAlBM;EACA;EAOA;EACA;AAUP,OAAK,OAAO;AACZ,OAAK,SAAS;AACd,OAAK,UAAU;AACf,OAAK,aAAa;AAClB,OAAK,OAAO,OACT;GACA,MAAM,MAAM,SACT,aAAa,CACd,QAAQ,MAAM,IAAI,CAClB,QAAQ,eAAe,GAAG;GAC5B,GAAG;GACH,GACA;;;AAIL,IAAa,kBAAb,cAAqC,iBAAiB;CACrD,YACC,AAAOC,SACP,AAAOC,QACN;AACD,QAAM,KAAK;GACD;GACT,MAAM;GACN,CAAC;EANK;EACA;AAOP,OAAK,SAAS;;;AAIhB,IAAa,kBAAb,cAAqC,MAAM;CAC1C,YAAY,SAAiB;AAC5B,QAAM,QAAQ;AACd,OAAK,OAAO;;;
|
|
1
|
+
{"version":3,"file":"error.cjs","names":["#hiddenStack","status: keyof typeof statusCodes | Status","body:\n\t\t\t| ({\n\t\t\t\t\tmessage?: string;\n\t\t\t\t\tcode?: string;\n\t\t\t\t\tcause?: unknown;\n\t\t\t } & Record<string, any>)\n\t\t\t| undefined","headers: HeadersInit","message: string","issues: readonly StandardSchemaV1.Issue[]"],"sources":["../src/error.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"./standard-schema\";\n// https://github.com/nodejs/node/blob/360f7cc7867b43344aac00564286b895e15f21d7/lib/internal/errors.js#L246C1-L261C2\nfunction isErrorStackTraceLimitWritable() {\n\tconst desc = Object.getOwnPropertyDescriptor(Error, \"stackTraceLimit\");\n\tif (desc === undefined) {\n\t\treturn Object.isExtensible(Error);\n\t}\n\n\treturn Object.prototype.hasOwnProperty.call(desc, \"writable\")\n\t\t? desc.writable\n\t\t: desc.set !== undefined;\n}\n\n/**\n * Hide internal stack frames from the error stack trace.\n */\nexport function hideInternalStackFrames(stack: string): string {\n\tconst lines = stack.split(\"\\n at \");\n\tif (lines.length <= 1) {\n\t\treturn stack;\n\t}\n\tlines.splice(1, 1);\n\treturn lines.join(\"\\n at \");\n}\n\n// https://github.com/nodejs/node/blob/360f7cc7867b43344aac00564286b895e15f21d7/lib/internal/errors.js#L411-L432\n/**\n * Creates a custom error class that hides stack frames.\n */\nexport function makeErrorForHideStackFrame<B extends new (...args: any[]) => Error>(\n\tBase: B,\n\tclazz: any,\n): {\n\tnew (...args: ConstructorParameters<B>): InstanceType<B> & { errorStack: string | undefined };\n} {\n\tclass HideStackFramesError extends Base {\n\t\t#hiddenStack: string | undefined;\n\n\t\tconstructor(...args: any[]) {\n\t\t\tif (isErrorStackTraceLimitWritable()) {\n\t\t\t\tconst limit = Error.stackTraceLimit;\n\t\t\t\tError.stackTraceLimit = 0;\n\t\t\t\tsuper(...args);\n\t\t\t\tError.stackTraceLimit = limit;\n\t\t\t} else {\n\t\t\t\tsuper(...args);\n\t\t\t}\n\t\t\tconst stack = new Error().stack;\n\t\t\tif (stack) {\n\t\t\t\tthis.#hiddenStack = hideInternalStackFrames(stack.replace(/^Error/, this.name));\n\t\t\t}\n\t\t}\n\n\t\t// use `getter` here to avoid the stack trace being captured by loggers\n\t\tget errorStack() {\n\t\t\treturn this.#hiddenStack;\n\t\t}\n\t}\n\n\t// This is a workaround for wpt tests that expect that the error\n\t// constructor has a `name` property of the base class.\n\tObject.defineProperty(HideStackFramesError.prototype, \"constructor\", {\n\t\tget() {\n\t\t\treturn clazz;\n\t\t},\n\t\tenumerable: false,\n\t\tconfigurable: true,\n\t});\n\n\treturn HideStackFramesError as any;\n}\n\nexport const statusCodes = {\n\tOK: 200,\n\tCREATED: 201,\n\tACCEPTED: 202,\n\tNO_CONTENT: 204,\n\tMULTIPLE_CHOICES: 300,\n\tMOVED_PERMANENTLY: 301,\n\tFOUND: 302,\n\tSEE_OTHER: 303,\n\tNOT_MODIFIED: 304,\n\tTEMPORARY_REDIRECT: 307,\n\tBAD_REQUEST: 400,\n\tUNAUTHORIZED: 401,\n\tPAYMENT_REQUIRED: 402,\n\tFORBIDDEN: 403,\n\tNOT_FOUND: 404,\n\tMETHOD_NOT_ALLOWED: 405,\n\tNOT_ACCEPTABLE: 406,\n\tPROXY_AUTHENTICATION_REQUIRED: 407,\n\tREQUEST_TIMEOUT: 408,\n\tCONFLICT: 409,\n\tGONE: 410,\n\tLENGTH_REQUIRED: 411,\n\tPRECONDITION_FAILED: 412,\n\tPAYLOAD_TOO_LARGE: 413,\n\tURI_TOO_LONG: 414,\n\tUNSUPPORTED_MEDIA_TYPE: 415,\n\tRANGE_NOT_SATISFIABLE: 416,\n\tEXPECTATION_FAILED: 417,\n\t\"I'M_A_TEAPOT\": 418,\n\tMISDIRECTED_REQUEST: 421,\n\tUNPROCESSABLE_ENTITY: 422,\n\tLOCKED: 423,\n\tFAILED_DEPENDENCY: 424,\n\tTOO_EARLY: 425,\n\tUPGRADE_REQUIRED: 426,\n\tPRECONDITION_REQUIRED: 428,\n\tTOO_MANY_REQUESTS: 429,\n\tREQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n\tUNAVAILABLE_FOR_LEGAL_REASONS: 451,\n\tINTERNAL_SERVER_ERROR: 500,\n\tNOT_IMPLEMENTED: 501,\n\tBAD_GATEWAY: 502,\n\tSERVICE_UNAVAILABLE: 503,\n\tGATEWAY_TIMEOUT: 504,\n\tHTTP_VERSION_NOT_SUPPORTED: 505,\n\tVARIANT_ALSO_NEGOTIATES: 506,\n\tINSUFFICIENT_STORAGE: 507,\n\tLOOP_DETECTED: 508,\n\tNOT_EXTENDED: 510,\n\tNETWORK_AUTHENTICATION_REQUIRED: 511,\n};\n\nexport type Status =\n\t| 100\n\t| 101\n\t| 102\n\t| 103\n\t| 200\n\t| 201\n\t| 202\n\t| 203\n\t| 204\n\t| 205\n\t| 206\n\t| 207\n\t| 208\n\t| 226\n\t| 300\n\t| 301\n\t| 302\n\t| 303\n\t| 304\n\t| 305\n\t| 306\n\t| 307\n\t| 308\n\t| 400\n\t| 401\n\t| 402\n\t| 403\n\t| 404\n\t| 405\n\t| 406\n\t| 407\n\t| 408\n\t| 409\n\t| 410\n\t| 411\n\t| 412\n\t| 413\n\t| 414\n\t| 415\n\t| 416\n\t| 417\n\t| 418\n\t| 421\n\t| 422\n\t| 423\n\t| 424\n\t| 425\n\t| 426\n\t| 428\n\t| 429\n\t| 431\n\t| 451\n\t| 500\n\t| 501\n\t| 502\n\t| 503\n\t| 504\n\t| 505\n\t| 506\n\t| 507\n\t| 508\n\t| 510\n\t| 511;\n\nclass InternalAPIError extends Error {\n\tconstructor(\n\t\tpublic status: keyof typeof statusCodes | Status = \"INTERNAL_SERVER_ERROR\",\n\t\tpublic body:\n\t\t\t| ({\n\t\t\t\t\tmessage?: string;\n\t\t\t\t\tcode?: string;\n\t\t\t\t\tcause?: unknown;\n\t\t\t } & Record<string, any>)\n\t\t\t| undefined = undefined,\n\t\tpublic headers: HeadersInit = {},\n\t\tpublic statusCode = typeof status === \"number\" ? status : statusCodes[status],\n\t) {\n\t\tsuper(\n\t\t\tbody?.message,\n\t\t\tbody?.cause\n\t\t\t\t? {\n\t\t\t\t\t\tcause: body.cause,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t);\n\t\tthis.name = \"APIError\";\n\t\tthis.status = status;\n\t\tthis.headers = headers;\n\t\tthis.statusCode = statusCode;\n\t\tthis.body = body\n\t\t\t? {\n\t\t\t\t\tcode: body?.message\n\t\t\t\t\t\t?.toUpperCase()\n\t\t\t\t\t\t.replace(/ /g, \"_\")\n\t\t\t\t\t\t.replace(/[^A-Z0-9_]/g, \"\"),\n\t\t\t\t\t...body,\n\t\t\t\t}\n\t\t\t: undefined;\n\t}\n}\n\nexport class ValidationError extends InternalAPIError {\n\tconstructor(\n\t\tpublic message: string,\n\t\tpublic issues: readonly StandardSchemaV1.Issue[],\n\t) {\n\t\tsuper(400, {\n\t\t\tmessage: message,\n\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t});\n\n\t\tthis.issues = issues;\n\t}\n}\n\nexport class BetterCallError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"BetterCallError\";\n\t}\n}\n\nexport const kAPIErrorHeaderSymbol = Symbol.for(\"better-call:api-error-headers\");\n\nexport type APIError = InstanceType<typeof InternalAPIError>;\nexport const APIError = makeErrorForHideStackFrame(InternalAPIError, Error);\n"],"mappings":"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"}
|
package/dist/error.d.cts
CHANGED
|
@@ -90,6 +90,7 @@ declare class ValidationError extends InternalAPIError {
|
|
|
90
90
|
declare class BetterCallError extends Error {
|
|
91
91
|
constructor(message: string);
|
|
92
92
|
}
|
|
93
|
+
declare const kAPIErrorHeaderSymbol: unique symbol;
|
|
93
94
|
type APIError = InstanceType<typeof InternalAPIError>;
|
|
94
95
|
declare const APIError: new (status?: "OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED" | Status | undefined, body?: ({
|
|
95
96
|
message?: string;
|
|
@@ -99,5 +100,5 @@ declare const APIError: new (status?: "OK" | "CREATED" | "ACCEPTED" | "NO_CONTEN
|
|
|
99
100
|
errorStack: string | undefined;
|
|
100
101
|
};
|
|
101
102
|
//#endregion
|
|
102
|
-
export { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes };
|
|
103
|
+
export { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes };
|
|
103
104
|
//# sourceMappingURL=error.d.cts.map
|
package/dist/error.d.mts
CHANGED
|
@@ -90,6 +90,7 @@ declare class ValidationError extends InternalAPIError {
|
|
|
90
90
|
declare class BetterCallError extends Error {
|
|
91
91
|
constructor(message: string);
|
|
92
92
|
}
|
|
93
|
+
declare const kAPIErrorHeaderSymbol: unique symbol;
|
|
93
94
|
type APIError = InstanceType<typeof InternalAPIError>;
|
|
94
95
|
declare const APIError: new (status?: "OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED" | Status | undefined, body?: ({
|
|
95
96
|
message?: string;
|
|
@@ -99,5 +100,5 @@ declare const APIError: new (status?: "OK" | "CREATED" | "ACCEPTED" | "NO_CONTEN
|
|
|
99
100
|
errorStack: string | undefined;
|
|
100
101
|
};
|
|
101
102
|
//#endregion
|
|
102
|
-
export { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes };
|
|
103
|
+
export { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes };
|
|
103
104
|
//# sourceMappingURL=error.d.mts.map
|
package/dist/error.mjs
CHANGED
|
@@ -128,8 +128,9 @@ var BetterCallError = class extends Error {
|
|
|
128
128
|
this.name = "BetterCallError";
|
|
129
129
|
}
|
|
130
130
|
};
|
|
131
|
+
const kAPIErrorHeaderSymbol = Symbol.for("better-call:api-error-headers");
|
|
131
132
|
const APIError = makeErrorForHideStackFrame(InternalAPIError, Error);
|
|
132
133
|
|
|
133
134
|
//#endregion
|
|
134
|
-
export { APIError, BetterCallError, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes };
|
|
135
|
+
export { APIError, BetterCallError, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes };
|
|
135
136
|
//# sourceMappingURL=error.mjs.map
|
package/dist/error.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.mjs","names":["#hiddenStack","status: keyof typeof statusCodes | Status","body:\n\t\t\t| ({\n\t\t\t\t\tmessage?: string;\n\t\t\t\t\tcode?: string;\n\t\t\t\t\tcause?: unknown;\n\t\t\t } & Record<string, any>)\n\t\t\t| undefined","headers: HeadersInit","message: string","issues: readonly StandardSchemaV1.Issue[]"],"sources":["../src/error.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"./standard-schema\";\n// https://github.com/nodejs/node/blob/360f7cc7867b43344aac00564286b895e15f21d7/lib/internal/errors.js#L246C1-L261C2\nfunction isErrorStackTraceLimitWritable() {\n\tconst desc = Object.getOwnPropertyDescriptor(Error, \"stackTraceLimit\");\n\tif (desc === undefined) {\n\t\treturn Object.isExtensible(Error);\n\t}\n\n\treturn Object.prototype.hasOwnProperty.call(desc, \"writable\")\n\t\t? desc.writable\n\t\t: desc.set !== undefined;\n}\n\n/**\n * Hide internal stack frames from the error stack trace.\n */\nexport function hideInternalStackFrames(stack: string): string {\n\tconst lines = stack.split(\"\\n at \");\n\tif (lines.length <= 1) {\n\t\treturn stack;\n\t}\n\tlines.splice(1, 1);\n\treturn lines.join(\"\\n at \");\n}\n\n// https://github.com/nodejs/node/blob/360f7cc7867b43344aac00564286b895e15f21d7/lib/internal/errors.js#L411-L432\n/**\n * Creates a custom error class that hides stack frames.\n */\nexport function makeErrorForHideStackFrame<B extends new (...args: any[]) => Error>(\n\tBase: B,\n\tclazz: any,\n): {\n\tnew (...args: ConstructorParameters<B>): InstanceType<B> & { errorStack: string | undefined };\n} {\n\tclass HideStackFramesError extends Base {\n\t\t#hiddenStack: string | undefined;\n\n\t\tconstructor(...args: any[]) {\n\t\t\tif (isErrorStackTraceLimitWritable()) {\n\t\t\t\tconst limit = Error.stackTraceLimit;\n\t\t\t\tError.stackTraceLimit = 0;\n\t\t\t\tsuper(...args);\n\t\t\t\tError.stackTraceLimit = limit;\n\t\t\t} else {\n\t\t\t\tsuper(...args);\n\t\t\t}\n\t\t\tconst stack = new Error().stack;\n\t\t\tif (stack) {\n\t\t\t\tthis.#hiddenStack = hideInternalStackFrames(stack.replace(/^Error/, this.name));\n\t\t\t}\n\t\t}\n\n\t\t// use `getter` here to avoid the stack trace being captured by loggers\n\t\tget errorStack() {\n\t\t\treturn this.#hiddenStack;\n\t\t}\n\t}\n\n\t// This is a workaround for wpt tests that expect that the error\n\t// constructor has a `name` property of the base class.\n\tObject.defineProperty(HideStackFramesError.prototype, \"constructor\", {\n\t\tget() {\n\t\t\treturn clazz;\n\t\t},\n\t\tenumerable: false,\n\t\tconfigurable: true,\n\t});\n\n\treturn HideStackFramesError as any;\n}\n\nexport const statusCodes = {\n\tOK: 200,\n\tCREATED: 201,\n\tACCEPTED: 202,\n\tNO_CONTENT: 204,\n\tMULTIPLE_CHOICES: 300,\n\tMOVED_PERMANENTLY: 301,\n\tFOUND: 302,\n\tSEE_OTHER: 303,\n\tNOT_MODIFIED: 304,\n\tTEMPORARY_REDIRECT: 307,\n\tBAD_REQUEST: 400,\n\tUNAUTHORIZED: 401,\n\tPAYMENT_REQUIRED: 402,\n\tFORBIDDEN: 403,\n\tNOT_FOUND: 404,\n\tMETHOD_NOT_ALLOWED: 405,\n\tNOT_ACCEPTABLE: 406,\n\tPROXY_AUTHENTICATION_REQUIRED: 407,\n\tREQUEST_TIMEOUT: 408,\n\tCONFLICT: 409,\n\tGONE: 410,\n\tLENGTH_REQUIRED: 411,\n\tPRECONDITION_FAILED: 412,\n\tPAYLOAD_TOO_LARGE: 413,\n\tURI_TOO_LONG: 414,\n\tUNSUPPORTED_MEDIA_TYPE: 415,\n\tRANGE_NOT_SATISFIABLE: 416,\n\tEXPECTATION_FAILED: 417,\n\t\"I'M_A_TEAPOT\": 418,\n\tMISDIRECTED_REQUEST: 421,\n\tUNPROCESSABLE_ENTITY: 422,\n\tLOCKED: 423,\n\tFAILED_DEPENDENCY: 424,\n\tTOO_EARLY: 425,\n\tUPGRADE_REQUIRED: 426,\n\tPRECONDITION_REQUIRED: 428,\n\tTOO_MANY_REQUESTS: 429,\n\tREQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n\tUNAVAILABLE_FOR_LEGAL_REASONS: 451,\n\tINTERNAL_SERVER_ERROR: 500,\n\tNOT_IMPLEMENTED: 501,\n\tBAD_GATEWAY: 502,\n\tSERVICE_UNAVAILABLE: 503,\n\tGATEWAY_TIMEOUT: 504,\n\tHTTP_VERSION_NOT_SUPPORTED: 505,\n\tVARIANT_ALSO_NEGOTIATES: 506,\n\tINSUFFICIENT_STORAGE: 507,\n\tLOOP_DETECTED: 508,\n\tNOT_EXTENDED: 510,\n\tNETWORK_AUTHENTICATION_REQUIRED: 511,\n};\n\nexport type Status =\n\t| 100\n\t| 101\n\t| 102\n\t| 103\n\t| 200\n\t| 201\n\t| 202\n\t| 203\n\t| 204\n\t| 205\n\t| 206\n\t| 207\n\t| 208\n\t| 226\n\t| 300\n\t| 301\n\t| 302\n\t| 303\n\t| 304\n\t| 305\n\t| 306\n\t| 307\n\t| 308\n\t| 400\n\t| 401\n\t| 402\n\t| 403\n\t| 404\n\t| 405\n\t| 406\n\t| 407\n\t| 408\n\t| 409\n\t| 410\n\t| 411\n\t| 412\n\t| 413\n\t| 414\n\t| 415\n\t| 416\n\t| 417\n\t| 418\n\t| 421\n\t| 422\n\t| 423\n\t| 424\n\t| 425\n\t| 426\n\t| 428\n\t| 429\n\t| 431\n\t| 451\n\t| 500\n\t| 501\n\t| 502\n\t| 503\n\t| 504\n\t| 505\n\t| 506\n\t| 507\n\t| 508\n\t| 510\n\t| 511;\n\nclass InternalAPIError extends Error {\n\tconstructor(\n\t\tpublic status: keyof typeof statusCodes | Status = \"INTERNAL_SERVER_ERROR\",\n\t\tpublic body:\n\t\t\t| ({\n\t\t\t\t\tmessage?: string;\n\t\t\t\t\tcode?: string;\n\t\t\t\t\tcause?: unknown;\n\t\t\t } & Record<string, any>)\n\t\t\t| undefined = undefined,\n\t\tpublic headers: HeadersInit = {},\n\t\tpublic statusCode = typeof status === \"number\" ? status : statusCodes[status],\n\t) {\n\t\tsuper(\n\t\t\tbody?.message,\n\t\t\tbody?.cause\n\t\t\t\t? {\n\t\t\t\t\t\tcause: body.cause,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t);\n\t\tthis.name = \"APIError\";\n\t\tthis.status = status;\n\t\tthis.headers = headers;\n\t\tthis.statusCode = statusCode;\n\t\tthis.body = body\n\t\t\t? {\n\t\t\t\t\tcode: body?.message\n\t\t\t\t\t\t?.toUpperCase()\n\t\t\t\t\t\t.replace(/ /g, \"_\")\n\t\t\t\t\t\t.replace(/[^A-Z0-9_]/g, \"\"),\n\t\t\t\t\t...body,\n\t\t\t\t}\n\t\t\t: undefined;\n\t}\n}\n\nexport class ValidationError extends InternalAPIError {\n\tconstructor(\n\t\tpublic message: string,\n\t\tpublic issues: readonly StandardSchemaV1.Issue[],\n\t) {\n\t\tsuper(400, {\n\t\t\tmessage: message,\n\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t});\n\n\t\tthis.issues = issues;\n\t}\n}\n\nexport class BetterCallError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"BetterCallError\";\n\t}\n}\n\nexport type APIError = InstanceType<typeof InternalAPIError>;\nexport const APIError = makeErrorForHideStackFrame(InternalAPIError, Error);\n"],"mappings":";AAEA,SAAS,iCAAiC;CACzC,MAAM,OAAO,OAAO,yBAAyB,OAAO,kBAAkB;AACtE,KAAI,SAAS,OACZ,QAAO,OAAO,aAAa,MAAM;AAGlC,QAAO,OAAO,UAAU,eAAe,KAAK,MAAM,WAAW,GAC1D,KAAK,WACL,KAAK,QAAQ;;;;;AAMjB,SAAgB,wBAAwB,OAAuB;CAC9D,MAAM,QAAQ,MAAM,MAAM,YAAY;AACtC,KAAI,MAAM,UAAU,EACnB,QAAO;AAER,OAAM,OAAO,GAAG,EAAE;AAClB,QAAO,MAAM,KAAK,YAAY;;;;;AAO/B,SAAgB,2BACf,MACA,OAGC;CACD,MAAM,6BAA6B,KAAK;EACvC;EAEA,YAAY,GAAG,MAAa;AAC3B,OAAI,gCAAgC,EAAE;IACrC,MAAM,QAAQ,MAAM;AACpB,UAAM,kBAAkB;AACxB,UAAM,GAAG,KAAK;AACd,UAAM,kBAAkB;SAExB,OAAM,GAAG,KAAK;GAEf,MAAM,yBAAQ,IAAI,OAAO,EAAC;AAC1B,OAAI,MACH,OAAKA,cAAe,wBAAwB,MAAM,QAAQ,UAAU,KAAK,KAAK,CAAC;;EAKjF,IAAI,aAAa;AAChB,UAAO,MAAKA;;;AAMd,QAAO,eAAe,qBAAqB,WAAW,eAAe;EACpE,MAAM;AACL,UAAO;;EAER,YAAY;EACZ,cAAc;EACd,CAAC;AAEF,QAAO;;AAGR,MAAa,cAAc;CAC1B,IAAI;CACJ,SAAS;CACT,UAAU;CACV,YAAY;CACZ,kBAAkB;CAClB,mBAAmB;CACnB,OAAO;CACP,WAAW;CACX,cAAc;CACd,oBAAoB;CACpB,aAAa;CACb,cAAc;CACd,kBAAkB;CAClB,WAAW;CACX,WAAW;CACX,oBAAoB;CACpB,gBAAgB;CAChB,+BAA+B;CAC/B,iBAAiB;CACjB,UAAU;CACV,MAAM;CACN,iBAAiB;CACjB,qBAAqB;CACrB,mBAAmB;CACnB,cAAc;CACd,wBAAwB;CACxB,uBAAuB;CACvB,oBAAoB;CACpB,gBAAgB;CAChB,qBAAqB;CACrB,sBAAsB;CACtB,QAAQ;CACR,mBAAmB;CACnB,WAAW;CACX,kBAAkB;CAClB,uBAAuB;CACvB,mBAAmB;CACnB,iCAAiC;CACjC,+BAA+B;CAC/B,uBAAuB;CACvB,iBAAiB;CACjB,aAAa;CACb,qBAAqB;CACrB,iBAAiB;CACjB,4BAA4B;CAC5B,yBAAyB;CACzB,sBAAsB;CACtB,eAAe;CACf,cAAc;CACd,iCAAiC;CACjC;AAmED,IAAM,mBAAN,cAA+B,MAAM;CACpC,YACC,AAAOC,SAA4C,yBACnD,AAAOC,OAMQ,QACf,AAAOC,UAAuB,EAAE,EAChC,AAAO,aAAa,OAAO,WAAW,WAAW,SAAS,YAAY,SACrE;AACD,QACC,MAAM,SACN,MAAM,QACH,EACA,OAAO,KAAK,OACZ,GACA,OACH;EAlBM;EACA;EAOA;EACA;AAUP,OAAK,OAAO;AACZ,OAAK,SAAS;AACd,OAAK,UAAU;AACf,OAAK,aAAa;AAClB,OAAK,OAAO,OACT;GACA,MAAM,MAAM,SACT,aAAa,CACd,QAAQ,MAAM,IAAI,CAClB,QAAQ,eAAe,GAAG;GAC5B,GAAG;GACH,GACA;;;AAIL,IAAa,kBAAb,cAAqC,iBAAiB;CACrD,YACC,AAAOC,SACP,AAAOC,QACN;AACD,QAAM,KAAK;GACD;GACT,MAAM;GACN,CAAC;EANK;EACA;AAOP,OAAK,SAAS;;;AAIhB,IAAa,kBAAb,cAAqC,MAAM;CAC1C,YAAY,SAAiB;AAC5B,QAAM,QAAQ;AACd,OAAK,OAAO;;;
|
|
1
|
+
{"version":3,"file":"error.mjs","names":["#hiddenStack","status: keyof typeof statusCodes | Status","body:\n\t\t\t| ({\n\t\t\t\t\tmessage?: string;\n\t\t\t\t\tcode?: string;\n\t\t\t\t\tcause?: unknown;\n\t\t\t } & Record<string, any>)\n\t\t\t| undefined","headers: HeadersInit","message: string","issues: readonly StandardSchemaV1.Issue[]"],"sources":["../src/error.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"./standard-schema\";\n// https://github.com/nodejs/node/blob/360f7cc7867b43344aac00564286b895e15f21d7/lib/internal/errors.js#L246C1-L261C2\nfunction isErrorStackTraceLimitWritable() {\n\tconst desc = Object.getOwnPropertyDescriptor(Error, \"stackTraceLimit\");\n\tif (desc === undefined) {\n\t\treturn Object.isExtensible(Error);\n\t}\n\n\treturn Object.prototype.hasOwnProperty.call(desc, \"writable\")\n\t\t? desc.writable\n\t\t: desc.set !== undefined;\n}\n\n/**\n * Hide internal stack frames from the error stack trace.\n */\nexport function hideInternalStackFrames(stack: string): string {\n\tconst lines = stack.split(\"\\n at \");\n\tif (lines.length <= 1) {\n\t\treturn stack;\n\t}\n\tlines.splice(1, 1);\n\treturn lines.join(\"\\n at \");\n}\n\n// https://github.com/nodejs/node/blob/360f7cc7867b43344aac00564286b895e15f21d7/lib/internal/errors.js#L411-L432\n/**\n * Creates a custom error class that hides stack frames.\n */\nexport function makeErrorForHideStackFrame<B extends new (...args: any[]) => Error>(\n\tBase: B,\n\tclazz: any,\n): {\n\tnew (...args: ConstructorParameters<B>): InstanceType<B> & { errorStack: string | undefined };\n} {\n\tclass HideStackFramesError extends Base {\n\t\t#hiddenStack: string | undefined;\n\n\t\tconstructor(...args: any[]) {\n\t\t\tif (isErrorStackTraceLimitWritable()) {\n\t\t\t\tconst limit = Error.stackTraceLimit;\n\t\t\t\tError.stackTraceLimit = 0;\n\t\t\t\tsuper(...args);\n\t\t\t\tError.stackTraceLimit = limit;\n\t\t\t} else {\n\t\t\t\tsuper(...args);\n\t\t\t}\n\t\t\tconst stack = new Error().stack;\n\t\t\tif (stack) {\n\t\t\t\tthis.#hiddenStack = hideInternalStackFrames(stack.replace(/^Error/, this.name));\n\t\t\t}\n\t\t}\n\n\t\t// use `getter` here to avoid the stack trace being captured by loggers\n\t\tget errorStack() {\n\t\t\treturn this.#hiddenStack;\n\t\t}\n\t}\n\n\t// This is a workaround for wpt tests that expect that the error\n\t// constructor has a `name` property of the base class.\n\tObject.defineProperty(HideStackFramesError.prototype, \"constructor\", {\n\t\tget() {\n\t\t\treturn clazz;\n\t\t},\n\t\tenumerable: false,\n\t\tconfigurable: true,\n\t});\n\n\treturn HideStackFramesError as any;\n}\n\nexport const statusCodes = {\n\tOK: 200,\n\tCREATED: 201,\n\tACCEPTED: 202,\n\tNO_CONTENT: 204,\n\tMULTIPLE_CHOICES: 300,\n\tMOVED_PERMANENTLY: 301,\n\tFOUND: 302,\n\tSEE_OTHER: 303,\n\tNOT_MODIFIED: 304,\n\tTEMPORARY_REDIRECT: 307,\n\tBAD_REQUEST: 400,\n\tUNAUTHORIZED: 401,\n\tPAYMENT_REQUIRED: 402,\n\tFORBIDDEN: 403,\n\tNOT_FOUND: 404,\n\tMETHOD_NOT_ALLOWED: 405,\n\tNOT_ACCEPTABLE: 406,\n\tPROXY_AUTHENTICATION_REQUIRED: 407,\n\tREQUEST_TIMEOUT: 408,\n\tCONFLICT: 409,\n\tGONE: 410,\n\tLENGTH_REQUIRED: 411,\n\tPRECONDITION_FAILED: 412,\n\tPAYLOAD_TOO_LARGE: 413,\n\tURI_TOO_LONG: 414,\n\tUNSUPPORTED_MEDIA_TYPE: 415,\n\tRANGE_NOT_SATISFIABLE: 416,\n\tEXPECTATION_FAILED: 417,\n\t\"I'M_A_TEAPOT\": 418,\n\tMISDIRECTED_REQUEST: 421,\n\tUNPROCESSABLE_ENTITY: 422,\n\tLOCKED: 423,\n\tFAILED_DEPENDENCY: 424,\n\tTOO_EARLY: 425,\n\tUPGRADE_REQUIRED: 426,\n\tPRECONDITION_REQUIRED: 428,\n\tTOO_MANY_REQUESTS: 429,\n\tREQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n\tUNAVAILABLE_FOR_LEGAL_REASONS: 451,\n\tINTERNAL_SERVER_ERROR: 500,\n\tNOT_IMPLEMENTED: 501,\n\tBAD_GATEWAY: 502,\n\tSERVICE_UNAVAILABLE: 503,\n\tGATEWAY_TIMEOUT: 504,\n\tHTTP_VERSION_NOT_SUPPORTED: 505,\n\tVARIANT_ALSO_NEGOTIATES: 506,\n\tINSUFFICIENT_STORAGE: 507,\n\tLOOP_DETECTED: 508,\n\tNOT_EXTENDED: 510,\n\tNETWORK_AUTHENTICATION_REQUIRED: 511,\n};\n\nexport type Status =\n\t| 100\n\t| 101\n\t| 102\n\t| 103\n\t| 200\n\t| 201\n\t| 202\n\t| 203\n\t| 204\n\t| 205\n\t| 206\n\t| 207\n\t| 208\n\t| 226\n\t| 300\n\t| 301\n\t| 302\n\t| 303\n\t| 304\n\t| 305\n\t| 306\n\t| 307\n\t| 308\n\t| 400\n\t| 401\n\t| 402\n\t| 403\n\t| 404\n\t| 405\n\t| 406\n\t| 407\n\t| 408\n\t| 409\n\t| 410\n\t| 411\n\t| 412\n\t| 413\n\t| 414\n\t| 415\n\t| 416\n\t| 417\n\t| 418\n\t| 421\n\t| 422\n\t| 423\n\t| 424\n\t| 425\n\t| 426\n\t| 428\n\t| 429\n\t| 431\n\t| 451\n\t| 500\n\t| 501\n\t| 502\n\t| 503\n\t| 504\n\t| 505\n\t| 506\n\t| 507\n\t| 508\n\t| 510\n\t| 511;\n\nclass InternalAPIError extends Error {\n\tconstructor(\n\t\tpublic status: keyof typeof statusCodes | Status = \"INTERNAL_SERVER_ERROR\",\n\t\tpublic body:\n\t\t\t| ({\n\t\t\t\t\tmessage?: string;\n\t\t\t\t\tcode?: string;\n\t\t\t\t\tcause?: unknown;\n\t\t\t } & Record<string, any>)\n\t\t\t| undefined = undefined,\n\t\tpublic headers: HeadersInit = {},\n\t\tpublic statusCode = typeof status === \"number\" ? status : statusCodes[status],\n\t) {\n\t\tsuper(\n\t\t\tbody?.message,\n\t\t\tbody?.cause\n\t\t\t\t? {\n\t\t\t\t\t\tcause: body.cause,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t);\n\t\tthis.name = \"APIError\";\n\t\tthis.status = status;\n\t\tthis.headers = headers;\n\t\tthis.statusCode = statusCode;\n\t\tthis.body = body\n\t\t\t? {\n\t\t\t\t\tcode: body?.message\n\t\t\t\t\t\t?.toUpperCase()\n\t\t\t\t\t\t.replace(/ /g, \"_\")\n\t\t\t\t\t\t.replace(/[^A-Z0-9_]/g, \"\"),\n\t\t\t\t\t...body,\n\t\t\t\t}\n\t\t\t: undefined;\n\t}\n}\n\nexport class ValidationError extends InternalAPIError {\n\tconstructor(\n\t\tpublic message: string,\n\t\tpublic issues: readonly StandardSchemaV1.Issue[],\n\t) {\n\t\tsuper(400, {\n\t\t\tmessage: message,\n\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t});\n\n\t\tthis.issues = issues;\n\t}\n}\n\nexport class BetterCallError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"BetterCallError\";\n\t}\n}\n\nexport const kAPIErrorHeaderSymbol = Symbol.for(\"better-call:api-error-headers\");\n\nexport type APIError = InstanceType<typeof InternalAPIError>;\nexport const APIError = makeErrorForHideStackFrame(InternalAPIError, Error);\n"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -18,6 +18,7 @@ exports.generator = require_openapi.generator;
|
|
|
18
18
|
exports.getCookieKey = require_cookies.getCookieKey;
|
|
19
19
|
exports.getHTML = require_openapi.getHTML;
|
|
20
20
|
exports.hideInternalStackFrames = require_error.hideInternalStackFrames;
|
|
21
|
+
exports.kAPIErrorHeaderSymbol = require_error.kAPIErrorHeaderSymbol;
|
|
21
22
|
exports.makeErrorForHideStackFrame = require_error.makeErrorForHideStackFrame;
|
|
22
23
|
exports.parseCookies = require_cookies.parseCookies;
|
|
23
24
|
exports.serializeCookie = require_cookies.serializeCookie;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HasRequiredKeys, InferParamPath, InferParamWildCard, IsEmptyObject, MergeObject, Prettify, RequiredKeysOf, UnionToIntersection } from "./helper.cjs";
|
|
2
2
|
import { StandardSchemaV1 } from "./standard-schema.cjs";
|
|
3
|
-
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes } from "./error.cjs";
|
|
3
|
+
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes } from "./error.cjs";
|
|
4
4
|
import { CookieOptions, CookiePrefixOptions, getCookieKey, parseCookies, serializeCookie, serializeSignedCookie } from "./cookies.cjs";
|
|
5
5
|
import { HTTPMethod, InferBody, InferBodyInput, InferHeaders, InferHeadersInput, InferInputMethod, InferMethod, InferMiddlewareBody, InferMiddlewareQuery, InferParam, InferParamInput, InferQuery, InferQueryInput, InferRequest, InferRequestInput, InferUse, InputContext, Method, createInternalContext } from "./context.cjs";
|
|
6
6
|
import { Middleware, MiddlewareContext, MiddlewareInputContext, MiddlewareOptions, MiddlewareResponse, createMiddleware } from "./middleware.cjs";
|
|
@@ -8,4 +8,4 @@ import { OpenAPIParameter, OpenAPISchemaType, Path, generator, getHTML } from ".
|
|
|
8
8
|
import { Endpoint, EndpointBaseOptions, EndpointBodyMethodOptions, EndpointContext, EndpointOptions, StrictEndpoint, createEndpoint } from "./endpoint.cjs";
|
|
9
9
|
import { Router, RouterConfig, createRouter } from "./router.cjs";
|
|
10
10
|
import { JSONResponse, toResponse } from "./to-response.cjs";
|
|
11
|
-
export { APIError, BetterCallError, CookieOptions, CookiePrefixOptions, Endpoint, EndpointBaseOptions, EndpointBodyMethodOptions, EndpointContext, EndpointOptions, HTTPMethod, HasRequiredKeys, InferBody, InferBodyInput, InferHeaders, InferHeadersInput, InferInputMethod, InferMethod, InferMiddlewareBody, InferMiddlewareQuery, InferParam, InferParamInput, InferParamPath, InferParamWildCard, InferQuery, InferQueryInput, InferRequest, InferRequestInput, InferUse, InputContext, IsEmptyObject, JSONResponse, MergeObject, Method, Middleware, MiddlewareContext, MiddlewareInputContext, MiddlewareOptions, MiddlewareResponse, OpenAPIParameter, OpenAPISchemaType, Path, Prettify, RequiredKeysOf, Router, RouterConfig, StandardSchemaV1, Status, StrictEndpoint, UnionToIntersection, ValidationError, createEndpoint, createInternalContext, createMiddleware, createRouter, generator, getCookieKey, getHTML, hideInternalStackFrames, makeErrorForHideStackFrame, parseCookies, serializeCookie, serializeSignedCookie, statusCodes, toResponse };
|
|
11
|
+
export { APIError, BetterCallError, CookieOptions, CookiePrefixOptions, Endpoint, EndpointBaseOptions, EndpointBodyMethodOptions, EndpointContext, EndpointOptions, HTTPMethod, HasRequiredKeys, InferBody, InferBodyInput, InferHeaders, InferHeadersInput, InferInputMethod, InferMethod, InferMiddlewareBody, InferMiddlewareQuery, InferParam, InferParamInput, InferParamPath, InferParamWildCard, InferQuery, InferQueryInput, InferRequest, InferRequestInput, InferUse, InputContext, IsEmptyObject, JSONResponse, MergeObject, Method, Middleware, MiddlewareContext, MiddlewareInputContext, MiddlewareOptions, MiddlewareResponse, OpenAPIParameter, OpenAPISchemaType, Path, Prettify, RequiredKeysOf, Router, RouterConfig, StandardSchemaV1, Status, StrictEndpoint, UnionToIntersection, ValidationError, createEndpoint, createInternalContext, createMiddleware, createRouter, generator, getCookieKey, getHTML, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, parseCookies, serializeCookie, serializeSignedCookie, statusCodes, toResponse };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HasRequiredKeys, InferParamPath, InferParamWildCard, IsEmptyObject, MergeObject, Prettify, RequiredKeysOf, UnionToIntersection } from "./helper.mjs";
|
|
2
2
|
import { StandardSchemaV1 } from "./standard-schema.mjs";
|
|
3
|
-
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
3
|
+
import { APIError, BetterCallError, Status, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
4
4
|
import { CookieOptions, CookiePrefixOptions, getCookieKey, parseCookies, serializeCookie, serializeSignedCookie } from "./cookies.mjs";
|
|
5
5
|
import { HTTPMethod, InferBody, InferBodyInput, InferHeaders, InferHeadersInput, InferInputMethod, InferMethod, InferMiddlewareBody, InferMiddlewareQuery, InferParam, InferParamInput, InferQuery, InferQueryInput, InferRequest, InferRequestInput, InferUse, InputContext, Method, createInternalContext } from "./context.mjs";
|
|
6
6
|
import { Middleware, MiddlewareContext, MiddlewareInputContext, MiddlewareOptions, MiddlewareResponse, createMiddleware } from "./middleware.mjs";
|
|
@@ -8,4 +8,4 @@ import { OpenAPIParameter, OpenAPISchemaType, Path, generator, getHTML } from ".
|
|
|
8
8
|
import { Endpoint, EndpointBaseOptions, EndpointBodyMethodOptions, EndpointContext, EndpointOptions, StrictEndpoint, createEndpoint } from "./endpoint.mjs";
|
|
9
9
|
import { Router, RouterConfig, createRouter } from "./router.mjs";
|
|
10
10
|
import { JSONResponse, toResponse } from "./to-response.mjs";
|
|
11
|
-
export { APIError, BetterCallError, CookieOptions, CookiePrefixOptions, Endpoint, EndpointBaseOptions, EndpointBodyMethodOptions, EndpointContext, EndpointOptions, HTTPMethod, HasRequiredKeys, InferBody, InferBodyInput, InferHeaders, InferHeadersInput, InferInputMethod, InferMethod, InferMiddlewareBody, InferMiddlewareQuery, InferParam, InferParamInput, InferParamPath, InferParamWildCard, InferQuery, InferQueryInput, InferRequest, InferRequestInput, InferUse, InputContext, IsEmptyObject, JSONResponse, MergeObject, Method, Middleware, MiddlewareContext, MiddlewareInputContext, MiddlewareOptions, MiddlewareResponse, OpenAPIParameter, OpenAPISchemaType, Path, Prettify, RequiredKeysOf, Router, RouterConfig, StandardSchemaV1, Status, StrictEndpoint, UnionToIntersection, ValidationError, createEndpoint, createInternalContext, createMiddleware, createRouter, generator, getCookieKey, getHTML, hideInternalStackFrames, makeErrorForHideStackFrame, parseCookies, serializeCookie, serializeSignedCookie, statusCodes, toResponse };
|
|
11
|
+
export { APIError, BetterCallError, CookieOptions, CookiePrefixOptions, Endpoint, EndpointBaseOptions, EndpointBodyMethodOptions, EndpointContext, EndpointOptions, HTTPMethod, HasRequiredKeys, InferBody, InferBodyInput, InferHeaders, InferHeadersInput, InferInputMethod, InferMethod, InferMiddlewareBody, InferMiddlewareQuery, InferParam, InferParamInput, InferParamPath, InferParamWildCard, InferQuery, InferQueryInput, InferRequest, InferRequestInput, InferUse, InputContext, IsEmptyObject, JSONResponse, MergeObject, Method, Middleware, MiddlewareContext, MiddlewareInputContext, MiddlewareOptions, MiddlewareResponse, OpenAPIParameter, OpenAPISchemaType, Path, Prettify, RequiredKeysOf, Router, RouterConfig, StandardSchemaV1, Status, StrictEndpoint, UnionToIntersection, ValidationError, createEndpoint, createInternalContext, createMiddleware, createRouter, generator, getCookieKey, getHTML, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, parseCookies, serializeCookie, serializeSignedCookie, statusCodes, toResponse };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { APIError, BetterCallError, ValidationError, hideInternalStackFrames, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
1
|
+
import { APIError, BetterCallError, ValidationError, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, statusCodes } from "./error.mjs";
|
|
2
2
|
import { toResponse } from "./to-response.mjs";
|
|
3
3
|
import { getCookieKey, parseCookies, serializeCookie, serializeSignedCookie } from "./cookies.mjs";
|
|
4
4
|
import { createInternalContext } from "./context.mjs";
|
|
@@ -7,4 +7,4 @@ import { createMiddleware } from "./middleware.mjs";
|
|
|
7
7
|
import { generator, getHTML } from "./openapi.mjs";
|
|
8
8
|
import { createRouter } from "./router.mjs";
|
|
9
9
|
|
|
10
|
-
export { APIError, BetterCallError, ValidationError, createEndpoint, createInternalContext, createMiddleware, createRouter, generator, getCookieKey, getHTML, hideInternalStackFrames, makeErrorForHideStackFrame, parseCookies, serializeCookie, serializeSignedCookie, statusCodes, toResponse };
|
|
10
|
+
export { APIError, BetterCallError, ValidationError, createEndpoint, createInternalContext, createMiddleware, createRouter, generator, getCookieKey, getHTML, hideInternalStackFrames, kAPIErrorHeaderSymbol, makeErrorForHideStackFrame, parseCookies, serializeCookie, serializeSignedCookie, statusCodes, toResponse };
|
package/dist/middleware.cjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const require_error = require('./error.cjs');
|
|
2
|
+
const require_utils = require('./utils.cjs');
|
|
1
3
|
const require_context = require('./context.cjs');
|
|
2
4
|
require('./endpoint.cjs');
|
|
3
5
|
|
|
@@ -11,12 +13,23 @@ function createMiddleware(optionsOrHandler, handler) {
|
|
|
11
13
|
path: "/"
|
|
12
14
|
});
|
|
13
15
|
if (!_handler) throw new Error("handler must be defined");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
try {
|
|
17
|
+
const response = await _handler(internalContext);
|
|
18
|
+
const headers = internalContext.responseHeaders;
|
|
19
|
+
return context.returnHeaders ? {
|
|
20
|
+
headers,
|
|
21
|
+
response
|
|
22
|
+
} : response;
|
|
23
|
+
} catch (e) {
|
|
24
|
+
if (require_utils.isAPIError(e)) Object.defineProperty(e, require_error.kAPIErrorHeaderSymbol, {
|
|
25
|
+
enumerable: false,
|
|
26
|
+
configurable: false,
|
|
27
|
+
get() {
|
|
28
|
+
return internalContext.responseHeaders;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
throw e;
|
|
32
|
+
}
|
|
20
33
|
};
|
|
21
34
|
internalHandler.options = typeof optionsOrHandler === "function" ? {} : optionsOrHandler;
|
|
22
35
|
return internalHandler;
|
package/dist/middleware.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.cjs","names":["createInternalContext"],"sources":["../src/middleware.ts"],"sourcesContent":["import {\n\tcreateEndpoint,\n\ttype Endpoint,\n\ttype EndpointContext,\n\ttype EndpointOptions,\n} from \"./endpoint\";\nimport {\n\tcreateInternalContext,\n\ttype InferBody,\n\ttype InferBodyInput,\n\ttype InferHeaders,\n\ttype InferHeadersInput,\n\ttype InferMiddlewareBody,\n\ttype InferMiddlewareQuery,\n\ttype InferQuery,\n\ttype InferQueryInput,\n\ttype InferRequest,\n\ttype InferRequestInput,\n\ttype InferUse,\n\ttype InputContext,\n} from \"./context\";\nimport type { Prettify } from \"./helper\";\n\nexport interface MiddlewareOptions extends Omit<EndpointOptions, \"method\"> {}\n\nexport type MiddlewareResponse = null | void | undefined | Record<string, any>;\n\nexport type MiddlewareContext<Options extends MiddlewareOptions, Context = {}> = EndpointContext<\n\tstring,\n\tOptions & {\n\t\tmethod: \"*\";\n\t}\n> & {\n\t/**\n\t * Method\n\t *\n\t * The request method\n\t */\n\tmethod: string;\n\t/**\n\t * Path\n\t *\n\t * The path of the endpoint\n\t */\n\tpath: string;\n\t/**\n\t * Body\n\t *\n\t * The body object will be the parsed JSON from the request and validated\n\t * against the body schema if it exists\n\t */\n\tbody: InferMiddlewareBody<Options>;\n\t/**\n\t * Query\n\t *\n\t * The query object will be the parsed query string from the request\n\t * and validated against the query schema if it exists\n\t */\n\tquery: InferMiddlewareQuery<Options>;\n\t/**\n\t * Params\n\t *\n\t * If the path is `/user/:id` and the request is `/user/1` then the\n\t * params will\n\t * be `{ id: \"1\" }` and if the path includes a wildcard like `/user/*`\n\t * then the\n\t * params will be `{ _: \"1\" }` where `_` is the wildcard key. If the\n\t * wildcard\n\t * is named like `/user/**:name` then the params will be `{ name: string }`\n\t */\n\tparams: string;\n\t/**\n\t * Request object\n\t *\n\t * If `requireRequest` is set to true in the endpoint options this will be\n\t * required\n\t */\n\trequest: InferRequest<Options>;\n\t/**\n\t * Headers\n\t *\n\t * If `requireHeaders` is set to true in the endpoint options this will be\n\t * required\n\t */\n\theaders: InferHeaders<Options>;\n\t/**\n\t * Set header\n\t *\n\t * If it's called outside of a request it will just be ignored.\n\t */\n\tsetHeader: (key: string, value: string) => void;\n\t/**\n\t * Get header\n\t *\n\t * If it's called outside of a request it will just return null\n\t *\n\t * @param key - The key of the header\n\t * @returns\n\t */\n\tgetHeader: (key: string) => string | null;\n\t/**\n\t * JSON\n\t *\n\t * a helper function to create a JSON response with\n\t * the correct headers\n\t * and status code. If `asResponse` is set to true in\n\t * the context then\n\t * it will return a Response object instead of the\n\t * JSON object.\n\t *\n\t * @param json - The JSON object to return\n\t * @param routerResponse - The response object to\n\t * return if `asResponse` is\n\t * true in the context this will take precedence\n\t */\n\tjson: <R extends Record<string, any> | null>(\n\t\tjson: R,\n\t\trouterResponse?:\n\t\t\t| {\n\t\t\t\t\tstatus?: number;\n\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\tresponse?: Response;\n\t\t\t }\n\t\t\t| Response,\n\t) => Promise<R>;\n\t/**\n\t * Middleware context\n\t */\n\tcontext: Prettify<Context>;\n};\n\nexport function createMiddleware<Options extends MiddlewareOptions, R>(\n\toptions: Options,\n\thandler: (context: MiddlewareContext<Options>) => Promise<R>,\n): <InputCtx extends MiddlewareInputContext<Options>>(inputContext: InputCtx) => Promise<R>;\nexport function createMiddleware<Options extends MiddlewareOptions, R>(\n\thandler: (context: MiddlewareContext<Options>) => Promise<R>,\n): <InputCtx extends MiddlewareInputContext<Options>>(inputContext: InputCtx) => Promise<R>;\nexport function createMiddleware(optionsOrHandler: any, handler?: any) {\n\tconst internalHandler = async (inputCtx: InputContext<any, any>) => {\n\t\tconst context = inputCtx as InputContext<any, any>;\n\t\tconst _handler = typeof optionsOrHandler === \"function\" ? optionsOrHandler : handler;\n\t\tconst options = typeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\t\tconst internalContext = await createInternalContext(context, {\n\t\t\toptions,\n\t\t\tpath: \"/\",\n\t\t});\n\n\t\tif (!_handler) {\n\t\t\tthrow new Error(\"handler must be defined\");\n\t\t}\n\t\tconst response = await _handler(internalContext as any);\n\t\tconst headers = internalContext.responseHeaders;\n\t\treturn context.returnHeaders\n\t\t\t? {\n\t\t\t\t\theaders,\n\t\t\t\t\tresponse,\n\t\t\t\t}\n\t\t\t: response;\n\t};\n\tinternalHandler.options = typeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\treturn internalHandler;\n}\n\nexport type MiddlewareInputContext<Options extends MiddlewareOptions> = InferBodyInput<Options> &\n\tInferQueryInput<Options> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\tuse?: Middleware[];\n\t};\n\nexport type Middleware<\n\tOptions extends MiddlewareOptions = MiddlewareOptions,\n\tHandler extends (inputCtx: any) => Promise<any> = any,\n> = Handler & {\n\toptions: Options;\n};\n\ncreateMiddleware.create = <\n\tE extends {\n\t\tuse?: Middleware[];\n\t},\n>(\n\topts?: E,\n) => {\n\ttype InferredContext = InferUse<E[\"use\"]>;\n\tfunction fn<Options extends MiddlewareOptions, R>(\n\t\toptions: Options,\n\t\thandler: (ctx: MiddlewareContext<Options, InferredContext>) => Promise<R>,\n\t): (inputContext: MiddlewareInputContext<Options>) => Promise<R>;\n\tfunction fn<Options extends MiddlewareOptions, R>(\n\t\thandler: (ctx: MiddlewareContext<Options, InferredContext>) => Promise<R>,\n\t): (inputContext: MiddlewareInputContext<Options>) => Promise<R>;\n\tfunction fn(optionsOrHandler: any, handler?: any) {\n\t\tif (typeof optionsOrHandler === \"function\") {\n\t\t\treturn createMiddleware(\n\t\t\t\t{\n\t\t\t\t\tuse: opts?.use,\n\t\t\t\t},\n\t\t\t\toptionsOrHandler,\n\t\t\t);\n\t\t}\n\t\tif (!handler) {\n\t\t\tthrow new Error(\"Middleware handler is required\");\n\t\t}\n\t\tconst middleware = createMiddleware(\n\t\t\t{\n\t\t\t\t...optionsOrHandler,\n\t\t\t\tmethod: \"*\",\n\t\t\t\tuse: [...(opts?.use || []), ...(optionsOrHandler.use || [])],\n\t\t\t},\n\t\t\thandler,\n\t\t);\n\t\treturn middleware as any;\n\t}\n\treturn fn;\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"middleware.cjs","names":["createInternalContext","isAPIError","kAPIErrorHeaderSymbol"],"sources":["../src/middleware.ts"],"sourcesContent":["import {\n\tcreateEndpoint,\n\ttype Endpoint,\n\ttype EndpointContext,\n\ttype EndpointOptions,\n} from \"./endpoint\";\nimport {\n\tcreateInternalContext,\n\ttype InferBody,\n\ttype InferBodyInput,\n\ttype InferHeaders,\n\ttype InferHeadersInput,\n\ttype InferMiddlewareBody,\n\ttype InferMiddlewareQuery,\n\ttype InferQuery,\n\ttype InferQueryInput,\n\ttype InferRequest,\n\ttype InferRequestInput,\n\ttype InferUse,\n\ttype InputContext,\n} from \"./context\";\nimport type { Prettify } from \"./helper\";\nimport { isAPIError } from \"./utils\";\nimport { kAPIErrorHeaderSymbol } from \"./error\";\n\nexport interface MiddlewareOptions extends Omit<EndpointOptions, \"method\"> {}\n\nexport type MiddlewareResponse = null | void | undefined | Record<string, any>;\n\nexport type MiddlewareContext<Options extends MiddlewareOptions, Context = {}> = EndpointContext<\n\tstring,\n\tOptions & {\n\t\tmethod: \"*\";\n\t}\n> & {\n\t/**\n\t * Method\n\t *\n\t * The request method\n\t */\n\tmethod: string;\n\t/**\n\t * Path\n\t *\n\t * The path of the endpoint\n\t */\n\tpath: string;\n\t/**\n\t * Body\n\t *\n\t * The body object will be the parsed JSON from the request and validated\n\t * against the body schema if it exists\n\t */\n\tbody: InferMiddlewareBody<Options>;\n\t/**\n\t * Query\n\t *\n\t * The query object will be the parsed query string from the request\n\t * and validated against the query schema if it exists\n\t */\n\tquery: InferMiddlewareQuery<Options>;\n\t/**\n\t * Params\n\t *\n\t * If the path is `/user/:id` and the request is `/user/1` then the\n\t * params will\n\t * be `{ id: \"1\" }` and if the path includes a wildcard like `/user/*`\n\t * then the\n\t * params will be `{ _: \"1\" }` where `_` is the wildcard key. If the\n\t * wildcard\n\t * is named like `/user/**:name` then the params will be `{ name: string }`\n\t */\n\tparams: string;\n\t/**\n\t * Request object\n\t *\n\t * If `requireRequest` is set to true in the endpoint options this will be\n\t * required\n\t */\n\trequest: InferRequest<Options>;\n\t/**\n\t * Headers\n\t *\n\t * If `requireHeaders` is set to true in the endpoint options this will be\n\t * required\n\t */\n\theaders: InferHeaders<Options>;\n\t/**\n\t * Set header\n\t *\n\t * If it's called outside of a request it will just be ignored.\n\t */\n\tsetHeader: (key: string, value: string) => void;\n\t/**\n\t * Get header\n\t *\n\t * If it's called outside of a request it will just return null\n\t *\n\t * @param key - The key of the header\n\t * @returns\n\t */\n\tgetHeader: (key: string) => string | null;\n\t/**\n\t * JSON\n\t *\n\t * a helper function to create a JSON response with\n\t * the correct headers\n\t * and status code. If `asResponse` is set to true in\n\t * the context then\n\t * it will return a Response object instead of the\n\t * JSON object.\n\t *\n\t * @param json - The JSON object to return\n\t * @param routerResponse - The response object to\n\t * return if `asResponse` is\n\t * true in the context this will take precedence\n\t */\n\tjson: <R extends Record<string, any> | null>(\n\t\tjson: R,\n\t\trouterResponse?:\n\t\t\t| {\n\t\t\t\t\tstatus?: number;\n\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\tresponse?: Response;\n\t\t\t }\n\t\t\t| Response,\n\t) => Promise<R>;\n\t/**\n\t * Middleware context\n\t */\n\tcontext: Prettify<Context>;\n};\n\nexport function createMiddleware<Options extends MiddlewareOptions, R>(\n\toptions: Options,\n\thandler: (context: MiddlewareContext<Options>) => Promise<R>,\n): <InputCtx extends MiddlewareInputContext<Options>>(inputContext: InputCtx) => Promise<R>;\nexport function createMiddleware<Options extends MiddlewareOptions, R>(\n\thandler: (context: MiddlewareContext<Options>) => Promise<R>,\n): <InputCtx extends MiddlewareInputContext<Options>>(inputContext: InputCtx) => Promise<R>;\nexport function createMiddleware(optionsOrHandler: any, handler?: any) {\n\tconst internalHandler = async (inputCtx: InputContext<any, any>) => {\n\t\tconst context = inputCtx as InputContext<any, any>;\n\t\tconst _handler = typeof optionsOrHandler === \"function\" ? optionsOrHandler : handler;\n\t\tconst options = typeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\t\tconst internalContext = await createInternalContext(context, {\n\t\t\toptions,\n\t\t\tpath: \"/\",\n\t\t});\n\n\t\tif (!_handler) {\n\t\t\tthrow new Error(\"handler must be defined\");\n\t\t}\n\t\ttry {\n\t\t\tconst response = await _handler(internalContext as any);\n\t\t\tconst headers = internalContext.responseHeaders;\n\t\t\treturn context.returnHeaders\n\t\t\t\t? {\n\t\t\t\t\t\theaders,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t}\n\t\t\t\t: response;\n\t\t} catch (e) {\n\t\t\t// fixme(alex): this is workaround that set-cookie headers are not accessible when error is thrown from middleware\n\t\t\tif (isAPIError(e)) {\n\t\t\t\tObject.defineProperty(e, kAPIErrorHeaderSymbol, {\n\t\t\t\t\tenumerable: false,\n\t\t\t\t\tconfigurable: false,\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn internalContext.responseHeaders;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t};\n\tinternalHandler.options = typeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\treturn internalHandler;\n}\n\nexport type MiddlewareInputContext<Options extends MiddlewareOptions> = InferBodyInput<Options> &\n\tInferQueryInput<Options> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\tuse?: Middleware[];\n\t};\n\nexport type Middleware<\n\tOptions extends MiddlewareOptions = MiddlewareOptions,\n\tHandler extends (inputCtx: any) => Promise<any> = any,\n> = Handler & {\n\toptions: Options;\n};\n\ncreateMiddleware.create = <\n\tE extends {\n\t\tuse?: Middleware[];\n\t},\n>(\n\topts?: E,\n) => {\n\ttype InferredContext = InferUse<E[\"use\"]>;\n\tfunction fn<Options extends MiddlewareOptions, R>(\n\t\toptions: Options,\n\t\thandler: (ctx: MiddlewareContext<Options, InferredContext>) => Promise<R>,\n\t): (inputContext: MiddlewareInputContext<Options>) => Promise<R>;\n\tfunction fn<Options extends MiddlewareOptions, R>(\n\t\thandler: (ctx: MiddlewareContext<Options, InferredContext>) => Promise<R>,\n\t): (inputContext: MiddlewareInputContext<Options>) => Promise<R>;\n\tfunction fn(optionsOrHandler: any, handler?: any) {\n\t\tif (typeof optionsOrHandler === \"function\") {\n\t\t\treturn createMiddleware(\n\t\t\t\t{\n\t\t\t\t\tuse: opts?.use,\n\t\t\t\t},\n\t\t\t\toptionsOrHandler,\n\t\t\t);\n\t\t}\n\t\tif (!handler) {\n\t\t\tthrow new Error(\"Middleware handler is required\");\n\t\t}\n\t\tconst middleware = createMiddleware(\n\t\t\t{\n\t\t\t\t...optionsOrHandler,\n\t\t\t\tmethod: \"*\",\n\t\t\t\tuse: [...(opts?.use || []), ...(optionsOrHandler.use || [])],\n\t\t\t},\n\t\t\thandler,\n\t\t);\n\t\treturn middleware as any;\n\t}\n\treturn fn;\n};\n"],"mappings":";;;;;;AA4IA,SAAgB,iBAAiB,kBAAuB,SAAe;CACtE,MAAM,kBAAkB,OAAO,aAAqC;EACnE,MAAM,UAAU;EAChB,MAAM,WAAW,OAAO,qBAAqB,aAAa,mBAAmB;EAE7E,MAAM,kBAAkB,MAAMA,sCAAsB,SAAS;GAC5D,SAFe,OAAO,qBAAqB,aAAa,EAAE,GAAG;GAG7D,MAAM;GACN,CAAC;AAEF,MAAI,CAAC,SACJ,OAAM,IAAI,MAAM,0BAA0B;AAE3C,MAAI;GACH,MAAM,WAAW,MAAM,SAAS,gBAAuB;GACvD,MAAM,UAAU,gBAAgB;AAChC,UAAO,QAAQ,gBACZ;IACA;IACA;IACA,GACA;WACK,GAAG;AAEX,OAAIC,yBAAW,EAAE,CAChB,QAAO,eAAe,GAAGC,qCAAuB;IAC/C,YAAY;IACZ,cAAc;IACd,MAAM;AACL,YAAO,gBAAgB;;IAExB,CAAC;AAEH,SAAM;;;AAGR,iBAAgB,UAAU,OAAO,qBAAqB,aAAa,EAAE,GAAG;AACxE,QAAO;;AAmBR,iBAAiB,UAKhB,SACI;CASJ,SAAS,GAAG,kBAAuB,SAAe;AACjD,MAAI,OAAO,qBAAqB,WAC/B,QAAO,iBACN,EACC,KAAK,MAAM,KACX,EACD,iBACA;AAEF,MAAI,CAAC,QACJ,OAAM,IAAI,MAAM,iCAAiC;AAUlD,SARmB,iBAClB;GACC,GAAG;GACH,QAAQ;GACR,KAAK,CAAC,GAAI,MAAM,OAAO,EAAE,EAAG,GAAI,iBAAiB,OAAO,EAAE,CAAE;GAC5D,EACD,QACA;;AAGF,QAAO"}
|
package/dist/middleware.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { kAPIErrorHeaderSymbol } from "./error.mjs";
|
|
2
|
+
import { isAPIError } from "./utils.mjs";
|
|
1
3
|
import { createInternalContext } from "./context.mjs";
|
|
2
4
|
import "./endpoint.mjs";
|
|
3
5
|
|
|
@@ -11,12 +13,23 @@ function createMiddleware(optionsOrHandler, handler) {
|
|
|
11
13
|
path: "/"
|
|
12
14
|
});
|
|
13
15
|
if (!_handler) throw new Error("handler must be defined");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
try {
|
|
17
|
+
const response = await _handler(internalContext);
|
|
18
|
+
const headers = internalContext.responseHeaders;
|
|
19
|
+
return context.returnHeaders ? {
|
|
20
|
+
headers,
|
|
21
|
+
response
|
|
22
|
+
} : response;
|
|
23
|
+
} catch (e) {
|
|
24
|
+
if (isAPIError(e)) Object.defineProperty(e, kAPIErrorHeaderSymbol, {
|
|
25
|
+
enumerable: false,
|
|
26
|
+
configurable: false,
|
|
27
|
+
get() {
|
|
28
|
+
return internalContext.responseHeaders;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
throw e;
|
|
32
|
+
}
|
|
20
33
|
};
|
|
21
34
|
internalHandler.options = typeof optionsOrHandler === "function" ? {} : optionsOrHandler;
|
|
22
35
|
return internalHandler;
|
package/dist/middleware.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.mjs","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["import {\n\tcreateEndpoint,\n\ttype Endpoint,\n\ttype EndpointContext,\n\ttype EndpointOptions,\n} from \"./endpoint\";\nimport {\n\tcreateInternalContext,\n\ttype InferBody,\n\ttype InferBodyInput,\n\ttype InferHeaders,\n\ttype InferHeadersInput,\n\ttype InferMiddlewareBody,\n\ttype InferMiddlewareQuery,\n\ttype InferQuery,\n\ttype InferQueryInput,\n\ttype InferRequest,\n\ttype InferRequestInput,\n\ttype InferUse,\n\ttype InputContext,\n} from \"./context\";\nimport type { Prettify } from \"./helper\";\n\nexport interface MiddlewareOptions extends Omit<EndpointOptions, \"method\"> {}\n\nexport type MiddlewareResponse = null | void | undefined | Record<string, any>;\n\nexport type MiddlewareContext<Options extends MiddlewareOptions, Context = {}> = EndpointContext<\n\tstring,\n\tOptions & {\n\t\tmethod: \"*\";\n\t}\n> & {\n\t/**\n\t * Method\n\t *\n\t * The request method\n\t */\n\tmethod: string;\n\t/**\n\t * Path\n\t *\n\t * The path of the endpoint\n\t */\n\tpath: string;\n\t/**\n\t * Body\n\t *\n\t * The body object will be the parsed JSON from the request and validated\n\t * against the body schema if it exists\n\t */\n\tbody: InferMiddlewareBody<Options>;\n\t/**\n\t * Query\n\t *\n\t * The query object will be the parsed query string from the request\n\t * and validated against the query schema if it exists\n\t */\n\tquery: InferMiddlewareQuery<Options>;\n\t/**\n\t * Params\n\t *\n\t * If the path is `/user/:id` and the request is `/user/1` then the\n\t * params will\n\t * be `{ id: \"1\" }` and if the path includes a wildcard like `/user/*`\n\t * then the\n\t * params will be `{ _: \"1\" }` where `_` is the wildcard key. If the\n\t * wildcard\n\t * is named like `/user/**:name` then the params will be `{ name: string }`\n\t */\n\tparams: string;\n\t/**\n\t * Request object\n\t *\n\t * If `requireRequest` is set to true in the endpoint options this will be\n\t * required\n\t */\n\trequest: InferRequest<Options>;\n\t/**\n\t * Headers\n\t *\n\t * If `requireHeaders` is set to true in the endpoint options this will be\n\t * required\n\t */\n\theaders: InferHeaders<Options>;\n\t/**\n\t * Set header\n\t *\n\t * If it's called outside of a request it will just be ignored.\n\t */\n\tsetHeader: (key: string, value: string) => void;\n\t/**\n\t * Get header\n\t *\n\t * If it's called outside of a request it will just return null\n\t *\n\t * @param key - The key of the header\n\t * @returns\n\t */\n\tgetHeader: (key: string) => string | null;\n\t/**\n\t * JSON\n\t *\n\t * a helper function to create a JSON response with\n\t * the correct headers\n\t * and status code. If `asResponse` is set to true in\n\t * the context then\n\t * it will return a Response object instead of the\n\t * JSON object.\n\t *\n\t * @param json - The JSON object to return\n\t * @param routerResponse - The response object to\n\t * return if `asResponse` is\n\t * true in the context this will take precedence\n\t */\n\tjson: <R extends Record<string, any> | null>(\n\t\tjson: R,\n\t\trouterResponse?:\n\t\t\t| {\n\t\t\t\t\tstatus?: number;\n\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\tresponse?: Response;\n\t\t\t }\n\t\t\t| Response,\n\t) => Promise<R>;\n\t/**\n\t * Middleware context\n\t */\n\tcontext: Prettify<Context>;\n};\n\nexport function createMiddleware<Options extends MiddlewareOptions, R>(\n\toptions: Options,\n\thandler: (context: MiddlewareContext<Options>) => Promise<R>,\n): <InputCtx extends MiddlewareInputContext<Options>>(inputContext: InputCtx) => Promise<R>;\nexport function createMiddleware<Options extends MiddlewareOptions, R>(\n\thandler: (context: MiddlewareContext<Options>) => Promise<R>,\n): <InputCtx extends MiddlewareInputContext<Options>>(inputContext: InputCtx) => Promise<R>;\nexport function createMiddleware(optionsOrHandler: any, handler?: any) {\n\tconst internalHandler = async (inputCtx: InputContext<any, any>) => {\n\t\tconst context = inputCtx as InputContext<any, any>;\n\t\tconst _handler = typeof optionsOrHandler === \"function\" ? optionsOrHandler : handler;\n\t\tconst options = typeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\t\tconst internalContext = await createInternalContext(context, {\n\t\t\toptions,\n\t\t\tpath: \"/\",\n\t\t});\n\n\t\tif (!_handler) {\n\t\t\tthrow new Error(\"handler must be defined\");\n\t\t}\n\t\tconst response = await _handler(internalContext as any);\n\t\tconst headers = internalContext.responseHeaders;\n\t\treturn context.returnHeaders\n\t\t\t? {\n\t\t\t\t\theaders,\n\t\t\t\t\tresponse,\n\t\t\t\t}\n\t\t\t: response;\n\t};\n\tinternalHandler.options = typeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\treturn internalHandler;\n}\n\nexport type MiddlewareInputContext<Options extends MiddlewareOptions> = InferBodyInput<Options> &\n\tInferQueryInput<Options> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\tuse?: Middleware[];\n\t};\n\nexport type Middleware<\n\tOptions extends MiddlewareOptions = MiddlewareOptions,\n\tHandler extends (inputCtx: any) => Promise<any> = any,\n> = Handler & {\n\toptions: Options;\n};\n\ncreateMiddleware.create = <\n\tE extends {\n\t\tuse?: Middleware[];\n\t},\n>(\n\topts?: E,\n) => {\n\ttype InferredContext = InferUse<E[\"use\"]>;\n\tfunction fn<Options extends MiddlewareOptions, R>(\n\t\toptions: Options,\n\t\thandler: (ctx: MiddlewareContext<Options, InferredContext>) => Promise<R>,\n\t): (inputContext: MiddlewareInputContext<Options>) => Promise<R>;\n\tfunction fn<Options extends MiddlewareOptions, R>(\n\t\thandler: (ctx: MiddlewareContext<Options, InferredContext>) => Promise<R>,\n\t): (inputContext: MiddlewareInputContext<Options>) => Promise<R>;\n\tfunction fn(optionsOrHandler: any, handler?: any) {\n\t\tif (typeof optionsOrHandler === \"function\") {\n\t\t\treturn createMiddleware(\n\t\t\t\t{\n\t\t\t\t\tuse: opts?.use,\n\t\t\t\t},\n\t\t\t\toptionsOrHandler,\n\t\t\t);\n\t\t}\n\t\tif (!handler) {\n\t\t\tthrow new Error(\"Middleware handler is required\");\n\t\t}\n\t\tconst middleware = createMiddleware(\n\t\t\t{\n\t\t\t\t...optionsOrHandler,\n\t\t\t\tmethod: \"*\",\n\t\t\t\tuse: [...(opts?.use || []), ...(optionsOrHandler.use || [])],\n\t\t\t},\n\t\t\thandler,\n\t\t);\n\t\treturn middleware as any;\n\t}\n\treturn fn;\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"middleware.mjs","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["import {\n\tcreateEndpoint,\n\ttype Endpoint,\n\ttype EndpointContext,\n\ttype EndpointOptions,\n} from \"./endpoint\";\nimport {\n\tcreateInternalContext,\n\ttype InferBody,\n\ttype InferBodyInput,\n\ttype InferHeaders,\n\ttype InferHeadersInput,\n\ttype InferMiddlewareBody,\n\ttype InferMiddlewareQuery,\n\ttype InferQuery,\n\ttype InferQueryInput,\n\ttype InferRequest,\n\ttype InferRequestInput,\n\ttype InferUse,\n\ttype InputContext,\n} from \"./context\";\nimport type { Prettify } from \"./helper\";\nimport { isAPIError } from \"./utils\";\nimport { kAPIErrorHeaderSymbol } from \"./error\";\n\nexport interface MiddlewareOptions extends Omit<EndpointOptions, \"method\"> {}\n\nexport type MiddlewareResponse = null | void | undefined | Record<string, any>;\n\nexport type MiddlewareContext<Options extends MiddlewareOptions, Context = {}> = EndpointContext<\n\tstring,\n\tOptions & {\n\t\tmethod: \"*\";\n\t}\n> & {\n\t/**\n\t * Method\n\t *\n\t * The request method\n\t */\n\tmethod: string;\n\t/**\n\t * Path\n\t *\n\t * The path of the endpoint\n\t */\n\tpath: string;\n\t/**\n\t * Body\n\t *\n\t * The body object will be the parsed JSON from the request and validated\n\t * against the body schema if it exists\n\t */\n\tbody: InferMiddlewareBody<Options>;\n\t/**\n\t * Query\n\t *\n\t * The query object will be the parsed query string from the request\n\t * and validated against the query schema if it exists\n\t */\n\tquery: InferMiddlewareQuery<Options>;\n\t/**\n\t * Params\n\t *\n\t * If the path is `/user/:id` and the request is `/user/1` then the\n\t * params will\n\t * be `{ id: \"1\" }` and if the path includes a wildcard like `/user/*`\n\t * then the\n\t * params will be `{ _: \"1\" }` where `_` is the wildcard key. If the\n\t * wildcard\n\t * is named like `/user/**:name` then the params will be `{ name: string }`\n\t */\n\tparams: string;\n\t/**\n\t * Request object\n\t *\n\t * If `requireRequest` is set to true in the endpoint options this will be\n\t * required\n\t */\n\trequest: InferRequest<Options>;\n\t/**\n\t * Headers\n\t *\n\t * If `requireHeaders` is set to true in the endpoint options this will be\n\t * required\n\t */\n\theaders: InferHeaders<Options>;\n\t/**\n\t * Set header\n\t *\n\t * If it's called outside of a request it will just be ignored.\n\t */\n\tsetHeader: (key: string, value: string) => void;\n\t/**\n\t * Get header\n\t *\n\t * If it's called outside of a request it will just return null\n\t *\n\t * @param key - The key of the header\n\t * @returns\n\t */\n\tgetHeader: (key: string) => string | null;\n\t/**\n\t * JSON\n\t *\n\t * a helper function to create a JSON response with\n\t * the correct headers\n\t * and status code. If `asResponse` is set to true in\n\t * the context then\n\t * it will return a Response object instead of the\n\t * JSON object.\n\t *\n\t * @param json - The JSON object to return\n\t * @param routerResponse - The response object to\n\t * return if `asResponse` is\n\t * true in the context this will take precedence\n\t */\n\tjson: <R extends Record<string, any> | null>(\n\t\tjson: R,\n\t\trouterResponse?:\n\t\t\t| {\n\t\t\t\t\tstatus?: number;\n\t\t\t\t\theaders?: Record<string, string>;\n\t\t\t\t\tresponse?: Response;\n\t\t\t }\n\t\t\t| Response,\n\t) => Promise<R>;\n\t/**\n\t * Middleware context\n\t */\n\tcontext: Prettify<Context>;\n};\n\nexport function createMiddleware<Options extends MiddlewareOptions, R>(\n\toptions: Options,\n\thandler: (context: MiddlewareContext<Options>) => Promise<R>,\n): <InputCtx extends MiddlewareInputContext<Options>>(inputContext: InputCtx) => Promise<R>;\nexport function createMiddleware<Options extends MiddlewareOptions, R>(\n\thandler: (context: MiddlewareContext<Options>) => Promise<R>,\n): <InputCtx extends MiddlewareInputContext<Options>>(inputContext: InputCtx) => Promise<R>;\nexport function createMiddleware(optionsOrHandler: any, handler?: any) {\n\tconst internalHandler = async (inputCtx: InputContext<any, any>) => {\n\t\tconst context = inputCtx as InputContext<any, any>;\n\t\tconst _handler = typeof optionsOrHandler === \"function\" ? optionsOrHandler : handler;\n\t\tconst options = typeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\t\tconst internalContext = await createInternalContext(context, {\n\t\t\toptions,\n\t\t\tpath: \"/\",\n\t\t});\n\n\t\tif (!_handler) {\n\t\t\tthrow new Error(\"handler must be defined\");\n\t\t}\n\t\ttry {\n\t\t\tconst response = await _handler(internalContext as any);\n\t\t\tconst headers = internalContext.responseHeaders;\n\t\t\treturn context.returnHeaders\n\t\t\t\t? {\n\t\t\t\t\t\theaders,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t}\n\t\t\t\t: response;\n\t\t} catch (e) {\n\t\t\t// fixme(alex): this is workaround that set-cookie headers are not accessible when error is thrown from middleware\n\t\t\tif (isAPIError(e)) {\n\t\t\t\tObject.defineProperty(e, kAPIErrorHeaderSymbol, {\n\t\t\t\t\tenumerable: false,\n\t\t\t\t\tconfigurable: false,\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn internalContext.responseHeaders;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t};\n\tinternalHandler.options = typeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\treturn internalHandler;\n}\n\nexport type MiddlewareInputContext<Options extends MiddlewareOptions> = InferBodyInput<Options> &\n\tInferQueryInput<Options> &\n\tInferRequestInput<Options> &\n\tInferHeadersInput<Options> & {\n\t\tasResponse?: boolean;\n\t\treturnHeaders?: boolean;\n\t\tuse?: Middleware[];\n\t};\n\nexport type Middleware<\n\tOptions extends MiddlewareOptions = MiddlewareOptions,\n\tHandler extends (inputCtx: any) => Promise<any> = any,\n> = Handler & {\n\toptions: Options;\n};\n\ncreateMiddleware.create = <\n\tE extends {\n\t\tuse?: Middleware[];\n\t},\n>(\n\topts?: E,\n) => {\n\ttype InferredContext = InferUse<E[\"use\"]>;\n\tfunction fn<Options extends MiddlewareOptions, R>(\n\t\toptions: Options,\n\t\thandler: (ctx: MiddlewareContext<Options, InferredContext>) => Promise<R>,\n\t): (inputContext: MiddlewareInputContext<Options>) => Promise<R>;\n\tfunction fn<Options extends MiddlewareOptions, R>(\n\t\thandler: (ctx: MiddlewareContext<Options, InferredContext>) => Promise<R>,\n\t): (inputContext: MiddlewareInputContext<Options>) => Promise<R>;\n\tfunction fn(optionsOrHandler: any, handler?: any) {\n\t\tif (typeof optionsOrHandler === \"function\") {\n\t\t\treturn createMiddleware(\n\t\t\t\t{\n\t\t\t\t\tuse: opts?.use,\n\t\t\t\t},\n\t\t\t\toptionsOrHandler,\n\t\t\t);\n\t\t}\n\t\tif (!handler) {\n\t\t\tthrow new Error(\"Middleware handler is required\");\n\t\t}\n\t\tconst middleware = createMiddleware(\n\t\t\t{\n\t\t\t\t...optionsOrHandler,\n\t\t\t\tmethod: \"*\",\n\t\t\t\tuse: [...(opts?.use || []), ...(optionsOrHandler.use || [])],\n\t\t\t},\n\t\t\thandler,\n\t\t);\n\t\treturn middleware as any;\n\t}\n\treturn fn;\n};\n"],"mappings":";;;;;;AA4IA,SAAgB,iBAAiB,kBAAuB,SAAe;CACtE,MAAM,kBAAkB,OAAO,aAAqC;EACnE,MAAM,UAAU;EAChB,MAAM,WAAW,OAAO,qBAAqB,aAAa,mBAAmB;EAE7E,MAAM,kBAAkB,MAAM,sBAAsB,SAAS;GAC5D,SAFe,OAAO,qBAAqB,aAAa,EAAE,GAAG;GAG7D,MAAM;GACN,CAAC;AAEF,MAAI,CAAC,SACJ,OAAM,IAAI,MAAM,0BAA0B;AAE3C,MAAI;GACH,MAAM,WAAW,MAAM,SAAS,gBAAuB;GACvD,MAAM,UAAU,gBAAgB;AAChC,UAAO,QAAQ,gBACZ;IACA;IACA;IACA,GACA;WACK,GAAG;AAEX,OAAI,WAAW,EAAE,CAChB,QAAO,eAAe,GAAG,uBAAuB;IAC/C,YAAY;IACZ,cAAc;IACd,MAAM;AACL,YAAO,gBAAgB;;IAExB,CAAC;AAEH,SAAM;;;AAGR,iBAAgB,UAAU,OAAO,qBAAqB,aAAa,EAAE,GAAG;AACxE,QAAO;;AAmBR,iBAAiB,UAKhB,SACI;CASJ,SAAS,GAAG,kBAAuB,SAAe;AACjD,MAAI,OAAO,qBAAqB,WAC/B,QAAO,iBACN,EACC,KAAK,MAAM,KACX,EACD,iBACA;AAEF,MAAI,CAAC,QACJ,OAAM,IAAI,MAAM,iCAAiC;AAUlD,SARmB,iBAClB;GACC,GAAG;GACH,QAAQ;GACR,KAAK,CAAC,GAAI,MAAM,OAAO,EAAE,EAAG,GAAI,iBAAiB,OAAO,EAAE,CAAE;GAC5D,EACD,QACA;;AAGF,QAAO"}
|
package/dist/router.cjs
CHANGED
|
@@ -103,7 +103,7 @@ const createRouter = (endpoints, config) => {
|
|
|
103
103
|
handler: async (request) => {
|
|
104
104
|
const onReq = await config?.onRequest?.(request);
|
|
105
105
|
if (onReq instanceof Response) return onReq;
|
|
106
|
-
const res = await processRequest(onReq
|
|
106
|
+
const res = await processRequest(require_utils.isRequest(onReq) ? onReq : request);
|
|
107
107
|
const onRes = await config?.onResponse?.(res);
|
|
108
108
|
if (onRes instanceof Response) return onRes;
|
|
109
109
|
return res;
|
package/dist/router.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.cjs","names":["createEndpoint","generator","getHTML","query: Record<string, string | string[]>","getBody","toResponse","error","isAPIError"],"sources":["../src/router.ts"],"sourcesContent":["import { addRoute, createRouter as createRou3Router, findAllRoutes, findRoute } from \"rou3\";\nimport { type Endpoint, createEndpoint } from \"./endpoint\";\nimport type { Middleware } from \"./middleware\";\nimport { generator, getHTML } from \"./openapi\";\nimport { toResponse } from \"./to-response\";\nimport { getBody, isAPIError } from \"./utils\";\n\nexport interface RouterConfig {\n\tthrowError?: boolean;\n\tonError?: (e: unknown) => void | Promise<void> | Response | Promise<Response>;\n\tbasePath?: string;\n\trouterMiddleware?: Array<{\n\t\tpath: string;\n\t\tmiddleware: Middleware;\n\t}>;\n\t/**\n\t * additional Context that needs to passed to endpoints\n\t *\n\t * this will be available on `ctx.context` on endpoints\n\t */\n\trouterContext?: Record<string, any>;\n\t/**\n\t * A callback to run before any response\n\t */\n\tonResponse?: (res: Response) => any | Promise<any>;\n\t/**\n\t * A callback to run before any request\n\t */\n\tonRequest?: (req: Request) => any | Promise<any>;\n\t/**\n\t * List of allowed media types (MIME types) for the router\n\t *\n\t * if provided, only the media types in the list will be allowed to be passed in the body.\n\t *\n\t * If an endpoint has allowed media types, it will override the router's allowed media types.\n\t *\n\t * @example\n\t * ```ts\n\t * const router = createRouter({\n\t * \t\tallowedMediaTypes: [\"application/json\", \"application/x-www-form-urlencoded\"],\n\t * \t})\n\t */\n\tallowedMediaTypes?: string[];\n\t/**\n\t * Skip trailing slashes\n\t *\n\t * @default false\n\t */\n\tskipTrailingSlashes?: boolean;\n\t/**\n\t * Open API route configuration\n\t */\n\topenapi?: {\n\t\t/**\n\t\t * Disable openapi route\n\t\t *\n\t\t * @default false\n\t\t */\n\t\tdisabled?: boolean;\n\t\t/**\n\t\t * A path to display open api using scalar\n\t\t *\n\t\t * @default \"/api/reference\"\n\t\t */\n\t\tpath?: string;\n\t\t/**\n\t\t * Scalar Configuration\n\t\t */\n\t\tscalar?: {\n\t\t\t/**\n\t\t\t * Title\n\t\t\t * @default \"Open API Reference\"\n\t\t\t */\n\t\t\ttitle?: string;\n\t\t\t/**\n\t\t\t * Description\n\t\t\t *\n\t\t\t * @default \"Better Call Open API Reference\"\n\t\t\t */\n\t\t\tdescription?: string;\n\t\t\t/**\n\t\t\t * Logo URL\n\t\t\t */\n\t\t\tlogo?: string;\n\t\t\t/**\n\t\t\t * Scalar theme\n\t\t\t * @default \"saturn\"\n\t\t\t */\n\t\t\ttheme?: string;\n\t\t};\n\t};\n}\n\nexport const createRouter = <E extends Record<string, Endpoint>, Config extends RouterConfig>(\n\tendpoints: E,\n\tconfig?: Config,\n) => {\n\tif (!config?.openapi?.disabled) {\n\t\tconst openapi = {\n\t\t\tpath: \"/api/reference\",\n\t\t\t...config?.openapi,\n\t\t};\n\t\t//@ts-expect-error\n\t\tendpoints[\"openapi\"] = createEndpoint(\n\t\t\topenapi.path,\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t},\n\t\t\tasync (c) => {\n\t\t\t\tconst schema = await generator(endpoints);\n\t\t\t\treturn new Response(getHTML(schema, openapi.scalar), {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"text/html\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\tconst router = createRou3Router();\n\tconst middlewareRouter = createRou3Router();\n\n\tfor (const endpoint of Object.values(endpoints)) {\n\t\tif (!endpoint.options || !endpoint.path) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (endpoint.options?.metadata?.SERVER_ONLY) continue;\n\n\t\tconst methods = Array.isArray(endpoint.options?.method)\n\t\t\t? endpoint.options.method\n\t\t\t: [endpoint.options?.method];\n\n\t\tfor (const method of methods) {\n\t\t\taddRoute(router, method, endpoint.path, endpoint);\n\t\t}\n\t}\n\n\tif (config?.routerMiddleware?.length) {\n\t\tfor (const { path, middleware } of config.routerMiddleware) {\n\t\t\taddRoute(middlewareRouter, \"*\", path, middleware);\n\t\t}\n\t}\n\n\tconst processRequest = async (request: Request) => {\n\t\tconst url = new URL(request.url);\n\t\tconst pathname = url.pathname;\n\t\tconst path =\n\t\t\tconfig?.basePath && config.basePath !== \"/\"\n\t\t\t\t? pathname\n\t\t\t\t\t\t.split(config.basePath)\n\t\t\t\t\t\t.reduce((acc, curr, index) => {\n\t\t\t\t\t\t\tif (index !== 0) {\n\t\t\t\t\t\t\t\tif (index > 1) {\n\t\t\t\t\t\t\t\t\tacc.push(`${config.basePath}${curr}`);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tacc.push(curr);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn acc;\n\t\t\t\t\t\t}, [] as string[])\n\t\t\t\t\t\t.join(\"\")\n\t\t\t\t: url.pathname;\n\t\tif (!path?.length) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\t// Reject paths with consecutive slashes\n\t\tif (/\\/{2,}/.test(path)) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\tconst route = findRoute(router, request.method, path) as {\n\t\t\tdata: Endpoint & { path: string };\n\t\t\tparams: Record<string, string>;\n\t\t};\n\t\tconst hasTrailingSlash = path.endsWith(\"/\");\n\t\tconst routeHasTrailingSlash = route?.data?.path?.endsWith(\"/\");\n\n\t\t// If the path has a trailing slash and the route doesn't have a trailing slash and skipTrailingSlashes is not set, return 404\n\t\tif (hasTrailingSlash !== routeHasTrailingSlash && !config?.skipTrailingSlashes) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\t\tif (!route?.data) return new Response(null, { status: 404, statusText: \"Not Found\" });\n\n\t\tconst query: Record<string, string | string[]> = {};\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tif (key in query) {\n\t\t\t\tif (Array.isArray(query[key])) {\n\t\t\t\t\t(query[key] as string[]).push(value);\n\t\t\t\t} else {\n\t\t\t\t\tquery[key] = [query[key] as string, value];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tquery[key] = value;\n\t\t\t}\n\t\t});\n\n\t\tconst handler = route.data as Endpoint;\n\n\t\ttry {\n\t\t\t// Determine which allowedMediaTypes to use: endpoint-level overrides router-level\n\t\t\tconst allowedMediaTypes =\n\t\t\t\thandler.options.metadata?.allowedMediaTypes || config?.allowedMediaTypes;\n\t\t\tconst context = {\n\t\t\t\tpath,\n\t\t\t\tmethod: request.method as \"GET\",\n\t\t\t\theaders: request.headers,\n\t\t\t\tparams: route.params ? (JSON.parse(JSON.stringify(route.params)) as any) : {},\n\t\t\t\trequest: request,\n\t\t\t\tbody: handler.options.disableBody\n\t\t\t\t\t? undefined\n\t\t\t\t\t: await getBody(\n\t\t\t\t\t\t\thandler.options.cloneRequest ? request.clone() : request,\n\t\t\t\t\t\t\tallowedMediaTypes,\n\t\t\t\t\t\t),\n\t\t\t\tquery,\n\t\t\t\t_flag: \"router\" as const,\n\t\t\t\tasResponse: true,\n\t\t\t\tcontext: config?.routerContext,\n\t\t\t};\n\t\t\tconst middlewareRoutes = findAllRoutes(middlewareRouter, \"*\", path);\n\t\t\tif (middlewareRoutes?.length) {\n\t\t\t\tfor (const { data: middleware, params } of middlewareRoutes) {\n\t\t\t\t\tconst res = await (middleware as Endpoint)({\n\t\t\t\t\t\t...context,\n\t\t\t\t\t\tparams,\n\t\t\t\t\t\tasResponse: false,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (res instanceof Response) return res;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst response = (await handler(context)) as Response;\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tif (config?.onError) {\n\t\t\t\ttry {\n\t\t\t\t\tconst errorResponse = await config.onError(error);\n\n\t\t\t\t\tif (errorResponse instanceof Response) {\n\t\t\t\t\t\treturn toResponse(errorResponse);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (isAPIError(error)) {\n\t\t\t\t\t\treturn toResponse(error);\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config?.throwError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (isAPIError(error)) {\n\t\t\t\treturn toResponse(error);\n\t\t\t}\n\n\t\t\tconsole.error(`# SERVER_ERROR: `, error);\n\t\t\treturn new Response(null, {\n\t\t\t\tstatus: 500,\n\t\t\t\tstatusText: \"Internal Server Error\",\n\t\t\t});\n\t\t}\n\t};\n\n\treturn {\n\t\thandler: async (request: Request) => {\n\t\t\tconst onReq = await config?.onRequest?.(request);\n\t\t\tif (onReq instanceof Response) {\n\t\t\t\treturn onReq;\n\t\t\t}\n\t\t\tconst req = onReq instanceof Request ? onReq : request;\n\t\t\tconst res = await processRequest(req);\n\t\t\tconst onRes = await config?.onResponse?.(res);\n\t\t\tif (onRes instanceof Response) {\n\t\t\t\treturn onRes;\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\tendpoints,\n\t};\n};\n\nexport type Router = ReturnType<typeof createRouter>;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"router.cjs","names":["createEndpoint","generator","getHTML","query: Record<string, string | string[]>","getBody","toResponse","error","isAPIError","isRequest"],"sources":["../src/router.ts"],"sourcesContent":["import { addRoute, createRouter as createRou3Router, findAllRoutes, findRoute } from \"rou3\";\nimport { type Endpoint, createEndpoint } from \"./endpoint\";\nimport type { Middleware } from \"./middleware\";\nimport { generator, getHTML } from \"./openapi\";\nimport { toResponse } from \"./to-response\";\nimport { getBody, isAPIError, isRequest } from \"./utils\";\n\nexport interface RouterConfig {\n\tthrowError?: boolean;\n\tonError?: (e: unknown) => void | Promise<void> | Response | Promise<Response>;\n\tbasePath?: string;\n\trouterMiddleware?: Array<{\n\t\tpath: string;\n\t\tmiddleware: Middleware;\n\t}>;\n\t/**\n\t * additional Context that needs to passed to endpoints\n\t *\n\t * this will be available on `ctx.context` on endpoints\n\t */\n\trouterContext?: Record<string, any>;\n\t/**\n\t * A callback to run before any response\n\t */\n\tonResponse?: (res: Response) => any | Promise<any>;\n\t/**\n\t * A callback to run before any request\n\t */\n\tonRequest?: (req: Request) => any | Promise<any>;\n\t/**\n\t * List of allowed media types (MIME types) for the router\n\t *\n\t * if provided, only the media types in the list will be allowed to be passed in the body.\n\t *\n\t * If an endpoint has allowed media types, it will override the router's allowed media types.\n\t *\n\t * @example\n\t * ```ts\n\t * const router = createRouter({\n\t * \t\tallowedMediaTypes: [\"application/json\", \"application/x-www-form-urlencoded\"],\n\t * \t})\n\t */\n\tallowedMediaTypes?: string[];\n\t/**\n\t * Skip trailing slashes\n\t *\n\t * @default false\n\t */\n\tskipTrailingSlashes?: boolean;\n\t/**\n\t * Open API route configuration\n\t */\n\topenapi?: {\n\t\t/**\n\t\t * Disable openapi route\n\t\t *\n\t\t * @default false\n\t\t */\n\t\tdisabled?: boolean;\n\t\t/**\n\t\t * A path to display open api using scalar\n\t\t *\n\t\t * @default \"/api/reference\"\n\t\t */\n\t\tpath?: string;\n\t\t/**\n\t\t * Scalar Configuration\n\t\t */\n\t\tscalar?: {\n\t\t\t/**\n\t\t\t * Title\n\t\t\t * @default \"Open API Reference\"\n\t\t\t */\n\t\t\ttitle?: string;\n\t\t\t/**\n\t\t\t * Description\n\t\t\t *\n\t\t\t * @default \"Better Call Open API Reference\"\n\t\t\t */\n\t\t\tdescription?: string;\n\t\t\t/**\n\t\t\t * Logo URL\n\t\t\t */\n\t\t\tlogo?: string;\n\t\t\t/**\n\t\t\t * Scalar theme\n\t\t\t * @default \"saturn\"\n\t\t\t */\n\t\t\ttheme?: string;\n\t\t};\n\t};\n}\n\nexport const createRouter = <E extends Record<string, Endpoint>, Config extends RouterConfig>(\n\tendpoints: E,\n\tconfig?: Config,\n) => {\n\tif (!config?.openapi?.disabled) {\n\t\tconst openapi = {\n\t\t\tpath: \"/api/reference\",\n\t\t\t...config?.openapi,\n\t\t};\n\t\t//@ts-expect-error\n\t\tendpoints[\"openapi\"] = createEndpoint(\n\t\t\topenapi.path,\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t},\n\t\t\tasync (c) => {\n\t\t\t\tconst schema = await generator(endpoints);\n\t\t\t\treturn new Response(getHTML(schema, openapi.scalar), {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"text/html\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\tconst router = createRou3Router();\n\tconst middlewareRouter = createRou3Router();\n\n\tfor (const endpoint of Object.values(endpoints)) {\n\t\tif (!endpoint.options || !endpoint.path) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (endpoint.options?.metadata?.SERVER_ONLY) continue;\n\n\t\tconst methods = Array.isArray(endpoint.options?.method)\n\t\t\t? endpoint.options.method\n\t\t\t: [endpoint.options?.method];\n\n\t\tfor (const method of methods) {\n\t\t\taddRoute(router, method, endpoint.path, endpoint);\n\t\t}\n\t}\n\n\tif (config?.routerMiddleware?.length) {\n\t\tfor (const { path, middleware } of config.routerMiddleware) {\n\t\t\taddRoute(middlewareRouter, \"*\", path, middleware);\n\t\t}\n\t}\n\n\tconst processRequest = async (request: Request) => {\n\t\tconst url = new URL(request.url);\n\t\tconst pathname = url.pathname;\n\t\tconst path =\n\t\t\tconfig?.basePath && config.basePath !== \"/\"\n\t\t\t\t? pathname\n\t\t\t\t\t\t.split(config.basePath)\n\t\t\t\t\t\t.reduce((acc, curr, index) => {\n\t\t\t\t\t\t\tif (index !== 0) {\n\t\t\t\t\t\t\t\tif (index > 1) {\n\t\t\t\t\t\t\t\t\tacc.push(`${config.basePath}${curr}`);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tacc.push(curr);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn acc;\n\t\t\t\t\t\t}, [] as string[])\n\t\t\t\t\t\t.join(\"\")\n\t\t\t\t: url.pathname;\n\t\tif (!path?.length) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\t// Reject paths with consecutive slashes\n\t\tif (/\\/{2,}/.test(path)) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\tconst route = findRoute(router, request.method, path) as {\n\t\t\tdata: Endpoint & { path: string };\n\t\t\tparams: Record<string, string>;\n\t\t};\n\t\tconst hasTrailingSlash = path.endsWith(\"/\");\n\t\tconst routeHasTrailingSlash = route?.data?.path?.endsWith(\"/\");\n\n\t\t// If the path has a trailing slash and the route doesn't have a trailing slash and skipTrailingSlashes is not set, return 404\n\t\tif (hasTrailingSlash !== routeHasTrailingSlash && !config?.skipTrailingSlashes) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\t\tif (!route?.data) return new Response(null, { status: 404, statusText: \"Not Found\" });\n\n\t\tconst query: Record<string, string | string[]> = {};\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tif (key in query) {\n\t\t\t\tif (Array.isArray(query[key])) {\n\t\t\t\t\t(query[key] as string[]).push(value);\n\t\t\t\t} else {\n\t\t\t\t\tquery[key] = [query[key] as string, value];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tquery[key] = value;\n\t\t\t}\n\t\t});\n\n\t\tconst handler = route.data as Endpoint;\n\n\t\ttry {\n\t\t\t// Determine which allowedMediaTypes to use: endpoint-level overrides router-level\n\t\t\tconst allowedMediaTypes =\n\t\t\t\thandler.options.metadata?.allowedMediaTypes || config?.allowedMediaTypes;\n\t\t\tconst context = {\n\t\t\t\tpath,\n\t\t\t\tmethod: request.method as \"GET\",\n\t\t\t\theaders: request.headers,\n\t\t\t\tparams: route.params ? (JSON.parse(JSON.stringify(route.params)) as any) : {},\n\t\t\t\trequest: request,\n\t\t\t\tbody: handler.options.disableBody\n\t\t\t\t\t? undefined\n\t\t\t\t\t: await getBody(\n\t\t\t\t\t\t\thandler.options.cloneRequest ? request.clone() : request,\n\t\t\t\t\t\t\tallowedMediaTypes,\n\t\t\t\t\t\t),\n\t\t\t\tquery,\n\t\t\t\t_flag: \"router\" as const,\n\t\t\t\tasResponse: true,\n\t\t\t\tcontext: config?.routerContext,\n\t\t\t};\n\t\t\tconst middlewareRoutes = findAllRoutes(middlewareRouter, \"*\", path);\n\t\t\tif (middlewareRoutes?.length) {\n\t\t\t\tfor (const { data: middleware, params } of middlewareRoutes) {\n\t\t\t\t\tconst res = await (middleware as Endpoint)({\n\t\t\t\t\t\t...context,\n\t\t\t\t\t\tparams,\n\t\t\t\t\t\tasResponse: false,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (res instanceof Response) return res;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst response = (await handler(context)) as Response;\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tif (config?.onError) {\n\t\t\t\ttry {\n\t\t\t\t\tconst errorResponse = await config.onError(error);\n\n\t\t\t\t\tif (errorResponse instanceof Response) {\n\t\t\t\t\t\treturn toResponse(errorResponse);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (isAPIError(error)) {\n\t\t\t\t\t\treturn toResponse(error);\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config?.throwError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (isAPIError(error)) {\n\t\t\t\treturn toResponse(error);\n\t\t\t}\n\n\t\t\tconsole.error(`# SERVER_ERROR: `, error);\n\t\t\treturn new Response(null, {\n\t\t\t\tstatus: 500,\n\t\t\t\tstatusText: \"Internal Server Error\",\n\t\t\t});\n\t\t}\n\t};\n\n\treturn {\n\t\thandler: async (request: Request) => {\n\t\t\tconst onReq = await config?.onRequest?.(request);\n\t\t\tif (onReq instanceof Response) {\n\t\t\t\treturn onReq;\n\t\t\t}\n\t\t\tconst req = isRequest(onReq) ? onReq : request;\n\t\t\tconst res = await processRequest(req);\n\t\t\tconst onRes = await config?.onResponse?.(res);\n\t\t\tif (onRes instanceof Response) {\n\t\t\t\treturn onRes;\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\tendpoints,\n\t};\n};\n\nexport type Router = ReturnType<typeof createRouter>;\n"],"mappings":"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"}
|
package/dist/router.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getBody, isAPIError } from "./utils.mjs";
|
|
1
|
+
import { getBody, isAPIError, isRequest } from "./utils.mjs";
|
|
2
2
|
import { toResponse } from "./to-response.mjs";
|
|
3
3
|
import { createEndpoint } from "./endpoint.mjs";
|
|
4
4
|
import { generator, getHTML } from "./openapi.mjs";
|
|
@@ -102,7 +102,7 @@ const createRouter$1 = (endpoints, config) => {
|
|
|
102
102
|
handler: async (request) => {
|
|
103
103
|
const onReq = await config?.onRequest?.(request);
|
|
104
104
|
if (onReq instanceof Response) return onReq;
|
|
105
|
-
const res = await processRequest(onReq
|
|
105
|
+
const res = await processRequest(isRequest(onReq) ? onReq : request);
|
|
106
106
|
const onRes = await config?.onResponse?.(res);
|
|
107
107
|
if (onRes instanceof Response) return onRes;
|
|
108
108
|
return res;
|
package/dist/router.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.mjs","names":["createRouter","createRou3Router","query: Record<string, string | string[]>","error"],"sources":["../src/router.ts"],"sourcesContent":["import { addRoute, createRouter as createRou3Router, findAllRoutes, findRoute } from \"rou3\";\nimport { type Endpoint, createEndpoint } from \"./endpoint\";\nimport type { Middleware } from \"./middleware\";\nimport { generator, getHTML } from \"./openapi\";\nimport { toResponse } from \"./to-response\";\nimport { getBody, isAPIError } from \"./utils\";\n\nexport interface RouterConfig {\n\tthrowError?: boolean;\n\tonError?: (e: unknown) => void | Promise<void> | Response | Promise<Response>;\n\tbasePath?: string;\n\trouterMiddleware?: Array<{\n\t\tpath: string;\n\t\tmiddleware: Middleware;\n\t}>;\n\t/**\n\t * additional Context that needs to passed to endpoints\n\t *\n\t * this will be available on `ctx.context` on endpoints\n\t */\n\trouterContext?: Record<string, any>;\n\t/**\n\t * A callback to run before any response\n\t */\n\tonResponse?: (res: Response) => any | Promise<any>;\n\t/**\n\t * A callback to run before any request\n\t */\n\tonRequest?: (req: Request) => any | Promise<any>;\n\t/**\n\t * List of allowed media types (MIME types) for the router\n\t *\n\t * if provided, only the media types in the list will be allowed to be passed in the body.\n\t *\n\t * If an endpoint has allowed media types, it will override the router's allowed media types.\n\t *\n\t * @example\n\t * ```ts\n\t * const router = createRouter({\n\t * \t\tallowedMediaTypes: [\"application/json\", \"application/x-www-form-urlencoded\"],\n\t * \t})\n\t */\n\tallowedMediaTypes?: string[];\n\t/**\n\t * Skip trailing slashes\n\t *\n\t * @default false\n\t */\n\tskipTrailingSlashes?: boolean;\n\t/**\n\t * Open API route configuration\n\t */\n\topenapi?: {\n\t\t/**\n\t\t * Disable openapi route\n\t\t *\n\t\t * @default false\n\t\t */\n\t\tdisabled?: boolean;\n\t\t/**\n\t\t * A path to display open api using scalar\n\t\t *\n\t\t * @default \"/api/reference\"\n\t\t */\n\t\tpath?: string;\n\t\t/**\n\t\t * Scalar Configuration\n\t\t */\n\t\tscalar?: {\n\t\t\t/**\n\t\t\t * Title\n\t\t\t * @default \"Open API Reference\"\n\t\t\t */\n\t\t\ttitle?: string;\n\t\t\t/**\n\t\t\t * Description\n\t\t\t *\n\t\t\t * @default \"Better Call Open API Reference\"\n\t\t\t */\n\t\t\tdescription?: string;\n\t\t\t/**\n\t\t\t * Logo URL\n\t\t\t */\n\t\t\tlogo?: string;\n\t\t\t/**\n\t\t\t * Scalar theme\n\t\t\t * @default \"saturn\"\n\t\t\t */\n\t\t\ttheme?: string;\n\t\t};\n\t};\n}\n\nexport const createRouter = <E extends Record<string, Endpoint>, Config extends RouterConfig>(\n\tendpoints: E,\n\tconfig?: Config,\n) => {\n\tif (!config?.openapi?.disabled) {\n\t\tconst openapi = {\n\t\t\tpath: \"/api/reference\",\n\t\t\t...config?.openapi,\n\t\t};\n\t\t//@ts-expect-error\n\t\tendpoints[\"openapi\"] = createEndpoint(\n\t\t\topenapi.path,\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t},\n\t\t\tasync (c) => {\n\t\t\t\tconst schema = await generator(endpoints);\n\t\t\t\treturn new Response(getHTML(schema, openapi.scalar), {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"text/html\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\tconst router = createRou3Router();\n\tconst middlewareRouter = createRou3Router();\n\n\tfor (const endpoint of Object.values(endpoints)) {\n\t\tif (!endpoint.options || !endpoint.path) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (endpoint.options?.metadata?.SERVER_ONLY) continue;\n\n\t\tconst methods = Array.isArray(endpoint.options?.method)\n\t\t\t? endpoint.options.method\n\t\t\t: [endpoint.options?.method];\n\n\t\tfor (const method of methods) {\n\t\t\taddRoute(router, method, endpoint.path, endpoint);\n\t\t}\n\t}\n\n\tif (config?.routerMiddleware?.length) {\n\t\tfor (const { path, middleware } of config.routerMiddleware) {\n\t\t\taddRoute(middlewareRouter, \"*\", path, middleware);\n\t\t}\n\t}\n\n\tconst processRequest = async (request: Request) => {\n\t\tconst url = new URL(request.url);\n\t\tconst pathname = url.pathname;\n\t\tconst path =\n\t\t\tconfig?.basePath && config.basePath !== \"/\"\n\t\t\t\t? pathname\n\t\t\t\t\t\t.split(config.basePath)\n\t\t\t\t\t\t.reduce((acc, curr, index) => {\n\t\t\t\t\t\t\tif (index !== 0) {\n\t\t\t\t\t\t\t\tif (index > 1) {\n\t\t\t\t\t\t\t\t\tacc.push(`${config.basePath}${curr}`);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tacc.push(curr);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn acc;\n\t\t\t\t\t\t}, [] as string[])\n\t\t\t\t\t\t.join(\"\")\n\t\t\t\t: url.pathname;\n\t\tif (!path?.length) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\t// Reject paths with consecutive slashes\n\t\tif (/\\/{2,}/.test(path)) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\tconst route = findRoute(router, request.method, path) as {\n\t\t\tdata: Endpoint & { path: string };\n\t\t\tparams: Record<string, string>;\n\t\t};\n\t\tconst hasTrailingSlash = path.endsWith(\"/\");\n\t\tconst routeHasTrailingSlash = route?.data?.path?.endsWith(\"/\");\n\n\t\t// If the path has a trailing slash and the route doesn't have a trailing slash and skipTrailingSlashes is not set, return 404\n\t\tif (hasTrailingSlash !== routeHasTrailingSlash && !config?.skipTrailingSlashes) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\t\tif (!route?.data) return new Response(null, { status: 404, statusText: \"Not Found\" });\n\n\t\tconst query: Record<string, string | string[]> = {};\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tif (key in query) {\n\t\t\t\tif (Array.isArray(query[key])) {\n\t\t\t\t\t(query[key] as string[]).push(value);\n\t\t\t\t} else {\n\t\t\t\t\tquery[key] = [query[key] as string, value];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tquery[key] = value;\n\t\t\t}\n\t\t});\n\n\t\tconst handler = route.data as Endpoint;\n\n\t\ttry {\n\t\t\t// Determine which allowedMediaTypes to use: endpoint-level overrides router-level\n\t\t\tconst allowedMediaTypes =\n\t\t\t\thandler.options.metadata?.allowedMediaTypes || config?.allowedMediaTypes;\n\t\t\tconst context = {\n\t\t\t\tpath,\n\t\t\t\tmethod: request.method as \"GET\",\n\t\t\t\theaders: request.headers,\n\t\t\t\tparams: route.params ? (JSON.parse(JSON.stringify(route.params)) as any) : {},\n\t\t\t\trequest: request,\n\t\t\t\tbody: handler.options.disableBody\n\t\t\t\t\t? undefined\n\t\t\t\t\t: await getBody(\n\t\t\t\t\t\t\thandler.options.cloneRequest ? request.clone() : request,\n\t\t\t\t\t\t\tallowedMediaTypes,\n\t\t\t\t\t\t),\n\t\t\t\tquery,\n\t\t\t\t_flag: \"router\" as const,\n\t\t\t\tasResponse: true,\n\t\t\t\tcontext: config?.routerContext,\n\t\t\t};\n\t\t\tconst middlewareRoutes = findAllRoutes(middlewareRouter, \"*\", path);\n\t\t\tif (middlewareRoutes?.length) {\n\t\t\t\tfor (const { data: middleware, params } of middlewareRoutes) {\n\t\t\t\t\tconst res = await (middleware as Endpoint)({\n\t\t\t\t\t\t...context,\n\t\t\t\t\t\tparams,\n\t\t\t\t\t\tasResponse: false,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (res instanceof Response) return res;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst response = (await handler(context)) as Response;\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tif (config?.onError) {\n\t\t\t\ttry {\n\t\t\t\t\tconst errorResponse = await config.onError(error);\n\n\t\t\t\t\tif (errorResponse instanceof Response) {\n\t\t\t\t\t\treturn toResponse(errorResponse);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (isAPIError(error)) {\n\t\t\t\t\t\treturn toResponse(error);\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config?.throwError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (isAPIError(error)) {\n\t\t\t\treturn toResponse(error);\n\t\t\t}\n\n\t\t\tconsole.error(`# SERVER_ERROR: `, error);\n\t\t\treturn new Response(null, {\n\t\t\t\tstatus: 500,\n\t\t\t\tstatusText: \"Internal Server Error\",\n\t\t\t});\n\t\t}\n\t};\n\n\treturn {\n\t\thandler: async (request: Request) => {\n\t\t\tconst onReq = await config?.onRequest?.(request);\n\t\t\tif (onReq instanceof Response) {\n\t\t\t\treturn onReq;\n\t\t\t}\n\t\t\tconst req = onReq instanceof Request ? onReq : request;\n\t\t\tconst res = await processRequest(req);\n\t\t\tconst onRes = await config?.onResponse?.(res);\n\t\t\tif (onRes instanceof Response) {\n\t\t\t\treturn onRes;\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\tendpoints,\n\t};\n};\n\nexport type Router = ReturnType<typeof createRouter>;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"router.mjs","names":["createRouter","createRou3Router","query: Record<string, string | string[]>","error"],"sources":["../src/router.ts"],"sourcesContent":["import { addRoute, createRouter as createRou3Router, findAllRoutes, findRoute } from \"rou3\";\nimport { type Endpoint, createEndpoint } from \"./endpoint\";\nimport type { Middleware } from \"./middleware\";\nimport { generator, getHTML } from \"./openapi\";\nimport { toResponse } from \"./to-response\";\nimport { getBody, isAPIError, isRequest } from \"./utils\";\n\nexport interface RouterConfig {\n\tthrowError?: boolean;\n\tonError?: (e: unknown) => void | Promise<void> | Response | Promise<Response>;\n\tbasePath?: string;\n\trouterMiddleware?: Array<{\n\t\tpath: string;\n\t\tmiddleware: Middleware;\n\t}>;\n\t/**\n\t * additional Context that needs to passed to endpoints\n\t *\n\t * this will be available on `ctx.context` on endpoints\n\t */\n\trouterContext?: Record<string, any>;\n\t/**\n\t * A callback to run before any response\n\t */\n\tonResponse?: (res: Response) => any | Promise<any>;\n\t/**\n\t * A callback to run before any request\n\t */\n\tonRequest?: (req: Request) => any | Promise<any>;\n\t/**\n\t * List of allowed media types (MIME types) for the router\n\t *\n\t * if provided, only the media types in the list will be allowed to be passed in the body.\n\t *\n\t * If an endpoint has allowed media types, it will override the router's allowed media types.\n\t *\n\t * @example\n\t * ```ts\n\t * const router = createRouter({\n\t * \t\tallowedMediaTypes: [\"application/json\", \"application/x-www-form-urlencoded\"],\n\t * \t})\n\t */\n\tallowedMediaTypes?: string[];\n\t/**\n\t * Skip trailing slashes\n\t *\n\t * @default false\n\t */\n\tskipTrailingSlashes?: boolean;\n\t/**\n\t * Open API route configuration\n\t */\n\topenapi?: {\n\t\t/**\n\t\t * Disable openapi route\n\t\t *\n\t\t * @default false\n\t\t */\n\t\tdisabled?: boolean;\n\t\t/**\n\t\t * A path to display open api using scalar\n\t\t *\n\t\t * @default \"/api/reference\"\n\t\t */\n\t\tpath?: string;\n\t\t/**\n\t\t * Scalar Configuration\n\t\t */\n\t\tscalar?: {\n\t\t\t/**\n\t\t\t * Title\n\t\t\t * @default \"Open API Reference\"\n\t\t\t */\n\t\t\ttitle?: string;\n\t\t\t/**\n\t\t\t * Description\n\t\t\t *\n\t\t\t * @default \"Better Call Open API Reference\"\n\t\t\t */\n\t\t\tdescription?: string;\n\t\t\t/**\n\t\t\t * Logo URL\n\t\t\t */\n\t\t\tlogo?: string;\n\t\t\t/**\n\t\t\t * Scalar theme\n\t\t\t * @default \"saturn\"\n\t\t\t */\n\t\t\ttheme?: string;\n\t\t};\n\t};\n}\n\nexport const createRouter = <E extends Record<string, Endpoint>, Config extends RouterConfig>(\n\tendpoints: E,\n\tconfig?: Config,\n) => {\n\tif (!config?.openapi?.disabled) {\n\t\tconst openapi = {\n\t\t\tpath: \"/api/reference\",\n\t\t\t...config?.openapi,\n\t\t};\n\t\t//@ts-expect-error\n\t\tendpoints[\"openapi\"] = createEndpoint(\n\t\t\topenapi.path,\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t},\n\t\t\tasync (c) => {\n\t\t\t\tconst schema = await generator(endpoints);\n\t\t\t\treturn new Response(getHTML(schema, openapi.scalar), {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"text/html\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\tconst router = createRou3Router();\n\tconst middlewareRouter = createRou3Router();\n\n\tfor (const endpoint of Object.values(endpoints)) {\n\t\tif (!endpoint.options || !endpoint.path) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (endpoint.options?.metadata?.SERVER_ONLY) continue;\n\n\t\tconst methods = Array.isArray(endpoint.options?.method)\n\t\t\t? endpoint.options.method\n\t\t\t: [endpoint.options?.method];\n\n\t\tfor (const method of methods) {\n\t\t\taddRoute(router, method, endpoint.path, endpoint);\n\t\t}\n\t}\n\n\tif (config?.routerMiddleware?.length) {\n\t\tfor (const { path, middleware } of config.routerMiddleware) {\n\t\t\taddRoute(middlewareRouter, \"*\", path, middleware);\n\t\t}\n\t}\n\n\tconst processRequest = async (request: Request) => {\n\t\tconst url = new URL(request.url);\n\t\tconst pathname = url.pathname;\n\t\tconst path =\n\t\t\tconfig?.basePath && config.basePath !== \"/\"\n\t\t\t\t? pathname\n\t\t\t\t\t\t.split(config.basePath)\n\t\t\t\t\t\t.reduce((acc, curr, index) => {\n\t\t\t\t\t\t\tif (index !== 0) {\n\t\t\t\t\t\t\t\tif (index > 1) {\n\t\t\t\t\t\t\t\t\tacc.push(`${config.basePath}${curr}`);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tacc.push(curr);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn acc;\n\t\t\t\t\t\t}, [] as string[])\n\t\t\t\t\t\t.join(\"\")\n\t\t\t\t: url.pathname;\n\t\tif (!path?.length) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\t// Reject paths with consecutive slashes\n\t\tif (/\\/{2,}/.test(path)) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\n\t\tconst route = findRoute(router, request.method, path) as {\n\t\t\tdata: Endpoint & { path: string };\n\t\t\tparams: Record<string, string>;\n\t\t};\n\t\tconst hasTrailingSlash = path.endsWith(\"/\");\n\t\tconst routeHasTrailingSlash = route?.data?.path?.endsWith(\"/\");\n\n\t\t// If the path has a trailing slash and the route doesn't have a trailing slash and skipTrailingSlashes is not set, return 404\n\t\tif (hasTrailingSlash !== routeHasTrailingSlash && !config?.skipTrailingSlashes) {\n\t\t\treturn new Response(null, { status: 404, statusText: \"Not Found\" });\n\t\t}\n\t\tif (!route?.data) return new Response(null, { status: 404, statusText: \"Not Found\" });\n\n\t\tconst query: Record<string, string | string[]> = {};\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tif (key in query) {\n\t\t\t\tif (Array.isArray(query[key])) {\n\t\t\t\t\t(query[key] as string[]).push(value);\n\t\t\t\t} else {\n\t\t\t\t\tquery[key] = [query[key] as string, value];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tquery[key] = value;\n\t\t\t}\n\t\t});\n\n\t\tconst handler = route.data as Endpoint;\n\n\t\ttry {\n\t\t\t// Determine which allowedMediaTypes to use: endpoint-level overrides router-level\n\t\t\tconst allowedMediaTypes =\n\t\t\t\thandler.options.metadata?.allowedMediaTypes || config?.allowedMediaTypes;\n\t\t\tconst context = {\n\t\t\t\tpath,\n\t\t\t\tmethod: request.method as \"GET\",\n\t\t\t\theaders: request.headers,\n\t\t\t\tparams: route.params ? (JSON.parse(JSON.stringify(route.params)) as any) : {},\n\t\t\t\trequest: request,\n\t\t\t\tbody: handler.options.disableBody\n\t\t\t\t\t? undefined\n\t\t\t\t\t: await getBody(\n\t\t\t\t\t\t\thandler.options.cloneRequest ? request.clone() : request,\n\t\t\t\t\t\t\tallowedMediaTypes,\n\t\t\t\t\t\t),\n\t\t\t\tquery,\n\t\t\t\t_flag: \"router\" as const,\n\t\t\t\tasResponse: true,\n\t\t\t\tcontext: config?.routerContext,\n\t\t\t};\n\t\t\tconst middlewareRoutes = findAllRoutes(middlewareRouter, \"*\", path);\n\t\t\tif (middlewareRoutes?.length) {\n\t\t\t\tfor (const { data: middleware, params } of middlewareRoutes) {\n\t\t\t\t\tconst res = await (middleware as Endpoint)({\n\t\t\t\t\t\t...context,\n\t\t\t\t\t\tparams,\n\t\t\t\t\t\tasResponse: false,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (res instanceof Response) return res;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst response = (await handler(context)) as Response;\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tif (config?.onError) {\n\t\t\t\ttry {\n\t\t\t\t\tconst errorResponse = await config.onError(error);\n\n\t\t\t\t\tif (errorResponse instanceof Response) {\n\t\t\t\t\t\treturn toResponse(errorResponse);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (isAPIError(error)) {\n\t\t\t\t\t\treturn toResponse(error);\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config?.throwError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (isAPIError(error)) {\n\t\t\t\treturn toResponse(error);\n\t\t\t}\n\n\t\t\tconsole.error(`# SERVER_ERROR: `, error);\n\t\t\treturn new Response(null, {\n\t\t\t\tstatus: 500,\n\t\t\t\tstatusText: \"Internal Server Error\",\n\t\t\t});\n\t\t}\n\t};\n\n\treturn {\n\t\thandler: async (request: Request) => {\n\t\t\tconst onReq = await config?.onRequest?.(request);\n\t\t\tif (onReq instanceof Response) {\n\t\t\t\treturn onReq;\n\t\t\t}\n\t\t\tconst req = isRequest(onReq) ? onReq : request;\n\t\t\tconst res = await processRequest(req);\n\t\t\tconst onRes = await config?.onResponse?.(res);\n\t\t\tif (onRes instanceof Response) {\n\t\t\t\treturn onRes;\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\tendpoints,\n\t};\n};\n\nexport type Router = ReturnType<typeof createRouter>;\n"],"mappings":"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"}
|
package/dist/utils.cjs
CHANGED
|
@@ -68,10 +68,19 @@ async function tryCatch(promise) {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if an object is a `Request`
|
|
73
|
+
* - `instanceof`: works for native Request instances
|
|
74
|
+
* - `toString`: handles where instanceof check fails but the object is still a valid Request
|
|
75
|
+
*/
|
|
76
|
+
function isRequest(obj) {
|
|
77
|
+
return obj instanceof Request || Object.prototype.toString.call(obj) === "[object Request]";
|
|
78
|
+
}
|
|
71
79
|
|
|
72
80
|
//#endregion
|
|
73
81
|
exports.getBody = getBody;
|
|
74
82
|
exports.isAPIError = isAPIError;
|
|
83
|
+
exports.isRequest = isRequest;
|
|
75
84
|
exports.tryCatch = tryCatch;
|
|
76
85
|
exports.tryDecode = tryDecode;
|
|
77
86
|
//# sourceMappingURL=utils.cjs.map
|
package/dist/utils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","names":["APIError","result: Record<string, string>","result: Record<string, any>"],"sources":["../src/utils.ts"],"sourcesContent":["import { APIError } from \"./error\";\n\nconst jsonContentTypeRegex = /^application\\/([a-z0-9.+-]*\\+)?json/i;\n\nexport async function getBody(request: Request, allowedMediaTypes?: string[]) {\n\tconst contentType = request.headers.get(\"content-type\") || \"\";\n\tconst normalizedContentType = contentType.toLowerCase();\n\n\tif (!request.body) {\n\t\treturn undefined;\n\t}\n\n\t// Validate content-type if allowedMediaTypes is provided\n\tif (allowedMediaTypes && allowedMediaTypes.length > 0) {\n\t\tconst isAllowed = allowedMediaTypes.some((allowed) => {\n\t\t\t// Normalize both content types for comparison\n\t\t\tconst normalizedContentTypeBase = normalizedContentType.split(\";\")[0].trim();\n\t\t\tconst normalizedAllowed = allowed.toLowerCase().trim();\n\t\t\treturn (\n\t\t\t\tnormalizedContentTypeBase === normalizedAllowed ||\n\t\t\t\tnormalizedContentTypeBase.includes(normalizedAllowed)\n\t\t\t);\n\t\t});\n\n\t\tif (!isAllowed) {\n\t\t\tif (!normalizedContentType) {\n\t\t\t\tthrow new APIError(415, {\n\t\t\t\t\tmessage: `Content-Type is required. Allowed types: ${allowedMediaTypes.join(\", \")}`,\n\t\t\t\t\tcode: \"UNSUPPORTED_MEDIA_TYPE\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow new APIError(415, {\n\t\t\t\tmessage: `Content-Type \"${contentType}\" is not allowed. Allowed types: ${allowedMediaTypes.join(\", \")}`,\n\t\t\t\tcode: \"UNSUPPORTED_MEDIA_TYPE\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (jsonContentTypeRegex.test(normalizedContentType)) {\n\t\treturn await request.json();\n\t}\n\n\tif (normalizedContentType.includes(\"application/x-www-form-urlencoded\")) {\n\t\tconst formData = await request.formData();\n\t\tconst result: Record<string, string> = {};\n\t\tformData.forEach((value, key) => {\n\t\t\tresult[key] = value.toString();\n\t\t});\n\t\treturn result;\n\t}\n\n\tif (normalizedContentType.includes(\"multipart/form-data\")) {\n\t\tconst formData = await request.formData();\n\t\tconst result: Record<string, any> = {};\n\t\tformData.forEach((value, key) => {\n\t\t\tresult[key] = value;\n\t\t});\n\t\treturn result;\n\t}\n\n\tif (normalizedContentType.includes(\"text/plain\")) {\n\t\treturn await request.text();\n\t}\n\n\tif (normalizedContentType.includes(\"application/octet-stream\")) {\n\t\treturn await request.arrayBuffer();\n\t}\n\n\tif (\n\t\tnormalizedContentType.includes(\"application/pdf\") ||\n\t\tnormalizedContentType.includes(\"image/\") ||\n\t\tnormalizedContentType.includes(\"video/\")\n\t) {\n\t\tconst blob = await request.blob();\n\t\treturn blob;\n\t}\n\n\tif (\n\t\tnormalizedContentType.includes(\"application/stream\") ||\n\t\trequest.body instanceof ReadableStream\n\t) {\n\t\treturn request.body;\n\t}\n\n\treturn await request.text();\n}\n\nexport function isAPIError(error: any): error is APIError {\n\treturn error instanceof APIError || error?.name === \"APIError\";\n}\n\nexport function tryDecode(str: string) {\n\ttry {\n\t\treturn str.includes(\"%\") ? decodeURIComponent(str) : str;\n\t} catch {\n\t\treturn str;\n\t}\n}\n\ntype Success<T> = {\n\tdata: T;\n\terror: null;\n};\n\ntype Failure<E> = {\n\tdata: null;\n\terror: E;\n};\n\ntype Result<T, E = Error> = Success<T> | Failure<E>;\n\nexport async function tryCatch<T, E = Error>(promise: Promise<T>): Promise<Result<T, E>> {\n\ttry {\n\t\tconst data = await promise;\n\t\treturn { data, error: null };\n\t} catch (error) {\n\t\treturn { data: null, error: error as E };\n\t}\n}\n"],"mappings":";;;AAEA,MAAM,uBAAuB;AAE7B,eAAsB,QAAQ,SAAkB,mBAA8B;CAC7E,MAAM,cAAc,QAAQ,QAAQ,IAAI,eAAe,IAAI;CAC3D,MAAM,wBAAwB,YAAY,aAAa;AAEvD,KAAI,CAAC,QAAQ,KACZ;AAID,KAAI,qBAAqB,kBAAkB,SAAS,GAWnD;MAAI,CAVc,kBAAkB,MAAM,YAAY;GAErD,MAAM,4BAA4B,sBAAsB,MAAM,IAAI,CAAC,GAAG,MAAM;GAC5E,MAAM,oBAAoB,QAAQ,aAAa,CAAC,MAAM;AACtD,UACC,8BAA8B,qBAC9B,0BAA0B,SAAS,kBAAkB;IAErD,EAEc;AACf,OAAI,CAAC,sBACJ,OAAM,IAAIA,uBAAS,KAAK;IACvB,SAAS,4CAA4C,kBAAkB,KAAK,KAAK;IACjF,MAAM;IACN,CAAC;AAEH,SAAM,IAAIA,uBAAS,KAAK;IACvB,SAAS,iBAAiB,YAAY,mCAAmC,kBAAkB,KAAK,KAAK;IACrG,MAAM;IACN,CAAC;;;AAIJ,KAAI,qBAAqB,KAAK,sBAAsB,CACnD,QAAO,MAAM,QAAQ,MAAM;AAG5B,KAAI,sBAAsB,SAAS,oCAAoC,EAAE;EACxE,MAAM,WAAW,MAAM,QAAQ,UAAU;EACzC,MAAMC,SAAiC,EAAE;AACzC,WAAS,SAAS,OAAO,QAAQ;AAChC,UAAO,OAAO,MAAM,UAAU;IAC7B;AACF,SAAO;;AAGR,KAAI,sBAAsB,SAAS,sBAAsB,EAAE;EAC1D,MAAM,WAAW,MAAM,QAAQ,UAAU;EACzC,MAAMC,SAA8B,EAAE;AACtC,WAAS,SAAS,OAAO,QAAQ;AAChC,UAAO,OAAO;IACb;AACF,SAAO;;AAGR,KAAI,sBAAsB,SAAS,aAAa,CAC/C,QAAO,MAAM,QAAQ,MAAM;AAG5B,KAAI,sBAAsB,SAAS,2BAA2B,CAC7D,QAAO,MAAM,QAAQ,aAAa;AAGnC,KACC,sBAAsB,SAAS,kBAAkB,IACjD,sBAAsB,SAAS,SAAS,IACxC,sBAAsB,SAAS,SAAS,CAGxC,QADa,MAAM,QAAQ,MAAM;AAIlC,KACC,sBAAsB,SAAS,qBAAqB,IACpD,QAAQ,gBAAgB,eAExB,QAAO,QAAQ;AAGhB,QAAO,MAAM,QAAQ,MAAM;;AAG5B,SAAgB,WAAW,OAA+B;AACzD,QAAO,iBAAiBF,0BAAY,OAAO,SAAS;;AAGrD,SAAgB,UAAU,KAAa;AACtC,KAAI;AACH,SAAO,IAAI,SAAS,IAAI,GAAG,mBAAmB,IAAI,GAAG;SAC9C;AACP,SAAO;;;AAgBT,eAAsB,SAAuB,SAA4C;AACxF,KAAI;AAEH,SAAO;GAAE,MADI,MAAM;GACJ,OAAO;GAAM;UACpB,OAAO;AACf,SAAO;GAAE,MAAM;GAAa;GAAY"}
|
|
1
|
+
{"version":3,"file":"utils.cjs","names":["APIError","result: Record<string, string>","result: Record<string, any>"],"sources":["../src/utils.ts"],"sourcesContent":["import { APIError } from \"./error\";\n\nconst jsonContentTypeRegex = /^application\\/([a-z0-9.+-]*\\+)?json/i;\n\nexport async function getBody(request: Request, allowedMediaTypes?: string[]) {\n\tconst contentType = request.headers.get(\"content-type\") || \"\";\n\tconst normalizedContentType = contentType.toLowerCase();\n\n\tif (!request.body) {\n\t\treturn undefined;\n\t}\n\n\t// Validate content-type if allowedMediaTypes is provided\n\tif (allowedMediaTypes && allowedMediaTypes.length > 0) {\n\t\tconst isAllowed = allowedMediaTypes.some((allowed) => {\n\t\t\t// Normalize both content types for comparison\n\t\t\tconst normalizedContentTypeBase = normalizedContentType.split(\";\")[0].trim();\n\t\t\tconst normalizedAllowed = allowed.toLowerCase().trim();\n\t\t\treturn (\n\t\t\t\tnormalizedContentTypeBase === normalizedAllowed ||\n\t\t\t\tnormalizedContentTypeBase.includes(normalizedAllowed)\n\t\t\t);\n\t\t});\n\n\t\tif (!isAllowed) {\n\t\t\tif (!normalizedContentType) {\n\t\t\t\tthrow new APIError(415, {\n\t\t\t\t\tmessage: `Content-Type is required. Allowed types: ${allowedMediaTypes.join(\", \")}`,\n\t\t\t\t\tcode: \"UNSUPPORTED_MEDIA_TYPE\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow new APIError(415, {\n\t\t\t\tmessage: `Content-Type \"${contentType}\" is not allowed. Allowed types: ${allowedMediaTypes.join(\", \")}`,\n\t\t\t\tcode: \"UNSUPPORTED_MEDIA_TYPE\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (jsonContentTypeRegex.test(normalizedContentType)) {\n\t\treturn await request.json();\n\t}\n\n\tif (normalizedContentType.includes(\"application/x-www-form-urlencoded\")) {\n\t\tconst formData = await request.formData();\n\t\tconst result: Record<string, string> = {};\n\t\tformData.forEach((value, key) => {\n\t\t\tresult[key] = value.toString();\n\t\t});\n\t\treturn result;\n\t}\n\n\tif (normalizedContentType.includes(\"multipart/form-data\")) {\n\t\tconst formData = await request.formData();\n\t\tconst result: Record<string, any> = {};\n\t\tformData.forEach((value, key) => {\n\t\t\tresult[key] = value;\n\t\t});\n\t\treturn result;\n\t}\n\n\tif (normalizedContentType.includes(\"text/plain\")) {\n\t\treturn await request.text();\n\t}\n\n\tif (normalizedContentType.includes(\"application/octet-stream\")) {\n\t\treturn await request.arrayBuffer();\n\t}\n\n\tif (\n\t\tnormalizedContentType.includes(\"application/pdf\") ||\n\t\tnormalizedContentType.includes(\"image/\") ||\n\t\tnormalizedContentType.includes(\"video/\")\n\t) {\n\t\tconst blob = await request.blob();\n\t\treturn blob;\n\t}\n\n\tif (\n\t\tnormalizedContentType.includes(\"application/stream\") ||\n\t\trequest.body instanceof ReadableStream\n\t) {\n\t\treturn request.body;\n\t}\n\n\treturn await request.text();\n}\n\nexport function isAPIError(error: any): error is APIError {\n\treturn error instanceof APIError || error?.name === \"APIError\";\n}\n\nexport function tryDecode(str: string) {\n\ttry {\n\t\treturn str.includes(\"%\") ? decodeURIComponent(str) : str;\n\t} catch {\n\t\treturn str;\n\t}\n}\n\ntype Success<T> = {\n\tdata: T;\n\terror: null;\n};\n\ntype Failure<E> = {\n\tdata: null;\n\terror: E;\n};\n\ntype Result<T, E = Error> = Success<T> | Failure<E>;\n\nexport async function tryCatch<T, E = Error>(promise: Promise<T>): Promise<Result<T, E>> {\n\ttry {\n\t\tconst data = await promise;\n\t\treturn { data, error: null };\n\t} catch (error) {\n\t\treturn { data: null, error: error as E };\n\t}\n}\n\n/**\n * Check if an object is a `Request`\n * - `instanceof`: works for native Request instances\n * - `toString`: handles where instanceof check fails but the object is still a valid Request\n */\nexport function isRequest(obj: unknown): obj is Request {\n\treturn obj instanceof Request || Object.prototype.toString.call(obj) === \"[object Request]\";\n}\n"],"mappings":";;;AAEA,MAAM,uBAAuB;AAE7B,eAAsB,QAAQ,SAAkB,mBAA8B;CAC7E,MAAM,cAAc,QAAQ,QAAQ,IAAI,eAAe,IAAI;CAC3D,MAAM,wBAAwB,YAAY,aAAa;AAEvD,KAAI,CAAC,QAAQ,KACZ;AAID,KAAI,qBAAqB,kBAAkB,SAAS,GAWnD;MAAI,CAVc,kBAAkB,MAAM,YAAY;GAErD,MAAM,4BAA4B,sBAAsB,MAAM,IAAI,CAAC,GAAG,MAAM;GAC5E,MAAM,oBAAoB,QAAQ,aAAa,CAAC,MAAM;AACtD,UACC,8BAA8B,qBAC9B,0BAA0B,SAAS,kBAAkB;IAErD,EAEc;AACf,OAAI,CAAC,sBACJ,OAAM,IAAIA,uBAAS,KAAK;IACvB,SAAS,4CAA4C,kBAAkB,KAAK,KAAK;IACjF,MAAM;IACN,CAAC;AAEH,SAAM,IAAIA,uBAAS,KAAK;IACvB,SAAS,iBAAiB,YAAY,mCAAmC,kBAAkB,KAAK,KAAK;IACrG,MAAM;IACN,CAAC;;;AAIJ,KAAI,qBAAqB,KAAK,sBAAsB,CACnD,QAAO,MAAM,QAAQ,MAAM;AAG5B,KAAI,sBAAsB,SAAS,oCAAoC,EAAE;EACxE,MAAM,WAAW,MAAM,QAAQ,UAAU;EACzC,MAAMC,SAAiC,EAAE;AACzC,WAAS,SAAS,OAAO,QAAQ;AAChC,UAAO,OAAO,MAAM,UAAU;IAC7B;AACF,SAAO;;AAGR,KAAI,sBAAsB,SAAS,sBAAsB,EAAE;EAC1D,MAAM,WAAW,MAAM,QAAQ,UAAU;EACzC,MAAMC,SAA8B,EAAE;AACtC,WAAS,SAAS,OAAO,QAAQ;AAChC,UAAO,OAAO;IACb;AACF,SAAO;;AAGR,KAAI,sBAAsB,SAAS,aAAa,CAC/C,QAAO,MAAM,QAAQ,MAAM;AAG5B,KAAI,sBAAsB,SAAS,2BAA2B,CAC7D,QAAO,MAAM,QAAQ,aAAa;AAGnC,KACC,sBAAsB,SAAS,kBAAkB,IACjD,sBAAsB,SAAS,SAAS,IACxC,sBAAsB,SAAS,SAAS,CAGxC,QADa,MAAM,QAAQ,MAAM;AAIlC,KACC,sBAAsB,SAAS,qBAAqB,IACpD,QAAQ,gBAAgB,eAExB,QAAO,QAAQ;AAGhB,QAAO,MAAM,QAAQ,MAAM;;AAG5B,SAAgB,WAAW,OAA+B;AACzD,QAAO,iBAAiBF,0BAAY,OAAO,SAAS;;AAGrD,SAAgB,UAAU,KAAa;AACtC,KAAI;AACH,SAAO,IAAI,SAAS,IAAI,GAAG,mBAAmB,IAAI,GAAG;SAC9C;AACP,SAAO;;;AAgBT,eAAsB,SAAuB,SAA4C;AACxF,KAAI;AAEH,SAAO;GAAE,MADI,MAAM;GACJ,OAAO;GAAM;UACpB,OAAO;AACf,SAAO;GAAE,MAAM;GAAa;GAAY;;;;;;;;AAS1C,SAAgB,UAAU,KAA8B;AACvD,QAAO,eAAe,WAAW,OAAO,UAAU,SAAS,KAAK,IAAI,KAAK"}
|
package/dist/utils.mjs
CHANGED
|
@@ -68,7 +68,15 @@ async function tryCatch(promise) {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if an object is a `Request`
|
|
73
|
+
* - `instanceof`: works for native Request instances
|
|
74
|
+
* - `toString`: handles where instanceof check fails but the object is still a valid Request
|
|
75
|
+
*/
|
|
76
|
+
function isRequest(obj) {
|
|
77
|
+
return obj instanceof Request || Object.prototype.toString.call(obj) === "[object Request]";
|
|
78
|
+
}
|
|
71
79
|
|
|
72
80
|
//#endregion
|
|
73
|
-
export { getBody, isAPIError, tryCatch, tryDecode };
|
|
81
|
+
export { getBody, isAPIError, isRequest, tryCatch, tryDecode };
|
|
74
82
|
//# sourceMappingURL=utils.mjs.map
|
package/dist/utils.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","names":["result: Record<string, string>","result: Record<string, any>"],"sources":["../src/utils.ts"],"sourcesContent":["import { APIError } from \"./error\";\n\nconst jsonContentTypeRegex = /^application\\/([a-z0-9.+-]*\\+)?json/i;\n\nexport async function getBody(request: Request, allowedMediaTypes?: string[]) {\n\tconst contentType = request.headers.get(\"content-type\") || \"\";\n\tconst normalizedContentType = contentType.toLowerCase();\n\n\tif (!request.body) {\n\t\treturn undefined;\n\t}\n\n\t// Validate content-type if allowedMediaTypes is provided\n\tif (allowedMediaTypes && allowedMediaTypes.length > 0) {\n\t\tconst isAllowed = allowedMediaTypes.some((allowed) => {\n\t\t\t// Normalize both content types for comparison\n\t\t\tconst normalizedContentTypeBase = normalizedContentType.split(\";\")[0].trim();\n\t\t\tconst normalizedAllowed = allowed.toLowerCase().trim();\n\t\t\treturn (\n\t\t\t\tnormalizedContentTypeBase === normalizedAllowed ||\n\t\t\t\tnormalizedContentTypeBase.includes(normalizedAllowed)\n\t\t\t);\n\t\t});\n\n\t\tif (!isAllowed) {\n\t\t\tif (!normalizedContentType) {\n\t\t\t\tthrow new APIError(415, {\n\t\t\t\t\tmessage: `Content-Type is required. Allowed types: ${allowedMediaTypes.join(\", \")}`,\n\t\t\t\t\tcode: \"UNSUPPORTED_MEDIA_TYPE\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow new APIError(415, {\n\t\t\t\tmessage: `Content-Type \"${contentType}\" is not allowed. Allowed types: ${allowedMediaTypes.join(\", \")}`,\n\t\t\t\tcode: \"UNSUPPORTED_MEDIA_TYPE\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (jsonContentTypeRegex.test(normalizedContentType)) {\n\t\treturn await request.json();\n\t}\n\n\tif (normalizedContentType.includes(\"application/x-www-form-urlencoded\")) {\n\t\tconst formData = await request.formData();\n\t\tconst result: Record<string, string> = {};\n\t\tformData.forEach((value, key) => {\n\t\t\tresult[key] = value.toString();\n\t\t});\n\t\treturn result;\n\t}\n\n\tif (normalizedContentType.includes(\"multipart/form-data\")) {\n\t\tconst formData = await request.formData();\n\t\tconst result: Record<string, any> = {};\n\t\tformData.forEach((value, key) => {\n\t\t\tresult[key] = value;\n\t\t});\n\t\treturn result;\n\t}\n\n\tif (normalizedContentType.includes(\"text/plain\")) {\n\t\treturn await request.text();\n\t}\n\n\tif (normalizedContentType.includes(\"application/octet-stream\")) {\n\t\treturn await request.arrayBuffer();\n\t}\n\n\tif (\n\t\tnormalizedContentType.includes(\"application/pdf\") ||\n\t\tnormalizedContentType.includes(\"image/\") ||\n\t\tnormalizedContentType.includes(\"video/\")\n\t) {\n\t\tconst blob = await request.blob();\n\t\treturn blob;\n\t}\n\n\tif (\n\t\tnormalizedContentType.includes(\"application/stream\") ||\n\t\trequest.body instanceof ReadableStream\n\t) {\n\t\treturn request.body;\n\t}\n\n\treturn await request.text();\n}\n\nexport function isAPIError(error: any): error is APIError {\n\treturn error instanceof APIError || error?.name === \"APIError\";\n}\n\nexport function tryDecode(str: string) {\n\ttry {\n\t\treturn str.includes(\"%\") ? decodeURIComponent(str) : str;\n\t} catch {\n\t\treturn str;\n\t}\n}\n\ntype Success<T> = {\n\tdata: T;\n\terror: null;\n};\n\ntype Failure<E> = {\n\tdata: null;\n\terror: E;\n};\n\ntype Result<T, E = Error> = Success<T> | Failure<E>;\n\nexport async function tryCatch<T, E = Error>(promise: Promise<T>): Promise<Result<T, E>> {\n\ttry {\n\t\tconst data = await promise;\n\t\treturn { data, error: null };\n\t} catch (error) {\n\t\treturn { data: null, error: error as E };\n\t}\n}\n"],"mappings":";;;AAEA,MAAM,uBAAuB;AAE7B,eAAsB,QAAQ,SAAkB,mBAA8B;CAC7E,MAAM,cAAc,QAAQ,QAAQ,IAAI,eAAe,IAAI;CAC3D,MAAM,wBAAwB,YAAY,aAAa;AAEvD,KAAI,CAAC,QAAQ,KACZ;AAID,KAAI,qBAAqB,kBAAkB,SAAS,GAWnD;MAAI,CAVc,kBAAkB,MAAM,YAAY;GAErD,MAAM,4BAA4B,sBAAsB,MAAM,IAAI,CAAC,GAAG,MAAM;GAC5E,MAAM,oBAAoB,QAAQ,aAAa,CAAC,MAAM;AACtD,UACC,8BAA8B,qBAC9B,0BAA0B,SAAS,kBAAkB;IAErD,EAEc;AACf,OAAI,CAAC,sBACJ,OAAM,IAAI,SAAS,KAAK;IACvB,SAAS,4CAA4C,kBAAkB,KAAK,KAAK;IACjF,MAAM;IACN,CAAC;AAEH,SAAM,IAAI,SAAS,KAAK;IACvB,SAAS,iBAAiB,YAAY,mCAAmC,kBAAkB,KAAK,KAAK;IACrG,MAAM;IACN,CAAC;;;AAIJ,KAAI,qBAAqB,KAAK,sBAAsB,CACnD,QAAO,MAAM,QAAQ,MAAM;AAG5B,KAAI,sBAAsB,SAAS,oCAAoC,EAAE;EACxE,MAAM,WAAW,MAAM,QAAQ,UAAU;EACzC,MAAMA,SAAiC,EAAE;AACzC,WAAS,SAAS,OAAO,QAAQ;AAChC,UAAO,OAAO,MAAM,UAAU;IAC7B;AACF,SAAO;;AAGR,KAAI,sBAAsB,SAAS,sBAAsB,EAAE;EAC1D,MAAM,WAAW,MAAM,QAAQ,UAAU;EACzC,MAAMC,SAA8B,EAAE;AACtC,WAAS,SAAS,OAAO,QAAQ;AAChC,UAAO,OAAO;IACb;AACF,SAAO;;AAGR,KAAI,sBAAsB,SAAS,aAAa,CAC/C,QAAO,MAAM,QAAQ,MAAM;AAG5B,KAAI,sBAAsB,SAAS,2BAA2B,CAC7D,QAAO,MAAM,QAAQ,aAAa;AAGnC,KACC,sBAAsB,SAAS,kBAAkB,IACjD,sBAAsB,SAAS,SAAS,IACxC,sBAAsB,SAAS,SAAS,CAGxC,QADa,MAAM,QAAQ,MAAM;AAIlC,KACC,sBAAsB,SAAS,qBAAqB,IACpD,QAAQ,gBAAgB,eAExB,QAAO,QAAQ;AAGhB,QAAO,MAAM,QAAQ,MAAM;;AAG5B,SAAgB,WAAW,OAA+B;AACzD,QAAO,iBAAiB,YAAY,OAAO,SAAS;;AAGrD,SAAgB,UAAU,KAAa;AACtC,KAAI;AACH,SAAO,IAAI,SAAS,IAAI,GAAG,mBAAmB,IAAI,GAAG;SAC9C;AACP,SAAO;;;AAgBT,eAAsB,SAAuB,SAA4C;AACxF,KAAI;AAEH,SAAO;GAAE,MADI,MAAM;GACJ,OAAO;GAAM;UACpB,OAAO;AACf,SAAO;GAAE,MAAM;GAAa;GAAY"}
|
|
1
|
+
{"version":3,"file":"utils.mjs","names":["result: Record<string, string>","result: Record<string, any>"],"sources":["../src/utils.ts"],"sourcesContent":["import { APIError } from \"./error\";\n\nconst jsonContentTypeRegex = /^application\\/([a-z0-9.+-]*\\+)?json/i;\n\nexport async function getBody(request: Request, allowedMediaTypes?: string[]) {\n\tconst contentType = request.headers.get(\"content-type\") || \"\";\n\tconst normalizedContentType = contentType.toLowerCase();\n\n\tif (!request.body) {\n\t\treturn undefined;\n\t}\n\n\t// Validate content-type if allowedMediaTypes is provided\n\tif (allowedMediaTypes && allowedMediaTypes.length > 0) {\n\t\tconst isAllowed = allowedMediaTypes.some((allowed) => {\n\t\t\t// Normalize both content types for comparison\n\t\t\tconst normalizedContentTypeBase = normalizedContentType.split(\";\")[0].trim();\n\t\t\tconst normalizedAllowed = allowed.toLowerCase().trim();\n\t\t\treturn (\n\t\t\t\tnormalizedContentTypeBase === normalizedAllowed ||\n\t\t\t\tnormalizedContentTypeBase.includes(normalizedAllowed)\n\t\t\t);\n\t\t});\n\n\t\tif (!isAllowed) {\n\t\t\tif (!normalizedContentType) {\n\t\t\t\tthrow new APIError(415, {\n\t\t\t\t\tmessage: `Content-Type is required. Allowed types: ${allowedMediaTypes.join(\", \")}`,\n\t\t\t\t\tcode: \"UNSUPPORTED_MEDIA_TYPE\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow new APIError(415, {\n\t\t\t\tmessage: `Content-Type \"${contentType}\" is not allowed. Allowed types: ${allowedMediaTypes.join(\", \")}`,\n\t\t\t\tcode: \"UNSUPPORTED_MEDIA_TYPE\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (jsonContentTypeRegex.test(normalizedContentType)) {\n\t\treturn await request.json();\n\t}\n\n\tif (normalizedContentType.includes(\"application/x-www-form-urlencoded\")) {\n\t\tconst formData = await request.formData();\n\t\tconst result: Record<string, string> = {};\n\t\tformData.forEach((value, key) => {\n\t\t\tresult[key] = value.toString();\n\t\t});\n\t\treturn result;\n\t}\n\n\tif (normalizedContentType.includes(\"multipart/form-data\")) {\n\t\tconst formData = await request.formData();\n\t\tconst result: Record<string, any> = {};\n\t\tformData.forEach((value, key) => {\n\t\t\tresult[key] = value;\n\t\t});\n\t\treturn result;\n\t}\n\n\tif (normalizedContentType.includes(\"text/plain\")) {\n\t\treturn await request.text();\n\t}\n\n\tif (normalizedContentType.includes(\"application/octet-stream\")) {\n\t\treturn await request.arrayBuffer();\n\t}\n\n\tif (\n\t\tnormalizedContentType.includes(\"application/pdf\") ||\n\t\tnormalizedContentType.includes(\"image/\") ||\n\t\tnormalizedContentType.includes(\"video/\")\n\t) {\n\t\tconst blob = await request.blob();\n\t\treturn blob;\n\t}\n\n\tif (\n\t\tnormalizedContentType.includes(\"application/stream\") ||\n\t\trequest.body instanceof ReadableStream\n\t) {\n\t\treturn request.body;\n\t}\n\n\treturn await request.text();\n}\n\nexport function isAPIError(error: any): error is APIError {\n\treturn error instanceof APIError || error?.name === \"APIError\";\n}\n\nexport function tryDecode(str: string) {\n\ttry {\n\t\treturn str.includes(\"%\") ? decodeURIComponent(str) : str;\n\t} catch {\n\t\treturn str;\n\t}\n}\n\ntype Success<T> = {\n\tdata: T;\n\terror: null;\n};\n\ntype Failure<E> = {\n\tdata: null;\n\terror: E;\n};\n\ntype Result<T, E = Error> = Success<T> | Failure<E>;\n\nexport async function tryCatch<T, E = Error>(promise: Promise<T>): Promise<Result<T, E>> {\n\ttry {\n\t\tconst data = await promise;\n\t\treturn { data, error: null };\n\t} catch (error) {\n\t\treturn { data: null, error: error as E };\n\t}\n}\n\n/**\n * Check if an object is a `Request`\n * - `instanceof`: works for native Request instances\n * - `toString`: handles where instanceof check fails but the object is still a valid Request\n */\nexport function isRequest(obj: unknown): obj is Request {\n\treturn obj instanceof Request || Object.prototype.toString.call(obj) === \"[object Request]\";\n}\n"],"mappings":";;;AAEA,MAAM,uBAAuB;AAE7B,eAAsB,QAAQ,SAAkB,mBAA8B;CAC7E,MAAM,cAAc,QAAQ,QAAQ,IAAI,eAAe,IAAI;CAC3D,MAAM,wBAAwB,YAAY,aAAa;AAEvD,KAAI,CAAC,QAAQ,KACZ;AAID,KAAI,qBAAqB,kBAAkB,SAAS,GAWnD;MAAI,CAVc,kBAAkB,MAAM,YAAY;GAErD,MAAM,4BAA4B,sBAAsB,MAAM,IAAI,CAAC,GAAG,MAAM;GAC5E,MAAM,oBAAoB,QAAQ,aAAa,CAAC,MAAM;AACtD,UACC,8BAA8B,qBAC9B,0BAA0B,SAAS,kBAAkB;IAErD,EAEc;AACf,OAAI,CAAC,sBACJ,OAAM,IAAI,SAAS,KAAK;IACvB,SAAS,4CAA4C,kBAAkB,KAAK,KAAK;IACjF,MAAM;IACN,CAAC;AAEH,SAAM,IAAI,SAAS,KAAK;IACvB,SAAS,iBAAiB,YAAY,mCAAmC,kBAAkB,KAAK,KAAK;IACrG,MAAM;IACN,CAAC;;;AAIJ,KAAI,qBAAqB,KAAK,sBAAsB,CACnD,QAAO,MAAM,QAAQ,MAAM;AAG5B,KAAI,sBAAsB,SAAS,oCAAoC,EAAE;EACxE,MAAM,WAAW,MAAM,QAAQ,UAAU;EACzC,MAAMA,SAAiC,EAAE;AACzC,WAAS,SAAS,OAAO,QAAQ;AAChC,UAAO,OAAO,MAAM,UAAU;IAC7B;AACF,SAAO;;AAGR,KAAI,sBAAsB,SAAS,sBAAsB,EAAE;EAC1D,MAAM,WAAW,MAAM,QAAQ,UAAU;EACzC,MAAMC,SAA8B,EAAE;AACtC,WAAS,SAAS,OAAO,QAAQ;AAChC,UAAO,OAAO;IACb;AACF,SAAO;;AAGR,KAAI,sBAAsB,SAAS,aAAa,CAC/C,QAAO,MAAM,QAAQ,MAAM;AAG5B,KAAI,sBAAsB,SAAS,2BAA2B,CAC7D,QAAO,MAAM,QAAQ,aAAa;AAGnC,KACC,sBAAsB,SAAS,kBAAkB,IACjD,sBAAsB,SAAS,SAAS,IACxC,sBAAsB,SAAS,SAAS,CAGxC,QADa,MAAM,QAAQ,MAAM;AAIlC,KACC,sBAAsB,SAAS,qBAAqB,IACpD,QAAQ,gBAAgB,eAExB,QAAO,QAAQ;AAGhB,QAAO,MAAM,QAAQ,MAAM;;AAG5B,SAAgB,WAAW,OAA+B;AACzD,QAAO,iBAAiB,YAAY,OAAO,SAAS;;AAGrD,SAAgB,UAAU,KAAa;AACtC,KAAI;AACH,SAAO,IAAI,SAAS,IAAI,GAAG,mBAAmB,IAAI,GAAG;SAC9C;AACP,SAAO;;;AAgBT,eAAsB,SAAuB,SAA4C;AACxF,KAAI;AAEH,SAAO;GAAE,MADI,MAAM;GACJ,OAAO;GAAM;UACpB,OAAO;AACf,SAAO;GAAE,MAAM;GAAa;GAAY;;;;;;;;AAS1C,SAAgB,UAAU,KAA8B;AACvD,QAAO,eAAe,WAAW,OAAO,UAAU,SAAS,KAAK,IAAI,KAAK"}
|