Files
workinf_Blender_Wasm/tools/web/generate-dependency-inventory.mjs
mes123456 380cbed4ff
Some checks are pending
M6 deployable RC / quick (push) Waiting to run
M6 deployable RC / chromium (push) Blocked by required conditions
M6 deployable RC / release (push) Blocked by required conditions
Checkpoint web parity through Chromium input tasks
2026-08-19 10:39:03 -04:00

80 lines
3.9 KiB
JavaScript

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`);