@geekmidas/constructs 10.0.0-alpha.4 → 10.0.0-alpha.41
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 +223 -158
- package/dist/{Construct-BD5neF7w.mjs → Construct-BO1X-kt9.mjs} +32 -33
- package/dist/Construct-BO1X-kt9.mjs.map +1 -0
- package/dist/Construct-BQALFCh2.d.cts +230 -0
- package/dist/Construct-BQALFCh2.d.cts.map +1 -0
- package/dist/{Construct-CyS3RpTL.cjs → Construct-DmvXceVY.cjs} +52 -47
- package/dist/Construct-DmvXceVY.cjs.map +1 -0
- package/dist/Construct-QXnl3VqT.d.mts +230 -0
- package/dist/Construct-QXnl3VqT.d.mts.map +1 -0
- package/dist/{Cron-B2OFsfDM.d.cts → Cron-CMEGfRs8.d.cts} +21 -8
- package/dist/Cron-CMEGfRs8.d.cts.map +1 -0
- package/dist/{Cron-ByxdOfpE.d.mts → Cron-D6X4-xjB.d.mts} +21 -8
- package/dist/Cron-D6X4-xjB.d.mts.map +1 -0
- package/dist/CronBuilder-CEK7aOqD.d.cts +46 -0
- package/dist/CronBuilder-CEK7aOqD.d.cts.map +1 -0
- package/dist/CronBuilder-DB35T5dL.cjs +116 -0
- package/dist/CronBuilder-DB35T5dL.cjs.map +1 -0
- package/dist/CronBuilder-Dv0IlZs0.mjs +104 -0
- package/dist/CronBuilder-Dv0IlZs0.mjs.map +1 -0
- package/dist/CronBuilder-O_gvButp.d.mts +46 -0
- package/dist/CronBuilder-O_gvButp.d.mts.map +1 -0
- package/dist/{Endpoint-Dij_wOcc.mjs → Endpoint-CQAeh1Rh.mjs} +117 -109
- package/dist/Endpoint-CQAeh1Rh.mjs.map +1 -0
- package/dist/{Endpoint-DODn1RhN.cjs → Endpoint-D1L9qu5C.cjs} +145 -131
- package/dist/Endpoint-D1L9qu5C.cjs.map +1 -0
- package/dist/{Endpoint-2Wg7T7Cq.d.mts → Endpoint-Dp5AKIXl.d.cts} +69 -93
- package/dist/Endpoint-Dp5AKIXl.d.cts.map +1 -0
- package/dist/{Endpoint-DrD8a1yH.d.cts → Endpoint-DtI7heFm.d.mts} +70 -94
- package/dist/Endpoint-DtI7heFm.d.mts.map +1 -0
- package/dist/{EndpointFactory-b4ituq-s.mjs → EndpointFactory-BBdNeaGJ.mjs} +39 -74
- package/dist/EndpointFactory-BBdNeaGJ.mjs.map +1 -0
- package/dist/{EndpointFactory-BHFMmFkV.cjs → EndpointFactory-BZOCOaK6.cjs} +75 -110
- package/dist/EndpointFactory-BZOCOaK6.cjs.map +1 -0
- package/dist/{index-BxHDdy6a.d.mts → EndpointFactory-CgMDvERK.d.mts} +63 -133
- package/dist/EndpointFactory-CgMDvERK.d.mts.map +1 -0
- package/dist/{index-B8g8POkr.d.cts → EndpointFactory-FeFRmlDZ.d.cts} +62 -132
- package/dist/EndpointFactory-FeFRmlDZ.d.cts.map +1 -0
- package/dist/{HonoEndpointAdaptor-BM2jbWht.mjs → HonoEndpointAdaptor-Aui-x9Lg.mjs} +41 -47
- package/dist/HonoEndpointAdaptor-Aui-x9Lg.mjs.map +1 -0
- package/dist/{HonoEndpointAdaptor-De6IlBZe.cjs → HonoEndpointAdaptor-Cq99r9H7.cjs} +50 -53
- package/dist/HonoEndpointAdaptor-Cq99r9H7.cjs.map +1 -0
- package/dist/Queue-C1uDgjxt.mjs +100 -0
- package/dist/Queue-C1uDgjxt.mjs.map +1 -0
- package/dist/Queue-Ckmudcm8.cjs +105 -0
- package/dist/Queue-Ckmudcm8.cjs.map +1 -0
- package/dist/{Queue-D7ZuwBhy.d.cts → Queue-CpQIGB_2.d.cts} +28 -40
- package/dist/Queue-CpQIGB_2.d.cts.map +1 -0
- package/dist/{Queue-gVGfi2Yk.d.mts → Queue-YmvN2vEP.d.mts} +28 -40
- package/dist/Queue-YmvN2vEP.d.mts.map +1 -0
- package/dist/QueueBuilder-CJNcv4dy.cjs +112 -0
- package/dist/QueueBuilder-CJNcv4dy.cjs.map +1 -0
- package/dist/QueueBuilder-CM0WUxfw.d.mts +62 -0
- package/dist/QueueBuilder-CM0WUxfw.d.mts.map +1 -0
- package/dist/QueueBuilder-XEnnOWGe.d.cts +62 -0
- package/dist/QueueBuilder-XEnnOWGe.d.cts.map +1 -0
- package/dist/QueueBuilder-XuPKZwKH.mjs +95 -0
- package/dist/QueueBuilder-XuPKZwKH.mjs.map +1 -0
- package/dist/{Subscriber-2mEi0ImH.d.cts → Subscriber-B91YSkZt.d.cts} +14 -16
- package/dist/Subscriber-B91YSkZt.d.cts.map +1 -0
- package/dist/{Subscriber-xTJ9ayPN.d.mts → Subscriber-BjHYe5hK.d.mts} +14 -16
- package/dist/Subscriber-BjHYe5hK.d.mts.map +1 -0
- package/dist/SubscriberBuilder-BSpQX1JT.d.cts +55 -0
- package/dist/SubscriberBuilder-BSpQX1JT.d.cts.map +1 -0
- package/dist/SubscriberBuilder-BhMphk4z.d.mts +55 -0
- package/dist/SubscriberBuilder-BhMphk4z.d.mts.map +1 -0
- package/dist/{SubscriberBuilder-4OPehf2R.cjs → SubscriberBuilder-Duk028pD.cjs} +34 -37
- package/dist/SubscriberBuilder-Duk028pD.cjs.map +1 -0
- package/dist/{SubscriberBuilder-BjkbeT9l.mjs → SubscriberBuilder-DzQUWE08.mjs} +23 -25
- package/dist/SubscriberBuilder-DzQUWE08.mjs.map +1 -0
- package/dist/Topic-CkxOTrMv.cjs +104 -0
- package/dist/Topic-CkxOTrMv.cjs.map +1 -0
- package/dist/Topic-hPffOsot.mjs +99 -0
- package/dist/Topic-hPffOsot.mjs.map +1 -0
- package/dist/adaptors/aws.cjs +171 -108
- package/dist/adaptors/aws.cjs.map +1 -1
- package/dist/adaptors/aws.d.cts +75 -43
- package/dist/adaptors/aws.d.cts.map +1 -1
- package/dist/adaptors/aws.d.mts +76 -44
- package/dist/adaptors/aws.d.mts.map +1 -1
- package/dist/adaptors/aws.mjs +143 -83
- package/dist/adaptors/aws.mjs.map +1 -1
- package/dist/adaptors/hono.cjs +3 -10
- package/dist/adaptors/hono.d.cts +7 -16
- package/dist/adaptors/hono.d.cts.map +1 -1
- package/dist/adaptors/hono.d.mts +8 -17
- package/dist/adaptors/hono.d.mts.map +1 -1
- package/dist/adaptors/hono.mjs +2 -10
- package/dist/adaptors/testing.cjs +515 -87
- package/dist/adaptors/testing.cjs.map +1 -1
- package/dist/adaptors/testing.d.cts +250 -48
- package/dist/adaptors/testing.d.cts.map +1 -1
- package/dist/adaptors/testing.d.mts +250 -48
- package/dist/adaptors/testing.d.mts.map +1 -1
- package/dist/adaptors/testing.mjs +484 -68
- package/dist/adaptors/testing.mjs.map +1 -1
- package/dist/auth-CMwml9QN.d.mts +188 -0
- package/dist/auth-CMwml9QN.d.mts.map +1 -0
- package/dist/auth-rVRDjIw_.d.cts +188 -0
- package/dist/auth-rVRDjIw_.d.cts.map +1 -0
- package/dist/auth.cjs +171 -31
- 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 +160 -24
- package/dist/auth.mjs.map +1 -1
- package/dist/{cache-BrRz3fEB.d.mts → cache-C9a_hVCc.d.cts} +4 -7
- package/dist/cache-C9a_hVCc.d.cts.map +1 -0
- package/dist/{cache-BtZY_tHe.d.cts → cache-CeTMI8LR.d.mts} +4 -7
- package/dist/cache-CeTMI8LR.d.mts.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-_3zgxzXl.d.mts} +20 -11
- package/dist/construct-interface-_3zgxzXl.d.mts.map +1 -0
- package/dist/{construct-interface-D9d4Gm4p.d.cts → construct-interface-_xi4BPN8.d.cts} +20 -11
- package/dist/construct-interface-_xi4BPN8.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 +63 -16
- package/dist/credential.cjs.map +1 -1
- package/dist/credential.d.cts +16 -9
- package/dist/credential.d.cts.map +1 -1
- package/dist/credential.d.mts +16 -9
- package/dist/credential.d.mts.map +1 -1
- package/dist/credential.mjs +58 -12
- 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 +40 -15
- 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 +28 -5
- 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 +8 -10
- package/dist/endpoints/index.d.cts +51 -7
- package/dist/endpoints/index.d.cts.map +1 -0
- package/dist/endpoints/index.d.mts +51 -7
- package/dist/endpoints/index.d.mts.map +1 -0
- package/dist/endpoints/index.mjs +6 -10
- package/dist/external-api-DS3mujT5.d.mts +86 -0
- package/dist/external-api-DS3mujT5.d.mts.map +1 -0
- package/dist/external-api-LBfE-q3g.d.cts +86 -0
- package/dist/external-api-LBfE-q3g.d.cts.map +1 -0
- package/dist/external-api.cjs +124 -0
- package/dist/external-api.cjs.map +1 -0
- package/dist/external-api.d.cts +2 -0
- package/dist/external-api.d.mts +2 -0
- package/dist/external-api.mjs +121 -0
- package/dist/external-api.mjs.map +1 -0
- 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-Ck21Uyq0.mjs → functions-DCIfCRR-.mjs} +371 -241
- package/dist/functions-DCIfCRR-.mjs.map +1 -0
- package/dist/{functions-DJJA7VGc.cjs → functions-ZH60FE7H.cjs} +409 -273
- package/dist/functions-ZH60FE7H.cjs.map +1 -0
- package/dist/{index-AIfVzkhi.d.cts → index-B0kxstwf.d.cts} +49 -42
- package/dist/index-B0kxstwf.d.cts.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-CubPzHd9.d.mts → index-CjVEjOw0.d.mts} +49 -42
- package/dist/index-CjVEjOw0.d.mts.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-BJ8IQ_1P.d.mts +159 -0
- package/dist/kysely-BJ8IQ_1P.d.mts.map +1 -0
- package/dist/kysely-DVF8wOT4.d.cts +159 -0
- package/dist/kysely-DVF8wOT4.d.cts.map +1 -0
- package/dist/{lazyAccessors-BoJN3SMd.mjs → lazyAccessors-CFanua0O.mjs} +20 -60
- package/dist/lazyAccessors-CFanua0O.mjs.map +1 -0
- package/dist/{lazyAccessors-e3j2oE2m.cjs → lazyAccessors-hJKGv8Ay.cjs} +60 -113
- package/dist/lazyAccessors-hJKGv8Ay.cjs.map +1 -0
- package/dist/mobile-app.cjs +70 -0
- package/dist/mobile-app.cjs.map +1 -0
- package/dist/mobile-app.d.cts +61 -0
- package/dist/mobile-app.d.cts.map +1 -0
- package/dist/mobile-app.d.mts +61 -0
- package/dist/mobile-app.d.mts.map +1 -0
- package/dist/mobile-app.mjs +69 -0
- package/dist/mobile-app.mjs.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 +6 -189
- package/dist/queue/index.d.cts +3 -60
- package/dist/queue/index.d.mts +3 -60
- package/dist/queue/index.mjs +3 -186
- package/dist/rest-api.cjs +87 -63
- package/dist/rest-api.cjs.map +1 -1
- package/dist/rest-api.d.cts +62 -61
- package/dist/rest-api.d.cts.map +1 -1
- package/dist/rest-api.d.mts +62 -61
- package/dist/rest-api.d.mts.map +1 -1
- package/dist/rest-api.mjs +79 -55
- 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 +3 -137
- package/dist/topic/index.d.cts +2 -32
- package/dist/topic/index.d.mts +2 -32
- package/dist/topic/index.mjs +2 -134
- 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 +118 -35
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +95 -42
- package/dist/worker.d.cts.map +1 -1
- package/dist/worker.d.mts +95 -42
- package/dist/worker.d.mts.map +1 -1
- package/dist/worker.mjs +113 -30
- package/dist/worker.mjs.map +1 -1
- package/package.json +66 -41
- package/dist/Construct-BD5neF7w.mjs.map +0 -1
- package/dist/Construct-C0ijr2qp.d.cts +0 -117
- package/dist/Construct-C0ijr2qp.d.cts.map +0 -1
- package/dist/Construct-Ct8nalEi.d.mts +0 -117
- package/dist/Construct-Ct8nalEi.d.mts.map +0 -1
- package/dist/Construct-CyS3RpTL.cjs.map +0 -1
- package/dist/Cron-B2OFsfDM.d.cts.map +0 -1
- package/dist/Cron-ByxdOfpE.d.mts.map +0 -1
- package/dist/CronBuilder-BL0AP6fs.d.mts +0 -44
- package/dist/CronBuilder-BL0AP6fs.d.mts.map +0 -1
- package/dist/CronBuilder-CdibiHNB.mjs +0 -84
- package/dist/CronBuilder-CdibiHNB.mjs.map +0 -1
- package/dist/CronBuilder-DyUr6nYz.cjs +0 -96
- package/dist/CronBuilder-DyUr6nYz.cjs.map +0 -1
- package/dist/CronBuilder-LSJMfqnq.d.cts +0 -44
- package/dist/CronBuilder-LSJMfqnq.d.cts.map +0 -1
- package/dist/Endpoint-2Wg7T7Cq.d.mts.map +0 -1
- package/dist/Endpoint-DODn1RhN.cjs.map +0 -1
- package/dist/Endpoint-Dij_wOcc.mjs.map +0 -1
- package/dist/Endpoint-DrD8a1yH.d.cts.map +0 -1
- package/dist/EndpointFactory-BHFMmFkV.cjs.map +0 -1
- package/dist/EndpointFactory-b4ituq-s.mjs.map +0 -1
- package/dist/HonoEndpointAdaptor-BM2jbWht.mjs.map +0 -1
- package/dist/HonoEndpointAdaptor-De6IlBZe.cjs.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 +0 -62
- package/dist/SubscriberBuilder-Dptmo-1A.d.mts.map +0 -1
- package/dist/SubscriberBuilder-waNhzjSM.d.cts +0 -62
- package/dist/SubscriberBuilder-waNhzjSM.d.cts.map +0 -1
- package/dist/Topic-19QeHBIR.d.cts +0 -91
- package/dist/Topic-19QeHBIR.d.cts.map +0 -1
- package/dist/Topic-DuFeqkBh.d.mts +0 -91
- 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-Ck21Uyq0.mjs.map +0 -1
- package/dist/functions-DJJA7VGc.cjs.map +0 -1
- package/dist/index-AIfVzkhi.d.cts.map +0 -1
- package/dist/index-B8g8POkr.d.cts.map +0 -1
- package/dist/index-BxHDdy6a.d.mts.map +0 -1
- package/dist/index-CubPzHd9.d.mts.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/queue/index.cjs.map +0 -1
- package/dist/queue/index.d.cts.map +0 -1
- package/dist/queue/index.d.mts.map +0 -1
- package/dist/queue/index.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.cjs.map +0 -1
- package/dist/topic/index.d.cts.map +0 -1
- package/dist/topic/index.d.mts.map +0 -1
- package/dist/topic/index.mjs.map +0 -1
- package/dist/types-BlAkSuGI.d.cts.map +0 -1
- package/dist/types-aKksMEWL.d.mts.map +0 -1
package/dist/crons/index.d.mts
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import "../
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import { i as ScheduleExpression, n as CronExpression, r as RateExpression, t as Cron } from "../Cron-D6X4-xjB.mjs";
|
|
2
|
+
import { t as CronBuilder } from "../CronBuilder-O_gvButp.mjs";
|
|
3
|
+
//#region src/crons/schedule.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* A schedule a cron runner can take, as standard five-field cron.
|
|
6
|
+
*
|
|
7
|
+
* `ScheduleExpression` has two spellings. `cron(m h dom mon dow)` is already
|
|
8
|
+
* five-field cron and unwraps; `rate(n unit)` is an interval, and an interval
|
|
9
|
+
* is not a schedule — it says how often, where cron says when.
|
|
10
|
+
*
|
|
11
|
+
* Most intervals still have an exact cron equivalent, because they divide their
|
|
12
|
+
* unit evenly: `rate(5 minutes)` is every fifth minute of every hour, and that
|
|
13
|
+
* is `*/5 * * * *` precisely. `rate(7 hours)` has none. There is no cron field
|
|
14
|
+
* that means "every seven hours" — `*/7` in the hour field fires at 0, 7, 14
|
|
15
|
+
* and 21 and then starts over at midnight, so the gap between the last firing
|
|
16
|
+
* of one day and the first of the next is three hours rather than seven.
|
|
17
|
+
*
|
|
18
|
+
* Those are refused rather than rounded. A job that runs at the wrong hour is
|
|
19
|
+
* far harder to notice than one that refused to build, and a schedule quietly
|
|
20
|
+
* adjusted by the framework is a bug nobody goes looking for.
|
|
21
|
+
*/
|
|
22
|
+
export declare class UnrepresentableSchedule extends Error {
|
|
23
|
+
readonly schedule: string;
|
|
24
|
+
constructor(schedule: string, reason: string);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Standard five-field cron for a schedule expression.
|
|
28
|
+
*
|
|
29
|
+
* @throws {UnrepresentableSchedule} when a `rate(…)` has no exact equivalent.
|
|
30
|
+
*/
|
|
31
|
+
export declare function toCronExpression(schedule: ScheduleExpression): string;
|
|
14
32
|
//#endregion
|
|
15
|
-
export { Cron, CronBuilder, CronExpression, RateExpression, ScheduleExpression
|
|
33
|
+
export { Cron, CronBuilder, type CronExpression, type RateExpression, type ScheduleExpression };
|
|
16
34
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/crons/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/crons/schedule.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;qBAoBa,gCAAgC;WAElC;EADV,YACU,kBACT;;;;;;;wBAuBc,iBAAiB,UAAU"}
|
package/dist/crons/index.mjs
CHANGED
|
@@ -1,12 +1,68 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { n as Cron, t as CronBuilder } from "../CronBuilder-Dv0IlZs0.mjs";
|
|
2
|
+
//#region src/crons/schedule.ts
|
|
3
|
+
/**
|
|
4
|
+
* A schedule a cron runner can take, as standard five-field cron.
|
|
5
|
+
*
|
|
6
|
+
* `ScheduleExpression` has two spellings. `cron(m h dom mon dow)` is already
|
|
7
|
+
* five-field cron and unwraps; `rate(n unit)` is an interval, and an interval
|
|
8
|
+
* is not a schedule — it says how often, where cron says when.
|
|
9
|
+
*
|
|
10
|
+
* Most intervals still have an exact cron equivalent, because they divide their
|
|
11
|
+
* unit evenly: `rate(5 minutes)` is every fifth minute of every hour, and that
|
|
12
|
+
* is `*/5 * * * *` precisely. `rate(7 hours)` has none. There is no cron field
|
|
13
|
+
* that means "every seven hours" — `*/7` in the hour field fires at 0, 7, 14
|
|
14
|
+
* and 21 and then starts over at midnight, so the gap between the last firing
|
|
15
|
+
* of one day and the first of the next is three hours rather than seven.
|
|
16
|
+
*
|
|
17
|
+
* Those are refused rather than rounded. A job that runs at the wrong hour is
|
|
18
|
+
* far harder to notice than one that refused to build, and a schedule quietly
|
|
19
|
+
* adjusted by the framework is a bug nobody goes looking for.
|
|
20
|
+
*/
|
|
21
|
+
var UnrepresentableSchedule = class extends Error {
|
|
22
|
+
schedule;
|
|
23
|
+
constructor(schedule, reason) {
|
|
24
|
+
super(`\`${schedule}\` has no exact cron equivalent: ${reason}.\n\nCron says *when*, not *how often*, so an interval is only exact when it divides its unit evenly.
|
|
25
|
+
Write the schedule you mean instead — \`cron(0 */6 * * *)\` for every sixth hour, say — or pick an interval that divides: minutes into 60, hours into 24.`);
|
|
26
|
+
this.schedule = schedule;
|
|
27
|
+
this.name = "UnrepresentableSchedule";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/** Units `rate(…)` accepts, singular or plural. */
|
|
31
|
+
const UNITS = [
|
|
32
|
+
"minute",
|
|
33
|
+
"hour",
|
|
34
|
+
"day"
|
|
35
|
+
];
|
|
36
|
+
/**
|
|
37
|
+
* Standard five-field cron for a schedule expression.
|
|
38
|
+
*
|
|
39
|
+
* @throws {UnrepresentableSchedule} when a `rate(…)` has no exact equivalent.
|
|
40
|
+
*/
|
|
41
|
+
function toCronExpression(schedule) {
|
|
42
|
+
const cron = /^cron\((.+)\)$/.exec(schedule);
|
|
43
|
+
if (cron?.[1]) return cron[1].trim();
|
|
44
|
+
const rate = /^rate\(\s*(\d+)\s+(\w+?)s?\s*\)$/.exec(schedule);
|
|
45
|
+
if (!rate) throw new UnrepresentableSchedule(schedule, "it is neither `cron(…)` nor `rate(n unit)`");
|
|
46
|
+
const every = Number(rate[1]);
|
|
47
|
+
const unit = rate[2];
|
|
48
|
+
/* c8 ignore next */ if (!unit) throw new UnrepresentableSchedule(schedule, "no unit");
|
|
49
|
+
if (!UNITS.includes(unit)) throw new UnrepresentableSchedule(schedule, `\`${unit}\` is not one of ${UNITS.join(", ")}`);
|
|
50
|
+
if (every < 1) throw new UnrepresentableSchedule(schedule, "an interval must be at least 1");
|
|
51
|
+
switch (unit) {
|
|
52
|
+
case "minute":
|
|
53
|
+
if (every === 1) return "* * * * *";
|
|
54
|
+
if (60 % every !== 0) throw new UnrepresentableSchedule(schedule, `${every} does not divide 60, so the interval would reset at the top of each hour`);
|
|
55
|
+
return `*/${every} * * * *`;
|
|
56
|
+
case "hour":
|
|
57
|
+
if (every === 1) return "0 * * * *";
|
|
58
|
+
if (24 % every !== 0) throw new UnrepresentableSchedule(schedule, `${every} does not divide 24, so the interval would reset at midnight`);
|
|
59
|
+
return `0 */${every} * * *`;
|
|
60
|
+
case "day":
|
|
61
|
+
if (every === 1) return "0 0 * * *";
|
|
62
|
+
throw new UnrepresentableSchedule(schedule, "day-of-month restarts every month, so no multi-day interval is even");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
10
65
|
//#endregion
|
|
11
|
-
export { Cron, CronBuilder,
|
|
66
|
+
export { Cron, CronBuilder, UnrepresentableSchedule, toCronExpression };
|
|
67
|
+
|
|
12
68
|
//# sourceMappingURL=index.mjs.map
|
package/dist/crons/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/crons/
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/crons/schedule.ts"],"sourcesContent":["import type { ScheduleExpression } from './Cron';\n\n/**\n * A schedule a cron runner can take, as standard five-field cron.\n *\n * `ScheduleExpression` has two spellings. `cron(m h dom mon dow)` is already\n * five-field cron and unwraps; `rate(n unit)` is an interval, and an interval\n * is not a schedule — it says how often, where cron says when.\n *\n * Most intervals still have an exact cron equivalent, because they divide their\n * unit evenly: `rate(5 minutes)` is every fifth minute of every hour, and that\n * is `*/5 * * * *` precisely. `rate(7 hours)` has none. There is no cron field\n * that means \"every seven hours\" — `*/7` in the hour field fires at 0, 7, 14\n * and 21 and then starts over at midnight, so the gap between the last firing\n * of one day and the first of the next is three hours rather than seven.\n *\n * Those are refused rather than rounded. A job that runs at the wrong hour is\n * far harder to notice than one that refused to build, and a schedule quietly\n * adjusted by the framework is a bug nobody goes looking for.\n */\nexport class UnrepresentableSchedule extends Error {\n\tconstructor(\n\t\treadonly schedule: string,\n\t\treason: string,\n\t) {\n\t\tsuper(\n\t\t\t`\\`${schedule}\\` has no exact cron equivalent: ${reason}.\\n\\n` +\n\t\t\t\t'Cron says *when*, not *how often*, so an interval is only exact when ' +\n\t\t\t\t'it divides its unit evenly.\\n' +\n\t\t\t\t'Write the schedule you mean instead — `cron(0 */6 * * *)` for every ' +\n\t\t\t\t'sixth hour, say — or pick an interval that divides: minutes into 60, ' +\n\t\t\t\t'hours into 24.',\n\t\t);\n\t\tthis.name = 'UnrepresentableSchedule';\n\t}\n}\n\n/** Units `rate(…)` accepts, singular or plural. */\nconst UNITS = ['minute', 'hour', 'day'] as const;\ntype Unit = (typeof UNITS)[number];\n\n/**\n * Standard five-field cron for a schedule expression.\n *\n * @throws {UnrepresentableSchedule} when a `rate(…)` has no exact equivalent.\n */\nexport function toCronExpression(schedule: ScheduleExpression): string {\n\tconst cron = /^cron\\((.+)\\)$/.exec(schedule);\n\tif (cron?.[1]) return cron[1].trim();\n\n\tconst rate = /^rate\\(\\s*(\\d+)\\s+(\\w+?)s?\\s*\\)$/.exec(schedule);\n\tif (!rate) {\n\t\tthrow new UnrepresentableSchedule(\n\t\t\tschedule,\n\t\t\t'it is neither `cron(…)` nor `rate(n unit)`',\n\t\t);\n\t}\n\n\tconst every = Number(rate[1]);\n\tconst unit = rate[2] as Unit;\n\t/* c8 ignore next */ if (!unit)\n\t\tthrow new UnrepresentableSchedule(schedule, 'no unit');\n\n\tif (!UNITS.includes(unit)) {\n\t\tthrow new UnrepresentableSchedule(\n\t\t\tschedule,\n\t\t\t`\\`${unit}\\` is not one of ${UNITS.join(', ')}`,\n\t\t);\n\t}\n\n\tif (every < 1) {\n\t\tthrow new UnrepresentableSchedule(\n\t\t\tschedule,\n\t\t\t'an interval must be at least 1',\n\t\t);\n\t}\n\n\tswitch (unit) {\n\t\tcase 'minute':\n\t\t\tif (every === 1) return '* * * * *';\n\t\t\tif (60 % every !== 0) {\n\t\t\t\tthrow new UnrepresentableSchedule(\n\t\t\t\t\tschedule,\n\t\t\t\t\t`${every} does not divide 60, so the interval would reset at the top of each hour`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn `*/${every} * * * *`;\n\n\t\tcase 'hour':\n\t\t\tif (every === 1) return '0 * * * *';\n\t\t\tif (24 % every !== 0) {\n\t\t\t\tthrow new UnrepresentableSchedule(\n\t\t\t\t\tschedule,\n\t\t\t\t\t`${every} does not divide 24, so the interval would reset at midnight`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn `0 */${every} * * *`;\n\n\t\tcase 'day':\n\t\t\tif (every === 1) return '0 0 * * *';\n\t\t\t// `*/n` in day-of-month restarts on the 1st, so a 2-day interval fires\n\t\t\t// on the 1st and 3rd of a 31-day month and then again on the 1st — one\n\t\t\t// day later, not two. No month length makes that come out even.\n\t\t\tthrow new UnrepresentableSchedule(\n\t\t\t\tschedule,\n\t\t\t\t'day-of-month restarts every month, so no multi-day interval is even',\n\t\t\t);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBA,IAAa,0BAAb,cAA6C,MAAM;CAExC;CADV,YACC,UACA,QACC;EACD,MACC,KAAK,SAAS,mCAAmC,OAAO;0JAMzD;EAVS,KAAA,WAAA;EAWT,KAAK,OAAO;CACb;AACD;;AAGA,MAAM,QAAQ;CAAC;CAAU;CAAQ;AAAK;;;;;;AAQtC,SAAgB,iBAAiB,UAAsC;CACtE,MAAM,OAAO,iBAAiB,KAAK,QAAQ;CAC3C,IAAI,OAAO,IAAI,OAAO,KAAK,EAAE,CAAC,KAAK;CAEnC,MAAM,OAAO,mCAAmC,KAAK,QAAQ;CAC7D,IAAI,CAAC,MACJ,MAAM,IAAI,wBACT,UACA,4CACD;CAGD,MAAM,QAAQ,OAAO,KAAK,EAAE;CAC5B,MAAM,OAAO,KAAK;sBACG,IAAI,CAAC,MACzB,MAAM,IAAI,wBAAwB,UAAU,SAAS;CAEtD,IAAI,CAAC,MAAM,SAAS,IAAI,GACvB,MAAM,IAAI,wBACT,UACA,KAAK,KAAK,mBAAmB,MAAM,KAAK,IAAI,GAC7C;CAGD,IAAI,QAAQ,GACX,MAAM,IAAI,wBACT,UACA,gCACD;CAGD,QAAQ,MAAR;EACC,KAAK;GACJ,IAAI,UAAU,GAAG,OAAO;GACxB,IAAI,KAAK,UAAU,GAClB,MAAM,IAAI,wBACT,UACA,GAAG,MAAM,yEACV;GAED,OAAO,KAAK,MAAM;EAEnB,KAAK;GACJ,IAAI,UAAU,GAAG,OAAO;GACxB,IAAI,KAAK,UAAU,GAClB,MAAM,IAAI,wBACT,UACA,GAAG,MAAM,6DACV;GAED,OAAO,OAAO,MAAM;EAErB,KAAK;GACJ,IAAI,UAAU,GAAG,OAAO;GAIxB,MAAM,IAAI,wBACT,UACA,qEACD;CACF;AACD"}
|
package/dist/database/kysely.cjs
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rolldown_runtime = require("../rolldown-runtime-y5ARvAq5.cjs");
|
|
3
|
+
const require_cache = require("../cache.cjs");
|
|
4
|
+
let _geekmidas_manifest = require("@geekmidas/manifest");
|
|
5
|
+
let kysely = require("kysely");
|
|
6
|
+
let pg = require("pg");
|
|
7
|
+
pg = require_rolldown_runtime.__toESM(pg, 1);
|
|
7
8
|
//#region src/database/kysely.ts
|
|
9
|
+
/**
|
|
10
|
+
* `KyselyDatabase` — a declared Postgres database, typed by its schema.
|
|
11
|
+
*
|
|
12
|
+
* It declares a logical database, a schema, and the roles that reach it, and
|
|
13
|
+
* hands back a Kysely client built from the one URL the adapter supplied. It
|
|
14
|
+
* names no cloud: `--target=aws` fills that URL from RDS, local dev from the
|
|
15
|
+
* Postgres container.
|
|
16
|
+
*
|
|
17
|
+
* Transactions and RLS context are the execution wrapper's job — it opens the
|
|
18
|
+
* transaction and puts it in `ctx.db`. This construct does not resolve
|
|
19
|
+
* connections per request.
|
|
20
|
+
*/
|
|
8
21
|
/** The schema a database uses when it does not say otherwise. */
|
|
9
22
|
const DEFAULT_SCHEMA = "app";
|
|
10
23
|
/**
|
|
@@ -15,6 +28,7 @@ const DEFAULT_SCHEMA = "app";
|
|
|
15
28
|
* through `.database()`, which infers from the service.
|
|
16
29
|
*/
|
|
17
30
|
var KyselyDatabase = class KyselyDatabase {
|
|
31
|
+
options;
|
|
18
32
|
id;
|
|
19
33
|
service;
|
|
20
34
|
/**
|
|
@@ -28,18 +42,18 @@ var KyselyDatabase = class KyselyDatabase {
|
|
|
28
42
|
derivedFrom;
|
|
29
43
|
constructor(id, options = {}, derivedFrom) {
|
|
30
44
|
this.options = options;
|
|
31
|
-
const canonical = (0,
|
|
45
|
+
const canonical = (0, _geekmidas_manifest.canonicalId)(id);
|
|
32
46
|
this.id = canonical;
|
|
33
47
|
this.config = {
|
|
34
|
-
url: (0,
|
|
35
|
-
ownerUrl: (0,
|
|
48
|
+
url: (0, _geekmidas_manifest.provideKey)(canonical, "url"),
|
|
49
|
+
ownerUrl: (0, _geekmidas_manifest.provideKey)(canonical, "ownerUrl")
|
|
36
50
|
};
|
|
37
51
|
this.schemaName = options.schema ?? DEFAULT_SCHEMA;
|
|
38
52
|
this.roles = options.roles ?? true;
|
|
39
|
-
this.version = options.version ??
|
|
53
|
+
this.version = options.version ?? _geekmidas_manifest.DEFAULT_POSTGRES_VERSION;
|
|
40
54
|
this.derivedFrom = derivedFrom;
|
|
41
55
|
this.service = {
|
|
42
|
-
serviceName: (0,
|
|
56
|
+
serviceName: (0, _geekmidas_manifest.serviceKey)(canonical),
|
|
43
57
|
register: (registerOptions) => this.connect(registerOptions)
|
|
44
58
|
};
|
|
45
59
|
}
|
|
@@ -139,18 +153,29 @@ var KyselyDatabase = class KyselyDatabase {
|
|
|
139
153
|
*/
|
|
140
154
|
get owner() {
|
|
141
155
|
return {
|
|
142
|
-
serviceName: `${(0,
|
|
156
|
+
serviceName: `${(0, _geekmidas_manifest.serviceKey)(this.id)}Owner`,
|
|
143
157
|
register: (options) => this.connect(options, { owner: true })
|
|
144
158
|
};
|
|
145
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* What this database's clients are built with besides a dialect — the
|
|
162
|
+
* plugins and logging it was declared with.
|
|
163
|
+
*
|
|
164
|
+
* Public so that whatever opens a connection to it outside \`connect()\` —
|
|
165
|
+
* a test's transaction — builds the same client. A test that dropped the
|
|
166
|
+
* plugins would write \`createdAt\` where production writes \`created_at\`.
|
|
167
|
+
*/
|
|
168
|
+
get clientConfig() {
|
|
169
|
+
const { schema: _schema, roles: _roles, version: _version, ...kysely$1 } = this.options;
|
|
170
|
+
return kysely$1;
|
|
171
|
+
}
|
|
146
172
|
async connect(options, as = {}) {
|
|
147
173
|
const { url, ownerUrl } = options.envParser.create((get) => ({
|
|
148
174
|
url: get(this.config.url).string(),
|
|
149
175
|
ownerUrl: get(this.config.ownerUrl).string().optional()
|
|
150
176
|
})).parse();
|
|
151
|
-
const { schema: _schema, roles: _roles,...kysely$1 } = this.options;
|
|
152
177
|
return new kysely.Kysely({
|
|
153
|
-
...
|
|
178
|
+
...this.clientConfig,
|
|
154
179
|
dialect: new kysely.PostgresDialect({ pool: pool(as.owner ? ownerUrl ?? url : url) })
|
|
155
180
|
});
|
|
156
181
|
}
|
|
@@ -175,7 +200,7 @@ function pool(url) {
|
|
|
175
200
|
options: `-c search_path=${searchPath}`
|
|
176
201
|
});
|
|
177
202
|
}
|
|
178
|
-
|
|
179
203
|
//#endregion
|
|
180
204
|
exports.KyselyDatabase = KyselyDatabase;
|
|
205
|
+
|
|
181
206
|
//# sourceMappingURL=kysely.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kysely.cjs","names":["id: ConstructName<TName>","options: KyselyDatabaseOptions","derivedFrom?: DerivedFrom","DEFAULT_POSTGRES_VERSION","id: ConstructName<TCache>","options: { table?: string }","Cache","id: ConstructName<TTenant>","options: ServiceRegisterOptions","as: { owner?: boolean }","kysely","Kysely","PostgresDialect","url: string"],"sources":["../../src/database/kysely.ts"],"sourcesContent":["/**\n * `KyselyDatabase` — a declared Postgres database, typed by its schema.\n *\n * It declares a logical database, a schema, and the roles that reach it, and\n * hands back a Kysely client built from the one URL the adapter supplied. It\n * names no cloud: `--target=aws` fills that URL from RDS, local dev from the\n * Postgres container.\n *\n * Transactions and RLS context are the execution wrapper's job — it opens the\n * transaction and puts it in `ctx.db`. This construct does not resolve\n * connections per request.\n */\n\nimport {\n\ttype ConstructName,\n\tcanonicalId,\n\tDEFAULT_POSTGRES_VERSION,\n\ttype Declaration,\n\ttype PostgresVersion,\n\tprovideKey,\n\tserviceKey,\n} from '@geekmidas/manifest';\nimport type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport { Kysely, type KyselyConfig, PostgresDialect } from 'kysely';\nimport pg from 'pg';\nimport { Cache } from '../cache';\nimport type { Construct } from '../construct-interface';\n\n/** The schema a database uses when it does not say otherwise. */\nconst DEFAULT_SCHEMA = 'app';\n\n/**\n * Everything Kysely takes, plus what this construct declares.\n *\n * `dialect` is omitted because the construct owns it — it is built from the one\n * URL the adapter supplied, which is the whole point of the construct. The rest\n * of `KyselyConfig` (`plugins`, `log`) is the app's business and passes\n * straight through, so anything Kysely adds later arrives without being\n * tracked here.\n */\nexport interface KyselyDatabaseOptions extends Omit<KyselyConfig, 'dialect'> {\n\t/**\n\t * The schema, pinned on both roles' `search_path`.\n\t *\n\t * Defaults to `app` — the role the schema plays, rather than a restatement\n\t * of the database's own name, which reads correctly beside `auth` and\n\t * `pgboss` and keeps the application off `public`.\n\t */\n\tschema?: string;\n\t/**\n\t * Provision the owner/runtime role split. Defaults to on.\n\t *\n\t * Off falls back to the cluster's master credential in both URLs, giving up\n\t * the DDL/DML split and putting credentials that can drop a table into the\n\t * function's environment. A deliberate downgrade, not a default.\n\t */\n\troles?: boolean;\n\t/**\n\t * The Postgres major version to provision.\n\t *\n\t * Declared here so one statement reaches both targets. It was previously\n\t * set in two unrelated places — a container tag locally, nothing at all on\n\t * AWS (so Aurora chose) — which is how local came to run 18 while deployed\n\t * ran 17.7 with nothing recording the difference.\n\t *\n\t * Defaults to {@link DEFAULT_POSTGRES_VERSION}.\n\t */\n\tversion?: PostgresVersion;\n}\n\n/** What makes a construct derived rather than a database in its own right. */\ninterface DerivedFrom {\n\tkind: 'database-reader' | 'database-schema';\n\tof: string;\n\tschema?: string;\n}\n\n/**\n * @typeParam DB - the database's schema.\n * @typeParam TName - the canonical id. TypeScript has no partial\n * type-argument inference, so `new KyselyDatabase<OrdersDB>('orders')` leaves\n * this at its default and the service key widens to `string`. `db` still types\n * through `.database()`, which infers from the service.\n */\nexport class KyselyDatabase<DB = unknown, TName extends string = string>\n\timplements Construct<TName, Kysely<DB>>\n{\n\treadonly id: TName;\n\treadonly service: Service<Uncapitalize<TName>, Kysely<DB>>;\n\n\t/**\n\t * Declared once and read by both `declare()` and `connect()`, so the key the\n\t * build publishes and the key the client reads cannot drift.\n\t */\n\tprivate readonly config: { url: string; ownerUrl: string };\n\tprivate readonly schemaName: string;\n\tprivate readonly roles: boolean;\n\tprivate readonly version: PostgresVersion;\n\tprivate readonly derivedFrom?: DerivedFrom;\n\n\tconstructor(\n\t\tid: ConstructName<TName>,\n\t\tprivate readonly options: KyselyDatabaseOptions = {},\n\t\tderivedFrom?: DerivedFrom,\n\t) {\n\t\t// Canonicalises, so `orders` and `Orders` are one construct rather than\n\t\t// two that collide. Throws on anything that cannot become a valid id.\n\t\tconst canonical = canonicalId(id as string);\n\n\t\tthis.id = canonical as TName;\n\t\tthis.config = {\n\t\t\turl: provideKey(canonical, 'url'),\n\t\t\townerUrl: provideKey(canonical, 'ownerUrl'),\n\t\t};\n\t\tthis.schemaName = options.schema ?? DEFAULT_SCHEMA;\n\t\tthis.roles = options.roles ?? true;\n\t\tthis.version = options.version ?? DEFAULT_POSTGRES_VERSION;\n\t\tthis.derivedFrom = derivedFrom;\n\n\t\t// A field, not a getter: service discovery caches by object identity.\n\t\tthis.service = {\n\t\t\tserviceName: serviceKey(canonical) as Uncapitalize<TName>,\n\t\t\t// Forwards the whole options object — cherry-picking `envParser` strips\n\t\t\t// `context` and with it the request-scoped logger.\n\t\t\tregister: (registerOptions) => this.connect(registerOptions),\n\t\t};\n\t}\n\n\tdeclare(): Declaration[] {\n\t\tif (this.derivedFrom) {\n\t\t\tconst { kind, of, schema } = this.derivedFrom;\n\n\t\t\treturn [\n\t\t\t\tkind === 'database-schema'\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\tid: this.id,\n\t\t\t\t\t\t\tof,\n\t\t\t\t\t\t\tschema: schema ?? this.schemaName,\n\t\t\t\t\t\t\t// The runtime key alone — see the note below on the parent.\n\t\t\t\t\t\t\tprovides: [this.config.url],\n\t\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\tid: this.id,\n\t\t\t\t\t\t\tof,\n\t\t\t\t\t\t\t// A reader has no owner URL of its own — nothing migrates\n\t\t\t\t\t\t\t// through a read-only endpoint — so this is the one key.\n\t\t\t\t\t\t\tprovides: [this.config.url],\n\t\t\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: 'database',\n\t\t\t\tid: this.id,\n\t\t\t\tengine: 'postgres',\n\t\t\t\tschema: this.schemaName,\n\t\t\t\tversion: this.version,\n\t\t\t\t// One key, the runtime role's. `config` also holds the owner key and\n\t\t\t\t// it is deliberately absent here: a key in `provides` is a key an\n\t\t\t\t// edge can name, and nothing should be able to depend on DDL rights.\n\t\t\t\tprovides: [this.config.url],\n\t\t\t\t...(this.roles ? {} : { roles: false }),\n\t\t\t},\n\t\t];\n\t}\n\n\t/**\n\t * A read-only endpoint on this database.\n\t *\n\t * Read-only is enforced by the reader role's grants rather than by which\n\t * endpoint it resolves to, so falling back to the writer where no replica\n\t * exists is safe rather than a silently writable connection behind a name\n\t * that says reader. There is no `writer()`: the database *is* the writer, so\n\t * a replica can never be reached by accident.\n\t *\n\t * The return type is narrower than this class on purpose — see\n\t * {@link ReadOnlyDatabase}.\n\t */\n\treader(): ReadOnlyDatabase<DB, `${TName}Reader`> {\n\t\treturn new KyselyDatabase<DB, `${TName}Reader`>(\n\t\t\t`${this.id}Reader` as ConstructName<`${TName}Reader`>,\n\t\t\tthis.options,\n\t\t\t{ kind: 'database-reader', of: this.id },\n\t\t);\n\t}\n\n\t/**\n\t * A cache that lives in this database.\n\t *\n\t * The same strengthening `schema()` is over a second database: `new\n\t * Cache('Sessions')` says the app caches and leaves where to the deployment,\n\t * while this says it caches *here* — which is a fact about the application\n\t * and so belongs in its code.\n\t *\n\t * What it buys beyond being explicit: the table's schema and the role that\n\t * reaches it come from this database rather than from a second convention,\n\t * and the backend no longer has to guess which database \"the database\" meant\n\t * when an app declares two.\n\t *\n\t * A cache is not a `KyselyDatabase`, so this returns a `Cache` — the client\n\t * is a key/value store, not a query builder, and typing it as the parent\n\t * would be a convenience that lies.\n\t */\n\tcache<TCache extends string = `${TName}Cache`>(\n\t\tid: ConstructName<TCache> = `${this.id}Cache` as ConstructName<TCache>,\n\t\toptions: { table?: string } = {},\n\t): Cache<TCache> {\n\t\treturn new Cache<TCache>(id, {\n\t\t\tof: this.id,\n\t\t\t...(options.table ? { table: options.table } : {}),\n\t\t});\n\t}\n\n\t/**\n\t * A second schema in this database, with its own role(s) and its own URL —\n\t * so this database's role holds no grant on those tables at all.\n\t *\n\t * Typed separately because a tenant has its own tables: the point is that\n\t * `auth.selectFrom('sessions')` type-checks and\n\t * `orders.selectFrom('sessions')` does not.\n\t */\n\tschema<TenantDB, TTenant extends string>(\n\t\tid: ConstructName<TTenant>,\n\t\toptions: KyselyDatabaseOptions = {},\n\t): KyselyDatabase<TenantDB, TTenant> {\n\t\treturn new KyselyDatabase<TenantDB, TTenant>(id, options, {\n\t\t\tkind: 'database-schema',\n\t\t\tof: this.id,\n\t\t\tschema: options.schema ?? (id as string).toLowerCase(),\n\t\t});\n\t}\n\n\t/**\n\t * A connection as the *owner* role — the one that may create, alter and drop.\n\t *\n\t * A `Service` rather than part of the construct, and deliberately so: a\n\t * construct is what `.dependsOn()` accepts, and nothing should be able to\n\t * depend on this. A migrator asks for it by name; a handler cannot ask at\n\t * all, which is the security property the role split exists for.\n\t *\n\t * Falls back to the runtime URL where no owner URL was published — the\n\t * `roles: false` downgrade, where there is only one credential and it is the\n\t * cluster master's.\n\t */\n\tget owner(): Service<`${Uncapitalize<TName>}Owner`, Kysely<DB>> {\n\t\treturn {\n\t\t\tserviceName:\n\t\t\t\t`${serviceKey(this.id)}Owner` as `${Uncapitalize<TName>}Owner`,\n\t\t\tregister: (options) => this.connect(options, { owner: true }),\n\t\t};\n\t}\n\n\tprivate async connect(\n\t\toptions: ServiceRegisterOptions,\n\t\tas: { owner?: boolean } = {},\n\t): Promise<Kysely<DB>> {\n\t\tconst { url, ownerUrl } = options.envParser\n\t\t\t.create((get) => ({\n\t\t\t\turl: get(this.config.url).string(),\n\t\t\t\townerUrl: get(this.config.ownerUrl).string().optional(),\n\t\t\t}))\n\t\t\t.parse();\n\n\t\t// Split what the manifest declared from what Kysely takes, so neither\n\t\t// leaks into the other: `schema` and `roles` describe infrastructure and\n\t\t// mean nothing to a client.\n\t\tconst { schema: _schema, roles: _roles, ...kysely } = this.options;\n\n\t\treturn new Kysely<DB>({\n\t\t\t...kysely,\n\t\t\tdialect: new PostgresDialect({\n\t\t\t\tpool: pool(as.owner ? (ownerUrl ?? url) : url),\n\t\t\t}),\n\t\t});\n\t}\n}\n\n/**\n * A pool for one URL, with its schema actually on the search path.\n *\n * `?search_path=` is not a libpq parameter — a URL carrying it connects\n * happily and then resolves every unqualified name against `public`, which is\n * how a schema tenant silently writes its tables into the database it was\n * separated from. Postgres takes it as a startup option instead, so the URL\n * keeps the readable form the target derives and this turns it into the thing\n * the server understands.\n */\nfunction pool(url: string): pg.Pool {\n\tconst parsed = new URL(url);\n\tconst searchPath = parsed.searchParams.get('search_path');\n\n\tif (!searchPath) return new pg.Pool({ connectionString: url });\n\n\tparsed.searchParams.delete('search_path');\n\n\treturn new pg.Pool({\n\t\tconnectionString: parsed.toString(),\n\t\toptions: `-c search_path=${searchPath}`,\n\t});\n}\n\n/**\n * A database you may read through, and derive nothing from.\n *\n * A reader is terminal in the graph, and this is that fact in the type system.\n * `DERIVES_FROM` gives `cache` and `database-schema` no `database-reader`\n * parent, and there is no reader of a reader — so `orders.reader().cache(…)`\n * has always been illegal, but it type-checked and failed later at\n * `assertDerivations`. That is a long way round to learn that a read-only\n * endpoint cannot own a table something writes to.\n *\n * Omitting the three deriving methods rather than making them throw keeps the\n * failure where it costs least: the editor, on the line that wrote it.\n *\n * The result is deliberately not assignable back to `KyselyDatabase` — a\n * reader is not one, and anything that genuinely needs the writer should say\n * so.\n */\nexport type ReadOnlyDatabase<DB, TName extends string> = Omit<\n\tKyselyDatabase<DB, TName>,\n\t'reader' | 'cache' | 'schema'\n>;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"kysely.cjs","names":["canonicalId","provideKey","DEFAULT_POSTGRES_VERSION","serviceKey","Cache","kysely","Kysely","PostgresDialect"],"sources":["../../src/database/kysely.ts"],"sourcesContent":["/**\n * `KyselyDatabase` — a declared Postgres database, typed by its schema.\n *\n * It declares a logical database, a schema, and the roles that reach it, and\n * hands back a Kysely client built from the one URL the adapter supplied. It\n * names no cloud: `--target=aws` fills that URL from RDS, local dev from the\n * Postgres container.\n *\n * Transactions and RLS context are the execution wrapper's job — it opens the\n * transaction and puts it in `ctx.db`. This construct does not resolve\n * connections per request.\n */\n\nimport {\n\ttype ConstructName,\n\tcanonicalId,\n\tDEFAULT_POSTGRES_VERSION,\n\ttype Declaration,\n\ttype PostgresVersion,\n\tprovideKey,\n\tserviceKey,\n} from '@geekmidas/manifest';\nimport type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport { Kysely, type KyselyConfig, PostgresDialect } from 'kysely';\nimport pg from 'pg';\nimport { Cache } from '../cache';\nimport type { Construct } from '../construct-interface';\n\n/** The schema a database uses when it does not say otherwise. */\nconst DEFAULT_SCHEMA = 'app';\n\n/**\n * Everything Kysely takes, plus what this construct declares.\n *\n * `dialect` is omitted because the construct owns it — it is built from the one\n * URL the adapter supplied, which is the whole point of the construct. The rest\n * of `KyselyConfig` (`plugins`, `log`) is the app's business and passes\n * straight through, so anything Kysely adds later arrives without being\n * tracked here.\n */\nexport interface KyselyDatabaseOptions extends Omit<KyselyConfig, 'dialect'> {\n\t/**\n\t * The schema, pinned on both roles' `search_path`.\n\t *\n\t * Defaults to `app` — the role the schema plays, rather than a restatement\n\t * of the database's own name, which reads correctly beside `auth` and\n\t * `pgboss` and keeps the application off `public`.\n\t */\n\tschema?: string;\n\t/**\n\t * Provision the owner/runtime role split. Defaults to on.\n\t *\n\t * Off falls back to the cluster's master credential in both URLs, giving up\n\t * the DDL/DML split and putting credentials that can drop a table into the\n\t * function's environment. A deliberate downgrade, not a default.\n\t */\n\troles?: boolean;\n\t/**\n\t * The Postgres major version to provision.\n\t *\n\t * Declared here so one statement reaches both targets. It was previously\n\t * set in two unrelated places — a container tag locally, nothing at all on\n\t * AWS (so Aurora chose) — which is how local came to run 18 while deployed\n\t * ran 17.7 with nothing recording the difference.\n\t *\n\t * Defaults to {@link DEFAULT_POSTGRES_VERSION}.\n\t */\n\tversion?: PostgresVersion;\n}\n\n/** What makes a construct derived rather than a database in its own right. */\ninterface DerivedFrom {\n\tkind: 'database-reader' | 'database-schema';\n\tof: string;\n\tschema?: string;\n}\n\n/**\n * @typeParam DB - the database's schema.\n * @typeParam TName - the canonical id. TypeScript has no partial\n * type-argument inference, so `new KyselyDatabase<OrdersDB>('orders')` leaves\n * this at its default and the service key widens to `string`. `db` still types\n * through `.database()`, which infers from the service.\n */\nexport class KyselyDatabase<DB = unknown, TName extends string = string>\n\timplements Construct<TName, Kysely<DB>>\n{\n\treadonly id: TName;\n\treadonly service: Service<Uncapitalize<TName>, Kysely<DB>>;\n\n\t/**\n\t * Declared once and read by both `declare()` and `connect()`, so the key the\n\t * build publishes and the key the client reads cannot drift.\n\t */\n\tprivate readonly config: { url: string; ownerUrl: string };\n\tprivate readonly schemaName: string;\n\tprivate readonly roles: boolean;\n\tprivate readonly version: PostgresVersion;\n\tprivate readonly derivedFrom?: DerivedFrom;\n\n\tconstructor(\n\t\tid: ConstructName<TName>,\n\t\tprivate readonly options: KyselyDatabaseOptions = {},\n\t\tderivedFrom?: DerivedFrom,\n\t) {\n\t\t// Canonicalises, so `orders` and `Orders` are one construct rather than\n\t\t// two that collide. Throws on anything that cannot become a valid id.\n\t\tconst canonical = canonicalId(id as string);\n\n\t\tthis.id = canonical as TName;\n\t\tthis.config = {\n\t\t\turl: provideKey(canonical, 'url'),\n\t\t\townerUrl: provideKey(canonical, 'ownerUrl'),\n\t\t};\n\t\tthis.schemaName = options.schema ?? DEFAULT_SCHEMA;\n\t\tthis.roles = options.roles ?? true;\n\t\tthis.version = options.version ?? DEFAULT_POSTGRES_VERSION;\n\t\tthis.derivedFrom = derivedFrom;\n\n\t\t// A field, not a getter: service discovery caches by object identity.\n\t\tthis.service = {\n\t\t\tserviceName: serviceKey(canonical) as Uncapitalize<TName>,\n\t\t\t// Forwards the whole options object — cherry-picking `envParser` strips\n\t\t\t// `context` and with it the request-scoped logger.\n\t\t\tregister: (registerOptions) => this.connect(registerOptions),\n\t\t};\n\t}\n\n\tdeclare(): Declaration[] {\n\t\tif (this.derivedFrom) {\n\t\t\tconst { kind, of, schema } = this.derivedFrom;\n\n\t\t\treturn [\n\t\t\t\tkind === 'database-schema'\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\tid: this.id,\n\t\t\t\t\t\t\tof,\n\t\t\t\t\t\t\tschema: schema ?? this.schemaName,\n\t\t\t\t\t\t\t// The runtime key alone — see the note below on the parent.\n\t\t\t\t\t\t\tprovides: [this.config.url],\n\t\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\tid: this.id,\n\t\t\t\t\t\t\tof,\n\t\t\t\t\t\t\t// A reader has no owner URL of its own — nothing migrates\n\t\t\t\t\t\t\t// through a read-only endpoint — so this is the one key.\n\t\t\t\t\t\t\tprovides: [this.config.url],\n\t\t\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: 'database',\n\t\t\t\tid: this.id,\n\t\t\t\tengine: 'postgres',\n\t\t\t\tschema: this.schemaName,\n\t\t\t\tversion: this.version,\n\t\t\t\t// One key, the runtime role's. `config` also holds the owner key and\n\t\t\t\t// it is deliberately absent here: a key in `provides` is a key an\n\t\t\t\t// edge can name, and nothing should be able to depend on DDL rights.\n\t\t\t\tprovides: [this.config.url],\n\t\t\t\t...(this.roles ? {} : { roles: false }),\n\t\t\t},\n\t\t];\n\t}\n\n\t/**\n\t * A read-only endpoint on this database.\n\t *\n\t * Read-only is enforced by the reader role's grants rather than by which\n\t * endpoint it resolves to, so falling back to the writer where no replica\n\t * exists is safe rather than a silently writable connection behind a name\n\t * that says reader. There is no `writer()`: the database *is* the writer, so\n\t * a replica can never be reached by accident.\n\t *\n\t * The return type is narrower than this class on purpose — see\n\t * {@link ReadOnlyDatabase}.\n\t */\n\treader(): ReadOnlyDatabase<DB, `${TName}Reader`> {\n\t\treturn new KyselyDatabase<DB, `${TName}Reader`>(\n\t\t\t`${this.id}Reader` as ConstructName<`${TName}Reader`>,\n\t\t\tthis.options,\n\t\t\t{ kind: 'database-reader', of: this.id },\n\t\t);\n\t}\n\n\t/**\n\t * A cache that lives in this database.\n\t *\n\t * The same strengthening `schema()` is over a second database: `new\n\t * Cache('Sessions')` says the app caches and leaves where to the deployment,\n\t * while this says it caches *here* — which is a fact about the application\n\t * and so belongs in its code.\n\t *\n\t * What it buys beyond being explicit: the table's schema and the role that\n\t * reaches it come from this database rather than from a second convention,\n\t * and the backend no longer has to guess which database \"the database\" meant\n\t * when an app declares two.\n\t *\n\t * A cache is not a `KyselyDatabase`, so this returns a `Cache` — the client\n\t * is a key/value store, not a query builder, and typing it as the parent\n\t * would be a convenience that lies.\n\t */\n\tcache<TCache extends string = `${TName}Cache`>(\n\t\tid: ConstructName<TCache> = `${this.id}Cache` as ConstructName<TCache>,\n\t\toptions: { table?: string } = {},\n\t): Cache<TCache> {\n\t\treturn new Cache<TCache>(id, {\n\t\t\tof: this.id,\n\t\t\t...(options.table ? { table: options.table } : {}),\n\t\t});\n\t}\n\n\t/**\n\t * A second schema in this database, with its own role(s) and its own URL —\n\t * so this database's role holds no grant on those tables at all.\n\t *\n\t * Typed separately because a tenant has its own tables: the point is that\n\t * `auth.selectFrom('sessions')` type-checks and\n\t * `orders.selectFrom('sessions')` does not.\n\t */\n\tschema<TenantDB, TTenant extends string>(\n\t\tid: ConstructName<TTenant>,\n\t\toptions: KyselyDatabaseOptions = {},\n\t): KyselyDatabase<TenantDB, TTenant> {\n\t\treturn new KyselyDatabase<TenantDB, TTenant>(id, options, {\n\t\t\tkind: 'database-schema',\n\t\t\tof: this.id,\n\t\t\tschema: options.schema ?? (id as string).toLowerCase(),\n\t\t});\n\t}\n\n\t/**\n\t * A connection as the *owner* role — the one that may create, alter and drop.\n\t *\n\t * A `Service` rather than part of the construct, and deliberately so: a\n\t * construct is what `.dependsOn()` accepts, and nothing should be able to\n\t * depend on this. A migrator asks for it by name; a handler cannot ask at\n\t * all, which is the security property the role split exists for.\n\t *\n\t * Falls back to the runtime URL where no owner URL was published — the\n\t * `roles: false` downgrade, where there is only one credential and it is the\n\t * cluster master's.\n\t */\n\tget owner(): Service<`${Uncapitalize<TName>}Owner`, Kysely<DB>> {\n\t\treturn {\n\t\t\tserviceName:\n\t\t\t\t`${serviceKey(this.id)}Owner` as `${Uncapitalize<TName>}Owner`,\n\t\t\tregister: (options) => this.connect(options, { owner: true }),\n\t\t};\n\t}\n\n\t/**\n\t * What this database's clients are built with besides a dialect — the\n\t * plugins and logging it was declared with.\n\t *\n\t * Public so that whatever opens a connection to it outside \\`connect()\\` —\n\t * a test's transaction — builds the same client. A test that dropped the\n\t * plugins would write \\`createdAt\\` where production writes \\`created_at\\`.\n\t */\n\tget clientConfig(): Omit<KyselyConfig, 'dialect'> {\n\t\t// Split what the manifest declared from what Kysely takes, so neither\n\t\t// leaks into the other: \\`schema\\`, \\`roles\\` and \\`version\\` describe\n\t\t// infrastructure and mean nothing to a client.\n\t\tconst {\n\t\t\tschema: _schema,\n\t\t\troles: _roles,\n\t\t\tversion: _version,\n\t\t\t...kysely\n\t\t} = this.options;\n\t\treturn kysely;\n\t}\n\n\tprivate async connect(\n\t\toptions: ServiceRegisterOptions,\n\t\tas: { owner?: boolean } = {},\n\t): Promise<Kysely<DB>> {\n\t\tconst { url, ownerUrl } = options.envParser\n\t\t\t.create((get) => ({\n\t\t\t\turl: get(this.config.url).string(),\n\t\t\t\townerUrl: get(this.config.ownerUrl).string().optional(),\n\t\t\t}))\n\t\t\t.parse();\n\n\t\treturn new Kysely<DB>({\n\t\t\t...this.clientConfig,\n\t\t\tdialect: new PostgresDialect({\n\t\t\t\tpool: pool(as.owner ? (ownerUrl ?? url) : url),\n\t\t\t}),\n\t\t});\n\t}\n}\n\n/**\n * A pool for one URL, with its schema actually on the search path.\n *\n * `?search_path=` is not a libpq parameter — a URL carrying it connects\n * happily and then resolves every unqualified name against `public`, which is\n * how a schema tenant silently writes its tables into the database it was\n * separated from. Postgres takes it as a startup option instead, so the URL\n * keeps the readable form the target derives and this turns it into the thing\n * the server understands.\n */\nfunction pool(url: string): pg.Pool {\n\tconst parsed = new URL(url);\n\tconst searchPath = parsed.searchParams.get('search_path');\n\n\tif (!searchPath) return new pg.Pool({ connectionString: url });\n\n\tparsed.searchParams.delete('search_path');\n\n\treturn new pg.Pool({\n\t\tconnectionString: parsed.toString(),\n\t\toptions: `-c search_path=${searchPath}`,\n\t});\n}\n\n/**\n * A database you may read through, and derive nothing from.\n *\n * A reader is terminal in the graph, and this is that fact in the type system.\n * `DERIVES_FROM` gives `cache` and `database-schema` no `database-reader`\n * parent, and there is no reader of a reader — so `orders.reader().cache(…)`\n * has always been illegal, but it type-checked and failed later at\n * `assertDerivations`. That is a long way round to learn that a read-only\n * endpoint cannot own a table something writes to.\n *\n * Omitting the three deriving methods rather than making them throw keeps the\n * failure where it costs least: the editor, on the line that wrote it.\n *\n * The result is deliberately not assignable back to `KyselyDatabase` — a\n * reader is not one, and anything that genuinely needs the writer should say\n * so.\n */\nexport type ReadOnlyDatabase<DB, TName extends string> = Omit<\n\tKyselyDatabase<DB, TName>,\n\t'reader' | 'cache' | 'schema'\n>;\n"],"mappings":"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"}
|
|
@@ -1,152 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { Service } from "@geekmidas/services";
|
|
4
|
-
import { ConstructName, Declaration, PostgresVersion } from "@geekmidas/manifest";
|
|
5
|
-
import { Kysely, KyselyConfig } from "kysely";
|
|
6
|
-
|
|
7
|
-
//#region src/database/kysely.d.ts
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Everything Kysely takes, plus what this construct declares.
|
|
11
|
-
*
|
|
12
|
-
* `dialect` is omitted because the construct owns it — it is built from the one
|
|
13
|
-
* URL the adapter supplied, which is the whole point of the construct. The rest
|
|
14
|
-
* of `KyselyConfig` (`plugins`, `log`) is the app's business and passes
|
|
15
|
-
* straight through, so anything Kysely adds later arrives without being
|
|
16
|
-
* tracked here.
|
|
17
|
-
*/
|
|
18
|
-
interface KyselyDatabaseOptions extends Omit<KyselyConfig, 'dialect'> {
|
|
19
|
-
/**
|
|
20
|
-
* The schema, pinned on both roles' `search_path`.
|
|
21
|
-
*
|
|
22
|
-
* Defaults to `app` — the role the schema plays, rather than a restatement
|
|
23
|
-
* of the database's own name, which reads correctly beside `auth` and
|
|
24
|
-
* `pgboss` and keeps the application off `public`.
|
|
25
|
-
*/
|
|
26
|
-
schema?: string;
|
|
27
|
-
/**
|
|
28
|
-
* Provision the owner/runtime role split. Defaults to on.
|
|
29
|
-
*
|
|
30
|
-
* Off falls back to the cluster's master credential in both URLs, giving up
|
|
31
|
-
* the DDL/DML split and putting credentials that can drop a table into the
|
|
32
|
-
* function's environment. A deliberate downgrade, not a default.
|
|
33
|
-
*/
|
|
34
|
-
roles?: boolean;
|
|
35
|
-
/**
|
|
36
|
-
* The Postgres major version to provision.
|
|
37
|
-
*
|
|
38
|
-
* Declared here so one statement reaches both targets. It was previously
|
|
39
|
-
* set in two unrelated places — a container tag locally, nothing at all on
|
|
40
|
-
* AWS (so Aurora chose) — which is how local came to run 18 while deployed
|
|
41
|
-
* ran 17.7 with nothing recording the difference.
|
|
42
|
-
*
|
|
43
|
-
* Defaults to {@link DEFAULT_POSTGRES_VERSION}.
|
|
44
|
-
*/
|
|
45
|
-
version?: PostgresVersion;
|
|
46
|
-
}
|
|
47
|
-
/** What makes a construct derived rather than a database in its own right. */
|
|
48
|
-
interface DerivedFrom {
|
|
49
|
-
kind: 'database-reader' | 'database-schema';
|
|
50
|
-
of: string;
|
|
51
|
-
schema?: string;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* @typeParam DB - the database's schema.
|
|
55
|
-
* @typeParam TName - the canonical id. TypeScript has no partial
|
|
56
|
-
* type-argument inference, so `new KyselyDatabase<OrdersDB>('orders')` leaves
|
|
57
|
-
* this at its default and the service key widens to `string`. `db` still types
|
|
58
|
-
* through `.database()`, which infers from the service.
|
|
59
|
-
*/
|
|
60
|
-
declare class KyselyDatabase<DB = unknown, TName extends string = string> implements Construct<TName, Kysely<DB>> {
|
|
61
|
-
private readonly options;
|
|
62
|
-
readonly id: TName;
|
|
63
|
-
readonly service: Service<Uncapitalize<TName>, Kysely<DB>>;
|
|
64
|
-
/**
|
|
65
|
-
* Declared once and read by both `declare()` and `connect()`, so the key the
|
|
66
|
-
* build publishes and the key the client reads cannot drift.
|
|
67
|
-
*/
|
|
68
|
-
private readonly config;
|
|
69
|
-
private readonly schemaName;
|
|
70
|
-
private readonly roles;
|
|
71
|
-
private readonly version;
|
|
72
|
-
private readonly derivedFrom?;
|
|
73
|
-
constructor(id: ConstructName<TName>, options?: KyselyDatabaseOptions, derivedFrom?: DerivedFrom);
|
|
74
|
-
declare(): Declaration[];
|
|
75
|
-
/**
|
|
76
|
-
* A read-only endpoint on this database.
|
|
77
|
-
*
|
|
78
|
-
* Read-only is enforced by the reader role's grants rather than by which
|
|
79
|
-
* endpoint it resolves to, so falling back to the writer where no replica
|
|
80
|
-
* exists is safe rather than a silently writable connection behind a name
|
|
81
|
-
* that says reader. There is no `writer()`: the database *is* the writer, so
|
|
82
|
-
* a replica can never be reached by accident.
|
|
83
|
-
*
|
|
84
|
-
* The return type is narrower than this class on purpose — see
|
|
85
|
-
* {@link ReadOnlyDatabase}.
|
|
86
|
-
*/
|
|
87
|
-
reader(): ReadOnlyDatabase<DB, `${TName}Reader`>;
|
|
88
|
-
/**
|
|
89
|
-
* A cache that lives in this database.
|
|
90
|
-
*
|
|
91
|
-
* The same strengthening `schema()` is over a second database: `new
|
|
92
|
-
* Cache('Sessions')` says the app caches and leaves where to the deployment,
|
|
93
|
-
* while this says it caches *here* — which is a fact about the application
|
|
94
|
-
* and so belongs in its code.
|
|
95
|
-
*
|
|
96
|
-
* What it buys beyond being explicit: the table's schema and the role that
|
|
97
|
-
* reaches it come from this database rather than from a second convention,
|
|
98
|
-
* and the backend no longer has to guess which database "the database" meant
|
|
99
|
-
* when an app declares two.
|
|
100
|
-
*
|
|
101
|
-
* A cache is not a `KyselyDatabase`, so this returns a `Cache` — the client
|
|
102
|
-
* is a key/value store, not a query builder, and typing it as the parent
|
|
103
|
-
* would be a convenience that lies.
|
|
104
|
-
*/
|
|
105
|
-
cache<TCache extends string = `${TName}Cache`>(id?: ConstructName<TCache>, options?: {
|
|
106
|
-
table?: string;
|
|
107
|
-
}): Cache<TCache>;
|
|
108
|
-
/**
|
|
109
|
-
* A second schema in this database, with its own role(s) and its own URL —
|
|
110
|
-
* so this database's role holds no grant on those tables at all.
|
|
111
|
-
*
|
|
112
|
-
* Typed separately because a tenant has its own tables: the point is that
|
|
113
|
-
* `auth.selectFrom('sessions')` type-checks and
|
|
114
|
-
* `orders.selectFrom('sessions')` does not.
|
|
115
|
-
*/
|
|
116
|
-
schema<TenantDB, TTenant extends string>(id: ConstructName<TTenant>, options?: KyselyDatabaseOptions): KyselyDatabase<TenantDB, TTenant>;
|
|
117
|
-
/**
|
|
118
|
-
* A connection as the *owner* role — the one that may create, alter and drop.
|
|
119
|
-
*
|
|
120
|
-
* A `Service` rather than part of the construct, and deliberately so: a
|
|
121
|
-
* construct is what `.dependsOn()` accepts, and nothing should be able to
|
|
122
|
-
* depend on this. A migrator asks for it by name; a handler cannot ask at
|
|
123
|
-
* all, which is the security property the role split exists for.
|
|
124
|
-
*
|
|
125
|
-
* Falls back to the runtime URL where no owner URL was published — the
|
|
126
|
-
* `roles: false` downgrade, where there is only one credential and it is the
|
|
127
|
-
* cluster master's.
|
|
128
|
-
*/
|
|
129
|
-
get owner(): Service<`${Uncapitalize<TName>}Owner`, Kysely<DB>>;
|
|
130
|
-
private connect;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* A database you may read through, and derive nothing from.
|
|
134
|
-
*
|
|
135
|
-
* A reader is terminal in the graph, and this is that fact in the type system.
|
|
136
|
-
* `DERIVES_FROM` gives `cache` and `database-schema` no `database-reader`
|
|
137
|
-
* parent, and there is no reader of a reader — so `orders.reader().cache(…)`
|
|
138
|
-
* has always been illegal, but it type-checked and failed later at
|
|
139
|
-
* `assertDerivations`. That is a long way round to learn that a read-only
|
|
140
|
-
* endpoint cannot own a table something writes to.
|
|
141
|
-
*
|
|
142
|
-
* Omitting the three deriving methods rather than making them throw keeps the
|
|
143
|
-
* failure where it costs least: the editor, on the line that wrote it.
|
|
144
|
-
*
|
|
145
|
-
* The result is deliberately not assignable back to `KyselyDatabase` — a
|
|
146
|
-
* reader is not one, and anything that genuinely needs the writer should say
|
|
147
|
-
* so.
|
|
148
|
-
*/
|
|
149
|
-
type ReadOnlyDatabase<DB, TName extends string> = Omit<KyselyDatabase<DB, TName>, 'reader' | 'cache' | 'schema'>;
|
|
150
|
-
//#endregion
|
|
151
|
-
export { KyselyDatabase, KyselyDatabaseOptions, ReadOnlyDatabase };
|
|
152
|
-
//# sourceMappingURL=kysely.d.cts.map
|
|
1
|
+
import { n as KyselyDatabaseOptions, r as ReadOnlyDatabase, t as KyselyDatabase } from "../kysely-DVF8wOT4.cjs";
|
|
2
|
+
export { KyselyDatabase, KyselyDatabaseOptions, ReadOnlyDatabase };
|
|
@@ -1,152 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { ConstructName, Declaration, PostgresVersion } from "@geekmidas/manifest";
|
|
4
|
-
import { Service } from "@geekmidas/services";
|
|
5
|
-
import { Kysely, KyselyConfig } from "kysely";
|
|
6
|
-
|
|
7
|
-
//#region src/database/kysely.d.ts
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Everything Kysely takes, plus what this construct declares.
|
|
11
|
-
*
|
|
12
|
-
* `dialect` is omitted because the construct owns it — it is built from the one
|
|
13
|
-
* URL the adapter supplied, which is the whole point of the construct. The rest
|
|
14
|
-
* of `KyselyConfig` (`plugins`, `log`) is the app's business and passes
|
|
15
|
-
* straight through, so anything Kysely adds later arrives without being
|
|
16
|
-
* tracked here.
|
|
17
|
-
*/
|
|
18
|
-
interface KyselyDatabaseOptions extends Omit<KyselyConfig, 'dialect'> {
|
|
19
|
-
/**
|
|
20
|
-
* The schema, pinned on both roles' `search_path`.
|
|
21
|
-
*
|
|
22
|
-
* Defaults to `app` — the role the schema plays, rather than a restatement
|
|
23
|
-
* of the database's own name, which reads correctly beside `auth` and
|
|
24
|
-
* `pgboss` and keeps the application off `public`.
|
|
25
|
-
*/
|
|
26
|
-
schema?: string;
|
|
27
|
-
/**
|
|
28
|
-
* Provision the owner/runtime role split. Defaults to on.
|
|
29
|
-
*
|
|
30
|
-
* Off falls back to the cluster's master credential in both URLs, giving up
|
|
31
|
-
* the DDL/DML split and putting credentials that can drop a table into the
|
|
32
|
-
* function's environment. A deliberate downgrade, not a default.
|
|
33
|
-
*/
|
|
34
|
-
roles?: boolean;
|
|
35
|
-
/**
|
|
36
|
-
* The Postgres major version to provision.
|
|
37
|
-
*
|
|
38
|
-
* Declared here so one statement reaches both targets. It was previously
|
|
39
|
-
* set in two unrelated places — a container tag locally, nothing at all on
|
|
40
|
-
* AWS (so Aurora chose) — which is how local came to run 18 while deployed
|
|
41
|
-
* ran 17.7 with nothing recording the difference.
|
|
42
|
-
*
|
|
43
|
-
* Defaults to {@link DEFAULT_POSTGRES_VERSION}.
|
|
44
|
-
*/
|
|
45
|
-
version?: PostgresVersion;
|
|
46
|
-
}
|
|
47
|
-
/** What makes a construct derived rather than a database in its own right. */
|
|
48
|
-
interface DerivedFrom {
|
|
49
|
-
kind: 'database-reader' | 'database-schema';
|
|
50
|
-
of: string;
|
|
51
|
-
schema?: string;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* @typeParam DB - the database's schema.
|
|
55
|
-
* @typeParam TName - the canonical id. TypeScript has no partial
|
|
56
|
-
* type-argument inference, so `new KyselyDatabase<OrdersDB>('orders')` leaves
|
|
57
|
-
* this at its default and the service key widens to `string`. `db` still types
|
|
58
|
-
* through `.database()`, which infers from the service.
|
|
59
|
-
*/
|
|
60
|
-
declare class KyselyDatabase<DB = unknown, TName extends string = string> implements Construct<TName, Kysely<DB>> {
|
|
61
|
-
private readonly options;
|
|
62
|
-
readonly id: TName;
|
|
63
|
-
readonly service: Service<Uncapitalize<TName>, Kysely<DB>>;
|
|
64
|
-
/**
|
|
65
|
-
* Declared once and read by both `declare()` and `connect()`, so the key the
|
|
66
|
-
* build publishes and the key the client reads cannot drift.
|
|
67
|
-
*/
|
|
68
|
-
private readonly config;
|
|
69
|
-
private readonly schemaName;
|
|
70
|
-
private readonly roles;
|
|
71
|
-
private readonly version;
|
|
72
|
-
private readonly derivedFrom?;
|
|
73
|
-
constructor(id: ConstructName<TName>, options?: KyselyDatabaseOptions, derivedFrom?: DerivedFrom);
|
|
74
|
-
declare(): Declaration[];
|
|
75
|
-
/**
|
|
76
|
-
* A read-only endpoint on this database.
|
|
77
|
-
*
|
|
78
|
-
* Read-only is enforced by the reader role's grants rather than by which
|
|
79
|
-
* endpoint it resolves to, so falling back to the writer where no replica
|
|
80
|
-
* exists is safe rather than a silently writable connection behind a name
|
|
81
|
-
* that says reader. There is no `writer()`: the database *is* the writer, so
|
|
82
|
-
* a replica can never be reached by accident.
|
|
83
|
-
*
|
|
84
|
-
* The return type is narrower than this class on purpose — see
|
|
85
|
-
* {@link ReadOnlyDatabase}.
|
|
86
|
-
*/
|
|
87
|
-
reader(): ReadOnlyDatabase<DB, `${TName}Reader`>;
|
|
88
|
-
/**
|
|
89
|
-
* A cache that lives in this database.
|
|
90
|
-
*
|
|
91
|
-
* The same strengthening `schema()` is over a second database: `new
|
|
92
|
-
* Cache('Sessions')` says the app caches and leaves where to the deployment,
|
|
93
|
-
* while this says it caches *here* — which is a fact about the application
|
|
94
|
-
* and so belongs in its code.
|
|
95
|
-
*
|
|
96
|
-
* What it buys beyond being explicit: the table's schema and the role that
|
|
97
|
-
* reaches it come from this database rather than from a second convention,
|
|
98
|
-
* and the backend no longer has to guess which database "the database" meant
|
|
99
|
-
* when an app declares two.
|
|
100
|
-
*
|
|
101
|
-
* A cache is not a `KyselyDatabase`, so this returns a `Cache` — the client
|
|
102
|
-
* is a key/value store, not a query builder, and typing it as the parent
|
|
103
|
-
* would be a convenience that lies.
|
|
104
|
-
*/
|
|
105
|
-
cache<TCache extends string = `${TName}Cache`>(id?: ConstructName<TCache>, options?: {
|
|
106
|
-
table?: string;
|
|
107
|
-
}): Cache<TCache>;
|
|
108
|
-
/**
|
|
109
|
-
* A second schema in this database, with its own role(s) and its own URL —
|
|
110
|
-
* so this database's role holds no grant on those tables at all.
|
|
111
|
-
*
|
|
112
|
-
* Typed separately because a tenant has its own tables: the point is that
|
|
113
|
-
* `auth.selectFrom('sessions')` type-checks and
|
|
114
|
-
* `orders.selectFrom('sessions')` does not.
|
|
115
|
-
*/
|
|
116
|
-
schema<TenantDB, TTenant extends string>(id: ConstructName<TTenant>, options?: KyselyDatabaseOptions): KyselyDatabase<TenantDB, TTenant>;
|
|
117
|
-
/**
|
|
118
|
-
* A connection as the *owner* role — the one that may create, alter and drop.
|
|
119
|
-
*
|
|
120
|
-
* A `Service` rather than part of the construct, and deliberately so: a
|
|
121
|
-
* construct is what `.dependsOn()` accepts, and nothing should be able to
|
|
122
|
-
* depend on this. A migrator asks for it by name; a handler cannot ask at
|
|
123
|
-
* all, which is the security property the role split exists for.
|
|
124
|
-
*
|
|
125
|
-
* Falls back to the runtime URL where no owner URL was published — the
|
|
126
|
-
* `roles: false` downgrade, where there is only one credential and it is the
|
|
127
|
-
* cluster master's.
|
|
128
|
-
*/
|
|
129
|
-
get owner(): Service<`${Uncapitalize<TName>}Owner`, Kysely<DB>>;
|
|
130
|
-
private connect;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* A database you may read through, and derive nothing from.
|
|
134
|
-
*
|
|
135
|
-
* A reader is terminal in the graph, and this is that fact in the type system.
|
|
136
|
-
* `DERIVES_FROM` gives `cache` and `database-schema` no `database-reader`
|
|
137
|
-
* parent, and there is no reader of a reader — so `orders.reader().cache(…)`
|
|
138
|
-
* has always been illegal, but it type-checked and failed later at
|
|
139
|
-
* `assertDerivations`. That is a long way round to learn that a read-only
|
|
140
|
-
* endpoint cannot own a table something writes to.
|
|
141
|
-
*
|
|
142
|
-
* Omitting the three deriving methods rather than making them throw keeps the
|
|
143
|
-
* failure where it costs least: the editor, on the line that wrote it.
|
|
144
|
-
*
|
|
145
|
-
* The result is deliberately not assignable back to `KyselyDatabase` — a
|
|
146
|
-
* reader is not one, and anything that genuinely needs the writer should say
|
|
147
|
-
* so.
|
|
148
|
-
*/
|
|
149
|
-
type ReadOnlyDatabase<DB, TName extends string> = Omit<KyselyDatabase<DB, TName>, 'reader' | 'cache' | 'schema'>;
|
|
150
|
-
//#endregion
|
|
151
|
-
export { KyselyDatabase, KyselyDatabaseOptions, ReadOnlyDatabase };
|
|
152
|
-
//# sourceMappingURL=kysely.d.mts.map
|
|
1
|
+
import { n as KyselyDatabaseOptions, r as ReadOnlyDatabase, t as KyselyDatabase } from "../kysely-BJ8IQ_1P.mjs";
|
|
2
|
+
export { KyselyDatabase, KyselyDatabaseOptions, ReadOnlyDatabase };
|