#!/usr/bin/env node /** * Build script — compiles each app in src/apps/* into a single HTML file at dist/app-ui/{name}.html * Uses Vite + vite-plugin-singlefile to inline all JS/CSS/assets. */ import { build } from 'vite'; import { viteSingleFile } from 'vite-plugin-singlefile'; import { readdirSync, existsSync, mkdirSync } from 'fs'; import { resolve, join } from 'path'; const appsDir = resolve('src/apps'); const distDir = resolve('dist/app-ui'); if (!existsSync(distDir)) mkdirSync(distDir, { recursive: true }); const apps = readdirSync(appsDir).filter(d => { const indexHtml = join(appsDir, d, 'index.html'); return existsSync(indexHtml); }); console.log(`Building ${apps.length} MCP Apps...\n`); for (const app of apps) { const appDir = join(appsDir, app); const outDir = join(distDir); console.log(` Building: ${app}...`); try { await build({ root: appDir, plugins: [viteSingleFile()], build: { outDir, emptyOutDir: false, rollupOptions: { input: join(appDir, 'index.html'), output: { entryFileNames: `${app}.js`, assetFileNames: `${app}.[ext]`, } }, minify: 'esbuild', }, resolve: { alias: { '@components': resolve('src/components'), '@hooks': resolve('src/hooks'), '@styles': resolve('src/styles'), '@utils': resolve('src/utils'), } }, logLevel: 'warn', }); // Rename index.html to {app-name}.html const { renameSync } = await import('fs'); const srcPath = join(outDir, 'index.html'); const destPath = join(outDir, `${app}.html`); if (existsSync(srcPath) && srcPath !== destPath) { renameSync(srcPath, destPath); } console.log(` ✓ ${app} → dist/app-ui/${app}.html`); } catch (err) { console.error(` ✗ ${app} failed:`, err.message); } } console.log(`\nDone! ${apps.length} apps built.`);