@geekmidas/cli 1.10.31 → 1.10.32

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 (104) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/bin/gkm.mjs +1 -1
  3. package/dist/{CachedStateProvider-3couMAQk.cjs → CachedStateProvider-37pG1HBx.cjs} +1 -1
  4. package/dist/{CachedStateProvider-CQr31ups.mjs → CachedStateProvider-C8A-cCm5.mjs} +1 -1
  5. package/dist/{CachedStateProvider-CQr31ups.mjs.map → CachedStateProvider-C8A-cCm5.mjs.map} +1 -1
  6. package/dist/CachedStateProvider-CC0DyO09.mjs +3 -0
  7. package/dist/{CachedStateProvider-Cyn17x3x.cjs → CachedStateProvider-CxsXOKkg.cjs} +1 -1
  8. package/dist/{CachedStateProvider-Cyn17x3x.cjs.map → CachedStateProvider-CxsXOKkg.cjs.map} +1 -1
  9. package/dist/{HostingerProvider-C5oLa7N7.cjs → HostingerProvider-5KYmwoK2.cjs} +1 -1
  10. package/dist/{HostingerProvider-C5oLa7N7.cjs.map → HostingerProvider-5KYmwoK2.cjs.map} +1 -1
  11. package/dist/{HostingerProvider-YvCg3Mus.mjs → HostingerProvider-ANWchdiK.mjs} +1 -1
  12. package/dist/{HostingerProvider-YvCg3Mus.mjs.map → HostingerProvider-ANWchdiK.mjs.map} +1 -1
  13. package/dist/{LocalStateProvider-DI6n11UM.cjs → LocalStateProvider-CLifRC0Y.cjs} +1 -1
  14. package/dist/{LocalStateProvider-DI6n11UM.cjs.map → LocalStateProvider-CLifRC0Y.cjs.map} +1 -1
  15. package/dist/{LocalStateProvider-BciOhGR0.mjs → LocalStateProvider-Dp0KkRcw.mjs} +1 -1
  16. package/dist/{LocalStateProvider-BciOhGR0.mjs.map → LocalStateProvider-Dp0KkRcw.mjs.map} +1 -1
  17. package/dist/{Route53Provider-CYlDOrYO.mjs → Route53Provider-QoPgcXxn.mjs} +1 -1
  18. package/dist/{Route53Provider-CYlDOrYO.mjs.map → Route53Provider-QoPgcXxn.mjs.map} +1 -1
  19. package/dist/{Route53Provider-DISZ6E8f.cjs → Route53Provider-owQQ4pn6.cjs} +1 -1
  20. package/dist/{Route53Provider-DISZ6E8f.cjs.map → Route53Provider-owQQ4pn6.cjs.map} +1 -1
  21. package/dist/{SSMStateProvider-BljH5efc.cjs → SSMStateProvider-CT8tjl9o.cjs} +1 -1
  22. package/dist/{SSMStateProvider-BljH5efc.cjs.map → SSMStateProvider-CT8tjl9o.cjs.map} +1 -1
  23. package/dist/{SSMStateProvider-DXT1dIdI.mjs → SSMStateProvider-CksOTB8M.mjs} +1 -1
  24. package/dist/{SSMStateProvider-DXT1dIdI.mjs.map → SSMStateProvider-CksOTB8M.mjs.map} +1 -1
  25. package/dist/{backup-provisioner-CCUcj28C.mjs → backup-provisioner-BEXoHTuC.mjs} +1 -1
  26. package/dist/{backup-provisioner-CCUcj28C.mjs.map → backup-provisioner-BEXoHTuC.mjs.map} +1 -1
  27. package/dist/{backup-provisioner-CpirEvO1.cjs → backup-provisioner-C4noe75O.cjs} +1 -1
  28. package/dist/{backup-provisioner-CpirEvO1.cjs.map → backup-provisioner-C4noe75O.cjs.map} +1 -1
  29. package/dist/{bundler-CLOenWgi.cjs → bundler-BG6P249p.cjs} +2 -2
  30. package/dist/{bundler-CLOenWgi.cjs.map → bundler-BG6P249p.cjs.map} +1 -1
  31. package/dist/{bundler-E5VcXsPH.mjs → bundler-c6QvGUBM.mjs} +2 -2
  32. package/dist/{bundler-E5VcXsPH.mjs.map → bundler-c6QvGUBM.mjs.map} +1 -1
  33. package/dist/config.d.mts +2 -2
  34. package/dist/{dokploy-api-sfZFlWuE.mjs → dokploy-api-BIT0683o.mjs} +1 -1
  35. package/dist/{dokploy-api-sfZFlWuE.mjs.map → dokploy-api-BIT0683o.mjs.map} +1 -1
  36. package/dist/dokploy-api-BOx71j6F.cjs +3 -0
  37. package/dist/dokploy-api-BZGk-lkD.mjs +3 -0
  38. package/dist/{dokploy-api-CqOIKHme.cjs → dokploy-api-Dvyq-LsM.cjs} +1 -1
  39. package/dist/{dokploy-api-CqOIKHme.cjs.map → dokploy-api-Dvyq-LsM.cjs.map} +1 -1
  40. package/dist/{encryption-BVS7Vmzs.cjs → encryption-CipsS0KW.cjs} +1 -1
  41. package/dist/{encryption-CO5Q4Bhf.mjs → encryption-DSkIlEZ6.mjs} +1 -1
  42. package/dist/{encryption-CO5Q4Bhf.mjs.map → encryption-DSkIlEZ6.mjs.map} +1 -1
  43. package/dist/encryption-Db2zvGqM.mjs +3 -0
  44. package/dist/{encryption-MfXAiFTm.cjs → encryption-DgKS-Dv9.cjs} +1 -1
  45. package/dist/{encryption-MfXAiFTm.cjs.map → encryption-DgKS-Dv9.cjs.map} +1 -1
  46. package/dist/{index-C-_rW4KF.d.mts → index-Dt_dZ7K4.d.mts} +2 -2
  47. package/dist/{index-C-_rW4KF.d.mts.map → index-Dt_dZ7K4.d.mts.map} +1 -1
  48. package/dist/index.cjs +405 -81
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.mjs +381 -57
  51. package/dist/index.mjs.map +1 -1
  52. package/dist/{openapi-w-_smBTO.cjs → openapi-BQft1jm8.cjs} +36 -6
  53. package/dist/openapi-BQft1jm8.cjs.map +1 -0
  54. package/dist/{openapi-DHq5r17U.mjs → openapi-DE8b-vin.mjs} +23 -5
  55. package/dist/openapi-DE8b-vin.mjs.map +1 -0
  56. package/dist/{openapi-react-query-COpH7Mmz.mjs → openapi-react-query-C4UdILaI.mjs} +1 -1
  57. package/dist/{openapi-react-query-COpH7Mmz.mjs.map → openapi-react-query-C4UdILaI.mjs.map} +1 -1
  58. package/dist/{openapi-react-query-CxyQTTdF.cjs → openapi-react-query-DYbBq-WJ.cjs} +1 -1
  59. package/dist/{openapi-react-query-CxyQTTdF.cjs.map → openapi-react-query-DYbBq-WJ.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 -2
  63. package/dist/openapi.d.mts +1 -1
  64. package/dist/openapi.mjs +1 -2
  65. package/dist/{reconcile-C8KIy4Uy.cjs → reconcile-CZtzdrnc.cjs} +1 -1
  66. package/dist/{reconcile-C8KIy4Uy.cjs.map → reconcile-CZtzdrnc.cjs.map} +1 -1
  67. package/dist/{reconcile-D423q2QW.mjs → reconcile-DAAKa0YR.mjs} +1 -1
  68. package/dist/{reconcile-D423q2QW.mjs.map → reconcile-DAAKa0YR.mjs.map} +1 -1
  69. package/dist/{sync-fzT5WX_y.mjs → sync-COnAugP-.mjs} +1 -1
  70. package/dist/sync-D1Pa30oV.cjs +4 -0
  71. package/dist/{sync-BWY6yoUG.cjs → sync-DGXXSk2v.cjs} +1 -1
  72. package/dist/{sync-BWY6yoUG.cjs.map → sync-DGXXSk2v.cjs.map} +1 -1
  73. package/dist/{sync-Dc-QA4Mx.mjs → sync-D_NowTkZ.mjs} +1 -1
  74. package/dist/{sync-Dc-QA4Mx.mjs.map → sync-D_NowTkZ.mjs.map} +1 -1
  75. package/dist/{types-BqAbYt5a.d.mts → types-OszPdw9m.d.mts} +1 -1
  76. package/dist/{types-BqAbYt5a.d.mts.map → types-OszPdw9m.d.mts.map} +1 -1
  77. package/dist/workspace/index.d.mts +2 -2
  78. package/package.json +3 -3
  79. package/src/build/index.ts +5 -47
  80. package/src/build/types.ts +5 -0
  81. package/src/deploy/__tests__/index.spec.ts +1 -3
  82. package/src/generators/CronGenerator.ts +3 -1
  83. package/src/generators/EndpointGenerator.ts +6 -2
  84. package/src/generators/FunctionGenerator.ts +3 -1
  85. package/src/generators/SubscriberGenerator.ts +3 -1
  86. package/src/init/generators/docker.ts +2 -2
  87. package/src/init/versions.ts +1 -1
  88. package/dist/CachedStateProvider-C4QqvlPE.mjs +0 -3
  89. package/dist/client-generator-CUVVtAOo.mjs +0 -23
  90. package/dist/client-generator-CUVVtAOo.mjs.map +0 -1
  91. package/dist/client-generator-D-T4ypQo.cjs +0 -35
  92. package/dist/client-generator-D-T4ypQo.cjs.map +0 -1
  93. package/dist/dokploy-api-BPYkG-ZZ.cjs +0 -3
  94. package/dist/dokploy-api-BiSzWM4v.mjs +0 -3
  95. package/dist/encryption-Bd_m4q3g.mjs +0 -3
  96. package/dist/openapi-DHq5r17U.mjs.map +0 -1
  97. package/dist/openapi-w-_smBTO.cjs.map +0 -1
  98. package/dist/sniffer-BqSVVrWA.mjs +0 -356
  99. package/dist/sniffer-BqSVVrWA.mjs.map +0 -1
  100. package/dist/sniffer-CBhzByiY.cjs +0 -386
  101. package/dist/sniffer-CBhzByiY.cjs.map +0 -1
  102. package/dist/sniffer-Cpq_cbyz.mjs +0 -4
  103. package/dist/sniffer-eZ13G10M.cjs +0 -4
  104. package/dist/sync-B2CN_KS5.cjs +0 -4
package/dist/index.mjs CHANGED
@@ -5,14 +5,12 @@ import { getAppNameFromCwd, loadAppConfig, loadConfig, loadWorkspaceAppInfo, loa
5
5
  import { getCredentialsPath, getDokployCredentials, getDokployRegistryId, getDokployToken, removeDokployCredentials, storeDokployCredentials, storeDokployRegistryId } from "./credentials-s1kLcIzK.mjs";
6
6
  import { createStageSecrets, generateConnectionUrls, generateDbPassword, generateDbUrl, generateFullstackCustomSecrets, generateLocalStackCredentials, generatePgBossUrl, generateSecurePassword, generateServiceCredentials, rotateServicePassword, writeDockerEnvFromSecrets } from "./fullstack-secrets-P84v8zWn.mjs";
7
7
  import { getKeyPath, maskPassword, readStageSecrets, secretsExist, setCustomSecret, toEmbeddableSecrets, writeStageSecrets } from "./storage-dbb9RyBl.mjs";
8
- import { isPartitionedRoutes } from "./client-generator-CUVVtAOo.mjs";
9
- import { ConstructGenerator, EndpointGenerator, OPENAPI_OUTPUT_PATH, generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi-DHq5r17U.mjs";
10
- import { DokployApi } from "./dokploy-api-sfZFlWuE.mjs";
11
- import { encryptSecrets } from "./encryption-CO5Q4Bhf.mjs";
12
- import { sniffAllApps, sniffAppEnvironment } from "./sniffer-BqSVVrWA.mjs";
13
- import { CachedStateProvider } from "./CachedStateProvider-CQr31ups.mjs";
14
- import { generateReactQueryCommand } from "./openapi-react-query-COpH7Mmz.mjs";
15
- import { isSSMConfigured, pullSecrets, pushSecrets } from "./sync-Dc-QA4Mx.mjs";
8
+ import { ConstructGenerator, EndpointGenerator, OPENAPI_OUTPUT_PATH, generateOpenApi, isPartitionedRoutes, normalizeRoutes, openapiCommand, resolveOpenApiConfig } from "./openapi-DE8b-vin.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";
16
14
  import { createRequire } from "node:module";
17
15
  import { copyFileSync, existsSync, readFileSync, unlinkSync } from "node:fs";
18
16
  import { basename, dirname, join, parse, relative, resolve } from "node:path";
@@ -32,11 +30,12 @@ import { Function } from "@geekmidas/constructs/functions";
32
30
  import { Subscriber } from "@geekmidas/constructs/subscribers";
33
31
  import { Client } from "pg";
34
32
  import { lookup } from "node:dns/promises";
33
+ import { fileURLToPath, pathToFileURL } from "node:url";
35
34
  import prompts from "prompts";
36
35
 
37
36
  //#region package.json
38
37
  var name = "@geekmidas/cli";
39
- var version = "1.10.30";
38
+ var version = "1.10.31";
40
39
  var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
41
40
  var private$1 = false;
42
41
  var type = "module";
@@ -139,7 +138,7 @@ const logger$14 = console;
139
138
  * Validate Dokploy token by making a test API call
140
139
  */
141
140
  async function validateDokployToken(endpoint, token) {
142
- const { DokployApi: DokployApi$1 } = await import("./dokploy-api-BiSzWM4v.mjs");
141
+ const { DokployApi: DokployApi$1 } = await import("./dokploy-api-BZGk-lkD.mjs");
143
142
  const api = new DokployApi$1({
144
143
  baseUrl: endpoint,
145
144
  token
@@ -826,7 +825,7 @@ var CronGenerator = class extends ConstructGenerator {
826
825
  schedule: construct.schedule || "rate(1 hour)",
827
826
  timeout: construct.timeout,
828
827
  memorySize: construct.memorySize,
829
- environment: await construct.getEnvironment()
828
+ environment: await construct.getEnvironment({ markOptional: context.markOptional })
830
829
  });
831
830
  logger$15.log(`Generated cron handler: ${key}`);
832
831
  }
@@ -876,7 +875,7 @@ var FunctionGenerator = class extends ConstructGenerator {
876
875
  handler: relative(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
877
876
  timeout: construct.timeout,
878
877
  memorySize: construct.memorySize,
879
- environment: await construct.getEnvironment()
878
+ environment: await construct.getEnvironment({ markOptional: context.markOptional })
880
879
  });
881
880
  logger$15.log(`Generated function handler: ${key}`);
882
881
  }
@@ -930,7 +929,7 @@ var SubscriberGenerator = class extends ConstructGenerator {
930
929
  subscribedEvents: construct.subscribedEvents || [],
931
930
  timeout: construct.timeout,
932
931
  memorySize: construct.memorySize,
933
- environment: await construct.getEnvironment()
932
+ environment: await construct.getEnvironment({ markOptional: context.markOptional })
934
933
  });
935
934
  logger$15.log(`Generated subscriber handler: ${key}`);
936
935
  }
@@ -2181,7 +2180,8 @@ async function buildCommand(options) {
2181
2180
  studio,
2182
2181
  hooks,
2183
2182
  production,
2184
- dockerServices
2183
+ dockerServices,
2184
+ markOptional: options.markOptional ?? false
2185
2185
  };
2186
2186
  const endpointGenerator = new EndpointGenerator();
2187
2187
  const functionGenerator = new FunctionGenerator();
@@ -2203,25 +2203,19 @@ async function buildCommand(options) {
2203
2203
  }
2204
2204
  const rootOutputDir = join(process.cwd(), ".gkm");
2205
2205
  await mkdir(rootOutputDir, { recursive: true });
2206
- let optionalVarSet;
2207
- if (options.markOptional && config$1.envParser) try {
2208
- const { _sniffEnvParser } = await import("./sniffer-Cpq_cbyz.mjs");
2209
- const sniffed = await _sniffEnvParser(config$1.envParser, process.cwd(), process.cwd());
2210
- if (sniffed.optionalEnvVars.length > 0) optionalVarSet = new Set(sniffed.optionalEnvVars);
2211
- } catch {}
2212
2206
  let result = {};
2213
2207
  for (const provider of resolved.providers) {
2214
- const providerResult = await buildForProvider(provider, buildContext, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, allEndpoints, allFunctions, allCrons, allSubscribers, resolved.enableOpenApi, options.skipBundle ?? false, options.stage, optionalVarSet);
2208
+ const providerResult = await buildForProvider(provider, buildContext, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, allEndpoints, allFunctions, allCrons, allSubscribers, resolved.enableOpenApi, options.skipBundle ?? false, options.stage);
2215
2209
  if (providerResult.masterKey) result = providerResult;
2216
2210
  }
2217
2211
  await generateOpenApi(config$1, { bustCache: true });
2218
2212
  return result;
2219
2213
  }
2220
- async function buildForProvider(provider, context, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, endpoints, functions, crons, subscribers, enableOpenApi, skipBundle, stage, optionalVarSet) {
2214
+ async function buildForProvider(provider, context, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, endpoints, functions, crons, subscribers, enableOpenApi, skipBundle, stage) {
2221
2215
  const outputDir = join(process.cwd(), ".gkm", provider);
2222
2216
  await mkdir(outputDir, { recursive: true });
2223
2217
  logger$9.log(`\nGenerating handlers for provider: ${provider}`);
2224
- const [rawRoutes, rawFunctions, rawCrons, rawSubscribers] = await Promise.all([
2218
+ const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all([
2225
2219
  endpointGenerator.build(context, endpoints, outputDir, {
2226
2220
  provider,
2227
2221
  enableOpenApi
@@ -2230,23 +2224,6 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2230
2224
  cronGenerator.build(context, crons, outputDir, { provider }),
2231
2225
  subscriberGenerator.build(context, subscribers, outputDir, { provider })
2232
2226
  ]);
2233
- const markEnv = optionalVarSet ? (vars) => vars?.map((v) => optionalVarSet.has(v) ? `${v}?` : v) : (vars) => vars;
2234
- const routes = rawRoutes.map((r) => ({
2235
- ...r,
2236
- environment: markEnv(r.environment)
2237
- }));
2238
- const functionInfos = rawFunctions.map((f) => ({
2239
- ...f,
2240
- environment: markEnv(f.environment)
2241
- }));
2242
- const cronInfos = rawCrons.map((c) => ({
2243
- ...c,
2244
- environment: markEnv(c.environment)
2245
- }));
2246
- const subscriberInfos = rawSubscribers.map((s) => ({
2247
- ...s,
2248
- environment: markEnv(s.environment)
2249
- }));
2250
2227
  logger$9.log(`Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`);
2251
2228
  const manifestRoutes = assembleManifestField(routes, endpoints);
2252
2229
  const manifestFunctions = assembleManifestField(functionInfos, functions);
@@ -2268,7 +2245,7 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2268
2245
  let masterKey;
2269
2246
  if (context.production?.bundle && !skipBundle) {
2270
2247
  logger$9.log(`\n📦 Bundling production server...`);
2271
- const { bundleServer } = await import("./bundler-E5VcXsPH.mjs");
2248
+ const { bundleServer } = await import("./bundler-c6QvGUBM.mjs");
2272
2249
  const allConstructs = [
2273
2250
  ...endpoints.map((e) => e.construct),
2274
2251
  ...functions.map((f) => f.construct),
@@ -2595,11 +2572,11 @@ async function createDnsProvider(options) {
2595
2572
  if (isDnsProvider(config$1.provider)) return config$1.provider;
2596
2573
  const provider = config$1.provider;
2597
2574
  if (provider === "hostinger") {
2598
- const { HostingerProvider } = await import("./HostingerProvider-YvCg3Mus.mjs");
2575
+ const { HostingerProvider } = await import("./HostingerProvider-ANWchdiK.mjs");
2599
2576
  return new HostingerProvider();
2600
2577
  }
2601
2578
  if (provider === "route53") {
2602
- const { Route53Provider } = await import("./Route53Provider-CYlDOrYO.mjs");
2579
+ const { Route53Provider } = await import("./Route53Provider-QoPgcXxn.mjs");
2603
2580
  const route53Config = config$1;
2604
2581
  return new Route53Provider({
2605
2582
  region: route53Config.region,
@@ -5070,20 +5047,20 @@ function isStateProvider(value) {
5070
5047
  async function createStateProvider(options) {
5071
5048
  const { config: config$1, workspaceRoot, workspaceName } = options;
5072
5049
  if (!config$1) {
5073
- const { LocalStateProvider } = await import("./LocalStateProvider-BciOhGR0.mjs");
5050
+ const { LocalStateProvider } = await import("./LocalStateProvider-Dp0KkRcw.mjs");
5074
5051
  return new LocalStateProvider(workspaceRoot);
5075
5052
  }
5076
5053
  if (isStateProvider(config$1.provider)) return config$1.provider;
5077
5054
  const provider = config$1.provider;
5078
5055
  if (provider === "local") {
5079
- const { LocalStateProvider } = await import("./LocalStateProvider-BciOhGR0.mjs");
5056
+ const { LocalStateProvider } = await import("./LocalStateProvider-Dp0KkRcw.mjs");
5080
5057
  return new LocalStateProvider(workspaceRoot);
5081
5058
  }
5082
5059
  if (provider === "ssm") {
5083
5060
  if (!workspaceName) throw new Error("Workspace name is required for SSM state provider. Set \"name\" in gkm.config.ts.");
5084
- const { LocalStateProvider } = await import("./LocalStateProvider-BciOhGR0.mjs");
5085
- const { SSMStateProvider } = await import("./SSMStateProvider-DXT1dIdI.mjs");
5086
- const { CachedStateProvider: CachedStateProvider$1 } = await import("./CachedStateProvider-C4QqvlPE.mjs");
5061
+ const { LocalStateProvider } = await import("./LocalStateProvider-Dp0KkRcw.mjs");
5062
+ const { SSMStateProvider } = await import("./SSMStateProvider-CksOTB8M.mjs");
5063
+ const { CachedStateProvider: CachedStateProvider$1 } = await import("./CachedStateProvider-CC0DyO09.mjs");
5087
5064
  const ssmConfig = config$1;
5088
5065
  const local = new LocalStateProvider(workspaceRoot);
5089
5066
  const ssm = SSMStateProvider.create({
@@ -5193,6 +5170,353 @@ function generateSecretsReport(encryptedApps, sniffedApps) {
5193
5170
  };
5194
5171
  }
5195
5172
 
5173
+ //#endregion
5174
+ //#region src/deploy/sniffer.ts
5175
+ const __filename = fileURLToPath(import.meta.url);
5176
+ const __dirname = dirname(__filename);
5177
+ /**
5178
+ * Resolve the tsx package path from the CLI package's dependencies.
5179
+ * This ensures tsx is available regardless of whether the target project has it installed.
5180
+ */
5181
+ function resolveTsxPath() {
5182
+ const require$2 = createRequire(import.meta.url);
5183
+ return require$2.resolve("tsx");
5184
+ }
5185
+ /**
5186
+ * Resolve the path to a sniffer helper file.
5187
+ * Handles both dev (.ts with tsx) and production (.mjs from dist).
5188
+ *
5189
+ * In production: sniffer.ts is bundled into dist/index.mjs, but sniffer helper
5190
+ * files are output to dist/deploy/ as standalone modules for subprocess loading.
5191
+ *
5192
+ * In development: All files are in src/deploy/ and loaded via tsx.
5193
+ */
5194
+ function resolveSnifferFile(baseName) {
5195
+ const deployMjsPath = resolve(__dirname, "deploy", `${baseName}.mjs`);
5196
+ if (existsSync(deployMjsPath)) return deployMjsPath;
5197
+ const mjsPath = resolve(__dirname, `${baseName}.mjs`);
5198
+ if (existsSync(mjsPath)) return mjsPath;
5199
+ const tsPath = resolve(__dirname, `${baseName}.ts`);
5200
+ if (existsSync(tsPath)) return tsPath;
5201
+ return tsPath;
5202
+ }
5203
+ /**
5204
+ * Get required environment variables for an app.
5205
+ *
5206
+ * Detection strategy (in order):
5207
+ * 1. Frontend apps: Returns empty (no server secrets)
5208
+ * 2. Apps with `requiredEnv`: Uses explicit list from config
5209
+ * 3. Entry apps: Imports entry file in subprocess to capture config.parse() calls
5210
+ * 4. Route-based apps: Loads route files and calls getEnvironment() on each construct
5211
+ * 5. Apps with `envParser` (no routes): Runs SnifferEnvironmentParser to detect usage
5212
+ * 6. Apps with neither: Returns empty
5213
+ *
5214
+ * This function handles "fire and forget" async operations gracefully,
5215
+ * capturing errors and unhandled rejections without failing the build.
5216
+ *
5217
+ * @param app - The normalized app configuration
5218
+ * @param appName - The name of the app
5219
+ * @param workspacePath - Absolute path to the workspace root
5220
+ * @param options - Optional configuration for sniffing behavior
5221
+ * @returns The sniffed environment with required variables
5222
+ */
5223
+ async function sniffAppEnvironment(app, appName, workspacePath, options = {}) {
5224
+ const { logWarnings = true, markOptional = false } = options;
5225
+ if (app.type === "frontend") {
5226
+ const depVars = (app.dependencies ?? []).map((dep) => `NEXT_PUBLIC_${dep.toUpperCase()}_URL`);
5227
+ if (app.config) {
5228
+ const sniffedVars = [];
5229
+ const sniffedOptional = [];
5230
+ const configPaths = [];
5231
+ if (app.config.client) configPaths.push(app.config.client);
5232
+ if (app.config.server) configPaths.push(app.config.server);
5233
+ for (const configPath of configPaths) {
5234
+ const result = await sniffEntryFile(configPath, app.path, workspacePath);
5235
+ if (logWarnings && result.error) console.warn(`[sniffer] ${appName}: Config file "${configPath}" threw error during sniffing (env vars still captured): ${result.error.message}`);
5236
+ sniffedVars.push(...result.envVars);
5237
+ sniffedOptional.push(...result.optionalEnvVars);
5238
+ }
5239
+ const optionalEnvVars = [...new Set(sniffedOptional)];
5240
+ const allVars = applyMarkOptional([...new Set([...depVars, ...sniffedVars])], optionalEnvVars, markOptional);
5241
+ return {
5242
+ appName,
5243
+ requiredEnvVars: allVars,
5244
+ optionalEnvVars
5245
+ };
5246
+ }
5247
+ return {
5248
+ appName,
5249
+ requiredEnvVars: depVars,
5250
+ optionalEnvVars: []
5251
+ };
5252
+ }
5253
+ if (app.entry) {
5254
+ const result = await sniffEntryFile(app.entry, app.path, workspacePath);
5255
+ if (logWarnings && result.error) console.warn(`[sniffer] ${appName}: Entry file threw error during sniffing (env vars still captured): ${result.error.message}`);
5256
+ return {
5257
+ appName,
5258
+ requiredEnvVars: applyMarkOptional(result.envVars, result.optionalEnvVars, markOptional),
5259
+ optionalEnvVars: result.optionalEnvVars
5260
+ };
5261
+ }
5262
+ if (app.routes) {
5263
+ const result = await sniffRouteFiles(normalizeRoutes(app.routes), app.path, workspacePath);
5264
+ if (logWarnings && result.error) console.warn(`[sniffer] ${appName}: Route sniffing threw error (env vars still captured): ${result.error.message}`);
5265
+ return {
5266
+ appName,
5267
+ requiredEnvVars: applyMarkOptional(result.envVars, result.optionalEnvVars, markOptional),
5268
+ optionalEnvVars: result.optionalEnvVars
5269
+ };
5270
+ }
5271
+ if (app.envParser) {
5272
+ const result = await sniffEnvParser(app.envParser, app.path, workspacePath);
5273
+ if (logWarnings) {
5274
+ if (result.error) console.warn(`[sniffer] ${appName}: envParser threw error during sniffing (env vars still captured): ${result.error.message}`);
5275
+ if (result.unhandledRejections.length > 0) console.warn(`[sniffer] ${appName}: Fire-and-forget rejections during sniffing (suppressed): ${result.unhandledRejections.map((e) => e.message).join(", ")}`);
5276
+ }
5277
+ return {
5278
+ appName,
5279
+ requiredEnvVars: applyMarkOptional(result.envVars, result.optionalEnvVars, markOptional),
5280
+ optionalEnvVars: result.optionalEnvVars
5281
+ };
5282
+ }
5283
+ return {
5284
+ appName,
5285
+ requiredEnvVars: [],
5286
+ optionalEnvVars: []
5287
+ };
5288
+ }
5289
+ /**
5290
+ * Apply the `?` suffix to optional variables in an env var list.
5291
+ * Only modifies the list when `markOptional` is true and there are optional vars.
5292
+ */
5293
+ function applyMarkOptional(envVars, optionalEnvVars, markOptional) {
5294
+ if (!markOptional || optionalEnvVars.length === 0) return envVars;
5295
+ const optionalSet = new Set(optionalEnvVars);
5296
+ return envVars.map((v) => optionalSet.has(v) ? `${v}?` : v);
5297
+ }
5298
+ /**
5299
+ * Sniff an entry file by importing it in a subprocess.
5300
+ *
5301
+ * Entry apps call `config.parse()` at module load time. To capture which
5302
+ * env vars are accessed, we:
5303
+ * 1. Spawn a subprocess with a module loader hook
5304
+ * 2. The loader intercepts `@geekmidas/envkit` and replaces EnvironmentParser
5305
+ * with SnifferEnvironmentParser
5306
+ * 3. Import the entry file (triggers config.parse())
5307
+ * 4. Capture and return the accessed env var names
5308
+ *
5309
+ * This approach provides process isolation - each app is sniffed in its own
5310
+ * subprocess, preventing module cache pollution.
5311
+ *
5312
+ * @param entryPath - Relative path to the entry file (e.g., './src/index.ts')
5313
+ * @param appPath - The app's path relative to workspace (e.g., 'apps/auth')
5314
+ * @param workspacePath - Absolute path to workspace root
5315
+ * @returns EntrySniffResult with env vars and optional error
5316
+ */
5317
+ async function sniffEntryFile(entryPath, appPath, workspacePath) {
5318
+ const fullEntryPath = resolve(workspacePath, appPath, entryPath);
5319
+ const loaderPath = resolveSnifferFile("sniffer-loader");
5320
+ const workerPath = resolveSnifferFile("sniffer-worker");
5321
+ return new Promise((resolvePromise) => {
5322
+ const child = spawn("node", [
5323
+ "--import",
5324
+ loaderPath,
5325
+ workerPath,
5326
+ fullEntryPath
5327
+ ], {
5328
+ cwd: resolve(workspacePath, appPath),
5329
+ stdio: [
5330
+ "ignore",
5331
+ "pipe",
5332
+ "pipe"
5333
+ ],
5334
+ env: {
5335
+ ...process.env,
5336
+ NODE_OPTIONS: "--import=tsx"
5337
+ }
5338
+ });
5339
+ let stdout$1 = "";
5340
+ let stderr = "";
5341
+ child.stdout.on("data", (data) => {
5342
+ stdout$1 += data.toString();
5343
+ });
5344
+ child.stderr.on("data", (data) => {
5345
+ stderr += data.toString();
5346
+ });
5347
+ child.on("close", (code) => {
5348
+ try {
5349
+ const jsonMatch = stdout$1.match(/\{[^{}]*"envVars"[^{}]*\}[^{]*$/);
5350
+ if (jsonMatch) {
5351
+ const result = JSON.parse(jsonMatch[0]);
5352
+ resolvePromise({
5353
+ envVars: result.envVars || [],
5354
+ optionalEnvVars: result.optionalEnvVars || [],
5355
+ error: result.error ? new Error(result.error) : void 0
5356
+ });
5357
+ return;
5358
+ }
5359
+ } catch {}
5360
+ resolvePromise({
5361
+ envVars: [],
5362
+ optionalEnvVars: [],
5363
+ error: new Error(`Failed to sniff entry file (exit code ${code}): ${stderr || stdout$1 || "No output"}`)
5364
+ });
5365
+ });
5366
+ child.on("error", (err) => {
5367
+ resolvePromise({
5368
+ envVars: [],
5369
+ optionalEnvVars: [],
5370
+ error: err
5371
+ });
5372
+ });
5373
+ });
5374
+ }
5375
+ /**
5376
+ * Sniff route files by loading constructs and calling getEnvironment().
5377
+ *
5378
+ * Route-based apps have endpoints, functions, crons, and subscribers that
5379
+ * use services. Each service's register() method accesses environment variables.
5380
+ *
5381
+ * This runs in a subprocess with tsx loader to properly handle TypeScript
5382
+ * compilation and path alias resolution (e.g., `src/...` imports).
5383
+ *
5384
+ * @param routes - Glob pattern(s) for route files
5385
+ * @param appPath - The app's path relative to workspace (e.g., 'apps/api')
5386
+ * @param workspacePath - Absolute path to workspace root
5387
+ * @returns EntrySniffResult with env vars and optional error
5388
+ */
5389
+ async function sniffRouteFiles(routes, appPath, workspacePath) {
5390
+ const fullAppPath = resolve(workspacePath, appPath);
5391
+ const workerPath = resolveSnifferFile("sniffer-routes-worker");
5392
+ const tsxPath = resolveTsxPath();
5393
+ const routesArray = Array.isArray(routes) ? routes : [routes];
5394
+ const pattern = routesArray[0];
5395
+ if (!pattern) return {
5396
+ envVars: [],
5397
+ optionalEnvVars: [],
5398
+ error: new Error("No route patterns provided")
5399
+ };
5400
+ return new Promise((resolvePromise) => {
5401
+ const child = spawn("node", [
5402
+ "--import",
5403
+ tsxPath,
5404
+ workerPath,
5405
+ fullAppPath,
5406
+ pattern
5407
+ ], {
5408
+ cwd: fullAppPath,
5409
+ stdio: [
5410
+ "ignore",
5411
+ "pipe",
5412
+ "pipe"
5413
+ ],
5414
+ env: { ...process.env }
5415
+ });
5416
+ let stdout$1 = "";
5417
+ let stderr = "";
5418
+ child.stdout.on("data", (data) => {
5419
+ stdout$1 += data.toString();
5420
+ });
5421
+ child.stderr.on("data", (data) => {
5422
+ stderr += data.toString();
5423
+ });
5424
+ child.on("close", (code) => {
5425
+ if (stderr) stderr.split("\n").filter((line) => line.trim()).forEach((line) => console.warn(line));
5426
+ try {
5427
+ const jsonMatch = stdout$1.match(/\{[^{}]*"envVars"[^{}]*\}[^{]*$/);
5428
+ if (jsonMatch) {
5429
+ const result = JSON.parse(jsonMatch[0]);
5430
+ resolvePromise({
5431
+ envVars: result.envVars || [],
5432
+ optionalEnvVars: result.optionalEnvVars || [],
5433
+ error: result.error ? new Error(result.error) : void 0
5434
+ });
5435
+ return;
5436
+ }
5437
+ } catch {}
5438
+ resolvePromise({
5439
+ envVars: [],
5440
+ optionalEnvVars: [],
5441
+ error: new Error(`Failed to sniff route files (exit code ${code}): ${stderr || stdout$1 || "No output"}`)
5442
+ });
5443
+ });
5444
+ child.on("error", (err) => {
5445
+ resolvePromise({
5446
+ envVars: [],
5447
+ optionalEnvVars: [],
5448
+ error: err
5449
+ });
5450
+ });
5451
+ });
5452
+ }
5453
+ /**
5454
+ * Run the SnifferEnvironmentParser on an envParser module to detect
5455
+ * which environment variables it accesses.
5456
+ *
5457
+ * This function handles "fire and forget" async operations by using
5458
+ * the shared sniffWithFireAndForget utility from @geekmidas/envkit.
5459
+ *
5460
+ * @param envParserPath - The envParser config (e.g., './src/config/env#envParser')
5461
+ * @param appPath - The app's path relative to workspace
5462
+ * @param workspacePath - Absolute path to workspace root
5463
+ * @returns SniffResult with env vars and any errors encountered
5464
+ */
5465
+ async function sniffEnvParser(envParserPath, appPath, workspacePath) {
5466
+ const [modulePath, exportName = "default"] = envParserPath.split("#");
5467
+ if (!modulePath) return {
5468
+ envVars: [],
5469
+ optionalEnvVars: [],
5470
+ unhandledRejections: []
5471
+ };
5472
+ const fullPath = resolve(workspacePath, appPath, modulePath);
5473
+ let SnifferEnvironmentParser;
5474
+ let sniffWithFireAndForget;
5475
+ try {
5476
+ const envkitModule = await import("@geekmidas/envkit/sniffer");
5477
+ SnifferEnvironmentParser = envkitModule.SnifferEnvironmentParser;
5478
+ sniffWithFireAndForget = envkitModule.sniffWithFireAndForget;
5479
+ } catch (error) {
5480
+ const message = error instanceof Error ? error.message : String(error);
5481
+ console.warn(`[sniffer] Failed to import SnifferEnvironmentParser: ${message}`);
5482
+ return {
5483
+ envVars: [],
5484
+ optionalEnvVars: [],
5485
+ unhandledRejections: []
5486
+ };
5487
+ }
5488
+ const sniffer = new SnifferEnvironmentParser();
5489
+ return sniffWithFireAndForget(sniffer, async () => {
5490
+ const moduleUrl = pathToFileURL(fullPath).href;
5491
+ const module = await import(moduleUrl);
5492
+ const envParser = module[exportName];
5493
+ if (typeof envParser !== "function") {
5494
+ console.warn(`[sniffer] Export "${exportName}" from "${modulePath}" is not a function`);
5495
+ return;
5496
+ }
5497
+ const result = envParser(sniffer);
5498
+ if (result && typeof result.parse === "function") try {
5499
+ result.parse();
5500
+ } catch {}
5501
+ });
5502
+ }
5503
+ /**
5504
+ * Sniff environment requirements for multiple apps.
5505
+ *
5506
+ * @param apps - Map of app name to app config
5507
+ * @param workspacePath - Absolute path to workspace root
5508
+ * @param options - Optional configuration for sniffing behavior
5509
+ * @returns Map of app name to sniffed environment
5510
+ */
5511
+ async function sniffAllApps(apps, workspacePath, options = {}) {
5512
+ const results = /* @__PURE__ */ new Map();
5513
+ for (const [appName, app] of Object.entries(apps)) {
5514
+ const sniffed = await sniffAppEnvironment(app, appName, workspacePath, options);
5515
+ results.set(appName, sniffed);
5516
+ }
5517
+ return results;
5518
+ }
5519
+
5196
5520
  //#endregion
5197
5521
  //#region src/deploy/index.ts
5198
5522
  const logger$3 = console;
@@ -5862,7 +6186,7 @@ async function workspaceDeployCommand(workspace, options) {
5862
6186
  }
5863
6187
  if (workspace.deploy?.backups && provisionedPostgres) {
5864
6188
  logger$3.log("\n💾 Provisioning backup destination...");
5865
- const { provisionBackupDestination } = await import("./backup-provisioner-CCUcj28C.mjs");
6189
+ const { provisionBackupDestination } = await import("./backup-provisioner-BEXoHTuC.mjs");
5866
6190
  const backupState = await provisionBackupDestination({
5867
6191
  api,
5868
6192
  projectId: project.projectId,
@@ -6517,7 +6841,7 @@ const GEEKMIDAS_VERSIONS = {
6517
6841
  "@geekmidas/constructs": "~3.0.7",
6518
6842
  "@geekmidas/db": "~1.0.1",
6519
6843
  "@geekmidas/emailkit": "~1.0.0",
6520
- "@geekmidas/envkit": "~1.0.4",
6844
+ "@geekmidas/envkit": "~1.0.5",
6521
6845
  "@geekmidas/errors": "~1.0.0",
6522
6846
  "@geekmidas/events": "~1.1.0",
6523
6847
  "@geekmidas/logger": "~1.0.0",
@@ -7162,7 +7486,7 @@ ${volumes.join("\n")}
7162
7486
  /**
7163
7487
  * Generate .env file for docker-compose with database passwords
7164
7488
  */
7165
- function generateDockerEnv(apps, eventsBackend) {
7489
+ function generateDockerEnv(apps, _eventsBackend) {
7166
7490
  const envVars = apps.map((app) => {
7167
7491
  const envVar = `${app.name.toUpperCase()}_DB_PASSWORD`;
7168
7492
  return `${envVar}=${app.password}`;
@@ -7181,7 +7505,7 @@ ${envVars.join("\n")}
7181
7505
  * - auth user: uses auth schema with search_path=auth
7182
7506
  * - pgboss user: uses pgboss schema (when events === 'pgboss')
7183
7507
  */
7184
- function generatePostgresInitScript(apps, eventsBackend) {
7508
+ function generatePostgresInitScript(apps, _eventsBackend) {
7185
7509
  const userCreations = apps.map((app) => {
7186
7510
  const userName = app.name.replace(/-/g, "_");
7187
7511
  const envVar = `${app.name.toUpperCase()}_DB_PASSWORD`;
@@ -12151,8 +12475,8 @@ program.command("secrets:push").description("Push secrets to remote provider (SS
12151
12475
  const globalOptions = program.opts();
12152
12476
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
12153
12477
  const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
12154
- const { pushSecrets: pushSecrets$1 } = await import("./sync-fzT5WX_y.mjs");
12155
- const { reconcileMissingSecrets } = await import("./reconcile-D423q2QW.mjs");
12478
+ const { pushSecrets: pushSecrets$1 } = await import("./sync-COnAugP-.mjs");
12479
+ const { reconcileMissingSecrets } = await import("./reconcile-DAAKa0YR.mjs");
12156
12480
  const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-Cs4WBsc4.mjs");
12157
12481
  const { workspace } = await loadWorkspaceConfig$1();
12158
12482
  const secrets = await readStageSecrets$1(options.stage, workspace.root);
@@ -12176,9 +12500,9 @@ program.command("secrets:pull").description("Pull secrets from remote provider (
12176
12500
  const globalOptions = program.opts();
12177
12501
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
12178
12502
  const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
12179
- const { pullSecrets: pullSecrets$1 } = await import("./sync-fzT5WX_y.mjs");
12503
+ const { pullSecrets: pullSecrets$1 } = await import("./sync-COnAugP-.mjs");
12180
12504
  const { writeStageSecrets: writeStageSecrets$1 } = await import("./storage-Cs4WBsc4.mjs");
12181
- const { reconcileMissingSecrets } = await import("./reconcile-D423q2QW.mjs");
12505
+ const { reconcileMissingSecrets } = await import("./reconcile-DAAKa0YR.mjs");
12182
12506
  const { workspace } = await loadWorkspaceConfig$1();
12183
12507
  let secrets = await pullSecrets$1(options.stage, workspace);
12184
12508
  if (!secrets) {
@@ -12203,7 +12527,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
12203
12527
  const globalOptions = program.opts();
12204
12528
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
12205
12529
  const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
12206
- const { reconcileMissingSecrets } = await import("./reconcile-D423q2QW.mjs");
12530
+ const { reconcileMissingSecrets } = await import("./reconcile-DAAKa0YR.mjs");
12207
12531
  const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-Cs4WBsc4.mjs");
12208
12532
  const { workspace } = await loadWorkspaceConfig$1();
12209
12533
  const secrets = await readStageSecrets$1(options.stage, workspace.root);