import { createHash } from 'node:crypto'; import { readdir, readFile, stat, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const excludedDirectories = new Set(['.git', 'dist', 'node_modules', 'ForgeFlow-runtime-win-x64']); const excludedFiles = new Set(['SOURCE_MANIFEST.txt']); async function collect(directory, output = []) { for (const entry of await readdir(directory, { withFileTypes: true })) { if (excludedDirectories.has(entry.name)) continue; const absolute = path.join(directory, entry.name); if (entry.isDirectory()) await collect(absolute, output); else if (!excludedFiles.has(entry.name)) output.push(absolute); } return output; } const packageJson = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8')); const files = (await collect(root)).sort((left, right) => left.localeCompare(right, 'en')); const lines = [ `ForgeFlow ${packageJson.version} source manifest`, 'SHA-256 BYTES PATH', '(The manifest excludes itself, dependencies and generated release artifacts.)' ]; for (const absolute of files) { const bytes = await readFile(absolute); const size = (await stat(absolute)).size; const digest = createHash('sha256').update(bytes).digest('hex'); const relative = path.relative(root, absolute).replaceAll('\\', '/'); lines.push(`${digest} ${String(size).padStart(12)} ${relative}`); } await writeFile(path.join(root, 'SOURCE_MANIFEST.txt'), `${lines.join('\n')}\n`, 'utf8'); console.log(`Wrote ${files.length} entries for ForgeFlow ${packageJson.version}.`);