@geekmidas/cli 10.0.0-alpha.75 → 10.0.0-alpha.77
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/{LegacyStateStore-BFnXUFlx.cjs → LegacyStateStore-DwngfJxr.cjs} +2 -2
- package/dist/{LegacyStateStore-BFnXUFlx.cjs.map → LegacyStateStore-DwngfJxr.cjs.map} +1 -1
- package/dist/{LegacyStateStore-cpt3K1vx.mjs → LegacyStateStore-dyq07_Ir.mjs} +2 -2
- package/dist/{LegacyStateStore-cpt3K1vx.mjs.map → LegacyStateStore-dyq07_Ir.mjs.map} +1 -1
- package/dist/{LocalStateStore-zQGZ9b4J.cjs → LocalStateStore-B0NCde8Z.cjs} +2 -2
- package/dist/{LocalStateStore-zQGZ9b4J.cjs.map → LocalStateStore-B0NCde8Z.cjs.map} +1 -1
- package/dist/{LocalStateStore-RH9F2ZEy.mjs → LocalStateStore-DLxCCatI.mjs} +2 -2
- package/dist/{LocalStateStore-RH9F2ZEy.mjs.map → LocalStateStore-DLxCCatI.mjs.map} +1 -1
- package/dist/{S3StateStore-CT-ZMlQY.cjs → S3StateStore-BOenb-3o.cjs} +2 -2
- package/dist/{S3StateStore-CT-ZMlQY.cjs.map → S3StateStore-BOenb-3o.cjs.map} +1 -1
- package/dist/{S3StateStore-DBeBc0c0.mjs → S3StateStore-CGK_4hlo.mjs} +2 -2
- package/dist/{S3StateStore-DBeBc0c0.mjs.map → S3StateStore-CGK_4hlo.mjs.map} +1 -1
- package/dist/{SSMStateStore-rnzNfOaV.mjs → SSMStateStore-B_5_RqY-.mjs} +2 -2
- package/dist/{SSMStateStore-rnzNfOaV.mjs.map → SSMStateStore-B_5_RqY-.mjs.map} +1 -1
- package/dist/{SSMStateStore-HmsH3c4v.cjs → SSMStateStore-DYeD__7p.cjs} +2 -2
- package/dist/{SSMStateStore-HmsH3c4v.cjs.map → SSMStateStore-DYeD__7p.cjs.map} +1 -1
- package/dist/{add-CHBin8TF.cjs → add-DCsgtvDk.cjs} +8 -8
- package/dist/{add-CHBin8TF.cjs.map → add-DCsgtvDk.cjs.map} +1 -1
- package/dist/{add-Cvzdw8cf.mjs → add-EPQO-_dt.mjs} +3 -3
- package/dist/{add-Cvzdw8cf.mjs.map → add-EPQO-_dt.mjs.map} +1 -1
- package/dist/{aws-DojzQnLd.mjs → aws-Bja4zGSs.mjs} +13 -9
- package/dist/aws-Bja4zGSs.mjs.map +1 -0
- package/dist/{aws-DkHdTV-p.cjs → aws-CQAuluiu.cjs} +13 -9
- package/dist/aws-CQAuluiu.cjs.map +1 -0
- package/dist/awsStore-7VmS_cZR.cjs +54 -0
- package/dist/awsStore-7VmS_cZR.cjs.map +1 -0
- package/dist/awsStore-B529csle.mjs +43 -0
- package/dist/awsStore-B529csle.mjs.map +1 -0
- package/dist/{bundler-_8AEZhrs.cjs → bundler-5spPyduN.cjs} +5 -5
- package/dist/bundler-5spPyduN.cjs.map +1 -0
- package/dist/{bundler-xjp5RwRS.mjs → bundler-DgO_EMVs.mjs} +5 -5
- package/dist/bundler-DgO_EMVs.mjs.map +1 -0
- package/dist/{cli-BTGfA0B7.mjs → cli-B74Ru-V1.mjs} +3 -3
- package/dist/{cli-BTGfA0B7.mjs.map → cli-B74Ru-V1.mjs.map} +1 -1
- package/dist/{cli-B4ktxAsM.cjs → cli-ZpFTMbGw.cjs} +4 -4
- package/dist/{cli-B4ktxAsM.cjs.map → cli-ZpFTMbGw.cjs.map} +1 -1
- package/dist/{compose-UKyv_1yU.cjs → compose-CePlrbUw.cjs} +68 -60
- package/dist/compose-CePlrbUw.cjs.map +1 -0
- package/dist/{compose-DdH2JQJD.mjs → compose-IUuxRW0J.mjs} +18 -10
- package/dist/compose-IUuxRW0J.mjs.map +1 -0
- package/dist/{config-DA0kRTQe.d.mts → config-Ckmoj56i.d.mts} +3 -3
- package/dist/{config-B38YWicj.d.cts.map → config-Ckmoj56i.d.mts.map} +1 -1
- package/dist/{config-B38YWicj.d.cts → config-aAeLXH86.d.cts} +3 -3
- package/dist/{config-DA0kRTQe.d.mts.map → config-aAeLXH86.d.cts.map} +1 -1
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +3 -3
- package/dist/config.d.mts +3 -3
- package/dist/config.mjs +1 -1
- package/dist/deploy/public.cjs +12 -12
- package/dist/deploy/public.d.cts +3 -3
- package/dist/deploy/public.d.cts.map +1 -1
- package/dist/deploy/public.d.mts +3 -3
- package/dist/deploy/public.d.mts.map +1 -1
- package/dist/deploy/public.mjs +6 -6
- package/dist/{deploy-CuSsiFIc.mjs → deploy-Q6X6RXRG.mjs} +5 -5
- package/dist/{deploy-CuSsiFIc.mjs.map → deploy-Q6X6RXRG.mjs.map} +1 -1
- package/dist/{deploy-XUZoA1us.cjs → deploy-XHXi-_tL.cjs} +11 -11
- package/dist/{deploy-XUZoA1us.cjs.map → deploy-XHXi-_tL.cjs.map} +1 -1
- package/dist/{dokploy-DZXTQX10.mjs → dokploy-BtP5XSrS.mjs} +2 -2
- package/dist/{dokploy-DZXTQX10.mjs.map → dokploy-BtP5XSrS.mjs.map} +1 -1
- package/dist/{dokploy-Cvgg_pID.cjs → dokploy-MSsPBO-t.cjs} +2 -2
- package/dist/{dokploy-Cvgg_pID.cjs.map → dokploy-MSsPBO-t.cjs.map} +1 -1
- package/dist/{encryption-JkeMPugf.mjs → encryption-D4Ykywfr.mjs} +3 -3
- package/dist/{encryption-JkeMPugf.mjs.map → encryption-D4Ykywfr.mjs.map} +1 -1
- package/dist/{encryption-w-Ehh9DW.cjs → encryption-DY0na43R.cjs} +6 -6
- package/dist/{encryption-w-Ehh9DW.cjs.map → encryption-DY0na43R.cjs.map} +1 -1
- package/dist/{engine-CmozkHxq.mjs → engine-BI2xjCKt.mjs} +9 -4
- package/dist/{engine-CmozkHxq.mjs.map → engine-BI2xjCKt.mjs.map} +1 -1
- package/dist/{engine-zpWBMsQq.cjs → engine-y53kE_3H.cjs} +73 -68
- package/dist/{engine-zpWBMsQq.cjs.map → engine-y53kE_3H.cjs.map} +1 -1
- package/dist/{github-BNngHoId.mjs → github-BBIqk1Jv.mjs} +6 -6
- package/dist/github-BBIqk1Jv.mjs.map +1 -0
- package/dist/{github-BGdJ-Lnm.cjs → github-Bmb45xUQ.cjs} +10 -10
- package/dist/github-Bmb45xUQ.cjs.map +1 -0
- package/dist/{index-vMidfqhU.d.cts → index-C7Tma2m1.d.cts} +2 -2
- package/dist/{index-B-1lLGzy.d.mts.map → index-C7Tma2m1.d.cts.map} +1 -1
- package/dist/{index-B-1lLGzy.d.mts → index-CNdSRwar.d.mts} +2 -2
- package/dist/{index-vMidfqhU.d.cts.map → index-CNdSRwar.d.mts.map} +1 -1
- package/dist/index.cjs +210 -221
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +141 -152
- package/dist/index.mjs.map +1 -1
- package/dist/migrate-31JXUOaG.cjs +93 -0
- package/dist/migrate-31JXUOaG.cjs.map +1 -0
- package/dist/{migrate-BLL1RTAj.mjs → migrate-BUBsUiM3.mjs} +3 -3
- package/dist/{migrate-BLL1RTAj.mjs.map → migrate-BUBsUiM3.mjs.map} +1 -1
- package/dist/migrate-DWVl5PQK.mjs +93 -0
- package/dist/migrate-DWVl5PQK.mjs.map +1 -0
- package/dist/{migrate-CgjlYeun.cjs → migrate-sny0NjKe.cjs} +8 -8
- package/dist/{migrate-CgjlYeun.cjs.map → migrate-sny0NjKe.cjs.map} +1 -1
- package/dist/openapi.cjs +16 -6
- package/dist/openapi.cjs.map +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.d.mts.map +1 -1
- package/dist/openapi.mjs +16 -6
- package/dist/openapi.mjs.map +1 -1
- package/dist/reconcile/public.d.cts +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/{resolve-DZNx7rLy.mjs → resolve-BF1ICosS.mjs} +3 -3
- package/dist/{resolve-DZNx7rLy.mjs.map → resolve-BF1ICosS.mjs.map} +1 -1
- package/dist/{resolve-fevXn-wZ.cjs → resolve-DokLtTUb.cjs} +3 -3
- package/dist/{resolve-fevXn-wZ.cjs.map → resolve-DokLtTUb.cjs.map} +1 -1
- package/dist/{rollback-Dw-FW3X2.cjs → rollback-CpOWRR9H.cjs} +7 -7
- package/dist/{rollback-Dw-FW3X2.cjs.map → rollback-CpOWRR9H.cjs.map} +1 -1
- package/dist/{rollback-CLi5Pln_.mjs → rollback-sg0ZhKGG.mjs} +5 -5
- package/dist/{rollback-CLi5Pln_.mjs.map → rollback-sg0ZhKGG.mjs.map} +1 -1
- package/dist/{runtime-BzZD5HHi.d.cts → runtime-B5bYom9w.d.mts} +2 -2
- package/dist/{runtime-BzZD5HHi.d.cts.map → runtime-B5bYom9w.d.mts.map} +1 -1
- package/dist/{runtime-Cm6J6L7n.d.mts → runtime-BozOkPtG.d.cts} +2 -2
- package/dist/{runtime-Cm6J6L7n.d.mts.map → runtime-BozOkPtG.d.cts.map} +1 -1
- package/dist/secretsManager-DUXW3fQt.cjs +70 -0
- package/dist/secretsManager-DUXW3fQt.cjs.map +1 -0
- package/dist/secretsManager-Ti0oZwsS.mjs +70 -0
- package/dist/secretsManager-Ti0oZwsS.mjs.map +1 -0
- package/dist/{sniffer-BmCvVyhq.mjs → sniffer-DR8AlRCk.mjs} +17 -17
- package/dist/sniffer-DR8AlRCk.mjs.map +1 -0
- package/dist/{sniffer-bMzrX4cO.cjs → sniffer-Y6GQOCXB.cjs} +17 -17
- package/dist/sniffer-Y6GQOCXB.cjs.map +1 -0
- package/dist/{state-BrWIOce_.mjs → stale-DGzpiN5S.mjs} +270 -45
- package/dist/stale-DGzpiN5S.mjs.map +1 -0
- package/dist/{state-kA4Fkufx.cjs → stale-yu2FkH3G.cjs} +293 -44
- package/dist/stale-yu2FkH3G.cjs.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/{types-TzCChNrA.d.cts → types-B9yWJAis.d.mts} +59 -9
- package/dist/types-B9yWJAis.d.mts.map +1 -0
- package/dist/{types-Dp9lgx_S.d.mts → types-ct7pdQRf.d.cts} +60 -8
- package/dist/types-ct7pdQRf.d.cts.map +1 -0
- 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-vdrcRI-m.cjs → workspace-DOm81oUo.cjs} +54 -1
- package/dist/workspace-DOm81oUo.cjs.map +1 -0
- package/dist/{workspace-C7NqCsQF.mjs → workspace-QUTqYmVy.mjs} +43 -2
- package/dist/workspace-QUTqYmVy.mjs.map +1 -0
- package/package.json +16 -15
- package/dist/aws-DkHdTV-p.cjs.map +0 -1
- package/dist/aws-DojzQnLd.mjs.map +0 -1
- package/dist/bundler-_8AEZhrs.cjs.map +0 -1
- package/dist/bundler-xjp5RwRS.mjs.map +0 -1
- package/dist/compose-DdH2JQJD.mjs.map +0 -1
- package/dist/compose-UKyv_1yU.cjs.map +0 -1
- package/dist/github-BGdJ-Lnm.cjs.map +0 -1
- package/dist/github-BNngHoId.mjs.map +0 -1
- package/dist/sniffer-BmCvVyhq.mjs.map +0 -1
- package/dist/sniffer-bMzrX4cO.cjs.map +0 -1
- package/dist/state-BrWIOce_.mjs.map +0 -1
- package/dist/state-kA4Fkufx.cjs.map +0 -1
- package/dist/types-Dp9lgx_S.d.mts.map +0 -1
- package/dist/types-TzCChNrA.d.cts.map +0 -1
- package/dist/workspace-C7NqCsQF.mjs.map +0 -1
- package/dist/workspace-vdrcRI-m.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -5,20 +5,20 @@ const require_run = require("./run-fVZ-rLnc.cjs");
|
|
|
5
5
|
const require_credentials = require("./credentials-BVs7mrtw.cjs");
|
|
6
6
|
const require_discover = require("./discover-D1It5r_h.cjs");
|
|
7
7
|
const require_derive = require("./derive-DAbo49sm.cjs");
|
|
8
|
-
const require_workspace = require("./workspace-
|
|
8
|
+
const require_workspace = require("./workspace-DOm81oUo.cjs");
|
|
9
9
|
const require_config = require("./config.cjs");
|
|
10
|
-
const
|
|
10
|
+
const require_stale = require("./stale-yu2FkH3G.cjs");
|
|
11
11
|
const require_EndpointGenerator = require("./EndpointGenerator-CP6sBvQV.cjs");
|
|
12
|
-
const require_sniffer = require("./sniffer-bMzrX4cO.cjs");
|
|
13
12
|
const require_openapi = require("./openapi.cjs");
|
|
14
13
|
const require_SubscriberGenerator = require("./SubscriberGenerator-CajwOa5W.cjs");
|
|
15
14
|
const require_appPorts = require("./appPorts-Cu79hJF6.cjs");
|
|
16
15
|
const require_drivers = require("./drivers-BdvtCKc7.cjs");
|
|
17
16
|
const require_emit = require("./emit-Dmc1nvdS.cjs");
|
|
18
|
-
const
|
|
19
|
-
const
|
|
17
|
+
const require_sniffer = require("./sniffer-Y6GQOCXB.cjs");
|
|
18
|
+
const require_deploy = require("./deploy-XHXi-_tL.cjs");
|
|
19
|
+
const require_compose = require("./compose-CePlrbUw.cjs");
|
|
20
20
|
const require_credentialSchemas = require("./credentialSchemas-DCR4Wd1W.cjs");
|
|
21
|
-
const require_LocalStateStore = require("./LocalStateStore-
|
|
21
|
+
const require_LocalStateStore = require("./LocalStateStore-B0NCde8Z.cjs");
|
|
22
22
|
const require_utils = require("./utils-D2Nk1Nv2.cjs");
|
|
23
23
|
const require_ready = require("./ready-BB9xS4S9.cjs");
|
|
24
24
|
let node_path = require("node:path");
|
|
@@ -53,7 +53,7 @@ crypto = require_rolldown_runtime.__toESM(crypto, 1);
|
|
|
53
53
|
let _geekmidas_constructs_functions = require("@geekmidas/constructs/functions");
|
|
54
54
|
let _geekmidas_constructs_topic = require("@geekmidas/constructs/topic");
|
|
55
55
|
//#region package.json
|
|
56
|
-
var version = "10.0.0-alpha.
|
|
56
|
+
var version = "10.0.0-alpha.77";
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region src/prompt.ts
|
|
59
59
|
/**
|
|
@@ -136,7 +136,7 @@ const logger$8 = console;
|
|
|
136
136
|
* Validate Dokploy token by making a test API call
|
|
137
137
|
*/
|
|
138
138
|
async function validateDokployToken(endpoint, token) {
|
|
139
|
-
const { DokployApi } = await Promise.resolve().then(() => require("./sniffer-
|
|
139
|
+
const { DokployApi } = await Promise.resolve().then(() => require("./sniffer-Y6GQOCXB.cjs")).then((n) => n.dokploy_api_exports);
|
|
140
140
|
return new DokployApi({
|
|
141
141
|
baseUrl: endpoint,
|
|
142
142
|
token
|
|
@@ -304,7 +304,7 @@ function installation(platform, certificate) {
|
|
|
304
304
|
*/
|
|
305
305
|
async function trustCommand(options = {}) {
|
|
306
306
|
const { workspace } = await require_config.loadWorkspaceConfig();
|
|
307
|
-
const certificate = (0, node_path.join)(workspace.root,
|
|
307
|
+
const certificate = (0, node_path.join)(workspace.root, require_stale.LOCAL_CA_PATH);
|
|
308
308
|
if (!(0, node_fs.existsSync)(certificate)) throw new NoLocalAuthority(certificate);
|
|
309
309
|
const { describe, asks, steps } = installation(process.platform, certificate);
|
|
310
310
|
logger$7.log(`\n🔐 Trusting the local authority in ${describe}`);
|
|
@@ -1488,7 +1488,7 @@ async function serveFakes(fakes, ports) {
|
|
|
1488
1488
|
const served = [];
|
|
1489
1489
|
for (const [id, local] of Object.entries(fakes)) {
|
|
1490
1490
|
if (local.image) continue;
|
|
1491
|
-
const port = ports[
|
|
1491
|
+
const port = ports[require_stale.fakeKey(id)];
|
|
1492
1492
|
if (port === void 0) continue;
|
|
1493
1493
|
const { handler } = (await import((0, node_url.pathToFileURL)(local.file).href)).default;
|
|
1494
1494
|
const server = serve({
|
|
@@ -1531,16 +1531,16 @@ var NoCommandSpecified = class extends Error {
|
|
|
1531
1531
|
async function execCommand(commandArgs, options = {}) {
|
|
1532
1532
|
const cwd = options.cwd ?? process.cwd();
|
|
1533
1533
|
if (!commandArgs[0]) throw new NoCommandSpecified();
|
|
1534
|
-
const defaultEnv =
|
|
1534
|
+
const defaultEnv = require_stale.loadEnvFiles(".env");
|
|
1535
1535
|
if (defaultEnv.loaded.length > 0) logger$6.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
|
|
1536
|
-
const { credentials, secretsJsonPath, appName } = await
|
|
1536
|
+
const { credentials, secretsJsonPath, appName } = require_stale.isImageBuild() ? await imageBuildEntry(cwd) : await require_stale.prepareEntryCredentials({ cwd });
|
|
1537
1537
|
if (appName) logger$6.log(`📦 App: ${appName}`);
|
|
1538
1538
|
const secretCount = Object.keys(credentials).filter((k) => k !== "PORT").length;
|
|
1539
|
-
if (secretCount > 0) logger$6.log(`🔐 Loaded ${secretCount} secret(s)`);
|
|
1539
|
+
if (secretCount > 0 && !require_stale.isImageBuild()) logger$6.log(`🔐 Loaded ${secretCount} secret(s)`);
|
|
1540
1540
|
const preloadDir = (0, node_path.join)(cwd, ".gkm");
|
|
1541
1541
|
await (0, node_fs_promises.mkdir)(preloadDir, { recursive: true });
|
|
1542
1542
|
const preloadPath = (0, node_path.join)(preloadDir, "credentials-preload.mjs");
|
|
1543
|
-
await
|
|
1543
|
+
await require_stale.createCredentialsPreload(preloadPath, secretsJsonPath);
|
|
1544
1544
|
const [cmd, ...args] = commandArgs;
|
|
1545
1545
|
logger$6.log(`🚀 Running: ${[cmd, ...args].join(" ")}`);
|
|
1546
1546
|
const nodeOptions = [(process.env.NODE_OPTIONS ?? "").replace(/--import[= ]\S+/g, "").trim(), `--import=${preloadPath}`].filter(Boolean).join(" ");
|
|
@@ -1562,6 +1562,23 @@ async function execCommand(commandArgs, options = {}) {
|
|
|
1562
1562
|
});
|
|
1563
1563
|
if (exitCode !== 0) process.exit(exitCode);
|
|
1564
1564
|
}
|
|
1565
|
+
/**
|
|
1566
|
+
* `gkm exec` inside an image build: the public values the Dockerfile's build
|
|
1567
|
+
* args set, written where the preload reads them. No workspace is loaded, no
|
|
1568
|
+
* secret read and no address resolved.
|
|
1569
|
+
*/
|
|
1570
|
+
async function imageBuildEntry(cwd) {
|
|
1571
|
+
const credentials = require_stale.imageBuildCredentials();
|
|
1572
|
+
logger$6.log(`🐳 Image build: ${Object.keys(credentials).length} public value(s) from the build args`);
|
|
1573
|
+
const dir = (0, node_path.join)(cwd, ".gkm");
|
|
1574
|
+
await (0, node_fs_promises.mkdir)(dir, { recursive: true });
|
|
1575
|
+
const secretsJsonPath = (0, node_path.join)(dir, "image-build-env.json");
|
|
1576
|
+
await (0, node_fs_promises.writeFile)(secretsJsonPath, JSON.stringify(credentials, null, 2));
|
|
1577
|
+
return {
|
|
1578
|
+
credentials,
|
|
1579
|
+
secretsJsonPath
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1565
1582
|
//#endregion
|
|
1566
1583
|
//#region src/dev/index.ts
|
|
1567
1584
|
const logger$5 = console;
|
|
@@ -1632,7 +1649,7 @@ const SUBSCRIBERS_ENV = "GKM_SUBSCRIBERS";
|
|
|
1632
1649
|
async function devCommand(options) {
|
|
1633
1650
|
if (options.subscribers === false) process.env[SUBSCRIBERS_ENV] = "off";
|
|
1634
1651
|
if (options.entry) return entryDevCommand(options);
|
|
1635
|
-
const defaultEnv =
|
|
1652
|
+
const defaultEnv = require_stale.loadEnvFiles(".env");
|
|
1636
1653
|
if (defaultEnv.loaded.length > 0) logger$5.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
|
|
1637
1654
|
const appConfig = await require_config.loadAppConfig().catch((error) => {
|
|
1638
1655
|
if (error instanceof require_config.NotInAnApp || error instanceof require_config.NotABackendApp) return;
|
|
@@ -1648,7 +1665,7 @@ async function devCommand(options) {
|
|
|
1648
1665
|
const secretsRoot = appConfig.workspaceRoot;
|
|
1649
1666
|
const workspaceAppName = appConfig.appName;
|
|
1650
1667
|
const assigned = await require_appPorts.assignAppPorts(appConfig.workspace, [workspaceAppName], {
|
|
1651
|
-
free:
|
|
1668
|
+
free: require_stale.isPortAvailable,
|
|
1652
1669
|
holder: require_appPorts.holderOf
|
|
1653
1670
|
});
|
|
1654
1671
|
if (assigned.running.length > 0) throw new WorkspacePortsInUse(assigned.running);
|
|
@@ -1666,7 +1683,7 @@ async function devCommand(options) {
|
|
|
1666
1683
|
});
|
|
1667
1684
|
}
|
|
1668
1685
|
if (config.env) {
|
|
1669
|
-
const { loaded, missing } =
|
|
1686
|
+
const { loaded, missing } = require_stale.loadEnvFiles(config.env, appRoot);
|
|
1670
1687
|
if (loaded.length > 0) logger$5.log(`📦 Loaded env: ${loaded.join(", ")}`);
|
|
1671
1688
|
if (missing.length > 0) logger$5.warn(`⚠️ Missing env files: ${missing.join(", ")}`);
|
|
1672
1689
|
}
|
|
@@ -1679,8 +1696,8 @@ async function devCommand(options) {
|
|
|
1679
1696
|
appRoot,
|
|
1680
1697
|
target: "server",
|
|
1681
1698
|
enableOpenApi,
|
|
1682
|
-
cacheBackend:
|
|
1683
|
-
eventsBackend:
|
|
1699
|
+
cacheBackend: require_stale.cacheBackendFor(require_stale.providerOf(workspace ?? config)),
|
|
1700
|
+
eventsBackend: require_stale.eventsBackendFor(require_stale.providerOf(workspace ?? config)),
|
|
1684
1701
|
telescope,
|
|
1685
1702
|
databaseApi: true,
|
|
1686
1703
|
hooks,
|
|
@@ -1694,16 +1711,16 @@ async function devCommand(options) {
|
|
|
1694
1711
|
let secretsJsonPath;
|
|
1695
1712
|
let publicUrl;
|
|
1696
1713
|
let manifest;
|
|
1697
|
-
const appSecrets = await
|
|
1714
|
+
const appSecrets = await require_stale.loadSecretsForApp(workspace ? await require_stale.secretsStoreFor(workspace, config.stages.local) : new require_stale.FileSecretsStore(secretsRoot), config.stages.local);
|
|
1698
1715
|
if (workspace) {
|
|
1699
|
-
const reconciled = await
|
|
1716
|
+
const reconciled = await require_stale.reconcileWorkspace(workspace, {
|
|
1700
1717
|
stage: workspace.stages.local,
|
|
1701
1718
|
...options.fake ? { fake: true } : {},
|
|
1702
1719
|
progress: (message) => logger$5.log(message)
|
|
1703
1720
|
});
|
|
1704
1721
|
if (reconciled.services.length > 0) {
|
|
1705
1722
|
logger$5.log("🐳 Services");
|
|
1706
|
-
for (const line of
|
|
1723
|
+
for (const line of require_stale.describeServices(reconciled.services)) logger$5.log(line);
|
|
1707
1724
|
}
|
|
1708
1725
|
Object.assign(appSecrets, reconciled.env);
|
|
1709
1726
|
const own = reconciled.plan.resources.find((r) => (r.kind === "rest-api" || r.kind === "site") && require_derive.appKey(r.id) === workspaceAppName);
|
|
@@ -1982,8 +1999,8 @@ async function validateFrontendApps(workspace) {
|
|
|
1982
1999
|
async function loadDevSecrets(workspace) {
|
|
1983
2000
|
if (!workspace.secrets.enabled) return {};
|
|
1984
2001
|
const stage = workspace.stages.local;
|
|
1985
|
-
const secrets = await (await
|
|
1986
|
-
if (secrets) return
|
|
2002
|
+
const secrets = await (await require_stale.secretsStoreFor(workspace, stage)).read(stage);
|
|
2003
|
+
if (secrets) return require_stale.toEmbeddableSecrets(secrets);
|
|
1987
2004
|
return {};
|
|
1988
2005
|
}
|
|
1989
2006
|
/**
|
|
@@ -1998,7 +2015,7 @@ async function loadDevSecrets(workspace) {
|
|
|
1998
2015
|
async function workspaceDevCommand(configured, options) {
|
|
1999
2016
|
const scoped = options.app ? [options.app] : options.filter ? [] : Object.keys(configured.apps);
|
|
2000
2017
|
const assigned = await require_appPorts.assignAppPorts(configured, scoped, {
|
|
2001
|
-
free:
|
|
2018
|
+
free: require_stale.isPortAvailable,
|
|
2002
2019
|
holder: require_appPorts.holderOf
|
|
2003
2020
|
});
|
|
2004
2021
|
if (assigned.running.length > 0) throw new WorkspacePortsInUse(assigned.running);
|
|
@@ -2025,14 +2042,14 @@ async function workspaceDevCommand(configured, options) {
|
|
|
2025
2042
|
if (hasErrors) throw new Error("Frontend app validation failed. Fix the issues above and try again.");
|
|
2026
2043
|
}
|
|
2027
2044
|
const rawSecrets = await loadDevSecrets(workspace);
|
|
2028
|
-
const reconciled = await
|
|
2045
|
+
const reconciled = await require_stale.reconcileWorkspace(workspace, {
|
|
2029
2046
|
stage: workspace.stages.local,
|
|
2030
2047
|
...options.fake ? { fake: true } : {},
|
|
2031
2048
|
progress: (message) => logger$5.log(message)
|
|
2032
2049
|
});
|
|
2033
2050
|
if (reconciled.services.length > 0) {
|
|
2034
2051
|
logger$5.log("🐳 Services");
|
|
2035
|
-
for (const line of
|
|
2052
|
+
for (const line of require_stale.describeServices(reconciled.services)) logger$5.log(line);
|
|
2036
2053
|
}
|
|
2037
2054
|
const secretsEnv = {
|
|
2038
2055
|
...rawSecrets,
|
|
@@ -2042,9 +2059,9 @@ async function workspaceDevCommand(configured, options) {
|
|
|
2042
2059
|
for (const { id, port } of fakes) logger$5.log(`🎭 ${id} fake: http://localhost:${port}`);
|
|
2043
2060
|
logger$5.log(options.migrate || options.seed ? "🗄️ Migrating the databases" : "🗄️ Checking for pending migrations");
|
|
2044
2061
|
if (options.migrate || options.seed) {
|
|
2045
|
-
const { prepareDevDatabases } = await Promise.resolve().then(() => require("./migrate-
|
|
2062
|
+
const { prepareDevDatabases } = await Promise.resolve().then(() => require("./migrate-sny0NjKe.cjs"));
|
|
2046
2063
|
await prepareDevDatabases(workspace, reconciled.env, { seed: !!options.seed });
|
|
2047
|
-
} else await Promise.resolve().then(() => require("./migrate-
|
|
2064
|
+
} else await Promise.resolve().then(() => require("./migrate-sny0NjKe.cjs")).then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
|
|
2048
2065
|
logger$5.log(`⚠️ Could not check for pending migrations: ${error instanceof Error ? error.message : String(error)}`);
|
|
2049
2066
|
});
|
|
2050
2067
|
const appUrls = {};
|
|
@@ -2130,7 +2147,7 @@ async function workspaceDevCommand(configured, options) {
|
|
|
2130
2147
|
...secretsEnv,
|
|
2131
2148
|
NODE_ENV: "development",
|
|
2132
2149
|
...configPath ? { GKM_CONFIG_PATH: configPath } : {},
|
|
2133
|
-
...options.fake ? { [
|
|
2150
|
+
...options.fake ? { [require_stale.FAKE_ENV]: "1" } : {},
|
|
2134
2151
|
[DISCOVERY_QUIET_ENV]: "1"
|
|
2135
2152
|
};
|
|
2136
2153
|
logger$5.log(`🚀 Starting ${appCount} app(s) — each builds before it answers, and says so when it is ready`);
|
|
@@ -2193,16 +2210,16 @@ async function entryDevCommand(options) {
|
|
|
2193
2210
|
if (!entry) throw new Error("--entry requires a file path");
|
|
2194
2211
|
const entryPath = (0, node_path.resolve)(process.cwd(), entry);
|
|
2195
2212
|
if (!(0, node_fs.existsSync)(entryPath)) throw new Error(`Entry file not found: ${entryPath}`);
|
|
2196
|
-
const defaultEnv =
|
|
2213
|
+
const defaultEnv = require_stale.loadEnvFiles(".env");
|
|
2197
2214
|
if (defaultEnv.loaded.length > 0) logger$5.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
|
|
2198
|
-
const { credentials, resolvedPort, secretsJsonPath, appName } = await
|
|
2215
|
+
const { credentials, resolvedPort, secretsJsonPath, appName } = await require_stale.prepareEntryCredentials({ explicitPort: options.portExplicit ? options.port : void 0 });
|
|
2199
2216
|
if (appName) logger$5.log(`📦 App: ${appName} (port ${resolvedPort})`);
|
|
2200
2217
|
logger$5.log(`🚀 Starting entry file: ${entry} on port ${resolvedPort}`);
|
|
2201
2218
|
if (Object.keys(credentials).length > 1) logger$5.log(`🔐 Loaded ${Object.keys(credentials).length - 1} secret(s) + PORT`);
|
|
2202
2219
|
const wrapperDir = (0, node_path.join)(process.cwd(), ".gkm");
|
|
2203
2220
|
await (0, node_fs_promises.mkdir)(wrapperDir, { recursive: true });
|
|
2204
2221
|
const wrapperPath = (0, node_path.join)(wrapperDir, "entry-wrapper.ts");
|
|
2205
|
-
await
|
|
2222
|
+
await require_stale.createEntryWrapper(wrapperPath, entryPath, secretsJsonPath);
|
|
2206
2223
|
const runner = new EntryRunner(wrapperPath, entryPath, watch, resolvedPort);
|
|
2207
2224
|
await runner.start();
|
|
2208
2225
|
let isShuttingDown = false;
|
|
@@ -2511,10 +2528,10 @@ var DevServer = class {
|
|
|
2511
2528
|
this.startTime = Date.now();
|
|
2512
2529
|
if (this.isRunning) await this.stop();
|
|
2513
2530
|
if (this.portExplicit) {
|
|
2514
|
-
if (!await
|
|
2531
|
+
if (!await require_stale.isPortAvailable(this.requestedPort)) throw new DevPortInUse(this.requestedPort, listenerOn(this.requestedPort));
|
|
2515
2532
|
this.actualPort = this.requestedPort;
|
|
2516
2533
|
} else {
|
|
2517
|
-
this.actualPort = await
|
|
2534
|
+
this.actualPort = await require_stale.findAvailablePort(this.requestedPort);
|
|
2518
2535
|
if (this.actualPort !== this.requestedPort) logger$5.log(`ℹ️ Port ${this.requestedPort} was in use, using port ${this.actualPort} instead`);
|
|
2519
2536
|
}
|
|
2520
2537
|
const serverEntryPath = (0, node_path.join)(this.appRoot, ".gkm", "server", "server.ts");
|
|
@@ -2585,7 +2602,7 @@ var DevServer = class {
|
|
|
2585
2602
|
await this.stop();
|
|
2586
2603
|
let attempts = 0;
|
|
2587
2604
|
while (attempts < 30) {
|
|
2588
|
-
if (await
|
|
2605
|
+
if (await require_stale.isPortAvailable(portToReuse)) break;
|
|
2589
2606
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2590
2607
|
attempts++;
|
|
2591
2608
|
}
|
|
@@ -2926,7 +2943,7 @@ async function buildCommand(options) {
|
|
|
2926
2943
|
}
|
|
2927
2944
|
}
|
|
2928
2945
|
const config = loadedConfig.type !== "workspace" ? await require_config.loadConfig() : (0, node_path.resolve)(process.cwd()) === (0, node_path.resolve)(loadedConfig.workspace.root) ? rootGkmConfig(loadedConfig.workspace) : (await require_config.loadAppConfig()).gkmConfig;
|
|
2929
|
-
const target = options.provider ??
|
|
2946
|
+
const target = options.provider ?? require_stale.providerOf(loadedConfig.workspace);
|
|
2930
2947
|
const workspaceRoot = loadedConfig.workspace.root;
|
|
2931
2948
|
const appRoot = process.cwd();
|
|
2932
2949
|
const output = await buildOneApp({
|
|
@@ -2958,15 +2975,15 @@ async function declaredIn(config, cwd) {
|
|
|
2958
2975
|
*/
|
|
2959
2976
|
function backendsOf(workspace) {
|
|
2960
2977
|
return {
|
|
2961
|
-
cache:
|
|
2978
|
+
cache: require_stale.cacheBackendFor(require_stale.providerOf(workspace)),
|
|
2962
2979
|
email: "ses"
|
|
2963
2980
|
};
|
|
2964
2981
|
}
|
|
2965
2982
|
/** One app's build, from its config and the command's options. */
|
|
2966
2983
|
async function buildOneApp(input) {
|
|
2967
2984
|
const { config, options, workspace, appRoot, target } = input;
|
|
2968
|
-
const cacheBackend = options.cache ??
|
|
2969
|
-
const eventsBackend =
|
|
2985
|
+
const cacheBackend = options.cache ?? require_stale.cacheBackendFor(require_stale.providerOf(workspace));
|
|
2986
|
+
const eventsBackend = require_stale.eventsBackendFor(require_stale.providerOf(workspace));
|
|
2970
2987
|
const production = normalizeProductionConfig(options.production ?? false);
|
|
2971
2988
|
if (production) logger$4.log(`🏭 Building for PRODUCTION`);
|
|
2972
2989
|
logger$4.log(`Building for ${target}`);
|
|
@@ -3052,7 +3069,7 @@ async function buildApp(input) {
|
|
|
3052
3069
|
if (production?.bundle && !input.skipBundle) {
|
|
3053
3070
|
const outputDir = (0, node_path.join)(appRoot, ".gkm", "server");
|
|
3054
3071
|
const entryPoint = await writeSurfaceServer(outputDir, production);
|
|
3055
|
-
const { bundleServer } = await Promise.resolve().then(() => require("./bundler-
|
|
3072
|
+
const { bundleServer } = await Promise.resolve().then(() => require("./bundler-5spPyduN.cjs"));
|
|
3056
3073
|
await bundleServer({
|
|
3057
3074
|
entryPoint,
|
|
3058
3075
|
outputDir: (0, node_path.join)(outputDir, "dist"),
|
|
@@ -3096,9 +3113,9 @@ async function buildApp(input) {
|
|
|
3096
3113
|
};
|
|
3097
3114
|
const endpointGenerator = new require_EndpointGenerator.EndpointGenerator();
|
|
3098
3115
|
const functionGenerator = new FunctionGenerator();
|
|
3099
|
-
const cronGenerator = new
|
|
3116
|
+
const cronGenerator = new require_stale.CronGenerator();
|
|
3100
3117
|
const subscriberGenerator = new require_SubscriberGenerator.SubscriberGenerator();
|
|
3101
|
-
const queueGenerator = new
|
|
3118
|
+
const queueGenerator = new require_stale.QueueGenerator();
|
|
3102
3119
|
const topicGenerator = new TopicGenerator();
|
|
3103
3120
|
const code = constructGlobs;
|
|
3104
3121
|
const [loadedEndpoints, allFunctions, allCrons, allSubscribers, allQueues, allTopics] = await Promise.all([
|
|
@@ -3137,7 +3154,7 @@ async function buildApp(input) {
|
|
|
3137
3154
|
const appName = Object.entries(input.workspace.apps).find(([, app]) => (0, node_path.resolve)(input.workspace.root, app.path) === (0, node_path.resolve)(appRoot))?.[0];
|
|
3138
3155
|
await buildWorkers({
|
|
3139
3156
|
context: buildContext,
|
|
3140
|
-
workers:
|
|
3157
|
+
workers: require_stale.workerUnits(input.workspace, declared, background).filter((unit) => unit.app === appName),
|
|
3141
3158
|
serverDir: (0, node_path.join)(appRoot, ".gkm", "server"),
|
|
3142
3159
|
crons: allCrons,
|
|
3143
3160
|
queues: allQueues,
|
|
@@ -3160,7 +3177,7 @@ async function buildApp(input) {
|
|
|
3160
3177
|
* runnables built from that worker, and nothing built from another.
|
|
3161
3178
|
*/
|
|
3162
3179
|
async function buildWorkers(input) {
|
|
3163
|
-
const generator = new
|
|
3180
|
+
const generator = new require_stale.WorkerGenerator();
|
|
3164
3181
|
for (const worker of input.workers) {
|
|
3165
3182
|
const owned = (list) => list.filter(({ construct }) => construct.owner === worker.id);
|
|
3166
3183
|
const crons = owned(input.crons);
|
|
@@ -3169,15 +3186,15 @@ async function buildWorkers(input) {
|
|
|
3169
3186
|
const entryPoint = await generator.build({
|
|
3170
3187
|
context: input.context,
|
|
3171
3188
|
workerId: worker.id,
|
|
3172
|
-
outputDir:
|
|
3189
|
+
outputDir: require_stale.workerEntryDir(input.serverDir, worker.id),
|
|
3173
3190
|
crons,
|
|
3174
3191
|
queues,
|
|
3175
3192
|
subscribers
|
|
3176
3193
|
});
|
|
3177
3194
|
logger$4.log(`Generated worker ${worker.id}: ${crons.length} crons, ${queues.length} queues, ${subscribers.length} subscribers`);
|
|
3178
3195
|
if (!input.bundle) continue;
|
|
3179
|
-
const { bundleServer } = await Promise.resolve().then(() => require("./bundler-
|
|
3180
|
-
const outfile =
|
|
3196
|
+
const { bundleServer } = await Promise.resolve().then(() => require("./bundler-5spPyduN.cjs"));
|
|
3197
|
+
const outfile = require_stale.workerBundleName(worker.id);
|
|
3181
3198
|
await bundleServer({
|
|
3182
3199
|
entryPoint,
|
|
3183
3200
|
outputDir: (0, node_path.join)(input.serverDir, "dist"),
|
|
@@ -3246,7 +3263,7 @@ async function buildForTarget(target, context, appRoot, workspaceRoot, endpointG
|
|
|
3246
3263
|
let masterKey;
|
|
3247
3264
|
if (context.production?.bundle && !skipBundle) {
|
|
3248
3265
|
logger$4.log(`\n📦 Bundling production server...`);
|
|
3249
|
-
const { bundleServer } = await Promise.resolve().then(() => require("./bundler-
|
|
3266
|
+
const { bundleServer } = await Promise.resolve().then(() => require("./bundler-5spPyduN.cjs"));
|
|
3250
3267
|
const allConstructs = [
|
|
3251
3268
|
...endpoints.map((e) => e.construct),
|
|
3252
3269
|
...functions.map((f) => f.construct),
|
|
@@ -3377,7 +3394,7 @@ async function workspaceBuildCommand(workspace, options) {
|
|
|
3377
3394
|
const buildOrder = require_workspace.getAppBuildOrder(workspace);
|
|
3378
3395
|
logger$4.log(` Build order: ${buildOrder.join(" → ")}`);
|
|
3379
3396
|
try {
|
|
3380
|
-
const target = options.provider ??
|
|
3397
|
+
const target = options.provider ?? require_stale.providerOf(workspace);
|
|
3381
3398
|
const builds = [];
|
|
3382
3399
|
for (const appName of buildOrder) {
|
|
3383
3400
|
const app = workspace.apps[appName];
|
|
@@ -3500,14 +3517,14 @@ async function composeCommand(options, deps = {}) {
|
|
|
3500
3517
|
if (options.push && !options.build) throw new require_compose.ComposePushNeedsBuild();
|
|
3501
3518
|
const pulls = !options.build && (options.pull || options.tag !== void 0);
|
|
3502
3519
|
if (options.digestsFile && !options.push && !pulls) throw new require_compose.ComposePinNeedsPull();
|
|
3503
|
-
const allowDevServices =
|
|
3520
|
+
const allowDevServices = require_stale.parseDevServices(options.allowDevServices);
|
|
3504
3521
|
const cwd = (0, node_path.resolve)(options.cwd ?? process.cwd());
|
|
3505
3522
|
const { workspace } = await require_config.loadWorkspaceConfig(cwd);
|
|
3506
3523
|
const { stage } = options;
|
|
3507
3524
|
if (options.down) {
|
|
3508
3525
|
const override = require_compose.stackOverrideFile(workspace.root, stage);
|
|
3509
3526
|
const ref = {
|
|
3510
|
-
project: require_compose.composeProject(
|
|
3527
|
+
project: require_compose.composeProject(require_stale.deployIdentity(workspace, stage)),
|
|
3511
3528
|
file: (0, node_path.join)(workspace.root, require_compose.stackDir(stage), "docker-compose.yml"),
|
|
3512
3529
|
...(0, node_fs.existsSync)(override) ? { overrides: [override] } : {},
|
|
3513
3530
|
cwd: workspace.root
|
|
@@ -4016,13 +4033,6 @@ const SERVICE_DEFAULTS = {
|
|
|
4016
4033
|
region: "us-east-1"
|
|
4017
4034
|
}
|
|
4018
4035
|
};
|
|
4019
|
-
/** Default credentials for pgboss (not a Docker service, reuses postgres) */
|
|
4020
|
-
const PGBOSS_DEFAULTS = {
|
|
4021
|
-
host: "localhost",
|
|
4022
|
-
port: 5432,
|
|
4023
|
-
username: "pgboss",
|
|
4024
|
-
database: "app"
|
|
4025
|
-
};
|
|
4026
4036
|
/**
|
|
4027
4037
|
* Generate credentials for a specific service.
|
|
4028
4038
|
*/
|
|
@@ -4062,14 +4072,6 @@ function generateMinioEndpoint(creds) {
|
|
|
4062
4072
|
return `http://${host}:${port}`;
|
|
4063
4073
|
}
|
|
4064
4074
|
/**
|
|
4065
|
-
* Generate connection URL for pg-boss (uses PostgreSQL protocol).
|
|
4066
|
-
* Format: pgboss://user:pass@host:port/db?schema=pgboss
|
|
4067
|
-
*/
|
|
4068
|
-
function generatePgBossUrl(creds) {
|
|
4069
|
-
const { username, password, host, port, database } = creds;
|
|
4070
|
-
return `pgboss://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}?schema=pgboss`;
|
|
4071
|
-
}
|
|
4072
|
-
/**
|
|
4073
4075
|
* Generate connection URLs from service credentials.
|
|
4074
4076
|
*/
|
|
4075
4077
|
function generateConnectionUrls(services) {
|
|
@@ -4077,7 +4079,6 @@ function generateConnectionUrls(services) {
|
|
|
4077
4079
|
if (services.postgres) urls.DATABASE_URL = generatePostgresUrl(services.postgres);
|
|
4078
4080
|
if (services.redis) urls.REDIS_URL = generateRedisUrl(services.redis);
|
|
4079
4081
|
if (services.minio) urls.STORAGE_ENDPOINT = generateMinioEndpoint(services.minio);
|
|
4080
|
-
if (services.pgboss) urls.EVENT_PUBLISHER_CONNECTION_STRING = generatePgBossUrl(services.pgboss);
|
|
4081
4082
|
if (services.mailpit) {
|
|
4082
4083
|
urls.SMTP_HOST = services.mailpit.host;
|
|
4083
4084
|
urls.SMTP_PORT = String(services.mailpit.port);
|
|
@@ -4101,13 +4102,6 @@ function createStageSecrets(stage, services, options) {
|
|
|
4101
4102
|
serviceCredentials.minio.username = options.projectName;
|
|
4102
4103
|
}
|
|
4103
4104
|
}
|
|
4104
|
-
if (serviceCredentials.postgres && !serviceCredentials.pgboss) serviceCredentials.pgboss = {
|
|
4105
|
-
...PGBOSS_DEFAULTS,
|
|
4106
|
-
password: generateSecurePassword(),
|
|
4107
|
-
host: serviceCredentials.postgres.host,
|
|
4108
|
-
port: serviceCredentials.postgres.port,
|
|
4109
|
-
database: serviceCredentials.postgres.database
|
|
4110
|
-
};
|
|
4111
4105
|
return {
|
|
4112
4106
|
stage,
|
|
4113
4107
|
createdAt: now,
|
|
@@ -4970,25 +4964,25 @@ function loadPackageJson() {
|
|
|
4970
4964
|
* Run: pnpm --filter @geekmidas/cli sync-versions
|
|
4971
4965
|
*/
|
|
4972
4966
|
const GEEKMIDAS_VERSIONS = {
|
|
4973
|
-
"@geekmidas/audit": "~10.0.0-alpha.
|
|
4974
|
-
"@geekmidas/auth": "~10.0.0-alpha.
|
|
4975
|
-
"@geekmidas/cache": "~10.0.0-alpha.
|
|
4976
|
-
"@geekmidas/client": "~10.0.0-alpha.
|
|
4977
|
-
"@geekmidas/cloud": "~10.0.0-alpha.
|
|
4978
|
-
"@geekmidas/constructs": "~10.0.0-alpha.
|
|
4979
|
-
"@geekmidas/db": "~10.0.0-alpha.
|
|
4980
|
-
"@geekmidas/emailkit": "~10.0.0-alpha.
|
|
4981
|
-
"@geekmidas/envkit": "~10.0.0-alpha.
|
|
4982
|
-
"@geekmidas/errors": "~10.0.0-alpha.
|
|
4983
|
-
"@geekmidas/events": "~10.0.0-alpha.
|
|
4984
|
-
"@geekmidas/logger": "~10.0.0-alpha.
|
|
4985
|
-
"@geekmidas/manifest": "~10.0.0-alpha.
|
|
4986
|
-
"@geekmidas/rate-limit": "~10.0.0-alpha.
|
|
4987
|
-
"@geekmidas/schema": "~10.0.0-alpha.
|
|
4988
|
-
"@geekmidas/services": "~10.0.0-alpha.
|
|
4989
|
-
"@geekmidas/storage": "~10.0.0-alpha.
|
|
4990
|
-
"@geekmidas/telescope": "~10.0.0-alpha.
|
|
4991
|
-
"@geekmidas/testkit": "~10.0.0-alpha.
|
|
4967
|
+
"@geekmidas/audit": "~10.0.0-alpha.77",
|
|
4968
|
+
"@geekmidas/auth": "~10.0.0-alpha.77",
|
|
4969
|
+
"@geekmidas/cache": "~10.0.0-alpha.77",
|
|
4970
|
+
"@geekmidas/client": "~10.0.0-alpha.77",
|
|
4971
|
+
"@geekmidas/cloud": "~10.0.0-alpha.77",
|
|
4972
|
+
"@geekmidas/constructs": "~10.0.0-alpha.77",
|
|
4973
|
+
"@geekmidas/db": "~10.0.0-alpha.77",
|
|
4974
|
+
"@geekmidas/emailkit": "~10.0.0-alpha.77",
|
|
4975
|
+
"@geekmidas/envkit": "~10.0.0-alpha.77",
|
|
4976
|
+
"@geekmidas/errors": "~10.0.0-alpha.77",
|
|
4977
|
+
"@geekmidas/events": "~10.0.0-alpha.77",
|
|
4978
|
+
"@geekmidas/logger": "~10.0.0-alpha.77",
|
|
4979
|
+
"@geekmidas/manifest": "~10.0.0-alpha.77",
|
|
4980
|
+
"@geekmidas/rate-limit": "~10.0.0-alpha.77",
|
|
4981
|
+
"@geekmidas/schema": "~10.0.0-alpha.77",
|
|
4982
|
+
"@geekmidas/services": "~10.0.0-alpha.77",
|
|
4983
|
+
"@geekmidas/storage": "~10.0.0-alpha.77",
|
|
4984
|
+
"@geekmidas/telescope": "~10.0.0-alpha.77",
|
|
4985
|
+
"@geekmidas/testkit": "~10.0.0-alpha.77",
|
|
4992
4986
|
"@geekmidas/cli": `~${loadPackageJson().version}`
|
|
4993
4987
|
};
|
|
4994
4988
|
//#endregion
|
|
@@ -5571,7 +5565,7 @@ function deploy(options) {
|
|
|
5571
5565
|
role-to-assume: \${{ vars.AWS_ROLE_ARN }}
|
|
5572
5566
|
aws-region: ${options.region}
|
|
5573
5567
|
` : "";
|
|
5574
|
-
const keyDir = `~/.gkm/keys/${
|
|
5568
|
+
const keyDir = `~/.gkm/keys/${require_stale.projectKey({ name: options.name })}`;
|
|
5575
5569
|
const stageSecrets = sst ? credentials : `
|
|
5576
5570
|
# The stage's secrets are kept in the encrypted .gkm/secrets/<stage>.json,
|
|
5577
5571
|
# and each environment holds its key as GKM_SECRETS_KEY. .gkm/ is
|
|
@@ -6833,7 +6827,6 @@ docker-compose.constructs.yml
|
|
|
6833
6827
|
.env
|
|
6834
6828
|
.env.local
|
|
6835
6829
|
.env.*.local
|
|
6836
|
-
docker/.env
|
|
6837
6830
|
|
|
6838
6831
|
# IDE
|
|
6839
6832
|
.idea/
|
|
@@ -7046,6 +7039,7 @@ function secretsStore(options) {
|
|
|
7046
7039
|
return `
|
|
7047
7040
|
// Deployed stages keep their secrets in SSM, in the account each stage
|
|
7048
7041
|
// deploys to: \`gkm secrets:set <KEY> '…' --stage <stage>\` writes there.
|
|
7042
|
+
// Past 8 KB a stage needs { provider: 'secrets-manager', region } instead.
|
|
7049
7043
|
store: { provider: 'ssm', region: '${options.region}' },`;
|
|
7050
7044
|
}
|
|
7051
7045
|
/**
|
|
@@ -9901,18 +9895,17 @@ async function initCommand(projectName, options = {}) {
|
|
|
9901
9895
|
};
|
|
9902
9896
|
if (isFullstack) {
|
|
9903
9897
|
customSecrets.AUTH_PORT = "3002";
|
|
9904
|
-
customSecrets.AUTH_URL = "http://localhost:3002";
|
|
9905
9898
|
customSecrets.BETTER_AUTH_SECRET = `better-auth-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
9906
9899
|
customSecrets.BETTER_AUTH_URL = "http://localhost:3002";
|
|
9907
9900
|
customSecrets.BETTER_AUTH_TRUSTED_ORIGINS = "http://localhost:3000,http://localhost:3001";
|
|
9908
9901
|
}
|
|
9909
9902
|
devSecrets.custom = customSecrets;
|
|
9910
9903
|
const keys = {
|
|
9911
|
-
key:
|
|
9904
|
+
key: require_stale.projectKey({ name }),
|
|
9912
9905
|
legacy: [(0, node_path.basename)(targetDir)]
|
|
9913
9906
|
};
|
|
9914
|
-
await new
|
|
9915
|
-
const keyPath =
|
|
9907
|
+
await new require_stale.FileSecretsStore(targetDir, keys).write(local, devSecrets);
|
|
9908
|
+
const keyPath = require_stale.getKeyPath(local, keys);
|
|
9916
9909
|
console.log(` Secrets: .gkm/secrets/${local}.json (encrypted)`);
|
|
9917
9910
|
console.log(` Key: ${keyPath}\n`);
|
|
9918
9911
|
if (!options.skipInstall) {
|
|
@@ -10065,27 +10058,18 @@ var NotAnAwsRegion = class extends Error {
|
|
|
10065
10058
|
//#endregion
|
|
10066
10059
|
//#region src/setup/fullstack-secrets.ts
|
|
10067
10060
|
/**
|
|
10068
|
-
* Generate a secure random password for database users.
|
|
10069
|
-
* Uses a combination of timestamp and random bytes for uniqueness.
|
|
10070
|
-
*/
|
|
10071
|
-
function generateDbPassword() {
|
|
10072
|
-
return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;
|
|
10073
|
-
}
|
|
10074
|
-
/**
|
|
10075
|
-
* Generate database URL for an app.
|
|
10076
|
-
* All apps connect to the same database, but use different users/schemas.
|
|
10077
|
-
*/
|
|
10078
|
-
function generateDbUrl(appName, password, projectName, host = "localhost", port = 5432) {
|
|
10079
|
-
return `postgresql://${appName.replace(/-/g, "_")}:${password}@${host}:${port}/${`${projectName.replace(/-/g, "_")}_dev`}`;
|
|
10080
|
-
}
|
|
10081
|
-
/**
|
|
10082
10061
|
* Generate fullstack-aware custom secrets for a workspace.
|
|
10083
10062
|
*
|
|
10084
10063
|
* Generates:
|
|
10085
10064
|
* - Common secrets: PORT, LOG_LEVEL, JWT_SECRET (no `NODE_ENV` — the command
|
|
10086
10065
|
* decides that; see `gkm init`)
|
|
10087
|
-
* - Per-app database passwords and URLs for backend apps with db service
|
|
10088
10066
|
* - Better-auth secrets for apps using the better-auth framework
|
|
10067
|
+
*
|
|
10068
|
+
* No address of anything a construct declares — a database's or a tenant's
|
|
10069
|
+
* URL, a surface's or a site's. Those are derived from the construct, with
|
|
10070
|
+
* passwords from the stage, and one stored here would be a value set by hand,
|
|
10071
|
+
* which wins over the derived one: a `localhost` URL handed to a container,
|
|
10072
|
+
* with a password no role has.
|
|
10089
10073
|
*/
|
|
10090
10074
|
function generateFullstackCustomSecrets(workspace, containers = []) {
|
|
10091
10075
|
const hasDb = containers.includes("postgres");
|
|
@@ -10095,22 +10079,10 @@ function generateFullstackCustomSecrets(workspace, containers = []) {
|
|
|
10095
10079
|
JWT_SECRET: `dev-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
10096
10080
|
};
|
|
10097
10081
|
if (!hasDb) return customs;
|
|
10098
|
-
const
|
|
10099
|
-
|
|
10100
|
-
if (appConfig.type === "web") {
|
|
10101
|
-
frontendPorts.push(appConfig.port);
|
|
10102
|
-
const upperName = appName.toUpperCase();
|
|
10103
|
-
customs[`${upperName}_URL`] = `http://localhost:${appConfig.port}`;
|
|
10104
|
-
continue;
|
|
10105
|
-
}
|
|
10106
|
-
if (appConfig.type === "mobile") continue;
|
|
10107
|
-
const password = generateDbPassword();
|
|
10108
|
-
const upperName = appName.toUpperCase();
|
|
10109
|
-
customs[`${upperName}_DATABASE_URL`] = generateDbUrl(appName, password, workspace.name);
|
|
10110
|
-
customs[`${upperName}_DB_PASSWORD`] = password;
|
|
10082
|
+
for (const appConfig of Object.values(workspace.apps)) {
|
|
10083
|
+
if (appConfig.type === "web" || appConfig.type === "mobile") continue;
|
|
10111
10084
|
if (appConfig.framework === "better-auth") {
|
|
10112
10085
|
customs.AUTH_PORT = String(appConfig.port);
|
|
10113
|
-
customs.AUTH_URL = `http://localhost:${appConfig.port}`;
|
|
10114
10086
|
customs.BETTER_AUTH_SECRET = `better-auth-${Date.now()}-${generateSecurePassword(16)}`;
|
|
10115
10087
|
customs.BETTER_AUTH_URL = `http://localhost:${appConfig.port}`;
|
|
10116
10088
|
}
|
|
@@ -10118,38 +10090,19 @@ function generateFullstackCustomSecrets(workspace, containers = []) {
|
|
|
10118
10090
|
if (customs.BETTER_AUTH_SECRET) customs.BETTER_AUTH_TRUSTED_ORIGINS = Object.values(workspace.apps).map((a) => a.port).map((p) => `http://localhost:${p}`).join(",");
|
|
10119
10091
|
return customs;
|
|
10120
10092
|
}
|
|
10121
|
-
/**
|
|
10122
|
-
* Extract *_DB_PASSWORD keys from secrets and write docker/.env.
|
|
10123
|
-
*
|
|
10124
|
-
* The docker/.env file contains database passwords that the PostgreSQL
|
|
10125
|
-
* init script reads to create per-app database users.
|
|
10126
|
-
*/
|
|
10127
|
-
async function writeDockerEnvFromSecrets(secrets, workspaceRoot) {
|
|
10128
|
-
const dbPasswordEntries = Object.entries(secrets.custom).filter(([key]) => key.endsWith("_DB_PASSWORD"));
|
|
10129
|
-
if (secrets.services.pgboss && !dbPasswordEntries.some(([key]) => key === "PGBOSS_DB_PASSWORD")) dbPasswordEntries.push(["PGBOSS_DB_PASSWORD", secrets.services.pgboss.password]);
|
|
10130
|
-
if (dbPasswordEntries.length === 0) return;
|
|
10131
|
-
const envContent = `# Auto-generated docker environment file
|
|
10132
|
-
# Contains database passwords for docker-compose postgres init
|
|
10133
|
-
# This file is gitignored - do not commit to version control
|
|
10134
|
-
${dbPasswordEntries.map(([key, value]) => `${key}=${value}`).join("\n")}
|
|
10135
|
-
`;
|
|
10136
|
-
const envPath = (0, node_path.join)(workspaceRoot, "docker", ".env");
|
|
10137
|
-
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(envPath), { recursive: true });
|
|
10138
|
-
await (0, node_fs_promises.writeFile)(envPath, envContent);
|
|
10139
|
-
}
|
|
10140
10093
|
//#endregion
|
|
10141
10094
|
//#region src/secrets/index.ts
|
|
10142
10095
|
const logger$2 = console;
|
|
10143
10096
|
/**
|
|
10144
|
-
* The store the stage named on the command line keeps its secrets in — SSM
|
|
10145
|
-
* its account, for a deployed stage kept there. Outside any workspace nothing
|
|
10097
|
+
* The store the stage named on the command line keeps its secrets in — SSM or
|
|
10098
|
+
* Secrets Manager in its account, for a deployed stage kept there. Outside any workspace nothing
|
|
10146
10099
|
* names a store, so it is the file.
|
|
10147
10100
|
*/
|
|
10148
10101
|
async function storeFor(stage) {
|
|
10149
10102
|
try {
|
|
10150
|
-
return await
|
|
10103
|
+
return await require_stale.secretsStoreFor(await require_config.loadWorkspaceSettings(), stage);
|
|
10151
10104
|
} catch (error) {
|
|
10152
|
-
if (error instanceof require_config.ConfigNotFound) return new
|
|
10105
|
+
if (error instanceof require_config.ConfigNotFound) return new require_stale.FileSecretsStore(process.cwd());
|
|
10153
10106
|
throw error;
|
|
10154
10107
|
}
|
|
10155
10108
|
}
|
|
@@ -10220,9 +10173,50 @@ async function secretsSetCommand(key, value, options) {
|
|
|
10220
10173
|
process.exit(1);
|
|
10221
10174
|
}
|
|
10222
10175
|
await assertCredentialValue(key, secretValue, stage);
|
|
10223
|
-
await store.write(stage,
|
|
10176
|
+
await store.write(stage, require_stale.withCustomSecret(secrets, key, secretValue));
|
|
10224
10177
|
logger$2.log(`\n✓ Secret "${key}" set for stage "${stage}" (${store.name})`);
|
|
10225
10178
|
}
|
|
10179
|
+
/** `gkm secrets:unset` for a key the stage does not hold. */
|
|
10180
|
+
var SecretNotSet = class extends Error {
|
|
10181
|
+
key;
|
|
10182
|
+
stage;
|
|
10183
|
+
constructor(key, stage) {
|
|
10184
|
+
super(`The stage '${stage}' holds no secret '${key}'. List what it holds with gkm secrets:show --stage ${stage}.`);
|
|
10185
|
+
this.key = key;
|
|
10186
|
+
this.stage = stage;
|
|
10187
|
+
this.name = "SecretNotSet";
|
|
10188
|
+
}
|
|
10189
|
+
};
|
|
10190
|
+
/** `gkm secrets:unset` on a stage that has no secrets at all. */
|
|
10191
|
+
var StageSecretsNotFound = class extends Error {
|
|
10192
|
+
stage;
|
|
10193
|
+
constructor(stage) {
|
|
10194
|
+
super(`The stage '${stage}' has no secrets, so there is nothing to remove.`);
|
|
10195
|
+
this.stage = stage;
|
|
10196
|
+
this.name = "StageSecretsNotFound";
|
|
10197
|
+
}
|
|
10198
|
+
};
|
|
10199
|
+
/**
|
|
10200
|
+
* Remove a custom secret from a stage, in the stage's own store — the file,
|
|
10201
|
+
* SSM or Secrets Manager. The rest of the stage is written back as it was.
|
|
10202
|
+
*
|
|
10203
|
+
* @throws {StageSecretsNotFound} when the stage holds no secrets
|
|
10204
|
+
* @throws {SecretNotSet} when it holds none by that key
|
|
10205
|
+
*/
|
|
10206
|
+
async function secretsUnsetCommand(key, options) {
|
|
10207
|
+
const { stage } = options;
|
|
10208
|
+
const store = await storeFor(stage);
|
|
10209
|
+
const secrets = await store.read(stage);
|
|
10210
|
+
if (!secrets) throw new StageSecretsNotFound(stage);
|
|
10211
|
+
if (!(key in secrets.custom)) throw new SecretNotSet(key, stage);
|
|
10212
|
+
const { [key]: _removed, ...custom } = secrets.custom;
|
|
10213
|
+
await store.write(stage, {
|
|
10214
|
+
...secrets,
|
|
10215
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10216
|
+
custom
|
|
10217
|
+
});
|
|
10218
|
+
logger$2.log(`\n✓ Secret "${key}" removed from stage "${stage}" (${store.name})`);
|
|
10219
|
+
}
|
|
10226
10220
|
/**
|
|
10227
10221
|
* A third party's credentials, checked against the schema of the construct
|
|
10228
10222
|
* that reads them before they are stored — what the app would otherwise
|
|
@@ -10242,7 +10236,7 @@ async function assertCredentialValue(key, value, stage) {
|
|
|
10242
10236
|
}
|
|
10243
10237
|
const check = await (await require_credentialSchemas.loadCredentialSchemas({
|
|
10244
10238
|
root: workspace.root,
|
|
10245
|
-
patterns:
|
|
10239
|
+
patterns: require_stale.constructGlobs(workspace)
|
|
10246
10240
|
})).check(key, value);
|
|
10247
10241
|
if (!check.ok) throw new require_credentialSchemas.CredentialsInvalid(stage, [{
|
|
10248
10242
|
key,
|
|
@@ -10268,7 +10262,7 @@ async function secretsShowCommand(options) {
|
|
|
10268
10262
|
logger$2.log(` host: ${creds.host}`);
|
|
10269
10263
|
logger$2.log(` port: ${creds.port}`);
|
|
10270
10264
|
logger$2.log(` username: ${creds.username}`);
|
|
10271
|
-
logger$2.log(` password: ${reveal ? creds.password :
|
|
10265
|
+
logger$2.log(` password: ${reveal ? creds.password : require_stale.maskPassword(creds.password)}`);
|
|
10272
10266
|
if (creds.database) logger$2.log(` database: ${creds.database}`);
|
|
10273
10267
|
if (creds.bucket) logger$2.log(` bucket: ${creds.bucket}`);
|
|
10274
10268
|
}
|
|
@@ -10278,7 +10272,7 @@ async function secretsShowCommand(options) {
|
|
|
10278
10272
|
if (secrets.urls.STORAGE_ENDPOINT) logger$2.log(` STORAGE_ENDPOINT: ${secrets.urls.STORAGE_ENDPOINT}`);
|
|
10279
10273
|
if (Object.keys(secrets.custom).length > 0) {
|
|
10280
10274
|
logger$2.log("\nCustom Secrets:");
|
|
10281
|
-
for (const [key, value] of Object.entries(secrets.custom)) logger$2.log(` ${key}: ${reveal ? value :
|
|
10275
|
+
for (const [key, value] of Object.entries(secrets.custom)) logger$2.log(` ${key}: ${reveal ? value : require_stale.maskPassword(value)}`);
|
|
10282
10276
|
}
|
|
10283
10277
|
if (!reveal) logger$2.log("\nUse --reveal to show actual values");
|
|
10284
10278
|
}
|
|
@@ -10358,7 +10352,7 @@ async function secretsImportCommand(file, options) {
|
|
|
10358
10352
|
function maskUrl(url) {
|
|
10359
10353
|
try {
|
|
10360
10354
|
const parsed = new URL(url);
|
|
10361
|
-
if (parsed.password) parsed.password =
|
|
10355
|
+
if (parsed.password) parsed.password = require_stale.maskPassword(parsed.password);
|
|
10362
10356
|
return parsed.toString();
|
|
10363
10357
|
} catch {
|
|
10364
10358
|
return url;
|
|
@@ -10378,9 +10372,8 @@ const logger$1 = console;
|
|
|
10378
10372
|
*
|
|
10379
10373
|
* Orchestrates:
|
|
10380
10374
|
* 1. Load workspace config
|
|
10381
|
-
* 2. Resolve secrets (local →
|
|
10382
|
-
* 3.
|
|
10383
|
-
* 4. Start Docker services
|
|
10375
|
+
* 2. Resolve secrets (local → the stage's store → generate fresh)
|
|
10376
|
+
* 3. Start Docker services
|
|
10384
10377
|
*/
|
|
10385
10378
|
async function setupCommand(options = {}) {
|
|
10386
10379
|
logger$1.log("\n🔧 Setting up the local environment...\n");
|
|
@@ -10393,20 +10386,13 @@ async function setupCommand(options = {}) {
|
|
|
10393
10386
|
}
|
|
10394
10387
|
const stage = options.stage ?? loadedConfig.workspace.stages.local;
|
|
10395
10388
|
const { workspace } = loadedConfig;
|
|
10396
|
-
const isMultiApp = Object.keys(workspace.apps).length > 1;
|
|
10397
10389
|
logger$1.log(`📦 Workspace: ${workspace.name}`);
|
|
10398
10390
|
logger$1.log(`📱 Apps: ${Object.keys(workspace.apps).join(", ")}`);
|
|
10399
10391
|
logger$1.log(`🔑 Stage: ${stage}\n`);
|
|
10400
|
-
|
|
10401
|
-
if (!secrets) {
|
|
10392
|
+
if (!await resolveSecrets(stage, workspace, options)) {
|
|
10402
10393
|
logger$1.error("❌ Failed to resolve secrets. Exiting.");
|
|
10403
10394
|
process.exit(1);
|
|
10404
10395
|
}
|
|
10405
|
-
const containers = await require_state.derivedContainers(workspace, stage);
|
|
10406
|
-
if (isMultiApp && containers.includes("postgres")) {
|
|
10407
|
-
await writeDockerEnvFromSecrets(secrets, workspace.root);
|
|
10408
|
-
logger$1.log("📄 Generated docker/.env with database passwords");
|
|
10409
|
-
}
|
|
10410
10396
|
if (!options.skipDocker) {
|
|
10411
10397
|
logger$1.log("");
|
|
10412
10398
|
await reconcileLocal(workspace, stage, options);
|
|
@@ -10421,7 +10407,7 @@ async function setupCommand(options = {}) {
|
|
|
10421
10407
|
* free and quiet.
|
|
10422
10408
|
*/
|
|
10423
10409
|
async function reconcileLocal(workspace, stage, options) {
|
|
10424
|
-
const result = await
|
|
10410
|
+
const result = await require_stale.reconcileWorkspace(workspace, { stage });
|
|
10425
10411
|
if (result.plan.containers.length === 0) {
|
|
10426
10412
|
logger$1.log("🐳 No containers declared");
|
|
10427
10413
|
return;
|
|
@@ -10431,7 +10417,7 @@ async function reconcileLocal(workspace, stage, options) {
|
|
|
10431
10417
|
return;
|
|
10432
10418
|
}
|
|
10433
10419
|
logger$1.log("🐳 Services");
|
|
10434
|
-
for (const line of
|
|
10420
|
+
for (const line of require_stale.describeServices(result.services)) logger$1.log(line);
|
|
10435
10421
|
const url = result.plan.resources.filter((r) => r.kind === "rest-api" || r.kind === "site" || r.kind === "file-server").map((r) => result.env[r.envKey]).find((address) => address?.startsWith("https://"));
|
|
10436
10422
|
if (url) await ensureTrusted(workspace.root, url, { ...options.yes ? { assumeYes: true } : {} });
|
|
10437
10423
|
}
|
|
@@ -10448,11 +10434,11 @@ async function resolveSecrets(stage, workspace, options) {
|
|
|
10448
10434
|
logger$1.log("🔐 Generating fresh secrets (--force)...");
|
|
10449
10435
|
return generateFreshSecrets(stage, workspace);
|
|
10450
10436
|
}
|
|
10451
|
-
const store = await
|
|
10437
|
+
const store = await require_stale.secretsStoreFor(workspace, stage);
|
|
10452
10438
|
const secrets = await store.read(stage);
|
|
10453
10439
|
if (secrets) {
|
|
10454
10440
|
logger$1.log("🔐 Using existing secrets");
|
|
10455
|
-
const reconciled = reconcileSecrets(secrets, workspace, await
|
|
10441
|
+
const reconciled = reconcileSecrets(secrets, workspace, await require_stale.derivedContainers(workspace, stage));
|
|
10456
10442
|
if (reconciled) await store.write(stage, reconciled);
|
|
10457
10443
|
return reconciled ?? secrets;
|
|
10458
10444
|
}
|
|
@@ -10503,24 +10489,6 @@ function reconcileSecrets(secrets, workspace, containers = []) {
|
|
|
10503
10489
|
logger$1.log(` 🔄 Adding missing service credentials: ${name}`);
|
|
10504
10490
|
changed = true;
|
|
10505
10491
|
}
|
|
10506
|
-
if (result.services.postgres && !result.services.pgboss) {
|
|
10507
|
-
result = {
|
|
10508
|
-
...result,
|
|
10509
|
-
services: {
|
|
10510
|
-
...result.services,
|
|
10511
|
-
pgboss: {
|
|
10512
|
-
host: result.services.postgres.host,
|
|
10513
|
-
port: result.services.postgres.port,
|
|
10514
|
-
username: "pgboss",
|
|
10515
|
-
password: generateSecurePassword(),
|
|
10516
|
-
database: result.services.postgres.database ?? "app"
|
|
10517
|
-
}
|
|
10518
|
-
}
|
|
10519
|
-
};
|
|
10520
|
-
result.urls = generateConnectionUrls(result.services);
|
|
10521
|
-
logger$1.log(" 🔄 Adding missing service credentials: pgboss");
|
|
10522
|
-
changed = true;
|
|
10523
|
-
}
|
|
10524
10492
|
if (Object.keys(workspace.apps).length > 1) {
|
|
10525
10493
|
const expected = generateFullstackCustomSecrets(workspace, containers);
|
|
10526
10494
|
const missing = {};
|
|
@@ -10546,7 +10514,7 @@ function reconcileSecrets(secrets, workspace, containers = []) {
|
|
|
10546
10514
|
/**
|
|
10547
10515
|
* Build a fresh StageSecrets object for a workspace: service credentials,
|
|
10548
10516
|
* connection URLs, and custom secrets. Pure — does not write to disk or touch
|
|
10549
|
-
*
|
|
10517
|
+
* any store. Service passwords are freshly randomized, so the result must be the same
|
|
10550
10518
|
* one used to start the matching Docker containers.
|
|
10551
10519
|
* @internal Exported for reuse by `gkm test` auto-setup.
|
|
10552
10520
|
*/
|
|
@@ -10572,9 +10540,9 @@ function createFreshWorkspaceSecrets(stage, workspace, containers = []) {
|
|
|
10572
10540
|
*/
|
|
10573
10541
|
async function ensureStageSecrets(stage, cwd = process.cwd()) {
|
|
10574
10542
|
const { workspace } = await require_config.loadWorkspaceConfig(cwd);
|
|
10575
|
-
const store = await
|
|
10543
|
+
const store = await require_stale.secretsStoreFor(workspace, stage);
|
|
10576
10544
|
if (await store.read(stage)) return false;
|
|
10577
|
-
const secrets = createFreshWorkspaceSecrets(stage, workspace, await
|
|
10545
|
+
const secrets = createFreshWorkspaceSecrets(stage, workspace, await require_stale.derivedContainers(workspace, stage));
|
|
10578
10546
|
await store.write(stage, secrets);
|
|
10579
10547
|
return true;
|
|
10580
10548
|
}
|
|
@@ -10582,8 +10550,8 @@ async function ensureStageSecrets(stage, cwd = process.cwd()) {
|
|
|
10582
10550
|
* Generate fresh secrets for the workspace.
|
|
10583
10551
|
*/
|
|
10584
10552
|
async function generateFreshSecrets(stage, workspace) {
|
|
10585
|
-
const secrets = createFreshWorkspaceSecrets(stage, workspace, await
|
|
10586
|
-
const store = await
|
|
10553
|
+
const secrets = createFreshWorkspaceSecrets(stage, workspace, await require_stale.derivedContainers(workspace, stage));
|
|
10554
|
+
const store = await require_stale.secretsStoreFor(workspace, stage);
|
|
10587
10555
|
await store.write(stage, secrets);
|
|
10588
10556
|
logger$1.log(` Secrets written to the "${stage}" store (${store.name})`);
|
|
10589
10557
|
return secrets;
|
|
@@ -10623,7 +10591,7 @@ function printSummary(workspace, stage) {
|
|
|
10623
10591
|
* A no-op when nothing is recorded — no run yet, or one already torn down —
|
|
10624
10592
|
* so running it twice, or before a setup, is harmless.
|
|
10625
10593
|
*/
|
|
10626
|
-
async function dropTestDatabases(cwd, root, sql =
|
|
10594
|
+
async function dropTestDatabases(cwd, root, sql = require_stale.pgClient) {
|
|
10627
10595
|
const readyPath = (0, node_path.join)(cwd, require_ready.TEST_READY_FILE);
|
|
10628
10596
|
const ready = await readReady(readyPath);
|
|
10629
10597
|
const recorded = ready?.databases;
|
|
@@ -10631,9 +10599,9 @@ async function dropTestDatabases(cwd, root, sql = require_state.pgClient) {
|
|
|
10631
10599
|
const client = sql(recorded.port);
|
|
10632
10600
|
for (const name of recorded.names) {
|
|
10633
10601
|
if (!name.endsWith(`_test`)) throw new NotATestDatabase(name);
|
|
10634
|
-
await client.query(void 0, `DROP DATABASE IF EXISTS ${
|
|
10602
|
+
await client.query(void 0, `DROP DATABASE IF EXISTS ${require_stale.quoteIdentifier(name)} WITH (FORCE)`);
|
|
10635
10603
|
}
|
|
10636
|
-
await
|
|
10604
|
+
await require_stale.forgetState(root, require_workspace.TEST_STAGE);
|
|
10637
10605
|
const { databases: _dropped, ...rest } = ready;
|
|
10638
10606
|
await (0, node_fs_promises.writeFile)(readyPath, JSON.stringify(rest, null, 2));
|
|
10639
10607
|
return recorded.names;
|
|
@@ -10673,10 +10641,10 @@ async function testCommand(options = {}) {
|
|
|
10673
10641
|
const { ensureStageSecrets } = await Promise.resolve().then(() => setup_exports);
|
|
10674
10642
|
if (await ensureStageSecrets(stage, cwd)) console.log(` 🔐 Generated fresh ${stage} secrets (auto-setup)`);
|
|
10675
10643
|
}
|
|
10676
|
-
const defaultEnv =
|
|
10644
|
+
const defaultEnv = require_stale.loadEnvFiles(".env");
|
|
10677
10645
|
if (defaultEnv.loaded.length > 0) console.log(` 📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
|
|
10678
10646
|
if (!options.prepare) await teardown(cwd);
|
|
10679
|
-
const result = await
|
|
10647
|
+
const result = await require_stale.prepareEntryCredentials({
|
|
10680
10648
|
stage,
|
|
10681
10649
|
startDocker: !options.prepare,
|
|
10682
10650
|
secretsFileName: "test-secrets.json",
|
|
@@ -10697,14 +10665,14 @@ async function testCommand(options = {}) {
|
|
|
10697
10665
|
await (0, node_fs_promises.writeFile)(result.secretsJsonPath, JSON.stringify(finalCredentials, null, 2));
|
|
10698
10666
|
const gkmDir = (0, node_path.join)(cwd, ".gkm");
|
|
10699
10667
|
const preloadPath = (0, node_path.join)(gkmDir, "test-credentials-preload.ts");
|
|
10700
|
-
await
|
|
10668
|
+
await require_stale.createCredentialsPreload(preloadPath, result.secretsJsonPath);
|
|
10701
10669
|
const workspace = await require_config.loadWorkspaceConfig(cwd).then((loaded) => loaded.workspace).catch(() => void 0);
|
|
10702
10670
|
const manifestPath = workspace ? await require_ready.writeTestHarness({
|
|
10703
10671
|
root: workspace.root,
|
|
10704
10672
|
targets: [workspace.root, ...Object.values(workspace.apps).map((app) => (0, node_path.isAbsolute)(app.path) ? app.path : (0, node_path.join)(workspace.root, app.path))],
|
|
10705
|
-
patterns:
|
|
10706
|
-
cacheBackend:
|
|
10707
|
-
eventsBackend:
|
|
10673
|
+
patterns: require_stale.constructGlobs(workspace),
|
|
10674
|
+
cacheBackend: require_stale.backendsOf(workspace).cache,
|
|
10675
|
+
eventsBackend: require_stale.backendsOf(workspace).events,
|
|
10708
10676
|
stage: require_workspace.TEST_STAGE,
|
|
10709
10677
|
env: finalCredentials,
|
|
10710
10678
|
factories: (0, node_path.join)(workspace.root, workspace.test.factories ?? "test/factories")
|
|
@@ -10767,8 +10735,8 @@ async function teardown(cwd) {
|
|
|
10767
10735
|
* the plan provisions, on the port the shared container answers.
|
|
10768
10736
|
*/
|
|
10769
10737
|
function testDatabases(reconciled) {
|
|
10770
|
-
const port = reconciled?.ports[
|
|
10771
|
-
const names = reconciled ?
|
|
10738
|
+
const port = reconciled?.ports[require_stale.primaryPortKey("postgres")];
|
|
10739
|
+
const names = reconciled ? require_stale.postgresDatabaseNames(reconciled.plan) : [];
|
|
10772
10740
|
return port !== void 0 && names.length > 0 ? { databases: {
|
|
10773
10741
|
port,
|
|
10774
10742
|
names
|
|
@@ -10779,11 +10747,11 @@ function testDatabases(reconciled) {
|
|
|
10779
10747
|
* starts without the reference data the app needs.
|
|
10780
10748
|
*/
|
|
10781
10749
|
async function migrateTestStage(workspace, env) {
|
|
10782
|
-
const { migrateAndSeed } = await Promise.resolve().then(() => require("./migrate-
|
|
10750
|
+
const { migrateAndSeed } = await Promise.resolve().then(() => require("./migrate-sny0NjKe.cjs"));
|
|
10783
10751
|
const { discover } = await Promise.resolve().then(() => require("./discover-D1It5r_h.cjs")).then((n) => n.discover_exports);
|
|
10784
10752
|
const sources = {};
|
|
10785
10753
|
const manifest = await discover({
|
|
10786
|
-
patterns:
|
|
10754
|
+
patterns: require_stale.constructGlobs(workspace),
|
|
10787
10755
|
cwd: workspace.root,
|
|
10788
10756
|
sources
|
|
10789
10757
|
});
|
|
@@ -11212,7 +11180,7 @@ program.command("migrate").description("Apply each database construct's migratio
|
|
|
11212
11180
|
try {
|
|
11213
11181
|
const globalOptions = program.opts();
|
|
11214
11182
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11215
|
-
const { migrateCommand } = await Promise.resolve().then(() => require("./migrate-
|
|
11183
|
+
const { migrateCommand } = await Promise.resolve().then(() => require("./migrate-sny0NjKe.cjs"));
|
|
11216
11184
|
await migrateCommand({
|
|
11217
11185
|
...options,
|
|
11218
11186
|
...construct ? { construct } : {}
|
|
@@ -11226,7 +11194,7 @@ program.command("seed").description("Migrate, then run each database construct's
|
|
|
11226
11194
|
try {
|
|
11227
11195
|
const globalOptions = program.opts();
|
|
11228
11196
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11229
|
-
const { seedCommand } = await Promise.resolve().then(() => require("./migrate-
|
|
11197
|
+
const { seedCommand } = await Promise.resolve().then(() => require("./migrate-sny0NjKe.cjs"));
|
|
11230
11198
|
await seedCommand({
|
|
11231
11199
|
...options,
|
|
11232
11200
|
...construct ? { construct } : {}
|
|
@@ -11240,7 +11208,7 @@ program.command("migration").description("Write a construct's next migration: an
|
|
|
11240
11208
|
try {
|
|
11241
11209
|
const globalOptions = program.opts();
|
|
11242
11210
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11243
|
-
const { migrationCommand } = await Promise.resolve().then(() => require("./migrate-
|
|
11211
|
+
const { migrationCommand } = await Promise.resolve().then(() => require("./migrate-sny0NjKe.cjs"));
|
|
11244
11212
|
await migrationCommand({
|
|
11245
11213
|
construct,
|
|
11246
11214
|
...name ? { name } : {}
|
|
@@ -11279,7 +11247,7 @@ program.command("docker").description("Generate Docker deployment files").option
|
|
|
11279
11247
|
try {
|
|
11280
11248
|
const globalOptions = program.opts();
|
|
11281
11249
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11282
|
-
await
|
|
11250
|
+
await require_stale.dockerCommand(options);
|
|
11283
11251
|
} catch (error) {
|
|
11284
11252
|
console.error(formatError(error));
|
|
11285
11253
|
process.exit(1);
|
|
@@ -11299,7 +11267,7 @@ program.command("prepack").description("Generate Docker files for production dep
|
|
|
11299
11267
|
try {
|
|
11300
11268
|
const globalOptions = program.opts();
|
|
11301
11269
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11302
|
-
await
|
|
11270
|
+
await require_stale.dockerCommand({
|
|
11303
11271
|
build: options.build,
|
|
11304
11272
|
push: options.push,
|
|
11305
11273
|
tag: options.tag,
|
|
@@ -11330,11 +11298,21 @@ program.command("secrets:set").description("Set a custom secret for a stage").ar
|
|
|
11330
11298
|
process.exit(1);
|
|
11331
11299
|
}
|
|
11332
11300
|
});
|
|
11301
|
+
program.command("secrets:unset").description("Remove a custom secret from a stage").argument("<key>", "Secret key (e.g., API_KEY)").requiredOption("--stage <stage>", "Stage name").action(async (key, options) => {
|
|
11302
|
+
try {
|
|
11303
|
+
const globalOptions = program.opts();
|
|
11304
|
+
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11305
|
+
await secretsUnsetCommand(key, options);
|
|
11306
|
+
} catch (error) {
|
|
11307
|
+
console.error(formatError(error));
|
|
11308
|
+
process.exit(1);
|
|
11309
|
+
}
|
|
11310
|
+
});
|
|
11333
11311
|
program.command("secrets:add").description("Build the keys a stage must be given — buckets, mail, file servers, third parties' credentials — across every app").requiredOption("--stage <stage>", "Stage name").option("--missing", "Only the keys the stage has not set").option("--json", "Print the keys as JSON and ask nothing").action(async (options) => {
|
|
11334
11312
|
try {
|
|
11335
11313
|
const globalOptions = program.opts();
|
|
11336
11314
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11337
|
-
const { secretsAddCommand } = await Promise.resolve().then(() => require("./add-
|
|
11315
|
+
const { secretsAddCommand } = await Promise.resolve().then(() => require("./add-DCsgtvDk.cjs"));
|
|
11338
11316
|
await secretsAddCommand(options);
|
|
11339
11317
|
} catch (error) {
|
|
11340
11318
|
console.error(formatError(error));
|
|
@@ -11345,7 +11323,7 @@ program.command("encryption:rotate").description("Add a new current key to an En
|
|
|
11345
11323
|
try {
|
|
11346
11324
|
const globalOptions = program.opts();
|
|
11347
11325
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11348
|
-
const { encryptionRotateCommand } = await Promise.resolve().then(() => require("./encryption-
|
|
11326
|
+
const { encryptionRotateCommand } = await Promise.resolve().then(() => require("./encryption-DY0na43R.cjs"));
|
|
11349
11327
|
await encryptionRotateCommand(construct, options);
|
|
11350
11328
|
} catch (error) {
|
|
11351
11329
|
console.error(formatError(error));
|
|
@@ -11356,7 +11334,7 @@ program.command("encryption:retire").description("Remove an old key from an Encr
|
|
|
11356
11334
|
try {
|
|
11357
11335
|
const globalOptions = program.opts();
|
|
11358
11336
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11359
|
-
const { encryptionRetireCommand } = await Promise.resolve().then(() => require("./encryption-
|
|
11337
|
+
const { encryptionRetireCommand } = await Promise.resolve().then(() => require("./encryption-DY0na43R.cjs"));
|
|
11360
11338
|
await encryptionRetireCommand(construct, key, options);
|
|
11361
11339
|
} catch (error) {
|
|
11362
11340
|
console.error(formatError(error));
|
|
@@ -11399,7 +11377,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
11399
11377
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11400
11378
|
const { loadWorkspaceConfig } = await Promise.resolve().then(() => require("./config.cjs"));
|
|
11401
11379
|
const { reconcileMissingSecrets } = await Promise.resolve().then(() => require("./reconcile-CuCQBa5-.cjs"));
|
|
11402
|
-
const { secretsStoreFor } = await Promise.resolve().then(() => require("./
|
|
11380
|
+
const { secretsStoreFor } = await Promise.resolve().then(() => require("./stale-yu2FkH3G.cjs")).then((n) => n.store_exports);
|
|
11403
11381
|
const { workspace } = await loadWorkspaceConfig();
|
|
11404
11382
|
const stage = options.stage ?? workspace.stages.local;
|
|
11405
11383
|
const store = await secretsStoreFor(workspace, stage);
|
|
@@ -11408,7 +11386,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
11408
11386
|
console.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
|
|
11409
11387
|
process.exit(1);
|
|
11410
11388
|
}
|
|
11411
|
-
const { derivedContainers } = await Promise.resolve().then(() => require("./
|
|
11389
|
+
const { derivedContainers } = await Promise.resolve().then(() => require("./stale-yu2FkH3G.cjs")).then((n) => n.workspace_exports);
|
|
11412
11390
|
const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, stage));
|
|
11413
11391
|
if (!result) {
|
|
11414
11392
|
console.log(`\n✓ Secrets for stage "${stage}" are up-to-date`);
|
|
@@ -11422,8 +11400,19 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
11422
11400
|
process.exit(1);
|
|
11423
11401
|
}
|
|
11424
11402
|
});
|
|
11403
|
+
program.command("secrets:migrate").description("Copy a deployed stage's secrets from the configured store to another (file, ssm, secrets-manager)").requiredOption("--stage <stage>", "A deployed stage").requiredOption("--to <provider>", "file, ssm or secrets-manager").option("--region <region>", "The target's AWS region (default: the configured store's)").option("--profile <profile>", "AWS profile for the stage's account").option("--force", "Replace a stage the target already holds").action(async (options) => {
|
|
11404
|
+
try {
|
|
11405
|
+
const globalOptions = program.opts();
|
|
11406
|
+
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11407
|
+
const { secretsMigrateCommand } = await Promise.resolve().then(() => require("./migrate-31JXUOaG.cjs"));
|
|
11408
|
+
await secretsMigrateCommand(options);
|
|
11409
|
+
} catch (error) {
|
|
11410
|
+
console.error(formatError(error));
|
|
11411
|
+
process.exit(1);
|
|
11412
|
+
}
|
|
11413
|
+
});
|
|
11425
11414
|
program.command("deploy").description("Deploy a stage through its target").option("--target <name>", "Deploy target: dokploy, compose, sst, or one named in deploy.targets (default: deploy.default)").option("--provider <provider>", "[DEPRECATED] Use --target instead").requiredOption("--stage <stage>", "Deployment stage (e.g., production, staging)").option("--tag <tag>", "Image tag (default: stage-timestamp; compose: the commit). Compose pulls a given tag").option("--skip-push", "Skip pushing image to registry").option("--skip-build", "Skip build step (use existing build)").option("--json", "Write events as JSON lines instead of progress; never prompts").option("--dry-run", "Show what would be created or reused; change, build and push nothing").option("--atomic", "If the release fails, roll back every app it released, not only the failed ones").option("--allow-dev-services <list>", "Server targets: run MinIO and/or Mailpit (minio,mailpit) for mail and buckets the stage's secrets don't configure. Not production-grade").action(async (options) => {
|
|
11426
|
-
const { deployCli } = await Promise.resolve().then(() => require("./cli-
|
|
11415
|
+
const { deployCli } = await Promise.resolve().then(() => require("./cli-ZpFTMbGw.cjs"));
|
|
11427
11416
|
const globalOptions = program.opts();
|
|
11428
11417
|
const code = await deployCli({
|
|
11429
11418
|
cwd: (0, node_path.resolve)(globalOptions.cwd ?? process.cwd()),
|
|
@@ -11440,7 +11429,7 @@ program.command("deploy").description("Deploy a stage through its target").optio
|
|
|
11440
11429
|
});
|
|
11441
11430
|
program.command("deploy:rollback").description("Put a stage's app back on its previous release (Dokploy): one app with --app, every app with --atomic").requiredOption("--stage <stage>", "A deployed stage").option("--app <app>", "The app to roll back").option("--atomic", "Roll back every app that has an earlier release").action(async (options) => {
|
|
11442
11431
|
try {
|
|
11443
|
-
const { rollbackStage } = await Promise.resolve().then(() => require("./rollback-
|
|
11432
|
+
const { rollbackStage } = await Promise.resolve().then(() => require("./rollback-CpOWRR9H.cjs")).then((n) => n.rollback_exports);
|
|
11444
11433
|
const { terminalCredentials } = await Promise.resolve().then(() => require("./terminal-BL5E0xbR.cjs"));
|
|
11445
11434
|
const globalOptions = program.opts();
|
|
11446
11435
|
await rollbackStage({
|
|
@@ -11476,7 +11465,7 @@ program.command("deploy:github").description("Let GitHub Actions deploy a stage:
|
|
|
11476
11465
|
try {
|
|
11477
11466
|
const globalOptions = program.opts();
|
|
11478
11467
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11479
|
-
const { deployGithubCommand } = await Promise.resolve().then(() => require("./github-
|
|
11468
|
+
const { deployGithubCommand } = await Promise.resolve().then(() => require("./github-Bmb45xUQ.cjs"));
|
|
11480
11469
|
await deployGithubCommand(options);
|
|
11481
11470
|
} catch (error) {
|
|
11482
11471
|
console.error(formatError(error));
|