@geekmidas/cli 1.8.0 → 1.9.0

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 (55) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/{HostingerProvider-BiXdHjiq.cjs → HostingerProvider-CEsQbmpY.cjs} +1 -1
  3. package/dist/{HostingerProvider-BiXdHjiq.cjs.map → HostingerProvider-CEsQbmpY.cjs.map} +1 -1
  4. package/dist/{HostingerProvider-402UdK89.mjs → HostingerProvider-DkahM5AP.mjs} +1 -1
  5. package/dist/{HostingerProvider-402UdK89.mjs.map → HostingerProvider-DkahM5AP.mjs.map} +1 -1
  6. package/dist/{LocalStateProvider-BDm7ZqJo.mjs → LocalStateProvider-DXIwWb7k.mjs} +1 -1
  7. package/dist/{LocalStateProvider-BDm7ZqJo.mjs.map → LocalStateProvider-DXIwWb7k.mjs.map} +1 -1
  8. package/dist/{LocalStateProvider-CdspeSVL.cjs → LocalStateProvider-Roi202l7.cjs} +1 -1
  9. package/dist/{LocalStateProvider-CdspeSVL.cjs.map → LocalStateProvider-Roi202l7.cjs.map} +1 -1
  10. package/dist/{Route53Provider-kfJ77LmL.cjs → Route53Provider-BqXeHzuc.cjs} +1 -1
  11. package/dist/{Route53Provider-kfJ77LmL.cjs.map → Route53Provider-BqXeHzuc.cjs.map} +1 -1
  12. package/dist/{Route53Provider-DbBo7Uz5.mjs → Route53Provider-Ckq_n5Be.mjs} +1 -1
  13. package/dist/{Route53Provider-DbBo7Uz5.mjs.map → Route53Provider-Ckq_n5Be.mjs.map} +1 -1
  14. package/dist/{SSMStateProvider-DGrqYll0.cjs → SSMStateProvider-BReQA5re.cjs} +1 -1
  15. package/dist/{SSMStateProvider-DGrqYll0.cjs.map → SSMStateProvider-BReQA5re.cjs.map} +1 -1
  16. package/dist/{SSMStateProvider-DT0WV-E_.mjs → SSMStateProvider-wddd0_-d.mjs} +1 -1
  17. package/dist/{SSMStateProvider-DT0WV-E_.mjs.map → SSMStateProvider-wddd0_-d.mjs.map} +1 -1
  18. package/dist/{backup-provisioner-BIArpmTr.mjs → backup-provisioner-BAExdDtc.mjs} +1 -1
  19. package/dist/{backup-provisioner-BIArpmTr.mjs.map → backup-provisioner-BAExdDtc.mjs.map} +1 -1
  20. package/dist/{backup-provisioner-B5e-F6zX.cjs → backup-provisioner-C8VK63I-.cjs} +1 -1
  21. package/dist/{backup-provisioner-B5e-F6zX.cjs.map → backup-provisioner-C8VK63I-.cjs.map} +1 -1
  22. package/dist/{bundler-DgXsOSxc.mjs → bundler-BxHyDhdt.mjs} +1 -1
  23. package/dist/{bundler-DgXsOSxc.mjs.map → bundler-BxHyDhdt.mjs.map} +1 -1
  24. package/dist/{bundler-tHLLwYuU.cjs → bundler-CuMIfXw5.cjs} +1 -1
  25. package/dist/{bundler-tHLLwYuU.cjs.map → bundler-CuMIfXw5.cjs.map} +1 -1
  26. package/dist/config.d.mts +2 -2
  27. package/dist/{index-C-KxSGGK.d.mts → index-BVNXOydm.d.mts} +2 -2
  28. package/dist/{index-C-KxSGGK.d.mts.map → index-BVNXOydm.d.mts.map} +1 -1
  29. package/dist/index.cjs +1018 -550
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.mjs +1016 -548
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/openapi.d.mts +1 -1
  34. package/dist/sync-BOS0jKLn.cjs +93 -0
  35. package/dist/sync-BOS0jKLn.cjs.map +1 -0
  36. package/dist/sync-BnqNNc6O.mjs +3 -0
  37. package/dist/sync-BxFB34zW.cjs +4 -0
  38. package/dist/sync-CHfhmXF3.mjs +76 -0
  39. package/dist/sync-CHfhmXF3.mjs.map +1 -0
  40. package/dist/{types-CZg5iUgD.d.mts → types-eTlj5f2M.d.mts} +1 -1
  41. package/dist/{types-CZg5iUgD.d.mts.map → types-eTlj5f2M.d.mts.map} +1 -1
  42. package/dist/workspace/index.d.mts +2 -2
  43. package/package.json +5 -5
  44. package/src/dev/index.ts +1 -1
  45. package/src/generators/SubscriberGenerator.ts +1 -0
  46. package/src/index.ts +93 -0
  47. package/src/init/index.ts +4 -23
  48. package/src/init/utils.ts +103 -2
  49. package/src/secrets/index.ts +20 -1
  50. package/src/secrets/sync.ts +136 -0
  51. package/src/setup/fullstack-secrets.ts +121 -0
  52. package/src/setup/index.ts +212 -0
  53. package/src/test/__tests__/web.spec.ts +1 -1
  54. package/src/upgrade/__tests__/index.spec.ts +354 -0
  55. package/src/upgrade/index.ts +253 -0
package/dist/index.cjs CHANGED
@@ -9,6 +9,7 @@ const require_dokploy_api = require('./dokploy-api-DLgvEQlr.cjs');
9
9
  const require_encryption = require('./encryption-BE0UOb8j.cjs');
10
10
  const require_CachedStateProvider = require('./CachedStateProvider-D73dCqfH.cjs');
11
11
  const require_openapi_react_query = require('./openapi-react-query-BeXvk-wa.cjs');
12
+ const require_sync = require('./sync-BOS0jKLn.cjs');
12
13
  const node_fs = require_chunk.__toESM(require("node:fs"));
13
14
  const node_path = require_chunk.__toESM(require("node:path"));
14
15
  const commander = require_chunk.__toESM(require("commander"));
@@ -33,7 +34,7 @@ const prompts = require_chunk.__toESM(require("prompts"));
33
34
 
34
35
  //#region package.json
35
36
  var name = "@geekmidas/cli";
36
- var version = "1.7.0";
37
+ var version = "1.8.0";
37
38
  var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
38
39
  var private$1 = false;
39
40
  var type = "module";
@@ -131,7 +132,7 @@ var package_default = {
131
132
 
132
133
  //#endregion
133
134
  //#region src/auth/index.ts
134
- const logger$11 = console;
135
+ const logger$13 = console;
135
136
  /**
136
137
  * Validate Dokploy token by making a test API call
137
138
  */
@@ -199,36 +200,36 @@ async function prompt$1(message, hidden = false) {
199
200
  async function loginCommand(options) {
200
201
  const { service, token: providedToken, endpoint: providedEndpoint } = options;
201
202
  if (service === "dokploy") {
202
- logger$11.log("\n🔐 Logging in to Dokploy...\n");
203
+ logger$13.log("\n🔐 Logging in to Dokploy...\n");
203
204
  let endpoint = providedEndpoint;
204
205
  if (!endpoint) endpoint = await prompt$1("Dokploy URL (e.g., https://dokploy.example.com): ");
205
206
  endpoint = endpoint.replace(/\/$/, "");
206
207
  try {
207
208
  new URL(endpoint);
208
209
  } catch {
209
- logger$11.error("Invalid URL format");
210
+ logger$13.error("Invalid URL format");
210
211
  process.exit(1);
211
212
  }
212
213
  let token = providedToken;
213
214
  if (!token) {
214
- logger$11.log(`\nGenerate a token at: ${endpoint}/settings/profile\n`);
215
+ logger$13.log(`\nGenerate a token at: ${endpoint}/settings/profile\n`);
215
216
  token = await prompt$1("API Token: ", true);
216
217
  }
217
218
  if (!token) {
218
- logger$11.error("Token is required");
219
+ logger$13.error("Token is required");
219
220
  process.exit(1);
220
221
  }
221
- logger$11.log("\nValidating credentials...");
222
+ logger$13.log("\nValidating credentials...");
222
223
  const isValid = await validateDokployToken(endpoint, token);
223
224
  if (!isValid) {
224
- logger$11.error("\n✗ Invalid credentials. Please check your token and try again.");
225
+ logger$13.error("\n✗ Invalid credentials. Please check your token and try again.");
225
226
  process.exit(1);
226
227
  }
227
228
  await require_credentials.storeDokployCredentials(token, endpoint);
228
- logger$11.log("\n✓ Successfully logged in to Dokploy!");
229
- logger$11.log(` Endpoint: ${endpoint}`);
230
- logger$11.log(` Credentials stored in: ${require_credentials.getCredentialsPath()}`);
231
- logger$11.log("\nYou can now use deploy commands without setting DOKPLOY_API_TOKEN.");
229
+ logger$13.log("\n✓ Successfully logged in to Dokploy!");
230
+ logger$13.log(` Endpoint: ${endpoint}`);
231
+ logger$13.log(` Credentials stored in: ${require_credentials.getCredentialsPath()}`);
232
+ logger$13.log("\nYou can now use deploy commands without setting DOKPLOY_API_TOKEN.");
232
233
  }
233
234
  }
234
235
  /**
@@ -238,28 +239,28 @@ async function logoutCommand(options) {
238
239
  const { service = "dokploy" } = options;
239
240
  if (service === "all") {
240
241
  const dokployRemoved = await require_credentials.removeDokployCredentials();
241
- if (dokployRemoved) logger$11.log("\n✓ Logged out from all services");
242
- else logger$11.log("\nNo stored credentials found");
242
+ if (dokployRemoved) logger$13.log("\n✓ Logged out from all services");
243
+ else logger$13.log("\nNo stored credentials found");
243
244
  return;
244
245
  }
245
246
  if (service === "dokploy") {
246
247
  const removed = await require_credentials.removeDokployCredentials();
247
- if (removed) logger$11.log("\n✓ Logged out from Dokploy");
248
- else logger$11.log("\nNo Dokploy credentials found");
248
+ if (removed) logger$13.log("\n✓ Logged out from Dokploy");
249
+ else logger$13.log("\nNo Dokploy credentials found");
249
250
  }
250
251
  }
251
252
  /**
252
253
  * Show current login status
253
254
  */
254
255
  async function whoamiCommand() {
255
- logger$11.log("\n📋 Current credentials:\n");
256
+ logger$13.log("\n📋 Current credentials:\n");
256
257
  const dokploy = await require_credentials.getDokployCredentials();
257
258
  if (dokploy) {
258
- logger$11.log(" Dokploy:");
259
- logger$11.log(` Endpoint: ${dokploy.endpoint}`);
260
- logger$11.log(` Token: ${maskToken(dokploy.token)}`);
261
- } else logger$11.log(" Dokploy: Not logged in");
262
- logger$11.log(`\n Credentials file: ${require_credentials.getCredentialsPath()}`);
259
+ logger$13.log(" Dokploy:");
260
+ logger$13.log(` Endpoint: ${dokploy.endpoint}`);
261
+ logger$13.log(` Token: ${maskToken(dokploy.token)}`);
262
+ } else logger$13.log(" Dokploy: Not logged in");
263
+ logger$13.log(`\n Credentials file: ${require_credentials.getCredentialsPath()}`);
263
264
  }
264
265
  /**
265
266
  * Mask a token for display
@@ -345,7 +346,7 @@ function isEnabled(config) {
345
346
  var CronGenerator = class extends require_openapi.ConstructGenerator {
346
347
  async build(context, constructs, outputDir, options) {
347
348
  const provider = options?.provider || "aws-lambda";
348
- const logger$12 = console;
349
+ const logger$14 = console;
349
350
  const cronInfos = [];
350
351
  if (constructs.length === 0 || provider !== "aws-lambda") return cronInfos;
351
352
  const cronsDir = (0, node_path.join)(outputDir, "crons");
@@ -360,7 +361,7 @@ var CronGenerator = class extends require_openapi.ConstructGenerator {
360
361
  memorySize: construct.memorySize,
361
362
  environment: await construct.getEnvironment()
362
363
  });
363
- logger$12.log(`Generated cron handler: ${key}`);
364
+ logger$14.log(`Generated cron handler: ${key}`);
364
365
  }
365
366
  return cronInfos;
366
367
  }
@@ -396,7 +397,7 @@ var FunctionGenerator = class extends require_openapi.ConstructGenerator {
396
397
  }
397
398
  async build(context, constructs, outputDir, options) {
398
399
  const provider = options?.provider || "aws-lambda";
399
- const logger$12 = console;
400
+ const logger$14 = console;
400
401
  const functionInfos = [];
401
402
  if (constructs.length === 0 || provider !== "aws-lambda") return functionInfos;
402
403
  const functionsDir = (0, node_path.join)(outputDir, "functions");
@@ -410,7 +411,7 @@ var FunctionGenerator = class extends require_openapi.ConstructGenerator {
410
411
  memorySize: construct.memorySize,
411
412
  environment: await construct.getEnvironment()
412
413
  });
413
- logger$12.log(`Generated function handler: ${key}`);
414
+ logger$14.log(`Generated function handler: ${key}`);
414
415
  }
415
416
  return functionInfos;
416
417
  }
@@ -443,11 +444,11 @@ var SubscriberGenerator = class extends require_openapi.ConstructGenerator {
443
444
  }
444
445
  async build(context, constructs, outputDir, options) {
445
446
  const provider = options?.provider || "aws-lambda";
446
- const logger$12 = console;
447
+ const logger$14 = console;
447
448
  const subscriberInfos = [];
448
449
  if (provider === "server") {
449
450
  await this.generateServerSubscribersFile(outputDir, constructs);
450
- logger$12.log(`Generated server subscribers file with ${constructs.length} subscribers (polling mode)`);
451
+ logger$14.log(`Generated server subscribers file with ${constructs.length} subscribers (polling mode)`);
451
452
  return subscriberInfos;
452
453
  }
453
454
  if (constructs.length === 0) return subscriberInfos;
@@ -464,7 +465,7 @@ var SubscriberGenerator = class extends require_openapi.ConstructGenerator {
464
465
  memorySize: construct.memorySize,
465
466
  environment: await construct.getEnvironment()
466
467
  });
467
- logger$12.log(`Generated subscriber handler: ${key}`);
468
+ logger$14.log(`Generated subscriber handler: ${key}`);
468
469
  }
469
470
  return subscriberInfos;
470
471
  }
@@ -519,6 +520,7 @@ export const handler = adapter.handler;
519
520
  * - sqs://region/account-id/queue-name (SQS queue)
520
521
  * - sns://region/account-id/topic-name (SNS topic)
521
522
  * - rabbitmq://host:port/queue-name (RabbitMQ)
523
+ * - pgboss://user:pass@host:port/database (pg-boss / PostgreSQL)
522
524
  * - basic://in-memory (In-memory for testing)
523
525
  */
524
526
  import type { EnvironmentParser } from '@geekmidas/envkit';
@@ -630,7 +632,7 @@ export async function setupSubscribers(
630
632
 
631
633
  //#endregion
632
634
  //#region src/workspace/client-generator.ts
633
- const logger$10 = console;
635
+ const logger$12 = console;
634
636
  /**
635
637
  * Get frontend apps that depend on a backend app.
636
638
  */
@@ -659,7 +661,7 @@ function countEndpoints(content) {
659
661
  * Called when the backend's .gkm/openapi.ts file changes.
660
662
  */
661
663
  async function copyClientToFrontends(workspace, backendAppName, options = {}) {
662
- const log = options.silent ? () => {} : logger$10.log.bind(logger$10);
664
+ const log = options.silent ? () => {} : logger$12.log.bind(logger$12);
663
665
  const results = [];
664
666
  const backendApp = workspace.apps[backendAppName];
665
667
  if (!backendApp || backendApp.type !== "backend") return results;
@@ -722,7 +724,7 @@ async function copyAllClients(workspace, options = {}) {
722
724
 
723
725
  //#endregion
724
726
  //#region src/dev/index.ts
725
- const logger$9 = console;
727
+ const logger$11 = console;
726
728
  /**
727
729
  * Load environment files
728
730
  * @internal Exported for testing
@@ -773,7 +775,7 @@ async function findAvailablePort(preferredPort, maxAttempts = 10) {
773
775
  for (let i = 0; i < maxAttempts; i++) {
774
776
  const port = preferredPort + i;
775
777
  if (await isPortAvailable(port)) return port;
776
- logger$9.log(`⚠️ Port ${port} is in use, trying ${port + 1}...`);
778
+ logger$11.log(`⚠️ Port ${port} is in use, trying ${port + 1}...`);
777
779
  }
778
780
  throw new Error(`Could not find an available port after trying ${maxAttempts} ports starting from ${preferredPort}`);
779
781
  }
@@ -856,27 +858,27 @@ async function resolveServicePorts(workspaceRoot) {
856
858
  const savedState = await loadPortState(workspaceRoot);
857
859
  const dockerEnv = {};
858
860
  const ports = {};
859
- logger$9.log("\n🔌 Resolving service ports...");
861
+ logger$11.log("\n🔌 Resolving service ports...");
860
862
  for (const mapping of mappings) {
861
863
  const containerPort = getContainerHostPort(workspaceRoot, mapping.service, mapping.containerPort);
862
864
  if (containerPort !== null) {
863
865
  ports[mapping.envVar] = containerPort;
864
866
  dockerEnv[mapping.envVar] = String(containerPort);
865
- logger$9.log(` 🔄 ${mapping.service}:${mapping.containerPort}: reusing existing container on port ${containerPort}`);
867
+ logger$11.log(` 🔄 ${mapping.service}:${mapping.containerPort}: reusing existing container on port ${containerPort}`);
866
868
  continue;
867
869
  }
868
870
  const savedPort = savedState[mapping.envVar];
869
871
  if (savedPort && await isPortAvailable(savedPort)) {
870
872
  ports[mapping.envVar] = savedPort;
871
873
  dockerEnv[mapping.envVar] = String(savedPort);
872
- logger$9.log(` 💾 ${mapping.service}:${mapping.containerPort}: using saved port ${savedPort}`);
874
+ logger$11.log(` 💾 ${mapping.service}:${mapping.containerPort}: using saved port ${savedPort}`);
873
875
  continue;
874
876
  }
875
877
  const resolvedPort = await findAvailablePort(mapping.defaultPort);
876
878
  ports[mapping.envVar] = resolvedPort;
877
879
  dockerEnv[mapping.envVar] = String(resolvedPort);
878
- if (resolvedPort !== mapping.defaultPort) logger$9.log(` ⚡ ${mapping.service}:${mapping.containerPort}: port ${mapping.defaultPort} occupied, using port ${resolvedPort}`);
879
- else logger$9.log(` ✅ ${mapping.service}:${mapping.containerPort}: using default port ${resolvedPort}`);
880
+ if (resolvedPort !== mapping.defaultPort) logger$11.log(` ⚡ ${mapping.service}:${mapping.containerPort}: port ${mapping.defaultPort} occupied, using port ${resolvedPort}`);
881
+ else logger$11.log(` ✅ ${mapping.service}:${mapping.containerPort}: using default port ${resolvedPort}`);
880
882
  }
881
883
  await savePortState(workspaceRoot, ports);
882
884
  return {
@@ -1020,7 +1022,7 @@ function getProductionConfigFromGkm(config) {
1020
1022
  async function devCommand(options) {
1021
1023
  if (options.entry) return entryDevCommand(options);
1022
1024
  const defaultEnv = loadEnvFiles(".env");
1023
- if (defaultEnv.loaded.length > 0) logger$9.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1025
+ if (defaultEnv.loaded.length > 0) logger$11.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1024
1026
  const appName = require_config.getAppNameFromCwd();
1025
1027
  let config;
1026
1028
  let appRoot = process.cwd();
@@ -1034,9 +1036,9 @@ async function devCommand(options) {
1034
1036
  secretsRoot = appConfig.workspaceRoot;
1035
1037
  workspaceAppName = appConfig.appName;
1036
1038
  workspaceAppPort = appConfig.app.port;
1037
- logger$9.log(`📦 Running app: ${appConfig.appName} on port ${workspaceAppPort}`);
1039
+ logger$11.log(`📦 Running app: ${appConfig.appName} on port ${workspaceAppPort}`);
1038
1040
  if (appConfig.app.entry) {
1039
- logger$9.log(`📄 Using entry point: ${appConfig.app.entry}`);
1041
+ logger$11.log(`📄 Using entry point: ${appConfig.app.entry}`);
1040
1042
  return entryDevCommand({
1041
1043
  ...options,
1042
1044
  entry: appConfig.app.entry,
@@ -1047,7 +1049,7 @@ async function devCommand(options) {
1047
1049
  } catch {
1048
1050
  const loadedConfig = await require_config.loadWorkspaceConfig();
1049
1051
  if (loadedConfig.type === "workspace") {
1050
- logger$9.log("📦 Detected workspace configuration");
1052
+ logger$11.log("📦 Detected workspace configuration");
1051
1053
  return workspaceDevCommand(loadedConfig.workspace, options);
1052
1054
  }
1053
1055
  config = loadedConfig.raw;
@@ -1055,34 +1057,34 @@ async function devCommand(options) {
1055
1057
  else {
1056
1058
  const loadedConfig = await require_config.loadWorkspaceConfig();
1057
1059
  if (loadedConfig.type === "workspace") {
1058
- logger$9.log("📦 Detected workspace configuration");
1060
+ logger$11.log("📦 Detected workspace configuration");
1059
1061
  return workspaceDevCommand(loadedConfig.workspace, options);
1060
1062
  }
1061
1063
  config = loadedConfig.raw;
1062
1064
  }
1063
1065
  if (config.env) {
1064
1066
  const { loaded, missing } = loadEnvFiles(config.env, appRoot);
1065
- if (loaded.length > 0) logger$9.log(`📦 Loaded env: ${loaded.join(", ")}`);
1066
- if (missing.length > 0) logger$9.warn(`⚠️ Missing env files: ${missing.join(", ")}`);
1067
+ if (loaded.length > 0) logger$11.log(`📦 Loaded env: ${loaded.join(", ")}`);
1068
+ if (missing.length > 0) logger$11.warn(`⚠️ Missing env files: ${missing.join(", ")}`);
1067
1069
  }
1068
1070
  const resolved = resolveProviders(config, { provider: "server" });
1069
- logger$9.log("🚀 Starting development server...");
1070
- logger$9.log(`Loading routes from: ${config.routes}`);
1071
- if (config.functions) logger$9.log(`Loading functions from: ${config.functions}`);
1072
- if (config.crons) logger$9.log(`Loading crons from: ${config.crons}`);
1073
- if (config.subscribers) logger$9.log(`Loading subscribers from: ${config.subscribers}`);
1074
- logger$9.log(`Using envParser: ${config.envParser}`);
1071
+ logger$11.log("🚀 Starting development server...");
1072
+ logger$11.log(`Loading routes from: ${config.routes}`);
1073
+ if (config.functions) logger$11.log(`Loading functions from: ${config.functions}`);
1074
+ if (config.crons) logger$11.log(`Loading crons from: ${config.crons}`);
1075
+ if (config.subscribers) logger$11.log(`Loading subscribers from: ${config.subscribers}`);
1076
+ logger$11.log(`Using envParser: ${config.envParser}`);
1075
1077
  const { path: envParserPath, importPattern: envParserImportPattern } = require_config.parseModuleConfig(config.envParser, "envParser");
1076
1078
  const { path: loggerPath, importPattern: loggerImportPattern } = require_config.parseModuleConfig(config.logger, "logger");
1077
1079
  const telescope = normalizeTelescopeConfig(config.telescope);
1078
- if (telescope) logger$9.log(`🔭 Telescope enabled at ${telescope.path}`);
1080
+ if (telescope) logger$11.log(`🔭 Telescope enabled at ${telescope.path}`);
1079
1081
  const studio = normalizeStudioConfig(config.studio);
1080
- if (studio) logger$9.log(`🗄️ Studio enabled at ${studio.path}`);
1082
+ if (studio) logger$11.log(`🗄️ Studio enabled at ${studio.path}`);
1081
1083
  const hooks = normalizeHooksConfig(config.hooks, appRoot);
1082
- if (hooks) logger$9.log(`🪝 Server hooks enabled from ${config.hooks?.server}`);
1084
+ if (hooks) logger$11.log(`🪝 Server hooks enabled from ${config.hooks?.server}`);
1083
1085
  const openApiConfig = require_openapi.resolveOpenApiConfig(config);
1084
1086
  const enableOpenApi = openApiConfig.enabled || resolved.enableOpenApi;
1085
- if (enableOpenApi) logger$9.log(`📄 OpenAPI output: ${require_openapi.OPENAPI_OUTPUT_PATH}`);
1087
+ if (enableOpenApi) logger$11.log(`📄 OpenAPI output: ${require_openapi.OPENAPI_OUTPUT_PATH}`);
1086
1088
  const buildContext = {
1087
1089
  envParserPath,
1088
1090
  envParserImportPattern,
@@ -1102,7 +1104,7 @@ async function devCommand(options) {
1102
1104
  await (0, node_fs_promises.mkdir)(secretsDir, { recursive: true });
1103
1105
  secretsJsonPath = (0, node_path.join)(secretsDir, "dev-secrets.json");
1104
1106
  await (0, node_fs_promises.writeFile)(secretsJsonPath, JSON.stringify(appSecrets, null, 2));
1105
- logger$9.log(`🔐 Loaded ${Object.keys(appSecrets).length} secret(s)`);
1107
+ logger$11.log(`🔐 Loaded ${Object.keys(appSecrets).length} secret(s)`);
1106
1108
  }
1107
1109
  const devServer = new DevServer(resolved.providers[0], options.port ?? workspaceAppPort ?? 3e3, options.portExplicit ?? false, enableOpenApi, telescope, studio, runtime, appRoot, secretsJsonPath);
1108
1110
  await devServer.start();
@@ -1120,7 +1122,7 @@ async function devCommand(options) {
1120
1122
  ...hooksFile ? [hooksFile.endsWith(".ts") ? hooksFile : `${hooksFile}.ts`] : []
1121
1123
  ].flat().filter((p) => typeof p === "string");
1122
1124
  const normalizedPatterns = watchPatterns.map((p) => p.startsWith("./") ? p.slice(2) : p);
1123
- logger$9.log(`👀 Watching for changes in: ${normalizedPatterns.join(", ")}`);
1125
+ logger$11.log(`👀 Watching for changes in: ${normalizedPatterns.join(", ")}`);
1124
1126
  const resolvedFiles = await (0, fast_glob.default)(normalizedPatterns, {
1125
1127
  cwd: appRoot,
1126
1128
  absolute: false,
@@ -1130,7 +1132,7 @@ async function devCommand(options) {
1130
1132
  const parts = f.split("/");
1131
1133
  return parts.slice(0, -1).join("/");
1132
1134
  }))];
1133
- logger$9.log(`📁 Found ${resolvedFiles.length} files in ${dirsToWatch.length} directories`);
1135
+ logger$11.log(`📁 Found ${resolvedFiles.length} files in ${dirsToWatch.length} directories`);
1134
1136
  const watcher = chokidar.default.watch([...resolvedFiles, ...dirsToWatch], {
1135
1137
  ignored: /(^|[/\\])\../,
1136
1138
  persistent: true,
@@ -1138,27 +1140,27 @@ async function devCommand(options) {
1138
1140
  cwd: appRoot
1139
1141
  });
1140
1142
  watcher.on("ready", () => {
1141
- logger$9.log("🔍 File watcher ready");
1143
+ logger$11.log("🔍 File watcher ready");
1142
1144
  });
1143
1145
  watcher.on("error", (error) => {
1144
- logger$9.error("❌ Watcher error:", error);
1146
+ logger$11.error("❌ Watcher error:", error);
1145
1147
  });
1146
1148
  let rebuildTimeout = null;
1147
1149
  watcher.on("change", async (path) => {
1148
- logger$9.log(`📝 File changed: ${path}`);
1150
+ logger$11.log(`📝 File changed: ${path}`);
1149
1151
  if (rebuildTimeout) clearTimeout(rebuildTimeout);
1150
1152
  rebuildTimeout = setTimeout(async () => {
1151
1153
  try {
1152
- logger$9.log("🔄 Rebuilding...");
1154
+ logger$11.log("🔄 Rebuilding...");
1153
1155
  await buildServer(config, buildContext, resolved.providers[0], enableOpenApi, appRoot, true);
1154
1156
  if (enableOpenApi) await require_openapi.generateOpenApi(config, {
1155
1157
  silent: true,
1156
1158
  bustCache: true
1157
1159
  });
1158
- logger$9.log("✅ Rebuild complete, restarting server...");
1160
+ logger$11.log("✅ Rebuild complete, restarting server...");
1159
1161
  await devServer.restart();
1160
1162
  } catch (error) {
1161
- logger$9.error("❌ Rebuild failed:", error.message);
1163
+ logger$11.error("❌ Rebuild failed:", error.message);
1162
1164
  }
1163
1165
  }, 300);
1164
1166
  });
@@ -1166,9 +1168,9 @@ async function devCommand(options) {
1166
1168
  const shutdown = () => {
1167
1169
  if (isShuttingDown) return;
1168
1170
  isShuttingDown = true;
1169
- logger$9.log("\n🛑 Shutting down...");
1171
+ logger$11.log("\n🛑 Shutting down...");
1170
1172
  Promise.all([watcher.close(), devServer.stop()]).catch((err) => {
1171
- logger$9.error("Error during shutdown:", err);
1173
+ logger$11.error("Error during shutdown:", err);
1172
1174
  }).finally(() => {
1173
1175
  process.exit(0);
1174
1176
  });
@@ -1271,11 +1273,11 @@ async function loadDevSecrets(workspace) {
1271
1273
  for (const stage of stages) if (require_storage.secretsExist(stage, workspace.root)) {
1272
1274
  const secrets = await require_storage.readStageSecrets(stage, workspace.root);
1273
1275
  if (secrets) {
1274
- logger$9.log(`🔐 Loading secrets from stage: ${stage}`);
1276
+ logger$11.log(`🔐 Loading secrets from stage: ${stage}`);
1275
1277
  return require_storage.toEmbeddableSecrets(secrets);
1276
1278
  }
1277
1279
  }
1278
- logger$9.warn("⚠️ Secrets enabled but no dev/development secrets found. Run \"gkm secrets:init --stage dev\"");
1280
+ logger$11.warn("⚠️ Secrets enabled but no dev/development secrets found. Run \"gkm setup\" to initialize your development environment");
1279
1281
  return {};
1280
1282
  }
1281
1283
  /**
@@ -1290,7 +1292,7 @@ async function loadSecretsForApp(secretsRoot, appName) {
1290
1292
  for (const stage of stages) if (require_storage.secretsExist(stage, secretsRoot)) {
1291
1293
  const stageSecrets = await require_storage.readStageSecrets(stage, secretsRoot);
1292
1294
  if (stageSecrets) {
1293
- logger$9.log(`🔐 Loading secrets from stage: ${stage}`);
1295
+ logger$11.log(`🔐 Loading secrets from stage: ${stage}`);
1294
1296
  secrets = require_storage.toEmbeddableSecrets(stageSecrets);
1295
1297
  break;
1296
1298
  }
@@ -1315,11 +1317,11 @@ async function startWorkspaceServices(workspace, portEnv) {
1315
1317
  if (services.cache) servicesToStart.push("redis");
1316
1318
  if (services.mail) servicesToStart.push("mailpit");
1317
1319
  if (servicesToStart.length === 0) return;
1318
- logger$9.log(`🐳 Starting services: ${servicesToStart.join(", ")}`);
1320
+ logger$11.log(`🐳 Starting services: ${servicesToStart.join(", ")}`);
1319
1321
  try {
1320
1322
  const composeFile = (0, node_path.join)(workspace.root, "docker-compose.yml");
1321
1323
  if (!(0, node_fs.existsSync)(composeFile)) {
1322
- logger$9.warn("⚠️ No docker-compose.yml found. Services will not be started.");
1324
+ logger$11.warn("⚠️ No docker-compose.yml found. Services will not be started.");
1323
1325
  return;
1324
1326
  }
1325
1327
  (0, node_child_process.execSync)(`docker compose up -d ${servicesToStart.join(" ")}`, {
@@ -1330,9 +1332,9 @@ async function startWorkspaceServices(workspace, portEnv) {
1330
1332
  ...portEnv
1331
1333
  }
1332
1334
  });
1333
- logger$9.log("✅ Services started");
1335
+ logger$11.log("✅ Services started");
1334
1336
  } catch (error) {
1335
- logger$9.error("❌ Failed to start services:", error.message);
1337
+ logger$11.error("❌ Failed to start services:", error.message);
1336
1338
  throw error;
1337
1339
  }
1338
1340
  }
@@ -1349,41 +1351,41 @@ async function workspaceDevCommand(workspace, options) {
1349
1351
  const appCount = Object.keys(workspace.apps).length;
1350
1352
  const backendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "backend");
1351
1353
  const frontendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "frontend");
1352
- logger$9.log(`\n🚀 Starting workspace: ${workspace.name}`);
1353
- logger$9.log(` ${backendApps.length} backend app(s), ${frontendApps.length} frontend app(s)`);
1354
+ logger$11.log(`\n🚀 Starting workspace: ${workspace.name}`);
1355
+ logger$11.log(` ${backendApps.length} backend app(s), ${frontendApps.length} frontend app(s)`);
1354
1356
  const conflicts = checkPortConflicts(workspace);
1355
1357
  if (conflicts.length > 0) {
1356
- for (const conflict of conflicts) logger$9.error(`❌ Port conflict: Apps "${conflict.app1}" and "${conflict.app2}" both use port ${conflict.port}`);
1358
+ for (const conflict of conflicts) logger$11.error(`❌ Port conflict: Apps "${conflict.app1}" and "${conflict.app2}" both use port ${conflict.port}`);
1357
1359
  throw new Error("Port conflicts detected. Please assign unique ports to each app.");
1358
1360
  }
1359
1361
  if (frontendApps.length > 0) {
1360
- logger$9.log("\n🔍 Validating frontend apps...");
1362
+ logger$11.log("\n🔍 Validating frontend apps...");
1361
1363
  const validationResults = await validateFrontendApps(workspace);
1362
1364
  let hasErrors = false;
1363
1365
  for (const result of validationResults) {
1364
1366
  if (!result.valid) {
1365
1367
  hasErrors = true;
1366
- logger$9.error(`\n❌ Frontend app "${result.appName}" validation failed:`);
1367
- for (const error of result.errors) logger$9.error(` • ${error}`);
1368
+ logger$11.error(`\n❌ Frontend app "${result.appName}" validation failed:`);
1369
+ for (const error of result.errors) logger$11.error(` • ${error}`);
1368
1370
  }
1369
- for (const warning of result.warnings) logger$9.warn(` ⚠️ ${result.appName}: ${warning}`);
1371
+ for (const warning of result.warnings) logger$11.warn(` ⚠️ ${result.appName}: ${warning}`);
1370
1372
  }
1371
1373
  if (hasErrors) throw new Error("Frontend app validation failed. Fix the issues above and try again.");
1372
- logger$9.log("✅ Frontend apps validated");
1374
+ logger$11.log("✅ Frontend apps validated");
1373
1375
  }
1374
1376
  if (frontendApps.length > 0 && backendApps.length > 0) {
1375
1377
  const clientResults = await copyAllClients(workspace);
1376
1378
  const copiedCount = clientResults.filter((r) => r.success).length;
1377
- if (copiedCount > 0) logger$9.log(`\n📦 Copied ${copiedCount} API client(s)`);
1379
+ if (copiedCount > 0) logger$11.log(`\n📦 Copied ${copiedCount} API client(s)`);
1378
1380
  }
1379
1381
  const resolvedPorts = await resolveServicePorts(workspace.root);
1380
1382
  await startWorkspaceServices(workspace, resolvedPorts.dockerEnv);
1381
1383
  const secretsEnv = rewriteUrlsWithPorts(await loadDevSecrets(workspace), resolvedPorts);
1382
- if (Object.keys(secretsEnv).length > 0) logger$9.log(` Loaded ${Object.keys(secretsEnv).length} secret(s)`);
1384
+ if (Object.keys(secretsEnv).length > 0) logger$11.log(` Loaded ${Object.keys(secretsEnv).length} secret(s)`);
1383
1385
  const dependencyEnv = generateAllDependencyEnvVars(workspace);
1384
1386
  if (Object.keys(dependencyEnv).length > 0) {
1385
- logger$9.log("📡 Dependency URLs:");
1386
- for (const [key, value] of Object.entries(dependencyEnv)) logger$9.log(` ${key}=${value}`);
1387
+ logger$11.log("📡 Dependency URLs:");
1388
+ for (const [key, value] of Object.entries(dependencyEnv)) logger$11.log(` ${key}=${value}`);
1387
1389
  }
1388
1390
  let turboFilter = [];
1389
1391
  if (options.app) {
@@ -1392,18 +1394,18 @@ async function workspaceDevCommand(workspace, options) {
1392
1394
  throw new Error(`App "${options.app}" not found. Available apps: ${appNames}`);
1393
1395
  }
1394
1396
  turboFilter = ["--filter", options.app];
1395
- logger$9.log(`\n🎯 Running single app: ${options.app}`);
1397
+ logger$11.log(`\n🎯 Running single app: ${options.app}`);
1396
1398
  } else if (options.filter) {
1397
1399
  turboFilter = ["--filter", options.filter];
1398
- logger$9.log(`\n🔍 Using filter: ${options.filter}`);
1399
- } else logger$9.log(`\n🎯 Running all ${appCount} apps`);
1400
+ logger$11.log(`\n🔍 Using filter: ${options.filter}`);
1401
+ } else logger$11.log(`\n🎯 Running all ${appCount} apps`);
1400
1402
  const buildOrder = require_workspace.getAppBuildOrder(workspace);
1401
- logger$9.log("\n📋 Apps (in dependency order):");
1403
+ logger$11.log("\n📋 Apps (in dependency order):");
1402
1404
  for (const appName of buildOrder) {
1403
1405
  const app = workspace.apps[appName];
1404
1406
  if (!app) continue;
1405
1407
  const deps = app.dependencies.length > 0 ? ` (depends on: ${app.dependencies.join(", ")})` : "";
1406
- logger$9.log(` ${app.type === "backend" ? "🔧" : "🌐"} ${appName} → http://localhost:${app.port}${deps}`);
1408
+ logger$11.log(` ${app.type === "backend" ? "🔧" : "🌐"} ${appName} → http://localhost:${app.port}${deps}`);
1407
1409
  }
1408
1410
  const configFiles = [
1409
1411
  "gkm.config.ts",
@@ -1425,7 +1427,7 @@ async function workspaceDevCommand(workspace, options) {
1425
1427
  NODE_ENV: "development",
1426
1428
  ...configPath ? { GKM_CONFIG_PATH: configPath } : {}
1427
1429
  };
1428
- logger$9.log("\n🏃 Starting turbo run dev...\n");
1430
+ logger$11.log("\n🏃 Starting turbo run dev...\n");
1429
1431
  const turboProcess = (0, node_child_process.spawn)("pnpm", [
1430
1432
  "turbo",
1431
1433
  "run",
@@ -1447,7 +1449,7 @@ async function workspaceDevCommand(workspace, options) {
1447
1449
  });
1448
1450
  }
1449
1451
  if (openApiPaths.length > 0) {
1450
- logger$9.log(`\n👀 Watching ${openApiPaths.length} backend OpenAPI spec(s) for changes`);
1452
+ logger$11.log(`\n👀 Watching ${openApiPaths.length} backend OpenAPI spec(s) for changes`);
1451
1453
  const pathToApp = new Map(openApiPaths.map((p) => [p.path, p.appName]));
1452
1454
  openApiWatcher = chokidar.default.watch(openApiPaths.map((p) => p.path), {
1453
1455
  persistent: true,
@@ -1460,13 +1462,13 @@ async function workspaceDevCommand(workspace, options) {
1460
1462
  copyTimeout = setTimeout(async () => {
1461
1463
  const backendAppName = pathToApp.get(changedPath);
1462
1464
  if (!backendAppName) return;
1463
- logger$9.log(`\n🔄 OpenAPI spec changed for ${backendAppName}`);
1465
+ logger$11.log(`\n🔄 OpenAPI spec changed for ${backendAppName}`);
1464
1466
  try {
1465
1467
  const results = await copyClientToFrontends(workspace, backendAppName, { silent: true });
1466
- for (const result of results) if (result.success) logger$9.log(` 📦 Copied client to ${result.frontendApp} (${result.endpointCount} endpoints)`);
1467
- else if (result.error) logger$9.error(` ❌ Failed to copy client to ${result.frontendApp}: ${result.error}`);
1468
+ for (const result of results) if (result.success) logger$11.log(` 📦 Copied client to ${result.frontendApp} (${result.endpointCount} endpoints)`);
1469
+ else if (result.error) logger$11.error(` ❌ Failed to copy client to ${result.frontendApp}: ${result.error}`);
1468
1470
  } catch (error) {
1469
- logger$9.error(` ❌ Failed to copy clients: ${error.message}`);
1471
+ logger$11.error(` ❌ Failed to copy clients: ${error.message}`);
1470
1472
  }
1471
1473
  }, 200);
1472
1474
  };
@@ -1478,7 +1480,7 @@ async function workspaceDevCommand(workspace, options) {
1478
1480
  const shutdown = () => {
1479
1481
  if (isShuttingDown) return;
1480
1482
  isShuttingDown = true;
1481
- logger$9.log("\n🛑 Shutting down workspace...");
1483
+ logger$11.log("\n🛑 Shutting down workspace...");
1482
1484
  if (openApiWatcher) openApiWatcher.close().catch(() => {});
1483
1485
  if (turboProcess.pid) try {
1484
1486
  process.kill(-turboProcess.pid, "SIGTERM");
@@ -1493,7 +1495,7 @@ async function workspaceDevCommand(workspace, options) {
1493
1495
  process.on("SIGTERM", shutdown);
1494
1496
  return new Promise((resolve$3, reject) => {
1495
1497
  turboProcess.on("error", (error) => {
1496
- logger$9.error("❌ Turbo error:", error);
1498
+ logger$11.error("❌ Turbo error:", error);
1497
1499
  reject(error);
1498
1500
  });
1499
1501
  turboProcess.on("exit", (code) => {
@@ -1606,7 +1608,7 @@ async function prepareEntryCredentials(options) {
1606
1608
  secretsRoot = appInfo.workspaceRoot;
1607
1609
  appName = appInfo.appName;
1608
1610
  } catch (error) {
1609
- logger$9.log(`⚠️ Could not load workspace config: ${error.message}`);
1611
+ logger$11.log(`⚠️ Could not load workspace config: ${error.message}`);
1610
1612
  secretsRoot = findSecretsRoot(cwd);
1611
1613
  appName = require_config.getAppNameFromCwd(cwd) ?? void 0;
1612
1614
  }
@@ -1636,11 +1638,11 @@ async function entryDevCommand(options) {
1636
1638
  const entryPath = (0, node_path.resolve)(process.cwd(), entry);
1637
1639
  if (!(0, node_fs.existsSync)(entryPath)) throw new Error(`Entry file not found: ${entryPath}`);
1638
1640
  const defaultEnv = loadEnvFiles(".env");
1639
- if (defaultEnv.loaded.length > 0) logger$9.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1641
+ if (defaultEnv.loaded.length > 0) logger$11.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1640
1642
  const { credentials, resolvedPort, secretsJsonPath, appName } = await prepareEntryCredentials({ explicitPort: options.portExplicit ? options.port : void 0 });
1641
- if (appName) logger$9.log(`📦 App: ${appName} (port ${resolvedPort})`);
1642
- logger$9.log(`🚀 Starting entry file: ${entry} on port ${resolvedPort}`);
1643
- if (Object.keys(credentials).length > 1) logger$9.log(`🔐 Loaded ${Object.keys(credentials).length - 1} secret(s) + PORT`);
1643
+ if (appName) logger$11.log(`📦 App: ${appName} (port ${resolvedPort})`);
1644
+ logger$11.log(`🚀 Starting entry file: ${entry} on port ${resolvedPort}`);
1645
+ if (Object.keys(credentials).length > 1) logger$11.log(`🔐 Loaded ${Object.keys(credentials).length - 1} secret(s) + PORT`);
1644
1646
  const wrapperDir = (0, node_path.join)(process.cwd(), ".gkm");
1645
1647
  await (0, node_fs_promises.mkdir)(wrapperDir, { recursive: true });
1646
1648
  const wrapperPath = (0, node_path.join)(wrapperDir, "entry-wrapper.ts");
@@ -1651,7 +1653,7 @@ async function entryDevCommand(options) {
1651
1653
  const shutdown = () => {
1652
1654
  if (isShuttingDown) return;
1653
1655
  isShuttingDown = true;
1654
- logger$9.log("\n🛑 Shutting down...");
1656
+ logger$11.log("\n🛑 Shutting down...");
1655
1657
  runner.stop();
1656
1658
  process.exit(0);
1657
1659
  };
@@ -1683,14 +1685,14 @@ var EntryRunner = class {
1683
1685
  });
1684
1686
  let restartTimeout = null;
1685
1687
  this.watcher.on("change", (path) => {
1686
- logger$9.log(`📝 File changed: ${path}`);
1688
+ logger$11.log(`📝 File changed: ${path}`);
1687
1689
  if (restartTimeout) clearTimeout(restartTimeout);
1688
1690
  restartTimeout = setTimeout(async () => {
1689
- logger$9.log("🔄 Restarting...");
1691
+ logger$11.log("🔄 Restarting...");
1690
1692
  await this.restart();
1691
1693
  }, 300);
1692
1694
  });
1693
- logger$9.log(`👀 Watching for changes in: ${watchDir}`);
1695
+ logger$11.log(`👀 Watching for changes in: ${watchDir}`);
1694
1696
  }
1695
1697
  }
1696
1698
  async runProcess() {
@@ -1705,14 +1707,14 @@ var EntryRunner = class {
1705
1707
  });
1706
1708
  this.isRunning = true;
1707
1709
  this.childProcess.on("error", (error) => {
1708
- logger$9.error("❌ Process error:", error);
1710
+ logger$11.error("❌ Process error:", error);
1709
1711
  });
1710
1712
  this.childProcess.on("exit", (code) => {
1711
- if (code !== null && code !== 0 && code !== 143) logger$9.error(`❌ Process exited with code ${code}`);
1713
+ if (code !== null && code !== 0 && code !== 143) logger$11.error(`❌ Process exited with code ${code}`);
1712
1714
  this.isRunning = false;
1713
1715
  });
1714
1716
  await new Promise((resolve$3) => setTimeout(resolve$3, 500));
1715
- if (this.isRunning) logger$9.log(`\n🎉 Running at http://localhost:${this.port}`);
1717
+ if (this.isRunning) logger$11.log(`\n🎉 Running at http://localhost:${this.port}`);
1716
1718
  }
1717
1719
  async restart() {
1718
1720
  this.stopProcess();
@@ -1762,11 +1764,11 @@ var DevServer = class {
1762
1764
  this.actualPort = this.requestedPort;
1763
1765
  } else {
1764
1766
  this.actualPort = await findAvailablePort(this.requestedPort);
1765
- if (this.actualPort !== this.requestedPort) logger$9.log(`ℹ️ Port ${this.requestedPort} was in use, using port ${this.actualPort} instead`);
1767
+ if (this.actualPort !== this.requestedPort) logger$11.log(`ℹ️ Port ${this.requestedPort} was in use, using port ${this.actualPort} instead`);
1766
1768
  }
1767
1769
  const serverEntryPath = (0, node_path.join)(this.appRoot, ".gkm", this.provider, "server.ts");
1768
1770
  await this.createServerEntry();
1769
- logger$9.log(`\n✨ Starting server on port ${this.actualPort}...`);
1771
+ logger$11.log(`\n✨ Starting server on port ${this.actualPort}...`);
1770
1772
  this.serverProcess = (0, node_child_process.spawn)("npx", [
1771
1773
  "tsx",
1772
1774
  serverEntryPath,
@@ -1782,18 +1784,18 @@ var DevServer = class {
1782
1784
  });
1783
1785
  this.isRunning = true;
1784
1786
  this.serverProcess.on("error", (error) => {
1785
- logger$9.error("❌ Server error:", error);
1787
+ logger$11.error("❌ Server error:", error);
1786
1788
  });
1787
1789
  this.serverProcess.on("exit", (code, signal) => {
1788
- if (code !== null && code !== 0 && signal !== "SIGTERM") logger$9.error(`❌ Server exited with code ${code}`);
1790
+ if (code !== null && code !== 0 && signal !== "SIGTERM") logger$11.error(`❌ Server exited with code ${code}`);
1789
1791
  this.isRunning = false;
1790
1792
  });
1791
1793
  await new Promise((resolve$3) => setTimeout(resolve$3, 1e3));
1792
1794
  if (this.isRunning) {
1793
- logger$9.log(`\n🎉 Server running at http://localhost:${this.actualPort}`);
1794
- if (this.enableOpenApi) logger$9.log(`📚 API Docs available at http://localhost:${this.actualPort}/__docs`);
1795
- if (this.telescope) logger$9.log(`🔭 Telescope available at http://localhost:${this.actualPort}${this.telescope.path}`);
1796
- if (this.studio) logger$9.log(`🗄️ Studio available at http://localhost:${this.actualPort}${this.studio.path}`);
1795
+ logger$11.log(`\n🎉 Server running at http://localhost:${this.actualPort}`);
1796
+ if (this.enableOpenApi) logger$11.log(`📚 API Docs available at http://localhost:${this.actualPort}/__docs`);
1797
+ if (this.telescope) logger$11.log(`🔭 Telescope available at http://localhost:${this.actualPort}${this.telescope.path}`);
1798
+ if (this.studio) logger$11.log(`🗄️ Studio available at http://localhost:${this.actualPort}${this.studio.path}`);
1797
1799
  }
1798
1800
  }
1799
1801
  async stop() {
@@ -1831,9 +1833,9 @@ var DevServer = class {
1831
1833
  }
1832
1834
  async createServerEntry() {
1833
1835
  const { writeFile: fsWriteFile } = await import("node:fs/promises");
1834
- const { relative: relative$6, dirname: dirname$9 } = await import("node:path");
1836
+ const { relative: relative$6, dirname: dirname$11 } = await import("node:path");
1835
1837
  const serverPath = (0, node_path.join)(this.appRoot, ".gkm", this.provider, "server.ts");
1836
- const relativeAppPath = relative$6(dirname$9(serverPath), (0, node_path.join)(dirname$9(serverPath), "app.js"));
1838
+ const relativeAppPath = relative$6(dirname$11(serverPath), (0, node_path.join)(dirname$11(serverPath), "app.js"));
1837
1839
  const credentialsInjection = this.secretsJsonPath ? `import { Credentials } from '@geekmidas/envkit/credentials';
1838
1840
  import { existsSync, readFileSync } from 'node:fs';
1839
1841
 
@@ -1901,11 +1903,11 @@ async function execCommand(commandArgs, options = {}) {
1901
1903
  const cwd = options.cwd ?? process.cwd();
1902
1904
  if (commandArgs.length === 0) throw new Error("No command specified. Usage: gkm exec -- <command>");
1903
1905
  const defaultEnv = loadEnvFiles(".env");
1904
- if (defaultEnv.loaded.length > 0) logger$9.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1906
+ if (defaultEnv.loaded.length > 0) logger$11.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1905
1907
  const { credentials, secretsJsonPath, appName, secretsRoot } = await prepareEntryCredentials({ cwd });
1906
- if (appName) logger$9.log(`📦 App: ${appName}`);
1908
+ if (appName) logger$11.log(`📦 App: ${appName}`);
1907
1909
  const secretCount = Object.keys(credentials).filter((k) => k !== "PORT").length;
1908
- if (secretCount > 0) logger$9.log(`🔐 Loaded ${secretCount} secret(s)`);
1910
+ if (secretCount > 0) logger$11.log(`🔐 Loaded ${secretCount} secret(s)`);
1909
1911
  const composePath = (0, node_path.join)(secretsRoot, "docker-compose.yml");
1910
1912
  const mappings = parseComposePortMappings(composePath);
1911
1913
  if (mappings.length > 0) {
@@ -1917,7 +1919,7 @@ async function execCommand(commandArgs, options = {}) {
1917
1919
  mappings
1918
1920
  });
1919
1921
  Object.assign(credentials, rewritten);
1920
- logger$9.log(`🔌 Applied ${Object.keys(ports).length} port mapping(s)`);
1922
+ logger$11.log(`🔌 Applied ${Object.keys(ports).length} port mapping(s)`);
1921
1923
  }
1922
1924
  }
1923
1925
  try {
@@ -1934,7 +1936,7 @@ async function execCommand(commandArgs, options = {}) {
1934
1936
  const [cmd, ...rawArgs] = commandArgs;
1935
1937
  if (!cmd) throw new Error("No command specified");
1936
1938
  const args = rawArgs.map((arg) => arg.replace(/\$PORT\b/g, credentials.PORT ?? "3000"));
1937
- logger$9.log(`🚀 Running: ${[cmd, ...args].join(" ")}`);
1939
+ logger$11.log(`🚀 Running: ${[cmd, ...args].join(" ")}`);
1938
1940
  const existingNodeOptions = process.env.NODE_OPTIONS ?? "";
1939
1941
  const tsxImport = "--import=tsx";
1940
1942
  const preloadImport = `--import=${preloadPath}`;
@@ -1955,7 +1957,7 @@ async function execCommand(commandArgs, options = {}) {
1955
1957
  const exitCode = await new Promise((resolve$3) => {
1956
1958
  child.on("close", (code) => resolve$3(code ?? 0));
1957
1959
  child.on("error", (error) => {
1958
- logger$9.error(`Failed to run command: ${error.message}`);
1960
+ logger$11.error(`Failed to run command: ${error.message}`);
1959
1961
  resolve$3(1);
1960
1962
  });
1961
1963
  });
@@ -1964,7 +1966,7 @@ async function execCommand(commandArgs, options = {}) {
1964
1966
 
1965
1967
  //#endregion
1966
1968
  //#region src/build/manifests.ts
1967
- const logger$8 = console;
1969
+ const logger$10 = console;
1968
1970
  async function generateAwsManifest(outputDir, routes, functions, crons, subscribers) {
1969
1971
  const manifestDir = (0, node_path.join)(outputDir, "manifest");
1970
1972
  await (0, node_fs_promises.mkdir)(manifestDir, { recursive: true });
@@ -1989,8 +1991,8 @@ export type RoutePath = Route['path'];
1989
1991
  `;
1990
1992
  const manifestPath = (0, node_path.join)(manifestDir, "aws.ts");
1991
1993
  await (0, node_fs_promises.writeFile)(manifestPath, content);
1992
- logger$8.log(`Generated AWS manifest with ${awsRoutes.length} routes, ${functions.length} functions, ${crons.length} crons, ${subscribers.length} subscribers`);
1993
- logger$8.log(`Manifest: ${(0, node_path.relative)(process.cwd(), manifestPath)}`);
1994
+ logger$10.log(`Generated AWS manifest with ${awsRoutes.length} routes, ${functions.length} functions, ${crons.length} crons, ${subscribers.length} subscribers`);
1995
+ logger$10.log(`Manifest: ${(0, node_path.relative)(process.cwd(), manifestPath)}`);
1994
1996
  }
1995
1997
  async function generateServerManifest(outputDir, appInfo, routes, subscribers) {
1996
1998
  const manifestDir = (0, node_path.join)(outputDir, "manifest");
@@ -2021,13 +2023,13 @@ export type RoutePath = Route['path'];
2021
2023
  `;
2022
2024
  const manifestPath = (0, node_path.join)(manifestDir, "server.ts");
2023
2025
  await (0, node_fs_promises.writeFile)(manifestPath, content);
2024
- logger$8.log(`Generated server manifest with ${serverRoutes.length} routes, ${serverSubscribers.length} subscribers`);
2025
- logger$8.log(`Manifest: ${(0, node_path.relative)(process.cwd(), manifestPath)}`);
2026
+ logger$10.log(`Generated server manifest with ${serverRoutes.length} routes, ${serverSubscribers.length} subscribers`);
2027
+ logger$10.log(`Manifest: ${(0, node_path.relative)(process.cwd(), manifestPath)}`);
2026
2028
  }
2027
2029
 
2028
2030
  //#endregion
2029
2031
  //#region src/build/index.ts
2030
- const logger$7 = console;
2032
+ const logger$9 = console;
2031
2033
  async function buildCommand(options) {
2032
2034
  const loadedConfig = await require_config.loadWorkspaceConfig();
2033
2035
  if (loadedConfig.type === "workspace") {
@@ -2035,7 +2037,7 @@ async function buildCommand(options) {
2035
2037
  const workspaceRoot = (0, node_path.resolve)(loadedConfig.workspace.root);
2036
2038
  const isAtWorkspaceRoot = cwd === workspaceRoot;
2037
2039
  if (isAtWorkspaceRoot) {
2038
- logger$7.log("📦 Detected workspace configuration");
2040
+ logger$9.log("📦 Detected workspace configuration");
2039
2041
  return workspaceBuildCommand(loadedConfig.workspace, options);
2040
2042
  }
2041
2043
  }
@@ -2043,21 +2045,21 @@ async function buildCommand(options) {
2043
2045
  const resolved = resolveProviders(config, options);
2044
2046
  const productionConfigFromGkm = getProductionConfigFromGkm(config);
2045
2047
  const production = normalizeProductionConfig(options.production ?? false, productionConfigFromGkm);
2046
- if (production) logger$7.log(`🏭 Building for PRODUCTION`);
2047
- logger$7.log(`Building with providers: ${resolved.providers.join(", ")}`);
2048
- logger$7.log(`Loading routes from: ${config.routes}`);
2049
- if (config.functions) logger$7.log(`Loading functions from: ${config.functions}`);
2050
- if (config.crons) logger$7.log(`Loading crons from: ${config.crons}`);
2051
- if (config.subscribers) logger$7.log(`Loading subscribers from: ${config.subscribers}`);
2052
- logger$7.log(`Using envParser: ${config.envParser}`);
2048
+ if (production) logger$9.log(`🏭 Building for PRODUCTION`);
2049
+ logger$9.log(`Building with providers: ${resolved.providers.join(", ")}`);
2050
+ logger$9.log(`Loading routes from: ${config.routes}`);
2051
+ if (config.functions) logger$9.log(`Loading functions from: ${config.functions}`);
2052
+ if (config.crons) logger$9.log(`Loading crons from: ${config.crons}`);
2053
+ if (config.subscribers) logger$9.log(`Loading subscribers from: ${config.subscribers}`);
2054
+ logger$9.log(`Using envParser: ${config.envParser}`);
2053
2055
  const { path: envParserPath, importPattern: envParserImportPattern } = require_config.parseModuleConfig(config.envParser, "envParser");
2054
2056
  const { path: loggerPath, importPattern: loggerImportPattern } = require_config.parseModuleConfig(config.logger, "logger");
2055
2057
  const telescope = production ? void 0 : normalizeTelescopeConfig(config.telescope);
2056
- if (telescope) logger$7.log(`🔭 Telescope enabled at ${telescope.path}`);
2058
+ if (telescope) logger$9.log(`🔭 Telescope enabled at ${telescope.path}`);
2057
2059
  const studio = production ? void 0 : normalizeStudioConfig(config.studio);
2058
- if (studio) logger$7.log(`🗄️ Studio enabled at ${studio.path}`);
2060
+ if (studio) logger$9.log(`🗄️ Studio enabled at ${studio.path}`);
2059
2061
  const hooks = normalizeHooksConfig(config.hooks);
2060
- if (hooks) logger$7.log(`🪝 Server hooks enabled`);
2062
+ if (hooks) logger$9.log(`🪝 Server hooks enabled`);
2061
2063
  const services = config.docker?.compose?.services;
2062
2064
  const dockerServices = services ? Array.isArray(services) ? {
2063
2065
  postgres: services.includes("postgres"),
@@ -2089,12 +2091,12 @@ async function buildCommand(options) {
2089
2091
  config.crons ? cronGenerator.load(config.crons) : [],
2090
2092
  config.subscribers ? subscriberGenerator.load(config.subscribers) : []
2091
2093
  ]);
2092
- logger$7.log(`Found ${allEndpoints.length} endpoints`);
2093
- logger$7.log(`Found ${allFunctions.length} functions`);
2094
- logger$7.log(`Found ${allCrons.length} crons`);
2095
- logger$7.log(`Found ${allSubscribers.length} subscribers`);
2094
+ logger$9.log(`Found ${allEndpoints.length} endpoints`);
2095
+ logger$9.log(`Found ${allFunctions.length} functions`);
2096
+ logger$9.log(`Found ${allCrons.length} crons`);
2097
+ logger$9.log(`Found ${allSubscribers.length} subscribers`);
2096
2098
  if (allEndpoints.length === 0 && allFunctions.length === 0 && allCrons.length === 0 && allSubscribers.length === 0) {
2097
- logger$7.log("No endpoints, functions, crons, or subscribers found to process");
2099
+ logger$9.log("No endpoints, functions, crons, or subscribers found to process");
2098
2100
  return {};
2099
2101
  }
2100
2102
  const rootOutputDir = (0, node_path.join)(process.cwd(), ".gkm");
@@ -2109,7 +2111,7 @@ async function buildCommand(options) {
2109
2111
  async function buildForProvider(provider, context, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, endpoints, functions, crons, subscribers, enableOpenApi, skipBundle, stage) {
2110
2112
  const outputDir = (0, node_path.join)(process.cwd(), ".gkm", provider);
2111
2113
  await (0, node_fs_promises.mkdir)(outputDir, { recursive: true });
2112
- logger$7.log(`\nGenerating handlers for provider: ${provider}`);
2114
+ logger$9.log(`\nGenerating handlers for provider: ${provider}`);
2113
2115
  const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all([
2114
2116
  endpointGenerator.build(context, endpoints, outputDir, {
2115
2117
  provider,
@@ -2119,7 +2121,7 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2119
2121
  cronGenerator.build(context, crons, outputDir, { provider }),
2120
2122
  subscriberGenerator.build(context, subscribers, outputDir, { provider })
2121
2123
  ]);
2122
- logger$7.log(`Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`);
2124
+ logger$9.log(`Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`);
2123
2125
  if (provider === "server") {
2124
2126
  const routeMetadata = await Promise.all(endpoints.map(async ({ construct }) => ({
2125
2127
  path: construct._path,
@@ -2134,8 +2136,8 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2134
2136
  await generateServerManifest(rootOutputDir, appInfo, routeMetadata, subscriberInfos);
2135
2137
  let masterKey;
2136
2138
  if (context.production?.bundle && !skipBundle) {
2137
- logger$7.log(`\n📦 Bundling production server...`);
2138
- const { bundleServer } = await Promise.resolve().then(() => require("./bundler-tHLLwYuU.cjs"));
2139
+ logger$9.log(`\n📦 Bundling production server...`);
2140
+ const { bundleServer } = await Promise.resolve().then(() => require("./bundler-CuMIfXw5.cjs"));
2139
2141
  const allConstructs = [
2140
2142
  ...endpoints.map((e) => e.construct),
2141
2143
  ...functions.map((f) => f.construct),
@@ -2154,10 +2156,10 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2154
2156
  dockerServices
2155
2157
  });
2156
2158
  masterKey = bundleResult.masterKey;
2157
- logger$7.log(`✅ Bundle complete: .gkm/server/dist/server.mjs`);
2159
+ logger$9.log(`✅ Bundle complete: .gkm/server/dist/server.mjs`);
2158
2160
  if (masterKey) {
2159
- logger$7.log(`\n🔐 Secrets encrypted for deployment`);
2160
- logger$7.log(` Deploy with: GKM_MASTER_KEY=${masterKey}`);
2161
+ logger$9.log(`\n🔐 Secrets encrypted for deployment`);
2162
+ logger$9.log(` Deploy with: GKM_MASTER_KEY=${masterKey}`);
2161
2163
  }
2162
2164
  }
2163
2165
  return { masterKey };
@@ -2194,17 +2196,17 @@ async function workspaceBuildCommand(workspace, options) {
2194
2196
  const apps = Object.entries(workspace.apps);
2195
2197
  const backendApps = apps.filter(([, app]) => app.type === "backend");
2196
2198
  const frontendApps = apps.filter(([, app]) => app.type === "frontend");
2197
- logger$7.log(`\n🏗️ Building workspace: ${workspace.name}`);
2198
- logger$7.log(` Backend apps: ${backendApps.map(([name$1]) => name$1).join(", ") || "none"}`);
2199
- logger$7.log(` Frontend apps: ${frontendApps.map(([name$1]) => name$1).join(", ") || "none"}`);
2200
- if (options.production) logger$7.log(` 🏭 Production mode enabled`);
2199
+ logger$9.log(`\n🏗️ Building workspace: ${workspace.name}`);
2200
+ logger$9.log(` Backend apps: ${backendApps.map(([name$1]) => name$1).join(", ") || "none"}`);
2201
+ logger$9.log(` Frontend apps: ${frontendApps.map(([name$1]) => name$1).join(", ") || "none"}`);
2202
+ if (options.production) logger$9.log(` 🏭 Production mode enabled`);
2201
2203
  const buildOrder = require_workspace.getAppBuildOrder(workspace);
2202
- logger$7.log(` Build order: ${buildOrder.join(" → ")}`);
2204
+ logger$9.log(` Build order: ${buildOrder.join(" → ")}`);
2203
2205
  const pm = detectPackageManager$2();
2204
- logger$7.log(`\n📦 Using ${pm} with Turbo for parallel builds...\n`);
2206
+ logger$9.log(`\n📦 Using ${pm} with Turbo for parallel builds...\n`);
2205
2207
  try {
2206
2208
  const turboCommand = getTurboCommand(pm);
2207
- logger$7.log(`Running: ${turboCommand}`);
2209
+ logger$9.log(`Running: ${turboCommand}`);
2208
2210
  await new Promise((resolve$3, reject) => {
2209
2211
  const child = (0, node_child_process.spawn)(turboCommand, {
2210
2212
  shell: true,
@@ -2232,15 +2234,15 @@ async function workspaceBuildCommand(workspace, options) {
2232
2234
  outputPath
2233
2235
  });
2234
2236
  }
2235
- logger$7.log(`\n✅ Workspace build complete!`);
2236
- logger$7.log(`\n📋 Build Summary:`);
2237
+ logger$9.log(`\n✅ Workspace build complete!`);
2238
+ logger$9.log(`\n📋 Build Summary:`);
2237
2239
  for (const result of results) {
2238
2240
  const icon = result.type === "backend" ? "⚙️" : "🌐";
2239
- logger$7.log(` ${icon} ${result.appName}: ${result.outputPath || "built"}`);
2241
+ logger$9.log(` ${icon} ${result.appName}: ${result.outputPath || "built"}`);
2240
2242
  }
2241
2243
  } catch (error) {
2242
2244
  const errorMessage = error instanceof Error ? error.message : "Build failed";
2243
- logger$7.log(`\n❌ Build failed: ${errorMessage}`);
2245
+ logger$9.log(`\n❌ Build failed: ${errorMessage}`);
2244
2246
  for (const [appName, app] of apps) results.push({
2245
2247
  appName,
2246
2248
  type: app.type,
@@ -2414,11 +2416,11 @@ async function createDnsProvider(options) {
2414
2416
  if (isDnsProvider(config.provider)) return config.provider;
2415
2417
  const provider = config.provider;
2416
2418
  if (provider === "hostinger") {
2417
- const { HostingerProvider } = await Promise.resolve().then(() => require("./HostingerProvider-BiXdHjiq.cjs"));
2419
+ const { HostingerProvider } = await Promise.resolve().then(() => require("./HostingerProvider-CEsQbmpY.cjs"));
2418
2420
  return new HostingerProvider();
2419
2421
  }
2420
2422
  if (provider === "route53") {
2421
- const { Route53Provider } = await Promise.resolve().then(() => require("./Route53Provider-kfJ77LmL.cjs"));
2423
+ const { Route53Provider } = await Promise.resolve().then(() => require("./Route53Provider-BqXeHzuc.cjs"));
2422
2424
  const route53Config = config;
2423
2425
  return new Route53Provider({
2424
2426
  region: route53Config.region,
@@ -2432,7 +2434,7 @@ async function createDnsProvider(options) {
2432
2434
 
2433
2435
  //#endregion
2434
2436
  //#region src/deploy/dns/index.ts
2435
- const logger$6 = console;
2437
+ const logger$8 = console;
2436
2438
  /**
2437
2439
  * Check if DNS config is legacy format (single domain with `domain` property)
2438
2440
  */
@@ -2469,7 +2471,7 @@ function groupHostnamesByDomain(appHostnames, dnsConfig) {
2469
2471
  for (const [appName, hostname] of appHostnames) {
2470
2472
  const rootDomain = findRootDomain(hostname, dnsConfig);
2471
2473
  if (!rootDomain) {
2472
- logger$6.log(` ⚠ No DNS config found for hostname: ${hostname}`);
2474
+ logger$8.log(` ⚠ No DNS config found for hostname: ${hostname}`);
2473
2475
  continue;
2474
2476
  }
2475
2477
  if (!grouped.has(rootDomain)) grouped.set(rootDomain, /* @__PURE__ */ new Map());
@@ -2521,10 +2523,10 @@ function generateRequiredRecords(appHostnames, rootDomain, serverIp) {
2521
2523
  * Print DNS records table
2522
2524
  */
2523
2525
  function printDnsRecordsTable(records, rootDomain) {
2524
- logger$6.log(`\n 📋 DNS Records for ${rootDomain}:`);
2525
- logger$6.log(" ┌─────────────────────────────────────┬──────┬─────────────────┬────────┐");
2526
- logger$6.log(" │ Subdomain │ Type │ Value │ Status │");
2527
- logger$6.log(" ├─────────────────────────────────────┼──────┼─────────────────┼────────┤");
2526
+ logger$8.log(`\n 📋 DNS Records for ${rootDomain}:`);
2527
+ logger$8.log(" ┌─────────────────────────────────────┬──────┬─────────────────┬────────┐");
2528
+ logger$8.log(" │ Subdomain │ Type │ Value │ Status │");
2529
+ logger$8.log(" ├─────────────────────────────────────┼──────┼─────────────────┼────────┤");
2528
2530
  for (const record of records) {
2529
2531
  const subdomain = record.subdomain.padEnd(35);
2530
2532
  const type$1 = record.type.padEnd(4);
@@ -2534,18 +2536,18 @@ function printDnsRecordsTable(records, rootDomain) {
2534
2536
  else if (record.created) status = "✓ new";
2535
2537
  else if (record.existed) status = "✓";
2536
2538
  else status = "?";
2537
- logger$6.log(` │ ${subdomain} │ ${type$1} │ ${value} │ ${status.padEnd(6)} │`);
2539
+ logger$8.log(` │ ${subdomain} │ ${type$1} │ ${value} │ ${status.padEnd(6)} │`);
2538
2540
  }
2539
- logger$6.log(" └─────────────────────────────────────┴──────┴─────────────────┴────────┘");
2541
+ logger$8.log(" └─────────────────────────────────────┴──────┴─────────────────┴────────┘");
2540
2542
  }
2541
2543
  /**
2542
2544
  * Print DNS records in a simple format for manual setup
2543
2545
  */
2544
2546
  function printDnsRecordsSimple(records, rootDomain) {
2545
- logger$6.log("\n 📋 Required DNS Records:");
2546
- logger$6.log(` Add these A records to your DNS provider (${rootDomain}):\n`);
2547
- for (const record of records) logger$6.log(` ${record.subdomain} → ${record.value} (A record)`);
2548
- logger$6.log("");
2547
+ logger$8.log("\n 📋 Required DNS Records:");
2548
+ logger$8.log(` Add these A records to your DNS provider (${rootDomain}):\n`);
2549
+ for (const record of records) logger$8.log(` ${record.subdomain} → ${record.value} (A record)`);
2550
+ logger$8.log("");
2549
2551
  }
2550
2552
  /**
2551
2553
  * Create DNS records for a single domain using its configured provider
@@ -2557,7 +2559,7 @@ async function createDnsRecordsForDomain(records, rootDomain, providerConfig) {
2557
2559
  provider = await createDnsProvider({ config: providerConfig });
2558
2560
  } catch (error) {
2559
2561
  const message = error instanceof Error ? error.message : "Unknown error";
2560
- logger$6.log(` ⚠ Failed to create DNS provider for ${rootDomain}: ${message}`);
2562
+ logger$8.log(` ⚠ Failed to create DNS provider for ${rootDomain}: ${message}`);
2561
2563
  return records.map((r) => ({
2562
2564
  ...r,
2563
2565
  error: message
@@ -2611,7 +2613,7 @@ async function createDnsRecordsForDomain(records, rootDomain, providerConfig) {
2611
2613
  }
2612
2614
  } catch (error) {
2613
2615
  const message = error instanceof Error ? error.message : "Unknown error";
2614
- logger$6.log(` ⚠ Failed to create DNS records for ${rootDomain}: ${message}`);
2616
+ logger$8.log(` ⚠ Failed to create DNS records for ${rootDomain}: ${message}`);
2615
2617
  return records.map((r) => ({
2616
2618
  hostname: r.hostname,
2617
2619
  subdomain: r.subdomain,
@@ -2638,20 +2640,20 @@ async function createDnsRecordsForDomain(records, rootDomain, providerConfig) {
2638
2640
  async function orchestrateDns(appHostnames, dnsConfig, dokployEndpoint, state) {
2639
2641
  if (!dnsConfig) return null;
2640
2642
  const normalizedConfig = normalizeDnsConfig(dnsConfig);
2641
- logger$6.log("\n🌐 Setting up DNS records...");
2643
+ logger$8.log("\n🌐 Setting up DNS records...");
2642
2644
  let serverIp;
2643
2645
  try {
2644
2646
  const endpointUrl = new URL(dokployEndpoint);
2645
2647
  serverIp = await resolveHostnameToIp(endpointUrl.hostname);
2646
- logger$6.log(` Server IP: ${serverIp} (from ${endpointUrl.hostname})`);
2648
+ logger$8.log(` Server IP: ${serverIp} (from ${endpointUrl.hostname})`);
2647
2649
  } catch (error) {
2648
2650
  const message = error instanceof Error ? error.message : "Unknown error";
2649
- logger$6.log(` ⚠ Failed to resolve server IP: ${message}`);
2651
+ logger$8.log(` ⚠ Failed to resolve server IP: ${message}`);
2650
2652
  return null;
2651
2653
  }
2652
2654
  const groupedHostnames = groupHostnamesByDomain(appHostnames, normalizedConfig);
2653
2655
  if (groupedHostnames.size === 0) {
2654
- logger$6.log(" No DNS records needed (no hostnames match configured domains)");
2656
+ logger$8.log(" No DNS records needed (no hostnames match configured domains)");
2655
2657
  return {
2656
2658
  records: [],
2657
2659
  success: true,
@@ -2663,22 +2665,22 @@ async function orchestrateDns(appHostnames, dnsConfig, dokployEndpoint, state) {
2663
2665
  for (const [rootDomain, domainHostnames] of groupedHostnames) {
2664
2666
  const providerConfig = normalizedConfig[rootDomain];
2665
2667
  if (!providerConfig) {
2666
- logger$6.log(` ⚠ No provider config for ${rootDomain}`);
2668
+ logger$8.log(` ⚠ No provider config for ${rootDomain}`);
2667
2669
  continue;
2668
2670
  }
2669
2671
  const providerName = typeof providerConfig.provider === "string" ? providerConfig.provider : "custom";
2670
2672
  const requiredRecords = generateRequiredRecords(domainHostnames, rootDomain, serverIp);
2671
2673
  if (requiredRecords.length === 0) continue;
2672
- logger$6.log(` Creating DNS records for ${rootDomain} (${providerName})...`);
2674
+ logger$8.log(` Creating DNS records for ${rootDomain} (${providerName})...`);
2673
2675
  const domainRecords = await createDnsRecordsForDomain(requiredRecords, rootDomain, providerConfig);
2674
2676
  allRecords.push(...domainRecords);
2675
2677
  const created = domainRecords.filter((r) => r.created).length;
2676
2678
  const existed = domainRecords.filter((r) => r.existed).length;
2677
2679
  const failed = domainRecords.filter((r) => r.error).length;
2678
- if (created > 0) logger$6.log(` ✓ Created ${created} DNS record(s) for ${rootDomain}`);
2679
- if (existed > 0) logger$6.log(` ✓ ${existed} record(s) already exist for ${rootDomain}`);
2680
+ if (created > 0) logger$8.log(` ✓ Created ${created} DNS record(s) for ${rootDomain}`);
2681
+ if (existed > 0) logger$8.log(` ✓ ${existed} record(s) already exist for ${rootDomain}`);
2680
2682
  if (failed > 0) {
2681
- logger$6.log(` ⚠ ${failed} record(s) failed for ${rootDomain}`);
2683
+ logger$8.log(` ⚠ ${failed} record(s) failed for ${rootDomain}`);
2682
2684
  hasFailures = true;
2683
2685
  }
2684
2686
  if (state) {
@@ -2715,10 +2717,10 @@ async function orchestrateDns(appHostnames, dnsConfig, dokployEndpoint, state) {
2715
2717
  */
2716
2718
  async function verifyDnsRecords(appHostnames, serverIp, state) {
2717
2719
  const results = [];
2718
- logger$6.log("\n🔍 Verifying DNS records...");
2720
+ logger$8.log("\n🔍 Verifying DNS records...");
2719
2721
  for (const [appName, hostname] of appHostnames) {
2720
2722
  if (isDnsVerified(state, hostname, serverIp)) {
2721
- logger$6.log(` ✓ ${hostname} (previously verified)`);
2723
+ logger$8.log(` ✓ ${hostname} (previously verified)`);
2722
2724
  results.push({
2723
2725
  hostname,
2724
2726
  appName,
@@ -2732,7 +2734,7 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
2732
2734
  const resolvedIp = await resolveHostnameToIp(hostname);
2733
2735
  if (resolvedIp === serverIp) {
2734
2736
  setDnsVerification(state, hostname, serverIp);
2735
- logger$6.log(` ✓ ${hostname} → ${resolvedIp}`);
2737
+ logger$8.log(` ✓ ${hostname} → ${resolvedIp}`);
2736
2738
  results.push({
2737
2739
  hostname,
2738
2740
  appName,
@@ -2741,7 +2743,7 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
2741
2743
  expectedIp: serverIp
2742
2744
  });
2743
2745
  } else {
2744
- logger$6.log(` ⚠ ${hostname} resolves to ${resolvedIp}, expected ${serverIp}`);
2746
+ logger$8.log(` ⚠ ${hostname} resolves to ${resolvedIp}, expected ${serverIp}`);
2745
2747
  results.push({
2746
2748
  hostname,
2747
2749
  appName,
@@ -2752,7 +2754,7 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
2752
2754
  }
2753
2755
  } catch (error) {
2754
2756
  const message = error instanceof Error ? error.message : "Unknown error";
2755
- logger$6.log(` ⚠ ${hostname} DNS not propagated (${message})`);
2757
+ logger$8.log(` ⚠ ${hostname} DNS not propagated (${message})`);
2756
2758
  results.push({
2757
2759
  hostname,
2758
2760
  appName,
@@ -2766,9 +2768,9 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
2766
2768
  const skipped = results.filter((r) => r.skipped).length;
2767
2769
  const pending = results.filter((r) => !r.verified).length;
2768
2770
  if (pending > 0) {
2769
- logger$6.log(`\n ${verified} verified, ${pending} pending propagation`);
2770
- logger$6.log(" DNS changes may take 5-30 minutes to propagate");
2771
- } else if (skipped > 0) logger$6.log(` ${verified} verified (${skipped} from cache)`);
2771
+ logger$8.log(`\n ${verified} verified, ${pending} pending propagation`);
2772
+ logger$8.log(" DNS changes may take 5-30 minutes to propagate");
2773
+ } else if (skipped > 0) logger$8.log(` ${verified} verified (${skipped} from cache)`);
2772
2774
  return results;
2773
2775
  }
2774
2776
 
@@ -3844,7 +3846,7 @@ CMD ["node", "index.mjs"]
3844
3846
 
3845
3847
  //#endregion
3846
3848
  //#region src/docker/index.ts
3847
- const logger$5 = console;
3849
+ const logger$7 = console;
3848
3850
  /**
3849
3851
  * Docker command implementation
3850
3852
  * Generates Dockerfile, docker-compose.yml, and related files
@@ -3855,7 +3857,7 @@ const logger$5 = console;
3855
3857
  async function dockerCommand(options) {
3856
3858
  const loadedConfig = await require_config.loadWorkspaceConfig();
3857
3859
  if (loadedConfig.type === "workspace") {
3858
- logger$5.log("📦 Detected workspace configuration");
3860
+ logger$7.log("📦 Detected workspace configuration");
3859
3861
  return workspaceDockerCommand(loadedConfig.workspace, options);
3860
3862
  }
3861
3863
  const config = await require_config.loadConfig();
@@ -3876,14 +3878,14 @@ async function dockerCommand(options) {
3876
3878
  let useTurbo = options.turbo ?? false;
3877
3879
  if (inMonorepo && !useSlim) if (hasTurbo) {
3878
3880
  useTurbo = true;
3879
- logger$5.log(" Detected monorepo with turbo.json - using turbo prune");
3881
+ logger$7.log(" Detected monorepo with turbo.json - using turbo prune");
3880
3882
  } else throw new Error("Monorepo detected but turbo.json not found.\n\nDocker builds in monorepos require Turborepo for proper dependency isolation.\n\nTo fix this:\n 1. Install turbo: pnpm add -Dw turbo\n 2. Create turbo.json in your monorepo root\n 3. Run this command again\n\nSee: https://turbo.build/repo/docs/guides/tools/docker");
3881
3883
  let turboPackage = options.turboPackage ?? dockerConfig.imageName;
3882
3884
  if (useTurbo && !options.turboPackage) try {
3883
3885
  const pkg$1 = require(`${process.cwd()}/package.json`);
3884
3886
  if (pkg$1.name) {
3885
3887
  turboPackage = pkg$1.name;
3886
- logger$5.log(` Turbo package: ${turboPackage}`);
3888
+ logger$7.log(` Turbo package: ${turboPackage}`);
3887
3889
  }
3888
3890
  } catch {}
3889
3891
  const templateOptions = {
@@ -3900,7 +3902,7 @@ async function dockerCommand(options) {
3900
3902
  const dockerMode = useSlim ? "slim" : useTurbo ? "turbo" : "multi-stage";
3901
3903
  const dockerfilePath = (0, node_path.join)(dockerDir, "Dockerfile");
3902
3904
  await (0, node_fs_promises.writeFile)(dockerfilePath, dockerfile);
3903
- logger$5.log(`Generated: .gkm/docker/Dockerfile (${dockerMode}, ${packageManager})`);
3905
+ logger$7.log(`Generated: .gkm/docker/Dockerfile (${dockerMode}, ${packageManager})`);
3904
3906
  const composeOptions = {
3905
3907
  imageName: dockerConfig.imageName,
3906
3908
  registry: options.registry ?? dockerConfig.registry,
@@ -3912,15 +3914,15 @@ async function dockerCommand(options) {
3912
3914
  const dockerCompose = hasServices ? generateDockerCompose(composeOptions) : generateMinimalDockerCompose(composeOptions);
3913
3915
  const composePath = (0, node_path.join)(dockerDir, "docker-compose.yml");
3914
3916
  await (0, node_fs_promises.writeFile)(composePath, dockerCompose);
3915
- logger$5.log("Generated: .gkm/docker/docker-compose.yml");
3917
+ logger$7.log("Generated: .gkm/docker/docker-compose.yml");
3916
3918
  const dockerignore = generateDockerignore();
3917
3919
  const dockerignorePath = (0, node_path.join)(process.cwd(), ".dockerignore");
3918
3920
  await (0, node_fs_promises.writeFile)(dockerignorePath, dockerignore);
3919
- logger$5.log("Generated: .dockerignore (project root)");
3921
+ logger$7.log("Generated: .dockerignore (project root)");
3920
3922
  const entrypoint = generateDockerEntrypoint();
3921
3923
  const entrypointPath = (0, node_path.join)(dockerDir, "docker-entrypoint.sh");
3922
3924
  await (0, node_fs_promises.writeFile)(entrypointPath, entrypoint);
3923
- logger$5.log("Generated: .gkm/docker/docker-entrypoint.sh");
3925
+ logger$7.log("Generated: .gkm/docker/docker-entrypoint.sh");
3924
3926
  const result = {
3925
3927
  dockerfile: dockerfilePath,
3926
3928
  dockerCompose: composePath,
@@ -3939,13 +3941,13 @@ async function dockerCommand(options) {
3939
3941
  function ensureLockfile(cwd) {
3940
3942
  const lockfilePath = findLockfilePath(cwd);
3941
3943
  if (!lockfilePath) {
3942
- logger$5.warn("\n⚠️ No lockfile found. Docker build may fail or use stale dependencies.");
3944
+ logger$7.warn("\n⚠️ No lockfile found. Docker build may fail or use stale dependencies.");
3943
3945
  return null;
3944
3946
  }
3945
3947
  const lockfileName = (0, node_path.basename)(lockfilePath);
3946
3948
  const localLockfile = (0, node_path.join)(cwd, lockfileName);
3947
3949
  if (lockfilePath === localLockfile) return null;
3948
- logger$5.log(` Copying ${lockfileName} from monorepo root...`);
3950
+ logger$7.log(` Copying ${lockfileName} from monorepo root...`);
3949
3951
  (0, node_fs.copyFileSync)(lockfilePath, localLockfile);
3950
3952
  return () => {
3951
3953
  try {
@@ -3961,7 +3963,7 @@ async function buildDockerImage(imageName, options) {
3961
3963
  const tag = options.tag ?? "latest";
3962
3964
  const registry = options.registry;
3963
3965
  const fullImageName = registry ? `${registry}/${imageName}:${tag}` : `${imageName}:${tag}`;
3964
- logger$5.log(`\n🐳 Building Docker image: ${fullImageName}`);
3966
+ logger$7.log(`\n🐳 Building Docker image: ${fullImageName}`);
3965
3967
  const cwd = process.cwd();
3966
3968
  const cleanup = ensureLockfile(cwd);
3967
3969
  try {
@@ -3973,7 +3975,7 @@ async function buildDockerImage(imageName, options) {
3973
3975
  DOCKER_BUILDKIT: "1"
3974
3976
  }
3975
3977
  });
3976
- logger$5.log(`✅ Docker image built: ${fullImageName}`);
3978
+ logger$7.log(`✅ Docker image built: ${fullImageName}`);
3977
3979
  } catch (error) {
3978
3980
  throw new Error(`Failed to build Docker image: ${error instanceof Error ? error.message : "Unknown error"}`);
3979
3981
  } finally {
@@ -3988,13 +3990,13 @@ async function pushDockerImage(imageName, options) {
3988
3990
  const registry = options.registry;
3989
3991
  if (!registry) throw new Error("Registry is required to push Docker image. Use --registry or configure docker.registry in gkm.config.ts");
3990
3992
  const fullImageName = `${registry}/${imageName}:${tag}`;
3991
- logger$5.log(`\n🚀 Pushing Docker image: ${fullImageName}`);
3993
+ logger$7.log(`\n🚀 Pushing Docker image: ${fullImageName}`);
3992
3994
  try {
3993
3995
  (0, node_child_process.execSync)(`docker push ${fullImageName}`, {
3994
3996
  cwd: process.cwd(),
3995
3997
  stdio: "inherit"
3996
3998
  });
3997
- logger$5.log(`✅ Docker image pushed: ${fullImageName}`);
3999
+ logger$7.log(`✅ Docker image pushed: ${fullImageName}`);
3998
4000
  } catch (error) {
3999
4001
  throw new Error(`Failed to push Docker image: ${error instanceof Error ? error.message : "Unknown error"}`);
4000
4002
  }
@@ -4020,11 +4022,11 @@ function getAppPackageName(appPath) {
4020
4022
  async function workspaceDockerCommand(workspace, options) {
4021
4023
  const results = [];
4022
4024
  const apps = Object.entries(workspace.apps);
4023
- logger$5.log(`\n🐳 Generating Dockerfiles for workspace: ${workspace.name}`);
4025
+ logger$7.log(`\n🐳 Generating Dockerfiles for workspace: ${workspace.name}`);
4024
4026
  const dockerDir = (0, node_path.join)(workspace.root, ".gkm", "docker");
4025
4027
  await (0, node_fs_promises.mkdir)(dockerDir, { recursive: true });
4026
4028
  const packageManager = detectPackageManager$1(workspace.root);
4027
- logger$5.log(` Package manager: ${packageManager}`);
4029
+ logger$7.log(` Package manager: ${packageManager}`);
4028
4030
  for (const [appName, app] of apps) {
4029
4031
  const appPath = app.path;
4030
4032
  const fullAppPath = (0, node_path.join)(workspace.root, appPath);
@@ -4032,7 +4034,7 @@ async function workspaceDockerCommand(workspace, options) {
4032
4034
  const imageName = appName;
4033
4035
  const hasEntry = !!app.entry;
4034
4036
  const buildType = hasEntry ? "entry" : app.type;
4035
- logger$5.log(`\n 📄 Generating Dockerfile for ${appName} (${buildType})`);
4037
+ logger$7.log(`\n 📄 Generating Dockerfile for ${appName} (${buildType})`);
4036
4038
  let dockerfile;
4037
4039
  if (app.type === "frontend") dockerfile = generateNextjsDockerfile({
4038
4040
  imageName,
@@ -4063,7 +4065,7 @@ async function workspaceDockerCommand(workspace, options) {
4063
4065
  });
4064
4066
  const dockerfilePath = (0, node_path.join)(dockerDir, `Dockerfile.${appName}`);
4065
4067
  await (0, node_fs_promises.writeFile)(dockerfilePath, dockerfile);
4066
- logger$5.log(` Generated: .gkm/docker/Dockerfile.${appName}`);
4068
+ logger$7.log(` Generated: .gkm/docker/Dockerfile.${appName}`);
4067
4069
  results.push({
4068
4070
  appName,
4069
4071
  type: app.type,
@@ -4074,19 +4076,19 @@ async function workspaceDockerCommand(workspace, options) {
4074
4076
  const dockerignore = generateDockerignore();
4075
4077
  const dockerignorePath = (0, node_path.join)(workspace.root, ".dockerignore");
4076
4078
  await (0, node_fs_promises.writeFile)(dockerignorePath, dockerignore);
4077
- logger$5.log(`\n Generated: .dockerignore (workspace root)`);
4079
+ logger$7.log(`\n Generated: .dockerignore (workspace root)`);
4078
4080
  const dockerCompose = generateWorkspaceCompose(workspace, { registry: options.registry });
4079
4081
  const composePath = (0, node_path.join)(dockerDir, "docker-compose.yml");
4080
4082
  await (0, node_fs_promises.writeFile)(composePath, dockerCompose);
4081
- logger$5.log(` Generated: .gkm/docker/docker-compose.yml`);
4082
- logger$5.log(`\n✅ Generated ${results.length} Dockerfile(s) + docker-compose.yml`);
4083
- logger$5.log("\n📋 Build commands:");
4083
+ logger$7.log(` Generated: .gkm/docker/docker-compose.yml`);
4084
+ logger$7.log(`\n✅ Generated ${results.length} Dockerfile(s) + docker-compose.yml`);
4085
+ logger$7.log("\n📋 Build commands:");
4084
4086
  for (const result of results) {
4085
4087
  const icon = result.type === "backend" ? "⚙️" : "🌐";
4086
- logger$5.log(` ${icon} docker build -f .gkm/docker/Dockerfile.${result.appName} -t ${result.imageName} .`);
4088
+ logger$7.log(` ${icon} docker build -f .gkm/docker/Dockerfile.${result.appName} -t ${result.imageName} .`);
4087
4089
  }
4088
- logger$5.log("\n📋 Run all services:");
4089
- logger$5.log(" docker compose -f .gkm/docker/docker-compose.yml up --build");
4090
+ logger$7.log("\n📋 Run all services:");
4091
+ logger$7.log(" docker compose -f .gkm/docker/docker-compose.yml up --build");
4090
4092
  return {
4091
4093
  apps: results,
4092
4094
  dockerCompose: composePath,
@@ -4126,7 +4128,7 @@ function getAppNameFromPackageJson() {
4126
4128
  } catch {}
4127
4129
  return void 0;
4128
4130
  }
4129
- const logger$4 = console;
4131
+ const logger$6 = console;
4130
4132
  /**
4131
4133
  * Get the full image reference
4132
4134
  */
@@ -4141,18 +4143,18 @@ function getImageRef(registry, imageName, tag) {
4141
4143
  * @param buildArgs - Build arguments to pass to docker build
4142
4144
  */
4143
4145
  async function buildImage(imageRef, appName, buildArgs) {
4144
- logger$4.log(`\n🔨 Building Docker image: ${imageRef}`);
4146
+ logger$6.log(`\n🔨 Building Docker image: ${imageRef}`);
4145
4147
  const cwd = process.cwd();
4146
4148
  const lockfilePath = findLockfilePath(cwd);
4147
4149
  const lockfileDir = lockfilePath ? (0, node_path.dirname)(lockfilePath) : cwd;
4148
4150
  const inMonorepo = lockfileDir !== cwd;
4149
- if (appName || inMonorepo) logger$4.log(" Generating Dockerfile for monorepo (turbo prune)...");
4150
- else logger$4.log(" Generating Dockerfile...");
4151
+ if (appName || inMonorepo) logger$6.log(" Generating Dockerfile for monorepo (turbo prune)...");
4152
+ else logger$6.log(" Generating Dockerfile...");
4151
4153
  await dockerCommand({});
4152
4154
  const dockerfileSuffix = appName ? `.${appName}` : "";
4153
4155
  const dockerfilePath = `.gkm/docker/Dockerfile${dockerfileSuffix}`;
4154
4156
  const buildCwd = lockfilePath && (inMonorepo || appName) ? lockfileDir : cwd;
4155
- if (buildCwd !== cwd) logger$4.log(` Building from workspace root: ${buildCwd}`);
4157
+ if (buildCwd !== cwd) logger$6.log(` Building from workspace root: ${buildCwd}`);
4156
4158
  const buildArgsString = buildArgs && buildArgs.length > 0 ? buildArgs.map((arg) => `--build-arg "${arg}"`).join(" ") : "";
4157
4159
  try {
4158
4160
  const cmd = [
@@ -4171,7 +4173,7 @@ async function buildImage(imageRef, appName, buildArgs) {
4171
4173
  DOCKER_BUILDKIT: "1"
4172
4174
  }
4173
4175
  });
4174
- logger$4.log(`✅ Image built: ${imageRef}`);
4176
+ logger$6.log(`✅ Image built: ${imageRef}`);
4175
4177
  } catch (error) {
4176
4178
  throw new Error(`Failed to build Docker image: ${error instanceof Error ? error.message : "Unknown error"}`);
4177
4179
  }
@@ -4180,13 +4182,13 @@ async function buildImage(imageRef, appName, buildArgs) {
4180
4182
  * Push Docker image to registry
4181
4183
  */
4182
4184
  async function pushImage(imageRef) {
4183
- logger$4.log(`\n☁️ Pushing image: ${imageRef}`);
4185
+ logger$6.log(`\n☁️ Pushing image: ${imageRef}`);
4184
4186
  try {
4185
4187
  (0, node_child_process.execSync)(`docker push ${imageRef}`, {
4186
4188
  cwd: process.cwd(),
4187
4189
  stdio: "inherit"
4188
4190
  });
4189
- logger$4.log(`✅ Image pushed: ${imageRef}`);
4191
+ logger$6.log(`✅ Image pushed: ${imageRef}`);
4190
4192
  } catch (error) {
4191
4193
  throw new Error(`Failed to push Docker image: ${error instanceof Error ? error.message : "Unknown error"}`);
4192
4194
  }
@@ -4199,17 +4201,17 @@ async function deployDocker(options) {
4199
4201
  const imageName = config.imageName;
4200
4202
  const imageRef = getImageRef(config.registry, imageName, tag);
4201
4203
  await buildImage(imageRef, config.appName, buildArgs);
4202
- if (!skipPush) if (!config.registry) logger$4.warn("\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts");
4204
+ if (!skipPush) if (!config.registry) logger$6.warn("\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts");
4203
4205
  else await pushImage(imageRef);
4204
- logger$4.log("\n✅ Docker deployment ready!");
4205
- logger$4.log(`\n📋 Deployment details:`);
4206
- logger$4.log(` Image: ${imageRef}`);
4207
- logger$4.log(` Stage: ${stage}`);
4206
+ logger$6.log("\n✅ Docker deployment ready!");
4207
+ logger$6.log(`\n📋 Deployment details:`);
4208
+ logger$6.log(` Image: ${imageRef}`);
4209
+ logger$6.log(` Stage: ${stage}`);
4208
4210
  if (masterKey) {
4209
- logger$4.log(`\n🔐 Deploy with this environment variable:`);
4210
- logger$4.log(` GKM_MASTER_KEY=${masterKey}`);
4211
- logger$4.log("\n Example docker run:");
4212
- logger$4.log(` docker run -e GKM_MASTER_KEY=${masterKey} ${imageRef}`);
4211
+ logger$6.log(`\n🔐 Deploy with this environment variable:`);
4212
+ logger$6.log(` GKM_MASTER_KEY=${masterKey}`);
4213
+ logger$6.log("\n Example docker run:");
4214
+ logger$6.log(` docker run -e GKM_MASTER_KEY=${masterKey} ${imageRef}`);
4213
4215
  }
4214
4216
  return {
4215
4217
  imageRef,
@@ -4236,7 +4238,7 @@ function resolveDockerConfig(config) {
4236
4238
 
4237
4239
  //#endregion
4238
4240
  //#region src/deploy/dokploy.ts
4239
- const logger$3 = console;
4241
+ const logger$5 = console;
4240
4242
  /**
4241
4243
  * Get the Dokploy API token from stored credentials or environment
4242
4244
  */
@@ -4260,25 +4262,25 @@ async function createApi$1(endpoint) {
4260
4262
  */
4261
4263
  async function deployDokploy(options) {
4262
4264
  const { stage, imageRef, masterKey, config } = options;
4263
- logger$3.log(`\n🎯 Deploying to Dokploy...`);
4264
- logger$3.log(` Endpoint: ${config.endpoint}`);
4265
- logger$3.log(` Application: ${config.applicationId}`);
4265
+ logger$5.log(`\n🎯 Deploying to Dokploy...`);
4266
+ logger$5.log(` Endpoint: ${config.endpoint}`);
4267
+ logger$5.log(` Application: ${config.applicationId}`);
4266
4268
  const api = await createApi$1(config.endpoint);
4267
- logger$3.log(` Configuring Docker image: ${imageRef}`);
4269
+ logger$5.log(` Configuring Docker image: ${imageRef}`);
4268
4270
  const registryOptions = {};
4269
4271
  if (config.registryId) {
4270
4272
  registryOptions.registryId = config.registryId;
4271
- logger$3.log(` Using Dokploy registry: ${config.registryId}`);
4273
+ logger$5.log(` Using Dokploy registry: ${config.registryId}`);
4272
4274
  } else {
4273
4275
  const storedRegistryId = await require_credentials.getDokployRegistryId();
4274
4276
  if (storedRegistryId) {
4275
4277
  registryOptions.registryId = storedRegistryId;
4276
- logger$3.log(` Using stored Dokploy registry: ${storedRegistryId}`);
4278
+ logger$5.log(` Using stored Dokploy registry: ${storedRegistryId}`);
4277
4279
  } else if (config.registryCredentials) {
4278
4280
  registryOptions.username = config.registryCredentials.username;
4279
4281
  registryOptions.password = config.registryCredentials.password;
4280
4282
  registryOptions.registryUrl = config.registryCredentials.registryUrl;
4281
- logger$3.log(` Using registry credentials for: ${config.registryCredentials.registryUrl}`);
4283
+ logger$5.log(` Using registry credentials for: ${config.registryCredentials.registryUrl}`);
4282
4284
  } else {
4283
4285
  const username = process.env.DOCKER_REGISTRY_USERNAME;
4284
4286
  const password = process.env.DOCKER_REGISTRY_PASSWORD;
@@ -4287,31 +4289,31 @@ async function deployDokploy(options) {
4287
4289
  registryOptions.username = username;
4288
4290
  registryOptions.password = password;
4289
4291
  registryOptions.registryUrl = registryUrl;
4290
- logger$3.log(` Using registry credentials from environment`);
4292
+ logger$5.log(` Using registry credentials from environment`);
4291
4293
  }
4292
4294
  }
4293
4295
  }
4294
4296
  await api.saveDockerProvider(config.applicationId, imageRef, registryOptions);
4295
- logger$3.log(" ✓ Docker provider configured");
4297
+ logger$5.log(" ✓ Docker provider configured");
4296
4298
  const envVars = {};
4297
4299
  if (masterKey) envVars.GKM_MASTER_KEY = masterKey;
4298
4300
  if (Object.keys(envVars).length > 0) {
4299
- logger$3.log(" Updating environment variables...");
4301
+ logger$5.log(" Updating environment variables...");
4300
4302
  const envString = Object.entries(envVars).map(([key, value]) => `${key}=${value}`).join("\n");
4301
4303
  await api.saveApplicationEnv(config.applicationId, envString);
4302
- logger$3.log(" ✓ Environment variables updated");
4304
+ logger$5.log(" ✓ Environment variables updated");
4303
4305
  }
4304
- logger$3.log(" Triggering deployment...");
4306
+ logger$5.log(" Triggering deployment...");
4305
4307
  await api.deployApplication(config.applicationId);
4306
- logger$3.log(" ✓ Deployment triggered");
4307
- logger$3.log("\n✅ Dokploy deployment initiated!");
4308
- logger$3.log(`\n📋 Deployment details:`);
4309
- logger$3.log(` Image: ${imageRef}`);
4310
- logger$3.log(` Stage: ${stage}`);
4311
- logger$3.log(` Application ID: ${config.applicationId}`);
4312
- if (masterKey) logger$3.log(`\n🔐 GKM_MASTER_KEY has been set in Dokploy environment`);
4308
+ logger$5.log(" ✓ Deployment triggered");
4309
+ logger$5.log("\n✅ Dokploy deployment initiated!");
4310
+ logger$5.log(`\n📋 Deployment details:`);
4311
+ logger$5.log(` Image: ${imageRef}`);
4312
+ logger$5.log(` Stage: ${stage}`);
4313
+ logger$5.log(` Application ID: ${config.applicationId}`);
4314
+ if (masterKey) logger$5.log(`\n🔐 GKM_MASTER_KEY has been set in Dokploy environment`);
4313
4315
  const deploymentUrl = `${config.endpoint}/project/${config.projectId}`;
4314
- logger$3.log(`\n🔗 View deployment: ${deploymentUrl}`);
4316
+ logger$5.log(`\n🔗 View deployment: ${deploymentUrl}`);
4315
4317
  return {
4316
4318
  imageRef,
4317
4319
  masterKey,
@@ -4477,7 +4479,7 @@ function validateEnvVars(requiredVars, context) {
4477
4479
 
4478
4480
  //#endregion
4479
4481
  //#region src/deploy/init.ts
4480
- const logger$2 = console;
4482
+ const logger$4 = console;
4481
4483
  /**
4482
4484
  * Get the Dokploy API token from stored credentials or environment
4483
4485
  */
@@ -4511,20 +4513,20 @@ async function createApi(endpoint) {
4511
4513
  async function updateConfig(config, cwd = process.cwd()) {
4512
4514
  const configPath = (0, node_path.join)(cwd, "gkm.config.ts");
4513
4515
  if (!(0, node_fs.existsSync)(configPath)) {
4514
- logger$2.warn("\n gkm.config.ts not found. Add this configuration manually:\n");
4515
- logger$2.log(` providers: {`);
4516
- logger$2.log(` dokploy: {`);
4517
- logger$2.log(` endpoint: '${config.endpoint}',`);
4518
- logger$2.log(` projectId: '${config.projectId}',`);
4519
- logger$2.log(` applicationId: '${config.applicationId}',`);
4520
- logger$2.log(` },`);
4521
- logger$2.log(` },`);
4516
+ logger$4.warn("\n gkm.config.ts not found. Add this configuration manually:\n");
4517
+ logger$4.log(` providers: {`);
4518
+ logger$4.log(` dokploy: {`);
4519
+ logger$4.log(` endpoint: '${config.endpoint}',`);
4520
+ logger$4.log(` projectId: '${config.projectId}',`);
4521
+ logger$4.log(` applicationId: '${config.applicationId}',`);
4522
+ logger$4.log(` },`);
4523
+ logger$4.log(` },`);
4522
4524
  return;
4523
4525
  }
4524
4526
  const content = await (0, node_fs_promises.readFile)(configPath, "utf-8");
4525
4527
  if (content.includes("dokploy:") && content.includes("applicationId:")) {
4526
- logger$2.log("\n Dokploy config already exists in gkm.config.ts");
4527
- logger$2.log(" Updating with new values...");
4528
+ logger$4.log("\n Dokploy config already exists in gkm.config.ts");
4529
+ logger$4.log(" Updating with new values...");
4528
4530
  }
4529
4531
  const registryLine = config.registryId ? `\n\t\t\tregistryId: '${config.registryId}',` : "";
4530
4532
  const dokployConfigStr = `dokploy: {
@@ -4541,7 +4543,7 @@ async function updateConfig(config, cwd = process.cwd()) {
4541
4543
  },
4542
4544
  });`);
4543
4545
  await (0, node_fs_promises.writeFile)(configPath, newContent);
4544
- logger$2.log("\n ✓ Updated gkm.config.ts with Dokploy configuration");
4546
+ logger$4.log("\n ✓ Updated gkm.config.ts with Dokploy configuration");
4545
4547
  }
4546
4548
  /**
4547
4549
  * Initialize Dokploy deployment configuration
@@ -4550,24 +4552,24 @@ async function deployInitCommand(options) {
4550
4552
  const { projectName, appName, projectId: existingProjectId, registryId } = options;
4551
4553
  const endpoint = await getEndpoint(options.endpoint);
4552
4554
  const api = await createApi(endpoint);
4553
- logger$2.log(`\n🚀 Initializing Dokploy deployment...`);
4554
- logger$2.log(` Endpoint: ${endpoint}`);
4555
+ logger$4.log(`\n🚀 Initializing Dokploy deployment...`);
4556
+ logger$4.log(` Endpoint: ${endpoint}`);
4555
4557
  let projectId;
4556
4558
  if (existingProjectId) {
4557
4559
  projectId = existingProjectId;
4558
- logger$2.log(`\n📁 Using existing project: ${projectId}`);
4560
+ logger$4.log(`\n📁 Using existing project: ${projectId}`);
4559
4561
  } else {
4560
- logger$2.log(`\n📁 Looking for project: ${projectName}`);
4562
+ logger$4.log(`\n📁 Looking for project: ${projectName}`);
4561
4563
  const projects = await api.listProjects();
4562
4564
  const existingProject = projects.find((p) => p.name.toLowerCase() === projectName.toLowerCase());
4563
4565
  if (existingProject) {
4564
4566
  projectId = existingProject.projectId;
4565
- logger$2.log(` Found existing project: ${projectId}`);
4567
+ logger$4.log(` Found existing project: ${projectId}`);
4566
4568
  } else {
4567
- logger$2.log(` Creating new project...`);
4569
+ logger$4.log(` Creating new project...`);
4568
4570
  const result = await api.createProject(projectName);
4569
4571
  projectId = result.project.projectId;
4570
- logger$2.log(` ✓ Created project: ${projectId}`);
4572
+ logger$4.log(` ✓ Created project: ${projectId}`);
4571
4573
  }
4572
4574
  }
4573
4575
  const project = await api.getProject(projectId);
@@ -4575,23 +4577,23 @@ async function deployInitCommand(options) {
4575
4577
  const firstEnv = project.environments?.[0];
4576
4578
  if (firstEnv) environmentId = firstEnv.environmentId;
4577
4579
  else {
4578
- logger$2.log(` Creating production environment...`);
4580
+ logger$4.log(` Creating production environment...`);
4579
4581
  const env = await api.createEnvironment(projectId, "production");
4580
4582
  environmentId = env.environmentId;
4581
4583
  }
4582
- logger$2.log(`\n📦 Creating application: ${appName}`);
4584
+ logger$4.log(`\n📦 Creating application: ${appName}`);
4583
4585
  const application = await api.createApplication(appName, projectId, environmentId);
4584
- logger$2.log(` ✓ Created application: ${application.applicationId}`);
4586
+ logger$4.log(` ✓ Created application: ${application.applicationId}`);
4585
4587
  if (registryId) {
4586
- logger$2.log(`\n🔧 Configuring registry: ${registryId}`);
4588
+ logger$4.log(`\n🔧 Configuring registry: ${registryId}`);
4587
4589
  await api.updateApplication(application.applicationId, { registryId });
4588
- logger$2.log(` ✓ Registry configured`);
4590
+ logger$4.log(` ✓ Registry configured`);
4589
4591
  } else try {
4590
4592
  const registries = await api.listRegistries();
4591
4593
  if (registries.length > 0) {
4592
- logger$2.log(`\n📋 Available registries:`);
4593
- for (const reg of registries) logger$2.log(` - ${reg.registryName}: ${reg.registryUrl} (${reg.registryId})`);
4594
- logger$2.log(`\n To use a registry, run with --registry-id <id>`);
4594
+ logger$4.log(`\n📋 Available registries:`);
4595
+ for (const reg of registries) logger$4.log(` - ${reg.registryName}: ${reg.registryUrl} (${reg.registryId})`);
4596
+ logger$4.log(`\n To use a registry, run with --registry-id <id>`);
4595
4597
  }
4596
4598
  } catch {}
4597
4599
  const config = {
@@ -4600,14 +4602,14 @@ async function deployInitCommand(options) {
4600
4602
  applicationId: application.applicationId
4601
4603
  };
4602
4604
  await updateConfig(config);
4603
- logger$2.log(`\n✅ Dokploy deployment initialized!`);
4604
- logger$2.log(`\n📋 Configuration:`);
4605
- logger$2.log(` Project ID: ${projectId}`);
4606
- logger$2.log(` Application ID: ${application.applicationId}`);
4607
- logger$2.log(`\n🔗 View in Dokploy: ${endpoint}/project/${projectId}`);
4608
- logger$2.log(`\n📝 Next steps:`);
4609
- logger$2.log(` 1. Initialize secrets: gkm secrets:init --stage production`);
4610
- logger$2.log(` 2. Deploy: gkm deploy --provider dokploy --stage production`);
4605
+ logger$4.log(`\n✅ Dokploy deployment initialized!`);
4606
+ logger$4.log(`\n📋 Configuration:`);
4607
+ logger$4.log(` Project ID: ${projectId}`);
4608
+ logger$4.log(` Application ID: ${application.applicationId}`);
4609
+ logger$4.log(`\n🔗 View in Dokploy: ${endpoint}/project/${projectId}`);
4610
+ logger$4.log(`\n📝 Next steps:`);
4611
+ logger$4.log(` 1. Initialize secrets: gkm secrets:init --stage production`);
4612
+ logger$4.log(` 2. Deploy: gkm deploy --provider dokploy --stage production`);
4611
4613
  return config;
4612
4614
  }
4613
4615
  /**
@@ -4618,32 +4620,32 @@ async function deployListCommand(options) {
4618
4620
  const api = await createApi(endpoint);
4619
4621
  const { resource } = options;
4620
4622
  if (resource === "projects") {
4621
- logger$2.log(`\n📁 Projects in ${endpoint}:`);
4623
+ logger$4.log(`\n📁 Projects in ${endpoint}:`);
4622
4624
  const projects = await api.listProjects();
4623
4625
  if (projects.length === 0) {
4624
- logger$2.log(" No projects found");
4626
+ logger$4.log(" No projects found");
4625
4627
  return;
4626
4628
  }
4627
4629
  for (const project of projects) {
4628
- logger$2.log(`\n ${project.name} (${project.projectId})`);
4629
- if (project.description) logger$2.log(` ${project.description}`);
4630
+ logger$4.log(`\n ${project.name} (${project.projectId})`);
4631
+ if (project.description) logger$4.log(` ${project.description}`);
4630
4632
  }
4631
4633
  } else if (resource === "registries") {
4632
- logger$2.log(`\n🐳 Registries in ${endpoint}:`);
4634
+ logger$4.log(`\n🐳 Registries in ${endpoint}:`);
4633
4635
  const registries = await api.listRegistries();
4634
4636
  if (registries.length === 0) {
4635
- logger$2.log(" No registries configured");
4636
- logger$2.log(" Run \"gkm registry:setup\" to configure a registry");
4637
+ logger$4.log(" No registries configured");
4638
+ logger$4.log(" Run \"gkm registry:setup\" to configure a registry");
4637
4639
  return;
4638
4640
  }
4639
4641
  const storedRegistryId = await require_credentials.getDokployRegistryId();
4640
4642
  for (const registry of registries) {
4641
4643
  const isDefault = registry.registryId === storedRegistryId;
4642
4644
  const marker = isDefault ? " (default)" : "";
4643
- logger$2.log(`\n ${registry.registryName}${marker} (${registry.registryId})`);
4644
- logger$2.log(` URL: ${registry.registryUrl}`);
4645
- logger$2.log(` Username: ${registry.username}`);
4646
- if (registry.imagePrefix) logger$2.log(` Prefix: ${registry.imagePrefix}`);
4645
+ logger$4.log(`\n ${registry.registryName}${marker} (${registry.registryId})`);
4646
+ logger$4.log(` URL: ${registry.registryUrl}`);
4647
+ logger$4.log(` Username: ${registry.username}`);
4648
+ if (registry.imagePrefix) logger$4.log(` Prefix: ${registry.imagePrefix}`);
4647
4649
  }
4648
4650
  }
4649
4651
  }
@@ -4666,19 +4668,19 @@ function isStateProvider(value) {
4666
4668
  async function createStateProvider(options) {
4667
4669
  const { config, workspaceRoot, workspaceName } = options;
4668
4670
  if (!config) {
4669
- const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-CdspeSVL.cjs"));
4671
+ const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-Roi202l7.cjs"));
4670
4672
  return new LocalStateProvider(workspaceRoot);
4671
4673
  }
4672
4674
  if (isStateProvider(config.provider)) return config.provider;
4673
4675
  const provider = config.provider;
4674
4676
  if (provider === "local") {
4675
- const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-CdspeSVL.cjs"));
4677
+ const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-Roi202l7.cjs"));
4676
4678
  return new LocalStateProvider(workspaceRoot);
4677
4679
  }
4678
4680
  if (provider === "ssm") {
4679
4681
  if (!workspaceName) throw new Error("Workspace name is required for SSM state provider. Set \"name\" in gkm.config.ts.");
4680
- const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-CdspeSVL.cjs"));
4681
- const { SSMStateProvider } = await Promise.resolve().then(() => require("./SSMStateProvider-DGrqYll0.cjs"));
4682
+ const { LocalStateProvider } = await Promise.resolve().then(() => require("./LocalStateProvider-Roi202l7.cjs"));
4683
+ const { SSMStateProvider } = await Promise.resolve().then(() => require("./SSMStateProvider-BReQA5re.cjs"));
4682
4684
  const { CachedStateProvider: CachedStateProvider$1 } = await Promise.resolve().then(() => require("./CachedStateProvider-D_uISMmJ.cjs"));
4683
4685
  const ssmConfig = config;
4684
4686
  const local = new LocalStateProvider(workspaceRoot);
@@ -5111,7 +5113,7 @@ async function sniffAllApps(apps, workspacePath, options = {}) {
5111
5113
 
5112
5114
  //#endregion
5113
5115
  //#region src/deploy/index.ts
5114
- const logger$1 = console;
5116
+ const logger$3 = console;
5115
5117
  /**
5116
5118
  * Prompt for input
5117
5119
  */
@@ -5183,7 +5185,7 @@ async function waitForPostgres(host, port, user, password, database, maxRetries
5183
5185
  return;
5184
5186
  } catch {
5185
5187
  if (i < maxRetries - 1) {
5186
- logger$1.log(` Waiting for Postgres... (${i + 1}/${maxRetries})`);
5188
+ logger$3.log(` Waiting for Postgres... (${i + 1}/${maxRetries})`);
5187
5189
  await new Promise((r) => setTimeout(r, retryIntervalMs));
5188
5190
  }
5189
5191
  }
@@ -5218,12 +5220,12 @@ async function waitForPostgres(host, port, user, password, database, maxRetries
5218
5220
  * ```
5219
5221
  */
5220
5222
  async function initializePostgresUsers(api, postgres, serverHostname, users) {
5221
- logger$1.log("\n🔧 Initializing database users...");
5223
+ logger$3.log("\n🔧 Initializing database users...");
5222
5224
  const externalPort = 5432;
5223
- logger$1.log(` Enabling external port ${externalPort}...`);
5225
+ logger$3.log(` Enabling external port ${externalPort}...`);
5224
5226
  await api.savePostgresExternalPort(postgres.postgresId, externalPort);
5225
5227
  await api.deployPostgres(postgres.postgresId);
5226
- logger$1.log(` Waiting for Postgres to be accessible at ${serverHostname}:${externalPort}...`);
5228
+ logger$3.log(` Waiting for Postgres to be accessible at ${serverHostname}:${externalPort}...`);
5227
5229
  await waitForPostgres(serverHostname, externalPort, postgres.databaseUser, postgres.databasePassword, postgres.databaseName);
5228
5230
  const client = new pg.Client({
5229
5231
  host: serverHostname,
@@ -5236,7 +5238,7 @@ async function initializePostgresUsers(api, postgres, serverHostname, users) {
5236
5238
  await client.connect();
5237
5239
  for (const user of users) {
5238
5240
  const schemaName = user.usePublicSchema ? "public" : user.name;
5239
- logger$1.log(` Creating user "${user.name}" with schema "${schemaName}"...`);
5241
+ logger$3.log(` Creating user "${user.name}" with schema "${schemaName}"...`);
5240
5242
  if (user.usePublicSchema) {
5241
5243
  await client.query(`
5242
5244
  DO $$ BEGIN
@@ -5271,15 +5273,15 @@ async function initializePostgresUsers(api, postgres, serverHostname, users) {
5271
5273
  ALTER DEFAULT PRIVILEGES IN SCHEMA "${schemaName}" GRANT ALL ON TABLES TO "${user.name}";
5272
5274
  `);
5273
5275
  }
5274
- logger$1.log(` ✓ User "${user.name}" configured`);
5276
+ logger$3.log(` ✓ User "${user.name}" configured`);
5275
5277
  }
5276
5278
  } finally {
5277
5279
  await client.end();
5278
5280
  }
5279
- logger$1.log(" Disabling external port...");
5281
+ logger$3.log(" Disabling external port...");
5280
5282
  await api.savePostgresExternalPort(postgres.postgresId, null);
5281
5283
  await api.deployPostgres(postgres.postgresId);
5282
- logger$1.log(" ✓ Database users initialized");
5284
+ logger$3.log(" ✓ Database users initialized");
5283
5285
  }
5284
5286
  /**
5285
5287
  * Get the server hostname from the Dokploy endpoint URL
@@ -5293,24 +5295,24 @@ function getServerHostname(endpoint) {
5293
5295
  * @internal Exported for testing
5294
5296
  */
5295
5297
  async function provisionServices(api, projectId, environmentId, projectName, services, existingServiceIds) {
5296
- logger$1.log(`\n🔍 provisionServices called: services=${JSON.stringify(services)}, envId=${environmentId}`);
5298
+ logger$3.log(`\n🔍 provisionServices called: services=${JSON.stringify(services)}, envId=${environmentId}`);
5297
5299
  if (!services || !environmentId) {
5298
- logger$1.log(" Skipping: no services or no environmentId");
5300
+ logger$3.log(" Skipping: no services or no environmentId");
5299
5301
  return void 0;
5300
5302
  }
5301
5303
  const serviceUrls = {};
5302
5304
  const serviceIds = {};
5303
5305
  if (services.postgres) {
5304
- logger$1.log("\n🐘 Checking PostgreSQL...");
5306
+ logger$3.log("\n🐘 Checking PostgreSQL...");
5305
5307
  const postgresName = "db";
5306
5308
  try {
5307
5309
  let postgres = null;
5308
5310
  let created = false;
5309
5311
  if (existingServiceIds?.postgresId) {
5310
- logger$1.log(` Using cached ID: ${existingServiceIds.postgresId}`);
5312
+ logger$3.log(` Using cached ID: ${existingServiceIds.postgresId}`);
5311
5313
  postgres = await api.getPostgres(existingServiceIds.postgresId);
5312
- if (postgres) logger$1.log(` ✓ PostgreSQL found: ${postgres.postgresId}`);
5313
- else logger$1.log(` ⚠ Cached ID invalid, will create new`);
5314
+ if (postgres) logger$3.log(` ✓ PostgreSQL found: ${postgres.postgresId}`);
5315
+ else logger$3.log(` ⚠ Cached ID invalid, will create new`);
5314
5316
  }
5315
5317
  if (!postgres) {
5316
5318
  const databasePassword = (0, node_crypto.randomBytes)(16).toString("hex");
@@ -5322,10 +5324,10 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
5322
5324
  postgres = result.postgres;
5323
5325
  created = result.created;
5324
5326
  if (created) {
5325
- logger$1.log(` ✓ Created PostgreSQL: ${postgres.postgresId}`);
5327
+ logger$3.log(` ✓ Created PostgreSQL: ${postgres.postgresId}`);
5326
5328
  await api.deployPostgres(postgres.postgresId);
5327
- logger$1.log(" ✓ PostgreSQL deployed");
5328
- } else logger$1.log(` ✓ PostgreSQL already exists: ${postgres.postgresId}`);
5329
+ logger$3.log(" ✓ PostgreSQL deployed");
5330
+ } else logger$3.log(` ✓ PostgreSQL already exists: ${postgres.postgresId}`);
5329
5331
  }
5330
5332
  serviceIds.postgresId = postgres.postgresId;
5331
5333
  serviceUrls.DATABASE_HOST = postgres.appName;
@@ -5334,23 +5336,23 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
5334
5336
  serviceUrls.DATABASE_USER = postgres.databaseUser;
5335
5337
  serviceUrls.DATABASE_PASSWORD = postgres.databasePassword;
5336
5338
  serviceUrls.DATABASE_URL = `postgresql://${postgres.databaseUser}:${postgres.databasePassword}@${postgres.appName}:5432/${postgres.databaseName}`;
5337
- logger$1.log(` ✓ Database credentials configured`);
5339
+ logger$3.log(` ✓ Database credentials configured`);
5338
5340
  } catch (error) {
5339
5341
  const message = error instanceof Error ? error.message : "Unknown error";
5340
- logger$1.log(` ⚠ Failed to provision PostgreSQL: ${message}`);
5342
+ logger$3.log(` ⚠ Failed to provision PostgreSQL: ${message}`);
5341
5343
  }
5342
5344
  }
5343
5345
  if (services.redis) {
5344
- logger$1.log("\n🔴 Checking Redis...");
5346
+ logger$3.log("\n🔴 Checking Redis...");
5345
5347
  const redisName = "cache";
5346
5348
  try {
5347
5349
  let redis = null;
5348
5350
  let created = false;
5349
5351
  if (existingServiceIds?.redisId) {
5350
- logger$1.log(` Using cached ID: ${existingServiceIds.redisId}`);
5352
+ logger$3.log(` Using cached ID: ${existingServiceIds.redisId}`);
5351
5353
  redis = await api.getRedis(existingServiceIds.redisId);
5352
- if (redis) logger$1.log(` ✓ Redis found: ${redis.redisId}`);
5353
- else logger$1.log(` ⚠ Cached ID invalid, will create new`);
5354
+ if (redis) logger$3.log(` ✓ Redis found: ${redis.redisId}`);
5355
+ else logger$3.log(` ⚠ Cached ID invalid, will create new`);
5354
5356
  }
5355
5357
  if (!redis) {
5356
5358
  const { randomBytes: randomBytes$3 } = await import("node:crypto");
@@ -5359,10 +5361,10 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
5359
5361
  redis = result.redis;
5360
5362
  created = result.created;
5361
5363
  if (created) {
5362
- logger$1.log(` ✓ Created Redis: ${redis.redisId}`);
5364
+ logger$3.log(` ✓ Created Redis: ${redis.redisId}`);
5363
5365
  await api.deployRedis(redis.redisId);
5364
- logger$1.log(" ✓ Redis deployed");
5365
- } else logger$1.log(` ✓ Redis already exists: ${redis.redisId}`);
5366
+ logger$3.log(" ✓ Redis deployed");
5367
+ } else logger$3.log(` ✓ Redis already exists: ${redis.redisId}`);
5366
5368
  }
5367
5369
  serviceIds.redisId = redis.redisId;
5368
5370
  serviceUrls.REDIS_HOST = redis.appName;
@@ -5370,10 +5372,10 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
5370
5372
  if (redis.databasePassword) serviceUrls.REDIS_PASSWORD = redis.databasePassword;
5371
5373
  const password = redis.databasePassword ? `:${redis.databasePassword}@` : "";
5372
5374
  serviceUrls.REDIS_URL = `redis://${password}${redis.appName}:6379`;
5373
- logger$1.log(` ✓ Redis credentials configured`);
5375
+ logger$3.log(` ✓ Redis credentials configured`);
5374
5376
  } catch (error) {
5375
5377
  const message = error instanceof Error ? error.message : "Unknown error";
5376
- logger$1.log(` ⚠ Failed to provision Redis: ${message}`);
5378
+ logger$3.log(` ⚠ Failed to provision Redis: ${message}`);
5377
5379
  }
5378
5380
  }
5379
5381
  return Object.keys(serviceUrls).length > 0 ? {
@@ -5385,10 +5387,10 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
5385
5387
  * Ensure Dokploy is fully configured, recovering/creating resources as needed
5386
5388
  */
5387
5389
  async function ensureDokploySetup(config, dockerConfig, stage, services) {
5388
- logger$1.log("\n🔧 Checking Dokploy setup...");
5390
+ logger$3.log("\n🔧 Checking Dokploy setup...");
5389
5391
  let creds = await require_credentials.getDokployCredentials();
5390
5392
  if (!creds) {
5391
- logger$1.log("\n📋 Dokploy credentials not found. Let's set them up.");
5393
+ logger$3.log("\n📋 Dokploy credentials not found. Let's set them up.");
5392
5394
  const endpoint = await prompt("Dokploy URL (e.g., https://dokploy.example.com): ");
5393
5395
  const normalizedEndpoint = endpoint.replace(/\/$/, "");
5394
5396
  try {
@@ -5396,9 +5398,9 @@ async function ensureDokploySetup(config, dockerConfig, stage, services) {
5396
5398
  } catch {
5397
5399
  throw new Error("Invalid URL format");
5398
5400
  }
5399
- logger$1.log(`\nGenerate a token at: ${normalizedEndpoint}/settings/profile\n`);
5401
+ logger$3.log(`\nGenerate a token at: ${normalizedEndpoint}/settings/profile\n`);
5400
5402
  const token = await prompt("API Token: ", true);
5401
- logger$1.log("\nValidating credentials...");
5403
+ logger$3.log("\nValidating credentials...");
5402
5404
  const isValid = await validateDokployToken(normalizedEndpoint, token);
5403
5405
  if (!isValid) throw new Error("Invalid credentials. Please check your token.");
5404
5406
  await require_credentials.storeDokployCredentials(token, normalizedEndpoint);
@@ -5406,7 +5408,7 @@ async function ensureDokploySetup(config, dockerConfig, stage, services) {
5406
5408
  token,
5407
5409
  endpoint: normalizedEndpoint
5408
5410
  };
5409
- logger$1.log("✓ Credentials saved");
5411
+ logger$3.log("✓ Credentials saved");
5410
5412
  }
5411
5413
  const api = new require_dokploy_api.DokployApi({
5412
5414
  baseUrl: creds.endpoint,
@@ -5414,20 +5416,20 @@ async function ensureDokploySetup(config, dockerConfig, stage, services) {
5414
5416
  });
5415
5417
  const existingConfig = config.providers?.dokploy;
5416
5418
  if (existingConfig && typeof existingConfig !== "boolean" && existingConfig.applicationId && existingConfig.projectId) {
5417
- logger$1.log("✓ Dokploy config found in gkm.config.ts");
5419
+ logger$3.log("✓ Dokploy config found in gkm.config.ts");
5418
5420
  try {
5419
5421
  const projectDetails = await api.getProject(existingConfig.projectId);
5420
- logger$1.log("✓ Project verified");
5422
+ logger$3.log("✓ Project verified");
5421
5423
  const storedRegistryId = existingConfig.registryId ?? await require_credentials.getDokployRegistryId();
5422
5424
  const environments = projectDetails.environments ?? [];
5423
5425
  let environment = environments.find((e) => e.name.toLowerCase() === stage.toLowerCase());
5424
5426
  if (!environment) {
5425
- logger$1.log(` Creating "${stage}" environment...`);
5427
+ logger$3.log(` Creating "${stage}" environment...`);
5426
5428
  environment = await api.createEnvironment(existingConfig.projectId, stage);
5427
- logger$1.log(` ✓ Created environment: ${environment.environmentId}`);
5429
+ logger$3.log(` ✓ Created environment: ${environment.environmentId}`);
5428
5430
  }
5429
5431
  const environmentId$1 = environment.environmentId;
5430
- logger$1.log(` Services config: ${JSON.stringify(services)}, envId: ${environmentId$1}`);
5432
+ logger$3.log(` Services config: ${JSON.stringify(services)}, envId: ${environmentId$1}`);
5431
5433
  const provisionResult$1 = await provisionServices(api, existingConfig.projectId, environmentId$1, dockerConfig.appName, services, void 0);
5432
5434
  return {
5433
5435
  config: {
@@ -5440,97 +5442,97 @@ async function ensureDokploySetup(config, dockerConfig, stage, services) {
5440
5442
  serviceUrls: provisionResult$1?.serviceUrls
5441
5443
  };
5442
5444
  } catch {
5443
- logger$1.log("⚠ Project not found, will recover...");
5445
+ logger$3.log("⚠ Project not found, will recover...");
5444
5446
  }
5445
5447
  }
5446
- logger$1.log("\n📁 Looking for project...");
5448
+ logger$3.log("\n📁 Looking for project...");
5447
5449
  const projectName = dockerConfig.projectName;
5448
5450
  const projects = await api.listProjects();
5449
5451
  let project = projects.find((p) => p.name.toLowerCase() === projectName.toLowerCase());
5450
5452
  let environmentId;
5451
5453
  if (project) {
5452
- logger$1.log(` Found existing project: ${project.name} (${project.projectId})`);
5454
+ logger$3.log(` Found existing project: ${project.name} (${project.projectId})`);
5453
5455
  const projectDetails = await api.getProject(project.projectId);
5454
5456
  const environments = projectDetails.environments ?? [];
5455
5457
  const matchingEnv = environments.find((e) => e.name.toLowerCase() === stage.toLowerCase());
5456
5458
  if (matchingEnv) {
5457
5459
  environmentId = matchingEnv.environmentId;
5458
- logger$1.log(` Using environment: ${matchingEnv.name}`);
5460
+ logger$3.log(` Using environment: ${matchingEnv.name}`);
5459
5461
  } else {
5460
- logger$1.log(` Creating "${stage}" environment...`);
5462
+ logger$3.log(` Creating "${stage}" environment...`);
5461
5463
  const env = await api.createEnvironment(project.projectId, stage);
5462
5464
  environmentId = env.environmentId;
5463
- logger$1.log(` ✓ Created environment: ${stage}`);
5465
+ logger$3.log(` ✓ Created environment: ${stage}`);
5464
5466
  }
5465
5467
  } else {
5466
- logger$1.log(` Creating project: ${projectName}`);
5468
+ logger$3.log(` Creating project: ${projectName}`);
5467
5469
  const result = await api.createProject(projectName);
5468
5470
  project = result.project;
5469
5471
  if (result.environment.name.toLowerCase() !== stage.toLowerCase()) {
5470
- logger$1.log(` Creating "${stage}" environment...`);
5472
+ logger$3.log(` Creating "${stage}" environment...`);
5471
5473
  const env = await api.createEnvironment(project.projectId, stage);
5472
5474
  environmentId = env.environmentId;
5473
5475
  } else environmentId = result.environment.environmentId;
5474
- logger$1.log(` ✓ Created project: ${project.projectId}`);
5475
- logger$1.log(` ✓ Using environment: ${stage}`);
5476
+ logger$3.log(` ✓ Created project: ${project.projectId}`);
5477
+ logger$3.log(` ✓ Using environment: ${stage}`);
5476
5478
  }
5477
- logger$1.log("\n📦 Looking for application...");
5479
+ logger$3.log("\n📦 Looking for application...");
5478
5480
  const appName = dockerConfig.appName;
5479
5481
  let applicationId;
5480
5482
  if (existingConfig && typeof existingConfig !== "boolean" && existingConfig.applicationId) {
5481
5483
  applicationId = existingConfig.applicationId;
5482
- logger$1.log(` Using application from config: ${applicationId}`);
5484
+ logger$3.log(` Using application from config: ${applicationId}`);
5483
5485
  } else {
5484
- logger$1.log(` Creating application: ${appName}`);
5486
+ logger$3.log(` Creating application: ${appName}`);
5485
5487
  const app = await api.createApplication(appName, project.projectId, environmentId);
5486
5488
  applicationId = app.applicationId;
5487
- logger$1.log(` ✓ Created application: ${applicationId}`);
5489
+ logger$3.log(` ✓ Created application: ${applicationId}`);
5488
5490
  }
5489
- logger$1.log("\n🐳 Checking registry...");
5491
+ logger$3.log("\n🐳 Checking registry...");
5490
5492
  let registryId = await require_credentials.getDokployRegistryId();
5491
5493
  if (registryId) try {
5492
5494
  const registry = await api.getRegistry(registryId);
5493
- logger$1.log(` Using registry: ${registry.registryName}`);
5495
+ logger$3.log(` Using registry: ${registry.registryName}`);
5494
5496
  } catch {
5495
- logger$1.log(" ⚠ Stored registry not found, clearing...");
5497
+ logger$3.log(" ⚠ Stored registry not found, clearing...");
5496
5498
  registryId = void 0;
5497
5499
  await require_credentials.storeDokployRegistryId("");
5498
5500
  }
5499
5501
  if (!registryId) {
5500
5502
  const registries = await api.listRegistries();
5501
5503
  if (registries.length === 0) if (dockerConfig.registry) {
5502
- logger$1.log(" No registries found in Dokploy. Let's create one.");
5503
- logger$1.log(` Registry URL: ${dockerConfig.registry}`);
5504
+ logger$3.log(" No registries found in Dokploy. Let's create one.");
5505
+ logger$3.log(` Registry URL: ${dockerConfig.registry}`);
5504
5506
  const username = await prompt("Registry username: ");
5505
5507
  const password = await prompt("Registry password/token: ", true);
5506
5508
  const registry = await api.createRegistry("Default Registry", dockerConfig.registry, username, password);
5507
5509
  registryId = registry.registryId;
5508
5510
  await require_credentials.storeDokployRegistryId(registryId);
5509
- logger$1.log(` ✓ Registry created: ${registryId}`);
5510
- } else logger$1.log(" ⚠ No registry configured. Set docker.registry in gkm.config.ts");
5511
+ logger$3.log(` ✓ Registry created: ${registryId}`);
5512
+ } else logger$3.log(" ⚠ No registry configured. Set docker.registry in gkm.config.ts");
5511
5513
  else {
5512
- logger$1.log(" Available registries:");
5514
+ logger$3.log(" Available registries:");
5513
5515
  registries.forEach((reg, i) => {
5514
- logger$1.log(` ${i + 1}. ${reg.registryName} (${reg.registryUrl})`);
5516
+ logger$3.log(` ${i + 1}. ${reg.registryName} (${reg.registryUrl})`);
5515
5517
  });
5516
- if (dockerConfig.registry) logger$1.log(` ${registries.length + 1}. Create new registry`);
5518
+ if (dockerConfig.registry) logger$3.log(` ${registries.length + 1}. Create new registry`);
5517
5519
  const maxOption = dockerConfig.registry ? registries.length + 1 : registries.length;
5518
5520
  const selection = await prompt(` Select registry (1-${maxOption}): `);
5519
5521
  const index = parseInt(selection, 10) - 1;
5520
5522
  if (index >= 0 && index < registries.length) {
5521
5523
  registryId = registries[index].registryId;
5522
5524
  await require_credentials.storeDokployRegistryId(registryId);
5523
- logger$1.log(` ✓ Selected: ${registries[index].registryName}`);
5525
+ logger$3.log(` ✓ Selected: ${registries[index].registryName}`);
5524
5526
  } else if (dockerConfig.registry && index === registries.length) {
5525
- logger$1.log(`\n Creating new registry...`);
5526
- logger$1.log(` Registry URL: ${dockerConfig.registry}`);
5527
+ logger$3.log(`\n Creating new registry...`);
5528
+ logger$3.log(` Registry URL: ${dockerConfig.registry}`);
5527
5529
  const username = await prompt(" Registry username: ");
5528
5530
  const password = await prompt(" Registry password/token: ", true);
5529
5531
  const registry = await api.createRegistry(dockerConfig.registry.replace(/^https?:\/\//, ""), dockerConfig.registry, username, password);
5530
5532
  registryId = registry.registryId;
5531
5533
  await require_credentials.storeDokployRegistryId(registryId);
5532
- logger$1.log(` ✓ Registry created: ${registryId}`);
5533
- } else logger$1.log(" ⚠ Invalid selection, skipping registry setup");
5534
+ logger$3.log(` ✓ Registry created: ${registryId}`);
5535
+ } else logger$3.log(" ⚠ Invalid selection, skipping registry setup");
5534
5536
  }
5535
5537
  }
5536
5538
  const dokployConfig = {
@@ -5540,10 +5542,10 @@ async function ensureDokploySetup(config, dockerConfig, stage, services) {
5540
5542
  registryId: registryId ?? void 0
5541
5543
  };
5542
5544
  await updateConfig(dokployConfig);
5543
- logger$1.log("\n✅ Dokploy setup complete!");
5544
- logger$1.log(` Project: ${project.projectId}`);
5545
- logger$1.log(` Application: ${applicationId}`);
5546
- if (registryId) logger$1.log(` Registry: ${registryId}`);
5545
+ logger$3.log("\n✅ Dokploy setup complete!");
5546
+ logger$3.log(` Project: ${project.projectId}`);
5547
+ logger$3.log(` Application: ${applicationId}`);
5548
+ if (registryId) logger$3.log(` Registry: ${registryId}`);
5547
5549
  const provisionResult = await provisionServices(api, project.projectId, environmentId, dockerConfig.appName, services, void 0);
5548
5550
  return {
5549
5551
  config: dokployConfig,
@@ -5574,45 +5576,45 @@ function generateTag(stage) {
5574
5576
  async function workspaceDeployCommand(workspace, options) {
5575
5577
  const { provider, stage, tag, apps: selectedApps } = options;
5576
5578
  if (provider !== "dokploy") throw new Error(`Workspace deployment only supports Dokploy. Got: ${provider}`);
5577
- logger$1.log(`\n🚀 Deploying workspace "${workspace.name}" to Dokploy...`);
5578
- logger$1.log(` Stage: ${stage}`);
5579
+ logger$3.log(`\n🚀 Deploying workspace "${workspace.name}" to Dokploy...`);
5580
+ logger$3.log(` Stage: ${stage}`);
5579
5581
  const imageTag = tag ?? generateTag(stage);
5580
- logger$1.log(` Tag: ${imageTag}`);
5582
+ logger$3.log(` Tag: ${imageTag}`);
5581
5583
  const buildOrder = require_workspace.getAppBuildOrder(workspace);
5582
5584
  let appsToDeployNames = buildOrder;
5583
5585
  if (selectedApps && selectedApps.length > 0) {
5584
5586
  const invalidApps = selectedApps.filter((name$1) => !workspace.apps[name$1]);
5585
5587
  if (invalidApps.length > 0) throw new Error(`Unknown apps: ${invalidApps.join(", ")}\nAvailable apps: ${Object.keys(workspace.apps).join(", ")}`);
5586
5588
  appsToDeployNames = buildOrder.filter((name$1) => selectedApps.includes(name$1));
5587
- logger$1.log(` Deploying apps: ${appsToDeployNames.join(", ")}`);
5588
- } else logger$1.log(` Deploying all apps: ${appsToDeployNames.join(", ")}`);
5589
+ logger$3.log(` Deploying apps: ${appsToDeployNames.join(", ")}`);
5590
+ } else logger$3.log(` Deploying all apps: ${appsToDeployNames.join(", ")}`);
5589
5591
  const dokployApps = appsToDeployNames.filter((name$1) => {
5590
5592
  const app = workspace.apps[name$1];
5591
5593
  const target = app.resolvedDeployTarget;
5592
5594
  if (!require_workspace.isDeployTargetSupported(target)) {
5593
- logger$1.log(` ⚠️ Skipping ${name$1}: ${require_workspace.getDeployTargetError(target, name$1)}`);
5595
+ logger$3.log(` ⚠️ Skipping ${name$1}: ${require_workspace.getDeployTargetError(target, name$1)}`);
5594
5596
  return false;
5595
5597
  }
5596
5598
  return true;
5597
5599
  });
5598
5600
  if (dokployApps.length === 0) throw new Error("No apps to deploy. All selected apps have unsupported deploy targets.");
5599
5601
  appsToDeployNames = dokployApps;
5600
- logger$1.log("\n🔐 Loading secrets and analyzing environment requirements...");
5602
+ logger$3.log("\n🔐 Loading secrets and analyzing environment requirements...");
5601
5603
  const stageSecrets = await require_storage.readStageSecrets(stage, workspace.root);
5602
5604
  if (!stageSecrets) {
5603
- logger$1.log(` ⚠️ No secrets found for stage "${stage}"`);
5604
- logger$1.log(` Run "gkm secrets:init --stage ${stage}" to create secrets`);
5605
+ logger$3.log(` ⚠️ No secrets found for stage "${stage}"`);
5606
+ logger$3.log(` Run "gkm secrets:init --stage ${stage}" to create secrets`);
5605
5607
  }
5606
5608
  const sniffedApps = await sniffAllApps(workspace.apps, workspace.root);
5607
5609
  const encryptedSecrets = stageSecrets ? prepareSecretsForAllApps(stageSecrets, sniffedApps) : /* @__PURE__ */ new Map();
5608
5610
  if (stageSecrets) {
5609
5611
  const report = generateSecretsReport(encryptedSecrets, sniffedApps);
5610
- if (report.appsWithSecrets.length > 0) logger$1.log(` ✓ Encrypted secrets for: ${report.appsWithSecrets.join(", ")}`);
5611
- if (report.appsWithMissingSecrets.length > 0) for (const { appName, missing } of report.appsWithMissingSecrets) logger$1.log(` ⚠️ ${appName}: Missing secrets: ${missing.join(", ")}`);
5612
+ if (report.appsWithSecrets.length > 0) logger$3.log(` ✓ Encrypted secrets for: ${report.appsWithSecrets.join(", ")}`);
5613
+ if (report.appsWithMissingSecrets.length > 0) for (const { appName, missing } of report.appsWithMissingSecrets) logger$3.log(` ⚠️ ${appName}: Missing secrets: ${missing.join(", ")}`);
5612
5614
  }
5613
5615
  let creds = await require_credentials.getDokployCredentials();
5614
5616
  if (!creds) {
5615
- logger$1.log("\n📋 Dokploy credentials not found. Let's set them up.");
5617
+ logger$3.log("\n📋 Dokploy credentials not found. Let's set them up.");
5616
5618
  const endpoint = await prompt("Dokploy URL (e.g., https://dokploy.example.com): ");
5617
5619
  const normalizedEndpoint = endpoint.replace(/\/$/, "");
5618
5620
  try {
@@ -5620,9 +5622,9 @@ async function workspaceDeployCommand(workspace, options) {
5620
5622
  } catch {
5621
5623
  throw new Error("Invalid URL format");
5622
5624
  }
5623
- logger$1.log(`\nGenerate a token at: ${normalizedEndpoint}/settings/profile\n`);
5625
+ logger$3.log(`\nGenerate a token at: ${normalizedEndpoint}/settings/profile\n`);
5624
5626
  const token = await prompt("API Token: ", true);
5625
- logger$1.log("\nValidating credentials...");
5627
+ logger$3.log("\nValidating credentials...");
5626
5628
  const isValid = await validateDokployToken(normalizedEndpoint, token);
5627
5629
  if (!isValid) throw new Error("Invalid credentials. Please check your token.");
5628
5630
  await require_credentials.storeDokployCredentials(token, normalizedEndpoint);
@@ -5630,43 +5632,43 @@ async function workspaceDeployCommand(workspace, options) {
5630
5632
  token,
5631
5633
  endpoint: normalizedEndpoint
5632
5634
  };
5633
- logger$1.log("✓ Credentials saved");
5635
+ logger$3.log("✓ Credentials saved");
5634
5636
  }
5635
5637
  const api = new require_dokploy_api.DokployApi({
5636
5638
  baseUrl: creds.endpoint,
5637
5639
  token: creds.token
5638
5640
  });
5639
- logger$1.log("\n📁 Setting up Dokploy project...");
5641
+ logger$3.log("\n📁 Setting up Dokploy project...");
5640
5642
  const projectName = workspace.name;
5641
5643
  const projects = await api.listProjects();
5642
5644
  let project = projects.find((p) => p.name.toLowerCase() === projectName.toLowerCase());
5643
5645
  let environmentId;
5644
5646
  if (project) {
5645
- logger$1.log(` Found existing project: ${project.name}`);
5647
+ logger$3.log(` Found existing project: ${project.name}`);
5646
5648
  const projectDetails = await api.getProject(project.projectId);
5647
5649
  const environments = projectDetails.environments ?? [];
5648
5650
  const matchingEnv = environments.find((e) => e.name.toLowerCase() === stage.toLowerCase());
5649
5651
  if (matchingEnv) {
5650
5652
  environmentId = matchingEnv.environmentId;
5651
- logger$1.log(` Using environment: ${matchingEnv.name}`);
5653
+ logger$3.log(` Using environment: ${matchingEnv.name}`);
5652
5654
  } else {
5653
- logger$1.log(` Creating "${stage}" environment...`);
5655
+ logger$3.log(` Creating "${stage}" environment...`);
5654
5656
  const env = await api.createEnvironment(project.projectId, stage);
5655
5657
  environmentId = env.environmentId;
5656
- logger$1.log(` ✓ Created environment: ${stage}`);
5658
+ logger$3.log(` ✓ Created environment: ${stage}`);
5657
5659
  }
5658
5660
  } else {
5659
- logger$1.log(` Creating project: ${projectName}`);
5661
+ logger$3.log(` Creating project: ${projectName}`);
5660
5662
  const result = await api.createProject(projectName);
5661
5663
  project = result.project;
5662
5664
  if (result.environment.name.toLowerCase() !== stage.toLowerCase()) {
5663
- logger$1.log(` Creating "${stage}" environment...`);
5665
+ logger$3.log(` Creating "${stage}" environment...`);
5664
5666
  const env = await api.createEnvironment(project.projectId, stage);
5665
5667
  environmentId = env.environmentId;
5666
5668
  } else environmentId = result.environment.environmentId;
5667
- logger$1.log(` ✓ Created project: ${project.projectId}`);
5669
+ logger$3.log(` ✓ Created project: ${project.projectId}`);
5668
5670
  }
5669
- logger$1.log("\n📋 Loading deploy state...");
5671
+ logger$3.log("\n📋 Loading deploy state...");
5670
5672
  const stateProvider = await createStateProvider({
5671
5673
  config: workspace.state,
5672
5674
  workspaceRoot: workspace.root,
@@ -5674,27 +5676,27 @@ async function workspaceDeployCommand(workspace, options) {
5674
5676
  });
5675
5677
  let state = await stateProvider.read(stage);
5676
5678
  if (state) {
5677
- logger$1.log(` Found existing state for stage "${stage}"`);
5679
+ logger$3.log(` Found existing state for stage "${stage}"`);
5678
5680
  if (state.projectId !== project.projectId) {
5679
- logger$1.log(` ⚠ Project ID changed, updating state`);
5681
+ logger$3.log(` ⚠ Project ID changed, updating state`);
5680
5682
  state.projectId = project.projectId;
5681
5683
  }
5682
5684
  if (state.environmentId !== environmentId) {
5683
- logger$1.log(` ⚠ Environment ID changed, updating state`);
5685
+ logger$3.log(` ⚠ Environment ID changed, updating state`);
5684
5686
  state.environmentId = environmentId;
5685
5687
  }
5686
5688
  } else {
5687
- logger$1.log(` Creating new state for stage "${stage}"`);
5689
+ logger$3.log(` Creating new state for stage "${stage}"`);
5688
5690
  state = createEmptyState(stage, project.projectId, environmentId);
5689
5691
  }
5690
- logger$1.log("\n🐳 Checking registry...");
5692
+ logger$3.log("\n🐳 Checking registry...");
5691
5693
  let registryId = await require_credentials.getDokployRegistryId();
5692
5694
  const registry = workspace.deploy.dokploy?.registry;
5693
5695
  if (registryId) try {
5694
5696
  const reg = await api.getRegistry(registryId);
5695
- logger$1.log(` Using registry: ${reg.registryName}`);
5697
+ logger$3.log(` Using registry: ${reg.registryName}`);
5696
5698
  } catch {
5697
- logger$1.log(" ⚠ Stored registry not found, clearing...");
5699
+ logger$3.log(" ⚠ Stored registry not found, clearing...");
5698
5700
  registryId = void 0;
5699
5701
  await require_credentials.storeDokployRegistryId("");
5700
5702
  }
@@ -5703,17 +5705,17 @@ async function workspaceDeployCommand(workspace, options) {
5703
5705
  if (registries.length > 0) {
5704
5706
  registryId = registries[0].registryId;
5705
5707
  await require_credentials.storeDokployRegistryId(registryId);
5706
- logger$1.log(` Using registry: ${registries[0].registryName}`);
5708
+ logger$3.log(` Using registry: ${registries[0].registryName}`);
5707
5709
  } else if (registry) {
5708
- logger$1.log(" No registries found in Dokploy. Let's create one.");
5709
- logger$1.log(` Registry URL: ${registry}`);
5710
+ logger$3.log(" No registries found in Dokploy. Let's create one.");
5711
+ logger$3.log(` Registry URL: ${registry}`);
5710
5712
  const username = await prompt("Registry username: ");
5711
5713
  const password = await prompt("Registry password/token: ", true);
5712
5714
  const reg = await api.createRegistry("Default Registry", registry, username, password);
5713
5715
  registryId = reg.registryId;
5714
5716
  await require_credentials.storeDokployRegistryId(registryId);
5715
- logger$1.log(` ✓ Registry created: ${registryId}`);
5716
- } else logger$1.log(" ⚠ No registry configured. Set deploy.dokploy.registry in workspace config");
5717
+ logger$3.log(` ✓ Registry created: ${registryId}`);
5718
+ } else logger$3.log(" ⚠ No registry configured. Set deploy.dokploy.registry in workspace config");
5717
5719
  }
5718
5720
  const services = workspace.services;
5719
5721
  const dockerServices = {
@@ -5723,7 +5725,7 @@ async function workspaceDeployCommand(workspace, options) {
5723
5725
  let provisionedPostgres = null;
5724
5726
  let provisionedRedis = null;
5725
5727
  if (dockerServices.postgres || dockerServices.redis) {
5726
- logger$1.log("\n🔧 Provisioning infrastructure services...");
5728
+ logger$3.log("\n🔧 Provisioning infrastructure services...");
5727
5729
  const existingServiceIds = {
5728
5730
  postgresId: getPostgresId(state),
5729
5731
  redisId: getRedisId(state)
@@ -5749,13 +5751,13 @@ async function workspaceDeployCommand(workspace, options) {
5749
5751
  return requirements?.requiredEnvVars.includes("DATABASE_URL");
5750
5752
  });
5751
5753
  if (appsNeedingDb.length > 0) {
5752
- logger$1.log(`\n🔐 Setting up per-app database credentials...`);
5753
- logger$1.log(` Apps needing DATABASE_URL: ${appsNeedingDb.join(", ")}`);
5754
+ logger$3.log(`\n🔐 Setting up per-app database credentials...`);
5755
+ logger$3.log(` Apps needing DATABASE_URL: ${appsNeedingDb.join(", ")}`);
5754
5756
  const existingCredentials = getAllAppCredentials(state);
5755
5757
  const usersToCreate = [];
5756
5758
  for (const appName of appsNeedingDb) {
5757
5759
  let credentials = existingCredentials[appName];
5758
- if (credentials) logger$1.log(` ${appName}: Using existing credentials from state`);
5760
+ if (credentials) logger$3.log(` ${appName}: Using existing credentials from state`);
5759
5761
  else {
5760
5762
  const password = (0, node_crypto.randomBytes)(16).toString("hex");
5761
5763
  credentials = {
@@ -5763,7 +5765,7 @@ async function workspaceDeployCommand(workspace, options) {
5763
5765
  dbPassword: password
5764
5766
  };
5765
5767
  setAppCredentials(state, appName, credentials);
5766
- logger$1.log(` ${appName}: Generated new credentials`);
5768
+ logger$3.log(` ${appName}: Generated new credentials`);
5767
5769
  }
5768
5770
  perAppDbCredentials.set(appName, credentials);
5769
5771
  usersToCreate.push({
@@ -5777,8 +5779,8 @@ async function workspaceDeployCommand(workspace, options) {
5777
5779
  }
5778
5780
  }
5779
5781
  if (workspace.deploy?.backups && provisionedPostgres) {
5780
- logger$1.log("\n💾 Provisioning backup destination...");
5781
- const { provisionBackupDestination } = await Promise.resolve().then(() => require("./backup-provisioner-B5e-F6zX.cjs"));
5782
+ logger$3.log("\n💾 Provisioning backup destination...");
5783
+ const { provisionBackupDestination } = await Promise.resolve().then(() => require("./backup-provisioner-C8VK63I-.cjs"));
5782
5784
  const backupState = await provisionBackupDestination({
5783
5785
  api,
5784
5786
  projectId: project.projectId,
@@ -5786,13 +5788,13 @@ async function workspaceDeployCommand(workspace, options) {
5786
5788
  stage,
5787
5789
  config: workspace.deploy.backups,
5788
5790
  existingState: getBackupState(state),
5789
- logger: logger$1
5791
+ logger: logger$3
5790
5792
  });
5791
5793
  setBackupState(state, backupState);
5792
5794
  if (!backupState.postgresBackupId) {
5793
5795
  const backupSchedule = workspace.deploy.backups.schedule ?? "0 2 * * *";
5794
5796
  const backupRetention = workspace.deploy.backups.retention ?? 30;
5795
- logger$1.log(" Creating postgres backup schedule...");
5797
+ logger$3.log(" Creating postgres backup schedule...");
5796
5798
  const backup = await api.createPostgresBackup({
5797
5799
  schedule: backupSchedule,
5798
5800
  prefix: `${stage}/postgres`,
@@ -5803,8 +5805,8 @@ async function workspaceDeployCommand(workspace, options) {
5803
5805
  keepLatestCount: backupRetention
5804
5806
  });
5805
5807
  setPostgresBackupId(state, backup.backupId);
5806
- logger$1.log(` ✓ Postgres backup schedule created (${backupSchedule})`);
5807
- } else logger$1.log(" ✓ Using existing postgres backup schedule");
5808
+ logger$3.log(` ✓ Postgres backup schedule created (${backupSchedule})`);
5809
+ } else logger$3.log(" ✓ Using existing postgres backup schedule");
5808
5810
  }
5809
5811
  const publicUrls = {};
5810
5812
  const results = [];
@@ -5819,25 +5821,25 @@ async function workspaceDeployCommand(workspace, options) {
5819
5821
  frontendUrls.push(`https://${hostname}`);
5820
5822
  }
5821
5823
  if (backendApps.length > 0) {
5822
- logger$1.log("\n📦 PHASE 1: Deploying backend applications...");
5824
+ logger$3.log("\n📦 PHASE 1: Deploying backend applications...");
5823
5825
  for (const appName of backendApps) {
5824
5826
  const app = workspace.apps[appName];
5825
- logger$1.log(`\n ⚙️ Deploying ${appName}...`);
5827
+ logger$3.log(`\n ⚙️ Deploying ${appName}...`);
5826
5828
  try {
5827
5829
  const dokployAppName = appName;
5828
5830
  let application = null;
5829
5831
  const cachedAppId = getApplicationId(state, appName);
5830
5832
  if (cachedAppId) {
5831
- logger$1.log(` Using cached ID: ${cachedAppId}`);
5833
+ logger$3.log(` Using cached ID: ${cachedAppId}`);
5832
5834
  application = await api.getApplication(cachedAppId);
5833
- if (application) logger$1.log(` ✓ Application found: ${application.applicationId}`);
5834
- else logger$1.log(` ⚠ Cached ID invalid, will create new`);
5835
+ if (application) logger$3.log(` ✓ Application found: ${application.applicationId}`);
5836
+ else logger$3.log(` ⚠ Cached ID invalid, will create new`);
5835
5837
  }
5836
5838
  if (!application) {
5837
5839
  const result = await api.findOrCreateApplication(dokployAppName, project.projectId, environmentId);
5838
5840
  application = result.application;
5839
- if (result.created) logger$1.log(` Created application: ${application.applicationId}`);
5840
- else logger$1.log(` Found existing application: ${application.applicationId}`);
5841
+ if (result.created) logger$3.log(` Created application: ${application.applicationId}`);
5842
+ else logger$3.log(` Found existing application: ${application.applicationId}`);
5841
5843
  }
5842
5844
  setApplicationId(state, appName, application.applicationId);
5843
5845
  const appSecrets = encryptedSecrets.get(appName);
@@ -5845,11 +5847,11 @@ async function workspaceDeployCommand(workspace, options) {
5845
5847
  if (appSecrets && appSecrets.secretCount > 0) {
5846
5848
  buildArgs.push(`GKM_ENCRYPTED_CREDENTIALS=${appSecrets.payload.encrypted}`);
5847
5849
  buildArgs.push(`GKM_CREDENTIALS_IV=${appSecrets.payload.iv}`);
5848
- logger$1.log(` Encrypted ${appSecrets.secretCount} secrets`);
5850
+ logger$3.log(` Encrypted ${appSecrets.secretCount} secrets`);
5849
5851
  }
5850
5852
  const imageName = `${workspace.name}-${appName}`;
5851
5853
  const imageRef = registry ? `${registry}/${imageName}:${imageTag}` : `${imageName}:${imageTag}`;
5852
- logger$1.log(` Building Docker image: ${imageRef}`);
5854
+ logger$3.log(` Building Docker image: ${imageRef}`);
5853
5855
  await deployDocker({
5854
5856
  stage,
5855
5857
  tag: imageTag,
@@ -5899,10 +5901,10 @@ async function workspaceDeployCommand(workspace, options) {
5899
5901
  const { valid, missing, resolved } = validateEnvVars(requiredVars, envContext);
5900
5902
  if (!valid) throw new Error(formatMissingVarsError(appName, missing, stage));
5901
5903
  const envVars = Object.entries(resolved).map(([key, value]) => `${key}=${value}`);
5902
- if (Object.keys(resolved).length > 0) logger$1.log(` Resolved ${Object.keys(resolved).length} env vars: ${Object.keys(resolved).join(", ")}`);
5904
+ if (Object.keys(resolved).length > 0) logger$3.log(` Resolved ${Object.keys(resolved).length} env vars: ${Object.keys(resolved).join(", ")}`);
5903
5905
  await api.saveDockerProvider(application.applicationId, imageRef, { registryId });
5904
5906
  await api.saveApplicationEnv(application.applicationId, envVars.join("\n"));
5905
- logger$1.log(` Deploying to Dokploy...`);
5907
+ logger$3.log(` Deploying to Dokploy...`);
5906
5908
  await api.deployApplication(application.applicationId);
5907
5909
  const existingDomains = await api.getDomainsByApplicationId(application.applicationId);
5908
5910
  const existingDomain = existingDomains.find((d) => d.host === backendHost);
@@ -5910,7 +5912,7 @@ async function workspaceDeployCommand(workspace, options) {
5910
5912
  appHostnames.set(appName, backendHost);
5911
5913
  appDomainIds.set(appName, existingDomain.domainId);
5912
5914
  publicUrls[appName] = `https://${backendHost}`;
5913
- logger$1.log(` ✓ Domain: https://${backendHost} (existing)`);
5915
+ logger$3.log(` ✓ Domain: https://${backendHost} (existing)`);
5914
5916
  } else try {
5915
5917
  const domain = await api.createDomain({
5916
5918
  host: backendHost,
@@ -5922,10 +5924,10 @@ async function workspaceDeployCommand(workspace, options) {
5922
5924
  appHostnames.set(appName, backendHost);
5923
5925
  appDomainIds.set(appName, domain.domainId);
5924
5926
  publicUrls[appName] = `https://${backendHost}`;
5925
- logger$1.log(` ✓ Domain: https://${backendHost} (created)`);
5927
+ logger$3.log(` ✓ Domain: https://${backendHost} (created)`);
5926
5928
  } catch (domainError) {
5927
5929
  const message = domainError instanceof Error ? domainError.message : "Unknown error";
5928
- logger$1.log(` ⚠ Domain creation failed: ${message}`);
5930
+ logger$3.log(` ⚠ Domain creation failed: ${message}`);
5929
5931
  appHostnames.set(appName, backendHost);
5930
5932
  publicUrls[appName] = `https://${backendHost}`;
5931
5933
  }
@@ -5936,10 +5938,10 @@ async function workspaceDeployCommand(workspace, options) {
5936
5938
  applicationId: application.applicationId,
5937
5939
  imageRef
5938
5940
  });
5939
- logger$1.log(` ✓ ${appName} deployed successfully`);
5941
+ logger$3.log(` ✓ ${appName} deployed successfully`);
5940
5942
  } catch (error) {
5941
5943
  const message = error instanceof Error ? error.message : "Unknown error";
5942
- logger$1.log(` ✗ Failed to deploy ${appName}: ${message}`);
5944
+ logger$3.log(` ✗ Failed to deploy ${appName}: ${message}`);
5943
5945
  results.push({
5944
5946
  appName,
5945
5947
  type: app.type,
@@ -5951,25 +5953,25 @@ async function workspaceDeployCommand(workspace, options) {
5951
5953
  }
5952
5954
  }
5953
5955
  if (frontendApps.length > 0) {
5954
- logger$1.log("\n🌐 PHASE 2: Deploying frontend applications...");
5956
+ logger$3.log("\n🌐 PHASE 2: Deploying frontend applications...");
5955
5957
  for (const appName of frontendApps) {
5956
5958
  const app = workspace.apps[appName];
5957
- logger$1.log(`\n 🌐 Deploying ${appName}...`);
5959
+ logger$3.log(`\n 🌐 Deploying ${appName}...`);
5958
5960
  try {
5959
5961
  const dokployAppName = appName;
5960
5962
  let application = null;
5961
5963
  const cachedAppId = getApplicationId(state, appName);
5962
5964
  if (cachedAppId) {
5963
- logger$1.log(` Using cached ID: ${cachedAppId}`);
5965
+ logger$3.log(` Using cached ID: ${cachedAppId}`);
5964
5966
  application = await api.getApplication(cachedAppId);
5965
- if (application) logger$1.log(` ✓ Application found: ${application.applicationId}`);
5966
- else logger$1.log(` ⚠ Cached ID invalid, will create new`);
5967
+ if (application) logger$3.log(` ✓ Application found: ${application.applicationId}`);
5968
+ else logger$3.log(` ⚠ Cached ID invalid, will create new`);
5967
5969
  }
5968
5970
  if (!application) {
5969
5971
  const result = await api.findOrCreateApplication(dokployAppName, project.projectId, environmentId);
5970
5972
  application = result.application;
5971
- if (result.created) logger$1.log(` Created application: ${application.applicationId}`);
5972
- else logger$1.log(` Found existing application: ${application.applicationId}`);
5973
+ if (result.created) logger$3.log(` Created application: ${application.applicationId}`);
5974
+ else logger$3.log(` Found existing application: ${application.applicationId}`);
5973
5975
  }
5974
5976
  setApplicationId(state, appName, application.applicationId);
5975
5977
  const dependencyUrls = {};
@@ -5991,17 +5993,17 @@ async function workspaceDeployCommand(workspace, options) {
5991
5993
  const sniffedVars = sniffedApps.get(appName)?.requiredEnvVars ?? [];
5992
5994
  const { valid, missing, resolved } = validateEnvVars(sniffedVars, envContext);
5993
5995
  if (!valid) throw new Error(formatMissingVarsError(appName, missing, stage));
5994
- if (Object.keys(resolved).length > 0) logger$1.log(` Resolved ${Object.keys(resolved).length} env vars: ${Object.keys(resolved).join(", ")}`);
5996
+ if (Object.keys(resolved).length > 0) logger$3.log(` Resolved ${Object.keys(resolved).length} env vars: ${Object.keys(resolved).join(", ")}`);
5995
5997
  const buildArgs = [];
5996
5998
  const publicUrlArgNames = [];
5997
5999
  for (const [key, value] of Object.entries(resolved)) if (key.startsWith("NEXT_PUBLIC_")) {
5998
6000
  buildArgs.push(`${key}=${value}`);
5999
6001
  publicUrlArgNames.push(key);
6000
6002
  }
6001
- if (buildArgs.length > 0) logger$1.log(` Build args: ${publicUrlArgNames.join(", ")}`);
6003
+ if (buildArgs.length > 0) logger$3.log(` Build args: ${publicUrlArgNames.join(", ")}`);
6002
6004
  const imageName = `${workspace.name}-${appName}`;
6003
6005
  const imageRef = registry ? `${registry}/${imageName}:${imageTag}` : `${imageName}:${imageTag}`;
6004
- logger$1.log(` Building Docker image: ${imageRef}`);
6006
+ logger$3.log(` Building Docker image: ${imageRef}`);
6005
6007
  await deployDocker({
6006
6008
  stage,
6007
6009
  tag: imageTag,
@@ -6022,7 +6024,7 @@ async function workspaceDeployCommand(workspace, options) {
6022
6024
  for (const [key, value] of Object.entries(resolved)) envVars.push(`${key}=${value}`);
6023
6025
  await api.saveDockerProvider(application.applicationId, imageRef, { registryId });
6024
6026
  await api.saveApplicationEnv(application.applicationId, envVars.join("\n"));
6025
- logger$1.log(` Deploying to Dokploy...`);
6027
+ logger$3.log(` Deploying to Dokploy...`);
6026
6028
  await api.deployApplication(application.applicationId);
6027
6029
  const existingFrontendDomains = await api.getDomainsByApplicationId(application.applicationId);
6028
6030
  const existingFrontendDomain = existingFrontendDomains.find((d) => d.host === frontendHost);
@@ -6030,7 +6032,7 @@ async function workspaceDeployCommand(workspace, options) {
6030
6032
  appHostnames.set(appName, frontendHost);
6031
6033
  appDomainIds.set(appName, existingFrontendDomain.domainId);
6032
6034
  publicUrls[appName] = `https://${frontendHost}`;
6033
- logger$1.log(` ✓ Domain: https://${frontendHost} (existing)`);
6035
+ logger$3.log(` ✓ Domain: https://${frontendHost} (existing)`);
6034
6036
  } else try {
6035
6037
  const domain = await api.createDomain({
6036
6038
  host: frontendHost,
@@ -6042,10 +6044,10 @@ async function workspaceDeployCommand(workspace, options) {
6042
6044
  appHostnames.set(appName, frontendHost);
6043
6045
  appDomainIds.set(appName, domain.domainId);
6044
6046
  publicUrls[appName] = `https://${frontendHost}`;
6045
- logger$1.log(` ✓ Domain: https://${frontendHost} (created)`);
6047
+ logger$3.log(` ✓ Domain: https://${frontendHost} (created)`);
6046
6048
  } catch (domainError) {
6047
6049
  const message = domainError instanceof Error ? domainError.message : "Unknown error";
6048
- logger$1.log(` ⚠ Domain creation failed: ${message}`);
6050
+ logger$3.log(` ⚠ Domain creation failed: ${message}`);
6049
6051
  appHostnames.set(appName, frontendHost);
6050
6052
  publicUrls[appName] = `https://${frontendHost}`;
6051
6053
  }
@@ -6056,10 +6058,10 @@ async function workspaceDeployCommand(workspace, options) {
6056
6058
  applicationId: application.applicationId,
6057
6059
  imageRef
6058
6060
  });
6059
- logger$1.log(` ✓ ${appName} deployed successfully`);
6061
+ logger$3.log(` ✓ ${appName} deployed successfully`);
6060
6062
  } catch (error) {
6061
6063
  const message = error instanceof Error ? error.message : "Unknown error";
6062
- logger$1.log(` ✗ Failed to deploy ${appName}: ${message}`);
6064
+ logger$3.log(` ✗ Failed to deploy ${appName}: ${message}`);
6063
6065
  results.push({
6064
6066
  appName,
6065
6067
  type: app.type,
@@ -6069,9 +6071,9 @@ async function workspaceDeployCommand(workspace, options) {
6069
6071
  }
6070
6072
  }
6071
6073
  }
6072
- logger$1.log("\n📋 Saving deploy state...");
6074
+ logger$3.log("\n📋 Saving deploy state...");
6073
6075
  await stateProvider.write(stage, state);
6074
- logger$1.log(" ✓ State saved");
6076
+ logger$3.log(" ✓ State saved");
6075
6077
  const dnsConfig = workspace.deploy.dns;
6076
6078
  if (dnsConfig && appHostnames.size > 0) {
6077
6079
  const dnsResult = await orchestrateDns(appHostnames, dnsConfig, creds.endpoint);
@@ -6080,27 +6082,27 @@ async function workspaceDeployCommand(workspace, options) {
6080
6082
  await stateProvider.write(stage, state);
6081
6083
  }
6082
6084
  if (dnsResult?.success && appHostnames.size > 0) {
6083
- logger$1.log("\n🔒 Validating domains for SSL certificates...");
6085
+ logger$3.log("\n🔒 Validating domains for SSL certificates...");
6084
6086
  for (const [appName, hostname] of appHostnames) try {
6085
6087
  const result = await api.validateDomain(hostname);
6086
- if (result.isValid) logger$1.log(` ✓ ${appName}: ${hostname} → ${result.resolvedIp}`);
6087
- else logger$1.log(` ⚠ ${appName}: ${hostname} not valid`);
6088
+ if (result.isValid) logger$3.log(` ✓ ${appName}: ${hostname} → ${result.resolvedIp}`);
6089
+ else logger$3.log(` ⚠ ${appName}: ${hostname} not valid`);
6088
6090
  } catch (validationError) {
6089
6091
  const message = validationError instanceof Error ? validationError.message : "Unknown error";
6090
- logger$1.log(` ⚠ ${appName}: validation failed - ${message}`);
6092
+ logger$3.log(` ⚠ ${appName}: validation failed - ${message}`);
6091
6093
  }
6092
6094
  }
6093
6095
  }
6094
6096
  const successCount = results.filter((r) => r.success).length;
6095
6097
  const failedCount = results.filter((r) => !r.success).length;
6096
- logger$1.log(`\n${"─".repeat(50)}`);
6097
- logger$1.log(`\n✅ Workspace deployment complete!`);
6098
- logger$1.log(` Project: ${project.projectId}`);
6099
- logger$1.log(` Successful: ${successCount}`);
6100
- if (failedCount > 0) logger$1.log(` Failed: ${failedCount}`);
6098
+ logger$3.log(`\n${"─".repeat(50)}`);
6099
+ logger$3.log(`\n✅ Workspace deployment complete!`);
6100
+ logger$3.log(` Project: ${project.projectId}`);
6101
+ logger$3.log(` Successful: ${successCount}`);
6102
+ if (failedCount > 0) logger$3.log(` Failed: ${failedCount}`);
6101
6103
  if (Object.keys(publicUrls).length > 0) {
6102
- logger$1.log("\n 📡 Deployed URLs:");
6103
- for (const [name$1, url] of Object.entries(publicUrls)) logger$1.log(` ${name$1}: ${url}`);
6104
+ logger$3.log("\n 📡 Deployed URLs:");
6105
+ for (const [name$1, url] of Object.entries(publicUrls)) logger$3.log(` ${name$1}: ${url}`);
6104
6106
  }
6105
6107
  return {
6106
6108
  apps: results,
@@ -6116,14 +6118,14 @@ async function deployCommand(options) {
6116
6118
  const { provider, stage, tag, skipPush, skipBuild } = options;
6117
6119
  const loadedConfig = await require_config.loadWorkspaceConfig();
6118
6120
  if (loadedConfig.type === "workspace") {
6119
- logger$1.log("📦 Detected workspace configuration");
6121
+ logger$3.log("📦 Detected workspace configuration");
6120
6122
  return workspaceDeployCommand(loadedConfig.workspace, options);
6121
6123
  }
6122
- logger$1.log(`\n🚀 Deploying to ${provider}...`);
6123
- logger$1.log(` Stage: ${stage}`);
6124
+ logger$3.log(`\n🚀 Deploying to ${provider}...`);
6125
+ logger$3.log(` Stage: ${stage}`);
6124
6126
  const config = await require_config.loadConfig();
6125
6127
  const imageTag = tag ?? generateTag(stage);
6126
- logger$1.log(` Tag: ${imageTag}`);
6128
+ logger$3.log(` Tag: ${imageTag}`);
6127
6129
  const dockerConfig = resolveDockerConfig(config);
6128
6130
  const imageName = dockerConfig.imageName;
6129
6131
  const registry = dockerConfig.registry;
@@ -6132,7 +6134,7 @@ async function deployCommand(options) {
6132
6134
  let finalRegistry = registry;
6133
6135
  if (provider === "dokploy") {
6134
6136
  const composeServices = config.docker?.compose?.services;
6135
- logger$1.log(`\n🔍 Docker compose config: ${JSON.stringify(config.docker?.compose)}`);
6137
+ logger$3.log(`\n🔍 Docker compose config: ${JSON.stringify(config.docker?.compose)}`);
6136
6138
  const dockerServices = composeServices ? Array.isArray(composeServices) ? {
6137
6139
  postgres: composeServices.includes("postgres"),
6138
6140
  redis: composeServices.includes("redis"),
@@ -6149,7 +6151,7 @@ async function deployCommand(options) {
6149
6151
  const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1, initStageSecrets } = await Promise.resolve().then(() => require("./storage-C7pmBq1u.cjs"));
6150
6152
  let secrets = await readStageSecrets$1(stage);
6151
6153
  if (!secrets) {
6152
- logger$1.log(` Creating secrets file for stage "${stage}"...`);
6154
+ logger$3.log(` Creating secrets file for stage "${stage}"...`);
6153
6155
  secrets = initStageSecrets(stage);
6154
6156
  }
6155
6157
  let updated = false;
@@ -6164,12 +6166,12 @@ async function deployCommand(options) {
6164
6166
  const urlKey = key;
6165
6167
  if (!secrets.urls[urlKey]) {
6166
6168
  secrets.urls[urlKey] = value;
6167
- logger$1.log(` Saved ${key} to secrets.urls`);
6169
+ logger$3.log(` Saved ${key} to secrets.urls`);
6168
6170
  updated = true;
6169
6171
  }
6170
6172
  } else if (!secrets.custom[key]) {
6171
6173
  secrets.custom[key] = value;
6172
- logger$1.log(` Saved ${key} to secrets.custom`);
6174
+ logger$3.log(` Saved ${key} to secrets.custom`);
6173
6175
  updated = true;
6174
6176
  }
6175
6177
  }
@@ -6178,14 +6180,14 @@ async function deployCommand(options) {
6178
6180
  }
6179
6181
  let masterKey;
6180
6182
  if (!skipBuild) {
6181
- logger$1.log(`\n📦 Building for production...`);
6183
+ logger$3.log(`\n📦 Building for production...`);
6182
6184
  const buildResult = await buildCommand({
6183
6185
  provider: "server",
6184
6186
  production: true,
6185
6187
  stage
6186
6188
  });
6187
6189
  masterKey = buildResult.masterKey;
6188
- } else logger$1.log(`\n⏭️ Skipping build (--skip-build)`);
6190
+ } else logger$3.log(`\n⏭️ Skipping build (--skip-build)`);
6189
6191
  let result;
6190
6192
  switch (provider) {
6191
6193
  case "docker": {
@@ -6221,8 +6223,8 @@ async function deployCommand(options) {
6221
6223
  break;
6222
6224
  }
6223
6225
  case "aws-lambda": {
6224
- logger$1.log("\n⚠️ AWS Lambda deployment is not yet implemented.");
6225
- logger$1.log(" Use SST or AWS CDK for Lambda deployments.");
6226
+ logger$3.log("\n⚠️ AWS Lambda deployment is not yet implemented.");
6227
+ logger$3.log(" Use SST or AWS CDK for Lambda deployments.");
6226
6228
  result = {
6227
6229
  imageRef,
6228
6230
  masterKey
@@ -6231,7 +6233,7 @@ async function deployCommand(options) {
6231
6233
  }
6232
6234
  default: throw new Error(`Unknown deploy provider: ${provider}\nSupported providers: docker, dokploy, aws-lambda`);
6233
6235
  }
6234
- logger$1.log("\n✅ Deployment complete!");
6236
+ logger$3.log("\n✅ Deployment complete!");
6235
6237
  return result;
6236
6238
  }
6237
6239
 
@@ -6520,6 +6522,83 @@ function rotateServicePassword(secrets, service) {
6520
6522
  };
6521
6523
  }
6522
6524
 
6525
+ //#endregion
6526
+ //#region src/setup/fullstack-secrets.ts
6527
+ /**
6528
+ * Generate a secure random password for database users.
6529
+ * Uses a combination of timestamp and random bytes for uniqueness.
6530
+ */
6531
+ function generateDbPassword() {
6532
+ return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;
6533
+ }
6534
+ /**
6535
+ * Generate database URL for an app.
6536
+ * All apps connect to the same database, but use different users/schemas.
6537
+ */
6538
+ function generateDbUrl(appName, password, projectName, host = "localhost", port = 5432) {
6539
+ const userName = appName.replace(/-/g, "_");
6540
+ const dbName = `${projectName.replace(/-/g, "_")}_dev`;
6541
+ return `postgresql://${userName}:${password}@${host}:${port}/${dbName}`;
6542
+ }
6543
+ /**
6544
+ * Generate fullstack-aware custom secrets for a workspace.
6545
+ *
6546
+ * Generates:
6547
+ * - Common secrets: NODE_ENV, PORT, LOG_LEVEL, JWT_SECRET
6548
+ * - Per-app database passwords and URLs for backend apps with db service
6549
+ * - Better-auth secrets for apps using the better-auth framework
6550
+ */
6551
+ function generateFullstackCustomSecrets(workspace) {
6552
+ const hasDb = !!workspace.services.db;
6553
+ const customs = {
6554
+ NODE_ENV: "development",
6555
+ PORT: "3000",
6556
+ LOG_LEVEL: "debug",
6557
+ JWT_SECRET: `dev-${Date.now()}-${Math.random().toString(36).slice(2)}`
6558
+ };
6559
+ if (!hasDb) return customs;
6560
+ const frontendPorts = [];
6561
+ for (const [appName, appConfig] of Object.entries(workspace.apps)) {
6562
+ if (appConfig.type === "frontend") {
6563
+ frontendPorts.push(appConfig.port);
6564
+ continue;
6565
+ }
6566
+ const password = generateDbPassword();
6567
+ const upperName = appName.toUpperCase();
6568
+ customs[`${upperName}_DATABASE_URL`] = generateDbUrl(appName, password, workspace.name);
6569
+ customs[`${upperName}_DB_PASSWORD`] = password;
6570
+ if (appConfig.framework === "better-auth") {
6571
+ customs.AUTH_PORT = String(appConfig.port);
6572
+ customs.AUTH_URL = `http://localhost:${appConfig.port}`;
6573
+ customs.BETTER_AUTH_SECRET = `better-auth-${Date.now()}-${generateSecurePassword(16)}`;
6574
+ customs.BETTER_AUTH_URL = `http://localhost:${appConfig.port}`;
6575
+ }
6576
+ }
6577
+ if (customs.BETTER_AUTH_SECRET) {
6578
+ const allPorts = Object.values(workspace.apps).map((a) => a.port);
6579
+ customs.BETTER_AUTH_TRUSTED_ORIGINS = allPorts.map((p) => `http://localhost:${p}`).join(",");
6580
+ }
6581
+ return customs;
6582
+ }
6583
+ /**
6584
+ * Extract *_DB_PASSWORD keys from secrets and write docker/.env.
6585
+ *
6586
+ * The docker/.env file contains database passwords that the PostgreSQL
6587
+ * init script reads to create per-app database users.
6588
+ */
6589
+ async function writeDockerEnvFromSecrets(secrets, workspaceRoot) {
6590
+ const dbPasswordEntries = Object.entries(secrets.custom).filter(([key]) => key.endsWith("_DB_PASSWORD"));
6591
+ if (dbPasswordEntries.length === 0) return;
6592
+ const envContent = `# Auto-generated docker environment file
6593
+ # Contains database passwords for docker-compose postgres init
6594
+ # This file is gitignored - do not commit to version control
6595
+ ${dbPasswordEntries.map(([key, value]) => `${key}=${value}`).join("\n")}
6596
+ `;
6597
+ const envPath = (0, node_path.join)(workspaceRoot, "docker", ".env");
6598
+ await (0, node_fs_promises.mkdir)((0, node_path.dirname)(envPath), { recursive: true });
6599
+ await (0, node_fs_promises.writeFile)(envPath, envContent);
6600
+ }
6601
+
6523
6602
  //#endregion
6524
6603
  //#region src/init/versions.ts
6525
6604
  const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
@@ -10664,25 +10743,77 @@ function getRunCommand(pkgManager, script) {
10664
10743
  default: return `npm run ${script}`;
10665
10744
  }
10666
10745
  }
10667
-
10668
- //#endregion
10669
- //#region src/init/index.ts
10746
+ const lockfileByPm = {
10747
+ pnpm: "pnpm-lock.yaml",
10748
+ yarn: "yarn.lock",
10749
+ npm: "package-lock.json",
10750
+ bun: "bun.lockb"
10751
+ };
10670
10752
  /**
10671
- * Generate a secure random password for database users
10753
+ * Find the workspace/project root by walking up from cwd.
10754
+ * Checks for PM-specific workspace config, package.json#workspaces,
10755
+ * and lockfiles.
10672
10756
  */
10673
- function generateDbPassword() {
10674
- return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;
10757
+ function findWorkspaceRoot(cwd, pm) {
10758
+ let dir = cwd;
10759
+ const root = (0, node_path.parse)(dir).root;
10760
+ const lockfile = lockfileByPm[pm];
10761
+ while (dir !== root) {
10762
+ if (pm === "pnpm" && (0, node_fs.existsSync)((0, node_path.join)(dir, "pnpm-workspace.yaml"))) return dir;
10763
+ const pkgJsonPath = (0, node_path.join)(dir, "package.json");
10764
+ if ((0, node_fs.existsSync)(pkgJsonPath)) try {
10765
+ const pkg$1 = JSON.parse((0, node_fs.readFileSync)(pkgJsonPath, "utf-8"));
10766
+ if (pkg$1.workspaces) return dir;
10767
+ } catch {}
10768
+ if ((0, node_fs.existsSync)((0, node_path.join)(dir, lockfile))) return dir;
10769
+ dir = (0, node_path.dirname)(dir);
10770
+ }
10771
+ return cwd;
10675
10772
  }
10676
10773
  /**
10677
- * Generate database URL for an app
10678
- * All apps connect to the same database, but use different users/schemas
10774
+ * Get workspace package glob patterns from pnpm-workspace.yaml
10775
+ * or package.json#workspaces.
10679
10776
  */
10680
- function generateDbUrl(appName, password, projectName, host = "localhost", port = 5432) {
10681
- const userName = appName.replace(/-/g, "_");
10682
- const dbName = `${projectName.replace(/-/g, "_")}_dev`;
10683
- return `postgresql://${userName}:${password}@${host}:${port}/${dbName}`;
10777
+ function getWorkspaceGlobs(root) {
10778
+ const pnpmWorkspacePath = (0, node_path.join)(root, "pnpm-workspace.yaml");
10779
+ if ((0, node_fs.existsSync)(pnpmWorkspacePath)) {
10780
+ const content = (0, node_fs.readFileSync)(pnpmWorkspacePath, "utf-8");
10781
+ const parsed = (0, yaml.parse)(content);
10782
+ return parsed?.packages ?? [];
10783
+ }
10784
+ const rootPkgJsonPath = (0, node_path.join)(root, "package.json");
10785
+ if ((0, node_fs.existsSync)(rootPkgJsonPath)) {
10786
+ const pkg$1 = JSON.parse((0, node_fs.readFileSync)(rootPkgJsonPath, "utf-8"));
10787
+ if (Array.isArray(pkg$1.workspaces)) return pkg$1.workspaces;
10788
+ if (pkg$1.workspaces?.packages) return pkg$1.workspaces.packages;
10789
+ }
10790
+ return [];
10684
10791
  }
10685
10792
  /**
10793
+ * Find all package.json files across a workspace.
10794
+ * Returns the root package.json plus all workspace member package.json paths.
10795
+ */
10796
+ function findWorkspacePackages(cwd, pm) {
10797
+ const workspaceRoot = findWorkspaceRoot(cwd, pm);
10798
+ const results = [];
10799
+ const rootPkgJson = (0, node_path.join)(workspaceRoot, "package.json");
10800
+ if ((0, node_fs.existsSync)(rootPkgJson)) results.push(rootPkgJson);
10801
+ const globs = getWorkspaceGlobs(workspaceRoot);
10802
+ for (const glob of globs) {
10803
+ const pattern = `${glob}/package.json`;
10804
+ const matches = fast_glob.default.sync(pattern, {
10805
+ cwd: workspaceRoot,
10806
+ absolute: true,
10807
+ ignore: ["**/node_modules/**"]
10808
+ });
10809
+ results.push(...matches);
10810
+ }
10811
+ return [...new Set(results)];
10812
+ }
10813
+
10814
+ //#endregion
10815
+ //#region src/init/index.ts
10816
+ /**
10686
10817
  * Main init command - scaffolds a new project
10687
10818
  */
10688
10819
  async function initCommand(projectName, options = {}) {
@@ -10984,7 +11115,7 @@ function printNextSteps(projectName, options, pkgManager) {
10984
11115
 
10985
11116
  //#endregion
10986
11117
  //#region src/secrets/index.ts
10987
- const logger = console;
11118
+ const logger$2 = console;
10988
11119
  /**
10989
11120
  * Extract service names from compose config.
10990
11121
  */
@@ -11000,23 +11131,33 @@ function getServicesFromConfig(services) {
11000
11131
  async function secretsInitCommand(options) {
11001
11132
  const { stage, force } = options;
11002
11133
  if (!force && require_storage.secretsExist(stage)) {
11003
- logger.error(`Secrets already exist for stage "${stage}". Use --force to overwrite.`);
11134
+ logger$2.error(`Secrets already exist for stage "${stage}". Use --force to overwrite.`);
11004
11135
  process.exit(1);
11005
11136
  }
11006
11137
  const config = await require_config.loadConfig();
11007
11138
  const services = getServicesFromConfig(config.docker?.compose?.services);
11008
- if (services.length === 0) logger.warn("No services configured in docker.compose.services. Creating secrets with empty services.");
11139
+ if (services.length === 0) logger$2.warn("No services configured in docker.compose.services. Creating secrets with empty services.");
11009
11140
  const secrets = createStageSecrets(stage, services);
11141
+ try {
11142
+ const loaded = await require_config.loadWorkspaceConfig();
11143
+ const isMultiApp = Object.keys(loaded.workspace.apps).length > 1;
11144
+ if (isMultiApp) {
11145
+ const customSecrets = generateFullstackCustomSecrets(loaded.workspace);
11146
+ secrets.custom = customSecrets;
11147
+ logger$2.log(" Detected workspace mode — generating per-app secrets");
11148
+ }
11149
+ } catch {}
11010
11150
  await require_storage.writeStageSecrets(secrets);
11011
- logger.log(`\n✓ Secrets initialized for stage "${stage}"`);
11012
- logger.log(` Location: .gkm/secrets/${stage}.json`);
11013
- logger.log("\n Generated credentials for:");
11014
- for (const service of services) logger.log(` - ${service}`);
11015
- if (secrets.urls.DATABASE_URL) logger.log(`\n DATABASE_URL: ${maskUrl(secrets.urls.DATABASE_URL)}`);
11016
- if (secrets.urls.REDIS_URL) logger.log(` REDIS_URL: ${maskUrl(secrets.urls.REDIS_URL)}`);
11017
- if (secrets.urls.RABBITMQ_URL) logger.log(` RABBITMQ_URL: ${maskUrl(secrets.urls.RABBITMQ_URL)}`);
11018
- logger.log(`\n Use "gkm secrets:show --stage ${stage}" to view secrets`);
11019
- logger.log(" Use \"gkm secrets:set <KEY> <VALUE> --stage " + stage + "\" to add custom secrets");
11151
+ logger$2.log(`\n✓ Secrets initialized for stage "${stage}"`);
11152
+ logger$2.log(` Location: .gkm/secrets/${stage}.json`);
11153
+ logger$2.log("\n Generated credentials for:");
11154
+ for (const service of services) logger$2.log(` - ${service}`);
11155
+ if (secrets.urls.DATABASE_URL) logger$2.log(`\n DATABASE_URL: ${maskUrl(secrets.urls.DATABASE_URL)}`);
11156
+ if (secrets.urls.REDIS_URL) logger$2.log(` REDIS_URL: ${maskUrl(secrets.urls.REDIS_URL)}`);
11157
+ if (secrets.urls.RABBITMQ_URL) logger$2.log(` RABBITMQ_URL: ${maskUrl(secrets.urls.RABBITMQ_URL)}`);
11158
+ if (Object.keys(secrets.custom).length > 0) logger$2.log(`\n Custom secrets: ${Object.keys(secrets.custom).length}`);
11159
+ logger$2.log(`\n Use "gkm secrets:show --stage ${stage}" to view secrets`);
11160
+ logger$2.log(" Use \"gkm secrets:set <KEY> <VALUE> --stage " + stage + "\" to add custom secrets");
11020
11161
  }
11021
11162
  /**
11022
11163
  * Read all data from stdin.
@@ -11035,21 +11176,21 @@ async function secretsSetCommand(key, value, options) {
11035
11176
  let secretValue = value;
11036
11177
  if (!secretValue) {
11037
11178
  if (process.stdin.isTTY) {
11038
- logger.error("No value provided. Use: gkm secrets:set KEY VALUE --stage <stage>");
11039
- logger.error("Or pipe from stdin: echo \"value\" | gkm secrets:set KEY --stage <stage>");
11179
+ logger$2.error("No value provided. Use: gkm secrets:set KEY VALUE --stage <stage>");
11180
+ logger$2.error("Or pipe from stdin: echo \"value\" | gkm secrets:set KEY --stage <stage>");
11040
11181
  process.exit(1);
11041
11182
  }
11042
11183
  secretValue = await readStdin();
11043
11184
  if (!secretValue) {
11044
- logger.error("No value received from stdin");
11185
+ logger$2.error("No value received from stdin");
11045
11186
  process.exit(1);
11046
11187
  }
11047
11188
  }
11048
11189
  try {
11049
11190
  await require_storage.setCustomSecret(stage, key, secretValue);
11050
- logger.log(`\n✓ Secret "${key}" set for stage "${stage}"`);
11191
+ logger$2.log(`\n✓ Secret "${key}" set for stage "${stage}"`);
11051
11192
  } catch (error) {
11052
- logger.error(error instanceof Error ? error.message : "Failed to set secret");
11193
+ logger$2.error(error instanceof Error ? error.message : "Failed to set secret");
11053
11194
  process.exit(1);
11054
11195
  }
11055
11196
  }
@@ -11060,32 +11201,32 @@ async function secretsShowCommand(options) {
11060
11201
  const { stage, reveal } = options;
11061
11202
  const secrets = await require_storage.readStageSecrets(stage);
11062
11203
  if (!secrets) {
11063
- logger.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
11204
+ logger$2.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
11064
11205
  process.exit(1);
11065
11206
  }
11066
- logger.log(`\nSecrets for stage "${stage}":`);
11067
- logger.log(` Created: ${secrets.createdAt}`);
11068
- logger.log(` Updated: ${secrets.updatedAt}`);
11069
- logger.log("\nService Credentials:");
11207
+ logger$2.log(`\nSecrets for stage "${stage}":`);
11208
+ logger$2.log(` Created: ${secrets.createdAt}`);
11209
+ logger$2.log(` Updated: ${secrets.updatedAt}`);
11210
+ logger$2.log("\nService Credentials:");
11070
11211
  for (const [service, creds] of Object.entries(secrets.services)) if (creds) {
11071
- logger.log(`\n ${service}:`);
11072
- logger.log(` host: ${creds.host}`);
11073
- logger.log(` port: ${creds.port}`);
11074
- logger.log(` username: ${creds.username}`);
11075
- logger.log(` password: ${reveal ? creds.password : require_storage.maskPassword(creds.password)}`);
11076
- if (creds.database) logger.log(` database: ${creds.database}`);
11077
- if (creds.vhost) logger.log(` vhost: ${creds.vhost}`);
11078
- }
11079
- logger.log("\nConnection URLs:");
11080
- if (secrets.urls.DATABASE_URL) logger.log(` DATABASE_URL: ${reveal ? secrets.urls.DATABASE_URL : maskUrl(secrets.urls.DATABASE_URL)}`);
11081
- if (secrets.urls.REDIS_URL) logger.log(` REDIS_URL: ${reveal ? secrets.urls.REDIS_URL : maskUrl(secrets.urls.REDIS_URL)}`);
11082
- if (secrets.urls.RABBITMQ_URL) logger.log(` RABBITMQ_URL: ${reveal ? secrets.urls.RABBITMQ_URL : maskUrl(secrets.urls.RABBITMQ_URL)}`);
11212
+ logger$2.log(`\n ${service}:`);
11213
+ logger$2.log(` host: ${creds.host}`);
11214
+ logger$2.log(` port: ${creds.port}`);
11215
+ logger$2.log(` username: ${creds.username}`);
11216
+ logger$2.log(` password: ${reveal ? creds.password : require_storage.maskPassword(creds.password)}`);
11217
+ if (creds.database) logger$2.log(` database: ${creds.database}`);
11218
+ if (creds.vhost) logger$2.log(` vhost: ${creds.vhost}`);
11219
+ }
11220
+ logger$2.log("\nConnection URLs:");
11221
+ if (secrets.urls.DATABASE_URL) logger$2.log(` DATABASE_URL: ${reveal ? secrets.urls.DATABASE_URL : maskUrl(secrets.urls.DATABASE_URL)}`);
11222
+ if (secrets.urls.REDIS_URL) logger$2.log(` REDIS_URL: ${reveal ? secrets.urls.REDIS_URL : maskUrl(secrets.urls.REDIS_URL)}`);
11223
+ if (secrets.urls.RABBITMQ_URL) logger$2.log(` RABBITMQ_URL: ${reveal ? secrets.urls.RABBITMQ_URL : maskUrl(secrets.urls.RABBITMQ_URL)}`);
11083
11224
  const customKeys = Object.keys(secrets.custom);
11084
11225
  if (customKeys.length > 0) {
11085
- logger.log("\nCustom Secrets:");
11086
- for (const [key, value] of Object.entries(secrets.custom)) logger.log(` ${key}: ${reveal ? value : require_storage.maskPassword(value)}`);
11226
+ logger$2.log("\nCustom Secrets:");
11227
+ for (const [key, value] of Object.entries(secrets.custom)) logger$2.log(` ${key}: ${reveal ? value : require_storage.maskPassword(value)}`);
11087
11228
  }
11088
- if (!reveal) logger.log("\nUse --reveal to show actual values");
11229
+ if (!reveal) logger$2.log("\nUse --reveal to show actual values");
11089
11230
  }
11090
11231
  /**
11091
11232
  * Rotate passwords for services.
@@ -11094,25 +11235,25 @@ async function secretsRotateCommand(options) {
11094
11235
  const { stage, service } = options;
11095
11236
  const secrets = await require_storage.readStageSecrets(stage);
11096
11237
  if (!secrets) {
11097
- logger.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
11238
+ logger$2.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
11098
11239
  process.exit(1);
11099
11240
  }
11100
11241
  if (service) {
11101
11242
  if (!secrets.services[service]) {
11102
- logger.error(`Service "${service}" not configured in stage "${stage}"`);
11243
+ logger$2.error(`Service "${service}" not configured in stage "${stage}"`);
11103
11244
  process.exit(1);
11104
11245
  }
11105
11246
  const updated = rotateServicePassword(secrets, service);
11106
11247
  await require_storage.writeStageSecrets(updated);
11107
- logger.log(`\n✓ Password rotated for ${service} in stage "${stage}"`);
11248
+ logger$2.log(`\n✓ Password rotated for ${service} in stage "${stage}"`);
11108
11249
  } else {
11109
11250
  let updated = secrets;
11110
11251
  const services = Object.keys(secrets.services);
11111
11252
  for (const svc of services) updated = rotateServicePassword(updated, svc);
11112
11253
  await require_storage.writeStageSecrets(updated);
11113
- logger.log(`\n✓ Passwords rotated for all services in stage "${stage}": ${services.join(", ")}`);
11254
+ logger$2.log(`\n✓ Passwords rotated for all services in stage "${stage}": ${services.join(", ")}`);
11114
11255
  }
11115
- logger.log(`\nUse "gkm secrets:show --stage ${stage}" to view new values`);
11256
+ logger$2.log(`\nUse "gkm secrets:show --stage ${stage}" to view new values`);
11116
11257
  }
11117
11258
  /**
11118
11259
  * Import secrets from a JSON file.
@@ -11120,7 +11261,7 @@ async function secretsRotateCommand(options) {
11120
11261
  async function secretsImportCommand(file, options) {
11121
11262
  const { stage, merge = true } = options;
11122
11263
  if (!(0, node_fs.existsSync)(file)) {
11123
- logger.error(`File not found: ${file}`);
11264
+ logger$2.error(`File not found: ${file}`);
11124
11265
  process.exit(1);
11125
11266
  }
11126
11267
  let importedSecrets;
@@ -11130,12 +11271,12 @@ async function secretsImportCommand(file, options) {
11130
11271
  if (typeof importedSecrets !== "object" || importedSecrets === null) throw new Error("JSON must be an object");
11131
11272
  for (const [key, value] of Object.entries(importedSecrets)) if (typeof value !== "string") throw new Error(`Value for "${key}" must be a string, got ${typeof value}`);
11132
11273
  } catch (error) {
11133
- logger.error(`Failed to parse JSON file: ${error instanceof Error ? error.message : "Invalid JSON"}`);
11274
+ logger$2.error(`Failed to parse JSON file: ${error instanceof Error ? error.message : "Invalid JSON"}`);
11134
11275
  process.exit(1);
11135
11276
  }
11136
11277
  const secrets = await require_storage.readStageSecrets(stage);
11137
11278
  if (!secrets) {
11138
- logger.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
11279
+ logger$2.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
11139
11280
  process.exit(1);
11140
11281
  }
11141
11282
  const updatedCustom = merge ? {
@@ -11150,10 +11291,10 @@ async function secretsImportCommand(file, options) {
11150
11291
  await require_storage.writeStageSecrets(updated);
11151
11292
  const importedCount = Object.keys(importedSecrets).length;
11152
11293
  const totalCount = Object.keys(updatedCustom).length;
11153
- logger.log(`\n✓ Imported ${importedCount} secrets for stage "${stage}"`);
11154
- if (merge && totalCount > importedCount) logger.log(` Total custom secrets: ${totalCount}`);
11155
- logger.log("\n Imported keys:");
11156
- for (const key of Object.keys(importedSecrets)) logger.log(` - ${key}`);
11294
+ logger$2.log(`\n✓ Imported ${importedCount} secrets for stage "${stage}"`);
11295
+ if (merge && totalCount > importedCount) logger$2.log(` Total custom secrets: ${totalCount}`);
11296
+ logger$2.log("\n Imported keys:");
11297
+ for (const key of Object.keys(importedSecrets)) logger$2.log(` - ${key}`);
11157
11298
  }
11158
11299
  /**
11159
11300
  * Mask password in a URL for display.
@@ -11168,6 +11309,139 @@ function maskUrl(url) {
11168
11309
  }
11169
11310
  }
11170
11311
 
11312
+ //#endregion
11313
+ //#region src/setup/index.ts
11314
+ const logger$1 = console;
11315
+ /**
11316
+ * Setup development environment.
11317
+ *
11318
+ * Orchestrates:
11319
+ * 1. Load workspace config
11320
+ * 2. Resolve secrets (local → SSM → generate fresh)
11321
+ * 3. Write docker/.env from secrets
11322
+ * 4. Start Docker services
11323
+ */
11324
+ async function setupCommand(options = {}) {
11325
+ const stage = options.stage ?? "development";
11326
+ logger$1.log("\n🔧 Setting up development environment...\n");
11327
+ let loadedConfig;
11328
+ try {
11329
+ loadedConfig = await require_config.loadWorkspaceConfig();
11330
+ } catch {
11331
+ logger$1.error("❌ No gkm.config.ts found. Run this command from a workspace root.");
11332
+ process.exit(1);
11333
+ }
11334
+ const { workspace } = loadedConfig;
11335
+ const isMultiApp = Object.keys(workspace.apps).length > 1;
11336
+ logger$1.log(`📦 Workspace: ${workspace.name}`);
11337
+ logger$1.log(`📱 Apps: ${Object.keys(workspace.apps).join(", ")}`);
11338
+ logger$1.log(`🔑 Stage: ${stage}\n`);
11339
+ const secrets = await resolveSecrets(stage, workspace, options);
11340
+ if (!secrets) {
11341
+ logger$1.error("❌ Failed to resolve secrets. Exiting.");
11342
+ process.exit(1);
11343
+ }
11344
+ if (isMultiApp && workspace.services.db) {
11345
+ await writeDockerEnvFromSecrets(secrets, workspace.root);
11346
+ logger$1.log("📄 Generated docker/.env with database passwords");
11347
+ }
11348
+ if (!options.skipDocker) {
11349
+ const composeFile = (0, node_path.join)(workspace.root, "docker-compose.yml");
11350
+ if ((0, node_fs.existsSync)(composeFile)) {
11351
+ logger$1.log("");
11352
+ await startWorkspaceServices(workspace);
11353
+ } else logger$1.log("⚠️ No docker-compose.yml found. Skipping Docker services.");
11354
+ }
11355
+ printSummary(workspace, stage);
11356
+ }
11357
+ /**
11358
+ * Resolve secrets with priority:
11359
+ * 1. Local secrets exist → use them (preserves manual additions)
11360
+ * 2. SSM configured and has secrets → pull and use
11361
+ * 3. Neither → generate fresh secrets
11362
+ *
11363
+ * --force skips checks 1 and 2 and always regenerates.
11364
+ */
11365
+ async function resolveSecrets(stage, workspace, options) {
11366
+ if (options.force) {
11367
+ logger$1.log("🔐 Generating fresh secrets (--force)...");
11368
+ return generateFreshSecrets(stage, workspace, options);
11369
+ }
11370
+ if (require_storage.secretsExist(stage, workspace.root)) {
11371
+ logger$1.log("🔐 Using existing local secrets");
11372
+ const secrets = await require_storage.readStageSecrets(stage, workspace.root);
11373
+ if (secrets) return secrets;
11374
+ }
11375
+ if (require_sync.isSSMConfigured(workspace)) {
11376
+ logger$1.log("☁️ Checking for remote secrets in SSM...");
11377
+ try {
11378
+ const remoteSecrets = await require_sync.pullSecrets(stage, workspace);
11379
+ if (remoteSecrets) {
11380
+ logger$1.log("✅ Pulled secrets from SSM");
11381
+ await require_storage.writeStageSecrets(remoteSecrets, workspace.root);
11382
+ return remoteSecrets;
11383
+ }
11384
+ logger$1.log(" No remote secrets found");
11385
+ } catch (error) {
11386
+ logger$1.warn(`⚠️ Failed to pull from SSM: ${error.message}`);
11387
+ }
11388
+ }
11389
+ logger$1.log("🔐 Generating fresh development secrets...");
11390
+ return generateFreshSecrets(stage, workspace, options);
11391
+ }
11392
+ /**
11393
+ * Generate fresh secrets for the workspace.
11394
+ */
11395
+ async function generateFreshSecrets(stage, workspace, options) {
11396
+ const serviceNames = [];
11397
+ if (workspace.services.db) serviceNames.push("postgres");
11398
+ if (workspace.services.cache) serviceNames.push("redis");
11399
+ const secrets = createStageSecrets(stage, serviceNames);
11400
+ const isMultiApp = Object.keys(workspace.apps).length > 1;
11401
+ if (isMultiApp) {
11402
+ const customSecrets = generateFullstackCustomSecrets(workspace);
11403
+ secrets.custom = customSecrets;
11404
+ } else secrets.custom = {
11405
+ NODE_ENV: "development",
11406
+ PORT: "3000",
11407
+ LOG_LEVEL: "debug",
11408
+ JWT_SECRET: `dev-${Date.now()}-${Math.random().toString(36).slice(2)}`
11409
+ };
11410
+ await require_storage.writeStageSecrets(secrets, workspace.root);
11411
+ logger$1.log(` Secrets written to .gkm/secrets/${stage}.json`);
11412
+ if (require_sync.isSSMConfigured(workspace) && !options.yes) {
11413
+ const { shouldPush } = await (0, prompts.default)({
11414
+ type: "confirm",
11415
+ name: "shouldPush",
11416
+ message: "Push secrets to SSM for team sharing?",
11417
+ initial: true
11418
+ });
11419
+ if (shouldPush) try {
11420
+ await require_sync.pushSecrets(stage, workspace);
11421
+ logger$1.log("☁️ Secrets pushed to SSM");
11422
+ } catch (error) {
11423
+ logger$1.warn(`⚠️ Failed to push to SSM: ${error.message}`);
11424
+ }
11425
+ }
11426
+ return secrets;
11427
+ }
11428
+ /**
11429
+ * Print setup summary with next steps.
11430
+ */
11431
+ function printSummary(workspace, stage) {
11432
+ logger$1.log(`\n${"─".repeat(50)}`);
11433
+ logger$1.log("\n✅ Development environment ready!\n");
11434
+ logger$1.log("📋 Apps:");
11435
+ for (const [name$1, app] of Object.entries(workspace.apps)) {
11436
+ const icon = app.type === "frontend" ? "🌐" : "🔧";
11437
+ logger$1.log(` ${icon} ${name$1} → http://localhost:${app.port}`);
11438
+ }
11439
+ logger$1.log("\n🚀 Next steps:");
11440
+ logger$1.log(" gkm dev # Start all apps");
11441
+ logger$1.log(` gkm secrets:show --stage ${stage} # View secrets`);
11442
+ logger$1.log("");
11443
+ }
11444
+
11171
11445
  //#endregion
11172
11446
  //#region src/test/index.ts
11173
11447
  /**
@@ -11304,6 +11578,146 @@ async function ensureTestDatabase(env) {
11304
11578
  }
11305
11579
  }
11306
11580
 
11581
+ //#endregion
11582
+ //#region src/upgrade/index.ts
11583
+ const logger = console;
11584
+ async function upgradeCommand(options = {}) {
11585
+ const cwd = process.cwd();
11586
+ logger.log("\n📦 Scanning workspace for @geekmidas packages...\n");
11587
+ const pm = detectPackageManager(cwd);
11588
+ logger.log(` Package manager: ${pm}`);
11589
+ const packageJsonPaths = findWorkspacePackages(cwd, pm);
11590
+ logger.log(` Found ${packageJsonPaths.length} package(s) in workspace\n`);
11591
+ const dependencies$1 = scanForGeekmidasDeps(packageJsonPaths);
11592
+ if (dependencies$1.length === 0) {
11593
+ logger.log(" No @geekmidas packages found.\n");
11594
+ return;
11595
+ }
11596
+ const uniquePackages = [...new Set(dependencies$1.map((d) => d.packageName))];
11597
+ logger.log(` Checking ${uniquePackages.length} unique @geekmidas package(s) on npm...\n`);
11598
+ const latestVersions = await fetchLatestVersions(uniquePackages);
11599
+ const upgradeInfos = dependencies$1.map((dep) => resolveUpgradeInfo(dep, latestVersions));
11600
+ printUpgradeTable(upgradeInfos);
11601
+ const upgradable = upgradeInfos.filter((info) => info.needsUpgrade && !info.isWorkspaceRef);
11602
+ if (upgradable.length === 0) {
11603
+ logger.log("\n All @geekmidas packages are up to date!\n");
11604
+ return;
11605
+ }
11606
+ logger.log(`\n ${upgradable.length} package(s) can be upgraded.\n`);
11607
+ if (options.dryRun) {
11608
+ logger.log(" --dry-run: No changes made.\n");
11609
+ printUpgradeCommands(upgradable, pm);
11610
+ return;
11611
+ }
11612
+ executeUpgrade(upgradable, pm, cwd);
11613
+ logger.log("\n ✅ Upgrade complete! Run your tests to verify.\n");
11614
+ }
11615
+ function scanForGeekmidasDeps(packageJsonPaths) {
11616
+ const results = [];
11617
+ const depTypes = [
11618
+ "dependencies",
11619
+ "devDependencies",
11620
+ "peerDependencies"
11621
+ ];
11622
+ for (const pkgJsonPath of packageJsonPaths) {
11623
+ const pkg$1 = JSON.parse((0, node_fs.readFileSync)(pkgJsonPath, "utf-8"));
11624
+ const workspaceName = pkg$1.name ?? pkgJsonPath;
11625
+ for (const depType of depTypes) {
11626
+ const deps = pkg$1[depType];
11627
+ if (!deps) continue;
11628
+ for (const [name$1, version$1] of Object.entries(deps)) {
11629
+ if (!name$1.startsWith("@geekmidas/")) continue;
11630
+ results.push({
11631
+ packageName: name$1,
11632
+ currentVersion: version$1,
11633
+ depType,
11634
+ packageJsonPath: pkgJsonPath,
11635
+ workspaceName
11636
+ });
11637
+ }
11638
+ }
11639
+ }
11640
+ return results;
11641
+ }
11642
+ async function fetchLatestVersions(packageNames) {
11643
+ const versions = /* @__PURE__ */ new Map();
11644
+ const results = await Promise.allSettled(packageNames.map(async (name$1) => {
11645
+ const res = await fetch(`https://registry.npmjs.org/${name$1}/latest`);
11646
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
11647
+ const data = await res.json();
11648
+ return {
11649
+ name: name$1,
11650
+ version: data.version
11651
+ };
11652
+ }));
11653
+ for (const result of results) if (result.status === "fulfilled") versions.set(result.value.name, result.value.version);
11654
+ return versions;
11655
+ }
11656
+ function resolveUpgradeInfo(dep, latestVersions) {
11657
+ const isWorkspaceRef = dep.currentVersion.startsWith("workspace:");
11658
+ const latestVersion = latestVersions.get(dep.packageName) ?? "unknown";
11659
+ const currentBare = dep.currentVersion.replace(/^[\^~>=<]*/g, "");
11660
+ const needsUpgrade = !isWorkspaceRef && latestVersion !== "unknown" && currentBare !== latestVersion;
11661
+ return {
11662
+ ...dep,
11663
+ latestVersion,
11664
+ isWorkspaceRef,
11665
+ needsUpgrade
11666
+ };
11667
+ }
11668
+ function printUpgradeTable(infos) {
11669
+ const byPackage = /* @__PURE__ */ new Map();
11670
+ for (const info of infos) if (!byPackage.has(info.packageName)) byPackage.set(info.packageName, info);
11671
+ const nameWidth = 33;
11672
+ const verWidth = 14;
11673
+ const statusWidth = 14;
11674
+ const hr = ` ${"─".repeat(nameWidth + verWidth * 2 + statusWidth + 5)}`;
11675
+ logger.log(hr);
11676
+ logger.log(` ${"Package".padEnd(nameWidth)} ${"Current".padEnd(verWidth)} ${"Latest".padEnd(verWidth)} ${"Status".padEnd(statusWidth)}`);
11677
+ logger.log(hr);
11678
+ for (const [, info] of byPackage) {
11679
+ const name$1 = info.packageName.padEnd(nameWidth);
11680
+ const current = info.currentVersion.padEnd(verWidth);
11681
+ const latest = info.latestVersion.padEnd(verWidth);
11682
+ let status;
11683
+ if (info.isWorkspaceRef) status = "workspace";
11684
+ else if (info.needsUpgrade) status = "⬆ upgrade";
11685
+ else status = "✓ up-to-date";
11686
+ logger.log(` ${name$1} ${current} ${latest} ${status}`);
11687
+ }
11688
+ logger.log(hr);
11689
+ }
11690
+ function printUpgradeCommands(upgradable, pm) {
11691
+ logger.log(" Commands that would be run:\n");
11692
+ const uniquePackages = [...new Set(upgradable.map((i) => i.packageName))];
11693
+ const cmd = getWorkspaceUpgradeCommand(pm, uniquePackages);
11694
+ logger.log(` ${cmd}\n`);
11695
+ }
11696
+ function getWorkspaceUpgradeCommand(pm, packages) {
11697
+ const pkgList = packages.join(" ");
11698
+ switch (pm) {
11699
+ case "pnpm": return `pnpm update -r ${pkgList} --latest`;
11700
+ case "yarn": return `yarn upgrade ${pkgList}`;
11701
+ case "bun": return `bun update ${pkgList}`;
11702
+ case "npm": return `npm update ${pkgList} --workspaces`;
11703
+ default: return `npm update ${pkgList}`;
11704
+ }
11705
+ }
11706
+ function executeUpgrade(upgradable, pm, cwd) {
11707
+ const uniquePackages = [...new Set(upgradable.map((i) => i.packageName))];
11708
+ const cmd = getWorkspaceUpgradeCommand(pm, uniquePackages);
11709
+ logger.log(` Running: ${cmd}\n`);
11710
+ try {
11711
+ (0, node_child_process.execSync)(cmd, {
11712
+ cwd,
11713
+ stdio: "inherit",
11714
+ timeout: 12e4
11715
+ });
11716
+ } catch {
11717
+ throw new Error("Package upgrade failed. Check the output above for details.");
11718
+ }
11719
+ }
11720
+
11307
11721
  //#endregion
11308
11722
  //#region src/index.ts
11309
11723
  const program = new commander.Command();
@@ -11318,6 +11732,16 @@ program.command("init").description("Scaffold a new project").argument("[name]",
11318
11732
  process.exit(1);
11319
11733
  }
11320
11734
  });
11735
+ program.command("setup").description("Setup development environment (secrets, Docker, database)").option("--stage <stage>", "Stage name", "development").option("--force", "Regenerate secrets even if they exist").option("--skip-docker", "Skip starting Docker services").option("-y, --yes", "Skip prompts").action(async (options) => {
11736
+ try {
11737
+ const globalOptions = program.opts();
11738
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11739
+ await setupCommand(options);
11740
+ } catch (error) {
11741
+ console.error(error instanceof Error ? error.message : "Command failed");
11742
+ process.exit(1);
11743
+ }
11744
+ });
11321
11745
  program.command("build").description("Build handlers from endpoints, functions, and crons").option("--provider <provider>", "Target provider for generated handlers (aws, server)").option("--providers <providers>", "[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)").option("--enable-openapi", "Enable OpenAPI documentation generation for server builds").option("--production", "Build for production (no dev tools, bundled output)").option("--skip-bundle", "Skip bundling step in production build").option("--stage <stage>", "Inject encrypted secrets for deployment stage").action(async (options) => {
11322
11746
  try {
11323
11747
  const globalOptions = program.opts();
@@ -11514,6 +11938,40 @@ program.command("secrets:import").description("Import secrets from a JSON file")
11514
11938
  process.exit(1);
11515
11939
  }
11516
11940
  });
11941
+ program.command("secrets:push").description("Push secrets to remote provider (SSM)").requiredOption("--stage <stage>", "Stage name").action(async (options) => {
11942
+ try {
11943
+ const globalOptions = program.opts();
11944
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11945
+ const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await Promise.resolve().then(() => require("./config.cjs"));
11946
+ const { pushSecrets: pushSecrets$1 } = await Promise.resolve().then(() => require("./sync-BxFB34zW.cjs"));
11947
+ const { workspace } = await loadWorkspaceConfig$1();
11948
+ await pushSecrets$1(options.stage, workspace);
11949
+ console.log(`\n✓ Secrets pushed for stage "${options.stage}"`);
11950
+ } catch (error) {
11951
+ console.error(error instanceof Error ? error.message : "Command failed");
11952
+ process.exit(1);
11953
+ }
11954
+ });
11955
+ program.command("secrets:pull").description("Pull secrets from remote provider (SSM)").requiredOption("--stage <stage>", "Stage name").action(async (options) => {
11956
+ try {
11957
+ const globalOptions = program.opts();
11958
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11959
+ const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await Promise.resolve().then(() => require("./config.cjs"));
11960
+ const { pullSecrets: pullSecrets$1 } = await Promise.resolve().then(() => require("./sync-BxFB34zW.cjs"));
11961
+ const { writeStageSecrets: writeStageSecrets$1 } = await Promise.resolve().then(() => require("./storage-C7pmBq1u.cjs"));
11962
+ const { workspace } = await loadWorkspaceConfig$1();
11963
+ const secrets = await pullSecrets$1(options.stage, workspace);
11964
+ if (!secrets) {
11965
+ console.error(`No remote secrets found for stage "${options.stage}".`);
11966
+ process.exit(1);
11967
+ }
11968
+ await writeStageSecrets$1(secrets, workspace.root);
11969
+ console.log(`\n✓ Secrets pulled for stage "${options.stage}"`);
11970
+ } catch (error) {
11971
+ console.error(error instanceof Error ? error.message : "Command failed");
11972
+ process.exit(1);
11973
+ }
11974
+ });
11517
11975
  program.command("deploy").description("Deploy application to a provider").requiredOption("--provider <provider>", "Deploy provider (docker, dokploy, aws-lambda)").requiredOption("--stage <stage>", "Deployment stage (e.g., production, staging)").option("--tag <tag>", "Image tag (default: stage-timestamp)").option("--skip-push", "Skip pushing image to registry").option("--skip-build", "Skip build step (use existing build)").action(async (options) => {
11518
11976
  try {
11519
11977
  const globalOptions = program.opts();
@@ -11660,6 +12118,16 @@ program.command("state:diff").description("Compare local and remote deployment s
11660
12118
  process.exit(1);
11661
12119
  }
11662
12120
  });
12121
+ program.command("upgrade").description("Upgrade all @geekmidas packages to their latest versions").option("--dry-run", "Show what would be upgraded without making changes").action(async (options) => {
12122
+ try {
12123
+ const globalOptions = program.opts();
12124
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
12125
+ await upgradeCommand(options);
12126
+ } catch (error) {
12127
+ console.error(error instanceof Error ? error.message : "Command failed");
12128
+ process.exit(1);
12129
+ }
12130
+ });
11663
12131
  program.parse();
11664
12132
 
11665
12133
  //#endregion