import { readdir, readFile } from "node:fs/promises"; import { basename, extname, join, resolve } from "node:path"; const root = resolve(process.argv[2] || "."); const ignoredDirectories = new Set([ ".git", "dist", "node_modules", "secrets", "state", ]); const plainTextExtensions = new Set([".json", ".md", ".txt", ".yaml", ".yml"]); const failures = []; await inspect(root); if (failures.length) { for (const failure of failures) console.error(failure); process.exitCode = 1; } else { console.log("Layout constraints passed."); } async function inspect(directory) { const entries = await readdir(directory, { withFileTypes: true }); const files = entries.filter((entry) => entry.isFile()); const directories = entries.filter( (entry) => entry.isDirectory() && !ignoredDirectories.has(entry.name), ); const relative = directory.slice(root.length + 1) || "."; if (files.length > 3) { failures.push( `${relative}: ${files.length} files exceeds the limit of 3`, ); } if (directories.length > 4) { failures.push( `${relative}: ${directories.length} folders exceeds the limit of 4`, ); } await Promise.all( files.map((file) => inspectFile(join(directory, file.name))), ); await Promise.all( directories.map((child) => inspect(join(directory, child.name))), ); } async function inspectFile(path) { const name = basename(path); if (name.includes(".test.") || plainTextExtensions.has(extname(name))) return; const content = await readFile(path, "utf8"); const lines = content.split("\n").length; if (lines > 250) { failures.push( `${path.slice(root.length + 1)}: ${lines} lines exceeds 250`, ); } }