@shware/http 3.0.0 → 3.1.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/error/parse.cjs +4 -3
- package/dist/error/parse.cjs.map +1 -1
- package/dist/error/parse.d.cts.map +1 -1
- package/dist/error/parse.d.mts.map +1 -1
- package/dist/error/parse.mjs +4 -3
- package/dist/error/parse.mjs.map +1 -1
- package/dist/error/status.cjs +1 -1
- package/dist/error/status.cjs.map +1 -1
- package/dist/error/status.mjs +1 -1
- package/dist/error/status.mjs.map +1 -1
- package/dist/google-one-tap/index.cjs +20 -5
- package/dist/google-one-tap/index.cjs.map +1 -1
- package/dist/google-one-tap/index.d.cts +2 -1
- package/dist/google-one-tap/index.d.cts.map +1 -1
- package/dist/google-one-tap/index.d.mts +2 -1
- package/dist/google-one-tap/index.d.mts.map +1 -1
- package/dist/google-one-tap/index.mjs +20 -5
- package/dist/google-one-tap/index.mjs.map +1 -1
- package/dist/hono/csrf.cjs +2 -2
- package/dist/hono/csrf.cjs.map +1 -1
- package/dist/hono/csrf.mjs +2 -2
- package/dist/hono/csrf.mjs.map +1 -1
- package/dist/hono/handler.cjs +56 -9
- package/dist/hono/handler.cjs.map +1 -1
- package/dist/hono/handler.d.cts +8 -1
- package/dist/hono/handler.d.cts.map +1 -1
- package/dist/hono/handler.d.mts +8 -1
- package/dist/hono/handler.d.mts.map +1 -1
- package/dist/hono/handler.mjs +58 -12
- package/dist/hono/handler.mjs.map +1 -1
- package/dist/hono/validator.cjs +1 -1
- package/dist/hono/validator.cjs.map +1 -1
- package/dist/hono/validator.d.cts.map +1 -1
- package/dist/hono/validator.d.mts.map +1 -1
- package/dist/hono/validator.mjs +1 -1
- package/dist/hono/validator.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/iso/{iso_3601_1.cjs → iso-3601-1.cjs} +2 -2
- package/dist/iso/{iso_3601_1.cjs.map → iso-3601-1.cjs.map} +1 -1
- package/dist/iso/{iso_3601_1.d.mts → iso-3601-1.d.cts} +2 -2
- package/dist/iso/iso-3601-1.d.cts.map +1 -0
- package/dist/iso/{iso_3601_1.d.cts → iso-3601-1.d.mts} +2 -2
- package/dist/iso/iso-3601-1.d.mts.map +1 -0
- package/dist/iso/{iso_3601_1.mjs → iso-3601-1.mjs} +2 -2
- package/dist/iso/{iso_3601_1.mjs.map → iso-3601-1.mjs.map} +1 -1
- package/dist/polyfills/index.d.cts +1 -1
- package/dist/polyfills/index.d.mts +1 -1
- package/dist/response.cjs +3 -2
- package/dist/response.cjs.map +1 -1
- package/dist/response.d.cts.map +1 -1
- package/dist/response.d.mts.map +1 -1
- package/dist/response.mjs +3 -2
- package/dist/response.mjs.map +1 -1
- package/package.json +4 -4
- package/dist/iso/iso_3601_1.d.cts.map +0 -1
- package/dist/iso/iso_3601_1.d.mts.map +0 -1
package/dist/hono/csrf.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csrf.mjs","names":[],"sources":["../../src/hono/csrf.ts"],"sourcesContent":["import { timingSafeEqual } from 'node:crypto';\nimport type { MiddlewareHandler } from 'hono';\nimport { getCookie } from 'hono/cookie';\nimport { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\n\ntype HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\n\nexport type CSRFIgnoreRule = string | { path: string; methods?: [HTTPMethod, ...HTTPMethod[]] };\n\nexport interface CSRFConfig {\n /**\n * Cookie name for CSRF token\n * @default 'XSRF-TOKEN'\n */\n cookieName?: string;\n\n /**\n * Header name for CSRF token\n * @default 'X-XSRF-TOKEN'\n */\n headerName?: string;\n\n /**\n * Ignore rules for specific paths and methods\n * @example\n * [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' }, // ignores all methods\n * ]\n */\n ignores?: CSRFIgnoreRule[];\n\n /**\n * Skip CSRF check for these methods\n * @default ['GET', 'HEAD', 'OPTIONS']\n */\n safeMethods?: HTTPMethod[];\n\n /**\n * Origin allowed to bypass CSRF check\n * @default undefined\n */\n origin?: string[];\n\n /**\n * Sec-Fetch-Site allowed to bypass CSRF check\n * @default undefined\n */\n secFetchSite?: Array<'same-origin' | 'same-site' | 'none' | 'cross-origin'>;\n\n /**\n * Custom error message\n * @default 'CSRF token validation failed'\n */\n errorMessage?: string;\n}\n\n/** use timing safe compare to prevent timing attack */\nfunction safeCompare(a: string, b: string): boolean {\n if (typeof a !== 'string' || typeof b !== 'string') return false;\n if (a.length === 0 || b.length === 0) return false;\n\n const bufferA = Buffer.from(a, 'utf-8');\n const bufferB = Buffer.from(b, 'utf-8');\n if (bufferA.length !== bufferB.length) return false;\n return timingSafeEqual(bufferA, bufferB);\n}\n\n/**\n * Create CSRF protection middleware\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { csrf } from '@shware/http/hono';\n *\n * const app = new Hono();\n *\n * // basic usage\n * app.use(csrf());\n *\n * // with configuration\n * app.use(csrf({\n * cookieName: 'csrf-token',\n * headerName: 'X-CSRF-Token',\n * ignores: [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' },\n * ]\n * }));\n * ```\n */\nexport function csrf(config: CSRFConfig = {}): MiddlewareHandler {\n const cookieName = config.cookieName ?? 'XSRF-TOKEN';\n const headerName = config.headerName ?? 'X-XSRF-TOKEN';\n const safeMethods = new Set(config.safeMethods ?? ['GET', 'HEAD', 'OPTIONS']);\n const errorMessage = config.errorMessage ?? 'CSRF token validation failed';\n\n // initialize router for matching ignore rules\n const router = new SmartRouter<boolean>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n // register ignore rules\n if (config.ignores) {\n for (const rule of config.ignores) {\n if (typeof rule === 'string') {\n router.add(METHOD_NAME_ALL, rule, true);\n } else if (rule.methods && rule.methods.length > 0) {\n for (const method of rule.methods) {\n router.add(method, rule.path, true);\n }\n } else {\n // if no methods are specified, ignore all methods\n router.add(METHOD_NAME_ALL, rule.path, true);\n }\n }\n }\n\n // return middleware\n return async (c, next) => {\n const method = c.req.method;\n const path = c.req.path;\n\n // check if the request should be ignored\n // 1. ignore safe methods\n if (safeMethods.has(method)) {\n await next();\n return;\n }\n\n // 2. ignore configured origin\n if (config.origin
|
|
1
|
+
{"version":3,"file":"csrf.mjs","names":[],"sources":["../../src/hono/csrf.ts"],"sourcesContent":["import { timingSafeEqual } from 'node:crypto';\nimport type { MiddlewareHandler } from 'hono';\nimport { getCookie } from 'hono/cookie';\nimport { METHOD_NAME_ALL } from 'hono/router';\nimport { RegExpRouter } from 'hono/router/reg-exp-router';\nimport { SmartRouter } from 'hono/router/smart-router';\nimport { TrieRouter } from 'hono/router/trie-router';\nimport { Status } from '../error/status';\n\ntype HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\n\nexport type CSRFIgnoreRule = string | { path: string; methods?: [HTTPMethod, ...HTTPMethod[]] };\n\nexport interface CSRFConfig {\n /**\n * Cookie name for CSRF token\n * @default 'XSRF-TOKEN'\n */\n cookieName?: string;\n\n /**\n * Header name for CSRF token\n * @default 'X-XSRF-TOKEN'\n */\n headerName?: string;\n\n /**\n * Ignore rules for specific paths and methods\n * @example\n * [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' }, // ignores all methods\n * ]\n */\n ignores?: CSRFIgnoreRule[];\n\n /**\n * Skip CSRF check for these methods\n * @default ['GET', 'HEAD', 'OPTIONS']\n */\n safeMethods?: HTTPMethod[];\n\n /**\n * Origin allowed to bypass CSRF check\n * @default undefined\n */\n origin?: string[];\n\n /**\n * Sec-Fetch-Site allowed to bypass CSRF check\n * @default undefined\n */\n secFetchSite?: Array<'same-origin' | 'same-site' | 'none' | 'cross-origin'>;\n\n /**\n * Custom error message\n * @default 'CSRF token validation failed'\n */\n errorMessage?: string;\n}\n\n/** use timing safe compare to prevent timing attack */\nfunction safeCompare(a: string, b: string): boolean {\n if (typeof a !== 'string' || typeof b !== 'string') return false;\n if (a.length === 0 || b.length === 0) return false;\n\n const bufferA = Buffer.from(a, 'utf-8');\n const bufferB = Buffer.from(b, 'utf-8');\n if (bufferA.length !== bufferB.length) return false;\n return timingSafeEqual(bufferA, bufferB);\n}\n\n/**\n * Create CSRF protection middleware\n *\n * @example\n * ```ts\n * import { Hono } from 'hono';\n * import { csrf } from '@shware/http/hono';\n *\n * const app = new Hono();\n *\n * // basic usage\n * app.use(csrf());\n *\n * // with configuration\n * app.use(csrf({\n * cookieName: 'csrf-token',\n * headerName: 'X-CSRF-Token',\n * ignores: [\n * { path: '/api/webhook/*', methods: ['POST'] },\n * { path: '/auth/apple/callback' },\n * ]\n * }));\n * ```\n */\nexport function csrf(config: CSRFConfig = {}): MiddlewareHandler {\n const cookieName = config.cookieName ?? 'XSRF-TOKEN';\n const headerName = config.headerName ?? 'X-XSRF-TOKEN';\n const safeMethods = new Set(config.safeMethods ?? ['GET', 'HEAD', 'OPTIONS']);\n const errorMessage = config.errorMessage ?? 'CSRF token validation failed';\n\n // initialize router for matching ignore rules\n const router = new SmartRouter<boolean>({\n routers: [new RegExpRouter(), new TrieRouter()],\n });\n\n // register ignore rules\n if (config.ignores) {\n for (const rule of config.ignores) {\n if (typeof rule === 'string') {\n router.add(METHOD_NAME_ALL, rule, true);\n } else if (rule.methods && rule.methods.length > 0) {\n for (const method of rule.methods) {\n router.add(method, rule.path, true);\n }\n } else {\n // if no methods are specified, ignore all methods\n router.add(METHOD_NAME_ALL, rule.path, true);\n }\n }\n }\n\n // return middleware\n return async (c, next) => {\n const method = c.req.method;\n const path = c.req.path;\n\n // check if the request should be ignored\n // 1. ignore safe methods\n if (safeMethods.has(method)) {\n await next();\n return;\n }\n\n // 2. ignore configured origin\n if (config.origin?.includes(c.req.header('origin') ?? '')) {\n await next();\n return;\n }\n\n // 3. ignore configured secFetchSite\n if (config.secFetchSite?.includes((c.req.header('sec-fetch-site') ?? '') as never)) {\n await next();\n return;\n }\n\n // 4. ignore configured ignore rules\n const [matched] = router.match(method, path);\n if (matched.length > 0) {\n await next();\n return;\n }\n\n const cookieToken = getCookie(c, cookieName);\n const headerToken = c.req.header(headerName);\n\n if (!cookieToken || !headerToken) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n if (!safeCompare(cookieToken, headerToken)) {\n throw Status.permissionDenied(errorMessage).error();\n }\n\n await next();\n };\n}\n"],"mappings":";;;;;;;;;AA8DA,SAAS,YAAY,GAAW,GAAoB;CAClD,IAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU,OAAO;CAC3D,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GAAG,OAAO;CAE7C,MAAM,UAAU,OAAO,KAAK,GAAG,OAAO;CACtC,MAAM,UAAU,OAAO,KAAK,GAAG,OAAO;CACtC,IAAI,QAAQ,WAAW,QAAQ,QAAQ,OAAO;CAC9C,OAAO,gBAAgB,SAAS,OAAO;AACzC;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,KAAK,SAAqB,CAAC,GAAsB;CAC/D,MAAM,aAAa,OAAO,cAAc;CACxC,MAAM,aAAa,OAAO,cAAc;CACxC,MAAM,cAAc,IAAI,IAAI,OAAO,eAAe;EAAC;EAAO;EAAQ;CAAS,CAAC;CAC5E,MAAM,eAAe,OAAO,gBAAgB;CAG5C,MAAM,SAAS,IAAI,YAAqB,EACtC,SAAS,CAAC,IAAI,aAAa,GAAG,IAAI,WAAW,CAAC,EAChD,CAAC;CAGD,IAAI,OAAO,SACT,KAAK,MAAM,QAAQ,OAAO,SACxB,IAAI,OAAO,SAAS,UAClB,OAAO,IAAI,iBAAiB,MAAM,IAAI;MACjC,IAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,GAC/C,KAAK,MAAM,UAAU,KAAK,SACxB,OAAO,IAAI,QAAQ,KAAK,MAAM,IAAI;MAIpC,OAAO,IAAI,iBAAiB,KAAK,MAAM,IAAI;CAMjD,OAAO,OAAO,GAAG,SAAS;EACxB,MAAM,SAAS,EAAE,IAAI;EACrB,MAAM,OAAO,EAAE,IAAI;EAInB,IAAI,YAAY,IAAI,MAAM,GAAG;GAC3B,MAAM,KAAK;GACX;EACF;EAGA,IAAI,OAAO,QAAQ,SAAS,EAAE,IAAI,OAAO,QAAQ,KAAK,EAAE,GAAG;GACzD,MAAM,KAAK;GACX;EACF;EAGA,IAAI,OAAO,cAAc,SAAU,EAAE,IAAI,OAAO,gBAAgB,KAAK,EAAY,GAAG;GAClF,MAAM,KAAK;GACX;EACF;EAGA,MAAM,CAAC,WAAW,OAAO,MAAM,QAAQ,IAAI;EAC3C,IAAI,QAAQ,SAAS,GAAG;GACtB,MAAM,KAAK;GACX;EACF;EAEA,MAAM,cAAc,UAAU,GAAG,UAAU;EAC3C,MAAM,cAAc,EAAE,IAAI,OAAO,UAAU;EAE3C,IAAI,CAAC,eAAe,CAAC,aACnB,MAAM,OAAO,iBAAiB,YAAY,CAAC,CAAC,MAAM;EAGpD,IAAI,CAAC,YAAY,aAAa,WAAW,GACvC,MAAM,OAAO,iBAAiB,YAAY,CAAC,CAAC,MAAM;EAGpD,MAAM,KAAK;CACb;AACF"}
|
package/dist/hono/handler.cjs
CHANGED
|
@@ -1,10 +1,46 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_error_detail = require("../error/detail.cjs");
|
|
3
3
|
const require_error_status = require("../error/status.cjs");
|
|
4
|
+
let _shware_utils = require("@shware/utils");
|
|
5
|
+
let hono_http_exception = require("hono/http-exception");
|
|
4
6
|
//#region src/hono/handler.ts
|
|
7
|
+
/**
|
|
8
|
+
* `Code` maps a name to an HTTP status, and that mapping is not injective: 400 is INVALID_ARGUMENT,
|
|
9
|
+
* FAILED_PRECONDITION and OUT_OF_RANGE alike. Reversing it therefore needs a tiebreaker for the
|
|
10
|
+
* statuses several codes share — the rest is derived, so new entries in `Code` come along for free.
|
|
11
|
+
*/
|
|
12
|
+
const CANONICAL_CODE = {
|
|
13
|
+
400: "INVALID_ARGUMENT",
|
|
14
|
+
409: "ALREADY_EXISTS",
|
|
15
|
+
500: "INTERNAL"
|
|
16
|
+
};
|
|
17
|
+
const CODE_BY_HTTP_STATUS = {
|
|
18
|
+
...Object.fromEntries(Object.entries(require_error_status.Code).map(([name, status]) => [status, name])),
|
|
19
|
+
...CANONICAL_CODE
|
|
20
|
+
};
|
|
21
|
+
/** Canonical code for errors that only carry an HTTP status, such as hono's `HTTPException`. */
|
|
22
|
+
function toStatusCode(status, message) {
|
|
23
|
+
const code = CODE_BY_HTTP_STATUS[status] ?? (status < 500 ? "INVALID_ARGUMENT" : "INTERNAL");
|
|
24
|
+
return require_error_status.StatusCode.of(code, (0, _shware_utils.hasText)(message) ? message : void 0);
|
|
25
|
+
}
|
|
26
|
+
function summarize(error) {
|
|
27
|
+
if (error instanceof Error) return `${error.name}: ${error.message}`;
|
|
28
|
+
return String(error);
|
|
29
|
+
}
|
|
5
30
|
function isAxiosError(payload) {
|
|
6
31
|
return payload !== null && typeof payload === "object" && "isAxiosError" in payload && payload.isAxiosError === true;
|
|
7
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* `instanceof` alone is not enough: two copies of this package (duplicated in a lockfile, or one
|
|
35
|
+
* bundled into a dependency) produce distinct classes, and `Status.adapter` may swap in a
|
|
36
|
+
* host-defined error class entirely. Fall back to recognizing the error by shape.
|
|
37
|
+
*/
|
|
38
|
+
function isStatusError(payload) {
|
|
39
|
+
if (payload instanceof require_error_status.StatusError) return true;
|
|
40
|
+
if (payload === null || typeof payload !== "object") return false;
|
|
41
|
+
const { status, body } = payload;
|
|
42
|
+
return typeof status === "number" && typeof body?.error?.code === "number";
|
|
43
|
+
}
|
|
8
44
|
function errorHandler(error, c) {
|
|
9
45
|
const requestId = c.get("requestId");
|
|
10
46
|
const servingData = `${c.req.method}: ${c.req.path}`;
|
|
@@ -12,16 +48,26 @@ function errorHandler(error, c) {
|
|
|
12
48
|
requestId,
|
|
13
49
|
servingData
|
|
14
50
|
});
|
|
15
|
-
if (error
|
|
16
|
-
error.body
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
51
|
+
if (isStatusError(error)) {
|
|
52
|
+
const body = error.body ?? require_error_status.Status.internal().body();
|
|
53
|
+
body.error.details.push(...details.list);
|
|
54
|
+
(error.status >= 500 ? console.error : console.warn)(servingData, JSON.stringify(body.error));
|
|
55
|
+
return c.json(body, error.status);
|
|
56
|
+
}
|
|
57
|
+
if (c.req.raw.signal.aborted) {
|
|
58
|
+
console.warn(`Client closed request: ${servingData}`, summarize(error));
|
|
59
|
+
return require_error_status.Status.cancelled().response(details);
|
|
60
|
+
}
|
|
61
|
+
if (error instanceof hono_http_exception.HTTPException) {
|
|
62
|
+
(error.status >= 500 ? console.error : console.warn)(`HTTP exception: ${servingData}`, error.status, error.message);
|
|
63
|
+
if (error.res) return error.res;
|
|
64
|
+
return toStatusCode(error.status, error.message).response(details);
|
|
21
65
|
}
|
|
22
66
|
if (isAxiosError(error)) {
|
|
23
|
-
console.error({
|
|
24
|
-
|
|
67
|
+
console.error(`Axios error: ${servingData}`, {
|
|
68
|
+
requestId,
|
|
69
|
+
code: error.code,
|
|
70
|
+
status: error.status ?? error.response?.status,
|
|
25
71
|
message: error.message,
|
|
26
72
|
request: {
|
|
27
73
|
method: error.config?.method,
|
|
@@ -32,11 +78,12 @@ function errorHandler(error, c) {
|
|
|
32
78
|
});
|
|
33
79
|
return require_error_status.Status.internal("Axios error").response(details);
|
|
34
80
|
}
|
|
35
|
-
console.error(`Unknown error: ${servingData}`, error);
|
|
81
|
+
console.error(`Unknown error: ${servingData}`, requestId, error);
|
|
36
82
|
return require_error_status.Status.internal("Unknown error").response(details);
|
|
37
83
|
}
|
|
38
84
|
//#endregion
|
|
39
85
|
exports.errorHandler = errorHandler;
|
|
40
86
|
exports.isAxiosError = isAxiosError;
|
|
87
|
+
exports.isStatusError = isStatusError;
|
|
41
88
|
|
|
42
89
|
//# sourceMappingURL=handler.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.cjs","names":["
|
|
1
|
+
{"version":3,"file":"handler.cjs","names":["Code","StatusCode","StatusError","Details","Status","HTTPException"],"sources":["../../src/hono/handler.ts"],"sourcesContent":["import { hasText } from '@shware/utils';\nimport type { Context } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport type { RequestIdVariables } from 'hono/request-id';\nimport type { Bindings, HTTPResponseError } from 'hono/types';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { Details } from '../error/detail';\nimport { Code, Status, StatusCode, StatusError } from '../error/status';\n\nexport type Env = {\n Variables: RequestIdVariables;\n Bindings?: Bindings;\n};\n\ntype AxiosError = {\n code?: string;\n cause?: unknown;\n status?: number;\n message?: string;\n isAxiosError: boolean;\n response?: {\n data: unknown;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n };\n config?: { url?: string; data?: unknown; method?: string; headers?: Record<string, string> };\n};\n\n/**\n * `Code` maps a name to an HTTP status, and that mapping is not injective: 400 is INVALID_ARGUMENT,\n * FAILED_PRECONDITION and OUT_OF_RANGE alike. Reversing it therefore needs a tiebreaker for the\n * statuses several codes share — the rest is derived, so new entries in `Code` come along for free.\n */\nconst CANONICAL_CODE: Record<number, keyof typeof Code> = {\n 400: 'INVALID_ARGUMENT',\n 409: 'ALREADY_EXISTS',\n 500: 'INTERNAL',\n};\n\nconst CODE_BY_HTTP_STATUS: Record<number, keyof typeof Code> = {\n ...Object.fromEntries(Object.entries(Code).map(([name, status]) => [status, name])),\n ...CANONICAL_CODE,\n};\n\n/** Canonical code for errors that only carry an HTTP status, such as hono's `HTTPException`. */\nfunction toStatusCode(status: number, message?: string): StatusCode {\n const code = CODE_BY_HTTP_STATUS[status] ?? (status < 500 ? 'INVALID_ARGUMENT' : 'INTERNAL');\n return StatusCode.of(code, hasText(message) ? message : undefined);\n}\n\nfunction summarize(error: unknown): string {\n if (error instanceof Error) return `${error.name}: ${error.message}`;\n return String(error);\n}\n\nexport function isAxiosError(payload: unknown): payload is AxiosError {\n return (\n payload !== null &&\n typeof payload === 'object' &&\n 'isAxiosError' in payload &&\n payload.isAxiosError === true\n );\n}\n\n/**\n * `instanceof` alone is not enough: two copies of this package (duplicated in a lockfile, or one\n * bundled into a dependency) produce distinct classes, and `Status.adapter` may swap in a\n * host-defined error class entirely. Fall back to recognizing the error by shape.\n */\nexport function isStatusError(payload: unknown): payload is StatusError {\n if (payload instanceof StatusError) return true;\n if (payload === null || typeof payload !== 'object') return false;\n const { status, body } = payload as { status?: unknown; body?: { error?: { code?: unknown } } };\n return typeof status === 'number' && typeof body?.error?.code === 'number';\n}\n\nexport function errorHandler<E extends Env = never>(\n error: Error | HTTPResponseError,\n c: Context<E>\n): Response | Promise<Response> {\n const requestId = c.get('requestId');\n const servingData = `${c.req.method}: ${c.req.path}`;\n const details = Details.new().requestInfo({ requestId, servingData });\n\n if (isStatusError(error)) {\n const body = error.body ?? Status.internal().body();\n body.error.details.push(...details.list);\n // Only 5xx is a server fault; logging expected 4xx at error level drowns out the real ones.\n // Field violations travel inside `details`, so one line carries the whole error.\n const log = error.status >= 500 ? console.error : console.warn;\n log(servingData, JSON.stringify(body.error));\n return c.json(body, error.status as ContentfulStatusCode);\n }\n\n // The client vanished mid-request: tab closed, navigation, or an aborted fetch. Whatever we\n // return is discarded, and nothing failed on our side, so keep it to one terse line. Shows up\n // in local dev because the request body is streamed straight off the socket — a truncated body\n // fails to parse; platforms that buffer the whole request before invoking (API Gateway, Lambda\n // function URLs) never hand us a partial request in the first place.\n if (c.req.raw.signal.aborted) {\n console.warn(`Client closed request: ${servingData}`, summarize(error));\n return Status.cancelled().response(details);\n }\n\n if (error instanceof HTTPException) {\n // Middleware such as `bearerAuth` attaches a prepared response carrying headers the client\n // needs (`WWW-Authenticate`, …); hand that back untouched instead of re-wrapping it.\n const log = error.status >= 500 ? console.error : console.warn;\n log(`HTTP exception: ${servingData}`, error.status, error.message);\n if (error.res) return error.res;\n return toStatusCode(error.status, error.message).response(details);\n }\n\n if (isAxiosError(error)) {\n console.error(`Axios error: ${servingData}`, {\n requestId,\n code: error.code,\n status: error.status ?? error.response?.status,\n message: error.message,\n request: {\n method: error.config?.method,\n url: error.config?.url,\n data: error.config?.data,\n },\n response: { data: error.response?.data },\n });\n return Status.internal('Axios error').response(details);\n }\n\n console.error(`Unknown error: ${servingData}`, requestId, error);\n return Status.internal('Unknown error').response(details);\n}\n"],"mappings":";;;;;;;;;;;AAkCA,MAAM,iBAAoD;CACxD,KAAK;CACL,KAAK;CACL,KAAK;AACP;AAEA,MAAM,sBAAyD;CAC7D,GAAG,OAAO,YAAY,OAAO,QAAQA,qBAAAA,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY,CAAC,QAAQ,IAAI,CAAC,CAAC;CAClF,GAAG;AACL;;AAGA,SAAS,aAAa,QAAgB,SAA8B;CAClE,MAAM,OAAO,oBAAoB,YAAY,SAAS,MAAM,qBAAqB;CACjF,OAAOC,qBAAAA,WAAW,GAAG,OAAA,GAAA,cAAA,QAAA,CAAc,OAAO,IAAI,UAAU,KAAA,CAAS;AACnE;AAEA,SAAS,UAAU,OAAwB;CACzC,IAAI,iBAAiB,OAAO,OAAO,GAAG,MAAM,KAAK,IAAI,MAAM;CAC3D,OAAO,OAAO,KAAK;AACrB;AAEA,SAAgB,aAAa,SAAyC;CACpE,OACE,YAAY,QACZ,OAAO,YAAY,YACnB,kBAAkB,WAClB,QAAQ,iBAAiB;AAE7B;;;;;;AAOA,SAAgB,cAAc,SAA0C;CACtE,IAAI,mBAAmBC,qBAAAA,aAAa,OAAO;CAC3C,IAAI,YAAY,QAAQ,OAAO,YAAY,UAAU,OAAO;CAC5D,MAAM,EAAE,QAAQ,SAAS;CACzB,OAAO,OAAO,WAAW,YAAY,OAAO,MAAM,OAAO,SAAS;AACpE;AAEA,SAAgB,aACd,OACA,GAC8B;CAC9B,MAAM,YAAY,EAAE,IAAI,WAAW;CACnC,MAAM,cAAc,GAAG,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI;CAC9C,MAAM,UAAUC,qBAAAA,QAAQ,IAAI,CAAC,CAAC,YAAY;EAAE;EAAW;CAAY,CAAC;CAEpE,IAAI,cAAc,KAAK,GAAG;EACxB,MAAM,OAAO,MAAM,QAAQC,qBAAAA,OAAO,SAAS,CAAC,CAAC,KAAK;EAClD,KAAK,MAAM,QAAQ,KAAK,GAAG,QAAQ,IAAI;EAIvC,CADY,MAAM,UAAU,MAAM,QAAQ,QAAQ,QAAQ,KAAA,CACtD,aAAa,KAAK,UAAU,KAAK,KAAK,CAAC;EAC3C,OAAO,EAAE,KAAK,MAAM,MAAM,MAA8B;CAC1D;CAOA,IAAI,EAAE,IAAI,IAAI,OAAO,SAAS;EAC5B,QAAQ,KAAK,0BAA0B,eAAe,UAAU,KAAK,CAAC;EACtE,OAAOA,qBAAAA,OAAO,UAAU,CAAC,CAAC,SAAS,OAAO;CAC5C;CAEA,IAAI,iBAAiBC,oBAAAA,eAAe;EAIlC,CADY,MAAM,UAAU,MAAM,QAAQ,QAAQ,QAAQ,KAAA,CACtD,mBAAmB,eAAe,MAAM,QAAQ,MAAM,OAAO;EACjE,IAAI,MAAM,KAAK,OAAO,MAAM;EAC5B,OAAO,aAAa,MAAM,QAAQ,MAAM,OAAO,CAAC,CAAC,SAAS,OAAO;CACnE;CAEA,IAAI,aAAa,KAAK,GAAG;EACvB,QAAQ,MAAM,gBAAgB,eAAe;GAC3C;GACA,MAAM,MAAM;GACZ,QAAQ,MAAM,UAAU,MAAM,UAAU;GACxC,SAAS,MAAM;GACf,SAAS;IACP,QAAQ,MAAM,QAAQ;IACtB,KAAK,MAAM,QAAQ;IACnB,MAAM,MAAM,QAAQ;GACtB;GACA,UAAU,EAAE,MAAM,MAAM,UAAU,KAAK;EACzC,CAAC;EACD,OAAOD,qBAAAA,OAAO,SAAS,aAAa,CAAC,CAAC,SAAS,OAAO;CACxD;CAEA,QAAQ,MAAM,kBAAkB,eAAe,WAAW,KAAK;CAC/D,OAAOA,qBAAAA,OAAO,SAAS,eAAe,CAAC,CAAC,SAAS,OAAO;AAC1D"}
|
package/dist/hono/handler.d.cts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StatusError } from "../error/status.cjs";
|
|
1
2
|
import { Context } from "hono";
|
|
2
3
|
import { RequestIdVariables } from "hono/request-id";
|
|
3
4
|
import { Bindings, HTTPResponseError } from "hono/types";
|
|
@@ -26,7 +27,13 @@ type AxiosError = {
|
|
|
26
27
|
};
|
|
27
28
|
};
|
|
28
29
|
declare function isAxiosError(payload: unknown): payload is AxiosError;
|
|
30
|
+
/**
|
|
31
|
+
* `instanceof` alone is not enough: two copies of this package (duplicated in a lockfile, or one
|
|
32
|
+
* bundled into a dependency) produce distinct classes, and `Status.adapter` may swap in a
|
|
33
|
+
* host-defined error class entirely. Fall back to recognizing the error by shape.
|
|
34
|
+
*/
|
|
35
|
+
declare function isStatusError(payload: unknown): payload is StatusError;
|
|
29
36
|
declare function errorHandler<E extends Env = never>(error: Error | HTTPResponseError, c: Context<E>): Response | Promise<Response>;
|
|
30
37
|
//#endregion
|
|
31
|
-
export { Env, errorHandler, isAxiosError };
|
|
38
|
+
export { Env, errorHandler, isAxiosError, isStatusError };
|
|
32
39
|
//# sourceMappingURL=handler.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.cts","names":[],"sources":["../../src/hono/handler.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"handler.d.cts","names":[],"sources":["../../src/hono/handler.ts"],"mappings":";;;;;KASY;EACV,WAAW;EACX,WAAW;;KAGR;EACH;EACA;EACA;EACA;EACA;EACA;IACE;IACA;IACA;IACA,SAAS;;EAEX;IAAW;IAAc;IAAgB;IAAiB,UAAU;;;iBA8BtD,aAAa,mBAAmB,WAAW;;;;;;iBAc3C,cAAc,mBAAmB,WAAW;iBAO5C,aAAa,UAAU,aACrC,OAAO,QAAQ,mBACf,GAAG,QAAQ,KACV,WAAW,QAAQ"}
|
package/dist/hono/handler.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StatusError } from "../error/status.mjs";
|
|
1
2
|
import { Context } from "hono";
|
|
2
3
|
import { RequestIdVariables } from "hono/request-id";
|
|
3
4
|
import { Bindings, HTTPResponseError } from "hono/types";
|
|
@@ -26,7 +27,13 @@ type AxiosError = {
|
|
|
26
27
|
};
|
|
27
28
|
};
|
|
28
29
|
declare function isAxiosError(payload: unknown): payload is AxiosError;
|
|
30
|
+
/**
|
|
31
|
+
* `instanceof` alone is not enough: two copies of this package (duplicated in a lockfile, or one
|
|
32
|
+
* bundled into a dependency) produce distinct classes, and `Status.adapter` may swap in a
|
|
33
|
+
* host-defined error class entirely. Fall back to recognizing the error by shape.
|
|
34
|
+
*/
|
|
35
|
+
declare function isStatusError(payload: unknown): payload is StatusError;
|
|
29
36
|
declare function errorHandler<E extends Env = never>(error: Error | HTTPResponseError, c: Context<E>): Response | Promise<Response>;
|
|
30
37
|
//#endregion
|
|
31
|
-
export { Env, errorHandler, isAxiosError };
|
|
38
|
+
export { Env, errorHandler, isAxiosError, isStatusError };
|
|
32
39
|
//# sourceMappingURL=handler.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.mts","names":[],"sources":["../../src/hono/handler.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"handler.d.mts","names":[],"sources":["../../src/hono/handler.ts"],"mappings":";;;;;KASY;EACV,WAAW;EACX,WAAW;;KAGR;EACH;EACA;EACA;EACA;EACA;EACA;IACE;IACA;IACA;IACA,SAAS;;EAEX;IAAW;IAAc;IAAgB;IAAiB,UAAU;;;iBA8BtD,aAAa,mBAAmB,WAAW;;;;;;iBAc3C,cAAc,mBAAmB,WAAW;iBAO5C,aAAa,UAAU,aACrC,OAAO,QAAQ,mBACf,GAAG,QAAQ,KACV,WAAW,QAAQ"}
|
package/dist/hono/handler.mjs
CHANGED
|
@@ -1,9 +1,45 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Status, StatusError } from "../error/status.mjs";
|
|
1
|
+
import { Details } from "../error/detail.mjs";
|
|
2
|
+
import { Code, Status, StatusCode, StatusError } from "../error/status.mjs";
|
|
3
|
+
import { hasText } from "@shware/utils";
|
|
4
|
+
import { HTTPException } from "hono/http-exception";
|
|
3
5
|
//#region src/hono/handler.ts
|
|
6
|
+
/**
|
|
7
|
+
* `Code` maps a name to an HTTP status, and that mapping is not injective: 400 is INVALID_ARGUMENT,
|
|
8
|
+
* FAILED_PRECONDITION and OUT_OF_RANGE alike. Reversing it therefore needs a tiebreaker for the
|
|
9
|
+
* statuses several codes share — the rest is derived, so new entries in `Code` come along for free.
|
|
10
|
+
*/
|
|
11
|
+
const CANONICAL_CODE = {
|
|
12
|
+
400: "INVALID_ARGUMENT",
|
|
13
|
+
409: "ALREADY_EXISTS",
|
|
14
|
+
500: "INTERNAL"
|
|
15
|
+
};
|
|
16
|
+
const CODE_BY_HTTP_STATUS = {
|
|
17
|
+
...Object.fromEntries(Object.entries(Code).map(([name, status]) => [status, name])),
|
|
18
|
+
...CANONICAL_CODE
|
|
19
|
+
};
|
|
20
|
+
/** Canonical code for errors that only carry an HTTP status, such as hono's `HTTPException`. */
|
|
21
|
+
function toStatusCode(status, message) {
|
|
22
|
+
const code = CODE_BY_HTTP_STATUS[status] ?? (status < 500 ? "INVALID_ARGUMENT" : "INTERNAL");
|
|
23
|
+
return StatusCode.of(code, hasText(message) ? message : void 0);
|
|
24
|
+
}
|
|
25
|
+
function summarize(error) {
|
|
26
|
+
if (error instanceof Error) return `${error.name}: ${error.message}`;
|
|
27
|
+
return String(error);
|
|
28
|
+
}
|
|
4
29
|
function isAxiosError(payload) {
|
|
5
30
|
return payload !== null && typeof payload === "object" && "isAxiosError" in payload && payload.isAxiosError === true;
|
|
6
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* `instanceof` alone is not enough: two copies of this package (duplicated in a lockfile, or one
|
|
34
|
+
* bundled into a dependency) produce distinct classes, and `Status.adapter` may swap in a
|
|
35
|
+
* host-defined error class entirely. Fall back to recognizing the error by shape.
|
|
36
|
+
*/
|
|
37
|
+
function isStatusError(payload) {
|
|
38
|
+
if (payload instanceof StatusError) return true;
|
|
39
|
+
if (payload === null || typeof payload !== "object") return false;
|
|
40
|
+
const { status, body } = payload;
|
|
41
|
+
return typeof status === "number" && typeof body?.error?.code === "number";
|
|
42
|
+
}
|
|
7
43
|
function errorHandler(error, c) {
|
|
8
44
|
const requestId = c.get("requestId");
|
|
9
45
|
const servingData = `${c.req.method}: ${c.req.path}`;
|
|
@@ -11,16 +47,26 @@ function errorHandler(error, c) {
|
|
|
11
47
|
requestId,
|
|
12
48
|
servingData
|
|
13
49
|
});
|
|
14
|
-
if (error
|
|
15
|
-
error.body
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
50
|
+
if (isStatusError(error)) {
|
|
51
|
+
const body = error.body ?? Status.internal().body();
|
|
52
|
+
body.error.details.push(...details.list);
|
|
53
|
+
(error.status >= 500 ? console.error : console.warn)(servingData, JSON.stringify(body.error));
|
|
54
|
+
return c.json(body, error.status);
|
|
55
|
+
}
|
|
56
|
+
if (c.req.raw.signal.aborted) {
|
|
57
|
+
console.warn(`Client closed request: ${servingData}`, summarize(error));
|
|
58
|
+
return Status.cancelled().response(details);
|
|
59
|
+
}
|
|
60
|
+
if (error instanceof HTTPException) {
|
|
61
|
+
(error.status >= 500 ? console.error : console.warn)(`HTTP exception: ${servingData}`, error.status, error.message);
|
|
62
|
+
if (error.res) return error.res;
|
|
63
|
+
return toStatusCode(error.status, error.message).response(details);
|
|
20
64
|
}
|
|
21
65
|
if (isAxiosError(error)) {
|
|
22
|
-
console.error({
|
|
23
|
-
|
|
66
|
+
console.error(`Axios error: ${servingData}`, {
|
|
67
|
+
requestId,
|
|
68
|
+
code: error.code,
|
|
69
|
+
status: error.status ?? error.response?.status,
|
|
24
70
|
message: error.message,
|
|
25
71
|
request: {
|
|
26
72
|
method: error.config?.method,
|
|
@@ -31,10 +77,10 @@ function errorHandler(error, c) {
|
|
|
31
77
|
});
|
|
32
78
|
return Status.internal("Axios error").response(details);
|
|
33
79
|
}
|
|
34
|
-
console.error(`Unknown error: ${servingData}`, error);
|
|
80
|
+
console.error(`Unknown error: ${servingData}`, requestId, error);
|
|
35
81
|
return Status.internal("Unknown error").response(details);
|
|
36
82
|
}
|
|
37
83
|
//#endregion
|
|
38
|
-
export { errorHandler, isAxiosError };
|
|
84
|
+
export { errorHandler, isAxiosError, isStatusError };
|
|
39
85
|
|
|
40
86
|
//# sourceMappingURL=handler.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.mjs","names":[],"sources":["../../src/hono/handler.ts"],"sourcesContent":["import type { Context } from 'hono';\nimport type { RequestIdVariables } from 'hono/request-id';\nimport type { Bindings, HTTPResponseError } from 'hono/types';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport {
|
|
1
|
+
{"version":3,"file":"handler.mjs","names":[],"sources":["../../src/hono/handler.ts"],"sourcesContent":["import { hasText } from '@shware/utils';\nimport type { Context } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport type { RequestIdVariables } from 'hono/request-id';\nimport type { Bindings, HTTPResponseError } from 'hono/types';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { Details } from '../error/detail';\nimport { Code, Status, StatusCode, StatusError } from '../error/status';\n\nexport type Env = {\n Variables: RequestIdVariables;\n Bindings?: Bindings;\n};\n\ntype AxiosError = {\n code?: string;\n cause?: unknown;\n status?: number;\n message?: string;\n isAxiosError: boolean;\n response?: {\n data: unknown;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n };\n config?: { url?: string; data?: unknown; method?: string; headers?: Record<string, string> };\n};\n\n/**\n * `Code` maps a name to an HTTP status, and that mapping is not injective: 400 is INVALID_ARGUMENT,\n * FAILED_PRECONDITION and OUT_OF_RANGE alike. Reversing it therefore needs a tiebreaker for the\n * statuses several codes share — the rest is derived, so new entries in `Code` come along for free.\n */\nconst CANONICAL_CODE: Record<number, keyof typeof Code> = {\n 400: 'INVALID_ARGUMENT',\n 409: 'ALREADY_EXISTS',\n 500: 'INTERNAL',\n};\n\nconst CODE_BY_HTTP_STATUS: Record<number, keyof typeof Code> = {\n ...Object.fromEntries(Object.entries(Code).map(([name, status]) => [status, name])),\n ...CANONICAL_CODE,\n};\n\n/** Canonical code for errors that only carry an HTTP status, such as hono's `HTTPException`. */\nfunction toStatusCode(status: number, message?: string): StatusCode {\n const code = CODE_BY_HTTP_STATUS[status] ?? (status < 500 ? 'INVALID_ARGUMENT' : 'INTERNAL');\n return StatusCode.of(code, hasText(message) ? message : undefined);\n}\n\nfunction summarize(error: unknown): string {\n if (error instanceof Error) return `${error.name}: ${error.message}`;\n return String(error);\n}\n\nexport function isAxiosError(payload: unknown): payload is AxiosError {\n return (\n payload !== null &&\n typeof payload === 'object' &&\n 'isAxiosError' in payload &&\n payload.isAxiosError === true\n );\n}\n\n/**\n * `instanceof` alone is not enough: two copies of this package (duplicated in a lockfile, or one\n * bundled into a dependency) produce distinct classes, and `Status.adapter` may swap in a\n * host-defined error class entirely. Fall back to recognizing the error by shape.\n */\nexport function isStatusError(payload: unknown): payload is StatusError {\n if (payload instanceof StatusError) return true;\n if (payload === null || typeof payload !== 'object') return false;\n const { status, body } = payload as { status?: unknown; body?: { error?: { code?: unknown } } };\n return typeof status === 'number' && typeof body?.error?.code === 'number';\n}\n\nexport function errorHandler<E extends Env = never>(\n error: Error | HTTPResponseError,\n c: Context<E>\n): Response | Promise<Response> {\n const requestId = c.get('requestId');\n const servingData = `${c.req.method}: ${c.req.path}`;\n const details = Details.new().requestInfo({ requestId, servingData });\n\n if (isStatusError(error)) {\n const body = error.body ?? Status.internal().body();\n body.error.details.push(...details.list);\n // Only 5xx is a server fault; logging expected 4xx at error level drowns out the real ones.\n // Field violations travel inside `details`, so one line carries the whole error.\n const log = error.status >= 500 ? console.error : console.warn;\n log(servingData, JSON.stringify(body.error));\n return c.json(body, error.status as ContentfulStatusCode);\n }\n\n // The client vanished mid-request: tab closed, navigation, or an aborted fetch. Whatever we\n // return is discarded, and nothing failed on our side, so keep it to one terse line. Shows up\n // in local dev because the request body is streamed straight off the socket — a truncated body\n // fails to parse; platforms that buffer the whole request before invoking (API Gateway, Lambda\n // function URLs) never hand us a partial request in the first place.\n if (c.req.raw.signal.aborted) {\n console.warn(`Client closed request: ${servingData}`, summarize(error));\n return Status.cancelled().response(details);\n }\n\n if (error instanceof HTTPException) {\n // Middleware such as `bearerAuth` attaches a prepared response carrying headers the client\n // needs (`WWW-Authenticate`, …); hand that back untouched instead of re-wrapping it.\n const log = error.status >= 500 ? console.error : console.warn;\n log(`HTTP exception: ${servingData}`, error.status, error.message);\n if (error.res) return error.res;\n return toStatusCode(error.status, error.message).response(details);\n }\n\n if (isAxiosError(error)) {\n console.error(`Axios error: ${servingData}`, {\n requestId,\n code: error.code,\n status: error.status ?? error.response?.status,\n message: error.message,\n request: {\n method: error.config?.method,\n url: error.config?.url,\n data: error.config?.data,\n },\n response: { data: error.response?.data },\n });\n return Status.internal('Axios error').response(details);\n }\n\n console.error(`Unknown error: ${servingData}`, requestId, error);\n return Status.internal('Unknown error').response(details);\n}\n"],"mappings":";;;;;;;;;;AAkCA,MAAM,iBAAoD;CACxD,KAAK;CACL,KAAK;CACL,KAAK;AACP;AAEA,MAAM,sBAAyD;CAC7D,GAAG,OAAO,YAAY,OAAO,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY,CAAC,QAAQ,IAAI,CAAC,CAAC;CAClF,GAAG;AACL;;AAGA,SAAS,aAAa,QAAgB,SAA8B;CAClE,MAAM,OAAO,oBAAoB,YAAY,SAAS,MAAM,qBAAqB;CACjF,OAAO,WAAW,GAAG,MAAM,QAAQ,OAAO,IAAI,UAAU,KAAA,CAAS;AACnE;AAEA,SAAS,UAAU,OAAwB;CACzC,IAAI,iBAAiB,OAAO,OAAO,GAAG,MAAM,KAAK,IAAI,MAAM;CAC3D,OAAO,OAAO,KAAK;AACrB;AAEA,SAAgB,aAAa,SAAyC;CACpE,OACE,YAAY,QACZ,OAAO,YAAY,YACnB,kBAAkB,WAClB,QAAQ,iBAAiB;AAE7B;;;;;;AAOA,SAAgB,cAAc,SAA0C;CACtE,IAAI,mBAAmB,aAAa,OAAO;CAC3C,IAAI,YAAY,QAAQ,OAAO,YAAY,UAAU,OAAO;CAC5D,MAAM,EAAE,QAAQ,SAAS;CACzB,OAAO,OAAO,WAAW,YAAY,OAAO,MAAM,OAAO,SAAS;AACpE;AAEA,SAAgB,aACd,OACA,GAC8B;CAC9B,MAAM,YAAY,EAAE,IAAI,WAAW;CACnC,MAAM,cAAc,GAAG,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI;CAC9C,MAAM,UAAU,QAAQ,IAAI,CAAC,CAAC,YAAY;EAAE;EAAW;CAAY,CAAC;CAEpE,IAAI,cAAc,KAAK,GAAG;EACxB,MAAM,OAAO,MAAM,QAAQ,OAAO,SAAS,CAAC,CAAC,KAAK;EAClD,KAAK,MAAM,QAAQ,KAAK,GAAG,QAAQ,IAAI;EAIvC,CADY,MAAM,UAAU,MAAM,QAAQ,QAAQ,QAAQ,KAAA,CACtD,aAAa,KAAK,UAAU,KAAK,KAAK,CAAC;EAC3C,OAAO,EAAE,KAAK,MAAM,MAAM,MAA8B;CAC1D;CAOA,IAAI,EAAE,IAAI,IAAI,OAAO,SAAS;EAC5B,QAAQ,KAAK,0BAA0B,eAAe,UAAU,KAAK,CAAC;EACtE,OAAO,OAAO,UAAU,CAAC,CAAC,SAAS,OAAO;CAC5C;CAEA,IAAI,iBAAiB,eAAe;EAIlC,CADY,MAAM,UAAU,MAAM,QAAQ,QAAQ,QAAQ,KAAA,CACtD,mBAAmB,eAAe,MAAM,QAAQ,MAAM,OAAO;EACjE,IAAI,MAAM,KAAK,OAAO,MAAM;EAC5B,OAAO,aAAa,MAAM,QAAQ,MAAM,OAAO,CAAC,CAAC,SAAS,OAAO;CACnE;CAEA,IAAI,aAAa,KAAK,GAAG;EACvB,QAAQ,MAAM,gBAAgB,eAAe;GAC3C;GACA,MAAM,MAAM;GACZ,QAAQ,MAAM,UAAU,MAAM,UAAU;GACxC,SAAS,MAAM;GACf,SAAS;IACP,QAAQ,MAAM,QAAQ;IACtB,KAAK,MAAM,QAAQ;IACnB,MAAM,MAAM,QAAQ;GACtB;GACA,UAAU,EAAE,MAAM,MAAM,UAAU,KAAK;EACzC,CAAC;EACD,OAAO,OAAO,SAAS,aAAa,CAAC,CAAC,SAAS,OAAO;CACxD;CAEA,QAAQ,MAAM,kBAAkB,eAAe,WAAW,KAAK;CAC/D,OAAO,OAAO,SAAS,eAAe,CAAC,CAAC,SAAS,OAAO;AAC1D"}
|
package/dist/hono/validator.cjs
CHANGED
|
@@ -11,7 +11,7 @@ function zValidator(target, schema) {
|
|
|
11
11
|
const fieldViolations = result.error.issues.map(({ code, path, message }) => ({
|
|
12
12
|
field: path.join("."),
|
|
13
13
|
description: message,
|
|
14
|
-
reason: code
|
|
14
|
+
reason: code.toUpperCase(),
|
|
15
15
|
localizedMessage: {
|
|
16
16
|
locale: "en-US",
|
|
17
17
|
message
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.cjs","names":["Details","Status","NEVER"],"sources":["../../src/hono/validator.ts"],"sourcesContent":["import type { ValidationTargets } from 'hono';\nimport { validator } from 'hono/validator';\nimport type { ZodType, output as outputV4 } from 'zod';\nimport {\n NEVER,\n type ZodMiniType,\n type output as outputMini,\n pipe,\n string,\n transform,\n} from 'zod/mini';\nimport { type BadRequest, Details } from '../error/detail';\nimport { Status } from '../error/status';\n\nexport function zValidator<S extends ZodType | ZodMiniType>(\n target: keyof ValidationTargets,\n schema: S\n) {\n return validator(target, async (value) => {\n const result = await schema.safeParseAsync(value);\n if (result.success) return result.data as S extends ZodType ? outputV4<S> : outputMini<S>;\n\n const fieldViolations: BadRequest['fieldViolations'] = result.error.issues.map(\n ({ code, path, message }) => ({\n field: path.join('.'),\n description: message,\n reason: code
|
|
1
|
+
{"version":3,"file":"validator.cjs","names":["Details","Status","NEVER"],"sources":["../../src/hono/validator.ts"],"sourcesContent":["import type { ValidationTargets } from 'hono';\nimport { validator } from 'hono/validator';\nimport type { ZodType, output as outputV4 } from 'zod';\nimport {\n NEVER,\n type ZodMiniType,\n type output as outputMini,\n pipe,\n string,\n transform,\n} from 'zod/mini';\nimport { type BadRequest, Details } from '../error/detail';\nimport { Status } from '../error/status';\n\nexport function zValidator<S extends ZodType | ZodMiniType>(\n target: keyof ValidationTargets,\n schema: S\n) {\n return validator(target, async (value) => {\n const result = await schema.safeParseAsync(value);\n if (result.success) return result.data as S extends ZodType ? outputV4<S> : outputMini<S>;\n\n const fieldViolations: BadRequest['fieldViolations'] = result.error.issues.map(\n ({ code, path, message }) => ({\n field: path.join('.'),\n description: message,\n reason: code.toUpperCase(),\n localizedMessage: { locale: 'en-US', message: message },\n })\n );\n const details = Details.new().badRequest({ fieldViolations });\n throw Status.invalidArgument().error(details);\n });\n}\n\nexport const bigintId = pipe(\n string(),\n transform((input, ctx) => {\n if (!/^(0|[1-9]\\d{0,19})$/.test(input)) {\n const message = `Invalid bigint id: ${input}`;\n ctx.issues.push({ code: 'custom', input, message });\n return NEVER;\n }\n try {\n return BigInt(input);\n } catch {\n const message = `Parse bigint id: ${input} failed`;\n ctx.issues.push({ code: 'custom', input, message });\n return NEVER;\n }\n })\n);\n"],"mappings":";;;;;;AAcA,SAAgB,WACd,QACA,QACA;CACA,QAAA,GAAA,eAAA,UAAA,CAAiB,QAAQ,OAAO,UAAU;EACxC,MAAM,SAAS,MAAM,OAAO,eAAe,KAAK;EAChD,IAAI,OAAO,SAAS,OAAO,OAAO;EAElC,MAAM,kBAAiD,OAAO,MAAM,OAAO,KACxE,EAAE,MAAM,MAAM,eAAe;GAC5B,OAAO,KAAK,KAAK,GAAG;GACpB,aAAa;GACb,QAAQ,KAAK,YAAY;GACzB,kBAAkB;IAAE,QAAQ;IAAkB;GAAQ;EACxD,EACF;EACA,MAAM,UAAUA,qBAAAA,QAAQ,IAAI,CAAC,CAAC,WAAW,EAAE,gBAAgB,CAAC;EAC5D,MAAMC,qBAAAA,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO;CAC9C,CAAC;AACH;AAEA,MAAa,YAAA,GAAA,SAAA,KAAA,EAAA,GAAA,SAAA,OAAA,CACJ,IAAA,GAAA,SAAA,UAAA,EACI,OAAO,QAAQ;CACxB,IAAI,CAAC,sBAAsB,KAAK,KAAK,GAAG;EACtC,MAAM,UAAU,sBAAsB;EACtC,IAAI,OAAO,KAAK;GAAE,MAAM;GAAU;GAAO;EAAQ,CAAC;EAClD,OAAOC,SAAAA;CACT;CACA,IAAI;EACF,OAAO,OAAO,KAAK;CACrB,QAAQ;EACN,MAAM,UAAU,oBAAoB,MAAM;EAC1C,IAAI,OAAO,KAAK;GAAE,MAAM;GAAU;GAAO;EAAQ,CAAC;EAClD,OAAOA,SAAAA;CACT;AACF,CAAC,CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.cts","names":[],"sources":["../../src/hono/validator.ts"],"mappings":";;;;iBAcgB,WAAW,UAAU,UAAU,aAC7C,cAAc,mBACd,QAAQ,mBAAC
|
|
1
|
+
{"version":3,"file":"validator.d.cts","names":[],"sources":["../../src/hono/validator.ts"],"mappings":";;;;iBAcgB,WAAW,UAAU,UAAU,aAC7C,cAAc,mBACd,QAAQ,mBAAC;;;;;;;;;;;;;;;;;IAiBV,UAAA,gDAAA,uCAAA,OAAA,KAAA,OAAA,mBAAA,OAAA,aAAA,UAAA,gDAAA,uCAAA,OAAA,KAAA,OAAA,MAAA,2BAAA,oBAAA,WAAA,6CAAA,kBAAA,mCAAA,cAAA,KAAA,KAAA,KAAA,YAAA,WAAA,MAAA;cAEY,6BAAQ,+BAAA,0CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.mts","names":[],"sources":["../../src/hono/validator.ts"],"mappings":";;;;iBAcgB,WAAW,UAAU,UAAU,aAC7C,cAAc,mBACd,QAAQ,mBAAC
|
|
1
|
+
{"version":3,"file":"validator.d.mts","names":[],"sources":["../../src/hono/validator.ts"],"mappings":";;;;iBAcgB,WAAW,UAAU,UAAU,aAC7C,cAAc,mBACd,QAAQ,mBAAC;;;;;;;;;;;;;;;;;IAiBV,UAAA,gDAAA,uCAAA,OAAA,KAAA,OAAA,mBAAA,OAAA,aAAA,UAAA,gDAAA,uCAAA,OAAA,KAAA,OAAA,MAAA,2BAAA,oBAAA,WAAA,6CAAA,kBAAA,mCAAA,cAAA,KAAA,KAAA,KAAA,YAAA,WAAA,MAAA;cAEY,6BAAQ,+BAAA,0CAAA"}
|
package/dist/hono/validator.mjs
CHANGED
|
@@ -10,7 +10,7 @@ function zValidator(target, schema) {
|
|
|
10
10
|
const fieldViolations = result.error.issues.map(({ code, path, message }) => ({
|
|
11
11
|
field: path.join("."),
|
|
12
12
|
description: message,
|
|
13
|
-
reason: code
|
|
13
|
+
reason: code.toUpperCase(),
|
|
14
14
|
localizedMessage: {
|
|
15
15
|
locale: "en-US",
|
|
16
16
|
message
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.mjs","names":[],"sources":["../../src/hono/validator.ts"],"sourcesContent":["import type { ValidationTargets } from 'hono';\nimport { validator } from 'hono/validator';\nimport type { ZodType, output as outputV4 } from 'zod';\nimport {\n NEVER,\n type ZodMiniType,\n type output as outputMini,\n pipe,\n string,\n transform,\n} from 'zod/mini';\nimport { type BadRequest, Details } from '../error/detail';\nimport { Status } from '../error/status';\n\nexport function zValidator<S extends ZodType | ZodMiniType>(\n target: keyof ValidationTargets,\n schema: S\n) {\n return validator(target, async (value) => {\n const result = await schema.safeParseAsync(value);\n if (result.success) return result.data as S extends ZodType ? outputV4<S> : outputMini<S>;\n\n const fieldViolations: BadRequest['fieldViolations'] = result.error.issues.map(\n ({ code, path, message }) => ({\n field: path.join('.'),\n description: message,\n reason: code
|
|
1
|
+
{"version":3,"file":"validator.mjs","names":[],"sources":["../../src/hono/validator.ts"],"sourcesContent":["import type { ValidationTargets } from 'hono';\nimport { validator } from 'hono/validator';\nimport type { ZodType, output as outputV4 } from 'zod';\nimport {\n NEVER,\n type ZodMiniType,\n type output as outputMini,\n pipe,\n string,\n transform,\n} from 'zod/mini';\nimport { type BadRequest, Details } from '../error/detail';\nimport { Status } from '../error/status';\n\nexport function zValidator<S extends ZodType | ZodMiniType>(\n target: keyof ValidationTargets,\n schema: S\n) {\n return validator(target, async (value) => {\n const result = await schema.safeParseAsync(value);\n if (result.success) return result.data as S extends ZodType ? outputV4<S> : outputMini<S>;\n\n const fieldViolations: BadRequest['fieldViolations'] = result.error.issues.map(\n ({ code, path, message }) => ({\n field: path.join('.'),\n description: message,\n reason: code.toUpperCase(),\n localizedMessage: { locale: 'en-US', message: message },\n })\n );\n const details = Details.new().badRequest({ fieldViolations });\n throw Status.invalidArgument().error(details);\n });\n}\n\nexport const bigintId = pipe(\n string(),\n transform((input, ctx) => {\n if (!/^(0|[1-9]\\d{0,19})$/.test(input)) {\n const message = `Invalid bigint id: ${input}`;\n ctx.issues.push({ code: 'custom', input, message });\n return NEVER;\n }\n try {\n return BigInt(input);\n } catch {\n const message = `Parse bigint id: ${input} failed`;\n ctx.issues.push({ code: 'custom', input, message });\n return NEVER;\n }\n })\n);\n"],"mappings":";;;;;AAcA,SAAgB,WACd,QACA,QACA;CACA,OAAO,UAAU,QAAQ,OAAO,UAAU;EACxC,MAAM,SAAS,MAAM,OAAO,eAAe,KAAK;EAChD,IAAI,OAAO,SAAS,OAAO,OAAO;EAElC,MAAM,kBAAiD,OAAO,MAAM,OAAO,KACxE,EAAE,MAAM,MAAM,eAAe;GAC5B,OAAO,KAAK,KAAK,GAAG;GACpB,aAAa;GACb,QAAQ,KAAK,YAAY;GACzB,kBAAkB;IAAE,QAAQ;IAAkB;GAAQ;EACxD,EACF;EACA,MAAM,UAAU,QAAQ,IAAI,CAAC,CAAC,WAAW,EAAE,gBAAgB,CAAC;EAC5D,MAAM,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO;CAC9C,CAAC;AACH;AAEA,MAAa,WAAW,KACtB,OAAO,GACP,WAAW,OAAO,QAAQ;CACxB,IAAI,CAAC,sBAAsB,KAAK,KAAK,GAAG;EACtC,MAAM,UAAU,sBAAsB;EACtC,IAAI,OAAO,KAAK;GAAE,MAAM;GAAU;GAAO;EAAQ,CAAC;EAClD,OAAO;CACT;CACA,IAAI;EACF,OAAO,OAAO,KAAK;CACrB,QAAQ;EACN,MAAM,UAAU,oBAAoB,MAAM;EAC1C,IAAI,OAAO,KAAK;GAAE,MAAM;GAAU;GAAO;EAAQ,CAAC;EAClD,OAAO;CACT;AACF,CAAC,CACH"}
|
package/dist/index.cjs
CHANGED
|
@@ -8,7 +8,7 @@ const require_snowflake = require("./snowflake.cjs");
|
|
|
8
8
|
const require_max_length_index = require("./max-length/index.cjs");
|
|
9
9
|
const require_utils_timing = require("./utils/timing.cjs");
|
|
10
10
|
const require_utils_google_tag_gateway = require("./utils/google-tag-gateway.cjs");
|
|
11
|
-
const require_iso_iso_3601_1 = require("./iso/
|
|
11
|
+
const require_iso_iso_3601_1 = require("./iso/iso-3601-1.cjs");
|
|
12
12
|
exports.CheckoutCreateError = require_error_index.CheckoutCreateError;
|
|
13
13
|
exports.Cursor = require_response.Cursor;
|
|
14
14
|
exports.DetailType = require_error_detail.DetailType;
|
package/dist/index.d.cts
CHANGED
|
@@ -8,5 +8,5 @@ import { UidGenerator, uid } from "./snowflake.cjs";
|
|
|
8
8
|
import { index_d_exports } from "./max-length/index.cjs";
|
|
9
9
|
import { timing } from "./utils/timing.cjs";
|
|
10
10
|
import { forwardToGoogleTagGateway } from "./utils/google-tag-gateway.cjs";
|
|
11
|
-
import { ISO3166CountryCode, ISO_3601_1 } from "./iso/
|
|
11
|
+
import { ISO3166CountryCode, ISO_3601_1 } from "./iso/iso-3601-1.cjs";
|
|
12
12
|
export { type BadRequest, CheckoutCreateError, Cursor, type DebugInfo, type Detail, DetailType, Details, type Empty, type Entity, type EntityId, type ErrorBody, type ErrorInfo, type ErrorReason, type Help, type ISO3166CountryCode, ISO_3601_1, type InfinitePageData, type InitParams, Items, type LocalizedMessage, LoginCanceledError, LoginTimeoutError, index_d_exports as MAX_LENGTH, type NextParams, type Page, type PageParams, Pages, type ParentPageParams, type PreconditionFailure, type PrevParams, PurchaseError, type QuotaFailure, type RequestInfo, type ResolvedErrorReason, type ResourceInfo, type Response, type RetryInfo, Status, StatusError, UidGenerator, forwardToGoogleTagGateway, getErrorInfo, getErrorMessage, getFieldViolations, getNextPageParam, getPreviousPageParam, initialPageParam, pageParamsSchema, timing, uid };
|
package/dist/index.d.mts
CHANGED
|
@@ -8,5 +8,5 @@ import { UidGenerator, uid } from "./snowflake.mjs";
|
|
|
8
8
|
import { index_d_exports } from "./max-length/index.mjs";
|
|
9
9
|
import { timing } from "./utils/timing.mjs";
|
|
10
10
|
import { forwardToGoogleTagGateway } from "./utils/google-tag-gateway.mjs";
|
|
11
|
-
import { ISO3166CountryCode, ISO_3601_1 } from "./iso/
|
|
11
|
+
import { ISO3166CountryCode, ISO_3601_1 } from "./iso/iso-3601-1.mjs";
|
|
12
12
|
export { type BadRequest, CheckoutCreateError, Cursor, type DebugInfo, type Detail, DetailType, Details, type Empty, type Entity, type EntityId, type ErrorBody, type ErrorInfo, type ErrorReason, type Help, type ISO3166CountryCode, ISO_3601_1, type InfinitePageData, type InitParams, Items, type LocalizedMessage, LoginCanceledError, LoginTimeoutError, index_d_exports as MAX_LENGTH, type NextParams, type Page, type PageParams, Pages, type ParentPageParams, type PreconditionFailure, type PrevParams, PurchaseError, type QuotaFailure, type RequestInfo, type ResolvedErrorReason, type ResourceInfo, type Response, type RetryInfo, Status, StatusError, UidGenerator, forwardToGoogleTagGateway, getErrorInfo, getErrorMessage, getFieldViolations, getNextPageParam, getPreviousPageParam, initialPageParam, pageParamsSchema, timing, uid };
|
package/dist/index.mjs
CHANGED
|
@@ -7,5 +7,5 @@ import { UidGenerator, uid } from "./snowflake.mjs";
|
|
|
7
7
|
import { max_length_exports } from "./max-length/index.mjs";
|
|
8
8
|
import { timing } from "./utils/timing.mjs";
|
|
9
9
|
import { forwardToGoogleTagGateway } from "./utils/google-tag-gateway.mjs";
|
|
10
|
-
import { ISO_3601_1 } from "./iso/
|
|
10
|
+
import { ISO_3601_1 } from "./iso/iso-3601-1.mjs";
|
|
11
11
|
export { CheckoutCreateError, Cursor, DetailType, Details, ISO_3601_1, Items, LoginCanceledError, LoginTimeoutError, max_length_exports as MAX_LENGTH, Pages, PurchaseError, Status, StatusError, UidGenerator, forwardToGoogleTagGateway, getErrorInfo, getErrorMessage, getFieldViolations, getNextPageParam, getPreviousPageParam, initialPageParam, pageParamsSchema, timing, uid };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
//#region src/iso/
|
|
2
|
+
//#region src/iso/iso-3601-1.ts
|
|
3
3
|
const ISO_3601_1 = [
|
|
4
4
|
{
|
|
5
5
|
numeric: 4,
|
|
@@ -1511,4 +1511,4 @@ const ISO_3601_1 = [
|
|
|
1511
1511
|
//#endregion
|
|
1512
1512
|
exports.ISO_3601_1 = ISO_3601_1;
|
|
1513
1513
|
|
|
1514
|
-
//# sourceMappingURL=
|
|
1514
|
+
//# sourceMappingURL=iso-3601-1.cjs.map
|