stratal 0.0.26 → 0.1.0

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 (284) hide show
  1. package/CHANGELOG.md +912 -0
  2. package/README.md +96 -14
  3. package/dist/bin/cloudflare-workers-loader.mjs +18 -3
  4. package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
  5. package/dist/bin/quarry.mjs +85 -14
  6. package/dist/bin/quarry.mjs.map +1 -1
  7. package/dist/cache/index.d.mts +8 -9
  8. package/dist/cache/index.d.mts.map +1 -1
  9. package/dist/cache/index.mjs +56 -17
  10. package/dist/cache/index.mjs.map +1 -1
  11. package/dist/{cache.service-uElmBtdS.d.mts → cache.service-Dg0Hj0gp.d.mts} +27 -12
  12. package/dist/cache.service-Dg0Hj0gp.d.mts.map +1 -0
  13. package/dist/{command-DoBD2Cwl.d.mts → command-BXMccV_9.d.mts} +6 -3
  14. package/dist/command-BXMccV_9.d.mts.map +1 -0
  15. package/dist/{command-BvmUAPPQ.mjs → command-Bb820B6W.mjs} +36 -13
  16. package/dist/command-Bb820B6W.mjs.map +1 -0
  17. package/dist/common.schemas-BigQCwYB.mjs +89 -0
  18. package/dist/common.schemas-BigQCwYB.mjs.map +1 -0
  19. package/dist/config/index.d.mts +15 -15
  20. package/dist/config/index.d.mts.map +1 -1
  21. package/dist/config/index.mjs +4 -6
  22. package/dist/config/index.mjs.map +1 -1
  23. package/dist/{consumer-registry-D3iMTSdy.d.mts → consumer-registry-i9oCdarv.d.mts} +2 -3
  24. package/dist/consumer-registry-i9oCdarv.d.mts.map +1 -0
  25. package/dist/{container-storage-BmOJ4_Na.mjs → container-storage-DfF7SXdV.mjs} +11 -1
  26. package/dist/container-storage-DfF7SXdV.mjs.map +1 -0
  27. package/dist/{controller.decorator-YSTPQntu.mjs → controller.decorator-BB0JcwMg.mjs} +18 -9
  28. package/dist/controller.decorator-BB0JcwMg.mjs.map +1 -0
  29. package/dist/cron/index.d.mts +6 -7
  30. package/dist/cron/index.d.mts.map +1 -1
  31. package/dist/cron/index.mjs +1 -1
  32. package/dist/{cron-job-NesZRk8F.d.mts → cron-job-DAgNw4Bn.d.mts} +1 -2
  33. package/dist/cron-job-DAgNw4Bn.d.mts.map +1 -0
  34. package/dist/{cron.module-C81HTzR7.mjs → cron.module-Dnyl9sFk.mjs} +6 -7
  35. package/dist/{cron.module-C81HTzR7.mjs.map → cron.module-Dnyl9sFk.mjs.map} +1 -1
  36. package/dist/{decorate-CuAoSZvs.mjs → decorate-C79yt3Wt.mjs} +2 -2
  37. package/dist/di/index.d.mts +1 -1
  38. package/dist/di/index.mjs +2 -3
  39. package/dist/{di-D7qmrAir.mjs → di-DQ3xbjgf.mjs} +48 -6
  40. package/dist/di-DQ3xbjgf.mjs.map +1 -0
  41. package/dist/email/index.d.mts +158 -133
  42. package/dist/email/index.d.mts.map +1 -1
  43. package/dist/email/index.mjs +66 -78
  44. package/dist/email/index.mjs.map +1 -1
  45. package/dist/{en-CDZBMcc1.mjs → en-CCL84z4k.mjs} +2 -2
  46. package/dist/{en-CDZBMcc1.mjs.map → en-CCL84z4k.mjs.map} +1 -1
  47. package/dist/env-ug22bJj7.d.mts.map +1 -1
  48. package/dist/errors/index.d.mts +1 -1
  49. package/dist/errors/index.mjs +3 -3
  50. package/dist/{errors-C01O2T-n.mjs → errors-CrOXI_y5.mjs} +6 -8
  51. package/dist/errors-CrOXI_y5.mjs.map +1 -0
  52. package/dist/events/index.d.mts +8 -9
  53. package/dist/events/index.d.mts.map +1 -1
  54. package/dist/events/index.mjs +1 -1
  55. package/dist/{events-BhEQuT1X.mjs → events-GtwGEHyT.mjs} +5 -6
  56. package/dist/events-GtwGEHyT.mjs.map +1 -0
  57. package/dist/{exception-context-D-kvney-.mjs → exception-context-CdnGTQNF.mjs} +13 -7
  58. package/dist/exception-context-CdnGTQNF.mjs.map +1 -0
  59. package/dist/{gateway-context-m7kEzRa2.mjs → gateway-context-Cmc1NRS0.mjs} +7 -7
  60. package/dist/{gateway-context-m7kEzRa2.mjs.map → gateway-context-Cmc1NRS0.mjs.map} +1 -1
  61. package/dist/gateway-mode-0rUaeW3g.mjs +53 -0
  62. package/dist/gateway-mode-0rUaeW3g.mjs.map +1 -0
  63. package/dist/guards/index.d.mts +38 -20
  64. package/dist/guards/index.d.mts.map +1 -1
  65. package/dist/guards/index.mjs +2 -2
  66. package/dist/{guards-DALPXy3_.mjs → guards-DOGly9IF.mjs} +34 -11
  67. package/dist/guards-DOGly9IF.mjs.map +1 -0
  68. package/dist/hono-app-IhdqL0Fk.mjs +399 -0
  69. package/dist/hono-app-IhdqL0Fk.mjs.map +1 -0
  70. package/dist/{http-method.decorator-BljM8BDj.mjs → http-method.decorator-BDi9LTWj.mjs} +9 -8
  71. package/dist/http-method.decorator-BDi9LTWj.mjs.map +1 -0
  72. package/dist/i18n/index.d.mts +26 -137
  73. package/dist/i18n/index.d.mts.map +1 -1
  74. package/dist/i18n/index.mjs +4 -5
  75. package/dist/i18n/index.mjs.map +1 -1
  76. package/dist/i18n/messages/en/index.d.mts +1 -1
  77. package/dist/i18n/messages/en/index.mjs +1 -1
  78. package/dist/i18n/utils/index.d.mts +1 -2
  79. package/dist/i18n/utils/index.d.mts.map +1 -1
  80. package/dist/i18n/validation/index.d.mts +80 -5
  81. package/dist/i18n/validation/index.d.mts.map +1 -0
  82. package/dist/i18n/validation/index.mjs +4 -5
  83. package/dist/{i18n.module-B2DvWUPa.mjs → i18n.module-Bm3xlViA.mjs} +28 -13
  84. package/dist/i18n.module-Bm3xlViA.mjs.map +1 -0
  85. package/dist/index-0ItCjaqw.d.mts.map +1 -1
  86. package/dist/{index-CNuFQSNj.d.mts → index-3HJfhLlE.d.mts} +9 -11
  87. package/dist/index-3HJfhLlE.d.mts.map +1 -0
  88. package/dist/{index-uybm0bhQ.d.mts → index-B2WtEagR.d.mts} +1187 -234
  89. package/dist/index-B2WtEagR.d.mts.map +1 -0
  90. package/dist/index-BUt92sAE.d.mts.map +1 -1
  91. package/dist/index-CAHNCpvr.d.mts +203 -0
  92. package/dist/index-CAHNCpvr.d.mts.map +1 -0
  93. package/dist/index.d.mts +4 -4
  94. package/dist/index.mjs +2 -2
  95. package/dist/{is-command-CEPO9n8c.mjs → is-command-CSVv14wh.mjs} +2 -2
  96. package/dist/{is-command-CEPO9n8c.mjs.map → is-command-CSVv14wh.mjs.map} +1 -1
  97. package/dist/{is-seeder-Gvh_AM71.mjs → is-seeder-gLgXYbqC.mjs} +2 -2
  98. package/dist/is-seeder-gLgXYbqC.mjs.map +1 -0
  99. package/dist/{lazy-module-loader-M6YKudNL.d.mts → lazy-module-loader-C3OHoUnR.d.mts} +4 -5
  100. package/dist/lazy-module-loader-C3OHoUnR.d.mts.map +1 -0
  101. package/dist/limit-BE0HNAF6.mjs +116 -0
  102. package/dist/limit-BE0HNAF6.mjs.map +1 -0
  103. package/dist/locale-path.service-BqzDIrgy.mjs +213 -0
  104. package/dist/locale-path.service-BqzDIrgy.mjs.map +1 -0
  105. package/dist/locale-url-nZrZxqJP.mjs.map +1 -1
  106. package/dist/{locale-url.service-6bgia24_.mjs → locale-url.service-H8PH6GGh.mjs} +15 -5
  107. package/dist/{locale-url.service-6bgia24_.mjs.map → locale-url.service-H8PH6GGh.mjs.map} +1 -1
  108. package/dist/logger/index.mjs +3 -5
  109. package/dist/logger/index.mjs.map +1 -1
  110. package/dist/macroable-cvDTFZ_A.mjs.map +1 -1
  111. package/dist/metadata-Ba8Fxs1F.mjs +48 -0
  112. package/dist/metadata-Ba8Fxs1F.mjs.map +1 -0
  113. package/dist/module/index.d.mts +8 -9
  114. package/dist/module/index.d.mts.map +1 -1
  115. package/dist/module/index.mjs +3 -4
  116. package/dist/module/index.mjs.map +1 -1
  117. package/dist/{module-registry-NxX5O0Qk.mjs → module-registry-lkQPDuQe.mjs} +17 -15
  118. package/dist/module-registry-lkQPDuQe.mjs.map +1 -0
  119. package/dist/{module.decorator-CYHY6pG5.mjs → module.decorator-CYbrOlX9.mjs} +2 -2
  120. package/dist/{module.decorator-CYHY6pG5.mjs.map → module.decorator-CYbrOlX9.mjs.map} +1 -1
  121. package/dist/openapi/index.d.mts +19 -16
  122. package/dist/openapi/index.d.mts.map +1 -1
  123. package/dist/openapi/index.mjs +2 -2
  124. package/dist/{openapi-CMwuCp31.mjs → openapi-DBfBa5Qh.mjs} +41 -65
  125. package/dist/openapi-DBfBa5Qh.mjs.map +1 -0
  126. package/dist/openapi-generator-CCwiu8AU.mjs +134 -0
  127. package/dist/openapi-generator-CCwiu8AU.mjs.map +1 -0
  128. package/dist/{openapi-tools.service-BC5EC3R3.mjs → openapi-tools.service-VKZJlTIX.mjs} +12 -4
  129. package/dist/openapi-tools.service-VKZJlTIX.mjs.map +1 -0
  130. package/dist/openapi.service-Ds-R1tih.d.mts +43 -0
  131. package/dist/openapi.service-Ds-R1tih.d.mts.map +1 -0
  132. package/dist/quarry/index.d.mts +10 -11
  133. package/dist/quarry/index.d.mts.map +1 -1
  134. package/dist/quarry/index.mjs +4 -4
  135. package/dist/quarry/runner.d.mts +19 -20
  136. package/dist/quarry/runner.d.mts.map +1 -1
  137. package/dist/quarry/runner.mjs +16 -13
  138. package/dist/quarry/runner.mjs.map +1 -1
  139. package/dist/{quarry-registry-DRnV-DDa.d.mts → quarry-registry-Ci4k58FZ.d.mts} +3 -4
  140. package/dist/quarry-registry-Ci4k58FZ.d.mts.map +1 -0
  141. package/dist/{quarry.module-CcGxU2dJ.mjs → quarry.module-BssRR8f0.mjs} +20 -37
  142. package/dist/quarry.module-BssRR8f0.mjs.map +1 -0
  143. package/dist/queue/index.d.mts +2 -2
  144. package/dist/queue/index.mjs +3 -3
  145. package/dist/queue/index.mjs.map +1 -1
  146. package/dist/{queue.module-CEs4_kEM.mjs → queue.module-DnAdSbR-.mjs} +40 -41
  147. package/dist/queue.module-DnAdSbR-.mjs.map +1 -0
  148. package/dist/{r2-storage.provider-BoZmR6Ut.mjs → r2-storage.provider-wU_6api4.mjs} +45 -6
  149. package/dist/r2-storage.provider-wU_6api4.mjs.map +1 -0
  150. package/dist/{rate-limit.decorator-Djs4oYDB.mjs → rate-limit.decorator-PYQ9EYqs.mjs} +10 -5
  151. package/dist/{rate-limit.decorator-Djs4oYDB.mjs.map → rate-limit.decorator-PYQ9EYqs.mjs.map} +1 -1
  152. package/dist/rate-limiter/index.d.mts +64 -19
  153. package/dist/rate-limiter/index.d.mts.map +1 -1
  154. package/dist/rate-limiter/index.mjs +67 -83
  155. package/dist/rate-limiter/index.mjs.map +1 -1
  156. package/dist/response-cache/index.d.mts +326 -0
  157. package/dist/response-cache/index.d.mts.map +1 -0
  158. package/dist/response-cache/index.mjs +511 -0
  159. package/dist/response-cache/index.mjs.map +1 -0
  160. package/dist/response-cache.error-B4D0zy9W.mjs +24 -0
  161. package/dist/response-cache.error-B4D0zy9W.mjs.map +1 -0
  162. package/dist/response-headers-BqA57S_X.mjs +158 -0
  163. package/dist/response-headers-BqA57S_X.mjs.map +1 -0
  164. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  165. package/dist/route-cache-binding-CrLh8tB6.mjs +390 -0
  166. package/dist/route-cache-binding-CrLh8tB6.mjs.map +1 -0
  167. package/dist/route-metadata-QQhbed1i.mjs +17 -0
  168. package/dist/route-metadata-QQhbed1i.mjs.map +1 -0
  169. package/dist/{route-name-DGoBOfPg.mjs → route-name-BslSbmMP.mjs} +15 -11
  170. package/dist/route-name-BslSbmMP.mjs.map +1 -0
  171. package/dist/route-registration.service-COKBZTsn.mjs +1265 -0
  172. package/dist/route-registration.service-COKBZTsn.mjs.map +1 -0
  173. package/dist/{route-registry-BvLJisvK.mjs → route-registry-DFz9_-N6.mjs} +6 -6
  174. package/dist/{route-registry-BvLJisvK.mjs.map → route-registry-DFz9_-N6.mjs.map} +1 -1
  175. package/dist/router/index.d.mts +2 -2
  176. package/dist/router/index.mjs +16 -15
  177. package/dist/{router-resolver-sUV_jTrU.mjs → router-resolver-B-dMSMIG.mjs} +7 -3
  178. package/dist/router-resolver-B-dMSMIG.mjs.map +1 -0
  179. package/dist/{router-DwyqEXgf.mjs → router-wlsVkGkM.mjs} +5 -14
  180. package/dist/{router-DwyqEXgf.mjs.map → router-wlsVkGkM.mjs.map} +1 -1
  181. package/dist/seeder/index.d.mts +12 -13
  182. package/dist/seeder/index.d.mts.map +1 -1
  183. package/dist/seeder/index.mjs +4 -4
  184. package/dist/{seeder-BPGY5rUb.mjs → seeder-BrAk7XIj.mjs} +5 -6
  185. package/dist/{seeder-BPGY5rUb.mjs.map → seeder-BrAk7XIj.mjs.map} +1 -1
  186. package/dist/{seeder-registry-DEvCycsT.mjs → seeder-registry-Bo5BgLbC.mjs} +5 -6
  187. package/dist/{seeder-registry-DEvCycsT.mjs.map → seeder-registry-Bo5BgLbC.mjs.map} +1 -1
  188. package/dist/{seeder.module-CIwQbdN4.mjs → seeder.module-DOoVgTsK.mjs} +5 -5
  189. package/dist/{seeder.module-CIwQbdN4.mjs.map → seeder.module-DOoVgTsK.mjs.map} +1 -1
  190. package/dist/signed-url-DIU0sK_6.mjs.map +1 -1
  191. package/dist/storage/index.d.mts +63 -13
  192. package/dist/storage/index.d.mts.map +1 -1
  193. package/dist/storage/index.mjs +2 -2
  194. package/dist/storage/providers/index.d.mts +18 -16
  195. package/dist/storage/providers/index.d.mts.map +1 -1
  196. package/dist/storage/providers/index.mjs +1 -1
  197. package/dist/{storage-C30X81CS.mjs → storage-DBWVYMnn.mjs} +167 -49
  198. package/dist/storage-DBWVYMnn.mjs.map +1 -0
  199. package/dist/storage-provider.interface-CinHpjl1.d.mts +315 -0
  200. package/dist/storage-provider.interface-CinHpjl1.d.mts.map +1 -0
  201. package/dist/storage.error-Ao38Qdjx.mjs +7 -0
  202. package/dist/storage.error-Ao38Qdjx.mjs.map +1 -0
  203. package/dist/{stratal-D5j_I14G.d.mts → stratal-Bs1_E8GQ.d.mts} +13 -3
  204. package/dist/stratal-Bs1_E8GQ.d.mts.map +1 -0
  205. package/dist/{stratal-BL6FKUM_.mjs → stratal-CiwNpWy2.mjs} +56 -23
  206. package/dist/stratal-CiwNpWy2.mjs.map +1 -0
  207. package/dist/{tiered-cache.service-Dv3BhxxE.d.mts → tiered-cache.service-Bz8bbvyb.d.mts} +16 -3
  208. package/dist/tiered-cache.service-Bz8bbvyb.d.mts.map +1 -0
  209. package/dist/trailing-slash-2SctvePW.mjs.map +1 -1
  210. package/dist/types-CmV_9xBD.d.mts.map +1 -1
  211. package/dist/{uri-iwofWJ_T.mjs → uri-BrOq148R.mjs} +13 -9
  212. package/dist/{uri-iwofWJ_T.mjs.map → uri-BrOq148R.mjs.map} +1 -1
  213. package/dist/{usage-generator-DAWYasuP.mjs → usage-generator-BW7EcO-C.mjs} +3 -3
  214. package/dist/{usage-generator-DAWYasuP.mjs.map → usage-generator-BW7EcO-C.mjs.map} +1 -1
  215. package/dist/{zod-eKqqhZ5_.mjs → validation-CZ_B0aXY.mjs} +38 -17
  216. package/dist/validation-CZ_B0aXY.mjs.map +1 -0
  217. package/dist/{validation.context-CRvmrhq7.mjs → validation.context-CdbwQWIr.mjs} +2 -2
  218. package/dist/{validation.context-CRvmrhq7.mjs.map → validation.context-CdbwQWIr.mjs.map} +1 -1
  219. package/dist/{versioning.service-CCa2oYMJ.mjs → versioning.service-DnF_4Lnd.mjs} +5 -5
  220. package/dist/{versioning.service-CCa2oYMJ.mjs.map → versioning.service-DnF_4Lnd.mjs.map} +1 -1
  221. package/dist/websocket/index.d.mts +12 -13
  222. package/dist/websocket/index.d.mts.map +1 -1
  223. package/dist/websocket/index.mjs +1 -1
  224. package/dist/workers/index.d.mts +70 -7
  225. package/dist/workers/index.d.mts.map +1 -1
  226. package/dist/workers/index.mjs +72 -3
  227. package/dist/workers/index.mjs.map +1 -1
  228. package/dist/{zod-wecrEVAs.d.mts → zod-BGisqLs3.d.mts} +9 -16
  229. package/dist/zod-BGisqLs3.d.mts.map +1 -0
  230. package/package.json +33 -25
  231. package/dist/cache.service-uElmBtdS.d.mts.map +0 -1
  232. package/dist/chunk-BBjsoOtd.mjs +0 -27
  233. package/dist/command-BvmUAPPQ.mjs.map +0 -1
  234. package/dist/command-DoBD2Cwl.d.mts.map +0 -1
  235. package/dist/consumer-registry-D3iMTSdy.d.mts.map +0 -1
  236. package/dist/container-storage-BmOJ4_Na.mjs.map +0 -1
  237. package/dist/controller.decorator-YSTPQntu.mjs.map +0 -1
  238. package/dist/cron-job-NesZRk8F.d.mts.map +0 -1
  239. package/dist/di-D7qmrAir.mjs.map +0 -1
  240. package/dist/errors-C01O2T-n.mjs.map +0 -1
  241. package/dist/events-BhEQuT1X.mjs.map +0 -1
  242. package/dist/exception-context-D-kvney-.mjs.map +0 -1
  243. package/dist/guards-DALPXy3_.mjs.map +0 -1
  244. package/dist/hono-app-COAgmutc.mjs +0 -168
  245. package/dist/hono-app-COAgmutc.mjs.map +0 -1
  246. package/dist/http-method.decorator-BljM8BDj.mjs.map +0 -1
  247. package/dist/i18n.module-B2DvWUPa.mjs.map +0 -1
  248. package/dist/index-CNuFQSNj.d.mts.map +0 -1
  249. package/dist/index-DtBNIFuP.d.mts +0 -42
  250. package/dist/index-DtBNIFuP.d.mts.map +0 -1
  251. package/dist/index-HgOLNruQ.d.mts +0 -203
  252. package/dist/index-HgOLNruQ.d.mts.map +0 -1
  253. package/dist/index-uybm0bhQ.d.mts.map +0 -1
  254. package/dist/is-seeder-Gvh_AM71.mjs.map +0 -1
  255. package/dist/lazy-module-loader-M6YKudNL.d.mts.map +0 -1
  256. package/dist/locale-path.service-CH0CaxwH.mjs +0 -165
  257. package/dist/locale-path.service-CH0CaxwH.mjs.map +0 -1
  258. package/dist/metadata-DzzprcID.mjs +0 -39
  259. package/dist/metadata-DzzprcID.mjs.map +0 -1
  260. package/dist/module-registry-NxX5O0Qk.mjs.map +0 -1
  261. package/dist/openapi-CMwuCp31.mjs.map +0 -1
  262. package/dist/openapi-tools.service-BC5EC3R3.mjs.map +0 -1
  263. package/dist/openapi.service-2rvJBCEg.d.mts +0 -50
  264. package/dist/openapi.service-2rvJBCEg.d.mts.map +0 -1
  265. package/dist/quarry-registry-DRnV-DDa.d.mts.map +0 -1
  266. package/dist/quarry.module-CcGxU2dJ.mjs.map +0 -1
  267. package/dist/queue.module-CEs4_kEM.mjs.map +0 -1
  268. package/dist/r2-storage.provider-BoZmR6Ut.mjs.map +0 -1
  269. package/dist/route-name-DGoBOfPg.mjs.map +0 -1
  270. package/dist/route-registration.service-CDPQKpm4.mjs +0 -918
  271. package/dist/route-registration.service-CDPQKpm4.mjs.map +0 -1
  272. package/dist/router-resolver-sUV_jTrU.mjs.map +0 -1
  273. package/dist/storage-C30X81CS.mjs.map +0 -1
  274. package/dist/storage-provider.interface-ClUwxz4S.d.mts +0 -201
  275. package/dist/storage-provider.interface-ClUwxz4S.d.mts.map +0 -1
  276. package/dist/storage.error-BStXPmO4.mjs +0 -8
  277. package/dist/storage.error-BStXPmO4.mjs.map +0 -1
  278. package/dist/stratal-BL6FKUM_.mjs.map +0 -1
  279. package/dist/stratal-D5j_I14G.d.mts.map +0 -1
  280. package/dist/tiered-cache.service-Dv3BhxxE.d.mts.map +0 -1
  281. package/dist/validation-CpOjviyT.mjs +0 -49
  282. package/dist/validation-CpOjviyT.mjs.map +0 -1
  283. package/dist/zod-eKqqhZ5_.mjs.map +0 -1
  284. package/dist/zod-wecrEVAs.d.mts.map +0 -1
@@ -0,0 +1,315 @@
1
+ import { infer as __Infer } from "zod/mini";
2
+ //#region src/storage/types.d.ts
3
+ /**
4
+ * Storage entry configuration
5
+ * Represents a single storage disk backed by Cloudflare R2
6
+ */
7
+ interface StorageEntry {
8
+ disk: string;
9
+ /** R2Bucket binding name from wrangler.toml */
10
+ binding: string;
11
+ root: string;
12
+ }
13
+ /**
14
+ * Presigned URL configuration
15
+ */
16
+ interface PresignedUrlConfig {
17
+ defaultExpiry: number;
18
+ maxExpiry: number;
19
+ }
20
+ /**
21
+ * Storage route configuration
22
+ */
23
+ interface StorageRouteConfig {
24
+ /** Base path for storage routes. Default: '/storage' */
25
+ basePath?: string;
26
+ /** Disable auto-registered storage routes. Default: false */
27
+ disabled?: boolean;
28
+ }
29
+ /**
30
+ * Storage configuration used by framework
31
+ */
32
+ interface StorageConfig {
33
+ storage: StorageEntry[];
34
+ defaultStorageDisk: string;
35
+ presignedUrl: PresignedUrlConfig;
36
+ /** Config for auto-registered storage routes (presigned URL proxying) */
37
+ route?: StorageRouteConfig;
38
+ }
39
+ //#endregion
40
+ //#region src/storage/contracts/delete-file.input.d.ts
41
+ declare const deleteFileInputSchema: import("zod/mini").ZodMiniObject<{
42
+ path: import("zod/mini").ZodMiniString<string>;
43
+ disk: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
44
+ }, import("zod/v4/core").$strip>;
45
+ type DeleteFileInput = __Infer<typeof deleteFileInputSchema>;
46
+ //#endregion
47
+ //#region src/storage/contracts/download-result.d.ts
48
+ /**
49
+ * Download Result
50
+ *
51
+ * Result of downloading a file from storage.
52
+ * Includes the file stream and metadata.
53
+ */
54
+ interface DownloadResult {
55
+ /**
56
+ * ReadableStream of file contents
57
+ */
58
+ toStream(): undefined | ReadableStream<Uint8Array>;
59
+ toString(): undefined | Promise<string>;
60
+ toArrayBuffer(): undefined | Promise<Uint8Array>;
61
+ /**
62
+ * MIME type of the file (e.g., 'application/pdf', 'image/png')
63
+ */
64
+ contentType: string;
65
+ /**
66
+ * Size of the file in bytes
67
+ */
68
+ size: number;
69
+ /**
70
+ * Custom object metadata (S3-specific)
71
+ * Key-value pairs stored with the object
72
+ */
73
+ metadata?: Record<string, string>;
74
+ }
75
+ //#endregion
76
+ //#region src/storage/contracts/file-exists.input.d.ts
77
+ declare const fileExistsInputSchema: import("zod/mini").ZodMiniObject<{
78
+ path: import("zod/mini").ZodMiniString<string>;
79
+ disk: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
80
+ }, import("zod/v4/core").$strip>;
81
+ type FileExistsInput = __Infer<typeof fileExistsInputSchema>;
82
+ //#endregion
83
+ //#region src/storage/contracts/get-presigned-url.input.d.ts
84
+ declare const getPresignedUrlInputSchema: import("zod/mini").ZodMiniObject<{
85
+ path: import("zod/mini").ZodMiniString<string>;
86
+ method: import("zod/mini").ZodMiniDefault<import("zod/mini").ZodMiniEnum<{
87
+ DELETE: "DELETE";
88
+ GET: "GET";
89
+ HEAD: "HEAD";
90
+ PUT: "PUT";
91
+ }>>;
92
+ expiresIn: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniNumber<number>>;
93
+ disk: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
94
+ }, import("zod/v4/core").$strip>;
95
+ type GetPresignedUrlInput = __Infer<typeof getPresignedUrlInputSchema>;
96
+ declare const presignedUrlResultSchema: import("zod/mini").ZodMiniObject<{
97
+ url: import("zod/mini").ZodMiniURL;
98
+ expiresIn: import("zod/mini").ZodMiniNumber<number>;
99
+ expiresAt: import("zod/mini").ZodMiniDate<Date>;
100
+ method: import("zod/mini").ZodMiniEnum<{
101
+ DELETE: "DELETE";
102
+ GET: "GET";
103
+ HEAD: "HEAD";
104
+ PUT: "PUT";
105
+ }>;
106
+ }, import("zod/v4/core").$strip>;
107
+ type PresignedUrlResult = __Infer<typeof presignedUrlResultSchema>;
108
+ //#endregion
109
+ //#region src/storage/contracts/head-result.d.ts
110
+ /**
111
+ * Head Result
112
+ *
113
+ * Metadata for a stored object, read without transferring its body.
114
+ *
115
+ * The point of `head` over `download` is that the body never moves: asking "how big is this"
116
+ * for a hundred objects costs a hundred metadata reads rather than a hundred file transfers.
117
+ */
118
+ interface HeadResult {
119
+ /**
120
+ * Path of the object, relative to the disk root — the same form `download`/`delete` accept,
121
+ * so a result can be fed straight back in without the caller reassembling anything.
122
+ */
123
+ path: string;
124
+ /**
125
+ * Size of the object in bytes.
126
+ */
127
+ size: number;
128
+ /**
129
+ * MIME type recorded at upload, when the provider stored one.
130
+ */
131
+ contentType?: string;
132
+ /**
133
+ * Provider-assigned entity tag, for change detection.
134
+ */
135
+ etag?: string;
136
+ /**
137
+ * When the object was last written, when the provider reports it.
138
+ */
139
+ uploadedAt?: Date;
140
+ /**
141
+ * Custom key-value metadata stored alongside the object.
142
+ */
143
+ metadata?: Record<string, string>;
144
+ }
145
+ //#endregion
146
+ //#region src/storage/contracts/list-result.d.ts
147
+ /**
148
+ * Options for listing stored objects.
149
+ */
150
+ interface ListOptions {
151
+ /**
152
+ * Restrict the listing to objects whose path starts with this prefix, relative to the disk
153
+ * root. Omit to list the whole disk.
154
+ */
155
+ prefix?: string;
156
+ /**
157
+ * Continue a previous listing. Pass the `cursor` from a truncated `ListResult`.
158
+ */
159
+ cursor?: string;
160
+ /**
161
+ * Maximum objects to return in this page. Providers impose their own ceiling — R2 caps a
162
+ * single list at 1000 — so a larger value does not remove the need to follow `cursor`.
163
+ */
164
+ limit?: number;
165
+ /**
166
+ * Populate `contentType` and `metadata` on each listed object.
167
+ *
168
+ * Off by default because it costs page size: R2 returns fewer objects per call when metadata
169
+ * comes with them, so a listing that only needs paths and sizes pays extra round trips for
170
+ * fields it never reads. Turn it on when the listing itself has to inspect content types or
171
+ * custom metadata; leave it off and `head()` the few objects that matter otherwise.
172
+ */
173
+ includeMetadata?: boolean;
174
+ }
175
+ /**
176
+ * One page of a listing.
177
+ *
178
+ * **Listing is paginated, and this type makes that impossible to ignore.** A provider returns at
179
+ * most a page at a time (1000 objects on R2), so code that sums sizes, counts objects, or copies
180
+ * a prefix MUST loop while `truncated` is true, feeding `cursor` back in. Treating the first page
181
+ * as the whole set produces an answer that is quietly too small — and looks entirely reasonable,
182
+ * because nothing failed.
183
+ */
184
+ interface ListResult {
185
+ /**
186
+ * The objects in this page.
187
+ *
188
+ * `path`, `size`, `etag` and `uploadedAt` are always populated. `contentType` and `metadata`
189
+ * are undefined unless the listing asked for them with `includeMetadata`.
190
+ */
191
+ objects: HeadResult[];
192
+ /**
193
+ * True when more objects match than this page contains. When true, `cursor` is set.
194
+ */
195
+ truncated: boolean;
196
+ /**
197
+ * Pass to the next `list` call to continue. Undefined when `truncated` is false.
198
+ */
199
+ cursor?: string;
200
+ }
201
+ //#endregion
202
+ //#region src/storage/contracts/upload-file.input.d.ts
203
+ /**
204
+ * Upload options for streaming uploads
205
+ */
206
+ interface UploadOptions {
207
+ /**
208
+ * Size of the content in bytes
209
+ */
210
+ size: number;
211
+ /**
212
+ * MIME type of the content
213
+ */
214
+ mimeType?: string;
215
+ /**
216
+ * Custom metadata to store with the object (S3-specific)
217
+ * Stored as S3 object metadata headers
218
+ */
219
+ metadata?: Record<string, string>;
220
+ /**
221
+ * Object tagging for lifecycle policies (S3-specific)
222
+ * Format: key=value (e.g., "Tus-Completed=true")
223
+ */
224
+ tagging?: string;
225
+ }
226
+ declare const uploadResultSchema: import("zod/mini").ZodMiniObject<{
227
+ path: import("zod/mini").ZodMiniString<string>;
228
+ disk: import("zod/mini").ZodMiniString<string>;
229
+ fullPath: import("zod/mini").ZodMiniString<string>;
230
+ size: import("zod/mini").ZodMiniNumber<number>;
231
+ mimeType: import("zod/mini").ZodMiniString<string>;
232
+ uploadedAt: import("zod/mini").ZodMiniDate<Date>;
233
+ }, import("zod/v4/core").$strip>;
234
+ type UploadResult = __Infer<typeof uploadResultSchema>;
235
+ //#endregion
236
+ //#region src/storage/providers/storage-provider.interface.d.ts
237
+ /**
238
+ * Streaming blob payload input types
239
+ * Represents the types that can be used as the body of an upload operation
240
+ */
241
+ type StreamingBlobPayloadInputTypes = ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob | null;
242
+ /**
243
+ * Storage provider interface
244
+ * Defines the contract for storage implementations (R2, S3, GCS, etc.)
245
+ */
246
+ interface IStorageProvider {
247
+ /**
248
+ * Upload content to storage
249
+ * @param body - Content to upload (stream, buffer, or string)
250
+ * @param path - Full path including disk root
251
+ * @param options - Upload options including size and mime type
252
+ * @returns Upload result with metadata
253
+ */
254
+ upload(body: StreamingBlobPayloadInputTypes, path: string, options: UploadOptions): Promise<UploadResult>;
255
+ /**
256
+ * Download a file from storage
257
+ * @param path - Full path to the file
258
+ * @returns Download result with stream and metadata
259
+ */
260
+ download(path: string): Promise<DownloadResult>;
261
+ /**
262
+ * Delete a file from storage
263
+ * @param path - Full path to the file
264
+ */
265
+ delete(path: string): Promise<void>;
266
+ /**
267
+ * Delete many files in as few round trips as the provider allows
268
+ * @param paths - Full paths to delete
269
+ */
270
+ deleteMany(paths: string[]): Promise<void>;
271
+ /**
272
+ * Check if a file exists in storage
273
+ * @param path - Full path to the file
274
+ * @returns True if file exists, false otherwise
275
+ */
276
+ exists(path: string): Promise<boolean>;
277
+ /**
278
+ * Read an object's metadata without transferring its body
279
+ * @param path - Full path to the file
280
+ * @returns Metadata, or null when no object exists at that path
281
+ */
282
+ head(path: string): Promise<HeadResult | null>;
283
+ /**
284
+ * List objects, one page at a time
285
+ *
286
+ * Paginated by the provider. A caller that aggregates across a prefix must follow
287
+ * `truncated`/`cursor` — see `ListResult`.
288
+ *
289
+ * @param options - Prefix, cursor and page limit, with paths full rather than disk-relative
290
+ * @returns One page of matching objects
291
+ */
292
+ list(options: ListOptions): Promise<ListResult>;
293
+ /**
294
+ * Generate a presigned URL for temporary access
295
+ * @param path - Full path to the file
296
+ * @param method - HTTP method (GET, PUT, DELETE, HEAD)
297
+ * @param expiresIn - Expiry time in seconds (1-604800)
298
+ * @returns Presigned URL result
299
+ */
300
+ getPresignedUrl(path: string, method: 'GET' | 'PUT' | 'DELETE' | 'HEAD', expiresIn: number): Promise<PresignedUrlResult>;
301
+ /**
302
+ * Chunked upload for streaming data without known size
303
+ * Uses multipart upload under the hood for reliability
304
+ * @param body - Content to upload (stream or buffer)
305
+ * @param path - Full path including disk root
306
+ * @param options - Upload options (mimeType required, size optional)
307
+ * @returns Upload result with metadata
308
+ */
309
+ chunkedUpload(body: StreamingBlobPayloadInputTypes, path: string, options: Omit<UploadOptions, 'size'> & {
310
+ size?: number;
311
+ }): Promise<UploadResult>;
312
+ }
313
+ //#endregion
314
+ export { deleteFileInputSchema as _, uploadResultSchema as a, StorageEntry as b, HeadResult as c, getPresignedUrlInputSchema as d, presignedUrlResultSchema as f, DeleteFileInput as g, DownloadResult as h, UploadResult as i, GetPresignedUrlInput as l, fileExistsInputSchema as m, StreamingBlobPayloadInputTypes as n, ListOptions as o, FileExistsInput as p, UploadOptions as r, ListResult as s, IStorageProvider as t, PresignedUrlResult as u, PresignedUrlConfig as v, StorageRouteConfig as x, StorageConfig as y };
315
+ //# sourceMappingURL=storage-provider.interface-CinHpjl1.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-provider.interface-CinHpjl1.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/head-result.ts","../src/storage/contracts/list-result.ts","../src/storage/contracts/upload-file.input.ts","../src/storage/providers/storage-provider.interface.ts"],"mappings":";;;;;;UAIiB;EAChB;;EAEA;EACA;;;;;UAMgB;EAChB;EACA;;;;;UAMgB;;EAEhB;;EAEA;;;;;UAMgB;EAChB,SAAS;EACT;EACA,cAAc;;EAEd,QAAQ;;;;cCjCI,0CAAqB;;;yBAGhC;KAEU,kBAAkB,eAAa;;;;;;;;;UCH1B;;;;EAIf,wBAAwB,eAAe;EAEvC,wBAAwB;EAExB,6BAA6B,QAAQ;;;;EAKrC;;;;EAKA;;;;;EAMA,WAAW;;;;cC1BA,0CAAqB;;;yBAGhC;KAEU,kBAAkB,eAAa;;;cCH9B,+CAA0B;;;;;;;;;;yBAKrC;KAEU,uBAAuB,eAAa;cAEnC,6CAAwB;;;4CAAxB;;;;;;;yBAKX;KAEU,qBAAqB,eAAa;;;;;;;;;;;UCd7B;;;;;EAKf;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA,aAAa;;;;EAKb,WAAW;;;;;;;UCjCI;;;;;EAKf;;;;EAKA;;;;;EAMA;;;;;;;;;EAUA;;;;;;;;;;;UAYe;;;;;;;EAOf,SAAS;;;;EAKT;;;;EAKA;;;;;;;UCtDe;;;;EAIf;;;;EAIA;;;;;EAKA,WAAW;;;;;EAKX;;cAGW,uCAAkB;;;;;;6CAAlB;yBAOX;KAEU,eAAe,eAAa;;;;;;;KCtB5B,iCACR,iBACA,cACA,2BAEA;;;;;UAOa;;;;;;;;EAQf,OAAO,MAAM,gCAAgC,cAAc,SAAS,gBAAgB,QAAQ;;;;;;EAO5F,SAAS,eAAe,QAAQ;;;;;EAMhC,OAAO,eAAe;;;;;EAMtB,WAAW,kBAAkB;;;;;;EAO7B,OAAO,eAAe;;;;;;EAOtB,KAAK,eAAe,QAAQ;;;;;;;;;;EAW5B,KAAK,SAAS,cAAc,QAAQ;;;;;;;;EASpC,gBACE,cACA,2CACA,oBACC,QAAQ;;;;;;;;;EAUX,cACE,MAAM,gCACN,cACA,SAAS,KAAK;IAA2B;MACxC,QAAQ"}
@@ -0,0 +1,7 @@
1
+ import { a as ApplicationError } from "./container-storage-DfF7SXdV.mjs";
2
+ //#region src/storage/storage.error.ts
3
+ var StorageError = class extends ApplicationError {};
4
+ //#endregion
5
+ export { StorageError as t };
6
+
7
+ //# sourceMappingURL=storage.error-Ao38Qdjx.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.error-Ao38Qdjx.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"}
@@ -1,6 +1,5 @@
1
- import { Sn as HonoApp, ft as Application, pt as ApplicationConfig } from "./index-uybm0bhQ.mjs";
1
+ import { ft as Application, pt as ApplicationConfig, zn as HonoApp } from "./index-B2WtEagR.mjs";
2
2
  import { t as StratalEnv } from "./env-ug22bJj7.mjs";
3
-
4
3
  //#region src/stratal.d.ts
5
4
  /**
6
5
  * Stratal — Hono-style entry point for Cloudflare Workers.
@@ -30,6 +29,17 @@ declare class Stratal<Env extends StratalEnv = StratalEnv> {
30
29
  */
31
30
  private static _teardownChain;
32
31
  constructor(config: ApplicationConfig);
32
+ /**
33
+ * The eyeball entrypoint — and, when `stratal/response-cache`'s gateway is
34
+ * configured, the **gateway**.
35
+ *
36
+ * The execution context is marked before it reaches Hono so the dispatch
37
+ * middleware can tell which of the two entrypoints it is running inside.
38
+ * `cachedEntrypoint` deliberately does not mark, which is what stops the
39
+ * cached entrypoint from dispatching back into itself. The mark lives in a
40
+ * module-private `WeakSet` keyed on this object, so nothing a client sends
41
+ * can set or clear it. It is a no-op for apps that configure no gateway.
42
+ */
33
43
  fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response>;
34
44
  queue(batch: MessageBatch): Promise<void>;
35
45
  scheduled(controller: ScheduledController): Promise<void>;
@@ -50,4 +60,4 @@ declare class Stratal<Env extends StratalEnv = StratalEnv> {
50
60
  }
51
61
  //#endregion
52
62
  export { Stratal as t };
53
- //# sourceMappingURL=stratal-D5j_I14G.d.mts.map
63
+ //# sourceMappingURL=stratal-Bs1_E8GQ.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stratal-Bs1_E8GQ.d.mts","names":[],"sources":["../src/stratal.ts"],"mappings":";;;;;;;;;;;;;;;;;cAoBa,QAAQ,YAAY,aAAa;UACpC;UACA;iBAEO;iBACA;iBACA;;;;;;;iBAOA;EAEf,YAAY,QAAQ;;;;;;;;;;;;EAgDd,MAAM,SAAS,SAAS,KAAK,KAAK,KAAK,mBAAmB,QAAQ;EAMlE,MAAM,OAAO,eAAe;EAK5B,UAAU,YAAY,sBAAsB;MAK9C,QAAQ,QAAQ;EAId,YAAY;;;;;;;;;;SAwBL,sBAAsB,QAAQ;UAkB7B;UAeA"}
@@ -1,11 +1,12 @@
1
- import { b as ROUTER_TOKENS, r as DI_TOKENS, t as Container } from "./di-D7qmrAir.mjs";
2
- import { n as getContainer, r as runWithContainer, t as containerStorage } from "./container-storage-BmOJ4_Na.mjs";
1
+ import { C as ROUTER_TOKENS, r as DI_TOKENS, t as Container } from "./di-DQ3xbjgf.mjs";
2
+ import { n as getContainer, r as runWithContainer, t as containerStorage } from "./container-storage-DfF7SXdV.mjs";
3
3
  import { JsonFormatter, LOGGER_TOKENS, LoggerService, PrettyFormatter } from "./logger/index.mjs";
4
- import { i as StratalNotInitializedError, o as DefaultExceptionHandler, r as StratalSupersededError } from "./errors-C01O2T-n.mjs";
5
- import { i as createQueueExceptionContext, n as createCronExceptionContext, t as createCliExceptionContext } from "./exception-context-D-kvney-.mjs";
6
- import { a as getListenerHandlers } from "./events-BhEQuT1X.mjs";
7
- import { d as LazyModuleLoader, t as ModuleRegistry } from "./module-registry-NxX5O0Qk.mjs";
8
- import { t as SEEDER_TOKENS } from "./seeder-registry-DEvCycsT.mjs";
4
+ import { i as StratalNotInitializedError, o as DefaultExceptionHandler, r as StratalSupersededError } from "./errors-CrOXI_y5.mjs";
5
+ import { i as createQueueExceptionContext, n as createCronExceptionContext, t as createCliExceptionContext } from "./exception-context-CdnGTQNF.mjs";
6
+ import { a as getListenerHandlers } from "./events-GtwGEHyT.mjs";
7
+ import { d as LazyModuleLoader, t as ModuleRegistry } from "./module-registry-lkQPDuQe.mjs";
8
+ import { t as SEEDER_TOKENS } from "./seeder-registry-Bo5BgLbC.mjs";
9
+ import { n as markGatewayMode } from "./gateway-mode-0rUaeW3g.mjs";
9
10
  //#region src/application.ts
10
11
  var Application = class {
11
12
  _container;
@@ -39,10 +40,24 @@ var Application = class {
39
40
  get container() {
40
41
  return this._container;
41
42
  }
43
+ /** The application's logger (the singleton {@link LoggerService}). */
44
+ get logger() {
45
+ return this._container.resolve(LOGGER_TOKENS.LoggerService);
46
+ }
42
47
  async ensureHono() {
43
48
  await this.initializeRouting();
44
49
  return this.honoApp;
45
50
  }
51
+ /**
52
+ * Whether the app registers any HTTP controllers. Cheap (reads the already-
53
+ * populated registry; no routing built) and only meaningful after
54
+ * {@link initialize}. The worker entry uses it to decide whether to pre-warm
55
+ * the routing stack at boot — queue/scheduled-only apps return false and never
56
+ * build routes they won't serve.
57
+ */
58
+ hasHttpRoutes() {
59
+ return this.moduleRegistry.getAllControllers().length > 0;
60
+ }
46
61
  get config() {
47
62
  return this.appConfig;
48
63
  }
@@ -58,7 +73,7 @@ var Application = class {
58
73
  }
59
74
  }
60
75
  async initializeInternal() {
61
- const [{ QuarryModule }, { SeederModule }] = await Promise.all([import("./quarry.module-CcGxU2dJ.mjs").then((n) => n.n), import("./seeder.module-CIwQbdN4.mjs").then((n) => n.n)]);
76
+ const [{ QuarryModule }, { SeederModule }] = await Promise.all([import("./quarry.module-BssRR8f0.mjs").then((n) => n.n), import("./seeder.module-DOoVgTsK.mjs").then((n) => n.n)]);
62
77
  this.moduleRegistry.registerAll([QuarryModule, SeederModule]);
63
78
  this.moduleRegistry.register(this.appConfig.module);
64
79
  await this.moduleRegistry.initialize();
@@ -70,16 +85,18 @@ var Application = class {
70
85
  this.initialized = true;
71
86
  }
72
87
  async registerRoutingServices() {
73
- const [{ HonoApp }, { RouteRegistry }, { RouterResolver }, { VersioningService }, { LocalePathService }, { LocaleUrlService }, { RouteRegistrationService }, { Uri }] = await Promise.all([
74
- import("./hono-app-COAgmutc.mjs").then((n) => n.n),
75
- import("./route-registry-BvLJisvK.mjs").then((n) => n.n),
76
- import("./router-resolver-sUV_jTrU.mjs"),
77
- import("./versioning.service-CCa2oYMJ.mjs").then((n) => n.n),
78
- import("./locale-path.service-CH0CaxwH.mjs").then((n) => n.n),
79
- import("./locale-url.service-6bgia24_.mjs").then((n) => n.n),
80
- import("./route-registration.service-CDPQKpm4.mjs").then((n) => n.n),
81
- import("./uri-iwofWJ_T.mjs").then((n) => n.r)
88
+ const [{ HonoApp }, { RouteRegistry }, { RouterResolver }, { VersioningService }, { LocalePathService }, { LocaleUrlService }, { RouteRegistrationService }, { Uri }, { RouteMetadataRegistry }] = await Promise.all([
89
+ import("./hono-app-IhdqL0Fk.mjs").then((n) => n.n),
90
+ import("./route-registry-DFz9_-N6.mjs").then((n) => n.n),
91
+ import("./router-resolver-B-dMSMIG.mjs"),
92
+ import("./versioning.service-DnF_4Lnd.mjs").then((n) => n.n),
93
+ import("./locale-path.service-BqzDIrgy.mjs").then((n) => n.n),
94
+ import("./locale-url.service-H8PH6GGh.mjs").then((n) => n.n),
95
+ import("./route-registration.service-COKBZTsn.mjs").then((n) => n.n),
96
+ import("./uri-BrOq148R.mjs").then((n) => n.r),
97
+ import("./route-metadata-QQhbed1i.mjs")
82
98
  ]);
99
+ this._container.register(ROUTER_TOKENS.RouteMetadataRegistry, RouteMetadataRegistry);
83
100
  this._container.register(ROUTER_TOKENS.VersioningService, VersioningService);
84
101
  this._container.register(ROUTER_TOKENS.HonoApp, HonoApp);
85
102
  this._container.register(ROUTER_TOKENS.LocalePathService, LocalePathService);
@@ -99,7 +116,7 @@ var Application = class {
99
116
  */
100
117
  initializeEventListeners() {
101
118
  this.eventsInitPromise ??= runWithContainer(this._container, async () => {
102
- const { EventsModule } = await import("./events-BhEQuT1X.mjs").then((n) => n.n);
119
+ const { EventsModule } = await import("./events-GtwGEHyT.mjs").then((n) => n.n);
103
120
  await this.moduleRegistry.registerLazy(EventsModule);
104
121
  this.registerEventListeners();
105
122
  });
@@ -129,7 +146,7 @@ var Application = class {
129
146
  initializeQueue() {
130
147
  this.queueInitPromise ??= runWithContainer(this._container, async () => {
131
148
  await this.ensureI18n();
132
- const { QueueModule } = await import("./queue.module-CEs4_kEM.mjs").then((n) => n.n);
149
+ const { QueueModule } = await import("./queue.module-DnAdSbR-.mjs").then((n) => n.n);
133
150
  this.moduleRegistry.register(QueueModule);
134
151
  this.consumerRegistry = this._container.resolve(DI_TOKENS.ConsumerRegistry);
135
152
  await this.registerQueueConsumers();
@@ -144,7 +161,7 @@ var Application = class {
144
161
  */
145
162
  ensureI18n() {
146
163
  this.i18nInitPromise ??= runWithContainer(this._container, async () => {
147
- const { I18nModule } = await import("./i18n.module-B2DvWUPa.mjs").then((n) => n.n);
164
+ const { I18nModule } = await import("./i18n.module-Bm3xlViA.mjs").then((n) => n.n);
148
165
  await this.moduleRegistry.registerLazy(I18nModule);
149
166
  });
150
167
  return this.i18nInitPromise;
@@ -155,7 +172,7 @@ var Application = class {
155
172
  */
156
173
  ensureCron() {
157
174
  this.cronInitPromise ??= runWithContainer(this._container, async () => {
158
- const { CronModule } = await import("./cron.module-C81HTzR7.mjs").then((n) => n.n);
175
+ const { CronModule } = await import("./cron.module-Dnyl9sFk.mjs").then((n) => n.n);
159
176
  this.moduleRegistry.register(CronModule);
160
177
  this.cronManager = this._container.resolve(DI_TOKENS.Cron);
161
178
  this.registerCronJobs(this.cronManager);
@@ -353,8 +370,19 @@ var Stratal = class Stratal {
353
370
  console.error("[stratal] Initialization failed:", error);
354
371
  });
355
372
  }
373
+ /**
374
+ * The eyeball entrypoint — and, when `stratal/response-cache`'s gateway is
375
+ * configured, the **gateway**.
376
+ *
377
+ * The execution context is marked before it reaches Hono so the dispatch
378
+ * middleware can tell which of the two entrypoints it is running inside.
379
+ * `cachedEntrypoint` deliberately does not mark, which is what stops the
380
+ * cached entrypoint from dispatching back into itself. The mark lives in a
381
+ * module-private `WeakSet` keyed on this object, so nothing a client sends
382
+ * can set or clear it. It is a no-op for apps that configure no gateway.
383
+ */
356
384
  async fetch(request, env, ctx) {
357
- return (await (await this.ensureReady()).ensureHono()).fetch(request, env, ctx);
385
+ return (await (await this.ensureReady()).ensureHono()).fetch(request, env, markGatewayMode(ctx));
358
386
  }
359
387
  async queue(batch) {
360
388
  return (await this.ensureReady()).handleQueue(batch, batch.queue);
@@ -424,10 +452,15 @@ var Stratal = class Stratal {
424
452
  await app.shutdown();
425
453
  throw new StratalSupersededError(generation);
426
454
  }
455
+ if (app.hasHttpRoutes()) try {
456
+ await app.ensureHono();
457
+ } catch (error) {
458
+ app.logger.error("[stratal] Eager route registration failed", error instanceof Error ? error : new Error(String(error)));
459
+ }
427
460
  return app;
428
461
  }
429
462
  };
430
463
  //#endregion
431
464
  export { Application as n, Stratal as t };
432
465
 
433
- //# sourceMappingURL=stratal-BL6FKUM_.mjs.map
466
+ //# sourceMappingURL=stratal-CiwNpWy2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stratal-CiwNpWy2.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 { TrailingSlashConfig, 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?: TrailingSlashConfig\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 /** The application's logger (the singleton {@link LoggerService}). */\n get logger(): LoggerService {\n return this._container.resolve<LoggerService>(LOGGER_TOKENS.LoggerService)\n }\n\n async ensureHono(): Promise<HonoApp> {\n await this.initializeRouting()\n return this.honoApp\n }\n\n /**\n * Whether the app registers any HTTP controllers. Cheap (reads the already-\n * populated registry; no routing built) and only meaningful after\n * {@link initialize}. The worker entry uses it to decide whether to pre-warm\n * the routing stack at boot — queue/scheduled-only apps return false and never\n * build routes they won't serve.\n */\n hasHttpRoutes(): boolean {\n return this.moduleRegistry.getAllControllers().length > 0\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 try {\n await runWithContainer(this._container, () => this.initializeInternal())\n } catch (error) {\n // A failed boot can still hold live resources: every module whose\n // onInitialize already ran (DB pools, timers) and every container-cached\n // singleton. Tear them down here so callers never have to special-case\n // a failed initialize() — shutdown() stays a no-op for it.\n await this.teardown().catch((teardownError: unknown) => {\n console.error('[stratal] Teardown after failed initialization also failed:', teardownError)\n })\n throw error\n }\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 { RouteMetadataRegistry },\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 import('./router/route-metadata'),\n ])\n\n this._container.register(ROUTER_TOKENS.RouteMetadataRegistry, RouteMetadataRegistry)\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 // Non-HTTP scopes have no request headers\n header: () => undefined,\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 // A failed initialize() has already torn itself down — only a fully\n // initialized application owns resources here.\n if (!this.initialized) return\n this.initialized = false\n\n await this.teardown()\n }\n\n /** Releases everything boot acquired: module resources, then the container. */\n private async teardown(): Promise<void> {\n await this.moduleRegistry.shutdown()\n\n const logger = this._container.resolve<LoggerService>(LOGGER_TOKENS.LoggerService)\n logger.info('Disposing container...')\n\n await 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, StratalSupersededError } from './errors'\nimport { markGatewayMode } from './response-cache/gateway-mode'\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 _current: Stratal | null = null\n /**\n * Serializes generation teardown: each new instance appends the previous\n * instance's shutdown here, and `prepareApp` awaits the chain before\n * allocating the new Application. Old and new DI graphs never coexist,\n * so repeated Vite HMR reloads can't accumulate live object graphs.\n */\n private static _teardownChain: Promise<void> = Promise.resolve()\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 const previous = Stratal._current\n Stratal._current = this\n if (previous) {\n Stratal._teardownChain = Stratal._teardownChain\n .then(() => previous.shutdown())\n .catch((error: unknown) => {\n console.error('[stratal] Failed to shut down superseded instance:', error)\n })\n }\n\n // Capture the chain as of THIS construction: it contains only strictly\n // older generations' teardowns. Reading the static inside prepareApp\n // instead would deadlock when this generation is superseded before its\n // first await — it would wait on a chain containing its own shutdown,\n // which waits on this initPromise.\n const teardownBarrier = Stratal._teardownChain\n\n this.initPromise = this.prepareApp(config, generation, teardownBarrier)\n Stratal._application = this.initPromise\n // A superseded generation rejects; without an awaiter (no in-flight\n // request during the reload) that would surface as an unhandled rejection.\n // Anything else is a real bootstrap failure — log it so it isn't invisible\n // until the first request arrives (awaiters still get the rejection).\n this.initPromise.catch((error: unknown) => {\n if (error instanceof StratalSupersededError) return\n console.error('[stratal] Initialization failed:', error)\n })\n }\n\n /**\n * The eyeball entrypoint — and, when `stratal/response-cache`'s gateway is\n * configured, the **gateway**.\n *\n * The execution context is marked before it reaches Hono so the dispatch\n * middleware can tell which of the two entrypoints it is running inside.\n * `cachedEntrypoint` deliberately does not mark, which is what stops the\n * cached entrypoint from dispatching back into itself. The mark lives in a\n * module-private `WeakSet` keyed on this object, so nothing a client sends\n * can set or clear it. It is a no-op for apps that configure no gateway.\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, markGatewayMode(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.ensureReady().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 // If we're still the live generation (explicit shutdown, not supersession),\n // clear the statics so resolveApplication() throws StratalNotInitializedError\n // instead of handing out the disposed Application.\n if (Stratal._current === this) {\n Stratal._current = null\n Stratal._application = 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 * Generations superseded mid-boot reject with {@link StratalSupersededError};\n * this retries against the replacing generation so callers always land on\n * the live Application.\n */\n static async resolveApplication(): Promise<Application> {\n let current = Stratal._application\n while (current) {\n try {\n return await current\n } catch (error) {\n // Superseded by a newer generation while booting — its constructor has\n // already swapped _application; retry against the replacement.\n if (error instanceof StratalSupersededError && Stratal._application !== current) {\n current = Stratal._application\n continue\n }\n throw error\n }\n }\n throw new StratalNotInitializedError()\n }\n\n private async ensureReady(): Promise<Application> {\n if (this.app) return this.app\n try {\n this.app = await this.initPromise\n return this.app\n } catch (error) {\n if (error instanceof StratalSupersededError) {\n // This instance was replaced mid-boot (Vite HMR reload) — serve the\n // request from the generation that replaced it.\n return Stratal.resolveApplication()\n }\n throw error\n }\n }\n\n private async prepareApp(\n config: ApplicationConfig,\n generation: number,\n teardownBarrier: Promise<void>,\n ): Promise<Application> {\n const { env, waitUntil } = await import('cloudflare:workers')\n\n // Let every previous generation finish tearing down before allocating the\n // new DI graph — concurrent old+new graphs are what leak across reloads.\n await teardownBarrier\n\n // After the awaits, check if a newer instance has replaced us (Vite HMR reload)\n if (generation !== Stratal._generation) {\n throw new StratalSupersededError(generation)\n }\n\n const app = new Application({ ...config, env: env, ctx: { waitUntil } })\n await app.initialize()\n\n // Check again after initialization completes\n if (generation !== Stratal._generation) {\n await app.shutdown()\n throw new StratalSupersededError(generation)\n }\n\n // Pre-warm the HTTP routing stack as part of boot when the app serves HTTP,\n // so the first request doesn't pay route registration. Queue/scheduled-only\n // workers (no controllers) skip it and never build routes they won't use.\n //\n // Awaited, not fire-and-forget: Cloudflare Workers only progress async work\n // while a request is being handled, so a detached `void ensureHono()` would\n // either stall until the first request adopts it (no pre-warm) or, if it ran\n // I/O outside a request context, reject — and `initializeRouting` memoizes\n // that promise, so the first real request would await the poisoned promise\n // and fail. Awaiting folds routing into the same init chain `fetch()` already\n // awaits, running in the identical context as the proven `app.initialize()`.\n //\n // A routing failure is logged but not rethrown so it only breaks the HTTP\n // path (the memoized rejection resurfaces per request, as in lazy routing)\n // without taking down queue/scheduled handlers on a mixed worker.\n if (app.hasHttpRoutes()) {\n try {\n await app.ensureHono()\n } catch (error) {\n app.logger.error(\n '[stratal] Eager route registration failed',\n error instanceof Error ? error : new Error(String(error)),\n )\n }\n }\n\n return app\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
- import { t as CacheService } from "./cache.service-uElmBtdS.mjs";
2
-
1
+ import { t as CacheService } from "./cache.service-Dg0Hj0gp.mjs";
3
2
  //#region src/cache/services/tiered-cache.service.d.ts
4
3
  /**
5
4
  * Tiered Cache Service
@@ -65,6 +64,20 @@ declare class TieredCacheService {
65
64
  getWithMetadata<Metadata = unknown>(key: string, typeOrOptions: 'arrayBuffer' | KVNamespaceGetOptions<'arrayBuffer'>): Promise<KVNamespaceGetWithMetadataResult<ArrayBuffer, Metadata>>;
66
65
  getWithMetadata<Metadata = unknown>(key: string, typeOrOptions: 'stream' | KVNamespaceGetOptions<'stream'>): Promise<KVNamespaceGetWithMetadataResult<ReadableStream, Metadata>>;
67
66
  put(key: string, value: string | ArrayBuffer | ArrayBufferView | ReadableStream, options?: KVNamespacePutOptions): Promise<void>;
67
+ /**
68
+ * Write-through put that **awaits the durable L2 write** (throwing on
69
+ * failure) while keeping the isolate-local L1 in lock-step. Use for set-once
70
+ * values whose loss would be a correctness bug — queue idempotency claims,
71
+ * failed-job records. The deferred {@link put} is for best-effort caching.
72
+ *
73
+ * @throws {CacheError} If the KV write fails.
74
+ */
75
+ putDurable(key: string, value: string | ArrayBuffer | ArrayBufferView | ReadableStream, options?: KVNamespacePutOptions): Promise<void>;
76
+ /**
77
+ * Mirror a write into the isolate-local L1: cache string values; drop the
78
+ * entry for binary values, which L1 does not hold.
79
+ */
80
+ private writeThroughL1;
68
81
  delete(key: string): Promise<void>;
69
82
  list<Metadata = unknown>(options?: KVNamespaceListOptions): Promise<KVNamespaceListResult<Metadata>>;
70
83
  /** Read a fresh L1 entry, evicting it if expired. Returns `null` on miss. */
@@ -76,4 +89,4 @@ declare class TieredCacheService {
76
89
  }
77
90
  //#endregion
78
91
  export { TieredCacheService as t };
79
- //# sourceMappingURL=tiered-cache.service-Dv3BhxxE.d.mts.map
92
+ //# sourceMappingURL=tiered-cache.service-Bz8bbvyb.d.mts.map