refactor: simplify plugin dependency handling

Simplify plugin installation and runtime loading around package-manager-owned dependencies, with Jiti reserved for local/TS fallback paths.

Also scans npm plugin install roots so hoisted transitive dependencies are covered by dependency denylist and node_modules symlink checks.
This commit is contained in:
Peter Steinberger
2026-05-01 21:32:22 +01:00
committed by GitHub
parent 2e8e9cd6ca
commit ed8f50f240
294 changed files with 2562 additions and 25454 deletions

View File

@@ -3,11 +3,7 @@
import fs from "node:fs";
import path from "node:path";
import { pathToFileURL } from "node:url";
import {
collectBundledPluginRuntimeDependencySpecs,
collectRootDistBundledRuntimeMirrors,
packageNameFromSpecifier,
} from "./lib/bundled-plugin-root-runtime-mirrors.mjs";
import { packageNameFromSpecifier } from "./lib/bundled-plugin-root-runtime-mirrors.mjs";
const DEFAULT_SCAN_ROOTS = ["src", "extensions", "packages", "ui", "scripts", "test"];
const SCANNED_EXTENSIONS = new Set([".cjs", ".cts", ".js", ".jsx", ".mjs", ".mts", ".ts", ".tsx"]);
@@ -23,6 +19,12 @@ const DYNAMIC_CONSTANT_IMPORT_PATTERNS = [
/\brequire\s*\(\s*([_$A-Za-z][\w$]*)\s*\)/g,
/\b(?:require|[_$A-Za-z][\w$]*require[\w$]*)\.resolve\s*\(\s*([_$A-Za-z][\w$]*)\s*\)/gi,
];
const ROOT_OWNED_EXTENSION_RUNTIME_DEPENDENCIES = new Map([
[
"playwright-core",
"keep at root; the internal browser runtime is shipped with core even though downloadable browser-adjacent plugins also declare it",
],
]);
function readJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, "utf8"));
@@ -149,16 +151,6 @@ function sectionSetIsSubsetOf(sectionSet, allowed) {
export function classifyRootDependencyOwnership(record) {
const sections = new Set(record.sections);
if (record.rootMirrorImporters.length > 0) {
if (!sectionSetContainsCore(sections)) {
return {
category: "extension_only_localizable",
recommendation:
"remove from root package.json and rely on owning extension manifests plus doctor --fix",
};
}
}
if (sections.size === 0) {
return {
category: "unreferenced",
@@ -187,6 +179,17 @@ export function classifyRootDependencyOwnership(record) {
};
}
const rootOwnedExtensionRuntime = ROOT_OWNED_EXTENSION_RUNTIME_DEPENDENCIES.get(record.depName);
if (
rootOwnedExtensionRuntime &&
sectionSetIsSubsetOf(sections, new Set(["extensions", "test"]))
) {
return {
category: "root_owned_extension_runtime",
recommendation: rootOwnedExtensionRuntime,
};
}
if (sectionSetIsSubsetOf(sections, new Set(["extensions", "test"]))) {
return {
category: "extension_only_localizable",
@@ -216,7 +219,6 @@ export function collectRootDependencyOwnershipAudit(params = {}) {
sections: new Set(),
files: new Set(),
declaredInExtensions: [],
rootMirrorImporters: [],
spec: rootDependencies[depName],
},
]),
@@ -247,26 +249,6 @@ export function collectRootDependencyOwnershipAudit(params = {}) {
}
}
const distDir = path.join(repoRoot, "dist");
if (fs.existsSync(distDir)) {
const bundledSpecs = collectBundledPluginRuntimeDependencySpecs(
path.join(repoRoot, "extensions"),
);
const rootMirrors = collectRootDistBundledRuntimeMirrors({
bundledRuntimeDependencySpecs: bundledSpecs,
distDir,
});
for (const [depName, mirror] of rootMirrors) {
const record = records.get(depName);
if (!record) {
continue;
}
record.rootMirrorImporters = [...mirror.importers].toSorted((left, right) =>
left.localeCompare(right),
);
}
}
return [...records.values()]
.map((record) => {
const classification = classifyRootDependencyOwnership({
@@ -280,7 +262,6 @@ export function collectRootDependencyOwnershipAudit(params = {}) {
fileCount: record.files.size,
sampleFiles: [...record.files].slice(0, 5),
declaredInExtensions: record.declaredInExtensions,
rootMirrorImporters: record.rootMirrorImporters,
category: classification.category,
recommendation: classification.recommendation,
};
@@ -320,9 +301,6 @@ function printTextReport(records) {
if (record.declaredInExtensions.length > 0) {
details.push(`extensions=${record.declaredInExtensions.join(",")}`);
}
if (record.rootMirrorImporters.length > 0) {
details.push(`rootDist=${record.rootMirrorImporters.join(",")}`);
}
console.log(`- ${record.depName}@${record.spec} :: ${details.join(" | ")}`);
console.log(` ${record.recommendation}`);
}