@geekmidas/cli 10.0.0-alpha.94 → 10.0.0-alpha.96

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.
Files changed (206) hide show
  1. package/dist/{GoDaddyProvider-BRZUWD8z.mjs → GoDaddyProvider-BsUKjGcg.mjs} +3 -3
  2. package/dist/{GoDaddyProvider-BRZUWD8z.mjs.map → GoDaddyProvider-BsUKjGcg.mjs.map} +1 -1
  3. package/dist/{GoDaddyProvider-DzguxU_a.cjs → GoDaddyProvider-DyHXHDHe.cjs} +3 -3
  4. package/dist/{GoDaddyProvider-DzguxU_a.cjs.map → GoDaddyProvider-DyHXHDHe.cjs.map} +1 -1
  5. package/dist/{HostingerProvider-Cjh_2Ml6.mjs → HostingerProvider-BNpS9aRJ.mjs} +2 -2
  6. package/dist/{HostingerProvider-Cjh_2Ml6.mjs.map → HostingerProvider-BNpS9aRJ.mjs.map} +1 -1
  7. package/dist/{HostingerProvider-OdQmKXE3.cjs → HostingerProvider-DR1iws1P.cjs} +2 -2
  8. package/dist/{HostingerProvider-OdQmKXE3.cjs.map → HostingerProvider-DR1iws1P.cjs.map} +1 -1
  9. package/dist/{LegacyStateStore-BQZb6-j2.mjs → LegacyStateStore-B6SOqRFi.mjs} +3 -3
  10. package/dist/{LegacyStateStore-BQZb6-j2.mjs.map → LegacyStateStore-B6SOqRFi.mjs.map} +1 -1
  11. package/dist/{LegacyStateStore-D50dgUPc.cjs → LegacyStateStore-BnMcONE0.cjs} +3 -3
  12. package/dist/{LegacyStateStore-D50dgUPc.cjs.map → LegacyStateStore-BnMcONE0.cjs.map} +1 -1
  13. package/dist/{LocalStateStore-BSaS2535.mjs → LocalStateStore-6CrsZzqI.mjs} +2 -2
  14. package/dist/{LocalStateStore-BSaS2535.mjs.map → LocalStateStore-6CrsZzqI.mjs.map} +1 -1
  15. package/dist/{LocalStateStore-EFBUjuMX.cjs → LocalStateStore-pd4bbdJJ.cjs} +2 -2
  16. package/dist/{LocalStateStore-EFBUjuMX.cjs.map → LocalStateStore-pd4bbdJJ.cjs.map} +1 -1
  17. package/dist/{S3StateStore-C5mv8To3.cjs → S3StateStore-CoGk6ZKU.cjs} +2 -2
  18. package/dist/{S3StateStore-C5mv8To3.cjs.map → S3StateStore-CoGk6ZKU.cjs.map} +1 -1
  19. package/dist/{S3StateStore-CrFq4UZU.mjs → S3StateStore-DP_7Q4yb.mjs} +2 -2
  20. package/dist/{S3StateStore-CrFq4UZU.mjs.map → S3StateStore-DP_7Q4yb.mjs.map} +1 -1
  21. package/dist/{SSMStateStore-D3Z6mZnA.mjs → SSMStateStore-Bo6_KDYY.mjs} +2 -2
  22. package/dist/{SSMStateStore-D3Z6mZnA.mjs.map → SSMStateStore-Bo6_KDYY.mjs.map} +1 -1
  23. package/dist/{SSMStateStore-DuZCH7_v.cjs → SSMStateStore-D9s4_Do3.cjs} +2 -2
  24. package/dist/{SSMStateStore-DuZCH7_v.cjs.map → SSMStateStore-D9s4_Do3.cjs.map} +1 -1
  25. package/dist/{add-C85isXFl.mjs → add-BQS2QZHp.mjs} +22 -51
  26. package/dist/add-BQS2QZHp.mjs.map +1 -0
  27. package/dist/{add-DsVDdvon.cjs → add-CjURJ-vI.cjs} +23 -52
  28. package/dist/add-CjURJ-vI.cjs.map +1 -0
  29. package/dist/{bundler-BSHog8CH.mjs → bundler-BMM3UsGm.mjs} +5 -5
  30. package/dist/{bundler-BSHog8CH.mjs.map → bundler-BMM3UsGm.mjs.map} +1 -1
  31. package/dist/{bundler-BEgUKc4j.cjs → bundler-DmLJQ7AY.cjs} +5 -5
  32. package/dist/{bundler-BEgUKc4j.cjs.map → bundler-DmLJQ7AY.cjs.map} +1 -1
  33. package/dist/{cli-BvBdv660.cjs → cli-C2c-jOVK.cjs} +4 -4
  34. package/dist/{cli-BvBdv660.cjs.map → cli-C2c-jOVK.cjs.map} +1 -1
  35. package/dist/{cli-BsFenyaf.mjs → cli-Ce6NgaQF.mjs} +4 -4
  36. package/dist/{cli-BsFenyaf.mjs.map → cli-Ce6NgaQF.mjs.map} +1 -1
  37. package/dist/{compose-D2RFYd_f.mjs → compose-BJDPFBAN.mjs} +43 -47
  38. package/dist/compose-BJDPFBAN.mjs.map +1 -0
  39. package/dist/{compose-Cd09gW-n.cjs → compose-ETFKqkTu.cjs} +60 -64
  40. package/dist/compose-ETFKqkTu.cjs.map +1 -0
  41. package/dist/{config-Ngesg4O8.d.mts → config-4yirvxS8.d.cts} +4 -4
  42. package/dist/{config-DvHNMoOp.d.cts.map → config-4yirvxS8.d.cts.map} +1 -1
  43. package/dist/{config-DvHNMoOp.d.cts → config-C8NPCn1l.d.mts} +4 -4
  44. package/dist/{config-Ngesg4O8.d.mts.map → config-C8NPCn1l.d.mts.map} +1 -1
  45. package/dist/config.cjs +1 -1
  46. package/dist/config.d.cts +3 -3
  47. package/dist/config.d.mts +3 -3
  48. package/dist/config.mjs +1 -1
  49. package/dist/{credentials-DpfnUvIR.mjs → credentials-B5N5yKk6.mjs} +4 -132
  50. package/dist/credentials-B5N5yKk6.mjs.map +1 -0
  51. package/dist/{credentials-D7XJypNd.cjs → credentials-Zqr3QQYB.cjs} +3 -173
  52. package/dist/credentials-Zqr3QQYB.cjs.map +1 -0
  53. package/dist/deploy/public.cjs +16 -15
  54. package/dist/deploy/public.cjs.map +1 -1
  55. package/dist/deploy/public.d.cts +5 -5
  56. package/dist/deploy/public.d.cts.map +1 -1
  57. package/dist/deploy/public.d.mts +5 -5
  58. package/dist/deploy/public.d.mts.map +1 -1
  59. package/dist/deploy/public.mjs +11 -10
  60. package/dist/deploy/public.mjs.map +1 -1
  61. package/dist/deploy-BdN0ym2i.cjs +2057 -0
  62. package/dist/deploy-BdN0ym2i.cjs.map +1 -0
  63. package/dist/deploy-DktQl7ti.mjs +2008 -0
  64. package/dist/deploy-DktQl7ti.mjs.map +1 -0
  65. package/dist/{discover-CTzOSGUF.d.cts → discover-BtFofyQB.d.cts} +2 -2
  66. package/dist/{discover-CTzOSGUF.d.cts.map → discover-BtFofyQB.d.cts.map} +1 -1
  67. package/dist/{discover-CihAtaoj.d.mts → discover-D-MdXZgm.d.mts} +2 -2
  68. package/dist/{discover-CihAtaoj.d.mts.map → discover-D-MdXZgm.d.mts.map} +1 -1
  69. package/dist/dns-BjHECDO7.mjs +44 -0
  70. package/dist/dns-BjHECDO7.mjs.map +1 -0
  71. package/dist/dns-C-X6PLkV.cjs +663 -0
  72. package/dist/dns-C-X6PLkV.cjs.map +1 -0
  73. package/dist/dns-C2EeR6n2.mjs +610 -0
  74. package/dist/dns-C2EeR6n2.mjs.map +1 -0
  75. package/dist/dns-ClI7-d5g.cjs +55 -0
  76. package/dist/dns-ClI7-d5g.cjs.map +1 -0
  77. package/dist/{dokploy-CV7GcobZ.cjs → dokploy-CD_Bc4EV.cjs} +2 -2
  78. package/dist/{dokploy-CV7GcobZ.cjs.map → dokploy-CD_Bc4EV.cjs.map} +1 -1
  79. package/dist/{dokploy-D_aat2Xj.mjs → dokploy-CxtkS5hl.mjs} +2 -2
  80. package/dist/{dokploy-D_aat2Xj.mjs.map → dokploy-CxtkS5hl.mjs.map} +1 -1
  81. package/dist/{encryption-_4qKqtTx.mjs → encryption-BgQd4f2S.mjs} +3 -3
  82. package/dist/{encryption-_4qKqtTx.mjs.map → encryption-BgQd4f2S.mjs.map} +1 -1
  83. package/dist/{encryption-DFcivJaO.cjs → encryption-CqVfz-m7.cjs} +3 -3
  84. package/dist/{encryption-DFcivJaO.cjs.map → encryption-CqVfz-m7.cjs.map} +1 -1
  85. package/dist/{engine-Bv-LZpmj.cjs → engine-OVVKtPmW.cjs} +18 -36
  86. package/dist/engine-OVVKtPmW.cjs.map +1 -0
  87. package/dist/{engine-DPMHThkg.mjs → engine-YlXzlTUl.mjs} +14 -32
  88. package/dist/{engine-DPMHThkg.mjs.map → engine-YlXzlTUl.mjs.map} +1 -1
  89. package/dist/{github-Br42NMrW.cjs → github-CsMloeSL.cjs} +9 -7
  90. package/dist/{github-Br42NMrW.cjs.map → github-CsMloeSL.cjs.map} +1 -1
  91. package/dist/{github-xsDT19im.mjs → github-DuuvqI3Z.mjs} +5 -3
  92. package/dist/{github-xsDT19im.mjs.map → github-DuuvqI3Z.mjs.map} +1 -1
  93. package/dist/{index-CwLvFqtH.d.cts → index-5eL8rM6H.d.mts} +2 -2
  94. package/dist/{index-BlpcClwM.d.mts.map → index-5eL8rM6H.d.mts.map} +1 -1
  95. package/dist/{index-BlpcClwM.d.mts → index-Dz-gyjm_.d.cts} +2 -2
  96. package/dist/{index-CwLvFqtH.d.cts.map → index-Dz-gyjm_.d.cts.map} +1 -1
  97. package/dist/index.cjs +54 -53
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.mjs +52 -51
  100. package/dist/index.mjs.map +1 -1
  101. package/dist/{local-B7Zv1NoA.mjs → local-BwC2v2Y8.mjs} +2 -2
  102. package/dist/{local-B7Zv1NoA.mjs.map → local-BwC2v2Y8.mjs.map} +1 -1
  103. package/dist/{local-OPC9BCZt.cjs → local-DNhnkugT.cjs} +3 -3
  104. package/dist/{local-OPC9BCZt.cjs.map → local-DNhnkugT.cjs.map} +1 -1
  105. package/dist/{migrate-D5jUz20_.cjs → migrate-BAmJeVq1.cjs} +3 -3
  106. package/dist/{migrate-D5jUz20_.cjs.map → migrate-BAmJeVq1.cjs.map} +1 -1
  107. package/dist/{migrate-SkWJotn5.cjs → migrate-BdkoNdIu.cjs} +3 -3
  108. package/dist/{migrate-SkWJotn5.cjs.map → migrate-BdkoNdIu.cjs.map} +1 -1
  109. package/dist/{migrate-DhvFPGLi.mjs → migrate-CB8B6W9y.mjs} +3 -3
  110. package/dist/{migrate-DhvFPGLi.mjs.map → migrate-CB8B6W9y.mjs.map} +1 -1
  111. package/dist/{migrate-B7evHv7O.mjs → migrate-CsPFHgTs.mjs} +3 -3
  112. package/dist/{migrate-B7evHv7O.mjs.map → migrate-CsPFHgTs.mjs.map} +1 -1
  113. package/dist/openapi.cjs +1 -1
  114. package/dist/openapi.d.cts +1 -1
  115. package/dist/openapi.d.mts +1 -1
  116. package/dist/openapi.mjs +1 -1
  117. package/dist/reconcile/public.d.cts +2 -2
  118. package/dist/reconcile/public.d.mts +2 -2
  119. package/dist/{resolve-CFEOtRsl.cjs → resolve-BDatNOoG.cjs} +4 -4
  120. package/dist/{resolve-CFEOtRsl.cjs.map → resolve-BDatNOoG.cjs.map} +1 -1
  121. package/dist/{resolve-Dyd1S2wn.mjs → resolve-CUne0qOm.mjs} +4 -4
  122. package/dist/{resolve-Dyd1S2wn.mjs.map → resolve-CUne0qOm.mjs.map} +1 -1
  123. package/dist/{rollback-NroNbGC0.mjs → rollback-CCdEEEcF.mjs} +7 -8
  124. package/dist/{rollback-NroNbGC0.mjs.map → rollback-CCdEEEcF.mjs.map} +1 -1
  125. package/dist/{rollback-D720SFhV.cjs → rollback-CuG3DkTY.cjs} +8 -9
  126. package/dist/{rollback-D720SFhV.cjs.map → rollback-CuG3DkTY.cjs.map} +1 -1
  127. package/dist/run-BJLIerMM.mjs +133 -0
  128. package/dist/run-BJLIerMM.mjs.map +1 -0
  129. package/dist/run-fVZ-rLnc.cjs +174 -0
  130. package/dist/run-fVZ-rLnc.cjs.map +1 -0
  131. package/dist/{runtime-VktAo_8B.d.cts → runtime-DUQdM-mW.d.cts} +2 -2
  132. package/dist/{runtime-BRCq6dQ7.d.mts.map → runtime-DUQdM-mW.d.cts.map} +1 -1
  133. package/dist/{runtime-BRCq6dQ7.d.mts → runtime-Vr6mleo2.d.mts} +2 -2
  134. package/dist/{runtime-VktAo_8B.d.cts.map → runtime-Vr6mleo2.d.mts.map} +1 -1
  135. package/dist/{sandbox-D1gd0iDz.d.cts → sandbox-BbJmh2rI.d.cts} +2 -2
  136. package/dist/{sandbox-D1gd0iDz.d.cts.map → sandbox-BbJmh2rI.d.cts.map} +1 -1
  137. package/dist/{sandbox-zHnRLCj0.d.mts → sandbox-DGOsMPMf.d.mts} +2 -2
  138. package/dist/{sandbox-zHnRLCj0.d.mts.map → sandbox-DGOsMPMf.d.mts.map} +1 -1
  139. package/dist/{secrets-DAvi_O9g.cjs → secrets-C5qROlbp.cjs} +3 -3
  140. package/dist/{secrets-DAvi_O9g.cjs.map → secrets-C5qROlbp.cjs.map} +1 -1
  141. package/dist/{secrets-CwLauUB_.mjs → secrets-ZikTIxEm.mjs} +3 -3
  142. package/dist/{secrets-CwLauUB_.mjs.map → secrets-ZikTIxEm.mjs.map} +1 -1
  143. package/dist/{seeds-BCg8X36S.cjs → seeds-BjXW-Krf.cjs} +193 -946
  144. package/dist/seeds-BjXW-Krf.cjs.map +1 -0
  145. package/dist/{seeds-CTxTZa-R.mjs → seeds-CbJSne1A.mjs} +156 -825
  146. package/dist/seeds-CbJSne1A.mjs.map +1 -0
  147. package/dist/{sniffer-DCcuzHz_.mjs → sniffer-DQGBYY8i.mjs} +8 -8
  148. package/dist/{sniffer-DCcuzHz_.mjs.map → sniffer-DQGBYY8i.mjs.map} +1 -1
  149. package/dist/{sniffer-C0z3NB2A.cjs → sniffer-NPD1dyab.cjs} +8 -8
  150. package/dist/{sniffer-C0z3NB2A.cjs.map → sniffer-NPD1dyab.cjs.map} +1 -1
  151. package/dist/{sst-DRDSDwOk.mjs → sst-CGdjHn2A.mjs} +4 -3
  152. package/dist/{sst-DRDSDwOk.mjs.map → sst-CGdjHn2A.mjs.map} +1 -1
  153. package/dist/{sst-DKNH243z.cjs → sst-DGuHDxVU.cjs} +5 -4
  154. package/dist/{sst-DKNH243z.cjs.map → sst-DGuHDxVU.cjs.map} +1 -1
  155. package/dist/{stack-NrdH5ngX.mjs → stack-BFq3K-_z.mjs} +14 -52
  156. package/dist/stack-BFq3K-_z.mjs.map +1 -0
  157. package/dist/{stack-B3fPDTBg.cjs → stack-DOVvEd1T.cjs} +14 -52
  158. package/dist/stack-DOVvEd1T.cjs.map +1 -0
  159. package/dist/{stages-veC4TcQe.mjs → stages-BEn2ArJZ.mjs} +4 -3
  160. package/dist/{stages-veC4TcQe.mjs.map → stages-BEn2ArJZ.mjs.map} +1 -1
  161. package/dist/{stages-CkqP1N4S.cjs → stages-Cw6urZyJ.cjs} +5 -4
  162. package/dist/{stages-CkqP1N4S.cjs.map → stages-Cw6urZyJ.cjs.map} +1 -1
  163. package/dist/target/public.cjs +1 -1
  164. package/dist/target/public.d.cts +2 -2
  165. package/dist/target/public.d.mts +2 -2
  166. package/dist/target/public.mjs +1 -1
  167. package/dist/{terminal-CkUYuAPd.cjs → terminal-CPHuH4S1.cjs} +2 -2
  168. package/dist/{terminal-CkUYuAPd.cjs.map → terminal-CPHuH4S1.cjs.map} +1 -1
  169. package/dist/{terminal-DAHs2Zko.mjs → terminal-iNmAXXjs.mjs} +2 -2
  170. package/dist/{terminal-DAHs2Zko.mjs.map → terminal-iNmAXXjs.mjs.map} +1 -1
  171. package/dist/{types-DMoaFrjg.d.mts → types-bkqVscdN.d.mts} +12 -3
  172. package/dist/types-bkqVscdN.d.mts.map +1 -0
  173. package/dist/{types-DXyaSmqu.d.cts → types-dipJRmKV.d.cts} +12 -3
  174. package/dist/types-dipJRmKV.d.cts.map +1 -0
  175. package/dist/workspace/index.cjs +1 -1
  176. package/dist/workspace/index.d.cts +2 -2
  177. package/dist/workspace/index.d.mts +2 -2
  178. package/dist/workspace/index.mjs +1 -1
  179. package/dist/{workspace-DWK1PTXP.mjs → workspace-CqFUjObk.mjs} +54 -2
  180. package/dist/workspace-CqFUjObk.mjs.map +1 -0
  181. package/dist/{workspace-cSyi5nb1.cjs → workspace-DDkm4y6D.cjs} +71 -1
  182. package/dist/workspace-DDkm4y6D.cjs.map +1 -0
  183. package/package.json +15 -15
  184. package/dist/add-C85isXFl.mjs.map +0 -1
  185. package/dist/add-DsVDdvon.cjs.map +0 -1
  186. package/dist/compose-Cd09gW-n.cjs.map +0 -1
  187. package/dist/compose-D2RFYd_f.mjs.map +0 -1
  188. package/dist/credentials-D7XJypNd.cjs.map +0 -1
  189. package/dist/credentials-DpfnUvIR.mjs.map +0 -1
  190. package/dist/deploy-C911Akkn.cjs +0 -670
  191. package/dist/deploy-C911Akkn.cjs.map +0 -1
  192. package/dist/deploy-CeJ5D0xn.mjs +0 -641
  193. package/dist/deploy-CeJ5D0xn.mjs.map +0 -1
  194. package/dist/engine-Bv-LZpmj.cjs.map +0 -1
  195. package/dist/providers-BFeP_mYw.cjs +0 -1098
  196. package/dist/providers-BFeP_mYw.cjs.map +0 -1
  197. package/dist/providers-sTj-BG0S.mjs +0 -1079
  198. package/dist/providers-sTj-BG0S.mjs.map +0 -1
  199. package/dist/seeds-BCg8X36S.cjs.map +0 -1
  200. package/dist/seeds-CTxTZa-R.mjs.map +0 -1
  201. package/dist/stack-B3fPDTBg.cjs.map +0 -1
  202. package/dist/stack-NrdH5ngX.mjs.map +0 -1
  203. package/dist/types-DMoaFrjg.d.mts.map +0 -1
  204. package/dist/types-DXyaSmqu.d.cts.map +0 -1
  205. package/dist/workspace-DWK1PTXP.mjs.map +0 -1
  206. package/dist/workspace-cSyi5nb1.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"stages-veC4TcQe.mjs","names":[],"sources":["../src/stages/plan.ts","../src/stages/index.ts"],"sourcesContent":["/**\n * Which stages a workflow run builds and deploys, from the event that started\n * it and the project's `stages`.\n *\n * The rules live here, in tested code, rather than in a workflow's YAML or in\n * the action that runs `gkm stages --github-output`: a project's deploy\n * workflow names no stage, and what it does for each event is decided by the\n * CLI the project installed.\n *\n * | event | build | deploy |\n * | ------------------- | ------------------ | ------------------------------- |\n * | `push` | every deployed | deployed, less the protected |\n * | `release` | none | the protected |\n * | `workflow_dispatch` | none | the one stage named |\n * | anything else | none | none |\n *\n * A push builds every deployed stage, protected ones included, so a release\n * deploys images built from the very commit its tag names; a release and a\n * manual run deploy what a push already built.\n */\n\nimport { GkmError } from '../errors';\nimport { UndeclaredStage } from '../workspace/stages.js';\nimport type { StagesConfig } from '../workspace/types.js';\n\nexport interface StagePlan {\n\t/** The stages whose images this run builds and pushes. */\n\tbuild: string[];\n\t/** The stages this run deploys. */\n\tdeploy: string[];\n}\n\nexport interface PlanInput {\n\t/** The GitHub event name: `push`, `release`, `workflow_dispatch`, … */\n\tevent: string;\n\t/** The stage a `workflow_dispatch` names. */\n\tstage?: string;\n}\n\nexport function planStages(stages: StagesConfig, input: PlanInput): StagePlan {\n\tconst kept = stages.protected ?? [];\n\n\tswitch (input.event) {\n\t\tcase 'push':\n\t\t\treturn {\n\t\t\t\tbuild: [...stages.deployed],\n\t\t\t\tdeploy: stages.deployed.filter((stage) => !kept.includes(stage)),\n\t\t\t};\n\t\tcase 'release':\n\t\t\treturn { build: [], deploy: [...kept] };\n\t\tcase 'workflow_dispatch': {\n\t\t\tconst stage = input.stage?.trim();\n\t\t\tif (!stage) throw new DispatchNamesNoStage(stages.deployed);\n\t\t\tif (!stages.deployed.includes(stage)) {\n\t\t\t\tthrow new UndeclaredStage(stage, stages.deployed);\n\t\t\t}\n\t\t\treturn { build: [], deploy: [stage] };\n\t\t}\n\t\tdefault:\n\t\t\treturn { build: [], deploy: [] };\n\t}\n}\n\n/**\n * A manual run with no stage. Refused rather than read as \"nothing to do\", so\n * a run started with the field left empty fails where it can be seen.\n */\nexport class DispatchNamesNoStage extends GkmError {\n\tconstructor(readonly deployed: readonly string[]) {\n\t\tsuper(\n\t\t\t`A manual run deploys one stage, and none was given. Run the workflow again with stage set to one of: ${deployed.join(', ') || 'nothing yet — gkm.config.ts deploys to no stage'}.`,\n\t\t);\n\t\tthis.name = 'DispatchNamesNoStage';\n\t}\n}\n","/**\n * `gkm stages` — the workspace's stages, as gkm.config.ts declares them.\n *\n * ```bash\n * gkm stages # a table\n * gkm stages --json # {\"local\":\"dev\",\"deployed\":[\"prod\"],\"protected\":[\"prod\"]}\n * gkm stages --github-output # a workflow run's build and deploy matrices\n * ```\n *\n * The config is read by the normal loader (and sandbox), so a workflow never\n * parses TypeScript to learn which stages exist. `--github-output` is what the\n * `geekmidas/toolbox/actions/stages` action runs: it writes the stages, and\n * which of them this run builds and deploys, to `$GITHUB_OUTPUT`.\n */\n\nimport { appendFile } from 'node:fs/promises';\nimport { stageDnsDomains } from '../compose/dns.js';\nimport { loadWorkspaceSettings } from '../config.js';\nimport { GkmError } from '../errors';\nimport { stageProvider } from '../providers/config.js';\nimport { PROVIDER_KINDS } from '../providers/types.js';\nimport type { NormalizedWorkspace, StagesConfig } from '../workspace/types.js';\nimport { planStages } from './plan.js';\n\nexport { DispatchNamesNoStage, type PlanInput, planStages } from './plan.js';\n\nexport interface StagesOptions {\n\t/** Print the stages as JSON. */\n\tjson?: boolean;\n\t/** Write the outputs a deploy workflow reads to `$GITHUB_OUTPUT`. */\n\tgithubOutput?: boolean;\n\t/** The event to plan for; defaults to `GITHUB_EVENT_NAME`. */\n\tevent?: string;\n\t/** The stage a `workflow_dispatch` names. */\n\tstage?: string;\n}\n\nexport interface StagesDeps {\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\t/** Where lines go; stdout by default. */\n\tlog?: (line: string) => void;\n}\n\n/** The stages, as `gkm stages --json` prints them. */\nexport interface StagesJson {\n\tlocal: string;\n\tdeployed: string[];\n\tprotected: string[];\n}\n\nexport function stagesJson(stages: StagesConfig): StagesJson {\n\treturn {\n\t\tlocal: stages.local,\n\t\tdeployed: [...stages.deployed],\n\t\tprotected: [...(stages.protected ?? [])],\n\t};\n}\n\n/**\n * The region of the workspace's AWS secrets store — `ssm` or\n * `secrets-manager` — or `''` when its deployed stages keep their secrets\n * anywhere else. A job assumes the stage's AWS role only when this is set.\n */\nexport function awsSecretsRegion(workspace: NormalizedWorkspace): string {\n\tconst store = workspace.secrets?.store;\n\tif (typeof store !== 'object' || store === null) return '';\n\tif (store.provider === 'ssm' || store.provider === 'secrets-manager') {\n\t\treturn store.region;\n\t}\n\treturn '';\n}\n\n/**\n * The deployed stages with resources the deploy creates — a provider under\n * `deploy.<kind>.<stage>`, or a domain under a `dns` entry whose provider\n * writes records — and secrets a CI runner can reach (an AWS store): a\n * compose deploy workflow creates their resources on the runner, with the\n * stage's role and DNS token, rather than on the server.\n */\nexport function resourceStages(workspace: NormalizedWorkspace): string[] {\n\tif (!awsSecretsRegion(workspace)) return [];\n\treturn workspace.stages.deployed.filter(\n\t\t(stage) =>\n\t\t\tPROVIDER_KINDS.some(\n\t\t\t\t(kind) => stageProvider(workspace, kind, stage).mode === 'provider',\n\t\t\t) ||\n\t\t\tstageDnsDomains(stage, workspace.domains, workspace.dns).some(\n\t\t\t\t({ config }) => config.provider !== 'manual',\n\t\t\t),\n\t);\n}\n\n/**\n * Every output the stages action sets, each a string `fromJSON()` reads, for\n * one workflow run.\n */\nexport function githubOutputs(\n\tworkspace: NormalizedWorkspace,\n\tinput: { event: string; stage?: string },\n): Record<string, string> {\n\tconst stages = stagesJson(workspace.stages);\n\tconst plan = planStages(workspace.stages, input);\n\n\treturn {\n\t\tlocal: JSON.stringify(stages.local),\n\t\tdeployed: JSON.stringify(stages.deployed),\n\t\tprotected: JSON.stringify(stages.protected),\n\t\tbuild: JSON.stringify(plan.build),\n\t\tdeploy: JSON.stringify(plan.deploy),\n\t\t// A matrix over an empty list is an error on GitHub, so a job over one\n\t\t// is skipped on these instead.\n\t\t'has-build': String(plan.build.length > 0),\n\t\t'has-deploy': String(plan.deploy.length > 0),\n\t\t'aws-region': awsSecretsRegion(workspace),\n\t\tresources: JSON.stringify(resourceStages(workspace)),\n\t};\n}\n\n/** `name=value` lines, as `$GITHUB_OUTPUT` takes single-line values. */\nexport function formatGithubOutputs(outputs: Record<string, string>): string {\n\treturn Object.entries(outputs)\n\t\t.map(([name, value]) => `${name}=${value}\\n`)\n\t\t.join('');\n}\n\n/** A message as a workflow command's data: GitHub reads `%`, CR and LF escaped. */\nfunction workflowCommandData(message: string): string {\n\treturn message\n\t\t.replaceAll('%', '%25')\n\t\t.replaceAll('\\r', '%0D')\n\t\t.replaceAll('\\n', '%0A');\n}\n\nfunction table(stages: StagesJson): string {\n\tconst rows: [string, string][] = [\n\t\t['STAGE', 'KIND'],\n\t\t[stages.local, 'local'],\n\t\t...stages.deployed.map((name): [string, string] => [\n\t\t\tname,\n\t\t\tstages.protected.includes(name) ? 'deployed, protected' : 'deployed',\n\t\t]),\n\t];\n\tconst width = Math.max(...rows.map(([name]) => name.length));\n\treturn rows\n\t\t.map(([name, kind]) => `${name.padEnd(width)} ${kind}`)\n\t\t.join('\\n');\n}\n\nexport async function stagesCommand(\n\toptions: StagesOptions,\n\tdeps: StagesDeps = {},\n): Promise<void> {\n\tconst env = deps.env ?? process.env;\n\tconst log = deps.log ?? ((line: string) => console.log(line));\n\n\tif (!options.githubOutput) {\n\t\tconst workspace = await loadWorkspaceSettings(deps.cwd);\n\t\tconst stages = stagesJson(workspace.stages);\n\t\tlog(options.json ? JSON.stringify(stages) : table(stages));\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst file = env.GITHUB_OUTPUT;\n\t\tif (!file) throw new GithubOutputNotSet();\n\n\t\tconst workspace = await loadWorkspaceSettings(deps.cwd);\n\t\tconst event = options.event || env.GITHUB_EVENT_NAME;\n\t\tif (!event) throw new GithubEventNotSet();\n\n\t\tconst outputs = githubOutputs(workspace, {\n\t\t\tevent,\n\t\t\t...(options.stage ? { stage: options.stage } : {}),\n\t\t});\n\t\tawait appendFile(file, formatGithubOutputs(outputs));\n\n\t\tlog(`${event}: build ${outputs.build}, deploy ${outputs.deploy}`);\n\t} catch (error) {\n\t\t// Annotated on the run, where whoever started it looks first.\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tlog(`::error title=gkm stages::${workflowCommandData(message)}`);\n\t\tthrow error;\n\t}\n}\n\n/** `--github-output` outside a GitHub Actions step, which sets the file. */\nexport class GithubOutputNotSet extends GkmError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'gkm stages --github-output writes to the file GITHUB_OUTPUT names, and it is not set. Run it in a GitHub Actions step, or set GITHUB_OUTPUT to a file to write to.',\n\t\t);\n\t\tthis.name = 'GithubOutputNotSet';\n\t}\n}\n\n/** No `--event`, and no `GITHUB_EVENT_NAME` to take it from. */\nexport class GithubEventNotSet extends GkmError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'gkm stages --github-output plans for an event, and none was given. Pass --event (push, release, workflow_dispatch), or run it in a GitHub Actions step, which sets GITHUB_EVENT_NAME.',\n\t\t);\n\t\tthis.name = 'GithubEventNotSet';\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stages-BEn2ArJZ.mjs","names":[],"sources":["../src/stages/plan.ts","../src/stages/index.ts"],"sourcesContent":["/**\n * Which stages a workflow run builds and deploys, from the event that started\n * it and the project's `stages`.\n *\n * The rules live here, in tested code, rather than in a workflow's YAML or in\n * the action that runs `gkm stages --github-output`: a project's deploy\n * workflow names no stage, and what it does for each event is decided by the\n * CLI the project installed.\n *\n * | event | build | deploy |\n * | ------------------- | ------------------ | ------------------------------- |\n * | `push` | every deployed | deployed, less the protected |\n * | `release` | none | the protected |\n * | `workflow_dispatch` | none | the one stage named |\n * | anything else | none | none |\n *\n * A push builds every deployed stage, protected ones included, so a release\n * deploys images built from the very commit its tag names; a release and a\n * manual run deploy what a push already built.\n */\n\nimport { GkmError } from '../errors';\nimport { UndeclaredStage } from '../workspace/stages.js';\nimport type { StagesConfig } from '../workspace/types.js';\n\nexport interface StagePlan {\n\t/** The stages whose images this run builds and pushes. */\n\tbuild: string[];\n\t/** The stages this run deploys. */\n\tdeploy: string[];\n}\n\nexport interface PlanInput {\n\t/** The GitHub event name: `push`, `release`, `workflow_dispatch`, … */\n\tevent: string;\n\t/** The stage a `workflow_dispatch` names. */\n\tstage?: string;\n}\n\nexport function planStages(stages: StagesConfig, input: PlanInput): StagePlan {\n\tconst kept = stages.protected ?? [];\n\n\tswitch (input.event) {\n\t\tcase 'push':\n\t\t\treturn {\n\t\t\t\tbuild: [...stages.deployed],\n\t\t\t\tdeploy: stages.deployed.filter((stage) => !kept.includes(stage)),\n\t\t\t};\n\t\tcase 'release':\n\t\t\treturn { build: [], deploy: [...kept] };\n\t\tcase 'workflow_dispatch': {\n\t\t\tconst stage = input.stage?.trim();\n\t\t\tif (!stage) throw new DispatchNamesNoStage(stages.deployed);\n\t\t\tif (!stages.deployed.includes(stage)) {\n\t\t\t\tthrow new UndeclaredStage(stage, stages.deployed);\n\t\t\t}\n\t\t\treturn { build: [], deploy: [stage] };\n\t\t}\n\t\tdefault:\n\t\t\treturn { build: [], deploy: [] };\n\t}\n}\n\n/**\n * A manual run with no stage. Refused rather than read as \"nothing to do\", so\n * a run started with the field left empty fails where it can be seen.\n */\nexport class DispatchNamesNoStage extends GkmError {\n\tconstructor(readonly deployed: readonly string[]) {\n\t\tsuper(\n\t\t\t`A manual run deploys one stage, and none was given. Run the workflow again with stage set to one of: ${deployed.join(', ') || 'nothing yet — gkm.config.ts deploys to no stage'}.`,\n\t\t);\n\t\tthis.name = 'DispatchNamesNoStage';\n\t}\n}\n","/**\n * `gkm stages` — the workspace's stages, as gkm.config.ts declares them.\n *\n * ```bash\n * gkm stages # a table\n * gkm stages --json # {\"local\":\"dev\",\"deployed\":[\"prod\"],\"protected\":[\"prod\"]}\n * gkm stages --github-output # a workflow run's build and deploy matrices\n * ```\n *\n * The config is read by the normal loader (and sandbox), so a workflow never\n * parses TypeScript to learn which stages exist. `--github-output` is what the\n * `geekmidas/toolbox/actions/stages` action runs: it writes the stages, and\n * which of them this run builds and deploys, to `$GITHUB_OUTPUT`.\n */\n\nimport { appendFile } from 'node:fs/promises';\nimport { stageDnsDomains } from '../compose/dns.js';\nimport { loadWorkspaceSettings } from '../config.js';\nimport { GkmError } from '../errors';\nimport { stageProvider } from '../providers/config.js';\nimport { PROVIDER_KINDS } from '../providers/types.js';\nimport type { NormalizedWorkspace, StagesConfig } from '../workspace/types.js';\nimport { planStages } from './plan.js';\n\nexport { DispatchNamesNoStage, type PlanInput, planStages } from './plan.js';\n\nexport interface StagesOptions {\n\t/** Print the stages as JSON. */\n\tjson?: boolean;\n\t/** Write the outputs a deploy workflow reads to `$GITHUB_OUTPUT`. */\n\tgithubOutput?: boolean;\n\t/** The event to plan for; defaults to `GITHUB_EVENT_NAME`. */\n\tevent?: string;\n\t/** The stage a `workflow_dispatch` names. */\n\tstage?: string;\n}\n\nexport interface StagesDeps {\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\t/** Where lines go; stdout by default. */\n\tlog?: (line: string) => void;\n}\n\n/** The stages, as `gkm stages --json` prints them. */\nexport interface StagesJson {\n\tlocal: string;\n\tdeployed: string[];\n\tprotected: string[];\n}\n\nexport function stagesJson(stages: StagesConfig): StagesJson {\n\treturn {\n\t\tlocal: stages.local,\n\t\tdeployed: [...stages.deployed],\n\t\tprotected: [...(stages.protected ?? [])],\n\t};\n}\n\n/**\n * The region of the workspace's AWS secrets store — `ssm` or\n * `secrets-manager` — or `''` when its deployed stages keep their secrets\n * anywhere else. A job assumes the stage's AWS role only when this is set.\n */\nexport function awsSecretsRegion(workspace: NormalizedWorkspace): string {\n\tconst store = workspace.secrets?.store;\n\tif (typeof store !== 'object' || store === null) return '';\n\tif (store.provider === 'ssm' || store.provider === 'secrets-manager') {\n\t\treturn store.region;\n\t}\n\treturn '';\n}\n\n/**\n * The deployed stages with resources the deploy creates — a provider under\n * `deploy.<kind>.<stage>`, or a domain under a `dns` entry whose provider\n * writes records — and secrets a CI runner can reach (an AWS store): a\n * compose deploy workflow creates their resources on the runner, with the\n * stage's role and DNS token, rather than on the server.\n */\nexport function resourceStages(workspace: NormalizedWorkspace): string[] {\n\tif (!awsSecretsRegion(workspace)) return [];\n\treturn workspace.stages.deployed.filter(\n\t\t(stage) =>\n\t\t\tPROVIDER_KINDS.some(\n\t\t\t\t(kind) => stageProvider(workspace, kind, stage).mode === 'provider',\n\t\t\t) ||\n\t\t\tstageDnsDomains(stage, workspace.domains, workspace.dns).some(\n\t\t\t\t({ config }) => config.provider !== 'manual',\n\t\t\t),\n\t);\n}\n\n/**\n * Every output the stages action sets, each a string `fromJSON()` reads, for\n * one workflow run.\n */\nexport function githubOutputs(\n\tworkspace: NormalizedWorkspace,\n\tinput: { event: string; stage?: string },\n): Record<string, string> {\n\tconst stages = stagesJson(workspace.stages);\n\tconst plan = planStages(workspace.stages, input);\n\n\treturn {\n\t\tlocal: JSON.stringify(stages.local),\n\t\tdeployed: JSON.stringify(stages.deployed),\n\t\tprotected: JSON.stringify(stages.protected),\n\t\tbuild: JSON.stringify(plan.build),\n\t\tdeploy: JSON.stringify(plan.deploy),\n\t\t// A matrix over an empty list is an error on GitHub, so a job over one\n\t\t// is skipped on these instead.\n\t\t'has-build': String(plan.build.length > 0),\n\t\t'has-deploy': String(plan.deploy.length > 0),\n\t\t'aws-region': awsSecretsRegion(workspace),\n\t\tresources: JSON.stringify(resourceStages(workspace)),\n\t};\n}\n\n/** `name=value` lines, as `$GITHUB_OUTPUT` takes single-line values. */\nexport function formatGithubOutputs(outputs: Record<string, string>): string {\n\treturn Object.entries(outputs)\n\t\t.map(([name, value]) => `${name}=${value}\\n`)\n\t\t.join('');\n}\n\n/** A message as a workflow command's data: GitHub reads `%`, CR and LF escaped. */\nfunction workflowCommandData(message: string): string {\n\treturn message\n\t\t.replaceAll('%', '%25')\n\t\t.replaceAll('\\r', '%0D')\n\t\t.replaceAll('\\n', '%0A');\n}\n\nfunction table(stages: StagesJson): string {\n\tconst rows: [string, string][] = [\n\t\t['STAGE', 'KIND'],\n\t\t[stages.local, 'local'],\n\t\t...stages.deployed.map((name): [string, string] => [\n\t\t\tname,\n\t\t\tstages.protected.includes(name) ? 'deployed, protected' : 'deployed',\n\t\t]),\n\t];\n\tconst width = Math.max(...rows.map(([name]) => name.length));\n\treturn rows\n\t\t.map(([name, kind]) => `${name.padEnd(width)} ${kind}`)\n\t\t.join('\\n');\n}\n\nexport async function stagesCommand(\n\toptions: StagesOptions,\n\tdeps: StagesDeps = {},\n): Promise<void> {\n\tconst env = deps.env ?? process.env;\n\tconst log = deps.log ?? ((line: string) => console.log(line));\n\n\tif (!options.githubOutput) {\n\t\tconst workspace = await loadWorkspaceSettings(deps.cwd);\n\t\tconst stages = stagesJson(workspace.stages);\n\t\tlog(options.json ? JSON.stringify(stages) : table(stages));\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst file = env.GITHUB_OUTPUT;\n\t\tif (!file) throw new GithubOutputNotSet();\n\n\t\tconst workspace = await loadWorkspaceSettings(deps.cwd);\n\t\tconst event = options.event || env.GITHUB_EVENT_NAME;\n\t\tif (!event) throw new GithubEventNotSet();\n\n\t\tconst outputs = githubOutputs(workspace, {\n\t\t\tevent,\n\t\t\t...(options.stage ? { stage: options.stage } : {}),\n\t\t});\n\t\tawait appendFile(file, formatGithubOutputs(outputs));\n\n\t\tlog(`${event}: build ${outputs.build}, deploy ${outputs.deploy}`);\n\t} catch (error) {\n\t\t// Annotated on the run, where whoever started it looks first.\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tlog(`::error title=gkm stages::${workflowCommandData(message)}`);\n\t\tthrow error;\n\t}\n}\n\n/** `--github-output` outside a GitHub Actions step, which sets the file. */\nexport class GithubOutputNotSet extends GkmError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'gkm stages --github-output writes to the file GITHUB_OUTPUT names, and it is not set. Run it in a GitHub Actions step, or set GITHUB_OUTPUT to a file to write to.',\n\t\t);\n\t\tthis.name = 'GithubOutputNotSet';\n\t}\n}\n\n/** No `--event`, and no `GITHUB_EVENT_NAME` to take it from. */\nexport class GithubEventNotSet extends GkmError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'gkm stages --github-output plans for an event, and none was given. Pass --event (push, release, workflow_dispatch), or run it in a GitHub Actions step, which sets GITHUB_EVENT_NAME.',\n\t\t);\n\t\tthis.name = 'GithubEventNotSet';\n\t}\n}\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  const require_errors = require("./errors-DMC4Umsb.cjs");
2
- const require_workspace = require("./workspace-cSyi5nb1.cjs");
2
+ const require_workspace = require("./workspace-DDkm4y6D.cjs");
3
3
  const require_config = require("./config.cjs");
4
- const require_seeds = require("./seeds-BCg8X36S.cjs");
4
+ const require_seeds = require("./seeds-BjXW-Krf.cjs");
5
+ const require_dns = require("./dns-C-X6PLkV.cjs");
5
6
  let node_fs_promises = require("node:fs/promises");
6
7
  //#region src/stages/plan.ts
7
8
  /**
@@ -105,7 +106,7 @@ function awsSecretsRegion(workspace) {
105
106
  */
106
107
  function resourceStages(workspace) {
107
108
  if (!awsSecretsRegion(workspace)) return [];
108
- return workspace.stages.deployed.filter((stage) => require_seeds.PROVIDER_KINDS.some((kind) => require_workspace.stageProvider(workspace, kind, stage).mode === "provider") || require_seeds.stageDnsDomains(stage, workspace.domains, workspace.dns).some(({ config }) => config.provider !== "manual"));
109
+ return workspace.stages.deployed.filter((stage) => require_seeds.PROVIDER_KINDS.some((kind) => require_workspace.stageProvider(workspace, kind, stage).mode === "provider") || require_dns.stageDnsDomains(stage, workspace.domains, workspace.dns).some(({ config }) => config.provider !== "manual"));
109
110
  }
110
111
  /**
111
112
  * Every output the stages action sets, each a string `fromJSON()` reads, for
@@ -185,4 +186,4 @@ var GithubEventNotSet = class extends require_errors.GkmError {
185
186
  //#endregion
186
187
  exports.stagesCommand = stagesCommand;
187
188
 
188
- //# sourceMappingURL=stages-CkqP1N4S.cjs.map
189
+ //# sourceMappingURL=stages-Cw6urZyJ.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"stages-CkqP1N4S.cjs","names":["UndeclaredStage","GkmError","PROVIDER_KINDS","stageProvider","stageDnsDomains","loadWorkspaceSettings","appendFile","GkmError"],"sources":["../src/stages/plan.ts","../src/stages/index.ts"],"sourcesContent":["/**\n * Which stages a workflow run builds and deploys, from the event that started\n * it and the project's `stages`.\n *\n * The rules live here, in tested code, rather than in a workflow's YAML or in\n * the action that runs `gkm stages --github-output`: a project's deploy\n * workflow names no stage, and what it does for each event is decided by the\n * CLI the project installed.\n *\n * | event | build | deploy |\n * | ------------------- | ------------------ | ------------------------------- |\n * | `push` | every deployed | deployed, less the protected |\n * | `release` | none | the protected |\n * | `workflow_dispatch` | none | the one stage named |\n * | anything else | none | none |\n *\n * A push builds every deployed stage, protected ones included, so a release\n * deploys images built from the very commit its tag names; a release and a\n * manual run deploy what a push already built.\n */\n\nimport { GkmError } from '../errors';\nimport { UndeclaredStage } from '../workspace/stages.js';\nimport type { StagesConfig } from '../workspace/types.js';\n\nexport interface StagePlan {\n\t/** The stages whose images this run builds and pushes. */\n\tbuild: string[];\n\t/** The stages this run deploys. */\n\tdeploy: string[];\n}\n\nexport interface PlanInput {\n\t/** The GitHub event name: `push`, `release`, `workflow_dispatch`, … */\n\tevent: string;\n\t/** The stage a `workflow_dispatch` names. */\n\tstage?: string;\n}\n\nexport function planStages(stages: StagesConfig, input: PlanInput): StagePlan {\n\tconst kept = stages.protected ?? [];\n\n\tswitch (input.event) {\n\t\tcase 'push':\n\t\t\treturn {\n\t\t\t\tbuild: [...stages.deployed],\n\t\t\t\tdeploy: stages.deployed.filter((stage) => !kept.includes(stage)),\n\t\t\t};\n\t\tcase 'release':\n\t\t\treturn { build: [], deploy: [...kept] };\n\t\tcase 'workflow_dispatch': {\n\t\t\tconst stage = input.stage?.trim();\n\t\t\tif (!stage) throw new DispatchNamesNoStage(stages.deployed);\n\t\t\tif (!stages.deployed.includes(stage)) {\n\t\t\t\tthrow new UndeclaredStage(stage, stages.deployed);\n\t\t\t}\n\t\t\treturn { build: [], deploy: [stage] };\n\t\t}\n\t\tdefault:\n\t\t\treturn { build: [], deploy: [] };\n\t}\n}\n\n/**\n * A manual run with no stage. Refused rather than read as \"nothing to do\", so\n * a run started with the field left empty fails where it can be seen.\n */\nexport class DispatchNamesNoStage extends GkmError {\n\tconstructor(readonly deployed: readonly string[]) {\n\t\tsuper(\n\t\t\t`A manual run deploys one stage, and none was given. Run the workflow again with stage set to one of: ${deployed.join(', ') || 'nothing yet — gkm.config.ts deploys to no stage'}.`,\n\t\t);\n\t\tthis.name = 'DispatchNamesNoStage';\n\t}\n}\n","/**\n * `gkm stages` — the workspace's stages, as gkm.config.ts declares them.\n *\n * ```bash\n * gkm stages # a table\n * gkm stages --json # {\"local\":\"dev\",\"deployed\":[\"prod\"],\"protected\":[\"prod\"]}\n * gkm stages --github-output # a workflow run's build and deploy matrices\n * ```\n *\n * The config is read by the normal loader (and sandbox), so a workflow never\n * parses TypeScript to learn which stages exist. `--github-output` is what the\n * `geekmidas/toolbox/actions/stages` action runs: it writes the stages, and\n * which of them this run builds and deploys, to `$GITHUB_OUTPUT`.\n */\n\nimport { appendFile } from 'node:fs/promises';\nimport { stageDnsDomains } from '../compose/dns.js';\nimport { loadWorkspaceSettings } from '../config.js';\nimport { GkmError } from '../errors';\nimport { stageProvider } from '../providers/config.js';\nimport { PROVIDER_KINDS } from '../providers/types.js';\nimport type { NormalizedWorkspace, StagesConfig } from '../workspace/types.js';\nimport { planStages } from './plan.js';\n\nexport { DispatchNamesNoStage, type PlanInput, planStages } from './plan.js';\n\nexport interface StagesOptions {\n\t/** Print the stages as JSON. */\n\tjson?: boolean;\n\t/** Write the outputs a deploy workflow reads to `$GITHUB_OUTPUT`. */\n\tgithubOutput?: boolean;\n\t/** The event to plan for; defaults to `GITHUB_EVENT_NAME`. */\n\tevent?: string;\n\t/** The stage a `workflow_dispatch` names. */\n\tstage?: string;\n}\n\nexport interface StagesDeps {\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\t/** Where lines go; stdout by default. */\n\tlog?: (line: string) => void;\n}\n\n/** The stages, as `gkm stages --json` prints them. */\nexport interface StagesJson {\n\tlocal: string;\n\tdeployed: string[];\n\tprotected: string[];\n}\n\nexport function stagesJson(stages: StagesConfig): StagesJson {\n\treturn {\n\t\tlocal: stages.local,\n\t\tdeployed: [...stages.deployed],\n\t\tprotected: [...(stages.protected ?? [])],\n\t};\n}\n\n/**\n * The region of the workspace's AWS secrets store — `ssm` or\n * `secrets-manager` — or `''` when its deployed stages keep their secrets\n * anywhere else. A job assumes the stage's AWS role only when this is set.\n */\nexport function awsSecretsRegion(workspace: NormalizedWorkspace): string {\n\tconst store = workspace.secrets?.store;\n\tif (typeof store !== 'object' || store === null) return '';\n\tif (store.provider === 'ssm' || store.provider === 'secrets-manager') {\n\t\treturn store.region;\n\t}\n\treturn '';\n}\n\n/**\n * The deployed stages with resources the deploy creates — a provider under\n * `deploy.<kind>.<stage>`, or a domain under a `dns` entry whose provider\n * writes records — and secrets a CI runner can reach (an AWS store): a\n * compose deploy workflow creates their resources on the runner, with the\n * stage's role and DNS token, rather than on the server.\n */\nexport function resourceStages(workspace: NormalizedWorkspace): string[] {\n\tif (!awsSecretsRegion(workspace)) return [];\n\treturn workspace.stages.deployed.filter(\n\t\t(stage) =>\n\t\t\tPROVIDER_KINDS.some(\n\t\t\t\t(kind) => stageProvider(workspace, kind, stage).mode === 'provider',\n\t\t\t) ||\n\t\t\tstageDnsDomains(stage, workspace.domains, workspace.dns).some(\n\t\t\t\t({ config }) => config.provider !== 'manual',\n\t\t\t),\n\t);\n}\n\n/**\n * Every output the stages action sets, each a string `fromJSON()` reads, for\n * one workflow run.\n */\nexport function githubOutputs(\n\tworkspace: NormalizedWorkspace,\n\tinput: { event: string; stage?: string },\n): Record<string, string> {\n\tconst stages = stagesJson(workspace.stages);\n\tconst plan = planStages(workspace.stages, input);\n\n\treturn {\n\t\tlocal: JSON.stringify(stages.local),\n\t\tdeployed: JSON.stringify(stages.deployed),\n\t\tprotected: JSON.stringify(stages.protected),\n\t\tbuild: JSON.stringify(plan.build),\n\t\tdeploy: JSON.stringify(plan.deploy),\n\t\t// A matrix over an empty list is an error on GitHub, so a job over one\n\t\t// is skipped on these instead.\n\t\t'has-build': String(plan.build.length > 0),\n\t\t'has-deploy': String(plan.deploy.length > 0),\n\t\t'aws-region': awsSecretsRegion(workspace),\n\t\tresources: JSON.stringify(resourceStages(workspace)),\n\t};\n}\n\n/** `name=value` lines, as `$GITHUB_OUTPUT` takes single-line values. */\nexport function formatGithubOutputs(outputs: Record<string, string>): string {\n\treturn Object.entries(outputs)\n\t\t.map(([name, value]) => `${name}=${value}\\n`)\n\t\t.join('');\n}\n\n/** A message as a workflow command's data: GitHub reads `%`, CR and LF escaped. */\nfunction workflowCommandData(message: string): string {\n\treturn message\n\t\t.replaceAll('%', '%25')\n\t\t.replaceAll('\\r', '%0D')\n\t\t.replaceAll('\\n', '%0A');\n}\n\nfunction table(stages: StagesJson): string {\n\tconst rows: [string, string][] = [\n\t\t['STAGE', 'KIND'],\n\t\t[stages.local, 'local'],\n\t\t...stages.deployed.map((name): [string, string] => [\n\t\t\tname,\n\t\t\tstages.protected.includes(name) ? 'deployed, protected' : 'deployed',\n\t\t]),\n\t];\n\tconst width = Math.max(...rows.map(([name]) => name.length));\n\treturn rows\n\t\t.map(([name, kind]) => `${name.padEnd(width)} ${kind}`)\n\t\t.join('\\n');\n}\n\nexport async function stagesCommand(\n\toptions: StagesOptions,\n\tdeps: StagesDeps = {},\n): Promise<void> {\n\tconst env = deps.env ?? process.env;\n\tconst log = deps.log ?? ((line: string) => console.log(line));\n\n\tif (!options.githubOutput) {\n\t\tconst workspace = await loadWorkspaceSettings(deps.cwd);\n\t\tconst stages = stagesJson(workspace.stages);\n\t\tlog(options.json ? JSON.stringify(stages) : table(stages));\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst file = env.GITHUB_OUTPUT;\n\t\tif (!file) throw new GithubOutputNotSet();\n\n\t\tconst workspace = await loadWorkspaceSettings(deps.cwd);\n\t\tconst event = options.event || env.GITHUB_EVENT_NAME;\n\t\tif (!event) throw new GithubEventNotSet();\n\n\t\tconst outputs = githubOutputs(workspace, {\n\t\t\tevent,\n\t\t\t...(options.stage ? { stage: options.stage } : {}),\n\t\t});\n\t\tawait appendFile(file, formatGithubOutputs(outputs));\n\n\t\tlog(`${event}: build ${outputs.build}, deploy ${outputs.deploy}`);\n\t} catch (error) {\n\t\t// Annotated on the run, where whoever started it looks first.\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tlog(`::error title=gkm stages::${workflowCommandData(message)}`);\n\t\tthrow error;\n\t}\n}\n\n/** `--github-output` outside a GitHub Actions step, which sets the file. */\nexport class GithubOutputNotSet extends GkmError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'gkm stages --github-output writes to the file GITHUB_OUTPUT names, and it is not set. Run it in a GitHub Actions step, or set GITHUB_OUTPUT to a file to write to.',\n\t\t);\n\t\tthis.name = 'GithubOutputNotSet';\n\t}\n}\n\n/** No `--event`, and no `GITHUB_EVENT_NAME` to take it from. */\nexport class GithubEventNotSet extends GkmError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'gkm stages --github-output plans for an event, and none was given. Pass --event (push, release, workflow_dispatch), or run it in a GitHub Actions step, which sets GITHUB_EVENT_NAME.',\n\t\t);\n\t\tthis.name = 'GithubEventNotSet';\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stages-Cw6urZyJ.cjs","names":["UndeclaredStage","GkmError","PROVIDER_KINDS","stageProvider","stageDnsDomains","loadWorkspaceSettings","appendFile","GkmError"],"sources":["../src/stages/plan.ts","../src/stages/index.ts"],"sourcesContent":["/**\n * Which stages a workflow run builds and deploys, from the event that started\n * it and the project's `stages`.\n *\n * The rules live here, in tested code, rather than in a workflow's YAML or in\n * the action that runs `gkm stages --github-output`: a project's deploy\n * workflow names no stage, and what it does for each event is decided by the\n * CLI the project installed.\n *\n * | event | build | deploy |\n * | ------------------- | ------------------ | ------------------------------- |\n * | `push` | every deployed | deployed, less the protected |\n * | `release` | none | the protected |\n * | `workflow_dispatch` | none | the one stage named |\n * | anything else | none | none |\n *\n * A push builds every deployed stage, protected ones included, so a release\n * deploys images built from the very commit its tag names; a release and a\n * manual run deploy what a push already built.\n */\n\nimport { GkmError } from '../errors';\nimport { UndeclaredStage } from '../workspace/stages.js';\nimport type { StagesConfig } from '../workspace/types.js';\n\nexport interface StagePlan {\n\t/** The stages whose images this run builds and pushes. */\n\tbuild: string[];\n\t/** The stages this run deploys. */\n\tdeploy: string[];\n}\n\nexport interface PlanInput {\n\t/** The GitHub event name: `push`, `release`, `workflow_dispatch`, … */\n\tevent: string;\n\t/** The stage a `workflow_dispatch` names. */\n\tstage?: string;\n}\n\nexport function planStages(stages: StagesConfig, input: PlanInput): StagePlan {\n\tconst kept = stages.protected ?? [];\n\n\tswitch (input.event) {\n\t\tcase 'push':\n\t\t\treturn {\n\t\t\t\tbuild: [...stages.deployed],\n\t\t\t\tdeploy: stages.deployed.filter((stage) => !kept.includes(stage)),\n\t\t\t};\n\t\tcase 'release':\n\t\t\treturn { build: [], deploy: [...kept] };\n\t\tcase 'workflow_dispatch': {\n\t\t\tconst stage = input.stage?.trim();\n\t\t\tif (!stage) throw new DispatchNamesNoStage(stages.deployed);\n\t\t\tif (!stages.deployed.includes(stage)) {\n\t\t\t\tthrow new UndeclaredStage(stage, stages.deployed);\n\t\t\t}\n\t\t\treturn { build: [], deploy: [stage] };\n\t\t}\n\t\tdefault:\n\t\t\treturn { build: [], deploy: [] };\n\t}\n}\n\n/**\n * A manual run with no stage. Refused rather than read as \"nothing to do\", so\n * a run started with the field left empty fails where it can be seen.\n */\nexport class DispatchNamesNoStage extends GkmError {\n\tconstructor(readonly deployed: readonly string[]) {\n\t\tsuper(\n\t\t\t`A manual run deploys one stage, and none was given. Run the workflow again with stage set to one of: ${deployed.join(', ') || 'nothing yet — gkm.config.ts deploys to no stage'}.`,\n\t\t);\n\t\tthis.name = 'DispatchNamesNoStage';\n\t}\n}\n","/**\n * `gkm stages` — the workspace's stages, as gkm.config.ts declares them.\n *\n * ```bash\n * gkm stages # a table\n * gkm stages --json # {\"local\":\"dev\",\"deployed\":[\"prod\"],\"protected\":[\"prod\"]}\n * gkm stages --github-output # a workflow run's build and deploy matrices\n * ```\n *\n * The config is read by the normal loader (and sandbox), so a workflow never\n * parses TypeScript to learn which stages exist. `--github-output` is what the\n * `geekmidas/toolbox/actions/stages` action runs: it writes the stages, and\n * which of them this run builds and deploys, to `$GITHUB_OUTPUT`.\n */\n\nimport { appendFile } from 'node:fs/promises';\nimport { stageDnsDomains } from '../compose/dns.js';\nimport { loadWorkspaceSettings } from '../config.js';\nimport { GkmError } from '../errors';\nimport { stageProvider } from '../providers/config.js';\nimport { PROVIDER_KINDS } from '../providers/types.js';\nimport type { NormalizedWorkspace, StagesConfig } from '../workspace/types.js';\nimport { planStages } from './plan.js';\n\nexport { DispatchNamesNoStage, type PlanInput, planStages } from './plan.js';\n\nexport interface StagesOptions {\n\t/** Print the stages as JSON. */\n\tjson?: boolean;\n\t/** Write the outputs a deploy workflow reads to `$GITHUB_OUTPUT`. */\n\tgithubOutput?: boolean;\n\t/** The event to plan for; defaults to `GITHUB_EVENT_NAME`. */\n\tevent?: string;\n\t/** The stage a `workflow_dispatch` names. */\n\tstage?: string;\n}\n\nexport interface StagesDeps {\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\t/** Where lines go; stdout by default. */\n\tlog?: (line: string) => void;\n}\n\n/** The stages, as `gkm stages --json` prints them. */\nexport interface StagesJson {\n\tlocal: string;\n\tdeployed: string[];\n\tprotected: string[];\n}\n\nexport function stagesJson(stages: StagesConfig): StagesJson {\n\treturn {\n\t\tlocal: stages.local,\n\t\tdeployed: [...stages.deployed],\n\t\tprotected: [...(stages.protected ?? [])],\n\t};\n}\n\n/**\n * The region of the workspace's AWS secrets store — `ssm` or\n * `secrets-manager` — or `''` when its deployed stages keep their secrets\n * anywhere else. A job assumes the stage's AWS role only when this is set.\n */\nexport function awsSecretsRegion(workspace: NormalizedWorkspace): string {\n\tconst store = workspace.secrets?.store;\n\tif (typeof store !== 'object' || store === null) return '';\n\tif (store.provider === 'ssm' || store.provider === 'secrets-manager') {\n\t\treturn store.region;\n\t}\n\treturn '';\n}\n\n/**\n * The deployed stages with resources the deploy creates — a provider under\n * `deploy.<kind>.<stage>`, or a domain under a `dns` entry whose provider\n * writes records — and secrets a CI runner can reach (an AWS store): a\n * compose deploy workflow creates their resources on the runner, with the\n * stage's role and DNS token, rather than on the server.\n */\nexport function resourceStages(workspace: NormalizedWorkspace): string[] {\n\tif (!awsSecretsRegion(workspace)) return [];\n\treturn workspace.stages.deployed.filter(\n\t\t(stage) =>\n\t\t\tPROVIDER_KINDS.some(\n\t\t\t\t(kind) => stageProvider(workspace, kind, stage).mode === 'provider',\n\t\t\t) ||\n\t\t\tstageDnsDomains(stage, workspace.domains, workspace.dns).some(\n\t\t\t\t({ config }) => config.provider !== 'manual',\n\t\t\t),\n\t);\n}\n\n/**\n * Every output the stages action sets, each a string `fromJSON()` reads, for\n * one workflow run.\n */\nexport function githubOutputs(\n\tworkspace: NormalizedWorkspace,\n\tinput: { event: string; stage?: string },\n): Record<string, string> {\n\tconst stages = stagesJson(workspace.stages);\n\tconst plan = planStages(workspace.stages, input);\n\n\treturn {\n\t\tlocal: JSON.stringify(stages.local),\n\t\tdeployed: JSON.stringify(stages.deployed),\n\t\tprotected: JSON.stringify(stages.protected),\n\t\tbuild: JSON.stringify(plan.build),\n\t\tdeploy: JSON.stringify(plan.deploy),\n\t\t// A matrix over an empty list is an error on GitHub, so a job over one\n\t\t// is skipped on these instead.\n\t\t'has-build': String(plan.build.length > 0),\n\t\t'has-deploy': String(plan.deploy.length > 0),\n\t\t'aws-region': awsSecretsRegion(workspace),\n\t\tresources: JSON.stringify(resourceStages(workspace)),\n\t};\n}\n\n/** `name=value` lines, as `$GITHUB_OUTPUT` takes single-line values. */\nexport function formatGithubOutputs(outputs: Record<string, string>): string {\n\treturn Object.entries(outputs)\n\t\t.map(([name, value]) => `${name}=${value}\\n`)\n\t\t.join('');\n}\n\n/** A message as a workflow command's data: GitHub reads `%`, CR and LF escaped. */\nfunction workflowCommandData(message: string): string {\n\treturn message\n\t\t.replaceAll('%', '%25')\n\t\t.replaceAll('\\r', '%0D')\n\t\t.replaceAll('\\n', '%0A');\n}\n\nfunction table(stages: StagesJson): string {\n\tconst rows: [string, string][] = [\n\t\t['STAGE', 'KIND'],\n\t\t[stages.local, 'local'],\n\t\t...stages.deployed.map((name): [string, string] => [\n\t\t\tname,\n\t\t\tstages.protected.includes(name) ? 'deployed, protected' : 'deployed',\n\t\t]),\n\t];\n\tconst width = Math.max(...rows.map(([name]) => name.length));\n\treturn rows\n\t\t.map(([name, kind]) => `${name.padEnd(width)} ${kind}`)\n\t\t.join('\\n');\n}\n\nexport async function stagesCommand(\n\toptions: StagesOptions,\n\tdeps: StagesDeps = {},\n): Promise<void> {\n\tconst env = deps.env ?? process.env;\n\tconst log = deps.log ?? ((line: string) => console.log(line));\n\n\tif (!options.githubOutput) {\n\t\tconst workspace = await loadWorkspaceSettings(deps.cwd);\n\t\tconst stages = stagesJson(workspace.stages);\n\t\tlog(options.json ? JSON.stringify(stages) : table(stages));\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst file = env.GITHUB_OUTPUT;\n\t\tif (!file) throw new GithubOutputNotSet();\n\n\t\tconst workspace = await loadWorkspaceSettings(deps.cwd);\n\t\tconst event = options.event || env.GITHUB_EVENT_NAME;\n\t\tif (!event) throw new GithubEventNotSet();\n\n\t\tconst outputs = githubOutputs(workspace, {\n\t\t\tevent,\n\t\t\t...(options.stage ? { stage: options.stage } : {}),\n\t\t});\n\t\tawait appendFile(file, formatGithubOutputs(outputs));\n\n\t\tlog(`${event}: build ${outputs.build}, deploy ${outputs.deploy}`);\n\t} catch (error) {\n\t\t// Annotated on the run, where whoever started it looks first.\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tlog(`::error title=gkm stages::${workflowCommandData(message)}`);\n\t\tthrow error;\n\t}\n}\n\n/** `--github-output` outside a GitHub Actions step, which sets the file. */\nexport class GithubOutputNotSet extends GkmError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'gkm stages --github-output writes to the file GITHUB_OUTPUT names, and it is not set. Run it in a GitHub Actions step, or set GITHUB_OUTPUT to a file to write to.',\n\t\t);\n\t\tthis.name = 'GithubOutputNotSet';\n\t}\n}\n\n/** No `--event`, and no `GITHUB_EVENT_NAME` to take it from. */\nexport class GithubEventNotSet extends GkmError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t'gkm stages --github-output plans for an event, and none was given. Pass --event (push, release, workflow_dispatch), or run it in a GitHub Actions step, which sets GITHUB_EVENT_NAME.',\n\t\t);\n\t\tthis.name = 'GithubEventNotSet';\n\t}\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_define = require("../define-crmMcXFS.cjs");
3
- const require_resolve = require("../resolve-CFEOtRsl.cjs");
3
+ const require_resolve = require("../resolve-BDatNOoG.cjs");
4
4
  const require_provider = require("../provider-BqpjG9QM.cjs");
5
5
  exports.DeployTargetNotYetSupported = require_define.DeployTargetNotYetSupported;
6
6
  exports.InvalidTargetOptions = require_resolve.InvalidTargetOptions;
@@ -1,5 +1,5 @@
1
- import { $ as TargetOptions, G as DeployPhaseContext, J as DeployTarget, K as DeployRuntime, Ot as StageSecrets, Q as TargetEvent, St as StateStore, U as AnyDeployTarget, W as DeployFailure, X as DeployTargetEntry, Y as DeployTargetCapabilities, Z as DeployTargetLogger, at as DeployPhase, ct as AppDeployResult, dt as Credential, et as TargetOptionsIssue, ft as CredentialKind, ht as CredentialRequest, it as DeployEventType, kt as DeployIdentity, lt as DeployResult, mt as CredentialProvider, nt as DeployEvent, ot as ResourceChange, pt as CredentialKinds, q as DeploySecrets, rt as DeployEventError, st as ResourceVia, tt as TargetOptionsSchema, ut as AwsCredential } from "../types-DXyaSmqu.cjs";
2
- import { a as TargetRuntimeMismatch, c as DeployTargetNotYetSupported, i as TargetPackageInvalid, l as UnknownDeployTarget, n as InvalidTargetOptions, o as ProviderRemoved, r as TargetEntryInvalid, s as TargetPackageNotFound, t as TargetRuntimeUndeclared } from "../runtime-VktAo_8B.cjs";
1
+ import { $ as TargetOptions, G as DeployPhaseContext, J as DeployTarget, K as DeployRuntime, Ot as StageSecrets, Q as TargetEvent, St as StateStore, U as AnyDeployTarget, W as DeployFailure, X as DeployTargetEntry, Y as DeployTargetCapabilities, Z as DeployTargetLogger, at as DeployPhase, ct as AppDeployResult, dt as Credential, et as TargetOptionsIssue, ft as CredentialKind, ht as CredentialRequest, it as DeployEventType, kt as DeployIdentity, lt as DeployResult, mt as CredentialProvider, nt as DeployEvent, ot as ResourceChange, pt as CredentialKinds, q as DeploySecrets, rt as DeployEventError, st as ResourceVia, tt as TargetOptionsSchema, ut as AwsCredential } from "../types-dipJRmKV.cjs";
2
+ import { a as TargetRuntimeMismatch, c as DeployTargetNotYetSupported, i as TargetPackageInvalid, l as UnknownDeployTarget, n as InvalidTargetOptions, o as ProviderRemoved, r as TargetEntryInvalid, s as TargetPackageNotFound, t as TargetRuntimeUndeclared } from "../runtime-DUQdM-mW.cjs";
3
3
  //#region src/target/define.d.ts
4
4
  /**
5
5
  * A deploy target, typed from what it is written with: the options from its
@@ -1,5 +1,5 @@
1
- import { $ as TargetOptions, G as DeployPhaseContext, J as DeployTarget, K as DeployRuntime, Ot as StageSecrets, Q as TargetEvent, St as StateStore, U as AnyDeployTarget, W as DeployFailure, X as DeployTargetEntry, Y as DeployTargetCapabilities, Z as DeployTargetLogger, at as DeployPhase, ct as AppDeployResult, dt as Credential, et as TargetOptionsIssue, ft as CredentialKind, ht as CredentialRequest, it as DeployEventType, kt as DeployIdentity, lt as DeployResult, mt as CredentialProvider, nt as DeployEvent, ot as ResourceChange, pt as CredentialKinds, q as DeploySecrets, rt as DeployEventError, st as ResourceVia, tt as TargetOptionsSchema, ut as AwsCredential } from "../types-DMoaFrjg.mjs";
2
- import { a as TargetRuntimeMismatch, c as DeployTargetNotYetSupported, i as TargetPackageInvalid, l as UnknownDeployTarget, n as InvalidTargetOptions, o as ProviderRemoved, r as TargetEntryInvalid, s as TargetPackageNotFound, t as TargetRuntimeUndeclared } from "../runtime-BRCq6dQ7.mjs";
1
+ import { $ as TargetOptions, G as DeployPhaseContext, J as DeployTarget, K as DeployRuntime, Ot as StageSecrets, Q as TargetEvent, St as StateStore, U as AnyDeployTarget, W as DeployFailure, X as DeployTargetEntry, Y as DeployTargetCapabilities, Z as DeployTargetLogger, at as DeployPhase, ct as AppDeployResult, dt as Credential, et as TargetOptionsIssue, ft as CredentialKind, ht as CredentialRequest, it as DeployEventType, kt as DeployIdentity, lt as DeployResult, mt as CredentialProvider, nt as DeployEvent, ot as ResourceChange, pt as CredentialKinds, q as DeploySecrets, rt as DeployEventError, st as ResourceVia, tt as TargetOptionsSchema, ut as AwsCredential } from "../types-bkqVscdN.mjs";
2
+ import { a as TargetRuntimeMismatch, c as DeployTargetNotYetSupported, i as TargetPackageInvalid, l as UnknownDeployTarget, n as InvalidTargetOptions, o as ProviderRemoved, r as TargetEntryInvalid, s as TargetPackageNotFound, t as TargetRuntimeUndeclared } from "../runtime-Vr6mleo2.mjs";
3
3
  //#region src/target/define.d.ts
4
4
  /**
5
5
  * A deploy target, typed from what it is written with: the options from its
@@ -1,4 +1,4 @@
1
1
  import { a as UnknownDeployTarget, i as DeployTargetNotYetSupported, n as isDeployTarget, t as defineTarget } from "../define-6poNqm5O.mjs";
2
- import { i as TargetRuntimeMismatch, l as TargetPackageNotFound, n as TargetEntryInvalid, r as TargetPackageInvalid, s as TargetRuntimeUndeclared, t as InvalidTargetOptions } from "../resolve-Dyd1S2wn.mjs";
2
+ import { i as TargetRuntimeMismatch, l as TargetPackageNotFound, n as TargetEntryInvalid, r as TargetPackageInvalid, s as TargetRuntimeUndeclared, t as InvalidTargetOptions } from "../resolve-CUne0qOm.mjs";
3
3
  import { t as ProviderRemoved } from "../provider-CEOKk8NS.mjs";
4
4
  export { DeployTargetNotYetSupported, InvalidTargetOptions, ProviderRemoved, TargetEntryInvalid, TargetPackageInvalid, TargetPackageNotFound, TargetRuntimeMismatch, TargetRuntimeUndeclared, UnknownDeployTarget, defineTarget, isDeployTarget };
@@ -1,5 +1,5 @@
1
1
  const require_errors = require("./errors-DMC4Umsb.cjs");
2
- const require_credentials = require("./credentials-D7XJypNd.cjs");
2
+ const require_credentials = require("./credentials-Zqr3QQYB.cjs");
3
3
  const require_discover = require("./discover-DPgu-ScS.cjs");
4
4
  const require_index = require("./index.cjs");
5
5
  //#region src/deploy/terminal.ts
@@ -82,4 +82,4 @@ function terminalCredentials(base = require_credentials.storedCredentials()) {
82
82
  //#endregion
83
83
  exports.terminalCredentials = terminalCredentials;
84
84
 
85
- //# sourceMappingURL=terminal-CkUYuAPd.cjs.map
85
+ //# sourceMappingURL=terminal-CPHuH4S1.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"terminal-CkUYuAPd.cjs","names":["output","GkmError","canPrompt","prompt","validateDokployToken","storeDokployCredentials","storedCredentials","chainCredentials"],"sources":["../src/deploy/terminal.ts"],"sourcesContent":["/**\n * The credentials `gkm deploy` can ask a person for. CLI layer only.\n *\n * `deploy()` asks its `CredentialProvider` and stops with `MissingCredential`\n * when the answer is nothing. At a terminal, `gkm deploy` would rather ask:\n * this provider reads the environment and the stored login first, and only\n * when both are empty prompts — and stores a Dokploy login it validated, so\n * the next deploy does not ask again. With no terminal it answers nothing, and\n * the deploy says what was missing instead of waiting on a prompt nobody sees.\n */\n\nimport { validateDokployToken } from '../auth';\nimport { storeDokployCredentials } from '../auth/credentials';\nimport { GkmError } from '../errors';\nimport { output } from '../output';\nimport { canPrompt, prompt } from '../prompt';\nimport {\n\ttype CredentialProvider,\n\ttype CredentialRequest,\n\tchainCredentials,\n\tstoredCredentials,\n} from './credentials';\n\nconst logger = output;\n\n/** What answers a deploy prompt without a terminal. */\nconst INSTEAD = 'Please configure manually.';\n\n/** The Dokploy URL typed at the prompt is not a URL. */\nexport class DokployEndpointInvalid extends GkmError {\n\tconstructor(readonly endpoint: string) {\n\t\tsuper('Invalid URL format');\n\t\tthis.name = 'DokployEndpointInvalid';\n\t}\n}\n\n/** Dokploy refused the token typed at the prompt; nothing was stored. */\nexport class DokployTokenRejected extends GkmError {\n\tconstructor(readonly endpoint: string) {\n\t\tsuper('Invalid credentials. Please check your token.');\n\t\tthis.name = 'DokployTokenRejected';\n\t}\n}\n\n/** Asks the person at the terminal for what nothing else supplied. */\nfunction asking(): CredentialProvider {\n\treturn {\n\t\tasync get(asked) {\n\t\t\tif (!canPrompt()) return undefined;\n\t\t\t// The union, so checking `kind` narrows it: `K` itself never is.\n\t\t\tconst request = asked as CredentialRequest;\n\n\t\t\tif (request.kind === 'dokploy') {\n\t\t\t\tlogger.log(\"\\n📋 Dokploy credentials not found. Let's set them up.\");\n\t\t\t\tconst endpoint = (\n\t\t\t\t\tawait prompt('Dokploy URL (e.g., https://dokploy.example.com): ', {\n\t\t\t\t\t\tinstead: INSTEAD,\n\t\t\t\t\t})\n\t\t\t\t).replace(/\\/$/, '');\n\n\t\t\t\ttry {\n\t\t\t\t\tnew URL(endpoint);\n\t\t\t\t} catch {\n\t\t\t\t\tthrow new DokployEndpointInvalid(endpoint);\n\t\t\t\t}\n\n\t\t\t\tlogger.log(`\\nGenerate a token at: ${endpoint}/settings/profile\\n`);\n\t\t\t\tconst token = await prompt('API Token: ', {\n\t\t\t\t\thidden: true,\n\t\t\t\t\tinstead: INSTEAD,\n\t\t\t\t});\n\n\t\t\t\tlogger.log('\\nValidating credentials...');\n\t\t\t\tif (!(await validateDokployToken(endpoint, token))) {\n\t\t\t\t\tthrow new DokployTokenRejected(endpoint);\n\t\t\t\t}\n\n\t\t\t\tawait storeDokployCredentials(token, endpoint);\n\t\t\t\tlogger.log('✓ Credentials saved');\n\t\t\t\treturn { endpoint, token } as never;\n\t\t\t}\n\n\t\t\t// AWS is a profile or a role, set up with the AWS CLI — not keys\n\t\t\t// typed into a deploy.\n\t\t\tif (request.kind !== 'registry') return undefined;\n\n\t\t\tlogger.log(\n\t\t\t\t` Dokploy has no registry for ${request.url}. Let's create one.`,\n\t\t\t);\n\t\t\tconst username = await prompt('Registry username: ', {\n\t\t\t\tinstead: INSTEAD,\n\t\t\t});\n\t\t\tconst password = await prompt('Registry password/token: ', {\n\t\t\t\thidden: true,\n\t\t\t\tinstead: INSTEAD,\n\t\t\t});\n\t\t\treturn { username, password } as never;\n\t\t},\n\t};\n}\n\n/**\n * The environment, then the stored login, then — at a terminal — the person\n * running the command.\n */\nexport function terminalCredentials(\n\tbase: CredentialProvider = storedCredentials(),\n): CredentialProvider {\n\treturn chainCredentials(base, asking());\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,MAAM,SAASA,iBAAAA;;AAGf,MAAM,UAAU;;AAGhB,IAAa,yBAAb,cAA4CC,eAAAA,SAAS;CAC/B;CAArB,YAAY,UAA2B;EACtC,MAAM,oBAAoB;EADN,KAAA,WAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,uBAAb,cAA0CA,eAAAA,SAAS;CAC7B;CAArB,YAAY,UAA2B;EACtC,MAAM,+CAA+C;EADjC,KAAA,WAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,SAAS,SAA6B;CACrC,OAAO,EACN,MAAM,IAAI,OAAO;EAChB,IAAI,CAACC,cAAAA,UAAU,GAAG,OAAO,KAAA;EAEzB,MAAM,UAAU;EAEhB,IAAI,QAAQ,SAAS,WAAW;GAC/B,OAAO,IAAI,wDAAwD;GACnE,MAAM,YACL,MAAMC,cAAAA,OAAO,qDAAqD,EACjE,SAAS,QACV,CAAC,EAAA,CACA,QAAQ,OAAO,EAAE;GAEnB,IAAI;IACH,IAAI,IAAI,QAAQ;GACjB,QAAQ;IACP,MAAM,IAAI,uBAAuB,QAAQ;GAC1C;GAEA,OAAO,IAAI,0BAA0B,SAAS,oBAAoB;GAClE,MAAM,QAAQ,MAAMA,cAAAA,OAAO,eAAe;IACzC,QAAQ;IACR,SAAS;GACV,CAAC;GAED,OAAO,IAAI,6BAA6B;GACxC,IAAI,CAAE,MAAMC,cAAAA,qBAAqB,UAAU,KAAK,GAC/C,MAAM,IAAI,qBAAqB,QAAQ;GAGxC,MAAMC,oBAAAA,wBAAwB,OAAO,QAAQ;GAC7C,OAAO,IAAI,qBAAqB;GAChC,OAAO;IAAE;IAAU;GAAM;EAC1B;EAIA,IAAI,QAAQ,SAAS,YAAY,OAAO,KAAA;EAExC,OAAO,IACN,kCAAkC,QAAQ,IAAI,oBAC/C;EAQA,OAAO;GAAE,UAAA,MAPcF,cAAAA,OAAO,uBAAuB,EACpD,SAAS,QACV,CAAC;GAKkB,UAAA,MAJIA,cAAAA,OAAO,6BAA6B;IAC1D,QAAQ;IACR,SAAS;GACV,CAAC;EAC2B;CAC7B,EACD;AACD;;;;;AAMA,SAAgB,oBACf,OAA2BG,oBAAAA,kBAAkB,GACxB;CACrB,OAAOC,oBAAAA,iBAAiB,MAAM,OAAO,CAAC;AACvC"}
1
+ {"version":3,"file":"terminal-CPHuH4S1.cjs","names":["output","GkmError","canPrompt","prompt","validateDokployToken","storeDokployCredentials","storedCredentials","chainCredentials"],"sources":["../src/deploy/terminal.ts"],"sourcesContent":["/**\n * The credentials `gkm deploy` can ask a person for. CLI layer only.\n *\n * `deploy()` asks its `CredentialProvider` and stops with `MissingCredential`\n * when the answer is nothing. At a terminal, `gkm deploy` would rather ask:\n * this provider reads the environment and the stored login first, and only\n * when both are empty prompts — and stores a Dokploy login it validated, so\n * the next deploy does not ask again. With no terminal it answers nothing, and\n * the deploy says what was missing instead of waiting on a prompt nobody sees.\n */\n\nimport { validateDokployToken } from '../auth';\nimport { storeDokployCredentials } from '../auth/credentials';\nimport { GkmError } from '../errors';\nimport { output } from '../output';\nimport { canPrompt, prompt } from '../prompt';\nimport {\n\ttype CredentialProvider,\n\ttype CredentialRequest,\n\tchainCredentials,\n\tstoredCredentials,\n} from './credentials';\n\nconst logger = output;\n\n/** What answers a deploy prompt without a terminal. */\nconst INSTEAD = 'Please configure manually.';\n\n/** The Dokploy URL typed at the prompt is not a URL. */\nexport class DokployEndpointInvalid extends GkmError {\n\tconstructor(readonly endpoint: string) {\n\t\tsuper('Invalid URL format');\n\t\tthis.name = 'DokployEndpointInvalid';\n\t}\n}\n\n/** Dokploy refused the token typed at the prompt; nothing was stored. */\nexport class DokployTokenRejected extends GkmError {\n\tconstructor(readonly endpoint: string) {\n\t\tsuper('Invalid credentials. Please check your token.');\n\t\tthis.name = 'DokployTokenRejected';\n\t}\n}\n\n/** Asks the person at the terminal for what nothing else supplied. */\nfunction asking(): CredentialProvider {\n\treturn {\n\t\tasync get(asked) {\n\t\t\tif (!canPrompt()) return undefined;\n\t\t\t// The union, so checking `kind` narrows it: `K` itself never is.\n\t\t\tconst request = asked as CredentialRequest;\n\n\t\t\tif (request.kind === 'dokploy') {\n\t\t\t\tlogger.log(\"\\n📋 Dokploy credentials not found. Let's set them up.\");\n\t\t\t\tconst endpoint = (\n\t\t\t\t\tawait prompt('Dokploy URL (e.g., https://dokploy.example.com): ', {\n\t\t\t\t\t\tinstead: INSTEAD,\n\t\t\t\t\t})\n\t\t\t\t).replace(/\\/$/, '');\n\n\t\t\t\ttry {\n\t\t\t\t\tnew URL(endpoint);\n\t\t\t\t} catch {\n\t\t\t\t\tthrow new DokployEndpointInvalid(endpoint);\n\t\t\t\t}\n\n\t\t\t\tlogger.log(`\\nGenerate a token at: ${endpoint}/settings/profile\\n`);\n\t\t\t\tconst token = await prompt('API Token: ', {\n\t\t\t\t\thidden: true,\n\t\t\t\t\tinstead: INSTEAD,\n\t\t\t\t});\n\n\t\t\t\tlogger.log('\\nValidating credentials...');\n\t\t\t\tif (!(await validateDokployToken(endpoint, token))) {\n\t\t\t\t\tthrow new DokployTokenRejected(endpoint);\n\t\t\t\t}\n\n\t\t\t\tawait storeDokployCredentials(token, endpoint);\n\t\t\t\tlogger.log('✓ Credentials saved');\n\t\t\t\treturn { endpoint, token } as never;\n\t\t\t}\n\n\t\t\t// AWS is a profile or a role, set up with the AWS CLI — not keys\n\t\t\t// typed into a deploy.\n\t\t\tif (request.kind !== 'registry') return undefined;\n\n\t\t\tlogger.log(\n\t\t\t\t` Dokploy has no registry for ${request.url}. Let's create one.`,\n\t\t\t);\n\t\t\tconst username = await prompt('Registry username: ', {\n\t\t\t\tinstead: INSTEAD,\n\t\t\t});\n\t\t\tconst password = await prompt('Registry password/token: ', {\n\t\t\t\thidden: true,\n\t\t\t\tinstead: INSTEAD,\n\t\t\t});\n\t\t\treturn { username, password } as never;\n\t\t},\n\t};\n}\n\n/**\n * The environment, then the stored login, then — at a terminal — the person\n * running the command.\n */\nexport function terminalCredentials(\n\tbase: CredentialProvider = storedCredentials(),\n): CredentialProvider {\n\treturn chainCredentials(base, asking());\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,MAAM,SAASA,iBAAAA;;AAGf,MAAM,UAAU;;AAGhB,IAAa,yBAAb,cAA4CC,eAAAA,SAAS;CAC/B;CAArB,YAAY,UAA2B;EACtC,MAAM,oBAAoB;EADN,KAAA,WAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,uBAAb,cAA0CA,eAAAA,SAAS;CAC7B;CAArB,YAAY,UAA2B;EACtC,MAAM,+CAA+C;EADjC,KAAA,WAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,SAAS,SAA6B;CACrC,OAAO,EACN,MAAM,IAAI,OAAO;EAChB,IAAI,CAACC,cAAAA,UAAU,GAAG,OAAO,KAAA;EAEzB,MAAM,UAAU;EAEhB,IAAI,QAAQ,SAAS,WAAW;GAC/B,OAAO,IAAI,wDAAwD;GACnE,MAAM,YACL,MAAMC,cAAAA,OAAO,qDAAqD,EACjE,SAAS,QACV,CAAC,EAAA,CACA,QAAQ,OAAO,EAAE;GAEnB,IAAI;IACH,IAAI,IAAI,QAAQ;GACjB,QAAQ;IACP,MAAM,IAAI,uBAAuB,QAAQ;GAC1C;GAEA,OAAO,IAAI,0BAA0B,SAAS,oBAAoB;GAClE,MAAM,QAAQ,MAAMA,cAAAA,OAAO,eAAe;IACzC,QAAQ;IACR,SAAS;GACV,CAAC;GAED,OAAO,IAAI,6BAA6B;GACxC,IAAI,CAAE,MAAMC,cAAAA,qBAAqB,UAAU,KAAK,GAC/C,MAAM,IAAI,qBAAqB,QAAQ;GAGxC,MAAMC,oBAAAA,wBAAwB,OAAO,QAAQ;GAC7C,OAAO,IAAI,qBAAqB;GAChC,OAAO;IAAE;IAAU;GAAM;EAC1B;EAIA,IAAI,QAAQ,SAAS,YAAY,OAAO,KAAA;EAExC,OAAO,IACN,kCAAkC,QAAQ,IAAI,oBAC/C;EAQA,OAAO;GAAE,UAAA,MAPcF,cAAAA,OAAO,uBAAuB,EACpD,SAAS,QACV,CAAC;GAKkB,UAAA,MAJIA,cAAAA,OAAO,6BAA6B;IAC1D,QAAQ;IACR,SAAS;GACV,CAAC;EAC2B;CAC7B,EACD;AACD;;;;;AAMA,SAAgB,oBACf,OAA2BG,oBAAAA,kBAAkB,GACxB;CACrB,OAAOC,oBAAAA,iBAAiB,MAAM,OAAO,CAAC;AACvC"}
@@ -1,5 +1,5 @@
1
1
  import { t as GkmError } from "./errors-D8Gwp5kU.mjs";
2
- import { _ as storeDokployCredentials, n as chainCredentials, r as storedCredentials } from "./credentials-DpfnUvIR.mjs";
2
+ import { f as storeDokployCredentials, n as chainCredentials, r as storedCredentials } from "./credentials-B5N5yKk6.mjs";
3
3
  import { d as output } from "./discover-qjFapetL.mjs";
4
4
  import { a as validateDokployToken, o as canPrompt, s as prompt } from "./index.mjs";
5
5
  //#region src/deploy/terminal.ts
@@ -82,4 +82,4 @@ function terminalCredentials(base = storedCredentials()) {
82
82
  //#endregion
83
83
  export { terminalCredentials };
84
84
 
85
- //# sourceMappingURL=terminal-DAHs2Zko.mjs.map
85
+ //# sourceMappingURL=terminal-iNmAXXjs.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"terminal-DAHs2Zko.mjs","names":[],"sources":["../src/deploy/terminal.ts"],"sourcesContent":["/**\n * The credentials `gkm deploy` can ask a person for. CLI layer only.\n *\n * `deploy()` asks its `CredentialProvider` and stops with `MissingCredential`\n * when the answer is nothing. At a terminal, `gkm deploy` would rather ask:\n * this provider reads the environment and the stored login first, and only\n * when both are empty prompts — and stores a Dokploy login it validated, so\n * the next deploy does not ask again. With no terminal it answers nothing, and\n * the deploy says what was missing instead of waiting on a prompt nobody sees.\n */\n\nimport { validateDokployToken } from '../auth';\nimport { storeDokployCredentials } from '../auth/credentials';\nimport { GkmError } from '../errors';\nimport { output } from '../output';\nimport { canPrompt, prompt } from '../prompt';\nimport {\n\ttype CredentialProvider,\n\ttype CredentialRequest,\n\tchainCredentials,\n\tstoredCredentials,\n} from './credentials';\n\nconst logger = output;\n\n/** What answers a deploy prompt without a terminal. */\nconst INSTEAD = 'Please configure manually.';\n\n/** The Dokploy URL typed at the prompt is not a URL. */\nexport class DokployEndpointInvalid extends GkmError {\n\tconstructor(readonly endpoint: string) {\n\t\tsuper('Invalid URL format');\n\t\tthis.name = 'DokployEndpointInvalid';\n\t}\n}\n\n/** Dokploy refused the token typed at the prompt; nothing was stored. */\nexport class DokployTokenRejected extends GkmError {\n\tconstructor(readonly endpoint: string) {\n\t\tsuper('Invalid credentials. Please check your token.');\n\t\tthis.name = 'DokployTokenRejected';\n\t}\n}\n\n/** Asks the person at the terminal for what nothing else supplied. */\nfunction asking(): CredentialProvider {\n\treturn {\n\t\tasync get(asked) {\n\t\t\tif (!canPrompt()) return undefined;\n\t\t\t// The union, so checking `kind` narrows it: `K` itself never is.\n\t\t\tconst request = asked as CredentialRequest;\n\n\t\t\tif (request.kind === 'dokploy') {\n\t\t\t\tlogger.log(\"\\n📋 Dokploy credentials not found. Let's set them up.\");\n\t\t\t\tconst endpoint = (\n\t\t\t\t\tawait prompt('Dokploy URL (e.g., https://dokploy.example.com): ', {\n\t\t\t\t\t\tinstead: INSTEAD,\n\t\t\t\t\t})\n\t\t\t\t).replace(/\\/$/, '');\n\n\t\t\t\ttry {\n\t\t\t\t\tnew URL(endpoint);\n\t\t\t\t} catch {\n\t\t\t\t\tthrow new DokployEndpointInvalid(endpoint);\n\t\t\t\t}\n\n\t\t\t\tlogger.log(`\\nGenerate a token at: ${endpoint}/settings/profile\\n`);\n\t\t\t\tconst token = await prompt('API Token: ', {\n\t\t\t\t\thidden: true,\n\t\t\t\t\tinstead: INSTEAD,\n\t\t\t\t});\n\n\t\t\t\tlogger.log('\\nValidating credentials...');\n\t\t\t\tif (!(await validateDokployToken(endpoint, token))) {\n\t\t\t\t\tthrow new DokployTokenRejected(endpoint);\n\t\t\t\t}\n\n\t\t\t\tawait storeDokployCredentials(token, endpoint);\n\t\t\t\tlogger.log('✓ Credentials saved');\n\t\t\t\treturn { endpoint, token } as never;\n\t\t\t}\n\n\t\t\t// AWS is a profile or a role, set up with the AWS CLI — not keys\n\t\t\t// typed into a deploy.\n\t\t\tif (request.kind !== 'registry') return undefined;\n\n\t\t\tlogger.log(\n\t\t\t\t` Dokploy has no registry for ${request.url}. Let's create one.`,\n\t\t\t);\n\t\t\tconst username = await prompt('Registry username: ', {\n\t\t\t\tinstead: INSTEAD,\n\t\t\t});\n\t\t\tconst password = await prompt('Registry password/token: ', {\n\t\t\t\thidden: true,\n\t\t\t\tinstead: INSTEAD,\n\t\t\t});\n\t\t\treturn { username, password } as never;\n\t\t},\n\t};\n}\n\n/**\n * The environment, then the stored login, then — at a terminal — the person\n * running the command.\n */\nexport function terminalCredentials(\n\tbase: CredentialProvider = storedCredentials(),\n): CredentialProvider {\n\treturn chainCredentials(base, asking());\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,MAAM,SAAS;;AAGf,MAAM,UAAU;;AAGhB,IAAa,yBAAb,cAA4C,SAAS;CAC/B;CAArB,YAAY,UAA2B;EACtC,MAAM,oBAAoB;EADN,KAAA,WAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,uBAAb,cAA0C,SAAS;CAC7B;CAArB,YAAY,UAA2B;EACtC,MAAM,+CAA+C;EADjC,KAAA,WAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,SAAS,SAA6B;CACrC,OAAO,EACN,MAAM,IAAI,OAAO;EAChB,IAAI,CAAC,UAAU,GAAG,OAAO,KAAA;EAEzB,MAAM,UAAU;EAEhB,IAAI,QAAQ,SAAS,WAAW;GAC/B,OAAO,IAAI,wDAAwD;GACnE,MAAM,YACL,MAAM,OAAO,qDAAqD,EACjE,SAAS,QACV,CAAC,EAAA,CACA,QAAQ,OAAO,EAAE;GAEnB,IAAI;IACH,IAAI,IAAI,QAAQ;GACjB,QAAQ;IACP,MAAM,IAAI,uBAAuB,QAAQ;GAC1C;GAEA,OAAO,IAAI,0BAA0B,SAAS,oBAAoB;GAClE,MAAM,QAAQ,MAAM,OAAO,eAAe;IACzC,QAAQ;IACR,SAAS;GACV,CAAC;GAED,OAAO,IAAI,6BAA6B;GACxC,IAAI,CAAE,MAAM,qBAAqB,UAAU,KAAK,GAC/C,MAAM,IAAI,qBAAqB,QAAQ;GAGxC,MAAM,wBAAwB,OAAO,QAAQ;GAC7C,OAAO,IAAI,qBAAqB;GAChC,OAAO;IAAE;IAAU;GAAM;EAC1B;EAIA,IAAI,QAAQ,SAAS,YAAY,OAAO,KAAA;EAExC,OAAO,IACN,kCAAkC,QAAQ,IAAI,oBAC/C;EAQA,OAAO;GAAE,UAAA,MAPc,OAAO,uBAAuB,EACpD,SAAS,QACV,CAAC;GAKkB,UAAA,MAJI,OAAO,6BAA6B;IAC1D,QAAQ;IACR,SAAS;GACV,CAAC;EAC2B;CAC7B,EACD;AACD;;;;;AAMA,SAAgB,oBACf,OAA2B,kBAAkB,GACxB;CACrB,OAAO,iBAAiB,MAAM,OAAO,CAAC;AACvC"}
1
+ {"version":3,"file":"terminal-iNmAXXjs.mjs","names":[],"sources":["../src/deploy/terminal.ts"],"sourcesContent":["/**\n * The credentials `gkm deploy` can ask a person for. CLI layer only.\n *\n * `deploy()` asks its `CredentialProvider` and stops with `MissingCredential`\n * when the answer is nothing. At a terminal, `gkm deploy` would rather ask:\n * this provider reads the environment and the stored login first, and only\n * when both are empty prompts — and stores a Dokploy login it validated, so\n * the next deploy does not ask again. With no terminal it answers nothing, and\n * the deploy says what was missing instead of waiting on a prompt nobody sees.\n */\n\nimport { validateDokployToken } from '../auth';\nimport { storeDokployCredentials } from '../auth/credentials';\nimport { GkmError } from '../errors';\nimport { output } from '../output';\nimport { canPrompt, prompt } from '../prompt';\nimport {\n\ttype CredentialProvider,\n\ttype CredentialRequest,\n\tchainCredentials,\n\tstoredCredentials,\n} from './credentials';\n\nconst logger = output;\n\n/** What answers a deploy prompt without a terminal. */\nconst INSTEAD = 'Please configure manually.';\n\n/** The Dokploy URL typed at the prompt is not a URL. */\nexport class DokployEndpointInvalid extends GkmError {\n\tconstructor(readonly endpoint: string) {\n\t\tsuper('Invalid URL format');\n\t\tthis.name = 'DokployEndpointInvalid';\n\t}\n}\n\n/** Dokploy refused the token typed at the prompt; nothing was stored. */\nexport class DokployTokenRejected extends GkmError {\n\tconstructor(readonly endpoint: string) {\n\t\tsuper('Invalid credentials. Please check your token.');\n\t\tthis.name = 'DokployTokenRejected';\n\t}\n}\n\n/** Asks the person at the terminal for what nothing else supplied. */\nfunction asking(): CredentialProvider {\n\treturn {\n\t\tasync get(asked) {\n\t\t\tif (!canPrompt()) return undefined;\n\t\t\t// The union, so checking `kind` narrows it: `K` itself never is.\n\t\t\tconst request = asked as CredentialRequest;\n\n\t\t\tif (request.kind === 'dokploy') {\n\t\t\t\tlogger.log(\"\\n📋 Dokploy credentials not found. Let's set them up.\");\n\t\t\t\tconst endpoint = (\n\t\t\t\t\tawait prompt('Dokploy URL (e.g., https://dokploy.example.com): ', {\n\t\t\t\t\t\tinstead: INSTEAD,\n\t\t\t\t\t})\n\t\t\t\t).replace(/\\/$/, '');\n\n\t\t\t\ttry {\n\t\t\t\t\tnew URL(endpoint);\n\t\t\t\t} catch {\n\t\t\t\t\tthrow new DokployEndpointInvalid(endpoint);\n\t\t\t\t}\n\n\t\t\t\tlogger.log(`\\nGenerate a token at: ${endpoint}/settings/profile\\n`);\n\t\t\t\tconst token = await prompt('API Token: ', {\n\t\t\t\t\thidden: true,\n\t\t\t\t\tinstead: INSTEAD,\n\t\t\t\t});\n\n\t\t\t\tlogger.log('\\nValidating credentials...');\n\t\t\t\tif (!(await validateDokployToken(endpoint, token))) {\n\t\t\t\t\tthrow new DokployTokenRejected(endpoint);\n\t\t\t\t}\n\n\t\t\t\tawait storeDokployCredentials(token, endpoint);\n\t\t\t\tlogger.log('✓ Credentials saved');\n\t\t\t\treturn { endpoint, token } as never;\n\t\t\t}\n\n\t\t\t// AWS is a profile or a role, set up with the AWS CLI — not keys\n\t\t\t// typed into a deploy.\n\t\t\tif (request.kind !== 'registry') return undefined;\n\n\t\t\tlogger.log(\n\t\t\t\t` Dokploy has no registry for ${request.url}. Let's create one.`,\n\t\t\t);\n\t\t\tconst username = await prompt('Registry username: ', {\n\t\t\t\tinstead: INSTEAD,\n\t\t\t});\n\t\t\tconst password = await prompt('Registry password/token: ', {\n\t\t\t\thidden: true,\n\t\t\t\tinstead: INSTEAD,\n\t\t\t});\n\t\t\treturn { username, password } as never;\n\t\t},\n\t};\n}\n\n/**\n * The environment, then the stored login, then — at a terminal — the person\n * running the command.\n */\nexport function terminalCredentials(\n\tbase: CredentialProvider = storedCredentials(),\n): CredentialProvider {\n\treturn chainCredentials(base, asking());\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,MAAM,SAAS;;AAGf,MAAM,UAAU;;AAGhB,IAAa,yBAAb,cAA4C,SAAS;CAC/B;CAArB,YAAY,UAA2B;EACtC,MAAM,oBAAoB;EADN,KAAA,WAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,uBAAb,cAA0C,SAAS;CAC7B;CAArB,YAAY,UAA2B;EACtC,MAAM,+CAA+C;EADjC,KAAA,WAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,SAAS,SAA6B;CACrC,OAAO,EACN,MAAM,IAAI,OAAO;EAChB,IAAI,CAAC,UAAU,GAAG,OAAO,KAAA;EAEzB,MAAM,UAAU;EAEhB,IAAI,QAAQ,SAAS,WAAW;GAC/B,OAAO,IAAI,wDAAwD;GACnE,MAAM,YACL,MAAM,OAAO,qDAAqD,EACjE,SAAS,QACV,CAAC,EAAA,CACA,QAAQ,OAAO,EAAE;GAEnB,IAAI;IACH,IAAI,IAAI,QAAQ;GACjB,QAAQ;IACP,MAAM,IAAI,uBAAuB,QAAQ;GAC1C;GAEA,OAAO,IAAI,0BAA0B,SAAS,oBAAoB;GAClE,MAAM,QAAQ,MAAM,OAAO,eAAe;IACzC,QAAQ;IACR,SAAS;GACV,CAAC;GAED,OAAO,IAAI,6BAA6B;GACxC,IAAI,CAAE,MAAM,qBAAqB,UAAU,KAAK,GAC/C,MAAM,IAAI,qBAAqB,QAAQ;GAGxC,MAAM,wBAAwB,OAAO,QAAQ;GAC7C,OAAO,IAAI,qBAAqB;GAChC,OAAO;IAAE;IAAU;GAAM;EAC1B;EAIA,IAAI,QAAQ,SAAS,YAAY,OAAO,KAAA;EAExC,OAAO,IACN,kCAAkC,QAAQ,IAAI,oBAC/C;EAQA,OAAO;GAAE,UAAA,MAPc,OAAO,uBAAuB,EACpD,SAAS,QACV,CAAC;GAKkB,UAAA,MAJI,OAAO,6BAA6B;IAC1D,QAAQ;IACR,SAAS;GACV,CAAC;EAC2B;CAC7B,EACD;AACD;;;;;AAMA,SAAgB,oBACf,OAA2B,kBAAkB,GACxB;CACrB,OAAO,iBAAiB,MAAM,OAAO,CAAC;AACvC"}
@@ -1179,10 +1179,19 @@ interface DeployTarget<Options = undefined, Run = unknown> {
1179
1179
  readonly stage: string;
1180
1180
  }): Promise<string>;
1181
1181
  /**
1182
- * Everything the deploy needs, checked before anything changes: the
1183
- * config, the apps, credentials, the stage's secrets.
1182
+ * What the run is — the apps, the images, what each runs with — checked
1183
+ * before anything changes. A build-only run calls it too, so it checks
1184
+ * what building needs; what only a deploy needs is `ready`'s.
1184
1185
  */
1185
1186
  validate(ctx: DeployPhaseContext<Options>): Promise<Run>;
1187
+ /**
1188
+ * What only this target checks before a deploy changes anything — compose's
1189
+ * server address and its hosts' DNS. Run after `validate` and the stage's
1190
+ * own readiness check (every key it needs, after its providers wrote
1191
+ * theirs), on a deploy and its dry run. A build-only run never calls it:
1192
+ * an image needs none of it.
1193
+ */
1194
+ ready?(ctx: DeployPhaseContext<Options>, run: Run): Promise<void>;
1186
1195
  /** A dry run: emit `resource.planned` for what a real run would do. */
1187
1196
  plan(ctx: DeployPhaseContext<Options>, run: Run): Promise<void>;
1188
1197
  /**
@@ -7522,4 +7531,4 @@ interface GkmConfig {
7522
7531
  }
7523
7532
  //#endregion
7524
7533
  export { TargetOptions as $, BackendFramework as A, deployIdentity as At, isPhase2DeployTarget as B, SecretsConfig as C, StateVersionConflict as Ct, WorkspaceConfig as D, LocalActor as Dt, StageTelemetryConfig as E, GithubActor as Et, SUPPORTED_DEPLOY_TARGETS as F, DeployPhaseContext as G, validateWorkspaceConfig as H, WorkspaceConfigSchema as I, DeployTarget as J, DeployRuntime as K, formatValidationErrors as L, FrontendFramework as M, MobileFramework as N, WorkspaceInput as O, StageSecrets as Ot, PHASE_2_DEPLOY_TARGETS as P, TargetEvent as Q, getDeployTargetError as R, OtlpTelemetryConfig as S, StateStore as St, SharedConfig as T, Actor as Tt, AnyDeployTarget as U, safeValidateWorkspaceConfig as V, DeployFailure as W, DeployTargetEntry as X, DeployTargetCapabilities as Y, DeployTargetLogger as Z, InferredWorkspaceConfig as _, StoredCredentialsOptions as _t, Routes as a, DeployPhase as at, NormalizedAppConfig as b, LocalStateInCi as bt, AppInput as c, AppDeployResult as ct, ConstrainedApps as d, Credential as dt, TargetOptionsIssue as et, DeployConfig as f, CredentialKind as ft, InferAppNames as g, MissingCredential as gt, DokployWorkspaceConfig as h, CredentialRequest as ht, OpenApiConfig as i, DeployEventType as it, Framework as j, GkmError as jt, isWorkspaceConfig as k, DeployIdentity as kt, AppsRecord as l, DeployResult as lt, DevConfig as m, CredentialProvider as mt, EmailBackend as n, DeployEvent as nt, AppConfig as o, ResourceChange as ot, DeployTargetName as p, CredentialKinds as pt, DeploySecrets as q, GkmConfig as r, DeployEventError as rt, AppConfigInput as s, ResourceVia as st, CacheBackend as t, TargetOptionsSchema as tt, ComposeWorkspaceConfig as u, AwsCredential as ut, LoadedConfig as v, chainCredentials as vt, SelfHostedTelemetryConfig as w, ReleasedImage as wt, NormalizedWorkspace as x, StateLocked as xt, ModelsConfig as y, storedCredentials as yt, isDeployTargetSupported as z };
7525
- //# sourceMappingURL=types-DMoaFrjg.d.mts.map
7534
+ //# sourceMappingURL=types-bkqVscdN.d.mts.map