@geekmidas/cli 10.0.0-alpha.12 → 10.0.0-alpha.120
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 +310 -377
- package/bin/adjacent-tsconfig.mjs +46 -8
- package/bin/gkm.mjs +11 -3
- package/bin/owning-tsconfig-jsx-register.mjs +18 -0
- package/bin/owning-tsconfig-jsx.mjs +108 -0
- package/dist/EndpointGenerator-BDa6pPgE.cjs +1090 -0
- package/dist/EndpointGenerator-BDa6pPgE.cjs.map +1 -0
- package/dist/EndpointGenerator-CP_z_E3e.mjs +1031 -0
- package/dist/EndpointGenerator-CP_z_E3e.mjs.map +1 -0
- package/dist/GoDaddyProvider-3C8U_tVu.cjs +388 -0
- package/dist/GoDaddyProvider-3C8U_tVu.cjs.map +1 -0
- package/dist/GoDaddyProvider-D0MQoOM4.mjs +388 -0
- package/dist/GoDaddyProvider-D0MQoOM4.mjs.map +1 -0
- package/dist/{HostingerProvider-BcyFRbqV.mjs → HostingerProvider-BNpS9aRJ.mjs} +29 -25
- package/dist/HostingerProvider-BNpS9aRJ.mjs.map +1 -0
- package/dist/{HostingerProvider-BOvsgATO.cjs → HostingerProvider-DR1iws1P.cjs} +29 -25
- package/dist/HostingerProvider-DR1iws1P.cjs.map +1 -0
- package/dist/LegacyStateStore-CRi7TosX.mjs +124 -0
- package/dist/LegacyStateStore-CRi7TosX.mjs.map +1 -0
- package/dist/LegacyStateStore-DHsoQGOo.cjs +124 -0
- package/dist/LegacyStateStore-DHsoQGOo.cjs.map +1 -0
- package/dist/LocalStateStore-BQXTkeoS.cjs +178 -0
- package/dist/LocalStateStore-BQXTkeoS.cjs.map +1 -0
- package/dist/LocalStateStore-Dkth0jXX.mjs +167 -0
- package/dist/LocalStateStore-Dkth0jXX.mjs.map +1 -0
- package/dist/OpenApiTsGenerator-CsrukCE-.mjs +536 -0
- package/dist/OpenApiTsGenerator-CsrukCE-.mjs.map +1 -0
- package/dist/OpenApiTsGenerator-FNhY7Ssz.cjs +541 -0
- package/dist/OpenApiTsGenerator-FNhY7Ssz.cjs.map +1 -0
- package/dist/{Route53Provider-CH9XH7bz.cjs → Route53Provider-Bllus2NR.cjs} +21 -22
- package/dist/Route53Provider-Bllus2NR.cjs.map +1 -0
- package/dist/{Route53Provider-C0xmer8U.mjs → Route53Provider-QXxjkZO1.mjs} +13 -13
- package/dist/Route53Provider-QXxjkZO1.mjs.map +1 -0
- package/dist/S3StateStore-DGKZgyKz.cjs +222 -0
- package/dist/S3StateStore-DGKZgyKz.cjs.map +1 -0
- package/dist/S3StateStore-pZZnLLBd.mjs +223 -0
- package/dist/S3StateStore-pZZnLLBd.mjs.map +1 -0
- package/dist/SSMStateStore-CZRMERDA.mjs +205 -0
- package/dist/SSMStateStore-CZRMERDA.mjs.map +1 -0
- package/dist/SSMStateStore-DzkyjQ5D.cjs +204 -0
- package/dist/SSMStateStore-DzkyjQ5D.cjs.map +1 -0
- package/dist/SubscriberGenerator-C8CPxrCK.cjs +592 -0
- package/dist/SubscriberGenerator-C8CPxrCK.cjs.map +1 -0
- package/dist/SubscriberGenerator-y3pncae_.mjs +533 -0
- package/dist/SubscriberGenerator-y3pncae_.mjs.map +1 -0
- package/dist/add-C0kXOsWS.mjs +717 -0
- package/dist/add-C0kXOsWS.mjs.map +1 -0
- package/dist/add-Df8cmz0H.cjs +719 -0
- package/dist/add-Df8cmz0H.cjs.map +1 -0
- package/dist/appPorts-BoXMwolc.mjs +249 -0
- package/dist/appPorts-BoXMwolc.mjs.map +1 -0
- package/dist/appPorts-IW-OZmRi.cjs +296 -0
- package/dist/appPorts-IW-OZmRi.cjs.map +1 -0
- package/dist/aws-8QQ8n-t6.mjs +89 -0
- package/dist/aws-8QQ8n-t6.mjs.map +1 -0
- package/dist/aws-DY9NqQIT.cjs +100 -0
- package/dist/aws-DY9NqQIT.cjs.map +1 -0
- package/dist/awsStore-Bx5nCFnS.mjs +121 -0
- package/dist/awsStore-Bx5nCFnS.mjs.map +1 -0
- package/dist/awsStore-u3ehhMoY.cjs +138 -0
- package/dist/awsStore-u3ehhMoY.cjs.map +1 -0
- package/dist/{backup-provisioner-DXXg6FIL.mjs → backup-provisioner-C8DnCmxK.mjs} +11 -8
- package/dist/backup-provisioner-C8DnCmxK.mjs.map +1 -0
- package/dist/{backup-provisioner-cE2PuCTb.cjs → backup-provisioner-oDEsPj02.cjs} +22 -20
- package/dist/backup-provisioner-oDEsPj02.cjs.map +1 -0
- package/dist/backups/runner.cjs +519 -0
- package/dist/backups/runner.cjs.map +1 -0
- package/dist/backups/runner.d.cts +102 -0
- package/dist/backups/runner.d.cts.map +1 -0
- package/dist/backups/runner.d.mts +102 -0
- package/dist/backups/runner.d.mts.map +1 -0
- package/dist/backups/runner.mjs +506 -0
- package/dist/backups/runner.mjs.map +1 -0
- package/dist/{bundler-Bux2iF-v.mjs → bundler-B-I4Du99.mjs} +35 -16
- package/dist/bundler-B-I4Du99.mjs.map +1 -0
- package/dist/{bundler-BMekgx7a.cjs → bundler-Dx_grUmc.cjs} +37 -19
- package/dist/bundler-Dx_grUmc.cjs.map +1 -0
- package/dist/cli-Cd9exatJ.cjs +71 -0
- package/dist/cli-Cd9exatJ.cjs.map +1 -0
- package/dist/cli-DL7GxGAe.mjs +71 -0
- package/dist/cli-DL7GxGAe.mjs.map +1 -0
- package/dist/compose-C43c03WZ.mjs +3284 -0
- package/dist/compose-C43c03WZ.mjs.map +1 -0
- package/dist/compose-Mdgea4Yt.cjs +3427 -0
- package/dist/compose-Mdgea4Yt.cjs.map +1 -0
- package/dist/config-D48erO2j.d.mts +269 -0
- package/dist/config-D48erO2j.d.mts.map +1 -0
- package/dist/config-DHDtsQrB.d.cts +269 -0
- package/dist/config-DHDtsQrB.d.cts.map +1 -0
- package/dist/config.cjs +421 -11
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +4 -120
- package/dist/config.d.mts +4 -120
- package/dist/config.mjs +405 -4
- package/dist/config.mjs.map +1 -0
- package/dist/credentialSchemas-B67WJOOm.cjs +272 -0
- package/dist/credentialSchemas-B67WJOOm.cjs.map +1 -0
- package/dist/credentialSchemas-DDOLRCLF.mjs +237 -0
- package/dist/credentialSchemas-DDOLRCLF.mjs.map +1 -0
- package/dist/credentials-B5N5yKk6.mjs +267 -0
- package/dist/credentials-B5N5yKk6.mjs.map +1 -0
- package/dist/credentials-Zqr3QQYB.cjs +350 -0
- package/dist/credentials-Zqr3QQYB.cjs.map +1 -0
- package/dist/databases-BPOgTn1u.mjs +522 -0
- package/dist/databases-BPOgTn1u.mjs.map +1 -0
- package/dist/databases-fOaoBInm.cjs +625 -0
- package/dist/databases-fOaoBInm.cjs.map +1 -0
- package/dist/define-6poNqm5O.mjs +106 -0
- package/dist/define-6poNqm5O.mjs.map +1 -0
- package/dist/define-crmMcXFS.cjs +153 -0
- package/dist/define-crmMcXFS.cjs.map +1 -0
- package/dist/deploy/public.cjs +212 -0
- package/dist/deploy/public.cjs.map +1 -0
- package/dist/deploy/public.d.cts +654 -0
- package/dist/deploy/public.d.cts.map +1 -0
- package/dist/deploy/public.d.mts +654 -0
- package/dist/deploy/public.d.mts.map +1 -0
- package/dist/deploy/public.mjs +145 -0
- package/dist/deploy/public.mjs.map +1 -0
- package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
- package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
- package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
- package/dist/deploy/sniffer-envparser-worker.cjs +54 -0
- package/dist/deploy/sniffer-envparser-worker.cjs.map +1 -0
- package/dist/deploy/sniffer-envparser-worker.d.cts +1 -0
- package/dist/deploy/sniffer-envparser-worker.d.mts +1 -0
- package/dist/deploy/sniffer-envparser-worker.mjs +55 -0
- package/dist/deploy/sniffer-envparser-worker.mjs.map +1 -0
- package/dist/deploy/sniffer-hooks.cjs +13 -7
- package/dist/deploy/sniffer-hooks.cjs.map +1 -1
- package/dist/deploy/sniffer-hooks.d.cts +1 -2
- package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
- package/dist/deploy/sniffer-hooks.d.mts +1 -2
- package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
- package/dist/deploy/sniffer-hooks.mjs +10 -3
- package/dist/deploy/sniffer-hooks.mjs.map +1 -1
- package/dist/deploy/sniffer-loader.cjs +16 -7
- package/dist/deploy/sniffer-loader.cjs.map +1 -1
- package/dist/deploy/sniffer-loader.d.cts +1 -1
- package/dist/deploy/sniffer-loader.d.mts +1 -1
- package/dist/deploy/sniffer-loader.mjs +14 -3
- package/dist/deploy/sniffer-loader.mjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.cjs +11 -11
- package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
- package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
- package/dist/deploy/sniffer-routes-worker.mjs +4 -4
- package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
- package/dist/deploy/sniffer-worker.cjs +15 -6
- package/dist/deploy/sniffer-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-worker.d.cts +1 -3
- package/dist/deploy/sniffer-worker.d.cts.map +1 -1
- package/dist/deploy/sniffer-worker.d.mts +1 -3
- package/dist/deploy/sniffer-worker.d.mts.map +1 -1
- package/dist/deploy/sniffer-worker.mjs +15 -4
- package/dist/deploy/sniffer-worker.mjs.map +1 -1
- package/dist/deploy-BMM2hx-K.cjs +2401 -0
- package/dist/deploy-BMM2hx-K.cjs.map +1 -0
- package/dist/deploy-D5YhwDng.mjs +2328 -0
- package/dist/deploy-D5YhwDng.mjs.map +1 -0
- package/dist/derive-B4vDpzgP.mjs +150 -0
- package/dist/derive-B4vDpzgP.mjs.map +1 -0
- package/dist/derive-DAbo49sm.cjs +161 -0
- package/dist/derive-DAbo49sm.cjs.map +1 -0
- package/dist/discover-C5roJuc9.mjs +560 -0
- package/dist/discover-C5roJuc9.mjs.map +1 -0
- package/dist/discover-CSW_BMWa.d.cts +125 -0
- package/dist/discover-CSW_BMWa.d.cts.map +1 -0
- package/dist/discover-DozUKs8f.cjs +639 -0
- package/dist/discover-DozUKs8f.cjs.map +1 -0
- package/dist/discover-xtT7fgWg.d.mts +125 -0
- package/dist/discover-xtT7fgWg.d.mts.map +1 -0
- package/dist/dns-BIYf20p7.cjs +1057 -0
- package/dist/dns-BIYf20p7.cjs.map +1 -0
- package/dist/dns-agf2VCdV.mjs +926 -0
- package/dist/dns-agf2VCdV.mjs.map +1 -0
- package/dist/dokploy-2p4PK6ej.mjs +38 -0
- package/dist/dokploy-2p4PK6ej.mjs.map +1 -0
- package/dist/dokploy-BANMTroy.cjs +38 -0
- package/dist/dokploy-BANMTroy.cjs.map +1 -0
- package/dist/drivers-BjGDYfnC.mjs +195 -0
- package/dist/drivers-BjGDYfnC.mjs.map +1 -0
- package/dist/drivers-DbjiYpW6.cjs +224 -0
- package/dist/drivers-DbjiYpW6.cjs.map +1 -0
- package/dist/eas-CNi16SoO.cjs +337 -0
- package/dist/eas-CNi16SoO.cjs.map +1 -0
- package/dist/eas-iT2JDHCh.mjs +334 -0
- package/dist/eas-iT2JDHCh.mjs.map +1 -0
- package/dist/{emit-CIlvnDvV.mjs → emit-C1e8qD08.mjs} +13 -26
- package/dist/emit-C1e8qD08.mjs.map +1 -0
- package/dist/{emit-CUD1BWls.cjs → emit-Dmc1nvdS.cjs} +31 -57
- package/dist/emit-Dmc1nvdS.cjs.map +1 -0
- package/dist/encryption-DkXVbyZc.mjs +89 -0
- package/dist/encryption-DkXVbyZc.mjs.map +1 -0
- package/dist/encryption-d2lLtkYx.cjs +90 -0
- package/dist/encryption-d2lLtkYx.cjs.map +1 -0
- package/dist/engine-CatKW6E-.mjs +3089 -0
- package/dist/engine-CatKW6E-.mjs.map +1 -0
- package/dist/engine-DlEHexED.cjs +3202 -0
- package/dist/engine-DlEHexED.cjs.map +1 -0
- package/dist/errors-D8Gwp5kU.mjs +23 -0
- package/dist/errors-D8Gwp5kU.mjs.map +1 -0
- package/dist/errors-DMC4Umsb.cjs +34 -0
- package/dist/errors-DMC4Umsb.cjs.map +1 -0
- package/dist/github-BAeaC1Pl.cjs +833 -0
- package/dist/github-BAeaC1Pl.cjs.map +1 -0
- package/dist/github-DErsqKGN.mjs +832 -0
- package/dist/github-DErsqKGN.mjs.map +1 -0
- package/dist/googlePlay-BVcfFWRO.cjs +931 -0
- package/dist/googlePlay-BVcfFWRO.cjs.map +1 -0
- package/dist/googlePlay-BXJ5ZjMK.mjs +931 -0
- package/dist/googlePlay-BXJ5ZjMK.mjs.map +1 -0
- package/dist/identity-CBXr4wNi.mjs +129 -0
- package/dist/identity-CBXr4wNi.mjs.map +1 -0
- package/dist/identity-CbLfgQNT.cjs +182 -0
- package/dist/identity-CbLfgQNT.cjs.map +1 -0
- package/dist/{index-BzJ7QJ9c.d.mts → index-8OfpOtSI.d.cts} +39 -20
- package/dist/index-8OfpOtSI.d.cts.map +1 -0
- package/dist/{index-CfMjtdVC.d.cts → index-Dpji6Bxq.d.mts} +39 -20
- package/dist/index-Dpji6Bxq.d.mts.map +1 -0
- package/dist/index.cjs +14291 -11898
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +13938 -11560
- package/dist/index.mjs.map +1 -1
- package/dist/local-BwC2v2Y8.mjs +224 -0
- package/dist/local-BwC2v2Y8.mjs.map +1 -0
- package/dist/local-DNhnkugT.cjs +241 -0
- package/dist/local-DNhnkugT.cjs.map +1 -0
- package/dist/migrate-Bb1MmGHl.mjs +181 -0
- package/dist/migrate-Bb1MmGHl.mjs.map +1 -0
- package/dist/migrate-D79GI0XM.cjs +271 -0
- package/dist/migrate-D79GI0XM.cjs.map +1 -0
- package/dist/migrate-L4a273dY.cjs +181 -0
- package/dist/migrate-L4a273dY.cjs.map +1 -0
- package/dist/migrate-s4QizIoM.mjs +266 -0
- package/dist/migrate-s4QizIoM.mjs.map +1 -0
- package/dist/openapi.cjs +214 -10
- package/dist/openapi.cjs.map +1 -0
- package/dist/openapi.d.cts +38 -17
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.mts +38 -17
- package/dist/openapi.d.mts.map +1 -1
- package/dist/openapi.mjs +208 -5
- package/dist/openapi.mjs.map +1 -0
- package/dist/projectBucket-BBbQ1lHF.cjs +263 -0
- package/dist/projectBucket-BBbQ1lHF.cjs.map +1 -0
- package/dist/projectBucket-C_DN4WzF.mjs +222 -0
- package/dist/projectBucket-C_DN4WzF.mjs.map +1 -0
- package/dist/provider-BqpjG9QM.cjs +57 -0
- package/dist/provider-BqpjG9QM.cjs.map +1 -0
- package/dist/provider-CEOKk8NS.mjs +46 -0
- package/dist/provider-CEOKk8NS.mjs.map +1 -0
- package/dist/publish-CcTlmJT6.mjs +123 -0
- package/dist/publish-CcTlmJT6.mjs.map +1 -0
- package/dist/publish-ydscCYsW.cjs +124 -0
- package/dist/publish-ydscCYsW.cjs.map +1 -0
- package/dist/ready-BFFP838V.cjs +404 -0
- package/dist/ready-BFFP838V.cjs.map +1 -0
- package/dist/ready-BOfogqzr.mjs +375 -0
- package/dist/ready-BOfogqzr.mjs.map +1 -0
- package/dist/reconcile/public.cjs +3 -5
- package/dist/reconcile/public.d.cts +11 -87
- package/dist/reconcile/public.d.cts.map +1 -1
- package/dist/reconcile/public.d.mts +11 -87
- package/dist/reconcile/public.d.mts.map +1 -1
- package/dist/reconcile/public.mjs +3 -4
- package/dist/{reconcile-BI0tWkwz.mjs → reconcile--I7V4Klj.mjs} +4 -7
- package/dist/reconcile--I7V4Klj.mjs.map +1 -0
- package/dist/{reconcile-Bhw5fmKu.cjs → reconcile-CuCQBa5-.cjs} +5 -8
- package/dist/reconcile-CuCQBa5-.cjs.map +1 -0
- package/dist/resolve-BLp2trep.mjs +263 -0
- package/dist/resolve-BLp2trep.mjs.map +1 -0
- package/dist/resolve-BgL-brF9.cjs +316 -0
- package/dist/resolve-BgL-brF9.cjs.map +1 -0
- package/dist/rollback-2cyLXEH1.cjs +165 -0
- package/dist/rollback-2cyLXEH1.cjs.map +1 -0
- package/dist/rollback-DwqZ8zzj.mjs +136 -0
- package/dist/rollback-DwqZ8zzj.mjs.map +1 -0
- package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
- package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
- package/dist/run-BJLIerMM.mjs +133 -0
- package/dist/run-BJLIerMM.mjs.map +1 -0
- package/dist/run-fVZ-rLnc.cjs +174 -0
- package/dist/run-fVZ-rLnc.cjs.map +1 -0
- package/dist/runtime-ACdfK59n.d.cts +82 -0
- package/dist/runtime-ACdfK59n.d.cts.map +1 -0
- package/dist/runtime-YyQuekxi.d.mts +82 -0
- package/dist/runtime-YyQuekxi.d.mts.map +1 -0
- package/dist/s3-CrPoA89T.cjs +215 -0
- package/dist/s3-CrPoA89T.cjs.map +1 -0
- package/dist/s3-DQXZdmCM.mjs +215 -0
- package/dist/s3-DQXZdmCM.mjs.map +1 -0
- package/dist/sandbox/config-worker.cjs +43 -0
- package/dist/sandbox/config-worker.cjs.map +1 -0
- package/dist/sandbox/config-worker.d.cts +1 -0
- package/dist/sandbox/config-worker.d.mts +1 -0
- package/dist/sandbox/config-worker.mjs +44 -0
- package/dist/sandbox/config-worker.mjs.map +1 -0
- package/dist/sandbox/credentials-worker.cjs +54 -0
- package/dist/sandbox/credentials-worker.cjs.map +1 -0
- package/dist/sandbox/credentials-worker.d.cts +1 -0
- package/dist/sandbox/credentials-worker.d.mts +1 -0
- package/dist/sandbox/credentials-worker.mjs +55 -0
- package/dist/sandbox/credentials-worker.mjs.map +1 -0
- package/dist/sandbox/discover-worker.cjs +50 -0
- package/dist/sandbox/discover-worker.cjs.map +1 -0
- package/dist/sandbox/discover-worker.d.cts +1 -0
- package/dist/sandbox/discover-worker.d.mts +1 -0
- package/dist/sandbox/discover-worker.mjs +51 -0
- package/dist/sandbox/discover-worker.mjs.map +1 -0
- package/dist/sandbox/migrate-worker.cjs +75 -0
- package/dist/sandbox/migrate-worker.cjs.map +1 -0
- package/dist/sandbox/migrate-worker.d.cts +1 -0
- package/dist/sandbox/migrate-worker.d.mts +1 -0
- package/dist/sandbox/migrate-worker.mjs +76 -0
- package/dist/sandbox/migrate-worker.mjs.map +1 -0
- package/dist/sandbox-C4g1eG31.d.mts +104 -0
- package/dist/sandbox-C4g1eG31.d.mts.map +1 -0
- package/dist/sandbox-CHv3OYXg.cjs +165 -0
- package/dist/sandbox-CHv3OYXg.cjs.map +1 -0
- package/dist/sandbox-CbVB7uOD.mjs +118 -0
- package/dist/sandbox-CbVB7uOD.mjs.map +1 -0
- package/dist/sandbox-CdKgQ3XU.d.cts +104 -0
- package/dist/sandbox-CdKgQ3XU.d.cts.map +1 -0
- package/dist/{workspace-DPV7FtAv.cjs → schemas-BCwKKA42.mjs} +958 -1816
- package/dist/schemas-BCwKKA42.mjs.map +1 -0
- package/dist/{workspace-CtnZnWsa.mjs → schemas-BQ_v0lEX.cjs} +1048 -1626
- package/dist/schemas-BQ_v0lEX.cjs.map +1 -0
- package/dist/secretsManager-CQORubp9.mjs +97 -0
- package/dist/secretsManager-CQORubp9.mjs.map +1 -0
- package/dist/secretsManager-RAGcEDX1.cjs +108 -0
- package/dist/secretsManager-RAGcEDX1.cjs.map +1 -0
- package/dist/seeds-C2w4UqVP.cjs +9347 -0
- package/dist/seeds-C2w4UqVP.cjs.map +1 -0
- package/dist/seeds-Cwtv-U9-.mjs +8350 -0
- package/dist/seeds-Cwtv-U9-.mjs.map +1 -0
- package/dist/serverSetup-CKs4K9gD.cjs +630 -0
- package/dist/serverSetup-CKs4K9gD.cjs.map +1 -0
- package/dist/serverSetup-P68H5Lal.mjs +630 -0
- package/dist/serverSetup-P68H5Lal.mjs.map +1 -0
- package/dist/sniffer-8C4q6Szd.mjs +1825 -0
- package/dist/sniffer-8C4q6Szd.mjs.map +1 -0
- package/dist/sniffer-CF7wNxMo.cjs +1998 -0
- package/dist/sniffer-CF7wNxMo.cjs.map +1 -0
- package/dist/sst-B-Uz4cvm.cjs +464 -0
- package/dist/sst-B-Uz4cvm.cjs.map +1 -0
- package/dist/sst-C1pxbFEd.mjs +441 -0
- package/dist/sst-C1pxbFEd.mjs.map +1 -0
- package/dist/stage-BvM_u2z4.mjs +302 -0
- package/dist/stage-BvM_u2z4.mjs.map +1 -0
- package/dist/stage-DEQJGW3r.cjs +313 -0
- package/dist/stage-DEQJGW3r.cjs.map +1 -0
- package/dist/stages-Cb9rqRbN.mjs +190 -0
- package/dist/stages-Cb9rqRbN.mjs.map +1 -0
- package/dist/stages-D4SnG5yl.cjs +190 -0
- package/dist/stages-D4SnG5yl.cjs.map +1 -0
- package/dist/target/public.cjs +15 -0
- package/dist/target/public.d.cts +28 -0
- package/dist/target/public.d.cts.map +1 -0
- package/dist/target/public.d.mts +28 -0
- package/dist/target/public.d.mts.map +1 -0
- package/dist/target/public.mjs +4 -0
- package/dist/terminal-CW_dWeTe.mjs +85 -0
- package/dist/terminal-CW_dWeTe.mjs.map +1 -0
- package/dist/terminal-DJlqcW_U.cjs +85 -0
- package/dist/terminal-DJlqcW_U.cjs.map +1 -0
- package/dist/types-B6UXlEkf.d.cts +7650 -0
- package/dist/types-B6UXlEkf.d.cts.map +1 -0
- package/dist/types-HqVPddRK.d.mts +7649 -0
- package/dist/types-HqVPddRK.d.mts.map +1 -0
- package/dist/utils-D2Nk1Nv2.cjs +205 -0
- package/dist/utils-D2Nk1Nv2.cjs.map +1 -0
- package/dist/utils-D_fxUqvU.mjs +156 -0
- package/dist/utils-D_fxUqvU.mjs.map +1 -0
- package/dist/vitest.cjs +65 -0
- package/dist/vitest.cjs.map +1 -0
- package/dist/vitest.d.cts +29 -0
- package/dist/vitest.d.cts.map +1 -0
- package/dist/vitest.d.mts +29 -0
- package/dist/vitest.d.mts.map +1 -0
- package/dist/vitest.mjs +65 -0
- package/dist/vitest.mjs.map +1 -0
- package/dist/workerRuntime-BXfhbe13.cjs +108 -0
- package/dist/workerRuntime-BXfhbe13.cjs.map +1 -0
- package/dist/workerRuntime-CsOyBRx2.mjs +79 -0
- package/dist/workerRuntime-CsOyBRx2.mjs.map +1 -0
- package/dist/workspace/index.cjs +8 -4
- package/dist/workspace/index.d.cts +3 -3
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +2 -3
- package/dist/workspace-BwqQnool.cjs +2806 -0
- package/dist/workspace-BwqQnool.cjs.map +1 -0
- package/dist/workspace-D1QbNd55.mjs +2394 -0
- package/dist/workspace-D1QbNd55.mjs.map +1 -0
- package/package.json +54 -22
- package/dist/CachedStateProvider-BEBl2wQT.cjs +0 -60
- package/dist/CachedStateProvider-BEBl2wQT.cjs.map +0 -1
- package/dist/CachedStateProvider-C-8wtlto.mjs +0 -3
- package/dist/CachedStateProvider-Co4n5Wvs.mjs +0 -54
- package/dist/CachedStateProvider-Co4n5Wvs.mjs.map +0 -1
- package/dist/CachedStateProvider-DqhGpzsm.cjs +0 -3
- package/dist/HostingerProvider-BOvsgATO.cjs.map +0 -1
- package/dist/HostingerProvider-BcyFRbqV.mjs.map +0 -1
- package/dist/LocalStateProvider-Bq-0C0sg.mjs +0 -42
- package/dist/LocalStateProvider-Bq-0C0sg.mjs.map +0 -1
- package/dist/LocalStateProvider-yjXZXZDM.cjs +0 -43
- package/dist/LocalStateProvider-yjXZXZDM.cjs.map +0 -1
- package/dist/Route53Provider-C0xmer8U.mjs.map +0 -1
- package/dist/Route53Provider-CH9XH7bz.cjs.map +0 -1
- package/dist/SSMStateProvider-CXtNgPfy.cjs +0 -66
- package/dist/SSMStateProvider-CXtNgPfy.cjs.map +0 -1
- package/dist/SSMStateProvider-DOZifZfE.mjs +0 -66
- package/dist/SSMStateProvider-DOZifZfE.mjs.map +0 -1
- package/dist/backup-provisioner-DXXg6FIL.mjs.map +0 -1
- package/dist/backup-provisioner-cE2PuCTb.cjs.map +0 -1
- package/dist/bundler-BMekgx7a.cjs.map +0 -1
- package/dist/bundler-Bux2iF-v.mjs.map +0 -1
- package/dist/chunk-Duj1WY3L.mjs +0 -7
- package/dist/config-DTsVjKZD.mjs +0 -402
- package/dist/config-DTsVjKZD.mjs.map +0 -1
- package/dist/config-RYR9j6EF.cjs +0 -462
- package/dist/config-RYR9j6EF.cjs.map +0 -1
- package/dist/config.d.cts.map +0 -1
- package/dist/config.d.mts.map +0 -1
- package/dist/credentials-B5zRHdAl.mjs +0 -141
- package/dist/credentials-B5zRHdAl.mjs.map +0 -1
- package/dist/credentials-BapzjyV5.cjs +0 -195
- package/dist/credentials-BapzjyV5.cjs.map +0 -1
- package/dist/credentials-DQRvPz2S.cjs +0 -2769
- package/dist/credentials-DQRvPz2S.cjs.map +0 -1
- package/dist/credentials-jMJC63qs.mjs +0 -2625
- package/dist/credentials-jMJC63qs.mjs.map +0 -1
- package/dist/discover-BYHQwQqu.mjs +0 -242
- package/dist/discover-BYHQwQqu.mjs.map +0 -1
- package/dist/discover-DmW9Bscc.cjs +0 -290
- package/dist/discover-DmW9Bscc.cjs.map +0 -1
- package/dist/dokploy-api-5cK2InBm.cjs +0 -3
- package/dist/dokploy-api-D2Ny4Jrc.mjs +0 -3
- package/dist/dokploy-api-pdaBryoY.mjs +0 -706
- package/dist/dokploy-api-pdaBryoY.mjs.map +0 -1
- package/dist/dokploy-api-zqKe9lHH.cjs +0 -718
- package/dist/dokploy-api-zqKe9lHH.cjs.map +0 -1
- package/dist/emit-CIlvnDvV.mjs.map +0 -1
- package/dist/emit-CUD1BWls.cjs.map +0 -1
- package/dist/encryption-D2pL3tHH.cjs +0 -54
- package/dist/encryption-D2pL3tHH.cjs.map +0 -1
- package/dist/encryption-YDsXXi6w.mjs +0 -3
- package/dist/encryption-_4zwjOAR.mjs +0 -42
- package/dist/encryption-_4zwjOAR.mjs.map +0 -1
- package/dist/encryption-sQ2Oxx0d.cjs +0 -4
- package/dist/fullstack-secrets-B6KBHf-g.mjs +0 -87
- package/dist/fullstack-secrets-B6KBHf-g.mjs.map +0 -1
- package/dist/fullstack-secrets-DL8v0y4D.cjs +0 -99
- package/dist/fullstack-secrets-DL8v0y4D.cjs.map +0 -1
- package/dist/generator-CNzBw7g5.cjs +0 -289
- package/dist/generator-CNzBw7g5.cjs.map +0 -1
- package/dist/generator-VE2JrFlY.mjs +0 -253
- package/dist/generator-VE2JrFlY.mjs.map +0 -1
- package/dist/github-BThvbf2W.cjs +0 -197
- package/dist/github-BThvbf2W.cjs.map +0 -1
- package/dist/github-DpMZurEK.mjs +0 -196
- package/dist/github-DpMZurEK.mjs.map +0 -1
- package/dist/index-BzJ7QJ9c.d.mts.map +0 -1
- package/dist/index-CfMjtdVC.d.cts.map +0 -1
- package/dist/keystore-C9rint2E.cjs +0 -101
- package/dist/keystore-C9rint2E.cjs.map +0 -1
- package/dist/keystore-TxeYM7an.mjs +0 -83
- package/dist/keystore-TxeYM7an.mjs.map +0 -1
- package/dist/openapi-Bs3-5q_r.mjs +0 -2021
- package/dist/openapi-Bs3-5q_r.mjs.map +0 -1
- package/dist/openapi-DWLTsYLL.cjs +0 -2075
- package/dist/openapi-DWLTsYLL.cjs.map +0 -1
- package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
- package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
- package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
- package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
- package/dist/openapi-react-query.cjs +0 -4
- package/dist/openapi-react-query.d.cts +0 -11
- package/dist/openapi-react-query.d.cts.map +0 -1
- package/dist/openapi-react-query.d.mts +0 -11
- package/dist/openapi-react-query.d.mts.map +0 -1
- package/dist/openapi-react-query.mjs +0 -4
- package/dist/reconcile-BI0tWkwz.mjs.map +0 -1
- package/dist/reconcile-Bhw5fmKu.cjs.map +0 -1
- package/dist/setup-BmLoNrDX.mjs +0 -12
- package/dist/setup-BrR1_xGy.cjs +0 -12
- package/dist/setup-BsNR2LBG.cjs +0 -467
- package/dist/setup-BsNR2LBG.cjs.map +0 -1
- package/dist/setup-D5-JMknk.mjs +0 -437
- package/dist/setup-D5-JMknk.mjs.map +0 -1
- package/dist/storage-B020InPW.mjs +0 -222
- package/dist/storage-B020InPW.mjs.map +0 -1
- package/dist/storage-CSNplaJn.cjs +0 -282
- package/dist/storage-CSNplaJn.cjs.map +0 -1
- package/dist/storage-DGBzMLZa.mjs +0 -4
- package/dist/storage-DlVol_oj.cjs +0 -8
- package/dist/sync-0ILCb-1S.cjs +0 -93
- package/dist/sync-0ILCb-1S.cjs.map +0 -1
- package/dist/sync-CzHXiR9c.mjs +0 -76
- package/dist/sync-CzHXiR9c.mjs.map +0 -1
- package/dist/sync-DYENfOt4.cjs +0 -4
- package/dist/sync-HAau6h_R.mjs +0 -3
- package/dist/types-DVIx8I1N.d.mts +0 -1950
- package/dist/types-DVIx8I1N.d.mts.map +0 -1
- package/dist/types-PMP_qXRY.d.cts +0 -1950
- package/dist/types-PMP_qXRY.d.cts.map +0 -1
- package/dist/workspace-Cji6lE8E.cjs +0 -10
- package/dist/workspace-CkJAtRIX.mjs +0 -9
- package/dist/workspace-CtnZnWsa.mjs.map +0 -1
- package/dist/workspace-DPV7FtAv.cjs.map +0 -1
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
|
|
2
|
+
import { t as GkmError } from "./errors-D8Gwp5kU.mjs";
|
|
3
|
+
import { C as dockerCompose, a as edgePorts, b as dockerHost, d as composeStack, g as edgeAlias, s as deployedStackSecrets, x as sshAccess, y as composeServer } from "./compose-C43c03WZ.mjs";
|
|
4
|
+
import { N as assertDeployedStage } from "./workspace-D1QbNd55.mjs";
|
|
5
|
+
import { S as deploysWithCompose } from "./dns-agf2VCdV.mjs";
|
|
6
|
+
import { It as secretsStoreFor, dt as constructGlobs } from "./seeds-Cwtv-U9-.mjs";
|
|
7
|
+
import { n as deployIdentity } from "./identity-CBXr4wNi.mjs";
|
|
8
|
+
import { i as discover } from "./discover-C5roJuc9.mjs";
|
|
9
|
+
import { NotInAnApp, loadWorkspaceAppInfo, loadWorkspaceConfig } from "./config.mjs";
|
|
10
|
+
import { u as prompt } from "./index.mjs";
|
|
11
|
+
import { constants } from "node:os";
|
|
12
|
+
import { spawn } from "node:child_process";
|
|
13
|
+
//#region src/exec/stage.ts
|
|
14
|
+
/**
|
|
15
|
+
* `gkm exec --stage <stage> -- <command>`: a command run on this machine as
|
|
16
|
+
* a deployed compose stage's app — a data import, a backfill, a report.
|
|
17
|
+
*
|
|
18
|
+
* The app's environment is the one its container runs with, derived the way
|
|
19
|
+
* the deploy derives it (`composeStack`) from the stage's secrets, read from
|
|
20
|
+
* the stage's store the way the deploy reads them. Only what the container
|
|
21
|
+
* reaches on the stack's network is moved: each service it names that the
|
|
22
|
+
* server publishes on its loopback — Postgres, MinIO — is reached through an
|
|
23
|
+
* SSH tunnel on the deploy's own login (`ServerAccess.tunnel`), and each
|
|
24
|
+
* sibling app through its public address.
|
|
25
|
+
*
|
|
26
|
+
* Nothing is written to disk. The values exist only in the command's
|
|
27
|
+
* environment, and its Credentials are filled from there by a preload that
|
|
28
|
+
* is a `data:` URL naming the keys — never their values.
|
|
29
|
+
*/
|
|
30
|
+
var stage_exports = /* @__PURE__ */ __exportAll({
|
|
31
|
+
ExecAppNotInStack: () => ExecAppNotInStack,
|
|
32
|
+
ExecNotConfirmed: () => ExecNotConfirmed,
|
|
33
|
+
ExecStageNotComposed: () => ExecStageNotComposed,
|
|
34
|
+
ExecStageNotDeployed: () => ExecStageNotDeployed,
|
|
35
|
+
appEnvironment: () => appEnvironment,
|
|
36
|
+
credentialsImport: () => credentialsImport,
|
|
37
|
+
defaultStageExecDeps: () => defaultStageExecDeps,
|
|
38
|
+
execOnStage: () => execOnStage,
|
|
39
|
+
loadStage: () => loadStage,
|
|
40
|
+
stackAddresses: () => stackAddresses,
|
|
41
|
+
throughTunnels: () => throughTunnels
|
|
42
|
+
});
|
|
43
|
+
const logger = console;
|
|
44
|
+
/** The stage is not one the compose target deploys. */
|
|
45
|
+
var ExecStageNotComposed = class extends GkmError {
|
|
46
|
+
stage;
|
|
47
|
+
constructor(stage) {
|
|
48
|
+
super(`gkm exec --stage runs a command against a compose stage's server, and '${stage}' is not deployed with compose. Set deploy.default: 'compose' in gkm.config.ts, or run the command where the stage runs.`);
|
|
49
|
+
this.stage = stage;
|
|
50
|
+
this.name = "ExecStageNotComposed";
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/** The stage's secrets lack what its deploy generates: it was never deployed. */
|
|
54
|
+
var ExecStageNotDeployed = class extends GkmError {
|
|
55
|
+
stage;
|
|
56
|
+
missing;
|
|
57
|
+
constructor(stage, missing) {
|
|
58
|
+
super(`'${stage}' has no ${missing.join(", ")} in its secrets yet, so what its apps run with is not decided. Deploy it first: gkm deploy --stage ${stage}.`);
|
|
59
|
+
this.stage = stage;
|
|
60
|
+
this.missing = missing;
|
|
61
|
+
this.name = "ExecStageNotDeployed";
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
/** The directory is not one of the stack's apps. */
|
|
65
|
+
var ExecAppNotInStack = class extends GkmError {
|
|
66
|
+
stage;
|
|
67
|
+
app;
|
|
68
|
+
apps;
|
|
69
|
+
constructor(stage, app, apps) {
|
|
70
|
+
super(`${app ? `'${app}' is not` : "This directory is not in"} one of the apps '${stage}' runs (${apps.join(", ")}), so there is no environment to run as. Run from an app's directory: cd apps/${apps[0] ?? "<app>"} && gkm exec --stage ${stage} -- <command>.`);
|
|
71
|
+
this.stage = stage;
|
|
72
|
+
this.app = app;
|
|
73
|
+
this.apps = apps;
|
|
74
|
+
this.name = "ExecAppNotInStack";
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/** A protected stage, and nobody said yes. */
|
|
78
|
+
var ExecNotConfirmed = class extends GkmError {
|
|
79
|
+
stage;
|
|
80
|
+
constructor(stage) {
|
|
81
|
+
super(`Nothing was run against '${stage}'.`);
|
|
82
|
+
this.stage = stage;
|
|
83
|
+
this.name = "ExecNotConfirmed";
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const defaultStageExecDeps = {
|
|
87
|
+
docker: dockerCompose,
|
|
88
|
+
server: sshAccess,
|
|
89
|
+
confirm: async (question) => {
|
|
90
|
+
const answer = await prompt(`${question} [y/N] `, { instead: "Pass --yes to run without asking." });
|
|
91
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
92
|
+
},
|
|
93
|
+
env: process.env
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* The environment an app runs with on the stage: a backend's container's,
|
|
97
|
+
* over the keys of each worker built from it; a site's or a mobile app's,
|
|
98
|
+
* the public values its build reads.
|
|
99
|
+
*
|
|
100
|
+
* @throws {ExecAppNotInStack}
|
|
101
|
+
*/
|
|
102
|
+
function appEnvironment(stack, appName) {
|
|
103
|
+
const mobile = stack.mobileApps.find((candidate) => candidate.name === appName);
|
|
104
|
+
if (mobile) return { ...mobile.values };
|
|
105
|
+
const app = stack.apps.find((candidate) => candidate.name === appName);
|
|
106
|
+
if (!app) throw new ExecAppNotInStack(stack.stage, appName, [...stack.apps.map((candidate) => candidate.name), ...stack.mobileApps.map((candidate) => candidate.name)]);
|
|
107
|
+
if (app.kind === "site") return { ...app.build?.args };
|
|
108
|
+
const workers = stack.workers.filter((worker) => worker.host === app.name);
|
|
109
|
+
return Object.assign({}, ...workers.map((worker) => worker.env ?? {}), app.env ?? {});
|
|
110
|
+
}
|
|
111
|
+
/** `host:port`, at a URL's authority — after `//` or a login's `@`. */
|
|
112
|
+
function authority(host, port) {
|
|
113
|
+
return new RegExp(`(?<=[/@,])${host.replace(/[.-]/g, "\\$&")}:${port}(?!\\d)`, "g");
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Each of the stack's services the environment reaches on the stack's
|
|
117
|
+
* network, once: `postgres:5432`, `minio:9000`.
|
|
118
|
+
*/
|
|
119
|
+
function stackAddresses(env, stack) {
|
|
120
|
+
const found = /* @__PURE__ */ new Map();
|
|
121
|
+
const pattern = /(?<=[/@,])([a-z0-9-]+):(\d+)(?!\d)/g;
|
|
122
|
+
for (const value of Object.values(env)) for (const match of value.matchAll(pattern)) {
|
|
123
|
+
const service = match[1];
|
|
124
|
+
if (!stack.infra.includes(service)) continue;
|
|
125
|
+
const port = Number(match[2]);
|
|
126
|
+
found.set(`${service}:${port}`, {
|
|
127
|
+
service,
|
|
128
|
+
port
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return [...found.values()];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The environment as this machine reaches it: each service at its tunnel's
|
|
135
|
+
* local port, and each sibling app at its public address. What has no
|
|
136
|
+
* tunnel is left as the container has it.
|
|
137
|
+
*/
|
|
138
|
+
function throughTunnels(env, stack, tunnels) {
|
|
139
|
+
const rewrites = [];
|
|
140
|
+
for (const [address, port] of tunnels) {
|
|
141
|
+
const [service, inside] = address.split(":");
|
|
142
|
+
rewrites.push([authority(service, Number(inside)), `127.0.0.1:${port}`]);
|
|
143
|
+
}
|
|
144
|
+
for (const app of stack.apps) for (const host of [app.name, edgeAlias(stack.project, app.name)]) rewrites.push([new RegExp(`http://${host.replace(/[.-]/g, "\\$&")}:${app.port}(?!\\d)`, "g"), app.url]);
|
|
145
|
+
const out = {};
|
|
146
|
+
for (const [key, value] of Object.entries(env)) out[key] = rewrites.reduce((current, [pattern, replacement]) => current.replace(pattern, () => replacement), value);
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The preload that fills Credentials from the command's own environment: a
|
|
151
|
+
* `data:` URL holding the keys, so no file — and no value — is written.
|
|
152
|
+
*/
|
|
153
|
+
function credentialsImport(keys) {
|
|
154
|
+
const source = `globalThis.__gkm_credentials__=Object.fromEntries(${JSON.stringify(keys)}.map((k)=>[k,process.env[k]]));`;
|
|
155
|
+
return `--import=data:text/javascript,${encodeURIComponent(source)}`;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* The stage's stack, and the app this directory is, as the deploy has them:
|
|
159
|
+
* its secrets read from its store, its values derived as the deploy derives
|
|
160
|
+
* them. Nothing is reached but the store — no server, no SSH.
|
|
161
|
+
*
|
|
162
|
+
* @throws {UndeclaredStage}, {ExecStageNotComposed}, {ExecStageNotDeployed}
|
|
163
|
+
*/
|
|
164
|
+
async function loadStage(options, env = process.env) {
|
|
165
|
+
const cwd = options.cwd ?? process.cwd();
|
|
166
|
+
const { stage } = options;
|
|
167
|
+
const info = await loadWorkspaceAppInfo(cwd).catch((error) => {
|
|
168
|
+
if (error instanceof NotInAnApp) return void 0;
|
|
169
|
+
throw error;
|
|
170
|
+
});
|
|
171
|
+
const workspace = info?.workspace ?? (await loadWorkspaceConfig(cwd)).workspace;
|
|
172
|
+
assertDeployedStage(workspace.stages, stage);
|
|
173
|
+
if (!deploysWithCompose(workspace)) throw new ExecStageNotComposed(stage);
|
|
174
|
+
const runnables = {};
|
|
175
|
+
const background = {};
|
|
176
|
+
const manifest = await discover({
|
|
177
|
+
patterns: constructGlobs(workspace),
|
|
178
|
+
cwd: workspace.root,
|
|
179
|
+
runnables,
|
|
180
|
+
background
|
|
181
|
+
});
|
|
182
|
+
const store = await secretsStoreFor(workspace, stage, { ...options.profile ? { profile: options.profile } : {} });
|
|
183
|
+
const { secrets, generated } = deployedStackSecrets(workspace, stage, await store.read(stage), manifest);
|
|
184
|
+
if (generated.length > 0) throw new ExecStageNotDeployed(stage, generated);
|
|
185
|
+
return {
|
|
186
|
+
workspace,
|
|
187
|
+
manifest,
|
|
188
|
+
stack: composeStack({
|
|
189
|
+
workspace,
|
|
190
|
+
manifest,
|
|
191
|
+
runnables,
|
|
192
|
+
background,
|
|
193
|
+
stage,
|
|
194
|
+
identity: deployIdentity(workspace, stage),
|
|
195
|
+
images: {
|
|
196
|
+
mode: "build",
|
|
197
|
+
tag: "exec"
|
|
198
|
+
},
|
|
199
|
+
secrets,
|
|
200
|
+
ports: edgePorts(env)
|
|
201
|
+
}),
|
|
202
|
+
secrets,
|
|
203
|
+
appName: info?.appName,
|
|
204
|
+
protectedStage: workspace.stages.protected?.includes(stage) ?? false
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/** The stage's server, as SSH reaches it: `--ssh-user` over the config's. */
|
|
208
|
+
function stageServer(loaded, options) {
|
|
209
|
+
const server = composeServer({
|
|
210
|
+
stage: options.stage,
|
|
211
|
+
local: false,
|
|
212
|
+
config: loaded.workspace.deploy?.compose?.server,
|
|
213
|
+
custom: loaded.secrets.custom
|
|
214
|
+
});
|
|
215
|
+
if (options.sshUser) server.user = options.sshUser;
|
|
216
|
+
return server;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Run `commandArgs` as the app this directory is, on the stage — through a
|
|
220
|
+
* tunnel to each service it reaches — and return its exit code. Every tunnel
|
|
221
|
+
* is closed once it exits, whatever it exits with.
|
|
222
|
+
*
|
|
223
|
+
* @throws {ExecStageNotComposed}, {ExecStageNotDeployed}, {ExecAppNotInStack},
|
|
224
|
+
* {ExecNotConfirmed}, {ComposeServerUnreachable}
|
|
225
|
+
*/
|
|
226
|
+
async function execOnStage(commandArgs, options, deps = defaultStageExecDeps) {
|
|
227
|
+
const { stage } = options;
|
|
228
|
+
const loaded = await loadStage(options, deps.env);
|
|
229
|
+
const { stack, appName, protectedStage } = loaded;
|
|
230
|
+
const env = appEnvironment(stack, appName);
|
|
231
|
+
if (protectedStage && !options.yes) {
|
|
232
|
+
const question = `'${stage}' is a protected stage. Run ${commandArgs.join(" ")} against it?`;
|
|
233
|
+
if (!await deps.confirm(question)) throw new ExecNotConfirmed(stage);
|
|
234
|
+
}
|
|
235
|
+
const addresses = stackAddresses(env, stack);
|
|
236
|
+
if (addresses.length === 0) {
|
|
237
|
+
logger.log(`📦 App: ${appName} on '${stage}'`);
|
|
238
|
+
logger.log(`🔐 Loaded ${Object.keys(env).length} value(s) for '${stage}'`);
|
|
239
|
+
return run(commandArgs, env, options.cwd);
|
|
240
|
+
}
|
|
241
|
+
const server = stageServer(loaded, options);
|
|
242
|
+
logger.log(`📦 App: ${appName} on '${stage}' (${server.host})`);
|
|
243
|
+
await deps.server.check(server);
|
|
244
|
+
const tunnels = [];
|
|
245
|
+
const ports = /* @__PURE__ */ new Map();
|
|
246
|
+
try {
|
|
247
|
+
for (const address of addresses) {
|
|
248
|
+
const published = await deps.docker.published({ host: dockerHost(server) }, stack.project, address.service, address.port);
|
|
249
|
+
if (published === void 0) {
|
|
250
|
+
logger.log(`⚠️ ${address.service} is not published on the server (no running ${stack.project} ${address.service} publishes ${address.port}), so it is unreachable from here; its address is passed on unchanged.`);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
const tunnel = await deps.server.tunnel(server, published);
|
|
254
|
+
tunnels.push(tunnel);
|
|
255
|
+
ports.set(`${address.service}:${address.port}`, tunnel.port);
|
|
256
|
+
logger.log(`🚇 ${address.service} → 127.0.0.1:${tunnel.port} (over SSH)`);
|
|
257
|
+
}
|
|
258
|
+
const credentials = throughTunnels(env, stack, ports);
|
|
259
|
+
logger.log(`🔐 Loaded ${Object.keys(credentials).length} value(s) for '${stage}'`);
|
|
260
|
+
return await run(commandArgs, credentials, options.cwd);
|
|
261
|
+
} finally {
|
|
262
|
+
await Promise.all(tunnels.map((tunnel) => tunnel.close()));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* The command, with the values in its environment and its Credentials. A
|
|
267
|
+
* Ctrl-C reaches it — it is in the terminal's process group — and this
|
|
268
|
+
* process waits for it to exit rather than leaving before the tunnels close.
|
|
269
|
+
*/
|
|
270
|
+
function run(commandArgs, credentials, cwd) {
|
|
271
|
+
const [cmd, ...args] = commandArgs;
|
|
272
|
+
logger.log(`🚀 Running: ${commandArgs.join(" ")}`);
|
|
273
|
+
const nodeOptions = [(process.env.NODE_OPTIONS ?? "").replace(/--import[= ]\S+/g, "").trim(), credentialsImport(Object.keys(credentials))].filter(Boolean).join(" ");
|
|
274
|
+
const wait = () => {};
|
|
275
|
+
process.on("SIGINT", wait);
|
|
276
|
+
process.on("SIGTERM", wait);
|
|
277
|
+
return new Promise((resolve) => {
|
|
278
|
+
const child = spawn(cmd, args, {
|
|
279
|
+
...cwd ? { cwd } : {},
|
|
280
|
+
stdio: "inherit",
|
|
281
|
+
env: {
|
|
282
|
+
...process.env,
|
|
283
|
+
...credentials,
|
|
284
|
+
NODE_OPTIONS: nodeOptions
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
child.on("close", (code, signal) => {
|
|
288
|
+
resolve(code ?? 128 + (signal ? constants.signals[signal] : 0));
|
|
289
|
+
});
|
|
290
|
+
child.on("error", (error) => {
|
|
291
|
+
logger.error(`Failed to run command: ${error.message}`);
|
|
292
|
+
resolve(1);
|
|
293
|
+
});
|
|
294
|
+
}).finally(() => {
|
|
295
|
+
process.off("SIGINT", wait);
|
|
296
|
+
process.off("SIGTERM", wait);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
//#endregion
|
|
300
|
+
export { stage_exports as n, loadStage as t };
|
|
301
|
+
|
|
302
|
+
//# sourceMappingURL=stage-BvM_u2z4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-BvM_u2z4.mjs","names":[],"sources":["../src/exec/stage.ts"],"sourcesContent":["/**\n * `gkm exec --stage <stage> -- <command>`: a command run on this machine as\n * a deployed compose stage's app — a data import, a backfill, a report.\n *\n * The app's environment is the one its container runs with, derived the way\n * the deploy derives it (`composeStack`) from the stage's secrets, read from\n * the stage's store the way the deploy reads them. Only what the container\n * reaches on the stack's network is moved: each service it names that the\n * server publishes on its loopback — Postgres, MinIO — is reached through an\n * SSH tunnel on the deploy's own login (`ServerAccess.tunnel`), and each\n * sibling app through its public address.\n *\n * Nothing is written to disk. The values exist only in the command's\n * environment, and its Credentials are filled from there by a preload that\n * is a `data:` URL naming the keys — never their values.\n */\n\nimport { spawn } from 'node:child_process';\nimport { constants } from 'node:os';\nimport type { ConstructManifest } from '@geekmidas/manifest';\nimport { type ComposeDocker, dockerCompose } from '../compose/docker.js';\nimport { deployedStackSecrets } from '../compose/secrets.js';\nimport {\n\ttype ComposeServer,\n\tcomposeServer,\n\tdockerHost,\n\ttype ServerAccess,\n\tsshAccess,\n\ttype Tunnel,\n} from '../compose/server.js';\nimport { type ComposeStack, composeStack } from '../compose/stack.js';\nimport { edgeAlias } from '../compose/traefik.js';\nimport {\n\tloadWorkspaceAppInfo,\n\tloadWorkspaceConfig,\n\tNotInAnApp,\n} from '../config.js';\nimport { deployIdentity } from '../deploy/identity.js';\nimport { GkmError } from '../errors';\nimport { prompt } from '../prompt.js';\nimport { deploysWithCompose } from '../providers/dns.js';\nimport { discover } from '../reconcile/discover.js';\nimport { constructGlobs } from '../reconcile/workspace.js';\nimport { secretsStoreFor } from '../secrets/store.js';\nimport type { StageSecrets } from '../secrets/types.js';\nimport { edgePorts } from '../target/compose/phases.js';\nimport { assertDeployedStage } from '../workspace/stages.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\n\nconst logger = console;\n\n/** The stage is not one the compose target deploys. */\nexport class ExecStageNotComposed extends GkmError {\n\tconstructor(readonly stage: string) {\n\t\tsuper(\n\t\t\t`gkm exec --stage runs a command against a compose stage's server, and ` +\n\t\t\t\t`'${stage}' is not deployed with compose. Set deploy.default: 'compose' ` +\n\t\t\t\t'in gkm.config.ts, or run the command where the stage runs.',\n\t\t);\n\t\tthis.name = 'ExecStageNotComposed';\n\t}\n}\n\n/** The stage's secrets lack what its deploy generates: it was never deployed. */\nexport class ExecStageNotDeployed extends GkmError {\n\tconstructor(\n\t\treadonly stage: string,\n\t\treadonly missing: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`'${stage}' has no ${missing.join(', ')} in its secrets yet, so what its ` +\n\t\t\t\t'apps run with is not decided. Deploy it first: ' +\n\t\t\t\t`gkm deploy --stage ${stage}.`,\n\t\t);\n\t\tthis.name = 'ExecStageNotDeployed';\n\t}\n}\n\n/** The directory is not one of the stack's apps. */\nexport class ExecAppNotInStack extends GkmError {\n\tconstructor(\n\t\treadonly stage: string,\n\t\treadonly app: string | undefined,\n\t\treadonly apps: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`${app ? `'${app}' is not` : 'This directory is not in'} one of the apps ` +\n\t\t\t\t`'${stage}' runs (${apps.join(', ')}), so there is no environment to run ` +\n\t\t\t\t`as. Run from an app's directory: cd apps/${apps[0] ?? '<app>'} && ` +\n\t\t\t\t`gkm exec --stage ${stage} -- <command>.`,\n\t\t);\n\t\tthis.name = 'ExecAppNotInStack';\n\t}\n}\n\n/** A protected stage, and nobody said yes. */\nexport class ExecNotConfirmed extends GkmError {\n\tconstructor(readonly stage: string) {\n\t\tsuper(`Nothing was run against '${stage}'.`);\n\t\tthis.name = 'ExecNotConfirmed';\n\t}\n}\n\nexport interface StageExecOptions {\n\tstage: string;\n\t/** The AWS profile for the stage's account, where its secrets are kept. */\n\tprofile?: string;\n\t/**\n\t * The SSH login to reach the server as, in place of\n\t * `deploy.compose.server.<stage>.user` — a person's own, where the\n\t * deploy's key lives only in CI.\n\t */\n\tsshUser?: string;\n\t/** Run against a protected stage without asking. */\n\tyes?: boolean;\n\tcwd?: string;\n}\n\n/** What the command needs from outside the process, so tests can stand in. */\nexport interface StageExecDeps {\n\t/** The server's Docker, asked which port each service publishes. */\n\tdocker: ComposeDocker;\n\t/** The tunnels to the server's loopback. */\n\tserver: ServerAccess;\n\t/** Asked before running against a protected stage. */\n\tconfirm: (question: string) => Promise<boolean>;\n\t/** Where the edge's ports are read from, as the deploy reads them. */\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport const defaultStageExecDeps: StageExecDeps = {\n\tdocker: dockerCompose,\n\tserver: sshAccess,\n\tconfirm: async (question) => {\n\t\tconst answer = await prompt(`${question} [y/N] `, {\n\t\t\tinstead: 'Pass --yes to run without asking.',\n\t\t});\n\t\treturn /^y(es)?$/i.test(answer.trim());\n\t},\n\tenv: process.env,\n};\n\n/** A service on the stack's network the app's environment names. */\nexport interface StackAddress {\n\tservice: string;\n\tport: number;\n}\n\n/**\n * The environment an app runs with on the stage: a backend's container's,\n * over the keys of each worker built from it; a site's or a mobile app's,\n * the public values its build reads.\n *\n * @throws {ExecAppNotInStack}\n */\nexport function appEnvironment(\n\tstack: Pick<ComposeStack, 'stage' | 'apps' | 'workers' | 'mobileApps'>,\n\tappName: string | undefined,\n): Record<string, string> {\n\tconst mobile = stack.mobileApps.find(\n\t\t(candidate) => candidate.name === appName,\n\t);\n\tif (mobile) return { ...mobile.values };\n\tconst app = stack.apps.find((candidate) => candidate.name === appName);\n\tif (!app) {\n\t\tthrow new ExecAppNotInStack(stack.stage, appName, [\n\t\t\t...stack.apps.map((candidate) => candidate.name),\n\t\t\t...stack.mobileApps.map((candidate) => candidate.name),\n\t\t]);\n\t}\n\tif (app.kind === 'site') return { ...app.build?.args };\n\tconst workers = stack.workers.filter((worker) => worker.host === app.name);\n\treturn Object.assign(\n\t\t{},\n\t\t...workers.map((worker) => worker.env ?? {}),\n\t\tapp.env ?? {},\n\t);\n}\n\n/** `host:port`, at a URL's authority — after `//` or a login's `@`. */\nfunction authority(host: string, port: number): RegExp {\n\treturn new RegExp(\n\t\t`(?<=[/@,])${host.replace(/[.-]/g, '\\\\$&')}:${port}(?!\\\\d)`,\n\t\t'g',\n\t);\n}\n\n/**\n * Each of the stack's services the environment reaches on the stack's\n * network, once: `postgres:5432`, `minio:9000`.\n */\nexport function stackAddresses(\n\tenv: Readonly<Record<string, string>>,\n\tstack: Pick<ComposeStack, 'infra'>,\n): StackAddress[] {\n\tconst found = new Map<string, StackAddress>();\n\tconst pattern = /(?<=[/@,])([a-z0-9-]+):(\\d+)(?!\\d)/g;\n\tfor (const value of Object.values(env)) {\n\t\tfor (const match of value.matchAll(pattern)) {\n\t\t\tconst service = match[1]!;\n\t\t\tif (!stack.infra.includes(service)) continue;\n\t\t\tconst port = Number(match[2]);\n\t\t\tfound.set(`${service}:${port}`, { service, port });\n\t\t}\n\t}\n\treturn [...found.values()];\n}\n\n/**\n * The environment as this machine reaches it: each service at its tunnel's\n * local port, and each sibling app at its public address. What has no\n * tunnel is left as the container has it.\n */\nexport function throughTunnels(\n\tenv: Readonly<Record<string, string>>,\n\tstack: Pick<ComposeStack, 'apps' | 'project'>,\n\ttunnels: ReadonlyMap<string, number>,\n): Record<string, string> {\n\tconst rewrites: [RegExp, string][] = [];\n\tfor (const [address, port] of tunnels) {\n\t\tconst [service, inside] = address.split(':');\n\t\trewrites.push([authority(service!, Number(inside)), `127.0.0.1:${port}`]);\n\t}\n\tfor (const app of stack.apps) {\n\t\tfor (const host of [app.name, edgeAlias(stack.project, app.name)]) {\n\t\t\trewrites.push([\n\t\t\t\tnew RegExp(\n\t\t\t\t\t`http://${host.replace(/[.-]/g, '\\\\$&')}:${app.port}(?!\\\\d)`,\n\t\t\t\t\t'g',\n\t\t\t\t),\n\t\t\t\tapp.url,\n\t\t\t]);\n\t\t}\n\t}\n\tconst out: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(env)) {\n\t\tout[key] = rewrites.reduce(\n\t\t\t(current, [pattern, replacement]) =>\n\t\t\t\tcurrent.replace(pattern, () => replacement),\n\t\t\tvalue,\n\t\t);\n\t}\n\treturn out;\n}\n\n/**\n * The preload that fills Credentials from the command's own environment: a\n * `data:` URL holding the keys, so no file — and no value — is written.\n */\nexport function credentialsImport(keys: readonly string[]): string {\n\tconst source =\n\t\t'globalThis.__gkm_credentials__=Object.fromEntries(' +\n\t\t`${JSON.stringify(keys)}.map((k)=>[k,process.env[k]]));`;\n\treturn `--import=data:text/javascript,${encodeURIComponent(source)}`;\n}\n\n/** A deployed compose stage, as its deploy has it, and the app here. */\nexport interface LoadedStage {\n\tworkspace: NormalizedWorkspace;\n\tmanifest: ConstructManifest;\n\tstack: ComposeStack;\n\t/** The stage's secrets, as its deploy reads them. */\n\tsecrets: StageSecrets;\n\t/** The app this directory is, if it is one. */\n\tappName: string | undefined;\n\tprotectedStage: boolean;\n}\n\n/**\n * The stage's stack, and the app this directory is, as the deploy has them:\n * its secrets read from its store, its values derived as the deploy derives\n * them. Nothing is reached but the store — no server, no SSH.\n *\n * @throws {UndeclaredStage}, {ExecStageNotComposed}, {ExecStageNotDeployed}\n */\nexport async function loadStage(\n\toptions: Pick<StageExecOptions, 'stage' | 'profile' | 'cwd'>,\n\tenv: NodeJS.ProcessEnv = process.env,\n): Promise<LoadedStage> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst { stage } = options;\n\t// Outside an app the workspace is still loaded, so the stage is checked\n\t// before the directory is refused.\n\tconst info = await loadWorkspaceAppInfo(cwd).catch((error) => {\n\t\tif (error instanceof NotInAnApp) return undefined;\n\t\tthrow error;\n\t});\n\tconst workspace =\n\t\tinfo?.workspace ?? (await loadWorkspaceConfig(cwd)).workspace;\n\n\tassertDeployedStage(workspace.stages, stage);\n\tif (!deploysWithCompose(workspace)) throw new ExecStageNotComposed(stage);\n\n\tconst runnables: Record<string, string[]> = {};\n\tconst background: Record<string, string[]> = {};\n\tconst manifest: ConstructManifest = await discover({\n\t\tpatterns: constructGlobs(workspace),\n\t\tcwd: workspace.root,\n\t\trunnables,\n\t\tbackground,\n\t});\n\n\tconst store = await secretsStoreFor(workspace, stage, {\n\t\t...(options.profile ? { profile: options.profile } : {}),\n\t});\n\tconst { secrets, generated } = deployedStackSecrets(\n\t\tworkspace,\n\t\tstage,\n\t\tawait store.read(stage),\n\t\tmanifest,\n\t);\n\tif (generated.length > 0) throw new ExecStageNotDeployed(stage, generated);\n\n\tconst stack = composeStack({\n\t\tworkspace,\n\t\tmanifest,\n\t\trunnables,\n\t\tbackground,\n\t\tstage,\n\t\tidentity: deployIdentity(workspace, stage),\n\t\t// Built, so a site's public values are resolved as its build has them.\n\t\timages: { mode: 'build', tag: 'exec' },\n\t\tsecrets,\n\t\tports: edgePorts(env),\n\t});\n\treturn {\n\t\tworkspace,\n\t\tmanifest,\n\t\tstack,\n\t\tsecrets,\n\t\tappName: info?.appName,\n\t\tprotectedStage: workspace.stages.protected?.includes(stage) ?? false,\n\t};\n}\n\n/** The stage's server, as SSH reaches it: `--ssh-user` over the config's. */\nfunction stageServer(\n\tloaded: LoadedStage,\n\toptions: StageExecOptions,\n): ComposeServer {\n\tconst server = composeServer({\n\t\tstage: options.stage,\n\t\tlocal: false,\n\t\tconfig: loaded.workspace.deploy?.compose?.server,\n\t\tcustom: loaded.secrets.custom,\n\t})!;\n\tif (options.sshUser) server.user = options.sshUser;\n\treturn server;\n}\n\n/**\n * Run `commandArgs` as the app this directory is, on the stage — through a\n * tunnel to each service it reaches — and return its exit code. Every tunnel\n * is closed once it exits, whatever it exits with.\n *\n * @throws {ExecStageNotComposed}, {ExecStageNotDeployed}, {ExecAppNotInStack},\n * {ExecNotConfirmed}, {ComposeServerUnreachable}\n */\nexport async function execOnStage(\n\tcommandArgs: readonly [string, ...string[]],\n\toptions: StageExecOptions,\n\tdeps: StageExecDeps = defaultStageExecDeps,\n): Promise<number> {\n\tconst { stage } = options;\n\tconst loaded = await loadStage(options, deps.env);\n\tconst { stack, appName, protectedStage } = loaded;\n\tconst env = appEnvironment(stack, appName);\n\n\tif (protectedStage && !options.yes) {\n\t\tconst question = `'${stage}' is a protected stage. Run ${commandArgs.join(' ')} against it?`;\n\t\tif (!(await deps.confirm(question))) throw new ExecNotConfirmed(stage);\n\t}\n\n\t// Only what reaches a service on the stack needs the server: a site's or\n\t// a mobile app's values are public addresses, and need no SSH at all.\n\tconst addresses = stackAddresses(env, stack);\n\tif (addresses.length === 0) {\n\t\tlogger.log(`📦 App: ${appName} on '${stage}'`);\n\t\tlogger.log(`🔐 Loaded ${Object.keys(env).length} value(s) for '${stage}'`);\n\t\treturn run(commandArgs, env, options.cwd);\n\t}\n\n\tconst server = stageServer(loaded, options);\n\tlogger.log(`📦 App: ${appName} on '${stage}' (${server.host})`);\n\n\t// The deploy's own check: SSH logs in and Docker answers, before any\n\t// tunnel is asked for — so a key the server refuses is said as that.\n\tawait deps.server.check(server);\n\n\tconst tunnels: Tunnel[] = [];\n\tconst ports = new Map<string, number>();\n\ttry {\n\t\tfor (const address of addresses) {\n\t\t\tconst published = await deps.docker.published(\n\t\t\t\t{ host: dockerHost(server) },\n\t\t\t\tstack.project,\n\t\t\t\taddress.service,\n\t\t\t\taddress.port,\n\t\t\t);\n\t\t\tif (published === undefined) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`⚠️ ${address.service} is not published on the server (no running ` +\n\t\t\t\t\t\t`${stack.project} ${address.service} publishes ${address.port}), so ` +\n\t\t\t\t\t\t'it is unreachable from here; its address is passed on unchanged.',\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst tunnel = await deps.server.tunnel(server, published);\n\t\t\ttunnels.push(tunnel);\n\t\t\tports.set(`${address.service}:${address.port}`, tunnel.port);\n\t\t\tlogger.log(`🚇 ${address.service} → 127.0.0.1:${tunnel.port} (over SSH)`);\n\t\t}\n\n\t\tconst credentials = throughTunnels(env, stack, ports);\n\t\tlogger.log(\n\t\t\t`🔐 Loaded ${Object.keys(credentials).length} value(s) for '${stage}'`,\n\t\t);\n\t\treturn await run(commandArgs, credentials, options.cwd);\n\t} finally {\n\t\tawait Promise.all(tunnels.map((tunnel) => tunnel.close()));\n\t}\n}\n\n/**\n * The command, with the values in its environment and its Credentials. A\n * Ctrl-C reaches it — it is in the terminal's process group — and this\n * process waits for it to exit rather than leaving before the tunnels close.\n */\nfunction run(\n\tcommandArgs: readonly [string, ...string[]],\n\tcredentials: Record<string, string>,\n\tcwd: string | undefined,\n): Promise<number> {\n\tconst [cmd, ...args] = commandArgs;\n\tlogger.log(`🚀 Running: ${commandArgs.join(' ')}`);\n\n\tconst inherited = (process.env.NODE_OPTIONS ?? '')\n\t\t.replace(/--import[= ]\\S+/g, '')\n\t\t.trim();\n\tconst nodeOptions = [inherited, credentialsImport(Object.keys(credentials))]\n\t\t.filter(Boolean)\n\t\t.join(' ');\n\n\tconst wait = () => {};\n\tprocess.on('SIGINT', wait);\n\tprocess.on('SIGTERM', wait);\n\treturn new Promise<number>((resolve) => {\n\t\tconst child = spawn(cmd, args, {\n\t\t\t...(cwd ? { cwd } : {}),\n\t\t\tstdio: 'inherit',\n\t\t\tenv: { ...process.env, ...credentials, NODE_OPTIONS: nodeOptions },\n\t\t});\n\t\tchild.on('close', (code, signal) => {\n\t\t\tresolve(code ?? 128 + (signal ? constants.signals[signal] : 0));\n\t\t});\n\t\tchild.on('error', (error) => {\n\t\t\tlogger.error(`Failed to run command: ${error.message}`);\n\t\t\tresolve(1);\n\t\t});\n\t}).finally(() => {\n\t\tprocess.off('SIGINT', wait);\n\t\tprocess.off('SIGTERM', wait);\n\t});\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
|
|
2
|
+
const require_errors = require("./errors-DMC4Umsb.cjs");
|
|
3
|
+
const require_compose = require("./compose-Mdgea4Yt.cjs");
|
|
4
|
+
const require_workspace = require("./workspace-BwqQnool.cjs");
|
|
5
|
+
const require_dns = require("./dns-BIYf20p7.cjs");
|
|
6
|
+
const require_seeds = require("./seeds-C2w4UqVP.cjs");
|
|
7
|
+
const require_identity = require("./identity-CbLfgQNT.cjs");
|
|
8
|
+
const require_discover = require("./discover-DozUKs8f.cjs");
|
|
9
|
+
const require_config = require("./config.cjs");
|
|
10
|
+
const require_index = require("./index.cjs");
|
|
11
|
+
let node_os = require("node:os");
|
|
12
|
+
let node_child_process = require("node:child_process");
|
|
13
|
+
//#region src/exec/stage.ts
|
|
14
|
+
/**
|
|
15
|
+
* `gkm exec --stage <stage> -- <command>`: a command run on this machine as
|
|
16
|
+
* a deployed compose stage's app — a data import, a backfill, a report.
|
|
17
|
+
*
|
|
18
|
+
* The app's environment is the one its container runs with, derived the way
|
|
19
|
+
* the deploy derives it (`composeStack`) from the stage's secrets, read from
|
|
20
|
+
* the stage's store the way the deploy reads them. Only what the container
|
|
21
|
+
* reaches on the stack's network is moved: each service it names that the
|
|
22
|
+
* server publishes on its loopback — Postgres, MinIO — is reached through an
|
|
23
|
+
* SSH tunnel on the deploy's own login (`ServerAccess.tunnel`), and each
|
|
24
|
+
* sibling app through its public address.
|
|
25
|
+
*
|
|
26
|
+
* Nothing is written to disk. The values exist only in the command's
|
|
27
|
+
* environment, and its Credentials are filled from there by a preload that
|
|
28
|
+
* is a `data:` URL naming the keys — never their values.
|
|
29
|
+
*/
|
|
30
|
+
var stage_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
|
|
31
|
+
ExecAppNotInStack: () => ExecAppNotInStack,
|
|
32
|
+
ExecNotConfirmed: () => ExecNotConfirmed,
|
|
33
|
+
ExecStageNotComposed: () => ExecStageNotComposed,
|
|
34
|
+
ExecStageNotDeployed: () => ExecStageNotDeployed,
|
|
35
|
+
appEnvironment: () => appEnvironment,
|
|
36
|
+
credentialsImport: () => credentialsImport,
|
|
37
|
+
defaultStageExecDeps: () => defaultStageExecDeps,
|
|
38
|
+
execOnStage: () => execOnStage,
|
|
39
|
+
loadStage: () => loadStage,
|
|
40
|
+
stackAddresses: () => stackAddresses,
|
|
41
|
+
throughTunnels: () => throughTunnels
|
|
42
|
+
});
|
|
43
|
+
const logger = console;
|
|
44
|
+
/** The stage is not one the compose target deploys. */
|
|
45
|
+
var ExecStageNotComposed = class extends require_errors.GkmError {
|
|
46
|
+
stage;
|
|
47
|
+
constructor(stage) {
|
|
48
|
+
super(`gkm exec --stage runs a command against a compose stage's server, and '${stage}' is not deployed with compose. Set deploy.default: 'compose' in gkm.config.ts, or run the command where the stage runs.`);
|
|
49
|
+
this.stage = stage;
|
|
50
|
+
this.name = "ExecStageNotComposed";
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/** The stage's secrets lack what its deploy generates: it was never deployed. */
|
|
54
|
+
var ExecStageNotDeployed = class extends require_errors.GkmError {
|
|
55
|
+
stage;
|
|
56
|
+
missing;
|
|
57
|
+
constructor(stage, missing) {
|
|
58
|
+
super(`'${stage}' has no ${missing.join(", ")} in its secrets yet, so what its apps run with is not decided. Deploy it first: gkm deploy --stage ${stage}.`);
|
|
59
|
+
this.stage = stage;
|
|
60
|
+
this.missing = missing;
|
|
61
|
+
this.name = "ExecStageNotDeployed";
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
/** The directory is not one of the stack's apps. */
|
|
65
|
+
var ExecAppNotInStack = class extends require_errors.GkmError {
|
|
66
|
+
stage;
|
|
67
|
+
app;
|
|
68
|
+
apps;
|
|
69
|
+
constructor(stage, app, apps) {
|
|
70
|
+
super(`${app ? `'${app}' is not` : "This directory is not in"} one of the apps '${stage}' runs (${apps.join(", ")}), so there is no environment to run as. Run from an app's directory: cd apps/${apps[0] ?? "<app>"} && gkm exec --stage ${stage} -- <command>.`);
|
|
71
|
+
this.stage = stage;
|
|
72
|
+
this.app = app;
|
|
73
|
+
this.apps = apps;
|
|
74
|
+
this.name = "ExecAppNotInStack";
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/** A protected stage, and nobody said yes. */
|
|
78
|
+
var ExecNotConfirmed = class extends require_errors.GkmError {
|
|
79
|
+
stage;
|
|
80
|
+
constructor(stage) {
|
|
81
|
+
super(`Nothing was run against '${stage}'.`);
|
|
82
|
+
this.stage = stage;
|
|
83
|
+
this.name = "ExecNotConfirmed";
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const defaultStageExecDeps = {
|
|
87
|
+
docker: require_compose.dockerCompose,
|
|
88
|
+
server: require_compose.sshAccess,
|
|
89
|
+
confirm: async (question) => {
|
|
90
|
+
const answer = await require_index.prompt(`${question} [y/N] `, { instead: "Pass --yes to run without asking." });
|
|
91
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
92
|
+
},
|
|
93
|
+
env: process.env
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* The environment an app runs with on the stage: a backend's container's,
|
|
97
|
+
* over the keys of each worker built from it; a site's or a mobile app's,
|
|
98
|
+
* the public values its build reads.
|
|
99
|
+
*
|
|
100
|
+
* @throws {ExecAppNotInStack}
|
|
101
|
+
*/
|
|
102
|
+
function appEnvironment(stack, appName) {
|
|
103
|
+
const mobile = stack.mobileApps.find((candidate) => candidate.name === appName);
|
|
104
|
+
if (mobile) return { ...mobile.values };
|
|
105
|
+
const app = stack.apps.find((candidate) => candidate.name === appName);
|
|
106
|
+
if (!app) throw new ExecAppNotInStack(stack.stage, appName, [...stack.apps.map((candidate) => candidate.name), ...stack.mobileApps.map((candidate) => candidate.name)]);
|
|
107
|
+
if (app.kind === "site") return { ...app.build?.args };
|
|
108
|
+
const workers = stack.workers.filter((worker) => worker.host === app.name);
|
|
109
|
+
return Object.assign({}, ...workers.map((worker) => worker.env ?? {}), app.env ?? {});
|
|
110
|
+
}
|
|
111
|
+
/** `host:port`, at a URL's authority — after `//` or a login's `@`. */
|
|
112
|
+
function authority(host, port) {
|
|
113
|
+
return new RegExp(`(?<=[/@,])${host.replace(/[.-]/g, "\\$&")}:${port}(?!\\d)`, "g");
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Each of the stack's services the environment reaches on the stack's
|
|
117
|
+
* network, once: `postgres:5432`, `minio:9000`.
|
|
118
|
+
*/
|
|
119
|
+
function stackAddresses(env, stack) {
|
|
120
|
+
const found = /* @__PURE__ */ new Map();
|
|
121
|
+
const pattern = /(?<=[/@,])([a-z0-9-]+):(\d+)(?!\d)/g;
|
|
122
|
+
for (const value of Object.values(env)) for (const match of value.matchAll(pattern)) {
|
|
123
|
+
const service = match[1];
|
|
124
|
+
if (!stack.infra.includes(service)) continue;
|
|
125
|
+
const port = Number(match[2]);
|
|
126
|
+
found.set(`${service}:${port}`, {
|
|
127
|
+
service,
|
|
128
|
+
port
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return [...found.values()];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The environment as this machine reaches it: each service at its tunnel's
|
|
135
|
+
* local port, and each sibling app at its public address. What has no
|
|
136
|
+
* tunnel is left as the container has it.
|
|
137
|
+
*/
|
|
138
|
+
function throughTunnels(env, stack, tunnels) {
|
|
139
|
+
const rewrites = [];
|
|
140
|
+
for (const [address, port] of tunnels) {
|
|
141
|
+
const [service, inside] = address.split(":");
|
|
142
|
+
rewrites.push([authority(service, Number(inside)), `127.0.0.1:${port}`]);
|
|
143
|
+
}
|
|
144
|
+
for (const app of stack.apps) for (const host of [app.name, require_compose.edgeAlias(stack.project, app.name)]) rewrites.push([new RegExp(`http://${host.replace(/[.-]/g, "\\$&")}:${app.port}(?!\\d)`, "g"), app.url]);
|
|
145
|
+
const out = {};
|
|
146
|
+
for (const [key, value] of Object.entries(env)) out[key] = rewrites.reduce((current, [pattern, replacement]) => current.replace(pattern, () => replacement), value);
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The preload that fills Credentials from the command's own environment: a
|
|
151
|
+
* `data:` URL holding the keys, so no file — and no value — is written.
|
|
152
|
+
*/
|
|
153
|
+
function credentialsImport(keys) {
|
|
154
|
+
const source = `globalThis.__gkm_credentials__=Object.fromEntries(${JSON.stringify(keys)}.map((k)=>[k,process.env[k]]));`;
|
|
155
|
+
return `--import=data:text/javascript,${encodeURIComponent(source)}`;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* The stage's stack, and the app this directory is, as the deploy has them:
|
|
159
|
+
* its secrets read from its store, its values derived as the deploy derives
|
|
160
|
+
* them. Nothing is reached but the store — no server, no SSH.
|
|
161
|
+
*
|
|
162
|
+
* @throws {UndeclaredStage}, {ExecStageNotComposed}, {ExecStageNotDeployed}
|
|
163
|
+
*/
|
|
164
|
+
async function loadStage(options, env = process.env) {
|
|
165
|
+
const cwd = options.cwd ?? process.cwd();
|
|
166
|
+
const { stage } = options;
|
|
167
|
+
const info = await require_config.loadWorkspaceAppInfo(cwd).catch((error) => {
|
|
168
|
+
if (error instanceof require_config.NotInAnApp) return void 0;
|
|
169
|
+
throw error;
|
|
170
|
+
});
|
|
171
|
+
const workspace = info?.workspace ?? (await require_config.loadWorkspaceConfig(cwd)).workspace;
|
|
172
|
+
require_workspace.assertDeployedStage(workspace.stages, stage);
|
|
173
|
+
if (!require_dns.deploysWithCompose(workspace)) throw new ExecStageNotComposed(stage);
|
|
174
|
+
const runnables = {};
|
|
175
|
+
const background = {};
|
|
176
|
+
const manifest = await require_discover.discover({
|
|
177
|
+
patterns: require_seeds.constructGlobs(workspace),
|
|
178
|
+
cwd: workspace.root,
|
|
179
|
+
runnables,
|
|
180
|
+
background
|
|
181
|
+
});
|
|
182
|
+
const store = await require_seeds.secretsStoreFor(workspace, stage, { ...options.profile ? { profile: options.profile } : {} });
|
|
183
|
+
const { secrets, generated } = require_compose.deployedStackSecrets(workspace, stage, await store.read(stage), manifest);
|
|
184
|
+
if (generated.length > 0) throw new ExecStageNotDeployed(stage, generated);
|
|
185
|
+
return {
|
|
186
|
+
workspace,
|
|
187
|
+
manifest,
|
|
188
|
+
stack: require_compose.composeStack({
|
|
189
|
+
workspace,
|
|
190
|
+
manifest,
|
|
191
|
+
runnables,
|
|
192
|
+
background,
|
|
193
|
+
stage,
|
|
194
|
+
identity: require_identity.deployIdentity(workspace, stage),
|
|
195
|
+
images: {
|
|
196
|
+
mode: "build",
|
|
197
|
+
tag: "exec"
|
|
198
|
+
},
|
|
199
|
+
secrets,
|
|
200
|
+
ports: require_compose.edgePorts(env)
|
|
201
|
+
}),
|
|
202
|
+
secrets,
|
|
203
|
+
appName: info?.appName,
|
|
204
|
+
protectedStage: workspace.stages.protected?.includes(stage) ?? false
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/** The stage's server, as SSH reaches it: `--ssh-user` over the config's. */
|
|
208
|
+
function stageServer(loaded, options) {
|
|
209
|
+
const server = require_compose.composeServer({
|
|
210
|
+
stage: options.stage,
|
|
211
|
+
local: false,
|
|
212
|
+
config: loaded.workspace.deploy?.compose?.server,
|
|
213
|
+
custom: loaded.secrets.custom
|
|
214
|
+
});
|
|
215
|
+
if (options.sshUser) server.user = options.sshUser;
|
|
216
|
+
return server;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Run `commandArgs` as the app this directory is, on the stage — through a
|
|
220
|
+
* tunnel to each service it reaches — and return its exit code. Every tunnel
|
|
221
|
+
* is closed once it exits, whatever it exits with.
|
|
222
|
+
*
|
|
223
|
+
* @throws {ExecStageNotComposed}, {ExecStageNotDeployed}, {ExecAppNotInStack},
|
|
224
|
+
* {ExecNotConfirmed}, {ComposeServerUnreachable}
|
|
225
|
+
*/
|
|
226
|
+
async function execOnStage(commandArgs, options, deps = defaultStageExecDeps) {
|
|
227
|
+
const { stage } = options;
|
|
228
|
+
const loaded = await loadStage(options, deps.env);
|
|
229
|
+
const { stack, appName, protectedStage } = loaded;
|
|
230
|
+
const env = appEnvironment(stack, appName);
|
|
231
|
+
if (protectedStage && !options.yes) {
|
|
232
|
+
const question = `'${stage}' is a protected stage. Run ${commandArgs.join(" ")} against it?`;
|
|
233
|
+
if (!await deps.confirm(question)) throw new ExecNotConfirmed(stage);
|
|
234
|
+
}
|
|
235
|
+
const addresses = stackAddresses(env, stack);
|
|
236
|
+
if (addresses.length === 0) {
|
|
237
|
+
logger.log(`📦 App: ${appName} on '${stage}'`);
|
|
238
|
+
logger.log(`🔐 Loaded ${Object.keys(env).length} value(s) for '${stage}'`);
|
|
239
|
+
return run(commandArgs, env, options.cwd);
|
|
240
|
+
}
|
|
241
|
+
const server = stageServer(loaded, options);
|
|
242
|
+
logger.log(`📦 App: ${appName} on '${stage}' (${server.host})`);
|
|
243
|
+
await deps.server.check(server);
|
|
244
|
+
const tunnels = [];
|
|
245
|
+
const ports = /* @__PURE__ */ new Map();
|
|
246
|
+
try {
|
|
247
|
+
for (const address of addresses) {
|
|
248
|
+
const published = await deps.docker.published({ host: require_compose.dockerHost(server) }, stack.project, address.service, address.port);
|
|
249
|
+
if (published === void 0) {
|
|
250
|
+
logger.log(`⚠️ ${address.service} is not published on the server (no running ${stack.project} ${address.service} publishes ${address.port}), so it is unreachable from here; its address is passed on unchanged.`);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
const tunnel = await deps.server.tunnel(server, published);
|
|
254
|
+
tunnels.push(tunnel);
|
|
255
|
+
ports.set(`${address.service}:${address.port}`, tunnel.port);
|
|
256
|
+
logger.log(`🚇 ${address.service} → 127.0.0.1:${tunnel.port} (over SSH)`);
|
|
257
|
+
}
|
|
258
|
+
const credentials = throughTunnels(env, stack, ports);
|
|
259
|
+
logger.log(`🔐 Loaded ${Object.keys(credentials).length} value(s) for '${stage}'`);
|
|
260
|
+
return await run(commandArgs, credentials, options.cwd);
|
|
261
|
+
} finally {
|
|
262
|
+
await Promise.all(tunnels.map((tunnel) => tunnel.close()));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* The command, with the values in its environment and its Credentials. A
|
|
267
|
+
* Ctrl-C reaches it — it is in the terminal's process group — and this
|
|
268
|
+
* process waits for it to exit rather than leaving before the tunnels close.
|
|
269
|
+
*/
|
|
270
|
+
function run(commandArgs, credentials, cwd) {
|
|
271
|
+
const [cmd, ...args] = commandArgs;
|
|
272
|
+
logger.log(`🚀 Running: ${commandArgs.join(" ")}`);
|
|
273
|
+
const nodeOptions = [(process.env.NODE_OPTIONS ?? "").replace(/--import[= ]\S+/g, "").trim(), credentialsImport(Object.keys(credentials))].filter(Boolean).join(" ");
|
|
274
|
+
const wait = () => {};
|
|
275
|
+
process.on("SIGINT", wait);
|
|
276
|
+
process.on("SIGTERM", wait);
|
|
277
|
+
return new Promise((resolve) => {
|
|
278
|
+
const child = (0, node_child_process.spawn)(cmd, args, {
|
|
279
|
+
...cwd ? { cwd } : {},
|
|
280
|
+
stdio: "inherit",
|
|
281
|
+
env: {
|
|
282
|
+
...process.env,
|
|
283
|
+
...credentials,
|
|
284
|
+
NODE_OPTIONS: nodeOptions
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
child.on("close", (code, signal) => {
|
|
288
|
+
resolve(code ?? 128 + (signal ? node_os.constants.signals[signal] : 0));
|
|
289
|
+
});
|
|
290
|
+
child.on("error", (error) => {
|
|
291
|
+
logger.error(`Failed to run command: ${error.message}`);
|
|
292
|
+
resolve(1);
|
|
293
|
+
});
|
|
294
|
+
}).finally(() => {
|
|
295
|
+
process.off("SIGINT", wait);
|
|
296
|
+
process.off("SIGTERM", wait);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
//#endregion
|
|
300
|
+
Object.defineProperty(exports, "loadStage", {
|
|
301
|
+
enumerable: true,
|
|
302
|
+
get: function() {
|
|
303
|
+
return loadStage;
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
Object.defineProperty(exports, "stage_exports", {
|
|
307
|
+
enumerable: true,
|
|
308
|
+
get: function() {
|
|
309
|
+
return stage_exports;
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
//# sourceMappingURL=stage-DEQJGW3r.cjs.map
|