




















@@ -209,8 +209,15 @@ const defaultStagedRuntimeDepPruneRules = new Map([
209209["@jimp/plugin-print", { paths: ["src/__image_snapshots__"] }],
210210["@jimp/plugin-quantize", { paths: ["src/__image_snapshots__"] }],
211211["@jimp/plugin-threshold", { paths: ["src/__image_snapshots__"] }],
212+// tokenjuice ships built-in rules as JSON data under `dist/rules/tests/*.json`
213+// (e.g. `bun-test.json`, `jest.json`, `pytest.json`). These are NOT test
214+// fixtures — they are the runtime-loaded rule definitions consumed by
215+// `dist/core/builtin-rules.generated.js`. The global `tests` basename prune
216+// would strip them, and the plugin then fails to load with
217+// `Cannot find module '../rules/tests/bun-test.json'`. Keep them staged.
218+["tokenjuice", { keepDirectories: ["dist/rules/tests"] }],
212219]);
213-const runtimeDepsStagingVersion = 6;
220+const runtimeDepsStagingVersion = 7;
214221const exactVersionSpecRe = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u;
215222216223function resolveRuntimeDepPruneConfig(params = {}) {
@@ -547,7 +554,7 @@ function isNodeModulesPackageRoot(segments, index) {
547554return parent?.startsWith("@") === true && segments[index - 2] === "node_modules";
548555}
549556550-function pruneDependencyDirectoriesByBasename(depRoot, basenames) {
557+function pruneDependencyDirectoriesByBasename(depRoot, basenames, keepDirs = new Set()) {
551558if (!basenames || basenames.length === 0 || !fs.existsSync(depRoot)) {
552559return;
553560}
@@ -562,6 +569,15 @@ function pruneDependencyDirectoriesByBasename(depRoot, basenames) {
562569const fullPath = path.join(currentDir, entry.name);
563570const segments = relativePathSegments(depRoot, fullPath);
564571if (basenameSet.has(entry.name) && !isNodeModulesPackageRoot(segments, segments.length - 1)) {
572+// Per-package opt-out: a pruneRule may keep specific directories that
573+// would otherwise match a global basename prune (e.g. a data/asset
574+// directory named `tests/` that is NOT test code). Descend into kept
575+// directories so their contents are still subject to suffix/pattern
576+// pruning, but do not remove the directory itself.
577+if (keepDirs.has(fullPath)) {
578+queue.push(fullPath);
579+continue;
580+}
565581removePathIfExists(fullPath);
566582continue;
567583}
@@ -591,7 +607,12 @@ function pruneStagedInstalledDependencyCargo(nodeModulesDir, depName, pruneConfi
591607for (const relativePath of pruneRule?.paths ?? []) {
592608removePathIfExists(path.join(depRoot, relativePath));
593609}
594-pruneDependencyDirectoriesByBasename(depRoot, pruneConfig.globalPruneDirectories);
610+// Resolve per-package keepDirectories (opt-out of global basename prune)
611+// against depRoot up front so the walk can skip them cheaply.
612+const keepDirs = new Set(
613+(pruneRule?.keepDirectories ?? []).map((relativePath) => path.resolve(depRoot, relativePath)),
614+);
615+pruneDependencyDirectoriesByBasename(depRoot, pruneConfig.globalPruneDirectories, keepDirs);
595616pruneDependencyFilesByPatterns(depRoot, pruneConfig.globalPruneFilePatterns);
596617pruneDependencyFilesBySuffixes(depRoot, pruneConfig.globalPruneSuffixes);
597618pruneDependencyFilesBySuffixes(depRoot, pruneRule?.suffixes ?? []);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。