diff --git a/scripts/bom-gen.ts b/scripts/bom-gen.ts index 5b954fe..68d1908 100644 --- a/scripts/bom-gen.ts +++ b/scripts/bom-gen.ts @@ -1,22 +1,11 @@ -#!/usr/bin/env node +#!/usr/bin/env tsx // BOM generator — walks asset directories, lists files, prompts for descriptions, outputs BOM.yaml -// -// Usage: -// npx tsx scripts/bom-gen.ts [asset-root] -// -// Expected directory structure: -// audio/ — audio files -// images/ — image files -// fonts/ — font files -// videos/ — material video clips -// -// Output: BOM.yaml (YAML frontmatter-style) import { readdirSync, statSync, writeFileSync } from "node:fs"; -import { resolve, relative, join } from "node:path"; +import { resolve, relative } from "node:path"; import { createInterface } from "node:readline"; -type Asset = { path: string; size: number; description: string }; +type Asset = { path: string; size: number; description: string; hash: string }; const ASSET_DIRS = ["audio", "images", "fonts", "videos"]; @@ -27,10 +16,16 @@ function walk(dir: string): Asset[] { if (entry.isDirectory()) { assets.push(...walk(full)); } else { + const s = statSync(full); + const content = readFileSync(full); + // Simple hash: first 16 chars of node hash + const { createHash } = await import("node:crypto"); + const hash = createHash("md5").update(content).digest("hex").slice(0, 8); assets.push({ path: relative(".", full), - size: statSync(full).size, + size: s.size, description: "", + hash, }); } } @@ -84,11 +79,13 @@ async function main() { )).trim(); } - // Build YAML manually (no dependency) + // Build YAML let yaml = "---\nbom:\n"; for (const a of all) { - const desc = a.description.replace(/"/g, '\\"'); - yaml += ` ${a.path}:\n description: "${desc}"\n`; + yaml += ` - file: ${a.path}\n`; + yaml += ` size: ${a.size}\n`; + yaml += ` hash: ${a.hash}\n`; + yaml += ` description: "${a.description.replace(/"/g, '\\"')}"\n`; } yaml += `total_files: ${all.length}\ntotal_size: ${totalSize}\n...`;