@geekmidas/cli 10.0.0-alpha.12 → 10.0.0-alpha.13
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/dist/{HostingerProvider-BcyFRbqV.mjs → HostingerProvider-BY26bWwB.mjs} +20 -21
- package/dist/HostingerProvider-BY26bWwB.mjs.map +1 -0
- package/dist/{HostingerProvider-BOvsgATO.cjs → HostingerProvider-BZFGYYVA.cjs} +21 -22
- package/dist/HostingerProvider-BZFGYYVA.cjs.map +1 -0
- package/dist/{LocalStateProvider-yjXZXZDM.cjs → LocalStateProvider-7HR6SS2t.cjs} +11 -6
- package/dist/LocalStateProvider-7HR6SS2t.cjs.map +1 -0
- package/dist/{LocalStateProvider-Bq-0C0sg.mjs → LocalStateProvider-D7QyJoLM.mjs} +10 -4
- package/dist/LocalStateProvider-D7QyJoLM.mjs.map +1 -0
- package/dist/{Route53Provider-C0xmer8U.mjs → Route53Provider-Cvj40A8I.mjs} +12 -12
- package/dist/Route53Provider-Cvj40A8I.mjs.map +1 -0
- package/dist/{Route53Provider-CH9XH7bz.cjs → Route53Provider-DVILBsvV.cjs} +20 -21
- package/dist/Route53Provider-DVILBsvV.cjs.map +1 -0
- package/dist/{SSMStateProvider-DOZifZfE.mjs → SSMStateProvider-B0Hu1MKZ.mjs} +13 -4
- package/dist/SSMStateProvider-B0Hu1MKZ.mjs.map +1 -0
- package/dist/{SSMStateProvider-CXtNgPfy.cjs → SSMStateProvider-VrQ-yeqd.cjs} +17 -9
- package/dist/SSMStateProvider-VrQ-yeqd.cjs.map +1 -0
- package/dist/{backup-provisioner-cE2PuCTb.cjs → backup-provisioner-BmhIO_Yr.cjs} +21 -19
- package/dist/backup-provisioner-BmhIO_Yr.cjs.map +1 -0
- package/dist/{backup-provisioner-DXXg6FIL.mjs → backup-provisioner-DIVCbfee.mjs} +10 -7
- package/dist/backup-provisioner-DIVCbfee.mjs.map +1 -0
- package/dist/{bundler-BMekgx7a.cjs → bundler-BeNDZdHQ.cjs} +9 -12
- package/dist/bundler-BeNDZdHQ.cjs.map +1 -0
- package/dist/{bundler-Bux2iF-v.mjs → bundler-BodTL4kf.mjs} +8 -10
- package/dist/bundler-BodTL4kf.mjs.map +1 -0
- package/dist/{config-RYR9j6EF.cjs → config-Q1rvKHvw.cjs} +74 -69
- package/dist/config-Q1rvKHvw.cjs.map +1 -0
- package/dist/{config-DTsVjKZD.mjs → config-pqGD3hF9.mjs} +26 -14
- package/dist/config-pqGD3hF9.mjs.map +1 -0
- package/dist/config.cjs +4 -5
- package/dist/config.d.cts +14 -17
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +14 -17
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -5
- package/dist/{credentials-jMJC63qs.mjs → credentials-BekkKtY_.mjs} +234 -79
- package/dist/credentials-BekkKtY_.mjs.map +1 -0
- package/dist/{credentials-DQRvPz2S.cjs → credentials-Q6F0uqJq.cjs} +384 -236
- package/dist/credentials-Q6F0uqJq.cjs.map +1 -0
- package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
- package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
- package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
- package/dist/deploy/sniffer-hooks.cjs +13 -7
- package/dist/deploy/sniffer-hooks.cjs.map +1 -1
- package/dist/deploy/sniffer-hooks.d.cts +1 -2
- package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
- package/dist/deploy/sniffer-hooks.d.mts +1 -2
- package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
- package/dist/deploy/sniffer-hooks.mjs +9 -2
- package/dist/deploy/sniffer-hooks.mjs.map +1 -1
- package/dist/deploy/sniffer-loader.cjs +16 -7
- package/dist/deploy/sniffer-loader.cjs.map +1 -1
- package/dist/deploy/sniffer-loader.d.cts +1 -1
- package/dist/deploy/sniffer-loader.d.mts +1 -1
- package/dist/deploy/sniffer-loader.mjs +13 -2
- package/dist/deploy/sniffer-loader.mjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.cjs +11 -11
- package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
- package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
- package/dist/deploy/sniffer-routes-worker.mjs +2 -2
- package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
- package/dist/deploy/sniffer-worker.cjs +15 -6
- package/dist/deploy/sniffer-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-worker.d.cts +1 -3
- package/dist/deploy/sniffer-worker.d.cts.map +1 -1
- package/dist/deploy/sniffer-worker.d.mts +1 -3
- package/dist/deploy/sniffer-worker.d.mts.map +1 -1
- package/dist/deploy/sniffer-worker.mjs +15 -4
- package/dist/deploy/sniffer-worker.mjs.map +1 -1
- package/dist/{discover-DmW9Bscc.cjs → discover-BERGFg8v.cjs} +68 -70
- package/dist/discover-BERGFg8v.cjs.map +1 -0
- package/dist/{discover-BYHQwQqu.mjs → discover-CK-n3w6b.mjs} +22 -20
- package/dist/discover-CK-n3w6b.mjs.map +1 -0
- package/dist/{emit-CUD1BWls.cjs → emit-BdoPFjZf.cjs} +53 -36
- package/dist/emit-BdoPFjZf.cjs.map +1 -0
- package/dist/{emit-CIlvnDvV.mjs → emit-Bzq7JsMP.mjs} +24 -6
- package/dist/emit-Bzq7JsMP.mjs.map +1 -0
- package/dist/{fullstack-secrets-B6KBHf-g.mjs → fullstack-secrets-BET8gqwK.mjs} +9 -15
- package/dist/fullstack-secrets-BET8gqwK.mjs.map +1 -0
- package/dist/{fullstack-secrets-DL8v0y4D.cjs → fullstack-secrets-DXsWO-5m.cjs} +19 -26
- package/dist/fullstack-secrets-DXsWO-5m.cjs.map +1 -0
- package/dist/{generator-VE2JrFlY.mjs → generator-LfZU7NlU.mjs} +8 -14
- package/dist/generator-LfZU7NlU.mjs.map +1 -0
- package/dist/{generator-CNzBw7g5.cjs → generator-Wdfp0jCS.cjs} +38 -45
- package/dist/generator-Wdfp0jCS.cjs.map +1 -0
- package/dist/{github-BThvbf2W.cjs → github-BfflNPVe.cjs} +36 -30
- package/dist/{github-BThvbf2W.cjs.map → github-BfflNPVe.cjs.map} +1 -1
- package/dist/{github-DpMZurEK.mjs → github-CRwnxKmD.mjs} +27 -20
- package/dist/github-CRwnxKmD.mjs.map +1 -0
- package/dist/{index-BzJ7QJ9c.d.mts → index-Cd-qeOam.d.mts} +3 -8
- package/dist/index-Cd-qeOam.d.mts.map +1 -0
- package/dist/{index-CfMjtdVC.d.cts → index-D-iAVHx-.d.cts} +3 -8
- package/dist/index-D-iAVHx-.d.cts.map +1 -0
- package/dist/index.cjs +2894 -1582
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2765 -1470
- package/dist/index.mjs.map +1 -1
- package/dist/{keystore-TxeYM7an.mjs → keystore-B4PRlbgE.mjs} +5 -7
- package/dist/keystore-B4PRlbgE.mjs.map +1 -0
- package/dist/{keystore-C9rint2E.cjs → keystore-DgGRj2Yy.cjs} +23 -26
- package/dist/keystore-DgGRj2Yy.cjs.map +1 -0
- package/dist/{openapi-DWLTsYLL.cjs → openapi-Dcbme-Us.cjs} +134 -171
- package/dist/openapi-Dcbme-Us.cjs.map +1 -0
- package/dist/openapi-react-query.cjs +156 -2
- package/dist/openapi-react-query.cjs.map +1 -0
- package/dist/openapi-react-query.d.cts +1 -3
- package/dist/openapi-react-query.d.cts.map +1 -1
- package/dist/openapi-react-query.d.mts +1 -3
- package/dist/openapi-react-query.d.mts.map +1 -1
- package/dist/openapi-react-query.mjs +156 -2
- package/dist/openapi-react-query.mjs.map +1 -0
- package/dist/{openapi-Bs3-5q_r.mjs → openapi-vy4JzhUv.mjs} +76 -106
- package/dist/openapi-vy4JzhUv.mjs.map +1 -0
- package/dist/openapi.cjs +3 -6
- package/dist/openapi.d.cts +8 -11
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.mts +8 -11
- package/dist/openapi.d.mts.map +1 -1
- package/dist/openapi.mjs +2 -6
- package/dist/reconcile/public.cjs +4 -4
- package/dist/reconcile/public.d.cts +8 -26
- package/dist/reconcile/public.d.cts.map +1 -1
- package/dist/reconcile/public.d.mts +8 -26
- package/dist/reconcile/public.d.mts.map +1 -1
- package/dist/reconcile/public.mjs +3 -4
- package/dist/{reconcile-Bhw5fmKu.cjs → reconcile-Dd2iyILf.cjs} +4 -7
- package/dist/reconcile-Dd2iyILf.cjs.map +1 -0
- package/dist/{reconcile-BI0tWkwz.mjs → reconcile-DhQ00DpU.mjs} +4 -7
- package/dist/reconcile-DhQ00DpU.mjs.map +1 -0
- package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
- package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
- package/dist/{storage-CSNplaJn.cjs → storage-C-30BD1e.cjs} +59 -69
- package/dist/storage-C-30BD1e.cjs.map +1 -0
- package/dist/{storage-B020InPW.mjs → storage-P_b3w7uj.mjs} +22 -13
- package/dist/storage-P_b3w7uj.mjs.map +1 -0
- package/dist/{sync-CzHXiR9c.mjs → sync-B3xxXtJT.mjs} +18 -6
- package/dist/sync-B3xxXtJT.mjs.map +1 -0
- package/dist/{sync-0ILCb-1S.cjs → sync-D7uTIIEi.cjs} +43 -25
- package/dist/sync-D7uTIIEi.cjs.map +1 -0
- package/dist/types-BGo5TaNE.d.mts +6164 -0
- package/dist/types-BGo5TaNE.d.mts.map +1 -0
- package/dist/types-C5ZNpUad.d.cts +6165 -0
- package/dist/types-C5ZNpUad.d.cts.map +1 -0
- package/dist/workspace/index.cjs +3 -3
- package/dist/workspace/index.d.cts +3 -3
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +2 -3
- package/dist/{workspace-CtnZnWsa.mjs → workspace-CgwmXEtc.mjs} +712 -806
- package/dist/workspace-CgwmXEtc.mjs.map +1 -0
- package/dist/{workspace-DPV7FtAv.cjs → workspace-mFpI_ky_.cjs} +881 -976
- package/dist/workspace-mFpI_ky_.cjs.map +1 -0
- package/package.json +14 -14
- package/dist/CachedStateProvider-BEBl2wQT.cjs +0 -60
- package/dist/CachedStateProvider-BEBl2wQT.cjs.map +0 -1
- package/dist/CachedStateProvider-C-8wtlto.mjs +0 -3
- package/dist/CachedStateProvider-Co4n5Wvs.mjs +0 -54
- package/dist/CachedStateProvider-Co4n5Wvs.mjs.map +0 -1
- package/dist/CachedStateProvider-DqhGpzsm.cjs +0 -3
- package/dist/HostingerProvider-BOvsgATO.cjs.map +0 -1
- package/dist/HostingerProvider-BcyFRbqV.mjs.map +0 -1
- package/dist/LocalStateProvider-Bq-0C0sg.mjs.map +0 -1
- package/dist/LocalStateProvider-yjXZXZDM.cjs.map +0 -1
- package/dist/Route53Provider-C0xmer8U.mjs.map +0 -1
- package/dist/Route53Provider-CH9XH7bz.cjs.map +0 -1
- package/dist/SSMStateProvider-CXtNgPfy.cjs.map +0 -1
- package/dist/SSMStateProvider-DOZifZfE.mjs.map +0 -1
- package/dist/backup-provisioner-DXXg6FIL.mjs.map +0 -1
- package/dist/backup-provisioner-cE2PuCTb.cjs.map +0 -1
- package/dist/bundler-BMekgx7a.cjs.map +0 -1
- package/dist/bundler-Bux2iF-v.mjs.map +0 -1
- package/dist/chunk-Duj1WY3L.mjs +0 -7
- package/dist/config-DTsVjKZD.mjs.map +0 -1
- package/dist/config-RYR9j6EF.cjs.map +0 -1
- package/dist/credentials-B5zRHdAl.mjs +0 -141
- package/dist/credentials-B5zRHdAl.mjs.map +0 -1
- package/dist/credentials-BapzjyV5.cjs +0 -195
- package/dist/credentials-BapzjyV5.cjs.map +0 -1
- package/dist/credentials-DQRvPz2S.cjs.map +0 -1
- package/dist/credentials-jMJC63qs.mjs.map +0 -1
- package/dist/discover-BYHQwQqu.mjs.map +0 -1
- package/dist/discover-DmW9Bscc.cjs.map +0 -1
- package/dist/dokploy-api-5cK2InBm.cjs +0 -3
- package/dist/dokploy-api-D2Ny4Jrc.mjs +0 -3
- package/dist/dokploy-api-pdaBryoY.mjs +0 -706
- package/dist/dokploy-api-pdaBryoY.mjs.map +0 -1
- package/dist/dokploy-api-zqKe9lHH.cjs +0 -718
- package/dist/dokploy-api-zqKe9lHH.cjs.map +0 -1
- package/dist/emit-CIlvnDvV.mjs.map +0 -1
- package/dist/emit-CUD1BWls.cjs.map +0 -1
- package/dist/encryption-D2pL3tHH.cjs +0 -54
- package/dist/encryption-D2pL3tHH.cjs.map +0 -1
- package/dist/encryption-YDsXXi6w.mjs +0 -3
- package/dist/encryption-_4zwjOAR.mjs +0 -42
- package/dist/encryption-_4zwjOAR.mjs.map +0 -1
- package/dist/encryption-sQ2Oxx0d.cjs +0 -4
- package/dist/fullstack-secrets-B6KBHf-g.mjs.map +0 -1
- package/dist/fullstack-secrets-DL8v0y4D.cjs.map +0 -1
- package/dist/generator-CNzBw7g5.cjs.map +0 -1
- package/dist/generator-VE2JrFlY.mjs.map +0 -1
- package/dist/github-DpMZurEK.mjs.map +0 -1
- package/dist/index-BzJ7QJ9c.d.mts.map +0 -1
- package/dist/index-CfMjtdVC.d.cts.map +0 -1
- package/dist/keystore-C9rint2E.cjs.map +0 -1
- package/dist/keystore-TxeYM7an.mjs.map +0 -1
- package/dist/openapi-Bs3-5q_r.mjs.map +0 -1
- package/dist/openapi-DWLTsYLL.cjs.map +0 -1
- package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
- package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
- package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
- package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
- package/dist/reconcile-BI0tWkwz.mjs.map +0 -1
- package/dist/reconcile-Bhw5fmKu.cjs.map +0 -1
- package/dist/setup-BmLoNrDX.mjs +0 -12
- package/dist/setup-BrR1_xGy.cjs +0 -12
- package/dist/setup-BsNR2LBG.cjs +0 -467
- package/dist/setup-BsNR2LBG.cjs.map +0 -1
- package/dist/setup-D5-JMknk.mjs +0 -437
- package/dist/setup-D5-JMknk.mjs.map +0 -1
- package/dist/storage-B020InPW.mjs.map +0 -1
- package/dist/storage-CSNplaJn.cjs.map +0 -1
- package/dist/storage-DGBzMLZa.mjs +0 -4
- package/dist/storage-DlVol_oj.cjs +0 -8
- package/dist/sync-0ILCb-1S.cjs.map +0 -1
- package/dist/sync-CzHXiR9c.mjs.map +0 -1
- package/dist/sync-DYENfOt4.cjs +0 -4
- package/dist/sync-HAau6h_R.mjs +0 -3
- package/dist/types-DVIx8I1N.d.mts +0 -1950
- package/dist/types-DVIx8I1N.d.mts.map +0 -1
- package/dist/types-PMP_qXRY.d.cts +0 -1950
- package/dist/types-PMP_qXRY.d.cts.map +0 -1
- package/dist/workspace-Cji6lE8E.cjs +0 -10
- package/dist/workspace-CkJAtRIX.mjs +0 -9
- package/dist/workspace-CtnZnWsa.mjs.map +0 -1
- package/dist/workspace-DPV7FtAv.cjs.map +0 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
|
|
2
|
+
import { a as DEFAULT_EVENTS$1, i as DEFAULT_CACHE, o as DEFAULT_STORAGE, t as discover } from "./discover-CK-n3w6b.mjs";
|
|
3
|
+
import { a as loadWorkspaceAppInfo, c as appKey, n as getAppNameFromCwd } from "./config-pqGD3hF9.mjs";
|
|
4
|
+
import { s as getDependencyEnvVars, t as allConstructGlobs } from "./workspace-CgwmXEtc.mjs";
|
|
5
|
+
import { r as generatePgBossUrl } from "./generator-LfZU7NlU.mjs";
|
|
6
|
+
import { n as readStageSecrets, o as toEmbeddableSecrets, r as secretsExist } from "./storage-P_b3w7uj.mjs";
|
|
6
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
-
import { dirname, join, resolve } from "node:path";
|
|
8
|
-
import { DEFAULT_POSTGRES_VERSION, cacheTable, cookieDomain, dependentsOf, provideKey, providedKeyFor, provisionOrder, publicEnvFor } from "@geekmidas/manifest";
|
|
9
8
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
9
|
+
import { dirname, join, resolve } from "node:path";
|
|
10
10
|
import { execFile, execSync } from "node:child_process";
|
|
11
|
+
import { DEFAULT_POSTGRES_VERSION, cacheTable, cookieDomain, dependentsOf, provideKey, providedKeyFor, provisionOrder, publicEnvFor } from "@geekmidas/manifest";
|
|
11
12
|
import { createServer } from "node:net";
|
|
12
13
|
import { config } from "dotenv";
|
|
13
14
|
import { parse as parse$1, stringify } from "yaml";
|
|
@@ -17,9 +18,22 @@ import { CreateBucketCommand, GetBucketPolicyCommand, HeadBucketCommand, PutBuck
|
|
|
17
18
|
import { Client } from "pg";
|
|
18
19
|
import { promisify } from "node:util";
|
|
19
20
|
import { cacheTableStatements } from "@geekmidas/cache/postgres";
|
|
20
|
-
|
|
21
21
|
//#region src/workspace/backends.ts
|
|
22
22
|
/**
|
|
23
|
+
* Which backend each declared kind resolves to — decided by where the project
|
|
24
|
+
* deploys, and by nothing else.
|
|
25
|
+
*
|
|
26
|
+
* These used to be read out of a `services:` block, where one key answered two
|
|
27
|
+
* questions: *does this exist* and *what backs it*. The first is the manifest's
|
|
28
|
+
* — a declared `Cache` is why there is a cache — and the second is the deploy
|
|
29
|
+
* target's, because the right cache for a Lambda is not the right cache for a
|
|
30
|
+
* box already running Postgres. With both answered elsewhere there was nothing
|
|
31
|
+
* left for the block to say, so it is gone and these read the target.
|
|
32
|
+
*
|
|
33
|
+
* Mail has no answer here at all: every provider speaks SMTP, so the provider
|
|
34
|
+
* is whichever one the stage's mail URL points at.
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
23
37
|
* Which family of defaults a workspace's deploy target belongs to.
|
|
24
38
|
*
|
|
25
39
|
* One question, asked once: **does this target run containers the project
|
|
@@ -57,9 +71,8 @@ function storageBackendFor(on) {
|
|
|
57
71
|
* `Queue` has no events at all, whatever the target.
|
|
58
72
|
*/
|
|
59
73
|
function eventsBackendFor(on) {
|
|
60
|
-
return DEFAULT_EVENTS[on];
|
|
74
|
+
return DEFAULT_EVENTS$1[on];
|
|
61
75
|
}
|
|
62
|
-
|
|
63
76
|
//#endregion
|
|
64
77
|
//#region src/reconcile/containers.ts
|
|
65
78
|
/**
|
|
@@ -185,17 +198,15 @@ function portKeys(containers) {
|
|
|
185
198
|
* survives days of dev is noise rather than state.
|
|
186
199
|
*/
|
|
187
200
|
function volumeOf(container) {
|
|
188
|
-
|
|
201
|
+
return {
|
|
189
202
|
postgres: "postgres-data",
|
|
190
203
|
minio: "minio-data",
|
|
191
204
|
redis: "redis-data",
|
|
192
205
|
rabbitmq: "rabbitmq-data",
|
|
193
206
|
localstack: "localstack-data",
|
|
194
207
|
caddy: "caddy-data"
|
|
195
|
-
};
|
|
196
|
-
return volumes[container];
|
|
208
|
+
}[container];
|
|
197
209
|
}
|
|
198
|
-
|
|
199
210
|
//#endregion
|
|
200
211
|
//#region src/reconcile/caddyfile.ts
|
|
201
212
|
/**
|
|
@@ -272,7 +283,7 @@ function portOf(address) {
|
|
|
272
283
|
const { port, protocol } = new URL(address);
|
|
273
284
|
return port || (protocol === "https:" ? "443" : "80");
|
|
274
285
|
} catch {
|
|
275
|
-
return
|
|
286
|
+
return;
|
|
276
287
|
}
|
|
277
288
|
}
|
|
278
289
|
/**
|
|
@@ -355,10 +366,21 @@ const GENERATED = `# Generated by gkm from the construct manifest — do not edi
|
|
|
355
366
|
# root and point Node at it, so nothing has to be installed to use these URLs
|
|
356
367
|
# from code; a browser needs the root trusted once.
|
|
357
368
|
`;
|
|
358
|
-
|
|
359
369
|
//#endregion
|
|
360
370
|
//#region src/reconcile/plan.ts
|
|
361
371
|
/**
|
|
372
|
+
* The reconcile plan — what a manifest wants to exist, for one stage.
|
|
373
|
+
*
|
|
374
|
+
* Pure. Turning the plan into running containers and provisioned resources is
|
|
375
|
+
* the applier's job; deciding *what* should exist is this, so the decisions can
|
|
376
|
+
* be asserted as data rather than by starting Docker.
|
|
377
|
+
*
|
|
378
|
+
* One plan serves every stage. `gkm dev` reconciles `development` and `gkm test`
|
|
379
|
+
* reconciles `test`; they differ only in what the resources are called, never in
|
|
380
|
+
* what infrastructure exists. Roles are cluster-scoped in Postgres while grants
|
|
381
|
+
* are per-object, so one container and one role pair serve both.
|
|
382
|
+
*/
|
|
383
|
+
/**
|
|
362
384
|
* Which container serves a kind.
|
|
363
385
|
*
|
|
364
386
|
* Derived kinds map to the same container as their parent — a schema tenant
|
|
@@ -459,7 +481,7 @@ const EVENT_CONTAINERS = {
|
|
|
459
481
|
rabbitmq: "rabbitmq"
|
|
460
482
|
};
|
|
461
483
|
/** The backend a project gets when it declares queues or topics and says nothing. */
|
|
462
|
-
const DEFAULT_EVENTS
|
|
484
|
+
const DEFAULT_EVENTS = "pgboss";
|
|
463
485
|
/**
|
|
464
486
|
* How a resource of each kind separates its stage suffix.
|
|
465
487
|
*
|
|
@@ -492,7 +514,7 @@ function resourceName(id, kind, stage, localStage) {
|
|
|
492
514
|
* broker the project selected, which is why the backend is an argument here
|
|
493
515
|
* rather than a second pass that adds containers after the fact.
|
|
494
516
|
*/
|
|
495
|
-
function containerFor(kind, events = DEFAULT_EVENTS
|
|
517
|
+
function containerFor(kind, events = DEFAULT_EVENTS, cache = DEFAULT_CACHE.aws, derived = false, edge = true) {
|
|
496
518
|
if (EVENT_KINDS[kind]) return EVENT_CONTAINERS[events] ?? CONTAINERS.database;
|
|
497
519
|
if (kind === "file-server") return edge ? "caddy" : CONTAINERS.objects;
|
|
498
520
|
if (kind === "cache") {
|
|
@@ -511,7 +533,7 @@ function containerFor(kind, events = DEFAULT_EVENTS$1, cache = DEFAULT_CACHE.aws
|
|
|
511
533
|
function planFor(manifest, stage, order, options = {}) {
|
|
512
534
|
const containers = /* @__PURE__ */ new Set();
|
|
513
535
|
const resources = [];
|
|
514
|
-
const events = options.events ??
|
|
536
|
+
const events = options.events ?? "pgboss";
|
|
515
537
|
const cache = options.cache ?? DEFAULT_CACHE.aws;
|
|
516
538
|
for (const id of order) {
|
|
517
539
|
const declaration = manifest[id];
|
|
@@ -568,6 +590,7 @@ function planFor(manifest, stage, order, options = {}) {
|
|
|
568
590
|
* broker.
|
|
569
591
|
*/
|
|
570
592
|
var CacheNeedsDatabase = class extends Error {
|
|
593
|
+
ids;
|
|
571
594
|
constructor(ids) {
|
|
572
595
|
super(`A cache backed by the database needs a declared database, and none was declared, and on this deploy target that is where a cache lives. Declare one. Caches affected: ${ids.join(", ")}.`);
|
|
573
596
|
this.ids = ids;
|
|
@@ -586,6 +609,8 @@ var CacheNeedsDatabase = class extends Error {
|
|
|
586
609
|
* application rather than a deployment choice.
|
|
587
610
|
*/
|
|
588
611
|
var CacheIsAmbiguous = class extends Error {
|
|
612
|
+
ids;
|
|
613
|
+
databases;
|
|
589
614
|
constructor(ids, databases) {
|
|
590
615
|
super(`A cache backed by the database needs to know which one, and this app declares ${databases.length}: ${databases.join(", ")}. Declare the cache from its database — e.g. ${databases[0]}.cache('Sessions') — rather than as a bare new Cache(). Caches affected: ${ids.join(", ")}.`);
|
|
591
616
|
this.ids = ids;
|
|
@@ -594,16 +619,29 @@ var CacheIsAmbiguous = class extends Error {
|
|
|
594
619
|
}
|
|
595
620
|
};
|
|
596
621
|
var PgBossNeedsDatabase = class extends Error {
|
|
622
|
+
ids;
|
|
597
623
|
constructor(ids) {
|
|
598
624
|
super(`pg-boss keeps its queues in a declared database, and none was declared. Declare one: on this deploy target, events are carried by pg-boss. Queues and topics affected: ${ids.join(", ")}.`);
|
|
599
625
|
this.ids = ids;
|
|
600
626
|
this.name = "PgBossNeedsDatabase";
|
|
601
627
|
}
|
|
602
628
|
};
|
|
603
|
-
|
|
604
629
|
//#endregion
|
|
605
630
|
//#region src/reconcile/env.ts
|
|
606
631
|
/**
|
|
632
|
+
* The URLs a reconciled stage injects.
|
|
633
|
+
*
|
|
634
|
+
* One `<NAME>_URL` per construct, and the protocol picks the driver. This is the
|
|
635
|
+
* seam between the target that writes a URL and the client that parses it, so
|
|
636
|
+
* every component of it is read off the resource — never inherited from ambient
|
|
637
|
+
* environment. A bucket can live in a different region than the function reading
|
|
638
|
+
* it, and `AWS_REGION` in a Lambda is the *function's* region, so a URL that
|
|
639
|
+
* omits `?region=` breaks cross-region silently at runtime.
|
|
640
|
+
*
|
|
641
|
+
* Locally that self-containment is what lets the port be whatever was free: the
|
|
642
|
+
* app reads `ORDERS_URL` and never sees a host or a port.
|
|
643
|
+
*/
|
|
644
|
+
/**
|
|
607
645
|
* The credential local containers are brought up with.
|
|
608
646
|
*
|
|
609
647
|
* The design's `roles: false` case — both URLs fall back to the cluster's master
|
|
@@ -714,7 +752,7 @@ function originOf(address) {
|
|
|
714
752
|
try {
|
|
715
753
|
return new URL(address).origin;
|
|
716
754
|
} catch {
|
|
717
|
-
return
|
|
755
|
+
return;
|
|
718
756
|
}
|
|
719
757
|
}
|
|
720
758
|
/**
|
|
@@ -820,7 +858,7 @@ function urlFor(resource, plan, ports, project, addresses = {}) {
|
|
|
820
858
|
}
|
|
821
859
|
case "queue":
|
|
822
860
|
case "topic": return broker(plan, port);
|
|
823
|
-
default: return
|
|
861
|
+
default: return;
|
|
824
862
|
}
|
|
825
863
|
}
|
|
826
864
|
/**
|
|
@@ -911,7 +949,6 @@ function schemaOf(resource, plan) {
|
|
|
911
949
|
if (current.kind === "database-schema") return current.schema;
|
|
912
950
|
current = current.of ? byId.get(current.of) : void 0;
|
|
913
951
|
}
|
|
914
|
-
return void 0;
|
|
915
952
|
}
|
|
916
953
|
/**
|
|
917
954
|
* A backend whose local addresses cannot be derived yet.
|
|
@@ -921,6 +958,7 @@ function schemaOf(resource, plan) {
|
|
|
921
958
|
* lands, saying so is better than handing out a string that fails on first use.
|
|
922
959
|
*/
|
|
923
960
|
var UnprovisionedEventsBackend = class extends Error {
|
|
961
|
+
backend;
|
|
924
962
|
constructor(backend) {
|
|
925
963
|
super(`The local target cannot derive addresses for '${backend}' yet — its topics and queues are named by ARN, which nothing creates locally. Use 'pgboss' (the default) or 'rabbitmq' for local development.`);
|
|
926
964
|
this.backend = backend;
|
|
@@ -938,9 +976,27 @@ var UnprovisionedEventsBackend = class extends Error {
|
|
|
938
976
|
function localSecret(project, plan, resource) {
|
|
939
977
|
return createHash("sha256").update(`${project}:${plan.stage}:${resource.id}`).digest("base64url").slice(0, 43);
|
|
940
978
|
}
|
|
941
|
-
|
|
942
979
|
//#endregion
|
|
943
980
|
//#region src/reconcile/apps.ts
|
|
981
|
+
/**
|
|
982
|
+
* The apps, as services beside the containers their constructs derive.
|
|
983
|
+
*
|
|
984
|
+
* `gkm docker` used to write these by hand: every backend got
|
|
985
|
+
* `DATABASE_URL=postgresql://…@postgres:5432/app` and `REDIS_URL=redis://redis`,
|
|
986
|
+
* which was right only for a project whose single database happened to be
|
|
987
|
+
* called `Database` — an `Orders` database publishes `ORDERS_URL`, a schema
|
|
988
|
+
* tenant has a URL of its own, and buckets and mail were not wired at all.
|
|
989
|
+
*
|
|
990
|
+
* Now an app's environment is exactly what reconcile hands `gkm dev`: every key
|
|
991
|
+
* the declared constructs provide, from the same derivation. The only
|
|
992
|
+
* difference is where the addresses point — at the containers by service name
|
|
993
|
+
* on the compose network, rather than at `localhost` on the ports published for
|
|
994
|
+
* the host.
|
|
995
|
+
*
|
|
996
|
+
* Always from the *local* stage's plan, whichever stage is being reconciled:
|
|
997
|
+
* `gkm test` rewrites the same file, and running the tests must not quietly
|
|
998
|
+
* point these apps at the test databases.
|
|
999
|
+
*/
|
|
944
1000
|
/** The profile app services carry, so `gkm dev` starts only the containers. */
|
|
945
1001
|
const APPS_PROFILE = "apps";
|
|
946
1002
|
/**
|
|
@@ -1022,9 +1078,18 @@ function appServices(workspace, manifest, containers) {
|
|
|
1022
1078
|
}
|
|
1023
1079
|
return services;
|
|
1024
1080
|
}
|
|
1025
|
-
|
|
1026
1081
|
//#endregion
|
|
1027
1082
|
//#region src/reconcile/clients.ts
|
|
1083
|
+
/**
|
|
1084
|
+
* The real Postgres and MinIO clients the applier runs against.
|
|
1085
|
+
*
|
|
1086
|
+
* Kept apart from `provision.ts` so the rules there — what gets created, in what
|
|
1087
|
+
* order, and never dropping anything — are asserted against fakes, while the
|
|
1088
|
+
* drivers live here where there is nothing to assert but wiring.
|
|
1089
|
+
*
|
|
1090
|
+
* Both are constructed from the same local addresses the env writer composes,
|
|
1091
|
+
* so the applier cannot end up talking to a different container than the app.
|
|
1092
|
+
*/
|
|
1028
1093
|
/** The credential local containers are brought up with. */
|
|
1029
1094
|
const LOCAL_USER$1 = "geekmidas";
|
|
1030
1095
|
/**
|
|
@@ -1045,8 +1110,7 @@ function pgClient(port) {
|
|
|
1045
1110
|
});
|
|
1046
1111
|
await client.connect();
|
|
1047
1112
|
try {
|
|
1048
|
-
|
|
1049
|
-
return result.rows;
|
|
1113
|
+
return (await client.query(sql, values)).rows;
|
|
1050
1114
|
} finally {
|
|
1051
1115
|
await client.end();
|
|
1052
1116
|
}
|
|
@@ -1077,10 +1141,9 @@ function bucketClient(port) {
|
|
|
1077
1141
|
},
|
|
1078
1142
|
async policy(bucket) {
|
|
1079
1143
|
try {
|
|
1080
|
-
|
|
1081
|
-
return result.Policy;
|
|
1144
|
+
return (await s3.send(new GetBucketPolicyCommand({ Bucket: bucket }))).Policy;
|
|
1082
1145
|
} catch {
|
|
1083
|
-
return
|
|
1146
|
+
return;
|
|
1084
1147
|
}
|
|
1085
1148
|
},
|
|
1086
1149
|
async setPolicy(bucket, policy) {
|
|
@@ -1091,9 +1154,24 @@ function bucketClient(port) {
|
|
|
1091
1154
|
}
|
|
1092
1155
|
};
|
|
1093
1156
|
}
|
|
1094
|
-
|
|
1095
1157
|
//#endregion
|
|
1096
1158
|
//#region src/reconcile/compose.ts
|
|
1159
|
+
/**
|
|
1160
|
+
* The compose document a plan implies.
|
|
1161
|
+
*
|
|
1162
|
+
* The third declaration of the same containers disappears here: today a
|
|
1163
|
+
* `services: ['postgres','minio']` block is kept in step with the code by hand,
|
|
1164
|
+
* which is the triplication this design exists to remove, in the one place you
|
|
1165
|
+
* touch every day. A `database` implies Postgres; the list is derived.
|
|
1166
|
+
*
|
|
1167
|
+
* Returns an object rather than a string for the same reason `plan` is pure —
|
|
1168
|
+
* what should exist is asserted as data, and turning it into YAML is one line at
|
|
1169
|
+
* the edge.
|
|
1170
|
+
*
|
|
1171
|
+
* What stays config is unchanged: images and versions are pinned explicitly, and
|
|
1172
|
+
* a container no construct implies is still declared by hand. Neutral facts come
|
|
1173
|
+
* from the declaration, provider detail from config.
|
|
1174
|
+
*/
|
|
1097
1175
|
/** The credential every derived container is brought up with locally. */
|
|
1098
1176
|
const LOCAL_USER = "geekmidas";
|
|
1099
1177
|
/**
|
|
@@ -1354,9 +1432,18 @@ var UnassignedPort = class extends Error {
|
|
|
1354
1432
|
this.key = key;
|
|
1355
1433
|
}
|
|
1356
1434
|
};
|
|
1357
|
-
|
|
1358
1435
|
//#endregion
|
|
1359
1436
|
//#region src/reconcile/docker.ts
|
|
1437
|
+
/**
|
|
1438
|
+
* The real Docker, behind the small interface reconcile needs.
|
|
1439
|
+
*
|
|
1440
|
+
* Shells out to `docker compose` rather than talking to the daemon socket: it is
|
|
1441
|
+
* what a developer runs by hand when something is wrong, so the two cannot
|
|
1442
|
+
* disagree, and it keeps Docker out of this package's dependencies.
|
|
1443
|
+
*
|
|
1444
|
+
* Every call is scoped to the generated compose file. Nothing here can touch a
|
|
1445
|
+
* container this project did not generate.
|
|
1446
|
+
*/
|
|
1360
1447
|
const run = promisify(execFile);
|
|
1361
1448
|
/**
|
|
1362
1449
|
* The generated file, then the project's own if it has one.
|
|
@@ -1387,7 +1474,7 @@ const dockerCli = {
|
|
|
1387
1474
|
const port = Number(stdout.trim().split(":").pop());
|
|
1388
1475
|
return Number.isFinite(port) && port > 0 ? port : void 0;
|
|
1389
1476
|
} catch {
|
|
1390
|
-
return
|
|
1477
|
+
return;
|
|
1391
1478
|
}
|
|
1392
1479
|
},
|
|
1393
1480
|
async up(composePath, services) {
|
|
@@ -1439,8 +1526,7 @@ const dockerCli = {
|
|
|
1439
1526
|
const running = /* @__PURE__ */ new Set();
|
|
1440
1527
|
for (const line of stdout.trim().split("\n").filter(Boolean)) {
|
|
1441
1528
|
const entry = JSON.parse(line);
|
|
1442
|
-
|
|
1443
|
-
if (ok && entry.Service) running.add(entry.Service);
|
|
1529
|
+
if (entry.State === "running" && (entry.Health === void 0 || entry.Health === "" || entry.Health === "healthy") && entry.Service) running.add(entry.Service);
|
|
1444
1530
|
}
|
|
1445
1531
|
return services.every((service) => running.has(service));
|
|
1446
1532
|
} catch {
|
|
@@ -1448,10 +1534,27 @@ const dockerCli = {
|
|
|
1448
1534
|
}
|
|
1449
1535
|
}
|
|
1450
1536
|
};
|
|
1451
|
-
|
|
1452
1537
|
//#endregion
|
|
1453
1538
|
//#region src/reconcile/ports.ts
|
|
1454
1539
|
/**
|
|
1540
|
+
* Port allocation — why two projects can run at once.
|
|
1541
|
+
*
|
|
1542
|
+
* Publishing `5432:5432` means the second project on your machine cannot start.
|
|
1543
|
+
* Nothing solves that except giving each project its own ports, and what makes
|
|
1544
|
+
* it *possible* is the single-`<NAME>_URL` rule: an app reads `ORDERS_URL` and
|
|
1545
|
+
* never sees a host or a port, so reconcile is free to bind whatever is
|
|
1546
|
+
* available and compose the URL from what it bound. An app reading `DB_HOST` and
|
|
1547
|
+
* `DB_PORT` separately could not be moved this way.
|
|
1548
|
+
*
|
|
1549
|
+
* Assignments are **persisted, not recomputed**. Recomputing means adding a
|
|
1550
|
+
* construct renumbers its neighbours, and every running container, saved
|
|
1551
|
+
* connection string, and `psql` history goes stale at once.
|
|
1552
|
+
*
|
|
1553
|
+
* Pure, with the liveness probe injected — a collision with another project's
|
|
1554
|
+
* stack is a fact about the machine, and keeping it a parameter is what lets the
|
|
1555
|
+
* rules be asserted without binding a socket.
|
|
1556
|
+
*/
|
|
1557
|
+
/**
|
|
1455
1558
|
* The window ports are drawn from.
|
|
1456
1559
|
*
|
|
1457
1560
|
* Above the registered range so nothing here needs privileges, and below the
|
|
@@ -1549,17 +1652,33 @@ async function nextFree(from, taken, probe) {
|
|
|
1549
1652
|
* rather than as a connection failure ten minutes later.
|
|
1550
1653
|
*/
|
|
1551
1654
|
function isPortFree(port) {
|
|
1552
|
-
return new Promise((resolve
|
|
1655
|
+
return new Promise((resolve) => {
|
|
1553
1656
|
const server = createServer();
|
|
1554
|
-
server.once("error", () => resolve
|
|
1555
|
-
server.once("listening", () => server.close(() => resolve
|
|
1657
|
+
server.once("error", () => resolve(false));
|
|
1658
|
+
server.once("listening", () => server.close(() => resolve(true)));
|
|
1556
1659
|
server.listen(port, "0.0.0.0");
|
|
1557
1660
|
});
|
|
1558
1661
|
}
|
|
1559
|
-
|
|
1560
1662
|
//#endregion
|
|
1561
1663
|
//#region src/reconcile/provision.ts
|
|
1562
1664
|
/**
|
|
1665
|
+
* Creating what the URLs name.
|
|
1666
|
+
*
|
|
1667
|
+
* Convergent and idempotent: every statement asks whether the thing exists
|
|
1668
|
+
* first, so reconciling repeatedly is free and a half-applied run recovers by
|
|
1669
|
+
* being run again. That property is what lets `gkm dev` do this on every start.
|
|
1670
|
+
*
|
|
1671
|
+
* The line the design draws is at data, not at side effects — this creates
|
|
1672
|
+
* databases, schemas, and buckets, and it never seeds, resets, or drops. A
|
|
1673
|
+
* developer who wants their data gone asks for it explicitly.
|
|
1674
|
+
*
|
|
1675
|
+
* Statement generation is separated from application for the reason the design
|
|
1676
|
+
* gives: the same DDL has to run in-process locally and from a provisioner in a
|
|
1677
|
+
* VPC, and one implementation is what stops "works locally, fails deployed".
|
|
1678
|
+
* When the role DDL lands in `@geekmidas/db` this delegates to it rather than
|
|
1679
|
+
* growing its own.
|
|
1680
|
+
*/
|
|
1681
|
+
/**
|
|
1563
1682
|
* The Postgres work a plan implies.
|
|
1564
1683
|
*
|
|
1565
1684
|
* Databases before the schemas inside them, which `provisionOrder` already
|
|
@@ -1701,8 +1820,7 @@ async function applyPostgres(client, statements) {
|
|
|
1701
1820
|
});
|
|
1702
1821
|
continue;
|
|
1703
1822
|
}
|
|
1704
|
-
|
|
1705
|
-
if (rows.length > 0) {
|
|
1823
|
+
if ((await client.query(statement.database, statement.exists.sql, statement.exists.values)).length > 0) {
|
|
1706
1824
|
applied.push({
|
|
1707
1825
|
id: statement.id,
|
|
1708
1826
|
describe: statement.describe,
|
|
@@ -1827,9 +1945,20 @@ async function applyBuckets(client, buckets) {
|
|
|
1827
1945
|
}
|
|
1828
1946
|
return applied;
|
|
1829
1947
|
}
|
|
1830
|
-
|
|
1831
1948
|
//#endregion
|
|
1832
1949
|
//#region src/reconcile/state.ts
|
|
1950
|
+
/**
|
|
1951
|
+
* What reconcile records, and the hash that lets it do nothing.
|
|
1952
|
+
*
|
|
1953
|
+
* Reconciling on every `gkm dev` is only acceptable if the converged case is
|
|
1954
|
+
* free, so the desired plan is hashed: matching hash plus healthy containers
|
|
1955
|
+
* means there is nothing to do. Without that, the automatic reconcile the design
|
|
1956
|
+
* asks for would tax every start.
|
|
1957
|
+
*
|
|
1958
|
+
* Almost nothing needs recording — roles are queried, migrations have their own
|
|
1959
|
+
* table, containers are remembered by Docker. Only ports and this hash have no
|
|
1960
|
+
* other owner.
|
|
1961
|
+
*/
|
|
1833
1962
|
const STATE_DIR = ".gkm/reconcile";
|
|
1834
1963
|
/**
|
|
1835
1964
|
* The hash of everything a reconcile would act on.
|
|
@@ -1858,7 +1987,7 @@ async function loadState(root, stage) {
|
|
|
1858
1987
|
const state = JSON.parse(raw);
|
|
1859
1988
|
return state.stage === stage ? state : void 0;
|
|
1860
1989
|
} catch {
|
|
1861
|
-
return
|
|
1990
|
+
return;
|
|
1862
1991
|
}
|
|
1863
1992
|
}
|
|
1864
1993
|
/** Record what was applied, so the next run can skip it. */
|
|
@@ -1870,10 +1999,28 @@ async function saveState(root, state) {
|
|
|
1870
1999
|
function statePath(root, stage) {
|
|
1871
2000
|
return join(root, STATE_DIR, `${stage}.json`);
|
|
1872
2001
|
}
|
|
1873
|
-
|
|
1874
2002
|
//#endregion
|
|
1875
2003
|
//#region src/reconcile/index.ts
|
|
1876
2004
|
/**
|
|
2005
|
+
* Reconcile — the one convergent function `gkm dev`, `gkm test`, and `gkm setup`
|
|
2006
|
+
* all call.
|
|
2007
|
+
*
|
|
2008
|
+
* Three phases, and only this one has side effects: declaring is pure (`gkm
|
|
2009
|
+
* build` and the dev watcher), running reads `<NAME>_URL` and provisions
|
|
2010
|
+
* nothing. Reconcile computes the desired state, compares, and applies the
|
|
2011
|
+
* difference — which is what makes "when does it run" answerable with
|
|
2012
|
+
* *whenever, repeatedly*.
|
|
2013
|
+
*
|
|
2014
|
+
* It is safe to run automatically because its blast radius is entirely local:
|
|
2015
|
+
* this project's containers, this project's `.gkm/`. Nothing it does can reach a
|
|
2016
|
+
* cloud. The line is drawn at data, not at side effects — it allocates ports,
|
|
2017
|
+
* writes compose, starts containers, and creates roles; it never seeds, resets,
|
|
2018
|
+
* or drops.
|
|
2019
|
+
*
|
|
2020
|
+
* Docker is injected rather than imported so the rules above can be asserted
|
|
2021
|
+
* without a daemon. The default implementation is the real one.
|
|
2022
|
+
*/
|
|
2023
|
+
/**
|
|
1877
2024
|
* Where the generated compose file is written, relative to the project root.
|
|
1878
2025
|
*
|
|
1879
2026
|
* At the root, beside the project's own `docker-compose.yml`, because the two
|
|
@@ -1957,9 +2104,7 @@ async function reconcile(options) {
|
|
|
1957
2104
|
hash,
|
|
1958
2105
|
changed: false
|
|
1959
2106
|
};
|
|
1960
|
-
|
|
1961
|
-
const converged = recorded?.hash === hash && existsSync(composePath) && (!start || await docker.healthy(composePath, plan.containers));
|
|
1962
|
-
if (converged) return result;
|
|
2107
|
+
if ((await loadState(root, stage))?.hash === hash && existsSync(composePath) && (!start || await docker.healthy(composePath, plan.containers))) return result;
|
|
1963
2108
|
await write(composePath, toYaml(compose));
|
|
1964
2109
|
if (plan.containers.includes("caddy")) {
|
|
1965
2110
|
await write(join(root, CADDYFILE_PATH), caddyfileRoot());
|
|
@@ -2036,10 +2181,28 @@ async function write(path, content) {
|
|
|
2036
2181
|
await mkdir(dirname(path), { recursive: true });
|
|
2037
2182
|
await writeFile(path, content);
|
|
2038
2183
|
}
|
|
2039
|
-
|
|
2040
2184
|
//#endregion
|
|
2041
2185
|
//#region src/reconcile/workspace.ts
|
|
2042
2186
|
/**
|
|
2187
|
+
* Workspace config → reconcile.
|
|
2188
|
+
*
|
|
2189
|
+
* Nothing here is read from a `services:` block — there is none. Which
|
|
2190
|
+
* containers exist comes from the manifest; which backend a cache or a broker
|
|
2191
|
+
* resolves to comes from the deploy target; and an image pin is the project's
|
|
2192
|
+
* own `docker-compose.yml`, merged over the generated file.
|
|
2193
|
+
*
|
|
2194
|
+
* Shared by `gkm setup`, `gkm dev`, and `gkm test` so all three converge on the
|
|
2195
|
+
* same state, differing only in the stage they pass.
|
|
2196
|
+
*/
|
|
2197
|
+
var workspace_exports = /* @__PURE__ */ __exportAll({
|
|
2198
|
+
backendsOf: () => backendsOf,
|
|
2199
|
+
constructGlobs: () => constructGlobs,
|
|
2200
|
+
derivedContainers: () => derivedContainers,
|
|
2201
|
+
reconcileWorkspace: () => reconcileWorkspace,
|
|
2202
|
+
surfaceAddresses: () => surfaceAddresses,
|
|
2203
|
+
usesConstructs: () => usesConstructs
|
|
2204
|
+
});
|
|
2205
|
+
/**
|
|
2043
2206
|
* Every constructs glob in the workspace, resolved against its app.
|
|
2044
2207
|
*
|
|
2045
2208
|
* Absolute because discovery globs from a single cwd while apps live in
|
|
@@ -2126,22 +2289,16 @@ function surfaceAddresses(workspace, manifest, at = (_app, port) => localAddress
|
|
|
2126
2289
|
const addresses = {};
|
|
2127
2290
|
for (const [id, declaration] of Object.entries(manifest)) {
|
|
2128
2291
|
if (declaration.kind !== "rest-api" && declaration.kind !== "site") continue;
|
|
2129
|
-
const host =
|
|
2130
|
-
const
|
|
2131
|
-
if (
|
|
2292
|
+
const host = appKey(id);
|
|
2293
|
+
const port = workspace.apps[host]?.port;
|
|
2294
|
+
if (port) addresses[id] = at(host, port);
|
|
2132
2295
|
}
|
|
2133
2296
|
return addresses;
|
|
2134
2297
|
}
|
|
2135
|
-
/** The app key serving a surface, following a mount to its host. */
|
|
2136
|
-
function appKeyOfHost(manifest, id) {
|
|
2137
|
-
const host = hostOf(manifest, id);
|
|
2138
|
-
return host ? appKey(host) : void 0;
|
|
2139
|
-
}
|
|
2140
2298
|
/** Where a local process answers, given the port the workspace gave it. */
|
|
2141
2299
|
function localAddress(port) {
|
|
2142
2300
|
return `http://localhost:${port}`;
|
|
2143
2301
|
}
|
|
2144
|
-
|
|
2145
2302
|
//#endregion
|
|
2146
2303
|
//#region src/credentials/index.ts
|
|
2147
2304
|
const logger = console;
|
|
@@ -2174,15 +2331,15 @@ function loadEnvFiles(envConfig, cwd = process.cwd()) {
|
|
|
2174
2331
|
* @internal Exported for testing
|
|
2175
2332
|
*/
|
|
2176
2333
|
async function isPortAvailable(port) {
|
|
2177
|
-
return new Promise((resolve
|
|
2334
|
+
return new Promise((resolve) => {
|
|
2178
2335
|
const server = createServer();
|
|
2179
2336
|
server.once("error", (err) => {
|
|
2180
|
-
if (err.code === "EADDRINUSE") resolve
|
|
2181
|
-
else resolve
|
|
2337
|
+
if (err.code === "EADDRINUSE") resolve(false);
|
|
2338
|
+
else resolve(false);
|
|
2182
2339
|
});
|
|
2183
2340
|
server.once("listening", () => {
|
|
2184
2341
|
server.close();
|
|
2185
|
-
resolve
|
|
2342
|
+
resolve(true);
|
|
2186
2343
|
});
|
|
2187
2344
|
server.listen(port);
|
|
2188
2345
|
});
|
|
@@ -2251,11 +2408,10 @@ async function savePortState(workspaceRoot, ports) {
|
|
|
2251
2408
|
*/
|
|
2252
2409
|
function getContainerHostPort(workspaceRoot, service, containerPort) {
|
|
2253
2410
|
try {
|
|
2254
|
-
const
|
|
2411
|
+
const match = execSync(`docker compose port ${service} ${containerPort}`, {
|
|
2255
2412
|
cwd: workspaceRoot,
|
|
2256
2413
|
stdio: "pipe"
|
|
2257
|
-
}).toString().trim();
|
|
2258
|
-
const match = result.match(/:(\d+)$/);
|
|
2414
|
+
}).toString().trim().match(/:(\d+)$/);
|
|
2259
2415
|
return match ? Number(match[1]) : null;
|
|
2260
2416
|
} catch {
|
|
2261
2417
|
return null;
|
|
@@ -2268,8 +2424,7 @@ function getContainerHostPort(workspaceRoot, service, containerPort) {
|
|
|
2268
2424
|
* @internal Exported for testing
|
|
2269
2425
|
*/
|
|
2270
2426
|
async function resolveServicePorts(workspaceRoot) {
|
|
2271
|
-
const
|
|
2272
|
-
const mappings = parseComposePortMappings(composePath);
|
|
2427
|
+
const mappings = parseComposePortMappings(join(workspaceRoot, "docker-compose.yml"));
|
|
2273
2428
|
if (mappings.length === 0) return {
|
|
2274
2429
|
dockerEnv: {},
|
|
2275
2430
|
ports: {},
|
|
@@ -2503,13 +2658,12 @@ ${generateCredentialsInjection(secretsJsonPath)}`;
|
|
|
2503
2658
|
* @internal Exported for testing
|
|
2504
2659
|
*/
|
|
2505
2660
|
async function createEntryWrapper(wrapperPath, entryPath, secretsJsonPath) {
|
|
2506
|
-
const credentialsInjection = secretsJsonPath ? `${generateCredentialsInjection(secretsJsonPath)}
|
|
2507
|
-
` : "";
|
|
2508
2661
|
const content = `#!/usr/bin/env node
|
|
2509
2662
|
/**
|
|
2510
2663
|
* Entry wrapper generated by 'gkm dev --entry'
|
|
2511
2664
|
*/
|
|
2512
|
-
${
|
|
2665
|
+
${secretsJsonPath ? `${generateCredentialsInjection(secretsJsonPath)}
|
|
2666
|
+
` : ""}// Import and run the user's entry file (dynamic import ensures secrets load first)
|
|
2513
2667
|
await import('${entryPath}');
|
|
2514
2668
|
`;
|
|
2515
2669
|
await writeFile(wrapperPath, content);
|
|
@@ -2549,8 +2703,8 @@ async function prepareEntryCredentials(options) {
|
|
|
2549
2703
|
credentials.PORT = String(resolvedPort);
|
|
2550
2704
|
const declaredKeys = [];
|
|
2551
2705
|
if (appInfo && usesConstructs(appInfo.workspace)) {
|
|
2552
|
-
const { reconcileWorkspace
|
|
2553
|
-
const reconciled = await reconcileWorkspace
|
|
2706
|
+
const { reconcileWorkspace } = await Promise.resolve().then(() => workspace_exports);
|
|
2707
|
+
const reconciled = await reconcileWorkspace(appInfo.workspace, {
|
|
2554
2708
|
stage: options.reconcileStage ?? appInfo.workspace.stages.local,
|
|
2555
2709
|
start: options.startDocker ?? false
|
|
2556
2710
|
});
|
|
@@ -2558,8 +2712,7 @@ async function prepareEntryCredentials(options) {
|
|
|
2558
2712
|
declaredKeys.push(...Object.keys(reconciled.env));
|
|
2559
2713
|
if (Object.keys(reconciled.env).length > 0) logger.log(`🔌 Resolved ${Object.keys(reconciled.env).length} declared URL(s)`);
|
|
2560
2714
|
} else {
|
|
2561
|
-
const
|
|
2562
|
-
const mappings = parseComposePortMappings(composePath);
|
|
2715
|
+
const mappings = parseComposePortMappings(join(secretsRoot, "docker-compose.yml"));
|
|
2563
2716
|
if (mappings.length > 0) {
|
|
2564
2717
|
let resolvedPorts;
|
|
2565
2718
|
if (portMode === "full") resolvedPorts = await resolveServicePorts(secretsRoot);
|
|
@@ -2580,8 +2733,10 @@ async function prepareEntryCredentials(options) {
|
|
|
2580
2733
|
mappings
|
|
2581
2734
|
};
|
|
2582
2735
|
}
|
|
2583
|
-
if (options.startDocker)
|
|
2584
|
-
|
|
2736
|
+
if (options.startDocker) {
|
|
2737
|
+
if (appInfo) await startWorkspaceServices(appInfo.workspace, resolvedPorts.dockerEnv, credentials);
|
|
2738
|
+
else await startComposeServices(secretsRoot, resolvedPorts.dockerEnv, credentials);
|
|
2739
|
+
}
|
|
2585
2740
|
if (Object.keys(resolvedPorts.ports).length > 0) {
|
|
2586
2741
|
const rewritten = rewriteUrlsWithPorts(credentials, resolvedPorts);
|
|
2587
2742
|
Object.assign(credentials, rewritten);
|
|
@@ -2619,7 +2774,7 @@ async function prepareEntryCredentials(options) {
|
|
|
2619
2774
|
declaredKeys
|
|
2620
2775
|
};
|
|
2621
2776
|
}
|
|
2622
|
-
|
|
2623
2777
|
//#endregion
|
|
2624
|
-
export {
|
|
2625
|
-
|
|
2778
|
+
export { storageBackendFor as C, providerOf as S, LOCAL_CA_PATH as _, loadEnvFiles as a, cacheBackendFor as b, resolveServicePorts as c, constructGlobs as d, derivedContainers as f, COMPOSE_PATH as g, workspace_exports as h, isPortAvailable as i, rewriteUrlsWithPorts as l, usesConstructs as m, createEntryWrapper as n, loadSecretsForApp as o, reconcileWorkspace as p, findAvailablePort as r, prepareEntryCredentials as s, createCredentialsPreload as t, startWorkspaceServices as u, applyPostgres as v, eventsBackendFor as x, resourceName as y };
|
|
2779
|
+
|
|
2780
|
+
//# sourceMappingURL=credentials-BekkKtY_.mjs.map
|