frontmcp 1.1.0 → 1.1.1
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/package.json +5 -5
- package/src/commands/build/adapters/cloudflare.js +29 -1
- package/src/commands/build/adapters/cloudflare.js.map +1 -1
- package/src/commands/build/adapters/distributed.js +4 -1
- package/src/commands/build/adapters/distributed.js.map +1 -1
- package/src/commands/build/exec/cli-runtime/extract-public-message.snippet.d.ts +18 -0
- package/src/commands/build/exec/cli-runtime/extract-public-message.snippet.js +58 -0
- package/src/commands/build/exec/cli-runtime/extract-public-message.snippet.js.map +1 -0
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.d.ts +2 -2
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +165 -47
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -1
- package/src/commands/build/exec/cli-runtime/schema-extractor.d.ts +7 -0
- package/src/commands/build/exec/cli-runtime/schema-extractor.js +17 -1
- package/src/commands/build/exec/cli-runtime/schema-extractor.js.map +1 -1
- package/src/commands/build/exec/index.d.ts +11 -0
- package/src/commands/build/exec/index.js +68 -20
- package/src/commands/build/exec/index.js.map +1 -1
- package/src/commands/build/exec/installer-script.d.ts +8 -2
- package/src/commands/build/exec/installer-script.js +34 -15
- package/src/commands/build/exec/installer-script.js.map +1 -1
- package/src/commands/build/exec/manifest.d.ts +16 -3
- package/src/commands/build/exec/manifest.js +17 -5
- package/src/commands/build/exec/manifest.js.map +1 -1
- package/src/commands/build/exec/runner-script.d.ts +9 -1
- package/src/commands/build/exec/runner-script.js +60 -2
- package/src/commands/build/exec/runner-script.js.map +1 -1
- package/src/commands/build/index.js +80 -18
- package/src/commands/build/index.js.map +1 -1
- package/src/commands/build/load-entry-config.d.ts +5 -0
- package/src/commands/build/load-entry-config.js +96 -0
- package/src/commands/build/load-entry-config.js.map +1 -0
- package/src/commands/build/mcpb/manifest.d.ts +14 -0
- package/src/commands/build/mcpb/manifest.js +29 -0
- package/src/commands/build/mcpb/manifest.js.map +1 -1
- package/src/commands/build/types.d.ts +19 -0
- package/src/commands/build/types.js.map +1 -1
- package/src/commands/dev/doctor.js +7 -3
- package/src/commands/dev/doctor.js.map +1 -1
- package/src/commands/package/install.d.ts +1 -1
- package/src/commands/package/install.js +10 -8
- package/src/commands/package/install.js.map +1 -1
- package/src/commands/package/types.d.ts +2 -1
- package/src/commands/package/types.js.map +1 -1
- package/src/config/frontmcp-config.loader.d.ts +20 -0
- package/src/config/frontmcp-config.loader.js +124 -5
- package/src/config/frontmcp-config.loader.js.map +1 -1
- package/src/config/index.d.ts +1 -1
- package/src/config/index.js +2 -1
- package/src/config/index.js.map +1 -1
|
@@ -32,8 +32,24 @@ async function buildExec(opts) {
|
|
|
32
32
|
const cwd = process.cwd();
|
|
33
33
|
const outDir = path.resolve(cwd, opts.outDir || 'dist');
|
|
34
34
|
console.log(`${(0, colors_1.c)('cyan', '[build:exec]')} Building executable bundle...`);
|
|
35
|
-
// 1. Load config
|
|
35
|
+
// 1. Load config (and merge in overrides forwarded from frontmcp.config —
|
|
36
|
+
// `build.storage`, `deployments[].cli.outputDefault`, etc.)
|
|
36
37
|
const rawConfig = await (0, config_1.loadExecConfig)(cwd);
|
|
38
|
+
if (opts.execOverrides) {
|
|
39
|
+
if (opts.execOverrides.storage && !rawConfig.storage) {
|
|
40
|
+
rawConfig.storage = opts.execOverrides.storage;
|
|
41
|
+
}
|
|
42
|
+
if (opts.execOverrides.cli) {
|
|
43
|
+
const existing = rawConfig.cli;
|
|
44
|
+
// CliConfig requires `enabled: boolean`; preserve any existing value or
|
|
45
|
+
// default to true (we only get here when CLI mode is being configured).
|
|
46
|
+
rawConfig.cli = {
|
|
47
|
+
enabled: existing?.enabled ?? true,
|
|
48
|
+
...existing,
|
|
49
|
+
...opts.execOverrides.cli,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
37
53
|
const config = (0, config_1.normalizeConfig)(rawConfig);
|
|
38
54
|
const cliEnabled = opts.cli || config.cli?.enabled;
|
|
39
55
|
const seaEnabled = opts.sea || config.sea?.enabled;
|
|
@@ -90,14 +106,35 @@ async function buildExec(opts) {
|
|
|
90
106
|
// Always build non-self-contained first (schema extraction needs host SDK)
|
|
91
107
|
const bundleResult = await (0, esbuild_bundler_1.bundleWithEsbuild)(compiledEntry, outDir, config);
|
|
92
108
|
console.log(`${(0, colors_1.c)('green', '[build:exec]')} bundle created: ${path.relative(cwd, bundleResult.bundlePath)} (${(0, esbuild_bundler_1.formatSize)(bundleResult.bundleSize)})`);
|
|
93
|
-
// 6.
|
|
109
|
+
// 6. Extract schema once and reuse for both the manifest port resolution
|
|
110
|
+
// (#371) and the CLI command generation (when cliEnabled). Schema
|
|
111
|
+
// extraction loads the user's bundle and boots an in-memory client
|
|
112
|
+
// (~200ms); running it twice on every --target cli build added up.
|
|
94
113
|
const bundleFilename = `${config.name}.bundle.js`;
|
|
95
|
-
const
|
|
114
|
+
const { extractSchemas } = await import('./cli-runtime/schema-extractor.js');
|
|
115
|
+
let extractedSchema;
|
|
116
|
+
try {
|
|
117
|
+
extractedSchema = await extractSchemas(bundleResult.bundlePath);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
if (cliEnabled) {
|
|
121
|
+
// CLI builds genuinely need the schema — fail loud.
|
|
122
|
+
throw err;
|
|
123
|
+
}
|
|
124
|
+
// For --target node we only need httpPort from the schema; falling back
|
|
125
|
+
// to the manifest's default precedence chain is acceptable.
|
|
126
|
+
}
|
|
127
|
+
// 7. Generate manifest with extracted decorator port + per-deployment cli config
|
|
128
|
+
const manifest = (0, manifest_1.generateManifest)(config, bundleFilename, {
|
|
129
|
+
target: cliEnabled ? 'cli' : 'node',
|
|
130
|
+
decoratorHttpPort: extractedSchema?.httpPort,
|
|
131
|
+
outputDefault: config.cli?.outputDefault,
|
|
132
|
+
});
|
|
96
133
|
// 7. CLI build step (if enabled)
|
|
97
134
|
let cliBundlePath;
|
|
98
135
|
if (cliEnabled) {
|
|
99
136
|
console.log(`${(0, colors_1.c)('cyan', '[build:exec]')} extracting schemas for CLI...`);
|
|
100
|
-
const {
|
|
137
|
+
const { SYSTEM_TOOL_NAMES } = await import('./cli-runtime/schema-extractor.js');
|
|
101
138
|
const { generateCliEntry, resolveToolCommandName } = await import('./cli-runtime/generate-cli-entry.js');
|
|
102
139
|
const { generateOutputFormatterSource } = await import('./cli-runtime/output-formatter.js');
|
|
103
140
|
const { generateSessionManagerSource } = await import('./cli-runtime/session-manager.js');
|
|
@@ -105,8 +142,10 @@ async function buildExec(opts) {
|
|
|
105
142
|
const { generateOAuthHelperSource } = await import('./cli-runtime/oauth-helper.js');
|
|
106
143
|
const { generateDaemonClientSource } = await import('./cli-runtime/daemon-client.js');
|
|
107
144
|
const { bundleCliWithEsbuild } = await import('./cli-runtime/cli-bundler.js');
|
|
108
|
-
//
|
|
109
|
-
|
|
145
|
+
// Reuse the schema extracted in step 6 (single extraction per build).
|
|
146
|
+
// The non-null assertion is safe — we threw above if cliEnabled and
|
|
147
|
+
// extraction failed, so by here `extractedSchema` is always defined.
|
|
148
|
+
const schema = extractedSchema;
|
|
110
149
|
const capabilities = schema.capabilities;
|
|
111
150
|
const userToolCount = schema.tools.filter((t) => !SYSTEM_TOOL_NAMES.has(t.name)).length;
|
|
112
151
|
console.log(`${(0, colors_1.c)('cyan', '[build:exec]')} extracted: ${schema.tools.length} tools (${userToolCount} user), ${schema.resources.length} resources, ${schema.resourceTemplates.length} templates, ${schema.prompts.length} prompts`);
|
|
@@ -188,23 +227,29 @@ async function buildExec(opts) {
|
|
|
188
227
|
};
|
|
189
228
|
}
|
|
190
229
|
// 8. Build SEA binaries if enabled
|
|
230
|
+
//
|
|
231
|
+
// For --target cli (cliEnabled === true), the runner script `exec`s only
|
|
232
|
+
// the CLI binary — the standalone server SEA is dead weight (~114 MB, see
|
|
233
|
+
// issue #373). Skip the server-SEA pass entirely in that mode. For
|
|
234
|
+
// --target node (cliEnabled === false), build only the server SEA.
|
|
191
235
|
let seaServerResult;
|
|
192
236
|
let seaCliResult;
|
|
193
237
|
if (seaEnabled) {
|
|
194
238
|
const { buildSea } = await import('./sea-builder.js');
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
239
|
+
if (!cliEnabled) {
|
|
240
|
+
// Server-only SEA path (--target node): rebuild bundle as self-contained
|
|
241
|
+
// (inlines all deps) and produce ${name}-bin.
|
|
242
|
+
const seaTempName = `${config.name}.sea-temp`;
|
|
243
|
+
console.log(`${(0, colors_1.c)('cyan', '[build:sea]')} rebuilding server bundle (self-contained)...`);
|
|
244
|
+
const seaBundle = await (0, esbuild_bundler_1.bundleWithEsbuild)(compiledEntry, outDir, config, {
|
|
245
|
+
selfContained: true,
|
|
246
|
+
outputName: seaTempName,
|
|
247
|
+
});
|
|
248
|
+
console.log(`${(0, colors_1.c)('cyan', '[build:sea]')} building server SEA binary...`);
|
|
249
|
+
seaServerResult = await buildSea(seaBundle.bundlePath, outDir, config.name);
|
|
250
|
+
fs.unlinkSync(seaBundle.bundlePath);
|
|
251
|
+
console.log(`${(0, colors_1.c)('green', '[build:sea]')} server binary: ${path.relative(cwd, seaServerResult.executablePath)} (${(0, esbuild_bundler_1.formatSize)(seaServerResult.executableSize)})`);
|
|
252
|
+
}
|
|
208
253
|
if (cliBundlePath) {
|
|
209
254
|
console.log(`${(0, colors_1.c)('cyan', '[build:sea]')} building CLI SEA binary...`);
|
|
210
255
|
seaCliResult = await buildSea(cliBundlePath, outDir, `${config.name}-cli`);
|
|
@@ -221,7 +266,10 @@ async function buildExec(opts) {
|
|
|
221
266
|
fs.writeFileSync(runnerPath, runnerContent, { mode: 0o755 });
|
|
222
267
|
console.log(`${(0, colors_1.c)('green', '[build:exec]')} runner: ${path.relative(cwd, runnerPath)}`);
|
|
223
268
|
// 10. Generate installer script
|
|
224
|
-
const installerContent = (0, installer_script_1.generateInstallerScript)(config
|
|
269
|
+
const installerContent = (0, installer_script_1.generateInstallerScript)(config, {
|
|
270
|
+
target: cliEnabled ? 'cli' : 'node',
|
|
271
|
+
seaEnabled: !!seaEnabled,
|
|
272
|
+
});
|
|
225
273
|
const installerPath = path.join(outDir, `install-${config.name}.sh`);
|
|
226
274
|
fs.writeFileSync(installerPath, installerContent, { mode: 0o755 });
|
|
227
275
|
console.log(`${(0, colors_1.c)('green', '[build:exec]')} installer: ${path.relative(cwd, installerPath)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * buildExec() orchestrator — produces a distributable bundle from a FrontMCP app.\n *\n * Output (server-only mode):\n * dist/{name}.bundle.js — esbuild single-file bundle\n * dist/{name}.manifest.json — app metadata (runtime reqs, setup questions)\n * dist/{name} — bash runner script\n * dist/install-{name}.sh — bash installer script\n *\n * Output (CLI mode, --cli flag):\n * All of the above, plus:\n * dist/{name}-cli.bundle.js — CLI executable bundle (commander.js)\n * dist/{name} — bash runner dispatches to CLI bundle\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { type ParsedArgs } from '../../../core/args';\nimport { c } from '../../../core/colors';\nimport { resolveEntry } from '../../../shared/fs';\nimport { loadExecConfig, normalizeConfig } from './config';\nimport { bundleWithEsbuild, formatSize } from './esbuild-bundler';\nimport { generateManifest } from './manifest';\nimport { generateRunnerScript } from './runner-script';\nimport { generateInstallerScript } from './installer-script';\nimport { validateStepGraph } from './setup';\nimport { ensureDir, fileExists, runCmd } from '@frontmcp/utils';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../../core/tsconfig';\n\nexport async function buildExec(opts: ParsedArgs & { cli?: boolean; sea?: boolean }): Promise<void> {\n const cwd = process.cwd();\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n\n console.log(`${c('cyan', '[build:exec]')} Building executable bundle...`);\n\n // 1. Load config\n const rawConfig = await loadExecConfig(cwd);\n const config = normalizeConfig(rawConfig);\n const cliEnabled = opts.cli || config.cli?.enabled;\n const seaEnabled = opts.sea || config.sea?.enabled;\n\n console.log(`${c('cyan', '[build:exec]')} name: ${config.name}`);\n console.log(`${c('cyan', '[build:exec]')} version: ${config.version}`);\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} CLI mode: enabled`);\n }\n if (seaEnabled) {\n console.log(`${c('cyan', '[build:exec]')} SEA mode: enabled (single executable)`);\n }\n\n // 2. Resolve entry\n const entry = await resolveEntry(cwd, config.entry || opts.entry);\n console.log(`${c('cyan', '[build:exec]')} entry: ${path.relative(cwd, entry)}`);\n\n // 3. Validate setup graph if present\n if (config.setup?.steps) {\n console.log(\n `${c('cyan', '[build:exec]')} validating setup questionnaire (${config.setup.steps.length} steps)...`,\n );\n const errors = validateStepGraph(config.setup.steps);\n const realErrors = errors.filter((e) => !e.startsWith('Warning:'));\n const warnings = errors.filter((e) => e.startsWith('Warning:'));\n\n for (const w of warnings) {\n console.log(`${c('yellow', '[build:exec]')} ${w}`);\n }\n if (realErrors.length > 0) {\n for (const e of realErrors) {\n console.error(`${c('red', '[build:exec]')} ${e}`);\n }\n throw new Error('Setup questionnaire has validation errors. Fix them before building.');\n }\n }\n\n // 4. Compile TypeScript\n console.log(`${c('cyan', '[build:exec]')} compiling TypeScript...`);\n await ensureDir(outDir);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const tscArgs: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n tscArgs.push('--project', tsconfigPath);\n } else {\n tscArgs.push(entry);\n tscArgs.push('--rootDir', path.dirname(entry));\n tscArgs.push('--experimentalDecorators', '--emitDecoratorMetadata');\n tscArgs.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n tscArgs.push('--module', 'commonjs');\n tscArgs.push('--outDir', outDir);\n tscArgs.push('--skipLibCheck');\n\n await runCmd('npx', tscArgs);\n console.log(`${c('green', '[build:exec]')} TypeScript compiled.`);\n\n // 5. Bundle with esbuild\n console.log(`${c('cyan', '[build:exec]')} bundling with esbuild...`);\n const compiledEntry = path.join(\n outDir,\n path.basename(entry).replace(/\\.tsx?$/, '.js'),\n );\n\n // Always build non-self-contained first (schema extraction needs host SDK)\n const bundleResult = await bundleWithEsbuild(compiledEntry, outDir, config);\n console.log(\n `${c('green', '[build:exec]')} bundle created: ${path.relative(cwd, bundleResult.bundlePath)} (${formatSize(bundleResult.bundleSize)})`,\n );\n\n // 6. Generate manifest\n const bundleFilename = `${config.name}.bundle.js`;\n const manifest = generateManifest(config, bundleFilename);\n\n // 7. CLI build step (if enabled)\n let cliBundlePath: string | undefined;\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} extracting schemas for CLI...`);\n\n const { extractSchemas, SYSTEM_TOOL_NAMES } = await import('./cli-runtime/schema-extractor.js');\n const { generateCliEntry, resolveToolCommandName } = await import('./cli-runtime/generate-cli-entry.js');\n const { generateOutputFormatterSource } = await import('./cli-runtime/output-formatter.js');\n const { generateSessionManagerSource } = await import('./cli-runtime/session-manager.js');\n const { generateCredentialStoreSource } = await import('./cli-runtime/credential-store.js');\n const { generateOAuthHelperSource } = await import('./cli-runtime/oauth-helper.js');\n const { generateDaemonClientSource } = await import('./cli-runtime/daemon-client.js');\n const { bundleCliWithEsbuild } = await import('./cli-runtime/cli-bundler.js');\n\n // Extract schemas from server bundle\n const schema = await extractSchemas(bundleResult.bundlePath);\n\n const capabilities = schema.capabilities;\n const userToolCount = schema.tools.filter(\n (t) => !SYSTEM_TOOL_NAMES.has(t.name),\n ).length;\n\n console.log(\n `${c('cyan', '[build:exec]')} extracted: ${schema.tools.length} tools (${userToolCount} user), ${schema.resources.length} resources, ${schema.resourceTemplates.length} templates, ${schema.prompts.length} prompts`,\n );\n if (capabilities.skills) console.log(`${c('cyan', '[build:exec]')} capability: skills`);\n if (capabilities.jobs) console.log(`${c('cyan', '[build:exec]')} capability: jobs`);\n if (capabilities.workflows) console.log(`${c('cyan', '[build:exec]')} capability: workflows`);\n\n // Copy skill content files via shared helper (flat _skills/ layout).\n const { copySkillAssets } = await import('./skill-assets.js');\n const { copiedCount } = copySkillAssets(outDir, schema.skillAssets);\n if (copiedCount > 0) {\n console.log(`${c('green', '[build:exec]')} copied ${copiedCount} skill content file(s) to _skills/`);\n }\n\n // Log tool name conflicts\n const cliConfig = config.cli || { enabled: true };\n const excludeTools = cliConfig.excludeTools || [];\n schema.tools\n .filter((t) => !excludeTools.includes(t.name))\n .forEach((t) => {\n const { wasRenamed, cmdName } = resolveToolCommandName(t.name);\n if (wasRenamed) {\n console.log(\n `${c('yellow', '[build:exec]')} Tool \"${t.name}\" conflicts with built-in command, mapped to \"${cmdName}\"`,\n );\n }\n });\n\n // Generate runtime modules\n const outputDefault = cliConfig.outputDefault || 'text';\n const authRequired = cliConfig.authRequired ?? false;\n const nativeDeps = cliConfig.nativeDeps || {};\n const oauthConfig = cliConfig.oauth;\n\n // Write runtime modules to temp files for bundling\n const tempDir = path.join(outDir, '__cli_temp');\n fs.mkdirSync(tempDir, { recursive: true });\n\n fs.writeFileSync(\n path.join(tempDir, 'output-formatter.js'),\n generateOutputFormatterSource(),\n );\n fs.writeFileSync(\n path.join(tempDir, 'session-manager.js'),\n generateSessionManagerSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'credential-store.js'),\n generateCredentialStoreSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'oauth-helper.js'),\n generateOAuthHelperSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'daemon-client.js'),\n generateDaemonClientSource(),\n );\n\n // Generate CLI entry\n const cliEntrySource = generateCliEntry({\n appName: config.name,\n appVersion: config.version || '1.0.0',\n description: cliConfig.description || `${config.name} CLI`,\n serverBundleFilename: bundleFilename,\n outputDefault,\n authRequired,\n excludeTools,\n nativeDeps,\n schema,\n oauthConfig,\n selfContained: !!seaEnabled,\n });\n\n const cliEntryPath = path.join(tempDir, 'cli-entry.js');\n fs.writeFileSync(cliEntryPath, cliEntrySource);\n\n // Bundle CLI\n console.log(`${c('cyan', '[build:exec]')} bundling CLI...`);\n const cliResult = await bundleCliWithEsbuild(cliEntryPath, outDir, config, {\n selfContained: !!seaEnabled,\n });\n cliBundlePath = cliResult.bundlePath;\n console.log(\n `${c('green', '[build:exec]')} CLI bundle: ${path.relative(cwd, cliResult.bundlePath)} (${formatSize(cliResult.bundleSize)})`,\n );\n\n // Clean temp\n fs.rmSync(tempDir, { recursive: true, force: true });\n\n // Extend manifest with CLI metadata\n manifest.cli = {\n enabled: true,\n cliBundle: `${config.name}-cli.bundle.js`,\n outputDefault,\n authRequired,\n toolCount: userToolCount,\n resourceCount: schema.resources.length,\n templateCount: schema.resourceTemplates.length,\n promptCount: schema.prompts.length,\n oauthEnabled: !!oauthConfig,\n skillsEnabled: capabilities.skills || undefined,\n jobsEnabled: capabilities.jobs || undefined,\n workflowsEnabled: capabilities.workflows || undefined,\n };\n }\n\n // 8. Build SEA binaries if enabled\n let seaServerResult: { executablePath: string; executableSize: number } | undefined;\n let seaCliResult: { executablePath: string; executableSize: number } | undefined;\n if (seaEnabled) {\n const { buildSea } = await import('./sea-builder.js');\n\n // Rebuild server bundle as self-contained for SEA (inlines all deps)\n // Use a temp filename so the original non-self-contained bundle is preserved\n const seaTempName = `${config.name}.sea-temp`;\n console.log(`${c('cyan', '[build:sea]')} rebuilding server bundle (self-contained)...`);\n const seaBundle = await bundleWithEsbuild(compiledEntry, outDir, config, {\n selfContained: true,\n outputName: seaTempName,\n });\n\n console.log(`${c('cyan', '[build:sea]')} building server SEA binary...`);\n seaServerResult = await buildSea(seaBundle.bundlePath, outDir, config.name);\n // Clean up temp self-contained bundle\n fs.unlinkSync(seaBundle.bundlePath);\n console.log(\n `${c('green', '[build:sea]')} server binary: ${path.relative(cwd, seaServerResult.executablePath)} (${formatSize(seaServerResult.executableSize)})`,\n );\n\n if (cliBundlePath) {\n console.log(`${c('cyan', '[build:sea]')} building CLI SEA binary...`);\n seaCliResult = await buildSea(cliBundlePath, outDir, `${config.name}-cli`);\n console.log(\n `${c('green', '[build:sea]')} CLI binary: ${path.relative(cwd, seaCliResult.executablePath)} (${formatSize(seaCliResult.executableSize)})`,\n );\n }\n }\n\n // 9. Write manifest\n const manifestPath = path.join(outDir, `${config.name}.manifest.json`);\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');\n console.log(\n `${c('green', '[build:exec]')} manifest: ${path.relative(cwd, manifestPath)}`,\n );\n\n // 10. Generate runner script (dispatches to CLI bundle or SEA binary)\n const runnerContent = generateRunnerScript(config, !!cliEnabled, !!seaEnabled);\n const runnerPath = path.join(outDir, config.name);\n fs.writeFileSync(runnerPath, runnerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} runner: ${path.relative(cwd, runnerPath)}`,\n );\n\n // 10. Generate installer script\n const installerContent = generateInstallerScript(config);\n const installerPath = path.join(outDir, `install-${config.name}.sh`);\n fs.writeFileSync(installerPath, installerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} installer: ${path.relative(cwd, installerPath)}`,\n );\n\n // 12. Clean up intermediate compiled files\n const keepFiles = new Set([\n `${config.name}.bundle.js`,\n `${config.name}-cli.bundle.js`,\n `${config.name}.manifest.json`,\n config.name,\n `install-${config.name}.sh`,\n `${config.name}-bin`,\n `${config.name}-cli-bin`,\n '_skills',\n ]);\n\n const allFiles = fs.readdirSync(outDir);\n let cleaned = 0;\n for (const file of allFiles) {\n if (!keepFiles.has(file)) {\n const filePath = path.join(outDir, file);\n const stat = fs.statSync(filePath);\n // Only clean intermediate compiled files; preserve .md and _skills/ directory\n if (stat.isFile() && !file.endsWith('.md')) {\n fs.unlinkSync(filePath);\n cleaned++;\n }\n }\n }\n if (cleaned > 0) {\n console.log(\n `${c('gray', '[build:exec]')} cleaned ${cleaned} intermediate file(s)`,\n );\n }\n\n // 13. Print summary\n console.log(`\\n${c('green', 'Executable build completed.')}`);\n console.log(`\\n${c('bold', 'Output:')}`);\n console.log(` ${path.relative(cwd, bundleResult.bundlePath)} ${c('gray', `(${formatSize(bundleResult.bundleSize)})`)}`);\n if (cliBundlePath) {\n const cliStat = fs.statSync(cliBundlePath);\n console.log(` ${path.relative(cwd, cliBundlePath)} ${c('gray', `(${formatSize(cliStat.size)})`)}`);\n }\n if (seaServerResult) {\n console.log(` ${path.relative(cwd, seaServerResult.executablePath)} ${c('gray', `(${formatSize(seaServerResult.executableSize)})`)}`);\n }\n if (seaCliResult) {\n console.log(` ${path.relative(cwd, seaCliResult.executablePath)} ${c('gray', `(${formatSize(seaCliResult.executableSize)})`)}`);\n }\n console.log(` ${path.relative(cwd, manifestPath)}`);\n console.log(` ${path.relative(cwd, runnerPath)}`);\n console.log(` ${path.relative(cwd, installerPath)}`);\n\n if (cliEnabled) {\n console.log(`\\n${c('gray', 'Run the CLI:')} ./${path.relative(cwd, runnerPath)} --help`);\n console.log(`${c('gray', 'Start server:')} ./${path.relative(cwd, runnerPath)} serve`);\n } else {\n console.log(`\\n${c('gray', 'Run the server:')} ./${path.relative(cwd, runnerPath)}`);\n }\n if (seaServerResult || seaCliResult) {\n console.log(`\\n${c('yellow', 'Note:')} SEA binaries are native executables. Run directly (not via bash).`);\n }\n console.log(`${c('gray', 'Install to system:')} bash ./${path.relative(cwd, installerPath)}`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;AAgBH,8BAkYC;;AAhZD,mDAA6B;AAC7B,+CAAyB;AAEzB,iDAAyC;AACzC,2CAAkD;AAClD,qCAA2D;AAC3D,uDAAkE;AAClE,yCAA8C;AAC9C,mDAAuD;AACvD,yDAA6D;AAC7D,mCAA4C;AAC5C,2CAAgE;AAChE,qDAAmE;AAE5D,KAAK,UAAU,SAAS,CAC7B,IAOC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;IAExD,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,gCAAgC,CAAC,CAAC;IAE1E,0EAA0E;IAC1E,+DAA+D;IAC/D,MAAM,SAAS,GAAG,MAAM,IAAA,uBAAc,EAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;YACrD,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;QACjD,CAAC;QACD,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC;YAC/B,wEAAwE;YACxE,wEAAwE;YACxE,SAAS,CAAC,GAAG,GAAG;gBACd,OAAO,EAAE,QAAQ,EAAE,OAAO,IAAI,IAAI;gBAClC,GAAG,QAAQ;gBACX,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG;aAC1B,CAAC;QACJ,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,IAAA,wBAAe,EAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC;IAEnD,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,UAAU,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,aAAa,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACvE,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,oBAAoB,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,wCAAwC,CAAC,CAAC;IACpF,CAAC;IAED,mBAAmB;IACnB,MAAM,KAAK,GAAG,MAAM,IAAA,iBAAY,EAAC,GAAG,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAEhF,qCAAqC;IACrC,IAAI,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,oCAAoC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,YAAY,CACtG,CAAC;QACF,MAAM,MAAM,GAAG,IAAA,yBAAiB,EAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QAEhE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,GAAG,IAAA,UAAC,EAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,0BAA0B,CAAC,CAAC;IACpE,MAAM,IAAA,iBAAS,EAAC,MAAM,CAAC,CAAC;IAExB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,MAAM,IAAA,kBAAU,EAAC,YAAY,CAAC,CAAC;IACnD,MAAM,OAAO,GAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAExC,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,0BAA0B,EAAE,yBAAyB,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,oCAAyB,CAAC,MAAM,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAE/B,MAAM,IAAA,cAAM,EAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,OAAO,EAAE,cAAc,CAAC,uBAAuB,CAAC,CAAC;IAElE,yBAAyB;IACzB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,2BAA2B,CAAC,CAAC;IACrE,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAC7B,MAAM,EACN,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAC/C,CAAC;IAEF,2EAA2E;IAC3E,MAAM,YAAY,GAAG,MAAM,IAAA,mCAAiB,EAAC,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,OAAO,EAAE,cAAc,CAAC,oBAAoB,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,UAAU,CAAC,KAAK,IAAA,4BAAU,EAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CACxI,CAAC;IAEF,yEAAyE;IACzE,qEAAqE;IACrE,sEAAsE;IACtE,sEAAsE;IACtE,MAAM,cAAc,GAAG,GAAG,MAAM,CAAC,IAAI,YAAY,CAAC;IAClD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,mCAAmC,CAAC,CAAC;IAC7E,IAAI,eAAuE,CAAC;IAC5E,IAAI,CAAC;QACH,eAAe,GAAG,MAAM,cAAc,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IAClE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,UAAU,EAAE,CAAC;YACf,oDAAoD;YACpD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,wEAAwE;QACxE,4DAA4D;IAC9D,CAAC;IAED,iFAAiF;IACjF,MAAM,QAAQ,GAAG,IAAA,2BAAgB,EAAC,MAAM,EAAE,cAAc,EAAE;QACxD,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;QACnC,iBAAiB,EAAE,eAAe,EAAE,QAAQ;QAC5C,aAAa,EAAE,MAAM,CAAC,GAAG,EAAE,aAA4C;KACxE,CAAC,CAAC;IAEH,iCAAiC;IACjC,IAAI,aAAiC,CAAC;IACtC,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,gCAAgC,CAAC,CAAC;QAE1E,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,mCAAmC,CAAC,CAAC;QAChF,MAAM,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,qCAAqC,CAAC,CAAC;QACzG,MAAM,EAAE,6BAA6B,EAAE,GAAG,MAAM,MAAM,CAAC,mCAAmC,CAAC,CAAC;QAC5F,MAAM,EAAE,4BAA4B,EAAE,GAAG,MAAM,MAAM,CAAC,kCAAkC,CAAC,CAAC;QAC1F,MAAM,EAAE,6BAA6B,EAAE,GAAG,MAAM,MAAM,CAAC,mCAAmC,CAAC,CAAC;QAC5F,MAAM,EAAE,yBAAyB,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;QACpF,MAAM,EAAE,0BAA0B,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;QACtF,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;QAE9E,sEAAsE;QACtE,oEAAoE;QACpE,qEAAqE;QACrE,MAAM,MAAM,GAAG,eAAgB,CAAC;QAEhC,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACzC,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CACvC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CACtC,CAAC,MAAM,CAAC;QAET,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,eAAe,MAAM,CAAC,KAAK,CAAC,MAAM,WAAW,aAAa,WAAW,MAAM,CAAC,SAAS,CAAC,MAAM,eAAe,MAAM,CAAC,iBAAiB,CAAC,MAAM,eAAe,MAAM,CAAC,OAAO,CAAC,MAAM,UAAU,CACrN,CAAC;QACF,IAAI,YAAY,CAAC,MAAM;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,qBAAqB,CAAC,CAAC;QACxF,IAAI,YAAY,CAAC,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,mBAAmB,CAAC,CAAC;QACpF,IAAI,YAAY,CAAC,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,wBAAwB,CAAC,CAAC;QAE9F,qEAAqE;QACrE,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC9D,MAAM,EAAE,WAAW,EAAE,GAAG,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QACpE,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,OAAO,EAAE,cAAc,CAAC,WAAW,WAAW,oCAAoC,CAAC,CAAC;QACvG,CAAC;QAED,0BAA0B;QAC1B,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAClD,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,IAAI,EAAE,CAAC;QAClD,MAAM,CAAC,KAAK;aACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aAC7C,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACb,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC/D,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC,IAAI,iDAAiD,OAAO,GAAG,CAC1G,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEL,2BAA2B;QAC3B,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,IAAI,MAAM,CAAC;QACxD,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,IAAI,KAAK,CAAC;QACrD,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,IAAI,EAAE,CAAC;QAC9C,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,CAAC;QAEpC,mDAAmD;QACnD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE3C,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,qBAAqB,CAAC,EACzC,6BAA6B,EAAE,CAChC,CAAC;QACF,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,EACxC,4BAA4B,CAAC,MAAM,CAAC,IAAI,CAAC,CAC1C,CAAC;QACF,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,qBAAqB,CAAC,EACzC,6BAA6B,CAAC,MAAM,CAAC,IAAI,CAAC,CAC3C,CAAC;QACF,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,EACrC,yBAAyB,CAAC,MAAM,CAAC,IAAI,CAAC,CACvC,CAAC;QACF,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,EACtC,0BAA0B,EAAE,CAC7B,CAAC;QAEF,qBAAqB;QACrB,MAAM,cAAc,GAAG,gBAAgB,CAAC;YACtC,OAAO,EAAE,MAAM,CAAC,IAAI;YACpB,UAAU,EAAE,MAAM,CAAC,OAAO,IAAI,OAAO;YACrC,WAAW,EAAE,SAAS,CAAC,WAAW,IAAI,GAAG,MAAM,CAAC,IAAI,MAAM;YAC1D,oBAAoB,EAAE,cAAc;YACpC,aAAa;YACb,YAAY;YACZ,YAAY;YACZ,UAAU;YACV,MAAM;YACN,WAAW;YACX,aAAa,EAAE,CAAC,CAAC,UAAU;SAC5B,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QAE/C,aAAa;QACb,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,kBAAkB,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE;YACzE,aAAa,EAAE,CAAC,CAAC,UAAU;SAC5B,CAAC,CAAC;QACH,aAAa,GAAG,SAAS,CAAC,UAAU,CAAC;QACrC,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,OAAO,EAAE,cAAc,CAAC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,UAAU,CAAC,KAAK,IAAA,4BAAU,EAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAC9H,CAAC;QAEF,aAAa;QACb,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAErD,oCAAoC;QACpC,QAAQ,CAAC,GAAG,GAAG;YACb,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,GAAG,MAAM,CAAC,IAAI,gBAAgB;YACzC,aAAa;YACb,YAAY;YACZ,SAAS,EAAE,aAAa;YACxB,aAAa,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM;YACtC,aAAa,EAAE,MAAM,CAAC,iBAAiB,CAAC,MAAM;YAC9C,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;YAClC,YAAY,EAAE,CAAC,CAAC,WAAW;YAC3B,aAAa,EAAE,YAAY,CAAC,MAAM,IAAI,SAAS;YAC/C,WAAW,EAAE,YAAY,CAAC,IAAI,IAAI,SAAS;YAC3C,gBAAgB,EAAE,YAAY,CAAC,SAAS,IAAI,SAAS;SACtD,CAAC;IACJ,CAAC;IAED,mCAAmC;IACnC,EAAE;IACF,yEAAyE;IACzE,0EAA0E;IAC1E,mEAAmE;IACnE,mEAAmE;IACnE,IAAI,eAA+E,CAAC;IACpF,IAAI,YAA4E,CAAC;IACjF,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAEtD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,yEAAyE;YACzE,8CAA8C;YAC9C,MAAM,WAAW,GAAG,GAAG,MAAM,CAAC,IAAI,WAAW,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,aAAa,CAAC,+CAA+C,CAAC,CAAC;YACxF,MAAM,SAAS,GAAG,MAAM,IAAA,mCAAiB,EAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE;gBACvE,aAAa,EAAE,IAAI;gBACnB,UAAU,EAAE,WAAW;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,aAAa,CAAC,gCAAgC,CAAC,CAAC;YACzE,eAAe,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5E,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACpC,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,OAAO,EAAE,aAAa,CAAC,mBAAmB,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAC,cAAc,CAAC,KAAK,IAAA,4BAAU,EAAC,eAAe,CAAC,cAAc,CAAC,GAAG,CACpJ,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,aAAa,CAAC,6BAA6B,CAAC,CAAC;YACtE,YAAY,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC;YAC3E,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,OAAO,EAAE,aAAa,CAAC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,cAAc,CAAC,KAAK,IAAA,4BAAU,EAAC,YAAY,CAAC,cAAc,CAAC,GAAG,CAC3I,CAAC;QACJ,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,gBAAgB,CAAC,CAAC;IACvE,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,OAAO,EAAE,cAAc,CAAC,cAAc,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,CAC9E,CAAC;IAEF,sEAAsE;IACtE,MAAM,aAAa,GAAG,IAAA,oCAAoB,EAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IAC/E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAClD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,OAAO,EAAE,cAAc,CAAC,YAAY,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,CAC1E,CAAC;IAEF,gCAAgC;IAChC,MAAM,gBAAgB,GAAG,IAAA,0CAAuB,EAAC,MAAM,EAAE;QACvD,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;QACnC,UAAU,EAAE,CAAC,CAAC,UAAU;KACzB,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC;IACrE,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,OAAO,EAAE,cAAc,CAAC,eAAe,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,CAChF,CAAC;IAEF,2CAA2C;IAC3C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;QACxB,GAAG,MAAM,CAAC,IAAI,YAAY;QAC1B,GAAG,MAAM,CAAC,IAAI,gBAAgB;QAC9B,GAAG,MAAM,CAAC,IAAI,gBAAgB;QAC9B,MAAM,CAAC,IAAI;QACX,WAAW,MAAM,CAAC,IAAI,KAAK;QAC3B,GAAG,MAAM,CAAC,IAAI,MAAM;QACpB,GAAG,MAAM,CAAC,IAAI,UAAU;QACxB,SAAS;KACV,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnC,8EAA8E;YAC9E,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3C,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACxB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CACT,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,YAAY,OAAO,uBAAuB,CACvE,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAA,UAAC,EAAC,OAAO,EAAE,6BAA6B,CAAC,EAAE,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,IAAA,UAAC,EAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,UAAU,CAAC,KAAK,IAAA,UAAC,EAAC,MAAM,EAAE,IAAI,IAAA,4BAAU,EAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1H,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,KAAK,IAAA,UAAC,EAAC,MAAM,EAAE,IAAI,IAAA,4BAAU,EAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAC,cAAc,CAAC,KAAK,IAAA,UAAC,EAAC,MAAM,EAAE,IAAI,IAAA,4BAAU,EAAC,eAAe,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1I,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,cAAc,CAAC,KAAK,IAAA,UAAC,EAAC,MAAM,EAAE,IAAI,IAAA,4BAAU,EAAC,YAAY,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACpI,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC;IAEtD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,KAAK,IAAA,UAAC,EAAC,MAAM,EAAE,cAAc,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;QACzF,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,eAAe,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzF,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,IAAA,UAAC,EAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,IAAI,eAAe,IAAI,YAAY,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAA,UAAC,EAAC,QAAQ,EAAE,OAAO,CAAC,oEAAoE,CAAC,CAAC;IAC7G,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,oBAAoB,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC;AAChG,CAAC","sourcesContent":["/**\n * buildExec() orchestrator — produces a distributable bundle from a FrontMCP app.\n *\n * Output (server-only mode):\n * dist/{name}.bundle.js — esbuild single-file bundle\n * dist/{name}.manifest.json — app metadata (runtime reqs, setup questions)\n * dist/{name} — bash runner script\n * dist/install-{name}.sh — bash installer script\n *\n * Output (CLI mode, --cli flag):\n * All of the above, plus:\n * dist/{name}-cli.bundle.js — CLI executable bundle (commander.js)\n * dist/{name} — bash runner dispatches to CLI bundle\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { type ParsedArgs } from '../../../core/args';\nimport { c } from '../../../core/colors';\nimport { resolveEntry } from '../../../shared/fs';\nimport { loadExecConfig, normalizeConfig } from './config';\nimport { bundleWithEsbuild, formatSize } from './esbuild-bundler';\nimport { generateManifest } from './manifest';\nimport { generateRunnerScript } from './runner-script';\nimport { generateInstallerScript } from './installer-script';\nimport { validateStepGraph } from './setup';\nimport { ensureDir, fileExists, runCmd } from '@frontmcp/utils';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../../core/tsconfig';\n\nexport async function buildExec(\n opts: ParsedArgs & {\n cli?: boolean;\n sea?: boolean;\n execOverrides?: {\n storage?: { type: 'sqlite' | 'redis' | 'none'; required?: boolean };\n cli?: { outputDefault?: 'text' | 'json'; description?: string; authRequired?: boolean };\n };\n },\n): Promise<void> {\n const cwd = process.cwd();\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n\n console.log(`${c('cyan', '[build:exec]')} Building executable bundle...`);\n\n // 1. Load config (and merge in overrides forwarded from frontmcp.config —\n // `build.storage`, `deployments[].cli.outputDefault`, etc.)\n const rawConfig = await loadExecConfig(cwd);\n if (opts.execOverrides) {\n if (opts.execOverrides.storage && !rawConfig.storage) {\n rawConfig.storage = opts.execOverrides.storage;\n }\n if (opts.execOverrides.cli) {\n const existing = rawConfig.cli;\n // CliConfig requires `enabled: boolean`; preserve any existing value or\n // default to true (we only get here when CLI mode is being configured).\n rawConfig.cli = {\n enabled: existing?.enabled ?? true,\n ...existing,\n ...opts.execOverrides.cli,\n };\n }\n }\n const config = normalizeConfig(rawConfig);\n const cliEnabled = opts.cli || config.cli?.enabled;\n const seaEnabled = opts.sea || config.sea?.enabled;\n\n console.log(`${c('cyan', '[build:exec]')} name: ${config.name}`);\n console.log(`${c('cyan', '[build:exec]')} version: ${config.version}`);\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} CLI mode: enabled`);\n }\n if (seaEnabled) {\n console.log(`${c('cyan', '[build:exec]')} SEA mode: enabled (single executable)`);\n }\n\n // 2. Resolve entry\n const entry = await resolveEntry(cwd, config.entry || opts.entry);\n console.log(`${c('cyan', '[build:exec]')} entry: ${path.relative(cwd, entry)}`);\n\n // 3. Validate setup graph if present\n if (config.setup?.steps) {\n console.log(\n `${c('cyan', '[build:exec]')} validating setup questionnaire (${config.setup.steps.length} steps)...`,\n );\n const errors = validateStepGraph(config.setup.steps);\n const realErrors = errors.filter((e) => !e.startsWith('Warning:'));\n const warnings = errors.filter((e) => e.startsWith('Warning:'));\n\n for (const w of warnings) {\n console.log(`${c('yellow', '[build:exec]')} ${w}`);\n }\n if (realErrors.length > 0) {\n for (const e of realErrors) {\n console.error(`${c('red', '[build:exec]')} ${e}`);\n }\n throw new Error('Setup questionnaire has validation errors. Fix them before building.');\n }\n }\n\n // 4. Compile TypeScript\n console.log(`${c('cyan', '[build:exec]')} compiling TypeScript...`);\n await ensureDir(outDir);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const tscArgs: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n tscArgs.push('--project', tsconfigPath);\n } else {\n tscArgs.push(entry);\n tscArgs.push('--rootDir', path.dirname(entry));\n tscArgs.push('--experimentalDecorators', '--emitDecoratorMetadata');\n tscArgs.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n tscArgs.push('--module', 'commonjs');\n tscArgs.push('--outDir', outDir);\n tscArgs.push('--skipLibCheck');\n\n await runCmd('npx', tscArgs);\n console.log(`${c('green', '[build:exec]')} TypeScript compiled.`);\n\n // 5. Bundle with esbuild\n console.log(`${c('cyan', '[build:exec]')} bundling with esbuild...`);\n const compiledEntry = path.join(\n outDir,\n path.basename(entry).replace(/\\.tsx?$/, '.js'),\n );\n\n // Always build non-self-contained first (schema extraction needs host SDK)\n const bundleResult = await bundleWithEsbuild(compiledEntry, outDir, config);\n console.log(\n `${c('green', '[build:exec]')} bundle created: ${path.relative(cwd, bundleResult.bundlePath)} (${formatSize(bundleResult.bundleSize)})`,\n );\n\n // 6. Extract schema once and reuse for both the manifest port resolution\n // (#371) and the CLI command generation (when cliEnabled). Schema\n // extraction loads the user's bundle and boots an in-memory client\n // (~200ms); running it twice on every --target cli build added up.\n const bundleFilename = `${config.name}.bundle.js`;\n const { extractSchemas } = await import('./cli-runtime/schema-extractor.js');\n let extractedSchema: Awaited<ReturnType<typeof extractSchemas>> | undefined;\n try {\n extractedSchema = await extractSchemas(bundleResult.bundlePath);\n } catch (err) {\n if (cliEnabled) {\n // CLI builds genuinely need the schema — fail loud.\n throw err;\n }\n // For --target node we only need httpPort from the schema; falling back\n // to the manifest's default precedence chain is acceptable.\n }\n\n // 7. Generate manifest with extracted decorator port + per-deployment cli config\n const manifest = generateManifest(config, bundleFilename, {\n target: cliEnabled ? 'cli' : 'node',\n decoratorHttpPort: extractedSchema?.httpPort,\n outputDefault: config.cli?.outputDefault as 'text' | 'json' | undefined,\n });\n\n // 7. CLI build step (if enabled)\n let cliBundlePath: string | undefined;\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} extracting schemas for CLI...`);\n\n const { SYSTEM_TOOL_NAMES } = await import('./cli-runtime/schema-extractor.js');\n const { generateCliEntry, resolveToolCommandName } = await import('./cli-runtime/generate-cli-entry.js');\n const { generateOutputFormatterSource } = await import('./cli-runtime/output-formatter.js');\n const { generateSessionManagerSource } = await import('./cli-runtime/session-manager.js');\n const { generateCredentialStoreSource } = await import('./cli-runtime/credential-store.js');\n const { generateOAuthHelperSource } = await import('./cli-runtime/oauth-helper.js');\n const { generateDaemonClientSource } = await import('./cli-runtime/daemon-client.js');\n const { bundleCliWithEsbuild } = await import('./cli-runtime/cli-bundler.js');\n\n // Reuse the schema extracted in step 6 (single extraction per build).\n // The non-null assertion is safe — we threw above if cliEnabled and\n // extraction failed, so by here `extractedSchema` is always defined.\n const schema = extractedSchema!;\n\n const capabilities = schema.capabilities;\n const userToolCount = schema.tools.filter(\n (t) => !SYSTEM_TOOL_NAMES.has(t.name),\n ).length;\n\n console.log(\n `${c('cyan', '[build:exec]')} extracted: ${schema.tools.length} tools (${userToolCount} user), ${schema.resources.length} resources, ${schema.resourceTemplates.length} templates, ${schema.prompts.length} prompts`,\n );\n if (capabilities.skills) console.log(`${c('cyan', '[build:exec]')} capability: skills`);\n if (capabilities.jobs) console.log(`${c('cyan', '[build:exec]')} capability: jobs`);\n if (capabilities.workflows) console.log(`${c('cyan', '[build:exec]')} capability: workflows`);\n\n // Copy skill content files via shared helper (flat _skills/ layout).\n const { copySkillAssets } = await import('./skill-assets.js');\n const { copiedCount } = copySkillAssets(outDir, schema.skillAssets);\n if (copiedCount > 0) {\n console.log(`${c('green', '[build:exec]')} copied ${copiedCount} skill content file(s) to _skills/`);\n }\n\n // Log tool name conflicts\n const cliConfig = config.cli || { enabled: true };\n const excludeTools = cliConfig.excludeTools || [];\n schema.tools\n .filter((t) => !excludeTools.includes(t.name))\n .forEach((t) => {\n const { wasRenamed, cmdName } = resolveToolCommandName(t.name);\n if (wasRenamed) {\n console.log(\n `${c('yellow', '[build:exec]')} Tool \"${t.name}\" conflicts with built-in command, mapped to \"${cmdName}\"`,\n );\n }\n });\n\n // Generate runtime modules\n const outputDefault = cliConfig.outputDefault || 'text';\n const authRequired = cliConfig.authRequired ?? false;\n const nativeDeps = cliConfig.nativeDeps || {};\n const oauthConfig = cliConfig.oauth;\n\n // Write runtime modules to temp files for bundling\n const tempDir = path.join(outDir, '__cli_temp');\n fs.mkdirSync(tempDir, { recursive: true });\n\n fs.writeFileSync(\n path.join(tempDir, 'output-formatter.js'),\n generateOutputFormatterSource(),\n );\n fs.writeFileSync(\n path.join(tempDir, 'session-manager.js'),\n generateSessionManagerSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'credential-store.js'),\n generateCredentialStoreSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'oauth-helper.js'),\n generateOAuthHelperSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'daemon-client.js'),\n generateDaemonClientSource(),\n );\n\n // Generate CLI entry\n const cliEntrySource = generateCliEntry({\n appName: config.name,\n appVersion: config.version || '1.0.0',\n description: cliConfig.description || `${config.name} CLI`,\n serverBundleFilename: bundleFilename,\n outputDefault,\n authRequired,\n excludeTools,\n nativeDeps,\n schema,\n oauthConfig,\n selfContained: !!seaEnabled,\n });\n\n const cliEntryPath = path.join(tempDir, 'cli-entry.js');\n fs.writeFileSync(cliEntryPath, cliEntrySource);\n\n // Bundle CLI\n console.log(`${c('cyan', '[build:exec]')} bundling CLI...`);\n const cliResult = await bundleCliWithEsbuild(cliEntryPath, outDir, config, {\n selfContained: !!seaEnabled,\n });\n cliBundlePath = cliResult.bundlePath;\n console.log(\n `${c('green', '[build:exec]')} CLI bundle: ${path.relative(cwd, cliResult.bundlePath)} (${formatSize(cliResult.bundleSize)})`,\n );\n\n // Clean temp\n fs.rmSync(tempDir, { recursive: true, force: true });\n\n // Extend manifest with CLI metadata\n manifest.cli = {\n enabled: true,\n cliBundle: `${config.name}-cli.bundle.js`,\n outputDefault,\n authRequired,\n toolCount: userToolCount,\n resourceCount: schema.resources.length,\n templateCount: schema.resourceTemplates.length,\n promptCount: schema.prompts.length,\n oauthEnabled: !!oauthConfig,\n skillsEnabled: capabilities.skills || undefined,\n jobsEnabled: capabilities.jobs || undefined,\n workflowsEnabled: capabilities.workflows || undefined,\n };\n }\n\n // 8. Build SEA binaries if enabled\n //\n // For --target cli (cliEnabled === true), the runner script `exec`s only\n // the CLI binary — the standalone server SEA is dead weight (~114 MB, see\n // issue #373). Skip the server-SEA pass entirely in that mode. For\n // --target node (cliEnabled === false), build only the server SEA.\n let seaServerResult: { executablePath: string; executableSize: number } | undefined;\n let seaCliResult: { executablePath: string; executableSize: number } | undefined;\n if (seaEnabled) {\n const { buildSea } = await import('./sea-builder.js');\n\n if (!cliEnabled) {\n // Server-only SEA path (--target node): rebuild bundle as self-contained\n // (inlines all deps) and produce ${name}-bin.\n const seaTempName = `${config.name}.sea-temp`;\n console.log(`${c('cyan', '[build:sea]')} rebuilding server bundle (self-contained)...`);\n const seaBundle = await bundleWithEsbuild(compiledEntry, outDir, config, {\n selfContained: true,\n outputName: seaTempName,\n });\n\n console.log(`${c('cyan', '[build:sea]')} building server SEA binary...`);\n seaServerResult = await buildSea(seaBundle.bundlePath, outDir, config.name);\n fs.unlinkSync(seaBundle.bundlePath);\n console.log(\n `${c('green', '[build:sea]')} server binary: ${path.relative(cwd, seaServerResult.executablePath)} (${formatSize(seaServerResult.executableSize)})`,\n );\n }\n\n if (cliBundlePath) {\n console.log(`${c('cyan', '[build:sea]')} building CLI SEA binary...`);\n seaCliResult = await buildSea(cliBundlePath, outDir, `${config.name}-cli`);\n console.log(\n `${c('green', '[build:sea]')} CLI binary: ${path.relative(cwd, seaCliResult.executablePath)} (${formatSize(seaCliResult.executableSize)})`,\n );\n }\n }\n\n // 9. Write manifest\n const manifestPath = path.join(outDir, `${config.name}.manifest.json`);\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');\n console.log(\n `${c('green', '[build:exec]')} manifest: ${path.relative(cwd, manifestPath)}`,\n );\n\n // 10. Generate runner script (dispatches to CLI bundle or SEA binary)\n const runnerContent = generateRunnerScript(config, !!cliEnabled, !!seaEnabled);\n const runnerPath = path.join(outDir, config.name);\n fs.writeFileSync(runnerPath, runnerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} runner: ${path.relative(cwd, runnerPath)}`,\n );\n\n // 10. Generate installer script\n const installerContent = generateInstallerScript(config, {\n target: cliEnabled ? 'cli' : 'node',\n seaEnabled: !!seaEnabled,\n });\n const installerPath = path.join(outDir, `install-${config.name}.sh`);\n fs.writeFileSync(installerPath, installerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} installer: ${path.relative(cwd, installerPath)}`,\n );\n\n // 12. Clean up intermediate compiled files\n const keepFiles = new Set([\n `${config.name}.bundle.js`,\n `${config.name}-cli.bundle.js`,\n `${config.name}.manifest.json`,\n config.name,\n `install-${config.name}.sh`,\n `${config.name}-bin`,\n `${config.name}-cli-bin`,\n '_skills',\n ]);\n\n const allFiles = fs.readdirSync(outDir);\n let cleaned = 0;\n for (const file of allFiles) {\n if (!keepFiles.has(file)) {\n const filePath = path.join(outDir, file);\n const stat = fs.statSync(filePath);\n // Only clean intermediate compiled files; preserve .md and _skills/ directory\n if (stat.isFile() && !file.endsWith('.md')) {\n fs.unlinkSync(filePath);\n cleaned++;\n }\n }\n }\n if (cleaned > 0) {\n console.log(\n `${c('gray', '[build:exec]')} cleaned ${cleaned} intermediate file(s)`,\n );\n }\n\n // 13. Print summary\n console.log(`\\n${c('green', 'Executable build completed.')}`);\n console.log(`\\n${c('bold', 'Output:')}`);\n console.log(` ${path.relative(cwd, bundleResult.bundlePath)} ${c('gray', `(${formatSize(bundleResult.bundleSize)})`)}`);\n if (cliBundlePath) {\n const cliStat = fs.statSync(cliBundlePath);\n console.log(` ${path.relative(cwd, cliBundlePath)} ${c('gray', `(${formatSize(cliStat.size)})`)}`);\n }\n if (seaServerResult) {\n console.log(` ${path.relative(cwd, seaServerResult.executablePath)} ${c('gray', `(${formatSize(seaServerResult.executableSize)})`)}`);\n }\n if (seaCliResult) {\n console.log(` ${path.relative(cwd, seaCliResult.executablePath)} ${c('gray', `(${formatSize(seaCliResult.executableSize)})`)}`);\n }\n console.log(` ${path.relative(cwd, manifestPath)}`);\n console.log(` ${path.relative(cwd, runnerPath)}`);\n console.log(` ${path.relative(cwd, installerPath)}`);\n\n if (cliEnabled) {\n console.log(`\\n${c('gray', 'Run the CLI:')} ./${path.relative(cwd, runnerPath)} --help`);\n console.log(`${c('gray', 'Start server:')} ./${path.relative(cwd, runnerPath)} serve`);\n } else {\n console.log(`\\n${c('gray', 'Run the server:')} ./${path.relative(cwd, runnerPath)}`);\n }\n if (seaServerResult || seaCliResult) {\n console.log(`\\n${c('yellow', 'Note:')} SEA binaries are native executables. Run directly (not via bash).`);\n }\n console.log(`${c('gray', 'Install to system:')} bash ./${path.relative(cwd, installerPath)}`);\n}\n"]}
|
|
@@ -2,5 +2,11 @@
|
|
|
2
2
|
* Bash installer script generation.
|
|
3
3
|
* Supports interactive and --yes (silent) modes.
|
|
4
4
|
*/
|
|
5
|
-
import { FrontmcpExecConfig } from './config';
|
|
6
|
-
export
|
|
5
|
+
import { type FrontmcpExecConfig } from './config';
|
|
6
|
+
export interface InstallerScriptContext {
|
|
7
|
+
/** Build target this installer was generated for. Drives binary copying and Node version checks. */
|
|
8
|
+
target: 'node' | 'cli';
|
|
9
|
+
/** True when SEA binaries were emitted (CLI mode). Skips the Node version check at install time. */
|
|
10
|
+
seaEnabled: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function generateInstallerScript(config: FrontmcpExecConfig, context?: InstallerScriptContext): string;
|
|
@@ -5,17 +5,45 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.generateInstallerScript = generateInstallerScript;
|
|
8
|
-
|
|
8
|
+
const runner_script_1 = require("./runner-script");
|
|
9
|
+
function generateInstallerScript(config, context = { target: 'node', seaEnabled: false }) {
|
|
9
10
|
const name = config.name;
|
|
10
11
|
const nativeAddons = config.dependencies?.nativeAddons || [];
|
|
11
12
|
const storageType = config.storage?.type || 'none';
|
|
12
|
-
|
|
13
|
+
// Sanitize before interpolating into bash echo / error messages — the
|
|
14
|
+
// user-controlled `nodeVersion` ends up in command lines verbatim.
|
|
15
|
+
const nodeVersion = (0, runner_script_1.sanitizeShellLiteral)(config.nodeVersion || '>=22.0.0');
|
|
13
16
|
const minNodeMajor = extractMinMajor(nodeVersion);
|
|
17
|
+
// CLI/SEA installs ship a self-contained binary — no Node runtime required
|
|
18
|
+
// at install or run time. Skip the Node check entirely; the binary is the
|
|
19
|
+
// whole point of `--target cli`.
|
|
20
|
+
const seaCli = context.target === 'cli' && context.seaEnabled;
|
|
21
|
+
const nodeCheck = seaCli
|
|
22
|
+
? '# CLI/SEA install: Node.js not required at runtime — skipping version check.'
|
|
23
|
+
: `# Check Node.js
|
|
24
|
+
if ! command -v node &> /dev/null; then
|
|
25
|
+
echo "Error: Node.js is required."
|
|
26
|
+
echo "Install Node.js ${nodeVersion}: https://nodejs.org"
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
NODE_MAJOR=$(node -e "console.log(process.versions.node.split('.')[0])")
|
|
31
|
+
if [ "\${NODE_MAJOR}" -lt "${minNodeMajor}" ]; then
|
|
32
|
+
echo "Error: Node.js ${nodeVersion} required, found v$(node -v)"
|
|
33
|
+
exit 1
|
|
34
|
+
fi`;
|
|
35
|
+
// For SEA-CLI installs, also copy the CLI binary the runner exec's.
|
|
36
|
+
// Without this the installer leaves a runner pointing at a missing file.
|
|
37
|
+
const seaBinaryCopy = seaCli
|
|
38
|
+
? `# Copy SEA binary that the runner exec's
|
|
39
|
+
cp "\${SCRIPT_DIR}/${name}-cli-bin" "\${INSTALL_DIR}/"
|
|
40
|
+
chmod +x "\${INSTALL_DIR}/${name}-cli-bin"`
|
|
41
|
+
: '# No SEA binary to copy (JS bundle mode)';
|
|
14
42
|
return `#!/usr/bin/env bash
|
|
15
43
|
set -euo pipefail
|
|
16
44
|
|
|
17
45
|
# install-${name}.sh — FrontMCP App Installer
|
|
18
|
-
# Generated by frontmcp build --target
|
|
46
|
+
# Generated by frontmcp build --target ${context.target}
|
|
19
47
|
|
|
20
48
|
SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
|
21
49
|
APP_NAME="${name}"
|
|
@@ -32,18 +60,7 @@ done
|
|
|
32
60
|
echo "Installing \${APP_NAME}..."
|
|
33
61
|
echo ""
|
|
34
62
|
|
|
35
|
-
|
|
36
|
-
if ! command -v node &> /dev/null; then
|
|
37
|
-
echo "Error: Node.js is required."
|
|
38
|
-
echo "Install Node.js ${nodeVersion}: https://nodejs.org"
|
|
39
|
-
exit 1
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
NODE_MAJOR=$(node -e "console.log(process.versions.node.split('.')[0])")
|
|
43
|
-
if [ "\${NODE_MAJOR}" -lt "${minNodeMajor}" ]; then
|
|
44
|
-
echo "Error: Node.js ${nodeVersion} required, found v$(node -v)"
|
|
45
|
-
exit 1
|
|
46
|
-
fi
|
|
63
|
+
${nodeCheck}
|
|
47
64
|
|
|
48
65
|
# Create install directory
|
|
49
66
|
mkdir -p "\${INSTALL_DIR}"
|
|
@@ -54,6 +71,8 @@ cp "\${SCRIPT_DIR}/${name}.manifest.json" "\${INSTALL_DIR}/"
|
|
|
54
71
|
cp "\${SCRIPT_DIR}/${name}" "\${INSTALL_DIR}/"
|
|
55
72
|
chmod +x "\${INSTALL_DIR}/${name}"
|
|
56
73
|
|
|
74
|
+
${seaBinaryCopy}
|
|
75
|
+
|
|
57
76
|
${nativeAddons.length > 0 ? generateNativeAddonInstall(nativeAddons) : '# No native addons required'}
|
|
58
77
|
|
|
59
78
|
${storageType === 'sqlite' ? generateSqliteSetup(name) : '# No storage setup required'}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer-script.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/installer-script.ts"],"names":[],"mappings":";AAAA;;;GAGG;;
|
|
1
|
+
{"version":3,"file":"installer-script.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/installer-script.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAYH,0DA6FC;AAtGD,mDAAuD;AASvD,SAAgB,uBAAuB,CACrC,MAA0B,EAC1B,UAAkC,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE;IAEvE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,EAAE,YAAY,IAAI,EAAE,CAAC;IAC7D,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,IAAI,MAAM,CAAC;IACnD,sEAAsE;IACtE,mEAAmE;IACnE,MAAM,WAAW,GAAG,IAAA,oCAAoB,EAAC,MAAM,CAAC,WAAW,IAAI,UAAU,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAElD,2EAA2E;IAC3E,0EAA0E;IAC1E,iCAAiC;IACjC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;IAC9D,MAAM,SAAS,GAAG,MAAM;QACtB,CAAC,CAAC,8EAA8E;QAChF,CAAC,CAAC;;;0BAGoB,WAAW;;;;;6BAKR,YAAY;yBAChB,WAAW;;GAEjC,CAAC;IAEF,oEAAoE;IACpE,yEAAyE;IACzE,MAAM,aAAa,GAAG,MAAM;QAC1B,CAAC,CAAC;qBACe,IAAI;4BACG,IAAI,WAAW;QACvC,CAAC,CAAC,0CAA0C,CAAC;IAE/C,OAAO;;;YAGG,IAAI;yCACyB,OAAO,CAAC,MAAM;;;YAG3C,IAAI;;;;;;;;;;;;;;EAcd,SAAS;;;;;;qBAMU,IAAI;qBACJ,IAAI;qBACJ,IAAI;4BACG,IAAI;;EAE9B,aAAa;;EAEb,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,6BAA6B;;EAElG,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,6BAA6B;;;;iDAIrC,IAAI;;;;;;;;;;;;;CAapD,CAAC;AACF,CAAC;AAED,SAAS,0BAA0B,CAAC,MAAgB;IAClD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxD,OAAO;;2EAEkE,SAAS;CACnF,CAAC;AACF,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,OAAO;oCAC2B,IAAI;;0CAEE,IAAI;CAC7C,CAAC;AACF,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7C,CAAC","sourcesContent":["/**\n * Bash installer script generation.\n * Supports interactive and --yes (silent) modes.\n */\n\nimport { type FrontmcpExecConfig } from './config';\nimport { sanitizeShellLiteral } from './runner-script';\n\nexport interface InstallerScriptContext {\n /** Build target this installer was generated for. Drives binary copying and Node version checks. */\n target: 'node' | 'cli';\n /** True when SEA binaries were emitted (CLI mode). Skips the Node version check at install time. */\n seaEnabled: boolean;\n}\n\nexport function generateInstallerScript(\n config: FrontmcpExecConfig,\n context: InstallerScriptContext = { target: 'node', seaEnabled: false },\n): string {\n const name = config.name;\n const nativeAddons = config.dependencies?.nativeAddons || [];\n const storageType = config.storage?.type || 'none';\n // Sanitize before interpolating into bash echo / error messages — the\n // user-controlled `nodeVersion` ends up in command lines verbatim.\n const nodeVersion = sanitizeShellLiteral(config.nodeVersion || '>=22.0.0');\n const minNodeMajor = extractMinMajor(nodeVersion);\n\n // CLI/SEA installs ship a self-contained binary — no Node runtime required\n // at install or run time. Skip the Node check entirely; the binary is the\n // whole point of `--target cli`.\n const seaCli = context.target === 'cli' && context.seaEnabled;\n const nodeCheck = seaCli\n ? '# CLI/SEA install: Node.js not required at runtime — skipping version check.'\n : `# Check Node.js\nif ! command -v node &> /dev/null; then\n echo \"Error: Node.js is required.\"\n echo \"Install Node.js ${nodeVersion}: https://nodejs.org\"\n exit 1\nfi\n\nNODE_MAJOR=$(node -e \"console.log(process.versions.node.split('.')[0])\")\nif [ \"\\${NODE_MAJOR}\" -lt \"${minNodeMajor}\" ]; then\n echo \"Error: Node.js ${nodeVersion} required, found v$(node -v)\"\n exit 1\nfi`;\n\n // For SEA-CLI installs, also copy the CLI binary the runner exec's.\n // Without this the installer leaves a runner pointing at a missing file.\n const seaBinaryCopy = seaCli\n ? `# Copy SEA binary that the runner exec's\ncp \"\\${SCRIPT_DIR}/${name}-cli-bin\" \"\\${INSTALL_DIR}/\"\nchmod +x \"\\${INSTALL_DIR}/${name}-cli-bin\"`\n : '# No SEA binary to copy (JS bundle mode)';\n\n return `#!/usr/bin/env bash\nset -euo pipefail\n\n# install-${name}.sh — FrontMCP App Installer\n# Generated by frontmcp build --target ${context.target}\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nAPP_NAME=\"${name}\"\nINSTALL_DIR=\"\\${HOME}/.frontmcp/apps/\\${APP_NAME}\"\nSILENT=false\n\n# Parse args\nfor arg in \"$@\"; do\n case \"\\${arg}\" in\n --yes|-y) SILENT=true ;;\n esac\ndone\n\necho \"Installing \\${APP_NAME}...\"\necho \"\"\n\n${nodeCheck}\n\n# Create install directory\nmkdir -p \"\\${INSTALL_DIR}\"\n\n# Copy files\ncp \"\\${SCRIPT_DIR}/${name}.bundle.js\" \"\\${INSTALL_DIR}/\"\ncp \"\\${SCRIPT_DIR}/${name}.manifest.json\" \"\\${INSTALL_DIR}/\"\ncp \"\\${SCRIPT_DIR}/${name}\" \"\\${INSTALL_DIR}/\"\nchmod +x \"\\${INSTALL_DIR}/${name}\"\n\n${seaBinaryCopy}\n\n${nativeAddons.length > 0 ? generateNativeAddonInstall(nativeAddons) : '# No native addons required'}\n\n${storageType === 'sqlite' ? generateSqliteSetup(name) : '# No storage setup required'}\n\n# Run questionnaire if manifest has setup and not silent\nif [ \"\\${SILENT}\" = false ] && command -v frontmcp &> /dev/null; then\n if node -e \"const m=require('\\${INSTALL_DIR}/${name}.manifest.json'); process.exit(m.setup ? 0 : 1)\" 2>/dev/null; then\n echo \"\"\n echo \"Running setup questionnaire...\"\n frontmcp configure \"\\${APP_NAME}\"\n fi\nfi\n\necho \"\"\necho \"Installed to \\${INSTALL_DIR}\"\necho \"\"\necho \"Start with:\"\necho \" frontmcp start \\${APP_NAME}\"\necho \"\"\n`;\n}\n\nfunction generateNativeAddonInstall(addons: string[]): string {\n const addonList = addons.map((a) => `\"${a}\"`).join(' ');\n return `# Install native addons\necho \"Installing native dependencies...\"\n(cd \"\\${INSTALL_DIR}\" && npm init -y --silent 2>/dev/null && npm install ${addonList} --save --silent)\n`;\n}\n\nfunction generateSqliteSetup(name: string): string {\n return `# Create SQLite data directory\nDATA_DIR=\"\\${HOME}/.frontmcp/data/${name}\"\nmkdir -p \"\\${DATA_DIR}\"\necho \"FRONTMCP_SQLITE_PATH=\\${DATA_DIR}/${name}.sqlite\" >> \"\\${INSTALL_DIR}/.env\"\n`;\n}\n\nfunction extractMinMajor(version: string): number {\n const match = version.match(/(\\d+)/);\n return match ? parseInt(match[1], 10) : 22;\n}\n"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* The manifest is a JSON file that describes the bundled app
|
|
4
4
|
* for installation and runtime.
|
|
5
5
|
*/
|
|
6
|
-
import { FrontmcpExecConfig } from './config';
|
|
6
|
+
import { type FrontmcpExecConfig } from './config';
|
|
7
7
|
export interface ExecManifest {
|
|
8
8
|
name: string;
|
|
9
9
|
version: string;
|
|
@@ -12,7 +12,12 @@ export interface ExecManifest {
|
|
|
12
12
|
type: 'sqlite' | 'redis' | 'none';
|
|
13
13
|
required: boolean;
|
|
14
14
|
};
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Server bind config. Omitted entirely for `--target cli` (CLI builds don't
|
|
17
|
+
* bind a port — the manifest is consumed by `frontmcp install`, container
|
|
18
|
+
* `EXPOSE`, and proxy generators).
|
|
19
|
+
*/
|
|
20
|
+
network?: {
|
|
16
21
|
defaultPort: number;
|
|
17
22
|
supportsSocket: boolean;
|
|
18
23
|
};
|
|
@@ -50,4 +55,12 @@ export interface ManifestSetupStep {
|
|
|
50
55
|
next?: string | Record<string, string>;
|
|
51
56
|
showWhen?: Record<string, string | string[]>;
|
|
52
57
|
}
|
|
53
|
-
export
|
|
58
|
+
export interface GenerateManifestContext {
|
|
59
|
+
/** Build target the manifest is being written for. */
|
|
60
|
+
target?: 'node' | 'cli';
|
|
61
|
+
/** Port declared via `@FrontMcp({ http: { port } })` on the user's entry. */
|
|
62
|
+
decoratorHttpPort?: number;
|
|
63
|
+
/** `cli.outputDefault` from frontmcp.config.deployments[].cli (per-deployment). */
|
|
64
|
+
outputDefault?: 'text' | 'json';
|
|
65
|
+
}
|
|
66
|
+
export declare function generateManifest(config: FrontmcpExecConfig, bundleFilename: string, context?: GenerateManifestContext): ExecManifest;
|
|
@@ -7,7 +7,14 @@
|
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.generateManifest = generateManifest;
|
|
9
9
|
const setup_1 = require("./setup");
|
|
10
|
-
function generateManifest(config, bundleFilename) {
|
|
10
|
+
function generateManifest(config, bundleFilename, context = {}) {
|
|
11
|
+
// Resolve port precedence (highest → lowest):
|
|
12
|
+
// 1. `frontmcp.config.network.defaultPort` (build-config override)
|
|
13
|
+
// 2. `@FrontMcp({ http: { port } })` (decorator metadata)
|
|
14
|
+
// 3. 3000 (Express default)
|
|
15
|
+
// The legacy `3001` was a phantom default that didn't match what the
|
|
16
|
+
// server actually bound (#371).
|
|
17
|
+
const resolvedPort = config.network?.defaultPort ?? context.decoratorHttpPort ?? 3000;
|
|
11
18
|
const manifest = {
|
|
12
19
|
name: config.name,
|
|
13
20
|
version: config.version || '1.0.0',
|
|
@@ -16,16 +23,21 @@ function generateManifest(config, bundleFilename) {
|
|
|
16
23
|
type: config.storage?.type || 'none',
|
|
17
24
|
required: config.storage?.required ?? false,
|
|
18
25
|
},
|
|
19
|
-
network: {
|
|
20
|
-
defaultPort: config.network?.defaultPort || 3001,
|
|
21
|
-
supportsSocket: config.network?.supportsSocket ?? true,
|
|
22
|
-
},
|
|
23
26
|
dependencies: {
|
|
24
27
|
system: config.dependencies?.system || [],
|
|
25
28
|
nativeAddons: config.dependencies?.nativeAddons || [],
|
|
26
29
|
},
|
|
27
30
|
bundle: bundleFilename,
|
|
28
31
|
};
|
|
32
|
+
// Network section is server-build-specific. CLI builds don't bind a port,
|
|
33
|
+
// so emitting `network.defaultPort` confuses tooling that drives container
|
|
34
|
+
// `EXPOSE` / reverse proxies (#371 note).
|
|
35
|
+
if (context.target !== 'cli') {
|
|
36
|
+
manifest.network = {
|
|
37
|
+
defaultPort: resolvedPort,
|
|
38
|
+
supportsSocket: config.network?.supportsSocket ?? true,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
29
41
|
// Convert setup steps — serialize Zod schemas to JSON Schema
|
|
30
42
|
if (config.setup?.steps && config.setup.steps.length > 0) {
|
|
31
43
|
manifest.setup = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/manifest.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/manifest.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAmEH,4CA8CC;AA9GD,mCAA6E;AAgE7E,SAAgB,gBAAgB,CAC9B,MAA0B,EAC1B,cAAsB,EACtB,UAAmC,EAAE;IAErC,8CAA8C;IAC9C,6EAA6E;IAC7E,0EAA0E;IAC1E,uEAAuE;IACvE,qEAAqE;IACrE,gCAAgC;IAChC,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,EAAE,WAAW,IAAI,OAAO,CAAC,iBAAiB,IAAI,IAAI,CAAC;IAEtF,MAAM,QAAQ,GAAiB;QAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,OAAO;QAClC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,UAAU;QAC7C,OAAO,EAAE;YACP,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,IAAI,MAAM;YACpC,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,IAAI,KAAK;SAC5C;QACD,YAAY,EAAE;YACZ,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,IAAI,EAAE;YACzC,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,YAAY,IAAI,EAAE;SACtD;QACD,MAAM,EAAE,cAAc;KACvB,CAAC;IAEF,0EAA0E;IAC1E,2EAA2E;IAC3E,0CAA0C;IAC1C,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,QAAQ,CAAC,OAAO,GAAG;YACjB,WAAW,EAAE,YAAY;YACzB,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,cAAc,IAAI,IAAI;SACvD,CAAC;IACJ,CAAC;IAED,6DAA6D;IAC7D,IAAI,MAAM,CAAC,KAAK,EAAE,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,QAAQ,CAAC,KAAK,GAAG;YACf,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;SAC7D,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CAAC,IAAe;IACpC,IAAI,UAAU,GAA4B,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAE7D,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,8CAA8C;QAC9C,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IAC/B,CAAC;SAAM,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,oCAAoC;QACpC,UAAU,GAAG,IAAA,6BAAqB,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU;QACV,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,IAAA,mBAAW,EAAC,IAAI,CAAC,EAAE,CAAC;QACrC,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC;AACJ,CAAC","sourcesContent":["/**\n * ExecManifest type + generation.\n * The manifest is a JSON file that describes the bundled app\n * for installation and runtime.\n */\n\nimport { type FrontmcpExecConfig } from './config';\nimport { type SetupStep, zodSchemaToJsonSchema, idToEnvName } from './setup';\n\nexport interface ExecManifest {\n name: string;\n version: string;\n nodeVersion: string;\n storage: {\n type: 'sqlite' | 'redis' | 'none';\n required: boolean;\n };\n /**\n * Server bind config. Omitted entirely for `--target cli` (CLI builds don't\n * bind a port — the manifest is consumed by `frontmcp install`, container\n * `EXPOSE`, and proxy generators).\n */\n network?: {\n defaultPort: number;\n supportsSocket: boolean;\n };\n dependencies: {\n system: string[];\n nativeAddons: string[];\n };\n bundle: string; // bundle filename\n setup?: {\n steps: ManifestSetupStep[];\n };\n cli?: {\n enabled: boolean;\n cliBundle: string;\n outputDefault: 'text' | 'json';\n authRequired: boolean;\n toolCount: number;\n resourceCount: number;\n templateCount: number;\n promptCount: number;\n oauthEnabled: boolean;\n skillsEnabled?: boolean;\n jobsEnabled?: boolean;\n workflowsEnabled?: boolean;\n };\n}\n\nexport interface ManifestSetupStep {\n id: string;\n prompt: string;\n description?: string;\n jsonSchema: Record<string, unknown>;\n env: string;\n sensitive?: boolean;\n group?: string;\n next?: string | Record<string, string>;\n showWhen?: Record<string, string | string[]>;\n}\n\nexport interface GenerateManifestContext {\n /** Build target the manifest is being written for. */\n target?: 'node' | 'cli';\n /** Port declared via `@FrontMcp({ http: { port } })` on the user's entry. */\n decoratorHttpPort?: number;\n /** `cli.outputDefault` from frontmcp.config.deployments[].cli (per-deployment). */\n outputDefault?: 'text' | 'json';\n}\n\nexport function generateManifest(\n config: FrontmcpExecConfig,\n bundleFilename: string,\n context: GenerateManifestContext = {},\n): ExecManifest {\n // Resolve port precedence (highest → lowest):\n // 1. `frontmcp.config.network.defaultPort` (build-config override)\n // 2. `@FrontMcp({ http: { port } })` (decorator metadata)\n // 3. 3000 (Express default)\n // The legacy `3001` was a phantom default that didn't match what the\n // server actually bound (#371).\n const resolvedPort = config.network?.defaultPort ?? context.decoratorHttpPort ?? 3000;\n\n const manifest: ExecManifest = {\n name: config.name,\n version: config.version || '1.0.0',\n nodeVersion: config.nodeVersion || '>=22.0.0',\n storage: {\n type: config.storage?.type || 'none',\n required: config.storage?.required ?? false,\n },\n dependencies: {\n system: config.dependencies?.system || [],\n nativeAddons: config.dependencies?.nativeAddons || [],\n },\n bundle: bundleFilename,\n };\n\n // Network section is server-build-specific. CLI builds don't bind a port,\n // so emitting `network.defaultPort` confuses tooling that drives container\n // `EXPOSE` / reverse proxies (#371 note).\n if (context.target !== 'cli') {\n manifest.network = {\n defaultPort: resolvedPort,\n supportsSocket: config.network?.supportsSocket ?? true,\n };\n }\n\n // Convert setup steps — serialize Zod schemas to JSON Schema\n if (config.setup?.steps && config.setup.steps.length > 0) {\n manifest.setup = {\n steps: config.setup.steps.map((step) => serializeStep(step)),\n };\n }\n\n return manifest;\n}\n\nfunction serializeStep(step: SetupStep): ManifestSetupStep {\n let jsonSchema: Record<string, unknown> = { type: 'string' };\n\n if (step.jsonSchema) {\n // Already serialized (e.g., from JSON config)\n jsonSchema = step.jsonSchema;\n } else if (step.schema) {\n // Convert Zod schema to JSON Schema\n jsonSchema = zodSchemaToJsonSchema(step.schema);\n }\n\n return {\n id: step.id,\n prompt: step.prompt,\n description: step.description,\n jsonSchema,\n env: step.env || idToEnvName(step.id),\n sensitive: step.sensitive,\n group: step.group,\n next: step.next,\n showWhen: step.showWhen,\n };\n}\n"]}
|
|
@@ -2,5 +2,13 @@
|
|
|
2
2
|
* Bash runner script generation.
|
|
3
3
|
* The runner checks Node.js, loads .env, and runs the bundle.
|
|
4
4
|
*/
|
|
5
|
-
import { FrontmcpExecConfig } from './config';
|
|
5
|
+
import { type FrontmcpExecConfig } from './config';
|
|
6
|
+
/**
|
|
7
|
+
* Defense-in-depth: scrub anything outside `[a-zA-Z0-9._+-]` from values that
|
|
8
|
+
* the runner / installer scripts interpolate into bash. The user owns
|
|
9
|
+
* `frontmcp.config`, so a malicious value would be self-inflicted, but the
|
|
10
|
+
* generated scripts are committed into repos and downloaded by end-users —
|
|
11
|
+
* so we keep them safe to copy/paste regardless of upstream config hygiene.
|
|
12
|
+
*/
|
|
13
|
+
export declare function sanitizeShellLiteral(value: string): string;
|
|
6
14
|
export declare function generateRunnerScript(config: FrontmcpExecConfig, cliMode?: boolean, seaMode?: boolean): string;
|
|
@@ -4,9 +4,67 @@
|
|
|
4
4
|
* The runner checks Node.js, loads .env, and runs the bundle.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.sanitizeShellLiteral = sanitizeShellLiteral;
|
|
7
8
|
exports.generateRunnerScript = generateRunnerScript;
|
|
9
|
+
/**
|
|
10
|
+
* Defense-in-depth: scrub anything outside `[a-zA-Z0-9._+-]` from values that
|
|
11
|
+
* the runner / installer scripts interpolate into bash. The user owns
|
|
12
|
+
* `frontmcp.config`, so a malicious value would be self-inflicted, but the
|
|
13
|
+
* generated scripts are committed into repos and downloaded by end-users —
|
|
14
|
+
* so we keep them safe to copy/paste regardless of upstream config hygiene.
|
|
15
|
+
*/
|
|
16
|
+
function sanitizeShellLiteral(value) {
|
|
17
|
+
// `-` placed last in the character class is literal, so no escape needed.
|
|
18
|
+
return value.replace(/[^A-Za-z0-9._+-]/g, '_');
|
|
19
|
+
}
|
|
8
20
|
function generateRunnerScript(config, cliMode, seaMode) {
|
|
9
21
|
const name = config.name;
|
|
22
|
+
const version = sanitizeShellLiteral(config.version || '0.0.0');
|
|
23
|
+
// #377 — `--target node` runner used to silently exec the bundle for any
|
|
24
|
+
// flag, so `./frontegg-bin --help` quietly booted the HTTP server. Intercept
|
|
25
|
+
// help/version here so server-mode runners behave like a normal CLI for
|
|
26
|
+
// those flags. CLI-mode runners pass everything through to the bundle's
|
|
27
|
+
// own commander parser.
|
|
28
|
+
const helpInterceptor = !cliMode
|
|
29
|
+
? `
|
|
30
|
+
# Intercept standard CLI flags before booting the long-running server.
|
|
31
|
+
case "\${1:-}" in
|
|
32
|
+
-h|--help)
|
|
33
|
+
cat <<EOF
|
|
34
|
+
${name} v${version} — FrontMCP server
|
|
35
|
+
|
|
36
|
+
This binary starts a long-running MCP HTTP server.
|
|
37
|
+
|
|
38
|
+
Usage:
|
|
39
|
+
${name} Start the server
|
|
40
|
+
${name} --help Show this help
|
|
41
|
+
${name} --version Show version
|
|
42
|
+
${name} --print-manifest Print the deployment manifest as JSON
|
|
43
|
+
|
|
44
|
+
Configure via environment variables, .env, or frontmcp.config.
|
|
45
|
+
|
|
46
|
+
For a CLI-style binary that exposes tools/resources/prompts as subcommands,
|
|
47
|
+
build with: frontmcp build --target cli
|
|
48
|
+
EOF
|
|
49
|
+
exit 0
|
|
50
|
+
;;
|
|
51
|
+
--version)
|
|
52
|
+
echo "${name} ${version}"
|
|
53
|
+
exit 0
|
|
54
|
+
;;
|
|
55
|
+
--print-manifest)
|
|
56
|
+
cat "\${SCRIPT_DIR}/${name}.manifest.json"
|
|
57
|
+
exit 0
|
|
58
|
+
;;
|
|
59
|
+
--*)
|
|
60
|
+
echo "Error: unsupported flag '\${1}' on the server runner."
|
|
61
|
+
echo "This binary is a long-running HTTP server; flag-style invocation is reserved." >&2
|
|
62
|
+
echo "Run with no args to start, or build with --target cli for a CLI binary." >&2
|
|
63
|
+
exit 2
|
|
64
|
+
;;
|
|
65
|
+
esac
|
|
66
|
+
`
|
|
67
|
+
: '';
|
|
10
68
|
// SEA mode: binary is self-contained, no Node.js required
|
|
11
69
|
if (seaMode) {
|
|
12
70
|
const binary = cliMode ? `${name}-cli-bin` : `${name}-bin`;
|
|
@@ -26,7 +84,7 @@ if [ ! -f "\${BINARY}" ]; then
|
|
|
26
84
|
echo "Error: Binary not found at \${BINARY}"
|
|
27
85
|
exit 1
|
|
28
86
|
fi
|
|
29
|
-
|
|
87
|
+
${helpInterceptor}
|
|
30
88
|
# Load .env if present
|
|
31
89
|
ENV_FILE="\${SCRIPT_DIR}/.env"
|
|
32
90
|
if [ -f "\${ENV_FILE}" ]; then
|
|
@@ -55,7 +113,7 @@ ${comment}
|
|
|
55
113
|
|
|
56
114
|
SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
|
57
115
|
BUNDLE="${bundle}"
|
|
58
|
-
|
|
116
|
+
${helpInterceptor}
|
|
59
117
|
# Check Node.js
|
|
60
118
|
if ! command -v node &> /dev/null; then
|
|
61
119
|
echo "Error: Node.js is required but not installed."
|