@geekmidas/constructs 10.0.0-alpha.2 → 10.0.0-alpha.21
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/README.md +46 -3
- package/dist/{Construct-Ct8nalEi.d.mts → Construct-DTqYvkPG.d.cts} +11 -13
- package/dist/Construct-DTqYvkPG.d.cts.map +1 -0
- package/dist/{Construct-BD5neF7w.mjs → Construct-Detz65RA.mjs} +31 -29
- package/dist/Construct-Detz65RA.mjs.map +1 -0
- package/dist/{Construct-C0ijr2qp.d.cts → Construct-pVadmURD.d.mts} +10 -12
- package/dist/Construct-pVadmURD.d.mts.map +1 -0
- package/dist/{Construct-CyS3RpTL.cjs → Construct-yG9Sw-5p.cjs} +51 -43
- package/dist/Construct-yG9Sw-5p.cjs.map +1 -0
- package/dist/{Cron-ByxdOfpE.d.mts → Cron-AYpQq725.d.mts} +13 -6
- package/dist/Cron-AYpQq725.d.mts.map +1 -0
- package/dist/{Cron-Wqh464aO.d.cts → Cron-Bdcg9OAL.d.cts} +12 -5
- package/dist/Cron-Bdcg9OAL.d.cts.map +1 -0
- package/dist/{CronBuilder-BL0AP6fs.d.mts → CronBuilder-DR21m9h2.d.cts} +7 -10
- package/dist/CronBuilder-DR21m9h2.d.cts.map +1 -0
- package/dist/{CronBuilder-BqpEzMPQ.d.cts → CronBuilder-DeBnPVIT.d.mts} +7 -10
- package/dist/CronBuilder-DeBnPVIT.d.mts.map +1 -0
- package/dist/{CronBuilder-BmABazzH.mjs → CronBuilder-vkjuo1UP.mjs} +23 -15
- package/dist/CronBuilder-vkjuo1UP.mjs.map +1 -0
- package/dist/{CronBuilder-CkXPJiGO.cjs → CronBuilder-zdTdaT-e.cjs} +33 -25
- package/dist/CronBuilder-zdTdaT-e.cjs.map +1 -0
- package/dist/{Endpoint-2Wg7T7Cq.d.mts → Endpoint-BxkRWQ8G.d.mts} +63 -84
- package/dist/Endpoint-BxkRWQ8G.d.mts.map +1 -0
- package/dist/{Endpoint-BiaaMEn_.cjs → Endpoint-CtiPUpRX.cjs} +145 -131
- package/dist/Endpoint-CtiPUpRX.cjs.map +1 -0
- package/dist/{Endpoint-VIOpSo0S.mjs → Endpoint-DCr5tlbJ.mjs} +117 -109
- package/dist/Endpoint-DCr5tlbJ.mjs.map +1 -0
- package/dist/{Endpoint-CH9Fn1AD.d.cts → Endpoint-DbYQJgb-.d.cts} +61 -82
- package/dist/Endpoint-DbYQJgb-.d.cts.map +1 -0
- package/dist/{EndpointFactory-DTTCkGEL.mjs → EndpointFactory-Bs8pu-yY.mjs} +20 -29
- package/dist/EndpointFactory-Bs8pu-yY.mjs.map +1 -0
- package/dist/{index-BxHDdy6a.d.mts → EndpointFactory-DE6nKtFZ.d.cts} +12 -92
- package/dist/EndpointFactory-DE6nKtFZ.d.cts.map +1 -0
- package/dist/{index-V2nksZIJ.d.cts → EndpointFactory-T06kTFHg.d.mts} +12 -92
- package/dist/EndpointFactory-T06kTFHg.d.mts.map +1 -0
- package/dist/{EndpointFactory-ChxLZllA.cjs → EndpointFactory-vE2C1NG1.cjs} +57 -66
- package/dist/EndpointFactory-vE2C1NG1.cjs.map +1 -0
- package/dist/{HonoEndpointAdaptor-NKQQQbBY.mjs → HonoEndpointAdaptor-Be6UdK0r.mjs} +40 -47
- package/dist/{HonoEndpointAdaptor-D233Jvpk.cjs.map → HonoEndpointAdaptor-Be6UdK0r.mjs.map} +1 -1
- package/dist/{HonoEndpointAdaptor-D233Jvpk.cjs → HonoEndpointAdaptor-C9aivwKl.cjs} +48 -52
- package/dist/HonoEndpointAdaptor-C9aivwKl.cjs.map +1 -0
- package/dist/{Queue-D7ZuwBhy.d.cts → Queue-Bhzi2WQC.d.cts} +8 -9
- package/dist/Queue-Bhzi2WQC.d.cts.map +1 -0
- package/dist/{Queue-gVGfi2Yk.d.mts → Queue-BoUA-e83.d.mts} +9 -10
- package/dist/Queue-BoUA-e83.d.mts.map +1 -0
- package/dist/{Subscriber-2mEi0ImH.d.cts → Subscriber-CIO3pwji.d.mts} +7 -8
- package/dist/Subscriber-CIO3pwji.d.mts.map +1 -0
- package/dist/{Subscriber-xTJ9ayPN.d.mts → Subscriber-DQCaiOXF.d.cts} +7 -8
- package/dist/Subscriber-DQCaiOXF.d.cts.map +1 -0
- package/dist/{SubscriberBuilder-BjkbeT9l.mjs → SubscriberBuilder-B4YRTBng.mjs} +16 -10
- package/dist/SubscriberBuilder-B4YRTBng.mjs.map +1 -0
- package/dist/{SubscriberBuilder-4OPehf2R.cjs → SubscriberBuilder-C2bCOuPT.cjs} +28 -23
- package/dist/SubscriberBuilder-C2bCOuPT.cjs.map +1 -0
- package/dist/{SubscriberBuilder-Dptmo-1A.d.mts → SubscriberBuilder-ChX5v948.d.cts} +8 -11
- package/dist/SubscriberBuilder-ChX5v948.d.cts.map +1 -0
- package/dist/{SubscriberBuilder-waNhzjSM.d.cts → SubscriberBuilder-Dbiaskfi.d.mts} +8 -11
- package/dist/SubscriberBuilder-Dbiaskfi.d.mts.map +1 -0
- package/dist/{Topic-19QeHBIR.d.cts → Topic-D6blllEn.d.cts} +5 -7
- package/dist/Topic-D6blllEn.d.cts.map +1 -0
- package/dist/{Topic-DuFeqkBh.d.mts → Topic-DVvheJ_-.d.mts} +6 -8
- package/dist/Topic-DVvheJ_-.d.mts.map +1 -0
- package/dist/adaptors/aws.cjs +87 -106
- package/dist/adaptors/aws.cjs.map +1 -1
- package/dist/adaptors/aws.d.cts +14 -27
- package/dist/adaptors/aws.d.cts.map +1 -1
- package/dist/adaptors/aws.d.mts +16 -29
- package/dist/adaptors/aws.d.mts.map +1 -1
- package/dist/adaptors/aws.mjs +60 -81
- package/dist/adaptors/aws.mjs.map +1 -1
- package/dist/adaptors/hono.cjs +3 -10
- package/dist/adaptors/hono.d.cts +5 -13
- package/dist/adaptors/hono.d.cts.map +1 -1
- package/dist/adaptors/hono.d.mts +7 -15
- package/dist/adaptors/hono.d.mts.map +1 -1
- package/dist/adaptors/hono.mjs +2 -10
- package/dist/adaptors/testing.cjs +271 -82
- package/dist/adaptors/testing.cjs.map +1 -1
- package/dist/adaptors/testing.d.cts +62 -33
- package/dist/adaptors/testing.d.cts.map +1 -1
- package/dist/adaptors/testing.d.mts +63 -34
- package/dist/adaptors/testing.d.mts.map +1 -1
- package/dist/adaptors/testing.mjs +249 -63
- package/dist/adaptors/testing.mjs.map +1 -1
- package/dist/auth-BlO8MUkR.d.cts +123 -0
- package/dist/auth-BlO8MUkR.d.cts.map +1 -0
- package/dist/auth-CHWIdcQO.d.mts +123 -0
- package/dist/auth-CHWIdcQO.d.mts.map +1 -0
- package/dist/auth.cjs +41 -16
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +2 -108
- package/dist/auth.d.mts +2 -108
- package/dist/auth.mjs +32 -8
- package/dist/auth.mjs.map +1 -1
- package/dist/{cache-BrRz3fEB.d.mts → cache-AgQUMma6.d.mts} +3 -6
- package/dist/cache-AgQUMma6.d.mts.map +1 -0
- package/dist/{cache-BtZY_tHe.d.cts → cache-obq0fOIM.d.cts} +3 -6
- package/dist/cache-obq0fOIM.d.cts.map +1 -0
- package/dist/cache.cjs +68 -2
- package/dist/cache.cjs.map +1 -0
- package/dist/cache.d.cts +1 -2
- package/dist/cache.d.mts +1 -2
- package/dist/cache.mjs +67 -2
- package/dist/cache.mjs.map +1 -0
- package/dist/{clone-DblgEZZa.mjs → clone-EKNovYHu.mjs} +3 -3
- package/dist/clone-EKNovYHu.mjs.map +1 -0
- package/dist/{clone-Dy0cR2SZ.cjs → clone-UGJpvQnL.cjs} +7 -8
- package/dist/clone-UGJpvQnL.cjs.map +1 -0
- package/dist/{construct-interface-g5GM5pwR.d.mts → construct-interface-Clz7_BwB.d.mts} +15 -6
- package/dist/construct-interface-Clz7_BwB.d.mts.map +1 -0
- package/dist/{construct-interface-D9d4Gm4p.d.cts → construct-interface-DIaTNKax.d.cts} +15 -6
- package/dist/construct-interface-DIaTNKax.d.cts.map +1 -0
- package/dist/construct-interface.cjs +87 -7
- package/dist/construct-interface.cjs.map +1 -0
- package/dist/construct-interface.d.cts +2 -2
- package/dist/construct-interface.d.mts +2 -2
- package/dist/construct-interface.mjs +81 -2
- package/dist/construct-interface.mjs.map +1 -0
- package/dist/credential.cjs +43 -9
- package/dist/credential.cjs.map +1 -1
- package/dist/credential.d.cts +5 -8
- package/dist/credential.d.cts.map +1 -1
- package/dist/credential.d.mts +5 -8
- package/dist/credential.d.mts.map +1 -1
- package/dist/credential.mjs +36 -2
- package/dist/credential.mjs.map +1 -1
- package/dist/crons/index.cjs +68 -10
- package/dist/crons/index.cjs.map +1 -1
- package/dist/crons/index.d.cts +32 -14
- package/dist/crons/index.d.cts.map +1 -1
- package/dist/crons/index.d.mts +32 -14
- package/dist/crons/index.d.mts.map +1 -1
- package/dist/crons/index.mjs +66 -10
- package/dist/crons/index.mjs.map +1 -1
- package/dist/database/kysely.cjs +28 -14
- package/dist/database/kysely.cjs.map +1 -1
- package/dist/database/kysely.d.cts +2 -152
- package/dist/database/kysely.d.mts +2 -152
- package/dist/database/kysely.mjs +16 -4
- package/dist/database/kysely.mjs.map +1 -1
- package/dist/email.cjs +25 -12
- package/dist/email.cjs.map +1 -1
- package/dist/email.d.cts +3 -7
- package/dist/email.d.cts.map +1 -1
- package/dist/email.d.mts +3 -7
- package/dist/email.d.mts.map +1 -1
- package/dist/email.mjs +16 -3
- package/dist/email.mjs.map +1 -1
- package/dist/endpoints/index.cjs +7 -10
- package/dist/endpoints/index.d.cts +60 -7
- package/dist/endpoints/index.d.cts.map +1 -0
- package/dist/endpoints/index.d.mts +60 -7
- package/dist/endpoints/index.d.mts.map +1 -0
- package/dist/endpoints/index.mjs +5 -10
- package/dist/file-server.cjs +42 -10
- package/dist/file-server.cjs.map +1 -1
- package/dist/file-server.d.cts +6 -10
- package/dist/file-server.d.cts.map +1 -1
- package/dist/file-server.d.mts +6 -10
- package/dist/file-server.d.mts.map +1 -1
- package/dist/file-server.mjs +34 -2
- package/dist/file-server.mjs.map +1 -1
- package/dist/functions/index.cjs +2 -6
- package/dist/functions/index.d.cts +2 -4
- package/dist/functions/index.d.mts +2 -4
- package/dist/functions/index.mjs +2 -6
- package/dist/{functions-Bd3TPxid.cjs → functions-VnOTEp74.cjs} +309 -264
- package/dist/functions-VnOTEp74.cjs.map +1 -0
- package/dist/{functions-Cxbo-pEd.mjs → functions-faoJOUmr.mjs} +282 -234
- package/dist/functions-faoJOUmr.mjs.map +1 -0
- package/dist/index-CeEtxDmK.d.cts +79 -0
- package/dist/index-CeEtxDmK.d.cts.map +1 -0
- package/dist/index-CeEtxDmK.d.mts +79 -0
- package/dist/index-CeEtxDmK.d.mts.map +1 -0
- package/dist/{index-JSf9xNIJ.d.cts → index-DU3Twmwh.d.mts} +19 -24
- package/dist/index-DU3Twmwh.d.mts.map +1 -0
- package/dist/index-fnpjXiA-.d.mts +26 -0
- package/dist/index-fnpjXiA-.d.mts.map +1 -0
- package/dist/{index-CubPzHd9.d.mts → index-nBQT1tAh.d.cts} +19 -24
- package/dist/index-nBQT1tAh.d.cts.map +1 -0
- package/dist/index-tE_119SX.d.cts +26 -0
- package/dist/index-tE_119SX.d.cts.map +1 -0
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +4 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +2 -3
- package/dist/kysely-CXi49zc2.d.cts +150 -0
- package/dist/kysely-CXi49zc2.d.cts.map +1 -0
- package/dist/kysely-D3-G5b0j.d.mts +150 -0
- package/dist/kysely-D3-G5b0j.d.mts.map +1 -0
- package/dist/{lazyAccessors-BoJN3SMd.mjs → lazyAccessors-BHtcqgz2.mjs} +22 -25
- package/dist/lazyAccessors-BHtcqgz2.mjs.map +1 -0
- package/dist/{lazyAccessors-e3j2oE2m.cjs → lazyAccessors-Dx9NLwJZ.cjs} +72 -76
- package/dist/lazyAccessors-Dx9NLwJZ.cjs.map +1 -0
- package/dist/object-storage.cjs +18 -10
- package/dist/object-storage.cjs.map +1 -1
- package/dist/object-storage.d.cts +3 -7
- package/dist/object-storage.d.cts.map +1 -1
- package/dist/object-storage.d.mts +3 -7
- package/dist/object-storage.d.mts.map +1 -1
- package/dist/object-storage.mjs +11 -3
- package/dist/object-storage.mjs.map +1 -1
- package/dist/{processAudits-Dmts9H_b.mjs → processAudits-BpRlPQMW.mjs} +16 -19
- package/dist/processAudits-BpRlPQMW.mjs.map +1 -0
- package/dist/{processAudits-CGqttuXm.cjs → processAudits-D_2W5x8k.cjs} +26 -30
- package/dist/processAudits-D_2W5x8k.cjs.map +1 -0
- package/dist/queue/index.cjs +25 -21
- package/dist/queue/index.cjs.map +1 -1
- package/dist/queue/index.d.cts +8 -15
- package/dist/queue/index.d.cts.map +1 -1
- package/dist/queue/index.d.mts +8 -15
- package/dist/queue/index.d.mts.map +1 -1
- package/dist/queue/index.mjs +15 -11
- package/dist/queue/index.mjs.map +1 -1
- package/dist/rest-api.cjs +88 -62
- package/dist/rest-api.cjs.map +1 -1
- package/dist/rest-api.d.cts +62 -60
- package/dist/rest-api.d.cts.map +1 -1
- package/dist/rest-api.d.mts +62 -60
- package/dist/rest-api.d.mts.map +1 -1
- package/dist/rest-api.mjs +80 -54
- package/dist/rest-api.mjs.map +1 -1
- package/dist/{chunk-DWy1uDak.cjs → rolldown-runtime-y5ARvAq5.cjs} +14 -18
- package/dist/site.cjs +33 -9
- package/dist/site.cjs.map +1 -1
- package/dist/site.d.cts +11 -22
- package/dist/site.d.cts.map +1 -1
- package/dist/site.d.mts +11 -22
- package/dist/site.d.mts.map +1 -1
- package/dist/site.mjs +29 -5
- package/dist/site.mjs.map +1 -1
- package/dist/subscribers/index.cjs +2 -11
- package/dist/subscribers/index.d.cts +3 -14
- package/dist/subscribers/index.d.mts +3 -14
- package/dist/subscribers/index.mjs +2 -11
- package/dist/surfaceEnv-CNimK76p.cjs +56 -0
- package/dist/surfaceEnv-CNimK76p.cjs.map +1 -0
- package/dist/surfaceEnv-wMT5QzgZ.mjs +45 -0
- package/dist/surfaceEnv-wMT5QzgZ.mjs.map +1 -0
- package/dist/{telemetry-C3L0iS28.d.cts → telemetry-DGcFlVpB.d.cts} +2 -5
- package/dist/telemetry-DGcFlVpB.d.cts.map +1 -0
- package/dist/{telemetry-D7bVFLGi.d.mts → telemetry-DGcFlVpB.d.mts} +2 -5
- package/dist/telemetry-DGcFlVpB.d.mts.map +1 -0
- package/dist/topic/index.cjs +18 -20
- package/dist/topic/index.cjs.map +1 -1
- package/dist/topic/index.d.cts +3 -32
- package/dist/topic/index.d.mts +3 -32
- package/dist/topic/index.mjs +8 -10
- package/dist/topic/index.mjs.map +1 -1
- package/dist/{types-BlAkSuGI.d.cts → types-DMuSQeLL.d.cts} +3 -5
- package/dist/types-DMuSQeLL.d.cts.map +1 -0
- package/dist/{types-aKksMEWL.d.mts → types-DMuSQeLL.d.mts} +3 -5
- package/dist/types-DMuSQeLL.d.mts.map +1 -0
- package/dist/types.d.cts +1 -1
- package/dist/types.d.mts +1 -1
- package/dist/types.mjs +1 -0
- package/dist/worker.cjs +109 -35
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +87 -42
- package/dist/worker.d.cts.map +1 -1
- package/dist/worker.d.mts +87 -42
- package/dist/worker.d.mts.map +1 -1
- package/dist/worker.mjs +104 -30
- package/dist/worker.mjs.map +1 -1
- package/package.json +59 -55
- package/dist/Construct-BD5neF7w.mjs.map +0 -1
- package/dist/Construct-C0ijr2qp.d.cts.map +0 -1
- package/dist/Construct-Ct8nalEi.d.mts.map +0 -1
- package/dist/Construct-CyS3RpTL.cjs.map +0 -1
- package/dist/Cron-ByxdOfpE.d.mts.map +0 -1
- package/dist/Cron-Wqh464aO.d.cts.map +0 -1
- package/dist/CronBuilder-BL0AP6fs.d.mts.map +0 -1
- package/dist/CronBuilder-BmABazzH.mjs.map +0 -1
- package/dist/CronBuilder-BqpEzMPQ.d.cts.map +0 -1
- package/dist/CronBuilder-CkXPJiGO.cjs.map +0 -1
- package/dist/Endpoint-2Wg7T7Cq.d.mts.map +0 -1
- package/dist/Endpoint-BiaaMEn_.cjs.map +0 -1
- package/dist/Endpoint-CH9Fn1AD.d.cts.map +0 -1
- package/dist/Endpoint-VIOpSo0S.mjs.map +0 -1
- package/dist/EndpointFactory-ChxLZllA.cjs.map +0 -1
- package/dist/EndpointFactory-DTTCkGEL.mjs.map +0 -1
- package/dist/HonoEndpointAdaptor-NKQQQbBY.mjs.map +0 -1
- package/dist/Queue-D7ZuwBhy.d.cts.map +0 -1
- package/dist/Queue-gVGfi2Yk.d.mts.map +0 -1
- package/dist/Subscriber-2mEi0ImH.d.cts.map +0 -1
- package/dist/Subscriber-xTJ9ayPN.d.mts.map +0 -1
- package/dist/SubscriberBuilder-4OPehf2R.cjs.map +0 -1
- package/dist/SubscriberBuilder-BjkbeT9l.mjs.map +0 -1
- package/dist/SubscriberBuilder-Dptmo-1A.d.mts.map +0 -1
- package/dist/SubscriberBuilder-waNhzjSM.d.cts.map +0 -1
- package/dist/Topic-19QeHBIR.d.cts.map +0 -1
- package/dist/Topic-DuFeqkBh.d.mts.map +0 -1
- package/dist/auth.d.cts.map +0 -1
- package/dist/auth.d.mts.map +0 -1
- package/dist/cache-0ANvRQnD.mjs +0 -51
- package/dist/cache-0ANvRQnD.mjs.map +0 -1
- package/dist/cache-3WSvAulx.cjs +0 -57
- package/dist/cache-3WSvAulx.cjs.map +0 -1
- package/dist/cache-BrRz3fEB.d.mts.map +0 -1
- package/dist/cache-BtZY_tHe.d.cts.map +0 -1
- package/dist/clone-DblgEZZa.mjs.map +0 -1
- package/dist/clone-Dy0cR2SZ.cjs.map +0 -1
- package/dist/construct-interface-BfjcOD_E.cjs +0 -117
- package/dist/construct-interface-BfjcOD_E.cjs.map +0 -1
- package/dist/construct-interface-D9d4Gm4p.d.cts.map +0 -1
- package/dist/construct-interface-Z4CpS8tK.mjs +0 -81
- package/dist/construct-interface-Z4CpS8tK.mjs.map +0 -1
- package/dist/construct-interface-g5GM5pwR.d.mts.map +0 -1
- package/dist/database/kysely.d.cts.map +0 -1
- package/dist/database/kysely.d.mts.map +0 -1
- package/dist/functions-Bd3TPxid.cjs.map +0 -1
- package/dist/functions-Cxbo-pEd.mjs.map +0 -1
- package/dist/index-BxHDdy6a.d.mts.map +0 -1
- package/dist/index-CubPzHd9.d.mts.map +0 -1
- package/dist/index-JSf9xNIJ.d.cts.map +0 -1
- package/dist/index-V2nksZIJ.d.cts.map +0 -1
- package/dist/lazyAccessors-BoJN3SMd.mjs.map +0 -1
- package/dist/lazyAccessors-e3j2oE2m.cjs.map +0 -1
- package/dist/processAudits-CGqttuXm.cjs.map +0 -1
- package/dist/processAudits-Dmts9H_b.mjs.map +0 -1
- package/dist/subscribers/index.cjs.map +0 -1
- package/dist/subscribers/index.d.cts.map +0 -1
- package/dist/subscribers/index.d.mts.map +0 -1
- package/dist/subscribers/index.mjs.map +0 -1
- package/dist/surfaceEnv-BFXEms2f.cjs +0 -39
- package/dist/surfaceEnv-BFXEms2f.cjs.map +0 -1
- package/dist/surfaceEnv-C3Ktahea.mjs +0 -27
- package/dist/surfaceEnv-C3Ktahea.mjs.map +0 -1
- package/dist/telemetry-C3L0iS28.d.cts.map +0 -1
- package/dist/telemetry-D7bVFLGi.d.mts.map +0 -1
- package/dist/topic/index.d.cts.map +0 -1
- package/dist/topic/index.d.mts.map +0 -1
- package/dist/types-BlAkSuGI.d.cts.map +0 -1
- package/dist/types-aKksMEWL.d.mts.map +0 -1
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { n as ResponseBuilder, t as Endpoint } from "./Endpoint-DCr5tlbJ.mjs";
|
|
2
|
+
import { a as createHonoHeaders, i as createHonoCookies, l as publishConstructEvents } from "./lazyAccessors-BHtcqgz2.mjs";
|
|
3
|
+
import { n as executeWithAuditTransaction, t as createAuditContext } from "./processAudits-BpRlPQMW.mjs";
|
|
4
4
|
import { wrapError } from "@geekmidas/errors";
|
|
5
|
-
import { ServiceDiscovery, runWithRequestContext } from "@geekmidas/services";
|
|
6
|
-
import { withRlsContext } from "@geekmidas/db/rls";
|
|
7
|
-
import qs from "qs";
|
|
8
5
|
import { setCookie } from "hono/cookie";
|
|
6
|
+
import { withRlsContext } from "@geekmidas/db/rls";
|
|
9
7
|
import { checkRateLimit, getRateLimitHeaders } from "@geekmidas/rate-limit";
|
|
8
|
+
import { ServiceDiscovery, runWithRequestContext } from "@geekmidas/services";
|
|
10
9
|
import { Hono } from "hono";
|
|
11
10
|
import { logger } from "hono/logger";
|
|
12
11
|
import { timing } from "hono/timing";
|
|
13
12
|
import { validator } from "hono/validator";
|
|
14
13
|
import path from "node:path";
|
|
15
14
|
import fg from "fast-glob";
|
|
16
|
-
|
|
15
|
+
import qs from "qs";
|
|
17
16
|
//#region src/endpoints/helpers.ts
|
|
18
17
|
/**
|
|
19
18
|
* Discovers and imports all Endpoint instances from the specified route patterns.
|
|
@@ -47,8 +46,7 @@ async function getEndpointsFromRoutes(routes, cwd) {
|
|
|
47
46
|
const stream = fg.stream(routes, { cwd });
|
|
48
47
|
const endpoints = [];
|
|
49
48
|
for await (const f of stream) {
|
|
50
|
-
const
|
|
51
|
-
const route = await import(routePath);
|
|
49
|
+
const route = await import(path.resolve(cwd, f.toString()));
|
|
52
50
|
const handlers = Object.values(route).filter((value) => {
|
|
53
51
|
return Endpoint.isEndpoint(value);
|
|
54
52
|
});
|
|
@@ -56,7 +54,6 @@ async function getEndpointsFromRoutes(routes, cwd) {
|
|
|
56
54
|
}
|
|
57
55
|
return endpoints;
|
|
58
56
|
}
|
|
59
|
-
|
|
60
57
|
//#endregion
|
|
61
58
|
//#region src/endpoints/parseHonoQuery.ts
|
|
62
59
|
/**
|
|
@@ -70,7 +67,6 @@ function parseHonoQuery(c) {
|
|
|
70
67
|
const queryString = url.slice(queryIndex + 1);
|
|
71
68
|
return qs.parse(queryString);
|
|
72
69
|
}
|
|
73
|
-
|
|
74
70
|
//#endregion
|
|
75
71
|
//#region src/endpoints/HonoEndpointAdaptor.ts
|
|
76
72
|
/**
|
|
@@ -97,12 +93,13 @@ function analyzeEndpointFeatures(endpoint) {
|
|
|
97
93
|
};
|
|
98
94
|
}
|
|
99
95
|
var HonoEndpoint = class HonoEndpoint {
|
|
96
|
+
endpoint;
|
|
100
97
|
constructor(endpoint) {
|
|
101
98
|
this.endpoint = endpoint;
|
|
102
99
|
}
|
|
103
100
|
static isDev = process.env.NODE_ENV === "development";
|
|
104
101
|
static async validate(c, data, schema) {
|
|
105
|
-
if (!schema) return
|
|
102
|
+
if (!schema) return;
|
|
106
103
|
const parsed = await Endpoint.validate(schema, data);
|
|
107
104
|
if (parsed.issues) return c.json(parsed.issues, 422);
|
|
108
105
|
return parsed.value;
|
|
@@ -157,7 +154,7 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
157
154
|
const handler = async (c) => {
|
|
158
155
|
const startTime = Date.now();
|
|
159
156
|
const requestId = c.req.header("X-Request-ID") ?? crypto.randomUUID();
|
|
160
|
-
const logger
|
|
157
|
+
const logger = endpoint.logger.child({
|
|
161
158
|
requestId,
|
|
162
159
|
endpoint: endpoint.fullPath,
|
|
163
160
|
route: endpoint.route,
|
|
@@ -167,7 +164,7 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
167
164
|
});
|
|
168
165
|
c.header("X-Request-ID", requestId);
|
|
169
166
|
return runWithRequestContext({
|
|
170
|
-
logger
|
|
167
|
+
logger,
|
|
171
168
|
requestId,
|
|
172
169
|
startTime
|
|
173
170
|
}, async () => {
|
|
@@ -178,31 +175,30 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
178
175
|
const rawDb = features.hasDatabase ? await serviceDiscovery.register([endpoint.databaseService]).then((s) => s[endpoint.databaseService?.serviceName]) : void 0;
|
|
179
176
|
const session = await endpoint.getSession({
|
|
180
177
|
services,
|
|
181
|
-
logger
|
|
178
|
+
logger,
|
|
182
179
|
header,
|
|
183
180
|
cookie,
|
|
184
181
|
...rawDb !== void 0 && { db: rawDb }
|
|
185
182
|
});
|
|
186
|
-
|
|
183
|
+
if (!await endpoint.authorize({
|
|
187
184
|
header,
|
|
188
185
|
cookie,
|
|
189
186
|
services,
|
|
190
|
-
logger
|
|
187
|
+
logger,
|
|
191
188
|
session,
|
|
192
189
|
...rawDb !== void 0 && { db: rawDb },
|
|
193
190
|
body: features.hasBodyValidation ? c.req.valid("json") : void 0,
|
|
194
191
|
query: features.hasQueryValidation ? c.req.valid("query") : void 0,
|
|
195
192
|
params: features.hasParamValidation ? c.req.valid("param") : void 0
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
logger$1.warn("Forbidden access attempt");
|
|
193
|
+
})) {
|
|
194
|
+
logger.warn("Forbidden access attempt");
|
|
199
195
|
return c.json({ error: "Forbidden" }, 403);
|
|
200
196
|
}
|
|
201
197
|
if (features.hasRateLimit) {
|
|
202
198
|
const rateLimitInfo = await checkRateLimit(endpoint.rateLimit, {
|
|
203
199
|
header,
|
|
204
200
|
services,
|
|
205
|
-
logger
|
|
201
|
+
logger,
|
|
206
202
|
session,
|
|
207
203
|
path: c.req.path,
|
|
208
204
|
method: endpoint.method
|
|
@@ -210,29 +206,28 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
210
206
|
const rateLimitHeaders = getRateLimitHeaders(rateLimitInfo, endpoint.rateLimit);
|
|
211
207
|
for (const [key, value] of Object.entries(rateLimitHeaders)) if (value) c.header(key, value);
|
|
212
208
|
}
|
|
213
|
-
const auditContext = features.hasAudits ? await createAuditContext(endpoint, serviceDiscovery, logger
|
|
209
|
+
const auditContext = features.hasAudits ? await createAuditContext(endpoint, serviceDiscovery, logger, {
|
|
214
210
|
session,
|
|
215
211
|
header,
|
|
216
212
|
cookie,
|
|
217
213
|
services
|
|
218
214
|
}) : void 0;
|
|
219
215
|
const audits = features.hasAudits ? endpoint.audits : [];
|
|
220
|
-
if (features.hasAudits && !auditContext) logger
|
|
216
|
+
if (features.hasAudits && !auditContext) logger.warn("No auditor storage service available");
|
|
221
217
|
const rlsContext = features.hasRls && rawDb !== void 0 ? await endpoint.rlsConfig?.extractor({
|
|
222
218
|
services,
|
|
223
219
|
session,
|
|
224
220
|
header,
|
|
225
221
|
cookie,
|
|
226
|
-
logger
|
|
222
|
+
logger
|
|
227
223
|
}) : void 0;
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
const baseDb = sameDatabase ? auditor?.getTransaction?.() ?? rawDb : rawDb;
|
|
224
|
+
const { output, metadata } = await executeWithAuditTransaction(auditContext, async (auditor) => {
|
|
225
|
+
const baseDb = auditContext?.storage?.databaseServiceName && auditContext.storage.databaseServiceName === endpoint.databaseService?.serviceName ? auditor?.getTransaction?.() ?? rawDb : rawDb;
|
|
231
226
|
const executeHandler = async (db) => {
|
|
232
227
|
const responseBuilder = new ResponseBuilder();
|
|
233
228
|
const response = await endpoint.handler({
|
|
234
229
|
services,
|
|
235
|
-
logger
|
|
230
|
+
logger,
|
|
236
231
|
body: features.hasBodyValidation ? c.req.valid("json") : void 0,
|
|
237
232
|
query: features.hasQueryValidation ? c.req.valid("query") : void 0,
|
|
238
233
|
params: features.hasParamValidation ? c.req.valid("param") : void 0,
|
|
@@ -243,40 +238,38 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
243
238
|
db
|
|
244
239
|
}, responseBuilder);
|
|
245
240
|
let data = response;
|
|
246
|
-
let metadata
|
|
241
|
+
let metadata = responseBuilder.getMetadata();
|
|
247
242
|
if (Endpoint.hasMetadata(response)) {
|
|
248
243
|
data = response.data;
|
|
249
|
-
metadata
|
|
244
|
+
metadata = response.metadata;
|
|
250
245
|
}
|
|
251
|
-
const output$1 = endpoint.outputSchema ? await endpoint.parseOutput(data) : void 0;
|
|
252
246
|
return {
|
|
253
|
-
output:
|
|
254
|
-
metadata
|
|
247
|
+
output: endpoint.outputSchema ? await endpoint.parseOutput(data) : void 0,
|
|
248
|
+
metadata,
|
|
255
249
|
responseBuilder
|
|
256
250
|
};
|
|
257
251
|
};
|
|
258
252
|
if (features.hasRls && rlsContext && baseDb) return withRlsContext(baseDb, rlsContext, async (trx) => executeHandler(trx), { prefix: endpoint.rlsConfig?.prefix });
|
|
259
253
|
return executeHandler(baseDb);
|
|
260
|
-
}, async (result
|
|
254
|
+
}, async (result, auditor) => {
|
|
261
255
|
if (!audits?.length) return;
|
|
262
256
|
for (const audit of audits) {
|
|
263
|
-
if (audit.when && !audit.when(result
|
|
264
|
-
const payload = audit.payload(result
|
|
265
|
-
const entityId = audit.entityId?.(result
|
|
257
|
+
if (audit.when && !audit.when(result.output)) continue;
|
|
258
|
+
const payload = audit.payload(result.output);
|
|
259
|
+
const entityId = audit.entityId?.(result.output);
|
|
266
260
|
auditor.audit(audit.type, payload, {
|
|
267
261
|
table: audit.table,
|
|
268
262
|
entityId
|
|
269
263
|
});
|
|
270
264
|
}
|
|
271
265
|
}, { db: rawDb });
|
|
272
|
-
const { output, metadata } = result;
|
|
273
266
|
try {
|
|
274
267
|
let status = endpoint.status;
|
|
275
268
|
if (metadata.status) status = metadata.status;
|
|
276
269
|
if (metadata.headers) for (const [key, value] of Object.entries(metadata.headers)) c.header(key, value);
|
|
277
270
|
if (metadata.cookies) for (const [name, { value, options }] of metadata.cookies) setCookie(c, name, value, options);
|
|
278
|
-
if (features.hasEvents && Endpoint.isSuccessStatus(status)) await publishConstructEvents(endpoint, output, serviceDiscovery, logger
|
|
279
|
-
if (HonoEndpoint.isDev) logger
|
|
271
|
+
if (features.hasEvents && Endpoint.isSuccessStatus(status)) await publishConstructEvents(endpoint, output, serviceDiscovery, logger);
|
|
272
|
+
if (HonoEndpoint.isDev) logger.info({
|
|
280
273
|
status,
|
|
281
274
|
body: output
|
|
282
275
|
}, "Outgoing response");
|
|
@@ -284,18 +277,18 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
284
277
|
if (!(metadata.headers && hasContentTypeHeader(metadata.headers))) c.header("content-type", endpoint.responseType);
|
|
285
278
|
return c.body(output, status);
|
|
286
279
|
} catch (validationError) {
|
|
287
|
-
logger
|
|
280
|
+
logger.error(validationError, "Output validation failed");
|
|
288
281
|
const error = wrapError(validationError, 422, "Response validation failed");
|
|
289
|
-
if (HonoEndpoint.isDev) logger
|
|
282
|
+
if (HonoEndpoint.isDev) logger.info({
|
|
290
283
|
status: error.statusCode,
|
|
291
284
|
body: error
|
|
292
285
|
}, "Outgoing response");
|
|
293
286
|
return c.json(error, error.statusCode);
|
|
294
287
|
}
|
|
295
288
|
} catch (e) {
|
|
296
|
-
logger
|
|
289
|
+
logger.error(e, "Error processing endpoint request");
|
|
297
290
|
const error = wrapError(e, 500, "Internal Server Error");
|
|
298
|
-
if (HonoEndpoint.isDev) logger
|
|
291
|
+
if (HonoEndpoint.isDev) logger.info({
|
|
299
292
|
status: error.statusCode,
|
|
300
293
|
body: error
|
|
301
294
|
}, "Outgoing response");
|
|
@@ -316,7 +309,7 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
316
309
|
});
|
|
317
310
|
}
|
|
318
311
|
};
|
|
319
|
-
|
|
320
312
|
//#endregion
|
|
321
|
-
export { HonoEndpoint };
|
|
322
|
-
|
|
313
|
+
export { HonoEndpoint as t };
|
|
314
|
+
|
|
315
|
+
//# sourceMappingURL=HonoEndpointAdaptor-Be6UdK0r.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HonoEndpointAdaptor-D233Jvpk.cjs","names":["routes: string[]","cwd: string","endpoints: Endpoint<string, HttpMethod, any, any, TServices>[]","c: Context","headers: Record<string, string>","endpoint: Endpoint<\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany\n\t>","endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession,\n\t\t\tTEventPublisher,\n\t\t\tTEventPublisherServiceName,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTAuditAction,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>","c: Context<any, string, {}>","data: unknown","schema?: T","serviceDiscovery: ServiceDiscovery<ServiceRecord<TServices>>","app: Hono","_app: Hono","_serviceDiscovery: ServiceDiscovery<any>","routes: string[]","envParser: EnvironmentParser<{}>","Hono","_logger: TLogger","options?: HonoEndpointOptions","endpoints: Endpoint<string, HttpMethod, any, any, TServices, TLogger>[]","validators: any[]","c: Context","db: TDatabase | undefined","ResponseBuilder","metadata","output","result","validationError: any","e: any","docsPath: string","openApiOptions?: HonoEndpointOptions['openApiOptions']"],"sources":["../src/endpoints/helpers.ts","../src/endpoints/parseHonoQuery.ts","../src/endpoints/HonoEndpointAdaptor.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Service } from '@geekmidas/services';\nimport fg from 'fast-glob';\nimport type { HttpMethod } from '../types';\nimport { Endpoint } from './Endpoint';\n\n// Re-export utility functions\n\n/**\n * Recursively finds the project root directory by looking for lock files.\n * Traverses up the directory tree until it finds a package manager lock file.\n *\n * @param cwd - The current working directory to start searching from\n * @returns Promise resolving to the absolute path of the project root\n *\n * @example\n * ```typescript\n * const projectRoot = await getProjectRoot(process.cwd());\n * console.log(`Project root: ${projectRoot}`);\n * // Output: Project root: /Users/user/my-project\n * ```\n */\nexport async function getProjectRoot(cwd: string): Promise<string> {\n\tif (cwd === '/') {\n\t\treturn cwd;\n\t}\n\n\tconst stream = fg.stream(\n\t\t['yarn.lock', 'pnpm-lock.yaml', 'package-lock.json', 'deno.lock'],\n\t\t{ dot: true, cwd },\n\t);\n\n\tlet isRoot = false;\n\n\tfor await (const _ of stream) {\n\t\tisRoot = true;\n\t\tbreak;\n\t}\n\n\tif (isRoot) {\n\t\treturn cwd;\n\t}\n\n\treturn getProjectRoot(path.resolve(cwd, '..'));\n}\n\n/**\n * Discovers and imports all Endpoint instances from the specified route patterns.\n * Uses fast-glob to find files matching the patterns and extracts exported Endpoints.\n *\n * @template TServices - Array of service types used by the endpoints\n * @param routes - Array of glob patterns to match route files (e.g., ['src/routes/*.ts'])\n * @param cwd - The current working directory to resolve paths from\n * @returns Promise resolving to an array of Endpoint instances found in the matched files\n *\n * @example\n * ```typescript\n * // Find all endpoints in the routes directory\n * const endpoints = await getEndpointsFromRoutes(\n * ['src/routes/**\\/*.ts'],\n * process.cwd()\n * );\n *\n * // Register endpoints with your server\n * for (const endpoint of endpoints) {\n * server.register(endpoint);\n * }\n * ```\n *\n * @remarks\n * - Only exports that are valid Endpoint instances are included\n * - Files are imported dynamically, so they must be valid ES modules\n * - The function filters out non-Endpoint exports automatically\n */\nexport async function getEndpointsFromRoutes<TServices extends Service[]>(\n\troutes: string[],\n\tcwd: string,\n): Promise<Endpoint<string, HttpMethod, any, any, TServices>[]> {\n\tconst stream = fg.stream(routes, { cwd });\n\n\tconst endpoints: Endpoint<string, HttpMethod, any, any, TServices>[] = [];\n\n\tfor await (const f of stream) {\n\t\t// Resolve the absolute path for the route file\n\t\tconst routePath = path.resolve(cwd, f.toString());\n\t\t// Dynamically import the route module\n\t\tconst route = await import(routePath);\n\n\t\t// Filter exported values to find only Endpoint instances\n\t\tconst handlers = Object.values(route).filter((value) => {\n\t\t\treturn Endpoint.isEndpoint(value);\n\t\t}) as unknown as Endpoint<string, HttpMethod, any, any, TServices>[];\n\n\t\tendpoints.push(...handlers);\n\t}\n\n\treturn endpoints;\n}\n","import type { Context } from 'hono';\nimport qs from 'qs';\n\n/**\n * Parse Hono query parameters using qs bracket notation\n * Supports nested objects, arrays, and deep nesting via standard bracket syntax\n */\nexport function parseHonoQuery(c: Context): Record<string, any> {\n\tconst url = c.req.url;\n\tconst queryIndex = url.indexOf('?');\n\tif (queryIndex === -1) {\n\t\treturn {};\n\t}\n\tconst queryString = url.slice(queryIndex + 1);\n\treturn qs.parse(queryString) as Record<string, any>;\n}\n","import type { AuditableAction, AuditStorage } from '@geekmidas/audit';\nimport { withRlsContext } from '@geekmidas/db/rls';\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport { wrapError } from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport { checkRateLimit, getRateLimitHeaders } from '@geekmidas/rate-limit';\nimport {\n\trunWithRequestContext,\n\ttype Service,\n\tServiceDiscovery,\n\ttype ServiceRecord,\n} from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { type Context, Hono } from 'hono';\nimport { setCookie } from 'hono/cookie';\nimport { logger as honoLogger } from 'hono/logger';\nimport { timing } from 'hono/timing';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { validator } from 'hono/validator';\nimport { publishConstructEvents } from '../publisher';\nimport type { HttpMethod, LowerHttpMethod } from '../types';\nimport type { MappedAudit } from './audit';\nimport {\n\tEndpoint,\n\ttype EndpointContext,\n\ttype EndpointSchemas,\n\tResponseBuilder,\n} from './Endpoint';\nimport { getEndpointsFromRoutes } from './helpers';\nimport { createHonoCookies, createHonoHeaders } from './lazyAccessors';\nimport { parseHonoQuery } from './parseHonoQuery';\nimport {\n\tcreateAuditContext,\n\texecuteWithAuditTransaction,\n} from './processAudits';\n\nexport interface HonoEndpointOptions {\n\t/**\n\t * Path where OpenAPI documentation will be served.\n\t * Set to false to disable docs route.\n\t * @default '/docs'\n\t */\n\tdocsPath?: string | false;\n\t/**\n\t * OpenAPI schema options\n\t */\n\topenApiOptions?: {\n\t\ttitle?: string;\n\t\tversion?: string;\n\t\tdescription?: string;\n\t};\n}\n\n/**\n * Feature flags for an endpoint, analyzed once at route registration time.\n * This avoids per-request feature detection overhead.\n */\ninterface EndpointFeatures {\n\thasServices: boolean;\n\thasDatabase: boolean;\n\thasBodyValidation: boolean;\n\thasQueryValidation: boolean;\n\thasParamValidation: boolean;\n\thasAudits: boolean;\n\thasEvents: boolean;\n\thasRateLimit: boolean;\n\thasRls: boolean;\n}\n\n/**\n * Case-insensitive check for a `content-type` header in a metadata headers map.\n */\nfunction hasContentTypeHeader(headers: Record<string, string>): boolean {\n\tfor (const key of Object.keys(headers)) {\n\t\tif (key.toLowerCase() === 'content-type') return true;\n\t}\n\treturn false;\n}\n\n/**\n * Analyze endpoint features at registration time (not per-request)\n */\nfunction analyzeEndpointFeatures(\n\tendpoint: Endpoint<\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany\n\t>,\n): EndpointFeatures {\n\treturn {\n\t\thasServices: endpoint.services.length > 0,\n\t\thasDatabase: !!endpoint.databaseService,\n\t\thasBodyValidation: !!endpoint.input?.body,\n\t\thasQueryValidation: !!endpoint.input?.query,\n\t\thasParamValidation: !!endpoint.input?.params,\n\t\t// Audit context needed if declarative audits OR auditor storage service configured (for manual audits)\n\t\thasAudits:\n\t\t\t(endpoint.audits?.length ?? 0) > 0 || !!endpoint.auditorStorageService,\n\t\thasEvents: (endpoint.events?.length ?? 0) > 0,\n\t\thasRateLimit: !!endpoint.rateLimit,\n\t\thasRls: !!endpoint.rlsConfig && !endpoint.rlsBypass,\n\t};\n}\n\nexport class HonoEndpoint<\n\tTRoute extends string,\n\tTMethod extends HttpMethod,\n\tTInput extends EndpointSchemas = {},\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\tTEventPublisherServiceName extends string = string,\n\tTAuditStorage extends AuditStorage | undefined = undefined,\n\tTAuditStorageServiceName extends string = string,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tconstructor(\n\t\tprivate readonly endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession,\n\t\t\tTEventPublisher,\n\t\t\tTEventPublisherServiceName,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTAuditAction,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t) {}\n\n\tstatic isDev = process.env.NODE_ENV === 'development';\n\n\tstatic async validate<T extends StandardSchemaV1>(\n\t\tc: Context<any, string, {}>,\n\t\tdata: unknown,\n\t\tschema?: T,\n\t) {\n\t\tif (!schema) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst parsed = await Endpoint.validate(schema, data);\n\n\t\tif (parsed.issues) {\n\t\t\treturn c.json(parsed.issues, 422);\n\t\t}\n\n\t\treturn parsed.value;\n\t}\n\taddRoute(\n\t\tserviceDiscovery: ServiceDiscovery<ServiceRecord<TServices>>,\n\t\tapp: Hono,\n\t): void {\n\t\tHonoEndpoint.addRoute(this.endpoint, serviceDiscovery, app);\n\t}\n\n\t/**\n\t * @deprecated Global event middleware is no longer used.\n\t * Events are now published per-route only for endpoints that have events configured.\n\t * This method is kept for backward compatibility but does nothing.\n\t */\n\tstatic applyEventMiddleware(\n\t\t_app: Hono,\n\t\t_serviceDiscovery: ServiceDiscovery<any>,\n\t) {\n\t\t// No-op: Event publishing is now handled per-route in addRoute\n\t\t// This avoids running middleware on every request including 404s\n\t}\n\n\tstatic async fromRoutes<TLogger extends Logger, TServices extends Service[]>(\n\t\troutes: string[],\n\t\tenvParser: EnvironmentParser<{}>,\n\t\tapp = new Hono(),\n\t\t_logger: TLogger,\n\t\tcwd = process.cwd(),\n\t\toptions?: HonoEndpointOptions,\n\t): Promise<Hono> {\n\t\tconst endpoints = await getEndpointsFromRoutes<TServices>(routes, cwd);\n\t\tconst serviceDiscovery =\n\t\t\tServiceDiscovery.getInstance<ServiceRecord<TServices>>(envParser);\n\n\t\tHonoEndpoint.addRoutes(endpoints, serviceDiscovery, app, options);\n\n\t\treturn app;\n\t}\n\n\tstatic addRoutes<\n\t\tTServices extends Service[] = [],\n\t\tTLogger extends Logger = Logger,\n\t>(\n\t\tendpoints: Endpoint<string, HttpMethod, any, any, TServices, TLogger>[],\n\t\tserviceDiscovery: ServiceDiscovery<ServiceRecord<TServices>>,\n\t\tapp: Hono,\n\t\toptions?: HonoEndpointOptions,\n\t): void {\n\t\t// Add timing middleware (always enabled)\n\t\tapp.use('*', timing());\n\n\t\t// Add logger middleware in development mode\n\n\t\tif (HonoEndpoint.isDev) {\n\t\t\tapp.use('*', honoLogger());\n\t\t}\n\n\t\t// Add docs route if not disabled\n\t\tconst docsPath =\n\t\t\toptions?.docsPath !== false ? options?.docsPath || '/docs' : null;\n\t\tif (docsPath) {\n\t\t\tHonoEndpoint.addDocsRoute(\n\t\t\t\tendpoints,\n\t\t\t\tapp,\n\t\t\t\tdocsPath,\n\t\t\t\toptions?.openApiOptions,\n\t\t\t);\n\t\t}\n\n\t\t// Sort endpoints to ensure static routes come before dynamic ones\n\t\tconst sortedEndpoints = endpoints.sort((a, b) => {\n\t\t\tconst aSegments = a.route.split('/');\n\t\t\tconst bSegments = b.route.split('/');\n\n\t\t\t// Compare each segment\n\t\t\tfor (let i = 0; i < Math.max(aSegments.length, bSegments.length); i++) {\n\t\t\t\tconst aSegment = aSegments[i] || '';\n\t\t\t\tconst bSegment = bSegments[i] || '';\n\n\t\t\t\t// If one is dynamic and the other is not, static comes first\n\t\t\t\tconst aIsDynamic = aSegment.startsWith(':');\n\t\t\t\tconst bIsDynamic = bSegment.startsWith(':');\n\n\t\t\t\tif (!aIsDynamic && bIsDynamic) return -1;\n\t\t\t\tif (aIsDynamic && !bIsDynamic) return 1;\n\n\t\t\t\t// If both are the same type, compare alphabetically\n\t\t\t\tif (aSegment !== bSegment) {\n\t\t\t\t\treturn aSegment.localeCompare(bSegment);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t});\n\n\t\t// Note: Global event middleware removed for performance\n\t\t// Events are now published per-route only for endpoints with events configured\n\t\tfor (const endpoint of sortedEndpoints) {\n\t\t\tHonoEndpoint.addRoute(endpoint, serviceDiscovery, app);\n\t\t}\n\t}\n\n\t// biome-ignore lint/suspicious/useAdjacentOverloadSignatures: not an overload — the instance `addRoute` above registers this adaptor's own endpoint, this one registers any endpoint on a given app. They share a name because they do the same thing to different subjects.\n\tstatic addRoute<\n\t\tTRoute extends string,\n\t\tTMethod extends HttpMethod,\n\t\tTInput extends EndpointSchemas = {},\n\t\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\t\tTServices extends Service[] = [],\n\t\tTLogger extends Logger = Logger,\n\t\tTSession = unknown,\n\t\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\t\tTEventPublisherServiceName extends string = string,\n\t\tTAuditStorage extends AuditStorage | undefined = undefined,\n\t\tTAuditStorageServiceName extends string = string,\n\t\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>,\n\t\tTDatabase = undefined,\n\t\tTDatabaseServiceName extends string = string,\n\t>(\n\t\tendpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession,\n\t\t\tTEventPublisher,\n\t\t\tTEventPublisherServiceName,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTAuditAction,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t\tserviceDiscovery: ServiceDiscovery<ServiceRecord<TServices>>,\n\t\tapp: Hono,\n\t): void {\n\t\tconst { route } = endpoint;\n\t\tconst method = endpoint.method.toLowerCase() as LowerHttpMethod<TMethod>;\n\n\t\t// Analyze endpoint features once at registration time (not per-request)\n\t\tconst features = analyzeEndpointFeatures(endpoint);\n\n\t\t// Build validators array - only add validators for schemas that exist\n\t\tconst validators: any[] = [];\n\n\t\tif (features.hasBodyValidation) {\n\t\t\tvalidators.push(\n\t\t\t\tvalidator('json', (value, c) =>\n\t\t\t\t\tHonoEndpoint.validate(c, value, endpoint.input?.body),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (features.hasQueryValidation) {\n\t\t\tvalidators.push(\n\t\t\t\tvalidator('query', (_, c) => {\n\t\t\t\t\tconst parsedQuery = parseHonoQuery(c);\n\t\t\t\t\treturn HonoEndpoint.validate(c, parsedQuery, endpoint.input?.query);\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tif (features.hasParamValidation) {\n\t\t\tvalidators.push(\n\t\t\t\tvalidator('param', (params, c) =>\n\t\t\t\t\tHonoEndpoint.validate(c, params, endpoint.input?.params),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Main handler\n\t\tconst handler = async (c: Context) => {\n\t\t\t// Request context setup\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = c.req.header('X-Request-ID') ?? crypto.randomUUID();\n\n\t\t\tconst logger = endpoint.logger.child({\n\t\t\t\trequestId,\n\t\t\t\tendpoint: endpoint.fullPath,\n\t\t\t\troute: endpoint.route,\n\t\t\t\thost: c.req.header('host'),\n\t\t\t\tmethod: endpoint.method,\n\t\t\t\tpath: c.req.path,\n\t\t\t}) as TLogger;\n\n\t\t\t// Set response header\n\t\t\tc.header('X-Request-ID', requestId);\n\n\t\t\t// Wrap entire handler in request context for services to access\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime },\n\t\t\t\tasync () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Lazy accessors - no upfront parsing, use native Hono methods\n\t\t\t\t\t\tconst header = createHonoHeaders(c);\n\t\t\t\t\t\tconst cookie = createHonoCookies(c);\n\n\t\t\t\t\t\t// Only register services if endpoint has any\n\t\t\t\t\t\tconst services = features.hasServices\n\t\t\t\t\t\t\t? await serviceDiscovery.register(endpoint.services)\n\t\t\t\t\t\t\t: ({} as ServiceRecord<TServices>);\n\n\t\t\t\t\t\t// Resolve database service only if configured\n\t\t\t\t\t\tconst rawDb = features.hasDatabase\n\t\t\t\t\t\t\t? await serviceDiscovery\n\t\t\t\t\t\t\t\t\t.register([endpoint.databaseService!])\n\t\t\t\t\t\t\t\t\t.then(\n\t\t\t\t\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\t\t\t\t\ts[\n\t\t\t\t\t\t\t\t\t\t\t\tendpoint.databaseService?.serviceName as keyof typeof s\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\t// Extract session (defaults to empty object)\n\t\t\t\t\t\tconst session = await endpoint.getSession({\n\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\t...(rawDb !== undefined && { db: rawDb }),\n\t\t\t\t\t\t} as any);\n\n\t\t\t\t\t\t// Check authorization (defaults to true)\n\t\t\t\t\t\tconst isAuthorized = await endpoint.authorize({\n\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t...(rawDb !== undefined && { db: rawDb }),\n\t\t\t\t\t\t\tbody: features.hasBodyValidation\n\t\t\t\t\t\t\t\t? (c.req.valid as any)('json')\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\tquery: features.hasQueryValidation\n\t\t\t\t\t\t\t\t? (c.req.valid as any)('query')\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\tparams: features.hasParamValidation\n\t\t\t\t\t\t\t\t? (c.req.valid as any)('param')\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t} as any);\n\n\t\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\t\tlogger.warn('Forbidden access attempt');\n\t\t\t\t\t\t\treturn c.json({ error: 'Forbidden' }, 403);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check rate limit only if configured\n\t\t\t\t\t\tif (features.hasRateLimit) {\n\t\t\t\t\t\t\tconst rateLimitInfo = await checkRateLimit(endpoint.rateLimit!, {\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t\tpath: c.req.path,\n\t\t\t\t\t\t\t\tmethod: endpoint.method,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst rateLimitHeaders = getRateLimitHeaders(\n\t\t\t\t\t\t\t\trateLimitInfo,\n\t\t\t\t\t\t\t\tendpoint.rateLimit!,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tfor (const [key, value] of Object.entries(rateLimitHeaders)) {\n\t\t\t\t\t\t\t\tif (value) {\n\t\t\t\t\t\t\t\t\tc.header(key, value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Create audit context only if audits are configured\n\t\t\t\t\t\tconst auditContext = features.hasAudits\n\t\t\t\t\t\t\t? await createAuditContext(\n\t\t\t\t\t\t\t\t\tendpoint as any,\n\t\t\t\t\t\t\t\t\tserviceDiscovery,\n\t\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\t\t\t\tservices: services as Record<string, unknown>,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\tconst audits = features.hasAudits\n\t\t\t\t\t\t\t? (endpoint.audits as MappedAudit<TAuditAction, TOutSchema>[])\n\t\t\t\t\t\t\t: [];\n\n\t\t\t\t\t\t// Warn if declarative audits are configured but no audit storage\n\t\t\t\t\t\tif (features.hasAudits && !auditContext) {\n\t\t\t\t\t\t\tlogger.warn('No auditor storage service available');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Extract RLS context only if configured and not bypassed\n\t\t\t\t\t\tconst rlsContext =\n\t\t\t\t\t\t\tfeatures.hasRls && rawDb !== undefined\n\t\t\t\t\t\t\t\t? await endpoint.rlsConfig?.extractor({\n\t\t\t\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\t\t\t\tsession: session as TSession,\n\t\t\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\t// Execute handler with automatic audit transaction support\n\t\t\t\t\t\tconst result = await executeWithAuditTransaction(\n\t\t\t\t\t\t\tauditContext,\n\t\t\t\t\t\t\tasync (auditor) => {\n\t\t\t\t\t\t\t\tconst sameDatabase =\n\t\t\t\t\t\t\t\t\tauditContext?.storage?.databaseServiceName &&\n\t\t\t\t\t\t\t\t\tauditContext.storage.databaseServiceName ===\n\t\t\t\t\t\t\t\t\t\tendpoint.databaseService?.serviceName;\n\t\t\t\t\t\t\t\tconst baseDb = sameDatabase\n\t\t\t\t\t\t\t\t\t? (auditor?.getTransaction?.() ?? rawDb)\n\t\t\t\t\t\t\t\t\t: rawDb;\n\n\t\t\t\t\t\t\t\tconst executeHandler = async (db: TDatabase | undefined) => {\n\t\t\t\t\t\t\t\t\tconst responseBuilder = new ResponseBuilder();\n\t\t\t\t\t\t\t\t\tconst response = await endpoint.handler(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\t\t\t\tbody: features.hasBodyValidation\n\t\t\t\t\t\t\t\t\t\t\t\t? (c.req.valid as any)('json')\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\t\t\t\tquery: features.hasQueryValidation\n\t\t\t\t\t\t\t\t\t\t\t\t? (c.req.valid as any)('query')\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\t\t\t\tparams: features.hasParamValidation\n\t\t\t\t\t\t\t\t\t\t\t\t? (c.req.valid as any)('param')\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\t\t\t\t\tauditor,\n\t\t\t\t\t\t\t\t\t\t\tdb,\n\t\t\t\t\t\t\t\t\t\t} as unknown as EndpointContext<\n\t\t\t\t\t\t\t\t\t\t\tTInput,\n\t\t\t\t\t\t\t\t\t\t\tTServices,\n\t\t\t\t\t\t\t\t\t\t\tTLogger,\n\t\t\t\t\t\t\t\t\t\t\tTSession,\n\t\t\t\t\t\t\t\t\t\t\tTAuditAction,\n\t\t\t\t\t\t\t\t\t\t\tTDatabase,\n\t\t\t\t\t\t\t\t\t\t\tTAuditStorage\n\t\t\t\t\t\t\t\t\t\t>,\n\t\t\t\t\t\t\t\t\t\tresponseBuilder,\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\tlet data = response;\n\t\t\t\t\t\t\t\t\tlet metadata = responseBuilder.getMetadata();\n\n\t\t\t\t\t\t\t\t\tif (Endpoint.hasMetadata(response)) {\n\t\t\t\t\t\t\t\t\t\tdata = response.data;\n\t\t\t\t\t\t\t\t\t\tmetadata = response.metadata;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tconst output = endpoint.outputSchema\n\t\t\t\t\t\t\t\t\t\t? await endpoint.parseOutput(data)\n\t\t\t\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\t\t\t\treturn { output, metadata, responseBuilder };\n\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\tif (features.hasRls && rlsContext && baseDb) {\n\t\t\t\t\t\t\t\t\treturn withRlsContext(\n\t\t\t\t\t\t\t\t\t\tbaseDb as any,\n\t\t\t\t\t\t\t\t\t\trlsContext,\n\t\t\t\t\t\t\t\t\t\tasync (trx) => executeHandler(trx as TDatabase),\n\t\t\t\t\t\t\t\t\t\t{ prefix: endpoint.rlsConfig?.prefix },\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn executeHandler(baseDb as TDatabase | undefined);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tasync (result, auditor) => {\n\t\t\t\t\t\t\t\tif (!audits?.length) return;\n\n\t\t\t\t\t\t\t\tfor (const audit of audits) {\n\t\t\t\t\t\t\t\t\tif (audit.when && !audit.when(result.output as any)) {\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tconst payload = audit.payload(result.output as any);\n\t\t\t\t\t\t\t\t\tconst entityId = audit.entityId?.(result.output as any);\n\t\t\t\t\t\t\t\t\tauditor.audit(audit.type as any, payload as any, {\n\t\t\t\t\t\t\t\t\t\ttable: audit.table,\n\t\t\t\t\t\t\t\t\t\tentityId,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ db: rawDb },\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tconst { output, metadata } = result;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlet status = endpoint.status as ContentfulStatusCode;\n\n\t\t\t\t\t\t\tif (metadata.status) {\n\t\t\t\t\t\t\t\tstatus = metadata.status as ContentfulStatusCode;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (metadata.headers) {\n\t\t\t\t\t\t\t\tfor (const [key, value] of Object.entries(metadata.headers)) {\n\t\t\t\t\t\t\t\t\tc.header(key, value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (metadata.cookies) {\n\t\t\t\t\t\t\t\tfor (const [name, { value, options }] of metadata.cookies) {\n\t\t\t\t\t\t\t\t\tsetCookie(c, name, value, options);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Only publish events if configured (no global middleware overhead)\n\t\t\t\t\t\t\tif (features.hasEvents && Endpoint.isSuccessStatus(status)) {\n\t\t\t\t\t\t\t\tawait publishConstructEvents<any, any>(\n\t\t\t\t\t\t\t\t\tendpoint as any,\n\t\t\t\t\t\t\t\t\toutput,\n\t\t\t\t\t\t\t\t\tserviceDiscovery,\n\t\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (HonoEndpoint.isDev) {\n\t\t\t\t\t\t\t\tlogger.info({ status, body: output }, 'Outgoing response');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Respect the endpoint's declared responseType. For JSON (default)\n\t\t\t\t\t\t\t// we use c.json() which sets Content-Type and serializes. For any\n\t\t\t\t\t\t\t// other type, emit the body as-is and set the header explicitly —\n\t\t\t\t\t\t\t// metadata.headers (from r.header()) applied above still wins.\n\t\t\t\t\t\t\tif (endpoint.responseType === 'application/json') {\n\t\t\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\t\t\treturn c.json(output, status);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!(metadata.headers && hasContentTypeHeader(metadata.headers))\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tc.header('content-type', endpoint.responseType);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn c.body(output as any, status);\n\t\t\t\t\t\t} catch (validationError: any) {\n\t\t\t\t\t\t\tlogger.error(validationError, 'Output validation failed');\n\t\t\t\t\t\t\tconst error = wrapError(\n\t\t\t\t\t\t\t\tvalidationError,\n\t\t\t\t\t\t\t\t422,\n\t\t\t\t\t\t\t\t'Response validation failed',\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (HonoEndpoint.isDev) {\n\t\t\t\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t\t\t\t{ status: error.statusCode, body: error },\n\t\t\t\t\t\t\t\t\t'Outgoing response',\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn c.json(error, error.statusCode as ContentfulStatusCode);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\tlogger.error(e, 'Error processing endpoint request');\n\t\t\t\t\t\tconst error = wrapError(e, 500, 'Internal Server Error');\n\t\t\t\t\t\tif (HonoEndpoint.isDev) {\n\t\t\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t\t\t{ status: error.statusCode, body: error },\n\t\t\t\t\t\t\t\t'Outgoing response',\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn c.json(error, error.statusCode as ContentfulStatusCode);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\t// Register route with conditional validators\n\t\tapp[method](route, ...validators, handler);\n\t}\n\n\tstatic addDocsRoute<\n\t\tTServices extends Service[] = [],\n\t\tTLogger extends Logger = Logger,\n\t>(\n\t\tendpoints: Endpoint<string, HttpMethod, any, any, TServices, TLogger>[],\n\t\tapp: Hono,\n\t\tdocsPath: string,\n\t\topenApiOptions?: HonoEndpointOptions['openApiOptions'],\n\t): void {\n\t\tapp.get(docsPath, async (c) => {\n\t\t\ttry {\n\t\t\t\tconst openApiSchema = await Endpoint.buildOpenApiSchema(\n\t\t\t\t\tendpoints,\n\t\t\t\t\topenApiOptions,\n\t\t\t\t);\n\n\t\t\t\treturn c.json(openApiSchema);\n\t\t\t} catch {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: 'Failed to generate OpenAPI documentation' },\n\t\t\t\t\t500,\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HonoEndpointAdaptor-Be6UdK0r.mjs","names":["honoLogger"],"sources":["../src/endpoints/helpers.ts","../src/endpoints/parseHonoQuery.ts","../src/endpoints/HonoEndpointAdaptor.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Service } from '@geekmidas/services';\nimport fg from 'fast-glob';\nimport type { HttpMethod } from '../types';\nimport { Endpoint } from './Endpoint';\n\n// Re-export utility functions\n\n/**\n * Recursively finds the project root directory by looking for lock files.\n * Traverses up the directory tree until it finds a package manager lock file.\n *\n * @param cwd - The current working directory to start searching from\n * @returns Promise resolving to the absolute path of the project root\n *\n * @example\n * ```typescript\n * const projectRoot = await getProjectRoot(process.cwd());\n * console.log(`Project root: ${projectRoot}`);\n * // Output: Project root: /Users/user/my-project\n * ```\n */\nexport async function getProjectRoot(cwd: string): Promise<string> {\n\tif (cwd === '/') {\n\t\treturn cwd;\n\t}\n\n\tconst stream = fg.stream(\n\t\t['yarn.lock', 'pnpm-lock.yaml', 'package-lock.json', 'deno.lock'],\n\t\t{ dot: true, cwd },\n\t);\n\n\tlet isRoot = false;\n\n\tfor await (const _ of stream) {\n\t\tisRoot = true;\n\t\tbreak;\n\t}\n\n\tif (isRoot) {\n\t\treturn cwd;\n\t}\n\n\treturn getProjectRoot(path.resolve(cwd, '..'));\n}\n\n/**\n * Discovers and imports all Endpoint instances from the specified route patterns.\n * Uses fast-glob to find files matching the patterns and extracts exported Endpoints.\n *\n * @template TServices - Array of service types used by the endpoints\n * @param routes - Array of glob patterns to match route files (e.g., ['src/routes/*.ts'])\n * @param cwd - The current working directory to resolve paths from\n * @returns Promise resolving to an array of Endpoint instances found in the matched files\n *\n * @example\n * ```typescript\n * // Find all endpoints in the routes directory\n * const endpoints = await getEndpointsFromRoutes(\n * ['src/routes/**\\/*.ts'],\n * process.cwd()\n * );\n *\n * // Register endpoints with your server\n * for (const endpoint of endpoints) {\n * server.register(endpoint);\n * }\n * ```\n *\n * @remarks\n * - Only exports that are valid Endpoint instances are included\n * - Files are imported dynamically, so they must be valid ES modules\n * - The function filters out non-Endpoint exports automatically\n */\nexport async function getEndpointsFromRoutes<TServices extends Service[]>(\n\troutes: string[],\n\tcwd: string,\n): Promise<Endpoint<string, HttpMethod, any, any, TServices>[]> {\n\tconst stream = fg.stream(routes, { cwd });\n\n\tconst endpoints: Endpoint<string, HttpMethod, any, any, TServices>[] = [];\n\n\tfor await (const f of stream) {\n\t\t// Resolve the absolute path for the route file\n\t\tconst routePath = path.resolve(cwd, f.toString());\n\t\t// Dynamically import the route module\n\t\tconst route = await import(routePath);\n\n\t\t// Filter exported values to find only Endpoint instances\n\t\tconst handlers = Object.values(route).filter((value) => {\n\t\t\treturn Endpoint.isEndpoint(value);\n\t\t}) as unknown as Endpoint<string, HttpMethod, any, any, TServices>[];\n\n\t\tendpoints.push(...handlers);\n\t}\n\n\treturn endpoints;\n}\n","import type { Context } from 'hono';\nimport qs from 'qs';\n\n/**\n * Parse Hono query parameters using qs bracket notation\n * Supports nested objects, arrays, and deep nesting via standard bracket syntax\n */\nexport function parseHonoQuery(c: Context): Record<string, any> {\n\tconst url = c.req.url;\n\tconst queryIndex = url.indexOf('?');\n\tif (queryIndex === -1) {\n\t\treturn {};\n\t}\n\tconst queryString = url.slice(queryIndex + 1);\n\treturn qs.parse(queryString) as Record<string, any>;\n}\n","import type { AuditableAction, AuditStorage } from '@geekmidas/audit';\nimport { withRlsContext } from '@geekmidas/db/rls';\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport { wrapError } from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport { checkRateLimit, getRateLimitHeaders } from '@geekmidas/rate-limit';\nimport {\n\trunWithRequestContext,\n\ttype Service,\n\tServiceDiscovery,\n\ttype ServiceRecord,\n} from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { type Context, Hono } from 'hono';\nimport { setCookie } from 'hono/cookie';\nimport { logger as honoLogger } from 'hono/logger';\nimport { timing } from 'hono/timing';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { validator } from 'hono/validator';\nimport { publishConstructEvents } from '../publisher';\nimport type { HttpMethod, LowerHttpMethod } from '../types';\nimport type { MappedAudit } from './audit';\nimport {\n\tEndpoint,\n\ttype EndpointContext,\n\ttype EndpointSchemas,\n\tResponseBuilder,\n} from './Endpoint';\nimport { getEndpointsFromRoutes } from './helpers';\nimport { createHonoCookies, createHonoHeaders } from './lazyAccessors';\nimport { parseHonoQuery } from './parseHonoQuery';\nimport {\n\tcreateAuditContext,\n\texecuteWithAuditTransaction,\n} from './processAudits';\n\nexport interface HonoEndpointOptions {\n\t/**\n\t * Path where OpenAPI documentation will be served.\n\t * Set to false to disable docs route.\n\t * @default '/docs'\n\t */\n\tdocsPath?: string | false;\n\t/**\n\t * OpenAPI schema options\n\t */\n\topenApiOptions?: {\n\t\ttitle?: string;\n\t\tversion?: string;\n\t\tdescription?: string;\n\t};\n}\n\n/**\n * Feature flags for an endpoint, analyzed once at route registration time.\n * This avoids per-request feature detection overhead.\n */\ninterface EndpointFeatures {\n\thasServices: boolean;\n\thasDatabase: boolean;\n\thasBodyValidation: boolean;\n\thasQueryValidation: boolean;\n\thasParamValidation: boolean;\n\thasAudits: boolean;\n\thasEvents: boolean;\n\thasRateLimit: boolean;\n\thasRls: boolean;\n}\n\n/**\n * Case-insensitive check for a `content-type` header in a metadata headers map.\n */\nfunction hasContentTypeHeader(headers: Record<string, string>): boolean {\n\tfor (const key of Object.keys(headers)) {\n\t\tif (key.toLowerCase() === 'content-type') return true;\n\t}\n\treturn false;\n}\n\n/**\n * Analyze endpoint features at registration time (not per-request)\n */\nfunction analyzeEndpointFeatures(\n\tendpoint: Endpoint<\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany\n\t>,\n): EndpointFeatures {\n\treturn {\n\t\thasServices: endpoint.services.length > 0,\n\t\thasDatabase: !!endpoint.databaseService,\n\t\thasBodyValidation: !!endpoint.input?.body,\n\t\thasQueryValidation: !!endpoint.input?.query,\n\t\thasParamValidation: !!endpoint.input?.params,\n\t\t// Audit context needed if declarative audits OR auditor storage service configured (for manual audits)\n\t\thasAudits:\n\t\t\t(endpoint.audits?.length ?? 0) > 0 || !!endpoint.auditorStorageService,\n\t\thasEvents: (endpoint.events?.length ?? 0) > 0,\n\t\thasRateLimit: !!endpoint.rateLimit,\n\t\thasRls: !!endpoint.rlsConfig && !endpoint.rlsBypass,\n\t};\n}\n\nexport class HonoEndpoint<\n\tTRoute extends string,\n\tTMethod extends HttpMethod,\n\tTInput extends EndpointSchemas = {},\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\tTEventPublisherServiceName extends string = string,\n\tTAuditStorage extends AuditStorage | undefined = undefined,\n\tTAuditStorageServiceName extends string = string,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tconstructor(\n\t\tprivate readonly endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession,\n\t\t\tTEventPublisher,\n\t\t\tTEventPublisherServiceName,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTAuditAction,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t) {}\n\n\tstatic isDev = process.env.NODE_ENV === 'development';\n\n\tstatic async validate<T extends StandardSchemaV1>(\n\t\tc: Context<any, string, {}>,\n\t\tdata: unknown,\n\t\tschema?: T,\n\t) {\n\t\tif (!schema) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst parsed = await Endpoint.validate(schema, data);\n\n\t\tif (parsed.issues) {\n\t\t\treturn c.json(parsed.issues, 422);\n\t\t}\n\n\t\treturn parsed.value;\n\t}\n\taddRoute(\n\t\tserviceDiscovery: ServiceDiscovery<ServiceRecord<TServices>>,\n\t\tapp: Hono,\n\t): void {\n\t\tHonoEndpoint.addRoute(this.endpoint, serviceDiscovery, app);\n\t}\n\n\t/**\n\t * @deprecated Global event middleware is no longer used.\n\t * Events are now published per-route only for endpoints that have events configured.\n\t * This method is kept for backward compatibility but does nothing.\n\t */\n\tstatic applyEventMiddleware(\n\t\t_app: Hono,\n\t\t_serviceDiscovery: ServiceDiscovery<any>,\n\t) {\n\t\t// No-op: Event publishing is now handled per-route in addRoute\n\t\t// This avoids running middleware on every request including 404s\n\t}\n\n\tstatic async fromRoutes<TLogger extends Logger, TServices extends Service[]>(\n\t\troutes: string[],\n\t\tenvParser: EnvironmentParser<{}>,\n\t\tapp = new Hono(),\n\t\t_logger: TLogger,\n\t\tcwd = process.cwd(),\n\t\toptions?: HonoEndpointOptions,\n\t): Promise<Hono> {\n\t\tconst endpoints = await getEndpointsFromRoutes<TServices>(routes, cwd);\n\t\tconst serviceDiscovery =\n\t\t\tServiceDiscovery.getInstance<ServiceRecord<TServices>>(envParser);\n\n\t\tHonoEndpoint.addRoutes(endpoints, serviceDiscovery, app, options);\n\n\t\treturn app;\n\t}\n\n\tstatic addRoutes<\n\t\tTServices extends Service[] = [],\n\t\tTLogger extends Logger = Logger,\n\t>(\n\t\tendpoints: Endpoint<string, HttpMethod, any, any, TServices, TLogger>[],\n\t\tserviceDiscovery: ServiceDiscovery<ServiceRecord<TServices>>,\n\t\tapp: Hono,\n\t\toptions?: HonoEndpointOptions,\n\t): void {\n\t\t// Add timing middleware (always enabled)\n\t\tapp.use('*', timing());\n\n\t\t// Add logger middleware in development mode\n\n\t\tif (HonoEndpoint.isDev) {\n\t\t\tapp.use('*', honoLogger());\n\t\t}\n\n\t\t// Add docs route if not disabled\n\t\tconst docsPath =\n\t\t\toptions?.docsPath !== false ? options?.docsPath || '/docs' : null;\n\t\tif (docsPath) {\n\t\t\tHonoEndpoint.addDocsRoute(\n\t\t\t\tendpoints,\n\t\t\t\tapp,\n\t\t\t\tdocsPath,\n\t\t\t\toptions?.openApiOptions,\n\t\t\t);\n\t\t}\n\n\t\t// Sort endpoints to ensure static routes come before dynamic ones\n\t\tconst sortedEndpoints = endpoints.sort((a, b) => {\n\t\t\tconst aSegments = a.route.split('/');\n\t\t\tconst bSegments = b.route.split('/');\n\n\t\t\t// Compare each segment\n\t\t\tfor (let i = 0; i < Math.max(aSegments.length, bSegments.length); i++) {\n\t\t\t\tconst aSegment = aSegments[i] || '';\n\t\t\t\tconst bSegment = bSegments[i] || '';\n\n\t\t\t\t// If one is dynamic and the other is not, static comes first\n\t\t\t\tconst aIsDynamic = aSegment.startsWith(':');\n\t\t\t\tconst bIsDynamic = bSegment.startsWith(':');\n\n\t\t\t\tif (!aIsDynamic && bIsDynamic) return -1;\n\t\t\t\tif (aIsDynamic && !bIsDynamic) return 1;\n\n\t\t\t\t// If both are the same type, compare alphabetically\n\t\t\t\tif (aSegment !== bSegment) {\n\t\t\t\t\treturn aSegment.localeCompare(bSegment);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t});\n\n\t\t// Note: Global event middleware removed for performance\n\t\t// Events are now published per-route only for endpoints with events configured\n\t\tfor (const endpoint of sortedEndpoints) {\n\t\t\tHonoEndpoint.addRoute(endpoint, serviceDiscovery, app);\n\t\t}\n\t}\n\n\t// biome-ignore lint/suspicious/useAdjacentOverloadSignatures: not an overload — the instance `addRoute` above registers this adaptor's own endpoint, this one registers any endpoint on a given app. They share a name because they do the same thing to different subjects.\n\tstatic addRoute<\n\t\tTRoute extends string,\n\t\tTMethod extends HttpMethod,\n\t\tTInput extends EndpointSchemas = {},\n\t\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\t\tTServices extends Service[] = [],\n\t\tTLogger extends Logger = Logger,\n\t\tTSession = unknown,\n\t\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\t\tTEventPublisherServiceName extends string = string,\n\t\tTAuditStorage extends AuditStorage | undefined = undefined,\n\t\tTAuditStorageServiceName extends string = string,\n\t\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>,\n\t\tTDatabase = undefined,\n\t\tTDatabaseServiceName extends string = string,\n\t>(\n\t\tendpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession,\n\t\t\tTEventPublisher,\n\t\t\tTEventPublisherServiceName,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTAuditAction,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t\tserviceDiscovery: ServiceDiscovery<ServiceRecord<TServices>>,\n\t\tapp: Hono,\n\t): void {\n\t\tconst { route } = endpoint;\n\t\tconst method = endpoint.method.toLowerCase() as LowerHttpMethod<TMethod>;\n\n\t\t// Analyze endpoint features once at registration time (not per-request)\n\t\tconst features = analyzeEndpointFeatures(endpoint);\n\n\t\t// Build validators array - only add validators for schemas that exist\n\t\tconst validators: any[] = [];\n\n\t\tif (features.hasBodyValidation) {\n\t\t\tvalidators.push(\n\t\t\t\tvalidator('json', (value, c) =>\n\t\t\t\t\tHonoEndpoint.validate(c, value, endpoint.input?.body),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (features.hasQueryValidation) {\n\t\t\tvalidators.push(\n\t\t\t\tvalidator('query', (_, c) => {\n\t\t\t\t\tconst parsedQuery = parseHonoQuery(c);\n\t\t\t\t\treturn HonoEndpoint.validate(c, parsedQuery, endpoint.input?.query);\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tif (features.hasParamValidation) {\n\t\t\tvalidators.push(\n\t\t\t\tvalidator('param', (params, c) =>\n\t\t\t\t\tHonoEndpoint.validate(c, params, endpoint.input?.params),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Main handler\n\t\tconst handler = async (c: Context) => {\n\t\t\t// Request context setup\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = c.req.header('X-Request-ID') ?? crypto.randomUUID();\n\n\t\t\tconst logger = endpoint.logger.child({\n\t\t\t\trequestId,\n\t\t\t\tendpoint: endpoint.fullPath,\n\t\t\t\troute: endpoint.route,\n\t\t\t\thost: c.req.header('host'),\n\t\t\t\tmethod: endpoint.method,\n\t\t\t\tpath: c.req.path,\n\t\t\t}) as TLogger;\n\n\t\t\t// Set response header\n\t\t\tc.header('X-Request-ID', requestId);\n\n\t\t\t// Wrap entire handler in request context for services to access\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime },\n\t\t\t\tasync () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Lazy accessors - no upfront parsing, use native Hono methods\n\t\t\t\t\t\tconst header = createHonoHeaders(c);\n\t\t\t\t\t\tconst cookie = createHonoCookies(c);\n\n\t\t\t\t\t\t// Only register services if endpoint has any\n\t\t\t\t\t\tconst services = features.hasServices\n\t\t\t\t\t\t\t? await serviceDiscovery.register(endpoint.services)\n\t\t\t\t\t\t\t: ({} as ServiceRecord<TServices>);\n\n\t\t\t\t\t\t// Resolve database service only if configured\n\t\t\t\t\t\tconst rawDb = features.hasDatabase\n\t\t\t\t\t\t\t? await serviceDiscovery\n\t\t\t\t\t\t\t\t\t.register([endpoint.databaseService!])\n\t\t\t\t\t\t\t\t\t.then(\n\t\t\t\t\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\t\t\t\t\ts[\n\t\t\t\t\t\t\t\t\t\t\t\tendpoint.databaseService?.serviceName as keyof typeof s\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\t// Extract session (defaults to empty object)\n\t\t\t\t\t\tconst session = await endpoint.getSession({\n\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\t...(rawDb !== undefined && { db: rawDb }),\n\t\t\t\t\t\t} as any);\n\n\t\t\t\t\t\t// Check authorization (defaults to true)\n\t\t\t\t\t\tconst isAuthorized = await endpoint.authorize({\n\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t...(rawDb !== undefined && { db: rawDb }),\n\t\t\t\t\t\t\tbody: features.hasBodyValidation\n\t\t\t\t\t\t\t\t? (c.req.valid as any)('json')\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\tquery: features.hasQueryValidation\n\t\t\t\t\t\t\t\t? (c.req.valid as any)('query')\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\tparams: features.hasParamValidation\n\t\t\t\t\t\t\t\t? (c.req.valid as any)('param')\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t} as any);\n\n\t\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\t\tlogger.warn('Forbidden access attempt');\n\t\t\t\t\t\t\treturn c.json({ error: 'Forbidden' }, 403);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check rate limit only if configured\n\t\t\t\t\t\tif (features.hasRateLimit) {\n\t\t\t\t\t\t\tconst rateLimitInfo = await checkRateLimit(endpoint.rateLimit!, {\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t\tpath: c.req.path,\n\t\t\t\t\t\t\t\tmethod: endpoint.method,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst rateLimitHeaders = getRateLimitHeaders(\n\t\t\t\t\t\t\t\trateLimitInfo,\n\t\t\t\t\t\t\t\tendpoint.rateLimit!,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tfor (const [key, value] of Object.entries(rateLimitHeaders)) {\n\t\t\t\t\t\t\t\tif (value) {\n\t\t\t\t\t\t\t\t\tc.header(key, value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Create audit context only if audits are configured\n\t\t\t\t\t\tconst auditContext = features.hasAudits\n\t\t\t\t\t\t\t? await createAuditContext(\n\t\t\t\t\t\t\t\t\tendpoint as any,\n\t\t\t\t\t\t\t\t\tserviceDiscovery,\n\t\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\t\t\t\tservices: services as Record<string, unknown>,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\tconst audits = features.hasAudits\n\t\t\t\t\t\t\t? (endpoint.audits as MappedAudit<TAuditAction, TOutSchema>[])\n\t\t\t\t\t\t\t: [];\n\n\t\t\t\t\t\t// Warn if declarative audits are configured but no audit storage\n\t\t\t\t\t\tif (features.hasAudits && !auditContext) {\n\t\t\t\t\t\t\tlogger.warn('No auditor storage service available');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Extract RLS context only if configured and not bypassed\n\t\t\t\t\t\tconst rlsContext =\n\t\t\t\t\t\t\tfeatures.hasRls && rawDb !== undefined\n\t\t\t\t\t\t\t\t? await endpoint.rlsConfig?.extractor({\n\t\t\t\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\t\t\t\tsession: session as TSession,\n\t\t\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\t// Execute handler with automatic audit transaction support\n\t\t\t\t\t\tconst result = await executeWithAuditTransaction(\n\t\t\t\t\t\t\tauditContext,\n\t\t\t\t\t\t\tasync (auditor) => {\n\t\t\t\t\t\t\t\tconst sameDatabase =\n\t\t\t\t\t\t\t\t\tauditContext?.storage?.databaseServiceName &&\n\t\t\t\t\t\t\t\t\tauditContext.storage.databaseServiceName ===\n\t\t\t\t\t\t\t\t\t\tendpoint.databaseService?.serviceName;\n\t\t\t\t\t\t\t\tconst baseDb = sameDatabase\n\t\t\t\t\t\t\t\t\t? (auditor?.getTransaction?.() ?? rawDb)\n\t\t\t\t\t\t\t\t\t: rawDb;\n\n\t\t\t\t\t\t\t\tconst executeHandler = async (db: TDatabase | undefined) => {\n\t\t\t\t\t\t\t\t\tconst responseBuilder = new ResponseBuilder();\n\t\t\t\t\t\t\t\t\tconst response = await endpoint.handler(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\t\t\t\tbody: features.hasBodyValidation\n\t\t\t\t\t\t\t\t\t\t\t\t? (c.req.valid as any)('json')\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\t\t\t\tquery: features.hasQueryValidation\n\t\t\t\t\t\t\t\t\t\t\t\t? (c.req.valid as any)('query')\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\t\t\t\tparams: features.hasParamValidation\n\t\t\t\t\t\t\t\t\t\t\t\t? (c.req.valid as any)('param')\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\t\t\t\t\tauditor,\n\t\t\t\t\t\t\t\t\t\t\tdb,\n\t\t\t\t\t\t\t\t\t\t} as unknown as EndpointContext<\n\t\t\t\t\t\t\t\t\t\t\tTInput,\n\t\t\t\t\t\t\t\t\t\t\tTServices,\n\t\t\t\t\t\t\t\t\t\t\tTLogger,\n\t\t\t\t\t\t\t\t\t\t\tTSession,\n\t\t\t\t\t\t\t\t\t\t\tTAuditAction,\n\t\t\t\t\t\t\t\t\t\t\tTDatabase,\n\t\t\t\t\t\t\t\t\t\t\tTAuditStorage\n\t\t\t\t\t\t\t\t\t\t>,\n\t\t\t\t\t\t\t\t\t\tresponseBuilder,\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\tlet data = response;\n\t\t\t\t\t\t\t\t\tlet metadata = responseBuilder.getMetadata();\n\n\t\t\t\t\t\t\t\t\tif (Endpoint.hasMetadata(response)) {\n\t\t\t\t\t\t\t\t\t\tdata = response.data;\n\t\t\t\t\t\t\t\t\t\tmetadata = response.metadata;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tconst output = endpoint.outputSchema\n\t\t\t\t\t\t\t\t\t\t? await endpoint.parseOutput(data)\n\t\t\t\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\t\t\t\treturn { output, metadata, responseBuilder };\n\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\tif (features.hasRls && rlsContext && baseDb) {\n\t\t\t\t\t\t\t\t\treturn withRlsContext(\n\t\t\t\t\t\t\t\t\t\tbaseDb as any,\n\t\t\t\t\t\t\t\t\t\trlsContext,\n\t\t\t\t\t\t\t\t\t\tasync (trx) => executeHandler(trx as TDatabase),\n\t\t\t\t\t\t\t\t\t\t{ prefix: endpoint.rlsConfig?.prefix },\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn executeHandler(baseDb as TDatabase | undefined);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tasync (result, auditor) => {\n\t\t\t\t\t\t\t\tif (!audits?.length) return;\n\n\t\t\t\t\t\t\t\tfor (const audit of audits) {\n\t\t\t\t\t\t\t\t\tif (audit.when && !audit.when(result.output as any)) {\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tconst payload = audit.payload(result.output as any);\n\t\t\t\t\t\t\t\t\tconst entityId = audit.entityId?.(result.output as any);\n\t\t\t\t\t\t\t\t\tauditor.audit(audit.type as any, payload as any, {\n\t\t\t\t\t\t\t\t\t\ttable: audit.table,\n\t\t\t\t\t\t\t\t\t\tentityId,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ db: rawDb },\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tconst { output, metadata } = result;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlet status = endpoint.status as ContentfulStatusCode;\n\n\t\t\t\t\t\t\tif (metadata.status) {\n\t\t\t\t\t\t\t\tstatus = metadata.status as ContentfulStatusCode;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (metadata.headers) {\n\t\t\t\t\t\t\t\tfor (const [key, value] of Object.entries(metadata.headers)) {\n\t\t\t\t\t\t\t\t\tc.header(key, value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (metadata.cookies) {\n\t\t\t\t\t\t\t\tfor (const [name, { value, options }] of metadata.cookies) {\n\t\t\t\t\t\t\t\t\tsetCookie(c, name, value, options);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Only publish events if configured (no global middleware overhead)\n\t\t\t\t\t\t\tif (features.hasEvents && Endpoint.isSuccessStatus(status)) {\n\t\t\t\t\t\t\t\tawait publishConstructEvents<any, any>(\n\t\t\t\t\t\t\t\t\tendpoint as any,\n\t\t\t\t\t\t\t\t\toutput,\n\t\t\t\t\t\t\t\t\tserviceDiscovery,\n\t\t\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (HonoEndpoint.isDev) {\n\t\t\t\t\t\t\t\tlogger.info({ status, body: output }, 'Outgoing response');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Respect the endpoint's declared responseType. For JSON (default)\n\t\t\t\t\t\t\t// we use c.json() which sets Content-Type and serializes. For any\n\t\t\t\t\t\t\t// other type, emit the body as-is and set the header explicitly —\n\t\t\t\t\t\t\t// metadata.headers (from r.header()) applied above still wins.\n\t\t\t\t\t\t\tif (endpoint.responseType === 'application/json') {\n\t\t\t\t\t\t\t\t// Hono 4.13 types `c.json`'s status well enough that the\n\t\t\t\t\t\t\t\t// suppression here is now itself an error.\n\t\t\t\t\t\t\t\treturn c.json(output, status);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!(metadata.headers && hasContentTypeHeader(metadata.headers))\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tc.header('content-type', endpoint.responseType);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn c.body(output as any, status);\n\t\t\t\t\t\t} catch (validationError: any) {\n\t\t\t\t\t\t\tlogger.error(validationError, 'Output validation failed');\n\t\t\t\t\t\t\tconst error = wrapError(\n\t\t\t\t\t\t\t\tvalidationError,\n\t\t\t\t\t\t\t\t422,\n\t\t\t\t\t\t\t\t'Response validation failed',\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (HonoEndpoint.isDev) {\n\t\t\t\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t\t\t\t{ status: error.statusCode, body: error },\n\t\t\t\t\t\t\t\t\t'Outgoing response',\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn c.json(error, error.statusCode as ContentfulStatusCode);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\tlogger.error(e, 'Error processing endpoint request');\n\t\t\t\t\t\tconst error = wrapError(e, 500, 'Internal Server Error');\n\t\t\t\t\t\tif (HonoEndpoint.isDev) {\n\t\t\t\t\t\t\tlogger.info(\n\t\t\t\t\t\t\t\t{ status: error.statusCode, body: error },\n\t\t\t\t\t\t\t\t'Outgoing response',\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn c.json(error, error.statusCode as ContentfulStatusCode);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\t// Register route with conditional validators.\n\t\t//\n\t\t// `route` is a generic `TRoute`, and Hono 4.13 overloads `app.get` on\n\t\t// whether the first argument is a path or a handler. A generic that is\n\t\t// only *constrained* to string does not pick the path overload, so it\n\t\t// gets matched against the handler one and reported there. Saying it is a\n\t\t// string chooses the overload that was always intended.\n\t\t//\n\t\t// The spread is why a cast is needed rather than a better type: with\n\t\t// `...validators` of unknown length, the arity is not decidable, so the\n\t\t// first overload is chosen whatever the path argument says. Naming the\n\t\t// shape we are calling states the intent the overloads cannot infer.\n\t\t(\n\t\t\tapp[method] as unknown as (\n\t\t\t\tpath: string,\n\t\t\t\t...handlers: unknown[]\n\t\t\t) => unknown\n\t\t)(route, ...validators, handler);\n\t}\n\n\tstatic addDocsRoute<\n\t\tTServices extends Service[] = [],\n\t\tTLogger extends Logger = Logger,\n\t>(\n\t\tendpoints: Endpoint<string, HttpMethod, any, any, TServices, TLogger>[],\n\t\tapp: Hono,\n\t\tdocsPath: string,\n\t\topenApiOptions?: HonoEndpointOptions['openApiOptions'],\n\t): void {\n\t\tapp.get(docsPath, async (c) => {\n\t\t\ttry {\n\t\t\t\tconst openApiSchema = await Endpoint.buildOpenApiSchema(\n\t\t\t\t\tendpoints,\n\t\t\t\t\topenApiOptions,\n\t\t\t\t);\n\n\t\t\t\treturn c.json(openApiSchema);\n\t\t\t} catch {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ error: 'Failed to generate OpenAPI documentation' },\n\t\t\t\t\t500,\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
const
|
|
2
|
-
const require_Endpoint = require(
|
|
3
|
-
const require_lazyAccessors = require(
|
|
4
|
-
const require_processAudits = require(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-y5ARvAq5.cjs");
|
|
2
|
+
const require_Endpoint = require("./Endpoint-CtiPUpRX.cjs");
|
|
3
|
+
const require_lazyAccessors = require("./lazyAccessors-Dx9NLwJZ.cjs");
|
|
4
|
+
const require_processAudits = require("./processAudits-D_2W5x8k.cjs");
|
|
5
|
+
let _geekmidas_errors = require("@geekmidas/errors");
|
|
6
|
+
let hono_cookie = require("hono/cookie");
|
|
7
|
+
let _geekmidas_db_rls = require("@geekmidas/db/rls");
|
|
8
|
+
let _geekmidas_rate_limit = require("@geekmidas/rate-limit");
|
|
9
|
+
let _geekmidas_services = require("@geekmidas/services");
|
|
10
|
+
let hono = require("hono");
|
|
11
|
+
let hono_logger = require("hono/logger");
|
|
12
|
+
let hono_timing = require("hono/timing");
|
|
13
|
+
let hono_validator = require("hono/validator");
|
|
14
|
+
let node_path = require("node:path");
|
|
15
|
+
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
16
|
+
let fast_glob = require("fast-glob");
|
|
17
|
+
fast_glob = require_rolldown_runtime.__toESM(fast_glob, 1);
|
|
18
|
+
let qs = require("qs");
|
|
19
|
+
qs = require_rolldown_runtime.__toESM(qs, 1);
|
|
18
20
|
//#region src/endpoints/helpers.ts
|
|
19
21
|
/**
|
|
20
22
|
* Discovers and imports all Endpoint instances from the specified route patterns.
|
|
@@ -48,8 +50,7 @@ async function getEndpointsFromRoutes(routes, cwd) {
|
|
|
48
50
|
const stream = fast_glob.default.stream(routes, { cwd });
|
|
49
51
|
const endpoints = [];
|
|
50
52
|
for await (const f of stream) {
|
|
51
|
-
const
|
|
52
|
-
const route = await import(routePath);
|
|
53
|
+
const route = await import(node_path.default.resolve(cwd, f.toString()));
|
|
53
54
|
const handlers = Object.values(route).filter((value) => {
|
|
54
55
|
return require_Endpoint.Endpoint.isEndpoint(value);
|
|
55
56
|
});
|
|
@@ -57,7 +58,6 @@ async function getEndpointsFromRoutes(routes, cwd) {
|
|
|
57
58
|
}
|
|
58
59
|
return endpoints;
|
|
59
60
|
}
|
|
60
|
-
|
|
61
61
|
//#endregion
|
|
62
62
|
//#region src/endpoints/parseHonoQuery.ts
|
|
63
63
|
/**
|
|
@@ -71,7 +71,6 @@ function parseHonoQuery(c) {
|
|
|
71
71
|
const queryString = url.slice(queryIndex + 1);
|
|
72
72
|
return qs.default.parse(queryString);
|
|
73
73
|
}
|
|
74
|
-
|
|
75
74
|
//#endregion
|
|
76
75
|
//#region src/endpoints/HonoEndpointAdaptor.ts
|
|
77
76
|
/**
|
|
@@ -98,12 +97,13 @@ function analyzeEndpointFeatures(endpoint) {
|
|
|
98
97
|
};
|
|
99
98
|
}
|
|
100
99
|
var HonoEndpoint = class HonoEndpoint {
|
|
100
|
+
endpoint;
|
|
101
101
|
constructor(endpoint) {
|
|
102
102
|
this.endpoint = endpoint;
|
|
103
103
|
}
|
|
104
104
|
static isDev = process.env.NODE_ENV === "development";
|
|
105
105
|
static async validate(c, data, schema) {
|
|
106
|
-
if (!schema) return
|
|
106
|
+
if (!schema) return;
|
|
107
107
|
const parsed = await require_Endpoint.Endpoint.validate(schema, data);
|
|
108
108
|
if (parsed.issues) return c.json(parsed.issues, 422);
|
|
109
109
|
return parsed.value;
|
|
@@ -119,7 +119,7 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
119
119
|
static applyEventMiddleware(_app, _serviceDiscovery) {}
|
|
120
120
|
static async fromRoutes(routes, envParser, app = new hono.Hono(), _logger, cwd = process.cwd(), options) {
|
|
121
121
|
const endpoints = await getEndpointsFromRoutes(routes, cwd);
|
|
122
|
-
const serviceDiscovery =
|
|
122
|
+
const serviceDiscovery = _geekmidas_services.ServiceDiscovery.getInstance(envParser);
|
|
123
123
|
HonoEndpoint.addRoutes(endpoints, serviceDiscovery, app, options);
|
|
124
124
|
return app;
|
|
125
125
|
}
|
|
@@ -167,7 +167,7 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
167
167
|
path: c.req.path
|
|
168
168
|
});
|
|
169
169
|
c.header("X-Request-ID", requestId);
|
|
170
|
-
return (0,
|
|
170
|
+
return (0, _geekmidas_services.runWithRequestContext)({
|
|
171
171
|
logger,
|
|
172
172
|
requestId,
|
|
173
173
|
startTime
|
|
@@ -184,7 +184,7 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
184
184
|
cookie,
|
|
185
185
|
...rawDb !== void 0 && { db: rawDb }
|
|
186
186
|
});
|
|
187
|
-
|
|
187
|
+
if (!await endpoint.authorize({
|
|
188
188
|
header,
|
|
189
189
|
cookie,
|
|
190
190
|
services,
|
|
@@ -194,13 +194,12 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
194
194
|
body: features.hasBodyValidation ? c.req.valid("json") : void 0,
|
|
195
195
|
query: features.hasQueryValidation ? c.req.valid("query") : void 0,
|
|
196
196
|
params: features.hasParamValidation ? c.req.valid("param") : void 0
|
|
197
|
-
})
|
|
198
|
-
if (!isAuthorized) {
|
|
197
|
+
})) {
|
|
199
198
|
logger.warn("Forbidden access attempt");
|
|
200
199
|
return c.json({ error: "Forbidden" }, 403);
|
|
201
200
|
}
|
|
202
201
|
if (features.hasRateLimit) {
|
|
203
|
-
const rateLimitInfo = await (0,
|
|
202
|
+
const rateLimitInfo = await (0, _geekmidas_rate_limit.checkRateLimit)(endpoint.rateLimit, {
|
|
204
203
|
header,
|
|
205
204
|
services,
|
|
206
205
|
logger,
|
|
@@ -208,7 +207,7 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
208
207
|
path: c.req.path,
|
|
209
208
|
method: endpoint.method
|
|
210
209
|
});
|
|
211
|
-
const rateLimitHeaders = (0,
|
|
210
|
+
const rateLimitHeaders = (0, _geekmidas_rate_limit.getRateLimitHeaders)(rateLimitInfo, endpoint.rateLimit);
|
|
212
211
|
for (const [key, value] of Object.entries(rateLimitHeaders)) if (value) c.header(key, value);
|
|
213
212
|
}
|
|
214
213
|
const auditContext = features.hasAudits ? await require_processAudits.createAuditContext(endpoint, serviceDiscovery, logger, {
|
|
@@ -226,9 +225,8 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
226
225
|
cookie,
|
|
227
226
|
logger
|
|
228
227
|
}) : void 0;
|
|
229
|
-
const
|
|
230
|
-
const
|
|
231
|
-
const baseDb = sameDatabase ? auditor?.getTransaction?.() ?? rawDb : rawDb;
|
|
228
|
+
const { output, metadata } = await require_processAudits.executeWithAuditTransaction(auditContext, async (auditor) => {
|
|
229
|
+
const baseDb = auditContext?.storage?.databaseServiceName && auditContext.storage.databaseServiceName === endpoint.databaseService?.serviceName ? auditor?.getTransaction?.() ?? rawDb : rawDb;
|
|
232
230
|
const executeHandler = async (db) => {
|
|
233
231
|
const responseBuilder = new require_Endpoint.ResponseBuilder();
|
|
234
232
|
const response = await endpoint.handler({
|
|
@@ -244,33 +242,31 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
244
242
|
db
|
|
245
243
|
}, responseBuilder);
|
|
246
244
|
let data = response;
|
|
247
|
-
let metadata
|
|
245
|
+
let metadata = responseBuilder.getMetadata();
|
|
248
246
|
if (require_Endpoint.Endpoint.hasMetadata(response)) {
|
|
249
247
|
data = response.data;
|
|
250
|
-
metadata
|
|
248
|
+
metadata = response.metadata;
|
|
251
249
|
}
|
|
252
|
-
const output$1 = endpoint.outputSchema ? await endpoint.parseOutput(data) : void 0;
|
|
253
250
|
return {
|
|
254
|
-
output:
|
|
255
|
-
metadata
|
|
251
|
+
output: endpoint.outputSchema ? await endpoint.parseOutput(data) : void 0,
|
|
252
|
+
metadata,
|
|
256
253
|
responseBuilder
|
|
257
254
|
};
|
|
258
255
|
};
|
|
259
|
-
if (features.hasRls && rlsContext && baseDb) return (0,
|
|
256
|
+
if (features.hasRls && rlsContext && baseDb) return (0, _geekmidas_db_rls.withRlsContext)(baseDb, rlsContext, async (trx) => executeHandler(trx), { prefix: endpoint.rlsConfig?.prefix });
|
|
260
257
|
return executeHandler(baseDb);
|
|
261
|
-
}, async (result
|
|
258
|
+
}, async (result, auditor) => {
|
|
262
259
|
if (!audits?.length) return;
|
|
263
260
|
for (const audit of audits) {
|
|
264
|
-
if (audit.when && !audit.when(result
|
|
265
|
-
const payload = audit.payload(result
|
|
266
|
-
const entityId = audit.entityId?.(result
|
|
261
|
+
if (audit.when && !audit.when(result.output)) continue;
|
|
262
|
+
const payload = audit.payload(result.output);
|
|
263
|
+
const entityId = audit.entityId?.(result.output);
|
|
267
264
|
auditor.audit(audit.type, payload, {
|
|
268
265
|
table: audit.table,
|
|
269
266
|
entityId
|
|
270
267
|
});
|
|
271
268
|
}
|
|
272
269
|
}, { db: rawDb });
|
|
273
|
-
const { output, metadata } = result;
|
|
274
270
|
try {
|
|
275
271
|
let status = endpoint.status;
|
|
276
272
|
if (metadata.status) status = metadata.status;
|
|
@@ -286,7 +282,7 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
286
282
|
return c.body(output, status);
|
|
287
283
|
} catch (validationError) {
|
|
288
284
|
logger.error(validationError, "Output validation failed");
|
|
289
|
-
const error = (0,
|
|
285
|
+
const error = (0, _geekmidas_errors.wrapError)(validationError, 422, "Response validation failed");
|
|
290
286
|
if (HonoEndpoint.isDev) logger.info({
|
|
291
287
|
status: error.statusCode,
|
|
292
288
|
body: error
|
|
@@ -295,7 +291,7 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
295
291
|
}
|
|
296
292
|
} catch (e) {
|
|
297
293
|
logger.error(e, "Error processing endpoint request");
|
|
298
|
-
const error = (0,
|
|
294
|
+
const error = (0, _geekmidas_errors.wrapError)(e, 500, "Internal Server Error");
|
|
299
295
|
if (HonoEndpoint.isDev) logger.info({
|
|
300
296
|
status: error.statusCode,
|
|
301
297
|
body: error
|
|
@@ -317,12 +313,12 @@ var HonoEndpoint = class HonoEndpoint {
|
|
|
317
313
|
});
|
|
318
314
|
}
|
|
319
315
|
};
|
|
320
|
-
|
|
321
316
|
//#endregion
|
|
322
|
-
Object.defineProperty(exports,
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
317
|
+
Object.defineProperty(exports, "HonoEndpoint", {
|
|
318
|
+
enumerable: true,
|
|
319
|
+
get: function() {
|
|
320
|
+
return HonoEndpoint;
|
|
321
|
+
}
|
|
327
322
|
});
|
|
328
|
-
|
|
323
|
+
|
|
324
|
+
//# sourceMappingURL=HonoEndpointAdaptor-C9aivwKl.cjs.map
|