@geekmidas/cli 10.0.0-alpha.66 → 10.0.0-alpha.68

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 (151) hide show
  1. package/README.md +110 -178
  2. package/dist/{HostingerProvider-CY_VpVud.mjs → HostingerProvider-D85ayzTi.mjs} +2 -2
  3. package/dist/{HostingerProvider-CY_VpVud.mjs.map → HostingerProvider-D85ayzTi.mjs.map} +1 -1
  4. package/dist/{HostingerProvider-BznqRC2S.cjs → HostingerProvider-dxkwynSs.cjs} +2 -2
  5. package/dist/{HostingerProvider-BznqRC2S.cjs.map → HostingerProvider-dxkwynSs.cjs.map} +1 -1
  6. package/dist/{LegacyStateStore-BFcTT2QL.cjs → LegacyStateStore-BZiO9-Lw.cjs} +2 -2
  7. package/dist/{LegacyStateStore-BFcTT2QL.cjs.map → LegacyStateStore-BZiO9-Lw.cjs.map} +1 -1
  8. package/dist/{LegacyStateStore-CFheFo62.mjs → LegacyStateStore-C39UKwmf.mjs} +2 -2
  9. package/dist/{LegacyStateStore-CFheFo62.mjs.map → LegacyStateStore-C39UKwmf.mjs.map} +1 -1
  10. package/dist/{LocalStateStore-BVUexSvu.cjs → LocalStateStore-DHVsZLyF.cjs} +2 -2
  11. package/dist/{LocalStateStore-BVUexSvu.cjs.map → LocalStateStore-DHVsZLyF.cjs.map} +1 -1
  12. package/dist/{LocalStateStore-Bm3x9oOg.mjs → LocalStateStore-Dk3Wbvzk.mjs} +2 -2
  13. package/dist/{LocalStateStore-Bm3x9oOg.mjs.map → LocalStateStore-Dk3Wbvzk.mjs.map} +1 -1
  14. package/dist/{S3StateStore-CoXBhILd.cjs → S3StateStore--4tYVMAL.cjs} +2 -2
  15. package/dist/{S3StateStore-CoXBhILd.cjs.map → S3StateStore--4tYVMAL.cjs.map} +1 -1
  16. package/dist/{S3StateStore-BFHuctWM.mjs → S3StateStore-B_ZF9eHt.mjs} +2 -2
  17. package/dist/{S3StateStore-BFHuctWM.mjs.map → S3StateStore-B_ZF9eHt.mjs.map} +1 -1
  18. package/dist/{SSMStateStore-BqCA9TP2.cjs → SSMStateStore-ACZ8hRvZ.cjs} +2 -2
  19. package/dist/{SSMStateStore-BqCA9TP2.cjs.map → SSMStateStore-ACZ8hRvZ.cjs.map} +1 -1
  20. package/dist/{SSMStateStore-C1kvHScY.mjs → SSMStateStore-DjPuKqrm.mjs} +2 -2
  21. package/dist/{SSMStateStore-C1kvHScY.mjs.map → SSMStateStore-DjPuKqrm.mjs.map} +1 -1
  22. package/dist/{bundler-Dvaiud0h.mjs → bundler-C-w7aGoZ.mjs} +20 -5
  23. package/dist/bundler-C-w7aGoZ.mjs.map +1 -0
  24. package/dist/{bundler-orRqUJNZ.cjs → bundler-C1pnNrR0.cjs} +20 -5
  25. package/dist/bundler-C1pnNrR0.cjs.map +1 -0
  26. package/dist/{cli-D1JkkOwg.cjs → cli-BLyD4c0O.cjs} +14 -5
  27. package/dist/cli-BLyD4c0O.cjs.map +1 -0
  28. package/dist/{cli-CfHm0AO7.mjs → cli-Ce4pLL5O.mjs} +14 -5
  29. package/dist/cli-Ce4pLL5O.mjs.map +1 -0
  30. package/dist/{compose-CNQL8BnO.mjs → compose-DFxuYhn6.mjs} +291 -152
  31. package/dist/compose-DFxuYhn6.mjs.map +1 -0
  32. package/dist/{compose-jrLy7KGO.cjs → compose-DvsgumY2.cjs} +298 -159
  33. package/dist/compose-DvsgumY2.cjs.map +1 -0
  34. package/dist/{config-4XFxX1al.d.cts → config-BnA0kPTY.d.cts} +3 -3
  35. package/dist/{config-4XFxX1al.d.cts.map → config-BnA0kPTY.d.cts.map} +1 -1
  36. package/dist/{config-UtKzhpFb.d.mts → config-CxEp_g7j.d.mts} +3 -3
  37. package/dist/{config-UtKzhpFb.d.mts.map → config-CxEp_g7j.d.mts.map} +1 -1
  38. package/dist/config.d.cts +3 -3
  39. package/dist/config.d.mts +3 -3
  40. package/dist/{credentials-Bzbg23n8.cjs → credentials-BVs7mrtw.cjs} +239 -3
  41. package/dist/credentials-BVs7mrtw.cjs.map +1 -0
  42. package/dist/{credentials-Dq1MnWQf.mjs → credentials-pAtB70k3.mjs} +223 -5
  43. package/dist/credentials-pAtB70k3.mjs.map +1 -0
  44. package/dist/deploy/public.cjs +21 -17
  45. package/dist/deploy/public.cjs.map +1 -1
  46. package/dist/deploy/public.d.cts +15 -4
  47. package/dist/deploy/public.d.cts.map +1 -1
  48. package/dist/deploy/public.d.mts +15 -4
  49. package/dist/deploy/public.d.mts.map +1 -1
  50. package/dist/deploy/public.mjs +10 -10
  51. package/dist/{deploy-B7aJi_Ah.cjs → deploy-C08GONYW.cjs} +14 -10
  52. package/dist/deploy-C08GONYW.cjs.map +1 -0
  53. package/dist/{deploy-DWn7YfIc.mjs → deploy-D-EVOWvu.mjs} +11 -7
  54. package/dist/deploy-D-EVOWvu.mjs.map +1 -0
  55. package/dist/{dokploy-B4LcYG1E.cjs → dokploy-CZ6nfSV9.cjs} +2 -2
  56. package/dist/{dokploy-B4LcYG1E.cjs.map → dokploy-CZ6nfSV9.cjs.map} +1 -1
  57. package/dist/{dokploy-DalwLML5.mjs → dokploy-DU-XJsoT.mjs} +2 -2
  58. package/dist/{dokploy-DalwLML5.mjs.map → dokploy-DU-XJsoT.mjs.map} +1 -1
  59. package/dist/{encryption-3KlGS1sl.cjs → encryption-CCcBSLZs.cjs} +2 -2
  60. package/dist/{encryption-3KlGS1sl.cjs.map → encryption-CCcBSLZs.cjs.map} +1 -1
  61. package/dist/{encryption-CPfENwWO.mjs → encryption-DSiLau1-.mjs} +2 -2
  62. package/dist/{encryption-CPfENwWO.mjs.map → encryption-DSiLau1-.mjs.map} +1 -1
  63. package/dist/{engine-DR6KurWX.cjs → engine-BM9Dy_DT.cjs} +141 -209
  64. package/dist/engine-BM9Dy_DT.cjs.map +1 -0
  65. package/dist/{engine-CunvOG3s.mjs → engine-llWnMZH5.mjs} +137 -205
  66. package/dist/engine-llWnMZH5.mjs.map +1 -0
  67. package/dist/{github-BJ5gh9bw.cjs → github-ZoMam0OH.cjs} +2 -2
  68. package/dist/{github-BJ5gh9bw.cjs.map → github-ZoMam0OH.cjs.map} +1 -1
  69. package/dist/{github-MXA9v7Ge.mjs → github-yy6WpHIl.mjs} +2 -2
  70. package/dist/{github-MXA9v7Ge.mjs.map → github-yy6WpHIl.mjs.map} +1 -1
  71. package/dist/{index-DD1FfUHh.d.mts → index-CkX89m6S.d.mts} +2 -2
  72. package/dist/{index-CyApaHVe.d.cts.map → index-CkX89m6S.d.mts.map} +1 -1
  73. package/dist/{index-CyApaHVe.d.cts → index-EvZBkycu.d.cts} +2 -2
  74. package/dist/{index-DD1FfUHh.d.mts.map → index-EvZBkycu.d.cts.map} +1 -1
  75. package/dist/index.cjs +59 -70
  76. package/dist/index.cjs.map +1 -1
  77. package/dist/index.mjs +55 -66
  78. package/dist/index.mjs.map +1 -1
  79. package/dist/{migrate-BJBcm4sG.mjs → migrate-BWPuwiXk.mjs} +2 -2
  80. package/dist/{migrate-BJBcm4sG.mjs.map → migrate-BWPuwiXk.mjs.map} +1 -1
  81. package/dist/{migrate-CF4J4GQS.cjs → migrate-tOwxQBTI.cjs} +2 -2
  82. package/dist/{migrate-CF4J4GQS.cjs.map → migrate-tOwxQBTI.cjs.map} +1 -1
  83. package/dist/openapi.d.cts +1 -1
  84. package/dist/openapi.d.mts +1 -1
  85. package/dist/reconcile/public.d.cts +1 -1
  86. package/dist/reconcile/public.d.mts +1 -1
  87. package/dist/{resolve-CVmch0wI.cjs → resolve-BymzGtuT.cjs} +4 -4
  88. package/dist/{resolve-CVmch0wI.cjs.map → resolve-BymzGtuT.cjs.map} +1 -1
  89. package/dist/{resolve-Db0tNlrW.mjs → resolve-pIvXlZ1h.mjs} +4 -4
  90. package/dist/{resolve-Db0tNlrW.mjs.map → resolve-pIvXlZ1h.mjs.map} +1 -1
  91. package/dist/{rollback-DvAo4OKS.mjs → rollback-ZlsbQOvj.mjs} +5 -6
  92. package/dist/{rollback-DvAo4OKS.mjs.map → rollback-ZlsbQOvj.mjs.map} +1 -1
  93. package/dist/{rollback-DxJK84hy.cjs → rollback-zdfi6Reg.cjs} +6 -7
  94. package/dist/{rollback-DxJK84hy.cjs.map → rollback-zdfi6Reg.cjs.map} +1 -1
  95. package/dist/run-BJLIerMM.mjs +133 -0
  96. package/dist/run-BJLIerMM.mjs.map +1 -0
  97. package/dist/run-fVZ-rLnc.cjs +174 -0
  98. package/dist/run-fVZ-rLnc.cjs.map +1 -0
  99. package/dist/{runtime-BRqFOvPM.d.cts → runtime-B3jNgeP-.d.mts} +2 -2
  100. package/dist/{runtime-BRqFOvPM.d.cts.map → runtime-B3jNgeP-.d.mts.map} +1 -1
  101. package/dist/{runtime-CEk5n4VH.d.mts → runtime-DWThEP-r.d.cts} +2 -2
  102. package/dist/{runtime-CEk5n4VH.d.mts.map → runtime-DWThEP-r.d.cts.map} +1 -1
  103. package/dist/{sniffer-BAQhLEsI.mjs → sniffer-BdFeLSmA.mjs} +8 -60
  104. package/dist/sniffer-BdFeLSmA.mjs.map +1 -0
  105. package/dist/{sniffer-5xmrkh2a.cjs → sniffer-D66HIvi9.cjs} +7 -77
  106. package/dist/sniffer-D66HIvi9.cjs.map +1 -0
  107. package/dist/{sst-B2HbrDR3.mjs → sst-DRi3H5TB.mjs} +3 -3
  108. package/dist/{sst-B2HbrDR3.mjs.map → sst-DRi3H5TB.mjs.map} +1 -1
  109. package/dist/{sst-DcfsVH6x.cjs → sst-hBrKouBy.cjs} +5 -5
  110. package/dist/{sst-DcfsVH6x.cjs.map → sst-hBrKouBy.cjs.map} +1 -1
  111. package/dist/{state-uuYqnRVO.mjs → state-Bn5JDMFT.mjs} +1717 -1334
  112. package/dist/state-Bn5JDMFT.mjs.map +1 -0
  113. package/dist/{state-Y6ATakMX.cjs → state-CHZqCDRC.cjs} +2863 -2354
  114. package/dist/state-CHZqCDRC.cjs.map +1 -0
  115. package/dist/target/public.cjs +1 -1
  116. package/dist/target/public.d.cts +2 -2
  117. package/dist/target/public.d.mts +2 -2
  118. package/dist/target/public.mjs +1 -1
  119. package/dist/{terminal-DUhcZ1ND.mjs → terminal-C3cv-OQu.mjs} +2 -2
  120. package/dist/{terminal-DUhcZ1ND.mjs.map → terminal-C3cv-OQu.mjs.map} +1 -1
  121. package/dist/{terminal-CHy_MdjG.cjs → terminal-DjzgLu6m.cjs} +2 -2
  122. package/dist/{terminal-CHy_MdjG.cjs.map → terminal-DjzgLu6m.cjs.map} +1 -1
  123. package/dist/{types-CSw2w69a.d.mts → types-CZdCxUCK.d.cts} +64 -2
  124. package/dist/types-CZdCxUCK.d.cts.map +1 -0
  125. package/dist/{types-D5WIxRDP.d.cts → types-Da0E3Qv7.d.mts} +63 -3
  126. package/dist/types-Da0E3Qv7.d.mts.map +1 -0
  127. package/dist/workspace/index.d.cts +2 -2
  128. package/dist/workspace/index.d.mts +2 -2
  129. package/package.json +13 -13
  130. package/dist/bundler-Dvaiud0h.mjs.map +0 -1
  131. package/dist/bundler-orRqUJNZ.cjs.map +0 -1
  132. package/dist/cli-CfHm0AO7.mjs.map +0 -1
  133. package/dist/cli-D1JkkOwg.cjs.map +0 -1
  134. package/dist/compose-CNQL8BnO.mjs.map +0 -1
  135. package/dist/compose-jrLy7KGO.cjs.map +0 -1
  136. package/dist/credentials-Bzbg23n8.cjs.map +0 -1
  137. package/dist/credentials-Dq1MnWQf.mjs.map +0 -1
  138. package/dist/deploy-B7aJi_Ah.cjs.map +0 -1
  139. package/dist/deploy-DWn7YfIc.mjs.map +0 -1
  140. package/dist/engine-CunvOG3s.mjs.map +0 -1
  141. package/dist/engine-DR6KurWX.cjs.map +0 -1
  142. package/dist/local-BdH4XN0E.cjs +0 -409
  143. package/dist/local-BdH4XN0E.cjs.map +0 -1
  144. package/dist/local-CWR4Y_kW.mjs +0 -350
  145. package/dist/local-CWR4Y_kW.mjs.map +0 -1
  146. package/dist/sniffer-5xmrkh2a.cjs.map +0 -1
  147. package/dist/sniffer-BAQhLEsI.mjs.map +0 -1
  148. package/dist/state-Y6ATakMX.cjs.map +0 -1
  149. package/dist/state-uuYqnRVO.mjs.map +0 -1
  150. package/dist/types-CSw2w69a.d.mts.map +0 -1
  151. package/dist/types-D5WIxRDP.d.cts.map +0 -1
@@ -1,197 +1,19 @@
1
- const require_local = require("./local-BdH4XN0E.cjs");
2
- const require_credentials = require("./credentials-Bzbg23n8.cjs");
1
+ const require_credentials = require("./credentials-BVs7mrtw.cjs");
3
2
  const require_schemas = require("./schemas-RUlKHu27.cjs");
4
3
  const require_discover = require("./discover-OEfZ9OkA.cjs");
5
4
  const require_sandbox = require("./sandbox-CL--ZDui.cjs");
6
5
  const require_derive = require("./derive-DAbo49sm.cjs");
7
6
  const require_workspace = require("./workspace-ON-bqiJz.cjs");
8
- const require_state = require("./state-Y6ATakMX.cjs");
9
- const require_sniffer = require("./sniffer-5xmrkh2a.cjs");
7
+ const require_state = require("./state-CHZqCDRC.cjs");
8
+ const require_sniffer = require("./sniffer-D66HIvi9.cjs");
10
9
  const require_provider = require("./provider-B3Sv_a74.cjs");
11
10
  let node_path = require("node:path");
12
- let node_fs_promises = require("node:fs/promises");
13
- let node_os = require("node:os");
14
11
  let _geekmidas_manifest = require("@geekmidas/manifest");
15
12
  let node_crypto = require("node:crypto");
16
13
  let _geekmidas_db_pg_roles = require("@geekmidas/db/pg/roles");
17
14
  let pg = require("pg");
18
15
  let _geekmidas_cache_postgres = require("@geekmidas/cache/postgres");
19
16
  let node_dns_promises = require("node:dns/promises");
20
- //#region src/deploy/docker.ts
21
- const logger$3 = require_discover.output;
22
- /**
23
- * The id the Dockerfile templates mount the encrypted credentials under:
24
- * `RUN --mount=type=secret,id=gkm_credentials`.
25
- */
26
- const CREDENTIALS_SECRET_ID = "gkm_credentials";
27
- /**
28
- * Get the full image reference
29
- */
30
- function getImageRef(registry, imageName, tag) {
31
- if (registry) return `${registry}/${imageName}:${tag}`;
32
- return `${imageName}:${tag}`;
33
- }
34
- /**
35
- * The `docker build` argv for an image.
36
- *
37
- * One element per value, so nothing in a ref or a build arg is read by a
38
- * shell, and `--opt=value` rather than `--opt value`, so a value that starts
39
- * with `-` cannot be taken for one of docker's own flags.
40
- *
41
- * @internal Exported for testing
42
- */
43
- function dockerBuildArgs(options) {
44
- const { dockerfilePath, imageRef, buildArgs = [], credentialsFile } = options;
45
- return [
46
- "build",
47
- "--platform=linux/amd64",
48
- `--file=${dockerfilePath}`,
49
- `--tag=${imageRef}`,
50
- ...buildArgs.map((arg) => `--build-arg=${arg}`),
51
- ...credentialsFile ? [`--secret=id=${CREDENTIALS_SECRET_ID},src=${credentialsFile}`] : [],
52
- "."
53
- ];
54
- }
55
- /**
56
- * Write the encrypted credentials where `docker build --secret` reads them.
57
- *
58
- * Two lines — ciphertext, then IV — so a template can split them with `sed`
59
- * in any base image. Owner-only, in a directory of its own, and the returned
60
- * cleanup removes both whatever the build did.
61
- *
62
- * @internal Exported for testing
63
- */
64
- async function writeCredentialsFile(credentials) {
65
- const dir = await (0, node_fs_promises.mkdtemp)((0, node_path.join)((0, node_os.tmpdir)(), "gkm-credentials-"));
66
- const path = (0, node_path.join)(dir, CREDENTIALS_SECRET_ID);
67
- await (0, node_fs_promises.writeFile)(path, `${credentials.encrypted}\n${credentials.iv}\n`, { mode: 384 });
68
- await (0, node_fs_promises.chmod)(path, 384);
69
- return {
70
- path,
71
- cleanup: () => (0, node_fs_promises.rm)(dir, {
72
- recursive: true,
73
- force: true
74
- })
75
- };
76
- }
77
- /**
78
- * Build Docker image
79
- * @param imageRef - Full image reference (registry/name:tag)
80
- * @param buildArgs - Build arguments to pass to docker build
81
- * @param credentials - Encrypted credentials, passed as a build secret
82
- */
83
- async function buildImage(imageRef, buildArgs, credentials, { cwd, dockerfile, signal, stdio }) {
84
- logger$3.log(`\n🔨 Building Docker image: ${imageRef}`);
85
- logger$3.log(" Generating Dockerfile...");
86
- await require_state.dockerCommand({
87
- slim: true,
88
- cwd
89
- });
90
- const dockerfilePath = dockerfile;
91
- const secret = credentials ? await writeCredentialsFile(credentials) : void 0;
92
- try {
93
- await require_local.run("docker", dockerBuildArgs({
94
- dockerfilePath,
95
- imageRef,
96
- buildArgs,
97
- credentialsFile: secret?.path
98
- }), {
99
- cwd,
100
- env: {
101
- ...process.env,
102
- DOCKER_BUILDKIT: "1"
103
- },
104
- ...signal ? { signal } : {},
105
- ...stdio ? { stdio } : {}
106
- });
107
- logger$3.log(`✅ Image built: ${imageRef}`);
108
- } catch (error) {
109
- throw new require_state.DockerBuildFailed(imageRef, error);
110
- } finally {
111
- await secret?.cleanup();
112
- }
113
- }
114
- /**
115
- * Push Docker image to registry
116
- */
117
- async function pushImage(imageRef, { cwd, signal, stdio }) {
118
- logger$3.log(`\n☁️ Pushing image: ${imageRef}`);
119
- try {
120
- await require_local.run("docker", ["push", imageRef], {
121
- cwd,
122
- ...signal ? { signal } : {},
123
- ...stdio ? { stdio } : {}
124
- });
125
- logger$3.log(`✅ Image pushed: ${imageRef}`);
126
- } catch (error) {
127
- throw new require_state.DockerPushFailed(imageRef, error);
128
- }
129
- }
130
- /**
131
- * The digest the registry gave a pushed image, `sha256:…`.
132
- *
133
- * A tag can be pushed over — by the next deploy, or by anything else that
134
- * shares the repository — and the digest is what says which image a stage
135
- * actually ran. `RepoDigests` has one entry per repository the image was
136
- * pushed to, so the one for this ref's repository is picked by name.
137
- *
138
- * @internal Exported for testing
139
- */
140
- async function pushedDigest(imageRef, { cwd, signal } = { cwd: process.cwd() }) {
141
- const repository = imageRef.split("@")[0].replace(/:[\w][\w.-]*$/, "");
142
- const output = await require_local.runOutput("docker", [
143
- "image",
144
- "inspect",
145
- "--format={{json .RepoDigests}}",
146
- imageRef
147
- ], {
148
- cwd,
149
- ...signal ? { signal } : {}
150
- });
151
- let digests;
152
- try {
153
- digests = JSON.parse(output.trim() || "[]");
154
- } catch {
155
- return;
156
- }
157
- if (!Array.isArray(digests)) return void 0;
158
- return digests.find((entry) => typeof entry === "string" && entry.startsWith(`${repository}@`))?.slice(repository.length + 1);
159
- }
160
- /**
161
- * Deploy using Docker (build and optionally push image)
162
- */
163
- async function deployDocker(options) {
164
- const { stage, tag, skipPush, masterKey, config, buildArgs, credentials } = options;
165
- const imageName = config.imageName;
166
- const imageRef = require_state.validateImageRef(getImageRef(config.registry, imageName, tag));
167
- const cwd = options.cwd ?? process.cwd();
168
- const docker = {
169
- cwd,
170
- dockerfile: (0, node_path.join)(cwd, require_state.dockerfileOf(config.appName ?? imageName, options.appPath ?? ".")),
171
- ...options.signal ? { signal: options.signal } : {},
172
- ...options.stdio ? { stdio: options.stdio } : {}
173
- };
174
- await buildImage(imageRef, buildArgs, credentials, docker);
175
- let digest;
176
- if (!skipPush) {
177
- if (!config.registry) logger$3.warn("\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts");
178
- else {
179
- await pushImage(imageRef, docker);
180
- digest = await pushedDigest(imageRef, docker);
181
- }
182
- }
183
- logger$3.log("\n✅ Docker deployment ready!");
184
- logger$3.log(`\n📋 Deployment details:`);
185
- logger$3.log(` Image: ${imageRef}`);
186
- logger$3.log(` Stage: ${stage}`);
187
- if (masterKey) logger$3.log(`\n🔐 Run the container with GKM_MASTER_KEY set to the key with fingerprint ${require_sniffer.keyFingerprint(masterKey)}.`);
188
- return {
189
- imageRef,
190
- ...digest ? { digest } : {},
191
- masterKey
192
- };
193
- }
194
- //#endregion
195
17
  //#region src/deploy/ownership.ts
196
18
  /**
197
19
  * Which Dokploy project a deploy is allowed to deploy into.
@@ -439,7 +261,7 @@ function filterSecretsForApp(stageSecrets, sniffedEnv) {
439
261
  * @returns Encrypted payload with master key
440
262
  */
441
263
  function encryptSecretsForApp(filteredSecrets) {
442
- const payload = require_sniffer.encryptSecrets(filteredSecrets.secrets);
264
+ const payload = require_state.encryptSecrets(filteredSecrets.secrets);
443
265
  return {
444
266
  appName: filteredSecrets.appName,
445
267
  payload,
@@ -685,34 +507,47 @@ const PROVISIONERS = {
685
507
  return { provides: { [(0, _geekmidas_manifest.provideKey)(declaration.id, "url")]: url.toString() } };
686
508
  },
687
509
  /**
688
- * A bucket, as a MinIO stack on the box.
510
+ * A bucket: the stage's own, or — allowed — a MinIO stack on the box.
511
+ *
512
+ * A deployed stage's bucket is an external one — S3, R2, any S3-compatible
513
+ * store — whose URL and key pair the stage's secrets hold. Only with
514
+ * `--allow-dev-services minio` does this target run MinIO for one, and
515
+ * then only for a bucket whose URL the stage did not set.
689
516
  *
690
517
  * Dokploy has first-class primitives for Postgres and Redis and none for
691
- * object storage, so this is the one kind whose infrastructure this target
692
- * *writes* rather than configures — a compose file with one service in it.
518
+ * object storage, so MinIO is the one kind whose infrastructure this
519
+ * target *writes* rather than configures — a compose file with one
520
+ * service in it.
693
521
  *
694
522
  * The service is named `cloudName(...)` like everything else, which is not
695
523
  * cosmetic here: containers on `dokploy-network` resolve each other by
696
524
  * service name, so the name is the address. Calling it `minio` would work
697
525
  * for exactly one project on the box and then collide.
698
526
  *
699
- * `s3://` carries no credentials, deliberately — deployed on AWS the SDK
700
- * reads them from an execution role, so a URL that embedded a key would be
701
- * one more thing to rotate and leak. There is no role here, so the same
702
- * chain reads `AWS_ACCESS_KEY_ID` beside the URL, exactly as it does
703
- * locally.
527
+ * A stage's own bucket URL may carry a key scoped to that bucket
528
+ * (`s3://KEY:SECRET@bucket`), which the client signs with; the shared
529
+ * `AWS_ACCESS_KEY_ID` pair is passed beside it when the stage set one, for
530
+ * a bucket whose URL has none. The MinIO this provisions uses that pair —
531
+ * the stage's, or one derived for it.
704
532
  */
705
533
  objects: async (declaration, context) => {
706
534
  if (declaration.kind !== "objects") throw new WrongKind(declaration.kind);
535
+ const key = (0, _geekmidas_manifest.provideKey)(declaration.id, "url");
536
+ const given = context.supplied?.[key];
537
+ if (given !== void 0) return { provides: {
538
+ [key]: given,
539
+ ...storageKeys(context.supplied)
540
+ } };
707
541
  const backend = context.storage ?? "minio";
708
542
  if (backend !== "minio") throw new UnprovisionableBucket(declaration.id, backend);
543
+ if (!context.devServices?.includes("minio")) throw notConfigured(declaration.id, "objects", context);
709
544
  const service = serviceName({
710
545
  stage: context.stage,
711
546
  app: context.scope ?? context.project
712
547
  }, declaration.id);
713
548
  const bucket = require_state.resourceName(declaration.id, declaration.kind, context.stage);
714
- const user = `${bucket}-root`;
715
- const password = derivedPassword(context, `objects:${declaration.id}`);
549
+ const user = context.supplied?.AWS_ACCESS_KEY_ID ?? `${bucket}-root`;
550
+ const password = context.supplied?.AWS_SECRET_ACCESS_KEY ?? derivedPassword(context, `objects:${declaration.id}`);
716
551
  const { compose } = await context.api.findOrCreateCompose(service, context.projectId, context.environmentId, minioCompose({
717
552
  service,
718
553
  bucket,
@@ -721,33 +556,67 @@ const PROVISIONERS = {
721
556
  }));
722
557
  await context.api.deployCompose(compose.composeId);
723
558
  return { provides: {
724
- [(0, _geekmidas_manifest.provideKey)(declaration.id, "url")]: s3Url(service, bucket),
559
+ [key]: s3Url(service, bucket),
725
560
  AWS_ACCESS_KEY_ID: user,
726
561
  AWS_SECRET_ACCESS_KEY: password,
727
- AWS_REGION: MINIO_REGION
562
+ AWS_REGION: context.supplied?.AWS_REGION ?? MINIO_REGION
728
563
  } };
729
564
  },
730
565
  /**
731
566
  * The address a bucket's objects are served on.
732
567
  *
733
- * Nothing is provisioned: Dokploy runs Traefik, so a second reverse proxy
734
- * behind the first would terminate TLS twice — which is why the local
735
- * target's Caddy has no equivalent here. What this resolves is the address,
736
- * and the `open` prefixes are applied to the bucket rather than to an edge,
737
- * so a policy is what makes them public wherever the bucket lives.
568
+ * The stage's own — a CDN, the bucket's domain — when its secrets hold
569
+ * one, which a bucket that is not MinIO's needs.
738
570
  *
739
- * Until a Traefik rule exists it answers on MinIO directly, path-style,
740
- * which is honest about the shape it has today: the bucket is in the path
741
- * rather than fronted by a host of its own.
571
+ * Over MinIO nothing is provisioned: Dokploy runs Traefik, so a second
572
+ * reverse proxy behind the first would terminate TLS twice — which is why
573
+ * the local target's Caddy has no equivalent here. What this resolves is
574
+ * the address, and the `open` prefixes are applied to the bucket rather
575
+ * than to an edge, so a policy is what makes them public wherever the
576
+ * bucket lives. Until a Traefik rule exists it answers on MinIO directly,
577
+ * path-style, which is honest about the shape it has today: the bucket is
578
+ * in the path rather than fronted by a host of its own.
742
579
  */
743
580
  "file-server": async (declaration, context) => {
744
581
  if (declaration.kind !== "file-server") throw new WrongKind(declaration.kind);
582
+ const key = (0, _geekmidas_manifest.provideKey)(declaration.id, "url");
583
+ const given = context.supplied?.[key];
584
+ if (given !== void 0) return { provides: { [key]: given } };
745
585
  const parentUrl = context.provisioned[declaration.of]?.provides[(0, _geekmidas_manifest.provideKey)(declaration.of, "url")];
746
586
  if (!parentUrl) throw new UnresolvedParent(declaration.id, declaration.of);
747
587
  const endpoint = new URL(parentUrl).searchParams.get("endpoint");
748
588
  const bucket = new URL(parentUrl).hostname;
749
589
  if (!endpoint) throw new UnresolvedParent(declaration.id, declaration.of);
750
- return { provides: { [(0, _geekmidas_manifest.provideKey)(declaration.id, "url")]: `${endpoint}/${bucket}` } };
590
+ return { provides: { [key]: `${endpoint}/${bucket}` } };
591
+ },
592
+ /**
593
+ * Mail: the stage's own SMTP server, or — allowed — Mailpit on the box.
594
+ *
595
+ * Every provider speaks SMTP, so the provider is whatever the stage's
596
+ * `<ID>_URL` names, with the address it sends from beside it. Only with
597
+ * `--allow-dev-services mailpit`, and only where the stage set no URL,
598
+ * does this run Mailpit — which catches every message and delivers none.
599
+ */
600
+ email: async (declaration, context) => {
601
+ if (declaration.kind !== "email") throw new WrongKind(declaration.kind);
602
+ const key = (0, _geekmidas_manifest.provideKey)(declaration.id, "url");
603
+ const from = (0, _geekmidas_manifest.provideKey)(declaration.id, "from");
604
+ const given = context.supplied?.[key];
605
+ if (given !== void 0) return { provides: {
606
+ [key]: given,
607
+ [from]: supplied(declaration.id, from, context)
608
+ } };
609
+ if (!context.devServices?.includes("mailpit")) throw notConfigured(declaration.id, "email", context);
610
+ const service = serviceName({
611
+ stage: context.stage,
612
+ app: context.scope ?? context.project
613
+ }, declaration.id);
614
+ const { compose } = await context.api.findOrCreateCompose(service, context.projectId, context.environmentId, mailpitCompose(service));
615
+ await context.api.deployCompose(compose.composeId);
616
+ return { provides: {
617
+ [key]: `smtp://${service}:1025`,
618
+ [from]: context.supplied?.[from] ?? `noreply@${context.domain ?? "localhost"}`
619
+ } };
751
620
  },
752
621
  /**
753
622
  * A topic, and below it a queue — the same broker either way.
@@ -985,6 +854,56 @@ function minioCompose(options) {
985
854
  ""
986
855
  ].join("\n");
987
856
  }
857
+ /**
858
+ * A one-service compose file for Mailpit, on `dokploy-network` so the apps
859
+ * reach it by its service name. It accepts mail from anything on the network
860
+ * and delivers none of it.
861
+ */
862
+ function mailpitCompose(service) {
863
+ return [
864
+ "services:",
865
+ ` ${service}:`,
866
+ " image: axllent/mailpit:latest",
867
+ " environment:",
868
+ " MP_SMTP_AUTH_ACCEPT_ANY: '1'",
869
+ " MP_SMTP_AUTH_ALLOW_INSECURE: '1'",
870
+ " networks:",
871
+ " - dokploy-network",
872
+ "networks:",
873
+ " dokploy-network:",
874
+ " external: true",
875
+ ""
876
+ ].join("\n");
877
+ }
878
+ /**
879
+ * The S3 client's shared keys the stage set, for a bucket that is its own —
880
+ * none when it set none, since a bucket's URL may carry its own key.
881
+ */
882
+ function storageKeys(values) {
883
+ const keys = {};
884
+ for (const key of [...require_state.STORAGE_KEY_PAIR, "AWS_REGION"]) {
885
+ const value = values?.[key];
886
+ if (value !== void 0) keys[key] = value;
887
+ }
888
+ return keys;
889
+ }
890
+ /**
891
+ * The error for a bucket or mail the stage configured nothing for — what
892
+ * `validate` already refused, should a provisioner be reached without it.
893
+ */
894
+ function notConfigured(id, kind, context) {
895
+ const { missing } = require_state.externalServices({
896
+ stage: context.stage,
897
+ declarations: [{
898
+ id,
899
+ kind
900
+ }],
901
+ supplied: context.supplied ?? {},
902
+ allow: [],
903
+ ...context.domain ? { domain: context.domain } : {}
904
+ });
905
+ return new require_state.ExternalServicesNotConfigured(context.stage, missing);
906
+ }
988
907
  /** Whether anything reads through a reader on this construct. */
989
908
  function readsFrom(manifest, id) {
990
909
  return Object.values(manifest).some((declaration) => declaration.kind === "database-reader" && declaration.of === id);
@@ -1173,6 +1092,8 @@ async function provisionDeclared(options) {
1173
1092
  cache: require_state.cacheBackendFor(require_state.providerOf(workspace)),
1174
1093
  events: require_state.eventsBackendFor(require_state.providerOf(workspace)),
1175
1094
  storage: require_state.storageBackendFor(require_state.providerOf(workspace)),
1095
+ ...options.devServices ? { devServices: options.devServices } : {},
1096
+ ...workspace.deploy?.domains?.[options.stage] ? { domain: workspace.deploy.domains[options.stage] } : {},
1176
1097
  addresses: surfaceAddresses(manifest, options.appUrls),
1177
1098
  seed: options.seed,
1178
1099
  ...options.supplied ? { supplied: options.supplied } : {},
@@ -1273,7 +1194,7 @@ async function createDnsProvider(options) {
1273
1194
  if (isDnsProvider(config.provider)) return config.provider;
1274
1195
  const provider = config.provider;
1275
1196
  if (provider === "hostinger") {
1276
- const { HostingerProvider } = await Promise.resolve().then(() => require("./HostingerProvider-BznqRC2S.cjs"));
1197
+ const { HostingerProvider } = await Promise.resolve().then(() => require("./HostingerProvider-dxkwynSs.cjs"));
1277
1198
  return new HostingerProvider();
1278
1199
  }
1279
1200
  if (provider === "route53") {
@@ -1841,7 +1762,7 @@ const answer = require_schemas.discriminatedUnion("reason", [require_schemas.obj
1841
1762
  })]);
1842
1763
  /** Apply every pending migration, in the sandbox, as each construct's owner. */
1843
1764
  async function runMigrations(options) {
1844
- const sandbox = options.sandbox ?? require_sandbox.activeSandbox() ?? new require_local.LocalSandbox({ root: options.root });
1765
+ const sandbox = options.sandbox ?? require_sandbox.activeSandbox() ?? new require_credentials.LocalSandbox({ root: options.root });
1845
1766
  const { value } = await require_discover.runWorker(sandbox, "migrations", {
1846
1767
  name: "migrate-worker",
1847
1768
  args: [JSON.stringify({
@@ -2164,8 +2085,18 @@ async function validateDokploy(phase) {
2164
2085
  secrets: phase.secrets,
2165
2086
  ctx
2166
2087
  };
2088
+ const stored = await phase.secrets.read();
2089
+ const services = require_state.assertExternalServices({
2090
+ stage,
2091
+ declarations: require_state.manifestServiceDeclarations(phase.manifest),
2092
+ supplied: stored?.custom ?? {},
2093
+ allow: phase.allowDevServices,
2094
+ ...workspace.deploy?.domains?.[stage] ? { domain: workspace.deploy.domains[stage] } : {}
2095
+ });
2096
+ require_state.reportDevServices(phase, require_state.devServicesUsed(services));
2167
2097
  return {
2168
2098
  ...run,
2099
+ allowDevServices: phase.allowDevServices,
2169
2100
  preflight: await preflight(run),
2170
2101
  verify: verifySettings(workspace.deploy.dokploy?.verify),
2171
2102
  atomic: phase.atomic,
@@ -2345,7 +2276,8 @@ async function provision(run) {
2345
2276
  appUrls,
2346
2277
  supplied: stageSecrets.custom,
2347
2278
  seed: stageSecrets.seed,
2348
- manifest
2279
+ manifest,
2280
+ devServices: run.allowDevServices
2349
2281
  });
2350
2282
  declaredEnv = declared.env;
2351
2283
  declaredClusters = declared.clusters;
@@ -2535,7 +2467,7 @@ async function releaseDokploy(run) {
2535
2467
  if (appSecrets && credentials) logger.log(` Encrypted ${appSecrets.secretCount} secrets`);
2536
2468
  const imageRef$1 = require_state.imageRef(identity, appName, registry, imageTag);
2537
2469
  logger.log(` Building Docker image: ${imageRef$1}`);
2538
- const image = await deployDocker({
2470
+ const image = await require_state.deployDocker({
2539
2471
  stage,
2540
2472
  tag: imageTag,
2541
2473
  skipPush: false,
@@ -2644,7 +2576,7 @@ async function releaseDokploy(run) {
2644
2576
  if (buildArgs.length > 0) logger.log(` Build args: ${publicUrlArgNames.join(", ")}`);
2645
2577
  const imageRef$2 = require_state.imageRef(identity, appName, registry, imageTag);
2646
2578
  logger.log(` Building Docker image: ${imageRef$2}`);
2647
- const image = await deployDocker({
2579
+ const image = await require_state.deployDocker({
2648
2580
  stage,
2649
2581
  tag: imageTag,
2650
2582
  skipPush: false,
@@ -3276,4 +3208,4 @@ Object.defineProperty(exports, "verifySettings", {
3276
3208
  }
3277
3209
  });
3278
3210
 
3279
- //# sourceMappingURL=engine-DR6KurWX.cjs.map
3211
+ //# sourceMappingURL=engine-BM9Dy_DT.cjs.map