()
| 292 | let cached: { readonly html: string; readonly url: string } | undefined; |
| 293 | |
| 294 | const load = async (): Promise<{ readonly html: string; readonly url: string }> => { |
| 295 | if (cached) return cached; |
| 296 | const html = await buildMcpAppsShellHtml(); |
| 297 | // Build-blocking: runtime loaders authenticate the document by this |
| 298 | // fragment (an ASSETS-binding miss under SPA not-found handling answers |
| 299 | // with index.html and a 200), so a shell that lost it would make every |
| 300 | // deployed resource read fail. Catch that here, in the build. |
| 301 | if (!html.includes(MCP_APPS_SHELL_DOCUMENT_MARKER)) { |
| 302 | // oxlint-disable-next-line executor/no-try-catch-or-throw, executor/no-error-constructor -- boundary: Vite plugin hooks report build failures by throwing |
| 303 | throw new Error( |
| 304 | `Built MCP-Apps shell is missing its identity marker (${MCP_APPS_SHELL_DOCUMENT_MARKER}); ` + |
| 305 | "check the <meta> in src/shell/mcp-app.html.", |
| 306 | ); |
| 307 | } |
| 308 | const digest = createHash("sha256").update(html).digest("hex").slice(0, 12); |
| 309 | cached = { html, url: `/assets/executor-mcp-apps-shell-${digest}.html` }; |
| 310 | return cached; |
| 311 | }; |
| 312 | |
| 313 | return { |
| 314 | name: "executor-mcp-apps-shell-asset", |
no test coverage detected