@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.
Files changed (59) hide show
  1. package/dist/error/parse.cjs +4 -3
  2. package/dist/error/parse.cjs.map +1 -1
  3. package/dist/error/parse.d.cts.map +1 -1
  4. package/dist/error/parse.d.mts.map +1 -1
  5. package/dist/error/parse.mjs +4 -3
  6. package/dist/error/parse.mjs.map +1 -1
  7. package/dist/error/status.cjs +1 -1
  8. package/dist/error/status.cjs.map +1 -1
  9. package/dist/error/status.mjs +1 -1
  10. package/dist/error/status.mjs.map +1 -1
  11. package/dist/google-one-tap/index.cjs +20 -5
  12. package/dist/google-one-tap/index.cjs.map +1 -1
  13. package/dist/google-one-tap/index.d.cts +2 -1
  14. package/dist/google-one-tap/index.d.cts.map +1 -1
  15. package/dist/google-one-tap/index.d.mts +2 -1
  16. package/dist/google-one-tap/index.d.mts.map +1 -1
  17. package/dist/google-one-tap/index.mjs +20 -5
  18. package/dist/google-one-tap/index.mjs.map +1 -1
  19. package/dist/hono/csrf.cjs +2 -2
  20. package/dist/hono/csrf.cjs.map +1 -1
  21. package/dist/hono/csrf.mjs +2 -2
  22. package/dist/hono/csrf.mjs.map +1 -1
  23. package/dist/hono/handler.cjs +56 -9
  24. package/dist/hono/handler.cjs.map +1 -1
  25. package/dist/hono/handler.d.cts +8 -1
  26. package/dist/hono/handler.d.cts.map +1 -1
  27. package/dist/hono/handler.d.mts +8 -1
  28. package/dist/hono/handler.d.mts.map +1 -1
  29. package/dist/hono/handler.mjs +58 -12
  30. package/dist/hono/handler.mjs.map +1 -1
  31. package/dist/hono/validator.cjs +1 -1
  32. package/dist/hono/validator.cjs.map +1 -1
  33. package/dist/hono/validator.d.cts.map +1 -1
  34. package/dist/hono/validator.d.mts.map +1 -1
  35. package/dist/hono/validator.mjs +1 -1
  36. package/dist/hono/validator.mjs.map +1 -1
  37. package/dist/index.cjs +1 -1
  38. package/dist/index.d.cts +1 -1
  39. package/dist/index.d.mts +1 -1
  40. package/dist/index.mjs +1 -1
  41. package/dist/iso/{iso_3601_1.cjs → iso-3601-1.cjs} +2 -2
  42. package/dist/iso/{iso_3601_1.cjs.map → iso-3601-1.cjs.map} +1 -1
  43. package/dist/iso/{iso_3601_1.d.mts → iso-3601-1.d.cts} +2 -2
  44. package/dist/iso/iso-3601-1.d.cts.map +1 -0
  45. package/dist/iso/{iso_3601_1.d.cts → iso-3601-1.d.mts} +2 -2
  46. package/dist/iso/iso-3601-1.d.mts.map +1 -0
  47. package/dist/iso/{iso_3601_1.mjs → iso-3601-1.mjs} +2 -2
  48. package/dist/iso/{iso_3601_1.mjs.map → iso-3601-1.mjs.map} +1 -1
  49. package/dist/polyfills/index.d.cts +1 -1
  50. package/dist/polyfills/index.d.mts +1 -1
  51. package/dist/response.cjs +3 -2
  52. package/dist/response.cjs.map +1 -1
  53. package/dist/response.d.cts.map +1 -1
  54. package/dist/response.d.mts.map +1 -1
  55. package/dist/response.mjs +3 -2
  56. package/dist/response.mjs.map +1 -1
  57. package/package.json +4 -4
  58. package/dist/iso/iso_3601_1.d.cts.map +0 -1
  59. package/dist/iso/iso_3601_1.d.mts.map +0 -1
@@ -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 && config.origin.includes(c.req.header('origin') ?? '')) {\n await next();\n return;\n }\n\n // 3. ignore configured secFetchSite\n if (\n config.secFetchSite &&\n config.secFetchSite.includes((c.req.header('sec-fetch-site') ?? '') as never)\n ) {\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,UAAU,OAAO,OAAO,SAAS,EAAE,IAAI,OAAO,QAAQ,KAAK,EAAE,GAAG;GACzE,MAAM,KAAK;GACX;EACF;EAGA,IACE,OAAO,gBACP,OAAO,aAAa,SAAU,EAAE,IAAI,OAAO,gBAAgB,KAAK,EAAY,GAC5E;GACA,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"}
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"}
@@ -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 instanceof require_error_status.StatusError) {
16
- error.body?.error?.details?.push(...details.list);
17
- const badRequest = error.body?.error?.details.find((d) => d["@type"] === require_error_detail.DetailType.BAD_REQUEST);
18
- if (badRequest) console.warn(servingData, badRequest);
19
- console.error(servingData, JSON.stringify(error.body?.error ?? {}, null, 2));
20
- return c.json(error.body, error.status);
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
- status: error.status,
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":["Details","StatusError","DetailType","Status"],"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 { DetailType, Details } from '../error/detail';\nimport { Status, 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\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\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 (error instanceof StatusError) {\n error.body?.error?.details?.push(...details.list);\n const badRequest = error.body?.error?.details.find(\n (d) => d['@type'] === DetailType.BAD_REQUEST\n );\n if (badRequest) console.warn(servingData, badRequest);\n console.error(servingData, JSON.stringify(error.body?.error ?? {}, null, 2));\n return c.json(error.body, error.status as ContentfulStatusCode);\n }\n\n if (isAxiosError(error)) {\n console.error({\n status: error.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}`, error);\n return Status.internal('Unknown error').response(details);\n}\n"],"mappings":";;;;AA2BA,SAAgB,aAAa,SAAyC;CACpE,OACE,YAAY,QACZ,OAAO,YAAY,YACnB,kBAAkB,WAClB,QAAQ,iBAAiB;AAE7B;AAEA,SAAgB,aACd,OACA,GAC8B;CAC9B,MAAM,YAAY,EAAE,IAAI,WAAW;CACnC,MAAM,cAAc,GAAG,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI;CAC9C,MAAM,UAAUA,qBAAAA,QAAQ,IAAI,CAAC,CAAC,YAAY;EAAE;EAAW;CAAY,CAAC;CAEpE,IAAI,iBAAiBC,qBAAAA,aAAa;EAChC,MAAM,MAAM,OAAO,SAAS,KAAK,GAAG,QAAQ,IAAI;EAChD,MAAM,aAAa,MAAM,MAAM,OAAO,QAAQ,MAC3C,MAAM,EAAE,aAAaC,qBAAAA,WAAW,WACnC;EACA,IAAI,YAAY,QAAQ,KAAK,aAAa,UAAU;EACpD,QAAQ,MAAM,aAAa,KAAK,UAAU,MAAM,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC;EAC3E,OAAO,EAAE,KAAK,MAAM,MAAM,MAAM,MAA8B;CAChE;CAEA,IAAI,aAAa,KAAK,GAAG;EACvB,QAAQ,MAAM;GACZ,QAAQ,MAAM;GACd,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,OAAOC,qBAAAA,OAAO,SAAS,aAAa,CAAC,CAAC,SAAS,OAAO;CACxD;CAEA,QAAQ,MAAM,kBAAkB,eAAe,KAAK;CACpD,OAAOA,qBAAAA,OAAO,SAAS,eAAe,CAAC,CAAC,SAAS,OAAO;AAC1D"}
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"}
@@ -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":";;;;KAOY;EACV,WAAW;EACX,WAAW;;KAGR;EACH;EACA;EACA;EACA;EACA;EACA;IACE;IACA;IACA;IACA,SAAS;;EAEX;IAAW;IAAc;IAAgB;IAAiB,UAAU;;;iBAGtD,aAAa,mBAAmB,WAAW;iBAS3C,aAAa,UAAU,aACrC,OAAO,QAAQ,mBACf,GAAG,QAAQ,KACV,WAAW,QAAQ"}
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"}
@@ -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":";;;;KAOY;EACV,WAAW;EACX,WAAW;;KAGR;EACH;EACA;EACA;EACA;EACA;EACA;IACE;IACA;IACA;IACA,SAAS;;EAEX;IAAW;IAAc;IAAgB;IAAiB,UAAU;;;iBAGtD,aAAa,mBAAmB,WAAW;iBAS3C,aAAa,UAAU,aACrC,OAAO,QAAQ,mBACf,GAAG,QAAQ,KACV,WAAW,QAAQ"}
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"}
@@ -1,9 +1,45 @@
1
- import { DetailType, Details } from "../error/detail.mjs";
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 instanceof StatusError) {
15
- error.body?.error?.details?.push(...details.list);
16
- const badRequest = error.body?.error?.details.find((d) => d["@type"] === DetailType.BAD_REQUEST);
17
- if (badRequest) console.warn(servingData, badRequest);
18
- console.error(servingData, JSON.stringify(error.body?.error ?? {}, null, 2));
19
- return c.json(error.body, error.status);
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
- status: error.status,
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 { DetailType, Details } from '../error/detail';\nimport { Status, 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\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\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 (error instanceof StatusError) {\n error.body?.error?.details?.push(...details.list);\n const badRequest = error.body?.error?.details.find(\n (d) => d['@type'] === DetailType.BAD_REQUEST\n );\n if (badRequest) console.warn(servingData, badRequest);\n console.error(servingData, JSON.stringify(error.body?.error ?? {}, null, 2));\n return c.json(error.body, error.status as ContentfulStatusCode);\n }\n\n if (isAxiosError(error)) {\n console.error({\n status: error.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}`, error);\n return Status.internal('Unknown error').response(details);\n}\n"],"mappings":";;;AA2BA,SAAgB,aAAa,SAAyC;CACpE,OACE,YAAY,QACZ,OAAO,YAAY,YACnB,kBAAkB,WAClB,QAAQ,iBAAiB;AAE7B;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,iBAAiB,aAAa;EAChC,MAAM,MAAM,OAAO,SAAS,KAAK,GAAG,QAAQ,IAAI;EAChD,MAAM,aAAa,MAAM,MAAM,OAAO,QAAQ,MAC3C,MAAM,EAAE,aAAa,WAAW,WACnC;EACA,IAAI,YAAY,QAAQ,KAAK,aAAa,UAAU;EACpD,QAAQ,MAAM,aAAa,KAAK,UAAU,MAAM,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC;EAC3E,OAAO,EAAE,KAAK,MAAM,MAAM,MAAM,MAA8B;CAChE;CAEA,IAAI,aAAa,KAAK,GAAG;EACvB,QAAQ,MAAM;GACZ,QAAQ,MAAM;GACd,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,KAAK;CACpD,OAAO,OAAO,SAAS,eAAe,CAAC,CAAC,SAAS,OAAO;AAC1D"}
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"}
@@ -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?.toUpperCase() ?? "INVALID_ARGUMENT",
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?.toUpperCase() ?? 'INVALID_ARGUMENT',\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,MAAM,YAAY,KAAK;GAC/B,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
+ {"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;;;;;;;;;;;;;;;;;;cAmBE,6BAAQ,+BAAA,0CAAA"}
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;;;;;;;;;;;;;;;;;;cAmBE,6BAAQ,+BAAA,0CAAA"}
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"}
@@ -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?.toUpperCase() ?? "INVALID_ARGUMENT",
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?.toUpperCase() ?? 'INVALID_ARGUMENT',\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,MAAM,YAAY,KAAK;GAC/B,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"}
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/iso_3601_1.cjs");
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/iso_3601_1.cjs";
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/iso_3601_1.mjs";
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/iso_3601_1.mjs";
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/iso_3601_1.ts
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=iso_3601_1.cjs.map
1514
+ //# sourceMappingURL=iso-3601-1.cjs.map