@frontmcp/uipack 1.11.2 → 1.12.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +4 -4
- package/README.md +20 -15
- package/adapters/code-highlight.d.ts +20 -0
- package/adapters/code-highlight.d.ts.map +1 -0
- package/adapters/index.d.ts +4 -2
- package/adapters/index.d.ts.map +1 -1
- package/adapters/index.js +36 -16
- package/adapters/markdown.d.ts +10 -2
- package/adapters/markdown.d.ts.map +1 -1
- package/adapters/mdx.d.ts +34 -0
- package/adapters/mdx.d.ts.map +1 -0
- package/adapters/project-require.d.ts +22 -0
- package/adapters/project-require.d.ts.map +1 -0
- package/adapters/render-options.d.ts +28 -0
- package/adapters/render-options.d.ts.map +1 -0
- package/adapters/response-builder.d.ts +9 -0
- package/adapters/response-builder.d.ts.map +1 -1
- package/adapters/server-react.d.ts +22 -0
- package/adapters/server-react.d.ts.map +1 -0
- package/adapters/serving-mode.d.ts +4 -1
- package/adapters/serving-mode.d.ts.map +1 -1
- package/adapters/template-renderer.d.ts +42 -2
- package/adapters/template-renderer.d.ts.map +1 -1
- package/component/index.js +25 -11
- package/component/loader.d.ts +5 -0
- package/component/loader.d.ts.map +1 -1
- package/component/renderer.d.ts.map +1 -1
- package/component/server-render.d.ts +21 -0
- package/component/server-render.d.ts.map +1 -0
- package/component/transpiler.d.ts +17 -13
- package/component/transpiler.d.ts.map +1 -1
- package/component/types.d.ts +7 -0
- package/component/types.d.ts.map +1 -1
- package/esm/adapters/index.mjs +36 -16
- package/esm/component/index.mjs +25 -11
- package/esm/index.mjs +71 -18
- package/esm/package.json +24 -3
- package/esm/shell/index.mjs +34 -1
- package/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js +72 -19
- package/package.json +24 -3
- package/resolver/cdn-registry.d.ts +1 -1
- package/resolver/cdn-registry.d.ts.map +1 -1
- package/resolver/esm-sh.resolver.d.ts +1 -1
- package/resolver/esm-sh.resolver.d.ts.map +1 -1
- package/resolver/import-map.d.ts +1 -1
- package/resolver/import-map.d.ts.map +1 -1
- package/resolver/import-rewriter.d.ts.map +1 -1
- package/shell/custom-shell-resolver.d.ts +1 -1
- package/shell/custom-shell-resolver.d.ts.map +1 -1
- package/shell/custom-shell-validator.d.ts +1 -1
- package/shell/custom-shell-validator.d.ts.map +1 -1
- package/shell/index.d.ts +2 -0
- package/shell/index.d.ts.map +1 -1
- package/shell/index.js +35 -2
- package/shell/sanitize-css.d.ts +18 -0
- package/shell/sanitize-css.d.ts.map +1 -0
- package/shell/sanitize-html.d.ts +28 -0
- package/shell/sanitize-html.d.ts.map +1 -0
- package/shell/url-widget-shell.d.ts +35 -0
- package/shell/url-widget-shell.d.ts.map +1 -0
- package/types/ui-config.d.ts +207 -198
- package/types/ui-config.d.ts.map +1 -1
- package/types/ui-runtime.d.ts +11 -12
- package/types/ui-runtime.d.ts.map +1 -1
- package/typings/cache/memory-cache.d.ts +1 -1
- package/typings/cache/memory-cache.d.ts.map +1 -1
- package/typings/type-fetcher.d.ts +2 -2
- package/typings/type-fetcher.d.ts.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/adapters/markdown.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/adapters/markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,sGAAsG;IACtG,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sGAAsG;IACtG,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACpE;AAwGD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,MAAM,CA4EpF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MDX templates: a string template compiled with `@mdx-js/mdx` and rendered on the server with
|
|
3
|
+
* React, with `ui.mdxComponents` as its components.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
import type { CodeHighlighter } from './code-highlight';
|
|
8
|
+
/** The compiled template: given the JSX runtime and the call's data, its module, whose default export is the content. */
|
|
9
|
+
type MdxModule = (runtime: unknown, input: unknown, output: unknown, helpers: unknown) => {
|
|
10
|
+
default: unknown;
|
|
11
|
+
};
|
|
12
|
+
/** Import the ES modules an MDX template compiles with, before it is compiled synchronously. */
|
|
13
|
+
export declare function preloadMdxCompiler(gfm?: boolean): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Compile an MDX template, once per source. Its expressions see `input`, `output` and `helpers`.
|
|
16
|
+
*
|
|
17
|
+
* @throws On an MDX syntax error, on an `import` (the template has no module to import from), or
|
|
18
|
+
* when `@mdx-js/mdx` (or `remark-gfm` for `gfm`) isn't installed
|
|
19
|
+
*/
|
|
20
|
+
export declare function compileMdxTemplate(source: string, gfm?: boolean): MdxModule;
|
|
21
|
+
export interface RenderMdxOptions {
|
|
22
|
+
input: unknown;
|
|
23
|
+
output: unknown;
|
|
24
|
+
helpers: unknown;
|
|
25
|
+
/** `ui.mdxComponents`: the components the template's tags name, and overrides of HTML elements. */
|
|
26
|
+
components?: Record<string, unknown>;
|
|
27
|
+
gfm?: boolean;
|
|
28
|
+
/** Highlights fenced code that names its language. */
|
|
29
|
+
highlighter?: CodeHighlighter;
|
|
30
|
+
}
|
|
31
|
+
/** Render an MDX template to static HTML on the server. */
|
|
32
|
+
export declare function renderMdxTemplate(source: string, options: RenderMdxOptions): string;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=mdx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdx.d.ts","sourceRoot":"","sources":["../../src/adapters/mdx.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQxD,yHAAyH;AACzH,KAAK,SAAS,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAK/G,gGAAgG;AAChG,wBAAsB,kBAAkB,CAAC,GAAG,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,UAAQ,GAAG,SAAS,CAczE;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sDAAsD;IACtD,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAUnF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional packages a rendering option needs, loaded from the server's own project when a tool uses
|
|
3
|
+
* the option.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Load a package from the server's project, or return the copy {@link preloadFromProject} imported.
|
|
9
|
+
*
|
|
10
|
+
* @param specifier - The package, or a module in it
|
|
11
|
+
* @param purpose - What needs it, named in the error when it isn't installed
|
|
12
|
+
*/
|
|
13
|
+
export declare function requireFromProject<T>(specifier: string, purpose: string): T;
|
|
14
|
+
/**
|
|
15
|
+
* Import an ES module package from the server's project, so {@link requireFromProject} returns it
|
|
16
|
+
* from then on. A `require` of an ES module graph fails under some loaders (tsx), an `import` does
|
|
17
|
+
* not; where `import` can't run (a test runner's sandbox), the package is required instead.
|
|
18
|
+
*/
|
|
19
|
+
export declare function preloadFromProject(specifier: string, purpose: string): Promise<void>;
|
|
20
|
+
/** The path of a file in a package of the server's project. */
|
|
21
|
+
export declare function resolveFromProject(specifier: string, purpose: string): string;
|
|
22
|
+
//# sourceMappingURL=project-require.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-require.d.ts","sourceRoot":"","sources":["../../src/adapters/project-require.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkDH;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAG3E;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW1F;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7E"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which rendering options a template can take.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import type { UIType } from '../types/ui-runtime';
|
|
7
|
+
import type { RenderToolTemplateOptions } from './template-renderer';
|
|
8
|
+
type RenderOptions = Pick<RenderToolTemplateOptions, 'contentSecurity' | 'markdown' | 'mdxComponents' | 'uiType' | 'hydrate'>;
|
|
9
|
+
/** `ui.uiType` when it names a renderer, `undefined` for `'auto'` or unset. */
|
|
10
|
+
export declare function forcedUiType(options: Pick<RenderOptions, 'uiType'>): Exclude<UIType, 'auto'> | undefined;
|
|
11
|
+
/** How the template renders: as `ui.uiType` says, as MDX for a string with `mdxComponents`, else as detected. */
|
|
12
|
+
export declare function resolveUiType(template: unknown, options: RenderOptions): UIType;
|
|
13
|
+
/**
|
|
14
|
+
* The rendering options set for a template that it cannot take, one sentence each. The server
|
|
15
|
+
* refuses to start a tool with any, and {@link renderToolTemplate} throws for them.
|
|
16
|
+
*/
|
|
17
|
+
export declare function describeRenderOptionProblems(template: unknown, options: RenderOptions): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Load what the options need to render the template, so a missing package or theme fails at
|
|
20
|
+
* startup instead of at the first call, and compile an MDX template. Call it before rendering an
|
|
21
|
+
* MDX template under a loader that can't `require` an ES module graph, such as tsx.
|
|
22
|
+
*
|
|
23
|
+
* @throws When an optional package the options need isn't installed, a theme doesn't exist, or an
|
|
24
|
+
* MDX template doesn't compile
|
|
25
|
+
*/
|
|
26
|
+
export declare function prepareRenderOptions(template: unknown, options: RenderOptions): Promise<void>;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=render-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-options.d.ts","sourceRoot":"","sources":["../../src/adapters/render-options.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAIlD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAGrE,KAAK,aAAa,GAAG,IAAI,CACvB,yBAAyB,EACzB,iBAAiB,GAAG,UAAU,GAAG,eAAe,GAAG,QAAQ,GAAG,SAAS,CACxE,CAAC;AAEF,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAExG;AAED,iHAAiH;AACjH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAI/E;AAsBD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,EAAE,CA8ChG;AAoBD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnG"}
|
|
@@ -48,4 +48,13 @@ export interface BuildToolResponseContentOptions {
|
|
|
48
48
|
* - `_meta`: Platform-specific HTML key with rendered content
|
|
49
49
|
*/
|
|
50
50
|
export declare function buildToolResponseContent(options: BuildToolResponseContentOptions): ToolResponseContent;
|
|
51
|
+
/**
|
|
52
|
+
* The second text block of a "dual payload" (`ui.htmlResponsePrefix`): the prefix, a colon, and the
|
|
53
|
+
* page in an `html` code fence, for a client that renders no widget but shows HTML from a code
|
|
54
|
+
* block. The fence is longer than any run of backticks in the page, so the page can't close it.
|
|
55
|
+
*
|
|
56
|
+
* @example buildHtmlResponseText('Here is the weather dashboard', html)
|
|
57
|
+
* // 'Here is the weather dashboard:\n\n```html\n<!DOCTYPE html>…\n```'
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildHtmlResponseText(prefix: string, html: string): string;
|
|
51
60
|
//# sourceMappingURL=response-builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-builder.d.ts","sourceRoot":"","sources":["../../src/adapters/response-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,0BAA0B;IAC1B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C,sBAAsB;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,wBAAwB;IACxB,YAAY,EAAE,mBAAmB,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,+BAA+B,GAAG,mBAAmB,CAkCtG"}
|
|
1
|
+
{"version":3,"file":"response-builder.d.ts","sourceRoot":"","sources":["../../src/adapters/response-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,0BAA0B;IAC1B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C,sBAAsB;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,wBAAwB;IACxB,YAAY,EAAE,mBAAmB,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,+BAA+B,GAAG,mBAAmB,CAkCtG;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI1E"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React on the server, for templates rendered there: an MDX template, and a React component with
|
|
3
|
+
* `ui.uiType: 'react'`.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
export interface ReactApi {
|
|
8
|
+
createElement(type: unknown, props?: Record<string, unknown> | null, ...children: unknown[]): unknown;
|
|
9
|
+
}
|
|
10
|
+
interface ReactDomServer {
|
|
11
|
+
renderToStaticMarkup(element: unknown): string;
|
|
12
|
+
}
|
|
13
|
+
/** React, its JSX runtime and react-dom/server, from the server's project, so templates and the renderer share one React. */
|
|
14
|
+
export declare function loadServerReact(purpose: string): {
|
|
15
|
+
react: ReactApi;
|
|
16
|
+
jsxRuntime: unknown;
|
|
17
|
+
server: ReactDomServer;
|
|
18
|
+
};
|
|
19
|
+
/** A React component reference rendered to static HTML on the server, with the widget props. */
|
|
20
|
+
export declare function renderComponentOnServer(component: unknown, input: unknown, output: unknown): string;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=server-react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-react.d.ts","sourceRoot":"","sources":["../../src/adapters/server-react.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,QAAQ;IACvB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;CACvG;AAED,UAAU,cAAc;IACtB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;CAChD;AAED,6HAA6H;AAC7H,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAMjH;AAED,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAGnG"}
|
|
@@ -37,7 +37,10 @@ export interface ServingModeResult {
|
|
|
37
37
|
* Resolve the effective serving mode based on platform capabilities.
|
|
38
38
|
*
|
|
39
39
|
* - Gemini: No UI support
|
|
40
|
-
* - OpenAI
|
|
40
|
+
* - OpenAI: UI supported; `'auto'` is `'static'`, so a result carries no page: the OpenAI Apps SDK
|
|
41
|
+
* renders the widget from its `ui://` resource and never reads `_meta['ui/html']`, and a widget's
|
|
42
|
+
* own call through `window.openai.callTool()` cannot be told from the model's
|
|
43
|
+
* - ext-apps, claude, generic-mcp, unknown: UI supported, `'auto'` is `'inline'`
|
|
41
44
|
* - OpenAI/ext-apps/generic-mcp/codex/unknown: include structuredContent
|
|
42
45
|
*/
|
|
43
46
|
export declare function resolveServingMode(options: ResolveServingModeOptions): ServingModeResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serving-mode.d.ts","sourceRoot":"","sources":["../../src/adapters/serving-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAC3B,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,aAAa,GACb,OAAO,GACP,QAAQ,GACR,aAAa,GACb,SAAS,GACT,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,4DAA4D;IAC5D,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,YAAY,EAAE,mBAAmB,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,UAAU,EAAE,OAAO,CAAC;IACpB,qEAAqE;IACrE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gEAAgE;IAChE,oBAAoB,EAAE,OAAO,CAAC;IAC9B,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"serving-mode.d.ts","sourceRoot":"","sources":["../../src/adapters/serving-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAC3B,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,aAAa,GACb,OAAO,GACP,QAAQ,GACR,aAAa,GACb,SAAS,GACT,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,4DAA4D;IAC5D,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,YAAY,EAAE,mBAAmB,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,UAAU,EAAE,OAAO,CAAC;IACpB,qEAAqE;IACrE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gEAAgE;IAChE,oBAAoB,EAAE,OAAO,CAAC;IAC9B,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,iBAAiB,CA+CxF"}
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { ImportResolver } from '../resolver/types';
|
|
9
9
|
import type { ShellConfig, WidgetSizing } from '../shell/types';
|
|
10
|
+
import type { UIContentSecurity } from '../types/ui-config';
|
|
11
|
+
import type { UIType } from '../types/ui-runtime';
|
|
10
12
|
/**
|
|
11
13
|
* Options for rendering a tool template.
|
|
12
14
|
*/
|
|
@@ -57,6 +59,43 @@ export interface RenderToolTemplateOptions {
|
|
|
57
59
|
logger?: {
|
|
58
60
|
warn: (message: string) => void;
|
|
59
61
|
};
|
|
62
|
+
/**
|
|
63
|
+
* `ui.contentSecurity`: when set, the markup built on the server from the template (an HTML,
|
|
64
|
+
* Markdown or MDX string, a template function's result, a component rendered with
|
|
65
|
+
* `uiType: 'react'`) is sanitized with {@link sanitizeHtml}. Unset, the markup is used as written.
|
|
66
|
+
*/
|
|
67
|
+
contentSecurity?: UIContentSecurity;
|
|
68
|
+
/**
|
|
69
|
+
* `ui.runtimeOptions.markdown`, for a Markdown or MDX template: `gfm` adds GitHub-flavored Markdown
|
|
70
|
+
* (tables, task lists, strikethrough, links for bare URLs), and `highlightTheme` highlights fenced
|
|
71
|
+
* code that names its language with highlight.js and puts that theme's stylesheet in the page.
|
|
72
|
+
*/
|
|
73
|
+
markdown?: MarkdownRenderOptions;
|
|
74
|
+
/**
|
|
75
|
+
* `ui.mdxComponents`: a string template is MDX, compiled with `@mdx-js/mdx` and rendered on the
|
|
76
|
+
* server with React. Its tags name these components, and its expressions read `input`, `output`
|
|
77
|
+
* and `helpers`.
|
|
78
|
+
*/
|
|
79
|
+
mdxComponents?: Record<string, unknown>;
|
|
80
|
+
/**
|
|
81
|
+
* `ui.uiType`: the renderer, instead of the one detected from the template. `'html'` uses a string
|
|
82
|
+
* as written and calls a function as an HTML builder; `'markdown'` converts a string, or a
|
|
83
|
+
* function's string result, from Markdown; `'mdx'` renders a string as MDX; `'react'` renders a
|
|
84
|
+
* component reference on the server, or bundles a `{ file }` widget. `'auto'` (or unset) detects.
|
|
85
|
+
*/
|
|
86
|
+
uiType?: UIType;
|
|
87
|
+
/**
|
|
88
|
+
* `ui.hydrate` (or `ui.runtimeOptions.hydrate`): a `{ file }` `.tsx`/`.jsx` widget is rendered on
|
|
89
|
+
* the server into the page, and the page hydrates it instead of rendering it from scratch.
|
|
90
|
+
*/
|
|
91
|
+
hydrate?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/** `ui.runtimeOptions.markdown`. */
|
|
94
|
+
export interface MarkdownRenderOptions {
|
|
95
|
+
/** GitHub-flavored Markdown. */
|
|
96
|
+
gfm?: boolean;
|
|
97
|
+
/** A highlight.js theme, such as `'github'` or `'github-dark'`. */
|
|
98
|
+
highlightTheme?: string;
|
|
60
99
|
}
|
|
61
100
|
/**
|
|
62
101
|
* Result of rendering a tool template.
|
|
@@ -90,8 +129,9 @@ export declare function warnIfComponentReference(toolName: string, template: unk
|
|
|
90
129
|
* - HTML template builder function `(ctx) => string | TrustedHtml`
|
|
91
130
|
* - Static HTML/MDX string
|
|
92
131
|
*
|
|
93
|
-
* React function references (`template: MyComponent`)
|
|
94
|
-
*
|
|
132
|
+
* React function references (`template: MyComponent`) can't be bundled for the page: with
|
|
133
|
+
* `uiType: 'react'` they render on the server to static HTML; otherwise use
|
|
134
|
+
* `template: { file: './my-component.tsx' }`.
|
|
95
135
|
*/
|
|
96
136
|
export declare function renderToolTemplate(options: RenderToolTemplateOptions): RenderToolTemplateResult;
|
|
97
137
|
//# sourceMappingURL=template-renderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-renderer.d.ts","sourceRoot":"","sources":["../../src/adapters/template-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"template-renderer.d.ts","sourceRoot":"","sources":["../../src/adapters/template-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAKxD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAYlD;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,QAAQ,EAAE,OAAO,CAAC;IAClB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAChC;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,8FAA8F;IAC9F,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;IACzC;;;OAGG;IACH,GAAG,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAChE;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,yEAAyE;IACzE,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IAC7C;;;;OAIG;IACH,eAAe,CAAC,EAAE,iBAAiB,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,oCAAoC;AACpC,MAAM,WAAW,qBAAqB;IACpC,gCAAgC;IAChC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAuHD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,EACjB,MAAM,GAAE;IAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAAY,GACpD,OAAO,CAIT;AAeD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB,CAwJ/F"}
|
package/component/index.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
|
-
"use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var component_exports={};__export(component_exports,{FRONTMCP_META_KEY:()=>FRONTMCP_META_KEY,bundleFileSource:()=>bundleFileSource,extractDefaultExportName:()=>extractDefaultExportName,generateMountScript:()=>generateMountScript,isFileSource:()=>isFileSource,isFunctionSource:()=>isFunctionSource,isImportSource:()=>isImportSource,isNpmSource:()=>isNpmSource,renderComponent:()=>renderComponent,resolveUISource:()=>resolveUISource,transpileReactSource:()=>transpileReactSource});module.exports=__toCommonJS(component_exports);function isNpmSource(source){return typeof source==="object"&&source!==null&&"npm"in source}function isFileSource(source){return typeof source==="object"&&source!==null&&"file"in source}function isImportSource(source){return typeof source==="object"&&source!==null&&"import"in source}function isFunctionSource(source){return typeof source==="function"}var FRONTMCP_META_KEY="__frontmcp_meta";var DEFAULT_CDN_REGISTRY={react:{packageName:"react",defaultVersion:"19.2.4",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/react/19.2.4/umd/react.production.min.js",global:"React",crossorigin:"anonymous"},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/react@19.2.4/umd/react.production.min.js",global:"React",crossorigin:"anonymous"},unpkg:{url:"https://unpkg.com/react@19.2.4/umd/react.production.min.js",global:"React",crossorigin:"anonymous"},"esm.sh":{url:"https://esm.sh/react@19.2.4",esm:true,crossorigin:"anonymous"}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"A JavaScript library for building user interfaces",homepage:"https://react.dev",license:"MIT"}},"react-dom":{packageName:"react-dom",defaultVersion:"19.2.4",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/react-dom/19.2.4/umd/react-dom.production.min.js",global:"ReactDOM",crossorigin:"anonymous",peerDependencies:["react"]},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/react-dom@19.2.4/umd/react-dom.production.min.js",global:"ReactDOM",crossorigin:"anonymous",peerDependencies:["react"]},unpkg:{url:"https://unpkg.com/react-dom@19.2.4/umd/react-dom.production.min.js",global:"ReactDOM",crossorigin:"anonymous",peerDependencies:["react"]},"esm.sh":{url:"https://esm.sh/react-dom@19.2.4",esm:true,crossorigin:"anonymous",peerDependencies:["react"]}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"React package for working with the DOM",homepage:"https://react.dev",license:"MIT"}},"chart.js":{packageName:"chart.js",defaultVersion:"4.5.1",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.1/chart.umd.min.js",global:"Chart",crossorigin:"anonymous"},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js",global:"Chart",crossorigin:"anonymous"},unpkg:{url:"https://unpkg.com/chart.js@4.5.1/dist/chart.umd.min.js",global:"Chart",crossorigin:"anonymous"}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"Simple yet flexible JavaScript charting library",homepage:"https://www.chartjs.org",license:"MIT"}},d3:{packageName:"d3",defaultVersion:"7.9.0",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js",integrity:"sha512-vc58qvvBdrDR4etbxMdlTt4GBQk1qjvyORR2nrsPsFPyrs+/u5c3+1Ct6upOgdZoIl7eq6k3a1UPDSNAQi/32A==",global:"d3",crossorigin:"anonymous"},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js",global:"d3",crossorigin:"anonymous"},unpkg:{url:"https://unpkg.com/d3@7.9.0/dist/d3.min.js",global:"d3",crossorigin:"anonymous"}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"Data-Driven Documents",homepage:"https://d3js.org",license:"ISC"}},lodash:{packageName:"lodash",defaultVersion:"4.17.21",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js",integrity:"sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==",global:"_",crossorigin:"anonymous"},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js",global:"_",crossorigin:"anonymous"},unpkg:{url:"https://unpkg.com/lodash@4.17.21/lodash.min.js",global:"_",crossorigin:"anonymous"}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"A modern JavaScript utility library",homepage:"https://lodash.com",license:"MIT"}}};function lookupPackage(packageName,registry=DEFAULT_CDN_REGISTRY){return registry[packageName]}var IMPORT_PATTERNS={named:/import\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g,default:/import\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,namespace:/import\s*\*\s*as\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,sideEffect:/import\s*['"]([^'"]+)['"]/g,dynamic:/(?:await\s+)?import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,defaultAndNamed:/import\s+(\w+)\s*,\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g,defaultAndNamespace:/import\s+(\w+)\s*,\s*\*\s*as\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,reExport:/export\s*\{[^}]+\}\s*from\s*['"]([^'"]+)['"]/g,reExportAll:/export\s*\*\s*from\s*['"]([^'"]+)['"]/g};function parseNamedImports(namedString){return namedString.split(",").map(s=>s.trim()).filter(s=>s.length>0).map(s=>{const asMatch=s.match(/^(\w+)\s+as\s+\w+$/);return asMatch?asMatch[1]:s})}function isRelativeImport(specifier){return specifier.startsWith("./")||specifier.startsWith("../")||specifier.startsWith("/")}function isExternalImport(specifier){return!isRelativeImport(specifier)&&!specifier.startsWith("#")}function getPackageName(specifier){if(specifier.startsWith("@")){const parts=specifier.split("/");if(parts.length>=2){return`${parts[0]}/${parts[1]}`}return specifier}const firstSlash=specifier.indexOf("/");return firstSlash===-1?specifier:specifier.slice(0,firstSlash)}function getLineNumber(source,index){let line=1;for(let i=0;i<index&&i<source.length;i++){if(source[i]==="\n"){line++}}return line}function getColumnNumber(source,index){let column=0;for(let i=index-1;i>=0&&source[i]!=="\n";i--){column++}return column}function parseImports(source){const imports=[];const seenStatements=new Set;const addImport=imp=>{const key=`${imp.type}:${imp.specifier}:${imp.statement}`;if(!seenStatements.has(key)){seenStatements.add(key);imports.push(imp)}};let match;const defaultAndNamedRegex=new RegExp(IMPORT_PATTERNS.defaultAndNamed.source,"g");while((match=defaultAndNamedRegex.exec(source))!==null){const[statement,defaultName,namedString,specifier]=match;addImport({statement,specifier,type:"default",defaultImport:defaultName,namedImports:parseNamedImports(namedString),line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const defaultAndNamespaceRegex=new RegExp(IMPORT_PATTERNS.defaultAndNamespace.source,"g");while((match=defaultAndNamespaceRegex.exec(source))!==null){const[statement,defaultName,namespaceName,specifier]=match;addImport({statement,specifier,type:"default",defaultImport:defaultName,namespaceImport:namespaceName,line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const namedRegex=new RegExp(IMPORT_PATTERNS.named.source,"g");while((match=namedRegex.exec(source))!==null){const[statement,namedString,specifier]=match;addImport({statement,specifier,type:"named",namedImports:parseNamedImports(namedString),line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const defaultRegex=new RegExp(IMPORT_PATTERNS.default.source,"g");while((match=defaultRegex.exec(source))!==null){const[statement,defaultName,specifier]=match;const afterMatch=source.slice(match.index+match[0].length-specifier.length-2);if(afterMatch.startsWith(","))continue;addImport({statement,specifier,type:"default",defaultImport:defaultName,line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const namespaceRegex=new RegExp(IMPORT_PATTERNS.namespace.source,"g");while((match=namespaceRegex.exec(source))!==null){const[statement,namespaceName,specifier]=match;addImport({statement,specifier,type:"namespace",namespaceImport:namespaceName,line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const sideEffectRegex=new RegExp(IMPORT_PATTERNS.sideEffect.source,"g");while((match=sideEffectRegex.exec(source))!==null){const[statement,specifier]=match;const beforeMatch=source.slice(Math.max(0,match.index-50),match.index);if(beforeMatch.includes("from"))continue;addImport({statement,specifier,type:"side-effect",line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const dynamicRegex=new RegExp(IMPORT_PATTERNS.dynamic.source,"g");while((match=dynamicRegex.exec(source))!==null){const[statement,specifier]=match;addImport({statement,specifier,type:"dynamic",line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const reExportRegex=new RegExp(IMPORT_PATTERNS.reExport.source,"g");while((match=reExportRegex.exec(source))!==null){const[statement,specifier]=match;addImport({statement,specifier,type:"named",line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const reExportAllRegex=new RegExp(IMPORT_PATTERNS.reExportAll.source,"g");while((match=reExportAllRegex.exec(source))!==null){const[statement,specifier]=match;addImport({statement,specifier,type:"namespace",line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const externalImports=imports.filter(imp=>isExternalImport(imp.specifier));const relativeImports=imports.filter(imp=>isRelativeImport(imp.specifier));const externalPackages=[...new Set(externalImports.map(imp=>getPackageName(imp.specifier)))];return{imports,externalImports,relativeImports,externalPackages}}var DEFAULT_FALLBACK_CDN="https://esm.sh";function createEsmShResolver(options={}){const{fallbackCdnBase=DEFAULT_FALLBACK_CDN,registry=DEFAULT_CDN_REGISTRY,providerOrder=["esm.sh","cloudflare","jsdelivr","unpkg"]}=options;return{resolve(specifier,_context){if(specifier.startsWith("./")||specifier.startsWith("../")||specifier.startsWith("/")){return null}if(specifier.startsWith("node:")||specifier.startsWith("#")){return null}const pkgName=getPackageName(specifier);const entry=lookupPackage(pkgName,registry);if(entry){for(const provider of providerOrder){const config=entry.providers[provider];if(config?.url){const subpath=specifier.slice(pkgName.length);if(subpath&&config.url.includes("esm.sh/")){return{value:config.url+subpath,type:"url",integrity:config.integrity}}if(subpath){return{value:`${fallbackCdnBase}/${specifier}`,type:"url"}}if(config.global&&!config.esm){return{value:config.url,type:"url",integrity:config.integrity}}return{value:config.url,type:"url",integrity:config.integrity}}}}return{value:`${fallbackCdnBase}/${specifier}`,type:"url"}}}}var SCRIPT_UNSAFE_CHARACTERS=/[<>&\u2028\u2029]/g;function toUnicodeEscape(character){return`\\u${character.charCodeAt(0).toString(16).padStart(4,"0")}`}function safeJsonForScript(value){if(value===void 0){return"null"}try{const jsonString=JSON.stringify(value,(_key,val)=>{if(typeof val==="bigint"){return val.toString()}return val});if(jsonString===void 0){return"null"}return jsonString.replace(SCRIPT_UNSAFE_CHARACTERS,toUnicodeEscape)}catch{return'{"error":"Value could not be serialized"}'}}function isFrontmcpUiResolvable(...candidatePaths){try{const nodeFs=require("fs");const nodePath=require("path");const ORG="@frontmcp";const PKG="ui";for(const candidate of candidatePaths){let dir=candidate;while(true){const pkgJson=nodePath.join(dir,"node_modules",ORG,PKG,"package.json");if(nodeFs.existsSync(pkgJson))return true;const parent=nodePath.dirname(dir);if(parent===dir)break;dir=parent}}return false}catch{return false}}function loadEsbuild(filename){try{return require("esbuild")}catch(err){if(!isMissingEsbuild(err))throw err;const subject=filename?`FileSource widget "${filename}"`:"A FileSource widget";throw new Error(`${subject} needs esbuild, which is not installed. @frontmcp/uipack loads esbuild on demand to bundle FileSource widgets (.tsx/.jsx) when the tool is called, so it must be installed where the server runs: \`npm install esbuild\` (in "dependencies", not "devDependencies"). Projects created with \`frontmcp create\` already get it through the \`frontmcp\` package.`,{cause:err})}}function isMissingEsbuild(err){if(!(err instanceof Error))return false;return err.code==="MODULE_NOT_FOUND"&&/Cannot find module ['"]esbuild['"]/.test(err.message)}function transpileReactSource(source,filename){const esbuild=loadEsbuild(filename);const loader=filename?.endsWith(".tsx")?"tsx":"jsx";const result=esbuild.transformSync(source,{loader,jsx:"transform",jsxFactory:"React.createElement",jsxFragment:"React.Fragment",format:"esm",target:"es2020",define:{"process.env.NODE_ENV":'"production"'}});return result.code}function bundleFileSource(source,filename,resolveDir,componentName,options={}){if(!isFrontmcpUiResolvable(resolveDir,process.cwd())){throw new Error(`FileSource widget "${filename}" requires the @frontmcp/ui package, which provides the React bridge mount that's injected at bundle time. Install it (e.g. \`npm install @frontmcp/ui\` or \`yarn add @frontmcp/ui\`) and try again.`)}const esbuild=loadEsbuild(filename);const mountCode=`
|
|
1
|
+
"use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var component_exports={};__export(component_exports,{FRONTMCP_META_KEY:()=>FRONTMCP_META_KEY,bundleFileSource:()=>bundleFileSource,extractDefaultExportName:()=>extractDefaultExportName,generateMountScript:()=>generateMountScript,isFileSource:()=>isFileSource,isFunctionSource:()=>isFunctionSource,isImportSource:()=>isImportSource,isNpmSource:()=>isNpmSource,renderComponent:()=>renderComponent,resolveUISource:()=>resolveUISource,transpileReactSource:()=>transpileReactSource});module.exports=__toCommonJS(component_exports);function isNpmSource(source){return typeof source==="object"&&source!==null&&"npm"in source}function isFileSource(source){return typeof source==="object"&&source!==null&&"file"in source}function isImportSource(source){return typeof source==="object"&&source!==null&&"import"in source}function isFunctionSource(source){return typeof source==="function"}var FRONTMCP_META_KEY="__frontmcp_meta";var DEFAULT_CDN_REGISTRY={react:{packageName:"react",defaultVersion:"19.2.4",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/react/19.2.4/umd/react.production.min.js",global:"React",crossorigin:"anonymous"},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/react@19.2.4/umd/react.production.min.js",global:"React",crossorigin:"anonymous"},unpkg:{url:"https://unpkg.com/react@19.2.4/umd/react.production.min.js",global:"React",crossorigin:"anonymous"},"esm.sh":{url:"https://esm.sh/react@19.2.4",esm:true,crossorigin:"anonymous"}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"A JavaScript library for building user interfaces",homepage:"https://react.dev",license:"MIT"}},"react-dom":{packageName:"react-dom",defaultVersion:"19.2.4",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/react-dom/19.2.4/umd/react-dom.production.min.js",global:"ReactDOM",crossorigin:"anonymous",peerDependencies:["react"]},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/react-dom@19.2.4/umd/react-dom.production.min.js",global:"ReactDOM",crossorigin:"anonymous",peerDependencies:["react"]},unpkg:{url:"https://unpkg.com/react-dom@19.2.4/umd/react-dom.production.min.js",global:"ReactDOM",crossorigin:"anonymous",peerDependencies:["react"]},"esm.sh":{url:"https://esm.sh/react-dom@19.2.4",esm:true,crossorigin:"anonymous",peerDependencies:["react"]}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"React package for working with the DOM",homepage:"https://react.dev",license:"MIT"}},"chart.js":{packageName:"chart.js",defaultVersion:"4.5.1",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.1/chart.umd.min.js",global:"Chart",crossorigin:"anonymous"},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js",global:"Chart",crossorigin:"anonymous"},unpkg:{url:"https://unpkg.com/chart.js@4.5.1/dist/chart.umd.min.js",global:"Chart",crossorigin:"anonymous"}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"Simple yet flexible JavaScript charting library",homepage:"https://www.chartjs.org",license:"MIT"}},d3:{packageName:"d3",defaultVersion:"7.9.0",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js",integrity:"sha512-vc58qvvBdrDR4etbxMdlTt4GBQk1qjvyORR2nrsPsFPyrs+/u5c3+1Ct6upOgdZoIl7eq6k3a1UPDSNAQi/32A==",global:"d3",crossorigin:"anonymous"},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js",global:"d3",crossorigin:"anonymous"},unpkg:{url:"https://unpkg.com/d3@7.9.0/dist/d3.min.js",global:"d3",crossorigin:"anonymous"}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"Data-Driven Documents",homepage:"https://d3js.org",license:"ISC"}},lodash:{packageName:"lodash",defaultVersion:"4.17.21",providers:{cloudflare:{url:"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js",integrity:"sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==",global:"_",crossorigin:"anonymous"},jsdelivr:{url:"https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js",global:"_",crossorigin:"anonymous"},unpkg:{url:"https://unpkg.com/lodash@4.17.21/lodash.min.js",global:"_",crossorigin:"anonymous"}},preferredProviders:["esm.sh","cloudflare","jsdelivr","unpkg"],metadata:{description:"A modern JavaScript utility library",homepage:"https://lodash.com",license:"MIT"}}};function lookupPackage(packageName,registry=DEFAULT_CDN_REGISTRY){return registry[packageName]}var IMPORT_PATTERNS={named:/import\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g,default:/import\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,namespace:/import\s*\*\s*as\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,sideEffect:/import\s*['"]([^'"]+)['"]/g,dynamic:/(?:await\s+)?import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,defaultAndNamed:/import\s+(\w+)\s*,\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g,defaultAndNamespace:/import\s+(\w+)\s*,\s*\*\s*as\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,reExport:/export\s*\{[^}]+\}\s*from\s*['"]([^'"]+)['"]/g,reExportAll:/export\s*\*\s*from\s*['"]([^'"]+)['"]/g};function parseNamedImports(namedString){return namedString.split(",").map(s=>s.trim()).filter(s=>s.length>0).map(s=>{const asMatch=s.match(/^(\w+)\s+as\s+\w+$/);return asMatch?asMatch[1]:s})}function isRelativeImport(specifier){return specifier.startsWith("./")||specifier.startsWith("../")||specifier.startsWith("/")}function isExternalImport(specifier){return!isRelativeImport(specifier)&&!specifier.startsWith("#")}function getPackageName(specifier){if(specifier.startsWith("@")){const parts=specifier.split("/");if(parts.length>=2){return`${parts[0]}/${parts[1]}`}return specifier}const firstSlash=specifier.indexOf("/");return firstSlash===-1?specifier:specifier.slice(0,firstSlash)}function getLineNumber(source,index){let line=1;for(let i=0;i<index&&i<source.length;i++){if(source[i]==="\n"){line++}}return line}function getColumnNumber(source,index){let column=0;for(let i=index-1;i>=0&&source[i]!=="\n";i--){column++}return column}function parseImports(source){const imports=[];const seenStatements=new Set;const addImport=imp=>{const key=`${imp.type}:${imp.specifier}:${imp.statement}`;if(!seenStatements.has(key)){seenStatements.add(key);imports.push(imp)}};let match;const defaultAndNamedRegex=new RegExp(IMPORT_PATTERNS.defaultAndNamed.source,"g");while((match=defaultAndNamedRegex.exec(source))!==null){const[statement,defaultName,namedString,specifier]=match;addImport({statement,specifier,type:"default",defaultImport:defaultName,namedImports:parseNamedImports(namedString),line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const defaultAndNamespaceRegex=new RegExp(IMPORT_PATTERNS.defaultAndNamespace.source,"g");while((match=defaultAndNamespaceRegex.exec(source))!==null){const[statement,defaultName,namespaceName,specifier]=match;addImport({statement,specifier,type:"default",defaultImport:defaultName,namespaceImport:namespaceName,line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const namedRegex=new RegExp(IMPORT_PATTERNS.named.source,"g");while((match=namedRegex.exec(source))!==null){const[statement,namedString,specifier]=match;addImport({statement,specifier,type:"named",namedImports:parseNamedImports(namedString),line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const defaultRegex=new RegExp(IMPORT_PATTERNS.default.source,"g");while((match=defaultRegex.exec(source))!==null){const[statement,defaultName,specifier]=match;const afterMatch=source.slice(match.index+match[0].length-specifier.length-2);if(afterMatch.startsWith(","))continue;addImport({statement,specifier,type:"default",defaultImport:defaultName,line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const namespaceRegex=new RegExp(IMPORT_PATTERNS.namespace.source,"g");while((match=namespaceRegex.exec(source))!==null){const[statement,namespaceName,specifier]=match;addImport({statement,specifier,type:"namespace",namespaceImport:namespaceName,line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const sideEffectRegex=new RegExp(IMPORT_PATTERNS.sideEffect.source,"g");while((match=sideEffectRegex.exec(source))!==null){const[statement,specifier]=match;const beforeMatch=source.slice(Math.max(0,match.index-50),match.index);if(beforeMatch.includes("from"))continue;addImport({statement,specifier,type:"side-effect",line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const dynamicRegex=new RegExp(IMPORT_PATTERNS.dynamic.source,"g");while((match=dynamicRegex.exec(source))!==null){const[statement,specifier]=match;addImport({statement,specifier,type:"dynamic",line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const reExportRegex=new RegExp(IMPORT_PATTERNS.reExport.source,"g");while((match=reExportRegex.exec(source))!==null){const[statement,specifier]=match;addImport({statement,specifier,type:"named",line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const reExportAllRegex=new RegExp(IMPORT_PATTERNS.reExportAll.source,"g");while((match=reExportAllRegex.exec(source))!==null){const[statement,specifier]=match;addImport({statement,specifier,type:"namespace",line:getLineNumber(source,match.index),column:getColumnNumber(source,match.index)})}const externalImports=imports.filter(imp=>isExternalImport(imp.specifier));const relativeImports=imports.filter(imp=>isRelativeImport(imp.specifier));const externalPackages=[...new Set(externalImports.map(imp=>getPackageName(imp.specifier)))];return{imports,externalImports,relativeImports,externalPackages}}var DEFAULT_FALLBACK_CDN="https://esm.sh";function createEsmShResolver(options={}){const{fallbackCdnBase=DEFAULT_FALLBACK_CDN,registry=DEFAULT_CDN_REGISTRY,providerOrder=["esm.sh","cloudflare","jsdelivr","unpkg"]}=options;return{resolve(specifier,_context){if(specifier.startsWith("./")||specifier.startsWith("../")||specifier.startsWith("/")){return null}if(specifier.startsWith("node:")||specifier.startsWith("#")){return null}const pkgName=getPackageName(specifier);const entry=lookupPackage(pkgName,registry);if(entry){for(const provider of providerOrder){const config=entry.providers[provider];if(config?.url){const subpath=specifier.slice(pkgName.length);if(subpath&&config.url.includes("esm.sh/")){return{value:config.url+subpath,type:"url",integrity:config.integrity}}if(subpath){return{value:`${fallbackCdnBase}/${specifier}`,type:"url"}}if(config.global&&!config.esm){return{value:config.url,type:"url",integrity:config.integrity}}return{value:config.url,type:"url",integrity:config.integrity}}}}return{value:`${fallbackCdnBase}/${specifier}`,type:"url"}}}}var SCRIPT_UNSAFE_CHARACTERS=/[<>&\u2028\u2029]/g;function toUnicodeEscape(character){return`\\u${character.charCodeAt(0).toString(16).padStart(4,"0")}`}function safeJsonForScript(value){if(value===void 0){return"null"}try{const jsonString=JSON.stringify(value,(_key,val)=>{if(typeof val==="bigint"){return val.toString()}return val});if(jsonString===void 0){return"null"}return jsonString.replace(SCRIPT_UNSAFE_CHARACTERS,toUnicodeEscape)}catch{return'{"error":"Value could not be serialized"}'}}function isFrontmcpUiResolvable(...candidatePaths){try{const nodeFs=require("fs");const nodePath=require("path");const ORG="@frontmcp";const PKG="ui";for(const candidate of candidatePaths){let dir=candidate;while(true){const pkgJson=nodePath.join(dir,"node_modules",ORG,PKG,"package.json");if(nodeFs.existsSync(pkgJson))return true;const parent=nodePath.dirname(dir);if(parent===dir)break;dir=parent}}return false}catch{return false}}function loadEsbuild(filename){try{return require("esbuild")}catch(err){if(!isMissingEsbuild(err))throw err;const subject=filename?`FileSource widget "${filename}"`:"A FileSource widget";throw new Error(`${subject} needs esbuild, which is not installed. @frontmcp/uipack loads esbuild on demand to bundle FileSource widgets (.tsx/.jsx) when the tool is called, so it must be installed where the server runs: \`npm install esbuild\` (in "dependencies", not "devDependencies"). Projects created with \`frontmcp create\` already get it through the \`frontmcp\` package.`,{cause:err})}}function isMissingEsbuild(err){if(!(err instanceof Error))return false;return err.code==="MODULE_NOT_FOUND"&&/Cannot find module ['"]esbuild['"]/.test(err.message)}function transpileReactSource(source,filename){const esbuild=loadEsbuild(filename);const loader=filename?.endsWith(".tsx")?"tsx":"jsx";const result=esbuild.transformSync(source,{loader,jsx:"transform",jsxFactory:"React.createElement",jsxFragment:"React.Fragment",format:"esm",target:"es2020",define:{"process.env.NODE_ENV":'"production"'}});return result.code}var FIRST_RENDER=` // Render immediately (component shows loading state until data arrives)
|
|
2
|
+
__render(undefined);
|
|
3
|
+
`;var INJECTED_DATA_RENDER=` // 2. Try injected data globals (null: the page carries no call's data, e.g. compiled at startup)
|
|
4
|
+
if (__hasData(window.__mcpToolOutput) && window.__mcpToolOutput !== null) { __render(window.__mcpToolOutput); }
|
|
5
|
+
`;function hydrateFirstRender(componentName){return` // Hydrate the markup rendered on the server, with the data the page carries
|
|
6
|
+
var __initial = window.__mcpToolOutput !== null ? window.__mcpToolOutput : undefined;
|
|
7
|
+
__reactRoot = hydrateRoot(__root,
|
|
8
|
+
__h(McpBridgeProvider, null,
|
|
9
|
+
__h(${componentName}, { output: __hasData(__initial) ? __initial : null, input: window.__mcpToolInput, loading: !__hasData(__initial) })
|
|
10
|
+
)
|
|
11
|
+
);
|
|
12
|
+
`}function bundleFileSource(source,filename,resolveDir,componentName,options={}){if(!isFrontmcpUiResolvable(resolveDir,process.cwd())){throw new Error(`FileSource widget "${filename}" requires the @frontmcp/ui package, which provides the React bridge mount that's injected at bundle time. Install it (e.g. \`npm install @frontmcp/ui\` or \`yarn add @frontmcp/ui\`) and try again.`)}const esbuild=loadEsbuild(filename);const hydrate=options.hydrate===true;const mountCode=`
|
|
2
13
|
// --- Auto-generated mount ---
|
|
3
14
|
import { createElement as __h } from 'react';
|
|
4
|
-
import { createRoot } from 'react-dom/client';
|
|
15
|
+
import { ${hydrate?"hydrateRoot":"createRoot"} } from 'react-dom/client';
|
|
5
16
|
import { McpBridgeProvider } from '@frontmcp/ui/react';
|
|
6
17
|
var __root = document.getElementById('root');
|
|
7
18
|
if (__root) {
|
|
8
|
-
var __reactRoot = createRoot(__root);
|
|
19
|
+
var __reactRoot${hydrate?"":" = createRoot(__root)"};
|
|
9
20
|
function __hasData(v) { return v !== undefined; }
|
|
10
21
|
function __render(output) {
|
|
11
22
|
__reactRoot.render(
|
|
@@ -14,9 +25,7 @@ if (__root) {
|
|
|
14
25
|
)
|
|
15
26
|
);
|
|
16
27
|
}
|
|
17
|
-
//
|
|
18
|
-
__render(undefined);
|
|
19
|
-
// 1. Try OpenAI SDK (toolOutput set synchronously or after load)
|
|
28
|
+
${hydrate?hydrateFirstRender(componentName):FIRST_RENDER} // 1. Try OpenAI SDK (toolOutput set synchronously or after load)
|
|
20
29
|
if (typeof window !== 'undefined') {
|
|
21
30
|
if (!window.openai) window.openai = {};
|
|
22
31
|
var __cur = window.openai.toolOutput;
|
|
@@ -27,9 +36,7 @@ if (__root) {
|
|
|
27
36
|
configurable: true, enumerable: true
|
|
28
37
|
});
|
|
29
38
|
}
|
|
30
|
-
//
|
|
31
|
-
if (__hasData(window.__mcpToolOutput) && window.__mcpToolOutput !== null) { __render(window.__mcpToolOutput); }
|
|
32
|
-
// 3. Listen for bridge tool-result (ext-apps / MCP Inspector)
|
|
39
|
+
${hydrate?"":INJECTED_DATA_RENDER} // 3. Listen for bridge tool-result (ext-apps / MCP Inspector)
|
|
33
40
|
var __bridge = window.FrontMcpBridge;
|
|
34
41
|
if (__bridge && typeof __bridge.onToolResult === 'function') {
|
|
35
42
|
__bridge.onToolResult(function(data) { __render(data); });
|
|
@@ -40,7 +47,14 @@ if (__root) {
|
|
|
40
47
|
if (d) __render(d.structuredContent !== undefined ? d.structuredContent : d.content !== undefined ? d.content : d);
|
|
41
48
|
});
|
|
42
49
|
}
|
|
43
|
-
}`;const loader={".tsx":"tsx",".jsx":"jsx"};const stdinLoader=filename.endsWith(".tsx")?"tsx":"jsx";const alias={};try{const nodePath=require("path");const nodeFs=require("fs");const candidates=[nodePath.join(process.cwd(),"node_modules","@frontmcp","ui","dist","esm"),nodePath.join(resolveDir,"node_modules","@frontmcp","ui","dist","esm")];for(const uiEsmBase of candidates){if(!nodeFs.existsSync(uiEsmBase))continue;const subpaths=["components","react","theme","bridge","runtime"];for(const sub of subpaths){const mjs=nodePath.join(uiEsmBase,sub,"index.mjs");if(nodeFs.existsSync(mjs))alias[`@frontmcp/ui/${sub}`]=mjs}if(Object.keys(alias).length>0)break}}catch{}try{const result=esbuild.buildSync({stdin:{contents:source+"\n"+mountCode,loader:stdinLoader,resolveDir,sourcefile:filename},bundle:true,write:false,format:"esm",target:"es2020",jsx:"automatic",external:options.bundleReact?[]:["react","react-dom","react/jsx-runtime","react/jsx-dev-runtime"],alias,define:{"process.env.NODE_ENV":'"production"'},platform:"browser",treeShaking:true,logLevel:"warning",loader});return{code:result.outputFiles[0].text}}catch(err){const message=err instanceof Error?err.message:String(err);throw new Error(`Failed to bundle FileSource "${filename}": ${message}. If the error mentions @frontmcp/ui or @frontmcp/uipack, ensure both packages are installed in the consuming project.`,{cause:err})}}function
|
|
50
|
+
}`;const loader={".tsx":"tsx",".jsx":"jsx"};const stdinLoader=filename.endsWith(".tsx")?"tsx":"jsx";const alias={};try{const nodePath=require("path");const nodeFs=require("fs");const candidates=[nodePath.join(process.cwd(),"node_modules","@frontmcp","ui","dist","esm"),nodePath.join(resolveDir,"node_modules","@frontmcp","ui","dist","esm")];for(const uiEsmBase of candidates){if(!nodeFs.existsSync(uiEsmBase))continue;const subpaths=["components","react","theme","bridge","runtime"];for(const sub of subpaths){const mjs=nodePath.join(uiEsmBase,sub,"index.mjs");if(nodeFs.existsSync(mjs))alias[`@frontmcp/ui/${sub}`]=mjs}if(Object.keys(alias).length>0)break}}catch{}try{const result=esbuild.buildSync({stdin:{contents:source+"\n"+mountCode,loader:stdinLoader,resolveDir,sourcefile:filename},bundle:true,write:false,format:"esm",target:"es2020",jsx:"automatic",external:options.bundleReact?[]:["react","react-dom","react/jsx-runtime","react/jsx-dev-runtime"],alias,define:{"process.env.NODE_ENV":'"production"'},platform:"browser",treeShaking:true,logLevel:"warning",loader});return{code:result.outputFiles[0].text}}catch(err){const message=err instanceof Error?err.message:String(err);throw new Error(`Failed to bundle FileSource "${filename}": ${message}. If the error mentions @frontmcp/ui or @frontmcp/uipack, ensure both packages are installed in the consuming project.`,{cause:err})}}function bundleFileSourceForServer(filePath,exportName){const path=require("path");const resolveDir=path.dirname(filePath);if(!isFrontmcpUiResolvable(resolveDir,process.cwd())){throw new Error(`FileSource widget "${filePath}" requires the @frontmcp/ui package, whose McpBridgeProvider it renders in. Install it (e.g. \`npm install @frontmcp/ui\`) and try again.`)}const esbuild=loadEsbuild(filePath);const component=JSON.stringify(exportName??"default");const entry=`import * as __widget from ${JSON.stringify(`./${path.basename(filePath)}`)};
|
|
51
|
+
import { createElement } from 'react';
|
|
52
|
+
import { renderToString } from 'react-dom/server';
|
|
53
|
+
import { McpBridgeProvider } from '@frontmcp/ui/react';
|
|
54
|
+
var Component = __widget[${component}] ?? __widget.default;
|
|
55
|
+
export function render(props) {
|
|
56
|
+
return renderToString(createElement(McpBridgeProvider, null, createElement(Component, props)));
|
|
57
|
+
}`;try{const result=esbuild.buildSync({stdin:{contents:entry,loader:"jsx",resolveDir,sourcefile:"widget-server-entry.jsx"},bundle:true,write:false,format:"cjs",platform:"node",target:"node20",jsx:"automatic",external:["react","react-dom","react/*","react-dom/*"],define:{"process.env.NODE_ENV":'"production"'},logLevel:"silent",loader:{".tsx":"tsx",".jsx":"jsx"}});return{code:result.outputFiles[0].text}}catch(err){const message=err instanceof Error?err.message:String(err);throw new Error(`Failed to bundle FileSource "${filePath}" for the server: ${message}`,{cause:err})}}function extractDefaultExportName(code){let match=code.match(/export\s+default\s+(?:function|class)\s+(\w+)/);if(match)return match[1];match=code.match(/export\s+default\s+(\w+)\s*;/);if(match)return match[1];return null}function widgetProps(input,output){const data=output===void 0||output===null?void 0:output;return{input:input??null,output:data??null,loading:data===void 0}}var renderers=new Map;function renderFileSourceOnServer(filePath,source,exportName,props){const key=`${filePath}#${exportName??"default"}`;let renderer=renderers.get(key);if(renderer?.source!==source){renderer={source,render:loadServerBundle(filePath,exportName)};renderers.set(key,renderer)}return renderer.render(props)}function loadServerBundle(filePath,exportName){const{code}=bundleFileSourceForServer(filePath,exportName);const{createRequire}=process.getBuiltinModule("node:module");const path=process.getBuiltinModule("node:path");const module2={exports:{}};const evaluate=new Function("require","module","exports","__filename","__dirname",code);evaluate(createRequire(filePath),module2,module2.exports,filePath,path.dirname(filePath));const{render}=module2.exports;if(typeof render!=="function")throw new Error(`The server bundle of FileSource "${filePath}" has no render()`);return render}var DEFAULT_META={mcpAware:false,renderer:"auto"};function resolveUISource(source,options){if(options?.inlineReact&&options?.transformOnly){throw new Error("resolveUISource: `inlineReact` and `transformOnly` are mutually exclusive \u2014 set at most one.")}const resolver=options?.resolver??createEsmShResolver();if(isNpmSource(source)){return resolveNpmSource(source,resolver)}if(isImportSource(source)){return resolveImportSource(source)}if(isFileSource(source)){return resolveFileSource(source,{inlineReact:options?.inlineReact,transformOnly:options?.transformOnly,hydrate:options?.hydrate,input:options?.input,output:options?.output})}if(isFunctionSource(source)){return resolveFunctionSource(source,options?.input,options?.output)}throw new Error("Unknown UISource type")}function resolveNpmSource(source,resolver){const specifier=source.version?`${source.npm}@${source.version}`:source.npm;const pkgName=getPackageName(source.npm);const resolved=resolver.resolve(specifier);const url=resolved?.value??`https://esm.sh/${specifier}`;const peerDeps=[];if(pkgName!=="react"&&pkgName!=="react-dom"){peerDeps.push("react","react-dom")}return{mode:"module",url,exportName:source.exportName??"default",meta:{...DEFAULT_META,renderer:"react"},peerDependencies:peerDeps}}function resolveImportSource(source){return{mode:"module",url:source.import,exportName:source.exportName??"default",meta:{...DEFAULT_META},peerDependencies:[]}}var BUILD_DIR_SEGMENTS=new Set(["dist","build","out"]);function missingWidgetError(filePath,cause){const sourceWidget=findSourceWidget(filePath);const error=new Error(`FileSource widget not found (ENOENT): no file at "${filePath}". The widget source is read from this path when the tool is called, so it has to exist where the compiled tool runs \u2014 a path built from \`__dirname\` or \`import.meta.url\` points into the build output once the tool is compiled. tsc does not copy \`*.widget.tsx\` / \`*.widget.jsx\` files into its output; \`frontmcp build\` does, and any other build needs a step that copies them next to the compiled tool.`+(sourceWidget?` The source widget exists at "${sourceWidget}" \u2014 copy it to "${filePath}", or build with \`frontmcp build\`.`:""),{cause});error.code="ENOENT";error.path=filePath;return error}function findSourceWidget(filePath){const path=require("path");const fs=require("fs");const parts=filePath.split(path.sep);for(let i=parts.length-2;i>=0;i--){if(!BUILD_DIR_SEGMENTS.has(parts[i]))continue;const candidates=[[...parts.slice(0,i),"src",...parts.slice(i+1)]];if(parts.length-i>2)candidates.push([...parts.slice(0,i),"src",...parts.slice(i+2)]);candidates.push([...parts.slice(0,i),...parts.slice(i+1)]);for(const candidate of candidates){const candidatePath=candidate.join(path.sep);try{if(fs.existsSync(candidatePath))return candidatePath}catch{}}return void 0}return void 0}function resolveFileSource(source,options={}){const path=require("path");const ext=path.extname(source.file).toLowerCase();if(ext===".tsx"||ext===".jsx"){const fs=require("fs");const wasRelative=!path.isAbsolute(source.file);const filePath=wasRelative?path.resolve(process.cwd(),source.file):source.file;let rawSource;try{rawSource=fs.readFileSync(filePath,"utf-8")}catch(err){const isNotFound=err?.code==="ENOENT";if(isNotFound&&wasRelative){throw new Error(`FileSource widget "${source.file}" not found at "${filePath}". Relative paths are resolved against process.cwd() ("${process.cwd()}"), not the tool file's directory. To anchor the path to the tool file, pass an absolute path \u2014 e.g. \`{ file: fileURLToPath(new URL('./widget.tsx', import.meta.url)) }\` from \`node:url\` (see issue #444).`,{cause:err})}if(isNotFound)throw missingWidgetError(filePath,err);throw err}const componentName=source.exportName||extractDefaultExportName(rawSource)||"Component";if(options.transformOnly===true){const code=transpileReactSource(rawSource,path.basename(filePath));const parsed2=parseImports(code);return{mode:"module",code,imports:[...new Set(parsed2.externalImports.map(i=>i.specifier))],exportName:componentName,meta:{mcpAware:true,renderer:"react"},peerDependencies:source.peerDependencies||["react","react-dom"],bundled:false}}const hydrate=options.hydrate===true;const bundled=bundleFileSource(rawSource,source.file,path.dirname(filePath),componentName,{bundleReact:options.inlineReact===true,hydrate});const serverHtml=hydrate?renderFileSourceOnServer(filePath,rawSource,source.exportName,widgetProps(options.input,options.output)):void 0;const parsed=parseImports(bundled.code);return{mode:"module",code:bundled.code,imports:[...new Set(parsed.externalImports.map(i=>i.specifier))],exportName:componentName,meta:{mcpAware:true,renderer:"react"},peerDependencies:source.peerDependencies||["react","react-dom"],bundled:true,serverHtml}}if(source.inline){return{mode:"inline",html:`<!-- File source: ${source.file} (inline mode - content to be resolved at build time) -->`,exportName:"default",meta:{...DEFAULT_META,renderer:"html"},peerDependencies:[]}}return{mode:"module",url:source.file,exportName:"default",meta:{...DEFAULT_META},peerDependencies:[]}}function resolveFunctionSource(source,input,output){const html=source(input,output);return{mode:"inline",html,exportName:"default",meta:{mcpAware:false,renderer:"html"},peerDependencies:[]}}function generateMountScript(resolved,propsMapping){if(resolved.mode!=="module"||!resolved.url){return""}const componentImport=resolved.exportName==="default"?`import Component from '${resolved.url}';`:`import { ${resolved.exportName} as Component } from '${resolved.url}';`;if(resolved.meta.mcpAware){return`${componentImport}
|
|
44
58
|
import React from 'react';
|
|
45
59
|
import { createRoot } from 'react-dom/client';
|
|
46
60
|
createRoot(document.getElementById('root'))
|
|
@@ -1260,7 +1274,7 @@ ${headParts.map(p=>` ${p}`).join("\n")}
|
|
|
1260
1274
|
${content}
|
|
1261
1275
|
</body>
|
|
1262
1276
|
</html>`;return{html,hash:simpleHash(html),size:Buffer.byteLength(html,"utf-8")}}function buildCustomShell(content,customShell,ctx){let template;if(typeof customShell==="string"){const validation=validateShellTemplate(customShell);if(!validation.valid){throw new Error(`Custom shell template is missing required placeholder(s): ${validation.missingRequired.map(n=>`{{${n}}}`).join(", ")}`)}template=customShell}else{template=customShell.template}const cspTag=buildCSPMetaTag(ctx.csp);const dataScript=resolveDataInjectionScript({dataInjection:ctx.dataInjection,toolName:ctx.toolName,input:ctx.input,output:ctx.output,structuredContent:ctx.structuredContent,sizing:ctx.sizing,displayMode:ctx.displayMode});const sizingStyle=buildSizingStyleTag(ctx.sizing);const dataWithSizing=sizingStyle?`${dataScript}
|
|
1263
|
-
${sizingStyle}`:dataScript;let bridgeHtml="";if(ctx.includeBridge){const bridgeScript=generateBridgeIIFE({minify:true});bridgeHtml=`<script>${bridgeScript}</script>`}const html=applyShellTemplate(template,{csp:cspTag,data:dataWithSizing,bridge:bridgeHtml,content,title:ctx.title?escapeHtmlForTag(ctx.title):""});return{html,hash:simpleHash(html),size:Buffer.byteLength(html,"utf-8")}}function simpleHash(str){let hash=0;for(let i=0;i<str.length;i++){const char=str.charCodeAt(i);hash=(hash<<5)-hash+char|0}return Math.abs(hash).toString(16).padStart(8,"0")}function escapeHtmlForTag(str){return str.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}var DEFAULT_WIDGET_MOUNT={moduleSpecifier:"@frontmcp/ui/react",wrapperImportName:"McpBridgeProvider"};function renderComponent(config,shellConfig){const resolver=shellConfig.resolver??createEsmShResolver();const resolved=resolveUISource(config.source,{resolver,input:shellConfig.input,output:shellConfig.output,inlineReact:config.inlineReact===true,transformOnly:config.transformOnly===true});const mergedShellConfig={...shellConfig,withShell:config.withShell??shellConfig.withShell,includeBridge:config.includeBridge??shellConfig.includeBridge,customShell:config.customShell??shellConfig.customShell};if(resolved.mode==="inline"){return buildShell(resolved.html??"",mergedShellConfig)}const content=buildModuleContent(resolved,resolver,config.props,shellConfig.mount);return buildShell(content,mergedShellConfig)}function buildModuleContent(resolved,resolver,propsMapping,mount=DEFAULT_WIDGET_MOUNT){const parts=[];if(resolved.code&&resolved.bundled){const importEntries={};for(const spec of resolved.imports||[]){const depResolved=resolver.resolve(spec);if(depResolved){importEntries[spec]=depResolved}}if(Object.keys(importEntries).length>0){const importMap=createImportMapFromResolved(importEntries);parts.push(generateImportMapScriptTag(importMap))}parts.push(
|
|
1277
|
+
${sizingStyle}`:dataScript;let bridgeHtml="";if(ctx.includeBridge){const bridgeScript=generateBridgeIIFE({minify:true});bridgeHtml=`<script>${bridgeScript}</script>`}const html=applyShellTemplate(template,{csp:cspTag,data:dataWithSizing,bridge:bridgeHtml,content,title:ctx.title?escapeHtmlForTag(ctx.title):""});return{html,hash:simpleHash(html),size:Buffer.byteLength(html,"utf-8")}}function simpleHash(str){let hash=0;for(let i=0;i<str.length;i++){const char=str.charCodeAt(i);hash=(hash<<5)-hash+char|0}return Math.abs(hash).toString(16).padStart(8,"0")}function escapeHtmlForTag(str){return str.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}var DEFAULT_WIDGET_MOUNT={moduleSpecifier:"@frontmcp/ui/react",wrapperImportName:"McpBridgeProvider"};function renderComponent(config,shellConfig){const resolver=shellConfig.resolver??createEsmShResolver();const resolved=resolveUISource(config.source,{resolver,input:shellConfig.input,output:shellConfig.output,inlineReact:config.inlineReact===true,transformOnly:config.transformOnly===true,hydrate:config.hydrate===true});const mergedShellConfig={...shellConfig,withShell:config.withShell??shellConfig.withShell,includeBridge:config.includeBridge??shellConfig.includeBridge,customShell:config.customShell??shellConfig.customShell};if(resolved.mode==="inline"){return buildShell(resolved.html??"",mergedShellConfig)}const content=buildModuleContent(resolved,resolver,config.props,shellConfig.mount);return buildShell(content,mergedShellConfig)}function buildModuleContent(resolved,resolver,propsMapping,mount=DEFAULT_WIDGET_MOUNT){const parts=[];if(resolved.code&&resolved.bundled){const importEntries={};for(const spec of resolved.imports||[]){const depResolved=resolver.resolve(spec);if(depResolved){importEntries[spec]=depResolved}}if(Object.keys(importEntries).length>0){const importMap=createImportMapFromResolved(importEntries);parts.push(generateImportMapScriptTag(importMap))}parts.push(`<div id="root">${resolved.serverHtml??""}</div>`);parts.push(`<script type="module">
|
|
1264
1278
|
${resolved.code}
|
|
1265
1279
|
</script>`)}else if(resolved.code){const importEntries={};const allSpecifiers=new Set([...resolved.imports||[],"react-dom/client",mount.moduleSpecifier,"react/jsx-runtime","react/jsx-dev-runtime"]);if(mount===DEFAULT_WIDGET_MOUNT){allSpecifiers.add("react-dom/server");allSpecifiers.add("react-dom/static")}const coreDeps=new Set(["react","react-dom","react-dom/client","react/jsx-runtime","react/jsx-dev-runtime","react-dom/server","react-dom/static"]);for(const spec of allSpecifiers){const depResolved=resolver.resolve(spec);if(depResolved){if(!coreDeps.has(spec)&&depResolved.value?.includes("esm.sh")){importEntries[spec]={...depResolved,value:addExternalParam(depResolved.value,["react","react-dom"])}}else{importEntries[spec]=depResolved}}}if(importEntries["react-dom"]&&!importEntries["react-dom/client"]){const rdc=resolver.resolve("react-dom/client");if(rdc)importEntries["react-dom/client"]=rdc}if(Object.keys(importEntries).length>0){const importMap=createImportMapFromResolved(importEntries);parts.push(generateImportMapScriptTag(importMap))}const mountNodeId=mount.mountNodeId??"root";parts.push(`<div id="${mountNodeId}">${mount.mountNodeInnerHtml??""}</div>`);const mountCode=generateInlineMountCode(resolved.exportName,mount);parts.push(`<script type="module">
|
|
1266
1280
|
${resolved.code}
|
package/component/loader.d.ts
CHANGED
|
@@ -40,6 +40,11 @@ export declare function resolveUISource(source: UISource, options?: {
|
|
|
40
40
|
* exclusive with {@link inlineReact} (bundling). Default `false`.
|
|
41
41
|
*/
|
|
42
42
|
transformOnly?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* `ui.hydrate`: a FileSource `.tsx`/`.jsx` widget is also rendered on the server with the call's
|
|
45
|
+
* data (`serverHtml`), and its mount hydrates that markup.
|
|
46
|
+
*/
|
|
47
|
+
hydrate?: boolean;
|
|
43
48
|
}): ResolvedComponent;
|
|
44
49
|
/**
|
|
45
50
|
* Generate a mount script for module-based components.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/component/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/component/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,mBAAmB,CAAC;AAIxE,OAAO,EACL,iBAAiB,EAUjB,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACd,MAAM,SAAS,CAAC;AAOjB;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,QAAQ,EAChB,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GACA,iBAAiB,CAiCnB;AAkND;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CA6B9G;AAmBD;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/component/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAE,KAAK,WAAW,EAA6B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE/F,OAAO,EAA0B,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAehE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/component/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAE,KAAK,WAAW,EAA6B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE/F,OAAO,EAA0B,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAehE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,GAAG,WAAW,CA8BvF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server rendering of a FileSource `.tsx`/`.jsx` widget, for `ui.hydrate`.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
/** The props a widget component renders with, as the page's mount gives them: `null` output and `loading` until the call's data. */
|
|
7
|
+
export declare function widgetProps(input: unknown, output: unknown): {
|
|
8
|
+
input: unknown;
|
|
9
|
+
output: unknown;
|
|
10
|
+
loading: boolean;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The widget rendered to HTML on the server with `props`, as the page's mount renders it, so the
|
|
14
|
+
* page can hydrate it. The server bundle is built once per widget source.
|
|
15
|
+
*
|
|
16
|
+
* @param filePath - The widget's absolute path
|
|
17
|
+
* @param source - The widget's source, which keys the bundle
|
|
18
|
+
* @param exportName - The component's export, `default` when unset
|
|
19
|
+
*/
|
|
20
|
+
export declare function renderFileSourceOnServer(filePath: string, source: string, exportName: string | undefined, props: Record<string, unknown>): string;
|
|
21
|
+
//# sourceMappingURL=server-render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-render.d.ts","sourceRoot":"","sources":["../../src/component/server-render.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,oIAAoI;AACpI,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAGlH;AAID;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CAQR"}
|
|
@@ -18,19 +18,6 @@
|
|
|
18
18
|
* @returns Transpiled JavaScript source code (ESM format)
|
|
19
19
|
*/
|
|
20
20
|
export declare function transpileReactSource(source: string, filename?: string): string;
|
|
21
|
-
/**
|
|
22
|
-
* Bundle a FileSource .tsx/.jsx file with esbuild's buildSync.
|
|
23
|
-
*
|
|
24
|
-
* Resolves workspace dependencies (e.g. @frontmcp/ui) from local node_modules,
|
|
25
|
-
* inlines all non-React deps, and appends mount code so the output is a
|
|
26
|
-
* self-contained ES module that only depends on react/react-dom externally.
|
|
27
|
-
*
|
|
28
|
-
* @param source - Raw TSX/JSX source code
|
|
29
|
-
* @param filename - Filename hint for loader detection (e.g. 'widget.tsx')
|
|
30
|
-
* @param resolveDir - Directory for resolving bare imports (typically dirname of the source file)
|
|
31
|
-
* @param componentName - Name of the component to mount (extracted from source)
|
|
32
|
-
* @returns Bundled JavaScript source code
|
|
33
|
-
*/
|
|
34
21
|
/**
|
|
35
22
|
* Options for `bundleFileSource`.
|
|
36
23
|
*/
|
|
@@ -45,10 +32,27 @@ export interface BundleFileSourceOptions {
|
|
|
45
32
|
* behavior where React is loaded from the CDN via an import map.
|
|
46
33
|
*/
|
|
47
34
|
bundleReact?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* `ui.hydrate`: the page's `#root` holds the widget rendered on the server, so the mount hydrates
|
|
37
|
+
* it with `hydrateRoot` and the data the page carries, instead of rendering into an empty root.
|
|
38
|
+
*/
|
|
39
|
+
hydrate?: boolean;
|
|
48
40
|
}
|
|
49
41
|
export declare function bundleFileSource(source: string, filename: string, resolveDir: string, componentName: string, options?: BundleFileSourceOptions): {
|
|
50
42
|
code: string;
|
|
51
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Bundle a FileSource `.tsx`/`.jsx` widget for the server, for `ui.hydrate`: one CommonJS module
|
|
46
|
+
* whose `render(props)` returns the widget rendered to HTML inside the `McpBridgeProvider` the page
|
|
47
|
+
* mounts it in. Its packages are bundled, as in the page's bundle; React is left to the widget's
|
|
48
|
+
* project, so the widget and react-dom/server share one copy.
|
|
49
|
+
*
|
|
50
|
+
* @param filePath - The widget's absolute path
|
|
51
|
+
* @param exportName - The component's export, `default` when unset
|
|
52
|
+
*/
|
|
53
|
+
export declare function bundleFileSourceForServer(filePath: string, exportName: string | undefined): {
|
|
54
|
+
code: string;
|
|
55
|
+
};
|
|
52
56
|
/**
|
|
53
57
|
* Extract the default export name from transpiled source code.
|
|
54
58
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transpiler.d.ts","sourceRoot":"","sources":["../../src/component/transpiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyCH;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAiB9E;
|
|
1
|
+
{"version":3,"file":"transpiler.d.ts","sourceRoot":"","sources":["../../src/component/transpiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyCH;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAiB9E;AAmCD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,uBAA4B,GACpC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CA2HlB;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAuC5G;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUpE"}
|
package/component/types.d.ts
CHANGED
|
@@ -65,6 +65,11 @@ export interface UIConfig<In = unknown, Out = unknown> {
|
|
|
65
65
|
* exclusive with {@link inlineReact}. Default `false`.
|
|
66
66
|
*/
|
|
67
67
|
transformOnly?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* `ui.hydrate`: a FileSource `.tsx`/`.jsx` widget is rendered on the server into `#root` too, and
|
|
70
|
+
* the page hydrates it. Default `false`.
|
|
71
|
+
*/
|
|
72
|
+
hydrate?: boolean;
|
|
68
73
|
}
|
|
69
74
|
/** Auto-detected or declared metadata on a component module */
|
|
70
75
|
export interface ComponentMeta {
|
|
@@ -89,6 +94,8 @@ export interface ResolvedComponent {
|
|
|
89
94
|
code?: string;
|
|
90
95
|
/** External import specifiers found in the transpiled code */
|
|
91
96
|
imports?: string[];
|
|
97
|
+
/** The widget rendered on the server, for the page to hydrate (`hydrate`) */
|
|
98
|
+
serverHtml?: string;
|
|
92
99
|
/** Export name for the component (default: 'default') */
|
|
93
100
|
exportName: string;
|
|
94
101
|
/** Detected metadata */
|
package/component/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/component/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,wDAAwD;AACxD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,8DAA8D;AAC9D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,gCAAgC;AAChC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uCAAuC;AACvC,MAAM,MAAM,cAAc,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,KAAK,MAAM,CAAC;AAE7F,mCAAmC;AACnC,MAAM,MAAM,QAAQ,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAIpH,wBAAgB,WAAW,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,IAAI,SAAS,CAEjE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,IAAI,UAAU,CAEnE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,IAAI,YAAY,CAEvE;AAED,wBAAgB,gBAAgB,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,EAC1D,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,GACxB,MAAM,IAAI,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAEnC;AAID,sCAAsC;AACtC,MAAM,WAAW,QAAQ,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO;IACnD,yCAAyC;IACzC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC1B,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,oCAAoC;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6BAA6B;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,6BAA6B,EAAE,qBAAqB,GAAG,MAAM,CAAC;IACnF;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/component/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,wDAAwD;AACxD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,8DAA8D;AAC9D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,gCAAgC;AAChC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uCAAuC;AACvC,MAAM,MAAM,cAAc,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,KAAK,MAAM,CAAC;AAE7F,mCAAmC;AACnC,MAAM,MAAM,QAAQ,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAIpH,wBAAgB,WAAW,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,IAAI,SAAS,CAEjE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,IAAI,UAAU,CAEnE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,IAAI,YAAY,CAEvE;AAED,wBAAgB,gBAAgB,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,EAC1D,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,GACxB,MAAM,IAAI,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAEnC;AAID,sCAAsC;AACtC,MAAM,WAAW,QAAQ,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO;IACnD,yCAAyC;IACzC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC1B,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,oCAAoC;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6BAA6B;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,6BAA6B,EAAE,qBAAqB,GAAG,MAAM,CAAC;IACnF;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,QAAQ,EAAE,OAAO,CAAC;IAClB,yBAAyB;IACzB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAEnD,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,+CAA+C;IAC/C,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
|