@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.
- package/dist/{bundler-DsXfFSCU.cjs → bundler-BB-kETMd.cjs} +19 -48
- package/dist/bundler-BB-kETMd.cjs.map +1 -0
- package/dist/{bundler-Db83tLti.mjs → bundler-DGry2vaR.mjs} +21 -50
- package/dist/bundler-DGry2vaR.mjs.map +1 -0
- package/dist/index.cjs +26 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +26 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/build/bundler.ts +27 -79
- package/src/docker/index.ts +7 -3
- package/src/docker/templates.ts +16 -0
- package/src/init/templates/api.ts +4 -4
- package/dist/bundler-Db83tLti.mjs.map +0 -1
- package/dist/bundler-DsXfFSCU.cjs.map +0 -1
|
@@ -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
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
-
"
|
|
47
|
+
"esbuild",
|
|
70
48
|
entryPoint,
|
|
71
|
-
"--
|
|
72
|
-
"--
|
|
73
|
-
|
|
74
|
-
"--format",
|
|
75
|
-
|
|
76
|
-
"--
|
|
77
|
-
|
|
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(
|
|
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(`--
|
|
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(`
|
|
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-
|
|
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,
|
|
4
|
-
import {
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
-
"
|
|
46
|
+
"esbuild",
|
|
69
47
|
entryPoint,
|
|
70
|
-
"--
|
|
71
|
-
"--
|
|
72
|
-
|
|
73
|
-
"--format",
|
|
74
|
-
|
|
75
|
-
"--
|
|
76
|
-
|
|
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(
|
|
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(`--
|
|
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(`
|
|
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-
|
|
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.
|
|
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-
|
|
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
|
|
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: '
|
|
6376
|
-
{ id: '
|
|
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 {
|
|
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(
|
|
6427
|
+
.params({ id: IdSchema })
|
|
6409
6428
|
.output(UserResponseSchema)
|
|
6410
6429
|
.handle(async ({ params }) => ({
|
|
6411
6430
|
id: params.id,
|