@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
|
@@ -2,10 +2,10 @@ import { t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
|
|
|
2
2
|
import { i as run$1, s as gkmHome } from "./run-BJLIerMM.mjs";
|
|
3
3
|
import { d as output, r as discover, u as ConstructGenerator } from "./discover-BPelzeGW.mjs";
|
|
4
4
|
import { t as appKey } from "./derive-B4vDpzgP.mjs";
|
|
5
|
-
import { O as TEST_STAGE, h as getPublicEnvPrefix, n as allConstructGlobs } from "./workspace-
|
|
5
|
+
import { F as UnknownSecretsStoreProvider, O as TEST_STAGE, h as getPublicEnvPrefix, m as PUBLIC_ENV_PREFIXES, n as allConstructGlobs } from "./workspace-QUTqYmVy.mjs";
|
|
6
6
|
import { ConfigNotFound, NotInAnApp, loadWorkspaceAppInfo, loadWorkspaceConfig } from "./config.mjs";
|
|
7
7
|
import { n as runtimeFor, r as generateTelemetryModule } from "./EndpointGenerator-DftalLYg.mjs";
|
|
8
|
-
import { c as runtimeOf } from "./resolve-
|
|
8
|
+
import { c as runtimeOf } from "./resolve-BF1ICosS.mjs";
|
|
9
9
|
import { a as DEFAULT_STORAGE, i as DEFAULT_EVENTS$1, n as readFakes, o as holdsEveryCache, r as DEFAULT_CACHE, t as SubscriberGenerator } from "./SubscriberGenerator-5looQ3gB.mjs";
|
|
10
10
|
import { basename, dirname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
|
|
11
11
|
import { constants, existsSync, readFileSync } from "node:fs";
|
|
@@ -91,10 +91,6 @@ function toEmbeddableSecrets(secrets) {
|
|
|
91
91
|
AWS_SECRET_ACCESS_KEY: secrets.services.localstack.password,
|
|
92
92
|
AWS_REGION: secrets.services.localstack.region ?? "us-east-1",
|
|
93
93
|
AWS_ENDPOINT_URL: `http://${secrets.services.localstack.host}:${secrets.services.localstack.port}`
|
|
94
|
-
},
|
|
95
|
-
...secrets.services.pgboss && {
|
|
96
|
-
PGBOSS_DB_USER: secrets.services.pgboss.username,
|
|
97
|
-
PGBOSS_DB_PASSWORD: secrets.services.pgboss.password
|
|
98
94
|
}
|
|
99
95
|
};
|
|
100
96
|
}
|
|
@@ -527,7 +523,8 @@ function decrypt(data, keyHex) {
|
|
|
527
523
|
var store_exports = /* @__PURE__ */ __exportAll({
|
|
528
524
|
FileSecretsStore: () => FileSecretsStore,
|
|
529
525
|
isRemoteStore: () => isRemoteStore,
|
|
530
|
-
secretsStoreFor: () => secretsStoreFor
|
|
526
|
+
secretsStoreFor: () => secretsStoreFor,
|
|
527
|
+
storeFromConfig: () => storeFromConfig
|
|
531
528
|
});
|
|
532
529
|
/**
|
|
533
530
|
* The store a stage's secrets are kept in — what every command reads and
|
|
@@ -539,13 +536,41 @@ var store_exports = /* @__PURE__ */ __exportAll({
|
|
|
539
536
|
async function secretsStoreFor(workspace, stage, options = {}) {
|
|
540
537
|
const configured = workspace.secrets.store ?? "file";
|
|
541
538
|
if (stage === workspace.stages.local || configured === "file") return new FileSecretsStore(workspace.root, keystoreProject(workspace, options.home));
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
539
|
+
return storeFromConfig(workspace, configured, options);
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* The store a `secrets.store` value describes, for any stage — what
|
|
543
|
+
* {@link secretsStoreFor} answers for a deployed stage, and what
|
|
544
|
+
* `gkm secrets:migrate` builds for the store it copies to.
|
|
545
|
+
*/
|
|
546
|
+
async function storeFromConfig(workspace, config, options = {}) {
|
|
547
|
+
if (config === "file") return new FileSecretsStore(workspace.root, keystoreProject(workspace, options.home));
|
|
548
|
+
const profile = options.profile ? { profile: options.profile } : {};
|
|
549
|
+
switch (config.provider) {
|
|
550
|
+
case "ssm": {
|
|
551
|
+
const { AwsSecretsStore } = await import("./aws-Bja4zGSs.mjs");
|
|
552
|
+
return new AwsSecretsStore({
|
|
553
|
+
project: workspace.name,
|
|
554
|
+
region: config.region,
|
|
555
|
+
...profile
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
case "secrets-manager": {
|
|
559
|
+
const { kmsKeyId } = config;
|
|
560
|
+
const { SecretsManagerSecretsStore } = await import("./secretsManager-Ti0oZwsS.mjs");
|
|
561
|
+
return new SecretsManagerSecretsStore({
|
|
562
|
+
project: workspace.name,
|
|
563
|
+
region: config.region,
|
|
564
|
+
...kmsKeyId ? { kmsKeyId } : {},
|
|
565
|
+
...profile
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
default: {
|
|
569
|
+
const provider = config.provider;
|
|
570
|
+
if (typeof provider === "object" && provider !== null) return provider;
|
|
571
|
+
throw new UnknownSecretsStoreProvider(provider);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
549
574
|
}
|
|
550
575
|
/** Whether a stage's secrets live somewhere other than this machine. */
|
|
551
576
|
function isRemoteStore(workspace, stage) {
|
|
@@ -632,24 +657,18 @@ async function savePortState(workspaceRoot, ports) {
|
|
|
632
657
|
await writeFile(join(workspaceRoot, PORT_STATE_PATH), `${JSON.stringify(ports, null, 2)}\n`);
|
|
633
658
|
}
|
|
634
659
|
/**
|
|
635
|
-
* Load and flatten
|
|
636
|
-
*
|
|
660
|
+
* Load and flatten a stage's secrets from its store.
|
|
661
|
+
*
|
|
662
|
+
* Every key as stored — nothing renamed. An app's database URL is its
|
|
663
|
+
* construct's key, derived by reconcile, and never a stored per-app value
|
|
664
|
+
* mapped onto `DATABASE_URL`.
|
|
637
665
|
* @internal Exported for testing
|
|
638
666
|
*/
|
|
639
|
-
async function loadSecretsForApp(store, stage
|
|
640
|
-
let secrets = {};
|
|
667
|
+
async function loadSecretsForApp(store, stage) {
|
|
641
668
|
const stageSecrets = await store.read(stage);
|
|
642
|
-
if (stageSecrets) {
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
if (Object.keys(secrets).length === 0) return {};
|
|
647
|
-
if (!appName) return secrets;
|
|
648
|
-
const prefix = appName.toUpperCase();
|
|
649
|
-
const mapped = { ...secrets };
|
|
650
|
-
const appDbUrl = secrets[`${prefix}_DATABASE_URL`];
|
|
651
|
-
if (appDbUrl) mapped.DATABASE_URL = appDbUrl;
|
|
652
|
-
return mapped;
|
|
669
|
+
if (!stageSecrets) return {};
|
|
670
|
+
logger$1.log(`🔐 Loading secrets from stage: ${stage}`);
|
|
671
|
+
return toEmbeddableSecrets(stageSecrets);
|
|
653
672
|
}
|
|
654
673
|
/**
|
|
655
674
|
* Walk up the directory tree to find the root containing .gkm/secrets/.
|
|
@@ -757,7 +776,7 @@ async function prepareEntryCredentials(options) {
|
|
|
757
776
|
const resolvedPort = options.explicitPort ?? workspaceAppPort ?? 3e3;
|
|
758
777
|
const stage = options.stage ?? workspace?.stages.local;
|
|
759
778
|
const store = stage ? workspace ? await secretsStoreFor(workspace, stage) : new FileSecretsStore(secretsRoot) : void 0;
|
|
760
|
-
const credentials = store && stage ? await loadSecretsForApp(store, stage
|
|
779
|
+
const credentials = store && stage ? await loadSecretsForApp(store, stage) : {};
|
|
761
780
|
credentials.PORT = String(resolvedPort);
|
|
762
781
|
if (appInfo?.app.type === "mobile") credentials.RCT_METRO_PORT = String(resolvedPort);
|
|
763
782
|
const declaredKeys = [];
|
|
@@ -1022,6 +1041,36 @@ function eventsBackendFor(on) {
|
|
|
1022
1041
|
return DEFAULT_EVENTS$1[on];
|
|
1023
1042
|
}
|
|
1024
1043
|
//#endregion
|
|
1044
|
+
//#region src/exec/imageBuild.ts
|
|
1045
|
+
/**
|
|
1046
|
+
* Set by a site's Dockerfile in its builder stage: this process is building
|
|
1047
|
+
* an image.
|
|
1048
|
+
*
|
|
1049
|
+
* Inside an image there is no stage to load secrets for and no local
|
|
1050
|
+
* container to resolve an address from — the public URLs the bundle inlines
|
|
1051
|
+
* arrived as the Dockerfile's build args, already in the environment. So
|
|
1052
|
+
* `gkm exec -- next build` there injects exactly those, and never the
|
|
1053
|
+
* `localhost` addresses a workspace resolves on a developer's machine.
|
|
1054
|
+
*/
|
|
1055
|
+
const IMAGE_BUILD_ENV = "GKM_IMAGE_BUILD";
|
|
1056
|
+
/** Whether this process is building an image. */
|
|
1057
|
+
function isImageBuild(env = process.env) {
|
|
1058
|
+
return env[IMAGE_BUILD_ENV] === "1";
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* What `gkm exec` injects inside an image build: the public values its build
|
|
1062
|
+
* args set — every `NEXT_PUBLIC_*`, `VITE_*` and `EXPO_PUBLIC_*` — and
|
|
1063
|
+
* nothing read from a secrets store, a file or a container.
|
|
1064
|
+
*/
|
|
1065
|
+
function imageBuildCredentials(env = process.env) {
|
|
1066
|
+
const credentials = {};
|
|
1067
|
+
for (const [key, value] of Object.entries(env)) {
|
|
1068
|
+
if (value === void 0) continue;
|
|
1069
|
+
if (PUBLIC_ENV_PREFIXES.some((prefix) => key.startsWith(prefix))) credentials[key] = value;
|
|
1070
|
+
}
|
|
1071
|
+
return credentials;
|
|
1072
|
+
}
|
|
1073
|
+
//#endregion
|
|
1025
1074
|
//#region src/docker/templates.ts
|
|
1026
1075
|
/**
|
|
1027
1076
|
* The turbo every image prunes and builds with when the build root resolves
|
|
@@ -1319,7 +1368,48 @@ function binPath(options) {
|
|
|
1319
1368
|
* were installed.
|
|
1320
1369
|
*/
|
|
1321
1370
|
function gkmCommand(args) {
|
|
1322
|
-
return `GKM_BIN="$(node -e '
|
|
1371
|
+
return `GKM_BIN="$(node -e '${FIND_GKM_BIN}')" && node "$GKM_BIN" ${args}`;
|
|
1372
|
+
}
|
|
1373
|
+
/** Prints the `bin/gkm.mjs` Node resolves from the cwd, or fails saying so. */
|
|
1374
|
+
const FIND_GKM_BIN = `let d=process.cwd();const{existsSync:e}=require("fs"),{dirname:u,join:j}=require("path");for(;;){const p=j(d,"node_modules/@geekmidas/cli/bin/gkm.mjs");if(e(p)){console.log(p);break}if(u(d)===d){console.error("@geekmidas/cli is not installed where the app can resolve it");process.exit(1)}d=u(d)}`;
|
|
1375
|
+
/**
|
|
1376
|
+
* What a site's builder does with the gkm workspace it carries, before its
|
|
1377
|
+
* framework builds it — all of it inside the image, nothing from the host:
|
|
1378
|
+
*
|
|
1379
|
+
* - `gkm` on the PATH: the CLI the workspace installs, so a build script that
|
|
1380
|
+
* is `gkm exec -- next build` runs. Resolved from the gkm root rather than
|
|
1381
|
+
* through `node_modules/.bin`, where a CLI that is a workspace package has
|
|
1382
|
+
* no bin linked.
|
|
1383
|
+
* - `GKM_IMAGE_BUILD`, which has `gkm exec` inject the build args above — the
|
|
1384
|
+
* stage's public URLs — and never load a secret or resolve a local address.
|
|
1385
|
+
* - each backend's typed client, generated from its endpoints at the
|
|
1386
|
+
* workspace root's `.gkm/client/`, where the site's tsconfig paths point.
|
|
1387
|
+
*/
|
|
1388
|
+
function siteWorkspaceSteps(options) {
|
|
1389
|
+
const { gkmRoot } = layout(options);
|
|
1390
|
+
const root = `/app/${gkmRoot}`.replace(/\/\.$/, "");
|
|
1391
|
+
const clients = options.clients ?? [];
|
|
1392
|
+
const generate = clients.length ? `
|
|
1393
|
+
|
|
1394
|
+
# The typed client of each API this site calls, generated from its endpoints
|
|
1395
|
+
# into ${gkmRoot === "." ? "" : `${gkmRoot}/`}.gkm/client/ — offline, with no secret and no container.
|
|
1396
|
+
RUN ${clients.map(({ app, path }) => `cd /app/${path} && gkm openapi --app ${app}`).join(" && \\\n ")}` : "";
|
|
1397
|
+
return `# The gkm CLI the workspace installs, as \`gkm\`
|
|
1398
|
+
RUN cd ${root} && GKM_BIN="$(node -e '${FIND_GKM_BIN}')" && \\
|
|
1399
|
+
{ echo '#!/bin/sh'; echo "exec node \\"$GKM_BIN\\" \\"\\$@\\""; } > /usr/local/bin/gkm && \\
|
|
1400
|
+
chmod +x /usr/local/bin/gkm
|
|
1401
|
+
|
|
1402
|
+
# \`gkm exec\` in this build injects the build args, never a stage's secrets
|
|
1403
|
+
ENV ${IMAGE_BUILD_ENV}=1${generate}`;
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Build the site with turbo. Loose env mode, so the task sees what the
|
|
1407
|
+
* Dockerfile set — the build args and `GKM_IMAGE_BUILD` — whatever the
|
|
1408
|
+
* project's turbo.json declares: the image's environment holds nothing else.
|
|
1409
|
+
*/
|
|
1410
|
+
function siteBuild(options) {
|
|
1411
|
+
const { turbo } = layout(options);
|
|
1412
|
+
return `RUN ${turbo} run build --filter='${options.turboPackage}' --env-mode=loose`;
|
|
1323
1413
|
}
|
|
1324
1414
|
/**
|
|
1325
1415
|
* The encrypted credentials, from a build secret — never an ARG, which is
|
|
@@ -1473,8 +1563,7 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \\
|
|
|
1473
1563
|
* @internal Exported for testing
|
|
1474
1564
|
*/
|
|
1475
1565
|
function generateNextjsDockerfile(options) {
|
|
1476
|
-
const { port, appPath,
|
|
1477
|
-
const { turbo } = layout(options);
|
|
1566
|
+
const { port, appPath, publicUrlArgs = ["NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_AUTH_URL"] } = options;
|
|
1478
1567
|
return `# syntax=docker/dockerfile:1
|
|
1479
1568
|
# Next.js standalone Dockerfile, built from a turbo-pruned slice
|
|
1480
1569
|
|
|
@@ -1484,13 +1573,15 @@ ${depsStage(options)}
|
|
|
1484
1573
|
|
|
1485
1574
|
${builderStage(options, { args: publicUrlArgs })}
|
|
1486
1575
|
|
|
1576
|
+
${siteWorkspaceSteps(options)}
|
|
1577
|
+
|
|
1487
1578
|
# Ensure public directory exists (may be empty for scaffolded projects)
|
|
1488
1579
|
RUN mkdir -p ${appPath}/public
|
|
1489
1580
|
|
|
1490
1581
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
1491
1582
|
|
|
1492
1583
|
# Build the application
|
|
1493
|
-
|
|
1584
|
+
${siteBuild(options)}
|
|
1494
1585
|
|
|
1495
1586
|
# The runner needs the standalone server; without it there is nothing to run.
|
|
1496
1587
|
RUN if [ ! -d ${appPath}/.next/standalone ]; then \\
|
|
@@ -1678,8 +1769,7 @@ CMD ["node", "index.mjs"]
|
|
|
1678
1769
|
* @internal Exported for testing
|
|
1679
1770
|
*/
|
|
1680
1771
|
function generateNodeWebDockerfile(options) {
|
|
1681
|
-
const { port, appPath
|
|
1682
|
-
const { turbo } = layout(options);
|
|
1772
|
+
const { port, appPath } = options;
|
|
1683
1773
|
return `# syntax=docker/dockerfile:1
|
|
1684
1774
|
# Node SSR web Dockerfile (TanStack Start / Remix), from a turbo-pruned slice
|
|
1685
1775
|
|
|
@@ -1688,7 +1778,10 @@ ${prunerStage(options)}
|
|
|
1688
1778
|
${depsStage(options)}
|
|
1689
1779
|
|
|
1690
1780
|
${builderStage(options, { args: options.publicUrlArgs ?? [] })}
|
|
1691
|
-
|
|
1781
|
+
|
|
1782
|
+
${siteWorkspaceSteps(options)}
|
|
1783
|
+
|
|
1784
|
+
${siteBuild(options)}
|
|
1692
1785
|
|
|
1693
1786
|
FROM ${options.baseImage} AS runner
|
|
1694
1787
|
WORKDIR /app
|
|
@@ -1722,8 +1815,7 @@ CMD ["sh", "-c", "cd ${appPath} && npm start"]
|
|
|
1722
1815
|
* @internal Exported for testing
|
|
1723
1816
|
*/
|
|
1724
1817
|
function generateViteStaticDockerfile(options) {
|
|
1725
|
-
const { port, appPath
|
|
1726
|
-
const { turbo } = layout(options);
|
|
1818
|
+
const { port, appPath } = options;
|
|
1727
1819
|
return `# syntax=docker/dockerfile:1
|
|
1728
1820
|
# Vite SPA Dockerfile — a turbo-pruned slice built to static files, served by Caddy
|
|
1729
1821
|
|
|
@@ -1732,7 +1824,10 @@ ${prunerStage(options)}
|
|
|
1732
1824
|
${depsStage(options)}
|
|
1733
1825
|
|
|
1734
1826
|
${builderStage(options, { args: options.publicUrlArgs ?? [] })}
|
|
1735
|
-
|
|
1827
|
+
|
|
1828
|
+
${siteWorkspaceSteps(options)}
|
|
1829
|
+
|
|
1830
|
+
${siteBuild(options)}
|
|
1736
1831
|
|
|
1737
1832
|
FROM ${STATIC_SITE_IMAGE} AS runner
|
|
1738
1833
|
|
|
@@ -1841,7 +1936,7 @@ function fromBuildRoot(layout, path) {
|
|
|
1841
1936
|
return joined === "" ? "." : joined;
|
|
1842
1937
|
}
|
|
1843
1938
|
/** Everything a template needs about one app, relative to the build root. */
|
|
1844
|
-
function appImageOptions(layout, appName, app, workspaceRoot) {
|
|
1939
|
+
function appImageOptions(layout, appName, app, workspaceRoot, apps = {}) {
|
|
1845
1940
|
const turboPackage = packageName(isAbsolute(app.path) ? app.path : join(workspaceRoot, app.path)) ?? appName;
|
|
1846
1941
|
return {
|
|
1847
1942
|
imageName: appName,
|
|
@@ -1857,10 +1952,49 @@ function appImageOptions(layout, appName, app, workspaceRoot) {
|
|
|
1857
1952
|
...app.type === "backend" ? {
|
|
1858
1953
|
gkmPaths: layout.gkmPaths,
|
|
1859
1954
|
...layout.workspacePackage && layout.workspacePackage !== turboPackage ? { prunePackages: [layout.workspacePackage] } : {}
|
|
1860
|
-
} : {}
|
|
1955
|
+
} : app.type === "web" ? siteWorkspace(layout, app, apps, workspaceRoot, turboPackage) : {}
|
|
1861
1956
|
};
|
|
1862
1957
|
}
|
|
1863
1958
|
/**
|
|
1959
|
+
* What a site's image carries of the gkm workspace: its config and construct
|
|
1960
|
+
* directories, the workspace's own package where it is nested in a monorepo
|
|
1961
|
+
* (it holds the CLI), and each backend the site calls — whose endpoints its
|
|
1962
|
+
* client is generated from, and whose package their imports resolve in.
|
|
1963
|
+
*/
|
|
1964
|
+
function siteWorkspace(layout, site, apps, workspaceRoot, turboPackage) {
|
|
1965
|
+
const clients = siteClients(site, apps);
|
|
1966
|
+
const packages = /* @__PURE__ */ new Set();
|
|
1967
|
+
if (layout.workspacePackage) packages.add(layout.workspacePackage);
|
|
1968
|
+
for (const { app } of clients) {
|
|
1969
|
+
const backend = apps[app];
|
|
1970
|
+
const name = packageName(isAbsolute(backend.path) ? backend.path : join(workspaceRoot, backend.path));
|
|
1971
|
+
if (name) packages.add(name);
|
|
1972
|
+
}
|
|
1973
|
+
packages.delete(turboPackage);
|
|
1974
|
+
return {
|
|
1975
|
+
gkmPaths: layout.gkmPaths,
|
|
1976
|
+
...packages.size > 0 ? { prunePackages: [...packages].sort() } : {},
|
|
1977
|
+
...clients.length > 0 ? { clients: clients.map(({ app }) => ({
|
|
1978
|
+
app,
|
|
1979
|
+
path: fromBuildRoot(layout, apps[app].path)
|
|
1980
|
+
})) } : {}
|
|
1981
|
+
};
|
|
1982
|
+
}
|
|
1983
|
+
/**
|
|
1984
|
+
* The backends whose clients a site imports: each it depends on that gkm
|
|
1985
|
+
* builds from endpoints — not one with an entry of its own, and not one that
|
|
1986
|
+
* turned OpenAPI off.
|
|
1987
|
+
*/
|
|
1988
|
+
function siteClients(site, apps) {
|
|
1989
|
+
return site.dependencies.filter((name) => {
|
|
1990
|
+
const app = apps[name];
|
|
1991
|
+
if (!app || app.type !== "backend" || app.entry) return false;
|
|
1992
|
+
if (app.openapi === false) return false;
|
|
1993
|
+
if (typeof app.openapi === "object" && app.openapi.enabled === false) return false;
|
|
1994
|
+
return true;
|
|
1995
|
+
}).sort().map((app) => ({ app }));
|
|
1996
|
+
}
|
|
1997
|
+
/**
|
|
1864
1998
|
* The directories the workspace's construct globs start in, relative to its
|
|
1865
1999
|
* root: `./constructs/**\/*.ts` reads from `constructs`.
|
|
1866
2000
|
*/
|
|
@@ -5883,6 +6017,7 @@ async function workspaceDockerCommand(workspace, manifest, imageNames = {}, back
|
|
|
5883
6017
|
const dockerfile = appDockerfile(appName, app, {
|
|
5884
6018
|
layout,
|
|
5885
6019
|
workspaceRoot: workspace.root,
|
|
6020
|
+
apps: workspace.apps,
|
|
5886
6021
|
...manifest ? { manifest } : {}
|
|
5887
6022
|
});
|
|
5888
6023
|
const path = dockerfileOf(appName, app.path);
|
|
@@ -5938,7 +6073,7 @@ async function workspaceDockerCommand(workspace, manifest, imageNames = {}, back
|
|
|
5938
6073
|
* framework. The one choice every builder of images makes.
|
|
5939
6074
|
*/
|
|
5940
6075
|
function appDockerfile(appName, app, options) {
|
|
5941
|
-
const image = appImageOptions(options.layout, appName, app, options.workspaceRoot);
|
|
6076
|
+
const image = appImageOptions(options.layout, appName, app, options.workspaceRoot, options.apps);
|
|
5942
6077
|
if (app.type === "web") return siteDockerfile(appName, app, {
|
|
5943
6078
|
image,
|
|
5944
6079
|
...options.manifest ? { manifest: options.manifest } : {},
|
|
@@ -6352,6 +6487,96 @@ function setPostgresBackupId(state, backupId) {
|
|
|
6352
6487
|
if (state.backups) state.backups.postgresBackupId = backupId;
|
|
6353
6488
|
}
|
|
6354
6489
|
//#endregion
|
|
6355
|
-
|
|
6490
|
+
//#region src/secrets/stale.ts
|
|
6491
|
+
/**
|
|
6492
|
+
* Stored secrets an older gkm generated that now shadow a derived value.
|
|
6493
|
+
*
|
|
6494
|
+
* Before constructs, initialising a stage wrote an address for each app into
|
|
6495
|
+
* its custom secrets: `<APP>_DATABASE_URL` as a `postgresql://…@localhost`
|
|
6496
|
+
* URL with a password of its own, and `http://localhost:<port>` for a site or
|
|
6497
|
+
* an auth server. Those keys are now a construct's — `database.schema('AuthDatabase')`
|
|
6498
|
+
* provides `AUTH_DATABASE_URL`, `new BetterAuth('Auth')` provides `AUTH_URL`
|
|
6499
|
+
* — and a deploy derives them. A value the stage holds is a value set by hand,
|
|
6500
|
+
* and set by hand wins: the container is handed `localhost`, where nothing
|
|
6501
|
+
* answers, with a password no role has.
|
|
6502
|
+
*
|
|
6503
|
+
* So a deploy refuses such a stage rather than run it, naming each key and
|
|
6504
|
+
* the command that removes it. Nothing is deleted for the user: the value is
|
|
6505
|
+
* theirs, and only they can say it is stale. A URL that names a real host — a
|
|
6506
|
+
* managed database — is a deliberate choice and still wins.
|
|
6507
|
+
*/
|
|
6508
|
+
/** The kinds whose URL an older gkm wrote into a stage's secrets. */
|
|
6509
|
+
const ADDRESSED = /* @__PURE__ */ new Set([
|
|
6510
|
+
"database",
|
|
6511
|
+
"database-reader",
|
|
6512
|
+
"database-schema",
|
|
6513
|
+
"rest-api",
|
|
6514
|
+
"site"
|
|
6515
|
+
]);
|
|
6516
|
+
/** Hosts that are this machine — never anything, inside a container. */
|
|
6517
|
+
const LOOPBACK = /* @__PURE__ */ new Set([
|
|
6518
|
+
"localhost",
|
|
6519
|
+
"127.0.0.1",
|
|
6520
|
+
"[::1]",
|
|
6521
|
+
"::1"
|
|
6522
|
+
]);
|
|
6523
|
+
/**
|
|
6524
|
+
* A stage holds a construct's address as a custom secret, pointing at
|
|
6525
|
+
* `localhost` — what an older `gkm secrets:init`, `gkm setup` or `gkm init`
|
|
6526
|
+
* generated. Set by hand wins over derived, so the app would be handed it.
|
|
6527
|
+
*/
|
|
6528
|
+
var StaleStageSecrets = class extends Error {
|
|
6529
|
+
stage;
|
|
6530
|
+
stale;
|
|
6531
|
+
constructor(stage, stale) {
|
|
6532
|
+
const one = stale.length === 1;
|
|
6533
|
+
super(`The stage '${stage}' holds ${one ? "a value" : "values"} an older gkm generated for ${one ? "an address a construct" : "addresses constructs"} now ${one ? "provides" : "provide"}:\n` + stale.map((s) => ` ${s.key}: ${s.construct}'s, stored pointing at ${s.host}`).join("\n") + `
|
|
6534
|
+
A stored value wins over the derived one, so the app would be handed an address where nothing answers inside its container. Remove ${one ? "it" : "each"}, and the construct's own value is used:\n` + stale.map((s) => ` gkm secrets:unset ${s.key} --stage ${stage}`).join("\n") + "\nA managed service set with its real host is not affected.");
|
|
6535
|
+
this.stage = stage;
|
|
6536
|
+
this.stale = stale;
|
|
6537
|
+
this.name = "StaleStageSecrets";
|
|
6538
|
+
}
|
|
6539
|
+
};
|
|
6540
|
+
/** The host a stored value names, if it is a URL. */
|
|
6541
|
+
function hostOf(value) {
|
|
6542
|
+
try {
|
|
6543
|
+
return new URL(value).hostname;
|
|
6544
|
+
} catch {
|
|
6545
|
+
return;
|
|
6546
|
+
}
|
|
6547
|
+
}
|
|
6548
|
+
/**
|
|
6549
|
+
* Each stored key that a construct provides an address for, holding an
|
|
6550
|
+
* address on this machine.
|
|
6551
|
+
*/
|
|
6552
|
+
function staleStageSecrets(manifest, supplied) {
|
|
6553
|
+
const stale = [];
|
|
6554
|
+
for (const [id, declaration] of Object.entries(manifest)) {
|
|
6555
|
+
if (!ADDRESSED.has(declaration.kind)) continue;
|
|
6556
|
+
const key = providedKeyFor(id, declaration.kind, "url");
|
|
6557
|
+
const value = supplied[key];
|
|
6558
|
+
if (value === void 0) continue;
|
|
6559
|
+
const host = hostOf(value);
|
|
6560
|
+
if (host === void 0 || !LOOPBACK.has(host)) continue;
|
|
6561
|
+
stale.push({
|
|
6562
|
+
key,
|
|
6563
|
+
construct: id,
|
|
6564
|
+
host
|
|
6565
|
+
});
|
|
6566
|
+
}
|
|
6567
|
+
return stale.sort((a, b) => a.key.localeCompare(b.key));
|
|
6568
|
+
}
|
|
6569
|
+
/**
|
|
6570
|
+
* Refuse a stage whose stored secrets would shadow a construct's address with
|
|
6571
|
+
* `localhost`.
|
|
6572
|
+
*
|
|
6573
|
+
* @throws {StaleStageSecrets} naming each key and the command removing it
|
|
6574
|
+
*/
|
|
6575
|
+
function assertNoStaleSecrets(options) {
|
|
6576
|
+
const stale = staleStageSecrets(options.manifest, options.supplied);
|
|
6577
|
+
if (stale.length > 0) throw new StaleStageSecrets(options.stage, stale);
|
|
6578
|
+
}
|
|
6579
|
+
//#endregion
|
|
6580
|
+
export { workspace_exports as $, readKey as $t, DevServicesNeedServerTarget as A, eventsBackendFor as At, requiredStageKeys as B, findAvailablePort as Bt, validateImageRef as C, TURBO_VERSION as Ct, isOtlpDestination as D, imageBuildCredentials as Dt, resolveHost as E, findBuildRoot as Et, devServicesUsed as F, fakeKey as Ft, workerEntryDir as G, isRemoteStore as Gt, workerUnits as H, loadEnvFiles as Ht, externalServices as I, portKeys as It, FAKE_ENV as J, store_exports as Jt, QueueGenerator as K, secretsStoreFor as Kt, manifestServiceDeclarations as L, primaryPortKey as Lt, STORAGE_KEY_PAIR as M, storageBackendFor as Mt, UnknownDevService as N, DEFAULT_IMAGES as Nt, otelEnv as O, isImageBuild as Ot, assertExternalServices as P, describeServices as Pt, reconcileWorkspace as Q, projectKey as Qt, parseDevServices as R, createCredentialsPreload as Rt, workerDockerfileOf as S, imageLayout as St, isMainFrontendApp as T, detectPackageManager as Tt, WorkerGenerator as U, loadSecretsForApp as Ut, suppliedOnly as V, isPortAvailable as Vt, workerBundleName as W, prepareEntryCredentials as Wt, constructGlobs as X, getKeyPath as Xt, backendsOf as Y, FileSecretsStore as Yt, derivedContainers as Z, keystoreProject as Zt, DockerPushFailed as _, localRolePassword as _t, isDnsVerified as a, markerOf as an, bucketPolicies as at, ensureDockerignore as b, hostFor as bt, setApplicationId as c, initStageSecrets as cn, quoteIdentifier as ct, setDnsVerification as d, toEmbeddableSecrets as dn, pgClient as dt, applicationName as en, LOCAL_CA_PATH as et, setGeneratedSecret as f, withCustomSecret as fn, appEnvKeys as ft, DockerBuildFailed as g, envFor as gt, withGeneratedSecrets as h, workerEnvKeys as ht, getGeneratedSecret as i, isOwnedBy as in, applyPostgres as it, ExternalServicesNotConfigured as j, providerOf as jt, DEV_SERVICES as k, cacheBackendFor as kt, setBackupState as l, maskPassword as ln, composeFor as lt, DeployJournal as m, networkEnv as mt, createEmptyState as n, imageName as nn, applyBuckets as nt, recordRelease as o, ownershipMarker as on, postgresDatabaseNames as ot, setPostgresBackupId as p, dockerfileOf as pt, CronGenerator as q, storeFromConfig as qt, getBackupState as r, imageRef as rn, applyPolicies as rt, recordRollback as s, projectName as sn, postgresStatements as st, assertNoStaleSecrets as t, deployIdentity as tn, forgetState as tt, setDnsRecord as u, storage_exports as un, bucketClient as ut, appDockerfile as v, planFor as vt, NoDomainForStage as w, WORKER_PORT as wt, workerDockerfile as x, composeBuildPaths as xt, dockerCommand as y, resourceName as yt, reportDevServices as z, createEntryWrapper as zt };
|
|
6356
6581
|
|
|
6357
|
-
//# sourceMappingURL=
|
|
6582
|
+
//# sourceMappingURL=stale-DGzpiN5S.mjs.map
|