@geekmidas/cli 10.0.0-alpha.25 → 10.0.0-alpha.27
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/{config-Dn9DW2Fz.cjs → config-7R_-WyHq.cjs} +24 -3
- package/dist/{config-Dn9DW2Fz.cjs.map → config-7R_-WyHq.cjs.map} +1 -1
- package/dist/{config-DBGpRTUy.mjs → config-DXrrYvob.mjs} +19 -4
- package/dist/{config-DBGpRTUy.mjs.map → config-DXrrYvob.mjs.map} +1 -1
- package/dist/config.cjs +3 -2
- package/dist/config.d.cts +12 -1
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +12 -1
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -3
- package/dist/{github-BOaa3kQR.mjs → github-Ba5kXEJo.mjs} +4 -4
- package/dist/{github-BOaa3kQR.mjs.map → github-Ba5kXEJo.mjs.map} +1 -1
- package/dist/{github-CUjW3G91.cjs → github-CQflOKKV.cjs} +4 -4
- package/dist/{github-CUjW3G91.cjs.map → github-CQflOKKV.cjs.map} +1 -1
- package/dist/{index-RCUizGxL.d.cts → index-BPN7kghQ.d.cts} +2 -12
- package/dist/{index-B4H4XF7A.d.mts.map → index-BPN7kghQ.d.cts.map} +1 -1
- package/dist/{index-B4H4XF7A.d.mts → index-BqWKWRm0.d.mts} +2 -12
- package/dist/{index-RCUizGxL.d.cts.map → index-BqWKWRm0.d.mts.map} +1 -1
- package/dist/index.cjs +170 -169
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +123 -122
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-DHQlstv6.mjs → openapi-3NLVvtz-.mjs} +2 -2
- package/dist/{openapi-DHQlstv6.mjs.map → openapi-3NLVvtz-.mjs.map} +1 -1
- package/dist/{openapi-BAKQLho-.cjs → openapi-rhJdy2GC.cjs} +2 -2
- package/dist/{openapi-BAKQLho-.cjs.map → openapi-rhJdy2GC.cjs.map} +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/{generator-LfZU7NlU.mjs → reconcile-DhbCvh4K.mjs} +111 -2
- package/dist/reconcile-DhbCvh4K.mjs.map +1 -0
- package/dist/{generator-Wdfp0jCS.cjs → reconcile-szmJw_Sb.cjs} +130 -3
- package/dist/reconcile-szmJw_Sb.cjs.map +1 -0
- package/dist/{transfer-B88fTvnh.mjs → transfer-BV00TxZv.mjs} +4 -4
- package/dist/{transfer-B88fTvnh.mjs.map → transfer-BV00TxZv.mjs.map} +1 -1
- package/dist/{transfer-D59M4aaR.cjs → transfer-BYIn7z8m.cjs} +4 -4
- package/dist/{transfer-D59M4aaR.cjs.map → transfer-BYIn7z8m.cjs.map} +1 -1
- package/dist/workspace/index.cjs +1 -2
- package/dist/workspace/index.d.cts +2 -2
- package/dist/workspace/index.d.mts +2 -2
- package/dist/workspace/index.mjs +2 -2
- package/dist/{workspace-CRD9YinV.cjs → workspace-Bav3TVrP.cjs} +47 -78
- package/dist/workspace-Bav3TVrP.cjs.map +1 -0
- package/dist/{credentials-BpoOUa74.mjs → workspace-CUmR_k4J.mjs} +228 -492
- package/dist/workspace-CUmR_k4J.mjs.map +1 -0
- package/dist/{credentials-Dbyccl3A.cjs → workspace-DgeVgxmm.cjs} +229 -517
- package/dist/workspace-DgeVgxmm.cjs.map +1 -0
- package/dist/{workspace-Bu3xNCej.mjs → workspace-T4IVGSoB.mjs} +48 -73
- package/dist/workspace-T4IVGSoB.mjs.map +1 -0
- package/package.json +14 -14
- package/dist/credentials-BpoOUa74.mjs.map +0 -1
- package/dist/credentials-Dbyccl3A.cjs.map +0 -1
- package/dist/generator-LfZU7NlU.mjs.map +0 -1
- package/dist/generator-Wdfp0jCS.cjs.map +0 -1
- package/dist/reconcile-gb1lz1Dk.mjs +0 -113
- package/dist/reconcile-gb1lz1Dk.mjs.map +0 -1
- package/dist/reconcile-hx_vBvux.cjs +0 -136
- package/dist/reconcile-hx_vBvux.cjs.map +0 -1
- package/dist/workspace-Bu3xNCej.mjs.map +0 -1
- package/dist/workspace-CRD9YinV.cjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
2
|
import { n as __require, t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
|
|
3
3
|
import { i as DEFAULT_CACHE, r as ConstructGenerator, s as isPartitionedRoutes, t as discover } from "./discover-0fhCbnk0.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { C as providerOf, S as eventsBackendFor, _ as COMPOSE_PATH, a as loadEnvFiles, b as resourceName, c as resolveServicePorts, d as backendsOf, f as constructGlobs, h as usesConstructs, i as isPortAvailable, l as rewriteUrlsWithPorts, m as reconcileWorkspace, n as createEntryWrapper, o as loadSecretsForApp, p as derivedContainers, r as findAvailablePort, s as prepareEntryCredentials, t as createCredentialsPreload, u as startWorkspaceServices, v as LOCAL_CA_PATH, w as storageBackendFor, x as cacheBackendFor, y as applyPostgres } from "./credentials-BpoOUa74.mjs";
|
|
7
|
-
import { a as generateServiceCredentials, i as generateSecurePassword, n as generateConnectionUrls, o as rotateServicePassword, t as createStageSecrets } from "./generator-LfZU7NlU.mjs";
|
|
4
|
+
import { a as loadConfig, c as parseModuleConfig, i as loadAppConfig, r as getAppNameFromCwd, s as loadWorkspaceConfig, u as derivedApps } from "./config-DXrrYvob.mjs";
|
|
5
|
+
import { D as assertDeployedStage, E as TEST_STAGE, O as deployedProblems, T as InvalidStages, a as getAppBuildOrder, b as getDeployTargetError, k as stageProblems, m as stripPublicPrefix, o as getAppGkmConfig, p as getPublicEnvPrefix, t as allConstructGlobs, x as isDeployTargetSupported } from "./workspace-T4IVGSoB.mjs";
|
|
8
6
|
import { c as getKeyPath, i as setCustomSecret, n as readStageSecrets, o as toEmbeddableSecrets, r as secretsExist, s as writeStageSecrets, t as maskPassword } from "./storage-TP0x118M.mjs";
|
|
9
|
-
import {
|
|
7
|
+
import { _ as isPortAvailable, b as prepareEntryCredentials, c as applyPostgres, d as eventsBackendFor, f as providerOf, g as findAvailablePort, h as createEntryWrapper, i as reconcileWorkspace, l as resourceName, m as createCredentialsPreload, n as constructGlobs, o as COMPOSE_PATH, p as storageBackendFor, r as derivedContainers, s as LOCAL_CA_PATH, t as backendsOf, u as cacheBackendFor, v as loadEnvFiles, y as loadSecretsForApp } from "./workspace-CUmR_k4J.mjs";
|
|
8
|
+
import { a as openapiCommand, c as EndpointGenerator, l as runtimeFor, n as generateOpenApi, o as resolveOpenApiConfig, s as OpenApiTsGenerator, t as OPENAPI_OUTPUT_PATH$1 } from "./openapi-3NLVvtz-.mjs";
|
|
10
9
|
import { i as withRoutes, r as withCompute } from "./emit-Bzq7JsMP.mjs";
|
|
11
|
-
import { i as writeDockerEnvFromSecrets, r as generateFullstackCustomSecrets } from "./reconcile-
|
|
12
|
-
import { a as isRemoteStore, n as pullStageSecrets, r as pushStageSecrets, t as NoStoredSecrets } from "./transfer-
|
|
10
|
+
import { a as createStageSecrets, c as generateServiceCredentials, i as writeDockerEnvFromSecrets, l as rotateServicePassword, o as generateConnectionUrls, r as generateFullstackCustomSecrets, s as generateSecurePassword } from "./reconcile-DhbCvh4K.mjs";
|
|
11
|
+
import { a as isRemoteStore, n as pullStageSecrets, r as pushStageSecrets, t as NoStoredSecrets } from "./transfer-BV00TxZv.mjs";
|
|
13
12
|
import { createRequire } from "node:module";
|
|
14
13
|
import { Command } from "commander";
|
|
15
14
|
import { stdin, stdout } from "node:process";
|
|
@@ -22,13 +21,13 @@ import { execFile, execSync, spawn } from "node:child_process";
|
|
|
22
21
|
import { cacheTable, canonicalId, cloudName, cookieDomain, dependentsOf, kebabCase, provideKey, provisionOrder, scopedName, serviceKey } from "@geekmidas/manifest";
|
|
23
22
|
import fg from "fast-glob";
|
|
24
23
|
import chokidar from "chokidar";
|
|
25
|
-
import { parse as parse$1, parseDocument } from "yaml";
|
|
26
24
|
import { createCipheriv, createHash, randomBytes } from "node:crypto";
|
|
25
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
27
26
|
import { ownerRole, readerRole, roleStatements } from "@geekmidas/db/pg/roles";
|
|
28
27
|
import { Client } from "pg";
|
|
28
|
+
import { parse as parse$1, parseDocument } from "yaml";
|
|
29
29
|
import { promisify } from "node:util";
|
|
30
30
|
import { cacheTableStatements } from "@geekmidas/cache/postgres";
|
|
31
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
32
31
|
import { Cron } from "@geekmidas/constructs/crons";
|
|
33
32
|
import { Function } from "@geekmidas/constructs/functions";
|
|
34
33
|
import { Queue } from "@geekmidas/constructs/queue";
|
|
@@ -39,7 +38,7 @@ import prompts from "prompts";
|
|
|
39
38
|
import { EnvironmentParser } from "@geekmidas/envkit";
|
|
40
39
|
import { serviceContext } from "@geekmidas/services";
|
|
41
40
|
//#region package.json
|
|
42
|
-
var version = "10.0.0-alpha.
|
|
41
|
+
var version = "10.0.0-alpha.27";
|
|
43
42
|
//#endregion
|
|
44
43
|
//#region src/auth/credentials.ts
|
|
45
44
|
/**
|
|
@@ -431,10 +430,7 @@ async function execCommand(commandArgs, options = {}) {
|
|
|
431
430
|
if (!commandArgs[0]) throw new NoCommandSpecified();
|
|
432
431
|
const defaultEnv = loadEnvFiles(".env");
|
|
433
432
|
if (defaultEnv.loaded.length > 0) logger$12.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
|
|
434
|
-
const { credentials, secretsJsonPath, appName } = await prepareEntryCredentials({
|
|
435
|
-
cwd,
|
|
436
|
-
resolveDockerPorts: "readonly"
|
|
437
|
-
});
|
|
433
|
+
const { credentials, secretsJsonPath, appName } = await prepareEntryCredentials({ cwd });
|
|
438
434
|
if (appName) logger$12.log(`📦 App: ${appName}`);
|
|
439
435
|
const secretCount = Object.keys(credentials).filter((k) => k !== "PORT").length;
|
|
440
436
|
if (secretCount > 0) logger$12.log(`🔐 Loaded ${secretCount} secret(s)`);
|
|
@@ -592,6 +588,7 @@ async function devCommand(options) {
|
|
|
592
588
|
return workspaceDevCommand(loadedConfig.workspace, options);
|
|
593
589
|
}
|
|
594
590
|
config = loadedConfig.raw;
|
|
591
|
+
workspace = loadedConfig.workspace;
|
|
595
592
|
}
|
|
596
593
|
else {
|
|
597
594
|
const loadedConfig = await loadWorkspaceConfig();
|
|
@@ -636,24 +633,13 @@ async function devCommand(options) {
|
|
|
636
633
|
const runtime = config.runtime ?? "node";
|
|
637
634
|
let secretsJsonPath;
|
|
638
635
|
const appSecrets = await loadSecretsForApp(secretsRoot, config.stages.local, workspaceAppName);
|
|
639
|
-
if (workspace
|
|
636
|
+
if (workspace) {
|
|
640
637
|
const reconciled = await reconcileWorkspace(workspace, { stage: workspace.stages.local });
|
|
641
638
|
if (reconciled.changed && reconciled.plan.containers.length > 0) {
|
|
642
639
|
logger$11.log(`🐳 Services: ${reconciled.plan.containers.join(", ")}`);
|
|
643
640
|
for (const [container, address] of Object.entries(reconciled.addresses)) logger$11.log(` ${container}: ${address}`);
|
|
644
641
|
}
|
|
645
642
|
Object.assign(appSecrets, reconciled.env);
|
|
646
|
-
} else {
|
|
647
|
-
const resolvedPorts = await resolveServicePorts(secretsRoot);
|
|
648
|
-
if (Object.keys(resolvedPorts.ports).length > 0) {
|
|
649
|
-
const rewritten = rewriteUrlsWithPorts(appSecrets, resolvedPorts);
|
|
650
|
-
Object.assign(appSecrets, rewritten);
|
|
651
|
-
logger$11.log(`🔌 Applied ${Object.keys(resolvedPorts.ports).length} port mapping(s)`);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
if (workspace && workspaceAppName) {
|
|
655
|
-
const depEnv = getDependencyEnvVars(workspace, workspaceAppName);
|
|
656
|
-
Object.assign(appSecrets, depEnv);
|
|
657
643
|
}
|
|
658
644
|
if (Object.keys(appSecrets).length > 0) {
|
|
659
645
|
const secretsDir = join(secretsRoot, ".gkm");
|
|
@@ -663,7 +649,7 @@ async function devCommand(options) {
|
|
|
663
649
|
await writeFile(secretsJsonPath, JSON.stringify(appSecrets, null, 2));
|
|
664
650
|
logger$11.log(`🔐 Loaded ${Object.keys(appSecrets).length} secret(s)`);
|
|
665
651
|
}
|
|
666
|
-
const devServer = new DevServer(resolved.providers[0], options.port ?? workspaceAppPort ?? 3e3, options.portExplicit ??
|
|
652
|
+
const devServer = new DevServer(resolved.providers[0], options.port ?? workspaceAppPort ?? 3e3, options.portExplicit ?? workspaceAppPort !== void 0, enableOpenApi, telescope, studio, runtime, appRoot, secretsJsonPath, initial.selfServing !== void 0);
|
|
667
653
|
await devServer.start();
|
|
668
654
|
const hooksFile = (config.hooks?.server?.split("#"))?.[0];
|
|
669
655
|
const normalizedPatterns = [config.constructs, ...hooksFile ? [hooksFile.endsWith(".ts") ? hooksFile : `${hooksFile}.ts`] : []].flat().filter((p) => typeof p === "string").map((p) => p.startsWith("./") ? p.slice(2) : p);
|
|
@@ -722,19 +708,6 @@ async function devCommand(options) {
|
|
|
722
708
|
process.on("SIGTERM", shutdown);
|
|
723
709
|
}
|
|
724
710
|
/**
|
|
725
|
-
* Generate all dependency environment variables for all apps.
|
|
726
|
-
* Returns a flat object with all {APP_NAME}_URL variables.
|
|
727
|
-
* @internal Exported for testing
|
|
728
|
-
*/
|
|
729
|
-
function generateAllDependencyEnvVars(workspace, urlPrefix = "http://localhost") {
|
|
730
|
-
const env = {};
|
|
731
|
-
for (const appName of Object.keys(workspace.apps)) {
|
|
732
|
-
const appEnv = getDependencyEnvVars(workspace, appName, urlPrefix);
|
|
733
|
-
Object.assign(env, appEnv);
|
|
734
|
-
}
|
|
735
|
-
return env;
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
711
|
* Check for port conflicts across all apps.
|
|
739
712
|
* Returns list of conflicts if any ports are duplicated.
|
|
740
713
|
* @internal Exported for testing
|
|
@@ -959,27 +932,25 @@ async function workspaceDevCommand(workspace, options) {
|
|
|
959
932
|
logger$11.log("✅ Frontend apps validated");
|
|
960
933
|
}
|
|
961
934
|
const rawSecrets = await loadDevSecrets(workspace);
|
|
962
|
-
|
|
963
|
-
if (
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
const
|
|
975
|
-
|
|
976
|
-
secretsEnv = rewriteUrlsWithPorts(rawSecrets, resolvedPorts);
|
|
935
|
+
const reconciled = await reconcileWorkspace(workspace, { stage: workspace.stages.local });
|
|
936
|
+
if (reconciled.changed && reconciled.plan.containers.length > 0) {
|
|
937
|
+
logger$11.log(`🐳 Services: ${reconciled.plan.containers.join(", ")}`);
|
|
938
|
+
for (const [container, address] of Object.entries(reconciled.addresses)) logger$11.log(` ${container}: ${address}`);
|
|
939
|
+
}
|
|
940
|
+
const secretsEnv = {
|
|
941
|
+
...rawSecrets,
|
|
942
|
+
...reconciled.env
|
|
943
|
+
};
|
|
944
|
+
const appUrls = {};
|
|
945
|
+
for (const resource of reconciled.plan.resources) {
|
|
946
|
+
if (resource.kind !== "rest-api" && resource.kind !== "site") continue;
|
|
947
|
+
const address = reconciled.env[resource.envKey];
|
|
948
|
+
if (address) appUrls[resource.id] = address;
|
|
977
949
|
}
|
|
978
950
|
if (Object.keys(secretsEnv).length > 0) logger$11.log(` Loaded ${Object.keys(secretsEnv).length} secret(s)`);
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
logger$11.log(
|
|
982
|
-
for (const [key, value] of Object.entries(dependencyEnv)) logger$11.log(` ${key}=${value}`);
|
|
951
|
+
if (Object.keys(appUrls).length > 0) {
|
|
952
|
+
logger$11.log("🔒 App URLs:");
|
|
953
|
+
for (const [id, address] of Object.entries(appUrls)) logger$11.log(` ${id}: ${address}`);
|
|
983
954
|
}
|
|
984
955
|
let turboFilter = [];
|
|
985
956
|
if (options.app) {
|
|
@@ -1023,10 +994,20 @@ async function workspaceDevCommand(workspace, options) {
|
|
|
1023
994
|
const turboEnv = {
|
|
1024
995
|
...process.env,
|
|
1025
996
|
...secretsEnv,
|
|
1026
|
-
...dependencyEnv,
|
|
1027
997
|
NODE_ENV: "development",
|
|
1028
998
|
...configPath ? { GKM_CONFIG_PATH: configPath } : {}
|
|
1029
999
|
};
|
|
1000
|
+
const scoped = options.app ? [options.app] : options.filter ? [] : Object.keys(workspace.apps);
|
|
1001
|
+
const held = [];
|
|
1002
|
+
for (const appName of scoped) {
|
|
1003
|
+
const port = workspace.apps[appName]?.port;
|
|
1004
|
+
if (port && !await isPortAvailable(port)) held.push({
|
|
1005
|
+
app: appName,
|
|
1006
|
+
port,
|
|
1007
|
+
holder: listenerOn(port)
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
if (held.length > 0) throw new WorkspacePortsInUse(held);
|
|
1030
1011
|
logger$11.log("\n🏃 Starting turbo run dev...\n");
|
|
1031
1012
|
const turboProcess = spawn("pnpm", [
|
|
1032
1013
|
"turbo",
|
|
@@ -1204,6 +1185,19 @@ var EntryRunner = class {
|
|
|
1204
1185
|
*/
|
|
1205
1186
|
function generateServerEntryContent(options) {
|
|
1206
1187
|
const { secretsJsonPath, runtime = "node", enableOpenApi = false, appImportPath = "./app.js", selfServing = false } = options;
|
|
1188
|
+
const parentWatch = `// Exit when the gkm dev that started this server is gone.
|
|
1189
|
+
const __gkmDevPid = Number(process.env.GKM_DEV_PID);
|
|
1190
|
+
if (__gkmDevPid) {
|
|
1191
|
+
setInterval(() => {
|
|
1192
|
+
try {
|
|
1193
|
+
process.kill(__gkmDevPid, 0);
|
|
1194
|
+
} catch {
|
|
1195
|
+
process.exit(0);
|
|
1196
|
+
}
|
|
1197
|
+
}, 1000).unref();
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
`;
|
|
1207
1201
|
const credentialsInjection = secretsJsonPath ? `import { existsSync, readFileSync } from 'node:fs';
|
|
1208
1202
|
|
|
1209
1203
|
// Inject dev secrets via globalThis (must happen before app import)
|
|
@@ -1234,8 +1228,7 @@ if (existsSync(secretsPath)) {
|
|
|
1234
1228
|
* Development server entry point for a surface that serves itself
|
|
1235
1229
|
* This file is auto-generated by 'gkm dev'
|
|
1236
1230
|
*/
|
|
1237
|
-
${credentialsInjection}
|
|
1238
|
-
const port = process.argv.includes('--port')
|
|
1231
|
+
${credentialsInjection}${parentWatch}const port = process.argv.includes('--port')
|
|
1239
1232
|
? Number.parseInt(process.argv[process.argv.indexOf('--port') + 1])
|
|
1240
1233
|
: 3000;
|
|
1241
1234
|
|
|
@@ -1250,8 +1243,7 @@ console.log(\`Server started on port \${port}\`);
|
|
|
1250
1243
|
* Development server entry point
|
|
1251
1244
|
* This file is auto-generated by 'gkm dev'
|
|
1252
1245
|
*/
|
|
1253
|
-
${credentialsInjection}
|
|
1254
|
-
const port = process.argv.includes('--port')
|
|
1246
|
+
${credentialsInjection}${parentWatch}const port = process.argv.includes('--port')
|
|
1255
1247
|
? Number.parseInt(process.argv[process.argv.indexOf('--port') + 1])
|
|
1256
1248
|
: 3000;
|
|
1257
1249
|
|
|
@@ -1273,6 +1265,44 @@ start({
|
|
|
1273
1265
|
});
|
|
1274
1266
|
`;
|
|
1275
1267
|
}
|
|
1268
|
+
/** A port this app must serve on is held by something else. */
|
|
1269
|
+
var DevPortInUse = class extends Error {
|
|
1270
|
+
port;
|
|
1271
|
+
holder;
|
|
1272
|
+
constructor(port, holder) {
|
|
1273
|
+
super(`Port ${port} is already in use${holder ? ` by ${holder}` : ""}. It is the port this app is provisioned on — the one every other app and its CORS origins point at — so dev will not move off it. Stop what is holding it (often a dev server a previous run left behind), or pass -p/--port to run this app somewhere else.`);
|
|
1274
|
+
this.port = port;
|
|
1275
|
+
this.holder = holder;
|
|
1276
|
+
this.name = "DevPortInUse";
|
|
1277
|
+
}
|
|
1278
|
+
};
|
|
1279
|
+
/** Apps whose provisioned ports are held before the workspace starts. */
|
|
1280
|
+
var WorkspacePortsInUse = class extends Error {
|
|
1281
|
+
held;
|
|
1282
|
+
constructor(held) {
|
|
1283
|
+
super(`Ports this workspace's apps are provisioned on are already in use:\n${held.map(({ app, port, holder }) => ` ${app}: ${port}${holder ? ` — held by ${holder}` : ""}`).join("\n")}\nStop what is holding them (often dev servers a previous run left behind) and start again. Nothing was started.`);
|
|
1284
|
+
this.held = held;
|
|
1285
|
+
this.name = "WorkspacePortsInUse";
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
/** What is listening on a port, as `command (pid N)`, if `lsof` can tell. */
|
|
1289
|
+
function listenerOn(port) {
|
|
1290
|
+
try {
|
|
1291
|
+
const out = execSync(`lsof -nP -iTCP:${port} -sTCP:LISTEN -Fpc`, {
|
|
1292
|
+
encoding: "utf8",
|
|
1293
|
+
stdio: [
|
|
1294
|
+
"ignore",
|
|
1295
|
+
"pipe",
|
|
1296
|
+
"ignore"
|
|
1297
|
+
]
|
|
1298
|
+
});
|
|
1299
|
+
const pid = out.match(/^p(\d+)/m)?.[1];
|
|
1300
|
+
const command = out.match(/^c(.+)$/m)?.[1];
|
|
1301
|
+
return pid ? `${command ?? "a process"} (pid ${pid})` : void 0;
|
|
1302
|
+
} catch {
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1276
1306
|
var DevServer = class {
|
|
1277
1307
|
provider;
|
|
1278
1308
|
requestedPort;
|
|
@@ -1305,7 +1335,7 @@ var DevServer = class {
|
|
|
1305
1335
|
this.startTime = Date.now();
|
|
1306
1336
|
if (this.isRunning) await this.stop();
|
|
1307
1337
|
if (this.portExplicit) {
|
|
1308
|
-
if (!await isPortAvailable(this.requestedPort)) throw new
|
|
1338
|
+
if (!await isPortAvailable(this.requestedPort)) throw new DevPortInUse(this.requestedPort, listenerOn(this.requestedPort));
|
|
1309
1339
|
this.actualPort = this.requestedPort;
|
|
1310
1340
|
} else {
|
|
1311
1341
|
this.actualPort = await findAvailablePort(this.requestedPort);
|
|
@@ -1323,7 +1353,8 @@ var DevServer = class {
|
|
|
1323
1353
|
stdio: "inherit",
|
|
1324
1354
|
env: {
|
|
1325
1355
|
...process.env,
|
|
1326
|
-
NODE_ENV: "development"
|
|
1356
|
+
NODE_ENV: "development",
|
|
1357
|
+
GKM_DEV_PID: String(process.pid)
|
|
1327
1358
|
},
|
|
1328
1359
|
detached: true
|
|
1329
1360
|
});
|
|
@@ -3496,10 +3527,6 @@ var UnprovisionableBucket = class extends Error {
|
|
|
3496
3527
|
*/
|
|
3497
3528
|
/**
|
|
3498
3529
|
* Provision everything the workspace declares, and return what it resolved.
|
|
3499
|
-
*
|
|
3500
|
-
* Nothing happens for a project that has not adopted the model: `usesConstructs`
|
|
3501
|
-
* is the same hard switch reconcile reads, so an existing deploy is untouched
|
|
3502
|
-
* until it declares something.
|
|
3503
3530
|
*/
|
|
3504
3531
|
async function provisionDeclared(options) {
|
|
3505
3532
|
const { workspace } = options;
|
|
@@ -3509,7 +3536,6 @@ async function provisionDeclared(options) {
|
|
|
3509
3536
|
provisioned: {},
|
|
3510
3537
|
clusters: {}
|
|
3511
3538
|
};
|
|
3512
|
-
if (!usesConstructs(workspace)) return empty;
|
|
3513
3539
|
const manifest = options.manifest ?? await discover({
|
|
3514
3540
|
patterns: constructGlobs(workspace),
|
|
3515
3541
|
cwd: workspace.root
|
|
@@ -8515,26 +8541,26 @@ function loadPackageJson() {
|
|
|
8515
8541
|
* Run: pnpm --filter @geekmidas/cli sync-versions
|
|
8516
8542
|
*/
|
|
8517
8543
|
const GEEKMIDAS_VERSIONS = {
|
|
8518
|
-
"@geekmidas/audit": "~10.0.0-alpha.
|
|
8519
|
-
"@geekmidas/auth": "~10.0.0-alpha.
|
|
8520
|
-
"@geekmidas/cache": "~10.0.0-alpha.
|
|
8521
|
-
"@geekmidas/client": "~10.0.0-alpha.
|
|
8522
|
-
"@geekmidas/cloud": "~10.0.0-alpha.
|
|
8523
|
-
"@geekmidas/constructs": "~10.0.0-alpha.
|
|
8524
|
-
"@geekmidas/db": "~10.0.0-alpha.
|
|
8525
|
-
"@geekmidas/emailkit": "~10.0.0-alpha.
|
|
8526
|
-
"@geekmidas/envkit": "~10.0.0-alpha.
|
|
8527
|
-
"@geekmidas/errors": "~10.0.0-alpha.
|
|
8528
|
-
"@geekmidas/events": "~10.0.0-alpha.
|
|
8529
|
-
"@geekmidas/logger": "~10.0.0-alpha.
|
|
8530
|
-
"@geekmidas/manifest": "~10.0.0-alpha.
|
|
8531
|
-
"@geekmidas/rate-limit": "~10.0.0-alpha.
|
|
8532
|
-
"@geekmidas/schema": "~10.0.0-alpha.
|
|
8533
|
-
"@geekmidas/services": "~10.0.0-alpha.
|
|
8534
|
-
"@geekmidas/storage": "~10.0.0-alpha.
|
|
8535
|
-
"@geekmidas/studio": "~10.0.0-alpha.
|
|
8536
|
-
"@geekmidas/telescope": "~10.0.0-alpha.
|
|
8537
|
-
"@geekmidas/testkit": "~10.0.0-alpha.
|
|
8544
|
+
"@geekmidas/audit": "~10.0.0-alpha.27",
|
|
8545
|
+
"@geekmidas/auth": "~10.0.0-alpha.27",
|
|
8546
|
+
"@geekmidas/cache": "~10.0.0-alpha.27",
|
|
8547
|
+
"@geekmidas/client": "~10.0.0-alpha.27",
|
|
8548
|
+
"@geekmidas/cloud": "~10.0.0-alpha.27",
|
|
8549
|
+
"@geekmidas/constructs": "~10.0.0-alpha.27",
|
|
8550
|
+
"@geekmidas/db": "~10.0.0-alpha.27",
|
|
8551
|
+
"@geekmidas/emailkit": "~10.0.0-alpha.27",
|
|
8552
|
+
"@geekmidas/envkit": "~10.0.0-alpha.27",
|
|
8553
|
+
"@geekmidas/errors": "~10.0.0-alpha.27",
|
|
8554
|
+
"@geekmidas/events": "~10.0.0-alpha.27",
|
|
8555
|
+
"@geekmidas/logger": "~10.0.0-alpha.27",
|
|
8556
|
+
"@geekmidas/manifest": "~10.0.0-alpha.27",
|
|
8557
|
+
"@geekmidas/rate-limit": "~10.0.0-alpha.27",
|
|
8558
|
+
"@geekmidas/schema": "~10.0.0-alpha.27",
|
|
8559
|
+
"@geekmidas/services": "~10.0.0-alpha.27",
|
|
8560
|
+
"@geekmidas/storage": "~10.0.0-alpha.27",
|
|
8561
|
+
"@geekmidas/studio": "~10.0.0-alpha.27",
|
|
8562
|
+
"@geekmidas/telescope": "~10.0.0-alpha.27",
|
|
8563
|
+
"@geekmidas/testkit": "~10.0.0-alpha.27",
|
|
8538
8564
|
"@geekmidas/cli": `~${loadPackageJson().version}`
|
|
8539
8565
|
};
|
|
8540
8566
|
//#endregion
|
|
@@ -15480,7 +15506,6 @@ async function testCommand(options = {}) {
|
|
|
15480
15506
|
stage,
|
|
15481
15507
|
startDocker: !options.prepare,
|
|
15482
15508
|
secretsFileName: "test-secrets.json",
|
|
15483
|
-
resolveDockerPorts: "full",
|
|
15484
15509
|
reconcileStage: "test"
|
|
15485
15510
|
});
|
|
15486
15511
|
let finalCredentials = { ...result.credentials };
|
|
@@ -15494,14 +15519,13 @@ async function testCommand(options = {}) {
|
|
|
15494
15519
|
console.log(` 🔍 Sniffed ${sniffed.requiredEnvVars.length} required env var(s)` + (result.declaredKeys.length > 0 ? `, kept ${result.declaredKeys.length} declared` : ""));
|
|
15495
15520
|
}
|
|
15496
15521
|
}
|
|
15497
|
-
finalCredentials = rewriteDatabaseUrlForTests(finalCredentials);
|
|
15498
15522
|
console.log("");
|
|
15499
15523
|
await writeFile(result.secretsJsonPath, JSON.stringify(finalCredentials, null, 2));
|
|
15500
15524
|
const gkmDir = join(cwd, ".gkm");
|
|
15501
15525
|
const preloadPath = join(gkmDir, "test-credentials-preload.ts");
|
|
15502
15526
|
await createCredentialsPreload(preloadPath, result.secretsJsonPath);
|
|
15503
15527
|
const workspace = await loadWorkspaceConfig(cwd).then((loaded) => loaded.workspace).catch(() => void 0);
|
|
15504
|
-
const manifestPath = workspace
|
|
15528
|
+
const manifestPath = workspace ? await writeTestHarness({
|
|
15505
15529
|
root: workspace.root,
|
|
15506
15530
|
targets: [workspace.root, ...Object.values(workspace.apps).map((app) => isAbsolute(app.path) ? app.path : join(workspace.root, app.path))],
|
|
15507
15531
|
patterns: constructGlobs(workspace),
|
|
@@ -15545,29 +15569,6 @@ async function testCommand(options = {}) {
|
|
|
15545
15569
|
});
|
|
15546
15570
|
});
|
|
15547
15571
|
}
|
|
15548
|
-
const TEST_DB_SUFFIX = "_test";
|
|
15549
|
-
/**
|
|
15550
|
-
* Rewrite DATABASE_URL to point to a separate test database.
|
|
15551
|
-
* Appends `_test` to the database name (e.g., `app` -> `app_test`).
|
|
15552
|
-
* @internal Exported for testing
|
|
15553
|
-
*/
|
|
15554
|
-
function rewriteDatabaseUrlForTests(env) {
|
|
15555
|
-
const result = { ...env };
|
|
15556
|
-
for (const key of Object.keys(result)) {
|
|
15557
|
-
if (!key.includes("DATABASE_URL")) continue;
|
|
15558
|
-
const value = result[key];
|
|
15559
|
-
try {
|
|
15560
|
-
const url = new URL(value);
|
|
15561
|
-
const dbName = url.pathname.slice(1);
|
|
15562
|
-
if (dbName && !dbName.endsWith(TEST_DB_SUFFIX)) {
|
|
15563
|
-
url.pathname = `/${dbName}${TEST_DB_SUFFIX}`;
|
|
15564
|
-
result[key] = url.toString();
|
|
15565
|
-
console.log(` 🧪 ${key}: using test database "${dbName}${TEST_DB_SUFFIX}"`);
|
|
15566
|
-
}
|
|
15567
|
-
} catch {}
|
|
15568
|
-
}
|
|
15569
|
-
return result;
|
|
15570
|
-
}
|
|
15571
15572
|
/** `gkm test` outside a project that declares stages, with none named. */
|
|
15572
15573
|
var NoStageToTest = class extends Error {
|
|
15573
15574
|
constructor() {
|
|
@@ -16108,7 +16109,7 @@ program.command("secrets:push").description("Send a deployed stage's secrets to
|
|
|
16108
16109
|
const globalOptions = program.opts();
|
|
16109
16110
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
16110
16111
|
const { loadWorkspaceConfig } = await import("./config.mjs");
|
|
16111
|
-
const { pushStageSecrets } = await import("./transfer-
|
|
16112
|
+
const { pushStageSecrets } = await import("./transfer-BV00TxZv.mjs").then((n) => n.i);
|
|
16112
16113
|
const { workspace } = await loadWorkspaceConfig();
|
|
16113
16114
|
const { addedKeys } = await pushStageSecrets(workspace, options.stage, { profile: options.profile });
|
|
16114
16115
|
for (const key of addedKeys) console.log(` + ${key} (reconciled)`);
|
|
@@ -16123,7 +16124,7 @@ program.command("secrets:pull").description("Bring a deployed stage's secrets fr
|
|
|
16123
16124
|
const globalOptions = program.opts();
|
|
16124
16125
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
16125
16126
|
const { loadWorkspaceConfig } = await import("./config.mjs");
|
|
16126
|
-
const { pullStageSecrets } = await import("./transfer-
|
|
16127
|
+
const { pullStageSecrets } = await import("./transfer-BV00TxZv.mjs").then((n) => n.i);
|
|
16127
16128
|
const { workspace } = await loadWorkspaceConfig();
|
|
16128
16129
|
const { addedKeys } = await pullStageSecrets(workspace, options.stage, { profile: options.profile });
|
|
16129
16130
|
for (const key of addedKeys) console.log(` + ${key} (reconciled)`);
|
|
@@ -16138,7 +16139,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
16138
16139
|
const globalOptions = program.opts();
|
|
16139
16140
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
16140
16141
|
const { loadWorkspaceConfig } = await import("./config.mjs");
|
|
16141
|
-
const { reconcileMissingSecrets } = await import("./reconcile-
|
|
16142
|
+
const { reconcileMissingSecrets } = await import("./reconcile-DhbCvh4K.mjs").then((n) => n.n);
|
|
16142
16143
|
const { readStageSecrets, writeStageSecrets } = await import("./storage-TP0x118M.mjs").then((n) => n.a);
|
|
16143
16144
|
const { workspace } = await loadWorkspaceConfig();
|
|
16144
16145
|
const stage = options.stage ?? workspace.stages.local;
|
|
@@ -16147,7 +16148,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
16147
16148
|
console.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
|
|
16148
16149
|
process.exit(1);
|
|
16149
16150
|
}
|
|
16150
|
-
const { derivedContainers } = await import("./
|
|
16151
|
+
const { derivedContainers } = await import("./workspace-CUmR_k4J.mjs").then((n) => n.a);
|
|
16151
16152
|
const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, stage));
|
|
16152
16153
|
if (!result) {
|
|
16153
16154
|
console.log(`\n✓ Secrets for stage "${stage}" are up-to-date`);
|
|
@@ -16206,7 +16207,7 @@ program.command("deploy:github").description("Let GitHub Actions deploy a stage:
|
|
|
16206
16207
|
try {
|
|
16207
16208
|
const globalOptions = program.opts();
|
|
16208
16209
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
16209
|
-
const { deployGithubCommand } = await import("./github-
|
|
16210
|
+
const { deployGithubCommand } = await import("./github-Ba5kXEJo.mjs");
|
|
16210
16211
|
await deployGithubCommand(options);
|
|
16211
16212
|
} catch (error) {
|
|
16212
16213
|
console.error(formatError(error));
|