/** * Build script for ProxmoxPanel Alpine frontend. * - Bundles Swup into an IIFE (browser-loadable) * - Bundles xterm.js + addon-fit into IIFEs * - Copies all static assets to dist/ */ import * as esbuild from 'esbuild' import * as fs from 'fs' import * as path from 'path' const dist = 'dist' // Clean dist fs.rmSync(dist, { recursive: true, force: true }) fs.mkdirSync(`${dist}/js/vendors`, { recursive: true }) fs.mkdirSync(`${dist}/js`, { recursive: true }) fs.mkdirSync(`${dist}/css`, { recursive: true }) fs.mkdirSync(`${dist}/locales`, { recursive: true }) // 1. Bundle Swup into IIFE console.log('Bundling Swup...') await esbuild.build({ entryPoints: ['swup-bundle.entry.mjs'], bundle: true, format: 'iife', globalName: '_swupExports', outfile: `${dist}/js/vendors/swup.iife.js`, minify: true, }) // Expose Swup on window const swupOut = fs.readFileSync(`${dist}/js/vendors/swup.iife.js`, 'utf8') fs.writeFileSync(`${dist}/js/vendors/swup.iife.js`, swupOut + '\nwindow.Swup=_swupExports.Swup;') // 2. Bundle xterm.js console.log('Bundling xterm...') await esbuild.build({ entryPoints: ['xterm-bundle.entry.mjs'], bundle: true, format: 'iife', globalName: '_xtermExports', outfile: `${dist}/js/vendors/xterm.iife.js`, minify: true, }) const xtermOut = fs.readFileSync(`${dist}/js/vendors/xterm.iife.js`, 'utf8') fs.writeFileSync(`${dist}/js/vendors/xterm.iife.js`, xtermOut + '\nwindow.Terminal=_xtermExports.Terminal;window.FitAddon=_xtermExports.FitAddon;') // xterm CSS const xtermCss = 'node_modules/@xterm/xterm/css/xterm.css' if (fs.existsSync(xtermCss)) { fs.copyFileSync(xtermCss, `${dist}/css/xterm.css`) } // 3. Copy pre-downloaded vendors (Alpine, HTMX) for (const f of ['alpine.min.js', 'htmx.min.js']) { const src = `vendors/${f}` if (fs.existsSync(src)) { fs.copyFileSync(src, `${dist}/js/vendors/${f}`) console.log(`Copied ${f}`) } else { console.warn(`WARN: ${src} not found`) } } // 4. Copy app JS files for (const f of fs.readdirSync('js')) { if (f.endsWith('.js')) { fs.mkdirSync(`${dist}/js`, { recursive: true }) fs.copyFileSync(`js/${f}`, `${dist}/js/${f}`) } } // Service Worker doit être servi depuis la racine pour avoir le bon scope if (fs.existsSync('js/ws.sw.js')) { fs.copyFileSync('js/ws.sw.js', `${dist}/ws.sw.js`) } // 5. Copy CSS for (const f of fs.readdirSync('css')) { fs.copyFileSync(`css/${f}`, `${dist}/css/${f}`) } // 6. Copy locales for (const f of fs.readdirSync('locales')) { fs.copyFileSync(`locales/${f}`, `${dist}/locales/${f}`) } // 7. Copy HTML pages for (const f of fs.readdirSync('.')) { if (f.endsWith('.html')) { fs.copyFileSync(f, `${dist}/${f}`) } } // 8. Copy manifest.json if (fs.existsSync('manifest.json')) { fs.copyFileSync('manifest.json', `${dist}/manifest.json`) console.log('Copied manifest.json') } // 9. Copy icons/ if (fs.existsSync('icons')) { fs.mkdirSync(`${dist}/icons`, { recursive: true }) for (const f of fs.readdirSync('icons')) { fs.copyFileSync(`icons/${f}`, `${dist}/icons/${f}`) } console.log('Copied icons/') } console.log('✓ Build complete → dist/')