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.
- 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 +85 -14
- 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
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
import { t as Macroable } from "./index-0ItCjaqw.mjs";
|
|
2
2
|
import { t as StratalEnv } from "./env-ug22bJj7.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { o as ZodObject, s as ZodType } from "./zod-BGisqLs3.mjs";
|
|
4
4
|
import { c as LogLevel, r as LoggerService } from "./index-BUt92sAE.mjs";
|
|
5
5
|
import { t as Constructor } from "./types-CmV_9xBD.mjs";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
import { SSEMessage, SSEStreamingApi, SSEStreamingApi as SSEStreamingApi$1 } from "hono/streaming";
|
|
8
|
+
import { iso } from "zod/mini";
|
|
9
|
+
import { Context, Hono, MiddlewareHandler } from "hono";
|
|
10
|
+
import { DetectorOptions } from "hono/language";
|
|
8
11
|
import { ContentfulStatusCode, RedirectStatusCode } from "hono/utils/http-status";
|
|
9
|
-
import { Context, MiddlewareHandler, Next } from "hono";
|
|
10
12
|
import { CookieOptions } from "hono/utils/cookie";
|
|
11
13
|
import { StreamingApi, StreamingApi as StreamingApi$1 } from "hono/utils/stream";
|
|
12
|
-
|
|
14
|
+
import { $ZodError } from "zod/v4/core";
|
|
13
15
|
//#region src/errors/application-error.d.ts
|
|
14
16
|
declare class ApplicationError extends Error {
|
|
15
17
|
readonly timestamp: string;
|
|
16
18
|
constructor(message?: string, cause?: unknown);
|
|
19
|
+
/**
|
|
20
|
+
* Extra structured fields this error contributes to its log entry.
|
|
21
|
+
*
|
|
22
|
+
* Override in a subclass to surface error-specific detail (codes, identifiers,
|
|
23
|
+
* validation issues) to observability. Returns `undefined` by default. Reserved
|
|
24
|
+
* log keys (`message`, `name`, `stack`, `timestamp`, `cause`) cannot be
|
|
25
|
+
* overridden — `cause` is populated from the error's cause chain — and
|
|
26
|
+
* globally-registered context still takes precedence over these fields.
|
|
27
|
+
*/
|
|
28
|
+
reportContext(): Record<string, unknown> | undefined;
|
|
17
29
|
}
|
|
18
30
|
//#endregion
|
|
19
31
|
//#region src/di/tokens.d.ts
|
|
@@ -114,7 +126,7 @@ type CurrentRoute = { [K in RouteName]: {
|
|
|
114
126
|
name: K;
|
|
115
127
|
params: NonNullable<RouteParams<K>>;
|
|
116
128
|
defaults: Record<string, string>;
|
|
117
|
-
} }[RouteName] | {
|
|
129
|
+
}; }[RouteName] | {
|
|
118
130
|
name: null;
|
|
119
131
|
params: Record<string, string>;
|
|
120
132
|
defaults: Record<string, string>;
|
|
@@ -138,14 +150,322 @@ type RouteMatcher = keyof StratalRouteMap extends never ? string : RouteName | `
|
|
|
138
150
|
*/
|
|
139
151
|
type RoutePrefixes<S extends string> = S extends `${infer Head}.${infer Rest}` ? Head | `${Head}.${RoutePrefixes<Rest>}` : never;
|
|
140
152
|
//#endregion
|
|
153
|
+
//#region src/response-cache/tag-template.d.ts
|
|
154
|
+
/**
|
|
155
|
+
* Values available to `{scope.path}` placeholders when rendering tags.
|
|
156
|
+
*
|
|
157
|
+
* `body` is never populated by the HTTP router — `RouteRegistrationService
|
|
158
|
+
* .buildTagScopes` always sets it `undefined`, and route registration now
|
|
159
|
+
* rejects any `{body.*}` tag at boot (`bindRouteCache`) precisely because
|
|
160
|
+
* nothing can ever fill it in on the request path. It stays part of this
|
|
161
|
+
* type — rather than being dropped — because `renderTags` is a general
|
|
162
|
+
* template compiler exercised directly in its own unit tests with hand-built
|
|
163
|
+
* scopes (including `body`); those tests are about the compiler accepting
|
|
164
|
+
* all four scopes correctly, independent of what any one caller can supply.
|
|
165
|
+
*/
|
|
166
|
+
interface TagScopes {
|
|
167
|
+
param: Record<string, string>;
|
|
168
|
+
query: Record<string, string>;
|
|
169
|
+
body: unknown;
|
|
170
|
+
data: unknown;
|
|
171
|
+
/**
|
|
172
|
+
* The partition values this request resolved, keyed by partition name.
|
|
173
|
+
*
|
|
174
|
+
* The only scope guaranteed present on every variant of a response. `data`
|
|
175
|
+
* is the resolved payload, and an Inertia partial reload carries only the
|
|
176
|
+
* props it asked for — so `{data.auth.user.id}` renders on the document and
|
|
177
|
+
* throws on the partial, which fails that variant closed and leaves exactly
|
|
178
|
+
* the deferred work uncached. A partition is in the cache key by
|
|
179
|
+
* construction, so `{partition.user}` renders identically on both.
|
|
180
|
+
*/
|
|
181
|
+
partition: Record<string, string>;
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/router/middleware.interface.d.ts
|
|
185
|
+
/**
|
|
186
|
+
* The continuation passed to a {@link Middleware}. Calling it runs the rest of
|
|
187
|
+
* the chain (the next middleware, then the route handler).
|
|
188
|
+
*
|
|
189
|
+
* It resolves to a short-circuit `Response` when a downstream middleware
|
|
190
|
+
* returns one, or `void` otherwise — wider than Hono's own `Next` (which is
|
|
191
|
+
* typed `Promise<void>`) so a forwarding middleware can `return next()` to
|
|
192
|
+
* propagate a downstream short-circuit without an unsafe cast.
|
|
193
|
+
*/
|
|
194
|
+
type Next = () => Promise<Response | void>;
|
|
195
|
+
/**
|
|
196
|
+
* Middleware interface for request processing
|
|
197
|
+
*
|
|
198
|
+
* Middlewares use the `@Transient()` decorator and are registered via
|
|
199
|
+
* `configureRoutes(router)` in modules implementing `RouteConfigurable`.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* @Transient()
|
|
204
|
+
* export class LoggingMiddleware implements Middleware {
|
|
205
|
+
* async handle(ctx: RouterContext, next: Next): Promise<void> {
|
|
206
|
+
* const start = Date.now()
|
|
207
|
+
* await next()
|
|
208
|
+
* console.log(`Request took ${Date.now() - start}ms`)
|
|
209
|
+
* }
|
|
210
|
+
* }
|
|
211
|
+
*
|
|
212
|
+
* // Register in module:
|
|
213
|
+
* @Module({ providers: [LoggingMiddleware] })
|
|
214
|
+
* export class AppModule implements RouteConfigurable {
|
|
215
|
+
* configureRoutes(router: Router): void {
|
|
216
|
+
* router.middleware(LoggingMiddleware)
|
|
217
|
+
* }
|
|
218
|
+
* }
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
221
|
+
interface Middleware {
|
|
222
|
+
/**
|
|
223
|
+
* Handle middleware logic
|
|
224
|
+
* Call next() to continue the middleware chain
|
|
225
|
+
*
|
|
226
|
+
* @param ctx - Router context with request/response helpers
|
|
227
|
+
* @param next - Function to call the next middleware or route handler
|
|
228
|
+
*/
|
|
229
|
+
handle(ctx: RouterContext, next: Next): Promise<Response | void>;
|
|
230
|
+
}
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region src/response-cache/types.d.ts
|
|
233
|
+
/** Options accepted by `@Cacheable`. Every field is optional so module defaults can supply it. */
|
|
234
|
+
interface CacheableOptions {
|
|
235
|
+
/** Freshness lifetime in seconds, emitted as `max-age`. */
|
|
236
|
+
ttl?: number;
|
|
237
|
+
/**
|
|
238
|
+
* How long a PRIVATE cache — a visitor's browser — may reuse the response
|
|
239
|
+
* without asking, in seconds. Defaults to {@link ttl}.
|
|
240
|
+
*
|
|
241
|
+
* Set it to `0` for a response whose retraction has to be reliable. A purge
|
|
242
|
+
* reaches the shared cache and nothing else, so for a long `ttl` a browser
|
|
243
|
+
* copy outlives the response the server has already withdrawn. Pair `0` with
|
|
244
|
+
* {@link swr} and the browser still paints from its copy without waiting on
|
|
245
|
+
* the network, then picks the retraction up in the background.
|
|
246
|
+
*/
|
|
247
|
+
browserTtl?: number;
|
|
248
|
+
/** `stale-while-revalidate` window in seconds. */
|
|
249
|
+
swr?: number;
|
|
250
|
+
/** `Cache-Tag` values. Supports `{scope.path}` interpolation. Never defaulted at module level. */
|
|
251
|
+
tags?: string[];
|
|
252
|
+
/** Named partitions placed into `ctx.props`. An explicit `[]` declares the route public. */
|
|
253
|
+
partitionBy?: string[];
|
|
254
|
+
/** Additional `Vary` header names, unioned with module defaults. */
|
|
255
|
+
vary?: string[];
|
|
256
|
+
}
|
|
257
|
+
/** Options accepted by `@PurgesCache`. */
|
|
258
|
+
interface PurgesCacheOptions {
|
|
259
|
+
tags?: string[];
|
|
260
|
+
pathPrefixes?: string[];
|
|
261
|
+
/** Exclusive — cannot be combined with `tags` or `pathPrefixes`. */
|
|
262
|
+
purgeEverything?: boolean;
|
|
263
|
+
}
|
|
264
|
+
/** A `@Cacheable` config after module defaults have been applied. */
|
|
265
|
+
interface ResolvedCacheable {
|
|
266
|
+
ttl: number;
|
|
267
|
+
browserTtl: number;
|
|
268
|
+
swr?: number;
|
|
269
|
+
tags: string[];
|
|
270
|
+
partitionBy: string[];
|
|
271
|
+
vary: string[];
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Resolves one named partition value for the current request.
|
|
275
|
+
*
|
|
276
|
+
* Runs in the gateway, after the primer chain, so `ctx.user()` and the
|
|
277
|
+
* request-scoped container are available. Returning `null` or `undefined`
|
|
278
|
+
* fails closed — the response is not cached.
|
|
279
|
+
*/
|
|
280
|
+
type PartitionResolver = (ctx: RouterContext) => string | null | undefined | Promise<string | null | undefined>;
|
|
281
|
+
/**
|
|
282
|
+
* The `gateway.entrypoint` names derivable from a Worker's exports map.
|
|
283
|
+
*
|
|
284
|
+
* Drops `'default'`: the cached entrypoint is never the default export
|
|
285
|
+
* (`cachedEntrypoint` and the boot check both reject that), so naming it is
|
|
286
|
+
* always a mistake — one worth catching at compile time rather than on the
|
|
287
|
+
* first request after deploy. Non-string keys are dropped too.
|
|
288
|
+
*
|
|
289
|
+
* Degrades to `string` when the exports map is empty. That covers both a
|
|
290
|
+
* project that has not run `wrangler types` and the framework's own
|
|
291
|
+
* compilation, where `Cloudflare.Exports` is `{}` — neither should be blocked,
|
|
292
|
+
* and `resolveCachedEntrypoint` stays the runtime backstop for them.
|
|
293
|
+
*
|
|
294
|
+
* @typeParam Exports - a Worker's top-level exports, e.g. `Cloudflare.Exports`.
|
|
295
|
+
*/
|
|
296
|
+
type EntrypointNameFrom<Exports> = [Exclude<Extract<keyof Exports, string>, 'default'>] extends [never] ? string : Exclude<Extract<keyof Exports, string>, 'default'>;
|
|
297
|
+
/**
|
|
298
|
+
* The names `gateway.entrypoint` accepts.
|
|
299
|
+
*
|
|
300
|
+
* In a consumer project that has run `wrangler types`, `Cloudflare.Exports` is
|
|
301
|
+
* populated from `Cloudflare.GlobalProps.mainModule`, so this resolves to the
|
|
302
|
+
* union of that Worker's real, non-default export names: a typo like `'Cachd'`
|
|
303
|
+
* is a compile error at the config site, not a `ResponseCacheConfigError` on
|
|
304
|
+
* the first request after deploy. Without generated types it is `string`.
|
|
305
|
+
*/
|
|
306
|
+
type CachedEntrypointName = EntrypointNameFrom<Cloudflare.Exports>;
|
|
307
|
+
/**
|
|
308
|
+
* Names the cached entrypoint the gateway forwards partitioned reads to.
|
|
309
|
+
*
|
|
310
|
+
* The framework cannot discover the consumer's export name, so it is
|
|
311
|
+
* configured. It must match a top-level export built with
|
|
312
|
+
* `cachedEntrypoint(stratal)` from `stratal/workers`, and that export must be
|
|
313
|
+
* declared in the Wrangler `exports` block with `cache: { enabled: true }`
|
|
314
|
+
* while the default export has `cache: { enabled: false }`.
|
|
315
|
+
*/
|
|
316
|
+
interface ResponseCacheGatewayOptions {
|
|
317
|
+
/**
|
|
318
|
+
* e.g. `'Cached'` for `export const Cached = cachedEntrypoint(stratal)`.
|
|
319
|
+
*
|
|
320
|
+
* Typed as {@link CachedEntrypointName}: when `wrangler types` has generated
|
|
321
|
+
* `Cloudflare.Exports`, only this Worker's real, non-default export names are
|
|
322
|
+
* accepted, so a typo is caught by the type checker. It is still validated at
|
|
323
|
+
* runtime (`resolveCachedEntrypoint`) for projects without generated types.
|
|
324
|
+
*/
|
|
325
|
+
entrypoint: CachedEntrypointName;
|
|
326
|
+
/**
|
|
327
|
+
* Request headers whose values join the cache key, for routes that answer
|
|
328
|
+
* one URL with more than one representation.
|
|
329
|
+
*
|
|
330
|
+
* `Vary` is the mechanism HTTP defines for this, and Workers Caching
|
|
331
|
+
* documents it as honoured — but a response that varies is only *correct*
|
|
332
|
+
* when the thing it varies on is in the key, and the key is the one part of
|
|
333
|
+
* this that the framework controls. `ctx.props` is documented as impossible
|
|
334
|
+
* to bypass; `Vary` is a request-matching pass on top of a stored entry, and
|
|
335
|
+
* a URL carrying a query string has been measured serving one
|
|
336
|
+
* representation to a request that asked for the other. Naming the headers
|
|
337
|
+
* here makes the representation part of the key itself, so two
|
|
338
|
+
* representations are two entries and no matching pass has to hold.
|
|
339
|
+
*
|
|
340
|
+
* For an Inertia app this is `INERTIA_VARY_HEADERS` from `@stratal/inertia`:
|
|
341
|
+
* the document, the visit and each distinct partial reload are separate
|
|
342
|
+
* representations of one URL.
|
|
343
|
+
*
|
|
344
|
+
* Anything a response declares in `Vary` that is not named here (or handled
|
|
345
|
+
* by the platform itself, as `Accept-Encoding` is) makes that response
|
|
346
|
+
* uncacheable rather than wrongly cacheable — see `CacheabilityService`.
|
|
347
|
+
*/
|
|
348
|
+
keyBy?: readonly string[];
|
|
349
|
+
}
|
|
350
|
+
interface ResponseCacheModuleOptions {
|
|
351
|
+
/** Defaults applied to every `@Cacheable` route. `tags` is not defaultable. */
|
|
352
|
+
defaults?: Omit<CacheableOptions, 'tags'>;
|
|
353
|
+
/**
|
|
354
|
+
* The cached entrypoint partitioned reads are forwarded to.
|
|
355
|
+
*
|
|
356
|
+
* Required before any route may declare a non-empty `partitionBy`, and
|
|
357
|
+
* before `partitions`/`primers` may be configured — without it there is no
|
|
358
|
+
* way to place a partition in the cache key, and a route marked per-user
|
|
359
|
+
* that quietly shared one cache entry would serve one visitor's page to
|
|
360
|
+
* everyone.
|
|
361
|
+
*/
|
|
362
|
+
gateway?: ResponseCacheGatewayOptions;
|
|
363
|
+
/**
|
|
364
|
+
* Named partition resolvers, referenced by `partitionBy`.
|
|
365
|
+
*
|
|
366
|
+
* Resolvers run in the gateway, after the primer chain, so `ctx.user()` and
|
|
367
|
+
* the request-scoped container are available. Requires `gateway`: without a
|
|
368
|
+
* cached entrypoint nothing would ever call them, so configuring them alone
|
|
369
|
+
* throws `ResponseCacheConfigError` at boot rather than reading as proof
|
|
370
|
+
* that per-user keying is in effect.
|
|
371
|
+
*/
|
|
372
|
+
partitions?: Record<string, PartitionResolver>;
|
|
373
|
+
/**
|
|
374
|
+
* Middleware run in the gateway before partition resolution, so resolvers
|
|
375
|
+
* see the same context the app would.
|
|
376
|
+
*
|
|
377
|
+
* `@stratal/framework` exports `AUTH_GATEWAY_PRIMERS` for this — pass it to
|
|
378
|
+
* make `ctx.user()` resolve inside a partition resolver. Requires
|
|
379
|
+
* `gateway`, for the same reason `partitions` does.
|
|
380
|
+
*/
|
|
381
|
+
primers?: readonly (new (...args: never[]) => Middleware)[];
|
|
382
|
+
}
|
|
383
|
+
//#endregion
|
|
384
|
+
//#region src/response-cache/services/cacheability.service.d.ts
|
|
385
|
+
/** Inertia-specific conditions that make a page unsafe to cache. */
|
|
386
|
+
interface InertiaCacheSignals {
|
|
387
|
+
hasFlash: boolean;
|
|
388
|
+
isPartial: boolean;
|
|
389
|
+
hasOnceProps: boolean;
|
|
390
|
+
/**
|
|
391
|
+
* Request headers the adapter reports this response is a function of.
|
|
392
|
+
* Unioned into `Vary`, so a partial reload and the full page at the same URL
|
|
393
|
+
* are stored as separate variants rather than colliding.
|
|
394
|
+
*
|
|
395
|
+
* Required rather than optional: an empty list is what makes a partial reload
|
|
396
|
+
* fail closed, and an adapter that simply forgot the field would otherwise be
|
|
397
|
+
* indistinguishable from one declaring the response unkeyed.
|
|
398
|
+
*/
|
|
399
|
+
varyHeaders: readonly string[];
|
|
400
|
+
}
|
|
401
|
+
interface CacheabilitySignals {
|
|
402
|
+
/** False when any declared partition resolver returned null/undefined. */
|
|
403
|
+
partitionsResolved: boolean;
|
|
404
|
+
inertia?: InertiaCacheSignals;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Decides whether a `@Cacheable` response may actually be cached, and stamps
|
|
408
|
+
* the headers that say so.
|
|
409
|
+
*
|
|
410
|
+
* Everything that is not provably safe becomes `private, no-store`. That
|
|
411
|
+
* matters more than it looks: Workers Caching applies RFC 9111 heuristic
|
|
412
|
+
* freshness, so a response with no `Cache-Control` at all is still cached —
|
|
413
|
+
* `200` for two hours. Silence is not a safe default here.
|
|
414
|
+
*/
|
|
415
|
+
declare class CacheabilityService {
|
|
416
|
+
private readonly logger;
|
|
417
|
+
private readonly options;
|
|
418
|
+
constructor(logger: LoggerService, options: ResponseCacheModuleOptions);
|
|
419
|
+
apply(response: Response, resolved: ResolvedCacheable, scopes: TagScopes, signals: CacheabilitySignals): Response;
|
|
420
|
+
/** The first condition that makes this response unsafe to cache, if any. */
|
|
421
|
+
private rejectionReason;
|
|
422
|
+
/**
|
|
423
|
+
* What a PRIVATE cache — a visitor's browser — may do with the response.
|
|
424
|
+
*
|
|
425
|
+
* A browser copy is the one this feature cannot reach: `Cache-Tag` and
|
|
426
|
+
* `ctx.cache.purge()` retire the shared copy, and nothing retires that one.
|
|
427
|
+
* So `browserTtl` is what a route says it is willing to have held without
|
|
428
|
+
* being askable, and it defaults to `ttl` — the same lifetime the shared
|
|
429
|
+
* cache was already given.
|
|
430
|
+
*
|
|
431
|
+
* `stale-while-revalidate` is emitted here as well as on the shared header,
|
|
432
|
+
* and it is what makes a short `browserTtl` cheap rather than punishing: the
|
|
433
|
+
* browser paints from the copy it has instead of waiting on the network, and
|
|
434
|
+
* fetches the replacement behind that. A route that must be retractable sets
|
|
435
|
+
* `browserTtl: 0` with a stale window, and converges on the next navigation
|
|
436
|
+
* rather than holding a withdrawn response for the whole `ttl`.
|
|
437
|
+
*
|
|
438
|
+
* `must-revalidate` only where there is no stale window to protect: it
|
|
439
|
+
* forbids serving stale at all, which is the opposite of what `swr` asks
|
|
440
|
+
* for, so emitting both would leave the pair contradicting each other.
|
|
441
|
+
*/
|
|
442
|
+
private browserCacheControl;
|
|
443
|
+
/** The lifetime, for the cache that can be purged. */
|
|
444
|
+
private sharedCacheControl;
|
|
445
|
+
/** Union the declared Vary names with whatever the response already set. */
|
|
446
|
+
private mergeVary;
|
|
447
|
+
/**
|
|
448
|
+
* Overlay headers onto the response, mutating in place when the header
|
|
449
|
+
* list is writable — see `setResponseHeaders` for why that's the common
|
|
450
|
+
* case and safe. `Cache-Tag` and `CDN-Cache-Control` are explicitly deleted
|
|
451
|
+
* (not just omitted) when degrading to `no-store`, so neither a stale tag
|
|
452
|
+
* nor a lifetime from a differently-decided response lingers. The second
|
|
453
|
+
* matters most: Cloudflare reads `CDN-Cache-Control` in preference to
|
|
454
|
+
* `Cache-Control`, so one left behind would cache a response this just
|
|
455
|
+
* refused to cache.
|
|
456
|
+
*/
|
|
457
|
+
private withHeaders;
|
|
458
|
+
}
|
|
459
|
+
//#endregion
|
|
141
460
|
//#region src/router/constants.d.ts
|
|
142
461
|
/**
|
|
143
462
|
* Type-safe context keys for Hono router variables
|
|
144
463
|
* Using symbols to avoid string collisions
|
|
145
464
|
*/
|
|
146
465
|
declare const ROUTER_CONTEXT_KEYS: {
|
|
147
|
-
readonly REQUEST_CONTAINER:
|
|
148
|
-
readonly LOCALE:
|
|
466
|
+
readonly REQUEST_CONTAINER: 'requestContainer';
|
|
467
|
+
readonly LOCALE: 'locale';
|
|
468
|
+
readonly RESPONSE_PAYLOAD: 'responsePayload';
|
|
149
469
|
};
|
|
150
470
|
/**
|
|
151
471
|
* Metadata keys for storing route and controller configuration
|
|
@@ -163,15 +483,17 @@ declare const ROUTE_METADATA_KEYS: {
|
|
|
163
483
|
readonly WS_ON_CLOSE: symbol;
|
|
164
484
|
readonly WS_ON_ERROR: symbol;
|
|
165
485
|
readonly RATE_LIMIT: symbol;
|
|
486
|
+
readonly CACHEABLE: symbol;
|
|
487
|
+
readonly PURGES_CACHE: symbol;
|
|
166
488
|
};
|
|
167
489
|
/**
|
|
168
490
|
* Security scheme identifiers for OpenAPI
|
|
169
491
|
* These reference the security scheme definitions in security.schemas.ts
|
|
170
492
|
*/
|
|
171
493
|
declare const SECURITY_SCHEMES: {
|
|
172
|
-
readonly BEARER_AUTH:
|
|
173
|
-
readonly API_KEY:
|
|
174
|
-
readonly SESSION_COOKIE:
|
|
494
|
+
readonly BEARER_AUTH: 'bearerAuth';
|
|
495
|
+
readonly API_KEY: 'apiKey';
|
|
496
|
+
readonly SESSION_COOKIE: 'sessionCookie';
|
|
175
497
|
};
|
|
176
498
|
/**
|
|
177
499
|
* HTTP method mapping for RESTful controller methods
|
|
@@ -179,28 +501,28 @@ declare const SECURITY_SCHEMES: {
|
|
|
179
501
|
*/
|
|
180
502
|
declare const HTTP_METHODS: {
|
|
181
503
|
readonly index: {
|
|
182
|
-
readonly method:
|
|
183
|
-
readonly path:
|
|
504
|
+
readonly method: 'get';
|
|
505
|
+
readonly path: '';
|
|
184
506
|
};
|
|
185
507
|
readonly show: {
|
|
186
|
-
readonly method:
|
|
187
|
-
readonly path:
|
|
508
|
+
readonly method: 'get';
|
|
509
|
+
readonly path: '/:id';
|
|
188
510
|
};
|
|
189
511
|
readonly create: {
|
|
190
|
-
readonly method:
|
|
191
|
-
readonly path:
|
|
512
|
+
readonly method: 'post';
|
|
513
|
+
readonly path: '';
|
|
192
514
|
};
|
|
193
515
|
readonly update: {
|
|
194
|
-
readonly method:
|
|
195
|
-
readonly path:
|
|
516
|
+
readonly method: 'put';
|
|
517
|
+
readonly path: '/:id';
|
|
196
518
|
};
|
|
197
519
|
readonly patch: {
|
|
198
|
-
readonly method:
|
|
199
|
-
readonly path:
|
|
520
|
+
readonly method: 'patch';
|
|
521
|
+
readonly path: '/:id';
|
|
200
522
|
};
|
|
201
523
|
readonly destroy: {
|
|
202
|
-
readonly method:
|
|
203
|
-
readonly path:
|
|
524
|
+
readonly method: 'delete';
|
|
525
|
+
readonly path: '/:id';
|
|
204
526
|
};
|
|
205
527
|
};
|
|
206
528
|
/**
|
|
@@ -211,10 +533,10 @@ declare const VERSION_NEUTRAL: unique symbol;
|
|
|
211
533
|
//#endregion
|
|
212
534
|
//#region src/router/types.d.ts
|
|
213
535
|
/**
|
|
214
|
-
* Route parameter type
|
|
215
|
-
*
|
|
536
|
+
* Route parameter type — a Zod object schema (its `.shape` is composed with
|
|
537
|
+
* router-prefix params at registration).
|
|
216
538
|
*/
|
|
217
|
-
type ZodObjectWithEffect =
|
|
539
|
+
type ZodObjectWithEffect = ZodObject<any>;
|
|
218
540
|
type RouteParameter = ZodObjectWithEffect | undefined;
|
|
219
541
|
/**
|
|
220
542
|
* Hono context variables with type-safe keys
|
|
@@ -223,9 +545,28 @@ interface RouterVariables {
|
|
|
223
545
|
[ROUTER_CONTEXT_KEYS.REQUEST_CONTAINER]: Container;
|
|
224
546
|
[ROUTER_CONTEXT_KEYS.LOCALE]?: string;
|
|
225
547
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
548
|
+
* The handler's captured JSON payload, set by `capturePayload()` so
|
|
549
|
+
* `{data.*}` response-cache tag templates can read values the request
|
|
550
|
+
* itself never carried. Only populated for routes that declared a tag
|
|
551
|
+
* needing it — see `needsPayloadCapture`.
|
|
552
|
+
*/
|
|
553
|
+
[ROUTER_CONTEXT_KEYS.RESPONSE_PAYLOAD]?: unknown;
|
|
554
|
+
/**
|
|
555
|
+
* Cache safety signals for the page rendered on this request, set by
|
|
556
|
+
* `@stratal/inertia`'s `InertiaService.render()`. Read by
|
|
557
|
+
* `RouteRegistrationService.applyCacheDecision()` and passed to
|
|
558
|
+
* `CacheabilityService.apply()` so a `@Cacheable` route serving an Inertia
|
|
559
|
+
* page with flash data, a partial reload, or once-props fails closed
|
|
560
|
+
* instead of caching and replaying it. Declared here (not imported from
|
|
561
|
+
* `@stratal/inertia`) so core never depends on that package — the key is
|
|
562
|
+
* only ever populated when `@stratal/inertia` is in use.
|
|
563
|
+
*/
|
|
564
|
+
inertiaCacheSignals?: InertiaCacheSignals;
|
|
565
|
+
/**
|
|
566
|
+
* When set by middleware, the route handler returns this response instead of
|
|
567
|
+
* invoking the controller — skipping the handler entirely once request
|
|
568
|
+
* validators have passed. Used by packages like `@stratal/inertia` for
|
|
569
|
+
* precognition support.
|
|
229
570
|
*/
|
|
230
571
|
validationSuccessResponse?: Response;
|
|
231
572
|
/** Domain parameters set by the domain matching middleware (e.g., `domain:tenant`) */
|
|
@@ -247,23 +588,28 @@ type SecurityScheme = typeof SECURITY_SCHEMES[keyof typeof SECURITY_SCHEMES];
|
|
|
247
588
|
* HTTP method type from OpenAPI spec
|
|
248
589
|
*/
|
|
249
590
|
type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'options' | 'trace' | 'all';
|
|
591
|
+
/**
|
|
592
|
+
* Security scheme record for OpenAPI security array format
|
|
593
|
+
* Maps scheme names to scopes (empty array for no scopes)
|
|
594
|
+
*/
|
|
595
|
+
type SecuritySchemeRecord = Record<SecurityScheme, string[]>;
|
|
250
596
|
/**
|
|
251
597
|
* Object form for request body with optional content type
|
|
252
598
|
*/
|
|
253
599
|
interface RouteBodyObject {
|
|
254
|
-
schema:
|
|
600
|
+
schema: ZodType;
|
|
255
601
|
contentType?: string;
|
|
256
602
|
}
|
|
257
603
|
/**
|
|
258
604
|
* Request body definition for @Route() decorator
|
|
259
605
|
* Bare ZodType defaults to application/json
|
|
260
606
|
*/
|
|
261
|
-
type RouteBody =
|
|
607
|
+
type RouteBody = ZodType | RouteBodyObject;
|
|
262
608
|
/**
|
|
263
609
|
* Object form for response with optional description and content type
|
|
264
610
|
*/
|
|
265
611
|
interface RouteResponseObject {
|
|
266
|
-
schema:
|
|
612
|
+
schema: ZodType;
|
|
267
613
|
description?: string;
|
|
268
614
|
contentType?: string;
|
|
269
615
|
}
|
|
@@ -271,7 +617,7 @@ interface RouteResponseObject {
|
|
|
271
617
|
* Single response definition for @Route() decorator
|
|
272
618
|
* Status code is auto-derived from method name (create->201, others->200)
|
|
273
619
|
*/
|
|
274
|
-
type RouteResponse =
|
|
620
|
+
type RouteResponse = ZodType | RouteResponseObject;
|
|
275
621
|
/**
|
|
276
622
|
* Route configuration for @Route() decorator
|
|
277
623
|
* Defines OpenAPI metadata for a controller method
|
|
@@ -279,11 +625,11 @@ type RouteResponse = zod_d_exports.ZodType | RouteResponseObject;
|
|
|
279
625
|
interface RouteConfig {
|
|
280
626
|
/**
|
|
281
627
|
* Request body schema (for POST, PUT, PATCH)
|
|
282
|
-
* @example
|
|
628
|
+
* @example object({}) or { schema: object({}), contentType: 'multipart/form-data' }
|
|
283
629
|
*/
|
|
284
630
|
body?: RouteBody;
|
|
285
631
|
/**
|
|
286
|
-
* URL parameters schema (e.g., { id:
|
|
632
|
+
* URL parameters schema (e.g., object({ id: uuid() }))
|
|
287
633
|
* Must be ZodObject or ZodPipe for OpenAPI compatibility
|
|
288
634
|
*/
|
|
289
635
|
params?: RouteParameter;
|
|
@@ -309,6 +655,11 @@ interface RouteConfig {
|
|
|
309
655
|
* Empty array = public route (no auth)
|
|
310
656
|
*/
|
|
311
657
|
security?: SecurityScheme[];
|
|
658
|
+
/**
|
|
659
|
+
* Visibility group labels for this route.
|
|
660
|
+
* Appended to the controller-level groups.
|
|
661
|
+
*/
|
|
662
|
+
groups?: string[];
|
|
312
663
|
/**
|
|
313
664
|
* Human-readable description for OpenAPI docs
|
|
314
665
|
*/
|
|
@@ -377,6 +728,11 @@ interface ControllerOptions {
|
|
|
377
728
|
* Routes can add more schemes or override with empty array
|
|
378
729
|
*/
|
|
379
730
|
security?: SecurityScheme[];
|
|
731
|
+
/**
|
|
732
|
+
* Default visibility group labels applied to every route in this controller.
|
|
733
|
+
* Routes append more via the route-level `groups`.
|
|
734
|
+
*/
|
|
735
|
+
groups?: string[];
|
|
380
736
|
/**
|
|
381
737
|
* Hide all routes in this controller from OpenAPI documentation
|
|
382
738
|
* Routes remain functional but won't appear in /api/docs or /api/openapi.json
|
|
@@ -492,8 +848,58 @@ interface LocaleUrlConfig {
|
|
|
492
848
|
}
|
|
493
849
|
//#endregion
|
|
494
850
|
//#region src/execution-context.d.ts
|
|
851
|
+
/** A purge request in the shape `ctx.cache.purge()` accepts. */
|
|
852
|
+
interface PurgeSpec {
|
|
853
|
+
tags?: string[];
|
|
854
|
+
pathPrefixes?: string[];
|
|
855
|
+
purgeEverything?: true;
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* The subset of Cloudflare's Workers Caching API (`ctx.cache`) Stratal uses.
|
|
859
|
+
*
|
|
860
|
+
* Declared here rather than under `response-cache/` so the dependency points
|
|
861
|
+
* from the feature to this foundational module, not the reverse — describing
|
|
862
|
+
* the shape of an execution context should not require knowing about a
|
|
863
|
+
* feature. `stratal/response-cache` re-exports both types, so consumers still
|
|
864
|
+
* import them from there.
|
|
865
|
+
*/
|
|
866
|
+
interface WorkersCache {
|
|
867
|
+
purge(spec: PurgeSpec): Promise<{
|
|
868
|
+
success: boolean;
|
|
869
|
+
} | void>;
|
|
870
|
+
}
|
|
495
871
|
interface StratalExecutionContext {
|
|
496
872
|
waitUntil(promise: Promise<unknown>): void;
|
|
873
|
+
/**
|
|
874
|
+
* The Cloudflare Workers Caching API (`ctx.cache`). Optional because
|
|
875
|
+
* Wrangler only attaches it when `cache.enabled: true` is configured — see
|
|
876
|
+
* `cachingUnavailableReason`, which reports why `@Cacheable`/`@PurgesCache`
|
|
877
|
+
* routes are serving uncached when this is absent.
|
|
878
|
+
*
|
|
879
|
+
* Declared here (rather than left for call sites to cast onto their own
|
|
880
|
+
* narrower `ExecutionContext`) so `@stratal/testing` can populate a stub on
|
|
881
|
+
* the same object it hands to `Application` and to `HonoApp#fetch`, making
|
|
882
|
+
* cache-decorated routes testable without a real Workers Caching binding.
|
|
883
|
+
*/
|
|
884
|
+
cache?: WorkersCache;
|
|
885
|
+
/**
|
|
886
|
+
* Loopback bindings to the Worker's own top-level exports (`ctx.exports`),
|
|
887
|
+
* available with the `enable_ctx_exports` compatibility flag.
|
|
888
|
+
*
|
|
889
|
+
* `stratal/response-cache`'s gateway forwards partitioned reads through
|
|
890
|
+
* this, so it is declared here for the same reason `cache` is: so
|
|
891
|
+
* `@stratal/testing` can populate a stub on the object it hands to
|
|
892
|
+
* `Application` and `HonoApp#fetch`. Typed loosely because the shape of any
|
|
893
|
+
* one binding depends on the consumer's own exports, which the framework
|
|
894
|
+
* cannot know — see `resolveCachedEntrypoint`, which checks it at runtime.
|
|
895
|
+
*/
|
|
896
|
+
exports?: Record<string, unknown>;
|
|
897
|
+
/**
|
|
898
|
+
* The `ctx.props` the caller chose for this invocation. Wholly part of the
|
|
899
|
+
* Workers Caching cache key, which is what makes per-caller partitioning
|
|
900
|
+
* safe. Set by the gateway when it dispatches; never read by the framework.
|
|
901
|
+
*/
|
|
902
|
+
props?: unknown;
|
|
497
903
|
}
|
|
498
904
|
//#endregion
|
|
499
905
|
//#region src/di/lazy.d.ts
|
|
@@ -694,56 +1100,20 @@ interface IController {
|
|
|
694
1100
|
handle?(ctx: RouterContext): Promise<Response> | Response;
|
|
695
1101
|
}
|
|
696
1102
|
//#endregion
|
|
697
|
-
//#region src/router/middleware.interface.d.ts
|
|
698
|
-
type Next$1 = Next;
|
|
699
|
-
/**
|
|
700
|
-
* Middleware interface for request processing
|
|
701
|
-
*
|
|
702
|
-
* Middlewares use the `@Transient()` decorator and are registered via
|
|
703
|
-
* `configureRoutes(router)` in modules implementing `RouteConfigurable`.
|
|
704
|
-
*
|
|
705
|
-
* @example
|
|
706
|
-
* ```typescript
|
|
707
|
-
* @Transient()
|
|
708
|
-
* export class LoggingMiddleware implements Middleware {
|
|
709
|
-
* async handle(ctx: RouterContext, next: () => Promise<void>): Promise<void> {
|
|
710
|
-
* const start = Date.now()
|
|
711
|
-
* await next()
|
|
712
|
-
* console.log(`Request took ${Date.now() - start}ms`)
|
|
713
|
-
* }
|
|
714
|
-
* }
|
|
715
|
-
*
|
|
716
|
-
* // Register in module:
|
|
717
|
-
* @Module({ providers: [LoggingMiddleware] })
|
|
718
|
-
* export class AppModule implements RouteConfigurable {
|
|
719
|
-
* configureRoutes(router: Router): void {
|
|
720
|
-
* router.middleware(LoggingMiddleware)
|
|
721
|
-
* }
|
|
722
|
-
* }
|
|
723
|
-
* ```
|
|
724
|
-
*/
|
|
725
|
-
interface Middleware {
|
|
726
|
-
/**
|
|
727
|
-
* Handle middleware logic
|
|
728
|
-
* Call next() to continue the middleware chain
|
|
729
|
-
*
|
|
730
|
-
* @param ctx - Router context with request/response helpers
|
|
731
|
-
* @param next - Function to call the next middleware or route handler
|
|
732
|
-
*/
|
|
733
|
-
handle(ctx: RouterContext, next: Next$1): Promise<Response | void>;
|
|
734
|
-
}
|
|
735
|
-
//#endregion
|
|
736
1103
|
//#region src/router/hono-app.d.ts
|
|
737
1104
|
/**
|
|
738
|
-
* HonoApp — extends
|
|
1105
|
+
* HonoApp — extends plain Hono with Stratal-specific setup
|
|
739
1106
|
*
|
|
740
1107
|
* - Request scope middleware (child container per request)
|
|
741
1108
|
* - Global middleware (CORS, logging, error handling)
|
|
742
|
-
* - defaultHook for validation errors
|
|
743
1109
|
* - `use()` overload for Stratal middleware classes
|
|
744
1110
|
* - `configure()` for OpenAPI, routes, and 404
|
|
1111
|
+
*
|
|
1112
|
+
* Request validation is attached per-route via `hono/validator` middleware (see
|
|
1113
|
+
* route-registration), not a base-class hook, so schema-less routes pull in no
|
|
1114
|
+
* validation/zod code.
|
|
745
1115
|
*/
|
|
746
|
-
declare class HonoApp extends
|
|
1116
|
+
declare class HonoApp extends Hono<RouterEnv> {
|
|
747
1117
|
private configured;
|
|
748
1118
|
private readonly _container;
|
|
749
1119
|
private readonly _logger;
|
|
@@ -768,6 +1138,177 @@ declare class HonoApp extends OpenAPIHono<RouterEnv> {
|
|
|
768
1138
|
private handleException;
|
|
769
1139
|
}
|
|
770
1140
|
//#endregion
|
|
1141
|
+
//#region src/i18n/i18n.options.d.ts
|
|
1142
|
+
/**
|
|
1143
|
+
* Detection strategy for locale resolution
|
|
1144
|
+
*
|
|
1145
|
+
* - `'cookie'` — reads from the `locale` cookie (default)
|
|
1146
|
+
* - `'header'` — reads from the `Accept-Language` header
|
|
1147
|
+
* - `'querystring'` — reads from the `?locale=` query parameter
|
|
1148
|
+
* - `'path'` — reads from the first URL path segment (e.g., `/en/api/users`)
|
|
1149
|
+
*/
|
|
1150
|
+
type DetectionStrategy = 'cookie' | 'header' | 'querystring' | 'path';
|
|
1151
|
+
/** The cookie (and query-string key) the `locale` is read from / written to. */
|
|
1152
|
+
declare const LOCALE_COOKIE = "locale";
|
|
1153
|
+
interface BaseDetection {
|
|
1154
|
+
/** Set to false to disable language detection entirely. @default true */
|
|
1155
|
+
enabled?: boolean;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Language detection options (discriminated by strategy)
|
|
1159
|
+
*
|
|
1160
|
+
* @example Cookie detection (default)
|
|
1161
|
+
* ```typescript
|
|
1162
|
+
* { strategy: 'cookie' }
|
|
1163
|
+
* ```
|
|
1164
|
+
*
|
|
1165
|
+
* @example Header detection
|
|
1166
|
+
* ```typescript
|
|
1167
|
+
* { strategy: 'header' }
|
|
1168
|
+
* ```
|
|
1169
|
+
*
|
|
1170
|
+
* @example Path detection
|
|
1171
|
+
* ```typescript
|
|
1172
|
+
* { strategy: 'path' }
|
|
1173
|
+
* ```
|
|
1174
|
+
*
|
|
1175
|
+
* @example Disable detection
|
|
1176
|
+
* ```typescript
|
|
1177
|
+
* { enabled: false }
|
|
1178
|
+
* ```
|
|
1179
|
+
*/
|
|
1180
|
+
type LanguageDetectionOptions = (BaseDetection & {
|
|
1181
|
+
strategy?: 'cookie';
|
|
1182
|
+
cookieOptions?: DetectorOptions['cookieOptions'];
|
|
1183
|
+
}) | (BaseDetection & {
|
|
1184
|
+
strategy: 'header';
|
|
1185
|
+
}) | (BaseDetection & {
|
|
1186
|
+
strategy: 'querystring';
|
|
1187
|
+
}) | (BaseDetection & {
|
|
1188
|
+
strategy: 'path';
|
|
1189
|
+
/**
|
|
1190
|
+
* Controls whether the default locale gets a URL path prefix.
|
|
1191
|
+
*
|
|
1192
|
+
* - `false` (default) — The default locale has no prefix (`/users`), other locales
|
|
1193
|
+
* are prefixed (`/fr/users`). Requests to the prefixed default locale (`/en/users`) return 404.
|
|
1194
|
+
* - `'redirect'` — Same as `false`, but requests to the prefixed default locale
|
|
1195
|
+
* (`/en/users`) are 301-redirected to the unprefixed path (`/users`).
|
|
1196
|
+
* - `true` — All locales are prefixed (`/en/users`, `/fr/users`).
|
|
1197
|
+
*
|
|
1198
|
+
* @default false
|
|
1199
|
+
*/
|
|
1200
|
+
prefixDefaultLocale?: false | true | 'redirect';
|
|
1201
|
+
}) | {
|
|
1202
|
+
enabled: false;
|
|
1203
|
+
};
|
|
1204
|
+
/**
|
|
1205
|
+
* A per-path detection resolver.
|
|
1206
|
+
*
|
|
1207
|
+
* Returns the detection options for a given request path. It **must be a pure
|
|
1208
|
+
* function of the path**: route `/:locale` variant expansion runs it at boot,
|
|
1209
|
+
* once per registered route pattern, where no request exists — so the decision
|
|
1210
|
+
* (e.g. "`/admin` is cookie-localized, everything else is path-localized") has
|
|
1211
|
+
* to be derivable from the path alone, and must agree at boot and per request.
|
|
1212
|
+
*
|
|
1213
|
+
* @example
|
|
1214
|
+
* ```typescript
|
|
1215
|
+
* detection: (path) =>
|
|
1216
|
+
* path.startsWith('/admin')
|
|
1217
|
+
* ? { strategy: 'cookie', cookieOptions: { path: '/admin' } }
|
|
1218
|
+
* : { strategy: 'path' }
|
|
1219
|
+
* ```
|
|
1220
|
+
*/
|
|
1221
|
+
type DetectionResolver = (path: string) => LanguageDetectionOptions;
|
|
1222
|
+
/** Detection config: a single static option set, or a per-path resolver. */
|
|
1223
|
+
type DetectionConfig = LanguageDetectionOptions | DetectionResolver;
|
|
1224
|
+
/**
|
|
1225
|
+
* Options for configuring the I18n module
|
|
1226
|
+
*
|
|
1227
|
+
* @example
|
|
1228
|
+
* ```typescript
|
|
1229
|
+
* I18nModule.forRoot({
|
|
1230
|
+
* defaultLocale: 'en',
|
|
1231
|
+
* fallbackLocale: 'en',
|
|
1232
|
+
* locales: ['en', 'fr'],
|
|
1233
|
+
* detection: { strategy: 'header' },
|
|
1234
|
+
* })
|
|
1235
|
+
* ```
|
|
1236
|
+
*/
|
|
1237
|
+
interface I18nModuleOptions {
|
|
1238
|
+
/**
|
|
1239
|
+
* Default locale for the application
|
|
1240
|
+
* @default 'en'
|
|
1241
|
+
*/
|
|
1242
|
+
defaultLocale?: string;
|
|
1243
|
+
/**
|
|
1244
|
+
* Fallback locale when translation is missing
|
|
1245
|
+
* @default 'en'
|
|
1246
|
+
*/
|
|
1247
|
+
fallbackLocale?: string;
|
|
1248
|
+
/**
|
|
1249
|
+
* List of supported locales
|
|
1250
|
+
* Request locales not in this list will fall back to defaultLocale
|
|
1251
|
+
*/
|
|
1252
|
+
locales?: string[];
|
|
1253
|
+
/**
|
|
1254
|
+
* Language detection configuration. Either a single option set applied to
|
|
1255
|
+
* every request, or a {@link DetectionResolver} — a pure function of the
|
|
1256
|
+
* request path — so different areas can use different strategies (e.g. a
|
|
1257
|
+
* path-localized public site with a cookie-localized `/admin` panel).
|
|
1258
|
+
*/
|
|
1259
|
+
detection?: DetectionConfig;
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* Detection options resolved for a single path (all defaults applied).
|
|
1263
|
+
*/
|
|
1264
|
+
interface ResolvedDetection {
|
|
1265
|
+
enabled: boolean;
|
|
1266
|
+
strategy: DetectionStrategy;
|
|
1267
|
+
/** Only meaningful when `strategy` is `'path'`. */
|
|
1268
|
+
prefixDefaultLocale: false | true | 'redirect';
|
|
1269
|
+
/**
|
|
1270
|
+
* Cookie attributes for the persisted `locale` cookie under cookie strategy
|
|
1271
|
+
* (e.g. `{ path: '/admin' }` to scope a panel's locale so it isn't written at
|
|
1272
|
+
* the default `Path=/`).
|
|
1273
|
+
*/
|
|
1274
|
+
cookieOptions?: DetectorOptions['cookieOptions'];
|
|
1275
|
+
}
|
|
1276
|
+
/**
|
|
1277
|
+
* Resolved options with all defaults applied
|
|
1278
|
+
* Used internally by I18n services
|
|
1279
|
+
*/
|
|
1280
|
+
interface ResolvedI18nOptions {
|
|
1281
|
+
defaultLocale: string;
|
|
1282
|
+
fallbackLocale: string;
|
|
1283
|
+
locales: string[];
|
|
1284
|
+
/**
|
|
1285
|
+
* Detection resolved at the application root (`/`) — the app's primary mode.
|
|
1286
|
+
* For per-path detail (when `detection` is a resolver) use
|
|
1287
|
+
* {@link resolveDetectionForPath}.
|
|
1288
|
+
*/
|
|
1289
|
+
detection: ResolvedDetection;
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1292
|
+
* Resolve the detection options for a given request path, evaluating the
|
|
1293
|
+
* per-path resolver when `detection` is a function.
|
|
1294
|
+
*/
|
|
1295
|
+
declare function resolveDetectionForPath(detection: DetectionConfig | undefined, path: string): ResolvedDetection;
|
|
1296
|
+
/**
|
|
1297
|
+
* Resolve I18n options with defaults. `detection` reflects the application root
|
|
1298
|
+
* (`/`); use {@link resolveDetectionForPath} for per-path detail.
|
|
1299
|
+
*/
|
|
1300
|
+
declare function resolveI18nOptions(options?: I18nModuleOptions): ResolvedI18nOptions;
|
|
1301
|
+
/**
|
|
1302
|
+
* Build Hono languageDetector options for a resolved detection + locale config.
|
|
1303
|
+
*
|
|
1304
|
+
* Cookie strategy persists the detected locale to the `locale` cookie
|
|
1305
|
+
* (`caches: ['cookie']`) using the resolved `cookieOptions` — so a per-path
|
|
1306
|
+
* cookie area scopes the write (e.g. `{ path: '/admin' }`) instead of writing
|
|
1307
|
+
* at the default `Path=/` and leaking across the app. Other strategies don't
|
|
1308
|
+
* write any cookie.
|
|
1309
|
+
*/
|
|
1310
|
+
declare function buildDetectorOptions(detection: ResolvedDetection, locales: string[], defaultLocale: string): Partial<DetectorOptions>;
|
|
1311
|
+
//#endregion
|
|
771
1312
|
//#region src/router/services/locale-path.service.d.ts
|
|
772
1313
|
/**
|
|
773
1314
|
* A resolved path with locale variant metadata.
|
|
@@ -781,48 +1322,59 @@ interface ResolvedPath {
|
|
|
781
1322
|
/**
|
|
782
1323
|
* Resolves locale path variants for route paths.
|
|
783
1324
|
*
|
|
784
|
-
*
|
|
785
|
-
* path
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
* to HonoApp when resolved from the container.
|
|
1325
|
+
* Detection can be static or a per-path resolver (see {@link DetectionConfig}),
|
|
1326
|
+
* so this evaluates it **per path**: which routes get a `/:locale` variant
|
|
1327
|
+
* (at registration) and which detector runs (per request). A path resolving to
|
|
1328
|
+
* a non-`path` strategy gets no variant and is localized out-of-band (cookie).
|
|
789
1329
|
*
|
|
790
|
-
*
|
|
1330
|
+
* Also applies language detection and default-locale redirect middleware to
|
|
1331
|
+
* HonoApp when resolved from the container. Registered as a singleton.
|
|
791
1332
|
*/
|
|
792
1333
|
declare class LocalePathService {
|
|
793
1334
|
private readonly honoApp;
|
|
794
|
-
private readonly
|
|
795
|
-
private readonly
|
|
796
|
-
private readonly
|
|
1335
|
+
private readonly _locales;
|
|
1336
|
+
private readonly _defaultLocale;
|
|
1337
|
+
private readonly _detection;
|
|
1338
|
+
/** Detection + config resolved at the application root (`/`) — the primary mode. */
|
|
1339
|
+
private readonly _primary;
|
|
1340
|
+
private readonly _primaryConfig;
|
|
797
1341
|
constructor(container: Container, honoApp: HonoApp);
|
|
798
|
-
/** Whether path-based locale
|
|
1342
|
+
/** Whether the app uses path-based locale URLs (resolved at the root). */
|
|
799
1343
|
get enabled(): boolean;
|
|
800
|
-
/** The
|
|
1344
|
+
/** The primary (root) locale path config, or null if the root isn't path-localized. */
|
|
801
1345
|
get localePathConfig(): LocalePathConfig | null;
|
|
802
|
-
/** The prefixDefaultLocale setting (false, true, or 'redirect') */
|
|
1346
|
+
/** The primary (root) prefixDefaultLocale setting (false, true, or 'redirect'). */
|
|
803
1347
|
get prefixDefaultLocale(): false | true | 'redirect';
|
|
1348
|
+
/** Resolve the detection options for a given request path. */
|
|
1349
|
+
detectionFor(path: string): ResolvedDetection;
|
|
1350
|
+
/**
|
|
1351
|
+
* Whether a pathname is path-localized — served with a `/:locale` segment.
|
|
1352
|
+
* `false` for paths resolving to a non-`path` strategy (localized by cookie)
|
|
1353
|
+
* or with detection disabled. Redirect middleware should skip non-localized
|
|
1354
|
+
* paths so it never prepends a locale segment.
|
|
1355
|
+
*/
|
|
1356
|
+
isPathLocalized(pathname: string): boolean;
|
|
804
1357
|
/**
|
|
805
1358
|
* Expand a path into primary + locale-prefixed variants.
|
|
806
1359
|
*
|
|
807
|
-
* @param path - The base path to expand
|
|
1360
|
+
* @param path - The base route path to expand
|
|
808
1361
|
* @returns Array of resolved paths with locale metadata
|
|
809
1362
|
*/
|
|
810
1363
|
resolve(path: string): ResolvedPath[];
|
|
1364
|
+
/** Build the locale path config for a resolved detection, or null if not path-localized. */
|
|
1365
|
+
private buildConfig;
|
|
811
1366
|
/**
|
|
812
|
-
*
|
|
813
|
-
*
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
/**
|
|
817
|
-
* Apply Hono's languageDetector middleware and bridge the detected language
|
|
818
|
-
* to Stratal's LOCALE context variable.
|
|
1367
|
+
* Apply Hono's languageDetector and bridge the detected language to Stratal's
|
|
1368
|
+
* LOCALE context variable. With a per-path resolver, the detector is chosen
|
|
1369
|
+
* per request (cached by strategy); with a static config, one detector is
|
|
1370
|
+
* built up front.
|
|
819
1371
|
*/
|
|
820
1372
|
private setupLanguageDetection;
|
|
821
1373
|
/**
|
|
822
1374
|
* Redirect requests that include the default locale prefix to the unprefixed path.
|
|
823
1375
|
* For example, `/en/users` → 301 redirect to `/users`.
|
|
824
1376
|
*
|
|
825
|
-
* Only active when `prefixDefaultLocale` is `'redirect'`.
|
|
1377
|
+
* Only active when the root `prefixDefaultLocale` is `'redirect'`.
|
|
826
1378
|
*/
|
|
827
1379
|
private setupDefaultLocaleRedirect;
|
|
828
1380
|
}
|
|
@@ -849,6 +1401,13 @@ declare class LocaleUrlService {
|
|
|
849
1401
|
applyPrefix(pathname: string, locale: string): string;
|
|
850
1402
|
/** Strip a known-locale prefix from the start of a pathname. */
|
|
851
1403
|
stripPrefix(pathname: string): string;
|
|
1404
|
+
/**
|
|
1405
|
+
* Whether a pathname is path-localized — served with a `/:locale` segment.
|
|
1406
|
+
* `false` for paths localized out-of-band (cookie strategy) or with detection
|
|
1407
|
+
* disabled. Redirect middleware should skip non-localized paths so it never
|
|
1408
|
+
* prepends a locale segment to a path that isn't path-localized.
|
|
1409
|
+
*/
|
|
1410
|
+
isPathLocalized(pathname: string): boolean;
|
|
852
1411
|
private toUrlConfig;
|
|
853
1412
|
}
|
|
854
1413
|
//#endregion
|
|
@@ -860,8 +1419,9 @@ declare class LocaleUrlService {
|
|
|
860
1419
|
* Only internal modules (RouterResolver) import them, keeping the Router's
|
|
861
1420
|
* public API clean — users never see these methods.
|
|
862
1421
|
*
|
|
863
|
-
*
|
|
864
|
-
*
|
|
1422
|
+
* Registered via `Symbol.for` so that a duplicate evaluation of this module
|
|
1423
|
+
* (e.g. under a bundler or SSR module runner) resolves to the same symbol,
|
|
1424
|
+
* keeping symbol-keyed dispatch between `Router` and `RouterResolver` stable.
|
|
865
1425
|
*
|
|
866
1426
|
* @internal
|
|
867
1427
|
*/
|
|
@@ -883,7 +1443,7 @@ interface RouterGroupConfig {
|
|
|
883
1443
|
middleware?: Constructor<Middleware>[];
|
|
884
1444
|
version?: string | string[];
|
|
885
1445
|
hideFromDocs?: boolean;
|
|
886
|
-
params?:
|
|
1446
|
+
params?: ZodObject<any>;
|
|
887
1447
|
}
|
|
888
1448
|
/**
|
|
889
1449
|
* Internal entry representing a sub-group or the default scope.
|
|
@@ -896,7 +1456,7 @@ interface RouterEntry {
|
|
|
896
1456
|
middleware: Constructor<Middleware>[];
|
|
897
1457
|
version?: string | string[];
|
|
898
1458
|
hideFromDocs?: boolean;
|
|
899
|
-
params?:
|
|
1459
|
+
params?: ZodObject<any>;
|
|
900
1460
|
/** Controllers in this entry. undefined = all controllers not in any sub-group */
|
|
901
1461
|
controllers?: Constructor[];
|
|
902
1462
|
}
|
|
@@ -939,7 +1499,7 @@ declare class Router {
|
|
|
939
1499
|
private readonly _globalMiddleware;
|
|
940
1500
|
constructor(isChild?: boolean);
|
|
941
1501
|
/** Dynamic path prefix. For shared segments like `/:companyId` */
|
|
942
|
-
prefix(path: string, params?:
|
|
1502
|
+
prefix(path: string, params?: ZodObject<any>): this;
|
|
943
1503
|
/** Domain pattern for controllers in this scope */
|
|
944
1504
|
domain(pattern: string): this;
|
|
945
1505
|
/** Name prefix for routes in this scope */
|
|
@@ -1050,6 +1610,122 @@ declare class ModuleRegistry {
|
|
|
1050
1610
|
private collectIfListener;
|
|
1051
1611
|
}
|
|
1052
1612
|
//#endregion
|
|
1613
|
+
//#region src/response-cache/services/gateway-route-table.d.ts
|
|
1614
|
+
/**
|
|
1615
|
+
* What the dispatch middleware needs to know about one route.
|
|
1616
|
+
*
|
|
1617
|
+
* Typed as a `CacheableOptions` (every field optional) rather than a bespoke
|
|
1618
|
+
* shape so it can be handed straight to `shouldLoopback`, which already
|
|
1619
|
+
* encodes "only GET/HEAD ever loop back".
|
|
1620
|
+
*/
|
|
1621
|
+
interface GatewayRouteEntry extends CacheableOptions {
|
|
1622
|
+
partitionBy: string[];
|
|
1623
|
+
}
|
|
1624
|
+
/**
|
|
1625
|
+
* `${METHOD} ${routePath}` → the partitions that route declared.
|
|
1626
|
+
*
|
|
1627
|
+
* Populated once, at route registration, and only for routes whose
|
|
1628
|
+
* **effective** `partitionBy` (after module defaults) is non-empty. Every
|
|
1629
|
+
* other route is absent, and absence means "run inline" — the safe default,
|
|
1630
|
+
* and the one that keeps an app which uses no partitions paying nothing but a
|
|
1631
|
+
* single `isEmpty` check per request.
|
|
1632
|
+
*
|
|
1633
|
+
* The key is the route *pattern* Hono matched (`/posts/:id`), not the request
|
|
1634
|
+
* path, so one entry serves every request to that route.
|
|
1635
|
+
*/
|
|
1636
|
+
declare class GatewayRouteTable {
|
|
1637
|
+
private readonly entries;
|
|
1638
|
+
/**
|
|
1639
|
+
* The consumer's `export const <name> = cachedEntrypoint(stratal)`, from
|
|
1640
|
+
* `ResponseCacheModule.forRoot({ gateway: { entrypoint } })`.
|
|
1641
|
+
*
|
|
1642
|
+
* `undefined` means no gateway is configured, which is also the condition
|
|
1643
|
+
* under which `bindRouteCache` refuses a non-empty `partitionBy` — so an
|
|
1644
|
+
* unconfigured table is always an empty one.
|
|
1645
|
+
*/
|
|
1646
|
+
entrypoint: string | undefined;
|
|
1647
|
+
/**
|
|
1648
|
+
* `gateway.keyBy` — the request headers whose values join the cache key.
|
|
1649
|
+
*
|
|
1650
|
+
* Carried here rather than resolved per request because the dispatch
|
|
1651
|
+
* middleware already memoises this table, so reading it costs a property
|
|
1652
|
+
* access on the hot path instead of a container lookup.
|
|
1653
|
+
*/
|
|
1654
|
+
keyBy: readonly string[];
|
|
1655
|
+
/** Set by `RouteRegistrationService.configure()`, before any request. */
|
|
1656
|
+
configure(entrypoint: string | undefined, keyBy?: readonly string[]): void;
|
|
1657
|
+
/** True when no route in this app declares a partition. */
|
|
1658
|
+
get isEmpty(): boolean;
|
|
1659
|
+
/** Number of recorded routes. Test/diagnostic affordance. */
|
|
1660
|
+
get size(): number;
|
|
1661
|
+
/**
|
|
1662
|
+
* Record one registered route.
|
|
1663
|
+
*
|
|
1664
|
+
* `method` is the Hono-registered method; `path` is the pattern the route
|
|
1665
|
+
* was registered under (already expanded for versioning and locale
|
|
1666
|
+
* variants, so each variant gets its own entry).
|
|
1667
|
+
*/
|
|
1668
|
+
record(method: string, path: string, partitionBy: string[]): void;
|
|
1669
|
+
/** The entry for a matched route pattern, or `undefined` to run inline. */
|
|
1670
|
+
lookup(method: string, path: string): GatewayRouteEntry | undefined;
|
|
1671
|
+
}
|
|
1672
|
+
//#endregion
|
|
1673
|
+
//#region src/response-cache/services/partition-resolver.service.d.ts
|
|
1674
|
+
interface PartitionResult {
|
|
1675
|
+
/** Values to place in `ctx.props`. Empty when nothing resolved. */
|
|
1676
|
+
props: Record<string, string>;
|
|
1677
|
+
/** False when any declared partition could not be resolved — do not cache. */
|
|
1678
|
+
resolved: boolean;
|
|
1679
|
+
}
|
|
1680
|
+
/**
|
|
1681
|
+
* Resolves the named partitions a route declared into `ctx.props` values.
|
|
1682
|
+
*
|
|
1683
|
+
* `ctx.props` is part of the Workers Caching cache key and, per Cloudflare,
|
|
1684
|
+
* "cannot be bypassed" — so this is what keeps one caller's cached response
|
|
1685
|
+
* from reaching another.
|
|
1686
|
+
*/
|
|
1687
|
+
declare class PartitionResolverService {
|
|
1688
|
+
private readonly options;
|
|
1689
|
+
private readonly logger;
|
|
1690
|
+
constructor(options: ResponseCacheModuleOptions, logger: LoggerService);
|
|
1691
|
+
/** Throw at boot if a route names a partition with no registered resolver. */
|
|
1692
|
+
assertKnown(names: string[], where: string): void;
|
|
1693
|
+
/**
|
|
1694
|
+
* Partition names seen so far, split by whether they have ever resolved.
|
|
1695
|
+
*
|
|
1696
|
+
* A resolver that fails is ordinary traffic — an anonymous visitor to a
|
|
1697
|
+
* per-user route — so the per-request signal stays at `debug`. But a
|
|
1698
|
+
* partition that has *never* resolved is a configuration mistake, not
|
|
1699
|
+
* traffic: the usual cause is `partitions: { user: (ctx) => ctx.user().id }`
|
|
1700
|
+
* configured without `primers: AUTH_GATEWAY_PRIMERS`, so `ctx.user()` throws
|
|
1701
|
+
* on every request and the route is silently never cached. Warned once per
|
|
1702
|
+
* name, so that diagnosis is available without making normal misses noisy.
|
|
1703
|
+
*/
|
|
1704
|
+
private readonly warnedUnresolved;
|
|
1705
|
+
private readonly everResolved;
|
|
1706
|
+
private noteUnresolved;
|
|
1707
|
+
resolve(ctx: RouterContext, names: string[]): Promise<PartitionResult>;
|
|
1708
|
+
}
|
|
1709
|
+
//#endregion
|
|
1710
|
+
//#region src/response-cache/services/response-cache.service.d.ts
|
|
1711
|
+
declare class ResponseCacheService {
|
|
1712
|
+
private readonly logger;
|
|
1713
|
+
constructor(logger: LoggerService);
|
|
1714
|
+
/** Render a `@PurgesCache` declaration against this request's scopes. */
|
|
1715
|
+
buildPurgeSpec(options: PurgesCacheOptions, scopes: TagScopes): PurgeSpec;
|
|
1716
|
+
/**
|
|
1717
|
+
* Issue a purge and wait for it.
|
|
1718
|
+
*
|
|
1719
|
+
* Deliberately not deferred through `waitUntil`: a client that re-reads
|
|
1720
|
+
* immediately after its own write must not be served the pre-write response.
|
|
1721
|
+
*
|
|
1722
|
+
* @throws {CachePurgeError} The mutation has already committed at this point,
|
|
1723
|
+
* so failing loudly is the lesser evil against a cache that is silently
|
|
1724
|
+
* inconsistent with the database.
|
|
1725
|
+
*/
|
|
1726
|
+
purge(spec: PurgeSpec, cache: WorkersCache): Promise<void>;
|
|
1727
|
+
}
|
|
1728
|
+
//#endregion
|
|
1053
1729
|
//#region src/router/services/versioning.service.d.ts
|
|
1054
1730
|
/**
|
|
1055
1731
|
* Resolves version prefixes for route paths.
|
|
@@ -1110,9 +1786,13 @@ interface RegisteredRoute {
|
|
|
1110
1786
|
* and expands versioned/locale paths via injected services.
|
|
1111
1787
|
*/
|
|
1112
1788
|
type RouteRegistrationInput = Omit<RegisteredRoute, 'paramNames' | 'domainParamNames' | 'path' | 'localePaths' | 'isLocaleVariant'> & {
|
|
1113
|
-
/** Base path before versioning/locale expansion */
|
|
1114
|
-
|
|
1115
|
-
|
|
1789
|
+
/** Base path before versioning/locale expansion */
|
|
1790
|
+
basePath: string;
|
|
1791
|
+
/** Version from controller/router config (used by VersioningService). Accepts VERSION_NEUTRAL symbol. */
|
|
1792
|
+
version?: string | string[] | typeof VERSION_NEUTRAL;
|
|
1793
|
+
/** Pre-computed param names (optional, auto-extracted if omitted) */
|
|
1794
|
+
paramNames?: string[];
|
|
1795
|
+
/** Pre-computed domain param names (optional, auto-extracted if omitted) */
|
|
1116
1796
|
domainParamNames?: string[];
|
|
1117
1797
|
};
|
|
1118
1798
|
/**
|
|
@@ -1170,7 +1850,7 @@ interface ResolvedRouterConfig {
|
|
|
1170
1850
|
middleware: Constructor<Middleware>[];
|
|
1171
1851
|
version?: string | string[];
|
|
1172
1852
|
hideFromDocs?: boolean;
|
|
1173
|
-
params?:
|
|
1853
|
+
params?: ZodObject<any>;
|
|
1174
1854
|
}
|
|
1175
1855
|
/**
|
|
1176
1856
|
* Internal resolver that computes the effective Router config for each controller.
|
|
@@ -1210,6 +1890,68 @@ declare class RouterResolver {
|
|
|
1210
1890
|
private concatNames;
|
|
1211
1891
|
}
|
|
1212
1892
|
//#endregion
|
|
1893
|
+
//#region src/router/route-metadata.d.ts
|
|
1894
|
+
/** A single response declaration for a route, keyed by status code. */
|
|
1895
|
+
interface RouteResponseMeta {
|
|
1896
|
+
status: number;
|
|
1897
|
+
/** Absent for empty responses (e.g. 204); present for typed JSON responses. */
|
|
1898
|
+
schema?: ZodType;
|
|
1899
|
+
contentType: string;
|
|
1900
|
+
description: string;
|
|
1901
|
+
}
|
|
1902
|
+
/**
|
|
1903
|
+
* Schema + documentation metadata for one registered route. Collected at
|
|
1904
|
+
* registration time and consumed lazily by the OpenAPI generator. Holds Zod
|
|
1905
|
+
* schema *instances* (never imports `zod` itself) so a route with no schemas
|
|
1906
|
+
* contributes none and pulls in no validation code.
|
|
1907
|
+
*/
|
|
1908
|
+
interface RouteSchemaMeta {
|
|
1909
|
+
method: Exclude<HttpMethod, 'all'>;
|
|
1910
|
+
/** Clean OpenAPI path with `{param}` placeholders and regex constraints stripped. */
|
|
1911
|
+
path: string;
|
|
1912
|
+
/** Hidden routes are still registered (for access control) but excluded from the doc. */
|
|
1913
|
+
hidden: boolean;
|
|
1914
|
+
tags: string[];
|
|
1915
|
+
security: SecuritySchemeRecord[];
|
|
1916
|
+
summary?: string;
|
|
1917
|
+
description?: string;
|
|
1918
|
+
request: {
|
|
1919
|
+
params?: ZodType;
|
|
1920
|
+
query?: ZodType;
|
|
1921
|
+
body?: {
|
|
1922
|
+
schema: ZodType;
|
|
1923
|
+
contentType: string;
|
|
1924
|
+
};
|
|
1925
|
+
};
|
|
1926
|
+
responses: RouteResponseMeta[];
|
|
1927
|
+
/**
|
|
1928
|
+
* Localized variant: the `locale` path segment to document as an enum. The
|
|
1929
|
+
* value set is carried as plain strings so the generator emits the enum
|
|
1930
|
+
* without constructing a Zod schema on the hot path.
|
|
1931
|
+
*/
|
|
1932
|
+
localeParam?: {
|
|
1933
|
+
name: string;
|
|
1934
|
+
values: string[];
|
|
1935
|
+
};
|
|
1936
|
+
/**
|
|
1937
|
+
* Visibility group labels for this route, resolved from the controller's and
|
|
1938
|
+
* route's `groups` options. Absent when none are declared.
|
|
1939
|
+
*/
|
|
1940
|
+
groups?: string[];
|
|
1941
|
+
/** Extensible metadata bag for downstream packages. */
|
|
1942
|
+
meta?: Record<string, unknown>;
|
|
1943
|
+
}
|
|
1944
|
+
/**
|
|
1945
|
+
* Stratal-owned registry of route schema metadata. Replaces writes to
|
|
1946
|
+
* `@hono/zod-openapi`'s internal `openAPIRegistry`: route registration pushes
|
|
1947
|
+
* entries here, and the OpenAPI generator reads them on demand.
|
|
1948
|
+
*/
|
|
1949
|
+
declare class RouteMetadataRegistry {
|
|
1950
|
+
private readonly entries;
|
|
1951
|
+
add(entry: RouteSchemaMeta): void;
|
|
1952
|
+
all(): readonly RouteSchemaMeta[];
|
|
1953
|
+
}
|
|
1954
|
+
//#endregion
|
|
1213
1955
|
//#region src/router/services/route-registration.service.d.ts
|
|
1214
1956
|
/**
|
|
1215
1957
|
* Route registration service
|
|
@@ -1233,9 +1975,60 @@ declare class RouteRegistrationService {
|
|
|
1233
1975
|
private localePathService;
|
|
1234
1976
|
private app;
|
|
1235
1977
|
private moduleRegistry;
|
|
1978
|
+
private metadataRegistry;
|
|
1979
|
+
private cacheability?;
|
|
1980
|
+
private responseCache?;
|
|
1981
|
+
private responseCacheOptions?;
|
|
1982
|
+
private gatewayRouteTable?;
|
|
1983
|
+
private partitionResolver?;
|
|
1236
1984
|
private controllerClasses;
|
|
1237
1985
|
private upgradeWebSocketFn;
|
|
1238
|
-
|
|
1986
|
+
private cacheableRouteCount;
|
|
1987
|
+
/**
|
|
1988
|
+
* Whether Workers Caching is usable, answered once per entrypoint.
|
|
1989
|
+
*
|
|
1990
|
+
* Keyed on whether the request arrived through the gateway, because that is
|
|
1991
|
+
* the scope the answer actually has: a gateway topology runs two entrypoints
|
|
1992
|
+
* — `cache.enabled` false on the gateway, true on the cached one — over a
|
|
1993
|
+
* single isolate and therefore a single instance of this service. A verdict
|
|
1994
|
+
* reached on one says nothing about the other, so holding one for the
|
|
1995
|
+
* isolate lets whichever entrypoint happens to serve the first request
|
|
1996
|
+
* decide for both, and a `cache.enabled` that is false *by design* on the
|
|
1997
|
+
* gateway reads as the app being misconfigured.
|
|
1998
|
+
*
|
|
1999
|
+
* Memoized rather than recomputed because `cache.enabled` is a static
|
|
2000
|
+
* Wrangler setting: within one entrypoint the answer cannot change.
|
|
2001
|
+
*/
|
|
2002
|
+
private cachingAvailability;
|
|
2003
|
+
constructor(logger: LoggerService, registry: RouteRegistry, routerResolver: RouterResolver | null, localePathService: LocalePathService, app: HonoApp, moduleRegistry: ModuleRegistry, metadataRegistry: RouteMetadataRegistry, cacheability?: CacheabilityService | undefined, responseCache?: ResponseCacheService | undefined, responseCacheOptions?: ResponseCacheModuleOptions | undefined, gatewayRouteTable?: GatewayRouteTable | undefined, partitionResolver?: PartitionResolverService | undefined);
|
|
2004
|
+
/**
|
|
2005
|
+
* The cached entrypoint named by `forRoot({ gateway: { entrypoint } })`, or
|
|
2006
|
+
* `undefined` when no gateway is configured.
|
|
2007
|
+
*
|
|
2008
|
+
* A `Promise` (the `forRootAsync` trap) reads as "no gateway" here rather
|
|
2009
|
+
* than throwing: `responseCacheDefaults()` raises that as its own boot error
|
|
2010
|
+
* with a message about the real problem, and it is called first on every
|
|
2011
|
+
* path that consults this.
|
|
2012
|
+
*/
|
|
2013
|
+
private gatewayEntrypoint;
|
|
2014
|
+
/** `gateway.keyBy`, read under the same `forRootAsync` caveat as the entrypoint. */
|
|
2015
|
+
private gatewayKeyBy;
|
|
2016
|
+
/**
|
|
2017
|
+
* `ResponseCacheModule.forRoot({ defaults })`, resolved once at
|
|
2018
|
+
* construction (constructor injection is memoized on this singleton
|
|
2019
|
+
* instance) and falling back to `{}` when the module was never imported —
|
|
2020
|
+
* mirrors `OpenAPIConfigStore.getBaseConfig()`.
|
|
2021
|
+
*
|
|
2022
|
+
* `forRootAsync({ useFactory })` is a trap here: `ModuleRegistry` registers
|
|
2023
|
+
* the factory verbatim (`registerFactory`), and `Container.resolve()` never
|
|
2024
|
+
* awaits a factory's return value — so an async `useFactory` resolves this
|
|
2025
|
+
* token to a **Promise**, not the options object. Left unchecked, `?.defaults`
|
|
2026
|
+
* on a Promise is `undefined`, silently falling back to `{}` — including
|
|
2027
|
+
* silently dropping a `partitionBy` the author thought was enforced, the
|
|
2028
|
+
* exact per-user data leak this feature exists to prevent. Detected and
|
|
2029
|
+
* thrown here, once, at boot, rather than trusted per route.
|
|
2030
|
+
*/
|
|
2031
|
+
private responseCacheDefaults;
|
|
1239
2032
|
/**
|
|
1240
2033
|
* Configure router with controllers and global middleware.
|
|
1241
2034
|
* Resolves controllers from ModuleRegistry and global middleware from RouterResolver.
|
|
@@ -1295,14 +2088,20 @@ declare class RouteRegistrationService {
|
|
|
1295
2088
|
*/
|
|
1296
2089
|
private mergeMetadata;
|
|
1297
2090
|
/**
|
|
1298
|
-
*
|
|
1299
|
-
*
|
|
1300
|
-
*
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
2091
|
+
* Resolve a route's request body into its schema + content type, normalizing
|
|
2092
|
+
* the bare-schema and `{ schema, contentType }` forms. Returns `undefined`
|
|
2093
|
+
* when no body is declared. Shared by validator construction and metadata.
|
|
2094
|
+
*/
|
|
2095
|
+
private resolveBody;
|
|
2096
|
+
/**
|
|
2097
|
+
* Build the schema metadata entry for a route. Consumed lazily by the OpenAPI
|
|
2098
|
+
* generator — common error responses are added there, not here, so
|
|
2099
|
+
* `common.schemas` (and the schemas it references) never reach the routing
|
|
2100
|
+
* path. The `locale` path param of a localized route is recorded as plain
|
|
2101
|
+
* metadata (enforced by the route pattern, read via `getLocale()`), so no zod
|
|
2102
|
+
* enum is constructed at registration.
|
|
1304
2103
|
*/
|
|
1305
|
-
private
|
|
2104
|
+
private buildRouteMetadata;
|
|
1306
2105
|
/**
|
|
1307
2106
|
* Check if a body definition is a RouteBodyObject (has schema key) vs bare ZodType
|
|
1308
2107
|
*/
|
|
@@ -1326,6 +2125,140 @@ declare class RouteRegistrationService {
|
|
|
1326
2125
|
* This ensures each request gets a fresh controller with request-scoped context
|
|
1327
2126
|
*/
|
|
1328
2127
|
private createControllerHandler;
|
|
2128
|
+
/**
|
|
2129
|
+
* Apply this route's `@Cacheable`/`@PurgesCache` decision, if it has one.
|
|
2130
|
+
*
|
|
2131
|
+
* Deliberately does **not** stamp `no-store` for the "nothing to do" case
|
|
2132
|
+
* (`!cacheBinding`, or `cacheBinding.cacheable` absent) — the outermost
|
|
2133
|
+
* `createNoStoreFallbackMiddleware` (registered in `HonoApp`) catches every
|
|
2134
|
+
* response that reaches Hono without a `Cache-Control`, this one included,
|
|
2135
|
+
* so every response still gets an explicit decision without every call
|
|
2136
|
+
* site needing to know that. This function only needs to handle the
|
|
2137
|
+
* positive cases: computing `@Cacheable` headers, and firing `@PurgesCache`.
|
|
2138
|
+
*
|
|
2139
|
+
* `@PurgesCache` fires independently of `@Cacheable` — the common case is
|
|
2140
|
+
* a mutation route (create/update/destroy) that isn't itself cacheable but
|
|
2141
|
+
* must invalidate a GET route's cached entries on success. Gating the
|
|
2142
|
+
* purge on `cacheBinding.cacheable` would silently skip that purge.
|
|
2143
|
+
*
|
|
2144
|
+
* **Headers stamped here are not the last word.** This runs *inside* the
|
|
2145
|
+
* Hono route handler, so any outbound middleware — anything doing work
|
|
2146
|
+
* after its own `await next()` — sees the response afterwards and can
|
|
2147
|
+
* overwrite `Vary`, `Cache-Control`, or `Set-Cookie` with a plain
|
|
2148
|
+
* `c.header(name, value)`, which replaces rather than appends. That is
|
|
2149
|
+
* silent: the route still looks cached, but (for `Vary`) every variant
|
|
2150
|
+
* collapses onto one entry. Middleware that contributes to any of these
|
|
2151
|
+
* three headers must **merge** with what is already on the response, never
|
|
2152
|
+
* set it outright — see `InertiaMiddleware`'s `Vary: X-Inertia` handling
|
|
2153
|
+
* for the shape that fix takes.
|
|
2154
|
+
*/
|
|
2155
|
+
private applyCacheDecision;
|
|
2156
|
+
/**
|
|
2157
|
+
* Whether this request's declared partitions are actually in the cache key.
|
|
2158
|
+
*
|
|
2159
|
+
* Reaching a controller **inline while running as the gateway** is, for a
|
|
2160
|
+
* route with a non-empty `partitionBy`, proof that they are not: the
|
|
2161
|
+
* dispatch middleware forwards every such `GET`/`HEAD` whose partitions it
|
|
2162
|
+
* could resolve, so the only way one arrives here is that it declined —
|
|
2163
|
+
* an unresolved resolver, a resolver that threw, or a primer that
|
|
2164
|
+
* short-circuited. Reporting `true` there would stamp
|
|
2165
|
+
* `Cache-Control: public, max-age=…` on a response the author declared
|
|
2166
|
+
* per-caller, and while the gateway's own Workers cache is disabled, that
|
|
2167
|
+
* header still travels to the client and to every intermediary between
|
|
2168
|
+
* them. One user's dashboard in a shared proxy cache is exactly the leak
|
|
2169
|
+
* `partitionBy` exists to prevent, so it fails closed instead.
|
|
2170
|
+
*
|
|
2171
|
+
* Inside the cached entrypoint the partitions normally *are* in the key,
|
|
2172
|
+
* because the gateway chose `ctx.props` before forwarding. But that is the
|
|
2173
|
+
* caller's claim, not a fact, and this entrypoint is reachable by anything
|
|
2174
|
+
* that can name it — another Worker's service binding, a misrouted export,
|
|
2175
|
+
* or our own gateway having selected an overlapping route's binding. So it
|
|
2176
|
+
* is checked rather than trusted: every partition this route declared must
|
|
2177
|
+
* be present in `ctx.props`. A caller that supplies none, or only some, gets
|
|
2178
|
+
* `private, no-store` instead of a shared entry.
|
|
2179
|
+
*
|
|
2180
|
+
* With **no execution context at all** — `hono.fetch(request, env)`, which
|
|
2181
|
+
* `quarry api` and `mcp serve` both do — there is no way to tell those cases
|
|
2182
|
+
* apart, so unknown means uncacheable.
|
|
2183
|
+
*
|
|
2184
|
+
* An app with no gateway configured can never have a non-empty
|
|
2185
|
+
* `partitionBy` (`bindRouteCache` rejects it at boot), so this returns
|
|
2186
|
+
* `true` on the first line for every app that doesn't use the feature.
|
|
2187
|
+
*/
|
|
2188
|
+
private partitionsResolved;
|
|
2189
|
+
/**
|
|
2190
|
+
* `c.executionCtx` is a Hono getter that throws when the context wasn't
|
|
2191
|
+
* constructed with one (e.g. a bare `app.fetch(request)` in a unit test) —
|
|
2192
|
+
* unlike a plain optional property, there's no way to read it without a
|
|
2193
|
+
* `try`/`catch` when it might be absent. `cache` itself is optional even
|
|
2194
|
+
* when `executionCtx` exists: Wrangler only attaches it when `cache.enabled
|
|
2195
|
+
* = true` is configured.
|
|
2196
|
+
*
|
|
2197
|
+
* The cast is necessary despite `@cloudflare/workers-types` declaring
|
|
2198
|
+
* `cache?: CacheContext` on the *runtime* `ExecutionContext` — Hono's
|
|
2199
|
+
* `Context.executionCtx` getter is typed against Hono's own narrower
|
|
2200
|
+
* `ExecutionContext` interface (`waitUntil`/`passThroughOnException`/`props`
|
|
2201
|
+
* only), not Cloudflare's, so TypeScript doesn't know `.cache` exists on
|
|
2202
|
+
* what it returns even though the object handed to it at runtime does.
|
|
2203
|
+
*
|
|
2204
|
+
* **In gateway mode with a gateway configured, this is deliberately not
|
|
2205
|
+
* `ctx.cache`.** Only partitioned `GET`/`HEAD` requests are forwarded to the
|
|
2206
|
+
* cached entrypoint; every mutation — and so every `@PurgesCache` — runs
|
|
2207
|
+
* inline in the gateway, whose Wrangler config sets `cache: { enabled:
|
|
2208
|
+
* false }`. Purges are scoped to the entrypoint that issues them, so an
|
|
2209
|
+
* inline purge would either find no `ctx.cache` at all (and 500 a mutation
|
|
2210
|
+
* that already committed) or, if caching were left on for the gateway, purge
|
|
2211
|
+
* the gateway's own cache — reporting success while invalidating nothing and
|
|
2212
|
+
* leaving every cached read stale until its TTL ran out. Routing it over RPC
|
|
2213
|
+
* to the cached entrypoint puts the purge where the entries actually live.
|
|
2214
|
+
*/
|
|
2215
|
+
/**
|
|
2216
|
+
* Whether the entrypoint serving this request can cache.
|
|
2217
|
+
*
|
|
2218
|
+
* Reported once per entrypoint, at error level, because an app that declares
|
|
2219
|
+
* `@Cacheable` and gets no caching is misconfigured somewhere — in a
|
|
2220
|
+
* deployment that omitted `cache.enabled`, or in a local runtime that has no
|
|
2221
|
+
* Workers Caching to offer. Either way its routes then serve uncached and
|
|
2222
|
+
* say so in the response, rather than advertising a freshness nothing keeps.
|
|
2223
|
+
*/
|
|
2224
|
+
private cachingAvailable;
|
|
2225
|
+
/**
|
|
2226
|
+
* Whether this request came in through the gateway rather than the cached
|
|
2227
|
+
* entrypoint. Both run the same Hono app over the same isolate, and only the
|
|
2228
|
+
* execution context tells them apart.
|
|
2229
|
+
*/
|
|
2230
|
+
private isGatewayRequest;
|
|
2231
|
+
private executionCache;
|
|
2232
|
+
/**
|
|
2233
|
+
* Values available to `{scope.path}` cache tag templates for this request.
|
|
2234
|
+
*
|
|
2235
|
+
* `body` is deliberately `undefined`: the parsed request body isn't cheaply
|
|
2236
|
+
* available at this point in the pipeline, and re-parsing it here would add
|
|
2237
|
+
* a second parse to every request on the hot path just to support a rarely
|
|
2238
|
+
* used tag scope. A `{body.*}` tag can therefore never resolve — but that's
|
|
2239
|
+
* never discovered here, or at request time at all: `bindRouteCache`
|
|
2240
|
+
* rejects any `@Cacheable`/`@PurgesCache` tag using the `body` scope at
|
|
2241
|
+
* route registration, so a route that reaches this method never has one to
|
|
2242
|
+
* render. (It was never true that both services "fail closed" on this —
|
|
2243
|
+
* `CacheabilityService` does, but `@PurgesCache`'s `renderTags` call has no
|
|
2244
|
+
* surrounding try/catch, so letting a `{body.*}` tag through would 500 the
|
|
2245
|
+
* request after its mutation already committed, which is exactly why the
|
|
2246
|
+
* boot-time check exists.)
|
|
2247
|
+
*/
|
|
2248
|
+
private buildTagScopes;
|
|
2249
|
+
/**
|
|
2250
|
+
* The partition values Cloudflare is keying this response on.
|
|
2251
|
+
*
|
|
2252
|
+
* Read from `ctx.props`, which is where the gateway put them and what the
|
|
2253
|
+
* cache key is actually built from — so a `{partition.x}` tag names the same
|
|
2254
|
+
* value the entry is stored under, on every variant of it.
|
|
2255
|
+
*
|
|
2256
|
+
* Empty when there is no execution context, or when running as the gateway
|
|
2257
|
+
* (whose own responses are never stored). A tag naming a partition that is
|
|
2258
|
+
* absent then fails to render, which fails the response closed — the right
|
|
2259
|
+
* outcome, since the partition it claimed to be keyed by is not in the key.
|
|
2260
|
+
*/
|
|
2261
|
+
private partitionValues;
|
|
1329
2262
|
/**
|
|
1330
2263
|
* Extract the Zod schema from a RouteResponse definition.
|
|
1331
2264
|
* Returns null for non-JSON content types or when no response is defined.
|
|
@@ -1393,6 +2326,13 @@ declare const ROUTER_TOKENS: {
|
|
|
1393
2326
|
* URL generation service — route URLs, signed URLs, current/previous URL access
|
|
1394
2327
|
*/
|
|
1395
2328
|
readonly Uri: symbol;
|
|
2329
|
+
/**
|
|
2330
|
+
* Token for RouteMetadataRegistry (singleton)
|
|
2331
|
+
* Holds per-route schema metadata collected at registration so the OpenAPI
|
|
2332
|
+
* document can be generated lazily (on request) without coupling routing to
|
|
2333
|
+
* `@hono/zod-openapi`.
|
|
2334
|
+
*/
|
|
2335
|
+
readonly RouteMetadataRegistry: symbol;
|
|
1396
2336
|
};
|
|
1397
2337
|
//#endregion
|
|
1398
2338
|
//#region src/router/route-url.d.ts
|
|
@@ -1588,16 +2528,16 @@ declare function createMiddlewareChain(classes: Constructor<Middleware>[]): Midd
|
|
|
1588
2528
|
* This is the core controller decorator that handles:
|
|
1589
2529
|
* - Transient scope registration (request-scoped)
|
|
1590
2530
|
* - Route metadata storage
|
|
1591
|
-
* - Controller options (tags, security schemes, hideFromDocs)
|
|
2531
|
+
* - Controller options (tags, security schemes, groups, hideFromDocs)
|
|
1592
2532
|
*
|
|
1593
2533
|
* @param route - Base route for this controller (e.g., '/api/v1/users')
|
|
1594
|
-
* @param options - Optional configuration (tags, security schemes, hideFromDocs)
|
|
2534
|
+
* @param options - Optional configuration (tags, security schemes, groups, hideFromDocs)
|
|
1595
2535
|
*
|
|
1596
2536
|
* @example
|
|
1597
2537
|
* ```typescript
|
|
1598
2538
|
* import { Controller } from 'stratal/router'
|
|
1599
2539
|
*
|
|
1600
|
-
* @Controller('/api/v1/users', { tags: ['Users'] })
|
|
2540
|
+
* @Controller('/api/v1/users', { tags: ['Users'], groups: ['admin'] })
|
|
1601
2541
|
* export class UsersController implements IController {
|
|
1602
2542
|
* // All routes accessible
|
|
1603
2543
|
* }
|
|
@@ -1625,6 +2565,13 @@ declare function getControllerOptions(target: object): ControllerOptions | undef
|
|
|
1625
2565
|
* @returns Version string, array, VERSION_NEUTRAL symbol, or undefined if not set
|
|
1626
2566
|
*/
|
|
1627
2567
|
declare function getControllerVersion(target: object): ControllerOptions['version'];
|
|
2568
|
+
/**
|
|
2569
|
+
* Get the visibility groups from controller class metadata
|
|
2570
|
+
*
|
|
2571
|
+
* @param target - Controller class or instance
|
|
2572
|
+
* @returns The controller's `groups`, or undefined if none were declared
|
|
2573
|
+
*/
|
|
2574
|
+
declare function getControllerGroups(target: object): ControllerOptions['groups'];
|
|
1628
2575
|
//#endregion
|
|
1629
2576
|
//#region src/router/decorators/http-method.decorator.d.ts
|
|
1630
2577
|
/**
|
|
@@ -1635,12 +2582,14 @@ declare function getControllerVersion(target: object): ControllerOptions['versio
|
|
|
1635
2582
|
*
|
|
1636
2583
|
* @example
|
|
1637
2584
|
* ```typescript
|
|
1638
|
-
*
|
|
2585
|
+
* import { array, object, uuid } from 'zod/mini'
|
|
2586
|
+
*
|
|
2587
|
+
* @Controller('/users', { version: '1' })
|
|
1639
2588
|
* class UsersController {
|
|
1640
|
-
* @Get('/', { response:
|
|
2589
|
+
* @Get('/', { response: array(userSchema), summary: 'List users' })
|
|
1641
2590
|
* async list(ctx: RouterContext) { ... }
|
|
1642
2591
|
*
|
|
1643
|
-
* @Get('/:id', { params:
|
|
2592
|
+
* @Get('/:id', { params: object({ id: uuid() }), response: userSchema })
|
|
1644
2593
|
* async getUser(ctx: RouterContext) { ... }
|
|
1645
2594
|
* }
|
|
1646
2595
|
* ```
|
|
@@ -1737,7 +2686,7 @@ declare const All: (path: string, config?: RouteConfig) => (target: object, prop
|
|
|
1737
2686
|
*
|
|
1738
2687
|
* @Route({
|
|
1739
2688
|
* query: paginationSchema,
|
|
1740
|
-
* response:
|
|
2689
|
+
* response: array(noteSchema) // 200 auto-derived from 'index' method
|
|
1741
2690
|
* })
|
|
1742
2691
|
* async index(ctx: RouterContext): Promise<Response> {
|
|
1743
2692
|
* // GET /api/v1/notes (auto-derived)
|
|
@@ -1747,7 +2696,7 @@ declare const All: (path: string, config?: RouteConfig) => (target: object, prop
|
|
|
1747
2696
|
* }
|
|
1748
2697
|
*
|
|
1749
2698
|
* @Route({
|
|
1750
|
-
* params:
|
|
2699
|
+
* params: object({ id: uuid() }),
|
|
1751
2700
|
* response: {
|
|
1752
2701
|
* schema: noteSchema,
|
|
1753
2702
|
* description: 'Note details'
|
|
@@ -1787,119 +2736,103 @@ declare function getRouteDecoratedMethods(ControllerClass: new (...args: unknown
|
|
|
1787
2736
|
/**
|
|
1788
2737
|
* Common OpenAPI Schemas
|
|
1789
2738
|
*
|
|
1790
|
-
* Reusable schema definitions for common API patterns
|
|
1791
|
-
*
|
|
1792
|
-
*
|
|
1793
|
-
*
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
*
|
|
1797
|
-
*
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
*/
|
|
1840
|
-
declare const uuidParamSchema: z.ZodObject<{
|
|
1841
|
-
id: z.ZodString;
|
|
1842
|
-
}, z.core.$strip>;
|
|
1843
|
-
/**
|
|
1844
|
-
* Success message response schema
|
|
1845
|
-
* Used for operations that don't return data (e.g., DELETE)
|
|
1846
|
-
*/
|
|
1847
|
-
declare const successMessageSchema: z.ZodObject<{
|
|
1848
|
-
message: z.ZodString;
|
|
1849
|
-
data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1850
|
-
}, z.core.$strip>;
|
|
1851
|
-
/**
|
|
1852
|
-
* Common HTTP status error schemas
|
|
1853
|
-
* Pre-configured for standard error responses
|
|
1854
|
-
*/
|
|
2739
|
+
* Reusable schema definitions for common API patterns (error responses,
|
|
2740
|
+
* pagination, common parameters). Consumed by the lazy OpenAPI generator —
|
|
2741
|
+
* never imported on the routing hot path — so these never reach a running
|
|
2742
|
+
* worker unless the OpenAPI document is actually requested.
|
|
2743
|
+
*
|
|
2744
|
+
* Metadata (descriptions, component ids) is attached via the shared registry
|
|
2745
|
+
* helpers; the generator reads `id` to emit shared `components.schemas` entries
|
|
2746
|
+
* and `description` for field docs.
|
|
2747
|
+
*/
|
|
2748
|
+
/**
|
|
2749
|
+
* Generic error response schema. Matches the ErrorResponse shape produced by
|
|
2750
|
+
* ExceptionHandler. Used for all error responses (4xx, 5xx).
|
|
2751
|
+
*/
|
|
2752
|
+
declare const errorResponseSchema: import("zod/mini").ZodMiniObject<{
|
|
2753
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2754
|
+
timestamp: iso.ZodMiniISODateTime;
|
|
2755
|
+
stack: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2756
|
+
}, import("zod/v4/core").$strip>;
|
|
2757
|
+
/** Validation error response schema (400 Bad Request). Shares the ErrorResponse shape. */
|
|
2758
|
+
declare const validationErrorResponseSchema: import("zod/mini").ZodMiniObject<{
|
|
2759
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2760
|
+
timestamp: iso.ZodMiniISODateTime;
|
|
2761
|
+
stack: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2762
|
+
}, import("zod/v4/core").$strip>;
|
|
2763
|
+
/** Pagination query parameters for list endpoints. */
|
|
2764
|
+
declare const paginationQuerySchema: import("zod/mini").ZodMiniObject<{
|
|
2765
|
+
page: import("zod/mini").ZodMiniDefault<import("zod/mini").ZodMiniNumber<unknown>>;
|
|
2766
|
+
limit: import("zod/mini").ZodMiniDefault<import("zod/mini").ZodMiniNumber<unknown>>;
|
|
2767
|
+
}, import("zod/v4/core").$strip>;
|
|
2768
|
+
/** Generic wrapper for paginated list responses. */
|
|
2769
|
+
declare const paginatedResponseSchema: <T extends ZodType>(itemSchema: T) => import("zod/mini").ZodMiniObject<{
|
|
2770
|
+
data: import("zod/mini").ZodMiniArray<T>;
|
|
2771
|
+
pagination: import("zod/mini").ZodMiniObject<{
|
|
2772
|
+
page: import("zod/mini").ZodMiniNumber<number>;
|
|
2773
|
+
limit: import("zod/mini").ZodMiniNumber<number>;
|
|
2774
|
+
total: import("zod/mini").ZodMiniNumber<number>;
|
|
2775
|
+
totalPages: import("zod/mini").ZodMiniNumber<number>;
|
|
2776
|
+
}, import("zod/v4/core").$strip>;
|
|
2777
|
+
}, import("zod/v4/core").$strip>;
|
|
2778
|
+
/** UUID parameter schema for `:id` parameters in RESTful routes. */
|
|
2779
|
+
declare const uuidParamSchema: import("zod/mini").ZodMiniObject<{
|
|
2780
|
+
id: import("zod/mini").ZodMiniUUID;
|
|
2781
|
+
}, import("zod/v4/core").$strip>;
|
|
2782
|
+
/** Success message response for operations that don't return data (e.g. DELETE). */
|
|
2783
|
+
declare const successMessageSchema: import("zod/mini").ZodMiniObject<{
|
|
2784
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2785
|
+
data: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniRecord<import("zod/mini").ZodMiniString<string>, import("zod/mini").ZodMiniUnknown>>;
|
|
2786
|
+
}, import("zod/v4/core").$strip>;
|
|
2787
|
+
/** Pre-configured error response schemas keyed by standard HTTP status. */
|
|
1855
2788
|
declare const commonErrorSchemas: {
|
|
1856
2789
|
readonly 400: {
|
|
1857
|
-
readonly schema:
|
|
1858
|
-
message:
|
|
1859
|
-
timestamp:
|
|
1860
|
-
stack:
|
|
1861
|
-
},
|
|
1862
|
-
readonly description:
|
|
2790
|
+
readonly schema: import("zod/mini").ZodMiniObject<{
|
|
2791
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2792
|
+
timestamp: iso.ZodMiniISODateTime;
|
|
2793
|
+
stack: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2794
|
+
}, import("zod/v4/core").$strip>;
|
|
2795
|
+
readonly description: 'Validation error';
|
|
1863
2796
|
};
|
|
1864
2797
|
readonly 401: {
|
|
1865
|
-
readonly schema:
|
|
1866
|
-
message:
|
|
1867
|
-
timestamp:
|
|
1868
|
-
stack:
|
|
1869
|
-
},
|
|
1870
|
-
readonly description:
|
|
2798
|
+
readonly schema: import("zod/mini").ZodMiniObject<{
|
|
2799
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2800
|
+
timestamp: iso.ZodMiniISODateTime;
|
|
2801
|
+
stack: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2802
|
+
}, import("zod/v4/core").$strip>;
|
|
2803
|
+
readonly description: 'Unauthorized';
|
|
1871
2804
|
};
|
|
1872
2805
|
readonly 403: {
|
|
1873
|
-
readonly schema:
|
|
1874
|
-
message:
|
|
1875
|
-
timestamp:
|
|
1876
|
-
stack:
|
|
1877
|
-
},
|
|
1878
|
-
readonly description:
|
|
2806
|
+
readonly schema: import("zod/mini").ZodMiniObject<{
|
|
2807
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2808
|
+
timestamp: iso.ZodMiniISODateTime;
|
|
2809
|
+
stack: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2810
|
+
}, import("zod/v4/core").$strip>;
|
|
2811
|
+
readonly description: 'Forbidden';
|
|
1879
2812
|
};
|
|
1880
2813
|
readonly 404: {
|
|
1881
|
-
readonly schema:
|
|
1882
|
-
message:
|
|
1883
|
-
timestamp:
|
|
1884
|
-
stack:
|
|
1885
|
-
},
|
|
1886
|
-
readonly description:
|
|
2814
|
+
readonly schema: import("zod/mini").ZodMiniObject<{
|
|
2815
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2816
|
+
timestamp: iso.ZodMiniISODateTime;
|
|
2817
|
+
stack: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2818
|
+
}, import("zod/v4/core").$strip>;
|
|
2819
|
+
readonly description: 'Not found';
|
|
1887
2820
|
};
|
|
1888
2821
|
readonly 409: {
|
|
1889
|
-
readonly schema:
|
|
1890
|
-
message:
|
|
1891
|
-
timestamp:
|
|
1892
|
-
stack:
|
|
1893
|
-
},
|
|
1894
|
-
readonly description:
|
|
2822
|
+
readonly schema: import("zod/mini").ZodMiniObject<{
|
|
2823
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2824
|
+
timestamp: iso.ZodMiniISODateTime;
|
|
2825
|
+
stack: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2826
|
+
}, import("zod/v4/core").$strip>;
|
|
2827
|
+
readonly description: 'Conflict';
|
|
1895
2828
|
};
|
|
1896
2829
|
readonly 500: {
|
|
1897
|
-
readonly schema:
|
|
1898
|
-
message:
|
|
1899
|
-
timestamp:
|
|
1900
|
-
stack:
|
|
1901
|
-
},
|
|
1902
|
-
readonly description:
|
|
2830
|
+
readonly schema: import("zod/mini").ZodMiniObject<{
|
|
2831
|
+
message: import("zod/mini").ZodMiniString<string>;
|
|
2832
|
+
timestamp: iso.ZodMiniISODateTime;
|
|
2833
|
+
stack: import("zod/mini").ZodMiniOptional<import("zod/mini").ZodMiniString<string>>;
|
|
2834
|
+
}, import("zod/v4/core").$strip>;
|
|
2835
|
+
readonly description: 'Internal server error';
|
|
1903
2836
|
};
|
|
1904
2837
|
};
|
|
1905
2838
|
//#endregion
|
|
@@ -1941,6 +2874,16 @@ declare function parseDomainPattern(pattern: string): {
|
|
|
1941
2874
|
*/
|
|
1942
2875
|
declare function createDomainMiddleware(pattern: string): MiddlewareHandler<RouterEnv>;
|
|
1943
2876
|
//#endregion
|
|
2877
|
+
//#region src/router/nested-dispatch.d.ts
|
|
2878
|
+
/**
|
|
2879
|
+
* Mark a request as dispatched into this app from inside another request.
|
|
2880
|
+
*
|
|
2881
|
+
* Returns the same object it was given, so it can be used inline.
|
|
2882
|
+
*/
|
|
2883
|
+
declare function markNestedDispatch(request: Request): Request;
|
|
2884
|
+
/** Whether this request was marked by {@link markNestedDispatch}. */
|
|
2885
|
+
declare function isNestedDispatch(request: Request): boolean;
|
|
2886
|
+
//#endregion
|
|
1944
2887
|
//#region src/router/middleware/verify-signature.middleware.d.ts
|
|
1945
2888
|
/**
|
|
1946
2889
|
* Middleware that verifies signed URLs.
|
|
@@ -1963,7 +2906,7 @@ declare function createDomainMiddleware(pattern: string): MiddlewareHandler<Rout
|
|
|
1963
2906
|
* ```
|
|
1964
2907
|
*/
|
|
1965
2908
|
declare class VerifySignatureMiddleware implements Middleware {
|
|
1966
|
-
handle(ctx: RouterContext, next: Next
|
|
2909
|
+
handle(ctx: RouterContext, next: Next): Promise<void>;
|
|
1967
2910
|
}
|
|
1968
2911
|
//#endregion
|
|
1969
2912
|
//#region src/router/signed-url.d.ts
|
|
@@ -2020,7 +2963,8 @@ declare class SchemaValidationError extends HttpException {
|
|
|
2020
2963
|
message: string;
|
|
2021
2964
|
code: string;
|
|
2022
2965
|
}[];
|
|
2023
|
-
constructor(zodError: ZodError);
|
|
2966
|
+
constructor(zodError: $ZodError);
|
|
2967
|
+
reportContext(): Record<string, unknown>;
|
|
2024
2968
|
}
|
|
2025
2969
|
//#endregion
|
|
2026
2970
|
//#region src/router/errors/index.d.ts
|
|
@@ -2045,7 +2989,7 @@ declare class ResponseValidationError extends HttpException {
|
|
|
2045
2989
|
message: string;
|
|
2046
2990
|
code: string;
|
|
2047
2991
|
}[];
|
|
2048
|
-
constructor(zodError: ZodError);
|
|
2992
|
+
constructor(zodError: $ZodError);
|
|
2049
2993
|
}
|
|
2050
2994
|
//#endregion
|
|
2051
2995
|
//#region src/application.d.ts
|
|
@@ -2078,13 +3022,19 @@ declare class Application {
|
|
|
2078
3022
|
private cronInitPromise;
|
|
2079
3023
|
readonly env: StratalEnv;
|
|
2080
3024
|
private readonly appConfig;
|
|
2081
|
-
constructor({
|
|
2082
|
-
env,
|
|
2083
|
-
ctx,
|
|
2084
|
-
...config
|
|
2085
|
-
}: ApplicationOptions);
|
|
3025
|
+
constructor({ env, ctx, ...config }: ApplicationOptions);
|
|
2086
3026
|
get container(): Container;
|
|
3027
|
+
/** The application's logger (the singleton {@link LoggerService}). */
|
|
3028
|
+
get logger(): LoggerService;
|
|
2087
3029
|
ensureHono(): Promise<HonoApp>;
|
|
3030
|
+
/**
|
|
3031
|
+
* Whether the app registers any HTTP controllers. Cheap (reads the already-
|
|
3032
|
+
* populated registry; no routing built) and only meaningful after
|
|
3033
|
+
* {@link initialize}. The worker entry uses it to decide whether to pre-warm
|
|
3034
|
+
* the routing stack at boot — queue/scheduled-only apps return false and never
|
|
3035
|
+
* build routes they won't serve.
|
|
3036
|
+
*/
|
|
3037
|
+
hasHttpRoutes(): boolean;
|
|
2088
3038
|
get config(): ApplicationConfig;
|
|
2089
3039
|
initialize(): Promise<void>;
|
|
2090
3040
|
private initializeInternal;
|
|
@@ -2355,7 +3305,10 @@ declare class RouterContext<T extends RouterEnv = RouterEnv> extends Macroable {
|
|
|
2355
3305
|
*/
|
|
2356
3306
|
getContainer(): Container;
|
|
2357
3307
|
/**
|
|
2358
|
-
*
|
|
3308
|
+
* Override the locale for the current request (e.g. force a specific locale
|
|
3309
|
+
* for this response). Request-scoped only — it does not persist. Persistence
|
|
3310
|
+
* is the detection layer's job: cookie-strategy paths auto-persist the
|
|
3311
|
+
* `locale` cookie (scoped via the config's `cookieOptions`).
|
|
2359
3312
|
*
|
|
2360
3313
|
* @param locale - Locale code (e.g., 'en', 'fr')
|
|
2361
3314
|
*/
|
|
@@ -2719,7 +3672,7 @@ interface ClassMetadata {
|
|
|
2719
3672
|
token?: InjectionToken;
|
|
2720
3673
|
}
|
|
2721
3674
|
declare const Singleton: <T>(token?: InjectionToken<T>) => <TFunction extends abstract new (...args: never[]) => unknown>(target: TFunction) => TFunction;
|
|
2722
|
-
declare const Request: <T>(token?: InjectionToken<T>) => <TFunction extends abstract new (...args: never[]) => unknown>(target: TFunction) => TFunction;
|
|
3675
|
+
declare const Request$1: <T>(token?: InjectionToken<T>) => <TFunction extends abstract new (...args: never[]) => unknown>(target: TFunction) => TFunction;
|
|
2723
3676
|
declare const Transient: <T>(token?: InjectionToken<T>) => <TFunction extends abstract new (...args: never[]) => unknown>(target: TFunction) => TFunction;
|
|
2724
3677
|
declare function getClassMetadata(target: object): ClassMetadata | undefined;
|
|
2725
3678
|
//#endregion
|
|
@@ -3053,5 +4006,5 @@ declare class AuthError extends ApplicationError {
|
|
|
3053
4006
|
constructor(message?: string, cause?: unknown);
|
|
3054
4007
|
}
|
|
3055
4008
|
//#endregion
|
|
3056
|
-
export { Container as $,
|
|
3057
|
-
//# sourceMappingURL=index-
|
|
4009
|
+
export { Container as $, ModuleClass as $n, RouteMatcher as $r, extractDomainParamNames as $t, Environment as A, DetectionStrategy as An, RouterVariables as Ar, parseDomainPattern as At, getMetadata as B, IController as Bn, SECURITY_SCHEMES as Br, getRouteMetadata as Bt, ExceptionContext as C, Router as Cn, RouteBody as Cr, SignedUrlOptions as Ct, createCronExceptionContext as D, ResolvedPath as Dn, RouteResponse as Dr, isNestedDispatch as Dt, createCliExceptionContext as E, LocalePathService as En, RouteMetadata as Er, VerifySignatureMiddleware as Et, runWithContainer as F, ResolvedI18nOptions as Fn, TrailingSlashOptions as Fr, successMessageSchema as Ft, getClassMetadata as G, ParsedOption as Gn, PartitionResolver as Gr, Post as Gt, Request$1 as H, CommandInternals as Hn, CacheableOptions as Hr, Delete as Ht, Disposable as I, buildDetectorOptions as In, VersioningOptions as Ir, uuidParamSchema as It, INJECT_PARAM_METADATA_KEY as J, AsyncModuleOptions as Jn, ResponseCacheGatewayOptions as Jr, getControllerGroups as Jt, getInjectionTokens as K, ParsedSignature as Kn, PurgesCacheOptions as Kr, Put as Kt, disposeInstance as L, resolveDetectionForPath as Ln, HTTP_METHODS as Lr, validationErrorResponseSchema as Lt, isErrorResponse as M, LOCALE_COOKIE as Mn, TrailingSlashConfig as Mr, errorResponseSchema as Mt, containerStorage as N, LanguageDetectionOptions as Nn, TrailingSlashExclude as Nr, paginatedResponseSchema as Nt, createHttpExceptionContext as O, DetectionConfig as On, RouteResponseObject as Or, markNestedDispatch as Ot, getContainer as P, ResolvedDetection as Pn, TrailingSlashMode as Pr, paginationQuerySchema as Pt, ContainerError as Q, FactoryProvider as Qn, CurrentRoute as Qr, createMiddlewareChain as Qt, isDisposable as R, resolveI18nOptions as Rn, ROUTER_CONTEXT_KEYS as Rr, Route as Rt, CronExceptionContext as S, RouteConfigurable as Sn, LocaleUrlConfig as Sr, RouterError as St, QueueExceptionContext as T, LocaleUrlService as Tn, RouteConfig as Tr, verifySignedUrl as Tt, Singleton as U, CommandResult as Un, CachedEntrypointName as Ur, Get as Ut, hasMetadata as V, CommandInput as Vn, VERSION_NEUTRAL as Vr, All as Vt, Transient as W, ParsedArgument as Wn, EntrypointNameFrom as Wr, Patch as Wt, ParamInjection as X, DynamicModule as Xn, Middleware as Xr, getControllerRoute as Xt, InjectParam as Y, ClassProvider as Yn, ResponseCacheModuleOptions as Yr, getControllerOptions as Yt, getMethodInjections as Z, ExistingProvider as Zn, Next as Zr, getControllerVersion as Zt, RenderableCallback as _, RouteRegistry as _n, WorkersCache as _r, StreamingApi$1 as _t, ContainerNotInitializedError as a, StratalRouteMap as ai, applyTrailingSlash as an, Provider as ar, PredicateContainer as at, RespondCallback as b, GatewayRouteTable as bn, ExplicitRouteMetadata as br, SchemaValidationError as bt, HTTP_STATUS_MESSAGES as c, DI_TOKENS as ci, applyLocalePrefix as cn, ExtensionDecorator as cr, SignedUriOptions as ct, DefaultExceptionHandler as d, route as dn, WhenOptions as dr, buildRouteUrl as dt, RouteName as ei, extractParamNames as en, ModuleContext as er, ContainerOptions as et, ExceptionHandler as f, ROUTER_TOKENS as fn, LazyToken as fr, Application as ft, LogSeverity as g, RouteRegistrationInput as gn, StratalExecutionContext as gr, SSEStreamingApi$1 as gt, ErrorPageCallback as h, RegisteredRoute as hn, PurgeSpec as hr, SSEMessage as ht, StratalNotInitializedError as i, SerializedRoutes as ii, toOpenAPIPath as in, OnShutdown as ir, ConditionalBindingUse as it, ErrorResponse as j, I18nModuleOptions as jn, SecurityScheme as jr, commonErrorSchemas as jt, createQueueExceptionContext as k, DetectionResolver as kn, RouterEnv as kr, createDomainMiddleware as kt, HttpException as l, ApplicationError as li, shouldPrefixLocale as ln, InjectionToken as lr, Uri as lt, ContextCallback as m, RouteSchemaMeta as mn, lazy as mr, ApplicationOptions as mt, DatabaseError as n, RoutePrefixes as ni, getPathSpecificityScore as nn, OnException as nr, ConditionalBindingBuilderImpl as nt, isApplicationError as o, CONTAINER_TOKEN as oi, isTrailingSlashExcluded as on, ValueProvider as or, ContextQueryResult as ot, ApplicationErrorConstructor as p, RouteRegistrationService as pn, isLazyToken as pr, ApplicationConfig as pt, inject as q, Quarry as qn, ResolvedCacheable as qr, Controller as qt, StratalSupersededError as r, SerializedRoute as ri, sortRoutesBySpecificity as rn, OnInitialize as rr, ConditionalBindingGive as rt, InternalError as s, DIToken as si, resolveTrailingSlash as sn, ContainerLike as sr, RouterContext as st, AuthError as t, RouteParams as ti, generateConventionRouteName as tn, ModuleOptions as tr, ConditionalBindingBuilder as tt, abort as u, stripLocalePrefix as un, Scope as ur, UriOptions as ut, Reportable as v, VersioningService as vn, ControllerOptions as vr, InvalidSignatureError as vt, HttpExceptionContext as w, RouterGroupConfig as wn, RouteBodyObject as wr, signUrl as wt, CliExceptionContext as x, ModuleRegistry as xn, LocalePathConfig as xr, RouteNotFoundError as xt, ReportableCallback as y, GatewayRouteEntry as yn, ConventionRouteMetadata as yr, ResponseValidationError as yt, defineMetadata as z, HonoApp as zn, ROUTE_METADATA_KEYS as zr, getRouteDecoratedMethods as zt };
|
|
4010
|
+
//# sourceMappingURL=index-B2WtEagR.d.mts.map
|