stratal 0.0.21 → 0.0.23

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 (296) hide show
  1. package/README.md +2 -2
  2. package/dist/bin/cloudflare-workers-loader.mjs +80 -7
  3. package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
  4. package/dist/bin/quarry.mjs +84 -160
  5. package/dist/bin/quarry.mjs.map +1 -1
  6. package/dist/cache/index.d.mts +8 -46
  7. package/dist/cache/index.d.mts.map +1 -1
  8. package/dist/cache/index.mjs +134 -97
  9. package/dist/cache/index.mjs.map +1 -1
  10. package/dist/{cache.service-DsnKuNyO.d.mts → cache.service-uElmBtdS.d.mts} +29 -39
  11. package/dist/cache.service-uElmBtdS.d.mts.map +1 -0
  12. package/dist/{command-BgSlsS4M.mjs → command-BvmUAPPQ.mjs} +15 -4
  13. package/dist/command-BvmUAPPQ.mjs.map +1 -0
  14. package/dist/{command-Cmmf0oHX.d.mts → command-CPhFHjG3.d.mts} +3 -2
  15. package/dist/command-CPhFHjG3.d.mts.map +1 -0
  16. package/dist/command-not-found.error-ONAZ2Bpk.mjs +14 -0
  17. package/dist/command-not-found.error-ONAZ2Bpk.mjs.map +1 -0
  18. package/dist/config/index.d.mts +24 -11
  19. package/dist/config/index.d.mts.map +1 -1
  20. package/dist/config/index.mjs +32 -57
  21. package/dist/config/index.mjs.map +1 -1
  22. package/dist/{consumer-registry-B7yUNh0q.d.mts → consumer-registry-D3iMTSdy.d.mts} +54 -22
  23. package/dist/consumer-registry-D3iMTSdy.d.mts.map +1 -0
  24. package/dist/container-storage-BmOJ4_Na.mjs +52 -0
  25. package/dist/container-storage-BmOJ4_Na.mjs.map +1 -0
  26. package/dist/{controller.decorator-B9vwn0zK.mjs → controller.decorator-C5UVeJS3.mjs} +8 -8
  27. package/dist/controller.decorator-C5UVeJS3.mjs.map +1 -0
  28. package/dist/cron/index.d.mts +103 -7
  29. package/dist/cron/index.d.mts.map +1 -1
  30. package/dist/cron/index.mjs +2 -2
  31. package/dist/cron-job-NesZRk8F.d.mts +58 -0
  32. package/dist/cron-job-NesZRk8F.d.mts.map +1 -0
  33. package/dist/{cron-manager-DQSK8uoV.mjs → cron.module-Bgzq5hiT.mjs} +47 -17
  34. package/dist/cron.module-Bgzq5hiT.mjs.map +1 -0
  35. package/dist/decorate-CuAoSZvs.mjs +16 -0
  36. package/dist/deep-merge-ByiAOZ3r.mjs +18 -0
  37. package/dist/deep-merge-ByiAOZ3r.mjs.map +1 -0
  38. package/dist/di/index.d.mts +2 -2
  39. package/dist/di/index.mjs +4 -3
  40. package/dist/di-DseMn-z9.mjs +524 -0
  41. package/dist/di-DseMn-z9.mjs.map +1 -0
  42. package/dist/email/index.d.mts +40 -122
  43. package/dist/email/index.d.mts.map +1 -1
  44. package/dist/email/index.mjs +446 -131
  45. package/dist/email/index.mjs.map +1 -1
  46. package/dist/en-CDZBMcc1.mjs +202 -0
  47. package/dist/en-CDZBMcc1.mjs.map +1 -0
  48. package/dist/{env-D1rcZ8_r.d.mts → env-ug22bJj7.d.mts} +1 -1
  49. package/dist/env-ug22bJj7.d.mts.map +1 -0
  50. package/dist/errors/index.d.mts +2 -2
  51. package/dist/errors/index.mjs +4 -2
  52. package/dist/errors-mXYxG0XB.mjs +333 -0
  53. package/dist/errors-mXYxG0XB.mjs.map +1 -0
  54. package/dist/events/index.d.mts +14 -3
  55. package/dist/events/index.d.mts.map +1 -1
  56. package/dist/events/index.mjs +2 -2
  57. package/dist/{events-CzCV8jI8.mjs → events-BXJGZjpG.mjs} +23 -13
  58. package/dist/events-BXJGZjpG.mjs.map +1 -0
  59. package/dist/exception-context-kEoMFwze.mjs +429 -0
  60. package/dist/exception-context-kEoMFwze.mjs.map +1 -0
  61. package/dist/{gateway-context-CXmXtaUP.mjs → gateway-context-TMu_AlJt.mjs} +38 -31
  62. package/dist/gateway-context-TMu_AlJt.mjs.map +1 -0
  63. package/dist/guards/index.d.mts +3 -3
  64. package/dist/guards/index.d.mts.map +1 -1
  65. package/dist/guards/index.mjs +1 -1
  66. package/dist/{guards-DU1_J9YA.mjs → guards-DALPXy3_.mjs} +6 -5
  67. package/dist/guards-DALPXy3_.mjs.map +1 -0
  68. package/dist/hono-app-CvV3hOfT.mjs +161 -0
  69. package/dist/hono-app-CvV3hOfT.mjs.map +1 -0
  70. package/dist/{http-method.decorator-BrgHMdLQ.mjs → http-method.decorator-ByWZb9DO.mjs} +7 -6
  71. package/dist/http-method.decorator-ByWZb9DO.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-DRQAZoSZ.mjs +222 -0
  84. package/dist/i18n.module-DRQAZoSZ.mjs.map +1 -0
  85. package/dist/i18n.tokens-CZ_v8oyS.mjs +19 -0
  86. package/dist/i18n.tokens-CZ_v8oyS.mjs.map +1 -0
  87. package/dist/{index-7-hU3GTV.d.mts → index-0ItCjaqw.d.mts} +1 -1
  88. package/dist/index-0ItCjaqw.d.mts.map +1 -0
  89. package/dist/index-B5JBRcWD.d.mts +544 -0
  90. package/dist/index-B5JBRcWD.d.mts.map +1 -0
  91. package/dist/index-BUt92sAE.d.mts +124 -0
  92. package/dist/index-BUt92sAE.d.mts.map +1 -0
  93. package/dist/{index-ByOyTmqf.d.mts → index-B_JoEl3V.d.mts} +751 -2229
  94. package/dist/index-B_JoEl3V.d.mts.map +1 -0
  95. package/dist/index-DtBNIFuP.d.mts +42 -0
  96. package/dist/index-DtBNIFuP.d.mts.map +1 -0
  97. package/dist/{index-C1KvMncZ.d.mts → index-HgOLNruQ.d.mts} +3 -108
  98. package/dist/index-HgOLNruQ.d.mts.map +1 -0
  99. package/dist/index.d.mts +6 -43
  100. package/dist/index.mjs +3 -2
  101. package/dist/{is-command-C6a7WTPw.mjs → is-command-CEPO9n8c.mjs} +2 -2
  102. package/dist/{is-command-C6a7WTPw.mjs.map → is-command-CEPO9n8c.mjs.map} +1 -1
  103. package/dist/{is-seeder-CebjZCDn.mjs → is-seeder-Gvh_AM71.mjs} +1 -1
  104. package/dist/{is-seeder-CebjZCDn.mjs.map → is-seeder-Gvh_AM71.mjs.map} +1 -1
  105. package/dist/lazy-module-loader-Ib383jH_.d.mts +60 -0
  106. package/dist/lazy-module-loader-Ib383jH_.d.mts.map +1 -0
  107. package/dist/locale-path.service-D-dHiIPc.mjs +165 -0
  108. package/dist/locale-path.service-D-dHiIPc.mjs.map +1 -0
  109. package/dist/locale-url-nZrZxqJP.mjs +44 -0
  110. package/dist/locale-url-nZrZxqJP.mjs.map +1 -0
  111. package/dist/locale-url.service-C2EWmGdq.mjs +41 -0
  112. package/dist/locale-url.service-C2EWmGdq.mjs.map +1 -0
  113. package/dist/logger/index.d.mts +2 -2
  114. package/dist/logger/index.mjs +170 -2
  115. package/dist/logger/index.mjs.map +1 -0
  116. package/dist/macroable/index.d.mts +2 -2
  117. package/dist/macroable/index.mjs +1 -1
  118. package/dist/{macroable-BmufBshB.mjs → macroable-cvDTFZ_A.mjs} +1 -1
  119. package/dist/{macroable-BmufBshB.mjs.map → macroable-cvDTFZ_A.mjs.map} +1 -1
  120. package/dist/metadata-DzzprcID.mjs +39 -0
  121. package/dist/metadata-DzzprcID.mjs.map +1 -0
  122. package/dist/module/index.d.mts +7 -24
  123. package/dist/module/index.d.mts.map +1 -1
  124. package/dist/module/index.mjs +10 -2
  125. package/dist/module/index.mjs.map +1 -0
  126. package/dist/module-registry-Dm-pqHd3.mjs +554 -0
  127. package/dist/module-registry-Dm-pqHd3.mjs.map +1 -0
  128. package/dist/module.decorator-CYHY6pG5.mjs +19 -0
  129. package/dist/module.decorator-CYHY6pG5.mjs.map +1 -0
  130. package/dist/openapi/index.d.mts +44 -8
  131. package/dist/openapi/index.d.mts.map +1 -1
  132. package/dist/openapi/index.mjs +3 -3
  133. package/dist/openapi-CstuTM8S.mjs +309 -0
  134. package/dist/openapi-CstuTM8S.mjs.map +1 -0
  135. package/dist/{openapi-tools.service-Zs-Ewv7F.mjs → openapi-tools.service-BC5EC3R3.mjs} +8 -2
  136. package/dist/openapi-tools.service-BC5EC3R3.mjs.map +1 -0
  137. package/dist/{openapi.service-Bt9bCIrd.d.mts → openapi.service-YhTiJ1bO.d.mts} +3 -3
  138. package/dist/openapi.service-YhTiJ1bO.d.mts.map +1 -0
  139. package/dist/quarry/index.d.mts +14 -163
  140. package/dist/quarry/index.d.mts.map +1 -1
  141. package/dist/quarry/index.mjs +6 -5
  142. package/dist/quarry/runner.d.mts +184 -0
  143. package/dist/quarry/runner.d.mts.map +1 -0
  144. package/dist/quarry/runner.mjs +945 -0
  145. package/dist/quarry/runner.mjs.map +1 -0
  146. package/dist/quarry-registry-CXg0RFXq.d.mts +69 -0
  147. package/dist/quarry-registry-CXg0RFXq.d.mts.map +1 -0
  148. package/dist/quarry.module-BuRPGMDm.mjs +312 -0
  149. package/dist/quarry.module-BuRPGMDm.mjs.map +1 -0
  150. package/dist/queue/index.d.mts +3 -3
  151. package/dist/queue/index.mjs +57 -48
  152. package/dist/queue/index.mjs.map +1 -1
  153. package/dist/queue.module-nddvxzCB.mjs +613 -0
  154. package/dist/queue.module-nddvxzCB.mjs.map +1 -0
  155. package/dist/queue.tokens-DjHnFmre.mjs +11 -0
  156. package/dist/queue.tokens-DjHnFmre.mjs.map +1 -0
  157. package/dist/{r2-storage.provider-DuonKeYm.mjs → r2-storage.provider-DCxQt9dD.mjs} +6 -6
  158. package/dist/r2-storage.provider-DCxQt9dD.mjs.map +1 -0
  159. package/dist/{rate-limit.decorator-6qzNcSOt.mjs → rate-limit.decorator-BPAie_p3.mjs} +6 -11
  160. package/dist/rate-limit.decorator-BPAie_p3.mjs.map +1 -0
  161. package/dist/rate-limiter/index.d.mts +11 -50
  162. package/dist/rate-limiter/index.d.mts.map +1 -1
  163. package/dist/rate-limiter/index.mjs +33 -42
  164. package/dist/rate-limiter/index.mjs.map +1 -1
  165. package/dist/route-name-DGoBOfPg.mjs +171 -0
  166. package/dist/route-name-DGoBOfPg.mjs.map +1 -0
  167. package/dist/route-registration.service-D6vSwiKP.mjs +918 -0
  168. package/dist/route-registration.service-D6vSwiKP.mjs.map +1 -0
  169. package/dist/route-registry-CYqLp2Nj.mjs +123 -0
  170. package/dist/route-registry-CYqLp2Nj.mjs.map +1 -0
  171. package/dist/router/index.d.mts +2 -2
  172. package/dist/router/index.mjs +18 -7
  173. package/dist/router-CWGBD-Bg.mjs +78 -0
  174. package/dist/router-CWGBD-Bg.mjs.map +1 -0
  175. package/dist/router-resolver-D4YlPNlm.mjs +88 -0
  176. package/dist/router-resolver-D4YlPNlm.mjs.map +1 -0
  177. package/dist/seeder/index.d.mts +16 -11
  178. package/dist/seeder/index.d.mts.map +1 -1
  179. package/dist/seeder/index.mjs +5 -3
  180. package/dist/seeder-7ubkms-Y.mjs +81 -0
  181. package/dist/seeder-7ubkms-Y.mjs.map +1 -0
  182. package/dist/seeder-registry-CyUmKsJq.mjs +57 -0
  183. package/dist/seeder-registry-CyUmKsJq.mjs.map +1 -0
  184. package/dist/seeder.module-CYYwk3Qk.mjs +15 -0
  185. package/dist/seeder.module-CYYwk3Qk.mjs.map +1 -0
  186. package/dist/{signed-url-BQPbv2In.mjs → signed-url-DIU0sK_6.mjs} +1 -1
  187. package/dist/{signed-url-BQPbv2In.mjs.map → signed-url-DIU0sK_6.mjs.map} +1 -1
  188. package/dist/storage/index.d.mts +15 -39
  189. package/dist/storage/index.d.mts.map +1 -1
  190. package/dist/storage/index.mjs +3 -3
  191. package/dist/storage/providers/index.d.mts +2 -2
  192. package/dist/storage/providers/index.d.mts.map +1 -1
  193. package/dist/storage/providers/index.mjs +1 -1
  194. package/dist/{storage-D8CBP72Z.mjs → storage-MDZypIE9.mjs} +66 -59
  195. package/dist/storage-MDZypIE9.mjs.map +1 -0
  196. package/dist/{storage-provider.interface-Bd6vA4ak.d.mts → storage-provider.interface-ClUwxz4S.d.mts} +2 -3
  197. package/dist/storage-provider.interface-ClUwxz4S.d.mts.map +1 -0
  198. package/dist/storage.error-Dnib4VHc.mjs +8 -0
  199. package/dist/storage.error-Dnib4VHc.mjs.map +1 -0
  200. package/dist/stratal-DL9M38_s.mjs +383 -0
  201. package/dist/stratal-DL9M38_s.mjs.map +1 -0
  202. package/dist/stratal-DwDJPY9N.d.mts +43 -0
  203. package/dist/stratal-DwDJPY9N.d.mts.map +1 -0
  204. package/dist/tiered-cache.service-Dv3BhxxE.d.mts +79 -0
  205. package/dist/tiered-cache.service-Dv3BhxxE.d.mts.map +1 -0
  206. package/dist/trailing-slash-CFyw8nYu.mjs +34 -0
  207. package/dist/trailing-slash-CFyw8nYu.mjs.map +1 -0
  208. package/dist/{types-cySNS_lp.d.mts → types-CmV_9xBD.d.mts} +1 -1
  209. package/dist/types-CmV_9xBD.d.mts.map +1 -0
  210. package/dist/uri-h7Q8Jug9.mjs +251 -0
  211. package/dist/uri-h7Q8Jug9.mjs.map +1 -0
  212. package/dist/{usage-generator-BUdlhnCK.mjs → usage-generator-DAWYasuP.mjs} +7 -4
  213. package/dist/usage-generator-DAWYasuP.mjs.map +1 -0
  214. package/dist/validation-CpOjviyT.mjs +49 -0
  215. package/dist/validation-CpOjviyT.mjs.map +1 -0
  216. package/dist/validation.context-CRvmrhq7.mjs +117 -0
  217. package/dist/validation.context-CRvmrhq7.mjs.map +1 -0
  218. package/dist/versioning.service-C6aHky8-.mjs +36 -0
  219. package/dist/versioning.service-C6aHky8-.mjs.map +1 -0
  220. package/dist/websocket/index.d.mts +16 -14
  221. package/dist/websocket/index.d.mts.map +1 -1
  222. package/dist/websocket/index.mjs +2 -2
  223. package/dist/workers/index.d.mts +2 -2
  224. package/dist/workers/index.d.mts.map +1 -1
  225. package/dist/workers/index.mjs +3 -2
  226. package/dist/workers/index.mjs.map +1 -1
  227. package/dist/zod-eKqqhZ5_.mjs +72 -0
  228. package/dist/zod-eKqqhZ5_.mjs.map +1 -0
  229. package/dist/{index-Bnpfq6uk.d.mts → zod-wecrEVAs.d.mts} +63 -133
  230. package/dist/zod-wecrEVAs.d.mts.map +1 -0
  231. package/package.json +28 -39
  232. package/dist/base-email.provider-CfQCA08m.mjs +0 -42
  233. package/dist/base-email.provider-CfQCA08m.mjs.map +0 -1
  234. package/dist/cache.service-DsnKuNyO.d.mts.map +0 -1
  235. package/dist/cache.tokens-B7Rw1C9Q.mjs +0 -6
  236. package/dist/cache.tokens-B7Rw1C9Q.mjs.map +0 -1
  237. package/dist/colors-DJaRDXoS.mjs +0 -16
  238. package/dist/colors-DJaRDXoS.mjs.map +0 -1
  239. package/dist/command-BgSlsS4M.mjs.map +0 -1
  240. package/dist/command-Cmmf0oHX.d.mts.map +0 -1
  241. package/dist/consumer-registry-B7yUNh0q.d.mts.map +0 -1
  242. package/dist/controller.decorator-B9vwn0zK.mjs.map +0 -1
  243. package/dist/cron-manager-CmTimEjf.d.mts +0 -131
  244. package/dist/cron-manager-CmTimEjf.d.mts.map +0 -1
  245. package/dist/cron-manager-DQSK8uoV.mjs.map +0 -1
  246. package/dist/en-DSH_bhh6.mjs +0 -308
  247. package/dist/en-DSH_bhh6.mjs.map +0 -1
  248. package/dist/env-D1rcZ8_r.d.mts.map +0 -1
  249. package/dist/errors-COW9-Mar.mjs +0 -1739
  250. package/dist/errors-COW9-Mar.mjs.map +0 -1
  251. package/dist/errors-ORxu1-Bb.mjs +0 -74
  252. package/dist/errors-ORxu1-Bb.mjs.map +0 -1
  253. package/dist/events-CzCV8jI8.mjs.map +0 -1
  254. package/dist/gateway-context-CXmXtaUP.mjs.map +0 -1
  255. package/dist/guards-DU1_J9YA.mjs.map +0 -1
  256. package/dist/http-method.decorator-BrgHMdLQ.mjs.map +0 -1
  257. package/dist/i18n.module-CzXLW9Hy.mjs +0 -2532
  258. package/dist/i18n.module-CzXLW9Hy.mjs.map +0 -1
  259. package/dist/index-7-hU3GTV.d.mts.map +0 -1
  260. package/dist/index-Bnpfq6uk.d.mts.map +0 -1
  261. package/dist/index-ByOyTmqf.d.mts.map +0 -1
  262. package/dist/index-C1KvMncZ.d.mts.map +0 -1
  263. package/dist/index-DBd_2wv8.d.mts +0 -263
  264. package/dist/index-DBd_2wv8.d.mts.map +0 -1
  265. package/dist/index-DUzWs0z7.d.mts +0 -494
  266. package/dist/index-DUzWs0z7.d.mts.map +0 -1
  267. package/dist/index.d.mts.map +0 -1
  268. package/dist/logger-DlV7NtvD.mjs +0 -440
  269. package/dist/logger-DlV7NtvD.mjs.map +0 -1
  270. package/dist/module-BzLg57FK.mjs +0 -866
  271. package/dist/module-BzLg57FK.mjs.map +0 -1
  272. package/dist/openapi-tools.service-Zs-Ewv7F.mjs.map +0 -1
  273. package/dist/openapi.service-Bt9bCIrd.d.mts.map +0 -1
  274. package/dist/quarry-registry-BwY2hOxm.mjs +0 -699
  275. package/dist/quarry-registry-BwY2hOxm.mjs.map +0 -1
  276. package/dist/queue.module-BhCjZp6H.mjs +0 -409
  277. package/dist/queue.module-BhCjZp6H.mjs.map +0 -1
  278. package/dist/r2-storage.provider-DuonKeYm.mjs.map +0 -1
  279. package/dist/rate-limit.decorator-6qzNcSOt.mjs.map +0 -1
  280. package/dist/resend.provider-DB4IlFjG.mjs +0 -68
  281. package/dist/resend.provider-DB4IlFjG.mjs.map +0 -1
  282. package/dist/seeder-zoEfEw9i.mjs +0 -138
  283. package/dist/seeder-zoEfEw9i.mjs.map +0 -1
  284. package/dist/setup-CefZKV_e.mjs +0 -37
  285. package/dist/setup-CefZKV_e.mjs.map +0 -1
  286. package/dist/smtp.provider-B6D7zuWX.mjs +0 -76
  287. package/dist/smtp.provider-B6D7zuWX.mjs.map +0 -1
  288. package/dist/storage-D8CBP72Z.mjs.map +0 -1
  289. package/dist/storage-provider.interface-Bd6vA4ak.d.mts.map +0 -1
  290. package/dist/stratal-CNwpbSZl.mjs +0 -535
  291. package/dist/stratal-CNwpbSZl.mjs.map +0 -1
  292. package/dist/types-cySNS_lp.d.mts.map +0 -1
  293. package/dist/usage-generator-BUdlhnCK.mjs.map +0 -1
  294. package/dist/validation-DtJwAv7O.mjs +0 -248
  295. package/dist/validation-DtJwAv7O.mjs.map +0 -1
  296. /package/dist/{chunk-D1SwGrFN.mjs → chunk-BBjsoOtd.mjs} +0 -0
@@ -0,0 +1,429 @@
1
+ import { _ as ContainerError, v as ROUTER_TOKENS } from "./di-DseMn-z9.mjs";
2
+ import { t as Macroable } from "./macroable-cvDTFZ_A.mjs";
3
+ import { deleteCookie, getCookie, setCookie } from "hono/cookie";
4
+ import { stream, streamSSE, streamText } from "hono/streaming";
5
+ //#region src/router/constants.ts
6
+ /**
7
+ * Type-safe context keys for Hono router variables
8
+ * Using symbols to avoid string collisions
9
+ */
10
+ const ROUTER_CONTEXT_KEYS = {
11
+ REQUEST_CONTAINER: "requestContainer",
12
+ LOCALE: "locale"
13
+ };
14
+ /**
15
+ * Metadata keys for storing route and controller configuration
16
+ * Using symbols to avoid collisions with other decorators
17
+ */
18
+ const ROUTE_METADATA_KEYS = {
19
+ CONTROLLER_ROUTE: Symbol.for("stratal:controller:route"),
20
+ CONTROLLER_OPTIONS: Symbol.for("stratal:controller:options"),
21
+ CONTROLLER_MIDDLEWARES: Symbol.for("stratal:controller:middlewares"),
22
+ ROUTE_CONFIG: Symbol.for("stratal:route:config"),
23
+ DECORATED_METHODS: Symbol.for("stratal:decorated:methods"),
24
+ AUTH_GUARD: Symbol.for("stratal:auth:guard"),
25
+ GATEWAY_MARKER: Symbol.for("stratal:gateway:marker"),
26
+ WS_ON_MESSAGE: Symbol.for("stratal:ws:on-message"),
27
+ WS_ON_CLOSE: Symbol.for("stratal:ws:on-close"),
28
+ WS_ON_ERROR: Symbol.for("stratal:ws:on-error"),
29
+ RATE_LIMIT: Symbol.for("stratal:route:rate-limit")
30
+ };
31
+ /**
32
+ * Security scheme identifiers for OpenAPI
33
+ * These reference the security scheme definitions in security.schemas.ts
34
+ */
35
+ const SECURITY_SCHEMES = {
36
+ BEARER_AUTH: "bearerAuth",
37
+ API_KEY: "apiKey",
38
+ SESSION_COOKIE: "sessionCookie"
39
+ };
40
+ /**
41
+ * HTTP method mapping for RESTful controller methods
42
+ * Maps controller method names to HTTP verbs and path patterns
43
+ */
44
+ const HTTP_METHODS = {
45
+ index: {
46
+ method: "get",
47
+ path: ""
48
+ },
49
+ show: {
50
+ method: "get",
51
+ path: "/:id"
52
+ },
53
+ create: {
54
+ method: "post",
55
+ path: ""
56
+ },
57
+ update: {
58
+ method: "put",
59
+ path: "/:id"
60
+ },
61
+ patch: {
62
+ method: "patch",
63
+ path: "/:id"
64
+ },
65
+ destroy: {
66
+ method: "delete",
67
+ path: "/:id"
68
+ }
69
+ };
70
+ /**
71
+ * Default success status codes for RESTful controller methods
72
+ * Used by @Route() decorator to auto-derive response status
73
+ */
74
+ const METHOD_STATUS_CODES = {
75
+ index: 200,
76
+ show: 200,
77
+ create: 201,
78
+ update: 200,
79
+ patch: 200,
80
+ destroy: 200
81
+ };
82
+ /**
83
+ * Sentinel symbol to opt a controller out of versioning.
84
+ * When used as the version, no prefix is applied even when defaultVersion is set.
85
+ */
86
+ const VERSION_NEUTRAL = Symbol.for("stratal:version:neutral");
87
+ /**
88
+ * Default content type for request bodies and responses
89
+ */
90
+ const DEFAULT_CONTENT_TYPE = "application/json";
91
+ //#endregion
92
+ //#region src/router/router-context.ts
93
+ /**
94
+ * Router context wrapper with helper methods
95
+ *
96
+ * Provides convenient access to Hono's context and common request/response operations.
97
+ * The native Hono context is available via the `c` property for advanced use cases.
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * async index(ctx: RouterContext): Promise<Response> {
102
+ * // Use helper methods
103
+ * const users = await this.service.findAll()
104
+ * return ctx.json(users)
105
+ * }
106
+ *
107
+ * async show(ctx: RouterContext): Promise<Response> {
108
+ * // Access route params
109
+ * const id = ctx.param('id')
110
+ * const user = await this.service.findById(id)
111
+ * return ctx.json(user)
112
+ * }
113
+ *
114
+ * async create(ctx: RouterContext): Promise<Response> {
115
+ * // Parse request body
116
+ * const body = await ctx.body<CreateUserInput>()
117
+ * const user = await this.service.create(body)
118
+ * return ctx.json(user, 201)
119
+ * }
120
+ * ```
121
+ */
122
+ var RouterContext = class extends Macroable {
123
+ c;
124
+ /**
125
+ * Native Hono context
126
+ * Access for advanced use cases not covered by helper methods
127
+ */
128
+ constructor(c) {
129
+ super();
130
+ this.c = c;
131
+ }
132
+ /**
133
+ * Cloudflare-provided request properties (geo, TLS, bot management, etc.).
134
+ * Always available on Cloudflare Workers requests via `c.req.raw.cf`.
135
+ */
136
+ get cf() {
137
+ return this.c.req.raw.cf;
138
+ }
139
+ /**
140
+ * Get request-scoped DI container
141
+ * Contains request-specific services and context (AuthContext)
142
+ *
143
+ * @throws Error if container not initialized
144
+ */
145
+ getContainer() {
146
+ const container = this.c.get(ROUTER_CONTEXT_KEYS.REQUEST_CONTAINER);
147
+ if (!container) throw new ContainerError("Request container has not been initialized");
148
+ return container;
149
+ }
150
+ /**
151
+ * Set locale for the current request
152
+ *
153
+ * @param locale - Locale code (e.g., 'en', 'fr')
154
+ */
155
+ setLocale(locale) {
156
+ this.c.set(ROUTER_CONTEXT_KEYS.LOCALE, locale);
157
+ }
158
+ /**
159
+ * Get locale for the current request
160
+ *
161
+ * @returns Current locale code
162
+ */
163
+ getLocale() {
164
+ return this.c.get(ROUTER_CONTEXT_KEYS.LOCALE) || "en";
165
+ }
166
+ /**
167
+ * Return JSON response
168
+ *
169
+ * When data is null, automatically returns 204 No Content (configurable via status param).
170
+ *
171
+ * @param data - Data to serialize as JSON, or null for 204
172
+ * @param status - HTTP status code (default: 200, or 204 when data is null)
173
+ */
174
+ json(data, status) {
175
+ if (data === null) return this.c.body(null, status ?? 204);
176
+ return this.c.json(data, status);
177
+ }
178
+ param(key) {
179
+ const all = this.c.req.valid("param") ?? {};
180
+ return key === void 0 ? all : all[key];
181
+ }
182
+ /**
183
+ * Get query parameter value
184
+ *
185
+ * @param key - Query parameter name
186
+ */
187
+ query(key) {
188
+ const validated = this.c.req.valid("query");
189
+ return key ? validated[key] : validated;
190
+ }
191
+ /**
192
+ * Get request header value
193
+ *
194
+ * @param name - Header name (case-insensitive)
195
+ */
196
+ header(name) {
197
+ return this.c.req.header(name);
198
+ }
199
+ /**
200
+ * Read a cookie value from the current request.
201
+ *
202
+ * @param name - Cookie name
203
+ * @returns The cookie value, or `undefined` if the cookie is not present
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * const redirectTo = ctx.getCookie('redirectTo')
208
+ * ```
209
+ */
210
+ getCookie(name) {
211
+ return getCookie(this.c, name);
212
+ }
213
+ /**
214
+ * Set a cookie on the response.
215
+ *
216
+ * Cookie operations must run while the response is mutable — call this
217
+ * before returning the final `Response` from the handler.
218
+ *
219
+ * @param name - Cookie name
220
+ * @param value - Cookie value
221
+ * @param options - Cookie attributes (httpOnly, secure, sameSite, path, etc.)
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * ctx.setCookie('redirectTo', '/app/', {
226
+ * httpOnly: true,
227
+ * secure: true,
228
+ * sameSite: 'lax',
229
+ * path: '/',
230
+ * })
231
+ * ```
232
+ */
233
+ setCookie(name, value, options) {
234
+ setCookie(this.c, name, value, options);
235
+ }
236
+ /**
237
+ * Delete a cookie from the response.
238
+ *
239
+ * Pass the same `path` and `domain` options that were used when the cookie
240
+ * was set, otherwise the browser will not clear the matching cookie.
241
+ *
242
+ * @param name - Cookie name
243
+ * @param options - Cookie attributes used at set time (path, domain, etc.)
244
+ * @returns The deleted cookie's previous value, or `undefined`
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * ctx.deleteCookie('redirectTo', { path: '/' })
249
+ * ```
250
+ */
251
+ deleteCookie(name, options) {
252
+ return deleteCookie(this.c, name, options);
253
+ }
254
+ /**
255
+ * Get validated request body from OpenAPI route
256
+ * Returns pre-validated data that has passed schema validation
257
+ *
258
+ * @returns Validated JSON body
259
+ */
260
+ body() {
261
+ return this.c.req.valid("json");
262
+ }
263
+ /**
264
+ * Return text response
265
+ *
266
+ * @param text - Text content
267
+ * @param status - HTTP status code (default: 200)
268
+ */
269
+ text(text, status) {
270
+ return this.c.text(text, status);
271
+ }
272
+ /**
273
+ * Return HTML response
274
+ *
275
+ * @param html - HTML content
276
+ * @param status - HTTP status code (default: 200)
277
+ */
278
+ html(html, status) {
279
+ return this.c.html(html, status);
280
+ }
281
+ /**
282
+ * Generate a URL from a named route.
283
+ *
284
+ * Keys matching `:param` placeholders fill the path.
285
+ * Domain params are consumed from the same object.
286
+ * Extra keys become query string parameters.
287
+ *
288
+ * @param name - Named route identifier
289
+ * @param params - Route params + domain params + extra query params
290
+ * @param options - URL generation options (e.g., `{ absolute: true }`)
291
+ *
292
+ * @example
293
+ * ```typescript
294
+ * ctx.route('users.show', { id: '1' }) // '/v1/users/1'
295
+ * ctx.route('users.show', { id: '1', q: 'test' }) // '/v1/users/1?q=test'
296
+ * ```
297
+ */
298
+ route(name, params, options) {
299
+ return this.resolveUri().route(name, params, options);
300
+ }
301
+ /**
302
+ * Get a domain parameter value from the current request.
303
+ * Domain params are set by the domain matching middleware.
304
+ *
305
+ * @param key - Domain parameter name (e.g., 'tenant' from '{tenant}.myapp.com')
306
+ *
307
+ * @example
308
+ * ```typescript
309
+ * const tenant = ctx.domain('tenant')
310
+ * ```
311
+ */
312
+ domain(key) {
313
+ return this.c.get(`domain:${key}`);
314
+ }
315
+ /**
316
+ * Generate a signed URL from a named route.
317
+ *
318
+ * @param name - Named route identifier
319
+ * @param params - Route params (same as route())
320
+ * @param options - Signing options (e.g., expiresIn) and URL options
321
+ * @returns Signed URL string with signature query param
322
+ */
323
+ async signedUrl(name, params, options) {
324
+ return this.resolveUri().signedRoute(name, params, options);
325
+ }
326
+ /**
327
+ * Check if the current request has a valid signature.
328
+ *
329
+ * @returns true if the URL signature is valid and not expired
330
+ */
331
+ async hasValidSignature() {
332
+ return this.resolveUri().hasValidSignature();
333
+ }
334
+ /**
335
+ * Redirect to another URL
336
+ *
337
+ * @param url - Target URL
338
+ * @param status - HTTP status code (default: 302)
339
+ */
340
+ redirect(url, status) {
341
+ return this.c.redirect(url, status);
342
+ }
343
+ /**
344
+ * Return a streaming response (binary/generic)
345
+ *
346
+ * @param callback - Async function that writes to the stream
347
+ * @param onError - Optional error handler called if an error occurs during streaming
348
+ */
349
+ stream(callback, onError) {
350
+ return stream(this.c, callback, onError);
351
+ }
352
+ /**
353
+ * Return a streaming text response
354
+ *
355
+ * Automatically sets `Content-Encoding: Identity` for Cloudflare Workers compatibility.
356
+ *
357
+ * @param callback - Async function that writes text to the stream
358
+ * @param onError - Optional error handler called if an error occurs during streaming
359
+ */
360
+ streamText(callback, onError) {
361
+ this.c.header("Content-Encoding", "Identity");
362
+ return streamText(this.c, callback, onError);
363
+ }
364
+ /**
365
+ * Return a Server-Sent Events (SSE) streaming response
366
+ *
367
+ * Automatically sets `Content-Encoding: Identity` for Cloudflare Workers compatibility.
368
+ *
369
+ * @param callback - Async function that writes SSE events to the stream
370
+ * @param onError - Optional error handler called if an error occurs during streaming
371
+ */
372
+ streamSSE(callback, onError) {
373
+ this.c.header("Content-Encoding", "Identity");
374
+ return streamSSE(this.c, callback, onError);
375
+ }
376
+ resolveUri() {
377
+ return this.getContainer().resolve(ROUTER_TOKENS.Uri);
378
+ }
379
+ };
380
+ //#endregion
381
+ //#region src/errors/exception-context.ts
382
+ /**
383
+ * Create an HTTP exception context from a Hono context.
384
+ *
385
+ * @param c - The raw Hono context from the request
386
+ * @returns An {@link HttpExceptionContext} wrapping a RouterContext
387
+ */
388
+ function createHttpExceptionContext(c) {
389
+ return {
390
+ type: "http",
391
+ ctx: new RouterContext(c)
392
+ };
393
+ }
394
+ /**
395
+ * Create a queue exception context.
396
+ *
397
+ * @param queueName - The name of the queue being processed
398
+ * @returns A {@link QueueExceptionContext}
399
+ */
400
+ function createQueueExceptionContext(queueName) {
401
+ return {
402
+ type: "queue",
403
+ queueName
404
+ };
405
+ }
406
+ /**
407
+ * Create a cron exception context.
408
+ *
409
+ * @returns A {@link CronExceptionContext}
410
+ */
411
+ function createCronExceptionContext() {
412
+ return { type: "cron" };
413
+ }
414
+ /**
415
+ * Create a CLI command exception context.
416
+ *
417
+ * @param commandName - The name of the command that threw
418
+ * @returns A {@link CliExceptionContext}
419
+ */
420
+ function createCliExceptionContext(commandName) {
421
+ return {
422
+ type: "cli",
423
+ commandName
424
+ };
425
+ }
426
+ //#endregion
427
+ export { RouterContext as a, METHOD_STATUS_CODES as c, SECURITY_SCHEMES as d, VERSION_NEUTRAL as f, createQueueExceptionContext as i, ROUTER_CONTEXT_KEYS as l, createCronExceptionContext as n, DEFAULT_CONTENT_TYPE as o, createHttpExceptionContext as r, HTTP_METHODS as s, createCliExceptionContext as t, ROUTE_METADATA_KEYS as u };
428
+
429
+ //# sourceMappingURL=exception-context-kEoMFwze.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exception-context-kEoMFwze.mjs","names":["honoGetCookie","honoDeleteCookie","honoStream","honoStreamText","honoStreamSSE"],"sources":["../src/router/constants.ts","../src/router/router-context.ts","../src/errors/exception-context.ts"],"sourcesContent":["/**\n * Type-safe context keys for Hono router variables\n * Using symbols to avoid string collisions\n */\nexport const ROUTER_CONTEXT_KEYS = {\n REQUEST_CONTAINER: 'requestContainer',\n LOCALE: 'locale'\n} as const satisfies Record<string, string>\n\n/**\n * Metadata keys for storing route and controller configuration\n * Using symbols to avoid collisions with other decorators\n */\nexport const ROUTE_METADATA_KEYS = {\n CONTROLLER_ROUTE: Symbol.for('stratal:controller:route'),\n CONTROLLER_OPTIONS: Symbol.for('stratal:controller:options'),\n CONTROLLER_MIDDLEWARES: Symbol.for('stratal:controller:middlewares'),\n ROUTE_CONFIG: Symbol.for('stratal:route:config'),\n DECORATED_METHODS: Symbol.for('stratal:decorated:methods'),\n AUTH_GUARD: Symbol.for('stratal:auth:guard'),\n GATEWAY_MARKER: Symbol.for('stratal:gateway:marker'),\n WS_ON_MESSAGE: Symbol.for('stratal:ws:on-message'),\n WS_ON_CLOSE: Symbol.for('stratal:ws:on-close'),\n WS_ON_ERROR: Symbol.for('stratal:ws:on-error'),\n RATE_LIMIT: Symbol.for('stratal:route:rate-limit'),\n} as const\n\n/**\n * Security scheme identifiers for OpenAPI\n * These reference the security scheme definitions in security.schemas.ts\n */\nexport const SECURITY_SCHEMES = {\n BEARER_AUTH: 'bearerAuth',\n API_KEY: 'apiKey',\n SESSION_COOKIE: 'sessionCookie'\n} as const\n\n/**\n * HTTP method mapping for RESTful controller methods\n * Maps controller method names to HTTP verbs and path patterns\n */\nexport const HTTP_METHODS = {\n index: { method: 'get', path: '' } as const,\n show: { method: 'get', path: '/:id' } as const,\n create: { method: 'post', path: '' } as const,\n update: { method: 'put', path: '/:id' } as const,\n patch: { method: 'patch', path: '/:id' } as const,\n destroy: { method: 'delete', path: '/:id' } as const\n} as const\n\n/**\n * Default success status codes for RESTful controller methods\n * Used by @Route() decorator to auto-derive response status\n */\nexport const METHOD_STATUS_CODES = {\n index: 200,\n show: 200,\n create: 201,\n update: 200,\n patch: 200,\n destroy: 200\n} as const\n\n/**\n * Sentinel symbol to opt a controller out of versioning.\n * When used as the version, no prefix is applied even when defaultVersion is set.\n */\nexport const VERSION_NEUTRAL = Symbol.for('stratal:version:neutral')\n\n/**\n * Default content type for request bodies and responses\n */\nexport const DEFAULT_CONTENT_TYPE = 'application/json'\n","import type { Context } from 'hono'\nimport {\n deleteCookie as honoDeleteCookie,\n getCookie as honoGetCookie,\n setCookie as honoSetCookie,\n} from 'hono/cookie'\nimport type { SSEStreamingApi } from 'hono/streaming'\nimport { stream as honoStream, streamSSE as honoStreamSSE, streamText as honoStreamText } from 'hono/streaming'\nimport type { CookieOptions } from 'hono/utils/cookie'\nimport type { ContentfulStatusCode, RedirectStatusCode } from 'hono/utils/http-status'\nimport type { StreamingApi } from 'hono/utils/stream'\nimport type { Container } from '../di/container'\nimport { ContainerError } from '../di/container.error'\nimport { Macroable } from '../macroable'\nimport { ROUTER_CONTEXT_KEYS } from './constants'\nimport type { RouteName, RouteParams } from './route-map'\nimport { ROUTER_TOKENS } from './router.tokens'\nimport type { RouterEnv } from './types'\nimport type { SignedUriOptions, Uri, UriOptions } from './uri'\n\nexport type ContextQueryResult<R extends Record<string, unknown> | undefined, K extends string | undefined> = K extends string ? string : R extends undefined ? Record<string, unknown> : R\n\n/**\n * Router context wrapper with helper methods\n *\n * Provides convenient access to Hono's context and common request/response operations.\n * The native Hono context is available via the `c` property for advanced use cases.\n *\n * @example\n * ```typescript\n * async index(ctx: RouterContext): Promise<Response> {\n * // Use helper methods\n * const users = await this.service.findAll()\n * return ctx.json(users)\n * }\n *\n * async show(ctx: RouterContext): Promise<Response> {\n * // Access route params\n * const id = ctx.param('id')\n * const user = await this.service.findById(id)\n * return ctx.json(user)\n * }\n *\n * async create(ctx: RouterContext): Promise<Response> {\n * // Parse request body\n * const body = await ctx.body<CreateUserInput>()\n * const user = await this.service.create(body)\n * return ctx.json(user, 201)\n * }\n * ```\n */\nexport class RouterContext<T extends RouterEnv = RouterEnv> extends Macroable {\n /**\n * Native Hono context\n * Access for advanced use cases not covered by helper methods\n */\n constructor(\n public readonly c: Context<T>\n ) {\n super()\n }\n\n /**\n * Cloudflare-provided request properties (geo, TLS, bot management, etc.).\n * Always available on Cloudflare Workers requests via `c.req.raw.cf`.\n */\n get cf(): CfProperties {\n return this.c.req.raw.cf!\n }\n\n /**\n * Get request-scoped DI container\n * Contains request-specific services and context (AuthContext)\n *\n * @throws Error if container not initialized\n */\n getContainer(): Container {\n const container = this.c.get(ROUTER_CONTEXT_KEYS.REQUEST_CONTAINER)\n if (!container) {\n throw new ContainerError('Request container has not been initialized')\n }\n return container as Container\n }\n\n /**\n * Set locale for the current request\n *\n * @param locale - Locale code (e.g., 'en', 'fr')\n */\n setLocale(locale: string): void {\n this.c.set(ROUTER_CONTEXT_KEYS.LOCALE, locale)\n }\n\n /**\n * Get locale for the current request\n *\n * @returns Current locale code\n */\n getLocale(): string {\n const locale = this.c.get(ROUTER_CONTEXT_KEYS.LOCALE)\n return (locale as string) || 'en'\n }\n\n /**\n * Return JSON response\n *\n * When data is null, automatically returns 204 No Content (configurable via status param).\n *\n * @param data - Data to serialize as JSON, or null for 204\n * @param status - HTTP status code (default: 200, or 204 when data is null)\n */\n json(data: object | null, status?: ContentfulStatusCode): Response {\n if (data === null) {\n return this.c.body(null, status ?? 204)\n }\n return this.c.json(data, status)\n }\n\n /**\n * Get route parameter value(s).\n *\n * Reads the validated, Zod-coerced param record from `c.req.valid('param')`,\n * which is what `@hono/zod-openapi` populates for every route registered\n * via `app.openapi(...)`. Bare `c.req.param()` returns `undefined` for those\n * routes — always go through the validated record.\n *\n * - With a key → returns the single string value.\n * - With no args → returns the full `Record<string, string>` (or `{}` when\n * the matched route has no path params).\n *\n * @param key - Parameter name (e.g., 'id' for /users/:id)\n */\n param(): Record<string, string>\n param(key: string): string\n param(key?: string): string | Record<string, string> {\n const all = (this.c.req as unknown as { valid(target: 'param'): Record<string, string> | undefined }).valid('param') ?? {}\n return key === undefined ? all : all[key]\n }\n\n /**\n * Get query parameter value\n *\n * @param key - Query parameter name\n */\n query<R extends Record<string, unknown> | undefined = undefined, K extends string | undefined = undefined>(key?: K): ContextQueryResult<R, K> {\n const validated = (this.c.req as unknown as { valid(target: 'query'): Record<string, unknown> }).valid('query')\n return key ? validated[key] as ContextQueryResult<R, K> : validated as ContextQueryResult<R, K>\n }\n\n /**\n * Get request header value\n *\n * @param name - Header name (case-insensitive)\n */\n header(name: string): string | undefined {\n return this.c.req.header(name)\n }\n\n /**\n * Read a cookie value from the current request.\n *\n * @param name - Cookie name\n * @returns The cookie value, or `undefined` if the cookie is not present\n *\n * @example\n * ```typescript\n * const redirectTo = ctx.getCookie('redirectTo')\n * ```\n */\n getCookie(name: string): string | undefined {\n return honoGetCookie(this.c, name)\n }\n\n /**\n * Set a cookie on the response.\n *\n * Cookie operations must run while the response is mutable — call this\n * before returning the final `Response` from the handler.\n *\n * @param name - Cookie name\n * @param value - Cookie value\n * @param options - Cookie attributes (httpOnly, secure, sameSite, path, etc.)\n *\n * @example\n * ```typescript\n * ctx.setCookie('redirectTo', '/app/', {\n * httpOnly: true,\n * secure: true,\n * sameSite: 'lax',\n * path: '/',\n * })\n * ```\n */\n setCookie(name: string, value: string, options?: CookieOptions): void {\n honoSetCookie(this.c, name, value, options)\n }\n\n /**\n * Delete a cookie from the response.\n *\n * Pass the same `path` and `domain` options that were used when the cookie\n * was set, otherwise the browser will not clear the matching cookie.\n *\n * @param name - Cookie name\n * @param options - Cookie attributes used at set time (path, domain, etc.)\n * @returns The deleted cookie's previous value, or `undefined`\n *\n * @example\n * ```typescript\n * ctx.deleteCookie('redirectTo', { path: '/' })\n * ```\n */\n deleteCookie(name: string, options?: CookieOptions): string | undefined {\n return honoDeleteCookie(this.c, name, options)\n }\n\n /**\n * Get validated request body from OpenAPI route\n * Returns pre-validated data that has passed schema validation\n *\n * @returns Validated JSON body\n */\n body<T>(): Promise<T> {\n // Type assertion needed because req.valid() is type-safe per route\n // but this is a generic helper method that works across all routes\n return (this.c.req as unknown as { valid(target: 'json'): Promise<T> }).valid('json')\n }\n\n /**\n * Return text response\n *\n * @param text - Text content\n * @param status - HTTP status code (default: 200)\n */\n text(text: string, status?: ContentfulStatusCode): Response {\n return this.c.text(text, status)\n }\n\n /**\n * Return HTML response\n *\n * @param html - HTML content\n * @param status - HTTP status code (default: 200)\n */\n html(html: string, status?: ContentfulStatusCode): Response {\n return this.c.html(html, status)\n }\n\n /**\n * Generate a URL from a named route.\n *\n * Keys matching `:param` placeholders fill the path.\n * Domain params are consumed from the same object.\n * Extra keys become query string parameters.\n *\n * @param name - Named route identifier\n * @param params - Route params + domain params + extra query params\n * @param options - URL generation options (e.g., `{ absolute: true }`)\n *\n * @example\n * ```typescript\n * ctx.route('users.show', { id: '1' }) // '/v1/users/1'\n * ctx.route('users.show', { id: '1', q: 'test' }) // '/v1/users/1?q=test'\n * ```\n */\n route<N extends RouteName>(name: N, params?: RouteParams<N>, options?: UriOptions): string {\n return this.resolveUri().route(name, params, options)\n }\n\n /**\n * Get a domain parameter value from the current request.\n * Domain params are set by the domain matching middleware.\n *\n * @param key - Domain parameter name (e.g., 'tenant' from '{tenant}.myapp.com')\n *\n * @example\n * ```typescript\n * const tenant = ctx.domain('tenant')\n * ```\n */\n domain(key: string): string {\n return this.c.get(`domain:${key}`) as string\n }\n\n /**\n * Generate a signed URL from a named route.\n *\n * @param name - Named route identifier\n * @param params - Route params (same as route())\n * @param options - Signing options (e.g., expiresIn) and URL options\n * @returns Signed URL string with signature query param\n */\n async signedUrl<N extends RouteName>(name: N, params?: RouteParams<N>, options?: SignedUriOptions): Promise<string> {\n return this.resolveUri().signedRoute(name, params, options)\n }\n\n /**\n * Check if the current request has a valid signature.\n *\n * @returns true if the URL signature is valid and not expired\n */\n async hasValidSignature(): Promise<boolean> {\n return this.resolveUri().hasValidSignature()\n }\n\n /**\n * Redirect to another URL\n *\n * @param url - Target URL\n * @param status - HTTP status code (default: 302)\n */\n redirect(url: string, status?: RedirectStatusCode): Response {\n return this.c.redirect(url, status)\n }\n\n /**\n * Return a streaming response (binary/generic)\n *\n * @param callback - Async function that writes to the stream\n * @param onError - Optional error handler called if an error occurs during streaming\n */\n stream(callback: (stream: StreamingApi) => Promise<void>, onError?: (err: Error, stream: StreamingApi) => Promise<void>): Response {\n return honoStream(this.c, callback, onError)\n }\n\n /**\n * Return a streaming text response\n *\n * Automatically sets `Content-Encoding: Identity` for Cloudflare Workers compatibility.\n *\n * @param callback - Async function that writes text to the stream\n * @param onError - Optional error handler called if an error occurs during streaming\n */\n streamText(callback: (stream: StreamingApi) => Promise<void>, onError?: (err: Error, stream: StreamingApi) => Promise<void>): Response {\n this.c.header('Content-Encoding', 'Identity')\n return honoStreamText(this.c, callback, onError)\n }\n\n /**\n * Return a Server-Sent Events (SSE) streaming response\n *\n * Automatically sets `Content-Encoding: Identity` for Cloudflare Workers compatibility.\n *\n * @param callback - Async function that writes SSE events to the stream\n * @param onError - Optional error handler called if an error occurs during streaming\n */\n streamSSE(callback: (stream: SSEStreamingApi) => Promise<void>, onError?: (err: Error, stream: SSEStreamingApi) => Promise<void>): Response {\n this.c.header('Content-Encoding', 'Identity')\n return honoStreamSSE(this.c, callback, onError)\n }\n\n private resolveUri(): Uri {\n return this.getContainer().resolve<Uri>(ROUTER_TOKENS.Uri)\n }\n}\n","import type { Context } from 'hono'\nimport { RouterContext } from '../router/router-context'\nimport type { RouterEnv } from '../router/types'\n\n/**\n * Exception context for errors occurring during HTTP request handling.\n *\n * Provides access to the full {@link RouterContext} for building responses\n * with `ctx.json()`, `ctx.text()`, `ctx.html()`, etc.\n */\nexport interface HttpExceptionContext {\n readonly type: 'http'\n /** Stratal RouterContext — use for building HTTP responses */\n readonly ctx: RouterContext\n}\n\n/**\n * Exception context for errors occurring during queue message processing.\n */\nexport interface QueueExceptionContext {\n readonly type: 'queue'\n /** Name of the queue being processed */\n readonly queueName: string\n}\n\n/**\n * Exception context for errors occurring during scheduled cron execution.\n */\nexport interface CronExceptionContext {\n readonly type: 'cron'\n}\n\n/**\n * Exception context for errors occurring during CLI command execution.\n */\nexport interface CliExceptionContext {\n readonly type: 'cli'\n /** Name of the command that threw */\n readonly commandName: string\n}\n\n/**\n * Discriminated union of all exception context types.\n *\n * Narrow via `ctx.type` to access context-specific properties:\n *\n * @example\n * ```typescript\n * handler.renderable(MyError, (error, ctx) => {\n * if (ctx.type === 'http') {\n * return ctx.ctx.json({ message: 'Something went wrong' }, 500)\n * }\n * // Non-HTTP contexts: return undefined to use default rendering\n * })\n * ```\n */\nexport type ExceptionContext =\n | HttpExceptionContext\n | QueueExceptionContext\n | CronExceptionContext\n | CliExceptionContext\n\n/**\n * Create an HTTP exception context from a Hono context.\n *\n * @param c - The raw Hono context from the request\n * @returns An {@link HttpExceptionContext} wrapping a RouterContext\n */\nexport function createHttpExceptionContext(c: Context<RouterEnv>): HttpExceptionContext {\n return { type: 'http', ctx: new RouterContext(c) }\n}\n\n/**\n * Create a queue exception context.\n *\n * @param queueName - The name of the queue being processed\n * @returns A {@link QueueExceptionContext}\n */\nexport function createQueueExceptionContext(queueName: string): QueueExceptionContext {\n return { type: 'queue', queueName }\n}\n\n/**\n * Create a cron exception context.\n *\n * @returns A {@link CronExceptionContext}\n */\nexport function createCronExceptionContext(): CronExceptionContext {\n return { type: 'cron' }\n}\n\n/**\n * Create a CLI command exception context.\n *\n * @param commandName - The name of the command that threw\n * @returns A {@link CliExceptionContext}\n */\nexport function createCliExceptionContext(commandName: string): CliExceptionContext {\n return { type: 'cli', commandName }\n}\n"],"mappings":";;;;;;;;;AAIA,MAAa,sBAAsB;CACjC,mBAAmB;CACnB,QAAQ;AACV;;;;;AAMA,MAAa,sBAAsB;CACjC,kBAAkB,OAAO,IAAI,0BAA0B;CACvD,oBAAoB,OAAO,IAAI,4BAA4B;CAC3D,wBAAwB,OAAO,IAAI,gCAAgC;CACnE,cAAc,OAAO,IAAI,sBAAsB;CAC/C,mBAAmB,OAAO,IAAI,2BAA2B;CACzD,YAAY,OAAO,IAAI,oBAAoB;CAC3C,gBAAgB,OAAO,IAAI,wBAAwB;CACnD,eAAe,OAAO,IAAI,uBAAuB;CACjD,aAAa,OAAO,IAAI,qBAAqB;CAC7C,aAAa,OAAO,IAAI,qBAAqB;CAC7C,YAAY,OAAO,IAAI,0BAA0B;AACnD;;;;;AAMA,MAAa,mBAAmB;CAC9B,aAAa;CACb,SAAS;CACT,gBAAgB;AAClB;;;;;AAMA,MAAa,eAAe;CAC1B,OAAO;EAAE,QAAQ;EAAO,MAAM;CAAG;CACjC,MAAM;EAAE,QAAQ;EAAO,MAAM;CAAO;CACpC,QAAQ;EAAE,QAAQ;EAAQ,MAAM;CAAG;CACnC,QAAQ;EAAE,QAAQ;EAAO,MAAM;CAAO;CACtC,OAAO;EAAE,QAAQ;EAAS,MAAM;CAAO;CACvC,SAAS;EAAE,QAAQ;EAAU,MAAM;CAAO;AAC5C;;;;;AAMA,MAAa,sBAAsB;CACjC,OAAO;CACP,MAAM;CACN,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,SAAS;AACX;;;;;AAMA,MAAa,kBAAkB,OAAO,IAAI,yBAAyB;;;;AAKnE,MAAa,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrBpC,IAAa,gBAAb,cAAoE,UAAU;CAM1D;;;;;CADlB,YACE,GACA;EACA,MAAM;EAFU,KAAA,IAAA;CAGlB;;;;;CAMA,IAAI,KAAmB;EACrB,OAAO,KAAK,EAAE,IAAI,IAAI;CACxB;;;;;;;CAQA,eAA0B;EACxB,MAAM,YAAY,KAAK,EAAE,IAAI,oBAAoB,iBAAiB;EAClE,IAAI,CAAC,WACH,MAAM,IAAI,eAAe,4CAA4C;EAEvE,OAAO;CACT;;;;;;CAOA,UAAU,QAAsB;EAC9B,KAAK,EAAE,IAAI,oBAAoB,QAAQ,MAAM;CAC/C;;;;;;CAOA,YAAoB;EAElB,OADe,KAAK,EAAE,IAAI,oBAAoB,MACjC,KAAgB;CAC/B;;;;;;;;;CAUA,KAAK,MAAqB,QAAyC;EACjE,IAAI,SAAS,MACX,OAAO,KAAK,EAAE,KAAK,MAAM,UAAU,GAAG;EAExC,OAAO,KAAK,EAAE,KAAK,MAAM,MAAM;CACjC;CAkBA,MAAM,KAA+C;EACnD,MAAM,MAAO,KAAK,EAAE,IAAkF,MAAM,OAAO,KAAK,CAAC;EACzH,OAAO,QAAQ,KAAA,IAAY,MAAM,IAAI;CACvC;;;;;;CAOA,MAA2G,KAAmC;EAC5I,MAAM,YAAa,KAAK,EAAE,IAAuE,MAAM,OAAO;EAC9G,OAAO,MAAM,UAAU,OAAmC;CAC5D;;;;;;CAOA,OAAO,MAAkC;EACvC,OAAO,KAAK,EAAE,IAAI,OAAO,IAAI;CAC/B;;;;;;;;;;;;CAaA,UAAU,MAAkC;EAC1C,OAAOA,UAAc,KAAK,GAAG,IAAI;CACnC;;;;;;;;;;;;;;;;;;;;;CAsBA,UAAU,MAAc,OAAe,SAA+B;EACpE,UAAc,KAAK,GAAG,MAAM,OAAO,OAAO;CAC5C;;;;;;;;;;;;;;;;CAiBA,aAAa,MAAc,SAA6C;EACtE,OAAOC,aAAiB,KAAK,GAAG,MAAM,OAAO;CAC/C;;;;;;;CAQA,OAAsB;EAGpB,OAAQ,KAAK,EAAE,IAAyD,MAAM,MAAM;CACtF;;;;;;;CAQA,KAAK,MAAc,QAAyC;EAC1D,OAAO,KAAK,EAAE,KAAK,MAAM,MAAM;CACjC;;;;;;;CAQA,KAAK,MAAc,QAAyC;EAC1D,OAAO,KAAK,EAAE,KAAK,MAAM,MAAM;CACjC;;;;;;;;;;;;;;;;;;CAmBA,MAA2B,MAAS,QAAyB,SAA8B;EACzF,OAAO,KAAK,WAAW,EAAE,MAAM,MAAM,QAAQ,OAAO;CACtD;;;;;;;;;;;;CAaA,OAAO,KAAqB;EAC1B,OAAO,KAAK,EAAE,IAAI,UAAU,KAAK;CACnC;;;;;;;;;CAUA,MAAM,UAA+B,MAAS,QAAyB,SAA6C;EAClH,OAAO,KAAK,WAAW,EAAE,YAAY,MAAM,QAAQ,OAAO;CAC5D;;;;;;CAOA,MAAM,oBAAsC;EAC1C,OAAO,KAAK,WAAW,EAAE,kBAAkB;CAC7C;;;;;;;CAQA,SAAS,KAAa,QAAuC;EAC3D,OAAO,KAAK,EAAE,SAAS,KAAK,MAAM;CACpC;;;;;;;CAQA,OAAO,UAAmD,SAAyE;EACjI,OAAOC,OAAW,KAAK,GAAG,UAAU,OAAO;CAC7C;;;;;;;;;CAUA,WAAW,UAAmD,SAAyE;EACrI,KAAK,EAAE,OAAO,oBAAoB,UAAU;EAC5C,OAAOC,WAAe,KAAK,GAAG,UAAU,OAAO;CACjD;;;;;;;;;CAUA,UAAU,UAAsD,SAA4E;EAC1I,KAAK,EAAE,OAAO,oBAAoB,UAAU;EAC5C,OAAOC,UAAc,KAAK,GAAG,UAAU,OAAO;CAChD;CAEA,aAA0B;EACxB,OAAO,KAAK,aAAa,EAAE,QAAa,cAAc,GAAG;CAC3D;AACF;;;;;;;;;AC9RA,SAAgB,2BAA2B,GAA6C;CACtF,OAAO;EAAE,MAAM;EAAQ,KAAK,IAAI,cAAc,CAAC;CAAE;AACnD;;;;;;;AAQA,SAAgB,4BAA4B,WAA0C;CACpF,OAAO;EAAE,MAAM;EAAS;CAAU;AACpC;;;;;;AAOA,SAAgB,6BAAmD;CACjE,OAAO,EAAE,MAAM,OAAO;AACxB;;;;;;;AAQA,SAAgB,0BAA0B,aAA0C;CAClF,OAAO;EAAE,MAAM;EAAO;CAAY;AACpC"}
@@ -1,5 +1,9 @@
1
- import { H as ApplicationError, f as ROUTE_METADATA_KEYS, k as ERROR_CODES, s as RouterContext } from "./errors-COW9-Mar.mjs";
2
- import { t as Controller } from "./controller.decorator-B9vwn0zK.mjs";
1
+ import { a as ApplicationError } from "./container-storage-BmOJ4_Na.mjs";
2
+ import { n as getMetadata, t as defineMetadata } from "./metadata-DzzprcID.mjs";
3
+ import { LOGGER_TOKENS } from "./logger/index.mjs";
4
+ import "./errors-mXYxG0XB.mjs";
5
+ import { a as RouterContext, u as ROUTE_METADATA_KEYS } from "./exception-context-kEoMFwze.mjs";
6
+ import { t as Controller } from "./controller.decorator-C5UVeJS3.mjs";
3
7
  //#region src/websocket/decorators/gateway.decorator.ts
4
8
  const GATEWAY_MARKER_KEY = ROUTE_METADATA_KEYS.GATEWAY_MARKER;
5
9
  /**
@@ -33,7 +37,7 @@ const GATEWAY_MARKER_KEY = ROUTE_METADATA_KEYS.GATEWAY_MARKER;
33
37
  function Gateway(route, options) {
34
38
  return function(target) {
35
39
  Controller(route, options)(target);
36
- Reflect.defineMetadata(GATEWAY_MARKER_KEY, true, target);
40
+ defineMetadata(GATEWAY_MARKER_KEY, true, target);
37
41
  return target;
38
42
  };
39
43
  }
@@ -44,19 +48,11 @@ function Gateway(route, options) {
44
48
  * @returns true if the class is decorated with @Gateway
45
49
  */
46
50
  function isGateway(target) {
47
- const metadataTarget = typeof target === "function" ? target : target.constructor;
48
- return Reflect.getMetadata(GATEWAY_MARKER_KEY, metadataTarget) === true;
51
+ return getMetadata(GATEWAY_MARKER_KEY, typeof target === "function" ? target : target.constructor) === true;
49
52
  }
50
53
  //#endregion
51
- //#region src/websocket/errors/websocket-duplicate-event-handler.error.ts
52
- var WebSocketDuplicateEventHandlerError = class extends ApplicationError {
53
- constructor(decorator, existingMethod) {
54
- super("errors.websocketDuplicateEventHandler", ERROR_CODES.SYSTEM.WEBSOCKET_DUPLICATE_EVENT_HANDLER, {
55
- decorator,
56
- existingMethod
57
- });
58
- }
59
- };
54
+ //#region src/websocket/websocket.error.ts
55
+ var WebSocketError = class extends ApplicationError {};
60
56
  //#endregion
61
57
  //#region src/websocket/decorators/ws-event.decorator.ts
62
58
  const WS_ON_MESSAGE_KEY = ROUTE_METADATA_KEYS.WS_ON_MESSAGE;
@@ -67,9 +63,9 @@ const WS_ON_ERROR_KEY = ROUTE_METADATA_KEYS.WS_ON_ERROR;
67
63
  * Throws if a different method already owns this key (prevents silent override).
68
64
  */
69
65
  function defineSingleHandlerMetadata(key, propertyKey, target, decoratorName) {
70
- const existing = Reflect.getMetadata(key, target);
71
- if (existing !== void 0 && existing !== propertyKey) throw new WebSocketDuplicateEventHandlerError(decoratorName, String(existing));
72
- Reflect.defineMetadata(key, propertyKey, target);
66
+ const existing = getMetadata(key, target);
67
+ if (existing !== void 0 && existing !== propertyKey) throw new WebSocketError(`Duplicate @${decoratorName} handler: method "${String(existing)}" is already registered`);
68
+ defineMetadata(key, propertyKey, target);
73
69
  }
74
70
  /**
75
71
  * Marks a method as the WebSocket message handler
@@ -132,29 +128,24 @@ function OnError() {
132
128
  * Get the method name decorated with @OnMessage
133
129
  */
134
130
  function getWsOnMessageMethod(target) {
135
- return Reflect.getMetadata(WS_ON_MESSAGE_KEY, target.prototype);
131
+ return getMetadata(WS_ON_MESSAGE_KEY, target.prototype);
136
132
  }
137
133
  /**
138
134
  * Get the method name decorated with @OnClose
139
135
  */
140
136
  function getWsOnCloseMethod(target) {
141
- return Reflect.getMetadata(WS_ON_CLOSE_KEY, target.prototype);
137
+ return getMetadata(WS_ON_CLOSE_KEY, target.prototype);
142
138
  }
143
139
  /**
144
140
  * Get the method name decorated with @OnError
145
141
  */
146
142
  function getWsOnErrorMethod(target) {
147
- return Reflect.getMetadata(WS_ON_ERROR_KEY, target.prototype);
143
+ return getMetadata(WS_ON_ERROR_KEY, target.prototype);
148
144
  }
149
145
  //#endregion
150
- //#region src/websocket/errors/websocket-body-not-available.error.ts
151
- var WebSocketBodyNotAvailableError = class extends ApplicationError {
152
- constructor() {
153
- super("errors.websocketBodyNotAvailable", ERROR_CODES.SYSTEM.WEBSOCKET_BODY_NOT_AVAILABLE);
154
- }
155
- };
156
- //#endregion
157
146
  //#region src/websocket/gateway-context.ts
147
+ /** WebSocket OPEN ready state (`WSReadyState` is a type-only union in hono/ws). */
148
+ const WS_OPEN = 1;
158
149
  /**
159
150
  * WebSocket gateway context
160
151
  *
@@ -182,6 +173,22 @@ var GatewayContext = class extends RouterContext {
182
173
  send(data) {
183
174
  this.ws.send(data);
184
175
  }
176
+ /**
177
+ * Send only if the socket is still open. Returns `false` (and logs a warning)
178
+ * when the socket is closing/closed — e.g. inside `@OnError`, which fires on a
179
+ * transport error after the socket is already dead, or after an `await` in
180
+ * `@OnMessage` when the client disconnected mid-handler. Use this for
181
+ * fire-and-forget acks/errors instead of `send()`, which throws on a closed
182
+ * socket ("Can't call WebSocket send() after close()").
183
+ */
184
+ trySend(data) {
185
+ if (this.ws.readyState !== WS_OPEN) {
186
+ this.getContainer().resolve(LOGGER_TOKENS.LoggerService).warn("Skipped WebSocket send on non-open socket", { readyState: this.ws.readyState });
187
+ return false;
188
+ }
189
+ this.ws.send(data);
190
+ return true;
191
+ }
185
192
  /** Close the WebSocket connection */
186
193
  close(code, reason) {
187
194
  this.ws.close(code, reason);
@@ -206,13 +213,13 @@ var GatewayContext = class extends RouterContext {
206
213
  /**
207
214
  * Request body is not available in WebSocket gateways
208
215
  *
209
- * @throws WebSocketBodyNotAvailableError always — WebSocket upgrade requests do not have a body
216
+ * @throws WebSocketError always — WebSocket upgrade requests do not have a body
210
217
  */
211
218
  body() {
212
- throw new WebSocketBodyNotAvailableError();
219
+ throw new WebSocketError("Request body is not available in WebSocket gateways");
213
220
  }
214
221
  };
215
222
  //#endregion
216
- export { OnMessage as a, getWsOnMessageMethod as c, isGateway as d, OnError as i, WebSocketDuplicateEventHandlerError as l, WebSocketBodyNotAvailableError as n, getWsOnCloseMethod as o, OnClose as r, getWsOnErrorMethod as s, GatewayContext as t, Gateway as u };
223
+ export { getWsOnCloseMethod as a, WebSocketError as c, OnMessage as i, Gateway as l, OnClose as n, getWsOnErrorMethod as o, OnError as r, getWsOnMessageMethod as s, GatewayContext as t, isGateway as u };
217
224
 
218
- //# sourceMappingURL=gateway-context-CXmXtaUP.mjs.map
225
+ //# sourceMappingURL=gateway-context-TMu_AlJt.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-context-TMu_AlJt.mjs","names":[],"sources":["../src/websocket/decorators/gateway.decorator.ts","../src/websocket/websocket.error.ts","../src/websocket/decorators/ws-event.decorator.ts","../src/websocket/gateway-context.ts"],"sourcesContent":["import { defineMetadata, getMetadata } from '../../di/metadata'\nimport { ROUTE_METADATA_KEYS } from '../../router/constants'\nimport { Controller } from '../../router/decorators/controller.decorator'\nimport { type Constructor } from '../../types'\nimport type { GatewayOptions } from '../../websocket/types'\n\nconst GATEWAY_MARKER_KEY = ROUTE_METADATA_KEYS.GATEWAY_MARKER\n\n/**\n * Gateway decorator for WebSocket route registration\n *\n * Marks a class as a WebSocket gateway and stores route metadata.\n * Reuses the same metadata key as @Controller for middleware compatibility —\n * `getControllerRoute()`, `forRoutes()`, and the entire middleware system work\n * with zero changes.\n *\n * @param route - WebSocket route path (e.g., '/ws/chat')\n *\n * @example\n * ```typescript\n * import { type GatewayContext, Gateway, OnMessage, OnClose } from 'stratal/websocket'\n *\n * @Gateway('/ws/chat')\n * class ChatGateway {\n * @OnMessage()\n * handleMessage(evt: MessageEvent, ctx: GatewayContext) {\n * ctx.send('ack')\n * }\n *\n * @OnClose()\n * handleClose(evt: CloseEvent, ctx: GatewayContext) {\n * console.log('closed')\n * }\n * }\n * ```\n */\nexport function Gateway(route: string, options?: GatewayOptions) {\n return function <T extends Constructor>(target: T) {\n Controller(route, options)(target)\n defineMetadata(GATEWAY_MARKER_KEY, true, target)\n return target\n }\n}\n\n/**\n * Check if a class is a WebSocket gateway\n *\n * @param target - Class constructor or instance\n * @returns true if the class is decorated with @Gateway\n */\nexport function isGateway(target: object): boolean {\n const metadataTarget = typeof target === 'function' ? target : (target as { constructor: object }).constructor\n return getMetadata(GATEWAY_MARKER_KEY, metadataTarget) === true\n}\n","import { ApplicationError } from '../errors'\n\nexport class WebSocketError extends ApplicationError {}\n","import { defineMetadata, getMetadata } from '../../di/metadata'\nimport { ROUTE_METADATA_KEYS } from '../../router/constants'\nimport type { Constructor } from '../../types'\nimport { WebSocketError } from '../websocket.error'\n\nconst WS_ON_MESSAGE_KEY = ROUTE_METADATA_KEYS.WS_ON_MESSAGE\nconst WS_ON_CLOSE_KEY = ROUTE_METADATA_KEYS.WS_ON_CLOSE\nconst WS_ON_ERROR_KEY = ROUTE_METADATA_KEYS.WS_ON_ERROR\n\n/**\n * Define a single-handler metadata key on the prototype.\n * Throws if a different method already owns this key (prevents silent override).\n */\nfunction defineSingleHandlerMetadata(key: symbol, propertyKey: string | symbol, target: object, decoratorName: string): void {\n const existing = getMetadata<string | symbol>(key, target)\n if (existing !== undefined && existing !== propertyKey) {\n throw new WebSocketError(`Duplicate @${decoratorName} handler: method \"${String(existing)}\" is already registered`)\n }\n defineMetadata(key, propertyKey, target)\n}\n\n/**\n * Marks a method as the WebSocket message handler\n *\n * @example\n * ```typescript\n * @Gateway('/ws/chat')\n * class ChatGateway {\n * @OnMessage()\n * handleMessage(evt: MessageEvent, ctx: GatewayContext) {\n * ctx.send(evt.data)\n * }\n * }\n * ```\n */\nexport function OnMessage(): MethodDecorator {\n // `_target` is the class prototype (method decorator convention).\n // The getter functions below read from `target.prototype` symmetrically.\n return (_target: object, propertyKey: string | symbol) => {\n defineSingleHandlerMetadata(WS_ON_MESSAGE_KEY, propertyKey, _target, 'OnMessage')\n }\n}\n\n/**\n * Marks a method as the WebSocket close handler\n *\n * @example\n * ```typescript\n * @Gateway('/ws/chat')\n * class ChatGateway {\n * @OnClose()\n * handleClose(evt: CloseEvent, ctx: GatewayContext) {\n * console.log('closed')\n * }\n * }\n * ```\n */\nexport function OnClose(): MethodDecorator {\n return (_target: object, propertyKey: string | symbol) => {\n defineSingleHandlerMetadata(WS_ON_CLOSE_KEY, propertyKey, _target, 'OnClose')\n }\n}\n\n/**\n * Marks a method as the WebSocket error handler\n *\n * @example\n * ```typescript\n * @Gateway('/ws/chat')\n * class ChatGateway {\n * @OnError()\n * handleError(evt: Event, ctx: GatewayContext) {\n * console.error('WebSocket error', evt)\n * }\n * }\n * ```\n */\nexport function OnError(): MethodDecorator {\n return (_target: object, propertyKey: string | symbol) => {\n defineSingleHandlerMetadata(WS_ON_ERROR_KEY, propertyKey, _target, 'OnError')\n }\n}\n\n/**\n * Get the method name decorated with @OnMessage\n */\nexport function getWsOnMessageMethod(target: Constructor): string | undefined {\n return getMetadata<string>(WS_ON_MESSAGE_KEY, target.prototype as object)\n}\n\n/**\n * Get the method name decorated with @OnClose\n */\nexport function getWsOnCloseMethod(target: Constructor): string | undefined {\n return getMetadata<string>(WS_ON_CLOSE_KEY, target.prototype as object)\n}\n\n/**\n * Get the method name decorated with @OnError\n */\nexport function getWsOnErrorMethod(target: Constructor): string | undefined {\n return getMetadata<string>(WS_ON_ERROR_KEY, target.prototype as object)\n}\n","import type { Context } from 'hono'\nimport type { WSContext, WSReadyState } from 'hono/ws'\nimport { LOGGER_TOKENS, type LoggerService } from '../logger'\nimport type { ContextQueryResult } from '../router/router-context'\nimport { RouterContext } from '../router/router-context'\nimport type { RouterEnv } from '../router/types'\nimport { WebSocketError } from './websocket.error'\n\n/** WebSocket OPEN ready state (`WSReadyState` is a type-only union in hono/ws). */\nconst WS_OPEN = 1\n\n/**\n * WebSocket gateway context\n *\n * Extends RouterContext with WebSocket-specific methods.\n * Inherits `getContainer()`, `param()`, `query()`, `header()`, `getLocale()`\n * from RouterContext. HTTP response methods (`json()`, `redirect()`, etc.) are\n * inherited but harmless post-upgrade.\n *\n * @example\n * ```typescript\n * @OnMessage()\n * handleMessage(evt: MessageEvent, ctx: GatewayContext) {\n * ctx.send('ack') // convenience method\n * ctx.header('Authorization') // upgrade request headers\n * }\n * ```\n */\nexport class GatewayContext extends RouterContext {\n constructor(c: Context<RouterEnv>, public readonly ws: WSContext) {\n super(c)\n }\n\n /** Send data through the WebSocket connection */\n send(data: string | ArrayBuffer | Uint8Array<ArrayBuffer>): void {\n this.ws.send(data)\n }\n\n /**\n * Send only if the socket is still open. Returns `false` (and logs a warning)\n * when the socket is closing/closed — e.g. inside `@OnError`, which fires on a\n * transport error after the socket is already dead, or after an `await` in\n * `@OnMessage` when the client disconnected mid-handler. Use this for\n * fire-and-forget acks/errors instead of `send()`, which throws on a closed\n * socket (\"Can't call WebSocket send() after close()\").\n */\n trySend(data: string | ArrayBuffer | Uint8Array<ArrayBuffer>): boolean {\n if (this.ws.readyState !== WS_OPEN) {\n this.getContainer()\n .resolve<LoggerService>(LOGGER_TOKENS.LoggerService)\n .warn('Skipped WebSocket send on non-open socket', { readyState: this.ws.readyState })\n return false\n }\n this.ws.send(data)\n return true\n }\n\n /** Close the WebSocket connection */\n close(code?: number, reason?: string): void {\n this.ws.close(code, reason)\n }\n\n /** Current WebSocket ready state */\n get readyState(): WSReadyState {\n return this.ws.readyState\n }\n\n /**\n * Get route parameter value(s) from the raw request — WebSocket gateways are\n * not OpenAPI-registered, so reads come straight from Hono's matcher.\n *\n * - With a key → single string value.\n * - With no args → full `Record<string, string>` (or `{}` when none).\n *\n * @param key - Parameter name (e.g., 'id' for /ws/chat/:id)\n */\n override param(): Record<string, string>\n override param(key: string): string\n override param(key?: string): string | Record<string, string> {\n if (key === undefined) return this.c.req.param() ?? {}\n return this.c.req.param(key)!\n }\n\n /**\n * Get query parameter value from the raw request (no OpenAPI validation)\n *\n * @param key - Query parameter name\n */\n override query<R extends Record<string, unknown> | undefined = undefined, K extends string | undefined = undefined>(key?: K): ContextQueryResult<R, K> {\n if (key) {\n return this.c.req.query(key) as ContextQueryResult<R, K>\n }\n return this.c.req.query() as ContextQueryResult<R, K>\n }\n\n /**\n * Request body is not available in WebSocket gateways\n *\n * @throws WebSocketError always — WebSocket upgrade requests do not have a body\n */\n override body<T>(): Promise<T> {\n throw new WebSocketError('Request body is not available in WebSocket gateways')\n }\n}\n"],"mappings":";;;;;;;AAMA,MAAM,qBAAqB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8B/C,SAAgB,QAAQ,OAAe,SAA0B;CAC/D,OAAO,SAAiC,QAAW;EACjD,WAAW,OAAO,OAAO,EAAE,MAAM;EACjC,eAAe,oBAAoB,MAAM,MAAM;EAC/C,OAAO;CACT;AACF;;;;;;;AAQA,SAAgB,UAAU,QAAyB;CAEjD,OAAO,YAAY,oBADI,OAAO,WAAW,aAAa,SAAU,OAAmC,WAC9C,MAAM;AAC7D;;;ACnDA,IAAa,iBAAb,cAAoC,iBAAiB,CAAC;;;ACGtD,MAAM,oBAAoB,oBAAoB;AAC9C,MAAM,kBAAkB,oBAAoB;AAC5C,MAAM,kBAAkB,oBAAoB;;;;;AAM5C,SAAS,4BAA4B,KAAa,aAA8B,QAAgB,eAA6B;CAC3H,MAAM,WAAW,YAA6B,KAAK,MAAM;CACzD,IAAI,aAAa,KAAA,KAAa,aAAa,aACzC,MAAM,IAAI,eAAe,cAAc,cAAc,oBAAoB,OAAO,QAAQ,EAAE,wBAAwB;CAEpH,eAAe,KAAK,aAAa,MAAM;AACzC;;;;;;;;;;;;;;;AAgBA,SAAgB,YAA6B;CAG3C,QAAQ,SAAiB,gBAAiC;EACxD,4BAA4B,mBAAmB,aAAa,SAAS,WAAW;CAClF;AACF;;;;;;;;;;;;;;;AAgBA,SAAgB,UAA2B;CACzC,QAAQ,SAAiB,gBAAiC;EACxD,4BAA4B,iBAAiB,aAAa,SAAS,SAAS;CAC9E;AACF;;;;;;;;;;;;;;;AAgBA,SAAgB,UAA2B;CACzC,QAAQ,SAAiB,gBAAiC;EACxD,4BAA4B,iBAAiB,aAAa,SAAS,SAAS;CAC9E;AACF;;;;AAKA,SAAgB,qBAAqB,QAAyC;CAC5E,OAAO,YAAoB,mBAAmB,OAAO,SAAmB;AAC1E;;;;AAKA,SAAgB,mBAAmB,QAAyC;CAC1E,OAAO,YAAoB,iBAAiB,OAAO,SAAmB;AACxE;;;;AAKA,SAAgB,mBAAmB,QAAyC;CAC1E,OAAO,YAAoB,iBAAiB,OAAO,SAAmB;AACxE;;;;AC7FA,MAAM,UAAU;;;;;;;;;;;;;;;;;;AAmBhB,IAAa,iBAAb,cAAoC,cAAc;CACG;CAAnD,YAAY,GAAuB,IAA+B;EAChE,MAAM,CAAC;EAD0C,KAAA,KAAA;CAEnD;;CAGA,KAAK,MAA4D;EAC/D,KAAK,GAAG,KAAK,IAAI;CACnB;;;;;;;;;CAUA,QAAQ,MAA+D;EACrE,IAAI,KAAK,GAAG,eAAe,SAAS;GAClC,KAAK,aAAa,EACf,QAAuB,cAAc,aAAa,EAClD,KAAK,6CAA6C,EAAE,YAAY,KAAK,GAAG,WAAW,CAAC;GACvF,OAAO;EACT;EACA,KAAK,GAAG,KAAK,IAAI;EACjB,OAAO;CACT;;CAGA,MAAM,MAAe,QAAuB;EAC1C,KAAK,GAAG,MAAM,MAAM,MAAM;CAC5B;;CAGA,IAAI,aAA2B;EAC7B,OAAO,KAAK,GAAG;CACjB;CAaA,MAAe,KAA+C;EAC5D,IAAI,QAAQ,KAAA,GAAW,OAAO,KAAK,EAAE,IAAI,MAAM,KAAK,CAAC;EACrD,OAAO,KAAK,EAAE,IAAI,MAAM,GAAG;CAC7B;;;;;;CAOA,MAAoH,KAAmC;EACrJ,IAAI,KACF,OAAO,KAAK,EAAE,IAAI,MAAM,GAAG;EAE7B,OAAO,KAAK,EAAE,IAAI,MAAM;CAC1B;;;;;;CAOA,OAA+B;EAC7B,MAAM,IAAI,eAAe,qDAAqD;CAChF;AACF"}
@@ -1,6 +1,6 @@
1
- import { Dr as Container, V as RouterContext } from "../index-ByOyTmqf.mjs";
2
- import { t as Constructor } from "../types-cySNS_lp.mjs";
3
- import { i as LoggerService } from "../index-DBd_2wv8.mjs";
1
+ import { Y as Container, rt as RouterContext } from "../index-B_JoEl3V.mjs";
2
+ import { r as LoggerService } from "../index-BUt92sAE.mjs";
3
+ import { t as Constructor } from "../types-CmV_9xBD.mjs";
4
4
 
5
5
  //#region src/guards/types.d.ts
6
6
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/guards/types.ts","../../src/guards/use-guards.decorator.ts","../../src/guards/guard-execution.service.ts"],"mappings":";;;;;;;;AAqBA;;;;;;;;;;AAaA;;;;;UAbiB,WAAA;EAmBA;;;;AAKjB;;EAjBE,WAAA,CAAY,OAAA,EAAS,aAAA,aAA0B,OAAA;AAAA;;AAsCjD;;KAhCY,UAAA,GAAa,WAAA,CAAY,WAAA;;;AAuCrC;;KAjCY,KAAA,GAAQ,UAAA,GAAa,WAAA;;;;UAKhB,gBAAA;;ACYjB;;;;;;;;;;;;;EDGE,WAAA;AAAA;;;;UAMe,aAAA;EACf,MAAA,EAAQ,KAAA;AAAA;;;;cAMG,kBAAA;;;;;;;AApDb;;;;;;;;;;AAaA;;;;;AAMA;;;;;AAKA;;;;;AAqBA;;;;;AAOA;;;;;;;;AChBA;;;;;;;;;;;;;iBAAgB,SAAA,CAAA,GAAa,MAAA,EAAQ,KAAA,KAAU,cAAA,GAAiB,eAAA;AAoBhE;;;;;AAWA;AAXA,iBAAgB,mBAAA,CAAoB,MAAA,WAAiB,aAAA;;;;;;;;iBAWrC,eAAA,CAAgB,MAAA,UAAgB,WAAA,oBAA+B,aAAA;;;;ADnE/E;;;;;cEVa,qBAAA;EAAA,iBACkB,MAAA;cAAA,MAAA,EAAQ,aAAA;EFgBiB;;AAMxD;;;;;AAMA;;EEjBQ,aAAA,CACJ,MAAA,EAAQ,KAAA,IACR,OAAA,EAAS,aAAA,EACT,SAAA,EAAW,SAAA,GACV,OAAA;EFae;;AAKpB;;;;;EALoB,QE2BV,YAAA;EFDoB;;;EAAA,QEcpB,eAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/guards/types.ts","../../src/guards/use-guards.decorator.ts","../../src/guards/guard-execution.service.ts"],"mappings":";;;;;;;;AAqBA;;;;;;;;;AAOwD;AAMxD;;;;AAAgD;UAb/B,WAAA;EAmBA;;;AAA2B;AAK5C;;EAjBE,WAAA,CAAY,OAAA,EAAS,aAAA,aAA0B,OAAO;AAAA;AAgC3C;AAMb;;AANa,KA1BD,UAAA,GAAa,WAAW,CAAC,WAAA;;AAiCtB;AAMf;;KAjCY,KAAA,GAAQ,UAAA,GAAa,WAAW;;AAiCkB;;UA5B7C,gBAAA;;ACajB;;;;;;;;;;;;;EDEE,WAAW;AAAA;;;;UAMI,aAAA;EACf,MAAA,EAAQ,KAAK;AAAA;;;;cAMF,kBAAA;;;;;;;AApDb;;;;;;;;;AAOwD;AAMxD;;;;AAAgD;AAMhD;;;;AAA4C;AAK5C;;;;AAea;AAMb;;;;AACe;AAMf;;;;AAA8D;;;;ACf9D;;;;;;;;;;;;;iBAAgB,SAAA,IAAa,MAAA,EAAQ,KAAA,KAAU,cAAA,GAAiB,eAAA;AAoBhE;;;;AAAkE;AAWlE;AAXA,iBAAgB,mBAAA,CAAoB,MAAA,WAAiB,aAAa;;;;;;;AAW0B;iBAA5E,eAAA,CAAgB,MAAA,UAAgB,WAAA,oBAA+B,aAAa;;;;ADpE5F;;;;;cEVa,qBAAA;EAAA,iBACkB,MAAA;cAAA,MAAA,EAAQ,aAAA;EFgBiB;AAAA;AAMxD;;;;AAAgD;AAMhD;;EEjBQ,aAAA,CACJ,MAAA,EAAQ,KAAA,IACR,OAAA,EAAS,aAAA,EACT,SAAA,EAAW,SAAA,GACV,OAAA;EFae;AAAwB;AAK5C;;;;AAea;EApBO,QE2BV,YAAA;EFDoB;;;EAAA,QEcpB,eAAA;AAAA"}
@@ -1,2 +1,2 @@
1
- import { a as GUARD_METADATA_KEY, i as getMethodGuards, n as UseGuards, r as getControllerGuards, t as GuardExecutionService } from "../guards-DU1_J9YA.mjs";
1
+ import { a as GUARD_METADATA_KEY, i as getMethodGuards, n as UseGuards, r as getControllerGuards, t as GuardExecutionService } from "../guards-DALPXy3_.mjs";
2
2
  export { GUARD_METADATA_KEY, GuardExecutionService, UseGuards, getControllerGuards, getMethodGuards };