@belgie/mcp 0.1.0 → 0.32.0
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/dist/index.js +16 -231
- package/dist/index.js.map +1 -1
- package/dist/vite.js +13 -13
- package/dist/vite.js.map +1 -1
- package/package.json +19 -43
- package/types/html.d.ts +10 -0
- package/types/index.d.ts +29 -0
- package/types/scan-widgets.d.ts +15 -0
- package/types/validate-widget.d.ts +1 -0
- package/types/vite.d.ts +5 -0
- package/README.md +0 -98
- package/dist/cli.d.ts +0 -10
- package/dist/cli.js +0 -119
- package/dist/cli.js.map +0 -1
- package/dist/codegen-DnMS1wg_.js +0 -688
- package/dist/codegen-DnMS1wg_.js.map +0 -1
- package/dist/codegen.d.ts +0 -11
- package/dist/codegen.js +0 -2
- package/dist/index.d.ts +0 -60
- package/dist/internal.d.ts +0 -12
- package/dist/internal.js +0 -37
- package/dist/internal.js.map +0 -1
- package/dist/tool-result-source-DTFIKHfH.js +0 -99
- package/dist/tool-result-source-DTFIKHfH.js.map +0 -1
- package/dist/tool-result-source-niHoRYxM.d.ts +0 -42
- package/dist/vite.d.ts +0 -9
package/dist/index.js
CHANGED
|
@@ -1,192 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { StrictMode, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
1
|
+
import { StrictMode, createContext, useContext, useEffect, useRef, useState } from "react";
|
|
3
2
|
import { createRoot } from "react-dom/client";
|
|
4
3
|
import { App } from "@modelcontextprotocol/ext-apps";
|
|
5
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
//#region src/app.ts
|
|
7
|
-
function sendMessage(...args) {
|
|
8
|
-
return getActiveWidget().sendMessage(...args);
|
|
9
|
-
}
|
|
10
|
-
function sendLog(...args) {
|
|
11
|
-
return getActiveWidget().sendLog(...args);
|
|
12
|
-
}
|
|
13
|
-
function updateModelContext(...args) {
|
|
14
|
-
return getActiveWidget().updateModelContext(...args);
|
|
15
|
-
}
|
|
16
|
-
function openLink(...args) {
|
|
17
|
-
return getActiveWidget().openLink(...args);
|
|
18
|
-
}
|
|
19
|
-
function downloadFile(...args) {
|
|
20
|
-
return getActiveWidget().downloadFile(...args);
|
|
21
|
-
}
|
|
22
|
-
function requestDisplayMode(...args) {
|
|
23
|
-
return getActiveWidget().requestDisplayMode(...args);
|
|
24
|
-
}
|
|
25
|
-
function requestTeardown(...args) {
|
|
26
|
-
return getActiveWidget().requestTeardown(...args);
|
|
27
|
-
}
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region src/use-tool-result.ts
|
|
30
|
-
function sourceMismatchError(expectedName, actualName) {
|
|
31
|
-
if (actualName === void 0 || actualName === expectedName) return;
|
|
32
|
-
return /* @__PURE__ */ new Error(`useToolResult expected opening tool ${JSON.stringify(expectedName)}, received ${JSON.stringify(actualName)}`);
|
|
33
|
-
}
|
|
34
|
-
function openingSnapshot(adapter, lifecycle, mismatch) {
|
|
35
|
-
if (mismatch !== void 0) return {
|
|
36
|
-
data: void 0,
|
|
37
|
-
error: mismatch,
|
|
38
|
-
rawResult: lifecycle.rawResult,
|
|
39
|
-
status: "error",
|
|
40
|
-
isFetching: false
|
|
41
|
-
};
|
|
42
|
-
if (lifecycle.status === "pending") return {
|
|
43
|
-
data: void 0,
|
|
44
|
-
error: void 0,
|
|
45
|
-
rawResult: void 0,
|
|
46
|
-
status: "pending",
|
|
47
|
-
isFetching: true
|
|
48
|
-
};
|
|
49
|
-
if (lifecycle.status === "cancelled") return {
|
|
50
|
-
data: void 0,
|
|
51
|
-
error: new McpToolCancelledError(adapter.name, lifecycle.cancellationReason),
|
|
52
|
-
rawResult: void 0,
|
|
53
|
-
status: "error",
|
|
54
|
-
isFetching: false
|
|
55
|
-
};
|
|
56
|
-
const rawResult = lifecycle.rawResult;
|
|
57
|
-
const callResult = adapter.parse(rawResult);
|
|
58
|
-
return callResult.error === void 0 ? {
|
|
59
|
-
data: callResult.result,
|
|
60
|
-
error: void 0,
|
|
61
|
-
rawResult,
|
|
62
|
-
status: "success",
|
|
63
|
-
isFetching: false
|
|
64
|
-
} : {
|
|
65
|
-
data: void 0,
|
|
66
|
-
error: callResult.error,
|
|
67
|
-
rawResult,
|
|
68
|
-
status: "error",
|
|
69
|
-
isFetching: false
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function useToolResult(source) {
|
|
73
|
-
const context = useConnectedWidgetContext("useToolResult");
|
|
74
|
-
const adapter = getToolResultAdapter(source);
|
|
75
|
-
const [hostToolName, setHostToolName] = useState(() => context.app.getHostContext()?.toolInfo?.tool.name);
|
|
76
|
-
const mismatch = useMemo(() => sourceMismatchError(adapter.name, hostToolName), [adapter.name, hostToolName]);
|
|
77
|
-
const [snapshot, setSnapshot] = useState(() => openingSnapshot(adapter, context.tool, mismatch));
|
|
78
|
-
const hasExecutedRef = useRef(false);
|
|
79
|
-
const hasExplicitInputRef = useRef(false);
|
|
80
|
-
const latestInputRef = useRef(context.tool.input);
|
|
81
|
-
const latestRequestRef = useRef(0);
|
|
82
|
-
const mountedRef = useRef(true);
|
|
83
|
-
useEffect(() => {
|
|
84
|
-
mountedRef.current = true;
|
|
85
|
-
return () => {
|
|
86
|
-
mountedRef.current = false;
|
|
87
|
-
latestRequestRef.current += 1;
|
|
88
|
-
};
|
|
89
|
-
}, []);
|
|
90
|
-
useEffect(() => {
|
|
91
|
-
const syncHostToolName = () => {
|
|
92
|
-
setHostToolName(context.app.getHostContext()?.toolInfo?.tool.name);
|
|
93
|
-
};
|
|
94
|
-
syncHostToolName();
|
|
95
|
-
context.app.addEventListener("hostcontextchanged", syncHostToolName);
|
|
96
|
-
return () => {
|
|
97
|
-
context.app.removeEventListener("hostcontextchanged", syncHostToolName);
|
|
98
|
-
};
|
|
99
|
-
}, [context.app]);
|
|
100
|
-
useEffect(() => {
|
|
101
|
-
if (!hasExplicitInputRef.current && context.tool.inputReceived) latestInputRef.current = context.tool.input;
|
|
102
|
-
}, [context.tool.input, context.tool.inputReceived]);
|
|
103
|
-
useEffect(() => {
|
|
104
|
-
if (!hasExecutedRef.current) setSnapshot(openingSnapshot(adapter, context.tool, mismatch));
|
|
105
|
-
}, [
|
|
106
|
-
adapter,
|
|
107
|
-
context.tool,
|
|
108
|
-
mismatch
|
|
109
|
-
]);
|
|
110
|
-
const execute = useCallback(async function execute(input) {
|
|
111
|
-
hasExecutedRef.current = true;
|
|
112
|
-
if (arguments.length > 0) {
|
|
113
|
-
hasExplicitInputRef.current = true;
|
|
114
|
-
latestInputRef.current = input;
|
|
115
|
-
}
|
|
116
|
-
const request = ++latestRequestRef.current;
|
|
117
|
-
if (mismatch !== void 0) {
|
|
118
|
-
setSnapshot((current) => ({
|
|
119
|
-
...current,
|
|
120
|
-
error: mismatch,
|
|
121
|
-
status: "error",
|
|
122
|
-
isFetching: false
|
|
123
|
-
}));
|
|
124
|
-
return errorResult(mismatch);
|
|
125
|
-
}
|
|
126
|
-
setSnapshot((current) => ({
|
|
127
|
-
...current,
|
|
128
|
-
error: void 0,
|
|
129
|
-
status: current.data === void 0 ? "pending" : "success",
|
|
130
|
-
isFetching: true
|
|
131
|
-
}));
|
|
132
|
-
const execution = await adapter.execute(latestInputRef.current, context.app);
|
|
133
|
-
if (mountedRef.current && request === latestRequestRef.current) setSnapshot((current) => execution.callResult.error === void 0 ? {
|
|
134
|
-
data: execution.callResult.result,
|
|
135
|
-
error: void 0,
|
|
136
|
-
rawResult: execution.rawResult ?? current.rawResult,
|
|
137
|
-
status: "success",
|
|
138
|
-
isFetching: false
|
|
139
|
-
} : {
|
|
140
|
-
data: current.data,
|
|
141
|
-
error: execution.callResult.error,
|
|
142
|
-
rawResult: execution.rawResult ?? current.rawResult,
|
|
143
|
-
status: "error",
|
|
144
|
-
isFetching: false
|
|
145
|
-
});
|
|
146
|
-
return execution.callResult;
|
|
147
|
-
}, [
|
|
148
|
-
adapter,
|
|
149
|
-
context.app,
|
|
150
|
-
mismatch
|
|
151
|
-
]);
|
|
152
|
-
return {
|
|
153
|
-
data: snapshot.data,
|
|
154
|
-
error: snapshot.error,
|
|
155
|
-
rawResult: snapshot.rawResult,
|
|
156
|
-
status: snapshot.status,
|
|
157
|
-
isLoading: snapshot.isFetching && snapshot.data === void 0,
|
|
158
|
-
isFetching: snapshot.isFetching,
|
|
159
|
-
isSuccess: snapshot.status === "success",
|
|
160
|
-
isError: snapshot.status === "error",
|
|
161
|
-
execute
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
//#endregion
|
|
165
5
|
//#region src/index.tsx
|
|
6
|
+
var WidgetContext = createContext(null);
|
|
7
|
+
function useWidget() {
|
|
8
|
+
const app = useContext(WidgetContext);
|
|
9
|
+
if (app == null) throw new Error("useWidget must be used within a connected <Widget>");
|
|
10
|
+
return app;
|
|
11
|
+
}
|
|
166
12
|
function applyHooks(app, hooks) {
|
|
167
13
|
app.onerror = hooks?.error ?? ((error) => console.error(error));
|
|
168
14
|
if (!hooks) return;
|
|
169
|
-
if (hooks.toolInput) app.
|
|
170
|
-
if (hooks.toolInputPartial) app.
|
|
171
|
-
if (hooks.toolResult) app.
|
|
172
|
-
if (hooks.toolCancelled) app.
|
|
173
|
-
if (hooks.hostContextChanged) app.
|
|
15
|
+
if (hooks.toolInput) app.ontoolinput = hooks.toolInput;
|
|
16
|
+
if (hooks.toolInputPartial) app.ontoolinputpartial = hooks.toolInputPartial;
|
|
17
|
+
if (hooks.toolResult) app.ontoolresult = hooks.toolResult;
|
|
18
|
+
if (hooks.toolCancelled) app.ontoolcancelled = hooks.toolCancelled;
|
|
19
|
+
if (hooks.hostContextChanged) app.onhostcontextchanged = hooks.hostContextChanged;
|
|
20
|
+
if (hooks.teardown) app.onteardown = hooks.teardown;
|
|
174
21
|
}
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
input: void 0,
|
|
178
|
-
inputReceived: false,
|
|
179
|
-
rawResult: void 0,
|
|
180
|
-
cancellationReason: void 0,
|
|
181
|
-
status: "pending",
|
|
182
|
-
version: 0
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
let rootInstance = null;
|
|
22
|
+
var rootInstance = null;
|
|
186
23
|
function Widget({ metadata, children, hooks, fallback, error: errorUI }) {
|
|
187
24
|
const [connected, setConnected] = useState(false);
|
|
188
25
|
const [error, setError] = useState(null);
|
|
189
|
-
const [toolLifecycle, setToolLifecycle] = useState(initialToolLifecycle);
|
|
190
26
|
const appRef = useRef(null);
|
|
191
27
|
const initRef = useRef(null);
|
|
192
28
|
if (initRef.current == null) initRef.current = {
|
|
@@ -195,7 +31,6 @@ function Widget({ metadata, children, hooks, fallback, error: errorUI }) {
|
|
|
195
31
|
};
|
|
196
32
|
useEffect(() => {
|
|
197
33
|
let cancelled = false;
|
|
198
|
-
let active = false;
|
|
199
34
|
const { metadata: meta, hooks: initHooks } = initRef.current;
|
|
200
35
|
const { capabilities, autoResize, strict, name, version, title } = meta;
|
|
201
36
|
const options = {};
|
|
@@ -210,40 +45,7 @@ function Widget({ metadata, children, hooks, fallback, error: errorUI }) {
|
|
|
210
45
|
title
|
|
211
46
|
}, capabilities ?? {}, options);
|
|
212
47
|
appRef.current = app;
|
|
213
|
-
setToolLifecycle(initialToolLifecycle());
|
|
214
|
-
app.addEventListener("toolinput", (params) => {
|
|
215
|
-
if (!cancelled) setToolLifecycle((current) => ({
|
|
216
|
-
...current,
|
|
217
|
-
input: params.arguments,
|
|
218
|
-
inputReceived: true
|
|
219
|
-
}));
|
|
220
|
-
});
|
|
221
|
-
app.addEventListener("toolresult", (params) => {
|
|
222
|
-
if (!cancelled) setToolLifecycle((current) => ({
|
|
223
|
-
...current,
|
|
224
|
-
rawResult: params,
|
|
225
|
-
cancellationReason: void 0,
|
|
226
|
-
status: "result",
|
|
227
|
-
version: current.version + 1
|
|
228
|
-
}));
|
|
229
|
-
});
|
|
230
|
-
app.addEventListener("toolcancelled", (params) => {
|
|
231
|
-
if (!cancelled) setToolLifecycle((current) => ({
|
|
232
|
-
...current,
|
|
233
|
-
rawResult: void 0,
|
|
234
|
-
cancellationReason: params.reason,
|
|
235
|
-
status: "cancelled",
|
|
236
|
-
version: current.version + 1
|
|
237
|
-
}));
|
|
238
|
-
});
|
|
239
48
|
applyHooks(app, initHooks);
|
|
240
|
-
app.onteardown = async (params, extra) => {
|
|
241
|
-
if (active) {
|
|
242
|
-
deactivateWidget(app);
|
|
243
|
-
active = false;
|
|
244
|
-
}
|
|
245
|
-
return await initHooks?.teardown?.(params, extra) ?? {};
|
|
246
|
-
};
|
|
247
49
|
(async () => {
|
|
248
50
|
try {
|
|
249
51
|
await initHooks?.before?.();
|
|
@@ -254,28 +56,14 @@ function Widget({ metadata, children, hooks, fallback, error: errorUI }) {
|
|
|
254
56
|
if (!(err instanceof Error && err.message.includes("already connected"))) throw err;
|
|
255
57
|
}
|
|
256
58
|
if (cancelled) return;
|
|
257
|
-
activateWidget(app);
|
|
258
|
-
active = true;
|
|
259
59
|
await initHooks?.after?.();
|
|
260
60
|
if (!cancelled) setConnected(true);
|
|
261
|
-
else {
|
|
262
|
-
deactivateWidget(app);
|
|
263
|
-
active = false;
|
|
264
|
-
}
|
|
265
61
|
} catch (err) {
|
|
266
|
-
if (active) {
|
|
267
|
-
deactivateWidget(app);
|
|
268
|
-
active = false;
|
|
269
|
-
}
|
|
270
62
|
if (!cancelled) setError(err instanceof Error ? err : new Error(String(err)));
|
|
271
63
|
}
|
|
272
64
|
})();
|
|
273
65
|
return () => {
|
|
274
66
|
cancelled = true;
|
|
275
|
-
if (active) {
|
|
276
|
-
deactivateWidget(app);
|
|
277
|
-
active = false;
|
|
278
|
-
}
|
|
279
67
|
app.close();
|
|
280
68
|
if (appRef.current === app) appRef.current = null;
|
|
281
69
|
};
|
|
@@ -291,10 +79,7 @@ function Widget({ metadata, children, hooks, fallback, error: errorUI }) {
|
|
|
291
79
|
}
|
|
292
80
|
if (!connected || appRef.current == null) return fallback ?? /* @__PURE__ */ jsx("div", { children: "Connecting..." });
|
|
293
81
|
return /* @__PURE__ */ jsx(WidgetContext.Provider, {
|
|
294
|
-
value:
|
|
295
|
-
app: appRef.current,
|
|
296
|
-
tool: toolLifecycle
|
|
297
|
-
},
|
|
82
|
+
value: appRef.current,
|
|
298
83
|
children
|
|
299
84
|
});
|
|
300
85
|
}
|
|
@@ -307,6 +92,6 @@ function mountWidget(Widget) {
|
|
|
307
92
|
rootInstance.render(/* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(Widget, {}) }));
|
|
308
93
|
}
|
|
309
94
|
//#endregion
|
|
310
|
-
export {
|
|
95
|
+
export { Widget, mountWidget, useWidget };
|
|
311
96
|
|
|
312
97
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/app.ts","../src/use-tool-result.ts","../src/index.tsx"],"sourcesContent":["import type { App } from \"@modelcontextprotocol/ext-apps\";\n\nimport { getActiveWidget } from \"./widget-context\";\n\nexport function sendMessage(\n ...args: Parameters<App[\"sendMessage\"]>\n): ReturnType<App[\"sendMessage\"]> {\n return getActiveWidget().sendMessage(...args);\n}\n\nexport function sendLog(\n ...args: Parameters<App[\"sendLog\"]>\n): ReturnType<App[\"sendLog\"]> {\n return getActiveWidget().sendLog(...args);\n}\n\nexport function updateModelContext(\n ...args: Parameters<App[\"updateModelContext\"]>\n): ReturnType<App[\"updateModelContext\"]> {\n return getActiveWidget().updateModelContext(...args);\n}\n\nexport function openLink(\n ...args: Parameters<App[\"openLink\"]>\n): ReturnType<App[\"openLink\"]> {\n return getActiveWidget().openLink(...args);\n}\n\nexport function downloadFile(\n ...args: Parameters<App[\"downloadFile\"]>\n): ReturnType<App[\"downloadFile\"]> {\n return getActiveWidget().downloadFile(...args);\n}\n\nexport function requestDisplayMode(\n ...args: Parameters<App[\"requestDisplayMode\"]>\n): ReturnType<App[\"requestDisplayMode\"]> {\n return getActiveWidget().requestDisplayMode(...args);\n}\n\nexport function requestTeardown(\n ...args: Parameters<App[\"requestTeardown\"]>\n): ReturnType<App[\"requestTeardown\"]> {\n return getActiveWidget().requestTeardown(...args);\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport {\n McpToolCancelledError,\n type RawToolResult,\n type ToolCallError,\n type ToolCallResult,\n} from \"./tool-error\";\nimport {\n errorResult,\n getToolResultAdapter,\n type ToolResultAdapter,\n type ToolResultSource,\n} from \"./tool-result-source\";\nimport {\n useConnectedWidgetContext,\n type WidgetToolLifecycle,\n} from \"./widget-context\";\n\nexport type ToolResultStatus = \"pending\" | \"success\" | \"error\";\n\nexport type ToolResultState<Input extends object, Output> = {\n data: Output | undefined;\n error: ToolCallError | undefined;\n rawResult: RawToolResult | undefined;\n status: ToolResultStatus;\n isLoading: boolean;\n isFetching: boolean;\n isSuccess: boolean;\n isError: boolean;\n execute: (input?: Input) => Promise<ToolCallResult<Output>>;\n};\n\ntype ResultSnapshot<Output> = {\n data: Output | undefined;\n error: ToolCallError | undefined;\n rawResult: RawToolResult | undefined;\n status: ToolResultStatus;\n isFetching: boolean;\n};\n\nfunction sourceMismatchError(\n expectedName: string,\n actualName: string | undefined,\n): Error | undefined {\n if (actualName === undefined || actualName === expectedName) {\n return undefined;\n }\n return new Error(\n `useToolResult expected opening tool ${JSON.stringify(expectedName)}, received ${JSON.stringify(actualName)}`,\n );\n}\n\nfunction openingSnapshot<Input extends object, Output>(\n adapter: ToolResultAdapter<Input, Output>,\n lifecycle: WidgetToolLifecycle,\n mismatch: Error | undefined,\n): ResultSnapshot<Output> {\n if (mismatch !== undefined) {\n return {\n data: undefined,\n error: mismatch,\n rawResult: lifecycle.rawResult,\n status: \"error\",\n isFetching: false,\n };\n }\n if (lifecycle.status === \"pending\") {\n return {\n data: undefined,\n error: undefined,\n rawResult: undefined,\n status: \"pending\",\n isFetching: true,\n };\n }\n if (lifecycle.status === \"cancelled\") {\n return {\n data: undefined,\n error: new McpToolCancelledError(\n adapter.name,\n lifecycle.cancellationReason,\n ),\n rawResult: undefined,\n status: \"error\",\n isFetching: false,\n };\n }\n\n const rawResult = lifecycle.rawResult!;\n const callResult = adapter.parse(rawResult);\n return callResult.error === undefined\n ? {\n data: callResult.result,\n error: undefined,\n rawResult,\n status: \"success\",\n isFetching: false,\n }\n : {\n data: undefined,\n error: callResult.error,\n rawResult,\n status: \"error\",\n isFetching: false,\n };\n}\n\nexport function useToolResult<Input extends object, Output>(\n source: ToolResultSource<Input, Output>,\n): ToolResultState<Input, Output> {\n const context = useConnectedWidgetContext(\"useToolResult\");\n const adapter = getToolResultAdapter(source);\n const [hostToolName, setHostToolName] = useState<string | undefined>(\n () => context.app.getHostContext()?.toolInfo?.tool.name,\n );\n const mismatch = useMemo(\n () => sourceMismatchError(adapter.name, hostToolName),\n [adapter.name, hostToolName],\n );\n const [snapshot, setSnapshot] = useState<ResultSnapshot<Output>>(() =>\n openingSnapshot(adapter, context.tool, mismatch),\n );\n const hasExecutedRef = useRef(false);\n const hasExplicitInputRef = useRef(false);\n const latestInputRef = useRef<Input | undefined>(\n context.tool.input as Input | undefined,\n );\n const latestRequestRef = useRef(0);\n const mountedRef = useRef(true);\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n latestRequestRef.current += 1;\n };\n }, []);\n\n useEffect(() => {\n const syncHostToolName = () => {\n setHostToolName(context.app.getHostContext()?.toolInfo?.tool.name);\n };\n syncHostToolName();\n context.app.addEventListener(\"hostcontextchanged\", syncHostToolName);\n return () => {\n context.app.removeEventListener(\"hostcontextchanged\", syncHostToolName);\n };\n }, [context.app]);\n\n useEffect(() => {\n if (!hasExplicitInputRef.current && context.tool.inputReceived) {\n latestInputRef.current = context.tool.input as Input | undefined;\n }\n }, [context.tool.input, context.tool.inputReceived]);\n\n useEffect(() => {\n if (!hasExecutedRef.current) {\n setSnapshot(openingSnapshot(adapter, context.tool, mismatch));\n }\n }, [adapter, context.tool, mismatch]);\n\n const execute = useCallback(\n async function execute(input?: Input): Promise<ToolCallResult<Output>> {\n hasExecutedRef.current = true;\n if (arguments.length > 0) {\n hasExplicitInputRef.current = true;\n latestInputRef.current = input;\n }\n\n const request = ++latestRequestRef.current;\n if (mismatch !== undefined) {\n setSnapshot((current) => ({\n ...current,\n error: mismatch,\n status: \"error\",\n isFetching: false,\n }));\n return errorResult(mismatch);\n }\n\n setSnapshot((current) => ({\n ...current,\n error: undefined,\n status: current.data === undefined ? \"pending\" : \"success\",\n isFetching: true,\n }));\n const execution = await adapter.execute(\n latestInputRef.current,\n context.app,\n );\n if (mountedRef.current && request === latestRequestRef.current) {\n setSnapshot((current) =>\n execution.callResult.error === undefined\n ? {\n data: execution.callResult.result,\n error: undefined,\n rawResult: execution.rawResult ?? current.rawResult,\n status: \"success\",\n isFetching: false,\n }\n : {\n data: current.data,\n error: execution.callResult.error,\n rawResult: execution.rawResult ?? current.rawResult,\n status: \"error\",\n isFetching: false,\n },\n );\n }\n return execution.callResult;\n },\n [adapter, context.app, mismatch],\n );\n\n return {\n data: snapshot.data,\n error: snapshot.error,\n rawResult: snapshot.rawResult,\n status: snapshot.status,\n isLoading: snapshot.isFetching && snapshot.data === undefined,\n isFetching: snapshot.isFetching,\n isSuccess: snapshot.status === \"success\",\n isError: snapshot.status === \"error\",\n execute,\n };\n}\n","import {\n StrictMode,\n useEffect,\n useRef,\n useState,\n type ComponentType,\n type ReactNode,\n} from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport {\n App,\n type AppEventMap,\n type AppOptions,\n type McpUiAppCapabilities,\n} from \"@modelcontextprotocol/ext-apps\";\nimport {\n WidgetContext,\n activateWidget,\n deactivateWidget,\n useWidget,\n type WidgetToolLifecycle,\n} from \"./widget-context\";\n\nexport {\n downloadFile,\n openLink,\n requestDisplayMode,\n requestTeardown,\n sendLog,\n sendMessage,\n updateModelContext,\n} from \"./app\";\n\nexport {\n McpToolCancelledError,\n McpToolError,\n type McpToolErrorResult,\n type RawToolResult,\n type ToolCallError,\n type ToolCallResult,\n} from \"./tool-error\";\n\nexport {\n useToolResult,\n type ToolResultState,\n type ToolResultStatus,\n} from \"./use-tool-result\";\n\nexport { useWidget };\n\nexport type WidgetMetadata = {\n name: string;\n version: string;\n title?: string;\n capabilities?: McpUiAppCapabilities;\n} & Pick<AppOptions, \"autoResize\" | \"strict\">;\n\nexport type WidgetHooks = {\n before?: () => void | Promise<void>;\n after?: () => void | Promise<void>;\n error?: (error: Error) => void;\n toolInput?: (params: AppEventMap[\"toolinput\"]) => void;\n toolInputPartial?: (params: AppEventMap[\"toolinputpartial\"]) => void;\n toolResult?: (params: AppEventMap[\"toolresult\"]) => void;\n toolCancelled?: (params: AppEventMap[\"toolcancelled\"]) => void;\n hostContextChanged?: (params: AppEventMap[\"hostcontextchanged\"]) => void;\n teardown?: NonNullable<App[\"onteardown\"]>;\n};\n\nexport type WidgetProps = {\n metadata: WidgetMetadata;\n children: ReactNode;\n hooks?: WidgetHooks;\n fallback?: ReactNode;\n error?: ReactNode | ((error: Error) => ReactNode);\n};\n\nfunction applyHooks(app: App, hooks: WidgetHooks | undefined): void {\n app.onerror = hooks?.error ?? ((error) => console.error(error));\n if (!hooks) {\n return;\n }\n if (hooks.toolInput) {\n app.addEventListener(\"toolinput\", hooks.toolInput);\n }\n if (hooks.toolInputPartial) {\n app.addEventListener(\"toolinputpartial\", hooks.toolInputPartial);\n }\n if (hooks.toolResult) {\n app.addEventListener(\"toolresult\", hooks.toolResult);\n }\n if (hooks.toolCancelled) {\n app.addEventListener(\"toolcancelled\", hooks.toolCancelled);\n }\n if (hooks.hostContextChanged) {\n app.addEventListener(\"hostcontextchanged\", hooks.hostContextChanged);\n }\n}\n\nfunction initialToolLifecycle(): WidgetToolLifecycle {\n return {\n input: undefined,\n inputReceived: false,\n rawResult: undefined,\n cancellationReason: undefined,\n status: \"pending\",\n version: 0,\n };\n}\n\nlet rootInstance: Root | null = null;\n\nexport function Widget({\n metadata,\n children,\n hooks,\n fallback,\n error: errorUI,\n}: WidgetProps) {\n const [connected, setConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [toolLifecycle, setToolLifecycle] = useState(initialToolLifecycle);\n const appRef = useRef<App | null>(null);\n const initRef = useRef<{ metadata: WidgetMetadata; hooks: WidgetHooks | undefined } | null>(\n null,\n );\n if (initRef.current == null) {\n initRef.current = { metadata, hooks };\n }\n\n useEffect(() => {\n let cancelled = false;\n let active = false;\n const { metadata: meta, hooks: initHooks } = initRef.current!;\n const { capabilities, autoResize, strict, name, version, title } = meta;\n const options: AppOptions = {};\n if (autoResize !== undefined) {\n options.autoResize = autoResize;\n }\n if (strict !== undefined) {\n options.strict = strict;\n }\n const app = new App(\n title === undefined ? { name, version } : { name, version, title },\n capabilities ?? {},\n options,\n );\n appRef.current = app;\n setToolLifecycle(initialToolLifecycle());\n app.addEventListener(\"toolinput\", (params) => {\n if (!cancelled) {\n setToolLifecycle((current) => ({\n ...current,\n input: params.arguments,\n inputReceived: true,\n }));\n }\n });\n app.addEventListener(\"toolresult\", (params) => {\n if (!cancelled) {\n setToolLifecycle((current) => ({\n ...current,\n rawResult: params,\n cancellationReason: undefined,\n status: \"result\",\n version: current.version + 1,\n }));\n }\n });\n app.addEventListener(\"toolcancelled\", (params) => {\n if (!cancelled) {\n setToolLifecycle((current) => ({\n ...current,\n rawResult: undefined,\n cancellationReason: params.reason,\n status: \"cancelled\",\n version: current.version + 1,\n }));\n }\n });\n applyHooks(app, initHooks);\n app.onteardown = async (params, extra) => {\n if (active) {\n deactivateWidget(app);\n active = false;\n }\n return (await initHooks?.teardown?.(params, extra)) ?? {};\n };\n\n void (async () => {\n try {\n await initHooks?.before?.();\n if (cancelled) {\n return;\n }\n try {\n await app.connect();\n } catch (err: unknown) {\n if (!(err instanceof Error && err.message.includes(\"already connected\"))) {\n throw err;\n }\n }\n if (cancelled) {\n return;\n }\n activateWidget(app);\n active = true;\n await initHooks?.after?.();\n if (!cancelled) {\n setConnected(true);\n } else {\n deactivateWidget(app);\n active = false;\n }\n } catch (err: unknown) {\n if (active) {\n deactivateWidget(app);\n active = false;\n }\n if (!cancelled) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }\n })();\n\n return () => {\n cancelled = true;\n if (active) {\n deactivateWidget(app);\n active = false;\n }\n void app.close();\n if (appRef.current === app) {\n appRef.current = null;\n }\n };\n }, []);\n\n if (error) {\n if (typeof errorUI === \"function\") return errorUI(error);\n if (errorUI !== undefined) return errorUI;\n return (\n <div>\n <strong>ERROR:</strong> {error.message}\n </div>\n );\n }\n if (!connected || appRef.current == null) {\n return fallback ?? <div>Connecting...</div>;\n }\n\n return (\n <WidgetContext.Provider\n value={{ app: appRef.current, tool: toolLifecycle }}\n >\n {children}\n </WidgetContext.Provider>\n );\n}\n\nexport function mountWidget(Widget: ComponentType): void {\n if (!rootInstance) {\n const element = document.querySelector(\"#root\");\n if (!(element instanceof HTMLElement)) {\n throw new Error(\"Widget root #root was not found\");\n }\n rootInstance = createRoot(element);\n }\n\n rootInstance.render(\n <StrictMode>\n <Widget />\n </StrictMode>,\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.tsx"],"sourcesContent":["import {\n StrictMode,\n createContext,\n useContext,\n useEffect,\n useRef,\n useState,\n type ComponentType,\n type ReactNode,\n} from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport {\n App,\n type AppEventMap,\n type AppOptions,\n type McpUiAppCapabilities,\n} from \"@modelcontextprotocol/ext-apps\";\n\nexport type WidgetMetadata = {\n name: string;\n version: string;\n title?: string;\n capabilities?: McpUiAppCapabilities;\n} & Pick<AppOptions, \"autoResize\" | \"strict\">;\n\nexport type WidgetHooks = {\n before?: () => void | Promise<void>;\n after?: () => void | Promise<void>;\n error?: (error: Error) => void;\n toolInput?: (params: AppEventMap[\"toolinput\"]) => void;\n toolInputPartial?: (params: AppEventMap[\"toolinputpartial\"]) => void;\n toolResult?: (params: AppEventMap[\"toolresult\"]) => void;\n toolCancelled?: (params: AppEventMap[\"toolcancelled\"]) => void;\n hostContextChanged?: (params: AppEventMap[\"hostcontextchanged\"]) => void;\n teardown?: NonNullable<App[\"onteardown\"]>;\n};\n\nexport type WidgetProps = {\n metadata: WidgetMetadata;\n children: ReactNode;\n hooks?: WidgetHooks;\n fallback?: ReactNode;\n error?: ReactNode | ((error: Error) => ReactNode);\n};\n\nconst WidgetContext = createContext<App | null>(null);\n\nexport function useWidget(): App {\n const app = useContext(WidgetContext);\n if (app == null) {\n throw new Error(\"useWidget must be used within a connected <Widget>\");\n }\n return app;\n}\n\nfunction applyHooks(app: App, hooks: WidgetHooks | undefined): void {\n app.onerror = hooks?.error ?? ((error) => console.error(error));\n if (!hooks) {\n return;\n }\n if (hooks.toolInput) {\n app.ontoolinput = hooks.toolInput;\n }\n if (hooks.toolInputPartial) {\n app.ontoolinputpartial = hooks.toolInputPartial;\n }\n if (hooks.toolResult) {\n app.ontoolresult = hooks.toolResult;\n }\n if (hooks.toolCancelled) {\n app.ontoolcancelled = hooks.toolCancelled;\n }\n if (hooks.hostContextChanged) {\n app.onhostcontextchanged = hooks.hostContextChanged;\n }\n if (hooks.teardown) {\n app.onteardown = hooks.teardown;\n }\n}\n\nlet rootInstance: Root | null = null;\n\nexport function Widget({\n metadata,\n children,\n hooks,\n fallback,\n error: errorUI,\n}: WidgetProps) {\n const [connected, setConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const appRef = useRef<App | null>(null);\n const initRef = useRef<{ metadata: WidgetMetadata; hooks: WidgetHooks | undefined } | null>(\n null,\n );\n if (initRef.current == null) {\n initRef.current = { metadata, hooks };\n }\n\n useEffect(() => {\n let cancelled = false;\n const { metadata: meta, hooks: initHooks } = initRef.current!;\n const { capabilities, autoResize, strict, name, version, title } = meta;\n const options: AppOptions = {};\n if (autoResize !== undefined) {\n options.autoResize = autoResize;\n }\n if (strict !== undefined) {\n options.strict = strict;\n }\n const app = new App(\n title === undefined ? { name, version } : { name, version, title },\n capabilities ?? {},\n options,\n );\n appRef.current = app;\n applyHooks(app, initHooks);\n\n void (async () => {\n try {\n await initHooks?.before?.();\n if (cancelled) {\n return;\n }\n try {\n await app.connect();\n } catch (err: unknown) {\n if (!(err instanceof Error && err.message.includes(\"already connected\"))) {\n throw err;\n }\n }\n if (cancelled) {\n return;\n }\n await initHooks?.after?.();\n if (!cancelled) {\n setConnected(true);\n }\n } catch (err: unknown) {\n if (!cancelled) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }\n })();\n\n return () => {\n cancelled = true;\n void app.close();\n if (appRef.current === app) {\n appRef.current = null;\n }\n };\n }, []);\n\n if (error) {\n if (typeof errorUI === \"function\") return errorUI(error);\n if (errorUI !== undefined) return errorUI;\n return (\n <div>\n <strong>ERROR:</strong> {error.message}\n </div>\n );\n }\n if (!connected || appRef.current == null) {\n return fallback ?? <div>Connecting...</div>;\n }\n\n return (\n <WidgetContext.Provider value={appRef.current}>{children}</WidgetContext.Provider>\n );\n}\n\nexport function mountWidget(Widget: ComponentType): void {\n if (!rootInstance) {\n const element = document.querySelector(\"#root\");\n if (!(element instanceof HTMLElement)) {\n throw new Error(\"Widget root #root was not found\");\n }\n rootInstance = createRoot(element);\n }\n\n rootInstance.render(\n <StrictMode>\n <Widget />\n </StrictMode>,\n );\n}\n"],"mappings":"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"}
|
package/dist/vite.js
CHANGED
|
@@ -81,14 +81,14 @@ function assertNoInvalidWidgets(invalid) {
|
|
|
81
81
|
}
|
|
82
82
|
//#endregion
|
|
83
83
|
//#region src/vite.ts
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
var VIRTUAL_PREFIX = "/_belgie/widget/";
|
|
85
|
+
var VIRTUAL_MODULE_PREFIX = "\0belgie:widget:";
|
|
86
|
+
var ORCHESTRATION_ENTRY_ID = "belgie:widget-build-orchestrator";
|
|
87
|
+
var RESOLVED_ORCHESTRATION_ENTRY_ID = "\0belgie:widget-build-orchestrator";
|
|
88
|
+
var INTERNAL_WIDGET_PATH_ENV = "BELGIE_INTERNAL_WIDGET_PATH";
|
|
89
|
+
var MAX_INLINE_ASSET_SIZE = Number.MAX_SAFE_INTEGER;
|
|
90
|
+
var REACT_REFRESH_PLUGIN_NAME = "vite:react-refresh";
|
|
91
|
+
var TEXT_DECODER = new TextDecoder();
|
|
92
92
|
function getWidgetEntryPattern(srcDir) {
|
|
93
93
|
const escaped = normalizePath(srcDir).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
94
94
|
return new RegExp(`${escaped}\/[^/]+\/widget\\.tsx(?:\\?.*)?$`);
|
|
@@ -142,12 +142,13 @@ function ensureReactRefreshPreamble(html, base, enabled) {
|
|
|
142
142
|
].join("\n");
|
|
143
143
|
return html.replace("<head>", `<head>\n${preamble}`);
|
|
144
144
|
}
|
|
145
|
-
async function buildWidget(widget, config
|
|
145
|
+
async function buildWidget(widget, config) {
|
|
146
|
+
if (!config.configFile) throw new Error("belgie: isolated widget builds require a Vite config file; inline configs are not supported");
|
|
146
147
|
const previousWidgetPath = process.env[INTERNAL_WIDGET_PATH_ENV];
|
|
147
148
|
process.env[INTERNAL_WIDGET_PATH_ENV] = widget.filePath;
|
|
148
149
|
try {
|
|
149
150
|
await build({
|
|
150
|
-
configFile,
|
|
151
|
+
configFile: config.configFile,
|
|
151
152
|
configLoader: "native",
|
|
152
153
|
root: config.root,
|
|
153
154
|
mode: config.mode,
|
|
@@ -277,7 +278,7 @@ function belgie(options = {}) {
|
|
|
277
278
|
recursive: true,
|
|
278
279
|
force: true
|
|
279
280
|
});
|
|
280
|
-
for (const widget of widgetMap.values()) await buildWidget(widget, resolvedConfig
|
|
281
|
+
for (const widget of widgetMap.values()) await buildWidget(widget, resolvedConfig);
|
|
281
282
|
},
|
|
282
283
|
configureServer(server) {
|
|
283
284
|
if (!resolvedSrcDir) {
|
|
@@ -331,8 +332,7 @@ function belgie(options = {}) {
|
|
|
331
332
|
});
|
|
332
333
|
},
|
|
333
334
|
transform(code, id) {
|
|
334
|
-
|
|
335
|
-
if (widgetEntryPattern?.test(normalizedId) && !hasDefaultExport(code)) this.warn(`Widget file "${normalizedId.split("/").pop()}" is missing a default export.`);
|
|
335
|
+
if (widgetEntryPattern?.test(id) && !hasDefaultExport(code)) this.warn(`Widget file "${id.split("/").pop()}" is missing a default export.`);
|
|
336
336
|
return null;
|
|
337
337
|
}
|
|
338
338
|
};
|
package/dist/vite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.js","names":[],"sources":["../src/html.ts","../src/validate-widget.ts","../src/scan-widgets.ts","../src/vite.ts"],"sourcesContent":["export type WidgetHtmlDocumentOptions = {\n inlineScript?: string;\n inlineStyles?: string[];\n scripts?: string[];\n styles?: string[];\n};\n\nexport function escapeInlineScript(value: string): string {\n return value.replace(/<\\/script/gi, \"<\\\\/script\");\n}\n\nexport function escapeInlineStyle(value: string): string {\n return value.replace(/<\\/style/gi, \"<\\\\/style\");\n}\n\nexport function buildVirtualEntry(widgetFilePath: string): string {\n const normalized = widgetFilePath.replace(/\\\\/g, \"/\");\n return [\n `import { mountWidget } from \"@belgie/mcp\";`,\n `import Widget from ${JSON.stringify(normalized)};`,\n \"\",\n \"mountWidget(Widget);\",\n \"\",\n ].join(\"\\n\");\n}\n\nexport function renderWidgetHtmlDocument(options: WidgetHtmlDocumentOptions): string {\n const head = [\n '<meta charset=\"utf-8\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n ...(options.styles ?? []).map((href) => `<link rel=\"stylesheet\" crossorigin href=\"${href}\">`),\n ...(options.inlineStyles ?? []).map((style) => `<style>${escapeInlineStyle(style)}</style>`),\n ];\n const scripts = [\n ...(options.scripts ?? []).map((src) => `<script type=\"module\" crossorigin src=\"${src}\"></script>`),\n ...(options.inlineScript === undefined\n ? []\n : [`<script type=\"module\">${escapeInlineScript(options.inlineScript)}</script>`]),\n ];\n return [\n \"<!doctype html>\",\n \"<html>\",\n \"<head>\",\n ...head,\n \"</head>\",\n \"<body>\",\n '<div id=\"root\"></div>',\n ...scripts,\n \"</body>\",\n \"</html>\",\n \"\",\n ].join(\"\\n\");\n}\n","function stripComments(code: string): string {\n return code.replace(/\\/\\/.*$/gm, \"\").replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n}\n\nexport function hasDefaultExport(code: string): boolean {\n const stripped = stripComments(code);\n return (\n /export\\s+default\\s/.test(stripped) ||\n /export\\s*\\{[^}]*\\bas\\s+default\\b[^}]*}/.test(stripped)\n );\n}\n","import { globSync, readFileSync } from \"node:fs\";\nimport { basename, dirname, resolve } from \"node:path\";\n\nimport { hasDefaultExport } from \"./validate-widget.js\";\n\nexport type WidgetCandidate = {\n name: string;\n filePath: string;\n};\n\nexport type InvalidWidget = {\n filePath: string;\n};\n\nexport type WidgetScanResult = {\n valid: WidgetCandidate[];\n invalid: InvalidWidget[];\n};\n\nexport function scanWidgetsSync(srcDir: string): WidgetScanResult {\n const pattern = resolve(srcDir, \"*/widget.tsx\");\n const candidates = globSync(pattern).map((file) => ({\n name: basename(dirname(file)),\n filePath: file,\n }));\n\n const valid: WidgetCandidate[] = [];\n const invalid: InvalidWidget[] = [];\n for (const candidate of candidates) {\n const code = readFileSync(candidate.filePath, \"utf-8\");\n if (hasDefaultExport(code)) {\n valid.push(candidate);\n } else {\n invalid.push({ filePath: candidate.filePath });\n }\n }\n\n return { valid, invalid };\n}\n\nexport function assertUniqueWidgetNames(widgets: WidgetCandidate[]): void {\n const nameMap = new Map<string, string[]>();\n for (const widget of widgets) {\n const paths = nameMap.get(widget.name) ?? [];\n paths.push(widget.filePath);\n nameMap.set(widget.name, paths);\n }\n\n for (const [name, paths] of nameMap) {\n if (paths.length > 1) {\n throw new Error(\n `belgie: duplicate widget name \"${name}\" resolved from:\\n - ${paths.join(\"\\n - \")}\\nRename one of the files to avoid the conflict.`,\n );\n }\n }\n}\n\nexport function assertNoInvalidWidgets(invalid: InvalidWidget[]): void {\n if (invalid.length === 0) {\n return;\n }\n const paths = invalid.map((widget) => widget.filePath).join(\"\\n - \");\n throw new Error(\n `belgie: widget file(s) missing a default export:\\n - ${paths}\\nAdd a default export so the widget can be built.`,\n );\n}\n\nexport function discoverWidgetsSync(srcDir: string): WidgetCandidate[] {\n const { valid } = scanWidgetsSync(srcDir);\n assertUniqueWidgetNames(valid);\n return valid;\n}\n","import { rmSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\n\nimport { build, normalizePath, type Plugin, type ResolvedConfig, type UserConfig } from \"vite\";\n\nimport { buildVirtualEntry, renderWidgetHtmlDocument } from \"./html.js\";\nimport {\n assertNoInvalidWidgets,\n assertUniqueWidgetNames,\n scanWidgetsSync,\n type WidgetCandidate,\n} from \"./scan-widgets.js\";\nimport { hasDefaultExport } from \"./validate-widget.js\";\n\nconst VIRTUAL_PREFIX = \"/_belgie/widget/\";\nconst VIRTUAL_MODULE_PREFIX = \"\\0belgie:widget:\";\nconst ORCHESTRATION_ENTRY_ID = \"belgie:widget-build-orchestrator\";\nconst RESOLVED_ORCHESTRATION_ENTRY_ID = \"\\0belgie:widget-build-orchestrator\";\nconst INTERNAL_WIDGET_PATH_ENV = \"BELGIE_INTERNAL_WIDGET_PATH\";\nconst MAX_INLINE_ASSET_SIZE = Number.MAX_SAFE_INTEGER;\nconst REACT_REFRESH_PLUGIN_NAME = \"vite:react-refresh\";\nconst TEXT_DECODER = new TextDecoder();\n\nexport type BelgiePluginOptions = {\n srcDir?: string;\n};\n\ntype RollupInput = string | string[] | Record<string, string>;\n\ntype BuildAsset = {\n fileName: string;\n source: string | Uint8Array;\n type: \"asset\";\n};\n\ntype BuildChunk = {\n code: string;\n dynamicImports: string[];\n facadeModuleId: string | null;\n fileName: string;\n imports: string[];\n isEntry: boolean;\n type: \"chunk\";\n viteMetadata?: { importedCss?: Set<string> };\n};\n\ntype BuildArtifact = BuildAsset | BuildChunk;\n\nfunction getWidgetEntryPattern(srcDir: string): RegExp {\n const escaped = normalizePath(srcDir).replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(`${escaped}\\/[^/]+\\/widget\\\\.tsx(?:\\\\?.*)?$`);\n}\n\nfunction virtualWidgetName(id: string): string | undefined {\n if (!id.startsWith(VIRTUAL_PREFIX)) {\n return undefined;\n }\n return decodeURIComponent(id.slice(VIRTUAL_PREFIX.length).split(\"?\", 1)[0] ?? \"\");\n}\n\nfunction readAsset(asset: BuildAsset): string {\n return typeof asset.source === \"string\" ? asset.source : TEXT_DECODER.decode(asset.source);\n}\n\nfunction renderWidgetBundle(name: string, bundle: Record<string, BuildArtifact>): string {\n const artifacts = Object.values(bundle);\n const chunks = artifacts.filter((artifact): artifact is BuildChunk => artifact.type === \"chunk\");\n const entries = chunks.filter((chunk) => chunk.isEntry);\n if (entries.length !== 1) {\n throw new Error(`belgie: expected one entry chunk for widget \"${name}\", received ${entries.length}`);\n }\n\n const entry = entries[0]!;\n const extraChunks = chunks.filter((chunk) => chunk !== entry);\n if (extraChunks.length > 0) {\n throw new Error(\n `belgie: widget \"${name}\" emitted extra chunks: ${extraChunks.map((chunk) => chunk.fileName).join(\", \")}`,\n );\n }\n\n const imports = [...entry.imports, ...entry.dynamicImports].filter((item) => item !== entry.fileName);\n if (imports.length > 0) {\n throw new Error(`belgie: widget \"${name}\" retained imports: ${imports.join(\", \")}`);\n }\n\n const assets = artifacts.filter((artifact): artifact is BuildAsset => artifact.type === \"asset\");\n const nonCssAssets = assets.filter((asset) => !asset.fileName.endsWith(\".css\"));\n if (nonCssAssets.length > 0) {\n throw new Error(\n `belgie: widget \"${name}\" emitted non-CSS assets: ${nonCssAssets.map((asset) => asset.fileName).join(\", \")}`,\n );\n }\n\n const assetsByName = new Map(assets.map((asset) => [asset.fileName, asset]));\n const importedCss = [...(entry.viteMetadata?.importedCss ?? [])];\n const cssNames = importedCss.length > 0 ? importedCss : assets.map((asset) => asset.fileName).sort();\n const styles = cssNames.map((cssName) => {\n const asset = assetsByName.get(cssName);\n if (asset === undefined) {\n throw new Error(`belgie: widget \"${name}\" references missing CSS asset ${cssName}`);\n }\n return readAsset(asset);\n });\n return renderWidgetHtmlDocument({ inlineScript: entry.code, inlineStyles: styles });\n}\n\nfunction restoreEnvironment(name: string, previous: string | undefined): void {\n if (previous === undefined) {\n delete process.env[name];\n } else {\n process.env[name] = previous;\n }\n}\n\nfunction ensureReactRefreshPreamble(html: string, base: string, enabled: boolean): string {\n if (!enabled || html.includes(\"@react-refresh\")) {\n return html;\n }\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n const refreshPath = `${normalizedBase}@react-refresh`;\n const preamble = [\n '<script type=\"module\">',\n `import { injectIntoGlobalHook } from ${JSON.stringify(refreshPath)};`,\n \"injectIntoGlobalHook(window);\",\n \"window.$RefreshReg$ = () => {};\",\n \"window.$RefreshSig$ = () => (type) => type;\",\n \"</script>\",\n ].join(\"\\n\");\n return html.replace(\"<head>\", `<head>\\n${preamble}`);\n}\n\nasync function buildWidget(\n widget: WidgetCandidate,\n config: ResolvedConfig,\n configFile: string,\n): Promise<void> {\n const previousWidgetPath = process.env[INTERNAL_WIDGET_PATH_ENV];\n process.env[INTERNAL_WIDGET_PATH_ENV] = widget.filePath;\n try {\n await build({\n configFile,\n configLoader: \"native\",\n root: config.root,\n mode: config.mode,\n ...(config.logLevel === undefined ? {} : { logLevel: config.logLevel }),\n build: {\n emptyOutDir: false,\n outDir: \"dist\",\n },\n });\n } finally {\n restoreEnvironment(INTERNAL_WIDGET_PATH_ENV, previousWidgetPath);\n }\n}\n\nexport function belgie(options: BelgiePluginOptions = {}): Plugin {\n const rawSrcDir = options.srcDir ?? \"src/widgets\";\n const requestedWidgetPath = process.env[INTERNAL_WIDGET_PATH_ENV];\n let resolvedSrcDir = \"\";\n let projectRoot = \"\";\n let resolvedConfig: ResolvedConfig | undefined;\n let widgetMap = new Map<string, WidgetCandidate>();\n let widgetEntryPattern: RegExp | undefined;\n let usesOrchestrationEntry = false;\n let isBuildCommand = false;\n\n return {\n name: \"belgie\",\n enforce: \"pre\",\n api: { srcDir: rawSrcDir },\n\n config: {\n order: \"post\",\n handler(config: UserConfig, { command }) {\n isBuildCommand = command === \"build\";\n projectRoot = config.root || process.cwd();\n resolvedSrcDir = isAbsolute(rawSrcDir) ? rawSrcDir : resolve(projectRoot, rawSrcDir);\n widgetEntryPattern = getWidgetEntryPattern(resolvedSrcDir);\n\n const { valid, invalid } = scanWidgetsSync(resolvedSrcDir);\n assertUniqueWidgetNames(valid);\n if (command === \"build\") {\n assertNoInvalidWidgets(invalid);\n }\n\n if (requestedWidgetPath !== undefined) {\n const normalizedRequestedPath = normalizePath(resolve(requestedWidgetPath));\n const widget = valid.find((candidate) => normalizePath(resolve(candidate.filePath)) === normalizedRequestedPath);\n if (widget === undefined) {\n throw new Error(\n `belgie: isolated widget build requested unknown entry ${normalizePath(requestedWidgetPath)}`,\n );\n }\n widgetMap = new Map([[widget.name, widget]]);\n return {\n appType: \"custom\",\n resolve: { dedupe: [\"react\", \"react-dom\"] },\n build: {\n assetsInlineLimit: MAX_INLINE_ASSET_SIZE,\n copyPublicDir: false,\n cssCodeSplit: false,\n emptyOutDir: false,\n license: false,\n manifest: false,\n modulePreload: false,\n outDir: \"dist\",\n reportCompressedSize: false,\n sourcemap: false,\n ssrManifest: false,\n watch: null,\n write: true,\n rolldownOptions: {\n input: `${VIRTUAL_PREFIX}${encodeURIComponent(widget.name)}`,\n output: { codeSplitting: false },\n },\n },\n };\n }\n\n widgetMap = new Map(valid.map((widget) => [widget.name, widget]));\n const existingInput = config.build?.rolldownOptions?.input as RollupInput | undefined;\n usesOrchestrationEntry = existingInput === undefined;\n return {\n resolve: { dedupe: [\"react\", \"react-dom\"] },\n build: {\n rolldownOptions: {\n input: existingInput ?? ORCHESTRATION_ENTRY_ID,\n },\n },\n optimizeDeps: {\n entries: [`${resolvedSrcDir}/*/widget.tsx`],\n include: [\"react\", \"react-dom/client\", \"react/jsx-runtime\"],\n },\n };\n },\n },\n\n configResolved(config) {\n resolvedConfig = config;\n projectRoot = config.root;\n if (!resolvedSrcDir) {\n resolvedSrcDir = isAbsolute(rawSrcDir) ? rawSrcDir : resolve(projectRoot, rawSrcDir);\n }\n },\n\n resolveId(id) {\n if (id === ORCHESTRATION_ENTRY_ID) {\n return RESOLVED_ORCHESTRATION_ENTRY_ID;\n }\n const name = virtualWidgetName(id);\n if (name !== undefined && widgetMap.has(name)) {\n return `${VIRTUAL_MODULE_PREFIX}${name}`;\n }\n return null;\n },\n\n load(id) {\n if (id === RESOLVED_ORCHESTRATION_ENTRY_ID) {\n return \"export {};\\n\";\n }\n if (id.startsWith(VIRTUAL_MODULE_PREFIX)) {\n const widget = widgetMap.get(id.slice(VIRTUAL_MODULE_PREFIX.length));\n if (widget !== undefined) {\n return buildVirtualEntry(widget.filePath);\n }\n }\n return null;\n },\n\n generateBundle: {\n order: \"post\",\n handler(_options, bundle) {\n if (requestedWidgetPath !== undefined) {\n const widget = [...widgetMap.values()][0];\n if (widget === undefined) {\n throw new Error(\"belgie: isolated widget build lost its widget entry\");\n }\n const html = renderWidgetBundle(widget.name, bundle as Record<string, BuildArtifact>);\n for (const fileName of Object.keys(bundle)) {\n delete bundle[fileName];\n }\n this.emitFile({\n type: \"asset\",\n fileName: `widgets/${widget.name}/index.html`,\n source: html,\n });\n return;\n }\n\n if (usesOrchestrationEntry) {\n for (const [fileName, artifact] of Object.entries(bundle)) {\n if (artifact.type === \"chunk\" && artifact.facadeModuleId === RESOLVED_ORCHESTRATION_ENTRY_ID) {\n delete bundle[fileName];\n }\n }\n }\n },\n },\n\n async closeBundle() {\n if (!isBuildCommand || requestedWidgetPath !== undefined || resolvedConfig === undefined || widgetMap.size === 0) {\n return;\n }\n if (!resolvedConfig.configFile) {\n throw new Error(\n \"belgie: isolated widget builds require a Vite config file; inline configs are not supported\",\n );\n }\n rmSync(resolve(projectRoot, \"dist\", \"widgets\"), { recursive: true, force: true });\n for (const widget of widgetMap.values()) {\n await buildWidget(widget, resolvedConfig, resolvedConfig.configFile);\n }\n },\n\n configureServer(server) {\n if (!resolvedSrcDir) {\n const root = server.config.root || process.cwd();\n resolvedSrcDir = isAbsolute(rawSrcDir) ? rawSrcDir : resolve(root, rawSrcDir);\n projectRoot = root;\n widgetEntryPattern = getWidgetEntryPattern(resolvedSrcDir);\n }\n\n server.watcher.add(resolvedSrcDir);\n let knownInvalid = new Set<string>();\n const rescan = () => {\n try {\n const { valid, invalid } = scanWidgetsSync(resolvedSrcDir);\n const nextInvalid = new Set(invalid.map((widget) => widget.filePath));\n\n for (const filePath of nextInvalid) {\n if (!knownInvalid.has(filePath)) {\n server.config.logger.warn(\n `[belgie] widget file \"${relative(projectRoot, filePath)}\" is missing a default export — it won't be built until fixed.`,\n );\n }\n }\n for (const filePath of knownInvalid) {\n if (!nextInvalid.has(filePath)) {\n server.config.logger.info(`[belgie] widget file \"${relative(projectRoot, filePath)}\" resolved.`);\n }\n }\n knownInvalid = nextInvalid;\n\n assertUniqueWidgetNames(valid);\n widgetMap = new Map(valid.map((widget) => [widget.name, widget]));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n server.config.logger.error(`[belgie] widget rescan failed: ${message}`);\n }\n };\n\n rescan();\n server.watcher.on(\"add\", rescan);\n server.watcher.on(\"change\", rescan);\n server.watcher.on(\"unlink\", rescan);\n\n server.middlewares.use(async (request, response, next) => {\n try {\n const pathname = new URL(request.url ?? \"/\", \"http://localhost\").pathname;\n const match = /^\\/widgets\\/([^/]+)\\/index\\.html$/.exec(pathname);\n const name = match?.[1] === undefined ? undefined : decodeURIComponent(match[1]);\n if (name === undefined) {\n next();\n return;\n }\n if (!widgetMap.has(name)) {\n response.statusCode = 404;\n response.setHeader(\"Content-Type\", \"text/plain; charset=utf-8\");\n response.end(`Unknown widget: ${name}`);\n return;\n }\n const transformedHtml = await server.transformIndexHtml(\n pathname,\n renderWidgetHtmlDocument({ scripts: [`${VIRTUAL_PREFIX}${encodeURIComponent(name)}`] }),\n request.url,\n );\n const html = ensureReactRefreshPreamble(\n transformedHtml,\n server.config.base,\n server.config.plugins.some((plugin) => plugin.name === REACT_REFRESH_PLUGIN_NAME),\n );\n response.statusCode = 200;\n response.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\n response.end(html);\n } catch (error) {\n next(error);\n }\n });\n },\n\n transform(code, id) {\n const normalizedId = normalizePath(id);\n if (widgetEntryPattern?.test(normalizedId) && !hasDefaultExport(code)) {\n this.warn(`Widget file \"${normalizedId.split(\"/\").pop()}\" is missing a default export.`);\n }\n return null;\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vite.js","names":[],"sources":["../src/html.ts","../src/validate-widget.ts","../src/scan-widgets.ts","../src/vite.ts"],"sourcesContent":["export type WidgetHtmlDocumentOptions = {\n inlineScript?: string;\n inlineStyles?: string[];\n scripts?: string[];\n styles?: string[];\n};\n\nexport function escapeInlineScript(value: string): string {\n return value.replace(/<\\/script/gi, \"<\\\\/script\");\n}\n\nexport function escapeInlineStyle(value: string): string {\n return value.replace(/<\\/style/gi, \"<\\\\/style\");\n}\n\nexport function buildVirtualEntry(widgetFilePath: string): string {\n const normalized = widgetFilePath.replace(/\\\\/g, \"/\");\n return [\n `import { mountWidget } from \"@belgie/mcp\";`,\n `import Widget from ${JSON.stringify(normalized)};`,\n \"\",\n \"mountWidget(Widget);\",\n \"\",\n ].join(\"\\n\");\n}\n\nexport function renderWidgetHtmlDocument(options: WidgetHtmlDocumentOptions): string {\n const head = [\n '<meta charset=\"utf-8\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n ...(options.styles ?? []).map((href) => `<link rel=\"stylesheet\" crossorigin href=\"${href}\">`),\n ...(options.inlineStyles ?? []).map((style) => `<style>${escapeInlineStyle(style)}</style>`),\n ];\n const scripts = [\n ...(options.scripts ?? []).map((src) => `<script type=\"module\" crossorigin src=\"${src}\"></script>`),\n ...(options.inlineScript === undefined\n ? []\n : [`<script type=\"module\">${escapeInlineScript(options.inlineScript)}</script>`]),\n ];\n return [\n \"<!doctype html>\",\n \"<html>\",\n \"<head>\",\n ...head,\n \"</head>\",\n \"<body>\",\n '<div id=\"root\"></div>',\n ...scripts,\n \"</body>\",\n \"</html>\",\n \"\",\n ].join(\"\\n\");\n}\n","function stripComments(code: string): string {\n return code.replace(/\\/\\/.*$/gm, \"\").replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n}\n\nexport function hasDefaultExport(code: string): boolean {\n const stripped = stripComments(code);\n return (\n /export\\s+default\\s/.test(stripped) ||\n /export\\s*\\{[^}]*\\bas\\s+default\\b[^}]*}/.test(stripped)\n );\n}\n","import { globSync, readFileSync } from \"node:fs\";\nimport { basename, dirname, resolve } from \"node:path\";\n\nimport { hasDefaultExport } from \"./validate-widget.js\";\n\nexport type WidgetCandidate = {\n name: string;\n filePath: string;\n};\n\nexport type InvalidWidget = {\n filePath: string;\n};\n\nexport type WidgetScanResult = {\n valid: WidgetCandidate[];\n invalid: InvalidWidget[];\n};\n\nexport function scanWidgetsSync(srcDir: string): WidgetScanResult {\n const pattern = resolve(srcDir, \"*/widget.tsx\");\n const candidates = globSync(pattern).map((file) => ({\n name: basename(dirname(file)),\n filePath: file,\n }));\n\n const valid: WidgetCandidate[] = [];\n const invalid: InvalidWidget[] = [];\n for (const candidate of candidates) {\n const code = readFileSync(candidate.filePath, \"utf-8\");\n if (hasDefaultExport(code)) {\n valid.push(candidate);\n } else {\n invalid.push({ filePath: candidate.filePath });\n }\n }\n\n return { valid, invalid };\n}\n\nexport function assertUniqueWidgetNames(widgets: WidgetCandidate[]): void {\n const nameMap = new Map<string, string[]>();\n for (const widget of widgets) {\n const paths = nameMap.get(widget.name) ?? [];\n paths.push(widget.filePath);\n nameMap.set(widget.name, paths);\n }\n\n for (const [name, paths] of nameMap) {\n if (paths.length > 1) {\n throw new Error(\n `belgie: duplicate widget name \"${name}\" resolved from:\\n - ${paths.join(\"\\n - \")}\\nRename one of the files to avoid the conflict.`,\n );\n }\n }\n}\n\nexport function assertNoInvalidWidgets(invalid: InvalidWidget[]): void {\n if (invalid.length === 0) {\n return;\n }\n const paths = invalid.map((widget) => widget.filePath).join(\"\\n - \");\n throw new Error(\n `belgie: widget file(s) missing a default export:\\n - ${paths}\\nAdd a default export so the widget can be built.`,\n );\n}\n\nexport function discoverWidgetsSync(srcDir: string): WidgetCandidate[] {\n const { valid } = scanWidgetsSync(srcDir);\n assertUniqueWidgetNames(valid);\n return valid;\n}\n","import { rmSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\n\nimport { build, normalizePath, type Plugin, type ResolvedConfig, type UserConfig } from \"vite\";\n\nimport { buildVirtualEntry, renderWidgetHtmlDocument } from \"./html.js\";\nimport {\n assertNoInvalidWidgets,\n assertUniqueWidgetNames,\n scanWidgetsSync,\n type WidgetCandidate,\n} from \"./scan-widgets.js\";\nimport { hasDefaultExport } from \"./validate-widget.js\";\n\nconst VIRTUAL_PREFIX = \"/_belgie/widget/\";\nconst VIRTUAL_MODULE_PREFIX = \"\\0belgie:widget:\";\nconst ORCHESTRATION_ENTRY_ID = \"belgie:widget-build-orchestrator\";\nconst RESOLVED_ORCHESTRATION_ENTRY_ID = \"\\0belgie:widget-build-orchestrator\";\nconst INTERNAL_WIDGET_PATH_ENV = \"BELGIE_INTERNAL_WIDGET_PATH\";\nconst MAX_INLINE_ASSET_SIZE = Number.MAX_SAFE_INTEGER;\nconst REACT_REFRESH_PLUGIN_NAME = \"vite:react-refresh\";\nconst TEXT_DECODER = new TextDecoder();\n\nexport type BelgiePluginOptions = {\n srcDir?: string;\n};\n\ntype RollupInput = string | string[] | Record<string, string>;\n\ntype BuildAsset = {\n fileName: string;\n source: string | Uint8Array;\n type: \"asset\";\n};\n\ntype BuildChunk = {\n code: string;\n dynamicImports: string[];\n facadeModuleId: string | null;\n fileName: string;\n imports: string[];\n isEntry: boolean;\n type: \"chunk\";\n viteMetadata?: { importedCss?: Set<string> };\n};\n\ntype BuildArtifact = BuildAsset | BuildChunk;\n\nfunction getWidgetEntryPattern(srcDir: string): RegExp {\n const escaped = normalizePath(srcDir).replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(`${escaped}\\/[^/]+\\/widget\\\\.tsx(?:\\\\?.*)?$`);\n}\n\nfunction virtualWidgetName(id: string): string | undefined {\n if (!id.startsWith(VIRTUAL_PREFIX)) {\n return undefined;\n }\n return decodeURIComponent(id.slice(VIRTUAL_PREFIX.length).split(\"?\", 1)[0] ?? \"\");\n}\n\nfunction readAsset(asset: BuildAsset): string {\n return typeof asset.source === \"string\" ? asset.source : TEXT_DECODER.decode(asset.source);\n}\n\nfunction renderWidgetBundle(name: string, bundle: Record<string, BuildArtifact>): string {\n const artifacts = Object.values(bundle);\n const chunks = artifacts.filter((artifact): artifact is BuildChunk => artifact.type === \"chunk\");\n const entries = chunks.filter((chunk) => chunk.isEntry);\n if (entries.length !== 1) {\n throw new Error(`belgie: expected one entry chunk for widget \"${name}\", received ${entries.length}`);\n }\n\n const entry = entries[0]!;\n const extraChunks = chunks.filter((chunk) => chunk !== entry);\n if (extraChunks.length > 0) {\n throw new Error(\n `belgie: widget \"${name}\" emitted extra chunks: ${extraChunks.map((chunk) => chunk.fileName).join(\", \")}`,\n );\n }\n\n const imports = [...entry.imports, ...entry.dynamicImports].filter((item) => item !== entry.fileName);\n if (imports.length > 0) {\n throw new Error(`belgie: widget \"${name}\" retained imports: ${imports.join(\", \")}`);\n }\n\n const assets = artifacts.filter((artifact): artifact is BuildAsset => artifact.type === \"asset\");\n const nonCssAssets = assets.filter((asset) => !asset.fileName.endsWith(\".css\"));\n if (nonCssAssets.length > 0) {\n throw new Error(\n `belgie: widget \"${name}\" emitted non-CSS assets: ${nonCssAssets.map((asset) => asset.fileName).join(\", \")}`,\n );\n }\n\n const assetsByName = new Map(assets.map((asset) => [asset.fileName, asset]));\n const importedCss = [...(entry.viteMetadata?.importedCss ?? [])];\n const cssNames = importedCss.length > 0 ? importedCss : assets.map((asset) => asset.fileName).sort();\n const styles = cssNames.map((cssName) => {\n const asset = assetsByName.get(cssName);\n if (asset === undefined) {\n throw new Error(`belgie: widget \"${name}\" references missing CSS asset ${cssName}`);\n }\n return readAsset(asset);\n });\n return renderWidgetHtmlDocument({ inlineScript: entry.code, inlineStyles: styles });\n}\n\nfunction restoreEnvironment(name: string, previous: string | undefined): void {\n if (previous === undefined) {\n delete process.env[name];\n } else {\n process.env[name] = previous;\n }\n}\n\nfunction ensureReactRefreshPreamble(html: string, base: string, enabled: boolean): string {\n if (!enabled || html.includes(\"@react-refresh\")) {\n return html;\n }\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n const refreshPath = `${normalizedBase}@react-refresh`;\n const preamble = [\n '<script type=\"module\">',\n `import { injectIntoGlobalHook } from ${JSON.stringify(refreshPath)};`,\n \"injectIntoGlobalHook(window);\",\n \"window.$RefreshReg$ = () => {};\",\n \"window.$RefreshSig$ = () => (type) => type;\",\n \"</script>\",\n ].join(\"\\n\");\n return html.replace(\"<head>\", `<head>\\n${preamble}`);\n}\n\nasync function buildWidget(widget: WidgetCandidate, config: ResolvedConfig): Promise<void> {\n if (!config.configFile) {\n throw new Error(\n \"belgie: isolated widget builds require a Vite config file; inline configs are not supported\",\n );\n }\n const previousWidgetPath = process.env[INTERNAL_WIDGET_PATH_ENV];\n process.env[INTERNAL_WIDGET_PATH_ENV] = widget.filePath;\n try {\n await build({\n configFile: config.configFile,\n configLoader: \"native\",\n root: config.root,\n mode: config.mode,\n ...(config.logLevel === undefined ? {} : { logLevel: config.logLevel }),\n build: {\n emptyOutDir: false,\n outDir: \"dist\",\n },\n });\n } finally {\n restoreEnvironment(INTERNAL_WIDGET_PATH_ENV, previousWidgetPath);\n }\n}\n\nexport function belgie(options: BelgiePluginOptions = {}): Plugin {\n const rawSrcDir = options.srcDir ?? \"src/widgets\";\n const requestedWidgetPath = process.env[INTERNAL_WIDGET_PATH_ENV];\n let resolvedSrcDir = \"\";\n let projectRoot = \"\";\n let resolvedConfig: ResolvedConfig | undefined;\n let widgetMap = new Map<string, WidgetCandidate>();\n let widgetEntryPattern: RegExp | undefined;\n let usesOrchestrationEntry = false;\n let isBuildCommand = false;\n\n return {\n name: \"belgie\",\n enforce: \"pre\",\n api: { srcDir: rawSrcDir },\n\n config: {\n order: \"post\",\n handler(config: UserConfig, { command }) {\n isBuildCommand = command === \"build\";\n projectRoot = config.root || process.cwd();\n resolvedSrcDir = isAbsolute(rawSrcDir) ? rawSrcDir : resolve(projectRoot, rawSrcDir);\n widgetEntryPattern = getWidgetEntryPattern(resolvedSrcDir);\n\n const { valid, invalid } = scanWidgetsSync(resolvedSrcDir);\n assertUniqueWidgetNames(valid);\n if (command === \"build\") {\n assertNoInvalidWidgets(invalid);\n }\n\n if (requestedWidgetPath !== undefined) {\n const normalizedRequestedPath = normalizePath(resolve(requestedWidgetPath));\n const widget = valid.find((candidate) => normalizePath(resolve(candidate.filePath)) === normalizedRequestedPath);\n if (widget === undefined) {\n throw new Error(\n `belgie: isolated widget build requested unknown entry ${normalizePath(requestedWidgetPath)}`,\n );\n }\n widgetMap = new Map([[widget.name, widget]]);\n return {\n appType: \"custom\",\n resolve: { dedupe: [\"react\", \"react-dom\"] },\n build: {\n assetsInlineLimit: MAX_INLINE_ASSET_SIZE,\n copyPublicDir: false,\n cssCodeSplit: false,\n emptyOutDir: false,\n license: false,\n manifest: false,\n modulePreload: false,\n outDir: \"dist\",\n reportCompressedSize: false,\n sourcemap: false,\n ssrManifest: false,\n watch: null,\n write: true,\n rolldownOptions: {\n input: `${VIRTUAL_PREFIX}${encodeURIComponent(widget.name)}`,\n output: { codeSplitting: false },\n },\n },\n };\n }\n\n widgetMap = new Map(valid.map((widget) => [widget.name, widget]));\n const existingInput = config.build?.rolldownOptions?.input as RollupInput | undefined;\n usesOrchestrationEntry = existingInput === undefined;\n return {\n resolve: { dedupe: [\"react\", \"react-dom\"] },\n build: {\n rolldownOptions: {\n input: existingInput ?? ORCHESTRATION_ENTRY_ID,\n },\n },\n optimizeDeps: {\n entries: [`${resolvedSrcDir}/*/widget.tsx`],\n include: [\"react\", \"react-dom/client\", \"react/jsx-runtime\"],\n },\n };\n },\n },\n\n configResolved(config) {\n resolvedConfig = config;\n projectRoot = config.root;\n if (!resolvedSrcDir) {\n resolvedSrcDir = isAbsolute(rawSrcDir) ? rawSrcDir : resolve(projectRoot, rawSrcDir);\n }\n },\n\n resolveId(id) {\n if (id === ORCHESTRATION_ENTRY_ID) {\n return RESOLVED_ORCHESTRATION_ENTRY_ID;\n }\n const name = virtualWidgetName(id);\n if (name !== undefined && widgetMap.has(name)) {\n return `${VIRTUAL_MODULE_PREFIX}${name}`;\n }\n return null;\n },\n\n load(id) {\n if (id === RESOLVED_ORCHESTRATION_ENTRY_ID) {\n return \"export {};\\n\";\n }\n if (id.startsWith(VIRTUAL_MODULE_PREFIX)) {\n const widget = widgetMap.get(id.slice(VIRTUAL_MODULE_PREFIX.length));\n if (widget !== undefined) {\n return buildVirtualEntry(widget.filePath);\n }\n }\n return null;\n },\n\n generateBundle: {\n order: \"post\",\n handler(_options, bundle) {\n if (requestedWidgetPath !== undefined) {\n const widget = [...widgetMap.values()][0];\n if (widget === undefined) {\n throw new Error(\"belgie: isolated widget build lost its widget entry\");\n }\n const html = renderWidgetBundle(widget.name, bundle as Record<string, BuildArtifact>);\n for (const fileName of Object.keys(bundle)) {\n delete bundle[fileName];\n }\n this.emitFile({\n type: \"asset\",\n fileName: `widgets/${widget.name}/index.html`,\n source: html,\n });\n return;\n }\n\n if (usesOrchestrationEntry) {\n for (const [fileName, artifact] of Object.entries(bundle)) {\n if (artifact.type === \"chunk\" && artifact.facadeModuleId === RESOLVED_ORCHESTRATION_ENTRY_ID) {\n delete bundle[fileName];\n }\n }\n }\n },\n },\n\n async closeBundle() {\n if (!isBuildCommand || requestedWidgetPath !== undefined || resolvedConfig === undefined || widgetMap.size === 0) {\n return;\n }\n if (!resolvedConfig.configFile) {\n throw new Error(\n \"belgie: isolated widget builds require a Vite config file; inline configs are not supported\",\n );\n }\n rmSync(resolve(projectRoot, \"dist\", \"widgets\"), { recursive: true, force: true });\n for (const widget of widgetMap.values()) {\n await buildWidget(widget, resolvedConfig);\n }\n },\n\n configureServer(server) {\n if (!resolvedSrcDir) {\n const root = server.config.root || process.cwd();\n resolvedSrcDir = isAbsolute(rawSrcDir) ? rawSrcDir : resolve(root, rawSrcDir);\n projectRoot = root;\n widgetEntryPattern = getWidgetEntryPattern(resolvedSrcDir);\n }\n\n server.watcher.add(resolvedSrcDir);\n let knownInvalid = new Set<string>();\n const rescan = () => {\n try {\n const { valid, invalid } = scanWidgetsSync(resolvedSrcDir);\n const nextInvalid = new Set(invalid.map((widget) => widget.filePath));\n\n for (const filePath of nextInvalid) {\n if (!knownInvalid.has(filePath)) {\n server.config.logger.warn(\n `[belgie] widget file \"${relative(projectRoot, filePath)}\" is missing a default export — it won't be built until fixed.`,\n );\n }\n }\n for (const filePath of knownInvalid) {\n if (!nextInvalid.has(filePath)) {\n server.config.logger.info(`[belgie] widget file \"${relative(projectRoot, filePath)}\" resolved.`);\n }\n }\n knownInvalid = nextInvalid;\n\n assertUniqueWidgetNames(valid);\n widgetMap = new Map(valid.map((widget) => [widget.name, widget]));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n server.config.logger.error(`[belgie] widget rescan failed: ${message}`);\n }\n };\n\n rescan();\n server.watcher.on(\"add\", rescan);\n server.watcher.on(\"change\", rescan);\n server.watcher.on(\"unlink\", rescan);\n\n server.middlewares.use(async (request, response, next) => {\n try {\n const pathname = new URL(request.url ?? \"/\", \"http://localhost\").pathname;\n const match = /^\\/widgets\\/([^/]+)\\/index\\.html$/.exec(pathname);\n const name = match?.[1] === undefined ? undefined : decodeURIComponent(match[1]);\n if (name === undefined) {\n next();\n return;\n }\n if (!widgetMap.has(name)) {\n response.statusCode = 404;\n response.setHeader(\"Content-Type\", \"text/plain; charset=utf-8\");\n response.end(`Unknown widget: ${name}`);\n return;\n }\n const transformedHtml = await server.transformIndexHtml(\n pathname,\n renderWidgetHtmlDocument({ scripts: [`${VIRTUAL_PREFIX}${encodeURIComponent(name)}`] }),\n request.url,\n );\n const html = ensureReactRefreshPreamble(\n transformedHtml,\n server.config.base,\n server.config.plugins.some((plugin) => plugin.name === REACT_REFRESH_PLUGIN_NAME),\n );\n response.statusCode = 200;\n response.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\n response.end(html);\n } catch (error) {\n next(error);\n }\n });\n },\n\n transform(code, id) {\n if (widgetEntryPattern?.test(id) && !hasDefaultExport(code)) {\n this.warn(`Widget file \"${id.split(\"/\").pop()}\" is missing a default export.`);\n }\n return null;\n },\n };\n}\n"],"mappings":"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"}
|