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

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 (192) hide show
  1. package/dist/{GoDaddyProvider-BRZUWD8z.mjs → GoDaddyProvider-BwW51hPm.mjs} +3 -3
  2. package/dist/{GoDaddyProvider-BRZUWD8z.mjs.map → GoDaddyProvider-BwW51hPm.mjs.map} +1 -1
  3. package/dist/{GoDaddyProvider-DzguxU_a.cjs → GoDaddyProvider-C_DgIkMv.cjs} +3 -3
  4. package/dist/{GoDaddyProvider-DzguxU_a.cjs.map → GoDaddyProvider-C_DgIkMv.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-D50dgUPc.cjs → LegacyStateStore-BawjE_5n.cjs} +3 -3
  10. package/dist/{LegacyStateStore-D50dgUPc.cjs.map → LegacyStateStore-BawjE_5n.cjs.map} +1 -1
  11. package/dist/{LegacyStateStore-BQZb6-j2.mjs → LegacyStateStore-D5DarNA2.mjs} +3 -3
  12. package/dist/{LegacyStateStore-BQZb6-j2.mjs.map → LegacyStateStore-D5DarNA2.mjs.map} +1 -1
  13. package/dist/{LocalStateStore-EFBUjuMX.cjs → LocalStateStore-D8fu5WiF.cjs} +2 -2
  14. package/dist/{LocalStateStore-EFBUjuMX.cjs.map → LocalStateStore-D8fu5WiF.cjs.map} +1 -1
  15. package/dist/{LocalStateStore-BSaS2535.mjs → LocalStateStore-YjIqlgAz.mjs} +2 -2
  16. package/dist/{LocalStateStore-BSaS2535.mjs.map → LocalStateStore-YjIqlgAz.mjs.map} +1 -1
  17. package/dist/{S3StateStore-CrFq4UZU.mjs → S3StateStore-CjTAVsWh.mjs} +2 -2
  18. package/dist/{S3StateStore-CrFq4UZU.mjs.map → S3StateStore-CjTAVsWh.mjs.map} +1 -1
  19. package/dist/{S3StateStore-C5mv8To3.cjs → S3StateStore-Cm-v2IPI.cjs} +2 -2
  20. package/dist/{S3StateStore-C5mv8To3.cjs.map → S3StateStore-Cm-v2IPI.cjs.map} +1 -1
  21. package/dist/{SSMStateStore-DuZCH7_v.cjs → SSMStateStore-BS4BiZCN.cjs} +2 -2
  22. package/dist/{SSMStateStore-DuZCH7_v.cjs.map → SSMStateStore-BS4BiZCN.cjs.map} +1 -1
  23. package/dist/{SSMStateStore-D3Z6mZnA.mjs → SSMStateStore-BhtM6jOh.mjs} +2 -2
  24. package/dist/{SSMStateStore-D3Z6mZnA.mjs.map → SSMStateStore-BhtM6jOh.mjs.map} +1 -1
  25. package/dist/{add-DsVDdvon.cjs → add-D-3IKT7W.cjs} +22 -51
  26. package/dist/add-D-3IKT7W.cjs.map +1 -0
  27. package/dist/{add-C85isXFl.mjs → add-ylx8dejw.mjs} +21 -50
  28. package/dist/add-ylx8dejw.mjs.map +1 -0
  29. package/dist/{bundler-BEgUKc4j.cjs → bundler-CI3elfZS.cjs} +5 -5
  30. package/dist/{bundler-BEgUKc4j.cjs.map → bundler-CI3elfZS.cjs.map} +1 -1
  31. package/dist/{bundler-BSHog8CH.mjs → bundler-ywR3C1B_.mjs} +5 -5
  32. package/dist/{bundler-BSHog8CH.mjs.map → bundler-ywR3C1B_.mjs.map} +1 -1
  33. package/dist/{cli-BsFenyaf.mjs → cli-BCSuCfQk.mjs} +4 -4
  34. package/dist/{cli-BsFenyaf.mjs.map → cli-BCSuCfQk.mjs.map} +1 -1
  35. package/dist/{cli-BvBdv660.cjs → cli-Dewt2T21.cjs} +4 -4
  36. package/dist/{cli-BvBdv660.cjs.map → cli-Dewt2T21.cjs.map} +1 -1
  37. package/dist/{compose-D2RFYd_f.mjs → compose-C4js1JDv.mjs} +42 -46
  38. package/dist/compose-C4js1JDv.mjs.map +1 -0
  39. package/dist/{compose-Cd09gW-n.cjs → compose-Dd0XphvF.cjs} +59 -63
  40. package/dist/compose-Dd0XphvF.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.d.cts +3 -3
  46. package/dist/config.d.mts +3 -3
  47. package/dist/{credentials-DpfnUvIR.mjs → credentials-B5N5yKk6.mjs} +4 -132
  48. package/dist/credentials-B5N5yKk6.mjs.map +1 -0
  49. package/dist/{credentials-D7XJypNd.cjs → credentials-Zqr3QQYB.cjs} +3 -173
  50. package/dist/credentials-Zqr3QQYB.cjs.map +1 -0
  51. package/dist/deploy/public.cjs +15 -14
  52. package/dist/deploy/public.cjs.map +1 -1
  53. package/dist/deploy/public.d.cts +5 -5
  54. package/dist/deploy/public.d.cts.map +1 -1
  55. package/dist/deploy/public.d.mts +5 -5
  56. package/dist/deploy/public.d.mts.map +1 -1
  57. package/dist/deploy/public.mjs +10 -9
  58. package/dist/deploy/public.mjs.map +1 -1
  59. package/dist/{providers-sTj-BG0S.mjs → deploy-B0drCD6s.mjs} +898 -123
  60. package/dist/deploy-B0drCD6s.mjs.map +1 -0
  61. package/dist/{providers-BFeP_mYw.cjs → deploy-Bw1FjX_x.cjs} +939 -134
  62. package/dist/deploy-Bw1FjX_x.cjs.map +1 -0
  63. package/dist/{discover-CTzOSGUF.d.cts → discover-BtFofyQB.d.cts} +2 -2
  64. package/dist/{discover-CTzOSGUF.d.cts.map → discover-BtFofyQB.d.cts.map} +1 -1
  65. package/dist/{discover-CihAtaoj.d.mts → discover-D-MdXZgm.d.mts} +2 -2
  66. package/dist/{discover-CihAtaoj.d.mts.map → discover-D-MdXZgm.d.mts.map} +1 -1
  67. package/dist/dns-Bmk7P9c2.cjs +663 -0
  68. package/dist/dns-Bmk7P9c2.cjs.map +1 -0
  69. package/dist/dns-CyMIq6to.cjs +55 -0
  70. package/dist/dns-CyMIq6to.cjs.map +1 -0
  71. package/dist/dns-X3oqEV4C.mjs +44 -0
  72. package/dist/dns-X3oqEV4C.mjs.map +1 -0
  73. package/dist/dns-idXfyCay.mjs +610 -0
  74. package/dist/dns-idXfyCay.mjs.map +1 -0
  75. package/dist/{dokploy-D_aat2Xj.mjs → dokploy-CZYxXeMa.mjs} +2 -2
  76. package/dist/{dokploy-D_aat2Xj.mjs.map → dokploy-CZYxXeMa.mjs.map} +1 -1
  77. package/dist/{dokploy-CV7GcobZ.cjs → dokploy-DaT0mgLU.cjs} +2 -2
  78. package/dist/{dokploy-CV7GcobZ.cjs.map → dokploy-DaT0mgLU.cjs.map} +1 -1
  79. package/dist/{encryption-_4qKqtTx.mjs → encryption-D0ucY4O7.mjs} +2 -2
  80. package/dist/{encryption-_4qKqtTx.mjs.map → encryption-D0ucY4O7.mjs.map} +1 -1
  81. package/dist/{encryption-DFcivJaO.cjs → encryption-Dp0IvLVX.cjs} +2 -2
  82. package/dist/{encryption-DFcivJaO.cjs.map → encryption-Dp0IvLVX.cjs.map} +1 -1
  83. package/dist/{engine-DPMHThkg.mjs → engine-BcuhnyQO.mjs} +13 -31
  84. package/dist/{engine-DPMHThkg.mjs.map → engine-BcuhnyQO.mjs.map} +1 -1
  85. package/dist/{engine-Bv-LZpmj.cjs → engine-WY6j_kvA.cjs} +17 -35
  86. package/dist/engine-WY6j_kvA.cjs.map +1 -0
  87. package/dist/{github-xsDT19im.mjs → github-DUGA57du.mjs} +4 -2
  88. package/dist/{github-xsDT19im.mjs.map → github-DUGA57du.mjs.map} +1 -1
  89. package/dist/{github-Br42NMrW.cjs → github-DgmW83OP.cjs} +8 -6
  90. package/dist/{github-Br42NMrW.cjs.map → github-DgmW83OP.cjs.map} +1 -1
  91. package/dist/{index-CwLvFqtH.d.cts → index-5eL8rM6H.d.mts} +2 -2
  92. package/dist/{index-BlpcClwM.d.mts.map → index-5eL8rM6H.d.mts.map} +1 -1
  93. package/dist/{index-BlpcClwM.d.mts → index-Dz-gyjm_.d.cts} +2 -2
  94. package/dist/{index-CwLvFqtH.d.cts.map → index-Dz-gyjm_.d.cts.map} +1 -1
  95. package/dist/index.cjs +53 -52
  96. package/dist/index.cjs.map +1 -1
  97. package/dist/index.mjs +51 -50
  98. package/dist/index.mjs.map +1 -1
  99. package/dist/{local-B7Zv1NoA.mjs → local-BwC2v2Y8.mjs} +2 -2
  100. package/dist/{local-B7Zv1NoA.mjs.map → local-BwC2v2Y8.mjs.map} +1 -1
  101. package/dist/{local-OPC9BCZt.cjs → local-DNhnkugT.cjs} +3 -3
  102. package/dist/{local-OPC9BCZt.cjs.map → local-DNhnkugT.cjs.map} +1 -1
  103. package/dist/{migrate-SkWJotn5.cjs → migrate-BBcG1dhS.cjs} +2 -2
  104. package/dist/{migrate-SkWJotn5.cjs.map → migrate-BBcG1dhS.cjs.map} +1 -1
  105. package/dist/{migrate-DhvFPGLi.mjs → migrate-CZ-v5WV0.mjs} +2 -2
  106. package/dist/{migrate-DhvFPGLi.mjs.map → migrate-CZ-v5WV0.mjs.map} +1 -1
  107. package/dist/{migrate-B7evHv7O.mjs → migrate-D6PlNv2o.mjs} +2 -2
  108. package/dist/{migrate-B7evHv7O.mjs.map → migrate-D6PlNv2o.mjs.map} +1 -1
  109. package/dist/{migrate-D5jUz20_.cjs → migrate-afgRL3Hg.cjs} +2 -2
  110. package/dist/{migrate-D5jUz20_.cjs.map → migrate-afgRL3Hg.cjs.map} +1 -1
  111. package/dist/openapi.d.cts +1 -1
  112. package/dist/openapi.d.mts +1 -1
  113. package/dist/reconcile/public.d.cts +2 -2
  114. package/dist/reconcile/public.d.mts +2 -2
  115. package/dist/{resolve-CFEOtRsl.cjs → resolve-CFb4Navi.cjs} +4 -4
  116. package/dist/{resolve-CFEOtRsl.cjs.map → resolve-CFb4Navi.cjs.map} +1 -1
  117. package/dist/{resolve-Dyd1S2wn.mjs → resolve-DakDhr6Z.mjs} +4 -4
  118. package/dist/{resolve-Dyd1S2wn.mjs.map → resolve-DakDhr6Z.mjs.map} +1 -1
  119. package/dist/{rollback-D720SFhV.cjs → rollback-B-1dPP0m.cjs} +7 -8
  120. package/dist/{rollback-D720SFhV.cjs.map → rollback-B-1dPP0m.cjs.map} +1 -1
  121. package/dist/{rollback-NroNbGC0.mjs → rollback-B1TIpjdE.mjs} +6 -7
  122. package/dist/{rollback-NroNbGC0.mjs.map → rollback-B1TIpjdE.mjs.map} +1 -1
  123. package/dist/run-BJLIerMM.mjs +133 -0
  124. package/dist/run-BJLIerMM.mjs.map +1 -0
  125. package/dist/run-fVZ-rLnc.cjs +174 -0
  126. package/dist/run-fVZ-rLnc.cjs.map +1 -0
  127. package/dist/{runtime-VktAo_8B.d.cts → runtime-DUQdM-mW.d.cts} +2 -2
  128. package/dist/{runtime-BRCq6dQ7.d.mts.map → runtime-DUQdM-mW.d.cts.map} +1 -1
  129. package/dist/{runtime-BRCq6dQ7.d.mts → runtime-Vr6mleo2.d.mts} +2 -2
  130. package/dist/{runtime-VktAo_8B.d.cts.map → runtime-Vr6mleo2.d.mts.map} +1 -1
  131. package/dist/{sandbox-D1gd0iDz.d.cts → sandbox-BbJmh2rI.d.cts} +2 -2
  132. package/dist/{sandbox-D1gd0iDz.d.cts.map → sandbox-BbJmh2rI.d.cts.map} +1 -1
  133. package/dist/{sandbox-zHnRLCj0.d.mts → sandbox-DGOsMPMf.d.mts} +2 -2
  134. package/dist/{sandbox-zHnRLCj0.d.mts.map → sandbox-DGOsMPMf.d.mts.map} +1 -1
  135. package/dist/{secrets-DAvi_O9g.cjs → secrets-CPM0Qffe.cjs} +2 -2
  136. package/dist/{secrets-DAvi_O9g.cjs.map → secrets-CPM0Qffe.cjs.map} +1 -1
  137. package/dist/{secrets-CwLauUB_.mjs → secrets-oI9ClAPR.mjs} +2 -2
  138. package/dist/{secrets-CwLauUB_.mjs.map → secrets-oI9ClAPR.mjs.map} +1 -1
  139. package/dist/{seeds-BCg8X36S.cjs → seeds-CnXkgKUv.cjs} +192 -945
  140. package/dist/seeds-CnXkgKUv.cjs.map +1 -0
  141. package/dist/{seeds-CTxTZa-R.mjs → seeds-CoKkrSny.mjs} +156 -825
  142. package/dist/seeds-CoKkrSny.mjs.map +1 -0
  143. package/dist/{sniffer-DCcuzHz_.mjs → sniffer-CFRzIrby.mjs} +7 -7
  144. package/dist/{sniffer-DCcuzHz_.mjs.map → sniffer-CFRzIrby.mjs.map} +1 -1
  145. package/dist/{sniffer-C0z3NB2A.cjs → sniffer-vbiQ2Isn.cjs} +7 -7
  146. package/dist/{sniffer-C0z3NB2A.cjs.map → sniffer-vbiQ2Isn.cjs.map} +1 -1
  147. package/dist/{sst-DRDSDwOk.mjs → sst-CGdjHn2A.mjs} +4 -3
  148. package/dist/{sst-DRDSDwOk.mjs.map → sst-CGdjHn2A.mjs.map} +1 -1
  149. package/dist/{sst-DKNH243z.cjs → sst-DGuHDxVU.cjs} +5 -4
  150. package/dist/{sst-DKNH243z.cjs.map → sst-DGuHDxVU.cjs.map} +1 -1
  151. package/dist/{stack-B3fPDTBg.cjs → stack-1g57OfOw.cjs} +13 -51
  152. package/dist/stack-1g57OfOw.cjs.map +1 -0
  153. package/dist/{stack-NrdH5ngX.mjs → stack-B7O975TR.mjs} +13 -51
  154. package/dist/stack-B7O975TR.mjs.map +1 -0
  155. package/dist/{stages-veC4TcQe.mjs → stages-Bt4OggMm.mjs} +3 -2
  156. package/dist/{stages-veC4TcQe.mjs.map → stages-Bt4OggMm.mjs.map} +1 -1
  157. package/dist/{stages-CkqP1N4S.cjs → stages-BujUB4we.cjs} +4 -3
  158. package/dist/{stages-CkqP1N4S.cjs.map → stages-BujUB4we.cjs.map} +1 -1
  159. package/dist/target/public.cjs +1 -1
  160. package/dist/target/public.d.cts +2 -2
  161. package/dist/target/public.d.mts +2 -2
  162. package/dist/target/public.mjs +1 -1
  163. package/dist/{terminal-CkUYuAPd.cjs → terminal-CPHuH4S1.cjs} +2 -2
  164. package/dist/{terminal-CkUYuAPd.cjs.map → terminal-CPHuH4S1.cjs.map} +1 -1
  165. package/dist/{terminal-DAHs2Zko.mjs → terminal-iNmAXXjs.mjs} +2 -2
  166. package/dist/{terminal-DAHs2Zko.mjs.map → terminal-iNmAXXjs.mjs.map} +1 -1
  167. package/dist/{types-DMoaFrjg.d.mts → types-bkqVscdN.d.mts} +12 -3
  168. package/dist/types-bkqVscdN.d.mts.map +1 -0
  169. package/dist/{types-DXyaSmqu.d.cts → types-dipJRmKV.d.cts} +12 -3
  170. package/dist/types-dipJRmKV.d.cts.map +1 -0
  171. package/dist/workspace/index.d.cts +2 -2
  172. package/dist/workspace/index.d.mts +2 -2
  173. package/package.json +15 -15
  174. package/dist/add-C85isXFl.mjs.map +0 -1
  175. package/dist/add-DsVDdvon.cjs.map +0 -1
  176. package/dist/compose-Cd09gW-n.cjs.map +0 -1
  177. package/dist/compose-D2RFYd_f.mjs.map +0 -1
  178. package/dist/credentials-D7XJypNd.cjs.map +0 -1
  179. package/dist/credentials-DpfnUvIR.mjs.map +0 -1
  180. package/dist/deploy-C911Akkn.cjs +0 -670
  181. package/dist/deploy-C911Akkn.cjs.map +0 -1
  182. package/dist/deploy-CeJ5D0xn.mjs +0 -641
  183. package/dist/deploy-CeJ5D0xn.mjs.map +0 -1
  184. package/dist/engine-Bv-LZpmj.cjs.map +0 -1
  185. package/dist/providers-BFeP_mYw.cjs.map +0 -1
  186. package/dist/providers-sTj-BG0S.mjs.map +0 -1
  187. package/dist/seeds-BCg8X36S.cjs.map +0 -1
  188. package/dist/seeds-CTxTZa-R.mjs.map +0 -1
  189. package/dist/stack-B3fPDTBg.cjs.map +0 -1
  190. package/dist/stack-NrdH5ngX.mjs.map +0 -1
  191. package/dist/types-DMoaFrjg.d.mts.map +0 -1
  192. package/dist/types-DXyaSmqu.d.cts.map +0 -1
@@ -1,127 +1,84 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
2
  const require_errors = require("./errors-DMC4Umsb.cjs");
3
- const require_credentials = require("./credentials-D7XJypNd.cjs");
3
+ const require_run = require("./run-fVZ-rLnc.cjs");
4
+ const require_credentials = require("./credentials-Zqr3QQYB.cjs");
5
+ const require_discover = require("./discover-DPgu-ScS.cjs");
6
+ const require_sandbox = require("./sandbox-CHv3OYXg.cjs");
4
7
  const require_derive = require("./derive-DAbo49sm.cjs");
5
8
  const require_workspace = require("./workspace-cSyi5nb1.cjs");
6
- const require_seeds = require("./seeds-BCg8X36S.cjs");
9
+ const require_define = require("./define-crmMcXFS.cjs");
10
+ const require_config = require("./config.cjs");
11
+ const require_seeds = require("./seeds-CnXkgKUv.cjs");
12
+ const require_resolve = require("./resolve-CFb4Navi.cjs");
13
+ const require_local = require("./local-DNhnkugT.cjs");
14
+ const require_sniffer = require("./sniffer-vbiQ2Isn.cjs");
15
+ const require_dns = require("./dns-Bmk7P9c2.cjs");
16
+ const require_dns$1 = require("./dns-CyMIq6to.cjs");
17
+ const require_credentialSchemas = require("./credentialSchemas-CAPKFkrG.cjs");
18
+ let node_path = require("node:path");
7
19
  let _geekmidas_manifest = require("@geekmidas/manifest");
20
+ let node_crypto = require("node:crypto");
8
21
  let _geekmidas_storage_s3_url = require("@geekmidas/storage/s3-url");
9
22
  _geekmidas_storage_s3_url = require_rolldown_runtime.__toESM(_geekmidas_storage_s3_url, 1);
10
- //#region src/deploy/journal.ts
11
- var DeployJournal = class DeployJournal {
12
- store;
13
- stage;
14
- state;
15
- resources;
16
- version;
17
- existed;
18
- constructor(store, stage, state, resources, version, existed) {
19
- this.store = store;
20
- this.stage = stage;
21
- this.state = state;
22
- this.resources = resources;
23
- this.version = version;
24
- this.existed = existed;
25
- }
26
- static async open(store, stage, initial, adopt = (stored) => stored) {
27
- const stored = await store.read(stage);
28
- if (stored) return new DeployJournal(store, stage, adopt(stored.state), stored.resources, stored.version, true);
29
- const state = initial();
30
- const version = await store.write(stage, state, { expectedVersion: null });
31
- return new DeployJournal(store, stage, state, {}, version, false);
32
- }
33
- record(key) {
34
- return this.resources[key];
35
- }
36
- /** The keys a previous run marked `pending` and never saw created. */
37
- unfinished() {
38
- return Object.values(this.resources).filter((record) => record.status === "pending").map((record) => record.key);
39
- }
40
- /** Records that `entry` is about to be created. */
41
- async pending(entry) {
42
- await this.put({
43
- ...entry,
44
- status: "pending"
45
- });
46
- }
47
- /**
48
- * Records `entry` as existing with `id`; a no-op if it already is, with
49
- * the same data.
50
- */
51
- async ready(entry, id) {
52
- const current = this.resources[entry.key];
53
- if (current?.status === "ready" && current.id === id && JSON.stringify(current.data) === JSON.stringify(entry.data)) return;
54
- await this.put({
55
- ...entry,
56
- status: "ready",
57
- id
58
- });
59
- }
60
- /**
61
- * The resource `entry` names: by its recorded id, else by looking it up,
62
- * else created — with `pending` written before the create and `ready`
63
- * after, so a run that dies in between leaves a record the next run
64
- * resolves by looking the resource up rather than creating another.
65
- */
66
- async ensure(entry, steps) {
67
- const record = this.resources[entry.key];
68
- let staleId;
69
- if (record?.status === "ready" && record.id && steps.get) {
70
- const known = await steps.get(record.id);
71
- if (known) {
72
- await this.ready(entry, steps.id(known));
73
- return {
74
- resource: known,
75
- via: "recorded"
76
- };
77
- }
78
- staleId = record.id;
79
- }
80
- const existing = await steps.find();
81
- if (existing) {
82
- await this.ready(entry, steps.id(existing));
83
- return {
84
- resource: existing,
85
- via: record?.status === "pending" ? "resumed" : "found",
86
- ...staleId ? { staleId } : {}
87
- };
88
- }
89
- await this.pending(entry);
90
- const created = await steps.create();
91
- await this.ready(entry, steps.id(created));
92
- return {
93
- resource: created,
94
- via: "created",
95
- ...staleId ? { staleId } : {}
96
- };
97
- }
98
- /** Removes `key`'s record — a resource that no longer exists. */
99
- async forget(key) {
100
- if (!(key in this.resources)) return;
101
- this.version = await this.store.deleteResource(this.stage, key, { expectedVersion: this.version });
102
- const { [key]: _removed, ...resources } = this.resources;
103
- this.resources = resources;
104
- }
105
- /** Every record, as the journal last wrote or read it. */
106
- records() {
107
- return this.resources;
108
- }
109
- /** Writes the stage's state, keeping its resource records. */
110
- async save() {
111
- this.state.lastDeployedAt = (/* @__PURE__ */ new Date()).toISOString();
112
- this.version = await this.store.write(this.stage, this.state, { expectedVersion: this.version });
23
+ //#region src/target/secrets.ts
24
+ /**
25
+ * A stage's secrets as a target sees them: read and written through the
26
+ * stage's own store, and masked in everything the run prints once read.
27
+ */
28
+ /**
29
+ * Shorter values are left alone: what a progress line legitimately prints —
30
+ * a port, a stage, an app name — would otherwise come out as `***` wherever
31
+ * a secret happened to share it.
32
+ */
33
+ const SHORTEST_MASKED = 6;
34
+ /** The values a run must never print, and the rewrite that keeps it so. */
35
+ var Redactor = class {
36
+ values = /* @__PURE__ */ new Set();
37
+ add(value) {
38
+ if (value && value.length >= SHORTEST_MASKED) this.values.add(value);
113
39
  }
114
- async put(record) {
115
- this.version = await this.store.putResource(this.stage, record, { expectedVersion: this.version });
116
- this.resources = {
117
- ...this.resources,
118
- [record.key]: {
119
- ...record,
120
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
121
- }
122
- };
40
+ /** `text` with every masked value replaced by `***`, longest first. */
41
+ redact(text) {
42
+ if (this.values.size === 0) return text;
43
+ let out = text;
44
+ const longestFirst = [...this.values].sort((a, b) => b.length - a.length);
45
+ for (const value of longestFirst) out = out.replaceAll(value, "***");
46
+ return out;
123
47
  }
124
48
  };
49
+ /** Every value in `secrets` that is a secret rather than a label. */
50
+ function secretValues(secrets) {
51
+ return [
52
+ secrets.seed,
53
+ ...Object.values(secrets.custom ?? {}),
54
+ ...Object.values(secrets.urls ?? {}),
55
+ ...Object.values(secrets.services ?? {}).map((service) => service?.password)
56
+ ].filter((value) => typeof value === "string");
57
+ }
58
+ /**
59
+ * The stage's secrets through the store `secrets.store` names for it. Opening
60
+ * one builds a client and makes no request, so a target that never reads them
61
+ * costs nothing.
62
+ */
63
+ async function deploySecrets(workspace, stage, redactor, options = {}) {
64
+ const store = await require_seeds.secretsStoreFor(workspace, stage, options);
65
+ const mask = (secrets) => {
66
+ for (const value of secretValues(secrets)) redactor.add(value);
67
+ };
68
+ return {
69
+ store: store.name,
70
+ async read() {
71
+ const secrets = await store.read(stage);
72
+ if (secrets) mask(secrets);
73
+ return secrets;
74
+ },
75
+ async write(secrets) {
76
+ mask(secrets);
77
+ await store.write(stage, secrets);
78
+ },
79
+ mask: (value) => redactor.add(value)
80
+ };
81
+ }
125
82
  //#endregion
126
83
  //#region src/providers/aws.ts
127
84
  /**
@@ -195,6 +152,88 @@ async function awsClientConfig(credential, region) {
195
152
  };
196
153
  return { region };
197
154
  }
155
+ const SUFFIX_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
156
+ /** A name that S3 would refuse — what the name builder never returns. */
157
+ var InvalidBucketName = class extends require_errors.GkmError {
158
+ bucket;
159
+ reason;
160
+ constructor(bucket, reason) {
161
+ super(`'${bucket}' is not a valid S3 bucket name: ${reason}. Rename the construct or set deploy.namespace in gkm.config.ts to something that leaves room for it.`);
162
+ this.bucket = bucket;
163
+ this.reason = reason;
164
+ this.name = "InvalidBucketName";
165
+ }
166
+ };
167
+ /** Lowercase `[a-z0-9-]`, runs of anything else one `-`, no edge dashes. */
168
+ function part(value) {
169
+ return (0, _geekmidas_manifest.kebabCase)(value).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
170
+ }
171
+ /**
172
+ * `parts` joined by `-`, shortened to `max` characters by trimming the longest
173
+ * part one character at a time — so a long construct id gives way before a
174
+ * short stage name does, and every part keeps its start.
175
+ */
176
+ function fitParts(parts, max) {
177
+ const kept = parts.map(part).filter(Boolean);
178
+ const length = () => kept.reduce((sum, p) => sum + p.length, 0) + kept.length - 1;
179
+ while (length() > max) {
180
+ let longest = 0;
181
+ for (let i = 1; i < kept.length; i++) if (kept[i].length > kept[longest].length) longest = i;
182
+ if (kept[longest].length <= 1) break;
183
+ kept[longest] = kept[longest].slice(0, -1).replace(/-+$/, "");
184
+ }
185
+ return kept.join("-");
186
+ }
187
+ /** Why `name` is not a valid bucket name, or undefined when it is. */
188
+ function bucketNameProblem(name) {
189
+ if (name.length < 3 || name.length > 63) return `it is ${name.length} characters, and S3 takes 3 to 63`;
190
+ if (!/^[a-z0-9-]+$/.test(name)) return "it may hold only lowercase letters, digits and -";
191
+ if (!/^[a-z0-9].*[a-z0-9]$/.test(name)) return "it must start and end with a letter or a digit";
192
+ if (name.startsWith("xn--") || name.startsWith("sthree-")) return "it starts with a prefix S3 reserves ('xn--', 'sthree-')";
193
+ if (name.endsWith("-s3alias") || name.endsWith("--ol-s3")) return "it ends with a suffix S3 reserves ('-s3alias', '--ol-s3')";
194
+ }
195
+ /**
196
+ * The good name: `<namespace>-<project>-<stage>-<bucket id>`, lowercased, no
197
+ * dots, shortened to leave room for a clash's suffix.
198
+ *
199
+ * @throws {InvalidBucketName} when nothing usable is left
200
+ */
201
+ function bucketName(input) {
202
+ const name = fitParts([
203
+ input.scope,
204
+ input.stage,
205
+ input.id
206
+ ], 56);
207
+ const problem = bucketNameProblem(name);
208
+ if (problem) throw new InvalidBucketName(name, problem);
209
+ return name;
210
+ }
211
+ /** Six random `[a-z0-9]` characters. */
212
+ function randomSuffix(random = node_crypto.randomInt) {
213
+ let suffix = "";
214
+ for (let i = 0; i < 6; i++) suffix += SUFFIX_ALPHABET[random(36)];
215
+ return suffix;
216
+ }
217
+ /** The good name with a clash's suffix. */
218
+ function suffixedBucketName(good, suffix) {
219
+ return `${good}-${suffix}`;
220
+ }
221
+ /**
222
+ * The IAM user a bucket is reached with on a stage:
223
+ * `gkm-<project>-<stage>-<bucket id>`, at most 64 characters.
224
+ */
225
+ function iamUserName(input) {
226
+ return fitParts([
227
+ "gkm",
228
+ input.scope,
229
+ input.stage,
230
+ input.id
231
+ ], 64);
232
+ }
233
+ /** The path every user gkm creates is under, so it finds its own. */
234
+ const IAM_USER_PATH = "/gkm/";
235
+ /** The inline policy each user is given. */
236
+ const IAM_POLICY_NAME = "gkm-bucket";
198
237
  //#endregion
199
238
  //#region src/providers/s3/origins.ts
200
239
  /**
@@ -472,7 +511,7 @@ async function ensureBucket(ctx, clients, construct) {
472
511
  };
473
512
  const versioning = ctx.config.versioning ?? construct.versioned;
474
513
  const open = [...new Set(construct.servers.flatMap((s) => s.open))].sort();
475
- const { bucket, exists } = await ensureBucketName(ctx, clients, id, require_seeds.bucketName(nameInput));
514
+ const { bucket, exists } = await ensureBucketName(ctx, clients, id, bucketName(nameInput));
476
515
  await ensureBucketSettings(ctx, clients, {
477
516
  id,
478
517
  bucket,
@@ -483,7 +522,7 @@ async function ensureBucket(ctx, clients, construct) {
483
522
  await ensureAccessKey(ctx, clients, {
484
523
  id,
485
524
  bucket,
486
- ...await ensureUser(ctx, clients, id, require_seeds.iamUserName(nameInput), userPolicy(bucket, { versioning }))
525
+ ...await ensureUser(ctx, clients, id, iamUserName(nameInput), userPolicy(bucket, { versioning }))
487
526
  });
488
527
  const publicUrl = bucketPublicUrl(bucket, clients.region, clients.endpoint);
489
528
  for (const server of construct.servers) {
@@ -595,7 +634,7 @@ async function ensureBucketName(ctx, clients, id, good) {
595
634
  const names = [
596
635
  ...typeof pending === "string" && pending !== good ? [pending] : [],
597
636
  good,
598
- ...Array.from({ length: 5 }, () => require_seeds.suffixedBucketName(good, require_seeds.randomSuffix()))
637
+ ...Array.from({ length: 5 }, () => suffixedBucketName(good, randomSuffix()))
599
638
  ];
600
639
  const tried = [];
601
640
  for (const name of names) {
@@ -713,12 +752,12 @@ async function ensureUser(ctx, clients, id, user, policy) {
713
752
  } else await ctx.change({
714
753
  construct: id,
715
754
  resource: `IAM user ${user}`,
716
- change: `create under ${require_seeds.IAM_USER_PATH}`
755
+ change: `create under ${IAM_USER_PATH}`
717
756
  }, async () => {
718
757
  await ctx.state.pending(entry);
719
758
  await iam.send(new IAM.CreateUserCommand({
720
759
  UserName: user,
721
- Path: require_seeds.IAM_USER_PATH,
760
+ Path: IAM_USER_PATH,
722
761
  Tags: identityTags(ctx, id)
723
762
  }));
724
763
  await ctx.state.ready(entry, user);
@@ -726,17 +765,17 @@ async function ensureUser(ctx, clients, id, user, policy) {
726
765
  const exists = Boolean(found?.User) || !ctx.dryRun;
727
766
  const current = exists ? await readOr(() => iam.send(new IAM.GetUserPolicyCommand({
728
767
  UserName: user,
729
- PolicyName: require_seeds.IAM_POLICY_NAME
768
+ PolicyName: IAM_POLICY_NAME
730
769
  })), ["NoSuchEntity", "NoSuchEntityException"]) : void 0;
731
770
  const document = current?.PolicyDocument ? JSON.parse(decodePolicy(current.PolicyDocument)) : void 0;
732
771
  if (!document || canonicalPolicy(document) !== canonicalPolicy(policy)) await ctx.change({
733
772
  construct: id,
734
773
  resource: `IAM user ${user}`,
735
- change: `policy ${require_seeds.IAM_POLICY_NAME}: this bucket only`
774
+ change: `policy ${IAM_POLICY_NAME}: this bucket only`
736
775
  }, async () => {
737
776
  await iam.send(new IAM.PutUserPolicyCommand({
738
777
  UserName: user,
739
- PolicyName: require_seeds.IAM_POLICY_NAME,
778
+ PolicyName: IAM_POLICY_NAME,
740
779
  PolicyDocument: JSON.stringify(policy)
741
780
  }));
742
781
  });
@@ -909,12 +948,10 @@ function constructsOf(manifest, kind) {
909
948
  /**
910
949
  * What every deploy runs: each provider's `verify()` — the cheap check that
911
950
  * what it created is still there and the stage's key reaches it. Nothing on
912
- * the local stage, and nothing for a kind on `external`.
913
- *
914
- * @throws {StageProviderDisabled} for a declared kind the stage has none of
951
+ * the local stage, and nothing for a kind on `external` or `false` — a kind
952
+ * the stage has none of is the deploy's readiness check's to refuse.
915
953
  */
916
954
  async function verifyStageProviders(input) {
917
- require_seeds.assertStageProvidersEnabled(input.workspace, input.manifest, input.stage);
918
955
  const verified = [];
919
956
  for (const kind of require_seeds.PROVIDER_KINDS) {
920
957
  if (constructsOf(input.manifest, kind).length === 0) continue;
@@ -1012,7 +1049,7 @@ async function provisionStage(options) {
1012
1049
  const identity = require_seeds.deployIdentity(workspace, stage);
1013
1050
  let secrets = (await options.secrets.read())?.custom ?? {};
1014
1051
  for (const entry of configured) entry.report.planned = entry.provider.runtimeKeys(manifest).filter((key) => secrets[key] === void 0);
1015
- const state = dryRun ? await readOnlyState(options.state, stage) : journalState(await DeployJournal.open(options.state, stage, () => require_seeds.deploysWithCompose(workspace) ? require_seeds.createComposeState(stage) : require_seeds.createEmptyState(stage, "", "")));
1052
+ const state = dryRun ? await readOnlyState(options.state, stage) : journalState(await require_seeds.DeployJournal.open(options.state, stage, () => require_dns$1.deploysWithCompose(workspace) ? require_seeds.createComposeState(stage) : require_seeds.createEmptyState(stage, "", "")));
1016
1053
  const writeSecrets = async (values) => {
1017
1054
  if (dryRun) return;
1018
1055
  const stored = await options.secrets.read() ?? require_seeds.initStageSecrets(stage);
@@ -1076,23 +1113,791 @@ async function readOnlyState(store, stage) {
1076
1113
  };
1077
1114
  }
1078
1115
  //#endregion
1079
- Object.defineProperty(exports, "DeployJournal", {
1116
+ //#region src/secrets/stale.ts
1117
+ /**
1118
+ * Stored secrets an older gkm generated that now shadow a derived value.
1119
+ *
1120
+ * Before constructs, initialising a stage wrote an address for each app into
1121
+ * its custom secrets: `<APP>_DATABASE_URL` as a `postgresql://…@localhost`
1122
+ * URL with a password of its own, and `http://localhost:<port>` for a site or
1123
+ * an auth server. Those keys are now a construct's — `database.schema('AuthDatabase')`
1124
+ * provides `AUTH_DATABASE_URL`, `new BetterAuth('Auth')` provides `AUTH_URL`
1125
+ * — and a deploy derives them. A value the stage holds is a value set by hand,
1126
+ * and set by hand wins: the container is handed `localhost`, where nothing
1127
+ * answers, with a password no role has.
1128
+ *
1129
+ * So a deploy refuses such a stage rather than run it, naming each key and
1130
+ * the command that removes it. Nothing is deleted for the user: the value is
1131
+ * theirs, and only they can say it is stale. A URL that names a real host — a
1132
+ * managed database — is a deliberate choice and still wins.
1133
+ */
1134
+ /** The kinds whose URL an older gkm wrote into a stage's secrets. */
1135
+ const ADDRESSED = /* @__PURE__ */ new Set([
1136
+ "database",
1137
+ "database-reader",
1138
+ "database-schema",
1139
+ "rest-api",
1140
+ "site"
1141
+ ]);
1142
+ /** Hosts that are this machine — never anything, inside a container. */
1143
+ const LOOPBACK = /* @__PURE__ */ new Set([
1144
+ "localhost",
1145
+ "127.0.0.1",
1146
+ "[::1]",
1147
+ "::1"
1148
+ ]);
1149
+ /**
1150
+ * A stage holds a construct's address as a custom secret, pointing at
1151
+ * `localhost` — what an older `gkm secrets:init`, `gkm setup` or `gkm init`
1152
+ * generated. Set by hand wins over derived, so the app would be handed it.
1153
+ */
1154
+ var StaleStageSecrets = class extends require_errors.GkmError {
1155
+ stage;
1156
+ stale;
1157
+ constructor(stage, stale) {
1158
+ const one = stale.length === 1;
1159
+ super(`The stage '${stage}' holds ${one ? "a value" : "values"} an older gkm generated for ${one ? "an address a construct" : "addresses constructs"} now ${one ? "provides" : "provide"}:\n` + stale.map((s) => ` ${s.key}: ${s.construct}'s, stored pointing at ${s.host}`).join("\n") + `
1160
+ A stored value wins over the derived one, so the app would be handed an address where nothing answers inside its container. Remove ${one ? "it" : "each"}, and the construct's own value is used:\n` + stale.map((s) => ` gkm secrets:unset ${s.key} --stage ${stage}`).join("\n") + "\nA managed service set with its real host is not affected.");
1161
+ this.stage = stage;
1162
+ this.stale = stale;
1163
+ this.name = "StaleStageSecrets";
1164
+ }
1165
+ };
1166
+ /** The host a stored value names, if it is a URL. */
1167
+ function hostOf(value) {
1168
+ try {
1169
+ return new URL(value).hostname;
1170
+ } catch {
1171
+ return;
1172
+ }
1173
+ }
1174
+ /**
1175
+ * Each stored key that a construct provides an address for, holding an
1176
+ * address on this machine.
1177
+ */
1178
+ function staleStageSecrets(manifest, supplied) {
1179
+ const stale = [];
1180
+ for (const [id, declaration] of Object.entries(manifest)) {
1181
+ if (!ADDRESSED.has(declaration.kind)) continue;
1182
+ const key = (0, _geekmidas_manifest.providedKeyFor)(id, declaration.kind, "url");
1183
+ const value = supplied[key];
1184
+ if (value === void 0) continue;
1185
+ const host = hostOf(value);
1186
+ if (host === void 0 || !LOOPBACK.has(host)) continue;
1187
+ stale.push({
1188
+ key,
1189
+ construct: id,
1190
+ host
1191
+ });
1192
+ }
1193
+ return stale.sort((a, b) => a.key.localeCompare(b.key));
1194
+ }
1195
+ /**
1196
+ * Refuse a stage whose stored secrets would shadow a construct's address with
1197
+ * `localhost`.
1198
+ *
1199
+ * @throws {StaleStageSecrets} naming each key and the command removing it
1200
+ */
1201
+ function assertNoStaleSecrets(options) {
1202
+ const stale = staleStageSecrets(options.manifest, options.supplied);
1203
+ if (stale.length > 0) throw new StaleStageSecrets(options.stage, stale);
1204
+ }
1205
+ //#endregion
1206
+ //#region src/deploy/readiness.ts
1207
+ /**
1208
+ * Whether a stage is ready to be deployed: the one check, run once by every
1209
+ * deploy through a server target — after the stage's providers have created
1210
+ * what they create and written its keys, and before the target touches
1211
+ * anything.
1212
+ *
1213
+ * A build is not a deploy. Images carry no stage's keys, so a build-only run
1214
+ * (`gkm compose --build --push`) never calls this: a key the deploy itself
1215
+ * writes — a provider's bucket URL — is not there yet when CI builds, and
1216
+ * must not stop the build.
1217
+ */
1218
+ /**
1219
+ * The stage has every key it needs, read from its secrets as the providers
1220
+ * left them:
1221
+ *
1222
+ * 1. no kind it declares is one the stage set to `false`;
1223
+ * 2. its mail and storage are its own — or a dev service, where allowed,
1224
+ * reported once, loudly;
1225
+ * 3. what its providers created is still there, and its key reaches it;
1226
+ * 4. no key holds an address an older gkm stored for what a construct now
1227
+ * provides;
1228
+ * 5. each third party's credentials match their construct's schema.
1229
+ *
1230
+ * The local stage derives its mail and storage, so only 4 and 5 apply to it.
1231
+ *
1232
+ * @throws {StageProviderDisabled}
1233
+ * @throws {ExternalServicesNotConfigured} naming every missing key at once
1234
+ * @throws {StaleStageSecrets}
1235
+ * @throws {CredentialsInvalid}
1236
+ */
1237
+ async function assertStageReady(ctx) {
1238
+ const { workspace, manifest, stage } = ctx;
1239
+ const supplied = (await ctx.secrets.read())?.custom ?? {};
1240
+ if (stage !== workspace.stages.local) {
1241
+ require_seeds.assertStageProvidersEnabled(workspace, manifest, stage);
1242
+ const domain = workspace.domains?.[stage];
1243
+ const services = require_seeds.externalServices({
1244
+ stage,
1245
+ declarations: require_seeds.stageServiceDeclarations({
1246
+ manifest,
1247
+ ...ctx.runnables ? { runnables: ctx.runnables } : {}
1248
+ }),
1249
+ supplied,
1250
+ allow: ctx.allowDevServices,
1251
+ ...domain ? { domain } : {},
1252
+ providers: require_seeds.stageProviderNotes(workspace, stage)
1253
+ });
1254
+ if (services.missing.length > 0) throw new require_seeds.ExternalServicesNotConfigured(stage, services.missing);
1255
+ require_seeds.reportDevServices(ctx, require_seeds.devServicesUsed(services));
1256
+ const verified = await verifyStageProviders({
1257
+ workspace,
1258
+ manifest,
1259
+ stage,
1260
+ secrets: supplied
1261
+ });
1262
+ for (const line of verified) ctx.logger.info(`✓ ${line} verified`);
1263
+ }
1264
+ assertNoStaleSecrets({
1265
+ manifest,
1266
+ stage,
1267
+ supplied
1268
+ });
1269
+ await require_credentialSchemas.assertStageCredentials({
1270
+ root: workspace.root,
1271
+ patterns: require_seeds.constructGlobs(workspace),
1272
+ manifest,
1273
+ stage,
1274
+ supplied
1275
+ });
1276
+ }
1277
+ //#endregion
1278
+ //#region src/deploy/orchestrate.ts
1279
+ /**
1280
+ * The run around a target: what every deploy does whatever it deploys
1281
+ * through.
1282
+ *
1283
+ * It loads the workspace, resolves the target, works out the apps and the
1284
+ * identity, takes the stage's lock, and calls the target's phases in order,
1285
+ * reporting each as it starts, finishes or fails. Everything that is about
1286
+ * *where* the stage goes is the target's.
1287
+ */
1288
+ /** `--resources-only` with `--skip-resources`: the one asks for what the other skips. */
1289
+ var ResourcesOnlyAndSkipped = class extends require_errors.GkmError {
1290
+ constructor() {
1291
+ super("--resources-only creates the stage's resources and nothing else, and --skip-resources deploys without creating them. Run the first where the cloud credentials are (a CI runner), then the second where the stack runs.");
1292
+ this.name = "ResourcesOnlyAndSkipped";
1293
+ }
1294
+ };
1295
+ /** Apps were asked for by name that the workspace does not have. */
1296
+ var UnknownDeployApps = class extends require_errors.GkmError {
1297
+ apps;
1298
+ available;
1299
+ constructor(apps, available) {
1300
+ super(`Unknown apps: ${apps.join(", ")}\nAvailable apps: ${available.join(", ")}`);
1301
+ this.apps = apps;
1302
+ this.available = available;
1303
+ this.name = "UnknownDeployApps";
1304
+ }
1305
+ };
1306
+ /** Every app asked for deploys through some other target. */
1307
+ var NoDeployableApps = class extends require_errors.GkmError {
1308
+ stage;
1309
+ target;
1310
+ constructor(stage, target) {
1311
+ super(`No apps to deploy through "${target}": every selected app deploys somewhere else. Pick the target with --target, or set each app's deploy in gkm.config.ts.`);
1312
+ this.stage = stage;
1313
+ this.target = target;
1314
+ this.name = "NoDeployableApps";
1315
+ }
1316
+ };
1317
+ /** A build-only run through a target with no build phase. */
1318
+ var TargetBuildsNothing = class extends require_errors.GkmError {
1319
+ target;
1320
+ constructor(target) {
1321
+ super(`"${target}" has no build phase, so a build-only run would do nothing. Deploy it in full, or build through a target that builds images (compose).`);
1322
+ this.target = target;
1323
+ this.name = "TargetBuildsNothing";
1324
+ }
1325
+ };
1326
+ /** A failed rollback, after the failure that called for it. */
1327
+ var RollbackFailed = class extends Error {
1328
+ target;
1329
+ failure;
1330
+ constructor(target, failure, cause) {
1331
+ super(`Deploying through "${target}" failed, and so did rolling it back: ${cause instanceof Error ? cause.message : String(cause)}. The stage may be part-released; deploy again, or roll it back by hand. The first failure: ${failure instanceof Error ? failure.message : String(failure)}`, { cause });
1332
+ this.target = target;
1333
+ this.failure = failure;
1334
+ this.name = "RollbackFailed";
1335
+ }
1336
+ };
1337
+ /**
1338
+ * Generate image tag from stage and timestamp
1339
+ */
1340
+ function generateTag(stage) {
1341
+ return `${stage}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}`;
1342
+ }
1343
+ /** Why an app that deploys through another target is left out. */
1344
+ function elsewhere(target, stage) {
1345
+ const instead = require_define.builtinTarget(target)?.instead?.(stage);
1346
+ if (instead) return `it deploys through "${target}" — ${instead}`;
1347
+ return `it deploys through "${target}" — run \`gkm deploy --target ${target} --stage ${stage}\``;
1348
+ }
1349
+ /**
1350
+ * Deploy a workspace's stage through its target.
1351
+ *
1352
+ * The engine under `deploy()` and `gkm deploy`. It never prompts and never
1353
+ * exits: credentials come from `ctx.credentials`, progress goes to
1354
+ * `ctx.emit` and to `output`, and every failure is thrown.
1355
+ *
1356
+ * @internal
1357
+ */
1358
+ async function runDeploy(source, request, ctx) {
1359
+ const { stage } = request;
1360
+ const redactor = ctx.redactor ?? new Redactor();
1361
+ const emit = (event) => ctx.emit(event.type === "log" ? {
1362
+ ...event,
1363
+ message: redactor.redact(event.message)
1364
+ } : event);
1365
+ /** Run one phase between its events. */
1366
+ const phase = async (name, body) => {
1367
+ ctx.signal?.throwIfAborted();
1368
+ emit({
1369
+ type: "phase.started",
1370
+ phase: name
1371
+ });
1372
+ try {
1373
+ const value = await body();
1374
+ emit({
1375
+ type: "phase.finished",
1376
+ phase: name
1377
+ });
1378
+ return value;
1379
+ } catch (error) {
1380
+ emit({
1381
+ type: "phase.failed",
1382
+ phase: name,
1383
+ error: require_sniffer.eventError(error)
1384
+ });
1385
+ throw error;
1386
+ }
1387
+ };
1388
+ ctx.signal?.throwIfAborted();
1389
+ emit({
1390
+ type: "phase.started",
1391
+ phase: "validate"
1392
+ });
1393
+ let prepared;
1394
+ try {
1395
+ prepared = await prepare(source, request, ctx, emit, redactor);
1396
+ } catch (error) {
1397
+ emit({
1398
+ type: "phase.failed",
1399
+ phase: "validate",
1400
+ error: require_sniffer.eventError(error)
1401
+ });
1402
+ throw error;
1403
+ }
1404
+ const { resolved, phaseCtx, store } = prepared;
1405
+ const { target } = resolved;
1406
+ const resources = !ctx.buildOnly && !request.skipResources && phaseCtx.stage !== phaseCtx.workspace.stages.local;
1407
+ const provision = async () => {
1408
+ if (!request.skipDns && resolved.target.runtime === "server") try {
1409
+ await require_dns.dnsCredentials(phaseCtx.stage, require_dns.stageDnsDomains(phaseCtx.stage, phaseCtx.workspace.domains, phaseCtx.workspace.dns), ctx.credentials);
1410
+ } catch (error) {
1411
+ emit({
1412
+ type: "phase.failed",
1413
+ phase: "validate",
1414
+ error: require_sniffer.eventError(error)
1415
+ });
1416
+ throw error;
1417
+ }
1418
+ await provisionResources(phaseCtx, request, ctx, store, emit);
1419
+ };
1420
+ if (ctx.dryRun) {
1421
+ if (resources) await provision();
1422
+ if (request.resourcesOnly) return resourcesOnly(target, phaseCtx, emit);
1423
+ const run = await validate(phaseCtx, emit, () => readyToDeploy(target, phaseCtx));
1424
+ await phase("plan", () => target.plan(phaseCtx, run));
1425
+ return target.result(phaseCtx, run);
1426
+ }
1427
+ if (ctx.buildOnly) {
1428
+ if (!target.build) throw new TargetBuildsNothing(resolved.name);
1429
+ const run = await validate(phaseCtx, emit, () => target.validate(phaseCtx));
1430
+ await phase("build", () => target.build(phaseCtx, run));
1431
+ return target.result(phaseCtx, run);
1432
+ }
1433
+ let lock;
1434
+ try {
1435
+ require_sniffer.assertStateOutlivesRun(phaseCtx.workspace, stage, "deploy");
1436
+ lock = await store.lock(stage, { operation: "deploy" });
1437
+ } catch (error) {
1438
+ emit({
1439
+ type: "phase.failed",
1440
+ phase: "validate",
1441
+ error: require_sniffer.eventError(error)
1442
+ });
1443
+ throw error;
1444
+ }
1445
+ try {
1446
+ if (resources) await provision();
1447
+ if (request.resourcesOnly) return resourcesOnly(target, phaseCtx, emit);
1448
+ const run = await validate(phaseCtx, emit, () => readyToDeploy(target, phaseCtx));
1449
+ if (target.provision) await phase("provision", () => target.provision(phaseCtx, run));
1450
+ if (target.build) await phase("build", () => target.build(phaseCtx, run));
1451
+ let releasing = "release";
1452
+ try {
1453
+ await phase("release", () => target.release(phaseCtx, run));
1454
+ releasing = "verify";
1455
+ if (target.verify) await phase("verify", () => target.verify(phaseCtx, run));
1456
+ } catch (error) {
1457
+ if (ctx.signal?.aborted || !target.capabilities.rollback) throw error;
1458
+ if (!target.rollback) throw error;
1459
+ try {
1460
+ await phase("rollback", () => target.rollback(phaseCtx, run, {
1461
+ phase: releasing,
1462
+ error
1463
+ }));
1464
+ } catch (rollbackError) {
1465
+ throw new RollbackFailed(resolved.name, error, rollbackError);
1466
+ }
1467
+ throw error;
1468
+ }
1469
+ return await target.result(phaseCtx, run);
1470
+ } finally {
1471
+ await lock.release();
1472
+ }
1473
+ }
1474
+ /**
1475
+ * The stage's providers, run inside the validate phase. A dry run plans them
1476
+ * and, so the checks after it see the stage as the run would leave it, reads
1477
+ * the keys they would write as placeholders.
1478
+ */
1479
+ async function provisionResources(phaseCtx, request, ctx, store, emit) {
1480
+ try {
1481
+ const reports = await provisionStage({
1482
+ workspace: phaseCtx.workspace,
1483
+ stage: phaseCtx.stage,
1484
+ manifest: phaseCtx.manifest,
1485
+ runnables: phaseCtx.runnables ?? {},
1486
+ secrets: phaseCtx.secrets,
1487
+ state: store,
1488
+ dryRun: ctx.dryRun,
1489
+ ...request.rotateKeys ? { rotateKeys: true } : {},
1490
+ ...request.retireOldKeys ? { retireOldKeys: true } : {},
1491
+ ...ctx.home ? { home: ctx.home } : {},
1492
+ log: (line) => phaseCtx.logger.info(line)
1493
+ });
1494
+ if (!ctx.dryRun) return;
1495
+ const planned = reports.flatMap((r) => r.planned);
1496
+ if (planned.length === 0) return;
1497
+ const secrets = phaseCtx.secrets;
1498
+ phaseCtx.secrets = {
1499
+ ...secrets,
1500
+ async read() {
1501
+ const stored = await secrets.read() ?? require_seeds.initStageSecrets(phaseCtx.stage);
1502
+ const custom = { ...stored.custom };
1503
+ for (const key of planned) custom[key] ??= PLANNED_BY_THE_DEPLOY;
1504
+ return {
1505
+ ...stored,
1506
+ custom
1507
+ };
1508
+ }
1509
+ };
1510
+ } catch (error) {
1511
+ emit({
1512
+ type: "phase.failed",
1513
+ phase: "validate",
1514
+ error: require_sniffer.eventError(error)
1515
+ });
1516
+ throw error;
1517
+ }
1518
+ }
1519
+ /** What a dry run reads for a key its providers would write. */
1520
+ const PLANNED_BY_THE_DEPLOY = "s3://planned-by-this-deploy";
1521
+ /** `--resources-only`: the target's own resources, and nothing else. */
1522
+ async function resourcesOnly(target, phaseCtx, emit) {
1523
+ try {
1524
+ if (target.resources) await target.resources(phaseCtx);
1525
+ } catch (error) {
1526
+ emit({
1527
+ type: "phase.failed",
1528
+ phase: "validate",
1529
+ error: require_sniffer.eventError(error)
1530
+ });
1531
+ throw error;
1532
+ }
1533
+ emit({
1534
+ type: "phase.finished",
1535
+ phase: "validate"
1536
+ });
1537
+ return resourcesResult(phaseCtx);
1538
+ }
1539
+ /** A `--resources-only` run: no app was deployed. */
1540
+ function resourcesResult(phaseCtx) {
1541
+ return {
1542
+ apps: [],
1543
+ projectId: "",
1544
+ successCount: 0,
1545
+ failedCount: 0,
1546
+ stage: phaseCtx.stage,
1547
+ identity: phaseCtx.identity.key,
1548
+ tag: phaseCtx.tag,
1549
+ dryRun: phaseCtx.dryRun,
1550
+ environmentId: "",
1551
+ skipped: [...phaseCtx.skipped],
1552
+ urls: {},
1553
+ changes: []
1554
+ };
1555
+ }
1556
+ /**
1557
+ * What a deploy validates: the stage ready to be deployed — every key it
1558
+ * needs, read as its providers left them — then what the target would run,
1559
+ * then whatever only the target checks. A build-only run validates the
1560
+ * target's run alone: it calls neither readiness check.
1561
+ */
1562
+ async function readyToDeploy(target, phaseCtx) {
1563
+ if (target.runtime === "server") await assertStageReady(phaseCtx);
1564
+ const run = await target.validate(phaseCtx);
1565
+ await target.ready?.(phaseCtx, run);
1566
+ return run;
1567
+ }
1568
+ /** `body`, then the run's `deploy.started`, inside the validate phase. */
1569
+ async function validate(phaseCtx, emit, body) {
1570
+ try {
1571
+ const run = await body();
1572
+ const skipped = new Set(phaseCtx.skipped.map((s) => s.app));
1573
+ emit({
1574
+ type: "deploy.started",
1575
+ stage: phaseCtx.stage,
1576
+ target: phaseCtx.target,
1577
+ identity: phaseCtx.identity.key,
1578
+ tag: phaseCtx.tag,
1579
+ apps: phaseCtx.apps.filter((app) => !skipped.has(app)),
1580
+ dryRun: phaseCtx.dryRun
1581
+ });
1582
+ emit({
1583
+ type: "phase.finished",
1584
+ phase: "validate"
1585
+ });
1586
+ return run;
1587
+ } catch (error) {
1588
+ emit({
1589
+ type: "phase.failed",
1590
+ phase: "validate",
1591
+ error: require_sniffer.eventError(error)
1592
+ });
1593
+ throw error;
1594
+ }
1595
+ }
1596
+ /** Everything the phases are handed, worked out before the first of them. */
1597
+ async function prepare(source, request, ctx, emit, redactor) {
1598
+ const { stage } = request;
1599
+ if (request.resourcesOnly && request.skipResources) throw new ResourcesOnlyAndSkipped();
1600
+ const configured = typeof source === "function" ? await source() : source;
1601
+ const local = stage === configured.stages.local;
1602
+ if (!local) require_workspace.assertDeployedStage(configured.stages, stage);
1603
+ const targetName = request.target ?? configured.deploy?.default ?? "dokploy";
1604
+ const resolved = await require_resolve.resolveTarget(targetName, {
1605
+ workspace: configured,
1606
+ stage,
1607
+ ...ctx.targets ? { host: ctx.targets } : {}
1608
+ });
1609
+ if (local && !resolved.target.capabilities.localStage) require_workspace.assertDeployedStage(configured.stages, stage);
1610
+ const options = await require_resolve.parseTargetOptions(resolved);
1611
+ const allowDevServices = request.allowDevServices === true;
1612
+ if (allowDevServices && resolved.target.runtime === "aws") throw new require_seeds.DevServicesNeedServerTarget(targetName);
1613
+ const runnables = {};
1614
+ const background = {};
1615
+ const manifest = await require_discover.discover({
1616
+ patterns: require_seeds.constructGlobs(configured),
1617
+ cwd: configured.root,
1618
+ runnables,
1619
+ background
1620
+ });
1621
+ require_workspace.resolveStageTelemetry({
1622
+ ...configured.deploy?.telemetry ? { telemetry: configured.deploy.telemetry } : {},
1623
+ stage,
1624
+ local,
1625
+ target: targetName,
1626
+ runtime: resolved.target.runtime,
1627
+ selfHosted: resolved.target.capabilities.selfHostedTelemetry === true,
1628
+ used: require_seeds.usesTelemetry(manifest)
1629
+ });
1630
+ const units = require_derive.derivedApps(manifest, configured);
1631
+ const workspace = Object.keys(units).length > 0 ? {
1632
+ ...configured,
1633
+ apps: units
1634
+ } : configured;
1635
+ const identity = require_seeds.deployIdentity(workspace, stage);
1636
+ const tag = request.tag ?? (resolved.target.tag ? await resolved.target.tag({
1637
+ cwd: workspace.root,
1638
+ stage
1639
+ }) : generateTag(stage));
1640
+ const buildOrder = require_workspace.getAppBuildOrder(workspace);
1641
+ let selected = buildOrder;
1642
+ if (request.apps && request.apps.length > 0) {
1643
+ const unknown = request.apps.filter((name) => !workspace.apps[name]);
1644
+ if (unknown.length > 0) throw new UnknownDeployApps(unknown, Object.keys(workspace.apps));
1645
+ selected = buildOrder.filter((name) => request.apps.includes(name));
1646
+ }
1647
+ const skipped = [];
1648
+ const skip = (app, reason) => {
1649
+ skipped.push({
1650
+ app,
1651
+ reason
1652
+ });
1653
+ emit({
1654
+ type: "app.skipped",
1655
+ app,
1656
+ reason
1657
+ });
1658
+ };
1659
+ const byDefault = configured.deploy?.default ?? "dokploy";
1660
+ const apps = selected.filter((name) => {
1661
+ const own = workspace.apps[name].resolvedDeployTarget;
1662
+ const deploysThrough = own === byDefault ? targetName : own;
1663
+ if (deploysThrough === targetName) return true;
1664
+ skip(name, elsewhere(deploysThrough, stage));
1665
+ return false;
1666
+ });
1667
+ if (apps.length === 0) throw new NoDeployableApps(stage, targetName);
1668
+ const store = await require_sniffer.createStateStore({
1669
+ config: workspace.state,
1670
+ workspaceRoot: workspace.root,
1671
+ workspaceName: workspace.name
1672
+ });
1673
+ const secrets = await deploySecrets(workspace, stage, redactor, { ...ctx.home ? { home: ctx.home } : {} });
1674
+ const line = (level) => (message) => emit({
1675
+ type: "log",
1676
+ level,
1677
+ message
1678
+ });
1679
+ const logger = {
1680
+ info: line("info"),
1681
+ warn: line("warn"),
1682
+ error: line("error")
1683
+ };
1684
+ return {
1685
+ resolved,
1686
+ phaseCtx: {
1687
+ target: targetName,
1688
+ cwd: workspace.root,
1689
+ stage,
1690
+ tag,
1691
+ tagGiven: request.tag !== void 0,
1692
+ apps,
1693
+ skipped,
1694
+ identity,
1695
+ workspace,
1696
+ manifest,
1697
+ runnables,
1698
+ background,
1699
+ options,
1700
+ dryRun: ctx.dryRun,
1701
+ atomic: request.atomic ?? false,
1702
+ allowDevServices,
1703
+ ...request.skipDns ? { skipDns: true } : {},
1704
+ ...request.skipResources ? { skipResources: true } : {},
1705
+ credentials: ctx.credentials,
1706
+ state: store,
1707
+ secrets,
1708
+ logger,
1709
+ signal: ctx.signal ?? new AbortController().signal,
1710
+ childOutput: ctx.childOutput ?? "inherit",
1711
+ emit,
1712
+ skip,
1713
+ name: (resource) => require_seeds.applicationName(identity, resource)
1714
+ },
1715
+ store
1716
+ };
1717
+ }
1718
+ //#endregion
1719
+ //#region src/deploy/deploy.ts
1720
+ /**
1721
+ * `deploy()`: a deploy as a library call.
1722
+ *
1723
+ * `gkm deploy` could only be driven from an interactive terminal: it prompted
1724
+ * for what it lacked and exited the process on failure, worked out of
1725
+ * `process.cwd()`, and reported progress by printing. Here the caller says
1726
+ * where the project is, hands over the credentials and a signal, and gets back
1727
+ * a run — events to iterate while it goes, and a structured result at the end.
1728
+ * Nothing below this asks a person anything or ends the process; `gkm deploy`
1729
+ * is a thin wrapper that does both.
1730
+ */
1731
+ /**
1732
+ * Every event a run emits, kept so that each iteration — however late it
1733
+ * starts — sees the run from its first event to its last.
1734
+ */
1735
+ var EventLog = class {
1736
+ events = [];
1737
+ closed = false;
1738
+ waiting = [];
1739
+ push(event) {
1740
+ this.events.push(event);
1741
+ this.wake();
1742
+ }
1743
+ close() {
1744
+ this.closed = true;
1745
+ this.wake();
1746
+ }
1747
+ wake() {
1748
+ const waiting = this.waiting;
1749
+ this.waiting = [];
1750
+ for (const resume of waiting) resume();
1751
+ }
1752
+ async *iterate() {
1753
+ let next = 0;
1754
+ while (true) if (next < this.events.length) yield this.events[next++];
1755
+ else if (this.closed) return;
1756
+ else await new Promise((resume) => this.waiting.push(resume));
1757
+ }
1758
+ };
1759
+ function forward(logger, level, message) {
1760
+ if (!logger) return;
1761
+ if (level === "info") logger.info(message);
1762
+ else if (level === "error" && logger.error) logger.error(message);
1763
+ else logger.warn(message);
1764
+ }
1765
+ /**
1766
+ * Deploy a project's stage.
1767
+ *
1768
+ * ```ts
1769
+ * import { deploy } from '@geekmidas/cli/deploy';
1770
+ *
1771
+ * const run = deploy({ cwd: '/srv/checkouts/shop', stage: 'production' });
1772
+ * for await (const event of run) {
1773
+ * if (event.type === 'app.deployed') console.log(event.app, event.url);
1774
+ * }
1775
+ * const result = await run.result;
1776
+ * ```
1777
+ *
1778
+ * The run starts at once; iterating it is optional, and an iteration started
1779
+ * late still sees every event from the first.
1780
+ */
1781
+ function deploy(input) {
1782
+ const log = new EventLog();
1783
+ const redactor = new Redactor();
1784
+ const emit = (event) => {
1785
+ const masked = event.type === "log" ? {
1786
+ ...event,
1787
+ message: redactor.redact(event.message)
1788
+ } : event;
1789
+ log.push(masked);
1790
+ if (masked.type === "log") forward(input.logger, masked.level, masked.message);
1791
+ };
1792
+ const ctx = {
1793
+ emit,
1794
+ credentials: input.credentials ?? require_credentials.storedCredentials({ home: input.home ?? require_run.gkmHome() }),
1795
+ dryRun: input.dryRun ?? false,
1796
+ ...input.buildOnly ? { buildOnly: true } : {},
1797
+ home: input.home ?? require_run.gkmHome(),
1798
+ redactor,
1799
+ ...input.signal ? { signal: input.signal } : {},
1800
+ ...input.childOutput ? { childOutput: input.childOutput } : {},
1801
+ ...input.targets ? { targets: input.targets } : {}
1802
+ };
1803
+ const result = require_discover.withOutput((level, message) => emit({
1804
+ type: "log",
1805
+ level,
1806
+ message
1807
+ }), async () => {
1808
+ try {
1809
+ input.signal?.throwIfAborted();
1810
+ const sandbox = input.sandbox ?? new require_local.LocalSandbox({ root: require_config.findWorkspaceRoot((0, node_path.resolve)(input.cwd)) });
1811
+ const deployed = await require_sandbox.withSandbox(sandbox, () => runDeploy(() => load(input, sandbox), {
1812
+ stage: input.stage,
1813
+ ...input.target ? { target: input.target } : {},
1814
+ ...input.tag ? { tag: input.tag } : {},
1815
+ ...input.apps ? { apps: input.apps } : {},
1816
+ ...input.atomic ? { atomic: true } : {},
1817
+ ...input.allowDevServices ? { allowDevServices: input.allowDevServices } : {},
1818
+ ...input.skipDns ? { skipDns: true } : {},
1819
+ ...input.resourcesOnly ? { resourcesOnly: true } : {},
1820
+ ...input.skipResources ? { skipResources: true } : {},
1821
+ ...input.rotateKeys ? { rotateKeys: true } : {},
1822
+ ...input.retireOldKeys ? { retireOldKeys: true } : {}
1823
+ }, ctx));
1824
+ emit({
1825
+ type: "deploy.finished",
1826
+ result: deployed
1827
+ });
1828
+ return deployed;
1829
+ } catch (error) {
1830
+ emit({
1831
+ type: "deploy.failed",
1832
+ error: require_sniffer.eventError(error)
1833
+ });
1834
+ throw error;
1835
+ } finally {
1836
+ log.close();
1837
+ }
1838
+ });
1839
+ result.catch(() => {});
1840
+ return {
1841
+ result,
1842
+ [Symbol.asyncIterator]: () => log.iterate()
1843
+ };
1844
+ }
1845
+ /**
1846
+ * The workspace at `input.cwd`. The stage is checked by the run, once it
1847
+ * knows the target: one that runs on this machine may take the local stage.
1848
+ */
1849
+ async function load(input, sandbox) {
1850
+ const { workspace } = await require_config.loadWorkspaceConfig((0, node_path.resolve)(input.cwd), { sandbox });
1851
+ return workspace;
1852
+ }
1853
+ //#endregion
1854
+ Object.defineProperty(exports, "IAM_USER_PATH", {
1855
+ enumerable: true,
1856
+ get: function() {
1857
+ return IAM_USER_PATH;
1858
+ }
1859
+ });
1860
+ Object.defineProperty(exports, "NoDeployableApps", {
1861
+ enumerable: true,
1862
+ get: function() {
1863
+ return NoDeployableApps;
1864
+ }
1865
+ });
1866
+ Object.defineProperty(exports, "RollbackFailed", {
1867
+ enumerable: true,
1868
+ get: function() {
1869
+ return RollbackFailed;
1870
+ }
1871
+ });
1872
+ Object.defineProperty(exports, "TargetBuildsNothing", {
1873
+ enumerable: true,
1874
+ get: function() {
1875
+ return TargetBuildsNothing;
1876
+ }
1877
+ });
1878
+ Object.defineProperty(exports, "UnknownDeployApps", {
1879
+ enumerable: true,
1880
+ get: function() {
1881
+ return UnknownDeployApps;
1882
+ }
1883
+ });
1884
+ Object.defineProperty(exports, "bucketName", {
1080
1885
  enumerable: true,
1081
1886
  get: function() {
1082
- return DeployJournal;
1887
+ return bucketName;
1083
1888
  }
1084
1889
  });
1085
- Object.defineProperty(exports, "provisionStage", {
1890
+ Object.defineProperty(exports, "deploy", {
1086
1891
  enumerable: true,
1087
1892
  get: function() {
1088
- return provisionStage;
1893
+ return deploy;
1089
1894
  }
1090
1895
  });
1091
- Object.defineProperty(exports, "verifyStageProviders", {
1896
+ Object.defineProperty(exports, "iamUserName", {
1092
1897
  enumerable: true,
1093
1898
  get: function() {
1094
- return verifyStageProviders;
1899
+ return iamUserName;
1095
1900
  }
1096
1901
  });
1097
1902
 
1098
- //# sourceMappingURL=providers-BFeP_mYw.cjs.map
1903
+ //# sourceMappingURL=deploy-Bw1FjX_x.cjs.map