@geekmidas/cli 10.0.0-alpha.65 → 10.0.0-alpha.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -177
- package/dist/{HostingerProvider-x9gQTAGZ.mjs → HostingerProvider-D85ayzTi.mjs} +4 -4
- package/dist/HostingerProvider-D85ayzTi.mjs.map +1 -0
- package/dist/{HostingerProvider-Dlmbfass.cjs → HostingerProvider-dxkwynSs.cjs} +4 -4
- package/dist/HostingerProvider-dxkwynSs.cjs.map +1 -0
- package/dist/{LegacyStateStore-BGoo__sO.cjs → LegacyStateStore-BZiO9-Lw.cjs} +2 -2
- package/dist/{LegacyStateStore-BGoo__sO.cjs.map → LegacyStateStore-BZiO9-Lw.cjs.map} +1 -1
- package/dist/{LegacyStateStore-BUu1nQ5u.mjs → LegacyStateStore-C39UKwmf.mjs} +2 -2
- package/dist/{LegacyStateStore-BUu1nQ5u.mjs.map → LegacyStateStore-C39UKwmf.mjs.map} +1 -1
- package/dist/{LocalStateStore-93urXyQe.cjs → LocalStateStore-DHVsZLyF.cjs} +2 -2
- package/dist/{LocalStateStore-93urXyQe.cjs.map → LocalStateStore-DHVsZLyF.cjs.map} +1 -1
- package/dist/{LocalStateStore-BRhMQRuy.mjs → LocalStateStore-Dk3Wbvzk.mjs} +2 -2
- package/dist/{LocalStateStore-BRhMQRuy.mjs.map → LocalStateStore-Dk3Wbvzk.mjs.map} +1 -1
- package/dist/{OpenApiTsGenerator-BWuDRHe9.cjs → OpenApiTsGenerator-B2zrdyP4.cjs} +2 -2
- package/dist/{OpenApiTsGenerator-BWuDRHe9.cjs.map → OpenApiTsGenerator-B2zrdyP4.cjs.map} +1 -1
- package/dist/{OpenApiTsGenerator-C6v-IeHt.mjs → OpenApiTsGenerator-BmUAcR7d.mjs} +2 -2
- package/dist/{OpenApiTsGenerator-C6v-IeHt.mjs.map → OpenApiTsGenerator-BmUAcR7d.mjs.map} +1 -1
- package/dist/{Route53Provider-DVILBsvV.cjs → Route53Provider-Bllus2NR.cjs} +2 -2
- package/dist/Route53Provider-Bllus2NR.cjs.map +1 -0
- package/dist/{Route53Provider-Cvj40A8I.mjs → Route53Provider-QXxjkZO1.mjs} +2 -2
- package/dist/Route53Provider-QXxjkZO1.mjs.map +1 -0
- package/dist/{S3StateStore-F4dxw6kS.cjs → S3StateStore--4tYVMAL.cjs} +2 -2
- package/dist/{S3StateStore-F4dxw6kS.cjs.map → S3StateStore--4tYVMAL.cjs.map} +1 -1
- package/dist/{S3StateStore-pw1GhWwt.mjs → S3StateStore-B_ZF9eHt.mjs} +2 -2
- package/dist/{S3StateStore-pw1GhWwt.mjs.map → S3StateStore-B_ZF9eHt.mjs.map} +1 -1
- package/dist/{SSMStateStore-Bt9acuAF.cjs → SSMStateStore-ACZ8hRvZ.cjs} +2 -2
- package/dist/{SSMStateStore-Bt9acuAF.cjs.map → SSMStateStore-ACZ8hRvZ.cjs.map} +1 -1
- package/dist/{SSMStateStore-Dmj7zzFO.mjs → SSMStateStore-DjPuKqrm.mjs} +2 -2
- package/dist/{SSMStateStore-Dmj7zzFO.mjs.map → SSMStateStore-DjPuKqrm.mjs.map} +1 -1
- package/dist/{backup-provisioner-DIVCbfee.mjs → backup-provisioner-C8DnCmxK.mjs} +2 -2
- package/dist/backup-provisioner-C8DnCmxK.mjs.map +1 -0
- package/dist/{backup-provisioner-BmhIO_Yr.cjs → backup-provisioner-oDEsPj02.cjs} +2 -2
- package/dist/backup-provisioner-oDEsPj02.cjs.map +1 -0
- package/dist/{bundler-D_14JLZF.mjs → bundler-Bq3HaLOZ.mjs} +20 -5
- package/dist/bundler-Bq3HaLOZ.mjs.map +1 -0
- package/dist/{bundler-D6MlIfBT.cjs → bundler-pyLj-gS0.cjs} +20 -5
- package/dist/bundler-pyLj-gS0.cjs.map +1 -0
- package/dist/{cli-P56vvrDQ.mjs → cli-C2Tjbn27.mjs} +6 -5
- package/dist/cli-C2Tjbn27.mjs.map +1 -0
- package/dist/{cli-BfH1deAT.cjs → cli-DR7B2_fX.cjs} +6 -5
- package/dist/cli-DR7B2_fX.cjs.map +1 -0
- package/dist/{compose-391oEKj1.cjs → compose-5oNHAKNT.cjs} +137 -667
- package/dist/compose-5oNHAKNT.cjs.map +1 -0
- package/dist/{compose-DprE3ASm.mjs → compose-BjToENzG.mjs} +130 -569
- package/dist/compose-BjToENzG.mjs.map +1 -0
- package/dist/{config-V_X_BMpm.d.cts → config-4XFxX1al.d.cts} +3 -3
- package/dist/{config-BonvTW8p.d.mts.map → config-4XFxX1al.d.cts.map} +1 -1
- package/dist/{config-BonvTW8p.d.mts → config-UtKzhpFb.d.mts} +3 -3
- package/dist/{config-V_X_BMpm.d.cts.map → config-UtKzhpFb.d.mts.map} +1 -1
- package/dist/config.cjs +3 -3
- package/dist/config.d.cts +3 -3
- package/dist/config.d.mts +3 -3
- package/dist/config.mjs +3 -3
- package/dist/{credentials-Bzbg23n8.cjs → credentials-BVs7mrtw.cjs} +239 -3
- package/dist/credentials-BVs7mrtw.cjs.map +1 -0
- package/dist/{credentials-Dq1MnWQf.mjs → credentials-pAtB70k3.mjs} +223 -5
- package/dist/credentials-pAtB70k3.mjs.map +1 -0
- package/dist/databases-C2p5LGAp.cjs +419 -0
- package/dist/databases-C2p5LGAp.cjs.map +1 -0
- package/dist/databases-hUHTuwhx.mjs +346 -0
- package/dist/databases-hUHTuwhx.mjs.map +1 -0
- package/dist/deploy/public.cjs +37 -28
- package/dist/deploy/public.cjs.map +1 -1
- package/dist/deploy/public.d.cts +136 -19
- package/dist/deploy/public.d.cts.map +1 -1
- package/dist/deploy/public.d.mts +136 -19
- package/dist/deploy/public.d.mts.map +1 -1
- package/dist/deploy/public.mjs +11 -11
- package/dist/deploy-BucRfbvX.cjs +511 -0
- package/dist/deploy-BucRfbvX.cjs.map +1 -0
- package/dist/deploy-DRAwTG72.mjs +488 -0
- package/dist/deploy-DRAwTG72.mjs.map +1 -0
- package/dist/{discover-LMrqsWSU.mjs → discover-BFoJWKGD.mjs} +4 -2
- package/dist/discover-BFoJWKGD.mjs.map +1 -0
- package/dist/{discover-DHdECueV.cjs → discover-OEfZ9OkA.cjs} +4 -2
- package/dist/discover-OEfZ9OkA.cjs.map +1 -0
- package/dist/dokploy-DIt1IZl1.mjs +38 -0
- package/dist/dokploy-DIt1IZl1.mjs.map +1 -0
- package/dist/dokploy-m345Zx02.cjs +38 -0
- package/dist/dokploy-m345Zx02.cjs.map +1 -0
- package/dist/{encryption-DF_hgIpl.mjs → encryption-Ccbahik7.mjs} +3 -5
- package/dist/{encryption-DF_hgIpl.mjs.map → encryption-Ccbahik7.mjs.map} +1 -1
- package/dist/{encryption-B1wJwgae.cjs → encryption-rZ3BghXy.cjs} +5 -7
- package/dist/{encryption-B1wJwgae.cjs.map → encryption-rZ3BghXy.cjs.map} +1 -1
- package/dist/{deploy-Cy8igpQF.cjs → engine-Cx_dvx9q.cjs} +1491 -1260
- package/dist/engine-Cx_dvx9q.cjs.map +1 -0
- package/dist/{deploy-CZ5nlpsu.mjs → engine-Gs0abjuj.mjs} +1450 -1261
- package/dist/engine-Gs0abjuj.mjs.map +1 -0
- package/dist/{github-B0YYE98x.mjs → github-CJANTYqi.mjs} +3 -3
- package/dist/{github-B0YYE98x.mjs.map → github-CJANTYqi.mjs.map} +1 -1
- package/dist/{github-CYcmTdFs.cjs → github-CrcGFkfD.cjs} +7 -7
- package/dist/{github-CYcmTdFs.cjs.map → github-CrcGFkfD.cjs.map} +1 -1
- package/dist/{index-DPUAGJaK.d.cts → index-CyApaHVe.d.cts} +2 -2
- package/dist/{index-DPUAGJaK.d.cts.map → index-CyApaHVe.d.cts.map} +1 -1
- package/dist/{index-DwKD_8lt.d.mts → index-DD1FfUHh.d.mts} +2 -2
- package/dist/{index-DwKD_8lt.d.mts.map → index-DD1FfUHh.d.mts.map} +1 -1
- package/dist/index.cjs +285 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +258 -68
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-q4pPAXtO.cjs → migrate-CQdSpttI.cjs} +16 -16
- package/dist/{migrate-q4pPAXtO.cjs.map → migrate-CQdSpttI.cjs.map} +1 -1
- package/dist/{migrate-B2qL5wj4.mjs → migrate-DCVo5gLS.mjs} +6 -6
- package/dist/{migrate-B2qL5wj4.mjs.map → migrate-DCVo5gLS.mjs.map} +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/provider-B3Sv_a74.cjs +173 -0
- package/dist/provider-B3Sv_a74.cjs.map +1 -0
- package/dist/provider-D7rQzzzf.mjs +138 -0
- package/dist/provider-D7rQzzzf.mjs.map +1 -0
- package/dist/{ready-bQfu9GES.mjs → ready-2s3-CndS.mjs} +3 -3
- package/dist/{ready-bQfu9GES.mjs.map → ready-2s3-CndS.mjs.map} +1 -1
- package/dist/{ready-brEhh68f.cjs → ready-B6uHr4sm.cjs} +3 -3
- package/dist/{ready-brEhh68f.cjs.map → ready-B6uHr4sm.cjs.map} +1 -1
- package/dist/reconcile/public.cjs +1 -1
- package/dist/reconcile/public.d.cts +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/reconcile/public.mjs +1 -1
- package/dist/{resolve-N_i4XNd-.cjs → resolve-BexmDcsN.cjs} +4 -4
- package/dist/{resolve-N_i4XNd-.cjs.map → resolve-BexmDcsN.cjs.map} +1 -1
- package/dist/{resolve-DLkIXTct.mjs → resolve-DhZgtvZe.mjs} +4 -4
- package/dist/{resolve-DLkIXTct.mjs.map → resolve-DhZgtvZe.mjs.map} +1 -1
- package/dist/rollback-BnY7KuG_.cjs +161 -0
- package/dist/rollback-BnY7KuG_.cjs.map +1 -0
- package/dist/rollback-m4Yeym5x.mjs +132 -0
- package/dist/rollback-m4Yeym5x.mjs.map +1 -0
- package/dist/run-BJLIerMM.mjs +133 -0
- package/dist/run-BJLIerMM.mjs.map +1 -0
- package/dist/run-fVZ-rLnc.cjs +174 -0
- package/dist/run-fVZ-rLnc.cjs.map +1 -0
- package/dist/{runtime-BnD7Nn96.d.cts → runtime-BRqFOvPM.d.cts} +2 -2
- package/dist/{runtime-BnD7Nn96.d.cts.map → runtime-BRqFOvPM.d.cts.map} +1 -1
- package/dist/{runtime-j-tmFL65.d.mts → runtime-CEk5n4VH.d.mts} +2 -2
- package/dist/{runtime-j-tmFL65.d.mts.map → runtime-CEk5n4VH.d.mts.map} +1 -1
- package/dist/sandbox/discover-worker.cjs +1 -1
- package/dist/sandbox/discover-worker.mjs +1 -1
- package/dist/sandbox/migrate-worker.cjs +61 -0
- package/dist/sandbox/migrate-worker.cjs.map +1 -0
- package/dist/sandbox/migrate-worker.d.cts +1 -0
- package/dist/sandbox/migrate-worker.d.mts +1 -0
- package/dist/sandbox/migrate-worker.mjs +62 -0
- package/dist/sandbox/migrate-worker.mjs.map +1 -0
- package/dist/{schemas-D2LCF689.mjs → schemas-Cfhtpdo0.mjs} +10 -2
- package/dist/{schemas-Ckm_aBnF.cjs.map → schemas-Cfhtpdo0.mjs.map} +1 -1
- package/dist/{schemas-Ckm_aBnF.cjs → schemas-RUlKHu27.cjs} +15 -1
- package/dist/{schemas-D2LCF689.mjs.map → schemas-RUlKHu27.cjs.map} +1 -1
- package/dist/{sniffer-BZ-OJO4Y.mjs → sniffer-BdFeLSmA.mjs} +97 -600
- package/dist/sniffer-BdFeLSmA.mjs.map +1 -0
- package/dist/{sniffer-BSwaL-dX.cjs → sniffer-D66HIvi9.cjs} +110 -674
- package/dist/sniffer-D66HIvi9.cjs.map +1 -0
- package/dist/{sst-B2HbrDR3.mjs → sst-DRi3H5TB.mjs} +3 -3
- package/dist/{sst-B2HbrDR3.mjs.map → sst-DRi3H5TB.mjs.map} +1 -1
- package/dist/{sst-DcfsVH6x.cjs → sst-hBrKouBy.cjs} +5 -5
- package/dist/{sst-DcfsVH6x.cjs.map → sst-hBrKouBy.cjs.map} +1 -1
- package/dist/{state-DF26e_lo.cjs → state-DgmM4EKq.cjs} +2787 -1890
- package/dist/state-DgmM4EKq.cjs.map +1 -0
- package/dist/{state-B8YwmUZU.mjs → state-DkUStoqJ.mjs} +2813 -2084
- package/dist/state-DkUStoqJ.mjs.map +1 -0
- package/dist/target/public.cjs +1 -1
- package/dist/target/public.d.cts +2 -2
- package/dist/target/public.d.mts +2 -2
- package/dist/target/public.mjs +1 -1
- package/dist/{terminal-CfbiYUbZ.mjs → terminal-C3cv-OQu.mjs} +5 -5
- package/dist/{terminal-CfbiYUbZ.mjs.map → terminal-C3cv-OQu.mjs.map} +1 -1
- package/dist/{terminal-Bs5E1oxm.cjs → terminal-DjzgLu6m.cjs} +12 -16
- package/dist/{terminal-Bs5E1oxm.cjs.map → terminal-DjzgLu6m.cjs.map} +1 -1
- package/dist/{types-ByMWkXKP.d.cts → types-CSw2w69a.d.mts} +68 -10
- package/dist/types-CSw2w69a.d.mts.map +1 -0
- package/dist/{types-BCzMWBb6.d.mts → types-D5WIxRDP.d.cts} +69 -9
- package/dist/types-D5WIxRDP.d.cts.map +1 -0
- package/dist/vitest.cjs +1 -1
- package/dist/vitest.mjs +1 -1
- package/dist/workspace/index.cjs +1 -1
- package/dist/workspace/index.d.cts +2 -2
- package/dist/workspace/index.d.mts +2 -2
- package/dist/workspace/index.mjs +1 -1
- package/dist/{workspace-C06_pW4g.mjs → workspace-Be6uBhlF.mjs} +10 -3
- package/dist/workspace-Be6uBhlF.mjs.map +1 -0
- package/dist/{workspace-BewAHZIo.cjs → workspace-ON-bqiJz.cjs} +10 -3
- package/dist/workspace-ON-bqiJz.cjs.map +1 -0
- package/package.json +13 -13
- package/dist/HostingerProvider-Dlmbfass.cjs.map +0 -1
- package/dist/HostingerProvider-x9gQTAGZ.mjs.map +0 -1
- package/dist/Route53Provider-Cvj40A8I.mjs.map +0 -1
- package/dist/Route53Provider-DVILBsvV.cjs.map +0 -1
- package/dist/backup-provisioner-BmhIO_Yr.cjs.map +0 -1
- package/dist/backup-provisioner-DIVCbfee.mjs.map +0 -1
- package/dist/bundler-D6MlIfBT.cjs.map +0 -1
- package/dist/bundler-D_14JLZF.mjs.map +0 -1
- package/dist/cli-BfH1deAT.cjs.map +0 -1
- package/dist/cli-P56vvrDQ.mjs.map +0 -1
- package/dist/compose-391oEKj1.cjs.map +0 -1
- package/dist/compose-DprE3ASm.mjs.map +0 -1
- package/dist/credentials-Bzbg23n8.cjs.map +0 -1
- package/dist/credentials-Dq1MnWQf.mjs.map +0 -1
- package/dist/deploy-9MBG_QLd.mjs +0 -137
- package/dist/deploy-9MBG_QLd.mjs.map +0 -1
- package/dist/deploy-B80idPUZ.cjs +0 -142
- package/dist/deploy-B80idPUZ.cjs.map +0 -1
- package/dist/deploy-CZ5nlpsu.mjs.map +0 -1
- package/dist/deploy-Cy8igpQF.cjs.map +0 -1
- package/dist/discover-DHdECueV.cjs.map +0 -1
- package/dist/discover-LMrqsWSU.mjs.map +0 -1
- package/dist/dokploy-BdtBePjp.mjs +0 -32
- package/dist/dokploy-BdtBePjp.mjs.map +0 -1
- package/dist/dokploy-iFY8MY-L.cjs +0 -32
- package/dist/dokploy-iFY8MY-L.cjs.map +0 -1
- package/dist/local-BdH4XN0E.cjs +0 -409
- package/dist/local-BdH4XN0E.cjs.map +0 -1
- package/dist/local-CWR4Y_kW.mjs +0 -350
- package/dist/local-CWR4Y_kW.mjs.map +0 -1
- package/dist/sniffer-BSwaL-dX.cjs.map +0 -1
- package/dist/sniffer-BZ-OJO4Y.mjs.map +0 -1
- package/dist/state-B8YwmUZU.mjs.map +0 -1
- package/dist/state-DF26e_lo.cjs.map +0 -1
- package/dist/storage-BzaUxmqe.mjs +0 -124
- package/dist/storage-BzaUxmqe.mjs.map +0 -1
- package/dist/storage-CSGoC3bK.cjs +0 -152
- package/dist/storage-CSGoC3bK.cjs.map +0 -1
- package/dist/store-CJF1Tqkq.cjs +0 -510
- package/dist/store-CJF1Tqkq.cjs.map +0 -1
- package/dist/store-CLiHnqOY.mjs +0 -415
- package/dist/store-CLiHnqOY.mjs.map +0 -1
- package/dist/types-BCzMWBb6.d.mts.map +0 -1
- package/dist/types-ByMWkXKP.d.cts.map +0 -1
- package/dist/workspace-BewAHZIo.cjs.map +0 -1
- package/dist/workspace-C06_pW4g.mjs.map +0 -1
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
|
|
2
|
-
const
|
|
3
|
-
const require_discover = require("./discover-
|
|
4
|
-
const require_sandbox = require("./sandbox-CL--ZDui.cjs");
|
|
2
|
+
const require_run = require("./run-fVZ-rLnc.cjs");
|
|
3
|
+
const require_discover = require("./discover-OEfZ9OkA.cjs");
|
|
5
4
|
const require_derive = require("./derive-DAbo49sm.cjs");
|
|
6
5
|
const require_define = require("./define-DzRz8FgH.cjs");
|
|
7
|
-
const
|
|
8
|
-
const require_store = require("./store-CJF1Tqkq.cjs");
|
|
9
|
-
const require_state = require("./state-DF26e_lo.cjs");
|
|
6
|
+
const require_state = require("./state-DgmM4EKq.cjs");
|
|
10
7
|
const require_fakes = require("./fakes-zW-jNAbQ.cjs");
|
|
8
|
+
const require_databases = require("./databases-C2p5LGAp.cjs");
|
|
11
9
|
let node_path = require("node:path");
|
|
12
|
-
let node_fs = require("node:fs");
|
|
13
10
|
let node_fs_promises = require("node:fs/promises");
|
|
14
11
|
let _geekmidas_manifest = require("@geekmidas/manifest");
|
|
15
|
-
let node_module = require("node:module");
|
|
16
|
-
let node_url = require("node:url");
|
|
17
12
|
let node_child_process = require("node:child_process");
|
|
18
|
-
let pg = require("pg");
|
|
19
|
-
pg = require_rolldown_runtime.__toESM(pg, 1);
|
|
20
13
|
let yaml = require("yaml");
|
|
21
14
|
let node_https = require("node:https");
|
|
22
15
|
//#region src/compose/docker.ts
|
|
@@ -144,16 +137,16 @@ const dockerCompose = {
|
|
|
144
137
|
};
|
|
145
138
|
},
|
|
146
139
|
async build(stack, services) {
|
|
147
|
-
await
|
|
140
|
+
await require_run.run("docker", compose(stack, ["build", ...services]), runOptions(stack, {
|
|
148
141
|
...process.env,
|
|
149
142
|
DOCKER_BUILDKIT: "1"
|
|
150
143
|
}));
|
|
151
144
|
},
|
|
152
145
|
async pull(stack, services) {
|
|
153
|
-
await
|
|
146
|
+
await require_run.run("docker", compose(stack, ["pull", ...services]), runOptions(stack));
|
|
154
147
|
},
|
|
155
148
|
async up(stack, services) {
|
|
156
|
-
await
|
|
149
|
+
await require_run.run("docker", compose(stack, [
|
|
157
150
|
"up",
|
|
158
151
|
"-d",
|
|
159
152
|
"--wait",
|
|
@@ -163,10 +156,10 @@ const dockerCompose = {
|
|
|
163
156
|
]), runOptions(stack));
|
|
164
157
|
},
|
|
165
158
|
async down(stack) {
|
|
166
|
-
await
|
|
159
|
+
await require_run.run("docker", compose(stack, ["down"]), runOptions(stack));
|
|
167
160
|
},
|
|
168
161
|
async port(stack, service, inside) {
|
|
169
|
-
const output = await
|
|
162
|
+
const output = await require_run.runOutput("docker", compose(stack, [
|
|
170
163
|
"port",
|
|
171
164
|
service,
|
|
172
165
|
String(inside)
|
|
@@ -180,7 +173,7 @@ const dockerCompose = {
|
|
|
180
173
|
},
|
|
181
174
|
async copyOut(stack, service, from, to) {
|
|
182
175
|
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(to), { recursive: true });
|
|
183
|
-
await
|
|
176
|
+
await require_run.run("docker", compose(stack, [
|
|
184
177
|
"cp",
|
|
185
178
|
`${service}:${from}`,
|
|
186
179
|
to
|
|
@@ -537,6 +530,7 @@ function composeStack(input) {
|
|
|
537
530
|
};
|
|
538
531
|
for (const [key, value] of Object.entries(app.env)) if (/[\r\n]/.test(value)) throw new EnvValueMultiline(app.name, key);
|
|
539
532
|
}
|
|
533
|
+
const layout = input.layout ?? defaultLayout(workspace.root);
|
|
540
534
|
const compose = stackFile({
|
|
541
535
|
project,
|
|
542
536
|
plan,
|
|
@@ -544,7 +538,10 @@ function composeStack(input) {
|
|
|
544
538
|
apps,
|
|
545
539
|
master: credential.master,
|
|
546
540
|
https,
|
|
547
|
-
http
|
|
541
|
+
http,
|
|
542
|
+
composeDir: (0, node_path.join)(workspace.root, stackDir(stage)),
|
|
543
|
+
buildRoot: layout.buildRoot,
|
|
544
|
+
workspaceRoot: workspace.root
|
|
548
545
|
});
|
|
549
546
|
const caddyfile = edgeCaddyfile(apps.map((app) => ({
|
|
550
547
|
host: app.host,
|
|
@@ -553,18 +550,10 @@ function composeStack(input) {
|
|
|
553
550
|
const dockerfiles = {};
|
|
554
551
|
for (const app of apps) {
|
|
555
552
|
if (!app.build) continue;
|
|
556
|
-
dockerfiles[app.build.dockerfile] =
|
|
557
|
-
|
|
558
|
-
|
|
553
|
+
dockerfiles[app.build.dockerfile] = require_state.appDockerfile(app.name, workspace.apps[app.name], {
|
|
554
|
+
layout,
|
|
555
|
+
workspaceRoot: workspace.root,
|
|
559
556
|
manifest
|
|
560
|
-
}) : require_state.generateSlimDockerfile({
|
|
561
|
-
imageName: app.name,
|
|
562
|
-
baseImage: "node:22-alpine",
|
|
563
|
-
port: app.port,
|
|
564
|
-
healthCheckPath: "/health",
|
|
565
|
-
prebuilt: true,
|
|
566
|
-
packageManager: input.packageManager ?? "pnpm",
|
|
567
|
-
bundle: `${app.path}/.gkm/server/dist/server.mjs`
|
|
568
557
|
});
|
|
569
558
|
}
|
|
570
559
|
return {
|
|
@@ -605,7 +594,7 @@ function stackApps(workspace, manifest, plan, options) {
|
|
|
605
594
|
if (!app || !resource || !app.port) continue;
|
|
606
595
|
const host = hostOf(name, app, workspace, resource, options);
|
|
607
596
|
const tag = declaration.kind === "site" ? siteTag(options.images.tag, options.stage) : options.images.tag;
|
|
608
|
-
const ref = require_state.validateImageRef(
|
|
597
|
+
const ref = require_state.validateImageRef(require_state.imageRef(options.identity, name, options.images.registry, tag));
|
|
609
598
|
apps.push({
|
|
610
599
|
app: name,
|
|
611
600
|
name,
|
|
@@ -665,8 +654,12 @@ function stackFile(options) {
|
|
|
665
654
|
for (const app of apps) services[app.name] = {
|
|
666
655
|
image: app.ref,
|
|
667
656
|
...app.build ? { build: {
|
|
668
|
-
|
|
669
|
-
|
|
657
|
+
...require_state.composeBuildPaths({
|
|
658
|
+
composeDir: options.composeDir,
|
|
659
|
+
buildRoot: options.buildRoot,
|
|
660
|
+
workspaceRoot: options.workspaceRoot,
|
|
661
|
+
dockerfile: app.build.dockerfile
|
|
662
|
+
}),
|
|
670
663
|
...app.build.args ? { args: app.build.args } : {}
|
|
671
664
|
} } : {},
|
|
672
665
|
restart: "unless-stopped",
|
|
@@ -706,477 +699,83 @@ function stackFile(options) {
|
|
|
706
699
|
volumes
|
|
707
700
|
};
|
|
708
701
|
}
|
|
709
|
-
/** Render an app's env file: one `KEY=value` per line, read raw by compose. */
|
|
710
|
-
function envFile(env) {
|
|
711
|
-
return `${Object.entries(env).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${key}=${value}`).join("\n")}\n`;
|
|
712
|
-
}
|
|
713
|
-
//#endregion
|
|
714
|
-
//#region src/migrate/provider.ts
|
|
715
702
|
/**
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
* Two kinds of file, told apart by extension rather than by configuration: a
|
|
719
|
-
* script exports `up` (and may export `down`) — or `seed(db, { stage })`, in
|
|
720
|
-
* `seeds/` — and a
|
|
721
|
-
* `.sql` file is run whole. The second is what makes a folder independent of
|
|
722
|
-
* the client the app uses — Better Auth's schema is SQL whatever the
|
|
723
|
-
* application queries with.
|
|
703
|
+
* A build without a layout: the workspace is the build root, with pnpm.
|
|
704
|
+
* What a caller that never looked at the filesystem gets.
|
|
724
705
|
*/
|
|
725
|
-
|
|
726
|
-
".ts",
|
|
727
|
-
".mts",
|
|
728
|
-
".js",
|
|
729
|
-
".mjs"
|
|
730
|
-
]);
|
|
731
|
-
/** Two files in one folder that would be one migration. */
|
|
732
|
-
var DuplicateMigration = class extends Error {
|
|
733
|
-
folder;
|
|
734
|
-
migration;
|
|
735
|
-
constructor(folder, migration) {
|
|
736
|
-
super(`${folder} has two migrations named '${migration}' — a script and a .sql file with the same name. A migration is recorded by name, so only one of them could ever run; rename or remove the other.`);
|
|
737
|
-
this.folder = folder;
|
|
738
|
-
this.migration = migration;
|
|
739
|
-
this.name = "DuplicateMigration";
|
|
740
|
-
}
|
|
741
|
-
};
|
|
742
|
-
/** A script in a migrations folder that exports no `up`. */
|
|
743
|
-
var MigrationHasNoUp = class extends Error {
|
|
744
|
-
file;
|
|
745
|
-
constructor(file) {
|
|
746
|
-
super(`${file} is in a migrations folder but exports no \`up\` function. Export \`async function up(db: Kysely<unknown>)\`, or move the file out of the folder if it is not a migration.`);
|
|
747
|
-
this.file = file;
|
|
748
|
-
this.name = "MigrationHasNoUp";
|
|
749
|
-
}
|
|
750
|
-
};
|
|
751
|
-
/** A script in a seeds folder that exports no `seed`. */
|
|
752
|
-
var SeedHasNoSeed = class extends Error {
|
|
753
|
-
file;
|
|
754
|
-
constructor(file) {
|
|
755
|
-
super(`${file} is in a seeds folder but exports no \`seed\` function. Export \`async function seed(db, { stage })\`, or move the file out of the folder if it is not a seed.`);
|
|
756
|
-
this.file = file;
|
|
757
|
-
this.name = "SeedHasNoSeed";
|
|
758
|
-
}
|
|
759
|
-
};
|
|
760
|
-
/**
|
|
761
|
-
* The migration files in a folder, by name, without reading them.
|
|
762
|
-
*
|
|
763
|
-
* Also what `gkm dev` compares against a construct's history to report what
|
|
764
|
-
* is pending, which is why it is separate from loading them.
|
|
765
|
-
*/
|
|
766
|
-
async function migrationFiles(folder) {
|
|
767
|
-
const entries = await (0, node_fs_promises.readdir)(folder, { withFileTypes: true }).catch((error) => {
|
|
768
|
-
if (error.code === "ENOENT") return [];
|
|
769
|
-
throw error;
|
|
770
|
-
});
|
|
771
|
-
const files = /* @__PURE__ */ new Map();
|
|
772
|
-
for (const entry of entries) {
|
|
773
|
-
if (!entry.isFile() || !isMigration(entry.name)) continue;
|
|
774
|
-
const name = entry.name.slice(0, -(0, node_path.extname)(entry.name).length);
|
|
775
|
-
if (files.has(name)) throw new DuplicateMigration(folder, name);
|
|
776
|
-
files.set(name, (0, node_path.join)(folder, entry.name));
|
|
777
|
-
}
|
|
778
|
-
return files;
|
|
779
|
-
}
|
|
780
|
-
/** A Kysely provider over one construct's folder. */
|
|
781
|
-
function folderProvider(folder, raw) {
|
|
782
|
-
return { async getMigrations() {
|
|
783
|
-
const migrations = {};
|
|
784
|
-
for (const [name, file] of await migrationFiles(folder)) migrations[name] = (0, node_path.extname)(file) === ".sql" ? await sqlMigration(file, raw) : await scriptMigration(file);
|
|
785
|
-
return migrations;
|
|
786
|
-
} };
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
* The seeds in a folder, loaded, in name order.
|
|
790
|
-
*
|
|
791
|
-
* Every one runs on every pass — there is no history to consult — so the order
|
|
792
|
-
* is the only thing between two seeds where one reads what another writes.
|
|
793
|
-
* Name them to sort that way.
|
|
794
|
-
*/
|
|
795
|
-
async function loadSeeds(folder, raw) {
|
|
796
|
-
const files = [...await migrationFiles(folder)].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
797
|
-
const seeds = [];
|
|
798
|
-
for (const [name, file] of files) seeds.push({
|
|
799
|
-
name,
|
|
800
|
-
run: (0, node_path.extname)(file) === ".sql" ? (await sqlMigration(file, raw)).up : await scriptSeed(file)
|
|
801
|
-
});
|
|
802
|
-
return seeds;
|
|
803
|
-
}
|
|
804
|
-
/**
|
|
805
|
-
* A seed script, imported as it is on disk now.
|
|
806
|
-
*
|
|
807
|
-
* Keyed by its modification time: a seed is run again after it is edited, and
|
|
808
|
-
* a process that has imported it once would otherwise run the old one.
|
|
809
|
-
*/
|
|
810
|
-
async function scriptSeed(file) {
|
|
811
|
-
const url = (0, node_url.pathToFileURL)(file);
|
|
812
|
-
url.searchParams.set("mtime", String((await (0, node_fs_promises.stat)(file)).mtimeMs));
|
|
813
|
-
const module = await import(url.href);
|
|
814
|
-
if (typeof module.seed !== "function") throw new SeedHasNoSeed(file);
|
|
815
|
-
return module.seed;
|
|
816
|
-
}
|
|
817
|
-
function isMigration(file) {
|
|
818
|
-
if (file.endsWith(".d.ts")) return false;
|
|
819
|
-
if (/\.(spec|test)\.[cm]?[jt]s$/.test(file)) return false;
|
|
820
|
-
const extension = (0, node_path.extname)(file);
|
|
821
|
-
return extension === ".sql" || SCRIPTS.has(extension);
|
|
822
|
-
}
|
|
823
|
-
async function scriptMigration(file) {
|
|
824
|
-
const module = await import((0, node_url.pathToFileURL)(file).href);
|
|
825
|
-
if (typeof module.up !== "function") throw new MigrationHasNoUp(file);
|
|
706
|
+
function defaultLayout(root) {
|
|
826
707
|
return {
|
|
827
|
-
|
|
828
|
-
|
|
708
|
+
buildRoot: root,
|
|
709
|
+
gkmRoot: ".",
|
|
710
|
+
tools: {
|
|
711
|
+
packageManager: "pnpm",
|
|
712
|
+
turboVersion: require_state.TURBO_VERSION,
|
|
713
|
+
monorepo: true
|
|
714
|
+
},
|
|
715
|
+
gkmPaths: ["gkm.config.*"]
|
|
829
716
|
};
|
|
830
717
|
}
|
|
831
|
-
/**
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
* One query rather than split on `;`: with no parameters, Postgres takes
|
|
835
|
-
* several statements in one message, and splitting by hand breaks on the first
|
|
836
|
-
* `;` inside a string or a function body. There is no `down` — a generated
|
|
837
|
-
* schema is rolled back by a migration that says how, not by guessing.
|
|
838
|
-
*/
|
|
839
|
-
async function sqlMigration(file, raw) {
|
|
840
|
-
const statements = await (0, node_fs_promises.readFile)(file, "utf-8");
|
|
841
|
-
return { up: async (db) => {
|
|
842
|
-
await raw.raw(statements).execute(db);
|
|
843
|
-
} };
|
|
718
|
+
/** The id the stack's compose file names an app's build credentials by. */
|
|
719
|
+
function credentialsSecret(app) {
|
|
720
|
+
return `${app}_credentials`;
|
|
844
721
|
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
* Bring each construct's schema up to its migrations folder.
|
|
849
|
-
*
|
|
850
|
-
* Which constructs, in what order, from which folder, is `migrationTargets`'
|
|
851
|
-
* answer and nobody else's. What is decided here is only how one target is
|
|
852
|
-
* run: as its owner, in its own schema, with a history of its own.
|
|
853
|
-
*/
|
|
854
|
-
/** A folder under `db/` that names no construct. */
|
|
855
|
-
var UnknownMigrationFolder = class extends Error {
|
|
856
|
-
folder;
|
|
857
|
-
known;
|
|
858
|
-
constructor(folder, known) {
|
|
859
|
-
super(`${folder} names no database construct, so its migrations would never run. ${known.length > 0 ? `The folders that do: ${known.join(", ")}.` : "This project declares no database."} Rename the folder after the construct it belongs to.`);
|
|
860
|
-
this.folder = folder;
|
|
861
|
-
this.known = known;
|
|
862
|
-
this.name = "UnknownMigrationFolder";
|
|
863
|
-
}
|
|
864
|
-
};
|
|
865
|
-
/** A construct was asked for by a name that takes no migrations. */
|
|
866
|
-
var NoSuchMigrationTarget = class extends Error {
|
|
867
|
-
construct;
|
|
868
|
-
known;
|
|
869
|
-
constructor(construct, known) {
|
|
870
|
-
super(`'${construct}' is not a database construct. ` + (known.length > 0 ? `The ones with migrations: ${known.join(", ")}.` : "This project declares no database."));
|
|
871
|
-
this.construct = construct;
|
|
872
|
-
this.known = known;
|
|
873
|
-
this.name = "NoSuchMigrationTarget";
|
|
874
|
-
}
|
|
875
|
-
};
|
|
876
|
-
/**
|
|
877
|
-
* A migration left directly in a construct's folder, where nothing reads it.
|
|
878
|
-
*
|
|
879
|
-
* Migrations moved into `migrations/` so seeds could sit beside them. A file
|
|
880
|
-
* still at the old level would otherwise never run, and nothing would say so.
|
|
881
|
-
*/
|
|
882
|
-
var MigrationsOutsideFolder = class extends Error {
|
|
883
|
-
folder;
|
|
884
|
-
files;
|
|
885
|
-
constructor(folder, files) {
|
|
886
|
-
super(`${folder} has ${files.join(", ")} directly inside it, where nothing runs them. Migrations live in ${folder}/migrations/ and seeds in ${folder}/seeds/ — move ${files.length === 1 ? "it" : "them"} there.`);
|
|
887
|
-
this.folder = folder;
|
|
888
|
-
this.files = files;
|
|
889
|
-
this.name = "MigrationsOutsideFolder";
|
|
890
|
-
}
|
|
891
|
-
};
|
|
892
|
-
/** A folder inside a construct's folder that is neither `migrations` nor `seeds`. */
|
|
893
|
-
var UnknownDatabaseFolder = class extends Error {
|
|
894
|
-
folder;
|
|
895
|
-
constructor(folder) {
|
|
896
|
-
super(`${folder} is neither migrations/ nor seeds/, so nothing in it would ever run. A construct's folder holds those two; rename or remove it.`);
|
|
897
|
-
this.folder = folder;
|
|
898
|
-
this.name = "UnknownDatabaseFolder";
|
|
899
|
-
}
|
|
900
|
-
};
|
|
901
|
-
/** A seed failed; its own writes are rolled back, the ones before it stay. */
|
|
902
|
-
var SeedFailed = class extends Error {
|
|
903
|
-
construct;
|
|
904
|
-
seed;
|
|
905
|
-
cause;
|
|
906
|
-
constructor(construct, seed, cause) {
|
|
907
|
-
super(`${construct}: seed '${seed}' failed — ${cause instanceof Error ? cause.message : String(cause)}. Its writes were rolled back; fix it and run it again.`);
|
|
908
|
-
this.construct = construct;
|
|
909
|
-
this.seed = seed;
|
|
910
|
-
this.cause = cause;
|
|
911
|
-
this.name = "SeedFailed";
|
|
912
|
-
}
|
|
913
|
-
};
|
|
914
|
-
/** A construct with roles has no owner URL to migrate with. */
|
|
915
|
-
var NoOwnerCredential = class extends Error {
|
|
916
|
-
construct;
|
|
917
|
-
key;
|
|
918
|
-
constructor(construct, key) {
|
|
919
|
-
super(`${construct} has no ${key} to migrate with. Migrations run as the owner role — the runtime one cannot create a table — and nothing resolved its URL. Is the stage reconciled?`);
|
|
920
|
-
this.construct = construct;
|
|
921
|
-
this.key = key;
|
|
922
|
-
this.name = "NoOwnerCredential";
|
|
923
|
-
}
|
|
924
|
-
};
|
|
925
|
-
/** A migration failed; the ones before it in the run stay applied. */
|
|
926
|
-
var MigrationFailed = class extends Error {
|
|
927
|
-
construct;
|
|
928
|
-
migration;
|
|
929
|
-
cause;
|
|
930
|
-
constructor(construct, migration, cause) {
|
|
931
|
-
super(`${construct}: migration ${migration ? `'${migration}' ` : ""}failed — ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
932
|
-
this.construct = construct;
|
|
933
|
-
this.migration = migration;
|
|
934
|
-
this.cause = cause;
|
|
935
|
-
this.name = "MigrationFailed";
|
|
936
|
-
}
|
|
937
|
-
};
|
|
938
|
-
/** The project's Kysely could not be found from where a database is declared. */
|
|
939
|
-
var KyselyNotFound = class extends Error {
|
|
940
|
-
from;
|
|
941
|
-
constructor(from) {
|
|
942
|
-
super(`Could not resolve 'kysely' from ${from}. Migrations run with the project's own Kysely — install it where the database is declared.`);
|
|
943
|
-
this.from = from;
|
|
944
|
-
this.name = "KyselyNotFound";
|
|
945
|
-
}
|
|
946
|
-
};
|
|
947
|
-
/** Apply every pending migration, construct by construct, parents first. */
|
|
948
|
-
async function migrateDatabases(options) {
|
|
949
|
-
const runs = [];
|
|
950
|
-
for (const target of await targetsFor(options)) {
|
|
951
|
-
if ((await migrationFiles((0, node_path.join)(options.root, target.migrations))).size === 0) {
|
|
952
|
-
runs.push({
|
|
953
|
-
target,
|
|
954
|
-
applied: []
|
|
955
|
-
});
|
|
956
|
-
continue;
|
|
957
|
-
}
|
|
958
|
-
const applied = await withMigrator(options, target, async (migrator) => {
|
|
959
|
-
const { error, results = [] } = await migrator.migrateToLatest();
|
|
960
|
-
if (error) {
|
|
961
|
-
const failed = results.find((result) => result.status === "Error");
|
|
962
|
-
throw new MigrationFailed(target.id, failed?.migrationName, error);
|
|
963
|
-
}
|
|
964
|
-
return results.filter((result) => result.status === "Success").map((result) => result.migrationName);
|
|
965
|
-
});
|
|
966
|
-
runs.push({
|
|
967
|
-
target,
|
|
968
|
-
applied
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
return runs;
|
|
722
|
+
/** The file beside the compose file an app's build credentials are read from. */
|
|
723
|
+
function credentialsFile(app) {
|
|
724
|
+
return `${app}.credentials`;
|
|
972
725
|
}
|
|
973
726
|
/**
|
|
974
|
-
*
|
|
975
|
-
*
|
|
976
|
-
*
|
|
727
|
+
* The stack with each backend's image built with its encrypted credentials:
|
|
728
|
+
* a BuildKit secret per app — the file `credentialsFile` names, mounted as
|
|
729
|
+
* `gkm_credentials` — and the hash naming them as a build arg, so a new key
|
|
730
|
+
* rebuilds the layer that embeds them. Each backend's env file gains the
|
|
731
|
+
* `GKM_MASTER_KEY` that decrypts them, the way a Dokploy deploy injects it.
|
|
977
732
|
*
|
|
978
|
-
*
|
|
979
|
-
* history: a seed is an upsert, and a changed one is applied by the next run.
|
|
980
|
-
* Each runs in its own transaction, as the construct's owner, so a failure
|
|
981
|
-
* leaves nothing half-written. Assumes the schema is migrated —
|
|
982
|
-
* {@link migrateAndSeed} is what makes that true.
|
|
733
|
+
* Pure: the caller encrypted them.
|
|
983
734
|
*/
|
|
984
|
-
|
|
985
|
-
const
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
735
|
+
function withBuildCredentials(stack, credentials) {
|
|
736
|
+
const services = { ...stack.compose.services };
|
|
737
|
+
const secrets = { ...stack.compose.secrets };
|
|
738
|
+
const apps = stack.apps.map((app) => {
|
|
739
|
+
const own = credentials[app.name];
|
|
740
|
+
const service = services[app.name];
|
|
741
|
+
if (!own || !service?.build) return app;
|
|
742
|
+
const [key, value] = own.buildArg.split("=");
|
|
743
|
+
services[app.name] = {
|
|
744
|
+
...service,
|
|
745
|
+
build: {
|
|
746
|
+
...service.build,
|
|
747
|
+
args: {
|
|
748
|
+
...service.build.args,
|
|
749
|
+
[key]: value
|
|
750
|
+
},
|
|
751
|
+
secrets: [{
|
|
752
|
+
source: credentialsSecret(app.name),
|
|
753
|
+
target: "gkm_credentials"
|
|
754
|
+
}]
|
|
1004
755
|
}
|
|
1005
|
-
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
* Migrate, then seed: a seed only ever runs against the schema it was written
|
|
1016
|
-
* for.
|
|
1017
|
-
*
|
|
1018
|
-
* With `only`, the constructs it lives in are migrated too — a tenant's seed
|
|
1019
|
-
* cannot run before the database that owns its schema exists — and only it is
|
|
1020
|
-
* seeded.
|
|
1021
|
-
*/
|
|
1022
|
-
async function migrateAndSeed(options) {
|
|
1023
|
-
const migrations = [];
|
|
1024
|
-
for (const target of await withParents(options)) migrations.push(...await migrateDatabases({
|
|
1025
|
-
...options,
|
|
1026
|
-
only: target.id
|
|
1027
|
-
}));
|
|
756
|
+
};
|
|
757
|
+
secrets[credentialsSecret(app.name)] = { file: `./${credentialsFile(app.name)}` };
|
|
758
|
+
return {
|
|
759
|
+
...app,
|
|
760
|
+
env: {
|
|
761
|
+
...app.env,
|
|
762
|
+
GKM_MASTER_KEY: own.masterKey
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
});
|
|
1028
766
|
return {
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
const chosen = await targetsFor(options);
|
|
1036
|
-
if (!options.only) return chosen;
|
|
1037
|
-
const all = (0, _geekmidas_manifest.migrationTargets)(options.manifest);
|
|
1038
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1039
|
-
for (const target of chosen) {
|
|
1040
|
-
let current = target;
|
|
1041
|
-
while (current) {
|
|
1042
|
-
ids.add(current.id);
|
|
1043
|
-
const parent = current.of;
|
|
1044
|
-
current = parent ? all.find((t) => t.id === parent) : void 0;
|
|
767
|
+
...stack,
|
|
768
|
+
apps,
|
|
769
|
+
compose: {
|
|
770
|
+
...stack.compose,
|
|
771
|
+
services,
|
|
772
|
+
...Object.keys(secrets).length ? { secrets } : {}
|
|
1045
773
|
}
|
|
1046
|
-
}
|
|
1047
|
-
return all.filter((target) => ids.has(target.id));
|
|
1048
|
-
}
|
|
1049
|
-
/**
|
|
1050
|
-
* What each construct's folder has that its history does not — without
|
|
1051
|
-
* applying any of it. What `gkm dev` reports.
|
|
1052
|
-
*/
|
|
1053
|
-
async function pendingMigrations(options) {
|
|
1054
|
-
const found = [];
|
|
1055
|
-
for (const target of await targetsFor(options)) {
|
|
1056
|
-
if ((await migrationFiles((0, node_path.join)(options.root, target.migrations))).size === 0) continue;
|
|
1057
|
-
const pending = await withMigrator(options, target, async (migrator) => (await migrator.getMigrations()).filter((migration) => migration.executedAt === void 0).map((migration) => migration.name));
|
|
1058
|
-
if (pending.length > 0) found.push({
|
|
1059
|
-
target,
|
|
1060
|
-
pending
|
|
1061
|
-
});
|
|
1062
|
-
}
|
|
1063
|
-
return found;
|
|
1064
|
-
}
|
|
1065
|
-
/**
|
|
1066
|
-
* The targets this run covers, with every folder under `db/` accounted for.
|
|
1067
|
-
*
|
|
1068
|
-
* A folder that names no construct is an error rather than something to skip:
|
|
1069
|
-
* a typo in its name is otherwise a migration that silently never runs.
|
|
1070
|
-
*/
|
|
1071
|
-
async function targetsFor(options) {
|
|
1072
|
-
const targets = (0, _geekmidas_manifest.migrationTargets)(options.manifest);
|
|
1073
|
-
const folders = targets.map((target) => target.folder);
|
|
1074
|
-
for (const folder of await foldersIn((0, node_path.join)(options.root, _geekmidas_manifest.MIGRATIONS_ROOT))) {
|
|
1075
|
-
const relative = `${_geekmidas_manifest.MIGRATIONS_ROOT}/${folder}`;
|
|
1076
|
-
if (!folders.includes(relative)) throw new UnknownMigrationFolder(relative, folders);
|
|
1077
|
-
await checkLayout(options.root, relative);
|
|
1078
|
-
}
|
|
1079
|
-
if (!options.only) return targets;
|
|
1080
|
-
const id = (0, _geekmidas_manifest.canonicalId)(options.only);
|
|
1081
|
-
const chosen = targets.filter((target) => target.id === id);
|
|
1082
|
-
if (chosen.length === 0) throw new NoSuchMigrationTarget(options.only, targets.map((target) => target.id));
|
|
1083
|
-
return chosen;
|
|
1084
|
-
}
|
|
1085
|
-
/**
|
|
1086
|
-
* A construct's folder holds `migrations/` and `seeds/`, and nothing else —
|
|
1087
|
-
* anything beside them is a file or folder nothing would ever run.
|
|
1088
|
-
*/
|
|
1089
|
-
async function checkLayout(root, folder) {
|
|
1090
|
-
const entries = await (0, node_fs_promises.readdir)((0, node_path.join)(root, folder), { withFileTypes: true });
|
|
1091
|
-
const loose = entries.filter((entry) => entry.isFile() && !entry.name.startsWith(".")).map((entry) => entry.name);
|
|
1092
|
-
if (loose.length > 0) throw new MigrationsOutsideFolder(folder, loose);
|
|
1093
|
-
for (const entry of entries) if (entry.isDirectory() && !_geekmidas_manifest.DATABASE_FOLDERS.includes(entry.name)) throw new UnknownDatabaseFolder(`${folder}/${entry.name}`);
|
|
1094
|
-
}
|
|
1095
|
-
async function foldersIn(dir) {
|
|
1096
|
-
return (await (0, node_fs_promises.readdir)(dir, { withFileTypes: true }).catch((error) => {
|
|
1097
|
-
if (error.code === "ENOENT") return [];
|
|
1098
|
-
throw error;
|
|
1099
|
-
})).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
1100
|
-
}
|
|
1101
|
-
/**
|
|
1102
|
-
* A migrator for one target, connected as its owner.
|
|
1103
|
-
*
|
|
1104
|
-
* No `migrationTableSchema`: the owner role's `search_path` is pinned to the
|
|
1105
|
-
* construct's schema, so the history lands there — `app.kysely_migration` for
|
|
1106
|
-
* the database, `auth_database.kysely_migration` for its tenant — and two
|
|
1107
|
-
* constructs in one Postgres never share one.
|
|
1108
|
-
*
|
|
1109
|
-
* Unordered migrations are allowed. Files are timestamped, so a branch merged
|
|
1110
|
-
* after another's migration ran carries an older one; refusing it would make
|
|
1111
|
-
* every such merge a manual repair.
|
|
1112
|
-
*/
|
|
1113
|
-
async function withMigrator(options, target, run) {
|
|
1114
|
-
return withOwner(options, target, (db, { Migrator, sql }) => run(new Migrator({
|
|
1115
|
-
db,
|
|
1116
|
-
provider: folderProvider((0, node_path.join)(options.root, target.migrations), sql),
|
|
1117
|
-
allowUnorderedMigrations: true
|
|
1118
|
-
})));
|
|
1119
|
-
}
|
|
1120
|
-
/**
|
|
1121
|
-
* One target's database, connected as its owner and closed afterwards — what
|
|
1122
|
-
* migrations and seeds both run as.
|
|
1123
|
-
*/
|
|
1124
|
-
async function withOwner(options, target, run) {
|
|
1125
|
-
const kysely = await kyselyFrom(options.sources?.[target.id]?.file ?? (target.of ? options.sources?.[target.of]?.file : void 0) ?? (0, node_path.join)(options.root, "package.json"));
|
|
1126
|
-
const db = new kysely.Kysely({ dialect: new kysely.PostgresDialect({ pool: new pg.default.Pool(poolConfig(ownerUrl(options, target))) }) });
|
|
1127
|
-
try {
|
|
1128
|
-
return await run(db, kysely);
|
|
1129
|
-
} finally {
|
|
1130
|
-
await db.destroy();
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
/**
|
|
1134
|
-
* The owner's URL, with no fallback to the runtime one.
|
|
1135
|
-
*
|
|
1136
|
-
* The runtime role can create nothing, so falling back would only move the
|
|
1137
|
-
* failure to the first `CREATE TABLE` and make it read like a permissions
|
|
1138
|
-
* bug. The one exception is a database declared `roles: false`, where there is
|
|
1139
|
-
* no owner — both URLs are the master credential by design.
|
|
1140
|
-
*/
|
|
1141
|
-
function ownerUrl(options, target) {
|
|
1142
|
-
const key = (0, _geekmidas_manifest.provideKey)(target.id, "ownerUrl");
|
|
1143
|
-
const owner = options.env[key];
|
|
1144
|
-
if (owner) return owner;
|
|
1145
|
-
const database = options.manifest[target.of ?? target.id];
|
|
1146
|
-
if (database?.kind === "database" && database.roles === false) {
|
|
1147
|
-
const url = options.env[(0, _geekmidas_manifest.provideKey)(target.id, "url")];
|
|
1148
|
-
if (url) return url;
|
|
1149
|
-
}
|
|
1150
|
-
throw new NoOwnerCredential(target.id, key);
|
|
1151
|
-
}
|
|
1152
|
-
/**
|
|
1153
|
-
* Pool settings for a URL, with `?search_path=` as the startup option Postgres
|
|
1154
|
-
* reads. Only a `roles: false` URL carries it — a role pins its own.
|
|
1155
|
-
*/
|
|
1156
|
-
function poolConfig(url) {
|
|
1157
|
-
const parsed = new URL(url);
|
|
1158
|
-
const searchPath = parsed.searchParams.get("search_path");
|
|
1159
|
-
if (!searchPath) return { connectionString: url };
|
|
1160
|
-
parsed.searchParams.delete("search_path");
|
|
1161
|
-
return {
|
|
1162
|
-
connectionString: parsed.toString(),
|
|
1163
|
-
options: `-c search_path=${searchPath}`
|
|
1164
774
|
};
|
|
1165
775
|
}
|
|
1166
|
-
/**
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
try {
|
|
1170
|
-
const [main, migration] = await Promise.all([import((0, node_url.pathToFileURL)(require$1.resolve("kysely")).href), import((0, node_url.pathToFileURL)(require$1.resolve("kysely/migration")).href)]);
|
|
1171
|
-
return {
|
|
1172
|
-
Kysely: main.Kysely,
|
|
1173
|
-
PostgresDialect: main.PostgresDialect,
|
|
1174
|
-
sql: main.sql,
|
|
1175
|
-
Migrator: migration.Migrator
|
|
1176
|
-
};
|
|
1177
|
-
} catch {
|
|
1178
|
-
throw new KyselyNotFound(from);
|
|
1179
|
-
}
|
|
776
|
+
/** Render an app's env file: one `KEY=value` per line, read raw by compose. */
|
|
777
|
+
function envFile(env) {
|
|
778
|
+
return `${Object.entries(env).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${key}=${value}`).join("\n")}\n`;
|
|
1180
779
|
}
|
|
1181
780
|
//#endregion
|
|
1182
781
|
//#region src/target/compose/health.ts
|
|
@@ -1261,7 +860,11 @@ var ComposeAppsUnhealthy = class extends Error {
|
|
|
1261
860
|
* - What was started answers (`verify`): each app is asked through Caddy,
|
|
1262
861
|
* over HTTPS, with the certificate verified.
|
|
1263
862
|
*
|
|
1264
|
-
* Docker
|
|
863
|
+
* Every image is built inside Docker from a pruned slice of the build root —
|
|
864
|
+
* the same Dockerfiles `gkm docker` writes — so nothing is built on this
|
|
865
|
+
* machine before `docker compose build`.
|
|
866
|
+
*
|
|
867
|
+
* Docker, the registry, Postgres and the health probe are
|
|
1265
868
|
* injected, so the rules are asserted without a daemon; the defaults are the
|
|
1266
869
|
* real ones.
|
|
1267
870
|
*/
|
|
@@ -1285,33 +888,11 @@ var NoGitRevision = class extends Error {
|
|
|
1285
888
|
this.name = "NoGitRevision";
|
|
1286
889
|
}
|
|
1287
890
|
};
|
|
1288
|
-
/** A backend's production bundle did not build. */
|
|
1289
|
-
var BundleFailed = class extends Error {
|
|
1290
|
-
app;
|
|
1291
|
-
exitCode;
|
|
1292
|
-
stderr;
|
|
1293
|
-
constructor(app, exitCode, stderr) {
|
|
1294
|
-
super(`Bundling '${app}' for production failed (exit code ${exitCode}).${stderr.trim() ? `\n${stderr.trim().slice(-4e3)}` : ""}\nRun \`gkm build --provider server --production\` in the app's directory to see it again.`);
|
|
1295
|
-
this.app = app;
|
|
1296
|
-
this.exitCode = exitCode;
|
|
1297
|
-
this.stderr = stderr;
|
|
1298
|
-
this.name = "BundleFailed";
|
|
1299
|
-
}
|
|
1300
|
-
};
|
|
1301
|
-
/** The CLI's own entry, which the bundle step runs, is not where it should be. */
|
|
1302
|
-
var CliEntryNotFound = class extends Error {
|
|
1303
|
-
from;
|
|
1304
|
-
constructor(from) {
|
|
1305
|
-
super(`Could not find bin/gkm.mjs above ${from}, which bundling a backend runs. Reinstall @geekmidas/cli.`);
|
|
1306
|
-
this.from = from;
|
|
1307
|
-
this.name = "CliEntryNotFound";
|
|
1308
|
-
}
|
|
1309
|
-
};
|
|
1310
891
|
/** The commit HEAD is at, short — and `-dirty` when the tree has changes. */
|
|
1311
892
|
async function gitRevision(root) {
|
|
1312
893
|
let sha;
|
|
1313
894
|
try {
|
|
1314
|
-
sha = (await
|
|
895
|
+
sha = (await require_run.runOutput("git", [
|
|
1315
896
|
"rev-parse",
|
|
1316
897
|
"--short",
|
|
1317
898
|
"HEAD"
|
|
@@ -1320,7 +901,7 @@ async function gitRevision(root) {
|
|
|
1320
901
|
throw new NoGitRevision(root);
|
|
1321
902
|
}
|
|
1322
903
|
if (!sha) throw new NoGitRevision(root);
|
|
1323
|
-
return (await
|
|
904
|
+
return (await require_run.runOutput("git", ["status", "--porcelain"], { cwd: root }).catch(() => "")).trim() ? `${sha}-dirty` : sha;
|
|
1324
905
|
}
|
|
1325
906
|
/** The edge's ports, from the environment — 443 and 80 when unset. */
|
|
1326
907
|
function edgePorts(env = process.env) {
|
|
@@ -1336,49 +917,15 @@ function edgePorts(env = process.env) {
|
|
|
1336
917
|
http: read(EDGE_PORT_ENV.http, 80)
|
|
1337
918
|
};
|
|
1338
919
|
}
|
|
1339
|
-
/** `bin/gkm.mjs` of the CLI that is running. */
|
|
1340
|
-
function cliEntry() {
|
|
1341
|
-
const from = (0, node_path.dirname)((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
|
|
1342
|
-
for (let dir = from; (0, node_path.dirname)(dir) !== dir; dir = (0, node_path.dirname)(dir)) {
|
|
1343
|
-
const entry = (0, node_path.join)(dir, "bin", "gkm.mjs");
|
|
1344
|
-
if ((0, node_fs.existsSync)(entry)) return entry;
|
|
1345
|
-
}
|
|
1346
|
-
throw new CliEntryNotFound(from);
|
|
1347
|
-
}
|
|
1348
|
-
/** A cold production bundle is seconds; a hung one must not hold the lock. */
|
|
1349
|
-
const BUNDLE_TIMEOUT_MS = 6e5;
|
|
1350
|
-
/**
|
|
1351
|
-
* Bundle a backend with the gkm that is running — the same build a deploy
|
|
1352
|
-
* makes, so the image holds one file and no dependencies — in the run's
|
|
1353
|
-
* sandbox, because the build imports the project's code.
|
|
1354
|
-
*/
|
|
1355
|
-
async function bundleInSandbox(appRoot, ctx) {
|
|
1356
|
-
const sandbox = require_sandbox.activeSandbox() ?? new require_local.LocalSandbox({ root: ctx.cwd });
|
|
1357
|
-
const result = await sandbox.exec("node", [
|
|
1358
|
-
cliEntry(),
|
|
1359
|
-
"build",
|
|
1360
|
-
"--provider",
|
|
1361
|
-
"server",
|
|
1362
|
-
"--production"
|
|
1363
|
-
], {
|
|
1364
|
-
cwd: appRoot,
|
|
1365
|
-
env: sandbox.env,
|
|
1366
|
-
timeoutMs: BUNDLE_TIMEOUT_MS,
|
|
1367
|
-
output: ctx.childOutput,
|
|
1368
|
-
signal: ctx.signal
|
|
1369
|
-
});
|
|
1370
|
-
if (result.exitCode !== 0) throw new BundleFailed(appRoot, result.exitCode, result.stderr);
|
|
1371
|
-
}
|
|
1372
920
|
/**
|
|
1373
921
|
* The real ones. Each app is asked for three minutes before it counts as
|
|
1374
922
|
* down: a deployed stage's first ACME certificate can take that long.
|
|
1375
923
|
*/
|
|
1376
924
|
const defaultDeps = {
|
|
1377
925
|
docker: dockerCompose,
|
|
1378
|
-
bundle: bundleInSandbox,
|
|
1379
926
|
revision: gitRevision,
|
|
1380
927
|
sql: require_state.pgClient,
|
|
1381
|
-
migrate: migrateDatabases,
|
|
928
|
+
migrate: require_databases.migrateDatabases,
|
|
1382
929
|
probe: httpsProbe,
|
|
1383
930
|
healthAttempts: 90,
|
|
1384
931
|
healthIntervalMs: 2e3,
|
|
@@ -1400,7 +947,9 @@ async function validateCompose(ctx, deps, forced) {
|
|
|
1400
947
|
runnables
|
|
1401
948
|
});
|
|
1402
949
|
const { secrets, generated } = await stageSecrets(ctx, manifest);
|
|
1403
|
-
const
|
|
950
|
+
const masterKeys = {};
|
|
951
|
+
const layout = mode === "build" ? require_state.imageLayout(workspace) : void 0;
|
|
952
|
+
const composed = composeStack({
|
|
1404
953
|
workspace,
|
|
1405
954
|
manifest,
|
|
1406
955
|
runnables,
|
|
@@ -1413,12 +962,36 @@ async function validateCompose(ctx, deps, forced) {
|
|
|
1413
962
|
},
|
|
1414
963
|
secrets,
|
|
1415
964
|
ports: edgePorts(deps.env),
|
|
1416
|
-
|
|
1417
|
-
packages: Object.fromEntries(Object.entries(workspace.apps).map(([name, app]) => [name, require_state.appPackageName(root, name, app.path)]))
|
|
965
|
+
...layout ? { layout } : {}
|
|
1418
966
|
});
|
|
967
|
+
const credentials = {};
|
|
968
|
+
if (mode === "build") for (const app of composed.apps) {
|
|
969
|
+
if (app.kind !== "rest-api" || !app.env || !app.build) continue;
|
|
970
|
+
const { encrypted, iv, masterKey } = require_state.encryptSecrets(app.env);
|
|
971
|
+
credentials[app.name] = {
|
|
972
|
+
encrypted,
|
|
973
|
+
iv
|
|
974
|
+
};
|
|
975
|
+
ctx.secrets.mask(masterKey);
|
|
976
|
+
masterKeys[app.name] = {
|
|
977
|
+
masterKey,
|
|
978
|
+
buildArg: require_state.credentialsBuildArg({
|
|
979
|
+
encrypted,
|
|
980
|
+
iv
|
|
981
|
+
})
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
const stack = withBuildCredentials(composed, masterKeys);
|
|
1419
985
|
if (mode === "pull" && !ctx.dryRun) await assertImagesExist(deps.docker, tag, stack.apps);
|
|
1420
986
|
const dir = (0, node_path.join)(root, stackDir(stage));
|
|
1421
|
-
const previous = (await ctx.state.read(stage))?.state.
|
|
987
|
+
const previous = Object.fromEntries(Object.entries((await ctx.state.read(stage))?.state.releases ?? {}).map(([name, releases]) => {
|
|
988
|
+
const { ref, tag, digest } = releases.current;
|
|
989
|
+
return [name, {
|
|
990
|
+
ref,
|
|
991
|
+
...tag ? { tag } : {},
|
|
992
|
+
...digest ? { digest } : {}
|
|
993
|
+
}];
|
|
994
|
+
}));
|
|
1422
995
|
return {
|
|
1423
996
|
mode,
|
|
1424
997
|
stack,
|
|
@@ -1434,6 +1007,7 @@ async function validateCompose(ctx, deps, forced) {
|
|
|
1434
1007
|
generated,
|
|
1435
1008
|
previous,
|
|
1436
1009
|
files: [],
|
|
1010
|
+
credentials,
|
|
1437
1011
|
images: {},
|
|
1438
1012
|
changes: []
|
|
1439
1013
|
};
|
|
@@ -1450,7 +1024,7 @@ async function stageSecrets(ctx, manifest) {
|
|
|
1450
1024
|
secrets: stored,
|
|
1451
1025
|
generated: []
|
|
1452
1026
|
};
|
|
1453
|
-
const { secrets, generated } = require_state.withGeneratedSecrets(stored ??
|
|
1027
|
+
const { secrets, generated } = require_state.withGeneratedSecrets(stored ?? require_state.initStageSecrets(ctx.stage), manifest);
|
|
1454
1028
|
if (secrets.seed) ctx.secrets.mask(secrets.seed);
|
|
1455
1029
|
for (const value of Object.values(secrets.custom ?? {})) ctx.secrets.mask(value);
|
|
1456
1030
|
return {
|
|
@@ -1465,7 +1039,7 @@ async function stageSecrets(ctx, manifest) {
|
|
|
1465
1039
|
*/
|
|
1466
1040
|
async function planCompose(ctx, run) {
|
|
1467
1041
|
if (run.generated.length > 0) ctx.logger.info(`🔑 "${ctx.stage}" has no ${run.generated.join(", ")} yet; this dry run used values it did not keep.`);
|
|
1468
|
-
run.files = await writeStack(ctx.cwd, run.dir, run.stack);
|
|
1042
|
+
run.files = await writeStack(ctx.cwd, run.dir, run.stack, run.credentials);
|
|
1469
1043
|
printPlan(ctx, run);
|
|
1470
1044
|
const planned = (change) => {
|
|
1471
1045
|
run.changes.push(change);
|
|
@@ -1509,7 +1083,7 @@ async function provisionCompose(ctx, run, deps) {
|
|
|
1509
1083
|
await ctx.secrets.write(run.secrets);
|
|
1510
1084
|
ctx.logger.info(`🔑 Generated for "${ctx.stage}" (${ctx.secrets.store}): ${run.generated.join(", ")}`);
|
|
1511
1085
|
}
|
|
1512
|
-
run.files = await writeStack(ctx.cwd, run.dir, stack);
|
|
1086
|
+
run.files = await writeStack(ctx.cwd, run.dir, stack, run.credentials);
|
|
1513
1087
|
printPlan(ctx, run);
|
|
1514
1088
|
if (stack.infra.length > 0) {
|
|
1515
1089
|
ctx.logger.info(`\n🗄️ Starting ${stack.infra.join(", ")}…`);
|
|
@@ -1555,18 +1129,14 @@ async function prepareDatabases(ctx, run, deps) {
|
|
|
1555
1129
|
for (const { target, applied } of runs) if (applied.length > 0) ctx.logger.info(`🗄️ ${target.migrations}: applied ${applied.length}`);
|
|
1556
1130
|
}
|
|
1557
1131
|
/**
|
|
1558
|
-
* Each app's image: built from this checkout — every
|
|
1559
|
-
*
|
|
1132
|
+
* Each app's image: built from this checkout — inside Docker, every one of
|
|
1133
|
+
* them, from a pruned slice of the build root — or pulled at the tag. Nothing
|
|
1134
|
+
* live changes.
|
|
1560
1135
|
*/
|
|
1561
1136
|
async function buildCompose(ctx, run, deps) {
|
|
1562
1137
|
const { stack, ref } = run;
|
|
1563
1138
|
const apps = stack.apps.map((app) => app.name);
|
|
1564
1139
|
if (run.mode === "build") {
|
|
1565
|
-
for (const app of stack.apps.filter((a) => a.kind === "rest-api")) {
|
|
1566
|
-
ctx.signal.throwIfAborted();
|
|
1567
|
-
ctx.logger.info(`\n📦 Bundling ${app.name}…`);
|
|
1568
|
-
await deps.bundle((0, node_path.join)(ctx.cwd, app.path), ctx);
|
|
1569
|
-
}
|
|
1570
1140
|
ctx.logger.info("\n🐳 Building images…");
|
|
1571
1141
|
await deps.docker.build(ref, apps);
|
|
1572
1142
|
} else {
|
|
@@ -1637,7 +1207,7 @@ async function recordImages(ctx, run) {
|
|
|
1637
1207
|
ref: app.ref,
|
|
1638
1208
|
tag: app.tag
|
|
1639
1209
|
};
|
|
1640
|
-
require_state.
|
|
1210
|
+
require_state.recordRelease(journal.state, app.name, image);
|
|
1641
1211
|
}
|
|
1642
1212
|
journal.state.identity = ctx.identity.key;
|
|
1643
1213
|
await journal.save();
|
|
@@ -1749,7 +1319,7 @@ function applied(ctx, run, change) {
|
|
|
1749
1319
|
});
|
|
1750
1320
|
}
|
|
1751
1321
|
/** Write the stack's files: owner-only, since the env files hold secrets. */
|
|
1752
|
-
async function writeStack(root, dir, stack) {
|
|
1322
|
+
async function writeStack(root, dir, stack, credentials = {}) {
|
|
1753
1323
|
await (0, node_fs_promises.mkdir)(dir, {
|
|
1754
1324
|
recursive: true,
|
|
1755
1325
|
mode: 448
|
|
@@ -1765,21 +1335,11 @@ async function writeStack(root, dir, stack) {
|
|
|
1765
1335
|
await write((0, node_path.join)(dir, "docker-compose.yml"), composeYaml(stack));
|
|
1766
1336
|
await write((0, node_path.join)(dir, "Caddyfile"), stack.caddyfile);
|
|
1767
1337
|
for (const app of stack.apps) if (app.env) await write((0, node_path.join)(dir, `${app.name}.env`), envFile(app.env), 384);
|
|
1338
|
+
for (const [name, payload] of Object.entries(credentials)) await write((0, node_path.join)(dir, credentialsFile(name)), require_state.credentialsFileContent(payload), 384);
|
|
1768
1339
|
for (const [path, content] of Object.entries(stack.dockerfiles)) await write((0, node_path.join)(root, path), content);
|
|
1769
|
-
await
|
|
1340
|
+
await require_state.ensureDockerignore(require_state.findBuildRoot(root));
|
|
1770
1341
|
return files;
|
|
1771
1342
|
}
|
|
1772
|
-
/** Make sure the build context leaves `.gkm/compose` out. */
|
|
1773
|
-
async function ignoreStacks(root) {
|
|
1774
|
-
const path = (0, node_path.join)(root, ".dockerignore");
|
|
1775
|
-
if (!(0, node_fs.existsSync)(path)) {
|
|
1776
|
-
await (0, node_fs_promises.writeFile)(path, require_state.generateDockerignore());
|
|
1777
|
-
return;
|
|
1778
|
-
}
|
|
1779
|
-
const current = await (0, node_fs_promises.readFile)(path, "utf-8");
|
|
1780
|
-
if (/^\/?\.gkm\/compose\/?$|^\/?\.gkm\/?$/m.test(current)) return;
|
|
1781
|
-
await (0, node_fs_promises.appendFile)(path, `${current.endsWith("\n") ? "" : "\n"}\n# gkm compose's stacks: each app's env file holds its stage's secrets\n.gkm/compose\n`);
|
|
1782
|
-
}
|
|
1783
1343
|
function composeYaml(stack) {
|
|
1784
1344
|
const stage = stack.local ? "" : ` --stage ${stack.stage}`;
|
|
1785
1345
|
return `# Generated by gkm compose from the construct manifest — do not edit.
|
|
@@ -1858,72 +1418,6 @@ function composeTarget(options = {}) {
|
|
|
1858
1418
|
});
|
|
1859
1419
|
}
|
|
1860
1420
|
//#endregion
|
|
1861
|
-
Object.defineProperty(exports, "DuplicateMigration", {
|
|
1862
|
-
enumerable: true,
|
|
1863
|
-
get: function() {
|
|
1864
|
-
return DuplicateMigration;
|
|
1865
|
-
}
|
|
1866
|
-
});
|
|
1867
|
-
Object.defineProperty(exports, "KyselyNotFound", {
|
|
1868
|
-
enumerable: true,
|
|
1869
|
-
get: function() {
|
|
1870
|
-
return KyselyNotFound;
|
|
1871
|
-
}
|
|
1872
|
-
});
|
|
1873
|
-
Object.defineProperty(exports, "MigrationFailed", {
|
|
1874
|
-
enumerable: true,
|
|
1875
|
-
get: function() {
|
|
1876
|
-
return MigrationFailed;
|
|
1877
|
-
}
|
|
1878
|
-
});
|
|
1879
|
-
Object.defineProperty(exports, "MigrationHasNoUp", {
|
|
1880
|
-
enumerable: true,
|
|
1881
|
-
get: function() {
|
|
1882
|
-
return MigrationHasNoUp;
|
|
1883
|
-
}
|
|
1884
|
-
});
|
|
1885
|
-
Object.defineProperty(exports, "MigrationsOutsideFolder", {
|
|
1886
|
-
enumerable: true,
|
|
1887
|
-
get: function() {
|
|
1888
|
-
return MigrationsOutsideFolder;
|
|
1889
|
-
}
|
|
1890
|
-
});
|
|
1891
|
-
Object.defineProperty(exports, "NoOwnerCredential", {
|
|
1892
|
-
enumerable: true,
|
|
1893
|
-
get: function() {
|
|
1894
|
-
return NoOwnerCredential;
|
|
1895
|
-
}
|
|
1896
|
-
});
|
|
1897
|
-
Object.defineProperty(exports, "NoSuchMigrationTarget", {
|
|
1898
|
-
enumerable: true,
|
|
1899
|
-
get: function() {
|
|
1900
|
-
return NoSuchMigrationTarget;
|
|
1901
|
-
}
|
|
1902
|
-
});
|
|
1903
|
-
Object.defineProperty(exports, "SeedFailed", {
|
|
1904
|
-
enumerable: true,
|
|
1905
|
-
get: function() {
|
|
1906
|
-
return SeedFailed;
|
|
1907
|
-
}
|
|
1908
|
-
});
|
|
1909
|
-
Object.defineProperty(exports, "SeedHasNoSeed", {
|
|
1910
|
-
enumerable: true,
|
|
1911
|
-
get: function() {
|
|
1912
|
-
return SeedHasNoSeed;
|
|
1913
|
-
}
|
|
1914
|
-
});
|
|
1915
|
-
Object.defineProperty(exports, "UnknownDatabaseFolder", {
|
|
1916
|
-
enumerable: true,
|
|
1917
|
-
get: function() {
|
|
1918
|
-
return UnknownDatabaseFolder;
|
|
1919
|
-
}
|
|
1920
|
-
});
|
|
1921
|
-
Object.defineProperty(exports, "UnknownMigrationFolder", {
|
|
1922
|
-
enumerable: true,
|
|
1923
|
-
get: function() {
|
|
1924
|
-
return UnknownMigrationFolder;
|
|
1925
|
-
}
|
|
1926
|
-
});
|
|
1927
1421
|
Object.defineProperty(exports, "composeProject", {
|
|
1928
1422
|
enumerable: true,
|
|
1929
1423
|
get: function() {
|
|
@@ -1948,30 +1442,6 @@ Object.defineProperty(exports, "dockerCompose", {
|
|
|
1948
1442
|
return dockerCompose;
|
|
1949
1443
|
}
|
|
1950
1444
|
});
|
|
1951
|
-
Object.defineProperty(exports, "migrateAndSeed", {
|
|
1952
|
-
enumerable: true,
|
|
1953
|
-
get: function() {
|
|
1954
|
-
return migrateAndSeed;
|
|
1955
|
-
}
|
|
1956
|
-
});
|
|
1957
|
-
Object.defineProperty(exports, "migrateDatabases", {
|
|
1958
|
-
enumerable: true,
|
|
1959
|
-
get: function() {
|
|
1960
|
-
return migrateDatabases;
|
|
1961
|
-
}
|
|
1962
|
-
});
|
|
1963
|
-
Object.defineProperty(exports, "pendingMigrations", {
|
|
1964
|
-
enumerable: true,
|
|
1965
|
-
get: function() {
|
|
1966
|
-
return pendingMigrations;
|
|
1967
|
-
}
|
|
1968
|
-
});
|
|
1969
|
-
Object.defineProperty(exports, "seedDatabases", {
|
|
1970
|
-
enumerable: true,
|
|
1971
|
-
get: function() {
|
|
1972
|
-
return seedDatabases;
|
|
1973
|
-
}
|
|
1974
|
-
});
|
|
1975
1445
|
Object.defineProperty(exports, "stackDir", {
|
|
1976
1446
|
enumerable: true,
|
|
1977
1447
|
get: function() {
|
|
@@ -1979,4 +1449,4 @@ Object.defineProperty(exports, "stackDir", {
|
|
|
1979
1449
|
}
|
|
1980
1450
|
});
|
|
1981
1451
|
|
|
1982
|
-
//# sourceMappingURL=compose-
|
|
1452
|
+
//# sourceMappingURL=compose-5oNHAKNT.cjs.map
|