import { createHash } from "node:crypto"; import { lstat, mkdir, readFile, readdir, writeFile } from "node:fs/promises"; import { dirname, extname, resolve } from "node:path"; // Only these authored inputs are public. Build output, private deployment state, // hidden files, dependencies, and symlinks are never traversed. const textRoots = ["src", "scripts", "tests"]; const textExtensions = new Set([ ".html", ".css", ".js", ".mjs", ".json", ".md", ]); const assetExtensions = new Set([ ".svg", ".png", ".jpg", ".jpeg", ".webp", ".avif", ".woff", ".woff2", ".mp4", ".webm", ]); const documents = [ ".vercelignore", "package.json", "package-lock.json", "vercel.json", "README.md", "ASSETS.md", "MOTION.md", "CAPTURES.md", "CONCEPT-MAP.md", "DEPLOYMENT.md", ]; const excludedDirectories = new Set([ "node_modules", "dist", "reports", "captures", ]); function escapeHtml(value) { return value.replace( /[&<>"']/g, (character) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'", })[character], ); } async function listFiles(root, directory, extensions) { let entries; try { if (!(await lstat(resolve(root, directory))).isDirectory()) return []; entries = await readdir(resolve(root, directory), { withFileTypes: true }); } catch (error) { if (error.code === "ENOENT") return []; throw error; } const paths = await Promise.all( entries.map(async (entry) => { if (entry.name.startsWith(".") || entry.isSymbolicLink()) return []; const path = `${directory}/${entry.name}`; if (entry.isDirectory()) { return excludedDirectories.has(entry.name) ? [] : listFiles(root, path, extensions); } return entry.isFile() && extensions.has(extname(entry.name)) ? [path] : []; }), ); return paths.flat(); } async function existingDocuments(root) { const paths = await Promise.all( documents.map(async (path) => { try { return (await lstat(resolve(root, path))).isFile() ? [path] : []; } catch (error) { if (error.code === "ENOENT") return []; throw error; } }), ); return paths.flat(); } function metadata(path, url, content) { return { path, url, bytes: content.length, sha256: createHash("sha256").update(content).digest("hex"), }; } function indexPage(files, assets) { const source = files .map( ({ path, url, content }) => `
${escapeHtml(path)}

Read raw text

${escapeHtml(content)}
`, ) .join("\n"); const assetLinks = assets .map( ({ path, url }) => `
  • ${escapeHtml(path)}
  • `, ) .join("\n"); return ` DualEntry landing page — readable source

    DualEntry landing page source

    Complete authored HTML, CSS, JavaScript, build tools, tests, and local asset references. Expand a file to read it, or fetch the complete text bundle to recreate the project.

    Source files

    ${source}

    Assets

    \n`; } export async function publishSource(root, destination) { const paths = ( await Promise.all([ ...textRoots.map((directory) => listFiles(root, directory, textExtensions), ), existingDocuments(root), ]) ) .flat() .sort(); const files = await Promise.all( paths.map(async (path) => { const raw = await readFile(resolve(root, path)); const content = raw.toString("utf8"); // Fail visibly rather than expose machine-specific source or silently redact code. const localPath = new RegExp( "/(?:Users|Volumes|home)/[^\\s]+|[A-Za-z]:\\\\Users\\\\", ); if (localPath.test(content)) throw new Error(`Machine-specific path in public source: ${path}`); const url = `source/files/${path.split("/").map(encodeURIComponent).join("/")}.txt`; return { ...metadata(path, url, raw), content }; }), ); const assetPaths = (await listFiles(root, "assets", assetExtensions)).sort(); const assets = await Promise.all( assetPaths.map(async (path) => metadata( path, path.split("/").map(encodeURIComponent).join("/"), await readFile(resolve(root, path)), ), ), ); const manifest = { version: 1, files: files.map(({ content, ...entry }) => entry), assets, }; const directory = resolve(destination, "source"); await mkdir(directory, { recursive: true }); await Promise.all( files.map(async ({ url, content }) => { const output = resolve(destination, decodeURIComponent(url)); await mkdir(dirname(output), { recursive: true }); await writeFile(output, content); }), ); await Promise.all([ writeFile( resolve(directory, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n", ), writeFile( resolve(directory, "bundle.json"), JSON.stringify({ version: 1, files, assets }, null, 2) + "\n", ), writeFile(resolve(directory, "index.html"), indexPage(files, assets)), ]); return manifest; }