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,599 +1,74 @@
1
- import { A as Scope, D as runWithContainer, E as getContainer, H as ApplicationError, V as ROUTER_TOKENS, a as createHttpExceptionContext, c as DEFAULT_CONTENT_TYPE, d as ROUTER_CONTEXT_KEYS, f as ROUTE_METADATA_KEYS, k as ERROR_CODES, l as HTTP_METHODS, m as VERSION_NEUTRAL, p as SECURITY_SCHEMES, s as RouterContext, u as METHOD_STATUS_CODES, w as I18N_TOKENS } from "./errors-BdyV5PnY.mjs";
2
- import { a as __decorate, d as CONTAINER_TOKEN, f as DI_TOKENS, g as getMethodInjections, o as __decorateParam, p as Transient, s as __decorateMetadata, u as LOGGER_TOKENS } from "./logger-V6Ms3QnQ.mjs";
3
- import { S as createThrottleMiddleware, b as ControllerRegistrationError, c as InvalidSignatureError, d as MissingRouteParamError, f as ResponseValidationError, g as RouteNotFoundError, h as SchemaValidationError, k as Module, l as MiddlewareNextCalledMultipleTimesError, o as DomainMismatchError, p as RouteNameNotFoundError, s as DuplicateRouteNameError, u as MissingEnvironmentVariableError, v as OpenAPIRouteRegistrationError, x as ControllerMethodNotFoundError, y as HonoAppAlreadyConfiguredError } from "./module-Dk2qTa77.mjs";
4
- import { c as backendErrorMap, i as z, l as runWithErrorMapContext, r as validation_exports, t as OpenAPIHono } from "./validation-DtJwAv7O.mjs";
5
- import { n as OPENAPI_TOKENS } from "./openapi-tools.service-Zs-Ewv7F.mjs";
6
- import { t as en_exports } from "./en-DSH_bhh6.mjs";
7
- import { i as getMethodGuards, r as getControllerGuards, t as GuardExecutionService } from "./guards-DUk_Kzst.mjs";
8
- import { n as getControllerOptions, r as getControllerRoute } from "./controller.decorator-DQzenvSN.mjs";
9
- import { c as getWsOnMessageMethod, d as isGateway, o as getWsOnCloseMethod, s as getWsOnErrorMethod, t as GatewayContext } from "./gateway-context-CdJjpUCW.mjs";
10
- import "./http-method.decorator-DXwxAfb_.mjs";
11
- import { n as getRateLimits } from "./rate-limit.decorator--o6Q6p9w.mjs";
12
- import { n as verifySignedUrl, t as signUrl } from "./signed-url-BQPbv2In.mjs";
13
- import { t as setupI18nCompiler } from "./setup-CefZKV_e.mjs";
14
- import { inject } from "tsyringe";
15
- import { createCoreContext, translate } from "@intlify/core-base";
16
- import { swaggerUI } from "@hono/swagger-ui";
1
+ import { n as getContainer, r as runWithContainer } from "./container-storage-GpNNz79X.mjs";
2
+ import { _ as getMethodInjections, c as DI_TOKENS, l as Request, m as inject, o as ROUTER_TOKENS, s as CONTAINER_TOKEN, u as Singleton } from "./di-BO1QIb5H.mjs";
3
+ import { n as getMetadata, t as defineMetadata } from "./metadata-BVkc4aUu.mjs";
4
+ import { n as __decorateParam, t as __decorate } from "./decorate-HgTKAYK8.mjs";
5
+ import { LOGGER_TOKENS } from "./logger/index.mjs";
6
+ import { d as abort, u as HttpException } from "./errors-BBZTnjdq.mjs";
7
+ import { a as RouterContext, c as METHOD_STATUS_CODES, d as SECURITY_SCHEMES, f as VERSION_NEUTRAL, l as ROUTER_CONTEXT_KEYS, o as DEFAULT_CONTENT_TYPE, r as createHttpExceptionContext, s as HTTP_METHODS, u as ROUTE_METADATA_KEYS } from "./exception-context-B4kM-M53.mjs";
8
+ import { o as RouterError, s as createThrottleMiddleware } from "./module-xYoHba6B.mjs";
9
+ import { t as I18N_TOKENS } from "./i18n.tokens-hwRpmjRq.mjs";
10
+ import { i as zod_exports, r as z, t as OpenAPIHono } from "./zod-hMa3rSHV.mjs";
11
+ import { a as OPENAPI_TOKENS } from "./openapi-C6lm0RmV.mjs";
12
+ import { i as getMethodGuards, r as getControllerGuards, t as GuardExecutionService } from "./guards-Ced-uNIF.mjs";
13
+ import { n as getRateLimits } from "./rate-limit.decorator-D69zdZbp.mjs";
14
+ import { n as getControllerOptions, r as getControllerRoute } from "./controller.decorator-DIUazNU7.mjs";
15
+ import { a as getWsOnCloseMethod, o as getWsOnErrorMethod, s as getWsOnMessageMethod, t as GatewayContext, u as isGateway } from "./gateway-context-CFe6a9gz.mjs";
16
+ import "./http-method.decorator-CdjKFJZZ.mjs";
17
+ import { n as verifySignedUrl, t as signUrl } from "./signed-url-BqUqt5dF.mjs";
17
18
  import { languageDetector } from "hono/language";
18
- //#region src/i18n/middleware/i18n-context.middleware.ts
19
- /**
20
- * I18n Context Middleware
21
- *
22
- * Sets up AsyncLocalStorage context for Zod i18n validation.
23
- * Must run after LocaleExtractionMiddleware sets the locale.
24
- */
25
- let I18nContextMiddleware = class I18nContextMiddleware {
26
- constructor(i18n) {
27
- this.i18n = i18n;
28
- }
29
- async handle(ctx, next) {
30
- await runWithErrorMapContext({
31
- t: (key, params) => this.i18n.t(key, params),
32
- locale: ctx.getLocale()
33
- }, () => next());
34
- }
35
- };
36
- I18nContextMiddleware = __decorate([
37
- Transient(),
38
- __decorateParam(0, inject(I18N_TOKENS.I18nService)),
39
- __decorateMetadata("design:paramtypes", [Object])
40
- ], I18nContextMiddleware);
41
- //#endregion
42
- //#region src/openapi/services/openapi-config.service.ts
43
- let OpenAPIConfigService = class OpenAPIConfigService {
44
- overrides = [];
45
- constructor(baseOptions) {
46
- this.baseOptions = baseOptions;
47
- }
48
- /**
49
- * Add configuration override for this request.
50
- * Overrides are merged in the order they are added.
51
- */
52
- override(config) {
53
- this.overrides.push(config);
54
- }
55
- /** Get effective configuration (base merged with all overrides) */
56
- getEffectiveConfig() {
57
- let effective = {
58
- jsonPath: this.baseOptions?.jsonPath ?? "/api/openapi.json",
59
- ui: this.baseOptions?.ui,
60
- info: {
61
- title: this.baseOptions?.info?.title ?? "API",
62
- version: this.baseOptions?.info?.version ?? "1.0.0",
63
- description: this.baseOptions?.info?.description
64
- },
65
- securitySchemes: this.baseOptions?.securitySchemes
66
- };
67
- for (const override of this.overrides) effective = this.mergeConfig(effective, override);
68
- return effective;
69
- }
70
- /**
71
- * Merge override into effective config.
72
- * Info is shallow-merged, routeFilter is replaced.
73
- */
74
- mergeConfig(base, override) {
75
- return {
76
- ...base,
77
- info: {
78
- ...base.info,
79
- ...override.info && {
80
- title: override.info.title ?? base.info.title,
81
- version: override.info.version ?? base.info.version,
82
- description: override.info.description ?? base.info.description
83
- }
84
- },
85
- routeFilter: override.routeFilter ?? base.routeFilter
86
- };
87
- }
88
- };
89
- OpenAPIConfigService = __decorate([
90
- Transient(OPENAPI_TOKENS.ConfigService),
91
- __decorateParam(0, inject(OPENAPI_TOKENS.Options, { isOptional: true })),
92
- __decorateMetadata("design:paramtypes", [Object])
93
- ], OpenAPIConfigService);
94
- //#endregion
95
- //#region src/i18n/errors/locale-not-supported.error.ts
96
- /**
97
- * Locale Not Supported Error
98
- * Thrown when an unsupported locale is requested
99
- *
100
- * HTTP Status: 500 Internal Server Error
101
- * Error Code: 9301
102
- */
103
- var LocaleNotSupportedError = class extends ApplicationError {
104
- constructor(locale, supportedLocales) {
105
- super("errors.localeNotSupported", ERROR_CODES.I18N.LOCALE_NOT_SUPPORTED, {
106
- locale,
107
- supportedLocales: supportedLocales.join(", ")
108
- });
19
+ //#region src/router/errors/route-not-found.error.ts
20
+ var RouteNotFoundError = class extends HttpException {
21
+ path;
22
+ method;
23
+ constructor(path, method) {
24
+ super(404, `Route not found: ${method} ${path}`);
25
+ this.path = path;
26
+ this.method = method;
109
27
  }
110
28
  };
111
29
  //#endregion
112
- //#region src/i18n/errors/translation-missing.error.ts
113
- /**
114
- * Translation Missing Error
115
- * Thrown when a translation key is missing from all locales
116
- *
117
- * HTTP Status: 500 Internal Server Error
118
- * Error Code: 9300
119
- */
120
- var TranslationMissingError = class extends ApplicationError {
121
- constructor(key, locale) {
122
- super("errors.translationMissing", ERROR_CODES.I18N.TRANSLATION_MISSING, {
123
- key,
124
- locale
125
- });
126
- }
127
- };
128
- //#endregion
129
- //#region src/i18n/i18n.options.ts
130
- /**
131
- * Resolve I18n options with defaults
132
- */
133
- function resolveI18nOptions(options) {
134
- const detection = options?.detection;
135
- const enabled = detection ? detection.enabled !== false : true;
136
- const strategy = detection && "strategy" in detection ? detection.strategy ?? "cookie" : "cookie";
137
- const prefixDefaultLocale = detection && "prefixDefaultLocale" in detection && detection.prefixDefaultLocale !== void 0 ? detection.prefixDefaultLocale : false;
138
- return {
139
- defaultLocale: options?.defaultLocale ?? "en",
140
- fallbackLocale: options?.fallbackLocale ?? "en",
141
- locales: options?.locales ?? ["en"],
142
- detection: {
143
- enabled,
144
- strategy,
145
- prefixDefaultLocale
146
- }
147
- };
148
- }
149
- /**
150
- * Build Hono languageDetector options from I18n module options
151
- */
152
- function buildDetectorOptions(options) {
153
- const resolved = resolveI18nOptions(options);
154
- const strategy = resolved.detection.strategy;
155
- const detectorOptions = {
156
- order: [strategy],
157
- fallbackLanguage: resolved.defaultLocale,
158
- supportedLanguages: resolved.locales,
159
- lookupCookie: "locale",
160
- lookupQueryString: "locale",
161
- lookupFromPathIndex: 0,
162
- ignoreCase: true
163
- };
164
- if (strategy === "cookie") {
165
- detectorOptions.caches = ["cookie"];
166
- if (options?.detection && "cookieOptions" in options.detection && options.detection.cookieOptions) detectorOptions.cookieOptions = options.detection.cookieOptions;
167
- } else detectorOptions.caches = false;
168
- return detectorOptions;
169
- }
170
- //#endregion
171
- //#region src/i18n/messages/index.ts
172
- /**
173
- * Core Messages
174
- *
175
- * Messages used by packages/modules infrastructure.
176
- * These are automatically merged with application-specific messages.
177
- */
178
- /**
179
- * All locale messages
180
- * Explicitly import and export (no filesystem scanning - Cloudflare Workers compatible)
181
- */
182
- const messages = { en: en_exports };
183
- /**
184
- * Get messages for all locales
185
- */
186
- function getMessages() {
187
- return messages;
188
- }
189
- /**
190
- * Get available locales
191
- */
192
- function getLocales() {
193
- return Object.keys(messages);
194
- }
195
- //#endregion
196
- //#region src/i18n/utils/deep-merge.ts
197
- /**
198
- * Deep merge two objects. Source values override target at leaf level.
199
- */
200
- function deepMerge(target, source) {
201
- const result = { ...target };
202
- for (const key of Object.keys(source)) {
203
- const targetValue = target[key];
204
- const sourceValue = source[key];
205
- if (typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue) && typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue)) result[key] = deepMerge(targetValue, sourceValue);
206
- else result[key] = sourceValue;
207
- }
208
- return result;
209
- }
210
- //#endregion
211
- //#region src/i18n/services/message-loader.service.ts
212
- let MessageLoaderService = class MessageLoaderService {
213
- cache;
214
- contextCache;
215
- locales;
216
- defaultLocale;
217
- constructor(registry, options) {
218
- this.registry = registry;
219
- this.options = options;
220
- this.defaultLocale = this.options?.defaultLocale ?? "en";
221
- this.cache = /* @__PURE__ */ new Map();
222
- this.contextCache = /* @__PURE__ */ new Map();
223
- const coreMessages = getMessages();
224
- const coreLocales = getLocales();
225
- const registryMessages = this.registry.getMergedMessages();
226
- const registryLocales = Object.keys(registryMessages);
227
- const allLocales = [...new Set([...coreLocales, ...registryLocales])];
228
- this.locales = allLocales;
229
- for (const locale of allLocales) {
230
- const merged = deepMerge(coreMessages[locale] ?? {}, registryMessages[locale] ?? {});
231
- this.cache.set(locale, merged);
232
- }
233
- }
234
- /**
235
- * Get CoreContext for a locale (lazily built and cached on first access)
236
- * Falls back to default locale if locale not found
237
- */
238
- getCoreContext(locale) {
239
- const cached = this.contextCache.get(locale);
240
- if (cached) return cached;
241
- const effectiveLocale = this.cache.has(locale) ? locale : this.defaultLocale;
242
- const cachedEffective = this.contextCache.get(effectiveLocale);
243
- if (cachedEffective) return cachedEffective;
244
- const messages = this.cache.get(effectiveLocale) ?? {};
245
- const flattened = this.flattenMessages(messages);
246
- const ctx = createCoreContext({
247
- locale: effectiveLocale,
248
- messages: { [effectiveLocale]: flattened },
249
- missingWarn: false,
250
- fallbackWarn: false
251
- });
252
- this.contextCache.set(effectiveLocale, ctx);
253
- return ctx;
254
- }
255
- /**
256
- * Get messages for a specific locale.
257
- * Falls back to default locale if not found.
258
- */
259
- getMessages(locale) {
260
- return this.cache.get(locale) ?? this.cache.get(this.defaultLocale) ?? {};
261
- }
262
- /** Get list of available locale codes */
263
- getAvailableLocales() {
264
- return this.locales;
265
- }
266
- /** Check if a locale is supported */
267
- isLocaleSupported(locale) {
268
- return this.cache.has(locale);
269
- }
270
- /** Get default locale */
271
- getDefaultLocale() {
272
- return this.defaultLocale;
273
- }
274
- /**
275
- * Get flattened (dot-notation) messages for a locale, optionally filtered by namespace prefixes.
276
- *
277
- * Returns flat key-value pairs matching the format used by `@intlify/core-base`'s
278
- * `createCoreContext`. Requires `registerMessageCompiler(compile)` to be called
279
- * before `translate()` can resolve these flat keys.
280
- *
281
- * @param locale - Locale code (falls back to default locale if not found)
282
- * @param options - Optional filter configuration
283
- * @param options.only - Dot-notation prefixes to include (e.g., `['common', 'nav.sidebar']`)
284
- * @returns Flattened messages as `{ 'key.path': 'translated value' }`
285
- *
286
- * @example
287
- * ```typescript
288
- * // All messages for the locale
289
- * loader.getFilteredMessages('en')
290
- *
291
- * // Only 'common' and 'nav' namespaces
292
- * loader.getFilteredMessages('en', { only: ['common', 'nav'] })
293
- *
294
- * // Deeply nested prefix
295
- * loader.getFilteredMessages('en', { only: ['common.actions'] })
296
- * ```
297
- */
298
- getFilteredMessages(locale, options) {
299
- const messages = this.getMessages(locale);
300
- const flattened = this.flattenMessages(messages);
301
- if (!options?.only?.length) return flattened;
302
- const result = {};
303
- for (const [key, value] of Object.entries(flattened)) if (options.only.some((prefix) => key === prefix || key.startsWith(`${prefix}.`))) result[key] = value;
304
- return result;
305
- }
306
- /**
307
- * Flatten nested messages to dot-notation.
308
- * e.g. `{ a: { b: 'hello' } }` → `{ 'a.b': 'hello' }`
309
- */
310
- flattenMessages(messages, prefix = "") {
311
- const result = {};
312
- for (const key of Object.keys(messages)) {
313
- const value = messages[key];
314
- const newKey = prefix ? `${prefix}.${key}` : key;
315
- if (typeof value === "object" && value !== null && !Array.isArray(value)) Object.assign(result, this.flattenMessages(value, newKey));
316
- else result[newKey] = String(value);
317
- }
318
- return result;
30
+ //#region src/router/errors/schema-validation.error.ts
31
+ var SchemaValidationError = class extends HttpException {
32
+ issues;
33
+ constructor(zodError) {
34
+ super(400, "Schema validation failed");
35
+ this.issues = zodError.issues.map((err) => ({
36
+ path: err.path.join("."),
37
+ message: err.message,
38
+ code: err.code
39
+ }));
319
40
  }
320
41
  };
321
- MessageLoaderService = __decorate([
322
- Transient(I18N_TOKENS.MessageLoader),
323
- __decorateParam(0, inject(I18N_TOKENS.MessageRegistry)),
324
- __decorateParam(1, inject(I18N_TOKENS.Options, { isOptional: true })),
325
- __decorateMetadata("design:paramtypes", [Object, Object])
326
- ], MessageLoaderService);
327
42
  //#endregion
328
- //#region src/i18n/services/message-registry.ts
43
+ //#region src/router/errors/index.ts
329
44
  /**
330
- * Global key for the shared contributions array.
45
+ * Error thrown when a signed URL has an invalid or expired signature.
331
46
  *
332
- * When stratal is installed via portal/symlink (e.g., in monorepos), bundlers
333
- * like esbuild may inline multiple copies of this module. Each copy gets its
334
- * own static class fields, so messages registered by one copy are invisible
335
- * to another. Using a `Symbol.for()` key on `globalThis` ensures all copies
336
- * share the same contributions array.
47
+ * HTTP Status: 403 Forbidden
337
48
  */
338
- const CONTRIBUTIONS_KEY = Symbol.for("stratal:i18n:message-registry:contributions");
339
- function getContributions() {
340
- const g = globalThis;
341
- g[CONTRIBUTIONS_KEY] ??= [];
342
- return g[CONTRIBUTIONS_KEY];
343
- }
344
- let MessageRegistry = class MessageRegistry {
345
- /**
346
- * Add messages (called statically by I18nModule.registerMessages)
347
- */
348
- static addMessages(messages) {
349
- if (Boolean(messages) && typeof messages === "object" && Object.keys(messages).length > 0) getContributions().push(messages);
350
- }
351
- /**
352
- * Get all messages deep-merged in registration order
353
- */
354
- getMergedMessages() {
355
- const merged = {};
356
- for (const contribution of getContributions()) for (const locale of Object.keys(contribution)) merged[locale] = deepMerge(merged[locale] ?? {}, contribution[locale]);
357
- return merged;
358
- }
359
- /**
360
- * Reset registry (for testing)
361
- * @internal
362
- */
363
- static reset() {
364
- globalThis[CONTRIBUTIONS_KEY] = [];
365
- }
366
- };
367
- MessageRegistry = __decorate([Transient(I18N_TOKENS.MessageRegistry)], MessageRegistry);
368
- //#endregion
369
- //#region src/openapi/services/openapi.service.ts
370
- let OpenAPIService = class OpenAPIService {
371
- /**
372
- * Generate a filtered OpenAPI spec using the user's config.
373
- * Usable from both HTTP handlers and CLI commands.
374
- */
375
- getSpec(app, container) {
376
- const configService = container.resolve(OPENAPI_TOKENS.ConfigService);
377
- const i18n = container.resolve(I18N_TOKENS.I18nService);
378
- const config = configService.getEffectiveConfig();
379
- const fullSpec = app.getOpenAPIDocument({
380
- openapi: "3.0.0",
381
- info: {
382
- version: config.info.version,
383
- title: config.info.title,
384
- description: config.info.description
385
- }
386
- });
387
- fullSpec.components ??= {};
388
- fullSpec.components.securitySchemes = this.getSecuritySchemeDefinitions(i18n);
389
- if (config.routeFilter) fullSpec.paths = this.filterRoutes(fullSpec.paths, config);
390
- if (fullSpec.components.schemas) fullSpec.components.schemas = this.filterSchemas(fullSpec);
391
- return fullSpec;
392
- }
393
- /**
394
- * Setup OpenAPI documentation endpoints
395
- */
396
- setupEndpoints(app, container) {
397
- const config = container.resolve(OPENAPI_TOKENS.ConfigService).getEffectiveConfig();
398
- app.get(config.jsonPath, (c) => {
399
- const requestContainer = c.get(ROUTER_CONTEXT_KEYS.REQUEST_CONTAINER);
400
- const fullSpec = this.getSpec(app, requestContainer);
401
- const url = new URL(c.req.raw.url);
402
- const i18n = requestContainer.resolve(I18N_TOKENS.I18nService);
403
- fullSpec.servers = [{
404
- url: `${url.protocol}//${url.host}`,
405
- description: i18n.t("common.api.serverDescription")
406
- }];
407
- return c.json(fullSpec);
408
- });
409
- this.nameLastHandler(app, "OpenAPI", "spec");
410
- if (config.ui !== false) {
411
- const uiPath = config.ui?.path ?? "/api/docs";
412
- const uiRenderer = config.ui?.renderer;
413
- app.get(uiPath, (c, next) => {
414
- const effectiveConfig = c.get(ROUTER_CONTEXT_KEYS.REQUEST_CONTAINER).resolve(OPENAPI_TOKENS.ConfigService).getEffectiveConfig();
415
- const uiContext = {
416
- specUrl: effectiveConfig.jsonPath,
417
- title: effectiveConfig.info.title
418
- };
419
- if (uiRenderer) return uiRenderer(uiContext)(c, next);
420
- return swaggerUI({ url: uiContext.specUrl })(c, next);
421
- });
422
- this.nameLastHandler(app, "OpenAPI", "docs");
423
- }
424
- }
425
- nameLastHandler(app, controller, method) {
426
- const last = app.routes[app.routes.length - 1];
427
- Object.defineProperty(last.handler, "name", { value: `http:${controller}.${method}` });
428
- }
429
- /**
430
- * Get localized security scheme definitions
431
- */
432
- getSecuritySchemeDefinitions(i18n) {
433
- return {
434
- [SECURITY_SCHEMES.BEARER_AUTH]: {
435
- type: "http",
436
- scheme: "bearer",
437
- bearerFormat: "JWT",
438
- description: i18n.t("common.api.security.bearerAuth")
439
- },
440
- [SECURITY_SCHEMES.API_KEY]: {
441
- type: "apiKey",
442
- in: "header",
443
- name: "X-API-Key",
444
- description: i18n.t("common.api.security.apiKey")
445
- },
446
- [SECURITY_SCHEMES.SESSION_COOKIE]: {
447
- type: "apiKey",
448
- in: "cookie",
449
- name: "session",
450
- description: i18n.t("common.api.security.sessionCookie")
451
- }
452
- };
453
- }
454
- /**
455
- * Filter OpenAPI paths using custom routeFilter
456
- */
457
- filterRoutes(paths, config) {
458
- const filteredPaths = {};
459
- for (const [path, pathItem] of Object.entries(paths)) {
460
- if (config.routeFilter && !config.routeFilter(path, pathItem)) continue;
461
- filteredPaths[path] = pathItem;
462
- }
463
- return filteredPaths;
464
- }
465
- /**
466
- * Filter unreferenced schemas from OpenAPI spec
467
- */
468
- filterSchemas(spec) {
469
- const referencedSchemas = /* @__PURE__ */ new Set();
470
- this.collectSchemaRefs(spec.paths, referencedSchemas);
471
- const filteredSchemas = {};
472
- const components = spec.components;
473
- if (components?.schemas) {
474
- const allSchemas = components.schemas;
475
- let prevSize = 0;
476
- while (referencedSchemas.size > prevSize) {
477
- prevSize = referencedSchemas.size;
478
- for (const [schemaName, schemaValue] of Object.entries(allSchemas)) if (referencedSchemas.has(schemaName) && !filteredSchemas[schemaName]) {
479
- filteredSchemas[schemaName] = schemaValue;
480
- this.collectSchemaRefs(schemaValue, referencedSchemas);
481
- }
482
- }
483
- }
484
- return filteredSchemas;
485
- }
486
- /**
487
- * Recursively collect all schema references from an object
488
- */
489
- collectSchemaRefs(obj, refs) {
490
- if (!obj || typeof obj !== "object") return;
491
- const record = obj;
492
- if (record.$ref && typeof record.$ref === "string") {
493
- const match = /^#\/components\/schemas\/(.+)$/.exec(record.$ref);
494
- if (match) refs.add(match[1]);
495
- }
496
- if (Array.isArray(obj)) for (const item of obj) this.collectSchemaRefs(item, refs);
497
- else for (const value of Object.values(record)) this.collectSchemaRefs(value, refs);
49
+ var InvalidSignatureError = class extends HttpException {
50
+ constructor() {
51
+ super(403, "Invalid or expired signature");
498
52
  }
499
53
  };
500
- OpenAPIService = __decorate([Transient(OPENAPI_TOKENS.OpenAPIService)], OpenAPIService);
501
- //#endregion
502
- //#region src/openapi/openapi.module.ts
503
54
  /**
504
- * OpenAPI Module
505
- *
506
- * Provides configurable OpenAPI documentation endpoints with runtime override support.
507
- *
508
- * Features:
509
- * - Configurable paths for /openapi.json and /docs
510
- * - Runtime config overrides via middleware
511
- * - i18n support for titles and descriptions
512
- * - Route filtering via hideFromDocs and custom routeFilter
513
- *
514
- * @example Basic usage
515
- * ```typescript
516
- * @Module({
517
- * imports: [
518
- * OpenAPIModule.forRoot({
519
- * info: { title: 'My API', version: '1.0.0' }
520
- * })
521
- * ]
522
- * })
523
- * export class AppModule {}
524
- * ```
525
- *
526
- * @example With runtime override in middleware
527
- * ```typescript
528
- * // In RouteAccessMiddleware
529
- * constructor(
530
- * @inject(OPENAPI_TOKENS.ConfigService) private openAPIConfig: IOpenAPIConfigService
531
- * ) {}
55
+ * ResponseValidationError
532
56
  *
533
- * async handle(ctx, next) {
534
- * this.openAPIConfig.override({
535
- * info: { title: 'Custom API' },
536
- * routeFilter: (path) => this.shouldInclude(path)
537
- * })
538
- * await next()
539
- * }
540
- * ```
57
+ * Thrown when a controller's response body does not match the declared Zod response schema.
58
+ * Indicates a server-side schema mismatch — the controller is returning data that
59
+ * violates its own API contract.
541
60
  */
542
- var _OpenAPIModule;
543
- /** Default options when none provided */
544
- const DEFAULT_OPTIONS = {
545
- jsonPath: "/api/openapi.json",
546
- info: {
547
- title: "API",
548
- version: "1.0.0"
549
- }
550
- };
551
- let OpenAPIModule = _OpenAPIModule = class OpenAPIModule {
552
- /**
553
- * Configure OpenAPI module with static options
554
- *
555
- * @param options - OpenAPI configuration (paths, info, security schemes)
556
- * @returns DynamicModule with options provider
557
- */
558
- static forRoot(options = {}) {
559
- const mergedOptions = {
560
- ...DEFAULT_OPTIONS,
561
- ...options,
562
- info: {
563
- ...DEFAULT_OPTIONS.info,
564
- ...options.info,
565
- title: options.info?.title ?? DEFAULT_OPTIONS.info?.title ?? "API",
566
- version: options.info?.version ?? DEFAULT_OPTIONS.info?.version ?? "1.0.0"
567
- }
568
- };
569
- return {
570
- module: _OpenAPIModule,
571
- providers: [{
572
- provide: OPENAPI_TOKENS.Options,
573
- useValue: mergedOptions
574
- }]
575
- };
576
- }
577
- static forRootAsync(options) {
578
- return {
579
- module: _OpenAPIModule,
580
- providers: [{
581
- provide: OPENAPI_TOKENS.Options,
582
- useFactory: options.useFactory,
583
- inject: options.inject
584
- }]
585
- };
61
+ var ResponseValidationError = class extends HttpException {
62
+ issues;
63
+ constructor(zodError) {
64
+ super(500, "Response validation failed");
65
+ this.issues = zodError.issues.map((err) => ({
66
+ path: err.path.join("."),
67
+ message: err.message,
68
+ code: err.code
69
+ }));
586
70
  }
587
71
  };
588
- OpenAPIModule = _OpenAPIModule = __decorate([Module({ providers: [{
589
- provide: OPENAPI_TOKENS.ConfigService,
590
- useClass: OpenAPIConfigService,
591
- scope: Scope.Request
592
- }, {
593
- provide: OPENAPI_TOKENS.OpenAPIService,
594
- useClass: OpenAPIService,
595
- scope: Scope.Singleton
596
- }] })], OpenAPIModule);
597
72
  //#endregion
598
73
  //#region src/router/middleware/logger.middleware.ts
599
74
  /**
@@ -666,7 +141,7 @@ function stripPort(host) {
666
141
  * When the host matches, domain parameters are extracted and stored in context
667
142
  * variables accessible via `ctx.domain(key)`.
668
143
  *
669
- * When the host does NOT match, throws `DomainMismatchError` (404).
144
+ * When the host does NOT match, aborts with 404.
670
145
  *
671
146
  * @param pattern - Domain pattern with `{param}` placeholders (e.g., '{tenant}.myapp.com')
672
147
  *
@@ -686,7 +161,7 @@ function createDomainMiddleware(pattern) {
686
161
  return async (c, next) => {
687
162
  const host = stripPort(c.req.header("host") ?? "");
688
163
  const match = regex.exec(host);
689
- if (!match) throw new DomainMismatchError();
164
+ if (!match) abort(404, "Domain mismatch");
690
165
  for (let i = 0; i < paramNames.length; i++) c.set(`domain:${paramNames[i]}`, match[i + 1]);
691
166
  await next();
692
167
  };
@@ -714,12 +189,7 @@ function createMiddlewareChain(classes) {
714
189
  const middleware = requestContainer.resolve(middlewareClass);
715
190
  let called = false;
716
191
  const guardedNext = () => {
717
- if (called) {
718
- const err = new MiddlewareNextCalledMultipleTimesError(middlewareClass.name ?? "anonymous");
719
- console.error("[STRATAL DEBUG] next() called multiple times for " + middlewareClass.name);
720
- console.error("[STRATAL DEBUG] Stack trace:", (/* @__PURE__ */ new Error()).stack);
721
- return Promise.reject(err);
722
- }
192
+ if (called) return Promise.reject(new RouterError(`Middleware "${middlewareClass.name ?? "anonymous"}" called next() multiple times`));
723
193
  called = true;
724
194
  return prevNext();
725
195
  };
@@ -871,10 +341,10 @@ function Route(config) {
871
341
  type: "convention",
872
342
  config
873
343
  };
874
- Reflect.defineMetadata(ROUTE_METADATA_KEYS.ROUTE_CONFIG, metadata, target, propertyKey);
875
- const existing = Reflect.getOwnMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, target) ?? [];
344
+ defineMetadata(ROUTE_METADATA_KEYS.ROUTE_CONFIG, metadata, target, propertyKey);
345
+ const existing = getMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, target) ?? [];
876
346
  existing.push(propertyKey);
877
- Reflect.defineMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, existing, target);
347
+ defineMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, existing, target);
878
348
  return descriptor;
879
349
  };
880
350
  }
@@ -886,7 +356,7 @@ function Route(config) {
886
356
  * @returns Route metadata or undefined if not decorated
887
357
  */
888
358
  function getRouteMetadata(target, methodName) {
889
- return Reflect.getMetadata(ROUTE_METADATA_KEYS.ROUTE_CONFIG, target, methodName);
359
+ return getMetadata(ROUTE_METADATA_KEYS.ROUTE_CONFIG, target, methodName);
890
360
  }
891
361
  /**
892
362
  * Get all methods with route decorators (@Route, @Get, @Post, etc.) from a controller
@@ -898,7 +368,7 @@ function getRouteDecoratedMethods(ControllerClass) {
898
368
  const methods = /* @__PURE__ */ new Set();
899
369
  let proto = ControllerClass.prototype;
900
370
  while (proto && proto !== Object.prototype) {
901
- const own = Reflect.getOwnMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, proto);
371
+ const own = getMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, proto);
902
372
  if (own) for (const m of own) methods.add(m);
903
373
  proto = Object.getPrototypeOf(proto);
904
374
  }
@@ -917,31 +387,19 @@ function getRouteDecoratedMethods(ControllerClass) {
917
387
  /**
918
388
  * Generic error response schema
919
389
  * Used for all error responses (4xx, 5xx)
920
- * Matches ApplicationError.toErrorResponse() structure
390
+ * Matches the ErrorResponse shape produced by ExceptionHandler
921
391
  */
922
392
  const errorResponseSchema = z.object({
923
- code: z.number().int().describe("Application error code"),
924
393
  message: z.string().describe("Human-readable error message"),
925
394
  timestamp: z.string().datetime().describe("ISO timestamp when error occurred"),
926
- metadata: z.record(z.string(), z.unknown()).optional().describe("Additional error context"),
927
395
  stack: z.string().optional().describe("Stack trace (development only)")
928
396
  }).openapi("ErrorResponse");
929
397
  /**
930
398
  * Validation error response schema
931
399
  * Used for 400 Bad Request with validation failures
932
- * Matches ApplicationError.toErrorResponse() structure with validation-specific metadata
400
+ * Matches the ErrorResponse shape produced by ExceptionHandler
933
401
  */
934
- const validationErrorResponseSchema = z.object({
935
- code: z.number().int().describe("Application error code"),
936
- message: z.string().describe("Human-readable error message"),
937
- timestamp: z.string().datetime().describe("ISO timestamp when error occurred"),
938
- metadata: z.object({ issues: z.array(z.object({
939
- path: z.string().describe("Field path that failed validation"),
940
- message: z.string().describe("Validation failure message"),
941
- code: z.string().describe("Zod validation error code")
942
- })) }).describe("Validation error details"),
943
- stack: z.string().optional().describe("Stack trace (development only)")
944
- }).openapi("ValidationErrorResponse");
402
+ const validationErrorResponseSchema = errorResponseSchema.openapi("ValidationErrorResponse");
945
403
  /**
946
404
  * Pagination query parameters schema
947
405
  * Used for list endpoints
@@ -1050,10 +508,34 @@ function toRoutingOpenAPIPath(path) {
1050
508
  * Scoring: static = 0, `:param{constraint}` = 5, `:param` = 10, wildcard `{.+}` / `{.*}` = 100.
1051
509
  *
1052
510
  * Packed as: score * 10000 - segmentCount (negative segment count so more segments = lower key = higher priority)
511
+ *
512
+ * Locale variants score against the path with the leading `/:locale{…}` segment
513
+ * stripped — the variant's score therefore matches its primary, but its larger
514
+ * segment count makes it sort just before the primary. Without this, a primary
515
+ * catch-all (e.g. `/:slug{.+}`) gobbles locale-prefixed URLs because Hono picks
516
+ * whichever matching route was registered first.
1053
517
  */
1054
- function getPathSpecificityKey(path) {
518
+ function getPathSpecificityKey(route) {
519
+ const segmentCount = countSegments(route.path);
520
+ const scoringPath = route.isLocaleVariant ? route.path.replace(/^\/:locale\{[^}]*\}/, "") || "/" : route.path;
1055
521
  let score = 0;
1056
- let segmentCount = 0;
522
+ let i = 0;
523
+ while (i < scoringPath.length) {
524
+ if (scoringPath.charCodeAt(i) === 47) {
525
+ i++;
526
+ continue;
527
+ }
528
+ let end = scoringPath.indexOf("/", i);
529
+ if (end === -1) end = scoringPath.length;
530
+ const segment = scoringPath.substring(i, end);
531
+ if (segment.includes("{.+}") || segment.includes("{.*}")) score += 100;
532
+ else if (segment.charCodeAt(0) === 58) score += segment.includes("{") ? 5 : 10;
533
+ i = end;
534
+ }
535
+ return score * 1e4 - segmentCount;
536
+ }
537
+ function countSegments(path) {
538
+ let count = 0;
1057
539
  let i = 0;
1058
540
  while (i < path.length) {
1059
541
  if (path.charCodeAt(i) === 47) {
@@ -1062,13 +544,10 @@ function getPathSpecificityKey(path) {
1062
544
  }
1063
545
  let end = path.indexOf("/", i);
1064
546
  if (end === -1) end = path.length;
1065
- segmentCount++;
1066
- const segment = path.substring(i, end);
1067
- if (segment.includes("{.+}") || segment.includes("{.*}")) score += 100;
1068
- else if (segment.charCodeAt(0) === 58) score += segment.includes("{") ? 5 : 10;
547
+ count++;
1069
548
  i = end;
1070
549
  }
1071
- return score * 1e4 - segmentCount;
550
+ return count;
1072
551
  }
1073
552
  /**
1074
553
  * Compute a specificity score for route ordering.
@@ -1089,11 +568,13 @@ function getPathSpecificityScore(path) {
1089
568
  *
1090
569
  * 1. Static paths before parameterized before wildcards
1091
570
  * 2. More segments = more specific (tie-breaker)
1092
- * 3. Primary paths before locale-prefixed variants
571
+ * 3. Locale-prefixed variants before their primary (so a locale-prefixed
572
+ * request matches the variant first; a primary catch-all would otherwise
573
+ * swallow the locale prefix into its param)
1093
574
  */
1094
575
  function sortRoutesBySpecificity(routes) {
1095
576
  const keys = /* @__PURE__ */ new Map();
1096
- for (const route of routes) keys.set(route, getPathSpecificityKey(route.path));
577
+ for (const route of routes) keys.set(route, getPathSpecificityKey(route));
1097
578
  const copy = routes.slice();
1098
579
  copy.sort((a, b) => keys.get(a) - keys.get(b));
1099
580
  return copy;
@@ -1161,6 +642,12 @@ const invokeHandler = (instance, method, ...args) => {
1161
642
  }
1162
643
  };
1163
644
  let RouteRegistrationService = class RouteRegistrationService {
645
+ logger;
646
+ registry;
647
+ routerResolver;
648
+ localePathService;
649
+ app;
650
+ moduleRegistry;
1164
651
  controllerClasses = /* @__PURE__ */ new Map();
1165
652
  upgradeWebSocketFn = null;
1166
653
  constructor(logger, registry, routerResolver, localePathService, app, moduleRegistry) {
@@ -1196,7 +683,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1196
683
  collectRoutes(ControllerClass, actions) {
1197
684
  const isWsGateway = isGateway(ControllerClass);
1198
685
  const controllerRoute = getControllerRoute(ControllerClass);
1199
- if (!controllerRoute) throw new ControllerRegistrationError(ControllerClass.name, isWsGateway ? "Missing @Gateway decorator or route metadata" : "Missing @Controller decorator or route metadata");
686
+ if (!controllerRoute) throw new RouterError(`Controller "${ControllerClass.name}" registration failed: ${isWsGateway ? "Missing @Gateway decorator or route metadata" : "Missing @Controller decorator or route metadata"}`);
1200
687
  const controllerOpts = getControllerOptions(ControllerClass);
1201
688
  const controllerGuards = getControllerGuards(ControllerClass)?.guards ?? [];
1202
689
  const routerConfig = this.routerResolver?.resolveForController(ControllerClass) ?? { middleware: [] };
@@ -1249,7 +736,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1249
736
  return;
1250
737
  }
1251
738
  const decoratedMethods = getRouteDecoratedMethods(ControllerClass);
1252
- if (decoratedMethods.length === 0) throw new ControllerRegistrationError(ControllerClass.name, "No route decorators found. Use @Route() or HTTP method decorators (@Get, @Post, etc.) on controller methods.");
739
+ if (decoratedMethods.length === 0) throw new RouterError(`Controller "${ControllerClass.name}" registration failed: No route decorators found. Use @Route() or HTTP method decorators (@Get, @Post, etc.) on controller methods.`);
1253
740
  const methodMetadata = [];
1254
741
  let hasConvention = false;
1255
742
  let hasExplicit = false;
@@ -1263,7 +750,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1263
750
  if (meta.type === "convention") hasConvention = true;
1264
751
  else if (meta.type === "explicit") hasExplicit = true;
1265
752
  }
1266
- if (hasConvention && hasExplicit) throw new ControllerRegistrationError(ControllerClass.name, "Cannot mix @Route() with HTTP method decorators (@Get, @Post, etc.) in the same controller. Use one pattern or the other.");
753
+ if (hasConvention && hasExplicit) throw new RouterError(`Controller "${ControllerClass.name}" registration failed: Cannot mix @Route() with HTTP method decorators (@Get, @Post, etc.) in the same controller. Use one pattern or the other.`);
1267
754
  const routerHidden = routerConfig.hideFromDocs;
1268
755
  const controllerHidden = controllerOpts?.hideFromDocs ?? false;
1269
756
  const routerName = routerConfig.name;
@@ -1370,16 +857,16 @@ let RouteRegistrationService = class RouteRegistrationService {
1370
857
  const bindWsHandler = (method, onCatch) => {
1371
858
  return (evt, ws) => {
1372
859
  invokeHandler(gateway, method, evt, new GatewayContext(c, ws)).catch((err) => {
1373
- this.logger.error(`WebSocket ${method} handler error`, {
1374
- gateway: GatewayClass.name,
1375
- error: err instanceof Error ? err.message : String(err)
1376
- });
860
+ this.logger.error(`WebSocket ${method} handler error`, err, { gateway: GatewayClass.name });
1377
861
  onCatch?.(err, ws);
1378
862
  });
1379
863
  };
1380
864
  };
1381
865
  if (onMsgMethod) events.onMessage = bindWsHandler(onMsgMethod, (_err, ws) => ws.close(1011, "Internal Error"));
1382
866
  if (onCloseMethod) events.onClose = bindWsHandler(onCloseMethod);
867
+ else events.onClose = (_evt, ws) => {
868
+ ws.close();
869
+ };
1383
870
  if (onErrMethod) events.onError = bindWsHandler(onErrMethod);
1384
871
  return events;
1385
872
  });
@@ -1462,7 +949,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1462
949
  resolveMethodAndPath(meta, methodName, basePath, className) {
1463
950
  if (meta.type === "convention") {
1464
951
  const derived = this.deriveHttpMethodAndPath(methodName, basePath);
1465
- if (!derived) throw new ControllerRegistrationError(`Cannot derive HTTP method/path for convention-based route "${className}.${methodName}". Ensure the method name follows the naming convention (e.g., index, create, show).`);
952
+ if (!derived) throw new RouterError(`Cannot derive HTTP method/path for convention-based route "${className}.${methodName}". Ensure the method name follows the naming convention (e.g., index, create, show).`);
1466
953
  return {
1467
954
  httpMethod: derived.method,
1468
955
  fullPath: derived.path,
@@ -1582,9 +1069,9 @@ let RouteRegistrationService = class RouteRegistrationService {
1582
1069
  if (metadata.security.length > 0) route.security = metadata.security;
1583
1070
  if (routeConfig.description) route.description = routeConfig.description;
1584
1071
  if (routeConfig.summary) route.summary = routeConfig.summary;
1585
- return (0, validation_exports.createRoute)(route);
1072
+ return (0, zod_exports.createRoute)(route);
1586
1073
  } catch (error) {
1587
- throw new OpenAPIRouteRegistrationError(path, error instanceof Error ? error.message : String(error));
1074
+ throw new RouterError(`OpenAPI route registration failed for "${path}": ${error instanceof Error ? error.message : String(error)}`);
1588
1075
  }
1589
1076
  }
1590
1077
  /**
@@ -1629,7 +1116,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1629
1116
  if (responseSchema && c.env.ENVIRONMENT !== "production") return this.validateResponse(response, responseSchema);
1630
1117
  return response;
1631
1118
  }
1632
- throw new ControllerMethodNotFoundError(methodName, ControllerClass.name);
1119
+ throw new RouterError(`Method "${methodName}" not found on controller "${ControllerClass.name}"`);
1633
1120
  };
1634
1121
  this.nameHandler(handler, ControllerClass.name, methodName);
1635
1122
  return handler;
@@ -1679,21 +1166,13 @@ let RouteRegistrationService = class RouteRegistrationService {
1679
1166
  }
1680
1167
  };
1681
1168
  RouteRegistrationService = __decorate([
1682
- Transient(),
1169
+ Singleton(),
1683
1170
  __decorateParam(0, inject(LOGGER_TOKENS.LoggerService)),
1684
1171
  __decorateParam(1, inject(ROUTER_TOKENS.RouteRegistry)),
1685
- __decorateParam(2, inject(ROUTER_TOKENS.RouterResolver)),
1172
+ __decorateParam(2, inject(ROUTER_TOKENS.RouterResolver, { isOptional: true })),
1686
1173
  __decorateParam(3, inject(ROUTER_TOKENS.LocalePathService)),
1687
1174
  __decorateParam(4, inject(ROUTER_TOKENS.HonoApp)),
1688
- __decorateParam(5, inject(DI_TOKENS.ModuleRegistry)),
1689
- __decorateMetadata("design:paramtypes", [
1690
- Object,
1691
- Object,
1692
- Object,
1693
- Object,
1694
- Object,
1695
- Object
1696
- ])
1175
+ __decorateParam(5, inject(DI_TOKENS.ModuleRegistry))
1697
1176
  ], RouteRegistrationService);
1698
1177
  //#endregion
1699
1178
  //#region src/router/hono-app.ts
@@ -1750,7 +1229,7 @@ let HonoApp = class HonoApp extends OpenAPIHono {
1750
1229
  * Called once by Application.initialize().
1751
1230
  */
1752
1231
  async configure() {
1753
- if (this.configured) throw new HonoAppAlreadyConfiguredError();
1232
+ if (this.configured) throw new RouterError("HonoApp has already been configured");
1754
1233
  this._container.resolve(OPENAPI_TOKENS.OpenAPIService).setupEndpoints(this, this._container);
1755
1234
  await this._container.resolve(RouteRegistrationService).configure();
1756
1235
  this.notFound((c) => {
@@ -1773,19 +1252,57 @@ let HonoApp = class HonoApp extends OpenAPIHono {
1773
1252
  }
1774
1253
  };
1775
1254
  HonoApp = __decorate([
1776
- Transient(),
1255
+ Singleton(),
1777
1256
  __decorateParam(0, inject(CONTAINER_TOKEN)),
1778
1257
  __decorateParam(1, inject(LOGGER_TOKENS.LoggerService)),
1779
- __decorateParam(2, inject(DI_TOKENS.Application)),
1780
- __decorateMetadata("design:paramtypes", [
1781
- Object,
1782
- Object,
1783
- Object
1784
- ])
1258
+ __decorateParam(2, inject(DI_TOKENS.Application))
1785
1259
  ], HonoApp);
1786
1260
  //#endregion
1261
+ //#region src/i18n/i18n.options.ts
1262
+ /**
1263
+ * Resolve I18n options with defaults
1264
+ */
1265
+ function resolveI18nOptions(options) {
1266
+ const detection = options?.detection;
1267
+ const enabled = detection ? detection.enabled !== false : true;
1268
+ const strategy = detection && "strategy" in detection ? detection.strategy ?? "cookie" : "cookie";
1269
+ const prefixDefaultLocale = detection && "prefixDefaultLocale" in detection && detection.prefixDefaultLocale !== void 0 ? detection.prefixDefaultLocale : false;
1270
+ return {
1271
+ defaultLocale: options?.defaultLocale ?? "en",
1272
+ fallbackLocale: options?.fallbackLocale ?? "en",
1273
+ locales: options?.locales ?? ["en"],
1274
+ detection: {
1275
+ enabled,
1276
+ strategy,
1277
+ prefixDefaultLocale
1278
+ }
1279
+ };
1280
+ }
1281
+ /**
1282
+ * Build Hono languageDetector options from I18n module options
1283
+ */
1284
+ function buildDetectorOptions(options) {
1285
+ const resolved = resolveI18nOptions(options);
1286
+ const strategy = resolved.detection.strategy;
1287
+ const detectorOptions = {
1288
+ order: [strategy],
1289
+ fallbackLanguage: resolved.defaultLocale,
1290
+ supportedLanguages: resolved.locales,
1291
+ lookupCookie: "locale",
1292
+ lookupQueryString: "locale",
1293
+ lookupFromPathIndex: 0,
1294
+ ignoreCase: true
1295
+ };
1296
+ if (strategy === "cookie") {
1297
+ detectorOptions.caches = ["cookie"];
1298
+ if (options?.detection && "cookieOptions" in options.detection && options.detection.cookieOptions) detectorOptions.cookieOptions = options.detection.cookieOptions;
1299
+ } else detectorOptions.caches = false;
1300
+ return detectorOptions;
1301
+ }
1302
+ //#endregion
1787
1303
  //#region src/router/services/locale-path.service.ts
1788
1304
  let LocalePathService = class LocalePathService {
1305
+ honoApp;
1789
1306
  _config;
1790
1307
  _pathDetectionEnabled;
1791
1308
  _prefixDefaultLocale;
@@ -1891,10 +1408,9 @@ let LocalePathService = class LocalePathService {
1891
1408
  }
1892
1409
  };
1893
1410
  LocalePathService = __decorate([
1894
- Transient(),
1411
+ Singleton(),
1895
1412
  __decorateParam(0, inject(CONTAINER_TOKEN)),
1896
- __decorateParam(1, inject(ROUTER_TOKENS.HonoApp)),
1897
- __decorateMetadata("design:paramtypes", [Object, Object])
1413
+ __decorateParam(1, inject(ROUTER_TOKENS.HonoApp))
1898
1414
  ], LocalePathService);
1899
1415
  //#endregion
1900
1416
  //#region src/router/services/versioning.service.ts
@@ -1923,11 +1439,7 @@ let VersioningService = class VersioningService {
1923
1439
  return [basePath];
1924
1440
  }
1925
1441
  };
1926
- VersioningService = __decorate([
1927
- Transient(),
1928
- __decorateParam(0, inject(DI_TOKENS.Application)),
1929
- __decorateMetadata("design:paramtypes", [Object])
1930
- ], VersioningService);
1442
+ VersioningService = __decorate([Singleton(), __decorateParam(0, inject(DI_TOKENS.Application))], VersioningService);
1931
1443
  //#endregion
1932
1444
  //#region src/router/route-registry.ts
1933
1445
  const CONCRETE_HTTP_METHODS = [
@@ -1941,6 +1453,8 @@ const CONCRETE_HTTP_METHODS = [
1941
1453
  "trace"
1942
1454
  ];
1943
1455
  let RouteRegistry = class RouteRegistry {
1456
+ versioningService;
1457
+ localePathService;
1944
1458
  routes = [];
1945
1459
  namedRoutes = /* @__PURE__ */ new Map();
1946
1460
  _sortedCache = null;
@@ -1954,7 +1468,7 @@ let RouteRegistry = class RouteRegistry {
1954
1468
  * Named routes must have unique names.
1955
1469
  *
1956
1470
  * @returns Array of expanded RegisteredRoute entries (primary + locale variants)
1957
- * @throws DuplicateRouteNameError if a named route with the same name already exists
1471
+ * @throws RouterError if a named route with the same name already exists
1958
1472
  */
1959
1473
  register(input) {
1960
1474
  const domainParamNames = input.domainParamNames ?? (input.domain ? extractDomainParamNames(input.domain) : []);
@@ -1986,7 +1500,7 @@ let RouteRegistry = class RouteRegistry {
1986
1500
  if (route.name) {
1987
1501
  if (this.namedRoutes.has(route.name)) {
1988
1502
  const existing = this.namedRoutes.get(route.name);
1989
- throw new DuplicateRouteNameError(route.name, `${existing.controller}.${existing.action}`, `${route.controller}.${route.action}`);
1503
+ throw new RouterError(`Duplicate route name "${route.name}": already registered by ${existing.controller}.${existing.action}, cannot register ${route.controller}.${route.action}`);
1990
1504
  }
1991
1505
  this.namedRoutes.set(route.name, route);
1992
1506
  }
@@ -2025,7 +1539,7 @@ let RouteRegistry = class RouteRegistry {
2025
1539
  }
2026
1540
  return cache;
2027
1541
  }
2028
- /** Get all routes sorted by specificity (static > param > wildcard, primary before locale) */
1542
+ /** Get all routes sorted by specificity (static > param > wildcard, locale variant before its primary) */
2029
1543
  all() {
2030
1544
  this._sortedCache ??= sortRoutesBySpecificity(this.routes);
2031
1545
  return this._sortedCache;
@@ -2036,12 +1550,41 @@ let RouteRegistry = class RouteRegistry {
2036
1550
  }
2037
1551
  };
2038
1552
  RouteRegistry = __decorate([
2039
- Transient(),
1553
+ Singleton(),
2040
1554
  __decorateParam(0, inject(ROUTER_TOKENS.VersioningService)),
2041
- __decorateParam(1, inject(ROUTER_TOKENS.LocalePathService)),
2042
- __decorateMetadata("design:paramtypes", [Object, Object])
1555
+ __decorateParam(1, inject(ROUTER_TOKENS.LocalePathService))
2043
1556
  ], RouteRegistry);
2044
1557
  //#endregion
1558
+ //#region src/router/route-url.ts
1559
+ /**
1560
+ * Generate a URL from a named route.
1561
+ *
1562
+ * Keys in `params` matching `:param` placeholders fill the path.
1563
+ * Domain params (`{tenant}`) are also consumed from `params`.
1564
+ * Extra keys become query string parameters.
1565
+ *
1566
+ * Resolves RouteRegistry from the application container via AsyncLocalStorage.
1567
+ * Available after `Application.initialize()` has been called.
1568
+ *
1569
+ * @param name - Named route identifier
1570
+ * @param params - Route params + domain params + extra query params
1571
+ * @returns Generated URL string
1572
+ *
1573
+ * @example
1574
+ * ```typescript
1575
+ * // In a controller (preferred):
1576
+ * ctx.route('users.show', { id: '1' })
1577
+ *
1578
+ * // Outside controllers (standalone function):
1579
+ * import { route } from 'stratal/router'
1580
+ *
1581
+ * route('users.show', { id: '1' })
1582
+ * ```
1583
+ */
1584
+ function route(name, params, options) {
1585
+ return getContainer().resolve(ROUTER_TOKENS.Uri).route(name, params, options);
1586
+ }
1587
+ //#endregion
2045
1588
  //#region src/router/uri.ts
2046
1589
  /**
2047
1590
  * Encode a value for use as a path parameter.
@@ -2064,7 +1607,7 @@ function encodePathParam(value) {
2064
1607
  * @param params - Path params, domain params, and extra query params
2065
1608
  * @returns Relative URL string (or absolute with domain prefix if route has a domain pattern)
2066
1609
  *
2067
- * @throws MissingRouteParamError if a required path or domain param is missing
1610
+ * @throws RouterError if a required path or domain param is missing
2068
1611
  */
2069
1612
  function buildRouteUrl(route, name, params) {
2070
1613
  const allParams = { ...params };
@@ -2076,7 +1619,7 @@ function buildRouteUrl(route, name, params) {
2076
1619
  }
2077
1620
  for (const paramName of route.paramNames) {
2078
1621
  const value = allParams[paramName];
2079
- if (value === void 0) throw new MissingRouteParamError(paramName, name, route.path);
1622
+ if (value === void 0) throw new RouterError(`Missing required route parameter "${paramName}" for route "${name}" (path: ${route.path})`);
2080
1623
  url = url.replace(new RegExp(`:${paramName}(\\{[^}]*\\})?`), encodePathParam(value));
2081
1624
  consumedKeys.add(paramName);
2082
1625
  }
@@ -2085,7 +1628,7 @@ function buildRouteUrl(route, name, params) {
2085
1628
  domain = route.domain;
2086
1629
  for (const domainParam of route.domainParamNames) {
2087
1630
  const value = allParams[domainParam];
2088
- if (value === void 0) throw new MissingRouteParamError(domainParam, name, route.domain);
1631
+ if (value === void 0) throw new RouterError(`Missing required domain parameter "${domainParam}" for route "${name}" (domain: ${route.domain})`);
2089
1632
  domain = domain.replace(`{${domainParam}}`, encodeURIComponent(value));
2090
1633
  consumedKeys.add(domainParam);
2091
1634
  }
@@ -2099,6 +1642,8 @@ function buildRouteUrl(route, name, params) {
2099
1642
  return url;
2100
1643
  }
2101
1644
  let Uri = class Uri {
1645
+ registry;
1646
+ routerContext;
2102
1647
  _defaults = {};
2103
1648
  trailingSlash;
2104
1649
  constructor(registry, routerContext, application) {
@@ -2141,12 +1686,11 @@ let Uri = class Uri {
2141
1686
  * @param options - URL generation options
2142
1687
  * @returns Generated URL string
2143
1688
  *
2144
- * @throws RouteNameNotFoundError if route name not found
2145
- * @throws MissingRouteParamError if required params missing
1689
+ * @throws RouterError if route name not found or required params missing
2146
1690
  */
2147
1691
  route(name, params, options) {
2148
1692
  const registeredRoute = this.registry.get(name);
2149
- if (!registeredRoute) throw new RouteNameNotFoundError(name);
1693
+ if (!registeredRoute) throw new RouterError(`Route name "${name}" was not found in the registry`);
2150
1694
  let url = applyTrailingSlash(buildRouteUrl(registeredRoute, name, {
2151
1695
  ...this._defaults,
2152
1696
  ...params
@@ -2266,52 +1810,12 @@ let Uri = class Uri {
2266
1810
  }
2267
1811
  };
2268
1812
  Uri = __decorate([
2269
- Transient(),
1813
+ Request(),
2270
1814
  __decorateParam(0, inject(ROUTER_TOKENS.RouteRegistry)),
2271
1815
  __decorateParam(1, inject(ROUTER_TOKENS.RouterContext)),
2272
- __decorateParam(2, inject(DI_TOKENS.Application)),
2273
- __decorateMetadata("design:paramtypes", [
2274
- Object,
2275
- Object,
2276
- Object
2277
- ])
1816
+ __decorateParam(2, inject(DI_TOKENS.Application))
2278
1817
  ], Uri);
2279
1818
  //#endregion
2280
- //#region src/router/route-url.ts
2281
- /**
2282
- * Generate a URL from a named route.
2283
- *
2284
- * Keys in `params` matching `:param` placeholders fill the path.
2285
- * Domain params (`{tenant}`) are also consumed from `params`.
2286
- * Extra keys become query string parameters.
2287
- *
2288
- * Resolves RouteRegistry from the application container via AsyncLocalStorage.
2289
- * Available after `Application.initialize()` has been called.
2290
- *
2291
- * @param name - Named route identifier
2292
- * @param params - Route params + domain params + extra query params
2293
- * @returns Generated URL string
2294
- *
2295
- * @example
2296
- * ```typescript
2297
- * // In a controller (preferred):
2298
- * ctx.route('users.show', { id: '1' })
2299
- *
2300
- * // Outside controllers (standalone function):
2301
- * import { route } from 'stratal/router'
2302
- *
2303
- * route('users.show', { id: '1' })
2304
- * ```
2305
- */
2306
- function route(name, params) {
2307
- const container = getContainer();
2308
- const registry = container.resolve(ROUTER_TOKENS.RouteRegistry);
2309
- const application = container.resolve(DI_TOKENS.Application);
2310
- const registeredRoute = registry.get(name);
2311
- if (!registeredRoute) throw new RouteNameNotFoundError(name);
2312
- return applyTrailingSlash(buildRouteUrl(registeredRoute, name, params), application.config.trailingSlash ?? "ignore");
2313
- }
2314
- //#endregion
2315
1819
  //#region src/router/middleware/verify-signature.middleware.ts
2316
1820
  /**
2317
1821
  * Middleware that verifies signed URLs.
@@ -2337,156 +1841,12 @@ var VerifySignatureMiddleware = class {
2337
1841
  async handle(ctx, next) {
2338
1842
  const url = ctx.c.req.url;
2339
1843
  const secret = ctx.c.env.APP_SECRET;
2340
- if (!secret) throw new MissingEnvironmentVariableError("APP_SECRET");
1844
+ if (!secret) throw new RouterError("Missing required environment variable \"APP_SECRET\"");
2341
1845
  if (!await verifySignedUrl(url, secret)) throw new InvalidSignatureError();
2342
1846
  await next();
2343
1847
  }
2344
1848
  };
2345
1849
  //#endregion
2346
- //#region src/i18n/services/i18n.service.ts
2347
- /**
2348
- * I18n Service
2349
- *
2350
- * Request-scoped service for translations.
2351
- * Injects RouterContext to access request-specific locale.
2352
- * Uses pre-built CoreContext from MessageLoaderService (singleton) for zero-cost lookups.
2353
- */
2354
- let I18nService = class I18nService {
2355
- constructor(loader, routerContext) {
2356
- this.loader = loader;
2357
- this.routerContext = routerContext;
2358
- }
2359
- /**
2360
- * Translate a message key
2361
- *
2362
- * @param key - Message key (e.g., 'common.actions.save')
2363
- * @param params - Optional parameters for interpolation
2364
- * @returns Translated string
2365
- */
2366
- t(key, params) {
2367
- const context = this.loader.getCoreContext(this.getLocale());
2368
- const result = params !== void 0 ? translate(context, key, params) : translate(context, key);
2369
- return typeof result === "string" ? result : key;
2370
- }
2371
- /**
2372
- * Get current locale
2373
- *
2374
- * @returns Current locale code from RouterContext or default locale
2375
- */
2376
- getLocale() {
2377
- return this.routerContext?.getLocale() ?? "en";
2378
- }
2379
- };
2380
- I18nService = __decorate([
2381
- Transient(I18N_TOKENS.I18nService),
2382
- __decorateParam(0, inject(I18N_TOKENS.MessageLoader)),
2383
- __decorateParam(1, inject(ROUTER_TOKENS.RouterContext, { isOptional: true })),
2384
- __decorateMetadata("design:paramtypes", [Object, Object])
2385
- ], I18nService);
2386
- //#endregion
2387
- //#region src/i18n/i18n.module.ts
2388
- /**
2389
- * I18n Module
2390
- *
2391
- * Core infrastructure module for internationalization.
2392
- * Provides message translation and locale handling.
2393
- *
2394
- * - `forRoot()` configures locale settings (call once in root module)
2395
- * - `registerMessages()` adds translations (call from any module, as many times as needed)
2396
- *
2397
- * @example
2398
- * ```typescript
2399
- * @Module({
2400
- * imports: [
2401
- * I18nModule.forRoot({ defaultLocale: 'en', locales: ['en', 'fr'] }),
2402
- * I18nModule.registerMessages(appMessages),
2403
- * ],
2404
- * })
2405
- * export class AppModule {}
2406
- * ```
2407
- *
2408
- * @example Package contributing messages
2409
- * ```typescript
2410
- * @Module({
2411
- * imports: [
2412
- * I18nModule.registerMessages(tenancyMessages),
2413
- * ],
2414
- * })
2415
- * export class TenancyModule {}
2416
- * ```
2417
- */
2418
- var _I18nModule;
2419
- setupI18nCompiler();
2420
- z.config({ customError: backendErrorMap });
2421
- let I18nModule = _I18nModule = class I18nModule {
2422
- /**
2423
- * Configure I18n locale settings
2424
- *
2425
- * Call once in the root module. Does not accept messages —
2426
- * use `registerMessages()` to add translations.
2427
- *
2428
- * @param options - Locale configuration (defaultLocale, fallbackLocale, locales)
2429
- */
2430
- static forRoot(options = {}) {
2431
- return {
2432
- module: _I18nModule,
2433
- providers: [{
2434
- provide: I18N_TOKENS.Options,
2435
- useValue: options
2436
- }]
2437
- };
2438
- }
2439
- /**
2440
- * Register i18n messages
2441
- *
2442
- * Can be called from any module, as many times as needed.
2443
- * Messages are deep-merged in registration order — later calls override earlier ones at leaf level.
2444
- *
2445
- * @param messages - Messages keyed by locale code
2446
- *
2447
- * @example App-level messages
2448
- * ```typescript
2449
- * I18nModule.registerMessages({
2450
- * en: { common: { hello: 'Hello' }, errors: { notFound: 'Not found' } },
2451
- * fr: { common: { hello: 'Bonjour' }, errors: { notFound: 'Introuvable' } },
2452
- * })
2453
- * ```
2454
- *
2455
- * @example Package-level messages
2456
- * ```typescript
2457
- * I18nModule.registerMessages({
2458
- * en: { tenancy: { tenantNotFound: 'Tenant not found' } },
2459
- * })
2460
- * ```
2461
- */
2462
- static registerMessages(messages) {
2463
- MessageRegistry.addMessages(messages);
2464
- return {
2465
- module: _I18nModule,
2466
- providers: []
2467
- };
2468
- }
2469
- configureRoutes(router) {
2470
- router.use(I18nContextMiddleware);
2471
- }
2472
- };
2473
- I18nModule = _I18nModule = __decorate([Module({ providers: [
2474
- {
2475
- provide: I18N_TOKENS.MessageRegistry,
2476
- useClass: MessageRegistry,
2477
- scope: Scope.Singleton
2478
- },
2479
- {
2480
- provide: I18N_TOKENS.MessageLoader,
2481
- useClass: MessageLoaderService,
2482
- scope: Scope.Singleton
2483
- },
2484
- {
2485
- provide: I18N_TOKENS.I18nService,
2486
- useClass: I18nService
2487
- }
2488
- ] })], I18nModule);
2489
- //#endregion
2490
- export { OpenAPIModule as A, LocaleNotSupportedError as B, validationErrorResponseSchema as C, createMiddlewareChain as D, getRouteMetadata as E, getMessages as F, I18nContextMiddleware as H, messages as I, buildDetectorOptions as L, MessageRegistry as M, MessageLoaderService as N, createDomainMiddleware as O, getLocales as P, resolveI18nOptions as R, uuidParamSchema as S, getRouteDecoratedMethods as T, OpenAPIConfigService as V, commonErrorSchemas as _, buildRouteUrl as a, paginationQuerySchema as b, LocalePathService as c, extractDomainParamNames as d, extractParamNames as f, toOpenAPIPath as g, sortRoutesBySpecificity as h, Uri as i, OpenAPIService as j, parseDomainPattern as k, HonoApp as l, getPathSpecificityScore as m, VerifySignatureMiddleware as n, RouteRegistry as o, generateConventionRouteName as p, route as r, VersioningService as s, I18nModule as t, RouteRegistrationService as u, errorResponseSchema as v, Route as w, successMessageSchema as x, paginatedResponseSchema as y, TranslationMissingError as z };
1850
+ export { parseDomainPattern as A, uuidParamSchema as C, getRouteMetadata as D, getRouteDecoratedMethods as E, ResponseValidationError as M, SchemaValidationError as N, createMiddlewareChain as O, RouteNotFoundError as P, successMessageSchema as S, Route as T, toOpenAPIPath as _, RouteRegistry as a, paginatedResponseSchema as b, buildDetectorOptions as c, RouteRegistrationService as d, extractDomainParamNames as f, sortRoutesBySpecificity as g, getPathSpecificityScore as h, route as i, InvalidSignatureError as j, createDomainMiddleware as k, resolveI18nOptions as l, generateConventionRouteName as m, Uri as n, VersioningService as o, extractParamNames as p, buildRouteUrl as r, LocalePathService as s, VerifySignatureMiddleware as t, HonoApp as u, commonErrorSchemas as v, validationErrorResponseSchema as w, paginationQuerySchema as x, errorResponseSchema as y };
2491
1851
 
2492
- //# sourceMappingURL=i18n.module-BBlNNlcG.mjs.map
1852
+ //# sourceMappingURL=router-Cy6DjkvP.mjs.map