import fs from "node:fs"; import path from "node:path"; import crypto from "node:crypto"; import { fileURLToPath } from "node:url"; const hash = (bytes) => crypto.createHash("sha256").update(bytes).digest("hex"); export function syncWebEngineRuntime(root) { const build = path.join(root, "build_web_blender6/bin"); const wasm = fs.readFileSync(path.join(build, "web_engine.wasm")); const loader = fs.readFileSync(path.join(build, "web_engine.js")); if (!WebAssembly.validate(wasm) || !loader.length) throw new Error("compiled WebEngine artifacts are invalid"); const manifestPath = path.join(root, "web/app/public/wasm-module-manifest.json"); const original = fs.readFileSync(manifestPath, "utf8"); const manifest = JSON.parse(original); const artifactHashes = { "web_engine.wasm": hash(wasm), "web_engine.js": hash(loader) }; let bindings = 0; for (const module of manifest.modules ?? []) { for (const resource of Object.values(module.resources ?? {})) { for (const [name, digest] of Object.entries(artifactHashes)) { if (resource.url === `/vendor/blender/${name}`) { resource.sha256 = digest; bindings += 1; } } } } if (!bindings) throw new Error("runtime manifest has no compiled WebEngine binding"); const changed = []; const write = (destination, data) => { if (fs.existsSync(destination) && fs.readFileSync(destination).equals(Buffer.from(data))) return; fs.mkdirSync(path.dirname(destination), { recursive: true }); const temporary = `${destination}.tmp-${process.pid}`; fs.writeFileSync(temporary, data); fs.renameSync(temporary, destination); changed.push(path.relative(root, destination)); }; for (const directory of ["web/app/src/vendor/blender", "web/app/public/vendor/blender"]) { write(path.join(root, directory, "web_engine.js"), loader); write(path.join(root, directory, "web_engine.wasm"), wasm); } write(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`); return { operation: "sync_compiled_runtime", status: "PASS", changed, bindings, artifactHashes }; } if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { console.log(JSON.stringify(syncWebEngineRuntime(path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..")))); }