54 lines
2.3 KiB
JavaScript
54 lines
2.3 KiB
JavaScript
import { readFileSync } from "node:fs";
|
|||
|
|
import { createHash } from "node:crypto";
|
||
|
|
import { resolve } from "node:path";
|
||
|
|
import { pathToFileURL } from "node:url";
|
||
|
|
|
||
|
|
// 빌드가 성공해도 public 파일이 빠지면 게임은 실행 중 실패한다. 따라서 배포
|
||
|
|
// 폴더 자체의 파일 해시를 원본 manifest와 비교하는 계약을 빌드 마지막에 둔다.
|
||
|
|
export function verifyBuild(directory) {
|
||
|
|
// 번들에 실제 포함되는 전이 의존성도 잠금 파일에서 찾는다. 프로젝트의
|
||
|
|
// 비공개 라이선스와 별개로 설치된 MIT 전문·버전을 사본 세 곳에서 보존한다.
|
||
|
|
try {
|
||
|
|
const notice = readFileSync("THIRD_PARTY_NOTICES.md", "utf8");
|
||
|
|
const lock = JSON.parse(readFileSync("package-lock.json", "utf8"));
|
||
|
|
for (const [path, pkg] of Object.entries(lock.packages)) {
|
||
|
|
if (!path || pkg.dev) continue;
|
||
|
|
const name = path.split("node_modules/").at(-1);
|
||
|
|
const license = readFileSync(`${path}/LICENSE`, "utf8").trim();
|
||
|
|
if (!notice.includes(`## ${name} ${pkg.version}\n\n${license}`))
|
||
|
|
throw new Error(`${name} ${pkg.version}의 전문이 없습니다.`);
|
||
|
|
}
|
||
|
|
for (const path of [
|
||
|
|
"public/THIRD_PARTY_NOTICES.md",
|
||
|
|
resolve(directory, "THIRD_PARTY_NOTICES.md"),
|
||
|
|
]) {
|
||
|
|
if (readFileSync(path, "utf8") !== notice)
|
||
|
|
throw new Error(`${path}가 원본과 다릅니다.`);
|
||
|
|
}
|
||
|
|
} catch (cause) {
|
||
|
|
throw new Error("런타임 의존성 notice 누락 또는 불일치", { cause });
|
||
|
|
}
|
||
|
|
const manifest = JSON.parse(
|
||
|
|
readFileSync("public/audio/manifest.json", "utf8"),
|
||
|
|
);
|
||
|
|
const builtManifest = JSON.parse(
|
||
|
|
readFileSync(resolve(directory, "audio/manifest.json"), "utf8"),
|
||
|
|
);
|
||
|
|
if (JSON.stringify(manifest) !== JSON.stringify(builtManifest))
|
||
|
|
throw new Error("빌드 음성 목록이 원본과 다릅니다.");
|
||
|
|
for (const entry of manifest.files) {
|
||
|
|
const bytes = readFileSync(resolve(directory, "audio", entry.file));
|
||
|
|
if (createHash("sha256").update(bytes).digest("hex") !== entry.sha256)
|
||
|
|
throw new Error(`빌드 자산 해시 불일치: ${entry.file}`);
|
||
|
|
}
|
||
|
|
return manifest.files.length;
|
||
|
|
}
|
||
|
|
if (
|
||
|
|
process.argv[1] &&
|
||
|
|
import.meta.url === pathToFileURL(resolve(process.argv[1])).href
|
||
|
|
) {
|
||
|
|
console.log(
|
||
|
|
`빌드 음성 자산 ${verifyBuild("dist")}개 및 런타임 notice 전문 확인`,
|
||
|
|
);
|
||
|
|
}
|