stratal 0.0.27 → 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.
- package/CHANGELOG.md +912 -0
- package/README.md +96 -14
- package/dist/bin/cloudflare-workers-loader.mjs +18 -3
- package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
- package/dist/bin/quarry.mjs +73 -12
- package/dist/bin/quarry.mjs.map +1 -1
- package/dist/cache/index.d.mts +8 -9
- package/dist/cache/index.d.mts.map +1 -1
- package/dist/cache/index.mjs +56 -17
- package/dist/cache/index.mjs.map +1 -1
- package/dist/{cache.service-uElmBtdS.d.mts → cache.service-Dg0Hj0gp.d.mts} +27 -12
- package/dist/cache.service-Dg0Hj0gp.d.mts.map +1 -0
- package/dist/{command-DoBD2Cwl.d.mts → command-BXMccV_9.d.mts} +6 -3
- package/dist/command-BXMccV_9.d.mts.map +1 -0
- package/dist/{command-BvmUAPPQ.mjs → command-Bb820B6W.mjs} +36 -13
- package/dist/command-Bb820B6W.mjs.map +1 -0
- package/dist/common.schemas-BigQCwYB.mjs +89 -0
- package/dist/common.schemas-BigQCwYB.mjs.map +1 -0
- package/dist/config/index.d.mts +15 -15
- package/dist/config/index.d.mts.map +1 -1
- package/dist/config/index.mjs +4 -6
- package/dist/config/index.mjs.map +1 -1
- package/dist/{consumer-registry-D3iMTSdy.d.mts → consumer-registry-i9oCdarv.d.mts} +2 -3
- package/dist/consumer-registry-i9oCdarv.d.mts.map +1 -0
- package/dist/{container-storage-BmOJ4_Na.mjs → container-storage-DfF7SXdV.mjs} +11 -1
- package/dist/container-storage-DfF7SXdV.mjs.map +1 -0
- package/dist/{controller.decorator-YSTPQntu.mjs → controller.decorator-BB0JcwMg.mjs} +18 -9
- package/dist/controller.decorator-BB0JcwMg.mjs.map +1 -0
- package/dist/cron/index.d.mts +6 -7
- package/dist/cron/index.d.mts.map +1 -1
- package/dist/cron/index.mjs +1 -1
- package/dist/{cron-job-NesZRk8F.d.mts → cron-job-DAgNw4Bn.d.mts} +1 -2
- package/dist/cron-job-DAgNw4Bn.d.mts.map +1 -0
- package/dist/{cron.module-C81HTzR7.mjs → cron.module-Dnyl9sFk.mjs} +6 -7
- package/dist/{cron.module-C81HTzR7.mjs.map → cron.module-Dnyl9sFk.mjs.map} +1 -1
- package/dist/{decorate-CuAoSZvs.mjs → decorate-C79yt3Wt.mjs} +2 -2
- package/dist/di/index.d.mts +1 -1
- package/dist/di/index.mjs +2 -3
- package/dist/{di-D7qmrAir.mjs → di-DQ3xbjgf.mjs} +48 -6
- package/dist/di-DQ3xbjgf.mjs.map +1 -0
- package/dist/email/index.d.mts +158 -133
- package/dist/email/index.d.mts.map +1 -1
- package/dist/email/index.mjs +66 -78
- package/dist/email/index.mjs.map +1 -1
- package/dist/{en-CDZBMcc1.mjs → en-CCL84z4k.mjs} +2 -2
- package/dist/{en-CDZBMcc1.mjs.map → en-CCL84z4k.mjs.map} +1 -1
- package/dist/env-ug22bJj7.d.mts.map +1 -1
- package/dist/errors/index.d.mts +1 -1
- package/dist/errors/index.mjs +3 -3
- package/dist/{errors-C01O2T-n.mjs → errors-CrOXI_y5.mjs} +6 -8
- package/dist/errors-CrOXI_y5.mjs.map +1 -0
- package/dist/events/index.d.mts +8 -9
- package/dist/events/index.d.mts.map +1 -1
- package/dist/events/index.mjs +1 -1
- package/dist/{events-BhEQuT1X.mjs → events-GtwGEHyT.mjs} +5 -6
- package/dist/events-GtwGEHyT.mjs.map +1 -0
- package/dist/{exception-context-D-kvney-.mjs → exception-context-CdnGTQNF.mjs} +13 -7
- package/dist/exception-context-CdnGTQNF.mjs.map +1 -0
- package/dist/{gateway-context-m7kEzRa2.mjs → gateway-context-Cmc1NRS0.mjs} +7 -7
- package/dist/{gateway-context-m7kEzRa2.mjs.map → gateway-context-Cmc1NRS0.mjs.map} +1 -1
- package/dist/gateway-mode-0rUaeW3g.mjs +53 -0
- package/dist/gateway-mode-0rUaeW3g.mjs.map +1 -0
- package/dist/guards/index.d.mts +38 -20
- package/dist/guards/index.d.mts.map +1 -1
- package/dist/guards/index.mjs +2 -2
- package/dist/{guards-DALPXy3_.mjs → guards-DOGly9IF.mjs} +34 -11
- package/dist/guards-DOGly9IF.mjs.map +1 -0
- package/dist/hono-app-IhdqL0Fk.mjs +399 -0
- package/dist/hono-app-IhdqL0Fk.mjs.map +1 -0
- package/dist/{http-method.decorator-BljM8BDj.mjs → http-method.decorator-BDi9LTWj.mjs} +9 -8
- package/dist/http-method.decorator-BDi9LTWj.mjs.map +1 -0
- package/dist/i18n/index.d.mts +26 -137
- package/dist/i18n/index.d.mts.map +1 -1
- package/dist/i18n/index.mjs +4 -5
- package/dist/i18n/index.mjs.map +1 -1
- package/dist/i18n/messages/en/index.d.mts +1 -1
- package/dist/i18n/messages/en/index.mjs +1 -1
- package/dist/i18n/utils/index.d.mts +1 -2
- package/dist/i18n/utils/index.d.mts.map +1 -1
- package/dist/i18n/validation/index.d.mts +80 -5
- package/dist/i18n/validation/index.d.mts.map +1 -0
- package/dist/i18n/validation/index.mjs +4 -5
- package/dist/{i18n.module-B2DvWUPa.mjs → i18n.module-Bm3xlViA.mjs} +28 -13
- package/dist/i18n.module-Bm3xlViA.mjs.map +1 -0
- package/dist/index-0ItCjaqw.d.mts.map +1 -1
- package/dist/{index-CNuFQSNj.d.mts → index-3HJfhLlE.d.mts} +9 -11
- package/dist/index-3HJfhLlE.d.mts.map +1 -0
- package/dist/{index-uybm0bhQ.d.mts → index-B2WtEagR.d.mts} +1187 -234
- package/dist/index-B2WtEagR.d.mts.map +1 -0
- package/dist/index-BUt92sAE.d.mts.map +1 -1
- package/dist/index-CAHNCpvr.d.mts +203 -0
- package/dist/index-CAHNCpvr.d.mts.map +1 -0
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +2 -2
- package/dist/{is-command-CEPO9n8c.mjs → is-command-CSVv14wh.mjs} +2 -2
- package/dist/{is-command-CEPO9n8c.mjs.map → is-command-CSVv14wh.mjs.map} +1 -1
- package/dist/{is-seeder-Gvh_AM71.mjs → is-seeder-gLgXYbqC.mjs} +2 -2
- package/dist/is-seeder-gLgXYbqC.mjs.map +1 -0
- package/dist/{lazy-module-loader-M6YKudNL.d.mts → lazy-module-loader-C3OHoUnR.d.mts} +4 -5
- package/dist/lazy-module-loader-C3OHoUnR.d.mts.map +1 -0
- package/dist/limit-BE0HNAF6.mjs +116 -0
- package/dist/limit-BE0HNAF6.mjs.map +1 -0
- package/dist/locale-path.service-BqzDIrgy.mjs +213 -0
- package/dist/locale-path.service-BqzDIrgy.mjs.map +1 -0
- package/dist/locale-url-nZrZxqJP.mjs.map +1 -1
- package/dist/{locale-url.service-6bgia24_.mjs → locale-url.service-H8PH6GGh.mjs} +15 -5
- package/dist/{locale-url.service-6bgia24_.mjs.map → locale-url.service-H8PH6GGh.mjs.map} +1 -1
- package/dist/logger/index.mjs +3 -5
- package/dist/logger/index.mjs.map +1 -1
- package/dist/macroable-cvDTFZ_A.mjs.map +1 -1
- package/dist/metadata-Ba8Fxs1F.mjs +48 -0
- package/dist/metadata-Ba8Fxs1F.mjs.map +1 -0
- package/dist/module/index.d.mts +8 -9
- package/dist/module/index.d.mts.map +1 -1
- package/dist/module/index.mjs +3 -4
- package/dist/module/index.mjs.map +1 -1
- package/dist/{module-registry-NxX5O0Qk.mjs → module-registry-lkQPDuQe.mjs} +17 -15
- package/dist/module-registry-lkQPDuQe.mjs.map +1 -0
- package/dist/{module.decorator-CYHY6pG5.mjs → module.decorator-CYbrOlX9.mjs} +2 -2
- package/dist/{module.decorator-CYHY6pG5.mjs.map → module.decorator-CYbrOlX9.mjs.map} +1 -1
- package/dist/openapi/index.d.mts +19 -16
- package/dist/openapi/index.d.mts.map +1 -1
- package/dist/openapi/index.mjs +2 -2
- package/dist/{openapi-CMwuCp31.mjs → openapi-DBfBa5Qh.mjs} +41 -65
- package/dist/openapi-DBfBa5Qh.mjs.map +1 -0
- package/dist/openapi-generator-CCwiu8AU.mjs +134 -0
- package/dist/openapi-generator-CCwiu8AU.mjs.map +1 -0
- package/dist/{openapi-tools.service-BC5EC3R3.mjs → openapi-tools.service-VKZJlTIX.mjs} +12 -4
- package/dist/openapi-tools.service-VKZJlTIX.mjs.map +1 -0
- package/dist/openapi.service-Ds-R1tih.d.mts +43 -0
- package/dist/openapi.service-Ds-R1tih.d.mts.map +1 -0
- package/dist/quarry/index.d.mts +10 -11
- package/dist/quarry/index.d.mts.map +1 -1
- package/dist/quarry/index.mjs +4 -4
- package/dist/quarry/runner.d.mts +19 -20
- package/dist/quarry/runner.d.mts.map +1 -1
- package/dist/quarry/runner.mjs +16 -13
- package/dist/quarry/runner.mjs.map +1 -1
- package/dist/{quarry-registry-DRnV-DDa.d.mts → quarry-registry-Ci4k58FZ.d.mts} +3 -4
- package/dist/quarry-registry-Ci4k58FZ.d.mts.map +1 -0
- package/dist/{quarry.module-CcGxU2dJ.mjs → quarry.module-BssRR8f0.mjs} +20 -37
- package/dist/quarry.module-BssRR8f0.mjs.map +1 -0
- package/dist/queue/index.d.mts +2 -2
- package/dist/queue/index.mjs +3 -3
- package/dist/queue/index.mjs.map +1 -1
- package/dist/{queue.module-CEs4_kEM.mjs → queue.module-DnAdSbR-.mjs} +40 -41
- package/dist/queue.module-DnAdSbR-.mjs.map +1 -0
- package/dist/{r2-storage.provider-BoZmR6Ut.mjs → r2-storage.provider-wU_6api4.mjs} +45 -6
- package/dist/r2-storage.provider-wU_6api4.mjs.map +1 -0
- package/dist/{rate-limit.decorator-Djs4oYDB.mjs → rate-limit.decorator-PYQ9EYqs.mjs} +10 -5
- package/dist/{rate-limit.decorator-Djs4oYDB.mjs.map → rate-limit.decorator-PYQ9EYqs.mjs.map} +1 -1
- package/dist/rate-limiter/index.d.mts +64 -19
- package/dist/rate-limiter/index.d.mts.map +1 -1
- package/dist/rate-limiter/index.mjs +67 -83
- package/dist/rate-limiter/index.mjs.map +1 -1
- package/dist/response-cache/index.d.mts +326 -0
- package/dist/response-cache/index.d.mts.map +1 -0
- package/dist/response-cache/index.mjs +511 -0
- package/dist/response-cache/index.mjs.map +1 -0
- package/dist/response-cache.error-B4D0zy9W.mjs +24 -0
- package/dist/response-cache.error-B4D0zy9W.mjs.map +1 -0
- package/dist/response-headers-BqA57S_X.mjs +158 -0
- package/dist/response-headers-BqA57S_X.mjs.map +1 -0
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/dist/route-cache-binding-CrLh8tB6.mjs +390 -0
- package/dist/route-cache-binding-CrLh8tB6.mjs.map +1 -0
- package/dist/route-metadata-QQhbed1i.mjs +17 -0
- package/dist/route-metadata-QQhbed1i.mjs.map +1 -0
- package/dist/{route-name-DGoBOfPg.mjs → route-name-BslSbmMP.mjs} +15 -11
- package/dist/route-name-BslSbmMP.mjs.map +1 -0
- package/dist/route-registration.service-COKBZTsn.mjs +1265 -0
- package/dist/route-registration.service-COKBZTsn.mjs.map +1 -0
- package/dist/{route-registry-BvLJisvK.mjs → route-registry-DFz9_-N6.mjs} +6 -6
- package/dist/{route-registry-BvLJisvK.mjs.map → route-registry-DFz9_-N6.mjs.map} +1 -1
- package/dist/router/index.d.mts +2 -2
- package/dist/router/index.mjs +16 -15
- package/dist/{router-resolver-sUV_jTrU.mjs → router-resolver-B-dMSMIG.mjs} +7 -3
- package/dist/router-resolver-B-dMSMIG.mjs.map +1 -0
- package/dist/{router-DwyqEXgf.mjs → router-wlsVkGkM.mjs} +5 -14
- package/dist/{router-DwyqEXgf.mjs.map → router-wlsVkGkM.mjs.map} +1 -1
- package/dist/seeder/index.d.mts +12 -13
- package/dist/seeder/index.d.mts.map +1 -1
- package/dist/seeder/index.mjs +4 -4
- package/dist/{seeder-BPGY5rUb.mjs → seeder-BrAk7XIj.mjs} +5 -6
- package/dist/{seeder-BPGY5rUb.mjs.map → seeder-BrAk7XIj.mjs.map} +1 -1
- package/dist/{seeder-registry-DEvCycsT.mjs → seeder-registry-Bo5BgLbC.mjs} +5 -6
- package/dist/{seeder-registry-DEvCycsT.mjs.map → seeder-registry-Bo5BgLbC.mjs.map} +1 -1
- package/dist/{seeder.module-CIwQbdN4.mjs → seeder.module-DOoVgTsK.mjs} +5 -5
- package/dist/{seeder.module-CIwQbdN4.mjs.map → seeder.module-DOoVgTsK.mjs.map} +1 -1
- package/dist/signed-url-DIU0sK_6.mjs.map +1 -1
- package/dist/storage/index.d.mts +63 -13
- package/dist/storage/index.d.mts.map +1 -1
- package/dist/storage/index.mjs +2 -2
- package/dist/storage/providers/index.d.mts +18 -16
- package/dist/storage/providers/index.d.mts.map +1 -1
- package/dist/storage/providers/index.mjs +1 -1
- package/dist/{storage-C30X81CS.mjs → storage-DBWVYMnn.mjs} +167 -49
- package/dist/storage-DBWVYMnn.mjs.map +1 -0
- package/dist/storage-provider.interface-CinHpjl1.d.mts +315 -0
- package/dist/storage-provider.interface-CinHpjl1.d.mts.map +1 -0
- package/dist/storage.error-Ao38Qdjx.mjs +7 -0
- package/dist/storage.error-Ao38Qdjx.mjs.map +1 -0
- package/dist/{stratal-D5j_I14G.d.mts → stratal-Bs1_E8GQ.d.mts} +13 -3
- package/dist/stratal-Bs1_E8GQ.d.mts.map +1 -0
- package/dist/{stratal-BL6FKUM_.mjs → stratal-CiwNpWy2.mjs} +56 -23
- package/dist/stratal-CiwNpWy2.mjs.map +1 -0
- package/dist/{tiered-cache.service-Dv3BhxxE.d.mts → tiered-cache.service-Bz8bbvyb.d.mts} +16 -3
- package/dist/tiered-cache.service-Bz8bbvyb.d.mts.map +1 -0
- package/dist/trailing-slash-2SctvePW.mjs.map +1 -1
- package/dist/types-CmV_9xBD.d.mts.map +1 -1
- package/dist/{uri-iwofWJ_T.mjs → uri-BrOq148R.mjs} +13 -9
- package/dist/{uri-iwofWJ_T.mjs.map → uri-BrOq148R.mjs.map} +1 -1
- package/dist/{usage-generator-DAWYasuP.mjs → usage-generator-BW7EcO-C.mjs} +3 -3
- package/dist/{usage-generator-DAWYasuP.mjs.map → usage-generator-BW7EcO-C.mjs.map} +1 -1
- package/dist/{zod-eKqqhZ5_.mjs → validation-CZ_B0aXY.mjs} +38 -17
- package/dist/validation-CZ_B0aXY.mjs.map +1 -0
- package/dist/{validation.context-CRvmrhq7.mjs → validation.context-CdbwQWIr.mjs} +2 -2
- package/dist/{validation.context-CRvmrhq7.mjs.map → validation.context-CdbwQWIr.mjs.map} +1 -1
- package/dist/{versioning.service-CCa2oYMJ.mjs → versioning.service-DnF_4Lnd.mjs} +5 -5
- package/dist/{versioning.service-CCa2oYMJ.mjs.map → versioning.service-DnF_4Lnd.mjs.map} +1 -1
- package/dist/websocket/index.d.mts +12 -13
- package/dist/websocket/index.d.mts.map +1 -1
- package/dist/websocket/index.mjs +1 -1
- package/dist/workers/index.d.mts +70 -7
- package/dist/workers/index.d.mts.map +1 -1
- package/dist/workers/index.mjs +72 -3
- package/dist/workers/index.mjs.map +1 -1
- package/dist/{zod-wecrEVAs.d.mts → zod-BGisqLs3.d.mts} +9 -16
- package/dist/zod-BGisqLs3.d.mts.map +1 -0
- package/package.json +33 -25
- package/dist/cache.service-uElmBtdS.d.mts.map +0 -1
- package/dist/chunk-BBjsoOtd.mjs +0 -27
- package/dist/command-BvmUAPPQ.mjs.map +0 -1
- package/dist/command-DoBD2Cwl.d.mts.map +0 -1
- package/dist/consumer-registry-D3iMTSdy.d.mts.map +0 -1
- package/dist/container-storage-BmOJ4_Na.mjs.map +0 -1
- package/dist/controller.decorator-YSTPQntu.mjs.map +0 -1
- package/dist/cron-job-NesZRk8F.d.mts.map +0 -1
- package/dist/di-D7qmrAir.mjs.map +0 -1
- package/dist/errors-C01O2T-n.mjs.map +0 -1
- package/dist/events-BhEQuT1X.mjs.map +0 -1
- package/dist/exception-context-D-kvney-.mjs.map +0 -1
- package/dist/guards-DALPXy3_.mjs.map +0 -1
- package/dist/hono-app-COAgmutc.mjs +0 -168
- package/dist/hono-app-COAgmutc.mjs.map +0 -1
- package/dist/http-method.decorator-BljM8BDj.mjs.map +0 -1
- package/dist/i18n.module-B2DvWUPa.mjs.map +0 -1
- package/dist/index-CNuFQSNj.d.mts.map +0 -1
- package/dist/index-DtBNIFuP.d.mts +0 -42
- package/dist/index-DtBNIFuP.d.mts.map +0 -1
- package/dist/index-HgOLNruQ.d.mts +0 -203
- package/dist/index-HgOLNruQ.d.mts.map +0 -1
- package/dist/index-uybm0bhQ.d.mts.map +0 -1
- package/dist/is-seeder-Gvh_AM71.mjs.map +0 -1
- package/dist/lazy-module-loader-M6YKudNL.d.mts.map +0 -1
- package/dist/locale-path.service-CH0CaxwH.mjs +0 -165
- package/dist/locale-path.service-CH0CaxwH.mjs.map +0 -1
- package/dist/metadata-DzzprcID.mjs +0 -39
- package/dist/metadata-DzzprcID.mjs.map +0 -1
- package/dist/module-registry-NxX5O0Qk.mjs.map +0 -1
- package/dist/openapi-CMwuCp31.mjs.map +0 -1
- package/dist/openapi-tools.service-BC5EC3R3.mjs.map +0 -1
- package/dist/openapi.service-2rvJBCEg.d.mts +0 -50
- package/dist/openapi.service-2rvJBCEg.d.mts.map +0 -1
- package/dist/quarry-registry-DRnV-DDa.d.mts.map +0 -1
- package/dist/quarry.module-CcGxU2dJ.mjs.map +0 -1
- package/dist/queue.module-CEs4_kEM.mjs.map +0 -1
- package/dist/r2-storage.provider-BoZmR6Ut.mjs.map +0 -1
- package/dist/route-name-DGoBOfPg.mjs.map +0 -1
- package/dist/route-registration.service-CDPQKpm4.mjs +0 -918
- package/dist/route-registration.service-CDPQKpm4.mjs.map +0 -1
- package/dist/router-resolver-sUV_jTrU.mjs.map +0 -1
- package/dist/storage-C30X81CS.mjs.map +0 -1
- package/dist/storage-provider.interface-ClUwxz4S.d.mts +0 -201
- package/dist/storage-provider.interface-ClUwxz4S.d.mts.map +0 -1
- package/dist/storage.error-BStXPmO4.mjs +0 -8
- package/dist/storage.error-BStXPmO4.mjs.map +0 -1
- package/dist/stratal-BL6FKUM_.mjs.map +0 -1
- package/dist/stratal-D5j_I14G.d.mts.map +0 -1
- package/dist/tiered-cache.service-Dv3BhxxE.d.mts.map +0 -1
- package/dist/validation-CpOjviyT.mjs +0 -49
- package/dist/validation-CpOjviyT.mjs.map +0 -1
- package/dist/zod-eKqqhZ5_.mjs.map +0 -1
- package/dist/zod-wecrEVAs.d.mts.map +0 -1
package/dist/config/index.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Qn as FactoryProvider, Xn as DynamicModule, er as ModuleContext, li as ApplicationError, lr as InjectionToken, rr as OnInitialize } from "../index-B2WtEagR.mjs";
|
|
2
2
|
import { t as Macroable } from "../index-0ItCjaqw.mjs";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { s as ZodType } from "../zod-BGisqLs3.mjs";
|
|
4
|
+
import { $ZodError } from "zod/v4/core";
|
|
5
5
|
//#region src/config/config.error.d.ts
|
|
6
|
-
declare class ConfigError extends ApplicationError {}
|
|
6
|
+
export declare class ConfigError extends ApplicationError {}
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/config/config.tokens.d.ts
|
|
9
|
-
declare const CONFIG_TOKENS: {
|
|
9
|
+
export declare const CONFIG_TOKENS: {
|
|
10
10
|
readonly ConfigService: symbol;
|
|
11
11
|
readonly ConfigStore: symbol;
|
|
12
12
|
};
|
|
@@ -59,7 +59,7 @@ interface ConfigNamespace<TKey extends string, TEnv, TConfig extends object> {
|
|
|
59
59
|
* // Returns: { provide: databaseConfig.KEY, useFactory: ..., inject: [DI_TOKENS.CloudflareEnv] }
|
|
60
60
|
* ```
|
|
61
61
|
*/
|
|
62
|
-
declare function registerAs<TKey extends string, TEnv, TConfig extends object>(namespace: TKey, factory: (env: TEnv) => TConfig): ConfigNamespace<TKey, TEnv, TConfig>;
|
|
62
|
+
export declare function registerAs<TKey extends string, TEnv, TConfig extends object>(namespace: TKey, factory: (env: TEnv) => TConfig): ConfigNamespace<TKey, TEnv, TConfig>;
|
|
63
63
|
/**
|
|
64
64
|
* Helper to derive config type from registerAs result
|
|
65
65
|
*
|
|
@@ -89,7 +89,7 @@ interface ConfigModuleOptions {
|
|
|
89
89
|
* Optional Zod schema for validating the merged config
|
|
90
90
|
* Validates the entire config object after all namespaces are merged
|
|
91
91
|
*/
|
|
92
|
-
validateSchema?:
|
|
92
|
+
validateSchema?: ZodType;
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
95
95
|
* ConfigModule
|
|
@@ -134,7 +134,7 @@ interface ConfigModuleOptions {
|
|
|
134
134
|
* }
|
|
135
135
|
* ```
|
|
136
136
|
*/
|
|
137
|
-
declare class ConfigModule implements OnInitialize {
|
|
137
|
+
export declare class ConfigModule implements OnInitialize {
|
|
138
138
|
/**
|
|
139
139
|
* Configure ConfigModule with namespace loaders
|
|
140
140
|
*
|
|
@@ -153,9 +153,9 @@ declare class ConfigModule implements OnInitialize {
|
|
|
153
153
|
}
|
|
154
154
|
//#endregion
|
|
155
155
|
//#region src/config/config.types.d.ts
|
|
156
|
-
declare class ConfigValidationError extends Error {
|
|
157
|
-
readonly errors:
|
|
158
|
-
constructor(message: string, errors:
|
|
156
|
+
export declare class ConfigValidationError extends Error {
|
|
157
|
+
readonly errors: $ZodError;
|
|
158
|
+
constructor(message: string, errors: $ZodError);
|
|
159
159
|
}
|
|
160
160
|
/**
|
|
161
161
|
* Configuration that can be augmented by applications
|
|
@@ -177,7 +177,7 @@ interface ModuleConfig {}
|
|
|
177
177
|
* Generate all valid dot-notation paths from a config object type
|
|
178
178
|
* @example ConfigPath<{ database: { url: string } }> = 'database' | 'database.url'
|
|
179
179
|
*/
|
|
180
|
-
type ConfigPath<T> = { [K in keyof T & string]: T[K] extends Record<string, unknown> ? K | `${K}.${ConfigPath<T[K]>}` : K }[keyof T & string];
|
|
180
|
+
type ConfigPath<T> = { [K in keyof T & string]: T[K] extends Record<string, unknown> ? K | `${K}.${ConfigPath<T[K]>}` : K; }[keyof T & string];
|
|
181
181
|
/**
|
|
182
182
|
* Get the value type at a dot-notation path
|
|
183
183
|
* @example ConfigPathValue<{ database: { url: string } }, 'database.url'> = string
|
|
@@ -235,7 +235,7 @@ interface IConfigService<T extends object = ModuleConfig> {
|
|
|
235
235
|
* the same error you'd get for a missing key on an initialized store.
|
|
236
236
|
* Resolving the store via DI never throws on its own.
|
|
237
237
|
*/
|
|
238
|
-
declare class ConfigStore<T extends object = ModuleConfig> {
|
|
238
|
+
export declare class ConfigStore<T extends object = ModuleConfig> {
|
|
239
239
|
private data;
|
|
240
240
|
/**
|
|
241
241
|
* Initialize the store with validated configuration.
|
|
@@ -292,7 +292,7 @@ declare class ConfigStore<T extends object = ModuleConfig> {
|
|
|
292
292
|
* config.reset('environment.appUrl')
|
|
293
293
|
* ```
|
|
294
294
|
*/
|
|
295
|
-
declare class ConfigService<T extends object = ModuleConfig> extends Macroable implements IConfigService<T> {
|
|
295
|
+
export declare class ConfigService<T extends object = ModuleConfig> extends Macroable implements IConfigService<T> {
|
|
296
296
|
private readonly store;
|
|
297
297
|
private overrides;
|
|
298
298
|
constructor(store: ConfigStore<T>);
|
|
@@ -326,5 +326,5 @@ declare class ConfigService<T extends object = ModuleConfig> extends Macroable i
|
|
|
326
326
|
private deepClone;
|
|
327
327
|
}
|
|
328
328
|
//#endregion
|
|
329
|
-
export {
|
|
329
|
+
export type { ConfigModuleOptions, ConfigNamespace, ConfigPath, ConfigPathValue, IConfigService, InferConfigType, ModuleConfig };
|
|
330
330
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/config/config.error.ts","../../src/config/config.tokens.ts","../../src/config/register-as.ts","../../src/config/config.module.ts","../../src/config/config.types.ts","../../src/config/services/config.store.ts","../../src/config/services/config.service.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/config/config.error.ts","../../src/config/config.tokens.ts","../../src/config/register-as.ts","../../src/config/config.module.ts","../../src/config/config.types.ts","../../src/config/services/config.store.ts","../../src/config/services/config.service.ts"],"mappings":";;;;;qBAEa,oBAAoB;;;qBCFpB;WACZ;WACA;;;;;;;UCKgB,gBAAgB,qBAAqB,MAAM;;WAEjD,KAAK,eAAe;;WAEpB,WAAW;;WAEX,UAAU,KAAK,SAAS;;;;;EAKjC,cAAc,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAkChB,WAAW,qBAAqB,MAAM,wBACpD,WAAW,MACX,UAAU,KAAK,SAAS,UACvB,gBAAgB,MAAM,MAAM;;;;;;;;;;;KA2BnB,gBAAgB,KAAK,UAAU,uCAAuC,KAAK;;;;;;KCpE3E,qBAAqB;;;;UAKhB;;;;EAIf,MAAM;;;;;EAMN,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAgEN,wBAAwB;;;;;;;SAO5B,QAAQ,SAAS,sBAAsB;;;;;;;;EAuB9C,aAAa,SAAS;;;;qBCzHX,8BAA8B;WAGvB,QAAQ;EAF1B,YACE,iBACgB,QAAQ;;;;;;;;;;;;;;;;;UAsBX;;;;;KAML,WAAW,QACpB,WAAW,aAAa,EAAE,WAAW,0BACpC,OAAO,KAAK,WAAW,EAAE,QACzB,WACI;;;;;KAMI,gBAAgB,GAAG,oBAAoB,mBAAmB,WAAW,SAC7E,gBAAgB,IAChB,EAAE,WAAW,0BACb,gBAAgB,EAAE,IAAI,wBAGtB,gBAAgB,IAChB,EAAE;;;;;;;;UAUW,eAAe,mBAAmB;;;;;EAKjD,IAAI,UAAU,WAAW,IAAI,MAAM,IAAI,gBAAgB,GAAG;;;;;EAM1D,IAAI,UAAU,WAAW,IAAI,MAAM,GAAG,OAAO,gBAAgB,GAAG;;;;;EAMhE,MAAM,OAAO,WAAW;;;;EAKxB,OAAO,SAAS;;;;EAKhB,IAAI,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;qBC/DV,YAAY,mBAAmB;UAClC;;;;;EAMR,WAAW,QAAQ;;;;;EAQnB,IAAI,UAAU,WAAW,IAAI,MAAM,IAAI,gBAAgB,GAAG;;;;;EAY1D,IAAI,MAAM,WAAW;;;;;EAQrB,OAAO,SAAS;;;;EAOhB;UAIQ;UAWA;UAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCpDG,cAAc,mBAAmB,sBAAsB,qBAAqB,eAAe;mBAIhD;UAH9C;EAER,YACsD,OAAO,YAAY;;;;;EASzE,IAAI,UAAU,WAAW,IAAI,MAAM,IAAI,gBAAgB,GAAG;;;;;EAY1D,IAAI,UAAU,WAAW,IAAI,MAAM,GAAG,OAAO,gBAAgB,GAAG;;;;EAQhE,MAAM,OAAO,WAAW;;;;EAWxB,OAAO,SAAS;;;;EAehB,IAAI,MAAM,WAAW;UAKb;UAiBA;UASA;UAwBA;UAIA;UAIA"}
|
package/dist/config/index.mjs
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { c as Request, l as Singleton, p as inject, r as DI_TOKENS } from "../di-
|
|
2
|
-
import { a as ApplicationError } from "../container-storage-
|
|
3
|
-
import { n as __decorateParam, t as __decorate } from "../decorate-
|
|
4
|
-
import "../errors-C01O2T-n.mjs";
|
|
1
|
+
import { c as Request, l as Singleton, p as inject, r as DI_TOKENS } from "../di-DQ3xbjgf.mjs";
|
|
2
|
+
import { a as ApplicationError } from "../container-storage-DfF7SXdV.mjs";
|
|
3
|
+
import { n as __decorateParam, t as __decorate } from "../decorate-C79yt3Wt.mjs";
|
|
5
4
|
import { t as Macroable } from "../macroable-cvDTFZ_A.mjs";
|
|
6
|
-
import { n as Module } from "../module.decorator-
|
|
7
|
-
import "../module/index.mjs";
|
|
5
|
+
import { n as Module } from "../module.decorator-CYbrOlX9.mjs";
|
|
8
6
|
//#region src/config/config.error.ts
|
|
9
7
|
var ConfigError = class extends ApplicationError {};
|
|
10
8
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/config/config.error.ts","../../src/config/config.tokens.ts","../../src/config/config.types.ts","../../src/config/services/config.service.ts","../../src/config/services/config.store.ts","../../src/config/config.module.ts","../../src/config/register-as.ts"],"sourcesContent":["import { ApplicationError } from '../errors'\n\nexport class ConfigError extends ApplicationError {}\n","export const CONFIG_TOKENS = {\n\tConfigService: Symbol.for('stratal:config:service'),\n\tConfigStore: Symbol.for('stratal:config:store'),\n} as const\n","import type { z } from '../i18n/validation/zod'\n\nexport class ConfigValidationError extends Error {\n constructor(\n message: string,\n public readonly errors: z.ZodError\n ) {\n super(message)\n this.name = 'ConfigValidationError'\n }\n}\n\n/**\n * Configuration that can be augmented by applications\n * Apps should augment this interface with their AppConfig type using module augmentation\n *\n * @example\n * ```typescript\n * // In your app (e.g., apps/backend/src/config/types.ts)\n * declare module 'stratal' {\n * interface ModuleConfig {\n * database: { url: string; maxConnections: number }\n * email: { provider: string; from: { name: string; email: string } }\n * }\n * }\n * ```\n */\nexport interface ModuleConfig { }\n\n/**\n * Generate all valid dot-notation paths from a config object type\n * @example ConfigPath<{ database: { url: string } }> = 'database' | 'database.url'\n */\nexport type ConfigPath<T> = {\n [K in keyof T & string]: T[K] extends Record<string, unknown>\n ? K | `${K}.${ConfigPath<T[K]>}`\n : K\n}[keyof T & string]\n\n/**\n * Get the value type at a dot-notation path\n * @example ConfigPathValue<{ database: { url: string } }, 'database.url'> = string\n */\nexport type ConfigPathValue<T, P extends string> = P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? T[K] extends Record<string, unknown>\n ? ConfigPathValue<T[K], Rest>\n : never\n : never\n : P extends keyof T\n ? T[P]\n : never\n\n/**\n * ConfigService interface with dot notation support.\n *\n * Values are initialized on the underlying {@link ConfigStore} via\n * {@link ConfigModule}; the service itself exposes request-scoped\n * reads and per-request overrides.\n */\nexport interface IConfigService<T extends object = ModuleConfig> {\n /**\n * Get config value using dot notation\n * @example config.get('database.url')\n */\n get<P extends ConfigPath<T>>(path: P): ConfigPathValue<T, P>\n\n /**\n * Set config value at runtime (for runtime overrides)\n * @example config.set('email.from.name', 'Custom Name')\n */\n set<P extends ConfigPath<T>>(path: P, value: ConfigPathValue<T, P>): void\n\n /**\n * Reset config to original value\n * @param path - Optional path to reset (resets entire config if omitted)\n */\n reset(path?: ConfigPath<T>): void\n\n /**\n * Get entire config object\n */\n all(): Readonly<T>\n\n /**\n * Check if a config path exists\n */\n has(path: ConfigPath<T>): boolean\n}\n","import { inject } from '../../di'\nimport { Request } from '../../di/decorators'\nimport { Macroable } from '../../macroable/macroable'\nimport { CONFIG_TOKENS } from '../config.tokens'\nimport type { ConfigPath, ConfigPathValue, IConfigService, ModuleConfig } from '../config.types'\nimport { type ConfigStore } from './config.store'\n\n/**\n * ConfigService with dot notation support and per-request overrides.\n *\n * ConfigService is **request-scoped**: each request gets its own\n * instance with a private `overrides` map layered over the shared\n * {@link ConfigStore}. Calls to {@link set} mutate only the current\n * request's overrides, which makes it safe to mutate config from\n * middleware (e.g. to pin `environment.appUrl` to the request host).\n *\n * Extends {@link Macroable} so apps can add domain-specific getters\n * and methods via `ConfigService.getter()` / `ConfigService.macro()`.\n *\n * @example\n * ```typescript\n * // Read with dot notation\n * const url = config.get('database.url')\n * const fromName = config.get('email.from.name')\n *\n * // Per-request override (e.g. in middleware)\n * config.set('environment.appUrl', `${proto}://${host}`)\n *\n * // Reset the override for the current request\n * config.reset('environment.appUrl')\n * ```\n */\n@Request(CONFIG_TOKENS.ConfigService)\nexport class ConfigService<T extends object = ModuleConfig> extends Macroable implements IConfigService<T> {\n private overrides = new Map<string, unknown>()\n\n constructor(\n @inject(CONFIG_TOKENS.ConfigStore) private readonly store: ConfigStore<T>,\n ) {\n super()\n }\n\n /**\n * Get config value using dot notation. Request overrides take\n * precedence over the shared store.\n */\n get<P extends ConfigPath<T>>(path: P): ConfigPathValue<T, P> {\n const override = this.readOverride(path)\n if (override !== undefined) {\n return override as ConfigPathValue<T, P>\n }\n return this.store.get(path)\n }\n\n /**\n * Set a config value for the lifetime of the current request.\n * Does not mutate the shared store.\n */\n set<P extends ConfigPath<T>>(path: P, value: ConfigPathValue<T, P>): void {\n if (this.hasDangerousSegment(path)) return\n this.overrides.set(path, value)\n }\n\n /**\n * Clear a single override, or all overrides for this request.\n */\n reset(path?: ConfigPath<T>): void {\n if (path) {\n this.overrides.delete(path)\n return\n }\n this.overrides.clear()\n }\n\n /**\n * Get the full config object, with request overrides merged in.\n */\n all(): Readonly<T> {\n const base = this.store.all() as T\n if (this.overrides.size === 0) {\n return base as Readonly<T>\n }\n const merged = this.deepClone(base)\n for (const [path, value] of this.overrides) {\n this.writeByPath(merged, path, value)\n }\n return merged as Readonly<T>\n }\n\n /**\n * Check if a config path exists (in overrides or the store).\n */\n has(path: ConfigPath<T>): boolean {\n if (this.readOverride(path) !== undefined) return true\n return this.store.has(path)\n }\n\n private readOverride(path: string): unknown {\n if (this.hasDangerousSegment(path)) return undefined\n if (this.overrides.has(path)) {\n return this.overrides.get(path)\n }\n // Support partial-path reads: if an ancestor was overridden, walk into it.\n const segments = path.split('.')\n for (let i = segments.length - 1; i > 0; i--) {\n const parent = segments.slice(0, i).join('.')\n if (this.overrides.has(parent)) {\n const parentValue = this.overrides.get(parent)\n return this.walk(parentValue, segments.slice(i))\n }\n }\n return undefined\n }\n\n private walk(value: unknown, keys: string[]): unknown {\n let current = value\n for (const key of keys) {\n if (current === null || current === undefined) return undefined\n current = (current as Record<string, unknown>)[key]\n }\n return current\n }\n\n private writeByPath(obj: unknown, path: string, value: unknown): void {\n const keys = path.split('.')\n if (keys.some((key) => this.isDangerousKey(key))) return\n let current = obj as Record<string, unknown>\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i]\n if (!Object.hasOwn(current, key) || typeof current[key] !== 'object' || current[key] === null) {\n Object.defineProperty(current, key, {\n value: {},\n writable: true,\n enumerable: true,\n configurable: true,\n })\n }\n current = current[key] as Record<string, unknown>\n }\n Object.defineProperty(current, keys[keys.length - 1], {\n value,\n writable: true,\n enumerable: true,\n configurable: true,\n })\n }\n\n private hasDangerousSegment(path: string): boolean {\n return path.split('.').some((key) => this.isDangerousKey(key))\n }\n\n private isDangerousKey(key: string): boolean {\n return key === '__proto__' || key === 'constructor' || key === 'prototype'\n }\n\n private deepClone<V>(obj: V): V {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n return JSON.parse(JSON.stringify(obj)) as V\n }\n}\n","import { Singleton } from '../../di/decorators'\nimport { CONFIG_TOKENS } from '../config.tokens'\nimport type { ConfigPath, ConfigPathValue, ModuleConfig } from '../config.types'\nimport { ConfigError } from '../config.error'\n\n/**\n * ConfigStore\n *\n * Singleton-scoped holder of validated, merged configuration.\n *\n * ConfigStore is the source of truth for configuration values. It is\n * initialized once during application startup by {@link ConfigModule}\n * and never mutated afterwards.\n *\n * Per-request overrides live on {@link ConfigService}, which reads\n * through to this store for any key not explicitly overridden.\n *\n * If the store is never initialized (no `ConfigModule.forRoot()`), it\n * behaves like an empty config: `has()` returns `false`, `all()` returns\n * `{}`, and `get()` throws {@link ConfigError} for any path —\n * the same error you'd get for a missing key on an initialized store.\n * Resolving the store via DI never throws on its own.\n */\n@Singleton(CONFIG_TOKENS.ConfigStore)\nexport class ConfigStore<T extends object = ModuleConfig> {\n private data: T | undefined\n\n /**\n * Initialize the store with validated configuration.\n * Called by {@link ConfigModule} during initialization.\n */\n initialize(config: T): void {\n this.data = this.deepClone(config)\n }\n\n /**\n * Get config value using dot notation. Throws\n * {@link ConfigError} if the path is absent.\n */\n get<P extends ConfigPath<T>>(path: P): ConfigPathValue<T, P> {\n const value = this.getByPath(this.data ?? {}, path)\n if (value === undefined) {\n throw new ConfigError(`Configuration key \"${path}\" was not found`)\n }\n return value as ConfigPathValue<T, P>\n }\n\n /**\n * Check if a config path exists. Returns `false` when the store has\n * not been initialized.\n */\n has(path: ConfigPath<T>): boolean {\n return this.getByPath(this.data ?? {}, path) !== undefined\n }\n\n /**\n * Get the entire config object (readonly snapshot). Returns an empty\n * object when the store has not been initialized.\n */\n all(): Readonly<T> {\n return (this.data ?? ({} as T)) as Readonly<T>\n }\n\n /**\n * True once {@link initialize} has been called.\n */\n isInitialized(): boolean {\n return this.data !== undefined\n }\n\n private getByPath(obj: unknown, path: string): unknown {\n const keys = path.split('.')\n let current = obj\n for (const key of keys) {\n if (this.isDangerousKey(key)) return undefined\n if (current === null || current === undefined) return undefined\n current = (current as Record<string, unknown>)[key]\n }\n return current\n }\n\n private isDangerousKey(key: string): boolean {\n return key === '__proto__' || key === 'constructor' || key === 'prototype'\n }\n\n private deepClone<V>(obj: V): V {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n return JSON.parse(JSON.stringify(obj)) as V\n }\n}\n","import { DI_TOKENS } from '../di/tokens'\nimport type { z } from '../i18n/validation/zod'\nimport { Module } from '../module'\nimport type { DynamicModule, ModuleContext, OnInitialize, Provider } from '../module/types'\nimport { CONFIG_TOKENS } from './config.tokens'\nimport { ConfigValidationError, type ModuleConfig } from './config.types'\nimport type { ConfigNamespace } from './register-as'\nimport { ConfigService } from './services/config.service'\nimport { ConfigStore } from './services/config.store'\n\n/**\n * Any config namespace - uses structural typing for flexibility\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyConfigNamespace = ConfigNamespace<string, any, object>\n\n/**\n * Options for ConfigModule.forRoot\n */\nexport interface ConfigModuleOptions {\n /**\n * Array of config namespaces created via registerAs()\n */\n load: AnyConfigNamespace[]\n\n /**\n * Optional Zod schema for validating the merged config\n * Validates the entire config object after all namespaces are merged\n */\n validateSchema?: z.ZodType<object>\n}\n\n// Store options for use in onInitialize\nlet moduleOptions: ConfigModuleOptions | null = null\n\n/**\n * ConfigModule\n *\n * Provides configuration management with namespace support.\n * Uses registerAs() to create typed config namespaces that can be injected.\n *\n * @example\n * ```typescript\n * // Define config namespaces\n * const databaseConfig = registerAs('database', (env) => ({\n * url: env.DATABASE_URL,\n * maxConnections: 10\n * }))\n *\n * const emailConfig = registerAs('email', (env) => ({\n * provider: env.EMAIL_PROVIDER,\n * from: { name: 'App', email: 'noreply@example.com' }\n * }))\n *\n * // Register in module\n * @Module({\n * imports: [\n * ConfigModule.forRoot({\n * load: [databaseConfig, emailConfig],\n * validateSchema: AppConfigSchema\n * })\n * ]\n * })\n * export class AppModule {}\n *\n * // Inject config\n * constructor(\n * @inject(CONFIG_TOKENS.ConfigService) private config: IConfigService,\n * @inject(databaseConfig.KEY) private dbConfig: DatabaseConfig\n * ) {\n * // Use dot notation\n * const url = this.config.get('database.url')\n *\n * // Or inject namespace directly\n * const url = this.dbConfig.url\n * }\n * ```\n */\n@Module({\n providers: [\n // ConfigStore is the singleton source of truth for validated config.\n {\n provide: CONFIG_TOKENS.ConfigStore,\n useClass: ConfigStore,\n },\n // ConfigService is request-scoped: each request gets its own\n // overrides map layered over the shared ConfigStore.\n {\n provide: CONFIG_TOKENS.ConfigService,\n useClass: ConfigService,\n },\n ],\n})\nexport class ConfigModule implements OnInitialize {\n /**\n * Configure ConfigModule with namespace loaders\n *\n * @param options - Configuration options\n * @returns Dynamic module with config infrastructure\n */\n static forRoot(options: ConfigModuleOptions): DynamicModule {\n moduleOptions = options\n\n const providers: Provider[] = []\n\n // Register each namespace config using asProvider()\n for (const namespace of options.load) {\n providers.push(namespace.asProvider())\n }\n\n return {\n module: ConfigModule,\n providers,\n }\n }\n\n /**\n * Initialize config service with merged namespaces.\n * Called after all providers are registered. No-op when the module\n * was imported without `forRoot()` — the store stays empty and\n * `ConfigService.get()` will throw `ConfigError` only if\n * someone actually asks for a key.\n */\n onInitialize(context: ModuleContext): void {\n if (!moduleOptions) {\n return\n }\n\n const env = context.container.resolve<unknown>(DI_TOKENS.CloudflareEnv)\n const configStore = context.container.resolve<ConfigStore>(CONFIG_TOKENS.ConfigStore)\n\n // Build merged config from all namespaces\n const mergedConfig: Record<string, unknown> = {}\n\n for (const namespace of moduleOptions.load) {\n mergedConfig[namespace.namespace] = namespace.factory(env)\n }\n\n // Validate if schema provided\n if (moduleOptions.validateSchema) {\n const result = moduleOptions.validateSchema.safeParse(mergedConfig)\n if (!result.success) {\n throw new ConfigValidationError(\n 'Configuration validation failed',\n result.error\n )\n }\n }\n\n // Initialize the shared ConfigStore with merged config.\n configStore.initialize(mergedConfig as ModuleConfig)\n\n context.logger.debug('ConfigModule initialized', {\n namespaces: moduleOptions.load.map((n) => n.namespace),\n })\n }\n}\n","import type { InjectionToken } from '../di/types'\nimport { DI_TOKENS } from '../di/tokens'\nimport type { FactoryProvider } from '../module/types'\n\n/**\n * Configuration namespace registration result\n */\nexport interface ConfigNamespace<TKey extends string, TEnv, TConfig extends object> {\n /** Auto-derived injection token (e.g., 'database' -> Symbol('stratal:config:database')) */\n readonly KEY: InjectionToken<TConfig>\n /** The namespace key */\n readonly namespace: TKey\n /** The factory function that receives env and returns config */\n readonly factory: (env: TEnv) => TConfig\n /**\n * Returns a provider configuration for use in module registration\n * Automatically injects DI_TOKENS.CloudflareEnv\n */\n asProvider(): FactoryProvider<TConfig>\n}\n\n/**\n * Create a namespaced configuration factory\n * Similar to NestJS registerAs\n *\n * @param namespace - Configuration namespace (e.g., 'database', 'email')\n * @param factory - Factory function receiving env and returning config object\n * @returns ConfigNamespace with token, factory, and asProvider() method\n *\n * @example\n * ```typescript\n * // apps/backend/src/config/database.config.ts\n * export const databaseConfig = registerAs('database', (env: Env) => ({\n * url: env.DATABASE_URL,\n * maxConnections: parseInt(env.DATABASE_MAX_CONNECTIONS || '10'),\n * }))\n *\n * // Auto-generates: databaseConfig.KEY = Symbol('stratal:config:database')\n *\n * // Usage in module:\n * // Option 1: Manual provider\n * {\n * provide: databaseConfig.KEY,\n * useFactory: databaseConfig.factory,\n * inject: [DI_TOKENS.CloudflareEnv]\n * }\n *\n * // Option 2: asProvider() helper\n * databaseConfig.asProvider()\n * // Returns: { provide: databaseConfig.KEY, useFactory: ..., inject: [DI_TOKENS.CloudflareEnv] }\n * ```\n */\nexport function registerAs<TKey extends string, TEnv, TConfig extends object>(\n namespace: TKey,\n factory: (env: TEnv) => TConfig\n): ConfigNamespace<TKey, TEnv, TConfig> {\n const KEY = Symbol.for(`stratal:config:${namespace}`) as InjectionToken<TConfig>\n\n return {\n KEY,\n namespace,\n factory,\n asProvider(): FactoryProvider<TConfig> {\n return {\n provide: KEY,\n useFactory: factory,\n inject: [DI_TOKENS.CloudflareEnv],\n }\n },\n }\n}\n\n/**\n * Helper to derive config type from registerAs result\n *\n * @example\n * ```typescript\n * const databaseConfig = registerAs('database', (env) => ({ url: env.DATABASE_URL }))\n * type DatabaseConfig = InferConfigType<typeof databaseConfig>\n * // { url: string }\n * ```\n */\nexport type InferConfigType<T> = T extends ConfigNamespace<string, unknown, infer C> ? C : never\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/config/config.error.ts","../../src/config/config.tokens.ts","../../src/config/config.types.ts","../../src/config/services/config.service.ts","../../src/config/services/config.store.ts","../../src/config/config.module.ts","../../src/config/register-as.ts"],"sourcesContent":["import { ApplicationError } from '../errors'\n\nexport class ConfigError extends ApplicationError {}\n","export const CONFIG_TOKENS = {\n\tConfigService: Symbol.for('stratal:config:service'),\n\tConfigStore: Symbol.for('stratal:config:store'),\n} as const\n","import type { $ZodError } from 'zod/v4/core'\n\nexport class ConfigValidationError extends Error {\n constructor(\n message: string,\n public readonly errors: $ZodError\n ) {\n super(message)\n this.name = 'ConfigValidationError'\n }\n}\n\n/**\n * Configuration that can be augmented by applications\n * Apps should augment this interface with their AppConfig type using module augmentation\n *\n * @example\n * ```typescript\n * // In your app (e.g., apps/backend/src/config/types.ts)\n * declare module 'stratal' {\n * interface ModuleConfig {\n * database: { url: string; maxConnections: number }\n * email: { provider: string; from: { name: string; email: string } }\n * }\n * }\n * ```\n */\nexport interface ModuleConfig { }\n\n/**\n * Generate all valid dot-notation paths from a config object type\n * @example ConfigPath<{ database: { url: string } }> = 'database' | 'database.url'\n */\nexport type ConfigPath<T> = {\n [K in keyof T & string]: T[K] extends Record<string, unknown>\n ? K | `${K}.${ConfigPath<T[K]>}`\n : K\n}[keyof T & string]\n\n/**\n * Get the value type at a dot-notation path\n * @example ConfigPathValue<{ database: { url: string } }, 'database.url'> = string\n */\nexport type ConfigPathValue<T, P extends string> = P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? T[K] extends Record<string, unknown>\n ? ConfigPathValue<T[K], Rest>\n : never\n : never\n : P extends keyof T\n ? T[P]\n : never\n\n/**\n * ConfigService interface with dot notation support.\n *\n * Values are initialized on the underlying {@link ConfigStore} via\n * {@link ConfigModule}; the service itself exposes request-scoped\n * reads and per-request overrides.\n */\nexport interface IConfigService<T extends object = ModuleConfig> {\n /**\n * Get config value using dot notation\n * @example config.get('database.url')\n */\n get<P extends ConfigPath<T>>(path: P): ConfigPathValue<T, P>\n\n /**\n * Set config value at runtime (for runtime overrides)\n * @example config.set('email.from.name', 'Custom Name')\n */\n set<P extends ConfigPath<T>>(path: P, value: ConfigPathValue<T, P>): void\n\n /**\n * Reset config to original value\n * @param path - Optional path to reset (resets entire config if omitted)\n */\n reset(path?: ConfigPath<T>): void\n\n /**\n * Get entire config object\n */\n all(): Readonly<T>\n\n /**\n * Check if a config path exists\n */\n has(path: ConfigPath<T>): boolean\n}\n","import { inject } from '../../di'\nimport { Request } from '../../di/decorators'\nimport { Macroable } from '../../macroable/macroable'\nimport { CONFIG_TOKENS } from '../config.tokens'\nimport type { ConfigPath, ConfigPathValue, IConfigService, ModuleConfig } from '../config.types'\nimport { type ConfigStore } from './config.store'\n\n/**\n * ConfigService with dot notation support and per-request overrides.\n *\n * ConfigService is **request-scoped**: each request gets its own\n * instance with a private `overrides` map layered over the shared\n * {@link ConfigStore}. Calls to {@link set} mutate only the current\n * request's overrides, which makes it safe to mutate config from\n * middleware (e.g. to pin `environment.appUrl` to the request host).\n *\n * Extends {@link Macroable} so apps can add domain-specific getters\n * and methods via `ConfigService.getter()` / `ConfigService.macro()`.\n *\n * @example\n * ```typescript\n * // Read with dot notation\n * const url = config.get('database.url')\n * const fromName = config.get('email.from.name')\n *\n * // Per-request override (e.g. in middleware)\n * config.set('environment.appUrl', `${proto}://${host}`)\n *\n * // Reset the override for the current request\n * config.reset('environment.appUrl')\n * ```\n */\n@Request(CONFIG_TOKENS.ConfigService)\nexport class ConfigService<T extends object = ModuleConfig> extends Macroable implements IConfigService<T> {\n private overrides = new Map<string, unknown>()\n\n constructor(\n @inject(CONFIG_TOKENS.ConfigStore) private readonly store: ConfigStore<T>,\n ) {\n super()\n }\n\n /**\n * Get config value using dot notation. Request overrides take\n * precedence over the shared store.\n */\n get<P extends ConfigPath<T>>(path: P): ConfigPathValue<T, P> {\n const override = this.readOverride(path)\n if (override !== undefined) {\n return override as ConfigPathValue<T, P>\n }\n return this.store.get(path)\n }\n\n /**\n * Set a config value for the lifetime of the current request.\n * Does not mutate the shared store.\n */\n set<P extends ConfigPath<T>>(path: P, value: ConfigPathValue<T, P>): void {\n if (this.hasDangerousSegment(path)) return\n this.overrides.set(path, value)\n }\n\n /**\n * Clear a single override, or all overrides for this request.\n */\n reset(path?: ConfigPath<T>): void {\n if (path) {\n this.overrides.delete(path)\n return\n }\n this.overrides.clear()\n }\n\n /**\n * Get the full config object, with request overrides merged in.\n */\n all(): Readonly<T> {\n const base = this.store.all() as T\n if (this.overrides.size === 0) {\n return base\n }\n const merged = this.deepClone(base)\n for (const [path, value] of this.overrides) {\n this.writeByPath(merged, path, value)\n }\n return merged\n }\n\n /**\n * Check if a config path exists (in overrides or the store).\n */\n has(path: ConfigPath<T>): boolean {\n if (this.readOverride(path) !== undefined) return true\n return this.store.has(path)\n }\n\n private readOverride(path: string): unknown {\n if (this.hasDangerousSegment(path)) return undefined\n if (this.overrides.has(path)) {\n return this.overrides.get(path)\n }\n // Support partial-path reads: if an ancestor was overridden, walk into it.\n const segments = path.split('.')\n for (let i = segments.length - 1; i > 0; i--) {\n const parent = segments.slice(0, i).join('.')\n if (this.overrides.has(parent)) {\n const parentValue = this.overrides.get(parent)\n return this.walk(parentValue, segments.slice(i))\n }\n }\n return undefined\n }\n\n private walk(value: unknown, keys: string[]): unknown {\n let current = value\n for (const key of keys) {\n if (current === null || current === undefined) return undefined\n current = (current as Record<string, unknown>)[key]\n }\n return current\n }\n\n private writeByPath(obj: unknown, path: string, value: unknown): void {\n const keys = path.split('.')\n if (keys.some((key) => this.isDangerousKey(key))) return\n let current = obj as Record<string, unknown>\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i]\n if (!Object.hasOwn(current, key) || typeof current[key] !== 'object' || current[key] === null) {\n Object.defineProperty(current, key, {\n value: {},\n writable: true,\n enumerable: true,\n configurable: true,\n })\n }\n current = current[key] as Record<string, unknown>\n }\n Object.defineProperty(current, keys[keys.length - 1], {\n value,\n writable: true,\n enumerable: true,\n configurable: true,\n })\n }\n\n private hasDangerousSegment(path: string): boolean {\n return path.split('.').some((key) => this.isDangerousKey(key))\n }\n\n private isDangerousKey(key: string): boolean {\n return key === '__proto__' || key === 'constructor' || key === 'prototype'\n }\n\n private deepClone<V>(obj: V): V {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n return JSON.parse(JSON.stringify(obj)) as V\n }\n}\n","import { Singleton } from '../../di/decorators'\nimport { CONFIG_TOKENS } from '../config.tokens'\nimport type { ConfigPath, ConfigPathValue, ModuleConfig } from '../config.types'\nimport { ConfigError } from '../config.error'\n\n/**\n * ConfigStore\n *\n * Singleton-scoped holder of validated, merged configuration.\n *\n * ConfigStore is the source of truth for configuration values. It is\n * initialized once during application startup by {@link ConfigModule}\n * and never mutated afterwards.\n *\n * Per-request overrides live on {@link ConfigService}, which reads\n * through to this store for any key not explicitly overridden.\n *\n * If the store is never initialized (no `ConfigModule.forRoot()`), it\n * behaves like an empty config: `has()` returns `false`, `all()` returns\n * `{}`, and `get()` throws {@link ConfigError} for any path —\n * the same error you'd get for a missing key on an initialized store.\n * Resolving the store via DI never throws on its own.\n */\n@Singleton(CONFIG_TOKENS.ConfigStore)\nexport class ConfigStore<T extends object = ModuleConfig> {\n private data: T | undefined\n\n /**\n * Initialize the store with validated configuration.\n * Called by {@link ConfigModule} during initialization.\n */\n initialize(config: T): void {\n this.data = this.deepClone(config)\n }\n\n /**\n * Get config value using dot notation. Throws\n * {@link ConfigError} if the path is absent.\n */\n get<P extends ConfigPath<T>>(path: P): ConfigPathValue<T, P> {\n const value = this.getByPath(this.data ?? {}, path)\n if (value === undefined) {\n throw new ConfigError(`Configuration key \"${path}\" was not found`)\n }\n return value as ConfigPathValue<T, P>\n }\n\n /**\n * Check if a config path exists. Returns `false` when the store has\n * not been initialized.\n */\n has(path: ConfigPath<T>): boolean {\n return this.getByPath(this.data ?? {}, path) !== undefined\n }\n\n /**\n * Get the entire config object (readonly snapshot). Returns an empty\n * object when the store has not been initialized.\n */\n all(): Readonly<T> {\n return (this.data ?? ({} as T))\n }\n\n /**\n * True once {@link initialize} has been called.\n */\n isInitialized(): boolean {\n return this.data !== undefined\n }\n\n private getByPath(obj: unknown, path: string): unknown {\n const keys = path.split('.')\n let current = obj\n for (const key of keys) {\n if (this.isDangerousKey(key)) return undefined\n if (current === null || current === undefined) return undefined\n current = (current as Record<string, unknown>)[key]\n }\n return current\n }\n\n private isDangerousKey(key: string): boolean {\n return key === '__proto__' || key === 'constructor' || key === 'prototype'\n }\n\n private deepClone<V>(obj: V): V {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n return JSON.parse(JSON.stringify(obj)) as V\n }\n}\n","import { DI_TOKENS } from '../di/tokens';\nimport type { ZodType } from '../i18n/validation/zod';\nimport { Module } from '../module';\nimport type { DynamicModule, ModuleContext, OnInitialize, Provider } from '../module/types';\nimport { CONFIG_TOKENS } from './config.tokens';\nimport { ConfigValidationError } from './config.types';\nimport type { ConfigNamespace } from './register-as';\nimport { ConfigService } from './services/config.service';\nimport { ConfigStore } from './services/config.store';\n\n/**\n * Any config namespace - uses structural typing for flexibility\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyConfigNamespace = ConfigNamespace<string, any, object>\n\n/**\n * Options for ConfigModule.forRoot\n */\nexport interface ConfigModuleOptions {\n /**\n * Array of config namespaces created via registerAs()\n */\n load: AnyConfigNamespace[]\n\n /**\n * Optional Zod schema for validating the merged config\n * Validates the entire config object after all namespaces are merged\n */\n validateSchema?: ZodType\n}\n\n// Store options for use in onInitialize\nlet moduleOptions: ConfigModuleOptions | null = null\n\n/**\n * ConfigModule\n *\n * Provides configuration management with namespace support.\n * Uses registerAs() to create typed config namespaces that can be injected.\n *\n * @example\n * ```typescript\n * // Define config namespaces\n * const databaseConfig = registerAs('database', (env) => ({\n * url: env.DATABASE_URL,\n * maxConnections: 10\n * }))\n *\n * const emailConfig = registerAs('email', (env) => ({\n * provider: env.EMAIL_PROVIDER,\n * from: { name: 'App', email: 'noreply@example.com' }\n * }))\n *\n * // Register in module\n * @Module({\n * imports: [\n * ConfigModule.forRoot({\n * load: [databaseConfig, emailConfig],\n * validateSchema: AppConfigSchema\n * })\n * ]\n * })\n * export class AppModule {}\n *\n * // Inject config\n * constructor(\n * @inject(CONFIG_TOKENS.ConfigService) private config: IConfigService,\n * @inject(databaseConfig.KEY) private dbConfig: DatabaseConfig\n * ) {\n * // Use dot notation\n * const url = this.config.get('database.url')\n *\n * // Or inject namespace directly\n * const url = this.dbConfig.url\n * }\n * ```\n */\n@Module({\n providers: [\n // ConfigStore is the singleton source of truth for validated config.\n {\n provide: CONFIG_TOKENS.ConfigStore,\n useClass: ConfigStore,\n },\n // ConfigService is request-scoped: each request gets its own\n // overrides map layered over the shared ConfigStore.\n {\n provide: CONFIG_TOKENS.ConfigService,\n useClass: ConfigService,\n },\n ],\n})\nexport class ConfigModule implements OnInitialize {\n /**\n * Configure ConfigModule with namespace loaders\n *\n * @param options - Configuration options\n * @returns Dynamic module with config infrastructure\n */\n static forRoot(options: ConfigModuleOptions): DynamicModule {\n moduleOptions = options\n\n const providers: Provider[] = []\n\n // Register each namespace config using asProvider()\n for (const namespace of options.load) {\n providers.push(namespace.asProvider())\n }\n\n return {\n module: ConfigModule,\n providers,\n }\n }\n\n /**\n * Initialize config service with merged namespaces.\n * Called after all providers are registered. No-op when the module\n * was imported without `forRoot()` — the store stays empty and\n * `ConfigService.get()` will throw `ConfigError` only if\n * someone actually asks for a key.\n */\n onInitialize(context: ModuleContext): void {\n if (!moduleOptions) {\n return\n }\n\n const env = context.container.resolve<unknown>(DI_TOKENS.CloudflareEnv)\n const configStore = context.container.resolve<ConfigStore>(CONFIG_TOKENS.ConfigStore)\n\n // Build merged config from all namespaces\n const mergedConfig: Record<string, unknown> = {}\n\n for (const namespace of moduleOptions.load) {\n mergedConfig[namespace.namespace] = namespace.factory(env)\n }\n\n // Validate if schema provided\n if (moduleOptions.validateSchema) {\n const result = moduleOptions.validateSchema.safeParse(mergedConfig)\n if (!result.success) {\n throw new ConfigValidationError(\n 'Configuration validation failed',\n result.error\n )\n }\n }\n\n // Initialize the shared ConfigStore with merged config.\n configStore.initialize(mergedConfig)\n\n context.logger.debug('ConfigModule initialized', {\n namespaces: moduleOptions.load.map((n) => n.namespace),\n })\n }\n}\n","import type { InjectionToken } from '../di/types'\nimport { DI_TOKENS } from '../di/tokens'\nimport type { FactoryProvider } from '../module/types'\n\n/**\n * Configuration namespace registration result\n */\nexport interface ConfigNamespace<TKey extends string, TEnv, TConfig extends object> {\n /** Auto-derived injection token (e.g., 'database' -> Symbol('stratal:config:database')) */\n readonly KEY: InjectionToken<TConfig>\n /** The namespace key */\n readonly namespace: TKey\n /** The factory function that receives env and returns config */\n readonly factory: (env: TEnv) => TConfig\n /**\n * Returns a provider configuration for use in module registration\n * Automatically injects DI_TOKENS.CloudflareEnv\n */\n asProvider(): FactoryProvider<TConfig>\n}\n\n/**\n * Create a namespaced configuration factory\n * Similar to NestJS registerAs\n *\n * @param namespace - Configuration namespace (e.g., 'database', 'email')\n * @param factory - Factory function receiving env and returning config object\n * @returns ConfigNamespace with token, factory, and asProvider() method\n *\n * @example\n * ```typescript\n * // apps/backend/src/config/database.config.ts\n * export const databaseConfig = registerAs('database', (env: Env) => ({\n * url: env.DATABASE_URL,\n * maxConnections: parseInt(env.DATABASE_MAX_CONNECTIONS || '10'),\n * }))\n *\n * // Auto-generates: databaseConfig.KEY = Symbol('stratal:config:database')\n *\n * // Usage in module:\n * // Option 1: Manual provider\n * {\n * provide: databaseConfig.KEY,\n * useFactory: databaseConfig.factory,\n * inject: [DI_TOKENS.CloudflareEnv]\n * }\n *\n * // Option 2: asProvider() helper\n * databaseConfig.asProvider()\n * // Returns: { provide: databaseConfig.KEY, useFactory: ..., inject: [DI_TOKENS.CloudflareEnv] }\n * ```\n */\nexport function registerAs<TKey extends string, TEnv, TConfig extends object>(\n namespace: TKey,\n factory: (env: TEnv) => TConfig\n): ConfigNamespace<TKey, TEnv, TConfig> {\n const KEY = Symbol.for(`stratal:config:${namespace}`) as InjectionToken<TConfig>\n\n return {\n KEY,\n namespace,\n factory,\n asProvider(): FactoryProvider<TConfig> {\n return {\n provide: KEY,\n useFactory: factory,\n inject: [DI_TOKENS.CloudflareEnv],\n }\n },\n }\n}\n\n/**\n * Helper to derive config type from registerAs result\n *\n * @example\n * ```typescript\n * const databaseConfig = registerAs('database', (env) => ({ url: env.DATABASE_URL }))\n * type DatabaseConfig = InferConfigType<typeof databaseConfig>\n * // { url: string }\n * ```\n */\nexport type InferConfigType<T> = T extends ConfigNamespace<string, unknown, infer C> ? C : never\n"],"mappings":"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"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { t as StratalEnv } from "./env-ug22bJj7.mjs";
|
|
2
2
|
import { t as Constructor } from "./types-CmV_9xBD.mjs";
|
|
3
|
-
|
|
4
3
|
//#region src/queue/queue-binding.d.ts
|
|
5
4
|
/**
|
|
6
5
|
* String keys of `StratalEnv` whose value type is `Queue`.
|
|
7
6
|
*/
|
|
8
|
-
type QueueBindingFromEnv = Extract<{ [K in keyof StratalEnv]: StratalEnv[K] extends Queue ? K : never }[keyof StratalEnv], string>;
|
|
7
|
+
type QueueBindingFromEnv = Extract<{ [K in keyof StratalEnv]: StratalEnv[K] extends Queue ? K : never; }[keyof StratalEnv], string>;
|
|
9
8
|
/**
|
|
10
9
|
* Type-safe queue binding identifier.
|
|
11
10
|
*
|
|
@@ -171,4 +170,4 @@ declare class ConsumerRegistry {
|
|
|
171
170
|
}
|
|
172
171
|
//#endregion
|
|
173
172
|
export { QueueBinding as a, QueueMessage as i, ConsumerRegistry as n, IQueueConsumer as r, ConsumerRegistration as t };
|
|
174
|
-
//# sourceMappingURL=consumer-registry-
|
|
173
|
+
//# sourceMappingURL=consumer-registry-i9oCdarv.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consumer-registry-i9oCdarv.d.mts","names":[],"sources":["../src/queue/queue-binding.ts","../src/queue/queue-consumer.ts","../src/queue/consumer-registry.ts"],"mappings":";;;;;;KAwBK,sBAAsB,WACtB,WAAW,aAAa,WAAW,WAAW,QAAQ,mBAAkB;;;;;;;;KAWjE,gBAAgB,gDAExB;;;;;;;;;UC9Ba,aAAa;;EAE5B;;EAEA;;EAEA,SAAS;;EAET;IACE;IACA;;;;;;;IAOA,UAAU;KACT;;;;;;;;;;;;;;;;;;;;;UAsBY,eAAe;;;;;;;WAOrB;;;;;;EAOT,OAAO,SAAS,aAAa,KAAK;;;;;;;EAQlC,SAAS,OAAO,OAAO,SAAS,aAAa,KAAK;;;;;UChEnC;EACf,eAAe,YAAY;EAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmCW;;UAEH;;UAGA;;UAGA;;;;;;;;;;;;EAaR,SAAS,eAAe,YAAY,iBAAiB;;;;;;;;;;;EAyBrD,mBAAmB,sBAAsB,YAAY;;;;;;;EAcrD,aAAa;;;;;;EASb;;;;EAOA,6BAA6B"}
|
|
@@ -9,6 +9,16 @@ var ApplicationError = class extends Error {
|
|
|
9
9
|
this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
10
10
|
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Extra structured fields this error contributes to its log entry.
|
|
14
|
+
*
|
|
15
|
+
* Override in a subclass to surface error-specific detail (codes, identifiers,
|
|
16
|
+
* validation issues) to observability. Returns `undefined` by default. Reserved
|
|
17
|
+
* log keys (`message`, `name`, `stack`, `timestamp`, `cause`) cannot be
|
|
18
|
+
* overridden — `cause` is populated from the error's cause chain — and
|
|
19
|
+
* globally-registered context still takes precedence over these fields.
|
|
20
|
+
*/
|
|
21
|
+
reportContext() {}
|
|
12
22
|
};
|
|
13
23
|
//#endregion
|
|
14
24
|
//#region src/errors/container-not-initialized.error.ts
|
|
@@ -49,4 +59,4 @@ function runWithContainer(container, fn) {
|
|
|
49
59
|
//#endregion
|
|
50
60
|
export { ApplicationError as a, ContainerNotInitializedError as i, getContainer as n, runWithContainer as r, containerStorage as t };
|
|
51
61
|
|
|
52
|
-
//# sourceMappingURL=container-storage-
|
|
62
|
+
//# sourceMappingURL=container-storage-DfF7SXdV.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container-storage-DfF7SXdV.mjs","names":[],"sources":["../src/errors/application-error.ts","../src/errors/container-not-initialized.error.ts","../src/di/container-storage.ts"],"sourcesContent":["export class ApplicationError extends Error {\n public readonly timestamp: string\n\n constructor(message?: string, cause?: unknown) {\n super(message ?? 'Internal Server Error', cause !== undefined ? { cause } : undefined)\n\n Object.setPrototypeOf(this, new.target.prototype)\n\n this.name = this.constructor.name\n this.timestamp = new Date().toISOString()\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- captureStackTrace is V8-specific, not always present\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor)\n }\n }\n\n /**\n * Extra structured fields this error contributes to its log entry.\n *\n * Override in a subclass to surface error-specific detail (codes, identifiers,\n * validation issues) to observability. Returns `undefined` by default. Reserved\n * log keys (`message`, `name`, `stack`, `timestamp`, `cause`) cannot be\n * overridden — `cause` is populated from the error's cause chain — and\n * globally-registered context still takes precedence over these fields.\n */\n public reportContext(): Record<string, unknown> | undefined {\n return undefined\n }\n}\n","import { ApplicationError } from './application-error'\n\nexport class ContainerNotInitializedError extends ApplicationError {\n constructor() {\n super('Application container has not been initialized')\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport { ContainerNotInitializedError } from '../errors/container-not-initialized.error'\nimport type { Container } from './container'\n\n/**\n * AsyncLocalStorage for the application container.\n *\n * Set by `Application.initialize()` — all code from that point onward\n * (Stratal handlers, TestingModuleBuilder, standalone functions like `route()`)\n * can access the container without DI or static singletons.\n */\nexport const containerStorage = new AsyncLocalStorage<Container>()\n\n/**\n * Get the application container from AsyncLocalStorage.\n *\n * @throws ContainerNotInitializedError if called outside `Application.initialize()` scope\n */\nexport function getContainer(): Container {\n const container = containerStorage.getStore()\n if (!container) {\n throw new ContainerNotInitializedError()\n }\n return container\n}\n\n/**\n * Run a function within a container context.\n *\n * @param container - The application container to store\n * @param fn - The function to execute with container access\n */\nexport function runWithContainer<T>(container: Container, fn: () => T): T {\n return containerStorage.run(container, fn)\n}\n"],"mappings":";;AAAA,IAAa,mBAAb,cAAsC,MAAM;CAC1C;CAEA,YAAY,SAAkB,OAAiB;EAC7C,MAAM,WAAW,yBAAyB,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,KAAA,CAAS;EAErF,OAAO,eAAe,MAAM,WAAW,SAAS;EAEhD,KAAK,OAAO,KAAK,YAAY;EAC7B,KAAK,6BAAY,IAAI,KAAK,EAAA,CAAE,YAAY;EAGxC,IAAI,MAAM,mBACR,MAAM,kBAAkB,MAAM,KAAK,WAAW;CAElD;;;;;;;;;;CAWA,gBAA4D,CAE5D;AACF;;;AC3BA,IAAa,+BAAb,cAAkD,iBAAiB;CACjE,cAAc;EACZ,MAAM,gDAAgD;CACxD;AACF;;;;;;;;;;ACKA,MAAa,mBAAmB,IAAI,kBAA6B;;;;;;AAOjE,SAAgB,eAA0B;CACxC,MAAM,YAAY,iBAAiB,SAAS;CAC5C,IAAI,CAAC,WACH,MAAM,IAAI,6BAA6B;CAEzC,OAAO;AACT;;;;;;;AAQA,SAAgB,iBAAoB,WAAsB,IAAgB;CACxE,OAAO,iBAAiB,IAAI,WAAW,EAAE;AAC3C"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { u as Transient } from "./di-
|
|
2
|
-
import {
|
|
3
|
-
import { u as ROUTE_METADATA_KEYS } from "./exception-context-D-kvney-.mjs";
|
|
1
|
+
import { _ as defineMetadata, u as Transient, v as getMetadata } from "./di-DQ3xbjgf.mjs";
|
|
2
|
+
import { u as ROUTE_METADATA_KEYS } from "./exception-context-CdnGTQNF.mjs";
|
|
4
3
|
//#region src/router/decorators/controller.decorator.ts
|
|
5
4
|
const CONTROLLER_ROUTE_KEY = ROUTE_METADATA_KEYS.CONTROLLER_ROUTE;
|
|
6
5
|
/**
|
|
@@ -9,16 +8,16 @@ const CONTROLLER_ROUTE_KEY = ROUTE_METADATA_KEYS.CONTROLLER_ROUTE;
|
|
|
9
8
|
* This is the core controller decorator that handles:
|
|
10
9
|
* - Transient scope registration (request-scoped)
|
|
11
10
|
* - Route metadata storage
|
|
12
|
-
* - Controller options (tags, security schemes, hideFromDocs)
|
|
11
|
+
* - Controller options (tags, security schemes, groups, hideFromDocs)
|
|
13
12
|
*
|
|
14
13
|
* @param route - Base route for this controller (e.g., '/api/v1/users')
|
|
15
|
-
* @param options - Optional configuration (tags, security schemes, hideFromDocs)
|
|
14
|
+
* @param options - Optional configuration (tags, security schemes, groups, hideFromDocs)
|
|
16
15
|
*
|
|
17
16
|
* @example
|
|
18
17
|
* ```typescript
|
|
19
18
|
* import { Controller } from 'stratal/router'
|
|
20
19
|
*
|
|
21
|
-
* @Controller('/api/v1/users', { tags: ['Users'] })
|
|
20
|
+
* @Controller('/api/v1/users', { tags: ['Users'], groups: ['admin'] })
|
|
22
21
|
* export class UsersController implements IController {
|
|
23
22
|
* // All routes accessible
|
|
24
23
|
* }
|
|
@@ -39,7 +38,8 @@ function Controller(route, options) {
|
|
|
39
38
|
* @returns Route string or undefined if not set
|
|
40
39
|
*/
|
|
41
40
|
function getControllerRoute(target) {
|
|
42
|
-
|
|
41
|
+
const metadataTarget = typeof target === "function" ? target : target.constructor;
|
|
42
|
+
return getMetadata(CONTROLLER_ROUTE_KEY, metadataTarget);
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* Get the options from controller class metadata
|
|
@@ -60,7 +60,16 @@ function getControllerOptions(target) {
|
|
|
60
60
|
function getControllerVersion(target) {
|
|
61
61
|
return getControllerOptions(target)?.version;
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Get the visibility groups from controller class metadata
|
|
65
|
+
*
|
|
66
|
+
* @param target - Controller class or instance
|
|
67
|
+
* @returns The controller's `groups`, or undefined if none were declared
|
|
68
|
+
*/
|
|
69
|
+
function getControllerGroups(target) {
|
|
70
|
+
return getControllerOptions(target)?.groups;
|
|
71
|
+
}
|
|
63
72
|
//#endregion
|
|
64
|
-
export { getControllerVersion as i,
|
|
73
|
+
export { getControllerVersion as a, getControllerRoute as i, getControllerGroups as n, getControllerOptions as r, Controller as t };
|
|
65
74
|
|
|
66
|
-
//# sourceMappingURL=controller.decorator-
|
|
75
|
+
//# sourceMappingURL=controller.decorator-BB0JcwMg.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.decorator-BB0JcwMg.mjs","names":[],"sources":["../src/router/decorators/controller.decorator.ts"],"sourcesContent":["import { Transient } from '../../di/decorators'\nimport { defineMetadata, getMetadata } from '../../di/metadata'\nimport { type Constructor } from '../../types'\nimport { ROUTE_METADATA_KEYS } from '../constants'\nimport { type ControllerOptions } from '../types'\n\nconst CONTROLLER_ROUTE_KEY = ROUTE_METADATA_KEYS.CONTROLLER_ROUTE\n\n/**\n * Base controller decorator for route registration\n *\n * This is the core controller decorator that handles:\n * - Transient scope registration (request-scoped)\n * - Route metadata storage\n * - Controller options (tags, security schemes, groups, hideFromDocs)\n *\n * @param route - Base route for this controller (e.g., '/api/v1/users')\n * @param options - Optional configuration (tags, security schemes, groups, hideFromDocs)\n *\n * @example\n * ```typescript\n * import { Controller } from 'stratal/router'\n *\n * @Controller('/api/v1/users', { tags: ['Users'], groups: ['admin'] })\n * export class UsersController implements IController {\n * // All routes accessible\n * }\n * ```\n */\nexport function Controller(route: string, options?: ControllerOptions) {\n return function <T extends Constructor>(target: T) {\n // Wrap @Transient (handles @injectable and scope metadata)\n Transient()(target)\n\n // Store route metadata on the class\n defineMetadata(CONTROLLER_ROUTE_KEY, route, target)\n\n // Store options metadata if provided\n if (options) {\n defineMetadata(ROUTE_METADATA_KEYS.CONTROLLER_OPTIONS, options, target)\n }\n\n return target\n }\n}\n\n/**\n * Get the route from controller class metadata\n *\n * @param target - Controller class or instance\n * @returns Route string or undefined if not set\n */\nexport function getControllerRoute(target: object): string | undefined {\n // Check if target is a class constructor (function) or an instance\n // If class, get metadata from it directly; if instance, get from constructor\n const metadataTarget = typeof target === 'function' ? target : (target as { constructor: object }).constructor\n return getMetadata<string>(CONTROLLER_ROUTE_KEY, metadataTarget)\n}\n\n/**\n * Get the options from controller class metadata\n *\n * @param target - Controller class or instance\n * @returns Controller options or undefined if not set\n */\nexport function getControllerOptions(target: object): ControllerOptions | undefined {\n const metadataTarget = typeof target === 'function' ? target : (target as { constructor: object }).constructor\n return getMetadata<ControllerOptions>(ROUTE_METADATA_KEYS.CONTROLLER_OPTIONS, metadataTarget)\n}\n\n/**\n * Get the version from controller class metadata\n *\n * @param target - Controller class or instance\n * @returns Version string, array, VERSION_NEUTRAL symbol, or undefined if not set\n */\nexport function getControllerVersion(target: object): ControllerOptions['version'] {\n const options = getControllerOptions(target)\n return options?.version\n}\n\n/**\n * Get the visibility groups from controller class metadata\n *\n * @param target - Controller class or instance\n * @returns The controller's `groups`, or undefined if none were declared\n */\nexport function getControllerGroups(target: object): ControllerOptions['groups'] {\n const options = getControllerOptions(target)\n return options?.groups\n}\n"],"mappings":";;;AAMA,MAAM,uBAAuB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;AAuBjD,SAAgB,WAAW,OAAe,SAA6B;CACrE,OAAO,SAAiC,QAAW;EAEjD,UAAU,CAAC,CAAC,MAAM;EAGlB,eAAe,sBAAsB,OAAO,MAAM;EAGlD,IAAI,SACF,eAAe,oBAAoB,oBAAoB,SAAS,MAAM;EAGxE,OAAO;CACT;AACF;;;;;;;AAQA,SAAgB,mBAAmB,QAAoC;CAGrE,MAAM,iBAAiB,OAAO,WAAW,aAAa,SAAU,OAAmC;CACnG,OAAO,YAAoB,sBAAsB,cAAc;AACjE;;;;;;;AAQA,SAAgB,qBAAqB,QAA+C;CAClF,MAAM,iBAAiB,OAAO,WAAW,aAAa,SAAU,OAAmC;CACnG,OAAO,YAA+B,oBAAoB,oBAAoB,cAAc;AAC9F;;;;;;;AAQA,SAAgB,qBAAqB,QAA8C;CAEjF,OADgB,qBAAqB,MACxB,CAAC,EAAE;AAClB;;;;;;;AAQA,SAAgB,oBAAoB,QAA6C;CAE/E,OADgB,qBAAqB,MACxB,CAAC,EAAE;AAClB"}
|
package/dist/cron/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { $ as Container,
|
|
2
|
-
import { n as RegisteredJob, t as CronJob } from "../cron-job-
|
|
1
|
+
import { $ as Container, li as ApplicationError } from "../index-B2WtEagR.mjs";
|
|
2
|
+
import { n as RegisteredJob, t as CronJob } from "../cron-job-DAgNw4Bn.mjs";
|
|
3
3
|
import { ScheduledController as ScheduledController$1 } from "@cloudflare/workers-types";
|
|
4
|
-
|
|
5
4
|
//#region src/cron/cron-manager.d.ts
|
|
6
5
|
/**
|
|
7
6
|
* Manages cron job registration and execution
|
|
@@ -14,7 +13,7 @@ import { ScheduledController as ScheduledController$1 } from "@cloudflare/worker
|
|
|
14
13
|
* Jobs are grouped by their cron expression, allowing multiple jobs
|
|
15
14
|
* to run on the same schedule.
|
|
16
15
|
*/
|
|
17
|
-
declare class CronManager {
|
|
16
|
+
export declare class CronManager {
|
|
18
17
|
/**
|
|
19
18
|
* Map of cron expressions to registered job entries
|
|
20
19
|
* Key: Cron expression (e.g., '0 2 * * *')
|
|
@@ -75,7 +74,7 @@ declare class CronManager {
|
|
|
75
74
|
* (first scheduled trigger, or at bootstrap when the app declares jobs) and by
|
|
76
75
|
* the `schedule:list` command. Kept out of cold start for apps without cron.
|
|
77
76
|
*/
|
|
78
|
-
declare class CronModule {}
|
|
77
|
+
export declare class CronModule {}
|
|
79
78
|
//#endregion
|
|
80
79
|
//#region src/cron/errors/cron-execution.error.d.ts
|
|
81
80
|
interface CronJobFailure {
|
|
@@ -100,7 +99,7 @@ interface SerializedJobFailure {
|
|
|
100
99
|
* wrapping all of them (2+ jobs), so `LoggerService.serializeError` can
|
|
101
100
|
* walk the chain and surface every stack/cause.
|
|
102
101
|
*/
|
|
103
|
-
declare class CronExecutionError extends ApplicationError {
|
|
102
|
+
export declare class CronExecutionError extends ApplicationError {
|
|
104
103
|
readonly failures: readonly CronJobFailure[];
|
|
105
104
|
readonly schedule: string;
|
|
106
105
|
readonly failureCount: number;
|
|
@@ -108,5 +107,5 @@ declare class CronExecutionError extends ApplicationError {
|
|
|
108
107
|
constructor(schedule: string, failures: CronJobFailure[]);
|
|
109
108
|
}
|
|
110
109
|
//#endregion
|
|
111
|
-
export {
|
|
110
|
+
export type { CronJob, RegisteredJob, ScheduledController$1 as ScheduledController };
|
|
112
111
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/cron/cron-manager.ts","../../src/cron/cron.module.ts","../../src/cron/errors/cron-execution.error.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/cron/cron-manager.ts","../../src/cron/cron.module.ts","../../src/cron/errors/cron-execution.error.ts"],"mappings":";;;;;;;;;;;;;;;qBAoBa;;;;;;UAMJ;;;;;;;;;;EAWR,YAAY,kBAAkB,UAAU;;;;;;;;;;;;;;;EAoBlC,iBAAiB,YAAY,qBAAqB,WAAW,YAAY;;;;;;;EAqD/E,mBAAmB,mBAAmB;;;;;;EAStC;;;;;;EASA;;;;;;;;;;;qBChHY;;;UCdI;EAChB;EACA,OAAO;;UAGE;EACT;EACA;EACA;EACA;EACA;EACA;;;;;;;;;;;;qBAaY,2BAA2B;WACvB,mBAAmB;WACnB;WACA;WACA,MAAM;EAEtB,YAAY,kBAAkB,UAAU"}
|
package/dist/cron/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as CronExecutionError, r as CronManager, t as CronModule } from "../cron.module-
|
|
1
|
+
import { i as CronExecutionError, r as CronManager, t as CronModule } from "../cron.module-Dnyl9sFk.mjs";
|
|
2
2
|
export { CronExecutionError, CronManager, CronModule };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { t as Constructor } from "./types-CmV_9xBD.mjs";
|
|
2
|
-
|
|
3
2
|
//#region src/cron/cron-job.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Interface for cron jobs that can be registered by modules
|
|
@@ -55,4 +54,4 @@ interface CronJob {
|
|
|
55
54
|
}
|
|
56
55
|
//#endregion
|
|
57
56
|
export { RegisteredJob as n, CronJob as t };
|
|
58
|
-
//# sourceMappingURL=cron-job-
|
|
57
|
+
//# sourceMappingURL=cron-job-DAgNw4Bn.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-job-DAgNw4Bn.d.mts","names":[],"sources":["../src/cron/cron-job.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA8BiB;;EAEhB;;EAEA,UAAU,YAAY;;UAGN;;;;;;;EAOhB,QAAQ,YAAY,sBAAsB;;;;;;;;;EAU1C,SAAS,OAAO,OAAO,YAAY,sBAAsB"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { t as __exportAll } from "./
|
|
2
|
-
import { l as Singleton, r as DI_TOKENS } from "./di-
|
|
3
|
-
import { a as ApplicationError } from "./container-storage-
|
|
4
|
-
import { t as __decorate } from "./decorate-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { l as Singleton, r as DI_TOKENS } from "./di-DQ3xbjgf.mjs";
|
|
3
|
+
import { a as ApplicationError } from "./container-storage-DfF7SXdV.mjs";
|
|
4
|
+
import { t as __decorate } from "./decorate-C79yt3Wt.mjs";
|
|
5
5
|
import { LOGGER_TOKENS } from "./logger/index.mjs";
|
|
6
|
-
import "./
|
|
7
|
-
import { n as Module } from "./module.decorator-CYHY6pG5.mjs";
|
|
6
|
+
import { n as Module } from "./module.decorator-CYbrOlX9.mjs";
|
|
8
7
|
//#region src/cron/errors/cron-execution.error.ts
|
|
9
8
|
/**
|
|
10
9
|
* Error thrown when one or more cron jobs fail execution.
|
|
@@ -150,4 +149,4 @@ CronModule = __decorate([Module({ providers: [{
|
|
|
150
149
|
//#endregion
|
|
151
150
|
export { CronExecutionError as i, cron_module_exports as n, CronManager as r, CronModule as t };
|
|
152
151
|
|
|
153
|
-
//# sourceMappingURL=cron.module-
|
|
152
|
+
//# sourceMappingURL=cron.module-Dnyl9sFk.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cron.module-
|
|
1
|
+
{"version":3,"file":"cron.module-Dnyl9sFk.mjs","names":[],"sources":["../src/cron/errors/cron-execution.error.ts","../src/cron/cron-manager.ts","../src/cron/cron.module.ts"],"sourcesContent":["import { ApplicationError } from '../../errors'\n\nexport interface CronJobFailure {\n\tjob: string\n\terror: Error\n}\n\ninterface SerializedJobFailure {\n\tjob: string\n\tname: string\n\tcode?: number | string\n\tmessage: string\n\tdbErrorCode?: string\n\tsql?: string\n}\n\n/**\n * Error thrown when one or more cron jobs fail execution.\n *\n * Aggregates failures from multiple jobs that share the same schedule while\n * preserving each underlying error:\n * - The originals are kept on `this.failures` for typed access.\n * - `this.cause` is set to the only failure (1 job) or an `AggregateError`\n * wrapping all of them (2+ jobs), so `LoggerService.serializeError` can\n * walk the chain and surface every stack/cause.\n */\nexport class CronExecutionError extends ApplicationError {\n\tpublic readonly failures: readonly CronJobFailure[]\n\tpublic readonly schedule: string\n\tpublic readonly failureCount: number\n\tpublic readonly jobs: SerializedJobFailure[]\n\n\tconstructor(schedule: string, failures: CronJobFailure[]) {\n\t\tconst cause =\n\t\t\tfailures.length === 0\n\t\t\t\t? undefined\n\t\t\t\t: failures.length === 1\n\t\t\t\t\t? failures[0].error\n\t\t\t\t\t: new AggregateError(failures.map((f) => f.error), `${failures.length} cron jobs failed`)\n\n\t\tsuper(\n\t\t\t`${failures.length} cron job(s) failed for schedule \"${schedule}\"`,\n\t\t\tcause,\n\t\t)\n\n\t\tthis.failures = failures\n\t\tthis.schedule = schedule\n\t\tthis.failureCount = failures.length\n\t\tthis.jobs = failures.map((f) => serializeFailure(f))\n\t}\n}\n\nfunction serializeFailure({ job, error }: CronJobFailure): SerializedJobFailure {\n\tconst out: SerializedJobFailure = {\n\t\tjob,\n\t\tname: error.name,\n\t\tmessage: error.message,\n\t}\n\tconst maybeCoded = error as { code?: number | string }\n\tif (maybeCoded.code !== undefined) out.code = maybeCoded.code\n\treturn out\n}\n","import type { Container } from '../di/container'\nimport { Singleton } from '../di/decorators'\nimport { DI_TOKENS } from '../di/tokens'\nimport { LOGGER_TOKENS } from '../logger/logger.tokens'\nimport type { LoggerService } from '../logger/services/logger.service'\nimport type { CronJob, RegisteredJob } from './cron-job'\nimport { CronExecutionError } from './errors/cron-execution.error'\n\n/**\n * Manages cron job registration and execution\n *\n * CronManager is a singleton service that:\n * - Registers cron job class references from modules\n * - Routes scheduled events to matching jobs\n * - Resolves jobs from a request-scoped container at execution time\n *\n * Jobs are grouped by their cron expression, allowing multiple jobs\n * to run on the same schedule.\n */\n@Singleton(DI_TOKENS.Cron)\nexport class CronManager {\n\t/**\n\t * Map of cron expressions to registered job entries\n\t * Key: Cron expression (e.g., '0 2 * * *')\n\t * Value: Array of registered jobs (class ref + schedule)\n\t */\n\tprivate jobs = new Map<string, RegisteredJob[]>()\n\n\t/**\n\t * Register a cron job class\n\t *\n\t * Jobs with the same schedule are grouped together and executed\n\t * sequentially when the trigger fires.\n\t *\n\t * @param schedule - Cron expression (e.g., '0 2 * * *')\n\t * @param jobClass - CronJob class constructor (resolved at execution time)\n\t */\n\tregisterJob(schedule: string, jobClass: RegisteredJob['jobClass']): void {\n\t\tconst existing = this.jobs.get(schedule) ?? []\n\t\texisting.push({ schedule, jobClass })\n\t\tthis.jobs.set(schedule, existing)\n\t}\n\n\t/**\n\t * Execute all jobs matching the triggered cron expression\n\t *\n\t * Jobs are resolved from the provided request-scoped container,\n\t * ensuring dependencies (e.g. database) are properly scoped.\n\t *\n\t * Jobs are executed sequentially. If a job fails:\n\t * - Its onError() hook is called (if defined)\n\t * - Execution continues with the next job\n\t * - Errors are collected and thrown as CronExecutionError\n\t *\n\t * @param controller - Cloudflare ScheduledController\n\t * @param container - Request-scoped container to resolve jobs from\n\t */\n\tasync executeScheduled(controller: ScheduledController, container: Container): Promise<void> {\n\t\tconst { cron } = controller\n\t\tconst matchingJobs = this.jobs.get(cron) ?? []\n\n\t\tif (matchingJobs.length === 0) {\n\t\t\tconst logger = container.resolve<LoggerService>(LOGGER_TOKENS.LoggerService)\n\t\t\tlogger.warn('No cron jobs matched scheduled trigger', {\n\t\t\t\tincomingCron: cron,\n\t\t\t\tregisteredSchedules: Array.from(this.jobs.keys()),\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tconst errors: { job: string; error: Error }[] = []\n\n\t\tfor (const { jobClass } of matchingJobs) {\n\t\t\tconst jobName = jobClass.name\n\n\t\t\ttry {\n\t\t\t\t// Register the job class in the request-scoped container so its\n\t\t\t\t// dependencies are resolved from request scope (not the parent).\n\t\t\t\tcontainer.register(jobClass, jobClass)\n\t\t\t\tconst job = container.resolve<CronJob>(jobClass)\n\t\t\t\tawait job.execute(controller)\n\t\t\t} catch (error) {\n\t\t\t\tconst err = error as Error\n\t\t\t\terrors.push({ job: jobName, error: err })\n\n\t\t\t\t// Try to resolve and call onError if possible\n\t\t\t\ttry {\n\t\t\t\t\tconst job = container.resolve<CronJob>(jobClass)\n\t\t\t\t\tif (job.onError) {\n\t\t\t\t\t\tawait job.onError(err, controller)\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// If resolution or onError fails, continue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If any jobs failed, throw an aggregate error so ExceptionHandler logs\n\t\t// it. The full per-job errors are passed through so cause/stacks survive.\n\t\tif (errors.length > 0) {\n\t\t\tthrow new CronExecutionError(cron, errors)\n\t\t}\n\t}\n\n\t/**\n\t * Get all registered jobs for a specific cron expression\n\t *\n\t * @param schedule - Cron expression\n\t * @returns Array of registered jobs, or empty array if none\n\t */\n\tgetJobsForSchedule(schedule: string): RegisteredJob[] {\n\t\treturn this.jobs.get(schedule) ?? []\n\t}\n\n\t/**\n\t * Get all registered cron expressions\n\t *\n\t * @returns Array of unique cron expressions\n\t */\n\tgetAllSchedules(): string[] {\n\t\treturn Array.from(this.jobs.keys())\n\t}\n\n\t/**\n\t * Get total number of registered jobs across all schedules\n\t *\n\t * @returns Total job count\n\t */\n\tgetTotalJobCount(): number {\n\t\tlet count = 0\n\t\tfor (const jobs of this.jobs.values()) {\n\t\t\tcount += jobs.length\n\t\t}\n\t\treturn count\n\t}\n}\n","import { DI_TOKENS } from '../di/tokens'\nimport { Module } from '../module/module.decorator'\nimport { CronManager } from './cron-manager'\n\n/**\n * Registers the cron manager (`DI_TOKENS.Cron`).\n *\n * Lazy: loaded on demand via `await import()` — by `Application.ensureCron`\n * (first scheduled trigger, or at bootstrap when the app declares jobs) and by\n * the `schedule:list` command. Kept out of cold start for apps without cron.\n */\n@Module({\n providers: [\n { provide: DI_TOKENS.Cron, useClass: CronManager },\n ],\n})\nexport class CronModule { }\n"],"mappings":";;;;;;;;;;;;;;;;;AA0BA,IAAa,qBAAb,cAAwC,iBAAiB;CACxD;CACA;CACA;CACA;CAEA,YAAY,UAAkB,UAA4B;EACzD,MAAM,QACL,SAAS,WAAW,IACjB,KAAA,IACA,SAAS,WAAW,IACnB,SAAS,EAAE,CAAC,QACZ,IAAI,eAAe,SAAS,KAAK,MAAM,EAAE,KAAK,GAAG,GAAG,SAAS,OAAO,kBAAkB;EAE3F,MACC,GAAG,SAAS,OAAO,oCAAoC,SAAS,IAChE,KACD;EAEA,KAAK,WAAW;EAChB,KAAK,WAAW;EAChB,KAAK,eAAe,SAAS;EAC7B,KAAK,OAAO,SAAS,KAAK,MAAM,iBAAiB,CAAC,CAAC;CACpD;AACD;AAEA,SAAS,iBAAiB,EAAE,KAAK,SAA+C;CAC/E,MAAM,MAA4B;EACjC;EACA,MAAM,MAAM;EACZ,SAAS,MAAM;CAChB;CACA,MAAM,aAAa;CACnB,IAAI,WAAW,SAAS,KAAA,GAAW,IAAI,OAAO,WAAW;CACzD,OAAO;AACR;;;ACzCO,IAAM,cAAN,MAAM,YAAY;;;;;;CAMxB,uBAAe,IAAI,IAA6B;;;;;;;;;;CAWhD,YAAY,UAAkB,UAA2C;EACxE,MAAM,WAAW,KAAK,KAAK,IAAI,QAAQ,KAAK,CAAC;EAC7C,SAAS,KAAK;GAAE;GAAU;EAAS,CAAC;EACpC,KAAK,KAAK,IAAI,UAAU,QAAQ;CACjC;;;;;;;;;;;;;;;CAgBA,MAAM,iBAAiB,YAAiC,WAAqC;EAC5F,MAAM,EAAE,SAAS;EACjB,MAAM,eAAe,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC;EAE7C,IAAI,aAAa,WAAW,GAAG;GAE9B,UADyB,QAAuB,cAAc,aACzD,CAAC,CAAC,KAAK,0CAA0C;IACrD,cAAc;IACd,qBAAqB,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC;GACjD,CAAC;GACD;EACD;EAEA,MAAM,SAA0C,CAAC;EAEjD,KAAK,MAAM,EAAE,cAAc,cAAc;GACxC,MAAM,UAAU,SAAS;GAEzB,IAAI;IAGH,UAAU,SAAS,UAAU,QAAQ;IAErC,MADY,UAAU,QAAiB,QAC/B,CAAC,CAAC,QAAQ,UAAU;GAC7B,SAAS,OAAO;IACf,MAAM,MAAM;IACZ,OAAO,KAAK;KAAE,KAAK;KAAS,OAAO;IAAI,CAAC;IAGxC,IAAI;KACH,MAAM,MAAM,UAAU,QAAiB,QAAQ;KAC/C,IAAI,IAAI,SACP,MAAM,IAAI,QAAQ,KAAK,UAAU;IAEnC,QAAQ,CAER;GACD;EACD;EAIA,IAAI,OAAO,SAAS,GACnB,MAAM,IAAI,mBAAmB,MAAM,MAAM;CAE3C;;;;;;;CAQA,mBAAmB,UAAmC;EACrD,OAAO,KAAK,KAAK,IAAI,QAAQ,KAAK,CAAC;CACpC;;;;;;CAOA,kBAA4B;EAC3B,OAAO,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC;CACnC;;;;;;CAOA,mBAA2B;EAC1B,IAAI,QAAQ;EACZ,KAAK,MAAM,QAAQ,KAAK,KAAK,OAAO,GACnC,SAAS,KAAK;EAEf,OAAO;CACR;AACD;AApHC,cAAA,WAAA,CAAA,UAAU,UAAU,IAAI,CAAA,GAAA,WAAA;;;;ACHlB,IAAM,aAAN,MAAM,WAAW,CAAE;AALzB,aAAA,WAAA,CAAA,OAAO,EACN,WAAW,CACT;CAAE,SAAS,UAAU;CAAM,UAAU;AAAY,CACnD,EACF,CAAC,CAAA,GAAA,UAAA"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorateParam.js
|
|
2
2
|
function __decorateParam(paramIndex, decorator) {
|
|
3
3
|
return function(target, key) {
|
|
4
4
|
decorator(target, key, paramIndex);
|
|
5
5
|
};
|
|
6
6
|
}
|
|
7
7
|
//#endregion
|
|
8
|
-
//#region \0@oxc-project+runtime@0.
|
|
8
|
+
//#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorate.js
|
|
9
9
|
function __decorate(decorators, target, key, desc) {
|
|
10
10
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
11
11
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
package/dist/di/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as Container,
|
|
1
|
+
import { $ as Container, B as getMetadata, F as runWithContainer, G as getClassMetadata, H as Request, I as Disposable, J as INJECT_PARAM_METADATA_KEY, K as getInjectionTokens, L as disposeInstance, N as containerStorage, P as getContainer, Q as ContainerError, R as isDisposable, U as Singleton, V as hasMetadata, W as Transient, X as ParamInjection, Y as InjectParam, Z as getMethodInjections, at as PredicateContainer, ci as DI_TOKENS, cr as ExtensionDecorator, dr as WhenOptions, et as ContainerOptions, fr as LazyToken, it as ConditionalBindingUse, lr as InjectionToken, mr as lazy, nt as ConditionalBindingBuilderImpl, oi as CONTAINER_TOKEN, pr as isLazyToken, q as inject, rt as ConditionalBindingGive, si as DIToken, sr as ContainerLike, tt as ConditionalBindingBuilder, ur as Scope, z as defineMetadata } from "../index-B2WtEagR.mjs";
|
|
2
2
|
export { CONTAINER_TOKEN, ConditionalBindingBuilder, ConditionalBindingBuilderImpl, ConditionalBindingGive, ConditionalBindingUse, Container, ContainerError, ContainerLike, ContainerOptions, DIToken, DI_TOKENS, Disposable, ExtensionDecorator, INJECT_PARAM_METADATA_KEY, InjectParam, InjectionToken, LazyToken, type ParamInjection, PredicateContainer, Request, Scope, Singleton, Transient, WhenOptions, containerStorage, defineMetadata, disposeInstance, getClassMetadata, getContainer, getInjectionTokens, getMetadata, getMethodInjections, hasMetadata, inject, isDisposable, isLazyToken, lazy, runWithContainer };
|
package/dist/di/index.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { _ as
|
|
2
|
-
import { n as getContainer, r as runWithContainer, t as containerStorage } from "../container-storage-
|
|
3
|
-
import { n as getMetadata, r as hasMetadata, t as defineMetadata } from "../metadata-DzzprcID.mjs";
|
|
1
|
+
import { S as ContainerError, _ as defineMetadata, a as lazy, b as Scope, c as Request, d as getClassMetadata, f as getInjectionTokens, g as getMethodInjections, h as InjectParam, i as isLazyToken, l as Singleton, m as INJECT_PARAM_METADATA_KEY, n as CONTAINER_TOKEN, o as disposeInstance, p as inject, r as DI_TOKENS, s as isDisposable, t as Container, u as Transient, v as getMetadata, x as ConditionalBindingBuilderImpl, y as hasMetadata } from "../di-DQ3xbjgf.mjs";
|
|
2
|
+
import { n as getContainer, r as runWithContainer, t as containerStorage } from "../container-storage-DfF7SXdV.mjs";
|
|
4
3
|
export { CONTAINER_TOKEN, ConditionalBindingBuilderImpl, Container, ContainerError, DI_TOKENS, INJECT_PARAM_METADATA_KEY, InjectParam, Request, Scope, Singleton, Transient, containerStorage, defineMetadata, disposeInstance, getClassMetadata, getContainer, getInjectionTokens, getMetadata, getMethodInjections, hasMetadata, inject, isDisposable, isLazyToken, lazy, runWithContainer };
|