import { cp, mkdir, readFile, readdir, rm, 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 destination = path.join(root, "public"); const required = [ "LICENSE", "README.md", "CHANGELOG.md", "CONTRIBUTING.md", "SECURITY.md", "SOURCE.md", "THIRD_PARTY_NOTICES.md", ]; await mkdir(destination, { recursive: true }); for (const name of required) { await readFile(path.join(root, name)); await cp(path.join(root, name), path.join(destination, name)); } for (const directory of ["LICENSES", "docs"]) { const output = path.join(destination, directory); await rm(output, { recursive: true, force: true }); await cp(path.join(root, directory), output, { recursive: true }); } const lock = JSON.parse( await readFile(path.join(root, "package-lock.json"), "utf8"), ); const sections = []; for (const [location, locked] of Object.entries(lock.packages ?? {}).sort( ([left], [right]) => (left === right ? 0 : left < right ? -1 : 1), )) { if (!location.includes("node_modules/") || locked.dev === true) continue; const packageDirectory = path.join(root, location); const details = JSON.parse( await readFile(path.join(packageDirectory, "package.json"), "utf8"), ); const candidates = (await readdir(packageDirectory)) .filter((name) => /^(?:licen[cs]e|copying|notice)(?:\.|$)/iu.test(name)) .sort(); const texts = []; for (const candidate of candidates) { try { texts.push( `--- ${candidate} ---\n${( await readFile(path.join(packageDirectory, candidate), "utf8") ).trimEnd()}`, ); } catch { /* Ignore directories and non-text aliases. */ } } sections.push( [ "=".repeat(78), `${details.name}@${details.version}`, `Declared licence: ${details.license ?? locked.license ?? "See upstream"}`, `Installed from: ${location}`, "=".repeat(78), texts.join("\n\n") || "No package-local licence file was present; see THIRD_PARTY_NOTICES.md.", ].join("\n"), ); } await writeFile( path.join(destination, "LICENSES", "npm-runtime-licenses.txt"), `${sections.join("\n\n").trimEnd()}\n`, ); console.log("Prepared static release documentation and notices");