Checkpoint web parity through Chromium input tasks
This commit is contained in:
79
tools/web/generate-dependency-inventory.mjs
Normal file
79
tools/web/generate-dependency-inventory.mjs
Normal file
@@ -0,0 +1,79 @@
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const packagePath = path.join(root, "web/package.json");
|
||||
const lockPath = path.join(root, "web/package-lock.json");
|
||||
const outputPath = path.resolve(process.argv[2] ?? path.join(root, "tests/golden/M13-05C/dependency-inventory.json"));
|
||||
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));
|
||||
const lock = JSON.parse(fs.readFileSync(lockPath, "utf8"));
|
||||
const sha256 = (bytes) => crypto.createHash("sha256").update(bytes).digest("hex");
|
||||
const packageBytes = fs.readFileSync(packagePath);
|
||||
const lockBytes = fs.readFileSync(lockPath);
|
||||
const entries = new Map(Object.entries(lock.packages));
|
||||
const packageName = (packageKey) => {
|
||||
const marker = packageKey.lastIndexOf("node_modules/");
|
||||
return marker < 0 ? packageKey : packageKey.slice(marker + "node_modules/".length);
|
||||
};
|
||||
function resolveDependency(fromKey, dependency) {
|
||||
let base = fromKey;
|
||||
while (true) {
|
||||
const candidate = base ? `${base}/node_modules/${dependency}` : `node_modules/${dependency}`;
|
||||
if (entries.has(candidate)) return candidate;
|
||||
const marker = base.lastIndexOf("/node_modules/");
|
||||
if (marker < 0) return entries.has(`node_modules/${dependency}`) ? `node_modules/${dependency}` : null;
|
||||
base = base.slice(0, marker);
|
||||
}
|
||||
}
|
||||
function closure(roots) {
|
||||
const visited = new Set();
|
||||
const queue = roots.map((name) => resolveDependency("", name)).filter(Boolean);
|
||||
while (queue.length) {
|
||||
const key = queue.shift();
|
||||
if (!key || visited.has(key)) continue;
|
||||
visited.add(key);
|
||||
const entry = entries.get(key);
|
||||
for (const dependency of Object.keys({ ...(entry.dependencies ?? {}), ...(entry.optionalDependencies ?? {}) })) {
|
||||
const next = resolveDependency(key, dependency);
|
||||
if (next) queue.push(next);
|
||||
}
|
||||
}
|
||||
return visited;
|
||||
}
|
||||
const roots = {
|
||||
production: Object.keys(packageJson.dependencies ?? {}),
|
||||
build: ["@eslint/js", "@types/react", "@types/react-dom", "@types/three", "@vitejs/plugin-react", "eslint", "typescript", "typescript-eslint", "vite"],
|
||||
test: ["@axe-core/playwright", "@playwright/test"],
|
||||
};
|
||||
const categories = Object.fromEntries(Object.entries(roots).map(([category, names]) => [category, closure(names)]));
|
||||
const allKeys = new Set([...categories.production, ...categories.build, ...categories.test]);
|
||||
const packages = [...allKeys].sort().map((key) => {
|
||||
const entry = entries.get(key);
|
||||
const category = Object.entries(categories).filter(([, keys]) => keys.has(key)).map(([name]) => name);
|
||||
return {
|
||||
path: key,
|
||||
name: entry.name ?? packageName(key),
|
||||
version: entry.version,
|
||||
resolved: entry.resolved ?? null,
|
||||
integrity: entry.integrity ?? null,
|
||||
categories: category,
|
||||
dependencies: Object.keys({ ...(entry.dependencies ?? {}), ...(entry.optionalDependencies ?? {}) }).sort(),
|
||||
};
|
||||
});
|
||||
const inventory = {
|
||||
schemaVersion: 1,
|
||||
task: "M13-05C",
|
||||
operation: "NPM_DEPENDENCY_INVENTORY",
|
||||
package: { path: "web/package.json", sha256: sha256(packageBytes), name: lock.name, version: lock.version, lockfileVersion: lock.lockfileVersion },
|
||||
lockfile: { path: "web/package-lock.json", sha256: sha256(lockBytes), packageCount: entries.size - 1 },
|
||||
roots,
|
||||
categoryCounts: Object.fromEntries(Object.entries(categories).map(([name, keys]) => [name, keys.size])),
|
||||
sharedCount: packages.filter((item) => item.categories.length > 1).length,
|
||||
packages,
|
||||
nextTask: "M13-05D",
|
||||
};
|
||||
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
||||
fs.writeFileSync(outputPath, `${JSON.stringify(inventory, null, 2)}\n`);
|
||||
process.stdout.write(`dependency-inventory-generated production=${inventory.categoryCounts.production} build=${inventory.categoryCounts.build} test=${inventory.categoryCounts.test} shared=${inventory.sharedCount} next=${inventory.nextTask}\n`);
|
||||
Reference in New Issue
Block a user