const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const roots = { frontend: process.argv[2], player: process.argv[3] }; const outDir = path.join(__dirname, 'ui-updates'); const filesDir = path.join(outDir, 'files'); const keyPath = process.env.VYLA_UI_KEY || path.join(__dirname, 'ui-private.pem'); fs.rmSync(outDir, { recursive: true, force: true }); fs.mkdirSync(filesDir, { recursive: true }); fs.writeFileSync(path.join(outDir, '.gitattributes'), '* -text\n'); const files = []; const walk = (src, rel) => { for (const name of fs.readdirSync(src)) { if (name === 'node_modules' || name === '.git') continue; const full = path.join(src, name); const r = `${rel}/${name}`; const st = fs.lstatSync(full); if (st.isDirectory()) { walk(full, r); } else if (st.isFile()) { const data = fs.readFileSync(full); const dest = path.join(filesDir, ...r.split('/')); fs.mkdirSync(path.dirname(dest), { recursive: true }); fs.writeFileSync(dest, data); files.push({ path: r, sha256: crypto.createHash('sha256').update(data).digest('hex'), size: data.length }); } } }; for (const [root, src] of Object.entries(roots)) { if (!src || !fs.existsSync(src)) { console.error(`Missing source dir for ${root}`); process.exit(1); } walk(path.resolve(src), root); } const raw = Buffer.from(JSON.stringify({ seq: Math.floor(Date.now() / 1000), files })); const sig = crypto.sign(null, raw, crypto.createPrivateKey(fs.readFileSync(keyPath))); fs.writeFileSync(path.join(outDir, 'files-manifest.json'), raw); fs.writeFileSync(path.join(outDir, 'files-manifest.sig'), sig.toString('base64')); console.log(`${files.length} files signed`);