deslop-js 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +860 -130
- package/dist/index.mjs +861 -131
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import path, { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
1
|
+
import path, { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
2
2
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
3
3
|
import fg from "fast-glob";
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
@@ -224,7 +224,9 @@ const PLATFORM_SUFFIXES = [
|
|
|
224
224
|
".desktop",
|
|
225
225
|
".windows",
|
|
226
226
|
".macos",
|
|
227
|
-
".any"
|
|
227
|
+
".any",
|
|
228
|
+
".server",
|
|
229
|
+
".client"
|
|
228
230
|
];
|
|
229
231
|
const REACT_NATIVE_PLATFORM_EXTENSIONS = [
|
|
230
232
|
".web.ts",
|
|
@@ -575,6 +577,10 @@ const extractNamedExportDeclaration = (node, sourceText, exports) => {
|
|
|
575
577
|
}
|
|
576
578
|
};
|
|
577
579
|
const extractDefaultExportDeclaration = (node, sourceText, exports) => {
|
|
580
|
+
const defaultExpression = node.declaration;
|
|
581
|
+
let defaultExportLocalName;
|
|
582
|
+
if (defaultExpression?.type === "Identifier" && typeof defaultExpression.name === "string") defaultExportLocalName = defaultExpression.name;
|
|
583
|
+
else if ((defaultExpression?.type === "FunctionDeclaration" || defaultExpression?.type === "ClassDeclaration") && defaultExpression.id?.name) defaultExportLocalName = defaultExpression.id.name;
|
|
578
584
|
exports.push({
|
|
579
585
|
name: "default",
|
|
580
586
|
isDefault: true,
|
|
@@ -585,7 +591,8 @@ const extractDefaultExportDeclaration = (node, sourceText, exports) => {
|
|
|
585
591
|
reExportOriginalName: void 0,
|
|
586
592
|
isNamespaceReExport: false,
|
|
587
593
|
line: getLineFromOffset(sourceText, node.start),
|
|
588
|
-
column: getColumnFromOffset(sourceText, node.start)
|
|
594
|
+
column: getColumnFromOffset(sourceText, node.start),
|
|
595
|
+
defaultExportLocalName
|
|
589
596
|
});
|
|
590
597
|
};
|
|
591
598
|
const extractExportAllDeclaration = (node, sourceText, exports) => {
|
|
@@ -1066,6 +1073,12 @@ const collectWorkspacePatterns = (rootDir) => {
|
|
|
1066
1073
|
const packageLines = extractPnpmWorkspacePackages(readFileSync(pnpmWorkspacePath, "utf-8"));
|
|
1067
1074
|
patterns.push(...packageLines);
|
|
1068
1075
|
} catch {}
|
|
1076
|
+
const lernaJsonPath = join(rootDir, "lerna.json");
|
|
1077
|
+
if (existsSync(lernaJsonPath)) try {
|
|
1078
|
+
const content = readFileSync(lernaJsonPath, "utf-8");
|
|
1079
|
+
const lernaJson = JSON.parse(content);
|
|
1080
|
+
if (Array.isArray(lernaJson.packages)) patterns.push(...lernaJson.packages.filter((pattern) => typeof pattern === "string" && !pattern.startsWith("!")));
|
|
1081
|
+
} catch {}
|
|
1069
1082
|
return patterns;
|
|
1070
1083
|
};
|
|
1071
1084
|
const extractPnpmWorkspacePackages = (yamlContent) => {
|
|
@@ -1627,6 +1640,54 @@ const resolveSourcePath = (distPath, directory) => {
|
|
|
1627
1640
|
}
|
|
1628
1641
|
};
|
|
1629
1642
|
|
|
1643
|
+
//#endregion
|
|
1644
|
+
//#region src/utils/find-monorepo-root.ts
|
|
1645
|
+
const MONOREPO_ROOT_MARKERS = [
|
|
1646
|
+
"pnpm-workspace.yaml",
|
|
1647
|
+
"pnpm-workspace.yml",
|
|
1648
|
+
"lerna.json",
|
|
1649
|
+
"nx.json",
|
|
1650
|
+
"turbo.json",
|
|
1651
|
+
"rush.json"
|
|
1652
|
+
];
|
|
1653
|
+
const LOCKFILE_MARKERS = [
|
|
1654
|
+
"pnpm-lock.yaml",
|
|
1655
|
+
"yarn.lock",
|
|
1656
|
+
"package-lock.json",
|
|
1657
|
+
"bun.lockb",
|
|
1658
|
+
"bun.lock"
|
|
1659
|
+
];
|
|
1660
|
+
const MAX_MONOREPO_WALK_DEPTH = 5;
|
|
1661
|
+
const findMonorepoRoot = (rootDir) => {
|
|
1662
|
+
let currentDirectory = resolve(rootDir);
|
|
1663
|
+
let walkedDepth = 0;
|
|
1664
|
+
while (walkedDepth < MAX_MONOREPO_WALK_DEPTH) {
|
|
1665
|
+
const parentDirectory = dirname(currentDirectory);
|
|
1666
|
+
if (parentDirectory === currentDirectory) break;
|
|
1667
|
+
currentDirectory = parentDirectory;
|
|
1668
|
+
walkedDepth++;
|
|
1669
|
+
if (existsSync(join(currentDirectory, ".git"))) {
|
|
1670
|
+
for (const marker of MONOREPO_ROOT_MARKERS) if (existsSync(join(currentDirectory, marker))) return currentDirectory;
|
|
1671
|
+
const packageJsonPath = join(currentDirectory, "package.json");
|
|
1672
|
+
if (existsSync(packageJsonPath)) try {
|
|
1673
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
1674
|
+
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
1675
|
+
} catch {}
|
|
1676
|
+
for (const lockfile of LOCKFILE_MARKERS) if (existsSync(join(currentDirectory, lockfile))) return currentDirectory;
|
|
1677
|
+
return;
|
|
1678
|
+
}
|
|
1679
|
+
for (const marker of MONOREPO_ROOT_MARKERS) if (existsSync(join(currentDirectory, marker))) return currentDirectory;
|
|
1680
|
+
const packageJsonPath = join(currentDirectory, "package.json");
|
|
1681
|
+
if (existsSync(packageJsonPath)) try {
|
|
1682
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
1683
|
+
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
1684
|
+
} catch {
|
|
1685
|
+
continue;
|
|
1686
|
+
}
|
|
1687
|
+
for (const lockfile of LOCKFILE_MARKERS) if (existsSync(join(currentDirectory, lockfile))) return currentDirectory;
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
|
|
1630
1691
|
//#endregion
|
|
1631
1692
|
//#region src/collect/entries.ts
|
|
1632
1693
|
const collectSourceFiles = async (config) => {
|
|
@@ -1732,6 +1793,14 @@ const resolveEntries = async (config) => {
|
|
|
1732
1793
|
for (const entryPath of allDiscoveredEntries) if (entryPath.endsWith(".html") && existsSync(entryPath)) htmlScriptEntries.push(...extractScriptTagsFromHtmlFile(entryPath));
|
|
1733
1794
|
const angularEntries = extractAngularEntryPoints(absoluteRoot);
|
|
1734
1795
|
for (const workspacePackage of entryEligiblePackages) angularEntries.push(...extractAngularEntryPoints(workspacePackage.directory));
|
|
1796
|
+
const browserExtensionEntries = extractBrowserExtensionEntries(absoluteRoot);
|
|
1797
|
+
for (const workspacePackage of entryEligiblePackages) browserExtensionEntries.push(...extractBrowserExtensionEntries(workspacePackage.directory));
|
|
1798
|
+
const webWorkerEntries = extractWebWorkerEntries(absoluteRoot);
|
|
1799
|
+
for (const workspacePackage of entryEligiblePackages) webWorkerEntries.push(...extractWebWorkerEntries(workspacePackage.directory));
|
|
1800
|
+
const tsConfigIncludeEntries = extractTsConfigIncludeFilesEntries(absoluteRoot);
|
|
1801
|
+
for (const workspacePackage of entryEligiblePackages) tsConfigIncludeEntries.push(...extractTsConfigIncludeFilesEntries(workspacePackage.directory));
|
|
1802
|
+
const wranglerEntries = extractWranglerEntries(absoluteRoot);
|
|
1803
|
+
for (const workspacePackage of entryEligiblePackages) wranglerEntries.push(...extractWranglerEntries(workspacePackage.directory));
|
|
1735
1804
|
const testSetupEntries = extractTestSetupFiles(absoluteRoot);
|
|
1736
1805
|
for (const workspacePackage of entryEligiblePackages) testSetupEntries.push(...extractTestSetupFiles(workspacePackage.directory));
|
|
1737
1806
|
const pluginFileEntries = extractNextConfigPluginFiles(absoluteRoot);
|
|
@@ -1753,6 +1822,10 @@ const resolveEntries = async (config) => {
|
|
|
1753
1822
|
...bundlerConfigEntries,
|
|
1754
1823
|
...htmlScriptEntries,
|
|
1755
1824
|
...angularEntries,
|
|
1825
|
+
...browserExtensionEntries,
|
|
1826
|
+
...webWorkerEntries,
|
|
1827
|
+
...tsConfigIncludeEntries,
|
|
1828
|
+
...wranglerEntries,
|
|
1756
1829
|
...pluginFileEntries,
|
|
1757
1830
|
...toolingDiscovery.entryFiles,
|
|
1758
1831
|
...ciEntries
|
|
@@ -2396,6 +2469,231 @@ const extractScriptTagsFromHtmlFile = (htmlFilePath) => {
|
|
|
2396
2469
|
} catch {}
|
|
2397
2470
|
return entries;
|
|
2398
2471
|
};
|
|
2472
|
+
const TSCONFIG_FILENAME_GLOBS = ["tsconfig.json", "tsconfig.*.json"];
|
|
2473
|
+
const stripJsoncCommentsLocal = (sourceText) => {
|
|
2474
|
+
let result = "";
|
|
2475
|
+
let insideString = false;
|
|
2476
|
+
let index = 0;
|
|
2477
|
+
while (index < sourceText.length) {
|
|
2478
|
+
const ch = sourceText[index];
|
|
2479
|
+
if (insideString) {
|
|
2480
|
+
if (ch === "\\" && index + 1 < sourceText.length) {
|
|
2481
|
+
result += sourceText[index] + sourceText[index + 1];
|
|
2482
|
+
index += 2;
|
|
2483
|
+
continue;
|
|
2484
|
+
}
|
|
2485
|
+
if (ch === "\"") insideString = false;
|
|
2486
|
+
result += ch;
|
|
2487
|
+
index++;
|
|
2488
|
+
continue;
|
|
2489
|
+
}
|
|
2490
|
+
if (ch === "\"") {
|
|
2491
|
+
insideString = true;
|
|
2492
|
+
result += ch;
|
|
2493
|
+
index++;
|
|
2494
|
+
continue;
|
|
2495
|
+
}
|
|
2496
|
+
if (ch === "/" && index + 1 < sourceText.length) {
|
|
2497
|
+
if (sourceText[index + 1] === "/") {
|
|
2498
|
+
while (index < sourceText.length && sourceText[index] !== "\n") index++;
|
|
2499
|
+
continue;
|
|
2500
|
+
}
|
|
2501
|
+
if (sourceText[index + 1] === "*") {
|
|
2502
|
+
index += 2;
|
|
2503
|
+
while (index + 1 < sourceText.length && !(sourceText[index] === "*" && sourceText[index + 1] === "/")) index++;
|
|
2504
|
+
index += 2;
|
|
2505
|
+
continue;
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
result += ch;
|
|
2509
|
+
index++;
|
|
2510
|
+
}
|
|
2511
|
+
return result.replace(/,(\s*[}\]])/g, "$1");
|
|
2512
|
+
};
|
|
2513
|
+
const extractTsConfigIncludeFilesEntries = (directory) => {
|
|
2514
|
+
const entries = [];
|
|
2515
|
+
const tsconfigPaths = fg.sync(TSCONFIG_FILENAME_GLOBS, {
|
|
2516
|
+
cwd: directory,
|
|
2517
|
+
absolute: true,
|
|
2518
|
+
onlyFiles: true,
|
|
2519
|
+
ignore: [
|
|
2520
|
+
"**/node_modules/**",
|
|
2521
|
+
"**/dist/**",
|
|
2522
|
+
"**/build/**"
|
|
2523
|
+
],
|
|
2524
|
+
deep: 1
|
|
2525
|
+
});
|
|
2526
|
+
for (const tsconfigPath of tsconfigPaths) try {
|
|
2527
|
+
const cleaned = stripJsoncCommentsLocal(readFileSync(tsconfigPath, "utf-8"));
|
|
2528
|
+
const tsconfigJson = JSON.parse(cleaned);
|
|
2529
|
+
const tsconfigDir = dirname(tsconfigPath);
|
|
2530
|
+
const collectPaths = (rawList) => {
|
|
2531
|
+
if (!Array.isArray(rawList)) return;
|
|
2532
|
+
for (const item of rawList) {
|
|
2533
|
+
if (typeof item !== "string") continue;
|
|
2534
|
+
if (item.includes("*") || item.includes("?")) continue;
|
|
2535
|
+
const candidatePath = resolve(tsconfigDir, item);
|
|
2536
|
+
if (existsSync(candidatePath)) entries.push(candidatePath);
|
|
2537
|
+
}
|
|
2538
|
+
};
|
|
2539
|
+
collectPaths(tsconfigJson.include);
|
|
2540
|
+
collectPaths(tsconfigJson.files);
|
|
2541
|
+
} catch {}
|
|
2542
|
+
return entries;
|
|
2543
|
+
};
|
|
2544
|
+
const WRANGLER_TOML_MAIN_PATTERN = /^\s*main\s*=\s*['"]([^'"\n]+)['"]/m;
|
|
2545
|
+
const WRANGLER_JSON_MAIN_PATTERN = /"main"\s*:\s*"([^"]+)"/;
|
|
2546
|
+
const WRANGLER_SERVICE_BINDINGS_PATTERN = /entry_point\s*=\s*['"]([^'"\n]+)['"]/g;
|
|
2547
|
+
const extractWranglerEntries = (directory) => {
|
|
2548
|
+
const entries = [];
|
|
2549
|
+
const wranglerPaths = fg.sync([
|
|
2550
|
+
"wrangler.toml",
|
|
2551
|
+
"wrangler.json",
|
|
2552
|
+
"wrangler.jsonc"
|
|
2553
|
+
], {
|
|
2554
|
+
cwd: directory,
|
|
2555
|
+
absolute: true,
|
|
2556
|
+
onlyFiles: true,
|
|
2557
|
+
ignore: ["**/node_modules/**"],
|
|
2558
|
+
deep: 1
|
|
2559
|
+
});
|
|
2560
|
+
for (const wranglerPath of wranglerPaths) try {
|
|
2561
|
+
const content = readFileSync(wranglerPath, "utf-8");
|
|
2562
|
+
const wranglerDir = dirname(wranglerPath);
|
|
2563
|
+
const mainMatch = wranglerPath.endsWith(".toml") ? content.match(WRANGLER_TOML_MAIN_PATTERN) : content.match(WRANGLER_JSON_MAIN_PATTERN);
|
|
2564
|
+
if (mainMatch?.[1]) {
|
|
2565
|
+
const candidatePath = resolve(wranglerDir, mainMatch[1]);
|
|
2566
|
+
if (existsSync(candidatePath)) entries.push(candidatePath);
|
|
2567
|
+
else {
|
|
2568
|
+
const sourceCandidate = resolveSourcePath(candidatePath, wranglerDir);
|
|
2569
|
+
if (sourceCandidate) entries.push(sourceCandidate);
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
let entryPointMatch;
|
|
2573
|
+
WRANGLER_SERVICE_BINDINGS_PATTERN.lastIndex = 0;
|
|
2574
|
+
while ((entryPointMatch = WRANGLER_SERVICE_BINDINGS_PATTERN.exec(content)) !== null) {
|
|
2575
|
+
const candidatePath = resolve(wranglerDir, entryPointMatch[1]);
|
|
2576
|
+
if (existsSync(candidatePath)) entries.push(candidatePath);
|
|
2577
|
+
}
|
|
2578
|
+
} catch {}
|
|
2579
|
+
return entries;
|
|
2580
|
+
};
|
|
2581
|
+
const WORKER_FILE_GLOBS = [
|
|
2582
|
+
"**/*.worker.{ts,tsx,js,jsx,mts,mjs,cts,cjs}",
|
|
2583
|
+
"**/*.sw.{ts,tsx,js,jsx,mts,mjs,cts,cjs}",
|
|
2584
|
+
"**/sw.{ts,tsx,js,jsx,mts,mjs,cts,cjs}",
|
|
2585
|
+
"**/service-worker.{ts,tsx,js,jsx,mts,mjs,cts,cjs}"
|
|
2586
|
+
];
|
|
2587
|
+
const extractWebWorkerEntries = (directory) => {
|
|
2588
|
+
return fg.sync(WORKER_FILE_GLOBS, {
|
|
2589
|
+
cwd: directory,
|
|
2590
|
+
absolute: true,
|
|
2591
|
+
onlyFiles: true,
|
|
2592
|
+
ignore: [
|
|
2593
|
+
"**/node_modules/**",
|
|
2594
|
+
"**/dist/**",
|
|
2595
|
+
"**/build/**",
|
|
2596
|
+
"**/.next/**",
|
|
2597
|
+
"**/out/**"
|
|
2598
|
+
],
|
|
2599
|
+
deep: 8
|
|
2600
|
+
});
|
|
2601
|
+
};
|
|
2602
|
+
const collectBrowserExtensionManifestPaths = (manifest) => {
|
|
2603
|
+
const candidatePaths = [];
|
|
2604
|
+
if (typeof manifest !== "object" || manifest === null) return candidatePaths;
|
|
2605
|
+
const manifestRecord = manifest;
|
|
2606
|
+
const background = manifestRecord.background;
|
|
2607
|
+
if (typeof background === "object" && background !== null) {
|
|
2608
|
+
const backgroundRecord = background;
|
|
2609
|
+
if (typeof backgroundRecord.service_worker === "string") candidatePaths.push(backgroundRecord.service_worker);
|
|
2610
|
+
if (typeof backgroundRecord.page === "string") candidatePaths.push(backgroundRecord.page);
|
|
2611
|
+
if (typeof backgroundRecord.scripts === "string") candidatePaths.push(backgroundRecord.scripts);
|
|
2612
|
+
if (Array.isArray(backgroundRecord.scripts)) {
|
|
2613
|
+
for (const scriptPath of backgroundRecord.scripts) if (typeof scriptPath === "string") candidatePaths.push(scriptPath);
|
|
2614
|
+
}
|
|
2615
|
+
}
|
|
2616
|
+
const contentScripts = manifestRecord.content_scripts;
|
|
2617
|
+
if (Array.isArray(contentScripts)) for (const contentScript of contentScripts) {
|
|
2618
|
+
if (typeof contentScript !== "object" || contentScript === null) continue;
|
|
2619
|
+
const contentScriptRecord = contentScript;
|
|
2620
|
+
if (Array.isArray(contentScriptRecord.js)) {
|
|
2621
|
+
for (const scriptPath of contentScriptRecord.js) if (typeof scriptPath === "string") candidatePaths.push(scriptPath);
|
|
2622
|
+
}
|
|
2623
|
+
if (Array.isArray(contentScriptRecord.css)) {
|
|
2624
|
+
for (const stylePath of contentScriptRecord.css) if (typeof stylePath === "string") candidatePaths.push(stylePath);
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
const action = manifestRecord.action ?? manifestRecord.browser_action ?? manifestRecord.page_action;
|
|
2628
|
+
if (typeof action === "object" && action !== null) {
|
|
2629
|
+
const actionRecord = action;
|
|
2630
|
+
if (typeof actionRecord.default_popup === "string") candidatePaths.push(actionRecord.default_popup);
|
|
2631
|
+
}
|
|
2632
|
+
if (typeof manifestRecord.devtools_page === "string") candidatePaths.push(manifestRecord.devtools_page);
|
|
2633
|
+
if (typeof manifestRecord.options_page === "string") candidatePaths.push(manifestRecord.options_page);
|
|
2634
|
+
if (typeof manifestRecord.options_ui === "object" && manifestRecord.options_ui !== null) {
|
|
2635
|
+
const optionsRecord = manifestRecord.options_ui;
|
|
2636
|
+
if (typeof optionsRecord.page === "string") candidatePaths.push(optionsRecord.page);
|
|
2637
|
+
}
|
|
2638
|
+
if (typeof manifestRecord.sandbox === "object" && manifestRecord.sandbox !== null) {
|
|
2639
|
+
const sandboxRecord = manifestRecord.sandbox;
|
|
2640
|
+
if (Array.isArray(sandboxRecord.pages)) {
|
|
2641
|
+
for (const pagePath of sandboxRecord.pages) if (typeof pagePath === "string") candidatePaths.push(pagePath);
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
return candidatePaths;
|
|
2645
|
+
};
|
|
2646
|
+
const isLikelyBrowserExtensionManifest = (manifest) => {
|
|
2647
|
+
if (typeof manifest !== "object" || manifest === null) return false;
|
|
2648
|
+
return typeof manifest.manifest_version === "number";
|
|
2649
|
+
};
|
|
2650
|
+
const extractBrowserExtensionEntries = (directory) => {
|
|
2651
|
+
const entries = [];
|
|
2652
|
+
const manifestPaths = fg.sync([
|
|
2653
|
+
"manifest.json",
|
|
2654
|
+
"manifest.*.json",
|
|
2655
|
+
"src/manifest.json",
|
|
2656
|
+
"src/manifest.*.json",
|
|
2657
|
+
"public/manifest.json",
|
|
2658
|
+
"public/manifest.*.json",
|
|
2659
|
+
"static/manifest.json"
|
|
2660
|
+
], {
|
|
2661
|
+
cwd: directory,
|
|
2662
|
+
absolute: true,
|
|
2663
|
+
onlyFiles: true,
|
|
2664
|
+
ignore: [
|
|
2665
|
+
"**/node_modules/**",
|
|
2666
|
+
"**/dist/**",
|
|
2667
|
+
"**/build/**"
|
|
2668
|
+
],
|
|
2669
|
+
deep: 3
|
|
2670
|
+
});
|
|
2671
|
+
for (const manifestPath of manifestPaths) try {
|
|
2672
|
+
const content = readFileSync(manifestPath, "utf-8");
|
|
2673
|
+
const manifest = JSON.parse(content);
|
|
2674
|
+
if (!isLikelyBrowserExtensionManifest(manifest)) continue;
|
|
2675
|
+
const manifestDir = dirname(manifestPath);
|
|
2676
|
+
const candidatePaths = collectBrowserExtensionManifestPaths(manifest);
|
|
2677
|
+
const resolutionRoots = [
|
|
2678
|
+
manifestDir,
|
|
2679
|
+
resolve(manifestDir, ".."),
|
|
2680
|
+
directory
|
|
2681
|
+
];
|
|
2682
|
+
for (const candidatePath of candidatePaths) for (const resolutionRoot of resolutionRoots) {
|
|
2683
|
+
const candidateAbsolutePath = resolve(resolutionRoot, candidatePath);
|
|
2684
|
+
if (existsSync(candidateAbsolutePath)) {
|
|
2685
|
+
entries.push(candidateAbsolutePath);
|
|
2686
|
+
break;
|
|
2687
|
+
}
|
|
2688
|
+
const sourceFile = resolveSourcePath(candidateAbsolutePath, resolutionRoot);
|
|
2689
|
+
if (sourceFile) {
|
|
2690
|
+
entries.push(sourceFile);
|
|
2691
|
+
break;
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
} catch {}
|
|
2695
|
+
return entries;
|
|
2696
|
+
};
|
|
2399
2697
|
const ANGULAR_ENTRY_KEYS = [
|
|
2400
2698
|
"main",
|
|
2401
2699
|
"polyfills",
|
|
@@ -3126,8 +3424,14 @@ const FRAMEWORK_PATTERNS = [
|
|
|
3126
3424
|
alwaysUsed: ["tsr.config.json", "app.config.{ts,js}"]
|
|
3127
3425
|
},
|
|
3128
3426
|
{
|
|
3129
|
-
enablers: [
|
|
3130
|
-
|
|
3427
|
+
enablers: [
|
|
3428
|
+
"vite",
|
|
3429
|
+
"rolldown-vite",
|
|
3430
|
+
"vite-plus",
|
|
3431
|
+
"@voidzero-dev/vite-plus-core",
|
|
3432
|
+
"@voidzero-dev/vite-plus-test"
|
|
3433
|
+
],
|
|
3434
|
+
enablerPrefixes: ["@vitejs/", "@voidzero-dev/vite-plus"],
|
|
3131
3435
|
entryPatterns: [
|
|
3132
3436
|
"src/main.{ts,tsx,js,jsx}",
|
|
3133
3437
|
"src/index.{ts,tsx,js,jsx}",
|
|
@@ -3415,10 +3719,25 @@ const detectBunTestRunner = (directory) => {
|
|
|
3415
3719
|
return false;
|
|
3416
3720
|
}
|
|
3417
3721
|
};
|
|
3722
|
+
const readPackageJsonDependencies = (packageJsonPath) => {
|
|
3723
|
+
try {
|
|
3724
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
3725
|
+
const packageJson = JSON.parse(content);
|
|
3726
|
+
return {
|
|
3727
|
+
...packageJson.dependencies,
|
|
3728
|
+
...packageJson.devDependencies,
|
|
3729
|
+
...packageJson.optionalDependencies
|
|
3730
|
+
};
|
|
3731
|
+
} catch {
|
|
3732
|
+
return {};
|
|
3733
|
+
}
|
|
3734
|
+
};
|
|
3418
3735
|
const discoverTestRunnerEntryPoints = (rootDir, workspacePackages) => {
|
|
3419
3736
|
const allEntries = [];
|
|
3420
3737
|
const allAlwaysUsed = [];
|
|
3421
3738
|
const directoriesToCheck = [rootDir, ...workspacePackages.map((workspacePackage) => workspacePackage.directory)];
|
|
3739
|
+
const monorepoRoot = findMonorepoRoot(rootDir);
|
|
3740
|
+
const monorepoRootDeps = monorepoRoot && monorepoRoot !== rootDir ? readPackageJsonDependencies(join(monorepoRoot, "package.json")) : {};
|
|
3422
3741
|
for (const directory of directoriesToCheck) {
|
|
3423
3742
|
const packageJsonPath = join(directory, "package.json");
|
|
3424
3743
|
if (!existsSync(packageJsonPath)) continue;
|
|
@@ -3443,16 +3762,25 @@ const discoverTestRunnerEntryPoints = (rootDir, workspacePackages) => {
|
|
|
3443
3762
|
})) return true;
|
|
3444
3763
|
return runner.configFileActivators.some((configFile) => existsSync(join(checkDirectory, configFile)));
|
|
3445
3764
|
};
|
|
3446
|
-
for (const runner of TEST_FRAMEWORK_PATTERNS)
|
|
3447
|
-
const
|
|
3448
|
-
const
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3765
|
+
for (const runner of TEST_FRAMEWORK_PATTERNS) {
|
|
3766
|
+
const enabledLocally = isRunnerEnabled(runner, allDependencies, directory);
|
|
3767
|
+
const enabledViaMonorepo = !enabledLocally && monorepoRoot && (isRunnerEnabled(runner, monorepoRootDeps, monorepoRoot) || runner.configFileActivators.some((configFile) => existsSync(join(monorepoRoot, configFile))));
|
|
3768
|
+
if (enabledLocally || enabledViaMonorepo) {
|
|
3769
|
+
const isVitestRunner = runner.enablers.includes("vitest");
|
|
3770
|
+
const isJestRunner = runner.enablers.includes("jest");
|
|
3771
|
+
let customPatterns = [];
|
|
3772
|
+
if (isVitestRunner) {
|
|
3773
|
+
customPatterns = extractVitestIncludePatterns(directory);
|
|
3774
|
+
if (customPatterns.length === 0 && monorepoRoot) customPatterns = extractVitestIncludePatterns(monorepoRoot);
|
|
3775
|
+
} else if (isJestRunner) {
|
|
3776
|
+
customPatterns = extractJestTestMatchPatterns(directory);
|
|
3777
|
+
if (customPatterns.length === 0 && monorepoRoot) customPatterns = extractJestTestMatchPatterns(monorepoRoot);
|
|
3778
|
+
}
|
|
3779
|
+
if (customPatterns.length > 0) activatedPatterns.push(...customPatterns);
|
|
3780
|
+
else activatedPatterns.push(...runner.entryPatterns);
|
|
3781
|
+
activatedFixturePatterns.push(...runner.fixturePatterns);
|
|
3782
|
+
activatedAlwaysUsed.push(...runner.alwaysUsed);
|
|
3783
|
+
}
|
|
3456
3784
|
}
|
|
3457
3785
|
if (activatedPatterns.length === 0 && directory !== rootDir) {
|
|
3458
3786
|
const rootPackageJsonPath = join(rootDir, "package.json");
|
|
@@ -3517,6 +3845,45 @@ const isToolingPluginEnabled = (plugin, dependencies) => {
|
|
|
3517
3845
|
}
|
|
3518
3846
|
return false;
|
|
3519
3847
|
};
|
|
3848
|
+
const FRAMEWORK_SCRIPT_BINARIES = {
|
|
3849
|
+
next: ["next"],
|
|
3850
|
+
nuxt: ["nuxt"],
|
|
3851
|
+
astro: ["astro"],
|
|
3852
|
+
gatsby: ["gatsby"],
|
|
3853
|
+
remix: ["remix"],
|
|
3854
|
+
"@sveltejs/kit": ["svelte-kit", "vite-svelte-kit"],
|
|
3855
|
+
"@docusaurus/core": ["docusaurus"],
|
|
3856
|
+
"@angular/core": ["ng"],
|
|
3857
|
+
"@nestjs/core": ["nest"],
|
|
3858
|
+
storybook: [
|
|
3859
|
+
"storybook",
|
|
3860
|
+
"start-storybook",
|
|
3861
|
+
"build-storybook"
|
|
3862
|
+
]
|
|
3863
|
+
};
|
|
3864
|
+
const detectFrameworkFromScripts = (scripts) => {
|
|
3865
|
+
const enabledEnablers = /* @__PURE__ */ new Set();
|
|
3866
|
+
if (!scripts || typeof scripts !== "object") return enabledEnablers;
|
|
3867
|
+
for (const scriptValue of Object.values(scripts)) {
|
|
3868
|
+
if (typeof scriptValue !== "string") continue;
|
|
3869
|
+
const tokenized = scriptValue.split(/[\s|&;]+/);
|
|
3870
|
+
for (const token of tokenized) {
|
|
3871
|
+
const cleaned = token.replace(/^.*\//, "");
|
|
3872
|
+
for (const [enabler, binaries] of Object.entries(FRAMEWORK_SCRIPT_BINARIES)) if (binaries.includes(cleaned)) enabledEnablers.add(enabler);
|
|
3873
|
+
}
|
|
3874
|
+
}
|
|
3875
|
+
return enabledEnablers;
|
|
3876
|
+
};
|
|
3877
|
+
const readPackageScripts = (directory) => {
|
|
3878
|
+
const packageJsonPath = join(directory, "package.json");
|
|
3879
|
+
if (!existsSync(packageJsonPath)) return void 0;
|
|
3880
|
+
try {
|
|
3881
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
3882
|
+
return JSON.parse(content).scripts;
|
|
3883
|
+
} catch {
|
|
3884
|
+
return;
|
|
3885
|
+
}
|
|
3886
|
+
};
|
|
3520
3887
|
const discoverToolingEntryPoints = (rootDir, workspacePackages) => {
|
|
3521
3888
|
const allEntries = [];
|
|
3522
3889
|
const allAlwaysUsed = [];
|
|
@@ -3532,6 +3899,8 @@ const discoverToolingEntryPoints = (rootDir, workspacePackages) => {
|
|
|
3532
3899
|
...rootPackageJson.optionalDependencies
|
|
3533
3900
|
};
|
|
3534
3901
|
} catch {}
|
|
3902
|
+
const monorepoRoot = findMonorepoRoot(rootDir);
|
|
3903
|
+
const monorepoRootDeps = monorepoRoot && monorepoRoot !== rootDir ? readPackageJsonDependencies(join(monorepoRoot, "package.json")) : {};
|
|
3535
3904
|
for (const directory of directoriesToCheck) {
|
|
3536
3905
|
const packageJsonPath = join(directory, "package.json");
|
|
3537
3906
|
if (!existsSync(packageJsonPath)) continue;
|
|
@@ -3547,7 +3916,10 @@ const discoverToolingEntryPoints = (rootDir, workspacePackages) => {
|
|
|
3547
3916
|
} catch {
|
|
3548
3917
|
continue;
|
|
3549
3918
|
}
|
|
3550
|
-
const
|
|
3919
|
+
const scriptDetectedEnablers = detectFrameworkFromScripts(readPackageScripts(directory));
|
|
3920
|
+
const mergedDependencies = { ...workspaceDependencies };
|
|
3921
|
+
if (directory === rootDir) Object.assign(mergedDependencies, rootDependencies);
|
|
3922
|
+
else for (const enabler of scriptDetectedEnablers) if (enabler in monorepoRootDeps || enabler in rootDependencies) mergedDependencies[enabler] = "*";
|
|
3551
3923
|
const activatedPatterns = [];
|
|
3552
3924
|
const activatedAlwaysUsed = [];
|
|
3553
3925
|
for (const plugin of FRAMEWORK_PATTERNS) if (isToolingPluginEnabled(plugin, mergedDependencies)) {
|
|
@@ -3685,16 +4057,28 @@ const COMMON_RESOLVER_OPTIONS = {
|
|
|
3685
4057
|
".cjs": [".cts", ".cjs"]
|
|
3686
4058
|
}
|
|
3687
4059
|
};
|
|
4060
|
+
const WEBPACK_CONFIG_GLOBS = [
|
|
4061
|
+
"webpack.config.{js,ts,mjs,cjs}",
|
|
4062
|
+
"**/webpack*.config.{js,ts,mjs,cjs}",
|
|
4063
|
+
"**/webpack.config*.{js,ts,mjs,cjs}",
|
|
4064
|
+
"**/webpack*.config*.babel.{js,ts}"
|
|
4065
|
+
];
|
|
4066
|
+
const WEBPACK_ALIAS_BLOCK_PATTERN = /alias\s*:\s*\{([\s\S]*?)\}/g;
|
|
4067
|
+
const WEBPACK_ALIAS_ENTRY_PATTERN = /["']?([@\w$./-]+)["']?\s*:\s*(?:path\.(?:resolve|join)\(\s*__dirname\s*,\s*((?:["'][^"']+["']\s*,?\s*)+)\)|["']([^"']+)["'])/g;
|
|
4068
|
+
const WEBPACK_MODULES_BLOCK_PATTERN = /modules\s*:\s*\[([\s\S]*?)\]/g;
|
|
4069
|
+
const WEBPACK_PATH_CALL_PATTERN = /path\.(?:resolve|join)\(\s*__dirname\s*,\s*((?:["'][^"']+["']\s*,?\s*)+)\)/g;
|
|
4070
|
+
const WEBPACK_STRING_LITERAL_PATTERN = /["']([^"']+)["']/g;
|
|
3688
4071
|
const TSCONFIG_FILENAMES = [
|
|
3689
4072
|
"tsconfig.json",
|
|
3690
4073
|
"tsconfig.web.json",
|
|
3691
4074
|
"tsconfig.app.json",
|
|
3692
|
-
"tsconfig.base.json"
|
|
4075
|
+
"tsconfig.base.json",
|
|
4076
|
+
"jsconfig.json"
|
|
3693
4077
|
];
|
|
3694
|
-
const findNearestTsconfig = (fromDir, rootDir) => {
|
|
4078
|
+
const findNearestTsconfig = (fromDir, rootDir, monorepoRootDir) => {
|
|
3695
4079
|
let currentDirectory = fromDir;
|
|
3696
|
-
const
|
|
3697
|
-
while (currentDirectory.length >=
|
|
4080
|
+
const stopAt = monorepoRootDir ? resolve(monorepoRootDir) : resolve(rootDir);
|
|
4081
|
+
while (currentDirectory.length >= stopAt.length) {
|
|
3698
4082
|
for (const tsconfigFilename of TSCONFIG_FILENAMES) {
|
|
3699
4083
|
const tsconfigCandidate = join(currentDirectory, tsconfigFilename);
|
|
3700
4084
|
if (cachedExistsSync(tsconfigCandidate)) return tsconfigCandidate;
|
|
@@ -3733,6 +4117,108 @@ const resolveScssPartial = (specifier, fromDirectory) => {
|
|
|
3733
4117
|
candidates.push(join(basePath, `_index.sass`));
|
|
3734
4118
|
for (const candidate of candidates) if (cachedExistsSync(candidate)) return candidate;
|
|
3735
4119
|
};
|
|
4120
|
+
const isInsideDirectory = (filePath, directory) => {
|
|
4121
|
+
const relativePath = relative(directory, filePath);
|
|
4122
|
+
return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute(relativePath);
|
|
4123
|
+
};
|
|
4124
|
+
const extractQuotedSegments = (value) => {
|
|
4125
|
+
const segments = [];
|
|
4126
|
+
let segmentMatch;
|
|
4127
|
+
WEBPACK_STRING_LITERAL_PATTERN.lastIndex = 0;
|
|
4128
|
+
while ((segmentMatch = WEBPACK_STRING_LITERAL_PATTERN.exec(value)) !== null) segments.push(segmentMatch[1]);
|
|
4129
|
+
return segments;
|
|
4130
|
+
};
|
|
4131
|
+
const resolveWebpackPathValue = (value, configDirectory) => {
|
|
4132
|
+
if (isAbsolute(value)) return value;
|
|
4133
|
+
return resolve(configDirectory, value);
|
|
4134
|
+
};
|
|
4135
|
+
const findWebpackConfigScope = (configPath, rootDir) => {
|
|
4136
|
+
let currentDirectory = dirname(configPath);
|
|
4137
|
+
const absoluteRoot = resolve(rootDir);
|
|
4138
|
+
while (currentDirectory.length >= absoluteRoot.length) {
|
|
4139
|
+
if (cachedExistsSync(join(currentDirectory, "package.json"))) return currentDirectory;
|
|
4140
|
+
const parentDirectory = dirname(currentDirectory);
|
|
4141
|
+
if (parentDirectory === currentDirectory) break;
|
|
4142
|
+
currentDirectory = parentDirectory;
|
|
4143
|
+
}
|
|
4144
|
+
return absoluteRoot;
|
|
4145
|
+
};
|
|
4146
|
+
const extractWebpackAliases = (content, configDirectory) => {
|
|
4147
|
+
const aliases = [];
|
|
4148
|
+
let aliasBlockMatch;
|
|
4149
|
+
WEBPACK_ALIAS_BLOCK_PATTERN.lastIndex = 0;
|
|
4150
|
+
while ((aliasBlockMatch = WEBPACK_ALIAS_BLOCK_PATTERN.exec(content)) !== null) {
|
|
4151
|
+
const aliasBlock = aliasBlockMatch[1];
|
|
4152
|
+
let aliasEntryMatch;
|
|
4153
|
+
WEBPACK_ALIAS_ENTRY_PATTERN.lastIndex = 0;
|
|
4154
|
+
while ((aliasEntryMatch = WEBPACK_ALIAS_ENTRY_PATTERN.exec(aliasBlock)) !== null) {
|
|
4155
|
+
const rawName = aliasEntryMatch[1];
|
|
4156
|
+
const pathCallSegments = aliasEntryMatch[2];
|
|
4157
|
+
const stringTarget = aliasEntryMatch[3];
|
|
4158
|
+
if (!pathCallSegments && !stringTarget) continue;
|
|
4159
|
+
const isExact = rawName.endsWith("$");
|
|
4160
|
+
const name = isExact ? rawName.slice(0, -1) : rawName.replace(/\/$/, "");
|
|
4161
|
+
let targetDirectory;
|
|
4162
|
+
if (pathCallSegments) targetDirectory = resolve(configDirectory, ...extractQuotedSegments(pathCallSegments));
|
|
4163
|
+
else if (stringTarget) targetDirectory = resolveWebpackPathValue(stringTarget, configDirectory);
|
|
4164
|
+
else continue;
|
|
4165
|
+
aliases.push({
|
|
4166
|
+
name,
|
|
4167
|
+
targetDirectory,
|
|
4168
|
+
isExact
|
|
4169
|
+
});
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
return aliases;
|
|
4173
|
+
};
|
|
4174
|
+
const extractWebpackModuleDirectories = (content, configDirectory) => {
|
|
4175
|
+
const moduleDirectories = [];
|
|
4176
|
+
let modulesBlockMatch;
|
|
4177
|
+
WEBPACK_MODULES_BLOCK_PATTERN.lastIndex = 0;
|
|
4178
|
+
while ((modulesBlockMatch = WEBPACK_MODULES_BLOCK_PATTERN.exec(content)) !== null) {
|
|
4179
|
+
const modulesBlock = modulesBlockMatch[1];
|
|
4180
|
+
let pathCallMatch;
|
|
4181
|
+
WEBPACK_PATH_CALL_PATTERN.lastIndex = 0;
|
|
4182
|
+
while ((pathCallMatch = WEBPACK_PATH_CALL_PATTERN.exec(modulesBlock)) !== null) moduleDirectories.push(resolve(configDirectory, ...extractQuotedSegments(pathCallMatch[1])));
|
|
4183
|
+
let stringMatch;
|
|
4184
|
+
WEBPACK_STRING_LITERAL_PATTERN.lastIndex = 0;
|
|
4185
|
+
while ((stringMatch = WEBPACK_STRING_LITERAL_PATTERN.exec(modulesBlock)) !== null) {
|
|
4186
|
+
const moduleDirectory = stringMatch[1];
|
|
4187
|
+
if (moduleDirectory === "node_modules") continue;
|
|
4188
|
+
moduleDirectories.push(resolveWebpackPathValue(moduleDirectory, configDirectory));
|
|
4189
|
+
}
|
|
4190
|
+
}
|
|
4191
|
+
return [...new Set(moduleDirectories)];
|
|
4192
|
+
};
|
|
4193
|
+
const loadWebpackResolverConfigs = (rootDir) => {
|
|
4194
|
+
const configPaths = fg.sync(WEBPACK_CONFIG_GLOBS, {
|
|
4195
|
+
cwd: rootDir,
|
|
4196
|
+
absolute: true,
|
|
4197
|
+
onlyFiles: true,
|
|
4198
|
+
ignore: [
|
|
4199
|
+
"**/node_modules/**",
|
|
4200
|
+
"**/dist/**",
|
|
4201
|
+
"**/build/**"
|
|
4202
|
+
],
|
|
4203
|
+
deep: 4
|
|
4204
|
+
});
|
|
4205
|
+
const configs = [];
|
|
4206
|
+
for (const configPath of configPaths) try {
|
|
4207
|
+
const content = cachedReadFileSync(configPath);
|
|
4208
|
+
const configDirectory = dirname(configPath);
|
|
4209
|
+
const aliases = extractWebpackAliases(content, configDirectory);
|
|
4210
|
+
const moduleDirectories = extractWebpackModuleDirectories(content, configDirectory);
|
|
4211
|
+
if (aliases.length === 0 && moduleDirectories.length === 0) continue;
|
|
4212
|
+
configs.push({
|
|
4213
|
+
scopeDirectory: findWebpackConfigScope(configPath, rootDir),
|
|
4214
|
+
aliases,
|
|
4215
|
+
moduleDirectories
|
|
4216
|
+
});
|
|
4217
|
+
} catch {
|
|
4218
|
+
continue;
|
|
4219
|
+
}
|
|
4220
|
+
return configs;
|
|
4221
|
+
};
|
|
3736
4222
|
const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
3737
4223
|
const resolverCache = /* @__PURE__ */ new Map();
|
|
3738
4224
|
const resolveResultCache = /* @__PURE__ */ new Map();
|
|
@@ -3769,18 +4255,20 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3769
4255
|
};
|
|
3770
4256
|
const workspaceNameToDirectory = /* @__PURE__ */ new Map();
|
|
3771
4257
|
for (const workspacePackage of workspacePackages) workspaceNameToDirectory.set(workspacePackage.name, workspacePackage.directory);
|
|
4258
|
+
const webpackResolverConfigs = (options.monorepoRoot && options.monorepoRoot !== config.rootDir ? [config.rootDir, options.monorepoRoot] : [config.rootDir]).flatMap(loadWebpackResolverConfigs).sort((leftConfig, rightConfig) => rightConfig.scopeDirectory.length - leftConfig.scopeDirectory.length);
|
|
3772
4259
|
let rootTsconfigPath;
|
|
3773
4260
|
if (config.tsConfigPath) rootTsconfigPath = resolve(config.rootDir, config.tsConfigPath);
|
|
3774
|
-
else
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
4261
|
+
else {
|
|
4262
|
+
const tsconfigSearchDirs = options.monorepoRoot ? [config.rootDir, options.monorepoRoot] : [config.rootDir];
|
|
4263
|
+
for (const searchDir of tsconfigSearchDirs) {
|
|
4264
|
+
for (const candidate of TSCONFIG_FILENAMES) {
|
|
4265
|
+
const candidatePath = resolve(searchDir, candidate);
|
|
4266
|
+
if (cachedExistsSync(candidatePath)) {
|
|
4267
|
+
rootTsconfigPath = candidatePath;
|
|
4268
|
+
break;
|
|
4269
|
+
}
|
|
4270
|
+
}
|
|
4271
|
+
if (rootTsconfigPath) break;
|
|
3784
4272
|
}
|
|
3785
4273
|
}
|
|
3786
4274
|
const tsconfigPathCache = /* @__PURE__ */ new Map();
|
|
@@ -3789,24 +4277,56 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3789
4277
|
const fileDir = dirname(filePath);
|
|
3790
4278
|
const cached = tsconfigPathCache.get(fileDir);
|
|
3791
4279
|
if (cached !== void 0) return cached;
|
|
3792
|
-
const tsconfigResult = findNearestTsconfig(fileDir, config.rootDir) ?? rootTsconfigPath;
|
|
4280
|
+
const tsconfigResult = findNearestTsconfig(fileDir, config.rootDir, options.monorepoRoot) ?? rootTsconfigPath;
|
|
3793
4281
|
tsconfigPathCache.set(fileDir, tsconfigResult);
|
|
3794
4282
|
return tsconfigResult;
|
|
3795
4283
|
};
|
|
3796
4284
|
const tsconfigBaseUrlCache = /* @__PURE__ */ new Map();
|
|
3797
|
-
const
|
|
3798
|
-
|
|
3799
|
-
|
|
4285
|
+
const resolveExtendsPath = (extendsValue, fromDir) => {
|
|
4286
|
+
if (extendsValue.startsWith(".")) {
|
|
4287
|
+
const absolutePath = resolve(fromDir, extendsValue);
|
|
4288
|
+
if (cachedExistsSync(absolutePath)) return absolutePath;
|
|
4289
|
+
if (cachedExistsSync(absolutePath + ".json")) return absolutePath + ".json";
|
|
4290
|
+
return;
|
|
4291
|
+
}
|
|
4292
|
+
const packagePath = join(options.monorepoRoot ?? config.rootDir, "node_modules", extendsValue);
|
|
4293
|
+
if (cachedExistsSync(packagePath)) return packagePath;
|
|
4294
|
+
if (cachedExistsSync(packagePath + ".json")) return packagePath + ".json";
|
|
4295
|
+
const localPackagePath = join(fromDir, "node_modules", extendsValue);
|
|
4296
|
+
if (cachedExistsSync(localPackagePath)) return localPackagePath;
|
|
4297
|
+
if (cachedExistsSync(localPackagePath + ".json")) return localPackagePath + ".json";
|
|
4298
|
+
};
|
|
4299
|
+
const collectExtendsEntries = (tsconfigJson) => {
|
|
4300
|
+
if (typeof tsconfigJson.extends === "string") return [tsconfigJson.extends];
|
|
4301
|
+
if (Array.isArray(tsconfigJson.extends)) return tsconfigJson.extends.filter((entry) => typeof entry === "string");
|
|
4302
|
+
return [];
|
|
4303
|
+
};
|
|
4304
|
+
const extractBaseUrlFromTsconfig = (tsconfigFile, visitedFiles) => {
|
|
4305
|
+
if (visitedFiles.has(tsconfigFile)) return void 0;
|
|
4306
|
+
visitedFiles.add(tsconfigFile);
|
|
3800
4307
|
try {
|
|
3801
4308
|
const cleanedContent = stripJsonComments(cachedReadFileSync(tsconfigFile));
|
|
3802
|
-
const
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
4309
|
+
const tsconfigJson = JSON.parse(cleanedContent);
|
|
4310
|
+
const tsconfigDir = dirname(tsconfigFile);
|
|
4311
|
+
const baseUrl = tsconfigJson.compilerOptions?.baseUrl;
|
|
4312
|
+
if (baseUrl) return resolve(tsconfigDir, baseUrl);
|
|
4313
|
+
for (const extendsEntry of collectExtendsEntries(tsconfigJson)) {
|
|
4314
|
+
const resolvedPath = resolveExtendsPath(extendsEntry, tsconfigDir);
|
|
4315
|
+
if (resolvedPath) {
|
|
4316
|
+
const result = extractBaseUrlFromTsconfig(resolvedPath, visitedFiles);
|
|
4317
|
+
if (result) return result;
|
|
4318
|
+
}
|
|
3807
4319
|
}
|
|
3808
|
-
} catch {
|
|
3809
|
-
|
|
4320
|
+
} catch {
|
|
4321
|
+
return;
|
|
4322
|
+
}
|
|
4323
|
+
};
|
|
4324
|
+
const getBaseUrlDirectory = (tsconfigFile) => {
|
|
4325
|
+
const cached = tsconfigBaseUrlCache.get(tsconfigFile);
|
|
4326
|
+
if (cached !== void 0) return cached;
|
|
4327
|
+
const result = extractBaseUrlFromTsconfig(tsconfigFile, /* @__PURE__ */ new Set());
|
|
4328
|
+
tsconfigBaseUrlCache.set(tsconfigFile, result);
|
|
4329
|
+
return result;
|
|
3810
4330
|
};
|
|
3811
4331
|
const hasNextJsDependency = (() => {
|
|
3812
4332
|
try {
|
|
@@ -3819,25 +4339,83 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3819
4339
|
return false;
|
|
3820
4340
|
}
|
|
3821
4341
|
})();
|
|
3822
|
-
const
|
|
3823
|
-
|
|
4342
|
+
const packageDependencyCache = /* @__PURE__ */ new Map();
|
|
4343
|
+
const readPackageDependencies = (directory) => {
|
|
4344
|
+
const cached = packageDependencyCache.get(directory);
|
|
3824
4345
|
if (cached) return cached;
|
|
3825
|
-
const
|
|
3826
|
-
const
|
|
4346
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
4347
|
+
const packageJsonPath = join(directory, "package.json");
|
|
4348
|
+
try {
|
|
4349
|
+
const packageJson = JSON.parse(cachedReadFileSync(packageJsonPath));
|
|
4350
|
+
const dependencySections = [
|
|
4351
|
+
packageJson.dependencies,
|
|
4352
|
+
packageJson.devDependencies,
|
|
4353
|
+
packageJson.optionalDependencies
|
|
4354
|
+
];
|
|
4355
|
+
for (const dependencySection of dependencySections) {
|
|
4356
|
+
if (!dependencySection || typeof dependencySection !== "object") continue;
|
|
4357
|
+
for (const dependencyName of Object.keys(dependencySection)) dependencies.add(dependencyName);
|
|
4358
|
+
}
|
|
4359
|
+
} catch {}
|
|
4360
|
+
packageDependencyCache.set(directory, dependencies);
|
|
4361
|
+
return dependencies;
|
|
4362
|
+
};
|
|
4363
|
+
const findNearestPackageSrcDirectoryWithDependency = (filePath, dependencyNames) => {
|
|
4364
|
+
let currentDirectory = dirname(filePath);
|
|
4365
|
+
const stopAt = options.monorepoRoot ? resolve(options.monorepoRoot) : resolve(config.rootDir);
|
|
4366
|
+
while (currentDirectory.length >= stopAt.length) {
|
|
4367
|
+
if (cachedExistsSync(join(currentDirectory, "package.json"))) {
|
|
4368
|
+
const dependencies = readPackageDependencies(currentDirectory);
|
|
4369
|
+
if (dependencyNames.some((dependencyName) => dependencies.has(dependencyName))) {
|
|
4370
|
+
const srcDirectory = join(currentDirectory, "src");
|
|
4371
|
+
return cachedExistsSync(srcDirectory) ? srcDirectory : void 0;
|
|
4372
|
+
}
|
|
4373
|
+
}
|
|
4374
|
+
const parentDirectory = dirname(currentDirectory);
|
|
4375
|
+
if (parentDirectory === currentDirectory) break;
|
|
4376
|
+
currentDirectory = parentDirectory;
|
|
4377
|
+
}
|
|
4378
|
+
};
|
|
4379
|
+
const extractPathsFromTsconfig = (tsconfigFile, visitedFiles) => {
|
|
4380
|
+
if (visitedFiles.has(tsconfigFile)) return void 0;
|
|
4381
|
+
visitedFiles.add(tsconfigFile);
|
|
3827
4382
|
try {
|
|
3828
4383
|
const tsconfigContent = cachedReadFileSync(tsconfigFile).trim();
|
|
3829
|
-
if (tsconfigContent.length
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
4384
|
+
if (tsconfigContent.length === 0) return void 0;
|
|
4385
|
+
const cleanedContent = stripJsonComments(tsconfigContent);
|
|
4386
|
+
const tsconfigJson = JSON.parse(cleanedContent);
|
|
4387
|
+
const tsconfigDir = dirname(tsconfigFile);
|
|
4388
|
+
const paths = tsconfigJson.compilerOptions?.paths;
|
|
4389
|
+
const baseUrl = tsconfigJson.compilerOptions?.baseUrl;
|
|
4390
|
+
if (paths && typeof paths === "object") return {
|
|
4391
|
+
paths,
|
|
4392
|
+
baseUrl: baseUrl ?? ".",
|
|
4393
|
+
tsconfigDir
|
|
4394
|
+
};
|
|
4395
|
+
for (const extendsEntry of collectExtendsEntries(tsconfigJson)) {
|
|
4396
|
+
const resolvedPath = resolveExtendsPath(extendsEntry, tsconfigDir);
|
|
4397
|
+
if (resolvedPath) {
|
|
4398
|
+
const result = extractPathsFromTsconfig(resolvedPath, visitedFiles);
|
|
4399
|
+
if (result) return result;
|
|
3836
4400
|
}
|
|
3837
4401
|
}
|
|
3838
|
-
} catch {
|
|
3839
|
-
|
|
3840
|
-
|
|
4402
|
+
} catch {
|
|
4403
|
+
return;
|
|
4404
|
+
}
|
|
4405
|
+
};
|
|
4406
|
+
const getPathAliases = (tsconfigFile) => {
|
|
4407
|
+
const cached = tsconfigPathAliasCache.get(tsconfigFile);
|
|
4408
|
+
if (cached) return cached;
|
|
4409
|
+
const aliasMap = /* @__PURE__ */ new Map();
|
|
4410
|
+
const extracted = extractPathsFromTsconfig(tsconfigFile, /* @__PURE__ */ new Set());
|
|
4411
|
+
if (extracted) {
|
|
4412
|
+
for (const [pattern, targets] of Object.entries(extracted.paths)) if (Array.isArray(targets)) aliasMap.set(pattern, targets.map((target) => resolve(extracted.tsconfigDir, extracted.baseUrl, target)));
|
|
4413
|
+
}
|
|
4414
|
+
if (aliasMap.size === 0 && hasNextJsDependency) {
|
|
4415
|
+
const tsconfigDir = dirname(tsconfigFile);
|
|
4416
|
+
if (cachedExistsSync(resolve(tsconfigDir, "src"))) aliasMap.set("@/*", [resolve(tsconfigDir, "src/*")]);
|
|
4417
|
+
else aliasMap.set("@/*", [resolve(tsconfigDir, "*")]);
|
|
4418
|
+
}
|
|
3841
4419
|
tsconfigPathAliasCache.set(tsconfigFile, aliasMap);
|
|
3842
4420
|
return aliasMap;
|
|
3843
4421
|
};
|
|
@@ -3874,6 +4452,28 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3874
4452
|
}
|
|
3875
4453
|
}
|
|
3876
4454
|
};
|
|
4455
|
+
const tryResolveFromDirectory = (directory, specifier) => {
|
|
4456
|
+
const candidatePath = resolvePathWithExtensionFallback(resolve(directory, specifier));
|
|
4457
|
+
if (existsAsFile(candidatePath)) return candidatePath;
|
|
4458
|
+
};
|
|
4459
|
+
const tryResolveViaWebpackConfig = (specifier, fromFile) => {
|
|
4460
|
+
if (webpackResolverConfigs.length === 0) return void 0;
|
|
4461
|
+
if (!isBareSpecifier(specifier)) return void 0;
|
|
4462
|
+
for (const webpackConfig of webpackResolverConfigs) {
|
|
4463
|
+
if (!isInsideDirectory(fromFile, webpackConfig.scopeDirectory)) continue;
|
|
4464
|
+
for (const alias of webpackConfig.aliases) {
|
|
4465
|
+
if (alias.isExact && specifier !== alias.name) continue;
|
|
4466
|
+
const suffix = specifier === alias.name ? "" : specifier.startsWith(`${alias.name}/`) ? specifier.slice(alias.name.length + 1) : void 0;
|
|
4467
|
+
if (suffix === void 0) continue;
|
|
4468
|
+
const aliasCandidate = tryResolveFromDirectory(alias.targetDirectory, suffix);
|
|
4469
|
+
if (aliasCandidate) return aliasCandidate;
|
|
4470
|
+
}
|
|
4471
|
+
for (const moduleDirectory of webpackConfig.moduleDirectories) {
|
|
4472
|
+
const moduleCandidate = tryResolveFromDirectory(moduleDirectory, specifier);
|
|
4473
|
+
if (moduleCandidate) return moduleCandidate;
|
|
4474
|
+
}
|
|
4475
|
+
}
|
|
4476
|
+
};
|
|
3877
4477
|
const resolveModule = (specifier, fromFile) => {
|
|
3878
4478
|
const queryIndex = specifier.indexOf("?");
|
|
3879
4479
|
const cleanedSpecifier = queryIndex !== -1 ? specifier.slice(0, queryIndex) : specifier;
|
|
@@ -4037,6 +4637,16 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
4037
4637
|
resolveResultCache.set(cacheKey, resolvedResult);
|
|
4038
4638
|
return resolvedResult;
|
|
4039
4639
|
}
|
|
4640
|
+
const webpackResolved = tryResolveViaWebpackConfig(cleanedSpecifier, fromFile);
|
|
4641
|
+
if (webpackResolved) {
|
|
4642
|
+
const resolvedResult = {
|
|
4643
|
+
resolvedPath: webpackResolved,
|
|
4644
|
+
isExternal: false,
|
|
4645
|
+
packageName: void 0
|
|
4646
|
+
};
|
|
4647
|
+
resolveResultCache.set(cacheKey, resolvedResult);
|
|
4648
|
+
return resolvedResult;
|
|
4649
|
+
}
|
|
4040
4650
|
if (isBareSpecifier(cleanedSpecifier)) {
|
|
4041
4651
|
const tsconfigFile = findTsconfigForFile(fromFile);
|
|
4042
4652
|
if (tsconfigFile) {
|
|
@@ -4070,6 +4680,19 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
4070
4680
|
}
|
|
4071
4681
|
}
|
|
4072
4682
|
}
|
|
4683
|
+
const createReactAppSrcDirectory = findNearestPackageSrcDirectoryWithDependency(fromFile, ["react-scripts", "react-app-rewired"]);
|
|
4684
|
+
if (createReactAppSrcDirectory) {
|
|
4685
|
+
const craResolved = tryResolveFromDirectory(createReactAppSrcDirectory, cleanedSpecifier);
|
|
4686
|
+
if (craResolved) {
|
|
4687
|
+
const resolvedResult = {
|
|
4688
|
+
resolvedPath: craResolved,
|
|
4689
|
+
isExternal: false,
|
|
4690
|
+
packageName: void 0
|
|
4691
|
+
};
|
|
4692
|
+
resolveResultCache.set(cacheKey, resolvedResult);
|
|
4693
|
+
return resolvedResult;
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4073
4696
|
const resolvedResult = {
|
|
4074
4697
|
resolvedPath: void 0,
|
|
4075
4698
|
isExternal: true,
|
|
@@ -4533,12 +5156,16 @@ const detectDeadExports = (graph, config) => {
|
|
|
4533
5156
|
if (!module.isReachable) continue;
|
|
4534
5157
|
if (module.isDeclarationFile) continue;
|
|
4535
5158
|
if (module.isEntryPoint && !config.includeEntryExports) continue;
|
|
5159
|
+
const defaultExportLinkedNames = /* @__PURE__ */ new Set();
|
|
5160
|
+
for (const exportInfo of module.exports) if (exportInfo.isDefault && exportInfo.defaultExportLocalName && usageMap.has(`${module.fileId.path}::default`)) defaultExportLinkedNames.add(exportInfo.defaultExportLocalName);
|
|
4536
5161
|
for (const exportInfo of module.exports) {
|
|
4537
5162
|
if (exportInfo.name === "*" && exportInfo.isNamespaceReExport) continue;
|
|
4538
5163
|
if (exportInfo.isReExport && exportInfo.reExportOriginalName) continue;
|
|
4539
5164
|
if (!config.reportTypes && exportInfo.isTypeOnly) continue;
|
|
4540
5165
|
const usageKey = `${module.fileId.path}::${exportInfo.name}`;
|
|
4541
|
-
if (
|
|
5166
|
+
if (usageMap.has(usageKey)) continue;
|
|
5167
|
+
if (!exportInfo.isDefault && defaultExportLinkedNames.has(exportInfo.name)) continue;
|
|
5168
|
+
unusedExports.push({
|
|
4542
5169
|
path: module.fileId.path,
|
|
4543
5170
|
name: exportInfo.name,
|
|
4544
5171
|
line: exportInfo.line,
|
|
@@ -4654,62 +5281,18 @@ const followReExportChain = (reExporterModuleIndex, exportInfo, graph, sourceToT
|
|
|
4654
5281
|
//#endregion
|
|
4655
5282
|
//#region src/utils/package-name.ts
|
|
4656
5283
|
const extractPackageName = (specifier) => {
|
|
4657
|
-
|
|
5284
|
+
const normalizedSpecifier = specifier.startsWith("~") ? specifier.slice(1) : specifier;
|
|
5285
|
+
if (normalizedSpecifier.startsWith(".") || normalizedSpecifier.startsWith("/")) return void 0;
|
|
4658
5286
|
if (specifier.startsWith("node:")) return void 0;
|
|
4659
|
-
if (
|
|
4660
|
-
const parts =
|
|
5287
|
+
if (normalizedSpecifier.startsWith("@")) {
|
|
5288
|
+
const parts = normalizedSpecifier.split("/");
|
|
4661
5289
|
return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : void 0;
|
|
4662
5290
|
}
|
|
4663
|
-
return
|
|
5291
|
+
return normalizedSpecifier.split("/")[0];
|
|
4664
5292
|
};
|
|
4665
5293
|
|
|
4666
5294
|
//#endregion
|
|
4667
5295
|
//#region src/report/packages.ts
|
|
4668
|
-
const MONOREPO_ROOT_MARKERS = [
|
|
4669
|
-
"pnpm-workspace.yaml",
|
|
4670
|
-
"pnpm-workspace.yml",
|
|
4671
|
-
"lerna.json",
|
|
4672
|
-
"nx.json",
|
|
4673
|
-
"turbo.json",
|
|
4674
|
-
"rush.json"
|
|
4675
|
-
];
|
|
4676
|
-
const LOCKFILE_MARKERS = [
|
|
4677
|
-
"pnpm-lock.yaml",
|
|
4678
|
-
"yarn.lock",
|
|
4679
|
-
"package-lock.json",
|
|
4680
|
-
"bun.lockb",
|
|
4681
|
-
"bun.lock"
|
|
4682
|
-
];
|
|
4683
|
-
const MAX_MONOREPO_WALK_DEPTH = 5;
|
|
4684
|
-
const findMonorepoRoot = (rootDir) => {
|
|
4685
|
-
let currentDirectory = resolve(rootDir);
|
|
4686
|
-
let walkedDepth = 0;
|
|
4687
|
-
while (walkedDepth < MAX_MONOREPO_WALK_DEPTH) {
|
|
4688
|
-
const parentDirectory = dirname(currentDirectory);
|
|
4689
|
-
if (parentDirectory === currentDirectory) break;
|
|
4690
|
-
currentDirectory = parentDirectory;
|
|
4691
|
-
walkedDepth++;
|
|
4692
|
-
if (existsSync(join(currentDirectory, ".git"))) {
|
|
4693
|
-
for (const marker of MONOREPO_ROOT_MARKERS) if (existsSync(join(currentDirectory, marker))) return currentDirectory;
|
|
4694
|
-
const packageJsonPath = join(currentDirectory, "package.json");
|
|
4695
|
-
if (existsSync(packageJsonPath)) try {
|
|
4696
|
-
const content = readFileSync(packageJsonPath, "utf-8");
|
|
4697
|
-
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
4698
|
-
} catch {}
|
|
4699
|
-
for (const lockfile of LOCKFILE_MARKERS) if (existsSync(join(currentDirectory, lockfile))) return currentDirectory;
|
|
4700
|
-
return;
|
|
4701
|
-
}
|
|
4702
|
-
for (const marker of MONOREPO_ROOT_MARKERS) if (existsSync(join(currentDirectory, marker))) return currentDirectory;
|
|
4703
|
-
const packageJsonPath = join(currentDirectory, "package.json");
|
|
4704
|
-
if (existsSync(packageJsonPath)) try {
|
|
4705
|
-
const content = readFileSync(packageJsonPath, "utf-8");
|
|
4706
|
-
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
4707
|
-
} catch {
|
|
4708
|
-
continue;
|
|
4709
|
-
}
|
|
4710
|
-
for (const lockfile of LOCKFILE_MARKERS) if (existsSync(join(currentDirectory, lockfile))) return currentDirectory;
|
|
4711
|
-
}
|
|
4712
|
-
};
|
|
4713
5296
|
const discoverAllPackageJsonPaths = (rootDir) => {
|
|
4714
5297
|
const paths = [join(rootDir, "package.json")];
|
|
4715
5298
|
const workspacePackageJsons = fg.sync("**/package.json", {
|
|
@@ -4757,6 +5340,8 @@ const detectStalePackages = (graph, config) => {
|
|
|
4757
5340
|
const packageJsonConfigReferenced = collectPackageJsonConfigReferences(workspacePackageJsonPath, declaredNames);
|
|
4758
5341
|
for (const packageName of packageJsonConfigReferenced) usedPackageNames.add(packageName);
|
|
4759
5342
|
}
|
|
5343
|
+
const nxProjectReferenced = collectNxProjectJsonReferences(config.rootDir, declaredNames, binToPackage);
|
|
5344
|
+
for (const packageName of nxProjectReferenced) usedPackageNames.add(packageName);
|
|
4760
5345
|
const configSearchRoots = monorepoRoot && monorepoRoot !== config.rootDir ? [config.rootDir, monorepoRoot] : [config.rootDir];
|
|
4761
5346
|
for (const configSearchRoot of configSearchRoots) {
|
|
4762
5347
|
const configReferenced = collectConfigReferencedPackages(configSearchRoot, graph, declaredNames);
|
|
@@ -4770,8 +5355,36 @@ const detectStalePackages = (graph, config) => {
|
|
|
4770
5355
|
if (declaredNames.has("react-native")) usedPackageNames.add("react-native");
|
|
4771
5356
|
if (declaredNames.has("react-native-web")) usedPackageNames.add("react-native-web");
|
|
4772
5357
|
}
|
|
5358
|
+
if (declaredNames.has("react-dom")) {
|
|
5359
|
+
if ([
|
|
5360
|
+
"next",
|
|
5361
|
+
"gatsby",
|
|
5362
|
+
"@remix-run/react",
|
|
5363
|
+
"react-router-dom",
|
|
5364
|
+
"vite",
|
|
5365
|
+
"@docusaurus/core",
|
|
5366
|
+
"react-scripts",
|
|
5367
|
+
"astro",
|
|
5368
|
+
"@tanstack/react-router",
|
|
5369
|
+
"@tanstack/react-start",
|
|
5370
|
+
"react-app-rewired"
|
|
5371
|
+
].some((framework) => declaredNames.has(framework) || usedPackageNames.has(framework))) usedPackageNames.add("react-dom");
|
|
5372
|
+
}
|
|
5373
|
+
if (declaredNames.has("react") && declaredNames.has("react-dom")) {
|
|
5374
|
+
const packageJsonPath = resolve(config.rootDir, "package.json");
|
|
5375
|
+
try {
|
|
5376
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
5377
|
+
const peerDeps = JSON.parse(content).peerDependencies ?? {};
|
|
5378
|
+
if ("react" in peerDeps && declaredDependencies.get("react") === true) usedPackageNames.add("react");
|
|
5379
|
+
if ("react-dom" in peerDeps && declaredDependencies.get("react-dom") === true) usedPackageNames.add("react-dom");
|
|
5380
|
+
} catch {}
|
|
5381
|
+
}
|
|
4773
5382
|
const peerSatisfied = collectPeerSatisfiedPackages(nodeModulesRoot, declaredNames, usedPackageNames);
|
|
4774
5383
|
for (const packageName of peerSatisfied) usedPackageNames.add(packageName);
|
|
5384
|
+
const staticPeerSatisfied = collectStaticPeerSatisfiedPackages(declaredNames, usedPackageNames);
|
|
5385
|
+
for (const packageName of staticPeerSatisfied) usedPackageNames.add(packageName);
|
|
5386
|
+
const implicitCompanionPackages = collectImplicitCompanionPackages(declaredNames, usedPackageNames);
|
|
5387
|
+
for (const packageName of implicitCompanionPackages) usedPackageNames.add(packageName);
|
|
4775
5388
|
const candidateUnused = /* @__PURE__ */ new Set();
|
|
4776
5389
|
for (const [dependencyName] of declaredDependencies) {
|
|
4777
5390
|
if (isAlwaysConsideredUsed(dependencyName)) continue;
|
|
@@ -4825,11 +5438,75 @@ const collectPeerSatisfiedPackages = (rootDir, declaredNames, confirmedUsedNames
|
|
|
4825
5438
|
}
|
|
4826
5439
|
return peerSatisfied;
|
|
4827
5440
|
};
|
|
5441
|
+
const STATIC_PEER_DEPENDENCY_MAP = {
|
|
5442
|
+
"@apollo/client": ["graphql"],
|
|
5443
|
+
"@docusaurus/core": ["@mdx-js/react"],
|
|
5444
|
+
"@fortawesome/react-fontawesome": ["@fortawesome/fontawesome-svg-core"],
|
|
5445
|
+
"@gorhom/bottom-sheet": ["react-native-gesture-handler", "react-native-reanimated"],
|
|
5446
|
+
"@hookform/resolvers": ["zod"],
|
|
5447
|
+
"@mdx-js/loader": ["@mdx-js/react"],
|
|
5448
|
+
"@mui/material": ["react-transition-group", "styled-components"],
|
|
5449
|
+
"@stripe/react-stripe-js": ["@stripe/stripe-js"],
|
|
5450
|
+
"@tiptap/core": ["@tiptap/pm"],
|
|
5451
|
+
"@tiptap/react": ["@tiptap/pm"],
|
|
5452
|
+
"@trpc/server": ["zod"],
|
|
5453
|
+
"chart.js": [],
|
|
5454
|
+
"fumadocs-core": ["@mdx-js/react"],
|
|
5455
|
+
"fumadocs-mdx": ["@mdx-js/react"],
|
|
5456
|
+
"fumadocs-ui": ["@mdx-js/react"],
|
|
5457
|
+
"graphql-request": ["graphql"],
|
|
5458
|
+
nextra: ["@mdx-js/react"],
|
|
5459
|
+
"nextra-theme-blog": ["@mdx-js/react"],
|
|
5460
|
+
"nextra-theme-docs": ["@mdx-js/react"],
|
|
5461
|
+
"react-app-polyfill": ["core-js"],
|
|
5462
|
+
"react-bootstrap": ["react-transition-group"],
|
|
5463
|
+
"react-chartjs-2": ["chart.js"],
|
|
5464
|
+
"react-redux": ["redux"],
|
|
5465
|
+
"react-router-dom": ["react-router"],
|
|
5466
|
+
"redux-thunk": ["redux"],
|
|
5467
|
+
sanity: ["styled-components"],
|
|
5468
|
+
sequelize: ["pg"],
|
|
5469
|
+
"stylis-plugin-rtl": ["stylis"],
|
|
5470
|
+
urql: ["graphql"],
|
|
5471
|
+
"use-immer": ["immer"],
|
|
5472
|
+
zustand: ["immer"]
|
|
5473
|
+
};
|
|
5474
|
+
const collectStaticPeerSatisfiedPackages = (declaredNames, confirmedUsedNames) => {
|
|
5475
|
+
const peerSatisfied = /* @__PURE__ */ new Set();
|
|
5476
|
+
for (const [packageName, peerNames] of Object.entries(STATIC_PEER_DEPENDENCY_MAP)) {
|
|
5477
|
+
if (!confirmedUsedNames.has(packageName)) continue;
|
|
5478
|
+
for (const peerName of peerNames) if (declaredNames.has(peerName)) peerSatisfied.add(peerName);
|
|
5479
|
+
}
|
|
5480
|
+
return peerSatisfied;
|
|
5481
|
+
};
|
|
5482
|
+
const IMPLICIT_COMPANION_DEPENDENCY_MAP = {
|
|
5483
|
+
jest: ["jest-config"],
|
|
5484
|
+
"jest-cli": ["jest-config"]
|
|
5485
|
+
};
|
|
5486
|
+
const collectImplicitCompanionPackages = (declaredNames, confirmedUsedNames) => {
|
|
5487
|
+
const companions = /* @__PURE__ */ new Set();
|
|
5488
|
+
for (const [packageName, companionNames] of Object.entries(IMPLICIT_COMPANION_DEPENDENCY_MAP)) {
|
|
5489
|
+
if (!confirmedUsedNames.has(packageName)) continue;
|
|
5490
|
+
for (const companionName of companionNames) if (declaredNames.has(companionName)) companions.add(companionName);
|
|
5491
|
+
}
|
|
5492
|
+
return companions;
|
|
5493
|
+
};
|
|
4828
5494
|
const SHELL_SPLIT_PATTERN = /\s*(?:&&|\|\||[;&|])\s*/;
|
|
4829
5495
|
const CLI_BINARY_TO_PACKAGE = {
|
|
5496
|
+
"babel-node": "@babel/node",
|
|
5497
|
+
"trigger.dev": "trigger.dev",
|
|
5498
|
+
"@formatjs/cli": "@formatjs/cli",
|
|
4830
5499
|
"react-scripts": "react-scripts",
|
|
4831
5500
|
"webpack-cli": "webpack-cli",
|
|
4832
5501
|
"webpack-dev-server": "webpack-dev-server",
|
|
5502
|
+
babel: "@babel/cli",
|
|
5503
|
+
chokidar: "chokidar-cli",
|
|
5504
|
+
"replace-in-file": "replace-in-file",
|
|
5505
|
+
tauri: "@tauri-apps/cli",
|
|
5506
|
+
tinacms: "@tinacms/cli",
|
|
5507
|
+
"tsc-alias": "tsc-alias",
|
|
5508
|
+
formatjs: "@formatjs/cli",
|
|
5509
|
+
prompt: "prompt",
|
|
4833
5510
|
vitest: "vitest",
|
|
4834
5511
|
jest: "jest",
|
|
4835
5512
|
prisma: "prisma",
|
|
@@ -4847,6 +5524,10 @@ const CLI_BINARY_TO_PACKAGE = {
|
|
|
4847
5524
|
"generate-arg-types": "@webstudio-is/generate-arg-types",
|
|
4848
5525
|
email: "@react-email/preview-server"
|
|
4849
5526
|
};
|
|
5527
|
+
const CLI_BINARY_FALLBACK_PACKAGES = {
|
|
5528
|
+
babel: ["babel-cli"],
|
|
5529
|
+
jest: ["jest-cli"]
|
|
5530
|
+
};
|
|
4850
5531
|
const ENV_WRAPPER_BINARY_SET = new Set([
|
|
4851
5532
|
"cross-env",
|
|
4852
5533
|
"dotenv",
|
|
@@ -4878,36 +5559,43 @@ const collectScriptReferencedPackages = (packageJsonPath, declaredNames, binToPa
|
|
|
4878
5559
|
if (!scripts || typeof scripts !== "object") return referenced;
|
|
4879
5560
|
for (const scriptCommand of Object.values(scripts)) {
|
|
4880
5561
|
if (typeof scriptCommand !== "string") continue;
|
|
4881
|
-
const
|
|
4882
|
-
for (const
|
|
4883
|
-
const tokens = segment.trim().split(/\s+/);
|
|
4884
|
-
if (tokens.length === 0) continue;
|
|
4885
|
-
let binaryIndex = 0;
|
|
4886
|
-
const firstToken = tokens[0].replace(/^.*\//, "");
|
|
4887
|
-
if (ENV_WRAPPER_BINARY_SET.has(firstToken)) {
|
|
4888
|
-
const envPackage = binToPackage.get(firstToken);
|
|
4889
|
-
if (envPackage && declaredNames.has(envPackage)) referenced.add(envPackage);
|
|
4890
|
-
binaryIndex = 1;
|
|
4891
|
-
while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
|
|
4892
|
-
if (binaryIndex >= tokens.length) continue;
|
|
4893
|
-
}
|
|
4894
|
-
while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
|
|
4895
|
-
if (binaryIndex >= tokens.length) continue;
|
|
4896
|
-
const binaryToken = tokens[binaryIndex].replace(/^.*\//, "");
|
|
4897
|
-
const effectiveBinary = binaryToken === "npx" || binaryToken === "pnpx" || binaryToken === "bunx" ? tokens[binaryIndex + 1]?.replace(/^.*\//, "") ?? "" : binaryToken;
|
|
4898
|
-
for (const candidateBinary of [binaryToken, effectiveBinary]) {
|
|
4899
|
-
if (!candidateBinary) continue;
|
|
4900
|
-
const mappedPackage = binToPackage.get(candidateBinary);
|
|
4901
|
-
if (mappedPackage && declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
|
|
4902
|
-
if (declaredNames.has(candidateBinary)) referenced.add(candidateBinary);
|
|
4903
|
-
}
|
|
4904
|
-
}
|
|
5562
|
+
const commandReferenced = collectCommandReferencedPackages(scriptCommand, declaredNames, binToPackage);
|
|
5563
|
+
for (const packageName of commandReferenced) referenced.add(packageName);
|
|
4905
5564
|
}
|
|
4906
5565
|
} catch {
|
|
4907
5566
|
return referenced;
|
|
4908
5567
|
}
|
|
4909
5568
|
return referenced;
|
|
4910
5569
|
};
|
|
5570
|
+
const collectCommandReferencedPackages = (command, declaredNames, binToPackage) => {
|
|
5571
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
5572
|
+
const segments = command.split(SHELL_SPLIT_PATTERN);
|
|
5573
|
+
for (const segment of segments) {
|
|
5574
|
+
const tokens = segment.trim().split(/\s+/);
|
|
5575
|
+
if (tokens.length === 0) continue;
|
|
5576
|
+
let binaryIndex = 0;
|
|
5577
|
+
const firstToken = tokens[0].replace(/^.*\//, "");
|
|
5578
|
+
if (ENV_WRAPPER_BINARY_SET.has(firstToken)) {
|
|
5579
|
+
const envPackage = binToPackage.get(firstToken);
|
|
5580
|
+
if (envPackage && declaredNames.has(envPackage)) referenced.add(envPackage);
|
|
5581
|
+
binaryIndex = 1;
|
|
5582
|
+
while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
|
|
5583
|
+
if (binaryIndex >= tokens.length) continue;
|
|
5584
|
+
}
|
|
5585
|
+
while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
|
|
5586
|
+
if (binaryIndex >= tokens.length) continue;
|
|
5587
|
+
const binaryToken = tokens[binaryIndex].replace(/^.*\//, "");
|
|
5588
|
+
const effectiveBinary = binaryToken === "npx" || binaryToken === "pnpx" || binaryToken === "bunx" ? tokens[binaryIndex + 1]?.replace(/^.*\//, "") ?? "" : binaryToken;
|
|
5589
|
+
for (const candidateBinary of [binaryToken, effectiveBinary]) {
|
|
5590
|
+
if (!candidateBinary) continue;
|
|
5591
|
+
const mappedPackage = binToPackage.get(candidateBinary);
|
|
5592
|
+
if (mappedPackage && declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
|
|
5593
|
+
for (const fallbackPackage of CLI_BINARY_FALLBACK_PACKAGES[candidateBinary] ?? []) if (declaredNames.has(fallbackPackage)) referenced.add(fallbackPackage);
|
|
5594
|
+
if (declaredNames.has(candidateBinary)) referenced.add(candidateBinary);
|
|
5595
|
+
}
|
|
5596
|
+
}
|
|
5597
|
+
return referenced;
|
|
5598
|
+
};
|
|
4911
5599
|
const CONFIG_FILE_GLOBS = [
|
|
4912
5600
|
"postcss.config.{js,cjs,mjs,ts}",
|
|
4913
5601
|
".babelrc",
|
|
@@ -5004,6 +5692,39 @@ const collectPackageJsonConfigReferences = (packageJsonPath, declaredNames) => {
|
|
|
5004
5692
|
}
|
|
5005
5693
|
return referenced;
|
|
5006
5694
|
};
|
|
5695
|
+
const collectNxProjectJsonReferences = (rootDir, declaredNames, binToPackage) => {
|
|
5696
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
5697
|
+
const projectJsonPaths = fg.sync(["project.json", "**/project.json"], {
|
|
5698
|
+
cwd: rootDir,
|
|
5699
|
+
absolute: true,
|
|
5700
|
+
onlyFiles: true,
|
|
5701
|
+
ignore: [
|
|
5702
|
+
"**/node_modules/**",
|
|
5703
|
+
"**/dist/**",
|
|
5704
|
+
"**/build/**"
|
|
5705
|
+
],
|
|
5706
|
+
deep: 5
|
|
5707
|
+
});
|
|
5708
|
+
for (const projectJsonPath of projectJsonPaths) try {
|
|
5709
|
+
const content = readFileSync(projectJsonPath, "utf-8");
|
|
5710
|
+
const projectJson = JSON.parse(content);
|
|
5711
|
+
const projectText = JSON.stringify(projectJson);
|
|
5712
|
+
for (const packageName of declaredNames) if (projectText.includes(packageName)) referenced.add(packageName);
|
|
5713
|
+
for (const stringValue of collectStringValues(projectJson)) {
|
|
5714
|
+
const commandReferenced = collectCommandReferencedPackages(stringValue, declaredNames, binToPackage);
|
|
5715
|
+
for (const packageName of commandReferenced) referenced.add(packageName);
|
|
5716
|
+
}
|
|
5717
|
+
} catch {
|
|
5718
|
+
continue;
|
|
5719
|
+
}
|
|
5720
|
+
return referenced;
|
|
5721
|
+
};
|
|
5722
|
+
const collectStringValues = (value) => {
|
|
5723
|
+
if (typeof value === "string") return [value];
|
|
5724
|
+
if (!value || typeof value !== "object") return [];
|
|
5725
|
+
if (Array.isArray(value)) return value.flatMap(collectStringValues);
|
|
5726
|
+
return Object.values(value).flatMap(collectStringValues);
|
|
5727
|
+
};
|
|
5007
5728
|
const TSCONFIG_GLOBS = [
|
|
5008
5729
|
"tsconfig.json",
|
|
5009
5730
|
"tsconfig.*.json",
|
|
@@ -5362,7 +6083,13 @@ const defineConfig = (options) => ({
|
|
|
5362
6083
|
const analyze = async (config) => {
|
|
5363
6084
|
const pipelineStartTime = performance.now();
|
|
5364
6085
|
const workspaceDiscovery = resolveWorkspaces(resolve(config.rootDir));
|
|
5365
|
-
const workspacePackages = workspaceDiscovery.packages;
|
|
6086
|
+
const workspacePackages = [...workspaceDiscovery.packages];
|
|
6087
|
+
const monorepoRoot = findMonorepoRoot(config.rootDir);
|
|
6088
|
+
if (monorepoRoot) {
|
|
6089
|
+
const monorepoWorkspaces = resolveWorkspaces(monorepoRoot);
|
|
6090
|
+
const existingDirectories = new Set(workspacePackages.map((workspacePackage) => workspacePackage.directory));
|
|
6091
|
+
for (const monorepoPackage of monorepoWorkspaces.packages) if (!existingDirectories.has(monorepoPackage.directory)) workspacePackages.push(monorepoPackage);
|
|
6092
|
+
}
|
|
5366
6093
|
const frameworkIgnorePatterns = getFrameworkExclusions(config.rootDir);
|
|
5367
6094
|
const absoluteRoot = resolve(config.rootDir);
|
|
5368
6095
|
const outputDirectoryExclusions = OUTPUT_DIRECTORIES.flatMap((outputDirectory) => {
|
|
@@ -5388,7 +6115,10 @@ const analyze = async (config) => {
|
|
|
5388
6115
|
const moduleResolver = createResolver(config, workspacePackages.map((workspacePackage) => ({
|
|
5389
6116
|
name: workspacePackage.name,
|
|
5390
6117
|
directory: workspacePackage.directory
|
|
5391
|
-
})), {
|
|
6118
|
+
})), {
|
|
6119
|
+
hasReactNative,
|
|
6120
|
+
monorepoRoot
|
|
6121
|
+
});
|
|
5392
6122
|
const graphInputs = [];
|
|
5393
6123
|
for (const file of files) {
|
|
5394
6124
|
const parsedModule = parseSourceFile(file.path);
|