#!/usr/bin/env node /** * dist-hash.mjs — 计算构建产物的确定性指纹。 * * 用于「主站 + 镜像内容一致性校验」(验收:两边构建产物 hash 相同)。 * 因为 Astro 资源名是内容哈希、构建确定性,相同源码 → 相同 dist → 相同指纹。 * CI 在主站与镜像两路构建后比对本指纹即可断言一致。 * * 算法:对 dist 下所有文件按「相对路径\0sha256」排序后再求总 sha256。 */ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs'; import { createHash } from 'node:crypto'; import { join, resolve, relative } from 'node:path'; const DIST = resolve(process.argv[2] ?? 'dist'); if (!existsSync(DIST)) { console.error(`[dist-hash] 找不到 ${DIST}`); process.exit(2); } function walk(dir) { const out = []; for (const name of readdirSync(dir)) { const p = join(dir, name); const st = statSync(p); if (st.isDirectory()) out.push(...walk(p)); else out.push(p); } return out; } const entries = walk(DIST) .map((p) => { const rel = relative(DIST, p).split('\\').join('/'); const h = createHash('sha256').update(readFileSync(p)).digest('hex'); return `${rel}\0${h}`; }) .sort(); const fingerprint = createHash('sha256').update(entries.join('\n'), 'utf8').digest('hex'); console.log(fingerprint);