Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"scripts": {
"prepare": "husky",
"build:frontend": "tsx src/bridges/user/web/build.ts",
"build": "pnpm build:frontend && tsc && printf '#!/usr/bin/env node\n' | cat - dist/cli.js > dist/cli.tmp && mv dist/cli.tmp dist/cli.js",
"build": "pnpm build:frontend && tsc && tsx scripts/copy-web-assets.ts && printf '#!/usr/bin/env node\n' | cat - dist/cli.js > dist/cli.tmp && mv dist/cli.tmp dist/cli.js",
"generate:server-json": "tsx scripts/sync-release-metadata.ts",
"publish:mcp-registry": "tsx scripts/publish-mcp-registry.ts",
"lint": "eslint .",
Expand Down
35 changes: 35 additions & 0 deletions scripts/copy-web-assets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copy the built web frontend assets into the compiled output tree.
*
* `build:frontend` (esbuild) emits the bundles into
* `src/bridges/user/web/dist/`, and `index.html` lives alongside the frontend
* sources. `tsc` only emits JS/d.ts from `.ts` inputs, so these non-TS assets
* are never copied into the top-level `dist/`. Without this step the published
* package is missing `frontend/index.html`, `dist/bundle.js`, `dist/sw.js`,
* `dist/manifest.json` and `dist/icons/*`, and the web server crashes with
* ENOENT at module load — taking down every command, including setup. See #18.
*
* Usage: node/tsx scripts/copy-web-assets.ts (run after `tsc`)
*/

import * as fs from "node:fs";
import * as path from "node:path";
import { fileURLToPath } from "node:url";

const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const webSrc = path.join(root, "src", "bridges", "user", "web");
const webOut = path.join(root, "dist", "bridges", "user", "web");

// Frontend shell (loaded by the server as INDEX_HTML). cpSync creates the
// destination parent dir itself.
fs.cpSync(
path.join(webSrc, "frontend", "index.html"),
path.join(webOut, "frontend", "index.html"),
);

// esbuild bundles + web app manifest + PWA icons.
fs.cpSync(path.join(webSrc, "dist"), path.join(webOut, "dist"), {
recursive: true,
});

console.log(`Copied web assets to ${webOut}`);
4 changes: 4 additions & 0 deletions src/bridges/user/web/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ const inlineCssPlugin: esbuild.Plugin = {
};

async function main(): Promise<void> {
// Start from a clean output dir so stale artifacts (e.g. renamed bundles,
// leftover sourcemaps) can't linger and get swept into the published
// package by the copy-web-assets step.
fs.rmSync(DIST_DIR, { recursive: true, force: true });
fs.mkdirSync(DIST_DIR, { recursive: true });

await esbuild.build({
Expand Down