@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,222 @@
|
|
|
1
|
+
import { t as GkmError } from "./errors-D8Gwp5kU.mjs";
|
|
2
|
+
import "./identity-CBXr4wNi.mjs";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
//#region src/providers/projectBucket.ts
|
|
5
|
+
/**
|
|
6
|
+
* The project bucket: one S3 bucket per project and AWS account, created and
|
|
7
|
+
* owned by gkm, that holds what gkm keeps for every stage — the deploy state
|
|
8
|
+
* under `<prefix>/<project>/<stage>/`, and anything else gkm writes per stage
|
|
9
|
+
* beside it.
|
|
10
|
+
*
|
|
11
|
+
* Nothing can record its name — the deploy state lives in it — so the name is
|
|
12
|
+
* worked out the same way every time: `gkm-<scope>-<account id>`, the scope
|
|
13
|
+
* being the one the `s3` objects provider names its buckets with. The account
|
|
14
|
+
* id keeps it from clashing with another account's project of the same name
|
|
15
|
+
* without a random suffix; a clash that happens anyway (HeadBucket 403) is
|
|
16
|
+
* refused, never adopted.
|
|
17
|
+
*
|
|
18
|
+
* Created with versioning, SSE-S3, every public access blocked, ownership
|
|
19
|
+
* enforced for the bucket owner, a lifecycle that expires old versions, and
|
|
20
|
+
* the tag `gkm:project=<identity key>`.
|
|
21
|
+
*/
|
|
22
|
+
/** What the project part may take: 63 less `gkm-`, `-` and a 12-digit id. */
|
|
23
|
+
const SCOPE_MAX = 46;
|
|
24
|
+
/** The tag the bucket is created with, as the `s3` provider tags its own. */
|
|
25
|
+
const PROJECT_BUCKET_TAG = "gkm:project";
|
|
26
|
+
/** The bucket's name is held by another account, or cannot be reached. */
|
|
27
|
+
var ProjectBucketTaken = class extends GkmError {
|
|
28
|
+
bucket;
|
|
29
|
+
status;
|
|
30
|
+
constructor(bucket, status) {
|
|
31
|
+
super(`The project bucket '${bucket}' ${status === 301 ? "is in another region than the one configured" : "exists and this account cannot reach it — another account holds the name"} (HTTP ${status}). Name a bucket you own instead — in gkm.config.ts: state: { provider: 's3', bucket: '<your bucket>', region: '<its region>' } — or run with the credentials of the account the name is for.`);
|
|
32
|
+
this.bucket = bucket;
|
|
33
|
+
this.status = status;
|
|
34
|
+
this.name = "ProjectBucketTaken";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
/** The running credentials may not create the project bucket. */
|
|
38
|
+
var ProjectBucketNotCreatable = class extends GkmError {
|
|
39
|
+
bucket;
|
|
40
|
+
reason;
|
|
41
|
+
constructor(bucket, reason) {
|
|
42
|
+
super(`The project bucket '${bucket}' does not exist yet, and these credentials cannot create it (${reason}). Run the first deploy with credentials allowed s3:CreateBucket and the bucket put-config actions on it — \`gkm deploy:github\` grants them to the CI role — or name an existing bucket: state: { provider: 's3', bucket, region }.`);
|
|
43
|
+
this.bucket = bucket;
|
|
44
|
+
this.reason = reason;
|
|
45
|
+
this.name = "ProjectBucketNotCreatable";
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/** {@link projectBucket}, from a deploy identity's scope. */
|
|
49
|
+
function projectBucketName(scope, accountId) {
|
|
50
|
+
let part = scope.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
51
|
+
if (part.length > SCOPE_MAX) {
|
|
52
|
+
const hash = createHash("sha256").update(scope).digest("hex").slice(0, 6);
|
|
53
|
+
part = `${part.slice(0, 39).replace(/-+$/, "")}-${hash}`;
|
|
54
|
+
}
|
|
55
|
+
return `gkm-${part}-${accountId}`;
|
|
56
|
+
}
|
|
57
|
+
/** The account the credentials are in — what the bucket is named by. */
|
|
58
|
+
async function callerAccountId(sts) {
|
|
59
|
+
const { GetCallerIdentityCommand } = await import("@aws-sdk/client-sts");
|
|
60
|
+
const { Account } = await sts.send(new GetCallerIdentityCommand({}));
|
|
61
|
+
return Account ?? "";
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The bucket's whole lifecycle configuration. A put replaces every rule the
|
|
65
|
+
* bucket has, so this is the one place the set is built: the bucket's own
|
|
66
|
+
* noncurrent-version expiry, and any per-prefix expiry passed in.
|
|
67
|
+
*/
|
|
68
|
+
function projectBucketLifecycle(expiries = []) {
|
|
69
|
+
return [{
|
|
70
|
+
ID: "gkm-noncurrent-versions",
|
|
71
|
+
Status: "Enabled",
|
|
72
|
+
Filter: { Prefix: "" },
|
|
73
|
+
NoncurrentVersionExpiration: { NoncurrentDays: 90 },
|
|
74
|
+
Expiration: { ExpiredObjectDeleteMarker: true }
|
|
75
|
+
}, ...expiries.map((expiry) => ({
|
|
76
|
+
ID: expiry.id,
|
|
77
|
+
Status: "Enabled",
|
|
78
|
+
Filter: { Prefix: expiry.prefix },
|
|
79
|
+
Expiration: { Days: expiry.days },
|
|
80
|
+
...expiry.abortIncompleteDays ? { AbortIncompleteMultipartUpload: { DaysAfterInitiation: expiry.abortIncompleteDays } } : {}
|
|
81
|
+
}))];
|
|
82
|
+
}
|
|
83
|
+
/** A lifecycle rule reduced to what gkm sets, for comparing with what is there. */
|
|
84
|
+
function canonicalRule(rule) {
|
|
85
|
+
return JSON.stringify({
|
|
86
|
+
id: rule.ID ?? "",
|
|
87
|
+
status: rule.Status ?? "",
|
|
88
|
+
prefix: rule.Filter?.Prefix ?? rule.Prefix ?? "",
|
|
89
|
+
days: rule.Expiration?.Days ?? null,
|
|
90
|
+
markers: rule.Expiration?.ExpiredObjectDeleteMarker ?? null,
|
|
91
|
+
noncurrent: rule.NoncurrentVersionExpiration?.NoncurrentDays ?? null,
|
|
92
|
+
abort: rule.AbortIncompleteMultipartUpload?.DaysAfterInitiation ?? null
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/** Whether two rule sets say the same thing, in any order. */
|
|
96
|
+
function sameLifecycle(a, b) {
|
|
97
|
+
const canonical = (rules) => rules.map(canonicalRule).sort().join("\n");
|
|
98
|
+
return canonical(a) === canonical(b);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The project bucket's lifecycle put to {@link projectBucketLifecycle} of
|
|
102
|
+
* `expiries` — every stage's — when what it holds says anything else.
|
|
103
|
+
* Returns whether it was put; with `dryRun`, whether it would be.
|
|
104
|
+
*/
|
|
105
|
+
async function reconcileProjectBucketLifecycle(s3, bucket, expiries, options = {}) {
|
|
106
|
+
const S3 = await import("@aws-sdk/client-s3");
|
|
107
|
+
const rules = projectBucketLifecycle(expiries);
|
|
108
|
+
let current = [];
|
|
109
|
+
try {
|
|
110
|
+
current = (await s3.send(new S3.GetBucketLifecycleConfigurationCommand({ Bucket: bucket }))).Rules ?? [];
|
|
111
|
+
} catch (error) {
|
|
112
|
+
const failure = error;
|
|
113
|
+
if ((failure.Code ?? failure.name) !== "NoSuchLifecycleConfiguration") throw error;
|
|
114
|
+
}
|
|
115
|
+
if (sameLifecycle(current, rules)) return false;
|
|
116
|
+
if (!options.dryRun) await s3.send(new S3.PutBucketLifecycleConfigurationCommand({
|
|
117
|
+
Bucket: bucket,
|
|
118
|
+
LifecycleConfiguration: { Rules: rules }
|
|
119
|
+
}));
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Whether `bucket` is this account's (`ours`) or does not exist (`none`).
|
|
124
|
+
* Mapped by status: a HEAD has no body, so SDK v3 names a 301, 400 or 403
|
|
125
|
+
* `Unknown`.
|
|
126
|
+
*
|
|
127
|
+
* @throws {ProjectBucketTaken} on a 403 or 301
|
|
128
|
+
*/
|
|
129
|
+
async function findProjectBucket(s3, bucket) {
|
|
130
|
+
const { HeadBucketCommand } = await import("@aws-sdk/client-s3");
|
|
131
|
+
try {
|
|
132
|
+
await s3.send(new HeadBucketCommand({ Bucket: bucket }));
|
|
133
|
+
return "ours";
|
|
134
|
+
} catch (error) {
|
|
135
|
+
const status = error.$metadata?.httpStatusCode;
|
|
136
|
+
if (status === 404) return "none";
|
|
137
|
+
if (status === 403 || status === 301) throw new ProjectBucketTaken(bucket, status);
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The project bucket, created and configured if it does not exist yet.
|
|
143
|
+
* Returns whether this call created it. One that exists is used as it is.
|
|
144
|
+
*
|
|
145
|
+
* @throws {ProjectBucketTaken} when another account holds the name
|
|
146
|
+
* @throws {ProjectBucketNotCreatable} when the credentials may not create it
|
|
147
|
+
*/
|
|
148
|
+
async function ensureProjectBucket(s3, options) {
|
|
149
|
+
const { bucket: Bucket, region } = options;
|
|
150
|
+
if (await findProjectBucket(s3, Bucket) === "ours") return { created: false };
|
|
151
|
+
const S3 = await import("@aws-sdk/client-s3");
|
|
152
|
+
try {
|
|
153
|
+
await s3.send(new S3.CreateBucketCommand({
|
|
154
|
+
Bucket,
|
|
155
|
+
ObjectOwnership: "BucketOwnerEnforced",
|
|
156
|
+
...region === "us-east-1" ? {} : { CreateBucketConfiguration: { LocationConstraint: region } }
|
|
157
|
+
}));
|
|
158
|
+
} catch (error) {
|
|
159
|
+
const failure = error;
|
|
160
|
+
const code = failure.Code ?? failure.name;
|
|
161
|
+
if (code !== "BucketAlreadyOwnedByYou") {
|
|
162
|
+
if (code === "BucketAlreadyExists") throw new ProjectBucketTaken(Bucket, 409);
|
|
163
|
+
if (code === "AccessDenied" || failure.$metadata?.httpStatusCode === 403) throw new ProjectBucketNotCreatable(Bucket, failure.message ?? "AccessDenied");
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
await s3.send(new S3.PutPublicAccessBlockCommand({
|
|
168
|
+
Bucket,
|
|
169
|
+
PublicAccessBlockConfiguration: {
|
|
170
|
+
BlockPublicAcls: true,
|
|
171
|
+
IgnorePublicAcls: true,
|
|
172
|
+
BlockPublicPolicy: true,
|
|
173
|
+
RestrictPublicBuckets: true
|
|
174
|
+
}
|
|
175
|
+
}));
|
|
176
|
+
await s3.send(new S3.PutBucketOwnershipControlsCommand({
|
|
177
|
+
Bucket,
|
|
178
|
+
OwnershipControls: { Rules: [{ ObjectOwnership: "BucketOwnerEnforced" }] }
|
|
179
|
+
}));
|
|
180
|
+
await s3.send(new S3.PutBucketEncryptionCommand({
|
|
181
|
+
Bucket,
|
|
182
|
+
ServerSideEncryptionConfiguration: { Rules: [{ ApplyServerSideEncryptionByDefault: { SSEAlgorithm: "AES256" } }] }
|
|
183
|
+
}));
|
|
184
|
+
await s3.send(new S3.PutBucketVersioningCommand({
|
|
185
|
+
Bucket,
|
|
186
|
+
VersioningConfiguration: { Status: "Enabled" }
|
|
187
|
+
}));
|
|
188
|
+
await s3.send(new S3.PutBucketLifecycleConfigurationCommand({
|
|
189
|
+
Bucket,
|
|
190
|
+
LifecycleConfiguration: { Rules: projectBucketLifecycle(options.expiries) }
|
|
191
|
+
}));
|
|
192
|
+
await s3.send(new S3.PutBucketTaggingCommand({
|
|
193
|
+
Bucket,
|
|
194
|
+
Tagging: { TagSet: [{
|
|
195
|
+
Key: PROJECT_BUCKET_TAG,
|
|
196
|
+
Value: options.identity.key
|
|
197
|
+
}] }
|
|
198
|
+
}));
|
|
199
|
+
return { created: true };
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* The IAM actions creating and configuring the project bucket takes — what a
|
|
203
|
+
* role that runs the first deploy needs on it, beside object access.
|
|
204
|
+
*/
|
|
205
|
+
const PROJECT_BUCKET_CREATE_ACTIONS = [
|
|
206
|
+
"s3:CreateBucket",
|
|
207
|
+
"s3:PutBucketVersioning",
|
|
208
|
+
"s3:PutEncryptionConfiguration",
|
|
209
|
+
"s3:PutBucketPublicAccessBlock",
|
|
210
|
+
"s3:PutBucketOwnershipControls",
|
|
211
|
+
"s3:PutLifecycleConfiguration",
|
|
212
|
+
"s3:PutBucketTagging"
|
|
213
|
+
];
|
|
214
|
+
/**
|
|
215
|
+
* What keeping the project bucket's lifecycle takes on a bucket that exists:
|
|
216
|
+
* reading it, to put it back only when it drifted.
|
|
217
|
+
*/
|
|
218
|
+
const PROJECT_BUCKET_LIFECYCLE_ACTIONS = ["s3:GetLifecycleConfiguration", "s3:PutLifecycleConfiguration"];
|
|
219
|
+
//#endregion
|
|
220
|
+
export { findProjectBucket as a, ensureProjectBucket as i, PROJECT_BUCKET_LIFECYCLE_ACTIONS as n, projectBucketName as o, callerAccountId as r, reconcileProjectBucketLifecycle as s, PROJECT_BUCKET_CREATE_ACTIONS as t };
|
|
221
|
+
|
|
222
|
+
//# sourceMappingURL=projectBucket-C_DN4WzF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectBucket-C_DN4WzF.mjs","names":[],"sources":["../src/providers/projectBucket.ts"],"sourcesContent":["/**\n * The project bucket: one S3 bucket per project and AWS account, created and\n * owned by gkm, that holds what gkm keeps for every stage — the deploy state\n * under `<prefix>/<project>/<stage>/`, and anything else gkm writes per stage\n * beside it.\n *\n * Nothing can record its name — the deploy state lives in it — so the name is\n * worked out the same way every time: `gkm-<scope>-<account id>`, the scope\n * being the one the `s3` objects provider names its buckets with. The account\n * id keeps it from clashing with another account's project of the same name\n * without a random suffix; a clash that happens anyway (HeadBucket 403) is\n * refused, never adopted.\n *\n * Created with versioning, SSE-S3, every public access blocked, ownership\n * enforced for the bucket owner, a lifecycle that expires old versions, and\n * the tag `gkm:project=<identity key>`.\n */\n\nimport { createHash } from 'node:crypto';\nimport type {\n\tBucketLocationConstraint,\n\tLifecycleRule,\n\tS3Client,\n} from '@aws-sdk/client-s3';\nimport type { STSClient } from '@aws-sdk/client-sts';\nimport { type DeployIdentity, deployIdentity } from '../deploy/identity.js';\nimport { GkmError } from '../errors';\n\n/** S3's limit on a bucket name. */\nconst BUCKET_NAME_MAX = 63;\n/** What the project part may take: 63 less `gkm-`, `-` and a 12-digit id. */\nconst SCOPE_MAX = BUCKET_NAME_MAX - 'gkm-'.length - 1 - 12;\n\n/** The tag the bucket is created with, as the `s3` provider tags its own. */\nexport const PROJECT_BUCKET_TAG = 'gkm:project';\n\n/** How long a replaced or deleted object's old version is kept. */\nexport const NONCURRENT_VERSION_DAYS = 90;\n\n/** The bucket's name is held by another account, or cannot be reached. */\nexport class ProjectBucketTaken extends GkmError {\n\tconstructor(\n\t\treadonly bucket: string,\n\t\t/** HeadBucket's status: 403 another account's, 301 another region's. */\n\t\treadonly status: number,\n\t) {\n\t\tconst why =\n\t\t\tstatus === 301\n\t\t\t\t? 'is in another region than the one configured'\n\t\t\t\t: 'exists and this account cannot reach it — another account holds the name';\n\t\tsuper(\n\t\t\t`The project bucket '${bucket}' ${why} (HTTP ${status}). Name a bucket ` +\n\t\t\t\t\"you own instead — in gkm.config.ts: state: { provider: 's3', \" +\n\t\t\t\t\"bucket: '<your bucket>', region: '<its region>' } — or run with the \" +\n\t\t\t\t'credentials of the account the name is for.',\n\t\t);\n\t\tthis.name = 'ProjectBucketTaken';\n\t}\n}\n\n/** The running credentials may not create the project bucket. */\nexport class ProjectBucketNotCreatable extends GkmError {\n\tconstructor(\n\t\treadonly bucket: string,\n\t\treadonly reason: string,\n\t) {\n\t\tsuper(\n\t\t\t`The project bucket '${bucket}' does not exist yet, and these ` +\n\t\t\t\t`credentials cannot create it (${reason}). Run the first deploy with ` +\n\t\t\t\t'credentials allowed s3:CreateBucket and the bucket put-config ' +\n\t\t\t\t'actions on it — `gkm deploy:github` grants them to the CI role — ' +\n\t\t\t\t\"or name an existing bucket: state: { provider: 's3', bucket, region }.\",\n\t\t);\n\t\tthis.name = 'ProjectBucketNotCreatable';\n\t}\n}\n\n/**\n * The project bucket's name: `gkm-<scope>-<account id>`, lowercase and\n * DNS-safe. A scope too long to fit keeps its start and ends in a hash of\n * the whole, so two long scopes never share a name.\n */\nexport function projectBucket(\n\tworkspace: { name: string; deploy?: { namespace?: string } },\n\toptions: { accountId: string },\n): string {\n\tconst { scope } = deployIdentity(workspace, '');\n\treturn projectBucketName(scope, options.accountId);\n}\n\n/** {@link projectBucket}, from a deploy identity's scope. */\nexport function projectBucketName(scope: string, accountId: string): string {\n\tlet part = scope\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, '-')\n\t\t.replace(/^-+|-+$/g, '');\n\tif (part.length > SCOPE_MAX) {\n\t\tconst hash = createHash('sha256').update(scope).digest('hex').slice(0, 6);\n\t\tpart = `${part.slice(0, SCOPE_MAX - 7).replace(/-+$/, '')}-${hash}`;\n\t}\n\treturn `gkm-${part}-${accountId}`;\n}\n\n/** The account the credentials are in — what the bucket is named by. */\nexport async function callerAccountId(sts: STSClient): Promise<string> {\n\tconst { GetCallerIdentityCommand } = await import('@aws-sdk/client-sts');\n\tconst { Account } = await sts.send(new GetCallerIdentityCommand({}));\n\treturn Account ?? '';\n}\n\n/** An expiry for one stage's prefix, added beside the bucket's own rule. */\nexport interface PrefixExpiry {\n\t/** Rule id, unique in the bucket — e.g. `backups-production`. */\n\tid: string;\n\t/** Key prefix it applies to — e.g. `gkm/acme/production/backups/`. */\n\tprefix: string;\n\t/** Days after which a current object expires. */\n\tdays: number;\n\t/**\n\t * Days after which a multipart upload under the prefix that never\n\t * completed is aborted — its parts are stored, and billed, until it is.\n\t */\n\tabortIncompleteDays?: number;\n}\n\n/**\n * The bucket's whole lifecycle configuration. A put replaces every rule the\n * bucket has, so this is the one place the set is built: the bucket's own\n * noncurrent-version expiry, and any per-prefix expiry passed in.\n */\nexport function projectBucketLifecycle(\n\texpiries: readonly PrefixExpiry[] = [],\n): LifecycleRule[] {\n\treturn [\n\t\t{\n\t\t\tID: 'gkm-noncurrent-versions',\n\t\t\tStatus: 'Enabled',\n\t\t\tFilter: { Prefix: '' },\n\t\t\tNoncurrentVersionExpiration: { NoncurrentDays: NONCURRENT_VERSION_DAYS },\n\t\t\t// A lock is deleted every run; its markers go once nothing is under them.\n\t\t\tExpiration: { ExpiredObjectDeleteMarker: true },\n\t\t},\n\t\t...expiries.map(\n\t\t\t(expiry): LifecycleRule => ({\n\t\t\t\tID: expiry.id,\n\t\t\t\tStatus: 'Enabled',\n\t\t\t\tFilter: { Prefix: expiry.prefix },\n\t\t\t\tExpiration: { Days: expiry.days },\n\t\t\t\t...(expiry.abortIncompleteDays\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tAbortIncompleteMultipartUpload: {\n\t\t\t\t\t\t\t\tDaysAfterInitiation: expiry.abortIncompleteDays,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t}),\n\t\t),\n\t];\n}\n\n/** A lifecycle rule reduced to what gkm sets, for comparing with what is there. */\nfunction canonicalRule(rule: LifecycleRule): string {\n\treturn JSON.stringify({\n\t\tid: rule.ID ?? '',\n\t\tstatus: rule.Status ?? '',\n\t\tprefix: rule.Filter?.Prefix ?? rule.Prefix ?? '',\n\t\tdays: rule.Expiration?.Days ?? null,\n\t\tmarkers: rule.Expiration?.ExpiredObjectDeleteMarker ?? null,\n\t\tnoncurrent: rule.NoncurrentVersionExpiration?.NoncurrentDays ?? null,\n\t\tabort: rule.AbortIncompleteMultipartUpload?.DaysAfterInitiation ?? null,\n\t});\n}\n\n/** Whether two rule sets say the same thing, in any order. */\nexport function sameLifecycle(\n\ta: readonly LifecycleRule[],\n\tb: readonly LifecycleRule[],\n): boolean {\n\tconst canonical = (rules: readonly LifecycleRule[]) =>\n\t\trules.map(canonicalRule).sort().join('\\n');\n\treturn canonical(a) === canonical(b);\n}\n\n/**\n * The project bucket's lifecycle put to {@link projectBucketLifecycle} of\n * `expiries` — every stage's — when what it holds says anything else.\n * Returns whether it was put; with `dryRun`, whether it would be.\n */\nexport async function reconcileProjectBucketLifecycle(\n\ts3: S3Client,\n\tbucket: string,\n\texpiries: readonly PrefixExpiry[],\n\toptions: { dryRun?: boolean } = {},\n): Promise<boolean> {\n\tconst S3 = await import('@aws-sdk/client-s3');\n\tconst rules = projectBucketLifecycle(expiries);\n\tlet current: LifecycleRule[] = [];\n\ttry {\n\t\tconst out = await s3.send(\n\t\t\tnew S3.GetBucketLifecycleConfigurationCommand({ Bucket: bucket }),\n\t\t);\n\t\tcurrent = out.Rules ?? [];\n\t} catch (error) {\n\t\tconst failure = error as S3Failure;\n\t\tconst code = failure.Code ?? failure.name;\n\t\tif (code !== 'NoSuchLifecycleConfiguration') throw error;\n\t}\n\tif (sameLifecycle(current, rules)) return false;\n\tif (!options.dryRun) {\n\t\tawait s3.send(\n\t\t\tnew S3.PutBucketLifecycleConfigurationCommand({\n\t\t\t\tBucket: bucket,\n\t\t\t\tLifecycleConfiguration: { Rules: rules },\n\t\t\t}),\n\t\t);\n\t}\n\treturn true;\n}\n\ninterface S3Failure {\n\tname?: string;\n\tCode?: string;\n\tmessage?: string;\n\t$metadata?: { httpStatusCode?: number };\n}\n\n/**\n * Whether `bucket` is this account's (`ours`) or does not exist (`none`).\n * Mapped by status: a HEAD has no body, so SDK v3 names a 301, 400 or 403\n * `Unknown`.\n *\n * @throws {ProjectBucketTaken} on a 403 or 301\n */\nexport async function findProjectBucket(\n\ts3: S3Client,\n\tbucket: string,\n): Promise<'ours' | 'none'> {\n\tconst { HeadBucketCommand } = await import('@aws-sdk/client-s3');\n\ttry {\n\t\tawait s3.send(new HeadBucketCommand({ Bucket: bucket }));\n\t\treturn 'ours';\n\t} catch (error) {\n\t\tconst status = (error as S3Failure).$metadata?.httpStatusCode;\n\t\tif (status === 404) return 'none';\n\t\tif (status === 403 || status === 301) {\n\t\t\tthrow new ProjectBucketTaken(bucket, status);\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nexport interface EnsureProjectBucketOptions {\n\tbucket: string;\n\tregion: string;\n\t/** The deploy identity the bucket is tagged with. */\n\tidentity: Pick<DeployIdentity, 'key'>;\n\t/** Per-prefix expiries beside the bucket's own rule. */\n\texpiries?: readonly PrefixExpiry[];\n}\n\n/**\n * The project bucket, created and configured if it does not exist yet.\n * Returns whether this call created it. One that exists is used as it is.\n *\n * @throws {ProjectBucketTaken} when another account holds the name\n * @throws {ProjectBucketNotCreatable} when the credentials may not create it\n */\nexport async function ensureProjectBucket(\n\ts3: S3Client,\n\toptions: EnsureProjectBucketOptions,\n): Promise<{ created: boolean }> {\n\tconst { bucket: Bucket, region } = options;\n\tif ((await findProjectBucket(s3, Bucket)) === 'ours') {\n\t\treturn { created: false };\n\t}\n\n\tconst S3 = await import('@aws-sdk/client-s3');\n\ttry {\n\t\tawait s3.send(\n\t\t\tnew S3.CreateBucketCommand({\n\t\t\t\tBucket,\n\t\t\t\tObjectOwnership: 'BucketOwnerEnforced',\n\t\t\t\t// us-east-1 is the one region named by leaving it out.\n\t\t\t\t...(region === 'us-east-1'\n\t\t\t\t\t? {}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tCreateBucketConfiguration: {\n\t\t\t\t\t\t\t\tLocationConstraint: region as BucketLocationConstraint,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t}),\n\t\t);\n\t} catch (error) {\n\t\tconst failure = error as S3Failure;\n\t\tconst code = failure.Code ?? failure.name;\n\t\t// Another run created it a moment ago: configure it all the same.\n\t\tif (code !== 'BucketAlreadyOwnedByYou') {\n\t\t\tif (code === 'BucketAlreadyExists') {\n\t\t\t\tthrow new ProjectBucketTaken(Bucket, 409);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tcode === 'AccessDenied' ||\n\t\t\t\tfailure.$metadata?.httpStatusCode === 403\n\t\t\t) {\n\t\t\t\tthrow new ProjectBucketNotCreatable(\n\t\t\t\t\tBucket,\n\t\t\t\t\tfailure.message ?? 'AccessDenied',\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tawait s3.send(\n\t\tnew S3.PutPublicAccessBlockCommand({\n\t\t\tBucket,\n\t\t\tPublicAccessBlockConfiguration: {\n\t\t\t\tBlockPublicAcls: true,\n\t\t\t\tIgnorePublicAcls: true,\n\t\t\t\tBlockPublicPolicy: true,\n\t\t\t\tRestrictPublicBuckets: true,\n\t\t\t},\n\t\t}),\n\t);\n\tawait s3.send(\n\t\tnew S3.PutBucketOwnershipControlsCommand({\n\t\t\tBucket,\n\t\t\tOwnershipControls: {\n\t\t\t\tRules: [{ ObjectOwnership: 'BucketOwnerEnforced' }],\n\t\t\t},\n\t\t}),\n\t);\n\tawait s3.send(\n\t\tnew S3.PutBucketEncryptionCommand({\n\t\t\tBucket,\n\t\t\tServerSideEncryptionConfiguration: {\n\t\t\t\tRules: [\n\t\t\t\t\t{ ApplyServerSideEncryptionByDefault: { SSEAlgorithm: 'AES256' } },\n\t\t\t\t],\n\t\t\t},\n\t\t}),\n\t);\n\tawait s3.send(\n\t\tnew S3.PutBucketVersioningCommand({\n\t\t\tBucket,\n\t\t\tVersioningConfiguration: { Status: 'Enabled' },\n\t\t}),\n\t);\n\tawait s3.send(\n\t\tnew S3.PutBucketLifecycleConfigurationCommand({\n\t\t\tBucket,\n\t\t\tLifecycleConfiguration: {\n\t\t\t\tRules: projectBucketLifecycle(options.expiries),\n\t\t\t},\n\t\t}),\n\t);\n\tawait s3.send(\n\t\tnew S3.PutBucketTaggingCommand({\n\t\t\tBucket,\n\t\t\tTagging: {\n\t\t\t\tTagSet: [{ Key: PROJECT_BUCKET_TAG, Value: options.identity.key }],\n\t\t\t},\n\t\t}),\n\t);\n\treturn { created: true };\n}\n\n/**\n * The IAM actions creating and configuring the project bucket takes — what a\n * role that runs the first deploy needs on it, beside object access.\n */\nexport const PROJECT_BUCKET_CREATE_ACTIONS = [\n\t's3:CreateBucket',\n\t's3:PutBucketVersioning',\n\t's3:PutEncryptionConfiguration',\n\t's3:PutBucketPublicAccessBlock',\n\t's3:PutBucketOwnershipControls',\n\t's3:PutLifecycleConfiguration',\n\t's3:PutBucketTagging',\n] as const;\n\n/**\n * What keeping the project bucket's lifecycle takes on a bucket that exists:\n * reading it, to put it back only when it drifted.\n */\nexport const PROJECT_BUCKET_LIFECYCLE_ACTIONS = [\n\t's3:GetLifecycleConfiguration',\n\t's3:PutLifecycleConfiguration',\n] as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAM,YAAY;;AAGlB,MAAa,qBAAqB;;AAMlC,IAAa,qBAAb,cAAwC,SAAS;CAEtC;CAEA;CAHV,YACC,QAEA,QACC;EAKD,MACC,uBAAuB,OAAO,IAJ9B,WAAW,MACR,iDACA,2EAEmC,SAAS,OAAO,8LAIvD;EAbS,KAAA,SAAA;EAEA,KAAA,SAAA;EAYT,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,4BAAb,cAA+C,SAAS;CAE7C;CACA;CAFV,YACC,QACA,QACC;EACD,MACC,uBAAuB,OAAO,gEACI,OAAO,qOAI1C;EATS,KAAA,SAAA;EACA,KAAA,SAAA;EAST,KAAK,OAAO;CACb;AACD;;AAgBA,SAAgB,kBAAkB,OAAe,WAA2B;CAC3E,IAAI,OAAO,MACT,YAAY,CAAC,CACb,QAAQ,eAAe,GAAG,CAAC,CAC3B,QAAQ,YAAY,EAAE;CACxB,IAAI,KAAK,SAAS,WAAW;EAC5B,MAAM,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;EACxE,OAAO,GAAG,KAAK,MAAM,GAAG,EAAa,CAAC,CAAC,QAAQ,OAAO,EAAE,EAAE,GAAG;CAC9D;CACA,OAAO,OAAO,KAAK,GAAG;AACvB;;AAGA,eAAsB,gBAAgB,KAAiC;CACtE,MAAM,EAAE,6BAA6B,MAAM,OAAO;CAClD,MAAM,EAAE,YAAY,MAAM,IAAI,KAAK,IAAI,yBAAyB,CAAC,CAAC,CAAC;CACnE,OAAO,WAAW;AACnB;;;;;;AAsBA,SAAgB,uBACf,WAAoC,CAAC,GACnB;CAClB,OAAO,CACN;EACC,IAAI;EACJ,QAAQ;EACR,QAAQ,EAAE,QAAQ,GAAG;EACrB,6BAA6B,EAAE,gBAAA,GAAwC;EAEvE,YAAY,EAAE,2BAA2B,KAAK;CAC/C,GACA,GAAG,SAAS,KACV,YAA2B;EAC3B,IAAI,OAAO;EACX,QAAQ;EACR,QAAQ,EAAE,QAAQ,OAAO,OAAO;EAChC,YAAY,EAAE,MAAM,OAAO,KAAK;EAChC,GAAI,OAAO,sBACR,EACA,gCAAgC,EAC/B,qBAAqB,OAAO,oBAC7B,EACD,IACC,CAAC;CACL,EACD,CACD;AACD;;AAGA,SAAS,cAAc,MAA6B;CACnD,OAAO,KAAK,UAAU;EACrB,IAAI,KAAK,MAAM;EACf,QAAQ,KAAK,UAAU;EACvB,QAAQ,KAAK,QAAQ,UAAU,KAAK,UAAU;EAC9C,MAAM,KAAK,YAAY,QAAQ;EAC/B,SAAS,KAAK,YAAY,6BAA6B;EACvD,YAAY,KAAK,6BAA6B,kBAAkB;EAChE,OAAO,KAAK,gCAAgC,uBAAuB;CACpE,CAAC;AACF;;AAGA,SAAgB,cACf,GACA,GACU;CACV,MAAM,aAAa,UAClB,MAAM,IAAI,aAAa,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI;CAC1C,OAAO,UAAU,CAAC,MAAM,UAAU,CAAC;AACpC;;;;;;AAOA,eAAsB,gCACrB,IACA,QACA,UACA,UAAgC,CAAC,GACd;CACnB,MAAM,KAAK,MAAM,OAAO;CACxB,MAAM,QAAQ,uBAAuB,QAAQ;CAC7C,IAAI,UAA2B,CAAC;CAChC,IAAI;EAIH,WAAU,MAHQ,GAAG,KACpB,IAAI,GAAG,uCAAuC,EAAE,QAAQ,OAAO,CAAC,CACjE,EAAA,CACc,SAAS,CAAC;CACzB,SAAS,OAAO;EACf,MAAM,UAAU;EAEhB,KADa,QAAQ,QAAQ,QAAQ,UACxB,gCAAgC,MAAM;CACpD;CACA,IAAI,cAAc,SAAS,KAAK,GAAG,OAAO;CAC1C,IAAI,CAAC,QAAQ,QACZ,MAAM,GAAG,KACR,IAAI,GAAG,uCAAuC;EAC7C,QAAQ;EACR,wBAAwB,EAAE,OAAO,MAAM;CACxC,CAAC,CACF;CAED,OAAO;AACR;;;;;;;;AAgBA,eAAsB,kBACrB,IACA,QAC2B;CAC3B,MAAM,EAAE,sBAAsB,MAAM,OAAO;CAC3C,IAAI;EACH,MAAM,GAAG,KAAK,IAAI,kBAAkB,EAAE,QAAQ,OAAO,CAAC,CAAC;EACvD,OAAO;CACR,SAAS,OAAO;EACf,MAAM,SAAU,MAAoB,WAAW;EAC/C,IAAI,WAAW,KAAK,OAAO;EAC3B,IAAI,WAAW,OAAO,WAAW,KAChC,MAAM,IAAI,mBAAmB,QAAQ,MAAM;EAE5C,MAAM;CACP;AACD;;;;;;;;AAkBA,eAAsB,oBACrB,IACA,SACgC;CAChC,MAAM,EAAE,QAAQ,QAAQ,WAAW;CACnC,IAAK,MAAM,kBAAkB,IAAI,MAAM,MAAO,QAC7C,OAAO,EAAE,SAAS,MAAM;CAGzB,MAAM,KAAK,MAAM,OAAO;CACxB,IAAI;EACH,MAAM,GAAG,KACR,IAAI,GAAG,oBAAoB;GAC1B;GACA,iBAAiB;GAEjB,GAAI,WAAW,cACZ,CAAC,IACD,EACA,2BAA2B,EAC1B,oBAAoB,OACrB,EACD;EACH,CAAC,CACF;CACD,SAAS,OAAO;EACf,MAAM,UAAU;EAChB,MAAM,OAAO,QAAQ,QAAQ,QAAQ;EAErC,IAAI,SAAS,2BAA2B;GACvC,IAAI,SAAS,uBACZ,MAAM,IAAI,mBAAmB,QAAQ,GAAG;GAEzC,IACC,SAAS,kBACT,QAAQ,WAAW,mBAAmB,KAEtC,MAAM,IAAI,0BACT,QACA,QAAQ,WAAW,cACpB;GAED,MAAM;EACP;CACD;CAEA,MAAM,GAAG,KACR,IAAI,GAAG,4BAA4B;EAClC;EACA,gCAAgC;GAC/B,iBAAiB;GACjB,kBAAkB;GAClB,mBAAmB;GACnB,uBAAuB;EACxB;CACD,CAAC,CACF;CACA,MAAM,GAAG,KACR,IAAI,GAAG,kCAAkC;EACxC;EACA,mBAAmB,EAClB,OAAO,CAAC,EAAE,iBAAiB,sBAAsB,CAAC,EACnD;CACD,CAAC,CACF;CACA,MAAM,GAAG,KACR,IAAI,GAAG,2BAA2B;EACjC;EACA,mCAAmC,EAClC,OAAO,CACN,EAAE,oCAAoC,EAAE,cAAc,SAAS,EAAE,CAClE,EACD;CACD,CAAC,CACF;CACA,MAAM,GAAG,KACR,IAAI,GAAG,2BAA2B;EACjC;EACA,yBAAyB,EAAE,QAAQ,UAAU;CAC9C,CAAC,CACF;CACA,MAAM,GAAG,KACR,IAAI,GAAG,uCAAuC;EAC7C;EACA,wBAAwB,EACvB,OAAO,uBAAuB,QAAQ,QAAQ,EAC/C;CACD,CAAC,CACF;CACA,MAAM,GAAG,KACR,IAAI,GAAG,wBAAwB;EAC9B;EACA,SAAS,EACR,QAAQ,CAAC;GAAE,KAAK;GAAoB,OAAO,QAAQ,SAAS;EAAI,CAAC,EAClE;CACD,CAAC,CACF;CACA,OAAO,EAAE,SAAS,KAAK;AACxB;;;;;AAMA,MAAa,gCAAgC;CAC5C;CACA;CACA;CACA;CACA;CACA;CACA;AACD;;;;;AAMA,MAAa,mCAAmC,CAC/C,gCACA,8BACD"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const require_errors = require("./errors-DMC4Umsb.cjs");
|
|
2
|
+
const require_define = require("./define-crmMcXFS.cjs");
|
|
3
|
+
//#region src/target/provider.ts
|
|
4
|
+
/**
|
|
5
|
+
* `gkm deploy --provider`, from before there were targets.
|
|
6
|
+
*
|
|
7
|
+
* It named three things, and only one of them ever deployed a workspace:
|
|
8
|
+
* `dokploy` is now the target of that name; `docker` and `aws-lambda` were
|
|
9
|
+
* accepted and always failed, so they are gone with a pointer to what does
|
|
10
|
+
* the job.
|
|
11
|
+
*/
|
|
12
|
+
/** What each removed provider's job is done with now. */
|
|
13
|
+
const REMOVED = {
|
|
14
|
+
docker: "Build images with `gkm docker`, or run the stage as one Docker Compose stack with `gkm compose`",
|
|
15
|
+
"aws-lambda": "Deploy to AWS with SST: set deploy: { default: 'sst' } and run `gkm deploy --stage <stage>`, which runs `sst deploy`"
|
|
16
|
+
};
|
|
17
|
+
/** A `--provider` that no longer exists. */
|
|
18
|
+
var ProviderRemoved = class extends require_errors.GkmError {
|
|
19
|
+
provider;
|
|
20
|
+
instead;
|
|
21
|
+
constructor(provider, instead) {
|
|
22
|
+
super(`--provider ${provider} has been removed. ${instead}.`);
|
|
23
|
+
this.provider = provider;
|
|
24
|
+
this.instead = instead;
|
|
25
|
+
this.name = "ProviderRemoved";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/** The deprecation `--provider` prints when it still means something. */
|
|
29
|
+
function providerDeprecation(provider) {
|
|
30
|
+
return `--provider is deprecated; use --target ${provider}.`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The target a `--provider` value means. `warn` hears the deprecation; a
|
|
34
|
+
* provider that is gone, or a target not deployable yet, throws.
|
|
35
|
+
*/
|
|
36
|
+
function targetForProvider(provider, warn) {
|
|
37
|
+
const removed = REMOVED[provider];
|
|
38
|
+
if (removed) throw new ProviderRemoved(provider, removed);
|
|
39
|
+
if (provider === "vercel" || provider === "cloudflare") throw new require_define.DeployTargetNotYetSupported(provider);
|
|
40
|
+
warn(providerDeprecation(provider));
|
|
41
|
+
return provider;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
Object.defineProperty(exports, "ProviderRemoved", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
get: function() {
|
|
47
|
+
return ProviderRemoved;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
Object.defineProperty(exports, "targetForProvider", {
|
|
51
|
+
enumerable: true,
|
|
52
|
+
get: function() {
|
|
53
|
+
return targetForProvider;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=provider-BqpjG9QM.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-BqpjG9QM.cjs","names":["GkmError","DeployTargetNotYetSupported"],"sources":["../src/target/provider.ts"],"sourcesContent":["/**\n * `gkm deploy --provider`, from before there were targets.\n *\n * It named three things, and only one of them ever deployed a workspace:\n * `dokploy` is now the target of that name; `docker` and `aws-lambda` were\n * accepted and always failed, so they are gone with a pointer to what does\n * the job.\n */\n\nimport { GkmError } from '../errors';\nimport { DeployTargetNotYetSupported } from './builtins';\n\n/** What each removed provider's job is done with now. */\nconst REMOVED: Record<string, string> = {\n\tdocker:\n\t\t'Build images with `gkm docker`, or run the stage as one Docker Compose stack with `gkm compose`',\n\t'aws-lambda':\n\t\t\"Deploy to AWS with SST: set deploy: { default: 'sst' } and run `gkm deploy --stage <stage>`, which runs `sst deploy`\",\n};\n\n/** A `--provider` that no longer exists. */\nexport class ProviderRemoved extends GkmError {\n\tconstructor(\n\t\treadonly provider: string,\n\t\t/** What to use instead. */\n\t\treadonly instead: string,\n\t) {\n\t\tsuper(`--provider ${provider} has been removed. ${instead}.`);\n\t\tthis.name = 'ProviderRemoved';\n\t}\n}\n\n/** The deprecation `--provider` prints when it still means something. */\nexport function providerDeprecation(provider: string): string {\n\treturn `--provider is deprecated; use --target ${provider}.`;\n}\n\n/**\n * The target a `--provider` value means. `warn` hears the deprecation; a\n * provider that is gone, or a target not deployable yet, throws.\n */\nexport function targetForProvider(\n\tprovider: string,\n\twarn: (message: string) => void,\n): string {\n\tconst removed = REMOVED[provider];\n\tif (removed) throw new ProviderRemoved(provider, removed);\n\tif (provider === 'vercel' || provider === 'cloudflare') {\n\t\tthrow new DeployTargetNotYetSupported(provider);\n\t}\n\twarn(providerDeprecation(provider));\n\treturn provider;\n}\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,UAAkC;CACvC,QACC;CACD,cACC;AACF;;AAGA,IAAa,kBAAb,cAAqCA,eAAAA,SAAS;CAEnC;CAEA;CAHV,YACC,UAEA,SACC;EACD,MAAM,cAAc,SAAS,qBAAqB,QAAQ,EAAE;EAJnD,KAAA,WAAA;EAEA,KAAA,UAAA;EAGT,KAAK,OAAO;CACb;AACD;;AAGA,SAAgB,oBAAoB,UAA0B;CAC7D,OAAO,0CAA0C,SAAS;AAC3D;;;;;AAMA,SAAgB,kBACf,UACA,MACS;CACT,MAAM,UAAU,QAAQ;CACxB,IAAI,SAAS,MAAM,IAAI,gBAAgB,UAAU,OAAO;CACxD,IAAI,aAAa,YAAY,aAAa,cACzC,MAAM,IAAIC,eAAAA,4BAA4B,QAAQ;CAE/C,KAAK,oBAAoB,QAAQ,CAAC;CAClC,OAAO;AACR"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { t as GkmError } from "./errors-D8Gwp5kU.mjs";
|
|
2
|
+
import { i as DeployTargetNotYetSupported } from "./define-6poNqm5O.mjs";
|
|
3
|
+
//#region src/target/provider.ts
|
|
4
|
+
/**
|
|
5
|
+
* `gkm deploy --provider`, from before there were targets.
|
|
6
|
+
*
|
|
7
|
+
* It named three things, and only one of them ever deployed a workspace:
|
|
8
|
+
* `dokploy` is now the target of that name; `docker` and `aws-lambda` were
|
|
9
|
+
* accepted and always failed, so they are gone with a pointer to what does
|
|
10
|
+
* the job.
|
|
11
|
+
*/
|
|
12
|
+
/** What each removed provider's job is done with now. */
|
|
13
|
+
const REMOVED = {
|
|
14
|
+
docker: "Build images with `gkm docker`, or run the stage as one Docker Compose stack with `gkm compose`",
|
|
15
|
+
"aws-lambda": "Deploy to AWS with SST: set deploy: { default: 'sst' } and run `gkm deploy --stage <stage>`, which runs `sst deploy`"
|
|
16
|
+
};
|
|
17
|
+
/** A `--provider` that no longer exists. */
|
|
18
|
+
var ProviderRemoved = class extends GkmError {
|
|
19
|
+
provider;
|
|
20
|
+
instead;
|
|
21
|
+
constructor(provider, instead) {
|
|
22
|
+
super(`--provider ${provider} has been removed. ${instead}.`);
|
|
23
|
+
this.provider = provider;
|
|
24
|
+
this.instead = instead;
|
|
25
|
+
this.name = "ProviderRemoved";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/** The deprecation `--provider` prints when it still means something. */
|
|
29
|
+
function providerDeprecation(provider) {
|
|
30
|
+
return `--provider is deprecated; use --target ${provider}.`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The target a `--provider` value means. `warn` hears the deprecation; a
|
|
34
|
+
* provider that is gone, or a target not deployable yet, throws.
|
|
35
|
+
*/
|
|
36
|
+
function targetForProvider(provider, warn) {
|
|
37
|
+
const removed = REMOVED[provider];
|
|
38
|
+
if (removed) throw new ProviderRemoved(provider, removed);
|
|
39
|
+
if (provider === "vercel" || provider === "cloudflare") throw new DeployTargetNotYetSupported(provider);
|
|
40
|
+
warn(providerDeprecation(provider));
|
|
41
|
+
return provider;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { targetForProvider as n, ProviderRemoved as t };
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=provider-CEOKk8NS.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-CEOKk8NS.mjs","names":[],"sources":["../src/target/provider.ts"],"sourcesContent":["/**\n * `gkm deploy --provider`, from before there were targets.\n *\n * It named three things, and only one of them ever deployed a workspace:\n * `dokploy` is now the target of that name; `docker` and `aws-lambda` were\n * accepted and always failed, so they are gone with a pointer to what does\n * the job.\n */\n\nimport { GkmError } from '../errors';\nimport { DeployTargetNotYetSupported } from './builtins';\n\n/** What each removed provider's job is done with now. */\nconst REMOVED: Record<string, string> = {\n\tdocker:\n\t\t'Build images with `gkm docker`, or run the stage as one Docker Compose stack with `gkm compose`',\n\t'aws-lambda':\n\t\t\"Deploy to AWS with SST: set deploy: { default: 'sst' } and run `gkm deploy --stage <stage>`, which runs `sst deploy`\",\n};\n\n/** A `--provider` that no longer exists. */\nexport class ProviderRemoved extends GkmError {\n\tconstructor(\n\t\treadonly provider: string,\n\t\t/** What to use instead. */\n\t\treadonly instead: string,\n\t) {\n\t\tsuper(`--provider ${provider} has been removed. ${instead}.`);\n\t\tthis.name = 'ProviderRemoved';\n\t}\n}\n\n/** The deprecation `--provider` prints when it still means something. */\nexport function providerDeprecation(provider: string): string {\n\treturn `--provider is deprecated; use --target ${provider}.`;\n}\n\n/**\n * The target a `--provider` value means. `warn` hears the deprecation; a\n * provider that is gone, or a target not deployable yet, throws.\n */\nexport function targetForProvider(\n\tprovider: string,\n\twarn: (message: string) => void,\n): string {\n\tconst removed = REMOVED[provider];\n\tif (removed) throw new ProviderRemoved(provider, removed);\n\tif (provider === 'vercel' || provider === 'cloudflare') {\n\t\tthrow new DeployTargetNotYetSupported(provider);\n\t}\n\twarn(providerDeprecation(provider));\n\treturn provider;\n}\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,UAAkC;CACvC,QACC;CACD,cACC;AACF;;AAGA,IAAa,kBAAb,cAAqC,SAAS;CAEnC;CAEA;CAHV,YACC,UAEA,SACC;EACD,MAAM,cAAc,SAAS,qBAAqB,QAAQ,EAAE;EAJnD,KAAA,WAAA;EAEA,KAAA,UAAA;EAGT,KAAK,OAAO;CACb;AACD;;AAGA,SAAgB,oBAAoB,UAA0B;CAC7D,OAAO,0CAA0C,SAAS;AAC3D;;;;;AAMA,SAAgB,kBACf,UACA,MACS;CACT,MAAM,UAAU,QAAQ;CACxB,IAAI,SAAS,MAAM,IAAI,gBAAgB,UAAU,OAAO;CACxD,IAAI,aAAa,YAAY,aAAa,cACzC,MAAM,IAAI,4BAA4B,QAAQ;CAE/C,KAAK,oBAAoB,QAAQ,CAAC;CAClC,OAAO;AACR"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { t as GkmError } from "./errors-D8Gwp5kU.mjs";
|
|
2
|
+
import { easCli, easSync } from "./eas-iT2JDHCh.mjs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
//#region src/mobile/publish.ts
|
|
7
|
+
/**
|
|
8
|
+
* `gkm publish --stage <stage>`: a mobile app shipped for a deployed stage.
|
|
9
|
+
*
|
|
10
|
+
* First the stage's EAS project is synced (`gkm eas:sync`), so what is built
|
|
11
|
+
* reads the stage's values. Then, per platform, the cheapest release that
|
|
12
|
+
* gets the app's current code to the stage's users:
|
|
13
|
+
*
|
|
14
|
+
* - **An update**, when a store build with the same native code is already
|
|
15
|
+
* out: the fingerprint `runtimeVersion: { policy: 'fingerprint' }` gives a
|
|
16
|
+
* build is computed with the stage's profile, and a finished store build
|
|
17
|
+
* of that profile with that fingerprint means only JavaScript changed. It
|
|
18
|
+
* goes out on the stage's channel (`eas update`), which only builds of
|
|
19
|
+
* that runtime receive.
|
|
20
|
+
* - **A store build**, otherwise, submitted to the store as the stage's
|
|
21
|
+
* submit profile says (`eas build --auto-submit`): Android to its Play
|
|
22
|
+
* track; iOS to App Store Connect once `submit.<stage>.ios.ascAppId` is
|
|
23
|
+
* set — without it, iOS is built and not submitted, and gkm says so,
|
|
24
|
+
* rather than leave a prompt nobody in CI can answer.
|
|
25
|
+
*
|
|
26
|
+
* `--build` or `--update` decides instead. An update with no store build to
|
|
27
|
+
* receive it reaches nobody, so `--update` without one is refused.
|
|
28
|
+
*/
|
|
29
|
+
const logger = console;
|
|
30
|
+
/** `--update`, and no store build has this native code. */
|
|
31
|
+
var NoStoreBuildForUpdate = class extends GkmError {
|
|
32
|
+
platform;
|
|
33
|
+
stage;
|
|
34
|
+
fingerprint;
|
|
35
|
+
constructor(platform, stage, fingerprint) {
|
|
36
|
+
super(`No ${platform} store build of '${stage}' has this native code (fingerprint ${fingerprint}), so an update would reach nobody: a phone only takes updates for the runtime it was built with. Build one: gkm publish --stage ${stage} --platform ${platform} --build.`);
|
|
37
|
+
this.platform = platform;
|
|
38
|
+
this.stage = stage;
|
|
39
|
+
this.fingerprint = fingerprint;
|
|
40
|
+
this.name = "NoStoreBuildForUpdate";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
/** `--build` and `--update` together. */
|
|
44
|
+
var PublishModeConflict = class extends GkmError {
|
|
45
|
+
constructor() {
|
|
46
|
+
super("Pass --build or --update, not both: one release per platform.");
|
|
47
|
+
this.name = "PublishModeConflict";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Ship a mobile app for a deployed stage.
|
|
52
|
+
*
|
|
53
|
+
* @throws {NoStoreBuildForUpdate} — and what `easSync` throws
|
|
54
|
+
*/
|
|
55
|
+
async function publish(options, eas) {
|
|
56
|
+
const synced = await easSync(options, eas);
|
|
57
|
+
const cli = eas ?? easCli(synced.root, synced.values);
|
|
58
|
+
const { dir, stage } = synced;
|
|
59
|
+
const profile = stage.stage;
|
|
60
|
+
const easJson = existsSync(join(dir, "eas.json")) ? JSON.parse(readFileSync(join(dir, "eas.json"), "utf8")) : {};
|
|
61
|
+
const iosSubmits = Boolean(easJson.submit?.[profile]?.ios?.ascAppId);
|
|
62
|
+
const platforms = !options.platform || options.platform === "all" ? ["ios", "android"] : [options.platform];
|
|
63
|
+
const releases = [];
|
|
64
|
+
for (const platform of platforms) {
|
|
65
|
+
const fingerprint = await cli.fingerprint(dir, {
|
|
66
|
+
platform,
|
|
67
|
+
profile
|
|
68
|
+
});
|
|
69
|
+
const storeBuild = options.mode === "build" ? void 0 : await cli.storeBuild(dir, {
|
|
70
|
+
platform,
|
|
71
|
+
profile,
|
|
72
|
+
fingerprint
|
|
73
|
+
});
|
|
74
|
+
if (options.mode === "update" && !storeBuild) throw new NoStoreBuildForUpdate(platform, profile, fingerprint);
|
|
75
|
+
const release = options.mode ?? (storeBuild ? "update" : "build");
|
|
76
|
+
const submit = platform === "android" || iosSubmits;
|
|
77
|
+
releases.push({
|
|
78
|
+
platform,
|
|
79
|
+
fingerprint,
|
|
80
|
+
...storeBuild ? { storeBuild } : {},
|
|
81
|
+
release,
|
|
82
|
+
submit: release === "build" && submit
|
|
83
|
+
});
|
|
84
|
+
const why = storeBuild ? `store build ${storeBuild} has this native code` : "no store build has this native code";
|
|
85
|
+
if (release === "update") {
|
|
86
|
+
logger.log(`🔁 ${platform}: an update on '${stage.channel}' (${why})${options.dryRun ? " (dry run)" : ""}`);
|
|
87
|
+
if (options.dryRun) continue;
|
|
88
|
+
await cli.update(dir, {
|
|
89
|
+
platform,
|
|
90
|
+
channel: stage.channel,
|
|
91
|
+
environment: stage.environment,
|
|
92
|
+
message: options.message ?? commitSubject(synced.root, profile)
|
|
93
|
+
});
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const where = platform === "android" ? `submitted to Play's ${stage.android.track} track (${stage.android.releaseStatus})` : iosSubmits ? "submitted to App Store Connect" : `not submitted: submit.${profile}.ios.ascAppId is not set in eas.json`;
|
|
97
|
+
logger.log(`📦 ${platform}: a store build of '${profile}', ${where} (${why})${options.dryRun ? " (dry run)" : ""}`);
|
|
98
|
+
if (options.dryRun) continue;
|
|
99
|
+
await cli.build(dir, {
|
|
100
|
+
platform,
|
|
101
|
+
profile,
|
|
102
|
+
submit,
|
|
103
|
+
wait: options.wait ?? false
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return releases;
|
|
107
|
+
}
|
|
108
|
+
/** The current commit's subject, for an update's message. */
|
|
109
|
+
function commitSubject(root, stage) {
|
|
110
|
+
const result = spawnSync("git", [
|
|
111
|
+
"log",
|
|
112
|
+
"-1",
|
|
113
|
+
"--format=%s"
|
|
114
|
+
], {
|
|
115
|
+
cwd: root,
|
|
116
|
+
encoding: "utf8"
|
|
117
|
+
});
|
|
118
|
+
return (result.status === 0 ? result.stdout.trim() : "") || `gkm publish --stage ${stage}`;
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
export { PublishModeConflict, publish };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=publish-CcTlmJT6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish-CcTlmJT6.mjs","names":[],"sources":["../src/mobile/publish.ts"],"sourcesContent":["/**\n * `gkm publish --stage <stage>`: a mobile app shipped for a deployed stage.\n *\n * First the stage's EAS project is synced (`gkm eas:sync`), so what is built\n * reads the stage's values. Then, per platform, the cheapest release that\n * gets the app's current code to the stage's users:\n *\n * - **An update**, when a store build with the same native code is already\n * out: the fingerprint `runtimeVersion: { policy: 'fingerprint' }` gives a\n * build is computed with the stage's profile, and a finished store build\n * of that profile with that fingerprint means only JavaScript changed. It\n * goes out on the stage's channel (`eas update`), which only builds of\n * that runtime receive.\n * - **A store build**, otherwise, submitted to the store as the stage's\n * submit profile says (`eas build --auto-submit`): Android to its Play\n * track; iOS to App Store Connect once `submit.<stage>.ios.ascAppId` is\n * set — without it, iOS is built and not submitted, and gkm says so,\n * rather than leave a prompt nobody in CI can answer.\n *\n * `--build` or `--update` decides instead. An update with no store build to\n * receive it reaches nobody, so `--update` without one is refused.\n */\n\nimport { spawnSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { GkmError } from '../errors';\nimport {\n\ttype EasCli,\n\ttype EasPlatform,\n\ttype EasSyncOptions,\n\teasCli,\n\teasSync,\n} from './eas.js';\n\nconst logger = console;\n\n/** `--update`, and no store build has this native code. */\nexport class NoStoreBuildForUpdate extends GkmError {\n\tconstructor(\n\t\treadonly platform: EasPlatform,\n\t\treadonly stage: string,\n\t\treadonly fingerprint: string,\n\t) {\n\t\tsuper(\n\t\t\t`No ${platform} store build of '${stage}' has this native code ` +\n\t\t\t\t`(fingerprint ${fingerprint}), so an update would reach nobody: a phone ` +\n\t\t\t\t'only takes updates for the runtime it was built with. Build one: ' +\n\t\t\t\t`gkm publish --stage ${stage} --platform ${platform} --build.`,\n\t\t);\n\t\tthis.name = 'NoStoreBuildForUpdate';\n\t}\n}\n\n/** `--build` and `--update` together. */\nexport class PublishModeConflict extends GkmError {\n\tconstructor() {\n\t\tsuper('Pass --build or --update, not both: one release per platform.');\n\t\tthis.name = 'PublishModeConflict';\n\t}\n}\n\nexport interface PublishOptions extends EasSyncOptions {\n\t/** `ios`, `android`, or both (the default). */\n\tplatform?: EasPlatform | 'all';\n\t/** Build, or update, whatever the fingerprint says. */\n\tmode?: 'build' | 'update';\n\t/** Wait for a build to finish (and submit), rather than leave it on EAS. */\n\twait?: boolean;\n\t/** The update's message: the commit's subject by default. */\n\tmessage?: string;\n}\n\n/** What one platform's release was — or, dry, would be. */\nexport interface PlatformRelease {\n\tplatform: EasPlatform;\n\tfingerprint: string;\n\t/** The store build that already has this native code, if one does. */\n\tstoreBuild?: string;\n\trelease: 'build' | 'update';\n\t/** Whether a build is submitted to its store. */\n\tsubmit: boolean;\n}\n\n/**\n * Ship a mobile app for a deployed stage.\n *\n * @throws {NoStoreBuildForUpdate} — and what `easSync` throws\n */\nexport async function publish(\n\toptions: PublishOptions,\n\teas?: EasCli,\n): Promise<PlatformRelease[]> {\n\tconst synced = await easSync(options, eas);\n\tconst cli = eas ?? easCli(synced.root, synced.values);\n\tconst { dir, stage } = synced;\n\tconst profile = stage.stage;\n\n\tconst easJson = existsSync(join(dir, 'eas.json'))\n\t\t? (JSON.parse(readFileSync(join(dir, 'eas.json'), 'utf8')) as {\n\t\t\t\tsubmit?: Record<string, { ios?: { ascAppId?: string } }>;\n\t\t\t})\n\t\t: {};\n\tconst iosSubmits = Boolean(easJson.submit?.[profile]?.ios?.ascAppId);\n\n\tconst platforms: EasPlatform[] =\n\t\t!options.platform || options.platform === 'all'\n\t\t\t? ['ios', 'android']\n\t\t\t: [options.platform];\n\n\tconst releases: PlatformRelease[] = [];\n\tfor (const platform of platforms) {\n\t\tconst fingerprint = await cli.fingerprint(dir, { platform, profile });\n\t\tconst storeBuild =\n\t\t\toptions.mode === 'build'\n\t\t\t\t? undefined\n\t\t\t\t: await cli.storeBuild(dir, { platform, profile, fingerprint });\n\t\tif (options.mode === 'update' && !storeBuild) {\n\t\t\tthrow new NoStoreBuildForUpdate(platform, profile, fingerprint);\n\t\t}\n\t\tconst release = options.mode ?? (storeBuild ? 'update' : 'build');\n\t\tconst submit = platform === 'android' || iosSubmits;\n\t\treleases.push({\n\t\t\tplatform,\n\t\t\tfingerprint,\n\t\t\t...(storeBuild ? { storeBuild } : {}),\n\t\t\trelease,\n\t\t\tsubmit: release === 'build' && submit,\n\t\t});\n\n\t\tconst why = storeBuild\n\t\t\t? `store build ${storeBuild} has this native code`\n\t\t\t: 'no store build has this native code';\n\t\tif (release === 'update') {\n\t\t\tlogger.log(\n\t\t\t\t`🔁 ${platform}: an update on '${stage.channel}' (${why})${options.dryRun ? ' (dry run)' : ''}`,\n\t\t\t);\n\t\t\tif (options.dryRun) continue;\n\t\t\tawait cli.update(dir, {\n\t\t\t\tplatform,\n\t\t\t\tchannel: stage.channel,\n\t\t\t\tenvironment: stage.environment,\n\t\t\t\tmessage: options.message ?? commitSubject(synced.root, profile),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst where =\n\t\t\tplatform === 'android'\n\t\t\t\t? `submitted to Play's ${stage.android.track} track (${stage.android.releaseStatus})`\n\t\t\t\t: iosSubmits\n\t\t\t\t\t? 'submitted to App Store Connect'\n\t\t\t\t\t: `not submitted: submit.${profile}.ios.ascAppId is not set in eas.json`;\n\t\tlogger.log(\n\t\t\t`📦 ${platform}: a store build of '${profile}', ${where} (${why})${options.dryRun ? ' (dry run)' : ''}`,\n\t\t);\n\t\tif (options.dryRun) continue;\n\t\tawait cli.build(dir, {\n\t\t\tplatform,\n\t\t\tprofile,\n\t\t\tsubmit,\n\t\t\twait: options.wait ?? false,\n\t\t});\n\t}\n\treturn releases;\n}\n\n/** The current commit's subject, for an update's message. */\nfunction commitSubject(root: string, stage: string): string {\n\tconst result = spawnSync('git', ['log', '-1', '--format=%s'], {\n\t\tcwd: root,\n\t\tencoding: 'utf8',\n\t});\n\tconst subject = result.status === 0 ? result.stdout.trim() : '';\n\treturn subject || `gkm publish --stage ${stage}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAM,SAAS;;AAGf,IAAa,wBAAb,cAA2C,SAAS;CAEzC;CACA;CACA;CAHV,YACC,UACA,OACA,aACC;EACD,MACC,MAAM,SAAS,mBAAmB,MAAM,sCACvB,YAAY,mIAEL,MAAM,cAAc,SAAS,UACtD;EATS,KAAA,WAAA;EACA,KAAA,QAAA;EACA,KAAA,cAAA;EAQT,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,sBAAb,cAAyC,SAAS;CACjD,cAAc;EACb,MAAM,+DAA+D;EACrE,KAAK,OAAO;CACb;AACD;;;;;;AA6BA,eAAsB,QACrB,SACA,KAC6B;CAC7B,MAAM,SAAS,MAAM,QAAQ,SAAS,GAAG;CACzC,MAAM,MAAM,OAAO,OAAO,OAAO,MAAM,OAAO,MAAM;CACpD,MAAM,EAAE,KAAK,UAAU;CACvB,MAAM,UAAU,MAAM;CAEtB,MAAM,UAAU,WAAW,KAAK,KAAK,UAAU,CAAC,IAC5C,KAAK,MAAM,aAAa,KAAK,KAAK,UAAU,GAAG,MAAM,CAAC,IAGvD,CAAC;CACJ,MAAM,aAAa,QAAQ,QAAQ,SAAS,QAAQ,EAAE,KAAK,QAAQ;CAEnE,MAAM,YACL,CAAC,QAAQ,YAAY,QAAQ,aAAa,QACvC,CAAC,OAAO,SAAS,IACjB,CAAC,QAAQ,QAAQ;CAErB,MAAM,WAA8B,CAAC;CACrC,KAAK,MAAM,YAAY,WAAW;EACjC,MAAM,cAAc,MAAM,IAAI,YAAY,KAAK;GAAE;GAAU;EAAQ,CAAC;EACpE,MAAM,aACL,QAAQ,SAAS,UACd,KAAA,IACA,MAAM,IAAI,WAAW,KAAK;GAAE;GAAU;GAAS;EAAY,CAAC;EAChE,IAAI,QAAQ,SAAS,YAAY,CAAC,YACjC,MAAM,IAAI,sBAAsB,UAAU,SAAS,WAAW;EAE/D,MAAM,UAAU,QAAQ,SAAS,aAAa,WAAW;EACzD,MAAM,SAAS,aAAa,aAAa;EACzC,SAAS,KAAK;GACb;GACA;GACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;GACnC;GACA,QAAQ,YAAY,WAAW;EAChC,CAAC;EAED,MAAM,MAAM,aACT,eAAe,WAAW,yBAC1B;EACH,IAAI,YAAY,UAAU;GACzB,OAAO,IACN,MAAM,SAAS,kBAAkB,MAAM,QAAQ,KAAK,IAAI,GAAG,QAAQ,SAAS,eAAe,IAC5F;GACA,IAAI,QAAQ,QAAQ;GACpB,MAAM,IAAI,OAAO,KAAK;IACrB;IACA,SAAS,MAAM;IACf,aAAa,MAAM;IACnB,SAAS,QAAQ,WAAW,cAAc,OAAO,MAAM,OAAO;GAC/D,CAAC;GACD;EACD;EAEA,MAAM,QACL,aAAa,YACV,uBAAuB,MAAM,QAAQ,MAAM,UAAU,MAAM,QAAQ,cAAc,KACjF,aACC,mCACA,yBAAyB,QAAQ;EACtC,OAAO,IACN,MAAM,SAAS,sBAAsB,QAAQ,KAAK,MAAM,IAAI,IAAI,GAAG,QAAQ,SAAS,eAAe,IACpG;EACA,IAAI,QAAQ,QAAQ;EACpB,MAAM,IAAI,MAAM,KAAK;GACpB;GACA;GACA;GACA,MAAM,QAAQ,QAAQ;EACvB,CAAC;CACF;CACA,OAAO;AACR;;AAGA,SAAS,cAAc,MAAc,OAAuB;CAC3D,MAAM,SAAS,UAAU,OAAO;EAAC;EAAO;EAAM;CAAa,GAAG;EAC7D,KAAK;EACL,UAAU;CACX,CAAC;CAED,QADgB,OAAO,WAAW,IAAI,OAAO,OAAO,KAAK,IAAI,OAC3C,uBAAuB;AAC1C"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const require_errors = require("./errors-DMC4Umsb.cjs");
|
|
2
|
+
const require_eas = require("./eas-CNi16SoO.cjs");
|
|
3
|
+
let node_path = require("node:path");
|
|
4
|
+
let node_fs = require("node:fs");
|
|
5
|
+
let node_child_process = require("node:child_process");
|
|
6
|
+
//#region src/mobile/publish.ts
|
|
7
|
+
/**
|
|
8
|
+
* `gkm publish --stage <stage>`: a mobile app shipped for a deployed stage.
|
|
9
|
+
*
|
|
10
|
+
* First the stage's EAS project is synced (`gkm eas:sync`), so what is built
|
|
11
|
+
* reads the stage's values. Then, per platform, the cheapest release that
|
|
12
|
+
* gets the app's current code to the stage's users:
|
|
13
|
+
*
|
|
14
|
+
* - **An update**, when a store build with the same native code is already
|
|
15
|
+
* out: the fingerprint `runtimeVersion: { policy: 'fingerprint' }` gives a
|
|
16
|
+
* build is computed with the stage's profile, and a finished store build
|
|
17
|
+
* of that profile with that fingerprint means only JavaScript changed. It
|
|
18
|
+
* goes out on the stage's channel (`eas update`), which only builds of
|
|
19
|
+
* that runtime receive.
|
|
20
|
+
* - **A store build**, otherwise, submitted to the store as the stage's
|
|
21
|
+
* submit profile says (`eas build --auto-submit`): Android to its Play
|
|
22
|
+
* track; iOS to App Store Connect once `submit.<stage>.ios.ascAppId` is
|
|
23
|
+
* set — without it, iOS is built and not submitted, and gkm says so,
|
|
24
|
+
* rather than leave a prompt nobody in CI can answer.
|
|
25
|
+
*
|
|
26
|
+
* `--build` or `--update` decides instead. An update with no store build to
|
|
27
|
+
* receive it reaches nobody, so `--update` without one is refused.
|
|
28
|
+
*/
|
|
29
|
+
const logger = console;
|
|
30
|
+
/** `--update`, and no store build has this native code. */
|
|
31
|
+
var NoStoreBuildForUpdate = class extends require_errors.GkmError {
|
|
32
|
+
platform;
|
|
33
|
+
stage;
|
|
34
|
+
fingerprint;
|
|
35
|
+
constructor(platform, stage, fingerprint) {
|
|
36
|
+
super(`No ${platform} store build of '${stage}' has this native code (fingerprint ${fingerprint}), so an update would reach nobody: a phone only takes updates for the runtime it was built with. Build one: gkm publish --stage ${stage} --platform ${platform} --build.`);
|
|
37
|
+
this.platform = platform;
|
|
38
|
+
this.stage = stage;
|
|
39
|
+
this.fingerprint = fingerprint;
|
|
40
|
+
this.name = "NoStoreBuildForUpdate";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
/** `--build` and `--update` together. */
|
|
44
|
+
var PublishModeConflict = class extends require_errors.GkmError {
|
|
45
|
+
constructor() {
|
|
46
|
+
super("Pass --build or --update, not both: one release per platform.");
|
|
47
|
+
this.name = "PublishModeConflict";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Ship a mobile app for a deployed stage.
|
|
52
|
+
*
|
|
53
|
+
* @throws {NoStoreBuildForUpdate} — and what `easSync` throws
|
|
54
|
+
*/
|
|
55
|
+
async function publish(options, eas) {
|
|
56
|
+
const synced = await require_eas.easSync(options, eas);
|
|
57
|
+
const cli = eas ?? require_eas.easCli(synced.root, synced.values);
|
|
58
|
+
const { dir, stage } = synced;
|
|
59
|
+
const profile = stage.stage;
|
|
60
|
+
const easJson = (0, node_fs.existsSync)((0, node_path.join)(dir, "eas.json")) ? JSON.parse((0, node_fs.readFileSync)((0, node_path.join)(dir, "eas.json"), "utf8")) : {};
|
|
61
|
+
const iosSubmits = Boolean(easJson.submit?.[profile]?.ios?.ascAppId);
|
|
62
|
+
const platforms = !options.platform || options.platform === "all" ? ["ios", "android"] : [options.platform];
|
|
63
|
+
const releases = [];
|
|
64
|
+
for (const platform of platforms) {
|
|
65
|
+
const fingerprint = await cli.fingerprint(dir, {
|
|
66
|
+
platform,
|
|
67
|
+
profile
|
|
68
|
+
});
|
|
69
|
+
const storeBuild = options.mode === "build" ? void 0 : await cli.storeBuild(dir, {
|
|
70
|
+
platform,
|
|
71
|
+
profile,
|
|
72
|
+
fingerprint
|
|
73
|
+
});
|
|
74
|
+
if (options.mode === "update" && !storeBuild) throw new NoStoreBuildForUpdate(platform, profile, fingerprint);
|
|
75
|
+
const release = options.mode ?? (storeBuild ? "update" : "build");
|
|
76
|
+
const submit = platform === "android" || iosSubmits;
|
|
77
|
+
releases.push({
|
|
78
|
+
platform,
|
|
79
|
+
fingerprint,
|
|
80
|
+
...storeBuild ? { storeBuild } : {},
|
|
81
|
+
release,
|
|
82
|
+
submit: release === "build" && submit
|
|
83
|
+
});
|
|
84
|
+
const why = storeBuild ? `store build ${storeBuild} has this native code` : "no store build has this native code";
|
|
85
|
+
if (release === "update") {
|
|
86
|
+
logger.log(`🔁 ${platform}: an update on '${stage.channel}' (${why})${options.dryRun ? " (dry run)" : ""}`);
|
|
87
|
+
if (options.dryRun) continue;
|
|
88
|
+
await cli.update(dir, {
|
|
89
|
+
platform,
|
|
90
|
+
channel: stage.channel,
|
|
91
|
+
environment: stage.environment,
|
|
92
|
+
message: options.message ?? commitSubject(synced.root, profile)
|
|
93
|
+
});
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const where = platform === "android" ? `submitted to Play's ${stage.android.track} track (${stage.android.releaseStatus})` : iosSubmits ? "submitted to App Store Connect" : `not submitted: submit.${profile}.ios.ascAppId is not set in eas.json`;
|
|
97
|
+
logger.log(`📦 ${platform}: a store build of '${profile}', ${where} (${why})${options.dryRun ? " (dry run)" : ""}`);
|
|
98
|
+
if (options.dryRun) continue;
|
|
99
|
+
await cli.build(dir, {
|
|
100
|
+
platform,
|
|
101
|
+
profile,
|
|
102
|
+
submit,
|
|
103
|
+
wait: options.wait ?? false
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return releases;
|
|
107
|
+
}
|
|
108
|
+
/** The current commit's subject, for an update's message. */
|
|
109
|
+
function commitSubject(root, stage) {
|
|
110
|
+
const result = (0, node_child_process.spawnSync)("git", [
|
|
111
|
+
"log",
|
|
112
|
+
"-1",
|
|
113
|
+
"--format=%s"
|
|
114
|
+
], {
|
|
115
|
+
cwd: root,
|
|
116
|
+
encoding: "utf8"
|
|
117
|
+
});
|
|
118
|
+
return (result.status === 0 ? result.stdout.trim() : "") || `gkm publish --stage ${stage}`;
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
exports.PublishModeConflict = PublishModeConflict;
|
|
122
|
+
exports.publish = publish;
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=publish-ydscCYsW.cjs.map
|