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