frontmcp 1.1.2-beta.1 → 1.1.2
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 +4 -4
- package/src/commands/build/adapters/lambda.js +13 -8
- package/src/commands/build/adapters/lambda.js.map +1 -1
- package/src/commands/build/adapters/vercel.js +24 -10
- package/src/commands/build/adapters/vercel.js.map +1 -1
- package/src/commands/build/bundler.js +10 -0
- package/src/commands/build/bundler.js.map +1 -1
- package/src/commands/build/exec/config.d.ts +1 -1
- package/src/commands/build/exec/config.js +30 -1
- package/src/commands/build/exec/config.js.map +1 -1
- package/src/commands/build/exec/index.d.ts +1 -0
- package/src/commands/build/exec/index.js +6 -0
- package/src/commands/build/exec/index.js.map +1 -1
- package/src/commands/build/index.js +1 -0
- package/src/commands/build/index.js.map +1 -1
- package/src/config/frontmcp-config.loader.js +31 -18
- package/src/config/frontmcp-config.loader.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontmcp",
|
|
3
|
-
"version": "1.1.2
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "FrontMCP command line interface",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"homepage": "https://docs.agentfront.dev",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@clack/prompts": "^0.10.0",
|
|
34
|
-
"@frontmcp/lazy-zod": "1.1.2
|
|
35
|
-
"@frontmcp/utils": "1.1.2
|
|
36
|
-
"@frontmcp/skills": "1.1.2
|
|
34
|
+
"@frontmcp/lazy-zod": "1.1.2",
|
|
35
|
+
"@frontmcp/utils": "1.1.2",
|
|
36
|
+
"@frontmcp/skills": "1.1.2",
|
|
37
37
|
"commander": "^13.0.0",
|
|
38
38
|
"tslib": "^2.3.0",
|
|
39
39
|
"vectoriadb": "^2.2.0",
|
|
@@ -20,12 +20,16 @@ const path = tslib_1.__importStar(require("path"));
|
|
|
20
20
|
* @see https://github.com/codegenie/serverless-express
|
|
21
21
|
*/
|
|
22
22
|
exports.lambdaAdapter = {
|
|
23
|
-
|
|
23
|
+
// #368 round-3 — switched from 'esnext' to 'commonjs' for the same reason
|
|
24
|
+
// as the vercel adapter: strict-ESM rspack rejects TS-emitted extensionless
|
|
25
|
+
// relative imports, and the `byDependency.fullySpecified: false` workaround
|
|
26
|
+
// didn't suppress it reliably. Lambda's Node runtime accepts CJS handlers,
|
|
27
|
+
// and the bundled output is a CJS `handler.cjs` either way.
|
|
28
|
+
moduleFormat: 'commonjs',
|
|
24
29
|
shouldBundle: true,
|
|
25
30
|
bundleOutput: 'handler.cjs',
|
|
26
|
-
getSetupTemplate: () => `// Serverless environment setup - MUST be
|
|
31
|
+
getSetupTemplate: () => `// Serverless environment setup - MUST be required first
|
|
27
32
|
// This sets FRONTMCP_SERVERLESS before any decorators run
|
|
28
|
-
// Required because ESM hoists imports before other statements
|
|
29
33
|
process.env.FRONTMCP_SERVERLESS = '1';
|
|
30
34
|
process.env.FRONTMCP_DEPLOYMENT_MODE = 'serverless';
|
|
31
35
|
`,
|
|
@@ -35,10 +39,11 @@ process.env.FRONTMCP_DEPLOYMENT_MODE = 'serverless';
|
|
|
35
39
|
// IMPORTANT: This adapter requires @codegenie/serverless-express
|
|
36
40
|
// Install it with: npm install @codegenie/serverless-express
|
|
37
41
|
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
require('./serverless-setup.js');
|
|
43
|
+
require('${mainModulePath}');
|
|
44
|
+
const { getServerlessHandlerAsync } = require('@frontmcp/sdk');
|
|
45
|
+
const serverlessExpressMod = require('@codegenie/serverless-express');
|
|
46
|
+
const serverlessExpress = serverlessExpressMod.default || serverlessExpressMod;
|
|
42
47
|
|
|
43
48
|
let serverlessExpressInstance = null;
|
|
44
49
|
|
|
@@ -47,7 +52,7 @@ async function setup() {
|
|
|
47
52
|
serverlessExpressInstance = serverlessExpress({ app });
|
|
48
53
|
}
|
|
49
54
|
|
|
50
|
-
|
|
55
|
+
exports.handler = async (event, context) => {
|
|
51
56
|
if (!serverlessExpressInstance) {
|
|
52
57
|
await setup();
|
|
53
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lambda.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/lambda.ts"],"names":[],"mappings":";;;;AAAA,+CAAyB;AACzB,mDAA6B;AAG7B;;;;;;;;;;;;;;GAcG;AACU,QAAA,aAAa,GAAoB;IAC5C,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"lambda.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/lambda.ts"],"names":[],"mappings":";;;;AAAA,+CAAyB;AACzB,mDAA6B;AAG7B;;;;;;;;;;;;;;GAcG;AACU,QAAA,aAAa,GAAoB;IAC5C,0EAA0E;IAC1E,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,4DAA4D;IAC5D,YAAY,EAAE,UAAU;IACxB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,aAAa;IAE3B,gBAAgB,EAAE,GAAG,EAAE,CAAC;;;;CAIzB;IAEC,gBAAgB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC;;;;;;;WAOrC,cAAc;;;;;;;;;;;;;;;;;;CAkBxB;IAEC,uEAAuE;IACvE,2EAA2E;IAC3E,uEAAuE;IACvE,sEAAsE;IACtE,uEAAuE;IACvE,2DAA2D;IAC3D,QAAQ,EAAE,GAAG,EAAE;QACb,IAAI,CAAC;YACH,yEAAyE;YACzE,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YAClC,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC;gBACpB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,CAAC,CAAC;gBAC/F,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,OAAO;gBAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC/B,IAAI,IAAI,KAAK,GAAG;oBAAE,MAAM;gBACxB,GAAG,GAAG,IAAI,CAAC;YACb,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,8EAA8E;QAChF,CAAC;QACD,MAAM,IAAI,KAAK,CACb,qFAAqF;YACnF,iCAAiC;YACjC,iDAAiD;YACjD,6CAA6C,CAChD,CAAC;IACJ,CAAC;IAED,qEAAqE;CACtE,CAAC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport type { AdapterTemplate } from '../types';\n\n/**\n * AWS Lambda adapter - serverless deployment on AWS Lambda.\n * Compiles to ESM, bundles with rspack to CJS for maximum compatibility.\n *\n * Prerequisites:\n * npm install @codegenie/serverless-express\n *\n * The build process:\n * 1. TypeScript compiles to ESM in dist/\n * 2. serverless-setup.js is generated (sets FRONTMCP_SERVERLESS=1)\n * 3. index.js imports setup first, then main module\n * 4. rspack bundles everything into handler.cjs\n *\n * @see https://github.com/codegenie/serverless-express\n */\nexport const lambdaAdapter: AdapterTemplate = {\n // #368 round-3 — switched from 'esnext' to 'commonjs' for the same reason\n // as the vercel adapter: strict-ESM rspack rejects TS-emitted extensionless\n // relative imports, and the `byDependency.fullySpecified: false` workaround\n // didn't suppress it reliably. Lambda's Node runtime accepts CJS handlers,\n // and the bundled output is a CJS `handler.cjs` either way.\n moduleFormat: 'commonjs',\n shouldBundle: true,\n bundleOutput: 'handler.cjs',\n\n getSetupTemplate: () => `// Serverless environment setup - MUST be required first\n// This sets FRONTMCP_SERVERLESS before any decorators run\nprocess.env.FRONTMCP_SERVERLESS = '1';\nprocess.env.FRONTMCP_DEPLOYMENT_MODE = 'serverless';\n`,\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated AWS Lambda entry point\n// Generated by: frontmcp build --target lambda\n//\n// IMPORTANT: This adapter requires @codegenie/serverless-express\n// Install it with: npm install @codegenie/serverless-express\n//\nrequire('./serverless-setup.js');\nrequire('${mainModulePath}');\nconst { getServerlessHandlerAsync } = require('@frontmcp/sdk');\nconst serverlessExpressMod = require('@codegenie/serverless-express');\nconst serverlessExpress = serverlessExpressMod.default || serverlessExpressMod;\n\nlet serverlessExpressInstance = null;\n\nasync function setup() {\n const app = await getServerlessHandlerAsync();\n serverlessExpressInstance = serverlessExpress({ app });\n}\n\nexports.handler = async (event, context) => {\n if (!serverlessExpressInstance) {\n await setup();\n }\n return serverlessExpressInstance(event, context);\n};\n`,\n\n // #368 round-2 — `@codegenie/serverless-express` is a peer dep on this\n // adapter (the lambda runtime ships it via Layer or the user installs it).\n // The bundler externalizes it so rspack doesn't try to bundle it; this\n // validate hook surfaces a clear error at build time when the package\n // isn't installed locally either, instead of letting the user discover\n // a runtime \"Cannot find module\" error in CloudWatch logs.\n validate: () => {\n try {\n // Walk node_modules from cwd upward so monorepos / hoisted layouts work.\n let dir = process.cwd();\n const root = path.parse(dir).root;\n while (dir !== root) {\n const pkg = path.join(dir, 'node_modules', '@codegenie', 'serverless-express', 'package.json');\n if (fs.existsSync(pkg)) return;\n const next = path.dirname(dir);\n if (next === dir) break;\n dir = next;\n }\n } catch {\n // Fall through to throw — accessibility errors mean we can't verify presence.\n }\n throw new Error(\n `[--target lambda] missing required peer dependency @codegenie/serverless-express.\\n` +\n ` Install it in your project:\\n` +\n ` npm install @codegenie/serverless-express\\n` +\n ` (or use a Lambda Layer that provides it).`,\n );\n },\n\n // No config file - user manages serverless.yml, SAM template, or CDK\n};\n"]}
|
|
@@ -48,30 +48,37 @@ function detectPackageManager(cwd) {
|
|
|
48
48
|
* @see https://vercel.com/docs/build-output-api/v3
|
|
49
49
|
*/
|
|
50
50
|
exports.vercelAdapter = {
|
|
51
|
-
|
|
51
|
+
// #368 round-3 — was 'esnext'. The ESM entry forced rspack to treat the
|
|
52
|
+
// bundle as strict ESM, which requires fully-specified `./foo.js` imports
|
|
53
|
+
// in TS-emitted code. The `byDependency.fullySpecified: false` workaround
|
|
54
|
+
// didn't reliably suppress this. Switching to CJS mirrors the cloudflare
|
|
55
|
+
// adapter (which has been stable) and eliminates the entire class of
|
|
56
|
+
// extensionless-import errors. The bundled CJS handler still works on
|
|
57
|
+
// Vercel's Node runtime since rspack outputs CommonJS.
|
|
58
|
+
moduleFormat: 'commonjs',
|
|
52
59
|
shouldBundle: true,
|
|
53
60
|
bundleOutput: 'handler.cjs',
|
|
54
|
-
getSetupTemplate: () => `// Serverless environment setup - MUST be
|
|
61
|
+
getSetupTemplate: () => `// Serverless environment setup - MUST be required first
|
|
55
62
|
// This sets FRONTMCP_SERVERLESS before any decorators run
|
|
56
|
-
// Required because ESM hoists imports before other statements
|
|
57
63
|
process.env.FRONTMCP_SERVERLESS = '1';
|
|
58
64
|
process.env.FRONTMCP_DEPLOYMENT_MODE = 'serverless';
|
|
59
65
|
`,
|
|
60
66
|
getEntryTemplate: (mainModulePath) => `// Auto-generated Vercel entry point
|
|
61
67
|
// Generated by: frontmcp build --target vercel
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
require('./serverless-setup.js');
|
|
69
|
+
require('${mainModulePath}');
|
|
70
|
+
const { getServerlessHandlerAsync } = require('@frontmcp/sdk');
|
|
65
71
|
|
|
66
72
|
let handlerPromise = null;
|
|
67
73
|
|
|
68
|
-
|
|
74
|
+
module.exports = async function handler(req, res) {
|
|
69
75
|
if (!handlerPromise) {
|
|
70
76
|
handlerPromise = getServerlessHandlerAsync();
|
|
71
77
|
}
|
|
72
78
|
const app = await handlerPromise;
|
|
73
79
|
return app(req, res);
|
|
74
|
-
}
|
|
80
|
+
};
|
|
81
|
+
module.exports.default = module.exports;
|
|
75
82
|
`,
|
|
76
83
|
// Detect package manager and generate appropriate vercel.json
|
|
77
84
|
getConfig: (cwd) => {
|
|
@@ -120,8 +127,15 @@ export default async function handler(req, res) {
|
|
|
120
127
|
}
|
|
121
128
|
// Install runtime dependencies that can't be statically bundled (dynamic requires)
|
|
122
129
|
// These are packages loaded via require() inside functions that rspack can't analyze
|
|
123
|
-
// We install them fresh to ensure correct platform binaries (linux-x64 for Vercel)
|
|
124
|
-
|
|
130
|
+
// We install them fresh to ensure correct platform binaries (linux-x64 for Vercel).
|
|
131
|
+
//
|
|
132
|
+
// #368 round-3 — `openai` and `@anthropic-ai/sdk` are peer deps consumed
|
|
133
|
+
// by `@Agent({ adapter: 'openai' | 'anthropic' })` via lazy
|
|
134
|
+
// `await import()` inside the SDK. They're externalized at bundle time
|
|
135
|
+
// so rspack doesn't fail when they're not installed; only ship them on
|
|
136
|
+
// Vercel when the user actually has them in their package.json (i.e.,
|
|
137
|
+
// they wired up an agent). If absent, the lazy require never fires.
|
|
138
|
+
const runtimeDeps = ['@vercel/kv', 'esbuild', '@swc/core', 'openai', '@anthropic-ai/sdk'];
|
|
125
139
|
// Read package.json to get the exact versions
|
|
126
140
|
const pkgJsonPath = path.join(cwd, 'package.json');
|
|
127
141
|
const pkgJson = JSON.parse(await (0, utils_1.readFile)(pkgJsonPath, 'utf-8'));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vercel.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/vercel.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { existsSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { mkdir, readdir, stat, cp, copyFile, readFile, writeFile } from '@frontmcp/utils';\nimport type { AdapterTemplate } from '../types';\n\ntype PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';\n\ninterface PackageManagerConfig {\n install: string;\n run: string;\n}\n\nconst PACKAGE_MANAGERS: Record<PackageManager, PackageManagerConfig> = {\n bun: { install: 'bun install', run: 'bun run build' },\n pnpm: { install: 'pnpm install', run: 'pnpm run build' },\n yarn: { install: 'yarn install', run: 'yarn build' },\n npm: { install: 'npm install', run: 'npm run build' },\n};\n\nconst LOCKFILE_TO_PM: Record<string, PackageManager> = {\n 'bun.lockb': 'bun',\n 'pnpm-lock.yaml': 'pnpm',\n 'yarn.lock': 'yarn',\n 'package-lock.json': 'npm',\n};\n\n/**\n * Detect package manager based on lockfile presence.\n * Priority: bun > pnpm > yarn > npm (fastest to slowest install times)\n */\nfunction detectPackageManager(cwd: string): PackageManager {\n for (const [lockfile, pm] of Object.entries(LOCKFILE_TO_PM)) {\n if (existsSync(path.join(cwd, lockfile))) {\n return pm;\n }\n }\n return 'npm'; // Default fallback\n}\n\n/**\n * Vercel adapter - serverless deployment on Vercel.\n * Compiles to ESM, bundles with rspack to CJS for maximum compatibility.\n *\n * Uses Vercel Build Output API for deployment:\n * - Creates .vercel/output/config.json with routing\n * - Creates .vercel/output/functions/index.func/ with handler\n *\n * The build process:\n * 1. TypeScript compiles to ESM in dist/\n * 2. serverless-setup.js is generated (sets FRONTMCP_SERVERLESS=1)\n * 3. index.js imports setup first, then main module\n * 4. rspack bundles everything into handler.cjs\n * 5. Build Output API structure is created in .vercel/output/\n *\n * @see https://vercel.com/docs/build-output-api/v3\n */\nexport const vercelAdapter: AdapterTemplate = {\n moduleFormat: 'esnext',\n shouldBundle: true,\n bundleOutput: 'handler.cjs',\n\n getSetupTemplate: () => `// Serverless environment setup - MUST be imported first\n// This sets FRONTMCP_SERVERLESS before any decorators run\n// Required because ESM hoists imports before other statements\nprocess.env.FRONTMCP_SERVERLESS = '1';\nprocess.env.FRONTMCP_DEPLOYMENT_MODE = 'serverless';\n`,\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated Vercel entry point\n// Generated by: frontmcp build --target vercel\nimport './serverless-setup.js';\nimport '${mainModulePath}';\nimport { getServerlessHandlerAsync } from '@frontmcp/sdk';\n\nlet handlerPromise = null;\n\nexport default async function handler(req, res) {\n if (!handlerPromise) {\n handlerPromise = getServerlessHandlerAsync();\n }\n const app = await handlerPromise;\n return app(req, res);\n}\n`,\n\n // Detect package manager and generate appropriate vercel.json\n getConfig: (cwd: string) => {\n const pm = detectPackageManager(cwd);\n const config = PACKAGE_MANAGERS[pm];\n return {\n version: 2,\n buildCommand: config.run,\n installCommand: config.install,\n };\n },\n\n configFileName: 'vercel.json',\n\n /**\n * Create Vercel Build Output API structure after bundling.\n * This allows Vercel to deploy the function without needing an /api folder.\n *\n * Structure created:\n * .vercel/output/\n * ├── config.json (routes all requests to index function)\n * └── functions/\n * └── index.func/\n * ├── .vc-config.json (Node.js 22 runtime config)\n * ├── handler.cjs (bundled handler + chunks)\n * └── node_modules/ (runtime dependencies that can't be bundled)\n */\n postBundle: async (outDir: string, cwd: string, bundleOutput: string) => {\n const outputDir = path.join(cwd, '.vercel', 'output');\n const funcDir = path.join(outputDir, 'functions', 'index.func');\n\n // Create directories\n await mkdir(funcDir, { recursive: true });\n\n // Copy all files from dist to the function directory\n // This includes handler.cjs and any chunk files (*.handler.cjs)\n const distFiles = await readdir(outDir);\n for (const file of distFiles) {\n const srcPath = path.join(outDir, file);\n const destPath = path.join(funcDir, file);\n const fileStat = await stat(srcPath);\n\n if (fileStat.isDirectory()) {\n // Recursively copy directories\n await cp(srcPath, destPath, { recursive: true });\n } else {\n // Copy files\n await copyFile(srcPath, destPath);\n }\n }\n\n // Install runtime dependencies that can't be statically bundled (dynamic requires)\n // These are packages loaded via require() inside functions that rspack can't analyze\n // We install them fresh to ensure correct platform binaries (linux-x64 for Vercel)\n const runtimeDeps = ['@vercel/kv', 'esbuild', '@swc/core'];\n\n // Read package.json to get the exact versions\n const pkgJsonPath = path.join(cwd, 'package.json');\n const pkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n const allDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies };\n\n // Build list of deps with versions\n const depsToInstall: string[] = [];\n for (const dep of runtimeDeps) {\n const version = allDeps[dep];\n if (version) {\n depsToInstall.push(`${dep}@${version}`);\n }\n }\n\n if (depsToInstall.length > 0) {\n // Create package.json in function directory\n const funcPkgJson = { name: 'index.func', private: true, dependencies: {} };\n await writeFile(path.join(funcDir, 'package.json'), JSON.stringify(funcPkgJson, null, 2));\n\n // Install dependencies using npm (works on all platforms)\n try {\n execSync(`npm install ${depsToInstall.join(' ')} --omit=dev`, {\n cwd: funcDir,\n stdio: 'pipe',\n });\n } catch {\n // Silently continue if install fails - the dep might not be needed\n }\n }\n\n // Create function config (.vc-config.json)\n const vcConfig = {\n runtime: 'nodejs24.x',\n handler: bundleOutput,\n launcherType: 'Nodejs',\n };\n await writeFile(\n path.join(funcDir, '.vc-config.json'),\n JSON.stringify(vcConfig, null, 2),\n );\n\n // Create output config (config.json) with routing\n const outputConfig = {\n version: 3,\n routes: [{ src: '/(.*)', dest: '/index' }],\n };\n await writeFile(\n path.join(outputDir, 'config.json'),\n JSON.stringify(outputConfig, null, 2),\n );\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"vercel.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/vercel.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { existsSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { mkdir, readdir, stat, cp, copyFile, readFile, writeFile } from '@frontmcp/utils';\nimport type { AdapterTemplate } from '../types';\n\ntype PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';\n\ninterface PackageManagerConfig {\n install: string;\n run: string;\n}\n\nconst PACKAGE_MANAGERS: Record<PackageManager, PackageManagerConfig> = {\n bun: { install: 'bun install', run: 'bun run build' },\n pnpm: { install: 'pnpm install', run: 'pnpm run build' },\n yarn: { install: 'yarn install', run: 'yarn build' },\n npm: { install: 'npm install', run: 'npm run build' },\n};\n\nconst LOCKFILE_TO_PM: Record<string, PackageManager> = {\n 'bun.lockb': 'bun',\n 'pnpm-lock.yaml': 'pnpm',\n 'yarn.lock': 'yarn',\n 'package-lock.json': 'npm',\n};\n\n/**\n * Detect package manager based on lockfile presence.\n * Priority: bun > pnpm > yarn > npm (fastest to slowest install times)\n */\nfunction detectPackageManager(cwd: string): PackageManager {\n for (const [lockfile, pm] of Object.entries(LOCKFILE_TO_PM)) {\n if (existsSync(path.join(cwd, lockfile))) {\n return pm;\n }\n }\n return 'npm'; // Default fallback\n}\n\n/**\n * Vercel adapter - serverless deployment on Vercel.\n * Compiles to ESM, bundles with rspack to CJS for maximum compatibility.\n *\n * Uses Vercel Build Output API for deployment:\n * - Creates .vercel/output/config.json with routing\n * - Creates .vercel/output/functions/index.func/ with handler\n *\n * The build process:\n * 1. TypeScript compiles to ESM in dist/\n * 2. serverless-setup.js is generated (sets FRONTMCP_SERVERLESS=1)\n * 3. index.js imports setup first, then main module\n * 4. rspack bundles everything into handler.cjs\n * 5. Build Output API structure is created in .vercel/output/\n *\n * @see https://vercel.com/docs/build-output-api/v3\n */\nexport const vercelAdapter: AdapterTemplate = {\n // #368 round-3 — was 'esnext'. The ESM entry forced rspack to treat the\n // bundle as strict ESM, which requires fully-specified `./foo.js` imports\n // in TS-emitted code. The `byDependency.fullySpecified: false` workaround\n // didn't reliably suppress this. Switching to CJS mirrors the cloudflare\n // adapter (which has been stable) and eliminates the entire class of\n // extensionless-import errors. The bundled CJS handler still works on\n // Vercel's Node runtime since rspack outputs CommonJS.\n moduleFormat: 'commonjs',\n shouldBundle: true,\n bundleOutput: 'handler.cjs',\n\n getSetupTemplate: () => `// Serverless environment setup - MUST be required first\n// This sets FRONTMCP_SERVERLESS before any decorators run\nprocess.env.FRONTMCP_SERVERLESS = '1';\nprocess.env.FRONTMCP_DEPLOYMENT_MODE = 'serverless';\n`,\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated Vercel entry point\n// Generated by: frontmcp build --target vercel\nrequire('./serverless-setup.js');\nrequire('${mainModulePath}');\nconst { getServerlessHandlerAsync } = require('@frontmcp/sdk');\n\nlet handlerPromise = null;\n\nmodule.exports = async function handler(req, res) {\n if (!handlerPromise) {\n handlerPromise = getServerlessHandlerAsync();\n }\n const app = await handlerPromise;\n return app(req, res);\n};\nmodule.exports.default = module.exports;\n`,\n\n // Detect package manager and generate appropriate vercel.json\n getConfig: (cwd: string) => {\n const pm = detectPackageManager(cwd);\n const config = PACKAGE_MANAGERS[pm];\n return {\n version: 2,\n buildCommand: config.run,\n installCommand: config.install,\n };\n },\n\n configFileName: 'vercel.json',\n\n /**\n * Create Vercel Build Output API structure after bundling.\n * This allows Vercel to deploy the function without needing an /api folder.\n *\n * Structure created:\n * .vercel/output/\n * ├── config.json (routes all requests to index function)\n * └── functions/\n * └── index.func/\n * ├── .vc-config.json (Node.js 22 runtime config)\n * ├── handler.cjs (bundled handler + chunks)\n * └── node_modules/ (runtime dependencies that can't be bundled)\n */\n postBundle: async (outDir: string, cwd: string, bundleOutput: string) => {\n const outputDir = path.join(cwd, '.vercel', 'output');\n const funcDir = path.join(outputDir, 'functions', 'index.func');\n\n // Create directories\n await mkdir(funcDir, { recursive: true });\n\n // Copy all files from dist to the function directory\n // This includes handler.cjs and any chunk files (*.handler.cjs)\n const distFiles = await readdir(outDir);\n for (const file of distFiles) {\n const srcPath = path.join(outDir, file);\n const destPath = path.join(funcDir, file);\n const fileStat = await stat(srcPath);\n\n if (fileStat.isDirectory()) {\n // Recursively copy directories\n await cp(srcPath, destPath, { recursive: true });\n } else {\n // Copy files\n await copyFile(srcPath, destPath);\n }\n }\n\n // Install runtime dependencies that can't be statically bundled (dynamic requires)\n // These are packages loaded via require() inside functions that rspack can't analyze\n // We install them fresh to ensure correct platform binaries (linux-x64 for Vercel).\n //\n // #368 round-3 — `openai` and `@anthropic-ai/sdk` are peer deps consumed\n // by `@Agent({ adapter: 'openai' | 'anthropic' })` via lazy\n // `await import()` inside the SDK. They're externalized at bundle time\n // so rspack doesn't fail when they're not installed; only ship them on\n // Vercel when the user actually has them in their package.json (i.e.,\n // they wired up an agent). If absent, the lazy require never fires.\n const runtimeDeps = ['@vercel/kv', 'esbuild', '@swc/core', 'openai', '@anthropic-ai/sdk'];\n\n // Read package.json to get the exact versions\n const pkgJsonPath = path.join(cwd, 'package.json');\n const pkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));\n const allDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies };\n\n // Build list of deps with versions\n const depsToInstall: string[] = [];\n for (const dep of runtimeDeps) {\n const version = allDeps[dep];\n if (version) {\n depsToInstall.push(`${dep}@${version}`);\n }\n }\n\n if (depsToInstall.length > 0) {\n // Create package.json in function directory\n const funcPkgJson = { name: 'index.func', private: true, dependencies: {} };\n await writeFile(path.join(funcDir, 'package.json'), JSON.stringify(funcPkgJson, null, 2));\n\n // Install dependencies using npm (works on all platforms)\n try {\n execSync(`npm install ${depsToInstall.join(' ')} --omit=dev`, {\n cwd: funcDir,\n stdio: 'pipe',\n });\n } catch {\n // Silently continue if install fails - the dep might not be needed\n }\n }\n\n // Create function config (.vc-config.json)\n const vcConfig = {\n runtime: 'nodejs24.x',\n handler: bundleOutput,\n launcherType: 'Nodejs',\n };\n await writeFile(\n path.join(funcDir, '.vc-config.json'),\n JSON.stringify(vcConfig, null, 2),\n );\n\n // Create output config (config.json) with routing\n const outputConfig = {\n version: 3,\n routes: [{ src: '/(.*)', dest: '/index' }],\n };\n await writeFile(\n path.join(outputDir, 'config.json'),\n JSON.stringify(outputConfig, null, 2),\n );\n },\n};\n"]}
|
|
@@ -41,6 +41,16 @@ async function bundleForServerless(entryPath, outDir, outputFilename) {
|
|
|
41
41
|
// validate hook surfaces a clear "npm install @codegenie/serverless-express"
|
|
42
42
|
// error when it's actually missing from node_modules at build time.
|
|
43
43
|
'@codegenie/serverless-express': '@codegenie/serverless-express',
|
|
44
|
+
// #368 round-3 — `@frontmcp/sdk/esm` contains lazy `await import('openai')`
|
|
45
|
+
// and `await import('@anthropic-ai/sdk')` calls inside agent adapters.
|
|
46
|
+
// These are intentionally optional peers (only resolved when the user
|
|
47
|
+
// actually instantiates an OpenAI/Anthropic agent), but rspack treats
|
|
48
|
+
// them as hard imports during static analysis and the vercel/lambda
|
|
49
|
+
// build fails because neither is installed. Externalizing tells rspack
|
|
50
|
+
// to leave the `require()` in place — the dynamic-import branch only
|
|
51
|
+
// executes if the user wires up the corresponding agent.
|
|
52
|
+
openai: 'openai',
|
|
53
|
+
'@anthropic-ai/sdk': '@anthropic-ai/sdk',
|
|
44
54
|
},
|
|
45
55
|
resolve: {
|
|
46
56
|
extensions: ['.js', '.mjs', '.cjs', '.json'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundler.js","sourceRoot":"","sources":["../../../../src/commands/build/bundler.ts"],"names":[],"mappings":";;AAWA,
|
|
1
|
+
{"version":3,"file":"bundler.js","sourceRoot":"","sources":["../../../../src/commands/build/bundler.ts"],"names":[],"mappings":"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","sourcesContent":["import { rspack } from '@rspack/core';\nimport { c } from '../../core/colors';\n\n/**\n * Bundle the serverless entry point into a single CJS file using rspack.\n * This resolves ESM/CJS compatibility issues and dynamic import problems.\n *\n * @param entryPath - Absolute path to the entry file (e.g., dist/index.js)\n * @param outDir - Output directory for the bundled file\n * @param outputFilename - Name of the output bundle (e.g., 'handler.cjs')\n */\nexport async function bundleForServerless(\n entryPath: string,\n outDir: string,\n outputFilename: string,\n): Promise<void> {\n const compiler = rspack({\n mode: 'production',\n target: 'node',\n entry: entryPath,\n output: {\n path: outDir,\n filename: outputFilename,\n library: { type: 'commonjs2' },\n clean: false,\n },\n // Use node externals preset for built-in modules\n externalsPresets: { node: true },\n // Exclude problematic optional dependencies (native binaries that can't be bundled)\n externals: {\n '@swc/core': '@swc/core',\n fsevents: 'fsevents',\n esbuild: 'esbuild',\n // React is optional - only needed for MDX/JSX rendering\n react: 'react',\n 'react-dom': 'react-dom',\n 'react-dom/server': 'react-dom/server',\n 'react/jsx-runtime': 'react/jsx-runtime',\n // #368 round-2 — Lambda's entry imports `@codegenie/serverless-express`\n // which is intentionally a peer dep (the user installs the version\n // they want). Mark it external so rspack doesn't fail with\n // \"Module not found\" trying to bundle it. The lambda adapter's own\n // validate hook surfaces a clear \"npm install @codegenie/serverless-express\"\n // error when it's actually missing from node_modules at build time.\n '@codegenie/serverless-express': '@codegenie/serverless-express',\n // #368 round-3 — `@frontmcp/sdk/esm` contains lazy `await import('openai')`\n // and `await import('@anthropic-ai/sdk')` calls inside agent adapters.\n // These are intentionally optional peers (only resolved when the user\n // actually instantiates an OpenAI/Anthropic agent), but rspack treats\n // them as hard imports during static analysis and the vercel/lambda\n // build fails because neither is installed. Externalizing tells rspack\n // to leave the `require()` in place — the dynamic-import branch only\n // executes if the user wires up the corresponding agent.\n openai: 'openai',\n '@anthropic-ai/sdk': '@anthropic-ai/sdk',\n },\n resolve: {\n extensions: ['.js', '.mjs', '.cjs', '.json'],\n // Allow imports without file extensions (TypeScript compiles without .js\n // but strict ESM requires them).\n //\n // #368 round-2 — top-level `fullySpecified: false` alone wasn't enough.\n // When the entry's sibling `package.json` declares `{\"type\":\"module\"}`\n // (vercel/lambda adapters do this so Node treats `index.js` as ESM),\n // rspack classifies the relative import edges as `esm` dependencies\n // and applies its strict-ESM resolver, which ignores the top-level\n // setting. `byDependency` overrides per dependency type so\n // `import { CalcApp } from './calc.app'` resolves whether the import\n // is parsed as CJS, ESM, or commonjs-require.\n fullySpecified: false,\n byDependency: {\n esm: { fullySpecified: false },\n commonjs: { fullySpecified: false },\n 'commonjs-require': { fullySpecified: false },\n },\n },\n module: {\n rules: [],\n parser: {\n javascript: {\n // Handle dynamic requires like require('@vercel/kv') inside functions\n // by wrapping them instead of externalizing them\n dynamicImportMode: 'eager',\n exprContextCritical: false,\n unknownContextCritical: false,\n },\n },\n },\n // Don't minimize to preserve readability for debugging\n optimization: {\n minimize: false,\n },\n // Suppress known third-party library warnings that don't affect runtime\n ignoreWarnings: [\n // Express view engine dynamic require - expected behavior, harmless at runtime\n /Critical dependency: the request of a dependency is an expression/,\n // Handlebars require.extensions - deprecated Node.js API but works at runtime\n /require\\.extensions is not supported by Rspack/,\n ],\n // Suppress verbose output\n stats: 'errors-warnings',\n });\n\n return new Promise((resolve, reject) => {\n compiler.run((err, stats) => {\n if (err) {\n return reject(err);\n }\n if (stats?.hasErrors()) {\n const info = stats.toJson();\n const errorMessages = info.errors?.map((e) => e.message).join('\\n') || 'Unknown error';\n return reject(new Error(`Bundle failed:\\n${errorMessages}`));\n }\n if (stats?.hasWarnings()) {\n const info = stats.toJson();\n info.warnings?.forEach((w) => {\n console.log(c('yellow', ` Warning: ${w.message}`));\n });\n }\n compiler.close((closeErr) => {\n if (closeErr) {\n console.log(c('yellow', ` Warning closing compiler: ${closeErr.message}`));\n }\n resolve();\n });\n });\n });\n}\n"]}
|
|
@@ -56,7 +56,7 @@ export interface FrontmcpExecConfig {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* Load frontmcp.config.js
|
|
59
|
+
* Load frontmcp.config.{ts,js,json,mjs,cjs} from the given directory.
|
|
60
60
|
* Falls back to deriving minimal config from package.json.
|
|
61
61
|
*/
|
|
62
62
|
export declare function loadExecConfig(cwd: string): Promise<FrontmcpExecConfig>;
|
|
@@ -9,13 +9,19 @@ const tslib_1 = require("tslib");
|
|
|
9
9
|
const path = tslib_1.__importStar(require("path"));
|
|
10
10
|
const fs = tslib_1.__importStar(require("fs"));
|
|
11
11
|
const CONFIG_FILENAMES = [
|
|
12
|
+
// #365 round-3 — `.ts` is checked first so the user's typed config takes
|
|
13
|
+
// priority over a stale `.js` left in the project. `.ts` loading routes
|
|
14
|
+
// through the same esbuild path as the new-shape loader so it works under
|
|
15
|
+
// `"type": "commonjs"` (Node's `require(.ts)` and `await import(.ts)` are
|
|
16
|
+
// both unreliable here and were the root cause of #365 1.1.0–1.1.2-beta.1).
|
|
17
|
+
'frontmcp.config.ts',
|
|
12
18
|
'frontmcp.config.js',
|
|
13
19
|
'frontmcp.config.json',
|
|
14
20
|
'frontmcp.config.mjs',
|
|
15
21
|
'frontmcp.config.cjs',
|
|
16
22
|
];
|
|
17
23
|
/**
|
|
18
|
-
* Load frontmcp.config.js
|
|
24
|
+
* Load frontmcp.config.{ts,js,json,mjs,cjs} from the given directory.
|
|
19
25
|
* Falls back to deriving minimal config from package.json.
|
|
20
26
|
*/
|
|
21
27
|
async function loadExecConfig(cwd) {
|
|
@@ -26,6 +32,29 @@ async function loadExecConfig(cwd) {
|
|
|
26
32
|
const content = fs.readFileSync(configPath, 'utf-8');
|
|
27
33
|
return JSON.parse(content);
|
|
28
34
|
}
|
|
35
|
+
if (filename.endsWith('.ts')) {
|
|
36
|
+
// Delegate to the new loader's esbuild transpile so `.ts` configs
|
|
37
|
+
// work under `"type": "commonjs"` projects. Hard-fails on parse error
|
|
38
|
+
// (no silent default) — matches frontmcp-config.loader semantics.
|
|
39
|
+
// tsc uses `--moduleResolution nodenext`, so the dynamic import
|
|
40
|
+
// needs an explicit `.js` suffix that resolves to the compiled
|
|
41
|
+
// output. The barrel (`../../../config/index.js`) re-exports
|
|
42
|
+
// `loadFrontMcpConfig` from the loader module.
|
|
43
|
+
const { loadFrontMcpConfig } = await import('../../../config/index.js');
|
|
44
|
+
try {
|
|
45
|
+
// The new-shape loader returns a parsed config — we only consume the
|
|
46
|
+
// legacy-shape fields here. Fields that exist in both shapes
|
|
47
|
+
// (name, version, entry, nodeVersion) carry through; new-shape-only
|
|
48
|
+
// fields like `deployments` are ignored by this consumer.
|
|
49
|
+
const newShape = await loadFrontMcpConfig(cwd);
|
|
50
|
+
return newShape;
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
throw new Error(`Failed to load ${filename}: ${err.message}\n` +
|
|
54
|
+
`If your config doesn't match the new schema (deployments[] etc.), ` +
|
|
55
|
+
`rename it to .js or use the legacy module.exports shape.`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
29
58
|
// JS/MJS/CJS config — require it
|
|
30
59
|
const mod = require(configPath);
|
|
31
60
|
return (mod.default || mod);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/config.ts"],"names":[],"mappings":";AAAA;;GAEG;;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * frontmcp.config.js/json schema and loader.\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport type { SetupDefinition } from './setup';\n\nexport interface OAuthConfig {\n serverUrl?: string;\n clientId?: string;\n defaultScope?: string;\n portRange?: [number, number];\n defaultPort?: number;\n timeout?: number;\n}\n\nexport interface CliConfig {\n enabled: boolean;\n outputDefault?: 'text' | 'json';\n authRequired?: boolean;\n description?: string;\n excludeTools?: string[];\n nativeDeps?: {\n brew?: string[];\n apt?: string[];\n npm?: string[];\n };\n oauth?: OAuthConfig;\n}\n\nexport type ConfigBuildTarget = 'cli' | 'node' | 'sdk' | 'browser' | 'cloudflare' | 'vercel' | 'lambda' | 'distributed';\n\nexport interface FrontmcpExecConfig {\n name: string;\n version?: string;\n entry?: string;\n /** Build target. When set, takes precedence over cli.enabled / sea.enabled. */\n target?: ConfigBuildTarget;\n storage?: {\n type: 'sqlite' | 'redis' | 'none';\n required?: boolean;\n };\n network?: {\n defaultPort?: number;\n supportsSocket?: boolean;\n };\n dependencies?: {\n system?: string[];\n nativeAddons?: string[];\n };\n nodeVersion?: string;\n esbuild?: {\n external?: string[];\n define?: Record<string, string>;\n target?: string;\n minify?: boolean;\n };\n setup?: SetupDefinition;\n cli?: CliConfig;\n sea?: {\n enabled?: boolean;\n };\n}\n\nconst CONFIG_FILENAMES = [\n // #365 round-3 — `.ts` is checked first so the user's typed config takes\n // priority over a stale `.js` left in the project. `.ts` loading routes\n // through the same esbuild path as the new-shape loader so it works under\n // `\"type\": \"commonjs\"` (Node's `require(.ts)` and `await import(.ts)` are\n // both unreliable here and were the root cause of #365 1.1.0–1.1.2-beta.1).\n 'frontmcp.config.ts',\n 'frontmcp.config.js',\n 'frontmcp.config.json',\n 'frontmcp.config.mjs',\n 'frontmcp.config.cjs',\n];\n\n/**\n * Load frontmcp.config.{ts,js,json,mjs,cjs} from the given directory.\n * Falls back to deriving minimal config from package.json.\n */\nexport async function loadExecConfig(cwd: string): Promise<FrontmcpExecConfig> {\n for (const filename of CONFIG_FILENAMES) {\n const configPath = path.join(cwd, filename);\n if (fs.existsSync(configPath)) {\n if (filename.endsWith('.json')) {\n const content = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(content) as FrontmcpExecConfig;\n }\n if (filename.endsWith('.ts')) {\n // Delegate to the new loader's esbuild transpile so `.ts` configs\n // work under `\"type\": \"commonjs\"` projects. Hard-fails on parse error\n // (no silent default) — matches frontmcp-config.loader semantics.\n // tsc uses `--moduleResolution nodenext`, so the dynamic import\n // needs an explicit `.js` suffix that resolves to the compiled\n // output. The barrel (`../../../config/index.js`) re-exports\n // `loadFrontMcpConfig` from the loader module.\n const { loadFrontMcpConfig } = await import('../../../config/index.js');\n try {\n // The new-shape loader returns a parsed config — we only consume the\n // legacy-shape fields here. Fields that exist in both shapes\n // (name, version, entry, nodeVersion) carry through; new-shape-only\n // fields like `deployments` are ignored by this consumer.\n const newShape = await loadFrontMcpConfig(cwd);\n return newShape as unknown as FrontmcpExecConfig;\n } catch (err) {\n throw new Error(\n `Failed to load ${filename}: ${(err as Error).message}\\n` +\n `If your config doesn't match the new schema (deployments[] etc.), ` +\n `rename it to .js or use the legacy module.exports shape.`,\n );\n }\n }\n // JS/MJS/CJS config — require it\n\n const mod = require(configPath);\n return (mod.default || mod) as FrontmcpExecConfig;\n }\n }\n\n // Fallback: derive from package.json\n const pkgPath = path.join(cwd, 'package.json');\n if (!fs.existsSync(pkgPath)) {\n throw new Error(\n 'No frontmcp.config.js/json found and no package.json. Create a frontmcp.config.js for build targets.',\n );\n }\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));\n return {\n name: pkg.name?.replace(/^@[^/]+\\//, '') || path.basename(cwd),\n version: pkg.version || '1.0.0',\n entry: pkg.main,\n };\n}\n\n/**\n * Validate config and return normalized version.\n */\nexport function normalizeConfig(config: FrontmcpExecConfig): Required<\n Pick<FrontmcpExecConfig, 'name' | 'version' | 'nodeVersion'>\n> &\n FrontmcpExecConfig {\n if (!config.name || !/^[a-zA-Z0-9._-]+$/.test(config.name)) {\n throw new Error(\n `Invalid app name: \"${config.name}\". Must be alphanumeric with .-_ only.`,\n );\n }\n\n return {\n ...config,\n name: config.name,\n version: config.version || '1.0.0',\n nodeVersion: config.nodeVersion || '>=22.0.0',\n };\n}\n"]}
|
|
@@ -49,6 +49,12 @@ async function buildExec(opts) {
|
|
|
49
49
|
...opts.execOverrides.cli,
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
+
// #365 round-3 — apply only when the legacy loader didn't already pick up
|
|
53
|
+
// a value (the legacy loader can read it from .js/.json/.cjs/.mjs configs;
|
|
54
|
+
// the new-shape forward fills the .ts gap).
|
|
55
|
+
if (opts.execOverrides.nodeVersion && !rawConfig.nodeVersion) {
|
|
56
|
+
rawConfig.nodeVersion = opts.execOverrides.nodeVersion;
|
|
57
|
+
}
|
|
52
58
|
}
|
|
53
59
|
const config = (0, config_1.normalizeConfig)(rawConfig);
|
|
54
60
|
const cliEnabled = opts.cli || config.cli?.enabled;
|
|
@@ -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(\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"]}
|
|
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(\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 // #365 round-3 — top-level `nodeVersion` from new-shape frontmcp.config\n // gets forwarded here because the legacy `loadExecConfig` doesn't read\n // it from .ts files (and never read top-level nodeVersion at all in\n // the legacy shape).\n nodeVersion?: string;\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 // #365 round-3 — apply only when the legacy loader didn't already pick up\n // a value (the legacy loader can read it from .js/.json/.cjs/.mjs configs;\n // the new-shape forward fills the .ts gap).\n if (opts.execOverrides.nodeVersion && !rawConfig.nodeVersion) {\n rawConfig.nodeVersion = opts.execOverrides.nodeVersion;\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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/build/index.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { type ParsedArgs } from '../../core/args';\nimport { c } from '../../core/colors';\nimport { ensureDir, fileExists, runCmd, writeJSON } from '@frontmcp/utils';\nimport { fsp, resolveEntry } from '../../shared/fs';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../core/tsconfig';\nimport { ADAPTERS } from './adapters';\nimport { type AdapterName } from './types';\nimport { bundleForServerless } from './bundler';\nimport {\n type DeploymentTarget,\n findDeployment,\n type FrontMcpConfigParsed,\n getDeploymentTargets,\n tryLoadFrontMcpConfig,\n} from '../../config';\n\nfunction isTsLike(p: string): boolean {\n return /\\.tsx?$/i.test(p);\n}\n\n/**\n * Generate adapter-specific entry point and config files.\n */\nasync function generateAdapterFiles(\n adapter: AdapterName,\n outDir: string,\n entryBasename: string,\n cwd: string,\n deployment?: DeploymentTarget,\n): Promise<void> {\n const template = ADAPTERS[adapter];\n\n // Generate serverless setup file first (if adapter has one)\n // This file sets FRONTMCP_SERVERLESS=1 before any imports run\n if (template.getSetupTemplate) {\n const setupContent = template.getSetupTemplate();\n const setupPath = path.join(outDir, 'serverless-setup.js');\n await fsp.writeFile(setupPath, setupContent, 'utf8');\n console.log(c('green', ` Generated serverless setup at ${path.relative(cwd, setupPath)}`));\n }\n\n // Generate index.js entry point\n const mainModuleName = entryBasename.replace(/\\.tsx?$/, '.js');\n const entryContent = template.getEntryTemplate(`./${mainModuleName}`);\n\n // Skip if no entry template (e.g., node adapter)\n if (entryContent) {\n const entryPath = path.join(outDir, 'index.js');\n await fsp.writeFile(entryPath, entryContent, 'utf8');\n console.log(c('green', ` Generated ${adapter} entry at ${path.relative(cwd, entryPath)}`));\n\n // ESM adapters (vercel, lambda) emit `import` syntax in the entry. The\n // user's project may be `\"type\": \"commonjs\"`, in which case Node and\n // rspack treat the .js file as CJS and parsing fails on `import`.\n // Drop a sibling package.json with `\"type\": \"module\"` so the dist\n // directory is always interpreted correctly regardless of the parent.\n if (template.moduleFormat === 'esnext') {\n const pkgPath = path.join(outDir, 'package.json');\n await fsp.writeFile(pkgPath, JSON.stringify({ type: 'module' }, null, 2), 'utf8');\n }\n }\n\n // Bundle if adapter requires it (creates single CJS file for serverless)\n if (template.shouldBundle && template.bundleOutput) {\n console.log(c('cyan', `[build] Bundling for ${adapter}...`));\n const entryPath = path.join(outDir, 'index.js');\n await bundleForServerless(entryPath, outDir, template.bundleOutput);\n console.log(c('green', ` Created bundle: ${template.bundleOutput}`));\n\n // Run post-bundle hook if defined (e.g., create Build Output API structure)\n if (template.postBundle) {\n console.log(c('cyan', `[build] Creating ${adapter} deployment structure...`));\n await template.postBundle(outDir, cwd, template.bundleOutput);\n console.log(c('green', ` Created deployment output structure`));\n }\n }\n\n // Generate config file if adapter has one. By default we preserve an\n // existing user-edited file. Adapters that mark `alwaysWriteConfig` (e.g.,\n // cloudflare's wrangler.toml) overwrite it on every build so the\n // generated `main = ...` path always matches the actual build output —\n // see #374.\n if (template.getConfig && template.configFileName) {\n const configPath = path.join(cwd, template.configFileName);\n const exists = await fileExists(configPath);\n\n const configContent = template.getConfig(cwd, deployment);\n const writeIt = async (): Promise<void> => {\n if (typeof configContent === 'string') {\n await fsp.writeFile(configPath, configContent, 'utf8');\n } else {\n await writeJSON(configPath, configContent);\n }\n };\n\n if (!exists) {\n await writeIt();\n console.log(c('green', ` Generated ${template.configFileName}`));\n } else if (template.alwaysWriteConfig) {\n await writeIt();\n console.log(c('green', ` Updated ${template.configFileName} (build output reference)`));\n } else {\n console.log(c('yellow', ` ${template.configFileName} already exists (skipping)`));\n }\n }\n}\n\n/** Map target names to internal adapter names. */\nconst TARGET_TO_ADAPTER: Record<string, AdapterName> = {\n 'vercel': 'vercel',\n 'lambda': 'lambda',\n 'cloudflare': 'cloudflare',\n 'distributed': 'distributed',\n};\n\n/**\n * Build the FrontMCP server for a specific deployment target.\n *\n * @example\n * ```bash\n * frontmcp build --target node # Node.js server bundle\n * frontmcp build --target cli # CLI with SEA binary\n * frontmcp build --target cli --js # CLI without SEA\n * frontmcp build --target sdk # Library (CJS+ESM+types)\n * frontmcp build --target browser # Browser ESM bundle\n * frontmcp build --target vercel # Vercel serverless\n * frontmcp build --target lambda # AWS Lambda\n * frontmcp build --target cloudflare # Cloudflare Workers\n * ```\n */\nexport async function runBuild(opts: ParsedArgs): Promise<void> {\n const cwd = process.cwd();\n\n // Try loading frontmcp.config for multi-target support.\n //\n // #365 — `tryLoadFrontMcpConfig` differentiates between recoverable cases:\n // - no config file present → returns undefined\n // - config exists but doesn't match the new schema → returns undefined\n // (legacy top-level `cli`/`sea`/`esbuild` shape — picked up later by\n // the exec-build's own `loadExecConfig`)\n // …and hard failures:\n // - file exists but can't be parsed (TS syntax error, broken require)\n // → the error propagates, no silent-default regression.\n const config: FrontMcpConfigParsed | undefined = await tryLoadFrontMcpConfig(cwd);\n\n // If no -t flag and config has deployments, build all targets from config\n if (!opts.buildTarget && config && config.deployments.length > 0) {\n const targets = getDeploymentTargets(config);\n console.log(c('cyan', `[build] Building ${targets.length} target(s) from frontmcp.config: ${targets.join(', ')}`));\n\n for (const targetName of targets) {\n console.log(c('cyan', `\\n[build] ═══ ${targetName} ═══`));\n await buildSingleTarget(targetName, opts, config);\n }\n return;\n }\n\n // Single target build (from -t flag or default 'node')\n const target = opts.buildTarget ?? 'node';\n await buildSingleTarget(target, opts, config);\n}\n\n/**\n * Build a single deployment target.\n * Merges per-target config (from frontmcp.config) with CLI opts.\n */\nasync function buildSingleTarget(\n target: string,\n opts: ParsedArgs,\n config?: FrontMcpConfigParsed,\n): Promise<void> {\n const deployment:DeploymentTarget | undefined = config ? findDeployment(config, target) : undefined;\n\n // Resolve output directory: deployment.outDir > CLI --out-dir > dist/{target}\n const baseOutDir = path.resolve(process.cwd(), opts.outDir || 'dist');\n const targetOutDir = deployment?.outDir\n ? path.resolve(process.cwd(), deployment.outDir)\n : path.join(baseOutDir, target);\n\n // Merge entry from config if not provided via CLI\n const entry = opts.entry || config?.entry;\n const targetOpts = { ...opts, outDir: targetOutDir, entry };\n\n // #370: forward `build.storage` and per-deployment `cli.outputDefault` from\n // the FrontMcp config into the exec build so the manifest reflects them.\n // The exec build has its own loader (`loadExecConfig`) that doesn't see\n // the deployment-level shape; passing these via opts merges them in\n // `normalizeConfig` before the manifest is generated.\n //\n // Only the cli deployment shape carries a `cli` block; map it down to the\n // narrow exec-config shape (outputDefault / description / authRequired) so\n // the result is a clean object, never `false`.\n const cliDeploymentConfig = deployment?.target === 'cli' ? deployment.cli : undefined;\n const execOverrides: {\n storage?: { type: 'sqlite' | 'redis' | 'none'; required?: boolean };\n cli?: { outputDefault?: 'text' | 'json'; description?: string; authRequired?: boolean };\n } = {\n storage: config?.build?.storage,\n cli: cliDeploymentConfig\n ? {\n ...(cliDeploymentConfig.outputDefault ? { outputDefault: cliDeploymentConfig.outputDefault } : {}),\n ...(cliDeploymentConfig.description ? { description: cliDeploymentConfig.description } : {}),\n ...(typeof cliDeploymentConfig.authRequired === 'boolean'\n ? { authRequired: cliDeploymentConfig.authRequired }\n : {}),\n }\n : undefined,\n };\n\n switch (target) {\n case 'cli': {\n const { buildExec } = await import('./exec/index.js');\n return buildExec({\n ...targetOpts,\n cli: true,\n sea: !opts.js,\n execOverrides,\n } as ParsedArgs & { cli: boolean; sea: boolean; execOverrides?: typeof execOverrides });\n }\n case 'node': {\n const { buildExec } = await import('./exec/index.js');\n return buildExec({\n ...targetOpts,\n execOverrides,\n } as ParsedArgs & { execOverrides?: typeof execOverrides });\n }\n case 'sdk': {\n const { buildSdk } = await import('./sdk/index.js');\n return buildSdk(targetOpts);\n }\n case 'browser': {\n const { buildBrowser } = await import('./browser/index.js');\n return buildBrowser(targetOpts);\n }\n case 'mcpb': {\n const { buildMcpb } = await import('./mcpb/index.js');\n return buildMcpb(targetOpts, config);\n }\n case 'vercel':\n case 'lambda':\n case 'cloudflare':\n case 'distributed': {\n const adapter = TARGET_TO_ADAPTER[target];\n return runAdapterBuild(targetOpts, adapter, deployment);\n }\n default:\n throw new Error(`Unknown build target: ${target}. Available: cli, node, sdk, browser, cloudflare, vercel, lambda, distributed, mcpb`);\n }\n}\n\n/**\n * Build using a deployment adapter (serverless platforms).\n */\nasync function runAdapterBuild(\n opts: ParsedArgs,\n adapter: AdapterName,\n deployment?: DeploymentTarget,\n): Promise<void> {\n const cwd = process.cwd();\n const entry = await resolveEntry(cwd, opts.entry);\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n await ensureDir(outDir);\n\n const template = ADAPTERS[adapter];\n if (!template) {\n const available = Object.keys(ADAPTERS).join(', ');\n throw new Error(`Unknown adapter: ${adapter}. Available: ${available}`);\n }\n\n if (adapter === 'cloudflare') {\n console.log(\n c('yellow', 'Cloudflare Workers adapter is experimental. See docs for limitations.'),\n );\n }\n\n // #375 — adapter-level pre-validation: read the entry's @FrontMcp() config\n // metadata and let the adapter reject incompatible features\n // (sqlite/redis on Workers, etc.) before emitting an unrunnable bundle.\n // `loadEntryDecoratorInfo` handles both compiled-JS and raw-TS entries\n // (TS goes through esbuild + Module._compile so we don't need a tsc pass)\n // AND scans the source AST for keys hidden behind env-gated ternaries —\n // round-2 made the env-gated case the headline #375 reproducer.\n if (template.validate) {\n const { loadEntryDecoratorInfo } = await import('./load-entry-config.js');\n const info = await loadEntryDecoratorInfo(entry);\n template.validate(info.decoratorConfig, { keysSeenInSource: info.keysSeenInSource });\n }\n\n const moduleFormat = template.moduleFormat;\n\n console.log(`${c('cyan', '[build]')} entry: ${path.relative(cwd, entry)}`);\n console.log(`${c('cyan', '[build]')} outDir: ${path.relative(cwd, outDir)}`);\n console.log(`${c('cyan', '[build]')} target: ${adapter} (${moduleFormat})`);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const args: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n console.log(c('gray', `[build] tsconfig.json detected — compiling with project settings`));\n args.push('--project', tsconfigPath);\n } else {\n args.push(entry);\n args.push('--rootDir', path.dirname(entry));\n if (!isTsLike(entry)) {\n args.push('--allowJs');\n console.log(c('yellow', '[build] Entry is not TypeScript; enabling --allowJs'));\n }\n args.push('--experimentalDecorators', '--emitDecoratorMetadata');\n args.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n args.push('--module', moduleFormat);\n args.push('--outDir', outDir);\n args.push('--skipLibCheck');\n\n await runCmd('npx', args);\n\n if (adapter !== 'node') {\n console.log(c('cyan', `[build] Generating ${adapter} deployment files...`));\n const entryBasename = path.basename(entry);\n await generateAdapterFiles(adapter, outDir, entryBasename, cwd, deployment);\n }\n\n console.log(c('green', 'Build completed.'));\n console.log(c('gray', `Output placed in ${path.relative(cwd, outDir)}`));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/build/index.ts"],"names":[],"mappings":";;AAmIA,4BA8BC;;AAjKD,mDAA6B;AAE7B,8CAAsC;AACtC,2CAA2E;AAC3E,wCAAoD;AACpD,kDAAgE;AAChE,yCAAsC;AAEtC,uCAAgD;AAChD,yCAMsB;AAEtB,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,oBAAoB,CACjC,OAAoB,EACpB,MAAc,EACd,aAAqB,EACrB,GAAW,EACX,UAA6B;IAE7B,MAAM,QAAQ,GAAG,mBAAQ,CAAC,OAAO,CAAC,CAAC;IAEnC,4DAA4D;IAC5D,8DAA8D;IAC9D,IAAI,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAC9B,MAAM,YAAY,GAAG,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;QAC3D,MAAM,QAAG,CAAC,SAAS,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,OAAO,EAAE,mCAAmC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;IAED,gCAAgC;IAChC,MAAM,cAAc,GAAG,aAAa,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC/D,MAAM,YAAY,GAAG,QAAQ,CAAC,gBAAgB,CAAC,KAAK,cAAc,EAAE,CAAC,CAAC;IAEtE,iDAAiD;IACjD,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAChD,MAAM,QAAG,CAAC,SAAS,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,OAAO,EAAE,eAAe,OAAO,aAAa,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QAE5F,uEAAuE;QACvE,qEAAqE;QACrE,kEAAkE;QAClE,kEAAkE;QAClE,sEAAsE;QACtE,IAAI,QAAQ,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;YAClD,MAAM,QAAG,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,IAAI,QAAQ,CAAC,YAAY,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,wBAAwB,OAAO,KAAK,CAAC,CAAC,CAAC;QAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAChD,MAAM,IAAA,6BAAmB,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,OAAO,EAAE,qBAAqB,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAEtE,4EAA4E;QAC5E,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,oBAAoB,OAAO,0BAA0B,CAAC,CAAC,CAAC;YAC9E,MAAM,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;YAC9D,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,OAAO,EAAE,uCAAuC,CAAC,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,2EAA2E;IAC3E,iEAAiE;IACjE,uEAAuE;IACvE,YAAY;IACZ,IAAI,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAClD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAU,EAAC,UAAU,CAAC,CAAC;QAE5C,MAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;YACxC,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;gBACtC,MAAM,QAAG,CAAC,SAAS,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;YACzD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAA,iBAAS,EAAC,UAAU,EAAE,aAAa,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,OAAO,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,OAAO,EAAE,eAAe,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC;aAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,CAAC;YACtC,MAAM,OAAO,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,OAAO,EAAE,aAAa,QAAQ,CAAC,cAAc,2BAA2B,CAAC,CAAC,CAAC;QAC3F,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,QAAQ,EAAE,KAAK,QAAQ,CAAC,cAAc,4BAA4B,CAAC,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;AACH,CAAC;AAED,kDAAkD;AAClD,MAAM,iBAAiB,GAAgC;IACrD,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,QAAQ;IAClB,YAAY,EAAE,YAAY;IAC1B,aAAa,EAAE,aAAa;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACI,KAAK,UAAU,QAAQ,CAAC,IAAgB;IAC7C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAE1B,wDAAwD;IACxD,EAAE;IACF,2EAA2E;IAC3E,0EAA0E;IAC1E,0EAA0E;IAC1E,yEAAyE;IACzE,6CAA6C;IAC7C,sBAAsB;IACtB,wEAAwE;IACxE,4DAA4D;IAC5D,MAAM,MAAM,GAAqC,MAAM,IAAA,8BAAqB,EAAC,GAAG,CAAC,CAAC;IAElF,0EAA0E;IAC1E,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjE,MAAM,OAAO,GAAG,IAAA,6BAAoB,EAAC,MAAM,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,oBAAoB,OAAO,CAAC,MAAM,oCAAoC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAEnH,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,iBAAiB,UAAU,MAAM,CAAC,CAAC,CAAC;YAC1D,MAAM,iBAAiB,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACpD,CAAC;QACD,OAAO;IACT,CAAC;IAED,uDAAuD;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC;IAC1C,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,iBAAiB,CAC9B,MAAc,EACd,IAAgB,EAChB,MAA6B;IAE7B,MAAM,UAAU,GAAgC,MAAM,CAAC,CAAC,CAAC,IAAA,uBAAc,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEpG,8EAA8E;IAC9E,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;IACtE,MAAM,YAAY,GAAG,UAAU,EAAE,MAAM;QACrC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC;QAChD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAElC,kDAAkD;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,EAAE,KAAK,CAAC;IAC1C,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAE5D,4EAA4E;IAC5E,yEAAyE;IACzE,wEAAwE;IACxE,oEAAoE;IACpE,sDAAsD;IACtD,EAAE;IACF,0EAA0E;IAC1E,2EAA2E;IAC3E,+CAA+C;IAC/C,MAAM,mBAAmB,GAAG,UAAU,EAAE,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IACtF,MAAM,aAAa,GASf;QACF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;QAC/B,GAAG,EAAE,mBAAmB;YACtB,CAAC,CAAC;gBACE,GAAG,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,mBAAmB,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClG,GAAG,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,mBAAmB,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5F,GAAG,CAAC,OAAO,mBAAmB,CAAC,YAAY,KAAK,SAAS;oBACvD,CAAC,CAAC,EAAE,YAAY,EAAE,mBAAmB,CAAC,YAAY,EAAE;oBACpD,CAAC,CAAC,EAAE,CAAC;aACR;YACH,CAAC,CAAC,SAAS;QACb,WAAW,EAAE,MAAM,EAAE,WAAW;KACjC,CAAC;IAEF,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;YACtD,OAAO,SAAS,CAAC;gBACf,GAAG,UAAU;gBACb,GAAG,EAAE,IAAI;gBACT,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE;gBACb,aAAa;aACuE,CAAC,CAAC;QAC1F,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;YACtD,OAAO,SAAS,CAAC;gBACf,GAAG,UAAU;gBACb,aAAa;aAC2C,CAAC,CAAC;QAC9D,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;YACpD,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC5D,OAAO,YAAY,CAAC,UAAU,CAAC,CAAC;QAClC,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;YACtD,OAAO,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC;QACD,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ,CAAC;QACd,KAAK,YAAY,CAAC;QAClB,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC1C,OAAO,eAAe,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAC1D,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,qFAAqF,CAAC,CAAC;IAC1I,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,eAAe,CAC5B,IAAgB,EAChB,OAAoB,EACpB,UAA6B;IAE7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,MAAM,IAAA,iBAAY,EAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;IACxD,MAAM,IAAA,iBAAS,EAAC,MAAM,CAAC,CAAC;IAExB,MAAM,QAAQ,GAAG,mBAAQ,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,gBAAgB,SAAS,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CACT,IAAA,UAAC,EAAC,QAAQ,EAAE,uEAAuE,CAAC,CACrF,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,4DAA4D;IAC5D,wEAAwE;IACxE,uEAAuE;IACvE,0EAA0E;IAC1E,wEAAwE;IACxE,gEAAgE;IAChE,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACtB,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;QACjD,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC;IAE3C,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,SAAS,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,SAAS,CAAC,YAAY,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAC7E,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,SAAS,CAAC,YAAY,OAAO,KAAK,YAAY,GAAG,CAAC,CAAC;IAE5E,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,IAAI,GAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAErC,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,kEAAkE,CAAC,CAAC,CAAC;QAC3F,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,QAAQ,EAAE,qDAAqD,CAAC,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,yBAAyB,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oCAAyB,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACpC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAE5B,MAAM,IAAA,cAAM,EAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAE1B,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,sBAAsB,OAAO,sBAAsB,CAAC,CAAC,CAAC;QAC5E,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,oBAAoB,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["import * as path from 'path';\nimport { type ParsedArgs } from '../../core/args';\nimport { c } from '../../core/colors';\nimport { ensureDir, fileExists, runCmd, writeJSON } from '@frontmcp/utils';\nimport { fsp, resolveEntry } from '../../shared/fs';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../core/tsconfig';\nimport { ADAPTERS } from './adapters';\nimport { type AdapterName } from './types';\nimport { bundleForServerless } from './bundler';\nimport {\n type DeploymentTarget,\n findDeployment,\n type FrontMcpConfigParsed,\n getDeploymentTargets,\n tryLoadFrontMcpConfig,\n} from '../../config';\n\nfunction isTsLike(p: string): boolean {\n return /\\.tsx?$/i.test(p);\n}\n\n/**\n * Generate adapter-specific entry point and config files.\n */\nasync function generateAdapterFiles(\n adapter: AdapterName,\n outDir: string,\n entryBasename: string,\n cwd: string,\n deployment?: DeploymentTarget,\n): Promise<void> {\n const template = ADAPTERS[adapter];\n\n // Generate serverless setup file first (if adapter has one)\n // This file sets FRONTMCP_SERVERLESS=1 before any imports run\n if (template.getSetupTemplate) {\n const setupContent = template.getSetupTemplate();\n const setupPath = path.join(outDir, 'serverless-setup.js');\n await fsp.writeFile(setupPath, setupContent, 'utf8');\n console.log(c('green', ` Generated serverless setup at ${path.relative(cwd, setupPath)}`));\n }\n\n // Generate index.js entry point\n const mainModuleName = entryBasename.replace(/\\.tsx?$/, '.js');\n const entryContent = template.getEntryTemplate(`./${mainModuleName}`);\n\n // Skip if no entry template (e.g., node adapter)\n if (entryContent) {\n const entryPath = path.join(outDir, 'index.js');\n await fsp.writeFile(entryPath, entryContent, 'utf8');\n console.log(c('green', ` Generated ${adapter} entry at ${path.relative(cwd, entryPath)}`));\n\n // ESM adapters (vercel, lambda) emit `import` syntax in the entry. The\n // user's project may be `\"type\": \"commonjs\"`, in which case Node and\n // rspack treat the .js file as CJS and parsing fails on `import`.\n // Drop a sibling package.json with `\"type\": \"module\"` so the dist\n // directory is always interpreted correctly regardless of the parent.\n if (template.moduleFormat === 'esnext') {\n const pkgPath = path.join(outDir, 'package.json');\n await fsp.writeFile(pkgPath, JSON.stringify({ type: 'module' }, null, 2), 'utf8');\n }\n }\n\n // Bundle if adapter requires it (creates single CJS file for serverless)\n if (template.shouldBundle && template.bundleOutput) {\n console.log(c('cyan', `[build] Bundling for ${adapter}...`));\n const entryPath = path.join(outDir, 'index.js');\n await bundleForServerless(entryPath, outDir, template.bundleOutput);\n console.log(c('green', ` Created bundle: ${template.bundleOutput}`));\n\n // Run post-bundle hook if defined (e.g., create Build Output API structure)\n if (template.postBundle) {\n console.log(c('cyan', `[build] Creating ${adapter} deployment structure...`));\n await template.postBundle(outDir, cwd, template.bundleOutput);\n console.log(c('green', ` Created deployment output structure`));\n }\n }\n\n // Generate config file if adapter has one. By default we preserve an\n // existing user-edited file. Adapters that mark `alwaysWriteConfig` (e.g.,\n // cloudflare's wrangler.toml) overwrite it on every build so the\n // generated `main = ...` path always matches the actual build output —\n // see #374.\n if (template.getConfig && template.configFileName) {\n const configPath = path.join(cwd, template.configFileName);\n const exists = await fileExists(configPath);\n\n const configContent = template.getConfig(cwd, deployment);\n const writeIt = async (): Promise<void> => {\n if (typeof configContent === 'string') {\n await fsp.writeFile(configPath, configContent, 'utf8');\n } else {\n await writeJSON(configPath, configContent);\n }\n };\n\n if (!exists) {\n await writeIt();\n console.log(c('green', ` Generated ${template.configFileName}`));\n } else if (template.alwaysWriteConfig) {\n await writeIt();\n console.log(c('green', ` Updated ${template.configFileName} (build output reference)`));\n } else {\n console.log(c('yellow', ` ${template.configFileName} already exists (skipping)`));\n }\n }\n}\n\n/** Map target names to internal adapter names. */\nconst TARGET_TO_ADAPTER: Record<string, AdapterName> = {\n 'vercel': 'vercel',\n 'lambda': 'lambda',\n 'cloudflare': 'cloudflare',\n 'distributed': 'distributed',\n};\n\n/**\n * Build the FrontMCP server for a specific deployment target.\n *\n * @example\n * ```bash\n * frontmcp build --target node # Node.js server bundle\n * frontmcp build --target cli # CLI with SEA binary\n * frontmcp build --target cli --js # CLI without SEA\n * frontmcp build --target sdk # Library (CJS+ESM+types)\n * frontmcp build --target browser # Browser ESM bundle\n * frontmcp build --target vercel # Vercel serverless\n * frontmcp build --target lambda # AWS Lambda\n * frontmcp build --target cloudflare # Cloudflare Workers\n * ```\n */\nexport async function runBuild(opts: ParsedArgs): Promise<void> {\n const cwd = process.cwd();\n\n // Try loading frontmcp.config for multi-target support.\n //\n // #365 — `tryLoadFrontMcpConfig` differentiates between recoverable cases:\n // - no config file present → returns undefined\n // - config exists but doesn't match the new schema → returns undefined\n // (legacy top-level `cli`/`sea`/`esbuild` shape — picked up later by\n // the exec-build's own `loadExecConfig`)\n // …and hard failures:\n // - file exists but can't be parsed (TS syntax error, broken require)\n // → the error propagates, no silent-default regression.\n const config: FrontMcpConfigParsed | undefined = await tryLoadFrontMcpConfig(cwd);\n\n // If no -t flag and config has deployments, build all targets from config\n if (!opts.buildTarget && config && config.deployments.length > 0) {\n const targets = getDeploymentTargets(config);\n console.log(c('cyan', `[build] Building ${targets.length} target(s) from frontmcp.config: ${targets.join(', ')}`));\n\n for (const targetName of targets) {\n console.log(c('cyan', `\\n[build] ═══ ${targetName} ═══`));\n await buildSingleTarget(targetName, opts, config);\n }\n return;\n }\n\n // Single target build (from -t flag or default 'node')\n const target = opts.buildTarget ?? 'node';\n await buildSingleTarget(target, opts, config);\n}\n\n/**\n * Build a single deployment target.\n * Merges per-target config (from frontmcp.config) with CLI opts.\n */\nasync function buildSingleTarget(\n target: string,\n opts: ParsedArgs,\n config?: FrontMcpConfigParsed,\n): Promise<void> {\n const deployment:DeploymentTarget | undefined = config ? findDeployment(config, target) : undefined;\n\n // Resolve output directory: deployment.outDir > CLI --out-dir > dist/{target}\n const baseOutDir = path.resolve(process.cwd(), opts.outDir || 'dist');\n const targetOutDir = deployment?.outDir\n ? path.resolve(process.cwd(), deployment.outDir)\n : path.join(baseOutDir, target);\n\n // Merge entry from config if not provided via CLI\n const entry = opts.entry || config?.entry;\n const targetOpts = { ...opts, outDir: targetOutDir, entry };\n\n // #370: forward `build.storage` and per-deployment `cli.outputDefault` from\n // the FrontMcp config into the exec build so the manifest reflects them.\n // The exec build has its own loader (`loadExecConfig`) that doesn't see\n // the deployment-level shape; passing these via opts merges them in\n // `normalizeConfig` before the manifest is generated.\n //\n // Only the cli deployment shape carries a `cli` block; map it down to the\n // narrow exec-config shape (outputDefault / description / authRequired) so\n // the result is a clean object, never `false`.\n const cliDeploymentConfig = deployment?.target === 'cli' ? deployment.cli : undefined;\n const execOverrides: {\n storage?: { type: 'sqlite' | 'redis' | 'none'; required?: boolean };\n cli?: { outputDefault?: 'text' | 'json'; description?: string; authRequired?: boolean };\n // #365 round-3 — without this, top-level `nodeVersion` declared in\n // `frontmcp.config.{ts,js}` was silently dropped because the legacy\n // `loadExecConfig` doesn't read .ts and the new-shape loader's result\n // wasn't forwarded into buildExec. The exec build's manifest emitter\n // shipped the SDK default (`>=22.0.0`) instead of the user's value.\n nodeVersion?: string;\n } = {\n storage: config?.build?.storage,\n cli: cliDeploymentConfig\n ? {\n ...(cliDeploymentConfig.outputDefault ? { outputDefault: cliDeploymentConfig.outputDefault } : {}),\n ...(cliDeploymentConfig.description ? { description: cliDeploymentConfig.description } : {}),\n ...(typeof cliDeploymentConfig.authRequired === 'boolean'\n ? { authRequired: cliDeploymentConfig.authRequired }\n : {}),\n }\n : undefined,\n nodeVersion: config?.nodeVersion,\n };\n\n switch (target) {\n case 'cli': {\n const { buildExec } = await import('./exec/index.js');\n return buildExec({\n ...targetOpts,\n cli: true,\n sea: !opts.js,\n execOverrides,\n } as ParsedArgs & { cli: boolean; sea: boolean; execOverrides?: typeof execOverrides });\n }\n case 'node': {\n const { buildExec } = await import('./exec/index.js');\n return buildExec({\n ...targetOpts,\n execOverrides,\n } as ParsedArgs & { execOverrides?: typeof execOverrides });\n }\n case 'sdk': {\n const { buildSdk } = await import('./sdk/index.js');\n return buildSdk(targetOpts);\n }\n case 'browser': {\n const { buildBrowser } = await import('./browser/index.js');\n return buildBrowser(targetOpts);\n }\n case 'mcpb': {\n const { buildMcpb } = await import('./mcpb/index.js');\n return buildMcpb(targetOpts, config);\n }\n case 'vercel':\n case 'lambda':\n case 'cloudflare':\n case 'distributed': {\n const adapter = TARGET_TO_ADAPTER[target];\n return runAdapterBuild(targetOpts, adapter, deployment);\n }\n default:\n throw new Error(`Unknown build target: ${target}. Available: cli, node, sdk, browser, cloudflare, vercel, lambda, distributed, mcpb`);\n }\n}\n\n/**\n * Build using a deployment adapter (serverless platforms).\n */\nasync function runAdapterBuild(\n opts: ParsedArgs,\n adapter: AdapterName,\n deployment?: DeploymentTarget,\n): Promise<void> {\n const cwd = process.cwd();\n const entry = await resolveEntry(cwd, opts.entry);\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n await ensureDir(outDir);\n\n const template = ADAPTERS[adapter];\n if (!template) {\n const available = Object.keys(ADAPTERS).join(', ');\n throw new Error(`Unknown adapter: ${adapter}. Available: ${available}`);\n }\n\n if (adapter === 'cloudflare') {\n console.log(\n c('yellow', 'Cloudflare Workers adapter is experimental. See docs for limitations.'),\n );\n }\n\n // #375 — adapter-level pre-validation: read the entry's @FrontMcp() config\n // metadata and let the adapter reject incompatible features\n // (sqlite/redis on Workers, etc.) before emitting an unrunnable bundle.\n // `loadEntryDecoratorInfo` handles both compiled-JS and raw-TS entries\n // (TS goes through esbuild + Module._compile so we don't need a tsc pass)\n // AND scans the source AST for keys hidden behind env-gated ternaries —\n // round-2 made the env-gated case the headline #375 reproducer.\n if (template.validate) {\n const { loadEntryDecoratorInfo } = await import('./load-entry-config.js');\n const info = await loadEntryDecoratorInfo(entry);\n template.validate(info.decoratorConfig, { keysSeenInSource: info.keysSeenInSource });\n }\n\n const moduleFormat = template.moduleFormat;\n\n console.log(`${c('cyan', '[build]')} entry: ${path.relative(cwd, entry)}`);\n console.log(`${c('cyan', '[build]')} outDir: ${path.relative(cwd, outDir)}`);\n console.log(`${c('cyan', '[build]')} target: ${adapter} (${moduleFormat})`);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const args: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n console.log(c('gray', `[build] tsconfig.json detected — compiling with project settings`));\n args.push('--project', tsconfigPath);\n } else {\n args.push(entry);\n args.push('--rootDir', path.dirname(entry));\n if (!isTsLike(entry)) {\n args.push('--allowJs');\n console.log(c('yellow', '[build] Entry is not TypeScript; enabling --allowJs'));\n }\n args.push('--experimentalDecorators', '--emitDecoratorMetadata');\n args.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n args.push('--module', moduleFormat);\n args.push('--outDir', outDir);\n args.push('--skipLibCheck');\n\n await runCmd('npx', args);\n\n if (adapter !== 'node') {\n console.log(c('cyan', `[build] Generating ${adapter} deployment files...`));\n const entryBasename = path.basename(entry);\n await generateAdapterFiles(adapter, outDir, entryBasename, cwd, deployment);\n }\n\n console.log(c('green', 'Build completed.'));\n console.log(c('gray', `Output placed in ${path.relative(cwd, outDir)}`));\n}\n"]}
|
|
@@ -102,17 +102,32 @@ async function loadRawConfig(cwd) {
|
|
|
102
102
|
return JSON.parse(content);
|
|
103
103
|
}
|
|
104
104
|
if (filename.endsWith('.ts')) {
|
|
105
|
-
// #365 —
|
|
106
|
-
//
|
|
107
|
-
// Node
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
105
|
+
// #365 — Loading `.ts` under `"type": "commonjs"` (the default) is a
|
|
106
|
+
// minefield across Node versions:
|
|
107
|
+
// - Node 20: `require()` throws on TS syntax, `await import()` errors
|
|
108
|
+
// with "Make sure to set type: module".
|
|
109
|
+
// - Node 22+: `require(esm)` may succeed but return partial data, OR
|
|
110
|
+
// emit a warning on `await import()` even when the load succeeds.
|
|
111
|
+
// - Node 24: type-stripping may swallow `import { x } from ...`
|
|
112
|
+
// statements, returning `{}` instead of the user's exports — the
|
|
113
|
+
// 1.1.2-beta.1 silent-defaults regression.
|
|
114
|
+
// Round 3: under CJS, ALWAYS transpile via esbuild. It's the only path
|
|
115
|
+
// that produces a deterministic, fully-typed result. ESM projects can
|
|
116
|
+
// still use Node's runtime loaders since they're well-behaved there.
|
|
115
117
|
const isCjsProject = await isCommonJsProject(cwd);
|
|
118
|
+
if (isCjsProject) {
|
|
119
|
+
try {
|
|
120
|
+
return await loadTsConfigViaEsbuild(configPath);
|
|
121
|
+
}
|
|
122
|
+
catch (esbuildErr) {
|
|
123
|
+
throw new Error(`Failed to load ${filename} via esbuild.\n` +
|
|
124
|
+
` ${esbuildErr.message}\n` +
|
|
125
|
+
`Hint: ensure the file exports a default config (e.g., ` +
|
|
126
|
+
`\`export default defineConfig({...})\`) and that all imports resolve.`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// ESM project ("type": "module"): try Node's loaders first (faster,
|
|
130
|
+
// no transpile cost), fall back to esbuild on failure.
|
|
116
131
|
let requireErr;
|
|
117
132
|
try {
|
|
118
133
|
const mod = require(configPath);
|
|
@@ -121,14 +136,12 @@ async function loadRawConfig(cwd) {
|
|
|
121
136
|
catch (e) {
|
|
122
137
|
requireErr = e;
|
|
123
138
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
// Fall through to esbuild.
|
|
131
|
-
}
|
|
139
|
+
try {
|
|
140
|
+
const mod = await import(configPath);
|
|
141
|
+
return mod.default ?? mod;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
// Fall through to esbuild.
|
|
132
145
|
}
|
|
133
146
|
try {
|
|
134
147
|
return await loadTsConfigViaEsbuild(configPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmcp-config.loader.js","sourceRoot":"","sources":["../../../src/config/frontmcp-config.loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * FrontMCP Config Loader\n *\n * Loads `frontmcp.config.(json|js|ts|mjs|cjs)` from a directory.\n * Falls back to deriving minimal config from package.json.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { readFile } from '@frontmcp/utils';\n\nimport { frontmcpConfigSchema, type FrontMcpConfigParsed } from './frontmcp-config.schema';\nimport type { DeploymentTarget, FrontMcpConfig } from './frontmcp-config.types';\n\nconst CONFIG_FILENAMES = [\n 'frontmcp.config.ts',\n 'frontmcp.config.js',\n 'frontmcp.config.json',\n 'frontmcp.config.mjs',\n 'frontmcp.config.cjs',\n];\n\n/**\n * Load and validate a frontmcp.config file from the given directory.\n *\n * Resolution order:\n * 1. frontmcp.config.ts\n * 2. frontmcp.config.js\n * 3. frontmcp.config.json\n * 4. frontmcp.config.mjs\n * 5. frontmcp.config.cjs\n * 6. Derive from package.json (minimal config with 'node' target)\n */\nexport async function loadFrontMcpConfig(cwd: string): Promise<FrontMcpConfigParsed> {\n const raw = await loadRawConfig(cwd);\n return validateConfig(raw);\n}\n\n/**\n * Variant that load-errors propagate (parse failures in `frontmcp.config.ts`,\n * missing dependencies, etc.) but schema-validation errors return `undefined`.\n *\n * Used by `runBuild` to support both shapes: the new top-level\n * `frontmcpConfigSchema` (with `deployments`) and the older exec-only shape\n * (top-level `cli`, `sea`, `esbuild`) that `loadExecConfig` consumes\n * directly. A user with the old shape should still get a successful build\n * — the exec-loader picks the file up from disk by itself.\n *\n * Returns `undefined` when:\n * - no config file is present (caller falls back to CLI flags), or\n * - the file loads but doesn't match the new schema (legacy shape).\n *\n * Throws when:\n * - the file exists but can't be parsed (TS syntax error, ESM/CJS mismatch\n * that even esbuild can't recover from, etc.) — i.e., #365 silent-default\n * regressions.\n */\nexport async function tryLoadFrontMcpConfig(cwd: string): Promise<FrontMcpConfigParsed | undefined> {\n let raw: unknown;\n try {\n raw = await loadRawConfig(cwd);\n } catch (err) {\n // Distinguish \"no config and no package.json\" from real load failures.\n // `deriveFromPackageJson` throws this exact message — treat it as \"no config\".\n if ((err as Error).message?.startsWith('No frontmcp.config found')) {\n return undefined;\n }\n throw err;\n }\n const result = frontmcpConfigSchema.safeParse(raw);\n if (!result.success) {\n // Distinguish two failure shapes:\n // 1. Legacy exec-only config — top-level `cli` / `sea` / `esbuild`,\n // no `deployments` key. Return undefined so `loadExecConfig` picks\n // it up directly. Pre-v1.1 fixtures live in this branch.\n // 2. Anything else — looks like the user attempted a v1.1 config and\n // got it wrong (typo'd `deployments`, invalid `target`, etc.).\n // Throw so we don't silently fall back to defaults — that was the\n // silent-corruption mode #365 was trying to eliminate.\n const obj = typeof raw === 'object' && raw !== null ? (raw as Record<string, unknown>) : undefined;\n const isLegacyExecOnlyShape =\n !!obj && !('deployments' in obj) && ('cli' in obj || 'sea' in obj || 'esbuild' in obj);\n if (isLegacyExecOnlyShape) return undefined;\n const issues = result.error.issues.map((i) => ` - ${i.path.join('.')}: ${i.message}`).join('\\n');\n throw new Error(`Invalid frontmcp.config:\\n${issues}`);\n }\n return result.data;\n}\n\n/**\n * Load raw config without validation.\n */\nasync function loadRawConfig(cwd: string): Promise<unknown> {\n for (const filename of CONFIG_FILENAMES) {\n const configPath = path.join(cwd, filename);\n if (!fs.existsSync(configPath)) continue;\n\n if (filename.endsWith('.json')) {\n const content = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(content);\n }\n\n if (filename.endsWith('.ts')) {\n // #365 — When the project is `\"type\": \"commonjs\"` (the default),\n // `require()` can't load .ts without a hook and `await import()` emits\n // Node's `Failed to load the ES module … Make sure to set \"type\": \"module\"`\n // warning to stderr regardless of whether type-stripping eventually\n // succeeds — that warning by itself looked to retesters like a hard\n // load failure even when the build proceeded. Round 2: when the host\n // project is CJS, skip Node's `await import()` entirely and go\n // straight to esbuild. For ESM projects we still try the runtime\n // paths first (faster, no transpile cost). Either way, a failure on\n // every path throws the combined error — never silent defaults.\n const isCjsProject = await isCommonJsProject(cwd);\n let requireErr: Error | undefined;\n try {\n const mod = require(configPath);\n return mod.default ?? mod;\n } catch (e) {\n requireErr = e as Error;\n }\n if (!isCjsProject) {\n try {\n const mod = await import(configPath);\n return mod.default ?? mod;\n } catch {\n // Fall through to esbuild.\n }\n }\n try {\n return await loadTsConfigViaEsbuild(configPath);\n } catch (esbuildErr) {\n throw new Error(\n `Failed to load ${filename}.\\n` +\n ` require() error: ${requireErr?.message ?? '(skipped)'}\\n` +\n ` esbuild error: ${(esbuildErr as Error).message}\\n` +\n `Hint: ensure the file exports a default config (e.g., ` +\n `\\`export default defineConfig({...})\\`) and that all imports resolve.`,\n );\n }\n }\n\n // JS/MJS/CJS\n if (filename.endsWith('.mjs')) {\n const mod = await import(configPath);\n return mod.default ?? mod;\n }\n\n const mod = require(configPath);\n return mod.default ?? mod;\n }\n\n // Fallback: derive from package.json\n return deriveFromPackageJson(cwd);\n}\n\n/**\n * Read the host project's `package.json.type` to decide whether `await import()`\n * of a `.ts` file is worth attempting. Returns true when the project is\n * declared `\"type\": \"commonjs\"` or omits the field entirely (Node's default).\n *\n * Read errors (no package.json, malformed JSON) are treated as \"CJS\" — that's\n * the safer default for the loader because it routes us through esbuild\n * transpilation rather than relying on Node's experimental TS handling.\n *\n * Routed through `@frontmcp/utils` per repo convention so this module\n * doesn't reach into `node:fs` for an ad-hoc package.json read.\n */\nasync function isCommonJsProject(cwd: string): Promise<boolean> {\n try {\n const pkgPath = path.join(cwd, 'package.json');\n const contents = await readFile(pkgPath);\n const pkg = JSON.parse(contents) as { type?: string };\n return pkg.type !== 'module';\n } catch {\n return true;\n }\n}\n\n/**\n * Transpile a TypeScript config file with esbuild (CJS target) and eval the\n * result via Module-via-vm. Used as a last-resort path when neither `require()`\n * (no ts-node hook) nor `await import()` (project is `\"type\": \"commonjs\"`)\n * can load the file directly.\n *\n * Uses `esbuild.build({ bundle: true, packages: 'external' })` rather than\n * `transformSync` so a config that imports a sibling helper TS file\n * (`import { foo } from './helpers'`) gets the helper inlined into the\n * compiled output. Without bundling, the resulting CJS would emit\n * `require('./helpers')` which Node can't resolve under `\"type\": \"commonjs\"`.\n *\n * `packages: 'external'` keeps node_modules dependencies as runtime\n * `require()` calls so `import { defineConfig } from 'frontmcp'` still\n * resolves against the project's installed copy of the SDK.\n */\nasync function loadTsConfigViaEsbuild(configPath: string): Promise<unknown> {\n const esbuild = require('esbuild') as typeof import('esbuild');\n const built = await esbuild.build({\n entryPoints: [configPath],\n bundle: true,\n write: false,\n platform: 'node',\n format: 'cjs',\n target: 'es2022',\n packages: 'external',\n sourcemap: 'inline',\n logLevel: 'silent',\n });\n if (!built.outputFiles || built.outputFiles.length === 0) {\n throw new Error('esbuild produced no output for ' + configPath);\n }\n const code = built.outputFiles[0].text;\n\n const Module = require('module') as typeof import('module');\n const m = new Module(configPath, module);\n // Make the loaded module's `require` resolve relative to the config dir\n // so user `import { defineConfig } from 'frontmcp'` keeps working.\n m.filename = configPath;\n m.paths = (Module as unknown as { _nodeModulePaths(p: string): string[] })._nodeModulePaths(path.dirname(configPath));\n\n (m as any)._compile(code, configPath);\n\n const exported = (m as any).exports as { default?: unknown };\n return exported?.default ?? exported;\n}\n\n/**\n * Derive minimal config from package.json.\n */\nfunction deriveFromPackageJson(cwd: string): FrontMcpConfig {\n const pkgPath = path.join(cwd, 'package.json');\n if (!fs.existsSync(pkgPath)) {\n throw new Error(\n 'No frontmcp.config found and no package.json. Create a frontmcp.config.ts to configure build targets.',\n );\n }\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));\n return {\n name: pkg.name?.replace(/^@[^/]+\\//, '') || path.basename(cwd),\n version: pkg.version || '1.0.0',\n entry: pkg.main,\n deployments: [{ target: 'node' }],\n };\n}\n\n/**\n * Validate raw config against the Zod schema.\n */\nexport function validateConfig(raw: unknown): FrontMcpConfigParsed {\n const result = frontmcpConfigSchema.safeParse(raw);\n if (!result.success) {\n const issues = result.error.issues.map((i) => ` - ${i.path.join('.')}: ${i.message}`).join('\\n');\n throw new Error(`Invalid frontmcp.config:\\n${issues}`);\n }\n return result.data;\n}\n\n/**\n * Find a deployment target by type.\n */\nexport function findDeployment(config: FrontMcpConfigParsed, target: string): DeploymentTarget | undefined {\n return config.deployments.find((d) => d.target === target);\n}\n\n/**\n * Get all deployment target types from the config.\n */\nexport function getDeploymentTargets(config: FrontMcpConfigParsed): string[] {\n return config.deployments.map((d) => d.target);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"frontmcp-config.loader.js","sourceRoot":"","sources":["../../../src/config/frontmcp-config.loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * FrontMCP Config Loader\n *\n * Loads `frontmcp.config.(json|js|ts|mjs|cjs)` from a directory.\n * Falls back to deriving minimal config from package.json.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { readFile } from '@frontmcp/utils';\n\nimport { frontmcpConfigSchema, type FrontMcpConfigParsed } from './frontmcp-config.schema';\nimport type { DeploymentTarget, FrontMcpConfig } from './frontmcp-config.types';\n\nconst CONFIG_FILENAMES = [\n 'frontmcp.config.ts',\n 'frontmcp.config.js',\n 'frontmcp.config.json',\n 'frontmcp.config.mjs',\n 'frontmcp.config.cjs',\n];\n\n/**\n * Load and validate a frontmcp.config file from the given directory.\n *\n * Resolution order:\n * 1. frontmcp.config.ts\n * 2. frontmcp.config.js\n * 3. frontmcp.config.json\n * 4. frontmcp.config.mjs\n * 5. frontmcp.config.cjs\n * 6. Derive from package.json (minimal config with 'node' target)\n */\nexport async function loadFrontMcpConfig(cwd: string): Promise<FrontMcpConfigParsed> {\n const raw = await loadRawConfig(cwd);\n return validateConfig(raw);\n}\n\n/**\n * Variant that load-errors propagate (parse failures in `frontmcp.config.ts`,\n * missing dependencies, etc.) but schema-validation errors return `undefined`.\n *\n * Used by `runBuild` to support both shapes: the new top-level\n * `frontmcpConfigSchema` (with `deployments`) and the older exec-only shape\n * (top-level `cli`, `sea`, `esbuild`) that `loadExecConfig` consumes\n * directly. A user with the old shape should still get a successful build\n * — the exec-loader picks the file up from disk by itself.\n *\n * Returns `undefined` when:\n * - no config file is present (caller falls back to CLI flags), or\n * - the file loads but doesn't match the new schema (legacy shape).\n *\n * Throws when:\n * - the file exists but can't be parsed (TS syntax error, ESM/CJS mismatch\n * that even esbuild can't recover from, etc.) — i.e., #365 silent-default\n * regressions.\n */\nexport async function tryLoadFrontMcpConfig(cwd: string): Promise<FrontMcpConfigParsed | undefined> {\n let raw: unknown;\n try {\n raw = await loadRawConfig(cwd);\n } catch (err) {\n // Distinguish \"no config and no package.json\" from real load failures.\n // `deriveFromPackageJson` throws this exact message — treat it as \"no config\".\n if ((err as Error).message?.startsWith('No frontmcp.config found')) {\n return undefined;\n }\n throw err;\n }\n const result = frontmcpConfigSchema.safeParse(raw);\n if (!result.success) {\n // Distinguish two failure shapes:\n // 1. Legacy exec-only config — top-level `cli` / `sea` / `esbuild`,\n // no `deployments` key. Return undefined so `loadExecConfig` picks\n // it up directly. Pre-v1.1 fixtures live in this branch.\n // 2. Anything else — looks like the user attempted a v1.1 config and\n // got it wrong (typo'd `deployments`, invalid `target`, etc.).\n // Throw so we don't silently fall back to defaults — that was the\n // silent-corruption mode #365 was trying to eliminate.\n const obj = typeof raw === 'object' && raw !== null ? (raw as Record<string, unknown>) : undefined;\n const isLegacyExecOnlyShape =\n !!obj && !('deployments' in obj) && ('cli' in obj || 'sea' in obj || 'esbuild' in obj);\n if (isLegacyExecOnlyShape) return undefined;\n const issues = result.error.issues.map((i) => ` - ${i.path.join('.')}: ${i.message}`).join('\\n');\n throw new Error(`Invalid frontmcp.config:\\n${issues}`);\n }\n return result.data;\n}\n\n/**\n * Load raw config without validation.\n */\nasync function loadRawConfig(cwd: string): Promise<unknown> {\n for (const filename of CONFIG_FILENAMES) {\n const configPath = path.join(cwd, filename);\n if (!fs.existsSync(configPath)) continue;\n\n if (filename.endsWith('.json')) {\n const content = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(content);\n }\n\n if (filename.endsWith('.ts')) {\n // #365 — Loading `.ts` under `\"type\": \"commonjs\"` (the default) is a\n // minefield across Node versions:\n // - Node 20: `require()` throws on TS syntax, `await import()` errors\n // with \"Make sure to set type: module\".\n // - Node 22+: `require(esm)` may succeed but return partial data, OR\n // emit a warning on `await import()` even when the load succeeds.\n // - Node 24: type-stripping may swallow `import { x } from ...`\n // statements, returning `{}` instead of the user's exports — the\n // 1.1.2-beta.1 silent-defaults regression.\n // Round 3: under CJS, ALWAYS transpile via esbuild. It's the only path\n // that produces a deterministic, fully-typed result. ESM projects can\n // still use Node's runtime loaders since they're well-behaved there.\n const isCjsProject = await isCommonJsProject(cwd);\n if (isCjsProject) {\n try {\n return await loadTsConfigViaEsbuild(configPath);\n } catch (esbuildErr) {\n throw new Error(\n `Failed to load ${filename} via esbuild.\\n` +\n ` ${(esbuildErr as Error).message}\\n` +\n `Hint: ensure the file exports a default config (e.g., ` +\n `\\`export default defineConfig({...})\\`) and that all imports resolve.`,\n );\n }\n }\n // ESM project (\"type\": \"module\"): try Node's loaders first (faster,\n // no transpile cost), fall back to esbuild on failure.\n let requireErr: Error | undefined;\n try {\n const mod = require(configPath);\n return mod.default ?? mod;\n } catch (e) {\n requireErr = e as Error;\n }\n try {\n const mod = await import(configPath);\n return mod.default ?? mod;\n } catch {\n // Fall through to esbuild.\n }\n try {\n return await loadTsConfigViaEsbuild(configPath);\n } catch (esbuildErr) {\n throw new Error(\n `Failed to load ${filename}.\\n` +\n ` require() error: ${requireErr?.message ?? '(skipped)'}\\n` +\n ` esbuild error: ${(esbuildErr as Error).message}\\n` +\n `Hint: ensure the file exports a default config (e.g., ` +\n `\\`export default defineConfig({...})\\`) and that all imports resolve.`,\n );\n }\n }\n\n // JS/MJS/CJS\n if (filename.endsWith('.mjs')) {\n const mod = await import(configPath);\n return mod.default ?? mod;\n }\n\n const mod = require(configPath);\n return mod.default ?? mod;\n }\n\n // Fallback: derive from package.json\n return deriveFromPackageJson(cwd);\n}\n\n/**\n * Read the host project's `package.json.type` to decide whether `await import()`\n * of a `.ts` file is worth attempting. Returns true when the project is\n * declared `\"type\": \"commonjs\"` or omits the field entirely (Node's default).\n *\n * Read errors (no package.json, malformed JSON) are treated as \"CJS\" — that's\n * the safer default for the loader because it routes us through esbuild\n * transpilation rather than relying on Node's experimental TS handling.\n *\n * Routed through `@frontmcp/utils` per repo convention so this module\n * doesn't reach into `node:fs` for an ad-hoc package.json read.\n */\nasync function isCommonJsProject(cwd: string): Promise<boolean> {\n try {\n const pkgPath = path.join(cwd, 'package.json');\n const contents = await readFile(pkgPath);\n const pkg = JSON.parse(contents) as { type?: string };\n return pkg.type !== 'module';\n } catch {\n return true;\n }\n}\n\n/**\n * Transpile a TypeScript config file with esbuild (CJS target) and eval the\n * result via Module-via-vm. Used as a last-resort path when neither `require()`\n * (no ts-node hook) nor `await import()` (project is `\"type\": \"commonjs\"`)\n * can load the file directly.\n *\n * Uses `esbuild.build({ bundle: true, packages: 'external' })` rather than\n * `transformSync` so a config that imports a sibling helper TS file\n * (`import { foo } from './helpers'`) gets the helper inlined into the\n * compiled output. Without bundling, the resulting CJS would emit\n * `require('./helpers')` which Node can't resolve under `\"type\": \"commonjs\"`.\n *\n * `packages: 'external'` keeps node_modules dependencies as runtime\n * `require()` calls so `import { defineConfig } from 'frontmcp'` still\n * resolves against the project's installed copy of the SDK.\n */\nasync function loadTsConfigViaEsbuild(configPath: string): Promise<unknown> {\n const esbuild = require('esbuild') as typeof import('esbuild');\n const built = await esbuild.build({\n entryPoints: [configPath],\n bundle: true,\n write: false,\n platform: 'node',\n format: 'cjs',\n target: 'es2022',\n packages: 'external',\n sourcemap: 'inline',\n logLevel: 'silent',\n });\n if (!built.outputFiles || built.outputFiles.length === 0) {\n throw new Error('esbuild produced no output for ' + configPath);\n }\n const code = built.outputFiles[0].text;\n\n const Module = require('module') as typeof import('module');\n const m = new Module(configPath, module);\n // Make the loaded module's `require` resolve relative to the config dir\n // so user `import { defineConfig } from 'frontmcp'` keeps working.\n m.filename = configPath;\n m.paths = (Module as unknown as { _nodeModulePaths(p: string): string[] })._nodeModulePaths(path.dirname(configPath));\n\n (m as any)._compile(code, configPath);\n\n const exported = (m as any).exports as { default?: unknown };\n return exported?.default ?? exported;\n}\n\n/**\n * Derive minimal config from package.json.\n */\nfunction deriveFromPackageJson(cwd: string): FrontMcpConfig {\n const pkgPath = path.join(cwd, 'package.json');\n if (!fs.existsSync(pkgPath)) {\n throw new Error(\n 'No frontmcp.config found and no package.json. Create a frontmcp.config.ts to configure build targets.',\n );\n }\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));\n return {\n name: pkg.name?.replace(/^@[^/]+\\//, '') || path.basename(cwd),\n version: pkg.version || '1.0.0',\n entry: pkg.main,\n deployments: [{ target: 'node' }],\n };\n}\n\n/**\n * Validate raw config against the Zod schema.\n */\nexport function validateConfig(raw: unknown): FrontMcpConfigParsed {\n const result = frontmcpConfigSchema.safeParse(raw);\n if (!result.success) {\n const issues = result.error.issues.map((i) => ` - ${i.path.join('.')}: ${i.message}`).join('\\n');\n throw new Error(`Invalid frontmcp.config:\\n${issues}`);\n }\n return result.data;\n}\n\n/**\n * Find a deployment target by type.\n */\nexport function findDeployment(config: FrontMcpConfigParsed, target: string): DeploymentTarget | undefined {\n return config.deployments.find((d) => d.target === target);\n}\n\n/**\n * Get all deployment target types from the config.\n */\nexport function getDeploymentTargets(config: FrontMcpConfigParsed): string[] {\n return config.deployments.map((d) => d.target);\n}\n"]}
|