@geekmidas/cli 1.10.41 → 1.11.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 (94) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +14 -0
  3. package/dist/{CachedStateProvider-37pG1HBx.cjs → CachedStateProvider-BdX7klRc.cjs} +1 -1
  4. package/dist/{CachedStateProvider-C8A-cCm5.mjs → CachedStateProvider-CzyFct42.mjs} +1 -1
  5. package/dist/{CachedStateProvider-C8A-cCm5.mjs.map → CachedStateProvider-CzyFct42.mjs.map} +1 -1
  6. package/dist/CachedStateProvider-GcGziXh1.mjs +3 -0
  7. package/dist/{CachedStateProvider-CxsXOKkg.cjs → CachedStateProvider-klLWZXWF.cjs} +1 -1
  8. package/dist/{CachedStateProvider-CxsXOKkg.cjs.map → CachedStateProvider-klLWZXWF.cjs.map} +1 -1
  9. package/dist/{HostingerProvider-ANWchdiK.mjs → HostingerProvider-B2ZYz7Yc.mjs} +1 -1
  10. package/dist/{HostingerProvider-ANWchdiK.mjs.map → HostingerProvider-B2ZYz7Yc.mjs.map} +1 -1
  11. package/dist/{HostingerProvider-5KYmwoK2.cjs → HostingerProvider-CrHfsgz9.cjs} +1 -1
  12. package/dist/{HostingerProvider-5KYmwoK2.cjs.map → HostingerProvider-CrHfsgz9.cjs.map} +1 -1
  13. package/dist/{LocalStateProvider-Dp0KkRcw.mjs → LocalStateProvider-CP49rjzt.mjs} +1 -1
  14. package/dist/{LocalStateProvider-Dp0KkRcw.mjs.map → LocalStateProvider-CP49rjzt.mjs.map} +1 -1
  15. package/dist/{LocalStateProvider-CLifRC0Y.cjs → LocalStateProvider-CalzNfNA.cjs} +1 -1
  16. package/dist/{LocalStateProvider-CLifRC0Y.cjs.map → LocalStateProvider-CalzNfNA.cjs.map} +1 -1
  17. package/dist/{Route53Provider-owQQ4pn6.cjs → Route53Provider-DwgXiLxt.cjs} +1 -1
  18. package/dist/{Route53Provider-owQQ4pn6.cjs.map → Route53Provider-DwgXiLxt.cjs.map} +1 -1
  19. package/dist/{Route53Provider-QoPgcXxn.mjs → Route53Provider-tlgBzrRQ.mjs} +1 -1
  20. package/dist/{Route53Provider-QoPgcXxn.mjs.map → Route53Provider-tlgBzrRQ.mjs.map} +1 -1
  21. package/dist/{SSMStateProvider-CksOTB8M.mjs → SSMStateProvider-BlrTiV5m.mjs} +1 -1
  22. package/dist/{SSMStateProvider-CksOTB8M.mjs.map → SSMStateProvider-BlrTiV5m.mjs.map} +1 -1
  23. package/dist/{SSMStateProvider-CT8tjl9o.cjs → SSMStateProvider-Bt6r8CTL.cjs} +1 -1
  24. package/dist/{SSMStateProvider-CT8tjl9o.cjs.map → SSMStateProvider-Bt6r8CTL.cjs.map} +1 -1
  25. package/dist/{backup-provisioner-C4noe75O.cjs → backup-provisioner-B3HBN-2k.cjs} +1 -1
  26. package/dist/{backup-provisioner-C4noe75O.cjs.map → backup-provisioner-B3HBN-2k.cjs.map} +1 -1
  27. package/dist/{backup-provisioner-BEXoHTuC.mjs → backup-provisioner-Xunq-p_8.mjs} +1 -1
  28. package/dist/{backup-provisioner-BEXoHTuC.mjs.map → backup-provisioner-Xunq-p_8.mjs.map} +1 -1
  29. package/dist/{bundler-c6QvGUBM.mjs → bundler-DkA4qzUD.mjs} +2 -2
  30. package/dist/{bundler-c6QvGUBM.mjs.map → bundler-DkA4qzUD.mjs.map} +1 -1
  31. package/dist/{bundler-BG6P249p.cjs → bundler-Dufq3uvI.cjs} +2 -2
  32. package/dist/{bundler-BG6P249p.cjs.map → bundler-Dufq3uvI.cjs.map} +1 -1
  33. package/dist/config.d.mts +2 -2
  34. package/dist/dokploy-api-BPYkG-ZZ.cjs +3 -0
  35. package/dist/dokploy-api-BiSzWM4v.mjs +3 -0
  36. package/dist/{dokploy-api-Dvyq-LsM.cjs → dokploy-api-CqOIKHme.cjs} +1 -1
  37. package/dist/{dokploy-api-Dvyq-LsM.cjs.map → dokploy-api-CqOIKHme.cjs.map} +1 -1
  38. package/dist/{dokploy-api-BIT0683o.mjs → dokploy-api-sfZFlWuE.mjs} +1 -1
  39. package/dist/{dokploy-api-BIT0683o.mjs.map → dokploy-api-sfZFlWuE.mjs.map} +1 -1
  40. package/dist/{encryption-CipsS0KW.cjs → encryption-BVS7Vmzs.cjs} +1 -1
  41. package/dist/encryption-Bd_m4q3g.mjs +3 -0
  42. package/dist/{encryption-DSkIlEZ6.mjs → encryption-CO5Q4Bhf.mjs} +1 -1
  43. package/dist/{encryption-DSkIlEZ6.mjs.map → encryption-CO5Q4Bhf.mjs.map} +1 -1
  44. package/dist/{encryption-DgKS-Dv9.cjs → encryption-MfXAiFTm.cjs} +1 -1
  45. package/dist/{encryption-DgKS-Dv9.cjs.map → encryption-MfXAiFTm.cjs.map} +1 -1
  46. package/dist/{index-BBvGMG_A.d.mts → index-Dx9Kk5bR.d.mts} +2 -2
  47. package/dist/{index-BBvGMG_A.d.mts.map → index-Dx9Kk5bR.d.mts.map} +1 -1
  48. package/dist/index.cjs +596 -1314
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.mjs +725 -1443
  51. package/dist/index.mjs.map +1 -1
  52. package/dist/{openapi-DHp49UJV.cjs → openapi-CG1LBk7s.cjs} +1 -1
  53. package/dist/{openapi-DHp49UJV.cjs.map → openapi-CG1LBk7s.cjs.map} +1 -1
  54. package/dist/{openapi-DF9GyhyZ.mjs → openapi-CtRVU6RD.mjs} +1 -1
  55. package/dist/{openapi-DF9GyhyZ.mjs.map → openapi-CtRVU6RD.mjs.map} +1 -1
  56. package/dist/{openapi-react-query-C4UdILaI.mjs → openapi-react-query-C4iIvpPf.mjs} +1 -1
  57. package/dist/{openapi-react-query-C4UdILaI.mjs.map → openapi-react-query-C4iIvpPf.mjs.map} +1 -1
  58. package/dist/{openapi-react-query-DYbBq-WJ.cjs → openapi-react-query-CYWik72n.cjs} +1 -1
  59. package/dist/{openapi-react-query-DYbBq-WJ.cjs.map → openapi-react-query-CYWik72n.cjs.map} +1 -1
  60. package/dist/openapi-react-query.cjs +1 -1
  61. package/dist/openapi-react-query.mjs +1 -1
  62. package/dist/openapi.cjs +1 -1
  63. package/dist/openapi.d.mts +1 -1
  64. package/dist/openapi.mjs +1 -1
  65. package/dist/{reconcile-CYGmqXvq.mjs → reconcile-B2FoJE0a.mjs} +1 -1
  66. package/dist/{reconcile-CYGmqXvq.mjs.map → reconcile-B2FoJE0a.mjs.map} +1 -1
  67. package/dist/{reconcile-D93YG7G5.cjs → reconcile-BzqKJ2Rt.cjs} +1 -1
  68. package/dist/{reconcile-D93YG7G5.cjs.map → reconcile-BzqKJ2Rt.cjs.map} +1 -1
  69. package/dist/setup-DDXUXzzl.mjs +765 -0
  70. package/dist/setup-DDXUXzzl.mjs.map +1 -0
  71. package/dist/setup-DLwhfyt-.cjs +8 -0
  72. package/dist/setup-Dh-B7YTX.mjs +8 -0
  73. package/dist/setup-WZ-xqAQO.cjs +849 -0
  74. package/dist/setup-WZ-xqAQO.cjs.map +1 -0
  75. package/dist/{sync-COnAugP-.mjs → sync-B5UHXwRM.mjs} +1 -1
  76. package/dist/sync-BLA94rgC.cjs +4 -0
  77. package/dist/{sync-D_NowTkZ.mjs → sync-CSooqRQ8.mjs} +1 -1
  78. package/dist/{sync-D_NowTkZ.mjs.map → sync-CSooqRQ8.mjs.map} +1 -1
  79. package/dist/{sync-DGXXSk2v.cjs → sync-o_CtEbvR.cjs} +1 -1
  80. package/dist/{sync-DGXXSk2v.cjs.map → sync-o_CtEbvR.cjs.map} +1 -1
  81. package/dist/{types-OszPdw9m.d.mts → types-CqfhdmRi.d.mts} +1 -1
  82. package/dist/{types-OszPdw9m.d.mts.map → types-CqfhdmRi.d.mts.map} +1 -1
  83. package/dist/workspace/index.d.mts +2 -2
  84. package/package.json +4 -4
  85. package/src/index.ts +4 -0
  86. package/src/init/versions.ts +5 -5
  87. package/src/setup/__tests__/auto-setup.spec.ts +147 -0
  88. package/src/setup/index.ts +46 -6
  89. package/src/test/index.ts +17 -0
  90. package/dist/CachedStateProvider-CC0DyO09.mjs +0 -3
  91. package/dist/dokploy-api-BOx71j6F.cjs +0 -3
  92. package/dist/dokploy-api-BZGk-lkD.mjs +0 -3
  93. package/dist/encryption-Db2zvGqM.mjs +0 -3
  94. package/dist/sync-D1Pa30oV.cjs +0 -4
package/dist/index.mjs CHANGED
@@ -1,16 +1,17 @@
1
1
  #!/usr/bin/env -S npx tsx
2
2
  import { __require } from "./chunk-Duj1WY3L.mjs";
3
3
  import { getAppBuildOrder, getDependencyEnvVars, getDeployTargetError, getPublicEnvPrefix, isDeployTargetSupported, stripPublicPrefix } from "./workspace-D-37Ylqo.mjs";
4
- import { getAppNameFromCwd, loadAppConfig, loadConfig, loadWorkspaceAppInfo, loadWorkspaceConfig, parseModuleConfig } from "./config-Bbu1JKvf.mjs";
4
+ import { getAppNameFromCwd, loadAppConfig, loadConfig, loadWorkspaceConfig, parseModuleConfig } from "./config-Bbu1JKvf.mjs";
5
5
  import { getCredentialsPath, getDokployCredentials, getDokployRegistryId, getDokployToken, removeDokployCredentials, storeDokployCredentials, storeDokployRegistryId } from "./credentials-s1kLcIzK.mjs";
6
- import { createStageSecrets, generateConnectionUrls, generateDbPassword, generateDbUrl, generateFullstackCustomSecrets, generateLocalStackCredentials, generatePgBossUrl, generateSecurePassword, generateServiceCredentials, rotateServicePassword, writeDockerEnvFromSecrets } from "./fullstack-secrets-l8s3II_H.mjs";
6
+ import { createStageSecrets, generateDbPassword, generateDbUrl, generateFullstackCustomSecrets, rotateServicePassword } from "./fullstack-secrets-l8s3II_H.mjs";
7
7
  import { getKeyPath, maskPassword, readStageSecrets, secretsExist, setCustomSecret, toEmbeddableSecrets, writeStageSecrets } from "./storage-dbb9RyBl.mjs";
8
- import { ConstructGenerator, EndpointGenerator, OPENAPI_OUTPUT_PATH, generateOpenApi, isPartitionedRoutes, normalizeRoutes, openapiCommand, resolveOpenApiConfig } from "./openapi-DF9GyhyZ.mjs";
9
- import { DokployApi } from "./dokploy-api-BIT0683o.mjs";
10
- import { encryptSecrets } from "./encryption-DSkIlEZ6.mjs";
11
- import { CachedStateProvider } from "./CachedStateProvider-C8A-cCm5.mjs";
12
- import { generateReactQueryCommand } from "./openapi-react-query-C4UdILaI.mjs";
13
- import { isSSMConfigured, pullSecrets, pushSecrets } from "./sync-D_NowTkZ.mjs";
8
+ import { createCredentialsPreload, createEntryWrapper, findAvailablePort, isPortAvailable, loadEnvFiles, loadSecretsForApp, prepareEntryCredentials, resolveServicePorts, rewriteUrlsWithPorts, setupCommand, startWorkspaceServices } from "./setup-DDXUXzzl.mjs";
9
+ import { ConstructGenerator, EndpointGenerator, OPENAPI_OUTPUT_PATH, generateOpenApi, isPartitionedRoutes, normalizeRoutes, openapiCommand, resolveOpenApiConfig } from "./openapi-CtRVU6RD.mjs";
10
+ import { DokployApi } from "./dokploy-api-sfZFlWuE.mjs";
11
+ import { encryptSecrets } from "./encryption-CO5Q4Bhf.mjs";
12
+ import { CachedStateProvider } from "./CachedStateProvider-CzyFct42.mjs";
13
+ import { generateReactQueryCommand } from "./openapi-react-query-C4iIvpPf.mjs";
14
+ import "./sync-CSooqRQ8.mjs";
14
15
  import { createRequire } from "node:module";
15
16
  import { copyFileSync, existsSync, readFileSync, unlinkSync } from "node:fs";
16
17
  import { basename, dirname, join, parse, relative, resolve } from "node:path";
@@ -21,8 +22,6 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
21
22
  import { execSync, spawn } from "node:child_process";
22
23
  import chokidar from "chokidar";
23
24
  import fg from "fast-glob";
24
- import { createServer } from "node:net";
25
- import { config } from "dotenv";
26
25
  import { parse as parse$1 } from "yaml";
27
26
  import { randomBytes } from "node:crypto";
28
27
  import { Cron } from "@geekmidas/constructs/crons";
@@ -35,7 +34,7 @@ import prompts from "prompts";
35
34
 
36
35
  //#region package.json
37
36
  var name = "@geekmidas/cli";
38
- var version = "1.10.40";
37
+ var version = "1.10.41";
39
38
  var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
40
39
  var private$1 = false;
41
40
  var type = "module";
@@ -158,12 +157,12 @@ var package_default = {
158
157
 
159
158
  //#endregion
160
159
  //#region src/auth/index.ts
161
- const logger$14 = console;
160
+ const logger$12 = console;
162
161
  /**
163
162
  * Validate Dokploy token by making a test API call
164
163
  */
165
164
  async function validateDokployToken(endpoint, token) {
166
- const { DokployApi: DokployApi$1 } = await import("./dokploy-api-BZGk-lkD.mjs");
165
+ const { DokployApi: DokployApi$1 } = await import("./dokploy-api-BiSzWM4v.mjs");
167
166
  const api = new DokployApi$1({
168
167
  baseUrl: endpoint,
169
168
  token
@@ -226,36 +225,36 @@ async function prompt$1(message, hidden = false) {
226
225
  async function loginCommand(options) {
227
226
  const { service, token: providedToken, endpoint: providedEndpoint } = options;
228
227
  if (service === "dokploy") {
229
- logger$14.log("\n🔐 Logging in to Dokploy...\n");
228
+ logger$12.log("\n🔐 Logging in to Dokploy...\n");
230
229
  let endpoint = providedEndpoint;
231
230
  if (!endpoint) endpoint = await prompt$1("Dokploy URL (e.g., https://dokploy.example.com): ");
232
231
  endpoint = endpoint.replace(/\/$/, "");
233
232
  try {
234
233
  new URL(endpoint);
235
234
  } catch {
236
- logger$14.error("Invalid URL format");
235
+ logger$12.error("Invalid URL format");
237
236
  process.exit(1);
238
237
  }
239
238
  let token = providedToken;
240
239
  if (!token) {
241
- logger$14.log(`\nGenerate a token at: ${endpoint}/settings/profile\n`);
240
+ logger$12.log(`\nGenerate a token at: ${endpoint}/settings/profile\n`);
242
241
  token = await prompt$1("API Token: ", true);
243
242
  }
244
243
  if (!token) {
245
- logger$14.error("Token is required");
244
+ logger$12.error("Token is required");
246
245
  process.exit(1);
247
246
  }
248
- logger$14.log("\nValidating credentials...");
247
+ logger$12.log("\nValidating credentials...");
249
248
  const isValid = await validateDokployToken(endpoint, token);
250
249
  if (!isValid) {
251
- logger$14.error("\n✗ Invalid credentials. Please check your token and try again.");
250
+ logger$12.error("\n✗ Invalid credentials. Please check your token and try again.");
252
251
  process.exit(1);
253
252
  }
254
253
  await storeDokployCredentials(token, endpoint);
255
- logger$14.log("\n✓ Successfully logged in to Dokploy!");
256
- logger$14.log(` Endpoint: ${endpoint}`);
257
- logger$14.log(` Credentials stored in: ${getCredentialsPath()}`);
258
- logger$14.log("\nYou can now use deploy commands without setting DOKPLOY_API_TOKEN.");
254
+ logger$12.log("\n✓ Successfully logged in to Dokploy!");
255
+ logger$12.log(` Endpoint: ${endpoint}`);
256
+ logger$12.log(` Credentials stored in: ${getCredentialsPath()}`);
257
+ logger$12.log("\nYou can now use deploy commands without setting DOKPLOY_API_TOKEN.");
259
258
  }
260
259
  }
261
260
  /**
@@ -265,28 +264,28 @@ async function logoutCommand(options) {
265
264
  const { service = "dokploy" } = options;
266
265
  if (service === "all") {
267
266
  const dokployRemoved = await removeDokployCredentials();
268
- if (dokployRemoved) logger$14.log("\n✓ Logged out from all services");
269
- else logger$14.log("\nNo stored credentials found");
267
+ if (dokployRemoved) logger$12.log("\n✓ Logged out from all services");
268
+ else logger$12.log("\nNo stored credentials found");
270
269
  return;
271
270
  }
272
271
  if (service === "dokploy") {
273
272
  const removed = await removeDokployCredentials();
274
- if (removed) logger$14.log("\n✓ Logged out from Dokploy");
275
- else logger$14.log("\nNo Dokploy credentials found");
273
+ if (removed) logger$12.log("\n✓ Logged out from Dokploy");
274
+ else logger$12.log("\nNo Dokploy credentials found");
276
275
  }
277
276
  }
278
277
  /**
279
278
  * Show current login status
280
279
  */
281
280
  async function whoamiCommand() {
282
- logger$14.log("\n📋 Current credentials:\n");
281
+ logger$12.log("\n📋 Current credentials:\n");
283
282
  const dokploy = await getDokployCredentials();
284
283
  if (dokploy) {
285
- logger$14.log(" Dokploy:");
286
- logger$14.log(` Endpoint: ${dokploy.endpoint}`);
287
- logger$14.log(` Token: ${maskToken(dokploy.token)}`);
288
- } else logger$14.log(" Dokploy: Not logged in");
289
- logger$14.log(`\n Credentials file: ${getCredentialsPath()}`);
284
+ logger$12.log(" Dokploy:");
285
+ logger$12.log(` Endpoint: ${dokploy.endpoint}`);
286
+ logger$12.log(` Token: ${maskToken(dokploy.token)}`);
287
+ } else logger$12.log(" Dokploy: Not logged in");
288
+ logger$12.log(`\n Credentials file: ${getCredentialsPath()}`);
290
289
  }
291
290
  /**
292
291
  * Mask a token for display
@@ -302,7 +301,7 @@ function maskToken(token) {
302
301
  * Resolves provider configuration from the new simplified system
303
302
  * to the internal legacy format for backward compatibility
304
303
  */
305
- function resolveProviders(config$1, options) {
304
+ function resolveProviders(config, options) {
306
305
  const providers = [];
307
306
  let enableOpenApi = options.enableOpenApi || false;
308
307
  if (options.providers) return {
@@ -310,11 +309,11 @@ function resolveProviders(config$1, options) {
310
309
  enableOpenApi
311
310
  };
312
311
  if (options.provider) {
313
- const resolvedProviders = resolveMainProvider(options.provider, config$1.providers);
312
+ const resolvedProviders = resolveMainProvider(options.provider, config.providers);
314
313
  providers.push(...resolvedProviders.providers);
315
314
  enableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;
316
- } else if (config$1.providers) {
317
- const resolvedProviders = resolveAllConfiguredProviders(config$1.providers);
315
+ } else if (config.providers) {
316
+ const resolvedProviders = resolveAllConfiguredProviders(config.providers);
318
317
  providers.push(...resolvedProviders.providers);
319
318
  enableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;
320
319
  } else providers.push("aws-apigatewayv2", "aws-lambda");
@@ -361,475 +360,10 @@ function resolveAllConfiguredProviders(providersConfig) {
361
360
  enableOpenApi
362
361
  };
363
362
  }
364
- function isEnabled(config$1) {
365
- if (config$1 === void 0) return false;
366
- if (typeof config$1 === "boolean") return config$1;
367
- return config$1.enabled !== false;
368
- }
369
-
370
- //#endregion
371
- //#region src/credentials/index.ts
372
- const logger$13 = console;
373
- /**
374
- * Load environment files
375
- * @internal Exported for testing
376
- */
377
- function loadEnvFiles(envConfig, cwd = process.cwd()) {
378
- const loaded = [];
379
- const missing = [];
380
- const envFiles = envConfig ? Array.isArray(envConfig) ? envConfig : [envConfig] : [".env"];
381
- for (const envFile of envFiles) {
382
- const envPath = resolve(cwd, envFile);
383
- if (existsSync(envPath)) {
384
- config({
385
- path: envPath,
386
- override: true,
387
- quiet: true
388
- });
389
- loaded.push(envFile);
390
- } else if (envConfig) missing.push(envFile);
391
- }
392
- return {
393
- loaded,
394
- missing
395
- };
396
- }
397
- /**
398
- * Check if a port is available
399
- * @internal Exported for testing
400
- */
401
- async function isPortAvailable(port) {
402
- return new Promise((resolve$1) => {
403
- const server = createServer();
404
- server.once("error", (err) => {
405
- if (err.code === "EADDRINUSE") resolve$1(false);
406
- else resolve$1(false);
407
- });
408
- server.once("listening", () => {
409
- server.close();
410
- resolve$1(true);
411
- });
412
- server.listen(port);
413
- });
414
- }
415
- /**
416
- * Find an available port starting from the preferred port
417
- * @internal Exported for testing
418
- */
419
- async function findAvailablePort(preferredPort, maxAttempts = 10) {
420
- for (let i = 0; i < maxAttempts; i++) {
421
- const port = preferredPort + i;
422
- if (await isPortAvailable(port)) return port;
423
- logger$13.log(`⚠️ Port ${port} is in use, trying ${port + 1}...`);
424
- }
425
- throw new Error(`Could not find an available port after trying ${maxAttempts} ports starting from ${preferredPort}`);
426
- }
427
- const PORT_STATE_PATH = ".gkm/ports.json";
428
- /**
429
- * Parse docker-compose.yml and extract all port mappings that use env var interpolation.
430
- * Entries like `'${POSTGRES_HOST_PORT:-5432}:5432'` are captured.
431
- * Fixed port mappings like `'5050:80'` are skipped.
432
- * @internal Exported for testing
433
- */
434
- function parseComposePortMappings(composePath) {
435
- if (!existsSync(composePath)) return [];
436
- const content = readFileSync(composePath, "utf-8");
437
- const compose = parse$1(content);
438
- if (!compose?.services) return [];
439
- const results = [];
440
- for (const [serviceName, serviceConfig] of Object.entries(compose.services)) for (const portMapping of serviceConfig?.ports ?? []) {
441
- const match = String(portMapping).match(/\$\{(\w+):-(\d+)\}:(\d+)/);
442
- if (match?.[1] && match[2] && match[3]) results.push({
443
- service: serviceName,
444
- envVar: match[1],
445
- defaultPort: Number(match[2]),
446
- containerPort: Number(match[3])
447
- });
448
- }
449
- return results;
450
- }
451
- /**
452
- * Load saved port state from .gkm/ports.json.
453
- * @internal Exported for testing
454
- */
455
- async function loadPortState(workspaceRoot) {
456
- try {
457
- const raw = await readFile(join(workspaceRoot, PORT_STATE_PATH), "utf-8");
458
- return JSON.parse(raw);
459
- } catch {
460
- return {};
461
- }
462
- }
463
- /**
464
- * Save port state to .gkm/ports.json.
465
- * @internal Exported for testing
466
- */
467
- async function savePortState(workspaceRoot, ports) {
468
- const dir = join(workspaceRoot, ".gkm");
469
- await mkdir(dir, { recursive: true });
470
- await writeFile(join(workspaceRoot, PORT_STATE_PATH), `${JSON.stringify(ports, null, 2)}\n`);
471
- }
472
- /**
473
- * Check if a project's own Docker container is running and return its host port.
474
- * Uses `docker compose port` scoped to the project's compose file.
475
- * @internal Exported for testing
476
- */
477
- function getContainerHostPort(workspaceRoot, service, containerPort) {
478
- try {
479
- const result = execSync(`docker compose port ${service} ${containerPort}`, {
480
- cwd: workspaceRoot,
481
- stdio: "pipe"
482
- }).toString().trim();
483
- const match = result.match(/:(\d+)$/);
484
- return match ? Number(match[1]) : null;
485
- } catch {
486
- return null;
487
- }
488
- }
489
- /**
490
- * Resolve host ports for Docker services by parsing docker-compose.yml.
491
- * Priority: running container → saved state → find available port.
492
- * Persists resolved ports to .gkm/ports.json.
493
- * @internal Exported for testing
494
- */
495
- async function resolveServicePorts(workspaceRoot) {
496
- const composePath = join(workspaceRoot, "docker-compose.yml");
497
- const mappings = parseComposePortMappings(composePath);
498
- if (mappings.length === 0) return {
499
- dockerEnv: {},
500
- ports: {},
501
- mappings: []
502
- };
503
- const savedState = await loadPortState(workspaceRoot);
504
- const dockerEnv = {};
505
- const ports = {};
506
- const assignedPorts = /* @__PURE__ */ new Set();
507
- logger$13.log("\n🔌 Resolving service ports...");
508
- for (const mapping of mappings) {
509
- const containerPort = getContainerHostPort(workspaceRoot, mapping.service, mapping.containerPort);
510
- if (containerPort !== null) {
511
- ports[mapping.envVar] = containerPort;
512
- dockerEnv[mapping.envVar] = String(containerPort);
513
- assignedPorts.add(containerPort);
514
- logger$13.log(` 🔄 ${mapping.service}:${mapping.containerPort}: reusing existing container on port ${containerPort}`);
515
- continue;
516
- }
517
- const savedPort = savedState[mapping.envVar];
518
- if (savedPort && !assignedPorts.has(savedPort) && await isPortAvailable(savedPort)) {
519
- ports[mapping.envVar] = savedPort;
520
- dockerEnv[mapping.envVar] = String(savedPort);
521
- assignedPorts.add(savedPort);
522
- logger$13.log(` 💾 ${mapping.service}:${mapping.containerPort}: using saved port ${savedPort}`);
523
- continue;
524
- }
525
- let resolvedPort = await findAvailablePort(mapping.defaultPort);
526
- while (assignedPorts.has(resolvedPort)) resolvedPort = await findAvailablePort(resolvedPort + 1);
527
- ports[mapping.envVar] = resolvedPort;
528
- dockerEnv[mapping.envVar] = String(resolvedPort);
529
- assignedPorts.add(resolvedPort);
530
- if (resolvedPort !== mapping.defaultPort) logger$13.log(` ⚡ ${mapping.service}:${mapping.containerPort}: port ${mapping.defaultPort} occupied, using port ${resolvedPort}`);
531
- else logger$13.log(` ✅ ${mapping.service}:${mapping.containerPort}: using default port ${resolvedPort}`);
532
- }
533
- await savePortState(workspaceRoot, ports);
534
- return {
535
- dockerEnv,
536
- ports,
537
- mappings
538
- };
539
- }
540
- /**
541
- * Replace a port in a URL string.
542
- * Handles both `hostname:port` and `localhost:port` patterns.
543
- * @internal Exported for testing
544
- */
545
- function replacePortInUrl(url, oldPort, newPort) {
546
- if (oldPort === newPort) return url;
547
- let result = url.replace(new RegExp(`:${oldPort}(?=[/?#]|$)`, "g"), `:${newPort}`);
548
- result = result.replace(new RegExp(`%3A${oldPort}(?=[%/?#&]|$)`, "gi"), `%3A${newPort}`);
549
- return result;
550
- }
551
- /**
552
- * Rewrite connection URLs and port vars in secrets with resolved ports.
553
- * Uses the parsed compose mappings to determine which default ports to replace.
554
- * Pure transform — does not modify secrets on disk.
555
- * @internal Exported for testing
556
- */
557
- function rewriteUrlsWithPorts(secrets, resolvedPorts) {
558
- const { ports, mappings } = resolvedPorts;
559
- const result = { ...secrets };
560
- const portReplacements = [];
561
- const serviceNames = /* @__PURE__ */ new Set();
562
- for (const mapping of mappings) {
563
- serviceNames.add(mapping.service);
564
- const resolved = ports[mapping.envVar];
565
- if (resolved !== void 0) portReplacements.push({
566
- defaultPort: mapping.defaultPort,
567
- resolvedPort: resolved
568
- });
569
- }
570
- for (const [key, value] of Object.entries(result)) {
571
- if (!key.endsWith("_HOST")) continue;
572
- if (serviceNames.has(value)) result[key] = "localhost";
573
- }
574
- for (const [key, value] of Object.entries(result)) {
575
- if (!key.endsWith("_PORT")) continue;
576
- for (const { defaultPort, resolvedPort } of portReplacements) if (value === String(defaultPort)) result[key] = String(resolvedPort);
577
- }
578
- for (const [key, value] of Object.entries(result)) {
579
- if (!key.endsWith("_URL") && !key.endsWith("_ENDPOINT") && !key.endsWith("_CONNECTION_STRING") && key !== "DATABASE_URL") continue;
580
- let rewritten = value;
581
- for (const name$1 of serviceNames) rewritten = rewritten.replace(new RegExp(`@${name$1}:`, "g"), "@localhost:");
582
- for (const { defaultPort, resolvedPort } of portReplacements) rewritten = replacePortInUrl(rewritten, defaultPort, resolvedPort);
583
- result[key] = rewritten;
584
- }
585
- return result;
586
- }
587
- /**
588
- * Build the environment variables to pass to `docker compose up`.
589
- * Merges process.env, secrets, and port mappings so that Docker Compose
590
- * can interpolate variables like ${POSTGRES_USER} correctly.
591
- * @internal Exported for testing
592
- */
593
- function buildDockerComposeEnv(secretsEnv, portEnv) {
594
- return {
595
- ...process.env,
596
- ...secretsEnv,
597
- ...portEnv
598
- };
599
- }
600
- /**
601
- * Parse all service names from a docker-compose.yml file.
602
- * @internal Exported for testing
603
- */
604
- function parseComposeServiceNames(composePath) {
605
- if (!existsSync(composePath)) return [];
606
- const content = readFileSync(composePath, "utf-8");
607
- const compose = parse$1(content);
608
- return Object.keys(compose?.services ?? {});
609
- }
610
- /**
611
- * Start docker-compose services for a single-app project (no workspace config).
612
- * Starts all services defined in docker-compose.yml.
613
- */
614
- async function startComposeServices(cwd, portEnv, secretsEnv) {
615
- const composeFile = join(cwd, "docker-compose.yml");
616
- if (!existsSync(composeFile)) return;
617
- const servicesToStart = parseComposeServiceNames(composeFile);
618
- if (servicesToStart.length === 0) return;
619
- logger$13.log(`🐳 Starting services: ${servicesToStart.join(", ")}`);
620
- try {
621
- execSync(`docker compose up -d ${servicesToStart.join(" ")}`, {
622
- cwd,
623
- stdio: "inherit",
624
- env: buildDockerComposeEnv(secretsEnv, portEnv)
625
- });
626
- logger$13.log("✅ Services started");
627
- } catch (error) {
628
- logger$13.error("❌ Failed to start services:", error.message);
629
- throw error;
630
- }
631
- }
632
- /**
633
- * Start docker-compose services for a workspace.
634
- * Discovers all services from docker-compose.yml and starts everything
635
- * except app services (which are managed by turbo).
636
- * @internal Exported for testing
637
- */
638
- async function startWorkspaceServices(workspace, portEnv, secretsEnv) {
639
- const composeFile = join(workspace.root, "docker-compose.yml");
640
- if (!existsSync(composeFile)) return;
641
- const allServices = parseComposeServiceNames(composeFile);
642
- const appNames = new Set(Object.keys(workspace.apps));
643
- const servicesToStart = allServices.filter((name$1) => !appNames.has(name$1));
644
- if (servicesToStart.length === 0) return;
645
- logger$13.log(`🐳 Starting services: ${servicesToStart.join(", ")}`);
646
- try {
647
- execSync(`docker compose up -d ${servicesToStart.join(" ")}`, {
648
- cwd: workspace.root,
649
- stdio: "inherit",
650
- env: buildDockerComposeEnv(secretsEnv, portEnv)
651
- });
652
- logger$13.log("✅ Services started");
653
- } catch (error) {
654
- logger$13.error("❌ Failed to start services:", error.message);
655
- throw error;
656
- }
657
- }
658
- /**
659
- * Load and flatten secrets for an app from encrypted storage.
660
- * For workspace app: maps {APP}_DATABASE_URL → DATABASE_URL.
661
- * @internal Exported for testing
662
- */
663
- async function loadSecretsForApp(secretsRoot, appName, stages = ["dev", "development"]) {
664
- let secrets = {};
665
- for (const stage of stages) if (secretsExist(stage, secretsRoot)) {
666
- const stageSecrets = await readStageSecrets(stage, secretsRoot);
667
- if (stageSecrets) {
668
- logger$13.log(`🔐 Loading secrets from stage: ${stage}`);
669
- secrets = toEmbeddableSecrets(stageSecrets);
670
- break;
671
- }
672
- }
673
- if (Object.keys(secrets).length === 0) return {};
674
- if (!appName) return secrets;
675
- const prefix = appName.toUpperCase();
676
- const mapped = { ...secrets };
677
- const appDbUrl = secrets[`${prefix}_DATABASE_URL`];
678
- if (appDbUrl) mapped.DATABASE_URL = appDbUrl;
679
- return mapped;
680
- }
681
- /**
682
- * Walk up the directory tree to find the root containing .gkm/secrets/.
683
- * @internal Exported for testing
684
- */
685
- function findSecretsRoot(startDir) {
686
- let dir = startDir;
687
- while (dir !== "/") {
688
- if (existsSync(join(dir, ".gkm", "secrets"))) return dir;
689
- const parent = dirname(dir);
690
- if (parent === dir) break;
691
- dir = parent;
692
- }
693
- return startDir;
694
- }
695
- /**
696
- * Generate the credentials injection code snippet.
697
- * This is the common logic used by both entry wrapper and exec preload.
698
- * @internal
699
- */
700
- function generateCredentialsInjection(secretsJsonPath) {
701
- return `import { existsSync, readFileSync } from 'node:fs';
702
-
703
- // Inject dev secrets via globalThis and process.env
704
- // Using globalThis.__gkm_credentials__ avoids CJS/ESM interop issues where
705
- // Object.assign on the Credentials export only mutates one module copy.
706
- const secretsPath = '${secretsJsonPath}';
707
- if (existsSync(secretsPath)) {
708
- const secrets = JSON.parse(readFileSync(secretsPath, 'utf-8'));
709
- globalThis.__gkm_credentials__ = secrets;
710
- Object.assign(process.env, secrets);
711
- }
712
- `;
713
- }
714
- /**
715
- * Create a preload script that injects secrets into Credentials.
716
- * Used by `gkm exec` to inject secrets before running any command.
717
- * @internal Exported for testing
718
- */
719
- async function createCredentialsPreload(preloadPath, secretsJsonPath) {
720
- const content = `/**
721
- * Credentials preload generated by 'gkm exec'
722
- * This file is loaded via NODE_OPTIONS="--import <path>"
723
- */
724
- ${generateCredentialsInjection(secretsJsonPath)}`;
725
- await writeFile(preloadPath, content);
726
- }
727
- /**
728
- * Create a wrapper script that injects secrets before importing the entry file.
729
- * @internal Exported for testing
730
- */
731
- async function createEntryWrapper(wrapperPath, entryPath, secretsJsonPath) {
732
- const credentialsInjection = secretsJsonPath ? `${generateCredentialsInjection(secretsJsonPath)}
733
- ` : "";
734
- const content = `#!/usr/bin/env node
735
- /**
736
- * Entry wrapper generated by 'gkm dev --entry'
737
- */
738
- ${credentialsInjection}// Import and run the user's entry file (dynamic import ensures secrets load first)
739
- await import('${entryPath}');
740
- `;
741
- await writeFile(wrapperPath, content);
742
- }
743
- /**
744
- * Prepare credentials for dev/exec/test modes.
745
- * Loads workspace config, secrets, resolves Docker ports, rewrites URLs,
746
- * injects PORT, dependency URLs, and writes credentials JSON.
747
- *
748
- * @param options.resolveDockerPorts - How to resolve Docker ports:
749
- * - `'full'` (default): probe running containers, saved state, then find available ports. Used by dev/test.
750
- * - `'readonly'`: check running containers and saved state only, never probe for new ports. Used by exec.
751
- * @param options.stages - Secret stages to try, in order. Default: ['dev', 'development'].
752
- * @param options.startDocker - Start Docker Compose services after port resolution. Default: false.
753
- * @param options.secretsFileName - Custom secrets JSON filename. Default: 'dev-secrets-{appName}.json' or 'dev-secrets.json'.
754
- * @internal Exported for testing
755
- */
756
- async function prepareEntryCredentials(options) {
757
- const cwd = options.cwd ?? process.cwd();
758
- const portMode = options.resolveDockerPorts ?? "full";
759
- let workspaceAppPort;
760
- let secretsRoot = cwd;
761
- let appName;
762
- let appInfo;
763
- try {
764
- appInfo = await loadWorkspaceAppInfo(cwd);
765
- workspaceAppPort = appInfo.app.port;
766
- secretsRoot = appInfo.workspaceRoot;
767
- appName = appInfo.appName;
768
- } catch {
769
- secretsRoot = findSecretsRoot(cwd);
770
- appName = getAppNameFromCwd(cwd) ?? void 0;
771
- }
772
- const resolvedPort = options.explicitPort ?? workspaceAppPort ?? 3e3;
773
- const credentials = await loadSecretsForApp(secretsRoot, appName, options.stages);
774
- credentials.PORT = String(resolvedPort);
775
- const composePath = join(secretsRoot, "docker-compose.yml");
776
- const mappings = parseComposePortMappings(composePath);
777
- if (mappings.length > 0) {
778
- let resolvedPorts;
779
- if (portMode === "full") resolvedPorts = await resolveServicePorts(secretsRoot);
780
- else {
781
- const savedPorts = await loadPortState(secretsRoot);
782
- const ports = {};
783
- for (const mapping of mappings) {
784
- const containerPort = getContainerHostPort(secretsRoot, mapping.service, mapping.containerPort);
785
- if (containerPort !== null) ports[mapping.envVar] = containerPort;
786
- else {
787
- const saved = savedPorts[mapping.envVar];
788
- if (saved !== void 0) ports[mapping.envVar] = saved;
789
- }
790
- }
791
- resolvedPorts = {
792
- dockerEnv: {},
793
- ports,
794
- mappings
795
- };
796
- }
797
- if (options.startDocker) if (appInfo) await startWorkspaceServices(appInfo.workspace, resolvedPorts.dockerEnv, credentials);
798
- else await startComposeServices(secretsRoot, resolvedPorts.dockerEnv, credentials);
799
- if (Object.keys(resolvedPorts.ports).length > 0) {
800
- const rewritten = rewriteUrlsWithPorts(credentials, resolvedPorts);
801
- Object.assign(credentials, rewritten);
802
- logger$13.log(`🔌 Applied ${Object.keys(resolvedPorts.ports).length} port mapping(s)`);
803
- }
804
- }
805
- if (appInfo?.appName) {
806
- const depEnv = getDependencyEnvVars(appInfo.workspace, appInfo.appName);
807
- Object.assign(credentials, depEnv);
808
- }
809
- if (!credentials.EVENT_PUBLISHER_CONNECTION_STRING && !credentials.EVENT_SUBSCRIBER_CONNECTION_STRING && credentials.PGBOSS_DB_USER) {
810
- const pgbossUrl = generatePgBossUrl({
811
- username: credentials.PGBOSS_DB_USER,
812
- password: credentials.PGBOSS_DB_PASSWORD ?? "",
813
- host: credentials.POSTGRES_HOST ?? "localhost",
814
- port: Number(credentials.POSTGRES_PORT ?? "5432"),
815
- database: credentials.POSTGRES_DB ?? "app"
816
- });
817
- credentials.EVENT_PUBLISHER_CONNECTION_STRING = pgbossUrl;
818
- credentials.EVENT_SUBSCRIBER_CONNECTION_STRING = pgbossUrl;
819
- }
820
- const secretsDir = join(secretsRoot, ".gkm");
821
- await mkdir(secretsDir, { recursive: true });
822
- const secretsFileName = options.secretsFileName ?? (appName ? `dev-secrets-${appName}.json` : "dev-secrets.json");
823
- const secretsJsonPath = join(secretsDir, secretsFileName);
824
- await writeFile(secretsJsonPath, JSON.stringify(credentials, null, 2));
825
- return {
826
- credentials,
827
- resolvedPort,
828
- secretsJsonPath,
829
- appName,
830
- secretsRoot,
831
- appInfo
832
- };
363
+ function isEnabled(config) {
364
+ if (config === void 0) return false;
365
+ if (typeof config === "boolean") return config;
366
+ return config.enabled !== false;
833
367
  }
834
368
 
835
369
  //#endregion
@@ -837,7 +371,7 @@ async function prepareEntryCredentials(options) {
837
371
  var CronGenerator = class extends ConstructGenerator {
838
372
  async build(context, constructs, outputDir, options) {
839
373
  const provider = options?.provider || "aws-lambda";
840
- const logger$15 = console;
374
+ const logger$13 = console;
841
375
  const cronInfos = [];
842
376
  if (constructs.length === 0 || provider !== "aws-lambda") return cronInfos;
843
377
  const cronsDir = join(outputDir, "crons");
@@ -852,7 +386,7 @@ var CronGenerator = class extends ConstructGenerator {
852
386
  memorySize: construct.memorySize,
853
387
  environment: await construct.getEnvironment({ markOptional: context.markOptional })
854
388
  });
855
- logger$15.log(`Generated cron handler: ${key}`);
389
+ logger$13.log(`Generated cron handler: ${key}`);
856
390
  }
857
391
  return cronInfos;
858
392
  }
@@ -888,7 +422,7 @@ var FunctionGenerator = class extends ConstructGenerator {
888
422
  }
889
423
  async build(context, constructs, outputDir, options) {
890
424
  const provider = options?.provider || "aws-lambda";
891
- const logger$15 = console;
425
+ const logger$13 = console;
892
426
  const functionInfos = [];
893
427
  if (constructs.length === 0 || provider !== "aws-lambda") return functionInfos;
894
428
  const functionsDir = join(outputDir, "functions");
@@ -902,7 +436,7 @@ var FunctionGenerator = class extends ConstructGenerator {
902
436
  memorySize: construct.memorySize,
903
437
  environment: await construct.getEnvironment({ markOptional: context.markOptional })
904
438
  });
905
- logger$15.log(`Generated function handler: ${key}`);
439
+ logger$13.log(`Generated function handler: ${key}`);
906
440
  }
907
441
  return functionInfos;
908
442
  }
@@ -935,11 +469,11 @@ var SubscriberGenerator = class extends ConstructGenerator {
935
469
  }
936
470
  async build(context, constructs, outputDir, options) {
937
471
  const provider = options?.provider || "aws-lambda";
938
- const logger$15 = console;
472
+ const logger$13 = console;
939
473
  const subscriberInfos = [];
940
474
  if (provider === "server") {
941
475
  await this.generateServerSubscribersFile(outputDir, constructs);
942
- logger$15.log(`Generated server subscribers file with ${constructs.length} subscribers (polling mode)`);
476
+ logger$13.log(`Generated server subscribers file with ${constructs.length} subscribers (polling mode)`);
943
477
  return subscriberInfos;
944
478
  }
945
479
  if (constructs.length === 0) return subscriberInfos;
@@ -956,7 +490,7 @@ var SubscriberGenerator = class extends ConstructGenerator {
956
490
  memorySize: construct.memorySize,
957
491
  environment: await construct.getEnvironment({ markOptional: context.markOptional })
958
492
  });
959
- logger$15.log(`Generated subscriber handler: ${key}`);
493
+ logger$13.log(`Generated subscriber handler: ${key}`);
960
494
  }
961
495
  return subscriberInfos;
962
496
  }
@@ -1122,7 +656,7 @@ export async function setupSubscribers(
1122
656
 
1123
657
  //#endregion
1124
658
  //#region src/exec/index.ts
1125
- const logger$12 = console;
659
+ const logger$11 = console;
1126
660
  /**
1127
661
  * Run a command with secrets injected into Credentials.
1128
662
  * Uses Node's --import flag to preload a script that populates Credentials
@@ -1138,21 +672,21 @@ async function execCommand(commandArgs, options = {}) {
1138
672
  const cwd = options.cwd ?? process.cwd();
1139
673
  if (commandArgs.length === 0) throw new Error("No command specified. Usage: gkm exec -- <command>");
1140
674
  const defaultEnv = loadEnvFiles(".env");
1141
- if (defaultEnv.loaded.length > 0) logger$12.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
675
+ if (defaultEnv.loaded.length > 0) logger$11.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1142
676
  const { credentials, secretsJsonPath, appName } = await prepareEntryCredentials({
1143
677
  cwd,
1144
678
  resolveDockerPorts: "readonly"
1145
679
  });
1146
- if (appName) logger$12.log(`📦 App: ${appName}`);
680
+ if (appName) logger$11.log(`📦 App: ${appName}`);
1147
681
  const secretCount = Object.keys(credentials).filter((k) => k !== "PORT").length;
1148
- if (secretCount > 0) logger$12.log(`🔐 Loaded ${secretCount} secret(s)`);
682
+ if (secretCount > 0) logger$11.log(`🔐 Loaded ${secretCount} secret(s)`);
1149
683
  const preloadDir = join(cwd, ".gkm");
1150
684
  await mkdir(preloadDir, { recursive: true });
1151
685
  const preloadPath = join(preloadDir, "credentials-preload.mjs");
1152
686
  await createCredentialsPreload(preloadPath, secretsJsonPath);
1153
687
  const [cmd, ...args] = commandArgs;
1154
688
  if (!cmd) throw new Error("No command specified");
1155
- logger$12.log(`🚀 Running: ${[cmd, ...args].join(" ")}`);
689
+ logger$11.log(`🚀 Running: ${[cmd, ...args].join(" ")}`);
1156
690
  const existingNodeOptions = (process.env.NODE_OPTIONS ?? "").replace(/--import[= ]\S+/g, "").trim();
1157
691
  const preloadImport = `--import=${preloadPath}`;
1158
692
  const nodeOptions = [existingNodeOptions, preloadImport].filter(Boolean).join(" ");
@@ -1168,7 +702,7 @@ async function execCommand(commandArgs, options = {}) {
1168
702
  const exitCode = await new Promise((resolve$1) => {
1169
703
  child.on("close", (code) => resolve$1(code ?? 0));
1170
704
  child.on("error", (error) => {
1171
- logger$12.error(`Failed to run command: ${error.message}`);
705
+ logger$11.error(`Failed to run command: ${error.message}`);
1172
706
  resolve$1(1);
1173
707
  });
1174
708
  });
@@ -1177,15 +711,15 @@ async function execCommand(commandArgs, options = {}) {
1177
711
 
1178
712
  //#endregion
1179
713
  //#region src/dev/index.ts
1180
- const logger$11 = console;
714
+ const logger$10 = console;
1181
715
  /**
1182
716
  * Normalize telescope configuration
1183
717
  * @internal Exported for testing
1184
718
  */
1185
- function normalizeTelescopeConfig(config$1) {
1186
- if (config$1 === false) return void 0;
1187
- if (typeof config$1 === "string") {
1188
- const { path: telescopePath, importPattern: telescopeImportPattern } = parseModuleConfig(config$1, "telescope");
719
+ function normalizeTelescopeConfig(config) {
720
+ if (config === false) return void 0;
721
+ if (typeof config === "string") {
722
+ const { path: telescopePath, importPattern: telescopeImportPattern } = parseModuleConfig(config, "telescope");
1189
723
  return {
1190
724
  enabled: true,
1191
725
  telescopePath,
@@ -1197,9 +731,9 @@ function normalizeTelescopeConfig(config$1) {
1197
731
  websocket: true
1198
732
  };
1199
733
  }
1200
- const isEnabled$1 = config$1 === true || config$1 === void 0 || config$1.enabled !== false;
734
+ const isEnabled$1 = config === true || config === void 0 || config.enabled !== false;
1201
735
  if (!isEnabled$1) return void 0;
1202
- const telescopeConfig = typeof config$1 === "object" ? config$1 : {};
736
+ const telescopeConfig = typeof config === "object" ? config : {};
1203
737
  return {
1204
738
  enabled: true,
1205
739
  path: telescopeConfig.path ?? "/__telescope",
@@ -1213,10 +747,10 @@ function normalizeTelescopeConfig(config$1) {
1213
747
  * Normalize studio configuration
1214
748
  * @internal Exported for testing
1215
749
  */
1216
- function normalizeStudioConfig(config$1) {
1217
- if (config$1 === false) return void 0;
1218
- if (typeof config$1 === "string") {
1219
- const { path: studioPath, importPattern: studioImportPattern } = parseModuleConfig(config$1, "studio");
750
+ function normalizeStudioConfig(config) {
751
+ if (config === false) return void 0;
752
+ if (typeof config === "string") {
753
+ const { path: studioPath, importPattern: studioImportPattern } = parseModuleConfig(config, "studio");
1220
754
  return {
1221
755
  enabled: true,
1222
756
  studioPath,
@@ -1225,9 +759,9 @@ function normalizeStudioConfig(config$1) {
1225
759
  schema: "public"
1226
760
  };
1227
761
  }
1228
- const isEnabled$1 = config$1 === true || config$1 === void 0 || config$1.enabled !== false;
762
+ const isEnabled$1 = config === true || config === void 0 || config.enabled !== false;
1229
763
  if (!isEnabled$1) return void 0;
1230
- const studioConfig = typeof config$1 === "object" ? config$1 : {};
764
+ const studioConfig = typeof config === "object" ? config : {};
1231
765
  return {
1232
766
  enabled: true,
1233
767
  path: studioConfig.path ?? "/__studio",
@@ -1238,9 +772,9 @@ function normalizeStudioConfig(config$1) {
1238
772
  * Normalize hooks configuration
1239
773
  * @internal Exported for testing
1240
774
  */
1241
- function normalizeHooksConfig(config$1, cwd = process.cwd()) {
1242
- if (!config$1?.server) return void 0;
1243
- const serverPath = config$1.server.endsWith(".ts") ? config$1.server : `${config$1.server}.ts`;
775
+ function normalizeHooksConfig(config, cwd = process.cwd()) {
776
+ if (!config?.server) return void 0;
777
+ const serverPath = config.server.endsWith(".ts") ? config.server : `${config.server}.ts`;
1244
778
  const resolvedPath = resolve(cwd, serverPath);
1245
779
  return { serverHooksPath: resolvedPath };
1246
780
  }
@@ -1250,34 +784,34 @@ function normalizeHooksConfig(config$1, cwd = process.cwd()) {
1250
784
  */
1251
785
  function normalizeProductionConfig(cliProduction, configProduction) {
1252
786
  if (!cliProduction) return void 0;
1253
- const config$1 = configProduction ?? {};
787
+ const config = configProduction ?? {};
1254
788
  return {
1255
789
  enabled: true,
1256
- bundle: config$1.bundle ?? true,
1257
- minify: config$1.minify ?? true,
1258
- healthCheck: config$1.healthCheck ?? "/health",
1259
- gracefulShutdown: config$1.gracefulShutdown ?? true,
1260
- external: config$1.external ?? [],
1261
- subscribers: config$1.subscribers ?? "exclude",
1262
- openapi: config$1.openapi ?? false,
1263
- optimizedHandlers: config$1.optimizedHandlers ?? true
790
+ bundle: config.bundle ?? true,
791
+ minify: config.minify ?? true,
792
+ healthCheck: config.healthCheck ?? "/health",
793
+ gracefulShutdown: config.gracefulShutdown ?? true,
794
+ external: config.external ?? [],
795
+ subscribers: config.subscribers ?? "exclude",
796
+ openapi: config.openapi ?? false,
797
+ optimizedHandlers: config.optimizedHandlers ?? true
1264
798
  };
1265
799
  }
1266
800
  /**
1267
801
  * Get production config from GkmConfig
1268
802
  * @internal
1269
803
  */
1270
- function getProductionConfigFromGkm(config$1) {
1271
- const serverConfig = config$1.providers?.server;
804
+ function getProductionConfigFromGkm(config) {
805
+ const serverConfig = config.providers?.server;
1272
806
  if (typeof serverConfig === "object") return serverConfig.production;
1273
807
  return void 0;
1274
808
  }
1275
809
  async function devCommand(options) {
1276
810
  if (options.entry) return entryDevCommand(options);
1277
811
  const defaultEnv = loadEnvFiles(".env");
1278
- if (defaultEnv.loaded.length > 0) logger$11.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
812
+ if (defaultEnv.loaded.length > 0) logger$10.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1279
813
  const appName = getAppNameFromCwd();
1280
- let config$1;
814
+ let config;
1281
815
  let appRoot = process.cwd();
1282
816
  let secretsRoot = process.cwd();
1283
817
  let workspaceAppName;
@@ -1285,15 +819,15 @@ async function devCommand(options) {
1285
819
  let workspace;
1286
820
  if (appName) try {
1287
821
  const appConfig = await loadAppConfig();
1288
- config$1 = appConfig.gkmConfig;
822
+ config = appConfig.gkmConfig;
1289
823
  appRoot = appConfig.appRoot;
1290
824
  secretsRoot = appConfig.workspaceRoot;
1291
825
  workspaceAppName = appConfig.appName;
1292
826
  workspaceAppPort = appConfig.app.port;
1293
827
  workspace = appConfig.workspace;
1294
- logger$11.log(`📦 Running app: ${appConfig.appName} on port ${workspaceAppPort}`);
828
+ logger$10.log(`📦 Running app: ${appConfig.appName} on port ${workspaceAppPort}`);
1295
829
  if (appConfig.app.entry) {
1296
- logger$11.log(`📄 Using entry point: ${appConfig.app.entry}`);
830
+ logger$10.log(`📄 Using entry point: ${appConfig.app.entry}`);
1297
831
  return entryDevCommand({
1298
832
  ...options,
1299
833
  entry: appConfig.app.entry,
@@ -1304,42 +838,42 @@ async function devCommand(options) {
1304
838
  } catch {
1305
839
  const loadedConfig = await loadWorkspaceConfig();
1306
840
  if (loadedConfig.type === "workspace") {
1307
- logger$11.log("📦 Detected workspace configuration");
841
+ logger$10.log("📦 Detected workspace configuration");
1308
842
  return workspaceDevCommand(loadedConfig.workspace, options);
1309
843
  }
1310
- config$1 = loadedConfig.raw;
844
+ config = loadedConfig.raw;
1311
845
  }
1312
846
  else {
1313
847
  const loadedConfig = await loadWorkspaceConfig();
1314
848
  if (loadedConfig.type === "workspace") {
1315
- logger$11.log("📦 Detected workspace configuration");
849
+ logger$10.log("📦 Detected workspace configuration");
1316
850
  return workspaceDevCommand(loadedConfig.workspace, options);
1317
851
  }
1318
- config$1 = loadedConfig.raw;
1319
- }
1320
- if (config$1.env) {
1321
- const { loaded, missing } = loadEnvFiles(config$1.env, appRoot);
1322
- if (loaded.length > 0) logger$11.log(`📦 Loaded env: ${loaded.join(", ")}`);
1323
- if (missing.length > 0) logger$11.warn(`⚠️ Missing env files: ${missing.join(", ")}`);
1324
- }
1325
- const resolved = resolveProviders(config$1, { provider: "server" });
1326
- logger$11.log("🚀 Starting development server...");
1327
- logger$11.log(`Loading routes from: ${config$1.routes}`);
1328
- if (config$1.functions) logger$11.log(`Loading functions from: ${config$1.functions}`);
1329
- if (config$1.crons) logger$11.log(`Loading crons from: ${config$1.crons}`);
1330
- if (config$1.subscribers) logger$11.log(`Loading subscribers from: ${config$1.subscribers}`);
1331
- logger$11.log(`Using envParser: ${config$1.envParser}`);
1332
- const { path: envParserPath, importPattern: envParserImportPattern } = parseModuleConfig(config$1.envParser, "envParser");
1333
- const { path: loggerPath, importPattern: loggerImportPattern } = parseModuleConfig(config$1.logger, "logger");
1334
- const telescope = normalizeTelescopeConfig(config$1.telescope);
1335
- if (telescope) logger$11.log(`🔭 Telescope enabled at ${telescope.path}`);
1336
- const studio = normalizeStudioConfig(config$1.studio);
1337
- if (studio) logger$11.log(`🗄️ Studio enabled at ${studio.path}`);
1338
- const hooks = normalizeHooksConfig(config$1.hooks, appRoot);
1339
- if (hooks) logger$11.log(`🪝 Server hooks enabled from ${config$1.hooks?.server}`);
1340
- const openApiConfig = resolveOpenApiConfig(config$1);
852
+ config = loadedConfig.raw;
853
+ }
854
+ if (config.env) {
855
+ const { loaded, missing } = loadEnvFiles(config.env, appRoot);
856
+ if (loaded.length > 0) logger$10.log(`📦 Loaded env: ${loaded.join(", ")}`);
857
+ if (missing.length > 0) logger$10.warn(`⚠️ Missing env files: ${missing.join(", ")}`);
858
+ }
859
+ const resolved = resolveProviders(config, { provider: "server" });
860
+ logger$10.log("🚀 Starting development server...");
861
+ logger$10.log(`Loading routes from: ${config.routes}`);
862
+ if (config.functions) logger$10.log(`Loading functions from: ${config.functions}`);
863
+ if (config.crons) logger$10.log(`Loading crons from: ${config.crons}`);
864
+ if (config.subscribers) logger$10.log(`Loading subscribers from: ${config.subscribers}`);
865
+ logger$10.log(`Using envParser: ${config.envParser}`);
866
+ const { path: envParserPath, importPattern: envParserImportPattern } = parseModuleConfig(config.envParser, "envParser");
867
+ const { path: loggerPath, importPattern: loggerImportPattern } = parseModuleConfig(config.logger, "logger");
868
+ const telescope = normalizeTelescopeConfig(config.telescope);
869
+ if (telescope) logger$10.log(`🔭 Telescope enabled at ${telescope.path}`);
870
+ const studio = normalizeStudioConfig(config.studio);
871
+ if (studio) logger$10.log(`🗄️ Studio enabled at ${studio.path}`);
872
+ const hooks = normalizeHooksConfig(config.hooks, appRoot);
873
+ if (hooks) logger$10.log(`🪝 Server hooks enabled from ${config.hooks?.server}`);
874
+ const openApiConfig = resolveOpenApiConfig(config);
1341
875
  const enableOpenApi = openApiConfig.enabled || resolved.enableOpenApi;
1342
- if (enableOpenApi) logger$11.log(`📄 OpenAPI output: ${OPENAPI_OUTPUT_PATH}`);
876
+ if (enableOpenApi) logger$10.log(`📄 OpenAPI output: ${OPENAPI_OUTPUT_PATH}`);
1343
877
  const buildContext = {
1344
878
  envParserPath,
1345
879
  envParserImportPattern,
@@ -1349,16 +883,16 @@ async function devCommand(options) {
1349
883
  studio,
1350
884
  hooks
1351
885
  };
1352
- await buildServer(config$1, buildContext, resolved.providers[0], enableOpenApi, appRoot);
1353
- if (enableOpenApi) await generateOpenApi(config$1);
1354
- const runtime = config$1.runtime ?? "node";
886
+ await buildServer(config, buildContext, resolved.providers[0], enableOpenApi, appRoot);
887
+ if (enableOpenApi) await generateOpenApi(config);
888
+ const runtime = config.runtime ?? "node";
1355
889
  let secretsJsonPath;
1356
890
  const appSecrets = await loadSecretsForApp(secretsRoot, workspaceAppName);
1357
891
  const resolvedPorts = await resolveServicePorts(secretsRoot);
1358
892
  if (Object.keys(resolvedPorts.ports).length > 0) {
1359
893
  const rewritten = rewriteUrlsWithPorts(appSecrets, resolvedPorts);
1360
894
  Object.assign(appSecrets, rewritten);
1361
- logger$11.log(`🔌 Applied ${Object.keys(resolvedPorts.ports).length} port mapping(s)`);
895
+ logger$10.log(`🔌 Applied ${Object.keys(resolvedPorts.ports).length} port mapping(s)`);
1362
896
  }
1363
897
  if (workspace && workspaceAppName) {
1364
898
  const depEnv = getDependencyEnvVars(workspace, workspaceAppName);
@@ -1370,25 +904,25 @@ async function devCommand(options) {
1370
904
  const secretsFileName = workspaceAppName ? `dev-secrets-${workspaceAppName}.json` : "dev-secrets.json";
1371
905
  secretsJsonPath = join(secretsDir, secretsFileName);
1372
906
  await writeFile(secretsJsonPath, JSON.stringify(appSecrets, null, 2));
1373
- logger$11.log(`🔐 Loaded ${Object.keys(appSecrets).length} secret(s)`);
907
+ logger$10.log(`🔐 Loaded ${Object.keys(appSecrets).length} secret(s)`);
1374
908
  }
1375
909
  const devServer = new DevServer(resolved.providers[0], options.port ?? workspaceAppPort ?? 3e3, options.portExplicit ?? false, enableOpenApi, telescope, studio, runtime, appRoot, secretsJsonPath);
1376
910
  await devServer.start();
1377
- const envParserFile = config$1.envParser.split("#")[0] ?? config$1.envParser;
1378
- const loggerFile = config$1.logger.split("#")[0] ?? config$1.logger;
1379
- const hooksFileParts = config$1.hooks?.server?.split("#");
911
+ const envParserFile = config.envParser.split("#")[0] ?? config.envParser;
912
+ const loggerFile = config.logger.split("#")[0] ?? config.logger;
913
+ const hooksFileParts = config.hooks?.server?.split("#");
1380
914
  const hooksFile = hooksFileParts?.[0];
1381
915
  const watchPatterns = [
1382
- config$1.routes,
1383
- ...config$1.functions ? [config$1.functions] : [],
1384
- ...config$1.crons ? [config$1.crons] : [],
1385
- ...config$1.subscribers ? [config$1.subscribers] : [],
916
+ config.routes,
917
+ ...config.functions ? [config.functions] : [],
918
+ ...config.crons ? [config.crons] : [],
919
+ ...config.subscribers ? [config.subscribers] : [],
1386
920
  envParserFile.endsWith(".ts") ? envParserFile : `${envParserFile}.ts`,
1387
921
  loggerFile.endsWith(".ts") ? loggerFile : `${loggerFile}.ts`,
1388
922
  ...hooksFile ? [hooksFile.endsWith(".ts") ? hooksFile : `${hooksFile}.ts`] : []
1389
923
  ].flat().filter((p) => typeof p === "string");
1390
924
  const normalizedPatterns = watchPatterns.map((p) => p.startsWith("./") ? p.slice(2) : p);
1391
- logger$11.log(`👀 Watching for changes in: ${normalizedPatterns.join(", ")}`);
925
+ logger$10.log(`👀 Watching for changes in: ${normalizedPatterns.join(", ")}`);
1392
926
  const resolvedFiles = await fg(normalizedPatterns, {
1393
927
  cwd: appRoot,
1394
928
  absolute: false,
@@ -1398,7 +932,7 @@ async function devCommand(options) {
1398
932
  const parts = f.split("/");
1399
933
  return parts.slice(0, -1).join("/");
1400
934
  }))];
1401
- logger$11.log(`📁 Found ${resolvedFiles.length} files in ${dirsToWatch.length} directories`);
935
+ logger$10.log(`📁 Found ${resolvedFiles.length} files in ${dirsToWatch.length} directories`);
1402
936
  const watcher = chokidar.watch([...resolvedFiles, ...dirsToWatch], {
1403
937
  ignored: /(^|[/\\])\../,
1404
938
  persistent: true,
@@ -1406,29 +940,29 @@ async function devCommand(options) {
1406
940
  cwd: appRoot
1407
941
  });
1408
942
  watcher.on("ready", () => {
1409
- logger$11.log("🔍 File watcher ready");
943
+ logger$10.log("🔍 File watcher ready");
1410
944
  });
1411
945
  watcher.on("error", (error) => {
1412
- logger$11.error("❌ Watcher error:", error);
946
+ logger$10.error("❌ Watcher error:", error);
1413
947
  });
1414
948
  let rebuildTimeout = null;
1415
949
  watcher.on("change", async (path) => {
1416
- logger$11.log(`📝 File changed: ${path}`);
950
+ logger$10.log(`📝 File changed: ${path}`);
1417
951
  if (rebuildTimeout) clearTimeout(rebuildTimeout);
1418
952
  rebuildTimeout = setTimeout(async () => {
1419
953
  try {
1420
- logger$11.log("🔄 Rebuilding...");
1421
- await buildServer(config$1, buildContext, resolved.providers[0], enableOpenApi, appRoot, true);
1422
- if (enableOpenApi) await generateOpenApi(config$1, {
954
+ logger$10.log("🔄 Rebuilding...");
955
+ await buildServer(config, buildContext, resolved.providers[0], enableOpenApi, appRoot, true);
956
+ if (enableOpenApi) await generateOpenApi(config, {
1423
957
  silent: true,
1424
958
  bustCache: true
1425
959
  });
1426
- logger$11.log("✅ Rebuild complete, restarting server...");
960
+ logger$10.log("✅ Rebuild complete, restarting server...");
1427
961
  await devServer.restart();
1428
962
  } catch (error) {
1429
963
  const err = error;
1430
- logger$11.error(`❌ Rebuild failed: ${err.message}`);
1431
- if (err.stack) logger$11.error(err.stack);
964
+ logger$10.error(`❌ Rebuild failed: ${err.message}`);
965
+ if (err.stack) logger$10.error(err.stack);
1432
966
  }
1433
967
  }, 300);
1434
968
  });
@@ -1436,9 +970,9 @@ async function devCommand(options) {
1436
970
  const shutdown = () => {
1437
971
  if (isShuttingDown) return;
1438
972
  isShuttingDown = true;
1439
- logger$11.log("\n🛑 Shutting down...");
973
+ logger$10.log("\n🛑 Shutting down...");
1440
974
  Promise.all([watcher.close(), devServer.stop()]).catch((err) => {
1441
- logger$11.error("Error during shutdown:", err);
975
+ logger$10.error("Error during shutdown:", err);
1442
976
  }).finally(() => {
1443
977
  process.exit(0);
1444
978
  });
@@ -1637,11 +1171,11 @@ async function loadDevSecrets(workspace) {
1637
1171
  for (const stage of stages) if (secretsExist(stage, workspace.root)) {
1638
1172
  const secrets = await readStageSecrets(stage, workspace.root);
1639
1173
  if (secrets) {
1640
- logger$11.log(`🔐 Loading secrets from stage: ${stage}`);
1174
+ logger$10.log(`🔐 Loading secrets from stage: ${stage}`);
1641
1175
  return toEmbeddableSecrets(secrets);
1642
1176
  }
1643
1177
  }
1644
- logger$11.warn("⚠️ Secrets enabled but no dev/development secrets found. Run \"gkm setup\" to initialize your development environment");
1178
+ logger$10.warn("⚠️ Secrets enabled but no dev/development secrets found. Run \"gkm setup\" to initialize your development environment");
1645
1179
  return {};
1646
1180
  }
1647
1181
  /**
@@ -1658,39 +1192,39 @@ async function workspaceDevCommand(workspace, options) {
1658
1192
  const backendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "backend");
1659
1193
  const frontendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "web");
1660
1194
  const mobileApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "mobile");
1661
- logger$11.log(`\n🚀 Starting workspace: ${workspace.name}`);
1195
+ logger$10.log(`\n🚀 Starting workspace: ${workspace.name}`);
1662
1196
  const counts = [`${backendApps.length} backend`, `${frontendApps.length} web`];
1663
1197
  if (mobileApps.length > 0) counts.push(`${mobileApps.length} mobile`);
1664
- logger$11.log(` ${counts.join(", ")} app(s)`);
1198
+ logger$10.log(` ${counts.join(", ")} app(s)`);
1665
1199
  const conflicts = checkPortConflicts(workspace);
1666
1200
  if (conflicts.length > 0) {
1667
- for (const conflict of conflicts) logger$11.error(`❌ Port conflict: Apps "${conflict.app1}" and "${conflict.app2}" both use port ${conflict.port}`);
1201
+ for (const conflict of conflicts) logger$10.error(`❌ Port conflict: Apps "${conflict.app1}" and "${conflict.app2}" both use port ${conflict.port}`);
1668
1202
  throw new Error("Port conflicts detected. Please assign unique ports to each app.");
1669
1203
  }
1670
1204
  if (frontendApps.length > 0) {
1671
- logger$11.log("\n🔍 Validating frontend apps...");
1205
+ logger$10.log("\n🔍 Validating frontend apps...");
1672
1206
  const validationResults = await validateFrontendApps(workspace);
1673
1207
  let hasErrors = false;
1674
1208
  for (const result of validationResults) {
1675
1209
  if (!result.valid) {
1676
1210
  hasErrors = true;
1677
- logger$11.error(`\n❌ Frontend app "${result.appName}" validation failed:`);
1678
- for (const error of result.errors) logger$11.error(` • ${error}`);
1211
+ logger$10.error(`\n❌ Frontend app "${result.appName}" validation failed:`);
1212
+ for (const error of result.errors) logger$10.error(` • ${error}`);
1679
1213
  }
1680
- for (const warning of result.warnings) logger$11.warn(` ⚠️ ${result.appName}: ${warning}`);
1214
+ for (const warning of result.warnings) logger$10.warn(` ⚠️ ${result.appName}: ${warning}`);
1681
1215
  }
1682
1216
  if (hasErrors) throw new Error("Frontend app validation failed. Fix the issues above and try again.");
1683
- logger$11.log("✅ Frontend apps validated");
1217
+ logger$10.log("✅ Frontend apps validated");
1684
1218
  }
1685
1219
  const resolvedPorts = await resolveServicePorts(workspace.root);
1686
1220
  const rawSecrets = await loadDevSecrets(workspace);
1687
1221
  await startWorkspaceServices(workspace, resolvedPorts.dockerEnv, rawSecrets);
1688
1222
  const secretsEnv = rewriteUrlsWithPorts(rawSecrets, resolvedPorts);
1689
- if (Object.keys(secretsEnv).length > 0) logger$11.log(` Loaded ${Object.keys(secretsEnv).length} secret(s)`);
1223
+ if (Object.keys(secretsEnv).length > 0) logger$10.log(` Loaded ${Object.keys(secretsEnv).length} secret(s)`);
1690
1224
  const dependencyEnv = generateAllDependencyEnvVars(workspace);
1691
1225
  if (Object.keys(dependencyEnv).length > 0) {
1692
- logger$11.log("📡 Dependency URLs:");
1693
- for (const [key, value] of Object.entries(dependencyEnv)) logger$11.log(` ${key}=${value}`);
1226
+ logger$10.log("📡 Dependency URLs:");
1227
+ for (const [key, value] of Object.entries(dependencyEnv)) logger$10.log(` ${key}=${value}`);
1694
1228
  }
1695
1229
  let turboFilter = [];
1696
1230
  if (options.app) {
@@ -1699,19 +1233,19 @@ async function workspaceDevCommand(workspace, options) {
1699
1233
  throw new Error(`App "${options.app}" not found. Available apps: ${appNames}`);
1700
1234
  }
1701
1235
  turboFilter = ["--filter", options.app];
1702
- logger$11.log(`\n🎯 Running single app: ${options.app}`);
1236
+ logger$10.log(`\n🎯 Running single app: ${options.app}`);
1703
1237
  } else if (options.filter) {
1704
1238
  turboFilter = ["--filter", options.filter];
1705
- logger$11.log(`\n🔍 Using filter: ${options.filter}`);
1706
- } else logger$11.log(`\n🎯 Running all ${appCount} apps`);
1239
+ logger$10.log(`\n🔍 Using filter: ${options.filter}`);
1240
+ } else logger$10.log(`\n🎯 Running all ${appCount} apps`);
1707
1241
  const buildOrder = getAppBuildOrder(workspace);
1708
- logger$11.log("\n📋 Apps (in dependency order):");
1242
+ logger$10.log("\n📋 Apps (in dependency order):");
1709
1243
  for (const appName of buildOrder) {
1710
1244
  const app = workspace.apps[appName];
1711
1245
  if (!app) continue;
1712
1246
  const deps = app.dependencies.length > 0 ? ` (depends on: ${app.dependencies.join(", ")})` : "";
1713
1247
  const icon = app.type === "backend" ? "🔧" : app.type === "mobile" ? "📱" : "🌐";
1714
- logger$11.log(` ${icon} ${appName} → http://localhost:${app.port}${deps}`);
1248
+ logger$10.log(` ${icon} ${appName} → http://localhost:${app.port}${deps}`);
1715
1249
  }
1716
1250
  const configFiles = [
1717
1251
  "gkm.config.ts",
@@ -1733,7 +1267,7 @@ async function workspaceDevCommand(workspace, options) {
1733
1267
  NODE_ENV: "development",
1734
1268
  ...configPath ? { GKM_CONFIG_PATH: configPath } : {}
1735
1269
  };
1736
- logger$11.log("\n🏃 Starting turbo run dev...\n");
1270
+ logger$10.log("\n🏃 Starting turbo run dev...\n");
1737
1271
  const turboProcess = spawn("pnpm", [
1738
1272
  "turbo",
1739
1273
  "run",
@@ -1749,7 +1283,7 @@ async function workspaceDevCommand(workspace, options) {
1749
1283
  const shutdown = () => {
1750
1284
  if (isShuttingDown) return;
1751
1285
  isShuttingDown = true;
1752
- logger$11.log("\n🛑 Shutting down workspace...");
1286
+ logger$10.log("\n🛑 Shutting down workspace...");
1753
1287
  const pid = turboProcess.pid;
1754
1288
  if (pid) try {
1755
1289
  process.kill(-pid, "SIGTERM");
@@ -1773,7 +1307,7 @@ async function workspaceDevCommand(workspace, options) {
1773
1307
  process.on("SIGTERM", shutdown);
1774
1308
  return new Promise((resolve$1, reject) => {
1775
1309
  turboProcess.on("error", (error) => {
1776
- logger$11.error("❌ Turbo error:", error);
1310
+ logger$10.error("❌ Turbo error:", error);
1777
1311
  reject(error);
1778
1312
  });
1779
1313
  turboProcess.on("exit", (code) => {
@@ -1782,16 +1316,16 @@ async function workspaceDevCommand(workspace, options) {
1782
1316
  });
1783
1317
  });
1784
1318
  }
1785
- async function buildServer(config$1, context, provider, enableOpenApi, appRoot = process.cwd(), bustCache = false) {
1319
+ async function buildServer(config, context, provider, enableOpenApi, appRoot = process.cwd(), bustCache = false) {
1786
1320
  const endpointGenerator = new EndpointGenerator();
1787
1321
  const functionGenerator = new FunctionGenerator();
1788
1322
  const cronGenerator = new CronGenerator();
1789
1323
  const subscriberGenerator = new SubscriberGenerator();
1790
1324
  const [allEndpoints, allFunctions, allCrons, allSubscribers] = await Promise.all([
1791
- endpointGenerator.load(config$1.routes, appRoot, bustCache),
1792
- config$1.functions ? functionGenerator.load(config$1.functions, appRoot, bustCache) : [],
1793
- config$1.crons ? cronGenerator.load(config$1.crons, appRoot, bustCache) : [],
1794
- config$1.subscribers ? subscriberGenerator.load(config$1.subscribers, appRoot, bustCache) : []
1325
+ endpointGenerator.load(config.routes, appRoot, bustCache),
1326
+ config.functions ? functionGenerator.load(config.functions, appRoot, bustCache) : [],
1327
+ config.crons ? cronGenerator.load(config.crons, appRoot, bustCache) : [],
1328
+ config.subscribers ? subscriberGenerator.load(config.subscribers, appRoot, bustCache) : []
1795
1329
  ]);
1796
1330
  const outputDir = join(appRoot, ".gkm", provider);
1797
1331
  await mkdir(outputDir, { recursive: true });
@@ -1815,11 +1349,11 @@ async function entryDevCommand(options) {
1815
1349
  const entryPath = resolve(process.cwd(), entry);
1816
1350
  if (!existsSync(entryPath)) throw new Error(`Entry file not found: ${entryPath}`);
1817
1351
  const defaultEnv = loadEnvFiles(".env");
1818
- if (defaultEnv.loaded.length > 0) logger$11.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1352
+ if (defaultEnv.loaded.length > 0) logger$10.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1819
1353
  const { credentials, resolvedPort, secretsJsonPath, appName } = await prepareEntryCredentials({ explicitPort: options.portExplicit ? options.port : void 0 });
1820
- if (appName) logger$11.log(`📦 App: ${appName} (port ${resolvedPort})`);
1821
- logger$11.log(`🚀 Starting entry file: ${entry} on port ${resolvedPort}`);
1822
- if (Object.keys(credentials).length > 1) logger$11.log(`🔐 Loaded ${Object.keys(credentials).length - 1} secret(s) + PORT`);
1354
+ if (appName) logger$10.log(`📦 App: ${appName} (port ${resolvedPort})`);
1355
+ logger$10.log(`🚀 Starting entry file: ${entry} on port ${resolvedPort}`);
1356
+ if (Object.keys(credentials).length > 1) logger$10.log(`🔐 Loaded ${Object.keys(credentials).length - 1} secret(s) + PORT`);
1823
1357
  const wrapperDir = join(process.cwd(), ".gkm");
1824
1358
  await mkdir(wrapperDir, { recursive: true });
1825
1359
  const wrapperPath = join(wrapperDir, "entry-wrapper.ts");
@@ -1830,7 +1364,7 @@ async function entryDevCommand(options) {
1830
1364
  const shutdown = () => {
1831
1365
  if (isShuttingDown) return;
1832
1366
  isShuttingDown = true;
1833
- logger$11.log("\n🛑 Shutting down...");
1367
+ logger$10.log("\n🛑 Shutting down...");
1834
1368
  runner.stop();
1835
1369
  process.exit(0);
1836
1370
  };
@@ -1862,14 +1396,14 @@ var EntryRunner = class {
1862
1396
  });
1863
1397
  let restartTimeout = null;
1864
1398
  this.watcher.on("change", (path) => {
1865
- logger$11.log(`📝 File changed: ${path}`);
1399
+ logger$10.log(`📝 File changed: ${path}`);
1866
1400
  if (restartTimeout) clearTimeout(restartTimeout);
1867
1401
  restartTimeout = setTimeout(async () => {
1868
- logger$11.log("🔄 Restarting...");
1402
+ logger$10.log("🔄 Restarting...");
1869
1403
  await this.restart();
1870
1404
  }, 300);
1871
1405
  });
1872
- logger$11.log(`👀 Watching for changes in: ${watchDir}`);
1406
+ logger$10.log(`👀 Watching for changes in: ${watchDir}`);
1873
1407
  }
1874
1408
  }
1875
1409
  async runProcess() {
@@ -1884,17 +1418,17 @@ var EntryRunner = class {
1884
1418
  });
1885
1419
  this.isRunning = true;
1886
1420
  this.childProcess.on("error", (error) => {
1887
- logger$11.error("❌ Process error:", error);
1421
+ logger$10.error("❌ Process error:", error);
1888
1422
  });
1889
1423
  this.childProcess.on("exit", (code) => {
1890
- if (code !== null && code !== 0 && code !== 143) logger$11.error(`❌ Process exited with code ${code}`);
1424
+ if (code !== null && code !== 0 && code !== 143) logger$10.error(`❌ Process exited with code ${code}`);
1891
1425
  this.isRunning = false;
1892
1426
  });
1893
1427
  await new Promise((resolve$1) => setTimeout(resolve$1, 500));
1894
1428
  if (this.isRunning) {
1895
- logger$11.log("");
1896
- logger$11.log(` \x1b[32m✓ Ready\x1b[0m at \x1b[36mhttp://localhost:${this.port}\x1b[0m`);
1897
- logger$11.log("");
1429
+ logger$10.log("");
1430
+ logger$10.log(` \x1b[32m✓ Ready\x1b[0m at \x1b[36mhttp://localhost:${this.port}\x1b[0m`);
1431
+ logger$10.log("");
1898
1432
  }
1899
1433
  }
1900
1434
  async restart() {
@@ -2008,11 +1542,11 @@ var DevServer = class {
2008
1542
  this.actualPort = this.requestedPort;
2009
1543
  } else {
2010
1544
  this.actualPort = await findAvailablePort(this.requestedPort);
2011
- if (this.actualPort !== this.requestedPort) logger$11.log(`ℹ️ Port ${this.requestedPort} was in use, using port ${this.actualPort} instead`);
1545
+ if (this.actualPort !== this.requestedPort) logger$10.log(`ℹ️ Port ${this.requestedPort} was in use, using port ${this.actualPort} instead`);
2012
1546
  }
2013
1547
  const serverEntryPath = join(this.appRoot, ".gkm", this.provider, "server.ts");
2014
1548
  await this.createServerEntry();
2015
- logger$11.log(`\n⏳ Starting server...`);
1549
+ logger$10.log(`\n⏳ Starting server...`);
2016
1550
  this.serverProcess = spawn("npx", [
2017
1551
  "tsx",
2018
1552
  serverEntryPath,
@@ -2028,10 +1562,10 @@ var DevServer = class {
2028
1562
  });
2029
1563
  this.isRunning = true;
2030
1564
  this.serverProcess.on("error", (error) => {
2031
- logger$11.error("❌ Server error:", error);
1565
+ logger$10.error("❌ Server error:", error);
2032
1566
  });
2033
1567
  this.serverProcess.on("exit", (code, signal) => {
2034
- if (code !== null && code !== 0 && signal !== "SIGTERM") logger$11.error(`❌ Server exited with code ${code}`);
1568
+ if (code !== null && code !== 0 && signal !== "SIGTERM") logger$10.error(`❌ Server exited with code ${code}`);
2035
1569
  this.isRunning = false;
2036
1570
  });
2037
1571
  await new Promise((resolve$1) => setTimeout(resolve$1, 1e3));
@@ -2044,13 +1578,13 @@ var DevServer = class {
2044
1578
  const maxLen = Math.max(...lines.map((l) => l.length));
2045
1579
  const pad = (s) => s.padEnd(maxLen);
2046
1580
  const border = "─".repeat(maxLen + 2);
2047
- logger$11.log("");
2048
- logger$11.log(` \x1b[32m✓ Ready\x1b[0m in ${((Date.now() - this.startTime) / 1e3).toFixed(1)}s`);
2049
- logger$11.log("");
2050
- logger$11.log(` ┌${border}┐`);
2051
- for (const line of lines) logger$11.log(` │ ${pad(line)} │`);
2052
- logger$11.log(` └${border}┘`);
2053
- logger$11.log("");
1581
+ logger$10.log("");
1582
+ logger$10.log(` \x1b[32m✓ Ready\x1b[0m in ${((Date.now() - this.startTime) / 1e3).toFixed(1)}s`);
1583
+ logger$10.log("");
1584
+ logger$10.log(` ┌${border}┐`);
1585
+ for (const line of lines) logger$10.log(` │ ${pad(line)} │`);
1586
+ logger$10.log(` └${border}┘`);
1587
+ logger$10.log("");
2054
1588
  }
2055
1589
  }
2056
1590
  async stop() {
@@ -2100,7 +1634,7 @@ var DevServer = class {
2100
1634
 
2101
1635
  //#endregion
2102
1636
  //#region src/build/manifests.ts
2103
- const logger$10 = console;
1637
+ const logger$9 = console;
2104
1638
  function isPartitioned(field) {
2105
1639
  return !Array.isArray(field);
2106
1640
  }
@@ -2161,8 +1695,8 @@ export type RoutePath = Route['path'];
2161
1695
  `;
2162
1696
  const manifestPath = join(manifestDir, "aws.ts");
2163
1697
  await writeFile(manifestPath, content);
2164
- logger$10.log(`Generated AWS manifest with ${countItems(awsRoutes)} routes, ${countItems(functions)} functions, ${countItems(crons)} crons, ${countItems(subscribers)} subscribers`);
2165
- logger$10.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);
1698
+ logger$9.log(`Generated AWS manifest with ${countItems(awsRoutes)} routes, ${countItems(functions)} functions, ${countItems(crons)} crons, ${countItems(subscribers)} subscribers`);
1699
+ logger$9.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);
2166
1700
  }
2167
1701
  async function generateServerManifest(outputDir, appInfo, routes, subscribers) {
2168
1702
  const manifestDir = join(outputDir, "manifest");
@@ -2188,8 +1722,8 @@ export type RoutePath = Route['path'];
2188
1722
  `;
2189
1723
  const manifestPath = join(manifestDir, "server.ts");
2190
1724
  await writeFile(manifestPath, content);
2191
- logger$10.log(`Generated server manifest with ${countItems(serverRoutes)} routes, ${countItems(serverSubscribers)} subscribers`);
2192
- logger$10.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);
1725
+ logger$9.log(`Generated server manifest with ${countItems(serverRoutes)} routes, ${countItems(serverSubscribers)} subscribers`);
1726
+ logger$9.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);
2193
1727
  }
2194
1728
  /**
2195
1729
  * Filter out 'ALL' method routes from a manifest field (flat or partitioned).
@@ -2255,7 +1789,7 @@ function groupInfosByPartition(infos, constructs) {
2255
1789
 
2256
1790
  //#endregion
2257
1791
  //#region src/build/index.ts
2258
- const logger$9 = console;
1792
+ const logger$8 = console;
2259
1793
  async function buildCommand(options) {
2260
1794
  const loadedConfig = await loadWorkspaceConfig();
2261
1795
  if (loadedConfig.type === "workspace") {
@@ -2263,30 +1797,30 @@ async function buildCommand(options) {
2263
1797
  const workspaceRoot = resolve(loadedConfig.workspace.root);
2264
1798
  const isAtWorkspaceRoot = cwd === workspaceRoot;
2265
1799
  if (isAtWorkspaceRoot) {
2266
- logger$9.log("📦 Detected workspace configuration");
1800
+ logger$8.log("📦 Detected workspace configuration");
2267
1801
  return workspaceBuildCommand(loadedConfig.workspace, options);
2268
1802
  }
2269
1803
  }
2270
- const config$1 = loadedConfig.type === "workspace" ? (await loadAppConfig()).gkmConfig : await loadConfig();
2271
- const resolved = resolveProviders(config$1, options);
2272
- const productionConfigFromGkm = getProductionConfigFromGkm(config$1);
1804
+ const config = loadedConfig.type === "workspace" ? (await loadAppConfig()).gkmConfig : await loadConfig();
1805
+ const resolved = resolveProviders(config, options);
1806
+ const productionConfigFromGkm = getProductionConfigFromGkm(config);
2273
1807
  const production = normalizeProductionConfig(options.production ?? false, productionConfigFromGkm);
2274
- if (production) logger$9.log(`🏭 Building for PRODUCTION`);
2275
- logger$9.log(`Building with providers: ${resolved.providers.join(", ")}`);
2276
- logger$9.log(`Loading routes from: ${formatRoutes(config$1.routes)}`);
2277
- if (config$1.functions) logger$9.log(`Loading functions from: ${formatRoutes(config$1.functions)}`);
2278
- if (config$1.crons) logger$9.log(`Loading crons from: ${formatRoutes(config$1.crons)}`);
2279
- if (config$1.subscribers) logger$9.log(`Loading subscribers from: ${formatRoutes(config$1.subscribers)}`);
2280
- logger$9.log(`Using envParser: ${config$1.envParser}`);
2281
- const { path: envParserPath, importPattern: envParserImportPattern } = parseModuleConfig(config$1.envParser, "envParser");
2282
- const { path: loggerPath, importPattern: loggerImportPattern } = parseModuleConfig(config$1.logger, "logger");
2283
- const telescope = production ? void 0 : normalizeTelescopeConfig(config$1.telescope);
2284
- if (telescope) logger$9.log(`🔭 Telescope enabled at ${telescope.path}`);
2285
- const studio = production ? void 0 : normalizeStudioConfig(config$1.studio);
2286
- if (studio) logger$9.log(`🗄️ Studio enabled at ${studio.path}`);
2287
- const hooks = normalizeHooksConfig(config$1.hooks);
2288
- if (hooks) logger$9.log(`🪝 Server hooks enabled`);
2289
- const services = config$1.docker?.compose?.services;
1808
+ if (production) logger$8.log(`🏭 Building for PRODUCTION`);
1809
+ logger$8.log(`Building with providers: ${resolved.providers.join(", ")}`);
1810
+ logger$8.log(`Loading routes from: ${formatRoutes(config.routes)}`);
1811
+ if (config.functions) logger$8.log(`Loading functions from: ${formatRoutes(config.functions)}`);
1812
+ if (config.crons) logger$8.log(`Loading crons from: ${formatRoutes(config.crons)}`);
1813
+ if (config.subscribers) logger$8.log(`Loading subscribers from: ${formatRoutes(config.subscribers)}`);
1814
+ logger$8.log(`Using envParser: ${config.envParser}`);
1815
+ const { path: envParserPath, importPattern: envParserImportPattern } = parseModuleConfig(config.envParser, "envParser");
1816
+ const { path: loggerPath, importPattern: loggerImportPattern } = parseModuleConfig(config.logger, "logger");
1817
+ const telescope = production ? void 0 : normalizeTelescopeConfig(config.telescope);
1818
+ if (telescope) logger$8.log(`🔭 Telescope enabled at ${telescope.path}`);
1819
+ const studio = production ? void 0 : normalizeStudioConfig(config.studio);
1820
+ if (studio) logger$8.log(`🗄️ Studio enabled at ${studio.path}`);
1821
+ const hooks = normalizeHooksConfig(config.hooks);
1822
+ if (hooks) logger$8.log(`🪝 Server hooks enabled`);
1823
+ const services = config.docker?.compose?.services;
2290
1824
  const dockerServices = services ? Array.isArray(services) ? {
2291
1825
  postgres: services.includes("postgres"),
2292
1826
  redis: services.includes("redis"),
@@ -2313,17 +1847,17 @@ async function buildCommand(options) {
2313
1847
  const cronGenerator = new CronGenerator();
2314
1848
  const subscriberGenerator = new SubscriberGenerator();
2315
1849
  const [allEndpoints, allFunctions, allCrons, allSubscribers] = await Promise.all([
2316
- endpointGenerator.load(config$1.routes),
2317
- config$1.functions ? functionGenerator.load(config$1.functions) : [],
2318
- config$1.crons ? cronGenerator.load(config$1.crons) : [],
2319
- config$1.subscribers ? subscriberGenerator.load(config$1.subscribers) : []
1850
+ endpointGenerator.load(config.routes),
1851
+ config.functions ? functionGenerator.load(config.functions) : [],
1852
+ config.crons ? cronGenerator.load(config.crons) : [],
1853
+ config.subscribers ? subscriberGenerator.load(config.subscribers) : []
2320
1854
  ]);
2321
- logger$9.log(`Found ${allEndpoints.length} endpoints`);
2322
- logger$9.log(`Found ${allFunctions.length} functions`);
2323
- logger$9.log(`Found ${allCrons.length} crons`);
2324
- logger$9.log(`Found ${allSubscribers.length} subscribers`);
1855
+ logger$8.log(`Found ${allEndpoints.length} endpoints`);
1856
+ logger$8.log(`Found ${allFunctions.length} functions`);
1857
+ logger$8.log(`Found ${allCrons.length} crons`);
1858
+ logger$8.log(`Found ${allSubscribers.length} subscribers`);
2325
1859
  if (allEndpoints.length === 0 && allFunctions.length === 0 && allCrons.length === 0 && allSubscribers.length === 0) {
2326
- logger$9.log("No endpoints, functions, crons, or subscribers found to process");
1860
+ logger$8.log("No endpoints, functions, crons, or subscribers found to process");
2327
1861
  return {};
2328
1862
  }
2329
1863
  const rootOutputDir = join(process.cwd(), ".gkm");
@@ -2333,13 +1867,13 @@ async function buildCommand(options) {
2333
1867
  const providerResult = await buildForProvider(provider, buildContext, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, allEndpoints, allFunctions, allCrons, allSubscribers, resolved.enableOpenApi, options.skipBundle ?? false, options.stage);
2334
1868
  if (providerResult.masterKey) result = providerResult;
2335
1869
  }
2336
- await generateOpenApi(config$1, { bustCache: true });
1870
+ await generateOpenApi(config, { bustCache: true });
2337
1871
  return result;
2338
1872
  }
2339
1873
  async function buildForProvider(provider, context, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, endpoints, functions, crons, subscribers, enableOpenApi, skipBundle, stage) {
2340
1874
  const outputDir = join(process.cwd(), ".gkm", provider);
2341
1875
  await mkdir(outputDir, { recursive: true });
2342
- logger$9.log(`\nGenerating handlers for provider: ${provider}`);
1876
+ logger$8.log(`\nGenerating handlers for provider: ${provider}`);
2343
1877
  const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all([
2344
1878
  endpointGenerator.build(context, endpoints, outputDir, {
2345
1879
  provider,
@@ -2349,7 +1883,7 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2349
1883
  cronGenerator.build(context, crons, outputDir, { provider }),
2350
1884
  subscriberGenerator.build(context, subscribers, outputDir, { provider })
2351
1885
  ]);
2352
- logger$9.log(`Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`);
1886
+ logger$8.log(`Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`);
2353
1887
  const manifestRoutes = assembleManifestField(routes, endpoints);
2354
1888
  const manifestFunctions = assembleManifestField(functionInfos, functions);
2355
1889
  const manifestCrons = assembleManifestField(cronInfos, crons);
@@ -2369,8 +1903,8 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2369
1903
  await generateServerManifest(rootOutputDir, appInfo, serverRouteField, manifestSubscribers);
2370
1904
  let masterKey;
2371
1905
  if (context.production?.bundle && !skipBundle) {
2372
- logger$9.log(`\n📦 Bundling production server...`);
2373
- const { bundleServer } = await import("./bundler-c6QvGUBM.mjs");
1906
+ logger$8.log(`\n📦 Bundling production server...`);
1907
+ const { bundleServer } = await import("./bundler-DkA4qzUD.mjs");
2374
1908
  const allConstructs = [
2375
1909
  ...endpoints.map((e) => e.construct),
2376
1910
  ...functions.map((f) => f.construct),
@@ -2389,10 +1923,10 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2389
1923
  dockerServices
2390
1924
  });
2391
1925
  masterKey = bundleResult.masterKey;
2392
- logger$9.log(`✅ Bundle complete: .gkm/server/dist/server.mjs`);
1926
+ logger$8.log(`✅ Bundle complete: .gkm/server/dist/server.mjs`);
2393
1927
  if (masterKey) {
2394
- logger$9.log(`\n🔐 Secrets encrypted for deployment`);
2395
- logger$9.log(` Deploy with: GKM_MASTER_KEY=${masterKey}`);
1928
+ logger$8.log(`\n🔐 Secrets encrypted for deployment`);
1929
+ logger$8.log(` Deploy with: GKM_MASTER_KEY=${masterKey}`);
2396
1930
  }
2397
1931
  }
2398
1932
  return { masterKey };
@@ -2429,17 +1963,17 @@ async function workspaceBuildCommand(workspace, options) {
2429
1963
  const apps = Object.entries(workspace.apps);
2430
1964
  const backendApps = apps.filter(([, app]) => app.type === "backend");
2431
1965
  const frontendApps = apps.filter(([, app]) => app.type === "web");
2432
- logger$9.log(`\n🏗️ Building workspace: ${workspace.name}`);
2433
- logger$9.log(` Backend apps: ${backendApps.map(([name$1]) => name$1).join(", ") || "none"}`);
2434
- logger$9.log(` Frontend apps: ${frontendApps.map(([name$1]) => name$1).join(", ") || "none"}`);
2435
- if (options.production) logger$9.log(` 🏭 Production mode enabled`);
1966
+ logger$8.log(`\n🏗️ Building workspace: ${workspace.name}`);
1967
+ logger$8.log(` Backend apps: ${backendApps.map(([name$1]) => name$1).join(", ") || "none"}`);
1968
+ logger$8.log(` Frontend apps: ${frontendApps.map(([name$1]) => name$1).join(", ") || "none"}`);
1969
+ if (options.production) logger$8.log(` 🏭 Production mode enabled`);
2436
1970
  const buildOrder = getAppBuildOrder(workspace);
2437
- logger$9.log(` Build order: ${buildOrder.join(" → ")}`);
1971
+ logger$8.log(` Build order: ${buildOrder.join(" → ")}`);
2438
1972
  const pm = detectPackageManager$2();
2439
- logger$9.log(`\n📦 Using ${pm} with Turbo for parallel builds...\n`);
1973
+ logger$8.log(`\n📦 Using ${pm} with Turbo for parallel builds...\n`);
2440
1974
  try {
2441
1975
  const turboCommand = getTurboCommand(pm);
2442
- logger$9.log(`Running: ${turboCommand}`);
1976
+ logger$8.log(`Running: ${turboCommand}`);
2443
1977
  await new Promise((resolve$1, reject) => {
2444
1978
  const child = spawn(turboCommand, {
2445
1979
  shell: true,
@@ -2467,16 +2001,16 @@ async function workspaceBuildCommand(workspace, options) {
2467
2001
  outputPath
2468
2002
  });
2469
2003
  }
2470
- logger$9.log(`\n✅ Workspace build complete!`);
2004
+ logger$8.log(`\n✅ Workspace build complete!`);
2471
2005
  await openapiCommand({ cwd: workspace.root });
2472
- logger$9.log(`\n📋 Build Summary:`);
2006
+ logger$8.log(`\n📋 Build Summary:`);
2473
2007
  for (const result of results) {
2474
2008
  const icon = result.type === "backend" ? "⚙️" : result.type === "mobile" ? "📱" : "🌐";
2475
- logger$9.log(` ${icon} ${result.appName}: ${result.outputPath || "built"}`);
2009
+ logger$8.log(` ${icon} ${result.appName}: ${result.outputPath || "built"}`);
2476
2010
  }
2477
2011
  } catch (error) {
2478
2012
  const errorMessage = error instanceof Error ? error.message : "Build failed";
2479
- logger$9.log(`\n❌ Build failed: ${errorMessage}`);
2013
+ logger$8.log(`\n❌ Build failed: ${errorMessage}`);
2480
2014
  for (const [appName, app] of apps) results.push({
2481
2015
  appName,
2482
2016
  type: app.type,
@@ -2698,17 +2232,17 @@ function isDnsProvider(value) {
2698
2232
  * - Custom: Use provided DnsProvider implementation
2699
2233
  */
2700
2234
  async function createDnsProvider(options) {
2701
- const { config: config$1 } = options;
2702
- if (config$1.provider === "manual") return null;
2703
- if (isDnsProvider(config$1.provider)) return config$1.provider;
2704
- const provider = config$1.provider;
2235
+ const { config } = options;
2236
+ if (config.provider === "manual") return null;
2237
+ if (isDnsProvider(config.provider)) return config.provider;
2238
+ const provider = config.provider;
2705
2239
  if (provider === "hostinger") {
2706
- const { HostingerProvider } = await import("./HostingerProvider-ANWchdiK.mjs");
2240
+ const { HostingerProvider } = await import("./HostingerProvider-B2ZYz7Yc.mjs");
2707
2241
  return new HostingerProvider();
2708
2242
  }
2709
2243
  if (provider === "route53") {
2710
- const { Route53Provider } = await import("./Route53Provider-QoPgcXxn.mjs");
2711
- const route53Config = config$1;
2244
+ const { Route53Provider } = await import("./Route53Provider-tlgBzrRQ.mjs");
2245
+ const route53Config = config;
2712
2246
  return new Route53Provider({
2713
2247
  region: route53Config.region,
2714
2248
  profile: route53Config.profile,
@@ -2716,27 +2250,27 @@ async function createDnsProvider(options) {
2716
2250
  });
2717
2251
  }
2718
2252
  if (provider === "cloudflare") throw new Error("Cloudflare DNS provider not yet implemented");
2719
- throw new Error(`Unknown DNS provider: ${JSON.stringify(config$1)}`);
2253
+ throw new Error(`Unknown DNS provider: ${JSON.stringify(config)}`);
2720
2254
  }
2721
2255
 
2722
2256
  //#endregion
2723
2257
  //#region src/deploy/dns/index.ts
2724
- const logger$8 = console;
2258
+ const logger$7 = console;
2725
2259
  /**
2726
2260
  * Check if DNS config is legacy format (single domain with `domain` property)
2727
2261
  */
2728
- function isLegacyDnsConfig(config$1) {
2729
- return typeof config$1 === "object" && config$1 !== null && "provider" in config$1 && "domain" in config$1;
2262
+ function isLegacyDnsConfig(config) {
2263
+ return typeof config === "object" && config !== null && "provider" in config && "domain" in config;
2730
2264
  }
2731
2265
  /**
2732
2266
  * Normalize DNS config to new multi-domain format
2733
2267
  */
2734
- function normalizeDnsConfig(config$1) {
2735
- if (isLegacyDnsConfig(config$1)) {
2736
- const { domain,...providerConfig } = config$1;
2268
+ function normalizeDnsConfig(config) {
2269
+ if (isLegacyDnsConfig(config)) {
2270
+ const { domain,...providerConfig } = config;
2737
2271
  return { [domain]: providerConfig };
2738
2272
  }
2739
- return config$1;
2273
+ return config;
2740
2274
  }
2741
2275
  /**
2742
2276
  * Find the root domain for a hostname from available DNS configs
@@ -2758,7 +2292,7 @@ function groupHostnamesByDomain(appHostnames, dnsConfig) {
2758
2292
  for (const [appName, hostname] of appHostnames) {
2759
2293
  const rootDomain = findRootDomain(hostname, dnsConfig);
2760
2294
  if (!rootDomain) {
2761
- logger$8.log(` ⚠ No DNS config found for hostname: ${hostname}`);
2295
+ logger$7.log(` ⚠ No DNS config found for hostname: ${hostname}`);
2762
2296
  continue;
2763
2297
  }
2764
2298
  if (!grouped.has(rootDomain)) grouped.set(rootDomain, /* @__PURE__ */ new Map());
@@ -2810,10 +2344,10 @@ function generateRequiredRecords(appHostnames, rootDomain, serverIp) {
2810
2344
  * Print DNS records table
2811
2345
  */
2812
2346
  function printDnsRecordsTable(records, rootDomain) {
2813
- logger$8.log(`\n 📋 DNS Records for ${rootDomain}:`);
2814
- logger$8.log(" ┌─────────────────────────────────────┬──────┬─────────────────┬────────┐");
2815
- logger$8.log(" │ Subdomain │ Type │ Value │ Status │");
2816
- logger$8.log(" ├─────────────────────────────────────┼──────┼─────────────────┼────────┤");
2347
+ logger$7.log(`\n 📋 DNS Records for ${rootDomain}:`);
2348
+ logger$7.log(" ┌─────────────────────────────────────┬──────┬─────────────────┬────────┐");
2349
+ logger$7.log(" │ Subdomain │ Type │ Value │ Status │");
2350
+ logger$7.log(" ├─────────────────────────────────────┼──────┼─────────────────┼────────┤");
2817
2351
  for (const record of records) {
2818
2352
  const subdomain = record.subdomain.padEnd(35);
2819
2353
  const type$1 = record.type.padEnd(4);
@@ -2823,18 +2357,18 @@ function printDnsRecordsTable(records, rootDomain) {
2823
2357
  else if (record.created) status = "✓ new";
2824
2358
  else if (record.existed) status = "✓";
2825
2359
  else status = "?";
2826
- logger$8.log(` │ ${subdomain} │ ${type$1} │ ${value} │ ${status.padEnd(6)} │`);
2360
+ logger$7.log(` │ ${subdomain} │ ${type$1} │ ${value} │ ${status.padEnd(6)} │`);
2827
2361
  }
2828
- logger$8.log(" └─────────────────────────────────────┴──────┴─────────────────┴────────┘");
2362
+ logger$7.log(" └─────────────────────────────────────┴──────┴─────────────────┴────────┘");
2829
2363
  }
2830
2364
  /**
2831
2365
  * Print DNS records in a simple format for manual setup
2832
2366
  */
2833
2367
  function printDnsRecordsSimple(records, rootDomain) {
2834
- logger$8.log("\n 📋 Required DNS Records:");
2835
- logger$8.log(` Add these A records to your DNS provider (${rootDomain}):\n`);
2836
- for (const record of records) logger$8.log(` ${record.subdomain} → ${record.value} (A record)`);
2837
- logger$8.log("");
2368
+ logger$7.log("\n 📋 Required DNS Records:");
2369
+ logger$7.log(` Add these A records to your DNS provider (${rootDomain}):\n`);
2370
+ for (const record of records) logger$7.log(` ${record.subdomain} → ${record.value} (A record)`);
2371
+ logger$7.log("");
2838
2372
  }
2839
2373
  /**
2840
2374
  * Create DNS records for a single domain using its configured provider
@@ -2846,7 +2380,7 @@ async function createDnsRecordsForDomain(records, rootDomain, providerConfig) {
2846
2380
  provider = await createDnsProvider({ config: providerConfig });
2847
2381
  } catch (error) {
2848
2382
  const message = error instanceof Error ? error.message : "Unknown error";
2849
- logger$8.log(` ⚠ Failed to create DNS provider for ${rootDomain}: ${message}`);
2383
+ logger$7.log(` ⚠ Failed to create DNS provider for ${rootDomain}: ${message}`);
2850
2384
  return records.map((r) => ({
2851
2385
  ...r,
2852
2386
  error: message
@@ -2900,7 +2434,7 @@ async function createDnsRecordsForDomain(records, rootDomain, providerConfig) {
2900
2434
  }
2901
2435
  } catch (error) {
2902
2436
  const message = error instanceof Error ? error.message : "Unknown error";
2903
- logger$8.log(` ⚠ Failed to create DNS records for ${rootDomain}: ${message}`);
2437
+ logger$7.log(` ⚠ Failed to create DNS records for ${rootDomain}: ${message}`);
2904
2438
  return records.map((r) => ({
2905
2439
  hostname: r.hostname,
2906
2440
  subdomain: r.subdomain,
@@ -2927,20 +2461,20 @@ async function createDnsRecordsForDomain(records, rootDomain, providerConfig) {
2927
2461
  async function orchestrateDns(appHostnames, dnsConfig, dokployEndpoint, state) {
2928
2462
  if (!dnsConfig) return null;
2929
2463
  const normalizedConfig = normalizeDnsConfig(dnsConfig);
2930
- logger$8.log("\n🌐 Setting up DNS records...");
2464
+ logger$7.log("\n🌐 Setting up DNS records...");
2931
2465
  let serverIp;
2932
2466
  try {
2933
2467
  const endpointUrl = new URL(dokployEndpoint);
2934
2468
  serverIp = await resolveHostnameToIp(endpointUrl.hostname);
2935
- logger$8.log(` Server IP: ${serverIp} (from ${endpointUrl.hostname})`);
2469
+ logger$7.log(` Server IP: ${serverIp} (from ${endpointUrl.hostname})`);
2936
2470
  } catch (error) {
2937
2471
  const message = error instanceof Error ? error.message : "Unknown error";
2938
- logger$8.log(` ⚠ Failed to resolve server IP: ${message}`);
2472
+ logger$7.log(` ⚠ Failed to resolve server IP: ${message}`);
2939
2473
  return null;
2940
2474
  }
2941
2475
  const groupedHostnames = groupHostnamesByDomain(appHostnames, normalizedConfig);
2942
2476
  if (groupedHostnames.size === 0) {
2943
- logger$8.log(" No DNS records needed (no hostnames match configured domains)");
2477
+ logger$7.log(" No DNS records needed (no hostnames match configured domains)");
2944
2478
  return {
2945
2479
  records: [],
2946
2480
  success: true,
@@ -2952,22 +2486,22 @@ async function orchestrateDns(appHostnames, dnsConfig, dokployEndpoint, state) {
2952
2486
  for (const [rootDomain, domainHostnames] of groupedHostnames) {
2953
2487
  const providerConfig = normalizedConfig[rootDomain];
2954
2488
  if (!providerConfig) {
2955
- logger$8.log(` ⚠ No provider config for ${rootDomain}`);
2489
+ logger$7.log(` ⚠ No provider config for ${rootDomain}`);
2956
2490
  continue;
2957
2491
  }
2958
2492
  const providerName = typeof providerConfig.provider === "string" ? providerConfig.provider : "custom";
2959
2493
  const requiredRecords = generateRequiredRecords(domainHostnames, rootDomain, serverIp);
2960
2494
  if (requiredRecords.length === 0) continue;
2961
- logger$8.log(` Creating DNS records for ${rootDomain} (${providerName})...`);
2495
+ logger$7.log(` Creating DNS records for ${rootDomain} (${providerName})...`);
2962
2496
  const domainRecords = await createDnsRecordsForDomain(requiredRecords, rootDomain, providerConfig);
2963
2497
  allRecords.push(...domainRecords);
2964
2498
  const created = domainRecords.filter((r) => r.created).length;
2965
2499
  const existed = domainRecords.filter((r) => r.existed).length;
2966
2500
  const failed = domainRecords.filter((r) => r.error).length;
2967
- if (created > 0) logger$8.log(` ✓ Created ${created} DNS record(s) for ${rootDomain}`);
2968
- if (existed > 0) logger$8.log(` ✓ ${existed} record(s) already exist for ${rootDomain}`);
2501
+ if (created > 0) logger$7.log(` ✓ Created ${created} DNS record(s) for ${rootDomain}`);
2502
+ if (existed > 0) logger$7.log(` ✓ ${existed} record(s) already exist for ${rootDomain}`);
2969
2503
  if (failed > 0) {
2970
- logger$8.log(` ⚠ ${failed} record(s) failed for ${rootDomain}`);
2504
+ logger$7.log(` ⚠ ${failed} record(s) failed for ${rootDomain}`);
2971
2505
  hasFailures = true;
2972
2506
  }
2973
2507
  if (state) {
@@ -3004,10 +2538,10 @@ async function orchestrateDns(appHostnames, dnsConfig, dokployEndpoint, state) {
3004
2538
  */
3005
2539
  async function verifyDnsRecords(appHostnames, serverIp, state) {
3006
2540
  const results = [];
3007
- logger$8.log("\n🔍 Verifying DNS records...");
2541
+ logger$7.log("\n🔍 Verifying DNS records...");
3008
2542
  for (const [appName, hostname] of appHostnames) {
3009
2543
  if (isDnsVerified(state, hostname, serverIp)) {
3010
- logger$8.log(` ✓ ${hostname} (previously verified)`);
2544
+ logger$7.log(` ✓ ${hostname} (previously verified)`);
3011
2545
  results.push({
3012
2546
  hostname,
3013
2547
  appName,
@@ -3021,7 +2555,7 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
3021
2555
  const resolvedIp = await resolveHostnameToIp(hostname);
3022
2556
  if (resolvedIp === serverIp) {
3023
2557
  setDnsVerification(state, hostname, serverIp);
3024
- logger$8.log(` ✓ ${hostname} → ${resolvedIp}`);
2558
+ logger$7.log(` ✓ ${hostname} → ${resolvedIp}`);
3025
2559
  results.push({
3026
2560
  hostname,
3027
2561
  appName,
@@ -3030,7 +2564,7 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
3030
2564
  expectedIp: serverIp
3031
2565
  });
3032
2566
  } else {
3033
- logger$8.log(` ⚠ ${hostname} resolves to ${resolvedIp}, expected ${serverIp}`);
2567
+ logger$7.log(` ⚠ ${hostname} resolves to ${resolvedIp}, expected ${serverIp}`);
3034
2568
  results.push({
3035
2569
  hostname,
3036
2570
  appName,
@@ -3041,7 +2575,7 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
3041
2575
  }
3042
2576
  } catch (error) {
3043
2577
  const message = error instanceof Error ? error.message : "Unknown error";
3044
- logger$8.log(` ⚠ ${hostname} DNS not propagated (${message})`);
2578
+ logger$7.log(` ⚠ ${hostname} DNS not propagated (${message})`);
3045
2579
  results.push({
3046
2580
  hostname,
3047
2581
  appName,
@@ -3055,9 +2589,9 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
3055
2589
  const skipped = results.filter((r) => r.skipped).length;
3056
2590
  const pending = results.filter((r) => !r.verified).length;
3057
2591
  if (pending > 0) {
3058
- logger$8.log(`\n ${verified} verified, ${pending} pending propagation`);
3059
- logger$8.log(" DNS changes may take 5-30 minutes to propagate");
3060
- } else if (skipped > 0) logger$8.log(` ${verified} verified (${skipped} from cache)`);
2592
+ logger$7.log(`\n ${verified} verified, ${pending} pending propagation`);
2593
+ logger$7.log(" DNS changes may take 5-30 minutes to propagate");
2594
+ } else if (skipped > 0) logger$7.log(` ${verified} verified (${skipped} from cache)`);
3061
2595
  return results;
3062
2596
  }
3063
2597
 
@@ -3149,11 +2683,11 @@ function getDefaultImage(serviceName) {
3149
2683
  function normalizeServices(services) {
3150
2684
  const result = /* @__PURE__ */ new Map();
3151
2685
  if (Array.isArray(services)) for (const name$1 of services) result.set(name$1, getDefaultImage(name$1));
3152
- else for (const [name$1, config$1] of Object.entries(services)) {
2686
+ else for (const [name$1, config] of Object.entries(services)) {
3153
2687
  const serviceName = name$1;
3154
- if (config$1 === true) result.set(serviceName, getDefaultImage(serviceName));
3155
- else if (config$1 && typeof config$1 === "object") {
3156
- const serviceConfig = config$1;
2688
+ if (config === true) result.set(serviceName, getDefaultImage(serviceName));
2689
+ else if (config && typeof config === "object") {
2690
+ const serviceConfig = config;
3157
2691
  if (serviceConfig.image) result.set(serviceName, serviceConfig.image);
3158
2692
  else {
3159
2693
  const version$1 = serviceConfig.version ?? DEFAULT_SERVICE_VERSIONS[serviceName];
@@ -3586,22 +3120,22 @@ networks:
3586
3120
  /**
3587
3121
  * Get infrastructure service image with version.
3588
3122
  */
3589
- function getInfraServiceImage(serviceName, config$1) {
3123
+ function getInfraServiceImage(serviceName, config) {
3590
3124
  const defaults = {
3591
3125
  postgres: "postgres:18-alpine",
3592
3126
  redis: "redis:7-alpine",
3593
3127
  minio: "minio/minio:latest"
3594
3128
  };
3595
- if (!config$1 || config$1 === true) return defaults[serviceName];
3596
- if (typeof config$1 === "object") {
3597
- if (config$1.image) return config$1.image;
3598
- if (config$1.version) {
3129
+ if (!config || config === true) return defaults[serviceName];
3130
+ if (typeof config === "object") {
3131
+ if (config.image) return config.image;
3132
+ if (config.version) {
3599
3133
  const baseImages = {
3600
3134
  postgres: "postgres",
3601
3135
  redis: "redis",
3602
3136
  minio: "minio/minio"
3603
3137
  };
3604
- return `${baseImages[serviceName]}:${config$1.version}`;
3138
+ return `${baseImages[serviceName]}:${config.version}`;
3605
3139
  }
3606
3140
  }
3607
3141
  return defaults[serviceName];
@@ -4094,8 +3628,8 @@ exec "$@"
4094
3628
  /**
4095
3629
  * Resolve Docker configuration from GkmConfig with defaults
4096
3630
  */
4097
- function resolveDockerConfig$1(config$1) {
4098
- const docker = config$1.docker ?? {};
3631
+ function resolveDockerConfig$1(config) {
3632
+ const docker = config.docker ?? {};
4099
3633
  let defaultImageName = "api";
4100
3634
  try {
4101
3635
  const pkg$1 = __require(`${process.cwd()}/package.json`);
@@ -4528,7 +4062,7 @@ CMD ["nginx", "-g", "daemon off;"]
4528
4062
 
4529
4063
  //#endregion
4530
4064
  //#region src/docker/index.ts
4531
- const logger$7 = console;
4065
+ const logger$6 = console;
4532
4066
  /**
4533
4067
  * Docker command implementation
4534
4068
  * Generates Dockerfile, docker-compose.yml, and related files
@@ -4539,12 +4073,12 @@ const logger$7 = console;
4539
4073
  async function dockerCommand(options) {
4540
4074
  const loadedConfig = await loadWorkspaceConfig();
4541
4075
  if (loadedConfig.type === "workspace") {
4542
- logger$7.log("📦 Detected workspace configuration");
4076
+ logger$6.log("📦 Detected workspace configuration");
4543
4077
  return workspaceDockerCommand(loadedConfig.workspace, options);
4544
4078
  }
4545
- const config$1 = await loadConfig();
4546
- const dockerConfig = resolveDockerConfig$1(config$1);
4547
- const serverConfig = typeof config$1.providers?.server === "object" ? config$1.providers.server : void 0;
4079
+ const config = await loadConfig();
4080
+ const dockerConfig = resolveDockerConfig$1(config);
4081
+ const serverConfig = typeof config.providers?.server === "object" ? config.providers.server : void 0;
4548
4082
  const healthCheckPath = serverConfig?.production?.healthCheck ?? "/health";
4549
4083
  const useSlim = options.slim === true;
4550
4084
  if (useSlim) {
@@ -4560,14 +4094,14 @@ async function dockerCommand(options) {
4560
4094
  let useTurbo = options.turbo ?? false;
4561
4095
  if (inMonorepo && !useSlim) if (hasTurbo) {
4562
4096
  useTurbo = true;
4563
- logger$7.log(" Detected monorepo with turbo.json - using turbo prune");
4097
+ logger$6.log(" Detected monorepo with turbo.json - using turbo prune");
4564
4098
  } 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");
4565
4099
  let turboPackage = options.turboPackage ?? dockerConfig.imageName;
4566
4100
  if (useTurbo && !options.turboPackage) try {
4567
4101
  const pkg$1 = __require(`${process.cwd()}/package.json`);
4568
4102
  if (pkg$1.name) {
4569
4103
  turboPackage = pkg$1.name;
4570
- logger$7.log(` Turbo package: ${turboPackage}`);
4104
+ logger$6.log(` Turbo package: ${turboPackage}`);
4571
4105
  }
4572
4106
  } catch {}
4573
4107
  const templateOptions = {
@@ -4584,7 +4118,7 @@ async function dockerCommand(options) {
4584
4118
  const dockerMode = useSlim ? "slim" : useTurbo ? "turbo" : "multi-stage";
4585
4119
  const dockerfilePath = join(dockerDir, "Dockerfile");
4586
4120
  await writeFile(dockerfilePath, dockerfile);
4587
- logger$7.log(`Generated: .gkm/docker/Dockerfile (${dockerMode}, ${packageManager})`);
4121
+ logger$6.log(`Generated: .gkm/docker/Dockerfile (${dockerMode}, ${packageManager})`);
4588
4122
  const composeOptions = {
4589
4123
  imageName: dockerConfig.imageName,
4590
4124
  registry: options.registry ?? dockerConfig.registry,
@@ -4596,15 +4130,15 @@ async function dockerCommand(options) {
4596
4130
  const dockerCompose = hasServices ? generateDockerCompose(composeOptions) : generateMinimalDockerCompose(composeOptions);
4597
4131
  const composePath = join(dockerDir, "docker-compose.yml");
4598
4132
  await writeFile(composePath, dockerCompose);
4599
- logger$7.log("Generated: .gkm/docker/docker-compose.yml");
4133
+ logger$6.log("Generated: .gkm/docker/docker-compose.yml");
4600
4134
  const dockerignore = generateDockerignore();
4601
4135
  const dockerignorePath = join(process.cwd(), ".dockerignore");
4602
4136
  await writeFile(dockerignorePath, dockerignore);
4603
- logger$7.log("Generated: .dockerignore (project root)");
4137
+ logger$6.log("Generated: .dockerignore (project root)");
4604
4138
  const entrypoint = generateDockerEntrypoint();
4605
4139
  const entrypointPath = join(dockerDir, "docker-entrypoint.sh");
4606
4140
  await writeFile(entrypointPath, entrypoint);
4607
- logger$7.log("Generated: .gkm/docker/docker-entrypoint.sh");
4141
+ logger$6.log("Generated: .gkm/docker/docker-entrypoint.sh");
4608
4142
  const result = {
4609
4143
  dockerfile: dockerfilePath,
4610
4144
  dockerCompose: composePath,
@@ -4623,13 +4157,13 @@ async function dockerCommand(options) {
4623
4157
  function ensureLockfile(cwd) {
4624
4158
  const lockfilePath = findLockfilePath(cwd);
4625
4159
  if (!lockfilePath) {
4626
- logger$7.warn("\n⚠️ No lockfile found. Docker build may fail or use stale dependencies.");
4160
+ logger$6.warn("\n⚠️ No lockfile found. Docker build may fail or use stale dependencies.");
4627
4161
  return null;
4628
4162
  }
4629
4163
  const lockfileName = basename(lockfilePath);
4630
4164
  const localLockfile = join(cwd, lockfileName);
4631
4165
  if (lockfilePath === localLockfile) return null;
4632
- logger$7.log(` Copying ${lockfileName} from monorepo root...`);
4166
+ logger$6.log(` Copying ${lockfileName} from monorepo root...`);
4633
4167
  copyFileSync(lockfilePath, localLockfile);
4634
4168
  return () => {
4635
4169
  try {
@@ -4645,7 +4179,7 @@ async function buildDockerImage(imageName, options) {
4645
4179
  const tag = options.tag ?? "latest";
4646
4180
  const registry = options.registry;
4647
4181
  const fullImageName = registry ? `${registry}/${imageName}:${tag}` : `${imageName}:${tag}`;
4648
- logger$7.log(`\n🐳 Building Docker image: ${fullImageName}`);
4182
+ logger$6.log(`\n🐳 Building Docker image: ${fullImageName}`);
4649
4183
  const cwd = process.cwd();
4650
4184
  const cleanup = ensureLockfile(cwd);
4651
4185
  try {
@@ -4657,7 +4191,7 @@ async function buildDockerImage(imageName, options) {
4657
4191
  DOCKER_BUILDKIT: "1"
4658
4192
  }
4659
4193
  });
4660
- logger$7.log(`✅ Docker image built: ${fullImageName}`);
4194
+ logger$6.log(`✅ Docker image built: ${fullImageName}`);
4661
4195
  } catch (error) {
4662
4196
  throw new Error(`Failed to build Docker image: ${error instanceof Error ? error.message : "Unknown error"}`);
4663
4197
  } finally {
@@ -4672,13 +4206,13 @@ async function pushDockerImage(imageName, options) {
4672
4206
  const registry = options.registry;
4673
4207
  if (!registry) throw new Error("Registry is required to push Docker image. Use --registry or configure docker.registry in gkm.config.ts");
4674
4208
  const fullImageName = `${registry}/${imageName}:${tag}`;
4675
- logger$7.log(`\n🚀 Pushing Docker image: ${fullImageName}`);
4209
+ logger$6.log(`\n🚀 Pushing Docker image: ${fullImageName}`);
4676
4210
  try {
4677
4211
  execSync(`docker push ${fullImageName}`, {
4678
4212
  cwd: process.cwd(),
4679
4213
  stdio: "inherit"
4680
4214
  });
4681
- logger$7.log(`✅ Docker image pushed: ${fullImageName}`);
4215
+ logger$6.log(`✅ Docker image pushed: ${fullImageName}`);
4682
4216
  } catch (error) {
4683
4217
  throw new Error(`Failed to push Docker image: ${error instanceof Error ? error.message : "Unknown error"}`);
4684
4218
  }
@@ -4704,14 +4238,14 @@ function getAppPackageName(appPath) {
4704
4238
  async function workspaceDockerCommand(workspace, options) {
4705
4239
  const results = [];
4706
4240
  const apps = Object.entries(workspace.apps);
4707
- logger$7.log(`\n🐳 Generating Dockerfiles for workspace: ${workspace.name}`);
4241
+ logger$6.log(`\n🐳 Generating Dockerfiles for workspace: ${workspace.name}`);
4708
4242
  const dockerDir = join(workspace.root, ".gkm", "docker");
4709
4243
  await mkdir(dockerDir, { recursive: true });
4710
4244
  const packageManager = detectPackageManager$1(workspace.root);
4711
- logger$7.log(` Package manager: ${packageManager}`);
4245
+ logger$6.log(` Package manager: ${packageManager}`);
4712
4246
  for (const [appName, app] of apps) {
4713
4247
  if (app.type === "mobile") {
4714
- logger$7.log(`\n 📱 Skipping Docker for ${appName} (mobile app — deploy via framework toolchain)`);
4248
+ logger$6.log(`\n 📱 Skipping Docker for ${appName} (mobile app — deploy via framework toolchain)`);
4715
4249
  continue;
4716
4250
  }
4717
4251
  const appPath = app.path;
@@ -4720,7 +4254,7 @@ async function workspaceDockerCommand(workspace, options) {
4720
4254
  const imageName = appName;
4721
4255
  const hasEntry = !!app.entry;
4722
4256
  const buildType = hasEntry ? "entry" : app.type;
4723
- logger$7.log(`\n 📄 Generating Dockerfile for ${appName} (${buildType})`);
4257
+ logger$6.log(`\n 📄 Generating Dockerfile for ${appName} (${buildType})`);
4724
4258
  let dockerfile;
4725
4259
  if (app.type === "web") {
4726
4260
  const publicUrlArgs = getPublicUrlArgNames(app);
@@ -4764,7 +4298,7 @@ async function workspaceDockerCommand(workspace, options) {
4764
4298
  });
4765
4299
  const dockerfilePath = join(dockerDir, `Dockerfile.${appName}`);
4766
4300
  await writeFile(dockerfilePath, dockerfile);
4767
- logger$7.log(` Generated: .gkm/docker/Dockerfile.${appName}`);
4301
+ logger$6.log(` Generated: .gkm/docker/Dockerfile.${appName}`);
4768
4302
  results.push({
4769
4303
  appName,
4770
4304
  type: app.type,
@@ -4775,19 +4309,19 @@ async function workspaceDockerCommand(workspace, options) {
4775
4309
  const dockerignore = generateDockerignore();
4776
4310
  const dockerignorePath = join(workspace.root, ".dockerignore");
4777
4311
  await writeFile(dockerignorePath, dockerignore);
4778
- logger$7.log(`\n Generated: .dockerignore (workspace root)`);
4312
+ logger$6.log(`\n Generated: .dockerignore (workspace root)`);
4779
4313
  const dockerCompose = generateWorkspaceCompose(workspace, { registry: options.registry });
4780
4314
  const composePath = join(dockerDir, "docker-compose.yml");
4781
4315
  await writeFile(composePath, dockerCompose);
4782
- logger$7.log(` Generated: .gkm/docker/docker-compose.yml`);
4783
- logger$7.log(`\n✅ Generated ${results.length} Dockerfile(s) + docker-compose.yml`);
4784
- logger$7.log("\n📋 Build commands:");
4316
+ logger$6.log(` Generated: .gkm/docker/docker-compose.yml`);
4317
+ logger$6.log(`\n✅ Generated ${results.length} Dockerfile(s) + docker-compose.yml`);
4318
+ logger$6.log("\n📋 Build commands:");
4785
4319
  for (const result of results) {
4786
4320
  const icon = result.type === "backend" ? "⚙️" : result.type === "mobile" ? "📱" : "🌐";
4787
- logger$7.log(` ${icon} docker build -f .gkm/docker/Dockerfile.${result.appName} -t ${result.imageName} .`);
4321
+ logger$6.log(` ${icon} docker build -f .gkm/docker/Dockerfile.${result.appName} -t ${result.imageName} .`);
4788
4322
  }
4789
- logger$7.log("\n📋 Run all services:");
4790
- logger$7.log(" docker compose -f .gkm/docker/docker-compose.yml up --build");
4323
+ logger$6.log("\n📋 Run all services:");
4324
+ logger$6.log(" docker compose -f .gkm/docker/docker-compose.yml up --build");
4791
4325
  return {
4792
4326
  apps: results,
4793
4327
  dockerCompose: composePath,
@@ -4827,7 +4361,7 @@ function getAppNameFromPackageJson() {
4827
4361
  } catch {}
4828
4362
  return void 0;
4829
4363
  }
4830
- const logger$6 = console;
4364
+ const logger$5 = console;
4831
4365
  /**
4832
4366
  * Get the full image reference
4833
4367
  */
@@ -4842,18 +4376,18 @@ function getImageRef(registry, imageName, tag) {
4842
4376
  * @param buildArgs - Build arguments to pass to docker build
4843
4377
  */
4844
4378
  async function buildImage(imageRef, appName, buildArgs) {
4845
- logger$6.log(`\n🔨 Building Docker image: ${imageRef}`);
4379
+ logger$5.log(`\n🔨 Building Docker image: ${imageRef}`);
4846
4380
  const cwd = process.cwd();
4847
4381
  const lockfilePath = findLockfilePath(cwd);
4848
4382
  const lockfileDir = lockfilePath ? dirname(lockfilePath) : cwd;
4849
4383
  const inMonorepo = lockfileDir !== cwd;
4850
- if (appName || inMonorepo) logger$6.log(" Generating Dockerfile for monorepo (turbo prune)...");
4851
- else logger$6.log(" Generating Dockerfile...");
4384
+ if (appName || inMonorepo) logger$5.log(" Generating Dockerfile for monorepo (turbo prune)...");
4385
+ else logger$5.log(" Generating Dockerfile...");
4852
4386
  await dockerCommand({});
4853
4387
  const dockerfileSuffix = appName ? `.${appName}` : "";
4854
4388
  const dockerfilePath = `.gkm/docker/Dockerfile${dockerfileSuffix}`;
4855
4389
  const buildCwd = lockfilePath && (inMonorepo || appName) ? lockfileDir : cwd;
4856
- if (buildCwd !== cwd) logger$6.log(` Building from workspace root: ${buildCwd}`);
4390
+ if (buildCwd !== cwd) logger$5.log(` Building from workspace root: ${buildCwd}`);
4857
4391
  const buildArgsString = buildArgs && buildArgs.length > 0 ? buildArgs.map((arg) => `--build-arg "${arg}"`).join(" ") : "";
4858
4392
  try {
4859
4393
  const cmd = [
@@ -4872,7 +4406,7 @@ async function buildImage(imageRef, appName, buildArgs) {
4872
4406
  DOCKER_BUILDKIT: "1"
4873
4407
  }
4874
4408
  });
4875
- logger$6.log(`✅ Image built: ${imageRef}`);
4409
+ logger$5.log(`✅ Image built: ${imageRef}`);
4876
4410
  } catch (error) {
4877
4411
  throw new Error(`Failed to build Docker image: ${error instanceof Error ? error.message : "Unknown error"}`);
4878
4412
  }
@@ -4881,13 +4415,13 @@ async function buildImage(imageRef, appName, buildArgs) {
4881
4415
  * Push Docker image to registry
4882
4416
  */
4883
4417
  async function pushImage(imageRef) {
4884
- logger$6.log(`\n☁️ Pushing image: ${imageRef}`);
4418
+ logger$5.log(`\n☁️ Pushing image: ${imageRef}`);
4885
4419
  try {
4886
4420
  execSync(`docker push ${imageRef}`, {
4887
4421
  cwd: process.cwd(),
4888
4422
  stdio: "inherit"
4889
4423
  });
4890
- logger$6.log(`✅ Image pushed: ${imageRef}`);
4424
+ logger$5.log(`✅ Image pushed: ${imageRef}`);
4891
4425
  } catch (error) {
4892
4426
  throw new Error(`Failed to push Docker image: ${error instanceof Error ? error.message : "Unknown error"}`);
4893
4427
  }
@@ -4896,21 +4430,21 @@ async function pushImage(imageRef) {
4896
4430
  * Deploy using Docker (build and optionally push image)
4897
4431
  */
4898
4432
  async function deployDocker(options) {
4899
- const { stage, tag, skipPush, masterKey, config: config$1, buildArgs } = options;
4900
- const imageName = config$1.imageName;
4901
- const imageRef = getImageRef(config$1.registry, imageName, tag);
4902
- await buildImage(imageRef, config$1.appName, buildArgs);
4903
- if (!skipPush) if (!config$1.registry) logger$6.warn("\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts");
4433
+ const { stage, tag, skipPush, masterKey, config, buildArgs } = options;
4434
+ const imageName = config.imageName;
4435
+ const imageRef = getImageRef(config.registry, imageName, tag);
4436
+ await buildImage(imageRef, config.appName, buildArgs);
4437
+ if (!skipPush) if (!config.registry) logger$5.warn("\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts");
4904
4438
  else await pushImage(imageRef);
4905
- logger$6.log("\n✅ Docker deployment ready!");
4906
- logger$6.log(`\n📋 Deployment details:`);
4907
- logger$6.log(` Image: ${imageRef}`);
4908
- logger$6.log(` Stage: ${stage}`);
4439
+ logger$5.log("\n✅ Docker deployment ready!");
4440
+ logger$5.log(`\n📋 Deployment details:`);
4441
+ logger$5.log(` Image: ${imageRef}`);
4442
+ logger$5.log(` Stage: ${stage}`);
4909
4443
  if (masterKey) {
4910
- logger$6.log(`\n🔐 Deploy with this environment variable:`);
4911
- logger$6.log(` GKM_MASTER_KEY=${masterKey}`);
4912
- logger$6.log("\n Example docker run:");
4913
- logger$6.log(` docker run -e GKM_MASTER_KEY=${masterKey} ${imageRef}`);
4444
+ logger$5.log(`\n🔐 Deploy with this environment variable:`);
4445
+ logger$5.log(` GKM_MASTER_KEY=${masterKey}`);
4446
+ logger$5.log("\n Example docker run:");
4447
+ logger$5.log(` docker run -e GKM_MASTER_KEY=${masterKey} ${imageRef}`);
4914
4448
  }
4915
4449
  return {
4916
4450
  imageRef,
@@ -4923,12 +4457,12 @@ async function deployDocker(options) {
4923
4457
  * - projectName: from root package.json, or 'app' (for Dokploy project)
4924
4458
  * - appName: from cwd package.json, or projectName (for Dokploy app within project)
4925
4459
  */
4926
- function resolveDockerConfig(config$1) {
4460
+ function resolveDockerConfig(config) {
4927
4461
  const projectName = getAppNameFromPackageJson() ?? "app";
4928
4462
  const appName = getAppNameFromCwd$1() ?? projectName;
4929
- const imageName = config$1.docker?.imageName ?? appName;
4463
+ const imageName = config.docker?.imageName ?? appName;
4930
4464
  return {
4931
- registry: config$1.docker?.registry,
4465
+ registry: config.docker?.registry,
4932
4466
  imageName,
4933
4467
  projectName,
4934
4468
  appName
@@ -4937,7 +4471,7 @@ function resolveDockerConfig(config$1) {
4937
4471
 
4938
4472
  //#endregion
4939
4473
  //#region src/deploy/dokploy.ts
4940
- const logger$5 = console;
4474
+ const logger$4 = console;
4941
4475
  /**
4942
4476
  * Get the Dokploy API token from stored credentials or environment
4943
4477
  */
@@ -4960,59 +4494,59 @@ async function createApi$1(endpoint) {
4960
4494
  * Deploy to Dokploy
4961
4495
  */
4962
4496
  async function deployDokploy(options) {
4963
- const { stage, imageRef, masterKey, config: config$1 } = options;
4964
- logger$5.log(`\n🎯 Deploying to Dokploy...`);
4965
- logger$5.log(` Endpoint: ${config$1.endpoint}`);
4966
- logger$5.log(` Application: ${config$1.applicationId}`);
4967
- const api = await createApi$1(config$1.endpoint);
4968
- logger$5.log(` Configuring Docker image: ${imageRef}`);
4497
+ const { stage, imageRef, masterKey, config } = options;
4498
+ logger$4.log(`\n🎯 Deploying to Dokploy...`);
4499
+ logger$4.log(` Endpoint: ${config.endpoint}`);
4500
+ logger$4.log(` Application: ${config.applicationId}`);
4501
+ const api = await createApi$1(config.endpoint);
4502
+ logger$4.log(` Configuring Docker image: ${imageRef}`);
4969
4503
  const registryOptions = {};
4970
- if (config$1.registryId) {
4971
- registryOptions.registryId = config$1.registryId;
4972
- logger$5.log(` Using Dokploy registry: ${config$1.registryId}`);
4504
+ if (config.registryId) {
4505
+ registryOptions.registryId = config.registryId;
4506
+ logger$4.log(` Using Dokploy registry: ${config.registryId}`);
4973
4507
  } else {
4974
4508
  const storedRegistryId = await getDokployRegistryId();
4975
4509
  if (storedRegistryId) {
4976
4510
  registryOptions.registryId = storedRegistryId;
4977
- logger$5.log(` Using stored Dokploy registry: ${storedRegistryId}`);
4978
- } else if (config$1.registryCredentials) {
4979
- registryOptions.username = config$1.registryCredentials.username;
4980
- registryOptions.password = config$1.registryCredentials.password;
4981
- registryOptions.registryUrl = config$1.registryCredentials.registryUrl;
4982
- logger$5.log(` Using registry credentials for: ${config$1.registryCredentials.registryUrl}`);
4511
+ logger$4.log(` Using stored Dokploy registry: ${storedRegistryId}`);
4512
+ } else if (config.registryCredentials) {
4513
+ registryOptions.username = config.registryCredentials.username;
4514
+ registryOptions.password = config.registryCredentials.password;
4515
+ registryOptions.registryUrl = config.registryCredentials.registryUrl;
4516
+ logger$4.log(` Using registry credentials for: ${config.registryCredentials.registryUrl}`);
4983
4517
  } else {
4984
4518
  const username = process.env.DOCKER_REGISTRY_USERNAME;
4985
4519
  const password = process.env.DOCKER_REGISTRY_PASSWORD;
4986
- const registryUrl = process.env.DOCKER_REGISTRY_URL || config$1.registry;
4520
+ const registryUrl = process.env.DOCKER_REGISTRY_URL || config.registry;
4987
4521
  if (username && password && registryUrl) {
4988
4522
  registryOptions.username = username;
4989
4523
  registryOptions.password = password;
4990
4524
  registryOptions.registryUrl = registryUrl;
4991
- logger$5.log(` Using registry credentials from environment`);
4525
+ logger$4.log(` Using registry credentials from environment`);
4992
4526
  }
4993
4527
  }
4994
4528
  }
4995
- await api.saveDockerProvider(config$1.applicationId, imageRef, registryOptions);
4996
- logger$5.log(" ✓ Docker provider configured");
4529
+ await api.saveDockerProvider(config.applicationId, imageRef, registryOptions);
4530
+ logger$4.log(" ✓ Docker provider configured");
4997
4531
  const envVars = {};
4998
4532
  if (masterKey) envVars.GKM_MASTER_KEY = masterKey;
4999
4533
  if (Object.keys(envVars).length > 0) {
5000
- logger$5.log(" Updating environment variables...");
4534
+ logger$4.log(" Updating environment variables...");
5001
4535
  const envString = Object.entries(envVars).map(([key, value]) => `${key}=${value}`).join("\n");
5002
- await api.saveApplicationEnv(config$1.applicationId, envString);
5003
- logger$5.log(" ✓ Environment variables updated");
5004
- }
5005
- logger$5.log(" Triggering deployment...");
5006
- await api.deployApplication(config$1.applicationId);
5007
- logger$5.log(" ✓ Deployment triggered");
5008
- logger$5.log("\n✅ Dokploy deployment initiated!");
5009
- logger$5.log(`\n📋 Deployment details:`);
5010
- logger$5.log(` Image: ${imageRef}`);
5011
- logger$5.log(` Stage: ${stage}`);
5012
- logger$5.log(` Application ID: ${config$1.applicationId}`);
5013
- if (masterKey) logger$5.log(`\n🔐 GKM_MASTER_KEY has been set in Dokploy environment`);
5014
- const deploymentUrl = `${config$1.endpoint}/project/${config$1.projectId}`;
5015
- logger$5.log(`\n🔗 View deployment: ${deploymentUrl}`);
4536
+ await api.saveApplicationEnv(config.applicationId, envString);
4537
+ logger$4.log(" ✓ Environment variables updated");
4538
+ }
4539
+ logger$4.log(" Triggering deployment...");
4540
+ await api.deployApplication(config.applicationId);
4541
+ logger$4.log(" ✓ Deployment triggered");
4542
+ logger$4.log("\n✅ Dokploy deployment initiated!");
4543
+ logger$4.log(`\n📋 Deployment details:`);
4544
+ logger$4.log(` Image: ${imageRef}`);
4545
+ logger$4.log(` Stage: ${stage}`);
4546
+ logger$4.log(` Application ID: ${config.applicationId}`);
4547
+ if (masterKey) logger$4.log(`\n🔐 GKM_MASTER_KEY has been set in Dokploy environment`);
4548
+ const deploymentUrl = `${config.endpoint}/project/${config.projectId}`;
4549
+ logger$4.log(`\n🔗 View deployment: ${deploymentUrl}`);
5016
4550
  return {
5017
4551
  imageRef,
5018
4552
  masterKey,
@@ -5129,7 +4663,7 @@ function validateEnvVars(requiredVars, context) {
5129
4663
 
5130
4664
  //#endregion
5131
4665
  //#region src/deploy/init.ts
5132
- const logger$4 = console;
4666
+ const logger$3 = console;
5133
4667
  /**
5134
4668
  * Get the Dokploy API token from stored credentials or environment
5135
4669
  */
@@ -5160,29 +4694,29 @@ async function createApi(endpoint) {
5160
4694
  /**
5161
4695
  * Update gkm.config.ts with Dokploy configuration
5162
4696
  */
5163
- async function updateConfig(config$1, cwd = process.cwd()) {
4697
+ async function updateConfig(config, cwd = process.cwd()) {
5164
4698
  const configPath = join(cwd, "gkm.config.ts");
5165
4699
  if (!existsSync(configPath)) {
5166
- logger$4.warn("\n gkm.config.ts not found. Add this configuration manually:\n");
5167
- logger$4.log(` providers: {`);
5168
- logger$4.log(` dokploy: {`);
5169
- logger$4.log(` endpoint: '${config$1.endpoint}',`);
5170
- logger$4.log(` projectId: '${config$1.projectId}',`);
5171
- logger$4.log(` applicationId: '${config$1.applicationId}',`);
5172
- logger$4.log(` },`);
5173
- logger$4.log(` },`);
4700
+ logger$3.warn("\n gkm.config.ts not found. Add this configuration manually:\n");
4701
+ logger$3.log(` providers: {`);
4702
+ logger$3.log(` dokploy: {`);
4703
+ logger$3.log(` endpoint: '${config.endpoint}',`);
4704
+ logger$3.log(` projectId: '${config.projectId}',`);
4705
+ logger$3.log(` applicationId: '${config.applicationId}',`);
4706
+ logger$3.log(` },`);
4707
+ logger$3.log(` },`);
5174
4708
  return;
5175
4709
  }
5176
4710
  const content = await readFile(configPath, "utf-8");
5177
4711
  if (content.includes("dokploy:") && content.includes("applicationId:")) {
5178
- logger$4.log("\n Dokploy config already exists in gkm.config.ts");
5179
- logger$4.log(" Updating with new values...");
4712
+ logger$3.log("\n Dokploy config already exists in gkm.config.ts");
4713
+ logger$3.log(" Updating with new values...");
5180
4714
  }
5181
- const registryLine = config$1.registryId ? `\n\t\t\tregistryId: '${config$1.registryId}',` : "";
4715
+ const registryLine = config.registryId ? `\n\t\t\tregistryId: '${config.registryId}',` : "";
5182
4716
  const dokployConfigStr = `dokploy: {
5183
- endpoint: '${config$1.endpoint}',
5184
- projectId: '${config$1.projectId}',
5185
- applicationId: '${config$1.applicationId}',${registryLine}
4717
+ endpoint: '${config.endpoint}',
4718
+ projectId: '${config.projectId}',
4719
+ applicationId: '${config.applicationId}',${registryLine}
5186
4720
  }`;
5187
4721
  let newContent;
5188
4722
  if (content.includes("providers:")) if (content.includes("dokploy:")) newContent = content.replace(/dokploy:\s*\{[^}]*\}/s, dokployConfigStr);
@@ -5193,7 +4727,7 @@ async function updateConfig(config$1, cwd = process.cwd()) {
5193
4727
  },
5194
4728
  });`);
5195
4729
  await writeFile(configPath, newContent);
5196
- logger$4.log("\n ✓ Updated gkm.config.ts with Dokploy configuration");
4730
+ logger$3.log("\n ✓ Updated gkm.config.ts with Dokploy configuration");
5197
4731
  }
5198
4732
  /**
5199
4733
  * Initialize Dokploy deployment configuration
@@ -5202,24 +4736,24 @@ async function deployInitCommand(options) {
5202
4736
  const { projectName, appName, projectId: existingProjectId, registryId } = options;
5203
4737
  const endpoint = await getEndpoint(options.endpoint);
5204
4738
  const api = await createApi(endpoint);
5205
- logger$4.log(`\n🚀 Initializing Dokploy deployment...`);
5206
- logger$4.log(` Endpoint: ${endpoint}`);
4739
+ logger$3.log(`\n🚀 Initializing Dokploy deployment...`);
4740
+ logger$3.log(` Endpoint: ${endpoint}`);
5207
4741
  let projectId;
5208
4742
  if (existingProjectId) {
5209
4743
  projectId = existingProjectId;
5210
- logger$4.log(`\n📁 Using existing project: ${projectId}`);
4744
+ logger$3.log(`\n📁 Using existing project: ${projectId}`);
5211
4745
  } else {
5212
- logger$4.log(`\n📁 Looking for project: ${projectName}`);
4746
+ logger$3.log(`\n📁 Looking for project: ${projectName}`);
5213
4747
  const projects = await api.listProjects();
5214
4748
  const existingProject = projects.find((p) => p.name.toLowerCase() === projectName.toLowerCase());
5215
4749
  if (existingProject) {
5216
4750
  projectId = existingProject.projectId;
5217
- logger$4.log(` Found existing project: ${projectId}`);
4751
+ logger$3.log(` Found existing project: ${projectId}`);
5218
4752
  } else {
5219
- logger$4.log(` Creating new project...`);
4753
+ logger$3.log(` Creating new project...`);
5220
4754
  const result = await api.createProject(projectName);
5221
4755
  projectId = result.project.projectId;
5222
- logger$4.log(` ✓ Created project: ${projectId}`);
4756
+ logger$3.log(` ✓ Created project: ${projectId}`);
5223
4757
  }
5224
4758
  }
5225
4759
  const project = await api.getProject(projectId);
@@ -5227,40 +4761,40 @@ async function deployInitCommand(options) {
5227
4761
  const firstEnv = project.environments?.[0];
5228
4762
  if (firstEnv) environmentId = firstEnv.environmentId;
5229
4763
  else {
5230
- logger$4.log(` Creating production environment...`);
4764
+ logger$3.log(` Creating production environment...`);
5231
4765
  const env = await api.createEnvironment(projectId, "production");
5232
4766
  environmentId = env.environmentId;
5233
4767
  }
5234
- logger$4.log(`\n📦 Creating application: ${appName}`);
4768
+ logger$3.log(`\n📦 Creating application: ${appName}`);
5235
4769
  const application = await api.createApplication(appName, projectId, environmentId);
5236
- logger$4.log(` ✓ Created application: ${application.applicationId}`);
4770
+ logger$3.log(` ✓ Created application: ${application.applicationId}`);
5237
4771
  if (registryId) {
5238
- logger$4.log(`\n🔧 Configuring registry: ${registryId}`);
4772
+ logger$3.log(`\n🔧 Configuring registry: ${registryId}`);
5239
4773
  await api.updateApplication(application.applicationId, { registryId });
5240
- logger$4.log(` ✓ Registry configured`);
4774
+ logger$3.log(` ✓ Registry configured`);
5241
4775
  } else try {
5242
4776
  const registries = await api.listRegistries();
5243
4777
  if (registries.length > 0) {
5244
- logger$4.log(`\n📋 Available registries:`);
5245
- for (const reg of registries) logger$4.log(` - ${reg.registryName}: ${reg.registryUrl} (${reg.registryId})`);
5246
- logger$4.log(`\n To use a registry, run with --registry-id <id>`);
4778
+ logger$3.log(`\n📋 Available registries:`);
4779
+ for (const reg of registries) logger$3.log(` - ${reg.registryName}: ${reg.registryUrl} (${reg.registryId})`);
4780
+ logger$3.log(`\n To use a registry, run with --registry-id <id>`);
5247
4781
  }
5248
4782
  } catch {}
5249
- const config$1 = {
4783
+ const config = {
5250
4784
  endpoint,
5251
4785
  projectId,
5252
4786
  applicationId: application.applicationId
5253
4787
  };
5254
- await updateConfig(config$1);
5255
- logger$4.log(`\n✅ Dokploy deployment initialized!`);
5256
- logger$4.log(`\n📋 Configuration:`);
5257
- logger$4.log(` Project ID: ${projectId}`);
5258
- logger$4.log(` Application ID: ${application.applicationId}`);
5259
- logger$4.log(`\n🔗 View in Dokploy: ${endpoint}/project/${projectId}`);
5260
- logger$4.log(`\n📝 Next steps:`);
5261
- logger$4.log(` 1. Initialize secrets: gkm secrets:init --stage production`);
5262
- logger$4.log(` 2. Deploy: gkm deploy --provider dokploy --stage production`);
5263
- return config$1;
4788
+ await updateConfig(config);
4789
+ logger$3.log(`\n✅ Dokploy deployment initialized!`);
4790
+ logger$3.log(`\n📋 Configuration:`);
4791
+ logger$3.log(` Project ID: ${projectId}`);
4792
+ logger$3.log(` Application ID: ${application.applicationId}`);
4793
+ logger$3.log(`\n🔗 View in Dokploy: ${endpoint}/project/${projectId}`);
4794
+ logger$3.log(`\n📝 Next steps:`);
4795
+ logger$3.log(` 1. Initialize secrets: gkm secrets:init --stage production`);
4796
+ logger$3.log(` 2. Deploy: gkm deploy --provider dokploy --stage production`);
4797
+ return config;
5264
4798
  }
5265
4799
  /**
5266
4800
  * List available Dokploy resources
@@ -5270,32 +4804,32 @@ async function deployListCommand(options) {
5270
4804
  const api = await createApi(endpoint);
5271
4805
  const { resource } = options;
5272
4806
  if (resource === "projects") {
5273
- logger$4.log(`\n📁 Projects in ${endpoint}:`);
4807
+ logger$3.log(`\n📁 Projects in ${endpoint}:`);
5274
4808
  const projects = await api.listProjects();
5275
4809
  if (projects.length === 0) {
5276
- logger$4.log(" No projects found");
4810
+ logger$3.log(" No projects found");
5277
4811
  return;
5278
4812
  }
5279
4813
  for (const project of projects) {
5280
- logger$4.log(`\n ${project.name} (${project.projectId})`);
5281
- if (project.description) logger$4.log(` ${project.description}`);
4814
+ logger$3.log(`\n ${project.name} (${project.projectId})`);
4815
+ if (project.description) logger$3.log(` ${project.description}`);
5282
4816
  }
5283
4817
  } else if (resource === "registries") {
5284
- logger$4.log(`\n🐳 Registries in ${endpoint}:`);
4818
+ logger$3.log(`\n🐳 Registries in ${endpoint}:`);
5285
4819
  const registries = await api.listRegistries();
5286
4820
  if (registries.length === 0) {
5287
- logger$4.log(" No registries configured");
5288
- logger$4.log(" Run \"gkm registry:setup\" to configure a registry");
4821
+ logger$3.log(" No registries configured");
4822
+ logger$3.log(" Run \"gkm registry:setup\" to configure a registry");
5289
4823
  return;
5290
4824
  }
5291
4825
  const storedRegistryId = await getDokployRegistryId();
5292
4826
  for (const registry of registries) {
5293
4827
  const isDefault = registry.registryId === storedRegistryId;
5294
4828
  const marker = isDefault ? " (default)" : "";
5295
- logger$4.log(`\n ${registry.registryName}${marker} (${registry.registryId})`);
5296
- logger$4.log(` URL: ${registry.registryUrl}`);
5297
- logger$4.log(` Username: ${registry.username}`);
5298
- if (registry.imagePrefix) logger$4.log(` Prefix: ${registry.imagePrefix}`);
4829
+ logger$3.log(`\n ${registry.registryName}${marker} (${registry.registryId})`);
4830
+ logger$3.log(` URL: ${registry.registryUrl}`);
4831
+ logger$3.log(` Username: ${registry.username}`);
4832
+ if (registry.imagePrefix) logger$3.log(` Prefix: ${registry.imagePrefix}`);
5299
4833
  }
5300
4834
  }
5301
4835
  }
@@ -5316,23 +4850,23 @@ function isStateProvider(value) {
5316
4850
  * - Custom: Use provided StateProvider implementation
5317
4851
  */
5318
4852
  async function createStateProvider(options) {
5319
- const { config: config$1, workspaceRoot, workspaceName } = options;
5320
- if (!config$1) {
5321
- const { LocalStateProvider } = await import("./LocalStateProvider-Dp0KkRcw.mjs");
4853
+ const { config, workspaceRoot, workspaceName } = options;
4854
+ if (!config) {
4855
+ const { LocalStateProvider } = await import("./LocalStateProvider-CP49rjzt.mjs");
5322
4856
  return new LocalStateProvider(workspaceRoot);
5323
4857
  }
5324
- if (isStateProvider(config$1.provider)) return config$1.provider;
5325
- const provider = config$1.provider;
4858
+ if (isStateProvider(config.provider)) return config.provider;
4859
+ const provider = config.provider;
5326
4860
  if (provider === "local") {
5327
- const { LocalStateProvider } = await import("./LocalStateProvider-Dp0KkRcw.mjs");
4861
+ const { LocalStateProvider } = await import("./LocalStateProvider-CP49rjzt.mjs");
5328
4862
  return new LocalStateProvider(workspaceRoot);
5329
4863
  }
5330
4864
  if (provider === "ssm") {
5331
4865
  if (!workspaceName) throw new Error("Workspace name is required for SSM state provider. Set \"name\" in gkm.config.ts.");
5332
- const { LocalStateProvider } = await import("./LocalStateProvider-Dp0KkRcw.mjs");
5333
- const { SSMStateProvider } = await import("./SSMStateProvider-CksOTB8M.mjs");
5334
- const { CachedStateProvider: CachedStateProvider$1 } = await import("./CachedStateProvider-CC0DyO09.mjs");
5335
- const ssmConfig = config$1;
4866
+ const { LocalStateProvider } = await import("./LocalStateProvider-CP49rjzt.mjs");
4867
+ const { SSMStateProvider } = await import("./SSMStateProvider-BlrTiV5m.mjs");
4868
+ const { CachedStateProvider: CachedStateProvider$1 } = await import("./CachedStateProvider-GcGziXh1.mjs");
4869
+ const ssmConfig = config;
5336
4870
  const local = new LocalStateProvider(workspaceRoot);
5337
4871
  const ssm = SSMStateProvider.create({
5338
4872
  workspaceName,
@@ -5341,7 +4875,7 @@ async function createStateProvider(options) {
5341
4875
  });
5342
4876
  return new CachedStateProvider$1(ssm, local);
5343
4877
  }
5344
- throw new Error(`Unknown state provider: ${JSON.stringify(config$1)}`);
4878
+ throw new Error(`Unknown state provider: ${JSON.stringify(config)}`);
5345
4879
  }
5346
4880
 
5347
4881
  //#endregion
@@ -5791,7 +5325,7 @@ async function sniffAllApps(apps, workspacePath, options = {}) {
5791
5325
 
5792
5326
  //#endregion
5793
5327
  //#region src/deploy/index.ts
5794
- const logger$3 = console;
5328
+ const logger$2 = console;
5795
5329
  /**
5796
5330
  * Prompt for input
5797
5331
  */
@@ -5863,7 +5397,7 @@ async function waitForPostgres(host, port, user, password, database, maxRetries
5863
5397
  return;
5864
5398
  } catch {
5865
5399
  if (i < maxRetries - 1) {
5866
- logger$3.log(` Waiting for Postgres... (${i + 1}/${maxRetries})`);
5400
+ logger$2.log(` Waiting for Postgres... (${i + 1}/${maxRetries})`);
5867
5401
  await new Promise((r) => setTimeout(r, retryIntervalMs));
5868
5402
  }
5869
5403
  }
@@ -5898,12 +5432,12 @@ async function waitForPostgres(host, port, user, password, database, maxRetries
5898
5432
  * ```
5899
5433
  */
5900
5434
  async function initializePostgresUsers(api, postgres, serverHostname, users) {
5901
- logger$3.log("\n🔧 Initializing database users...");
5435
+ logger$2.log("\n🔧 Initializing database users...");
5902
5436
  const externalPort = 5432;
5903
- logger$3.log(` Enabling external port ${externalPort}...`);
5437
+ logger$2.log(` Enabling external port ${externalPort}...`);
5904
5438
  await api.savePostgresExternalPort(postgres.postgresId, externalPort);
5905
5439
  await api.deployPostgres(postgres.postgresId);
5906
- logger$3.log(` Waiting for Postgres to be accessible at ${serverHostname}:${externalPort}...`);
5440
+ logger$2.log(` Waiting for Postgres to be accessible at ${serverHostname}:${externalPort}...`);
5907
5441
  await waitForPostgres(serverHostname, externalPort, postgres.databaseUser, postgres.databasePassword, postgres.databaseName);
5908
5442
  const client = new Client({
5909
5443
  host: serverHostname,
@@ -5916,7 +5450,7 @@ async function initializePostgresUsers(api, postgres, serverHostname, users) {
5916
5450
  await client.connect();
5917
5451
  for (const user of users) {
5918
5452
  const schemaName = user.usePublicSchema ? "public" : user.name;
5919
- logger$3.log(` Creating user "${user.name}" with schema "${schemaName}"...`);
5453
+ logger$2.log(` Creating user "${user.name}" with schema "${schemaName}"...`);
5920
5454
  if (user.usePublicSchema) {
5921
5455
  await client.query(`
5922
5456
  DO $$ BEGIN
@@ -5951,15 +5485,15 @@ async function initializePostgresUsers(api, postgres, serverHostname, users) {
5951
5485
  ALTER DEFAULT PRIVILEGES IN SCHEMA "${schemaName}" GRANT ALL ON TABLES TO "${user.name}";
5952
5486
  `);
5953
5487
  }
5954
- logger$3.log(` ✓ User "${user.name}" configured`);
5488
+ logger$2.log(` ✓ User "${user.name}" configured`);
5955
5489
  }
5956
5490
  } finally {
5957
5491
  await client.end();
5958
5492
  }
5959
- logger$3.log(" Disabling external port...");
5493
+ logger$2.log(" Disabling external port...");
5960
5494
  await api.savePostgresExternalPort(postgres.postgresId, null);
5961
5495
  await api.deployPostgres(postgres.postgresId);
5962
- logger$3.log(" ✓ Database users initialized");
5496
+ logger$2.log(" ✓ Database users initialized");
5963
5497
  }
5964
5498
  /**
5965
5499
  * Get the server hostname from the Dokploy endpoint URL
@@ -5973,24 +5507,24 @@ function getServerHostname(endpoint) {
5973
5507
  * @internal Exported for testing
5974
5508
  */
5975
5509
  async function provisionServices(api, projectId, environmentId, projectName, services, existingServiceIds) {
5976
- logger$3.log(`\n🔍 provisionServices called: services=${JSON.stringify(services)}, envId=${environmentId}`);
5510
+ logger$2.log(`\n🔍 provisionServices called: services=${JSON.stringify(services)}, envId=${environmentId}`);
5977
5511
  if (!services || !environmentId) {
5978
- logger$3.log(" Skipping: no services or no environmentId");
5512
+ logger$2.log(" Skipping: no services or no environmentId");
5979
5513
  return void 0;
5980
5514
  }
5981
5515
  const serviceUrls = {};
5982
5516
  const serviceIds = {};
5983
5517
  if (services.postgres) {
5984
- logger$3.log("\n🐘 Checking PostgreSQL...");
5518
+ logger$2.log("\n🐘 Checking PostgreSQL...");
5985
5519
  const postgresName = "db";
5986
5520
  try {
5987
5521
  let postgres = null;
5988
5522
  let created = false;
5989
5523
  if (existingServiceIds?.postgresId) {
5990
- logger$3.log(` Using cached ID: ${existingServiceIds.postgresId}`);
5524
+ logger$2.log(` Using cached ID: ${existingServiceIds.postgresId}`);
5991
5525
  postgres = await api.getPostgres(existingServiceIds.postgresId);
5992
- if (postgres) logger$3.log(` ✓ PostgreSQL found: ${postgres.postgresId}`);
5993
- else logger$3.log(` ⚠ Cached ID invalid, will create new`);
5526
+ if (postgres) logger$2.log(` ✓ PostgreSQL found: ${postgres.postgresId}`);
5527
+ else logger$2.log(` ⚠ Cached ID invalid, will create new`);
5994
5528
  }
5995
5529
  if (!postgres) {
5996
5530
  const databasePassword = randomBytes(16).toString("hex");
@@ -6002,10 +5536,10 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
6002
5536
  postgres = result.postgres;
6003
5537
  created = result.created;
6004
5538
  if (created) {
6005
- logger$3.log(` ✓ Created PostgreSQL: ${postgres.postgresId}`);
5539
+ logger$2.log(` ✓ Created PostgreSQL: ${postgres.postgresId}`);
6006
5540
  await api.deployPostgres(postgres.postgresId);
6007
- logger$3.log(" ✓ PostgreSQL deployed");
6008
- } else logger$3.log(` ✓ PostgreSQL already exists: ${postgres.postgresId}`);
5541
+ logger$2.log(" ✓ PostgreSQL deployed");
5542
+ } else logger$2.log(` ✓ PostgreSQL already exists: ${postgres.postgresId}`);
6009
5543
  }
6010
5544
  serviceIds.postgresId = postgres.postgresId;
6011
5545
  serviceUrls.DATABASE_HOST = postgres.appName;
@@ -6014,23 +5548,23 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
6014
5548
  serviceUrls.DATABASE_USER = postgres.databaseUser;
6015
5549
  serviceUrls.DATABASE_PASSWORD = postgres.databasePassword;
6016
5550
  serviceUrls.DATABASE_URL = `postgresql://${postgres.databaseUser}:${postgres.databasePassword}@${postgres.appName}:5432/${postgres.databaseName}`;
6017
- logger$3.log(` ✓ Database credentials configured`);
5551
+ logger$2.log(` ✓ Database credentials configured`);
6018
5552
  } catch (error) {
6019
5553
  const message = error instanceof Error ? error.message : "Unknown error";
6020
- logger$3.log(` ⚠ Failed to provision PostgreSQL: ${message}`);
5554
+ logger$2.log(` ⚠ Failed to provision PostgreSQL: ${message}`);
6021
5555
  }
6022
5556
  }
6023
5557
  if (services.redis) {
6024
- logger$3.log("\n🔴 Checking Redis...");
5558
+ logger$2.log("\n🔴 Checking Redis...");
6025
5559
  const redisName = "cache";
6026
5560
  try {
6027
5561
  let redis = null;
6028
5562
  let created = false;
6029
5563
  if (existingServiceIds?.redisId) {
6030
- logger$3.log(` Using cached ID: ${existingServiceIds.redisId}`);
5564
+ logger$2.log(` Using cached ID: ${existingServiceIds.redisId}`);
6031
5565
  redis = await api.getRedis(existingServiceIds.redisId);
6032
- if (redis) logger$3.log(` ✓ Redis found: ${redis.redisId}`);
6033
- else logger$3.log(` ⚠ Cached ID invalid, will create new`);
5566
+ if (redis) logger$2.log(` ✓ Redis found: ${redis.redisId}`);
5567
+ else logger$2.log(` ⚠ Cached ID invalid, will create new`);
6034
5568
  }
6035
5569
  if (!redis) {
6036
5570
  const { randomBytes: randomBytes$1 } = await import("node:crypto");
@@ -6039,10 +5573,10 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
6039
5573
  redis = result.redis;
6040
5574
  created = result.created;
6041
5575
  if (created) {
6042
- logger$3.log(` ✓ Created Redis: ${redis.redisId}`);
5576
+ logger$2.log(` ✓ Created Redis: ${redis.redisId}`);
6043
5577
  await api.deployRedis(redis.redisId);
6044
- logger$3.log(" ✓ Redis deployed");
6045
- } else logger$3.log(` ✓ Redis already exists: ${redis.redisId}`);
5578
+ logger$2.log(" ✓ Redis deployed");
5579
+ } else logger$2.log(` ✓ Redis already exists: ${redis.redisId}`);
6046
5580
  }
6047
5581
  serviceIds.redisId = redis.redisId;
6048
5582
  serviceUrls.REDIS_HOST = redis.appName;
@@ -6050,10 +5584,10 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
6050
5584
  if (redis.databasePassword) serviceUrls.REDIS_PASSWORD = redis.databasePassword;
6051
5585
  const password = redis.databasePassword ? `:${redis.databasePassword}@` : "";
6052
5586
  serviceUrls.REDIS_URL = `redis://${password}${redis.appName}:6379`;
6053
- logger$3.log(` ✓ Redis credentials configured`);
5587
+ logger$2.log(` ✓ Redis credentials configured`);
6054
5588
  } catch (error) {
6055
5589
  const message = error instanceof Error ? error.message : "Unknown error";
6056
- logger$3.log(` ⚠ Failed to provision Redis: ${message}`);
5590
+ logger$2.log(` ⚠ Failed to provision Redis: ${message}`);
6057
5591
  }
6058
5592
  }
6059
5593
  return Object.keys(serviceUrls).length > 0 ? {
@@ -6064,11 +5598,11 @@ async function provisionServices(api, projectId, environmentId, projectName, ser
6064
5598
  /**
6065
5599
  * Ensure Dokploy is fully configured, recovering/creating resources as needed
6066
5600
  */
6067
- async function ensureDokploySetup(config$1, dockerConfig, stage, services) {
6068
- logger$3.log("\n🔧 Checking Dokploy setup...");
5601
+ async function ensureDokploySetup(config, dockerConfig, stage, services) {
5602
+ logger$2.log("\n🔧 Checking Dokploy setup...");
6069
5603
  let creds = await getDokployCredentials();
6070
5604
  if (!creds) {
6071
- logger$3.log("\n📋 Dokploy credentials not found. Let's set them up.");
5605
+ logger$2.log("\n📋 Dokploy credentials not found. Let's set them up.");
6072
5606
  const endpoint = await prompt("Dokploy URL (e.g., https://dokploy.example.com): ");
6073
5607
  const normalizedEndpoint = endpoint.replace(/\/$/, "");
6074
5608
  try {
@@ -6076,9 +5610,9 @@ async function ensureDokploySetup(config$1, dockerConfig, stage, services) {
6076
5610
  } catch {
6077
5611
  throw new Error("Invalid URL format");
6078
5612
  }
6079
- logger$3.log(`\nGenerate a token at: ${normalizedEndpoint}/settings/profile\n`);
5613
+ logger$2.log(`\nGenerate a token at: ${normalizedEndpoint}/settings/profile\n`);
6080
5614
  const token = await prompt("API Token: ", true);
6081
- logger$3.log("\nValidating credentials...");
5615
+ logger$2.log("\nValidating credentials...");
6082
5616
  const isValid = await validateDokployToken(normalizedEndpoint, token);
6083
5617
  if (!isValid) throw new Error("Invalid credentials. Please check your token.");
6084
5618
  await storeDokployCredentials(token, normalizedEndpoint);
@@ -6086,28 +5620,28 @@ async function ensureDokploySetup(config$1, dockerConfig, stage, services) {
6086
5620
  token,
6087
5621
  endpoint: normalizedEndpoint
6088
5622
  };
6089
- logger$3.log("✓ Credentials saved");
5623
+ logger$2.log("✓ Credentials saved");
6090
5624
  }
6091
5625
  const api = new DokployApi({
6092
5626
  baseUrl: creds.endpoint,
6093
5627
  token: creds.token
6094
5628
  });
6095
- const existingConfig = config$1.providers?.dokploy;
5629
+ const existingConfig = config.providers?.dokploy;
6096
5630
  if (existingConfig && typeof existingConfig !== "boolean" && existingConfig.applicationId && existingConfig.projectId) {
6097
- logger$3.log("✓ Dokploy config found in gkm.config.ts");
5631
+ logger$2.log("✓ Dokploy config found in gkm.config.ts");
6098
5632
  try {
6099
5633
  const projectDetails = await api.getProject(existingConfig.projectId);
6100
- logger$3.log("✓ Project verified");
5634
+ logger$2.log("✓ Project verified");
6101
5635
  const storedRegistryId = existingConfig.registryId ?? await getDokployRegistryId();
6102
5636
  const environments = projectDetails.environments ?? [];
6103
5637
  let environment = environments.find((e) => e.name.toLowerCase() === stage.toLowerCase());
6104
5638
  if (!environment) {
6105
- logger$3.log(` Creating "${stage}" environment...`);
5639
+ logger$2.log(` Creating "${stage}" environment...`);
6106
5640
  environment = await api.createEnvironment(existingConfig.projectId, stage);
6107
- logger$3.log(` ✓ Created environment: ${environment.environmentId}`);
5641
+ logger$2.log(` ✓ Created environment: ${environment.environmentId}`);
6108
5642
  }
6109
5643
  const environmentId$1 = environment.environmentId;
6110
- logger$3.log(` Services config: ${JSON.stringify(services)}, envId: ${environmentId$1}`);
5644
+ logger$2.log(` Services config: ${JSON.stringify(services)}, envId: ${environmentId$1}`);
6111
5645
  const provisionResult$1 = await provisionServices(api, existingConfig.projectId, environmentId$1, dockerConfig.appName, services, void 0);
6112
5646
  return {
6113
5647
  config: {
@@ -6120,97 +5654,97 @@ async function ensureDokploySetup(config$1, dockerConfig, stage, services) {
6120
5654
  serviceUrls: provisionResult$1?.serviceUrls
6121
5655
  };
6122
5656
  } catch {
6123
- logger$3.log("⚠ Project not found, will recover...");
5657
+ logger$2.log("⚠ Project not found, will recover...");
6124
5658
  }
6125
5659
  }
6126
- logger$3.log("\n📁 Looking for project...");
5660
+ logger$2.log("\n📁 Looking for project...");
6127
5661
  const projectName = dockerConfig.projectName;
6128
5662
  const projects = await api.listProjects();
6129
5663
  let project = projects.find((p) => p.name.toLowerCase() === projectName.toLowerCase());
6130
5664
  let environmentId;
6131
5665
  if (project) {
6132
- logger$3.log(` Found existing project: ${project.name} (${project.projectId})`);
5666
+ logger$2.log(` Found existing project: ${project.name} (${project.projectId})`);
6133
5667
  const projectDetails = await api.getProject(project.projectId);
6134
5668
  const environments = projectDetails.environments ?? [];
6135
5669
  const matchingEnv = environments.find((e) => e.name.toLowerCase() === stage.toLowerCase());
6136
5670
  if (matchingEnv) {
6137
5671
  environmentId = matchingEnv.environmentId;
6138
- logger$3.log(` Using environment: ${matchingEnv.name}`);
5672
+ logger$2.log(` Using environment: ${matchingEnv.name}`);
6139
5673
  } else {
6140
- logger$3.log(` Creating "${stage}" environment...`);
5674
+ logger$2.log(` Creating "${stage}" environment...`);
6141
5675
  const env = await api.createEnvironment(project.projectId, stage);
6142
5676
  environmentId = env.environmentId;
6143
- logger$3.log(` ✓ Created environment: ${stage}`);
5677
+ logger$2.log(` ✓ Created environment: ${stage}`);
6144
5678
  }
6145
5679
  } else {
6146
- logger$3.log(` Creating project: ${projectName}`);
5680
+ logger$2.log(` Creating project: ${projectName}`);
6147
5681
  const result = await api.createProject(projectName);
6148
5682
  project = result.project;
6149
5683
  if (result.environment.name.toLowerCase() !== stage.toLowerCase()) {
6150
- logger$3.log(` Creating "${stage}" environment...`);
5684
+ logger$2.log(` Creating "${stage}" environment...`);
6151
5685
  const env = await api.createEnvironment(project.projectId, stage);
6152
5686
  environmentId = env.environmentId;
6153
5687
  } else environmentId = result.environment.environmentId;
6154
- logger$3.log(` ✓ Created project: ${project.projectId}`);
6155
- logger$3.log(` ✓ Using environment: ${stage}`);
5688
+ logger$2.log(` ✓ Created project: ${project.projectId}`);
5689
+ logger$2.log(` ✓ Using environment: ${stage}`);
6156
5690
  }
6157
- logger$3.log("\n📦 Looking for application...");
5691
+ logger$2.log("\n📦 Looking for application...");
6158
5692
  const appName = dockerConfig.appName;
6159
5693
  let applicationId;
6160
5694
  if (existingConfig && typeof existingConfig !== "boolean" && existingConfig.applicationId) {
6161
5695
  applicationId = existingConfig.applicationId;
6162
- logger$3.log(` Using application from config: ${applicationId}`);
5696
+ logger$2.log(` Using application from config: ${applicationId}`);
6163
5697
  } else {
6164
- logger$3.log(` Creating application: ${appName}`);
5698
+ logger$2.log(` Creating application: ${appName}`);
6165
5699
  const app = await api.createApplication(appName, project.projectId, environmentId);
6166
5700
  applicationId = app.applicationId;
6167
- logger$3.log(` ✓ Created application: ${applicationId}`);
5701
+ logger$2.log(` ✓ Created application: ${applicationId}`);
6168
5702
  }
6169
- logger$3.log("\n🐳 Checking registry...");
5703
+ logger$2.log("\n🐳 Checking registry...");
6170
5704
  let registryId = await getDokployRegistryId();
6171
5705
  if (registryId) try {
6172
5706
  const registry = await api.getRegistry(registryId);
6173
- logger$3.log(` Using registry: ${registry.registryName}`);
5707
+ logger$2.log(` Using registry: ${registry.registryName}`);
6174
5708
  } catch {
6175
- logger$3.log(" ⚠ Stored registry not found, clearing...");
5709
+ logger$2.log(" ⚠ Stored registry not found, clearing...");
6176
5710
  registryId = void 0;
6177
5711
  await storeDokployRegistryId("");
6178
5712
  }
6179
5713
  if (!registryId) {
6180
5714
  const registries = await api.listRegistries();
6181
5715
  if (registries.length === 0) if (dockerConfig.registry) {
6182
- logger$3.log(" No registries found in Dokploy. Let's create one.");
6183
- logger$3.log(` Registry URL: ${dockerConfig.registry}`);
5716
+ logger$2.log(" No registries found in Dokploy. Let's create one.");
5717
+ logger$2.log(` Registry URL: ${dockerConfig.registry}`);
6184
5718
  const username = await prompt("Registry username: ");
6185
5719
  const password = await prompt("Registry password/token: ", true);
6186
5720
  const registry = await api.createRegistry("Default Registry", dockerConfig.registry, username, password);
6187
5721
  registryId = registry.registryId;
6188
5722
  await storeDokployRegistryId(registryId);
6189
- logger$3.log(` ✓ Registry created: ${registryId}`);
6190
- } else logger$3.log(" ⚠ No registry configured. Set docker.registry in gkm.config.ts");
5723
+ logger$2.log(` ✓ Registry created: ${registryId}`);
5724
+ } else logger$2.log(" ⚠ No registry configured. Set docker.registry in gkm.config.ts");
6191
5725
  else {
6192
- logger$3.log(" Available registries:");
5726
+ logger$2.log(" Available registries:");
6193
5727
  registries.forEach((reg, i) => {
6194
- logger$3.log(` ${i + 1}. ${reg.registryName} (${reg.registryUrl})`);
5728
+ logger$2.log(` ${i + 1}. ${reg.registryName} (${reg.registryUrl})`);
6195
5729
  });
6196
- if (dockerConfig.registry) logger$3.log(` ${registries.length + 1}. Create new registry`);
5730
+ if (dockerConfig.registry) logger$2.log(` ${registries.length + 1}. Create new registry`);
6197
5731
  const maxOption = dockerConfig.registry ? registries.length + 1 : registries.length;
6198
5732
  const selection = await prompt(` Select registry (1-${maxOption}): `);
6199
5733
  const index = parseInt(selection, 10) - 1;
6200
5734
  if (index >= 0 && index < registries.length) {
6201
5735
  registryId = registries[index].registryId;
6202
5736
  await storeDokployRegistryId(registryId);
6203
- logger$3.log(` ✓ Selected: ${registries[index].registryName}`);
5737
+ logger$2.log(` ✓ Selected: ${registries[index].registryName}`);
6204
5738
  } else if (dockerConfig.registry && index === registries.length) {
6205
- logger$3.log(`\n Creating new registry...`);
6206
- logger$3.log(` Registry URL: ${dockerConfig.registry}`);
5739
+ logger$2.log(`\n Creating new registry...`);
5740
+ logger$2.log(` Registry URL: ${dockerConfig.registry}`);
6207
5741
  const username = await prompt(" Registry username: ");
6208
5742
  const password = await prompt(" Registry password/token: ", true);
6209
5743
  const registry = await api.createRegistry(dockerConfig.registry.replace(/^https?:\/\//, ""), dockerConfig.registry, username, password);
6210
5744
  registryId = registry.registryId;
6211
5745
  await storeDokployRegistryId(registryId);
6212
- logger$3.log(` ✓ Registry created: ${registryId}`);
6213
- } else logger$3.log(" ⚠ Invalid selection, skipping registry setup");
5746
+ logger$2.log(` ✓ Registry created: ${registryId}`);
5747
+ } else logger$2.log(" ⚠ Invalid selection, skipping registry setup");
6214
5748
  }
6215
5749
  }
6216
5750
  const dokployConfig = {
@@ -6220,10 +5754,10 @@ async function ensureDokploySetup(config$1, dockerConfig, stage, services) {
6220
5754
  registryId: registryId ?? void 0
6221
5755
  };
6222
5756
  await updateConfig(dokployConfig);
6223
- logger$3.log("\n✅ Dokploy setup complete!");
6224
- logger$3.log(` Project: ${project.projectId}`);
6225
- logger$3.log(` Application: ${applicationId}`);
6226
- if (registryId) logger$3.log(` Registry: ${registryId}`);
5757
+ logger$2.log("\n✅ Dokploy setup complete!");
5758
+ logger$2.log(` Project: ${project.projectId}`);
5759
+ logger$2.log(` Application: ${applicationId}`);
5760
+ if (registryId) logger$2.log(` Registry: ${registryId}`);
6227
5761
  const provisionResult = await provisionServices(api, project.projectId, environmentId, dockerConfig.appName, services, void 0);
6228
5762
  return {
6229
5763
  config: dokployConfig,
@@ -6254,45 +5788,45 @@ function generateTag(stage) {
6254
5788
  async function workspaceDeployCommand(workspace, options) {
6255
5789
  const { provider, stage, tag, apps: selectedApps } = options;
6256
5790
  if (provider !== "dokploy") throw new Error(`Workspace deployment only supports Dokploy. Got: ${provider}`);
6257
- logger$3.log(`\n🚀 Deploying workspace "${workspace.name}" to Dokploy...`);
6258
- logger$3.log(` Stage: ${stage}`);
5791
+ logger$2.log(`\n🚀 Deploying workspace "${workspace.name}" to Dokploy...`);
5792
+ logger$2.log(` Stage: ${stage}`);
6259
5793
  const imageTag = tag ?? generateTag(stage);
6260
- logger$3.log(` Tag: ${imageTag}`);
5794
+ logger$2.log(` Tag: ${imageTag}`);
6261
5795
  const buildOrder = getAppBuildOrder(workspace);
6262
5796
  let appsToDeployNames = buildOrder;
6263
5797
  if (selectedApps && selectedApps.length > 0) {
6264
5798
  const invalidApps = selectedApps.filter((name$1) => !workspace.apps[name$1]);
6265
5799
  if (invalidApps.length > 0) throw new Error(`Unknown apps: ${invalidApps.join(", ")}\nAvailable apps: ${Object.keys(workspace.apps).join(", ")}`);
6266
5800
  appsToDeployNames = buildOrder.filter((name$1) => selectedApps.includes(name$1));
6267
- logger$3.log(` Deploying apps: ${appsToDeployNames.join(", ")}`);
6268
- } else logger$3.log(` Deploying all apps: ${appsToDeployNames.join(", ")}`);
5801
+ logger$2.log(` Deploying apps: ${appsToDeployNames.join(", ")}`);
5802
+ } else logger$2.log(` Deploying all apps: ${appsToDeployNames.join(", ")}`);
6269
5803
  const dokployApps = appsToDeployNames.filter((name$1) => {
6270
5804
  const app = workspace.apps[name$1];
6271
5805
  const target = app.resolvedDeployTarget;
6272
5806
  if (!isDeployTargetSupported(target)) {
6273
- logger$3.log(` ⚠️ Skipping ${name$1}: ${getDeployTargetError(target, name$1)}`);
5807
+ logger$2.log(` ⚠️ Skipping ${name$1}: ${getDeployTargetError(target, name$1)}`);
6274
5808
  return false;
6275
5809
  }
6276
5810
  return true;
6277
5811
  });
6278
5812
  if (dokployApps.length === 0) throw new Error("No apps to deploy. All selected apps have unsupported deploy targets.");
6279
5813
  appsToDeployNames = dokployApps;
6280
- logger$3.log("\n🔐 Loading secrets and analyzing environment requirements...");
5814
+ logger$2.log("\n🔐 Loading secrets and analyzing environment requirements...");
6281
5815
  const stageSecrets = await readStageSecrets(stage, workspace.root);
6282
5816
  if (!stageSecrets) {
6283
- logger$3.log(` ⚠️ No secrets found for stage "${stage}"`);
6284
- logger$3.log(` Run "gkm secrets:init --stage ${stage}" to create secrets`);
5817
+ logger$2.log(` ⚠️ No secrets found for stage "${stage}"`);
5818
+ logger$2.log(` Run "gkm secrets:init --stage ${stage}" to create secrets`);
6285
5819
  }
6286
5820
  const sniffedApps = await sniffAllApps(workspace.apps, workspace.root);
6287
5821
  const encryptedSecrets = stageSecrets ? prepareSecretsForAllApps(stageSecrets, sniffedApps) : /* @__PURE__ */ new Map();
6288
5822
  if (stageSecrets) {
6289
5823
  const report = generateSecretsReport(encryptedSecrets, sniffedApps);
6290
- if (report.appsWithSecrets.length > 0) logger$3.log(` ✓ Encrypted secrets for: ${report.appsWithSecrets.join(", ")}`);
6291
- if (report.appsWithMissingSecrets.length > 0) for (const { appName, missing } of report.appsWithMissingSecrets) logger$3.log(` ⚠️ ${appName}: Missing secrets: ${missing.join(", ")}`);
5824
+ if (report.appsWithSecrets.length > 0) logger$2.log(` ✓ Encrypted secrets for: ${report.appsWithSecrets.join(", ")}`);
5825
+ if (report.appsWithMissingSecrets.length > 0) for (const { appName, missing } of report.appsWithMissingSecrets) logger$2.log(` ⚠️ ${appName}: Missing secrets: ${missing.join(", ")}`);
6292
5826
  }
6293
5827
  let creds = await getDokployCredentials();
6294
5828
  if (!creds) {
6295
- logger$3.log("\n📋 Dokploy credentials not found. Let's set them up.");
5829
+ logger$2.log("\n📋 Dokploy credentials not found. Let's set them up.");
6296
5830
  const endpoint = await prompt("Dokploy URL (e.g., https://dokploy.example.com): ");
6297
5831
  const normalizedEndpoint = endpoint.replace(/\/$/, "");
6298
5832
  try {
@@ -6300,9 +5834,9 @@ async function workspaceDeployCommand(workspace, options) {
6300
5834
  } catch {
6301
5835
  throw new Error("Invalid URL format");
6302
5836
  }
6303
- logger$3.log(`\nGenerate a token at: ${normalizedEndpoint}/settings/profile\n`);
5837
+ logger$2.log(`\nGenerate a token at: ${normalizedEndpoint}/settings/profile\n`);
6304
5838
  const token = await prompt("API Token: ", true);
6305
- logger$3.log("\nValidating credentials...");
5839
+ logger$2.log("\nValidating credentials...");
6306
5840
  const isValid = await validateDokployToken(normalizedEndpoint, token);
6307
5841
  if (!isValid) throw new Error("Invalid credentials. Please check your token.");
6308
5842
  await storeDokployCredentials(token, normalizedEndpoint);
@@ -6310,43 +5844,43 @@ async function workspaceDeployCommand(workspace, options) {
6310
5844
  token,
6311
5845
  endpoint: normalizedEndpoint
6312
5846
  };
6313
- logger$3.log("✓ Credentials saved");
5847
+ logger$2.log("✓ Credentials saved");
6314
5848
  }
6315
5849
  const api = new DokployApi({
6316
5850
  baseUrl: creds.endpoint,
6317
5851
  token: creds.token
6318
5852
  });
6319
- logger$3.log("\n📁 Setting up Dokploy project...");
5853
+ logger$2.log("\n📁 Setting up Dokploy project...");
6320
5854
  const projectName = workspace.name;
6321
5855
  const projects = await api.listProjects();
6322
5856
  let project = projects.find((p) => p.name.toLowerCase() === projectName.toLowerCase());
6323
5857
  let environmentId;
6324
5858
  if (project) {
6325
- logger$3.log(` Found existing project: ${project.name}`);
5859
+ logger$2.log(` Found existing project: ${project.name}`);
6326
5860
  const projectDetails = await api.getProject(project.projectId);
6327
5861
  const environments = projectDetails.environments ?? [];
6328
5862
  const matchingEnv = environments.find((e) => e.name.toLowerCase() === stage.toLowerCase());
6329
5863
  if (matchingEnv) {
6330
5864
  environmentId = matchingEnv.environmentId;
6331
- logger$3.log(` Using environment: ${matchingEnv.name}`);
5865
+ logger$2.log(` Using environment: ${matchingEnv.name}`);
6332
5866
  } else {
6333
- logger$3.log(` Creating "${stage}" environment...`);
5867
+ logger$2.log(` Creating "${stage}" environment...`);
6334
5868
  const env = await api.createEnvironment(project.projectId, stage);
6335
5869
  environmentId = env.environmentId;
6336
- logger$3.log(` ✓ Created environment: ${stage}`);
5870
+ logger$2.log(` ✓ Created environment: ${stage}`);
6337
5871
  }
6338
5872
  } else {
6339
- logger$3.log(` Creating project: ${projectName}`);
5873
+ logger$2.log(` Creating project: ${projectName}`);
6340
5874
  const result = await api.createProject(projectName);
6341
5875
  project = result.project;
6342
5876
  if (result.environment.name.toLowerCase() !== stage.toLowerCase()) {
6343
- logger$3.log(` Creating "${stage}" environment...`);
5877
+ logger$2.log(` Creating "${stage}" environment...`);
6344
5878
  const env = await api.createEnvironment(project.projectId, stage);
6345
5879
  environmentId = env.environmentId;
6346
5880
  } else environmentId = result.environment.environmentId;
6347
- logger$3.log(` ✓ Created project: ${project.projectId}`);
5881
+ logger$2.log(` ✓ Created project: ${project.projectId}`);
6348
5882
  }
6349
- logger$3.log("\n📋 Loading deploy state...");
5883
+ logger$2.log("\n📋 Loading deploy state...");
6350
5884
  const stateProvider = await createStateProvider({
6351
5885
  config: workspace.state,
6352
5886
  workspaceRoot: workspace.root,
@@ -6354,27 +5888,27 @@ async function workspaceDeployCommand(workspace, options) {
6354
5888
  });
6355
5889
  let state = await stateProvider.read(stage);
6356
5890
  if (state) {
6357
- logger$3.log(` Found existing state for stage "${stage}"`);
5891
+ logger$2.log(` Found existing state for stage "${stage}"`);
6358
5892
  if (state.projectId !== project.projectId) {
6359
- logger$3.log(` ⚠ Project ID changed, updating state`);
5893
+ logger$2.log(` ⚠ Project ID changed, updating state`);
6360
5894
  state.projectId = project.projectId;
6361
5895
  }
6362
5896
  if (state.environmentId !== environmentId) {
6363
- logger$3.log(` ⚠ Environment ID changed, updating state`);
5897
+ logger$2.log(` ⚠ Environment ID changed, updating state`);
6364
5898
  state.environmentId = environmentId;
6365
5899
  }
6366
5900
  } else {
6367
- logger$3.log(` Creating new state for stage "${stage}"`);
5901
+ logger$2.log(` Creating new state for stage "${stage}"`);
6368
5902
  state = createEmptyState(stage, project.projectId, environmentId);
6369
5903
  }
6370
- logger$3.log("\n🐳 Checking registry...");
5904
+ logger$2.log("\n🐳 Checking registry...");
6371
5905
  let registryId = await getDokployRegistryId();
6372
5906
  const registry = workspace.deploy.dokploy?.registry;
6373
5907
  if (registryId) try {
6374
5908
  const reg = await api.getRegistry(registryId);
6375
- logger$3.log(` Using registry: ${reg.registryName}`);
5909
+ logger$2.log(` Using registry: ${reg.registryName}`);
6376
5910
  } catch {
6377
- logger$3.log(" ⚠ Stored registry not found, clearing...");
5911
+ logger$2.log(" ⚠ Stored registry not found, clearing...");
6378
5912
  registryId = void 0;
6379
5913
  await storeDokployRegistryId("");
6380
5914
  }
@@ -6383,17 +5917,17 @@ async function workspaceDeployCommand(workspace, options) {
6383
5917
  if (registries.length > 0) {
6384
5918
  registryId = registries[0].registryId;
6385
5919
  await storeDokployRegistryId(registryId);
6386
- logger$3.log(` Using registry: ${registries[0].registryName}`);
5920
+ logger$2.log(` Using registry: ${registries[0].registryName}`);
6387
5921
  } else if (registry) {
6388
- logger$3.log(" No registries found in Dokploy. Let's create one.");
6389
- logger$3.log(` Registry URL: ${registry}`);
5922
+ logger$2.log(" No registries found in Dokploy. Let's create one.");
5923
+ logger$2.log(` Registry URL: ${registry}`);
6390
5924
  const username = await prompt("Registry username: ");
6391
5925
  const password = await prompt("Registry password/token: ", true);
6392
5926
  const reg = await api.createRegistry("Default Registry", registry, username, password);
6393
5927
  registryId = reg.registryId;
6394
5928
  await storeDokployRegistryId(registryId);
6395
- logger$3.log(` ✓ Registry created: ${registryId}`);
6396
- } else logger$3.log(" ⚠ No registry configured. Set deploy.dokploy.registry in workspace config");
5929
+ logger$2.log(` ✓ Registry created: ${registryId}`);
5930
+ } else logger$2.log(" ⚠ No registry configured. Set deploy.dokploy.registry in workspace config");
6397
5931
  }
6398
5932
  const services = workspace.services;
6399
5933
  const dockerServices = {
@@ -6403,7 +5937,7 @@ async function workspaceDeployCommand(workspace, options) {
6403
5937
  let provisionedPostgres = null;
6404
5938
  let provisionedRedis = null;
6405
5939
  if (dockerServices.postgres || dockerServices.redis) {
6406
- logger$3.log("\n🔧 Provisioning infrastructure services...");
5940
+ logger$2.log("\n🔧 Provisioning infrastructure services...");
6407
5941
  const existingServiceIds = {
6408
5942
  postgresId: getPostgresId(state),
6409
5943
  redisId: getRedisId(state)
@@ -6421,7 +5955,7 @@ async function workspaceDeployCommand(workspace, options) {
6421
5955
  }
6422
5956
  }
6423
5957
  const skippedMobileApps = appsToDeployNames.filter((name$1) => workspace.apps[name$1].type === "mobile");
6424
- if (skippedMobileApps.length > 0) logger$3.log(`\n📱 Skipping ${skippedMobileApps.length} mobile app(s) — deploy via framework toolchain: ${skippedMobileApps.join(", ")}`);
5958
+ if (skippedMobileApps.length > 0) logger$2.log(`\n📱 Skipping ${skippedMobileApps.length} mobile app(s) — deploy via framework toolchain: ${skippedMobileApps.join(", ")}`);
6425
5959
  const backendApps = appsToDeployNames.filter((name$1) => workspace.apps[name$1].type === "backend");
6426
5960
  const frontendApps = appsToDeployNames.filter((name$1) => workspace.apps[name$1].type === "web");
6427
5961
  const perAppDbCredentials = /* @__PURE__ */ new Map();
@@ -6431,13 +5965,13 @@ async function workspaceDeployCommand(workspace, options) {
6431
5965
  return requirements?.requiredEnvVars.includes("DATABASE_URL");
6432
5966
  });
6433
5967
  if (appsNeedingDb.length > 0) {
6434
- logger$3.log(`\n🔐 Setting up per-app database credentials...`);
6435
- logger$3.log(` Apps needing DATABASE_URL: ${appsNeedingDb.join(", ")}`);
5968
+ logger$2.log(`\n🔐 Setting up per-app database credentials...`);
5969
+ logger$2.log(` Apps needing DATABASE_URL: ${appsNeedingDb.join(", ")}`);
6436
5970
  const existingCredentials = getAllAppCredentials(state);
6437
5971
  const usersToCreate = [];
6438
5972
  for (const appName of appsNeedingDb) {
6439
5973
  let credentials = existingCredentials[appName];
6440
- if (credentials) logger$3.log(` ${appName}: Using existing credentials from state`);
5974
+ if (credentials) logger$2.log(` ${appName}: Using existing credentials from state`);
6441
5975
  else {
6442
5976
  const password = randomBytes(16).toString("hex");
6443
5977
  credentials = {
@@ -6445,7 +5979,7 @@ async function workspaceDeployCommand(workspace, options) {
6445
5979
  dbPassword: password
6446
5980
  };
6447
5981
  setAppCredentials(state, appName, credentials);
6448
- logger$3.log(` ${appName}: Generated new credentials`);
5982
+ logger$2.log(` ${appName}: Generated new credentials`);
6449
5983
  }
6450
5984
  perAppDbCredentials.set(appName, credentials);
6451
5985
  usersToCreate.push({
@@ -6459,8 +5993,8 @@ async function workspaceDeployCommand(workspace, options) {
6459
5993
  }
6460
5994
  }
6461
5995
  if (workspace.deploy?.backups && provisionedPostgres) {
6462
- logger$3.log("\n💾 Provisioning backup destination...");
6463
- const { provisionBackupDestination } = await import("./backup-provisioner-BEXoHTuC.mjs");
5996
+ logger$2.log("\n💾 Provisioning backup destination...");
5997
+ const { provisionBackupDestination } = await import("./backup-provisioner-Xunq-p_8.mjs");
6464
5998
  const backupState = await provisionBackupDestination({
6465
5999
  api,
6466
6000
  projectId: project.projectId,
@@ -6468,13 +6002,13 @@ async function workspaceDeployCommand(workspace, options) {
6468
6002
  stage,
6469
6003
  config: workspace.deploy.backups,
6470
6004
  existingState: getBackupState(state),
6471
- logger: logger$3
6005
+ logger: logger$2
6472
6006
  });
6473
6007
  setBackupState(state, backupState);
6474
6008
  if (!backupState.postgresBackupId) {
6475
6009
  const backupSchedule = workspace.deploy.backups.schedule ?? "0 2 * * *";
6476
6010
  const backupRetention = workspace.deploy.backups.retention ?? 30;
6477
- logger$3.log(" Creating postgres backup schedule...");
6011
+ logger$2.log(" Creating postgres backup schedule...");
6478
6012
  const backup = await api.createPostgresBackup({
6479
6013
  schedule: backupSchedule,
6480
6014
  prefix: `${stage}/postgres`,
@@ -6485,8 +6019,8 @@ async function workspaceDeployCommand(workspace, options) {
6485
6019
  keepLatestCount: backupRetention
6486
6020
  });
6487
6021
  setPostgresBackupId(state, backup.backupId);
6488
- logger$3.log(` ✓ Postgres backup schedule created (${backupSchedule})`);
6489
- } else logger$3.log(" ✓ Using existing postgres backup schedule");
6022
+ logger$2.log(` ✓ Postgres backup schedule created (${backupSchedule})`);
6023
+ } else logger$2.log(" ✓ Using existing postgres backup schedule");
6490
6024
  }
6491
6025
  const publicUrls = {};
6492
6026
  const results = [];
@@ -6501,25 +6035,25 @@ async function workspaceDeployCommand(workspace, options) {
6501
6035
  frontendUrls.push(`https://${hostname}`);
6502
6036
  }
6503
6037
  if (backendApps.length > 0) {
6504
- logger$3.log("\n📦 PHASE 1: Deploying backend applications...");
6038
+ logger$2.log("\n📦 PHASE 1: Deploying backend applications...");
6505
6039
  for (const appName of backendApps) {
6506
6040
  const app = workspace.apps[appName];
6507
- logger$3.log(`\n ⚙️ Deploying ${appName}...`);
6041
+ logger$2.log(`\n ⚙️ Deploying ${appName}...`);
6508
6042
  try {
6509
6043
  const dokployAppName = appName;
6510
6044
  let application = null;
6511
6045
  const cachedAppId = getApplicationId(state, appName);
6512
6046
  if (cachedAppId) {
6513
- logger$3.log(` Using cached ID: ${cachedAppId}`);
6047
+ logger$2.log(` Using cached ID: ${cachedAppId}`);
6514
6048
  application = await api.getApplication(cachedAppId);
6515
- if (application) logger$3.log(` ✓ Application found: ${application.applicationId}`);
6516
- else logger$3.log(` ⚠ Cached ID invalid, will create new`);
6049
+ if (application) logger$2.log(` ✓ Application found: ${application.applicationId}`);
6050
+ else logger$2.log(` ⚠ Cached ID invalid, will create new`);
6517
6051
  }
6518
6052
  if (!application) {
6519
6053
  const result = await api.findOrCreateApplication(dokployAppName, project.projectId, environmentId);
6520
6054
  application = result.application;
6521
- if (result.created) logger$3.log(` Created application: ${application.applicationId}`);
6522
- else logger$3.log(` Found existing application: ${application.applicationId}`);
6055
+ if (result.created) logger$2.log(` Created application: ${application.applicationId}`);
6056
+ else logger$2.log(` Found existing application: ${application.applicationId}`);
6523
6057
  }
6524
6058
  setApplicationId(state, appName, application.applicationId);
6525
6059
  const appSecrets = encryptedSecrets.get(appName);
@@ -6527,11 +6061,11 @@ async function workspaceDeployCommand(workspace, options) {
6527
6061
  if (appSecrets && appSecrets.secretCount > 0) {
6528
6062
  buildArgs.push(`GKM_ENCRYPTED_CREDENTIALS=${appSecrets.payload.encrypted}`);
6529
6063
  buildArgs.push(`GKM_CREDENTIALS_IV=${appSecrets.payload.iv}`);
6530
- logger$3.log(` Encrypted ${appSecrets.secretCount} secrets`);
6064
+ logger$2.log(` Encrypted ${appSecrets.secretCount} secrets`);
6531
6065
  }
6532
6066
  const imageName = `${workspace.name}-${appName}`;
6533
6067
  const imageRef = registry ? `${registry}/${imageName}:${imageTag}` : `${imageName}:${imageTag}`;
6534
- logger$3.log(` Building Docker image: ${imageRef}`);
6068
+ logger$2.log(` Building Docker image: ${imageRef}`);
6535
6069
  await deployDocker({
6536
6070
  stage,
6537
6071
  tag: imageTag,
@@ -6581,10 +6115,10 @@ async function workspaceDeployCommand(workspace, options) {
6581
6115
  const { valid, missing, resolved } = validateEnvVars(requiredVars, envContext);
6582
6116
  if (!valid) throw new Error(formatMissingVarsError(appName, missing, stage));
6583
6117
  const envVars = Object.entries(resolved).map(([key, value]) => `${key}=${value}`);
6584
- if (Object.keys(resolved).length > 0) logger$3.log(` Resolved ${Object.keys(resolved).length} env vars: ${Object.keys(resolved).join(", ")}`);
6118
+ if (Object.keys(resolved).length > 0) logger$2.log(` Resolved ${Object.keys(resolved).length} env vars: ${Object.keys(resolved).join(", ")}`);
6585
6119
  await api.saveDockerProvider(application.applicationId, imageRef, { registryId });
6586
6120
  await api.saveApplicationEnv(application.applicationId, envVars.join("\n"));
6587
- logger$3.log(` Deploying to Dokploy...`);
6121
+ logger$2.log(` Deploying to Dokploy...`);
6588
6122
  await api.deployApplication(application.applicationId);
6589
6123
  const existingDomains = await api.getDomainsByApplicationId(application.applicationId);
6590
6124
  const existingDomain = existingDomains.find((d) => d.host === backendHost);
@@ -6592,7 +6126,7 @@ async function workspaceDeployCommand(workspace, options) {
6592
6126
  appHostnames.set(appName, backendHost);
6593
6127
  appDomainIds.set(appName, existingDomain.domainId);
6594
6128
  publicUrls[appName] = `https://${backendHost}`;
6595
- logger$3.log(` ✓ Domain: https://${backendHost} (existing)`);
6129
+ logger$2.log(` ✓ Domain: https://${backendHost} (existing)`);
6596
6130
  } else try {
6597
6131
  const domain = await api.createDomain({
6598
6132
  host: backendHost,
@@ -6604,10 +6138,10 @@ async function workspaceDeployCommand(workspace, options) {
6604
6138
  appHostnames.set(appName, backendHost);
6605
6139
  appDomainIds.set(appName, domain.domainId);
6606
6140
  publicUrls[appName] = `https://${backendHost}`;
6607
- logger$3.log(` ✓ Domain: https://${backendHost} (created)`);
6141
+ logger$2.log(` ✓ Domain: https://${backendHost} (created)`);
6608
6142
  } catch (domainError) {
6609
6143
  const message = domainError instanceof Error ? domainError.message : "Unknown error";
6610
- logger$3.log(` ⚠ Domain creation failed: ${message}`);
6144
+ logger$2.log(` ⚠ Domain creation failed: ${message}`);
6611
6145
  appHostnames.set(appName, backendHost);
6612
6146
  publicUrls[appName] = `https://${backendHost}`;
6613
6147
  }
@@ -6618,10 +6152,10 @@ async function workspaceDeployCommand(workspace, options) {
6618
6152
  applicationId: application.applicationId,
6619
6153
  imageRef
6620
6154
  });
6621
- logger$3.log(` ✓ ${appName} deployed successfully`);
6155
+ logger$2.log(` ✓ ${appName} deployed successfully`);
6622
6156
  } catch (error) {
6623
6157
  const message = error instanceof Error ? error.message : "Unknown error";
6624
- logger$3.log(` ✗ Failed to deploy ${appName}: ${message}`);
6158
+ logger$2.log(` ✗ Failed to deploy ${appName}: ${message}`);
6625
6159
  results.push({
6626
6160
  appName,
6627
6161
  type: app.type,
@@ -6633,25 +6167,25 @@ async function workspaceDeployCommand(workspace, options) {
6633
6167
  }
6634
6168
  }
6635
6169
  if (frontendApps.length > 0) {
6636
- logger$3.log("\n🌐 PHASE 2: Deploying frontend applications...");
6170
+ logger$2.log("\n🌐 PHASE 2: Deploying frontend applications...");
6637
6171
  for (const appName of frontendApps) {
6638
6172
  const app = workspace.apps[appName];
6639
- logger$3.log(`\n 🌐 Deploying ${appName}...`);
6173
+ logger$2.log(`\n 🌐 Deploying ${appName}...`);
6640
6174
  try {
6641
6175
  const dokployAppName = appName;
6642
6176
  let application = null;
6643
6177
  const cachedAppId = getApplicationId(state, appName);
6644
6178
  if (cachedAppId) {
6645
- logger$3.log(` Using cached ID: ${cachedAppId}`);
6179
+ logger$2.log(` Using cached ID: ${cachedAppId}`);
6646
6180
  application = await api.getApplication(cachedAppId);
6647
- if (application) logger$3.log(` ✓ Application found: ${application.applicationId}`);
6648
- else logger$3.log(` ⚠ Cached ID invalid, will create new`);
6181
+ if (application) logger$2.log(` ✓ Application found: ${application.applicationId}`);
6182
+ else logger$2.log(` ⚠ Cached ID invalid, will create new`);
6649
6183
  }
6650
6184
  if (!application) {
6651
6185
  const result = await api.findOrCreateApplication(dokployAppName, project.projectId, environmentId);
6652
6186
  application = result.application;
6653
- if (result.created) logger$3.log(` Created application: ${application.applicationId}`);
6654
- else logger$3.log(` Found existing application: ${application.applicationId}`);
6187
+ if (result.created) logger$2.log(` Created application: ${application.applicationId}`);
6188
+ else logger$2.log(` Found existing application: ${application.applicationId}`);
6655
6189
  }
6656
6190
  setApplicationId(state, appName, application.applicationId);
6657
6191
  const dependencyUrls = {};
@@ -6673,7 +6207,7 @@ async function workspaceDeployCommand(workspace, options) {
6673
6207
  const sniffedVars = sniffedApps.get(appName)?.requiredEnvVars ?? [];
6674
6208
  const { valid, missing, resolved } = validateEnvVars(sniffedVars, envContext);
6675
6209
  if (!valid) throw new Error(formatMissingVarsError(appName, missing, stage));
6676
- if (Object.keys(resolved).length > 0) logger$3.log(` Resolved ${Object.keys(resolved).length} env vars: ${Object.keys(resolved).join(", ")}`);
6210
+ if (Object.keys(resolved).length > 0) logger$2.log(` Resolved ${Object.keys(resolved).length} env vars: ${Object.keys(resolved).join(", ")}`);
6677
6211
  const publicPrefix = getPublicEnvPrefix(app.framework);
6678
6212
  const buildArgs = [];
6679
6213
  const publicUrlArgNames = [];
@@ -6683,10 +6217,10 @@ async function workspaceDeployCommand(workspace, options) {
6683
6217
  publicUrlArgNames.push(key);
6684
6218
  }
6685
6219
  }
6686
- if (buildArgs.length > 0) logger$3.log(` Build args: ${publicUrlArgNames.join(", ")}`);
6220
+ if (buildArgs.length > 0) logger$2.log(` Build args: ${publicUrlArgNames.join(", ")}`);
6687
6221
  const imageName = `${workspace.name}-${appName}`;
6688
6222
  const imageRef = registry ? `${registry}/${imageName}:${imageTag}` : `${imageName}:${imageTag}`;
6689
- logger$3.log(` Building Docker image: ${imageRef}`);
6223
+ logger$2.log(` Building Docker image: ${imageRef}`);
6690
6224
  await deployDocker({
6691
6225
  stage,
6692
6226
  tag: imageTag,
@@ -6707,7 +6241,7 @@ async function workspaceDeployCommand(workspace, options) {
6707
6241
  for (const [key, value] of Object.entries(resolved)) envVars.push(`${key}=${value}`);
6708
6242
  await api.saveDockerProvider(application.applicationId, imageRef, { registryId });
6709
6243
  await api.saveApplicationEnv(application.applicationId, envVars.join("\n"));
6710
- logger$3.log(` Deploying to Dokploy...`);
6244
+ logger$2.log(` Deploying to Dokploy...`);
6711
6245
  await api.deployApplication(application.applicationId);
6712
6246
  const existingFrontendDomains = await api.getDomainsByApplicationId(application.applicationId);
6713
6247
  const existingFrontendDomain = existingFrontendDomains.find((d) => d.host === frontendHost);
@@ -6715,7 +6249,7 @@ async function workspaceDeployCommand(workspace, options) {
6715
6249
  appHostnames.set(appName, frontendHost);
6716
6250
  appDomainIds.set(appName, existingFrontendDomain.domainId);
6717
6251
  publicUrls[appName] = `https://${frontendHost}`;
6718
- logger$3.log(` ✓ Domain: https://${frontendHost} (existing)`);
6252
+ logger$2.log(` ✓ Domain: https://${frontendHost} (existing)`);
6719
6253
  } else try {
6720
6254
  const domain = await api.createDomain({
6721
6255
  host: frontendHost,
@@ -6727,10 +6261,10 @@ async function workspaceDeployCommand(workspace, options) {
6727
6261
  appHostnames.set(appName, frontendHost);
6728
6262
  appDomainIds.set(appName, domain.domainId);
6729
6263
  publicUrls[appName] = `https://${frontendHost}`;
6730
- logger$3.log(` ✓ Domain: https://${frontendHost} (created)`);
6264
+ logger$2.log(` ✓ Domain: https://${frontendHost} (created)`);
6731
6265
  } catch (domainError) {
6732
6266
  const message = domainError instanceof Error ? domainError.message : "Unknown error";
6733
- logger$3.log(` ⚠ Domain creation failed: ${message}`);
6267
+ logger$2.log(` ⚠ Domain creation failed: ${message}`);
6734
6268
  appHostnames.set(appName, frontendHost);
6735
6269
  publicUrls[appName] = `https://${frontendHost}`;
6736
6270
  }
@@ -6741,10 +6275,10 @@ async function workspaceDeployCommand(workspace, options) {
6741
6275
  applicationId: application.applicationId,
6742
6276
  imageRef
6743
6277
  });
6744
- logger$3.log(` ✓ ${appName} deployed successfully`);
6278
+ logger$2.log(` ✓ ${appName} deployed successfully`);
6745
6279
  } catch (error) {
6746
6280
  const message = error instanceof Error ? error.message : "Unknown error";
6747
- logger$3.log(` ✗ Failed to deploy ${appName}: ${message}`);
6281
+ logger$2.log(` ✗ Failed to deploy ${appName}: ${message}`);
6748
6282
  results.push({
6749
6283
  appName,
6750
6284
  type: app.type,
@@ -6754,9 +6288,9 @@ async function workspaceDeployCommand(workspace, options) {
6754
6288
  }
6755
6289
  }
6756
6290
  }
6757
- logger$3.log("\n📋 Saving deploy state...");
6291
+ logger$2.log("\n📋 Saving deploy state...");
6758
6292
  await stateProvider.write(stage, state);
6759
- logger$3.log(" ✓ State saved");
6293
+ logger$2.log(" ✓ State saved");
6760
6294
  const dnsConfig = workspace.deploy.dns;
6761
6295
  if (dnsConfig && appHostnames.size > 0) {
6762
6296
  const dnsResult = await orchestrateDns(appHostnames, dnsConfig, creds.endpoint);
@@ -6765,27 +6299,27 @@ async function workspaceDeployCommand(workspace, options) {
6765
6299
  await stateProvider.write(stage, state);
6766
6300
  }
6767
6301
  if (dnsResult?.success && appHostnames.size > 0) {
6768
- logger$3.log("\n🔒 Validating domains for SSL certificates...");
6302
+ logger$2.log("\n🔒 Validating domains for SSL certificates...");
6769
6303
  for (const [appName, hostname] of appHostnames) try {
6770
6304
  const result = await api.validateDomain(hostname);
6771
- if (result.isValid) logger$3.log(` ✓ ${appName}: ${hostname} → ${result.resolvedIp}`);
6772
- else logger$3.log(` ⚠ ${appName}: ${hostname} not valid`);
6305
+ if (result.isValid) logger$2.log(` ✓ ${appName}: ${hostname} → ${result.resolvedIp}`);
6306
+ else logger$2.log(` ⚠ ${appName}: ${hostname} not valid`);
6773
6307
  } catch (validationError) {
6774
6308
  const message = validationError instanceof Error ? validationError.message : "Unknown error";
6775
- logger$3.log(` ⚠ ${appName}: validation failed - ${message}`);
6309
+ logger$2.log(` ⚠ ${appName}: validation failed - ${message}`);
6776
6310
  }
6777
6311
  }
6778
6312
  }
6779
6313
  const successCount = results.filter((r) => r.success).length;
6780
6314
  const failedCount = results.filter((r) => !r.success).length;
6781
- logger$3.log(`\n${"─".repeat(50)}`);
6782
- logger$3.log(`\n✅ Workspace deployment complete!`);
6783
- logger$3.log(` Project: ${project.projectId}`);
6784
- logger$3.log(` Successful: ${successCount}`);
6785
- if (failedCount > 0) logger$3.log(` Failed: ${failedCount}`);
6315
+ logger$2.log(`\n${"─".repeat(50)}`);
6316
+ logger$2.log(`\n✅ Workspace deployment complete!`);
6317
+ logger$2.log(` Project: ${project.projectId}`);
6318
+ logger$2.log(` Successful: ${successCount}`);
6319
+ if (failedCount > 0) logger$2.log(` Failed: ${failedCount}`);
6786
6320
  if (Object.keys(publicUrls).length > 0) {
6787
- logger$3.log("\n 📡 Deployed URLs:");
6788
- for (const [name$1, url] of Object.entries(publicUrls)) logger$3.log(` ${name$1}: ${url}`);
6321
+ logger$2.log("\n 📡 Deployed URLs:");
6322
+ for (const [name$1, url] of Object.entries(publicUrls)) logger$2.log(` ${name$1}: ${url}`);
6789
6323
  }
6790
6324
  return {
6791
6325
  apps: results,
@@ -6801,23 +6335,23 @@ async function deployCommand(options) {
6801
6335
  const { provider, stage, tag, skipPush, skipBuild } = options;
6802
6336
  const loadedConfig = await loadWorkspaceConfig();
6803
6337
  if (loadedConfig.type === "workspace") {
6804
- logger$3.log("📦 Detected workspace configuration");
6338
+ logger$2.log("📦 Detected workspace configuration");
6805
6339
  return workspaceDeployCommand(loadedConfig.workspace, options);
6806
6340
  }
6807
- logger$3.log(`\n🚀 Deploying to ${provider}...`);
6808
- logger$3.log(` Stage: ${stage}`);
6809
- const config$1 = await loadConfig();
6341
+ logger$2.log(`\n🚀 Deploying to ${provider}...`);
6342
+ logger$2.log(` Stage: ${stage}`);
6343
+ const config = await loadConfig();
6810
6344
  const imageTag = tag ?? generateTag(stage);
6811
- logger$3.log(` Tag: ${imageTag}`);
6812
- const dockerConfig = resolveDockerConfig(config$1);
6345
+ logger$2.log(` Tag: ${imageTag}`);
6346
+ const dockerConfig = resolveDockerConfig(config);
6813
6347
  const imageName = dockerConfig.imageName;
6814
6348
  const registry = dockerConfig.registry;
6815
6349
  const imageRef = registry ? `${registry}/${imageName}:${imageTag}` : `${imageName}:${imageTag}`;
6816
6350
  let dokployConfig;
6817
6351
  let finalRegistry = registry;
6818
6352
  if (provider === "dokploy") {
6819
- const composeServices = config$1.docker?.compose?.services;
6820
- logger$3.log(`\n🔍 Docker compose config: ${JSON.stringify(config$1.docker?.compose)}`);
6353
+ const composeServices = config.docker?.compose?.services;
6354
+ logger$2.log(`\n🔍 Docker compose config: ${JSON.stringify(config.docker?.compose)}`);
6821
6355
  const dockerServices = composeServices ? Array.isArray(composeServices) ? {
6822
6356
  postgres: composeServices.includes("postgres"),
6823
6357
  redis: composeServices.includes("redis"),
@@ -6827,14 +6361,14 @@ async function deployCommand(options) {
6827
6361
  redis: Boolean(composeServices.redis),
6828
6362
  rabbitmq: Boolean(composeServices.rabbitmq)
6829
6363
  } : void 0;
6830
- const setupResult = await ensureDokploySetup(config$1, dockerConfig, stage, dockerServices);
6364
+ const setupResult = await ensureDokploySetup(config, dockerConfig, stage, dockerServices);
6831
6365
  dokployConfig = setupResult.config;
6832
6366
  finalRegistry = dokployConfig.registry ?? dockerConfig.registry;
6833
6367
  if (setupResult.serviceUrls) {
6834
6368
  const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1, initStageSecrets } = await import("./storage-Cs4WBsc4.mjs");
6835
6369
  let secrets = await readStageSecrets$1(stage);
6836
6370
  if (!secrets) {
6837
- logger$3.log(` Creating secrets file for stage "${stage}"...`);
6371
+ logger$2.log(` Creating secrets file for stage "${stage}"...`);
6838
6372
  secrets = initStageSecrets(stage);
6839
6373
  }
6840
6374
  let updated = false;
@@ -6849,12 +6383,12 @@ async function deployCommand(options) {
6849
6383
  const urlKey = key;
6850
6384
  if (!secrets.urls[urlKey]) {
6851
6385
  secrets.urls[urlKey] = value;
6852
- logger$3.log(` Saved ${key} to secrets.urls`);
6386
+ logger$2.log(` Saved ${key} to secrets.urls`);
6853
6387
  updated = true;
6854
6388
  }
6855
6389
  } else if (!secrets.custom[key]) {
6856
6390
  secrets.custom[key] = value;
6857
- logger$3.log(` Saved ${key} to secrets.custom`);
6391
+ logger$2.log(` Saved ${key} to secrets.custom`);
6858
6392
  updated = true;
6859
6393
  }
6860
6394
  }
@@ -6863,14 +6397,14 @@ async function deployCommand(options) {
6863
6397
  }
6864
6398
  let masterKey;
6865
6399
  if (!skipBuild) {
6866
- logger$3.log(`\n📦 Building for production...`);
6400
+ logger$2.log(`\n📦 Building for production...`);
6867
6401
  const buildResult = await buildCommand({
6868
6402
  provider: "server",
6869
6403
  production: true,
6870
6404
  stage
6871
6405
  });
6872
6406
  masterKey = buildResult.masterKey;
6873
- } else logger$3.log(`\n⏭️ Skipping build (--skip-build)`);
6407
+ } else logger$2.log(`\n⏭️ Skipping build (--skip-build)`);
6874
6408
  let result;
6875
6409
  switch (provider) {
6876
6410
  case "docker": {
@@ -6906,8 +6440,8 @@ async function deployCommand(options) {
6906
6440
  break;
6907
6441
  }
6908
6442
  case "aws-lambda": {
6909
- logger$3.log("\n⚠️ AWS Lambda deployment is not yet implemented.");
6910
- logger$3.log(" Use SST or AWS CDK for Lambda deployments.");
6443
+ logger$2.log("\n⚠️ AWS Lambda deployment is not yet implemented.");
6444
+ logger$2.log(" Use SST or AWS CDK for Lambda deployments.");
6911
6445
  result = {
6912
6446
  imageRef,
6913
6447
  masterKey
@@ -6916,7 +6450,7 @@ async function deployCommand(options) {
6916
6450
  }
6917
6451
  default: throw new Error(`Unknown deploy provider: ${provider}\nSupported providers: docker, dokploy, aws-lambda`);
6918
6452
  }
6919
- logger$3.log("\n✅ Deployment complete!");
6453
+ logger$2.log("\n✅ Deployment complete!");
6920
6454
  return result;
6921
6455
  }
6922
6456
 
@@ -7113,22 +6647,22 @@ const GEEKMIDAS_VERSIONS = {
7113
6647
  "@geekmidas/audit": "~2.0.1",
7114
6648
  "@geekmidas/auth": "~2.0.1",
7115
6649
  "@geekmidas/cache": "~1.1.1",
7116
- "@geekmidas/client": "~5.0.0",
6650
+ "@geekmidas/client": "~6.0.0",
7117
6651
  "@geekmidas/cloud": "~1.0.1",
7118
- "@geekmidas/constructs": "~3.1.0",
6652
+ "@geekmidas/constructs": "~4.0.0",
7119
6653
  "@geekmidas/db": "~1.0.2",
7120
6654
  "@geekmidas/emailkit": "~1.0.1",
7121
6655
  "@geekmidas/envkit": "~1.0.7",
7122
6656
  "@geekmidas/errors": "~1.0.1",
7123
6657
  "@geekmidas/events": "~1.1.4",
7124
6658
  "@geekmidas/logger": "~1.0.2",
7125
- "@geekmidas/rate-limit": "~2.0.1",
6659
+ "@geekmidas/rate-limit": "~3.0.0",
7126
6660
  "@geekmidas/schema": "~1.0.2",
7127
- "@geekmidas/services": "~1.0.4",
6661
+ "@geekmidas/services": "~1.1.1",
7128
6662
  "@geekmidas/storage": "~2.0.3",
7129
6663
  "@geekmidas/studio": "~1.0.1",
7130
6664
  "@geekmidas/telescope": "~1.0.1",
7131
- "@geekmidas/testkit": "~1.0.9",
6665
+ "@geekmidas/testkit": "~2.0.0",
7132
6666
  "@geekmidas/cli": CLI_VERSION
7133
6667
  };
7134
6668
 
@@ -8961,7 +8495,7 @@ function generateWorkspaceConfig(options) {
8961
8495
  case "domain-based": return "./src/**/routes/*.ts";
8962
8496
  }
8963
8497
  };
8964
- let config$1 = `import { defineWorkspace } from '@geekmidas/cli/config';
8498
+ let config = `import { defineWorkspace } from '@geekmidas/cli/config';
8965
8499
 
8966
8500
  export default defineWorkspace({
8967
8501
  name: '${options.name}',
@@ -8974,12 +8508,12 @@ export default defineWorkspace({
8974
8508
  envParser: './src/config/env#envParser',
8975
8509
  logger: './src/config/logger#logger',
8976
8510
  dependencies: ['auth'],`;
8977
- if (telescope) config$1 += `
8511
+ if (telescope) config += `
8978
8512
  telescope: {
8979
8513
  enabled: true,
8980
8514
  path: '/__telescope',
8981
8515
  },`;
8982
- config$1 += `
8516
+ config += `
8983
8517
  openapi: {
8984
8518
  enabled: true,
8985
8519
  },
@@ -9003,33 +8537,33 @@ export default defineWorkspace({
9003
8537
  },
9004
8538
  },`;
9005
8539
  if (services.db || services.cache || services.mail || services.storage || services.events) {
9006
- config$1 += `
8540
+ config += `
9007
8541
  services: {`;
9008
- if (services.db) config$1 += `
8542
+ if (services.db) config += `
9009
8543
  db: true,`;
9010
- if (services.cache) config$1 += `
8544
+ if (services.cache) config += `
9011
8545
  cache: true,`;
9012
- if (services.mail) config$1 += `
8546
+ if (services.mail) config += `
9013
8547
  mail: true,`;
9014
- if (services.storage) config$1 += `
8548
+ if (services.storage) config += `
9015
8549
  storage: true,`;
9016
- if (services.events) config$1 += `
8550
+ if (services.events) config += `
9017
8551
  events: '${services.events}',`;
9018
- config$1 += `
8552
+ config += `
9019
8553
  },`;
9020
8554
  }
9021
- if (deployTarget === "dokploy") config$1 += `
8555
+ if (deployTarget === "dokploy") config += `
9022
8556
  deploy: {
9023
8557
  default: 'dokploy',
9024
8558
  },`;
9025
- config$1 += `
8559
+ config += `
9026
8560
  secrets: {
9027
8561
  enabled: true,
9028
8562
  },`;
9029
- config$1 += `
8563
+ config += `
9030
8564
  });
9031
8565
  `;
9032
- return config$1;
8566
+ return config;
9033
8567
  }
9034
8568
 
9035
8569
  //#endregion
@@ -12868,14 +12402,14 @@ function printNextSteps(projectName, options, pkgManager) {
12868
12402
 
12869
12403
  //#endregion
12870
12404
  //#region src/secrets/index.ts
12871
- const logger$2 = console;
12405
+ const logger$1 = console;
12872
12406
  /**
12873
12407
  * Extract service names from compose config.
12874
12408
  */
12875
12409
  function getServicesFromConfig(services) {
12876
12410
  if (!services) return [];
12877
12411
  if (Array.isArray(services)) return services;
12878
- return Object.entries(services).filter(([, config$1]) => config$1).map(([name$1]) => name$1);
12412
+ return Object.entries(services).filter(([, config]) => config).map(([name$1]) => name$1);
12879
12413
  }
12880
12414
  /**
12881
12415
  * Initialize secrets for a stage.
@@ -12884,12 +12418,12 @@ function getServicesFromConfig(services) {
12884
12418
  async function secretsInitCommand(options) {
12885
12419
  const { stage, force } = options;
12886
12420
  if (!force && secretsExist(stage)) {
12887
- logger$2.error(`Secrets already exist for stage "${stage}". Use --force to overwrite.`);
12421
+ logger$1.error(`Secrets already exist for stage "${stage}". Use --force to overwrite.`);
12888
12422
  process.exit(1);
12889
12423
  }
12890
- const config$1 = await loadConfig();
12891
- const services = getServicesFromConfig(config$1.docker?.compose?.services);
12892
- if (services.length === 0) logger$2.warn("No services configured in docker.compose.services. Creating secrets with empty services.");
12424
+ const config = await loadConfig();
12425
+ const services = getServicesFromConfig(config.docker?.compose?.services);
12426
+ if (services.length === 0) logger$1.warn("No services configured in docker.compose.services. Creating secrets with empty services.");
12893
12427
  let projectName;
12894
12428
  let workspaceSecrets;
12895
12429
  try {
@@ -12898,23 +12432,23 @@ async function secretsInitCommand(options) {
12898
12432
  const isMultiApp = Object.keys(loaded.workspace.apps).length > 1;
12899
12433
  if (isMultiApp) {
12900
12434
  workspaceSecrets = generateFullstackCustomSecrets(loaded.workspace);
12901
- logger$2.log(" Detected workspace mode — generating per-app secrets");
12435
+ logger$1.log(" Detected workspace mode — generating per-app secrets");
12902
12436
  }
12903
12437
  } catch {}
12904
12438
  const secrets = createStageSecrets(stage, services, { projectName });
12905
12439
  if (workspaceSecrets) secrets.custom = workspaceSecrets;
12906
12440
  await writeStageSecrets(secrets);
12907
- logger$2.log(`\n✓ Secrets initialized for stage "${stage}"`);
12908
- logger$2.log(` Location: .gkm/secrets/${stage}.json`);
12909
- logger$2.log("\n Generated credentials for:");
12910
- for (const service of services) logger$2.log(` - ${service}`);
12911
- if (secrets.urls.DATABASE_URL) logger$2.log(`\n DATABASE_URL: ${maskUrl(secrets.urls.DATABASE_URL)}`);
12912
- if (secrets.urls.REDIS_URL) logger$2.log(` REDIS_URL: ${maskUrl(secrets.urls.REDIS_URL)}`);
12913
- if (secrets.urls.RABBITMQ_URL) logger$2.log(` RABBITMQ_URL: ${maskUrl(secrets.urls.RABBITMQ_URL)}`);
12914
- if (secrets.urls.STORAGE_ENDPOINT) logger$2.log(` STORAGE_ENDPOINT: ${secrets.urls.STORAGE_ENDPOINT}`);
12915
- if (Object.keys(secrets.custom).length > 0) logger$2.log(`\n Custom secrets: ${Object.keys(secrets.custom).length}`);
12916
- logger$2.log(`\n Use "gkm secrets:show --stage ${stage}" to view secrets`);
12917
- logger$2.log(" Use \"gkm secrets:set <KEY> <VALUE> --stage " + stage + "\" to add custom secrets");
12441
+ logger$1.log(`\n✓ Secrets initialized for stage "${stage}"`);
12442
+ logger$1.log(` Location: .gkm/secrets/${stage}.json`);
12443
+ logger$1.log("\n Generated credentials for:");
12444
+ for (const service of services) logger$1.log(` - ${service}`);
12445
+ if (secrets.urls.DATABASE_URL) logger$1.log(`\n DATABASE_URL: ${maskUrl(secrets.urls.DATABASE_URL)}`);
12446
+ if (secrets.urls.REDIS_URL) logger$1.log(` REDIS_URL: ${maskUrl(secrets.urls.REDIS_URL)}`);
12447
+ if (secrets.urls.RABBITMQ_URL) logger$1.log(` RABBITMQ_URL: ${maskUrl(secrets.urls.RABBITMQ_URL)}`);
12448
+ if (secrets.urls.STORAGE_ENDPOINT) logger$1.log(` STORAGE_ENDPOINT: ${secrets.urls.STORAGE_ENDPOINT}`);
12449
+ if (Object.keys(secrets.custom).length > 0) logger$1.log(`\n Custom secrets: ${Object.keys(secrets.custom).length}`);
12450
+ logger$1.log(`\n Use "gkm secrets:show --stage ${stage}" to view secrets`);
12451
+ logger$1.log(" Use \"gkm secrets:set <KEY> <VALUE> --stage " + stage + "\" to add custom secrets");
12918
12452
  }
12919
12453
  /**
12920
12454
  * Read all data from stdin.
@@ -12933,21 +12467,21 @@ async function secretsSetCommand(key, value, options) {
12933
12467
  let secretValue = value;
12934
12468
  if (!secretValue) {
12935
12469
  if (process.stdin.isTTY) {
12936
- logger$2.error("No value provided. Use: gkm secrets:set KEY VALUE --stage <stage>");
12937
- logger$2.error("Or pipe from stdin: echo \"value\" | gkm secrets:set KEY --stage <stage>");
12470
+ logger$1.error("No value provided. Use: gkm secrets:set KEY VALUE --stage <stage>");
12471
+ logger$1.error("Or pipe from stdin: echo \"value\" | gkm secrets:set KEY --stage <stage>");
12938
12472
  process.exit(1);
12939
12473
  }
12940
12474
  secretValue = await readStdin();
12941
12475
  if (!secretValue) {
12942
- logger$2.error("No value received from stdin");
12476
+ logger$1.error("No value received from stdin");
12943
12477
  process.exit(1);
12944
12478
  }
12945
12479
  }
12946
12480
  try {
12947
12481
  await setCustomSecret(stage, key, secretValue);
12948
- logger$2.log(`\n✓ Secret "${key}" set for stage "${stage}"`);
12482
+ logger$1.log(`\n✓ Secret "${key}" set for stage "${stage}"`);
12949
12483
  } catch (error) {
12950
- logger$2.error(error instanceof Error ? error.message : "Failed to set secret");
12484
+ logger$1.error(error instanceof Error ? error.message : "Failed to set secret");
12951
12485
  process.exit(1);
12952
12486
  }
12953
12487
  }
@@ -12958,34 +12492,34 @@ async function secretsShowCommand(options) {
12958
12492
  const { stage, reveal } = options;
12959
12493
  const secrets = await readStageSecrets(stage);
12960
12494
  if (!secrets) {
12961
- logger$2.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
12495
+ logger$1.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
12962
12496
  process.exit(1);
12963
12497
  }
12964
- logger$2.log(`\nSecrets for stage "${stage}":`);
12965
- logger$2.log(` Created: ${secrets.createdAt}`);
12966
- logger$2.log(` Updated: ${secrets.updatedAt}`);
12967
- logger$2.log("\nService Credentials:");
12498
+ logger$1.log(`\nSecrets for stage "${stage}":`);
12499
+ logger$1.log(` Created: ${secrets.createdAt}`);
12500
+ logger$1.log(` Updated: ${secrets.updatedAt}`);
12501
+ logger$1.log("\nService Credentials:");
12968
12502
  for (const [service, creds] of Object.entries(secrets.services)) if (creds) {
12969
- logger$2.log(`\n ${service}:`);
12970
- logger$2.log(` host: ${creds.host}`);
12971
- logger$2.log(` port: ${creds.port}`);
12972
- logger$2.log(` username: ${creds.username}`);
12973
- logger$2.log(` password: ${reveal ? creds.password : maskPassword(creds.password)}`);
12974
- if (creds.database) logger$2.log(` database: ${creds.database}`);
12975
- if (creds.vhost) logger$2.log(` vhost: ${creds.vhost}`);
12976
- if (creds.bucket) logger$2.log(` bucket: ${creds.bucket}`);
12977
- }
12978
- logger$2.log("\nConnection URLs:");
12979
- if (secrets.urls.DATABASE_URL) logger$2.log(` DATABASE_URL: ${reveal ? secrets.urls.DATABASE_URL : maskUrl(secrets.urls.DATABASE_URL)}`);
12980
- if (secrets.urls.REDIS_URL) logger$2.log(` REDIS_URL: ${reveal ? secrets.urls.REDIS_URL : maskUrl(secrets.urls.REDIS_URL)}`);
12981
- if (secrets.urls.RABBITMQ_URL) logger$2.log(` RABBITMQ_URL: ${reveal ? secrets.urls.RABBITMQ_URL : maskUrl(secrets.urls.RABBITMQ_URL)}`);
12982
- if (secrets.urls.STORAGE_ENDPOINT) logger$2.log(` STORAGE_ENDPOINT: ${secrets.urls.STORAGE_ENDPOINT}`);
12503
+ logger$1.log(`\n ${service}:`);
12504
+ logger$1.log(` host: ${creds.host}`);
12505
+ logger$1.log(` port: ${creds.port}`);
12506
+ logger$1.log(` username: ${creds.username}`);
12507
+ logger$1.log(` password: ${reveal ? creds.password : maskPassword(creds.password)}`);
12508
+ if (creds.database) logger$1.log(` database: ${creds.database}`);
12509
+ if (creds.vhost) logger$1.log(` vhost: ${creds.vhost}`);
12510
+ if (creds.bucket) logger$1.log(` bucket: ${creds.bucket}`);
12511
+ }
12512
+ logger$1.log("\nConnection URLs:");
12513
+ if (secrets.urls.DATABASE_URL) logger$1.log(` DATABASE_URL: ${reveal ? secrets.urls.DATABASE_URL : maskUrl(secrets.urls.DATABASE_URL)}`);
12514
+ if (secrets.urls.REDIS_URL) logger$1.log(` REDIS_URL: ${reveal ? secrets.urls.REDIS_URL : maskUrl(secrets.urls.REDIS_URL)}`);
12515
+ if (secrets.urls.RABBITMQ_URL) logger$1.log(` RABBITMQ_URL: ${reveal ? secrets.urls.RABBITMQ_URL : maskUrl(secrets.urls.RABBITMQ_URL)}`);
12516
+ if (secrets.urls.STORAGE_ENDPOINT) logger$1.log(` STORAGE_ENDPOINT: ${secrets.urls.STORAGE_ENDPOINT}`);
12983
12517
  const customKeys = Object.keys(secrets.custom);
12984
12518
  if (customKeys.length > 0) {
12985
- logger$2.log("\nCustom Secrets:");
12986
- for (const [key, value] of Object.entries(secrets.custom)) logger$2.log(` ${key}: ${reveal ? value : maskPassword(value)}`);
12519
+ logger$1.log("\nCustom Secrets:");
12520
+ for (const [key, value] of Object.entries(secrets.custom)) logger$1.log(` ${key}: ${reveal ? value : maskPassword(value)}`);
12987
12521
  }
12988
- if (!reveal) logger$2.log("\nUse --reveal to show actual values");
12522
+ if (!reveal) logger$1.log("\nUse --reveal to show actual values");
12989
12523
  }
12990
12524
  /**
12991
12525
  * Rotate passwords for services.
@@ -12994,25 +12528,25 @@ async function secretsRotateCommand(options) {
12994
12528
  const { stage, service } = options;
12995
12529
  const secrets = await readStageSecrets(stage);
12996
12530
  if (!secrets) {
12997
- logger$2.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
12531
+ logger$1.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
12998
12532
  process.exit(1);
12999
12533
  }
13000
12534
  if (service) {
13001
12535
  if (!secrets.services[service]) {
13002
- logger$2.error(`Service "${service}" not configured in stage "${stage}"`);
12536
+ logger$1.error(`Service "${service}" not configured in stage "${stage}"`);
13003
12537
  process.exit(1);
13004
12538
  }
13005
12539
  const updated = rotateServicePassword(secrets, service);
13006
12540
  await writeStageSecrets(updated);
13007
- logger$2.log(`\n✓ Password rotated for ${service} in stage "${stage}"`);
12541
+ logger$1.log(`\n✓ Password rotated for ${service} in stage "${stage}"`);
13008
12542
  } else {
13009
12543
  let updated = secrets;
13010
12544
  const services = Object.keys(secrets.services);
13011
12545
  for (const svc of services) updated = rotateServicePassword(updated, svc);
13012
12546
  await writeStageSecrets(updated);
13013
- logger$2.log(`\n✓ Passwords rotated for all services in stage "${stage}": ${services.join(", ")}`);
12547
+ logger$1.log(`\n✓ Passwords rotated for all services in stage "${stage}": ${services.join(", ")}`);
13014
12548
  }
13015
- logger$2.log(`\nUse "gkm secrets:show --stage ${stage}" to view new values`);
12549
+ logger$1.log(`\nUse "gkm secrets:show --stage ${stage}" to view new values`);
13016
12550
  }
13017
12551
  /**
13018
12552
  * Import secrets from a JSON file.
@@ -13020,7 +12554,7 @@ async function secretsRotateCommand(options) {
13020
12554
  async function secretsImportCommand(file, options) {
13021
12555
  const { stage, merge = true } = options;
13022
12556
  if (!existsSync(file)) {
13023
- logger$2.error(`File not found: ${file}`);
12557
+ logger$1.error(`File not found: ${file}`);
13024
12558
  process.exit(1);
13025
12559
  }
13026
12560
  let importedSecrets;
@@ -13030,12 +12564,12 @@ async function secretsImportCommand(file, options) {
13030
12564
  if (typeof importedSecrets !== "object" || importedSecrets === null) throw new Error("JSON must be an object");
13031
12565
  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}`);
13032
12566
  } catch (error) {
13033
- logger$2.error(`Failed to parse JSON file: ${error instanceof Error ? error.message : "Invalid JSON"}`);
12567
+ logger$1.error(`Failed to parse JSON file: ${error instanceof Error ? error.message : "Invalid JSON"}`);
13034
12568
  process.exit(1);
13035
12569
  }
13036
12570
  const secrets = await readStageSecrets(stage);
13037
12571
  if (!secrets) {
13038
- logger$2.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
12572
+ logger$1.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
13039
12573
  process.exit(1);
13040
12574
  }
13041
12575
  const updatedCustom = merge ? {
@@ -13050,10 +12584,10 @@ async function secretsImportCommand(file, options) {
13050
12584
  await writeStageSecrets(updated);
13051
12585
  const importedCount = Object.keys(importedSecrets).length;
13052
12586
  const totalCount = Object.keys(updatedCustom).length;
13053
- logger$2.log(`\n✓ Imported ${importedCount} secrets for stage "${stage}"`);
13054
- if (merge && totalCount > importedCount) logger$2.log(` Total custom secrets: ${totalCount}`);
13055
- logger$2.log("\n Imported keys:");
13056
- for (const key of Object.keys(importedSecrets)) logger$2.log(` - ${key}`);
12587
+ logger$1.log(`\n✓ Imported ${importedCount} secrets for stage "${stage}"`);
12588
+ if (merge && totalCount > importedCount) logger$1.log(` Total custom secrets: ${totalCount}`);
12589
+ logger$1.log("\n Imported keys:");
12590
+ for (const key of Object.keys(importedSecrets)) logger$1.log(` - ${key}`);
13057
12591
  }
13058
12592
  /**
13059
12593
  * Mask password in a URL for display.
@@ -13068,264 +12602,6 @@ function maskUrl(url) {
13068
12602
  }
13069
12603
  }
13070
12604
 
13071
- //#endregion
13072
- //#region src/setup/index.ts
13073
- const logger$1 = console;
13074
- /**
13075
- * Setup development environment.
13076
- *
13077
- * Orchestrates:
13078
- * 1. Load workspace config
13079
- * 2. Resolve secrets (local → SSM → generate fresh)
13080
- * 3. Write docker/.env from secrets
13081
- * 4. Start Docker services
13082
- */
13083
- async function setupCommand(options = {}) {
13084
- const stage = options.stage ?? "development";
13085
- logger$1.log("\n🔧 Setting up development environment...\n");
13086
- let loadedConfig;
13087
- try {
13088
- loadedConfig = await loadWorkspaceConfig();
13089
- } catch {
13090
- logger$1.error("❌ No gkm.config.ts found. Run this command from a workspace root.");
13091
- process.exit(1);
13092
- }
13093
- const { workspace } = loadedConfig;
13094
- const isMultiApp = Object.keys(workspace.apps).length > 1;
13095
- logger$1.log(`📦 Workspace: ${workspace.name}`);
13096
- logger$1.log(`📱 Apps: ${Object.keys(workspace.apps).join(", ")}`);
13097
- logger$1.log(`🔑 Stage: ${stage}\n`);
13098
- const secrets = await resolveSecrets(stage, workspace, options);
13099
- if (!secrets) {
13100
- logger$1.error("❌ Failed to resolve secrets. Exiting.");
13101
- process.exit(1);
13102
- }
13103
- if (isMultiApp && workspace.services.db) {
13104
- await writeDockerEnvFromSecrets(secrets, workspace.root);
13105
- logger$1.log("📄 Generated docker/.env with database passwords");
13106
- }
13107
- if (!options.skipDocker) {
13108
- const composeFile = join(workspace.root, "docker-compose.yml");
13109
- if (existsSync(composeFile)) {
13110
- logger$1.log("");
13111
- const resolvedPorts = await resolveServicePorts(workspace.root);
13112
- await startWorkspaceServices(workspace, resolvedPorts.dockerEnv);
13113
- } else logger$1.log("⚠️ No docker-compose.yml found. Skipping Docker services.");
13114
- }
13115
- printSummary(workspace, stage);
13116
- }
13117
- /**
13118
- * Resolve secrets with priority:
13119
- * 1. Local secrets exist → use them (preserves manual additions)
13120
- * 2. SSM configured and has secrets → pull and use
13121
- * 3. Neither → generate fresh secrets
13122
- *
13123
- * --force skips checks 1 and 2 and always regenerates.
13124
- */
13125
- async function resolveSecrets(stage, workspace, options) {
13126
- if (options.force) {
13127
- logger$1.log("🔐 Generating fresh secrets (--force)...");
13128
- return generateFreshSecrets(stage, workspace, options);
13129
- }
13130
- if (secretsExist(stage, workspace.root)) {
13131
- logger$1.log("🔐 Using existing local secrets");
13132
- const secrets = await readStageSecrets(stage, workspace.root);
13133
- if (secrets) {
13134
- const reconciled = reconcileSecrets(secrets, workspace);
13135
- if (reconciled) await writeStageSecrets(reconciled, workspace.root);
13136
- return reconciled ?? secrets;
13137
- }
13138
- }
13139
- if (isSSMConfigured(workspace)) {
13140
- logger$1.log("☁️ Checking for remote secrets in SSM...");
13141
- try {
13142
- const remoteSecrets = await pullSecrets(stage, workspace);
13143
- if (remoteSecrets) {
13144
- logger$1.log("✅ Pulled secrets from SSM");
13145
- await writeStageSecrets(remoteSecrets, workspace.root);
13146
- return remoteSecrets;
13147
- }
13148
- logger$1.log(" No remote secrets found");
13149
- } catch (error) {
13150
- logger$1.warn(`⚠️ Failed to pull from SSM: ${error.message}`);
13151
- }
13152
- }
13153
- logger$1.log("🔐 Generating fresh development secrets...");
13154
- return generateFreshSecrets(stage, workspace, options);
13155
- }
13156
- /**
13157
- * Reconcile existing secrets with expected workspace-derived keys.
13158
- * Adds missing keys (e.g. BETTER_AUTH_*) without overwriting existing values.
13159
- * Returns the updated secrets if changes were made, or null if no changes needed.
13160
- * @internal Exported for testing
13161
- */
13162
- function reconcileSecrets(secrets, workspace) {
13163
- let changed = false;
13164
- let result = { ...secrets };
13165
- const serviceMap = [
13166
- {
13167
- key: "db",
13168
- name: "postgres"
13169
- },
13170
- {
13171
- key: "cache",
13172
- name: "redis"
13173
- },
13174
- {
13175
- key: "storage",
13176
- name: "minio"
13177
- },
13178
- {
13179
- key: "mail",
13180
- name: "mailpit"
13181
- }
13182
- ];
13183
- for (const { key, name: name$1 } of serviceMap) if (workspace.services[key] && !result.services[name$1]) {
13184
- const creds = generateServiceCredentials(name$1);
13185
- if (name$1 === "minio") {
13186
- creds.bucket = workspace.name;
13187
- creds.username = workspace.name;
13188
- }
13189
- result = {
13190
- ...result,
13191
- services: {
13192
- ...result.services,
13193
- [name$1]: creds
13194
- }
13195
- };
13196
- result.urls = generateConnectionUrls(result.services, result.eventsBackend);
13197
- logger$1.log(` 🔄 Adding missing service credentials: ${name$1}`);
13198
- changed = true;
13199
- }
13200
- if (result.services.postgres && !result.services.pgboss) {
13201
- result = {
13202
- ...result,
13203
- services: {
13204
- ...result.services,
13205
- pgboss: {
13206
- host: result.services.postgres.host,
13207
- port: result.services.postgres.port,
13208
- username: "pgboss",
13209
- password: generateSecurePassword(),
13210
- database: result.services.postgres.database ?? "app"
13211
- }
13212
- }
13213
- };
13214
- result.urls = generateConnectionUrls(result.services, result.eventsBackend);
13215
- logger$1.log(" 🔄 Adding missing service credentials: pgboss");
13216
- changed = true;
13217
- }
13218
- const eventsBackend = workspace.services.events;
13219
- if (eventsBackend && result.eventsBackend !== eventsBackend) {
13220
- result.eventsBackend = eventsBackend;
13221
- if (eventsBackend === "sns" && !result.services.localstack) {
13222
- result = {
13223
- ...result,
13224
- services: {
13225
- ...result.services,
13226
- localstack: generateLocalStackCredentials()
13227
- }
13228
- };
13229
- logger$1.log(" 🔄 Adding missing service credentials: localstack");
13230
- changed = true;
13231
- }
13232
- if (eventsBackend === "rabbitmq" && !result.services.rabbitmq) {
13233
- result = {
13234
- ...result,
13235
- services: {
13236
- ...result.services,
13237
- rabbitmq: generateServiceCredentials("rabbitmq")
13238
- }
13239
- };
13240
- logger$1.log(" 🔄 Adding missing service credentials: rabbitmq");
13241
- changed = true;
13242
- }
13243
- result.urls = generateConnectionUrls(result.services, eventsBackend);
13244
- changed = true;
13245
- }
13246
- const isMultiApp = Object.keys(workspace.apps).length > 1;
13247
- if (isMultiApp) {
13248
- const expected = generateFullstackCustomSecrets(workspace);
13249
- const missing = {};
13250
- for (const [key, value] of Object.entries(expected)) if (!(key in result.custom)) missing[key] = value;
13251
- if (Object.keys(missing).length > 0) {
13252
- logger$1.log(` 🔄 Adding missing secrets: ${Object.keys(missing).join(", ")}`);
13253
- result = {
13254
- ...result,
13255
- custom: {
13256
- ...result.custom,
13257
- ...missing
13258
- }
13259
- };
13260
- changed = true;
13261
- }
13262
- }
13263
- if (!changed) return null;
13264
- return {
13265
- ...result,
13266
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
13267
- };
13268
- }
13269
- /**
13270
- * Generate fresh secrets for the workspace.
13271
- */
13272
- async function generateFreshSecrets(stage, workspace, options) {
13273
- const serviceNames = [];
13274
- if (workspace.services.db) serviceNames.push("postgres");
13275
- if (workspace.services.cache) serviceNames.push("redis");
13276
- if (workspace.services.storage) serviceNames.push("minio");
13277
- if (workspace.services.mail) serviceNames.push("mailpit");
13278
- if (workspace.services.events === "sns") serviceNames.push("localstack");
13279
- if (workspace.services.events === "rabbitmq") serviceNames.push("rabbitmq");
13280
- const secrets = createStageSecrets(stage, serviceNames, {
13281
- projectName: workspace.name,
13282
- eventsBackend: workspace.services.events
13283
- });
13284
- const isMultiApp = Object.keys(workspace.apps).length > 1;
13285
- if (isMultiApp) {
13286
- const customSecrets = generateFullstackCustomSecrets(workspace);
13287
- secrets.custom = customSecrets;
13288
- } else secrets.custom = {
13289
- NODE_ENV: "development",
13290
- PORT: "3000",
13291
- LOG_LEVEL: "debug",
13292
- JWT_SECRET: `dev-${Date.now()}-${Math.random().toString(36).slice(2)}`
13293
- };
13294
- await writeStageSecrets(secrets, workspace.root);
13295
- logger$1.log(` Secrets written to .gkm/secrets/${stage}.json`);
13296
- if (isSSMConfigured(workspace) && !options.yes) {
13297
- const { shouldPush } = await prompts({
13298
- type: "confirm",
13299
- name: "shouldPush",
13300
- message: "Push secrets to SSM for team sharing?",
13301
- initial: true
13302
- });
13303
- if (shouldPush) try {
13304
- await pushSecrets(stage, workspace);
13305
- logger$1.log("☁️ Secrets pushed to SSM");
13306
- } catch (error) {
13307
- logger$1.warn(`⚠️ Failed to push to SSM: ${error.message}`);
13308
- }
13309
- }
13310
- return secrets;
13311
- }
13312
- /**
13313
- * Print setup summary with next steps.
13314
- */
13315
- function printSummary(workspace, stage) {
13316
- logger$1.log(`\n${"─".repeat(50)}`);
13317
- logger$1.log("\n✅ Development environment ready!\n");
13318
- logger$1.log("📋 Apps:");
13319
- for (const [name$1, app] of Object.entries(workspace.apps)) {
13320
- const icon = app.type === "web" ? "🌐" : app.type === "mobile" ? "📱" : "🔧";
13321
- logger$1.log(` ${icon} ${name$1} → http://localhost:${app.port}`);
13322
- }
13323
- logger$1.log("\n🚀 Next steps:");
13324
- logger$1.log(" gkm dev # Start all apps");
13325
- logger$1.log(` gkm secrets:show --stage ${stage} # View secrets`);
13326
- logger$1.log("");
13327
- }
13328
-
13329
12605
  //#endregion
13330
12606
  //#region src/test/index.ts
13331
12607
  /**
@@ -13336,6 +12612,12 @@ async function testCommand(options = {}) {
13336
12612
  const stage = options.stage ?? "development";
13337
12613
  const cwd = process.cwd();
13338
12614
  console.log(`\n🧪 Running tests with ${stage} environment...\n`);
12615
+ const autoSetup = options.autoSetup || Boolean(process.env.GKM_AUTO_SETUP);
12616
+ if (autoSetup) {
12617
+ const { ensureStageSecrets } = await import("./setup-Dh-B7YTX.mjs");
12618
+ const generated = await ensureStageSecrets(stage, cwd);
12619
+ if (generated) console.log(` 🔐 Generated fresh ${stage} secrets (auto-setup)`);
12620
+ }
13339
12621
  const defaultEnv = loadEnvFiles(".env");
13340
12622
  if (defaultEnv.loaded.length > 0) console.log(` 📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
13341
12623
  const result = await prepareEntryCredentials({
@@ -13648,7 +12930,7 @@ program.command("exec").description("Run a command with secrets injected into Cr
13648
12930
  process.exit(1);
13649
12931
  }
13650
12932
  });
13651
- program.command("test").description("Run tests with secrets loaded from environment").option("--stage <stage>", "Stage to load secrets from", "development").option("--run", "Run tests once without watch mode").option("--watch", "Enable watch mode").option("--coverage", "Generate coverage report").option("--ui", "Open Vitest UI").argument("[pattern]", "Pattern to filter tests").action(async (pattern, options) => {
12933
+ program.command("test").description("Run tests with secrets loaded from environment").option("--stage <stage>", "Stage to load secrets from", "development").option("--run", "Run tests once without watch mode").option("--watch", "Enable watch mode").option("--coverage", "Generate coverage report").option("--ui", "Open Vitest UI").option("--auto-setup", "Generate a fresh stage (secrets + key) from the workspace config when none exists (for CI; also via GKM_AUTO_SETUP)").argument("[pattern]", "Pattern to filter tests").action(async (pattern, options) => {
13652
12934
  try {
13653
12935
  const globalOptions = program.opts();
13654
12936
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
@@ -13790,8 +13072,8 @@ program.command("secrets:push").description("Push secrets to remote provider (SS
13790
13072
  const globalOptions = program.opts();
13791
13073
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
13792
13074
  const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
13793
- const { pushSecrets: pushSecrets$1 } = await import("./sync-COnAugP-.mjs");
13794
- const { reconcileMissingSecrets } = await import("./reconcile-CYGmqXvq.mjs");
13075
+ const { pushSecrets } = await import("./sync-B5UHXwRM.mjs");
13076
+ const { reconcileMissingSecrets } = await import("./reconcile-B2FoJE0a.mjs");
13795
13077
  const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-Cs4WBsc4.mjs");
13796
13078
  const { workspace } = await loadWorkspaceConfig$1();
13797
13079
  const secrets = await readStageSecrets$1(options.stage, workspace.root);
@@ -13803,7 +13085,7 @@ program.command("secrets:push").description("Push secrets to remote provider (SS
13803
13085
  for (const key of result.addedKeys) console.log(` + ${key}`);
13804
13086
  }
13805
13087
  }
13806
- await pushSecrets$1(options.stage, workspace);
13088
+ await pushSecrets(options.stage, workspace);
13807
13089
  console.log(`\n✓ Secrets pushed for stage "${options.stage}"`);
13808
13090
  } catch (error) {
13809
13091
  console.error(formatError(error));
@@ -13815,11 +13097,11 @@ program.command("secrets:pull").description("Pull secrets from remote provider (
13815
13097
  const globalOptions = program.opts();
13816
13098
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
13817
13099
  const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
13818
- const { pullSecrets: pullSecrets$1 } = await import("./sync-COnAugP-.mjs");
13100
+ const { pullSecrets } = await import("./sync-B5UHXwRM.mjs");
13819
13101
  const { writeStageSecrets: writeStageSecrets$1 } = await import("./storage-Cs4WBsc4.mjs");
13820
- const { reconcileMissingSecrets } = await import("./reconcile-CYGmqXvq.mjs");
13102
+ const { reconcileMissingSecrets } = await import("./reconcile-B2FoJE0a.mjs");
13821
13103
  const { workspace } = await loadWorkspaceConfig$1();
13822
- let secrets = await pullSecrets$1(options.stage, workspace);
13104
+ let secrets = await pullSecrets(options.stage, workspace);
13823
13105
  if (!secrets) {
13824
13106
  console.error(`No remote secrets found for stage "${options.stage}".`);
13825
13107
  process.exit(1);
@@ -13842,7 +13124,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
13842
13124
  const globalOptions = program.opts();
13843
13125
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
13844
13126
  const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
13845
- const { reconcileMissingSecrets } = await import("./reconcile-CYGmqXvq.mjs");
13127
+ const { reconcileMissingSecrets } = await import("./reconcile-B2FoJE0a.mjs");
13846
13128
  const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-Cs4WBsc4.mjs");
13847
13129
  const { workspace } = await loadWorkspaceConfig$1();
13848
13130
  const secrets = await readStageSecrets$1(options.stage, workspace.root);