frontmcp 1.0.0-beta.7 → 1.0.0-beta.9
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/cloudflare.js +1 -1
- package/src/commands/build/adapters/cloudflare.js.map +1 -1
- package/src/commands/build/adapters/lambda.js +1 -1
- package/src/commands/build/adapters/lambda.js.map +1 -1
- package/src/commands/build/adapters/vercel.js +1 -1
- package/src/commands/build/adapters/vercel.js.map +1 -1
- package/src/commands/build/browser/index.d.ts +17 -0
- package/src/commands/build/browser/index.js +68 -0
- package/src/commands/build/browser/index.js.map +1 -0
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +53 -13
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -1
- package/src/commands/build/exec/config.d.ts +3 -0
- package/src/commands/build/exec/config.js +1 -1
- package/src/commands/build/exec/config.js.map +1 -1
- package/src/commands/build/exec/esbuild-bundler.js +1 -1
- package/src/commands/build/exec/esbuild-bundler.js.map +1 -1
- package/src/commands/build/exec/index.d.ts +4 -1
- package/src/commands/build/exec/index.js.map +1 -1
- package/src/commands/build/exec/installer-script.js +1 -1
- package/src/commands/build/exec/installer-script.js.map +1 -1
- package/src/commands/build/exec/runner-script.js +3 -3
- package/src/commands/build/exec/runner-script.js.map +1 -1
- package/src/commands/build/index.d.ts +8 -13
- package/src/commands/build/index.js +48 -27
- package/src/commands/build/index.js.map +1 -1
- package/src/commands/build/register.js +4 -5
- package/src/commands/build/register.js.map +1 -1
- package/src/commands/build/sdk/index.d.ts +13 -0
- package/src/commands/build/sdk/index.js +76 -0
- package/src/commands/build/sdk/index.js.map +1 -0
- package/src/commands/dev/dev.js +54 -7
- package/src/commands/dev/dev.js.map +1 -1
- package/src/commands/package/install.js +2 -2
- package/src/commands/package/install.js.map +1 -1
- package/src/commands/scaffold/create.d.ts +3 -0
- package/src/commands/scaffold/create.js +85 -0
- package/src/commands/scaffold/create.js.map +1 -1
- package/src/commands/scaffold/register.js +2 -0
- package/src/commands/scaffold/register.js.map +1 -1
- package/src/commands/skills/catalog.d.ts +42 -0
- package/src/commands/skills/catalog.js +276 -0
- package/src/commands/skills/catalog.js.map +1 -0
- package/src/commands/skills/install.d.ts +4 -0
- package/src/commands/skills/install.js +40 -0
- package/src/commands/skills/install.js.map +1 -0
- package/src/commands/skills/list.d.ts +5 -0
- package/src/commands/skills/list.js +44 -0
- package/src/commands/skills/list.js.map +1 -0
- package/src/commands/skills/register.d.ts +2 -0
- package/src/commands/skills/register.js +59 -0
- package/src/commands/skills/register.js.map +1 -0
- package/src/commands/skills/search.d.ts +5 -0
- package/src/commands/skills/search.js +24 -0
- package/src/commands/skills/search.js.map +1 -0
- package/src/commands/skills/show.d.ts +1 -0
- package/src/commands/skills/show.js +46 -0
- package/src/commands/skills/show.js.map +1 -0
- package/src/core/args.d.ts +5 -4
- package/src/core/args.js +19 -11
- package/src/core/args.js.map +1 -1
- package/src/core/bridge.d.ts +1 -4
- package/src/core/bridge.js +9 -14
- package/src/core/bridge.js.map +1 -1
- package/src/core/help.js +3 -3
- package/src/core/help.js.map +1 -1
- package/src/core/program.js +2 -0
- package/src/core/program.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontmcp",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.9",
|
|
4
4
|
"description": "FrontMCP command line interface",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"homepage": "https://docs.agentfront.dev",
|
|
@@ -30,17 +30,17 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@clack/prompts": "^0.10.0",
|
|
33
|
-
"@frontmcp/utils": "1.0.0-beta.
|
|
33
|
+
"@frontmcp/utils": "1.0.0-beta.9",
|
|
34
34
|
"commander": "^13.0.0",
|
|
35
35
|
"tslib": "^2.3.0",
|
|
36
|
+
"vectoriadb": "^2.1.3",
|
|
36
37
|
"@rspack/core": "^1.7.6",
|
|
37
38
|
"esbuild": "^0.27.3"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"typescript": "^5.5.3",
|
|
41
42
|
"tsx": "^4.20.6",
|
|
42
|
-
"@types/node": "^24.0.0"
|
|
43
|
-
"@modelcontextprotocol/inspector": "^0.21.1"
|
|
43
|
+
"@types/node": "^24.0.0"
|
|
44
44
|
},
|
|
45
45
|
"types": "./index.d.js",
|
|
46
46
|
"type": "commonjs"
|
|
@@ -10,7 +10,7 @@ exports.cloudflareAdapter = void 0;
|
|
|
10
10
|
exports.cloudflareAdapter = {
|
|
11
11
|
moduleFormat: 'commonjs',
|
|
12
12
|
getEntryTemplate: (mainModulePath) => `// Auto-generated Cloudflare Workers entry point
|
|
13
|
-
// Generated by: frontmcp build --
|
|
13
|
+
// Generated by: frontmcp build --target cloudflare
|
|
14
14
|
process.env.FRONTMCP_SERVERLESS = '1';
|
|
15
15
|
|
|
16
16
|
require('${mainModulePath}');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/cloudflare.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACU,QAAA,iBAAiB,GAAoB;IAChD,YAAY,EAAE,UAAU;IAExB,gBAAgB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC;;;;WAIrC,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDxB;IAEC,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;;;CAG9B;IAEC,cAAc,EAAE,eAAe;CAChC,CAAC","sourcesContent":["import { AdapterTemplate } from '../types';\n\n/**\n * Cloudflare Workers adapter - edge deployment on Cloudflare.\n * Compiles to CommonJS and adapts the Express app to Cloudflare's fetch API.\n *\n * @see https://developers.cloudflare.com/workers/\n */\nexport const cloudflareAdapter: AdapterTemplate = {\n moduleFormat: 'commonjs',\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated Cloudflare Workers entry point\n// Generated by: frontmcp build --
|
|
1
|
+
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/cloudflare.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACU,QAAA,iBAAiB,GAAoB;IAChD,YAAY,EAAE,UAAU;IAExB,gBAAgB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC;;;;WAIrC,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDxB;IAEC,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC;;;CAG9B;IAEC,cAAc,EAAE,eAAe;CAChC,CAAC","sourcesContent":["import { AdapterTemplate } from '../types';\n\n/**\n * Cloudflare Workers adapter - edge deployment on Cloudflare.\n * Compiles to CommonJS and adapts the Express app to Cloudflare's fetch API.\n *\n * @see https://developers.cloudflare.com/workers/\n */\nexport const cloudflareAdapter: AdapterTemplate = {\n moduleFormat: 'commonjs',\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated Cloudflare Workers entry point\n// Generated by: frontmcp build --target cloudflare\nprocess.env.FRONTMCP_SERVERLESS = '1';\n\nrequire('${mainModulePath}');\nconst { getServerlessHandlerAsync } = require('@frontmcp/sdk');\n\nlet app = null;\n\nasync function handleRequest(request) {\n if (!app) {\n app = await getServerlessHandlerAsync();\n }\n\n // Convert Cloudflare Request to Node.js format\n const url = new URL(request.url);\n const req = {\n method: request.method,\n url: url.pathname + url.search,\n headers: Object.fromEntries(request.headers),\n body: request.body,\n };\n\n return new Promise((resolve) => {\n const res = {\n statusCode: 200,\n headers: {},\n body: '',\n status(code) { this.statusCode = code; return this; },\n setHeader(key, value) { this.headers[key] = value; },\n json(data) {\n this.headers['Content-Type'] = 'application/json';\n this.body = JSON.stringify(data);\n resolve(new Response(this.body, {\n status: this.statusCode,\n headers: this.headers,\n }));\n },\n send(data) {\n this.body = data;\n resolve(new Response(this.body, {\n status: this.statusCode,\n headers: this.headers,\n }));\n },\n end() {\n resolve(new Response(this.body, {\n status: this.statusCode,\n headers: this.headers,\n }));\n },\n };\n app(req, res);\n });\n}\n\nmodule.exports = {\n async fetch(request, env, ctx) {\n return handleRequest(request);\n }\n};\n`,\n\n getConfig: (_cwd: string) => `name = \"frontmcp-worker\"\nmain = \"dist/index.js\"\ncompatibility_date = \"2024-01-01\"\n`,\n\n configFileName: 'wrangler.toml',\n};\n"]}
|
|
@@ -26,7 +26,7 @@ exports.lambdaAdapter = {
|
|
|
26
26
|
process.env.FRONTMCP_SERVERLESS = '1';
|
|
27
27
|
`,
|
|
28
28
|
getEntryTemplate: (mainModulePath) => `// Auto-generated AWS Lambda entry point
|
|
29
|
-
// Generated by: frontmcp build --
|
|
29
|
+
// Generated by: frontmcp build --target lambda
|
|
30
30
|
//
|
|
31
31
|
// IMPORTANT: This adapter requires @codegenie/serverless-express
|
|
32
32
|
// Install it with: npm install @codegenie/serverless-express
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lambda.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/lambda.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;GAcG;AACU,QAAA,aAAa,GAAoB;IAC5C,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,aAAa;IAE3B,gBAAgB,EAAE,GAAG,EAAE,CAAC;;;;CAIzB;IAEC,gBAAgB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC;;;;;;;UAOtC,cAAc;;;;;;;;;;;;;;;;;CAiBvB;IAEC,qEAAqE;CACtE,CAAC","sourcesContent":["import { 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 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';\n`,\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated AWS Lambda entry point\n// Generated by: frontmcp build --
|
|
1
|
+
{"version":3,"file":"lambda.js","sourceRoot":"","sources":["../../../../../src/commands/build/adapters/lambda.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;GAcG;AACU,QAAA,aAAa,GAAoB;IAC5C,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,aAAa;IAE3B,gBAAgB,EAAE,GAAG,EAAE,CAAC;;;;CAIzB;IAEC,gBAAgB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC;;;;;;;UAOtC,cAAc;;;;;;;;;;;;;;;;;CAiBvB;IAEC,qEAAqE;CACtE,CAAC","sourcesContent":["import { 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 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';\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//\nimport './serverless-setup.js';\nimport '${mainModulePath}';\nimport { getServerlessHandlerAsync } from '@frontmcp/sdk';\nimport serverlessExpress from '@codegenie/serverless-express';\n\nlet serverlessExpressInstance = null;\n\nasync function setup() {\n const app = await getServerlessHandlerAsync();\n serverlessExpressInstance = serverlessExpress({ app });\n}\n\nexport const handler = async (event, context) => {\n if (!serverlessExpressInstance) {\n await setup();\n }\n return serverlessExpressInstance(event, context);\n};\n`,\n\n // No config file - user manages serverless.yml, SAM template, or CDK\n};\n"]}
|
|
@@ -57,7 +57,7 @@ exports.vercelAdapter = {
|
|
|
57
57
|
process.env.FRONTMCP_SERVERLESS = '1';
|
|
58
58
|
`,
|
|
59
59
|
getEntryTemplate: (mainModulePath) => `// Auto-generated Vercel entry point
|
|
60
|
-
// Generated by: frontmcp build --
|
|
60
|
+
// Generated by: frontmcp build --target vercel
|
|
61
61
|
import './serverless-setup.js';
|
|
62
62
|
import '${mainModulePath}';
|
|
63
63
|
import { getServerlessHandlerAsync } from '@frontmcp/sdk';
|
|
@@ -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 { 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';\n`,\n\n getEntryTemplate: (mainModulePath: string) => `// Auto-generated Vercel entry point\n// Generated by: frontmcp build --adapter 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: 'nodejs22.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 { 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';\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: 'nodejs22.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"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ParsedArgs } from '../../../core/args';
|
|
2
|
+
/**
|
|
3
|
+
* Build a browser-compatible ESM bundle.
|
|
4
|
+
*
|
|
5
|
+
* Uses esbuild with `platform: 'browser'` which resolves conditional imports
|
|
6
|
+
* (`#imports` in package.json) to browser implementations automatically:
|
|
7
|
+
* - Crypto → @noble/hashes + @noble/ciphers (no node:crypto)
|
|
8
|
+
* - AsyncLocalStorage → stack-based polyfill
|
|
9
|
+
* - EventEmitter → Map-based polyfill
|
|
10
|
+
* - SSE/Express/Stdio → stubs that throw on instantiation
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```bash
|
|
14
|
+
* frontmcp build --target browser
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildBrowser(opts: ParsedArgs): Promise<void>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildBrowser = buildBrowser;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const path = tslib_1.__importStar(require("path"));
|
|
6
|
+
const colors_1 = require("../../../core/colors");
|
|
7
|
+
const utils_1 = require("@frontmcp/utils");
|
|
8
|
+
const fs_1 = require("../../../shared/fs");
|
|
9
|
+
/**
|
|
10
|
+
* Build a browser-compatible ESM bundle.
|
|
11
|
+
*
|
|
12
|
+
* Uses esbuild with `platform: 'browser'` which resolves conditional imports
|
|
13
|
+
* (`#imports` in package.json) to browser implementations automatically:
|
|
14
|
+
* - Crypto → @noble/hashes + @noble/ciphers (no node:crypto)
|
|
15
|
+
* - AsyncLocalStorage → stack-based polyfill
|
|
16
|
+
* - EventEmitter → Map-based polyfill
|
|
17
|
+
* - SSE/Express/Stdio → stubs that throw on instantiation
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```bash
|
|
21
|
+
* frontmcp build --target browser
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
async function buildBrowser(opts) {
|
|
25
|
+
const cwd = process.cwd();
|
|
26
|
+
const entry = await (0, fs_1.resolveEntry)(cwd, opts.entry);
|
|
27
|
+
const outDir = path.resolve(cwd, opts.outDir || 'dist');
|
|
28
|
+
await (0, utils_1.ensureDir)(outDir);
|
|
29
|
+
const pkg = require(path.join(cwd, 'package.json'));
|
|
30
|
+
const appName = pkg.name || path.basename(cwd);
|
|
31
|
+
console.log(`${(0, colors_1.c)('cyan', '[build:browser]')} entry: ${path.relative(cwd, entry)}`);
|
|
32
|
+
console.log(`${(0, colors_1.c)('cyan', '[build:browser]')} outDir: ${path.relative(cwd, outDir)}`);
|
|
33
|
+
const esbuild = await import('esbuild');
|
|
34
|
+
// Build ESM bundle for browsers
|
|
35
|
+
console.log((0, colors_1.c)('cyan', '[build:browser] Bundling ESM for browser...'));
|
|
36
|
+
await esbuild.build({
|
|
37
|
+
entryPoints: [entry],
|
|
38
|
+
bundle: true,
|
|
39
|
+
platform: 'browser',
|
|
40
|
+
format: 'esm',
|
|
41
|
+
target: 'es2022',
|
|
42
|
+
outfile: path.join(outDir, `${appName}.browser.mjs`),
|
|
43
|
+
keepNames: true,
|
|
44
|
+
treeShaking: true,
|
|
45
|
+
sourcemap: true,
|
|
46
|
+
// Browser-safe: keep React and peer deps external (user's bundler handles them)
|
|
47
|
+
external: [
|
|
48
|
+
'react', 'react-dom', 'react-router', 'react-router-dom',
|
|
49
|
+
// Keep @frontmcp/* external — user installs them
|
|
50
|
+
'@frontmcp/sdk', '@frontmcp/di', '@frontmcp/utils',
|
|
51
|
+
'@frontmcp/auth', '@frontmcp/react',
|
|
52
|
+
'reflect-metadata',
|
|
53
|
+
// Node.js-only — these should be tree-shaken by platform: 'browser'
|
|
54
|
+
// but list explicitly to avoid accidental bundling
|
|
55
|
+
'better-sqlite3', 'fsevents', 'ioredis',
|
|
56
|
+
...Object.keys(pkg.peerDependencies || {}),
|
|
57
|
+
],
|
|
58
|
+
// Resolve conditional imports to browser variants
|
|
59
|
+
conditions: ['browser', 'import', 'default'],
|
|
60
|
+
define: {
|
|
61
|
+
'process.env.NODE_ENV': '"production"',
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
console.log((0, colors_1.c)('green', `\n Browser build complete:`));
|
|
65
|
+
console.log((0, colors_1.c)('gray', ` ESM: ${appName}.browser.mjs`));
|
|
66
|
+
console.log((0, colors_1.c)('gray', ` Source map: ${appName}.browser.mjs.map`));
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/build/browser/index.ts"],"names":[],"mappings":";;AAqBA,oCAgDC;;AArED,mDAA6B;AAE7B,iDAAyC;AACzC,2CAA4C;AAC5C,2CAAkD;AAElD;;;;;;;;;;;;;;GAcG;AACI,KAAK,UAAU,YAAY,CAAC,IAAgB;IACjD,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,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE/C,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,iBAAiB,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IACnF,OAAO,CAAC,GAAG,CAAC,GAAG,IAAA,UAAC,EAAC,MAAM,EAAE,iBAAiB,CAAC,YAAY,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAErF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAExC,gCAAgC;IAChC,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,6CAA6C,CAAC,CAAC,CAAC;IACtE,MAAM,OAAO,CAAC,KAAK,CAAC;QAClB,WAAW,EAAE,CAAC,KAAK,CAAC;QACpB,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,cAAc,CAAC;QACpD,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,IAAI;QACjB,SAAS,EAAE,IAAI;QACf,gFAAgF;QAChF,QAAQ,EAAE;YACR,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB;YACxD,iDAAiD;YACjD,eAAe,EAAE,cAAc,EAAE,iBAAiB;YAClD,gBAAgB,EAAE,iBAAiB;YACnC,kBAAkB;YAClB,oEAAoE;YACpE,mDAAmD;YACnD,gBAAgB,EAAE,UAAU,EAAE,SAAS;YACvC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC;SAC3C;QACD,kDAAkD;QAClD,UAAU,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QAC5C,MAAM,EAAE;YACN,sBAAsB,EAAE,cAAc;SACvC;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,UAAU,OAAO,cAAc,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,IAAA,UAAC,EAAC,MAAM,EAAE,iBAAiB,OAAO,kBAAkB,CAAC,CAAC,CAAC;AACrE,CAAC","sourcesContent":["import * as path from 'path';\nimport { ParsedArgs } from '../../../core/args';\nimport { c } from '../../../core/colors';\nimport { ensureDir } from '@frontmcp/utils';\nimport { resolveEntry } from '../../../shared/fs';\n\n/**\n * Build a browser-compatible ESM bundle.\n *\n * Uses esbuild with `platform: 'browser'` which resolves conditional imports\n * (`#imports` in package.json) to browser implementations automatically:\n * - Crypto → @noble/hashes + @noble/ciphers (no node:crypto)\n * - AsyncLocalStorage → stack-based polyfill\n * - EventEmitter → Map-based polyfill\n * - SSE/Express/Stdio → stubs that throw on instantiation\n *\n * @example\n * ```bash\n * frontmcp build --target browser\n * ```\n */\nexport async function buildBrowser(opts: ParsedArgs): 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 pkg = require(path.join(cwd, 'package.json'));\n const appName = pkg.name || path.basename(cwd);\n\n console.log(`${c('cyan', '[build:browser]')} entry: ${path.relative(cwd, entry)}`);\n console.log(`${c('cyan', '[build:browser]')} outDir: ${path.relative(cwd, outDir)}`);\n\n const esbuild = await import('esbuild');\n\n // Build ESM bundle for browsers\n console.log(c('cyan', '[build:browser] Bundling ESM for browser...'));\n await esbuild.build({\n entryPoints: [entry],\n bundle: true,\n platform: 'browser',\n format: 'esm',\n target: 'es2022',\n outfile: path.join(outDir, `${appName}.browser.mjs`),\n keepNames: true,\n treeShaking: true,\n sourcemap: true,\n // Browser-safe: keep React and peer deps external (user's bundler handles them)\n external: [\n 'react', 'react-dom', 'react-router', 'react-router-dom',\n // Keep @frontmcp/* external — user installs them\n '@frontmcp/sdk', '@frontmcp/di', '@frontmcp/utils',\n '@frontmcp/auth', '@frontmcp/react',\n 'reflect-metadata',\n // Node.js-only — these should be tree-shaken by platform: 'browser'\n // but list explicitly to avoid accidental bundling\n 'better-sqlite3', 'fsevents', 'ioredis',\n ...Object.keys(pkg.peerDependencies || {}),\n ],\n // Resolve conditional imports to browser variants\n conditions: ['browser', 'import', 'default'],\n define: {\n 'process.env.NODE_ENV': '\"production\"',\n },\n });\n\n console.log(c('green', `\\n Browser build complete:`));\n console.log(c('gray', ` ESM: ${appName}.browser.mjs`));\n console.log(c('gray', ` Source map: ${appName}.browser.mjs.map`));\n}\n"]}
|
|
@@ -50,10 +50,10 @@ function generateCliEntry(options) {
|
|
|
50
50
|
generateLogoutCommand(appName),
|
|
51
51
|
generateSessionCommands(),
|
|
52
52
|
] : []),
|
|
53
|
-
generateServeCommand(serverBundleFilename),
|
|
53
|
+
generateServeCommand(serverBundleFilename, selfContained),
|
|
54
54
|
generateDoctorCommand(appName, options.nativeDeps),
|
|
55
55
|
generateInstallCommand(appName, options.nativeDeps, selfContained),
|
|
56
|
-
generateDaemonCommands(appName, serverBundleFilename),
|
|
56
|
+
generateDaemonCommands(appName, serverBundleFilename, selfContained),
|
|
57
57
|
generateFooter(),
|
|
58
58
|
];
|
|
59
59
|
return sections.filter(Boolean).join('\n\n');
|
|
@@ -81,7 +81,24 @@ function generateHeader(appName, appVersion, description, serverBundleFilename,
|
|
|
81
81
|
groupEntries.push(` 'Subscriptions': []`);
|
|
82
82
|
groupEntries.push(` 'System': []`);
|
|
83
83
|
return `'use strict';
|
|
84
|
-
|
|
84
|
+
${selfContained ? `
|
|
85
|
+
// SEA daemon mode: when spawned by 'daemon start', run the server directly
|
|
86
|
+
// using the inlined (bundled) server code — no external requires needed.
|
|
87
|
+
if (process.env.__FRONTMCP_DAEMON_MODE === '1') {
|
|
88
|
+
require('reflect-metadata');
|
|
89
|
+
var _dMod = require(${JSON.stringify('../' + serverBundleFilename)});
|
|
90
|
+
var _dSdk = require('@frontmcp/sdk');
|
|
91
|
+
var _FMI = _dSdk.FrontMcpInstance || _dSdk.default.FrontMcpInstance;
|
|
92
|
+
var _raw = _dMod.default || _dMod;
|
|
93
|
+
var _cfg = (typeof _raw === 'function' && typeof Reflect !== 'undefined' && Reflect.getMetadata)
|
|
94
|
+
? (Reflect.getMetadata('__frontmcp:config', _raw) || _raw) : _raw;
|
|
95
|
+
var _sp = process.env.FRONTMCP_DAEMON_SOCKET;
|
|
96
|
+
_FMI.runUnixSocket(Object.assign({}, _cfg, { socketPath: _sp }))
|
|
97
|
+
.then(function() { console.log('Daemon listening on ' + _sp); })
|
|
98
|
+
.catch(function(e) { console.error('Daemon failed:', e); process.exit(1); });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
` : ''}
|
|
85
102
|
var { Command, Option } = require('commander');
|
|
86
103
|
var path = require('path');
|
|
87
104
|
var fs = require('fs');
|
|
@@ -956,17 +973,30 @@ program
|
|
|
956
973
|
console.log('Credentials stored for session: ' + sessionName);
|
|
957
974
|
});`;
|
|
958
975
|
}
|
|
959
|
-
function generateServeCommand(serverBundleFilename) {
|
|
976
|
+
function generateServeCommand(serverBundleFilename, selfContained) {
|
|
977
|
+
// In self-contained/SEA mode, use a static relative require that esbuild can resolve at bundle time.
|
|
978
|
+
// In normal mode, use dynamic path.join for runtime resolution from disk.
|
|
979
|
+
const requireExpr = selfContained
|
|
980
|
+
? `require(${JSON.stringify('../' + serverBundleFilename)})`
|
|
981
|
+
: `require(path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)}))`;
|
|
960
982
|
return `program
|
|
961
983
|
.command('serve')
|
|
962
984
|
.description('Start the HTTP/SSE server')
|
|
963
985
|
.option('-p, --port <port>', 'Port number', function(v) { return parseInt(v, 10); })
|
|
964
986
|
.action(async function(opts) {
|
|
965
|
-
var mod =
|
|
987
|
+
var mod = ${requireExpr};
|
|
966
988
|
if (opts.port) process.env.PORT = String(opts.port);
|
|
967
|
-
//
|
|
968
|
-
if (typeof mod.start === 'function') await mod.start();
|
|
969
|
-
|
|
989
|
+
// If the bundle exports a start() function (@FrontMcp-decorated class auto-bootstraps), use it
|
|
990
|
+
if (typeof mod.start === 'function') { await mod.start(); return; }
|
|
991
|
+
if (typeof mod.default?.start === 'function') { await mod.default.start(); return; }
|
|
992
|
+
// Otherwise, bootstrap the plain config object via FrontMcpInstance
|
|
993
|
+
var raw = mod.default || mod;
|
|
994
|
+
var sdk = require('@frontmcp/sdk');
|
|
995
|
+
var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;
|
|
996
|
+
var config = (typeof raw === 'function' && typeof Reflect !== 'undefined' && Reflect.getMetadata)
|
|
997
|
+
? (Reflect.getMetadata('__frontmcp:config', raw) || raw) : raw;
|
|
998
|
+
if (opts.port) config = Object.assign({}, config, { http: Object.assign({}, config.http || {}, { port: opts.port }) });
|
|
999
|
+
await FrontMcpInstance.bootstrap(config);
|
|
970
1000
|
});`;
|
|
971
1001
|
}
|
|
972
1002
|
function generateDoctorCommand(appName, nativeDeps) {
|
|
@@ -1156,7 +1186,7 @@ program
|
|
|
1156
1186
|
console.log('Uninstalled ${appName}.');
|
|
1157
1187
|
});`;
|
|
1158
1188
|
}
|
|
1159
|
-
function generateDaemonCommands(appName, serverBundleFilename) {
|
|
1189
|
+
function generateDaemonCommands(appName, serverBundleFilename, selfContained) {
|
|
1160
1190
|
return `var daemonCmd = program.command('daemon').description('Daemon management');
|
|
1161
1191
|
|
|
1162
1192
|
daemonCmd
|
|
@@ -1196,7 +1226,13 @@ daemonCmd
|
|
|
1196
1226
|
var out = fs.openSync(logPath, 'a');
|
|
1197
1227
|
var err = fs.openSync(logPath, 'a');
|
|
1198
1228
|
|
|
1199
|
-
//
|
|
1229
|
+
${selfContained ? ` // SEA mode: spawn the binary itself in daemon mode — all code is inlined
|
|
1230
|
+
env.__FRONTMCP_DAEMON_MODE = '1';
|
|
1231
|
+
var child = spawn(process.execPath, [], {
|
|
1232
|
+
detached: true,
|
|
1233
|
+
stdio: ['ignore', out, err],
|
|
1234
|
+
env: env
|
|
1235
|
+
});` : ` // Start the daemon using runUnixSocket via a small wrapper script
|
|
1200
1236
|
// Always use absolute path for the server bundle (SCRIPT_DIR resolves to __dirname at runtime)
|
|
1201
1237
|
var serverBundlePath = pathMod.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});
|
|
1202
1238
|
var daemonScript = 'require("reflect-metadata");' +
|
|
@@ -1204,7 +1240,7 @@ daemonCmd
|
|
|
1204
1240
|
'var sdk = require("@frontmcp/sdk");' +
|
|
1205
1241
|
'var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;' +
|
|
1206
1242
|
'var raw = mod.default || mod;' +
|
|
1207
|
-
// If the export is a @FrontMcp-decorated class, extract config via Reflect metadata
|
|
1243
|
+
${'// If the export is a @FrontMcp-decorated class, extract config via Reflect metadata'}
|
|
1208
1244
|
'var config = (typeof raw === "function" && typeof Reflect !== "undefined" && Reflect.getMetadata) ' +
|
|
1209
1245
|
' ? (Reflect.getMetadata("__frontmcp:config", raw) || raw) : raw;' +
|
|
1210
1246
|
'FrontMcpInstance.runUnixSocket(Object.assign({}, config, { socketPath: ' + JSON.stringify(socketPath) + ' }))' +
|
|
@@ -1215,7 +1251,7 @@ daemonCmd
|
|
|
1215
1251
|
detached: true,
|
|
1216
1252
|
stdio: ['ignore', out, err],
|
|
1217
1253
|
env: env
|
|
1218
|
-
})
|
|
1254
|
+
});`}
|
|
1219
1255
|
|
|
1220
1256
|
fs.writeFileSync(pidPath, JSON.stringify({
|
|
1221
1257
|
pid: child.pid,
|
|
@@ -1295,7 +1331,11 @@ daemonCmd
|
|
|
1295
1331
|
});`;
|
|
1296
1332
|
}
|
|
1297
1333
|
function generateFooter() {
|
|
1298
|
-
return `program.
|
|
1334
|
+
return `program.on('command:*', function(args) {
|
|
1335
|
+
console.error('Unknown command: ' + args[0]);
|
|
1336
|
+
process.exitCode = 1;
|
|
1337
|
+
});
|
|
1338
|
+
program.parseAsync(process.argv).catch(function(err) {
|
|
1299
1339
|
console.error('Fatal:', err.message || err);
|
|
1300
1340
|
process.exit(1);
|
|
1301
1341
|
});`;
|