stratal 0.0.21 → 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 (246) 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/quarry.mjs +46 -109
  5. package/dist/bin/quarry.mjs.map +1 -1
  6. package/dist/cache/index.d.mts +6 -46
  7. package/dist/cache/index.d.mts.map +1 -1
  8. package/dist/cache/index.mjs +20 -67
  9. package/dist/cache/index.mjs.map +1 -1
  10. package/dist/{cache.service-DsnKuNyO.d.mts → cache.service-e34gV6tz.d.mts} +8 -8
  11. package/dist/{cache.service-DsnKuNyO.d.mts.map → cache.service-e34gV6tz.d.mts.map} +1 -1
  12. package/dist/{cache.tokens-B7Rw1C9Q.mjs → cache.tokens-ovi_c52J.mjs} +1 -1
  13. package/dist/{cache.tokens-B7Rw1C9Q.mjs.map → cache.tokens-ovi_c52J.mjs.map} +1 -1
  14. package/dist/{colors-DJaRDXoS.mjs → colors-axmupKdp.mjs} +1 -1
  15. package/dist/{colors-DJaRDXoS.mjs.map → colors-axmupKdp.mjs.map} +1 -1
  16. package/dist/{command-BgSlsS4M.mjs → command-BU4ApTo5.mjs} +2 -3
  17. package/dist/command-BU4ApTo5.mjs.map +1 -0
  18. package/dist/{command-Cmmf0oHX.d.mts → command-wXfvHbBZ.d.mts} +3 -2
  19. package/dist/command-wXfvHbBZ.d.mts.map +1 -0
  20. package/dist/config/index.d.mts +24 -11
  21. package/dist/config/index.d.mts.map +1 -1
  22. package/dist/config/index.mjs +31 -57
  23. package/dist/config/index.mjs.map +1 -1
  24. package/dist/{consumer-registry-B7yUNh0q.d.mts → consumer-registry-DHQtypr1.d.mts} +1 -1
  25. package/dist/{consumer-registry-B7yUNh0q.d.mts.map → consumer-registry-DHQtypr1.d.mts.map} +1 -1
  26. package/dist/container-storage-GpNNz79X.mjs +52 -0
  27. package/dist/container-storage-GpNNz79X.mjs.map +1 -0
  28. package/dist/{controller.decorator-B9vwn0zK.mjs → controller.decorator-DIUazNU7.mjs} +8 -8
  29. package/dist/controller.decorator-DIUazNU7.mjs.map +1 -0
  30. package/dist/cron/index.d.mts +26 -5
  31. package/dist/cron/index.d.mts.map +1 -1
  32. package/dist/cron/index.mjs +1 -1
  33. package/dist/{cron-manager-DQSK8uoV.mjs → cron-manager-9bpN9bu4.mjs} +35 -15
  34. package/dist/cron-manager-9bpN9bu4.mjs.map +1 -0
  35. package/dist/{cron-manager-CmTimEjf.d.mts → cron-manager-CSTIBPcM.d.mts} +6 -13
  36. package/dist/cron-manager-CSTIBPcM.d.mts.map +1 -0
  37. package/dist/decorate-HgTKAYK8.mjs +16 -0
  38. package/dist/deep-merge-C8NgcXw4.mjs +18 -0
  39. package/dist/deep-merge-C8NgcXw4.mjs.map +1 -0
  40. package/dist/di/index.d.mts +2 -2
  41. package/dist/di/index.mjs +4 -3
  42. package/dist/di-BO1QIb5H.mjs +415 -0
  43. package/dist/di-BO1QIb5H.mjs.map +1 -0
  44. package/dist/email/index.d.mts +14 -89
  45. package/dist/email/index.d.mts.map +1 -1
  46. package/dist/email/index.mjs +25 -125
  47. package/dist/email/index.mjs.map +1 -1
  48. package/dist/en-BPP6h6y5.mjs +202 -0
  49. package/dist/en-BPP6h6y5.mjs.map +1 -0
  50. package/dist/{env-D1rcZ8_r.d.mts → env-DKSbuBi5.d.mts} +1 -1
  51. package/dist/env-DKSbuBi5.d.mts.map +1 -0
  52. package/dist/errors/index.d.mts +2 -2
  53. package/dist/errors/index.mjs +4 -2
  54. package/dist/errors-BBZTnjdq.mjs +333 -0
  55. package/dist/errors-BBZTnjdq.mjs.map +1 -0
  56. package/dist/events/index.d.mts +2 -2
  57. package/dist/events/index.d.mts.map +1 -1
  58. package/dist/events/index.mjs +1 -1
  59. package/dist/{events-CzCV8jI8.mjs → events-D1KdDaiP.mjs} +11 -11
  60. package/dist/events-D1KdDaiP.mjs.map +1 -0
  61. package/dist/exception-context-B4kM-M53.mjs +429 -0
  62. package/dist/exception-context-B4kM-M53.mjs.map +1 -0
  63. package/dist/{gateway-context-CXmXtaUP.mjs → gateway-context-CFe6a9gz.mjs} +19 -31
  64. package/dist/gateway-context-CFe6a9gz.mjs.map +1 -0
  65. package/dist/guards/index.d.mts +3 -3
  66. package/dist/guards/index.d.mts.map +1 -1
  67. package/dist/guards/index.mjs +1 -1
  68. package/dist/{guards-DU1_J9YA.mjs → guards-Ced-uNIF.mjs} +6 -5
  69. package/dist/guards-Ced-uNIF.mjs.map +1 -0
  70. package/dist/{http-method.decorator-BrgHMdLQ.mjs → http-method.decorator-CdjKFJZZ.mjs} +7 -6
  71. package/dist/http-method.decorator-CdjKFJZZ.mjs.map +1 -0
  72. package/dist/i18n/index.d.mts +238 -3
  73. package/dist/i18n/index.d.mts.map +1 -0
  74. package/dist/i18n/index.mjs +39 -3
  75. package/dist/i18n/index.mjs.map +1 -0
  76. package/dist/i18n/messages/en/index.d.mts +2 -2
  77. package/dist/i18n/messages/en/index.mjs +2 -2
  78. package/dist/i18n/utils/index.d.mts +4 -26
  79. package/dist/i18n/utils/index.d.mts.map +1 -1
  80. package/dist/i18n/utils/index.mjs +2 -2
  81. package/dist/i18n/validation/index.d.mts +3 -2
  82. package/dist/i18n/validation/index.mjs +4 -2
  83. package/dist/i18n.module-BlXrtAlV.mjs +219 -0
  84. package/dist/i18n.module-BlXrtAlV.mjs.map +1 -0
  85. package/dist/i18n.tokens-hwRpmjRq.mjs +19 -0
  86. package/dist/i18n.tokens-hwRpmjRq.mjs.map +1 -0
  87. package/dist/{index-7-hU3GTV.d.mts → index-B4UBK-2T.d.mts} +1 -1
  88. package/dist/{index-7-hU3GTV.d.mts.map → index-B4UBK-2T.d.mts.map} +1 -1
  89. package/dist/index-BtlE9RuO.d.mts +124 -0
  90. package/dist/index-BtlE9RuO.d.mts.map +1 -0
  91. package/dist/{index-DUzWs0z7.d.mts → index-CW1YHSft.d.mts} +71 -167
  92. package/dist/index-CW1YHSft.d.mts.map +1 -0
  93. package/dist/{index-ByOyTmqf.d.mts → index-DEncMcC6.d.mts} +554 -2237
  94. package/dist/index-DEncMcC6.d.mts.map +1 -0
  95. package/dist/index-Dj5IMwtr.d.mts +44 -0
  96. package/dist/index-Dj5IMwtr.d.mts.map +1 -0
  97. package/dist/{index-C1KvMncZ.d.mts → index-KMgSCSM7.d.mts} +3 -108
  98. package/dist/index-KMgSCSM7.d.mts.map +1 -0
  99. package/dist/index.d.mts +5 -43
  100. package/dist/index.mjs +1 -1
  101. package/dist/{is-command-C6a7WTPw.mjs → is-command-CX5rAfZW.mjs} +2 -2
  102. package/dist/{is-command-C6a7WTPw.mjs.map → is-command-CX5rAfZW.mjs.map} +1 -1
  103. package/dist/{is-seeder-CebjZCDn.mjs → is-seeder-CYCtELlm.mjs} +1 -1
  104. package/dist/{is-seeder-CebjZCDn.mjs.map → is-seeder-CYCtELlm.mjs.map} +1 -1
  105. package/dist/logger/index.d.mts +2 -2
  106. package/dist/logger/index.mjs +170 -2
  107. package/dist/logger/index.mjs.map +1 -0
  108. package/dist/macroable/index.d.mts +1 -1
  109. package/dist/macroable/index.mjs +1 -1
  110. package/dist/{macroable-BmufBshB.mjs → macroable-DzlfzT50.mjs} +1 -1
  111. package/dist/{macroable-BmufBshB.mjs.map → macroable-DzlfzT50.mjs.map} +1 -1
  112. package/dist/metadata-BVkc4aUu.mjs +39 -0
  113. package/dist/metadata-BVkc4aUu.mjs.map +1 -0
  114. package/dist/module/index.d.mts +6 -24
  115. package/dist/module/index.d.mts.map +1 -1
  116. package/dist/module/index.mjs +2 -2
  117. package/dist/module-xYoHba6B.mjs +422 -0
  118. package/dist/module-xYoHba6B.mjs.map +1 -0
  119. package/dist/openapi/index.d.mts +3 -3
  120. package/dist/openapi/index.d.mts.map +1 -1
  121. package/dist/openapi/index.mjs +1 -2
  122. package/dist/openapi-C6lm0RmV.mjs +483 -0
  123. package/dist/openapi-C6lm0RmV.mjs.map +1 -0
  124. package/dist/{openapi.service-Bt9bCIrd.d.mts → openapi.service-CrLlsXAd.d.mts} +3 -3
  125. package/dist/openapi.service-CrLlsXAd.d.mts.map +1 -0
  126. package/dist/quarry/index.d.mts +5 -163
  127. package/dist/quarry/index.d.mts.map +1 -1
  128. package/dist/quarry/index.mjs +5 -5
  129. package/dist/quarry/runner.d.mts +184 -0
  130. package/dist/quarry/runner.d.mts.map +1 -0
  131. package/dist/quarry/runner.mjs +775 -0
  132. package/dist/quarry/runner.mjs.map +1 -0
  133. package/dist/quarry-registry-D4hIGScf.d.mts +69 -0
  134. package/dist/quarry-registry-D4hIGScf.d.mts.map +1 -0
  135. package/dist/quarry-registry-DkraZNwn.mjs +311 -0
  136. package/dist/quarry-registry-DkraZNwn.mjs.map +1 -0
  137. package/dist/queue/index.d.mts +3 -3
  138. package/dist/queue/index.mjs +26 -28
  139. package/dist/queue/index.mjs.map +1 -1
  140. package/dist/{queue.module-BhCjZp6H.mjs → queue.module-DeWJ0tQM.mjs} +59 -113
  141. package/dist/queue.module-DeWJ0tQM.mjs.map +1 -0
  142. package/dist/{r2-storage.provider-DuonKeYm.mjs → r2-storage.provider-Hfm6LdZQ.mjs} +5 -5
  143. package/dist/r2-storage.provider-Hfm6LdZQ.mjs.map +1 -0
  144. package/dist/{rate-limit.decorator-6qzNcSOt.mjs → rate-limit.decorator-D69zdZbp.mjs} +6 -11
  145. package/dist/rate-limit.decorator-D69zdZbp.mjs.map +1 -0
  146. package/dist/rate-limiter/index.d.mts +11 -50
  147. package/dist/rate-limiter/index.d.mts.map +1 -1
  148. package/dist/rate-limiter/index.mjs +16 -30
  149. package/dist/rate-limiter/index.mjs.map +1 -1
  150. package/dist/{resend.provider-DB4IlFjG.mjs → resend.provider-Ur6tU7fK.mjs} +7 -7
  151. package/dist/resend.provider-Ur6tU7fK.mjs.map +1 -0
  152. package/dist/router/index.d.mts +2 -2
  153. package/dist/router/index.mjs +8 -7
  154. package/dist/{i18n.module-CzXLW9Hy.mjs → router-Cy6DjkvP.mjs} +171 -851
  155. package/dist/router-Cy6DjkvP.mjs.map +1 -0
  156. package/dist/seeder/index.d.mts +6 -11
  157. package/dist/seeder/index.d.mts.map +1 -1
  158. package/dist/seeder/index.mjs +3 -3
  159. package/dist/{seeder-zoEfEw9i.mjs → seeder-BADTig4n.mjs} +14 -22
  160. package/dist/seeder-BADTig4n.mjs.map +1 -0
  161. package/dist/{signed-url-BQPbv2In.mjs → signed-url-BqUqt5dF.mjs} +1 -1
  162. package/dist/{signed-url-BQPbv2In.mjs.map → signed-url-BqUqt5dF.mjs.map} +1 -1
  163. package/dist/{smtp.provider-B6D7zuWX.mjs → smtp.provider-C129sNBT.mjs} +6 -6
  164. package/dist/smtp.provider-C129sNBT.mjs.map +1 -0
  165. package/dist/storage/index.d.mts +15 -39
  166. package/dist/storage/index.d.mts.map +1 -1
  167. package/dist/storage/index.mjs +3 -3
  168. package/dist/storage/providers/index.d.mts +2 -2
  169. package/dist/storage/providers/index.mjs +1 -1
  170. package/dist/{storage-D8CBP72Z.mjs → storage-BA3ppVYM.mjs} +65 -59
  171. package/dist/storage-BA3ppVYM.mjs.map +1 -0
  172. package/dist/{storage-provider.interface-Bd6vA4ak.d.mts → storage-provider.interface-DQMtT42e.d.mts} +2 -3
  173. package/dist/storage-provider.interface-DQMtT42e.d.mts.map +1 -0
  174. package/dist/storage.error-C6FY037a.mjs +8 -0
  175. package/dist/storage.error-C6FY037a.mjs.map +1 -0
  176. package/dist/{stratal-CNwpbSZl.mjs → stratal-Bdq4IdB3.mjs} +31 -185
  177. package/dist/stratal-Bdq4IdB3.mjs.map +1 -0
  178. package/dist/stratal-BsKmvP6J.d.mts +43 -0
  179. package/dist/stratal-BsKmvP6J.d.mts.map +1 -0
  180. package/dist/{types-cySNS_lp.d.mts → types-BaeHi67f.d.mts} +1 -1
  181. package/dist/types-BaeHi67f.d.mts.map +1 -0
  182. package/dist/{usage-generator-BUdlhnCK.mjs → usage-generator-DTqaUMR9.mjs} +6 -3
  183. package/dist/usage-generator-DTqaUMR9.mjs.map +1 -0
  184. package/dist/validation-DUzcjb8Q.mjs +49 -0
  185. package/dist/validation-DUzcjb8Q.mjs.map +1 -0
  186. package/dist/validation.context-XTysWJ3b.mjs +117 -0
  187. package/dist/validation.context-XTysWJ3b.mjs.map +1 -0
  188. package/dist/websocket/index.d.mts +7 -14
  189. package/dist/websocket/index.d.mts.map +1 -1
  190. package/dist/websocket/index.mjs +2 -2
  191. package/dist/workers/index.d.mts +2 -2
  192. package/dist/workers/index.mjs +3 -2
  193. package/dist/workers/index.mjs.map +1 -1
  194. package/dist/{index-Bnpfq6uk.d.mts → zod-DvWTfRpI.d.mts} +58 -133
  195. package/dist/zod-DvWTfRpI.d.mts.map +1 -0
  196. package/dist/zod-hMa3rSHV.mjs +72 -0
  197. package/dist/zod-hMa3rSHV.mjs.map +1 -0
  198. package/package.json +10 -10
  199. package/dist/command-BgSlsS4M.mjs.map +0 -1
  200. package/dist/command-Cmmf0oHX.d.mts.map +0 -1
  201. package/dist/controller.decorator-B9vwn0zK.mjs.map +0 -1
  202. package/dist/cron-manager-CmTimEjf.d.mts.map +0 -1
  203. package/dist/cron-manager-DQSK8uoV.mjs.map +0 -1
  204. package/dist/en-DSH_bhh6.mjs +0 -308
  205. package/dist/en-DSH_bhh6.mjs.map +0 -1
  206. package/dist/env-D1rcZ8_r.d.mts.map +0 -1
  207. package/dist/errors-COW9-Mar.mjs +0 -1739
  208. package/dist/errors-COW9-Mar.mjs.map +0 -1
  209. package/dist/errors-ORxu1-Bb.mjs +0 -74
  210. package/dist/errors-ORxu1-Bb.mjs.map +0 -1
  211. package/dist/events-CzCV8jI8.mjs.map +0 -1
  212. package/dist/gateway-context-CXmXtaUP.mjs.map +0 -1
  213. package/dist/guards-DU1_J9YA.mjs.map +0 -1
  214. package/dist/http-method.decorator-BrgHMdLQ.mjs.map +0 -1
  215. package/dist/i18n.module-CzXLW9Hy.mjs.map +0 -1
  216. package/dist/index-Bnpfq6uk.d.mts.map +0 -1
  217. package/dist/index-ByOyTmqf.d.mts.map +0 -1
  218. package/dist/index-C1KvMncZ.d.mts.map +0 -1
  219. package/dist/index-DBd_2wv8.d.mts +0 -263
  220. package/dist/index-DBd_2wv8.d.mts.map +0 -1
  221. package/dist/index-DUzWs0z7.d.mts.map +0 -1
  222. package/dist/index.d.mts.map +0 -1
  223. package/dist/logger-DlV7NtvD.mjs +0 -440
  224. package/dist/logger-DlV7NtvD.mjs.map +0 -1
  225. package/dist/module-BzLg57FK.mjs +0 -866
  226. package/dist/module-BzLg57FK.mjs.map +0 -1
  227. package/dist/openapi-tools.service-Zs-Ewv7F.mjs +0 -200
  228. package/dist/openapi-tools.service-Zs-Ewv7F.mjs.map +0 -1
  229. package/dist/openapi.service-Bt9bCIrd.d.mts.map +0 -1
  230. package/dist/quarry-registry-BwY2hOxm.mjs +0 -699
  231. package/dist/quarry-registry-BwY2hOxm.mjs.map +0 -1
  232. package/dist/queue.module-BhCjZp6H.mjs.map +0 -1
  233. package/dist/r2-storage.provider-DuonKeYm.mjs.map +0 -1
  234. package/dist/rate-limit.decorator-6qzNcSOt.mjs.map +0 -1
  235. package/dist/resend.provider-DB4IlFjG.mjs.map +0 -1
  236. package/dist/seeder-zoEfEw9i.mjs.map +0 -1
  237. package/dist/setup-CefZKV_e.mjs +0 -37
  238. package/dist/setup-CefZKV_e.mjs.map +0 -1
  239. package/dist/smtp.provider-B6D7zuWX.mjs.map +0 -1
  240. package/dist/storage-D8CBP72Z.mjs.map +0 -1
  241. package/dist/storage-provider.interface-Bd6vA4ak.d.mts.map +0 -1
  242. package/dist/stratal-CNwpbSZl.mjs.map +0 -1
  243. package/dist/types-cySNS_lp.d.mts.map +0 -1
  244. package/dist/usage-generator-BUdlhnCK.mjs.map +0 -1
  245. package/dist/validation-DtJwAv7O.mjs +0 -248
  246. package/dist/validation-DtJwAv7O.mjs.map +0 -1
@@ -1,604 +1,75 @@
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-COW9-Mar.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-DlV7NtvD.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-BzLg57FK.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-DU1_J9YA.mjs";
8
- import { n as getControllerOptions, r as getControllerRoute } from "./controller.decorator-B9vwn0zK.mjs";
9
- import { c as getWsOnMessageMethod, d as isGateway, o as getWsOnCloseMethod, s as getWsOnErrorMethod, t as GatewayContext } from "./gateway-context-CXmXtaUP.mjs";
10
- import "./http-method.decorator-BrgHMdLQ.mjs";
11
- import { n as getRateLimits } from "./rate-limit.decorator-6qzNcSOt.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
- i18n;
27
- constructor(i18n) {
28
- this.i18n = i18n;
29
- }
30
- async handle(ctx, next) {
31
- await runWithErrorMapContext({
32
- t: (key, params) => this.i18n.t(key, params),
33
- locale: ctx.getLocale()
34
- }, () => next());
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;
35
27
  }
36
28
  };
37
- I18nContextMiddleware = __decorate([
38
- Transient(),
39
- __decorateParam(0, inject(I18N_TOKENS.I18nService)),
40
- __decorateMetadata("design:paramtypes", [Object])
41
- ], I18nContextMiddleware);
42
29
  //#endregion
43
- //#region src/openapi/services/openapi-config.service.ts
44
- let OpenAPIConfigService = class OpenAPIConfigService {
45
- baseOptions;
46
- overrides = [];
47
- constructor(baseOptions) {
48
- this.baseOptions = baseOptions;
49
- }
50
- /**
51
- * Add configuration override for this request.
52
- * Overrides are merged in the order they are added.
53
- */
54
- override(config) {
55
- this.overrides.push(config);
56
- }
57
- /** Get effective configuration (base merged with all overrides) */
58
- getEffectiveConfig() {
59
- let effective = {
60
- jsonPath: this.baseOptions?.jsonPath ?? "/api/openapi.json",
61
- ui: this.baseOptions?.ui,
62
- info: {
63
- title: this.baseOptions?.info?.title ?? "API",
64
- version: this.baseOptions?.info?.version ?? "1.0.0",
65
- description: this.baseOptions?.info?.description
66
- },
67
- securitySchemes: this.baseOptions?.securitySchemes
68
- };
69
- for (const override of this.overrides) effective = this.mergeConfig(effective, override);
70
- return effective;
71
- }
72
- /**
73
- * Merge override into effective config.
74
- * Info is shallow-merged, routeFilter is replaced.
75
- */
76
- mergeConfig(base, override) {
77
- return {
78
- ...base,
79
- info: {
80
- ...base.info,
81
- ...override.info && {
82
- title: override.info.title ?? base.info.title,
83
- version: override.info.version ?? base.info.version,
84
- description: override.info.description ?? base.info.description
85
- }
86
- },
87
- routeFilter: override.routeFilter ?? base.routeFilter
88
- };
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
+ }));
89
40
  }
90
41
  };
91
- OpenAPIConfigService = __decorate([
92
- Transient(OPENAPI_TOKENS.ConfigService),
93
- __decorateParam(0, inject(OPENAPI_TOKENS.Options, { isOptional: true })),
94
- __decorateMetadata("design:paramtypes", [Object])
95
- ], OpenAPIConfigService);
96
42
  //#endregion
97
- //#region src/i18n/errors/locale-not-supported.error.ts
43
+ //#region src/router/errors/index.ts
98
44
  /**
99
- * Locale Not Supported Error
100
- * Thrown when an unsupported locale is requested
45
+ * Error thrown when a signed URL has an invalid or expired signature.
101
46
  *
102
- * HTTP Status: 500 Internal Server Error
103
- * Error Code: 9301
47
+ * HTTP Status: 403 Forbidden
104
48
  */
105
- var LocaleNotSupportedError = class extends ApplicationError {
106
- constructor(locale, supportedLocales) {
107
- super("errors.localeNotSupported", ERROR_CODES.I18N.LOCALE_NOT_SUPPORTED, {
108
- locale,
109
- supportedLocales: supportedLocales.join(", ")
110
- });
49
+ var InvalidSignatureError = class extends HttpException {
50
+ constructor() {
51
+ super(403, "Invalid or expired signature");
111
52
  }
112
53
  };
113
- //#endregion
114
- //#region src/i18n/errors/translation-missing.error.ts
115
54
  /**
116
- * Translation Missing Error
117
- * Thrown when a translation key is missing from all locales
55
+ * ResponseValidationError
118
56
  *
119
- * HTTP Status: 500 Internal Server Error
120
- * Error Code: 9300
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.
121
60
  */
122
- var TranslationMissingError = class extends ApplicationError {
123
- constructor(key, locale) {
124
- super("errors.translationMissing", ERROR_CODES.I18N.TRANSLATION_MISSING, {
125
- key,
126
- locale
127
- });
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
+ }));
128
70
  }
129
71
  };
130
72
  //#endregion
131
- //#region src/i18n/i18n.options.ts
132
- /**
133
- * Resolve I18n options with defaults
134
- */
135
- function resolveI18nOptions(options) {
136
- const detection = options?.detection;
137
- const enabled = detection ? detection.enabled !== false : true;
138
- const strategy = detection && "strategy" in detection ? detection.strategy ?? "cookie" : "cookie";
139
- const prefixDefaultLocale = detection && "prefixDefaultLocale" in detection && detection.prefixDefaultLocale !== void 0 ? detection.prefixDefaultLocale : false;
140
- return {
141
- defaultLocale: options?.defaultLocale ?? "en",
142
- fallbackLocale: options?.fallbackLocale ?? "en",
143
- locales: options?.locales ?? ["en"],
144
- detection: {
145
- enabled,
146
- strategy,
147
- prefixDefaultLocale
148
- }
149
- };
150
- }
151
- /**
152
- * Build Hono languageDetector options from I18n module options
153
- */
154
- function buildDetectorOptions(options) {
155
- const resolved = resolveI18nOptions(options);
156
- const strategy = resolved.detection.strategy;
157
- const detectorOptions = {
158
- order: [strategy],
159
- fallbackLanguage: resolved.defaultLocale,
160
- supportedLanguages: resolved.locales,
161
- lookupCookie: "locale",
162
- lookupQueryString: "locale",
163
- lookupFromPathIndex: 0,
164
- ignoreCase: true
165
- };
166
- if (strategy === "cookie") {
167
- detectorOptions.caches = ["cookie"];
168
- if (options?.detection && "cookieOptions" in options.detection && options.detection.cookieOptions) detectorOptions.cookieOptions = options.detection.cookieOptions;
169
- } else detectorOptions.caches = false;
170
- return detectorOptions;
171
- }
172
- //#endregion
173
- //#region src/i18n/messages/index.ts
174
- /**
175
- * Core Messages
176
- *
177
- * Messages used by packages/modules infrastructure.
178
- * These are automatically merged with application-specific messages.
179
- */
180
- /**
181
- * All locale messages
182
- * Explicitly import and export (no filesystem scanning - Cloudflare Workers compatible)
183
- */
184
- const messages = { en: en_exports };
185
- /**
186
- * Get messages for all locales
187
- */
188
- function getMessages() {
189
- return messages;
190
- }
191
- /**
192
- * Get available locales
193
- */
194
- function getLocales() {
195
- return Object.keys(messages);
196
- }
197
- //#endregion
198
- //#region src/i18n/utils/deep-merge.ts
199
- /**
200
- * Deep merge two objects. Source values override target at leaf level.
201
- */
202
- function deepMerge(target, source) {
203
- const result = { ...target };
204
- for (const key of Object.keys(source)) {
205
- const targetValue = target[key];
206
- const sourceValue = source[key];
207
- if (typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue) && typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue)) result[key] = deepMerge(targetValue, sourceValue);
208
- else result[key] = sourceValue;
209
- }
210
- return result;
211
- }
212
- //#endregion
213
- //#region src/i18n/services/message-loader.service.ts
214
- let MessageLoaderService = class MessageLoaderService {
215
- registry;
216
- options;
217
- cache;
218
- contextCache;
219
- locales;
220
- defaultLocale;
221
- constructor(registry, options) {
222
- this.registry = registry;
223
- this.options = options;
224
- this.defaultLocale = this.options?.defaultLocale ?? "en";
225
- this.cache = /* @__PURE__ */ new Map();
226
- this.contextCache = /* @__PURE__ */ new Map();
227
- const coreMessages = getMessages();
228
- const coreLocales = getLocales();
229
- const registryMessages = this.registry.getMergedMessages();
230
- const registryLocales = Object.keys(registryMessages);
231
- const allLocales = [...new Set([...coreLocales, ...registryLocales])];
232
- this.locales = allLocales;
233
- for (const locale of allLocales) {
234
- const merged = deepMerge(coreMessages[locale] ?? {}, registryMessages[locale] ?? {});
235
- this.cache.set(locale, merged);
236
- }
237
- }
238
- /**
239
- * Get CoreContext for a locale (lazily built and cached on first access)
240
- * Falls back to default locale if locale not found
241
- */
242
- getCoreContext(locale) {
243
- const cached = this.contextCache.get(locale);
244
- if (cached) return cached;
245
- const effectiveLocale = this.cache.has(locale) ? locale : this.defaultLocale;
246
- const cachedEffective = this.contextCache.get(effectiveLocale);
247
- if (cachedEffective) return cachedEffective;
248
- const messages = this.cache.get(effectiveLocale) ?? {};
249
- const flattened = this.flattenMessages(messages);
250
- const ctx = createCoreContext({
251
- locale: effectiveLocale,
252
- messages: { [effectiveLocale]: flattened },
253
- missingWarn: false,
254
- fallbackWarn: false
255
- });
256
- this.contextCache.set(effectiveLocale, ctx);
257
- return ctx;
258
- }
259
- /**
260
- * Get messages for a specific locale.
261
- * Falls back to default locale if not found.
262
- */
263
- getMessages(locale) {
264
- return this.cache.get(locale) ?? this.cache.get(this.defaultLocale) ?? {};
265
- }
266
- /** Get list of available locale codes */
267
- getAvailableLocales() {
268
- return this.locales;
269
- }
270
- /** Check if a locale is supported */
271
- isLocaleSupported(locale) {
272
- return this.cache.has(locale);
273
- }
274
- /** Get default locale */
275
- getDefaultLocale() {
276
- return this.defaultLocale;
277
- }
278
- /**
279
- * Get flattened (dot-notation) messages for a locale, optionally filtered by namespace prefixes.
280
- *
281
- * Returns flat key-value pairs matching the format used by `@intlify/core-base`'s
282
- * `createCoreContext`. Requires `registerMessageCompiler(compile)` to be called
283
- * before `translate()` can resolve these flat keys.
284
- *
285
- * @param locale - Locale code (falls back to default locale if not found)
286
- * @param options - Optional filter configuration
287
- * @param options.only - Dot-notation prefixes to include (e.g., `['common', 'nav.sidebar']`)
288
- * @returns Flattened messages as `{ 'key.path': 'translated value' }`
289
- *
290
- * @example
291
- * ```typescript
292
- * // All messages for the locale
293
- * loader.getFilteredMessages('en')
294
- *
295
- * // Only 'common' and 'nav' namespaces
296
- * loader.getFilteredMessages('en', { only: ['common', 'nav'] })
297
- *
298
- * // Deeply nested prefix
299
- * loader.getFilteredMessages('en', { only: ['common.actions'] })
300
- * ```
301
- */
302
- getFilteredMessages(locale, options) {
303
- const messages = this.getMessages(locale);
304
- const flattened = this.flattenMessages(messages);
305
- if (!options?.only?.length) return flattened;
306
- const result = {};
307
- for (const [key, value] of Object.entries(flattened)) if (options.only.some((prefix) => key === prefix || key.startsWith(`${prefix}.`))) result[key] = value;
308
- return result;
309
- }
310
- /**
311
- * Flatten nested messages to dot-notation.
312
- * e.g. `{ a: { b: 'hello' } }` → `{ 'a.b': 'hello' }`
313
- */
314
- flattenMessages(messages, prefix = "") {
315
- const result = {};
316
- for (const key of Object.keys(messages)) {
317
- const value = messages[key];
318
- const newKey = prefix ? `${prefix}.${key}` : key;
319
- if (typeof value === "object" && value !== null && !Array.isArray(value)) Object.assign(result, this.flattenMessages(value, newKey));
320
- else result[newKey] = String(value);
321
- }
322
- return result;
323
- }
324
- };
325
- MessageLoaderService = __decorate([
326
- Transient(I18N_TOKENS.MessageLoader),
327
- __decorateParam(0, inject(I18N_TOKENS.MessageRegistry)),
328
- __decorateParam(1, inject(I18N_TOKENS.Options, { isOptional: true })),
329
- __decorateMetadata("design:paramtypes", [Object, Object])
330
- ], MessageLoaderService);
331
- //#endregion
332
- //#region src/i18n/services/message-registry.ts
333
- /**
334
- * Global key for the shared contributions array.
335
- *
336
- * When stratal is installed via portal/symlink (e.g., in monorepos), bundlers
337
- * like esbuild may inline multiple copies of this module. Each copy gets its
338
- * own static class fields, so messages registered by one copy are invisible
339
- * to another. Using a `Symbol.for()` key on `globalThis` ensures all copies
340
- * share the same contributions array.
341
- */
342
- const CONTRIBUTIONS_KEY = Symbol.for("stratal:i18n:message-registry:contributions");
343
- function getContributions() {
344
- const g = globalThis;
345
- g[CONTRIBUTIONS_KEY] ??= [];
346
- return g[CONTRIBUTIONS_KEY];
347
- }
348
- let MessageRegistry = class MessageRegistry {
349
- /**
350
- * Add messages (called statically by I18nModule.registerMessages)
351
- */
352
- static addMessages(messages) {
353
- if (Boolean(messages) && typeof messages === "object" && Object.keys(messages).length > 0) getContributions().push(messages);
354
- }
355
- /**
356
- * Get all messages deep-merged in registration order
357
- */
358
- getMergedMessages() {
359
- const merged = {};
360
- for (const contribution of getContributions()) for (const locale of Object.keys(contribution)) merged[locale] = deepMerge(merged[locale] ?? {}, contribution[locale]);
361
- return merged;
362
- }
363
- /**
364
- * Reset registry (for testing)
365
- * @internal
366
- */
367
- static reset() {
368
- globalThis[CONTRIBUTIONS_KEY] = [];
369
- }
370
- };
371
- MessageRegistry = __decorate([Transient(I18N_TOKENS.MessageRegistry)], MessageRegistry);
372
- //#endregion
373
- //#region src/openapi/services/openapi.service.ts
374
- let OpenAPIService = class OpenAPIService {
375
- /**
376
- * Generate a filtered OpenAPI spec using the user's config.
377
- * Usable from both HTTP handlers and CLI commands.
378
- */
379
- getSpec(app, container) {
380
- const configService = container.resolve(OPENAPI_TOKENS.ConfigService);
381
- const i18n = container.resolve(I18N_TOKENS.I18nService);
382
- const config = configService.getEffectiveConfig();
383
- const fullSpec = app.getOpenAPIDocument({
384
- openapi: "3.0.0",
385
- info: {
386
- version: config.info.version,
387
- title: config.info.title,
388
- description: config.info.description
389
- }
390
- });
391
- fullSpec.components ??= {};
392
- fullSpec.components.securitySchemes = this.getSecuritySchemeDefinitions(i18n);
393
- if (config.routeFilter) fullSpec.paths = this.filterRoutes(fullSpec.paths, config);
394
- if (fullSpec.components.schemas) fullSpec.components.schemas = this.filterSchemas(fullSpec);
395
- return fullSpec;
396
- }
397
- /**
398
- * Setup OpenAPI documentation endpoints
399
- */
400
- setupEndpoints(app, container) {
401
- const config = container.resolve(OPENAPI_TOKENS.ConfigService).getEffectiveConfig();
402
- app.get(config.jsonPath, (c) => {
403
- const requestContainer = c.get(ROUTER_CONTEXT_KEYS.REQUEST_CONTAINER);
404
- const fullSpec = this.getSpec(app, requestContainer);
405
- const url = new URL(c.req.raw.url);
406
- const i18n = requestContainer.resolve(I18N_TOKENS.I18nService);
407
- fullSpec.servers = [{
408
- url: `${url.protocol}//${url.host}`,
409
- description: i18n.t("common.api.serverDescription")
410
- }];
411
- return c.json(fullSpec);
412
- });
413
- this.nameLastHandler(app, "OpenAPI", "spec");
414
- if (config.ui !== false) {
415
- const uiPath = config.ui?.path ?? "/api/docs";
416
- const uiRenderer = config.ui?.renderer;
417
- app.get(uiPath, (c, next) => {
418
- const effectiveConfig = c.get(ROUTER_CONTEXT_KEYS.REQUEST_CONTAINER).resolve(OPENAPI_TOKENS.ConfigService).getEffectiveConfig();
419
- const uiContext = {
420
- specUrl: effectiveConfig.jsonPath,
421
- title: effectiveConfig.info.title
422
- };
423
- if (uiRenderer) return uiRenderer(uiContext)(c, next);
424
- return swaggerUI({ url: uiContext.specUrl })(c, next);
425
- });
426
- this.nameLastHandler(app, "OpenAPI", "docs");
427
- }
428
- }
429
- nameLastHandler(app, controller, method) {
430
- const last = app.routes[app.routes.length - 1];
431
- Object.defineProperty(last.handler, "name", { value: `http:${controller}.${method}` });
432
- }
433
- /**
434
- * Get localized security scheme definitions
435
- */
436
- getSecuritySchemeDefinitions(i18n) {
437
- return {
438
- [SECURITY_SCHEMES.BEARER_AUTH]: {
439
- type: "http",
440
- scheme: "bearer",
441
- bearerFormat: "JWT",
442
- description: i18n.t("common.api.security.bearerAuth")
443
- },
444
- [SECURITY_SCHEMES.API_KEY]: {
445
- type: "apiKey",
446
- in: "header",
447
- name: "X-API-Key",
448
- description: i18n.t("common.api.security.apiKey")
449
- },
450
- [SECURITY_SCHEMES.SESSION_COOKIE]: {
451
- type: "apiKey",
452
- in: "cookie",
453
- name: "session",
454
- description: i18n.t("common.api.security.sessionCookie")
455
- }
456
- };
457
- }
458
- /**
459
- * Filter OpenAPI paths using custom routeFilter
460
- */
461
- filterRoutes(paths, config) {
462
- const filteredPaths = {};
463
- for (const [path, pathItem] of Object.entries(paths)) {
464
- if (config.routeFilter && !config.routeFilter(path, pathItem)) continue;
465
- filteredPaths[path] = pathItem;
466
- }
467
- return filteredPaths;
468
- }
469
- /**
470
- * Filter unreferenced schemas from OpenAPI spec
471
- */
472
- filterSchemas(spec) {
473
- const referencedSchemas = /* @__PURE__ */ new Set();
474
- this.collectSchemaRefs(spec.paths, referencedSchemas);
475
- const filteredSchemas = {};
476
- const components = spec.components;
477
- if (components?.schemas) {
478
- const allSchemas = components.schemas;
479
- let prevSize = 0;
480
- while (referencedSchemas.size > prevSize) {
481
- prevSize = referencedSchemas.size;
482
- for (const [schemaName, schemaValue] of Object.entries(allSchemas)) if (referencedSchemas.has(schemaName) && !filteredSchemas[schemaName]) {
483
- filteredSchemas[schemaName] = schemaValue;
484
- this.collectSchemaRefs(schemaValue, referencedSchemas);
485
- }
486
- }
487
- }
488
- return filteredSchemas;
489
- }
490
- /**
491
- * Recursively collect all schema references from an object
492
- */
493
- collectSchemaRefs(obj, refs) {
494
- if (!obj || typeof obj !== "object") return;
495
- const record = obj;
496
- if (record.$ref && typeof record.$ref === "string") {
497
- const match = /^#\/components\/schemas\/(.+)$/.exec(record.$ref);
498
- if (match) refs.add(match[1]);
499
- }
500
- if (Array.isArray(obj)) for (const item of obj) this.collectSchemaRefs(item, refs);
501
- else for (const value of Object.values(record)) this.collectSchemaRefs(value, refs);
502
- }
503
- };
504
- OpenAPIService = __decorate([Transient(OPENAPI_TOKENS.OpenAPIService)], OpenAPIService);
505
- //#endregion
506
- //#region src/openapi/openapi.module.ts
507
- /**
508
- * OpenAPI Module
509
- *
510
- * Provides configurable OpenAPI documentation endpoints with runtime override support.
511
- *
512
- * Features:
513
- * - Configurable paths for /openapi.json and /docs
514
- * - Runtime config overrides via middleware
515
- * - i18n support for titles and descriptions
516
- * - Route filtering via hideFromDocs and custom routeFilter
517
- *
518
- * @example Basic usage
519
- * ```typescript
520
- * @Module({
521
- * imports: [
522
- * OpenAPIModule.forRoot({
523
- * info: { title: 'My API', version: '1.0.0' }
524
- * })
525
- * ]
526
- * })
527
- * export class AppModule {}
528
- * ```
529
- *
530
- * @example With runtime override in middleware
531
- * ```typescript
532
- * // In RouteAccessMiddleware
533
- * constructor(
534
- * @inject(OPENAPI_TOKENS.ConfigService) private openAPIConfig: IOpenAPIConfigService
535
- * ) {}
536
- *
537
- * async handle(ctx, next) {
538
- * this.openAPIConfig.override({
539
- * info: { title: 'Custom API' },
540
- * routeFilter: (path) => this.shouldInclude(path)
541
- * })
542
- * await next()
543
- * }
544
- * ```
545
- */
546
- var _OpenAPIModule;
547
- /** Default options when none provided */
548
- const DEFAULT_OPTIONS = {
549
- jsonPath: "/api/openapi.json",
550
- info: {
551
- title: "API",
552
- version: "1.0.0"
553
- }
554
- };
555
- let OpenAPIModule = _OpenAPIModule = class OpenAPIModule {
556
- /**
557
- * Configure OpenAPI module with static options
558
- *
559
- * @param options - OpenAPI configuration (paths, info, security schemes)
560
- * @returns DynamicModule with options provider
561
- */
562
- static forRoot(options = {}) {
563
- const mergedOptions = {
564
- ...DEFAULT_OPTIONS,
565
- ...options,
566
- info: {
567
- ...DEFAULT_OPTIONS.info,
568
- ...options.info,
569
- title: options.info?.title ?? DEFAULT_OPTIONS.info?.title ?? "API",
570
- version: options.info?.version ?? DEFAULT_OPTIONS.info?.version ?? "1.0.0"
571
- }
572
- };
573
- return {
574
- module: _OpenAPIModule,
575
- providers: [{
576
- provide: OPENAPI_TOKENS.Options,
577
- useValue: mergedOptions
578
- }]
579
- };
580
- }
581
- static forRootAsync(options) {
582
- return {
583
- module: _OpenAPIModule,
584
- providers: [{
585
- provide: OPENAPI_TOKENS.Options,
586
- useFactory: options.useFactory,
587
- inject: options.inject
588
- }]
589
- };
590
- }
591
- };
592
- OpenAPIModule = _OpenAPIModule = __decorate([Module({ providers: [{
593
- provide: OPENAPI_TOKENS.ConfigService,
594
- useClass: OpenAPIConfigService,
595
- scope: Scope.Request
596
- }, {
597
- provide: OPENAPI_TOKENS.OpenAPIService,
598
- useClass: OpenAPIService,
599
- scope: Scope.Singleton
600
- }] })], OpenAPIModule);
601
- //#endregion
602
73
  //#region src/router/middleware/logger.middleware.ts
603
74
  /**
604
75
  * Create a Hono middleware that logs HTTP requests using our Logger service
@@ -670,7 +141,7 @@ function stripPort(host) {
670
141
  * When the host matches, domain parameters are extracted and stored in context
671
142
  * variables accessible via `ctx.domain(key)`.
672
143
  *
673
- * When the host does NOT match, throws `DomainMismatchError` (404).
144
+ * When the host does NOT match, aborts with 404.
674
145
  *
675
146
  * @param pattern - Domain pattern with `{param}` placeholders (e.g., '{tenant}.myapp.com')
676
147
  *
@@ -690,7 +161,7 @@ function createDomainMiddleware(pattern) {
690
161
  return async (c, next) => {
691
162
  const host = stripPort(c.req.header("host") ?? "");
692
163
  const match = regex.exec(host);
693
- if (!match) throw new DomainMismatchError();
164
+ if (!match) abort(404, "Domain mismatch");
694
165
  for (let i = 0; i < paramNames.length; i++) c.set(`domain:${paramNames[i]}`, match[i + 1]);
695
166
  await next();
696
167
  };
@@ -718,12 +189,7 @@ function createMiddlewareChain(classes) {
718
189
  const middleware = requestContainer.resolve(middlewareClass);
719
190
  let called = false;
720
191
  const guardedNext = () => {
721
- if (called) {
722
- const err = new MiddlewareNextCalledMultipleTimesError(middlewareClass.name ?? "anonymous");
723
- console.error("[STRATAL DEBUG] next() called multiple times for " + middlewareClass.name);
724
- console.error("[STRATAL DEBUG] Stack trace:", (/* @__PURE__ */ new Error()).stack);
725
- return Promise.reject(err);
726
- }
192
+ if (called) return Promise.reject(new RouterError(`Middleware "${middlewareClass.name ?? "anonymous"}" called next() multiple times`));
727
193
  called = true;
728
194
  return prevNext();
729
195
  };
@@ -875,10 +341,10 @@ function Route(config) {
875
341
  type: "convention",
876
342
  config
877
343
  };
878
- Reflect.defineMetadata(ROUTE_METADATA_KEYS.ROUTE_CONFIG, metadata, target, propertyKey);
879
- 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) ?? [];
880
346
  existing.push(propertyKey);
881
- Reflect.defineMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, existing, target);
347
+ defineMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, existing, target);
882
348
  return descriptor;
883
349
  };
884
350
  }
@@ -890,7 +356,7 @@ function Route(config) {
890
356
  * @returns Route metadata or undefined if not decorated
891
357
  */
892
358
  function getRouteMetadata(target, methodName) {
893
- return Reflect.getMetadata(ROUTE_METADATA_KEYS.ROUTE_CONFIG, target, methodName);
359
+ return getMetadata(ROUTE_METADATA_KEYS.ROUTE_CONFIG, target, methodName);
894
360
  }
895
361
  /**
896
362
  * Get all methods with route decorators (@Route, @Get, @Post, etc.) from a controller
@@ -902,7 +368,7 @@ function getRouteDecoratedMethods(ControllerClass) {
902
368
  const methods = /* @__PURE__ */ new Set();
903
369
  let proto = ControllerClass.prototype;
904
370
  while (proto && proto !== Object.prototype) {
905
- const own = Reflect.getOwnMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, proto);
371
+ const own = getMetadata(ROUTE_METADATA_KEYS.DECORATED_METHODS, proto);
906
372
  if (own) for (const m of own) methods.add(m);
907
373
  proto = Object.getPrototypeOf(proto);
908
374
  }
@@ -921,31 +387,19 @@ function getRouteDecoratedMethods(ControllerClass) {
921
387
  /**
922
388
  * Generic error response schema
923
389
  * Used for all error responses (4xx, 5xx)
924
- * Matches ApplicationError.toErrorResponse() structure
390
+ * Matches the ErrorResponse shape produced by ExceptionHandler
925
391
  */
926
392
  const errorResponseSchema = z.object({
927
- code: z.number().int().describe("Application error code"),
928
393
  message: z.string().describe("Human-readable error message"),
929
394
  timestamp: z.string().datetime().describe("ISO timestamp when error occurred"),
930
- metadata: z.record(z.string(), z.unknown()).optional().describe("Additional error context"),
931
395
  stack: z.string().optional().describe("Stack trace (development only)")
932
396
  }).openapi("ErrorResponse");
933
397
  /**
934
398
  * Validation error response schema
935
399
  * Used for 400 Bad Request with validation failures
936
- * Matches ApplicationError.toErrorResponse() structure with validation-specific metadata
400
+ * Matches the ErrorResponse shape produced by ExceptionHandler
937
401
  */
938
- const validationErrorResponseSchema = z.object({
939
- code: z.number().int().describe("Application error code"),
940
- message: z.string().describe("Human-readable error message"),
941
- timestamp: z.string().datetime().describe("ISO timestamp when error occurred"),
942
- metadata: z.object({ issues: z.array(z.object({
943
- path: z.string().describe("Field path that failed validation"),
944
- message: z.string().describe("Validation failure message"),
945
- code: z.string().describe("Zod validation error code")
946
- })) }).describe("Validation error details"),
947
- stack: z.string().optional().describe("Stack trace (development only)")
948
- }).openapi("ValidationErrorResponse");
402
+ const validationErrorResponseSchema = errorResponseSchema.openapi("ValidationErrorResponse");
949
403
  /**
950
404
  * Pagination query parameters schema
951
405
  * Used for list endpoints
@@ -1229,7 +683,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1229
683
  collectRoutes(ControllerClass, actions) {
1230
684
  const isWsGateway = isGateway(ControllerClass);
1231
685
  const controllerRoute = getControllerRoute(ControllerClass);
1232
- 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"}`);
1233
687
  const controllerOpts = getControllerOptions(ControllerClass);
1234
688
  const controllerGuards = getControllerGuards(ControllerClass)?.guards ?? [];
1235
689
  const routerConfig = this.routerResolver?.resolveForController(ControllerClass) ?? { middleware: [] };
@@ -1282,7 +736,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1282
736
  return;
1283
737
  }
1284
738
  const decoratedMethods = getRouteDecoratedMethods(ControllerClass);
1285
- 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.`);
1286
740
  const methodMetadata = [];
1287
741
  let hasConvention = false;
1288
742
  let hasExplicit = false;
@@ -1296,7 +750,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1296
750
  if (meta.type === "convention") hasConvention = true;
1297
751
  else if (meta.type === "explicit") hasExplicit = true;
1298
752
  }
1299
- 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.`);
1300
754
  const routerHidden = routerConfig.hideFromDocs;
1301
755
  const controllerHidden = controllerOpts?.hideFromDocs ?? false;
1302
756
  const routerName = routerConfig.name;
@@ -1403,16 +857,16 @@ let RouteRegistrationService = class RouteRegistrationService {
1403
857
  const bindWsHandler = (method, onCatch) => {
1404
858
  return (evt, ws) => {
1405
859
  invokeHandler(gateway, method, evt, new GatewayContext(c, ws)).catch((err) => {
1406
- this.logger.error(`WebSocket ${method} handler error`, {
1407
- gateway: GatewayClass.name,
1408
- error: err instanceof Error ? err.message : String(err)
1409
- });
860
+ this.logger.error(`WebSocket ${method} handler error`, err, { gateway: GatewayClass.name });
1410
861
  onCatch?.(err, ws);
1411
862
  });
1412
863
  };
1413
864
  };
1414
865
  if (onMsgMethod) events.onMessage = bindWsHandler(onMsgMethod, (_err, ws) => ws.close(1011, "Internal Error"));
1415
866
  if (onCloseMethod) events.onClose = bindWsHandler(onCloseMethod);
867
+ else events.onClose = (_evt, ws) => {
868
+ ws.close();
869
+ };
1416
870
  if (onErrMethod) events.onError = bindWsHandler(onErrMethod);
1417
871
  return events;
1418
872
  });
@@ -1495,7 +949,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1495
949
  resolveMethodAndPath(meta, methodName, basePath, className) {
1496
950
  if (meta.type === "convention") {
1497
951
  const derived = this.deriveHttpMethodAndPath(methodName, basePath);
1498
- 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).`);
1499
953
  return {
1500
954
  httpMethod: derived.method,
1501
955
  fullPath: derived.path,
@@ -1615,9 +1069,9 @@ let RouteRegistrationService = class RouteRegistrationService {
1615
1069
  if (metadata.security.length > 0) route.security = metadata.security;
1616
1070
  if (routeConfig.description) route.description = routeConfig.description;
1617
1071
  if (routeConfig.summary) route.summary = routeConfig.summary;
1618
- return (0, validation_exports.createRoute)(route);
1072
+ return (0, zod_exports.createRoute)(route);
1619
1073
  } catch (error) {
1620
- 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)}`);
1621
1075
  }
1622
1076
  }
1623
1077
  /**
@@ -1662,7 +1116,7 @@ let RouteRegistrationService = class RouteRegistrationService {
1662
1116
  if (responseSchema && c.env.ENVIRONMENT !== "production") return this.validateResponse(response, responseSchema);
1663
1117
  return response;
1664
1118
  }
1665
- throw new ControllerMethodNotFoundError(methodName, ControllerClass.name);
1119
+ throw new RouterError(`Method "${methodName}" not found on controller "${ControllerClass.name}"`);
1666
1120
  };
1667
1121
  this.nameHandler(handler, ControllerClass.name, methodName);
1668
1122
  return handler;
@@ -1712,21 +1166,13 @@ let RouteRegistrationService = class RouteRegistrationService {
1712
1166
  }
1713
1167
  };
1714
1168
  RouteRegistrationService = __decorate([
1715
- Transient(),
1169
+ Singleton(),
1716
1170
  __decorateParam(0, inject(LOGGER_TOKENS.LoggerService)),
1717
1171
  __decorateParam(1, inject(ROUTER_TOKENS.RouteRegistry)),
1718
- __decorateParam(2, inject(ROUTER_TOKENS.RouterResolver)),
1172
+ __decorateParam(2, inject(ROUTER_TOKENS.RouterResolver, { isOptional: true })),
1719
1173
  __decorateParam(3, inject(ROUTER_TOKENS.LocalePathService)),
1720
1174
  __decorateParam(4, inject(ROUTER_TOKENS.HonoApp)),
1721
- __decorateParam(5, inject(DI_TOKENS.ModuleRegistry)),
1722
- __decorateMetadata("design:paramtypes", [
1723
- Object,
1724
- Object,
1725
- Object,
1726
- Object,
1727
- Object,
1728
- Object
1729
- ])
1175
+ __decorateParam(5, inject(DI_TOKENS.ModuleRegistry))
1730
1176
  ], RouteRegistrationService);
1731
1177
  //#endregion
1732
1178
  //#region src/router/hono-app.ts
@@ -1783,7 +1229,7 @@ let HonoApp = class HonoApp extends OpenAPIHono {
1783
1229
  * Called once by Application.initialize().
1784
1230
  */
1785
1231
  async configure() {
1786
- if (this.configured) throw new HonoAppAlreadyConfiguredError();
1232
+ if (this.configured) throw new RouterError("HonoApp has already been configured");
1787
1233
  this._container.resolve(OPENAPI_TOKENS.OpenAPIService).setupEndpoints(this, this._container);
1788
1234
  await this._container.resolve(RouteRegistrationService).configure();
1789
1235
  this.notFound((c) => {
@@ -1806,17 +1252,54 @@ let HonoApp = class HonoApp extends OpenAPIHono {
1806
1252
  }
1807
1253
  };
1808
1254
  HonoApp = __decorate([
1809
- Transient(),
1255
+ Singleton(),
1810
1256
  __decorateParam(0, inject(CONTAINER_TOKEN)),
1811
1257
  __decorateParam(1, inject(LOGGER_TOKENS.LoggerService)),
1812
- __decorateParam(2, inject(DI_TOKENS.Application)),
1813
- __decorateMetadata("design:paramtypes", [
1814
- Object,
1815
- Object,
1816
- Object
1817
- ])
1258
+ __decorateParam(2, inject(DI_TOKENS.Application))
1818
1259
  ], HonoApp);
1819
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
1820
1303
  //#region src/router/services/locale-path.service.ts
1821
1304
  let LocalePathService = class LocalePathService {
1822
1305
  honoApp;
@@ -1925,10 +1408,9 @@ let LocalePathService = class LocalePathService {
1925
1408
  }
1926
1409
  };
1927
1410
  LocalePathService = __decorate([
1928
- Transient(),
1411
+ Singleton(),
1929
1412
  __decorateParam(0, inject(CONTAINER_TOKEN)),
1930
- __decorateParam(1, inject(ROUTER_TOKENS.HonoApp)),
1931
- __decorateMetadata("design:paramtypes", [Object, Object])
1413
+ __decorateParam(1, inject(ROUTER_TOKENS.HonoApp))
1932
1414
  ], LocalePathService);
1933
1415
  //#endregion
1934
1416
  //#region src/router/services/versioning.service.ts
@@ -1957,11 +1439,7 @@ let VersioningService = class VersioningService {
1957
1439
  return [basePath];
1958
1440
  }
1959
1441
  };
1960
- VersioningService = __decorate([
1961
- Transient(),
1962
- __decorateParam(0, inject(DI_TOKENS.Application)),
1963
- __decorateMetadata("design:paramtypes", [Object])
1964
- ], VersioningService);
1442
+ VersioningService = __decorate([Singleton(), __decorateParam(0, inject(DI_TOKENS.Application))], VersioningService);
1965
1443
  //#endregion
1966
1444
  //#region src/router/route-registry.ts
1967
1445
  const CONCRETE_HTTP_METHODS = [
@@ -1990,7 +1468,7 @@ let RouteRegistry = class RouteRegistry {
1990
1468
  * Named routes must have unique names.
1991
1469
  *
1992
1470
  * @returns Array of expanded RegisteredRoute entries (primary + locale variants)
1993
- * @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
1994
1472
  */
1995
1473
  register(input) {
1996
1474
  const domainParamNames = input.domainParamNames ?? (input.domain ? extractDomainParamNames(input.domain) : []);
@@ -2022,7 +1500,7 @@ let RouteRegistry = class RouteRegistry {
2022
1500
  if (route.name) {
2023
1501
  if (this.namedRoutes.has(route.name)) {
2024
1502
  const existing = this.namedRoutes.get(route.name);
2025
- 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}`);
2026
1504
  }
2027
1505
  this.namedRoutes.set(route.name, route);
2028
1506
  }
@@ -2072,12 +1550,41 @@ let RouteRegistry = class RouteRegistry {
2072
1550
  }
2073
1551
  };
2074
1552
  RouteRegistry = __decorate([
2075
- Transient(),
1553
+ Singleton(),
2076
1554
  __decorateParam(0, inject(ROUTER_TOKENS.VersioningService)),
2077
- __decorateParam(1, inject(ROUTER_TOKENS.LocalePathService)),
2078
- __decorateMetadata("design:paramtypes", [Object, Object])
1555
+ __decorateParam(1, inject(ROUTER_TOKENS.LocalePathService))
2079
1556
  ], RouteRegistry);
2080
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
2081
1588
  //#region src/router/uri.ts
2082
1589
  /**
2083
1590
  * Encode a value for use as a path parameter.
@@ -2100,7 +1607,7 @@ function encodePathParam(value) {
2100
1607
  * @param params - Path params, domain params, and extra query params
2101
1608
  * @returns Relative URL string (or absolute with domain prefix if route has a domain pattern)
2102
1609
  *
2103
- * @throws MissingRouteParamError if a required path or domain param is missing
1610
+ * @throws RouterError if a required path or domain param is missing
2104
1611
  */
2105
1612
  function buildRouteUrl(route, name, params) {
2106
1613
  const allParams = { ...params };
@@ -2112,7 +1619,7 @@ function buildRouteUrl(route, name, params) {
2112
1619
  }
2113
1620
  for (const paramName of route.paramNames) {
2114
1621
  const value = allParams[paramName];
2115
- 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})`);
2116
1623
  url = url.replace(new RegExp(`:${paramName}(\\{[^}]*\\})?`), encodePathParam(value));
2117
1624
  consumedKeys.add(paramName);
2118
1625
  }
@@ -2121,7 +1628,7 @@ function buildRouteUrl(route, name, params) {
2121
1628
  domain = route.domain;
2122
1629
  for (const domainParam of route.domainParamNames) {
2123
1630
  const value = allParams[domainParam];
2124
- 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})`);
2125
1632
  domain = domain.replace(`{${domainParam}}`, encodeURIComponent(value));
2126
1633
  consumedKeys.add(domainParam);
2127
1634
  }
@@ -2179,12 +1686,11 @@ let Uri = class Uri {
2179
1686
  * @param options - URL generation options
2180
1687
  * @returns Generated URL string
2181
1688
  *
2182
- * @throws RouteNameNotFoundError if route name not found
2183
- * @throws MissingRouteParamError if required params missing
1689
+ * @throws RouterError if route name not found or required params missing
2184
1690
  */
2185
1691
  route(name, params, options) {
2186
1692
  const registeredRoute = this.registry.get(name);
2187
- if (!registeredRoute) throw new RouteNameNotFoundError(name);
1693
+ if (!registeredRoute) throw new RouterError(`Route name "${name}" was not found in the registry`);
2188
1694
  let url = applyTrailingSlash(buildRouteUrl(registeredRoute, name, {
2189
1695
  ...this._defaults,
2190
1696
  ...params
@@ -2304,52 +1810,12 @@ let Uri = class Uri {
2304
1810
  }
2305
1811
  };
2306
1812
  Uri = __decorate([
2307
- Transient(),
1813
+ Request(),
2308
1814
  __decorateParam(0, inject(ROUTER_TOKENS.RouteRegistry)),
2309
1815
  __decorateParam(1, inject(ROUTER_TOKENS.RouterContext)),
2310
- __decorateParam(2, inject(DI_TOKENS.Application)),
2311
- __decorateMetadata("design:paramtypes", [
2312
- Object,
2313
- Object,
2314
- Object
2315
- ])
1816
+ __decorateParam(2, inject(DI_TOKENS.Application))
2316
1817
  ], Uri);
2317
1818
  //#endregion
2318
- //#region src/router/route-url.ts
2319
- /**
2320
- * Generate a URL from a named route.
2321
- *
2322
- * Keys in `params` matching `:param` placeholders fill the path.
2323
- * Domain params (`{tenant}`) are also consumed from `params`.
2324
- * Extra keys become query string parameters.
2325
- *
2326
- * Resolves RouteRegistry from the application container via AsyncLocalStorage.
2327
- * Available after `Application.initialize()` has been called.
2328
- *
2329
- * @param name - Named route identifier
2330
- * @param params - Route params + domain params + extra query params
2331
- * @returns Generated URL string
2332
- *
2333
- * @example
2334
- * ```typescript
2335
- * // In a controller (preferred):
2336
- * ctx.route('users.show', { id: '1' })
2337
- *
2338
- * // Outside controllers (standalone function):
2339
- * import { route } from 'stratal/router'
2340
- *
2341
- * route('users.show', { id: '1' })
2342
- * ```
2343
- */
2344
- function route(name, params) {
2345
- const container = getContainer();
2346
- const registry = container.resolve(ROUTER_TOKENS.RouteRegistry);
2347
- const application = container.resolve(DI_TOKENS.Application);
2348
- const registeredRoute = registry.get(name);
2349
- if (!registeredRoute) throw new RouteNameNotFoundError(name);
2350
- return applyTrailingSlash(buildRouteUrl(registeredRoute, name, params), application.config.trailingSlash ?? "ignore");
2351
- }
2352
- //#endregion
2353
1819
  //#region src/router/middleware/verify-signature.middleware.ts
2354
1820
  /**
2355
1821
  * Middleware that verifies signed URLs.
@@ -2375,158 +1841,12 @@ var VerifySignatureMiddleware = class {
2375
1841
  async handle(ctx, next) {
2376
1842
  const url = ctx.c.req.url;
2377
1843
  const secret = ctx.c.env.APP_SECRET;
2378
- if (!secret) throw new MissingEnvironmentVariableError("APP_SECRET");
1844
+ if (!secret) throw new RouterError("Missing required environment variable \"APP_SECRET\"");
2379
1845
  if (!await verifySignedUrl(url, secret)) throw new InvalidSignatureError();
2380
1846
  await next();
2381
1847
  }
2382
1848
  };
2383
1849
  //#endregion
2384
- //#region src/i18n/services/i18n.service.ts
2385
- /**
2386
- * I18n Service
2387
- *
2388
- * Request-scoped service for translations.
2389
- * Injects RouterContext to access request-specific locale.
2390
- * Uses pre-built CoreContext from MessageLoaderService (singleton) for zero-cost lookups.
2391
- */
2392
- let I18nService = class I18nService {
2393
- loader;
2394
- routerContext;
2395
- constructor(loader, routerContext) {
2396
- this.loader = loader;
2397
- this.routerContext = routerContext;
2398
- }
2399
- /**
2400
- * Translate a message key
2401
- *
2402
- * @param key - Message key (e.g., 'common.actions.save')
2403
- * @param params - Optional parameters for interpolation
2404
- * @returns Translated string
2405
- */
2406
- t(key, params) {
2407
- const context = this.loader.getCoreContext(this.getLocale());
2408
- const result = params !== void 0 ? translate(context, key, params) : translate(context, key);
2409
- return typeof result === "string" ? result : key;
2410
- }
2411
- /**
2412
- * Get current locale
2413
- *
2414
- * @returns Current locale code from RouterContext or default locale
2415
- */
2416
- getLocale() {
2417
- return this.routerContext?.getLocale() ?? "en";
2418
- }
2419
- };
2420
- I18nService = __decorate([
2421
- Transient(I18N_TOKENS.I18nService),
2422
- __decorateParam(0, inject(I18N_TOKENS.MessageLoader)),
2423
- __decorateParam(1, inject(ROUTER_TOKENS.RouterContext, { isOptional: true })),
2424
- __decorateMetadata("design:paramtypes", [Object, Object])
2425
- ], I18nService);
2426
- //#endregion
2427
- //#region src/i18n/i18n.module.ts
2428
- /**
2429
- * I18n Module
2430
- *
2431
- * Core infrastructure module for internationalization.
2432
- * Provides message translation and locale handling.
2433
- *
2434
- * - `forRoot()` configures locale settings (call once in root module)
2435
- * - `registerMessages()` adds translations (call from any module, as many times as needed)
2436
- *
2437
- * @example
2438
- * ```typescript
2439
- * @Module({
2440
- * imports: [
2441
- * I18nModule.forRoot({ defaultLocale: 'en', locales: ['en', 'fr'] }),
2442
- * I18nModule.registerMessages(appMessages),
2443
- * ],
2444
- * })
2445
- * export class AppModule {}
2446
- * ```
2447
- *
2448
- * @example Package contributing messages
2449
- * ```typescript
2450
- * @Module({
2451
- * imports: [
2452
- * I18nModule.registerMessages(tenancyMessages),
2453
- * ],
2454
- * })
2455
- * export class TenancyModule {}
2456
- * ```
2457
- */
2458
- var _I18nModule;
2459
- setupI18nCompiler();
2460
- z.config({ customError: backendErrorMap });
2461
- let I18nModule = _I18nModule = class I18nModule {
2462
- /**
2463
- * Configure I18n locale settings
2464
- *
2465
- * Call once in the root module. Does not accept messages —
2466
- * use `registerMessages()` to add translations.
2467
- *
2468
- * @param options - Locale configuration (defaultLocale, fallbackLocale, locales)
2469
- */
2470
- static forRoot(options = {}) {
2471
- return {
2472
- module: _I18nModule,
2473
- providers: [{
2474
- provide: I18N_TOKENS.Options,
2475
- useValue: options
2476
- }]
2477
- };
2478
- }
2479
- /**
2480
- * Register i18n messages
2481
- *
2482
- * Can be called from any module, as many times as needed.
2483
- * Messages are deep-merged in registration order — later calls override earlier ones at leaf level.
2484
- *
2485
- * @param messages - Messages keyed by locale code
2486
- *
2487
- * @example App-level messages
2488
- * ```typescript
2489
- * I18nModule.registerMessages({
2490
- * en: { common: { hello: 'Hello' }, errors: { notFound: 'Not found' } },
2491
- * fr: { common: { hello: 'Bonjour' }, errors: { notFound: 'Introuvable' } },
2492
- * })
2493
- * ```
2494
- *
2495
- * @example Package-level messages
2496
- * ```typescript
2497
- * I18nModule.registerMessages({
2498
- * en: { tenancy: { tenantNotFound: 'Tenant not found' } },
2499
- * })
2500
- * ```
2501
- */
2502
- static registerMessages(messages) {
2503
- MessageRegistry.addMessages(messages);
2504
- return {
2505
- module: _I18nModule,
2506
- providers: []
2507
- };
2508
- }
2509
- configureRoutes(router) {
2510
- router.use(I18nContextMiddleware);
2511
- }
2512
- };
2513
- I18nModule = _I18nModule = __decorate([Module({ providers: [
2514
- {
2515
- provide: I18N_TOKENS.MessageRegistry,
2516
- useClass: MessageRegistry,
2517
- scope: Scope.Singleton
2518
- },
2519
- {
2520
- provide: I18N_TOKENS.MessageLoader,
2521
- useClass: MessageLoaderService,
2522
- scope: Scope.Singleton
2523
- },
2524
- {
2525
- provide: I18N_TOKENS.I18nService,
2526
- useClass: I18nService
2527
- }
2528
- ] })], I18nModule);
2529
- //#endregion
2530
- 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 };
2531
1851
 
2532
- //# sourceMappingURL=i18n.module-CzXLW9Hy.mjs.map
1852
+ //# sourceMappingURL=router-Cy6DjkvP.mjs.map