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 @@
1
+ {"version":3,"file":"storage-MDZypIE9.mjs","names":[],"sources":["../src/storage/storage.tokens.ts","../src/storage/services/storage-manager.service.ts","../src/storage/services/storage.service.ts","../src/storage/storage.module.ts","../src/storage/errors/file-not-found.error.ts","../src/storage/controllers/storage.controller.ts","../src/storage/contracts/delete-file.input.ts","../src/storage/contracts/file-exists.input.ts","../src/storage/contracts/get-presigned-url.input.ts","../src/storage/contracts/upload-file.input.ts","../src/storage/errors/file-too-large.error.ts","../src/storage/errors/invalid-file-type.error.ts"],"sourcesContent":["/**\n * Dependency injection tokens for the Storage module\n * Using Symbol-based tokens to avoid magic strings\n */\nexport const STORAGE_TOKENS = {\n Options: Symbol.for('stratal:storage:options'),\n StorageService: Symbol.for('stratal:storage:service'),\n StorageManager: Symbol.for('stratal:storage:manager'),\n} as const\n","import { inject } from '../../di'\nimport { Singleton } from '../../di/decorators'\nimport { DI_TOKENS } from '../../di/tokens'\nimport { type StratalEnv } from '../../env'\nimport { StorageError } from '../storage.error'\nimport type { IStorageProvider } from '../providers/storage-provider.interface'\nimport { STORAGE_TOKENS } from '../storage.tokens'\nimport type { StorageConfig, StorageEntry } from '../types'\n\n/**\n * Storage Manager Service\n * Manages multiple storage providers (one per disk)\n * Handles lazy initialization and caching of R2 providers\n */\n@Singleton(STORAGE_TOKENS.StorageManager)\nexport class StorageManagerService {\n private readonly providers = new Map<string, IStorageProvider>()\n private readonly creationPromises = new Map<string, Promise<IStorageProvider>>()\n private readonly diskConfigs = new Map<string, StorageEntry>()\n\n constructor(\n @inject(STORAGE_TOKENS.Options)\n private readonly options: StorageConfig,\n @inject(DI_TOKENS.CloudflareEnv)\n private readonly env: StratalEnv\n ) {\n this.initializeDiskConfigs()\n }\n\n /**\n * Initialize disk configurations from options\n */\n private initializeDiskConfigs(): void {\n for (const entry of this.options.storage) {\n this.diskConfigs.set(entry.disk, entry)\n }\n }\n\n /**\n * Get provider for a specific disk\n * Lazily initializes provider on first access\n * @param diskName - Name of the disk\n * @returns Storage provider instance\n */\n async getProvider(diskName: string): Promise<IStorageProvider> {\n // Return cached provider if exists\n const cached = this.providers.get(diskName)\n if (cached) {\n return cached\n }\n\n // Return in-flight creation promise to deduplicate concurrent calls\n const inflight = this.creationPromises.get(diskName)\n if (inflight) {\n return inflight\n }\n\n // Get disk configuration\n const diskConfig = this.diskConfigs.get(diskName)\n if (!diskConfig) {\n throw new StorageError(`Disk \"${diskName}\" is not configured`)\n }\n\n // Create provider and deduplicate concurrent calls\n const promise = this.createProvider(diskConfig).then((provider) => {\n this.providers.set(diskName, provider)\n this.creationPromises.delete(diskName)\n return provider\n }).catch((error: unknown) => {\n this.creationPromises.delete(diskName)\n throw error\n })\n\n this.creationPromises.set(diskName, promise)\n\n return promise\n }\n\n /**\n * Create an R2 provider instance\n * Dynamically imports R2StorageProvider to support code splitting\n * @param config - Storage entry configuration\n * @returns Storage provider instance\n */\n private async createProvider(config: StorageEntry): Promise<IStorageProvider> {\n const { R2StorageProvider } = await import('../providers/r2-storage.provider')\n const bucket = this.env[config.binding as keyof StratalEnv] as unknown as R2Bucket | undefined\n if (!bucket) {\n throw new StorageError(`R2 binding \"${config.binding}\" was not found in the environment`)\n }\n return new R2StorageProvider(config, bucket, this.env, this.options.route)\n }\n\n /**\n * Get disk configuration\n * @param diskName - Name of the disk\n * @returns Storage entry configuration\n */\n getDiskConfig(diskName: string): StorageEntry {\n const config = this.diskConfigs.get(diskName)\n if (!config) {\n throw new StorageError(`Disk \"${diskName}\" is not configured`)\n }\n return config\n }\n\n /**\n * Check if a disk exists\n * @param diskName - Name of the disk\n * @returns True if disk exists, false otherwise\n */\n hasDisk(diskName: string): boolean {\n return this.diskConfigs.has(diskName)\n }\n\n /**\n * Get all available disk names\n * @returns Array of disk names\n */\n getAvailableDisks(): string[] {\n return Array.from(this.diskConfigs.keys())\n }\n}\n","import { inject } from '../../di'\nimport { Request } from '../../di/decorators'\nimport type { DownloadResult, PresignedUrlResult, UploadOptions, UploadResult } from '../contracts'\nimport { StorageError } from '../storage.error'\nimport type { StreamingBlobPayloadInputTypes } from '../providers/storage-provider.interface'\nimport { STORAGE_TOKENS } from '../storage.tokens'\nimport type { StorageConfig } from '../types'\nimport { type StorageManagerService } from './storage-manager.service'\n\n/**\n * Storage Service\n *\n * Main facade for storage operations.\n * Request-scoped for proper isolation.\n *\n * @example\n * ```typescript\n * @inject(STORAGE_TOKENS.StorageService)\n * private readonly storage: StorageService\n *\n * await this.storage.upload(file, 'documents/report.pdf')\n * ```\n */\n@Request(STORAGE_TOKENS.StorageService)\nexport class StorageService {\n constructor(\n @inject(STORAGE_TOKENS.StorageManager)\n protected readonly storageManager: StorageManagerService,\n @inject(STORAGE_TOKENS.Options)\n protected readonly options: StorageConfig\n ) { }\n\n /**\n * Upload content to storage\n * @param body - Content to upload (stream, buffer, or string)\n * @param relativePath - Relative path within the disk\n * @param options - Upload options including size and mime type\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Upload result with metadata\n */\n async upload(\n body: StreamingBlobPayloadInputTypes,\n relativePath: string,\n options: UploadOptions,\n disk?: string\n ): Promise<UploadResult> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n return provider.upload(body, fullPath, options)\n }\n\n /**\n * Download a file from storage\n * @param relativePath - Relative path within the disk\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Download result with stream and metadata\n */\n async download(relativePath: string, disk?: string): Promise<DownloadResult> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n return provider.download(fullPath)\n }\n\n /**\n * Delete a file from storage\n * @param relativePath - Relative path within the disk\n * @param disk - Optional disk name (uses default if not provided)\n */\n async delete(relativePath: string, disk?: string): Promise<void> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n await provider.delete(fullPath)\n }\n\n /**\n * Check if a file exists in storage\n * @param relativePath - Relative path within the disk\n * @param disk - Optional disk name (uses default if not provided)\n * @returns True if file exists, false otherwise\n */\n async exists(relativePath: string, disk?: string): Promise<boolean> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n return provider.exists(fullPath)\n }\n\n /**\n * Generate a presigned download URL\n * @param relativePath - Relative path within the disk\n * @param expiresIn - Optional expiry time in seconds (uses default if not provided)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Presigned URL result\n */\n async getPresignedDownloadUrl(\n relativePath: string,\n expiresIn?: number,\n disk?: string\n ): Promise<PresignedUrlResult> {\n return this.getPresignedUrl(relativePath, 'GET', expiresIn, disk)\n }\n\n /**\n * Generate a presigned upload URL\n * @param relativePath - Relative path within the disk\n * @param expiresIn - Optional expiry time in seconds (uses default if not provided)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Presigned URL result\n */\n async getPresignedUploadUrl(\n relativePath: string,\n expiresIn?: number,\n disk?: string\n ): Promise<PresignedUrlResult> {\n return this.getPresignedUrl(relativePath, 'PUT', expiresIn, disk)\n }\n\n /**\n * Generate a presigned delete URL\n * @param relativePath - Relative path within the disk\n * @param expiresIn - Optional expiry time in seconds (uses default if not provided)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Presigned URL result\n */\n async getPresignedDeleteUrl(\n relativePath: string,\n expiresIn?: number,\n disk?: string\n ): Promise<PresignedUrlResult> {\n return this.getPresignedUrl(relativePath, 'DELETE', expiresIn, disk)\n }\n\n /**\n * Generate a presigned URL for any method\n * @param relativePath - Relative path within the disk\n * @param method - HTTP method (GET, PUT, DELETE, HEAD)\n * @param expiresIn - Optional expiry time in seconds (uses default if not provided)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Presigned URL result\n */\n protected async getPresignedUrl(\n relativePath: string,\n method: 'GET' | 'PUT' | 'DELETE' | 'HEAD',\n expiresIn?: number,\n disk?: string\n ): Promise<PresignedUrlResult> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n const validatedExpiresIn = this.validateExpiresIn(expiresIn)\n\n return provider.getPresignedUrl(fullPath, method, validatedExpiresIn)\n }\n\n /**\n * Resolve disk name (use default if not provided)\n * @param disk - Optional disk name\n * @returns Resolved disk name\n */\n protected resolveDisk(disk?: string): string {\n const diskName = disk ?? this.options.defaultStorageDisk\n\n if (!this.storageManager.hasDisk(diskName)) {\n throw new StorageError(`Disk \"${diskName}\" is not configured`)\n }\n\n return diskName\n }\n\n /**\n * Build full path with disk root and path template substitution\n * @param relativePath - Relative path within the disk\n * @param diskName - Name of the disk\n * @returns Full path including disk root\n */\n protected buildFullPath(relativePath: string, diskName: string): string {\n const diskConfig = this.storageManager.getDiskConfig(diskName)\n let root = diskConfig.root || ''\n\n // Substitute template variables\n root = this.substituteTemplateVariables(root)\n\n // Combine root and relative path\n const fullPath = `${root}/${relativePath}`.replace(/\\/+/g, '/').replace(/^\\//, '')\n\n return fullPath\n }\n\n /**\n * Substitute template variables in path\n * Override this method in subclasses to add custom substitutions\n *\n * @param path - Path with template variables\n * @returns Path with substituted variables\n */\n protected substituteTemplateVariables(path: string): string {\n let result = path\n\n // Substitute {date}, {year}, {month}\n const now = new Date()\n result = result.replace(/{date}/g, now.toISOString().split('T')[0])\n result = result.replace(/{year}/g, now.getFullYear().toString())\n result = result.replace(/{month}/g, (now.getMonth() + 1).toString().padStart(2, '0'))\n\n return result\n }\n\n /**\n * Validate expiry time for presigned URLs\n * @param expiresIn - Optional expiry time in seconds\n * @returns Validated expiry time\n */\n protected validateExpiresIn(expiresIn?: number): number {\n const presignedUrlConfig = this.options.presignedUrl\n const validatedExpiresIn = expiresIn ?? presignedUrlConfig.defaultExpiry\n\n const minExpiry = 1\n const maxExpiry = presignedUrlConfig.maxExpiry\n\n if (validatedExpiresIn < minExpiry || validatedExpiresIn > maxExpiry) {\n throw new StorageError(`Presigned URL expiry ${validatedExpiresIn}s is out of range (${minExpiry}–${maxExpiry}s)`)\n }\n\n return validatedExpiresIn\n }\n\n /**\n * Get all available disk names\n * @returns Array of disk names\n */\n getAvailableDisks(): string[] {\n return this.storageManager.getAvailableDisks()\n }\n\n /**\n * Chunked upload for streaming data without known size\n * Uses multipart upload under the hood - handles retries and large files\n *\n * Use this method when:\n * - Content-Length is unknown or unreliable\n * - Uploading from streams that can't be rewound\n * - Need automatic retry handling for transient failures\n *\n * @param body - Content to upload (stream or buffer)\n * @param relativePath - Relative path within the disk\n * @param options - Upload options (mimeType required, size optional)\n * @param disk - Optional disk name (uses default if not provided)\n * @returns Upload result with metadata\n */\n async chunkedUpload(\n body: StreamingBlobPayloadInputTypes,\n relativePath: string,\n options: Omit<UploadOptions, 'size'> & { size?: number },\n disk?: string\n ): Promise<UploadResult> {\n const diskName = this.resolveDisk(disk)\n const provider = await this.storageManager.getProvider(diskName)\n const fullPath = this.buildFullPath(relativePath, diskName)\n\n return provider.chunkedUpload(body, fullPath, options)\n }\n}\n","/**\n * Storage Module\n * Provides file storage capabilities using Cloudflare R2\n * Supports multiple disk configurations with dynamic path templates\n */\n\nimport { Module } from '../module'\nimport type { AsyncModuleOptions, DynamicModule } from '../module/types'\nimport { StorageManagerService } from './services/storage-manager.service'\nimport { StorageService } from './services/storage.service'\nimport { STORAGE_TOKENS } from './storage.tokens'\nimport type { StorageConfig } from './types'\n\n/**\n * Storage module options\n * Same as StorageConfig from types.ts\n */\nexport type StorageModuleOptions = StorageConfig\n\n@Module({\n providers: [\n { provide: STORAGE_TOKENS.StorageManager, useClass: StorageManagerService },\n { provide: STORAGE_TOKENS.StorageService, useClass: StorageService },\n ],\n})\nexport class StorageModule {\n /**\n * Configure StorageModule with static options\n *\n * @example\n * ```typescript\n * StorageModule.forRoot({\n * storage: [{ disk: 'uploads', binding: 'MY_BUCKET', root: 'uploads' }],\n * defaultStorageDisk: 'uploads',\n * presignedUrl: { defaultExpiry: 3600, maxExpiry: 86400 }\n * })\n * ```\n */\n static forRoot(options: StorageModuleOptions): DynamicModule {\n return {\n module: StorageModule,\n providers: [\n { provide: STORAGE_TOKENS.Options, useValue: options },\n ],\n }\n }\n\n /**\n * Configure StorageModule with async factory\n *\n * Use when configuration depends on other services.\n *\n * @example\n * ```typescript\n * StorageModule.forRootAsync({\n * inject: [storageConfig.KEY],\n * useFactory: (storage) => ({\n * storage: storage.storage,\n * defaultStorageDisk: storage.defaultStorageDisk,\n * presignedUrl: storage.presignedUrl\n * })\n * })\n * ```\n */\n static forRootAsync(options: AsyncModuleOptions<StorageModuleOptions>): DynamicModule {\n return {\n module: StorageModule,\n providers: [\n {\n provide: STORAGE_TOKENS.Options,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n ],\n }\n }\n}\n","import { HttpException } from '../../errors'\n\nexport class FileNotFoundError extends HttpException {\n constructor(path?: string) {\n super(404, path ? `File not found: \"${path}\"` : 'File not found')\n }\n}\n","import { inject } from '../../di'\nimport { z } from '../../i18n/validation'\nimport { Controller } from '../../router/decorators/controller.decorator'\nimport { Delete, Get, Put } from '../../router/decorators/http-method.decorator'\nimport { type RouterContext } from '../../router/router-context'\nimport { FileNotFoundError } from '../errors/file-not-found.error'\nimport type { StorageService } from '../services/storage.service'\nimport { STORAGE_TOKENS } from '../storage.tokens'\n\nconst diskParam = z.object({\n disk: z.string(),\n})\n\n/**\n * Storage Controller\n *\n * Auto-registered controller that proxies R2 operations behind signed URLs.\n * Signature verification is applied via VerifySignatureMiddleware on the module's\n * configureRoutes() method.\n *\n * Routes:\n * - GET /storage/:disk/* → download file\n * - PUT /storage/:disk/* → upload file\n * - DELETE /storage/:disk/* → delete file\n */\n@Controller('/storage', { hideFromDocs: true })\nexport class StorageController {\n constructor(\n @inject(STORAGE_TOKENS.StorageService)\n private readonly storage: StorageService\n ) {}\n\n @Get('/:disk/*', { hideFromDocs: true, params: diskParam })\n async download(ctx: RouterContext): Promise<Response> {\n const disk = ctx.param('disk')\n const path = extractWildcardPath(ctx)\n const result = await this.storage.download(path, disk)\n\n const stream = result.toStream()\n if (!stream) {\n throw new FileNotFoundError(path)\n }\n\n return new Response(stream, {\n headers: {\n 'Content-Type': result.contentType,\n 'Content-Length': String(result.size),\n 'Content-Disposition': 'inline',\n },\n })\n }\n\n @Put('/:disk/*', { hideFromDocs: true, params: diskParam })\n async upload(ctx: RouterContext): Promise<Response> {\n const disk = ctx.param('disk')\n const path = extractWildcardPath(ctx)\n\n const body = ctx.c.req.raw.body\n const contentType = ctx.header('content-type') ?? 'application/octet-stream'\n const contentLength = ctx.header('content-length')\n\n await this.storage.upload(body, path, {\n mimeType: contentType,\n size: contentLength ? parseInt(contentLength, 10) : 0,\n }, disk)\n\n return ctx.json({ path, disk }, 200)\n }\n\n @Delete('/:disk/*', { hideFromDocs: true, params: diskParam })\n async destroy(ctx: RouterContext): Promise<Response> {\n const disk = ctx.param('disk')\n const path = extractWildcardPath(ctx)\n\n await this.storage.delete(path, disk)\n\n return ctx.c.body(null, 204)\n }\n}\n\n/**\n * Extract the wildcard path from the Hono context.\n * Hono stores wildcard params under the key matching the path pattern.\n */\nfunction extractWildcardPath(ctx: RouterContext): string {\n // Hono exposes wildcard capture as the raw path after the matched prefix\n const url = new URL(ctx.c.req.url)\n const fullPath = url.pathname\n // Remove /storage/:disk/ prefix to get the file path\n const parts = fullPath.split('/')\n // ['', 'storage', 'disk', ...rest]\n return parts.slice(3).join('/')\n}\n","import { z, withZodI18n } from '../../i18n/validation'\n\nexport const deleteFileInputSchema = z.object({\n path: z.string().min(1, withZodI18n('zodI18n.errors.custom.filePathRequired')),\n disk: z.string().optional(),\n})\n\nexport type DeleteFileInput = z.infer<typeof deleteFileInputSchema>\n","import { z, withZodI18n } from '../../i18n/validation'\n\nexport const fileExistsInputSchema = z.object({\n path: z.string().min(1, withZodI18n('zodI18n.errors.custom.filePathRequired')),\n disk: z.string().optional(),\n})\n\nexport type FileExistsInput = z.infer<typeof fileExistsInputSchema>\n","import { z, withZodI18n } from '../../i18n/validation'\n\nexport const getPresignedUrlInputSchema = z.object({\n path: z.string().min(1, withZodI18n('zodI18n.errors.custom.filePathRequired')),\n method: z.enum(['GET', 'PUT', 'DELETE', 'HEAD']).default('GET'),\n expiresIn: z.number().int().min(1).max(604800).optional(),\n disk: z.string().optional(),\n})\n\nexport type GetPresignedUrlInput = z.infer<typeof getPresignedUrlInputSchema>\n\nexport const presignedUrlResultSchema = z.object({\n url: z.string().url(),\n expiresIn: z.number(),\n expiresAt: z.date(),\n method: z.enum(['GET', 'PUT', 'DELETE', 'HEAD']),\n})\n\nexport type PresignedUrlResult = z.infer<typeof presignedUrlResultSchema>\n","import { z } from '../../i18n/validation'\n\n/**\n * Upload options for streaming uploads\n */\nexport interface UploadOptions {\n /**\n * Size of the content in bytes\n */\n size: number\n /**\n * MIME type of the content\n */\n mimeType?: string\n /**\n * Custom metadata to store with the object (S3-specific)\n * Stored as S3 object metadata headers\n */\n metadata?: Record<string, string>\n /**\n * Object tagging for lifecycle policies (S3-specific)\n * Format: key=value (e.g., \"Tus-Completed=true\")\n */\n tagging?: string\n}\n\nexport const uploadResultSchema = z.object({\n path: z.string(),\n disk: z.string(),\n fullPath: z.string(),\n size: z.number(),\n mimeType: z.string(),\n uploadedAt: z.date(),\n})\n\nexport type UploadResult = z.infer<typeof uploadResultSchema>\n","import { HttpException } from '../../errors'\n\nexport class FileTooLargeError extends HttpException {\n constructor(public readonly size?: number, public readonly maxSize?: number) {\n super(413, 'File too large')\n }\n}\n","import { HttpException } from '../../errors'\n\nexport class InvalidFileTypeError extends HttpException {\n constructor(public readonly mimeType?: string) {\n super(422, 'Invalid file type')\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAIA,MAAa,iBAAiB;CAC5B,SAAS,OAAO,IAAI,yBAAyB;CAC7C,gBAAgB,OAAO,IAAI,yBAAyB;CACpD,gBAAgB,OAAO,IAAI,yBAAyB;AACtD;;;ACOO,IAAA,wBAAA,MAAM,sBAAsB;CAOd;CAEA;CARnB,4BAA6B,IAAI,IAA8B;CAC/D,mCAAoC,IAAI,IAAuC;CAC/E,8BAA+B,IAAI,IAA0B;CAE7D,YACE,SAEA,KAEA;EAHiB,KAAA,UAAA;EAEA,KAAA,MAAA;EAEjB,KAAK,sBAAsB;CAC7B;;;;CAKA,wBAAsC;EACpC,KAAK,MAAM,SAAS,KAAK,QAAQ,SAC/B,KAAK,YAAY,IAAI,MAAM,MAAM,KAAK;CAE1C;;;;;;;CAQA,MAAM,YAAY,UAA6C;EAE7D,MAAM,SAAS,KAAK,UAAU,IAAI,QAAQ;EAC1C,IAAI,QACF,OAAO;EAIT,MAAM,WAAW,KAAK,iBAAiB,IAAI,QAAQ;EACnD,IAAI,UACF,OAAO;EAIT,MAAM,aAAa,KAAK,YAAY,IAAI,QAAQ;EAChD,IAAI,CAAC,YACH,MAAM,IAAI,aAAa,SAAS,SAAS,oBAAoB;EAI/D,MAAM,UAAU,KAAK,eAAe,UAAU,EAAE,MAAM,aAAa;GACjE,KAAK,UAAU,IAAI,UAAU,QAAQ;GACrC,KAAK,iBAAiB,OAAO,QAAQ;GACrC,OAAO;EACT,CAAC,EAAE,OAAO,UAAmB;GAC3B,KAAK,iBAAiB,OAAO,QAAQ;GACrC,MAAM;EACR,CAAC;EAED,KAAK,iBAAiB,IAAI,UAAU,OAAO;EAE3C,OAAO;CACT;;;;;;;CAQA,MAAc,eAAe,QAAiD;EAC5E,MAAM,EAAE,sBAAsB,MAAM,OAAO,sCAAA,MAAA,MAAA,EAAA,CAAA;EAC3C,MAAM,SAAS,KAAK,IAAI,OAAO;EAC/B,IAAI,CAAC,QACH,MAAM,IAAI,aAAa,eAAe,OAAO,QAAQ,mCAAmC;EAE1F,OAAO,IAAI,kBAAkB,QAAQ,QAAQ,KAAK,KAAK,KAAK,QAAQ,KAAK;CAC3E;;;;;;CAOA,cAAc,UAAgC;EAC5C,MAAM,SAAS,KAAK,YAAY,IAAI,QAAQ;EAC5C,IAAI,CAAC,QACH,MAAM,IAAI,aAAa,SAAS,SAAS,oBAAoB;EAE/D,OAAO;CACT;;;;;;CAOA,QAAQ,UAA2B;EACjC,OAAO,KAAK,YAAY,IAAI,QAAQ;CACtC;;;;;CAMA,oBAA8B;EAC5B,OAAO,MAAM,KAAK,KAAK,YAAY,KAAK,CAAC;CAC3C;AACF;;CA5GC,UAAU,eAAe,cAAc;oBAOnC,OAAO,eAAe,OAAO,CAAA;oBAE7B,OAAO,UAAU,aAAa,CAAA;;;;ACC5B,IAAA,iBAAA,MAAM,eAAe;CAGL;CAEA;CAJrB,YACE,gBAEA,SAEA;EAHmB,KAAA,iBAAA;EAEA,KAAA,UAAA;CACjB;;;;;;;;;CAUJ,MAAM,OACJ,MACA,cACA,SACA,MACuB;EACvB,MAAM,WAAW,KAAK,YAAY,IAAI;EACtC,MAAM,WAAW,MAAM,KAAK,eAAe,YAAY,QAAQ;EAC/D,MAAM,WAAW,KAAK,cAAc,cAAc,QAAQ;EAE1D,OAAO,SAAS,OAAO,MAAM,UAAU,OAAO;CAChD;;;;;;;CAQA,MAAM,SAAS,cAAsB,MAAwC;EAC3E,MAAM,WAAW,KAAK,YAAY,IAAI;EACtC,MAAM,WAAW,MAAM,KAAK,eAAe,YAAY,QAAQ;EAC/D,MAAM,WAAW,KAAK,cAAc,cAAc,QAAQ;EAE1D,OAAO,SAAS,SAAS,QAAQ;CACnC;;;;;;CAOA,MAAM,OAAO,cAAsB,MAA8B;EAC/D,MAAM,WAAW,KAAK,YAAY,IAAI;EACtC,MAAM,WAAW,MAAM,KAAK,eAAe,YAAY,QAAQ;EAC/D,MAAM,WAAW,KAAK,cAAc,cAAc,QAAQ;EAE1D,MAAM,SAAS,OAAO,QAAQ;CAChC;;;;;;;CAQA,MAAM,OAAO,cAAsB,MAAiC;EAClE,MAAM,WAAW,KAAK,YAAY,IAAI;EACtC,MAAM,WAAW,MAAM,KAAK,eAAe,YAAY,QAAQ;EAC/D,MAAM,WAAW,KAAK,cAAc,cAAc,QAAQ;EAE1D,OAAO,SAAS,OAAO,QAAQ;CACjC;;;;;;;;CASA,MAAM,wBACJ,cACA,WACA,MAC6B;EAC7B,OAAO,KAAK,gBAAgB,cAAc,OAAO,WAAW,IAAI;CAClE;;;;;;;;CASA,MAAM,sBACJ,cACA,WACA,MAC6B;EAC7B,OAAO,KAAK,gBAAgB,cAAc,OAAO,WAAW,IAAI;CAClE;;;;;;;;CASA,MAAM,sBACJ,cACA,WACA,MAC6B;EAC7B,OAAO,KAAK,gBAAgB,cAAc,UAAU,WAAW,IAAI;CACrE;;;;;;;;;CAUA,MAAgB,gBACd,cACA,QACA,WACA,MAC6B;EAC7B,MAAM,WAAW,KAAK,YAAY,IAAI;EACtC,MAAM,WAAW,MAAM,KAAK,eAAe,YAAY,QAAQ;EAC/D,MAAM,WAAW,KAAK,cAAc,cAAc,QAAQ;EAC1D,MAAM,qBAAqB,KAAK,kBAAkB,SAAS;EAE3D,OAAO,SAAS,gBAAgB,UAAU,QAAQ,kBAAkB;CACtE;;;;;;CAOA,YAAsB,MAAuB;EAC3C,MAAM,WAAW,QAAQ,KAAK,QAAQ;EAEtC,IAAI,CAAC,KAAK,eAAe,QAAQ,QAAQ,GACvC,MAAM,IAAI,aAAa,SAAS,SAAS,oBAAoB;EAG/D,OAAO;CACT;;;;;;;CAQA,cAAwB,cAAsB,UAA0B;EAEtE,IAAI,OADe,KAAK,eAAe,cAAc,QACjC,EAAE,QAAQ;EAG9B,OAAO,KAAK,4BAA4B,IAAI;EAK5C,OAFiB,GAAG,KAAK,GAAG,eAAe,QAAQ,QAAQ,GAAG,EAAE,QAAQ,OAAO,EAEjE;CAChB;;;;;;;;CASA,4BAAsC,MAAsB;EAC1D,IAAI,SAAS;EAGb,MAAM,sBAAM,IAAI,KAAK;EACrB,SAAS,OAAO,QAAQ,WAAW,IAAI,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE;EAClE,SAAS,OAAO,QAAQ,WAAW,IAAI,YAAY,EAAE,SAAS,CAAC;EAC/D,SAAS,OAAO,QAAQ,aAAa,IAAI,SAAS,IAAI,GAAG,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;EAEpF,OAAO;CACT;;;;;;CAOA,kBAA4B,WAA4B;EACtD,MAAM,qBAAqB,KAAK,QAAQ;EACxC,MAAM,qBAAqB,aAAa,mBAAmB;EAE3D,MAAM,YAAY;EAClB,MAAM,YAAY,mBAAmB;EAErC,IAAI,qBAAqB,aAAa,qBAAqB,WACzD,MAAM,IAAI,aAAa,wBAAwB,mBAAmB,qBAAqB,UAAU,GAAG,UAAU,GAAG;EAGnH,OAAO;CACT;;;;;CAMA,oBAA8B;EAC5B,OAAO,KAAK,eAAe,kBAAkB;CAC/C;;;;;;;;;;;;;;;;CAiBA,MAAM,cACJ,MACA,cACA,SACA,MACuB;EACvB,MAAM,WAAW,KAAK,YAAY,IAAI;EACtC,MAAM,WAAW,MAAM,KAAK,eAAe,YAAY,QAAQ;EAC/D,MAAM,WAAW,KAAK,cAAc,cAAc,QAAQ;EAE1D,OAAO,SAAS,cAAc,MAAM,UAAU,OAAO;CACvD;AACF;;CArPC,QAAQ,eAAe,cAAc;oBAGjC,OAAO,eAAe,cAAc,CAAA;oBAEpC,OAAO,eAAe,OAAO,CAAA;;;;;;;;;;ACH3B,IAAA,gBAAA,iBAAA,MAAM,cAAc;;;;;;;;;;;;;CAazB,OAAO,QAAQ,SAA8C;EAC3D,OAAO;GACL,QAAA;GACA,WAAW,CACT;IAAE,SAAS,eAAe;IAAS,UAAU;GAAQ,CACvD;EACF;CACF;;;;;;;;;;;;;;;;;;CAmBA,OAAO,aAAa,SAAkE;EACpF,OAAO;GACL,QAAA;GACA,WAAW,CACT;IACE,SAAS,eAAe;IACxB,YAAY,QAAQ;IACpB,QAAQ,QAAQ;GAClB,CACF;EACF;CACF;AACF;6CAzDC,OAAO,EACN,WAAW,CACT;CAAE,SAAS,eAAe;CAAgB,UAAU;AAAsB,GAC1E;CAAE,SAAS,eAAe;CAAgB,UAAU;AAAe,CACrE,EACF,CAAC,CAAA,GAAA,aAAA;;;ACtBD,IAAa,oBAAb,cAAuC,cAAc;CACnD,YAAY,MAAe;EACzB,MAAM,KAAK,OAAO,oBAAoB,KAAK,KAAK,gBAAgB;CAClE;AACF;;;ACGA,MAAM,YAAY,EAAE,OAAO,EACzB,MAAM,EAAE,OAAO,EACjB,CAAC;AAeM,IAAA,oBAAA,MAAM,kBAAkB;CAGV;CAFnB,YACE,SAEA;EADiB,KAAA,UAAA;CAChB;CAEH,MACM,SAAS,KAAuC;EACpD,MAAM,OAAO,IAAI,MAAM,MAAM;EAC7B,MAAM,OAAO,oBAAoB,GAAG;EACpC,MAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,MAAM,IAAI;EAErD,MAAM,SAAS,OAAO,SAAS;EAC/B,IAAI,CAAC,QACH,MAAM,IAAI,kBAAkB,IAAI;EAGlC,OAAO,IAAI,SAAS,QAAQ,EAC1B,SAAS;GACP,gBAAgB,OAAO;GACvB,kBAAkB,OAAO,OAAO,IAAI;GACpC,uBAAuB;EACzB,EACF,CAAC;CACH;CAEA,MACM,OAAO,KAAuC;EAClD,MAAM,OAAO,IAAI,MAAM,MAAM;EAC7B,MAAM,OAAO,oBAAoB,GAAG;EAEpC,MAAM,OAAO,IAAI,EAAE,IAAI,IAAI;EAC3B,MAAM,cAAc,IAAI,OAAO,cAAc,KAAK;EAClD,MAAM,gBAAgB,IAAI,OAAO,gBAAgB;EAEjD,MAAM,KAAK,QAAQ,OAAO,MAAM,MAAM;GACpC,UAAU;GACV,MAAM,gBAAgB,SAAS,eAAe,EAAE,IAAI;EACtD,GAAG,IAAI;EAEP,OAAO,IAAI,KAAK;GAAE;GAAM;EAAK,GAAG,GAAG;CACrC;CAEA,MACM,QAAQ,KAAuC;EACnD,MAAM,OAAO,IAAI,MAAM,MAAM;EAC7B,MAAM,OAAO,oBAAoB,GAAG;EAEpC,MAAM,KAAK,QAAQ,OAAO,MAAM,IAAI;EAEpC,OAAO,IAAI,EAAE,KAAK,MAAM,GAAG;CAC7B;AACF;YA9CG,IAAI,YAAY;CAAE,cAAc;CAAM,QAAQ;AAAU,CAAC,CAAA,GAAA,kBAAA,WAAA,YAAA,IAAA;YAoBzD,IAAI,YAAY;CAAE,cAAc;CAAM,QAAQ;AAAU,CAAC,CAAA,GAAA,kBAAA,WAAA,UAAA,IAAA;YAiBzD,OAAO,YAAY;CAAE,cAAc;CAAM,QAAQ;AAAU,CAAC,CAAA,GAAA,kBAAA,WAAA,WAAA,IAAA;gCA5C9D,WAAW,YAAY,EAAE,cAAc,KAAK,CAAC,GAAA,gBAAA,GAGzC,OAAO,eAAe,cAAc,CAAA,CAAA,GAAA,iBAAA;;;;;AAwDzC,SAAS,oBAAoB,KAA4B;CAOvD,OAJiB,IADD,IAAI,IAAI,EAAE,IAAI,GACX,EAAE,SAEE,MAAM,GAElB,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG;AAChC;;;AC1FA,MAAa,wBAAwB,EAAE,OAAO;CAC5C,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,YAAY,wCAAwC,CAAC;CAC7E,MAAM,EAAE,OAAO,EAAE,SAAS;AAC5B,CAAC;;;ACHD,MAAa,wBAAwB,EAAE,OAAO;CAC5C,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,YAAY,wCAAwC,CAAC;CAC7E,MAAM,EAAE,OAAO,EAAE,SAAS;AAC5B,CAAC;;;ACHD,MAAa,6BAA6B,EAAE,OAAO;CACjD,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,YAAY,wCAAwC,CAAC;CAC7E,QAAQ,EAAE,KAAK;EAAC;EAAO;EAAO;EAAU;CAAM,CAAC,EAAE,QAAQ,KAAK;CAC9D,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,MAAM,EAAE,SAAS;CACxD,MAAM,EAAE,OAAO,EAAE,SAAS;AAC5B,CAAC;AAID,MAAa,2BAA2B,EAAE,OAAO;CAC/C,KAAK,EAAE,OAAO,EAAE,IAAI;CACpB,WAAW,EAAE,OAAO;CACpB,WAAW,EAAE,KAAK;CAClB,QAAQ,EAAE,KAAK;EAAC;EAAO;EAAO;EAAU;CAAM,CAAC;AACjD,CAAC;;;ACUD,MAAa,qBAAqB,EAAE,OAAO;CACzC,MAAM,EAAE,OAAO;CACf,MAAM,EAAE,OAAO;CACf,UAAU,EAAE,OAAO;CACnB,MAAM,EAAE,OAAO;CACf,UAAU,EAAE,OAAO;CACnB,YAAY,EAAE,KAAK;AACrB,CAAC;;;AC/BD,IAAa,oBAAb,cAAuC,cAAc;CACvB;CAA+B;CAA3D,YAAY,MAA+B,SAAkC;EAC3E,MAAM,KAAK,gBAAgB;EADD,KAAA,OAAA;EAA+B,KAAA,UAAA;CAE3D;AACF;;;ACJA,IAAa,uBAAb,cAA0C,cAAc;CAC1B;CAA5B,YAAY,UAAmC;EAC7C,MAAM,KAAK,mBAAmB;EADJ,KAAA,WAAA;CAE5B;AACF"}
@@ -1,5 +1,4 @@
1
- import { o as z } from "./index-Bnpfq6uk.mjs";
2
-
1
+ import { a as z } from "./zod-wecrEVAs.mjs";
3
2
  //#region src/storage/types.d.ts
4
3
  /**
5
4
  * Storage entry configuration
@@ -199,4 +198,4 @@ interface IStorageProvider {
199
198
  }
200
199
  //#endregion
201
200
  export { StorageEntry as _, uploadResultSchema as a, getPresignedUrlInputSchema as c, fileExistsInputSchema as d, DownloadResult as f, StorageConfig as g, PresignedUrlConfig as h, UploadResult as i, presignedUrlResultSchema as l, deleteFileInputSchema as m, StreamingBlobPayloadInputTypes as n, GetPresignedUrlInput as o, DeleteFileInput as p, UploadOptions as r, PresignedUrlResult as s, IStorageProvider as t, FileExistsInput as u, StorageRouteConfig as v };
202
- //# sourceMappingURL=storage-provider.interface-Bd6vA4ak.d.mts.map
201
+ //# sourceMappingURL=storage-provider.interface-ClUwxz4S.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-provider.interface-ClUwxz4S.d.mts","names":[],"sources":["../src/storage/types.ts","../src/storage/contracts/delete-file.input.ts","../src/storage/contracts/download-result.ts","../src/storage/contracts/file-exists.input.ts","../src/storage/contracts/get-presigned-url.input.ts","../src/storage/contracts/upload-file.input.ts","../src/storage/providers/storage-provider.interface.ts"],"mappings":";;;;;;UAIiB,YAAA;EAChB,IAAA;;EAEA,OAAA;EACA,IAAA;AAAA;;;AAAI;UAMY,kBAAA;EAChB,aAAA;EACA,SAAS;AAAA;AAAA;AAMV;;AANU,UAMO,kBAAA;EAEhB;EAAA,QAAA;EAQgB;EANhB,QAAQ;AAAA;;;;UAMQ,aAAA;EAChB,OAAA,EAAS,YAAA;EACT,kBAAA;EACA,YAAA,EAAc,kBAAA;EADd;EAGA,KAAA,GAAQ,kBAAA;AAAA;;;cCnCI,qBAAA,EAAqB,CAAA,CAAA,SAAA;;;;KAKtB,eAAA,GAAkB,CAAA,CAAE,KAAK,QAAQ,qBAAA;;;;;;;ADH7C;;UEEiB,cAAA;EFFY;;;EEM3B,QAAA,gBAAwB,cAAA,CAAe,UAAA;EAEvC,QAAA,gBAAwB,OAAA;EAExB,aAAA,gBAA6B,OAAA,CAAQ,UAAA;EFAtB;;;EEKf,WAAA;EFHQ;AAMV;;EEEE,IAAA;EFAD;AAEQ;AAMT;;EEFE,QAAA,GAAW,MAAA;AAAA;;;cC5BA,qBAAA,EAAqB,CAAA,CAAA,SAAA;;;;KAKtB,eAAA,GAAkB,CAAA,CAAE,KAAK,QAAQ,qBAAA;;;cCLhC,0BAAA,EAA0B,CAAA,CAAA,SAAA;;;;;;;;;;;KAO3B,oBAAA,GAAuB,CAAA,CAAE,KAAK,QAAQ,0BAAA;AAAA,cAErC,wBAAA,EAAwB,CAAA,CAAA,SAAA;;;;;;;;;;;KAOzB,kBAAA,GAAqB,CAAA,CAAE,KAAK,QAAQ,wBAAA;;;;;;UCb/B,aAAA;ELDY;;;EKK3B,IAAA;ELFD;;;EKMC,QAAA;ELCe;;;;EKIf,QAAA,GAAW,MAAM;ELIF;;;;EKCf,OAAA;AAAA;AAAA,cAGW,kBAAA,EAAkB,CAAA,CAAA,SAAA;;;;;;;;KASnB,YAAA,GAAe,CAAA,CAAE,KAAK,QAAQ,kBAAA;;;;;;AL/B1C;KMEY,8BAAA,GACR,cAAA,GACA,WAAA,GACA,eAAA,YAEA,IAAA;;;;;UAOa,gBAAA;ENVZ;AAAA;AAML;;;;AAEU;EMUR,MAAA,CAAO,IAAA,EAAM,8BAAA,EAAgC,IAAA,UAAc,OAAA,EAAS,aAAA,GAAgB,OAAA,CAAQ,YAAA;ENJ3D;;;AAI1B;AAMT;EMCE,QAAA,CAAS,IAAA,WAAe,OAAA,CAAQ,cAAA;;;;;EAMhC,MAAA,CAAO,IAAA,WAAe,OAAA;ENFG;;;;;EMSzB,MAAA,CAAO,IAAA,WAAe,OAAA;ENTvB;;;AAA0B;;;;EMkBzB,eAAA,CACE,IAAA,UACA,MAAA,qCACA,SAAA,WACC,OAAA,CAAQ,kBAAA;ELtDX;;;;;;;;EKgEA,aAAA,CACE,IAAA,EAAM,8BAAA,EACN,IAAA,UACA,OAAA,EAAS,IAAA,CAAK,aAAA;IAA2B,IAAA;EAAA,IACxC,OAAA,CAAQ,YAAA;AAAA"}
@@ -0,0 +1,8 @@
1
+ import { a as ApplicationError } from "./container-storage-BmOJ4_Na.mjs";
2
+ import "./errors-mXYxG0XB.mjs";
3
+ //#region src/storage/storage.error.ts
4
+ var StorageError = class extends ApplicationError {};
5
+ //#endregion
6
+ export { StorageError as t };
7
+
8
+ //# sourceMappingURL=storage.error-Dnib4VHc.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.error-Dnib4VHc.mjs","names":[],"sources":["../src/storage/storage.error.ts"],"sourcesContent":["import { ApplicationError } from '../errors'\n\nexport class StorageError extends ApplicationError {}\n"],"mappings":";;;AAEA,IAAa,eAAb,cAAkC,iBAAiB,CAAC"}
@@ -0,0 +1,383 @@
1
+ import { r as DI_TOKENS, t as Container, v as ROUTER_TOKENS } from "./di-DseMn-z9.mjs";
2
+ import { n as getContainer, r as runWithContainer, t as containerStorage } from "./container-storage-BmOJ4_Na.mjs";
3
+ import { JsonFormatter, LOGGER_TOKENS, LoggerService, PrettyFormatter } from "./logger/index.mjs";
4
+ import { a as DefaultExceptionHandler, r as StratalNotInitializedError } from "./errors-mXYxG0XB.mjs";
5
+ import { i as createQueueExceptionContext, n as createCronExceptionContext, t as createCliExceptionContext } from "./exception-context-kEoMFwze.mjs";
6
+ import { a as getListenerHandlers } from "./events-BXJGZjpG.mjs";
7
+ import { d as LazyModuleLoader, t as ModuleRegistry } from "./module-registry-Dm-pqHd3.mjs";
8
+ import { t as SEEDER_TOKENS } from "./seeder-registry-CyUmKsJq.mjs";
9
+ //#region src/application.ts
10
+ var Application = class {
11
+ _container;
12
+ honoApp;
13
+ moduleRegistry;
14
+ consumerRegistry;
15
+ cronManager;
16
+ quarry;
17
+ initialized = false;
18
+ routingInitPromise = null;
19
+ eventsInitPromise = null;
20
+ queueInitPromise = null;
21
+ i18nInitPromise = null;
22
+ cronInitPromise = null;
23
+ env;
24
+ appConfig;
25
+ constructor({ env, ctx, ...config }) {
26
+ this.env = env;
27
+ this.appConfig = config;
28
+ this._container = new Container();
29
+ this._container.registerValue(DI_TOKENS.Application, this);
30
+ this._container.registerValue(DI_TOKENS.CloudflareEnv, env);
31
+ this._container.registerValue(DI_TOKENS.ExecutionContext, ctx);
32
+ this._container.registerValue(ROUTER_TOKENS.RouterContext, null);
33
+ this.registerLoggerService();
34
+ this.registerCoreServices();
35
+ const logger = this._container.resolve(LOGGER_TOKENS.LoggerService);
36
+ this.moduleRegistry = new ModuleRegistry(this._container, logger);
37
+ this._container.registerValue(DI_TOKENS.ModuleRegistry, this.moduleRegistry);
38
+ }
39
+ get container() {
40
+ return this._container;
41
+ }
42
+ async ensureHono() {
43
+ await this.initializeRouting();
44
+ return this.honoApp;
45
+ }
46
+ get config() {
47
+ return this.appConfig;
48
+ }
49
+ async initialize() {
50
+ if (this.initialized) return;
51
+ await runWithContainer(this._container, () => this.initializeInternal());
52
+ }
53
+ async initializeInternal() {
54
+ const [{ QuarryModule }, { SeederModule }] = await Promise.all([import("./quarry.module-BuRPGMDm.mjs").then((n) => n.n), import("./seeder.module-CYYwk3Qk.mjs").then((n) => n.n)]);
55
+ this.moduleRegistry.registerAll([QuarryModule, SeederModule]);
56
+ this.moduleRegistry.register(this.appConfig.module);
57
+ await this.moduleRegistry.initialize();
58
+ this.initializeExceptionHandler();
59
+ this.registerCommands();
60
+ this.registerSeeders();
61
+ if (this.moduleRegistry.getAllListeners().length > 0) await this.initializeEventListeners();
62
+ if (this.moduleRegistry.getAllJobs().length > 0) await this.ensureCron();
63
+ this.initialized = true;
64
+ }
65
+ async registerRoutingServices() {
66
+ const [{ HonoApp }, { RouteRegistry }, { RouterResolver }, { VersioningService }, { LocalePathService }, { LocaleUrlService }, { RouteRegistrationService }, { Uri }] = await Promise.all([
67
+ import("./hono-app-CvV3hOfT.mjs").then((n) => n.n),
68
+ import("./route-registry-CYqLp2Nj.mjs").then((n) => n.n),
69
+ import("./router-resolver-D4YlPNlm.mjs"),
70
+ import("./versioning.service-C6aHky8-.mjs").then((n) => n.n),
71
+ import("./locale-path.service-D-dHiIPc.mjs").then((n) => n.n),
72
+ import("./locale-url.service-C2EWmGdq.mjs").then((n) => n.n),
73
+ import("./route-registration.service-D6vSwiKP.mjs").then((n) => n.n),
74
+ import("./uri-h7Q8Jug9.mjs").then((n) => n.r)
75
+ ]);
76
+ this._container.register(ROUTER_TOKENS.VersioningService, VersioningService);
77
+ this._container.register(ROUTER_TOKENS.HonoApp, HonoApp);
78
+ this._container.register(ROUTER_TOKENS.LocalePathService, LocalePathService);
79
+ this._container.register(ROUTER_TOKENS.LocaleUrlService, LocaleUrlService);
80
+ this._container.register(ROUTER_TOKENS.RouteRegistry, RouteRegistry);
81
+ this._container.register(ROUTER_TOKENS.Uri, Uri);
82
+ const routerConfigs = this.moduleRegistry.getAllRouterConfigs();
83
+ if (routerConfigs.length > 0) this._container.registerValue(ROUTER_TOKENS.RouterResolver, new RouterResolver(routerConfigs));
84
+ this._container.register(RouteRegistrationService, RouteRegistrationService);
85
+ }
86
+ /**
87
+ * Load the events subsystem and wire listeners. Needed by the HTTP, queue,
88
+ * and scheduled paths (handlers emit events). Independent of the queue
89
+ * subsystem so HTTP-only apps never load queue code. EventsModule is
90
+ * registered before the (possibly empty) listener wiring so `emit()` works
91
+ * even with zero listeners; dedups against the framework's own load.
92
+ */
93
+ initializeEventListeners() {
94
+ this.eventsInitPromise ??= runWithContainer(this._container, async () => {
95
+ const { EventsModule } = await import("./events-BXJGZjpG.mjs").then((n) => n.n);
96
+ await this.moduleRegistry.registerLazy(EventsModule);
97
+ this.registerEventListeners();
98
+ });
99
+ return this.eventsInitPromise;
100
+ }
101
+ /**
102
+ * Wire event and queue handlers for any non-HTTP request scope — queue
103
+ * batches, scheduled/cron runs, CLI commands, Durable Objects, Workflows,
104
+ * WorkerEntrypoints — all of which may emit events or dispatch to queues from
105
+ * arbitrary user code. This is the single source of truth for that wiring:
106
+ * every non-HTTP entry point routes through it rather than open-coding which
107
+ * subsystems to init, so a subsystem can't be silently dropped by a future
108
+ * refactor (the queue half was once lost from the command path that way).
109
+ *
110
+ * HTTP (`fetch`) deliberately does NOT use this: a fetch worker only enqueues
111
+ * to the async Cloudflare queue and never processes consumers inline, so it
112
+ * skips queue init via `initializeRouting`.
113
+ */
114
+ async ensureScopedHandlers() {
115
+ await this.initializeEventListeners();
116
+ await this.initializeQueue();
117
+ }
118
+ /**
119
+ * Load the queue subsystem on demand (first queue/scheduled trigger). i18n is
120
+ * ensured first because the queue registry depends on it.
121
+ */
122
+ initializeQueue() {
123
+ this.queueInitPromise ??= runWithContainer(this._container, async () => {
124
+ await this.ensureI18n();
125
+ const { QueueModule } = await import("./queue.module-nddvxzCB.mjs").then((n) => n.n);
126
+ this.moduleRegistry.register(QueueModule);
127
+ this.consumerRegistry = this._container.resolve(DI_TOKENS.ConsumerRegistry);
128
+ await this.registerQueueConsumers();
129
+ });
130
+ return this.queueInitPromise;
131
+ }
132
+ /**
133
+ * Load i18n on demand. Coupled to the request path (Zod validation error maps,
134
+ * OpenAPI descriptions, queue registry), so it loads before routing/queue
135
+ * handling. Uses `registerLazy` because I18nModule has an `onInitialize` hook
136
+ * (configures the Zod error map). Dedups if the app already imported i18n.
137
+ */
138
+ ensureI18n() {
139
+ this.i18nInitPromise ??= runWithContainer(this._container, async () => {
140
+ const { I18nModule } = await import("./i18n.module-DRQAZoSZ.mjs").then((n) => n.n);
141
+ await this.moduleRegistry.registerLazy(I18nModule);
142
+ });
143
+ return this.i18nInitPromise;
144
+ }
145
+ /**
146
+ * Load the cron subsystem on demand (first scheduled trigger, or at bootstrap
147
+ * when the app declares jobs).
148
+ */
149
+ ensureCron() {
150
+ this.cronInitPromise ??= runWithContainer(this._container, async () => {
151
+ const { CronModule } = await import("./cron.module-Bgzq5hiT.mjs").then((n) => n.n);
152
+ this.moduleRegistry.register(CronModule);
153
+ this.cronManager = this._container.resolve(DI_TOKENS.Cron);
154
+ this.registerCronJobs(this.cronManager);
155
+ });
156
+ return this.cronInitPromise.then(() => this.cronManager);
157
+ }
158
+ resolve(token) {
159
+ try {
160
+ return this._container.resolve(token);
161
+ } catch (error) {
162
+ const handler = this._container.resolve(DI_TOKENS.ExceptionHandler);
163
+ const ctx = createCliExceptionContext("resolve");
164
+ handler.handle(error, ctx);
165
+ throw error;
166
+ }
167
+ }
168
+ async handleQueue(batch, queueName) {
169
+ await this.ensureScopedHandlers();
170
+ const locale = (batch.messages[0]?.body)?.metadata?.locale ?? "en";
171
+ const mockRouterContext = this.createMockRouterContext(locale);
172
+ await this._container.runInRequestScope(mockRouterContext, async (requestContainer) => {
173
+ try {
174
+ await requestContainer.resolve(DI_TOKENS.Queue).processBatch(queueName, batch);
175
+ } catch (error) {
176
+ await requestContainer.resolve(DI_TOKENS.ExceptionHandler).handle(error, createQueueExceptionContext(queueName));
177
+ throw error;
178
+ }
179
+ });
180
+ }
181
+ async handleScheduled(controller) {
182
+ const cronManager = await this.ensureCron();
183
+ await this.ensureScopedHandlers();
184
+ await this.ensureI18n();
185
+ const mockRouterContext = this.createMockRouterContext("en");
186
+ await this._container.runInRequestScope(mockRouterContext, async (requestContainer) => {
187
+ try {
188
+ await cronManager.executeScheduled(controller, requestContainer);
189
+ } catch (error) {
190
+ await requestContainer.resolve(DI_TOKENS.ExceptionHandler).handle(error, createCronExceptionContext());
191
+ throw error;
192
+ }
193
+ });
194
+ }
195
+ createMockRouterContext(locale = "en") {
196
+ return {
197
+ getLocale: () => locale,
198
+ setLocale: () => {},
199
+ getContainer: () => containerStorage.getStore() ?? this._container
200
+ };
201
+ }
202
+ async shutdown() {
203
+ if (!this.initialized) return;
204
+ this.initialized = false;
205
+ await this.moduleRegistry.shutdown();
206
+ this._container.resolve(LOGGER_TOKENS.LoggerService).info("Disposing container...");
207
+ this._container.dispose();
208
+ }
209
+ async handleCommand(name, input) {
210
+ await this.initializeRouting();
211
+ await this.ensureScopedHandlers();
212
+ this.quarry ??= this._container.resolve(DI_TOKENS.Quarry);
213
+ const mockContext = this.createMockRouterContext("en");
214
+ return this._container.runInRequestScope(mockContext, async () => {
215
+ return this.quarry.call(name, input);
216
+ });
217
+ }
218
+ initializeRouting() {
219
+ this.routingInitPromise ??= runWithContainer(this._container, async () => {
220
+ await this.initializeEventListeners();
221
+ await this.ensureI18n();
222
+ const { OpenAPIModule } = await import("./openapi/index.mjs");
223
+ this.moduleRegistry.register(OpenAPIModule);
224
+ await this.registerRoutingServices();
225
+ this.honoApp = this._container.resolve(ROUTER_TOKENS.HonoApp);
226
+ await this.honoApp.configure();
227
+ });
228
+ return this.routingInitPromise;
229
+ }
230
+ registerCommands() {
231
+ this.quarry ??= this._container.resolve(DI_TOKENS.Quarry);
232
+ const commands = this.moduleRegistry.getAllCommands();
233
+ for (const CommandClass of commands) this.quarry.register(CommandClass);
234
+ }
235
+ registerSeeders() {
236
+ const seeders = this.moduleRegistry.getAllSeeders();
237
+ if (seeders.length === 0) return;
238
+ const registry = this._container.resolve(SEEDER_TOKENS.SeederRegistry);
239
+ for (const SeederClass of seeders) registry.register(SeederClass);
240
+ }
241
+ async registerQueueConsumers() {
242
+ const consumerClasses = this.moduleRegistry.getAllConsumers();
243
+ if (consumerClasses.length === 0) return;
244
+ const mockContext = this.createMockRouterContext("en");
245
+ await this._container.runInRequestScope(mockContext, (requestContainer) => {
246
+ for (const ConsumerClass of consumerClasses) {
247
+ const consumer = requestContainer.resolve(ConsumerClass);
248
+ this.consumerRegistry.register(ConsumerClass, consumer.messageTypes);
249
+ }
250
+ });
251
+ }
252
+ registerCronJobs(cronManager) {
253
+ for (const JobClass of this.moduleRegistry.getAllJobs()) {
254
+ const schedule = JobClass.schedule;
255
+ if (schedule) cronManager.registerJob(schedule, JobClass);
256
+ else this._container.resolve(LOGGER_TOKENS.LoggerService).warn(`Cron job "${JobClass.name}" has no static schedule property — skipped`);
257
+ }
258
+ }
259
+ registerEventListeners() {
260
+ const listeners = this.moduleRegistry.getAllListeners();
261
+ if (listeners.length === 0) return;
262
+ const eventRegistry = this._container.resolve(DI_TOKENS.EventRegistry);
263
+ for (const ListenerClass of listeners) {
264
+ const handlers = getListenerHandlers(ListenerClass);
265
+ for (const { methodName, event, options } of handlers) {
266
+ const handler = ((...args) => {
267
+ return getContainer().resolve(ListenerClass)[methodName](...args);
268
+ });
269
+ eventRegistry.on(event, handler, options);
270
+ }
271
+ }
272
+ }
273
+ registerLoggerService() {
274
+ const logLevel = this.appConfig.logging?.level ?? "info";
275
+ const formatter = this.appConfig.logging?.formatter ?? "json";
276
+ this._container.registerValue(LOGGER_TOKENS.LogLevelOptions, logLevel);
277
+ this._container.when(() => formatter === "pretty").use(LOGGER_TOKENS.Formatter).give(PrettyFormatter).otherwise(JsonFormatter);
278
+ this._container.registerSingleton(LOGGER_TOKENS.LoggerService, LoggerService);
279
+ }
280
+ /**
281
+ * Bootstrap kernel — registered imperatively because they cannot be expressed
282
+ * as ordinary module providers: ExceptionHandler is a user-overridable forced
283
+ * singleton (a module ClassProvider derives scope from the class decorator,
284
+ * which a user handler may not carry), and LazyModuleLoader is the loader
285
+ * itself. Subsystem registries (events/cron/quarry/seeder) are modules.
286
+ */
287
+ registerCoreServices() {
288
+ this._container.registerSingleton(DI_TOKENS.ExceptionHandler, this.appConfig.exceptionHandler ?? DefaultExceptionHandler);
289
+ this._container.registerSingleton(DI_TOKENS.LazyModuleLoader, LazyModuleLoader);
290
+ }
291
+ initializeExceptionHandler() {
292
+ const handler = this._container.resolve(DI_TOKENS.ExceptionHandler);
293
+ handler.register();
294
+ this.moduleRegistry.configureExceptionHandlers(handler);
295
+ }
296
+ };
297
+ //#endregion
298
+ //#region src/stratal.ts
299
+ /**
300
+ * Stratal — Hono-style entry point for Cloudflare Workers.
301
+ *
302
+ * Eagerly bootstraps the Application at construction time, dynamically
303
+ * importing `cloudflare:workers` for env and waitUntil.
304
+ *
305
+ * @example
306
+ * ```typescript
307
+ * import { Stratal } from 'stratal'
308
+ * import { AppModule } from './app.module'
309
+ *
310
+ * export default new Stratal({ module: AppModule })
311
+ * ```
312
+ */
313
+ var Stratal = class Stratal {
314
+ app = null;
315
+ initPromise;
316
+ static _application = null;
317
+ static _generation = 0;
318
+ static _previousInstance = null;
319
+ constructor(config) {
320
+ this.fetch = this.fetch.bind(this);
321
+ this.queue = this.queue.bind(this);
322
+ this.scheduled = this.scheduled.bind(this);
323
+ const generation = ++Stratal._generation;
324
+ if (Stratal._previousInstance) Stratal._previousInstance.shutdown();
325
+ Stratal._previousInstance = this;
326
+ this.initPromise = this.prepareApp(config, generation);
327
+ Stratal._application = this.initPromise;
328
+ }
329
+ async fetch(request, env, ctx) {
330
+ return (await (await this.ensureReady()).ensureHono()).fetch(request, env, ctx);
331
+ }
332
+ async queue(batch) {
333
+ return (await this.ensureReady()).handleQueue(batch, batch.queue);
334
+ }
335
+ async scheduled(controller) {
336
+ return (await this.ensureReady()).handleScheduled(controller);
337
+ }
338
+ get hono() {
339
+ return this.initPromise.then((app) => app.ensureHono());
340
+ }
341
+ async shutdown() {
342
+ try {
343
+ this.app = await this.initPromise;
344
+ } catch {}
345
+ if (this.app) {
346
+ await this.app.shutdown();
347
+ this.app = null;
348
+ }
349
+ }
350
+ /**
351
+ * @internal
352
+ * Resolves the Application instance from the static singleton.
353
+ * Used by worker base classes (DurableObject, Workflow, WorkerEntrypoint)
354
+ * to access the DI container without going through Cloudflare RPC.
355
+ */
356
+ static resolveApplication() {
357
+ if (!Stratal._application) throw new StratalNotInitializedError();
358
+ return Stratal._application;
359
+ }
360
+ async ensureReady() {
361
+ this.app ??= await this.initPromise;
362
+ return this.app;
363
+ }
364
+ async prepareApp(config, generation) {
365
+ const { env, waitUntil } = await import("cloudflare:workers");
366
+ if (generation !== Stratal._generation) return new Promise(() => {});
367
+ const app = new Application({
368
+ ...config,
369
+ env,
370
+ ctx: { waitUntil }
371
+ });
372
+ await app.initialize();
373
+ if (generation !== Stratal._generation) {
374
+ await app.shutdown();
375
+ return new Promise(() => {});
376
+ }
377
+ return app;
378
+ }
379
+ };
380
+ //#endregion
381
+ export { Application as n, Stratal as t };
382
+
383
+ //# sourceMappingURL=stratal-DL9M38_s.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stratal-DL9M38_s.mjs","names":[],"sources":["../src/application.ts","../src/stratal.ts"],"sourcesContent":["import type { CronJob } from './cron/cron-job'\nimport type { CronManager } from './cron/cron-manager'\nimport { Container } from './di/container'\nimport { containerStorage, getContainer, runWithContainer } from './di/container-storage'\nimport { DI_TOKENS } from './di/tokens'\nimport { type StratalEnv } from './env'\nimport { DefaultExceptionHandler } from './errors/default-exception-handler'\nimport { createCliExceptionContext, createCronExceptionContext, createQueueExceptionContext } from './errors/exception-context'\nimport type { ExceptionHandler } from './errors/exception-handler'\nimport type { EventHandler, EventRegistry } from './events'\nimport { getListenerHandlers } from './events'\nimport type { StratalExecutionContext } from './execution-context'\nimport { JsonFormatter, LOGGER_TOKENS, LoggerService, LogLevel, PrettyFormatter } from './logger'\nimport { LazyModuleLoader } from './module/lazy-module-loader'\nimport { ModuleRegistry } from './module/module-registry'\nimport type { DynamicModule, ModuleClass } from './module/types'\nimport type { Command } from './quarry/command'\nimport type { QuarryRegistry } from './quarry/quarry-registry'\nimport type { CommandInput, CommandResult } from './quarry/types'\nimport type { ConsumerRegistry } from './queue/consumer-registry'\nimport type { IQueueConsumer, QueueMessage } from './queue/queue-consumer'\nimport type { QueueManager } from './queue/queue-manager'\nimport type { RouterContext } from './router'\nimport type { HonoApp } from './router/hono-app'\nimport { ROUTER_TOKENS } from './router/router.tokens'\nimport type { TrailingSlashMode, VersioningOptions } from './router/types'\nimport type { Seeder } from './seeder/seeder'\nimport { SEEDER_TOKENS } from './seeder/seeder-registry'\nimport type { SeederRegistry } from './seeder/seeder-registry'\nimport type { Constructor } from './types'\n\nexport interface ApplicationConfig {\n module: ModuleClass | DynamicModule\n logging?: {\n level?: LogLevel\n formatter?: 'json' | 'pretty'\n }\n versioning?: VersioningOptions\n trailingSlash?: TrailingSlashMode\n exceptionHandler?: Constructor<ExceptionHandler>\n}\n\nexport interface ApplicationOptions extends ApplicationConfig {\n env: StratalEnv\n ctx: StratalExecutionContext\n}\n\nexport class Application {\n private _container: Container\n private honoApp!: HonoApp\n private moduleRegistry: ModuleRegistry\n private consumerRegistry!: ConsumerRegistry\n private cronManager?: CronManager\n private quarry!: QuarryRegistry\n private initialized = false\n\n // Independently memoized lazy-init promises — each built-in subsystem is\n // loaded on demand at its trigger point to keep cold start lean.\n private routingInitPromise: Promise<void> | null = null\n private eventsInitPromise: Promise<void> | null = null\n private queueInitPromise: Promise<void> | null = null\n private i18nInitPromise: Promise<void> | null = null\n private cronInitPromise: Promise<void> | null = null\n\n readonly env: StratalEnv\n private readonly appConfig: ApplicationConfig\n\n constructor({ env, ctx, ...config }: ApplicationOptions) {\n this.env = env\n this.appConfig = config\n\n this._container = new Container()\n\n this._container.registerValue(DI_TOKENS.Application, this)\n this._container.registerValue(DI_TOKENS.CloudflareEnv, env)\n this._container.registerValue(DI_TOKENS.ExecutionContext, ctx)\n this._container.registerValue(ROUTER_TOKENS.RouterContext, null)\n\n this.registerLoggerService()\n this.registerCoreServices()\n\n const logger = this._container.resolve<LoggerService>(LOGGER_TOKENS.LoggerService)\n this.moduleRegistry = new ModuleRegistry(this._container, logger)\n\n this._container.registerValue(DI_TOKENS.ModuleRegistry, this.moduleRegistry)\n }\n\n get container(): Container {\n return this._container\n }\n\n async ensureHono(): Promise<HonoApp> {\n await this.initializeRouting()\n return this.honoApp\n }\n\n get config(): ApplicationConfig {\n return this.appConfig\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return\n }\n\n await runWithContainer(this._container, () => this.initializeInternal())\n }\n\n private async initializeInternal(): Promise<void> {\n // Eager subsystem modules — Quarry/Seeder are resolved synchronously\n // post-init (CLI runner, test harness), so they must be registered before\n // initialize() completes. Dynamic import keeps application.ts free of static\n // subsystem imports (uniform with the other built-ins). They load at boot\n // regardless, so this is for consistency, not cold-start deferral.\n const [{ QuarryModule }, { SeederModule }] = await Promise.all([\n import('./quarry/quarry.module'),\n import('./seeder/seeder.module'),\n ])\n this.moduleRegistry.registerAll([QuarryModule, SeederModule])\n\n // Register the user's root module (traverses imports). Other built-in\n // subsystems (i18n, queue, cache, openapi, cron, events, router) load on\n // demand at their trigger points.\n this.moduleRegistry.register(this.appConfig.module)\n\n // Initialize all modules (only those with lifecycle hooks)\n await this.moduleRegistry.initialize()\n\n // Initialize ExceptionHandler\n this.initializeExceptionHandler()\n\n // Register CLI commands + seeders (class refs only; no instantiation)\n this.registerCommands()\n this.registerSeeders()\n\n // Wire event listeners as part of initialization whenever the application\n // declares any, so emitted events reach their handlers regardless of which\n // entry point drives the app. Listener wiring otherwise happens lazily only\n // on the HTTP router (`initializeRouting`) and queue/scheduled/command\n // (`ensureScopedHandlers`) paths; any code that emits events without going\n // through one of those — a direct service or repository call, an RPC\n // entrypoint, or a Durable Object — would dispatch into a registry with no\n // handlers attached, silently dropping the event. Guarded on there being\n // listeners so applications with none still skip loading the events\n // subsystem; `initializeEventListeners` dedups, so any later lazy trigger\n // becomes a no-op.\n if (this.moduleRegistry.getAllListeners().length > 0) {\n await this.initializeEventListeners()\n }\n\n // Cron only loads when the app actually declares scheduled jobs\n if (this.moduleRegistry.getAllJobs().length > 0) {\n await this.ensureCron()\n }\n\n this.initialized = true\n }\n\n private async registerRoutingServices(): Promise<void> {\n const [\n { HonoApp },\n { RouteRegistry },\n { RouterResolver },\n { VersioningService },\n { LocalePathService },\n { LocaleUrlService },\n { RouteRegistrationService },\n { Uri },\n ] = await Promise.all([\n import('./router/hono-app'),\n import('./router/route-registry'),\n import('./router/router-resolver'),\n import('./router/services/versioning.service'),\n import('./router/services/locale-path.service'),\n import('./router/services/locale-url.service'),\n import('./router/services/route-registration.service'),\n import('./router/uri'),\n ])\n\n this._container.register(ROUTER_TOKENS.VersioningService, VersioningService)\n this._container.register(ROUTER_TOKENS.HonoApp, HonoApp)\n this._container.register(ROUTER_TOKENS.LocalePathService, LocalePathService)\n this._container.register(ROUTER_TOKENS.LocaleUrlService, LocaleUrlService)\n this._container.register(ROUTER_TOKENS.RouteRegistry, RouteRegistry)\n this._container.register(ROUTER_TOKENS.Uri, Uri)\n\n const routerConfigs = this.moduleRegistry.getAllRouterConfigs()\n if (routerConfigs.length > 0) {\n this._container.registerValue(ROUTER_TOKENS.RouterResolver, new RouterResolver(routerConfigs))\n }\n\n this._container.register(RouteRegistrationService, RouteRegistrationService)\n }\n\n /**\n * Load the events subsystem and wire listeners. Needed by the HTTP, queue,\n * and scheduled paths (handlers emit events). Independent of the queue\n * subsystem so HTTP-only apps never load queue code. EventsModule is\n * registered before the (possibly empty) listener wiring so `emit()` works\n * even with zero listeners; dedups against the framework's own load.\n */\n private initializeEventListeners(): Promise<void> {\n this.eventsInitPromise ??= runWithContainer(this._container, async () => {\n const { EventsModule } = await import('./events/events.module')\n await this.moduleRegistry.registerLazy(EventsModule)\n this.registerEventListeners()\n })\n return this.eventsInitPromise\n }\n\n /**\n * Wire event and queue handlers for any non-HTTP request scope — queue\n * batches, scheduled/cron runs, CLI commands, Durable Objects, Workflows,\n * WorkerEntrypoints — all of which may emit events or dispatch to queues from\n * arbitrary user code. This is the single source of truth for that wiring:\n * every non-HTTP entry point routes through it rather than open-coding which\n * subsystems to init, so a subsystem can't be silently dropped by a future\n * refactor (the queue half was once lost from the command path that way).\n *\n * HTTP (`fetch`) deliberately does NOT use this: a fetch worker only enqueues\n * to the async Cloudflare queue and never processes consumers inline, so it\n * skips queue init via `initializeRouting`.\n */\n async ensureScopedHandlers(): Promise<void> {\n await this.initializeEventListeners()\n await this.initializeQueue()\n }\n\n /**\n * Load the queue subsystem on demand (first queue/scheduled trigger). i18n is\n * ensured first because the queue registry depends on it.\n */\n private initializeQueue(): Promise<void> {\n this.queueInitPromise ??= runWithContainer(this._container, async () => {\n await this.ensureI18n()\n const { QueueModule } = await import('./queue/queue.module')\n this.moduleRegistry.register(QueueModule as unknown as ModuleClass)\n this.consumerRegistry = this._container.resolve<ConsumerRegistry>(DI_TOKENS.ConsumerRegistry)\n await this.registerQueueConsumers()\n })\n return this.queueInitPromise\n }\n\n /**\n * Load i18n on demand. Coupled to the request path (Zod validation error maps,\n * OpenAPI descriptions, queue registry), so it loads before routing/queue\n * handling. Uses `registerLazy` because I18nModule has an `onInitialize` hook\n * (configures the Zod error map). Dedups if the app already imported i18n.\n */\n private ensureI18n(): Promise<void> {\n this.i18nInitPromise ??= runWithContainer(this._container, async () => {\n const { I18nModule } = await import('./i18n/i18n.module')\n await this.moduleRegistry.registerLazy(I18nModule as unknown as ModuleClass)\n })\n return this.i18nInitPromise\n }\n\n /**\n * Load the cron subsystem on demand (first scheduled trigger, or at bootstrap\n * when the app declares jobs).\n */\n private ensureCron(): Promise<CronManager> {\n this.cronInitPromise ??= runWithContainer(this._container, async () => {\n const { CronModule } = await import('./cron/cron.module')\n this.moduleRegistry.register(CronModule)\n this.cronManager = this._container.resolve<CronManager>(DI_TOKENS.Cron)\n this.registerCronJobs(this.cronManager)\n })\n return this.cronInitPromise.then(() => this.cronManager!)\n }\n\n resolve<T>(token: symbol): T {\n try {\n return this._container.resolve(token)\n } catch (error) {\n const handler = this._container.resolve<ExceptionHandler>(DI_TOKENS.ExceptionHandler)\n const ctx = createCliExceptionContext('resolve')\n void handler.handle(error, ctx)\n throw error\n }\n }\n\n async handleQueue(batch: MessageBatch, queueName: string): Promise<void> {\n await this.ensureScopedHandlers()\n\n const firstMessage = batch.messages[0]?.body as QueueMessage | undefined\n const locale = firstMessage?.metadata?.locale ?? 'en'\n const mockRouterContext = this.createMockRouterContext(locale)\n\n await this._container.runInRequestScope(mockRouterContext, async (requestContainer) => {\n try {\n const queueManager = requestContainer.resolve<QueueManager>(DI_TOKENS.Queue)\n await queueManager.processBatch(queueName, batch)\n } catch (error) {\n const handler = requestContainer.resolve<ExceptionHandler>(DI_TOKENS.ExceptionHandler)\n await handler.handle(error, createQueueExceptionContext(queueName))\n throw error\n }\n })\n }\n\n async handleScheduled(controller: ScheduledController): Promise<void> {\n const cronManager = await this.ensureCron()\n // A scheduled job is a non-HTTP scope that can emit events and dispatch to\n // queues (timeout/reminder/digest emails) — wire both so dispatches aren't\n // silently dropped by the sync provider. i18n is ensured independently for\n // the job execution context. All inits are memoized, so this is idempotent.\n await this.ensureScopedHandlers()\n await this.ensureI18n()\n\n const mockRouterContext = this.createMockRouterContext('en')\n\n await this._container.runInRequestScope(mockRouterContext, async (requestContainer) => {\n try {\n await cronManager.executeScheduled(controller, requestContainer)\n } catch (error) {\n const handler = requestContainer.resolve<ExceptionHandler>(DI_TOKENS.ExceptionHandler)\n await handler.handle(error, createCronExceptionContext())\n throw error\n }\n })\n }\n\n createMockRouterContext(locale = 'en'): RouterContext {\n return {\n getLocale: () => locale,\n setLocale: () => { /* no-op */ },\n // Inside runInRequestScope the active container is the request-scoped child\n // (set in AsyncLocalStorage); return it so request-scoped providers resolve\n // against the scope, not the global container.\n getContainer: () => containerStorage.getStore() ?? this._container,\n } as unknown as RouterContext\n }\n\n async shutdown(): Promise<void> {\n if (!this.initialized) return\n this.initialized = false\n\n await this.moduleRegistry.shutdown()\n\n const logger = this._container.resolve<LoggerService>(LOGGER_TOKENS.LoggerService)\n logger.info('Disposing container...')\n\n this._container.dispose()\n }\n\n async handleCommand(name: string, input?: CommandInput): Promise<CommandResult> {\n // Routing first: commands generate URLs via route() (e.g. tenant:bootstrap\n // prints tenant URLs / builds email links).\n await this.initializeRouting()\n // A CLI command is a non-HTTP scope that can dispatch to queues and emit\n // events from arbitrary user code (e.g. tenant:bootstrap → email.send /\n // tenant.geo.seed). Without this the dev/CLI sync provider finds zero\n // consumers and silently drops every dispatched message. All inits are\n // memoized, so the events half (already wired by routing) is a no-op here.\n await this.ensureScopedHandlers()\n // Resolve QuarryRegistry lazily (deferred from bootstrap)\n this.quarry ??= this._container.resolve<QuarryRegistry>(DI_TOKENS.Quarry)\n const mockContext = this.createMockRouterContext('en')\n return this._container.runInRequestScope(mockContext, async () => {\n return this.quarry.call(name, input)\n })\n }\n\n private initializeRouting(): Promise<void> {\n this.routingInitPromise ??= runWithContainer(this._container, async () => {\n await this.initializeEventListeners()\n await this.ensureI18n()\n const { OpenAPIModule } = await import('./openapi')\n this.moduleRegistry.register(OpenAPIModule as unknown as ModuleClass)\n await this.registerRoutingServices()\n this.honoApp = this._container.resolve<HonoApp>(ROUTER_TOKENS.HonoApp)\n await this.honoApp.configure()\n })\n return this.routingInitPromise\n }\n\n private registerCommands(): void {\n this.quarry ??= this._container.resolve<QuarryRegistry>(DI_TOKENS.Quarry)\n const commands = this.moduleRegistry.getAllCommands()\n for (const CommandClass of commands) {\n this.quarry.register(CommandClass as Constructor<Command>)\n }\n }\n\n private registerSeeders(): void {\n const seeders = this.moduleRegistry.getAllSeeders()\n if (seeders.length === 0) return\n const registry = this._container.resolve<SeederRegistry>(SEEDER_TOKENS.SeederRegistry)\n for (const SeederClass of seeders) {\n registry.register(SeederClass as Constructor<Seeder>)\n }\n }\n\n private async registerQueueConsumers(): Promise<void> {\n const consumerClasses = this.moduleRegistry.getAllConsumers()\n if (consumerClasses.length === 0) return\n\n // Consumers are resolved fresh per message at dispatch time (see\n // QueueManager / SyncQueueProvider). Here we only need each consumer's\n // declared message types; read them from a throwaway instance built inside a\n // request scope so a consumer that injects request-scoped providers\n // (@InjectQueue, i18n, auth context, …) doesn't fail to instantiate at boot.\n const mockContext = this.createMockRouterContext('en')\n await this._container.runInRequestScope(mockContext, (requestContainer) => {\n for (const ConsumerClass of consumerClasses) {\n const consumer = requestContainer.resolve(ConsumerClass) as IQueueConsumer\n this.consumerRegistry.register(\n ConsumerClass as Constructor<IQueueConsumer>,\n consumer.messageTypes,\n )\n }\n })\n }\n\n private registerCronJobs(cronManager: CronManager): void {\n for (const JobClass of this.moduleRegistry.getAllJobs()) {\n const schedule = (JobClass as unknown as { schedule: string }).schedule\n if (schedule) {\n cronManager.registerJob(schedule, JobClass as Constructor<CronJob>)\n } else {\n const logger = this._container.resolve<LoggerService>(LOGGER_TOKENS.LoggerService)\n logger.warn(`Cron job \"${JobClass.name}\" has no static schedule property — skipped`)\n }\n }\n }\n\n private registerEventListeners(): void {\n const listeners = this.moduleRegistry.getAllListeners()\n if (listeners.length === 0) {\n return\n }\n\n const eventRegistry = this._container.resolve<EventRegistry>(DI_TOKENS.EventRegistry)\n\n for (const ListenerClass of listeners) {\n const handlers = getListenerHandlers(ListenerClass)\n\n for (const { methodName, event, options } of handlers) {\n // Resolve the listener fresh per event from the active scope (events are\n // emitted inside an HTTP request or runInScope), so request-scoped\n // listener dependencies bind to the emitting request rather than being\n // frozen at boot. Listener metadata is read from the class statically —\n // no instance is created until an event actually fires.\n const handler: EventHandler = ((...args: unknown[]) => {\n const instance = getContainer().resolve(ListenerClass) as Record<\n string,\n (...a: unknown[]) => unknown\n >\n return instance[methodName](...args)\n }) as EventHandler\n\n eventRegistry.on(event, handler, options)\n }\n }\n }\n\n private registerLoggerService(): void {\n const logLevel = this.appConfig.logging?.level ?? LogLevel.INFO\n const formatter = this.appConfig.logging?.formatter ?? 'json'\n\n this._container.registerValue(LOGGER_TOKENS.LogLevelOptions, logLevel)\n\n this._container\n .when(() => formatter === 'pretty')\n .use(LOGGER_TOKENS.Formatter)\n .give(PrettyFormatter)\n .otherwise(JsonFormatter)\n\n this._container.registerSingleton(LOGGER_TOKENS.LoggerService, LoggerService)\n }\n\n /**\n * Bootstrap kernel — registered imperatively because they cannot be expressed\n * as ordinary module providers: ExceptionHandler is a user-overridable forced\n * singleton (a module ClassProvider derives scope from the class decorator,\n * which a user handler may not carry), and LazyModuleLoader is the loader\n * itself. Subsystem registries (events/cron/quarry/seeder) are modules.\n */\n private registerCoreServices(): void {\n this._container.registerSingleton(\n DI_TOKENS.ExceptionHandler,\n (this.appConfig.exceptionHandler ?? DefaultExceptionHandler) as Constructor,\n )\n this._container.registerSingleton(DI_TOKENS.LazyModuleLoader, LazyModuleLoader)\n }\n\n private initializeExceptionHandler(): void {\n const handler = this._container.resolve<ExceptionHandler>(DI_TOKENS.ExceptionHandler)\n handler.register()\n this.moduleRegistry.configureExceptionHandlers(handler)\n }\n}\n","import { Application, type ApplicationConfig } from './application'\nimport type { StratalEnv } from './env'\nimport { StratalNotInitializedError } from './errors'\nimport type { HonoApp } from './router/hono-app'\n\n/**\n * Stratal — Hono-style entry point for Cloudflare Workers.\n *\n * Eagerly bootstraps the Application at construction time, dynamically\n * importing `cloudflare:workers` for env and waitUntil.\n *\n * @example\n * ```typescript\n * import { Stratal } from 'stratal'\n * import { AppModule } from './app.module'\n *\n * export default new Stratal({ module: AppModule })\n * ```\n */\nexport class Stratal<Env extends StratalEnv = StratalEnv> {\n private app: Application | null = null\n private initPromise: Promise<Application>\n\n private static _application: Promise<Application> | null = null\n private static _generation = 0\n private static _previousInstance: Stratal | null = null\n\n constructor(config: ApplicationConfig) {\n this.fetch = this.fetch.bind(this)\n this.queue = this.queue.bind(this)\n this.scheduled = this.scheduled.bind(this)\n\n // Invalidate any in-flight initialization from a previous instance (Vite HMR reload)\n const generation = ++Stratal._generation\n\n if (Stratal._previousInstance) {\n void Stratal._previousInstance.shutdown()\n }\n Stratal._previousInstance = this\n\n this.initPromise = this.prepareApp(config, generation)\n Stratal._application = this.initPromise\n }\n\n async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {\n const app = await this.ensureReady()\n const hono = await app.ensureHono()\n return hono.fetch(request, env, ctx)\n }\n\n async queue(batch: MessageBatch): Promise<void> {\n const app = await this.ensureReady()\n return app.handleQueue(batch, batch.queue)\n }\n\n async scheduled(controller: ScheduledController): Promise<void> {\n const app = await this.ensureReady()\n return app.handleScheduled(controller)\n }\n\n get hono(): Promise<HonoApp> {\n return this.initPromise.then(app => app.ensureHono())\n }\n\n async shutdown(): Promise<void> {\n try { this.app = await this.initPromise } catch { /* ignore */ }\n if (this.app) {\n await this.app.shutdown()\n this.app = null\n }\n }\n\n /**\n * @internal\n * Resolves the Application instance from the static singleton.\n * Used by worker base classes (DurableObject, Workflow, WorkerEntrypoint)\n * to access the DI container without going through Cloudflare RPC.\n */\n static resolveApplication(): Promise<Application> {\n if (!Stratal._application) {\n throw new StratalNotInitializedError()\n }\n return Stratal._application\n }\n\n private async ensureReady(): Promise<Application> {\n this.app ??= await this.initPromise;\n return this.app\n }\n\n private async prepareApp(config: ApplicationConfig, generation: number): Promise<Application> {\n const { env, waitUntil } = await import('cloudflare:workers')\n\n // After async import, check if a newer instance has replaced us (Vite HMR reload)\n if (generation !== Stratal._generation) {\n return new Promise<Application>(() => {\n //\n }) // Never resolves — avoids cross-request promise warning\n }\n\n const app = new Application({ ...config, env: env as Env, ctx: { waitUntil } })\n await app.initialize()\n\n // Check again after initialization completes\n if (generation !== Stratal._generation) {\n await app.shutdown()\n return new Promise<Application>(() => {\n //\n })\n }\n\n return app\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { ct as Application, gn as HonoApp, lt as ApplicationConfig } from "./index-B_JoEl3V.mjs";
2
+ import { t as StratalEnv } from "./env-ug22bJj7.mjs";
3
+
4
+ //#region src/stratal.d.ts
5
+ /**
6
+ * Stratal — Hono-style entry point for Cloudflare Workers.
7
+ *
8
+ * Eagerly bootstraps the Application at construction time, dynamically
9
+ * importing `cloudflare:workers` for env and waitUntil.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { Stratal } from 'stratal'
14
+ * import { AppModule } from './app.module'
15
+ *
16
+ * export default new Stratal({ module: AppModule })
17
+ * ```
18
+ */
19
+ declare class Stratal<Env extends StratalEnv = StratalEnv> {
20
+ private app;
21
+ private initPromise;
22
+ private static _application;
23
+ private static _generation;
24
+ private static _previousInstance;
25
+ constructor(config: ApplicationConfig);
26
+ fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response>;
27
+ queue(batch: MessageBatch): Promise<void>;
28
+ scheduled(controller: ScheduledController): Promise<void>;
29
+ get hono(): Promise<HonoApp>;
30
+ shutdown(): Promise<void>;
31
+ /**
32
+ * @internal
33
+ * Resolves the Application instance from the static singleton.
34
+ * Used by worker base classes (DurableObject, Workflow, WorkerEntrypoint)
35
+ * to access the DI container without going through Cloudflare RPC.
36
+ */
37
+ static resolveApplication(): Promise<Application>;
38
+ private ensureReady;
39
+ private prepareApp;
40
+ }
41
+ //#endregion
42
+ export { Stratal as t };
43
+ //# sourceMappingURL=stratal-DwDJPY9N.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stratal-DwDJPY9N.d.mts","names":[],"sources":["../src/stratal.ts"],"mappings":";;;;;AAmBA;;;;;;;;;;;;;cAAa,OAAA,aAAoB,UAAA,GAAa,UAAA;EAAA,QACpC,GAAA;EAAA,QACA,WAAA;EAAA,eAEO,YAAA;EAAA,eACA,WAAA;EAAA,eACA,iBAAA;cAEH,MAAA,EAAQ,iBAAA;EAiBd,KAAA,CAAM,OAAA,EAAS,OAAA,EAAS,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,gBAAA,GAAmB,OAAA,CAAQ,QAAA;EAMlE,KAAA,CAAM,KAAA,EAAO,YAAA,GAAe,OAAA;EAK5B,SAAA,CAAU,UAAA,EAAY,mBAAA,GAAsB,OAAA;EAAA,IAK9C,IAAA,IAAQ,OAAA,CAAQ,OAAA;EAId,QAAA,IAAY,OAAA;EA5CV;;;;;;EAAA,OA0DD,kBAAA,IAAsB,OAAA,CAAQ,WAAA;EAAA,QAOvB,WAAA;EAAA,QAKA,UAAA;AAAA"}