@geekmidas/cli 0.53.0 → 0.54.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.
package/dist/index.cjs CHANGED
@@ -20,6 +20,7 @@ const chokidar = require_chunk.__toESM(require("chokidar"));
20
20
  const dotenv = require_chunk.__toESM(require("dotenv"));
21
21
  const fast_glob = require_chunk.__toESM(require("fast-glob"));
22
22
  const __geekmidas_constructs_crons = require_chunk.__toESM(require("@geekmidas/constructs/crons"));
23
+ const __geekmidas_constructs_endpoints = require_chunk.__toESM(require("@geekmidas/constructs/endpoints"));
23
24
  const __geekmidas_constructs_functions = require_chunk.__toESM(require("@geekmidas/constructs/functions"));
24
25
  const __geekmidas_constructs_subscribers = require_chunk.__toESM(require("@geekmidas/constructs/subscribers"));
25
26
  const node_crypto = require_chunk.__toESM(require("node:crypto"));
@@ -31,7 +32,7 @@ const node_module = require_chunk.__toESM(require("node:module"));
31
32
 
32
33
  //#region package.json
33
34
  var name = "@geekmidas/cli";
34
- var version = "0.53.0";
35
+ var version = "0.54.0";
35
36
  var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
36
37
  var private$1 = false;
37
38
  var type = "module";
@@ -3386,7 +3387,7 @@ WORKDIR /app
3386
3387
  COPY . .
3387
3388
 
3388
3389
  # Build production server using gkm
3389
- RUN pnpm exec gkm build --provider server --production
3390
+ RUN ${pm.exec} gkm build --provider server --production
3390
3391
 
3391
3392
  # Stage 3: Production
3392
3393
  FROM ${baseImage} AS runner
@@ -3468,7 +3469,7 @@ WORKDIR /app
3468
3469
  COPY --from=pruner /app/out/full/ ./
3469
3470
 
3470
3471
  # Build production server using gkm
3471
- RUN pnpm exec gkm build --provider server --production
3472
+ RUN ${pm.exec} gkm build --provider server --production
3472
3473
 
3473
3474
  # Stage 4: Production
3474
3475
  FROM ${baseImage} AS runner
@@ -3789,7 +3790,7 @@ RUN if [ -n "$GKM_ENCRYPTED_CREDENTIALS" ]; then \
3789
3790
  fi
3790
3791
 
3791
3792
  # Build production server using gkm
3792
- RUN cd ${appPath} && pnpm exec gkm build --provider server --production
3793
+ RUN cd ${appPath} && ${pm.exec} gkm build --provider server --production
3793
3794
 
3794
3795
  # Stage 4: Production
3795
3796
  FROM ${baseImage} AS runner
@@ -4858,6 +4859,12 @@ function generateSecretsReport(encryptedApps, sniffedApps) {
4858
4859
  const __filename$1 = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
4859
4860
  const __dirname$1 = (0, node_path.dirname)(__filename$1);
4860
4861
  /**
4862
+ * Check if a value is a gkm construct (Endpoint, Function, Cron, or Subscriber).
4863
+ */
4864
+ function isConstruct(value) {
4865
+ return __geekmidas_constructs_endpoints.Endpoint.isEndpoint(value) || __geekmidas_constructs_functions.Function.isFunction(value) || __geekmidas_constructs_crons.Cron.isCron(value) || __geekmidas_constructs_subscribers.Subscriber.isSubscriber(value);
4866
+ }
4867
+ /**
4861
4868
  * Resolve the path to a sniffer helper file.
4862
4869
  * Handles both dev (.ts with tsx) and production (.mjs from dist).
4863
4870
  *
@@ -4882,8 +4889,9 @@ function resolveSnifferFile(baseName) {
4882
4889
  * 1. Frontend apps: Returns empty (no server secrets)
4883
4890
  * 2. Apps with `requiredEnv`: Uses explicit list from config
4884
4891
  * 3. Entry apps: Imports entry file in subprocess to capture config.parse() calls
4885
- * 4. Apps with `envParser`: Runs SnifferEnvironmentParser to detect usage
4886
- * 5. Apps with neither: Returns empty
4892
+ * 4. Route-based apps: Loads route files and calls getEnvironment() on each construct
4893
+ * 5. Apps with `envParser` (no routes): Runs SnifferEnvironmentParser to detect usage
4894
+ * 6. Apps with neither: Returns empty
4887
4895
  *
4888
4896
  * This function handles "fire and forget" async operations gracefully,
4889
4897
  * capturing errors and unhandled rejections without failing the build.
@@ -4912,6 +4920,14 @@ async function sniffAppEnvironment(app, appName, workspacePath, options = {}) {
4912
4920
  requiredEnvVars: result.envVars
4913
4921
  };
4914
4922
  }
4923
+ if (app.routes) {
4924
+ const result = await sniffRouteFiles(app.routes, app.path, workspacePath);
4925
+ if (logWarnings && result.error) console.warn(`[sniffer] ${appName}: Route sniffing threw error (env vars still captured): ${result.error.message}`);
4926
+ return {
4927
+ appName,
4928
+ requiredEnvVars: result.envVars
4929
+ };
4930
+ }
4915
4931
  if (app.envParser) {
4916
4932
  const result = await sniffEnvParser(app.envParser, app.path, workspacePath);
4917
4933
  if (logWarnings) {
@@ -5003,6 +5019,47 @@ async function sniffEntryFile(entryPath, appPath, workspacePath) {
5003
5019
  });
5004
5020
  }
5005
5021
  /**
5022
+ * Sniff route files by loading constructs and calling getEnvironment().
5023
+ *
5024
+ * Route-based apps have endpoints, functions, crons, and subscribers that
5025
+ * use services. Each service's register() method accesses environment variables.
5026
+ * This function mimics what the bundler does during build to capture those vars.
5027
+ *
5028
+ * @param routes - Glob pattern(s) for route files
5029
+ * @param appPath - The app's path relative to workspace (e.g., 'apps/api')
5030
+ * @param workspacePath - Absolute path to workspace root
5031
+ * @returns EntrySniffResult with env vars and optional error
5032
+ */
5033
+ async function sniffRouteFiles(routes, appPath, workspacePath) {
5034
+ const fullAppPath = (0, node_path.resolve)(workspacePath, appPath);
5035
+ const patterns = Array.isArray(routes) ? routes : [routes];
5036
+ const envVars = /* @__PURE__ */ new Set();
5037
+ let error;
5038
+ try {
5039
+ const files = await (0, fast_glob.default)(patterns, {
5040
+ cwd: fullAppPath,
5041
+ absolute: true
5042
+ });
5043
+ for (const file of files) try {
5044
+ const module$1 = await import(file);
5045
+ for (const [, exportValue] of Object.entries(module$1)) if (isConstruct(exportValue)) try {
5046
+ const constructEnvVars = await exportValue.getEnvironment();
5047
+ constructEnvVars.forEach((v) => envVars.add(v));
5048
+ } catch (e) {
5049
+ console.warn(`[sniffer] Failed to get environment for construct in ${file}: ${e instanceof Error ? e.message : String(e)}`);
5050
+ }
5051
+ } catch (e) {
5052
+ console.warn(`[sniffer] Failed to import ${file}: ${e instanceof Error ? e.message : String(e)}`);
5053
+ }
5054
+ } catch (e) {
5055
+ error = e instanceof Error ? e : new Error(String(e));
5056
+ }
5057
+ return {
5058
+ envVars: Array.from(envVars).sort(),
5059
+ error
5060
+ };
5061
+ }
5062
+ /**
5006
5063
  * Run the SnifferEnvironmentParser on an envParser module to detect
5007
5064
  * which environment variables it accesses.
5008
5065
  *