import { readdirSync, readFileSync, rmSync, statSync } from 'node:fs'; import { join, resolve } from 'node:path'; import { gzipSync } from 'node:zlib'; import { svelte } from '@sveltejs/vite-plugin-svelte'; import { build } from 'vite'; const root = process.cwd(); const outDir = resolve(root, 'build/.bundle-smoke'); const virtualId = 'virtual:active-app-smoke'; const resolvedVirtualId = `\0${virtualId}`; const maxGzipKb = Number(process.env.ACTIVE_BUNDLE_GZIP_LIMIT_KB ?? 70); const alias = { $aapp: resolve(root, 'src/arts/aapp'), $adom: resolve(root, 'src/arts/adom'), $auth: resolve(root, 'src/arts/auth'), $cach: resolve(root, 'src/arts/cach'), $conn: resolve(root, 'src/arts/conn'), $fend: resolve(root, 'src/arts/fend'), $fmts: resolve(root, 'src/arts/fmts'), $http: resolve(root, 'src/arts/http'), $lang: resolve(root, 'src/arts/lang'), $libs: resolve(root, 'src/libs'), $locale: resolve(root, 'src/libs/locale'), $logr: resolve(root, 'src/arts/logr'), $perm: resolve(root, 'src/arts/perm'), $reactive: resolve(root, 'src/libs/reactive'), $sess: resolve(root, 'src/arts/sess'), $sium: resolve(root, 'src/arts/sium'), $stor: resolve(root, 'src/arts/stor'), $svrs: resolve(root, 'src/svrs'), $timr: resolve(root, 'src/arts/timr') }; rmSync(outDir, { recursive: true, force: true }); await build({ root, configFile: false, logLevel: 'silent', plugins: [ svelte({ compilerOptions: { runes: true } }), { name: 'active-app-smoke-entry', resolveId(id) { return id === virtualId ? resolvedVirtualId : undefined; }, load(id) { if (id !== resolvedVirtualId) return undefined; return [ "import { createActiveApp } from '$aapp/active-app.svelte';", "import { LogLevel } from '$logr/types';", 'const App = createActiveApp({ logger: { level: LogLevel.NONE, transports: [] } });', 'App.dispose();', 'export default App;' ].join('\n'); } } ], resolve: { alias }, build: { emptyOutDir: true, minify: 'oxc', outDir, rollupOptions: { input: virtualId, output: { chunkFileNames: 'chunks/[name]-[hash].js', entryFileNames: 'entry.js', format: 'es' } }, sourcemap: false } }); const jsFiles = listFiles(outDir).filter((file) => file.endsWith('.js')); const rawBytes = jsFiles.reduce((sum, file) => sum + statSync(file).size, 0); const gzBytes = gzipSync(Buffer.concat(jsFiles.map((file) => readFileSync(file)))).byteLength; const rawKb = bytesToKb(rawBytes); const gzKb = bytesToKb(gzBytes); console.log( `active bundle smoke: ${gzKb.toFixed(2)} KB gzip (${rawKb.toFixed(2)} KB raw, ${jsFiles.length} JS file)` ); if (gzKb > maxGzipKb) { console.error( `active bundle smoke exceeded ${maxGzipKb.toFixed(2)} KB gzip. Current: ${gzKb.toFixed(2)} KB.` ); process.exitCode = 1; } function listFiles(dir) { return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => { const path = join(dir, entry.name); return entry.isDirectory() ? listFiles(path) : [path]; }); } function bytesToKb(bytes) { return bytes / 1024; }