@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.
Files changed (39) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/config.d.cts +1 -1
  3. package/dist/config.d.mts +1 -1
  4. package/dist/{fullstack-secrets-DqxYGrgW.cjs → fullstack-secrets-BctGaE4E.cjs} +7 -2
  5. package/dist/fullstack-secrets-BctGaE4E.cjs.map +1 -0
  6. package/dist/{fullstack-secrets-odm79Uo1.mjs → fullstack-secrets-ca0Kyrvt.mjs} +7 -2
  7. package/dist/fullstack-secrets-ca0Kyrvt.mjs.map +1 -0
  8. package/dist/{index-3n-giNaw.d.mts → index-9tjTQjFt.d.mts} +3 -3
  9. package/dist/{index-3n-giNaw.d.mts.map → index-9tjTQjFt.d.mts.map} +1 -1
  10. package/dist/{index-CiEOtKEX.d.cts → index-VOKKO-lm.d.cts} +3 -3
  11. package/dist/{index-CiEOtKEX.d.cts.map → index-VOKKO-lm.d.cts.map} +1 -1
  12. package/dist/index.cjs +37 -56
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.mjs +37 -56
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/{reconcile-WzC1oAUV.mjs → reconcile-C5OyCA7V.mjs} +2 -2
  17. package/dist/{reconcile-WzC1oAUV.mjs.map → reconcile-C5OyCA7V.mjs.map} +1 -1
  18. package/dist/{reconcile-CCtrj-zt.cjs → reconcile-TEBsryVn.cjs} +2 -2
  19. package/dist/{reconcile-CCtrj-zt.cjs.map → reconcile-TEBsryVn.cjs.map} +1 -1
  20. package/dist/workspace/index.d.cts +1 -1
  21. package/dist/workspace/index.d.mts +1 -1
  22. package/dist/workspace-4SP3Gx4Y.cjs.map +1 -1
  23. package/dist/workspace-D4z4A4cq.mjs.map +1 -1
  24. package/package.json +4 -4
  25. package/src/dev/__tests__/index.spec.ts +35 -9
  26. package/src/dev/index.ts +18 -1
  27. package/src/docker/__tests__/compose.spec.ts +13 -11
  28. package/src/docker/compose.ts +10 -10
  29. package/src/init/__tests__/init.spec.ts +1 -1
  30. package/src/init/generators/docker.ts +7 -7
  31. package/src/init/index.ts +3 -1
  32. package/src/secrets/generator.ts +11 -0
  33. package/src/secrets/index.ts +12 -6
  34. package/src/setup/index.ts +3 -1
  35. package/src/test/__tests__/index.spec.ts +62 -34
  36. package/src/test/index.ts +0 -41
  37. package/src/workspace/types.ts +2 -2
  38. package/dist/fullstack-secrets-DqxYGrgW.cjs.map +0 -1
  39. 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-odm79Uo1.mjs";
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.3";
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: "16-alpine",
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://postgres:postgres@postgres:5432/app}
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
- - postgres_data:/var/lib/postgresql/data
2925
+ - dbdata:/var/lib/postgresql/18/data
2919
2926
  healthcheck:
2920
- test: ["CMD-SHELL", "pg_isready -U postgres"]
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 += ` postgres_data:
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
- - postgres_data:/var/lib/postgresql/data
3054
+ - dbdata:/var/lib/postgresql/18/data
3048
3055
  healthcheck:
3049
- test: ["CMD-SHELL", "pg_isready -U postgres"]
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 += ` postgres_data:
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:16-alpine",
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://postgres:postgres@postgres:5432/app}
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:16-alpine
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: ${options.name.replace(/-/g, "_")}_dev
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
- - postgres_data:/var/lib/postgresql/data${initVolume}
6967
+ - dbdata:/var/lib/postgresql/18/data${initVolume}
6961
6968
  healthcheck:
6962
- test: ['CMD-SHELL', 'pg_isready -U postgres']
6969
+ test: ['CMD-SHELL', 'pg_isready -U $$POSTGRES_USER']
6963
6970
  interval: 5s
6964
6971
  timeout: 5s
6965
6972
  retries: 5`);
6966
- volumes.push(" postgres_data:");
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
- const secrets = createStageSecrets(stage, services);
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
- const customSecrets = generateFullstackCustomSecrets(loaded.workspace);
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-WzC1oAUV.mjs");
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-WzC1oAUV.mjs");
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-WzC1oAUV.mjs");
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);