import { createHash } from "node:crypto"; import { readFile, writeFile, readdir } from "node:fs/promises"; import path from "node:path"; const PLACEHOLDER = "__ASSET_VERSION__"; const root = path.resolve(process.argv[2] || process.cwd()); const assetRoots = ["public", "shared"]; async function walk(directory) { const entries = await readdir(directory, { withFileTypes: true }); const files = await Promise.all( entries.map((entry) => { const target = path.join(directory, entry.name); return entry.isDirectory() ? walk(target) : target; }), ); return files.flat().sort(); } const files = ( await Promise.all(assetRoots.map((directory) => walk(path.join(root, directory)))) ).flat(); const sources = await Promise.all(files.map((file) => readFile(file, "utf8"))); const version = createHash("sha256") .update(files.map((file, index) => `${path.relative(root, file)}\0${sources[index]}`).join("\0")) .digest("hex") .slice(0, 16); let replacements = 0; await Promise.all( files.map(async (file, index) => { const source = sources[index]; const count = source.split(PLACEHOLDER).length - 1; if (!count) return; replacements += count; await writeFile(file, source.replaceAll(PLACEHOLDER, version)); }), ); if (!replacements) throw new Error(`No ${PLACEHOLDER} markers found under ${assetRoots.join(", ")}.`); console.log(`Stamped ${replacements} asset references with version ${version}.`);