frontmcp 1.5.2 → 1.5.3
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/exec/cli-runtime/cli-bundler.d.ts +1 -1
- package/src/commands/build/exec/cli-runtime/cli-bundler.js +5 -2
- package/src/commands/build/exec/cli-runtime/cli-bundler.js.map +1 -1
- package/src/commands/build/exec/esbuild-bundler.d.ts +11 -0
- package/src/commands/build/exec/esbuild-bundler.js +24 -1
- package/src/commands/build/exec/esbuild-bundler.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontmcp",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"description": "FrontMCP command line interface",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"homepage": "https://docs.agentfront.dev",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@clack/prompts": "^0.10.0",
|
|
32
|
-
"@frontmcp/lazy-zod": "1.5.
|
|
33
|
-
"@frontmcp/skills": "1.5.
|
|
34
|
-
"@frontmcp/utils": "1.5.
|
|
32
|
+
"@frontmcp/lazy-zod": "1.5.3",
|
|
33
|
+
"@frontmcp/skills": "1.5.3",
|
|
34
|
+
"@frontmcp/utils": "1.5.3",
|
|
35
35
|
"@rspack/core": "^1.7.6",
|
|
36
36
|
"commander": "^13.0.0",
|
|
37
37
|
"esbuild": "^0.27.3",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* esbuild configuration for the CLI bundle.
|
|
3
3
|
* Bundles the generated CLI entry point with commander.js inlined.
|
|
4
4
|
*/
|
|
5
|
-
import { FrontmcpExecConfig } from '../config';
|
|
5
|
+
import { type FrontmcpExecConfig } from '../config';
|
|
6
6
|
export interface CliBundleResult {
|
|
7
7
|
bundlePath: string;
|
|
8
8
|
bundleSize: number;
|
|
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.bundleCliWithEsbuild = bundleCliWithEsbuild;
|
|
8
8
|
const tslib_1 = require("tslib");
|
|
9
9
|
const path = tslib_1.__importStar(require("path"));
|
|
10
|
+
const esbuild_bundler_1 = require("../esbuild-bundler");
|
|
10
11
|
/**
|
|
11
12
|
* Bundle the generated CLI entry with esbuild.
|
|
12
13
|
* Commander.js and runtime modules are inlined; the server bundle is external
|
|
@@ -26,6 +27,9 @@ async function bundleCliWithEsbuild(cliEntryPath, outDir, config, options) {
|
|
|
26
27
|
// The server bundle is loaded via require() at runtime — keep external
|
|
27
28
|
// unless selfContained mode where everything is inlined for SEA
|
|
28
29
|
const serverBundleName = `${config.name}.bundle.js`;
|
|
30
|
+
// NOTE: `@enclave-vm/core` (Node-only full sandbox) is externalized via
|
|
31
|
+
// `enclaveCoreExactExternalPlugin()` rather than these lists, so its
|
|
32
|
+
// bundle-safe `@enclave-vm/core/worker` subpath still gets bundled.
|
|
29
33
|
const external = selfContained
|
|
30
34
|
? [
|
|
31
35
|
// Only true native addons and optional peer deps stay external in self-contained mode
|
|
@@ -34,7 +38,6 @@ async function bundleCliWithEsbuild(cliEntryPath, outDir, config, options) {
|
|
|
34
38
|
'esbuild',
|
|
35
39
|
'@vercel/kv',
|
|
36
40
|
'@frontmcp/storage-sqlite',
|
|
37
|
-
'@enclave-vm/core',
|
|
38
41
|
...(config.dependencies?.nativeAddons || []),
|
|
39
42
|
]
|
|
40
43
|
: [
|
|
@@ -45,7 +48,6 @@ async function bundleCliWithEsbuild(cliEntryPath, outDir, config, options) {
|
|
|
45
48
|
'esbuild',
|
|
46
49
|
'@vercel/kv',
|
|
47
50
|
'@frontmcp/storage-sqlite',
|
|
48
|
-
'@enclave-vm/core',
|
|
49
51
|
...(config.dependencies?.nativeAddons || []),
|
|
50
52
|
...(config.esbuild?.external || []),
|
|
51
53
|
];
|
|
@@ -57,6 +59,7 @@ async function bundleCliWithEsbuild(cliEntryPath, outDir, config, options) {
|
|
|
57
59
|
target: config.esbuild?.target || 'node22',
|
|
58
60
|
outfile: bundlePath,
|
|
59
61
|
external,
|
|
62
|
+
plugins: [(0, esbuild_bundler_1.enclaveCoreExactExternalPlugin)()],
|
|
60
63
|
keepNames: true,
|
|
61
64
|
treeShaking: true,
|
|
62
65
|
minify: config.esbuild?.minify ?? false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-bundler.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/cli-bundler.ts"],"names":[],"mappings":";AAAA;;;GAGG;;
|
|
1
|
+
{"version":3,"file":"cli-bundler.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/cli-bundler.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAgBH,oDA2EC;;AAzFD,mDAA6B;AAE7B,wDAAoE;AAOpE;;;;GAIG;AACI,KAAK,UAAU,oBAAoB,CACxC,YAAoB,EACpB,MAAc,EACd,MAA0B,EAC1B,OAAqC;IAErC,IAAI,OAAiC,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,GAAG,MAAM,CAAC,IAAI,gBAAgB,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,IAAI,KAAK,CAAC;IAEtD,uEAAuE;IACvE,gEAAgE;IAChE,MAAM,gBAAgB,GAAG,GAAG,MAAM,CAAC,IAAI,YAAY,CAAC;IAEpD,wEAAwE;IACxE,qEAAqE;IACrE,oEAAoE;IACpE,MAAM,QAAQ,GAAG,aAAa;QAC5B,CAAC,CAAC;YACE,sFAAsF;YACtF,gBAAgB;YAChB,UAAU;YACV,SAAS;YACT,YAAY;YACZ,0BAA0B;YAC1B,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,IAAI,EAAE,CAAC;SAC7C;QACH,CAAC,CAAC;YACE,KAAK,gBAAgB,EAAE;YACvB,eAAe;YACf,gBAAgB;YAChB,UAAU;YACV,SAAS;YACT,YAAY;YACZ,0BAA0B;YAC1B,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,IAAI,EAAE,CAAC;YAC5C,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC;SACpC,CAAC;IAEN,MAAM,OAAO,CAAC,KAAK,CAAC;QAClB,WAAW,EAAE,CAAC,YAAY,CAAC;QAC3B,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,MAAM;QAChB,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,QAAQ;QAC1C,OAAO,EAAE,UAAU;QACnB,QAAQ;QACR,OAAO,EAAE,CAAC,IAAA,gDAA8B,GAAE,CAAC;QAC3C,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK;QACvC,MAAM,EAAE;YACN,EAAE,EAAE,qBAAqB;SAC1B;QACD,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM;QAC9B,SAAS,EAAE,KAAK;QAChB,QAAQ,EAAE,SAAS;KACpB,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAErC,OAAO;QACL,UAAU;QACV,UAAU,EAAE,IAAI,CAAC,IAAI;KACtB,CAAC;AACJ,CAAC","sourcesContent":["/**\n * esbuild configuration for the CLI bundle.\n * Bundles the generated CLI entry point with commander.js inlined.\n */\n\nimport * as path from 'path';\nimport { type FrontmcpExecConfig } from '../config';\nimport { enclaveCoreExactExternalPlugin } from '../esbuild-bundler';\n\nexport interface CliBundleResult {\n bundlePath: string;\n bundleSize: number;\n}\n\n/**\n * Bundle the generated CLI entry with esbuild.\n * Commander.js and runtime modules are inlined; the server bundle is external\n * unless selfContained mode is enabled (for SEA builds).\n */\nexport async function bundleCliWithEsbuild(\n cliEntryPath: string,\n outDir: string,\n config: FrontmcpExecConfig,\n options?: { selfContained?: boolean },\n): Promise<CliBundleResult> {\n let esbuild: typeof import('esbuild');\n try {\n esbuild = require('esbuild');\n } catch {\n throw new Error(\n 'esbuild is required for CLI builds. Install it: npm install -D esbuild',\n );\n }\n\n const cliBundleName = `${config.name}-cli.bundle.js`;\n const bundlePath = path.join(outDir, cliBundleName);\n const selfContained = options?.selfContained ?? false;\n\n // The server bundle is loaded via require() at runtime — keep external\n // unless selfContained mode where everything is inlined for SEA\n const serverBundleName = `${config.name}.bundle.js`;\n\n // NOTE: `@enclave-vm/core` (Node-only full sandbox) is externalized via\n // `enclaveCoreExactExternalPlugin()` rather than these lists, so its\n // bundle-safe `@enclave-vm/core/worker` subpath still gets bundled.\n const external = selfContained\n ? [\n // Only true native addons and optional peer deps stay external in self-contained mode\n 'better-sqlite3',\n 'fsevents',\n 'esbuild',\n '@vercel/kv',\n '@frontmcp/storage-sqlite',\n ...(config.dependencies?.nativeAddons || []),\n ]\n : [\n `./${serverBundleName}`,\n '@frontmcp/sdk',\n 'better-sqlite3',\n 'fsevents',\n 'esbuild',\n '@vercel/kv',\n '@frontmcp/storage-sqlite',\n ...(config.dependencies?.nativeAddons || []),\n ...(config.esbuild?.external || []),\n ];\n\n await esbuild.build({\n entryPoints: [cliEntryPath],\n bundle: true,\n platform: 'node',\n format: 'cjs',\n target: config.esbuild?.target || 'node22',\n outfile: bundlePath,\n external,\n plugins: [enclaveCoreExactExternalPlugin()],\n keepNames: true,\n treeShaking: true,\n minify: config.esbuild?.minify ?? false,\n banner: {\n js: '#!/usr/bin/env node',\n },\n define: config.esbuild?.define,\n sourcemap: false,\n logLevel: 'warning',\n });\n\n const fs = require('fs');\n const stat = fs.statSync(bundlePath);\n\n return {\n bundlePath,\n bundleSize: stat.size,\n };\n}\n"]}
|
|
@@ -7,6 +7,17 @@ export interface BundleResult {
|
|
|
7
7
|
bundlePath: string;
|
|
8
8
|
bundleSize: number;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* esbuild plugin that externalizes the EXACT `@enclave-vm/core` package while
|
|
12
|
+
* leaving `@enclave-vm/core/worker` to be resolved and BUNDLED.
|
|
13
|
+
*
|
|
14
|
+
* `@enclave-vm/core` is the Node-only full sandbox (worker_threads / node:vm
|
|
15
|
+
* adapters) that cannot be bundled; its `/worker` subpath is a dependency-free
|
|
16
|
+
* interpreter that IS safe (and, on isolate/Worker deploys where node_modules is
|
|
17
|
+
* absent, REQUIRED) to bundle. Adding the bare package to esbuild's `external`
|
|
18
|
+
* array would externalize the subpath too — hence this exact-match plugin.
|
|
19
|
+
*/
|
|
20
|
+
export declare function enclaveCoreExactExternalPlugin(): import('esbuild').Plugin;
|
|
10
21
|
export declare function bundleWithEsbuild(entryPath: string, outDir: string, config: FrontmcpExecConfig, options?: {
|
|
11
22
|
selfContained?: boolean;
|
|
12
23
|
outputName?: string;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Produces a single CJS file for distribution.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.enclaveCoreExactExternalPlugin = enclaveCoreExactExternalPlugin;
|
|
7
8
|
exports.bundleWithEsbuild = bundleWithEsbuild;
|
|
8
9
|
exports.formatSize = formatSize;
|
|
9
10
|
const tslib_1 = require("tslib");
|
|
@@ -18,7 +19,10 @@ const DEFAULT_EXTERNALS = [
|
|
|
18
19
|
'esbuild',
|
|
19
20
|
'@vercel/kv',
|
|
20
21
|
'@frontmcp/storage-sqlite',
|
|
21
|
-
|
|
22
|
+
// NOTE: `@enclave-vm/core` (the Node-only full sandbox) is externalized via
|
|
23
|
+
// `enclaveCoreExactExternalPlugin()` instead of this list, so that its
|
|
24
|
+
// bundle-safe `@enclave-vm/core/worker` subpath still gets BUNDLED. Listing
|
|
25
|
+
// the bare package here would externalize the subpath too.
|
|
22
26
|
// Externalize FrontMCP packages for single-copy semantics
|
|
23
27
|
// (required for schema extraction — bundled copies create separate Symbol tokens)
|
|
24
28
|
'@frontmcp/sdk',
|
|
@@ -29,6 +33,24 @@ const DEFAULT_EXTERNALS = [
|
|
|
29
33
|
'@frontmcp/lazy-zod',
|
|
30
34
|
'reflect-metadata',
|
|
31
35
|
];
|
|
36
|
+
/**
|
|
37
|
+
* esbuild plugin that externalizes the EXACT `@enclave-vm/core` package while
|
|
38
|
+
* leaving `@enclave-vm/core/worker` to be resolved and BUNDLED.
|
|
39
|
+
*
|
|
40
|
+
* `@enclave-vm/core` is the Node-only full sandbox (worker_threads / node:vm
|
|
41
|
+
* adapters) that cannot be bundled; its `/worker` subpath is a dependency-free
|
|
42
|
+
* interpreter that IS safe (and, on isolate/Worker deploys where node_modules is
|
|
43
|
+
* absent, REQUIRED) to bundle. Adding the bare package to esbuild's `external`
|
|
44
|
+
* array would externalize the subpath too — hence this exact-match plugin.
|
|
45
|
+
*/
|
|
46
|
+
function enclaveCoreExactExternalPlugin() {
|
|
47
|
+
return {
|
|
48
|
+
name: 'frontmcp-enclave-core-exact-external',
|
|
49
|
+
setup(build) {
|
|
50
|
+
build.onResolve({ filter: /^@enclave-vm\/core$/ }, (args) => ({ path: args.path, external: true }));
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
32
54
|
async function bundleWithEsbuild(entryPath, outDir, config, options) {
|
|
33
55
|
// Lazy-load esbuild
|
|
34
56
|
let esbuild;
|
|
@@ -59,6 +81,7 @@ async function bundleWithEsbuild(entryPath, outDir, config, options) {
|
|
|
59
81
|
target: config.esbuild?.target || 'node22',
|
|
60
82
|
outfile: bundlePath,
|
|
61
83
|
external,
|
|
84
|
+
plugins: [enclaveCoreExactExternalPlugin()],
|
|
62
85
|
keepNames: true, // preserve class names for decorator metadata
|
|
63
86
|
treeShaking: true,
|
|
64
87
|
minify: config.esbuild?.minify ?? false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esbuild-bundler.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/esbuild-bundler.ts"],"names":[],"mappings":";AAAA;;;GAGG;;
|
|
1
|
+
{"version":3,"file":"esbuild-bundler.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/esbuild-bundler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * esbuild bundling for executable builds.\n * Produces a single CJS file for distribution.\n */\n\nimport * as path from 'path';\nimport { type FrontmcpExecConfig } from './config';\n\n// Default packages that must be kept external:\n// - native addons that cannot be bundled\n// - optional/lazy-required peer dependencies\nconst DEFAULT_EXTERNALS = [\n 'better-sqlite3',\n 'fsevents',\n '@swc/core',\n 'esbuild',\n '@vercel/kv',\n '@frontmcp/storage-sqlite',\n // NOTE: `@enclave-vm/core` (the Node-only full sandbox) is externalized via\n // `enclaveCoreExactExternalPlugin()` instead of this list, so that its\n // bundle-safe `@enclave-vm/core/worker` subpath still gets BUNDLED. Listing\n // the bare package here would externalize the subpath too.\n // Externalize FrontMCP packages for single-copy semantics\n // (required for schema extraction — bundled copies create separate Symbol tokens)\n '@frontmcp/sdk',\n '@frontmcp/di',\n '@frontmcp/utils',\n '@frontmcp/auth',\n '@frontmcp/adapters',\n '@frontmcp/lazy-zod',\n 'reflect-metadata',\n];\n\nexport interface BundleResult {\n bundlePath: string;\n bundleSize: number;\n}\n\n/**\n * esbuild plugin that externalizes the EXACT `@enclave-vm/core` package while\n * leaving `@enclave-vm/core/worker` to be resolved and BUNDLED.\n *\n * `@enclave-vm/core` is the Node-only full sandbox (worker_threads / node:vm\n * adapters) that cannot be bundled; its `/worker` subpath is a dependency-free\n * interpreter that IS safe (and, on isolate/Worker deploys where node_modules is\n * absent, REQUIRED) to bundle. Adding the bare package to esbuild's `external`\n * array would externalize the subpath too — hence this exact-match plugin.\n */\nexport function enclaveCoreExactExternalPlugin(): import('esbuild').Plugin {\n return {\n name: 'frontmcp-enclave-core-exact-external',\n setup(build) {\n build.onResolve({ filter: /^@enclave-vm\\/core$/ }, (args) => ({ path: args.path, external: true }));\n },\n };\n}\n\nexport async function bundleWithEsbuild(\n entryPath: string,\n outDir: string,\n config: FrontmcpExecConfig,\n options?: { selfContained?: boolean; outputName?: string },\n): Promise<BundleResult> {\n // Lazy-load esbuild\n let esbuild: typeof import('esbuild');\n try {\n\n esbuild = require('esbuild');\n } catch {\n throw new Error(\n 'esbuild is required for build targets. Install it: npm install -D esbuild',\n );\n }\n\n const bundleName = `${options?.outputName || config.name}.bundle.js`;\n const bundlePath = path.join(outDir, bundleName);\n\n // In self-contained mode (SEA), only keep true native addons external\n const external = options?.selfContained\n ? [\n ...DEFAULT_EXTERNALS,\n ...(config.dependencies?.nativeAddons || []),\n ]\n : [\n ...DEFAULT_EXTERNALS,\n ...(config.dependencies?.nativeAddons || []),\n ...(config.esbuild?.external || []),\n ];\n\n await esbuild.build({\n entryPoints: [entryPath],\n bundle: true,\n platform: 'node',\n format: 'cjs',\n target: config.esbuild?.target || 'node22',\n outfile: bundlePath,\n external,\n plugins: [enclaveCoreExactExternalPlugin()],\n keepNames: true, // preserve class names for decorator metadata\n treeShaking: true,\n minify: config.esbuild?.minify ?? false,\n define: config.esbuild?.define,\n sourcemap: false,\n metafile: true,\n logLevel: 'warning',\n });\n\n // Calculate bundle size\n const fs = require('fs');\n const stat = fs.statSync(bundlePath);\n\n return {\n bundlePath,\n bundleSize: stat.size,\n };\n}\n\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n"]}
|