stratal 0.0.20 → 0.0.22

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 (247) hide show
  1. package/README.md +1 -1
  2. package/dist/{base-email.provider-CfQCA08m.mjs → base-email.provider-BWZHIjt8.mjs} +1 -1
  3. package/dist/{base-email.provider-CfQCA08m.mjs.map → base-email.provider-BWZHIjt8.mjs.map} +1 -1
  4. package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
  5. package/dist/bin/quarry.mjs +46 -109
  6. package/dist/bin/quarry.mjs.map +1 -1
  7. package/dist/cache/index.d.mts +6 -46
  8. package/dist/cache/index.d.mts.map +1 -1
  9. package/dist/cache/index.mjs +22 -67
  10. package/dist/cache/index.mjs.map +1 -1
  11. package/dist/{cache.service-DsnKuNyO.d.mts → cache.service-e34gV6tz.d.mts} +8 -8
  12. package/dist/{cache.service-DsnKuNyO.d.mts.map → cache.service-e34gV6tz.d.mts.map} +1 -1
  13. package/dist/{cache.tokens-B7Rw1C9Q.mjs → cache.tokens-ovi_c52J.mjs} +1 -1
  14. package/dist/{cache.tokens-B7Rw1C9Q.mjs.map → cache.tokens-ovi_c52J.mjs.map} +1 -1
  15. package/dist/{colors-DJaRDXoS.mjs → colors-axmupKdp.mjs} +1 -1
  16. package/dist/{colors-DJaRDXoS.mjs.map → colors-axmupKdp.mjs.map} +1 -1
  17. package/dist/{command-BgSlsS4M.mjs → command-BU4ApTo5.mjs} +2 -3
  18. package/dist/command-BU4ApTo5.mjs.map +1 -0
  19. package/dist/{command-Bu-PjJrX.d.mts → command-wXfvHbBZ.d.mts} +3 -2
  20. package/dist/command-wXfvHbBZ.d.mts.map +1 -0
  21. package/dist/config/index.d.mts +24 -11
  22. package/dist/config/index.d.mts.map +1 -1
  23. package/dist/config/index.mjs +33 -57
  24. package/dist/config/index.mjs.map +1 -1
  25. package/dist/{consumer-registry-B7yUNh0q.d.mts → consumer-registry-DHQtypr1.d.mts} +1 -1
  26. package/dist/{consumer-registry-B7yUNh0q.d.mts.map → consumer-registry-DHQtypr1.d.mts.map} +1 -1
  27. package/dist/container-storage-GpNNz79X.mjs +52 -0
  28. package/dist/container-storage-GpNNz79X.mjs.map +1 -0
  29. package/dist/{controller.decorator-DQzenvSN.mjs → controller.decorator-DIUazNU7.mjs} +8 -8
  30. package/dist/controller.decorator-DIUazNU7.mjs.map +1 -0
  31. package/dist/cron/index.d.mts +26 -5
  32. package/dist/cron/index.d.mts.map +1 -1
  33. package/dist/cron/index.mjs +1 -1
  34. package/dist/{cron-manager-7Symz_TE.mjs → cron-manager-9bpN9bu4.mjs} +42 -16
  35. package/dist/cron-manager-9bpN9bu4.mjs.map +1 -0
  36. package/dist/{cron-manager-BEsH1mjW.d.mts → cron-manager-CSTIBPcM.d.mts} +6 -13
  37. package/dist/cron-manager-CSTIBPcM.d.mts.map +1 -0
  38. package/dist/decorate-HgTKAYK8.mjs +16 -0
  39. package/dist/deep-merge-C8NgcXw4.mjs +18 -0
  40. package/dist/deep-merge-C8NgcXw4.mjs.map +1 -0
  41. package/dist/di/index.d.mts +2 -2
  42. package/dist/di/index.mjs +4 -3
  43. package/dist/di-BO1QIb5H.mjs +415 -0
  44. package/dist/di-BO1QIb5H.mjs.map +1 -0
  45. package/dist/email/index.d.mts +14 -89
  46. package/dist/email/index.d.mts.map +1 -1
  47. package/dist/email/index.mjs +30 -125
  48. package/dist/email/index.mjs.map +1 -1
  49. package/dist/en-BPP6h6y5.mjs +202 -0
  50. package/dist/en-BPP6h6y5.mjs.map +1 -0
  51. package/dist/{env-D1rcZ8_r.d.mts → env-DKSbuBi5.d.mts} +1 -1
  52. package/dist/env-DKSbuBi5.d.mts.map +1 -0
  53. package/dist/errors/index.d.mts +2 -2
  54. package/dist/errors/index.mjs +4 -2
  55. package/dist/errors-BBZTnjdq.mjs +333 -0
  56. package/dist/errors-BBZTnjdq.mjs.map +1 -0
  57. package/dist/events/index.d.mts +2 -2
  58. package/dist/events/index.d.mts.map +1 -1
  59. package/dist/events/index.mjs +1 -1
  60. package/dist/{events-COKixqnG.mjs → events-D1KdDaiP.mjs} +13 -11
  61. package/dist/events-D1KdDaiP.mjs.map +1 -0
  62. package/dist/exception-context-B4kM-M53.mjs +429 -0
  63. package/dist/exception-context-B4kM-M53.mjs.map +1 -0
  64. package/dist/{gateway-context-CdJjpUCW.mjs → gateway-context-CFe6a9gz.mjs} +20 -31
  65. package/dist/gateway-context-CFe6a9gz.mjs.map +1 -0
  66. package/dist/guards/index.d.mts +3 -3
  67. package/dist/guards/index.d.mts.map +1 -1
  68. package/dist/guards/index.mjs +1 -1
  69. package/dist/{guards-DUk_Kzst.mjs → guards-Ced-uNIF.mjs} +7 -5
  70. package/dist/guards-Ced-uNIF.mjs.map +1 -0
  71. package/dist/{http-method.decorator-DXwxAfb_.mjs → http-method.decorator-CdjKFJZZ.mjs} +7 -6
  72. package/dist/http-method.decorator-CdjKFJZZ.mjs.map +1 -0
  73. package/dist/i18n/index.d.mts +238 -3
  74. package/dist/i18n/index.d.mts.map +1 -0
  75. package/dist/i18n/index.mjs +39 -3
  76. package/dist/i18n/index.mjs.map +1 -0
  77. package/dist/i18n/messages/en/index.d.mts +2 -2
  78. package/dist/i18n/messages/en/index.mjs +2 -2
  79. package/dist/i18n/utils/index.d.mts +4 -26
  80. package/dist/i18n/utils/index.d.mts.map +1 -1
  81. package/dist/i18n/utils/index.mjs +2 -2
  82. package/dist/i18n/validation/index.d.mts +3 -2
  83. package/dist/i18n/validation/index.mjs +4 -2
  84. package/dist/i18n.module-BlXrtAlV.mjs +219 -0
  85. package/dist/i18n.module-BlXrtAlV.mjs.map +1 -0
  86. package/dist/i18n.tokens-hwRpmjRq.mjs +19 -0
  87. package/dist/i18n.tokens-hwRpmjRq.mjs.map +1 -0
  88. package/dist/{index-7-hU3GTV.d.mts → index-B4UBK-2T.d.mts} +1 -1
  89. package/dist/{index-7-hU3GTV.d.mts.map → index-B4UBK-2T.d.mts.map} +1 -1
  90. package/dist/index-BtlE9RuO.d.mts +124 -0
  91. package/dist/index-BtlE9RuO.d.mts.map +1 -0
  92. package/dist/{index-CjaQ6_tZ.d.mts → index-CW1YHSft.d.mts} +71 -167
  93. package/dist/index-CW1YHSft.d.mts.map +1 -0
  94. package/dist/{index-D0US0X14.d.mts → index-DEncMcC6.d.mts} +559 -2239
  95. package/dist/index-DEncMcC6.d.mts.map +1 -0
  96. package/dist/index-Dj5IMwtr.d.mts +44 -0
  97. package/dist/index-Dj5IMwtr.d.mts.map +1 -0
  98. package/dist/{index-C1KvMncZ.d.mts → index-KMgSCSM7.d.mts} +3 -108
  99. package/dist/index-KMgSCSM7.d.mts.map +1 -0
  100. package/dist/index.d.mts +5 -43
  101. package/dist/index.mjs +1 -1
  102. package/dist/{is-command-C6a7WTPw.mjs → is-command-CX5rAfZW.mjs} +2 -2
  103. package/dist/{is-command-C6a7WTPw.mjs.map → is-command-CX5rAfZW.mjs.map} +1 -1
  104. package/dist/{is-seeder-CebjZCDn.mjs → is-seeder-CYCtELlm.mjs} +1 -1
  105. package/dist/{is-seeder-CebjZCDn.mjs.map → is-seeder-CYCtELlm.mjs.map} +1 -1
  106. package/dist/logger/index.d.mts +2 -2
  107. package/dist/logger/index.mjs +170 -2
  108. package/dist/logger/index.mjs.map +1 -0
  109. package/dist/macroable/index.d.mts +1 -1
  110. package/dist/macroable/index.mjs +1 -1
  111. package/dist/{macroable-BmufBshB.mjs → macroable-DzlfzT50.mjs} +1 -1
  112. package/dist/{macroable-BmufBshB.mjs.map → macroable-DzlfzT50.mjs.map} +1 -1
  113. package/dist/metadata-BVkc4aUu.mjs +39 -0
  114. package/dist/metadata-BVkc4aUu.mjs.map +1 -0
  115. package/dist/module/index.d.mts +6 -24
  116. package/dist/module/index.d.mts.map +1 -1
  117. package/dist/module/index.mjs +2 -2
  118. package/dist/module-xYoHba6B.mjs +422 -0
  119. package/dist/module-xYoHba6B.mjs.map +1 -0
  120. package/dist/openapi/index.d.mts +3 -3
  121. package/dist/openapi/index.d.mts.map +1 -1
  122. package/dist/openapi/index.mjs +1 -2
  123. package/dist/openapi-C6lm0RmV.mjs +483 -0
  124. package/dist/openapi-C6lm0RmV.mjs.map +1 -0
  125. package/dist/{openapi.service-BLgvn3hJ.d.mts → openapi.service-CrLlsXAd.d.mts} +3 -3
  126. package/dist/openapi.service-CrLlsXAd.d.mts.map +1 -0
  127. package/dist/quarry/index.d.mts +5 -163
  128. package/dist/quarry/index.d.mts.map +1 -1
  129. package/dist/quarry/index.mjs +5 -5
  130. package/dist/quarry/runner.d.mts +184 -0
  131. package/dist/quarry/runner.d.mts.map +1 -0
  132. package/dist/quarry/runner.mjs +775 -0
  133. package/dist/quarry/runner.mjs.map +1 -0
  134. package/dist/quarry-registry-D4hIGScf.d.mts +69 -0
  135. package/dist/quarry-registry-D4hIGScf.d.mts.map +1 -0
  136. package/dist/quarry-registry-DkraZNwn.mjs +311 -0
  137. package/dist/quarry-registry-DkraZNwn.mjs.map +1 -0
  138. package/dist/queue/index.d.mts +3 -3
  139. package/dist/queue/index.mjs +27 -28
  140. package/dist/queue/index.mjs.map +1 -1
  141. package/dist/{queue.module-BCdCiySt.mjs → queue.module-DeWJ0tQM.mjs} +67 -112
  142. package/dist/queue.module-DeWJ0tQM.mjs.map +1 -0
  143. package/dist/{r2-storage.provider-Co6F0ZYV.mjs → r2-storage.provider-Hfm6LdZQ.mjs} +8 -5
  144. package/dist/r2-storage.provider-Hfm6LdZQ.mjs.map +1 -0
  145. package/dist/{rate-limit.decorator--o6Q6p9w.mjs → rate-limit.decorator-D69zdZbp.mjs} +6 -11
  146. package/dist/rate-limit.decorator-D69zdZbp.mjs.map +1 -0
  147. package/dist/rate-limiter/index.d.mts +11 -50
  148. package/dist/rate-limiter/index.d.mts.map +1 -1
  149. package/dist/rate-limiter/index.mjs +25 -30
  150. package/dist/rate-limiter/index.mjs.map +1 -1
  151. package/dist/{resend.provider-M6qRLrcy.mjs → resend.provider-Ur6tU7fK.mjs} +8 -7
  152. package/dist/resend.provider-Ur6tU7fK.mjs.map +1 -0
  153. package/dist/router/index.d.mts +2 -2
  154. package/dist/router/index.mjs +8 -7
  155. package/dist/{i18n.module-BBlNNlcG.mjs → router-Cy6DjkvP.mjs} +215 -855
  156. package/dist/router-Cy6DjkvP.mjs.map +1 -0
  157. package/dist/seeder/index.d.mts +6 -11
  158. package/dist/seeder/index.d.mts.map +1 -1
  159. package/dist/seeder/index.mjs +3 -3
  160. package/dist/{seeder-CJAOHEIo.mjs → seeder-BADTig4n.mjs} +17 -22
  161. package/dist/seeder-BADTig4n.mjs.map +1 -0
  162. package/dist/{signed-url-BQPbv2In.mjs → signed-url-BqUqt5dF.mjs} +1 -1
  163. package/dist/{signed-url-BQPbv2In.mjs.map → signed-url-BqUqt5dF.mjs.map} +1 -1
  164. package/dist/{smtp.provider-w0Ve52Xg.mjs → smtp.provider-C129sNBT.mjs} +7 -6
  165. package/dist/smtp.provider-C129sNBT.mjs.map +1 -0
  166. package/dist/storage/index.d.mts +15 -39
  167. package/dist/storage/index.d.mts.map +1 -1
  168. package/dist/storage/index.mjs +3 -3
  169. package/dist/storage/providers/index.d.mts +2 -2
  170. package/dist/storage/providers/index.mjs +1 -1
  171. package/dist/{storage-1zw-6Yiz.mjs → storage-BA3ppVYM.mjs} +70 -59
  172. package/dist/storage-BA3ppVYM.mjs.map +1 -0
  173. package/dist/{storage-provider.interface-Bd6vA4ak.d.mts → storage-provider.interface-DQMtT42e.d.mts} +2 -3
  174. package/dist/storage-provider.interface-DQMtT42e.d.mts.map +1 -0
  175. package/dist/storage.error-C6FY037a.mjs +8 -0
  176. package/dist/storage.error-C6FY037a.mjs.map +1 -0
  177. package/dist/{stratal-DeEcGgdq.mjs → stratal-Bdq4IdB3.mjs} +31 -183
  178. package/dist/stratal-Bdq4IdB3.mjs.map +1 -0
  179. package/dist/stratal-BsKmvP6J.d.mts +43 -0
  180. package/dist/stratal-BsKmvP6J.d.mts.map +1 -0
  181. package/dist/{types-cySNS_lp.d.mts → types-BaeHi67f.d.mts} +1 -1
  182. package/dist/types-BaeHi67f.d.mts.map +1 -0
  183. package/dist/{usage-generator-BUdlhnCK.mjs → usage-generator-DTqaUMR9.mjs} +6 -3
  184. package/dist/usage-generator-DTqaUMR9.mjs.map +1 -0
  185. package/dist/validation-DUzcjb8Q.mjs +49 -0
  186. package/dist/validation-DUzcjb8Q.mjs.map +1 -0
  187. package/dist/validation.context-XTysWJ3b.mjs +117 -0
  188. package/dist/validation.context-XTysWJ3b.mjs.map +1 -0
  189. package/dist/websocket/index.d.mts +7 -14
  190. package/dist/websocket/index.d.mts.map +1 -1
  191. package/dist/websocket/index.mjs +2 -2
  192. package/dist/workers/index.d.mts +2 -2
  193. package/dist/workers/index.mjs +3 -2
  194. package/dist/workers/index.mjs.map +1 -1
  195. package/dist/{index-Bnpfq6uk.d.mts → zod-DvWTfRpI.d.mts} +58 -133
  196. package/dist/zod-DvWTfRpI.d.mts.map +1 -0
  197. package/dist/zod-hMa3rSHV.mjs +72 -0
  198. package/dist/zod-hMa3rSHV.mjs.map +1 -0
  199. package/package.json +20 -20
  200. package/dist/command-BgSlsS4M.mjs.map +0 -1
  201. package/dist/command-Bu-PjJrX.d.mts.map +0 -1
  202. package/dist/controller.decorator-DQzenvSN.mjs.map +0 -1
  203. package/dist/cron-manager-7Symz_TE.mjs.map +0 -1
  204. package/dist/cron-manager-BEsH1mjW.d.mts.map +0 -1
  205. package/dist/en-DSH_bhh6.mjs +0 -308
  206. package/dist/en-DSH_bhh6.mjs.map +0 -1
  207. package/dist/env-D1rcZ8_r.d.mts.map +0 -1
  208. package/dist/errors-BdyV5PnY.mjs +0 -1725
  209. package/dist/errors-BdyV5PnY.mjs.map +0 -1
  210. package/dist/errors-Da3Pz2X7.mjs +0 -74
  211. package/dist/errors-Da3Pz2X7.mjs.map +0 -1
  212. package/dist/events-COKixqnG.mjs.map +0 -1
  213. package/dist/gateway-context-CdJjpUCW.mjs.map +0 -1
  214. package/dist/guards-DUk_Kzst.mjs.map +0 -1
  215. package/dist/http-method.decorator-DXwxAfb_.mjs.map +0 -1
  216. package/dist/i18n.module-BBlNNlcG.mjs.map +0 -1
  217. package/dist/index-Bnpfq6uk.d.mts.map +0 -1
  218. package/dist/index-C1KvMncZ.d.mts.map +0 -1
  219. package/dist/index-CjaQ6_tZ.d.mts.map +0 -1
  220. package/dist/index-D0US0X14.d.mts.map +0 -1
  221. package/dist/index-DBd_2wv8.d.mts +0 -263
  222. package/dist/index-DBd_2wv8.d.mts.map +0 -1
  223. package/dist/index.d.mts.map +0 -1
  224. package/dist/logger-V6Ms3QnQ.mjs +0 -436
  225. package/dist/logger-V6Ms3QnQ.mjs.map +0 -1
  226. package/dist/module-Dk2qTa77.mjs +0 -860
  227. package/dist/module-Dk2qTa77.mjs.map +0 -1
  228. package/dist/openapi-tools.service-Zs-Ewv7F.mjs +0 -200
  229. package/dist/openapi-tools.service-Zs-Ewv7F.mjs.map +0 -1
  230. package/dist/openapi.service-BLgvn3hJ.d.mts.map +0 -1
  231. package/dist/quarry-registry-DNEej-Db.mjs +0 -688
  232. package/dist/quarry-registry-DNEej-Db.mjs.map +0 -1
  233. package/dist/queue.module-BCdCiySt.mjs.map +0 -1
  234. package/dist/r2-storage.provider-Co6F0ZYV.mjs.map +0 -1
  235. package/dist/rate-limit.decorator--o6Q6p9w.mjs.map +0 -1
  236. package/dist/resend.provider-M6qRLrcy.mjs.map +0 -1
  237. package/dist/seeder-CJAOHEIo.mjs.map +0 -1
  238. package/dist/setup-CefZKV_e.mjs +0 -37
  239. package/dist/setup-CefZKV_e.mjs.map +0 -1
  240. package/dist/smtp.provider-w0Ve52Xg.mjs.map +0 -1
  241. package/dist/storage-1zw-6Yiz.mjs.map +0 -1
  242. package/dist/storage-provider.interface-Bd6vA4ak.d.mts.map +0 -1
  243. package/dist/stratal-DeEcGgdq.mjs.map +0 -1
  244. package/dist/types-cySNS_lp.d.mts.map +0 -1
  245. package/dist/usage-generator-BUdlhnCK.mjs.map +0 -1
  246. package/dist/validation-DtJwAv7O.mjs +0 -248
  247. package/dist/validation-DtJwAv7O.mjs.map +0 -1
@@ -1,269 +1,48 @@
1
- import { t as Constructor } from "./types-cySNS_lp.mjs";
2
- import { t as Macroable } from "./index-7-hU3GTV.mjs";
3
- import { t as StratalEnv } from "./env-D1rcZ8_r.mjs";
4
- import { t as index_d_exports } from "./index-C1KvMncZ.mjs";
5
- import { C as MessageParams, S as MessageKeys, a as index_d_exports$1, b as II18nService, i as ZodError, o as z, t as OpenAPIHono, x as MessageKeyPrefix } from "./index-Bnpfq6uk.mjs";
6
- import { i as LoggerService, l as LogLevel } from "./index-DBd_2wv8.mjs";
7
- import { DependencyContainer, DependencyContainer as DependencyContainer$1, container as container$1, delay, inject as inject$1, injectable as injectable$1, instancePerContainerCachingFactory as instancePerContainerCachingFactory$1, singleton } from "tsyringe";
1
+ import { t as Macroable } from "./index-B4UBK-2T.mjs";
2
+ import { t as StratalEnv } from "./env-DKSbuBi5.mjs";
3
+ import { a as z, i as ZodError, o as zod_d_exports, t as OpenAPIHono } from "./zod-DvWTfRpI.mjs";
4
+ import { c as LogLevel, r as LoggerService } from "./index-BtlE9RuO.mjs";
5
+ import { t as Constructor } from "./types-BaeHi67f.mjs";
8
6
  import { AsyncLocalStorage } from "node:async_hooks";
9
7
  import { SSEMessage, SSEStreamingApi, SSEStreamingApi as SSEStreamingApi$1 } from "hono/streaming";
10
- import { CoreContext } from "@intlify/core-base";
11
- import { DetectorOptions } from "hono/language";
12
- import { Context, MiddlewareHandler, Next } from "hono";
13
8
  import { ContentfulStatusCode, RedirectStatusCode } from "hono/utils/http-status";
9
+ import { Context, MiddlewareHandler, Next } from "hono";
10
+ import { CookieOptions } from "hono/utils/cookie";
14
11
  import { StreamingApi, StreamingApi as StreamingApi$1 } from "hono/utils/stream";
15
- import InjectionToken$1, { default as InjectionToken$2 } from "tsyringe/dist/typings/providers/injection-token";
16
12
 
17
- //#region src/errors/error-response.d.ts
18
- type Environment = 'development' | 'staging' | 'production';
19
- interface ErrorResponse {
20
- /**
21
- * Numeric error code for identification and escalation
22
- * See error-codes.ts for the complete registry
23
- */
24
- code: number;
25
- /**
26
- * Human-readable error message
27
- * Fixed per error type, not customizable
28
- */
29
- message: string;
30
- /**
31
- * ISO timestamp when the error occurred
32
- */
33
- timestamp: string;
34
- /**
35
- * Additional structured data about the error
36
- * Only included in development environment
37
- */
38
- metadata?: Record<string, unknown>;
39
- /**
40
- * Stack trace for debugging
41
- * Only included in development environment
42
- */
43
- stack?: string;
44
- }
45
- /**
46
- * Type guard to check if an object is an ErrorResponse
47
- */
48
- declare function isErrorResponse(obj: unknown): obj is ErrorResponse;
49
- //#endregion
50
- //#region src/di/types.d.ts
51
- /**
52
- * Service scope for DI registration
53
- *
54
- * Maps directly to tsyringe's Lifecycle enum.
55
- * Scope is specified at registration time via provider configuration,
56
- * not at class decoration time.
57
- *
58
- * @example
59
- * ```typescript
60
- * // In module providers:
61
- * { provide: MY_TOKEN, useClass: MyService, scope: Scope.Singleton }
62
- *
63
- * // In Application.ts:
64
- * container.register(MY_TOKEN, MyService, Scope.Request)
65
- * ```
66
- */
67
- declare enum Scope {
68
- /** New instance per resolution (default) */
69
- Transient = 0,
70
- /** Single instance shared globally */
71
- Singleton = 1,
72
- /** New instance per child container (per request) */
73
- Request = 3
74
- }
75
- /**
76
- * Options for conditional binding with `when()` method
77
- */
78
- interface WhenOptions {
79
- /**
80
- * Cache predicate result after first evaluation.
81
- * When true, the predicate is evaluated once and the result is reused.
82
- * When false (default), predicate is evaluated on each resolution.
83
- */
84
- cache?: boolean;
85
- }
86
- /**
87
- * Decorator function type for extend() method
88
- *
89
- * @template T The service type being decorated
90
- */
91
- type ExtensionDecorator<T> = (service: T, container: ContainerLike) => T;
92
- /**
93
- * Minimal container interface for decorator functions
94
- * Avoids circular dependency with Container class
95
- */
96
- interface ContainerLike {
97
- resolve<T>(token: InjectionToken$1<T>): T;
98
- }
99
- //#endregion
100
- //#region src/di/conditional-binding-builder.d.ts
101
- /**
102
- * Container interface for predicate functions
103
- * Using a minimal interface to avoid circular imports
104
- */
105
- interface PredicateContainer {
106
- resolve<T>(token: InjectionToken$1<T>): T;
107
- isRegistered<T>(token: InjectionToken$1<T>): boolean;
108
- }
109
- /**
110
- * Initial builder returned by container.when()
111
- */
112
- interface ConditionalBindingBuilder {
113
- /**
114
- * Specify the token to conditionally bind
115
- *
116
- * @param token - DI token for the service
117
- * @returns Builder for specifying implementations
118
- */
119
- use<T extends object>(token: InjectionToken$1<T>): ConditionalBindingUse<T>;
120
- }
121
- /**
122
- * Builder after specifying token with use()
123
- */
124
- interface ConditionalBindingUse<T extends object> {
125
- /**
126
- * Specify the implementation when predicate returns true.
127
- * Registration is completed immediately.
128
- *
129
- * If predicate is false at resolution time:
130
- * - Uses `otherwise()` implementation if provided
131
- * - Falls back to existing registration if available
132
- * - Throws error if no fallback exists
133
- *
134
- * @param implementation - Service class to use when predicate is true
135
- * @returns Builder for optional fallback specification
136
- */
137
- give(implementation: Constructor<T>): ConditionalBindingGive<T>;
138
- }
139
- /**
140
- * Builder after specifying true implementation with give()
141
- * Registration is already complete at this point.
142
- */
143
- interface ConditionalBindingGive<T extends object> {
144
- /**
145
- * Optionally specify a fallback implementation when predicate returns false.
146
- * This re-registers with the explicit fallback instead of existing registration.
147
- *
148
- * @param implementation - Service class to use when predicate is false
149
- */
150
- otherwise(implementation: Constructor<T>): void;
151
- }
152
- /**
153
- * Implementation of ConditionalBindingBuilder
154
- *
155
- * @internal
156
- */
157
- declare class ConditionalBindingBuilderImpl implements ConditionalBindingBuilder {
158
- private readonly tsyringeContainer;
159
- private readonly predicateContainer;
160
- private readonly predicate;
161
- private readonly options;
162
- constructor(tsyringeContainer: DependencyContainer, predicateContainer: PredicateContainer, predicate: (container: PredicateContainer) => boolean, options: WhenOptions);
163
- use<T extends object>(token: InjectionToken$1<T>): ConditionalBindingUse<T>;
13
+ //#region src/errors/application-error.d.ts
14
+ declare class ApplicationError extends Error {
15
+ readonly timestamp: string;
16
+ constructor(message?: string, cause?: unknown);
164
17
  }
165
18
  //#endregion
166
- //#region src/di/container.d.ts
167
- /**
168
- * Options for creating a Container instance
169
- */
170
- interface ContainerOptions {
171
- /** Pre-created DependencyContainer */
172
- container: DependencyContainer;
173
- /** Whether this is a request-scoped container */
174
- isRequestScoped?: boolean;
175
- }
19
+ //#region src/di/tokens.d.ts
176
20
  /**
177
- * Unified Container for DI management
178
- *
179
- * Manages the two-tier container hierarchy:
180
- * - Global scope: Singletons, base instances of request-scoped services
181
- * - Request scope: Context-enriched instances per HTTP request
182
- *
183
- * @example Basic registration
184
- * ```typescript
185
- * import { container as tsyringeRootContainer } from 'tsyringe'
186
- *
187
- * const container = new Container({
188
- * container: tsyringeRootContainer.createChildContainer()
189
- * })
190
- *
191
- * container.register(I18nService)
192
- * container.register(MY_TOKEN, MyService)
193
- * container.registerSingleton(ConfigService)
194
- * container.registerValue(MY_TOKEN, myInstance)
195
- * ```
196
- *
197
- * @example Request scope (automatic lifecycle)
198
- * ```typescript
199
- * await container.runInRequestScope(routerContext, async (requestContainer) => {
200
- * const i18n = requestContainer.resolve(I18N_TOKEN)
201
- * })
202
- * ```
21
+ * Token for the Container instance
22
+ * Used for injecting the Container into services that need dynamic resolution
203
23
  */
204
- declare class Container {
205
- private readonly container;
206
- private readonly isRequestScoped;
207
- constructor(options: ContainerOptions);
208
- /**
209
- * Register a service with optional explicit token and scope
210
- */
211
- register<T extends object>(serviceClass: Constructor<T>, scope?: Scope): void;
212
- register<T extends object>(token: InjectionToken$1<T>, serviceClass: Constructor<T>, scope?: Scope): void;
213
- /**
214
- * Register a service as singleton
215
- */
216
- registerSingleton<T extends object>(serviceClass: Constructor<T>): void;
217
- registerSingleton<T extends object>(token: InjectionToken$1<T>, serviceClass: Constructor<T>): void;
218
- /**
219
- * Register a value (instance) directly
220
- */
221
- registerValue<T>(token: InjectionToken$1<T>, value: T): void;
222
- /**
223
- * Register with factory function
224
- */
225
- registerFactory<T>(token: InjectionToken$1<T>, factory: (container: Container) => T): void;
226
- /**
227
- * Register an alias to an existing token
228
- */
229
- registerExisting<T>(alias: InjectionToken$1<T>, target: InjectionToken$1<T>): void;
230
- /**
231
- * Resolve a service from the container
232
- */
233
- resolve<T>(token: InjectionToken$1<T>): T;
234
- /**
235
- * Check if a token is registered
236
- */
237
- isRegistered<T>(token: InjectionToken$1<T>): boolean;
238
- /**
239
- * Start a conditional binding with predicate evaluation
240
- */
241
- when(predicate: (container: PredicateContainer) => boolean, options?: WhenOptions): ConditionalBindingBuilder;
242
- /**
243
- * Replace a service registration with a decorated version
244
- */
245
- extend<T>(token: InjectionToken$1<T>, decorator: ExtensionDecorator<T>): void;
246
- /**
247
- * Run callback within request scope
248
- *
249
- * Creates a child container with fresh instances for services registered with `scope: Scope.Request`.
250
- * Callback receives the request-scoped container as argument.
251
- *
252
- * Can only be called on global container (not request-scoped).
253
- */
254
- runInRequestScope<T>(routerContext: RouterContext, callback: (requestContainer: Container) => T | Promise<T>): Promise<T>;
255
- /**
256
- * Create request scope container
257
- *
258
- * Can only be called on global container (not request-scoped).
259
- */
260
- createRequestScope(routerContext: RouterContext): Container;
24
+ declare const CONTAINER_TOKEN: unique symbol;
25
+ declare const DI_TOKENS: {
26
+ readonly CloudflareEnv: symbol;
27
+ readonly ExecutionContext: symbol;
28
+ readonly Container: typeof CONTAINER_TOKEN;
29
+ readonly Application: symbol;
30
+ readonly ModuleRegistry: symbol;
31
+ readonly ExceptionHandler: symbol;
32
+ readonly Database: symbol;
33
+ readonly Queue: symbol;
34
+ readonly ConsumerRegistry: symbol;
35
+ readonly Cron: symbol;
36
+ readonly EventRegistry: symbol;
37
+ readonly Quarry: symbol;
261
38
  /**
262
- * Get underlying tsyringe container
39
+ * AuthContext: Use for services that need user authentication (userId).
263
40
  */
264
- getTsyringeContainer(): DependencyContainer;
265
- dispose(): void | Promise<void>;
266
- }
41
+ readonly AuthContext: symbol;
42
+ readonly DurableObjectState: symbol;
43
+ readonly DurableObjectId: symbol;
44
+ };
45
+ type DIToken = typeof DI_TOKENS[keyof typeof DI_TOKENS];
267
46
  //#endregion
268
47
  //#region src/router/route-map.d.ts
269
48
  /**
@@ -358,228 +137,44 @@ type RouteMatcher = keyof StratalRouteMap extends never ? string : RouteName | `
358
137
  */
359
138
  type RoutePrefixes<S extends string> = S extends `${infer Head}.${infer Rest}` ? Head | `${Head}.${RoutePrefixes<Rest>}` : never;
360
139
  //#endregion
361
- //#region src/di/tokens.d.ts
140
+ //#region src/router/constants.d.ts
362
141
  /**
363
- * Token for the Container instance
364
- * Used for injecting the Container into services that need dynamic resolution
142
+ * Type-safe context keys for Hono router variables
143
+ * Using symbols to avoid string collisions
365
144
  */
366
- declare const CONTAINER_TOKEN: unique symbol;
367
- declare const DI_TOKENS: {
368
- readonly CloudflareEnv: symbol;
369
- readonly ExecutionContext: symbol;
370
- readonly Container: typeof CONTAINER_TOKEN;
371
- readonly Application: symbol;
372
- readonly ModuleRegistry: symbol;
373
- readonly ExceptionHandler: symbol;
374
- readonly Database: symbol;
375
- readonly Queue: symbol;
376
- readonly ConsumerRegistry: symbol;
377
- readonly Cron: symbol;
378
- readonly EventRegistry: symbol;
379
- readonly Quarry: symbol;
380
- /**
381
- * AuthContext: Use for services that need user authentication (userId).
382
- */
383
- readonly AuthContext: symbol;
384
- readonly DurableObjectState: symbol;
385
- readonly DurableObjectId: symbol;
145
+ declare const ROUTER_CONTEXT_KEYS: {
146
+ readonly REQUEST_CONTAINER: "requestContainer";
147
+ readonly LOCALE: "locale";
386
148
  };
387
- type DIToken = typeof DI_TOKENS[keyof typeof DI_TOKENS];
388
- //#endregion
389
- //#region src/di/decorators/inject-param.decorator.d.ts
390
- /**
391
- * Metadata key for storing parameter injection information
392
- */
393
- declare const INJECT_PARAM_METADATA_KEY: unique symbol;
394
149
  /**
395
- * Describes a parameter injection
150
+ * Metadata keys for storing route and controller configuration
151
+ * Using symbols to avoid collisions with other decorators
396
152
  */
397
- interface ParamInjection {
398
- /** Parameter index in the method signature (0-based) */
399
- index: number;
400
- /** DI token to resolve */
401
- token: InjectionToken$1;
402
- }
153
+ declare const ROUTE_METADATA_KEYS: {
154
+ readonly CONTROLLER_ROUTE: symbol;
155
+ readonly CONTROLLER_OPTIONS: symbol;
156
+ readonly CONTROLLER_MIDDLEWARES: symbol;
157
+ readonly ROUTE_CONFIG: symbol;
158
+ readonly DECORATED_METHODS: symbol;
159
+ readonly AUTH_GUARD: symbol;
160
+ readonly GATEWAY_MARKER: symbol;
161
+ readonly WS_ON_MESSAGE: symbol;
162
+ readonly WS_ON_CLOSE: symbol;
163
+ readonly WS_ON_ERROR: symbol;
164
+ readonly RATE_LIMIT: symbol;
165
+ };
403
166
  /**
404
- * Mark a method parameter for DI injection
405
- *
406
- * The parameter will be resolved from the request-scoped container
407
- * when the controller method is invoked.
408
- *
409
- * @param token - DI token to resolve (class or symbol)
410
- *
411
- * @example With class token
412
- * ```typescript
413
- * async show(
414
- * ctx: RouterContext,
415
- * @InjectParam(UserService) userService: UserService
416
- * ) { }
417
- * ```
418
- *
419
- * @example With symbol token
420
- * ```typescript
421
- * async show(
422
- * ctx: RouterContext,
423
- * @InjectParam(DI_TOKENS.Cache) cache: ICacheService
424
- * ) { }
425
- * ```
167
+ * Security scheme identifiers for OpenAPI
168
+ * These reference the security scheme definitions in security.schemas.ts
426
169
  */
427
- declare function InjectParam<T>(token: InjectionToken$1<T>): ParameterDecorator;
170
+ declare const SECURITY_SCHEMES: {
171
+ readonly BEARER_AUTH: "bearerAuth";
172
+ readonly API_KEY: "apiKey";
173
+ readonly SESSION_COOKIE: "sessionCookie";
174
+ };
428
175
  /**
429
- * Get method parameter injections
430
- *
431
- * @param target - Controller prototype
432
- * @param propertyKey - Method name
433
- * @returns Array of parameter injections sorted by index
434
- */
435
- declare function getMethodInjections(target: object, propertyKey: string | symbol): ParamInjection[];
436
- //#endregion
437
- //#region src/di/decorators.d.ts
438
- /**
439
- * Mark a class as injectable
440
- *
441
- * This decorator wraps tsyringe's `@injectable` decorator and optionally
442
- * associates a token with the class. The actual lifecycle (Singleton, Request,
443
- * Transient) is determined at registration time, not decoration time.
444
- *
445
- * **Lifecycle Control:**
446
- * - Use `scope: Scope.Singleton` in module providers for singleton
447
- * - Use `scope: Scope.Request` in module providers for request-scoped
448
- * - Default is Transient (new instance per resolution)
449
- *
450
- * @param token - Optional DI token for service resolution
451
- *
452
- * @example Basic usage (no token)
453
- * ```typescript
454
- * @Transient()
455
- * export class UserService {
456
- * constructor(@inject(DI_TOKENS.Database) private db: DatabaseService) {}
457
- * }
458
- *
459
- * // In module:
460
- * @Module({
461
- * providers: [UserService] // Transient by default
462
- * })
463
- * ```
464
- *
465
- * @example With token
466
- * ```typescript
467
- * @Transient(DI_TOKENS.ConnectionManager)
468
- * export class ConnectionManager implements Disposable {
469
- * // ...
470
- * }
471
- *
472
- * // In Application.ts:
473
- * container.register(DI_TOKENS.ConnectionManager, ConnectionManager, Scope.Request)
474
- * ```
475
- *
476
- * @example Singleton via provider scope
477
- * ```typescript
478
- * @Transient()
479
- * export class ConsumerRegistry {
480
- * // ...
481
- * }
482
- *
483
- * // In module:
484
- * @Module({
485
- * providers: [
486
- * { provide: DI_TOKENS.ConsumerRegistry, useClass: ConsumerRegistry, scope: Scope.Singleton }
487
- * ]
488
- * })
489
- * ```
490
- */
491
- declare function Transient<T>(token?: InjectionToken$1<T>): <TFunction extends abstract new (...args: never[]) => unknown>(target: TFunction) => TFunction;
492
- //#endregion
493
- //#region src/di/errors/conditional-binding-fallback.error.d.ts
494
- /**
495
- * ConditionalBindingFallbackError
496
- *
497
- * Thrown when a conditional binding predicate returns false but no fallback
498
- * implementation was provided and no existing registration exists for the token.
499
- *
500
- * This typically indicates a misconfiguration in the DI setup where:
501
- * - A `when().use().give()` chain was used without `otherwise()`
502
- * - AND the token wasn't previously registered
503
- * - AND the predicate evaluated to false at resolution time
504
- */
505
- declare class ConditionalBindingFallbackError extends ApplicationError {
506
- constructor(token: string);
507
- }
508
- //#endregion
509
- //#region src/di/errors/request-scope-operation-not-allowed.error.d.ts
510
- /**
511
- * RequestScopeOperationNotAllowedError
512
- *
513
- * Thrown when attempting to call a method that is not allowed on the current container scope.
514
- * - `createRequestScope()` and `runInRequestScope()` can only be called on global containers
515
- */
516
- declare class RequestScopeOperationNotAllowedError extends ApplicationError {
517
- constructor(methodName: string);
518
- }
519
- //#endregion
520
- //#region src/di/container-storage.d.ts
521
- /**
522
- * AsyncLocalStorage for the application container.
523
- *
524
- * Set by `Application.initialize()` — all code from that point onward
525
- * (Stratal handlers, TestingModuleBuilder, standalone functions like `route()`)
526
- * can access the container without DI or static singletons.
527
- *
528
- * Follows the same pattern as `errorMapContextStorage` in `i18n/validation/validation.context.ts`.
529
- */
530
- declare const containerStorage: AsyncLocalStorage<Container>;
531
- /**
532
- * Get the application container from AsyncLocalStorage.
533
- *
534
- * @throws ContainerNotInitializedError if called outside `Application.initialize()` scope
535
- */
536
- declare function getContainer(): Container;
537
- /**
538
- * Run a function within a container context.
539
- *
540
- * @param container - The application container to store
541
- * @param fn - The function to execute with container access
542
- */
543
- declare function runWithContainer<T>(container: Container, fn: () => T): T;
544
- //#endregion
545
- //#region src/router/constants.d.ts
546
- /**
547
- * Type-safe context keys for Hono router variables
548
- * Using symbols to avoid string collisions
549
- */
550
- declare const ROUTER_CONTEXT_KEYS: {
551
- readonly REQUEST_CONTAINER: "requestContainer";
552
- readonly LOCALE: "locale";
553
- };
554
- /**
555
- * Metadata keys for storing route and controller configuration
556
- * Using symbols to avoid collisions with other decorators
557
- */
558
- declare const ROUTE_METADATA_KEYS: {
559
- readonly CONTROLLER_ROUTE: symbol;
560
- readonly CONTROLLER_OPTIONS: symbol;
561
- readonly CONTROLLER_MIDDLEWARES: symbol;
562
- readonly ROUTE_CONFIG: symbol;
563
- readonly DECORATED_METHODS: symbol;
564
- readonly AUTH_GUARD: symbol;
565
- readonly GATEWAY_MARKER: symbol;
566
- readonly WS_ON_MESSAGE: symbol;
567
- readonly WS_ON_CLOSE: symbol;
568
- readonly WS_ON_ERROR: symbol;
569
- readonly RATE_LIMIT: symbol;
570
- };
571
- /**
572
- * Security scheme identifiers for OpenAPI
573
- * These reference the security scheme definitions in security.schemas.ts
574
- */
575
- declare const SECURITY_SCHEMES: {
576
- readonly BEARER_AUTH: "bearerAuth";
577
- readonly API_KEY: "apiKey";
578
- readonly SESSION_COOKIE: "sessionCookie";
579
- };
580
- /**
581
- * HTTP method mapping for RESTful controller methods
582
- * Maps controller method names to HTTP verbs and path patterns
176
+ * HTTP method mapping for RESTful controller methods
177
+ * Maps controller method names to HTTP verbs and path patterns
583
178
  */
584
179
  declare const HTTP_METHODS: {
585
180
  readonly index: {
@@ -618,7 +213,7 @@ declare const VERSION_NEUTRAL: unique symbol;
618
213
  * Route parameter type for OpenAPI
619
214
  * ZodObject or ZodPipe (piped validation)
620
215
  */
621
- type ZodObjectWithEffect = index_d_exports$1.ZodObject<any> | index_d_exports$1.ZodPipe<any, any>;
216
+ type ZodObjectWithEffect = zod_d_exports.ZodObject<any> | zod_d_exports.ZodPipe<any, any>;
622
217
  type RouteParameter = ZodObjectWithEffect | undefined;
623
218
  /**
624
219
  * Hono context variables with type-safe keys
@@ -655,19 +250,19 @@ type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'option
655
250
  * Object form for request body with optional content type
656
251
  */
657
252
  interface RouteBodyObject {
658
- schema: index_d_exports$1.ZodType;
253
+ schema: zod_d_exports.ZodType;
659
254
  contentType?: string;
660
255
  }
661
256
  /**
662
257
  * Request body definition for @Route() decorator
663
258
  * Bare ZodType defaults to application/json
664
259
  */
665
- type RouteBody = index_d_exports$1.ZodType | RouteBodyObject;
260
+ type RouteBody = zod_d_exports.ZodType | RouteBodyObject;
666
261
  /**
667
262
  * Object form for response with optional description and content type
668
263
  */
669
264
  interface RouteResponseObject {
670
- schema: index_d_exports$1.ZodType;
265
+ schema: zod_d_exports.ZodType;
671
266
  description?: string;
672
267
  contentType?: string;
673
268
  }
@@ -675,7 +270,7 @@ interface RouteResponseObject {
675
270
  * Single response definition for @Route() decorator
676
271
  * Status code is auto-derived from method name (create->201, others->200)
677
272
  */
678
- type RouteResponse = index_d_exports$1.ZodType | RouteResponseObject;
273
+ type RouteResponse = zod_d_exports.ZodType | RouteResponseObject;
679
274
  /**
680
275
  * Route configuration for @Route() decorator
681
276
  * Defines OpenAPI metadata for a controller method
@@ -865,667 +460,159 @@ interface StratalExecutionContext {
865
460
  waitUntil(promise: Promise<unknown>): void;
866
461
  }
867
462
  //#endregion
868
- //#region src/errors/exception-handler.types.d.ts
463
+ //#region src/di/lazy.d.ts
464
+ declare const LAZY_MARKER: unique symbol;
465
+ interface LazyToken<T = unknown> {
466
+ [LAZY_MARKER]: true;
467
+ factory: () => Constructor<T>;
468
+ }
469
+ declare function lazy<T>(factory: () => Constructor<T>): LazyToken<T>;
470
+ declare function isLazyToken(value: unknown): value is LazyToken;
471
+ //#endregion
472
+ //#region src/di/types.d.ts
473
+ type InjectionToken<T = unknown> = Constructor<T> | string | symbol | LazyToken<T>;
474
+ declare enum Scope {
475
+ Transient = 0,
476
+ Singleton = 1,
477
+ Request = 2
478
+ }
479
+ interface WhenOptions {
480
+ cache?: boolean;
481
+ }
482
+ type ExtensionDecorator<T> = (service: T, container: ContainerLike) => T;
483
+ interface ContainerLike {
484
+ resolve<T>(token: InjectionToken<T>): T;
485
+ }
486
+ //#endregion
487
+ //#region src/module/types.d.ts
488
+ interface ClassProvider<T extends object = object> {
489
+ provide: InjectionToken<T>;
490
+ useClass: Constructor<T>;
491
+ }
492
+ interface ValueProvider<T extends object = object> {
493
+ provide: InjectionToken<T>;
494
+ useValue: T;
495
+ }
496
+ interface FactoryProvider<T extends object = object> {
497
+ provide: InjectionToken<T>;
498
+ useFactory: (...deps: any[]) => T | Promise<T>;
499
+ inject?: InjectionToken[];
500
+ }
501
+ interface ExistingProvider<T extends object = object> {
502
+ provide: InjectionToken<T>;
503
+ useExisting: InjectionToken<T>;
504
+ }
505
+ type Provider<T extends object = object> = Constructor<T> | ClassProvider<T> | ValueProvider<T> | FactoryProvider<T> | ExistingProvider<T>;
506
+ interface ModuleClass<T extends object = object> extends Constructor<T> {
507
+ forRoot?: (...args: unknown[]) => DynamicModule;
508
+ forRootAsync?: <TOptions>(options: AsyncModuleOptions<TOptions>) => DynamicModule;
509
+ }
510
+ interface ModuleOptions {
511
+ imports?: (ModuleClass | DynamicModule)[];
512
+ providers?: Provider[];
513
+ controllers?: Constructor[];
514
+ consumers?: Constructor[];
515
+ jobs?: Constructor[];
516
+ }
517
+ interface DynamicModule extends Omit<ModuleOptions, 'imports'> {
518
+ module: Constructor;
519
+ }
520
+ interface AsyncModuleOptions<TOptions> {
521
+ inject?: InjectionToken[];
522
+ useFactory: (...deps: any[]) => TOptions | Promise<TOptions>;
523
+ }
524
+ interface ModuleContext {
525
+ container: Container;
526
+ logger: LoggerService;
527
+ }
528
+ interface OnInitialize {
529
+ onInitialize(context: ModuleContext): void | Promise<void>;
530
+ }
531
+ interface OnShutdown {
532
+ onShutdown(context: ModuleContext): void | Promise<void>;
533
+ }
534
+ interface OnException {
535
+ onException(handler: ExceptionHandler): void;
536
+ }
537
+ //#endregion
538
+ //#region src/quarry/types.d.ts
869
539
  /**
870
- * Log severity levels for exception reporting.
540
+ * Flat input object for programmatic command invocation.
871
541
  */
872
- type LogSeverity = 'error' | 'warn' | 'info' | 'debug';
542
+ type CommandInput = Record<string, unknown>;
873
543
  /**
874
- * Callback invoked when a specific exception type is reported.
875
- *
876
- * @typeParam T - The exception type this callback handles
877
- * @param error - The matched exception instance
878
- * @param context - The execution context where the error occurred
544
+ * Result of a command execution.
879
545
  */
880
- type ReportableCallback<T extends ApplicationError> = (error: T, context: ExceptionContext) => void | Promise<void>;
546
+ interface CommandResult {
547
+ exitCode: number;
548
+ output: string[];
549
+ errors: string[];
550
+ }
881
551
  /**
882
- * Callback invoked to render a specific exception type into a Response.
883
- *
884
- * Return `undefined` to fall through to the default renderer.
552
+ * User-facing Quarry interface. Only exposes the `call()` method.
885
553
  *
886
- * @typeParam T - The exception type this callback handles
887
- * @param error - The matched exception instance
888
- * @param context - The execution context where the error occurred
889
- * @returns A Response, ErrorResponse, or undefined to fall through
554
+ * Inject via `@inject(DI_TOKENS.Quarry)` and type as `Quarry`.
890
555
  */
891
- type RenderableCallback<T extends ApplicationError> = (error: T, context: ExceptionContext) => Response | ErrorResponse | Promise<Response> | undefined;
556
+ interface Quarry {
557
+ call(name: string, input?: CommandInput): Promise<CommandResult>;
558
+ }
892
559
  /**
893
- * Callback invoked to post-process every error Response before it is returned.
894
- *
895
- * Use this to add headers, change the response body, swap content type, etc.
896
- *
897
- * @param response - The rendered Response
898
- * @param error - The original exception
899
- * @param context - The execution context where the error occurred
900
- * @returns The (possibly modified) Response
560
+ * Internal mutable state stored on Command instances via Symbol key.
561
+ * @internal
901
562
  */
902
- type RespondCallback = (response: Response, error: ApplicationError, context: ExceptionContext) => Response;
563
+ interface CommandInternals {
564
+ inputs: CommandInput;
565
+ output: string[];
566
+ errors: string[];
567
+ exitCode: number;
568
+ quarry: Quarry | null;
569
+ }
903
570
  /**
904
- * Callback that returns additional context data to include in all exception logs.
905
- *
906
- * @returns Key-value pairs merged into every log entry
571
+ * A parsed argument from a Laravel-style signature string.
907
572
  */
908
- type ContextCallback = () => Record<string, unknown>;
573
+ interface ParsedArgument {
574
+ name: string;
575
+ required: boolean;
576
+ default?: string;
577
+ description?: string;
578
+ isArray: boolean;
579
+ }
909
580
  /**
910
- * Handle returned by `reportable()` to control whether default reporting runs.
581
+ * A parsed option from a Laravel-style signature string.
911
582
  */
912
- interface Reportable {
913
- /**
914
- * Prevent the default logger from reporting this exception
915
- * after the custom reportable callback has run.
916
- */
917
- stop(): void;
583
+ interface ParsedOption {
584
+ name: string;
585
+ alias?: string;
586
+ isFlag: boolean;
587
+ isArray: boolean;
588
+ default?: string;
589
+ description?: string;
918
590
  }
919
591
  /**
920
- * Constructor type for ApplicationError subclasses.
592
+ * Fully parsed command signature.
921
593
  */
922
- type ApplicationErrorConstructor<T extends ApplicationError = ApplicationError> = new (...args: any[]) => T;
594
+ interface ParsedSignature {
595
+ name: string;
596
+ arguments: ParsedArgument[];
597
+ options: ParsedOption[];
598
+ }
923
599
  //#endregion
924
- //#region src/errors/exception-handler.d.ts
600
+ //#region src/router/controller.d.ts
925
601
  /**
926
- * ExceptionHandler Laravel-inspired exception handling for Stratal.
927
- *
928
- * Provides a composable, expressive API for controlling how exceptions are
929
- * reported (logged / sent to external services) and rendered (turned into
930
- * HTTP Responses or ErrorResponse objects).
931
- *
932
- * **Lifecycle:**
933
- * 1. The framework resolves this from the DI container (once at init time).
934
- * 2. `register()` is called to let the user configure reporting / rendering.
935
- * 3. Module `onException()` hooks contribute additional configuration.
936
- * 4. On every error, `handle()` runs the pipeline: normalize → report → render → respond.
937
- *
938
- * **Usage — extend and override `register()`:**
602
+ * Controller interface for handling HTTP requests
939
603
  *
940
- * @example
941
- * ```typescript
942
- * export class AppExceptionHandler extends ExceptionHandler {
943
- * register(): void {
944
- * this.reportable(PaymentError, (e, ctx) => {
945
- * this.resolve(SentryService).captureException(e)
946
- * }).stop()
604
+ * Controllers can implement RESTful methods or a custom handle() method.
605
+ * The route for the controller is set via the `@Controller` decorator.
947
606
  *
948
- * this.renderable(MaintenanceError, (e, ctx) => {
949
- * if (ctx.type === 'http') return ctx.ctx.html('<h1>Maintenance</h1>', 503)
950
- * })
607
+ * RESTful methods auto-map to HTTP verbs:
608
+ * - index() GET /route
609
+ * - show() → GET /route/:id
610
+ * - create() → POST /route
611
+ * - update() → PUT /route/:id
612
+ * - patch() → PATCH /route/:id
613
+ * - destroy() → DELETE /route/:id
951
614
  *
952
- * this.dontReport([RouteNotFoundError])
953
- * this.level(RecordNotFoundError, 'warn')
954
- * this.context(() => ({ region: 'us-east-1' }))
955
- * this.respond((res, err) => {
956
- * res.headers.set('X-Error-Code', String(err.code))
957
- * return res
958
- * })
959
- * }
960
- * }
961
- * ```
962
- */
963
- declare abstract class ExceptionHandler {
964
- protected readonly logger: LoggerService;
965
- protected readonly env: StratalEnv;
966
- private readonly container;
967
- private readonly executionContext;
968
- private readonly reportables;
969
- private readonly renderables;
970
- private readonly dontReportSet;
971
- private readonly levelOverrides;
972
- private readonly contextCallbacks;
973
- private readonly respondCallbacks;
974
- private readonly environment;
975
- constructor(logger: LoggerService, env: StratalEnv, container: Container, executionContext: StratalExecutionContext);
976
- /**
977
- * Configure exception reporting and rendering.
978
- *
979
- * Override this method in your handler class to register custom
980
- * `reportable()`, `renderable()`, `dontReport()`, `level()`,
981
- * `context()`, and `respond()` callbacks.
982
- */
983
- abstract register(): void;
984
- /**
985
- * Register a custom reporting callback for a specific exception type.
986
- *
987
- * The callback is invoked when an error matching `errorClass` (via `instanceof`)
988
- * is thrown. Chain `.stop()` to prevent the default logger from also reporting.
989
- *
990
- * @typeParam T - The exception type to match
991
- * @param errorClass - Constructor of the exception to match
992
- * @param callback - Reporting function receiving the typed error and context
993
- * @returns A {@link Reportable} with a `stop()` method
994
- *
995
- * @example
996
- * ```typescript
997
- * this.reportable(PaymentError, (e, ctx) => {
998
- * sentry.captureException(e)
999
- * }).stop() // skip default logging
1000
- * ```
1001
- */
1002
- reportable<T extends ApplicationError>(errorClass: ApplicationErrorConstructor<T>, callback: ReportableCallback<T>): Reportable;
1003
- /**
1004
- * Register a custom rendering callback for a specific exception type.
1005
- *
1006
- * The callback should return a `Response` (for HTTP contexts), an `ErrorResponse`,
1007
- * or `undefined` to fall through to the default renderer.
1008
- *
1009
- * @typeParam T - The exception type to match
1010
- * @param errorClass - Constructor of the exception to match
1011
- * @param callback - Rendering function receiving the typed error and context
1012
- *
1013
- * @example
1014
- * ```typescript
1015
- * this.renderable(MaintenanceError, (e, ctx) => {
1016
- * if (ctx.type === 'http') {
1017
- * return ctx.ctx.html('<h1>Down for maintenance</h1>', 503)
1018
- * }
1019
- * })
1020
- * ```
1021
- */
1022
- renderable<T extends ApplicationError>(errorClass: ApplicationErrorConstructor<T>, callback: RenderableCallback<T>): void;
1023
- /**
1024
- * Suppress reporting (logging) for the given exception types.
1025
- *
1026
- * Errors matching these classes will still be rendered into responses
1027
- * but will not be logged or sent to external reporters.
1028
- *
1029
- * @param errorClasses - Array of exception constructors to suppress
1030
- *
1031
- * @example
1032
- * ```typescript
1033
- * this.dontReport([RouteNotFoundError, SchemaValidationError])
1034
- * ```
1035
- */
1036
- dontReport(errorClasses: ApplicationErrorConstructor[]): void;
1037
- /**
1038
- * Override the log severity for a specific exception type.
1039
- *
1040
- * By default, severity is derived from the error code range.
1041
- * Use this to promote or demote specific errors.
1042
- *
1043
- * @param errorClass - Constructor of the exception to override
1044
- * @param severity - The log severity to use
1045
- *
1046
- * @example
1047
- * ```typescript
1048
- * this.level(RecordNotFoundError, 'warn')
1049
- * ```
1050
- */
1051
- level(errorClass: ApplicationErrorConstructor, severity: LogSeverity): void;
1052
- /**
1053
- * Add global context data to all exception log entries.
1054
- *
1055
- * The callback is invoked on every reported error and its return value
1056
- * is merged into the log data.
1057
- *
1058
- * @param callback - Function returning key-value pairs to include in logs
1059
- *
1060
- * @example
1061
- * ```typescript
1062
- * this.context(() => ({
1063
- * appVersion: '1.2.3',
1064
- * region: env.CF_REGION,
1065
- * }))
1066
- * ```
1067
- */
1068
- context(callback: ContextCallback): void;
1069
- /**
1070
- * Register a callback to post-process every error Response before it is returned.
1071
- *
1072
- * Use this to add headers, modify the body, change content type, or
1073
- * transform the response in any way.
1074
- *
1075
- * @param callback - Function receiving (response, error, context) and returning a Response
1076
- *
1077
- * @example
1078
- * ```typescript
1079
- * this.respond((response, error, ctx) => {
1080
- * response.headers.set('X-Error-Code', String(error.code))
1081
- * return response
1082
- * })
1083
- * ```
1084
- */
1085
- respond(callback: RespondCallback): void;
1086
- /**
1087
- * Resolve a service from the DI container.
1088
- *
1089
- * Useful inside `register()` callbacks for accessing injected services
1090
- * (e.g., Sentry, analytics, custom loggers).
1091
- *
1092
- * @typeParam T - The type of the service to resolve
1093
- * @param token - DI token (symbol or constructor)
1094
- * @returns The resolved service instance
1095
- *
1096
- * @example
1097
- * ```typescript
1098
- * this.reportable(CriticalError, (e) => {
1099
- * this.resolve(SentryService).captureException(e)
1100
- * })
1101
- * ```
1102
- */
1103
- resolve<T>(token: symbol | (new (...args: unknown[]) => T)): T;
1104
- /**
1105
- * Handle an error through the full exception pipeline.
1106
- *
1107
- * This is the single entry point used by all contexts (HTTP, queue, cron, CLI).
1108
- * It normalizes the error, reports it (non-blocking via `waitUntil`),
1109
- * renders it into a Response, and applies post-processing.
1110
- *
1111
- * @param error - The thrown error (may or may not be an ApplicationError)
1112
- * @param context - The execution context where the error occurred
1113
- * @returns A Response (JSON by default, customizable via renderable/respond)
1114
- */
1115
- handle(error: unknown, context: ExceptionContext): Promise<Response>;
1116
- /**
1117
- * Normalize an unknown error into an ApplicationError.
1118
- * Non-ApplicationError values are wrapped in InternalError.
1119
- */
1120
- private normalizeError;
1121
- /**
1122
- * Run the reporting pipeline for an error.
1123
- */
1124
- private performReport;
1125
- /**
1126
- * Run the rendering pipeline for an error, producing a Response.
1127
- */
1128
- private performRender;
1129
- /**
1130
- * Apply all respond() callbacks to post-process a Response.
1131
- */
1132
- private applyRespondCallbacks;
1133
- /**
1134
- * Check if an error is in the dontReport set.
1135
- */
1136
- private shouldNotReport;
1137
- /**
1138
- * Find the most-specific reportable entry for an error.
1139
- * Walks entries in registration order; picks the most-specific `instanceof` match.
1140
- */
1141
- private findReportable;
1142
- /**
1143
- * Find the most-specific renderable entry for an error.
1144
- */
1145
- private findRenderable;
1146
- /**
1147
- * Default reporting — log with appropriate severity and i18n translation.
1148
- */
1149
- private defaultReport;
1150
- /**
1151
- * Default rendering — content-negotiated.
1152
- *
1153
- * For HTTP requests that accept HTML: renders a minimal branded HTML page.
1154
- * For everything else (API, queue, cron, CLI): returns JSON.
1155
- *
1156
- * Errors are always logged via `performReport` (non-blocking waitUntil),
1157
- * so they appear in the console regardless of the rendered response format.
1158
- */
1159
- private defaultRender;
1160
- /**
1161
- * Check if the HTTP request prefers an HTML response.
1162
- *
1163
- * Uses the `Accept` header to determine format. Inertia v3 XHR requests
1164
- * send `Accept: text/html, application/xhtml+xml`, so they naturally
1165
- * receive HTML error pages (displayed in Inertia's error modal in dev).
1166
- *
1167
- * Override in a subclass to customize content negotiation logic.
1168
- */
1169
- protected wantsHtml(context: HttpExceptionContext): boolean;
1170
- /**
1171
- * Minimal production HTML error page with inline styles.
1172
- */
1173
- private renderDefaultHtml;
1174
- private escapeHtml;
1175
- /**
1176
- * Convert a render result (Response or ErrorResponse) into a Response.
1177
- */
1178
- private toResponse;
1179
- /**
1180
- * Translate an error's message key via i18n.
1181
- * Uses the request container (from HTTP context) for correct locale,
1182
- * falling back to the global container or raw message string.
1183
- */
1184
- private translateError;
1185
- /**
1186
- * Resolve the log severity for an error.
1187
- * Checks level overrides first, then falls back to code-range-based severity.
1188
- */
1189
- private resolveSeverity;
1190
- /**
1191
- * Determine default log severity based on error code range.
1192
- */
1193
- private getDefaultSeverity;
1194
- /**
1195
- * Gather all global context data from registered callbacks.
1196
- */
1197
- private gatherContext;
1198
- }
1199
- //#endregion
1200
- //#region src/module/types.d.ts
1201
- /**
1202
- * Provider that uses a class constructor
1203
- *
1204
- * @example Transient (default)
1205
- * ```typescript
1206
- * { provide: UserService, useClass: UserService }
1207
- * ```
1208
- *
1209
- * @example Singleton
1210
- * ```typescript
1211
- * { provide: DI_TOKENS.ConsumerRegistry, useClass: ConsumerRegistry, scope: Scope.Singleton }
1212
- * ```
1213
- *
1214
- * @example Request-scoped
1215
- * ```typescript
1216
- * { provide: DI_TOKENS.ConnectionManager, useClass: ConnectionManager, scope: Scope.Request }
1217
- * ```
1218
- */
1219
- interface ClassProvider<T extends object = object> {
1220
- provide: InjectionToken$2<T>;
1221
- useClass: Constructor<T>;
1222
- /** Lifecycle scope - defaults to Transient if not specified */
1223
- scope?: Scope;
1224
- }
1225
- /**
1226
- * Provider that uses a pre-created value
1227
- *
1228
- * Note: Values are inherently singleton-like (same instance always returned).
1229
- * No scope option needed.
1230
- */
1231
- interface ValueProvider<T extends object = object> {
1232
- provide: InjectionToken$2<T>;
1233
- useValue: T;
1234
- }
1235
- /**
1236
- * Provider that uses a factory function with auto-injection support
1237
- *
1238
- * Note: Factory providers do not support scope/lifecycle in tsyringe.
1239
- * Factories are always called fresh on each resolution (transient-like behavior).
1240
- *
1241
- * @example Factory with dependencies
1242
- * ```typescript
1243
- * {
1244
- * provide: LOGGER_TOKENS.Transports,
1245
- * useFactory: (console) => [console],
1246
- * inject: [LOGGER_TOKENS.ConsoleTransport]
1247
- * }
1248
- * ```
1249
- */
1250
- interface FactoryProvider<T extends object = object> {
1251
- provide: InjectionToken$2<T>;
1252
- useFactory: (...deps: any[]) => T | Promise<T>;
1253
- inject?: InjectionToken$2<unknown>[];
1254
- }
1255
- /**
1256
- * Provider that creates an alias to an existing token
1257
- *
1258
- * When the `provide` token is resolved, the container resolves `useExisting` instead.
1259
- * Both tokens return the same instance (for singleton/request-scoped services).
1260
- *
1261
- * Use cases:
1262
- * - Creating interface tokens that alias concrete implementations
1263
- * - Multiple tokens resolving to the same service
1264
- *
1265
- * @example Basic alias
1266
- * ```typescript
1267
- * {
1268
- * provide: 'IUserService',
1269
- * useExisting: UserService
1270
- * }
1271
- * // Resolving 'IUserService' returns the UserService instance
1272
- * ```
1273
- *
1274
- * @example Interface abstraction
1275
- * ```typescript
1276
- * providers: [
1277
- * UserService,
1278
- * { provide: I_USER_SERVICE, useExisting: UserService }
1279
- * ]
1280
- * // Both UserService and I_USER_SERVICE resolve to the same instance
1281
- * ```
1282
- */
1283
- interface ExistingProvider<T extends object = object> {
1284
- provide: InjectionToken$2<T>;
1285
- useExisting: InjectionToken$2<T>;
1286
- }
1287
- /**
1288
- * Union type for all provider types
1289
- */
1290
- type Provider<T extends object = object> = Constructor<T> | ClassProvider<T> | ValueProvider<T> | FactoryProvider<T> | ExistingProvider<T>;
1291
- /**
1292
- * Module class type (decorated with @Module)
1293
- *
1294
- * Static methods for dynamic module configuration:
1295
- * - forRoot: Synchronous configuration (like NestJS forRoot)
1296
- * - forRootAsync: Async configuration with factory (like NestJS forRootAsync)
1297
- */
1298
- interface ModuleClass<T extends object = object> extends Constructor<T> {
1299
- /**
1300
- * Synchronous module configuration
1301
- *
1302
- * Use for global singleton modules with static configuration
1303
- *
1304
- * @example
1305
- * ```typescript
1306
- * @Module({ providers: [] })
1307
- * export class ConfigModule {
1308
- * static forRoot(options: ConfigOptions): DynamicModule {
1309
- * return {
1310
- * providers: [
1311
- * { provide: CONFIG_TOKEN, useValue: options }
1312
- * ]
1313
- * }
1314
- * }
1315
- * }
1316
- *
1317
- * // Usage in AppModule
1318
- * @Module({ imports: [ConfigModule.forRoot({ apiKey: '...' })] })
1319
- * ```
1320
- */
1321
- forRoot?: (...args: unknown[]) => DynamicModule;
1322
- /**
1323
- * Async module configuration with dependency injection
1324
- *
1325
- * Use when configuration depends on other services
1326
- *
1327
- * @example
1328
- * ```typescript
1329
- * @Module({ providers: [] })
1330
- * export class DatabaseModule {
1331
- * static forRootAsync<T>(options: AsyncModuleOptions<T>): DynamicModule {
1332
- * return {
1333
- * providers: [
1334
- * {
1335
- * provide: DB_TOKEN,
1336
- * useFactory: options.useFactory,
1337
- * inject: options.inject
1338
- * }
1339
- * ]
1340
- * }
1341
- * }
1342
- * }
1343
- *
1344
- * // Usage in AppModule
1345
- * @Module({
1346
- * imports: [
1347
- * DatabaseModule.forRootAsync({
1348
- * inject: [CONFIG_TOKEN],
1349
- * useFactory: (config) => ({ url: config.databaseUrl })
1350
- * })
1351
- * ]
1352
- * })
1353
- * ```
1354
- */
1355
- forRootAsync?: <TOptions>(options: AsyncModuleOptions<TOptions>) => DynamicModule;
1356
- }
1357
- /**
1358
- * Module options for `@Module` decorator
1359
- *
1360
- * Note: Middlewares are configured via the RouteConfigurable interface's
1361
- * configureRoutes() method, not via this options object. See router/router.ts.
1362
- */
1363
- interface ModuleOptions {
1364
- imports?: (ModuleClass | DynamicModule)[];
1365
- providers?: Provider[];
1366
- controllers?: Constructor[];
1367
- consumers?: Constructor[];
1368
- jobs?: Constructor[];
1369
- }
1370
- /**
1371
- * Dynamic module returned by forRoot/forRootAsync
1372
- *
1373
- * Contains additional providers, controllers, consumers, and jobs
1374
- * that are added to the module when configured dynamically.
1375
- */
1376
- interface DynamicModule extends Omit<ModuleOptions, 'imports'> {
1377
- /**
1378
- * Reference to the module class that created this dynamic module
1379
- *
1380
- * Required for dynamic modules to support lifecycle methods (configure, onInitialize, onShutdown).
1381
- * ModuleRegistry uses this to instantiate the actual module class instead of an anonymous wrapper.
1382
- *
1383
- * Note: This is NOT for provider scoping (tsyringe is always global).
1384
- * It's purely for preserving the class reference for lifecycle method calls.
1385
- */
1386
- module: Constructor;
1387
- }
1388
- /**
1389
- * Async configuration options for forRootAsync
1390
- */
1391
- interface AsyncModuleOptions<TOptions> {
1392
- inject?: InjectionToken$2<unknown>[];
1393
- useFactory: (...deps: any[]) => TOptions | Promise<TOptions>;
1394
- }
1395
- /**
1396
- * Context passed to lifecycle hooks
1397
- */
1398
- interface ModuleContext {
1399
- container: Container;
1400
- logger: LoggerService;
1401
- }
1402
- /**
1403
- * Lifecycle hook: called after all providers are registered
1404
- */
1405
- interface OnInitialize {
1406
- onInitialize(context: ModuleContext): void | Promise<void>;
1407
- }
1408
- /**
1409
- * Lifecycle hook: called during application shutdown
1410
- */
1411
- interface OnShutdown {
1412
- onShutdown(context: ModuleContext): void | Promise<void>;
1413
- }
1414
- /**
1415
- * Lifecycle hook: called after the {@link ExceptionHandler} is initialized.
1416
- *
1417
- * Implement this interface on a module class to contribute custom
1418
- * `reportable()`, `renderable()`, `dontReport()`, etc. registrations
1419
- * to the application's exception handler.
1420
- *
1421
- * @example
1422
- * ```typescript
1423
- * @Module({ providers: [PaymentService] })
1424
- * export class PaymentModule implements OnException {
1425
- * onException(handler: ExceptionHandler): void {
1426
- * handler.reportable(PaymentError, (e) => { ... })
1427
- * handler.renderable(PaymentDeclinedError, (e, ctx) => {
1428
- * if (ctx.type === 'http') return ctx.ctx.json({ retryable: true }, 402)
1429
- * })
1430
- * }
1431
- * }
1432
- * ```
1433
- */
1434
- interface OnException {
1435
- onException(handler: ExceptionHandler): void;
1436
- }
1437
- /**
1438
- * Tsyringe registry entry type (for internal use)
1439
- *
1440
- * Note: useFactory receives DependencyContainer from tsyringe,
1441
- * but we resolve our Container via CONTAINER_TOKEN for consistency.
1442
- */
1443
- interface RegistryEntry<T extends object = object> {
1444
- token: InjectionToken$2<T>;
1445
- useClass?: Constructor<T>;
1446
- useValue?: T;
1447
- useFactory?: (dependencyContainer: DependencyContainer) => T;
1448
- useToken?: InjectionToken$2<T>;
1449
- }
1450
- //#endregion
1451
- //#region src/quarry/types.d.ts
1452
- /**
1453
- * Flat input object for programmatic command invocation.
1454
- */
1455
- type CommandInput = Record<string, unknown>;
1456
- /**
1457
- * Result of a command execution.
1458
- */
1459
- interface CommandResult {
1460
- exitCode: number;
1461
- output: string[];
1462
- errors: string[];
1463
- }
1464
- /**
1465
- * User-facing Quarry interface. Only exposes the `call()` method.
1466
- *
1467
- * Inject via `@inject(DI_TOKENS.Quarry)` and type as `Quarry`.
1468
- */
1469
- interface Quarry {
1470
- call(name: string, input?: CommandInput): Promise<CommandResult>;
1471
- }
1472
- /**
1473
- * Internal mutable state stored on Command instances via Symbol key.
1474
- * @internal
1475
- */
1476
- interface CommandInternals {
1477
- inputs: CommandInput;
1478
- output: string[];
1479
- errors: string[];
1480
- exitCode: number;
1481
- quarry: Quarry | null;
1482
- }
1483
- /**
1484
- * A parsed argument from a Laravel-style signature string.
1485
- */
1486
- interface ParsedArgument {
1487
- name: string;
1488
- required: boolean;
1489
- default?: string;
1490
- description?: string;
1491
- isArray: boolean;
1492
- }
1493
- /**
1494
- * A parsed option from a Laravel-style signature string.
1495
- */
1496
- interface ParsedOption {
1497
- name: string;
1498
- alias?: string;
1499
- isFlag: boolean;
1500
- isArray: boolean;
1501
- default?: string;
1502
- description?: string;
1503
- }
1504
- /**
1505
- * Fully parsed command signature.
1506
- */
1507
- interface ParsedSignature {
1508
- name: string;
1509
- arguments: ParsedArgument[];
1510
- options: ParsedOption[];
1511
- }
1512
- //#endregion
1513
- //#region src/router/controller.d.ts
1514
- /**
1515
- * Controller interface for handling HTTP requests
1516
- *
1517
- * Controllers can implement RESTful methods or a custom handle() method.
1518
- * The route for the controller is set via the `@Controller` decorator.
1519
- *
1520
- * RESTful methods auto-map to HTTP verbs:
1521
- * - index() → GET /route
1522
- * - show() → GET /route/:id
1523
- * - create() → POST /route
1524
- * - update() → PUT /route/:id
1525
- * - patch() → PATCH /route/:id
1526
- * - destroy() → DELETE /route/:id
1527
- *
1528
- * For non-RESTful routes (wildcards, custom patterns), implement handle()
615
+ * For non-RESTful routes (wildcards, custom patterns), implement handle()
1529
616
  */
1530
617
  interface IController {
1531
618
  /**
@@ -1730,7 +817,7 @@ interface RouterGroupConfig {
1730
817
  middleware?: Constructor<Middleware>[];
1731
818
  version?: string | string[];
1732
819
  hideFromDocs?: boolean;
1733
- params?: index_d_exports$1.ZodObject<any>;
820
+ params?: zod_d_exports.ZodObject<any>;
1734
821
  }
1735
822
  /**
1736
823
  * Internal entry representing a sub-group or the default scope.
@@ -1743,7 +830,7 @@ interface RouterEntry {
1743
830
  middleware: Constructor<Middleware>[];
1744
831
  version?: string | string[];
1745
832
  hideFromDocs?: boolean;
1746
- params?: index_d_exports$1.ZodObject<any>;
833
+ params?: zod_d_exports.ZodObject<any>;
1747
834
  /** Controllers in this entry. undefined = all controllers not in any sub-group */
1748
835
  controllers?: Constructor[];
1749
836
  }
@@ -1786,7 +873,7 @@ declare class Router {
1786
873
  private readonly _globalMiddleware;
1787
874
  constructor(isChild?: boolean);
1788
875
  /** Dynamic path prefix. For shared segments like `/:companyId` */
1789
- prefix(path: string, params?: index_d_exports$1.ZodObject<any>): this;
876
+ prefix(path: string, params?: zod_d_exports.ZodObject<any>): this;
1790
877
  /** Domain pattern for controllers in this scope */
1791
878
  domain(pattern: string): this;
1792
879
  /** Name prefix for routes in this scope */
@@ -1828,18 +915,6 @@ declare class Router {
1828
915
  }
1829
916
  //#endregion
1830
917
  //#region src/module/module-registry.d.ts
1831
- /**
1832
- * ModuleRegistry - manages module lifecycle
1833
- *
1834
- * @example
1835
- * ```typescript
1836
- * const registry = new ModuleRegistry(container, logger)
1837
- * registry.register(AppModule) // Traverses imports recursively
1838
- * await registry.initialize()
1839
- * // ... application running ...
1840
- * await registry.shutdown()
1841
- * ```
1842
- */
1843
918
  declare class ModuleRegistry {
1844
919
  private readonly container;
1845
920
  private readonly logger;
@@ -1854,106 +929,30 @@ declare class ModuleRegistry {
1854
929
  private allSeeders;
1855
930
  private allRouterConfigs;
1856
931
  constructor(container: Container, logger: LoggerService);
1857
- /**
1858
- * Register a module (static or dynamic)
1859
- *
1860
- * @param moduleOrDynamic - Module class decorated with `@Module` or DynamicModule from configure()
1861
- */
1862
932
  register(moduleOrDynamic: ModuleClass | DynamicModule): void;
1863
- /**
1864
- * Register multiple modules in order
1865
- */
1866
933
  registerAll(modules: (ModuleClass | DynamicModule)[]): void;
1867
- /**
1868
- * Initialize all modules (call configure and onInitialize hooks)
1869
- */
1870
934
  initialize(): Promise<void>;
1871
- /**
1872
- * Get all controllers registered from all modules
1873
- */
1874
935
  getAllControllers(): Constructor[];
1875
- /**
1876
- * Get all consumers registered from all modules
1877
- */
1878
936
  getAllConsumers(): Constructor[];
1879
- /**
1880
- * Get all jobs registered from all modules
1881
- */
1882
937
  getAllJobs(): Constructor[];
1883
- /**
1884
- * Get all listeners registered from all modules
1885
- */
1886
938
  getAllListeners(): Constructor[];
1887
- /**
1888
- * Get all commands registered from all modules
1889
- */
1890
939
  getAllCommands(): Constructor[];
1891
- /**
1892
- * Get all seeders registered from all modules
1893
- */
1894
940
  getAllSeeders(): Constructor[];
1895
- /**
1896
- * Get all Router configurations from modules implementing RouteConfigurable.
1897
- * Runs configureRoutes() lazily on first call (deferred from initialize()).
1898
- */
1899
941
  getAllRouterConfigs(): {
1900
942
  router: Router;
1901
943
  controllers: Constructor[];
1902
944
  }[];
1903
- /**
1904
- * Call `onException()` on all modules that implement the OnException interface.
1905
- * Invoked by Application after the ExceptionHandler is resolved and `register()` is called.
1906
- *
1907
- * @param handler - The resolved ExceptionHandler instance
1908
- */
1909
945
  configureExceptionHandlers(handler: ExceptionHandler): void;
1910
- /**
1911
- * Shutdown all modules (call onShutdown hooks in reverse order)
1912
- */
1913
946
  shutdown(): Promise<void>;
1914
- /**
1915
- * Type guard for RouteConfigurable
1916
- */
1917
947
  private hasRouteConfigurable;
1918
- /**
1919
- * Type guard for OnInitialize
1920
- */
1921
948
  private hasOnInitialize;
1922
- /**
1923
- * Type guard for OnShutdown
1924
- */
1925
949
  private hasOnShutdown;
1926
- /**
1927
- * Type guard for OnException
1928
- */
1929
950
  private hasOnException;
1930
- /**
1931
- * Resolve module class and options from static or dynamic module
1932
- *
1933
- * For DynamicModules, merges the decorator metadata (consumers, controllers, jobs)
1934
- * with the DynamicModule options (providers, imports). This ensures modules using
1935
- * forRoot/forRootAsync patterns still have their decorator-defined consumers registered.
1936
- */
1937
951
  private resolveModule;
1938
- /**
1939
- * Type guard for DynamicModule
1940
- */
1941
952
  private isDynamicModule;
1942
- /**
1943
- * Register a single provider in the container
1944
- */
1945
953
  private registerProvider;
1946
- /**
1947
- * Check if a class is a `Command` and collect it for auto-wiring
1948
- */
1949
954
  private collectIfCommand;
1950
- /**
1951
- * Check if a class is a `Seeder` and collect it for auto-wiring
1952
- */
1953
955
  private collectIfSeeder;
1954
- /**
1955
- * Check if a class is a `@Listener()` and collect it for auto-wiring
1956
- */
1957
956
  private collectIfListener;
1958
957
  }
1959
958
  //#endregion
@@ -2044,7 +1043,7 @@ declare class RouteRegistry {
2044
1043
  * Named routes must have unique names.
2045
1044
  *
2046
1045
  * @returns Array of expanded RegisteredRoute entries (primary + locale variants)
2047
- * @throws DuplicateRouteNameError if a named route with the same name already exists
1046
+ * @throws RouterError if a named route with the same name already exists
2048
1047
  */
2049
1048
  register(input: RouteRegistrationInput): RegisteredRoute[];
2050
1049
  /** Get a named route by name */
@@ -2059,7 +1058,7 @@ declare class RouteRegistry {
2059
1058
  */
2060
1059
  findNameByRoute(method: string, path: string): string | undefined;
2061
1060
  private buildRouteToNameCache;
2062
- /** Get all routes sorted by specificity (static > param > wildcard, primary before locale) */
1061
+ /** Get all routes sorted by specificity (static > param > wildcard, locale variant before its primary) */
2063
1062
  all(): RegisteredRoute[];
2064
1063
  /** Get only named routes */
2065
1064
  named(): RegisteredRoute[];
@@ -2077,7 +1076,7 @@ interface ResolvedRouterConfig {
2077
1076
  middleware: Constructor<Middleware>[];
2078
1077
  version?: string | string[];
2079
1078
  hideFromDocs?: boolean;
2080
- params?: index_d_exports$1.ZodObject<any>;
1079
+ params?: zod_d_exports.ZodObject<any>;
2081
1080
  }
2082
1081
  /**
2083
1082
  * Internal resolver that computes the effective Router config for each controller.
@@ -2322,7 +1321,7 @@ declare const ROUTER_TOKENS: {
2322
1321
  * route('users.show', { id: '1' })
2323
1322
  * ```
2324
1323
  */
2325
- declare function route<N extends RouteName>(name: N, params?: RouteParams<N>): string;
1324
+ declare function route<N extends RouteName>(name: N, params?: RouteParams<N>, options?: UriOptions): string;
2326
1325
  //#endregion
2327
1326
  //#region src/router/utils/path.d.ts
2328
1327
  /**
@@ -2354,10 +1353,13 @@ declare function getPathSpecificityScore(path: string): number;
2354
1353
  *
2355
1354
  * 1. Static paths before parameterized before wildcards
2356
1355
  * 2. More segments = more specific (tie-breaker)
2357
- * 3. Primary paths before locale-prefixed variants
1356
+ * 3. Locale-prefixed variants before their primary (so a locale-prefixed
1357
+ * request matches the variant first; a primary catch-all would otherwise
1358
+ * swallow the locale prefix into its param)
2358
1359
  */
2359
1360
  declare function sortRoutesBySpecificity<T extends {
2360
1361
  path: string;
1362
+ isLocaleVariant?: boolean;
2361
1363
  }>(routes: T[]): T[];
2362
1364
  //#endregion
2363
1365
  //#region src/router/utils/route-name.d.ts
@@ -2627,31 +1629,21 @@ declare function getRouteDecoratedMethods(ControllerClass: new (...args: unknown
2627
1629
  /**
2628
1630
  * Generic error response schema
2629
1631
  * Used for all error responses (4xx, 5xx)
2630
- * Matches ApplicationError.toErrorResponse() structure
1632
+ * Matches the ErrorResponse shape produced by ExceptionHandler
2631
1633
  */
2632
1634
  declare const errorResponseSchema: z.ZodObject<{
2633
- code: z.ZodNumber;
2634
1635
  message: z.ZodString;
2635
1636
  timestamp: z.ZodString;
2636
- metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2637
1637
  stack: z.ZodOptional<z.ZodString>;
2638
1638
  }, z.core.$strip>;
2639
1639
  /**
2640
1640
  * Validation error response schema
2641
1641
  * Used for 400 Bad Request with validation failures
2642
- * Matches ApplicationError.toErrorResponse() structure with validation-specific metadata
1642
+ * Matches the ErrorResponse shape produced by ExceptionHandler
2643
1643
  */
2644
1644
  declare const validationErrorResponseSchema: z.ZodObject<{
2645
- code: z.ZodNumber;
2646
1645
  message: z.ZodString;
2647
1646
  timestamp: z.ZodString;
2648
- metadata: z.ZodObject<{
2649
- issues: z.ZodArray<z.ZodObject<{
2650
- path: z.ZodString;
2651
- message: z.ZodString;
2652
- code: z.ZodString;
2653
- }, z.core.$strip>>;
2654
- }, z.core.$strip>;
2655
1647
  stack: z.ZodOptional<z.ZodString>;
2656
1648
  }, z.core.$strip>;
2657
1649
  /**
@@ -2697,66 +1689,48 @@ declare const successMessageSchema: z.ZodObject<{
2697
1689
  declare const commonErrorSchemas: {
2698
1690
  readonly 400: {
2699
1691
  readonly schema: z.ZodObject<{
2700
- code: z.ZodNumber;
2701
1692
  message: z.ZodString;
2702
1693
  timestamp: z.ZodString;
2703
- metadata: z.ZodObject<{
2704
- issues: z.ZodArray<z.ZodObject<{
2705
- path: z.ZodString;
2706
- message: z.ZodString;
2707
- code: z.ZodString;
2708
- }, z.core.$strip>>;
2709
- }, z.core.$strip>;
2710
1694
  stack: z.ZodOptional<z.ZodString>;
2711
1695
  }, z.core.$strip>;
2712
1696
  readonly description: "Validation error";
2713
1697
  };
2714
1698
  readonly 401: {
2715
1699
  readonly schema: z.ZodObject<{
2716
- code: z.ZodNumber;
2717
1700
  message: z.ZodString;
2718
1701
  timestamp: z.ZodString;
2719
- metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2720
1702
  stack: z.ZodOptional<z.ZodString>;
2721
1703
  }, z.core.$strip>;
2722
1704
  readonly description: "Unauthorized";
2723
1705
  };
2724
1706
  readonly 403: {
2725
1707
  readonly schema: z.ZodObject<{
2726
- code: z.ZodNumber;
2727
1708
  message: z.ZodString;
2728
1709
  timestamp: z.ZodString;
2729
- metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2730
1710
  stack: z.ZodOptional<z.ZodString>;
2731
1711
  }, z.core.$strip>;
2732
1712
  readonly description: "Forbidden";
2733
1713
  };
2734
1714
  readonly 404: {
2735
1715
  readonly schema: z.ZodObject<{
2736
- code: z.ZodNumber;
2737
1716
  message: z.ZodString;
2738
1717
  timestamp: z.ZodString;
2739
- metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2740
1718
  stack: z.ZodOptional<z.ZodString>;
2741
1719
  }, z.core.$strip>;
2742
1720
  readonly description: "Not found";
2743
1721
  };
2744
1722
  readonly 409: {
2745
1723
  readonly schema: z.ZodObject<{
2746
- code: z.ZodNumber;
2747
1724
  message: z.ZodString;
2748
1725
  timestamp: z.ZodString;
2749
- metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2750
1726
  stack: z.ZodOptional<z.ZodString>;
2751
1727
  }, z.core.$strip>;
2752
1728
  readonly description: "Conflict";
2753
1729
  };
2754
1730
  readonly 500: {
2755
1731
  readonly schema: z.ZodObject<{
2756
- code: z.ZodNumber;
2757
1732
  message: z.ZodString;
2758
1733
  timestamp: z.ZodString;
2759
- metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2760
1734
  stack: z.ZodOptional<z.ZodString>;
2761
1735
  }, z.core.$strip>;
2762
1736
  readonly description: "Internal server error";
@@ -2784,7 +1758,7 @@ declare function parseDomainPattern(pattern: string): {
2784
1758
  * When the host matches, domain parameters are extracted and stored in context
2785
1759
  * variables accessible via `ctx.domain(key)`.
2786
1760
  *
2787
- * When the host does NOT match, throws `DomainMismatchError` (404).
1761
+ * When the host does NOT match, aborts with 404.
2788
1762
  *
2789
1763
  * @param pattern - Domain pattern with `{param}` placeholders (e.g., '{tenant}.myapp.com')
2790
1764
  *
@@ -2863,237 +1837,67 @@ declare function signUrl(url: string, secret: string, options?: SignedUrlOptions
2863
1837
  */
2864
1838
  declare function verifySignedUrl(url: string, secret: string): Promise<boolean>;
2865
1839
  //#endregion
2866
- //#region src/router/errors/controller-registration.error.d.ts
2867
- /**
2868
- * Error thrown when a controller fails to register
2869
- *
2870
- * This typically happens when:
2871
- * - Controller is missing the `@Controller` decorator
2872
- * - Controller route metadata is not set
2873
- * - Controller class name is invalid
2874
- *
2875
- * Error Code: 9005
2876
- */
2877
- declare class ControllerRegistrationError extends ApplicationError {
2878
- constructor(controllerName: string, reason?: string);
2879
- }
2880
- //#endregion
2881
- //#region src/router/errors/hono-app-already-configured.error.d.ts
2882
- /**
2883
- * Error thrown when HonoApp.configure() is called more than once.
2884
- *
2885
- * HonoApp can only be configured a single time during application bootstrap.
2886
- */
2887
- declare class HonoAppAlreadyConfiguredError extends ApplicationError {
2888
- constructor();
2889
- }
2890
- //#endregion
2891
- //#region src/router/errors/openapi-route-registration.error.d.ts
2892
- /**
2893
- * OpenAPIRouteRegistrationError
2894
- *
2895
- * Thrown when an OpenAPI route fails to register properly
2896
- * This indicates a configuration issue with route decorators or metadata
2897
- * Uses i18n key for localized error messages
2898
- *
2899
- * @example
2900
- * ```typescript
2901
- * throw new OpenAPIRouteRegistrationError('/api/v1/users', 'Missing response schema')
2902
- * ```
2903
- */
2904
- declare class OpenAPIRouteRegistrationError extends ApplicationError {
2905
- constructor(path: string, reason: string);
2906
- }
2907
- //#endregion
2908
- //#region src/router/errors/openapi-validation.error.d.ts
2909
- /**
2910
- * OpenAPIValidationError
2911
- *
2912
- * Thrown when OpenAPI request/response validation fails
2913
- * Uses i18n key for localized error messages
2914
- *
2915
- * HTTP Status: 400 Bad Request
2916
- * Error Code: 1004
2917
- *
2918
- * @example
2919
- * ```typescript
2920
- * throw new OpenAPIValidationError('Request body missing required field: email')
2921
- * ```
2922
- */
2923
- declare class OpenAPIValidationError extends ApplicationError {
2924
- constructor(details: string);
2925
- }
1840
+ //#region src/router/router.error.d.ts
1841
+ declare class RouterError extends ApplicationError {}
2926
1842
  //#endregion
2927
1843
  //#region src/router/errors/route-not-found.error.d.ts
2928
- /**
2929
- * Error thrown when a requested route is not found
2930
- *
2931
- * HTTP Status: 404 Not Found
2932
- * Error Code: 4004
2933
- */
2934
- declare class RouteNotFoundError extends ApplicationError {
1844
+ declare class RouteNotFoundError extends HttpException {
1845
+ readonly path: string;
1846
+ readonly method: string;
2935
1847
  constructor(path: string, method: string);
2936
1848
  }
2937
1849
  //#endregion
2938
1850
  //#region src/router/errors/schema-validation.error.d.ts
2939
- /**
2940
- * SchemaValidationError
2941
- *
2942
- * Thrown when Zod schema validation fails
2943
- */
2944
- declare class SchemaValidationError extends ApplicationError {
1851
+ declare class SchemaValidationError extends HttpException {
1852
+ readonly issues: {
1853
+ path: string;
1854
+ message: string;
1855
+ code: string;
1856
+ }[];
2945
1857
  constructor(zodError: ZodError);
2946
1858
  }
2947
1859
  //#endregion
2948
1860
  //#region src/router/errors/index.d.ts
2949
1861
  /**
2950
- * Error thrown when a request's host header does not match the expected domain pattern.
2951
- *
2952
- * HTTP Status: 404 Not Found
2953
- */
2954
- declare class DomainMismatchError extends HttpException {
2955
- constructor();
2956
- }
2957
- /**
2958
- * Thrown when registering a named route that conflicts with an existing route name.
2959
- *
2960
- * Error Code: 9010
2961
- */
2962
- declare class DuplicateRouteNameError extends ApplicationError {
2963
- constructor(name: string, existingHandler: string, newHandler: string);
2964
- }
2965
- /**
2966
- * Error thrown when a signed URL has an invalid or expired signature.
2967
- *
2968
- * HTTP Status: 403 Forbidden
2969
- */
2970
- declare class InvalidSignatureError extends HttpException {
2971
- constructor();
2972
- }
2973
- /**
2974
- * Thrown when a required environment variable is not set.
2975
- *
2976
- * Maps to HTTP 500 via error code range (9xxx → 500).
2977
- */
2978
- declare class MissingEnvironmentVariableError extends ApplicationError {
2979
- constructor(variable: string);
2980
- }
2981
- /**
2982
- * Thrown when a required path or domain parameter is missing during URL generation.
2983
- *
2984
- * Error Code: 9012
2985
- */
2986
- declare class MissingRouteParamError extends ApplicationError {
2987
- constructor(param: string, name: string, path: string);
2988
- }
2989
- /**
2990
- * ResponseValidationError
2991
- *
2992
- * Thrown when a controller's response body does not match the declared Zod response schema.
2993
- * Indicates a server-side schema mismatch — the controller is returning data that
2994
- * violates its own API contract.
2995
- */
2996
- declare class ResponseValidationError extends ApplicationError {
2997
- constructor(zodError: ZodError);
2998
- }
2999
- /**
3000
- * Thrown when attempting to generate a URL for a route name that doesn't exist in the registry.
3001
- *
3002
- * Error Code: 9011
3003
- */
3004
- declare class RouteNameNotFoundError extends ApplicationError {
3005
- constructor(name: string);
3006
- }
3007
- /**
3008
- * Thrown when `router.use()` is called inside a `group()` callback.
3009
- * `use()` registers global middleware and is only allowed on the root Router.
1862
+ * Error thrown when a signed URL has an invalid or expired signature.
3010
1863
  *
3011
- * Error Code: 9013
1864
+ * HTTP Status: 403 Forbidden
3012
1865
  */
3013
- declare class RouterUseScopeError extends ApplicationError {
1866
+ declare class InvalidSignatureError extends HttpException {
3014
1867
  constructor();
3015
1868
  }
3016
1869
  /**
3017
- * Thrown when a middleware calls next() more than once.
3018
- * This is a programming error — each middleware must call next() at most once.
1870
+ * ResponseValidationError
3019
1871
  *
3020
- * Error Code: 9014
1872
+ * Thrown when a controller's response body does not match the declared Zod response schema.
1873
+ * Indicates a server-side schema mismatch — the controller is returning data that
1874
+ * violates its own API contract.
3021
1875
  */
3022
- declare class MiddlewareNextCalledMultipleTimesError extends ApplicationError {
3023
- constructor(middlewareName: string);
1876
+ declare class ResponseValidationError extends HttpException {
1877
+ readonly issues: {
1878
+ path: string;
1879
+ message: string;
1880
+ code: string;
1881
+ }[];
1882
+ constructor(zodError: ZodError);
3024
1883
  }
3025
1884
  //#endregion
3026
1885
  //#region src/application.d.ts
3027
1886
  interface ApplicationConfig {
3028
- /** Root application module */
3029
1887
  module: ModuleClass | DynamicModule;
3030
- /** Logging configuration. Defaults: level=INFO, formatter='json' */
3031
1888
  logging?: {
3032
1889
  level?: LogLevel;
3033
1890
  formatter?: 'json' | 'pretty';
3034
1891
  };
3035
- /**
3036
- * API versioning configuration.
3037
- * When provided, enables URI-based versioning for controllers.
3038
- */
3039
1892
  versioning?: VersioningOptions;
3040
- /**
3041
- * Trailing-slash handling for incoming requests.
3042
- *
3043
- * Defaults to `'ignore'` — both `/foo` and `/foo/` resolve to the same route.
3044
- *
3045
- * - `'ignore'` — match both, no redirect.
3046
- * - `'always'` — non-trailing requests redirect (308) to the trailing-slash form.
3047
- * - `'never'` — trailing requests redirect (308) to the non-trailing form.
3048
- */
3049
1893
  trailingSlash?: TrailingSlashMode;
3050
- /**
3051
- * Custom exception handler class.
3052
- *
3053
- * Extend {@link ExceptionHandler} and override `register()` to configure
3054
- * custom reporting, rendering, and post-processing of exceptions.
3055
- *
3056
- * When not provided, {@link DefaultExceptionHandler} is used (standard
3057
- * severity-based logging and JSON error responses).
3058
- *
3059
- * @example
3060
- * ```typescript
3061
- * new Stratal({
3062
- * module: AppModule,
3063
- * exceptionHandler: AppExceptionHandler,
3064
- * })
3065
- * ```
3066
- */
3067
1894
  exceptionHandler?: Constructor<ExceptionHandler>;
3068
1895
  }
3069
1896
  interface ApplicationOptions extends ApplicationConfig {
3070
1897
  env: StratalEnv;
3071
1898
  ctx: StratalExecutionContext;
3072
1899
  }
3073
- /**
3074
- * Application
3075
- *
3076
- * Main application class managing the two-tier container hierarchy:
3077
- * - Global Container: All services (singletons via tsyringe native)
3078
- * - Request Container: Child of global, context-enriched instances per request
3079
- *
3080
- * @example
3081
- * ```typescript
3082
- * const app = new Application({ module: AppModule, env, ctx })
3083
- * await app.initialize()
3084
- *
3085
- * // Access container via getter
3086
- * const service = app.container.resolve(MY_TOKEN)
3087
- *
3088
- * // Handle HTTP request (via HonoApp)
3089
- * // Handle queue batch
3090
- * await app.handleQueue(batch, 'my-queue')
3091
- * ```
3092
- */
3093
1900
  declare class Application {
3094
- /**
3095
- * Unified Container - manages all DI operations
3096
- */
3097
1901
  private _container;
3098
1902
  private honoApp;
3099
1903
  private moduleRegistry;
@@ -3110,79 +1914,27 @@ declare class Application {
3110
1914
  ctx,
3111
1915
  ...config
3112
1916
  }: ApplicationOptions);
3113
- /**
3114
- * Get the Container instance
3115
- */
3116
1917
  get container(): Container;
3117
- /**
3118
- * Lazily initialize routing and return the HonoApp instance.
3119
- *
3120
- * Routing (service registration, HonoApp resolution, route configuration)
3121
- * is deferred so that `scheduled` and `queue` handlers don't pay the CPU
3122
- * cost of route setup on cold start.
3123
- */
3124
1918
  ensureHono(): Promise<HonoApp>;
3125
- /**
3126
- * Get the application configuration
3127
- */
3128
1919
  get config(): ApplicationConfig;
3129
1920
  initialize(): Promise<void>;
3130
1921
  private initializeInternal;
3131
- /**
3132
- * Register routing services as singletons in the container.
3133
- * Called after module initialization so I18N_TOKENS.Options is available.
3134
- */
3135
1922
  private registerRoutingServices;
3136
- /**
3137
- * Wire up queue consumers and event listeners.
3138
- * Called lazily on first fetch/queue — not during scheduled handling.
3139
- */
3140
- private initializeHandlers;
3141
- /**
3142
- * Register routing services, resolve HonoApp, and configure routes.
3143
- * Called lazily on first fetch — not during scheduled/queue handling.
3144
- */
1923
+ initializeHandlers(): Promise<void>;
3145
1924
  private initializeRouting;
3146
- /**
3147
- * Resolve a service from the container
3148
- */
3149
1925
  resolve<T>(token: symbol): T;
3150
- /**
3151
- * Handle queue batch processing
3152
- */
3153
1926
  handleQueue(batch: MessageBatch, queueName: string): Promise<void>;
3154
- /**
3155
- * Handle scheduled cron trigger
3156
- */
3157
1927
  handleScheduled(controller: ScheduledController): Promise<void>;
3158
- /**
3159
- * Create mock RouterContext for queue/cron/seeder processing
3160
- */
3161
1928
  createMockRouterContext(locale?: string): RouterContext;
3162
1929
  shutdown(): Promise<void>;
3163
- /**
3164
- * Execute a command by name in a request-scoped container.
3165
- */
3166
1930
  handleCommand(name: string, input?: CommandInput): Promise<CommandResult>;
3167
1931
  private registerCommands;
3168
1932
  private registerSeeders;
3169
1933
  private registerQueueConsumers;
3170
1934
  private registerCronJobs;
3171
- /**
3172
- * Auto-wire `@Listener()` classes with the EventRegistry.
3173
- */
3174
1935
  private registerEventListeners;
3175
- /**
3176
- * Register LoggerService and dependencies
3177
- */
3178
1936
  private registerLoggerService;
3179
- /**
3180
- * Register core services with explicit scope
3181
- */
3182
1937
  private registerCoreServices;
3183
- /**
3184
- * Initialize the ExceptionHandler: call register(), then module onException hooks.
3185
- */
3186
1938
  private initializeExceptionHandler;
3187
1939
  }
3188
1940
  //#endregion
@@ -3208,7 +1960,7 @@ interface SignedUriOptions extends UriOptions, SignedUrlOptions {}
3208
1960
  * @param params - Path params, domain params, and extra query params
3209
1961
  * @returns Relative URL string (or absolute with domain prefix if route has a domain pattern)
3210
1962
  *
3211
- * @throws MissingRouteParamError if a required path or domain param is missing
1963
+ * @throws RouterError if a required path or domain param is missing
3212
1964
  */
3213
1965
  declare function buildRouteUrl(route: RegisteredRoute, name: string, params?: Record<string, string>): string;
3214
1966
  /**
@@ -3264,8 +2016,7 @@ declare class Uri {
3264
2016
  * @param options - URL generation options
3265
2017
  * @returns Generated URL string
3266
2018
  *
3267
- * @throws RouteNameNotFoundError if route name not found
3268
- * @throws MissingRouteParamError if required params missing
2019
+ * @throws RouterError if route name not found or required params missing
3269
2020
  */
3270
2021
  route<N extends RouteName>(name: N, params?: RouteParams<N>, options?: UriOptions): string;
3271
2022
  /**
@@ -3434,6 +2185,55 @@ declare class RouterContext<T extends RouterEnv = RouterEnv> extends Macroable {
3434
2185
  * @param name - Header name (case-insensitive)
3435
2186
  */
3436
2187
  header(name: string): string | undefined;
2188
+ /**
2189
+ * Read a cookie value from the current request.
2190
+ *
2191
+ * @param name - Cookie name
2192
+ * @returns The cookie value, or `undefined` if the cookie is not present
2193
+ *
2194
+ * @example
2195
+ * ```typescript
2196
+ * const redirectTo = ctx.getCookie('redirectTo')
2197
+ * ```
2198
+ */
2199
+ getCookie(name: string): string | undefined;
2200
+ /**
2201
+ * Set a cookie on the response.
2202
+ *
2203
+ * Cookie operations must run while the response is mutable — call this
2204
+ * before returning the final `Response` from the handler.
2205
+ *
2206
+ * @param name - Cookie name
2207
+ * @param value - Cookie value
2208
+ * @param options - Cookie attributes (httpOnly, secure, sameSite, path, etc.)
2209
+ *
2210
+ * @example
2211
+ * ```typescript
2212
+ * ctx.setCookie('redirectTo', '/app/', {
2213
+ * httpOnly: true,
2214
+ * secure: true,
2215
+ * sameSite: 'lax',
2216
+ * path: '/',
2217
+ * })
2218
+ * ```
2219
+ */
2220
+ setCookie(name: string, value: string, options?: CookieOptions): void;
2221
+ /**
2222
+ * Delete a cookie from the response.
2223
+ *
2224
+ * Pass the same `path` and `domain` options that were used when the cookie
2225
+ * was set, otherwise the browser will not clear the matching cookie.
2226
+ *
2227
+ * @param name - Cookie name
2228
+ * @param options - Cookie attributes used at set time (path, domain, etc.)
2229
+ * @returns The deleted cookie's previous value, or `undefined`
2230
+ *
2231
+ * @example
2232
+ * ```typescript
2233
+ * ctx.deleteCookie('redirectTo', { path: '/' })
2234
+ * ```
2235
+ */
2236
+ deleteCookie(name: string, options?: CookieOptions): string | undefined;
3437
2237
  /**
3438
2238
  * Get validated request body from OpenAPI route
3439
2239
  * Returns pre-validated data that has passed schema validation
@@ -3535,6 +2335,154 @@ declare class RouterContext<T extends RouterEnv = RouterEnv> extends Macroable {
3535
2335
  private resolveUri;
3536
2336
  }
3537
2337
  //#endregion
2338
+ //#region src/di/conditional-binding-builder.d.ts
2339
+ interface PredicateContainer {
2340
+ resolve<T>(token: InjectionToken<T>): T;
2341
+ isRegistered<T>(token: InjectionToken<T>): boolean;
2342
+ }
2343
+ interface ConditionalBindingBuilder {
2344
+ use<T extends object>(token: InjectionToken<T>): ConditionalBindingUse<T>;
2345
+ }
2346
+ interface ConditionalBindingUse<T extends object> {
2347
+ give(implementation: Constructor<T>): ConditionalBindingGive<T>;
2348
+ }
2349
+ interface ConditionalBindingGive<T extends object> {
2350
+ otherwise(implementation: Constructor<T>): void;
2351
+ }
2352
+ declare class ConditionalBindingBuilderImpl implements ConditionalBindingBuilder {
2353
+ private readonly container;
2354
+ private readonly predicate;
2355
+ private readonly options;
2356
+ constructor(container: Container, predicate: (container: PredicateContainer) => boolean, options: WhenOptions);
2357
+ use<T extends object>(token: InjectionToken<T>): ConditionalBindingUse<T>;
2358
+ }
2359
+ //#endregion
2360
+ //#region src/di/container.d.ts
2361
+ interface ClassRegistration {
2362
+ kind: 'class';
2363
+ useClass: Constructor;
2364
+ scope: Scope;
2365
+ }
2366
+ interface LazyClassRegistration {
2367
+ kind: 'lazy';
2368
+ factory: () => Constructor;
2369
+ scope: Scope;
2370
+ }
2371
+ interface ValueRegistration {
2372
+ kind: 'value';
2373
+ value: unknown;
2374
+ }
2375
+ interface FactoryRegistration {
2376
+ kind: 'factory';
2377
+ factory: (container: Container) => unknown;
2378
+ }
2379
+ interface AliasRegistration {
2380
+ kind: 'alias';
2381
+ target: InjectionToken;
2382
+ }
2383
+ type Registration = ClassRegistration | LazyClassRegistration | ValueRegistration | FactoryRegistration | AliasRegistration;
2384
+ interface ContainerOptions {
2385
+ parent?: Container;
2386
+ isRequestScoped?: boolean;
2387
+ }
2388
+ declare class Container {
2389
+ private readonly registrations;
2390
+ private readonly singletons;
2391
+ private readonly requestCache;
2392
+ private readonly parent;
2393
+ private readonly isRequestScoped;
2394
+ constructor(options?: ContainerOptions);
2395
+ register<T extends object>(serviceClass: Constructor<T>): void;
2396
+ register<T extends object>(token: InjectionToken<T>, serviceClassOrLazy: Constructor<T> | LazyToken<T>): void;
2397
+ registerSingleton<T extends object>(serviceClass: Constructor<T>): void;
2398
+ registerSingleton<T extends object>(token: InjectionToken<T>, serviceClass: Constructor<T>): void;
2399
+ registerValue<T>(token: InjectionToken<T>, value: T): void;
2400
+ registerFactory<T>(token: InjectionToken<T>, factory: (container: Container) => T): void;
2401
+ registerExisting<T>(alias: InjectionToken<T>, target: InjectionToken<T>): void;
2402
+ resolve<T>(token: InjectionToken<T>): T;
2403
+ tryResolve<T>(token: InjectionToken<T>): T | undefined;
2404
+ isRegistered<T>(token: InjectionToken<T>): boolean;
2405
+ when(predicate: (container: PredicateContainer) => boolean, options?: WhenOptions): ConditionalBindingBuilder;
2406
+ extend<T>(token: InjectionToken<T>, decorator: ExtensionDecorator<T>): void;
2407
+ runInRequestScope<T>(routerContext: RouterContext, callback: (requestContainer: Container) => T | Promise<T>): Promise<T>;
2408
+ createRequestScope(routerContext: RouterContext): Container;
2409
+ dispose(): void;
2410
+ private resolveRegistration;
2411
+ private resolveClass;
2412
+ private instantiate;
2413
+ findRegistration(token: InjectionToken): Registration | undefined;
2414
+ private getRoot;
2415
+ }
2416
+ //#endregion
2417
+ //#region src/di/container.error.d.ts
2418
+ declare class ContainerError extends ApplicationError {}
2419
+ //#endregion
2420
+ //#region src/di/decorators/inject-param.decorator.d.ts
2421
+ declare const INJECT_PARAM_METADATA_KEY: unique symbol;
2422
+ interface ParamInjection {
2423
+ index: number;
2424
+ token: InjectionToken;
2425
+ }
2426
+ declare function InjectParam<T>(token: InjectionToken<T>): ParameterDecorator;
2427
+ declare function getMethodInjections(target: object, propertyKey: string | symbol): ParamInjection[];
2428
+ //#endregion
2429
+ //#region src/di/decorators/inject.decorator.d.ts
2430
+ interface InjectionEntry {
2431
+ token: InjectionToken;
2432
+ optional: boolean;
2433
+ }
2434
+ declare function inject<T>(token: InjectionToken<T>, options?: {
2435
+ isOptional?: boolean;
2436
+ }): ParameterDecorator;
2437
+ declare function getInjectionTokens(target: object): Map<number, InjectionEntry>;
2438
+ //#endregion
2439
+ //#region src/di/decorators.d.ts
2440
+ interface ClassMetadata {
2441
+ scope: Scope;
2442
+ token?: InjectionToken;
2443
+ }
2444
+ declare const Singleton: <T>(token?: InjectionToken<T>) => <TFunction extends abstract new (...args: never[]) => unknown>(target: TFunction) => TFunction;
2445
+ declare const Request: <T>(token?: InjectionToken<T>) => <TFunction extends abstract new (...args: never[]) => unknown>(target: TFunction) => TFunction;
2446
+ declare const Transient: <T>(token?: InjectionToken<T>) => <TFunction extends abstract new (...args: never[]) => unknown>(target: TFunction) => TFunction;
2447
+ declare function getClassMetadata(target: object): ClassMetadata | undefined;
2448
+ //#endregion
2449
+ //#region src/di/metadata.d.ts
2450
+ declare function defineMetadata(key: symbol, value: unknown, target: object, propertyKey?: string | symbol): void;
2451
+ declare function getMetadata<T = unknown>(key: symbol, target: object, propertyKey?: string | symbol): T | undefined;
2452
+ declare function hasMetadata(key: symbol, target: object, propertyKey?: string | symbol): boolean;
2453
+ //#endregion
2454
+ //#region src/di/container-storage.d.ts
2455
+ /**
2456
+ * AsyncLocalStorage for the application container.
2457
+ *
2458
+ * Set by `Application.initialize()` — all code from that point onward
2459
+ * (Stratal handlers, TestingModuleBuilder, standalone functions like `route()`)
2460
+ * can access the container without DI or static singletons.
2461
+ */
2462
+ declare const containerStorage: AsyncLocalStorage<Container>;
2463
+ /**
2464
+ * Get the application container from AsyncLocalStorage.
2465
+ *
2466
+ * @throws ContainerNotInitializedError if called outside `Application.initialize()` scope
2467
+ */
2468
+ declare function getContainer(): Container;
2469
+ /**
2470
+ * Run a function within a container context.
2471
+ *
2472
+ * @param container - The application container to store
2473
+ * @param fn - The function to execute with container access
2474
+ */
2475
+ declare function runWithContainer<T>(container: Container, fn: () => T): T;
2476
+ //#endregion
2477
+ //#region src/errors/error-response.d.ts
2478
+ type Environment = 'development' | 'staging' | 'production';
2479
+ interface ErrorResponse {
2480
+ message: string;
2481
+ timestamp: string;
2482
+ stack?: string;
2483
+ }
2484
+ declare function isErrorResponse(obj: unknown): obj is ErrorResponse;
2485
+ //#endregion
3538
2486
  //#region src/errors/exception-context.d.ts
3539
2487
  /**
3540
2488
  * Exception context for errors occurring during HTTP request handling.
@@ -3604,641 +2552,135 @@ declare function createQueueExceptionContext(queueName: string): QueueExceptionC
3604
2552
  *
3605
2553
  * @returns A {@link CronExceptionContext}
3606
2554
  */
3607
- declare function createCronExceptionContext(): CronExceptionContext;
3608
- /**
3609
- * Create a CLI command exception context.
3610
- *
3611
- * @param commandName - The name of the command that threw
3612
- * @returns A {@link CliExceptionContext}
3613
- */
3614
- declare function createCliExceptionContext(commandName: string): CliExceptionContext;
3615
- //#endregion
3616
- //#region src/i18n/errors/locale-not-supported.error.d.ts
3617
- declare class LocaleNotSupportedError extends ApplicationError {
3618
- constructor(locale: string, supportedLocales: string[]);
3619
- }
3620
- //#endregion
3621
- //#region src/i18n/errors/translation-missing.error.d.ts
3622
- declare class TranslationMissingError extends ApplicationError {
3623
- constructor(key: string, locale: string);
3624
- }
3625
- //#endregion
3626
- //#region src/i18n/i18n.options.d.ts
3627
- /**
3628
- * Detection strategy for locale resolution
3629
- *
3630
- * - `'cookie'` — reads from the `locale` cookie (default)
3631
- * - `'header'` — reads from the `Accept-Language` header
3632
- * - `'querystring'` — reads from the `?locale=` query parameter
3633
- * - `'path'` — reads from the first URL path segment (e.g., `/en/api/users`)
3634
- */
3635
- type DetectionStrategy = 'cookie' | 'header' | 'querystring' | 'path';
3636
- interface BaseDetection {
3637
- /** Set to false to disable language detection entirely. @default true */
3638
- enabled?: boolean;
3639
- }
3640
- /**
3641
- * Language detection options (discriminated by strategy)
3642
- *
3643
- * @example Cookie detection (default)
3644
- * ```typescript
3645
- * { strategy: 'cookie' }
3646
- * ```
3647
- *
3648
- * @example Header detection
3649
- * ```typescript
3650
- * { strategy: 'header' }
3651
- * ```
3652
- *
3653
- * @example Path detection
3654
- * ```typescript
3655
- * { strategy: 'path' }
3656
- * ```
3657
- *
3658
- * @example Disable detection
3659
- * ```typescript
3660
- * { enabled: false }
3661
- * ```
3662
- */
3663
- type LanguageDetectionOptions = (BaseDetection & {
3664
- strategy?: 'cookie';
3665
- cookieOptions?: DetectorOptions['cookieOptions'];
3666
- }) | (BaseDetection & {
3667
- strategy: 'header';
3668
- }) | (BaseDetection & {
3669
- strategy: 'querystring';
3670
- }) | (BaseDetection & {
3671
- strategy: 'path';
3672
- /**
3673
- * Controls whether the default locale gets a URL path prefix.
3674
- *
3675
- * - `false` (default) — The default locale has no prefix (`/users`), other locales
3676
- * are prefixed (`/fr/users`). Requests to the prefixed default locale (`/en/users`) return 404.
3677
- * - `'redirect'` — Same as `false`, but requests to the prefixed default locale
3678
- * (`/en/users`) are 301-redirected to the unprefixed path (`/users`).
3679
- * - `true` — All locales are prefixed (`/en/users`, `/fr/users`).
3680
- *
3681
- * @default false
3682
- */
3683
- prefixDefaultLocale?: false | true | 'redirect';
3684
- }) | {
3685
- enabled: false;
3686
- };
3687
- /**
3688
- * Options for configuring the I18n module
3689
- *
3690
- * @example
3691
- * ```typescript
3692
- * I18nModule.forRoot({
3693
- * defaultLocale: 'en',
3694
- * fallbackLocale: 'en',
3695
- * locales: ['en', 'fr'],
3696
- * detection: { strategy: 'header' },
3697
- * })
3698
- * ```
3699
- */
3700
- interface I18nModuleOptions {
3701
- /**
3702
- * Default locale for the application
3703
- * @default 'en'
3704
- */
3705
- defaultLocale?: string;
3706
- /**
3707
- * Fallback locale when translation is missing
3708
- * @default 'en'
3709
- */
3710
- fallbackLocale?: string;
3711
- /**
3712
- * List of supported locales
3713
- * Request locales not in this list will fall back to defaultLocale
3714
- */
3715
- locales?: string[];
3716
- /**
3717
- * Language detection configuration
3718
- * Controls how the locale is extracted from incoming requests
3719
- */
3720
- detection?: LanguageDetectionOptions;
3721
- }
3722
- /**
3723
- * Resolved options with all defaults applied
3724
- * Used internally by I18n services
3725
- */
3726
- interface ResolvedI18nOptions {
3727
- defaultLocale: string;
3728
- fallbackLocale: string;
3729
- locales: string[];
3730
- detection: {
3731
- enabled: boolean;
3732
- strategy: DetectionStrategy; /** Resolved value of the path detection `prefixDefaultLocale` option. Only meaningful when `strategy` is `'path'`. */
3733
- prefixDefaultLocale: false | true | 'redirect';
3734
- };
3735
- }
3736
- /**
3737
- * Resolve I18n options with defaults
3738
- */
3739
- declare function resolveI18nOptions(options?: I18nModuleOptions): ResolvedI18nOptions;
3740
- /**
3741
- * Build Hono languageDetector options from I18n module options
3742
- */
3743
- declare function buildDetectorOptions(options?: I18nModuleOptions): Partial<DetectorOptions>;
3744
- //#endregion
3745
- //#region src/i18n/i18n.module.d.ts
3746
- declare class I18nModule implements RouteConfigurable {
3747
- /**
3748
- * Configure I18n locale settings
3749
- *
3750
- * Call once in the root module. Does not accept messages —
3751
- * use `registerMessages()` to add translations.
3752
- *
3753
- * @param options - Locale configuration (defaultLocale, fallbackLocale, locales)
3754
- */
3755
- static forRoot(options?: I18nModuleOptions): DynamicModule;
3756
- /**
3757
- * Register i18n messages
3758
- *
3759
- * Can be called from any module, as many times as needed.
3760
- * Messages are deep-merged in registration order — later calls override earlier ones at leaf level.
3761
- *
3762
- * @param messages - Messages keyed by locale code
3763
- *
3764
- * @example App-level messages
3765
- * ```typescript
3766
- * I18nModule.registerMessages({
3767
- * en: { common: { hello: 'Hello' }, errors: { notFound: 'Not found' } },
3768
- * fr: { common: { hello: 'Bonjour' }, errors: { notFound: 'Introuvable' } },
3769
- * })
3770
- * ```
3771
- *
3772
- * @example Package-level messages
3773
- * ```typescript
3774
- * I18nModule.registerMessages({
3775
- * en: { tenancy: { tenantNotFound: 'Tenant not found' } },
3776
- * })
3777
- * ```
3778
- */
3779
- static registerMessages(messages: Record<string, Record<string, unknown>>): DynamicModule;
3780
- configureRoutes(router: Router): void;
3781
- }
3782
- //#endregion
3783
- //#region src/i18n/i18n.tokens.d.ts
3784
- /**
3785
- * I18n Module DI Tokens
3786
- * Symbol-based tokens to avoid string collisions
3787
- */
3788
- declare const I18N_TOKENS: {
3789
- /** MessageLoaderService - loads and caches locale messages */readonly MessageLoader: symbol; /** I18nService - request-scoped translation service */
3790
- readonly I18nService: symbol; /** I18nModuleOptions - configuration options from forRoot() */
3791
- readonly Options: symbol; /** MessageRegistry - singleton accumulator for registerMessages() contributions */
3792
- readonly MessageRegistry: symbol;
3793
- };
3794
- //#endregion
3795
- //#region src/i18n/messages/index.d.ts
3796
- /**
3797
- * All locale messages
3798
- * Explicitly import and export (no filesystem scanning - Cloudflare Workers compatible)
3799
- */
3800
- declare const messages: {
3801
- readonly en: typeof index_d_exports;
3802
- };
2555
+ declare function createCronExceptionContext(): CronExceptionContext;
3803
2556
  /**
3804
- * Type for all messages
2557
+ * Create a CLI command exception context.
2558
+ *
2559
+ * @param commandName - The name of the command that threw
2560
+ * @returns A {@link CliExceptionContext}
3805
2561
  */
3806
- type Messages = typeof messages;
2562
+ declare function createCliExceptionContext(commandName: string): CliExceptionContext;
2563
+ //#endregion
2564
+ //#region src/errors/exception-handler.types.d.ts
3807
2565
  /**
3808
- * Get messages for all locales
2566
+ * Log severity levels for exception reporting.
3809
2567
  */
3810
- declare function getMessages(): Record<string, Record<string, unknown>>;
2568
+ type LogSeverity = 'error' | 'warn' | 'info' | 'debug';
3811
2569
  /**
3812
- * Get available locales
2570
+ * Callback invoked when a specific exception type is reported.
2571
+ *
2572
+ * @typeParam T - The exception type this callback handles
2573
+ * @param error - The matched exception instance
2574
+ * @param context - The execution context where the error occurred
3813
2575
  */
3814
- declare function getLocales(): string[];
3815
- //#endregion
3816
- //#region src/i18n/services/message-registry.d.ts
2576
+ type ReportableCallback<T extends ApplicationError> = (error: T, context: ExceptionContext) => void | Promise<void>;
3817
2577
  /**
3818
- * Message Registry
2578
+ * Callback invoked to render a specific exception type into a Response.
3819
2579
  *
3820
- * Accumulates i18n messages from multiple `I18nModule.registerMessages()` calls.
3821
- * Messages are collected statically (at module import time) and deep-merged
3822
- * when `getMergedMessages()` is called by `MessageLoaderService`.
2580
+ * Return `undefined` to fall through to the default renderer.
3823
2581
  *
3824
- * Later registrations override earlier ones at leaf level.
2582
+ * @typeParam T - The exception type this callback handles
2583
+ * @param error - The matched exception instance
2584
+ * @param context - The execution context where the error occurred
2585
+ * @returns A Response, ErrorResponse, or undefined to fall through
3825
2586
  */
3826
- declare class MessageRegistry {
3827
- /**
3828
- * Add messages (called statically by I18nModule.registerMessages)
3829
- */
3830
- static addMessages(messages: Record<string, Record<string, unknown>>): void;
3831
- /**
3832
- * Get all messages deep-merged in registration order
3833
- */
3834
- getMergedMessages(): Record<string, Record<string, unknown>>;
3835
- /**
3836
- * Reset registry (for testing)
3837
- * @internal
3838
- */
3839
- static reset(): void;
3840
- }
3841
- //#endregion
3842
- //#region src/i18n/services/message-loader.service.d.ts
3843
- declare class MessageLoaderService {
3844
- private readonly registry;
3845
- private readonly options?;
3846
- private readonly cache;
3847
- private readonly contextCache;
3848
- private readonly locales;
3849
- private readonly defaultLocale;
3850
- constructor(registry: MessageRegistry, options?: I18nModuleOptions | undefined);
3851
- /**
3852
- * Get CoreContext for a locale (lazily built and cached on first access)
3853
- * Falls back to default locale if locale not found
3854
- */
3855
- getCoreContext(locale: string): CoreContext;
3856
- /**
3857
- * Get messages for a specific locale.
3858
- * Falls back to default locale if not found.
3859
- */
3860
- getMessages(locale: string): Record<string, unknown>;
3861
- /** Get list of available locale codes */
3862
- getAvailableLocales(): string[];
3863
- /** Check if a locale is supported */
3864
- isLocaleSupported(locale: string): boolean;
3865
- /** Get default locale */
3866
- getDefaultLocale(): string;
3867
- /**
3868
- * Get flattened (dot-notation) messages for a locale, optionally filtered by namespace prefixes.
3869
- *
3870
- * Returns flat key-value pairs matching the format used by `@intlify/core-base`'s
3871
- * `createCoreContext`. Requires `registerMessageCompiler(compile)` to be called
3872
- * before `translate()` can resolve these flat keys.
3873
- *
3874
- * @param locale - Locale code (falls back to default locale if not found)
3875
- * @param options - Optional filter configuration
3876
- * @param options.only - Dot-notation prefixes to include (e.g., `['common', 'nav.sidebar']`)
3877
- * @returns Flattened messages as `{ 'key.path': 'translated value' }`
3878
- *
3879
- * @example
3880
- * ```typescript
3881
- * // All messages for the locale
3882
- * loader.getFilteredMessages('en')
3883
- *
3884
- * // Only 'common' and 'nav' namespaces
3885
- * loader.getFilteredMessages('en', { only: ['common', 'nav'] })
3886
- *
3887
- * // Deeply nested prefix
3888
- * loader.getFilteredMessages('en', { only: ['common.actions'] })
3889
- * ```
3890
- */
3891
- getFilteredMessages(locale: string, options?: {
3892
- only?: MessageKeyPrefix[];
3893
- }): Record<string, string>;
3894
- /**
3895
- * Flatten nested messages to dot-notation.
3896
- * e.g. `{ a: { b: 'hello' } }` → `{ 'a.b': 'hello' }`
3897
- */
3898
- private flattenMessages;
3899
- }
3900
- //#endregion
3901
- //#region src/i18n/services/i18n.service.d.ts
2587
+ type RenderableCallback<T extends ApplicationError> = (error: T, context: ExceptionContext) => Response | ErrorResponse | Promise<Response> | undefined;
3902
2588
  /**
3903
- * I18n Service
3904
- *
3905
- * Provides internationalization (i18n) support for the application.
3906
- * Injects RouterContext to access request-specific locale.
2589
+ * Callback invoked to post-process every error Response before it is returned.
3907
2590
  *
3908
- * @example Usage in services
3909
- * ```typescript
3910
- * @Transient(MY_TOKENS.UserService)
3911
- * export class UserService {
3912
- * constructor(
3913
- * @inject(I18N_TOKENS.I18nService) private readonly i18n: II18nService
3914
- * ) {}
2591
+ * Use this to add headers, change the response body, swap content type, etc.
3915
2592
  *
3916
- * getWelcomeMessage(): string {
3917
- * return this.i18n.t('common.welcome')
3918
- * }
3919
- * }
3920
- * ```
2593
+ * @param response - The rendered Response
2594
+ * @param error - The original exception
2595
+ * @param context - The execution context where the error occurred
2596
+ * @returns The (possibly modified) Response
3921
2597
  */
3922
- declare class I18nService implements II18nService {
3923
- private readonly loader;
3924
- private readonly routerContext?;
3925
- constructor(loader: MessageLoaderService, routerContext?: RouterContext | undefined);
3926
- /**
3927
- * Translate a message key
3928
- *
3929
- * @param key - Message key (e.g., 'common.actions.save')
3930
- * @param params - Optional parameters for interpolation
3931
- * @returns Translated string
3932
- */
3933
- t(key: MessageKeys, params?: MessageParams): string;
3934
- /**
3935
- * Get current locale
3936
- *
3937
- * @returns Current locale code from RouterContext or default locale
3938
- */
3939
- getLocale(): string;
3940
- }
3941
- //#endregion
3942
- //#region src/i18n/middleware/i18n-context.middleware.d.ts
3943
- declare class I18nContextMiddleware implements Middleware {
3944
- private readonly i18n;
3945
- constructor(i18n: I18nService);
3946
- handle(ctx: RouterContext, next: Next$1): Promise<void>;
3947
- }
3948
- //#endregion
3949
- //#region src/errors/error-codes.d.ts
2598
+ type RespondCallback = (response: Response, error: ApplicationError, context: ExceptionContext) => Response;
3950
2599
  /**
3951
- * Centralized Error Code Registry
2600
+ * Callback that returns additional context data to include in all exception logs.
3952
2601
  *
3953
- * Error codes are organized by category with specific ranges:
3954
- * - 1000-1999: Validation errors
3955
- * - 2000-2999: Database errors (generic)
3956
- * - 3000-3999: Authentication & Authorization
3957
- * - 4000-4999: Resource errors
3958
- * - 5000-5999: Domain-specific business logic (per module)
3959
- * - 9000-9999: System/Internal errors
3960
- * - 9000-9099: Router errors
3961
- * - 9100-9199: Configuration errors
3962
- * - 9200-9299: Infrastructure errors
3963
- * - 9300-9399: I18n errors
2602
+ * @returns Key-value pairs merged into every log entry
3964
2603
  */
3965
- declare const ERROR_CODES: {
3966
- /**
3967
- * Database Errors (2000-2999)
3968
- * Generic database errors thrown by Prisma client extensions
3969
- */
3970
- readonly DATABASE: {
3971
- /** Generic database error */readonly GENERIC: 2000; /** Record not found in database */
3972
- readonly RECORD_NOT_FOUND: 2001; /** Unique constraint violation */
3973
- readonly UNIQUE_CONSTRAINT: 2002; /** Foreign key constraint violation */
3974
- readonly FOREIGN_KEY_CONSTRAINT: 2003; /** Database connection failed */
3975
- readonly CONNECTION_FAILED: 2004; /** Database timeout */
3976
- readonly TIMEOUT: 2005; /** Null constraint violation */
3977
- readonly NULL_CONSTRAINT: 2006; /** Too many database connections */
3978
- readonly TOO_MANY_CONNECTIONS: 2007; /** Transaction conflict or deadlock */
3979
- readonly TRANSACTION_CONFLICT: 2008;
3980
- };
3981
- /**
3982
- * Authentication Errors (3000-3099)
3983
- * Authentication-related failures
3984
- */
3985
- readonly AUTH: {
3986
- /** Invalid credentials provided */readonly INVALID_CREDENTIALS: 3000; /** Session expired or invalid */
3987
- readonly SESSION_EXPIRED: 3001; /** Account locked or disabled */
3988
- readonly ACCOUNT_LOCKED: 3002; /** Invalid or expired token */
3989
- readonly INVALID_TOKEN: 3003; /** Context not initialized */
3990
- readonly CONTEXT_NOT_INITIALIZED: 3004; /** User not authenticated */
3991
- readonly USER_NOT_AUTHENTICATED: 3005; /** Email verification required before login */
3992
- readonly EMAIL_NOT_VERIFIED: 3007; /** Password doesn't meet minimum length */
3993
- readonly PASSWORD_TOO_SHORT: 3008; /** Password exceeds maximum length */
3994
- readonly PASSWORD_TOO_LONG: 3009; /** Account with email already exists */
3995
- readonly ACCOUNT_ALREADY_EXISTS: 3010; /** User creation failed */
3996
- readonly FAILED_TO_CREATE_USER: 3011; /** Session creation failed */
3997
- readonly FAILED_TO_CREATE_SESSION: 3012; /** User update failed */
3998
- readonly FAILED_TO_UPDATE_USER: 3013; /** Social account already linked */
3999
- readonly SOCIAL_ACCOUNT_LINKED: 3014; /** Last account cannot be unlinked */
4000
- readonly CANNOT_UNLINK_LAST_ACCOUNT: 3015; /** Organization not found */
4001
- readonly ORGANIZATION_NOT_FOUND: 3020; /** Organization member not found */
4002
- readonly MEMBER_NOT_FOUND: 3021; /** Organization invitation not found */
4003
- readonly INVITATION_NOT_FOUND: 3022; /** Invitation recipient mismatch */
4004
- readonly INVITATION_RECIPIENT_MISMATCH: 3023; /** Organization limit reached */
4005
- readonly ORGANIZATION_LIMIT_REACHED: 3024; /** Organization membership constraint violation */
4006
- readonly ORGANIZATION_MEMBERSHIP_REQUIRED: 3025;
4007
- };
4008
- /**
4009
- * Authorization Errors (3100-3199)
4010
- * Permission and access control failures
4011
- */
4012
- readonly AUTHZ: {
4013
- /** Insufficient permissions */readonly FORBIDDEN: 3100; /** Resource access denied */
4014
- readonly ACCESS_DENIED: 3101; /** User lacks required role */
4015
- readonly INSUFFICIENT_PERMISSIONS: 3102;
4016
- };
4017
- /**
4018
- * Resource Errors (4000-4999)
4019
- * Generic resource-related errors
4020
- */
4021
- readonly RESOURCE: {
4022
- /** Generic resource not found */readonly NOT_FOUND: 4000; /** Route/endpoint not found */
4023
- readonly ROUTE_NOT_FOUND: 4004; /** Resource conflict or duplicate */
4024
- readonly CONFLICT: 4100; /** Resource already exists */
4025
- readonly ALREADY_EXISTS: 4101; /** Rate limit exceeded */
4026
- readonly TOO_MANY_REQUESTS: 4290;
4027
- };
4028
- /**
4029
- * Validation Errors (1000-1999)
4030
- * Input validation failures
4031
- */
4032
- readonly VALIDATION: {
4033
- /** Generic validation error */readonly GENERIC: 1000; /** Required field missing */
4034
- readonly REQUIRED_FIELD: 1001; /** Invalid format */
4035
- readonly INVALID_FORMAT: 1002; /** Schema validation failed */
4036
- readonly SCHEMA_VALIDATION: 1003; /** Request validation failed (OpenAPI, etc.) */
4037
- readonly REQUEST_VALIDATION: 1004; /** Response validation failed (response body doesn't match declared schema) */
4038
- readonly RESPONSE_VALIDATION: 1005;
4039
- };
4040
- /**
4041
- * Router Errors (9000-9099)
4042
- * Router and controller-related INTERNAL errors
4043
- */
4044
- readonly ROUTER: {
4045
- /** Controller registration error */readonly CONTROLLER_REGISTRATION_ERROR: 9005; /** Controller method not found */
4046
- readonly CONTROLLER_METHOD_NOT_FOUND: 9006; /** OpenAPI route registration failed */
4047
- readonly OPENAPI_ROUTE_REGISTRATION: 9008; /** Duplicate route name in RouteRegistry */
4048
- readonly DUPLICATE_ROUTE_NAME: 9010; /** Named route not found in RouteRegistry */
4049
- readonly ROUTE_NAME_NOT_FOUND: 9011; /** Required route parameter missing during URL generation */
4050
- readonly MISSING_ROUTE_PARAM: 9012; /** router.use() called inside group() callback */
4051
- readonly USE_SCOPE_VIOLATION: 9013; /** next() called more than once in a middleware */
4052
- readonly MIDDLEWARE_NEXT_CALLED_MULTIPLE_TIMES: 9014;
4053
- };
4054
- /**
4055
- * I18n Errors (9300-9399)
4056
- * Internationalization and localization errors
4057
- */
4058
- readonly I18N: {
4059
- /** Translation key missing from all locales */readonly TRANSLATION_MISSING: 9300; /** Requested locale not supported */
4060
- readonly LOCALE_NOT_SUPPORTED: 9301;
4061
- };
4062
- /**
4063
- * System Errors (9000-9999)
4064
- * Internal system errors and unexpected failures
4065
- */
4066
- readonly SYSTEM: {
4067
- /** Internal server error */readonly INTERNAL_ERROR: 9000; /** Generic configuration error */
4068
- readonly CONFIGURATION_ERROR: 9100; /** ConfigService not initialized */
4069
- readonly CONFIG_NOT_INITIALIZED: 9101; /** Module already registered */
4070
- readonly MODULE_ALREADY_REGISTERED: 9102; /** Circular module dependency detected */
4071
- readonly MODULE_CIRCULAR_DEPENDENCY: 9103; /** Module dependency not found */
4072
- readonly MODULE_DEPENDENCY_NOT_FOUND: 9104; /** Invalid error code range */
4073
- readonly INVALID_ERROR_CODE_RANGE: 9105; /** Invalid module provider configuration */
4074
- readonly INVALID_MODULE_PROVIDER: 9106; /** ConfigModule.forRoot() was not called */
4075
- readonly CONFIG_MODULE_NOT_INITIALIZED: 9107; /** Generic infrastructure error */
4076
- readonly INFRASTRUCTURE_ERROR: 9200; /** Execution context not initialized */
4077
- readonly EXECUTION_CONTEXT_NOT_INITIALIZED: 9201; /** Request container not initialized */
4078
- readonly REQUEST_CONTAINER_NOT_INITIALIZED: 9202; /** Queue binding not found */
4079
- readonly QUEUE_BINDING_NOT_FOUND: 9203; /** Cron job execution failed */
4080
- readonly CRON_EXECUTION_FAILED: 9204; /** Queue provider not supported */
4081
- readonly QUEUE_PROVIDER_NOT_SUPPORTED: 9205; /** body() called on WebSocket gateway context */
4082
- readonly WEBSOCKET_BODY_NOT_AVAILABLE: 9206; /** Duplicate WebSocket event decorator on a gateway */
4083
- readonly WEBSOCKET_DUPLICATE_EVENT_HANDLER: 9207; /** Seeder name collision — two seeders share the same class name */
4084
- readonly SEEDER_NAME_COLLISION: 9208; /** Seeder not registered in the SeederRegistry */
4085
- readonly SEEDER_NOT_REGISTERED: 9209; /** Application container not initialized (AsyncLocalStorage) */
4086
- readonly CONTAINER_NOT_INITIALIZED: 9210; /** Required environment variable not set */
4087
- readonly MISSING_ENVIRONMENT_VARIABLE: 9211;
4088
- };
4089
- };
2604
+ type ContextCallback = () => Record<string, unknown>;
4090
2605
  /**
4091
- * Recursively extract all leaf values from a nested object type
4092
- * Similar to DeepKeys but extracts values instead of keys
4093
- *
4094
- * Example:
4095
- * { DATABASE: { GENERIC: 2000, NOT_FOUND: 2001 }, AUTH: { INVALID: 3000 } }
4096
- * becomes
4097
- * 2000 | 2001 | 3000
2606
+ * Handle returned by `reportable()` to control whether default reporting runs.
4098
2607
  */
4099
- type DeepValues<T> = T extends object ? { [K in keyof T]: DeepValues<T[K]> }[keyof T] : T;
2608
+ interface Reportable {
2609
+ /**
2610
+ * Prevent the default logger from reporting this exception
2611
+ * after the custom reportable callback has run.
2612
+ */
2613
+ stop(): void;
2614
+ }
4100
2615
  /**
4101
- * Type helper to extract all error code values
4102
- * Union type of all numeric error codes defined in ERROR_CODES
4103
- *
4104
- * Type: 2000 | 2001 | 2002 | ... | 9203
2616
+ * Constructor type for ApplicationError subclasses.
4105
2617
  */
4106
- type ErrorCode = DeepValues<typeof ERROR_CODES>;
4107
- //#endregion
4108
- //#region src/errors/application-error.d.ts
2618
+ type ApplicationErrorConstructor<T extends ApplicationError = ApplicationError> = new (...args: any[]) => T;
4109
2619
  /**
4110
- * ApplicationError
2620
+ * Callback invoked to render the HTML error page for HTTP requests that
2621
+ * accept `text/html`. Registered via {@link ExceptionHandler.errorPage}.
4111
2622
  *
4112
- * Abstract base class for all application errors.
2623
+ * Runs after content negotiation, after translation, after status resolution —
2624
+ * everything is computed and handed to the callback. Return `undefined` to
2625
+ * defer to the next registered `errorPage` callback, or — if none match —
2626
+ * to the built-in minimal HTML page.
4113
2627
  *
4114
- * @deprecated Use {@link HttpException} for new error classes. `HttpException` provides
4115
- * a simpler constructor that takes `(httpStatus, message?)` and derives the error code
4116
- * automatically. Existing subclasses will continue to work but should be migrated over time.
2628
+ * Callbacks are walked in registration order (first non-undefined wins).
2629
+ * Since the consumer's `register()` runs before module `onException()` hooks,
2630
+ * user overrides take precedence over module-supplied defaults.
4117
2631
  *
4118
- * Features:
4119
- * - Type-safe error codes from ERROR_CODES registry
4120
- * - Type-safe message keys from i18n module
4121
- * - Localized message keys (translated by ExceptionHandler)
4122
- * - Structured metadata for logging and interpolation
4123
- * - Proper Error prototype chain
4124
- * - Automatic timestamp generation
4125
- * - Serialization for RPC transmission
4126
- * - Optional self-reporting via `report()` method
4127
- * - Optional self-rendering via `render()` method
4128
- *
4129
- * Message Localization:
4130
- * - Each error class passes an i18n key (e.g., 'errors.userNotFound') to super()
4131
- * - `Error.message` contains the i18n key for useful stack traces and fallback display
4132
- * - Metadata provides interpolation parameters (e.g., { userId: '123' })
4133
- * - ExceptionHandler translates the message key using I18nService before sending response
4134
- * - This ensures errors are localized based on the user's locale
2632
+ * @param errorResponse - The translated, env-stripped error response payload
2633
+ * @param status - The resolved HTTP status code
2634
+ * @param context - The HTTP exception context (with full RouterContext access)
2635
+ * @param error - The original ApplicationError (escape hatch for metadata, etc.)
2636
+ * @returns A Response, or undefined to defer to the next callback / default
4135
2637
  */
4136
- declare abstract class ApplicationError extends Error {
4137
- /**
4138
- * Controls whether stack traces are captured.
4139
- * Set to false in production to skip the expensive Error.captureStackTrace() call,
4140
- * since stack traces are stripped from responses in production anyway.
4141
- */
4142
- static captureStackTraces: boolean;
4143
- /**
4144
- * Type-safe error code from ERROR_CODES registry
4145
- * See error-codes.ts for the complete registry
4146
- */
4147
- readonly code: ErrorCode;
4148
- /**
4149
- * ISO timestamp when the error was created
4150
- */
4151
- readonly timestamp: string;
4152
- /**
4153
- * Additional structured data about the error
4154
- * Used for:
4155
- * 1. Logging and debugging
4156
- * 2. Message interpolation (e.g., { userId: '123', email: 'user@example.com' })
4157
- */
4158
- readonly metadata?: Record<string, unknown>;
4159
- /**
4160
- * @param i18nKey - Type-safe i18n message key (e.g., 'errors.userNotFound')
4161
- * @param code - Type-safe error code from ERROR_CODES registry
4162
- * @param metadata - Optional data for logging and interpolation
4163
- */
4164
- constructor(i18nKey: MessageKeys, code: ErrorCode, metadata?: Record<string, unknown>);
4165
- /**
4166
- * Filter metadata to include only user-facing properties
4167
- *
4168
- * User-facing properties (validation/constraint errors):
4169
- * - issues: Validation errors from SchemaValidationError
4170
- * - fields: Constraint violation fields
4171
- * - field: Single field constraint/foreign key
4172
- *
4173
- * Internal properties (excluded from response):
4174
- * - path, method: Route debugging
4175
- * - controllerName, reason: Controller errors
4176
- * - details, etc.: Internal debugging info
4177
- *
4178
- * @param metadata - Raw metadata object
4179
- * @returns Filtered metadata with only whitelisted properties
4180
- */
4181
- private static filterMetadata;
4182
- /**
4183
- * Serialize error to ErrorResponse format for RPC transmission
4184
- *
4185
- * @param env - Environment (development | production)
4186
- * @param translatedMessage - Optional translated message (from ExceptionHandler)
4187
- * @returns ErrorResponse object suitable for JSON serialization
4188
- */
4189
- toErrorResponse(env: Environment, translatedMessage?: string): ErrorResponse;
4190
- /**
4191
- * JSON serialization (used by JSON.stringify)
4192
- * Defaults to development mode for backward compatibility
4193
- * Note: This will use the untranslated message key - use ExceptionHandler for proper localization
4194
- */
4195
- toJSON(): ErrorResponse;
4196
- /**
4197
- * Self-reporting hook. Override in subclasses to define custom reporting logic
4198
- * that runs instead of the default logger.
4199
- *
4200
- * - Return `void` (or nothing) to **skip** default reporting after this runs.
4201
- * - Return `false` to **also run** default reporting after this runs.
4202
- *
4203
- * @example
4204
- * ```typescript
4205
- * class PaymentError extends HttpException {
4206
- * report(): void {
4207
- * sentry.captureException(this)
4208
- * // Default logging is skipped
4209
- * }
4210
- * }
4211
- *
4212
- * class SoftError extends HttpException {
4213
- * report(): false {
4214
- * analytics.track(this)
4215
- * return false // Default logging also runs
4216
- * }
4217
- * }
4218
- * ```
4219
- */
4220
- report?(): void | false;
4221
- /**
4222
- * Self-rendering hook. Override in subclasses to define how this error
4223
- * is rendered into a Response.
4224
- *
4225
- * Return `undefined` to fall through to the default renderer.
4226
- *
4227
- * @param ctx - The execution context (narrow via `ctx.type` for HTTP helpers)
4228
- * @returns A Response, ErrorResponse, or undefined to use default rendering
4229
- *
4230
- * @example
4231
- * ```typescript
4232
- * class MaintenanceError extends HttpException {
4233
- * render(ctx: ExceptionContext): Response | undefined {
4234
- * if (ctx.type === 'http') {
4235
- * return ctx.ctx.html('<h1>Down for maintenance</h1>', 503)
4236
- * }
4237
- * }
4238
- * }
4239
- * ```
4240
- */
4241
- render?(ctx: ExceptionContext): Response | ErrorResponse | undefined;
2638
+ type ErrorPageCallback = (errorResponse: ErrorResponse, status: ContentfulStatusCode, context: HttpExceptionContext, error: ApplicationError) => Response | Promise<Response | undefined> | undefined;
2639
+ //#endregion
2640
+ //#region src/errors/exception-handler.d.ts
2641
+ declare abstract class ExceptionHandler {
2642
+ protected readonly logger: LoggerService;
2643
+ protected readonly env: StratalEnv;
2644
+ private readonly container;
2645
+ private readonly executionContext;
2646
+ private readonly reportables;
2647
+ private readonly renderables;
2648
+ private readonly dontReportSet;
2649
+ private readonly levelOverrides;
2650
+ private readonly contextCallbacks;
2651
+ private readonly respondCallbacks;
2652
+ private readonly errorPages;
2653
+ private readonly environment;
2654
+ constructor(logger: LoggerService, env: StratalEnv, container: Container, executionContext: StratalExecutionContext);
2655
+ abstract register(): void;
2656
+ reportable<T extends ApplicationError>(errorClass: ApplicationErrorConstructor<T>, callback: ReportableCallback<T>): Reportable;
2657
+ renderable<T extends ApplicationError>(errorClass: ApplicationErrorConstructor<T>, callback: RenderableCallback<T>): void;
2658
+ dontReport(errorClasses: ApplicationErrorConstructor[]): void;
2659
+ level(errorClass: ApplicationErrorConstructor, severity: LogSeverity): void;
2660
+ context(callback: ContextCallback): void;
2661
+ respond(callback: RespondCallback): void;
2662
+ errorPage(callback: ErrorPageCallback): void;
2663
+ resolve<T>(token: symbol | (new (...args: unknown[]) => T)): T;
2664
+ handle(error: unknown, context: ExceptionContext): Promise<Response>;
2665
+ private normalizeError;
2666
+ private performReport;
2667
+ private performRender;
2668
+ private applyRespondCallbacks;
2669
+ private shouldNotReport;
2670
+ private findReportable;
2671
+ private findRenderable;
2672
+ private matchesErrorClass;
2673
+ private defaultReport;
2674
+ private defaultRender;
2675
+ protected wantsHtml(context: HttpExceptionContext): boolean;
2676
+ protected renderDefaultHtml(errorResponse: ErrorResponse, status: ContentfulStatusCode): Response;
2677
+ private resolveStatus;
2678
+ private buildErrorResponse;
2679
+ private escapeHtml;
2680
+ private toResponse;
2681
+ private resolveSeverity;
2682
+ private getDefaultSeverity;
2683
+ private gatherContext;
4242
2684
  }
4243
2685
  //#endregion
4244
2686
  //#region src/errors/default-exception-handler.d.ts
@@ -4265,163 +2707,41 @@ declare class DefaultExceptionHandler extends ExceptionHandler {
4265
2707
  register(): void;
4266
2708
  }
4267
2709
  //#endregion
4268
- //#region src/errors/get-http-status.d.ts
4269
- /**
4270
- * Maps error codes to HTTP status codes
4271
- *
4272
- * This utility is used by the frontend to set appropriate HTTP status codes
4273
- * when returning errors from API routes.
4274
- *
4275
- * @param code - Numeric error code from ERROR_CODES registry
4276
- * @returns HTTP status code (200-599)
4277
- */
4278
- declare function getHttpStatus(code: number): ContentfulStatusCode;
4279
- /**
4280
- * Resolve the HTTP status code for an ApplicationError.
4281
- *
4282
- * If the error is an {@link HttpException}, its `httpStatus` property takes precedence.
4283
- * Otherwise, falls back to the code-range-based mapping via {@link getHttpStatus}.
4284
- *
4285
- * @param error - The application error to resolve the status for
4286
- * @returns HTTP status code
4287
- */
4288
- declare function resolveHttpStatus(error: ApplicationError): ContentfulStatusCode;
4289
- //#endregion
4290
2710
  //#region src/errors/http-exception.d.ts
4291
- /**
4292
- * HTTP-centric exception base class.
4293
- *
4294
- * Unlike {@link ApplicationError} which requires `(i18nKey, code, metadata)`,
4295
- * `HttpException` takes just `(httpStatus, message?)` and derives the error code
4296
- * from the HTTP status automatically.
4297
- *
4298
- * The message can be a plain string or an i18n key — the {@link ExceptionHandler}
4299
- * tries to translate it via `i18n.t()`, falling back to the raw string if the
4300
- * key is not found.
4301
- *
4302
- * Existing {@link ApplicationError} subclasses can be migrated to this gradually.
4303
- *
4304
- * @example
4305
- * ```typescript
4306
- * // Simple usage with plain message
4307
- * throw new HttpException(404, 'User not found')
4308
- *
4309
- * // With i18n key (auto-translated if key exists)
4310
- * throw new HttpException(422, 'errors.invalidInput')
4311
- *
4312
- * // Default message for status code
4313
- * throw new HttpException(500)
4314
- *
4315
- * // Subclass for domain-specific errors
4316
- * class PaymentDeclinedError extends HttpException {
4317
- * constructor() {
4318
- * super(402, 'errors.paymentDeclined')
4319
- * }
4320
- * }
4321
- * ```
4322
- */
2711
+ declare const HTTP_STATUS_MESSAGES: Partial<Record<number, string>>;
4323
2712
  declare class HttpException extends ApplicationError {
4324
- /**
4325
- * The HTTP status code for this exception.
4326
- * Used by the {@link ExceptionHandler} to set the response status.
4327
- */
4328
2713
  readonly httpStatus: ContentfulStatusCode;
4329
- /**
4330
- * @param httpStatus - HTTP status code (e.g., 404, 422, 500)
4331
- * @param message - Optional message string or i18n key. Defaults to the
4332
- * standard HTTP status message (e.g., "Not Found" for 404).
4333
- */
4334
- constructor(httpStatus: ContentfulStatusCode, message?: string);
2714
+ constructor(httpStatus: ContentfulStatusCode, message?: string, cause?: unknown);
4335
2715
  }
4336
- /**
4337
- * Throw an HTTP exception from anywhere in the application.
4338
- *
4339
- * The message can be a plain string or an i18n key — the {@link ExceptionHandler}
4340
- * translates it automatically, falling back to the raw string if the key is not found.
4341
- *
4342
- * @param status - HTTP status code
4343
- * @param message - Optional message (plain string or i18n key)
4344
- * @throws {@link HttpException} — always throws, never returns
4345
- *
4346
- * @example
4347
- * ```typescript
4348
- * // With plain message
4349
- * abort(404, 'User not found')
4350
- *
4351
- * // Default message for status
4352
- * abort(403)
4353
- *
4354
- * // With i18n key
4355
- * abort(422, 'errors.invalidInput')
4356
- * ```
4357
- */
4358
- declare function abort(status: ContentfulStatusCode, message?: MessageKeys | string & {}): never;
2716
+ declare function abort(status: ContentfulStatusCode, message?: string): never;
4359
2717
  //#endregion
4360
2718
  //#region src/errors/internal-error.d.ts
4361
- /**
4362
- * InternalError
4363
- *
4364
- * Represents an unexpected internal server error.
4365
- * Used to wrap unknown errors that don't fit into specific error categories.
4366
- *
4367
- * This error is thrown when:
4368
- * - An unexpected exception occurs
4369
- * - An error type is not recognized
4370
- * - A system-level failure happens
4371
- */
4372
2719
  declare class InternalError extends ApplicationError {
4373
- constructor(metadata?: Record<string, unknown>);
2720
+ constructor(cause?: unknown);
4374
2721
  }
4375
2722
  //#endregion
4376
2723
  //#region src/errors/is-application-error.d.ts
4377
- /**
4378
- * Type guard to check if an error is an ApplicationError.
4379
- *
4380
- * Uses `instanceof` first, then falls back to a structural check
4381
- * for the `code` and `timestamp` properties that all ApplicationError
4382
- * instances have. This handles cross-module boundary cases where
4383
- * `instanceof` fails due to duplicate class identities (e.g., Vite's
4384
- * module graph in workerd).
4385
- *
4386
- * @param error - The error to check
4387
- * @returns True if the error is an ApplicationError instance
4388
- */
4389
2724
  declare function isApplicationError(error: unknown): error is ApplicationError;
4390
2725
  //#endregion
4391
2726
  //#region src/errors/container-not-initialized.error.d.ts
4392
- /**
4393
- * Thrown when attempting to access the application container via AsyncLocalStorage
4394
- * before `Application.initialize()` has been called.
4395
- *
4396
- * This typically means `route()` or another standalone function is being called
4397
- * outside the application lifecycle.
4398
- */
4399
2727
  declare class ContainerNotInitializedError extends ApplicationError {
4400
2728
  constructor();
4401
2729
  }
4402
2730
  //#endregion
4403
- //#region src/errors/request-container-not-initialized.error.d.ts
4404
- /**
4405
- * RequestContainerNotInitializedError
4406
- *
4407
- * Thrown when attempting to access the request-scoped container before it has been initialized.
4408
- * This typically indicates that the RouterService middleware hasn't run yet,
4409
- * or the router context is being accessed outside of a request lifecycle.
4410
- */
4411
- declare class RequestContainerNotInitializedError extends ApplicationError {
4412
- constructor();
4413
- }
4414
- //#endregion
4415
2731
  //#region src/errors/stratal-not-initialized.error.d.ts
4416
- /**
4417
- * StratalNotInitializedError
4418
- *
4419
- * Thrown when attempting to resolve the Application instance before Stratal has been instantiated.
4420
- * This typically indicates that the Stratal instance is not exported as the default export.
4421
- */
4422
2732
  declare class StratalNotInitializedError extends ApplicationError {
4423
2733
  constructor();
4424
2734
  }
4425
2735
  //#endregion
4426
- export { DuplicateRouteNameError as $, TrailingSlashMode as $n, ModuleRegistry as $t, LocaleNotSupportedError as A, ValueProvider as An, container$1 as Ar, Delete as At, ContextQueryResult as B, ControllerOptions as Bn, PredicateContainer as Br, extractDomainParamNames as Bt, DetectionStrategy as C, ModuleContext as Cn, RoutePrefixes as Cr, successMessageSchema as Ct, buildDetectorOptions as D, OnShutdown as Dn, Container as Dr, getRouteDecoratedMethods as Dt, ResolvedI18nOptions as E, OnInitialize as En, StratalRouteMap as Er, Route as Et, QueueExceptionContext as F, RenderableCallback as Fn, singleton as Fr, Controller as Ft, buildRouteUrl as G, RouteBodyObject as Gn, Environment as Gr, toOpenAPIPath as Gt, SignedUriOptions as H, ExplicitRouteMetadata as Hn, ExtensionDecorator as Hr, generateConventionRouteName as Ht, createCliExceptionContext as I, Reportable as In, ConditionalBindingBuilder as Ir, getControllerOptions as It, ApplicationOptions as J, RouteResponse as Jn, RouteRegistrationService as Jt, Application as K, RouteConfig as Kn, ErrorResponse as Kr, route as Kt, createCronExceptionContext as L, ReportableCallback as Ln, ConditionalBindingBuilderImpl as Lr, getControllerRoute as Lt, CronExceptionContext as M, ApplicationErrorConstructor as Mn, inject$1 as Mr, Patch as Mt, ExceptionContext as N, ContextCallback as Nn, injectable$1 as Nr, Post as Nt, resolveI18nOptions as O, Provider as On, ContainerOptions as Or, getRouteMetadata as Ot, HttpExceptionContext as P, LogSeverity as Pn, instancePerContainerCachingFactory$1 as Pr, Put as Pt, DomainMismatchError as Q, SecurityScheme as Qn, VersioningService as Qt, createHttpExceptionContext as R, RespondCallback as Rn, ConditionalBindingGive as Rr, getControllerVersion as Rt, I18nModule as S, ModuleClass as Sn, RouteParams as Sr, paginationQuerySchema as St, LanguageDetectionOptions as T, OnException as Tn, SerializedRoutes as Tr, validationErrorResponseSchema as Tt, Uri as U, LocalePathConfig as Un, Scope as Ur, getPathSpecificityScore as Ut, RouterContext as V, ConventionRouteMetadata as Vn, ContainerLike as Vr, extractParamNames as Vt, UriOptions as W, RouteBody as Wn, WhenOptions as Wr, sortRoutesBySpecificity as Wt, SSEStreamingApi$1 as X, RouterEnv as Xn, RouteRegistrationInput as Xt, SSEMessage as Y, RouteResponseObject as Yn, RegisteredRoute as Yt, StreamingApi$1 as Z, RouterVariables as Zn, RouteRegistry as Zt, Messages as _, ClassProvider as _n, DIToken as _r, createDomainMiddleware as _t, InternalError as a, HonoApp as an, VERSION_NEUTRAL as ar, RouteNameNotFoundError as at, messages as b, FactoryProvider as bn, RouteMatcher as br, errorResponseSchema as bt, getHttpStatus as c, IController as cn, runWithContainer as cr, RouteNotFoundError as ct, ApplicationError as d, CommandResult as dn, Transient as dr, HonoAppAlreadyConfiguredError as dt, RouteConfigurable as en, VersioningOptions as er, InvalidSignatureError as et, ERROR_CODES as f, ParsedArgument as fn, INJECT_PARAM_METADATA_KEY as fr, ControllerRegistrationError as ft, MessageRegistry as g, AsyncModuleOptions as gn, CONTAINER_TOKEN as gr, VerifySignatureMiddleware as gt, MessageLoaderService as h, Quarry as hn, getMethodInjections as hr, verifySignedUrl as ht, isApplicationError as i, ResolvedPath as in, SECURITY_SCHEMES as ir, ResponseValidationError as it, CliExceptionContext as j, ExceptionHandler as jn, delay as jr, Get as jt, TranslationMissingError as k, RegistryEntry as kn, DependencyContainer$1 as kr, All as kt, resolveHttpStatus as l, CommandInput as ln, RequestScopeOperationNotAllowedError as lr, OpenAPIValidationError as lt, I18nContextMiddleware as m, ParsedSignature as mn, ParamInjection as mr, signUrl as mt, RequestContainerNotInitializedError as n, RouterGroupConfig as nn, ROUTER_CONTEXT_KEYS as nr, MissingEnvironmentVariableError as nt, HttpException as o, Middleware as on, containerStorage as or, RouterUseScopeError as ot, ErrorCode as p, ParsedOption as pn, InjectParam as pr, SignedUrlOptions as pt, ApplicationConfig as q, RouteMetadata as qn, isErrorResponse as qr, ROUTER_TOKENS as qt, ContainerNotInitializedError as r, LocalePathService as rn, ROUTE_METADATA_KEYS as rr, MissingRouteParamError as rt, abort as s, Next$1 as sn, getContainer as sr, SchemaValidationError as st, StratalNotInitializedError as t, Router as tn, HTTP_METHODS as tr, MiddlewareNextCalledMultipleTimesError as tt, DefaultExceptionHandler as u, CommandInternals as un, ConditionalBindingFallbackError as ur, OpenAPIRouteRegistrationError as ut, getLocales as v, DynamicModule as vn, DI_TOKENS as vr, parseDomainPattern as vt, I18nModuleOptions as w, ModuleOptions as wn, SerializedRoute as wr, uuidParamSchema as wt, I18N_TOKENS as x, InjectionToken$2 as xn, RouteName as xr, paginatedResponseSchema as xt, getMessages as y, ExistingProvider as yn, CurrentRoute as yr, commonErrorSchemas as yt, createQueueExceptionContext as z, StratalExecutionContext as zn, ConditionalBindingUse as zr, createMiddlewareChain as zt };
4427
- //# sourceMappingURL=index-D0US0X14.d.mts.map
2736
+ //#region src/errors/database.error.d.ts
2737
+ declare class DatabaseError extends ApplicationError {
2738
+ constructor(message?: string, cause?: unknown);
2739
+ }
2740
+ //#endregion
2741
+ //#region src/errors/auth.error.d.ts
2742
+ declare class AuthError extends ApplicationError {
2743
+ constructor(message?: string, cause?: unknown);
2744
+ }
2745
+ //#endregion
2746
+ export { ConditionalBindingGive as $, RouteResponseObject as $n, ROUTER_TOKENS as $t, ErrorResponse as A, OnException as An, uuidParamSchema as At, Transient as B, LazyToken as Bn, Put as Bt, HttpExceptionContext as C, ClassProvider as Cn, createDomainMiddleware as Ct, createHttpExceptionContext as D, ModuleClass as Dn, paginatedResponseSchema as Dt, createCronExceptionContext as E, FactoryProvider as En, errorResponseSchema as Et, defineMetadata as F, ContainerLike as Fn, All as Ft, InjectParam as G, ConventionRouteMetadata as Gn, createMiddlewareChain as Gt, getInjectionTokens as H, lazy as Hn, getControllerOptions as Ht, getMetadata as I, ExtensionDecorator as In, Delete as It, ContainerError as J, RouteBody as Jn, generateConventionRouteName as Jt, ParamInjection as K, ExplicitRouteMetadata as Kn, extractDomainParamNames as Kt, hasMetadata as L, InjectionToken as Ln, Get as Lt, containerStorage as M, OnShutdown as Mn, Route as Mt, getContainer as N, Provider as Nn, getRouteDecoratedMethods as Nt, createQueueExceptionContext as O, ModuleContext as On, paginationQuerySchema as Ot, runWithContainer as P, ValueProvider as Pn, getRouteMetadata as Pt, ConditionalBindingBuilderImpl as Q, RouteResponse as Qn, route as Qt, Request as R, Scope as Rn, Patch as Rt, ExceptionContext as S, AsyncModuleOptions as Sn, VerifySignatureMiddleware as St, createCliExceptionContext as T, ExistingProvider as Tn, commonErrorSchemas as Tt, inject as U, StratalExecutionContext as Un, getControllerRoute as Ut, getClassMetadata as V, isLazyToken as Vn, Controller as Vt, INJECT_PARAM_METADATA_KEY as W, ControllerOptions as Wn, getControllerVersion as Wt, ContainerOptions as X, RouteConfig as Xn, sortRoutesBySpecificity as Xt, Container as Y, RouteBodyObject as Yn, getPathSpecificityScore as Yt, ConditionalBindingBuilder as Z, RouteMetadata as Zn, toOpenAPIPath as Zt, Reportable as _, CommandResult as _n, StratalRouteMap as _r, RouteNotFoundError as _t, isApplicationError as a, ModuleRegistry as an, HTTP_METHODS as ar, Uri as at, CliExceptionContext as b, ParsedSignature as bn, DI_TOKENS as br, signUrl as bt, HttpException as c, RouterGroupConfig as cn, SECURITY_SCHEMES as cr, Application as ct, ExceptionHandler as d, HonoApp as dn, RouteMatcher as dr, SSEMessage as dt, RouteRegistrationService as en, RouterEnv as er, ConditionalBindingUse as et, ApplicationErrorConstructor as f, Middleware as fn, RouteName as fr, SSEStreamingApi$1 as ft, RenderableCallback as g, CommandInternals as gn, SerializedRoutes as gr, SchemaValidationError as gt, LogSeverity as h, CommandInput as hn, SerializedRoute as hr, ResponseValidationError as ht, ContainerNotInitializedError as i, VersioningService as in, VersioningOptions as ir, SignedUriOptions as it, isErrorResponse as j, OnInitialize as jn, validationErrorResponseSchema as jt, Environment as k, ModuleOptions as kn, successMessageSchema as kt, abort as l, LocalePathService as ln, VERSION_NEUTRAL as lr, ApplicationConfig as lt, ErrorPageCallback as m, IController as mn, RoutePrefixes as mr, InvalidSignatureError as mt, DatabaseError as n, RouteRegistrationInput as nn, SecurityScheme as nr, ContextQueryResult as nt, InternalError as o, RouteConfigurable as on, ROUTER_CONTEXT_KEYS as or, UriOptions as ot, ContextCallback as p, Next$1 as pn, RouteParams as pr, StreamingApi$1 as pt, getMethodInjections as q, LocalePathConfig as qn, extractParamNames as qt, StratalNotInitializedError as r, RouteRegistry as rn, TrailingSlashMode as rr, RouterContext as rt, HTTP_STATUS_MESSAGES as s, Router as sn, ROUTE_METADATA_KEYS as sr, buildRouteUrl as st, AuthError as t, RegisteredRoute as tn, RouterVariables as tr, PredicateContainer as tt, DefaultExceptionHandler as u, ResolvedPath as un, CurrentRoute as ur, ApplicationOptions as ut, ReportableCallback as v, ParsedArgument as vn, CONTAINER_TOKEN as vr, RouterError as vt, QueueExceptionContext as w, DynamicModule as wn, parseDomainPattern as wt, CronExceptionContext as x, Quarry as xn, ApplicationError as xr, verifySignedUrl as xt, RespondCallback as y, ParsedOption as yn, DIToken as yr, SignedUrlOptions as yt, Singleton as z, WhenOptions as zn, Post as zt };
2747
+ //# sourceMappingURL=index-DEncMcC6.d.mts.map