| 369 | }); |
| 370 | }, |
| 371 | async generateBundle(_options, _bundle, _isWrite) { |
| 372 | if (command !== "build") return; |
| 373 | |
| 374 | // Client output only. A multi-environment build (TanStack Start on cloud |
| 375 | // emits `dist/client` and `dist/server`) runs this hook once per |
| 376 | // environment, and `dist/server` IS the deployed Worker — emitting 4.5 MB |
| 377 | // of browser document there would inflate the Worker bundle with |
| 378 | // something only the browser ever fetches, over the ASSETS binding, from |
| 379 | // `dist/client`. |
| 380 | // |
| 381 | // The hook's own environment is the authority, because it is the only |
| 382 | // signal that is per-bundle: `configResolved`'s `build.ssr` is recorded |
| 383 | // once per environment on this shared plugin instance, so by the time any |
| 384 | // bundle is generated it holds whichever environment resolved last. A |
| 385 | // single-environment build (selfhost) reports no environment, and falls |
| 386 | // back to that flag, where the two do agree. |
| 387 | const consumer = this.environment?.config?.consumer; |
| 388 | if (consumer === undefined ? ssr : consumer !== "client") return; |
| 389 | |
| 390 | const { html, url } = await load(); |
| 391 | // `emitFile` puts the document through Rollup's own output writer, so it |
| 392 | // lands in whatever client outDir the app (or its framework plugin) |
| 393 | // configured — which `process.cwd()`-relative writes get wrong for |
| 394 | // TanStack Start, where the client build writes to `dist/client`. |
| 395 | this.emitFile({ type: "asset", fileName: url.replace(/^\//, ""), source: html }); |
| 396 | // A second copy at the STABLE name, for the server side: a Workers host |
| 397 | // serves the `ui://executor/shell.html` MCP resource by fetching this |
| 398 | // through its ASSETS binding (`makeAssetsShellHtmlLoader`), and the |
| 399 | // self-host image reads it from the SPA dist on disk — neither can know |
| 400 | // the content hash the client build minted. See `./shell-asset-path`. |
| 401 | this.emitFile({ |
| 402 | type: "asset", |
| 403 | fileName: MCP_APPS_SHELL_STABLE_ASSET_PATH.replace(/^\//, ""), |
| 404 | source: html, |
| 405 | }); |
| 406 | }, |
| 407 | async closeBundle() { |
| 408 | cached = undefined; |
| 409 | }, |