rename web/ to admin/, along with the web-named build and cli identifiers
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
// The decisions behind `npm run assert-bundled`, kept separate from the script
|
||||
// that does the I/O so they can be unit-tested (milestone-14 deviation 24).
|
||||
//
|
||||
// The licence inventory has to cover every package whose bytes ship, and the
|
||||
// lockfile does not answer that question: it lists what could be reached, not
|
||||
// what rollup kept. Several packages of the non-dev closure are recorded as
|
||||
// tree-shaken away, and if application code starts importing one of them, no
|
||||
// lockfile, no version and no dependency set changes — only the bundle does. So
|
||||
// the bundle is what this reads.
|
||||
|
||||
const sectionHeading = "[npm packages bundled into admin/dist]";
|
||||
|
||||
// A sourcemap `sources` entry for a dependency ends in
|
||||
// `node_modules/<name>/<file>` or `node_modules/@<scope>/<name>/<file>`. Only
|
||||
// the last `node_modules/` matters: a nested dependency's path carries two.
|
||||
export function packageFromSource(source) {
|
||||
const marker = "node_modules/";
|
||||
const at = source.lastIndexOf(marker);
|
||||
if (at === -1) return null;
|
||||
const rest = source.slice(at + marker.length);
|
||||
const parts = rest.split("/");
|
||||
if (parts.length === 0 || parts[0] === "") return null;
|
||||
if (parts[0].startsWith("@")) {
|
||||
if (parts.length < 2 || parts[1] === "") return null;
|
||||
return `${parts[0]}/${parts[1]}`;
|
||||
}
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
/// The sorted, deduplicated package set of a list of sourcemap `sources` arrays.
|
||||
export function bundledPackages(sourceLists) {
|
||||
const found = new Set();
|
||||
for (const sources of sourceLists) {
|
||||
for (const source of sources) {
|
||||
const name = packageFromSource(source);
|
||||
if (name !== null) found.add(name);
|
||||
}
|
||||
}
|
||||
return [...found].sort();
|
||||
}
|
||||
|
||||
/// The recorded section of `licenses/dependency-identity.txt`: every non-blank
|
||||
/// line after the heading, up to the next `[section]`.
|
||||
export function recordedPackages(text) {
|
||||
const recorded = new Set();
|
||||
let grabbing = false;
|
||||
for (const raw of text.split("\n")) {
|
||||
const line = raw.trim();
|
||||
if (!grabbing) {
|
||||
if (line === sectionHeading) grabbing = true;
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("[")) break;
|
||||
if (line !== "") recorded.add(line);
|
||||
}
|
||||
return grabbing ? [...recorded].sort() : null;
|
||||
}
|
||||
|
||||
/// What changed, in the two directions that mean different things: a package
|
||||
/// that started shipping needs a licence decision, and one that stopped needs
|
||||
/// the record corrected.
|
||||
export function comparePackages(recorded, bundled) {
|
||||
const inBundle = new Set(bundled);
|
||||
const inRecord = new Set(recorded);
|
||||
return {
|
||||
added: bundled.filter((name) => !inRecord.has(name)),
|
||||
removed: recorded.filter((name) => !inBundle.has(name)),
|
||||
};
|
||||
}
|
||||
|
||||
export function formatDiff(recorded, bundled) {
|
||||
const { added, removed } = comparePackages(recorded, bundled);
|
||||
const lines = [];
|
||||
for (const name of removed) lines.push(`-${name}`);
|
||||
for (const name of added) lines.push(`+${name}`);
|
||||
return lines.join("\n");
|
||||
}
|
||||
Reference in New Issue
Block a user