@geekmidas/cli 1.10.4 → 1.10.6
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/CHANGELOG.md +12 -0
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/{fullstack-secrets-DqxYGrgW.cjs → fullstack-secrets-BctGaE4E.cjs} +7 -2
- package/dist/fullstack-secrets-BctGaE4E.cjs.map +1 -0
- package/dist/{fullstack-secrets-odm79Uo1.mjs → fullstack-secrets-ca0Kyrvt.mjs} +7 -2
- package/dist/fullstack-secrets-ca0Kyrvt.mjs.map +1 -0
- package/dist/{index-3n-giNaw.d.mts → index-9tjTQjFt.d.mts} +3 -3
- package/dist/{index-3n-giNaw.d.mts.map → index-9tjTQjFt.d.mts.map} +1 -1
- package/dist/{index-CiEOtKEX.d.cts → index-VOKKO-lm.d.cts} +3 -3
- package/dist/{index-CiEOtKEX.d.cts.map → index-VOKKO-lm.d.cts.map} +1 -1
- package/dist/index.cjs +37 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +37 -56
- package/dist/index.mjs.map +1 -1
- package/dist/{reconcile-WzC1oAUV.mjs → reconcile-C5OyCA7V.mjs} +2 -2
- package/dist/{reconcile-WzC1oAUV.mjs.map → reconcile-C5OyCA7V.mjs.map} +1 -1
- package/dist/{reconcile-CCtrj-zt.cjs → reconcile-TEBsryVn.cjs} +2 -2
- package/dist/{reconcile-CCtrj-zt.cjs.map → reconcile-TEBsryVn.cjs.map} +1 -1
- package/dist/workspace/index.d.cts +1 -1
- package/dist/workspace/index.d.mts +1 -1
- package/dist/workspace-4SP3Gx4Y.cjs.map +1 -1
- package/dist/workspace-D4z4A4cq.mjs.map +1 -1
- package/package.json +4 -4
- package/src/dev/__tests__/index.spec.ts +35 -9
- package/src/dev/index.ts +18 -1
- package/src/docker/__tests__/compose.spec.ts +13 -11
- package/src/docker/compose.ts +10 -10
- package/src/init/__tests__/init.spec.ts +1 -1
- package/src/init/generators/docker.ts +7 -7
- package/src/init/index.ts +3 -1
- package/src/secrets/generator.ts +11 -0
- package/src/secrets/index.ts +12 -6
- package/src/setup/index.ts +3 -1
- package/src/test/__tests__/index.spec.ts +62 -34
- package/src/test/index.ts +0 -41
- package/src/workspace/types.ts +2 -2
- package/dist/fullstack-secrets-DqxYGrgW.cjs.map +0 -1
- package/dist/fullstack-secrets-odm79Uo1.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { getKeyPath, maskPassword, readStageSecrets, secretsExist, setCustomSecr
|
|
|
8
8
|
import { DokployApi } from "./dokploy-api-2ldYoN3i.mjs";
|
|
9
9
|
import { encryptSecrets } from "./encryption-BOH5M-f-.mjs";
|
|
10
10
|
import { CachedStateProvider } from "./CachedStateProvider-BDq5WqSy.mjs";
|
|
11
|
-
import { createStageSecrets, generateDbPassword, generateDbUrl, generateFullstackCustomSecrets, rotateServicePassword, writeDockerEnvFromSecrets } from "./fullstack-secrets-
|
|
11
|
+
import { createStageSecrets, generateDbPassword, generateDbUrl, generateFullstackCustomSecrets, rotateServicePassword, writeDockerEnvFromSecrets } from "./fullstack-secrets-ca0Kyrvt.mjs";
|
|
12
12
|
import { generateReactQueryCommand } from "./openapi-react-query-C4UdILaI.mjs";
|
|
13
13
|
import { isSSMConfigured, pullSecrets, pushSecrets } from "./sync-CbeKrnQV.mjs";
|
|
14
14
|
import { createRequire } from "node:module";
|
|
@@ -35,7 +35,7 @@ import prompts from "prompts";
|
|
|
35
35
|
|
|
36
36
|
//#region package.json
|
|
37
37
|
var name = "@geekmidas/cli";
|
|
38
|
-
var version = "1.10.
|
|
38
|
+
var version = "1.10.5";
|
|
39
39
|
var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
|
|
40
40
|
var private$1 = false;
|
|
41
41
|
var type = "module";
|
|
@@ -815,13 +815,19 @@ function rewriteUrlsWithPorts(secrets, resolvedPorts) {
|
|
|
815
815
|
const { ports, mappings } = resolvedPorts;
|
|
816
816
|
const result = { ...secrets };
|
|
817
817
|
const portReplacements = [];
|
|
818
|
+
const serviceNames = /* @__PURE__ */ new Set();
|
|
818
819
|
for (const mapping of mappings) {
|
|
820
|
+
serviceNames.add(mapping.service);
|
|
819
821
|
const resolved = ports[mapping.envVar];
|
|
820
822
|
if (resolved !== void 0) portReplacements.push({
|
|
821
823
|
defaultPort: mapping.defaultPort,
|
|
822
824
|
resolvedPort: resolved
|
|
823
825
|
});
|
|
824
826
|
}
|
|
827
|
+
for (const [key, value] of Object.entries(result)) {
|
|
828
|
+
if (!key.endsWith("_HOST")) continue;
|
|
829
|
+
if (serviceNames.has(value)) result[key] = "localhost";
|
|
830
|
+
}
|
|
825
831
|
for (const [key, value] of Object.entries(result)) {
|
|
826
832
|
if (!key.endsWith("_PORT")) continue;
|
|
827
833
|
for (const { defaultPort, resolvedPort } of portReplacements) if (value === String(defaultPort)) result[key] = String(resolvedPort);
|
|
@@ -829,6 +835,7 @@ function rewriteUrlsWithPorts(secrets, resolvedPorts) {
|
|
|
829
835
|
for (const [key, value] of Object.entries(result)) {
|
|
830
836
|
if (!key.endsWith("_URL") && key !== "DATABASE_URL") continue;
|
|
831
837
|
let rewritten = value;
|
|
838
|
+
for (const name$1 of serviceNames) rewritten = rewritten.replace(new RegExp(`@${name$1}:`, "g"), "@localhost:");
|
|
832
839
|
for (const { defaultPort, resolvedPort } of portReplacements) rewritten = replacePortInUrl(rewritten, defaultPort, resolvedPort);
|
|
833
840
|
result[key] = rewritten;
|
|
834
841
|
}
|
|
@@ -2834,7 +2841,7 @@ const DEFAULT_SERVICE_IMAGES = {
|
|
|
2834
2841
|
};
|
|
2835
2842
|
/** Default Docker image versions for services */
|
|
2836
2843
|
const DEFAULT_SERVICE_VERSIONS = {
|
|
2837
|
-
postgres: "
|
|
2844
|
+
postgres: "18-alpine",
|
|
2838
2845
|
redis: "7-alpine",
|
|
2839
2846
|
rabbitmq: "3-management-alpine"
|
|
2840
2847
|
};
|
|
@@ -2882,7 +2889,7 @@ services:
|
|
|
2882
2889
|
environment:
|
|
2883
2890
|
- NODE_ENV=production
|
|
2884
2891
|
`;
|
|
2885
|
-
if (serviceMap.has("postgres")) yaml += ` - DATABASE_URL=\${DATABASE_URL:-postgresql
|
|
2892
|
+
if (serviceMap.has("postgres")) yaml += ` - DATABASE_URL=\${DATABASE_URL:-postgresql://\${POSTGRES_USER:-postgres}:\${POSTGRES_PASSWORD:-postgres}@postgres:5432/\${POSTGRES_DB:-app}}
|
|
2886
2893
|
`;
|
|
2887
2894
|
if (serviceMap.has("redis")) yaml += ` - REDIS_URL=\${REDIS_URL:-redis://redis:6379}
|
|
2888
2895
|
`;
|
|
@@ -2915,9 +2922,9 @@ services:
|
|
|
2915
2922
|
POSTGRES_PASSWORD: \${POSTGRES_PASSWORD:-postgres}
|
|
2916
2923
|
POSTGRES_DB: \${POSTGRES_DB:-app}
|
|
2917
2924
|
volumes:
|
|
2918
|
-
-
|
|
2925
|
+
- dbdata:/var/lib/postgresql/18/data
|
|
2919
2926
|
healthcheck:
|
|
2920
|
-
test: ["CMD-SHELL", "pg_isready -U
|
|
2927
|
+
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
|
|
2921
2928
|
interval: 5s
|
|
2922
2929
|
timeout: 5s
|
|
2923
2930
|
retries: 5
|
|
@@ -2964,7 +2971,7 @@ services:
|
|
|
2964
2971
|
yaml += `
|
|
2965
2972
|
volumes:
|
|
2966
2973
|
`;
|
|
2967
|
-
if (serviceMap.has("postgres")) yaml += `
|
|
2974
|
+
if (serviceMap.has("postgres")) yaml += ` dbdata:
|
|
2968
2975
|
`;
|
|
2969
2976
|
if (serviceMap.has("redis")) yaml += ` redis_data:
|
|
2970
2977
|
`;
|
|
@@ -3044,9 +3051,9 @@ services:
|
|
|
3044
3051
|
POSTGRES_PASSWORD: \${POSTGRES_PASSWORD:-postgres}
|
|
3045
3052
|
POSTGRES_DB: \${POSTGRES_DB:-app}
|
|
3046
3053
|
volumes:
|
|
3047
|
-
-
|
|
3054
|
+
- dbdata:/var/lib/postgresql/18/data
|
|
3048
3055
|
healthcheck:
|
|
3049
|
-
test: ["CMD-SHELL", "pg_isready -U
|
|
3056
|
+
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
|
|
3050
3057
|
interval: 5s
|
|
3051
3058
|
timeout: 5s
|
|
3052
3059
|
retries: 5
|
|
@@ -3082,7 +3089,7 @@ services:
|
|
|
3082
3089
|
yaml += `
|
|
3083
3090
|
volumes:
|
|
3084
3091
|
`;
|
|
3085
|
-
if (hasPostgres) yaml += `
|
|
3092
|
+
if (hasPostgres) yaml += ` dbdata:
|
|
3086
3093
|
`;
|
|
3087
3094
|
if (hasRedis) yaml += ` redis_data:
|
|
3088
3095
|
`;
|
|
@@ -3098,7 +3105,7 @@ networks:
|
|
|
3098
3105
|
*/
|
|
3099
3106
|
function getInfraServiceImage(serviceName, config$1) {
|
|
3100
3107
|
const defaults = {
|
|
3101
|
-
postgres: "postgres:
|
|
3108
|
+
postgres: "postgres:18-alpine",
|
|
3102
3109
|
redis: "redis:7-alpine"
|
|
3103
3110
|
};
|
|
3104
3111
|
if (!config$1 || config$1 === true) return defaults[serviceName];
|
|
@@ -3139,7 +3146,7 @@ function generateAppService(appName, app, allApps, options) {
|
|
|
3139
3146
|
`;
|
|
3140
3147
|
}
|
|
3141
3148
|
if (app.type === "backend") {
|
|
3142
|
-
if (hasPostgres) yaml += ` - DATABASE_URL=\${DATABASE_URL:-postgresql
|
|
3149
|
+
if (hasPostgres) yaml += ` - DATABASE_URL=\${DATABASE_URL:-postgresql://\${POSTGRES_USER:-postgres}:\${POSTGRES_PASSWORD:-postgres}@postgres:5432/\${POSTGRES_DB:-app}}
|
|
3143
3150
|
`;
|
|
3144
3151
|
if (hasRedis) yaml += ` - REDIS_URL=\${REDIS_URL:-redis://redis:6379}
|
|
3145
3152
|
`;
|
|
@@ -6947,23 +6954,23 @@ function generateDockerFiles(options, template, dbApps) {
|
|
|
6947
6954
|
env_file:
|
|
6948
6955
|
- ./docker/.env` : "";
|
|
6949
6956
|
services.push(` postgres:
|
|
6950
|
-
image: postgres:
|
|
6957
|
+
image: postgres:18-alpine
|
|
6951
6958
|
container_name: ${options.name}-postgres
|
|
6952
6959
|
restart: unless-stopped${envFile}
|
|
6953
6960
|
environment:
|
|
6954
|
-
POSTGRES_USER: postgres
|
|
6955
|
-
POSTGRES_PASSWORD: postgres
|
|
6956
|
-
POSTGRES_DB:
|
|
6961
|
+
POSTGRES_USER: \${POSTGRES_USER:-postgres}
|
|
6962
|
+
POSTGRES_PASSWORD: \${POSTGRES_PASSWORD:-postgres}
|
|
6963
|
+
POSTGRES_DB: \${POSTGRES_DB:-${options.name.replace(/-/g, "_")}_dev}
|
|
6957
6964
|
ports:
|
|
6958
6965
|
- '\${POSTGRES_HOST_PORT:-5432}:5432'
|
|
6959
6966
|
volumes:
|
|
6960
|
-
-
|
|
6967
|
+
- dbdata:/var/lib/postgresql/18/data${initVolume}
|
|
6961
6968
|
healthcheck:
|
|
6962
|
-
test: ['CMD-SHELL', 'pg_isready -U
|
|
6969
|
+
test: ['CMD-SHELL', 'pg_isready -U $$POSTGRES_USER']
|
|
6963
6970
|
interval: 5s
|
|
6964
6971
|
timeout: 5s
|
|
6965
6972
|
retries: 5`);
|
|
6966
|
-
volumes.push("
|
|
6973
|
+
volumes.push(" dbdata:");
|
|
6967
6974
|
if (isFullstack && dbApps?.length) {
|
|
6968
6975
|
files.push({
|
|
6969
6976
|
path: "docker/postgres/init.sh",
|
|
@@ -10861,7 +10868,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
10861
10868
|
const secretServices = [];
|
|
10862
10869
|
if (services.db) secretServices.push("postgres");
|
|
10863
10870
|
if (services.cache) secretServices.push("redis");
|
|
10864
|
-
const devSecrets = createStageSecrets("development", secretServices);
|
|
10871
|
+
const devSecrets = createStageSecrets("development", secretServices, { projectName: name$1 });
|
|
10865
10872
|
const customSecrets = {
|
|
10866
10873
|
NODE_ENV: "development",
|
|
10867
10874
|
PORT: "3000",
|
|
@@ -10998,16 +11005,19 @@ async function secretsInitCommand(options) {
|
|
|
10998
11005
|
const config$1 = await loadConfig();
|
|
10999
11006
|
const services = getServicesFromConfig(config$1.docker?.compose?.services);
|
|
11000
11007
|
if (services.length === 0) logger$2.warn("No services configured in docker.compose.services. Creating secrets with empty services.");
|
|
11001
|
-
|
|
11008
|
+
let projectName;
|
|
11009
|
+
let workspaceSecrets;
|
|
11002
11010
|
try {
|
|
11003
11011
|
const loaded = await loadWorkspaceConfig();
|
|
11012
|
+
projectName = loaded.workspace.name;
|
|
11004
11013
|
const isMultiApp = Object.keys(loaded.workspace.apps).length > 1;
|
|
11005
11014
|
if (isMultiApp) {
|
|
11006
|
-
|
|
11007
|
-
secrets.custom = customSecrets;
|
|
11015
|
+
workspaceSecrets = generateFullstackCustomSecrets(loaded.workspace);
|
|
11008
11016
|
logger$2.log(" Detected workspace mode — generating per-app secrets");
|
|
11009
11017
|
}
|
|
11010
11018
|
} catch {}
|
|
11019
|
+
const secrets = createStageSecrets(stage, services, { projectName });
|
|
11020
|
+
if (workspaceSecrets) secrets.custom = workspaceSecrets;
|
|
11011
11021
|
await writeStageSecrets(secrets);
|
|
11012
11022
|
logger$2.log(`\n✓ Secrets initialized for stage "${stage}"`);
|
|
11013
11023
|
logger$2.log(` Location: .gkm/secrets/${stage}.json`);
|
|
@@ -11285,7 +11295,7 @@ async function generateFreshSecrets(stage, workspace, options) {
|
|
|
11285
11295
|
const serviceNames = [];
|
|
11286
11296
|
if (workspace.services.db) serviceNames.push("postgres");
|
|
11287
11297
|
if (workspace.services.cache) serviceNames.push("redis");
|
|
11288
|
-
const secrets = createStageSecrets(stage, serviceNames);
|
|
11298
|
+
const secrets = createStageSecrets(stage, serviceNames, { projectName: workspace.name });
|
|
11289
11299
|
const isMultiApp = Object.keys(workspace.apps).length > 1;
|
|
11290
11300
|
if (isMultiApp) {
|
|
11291
11301
|
const customSecrets = generateFullstackCustomSecrets(workspace);
|
|
@@ -11368,7 +11378,6 @@ async function testCommand(options = {}) {
|
|
|
11368
11378
|
}
|
|
11369
11379
|
}
|
|
11370
11380
|
secretsEnv = rewriteDatabaseUrlForTests(secretsEnv);
|
|
11371
|
-
await ensureTestDatabase(secretsEnv);
|
|
11372
11381
|
let dependencyEnv = {};
|
|
11373
11382
|
try {
|
|
11374
11383
|
const appInfo = await loadWorkspaceAppInfo(cwd);
|
|
@@ -11456,34 +11465,6 @@ function rewriteDatabaseUrlForTests(env) {
|
|
|
11456
11465
|
}
|
|
11457
11466
|
return result;
|
|
11458
11467
|
}
|
|
11459
|
-
/**
|
|
11460
|
-
* Ensure the test database exists by connecting to the default database
|
|
11461
|
-
* and running CREATE DATABASE IF NOT EXISTS.
|
|
11462
|
-
* @internal Exported for testing
|
|
11463
|
-
*/
|
|
11464
|
-
async function ensureTestDatabase(env) {
|
|
11465
|
-
const databaseUrl = env.DATABASE_URL;
|
|
11466
|
-
if (!databaseUrl) return;
|
|
11467
|
-
try {
|
|
11468
|
-
const url = new URL(databaseUrl);
|
|
11469
|
-
const testDbName = url.pathname.slice(1);
|
|
11470
|
-
if (!testDbName) return;
|
|
11471
|
-
url.pathname = "/postgres";
|
|
11472
|
-
const { default: pg } = await import("pg");
|
|
11473
|
-
const client = new pg.Client({ connectionString: url.toString() });
|
|
11474
|
-
await client.connect();
|
|
11475
|
-
try {
|
|
11476
|
-
await client.query(`CREATE DATABASE "${testDbName}"`);
|
|
11477
|
-
console.log(` 📦 Created test database "${testDbName}"`);
|
|
11478
|
-
} catch (err) {
|
|
11479
|
-
if (err.code !== "42P04") throw err;
|
|
11480
|
-
} finally {
|
|
11481
|
-
await client.end();
|
|
11482
|
-
}
|
|
11483
|
-
} catch (err) {
|
|
11484
|
-
console.log(` ⚠️ Could not ensure test database: ${err.message}`);
|
|
11485
|
-
}
|
|
11486
|
-
}
|
|
11487
11468
|
|
|
11488
11469
|
//#endregion
|
|
11489
11470
|
//#region src/upgrade/index.ts
|
|
@@ -11851,7 +11832,7 @@ program.command("secrets:push").description("Push secrets to remote provider (SS
|
|
|
11851
11832
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11852
11833
|
const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
|
|
11853
11834
|
const { pushSecrets: pushSecrets$1 } = await import("./sync-6FoT41G3.mjs");
|
|
11854
|
-
const { reconcileMissingSecrets } = await import("./reconcile-
|
|
11835
|
+
const { reconcileMissingSecrets } = await import("./reconcile-C5OyCA7V.mjs");
|
|
11855
11836
|
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-Dx_jZbq6.mjs");
|
|
11856
11837
|
const { workspace } = await loadWorkspaceConfig$1();
|
|
11857
11838
|
const secrets = await readStageSecrets$1(options.stage, workspace.root);
|
|
@@ -11877,7 +11858,7 @@ program.command("secrets:pull").description("Pull secrets from remote provider (
|
|
|
11877
11858
|
const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
|
|
11878
11859
|
const { pullSecrets: pullSecrets$1 } = await import("./sync-6FoT41G3.mjs");
|
|
11879
11860
|
const { writeStageSecrets: writeStageSecrets$1 } = await import("./storage-Dx_jZbq6.mjs");
|
|
11880
|
-
const { reconcileMissingSecrets } = await import("./reconcile-
|
|
11861
|
+
const { reconcileMissingSecrets } = await import("./reconcile-C5OyCA7V.mjs");
|
|
11881
11862
|
const { workspace } = await loadWorkspaceConfig$1();
|
|
11882
11863
|
let secrets = await pullSecrets$1(options.stage, workspace);
|
|
11883
11864
|
if (!secrets) {
|
|
@@ -11902,7 +11883,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
11902
11883
|
const globalOptions = program.opts();
|
|
11903
11884
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11904
11885
|
const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
|
|
11905
|
-
const { reconcileMissingSecrets } = await import("./reconcile-
|
|
11886
|
+
const { reconcileMissingSecrets } = await import("./reconcile-C5OyCA7V.mjs");
|
|
11906
11887
|
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-Dx_jZbq6.mjs");
|
|
11907
11888
|
const { workspace } = await loadWorkspaceConfig$1();
|
|
11908
11889
|
const secrets = await readStageSecrets$1(options.stage, workspace.root);
|