e32d59ca44
- scripts/make-verify-json.js: 산출물 폴더 → extras/assets JSON 생성 - scripts/verify.js: JSON 입력으로 무결성 검증(종료코드 반영) - package.json: verify 스크립트 추가 - .gitea/workflows/ci.yml: ./artifacts/export 존재 시 검증 스텝 실행
48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
export type ListDir = (dir: string) => Promise<string[]>
|
|
export type ReadFile = (path: string) => Promise<Uint8Array>
|
|
|
|
function toBase64(u8: Uint8Array): string {
|
|
if (typeof Buffer !== 'undefined') return Buffer.from(u8).toString('base64')
|
|
throw new Error('Buffer not available')
|
|
}
|
|
|
|
// Generate inputs for verify CLI from a folder tree.
|
|
// - root: export folder (contains assets.integrity.index.json and assets/*)
|
|
// - listDir: returns list of file paths under root (can be recursive listing)
|
|
// - readFile: reads a file into bytes
|
|
export async function generateVerifyInputs(
|
|
root: string,
|
|
listDir: ListDir,
|
|
readFile: ReadFile
|
|
): Promise<{ extras: Record<string, string>; assets: Record<string, string> }> {
|
|
const all = await listDir(root)
|
|
const norm = (p: string) => p.replace(/\\/g, '/')
|
|
const rootNorm = norm(root).replace(/\/$/, '')
|
|
const rel = (p: string) => {
|
|
const pn = norm(p)
|
|
return pn.startsWith(rootNorm + '/') ? pn.slice(rootNorm.length + 1) : pn
|
|
}
|
|
|
|
const extras: Record<string, string> = {}
|
|
const assets: Record<string, string> = {}
|
|
|
|
// assets.integrity.index.json at root
|
|
const integrityPath = all.find((p) => rel(p) === 'assets.integrity.index.json')
|
|
if (integrityPath) {
|
|
const bytes = await readFile(integrityPath)
|
|
extras['assets.integrity.index.json'] = toBase64(bytes)
|
|
}
|
|
|
|
// collect assets/**/*
|
|
for (const abs of all) {
|
|
const r = rel(abs)
|
|
if (!r.startsWith('assets/')) continue
|
|
// skip directories: best-effort by checking trailing slash
|
|
if (r.endsWith('/')) continue
|
|
const bytes = await readFile(abs)
|
|
assets[r] = toBase64(bytes)
|
|
}
|
|
|
|
return { extras, assets }
|
|
}
|