@geekmidas/cli 1.10.11 → 1.10.12

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 (61) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/{bundler-wY-XZDl9.cjs → bundler-DVJkwNMQ.cjs} +2 -2
  3. package/dist/{bundler-wY-XZDl9.cjs.map → bundler-DVJkwNMQ.cjs.map} +1 -1
  4. package/dist/{bundler-BvByD6tt.mjs → bundler-Di5Gz9Ou.mjs} +2 -2
  5. package/dist/{bundler-BvByD6tt.mjs.map → bundler-Di5Gz9Ou.mjs.map} +1 -1
  6. package/dist/config.d.cts +2 -2
  7. package/dist/config.d.mts +2 -2
  8. package/dist/{fullstack-secrets-Bnm_QeZr.mjs → fullstack-secrets-BIFFv4UZ.mjs} +10 -1
  9. package/dist/fullstack-secrets-BIFFv4UZ.mjs.map +1 -0
  10. package/dist/{fullstack-secrets-AUkUyeW0.cjs → fullstack-secrets-D9rjTNyx.cjs} +10 -1
  11. package/dist/fullstack-secrets-D9rjTNyx.cjs.map +1 -0
  12. package/dist/{index-BdJZKXCJ.d.cts → index-UCsZ_Vkw.d.cts} +2 -2
  13. package/dist/{index-BdJZKXCJ.d.cts.map → index-UCsZ_Vkw.d.cts.map} +1 -1
  14. package/dist/{index-DB9VbcCD.d.mts → index-gXAGDSGu.d.mts} +2 -2
  15. package/dist/{index-DB9VbcCD.d.mts.map → index-gXAGDSGu.d.mts.map} +1 -1
  16. package/dist/index.cjs +90 -31
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.mjs +90 -31
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/openapi-BYxAWwok.cjs.map +1 -1
  21. package/dist/openapi-DenF-okj.mjs.map +1 -1
  22. package/dist/openapi.d.cts +1 -1
  23. package/dist/openapi.d.mts +1 -1
  24. package/dist/{reconcile--yaWO052.mjs → reconcile-DxTEausy.mjs} +2 -2
  25. package/dist/{reconcile--yaWO052.mjs.map → reconcile-DxTEausy.mjs.map} +1 -1
  26. package/dist/{reconcile-oktp4i_4.cjs → reconcile-LaaJkFlO.cjs} +2 -2
  27. package/dist/{reconcile-oktp4i_4.cjs.map → reconcile-LaaJkFlO.cjs.map} +1 -1
  28. package/dist/{storage-CEisMvif.cjs → storage-6GBoLCYF.cjs} +7 -1
  29. package/dist/{storage-CEisMvif.cjs.map → storage-6GBoLCYF.cjs.map} +1 -1
  30. package/dist/{storage-D3lh8Xpq.mjs → storage-BFqrVsip.mjs} +1 -1
  31. package/dist/{storage-B3aXQBpI.cjs → storage-DCqjCiDn.cjs} +1 -1
  32. package/dist/{storage-Df-NFMY9.mjs → storage-DMf420PP.mjs} +7 -1
  33. package/dist/{storage-Df-NFMY9.mjs.map → storage-DMf420PP.mjs.map} +1 -1
  34. package/dist/sync-BVNso6AA.cjs +4 -0
  35. package/dist/{sync-CcDvBUu4.cjs → sync-DIGGOxCw.cjs} +2 -2
  36. package/dist/{sync-CcDvBUu4.cjs.map → sync-DIGGOxCw.cjs.map} +1 -1
  37. package/dist/{sync-CIzj1CQe.mjs → sync-DjD_TeNX.mjs} +1 -1
  38. package/dist/{sync-D-7NTKvV.mjs → sync-Do9O7QZ8.mjs} +2 -2
  39. package/dist/{sync-D-7NTKvV.mjs.map → sync-Do9O7QZ8.mjs.map} +1 -1
  40. package/dist/{types-D4MLWXSL.d.cts → types-DiV9Mbvc.d.mts} +2 -2
  41. package/dist/{types-D4MLWXSL.d.cts.map → types-DiV9Mbvc.d.mts.map} +1 -1
  42. package/dist/{types-DwpLq_fp.d.mts → types-JvWj5Ckc.d.cts} +2 -2
  43. package/dist/{types-DwpLq_fp.d.mts.map → types-JvWj5Ckc.d.cts.map} +1 -1
  44. package/dist/workspace/index.d.cts +2 -2
  45. package/dist/workspace/index.d.mts +2 -2
  46. package/package.json +3 -3
  47. package/src/dev/index.ts +35 -0
  48. package/src/docker/__tests__/compose.spec.ts +24 -2
  49. package/src/docker/compose.ts +53 -3
  50. package/src/init/__tests__/generators.spec.ts +1 -0
  51. package/src/init/generators/docker.ts +1 -2
  52. package/src/init/index.ts +1 -0
  53. package/src/init/versions.ts +1 -1
  54. package/src/secrets/generator.ts +10 -0
  55. package/src/secrets/storage.ts +6 -0
  56. package/src/secrets/types.ts +3 -0
  57. package/src/test/index.ts +8 -10
  58. package/src/types.ts +6 -1
  59. package/dist/fullstack-secrets-AUkUyeW0.cjs.map +0 -1
  60. package/dist/fullstack-secrets-Bnm_QeZr.mjs.map +0 -1
  61. package/dist/sync-QNXT8x13.cjs +0 -4
package/dist/index.mjs CHANGED
@@ -4,13 +4,13 @@ import { getAppBuildOrder, getDependencyEnvVars, getDeployTargetError, isDeployT
4
4
  import { getAppNameFromCwd, loadAppConfig, loadConfig, loadWorkspaceAppInfo, loadWorkspaceConfig, parseModuleConfig } from "./config-jsRYHOHU.mjs";
5
5
  import { getCredentialsPath, getDokployCredentials, getDokployRegistryId, getDokployToken, removeDokployCredentials, storeDokployCredentials, storeDokployRegistryId } from "./credentials-s1kLcIzK.mjs";
6
6
  import { ConstructGenerator, EndpointGenerator, OPENAPI_OUTPUT_PATH, copyAllClients, copyClientToFrontends, generateOpenApi, getBackendOpenApiPath, isPartitionedRoutes, normalizeRoutes, openapiCommand, resolveOpenApiConfig } from "./openapi-DenF-okj.mjs";
7
- import { getKeyPath, maskPassword, readStageSecrets, secretsExist, setCustomSecret, toEmbeddableSecrets, writeStageSecrets } from "./storage-Df-NFMY9.mjs";
7
+ import { getKeyPath, maskPassword, readStageSecrets, secretsExist, setCustomSecret, toEmbeddableSecrets, writeStageSecrets } from "./storage-DMf420PP.mjs";
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, generateConnectionUrls, generateDbPassword, generateDbUrl, generateFullstackCustomSecrets, generateServiceCredentials, rotateServicePassword, writeDockerEnvFromSecrets } from "./fullstack-secrets-Bnm_QeZr.mjs";
11
+ import { createStageSecrets, generateConnectionUrls, generateDbPassword, generateDbUrl, generateFullstackCustomSecrets, generateServiceCredentials, rotateServicePassword, writeDockerEnvFromSecrets } from "./fullstack-secrets-BIFFv4UZ.mjs";
12
12
  import { generateReactQueryCommand } from "./openapi-react-query-C4UdILaI.mjs";
13
- import { isSSMConfigured, pullSecrets, pushSecrets } from "./sync-D-7NTKvV.mjs";
13
+ import { isSSMConfigured, pullSecrets, pushSecrets } from "./sync-Do9O7QZ8.mjs";
14
14
  import { createRequire } from "node:module";
15
15
  import { copyFileSync, existsSync, readFileSync, unlinkSync } from "node:fs";
16
16
  import { basename, dirname, join, parse, relative, resolve } from "node:path";
@@ -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.10";
38
+ var version = "1.10.11";
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";
@@ -1256,6 +1256,28 @@ function parseComposeServiceNames(composePath) {
1256
1256
  * This ensures manually added services are always started.
1257
1257
  * @internal Exported for testing
1258
1258
  */
1259
+ /**
1260
+ * Start docker-compose services for a single-app project (no workspace config).
1261
+ * Starts all services defined in docker-compose.yml.
1262
+ */
1263
+ async function startComposeServices(cwd, portEnv, secretsEnv) {
1264
+ const composeFile = join(cwd, "docker-compose.yml");
1265
+ if (!existsSync(composeFile)) return;
1266
+ const servicesToStart = parseComposeServiceNames(composeFile);
1267
+ if (servicesToStart.length === 0) return;
1268
+ logger$11.log(`🐳 Starting services: ${servicesToStart.join(", ")}`);
1269
+ try {
1270
+ execSync(`docker compose up -d ${servicesToStart.join(" ")}`, {
1271
+ cwd,
1272
+ stdio: "inherit",
1273
+ env: buildDockerComposeEnv(secretsEnv, portEnv)
1274
+ });
1275
+ logger$11.log("✅ Services started");
1276
+ } catch (error) {
1277
+ logger$11.error("❌ Failed to start services:", error.message);
1278
+ throw error;
1279
+ }
1280
+ }
1259
1281
  async function startWorkspaceServices(workspace, portEnv, secretsEnv) {
1260
1282
  const composeFile = join(workspace.root, "docker-compose.yml");
1261
1283
  if (!existsSync(composeFile)) return;
@@ -2198,7 +2220,7 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2198
2220
  let masterKey;
2199
2221
  if (context.production?.bundle && !skipBundle) {
2200
2222
  logger$9.log(`\n📦 Bundling production server...`);
2201
- const { bundleServer } = await import("./bundler-BvByD6tt.mjs");
2223
+ const { bundleServer } = await import("./bundler-Di5Gz9Ou.mjs");
2202
2224
  const allConstructs = [
2203
2225
  ...endpoints.map((e) => e.construct),
2204
2226
  ...functions.map((f) => f.construct),
@@ -2861,14 +2883,16 @@ const DEFAULT_SERVICE_IMAGES = {
2861
2883
  postgres: "postgres",
2862
2884
  redis: "redis",
2863
2885
  rabbitmq: "rabbitmq",
2864
- minio: "minio/minio"
2886
+ minio: "minio/minio",
2887
+ mailpit: "axllent/mailpit"
2865
2888
  };
2866
2889
  /** Default Docker image versions for services */
2867
2890
  const DEFAULT_SERVICE_VERSIONS = {
2868
2891
  postgres: "18-alpine",
2869
2892
  redis: "7-alpine",
2870
2893
  rabbitmq: "3-management-alpine",
2871
- minio: "latest"
2894
+ minio: "latest",
2895
+ mailpit: "latest"
2872
2896
  };
2873
2897
  /** Get the default full image reference for a service */
2874
2898
  function getDefaultImage(serviceName) {
@@ -2928,6 +2952,11 @@ services:
2928
2952
  - STORAGE_BUCKET=\${STORAGE_BUCKET:-${imageName}}
2929
2953
  - STORAGE_REGION=\${STORAGE_REGION:-eu-west-1}
2930
2954
  - STORAGE_FORCE_PATH_STYLE=true
2955
+ `;
2956
+ if (serviceMap.has("mailpit")) yaml += ` - SMTP_HOST=\${SMTP_HOST:-mailpit}
2957
+ - SMTP_PORT=\${SMTP_PORT:-1025}
2958
+ - SMTP_USER=\${SMTP_USER:-${imageName}}
2959
+ - SMTP_PASS=\${SMTP_PASS:-${imageName}}
2931
2960
  `;
2932
2961
  yaml += ` healthcheck:
2933
2962
  test: ["CMD", "wget", "-q", "--spider", "http://localhost:${port}${healthCheckPath}"]
@@ -3025,6 +3054,25 @@ services:
3025
3054
  retries: 5
3026
3055
  networks:
3027
3056
  - app-network
3057
+ `;
3058
+ const mailpitImage = serviceMap.get("mailpit");
3059
+ if (mailpitImage) yaml += `
3060
+ mailpit:
3061
+ image: ${mailpitImage}
3062
+ container_name: mailpit
3063
+ restart: unless-stopped
3064
+ environment:
3065
+ MP_SMTP_AUTH: \${SMTP_USER:-${imageName}}:\${SMTP_PASS:-${imageName}}
3066
+ ports:
3067
+ - "\${MAILPIT_UI_PORT:-8025}:8025" # Web UI
3068
+ - "\${MAILPIT_SMTP_PORT:-1025}:1025" # SMTP
3069
+ healthcheck:
3070
+ test: ["CMD", "wget", "-q", "--spider", "http://localhost:8025"]
3071
+ interval: 5s
3072
+ timeout: 5s
3073
+ retries: 5
3074
+ networks:
3075
+ - app-network
3028
3076
  `;
3029
3077
  yaml += `
3030
3078
  volumes:
@@ -3106,7 +3154,8 @@ services:
3106
3154
  projectName: workspace.name,
3107
3155
  hasPostgres,
3108
3156
  hasRedis,
3109
- hasMinio
3157
+ hasMinio,
3158
+ hasMail
3110
3159
  });
3111
3160
  if (hasPostgres) yaml += `
3112
3161
  postgres:
@@ -3147,9 +3196,16 @@ services:
3147
3196
  image: axllent/mailpit:latest
3148
3197
  container_name: ${workspace.name}-mailpit
3149
3198
  restart: unless-stopped
3199
+ environment:
3200
+ MP_SMTP_AUTH: \${SMTP_USER:-${workspace.name}}:\${SMTP_PASS:-${workspace.name}}
3150
3201
  ports:
3151
- - "8025:8025" # Web UI
3152
- - "1025:1025" # SMTP
3202
+ - "\${MAILPIT_UI_PORT:-8025}:8025" # Web UI
3203
+ - "\${MAILPIT_SMTP_PORT:-1025}:1025" # SMTP
3204
+ healthcheck:
3205
+ test: ["CMD", "wget", "-q", "--spider", "http://localhost:8025"]
3206
+ interval: 5s
3207
+ timeout: 5s
3208
+ retries: 5
3153
3209
  networks:
3154
3210
  - workspace-network
3155
3211
  `;
@@ -3219,7 +3275,7 @@ function getInfraServiceImage(serviceName, config$1) {
3219
3275
  * Generate a service definition for an app.
3220
3276
  */
3221
3277
  function generateAppService(appName, app, allApps, options) {
3222
- const { registry, projectName, hasPostgres, hasRedis, hasMinio } = options;
3278
+ const { registry, projectName, hasPostgres, hasRedis, hasMinio, hasMail } = options;
3223
3279
  const imageRef = registry ? `\${REGISTRY:-${registry}}/` : "";
3224
3280
  const healthCheckPath = app.type === "frontend" ? "/" : "/health";
3225
3281
  const healthCheckCmd = app.type === "frontend" ? `["CMD", "wget", "-q", "--spider", "http://localhost:${app.port}/"]` : `["CMD", "wget", "-q", "--spider", "http://localhost:${app.port}${healthCheckPath}"]`;
@@ -3253,6 +3309,11 @@ function generateAppService(appName, app, allApps, options) {
3253
3309
  - STORAGE_BUCKET=\${STORAGE_BUCKET:-${projectName}}
3254
3310
  - STORAGE_REGION=\${STORAGE_REGION:-eu-west-1}
3255
3311
  - STORAGE_FORCE_PATH_STYLE=true
3312
+ `;
3313
+ if (hasMail) yaml += ` - SMTP_HOST=\${SMTP_HOST:-mailpit}
3314
+ - SMTP_PORT=\${SMTP_PORT:-1025}
3315
+ - SMTP_USER=\${SMTP_USER:-${projectName}}
3316
+ - SMTP_PASS=\${SMTP_PASS:-${projectName}}
3256
3317
  `;
3257
3318
  }
3258
3319
  yaml += ` healthcheck:
@@ -3266,6 +3327,7 @@ function generateAppService(appName, app, allApps, options) {
3266
3327
  if (hasPostgres) dependencies$1.push("postgres");
3267
3328
  if (hasRedis) dependencies$1.push("redis");
3268
3329
  if (hasMinio) dependencies$1.push("minio");
3330
+ if (hasMail) dependencies$1.push("mailpit");
3269
3331
  }
3270
3332
  if (dependencies$1.length > 0) {
3271
3333
  yaml += ` depends_on:
@@ -6310,7 +6372,7 @@ async function deployCommand(options) {
6310
6372
  dokployConfig = setupResult.config;
6311
6373
  finalRegistry = dokployConfig.registry ?? dockerConfig.registry;
6312
6374
  if (setupResult.serviceUrls) {
6313
- const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1, initStageSecrets } = await import("./storage-D3lh8Xpq.mjs");
6375
+ const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1, initStageSecrets } = await import("./storage-BFqrVsip.mjs");
6314
6376
  let secrets = await readStageSecrets$1(stage);
6315
6377
  if (!secrets) {
6316
6378
  logger$3.log(` Creating secrets file for stage "${stage}"...`);
@@ -6604,7 +6666,7 @@ const GEEKMIDAS_VERSIONS = {
6604
6666
  "@geekmidas/rate-limit": "~2.0.0",
6605
6667
  "@geekmidas/schema": "~1.0.0",
6606
6668
  "@geekmidas/services": "~1.0.1",
6607
- "@geekmidas/storage": "~2.0.0",
6669
+ "@geekmidas/storage": "~2.0.1",
6608
6670
  "@geekmidas/studio": "~1.0.0",
6609
6671
  "@geekmidas/telescope": "~1.0.0",
6610
6672
  "@geekmidas/testkit": "~1.0.5",
@@ -7160,8 +7222,7 @@ function generateDockerFiles(options, template, dbApps) {
7160
7222
  - '\${MAILPIT_SMTP_HOST_PORT:-1025}:1025'
7161
7223
  - '\${MAILPIT_UI_HOST_PORT:-8025}:8025'
7162
7224
  environment:
7163
- MP_SMTP_AUTH_ACCEPT_ANY: 1
7164
- MP_SMTP_AUTH_ALLOW_INSECURE: 1`);
7225
+ MP_SMTP_AUTH: \${SMTP_USER:-${options.name}}:\${SMTP_PASS:-${options.name}}`);
7165
7226
  let dockerCompose = `# Use "gkm dev" or "gkm test" to start services.
7166
7227
  # Running "docker compose up" directly will not inject secrets or resolve ports.
7167
7228
  services:
@@ -10976,6 +11037,7 @@ async function initCommand(projectName, options = {}) {
10976
11037
  if (services.db) secretServices.push("postgres");
10977
11038
  if (services.cache) secretServices.push("redis");
10978
11039
  if (services.storage) secretServices.push("minio");
11040
+ if (services.mail) secretServices.push("mailpit");
10979
11041
  const devSecrets = createStageSecrets("development", secretServices, { projectName: name$1 });
10980
11042
  const customSecrets = {
10981
11043
  NODE_ENV: "development",
@@ -11544,14 +11606,11 @@ async function testCommand(options = {}) {
11544
11606
  const composePath = join(cwd, "docker-compose.yml");
11545
11607
  const mappings = parseComposePortMappings(composePath);
11546
11608
  if (mappings.length > 0) {
11547
- const ports = await loadPortState(cwd);
11548
- if (Object.keys(ports).length > 0) {
11549
- secretsEnv = rewriteUrlsWithPorts(secretsEnv, {
11550
- dockerEnv: {},
11551
- ports,
11552
- mappings
11553
- });
11554
- console.log(` 🔌 Applied ${Object.keys(ports).length} port mapping(s)`);
11609
+ const resolvedPorts = await resolveServicePorts(cwd);
11610
+ await startComposeServices(cwd, resolvedPorts.dockerEnv, secretsEnv);
11611
+ if (resolvedPorts.mappings.length > 0) {
11612
+ secretsEnv = rewriteUrlsWithPorts(secretsEnv, resolvedPorts);
11613
+ console.log(` 🔌 Applied ${Object.keys(resolvedPorts.ports).length} port mapping(s)`);
11555
11614
  }
11556
11615
  }
11557
11616
  }
@@ -11990,9 +12049,9 @@ program.command("secrets:push").description("Push secrets to remote provider (SS
11990
12049
  const globalOptions = program.opts();
11991
12050
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11992
12051
  const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
11993
- const { pushSecrets: pushSecrets$1 } = await import("./sync-CIzj1CQe.mjs");
11994
- const { reconcileMissingSecrets } = await import("./reconcile--yaWO052.mjs");
11995
- const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-D3lh8Xpq.mjs");
12052
+ const { pushSecrets: pushSecrets$1 } = await import("./sync-DjD_TeNX.mjs");
12053
+ const { reconcileMissingSecrets } = await import("./reconcile-DxTEausy.mjs");
12054
+ const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-BFqrVsip.mjs");
11996
12055
  const { workspace } = await loadWorkspaceConfig$1();
11997
12056
  const secrets = await readStageSecrets$1(options.stage, workspace.root);
11998
12057
  if (secrets) {
@@ -12015,9 +12074,9 @@ program.command("secrets:pull").description("Pull secrets from remote provider (
12015
12074
  const globalOptions = program.opts();
12016
12075
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
12017
12076
  const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
12018
- const { pullSecrets: pullSecrets$1 } = await import("./sync-CIzj1CQe.mjs");
12019
- const { writeStageSecrets: writeStageSecrets$1 } = await import("./storage-D3lh8Xpq.mjs");
12020
- const { reconcileMissingSecrets } = await import("./reconcile--yaWO052.mjs");
12077
+ const { pullSecrets: pullSecrets$1 } = await import("./sync-DjD_TeNX.mjs");
12078
+ const { writeStageSecrets: writeStageSecrets$1 } = await import("./storage-BFqrVsip.mjs");
12079
+ const { reconcileMissingSecrets } = await import("./reconcile-DxTEausy.mjs");
12021
12080
  const { workspace } = await loadWorkspaceConfig$1();
12022
12081
  let secrets = await pullSecrets$1(options.stage, workspace);
12023
12082
  if (!secrets) {
@@ -12042,8 +12101,8 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
12042
12101
  const globalOptions = program.opts();
12043
12102
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
12044
12103
  const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
12045
- const { reconcileMissingSecrets } = await import("./reconcile--yaWO052.mjs");
12046
- const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-D3lh8Xpq.mjs");
12104
+ const { reconcileMissingSecrets } = await import("./reconcile-DxTEausy.mjs");
12105
+ const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-BFqrVsip.mjs");
12047
12106
  const { workspace } = await loadWorkspaceConfig$1();
12048
12107
  const secrets = await readStageSecrets$1(options.stage, workspace.root);
12049
12108
  if (!secrets) {