@geekmidas/cli 0.40.0 → 0.41.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.
@@ -1,38 +1,15 @@
1
1
  const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const node_fs = require_chunk.__toESM(require("node:fs"));
3
2
  const node_path = require_chunk.__toESM(require("node:path"));
4
3
  const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
5
4
  const node_child_process = require_chunk.__toESM(require("node:child_process"));
6
5
 
7
6
  //#region src/build/bundler.ts
8
- const MIN_TSDOWN_VERSION = "0.11.0";
9
7
  /**
10
- * Check if tsdown is installed and meets minimum version requirement
8
+ * Banner to inject into ESM bundle for CJS compatibility.
9
+ * Creates a `require` function using Node's createRequire for packages
10
+ * that internally use CommonJS require() for Node builtins.
11
11
  */
12
- function checkTsdownVersion() {
13
- try {
14
- const result = (0, node_child_process.execSync)("npx tsdown --version", {
15
- encoding: "utf-8",
16
- stdio: [
17
- "pipe",
18
- "pipe",
19
- "pipe"
20
- ]
21
- });
22
- const match = result.match(/tsdown\/(\d+\.\d+\.\d+)/);
23
- if (match) {
24
- const version = match[1];
25
- const [major, minor] = version.split(".").map(Number);
26
- const [minMajor, minMinor] = MIN_TSDOWN_VERSION.split(".").map(Number);
27
- if (major < minMajor || major === minMajor && minor < minMinor) throw new Error(`tsdown version ${version} is too old. Please upgrade to ${MIN_TSDOWN_VERSION} or later:\n npm install -D tsdown@latest
28
- # or
29
- pnpm add -D tsdown@latest`);
30
- }
31
- } catch (error) {
32
- if (error instanceof Error && error.message.includes("too old")) throw error;
33
- throw new Error("tsdown is required for bundling. Please install it:\n npm install -D tsdown@latest\n # or\n pnpm add -D tsdown@latest");
34
- }
35
- }
12
+ const ESM_CJS_COMPAT_BANNER = "import { createRequire } from \"module\"; const require = createRequire(import.meta.url);";
36
13
  /**
37
14
  * Collect all required environment variables from constructs.
38
15
  * Uses the SnifferEnvironmentParser to detect which env vars each service needs.
@@ -49,7 +26,8 @@ async function collectRequiredEnvVars(constructs) {
49
26
  return Array.from(allEnvVars).sort();
50
27
  }
51
28
  /**
52
- * Bundle the server application using tsdown
29
+ * Bundle the server application using esbuild.
30
+ * Creates a fully standalone bundle with all dependencies included.
53
31
  *
54
32
  * @param options - Bundle configuration options
55
33
  * @returns Bundle result with output path and optional master key
@@ -62,27 +40,23 @@ const DOCKER_SERVICE_ENV_VARS = {
62
40
  };
63
41
  async function bundleServer(options) {
64
42
  const { entryPoint, outputDir, minify, sourcemap, external, stage, constructs, dockerServices } = options;
65
- checkTsdownVersion();
66
43
  await (0, node_fs_promises.mkdir)(outputDir, { recursive: true });
44
+ const mjsOutput = (0, node_path.join)(outputDir, "server.mjs");
67
45
  const args = [
68
46
  "npx",
69
- "tsdown",
47
+ "esbuild",
70
48
  entryPoint,
71
- "--no-config",
72
- "--out-dir",
73
- outputDir,
74
- "--format",
75
- "esm",
76
- "--platform",
77
- "node",
78
- "--target",
79
- "node22",
80
- "--clean"
49
+ "--bundle",
50
+ "--platform=node",
51
+ "--target=node22",
52
+ "--format=esm",
53
+ `--outfile=${mjsOutput}`,
54
+ "--packages=bundle",
55
+ `--banner:js=${ESM_CJS_COMPAT_BANNER}`
81
56
  ];
82
57
  if (minify) args.push("--minify");
83
58
  if (sourcemap) args.push("--sourcemap");
84
- for (const ext of external) args.push("--external", ext);
85
- args.push("--external", "node:*");
59
+ for (const ext of external) args.push(`--external:${ext}`);
86
60
  let masterKey;
87
61
  if (stage) {
88
62
  const { readStageSecrets, toEmbeddableSecrets, validateEnvironmentVariables, initStageSecrets, writeStageSecrets } = await Promise.resolve().then(() => require("./storage-fOR8dMu5.cjs"));
@@ -133,10 +107,9 @@ async function bundleServer(options) {
133
107
  const encrypted = encryptSecrets(embeddable);
134
108
  masterKey = encrypted.masterKey;
135
109
  const defines = generateDefineOptions(encrypted);
136
- for (const [key, value] of Object.entries(defines)) args.push(`--env.${key}`, value);
110
+ for (const [key, value] of Object.entries(defines)) args.push(`--define:${key}=${JSON.stringify(value)}`);
137
111
  console.log(` Secrets encrypted for stage "${stage}"`);
138
112
  }
139
- const mjsOutput = (0, node_path.join)(outputDir, "server.mjs");
140
113
  try {
141
114
  const [cmd, ...cmdArgs] = args;
142
115
  const result = (0, node_child_process.spawnSync)(cmd, cmdArgs, {
@@ -145,9 +118,7 @@ async function bundleServer(options) {
145
118
  shell: process.platform === "win32"
146
119
  });
147
120
  if (result.error) throw result.error;
148
- if (result.status !== 0) throw new Error(`tsdown exited with code ${result.status}`);
149
- const jsOutput = (0, node_path.join)(outputDir, "server.js");
150
- if ((0, node_fs.existsSync)(jsOutput)) await (0, node_fs_promises.rename)(jsOutput, mjsOutput);
121
+ if (result.status !== 0) throw new Error(`esbuild exited with code ${result.status}`);
151
122
  const { readFile } = await import("node:fs/promises");
152
123
  const content = await readFile(mjsOutput, "utf-8");
153
124
  if (!content.startsWith("#!")) await (0, node_fs_promises.writeFile)(mjsOutput, `#!/usr/bin/env node\n${content}`);
@@ -162,4 +133,4 @@ async function bundleServer(options) {
162
133
 
163
134
  //#endregion
164
135
  exports.bundleServer = bundleServer;
165
- //# sourceMappingURL=bundler-DsXfFSCU.cjs.map
136
+ //# sourceMappingURL=bundler-BB-kETMd.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundler-BB-kETMd.cjs","names":["constructs: Construct[]","DOCKER_SERVICE_ENV_VARS: Record<string, Record<string, string>>","options: BundleOptions","masterKey: string | undefined"],"sources":["../src/build/bundler.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Construct } from '@geekmidas/constructs';\n\n/**\n * Banner to inject into ESM bundle for CJS compatibility.\n * Creates a `require` function using Node's createRequire for packages\n * that internally use CommonJS require() for Node builtins.\n */\nconst ESM_CJS_COMPAT_BANNER =\n\t'import { createRequire } from \"module\"; const require = createRequire(import.meta.url);';\n\nexport interface BundleOptions {\n\t/** Entry point file (e.g., .gkm/server/server.ts) */\n\tentryPoint: string;\n\t/** Output directory for bundled files */\n\toutputDir: string;\n\t/** Minify the output (default: true) */\n\tminify: boolean;\n\t/** Generate sourcemaps (default: false) */\n\tsourcemap: boolean;\n\t/** Packages to exclude from bundling */\n\texternal: string[];\n\t/** Stage for secrets injection (optional) */\n\tstage?: string;\n\t/** Constructs to validate environment variables for */\n\tconstructs?: Construct[];\n\t/** Docker compose services configured (for auto-populating env vars) */\n\tdockerServices?: {\n\t\tpostgres?: boolean;\n\t\tredis?: boolean;\n\t\trabbitmq?: boolean;\n\t};\n}\n\nexport interface BundleResult {\n\t/** Path to the bundled output */\n\toutputPath: string;\n\t/** Ephemeral master key for deployment (only if stage was provided) */\n\tmasterKey?: string;\n}\n\n/**\n * Collect all required environment variables from constructs.\n * Uses the SnifferEnvironmentParser to detect which env vars each service needs.\n *\n * @param constructs - Array of constructs to analyze\n * @returns Deduplicated array of required environment variable names\n */\nasync function collectRequiredEnvVars(\n\tconstructs: Construct[],\n): Promise<string[]> {\n\tconst allEnvVars = new Set<string>();\n\n\tfor (const construct of constructs) {\n\t\tconst envVars = await construct.getEnvironment();\n\t\tenvVars.forEach((v) => allEnvVars.add(v));\n\t}\n\n\treturn Array.from(allEnvVars).sort();\n}\n\n/**\n * Bundle the server application using esbuild.\n * Creates a fully standalone bundle with all dependencies included.\n *\n * @param options - Bundle configuration options\n * @returns Bundle result with output path and optional master key\n */\n\n/** Default env var values for docker compose services */\nconst DOCKER_SERVICE_ENV_VARS: Record<string, Record<string, string>> = {\n\tpostgres: {\n\t\tDATABASE_URL: 'postgresql://postgres:postgres@postgres:5432/app',\n\t},\n\tredis: {\n\t\tREDIS_URL: 'redis://redis:6379',\n\t},\n\trabbitmq: {\n\t\tRABBITMQ_URL: 'amqp://rabbitmq:5672',\n\t},\n};\n\nexport async function bundleServer(\n\toptions: BundleOptions,\n): Promise<BundleResult> {\n\tconst {\n\t\tentryPoint,\n\t\toutputDir,\n\t\tminify,\n\t\tsourcemap,\n\t\texternal,\n\t\tstage,\n\t\tconstructs,\n\t\tdockerServices,\n\t} = options;\n\n\t// Ensure output directory exists\n\tawait mkdir(outputDir, { recursive: true });\n\n\tconst mjsOutput = join(outputDir, 'server.mjs');\n\n\t// Build command-line arguments for esbuild\n\tconst args = [\n\t\t'npx',\n\t\t'esbuild',\n\t\tentryPoint,\n\t\t'--bundle',\n\t\t'--platform=node',\n\t\t'--target=node22',\n\t\t'--format=esm',\n\t\t`--outfile=${mjsOutput}`,\n\t\t'--packages=bundle', // Bundle all dependencies for standalone output\n\t\t`--banner:js=${ESM_CJS_COMPAT_BANNER}`, // CJS compatibility for packages like pino\n\t];\n\n\tif (minify) {\n\t\targs.push('--minify');\n\t}\n\n\tif (sourcemap) {\n\t\targs.push('--sourcemap');\n\t}\n\n\t// Add external packages (user-specified)\n\tfor (const ext of external) {\n\t\targs.push(`--external:${ext}`);\n\t}\n\n\t// Handle secrets injection if stage is provided\n\tlet masterKey: string | undefined;\n\n\tif (stage) {\n\t\tconst {\n\t\t\treadStageSecrets,\n\t\t\ttoEmbeddableSecrets,\n\t\t\tvalidateEnvironmentVariables,\n\t\t\tinitStageSecrets,\n\t\t\twriteStageSecrets,\n\t\t} = await import('../secrets/storage');\n\t\tconst { encryptSecrets, generateDefineOptions } = await import(\n\t\t\t'../secrets/encryption'\n\t\t);\n\n\t\tlet secrets = await readStageSecrets(stage);\n\n\t\tif (!secrets) {\n\t\t\t// Auto-initialize secrets for the stage\n\t\t\tconsole.log(` Initializing secrets for stage \"${stage}\"...`);\n\t\t\tsecrets = initStageSecrets(stage);\n\t\t\tawait writeStageSecrets(secrets);\n\t\t\tconsole.log(` ✓ Created .gkm/secrets/${stage}.json`);\n\t\t}\n\n\t\t// Auto-populate env vars from docker compose services\n\t\tif (dockerServices) {\n\t\t\tfor (const [service, enabled] of Object.entries(dockerServices)) {\n\t\t\t\tif (enabled && DOCKER_SERVICE_ENV_VARS[service]) {\n\t\t\t\t\tfor (const [envVar, defaultValue] of Object.entries(\n\t\t\t\t\t\tDOCKER_SERVICE_ENV_VARS[service],\n\t\t\t\t\t)) {\n\t\t\t\t\t\t// Check if not already in urls or custom\n\t\t\t\t\t\tconst urlKey = envVar as keyof typeof secrets.urls;\n\t\t\t\t\t\tif (!secrets.urls[urlKey] && !secrets.custom[envVar]) {\n\t\t\t\t\t\t\tsecrets.urls[urlKey] = defaultValue;\n\t\t\t\t\t\t\tconsole.log(` Auto-populated ${envVar} from docker compose`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Validate environment variables if constructs are provided\n\t\tif (constructs && constructs.length > 0) {\n\t\t\tconsole.log(' Analyzing environment variable requirements...');\n\t\t\tconst requiredVars = await collectRequiredEnvVars(constructs);\n\n\t\t\tif (requiredVars.length > 0) {\n\t\t\t\tconst validation = validateEnvironmentVariables(requiredVars, secrets);\n\n\t\t\t\tif (!validation.valid) {\n\t\t\t\t\tconst errorMessage = [\n\t\t\t\t\t\t`Missing environment variables for stage \"${stage}\":`,\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t...validation.missing.map((v) => ` ❌ ${v}`),\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t'To fix this, either:',\n\t\t\t\t\t\t` 1. Add the missing variables to .gkm/secrets/${stage}.json using:`,\n\t\t\t\t\t\t` gkm secrets:set <KEY> <VALUE> --stage ${stage}`,\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t` 2. Or import from a JSON file:`,\n\t\t\t\t\t\t` gkm secrets:import secrets.json --stage ${stage}`,\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t'Required variables:',\n\t\t\t\t\t\t...validation.required.map((v) =>\n\t\t\t\t\t\t\tvalidation.missing.includes(v) ? ` ❌ ${v}` : ` ✓ ${v}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t].join('\\n');\n\n\t\t\t\t\tthrow new Error(errorMessage);\n\t\t\t\t}\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ✓ All ${requiredVars.length} required environment variables found`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Convert to embeddable format and encrypt\n\t\tconst embeddable = toEmbeddableSecrets(secrets);\n\t\tconst encrypted = encryptSecrets(embeddable);\n\t\tmasterKey = encrypted.masterKey;\n\n\t\t// Add define options for build-time injection using esbuild's --define:KEY=VALUE format\n\t\tconst defines = generateDefineOptions(encrypted);\n\t\tfor (const [key, value] of Object.entries(defines)) {\n\t\t\targs.push(`--define:${key}=${JSON.stringify(value)}`);\n\t\t}\n\n\t\tconsole.log(` Secrets encrypted for stage \"${stage}\"`);\n\t}\n\n\ttry {\n\t\t// Run esbuild with command-line arguments\n\t\tconst [cmd, ...cmdArgs] = args as [string, ...string[]];\n\t\tconst result = spawnSync(cmd, cmdArgs, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: 'inherit',\n\t\t\tshell: process.platform === 'win32', // Only use shell on Windows for npx resolution\n\t\t});\n\n\t\tif (result.error) {\n\t\t\tthrow result.error;\n\t\t}\n\t\tif (result.status !== 0) {\n\t\t\tthrow new Error(`esbuild exited with code ${result.status}`);\n\t\t}\n\n\t\t// Add shebang to the bundled file\n\t\tconst { readFile } = await import('node:fs/promises');\n\t\tconst content = await readFile(mjsOutput, 'utf-8');\n\t\tif (!content.startsWith('#!')) {\n\t\t\tawait writeFile(mjsOutput, `#!/usr/bin/env node\\n${content}`);\n\t\t}\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to bundle server: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t}\n\n\treturn {\n\t\toutputPath: mjsOutput,\n\t\tmasterKey,\n\t};\n}\n"],"mappings":"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"}
@@ -1,37 +1,14 @@
1
- import { existsSync } from "node:fs";
2
1
  import { join } from "node:path";
3
- import { mkdir, rename, writeFile } from "node:fs/promises";
4
- import { execSync, spawnSync } from "node:child_process";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import { spawnSync } from "node:child_process";
5
4
 
6
5
  //#region src/build/bundler.ts
7
- const MIN_TSDOWN_VERSION = "0.11.0";
8
6
  /**
9
- * Check if tsdown is installed and meets minimum version requirement
7
+ * Banner to inject into ESM bundle for CJS compatibility.
8
+ * Creates a `require` function using Node's createRequire for packages
9
+ * that internally use CommonJS require() for Node builtins.
10
10
  */
11
- function checkTsdownVersion() {
12
- try {
13
- const result = execSync("npx tsdown --version", {
14
- encoding: "utf-8",
15
- stdio: [
16
- "pipe",
17
- "pipe",
18
- "pipe"
19
- ]
20
- });
21
- const match = result.match(/tsdown\/(\d+\.\d+\.\d+)/);
22
- if (match) {
23
- const version = match[1];
24
- const [major, minor] = version.split(".").map(Number);
25
- const [minMajor, minMinor] = MIN_TSDOWN_VERSION.split(".").map(Number);
26
- if (major < minMajor || major === minMajor && minor < minMinor) throw new Error(`tsdown version ${version} is too old. Please upgrade to ${MIN_TSDOWN_VERSION} or later:\n npm install -D tsdown@latest
27
- # or
28
- pnpm add -D tsdown@latest`);
29
- }
30
- } catch (error) {
31
- if (error instanceof Error && error.message.includes("too old")) throw error;
32
- throw new Error("tsdown is required for bundling. Please install it:\n npm install -D tsdown@latest\n # or\n pnpm add -D tsdown@latest");
33
- }
34
- }
11
+ const ESM_CJS_COMPAT_BANNER = "import { createRequire } from \"module\"; const require = createRequire(import.meta.url);";
35
12
  /**
36
13
  * Collect all required environment variables from constructs.
37
14
  * Uses the SnifferEnvironmentParser to detect which env vars each service needs.
@@ -48,7 +25,8 @@ async function collectRequiredEnvVars(constructs) {
48
25
  return Array.from(allEnvVars).sort();
49
26
  }
50
27
  /**
51
- * Bundle the server application using tsdown
28
+ * Bundle the server application using esbuild.
29
+ * Creates a fully standalone bundle with all dependencies included.
52
30
  *
53
31
  * @param options - Bundle configuration options
54
32
  * @returns Bundle result with output path and optional master key
@@ -61,27 +39,23 @@ const DOCKER_SERVICE_ENV_VARS = {
61
39
  };
62
40
  async function bundleServer(options) {
63
41
  const { entryPoint, outputDir, minify, sourcemap, external, stage, constructs, dockerServices } = options;
64
- checkTsdownVersion();
65
42
  await mkdir(outputDir, { recursive: true });
43
+ const mjsOutput = join(outputDir, "server.mjs");
66
44
  const args = [
67
45
  "npx",
68
- "tsdown",
46
+ "esbuild",
69
47
  entryPoint,
70
- "--no-config",
71
- "--out-dir",
72
- outputDir,
73
- "--format",
74
- "esm",
75
- "--platform",
76
- "node",
77
- "--target",
78
- "node22",
79
- "--clean"
48
+ "--bundle",
49
+ "--platform=node",
50
+ "--target=node22",
51
+ "--format=esm",
52
+ `--outfile=${mjsOutput}`,
53
+ "--packages=bundle",
54
+ `--banner:js=${ESM_CJS_COMPAT_BANNER}`
80
55
  ];
81
56
  if (minify) args.push("--minify");
82
57
  if (sourcemap) args.push("--sourcemap");
83
- for (const ext of external) args.push("--external", ext);
84
- args.push("--external", "node:*");
58
+ for (const ext of external) args.push(`--external:${ext}`);
85
59
  let masterKey;
86
60
  if (stage) {
87
61
  const { readStageSecrets, toEmbeddableSecrets, validateEnvironmentVariables, initStageSecrets, writeStageSecrets } = await import("./storage-DNj_I11J.mjs");
@@ -132,10 +106,9 @@ async function bundleServer(options) {
132
106
  const encrypted = encryptSecrets(embeddable);
133
107
  masterKey = encrypted.masterKey;
134
108
  const defines = generateDefineOptions(encrypted);
135
- for (const [key, value] of Object.entries(defines)) args.push(`--env.${key}`, value);
109
+ for (const [key, value] of Object.entries(defines)) args.push(`--define:${key}=${JSON.stringify(value)}`);
136
110
  console.log(` Secrets encrypted for stage "${stage}"`);
137
111
  }
138
- const mjsOutput = join(outputDir, "server.mjs");
139
112
  try {
140
113
  const [cmd, ...cmdArgs] = args;
141
114
  const result = spawnSync(cmd, cmdArgs, {
@@ -144,9 +117,7 @@ async function bundleServer(options) {
144
117
  shell: process.platform === "win32"
145
118
  });
146
119
  if (result.error) throw result.error;
147
- if (result.status !== 0) throw new Error(`tsdown exited with code ${result.status}`);
148
- const jsOutput = join(outputDir, "server.js");
149
- if (existsSync(jsOutput)) await rename(jsOutput, mjsOutput);
120
+ if (result.status !== 0) throw new Error(`esbuild exited with code ${result.status}`);
150
121
  const { readFile: readFile$1 } = await import("node:fs/promises");
151
122
  const content = await readFile$1(mjsOutput, "utf-8");
152
123
  if (!content.startsWith("#!")) await writeFile(mjsOutput, `#!/usr/bin/env node\n${content}`);
@@ -161,4 +132,4 @@ async function bundleServer(options) {
161
132
 
162
133
  //#endregion
163
134
  export { bundleServer };
164
- //# sourceMappingURL=bundler-Db83tLti.mjs.map
135
+ //# sourceMappingURL=bundler-DGry2vaR.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundler-DGry2vaR.mjs","names":["constructs: Construct[]","DOCKER_SERVICE_ENV_VARS: Record<string, Record<string, string>>","options: BundleOptions","masterKey: string | undefined"],"sources":["../src/build/bundler.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Construct } from '@geekmidas/constructs';\n\n/**\n * Banner to inject into ESM bundle for CJS compatibility.\n * Creates a `require` function using Node's createRequire for packages\n * that internally use CommonJS require() for Node builtins.\n */\nconst ESM_CJS_COMPAT_BANNER =\n\t'import { createRequire } from \"module\"; const require = createRequire(import.meta.url);';\n\nexport interface BundleOptions {\n\t/** Entry point file (e.g., .gkm/server/server.ts) */\n\tentryPoint: string;\n\t/** Output directory for bundled files */\n\toutputDir: string;\n\t/** Minify the output (default: true) */\n\tminify: boolean;\n\t/** Generate sourcemaps (default: false) */\n\tsourcemap: boolean;\n\t/** Packages to exclude from bundling */\n\texternal: string[];\n\t/** Stage for secrets injection (optional) */\n\tstage?: string;\n\t/** Constructs to validate environment variables for */\n\tconstructs?: Construct[];\n\t/** Docker compose services configured (for auto-populating env vars) */\n\tdockerServices?: {\n\t\tpostgres?: boolean;\n\t\tredis?: boolean;\n\t\trabbitmq?: boolean;\n\t};\n}\n\nexport interface BundleResult {\n\t/** Path to the bundled output */\n\toutputPath: string;\n\t/** Ephemeral master key for deployment (only if stage was provided) */\n\tmasterKey?: string;\n}\n\n/**\n * Collect all required environment variables from constructs.\n * Uses the SnifferEnvironmentParser to detect which env vars each service needs.\n *\n * @param constructs - Array of constructs to analyze\n * @returns Deduplicated array of required environment variable names\n */\nasync function collectRequiredEnvVars(\n\tconstructs: Construct[],\n): Promise<string[]> {\n\tconst allEnvVars = new Set<string>();\n\n\tfor (const construct of constructs) {\n\t\tconst envVars = await construct.getEnvironment();\n\t\tenvVars.forEach((v) => allEnvVars.add(v));\n\t}\n\n\treturn Array.from(allEnvVars).sort();\n}\n\n/**\n * Bundle the server application using esbuild.\n * Creates a fully standalone bundle with all dependencies included.\n *\n * @param options - Bundle configuration options\n * @returns Bundle result with output path and optional master key\n */\n\n/** Default env var values for docker compose services */\nconst DOCKER_SERVICE_ENV_VARS: Record<string, Record<string, string>> = {\n\tpostgres: {\n\t\tDATABASE_URL: 'postgresql://postgres:postgres@postgres:5432/app',\n\t},\n\tredis: {\n\t\tREDIS_URL: 'redis://redis:6379',\n\t},\n\trabbitmq: {\n\t\tRABBITMQ_URL: 'amqp://rabbitmq:5672',\n\t},\n};\n\nexport async function bundleServer(\n\toptions: BundleOptions,\n): Promise<BundleResult> {\n\tconst {\n\t\tentryPoint,\n\t\toutputDir,\n\t\tminify,\n\t\tsourcemap,\n\t\texternal,\n\t\tstage,\n\t\tconstructs,\n\t\tdockerServices,\n\t} = options;\n\n\t// Ensure output directory exists\n\tawait mkdir(outputDir, { recursive: true });\n\n\tconst mjsOutput = join(outputDir, 'server.mjs');\n\n\t// Build command-line arguments for esbuild\n\tconst args = [\n\t\t'npx',\n\t\t'esbuild',\n\t\tentryPoint,\n\t\t'--bundle',\n\t\t'--platform=node',\n\t\t'--target=node22',\n\t\t'--format=esm',\n\t\t`--outfile=${mjsOutput}`,\n\t\t'--packages=bundle', // Bundle all dependencies for standalone output\n\t\t`--banner:js=${ESM_CJS_COMPAT_BANNER}`, // CJS compatibility for packages like pino\n\t];\n\n\tif (minify) {\n\t\targs.push('--minify');\n\t}\n\n\tif (sourcemap) {\n\t\targs.push('--sourcemap');\n\t}\n\n\t// Add external packages (user-specified)\n\tfor (const ext of external) {\n\t\targs.push(`--external:${ext}`);\n\t}\n\n\t// Handle secrets injection if stage is provided\n\tlet masterKey: string | undefined;\n\n\tif (stage) {\n\t\tconst {\n\t\t\treadStageSecrets,\n\t\t\ttoEmbeddableSecrets,\n\t\t\tvalidateEnvironmentVariables,\n\t\t\tinitStageSecrets,\n\t\t\twriteStageSecrets,\n\t\t} = await import('../secrets/storage');\n\t\tconst { encryptSecrets, generateDefineOptions } = await import(\n\t\t\t'../secrets/encryption'\n\t\t);\n\n\t\tlet secrets = await readStageSecrets(stage);\n\n\t\tif (!secrets) {\n\t\t\t// Auto-initialize secrets for the stage\n\t\t\tconsole.log(` Initializing secrets for stage \"${stage}\"...`);\n\t\t\tsecrets = initStageSecrets(stage);\n\t\t\tawait writeStageSecrets(secrets);\n\t\t\tconsole.log(` ✓ Created .gkm/secrets/${stage}.json`);\n\t\t}\n\n\t\t// Auto-populate env vars from docker compose services\n\t\tif (dockerServices) {\n\t\t\tfor (const [service, enabled] of Object.entries(dockerServices)) {\n\t\t\t\tif (enabled && DOCKER_SERVICE_ENV_VARS[service]) {\n\t\t\t\t\tfor (const [envVar, defaultValue] of Object.entries(\n\t\t\t\t\t\tDOCKER_SERVICE_ENV_VARS[service],\n\t\t\t\t\t)) {\n\t\t\t\t\t\t// Check if not already in urls or custom\n\t\t\t\t\t\tconst urlKey = envVar as keyof typeof secrets.urls;\n\t\t\t\t\t\tif (!secrets.urls[urlKey] && !secrets.custom[envVar]) {\n\t\t\t\t\t\t\tsecrets.urls[urlKey] = defaultValue;\n\t\t\t\t\t\t\tconsole.log(` Auto-populated ${envVar} from docker compose`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Validate environment variables if constructs are provided\n\t\tif (constructs && constructs.length > 0) {\n\t\t\tconsole.log(' Analyzing environment variable requirements...');\n\t\t\tconst requiredVars = await collectRequiredEnvVars(constructs);\n\n\t\t\tif (requiredVars.length > 0) {\n\t\t\t\tconst validation = validateEnvironmentVariables(requiredVars, secrets);\n\n\t\t\t\tif (!validation.valid) {\n\t\t\t\t\tconst errorMessage = [\n\t\t\t\t\t\t`Missing environment variables for stage \"${stage}\":`,\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t...validation.missing.map((v) => ` ❌ ${v}`),\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t'To fix this, either:',\n\t\t\t\t\t\t` 1. Add the missing variables to .gkm/secrets/${stage}.json using:`,\n\t\t\t\t\t\t` gkm secrets:set <KEY> <VALUE> --stage ${stage}`,\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t` 2. Or import from a JSON file:`,\n\t\t\t\t\t\t` gkm secrets:import secrets.json --stage ${stage}`,\n\t\t\t\t\t\t'',\n\t\t\t\t\t\t'Required variables:',\n\t\t\t\t\t\t...validation.required.map((v) =>\n\t\t\t\t\t\t\tvalidation.missing.includes(v) ? ` ❌ ${v}` : ` ✓ ${v}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t].join('\\n');\n\n\t\t\t\t\tthrow new Error(errorMessage);\n\t\t\t\t}\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ✓ All ${requiredVars.length} required environment variables found`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Convert to embeddable format and encrypt\n\t\tconst embeddable = toEmbeddableSecrets(secrets);\n\t\tconst encrypted = encryptSecrets(embeddable);\n\t\tmasterKey = encrypted.masterKey;\n\n\t\t// Add define options for build-time injection using esbuild's --define:KEY=VALUE format\n\t\tconst defines = generateDefineOptions(encrypted);\n\t\tfor (const [key, value] of Object.entries(defines)) {\n\t\t\targs.push(`--define:${key}=${JSON.stringify(value)}`);\n\t\t}\n\n\t\tconsole.log(` Secrets encrypted for stage \"${stage}\"`);\n\t}\n\n\ttry {\n\t\t// Run esbuild with command-line arguments\n\t\tconst [cmd, ...cmdArgs] = args as [string, ...string[]];\n\t\tconst result = spawnSync(cmd, cmdArgs, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: 'inherit',\n\t\t\tshell: process.platform === 'win32', // Only use shell on Windows for npx resolution\n\t\t});\n\n\t\tif (result.error) {\n\t\t\tthrow result.error;\n\t\t}\n\t\tif (result.status !== 0) {\n\t\t\tthrow new Error(`esbuild exited with code ${result.status}`);\n\t\t}\n\n\t\t// Add shebang to the bundled file\n\t\tconst { readFile } = await import('node:fs/promises');\n\t\tconst content = await readFile(mjsOutput, 'utf-8');\n\t\tif (!content.startsWith('#!')) {\n\t\t\tawait writeFile(mjsOutput, `#!/usr/bin/env node\\n${content}`);\n\t\t}\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to bundle server: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t}\n\n\treturn {\n\t\toutputPath: mjsOutput,\n\t\tmasterKey,\n\t};\n}\n"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -29,7 +29,7 @@ const node_module = require_chunk.__toESM(require("node:module"));
29
29
 
30
30
  //#region package.json
31
31
  var name = "@geekmidas/cli";
32
- var version = "0.40.0";
32
+ var version = "0.41.0";
33
33
  var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
34
34
  var private$1 = false;
35
35
  var type = "module";
@@ -2122,7 +2122,7 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2122
2122
  let masterKey;
2123
2123
  if (context.production?.bundle && !skipBundle) {
2124
2124
  logger$6.log(`\n📦 Bundling production server...`);
2125
- const { bundleServer } = await Promise.resolve().then(() => require("./bundler-DsXfFSCU.cjs"));
2125
+ const { bundleServer } = await Promise.resolve().then(() => require("./bundler-BB-kETMd.cjs"));
2126
2126
  const allConstructs = [
2127
2127
  ...endpoints.map((e) => e.construct),
2128
2128
  ...functions.map((f) => f.construct),
@@ -3079,6 +3079,13 @@ ${publicUrlEnvDeclarations}
3079
3079
  # Copy pruned source
3080
3080
  COPY --from=pruner /app/out/full/ ./
3081
3081
 
3082
+ # Copy workspace root configs for turbo builds (turbo prune doesn't include root configs)
3083
+ # Using wildcard to make it optional for single-app projects
3084
+ COPY --from=pruner /app/tsconfig.* ./
3085
+
3086
+ # Ensure public directory exists (may be empty for scaffolded projects)
3087
+ RUN mkdir -p ${appPath}/public
3088
+
3082
3089
  # Set Next.js to produce standalone output
3083
3090
  ENV NEXT_TELEMETRY_DISABLED=1
3084
3091
 
@@ -3173,6 +3180,11 @@ ARG GKM_CREDENTIALS_IV=""
3173
3180
  # Copy pruned source
3174
3181
  COPY --from=pruner /app/out/full/ ./
3175
3182
 
3183
+ # Copy workspace root configs for turbo builds (turbo prune doesn't include root configs)
3184
+ # Using wildcard to make it optional for single-app projects
3185
+ COPY --from=pruner /app/gkm.config.* ./
3186
+ COPY --from=pruner /app/tsconfig.* ./
3187
+
3176
3188
  # Write encrypted credentials for gkm build to embed
3177
3189
  RUN if [ -n "$GKM_ENCRYPTED_CREDENTIALS" ]; then \
3178
3190
  mkdir -p ${appPath}/.gkm && \
@@ -3264,6 +3276,10 @@ ARG GKM_CREDENTIALS_IV=""
3264
3276
  # Copy pruned source
3265
3277
  COPY --from=pruner /app/out/full/ ./
3266
3278
 
3279
+ # Copy workspace root configs for turbo builds (turbo prune doesn't include root configs)
3280
+ # Using wildcard to make it optional for single-app projects
3281
+ COPY --from=pruner /app/tsconfig.* ./
3282
+
3267
3283
  # Write encrypted credentials for tsdown to embed via define
3268
3284
  RUN if [ -n "$GKM_ENCRYPTED_CREDENTIALS" ]; then \
3269
3285
  mkdir -p ${appPath}/.gkm && \
@@ -3474,7 +3490,10 @@ async function pushDockerImage(imageName, options) {
3474
3490
  */
3475
3491
  function getAppPackageName(appPath) {
3476
3492
  try {
3477
- const pkg$1 = require(`${appPath}/package.json`);
3493
+ const pkgPath = (0, node_path.join)(appPath, "package.json");
3494
+ if (!(0, node_fs.existsSync)(pkgPath)) return void 0;
3495
+ const content = (0, node_fs.readFileSync)(pkgPath, "utf-8");
3496
+ const pkg$1 = JSON.parse(content);
3478
3497
  return pkg$1.name;
3479
3498
  } catch {
3480
3499
  return void 0;
@@ -6372,8 +6391,8 @@ export const listUsersEndpoint = e
6372
6391
  .output(ListUsersResponseSchema)
6373
6392
  .handle(async () => ({
6374
6393
  users: [
6375
- { id: '1', name: 'Alice' },
6376
- { id: '2', name: 'Bob' },
6394
+ { id: '550e8400-e29b-41d4-a716-446655440001', name: 'Alice' },
6395
+ { id: '550e8400-e29b-41d4-a716-446655440002', name: 'Bob' },
6377
6396
  ],
6378
6397
  }));
6379
6398
  ` : `import { e } from '@geekmidas/constructs/endpoints';
@@ -6400,12 +6419,12 @@ export const listUsersEndpoint = e
6400
6419
  {
6401
6420
  path: getRoutePath("users/get.ts"),
6402
6421
  content: modelsImport ? `import { e } from '@geekmidas/constructs/endpoints';
6403
- import { z } from 'zod';
6422
+ import { IdSchema } from '${modelsImport}/common';
6404
6423
  import { UserResponseSchema } from '${modelsImport}/user';
6405
6424
 
6406
6425
  export const getUserEndpoint = e
6407
6426
  .get('/users/:id')
6408
- .params(z.object({ id: z.string() }))
6427
+ .params({ id: IdSchema })
6409
6428
  .output(UserResponseSchema)
6410
6429
  .handle(async ({ params }) => ({
6411
6430
  id: params.id,