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.cjs
CHANGED
|
@@ -254,7 +254,9 @@ const PLATFORM_SUFFIXES = [
|
|
|
254
254
|
".desktop",
|
|
255
255
|
".windows",
|
|
256
256
|
".macos",
|
|
257
|
-
".any"
|
|
257
|
+
".any",
|
|
258
|
+
".server",
|
|
259
|
+
".client"
|
|
258
260
|
];
|
|
259
261
|
const REACT_NATIVE_PLATFORM_EXTENSIONS = [
|
|
260
262
|
".web.ts",
|
|
@@ -605,6 +607,10 @@ const extractNamedExportDeclaration = (node, sourceText, exports) => {
|
|
|
605
607
|
}
|
|
606
608
|
};
|
|
607
609
|
const extractDefaultExportDeclaration = (node, sourceText, exports) => {
|
|
610
|
+
const defaultExpression = node.declaration;
|
|
611
|
+
let defaultExportLocalName;
|
|
612
|
+
if (defaultExpression?.type === "Identifier" && typeof defaultExpression.name === "string") defaultExportLocalName = defaultExpression.name;
|
|
613
|
+
else if ((defaultExpression?.type === "FunctionDeclaration" || defaultExpression?.type === "ClassDeclaration") && defaultExpression.id?.name) defaultExportLocalName = defaultExpression.id.name;
|
|
608
614
|
exports.push({
|
|
609
615
|
name: "default",
|
|
610
616
|
isDefault: true,
|
|
@@ -615,7 +621,8 @@ const extractDefaultExportDeclaration = (node, sourceText, exports) => {
|
|
|
615
621
|
reExportOriginalName: void 0,
|
|
616
622
|
isNamespaceReExport: false,
|
|
617
623
|
line: getLineFromOffset(sourceText, node.start),
|
|
618
|
-
column: getColumnFromOffset(sourceText, node.start)
|
|
624
|
+
column: getColumnFromOffset(sourceText, node.start),
|
|
625
|
+
defaultExportLocalName
|
|
619
626
|
});
|
|
620
627
|
};
|
|
621
628
|
const extractExportAllDeclaration = (node, sourceText, exports) => {
|
|
@@ -1096,6 +1103,12 @@ const collectWorkspacePatterns = (rootDir) => {
|
|
|
1096
1103
|
const packageLines = extractPnpmWorkspacePackages((0, node_fs.readFileSync)(pnpmWorkspacePath, "utf-8"));
|
|
1097
1104
|
patterns.push(...packageLines);
|
|
1098
1105
|
} catch {}
|
|
1106
|
+
const lernaJsonPath = (0, node_path.join)(rootDir, "lerna.json");
|
|
1107
|
+
if ((0, node_fs.existsSync)(lernaJsonPath)) try {
|
|
1108
|
+
const content = (0, node_fs.readFileSync)(lernaJsonPath, "utf-8");
|
|
1109
|
+
const lernaJson = JSON.parse(content);
|
|
1110
|
+
if (Array.isArray(lernaJson.packages)) patterns.push(...lernaJson.packages.filter((pattern) => typeof pattern === "string" && !pattern.startsWith("!")));
|
|
1111
|
+
} catch {}
|
|
1099
1112
|
return patterns;
|
|
1100
1113
|
};
|
|
1101
1114
|
const extractPnpmWorkspacePackages = (yamlContent) => {
|
|
@@ -1657,6 +1670,54 @@ const resolveSourcePath = (distPath, directory) => {
|
|
|
1657
1670
|
}
|
|
1658
1671
|
};
|
|
1659
1672
|
|
|
1673
|
+
//#endregion
|
|
1674
|
+
//#region src/utils/find-monorepo-root.ts
|
|
1675
|
+
const MONOREPO_ROOT_MARKERS = [
|
|
1676
|
+
"pnpm-workspace.yaml",
|
|
1677
|
+
"pnpm-workspace.yml",
|
|
1678
|
+
"lerna.json",
|
|
1679
|
+
"nx.json",
|
|
1680
|
+
"turbo.json",
|
|
1681
|
+
"rush.json"
|
|
1682
|
+
];
|
|
1683
|
+
const LOCKFILE_MARKERS = [
|
|
1684
|
+
"pnpm-lock.yaml",
|
|
1685
|
+
"yarn.lock",
|
|
1686
|
+
"package-lock.json",
|
|
1687
|
+
"bun.lockb",
|
|
1688
|
+
"bun.lock"
|
|
1689
|
+
];
|
|
1690
|
+
const MAX_MONOREPO_WALK_DEPTH = 5;
|
|
1691
|
+
const findMonorepoRoot = (rootDir) => {
|
|
1692
|
+
let currentDirectory = (0, node_path.resolve)(rootDir);
|
|
1693
|
+
let walkedDepth = 0;
|
|
1694
|
+
while (walkedDepth < MAX_MONOREPO_WALK_DEPTH) {
|
|
1695
|
+
const parentDirectory = (0, node_path.dirname)(currentDirectory);
|
|
1696
|
+
if (parentDirectory === currentDirectory) break;
|
|
1697
|
+
currentDirectory = parentDirectory;
|
|
1698
|
+
walkedDepth++;
|
|
1699
|
+
if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, ".git"))) {
|
|
1700
|
+
for (const marker of MONOREPO_ROOT_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, marker))) return currentDirectory;
|
|
1701
|
+
const packageJsonPath = (0, node_path.join)(currentDirectory, "package.json");
|
|
1702
|
+
if ((0, node_fs.existsSync)(packageJsonPath)) try {
|
|
1703
|
+
const content = (0, node_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
1704
|
+
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
1705
|
+
} catch {}
|
|
1706
|
+
for (const lockfile of LOCKFILE_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, lockfile))) return currentDirectory;
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
for (const marker of MONOREPO_ROOT_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, marker))) return currentDirectory;
|
|
1710
|
+
const packageJsonPath = (0, node_path.join)(currentDirectory, "package.json");
|
|
1711
|
+
if ((0, node_fs.existsSync)(packageJsonPath)) try {
|
|
1712
|
+
const content = (0, node_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
1713
|
+
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
1714
|
+
} catch {
|
|
1715
|
+
continue;
|
|
1716
|
+
}
|
|
1717
|
+
for (const lockfile of LOCKFILE_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, lockfile))) return currentDirectory;
|
|
1718
|
+
}
|
|
1719
|
+
};
|
|
1720
|
+
|
|
1660
1721
|
//#endregion
|
|
1661
1722
|
//#region src/collect/entries.ts
|
|
1662
1723
|
const collectSourceFiles = async (config) => {
|
|
@@ -1762,6 +1823,14 @@ const resolveEntries = async (config) => {
|
|
|
1762
1823
|
for (const entryPath of allDiscoveredEntries) if (entryPath.endsWith(".html") && (0, node_fs.existsSync)(entryPath)) htmlScriptEntries.push(...extractScriptTagsFromHtmlFile(entryPath));
|
|
1763
1824
|
const angularEntries = extractAngularEntryPoints(absoluteRoot);
|
|
1764
1825
|
for (const workspacePackage of entryEligiblePackages) angularEntries.push(...extractAngularEntryPoints(workspacePackage.directory));
|
|
1826
|
+
const browserExtensionEntries = extractBrowserExtensionEntries(absoluteRoot);
|
|
1827
|
+
for (const workspacePackage of entryEligiblePackages) browserExtensionEntries.push(...extractBrowserExtensionEntries(workspacePackage.directory));
|
|
1828
|
+
const webWorkerEntries = extractWebWorkerEntries(absoluteRoot);
|
|
1829
|
+
for (const workspacePackage of entryEligiblePackages) webWorkerEntries.push(...extractWebWorkerEntries(workspacePackage.directory));
|
|
1830
|
+
const tsConfigIncludeEntries = extractTsConfigIncludeFilesEntries(absoluteRoot);
|
|
1831
|
+
for (const workspacePackage of entryEligiblePackages) tsConfigIncludeEntries.push(...extractTsConfigIncludeFilesEntries(workspacePackage.directory));
|
|
1832
|
+
const wranglerEntries = extractWranglerEntries(absoluteRoot);
|
|
1833
|
+
for (const workspacePackage of entryEligiblePackages) wranglerEntries.push(...extractWranglerEntries(workspacePackage.directory));
|
|
1765
1834
|
const testSetupEntries = extractTestSetupFiles(absoluteRoot);
|
|
1766
1835
|
for (const workspacePackage of entryEligiblePackages) testSetupEntries.push(...extractTestSetupFiles(workspacePackage.directory));
|
|
1767
1836
|
const pluginFileEntries = extractNextConfigPluginFiles(absoluteRoot);
|
|
@@ -1783,6 +1852,10 @@ const resolveEntries = async (config) => {
|
|
|
1783
1852
|
...bundlerConfigEntries,
|
|
1784
1853
|
...htmlScriptEntries,
|
|
1785
1854
|
...angularEntries,
|
|
1855
|
+
...browserExtensionEntries,
|
|
1856
|
+
...webWorkerEntries,
|
|
1857
|
+
...tsConfigIncludeEntries,
|
|
1858
|
+
...wranglerEntries,
|
|
1786
1859
|
...pluginFileEntries,
|
|
1787
1860
|
...toolingDiscovery.entryFiles,
|
|
1788
1861
|
...ciEntries
|
|
@@ -2426,6 +2499,231 @@ const extractScriptTagsFromHtmlFile = (htmlFilePath) => {
|
|
|
2426
2499
|
} catch {}
|
|
2427
2500
|
return entries;
|
|
2428
2501
|
};
|
|
2502
|
+
const TSCONFIG_FILENAME_GLOBS = ["tsconfig.json", "tsconfig.*.json"];
|
|
2503
|
+
const stripJsoncCommentsLocal = (sourceText) => {
|
|
2504
|
+
let result = "";
|
|
2505
|
+
let insideString = false;
|
|
2506
|
+
let index = 0;
|
|
2507
|
+
while (index < sourceText.length) {
|
|
2508
|
+
const ch = sourceText[index];
|
|
2509
|
+
if (insideString) {
|
|
2510
|
+
if (ch === "\\" && index + 1 < sourceText.length) {
|
|
2511
|
+
result += sourceText[index] + sourceText[index + 1];
|
|
2512
|
+
index += 2;
|
|
2513
|
+
continue;
|
|
2514
|
+
}
|
|
2515
|
+
if (ch === "\"") insideString = false;
|
|
2516
|
+
result += ch;
|
|
2517
|
+
index++;
|
|
2518
|
+
continue;
|
|
2519
|
+
}
|
|
2520
|
+
if (ch === "\"") {
|
|
2521
|
+
insideString = true;
|
|
2522
|
+
result += ch;
|
|
2523
|
+
index++;
|
|
2524
|
+
continue;
|
|
2525
|
+
}
|
|
2526
|
+
if (ch === "/" && index + 1 < sourceText.length) {
|
|
2527
|
+
if (sourceText[index + 1] === "/") {
|
|
2528
|
+
while (index < sourceText.length && sourceText[index] !== "\n") index++;
|
|
2529
|
+
continue;
|
|
2530
|
+
}
|
|
2531
|
+
if (sourceText[index + 1] === "*") {
|
|
2532
|
+
index += 2;
|
|
2533
|
+
while (index + 1 < sourceText.length && !(sourceText[index] === "*" && sourceText[index + 1] === "/")) index++;
|
|
2534
|
+
index += 2;
|
|
2535
|
+
continue;
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
result += ch;
|
|
2539
|
+
index++;
|
|
2540
|
+
}
|
|
2541
|
+
return result.replace(/,(\s*[}\]])/g, "$1");
|
|
2542
|
+
};
|
|
2543
|
+
const extractTsConfigIncludeFilesEntries = (directory) => {
|
|
2544
|
+
const entries = [];
|
|
2545
|
+
const tsconfigPaths = fast_glob.default.sync(TSCONFIG_FILENAME_GLOBS, {
|
|
2546
|
+
cwd: directory,
|
|
2547
|
+
absolute: true,
|
|
2548
|
+
onlyFiles: true,
|
|
2549
|
+
ignore: [
|
|
2550
|
+
"**/node_modules/**",
|
|
2551
|
+
"**/dist/**",
|
|
2552
|
+
"**/build/**"
|
|
2553
|
+
],
|
|
2554
|
+
deep: 1
|
|
2555
|
+
});
|
|
2556
|
+
for (const tsconfigPath of tsconfigPaths) try {
|
|
2557
|
+
const cleaned = stripJsoncCommentsLocal((0, node_fs.readFileSync)(tsconfigPath, "utf-8"));
|
|
2558
|
+
const tsconfigJson = JSON.parse(cleaned);
|
|
2559
|
+
const tsconfigDir = (0, node_path.dirname)(tsconfigPath);
|
|
2560
|
+
const collectPaths = (rawList) => {
|
|
2561
|
+
if (!Array.isArray(rawList)) return;
|
|
2562
|
+
for (const item of rawList) {
|
|
2563
|
+
if (typeof item !== "string") continue;
|
|
2564
|
+
if (item.includes("*") || item.includes("?")) continue;
|
|
2565
|
+
const candidatePath = (0, node_path.resolve)(tsconfigDir, item);
|
|
2566
|
+
if ((0, node_fs.existsSync)(candidatePath)) entries.push(candidatePath);
|
|
2567
|
+
}
|
|
2568
|
+
};
|
|
2569
|
+
collectPaths(tsconfigJson.include);
|
|
2570
|
+
collectPaths(tsconfigJson.files);
|
|
2571
|
+
} catch {}
|
|
2572
|
+
return entries;
|
|
2573
|
+
};
|
|
2574
|
+
const WRANGLER_TOML_MAIN_PATTERN = /^\s*main\s*=\s*['"]([^'"\n]+)['"]/m;
|
|
2575
|
+
const WRANGLER_JSON_MAIN_PATTERN = /"main"\s*:\s*"([^"]+)"/;
|
|
2576
|
+
const WRANGLER_SERVICE_BINDINGS_PATTERN = /entry_point\s*=\s*['"]([^'"\n]+)['"]/g;
|
|
2577
|
+
const extractWranglerEntries = (directory) => {
|
|
2578
|
+
const entries = [];
|
|
2579
|
+
const wranglerPaths = fast_glob.default.sync([
|
|
2580
|
+
"wrangler.toml",
|
|
2581
|
+
"wrangler.json",
|
|
2582
|
+
"wrangler.jsonc"
|
|
2583
|
+
], {
|
|
2584
|
+
cwd: directory,
|
|
2585
|
+
absolute: true,
|
|
2586
|
+
onlyFiles: true,
|
|
2587
|
+
ignore: ["**/node_modules/**"],
|
|
2588
|
+
deep: 1
|
|
2589
|
+
});
|
|
2590
|
+
for (const wranglerPath of wranglerPaths) try {
|
|
2591
|
+
const content = (0, node_fs.readFileSync)(wranglerPath, "utf-8");
|
|
2592
|
+
const wranglerDir = (0, node_path.dirname)(wranglerPath);
|
|
2593
|
+
const mainMatch = wranglerPath.endsWith(".toml") ? content.match(WRANGLER_TOML_MAIN_PATTERN) : content.match(WRANGLER_JSON_MAIN_PATTERN);
|
|
2594
|
+
if (mainMatch?.[1]) {
|
|
2595
|
+
const candidatePath = (0, node_path.resolve)(wranglerDir, mainMatch[1]);
|
|
2596
|
+
if ((0, node_fs.existsSync)(candidatePath)) entries.push(candidatePath);
|
|
2597
|
+
else {
|
|
2598
|
+
const sourceCandidate = resolveSourcePath(candidatePath, wranglerDir);
|
|
2599
|
+
if (sourceCandidate) entries.push(sourceCandidate);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
let entryPointMatch;
|
|
2603
|
+
WRANGLER_SERVICE_BINDINGS_PATTERN.lastIndex = 0;
|
|
2604
|
+
while ((entryPointMatch = WRANGLER_SERVICE_BINDINGS_PATTERN.exec(content)) !== null) {
|
|
2605
|
+
const candidatePath = (0, node_path.resolve)(wranglerDir, entryPointMatch[1]);
|
|
2606
|
+
if ((0, node_fs.existsSync)(candidatePath)) entries.push(candidatePath);
|
|
2607
|
+
}
|
|
2608
|
+
} catch {}
|
|
2609
|
+
return entries;
|
|
2610
|
+
};
|
|
2611
|
+
const WORKER_FILE_GLOBS = [
|
|
2612
|
+
"**/*.worker.{ts,tsx,js,jsx,mts,mjs,cts,cjs}",
|
|
2613
|
+
"**/*.sw.{ts,tsx,js,jsx,mts,mjs,cts,cjs}",
|
|
2614
|
+
"**/sw.{ts,tsx,js,jsx,mts,mjs,cts,cjs}",
|
|
2615
|
+
"**/service-worker.{ts,tsx,js,jsx,mts,mjs,cts,cjs}"
|
|
2616
|
+
];
|
|
2617
|
+
const extractWebWorkerEntries = (directory) => {
|
|
2618
|
+
return fast_glob.default.sync(WORKER_FILE_GLOBS, {
|
|
2619
|
+
cwd: directory,
|
|
2620
|
+
absolute: true,
|
|
2621
|
+
onlyFiles: true,
|
|
2622
|
+
ignore: [
|
|
2623
|
+
"**/node_modules/**",
|
|
2624
|
+
"**/dist/**",
|
|
2625
|
+
"**/build/**",
|
|
2626
|
+
"**/.next/**",
|
|
2627
|
+
"**/out/**"
|
|
2628
|
+
],
|
|
2629
|
+
deep: 8
|
|
2630
|
+
});
|
|
2631
|
+
};
|
|
2632
|
+
const collectBrowserExtensionManifestPaths = (manifest) => {
|
|
2633
|
+
const candidatePaths = [];
|
|
2634
|
+
if (typeof manifest !== "object" || manifest === null) return candidatePaths;
|
|
2635
|
+
const manifestRecord = manifest;
|
|
2636
|
+
const background = manifestRecord.background;
|
|
2637
|
+
if (typeof background === "object" && background !== null) {
|
|
2638
|
+
const backgroundRecord = background;
|
|
2639
|
+
if (typeof backgroundRecord.service_worker === "string") candidatePaths.push(backgroundRecord.service_worker);
|
|
2640
|
+
if (typeof backgroundRecord.page === "string") candidatePaths.push(backgroundRecord.page);
|
|
2641
|
+
if (typeof backgroundRecord.scripts === "string") candidatePaths.push(backgroundRecord.scripts);
|
|
2642
|
+
if (Array.isArray(backgroundRecord.scripts)) {
|
|
2643
|
+
for (const scriptPath of backgroundRecord.scripts) if (typeof scriptPath === "string") candidatePaths.push(scriptPath);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
const contentScripts = manifestRecord.content_scripts;
|
|
2647
|
+
if (Array.isArray(contentScripts)) for (const contentScript of contentScripts) {
|
|
2648
|
+
if (typeof contentScript !== "object" || contentScript === null) continue;
|
|
2649
|
+
const contentScriptRecord = contentScript;
|
|
2650
|
+
if (Array.isArray(contentScriptRecord.js)) {
|
|
2651
|
+
for (const scriptPath of contentScriptRecord.js) if (typeof scriptPath === "string") candidatePaths.push(scriptPath);
|
|
2652
|
+
}
|
|
2653
|
+
if (Array.isArray(contentScriptRecord.css)) {
|
|
2654
|
+
for (const stylePath of contentScriptRecord.css) if (typeof stylePath === "string") candidatePaths.push(stylePath);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
const action = manifestRecord.action ?? manifestRecord.browser_action ?? manifestRecord.page_action;
|
|
2658
|
+
if (typeof action === "object" && action !== null) {
|
|
2659
|
+
const actionRecord = action;
|
|
2660
|
+
if (typeof actionRecord.default_popup === "string") candidatePaths.push(actionRecord.default_popup);
|
|
2661
|
+
}
|
|
2662
|
+
if (typeof manifestRecord.devtools_page === "string") candidatePaths.push(manifestRecord.devtools_page);
|
|
2663
|
+
if (typeof manifestRecord.options_page === "string") candidatePaths.push(manifestRecord.options_page);
|
|
2664
|
+
if (typeof manifestRecord.options_ui === "object" && manifestRecord.options_ui !== null) {
|
|
2665
|
+
const optionsRecord = manifestRecord.options_ui;
|
|
2666
|
+
if (typeof optionsRecord.page === "string") candidatePaths.push(optionsRecord.page);
|
|
2667
|
+
}
|
|
2668
|
+
if (typeof manifestRecord.sandbox === "object" && manifestRecord.sandbox !== null) {
|
|
2669
|
+
const sandboxRecord = manifestRecord.sandbox;
|
|
2670
|
+
if (Array.isArray(sandboxRecord.pages)) {
|
|
2671
|
+
for (const pagePath of sandboxRecord.pages) if (typeof pagePath === "string") candidatePaths.push(pagePath);
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
return candidatePaths;
|
|
2675
|
+
};
|
|
2676
|
+
const isLikelyBrowserExtensionManifest = (manifest) => {
|
|
2677
|
+
if (typeof manifest !== "object" || manifest === null) return false;
|
|
2678
|
+
return typeof manifest.manifest_version === "number";
|
|
2679
|
+
};
|
|
2680
|
+
const extractBrowserExtensionEntries = (directory) => {
|
|
2681
|
+
const entries = [];
|
|
2682
|
+
const manifestPaths = fast_glob.default.sync([
|
|
2683
|
+
"manifest.json",
|
|
2684
|
+
"manifest.*.json",
|
|
2685
|
+
"src/manifest.json",
|
|
2686
|
+
"src/manifest.*.json",
|
|
2687
|
+
"public/manifest.json",
|
|
2688
|
+
"public/manifest.*.json",
|
|
2689
|
+
"static/manifest.json"
|
|
2690
|
+
], {
|
|
2691
|
+
cwd: directory,
|
|
2692
|
+
absolute: true,
|
|
2693
|
+
onlyFiles: true,
|
|
2694
|
+
ignore: [
|
|
2695
|
+
"**/node_modules/**",
|
|
2696
|
+
"**/dist/**",
|
|
2697
|
+
"**/build/**"
|
|
2698
|
+
],
|
|
2699
|
+
deep: 3
|
|
2700
|
+
});
|
|
2701
|
+
for (const manifestPath of manifestPaths) try {
|
|
2702
|
+
const content = (0, node_fs.readFileSync)(manifestPath, "utf-8");
|
|
2703
|
+
const manifest = JSON.parse(content);
|
|
2704
|
+
if (!isLikelyBrowserExtensionManifest(manifest)) continue;
|
|
2705
|
+
const manifestDir = (0, node_path.dirname)(manifestPath);
|
|
2706
|
+
const candidatePaths = collectBrowserExtensionManifestPaths(manifest);
|
|
2707
|
+
const resolutionRoots = [
|
|
2708
|
+
manifestDir,
|
|
2709
|
+
(0, node_path.resolve)(manifestDir, ".."),
|
|
2710
|
+
directory
|
|
2711
|
+
];
|
|
2712
|
+
for (const candidatePath of candidatePaths) for (const resolutionRoot of resolutionRoots) {
|
|
2713
|
+
const candidateAbsolutePath = (0, node_path.resolve)(resolutionRoot, candidatePath);
|
|
2714
|
+
if ((0, node_fs.existsSync)(candidateAbsolutePath)) {
|
|
2715
|
+
entries.push(candidateAbsolutePath);
|
|
2716
|
+
break;
|
|
2717
|
+
}
|
|
2718
|
+
const sourceFile = resolveSourcePath(candidateAbsolutePath, resolutionRoot);
|
|
2719
|
+
if (sourceFile) {
|
|
2720
|
+
entries.push(sourceFile);
|
|
2721
|
+
break;
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
} catch {}
|
|
2725
|
+
return entries;
|
|
2726
|
+
};
|
|
2429
2727
|
const ANGULAR_ENTRY_KEYS = [
|
|
2430
2728
|
"main",
|
|
2431
2729
|
"polyfills",
|
|
@@ -3156,8 +3454,14 @@ const FRAMEWORK_PATTERNS = [
|
|
|
3156
3454
|
alwaysUsed: ["tsr.config.json", "app.config.{ts,js}"]
|
|
3157
3455
|
},
|
|
3158
3456
|
{
|
|
3159
|
-
enablers: [
|
|
3160
|
-
|
|
3457
|
+
enablers: [
|
|
3458
|
+
"vite",
|
|
3459
|
+
"rolldown-vite",
|
|
3460
|
+
"vite-plus",
|
|
3461
|
+
"@voidzero-dev/vite-plus-core",
|
|
3462
|
+
"@voidzero-dev/vite-plus-test"
|
|
3463
|
+
],
|
|
3464
|
+
enablerPrefixes: ["@vitejs/", "@voidzero-dev/vite-plus"],
|
|
3161
3465
|
entryPatterns: [
|
|
3162
3466
|
"src/main.{ts,tsx,js,jsx}",
|
|
3163
3467
|
"src/index.{ts,tsx,js,jsx}",
|
|
@@ -3445,10 +3749,25 @@ const detectBunTestRunner = (directory) => {
|
|
|
3445
3749
|
return false;
|
|
3446
3750
|
}
|
|
3447
3751
|
};
|
|
3752
|
+
const readPackageJsonDependencies = (packageJsonPath) => {
|
|
3753
|
+
try {
|
|
3754
|
+
const content = (0, node_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
3755
|
+
const packageJson = JSON.parse(content);
|
|
3756
|
+
return {
|
|
3757
|
+
...packageJson.dependencies,
|
|
3758
|
+
...packageJson.devDependencies,
|
|
3759
|
+
...packageJson.optionalDependencies
|
|
3760
|
+
};
|
|
3761
|
+
} catch {
|
|
3762
|
+
return {};
|
|
3763
|
+
}
|
|
3764
|
+
};
|
|
3448
3765
|
const discoverTestRunnerEntryPoints = (rootDir, workspacePackages) => {
|
|
3449
3766
|
const allEntries = [];
|
|
3450
3767
|
const allAlwaysUsed = [];
|
|
3451
3768
|
const directoriesToCheck = [rootDir, ...workspacePackages.map((workspacePackage) => workspacePackage.directory)];
|
|
3769
|
+
const monorepoRoot = findMonorepoRoot(rootDir);
|
|
3770
|
+
const monorepoRootDeps = monorepoRoot && monorepoRoot !== rootDir ? readPackageJsonDependencies((0, node_path.join)(monorepoRoot, "package.json")) : {};
|
|
3452
3771
|
for (const directory of directoriesToCheck) {
|
|
3453
3772
|
const packageJsonPath = (0, node_path.join)(directory, "package.json");
|
|
3454
3773
|
if (!(0, node_fs.existsSync)(packageJsonPath)) continue;
|
|
@@ -3473,16 +3792,25 @@ const discoverTestRunnerEntryPoints = (rootDir, workspacePackages) => {
|
|
|
3473
3792
|
})) return true;
|
|
3474
3793
|
return runner.configFileActivators.some((configFile) => (0, node_fs.existsSync)((0, node_path.join)(checkDirectory, configFile)));
|
|
3475
3794
|
};
|
|
3476
|
-
for (const runner of TEST_FRAMEWORK_PATTERNS)
|
|
3477
|
-
const
|
|
3478
|
-
const
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3795
|
+
for (const runner of TEST_FRAMEWORK_PATTERNS) {
|
|
3796
|
+
const enabledLocally = isRunnerEnabled(runner, allDependencies, directory);
|
|
3797
|
+
const enabledViaMonorepo = !enabledLocally && monorepoRoot && (isRunnerEnabled(runner, monorepoRootDeps, monorepoRoot) || runner.configFileActivators.some((configFile) => (0, node_fs.existsSync)((0, node_path.join)(monorepoRoot, configFile))));
|
|
3798
|
+
if (enabledLocally || enabledViaMonorepo) {
|
|
3799
|
+
const isVitestRunner = runner.enablers.includes("vitest");
|
|
3800
|
+
const isJestRunner = runner.enablers.includes("jest");
|
|
3801
|
+
let customPatterns = [];
|
|
3802
|
+
if (isVitestRunner) {
|
|
3803
|
+
customPatterns = extractVitestIncludePatterns(directory);
|
|
3804
|
+
if (customPatterns.length === 0 && monorepoRoot) customPatterns = extractVitestIncludePatterns(monorepoRoot);
|
|
3805
|
+
} else if (isJestRunner) {
|
|
3806
|
+
customPatterns = extractJestTestMatchPatterns(directory);
|
|
3807
|
+
if (customPatterns.length === 0 && monorepoRoot) customPatterns = extractJestTestMatchPatterns(monorepoRoot);
|
|
3808
|
+
}
|
|
3809
|
+
if (customPatterns.length > 0) activatedPatterns.push(...customPatterns);
|
|
3810
|
+
else activatedPatterns.push(...runner.entryPatterns);
|
|
3811
|
+
activatedFixturePatterns.push(...runner.fixturePatterns);
|
|
3812
|
+
activatedAlwaysUsed.push(...runner.alwaysUsed);
|
|
3813
|
+
}
|
|
3486
3814
|
}
|
|
3487
3815
|
if (activatedPatterns.length === 0 && directory !== rootDir) {
|
|
3488
3816
|
const rootPackageJsonPath = (0, node_path.join)(rootDir, "package.json");
|
|
@@ -3547,6 +3875,45 @@ const isToolingPluginEnabled = (plugin, dependencies) => {
|
|
|
3547
3875
|
}
|
|
3548
3876
|
return false;
|
|
3549
3877
|
};
|
|
3878
|
+
const FRAMEWORK_SCRIPT_BINARIES = {
|
|
3879
|
+
next: ["next"],
|
|
3880
|
+
nuxt: ["nuxt"],
|
|
3881
|
+
astro: ["astro"],
|
|
3882
|
+
gatsby: ["gatsby"],
|
|
3883
|
+
remix: ["remix"],
|
|
3884
|
+
"@sveltejs/kit": ["svelte-kit", "vite-svelte-kit"],
|
|
3885
|
+
"@docusaurus/core": ["docusaurus"],
|
|
3886
|
+
"@angular/core": ["ng"],
|
|
3887
|
+
"@nestjs/core": ["nest"],
|
|
3888
|
+
storybook: [
|
|
3889
|
+
"storybook",
|
|
3890
|
+
"start-storybook",
|
|
3891
|
+
"build-storybook"
|
|
3892
|
+
]
|
|
3893
|
+
};
|
|
3894
|
+
const detectFrameworkFromScripts = (scripts) => {
|
|
3895
|
+
const enabledEnablers = /* @__PURE__ */ new Set();
|
|
3896
|
+
if (!scripts || typeof scripts !== "object") return enabledEnablers;
|
|
3897
|
+
for (const scriptValue of Object.values(scripts)) {
|
|
3898
|
+
if (typeof scriptValue !== "string") continue;
|
|
3899
|
+
const tokenized = scriptValue.split(/[\s|&;]+/);
|
|
3900
|
+
for (const token of tokenized) {
|
|
3901
|
+
const cleaned = token.replace(/^.*\//, "");
|
|
3902
|
+
for (const [enabler, binaries] of Object.entries(FRAMEWORK_SCRIPT_BINARIES)) if (binaries.includes(cleaned)) enabledEnablers.add(enabler);
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
return enabledEnablers;
|
|
3906
|
+
};
|
|
3907
|
+
const readPackageScripts = (directory) => {
|
|
3908
|
+
const packageJsonPath = (0, node_path.join)(directory, "package.json");
|
|
3909
|
+
if (!(0, node_fs.existsSync)(packageJsonPath)) return void 0;
|
|
3910
|
+
try {
|
|
3911
|
+
const content = (0, node_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
3912
|
+
return JSON.parse(content).scripts;
|
|
3913
|
+
} catch {
|
|
3914
|
+
return;
|
|
3915
|
+
}
|
|
3916
|
+
};
|
|
3550
3917
|
const discoverToolingEntryPoints = (rootDir, workspacePackages) => {
|
|
3551
3918
|
const allEntries = [];
|
|
3552
3919
|
const allAlwaysUsed = [];
|
|
@@ -3562,6 +3929,8 @@ const discoverToolingEntryPoints = (rootDir, workspacePackages) => {
|
|
|
3562
3929
|
...rootPackageJson.optionalDependencies
|
|
3563
3930
|
};
|
|
3564
3931
|
} catch {}
|
|
3932
|
+
const monorepoRoot = findMonorepoRoot(rootDir);
|
|
3933
|
+
const monorepoRootDeps = monorepoRoot && monorepoRoot !== rootDir ? readPackageJsonDependencies((0, node_path.join)(monorepoRoot, "package.json")) : {};
|
|
3565
3934
|
for (const directory of directoriesToCheck) {
|
|
3566
3935
|
const packageJsonPath = (0, node_path.join)(directory, "package.json");
|
|
3567
3936
|
if (!(0, node_fs.existsSync)(packageJsonPath)) continue;
|
|
@@ -3577,7 +3946,10 @@ const discoverToolingEntryPoints = (rootDir, workspacePackages) => {
|
|
|
3577
3946
|
} catch {
|
|
3578
3947
|
continue;
|
|
3579
3948
|
}
|
|
3580
|
-
const
|
|
3949
|
+
const scriptDetectedEnablers = detectFrameworkFromScripts(readPackageScripts(directory));
|
|
3950
|
+
const mergedDependencies = { ...workspaceDependencies };
|
|
3951
|
+
if (directory === rootDir) Object.assign(mergedDependencies, rootDependencies);
|
|
3952
|
+
else for (const enabler of scriptDetectedEnablers) if (enabler in monorepoRootDeps || enabler in rootDependencies) mergedDependencies[enabler] = "*";
|
|
3581
3953
|
const activatedPatterns = [];
|
|
3582
3954
|
const activatedAlwaysUsed = [];
|
|
3583
3955
|
for (const plugin of FRAMEWORK_PATTERNS) if (isToolingPluginEnabled(plugin, mergedDependencies)) {
|
|
@@ -3715,16 +4087,28 @@ const COMMON_RESOLVER_OPTIONS = {
|
|
|
3715
4087
|
".cjs": [".cts", ".cjs"]
|
|
3716
4088
|
}
|
|
3717
4089
|
};
|
|
4090
|
+
const WEBPACK_CONFIG_GLOBS = [
|
|
4091
|
+
"webpack.config.{js,ts,mjs,cjs}",
|
|
4092
|
+
"**/webpack*.config.{js,ts,mjs,cjs}",
|
|
4093
|
+
"**/webpack.config*.{js,ts,mjs,cjs}",
|
|
4094
|
+
"**/webpack*.config*.babel.{js,ts}"
|
|
4095
|
+
];
|
|
4096
|
+
const WEBPACK_ALIAS_BLOCK_PATTERN = /alias\s*:\s*\{([\s\S]*?)\}/g;
|
|
4097
|
+
const WEBPACK_ALIAS_ENTRY_PATTERN = /["']?([@\w$./-]+)["']?\s*:\s*(?:path\.(?:resolve|join)\(\s*__dirname\s*,\s*((?:["'][^"']+["']\s*,?\s*)+)\)|["']([^"']+)["'])/g;
|
|
4098
|
+
const WEBPACK_MODULES_BLOCK_PATTERN = /modules\s*:\s*\[([\s\S]*?)\]/g;
|
|
4099
|
+
const WEBPACK_PATH_CALL_PATTERN = /path\.(?:resolve|join)\(\s*__dirname\s*,\s*((?:["'][^"']+["']\s*,?\s*)+)\)/g;
|
|
4100
|
+
const WEBPACK_STRING_LITERAL_PATTERN = /["']([^"']+)["']/g;
|
|
3718
4101
|
const TSCONFIG_FILENAMES = [
|
|
3719
4102
|
"tsconfig.json",
|
|
3720
4103
|
"tsconfig.web.json",
|
|
3721
4104
|
"tsconfig.app.json",
|
|
3722
|
-
"tsconfig.base.json"
|
|
4105
|
+
"tsconfig.base.json",
|
|
4106
|
+
"jsconfig.json"
|
|
3723
4107
|
];
|
|
3724
|
-
const findNearestTsconfig = (fromDir, rootDir) => {
|
|
4108
|
+
const findNearestTsconfig = (fromDir, rootDir, monorepoRootDir) => {
|
|
3725
4109
|
let currentDirectory = fromDir;
|
|
3726
|
-
const
|
|
3727
|
-
while (currentDirectory.length >=
|
|
4110
|
+
const stopAt = monorepoRootDir ? (0, node_path.resolve)(monorepoRootDir) : (0, node_path.resolve)(rootDir);
|
|
4111
|
+
while (currentDirectory.length >= stopAt.length) {
|
|
3728
4112
|
for (const tsconfigFilename of TSCONFIG_FILENAMES) {
|
|
3729
4113
|
const tsconfigCandidate = (0, node_path.join)(currentDirectory, tsconfigFilename);
|
|
3730
4114
|
if (cachedExistsSync(tsconfigCandidate)) return tsconfigCandidate;
|
|
@@ -3763,6 +4147,108 @@ const resolveScssPartial = (specifier, fromDirectory) => {
|
|
|
3763
4147
|
candidates.push((0, node_path.join)(basePath, `_index.sass`));
|
|
3764
4148
|
for (const candidate of candidates) if (cachedExistsSync(candidate)) return candidate;
|
|
3765
4149
|
};
|
|
4150
|
+
const isInsideDirectory = (filePath, directory) => {
|
|
4151
|
+
const relativePath = (0, node_path.relative)(directory, filePath);
|
|
4152
|
+
return relativePath === "" || !relativePath.startsWith("..") && !(0, node_path.isAbsolute)(relativePath);
|
|
4153
|
+
};
|
|
4154
|
+
const extractQuotedSegments = (value) => {
|
|
4155
|
+
const segments = [];
|
|
4156
|
+
let segmentMatch;
|
|
4157
|
+
WEBPACK_STRING_LITERAL_PATTERN.lastIndex = 0;
|
|
4158
|
+
while ((segmentMatch = WEBPACK_STRING_LITERAL_PATTERN.exec(value)) !== null) segments.push(segmentMatch[1]);
|
|
4159
|
+
return segments;
|
|
4160
|
+
};
|
|
4161
|
+
const resolveWebpackPathValue = (value, configDirectory) => {
|
|
4162
|
+
if ((0, node_path.isAbsolute)(value)) return value;
|
|
4163
|
+
return (0, node_path.resolve)(configDirectory, value);
|
|
4164
|
+
};
|
|
4165
|
+
const findWebpackConfigScope = (configPath, rootDir) => {
|
|
4166
|
+
let currentDirectory = (0, node_path.dirname)(configPath);
|
|
4167
|
+
const absoluteRoot = (0, node_path.resolve)(rootDir);
|
|
4168
|
+
while (currentDirectory.length >= absoluteRoot.length) {
|
|
4169
|
+
if (cachedExistsSync((0, node_path.join)(currentDirectory, "package.json"))) return currentDirectory;
|
|
4170
|
+
const parentDirectory = (0, node_path.dirname)(currentDirectory);
|
|
4171
|
+
if (parentDirectory === currentDirectory) break;
|
|
4172
|
+
currentDirectory = parentDirectory;
|
|
4173
|
+
}
|
|
4174
|
+
return absoluteRoot;
|
|
4175
|
+
};
|
|
4176
|
+
const extractWebpackAliases = (content, configDirectory) => {
|
|
4177
|
+
const aliases = [];
|
|
4178
|
+
let aliasBlockMatch;
|
|
4179
|
+
WEBPACK_ALIAS_BLOCK_PATTERN.lastIndex = 0;
|
|
4180
|
+
while ((aliasBlockMatch = WEBPACK_ALIAS_BLOCK_PATTERN.exec(content)) !== null) {
|
|
4181
|
+
const aliasBlock = aliasBlockMatch[1];
|
|
4182
|
+
let aliasEntryMatch;
|
|
4183
|
+
WEBPACK_ALIAS_ENTRY_PATTERN.lastIndex = 0;
|
|
4184
|
+
while ((aliasEntryMatch = WEBPACK_ALIAS_ENTRY_PATTERN.exec(aliasBlock)) !== null) {
|
|
4185
|
+
const rawName = aliasEntryMatch[1];
|
|
4186
|
+
const pathCallSegments = aliasEntryMatch[2];
|
|
4187
|
+
const stringTarget = aliasEntryMatch[3];
|
|
4188
|
+
if (!pathCallSegments && !stringTarget) continue;
|
|
4189
|
+
const isExact = rawName.endsWith("$");
|
|
4190
|
+
const name = isExact ? rawName.slice(0, -1) : rawName.replace(/\/$/, "");
|
|
4191
|
+
let targetDirectory;
|
|
4192
|
+
if (pathCallSegments) targetDirectory = (0, node_path.resolve)(configDirectory, ...extractQuotedSegments(pathCallSegments));
|
|
4193
|
+
else if (stringTarget) targetDirectory = resolveWebpackPathValue(stringTarget, configDirectory);
|
|
4194
|
+
else continue;
|
|
4195
|
+
aliases.push({
|
|
4196
|
+
name,
|
|
4197
|
+
targetDirectory,
|
|
4198
|
+
isExact
|
|
4199
|
+
});
|
|
4200
|
+
}
|
|
4201
|
+
}
|
|
4202
|
+
return aliases;
|
|
4203
|
+
};
|
|
4204
|
+
const extractWebpackModuleDirectories = (content, configDirectory) => {
|
|
4205
|
+
const moduleDirectories = [];
|
|
4206
|
+
let modulesBlockMatch;
|
|
4207
|
+
WEBPACK_MODULES_BLOCK_PATTERN.lastIndex = 0;
|
|
4208
|
+
while ((modulesBlockMatch = WEBPACK_MODULES_BLOCK_PATTERN.exec(content)) !== null) {
|
|
4209
|
+
const modulesBlock = modulesBlockMatch[1];
|
|
4210
|
+
let pathCallMatch;
|
|
4211
|
+
WEBPACK_PATH_CALL_PATTERN.lastIndex = 0;
|
|
4212
|
+
while ((pathCallMatch = WEBPACK_PATH_CALL_PATTERN.exec(modulesBlock)) !== null) moduleDirectories.push((0, node_path.resolve)(configDirectory, ...extractQuotedSegments(pathCallMatch[1])));
|
|
4213
|
+
let stringMatch;
|
|
4214
|
+
WEBPACK_STRING_LITERAL_PATTERN.lastIndex = 0;
|
|
4215
|
+
while ((stringMatch = WEBPACK_STRING_LITERAL_PATTERN.exec(modulesBlock)) !== null) {
|
|
4216
|
+
const moduleDirectory = stringMatch[1];
|
|
4217
|
+
if (moduleDirectory === "node_modules") continue;
|
|
4218
|
+
moduleDirectories.push(resolveWebpackPathValue(moduleDirectory, configDirectory));
|
|
4219
|
+
}
|
|
4220
|
+
}
|
|
4221
|
+
return [...new Set(moduleDirectories)];
|
|
4222
|
+
};
|
|
4223
|
+
const loadWebpackResolverConfigs = (rootDir) => {
|
|
4224
|
+
const configPaths = fast_glob.default.sync(WEBPACK_CONFIG_GLOBS, {
|
|
4225
|
+
cwd: rootDir,
|
|
4226
|
+
absolute: true,
|
|
4227
|
+
onlyFiles: true,
|
|
4228
|
+
ignore: [
|
|
4229
|
+
"**/node_modules/**",
|
|
4230
|
+
"**/dist/**",
|
|
4231
|
+
"**/build/**"
|
|
4232
|
+
],
|
|
4233
|
+
deep: 4
|
|
4234
|
+
});
|
|
4235
|
+
const configs = [];
|
|
4236
|
+
for (const configPath of configPaths) try {
|
|
4237
|
+
const content = cachedReadFileSync(configPath);
|
|
4238
|
+
const configDirectory = (0, node_path.dirname)(configPath);
|
|
4239
|
+
const aliases = extractWebpackAliases(content, configDirectory);
|
|
4240
|
+
const moduleDirectories = extractWebpackModuleDirectories(content, configDirectory);
|
|
4241
|
+
if (aliases.length === 0 && moduleDirectories.length === 0) continue;
|
|
4242
|
+
configs.push({
|
|
4243
|
+
scopeDirectory: findWebpackConfigScope(configPath, rootDir),
|
|
4244
|
+
aliases,
|
|
4245
|
+
moduleDirectories
|
|
4246
|
+
});
|
|
4247
|
+
} catch {
|
|
4248
|
+
continue;
|
|
4249
|
+
}
|
|
4250
|
+
return configs;
|
|
4251
|
+
};
|
|
3766
4252
|
const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
3767
4253
|
const resolverCache = /* @__PURE__ */ new Map();
|
|
3768
4254
|
const resolveResultCache = /* @__PURE__ */ new Map();
|
|
@@ -3799,18 +4285,20 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3799
4285
|
};
|
|
3800
4286
|
const workspaceNameToDirectory = /* @__PURE__ */ new Map();
|
|
3801
4287
|
for (const workspacePackage of workspacePackages) workspaceNameToDirectory.set(workspacePackage.name, workspacePackage.directory);
|
|
4288
|
+
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);
|
|
3802
4289
|
let rootTsconfigPath;
|
|
3803
4290
|
if (config.tsConfigPath) rootTsconfigPath = (0, node_path.resolve)(config.rootDir, config.tsConfigPath);
|
|
3804
|
-
else
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
4291
|
+
else {
|
|
4292
|
+
const tsconfigSearchDirs = options.monorepoRoot ? [config.rootDir, options.monorepoRoot] : [config.rootDir];
|
|
4293
|
+
for (const searchDir of tsconfigSearchDirs) {
|
|
4294
|
+
for (const candidate of TSCONFIG_FILENAMES) {
|
|
4295
|
+
const candidatePath = (0, node_path.resolve)(searchDir, candidate);
|
|
4296
|
+
if (cachedExistsSync(candidatePath)) {
|
|
4297
|
+
rootTsconfigPath = candidatePath;
|
|
4298
|
+
break;
|
|
4299
|
+
}
|
|
4300
|
+
}
|
|
4301
|
+
if (rootTsconfigPath) break;
|
|
3814
4302
|
}
|
|
3815
4303
|
}
|
|
3816
4304
|
const tsconfigPathCache = /* @__PURE__ */ new Map();
|
|
@@ -3819,24 +4307,56 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3819
4307
|
const fileDir = (0, node_path.dirname)(filePath);
|
|
3820
4308
|
const cached = tsconfigPathCache.get(fileDir);
|
|
3821
4309
|
if (cached !== void 0) return cached;
|
|
3822
|
-
const tsconfigResult = findNearestTsconfig(fileDir, config.rootDir) ?? rootTsconfigPath;
|
|
4310
|
+
const tsconfigResult = findNearestTsconfig(fileDir, config.rootDir, options.monorepoRoot) ?? rootTsconfigPath;
|
|
3823
4311
|
tsconfigPathCache.set(fileDir, tsconfigResult);
|
|
3824
4312
|
return tsconfigResult;
|
|
3825
4313
|
};
|
|
3826
4314
|
const tsconfigBaseUrlCache = /* @__PURE__ */ new Map();
|
|
3827
|
-
const
|
|
3828
|
-
|
|
3829
|
-
|
|
4315
|
+
const resolveExtendsPath = (extendsValue, fromDir) => {
|
|
4316
|
+
if (extendsValue.startsWith(".")) {
|
|
4317
|
+
const absolutePath = (0, node_path.resolve)(fromDir, extendsValue);
|
|
4318
|
+
if (cachedExistsSync(absolutePath)) return absolutePath;
|
|
4319
|
+
if (cachedExistsSync(absolutePath + ".json")) return absolutePath + ".json";
|
|
4320
|
+
return;
|
|
4321
|
+
}
|
|
4322
|
+
const packagePath = (0, node_path.join)(options.monorepoRoot ?? config.rootDir, "node_modules", extendsValue);
|
|
4323
|
+
if (cachedExistsSync(packagePath)) return packagePath;
|
|
4324
|
+
if (cachedExistsSync(packagePath + ".json")) return packagePath + ".json";
|
|
4325
|
+
const localPackagePath = (0, node_path.join)(fromDir, "node_modules", extendsValue);
|
|
4326
|
+
if (cachedExistsSync(localPackagePath)) return localPackagePath;
|
|
4327
|
+
if (cachedExistsSync(localPackagePath + ".json")) return localPackagePath + ".json";
|
|
4328
|
+
};
|
|
4329
|
+
const collectExtendsEntries = (tsconfigJson) => {
|
|
4330
|
+
if (typeof tsconfigJson.extends === "string") return [tsconfigJson.extends];
|
|
4331
|
+
if (Array.isArray(tsconfigJson.extends)) return tsconfigJson.extends.filter((entry) => typeof entry === "string");
|
|
4332
|
+
return [];
|
|
4333
|
+
};
|
|
4334
|
+
const extractBaseUrlFromTsconfig = (tsconfigFile, visitedFiles) => {
|
|
4335
|
+
if (visitedFiles.has(tsconfigFile)) return void 0;
|
|
4336
|
+
visitedFiles.add(tsconfigFile);
|
|
3830
4337
|
try {
|
|
3831
4338
|
const cleanedContent = stripJsonComments(cachedReadFileSync(tsconfigFile));
|
|
3832
|
-
const
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
4339
|
+
const tsconfigJson = JSON.parse(cleanedContent);
|
|
4340
|
+
const tsconfigDir = (0, node_path.dirname)(tsconfigFile);
|
|
4341
|
+
const baseUrl = tsconfigJson.compilerOptions?.baseUrl;
|
|
4342
|
+
if (baseUrl) return (0, node_path.resolve)(tsconfigDir, baseUrl);
|
|
4343
|
+
for (const extendsEntry of collectExtendsEntries(tsconfigJson)) {
|
|
4344
|
+
const resolvedPath = resolveExtendsPath(extendsEntry, tsconfigDir);
|
|
4345
|
+
if (resolvedPath) {
|
|
4346
|
+
const result = extractBaseUrlFromTsconfig(resolvedPath, visitedFiles);
|
|
4347
|
+
if (result) return result;
|
|
4348
|
+
}
|
|
3837
4349
|
}
|
|
3838
|
-
} catch {
|
|
3839
|
-
|
|
4350
|
+
} catch {
|
|
4351
|
+
return;
|
|
4352
|
+
}
|
|
4353
|
+
};
|
|
4354
|
+
const getBaseUrlDirectory = (tsconfigFile) => {
|
|
4355
|
+
const cached = tsconfigBaseUrlCache.get(tsconfigFile);
|
|
4356
|
+
if (cached !== void 0) return cached;
|
|
4357
|
+
const result = extractBaseUrlFromTsconfig(tsconfigFile, /* @__PURE__ */ new Set());
|
|
4358
|
+
tsconfigBaseUrlCache.set(tsconfigFile, result);
|
|
4359
|
+
return result;
|
|
3840
4360
|
};
|
|
3841
4361
|
const hasNextJsDependency = (() => {
|
|
3842
4362
|
try {
|
|
@@ -3849,25 +4369,83 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3849
4369
|
return false;
|
|
3850
4370
|
}
|
|
3851
4371
|
})();
|
|
3852
|
-
const
|
|
3853
|
-
|
|
4372
|
+
const packageDependencyCache = /* @__PURE__ */ new Map();
|
|
4373
|
+
const readPackageDependencies = (directory) => {
|
|
4374
|
+
const cached = packageDependencyCache.get(directory);
|
|
3854
4375
|
if (cached) return cached;
|
|
3855
|
-
const
|
|
3856
|
-
const
|
|
4376
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
4377
|
+
const packageJsonPath = (0, node_path.join)(directory, "package.json");
|
|
4378
|
+
try {
|
|
4379
|
+
const packageJson = JSON.parse(cachedReadFileSync(packageJsonPath));
|
|
4380
|
+
const dependencySections = [
|
|
4381
|
+
packageJson.dependencies,
|
|
4382
|
+
packageJson.devDependencies,
|
|
4383
|
+
packageJson.optionalDependencies
|
|
4384
|
+
];
|
|
4385
|
+
for (const dependencySection of dependencySections) {
|
|
4386
|
+
if (!dependencySection || typeof dependencySection !== "object") continue;
|
|
4387
|
+
for (const dependencyName of Object.keys(dependencySection)) dependencies.add(dependencyName);
|
|
4388
|
+
}
|
|
4389
|
+
} catch {}
|
|
4390
|
+
packageDependencyCache.set(directory, dependencies);
|
|
4391
|
+
return dependencies;
|
|
4392
|
+
};
|
|
4393
|
+
const findNearestPackageSrcDirectoryWithDependency = (filePath, dependencyNames) => {
|
|
4394
|
+
let currentDirectory = (0, node_path.dirname)(filePath);
|
|
4395
|
+
const stopAt = options.monorepoRoot ? (0, node_path.resolve)(options.monorepoRoot) : (0, node_path.resolve)(config.rootDir);
|
|
4396
|
+
while (currentDirectory.length >= stopAt.length) {
|
|
4397
|
+
if (cachedExistsSync((0, node_path.join)(currentDirectory, "package.json"))) {
|
|
4398
|
+
const dependencies = readPackageDependencies(currentDirectory);
|
|
4399
|
+
if (dependencyNames.some((dependencyName) => dependencies.has(dependencyName))) {
|
|
4400
|
+
const srcDirectory = (0, node_path.join)(currentDirectory, "src");
|
|
4401
|
+
return cachedExistsSync(srcDirectory) ? srcDirectory : void 0;
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
4404
|
+
const parentDirectory = (0, node_path.dirname)(currentDirectory);
|
|
4405
|
+
if (parentDirectory === currentDirectory) break;
|
|
4406
|
+
currentDirectory = parentDirectory;
|
|
4407
|
+
}
|
|
4408
|
+
};
|
|
4409
|
+
const extractPathsFromTsconfig = (tsconfigFile, visitedFiles) => {
|
|
4410
|
+
if (visitedFiles.has(tsconfigFile)) return void 0;
|
|
4411
|
+
visitedFiles.add(tsconfigFile);
|
|
3857
4412
|
try {
|
|
3858
4413
|
const tsconfigContent = cachedReadFileSync(tsconfigFile).trim();
|
|
3859
|
-
if (tsconfigContent.length
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
4414
|
+
if (tsconfigContent.length === 0) return void 0;
|
|
4415
|
+
const cleanedContent = stripJsonComments(tsconfigContent);
|
|
4416
|
+
const tsconfigJson = JSON.parse(cleanedContent);
|
|
4417
|
+
const tsconfigDir = (0, node_path.dirname)(tsconfigFile);
|
|
4418
|
+
const paths = tsconfigJson.compilerOptions?.paths;
|
|
4419
|
+
const baseUrl = tsconfigJson.compilerOptions?.baseUrl;
|
|
4420
|
+
if (paths && typeof paths === "object") return {
|
|
4421
|
+
paths,
|
|
4422
|
+
baseUrl: baseUrl ?? ".",
|
|
4423
|
+
tsconfigDir
|
|
4424
|
+
};
|
|
4425
|
+
for (const extendsEntry of collectExtendsEntries(tsconfigJson)) {
|
|
4426
|
+
const resolvedPath = resolveExtendsPath(extendsEntry, tsconfigDir);
|
|
4427
|
+
if (resolvedPath) {
|
|
4428
|
+
const result = extractPathsFromTsconfig(resolvedPath, visitedFiles);
|
|
4429
|
+
if (result) return result;
|
|
3866
4430
|
}
|
|
3867
4431
|
}
|
|
3868
|
-
} catch {
|
|
3869
|
-
|
|
3870
|
-
|
|
4432
|
+
} catch {
|
|
4433
|
+
return;
|
|
4434
|
+
}
|
|
4435
|
+
};
|
|
4436
|
+
const getPathAliases = (tsconfigFile) => {
|
|
4437
|
+
const cached = tsconfigPathAliasCache.get(tsconfigFile);
|
|
4438
|
+
if (cached) return cached;
|
|
4439
|
+
const aliasMap = /* @__PURE__ */ new Map();
|
|
4440
|
+
const extracted = extractPathsFromTsconfig(tsconfigFile, /* @__PURE__ */ new Set());
|
|
4441
|
+
if (extracted) {
|
|
4442
|
+
for (const [pattern, targets] of Object.entries(extracted.paths)) if (Array.isArray(targets)) aliasMap.set(pattern, targets.map((target) => (0, node_path.resolve)(extracted.tsconfigDir, extracted.baseUrl, target)));
|
|
4443
|
+
}
|
|
4444
|
+
if (aliasMap.size === 0 && hasNextJsDependency) {
|
|
4445
|
+
const tsconfigDir = (0, node_path.dirname)(tsconfigFile);
|
|
4446
|
+
if (cachedExistsSync((0, node_path.resolve)(tsconfigDir, "src"))) aliasMap.set("@/*", [(0, node_path.resolve)(tsconfigDir, "src/*")]);
|
|
4447
|
+
else aliasMap.set("@/*", [(0, node_path.resolve)(tsconfigDir, "*")]);
|
|
4448
|
+
}
|
|
3871
4449
|
tsconfigPathAliasCache.set(tsconfigFile, aliasMap);
|
|
3872
4450
|
return aliasMap;
|
|
3873
4451
|
};
|
|
@@ -3904,6 +4482,28 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3904
4482
|
}
|
|
3905
4483
|
}
|
|
3906
4484
|
};
|
|
4485
|
+
const tryResolveFromDirectory = (directory, specifier) => {
|
|
4486
|
+
const candidatePath = resolvePathWithExtensionFallback((0, node_path.resolve)(directory, specifier));
|
|
4487
|
+
if (existsAsFile(candidatePath)) return candidatePath;
|
|
4488
|
+
};
|
|
4489
|
+
const tryResolveViaWebpackConfig = (specifier, fromFile) => {
|
|
4490
|
+
if (webpackResolverConfigs.length === 0) return void 0;
|
|
4491
|
+
if (!isBareSpecifier(specifier)) return void 0;
|
|
4492
|
+
for (const webpackConfig of webpackResolverConfigs) {
|
|
4493
|
+
if (!isInsideDirectory(fromFile, webpackConfig.scopeDirectory)) continue;
|
|
4494
|
+
for (const alias of webpackConfig.aliases) {
|
|
4495
|
+
if (alias.isExact && specifier !== alias.name) continue;
|
|
4496
|
+
const suffix = specifier === alias.name ? "" : specifier.startsWith(`${alias.name}/`) ? specifier.slice(alias.name.length + 1) : void 0;
|
|
4497
|
+
if (suffix === void 0) continue;
|
|
4498
|
+
const aliasCandidate = tryResolveFromDirectory(alias.targetDirectory, suffix);
|
|
4499
|
+
if (aliasCandidate) return aliasCandidate;
|
|
4500
|
+
}
|
|
4501
|
+
for (const moduleDirectory of webpackConfig.moduleDirectories) {
|
|
4502
|
+
const moduleCandidate = tryResolveFromDirectory(moduleDirectory, specifier);
|
|
4503
|
+
if (moduleCandidate) return moduleCandidate;
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4506
|
+
};
|
|
3907
4507
|
const resolveModule = (specifier, fromFile) => {
|
|
3908
4508
|
const queryIndex = specifier.indexOf("?");
|
|
3909
4509
|
const cleanedSpecifier = queryIndex !== -1 ? specifier.slice(0, queryIndex) : specifier;
|
|
@@ -4067,6 +4667,16 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
4067
4667
|
resolveResultCache.set(cacheKey, resolvedResult);
|
|
4068
4668
|
return resolvedResult;
|
|
4069
4669
|
}
|
|
4670
|
+
const webpackResolved = tryResolveViaWebpackConfig(cleanedSpecifier, fromFile);
|
|
4671
|
+
if (webpackResolved) {
|
|
4672
|
+
const resolvedResult = {
|
|
4673
|
+
resolvedPath: webpackResolved,
|
|
4674
|
+
isExternal: false,
|
|
4675
|
+
packageName: void 0
|
|
4676
|
+
};
|
|
4677
|
+
resolveResultCache.set(cacheKey, resolvedResult);
|
|
4678
|
+
return resolvedResult;
|
|
4679
|
+
}
|
|
4070
4680
|
if (isBareSpecifier(cleanedSpecifier)) {
|
|
4071
4681
|
const tsconfigFile = findTsconfigForFile(fromFile);
|
|
4072
4682
|
if (tsconfigFile) {
|
|
@@ -4100,6 +4710,19 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
4100
4710
|
}
|
|
4101
4711
|
}
|
|
4102
4712
|
}
|
|
4713
|
+
const createReactAppSrcDirectory = findNearestPackageSrcDirectoryWithDependency(fromFile, ["react-scripts", "react-app-rewired"]);
|
|
4714
|
+
if (createReactAppSrcDirectory) {
|
|
4715
|
+
const craResolved = tryResolveFromDirectory(createReactAppSrcDirectory, cleanedSpecifier);
|
|
4716
|
+
if (craResolved) {
|
|
4717
|
+
const resolvedResult = {
|
|
4718
|
+
resolvedPath: craResolved,
|
|
4719
|
+
isExternal: false,
|
|
4720
|
+
packageName: void 0
|
|
4721
|
+
};
|
|
4722
|
+
resolveResultCache.set(cacheKey, resolvedResult);
|
|
4723
|
+
return resolvedResult;
|
|
4724
|
+
}
|
|
4725
|
+
}
|
|
4103
4726
|
const resolvedResult = {
|
|
4104
4727
|
resolvedPath: void 0,
|
|
4105
4728
|
isExternal: true,
|
|
@@ -4563,12 +5186,16 @@ const detectDeadExports = (graph, config) => {
|
|
|
4563
5186
|
if (!module.isReachable) continue;
|
|
4564
5187
|
if (module.isDeclarationFile) continue;
|
|
4565
5188
|
if (module.isEntryPoint && !config.includeEntryExports) continue;
|
|
5189
|
+
const defaultExportLinkedNames = /* @__PURE__ */ new Set();
|
|
5190
|
+
for (const exportInfo of module.exports) if (exportInfo.isDefault && exportInfo.defaultExportLocalName && usageMap.has(`${module.fileId.path}::default`)) defaultExportLinkedNames.add(exportInfo.defaultExportLocalName);
|
|
4566
5191
|
for (const exportInfo of module.exports) {
|
|
4567
5192
|
if (exportInfo.name === "*" && exportInfo.isNamespaceReExport) continue;
|
|
4568
5193
|
if (exportInfo.isReExport && exportInfo.reExportOriginalName) continue;
|
|
4569
5194
|
if (!config.reportTypes && exportInfo.isTypeOnly) continue;
|
|
4570
5195
|
const usageKey = `${module.fileId.path}::${exportInfo.name}`;
|
|
4571
|
-
if (
|
|
5196
|
+
if (usageMap.has(usageKey)) continue;
|
|
5197
|
+
if (!exportInfo.isDefault && defaultExportLinkedNames.has(exportInfo.name)) continue;
|
|
5198
|
+
unusedExports.push({
|
|
4572
5199
|
path: module.fileId.path,
|
|
4573
5200
|
name: exportInfo.name,
|
|
4574
5201
|
line: exportInfo.line,
|
|
@@ -4684,62 +5311,18 @@ const followReExportChain = (reExporterModuleIndex, exportInfo, graph, sourceToT
|
|
|
4684
5311
|
//#endregion
|
|
4685
5312
|
//#region src/utils/package-name.ts
|
|
4686
5313
|
const extractPackageName = (specifier) => {
|
|
4687
|
-
|
|
5314
|
+
const normalizedSpecifier = specifier.startsWith("~") ? specifier.slice(1) : specifier;
|
|
5315
|
+
if (normalizedSpecifier.startsWith(".") || normalizedSpecifier.startsWith("/")) return void 0;
|
|
4688
5316
|
if (specifier.startsWith("node:")) return void 0;
|
|
4689
|
-
if (
|
|
4690
|
-
const parts =
|
|
5317
|
+
if (normalizedSpecifier.startsWith("@")) {
|
|
5318
|
+
const parts = normalizedSpecifier.split("/");
|
|
4691
5319
|
return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : void 0;
|
|
4692
5320
|
}
|
|
4693
|
-
return
|
|
5321
|
+
return normalizedSpecifier.split("/")[0];
|
|
4694
5322
|
};
|
|
4695
5323
|
|
|
4696
5324
|
//#endregion
|
|
4697
5325
|
//#region src/report/packages.ts
|
|
4698
|
-
const MONOREPO_ROOT_MARKERS = [
|
|
4699
|
-
"pnpm-workspace.yaml",
|
|
4700
|
-
"pnpm-workspace.yml",
|
|
4701
|
-
"lerna.json",
|
|
4702
|
-
"nx.json",
|
|
4703
|
-
"turbo.json",
|
|
4704
|
-
"rush.json"
|
|
4705
|
-
];
|
|
4706
|
-
const LOCKFILE_MARKERS = [
|
|
4707
|
-
"pnpm-lock.yaml",
|
|
4708
|
-
"yarn.lock",
|
|
4709
|
-
"package-lock.json",
|
|
4710
|
-
"bun.lockb",
|
|
4711
|
-
"bun.lock"
|
|
4712
|
-
];
|
|
4713
|
-
const MAX_MONOREPO_WALK_DEPTH = 5;
|
|
4714
|
-
const findMonorepoRoot = (rootDir) => {
|
|
4715
|
-
let currentDirectory = (0, node_path.resolve)(rootDir);
|
|
4716
|
-
let walkedDepth = 0;
|
|
4717
|
-
while (walkedDepth < MAX_MONOREPO_WALK_DEPTH) {
|
|
4718
|
-
const parentDirectory = (0, node_path.dirname)(currentDirectory);
|
|
4719
|
-
if (parentDirectory === currentDirectory) break;
|
|
4720
|
-
currentDirectory = parentDirectory;
|
|
4721
|
-
walkedDepth++;
|
|
4722
|
-
if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, ".git"))) {
|
|
4723
|
-
for (const marker of MONOREPO_ROOT_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, marker))) return currentDirectory;
|
|
4724
|
-
const packageJsonPath = (0, node_path.join)(currentDirectory, "package.json");
|
|
4725
|
-
if ((0, node_fs.existsSync)(packageJsonPath)) try {
|
|
4726
|
-
const content = (0, node_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
4727
|
-
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
4728
|
-
} catch {}
|
|
4729
|
-
for (const lockfile of LOCKFILE_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, lockfile))) return currentDirectory;
|
|
4730
|
-
return;
|
|
4731
|
-
}
|
|
4732
|
-
for (const marker of MONOREPO_ROOT_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, marker))) return currentDirectory;
|
|
4733
|
-
const packageJsonPath = (0, node_path.join)(currentDirectory, "package.json");
|
|
4734
|
-
if ((0, node_fs.existsSync)(packageJsonPath)) try {
|
|
4735
|
-
const content = (0, node_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
4736
|
-
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
4737
|
-
} catch {
|
|
4738
|
-
continue;
|
|
4739
|
-
}
|
|
4740
|
-
for (const lockfile of LOCKFILE_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, lockfile))) return currentDirectory;
|
|
4741
|
-
}
|
|
4742
|
-
};
|
|
4743
5326
|
const discoverAllPackageJsonPaths = (rootDir) => {
|
|
4744
5327
|
const paths = [(0, node_path.join)(rootDir, "package.json")];
|
|
4745
5328
|
const workspacePackageJsons = fast_glob.default.sync("**/package.json", {
|
|
@@ -4787,6 +5370,8 @@ const detectStalePackages = (graph, config) => {
|
|
|
4787
5370
|
const packageJsonConfigReferenced = collectPackageJsonConfigReferences(workspacePackageJsonPath, declaredNames);
|
|
4788
5371
|
for (const packageName of packageJsonConfigReferenced) usedPackageNames.add(packageName);
|
|
4789
5372
|
}
|
|
5373
|
+
const nxProjectReferenced = collectNxProjectJsonReferences(config.rootDir, declaredNames, binToPackage);
|
|
5374
|
+
for (const packageName of nxProjectReferenced) usedPackageNames.add(packageName);
|
|
4790
5375
|
const configSearchRoots = monorepoRoot && monorepoRoot !== config.rootDir ? [config.rootDir, monorepoRoot] : [config.rootDir];
|
|
4791
5376
|
for (const configSearchRoot of configSearchRoots) {
|
|
4792
5377
|
const configReferenced = collectConfigReferencedPackages(configSearchRoot, graph, declaredNames);
|
|
@@ -4800,8 +5385,36 @@ const detectStalePackages = (graph, config) => {
|
|
|
4800
5385
|
if (declaredNames.has("react-native")) usedPackageNames.add("react-native");
|
|
4801
5386
|
if (declaredNames.has("react-native-web")) usedPackageNames.add("react-native-web");
|
|
4802
5387
|
}
|
|
5388
|
+
if (declaredNames.has("react-dom")) {
|
|
5389
|
+
if ([
|
|
5390
|
+
"next",
|
|
5391
|
+
"gatsby",
|
|
5392
|
+
"@remix-run/react",
|
|
5393
|
+
"react-router-dom",
|
|
5394
|
+
"vite",
|
|
5395
|
+
"@docusaurus/core",
|
|
5396
|
+
"react-scripts",
|
|
5397
|
+
"astro",
|
|
5398
|
+
"@tanstack/react-router",
|
|
5399
|
+
"@tanstack/react-start",
|
|
5400
|
+
"react-app-rewired"
|
|
5401
|
+
].some((framework) => declaredNames.has(framework) || usedPackageNames.has(framework))) usedPackageNames.add("react-dom");
|
|
5402
|
+
}
|
|
5403
|
+
if (declaredNames.has("react") && declaredNames.has("react-dom")) {
|
|
5404
|
+
const packageJsonPath = (0, node_path.resolve)(config.rootDir, "package.json");
|
|
5405
|
+
try {
|
|
5406
|
+
const content = (0, node_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
5407
|
+
const peerDeps = JSON.parse(content).peerDependencies ?? {};
|
|
5408
|
+
if ("react" in peerDeps && declaredDependencies.get("react") === true) usedPackageNames.add("react");
|
|
5409
|
+
if ("react-dom" in peerDeps && declaredDependencies.get("react-dom") === true) usedPackageNames.add("react-dom");
|
|
5410
|
+
} catch {}
|
|
5411
|
+
}
|
|
4803
5412
|
const peerSatisfied = collectPeerSatisfiedPackages(nodeModulesRoot, declaredNames, usedPackageNames);
|
|
4804
5413
|
for (const packageName of peerSatisfied) usedPackageNames.add(packageName);
|
|
5414
|
+
const staticPeerSatisfied = collectStaticPeerSatisfiedPackages(declaredNames, usedPackageNames);
|
|
5415
|
+
for (const packageName of staticPeerSatisfied) usedPackageNames.add(packageName);
|
|
5416
|
+
const implicitCompanionPackages = collectImplicitCompanionPackages(declaredNames, usedPackageNames);
|
|
5417
|
+
for (const packageName of implicitCompanionPackages) usedPackageNames.add(packageName);
|
|
4805
5418
|
const candidateUnused = /* @__PURE__ */ new Set();
|
|
4806
5419
|
for (const [dependencyName] of declaredDependencies) {
|
|
4807
5420
|
if (isAlwaysConsideredUsed(dependencyName)) continue;
|
|
@@ -4855,11 +5468,75 @@ const collectPeerSatisfiedPackages = (rootDir, declaredNames, confirmedUsedNames
|
|
|
4855
5468
|
}
|
|
4856
5469
|
return peerSatisfied;
|
|
4857
5470
|
};
|
|
5471
|
+
const STATIC_PEER_DEPENDENCY_MAP = {
|
|
5472
|
+
"@apollo/client": ["graphql"],
|
|
5473
|
+
"@docusaurus/core": ["@mdx-js/react"],
|
|
5474
|
+
"@fortawesome/react-fontawesome": ["@fortawesome/fontawesome-svg-core"],
|
|
5475
|
+
"@gorhom/bottom-sheet": ["react-native-gesture-handler", "react-native-reanimated"],
|
|
5476
|
+
"@hookform/resolvers": ["zod"],
|
|
5477
|
+
"@mdx-js/loader": ["@mdx-js/react"],
|
|
5478
|
+
"@mui/material": ["react-transition-group", "styled-components"],
|
|
5479
|
+
"@stripe/react-stripe-js": ["@stripe/stripe-js"],
|
|
5480
|
+
"@tiptap/core": ["@tiptap/pm"],
|
|
5481
|
+
"@tiptap/react": ["@tiptap/pm"],
|
|
5482
|
+
"@trpc/server": ["zod"],
|
|
5483
|
+
"chart.js": [],
|
|
5484
|
+
"fumadocs-core": ["@mdx-js/react"],
|
|
5485
|
+
"fumadocs-mdx": ["@mdx-js/react"],
|
|
5486
|
+
"fumadocs-ui": ["@mdx-js/react"],
|
|
5487
|
+
"graphql-request": ["graphql"],
|
|
5488
|
+
nextra: ["@mdx-js/react"],
|
|
5489
|
+
"nextra-theme-blog": ["@mdx-js/react"],
|
|
5490
|
+
"nextra-theme-docs": ["@mdx-js/react"],
|
|
5491
|
+
"react-app-polyfill": ["core-js"],
|
|
5492
|
+
"react-bootstrap": ["react-transition-group"],
|
|
5493
|
+
"react-chartjs-2": ["chart.js"],
|
|
5494
|
+
"react-redux": ["redux"],
|
|
5495
|
+
"react-router-dom": ["react-router"],
|
|
5496
|
+
"redux-thunk": ["redux"],
|
|
5497
|
+
sanity: ["styled-components"],
|
|
5498
|
+
sequelize: ["pg"],
|
|
5499
|
+
"stylis-plugin-rtl": ["stylis"],
|
|
5500
|
+
urql: ["graphql"],
|
|
5501
|
+
"use-immer": ["immer"],
|
|
5502
|
+
zustand: ["immer"]
|
|
5503
|
+
};
|
|
5504
|
+
const collectStaticPeerSatisfiedPackages = (declaredNames, confirmedUsedNames) => {
|
|
5505
|
+
const peerSatisfied = /* @__PURE__ */ new Set();
|
|
5506
|
+
for (const [packageName, peerNames] of Object.entries(STATIC_PEER_DEPENDENCY_MAP)) {
|
|
5507
|
+
if (!confirmedUsedNames.has(packageName)) continue;
|
|
5508
|
+
for (const peerName of peerNames) if (declaredNames.has(peerName)) peerSatisfied.add(peerName);
|
|
5509
|
+
}
|
|
5510
|
+
return peerSatisfied;
|
|
5511
|
+
};
|
|
5512
|
+
const IMPLICIT_COMPANION_DEPENDENCY_MAP = {
|
|
5513
|
+
jest: ["jest-config"],
|
|
5514
|
+
"jest-cli": ["jest-config"]
|
|
5515
|
+
};
|
|
5516
|
+
const collectImplicitCompanionPackages = (declaredNames, confirmedUsedNames) => {
|
|
5517
|
+
const companions = /* @__PURE__ */ new Set();
|
|
5518
|
+
for (const [packageName, companionNames] of Object.entries(IMPLICIT_COMPANION_DEPENDENCY_MAP)) {
|
|
5519
|
+
if (!confirmedUsedNames.has(packageName)) continue;
|
|
5520
|
+
for (const companionName of companionNames) if (declaredNames.has(companionName)) companions.add(companionName);
|
|
5521
|
+
}
|
|
5522
|
+
return companions;
|
|
5523
|
+
};
|
|
4858
5524
|
const SHELL_SPLIT_PATTERN = /\s*(?:&&|\|\||[;&|])\s*/;
|
|
4859
5525
|
const CLI_BINARY_TO_PACKAGE = {
|
|
5526
|
+
"babel-node": "@babel/node",
|
|
5527
|
+
"trigger.dev": "trigger.dev",
|
|
5528
|
+
"@formatjs/cli": "@formatjs/cli",
|
|
4860
5529
|
"react-scripts": "react-scripts",
|
|
4861
5530
|
"webpack-cli": "webpack-cli",
|
|
4862
5531
|
"webpack-dev-server": "webpack-dev-server",
|
|
5532
|
+
babel: "@babel/cli",
|
|
5533
|
+
chokidar: "chokidar-cli",
|
|
5534
|
+
"replace-in-file": "replace-in-file",
|
|
5535
|
+
tauri: "@tauri-apps/cli",
|
|
5536
|
+
tinacms: "@tinacms/cli",
|
|
5537
|
+
"tsc-alias": "tsc-alias",
|
|
5538
|
+
formatjs: "@formatjs/cli",
|
|
5539
|
+
prompt: "prompt",
|
|
4863
5540
|
vitest: "vitest",
|
|
4864
5541
|
jest: "jest",
|
|
4865
5542
|
prisma: "prisma",
|
|
@@ -4877,6 +5554,10 @@ const CLI_BINARY_TO_PACKAGE = {
|
|
|
4877
5554
|
"generate-arg-types": "@webstudio-is/generate-arg-types",
|
|
4878
5555
|
email: "@react-email/preview-server"
|
|
4879
5556
|
};
|
|
5557
|
+
const CLI_BINARY_FALLBACK_PACKAGES = {
|
|
5558
|
+
babel: ["babel-cli"],
|
|
5559
|
+
jest: ["jest-cli"]
|
|
5560
|
+
};
|
|
4880
5561
|
const ENV_WRAPPER_BINARY_SET = new Set([
|
|
4881
5562
|
"cross-env",
|
|
4882
5563
|
"dotenv",
|
|
@@ -4908,36 +5589,43 @@ const collectScriptReferencedPackages = (packageJsonPath, declaredNames, binToPa
|
|
|
4908
5589
|
if (!scripts || typeof scripts !== "object") return referenced;
|
|
4909
5590
|
for (const scriptCommand of Object.values(scripts)) {
|
|
4910
5591
|
if (typeof scriptCommand !== "string") continue;
|
|
4911
|
-
const
|
|
4912
|
-
for (const
|
|
4913
|
-
const tokens = segment.trim().split(/\s+/);
|
|
4914
|
-
if (tokens.length === 0) continue;
|
|
4915
|
-
let binaryIndex = 0;
|
|
4916
|
-
const firstToken = tokens[0].replace(/^.*\//, "");
|
|
4917
|
-
if (ENV_WRAPPER_BINARY_SET.has(firstToken)) {
|
|
4918
|
-
const envPackage = binToPackage.get(firstToken);
|
|
4919
|
-
if (envPackage && declaredNames.has(envPackage)) referenced.add(envPackage);
|
|
4920
|
-
binaryIndex = 1;
|
|
4921
|
-
while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
|
|
4922
|
-
if (binaryIndex >= tokens.length) continue;
|
|
4923
|
-
}
|
|
4924
|
-
while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
|
|
4925
|
-
if (binaryIndex >= tokens.length) continue;
|
|
4926
|
-
const binaryToken = tokens[binaryIndex].replace(/^.*\//, "");
|
|
4927
|
-
const effectiveBinary = binaryToken === "npx" || binaryToken === "pnpx" || binaryToken === "bunx" ? tokens[binaryIndex + 1]?.replace(/^.*\//, "") ?? "" : binaryToken;
|
|
4928
|
-
for (const candidateBinary of [binaryToken, effectiveBinary]) {
|
|
4929
|
-
if (!candidateBinary) continue;
|
|
4930
|
-
const mappedPackage = binToPackage.get(candidateBinary);
|
|
4931
|
-
if (mappedPackage && declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
|
|
4932
|
-
if (declaredNames.has(candidateBinary)) referenced.add(candidateBinary);
|
|
4933
|
-
}
|
|
4934
|
-
}
|
|
5592
|
+
const commandReferenced = collectCommandReferencedPackages(scriptCommand, declaredNames, binToPackage);
|
|
5593
|
+
for (const packageName of commandReferenced) referenced.add(packageName);
|
|
4935
5594
|
}
|
|
4936
5595
|
} catch {
|
|
4937
5596
|
return referenced;
|
|
4938
5597
|
}
|
|
4939
5598
|
return referenced;
|
|
4940
5599
|
};
|
|
5600
|
+
const collectCommandReferencedPackages = (command, declaredNames, binToPackage) => {
|
|
5601
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
5602
|
+
const segments = command.split(SHELL_SPLIT_PATTERN);
|
|
5603
|
+
for (const segment of segments) {
|
|
5604
|
+
const tokens = segment.trim().split(/\s+/);
|
|
5605
|
+
if (tokens.length === 0) continue;
|
|
5606
|
+
let binaryIndex = 0;
|
|
5607
|
+
const firstToken = tokens[0].replace(/^.*\//, "");
|
|
5608
|
+
if (ENV_WRAPPER_BINARY_SET.has(firstToken)) {
|
|
5609
|
+
const envPackage = binToPackage.get(firstToken);
|
|
5610
|
+
if (envPackage && declaredNames.has(envPackage)) referenced.add(envPackage);
|
|
5611
|
+
binaryIndex = 1;
|
|
5612
|
+
while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
|
|
5613
|
+
if (binaryIndex >= tokens.length) continue;
|
|
5614
|
+
}
|
|
5615
|
+
while (binaryIndex < tokens.length && INLINE_ENV_VAR_PATTERN.test(tokens[binaryIndex])) binaryIndex++;
|
|
5616
|
+
if (binaryIndex >= tokens.length) continue;
|
|
5617
|
+
const binaryToken = tokens[binaryIndex].replace(/^.*\//, "");
|
|
5618
|
+
const effectiveBinary = binaryToken === "npx" || binaryToken === "pnpx" || binaryToken === "bunx" ? tokens[binaryIndex + 1]?.replace(/^.*\//, "") ?? "" : binaryToken;
|
|
5619
|
+
for (const candidateBinary of [binaryToken, effectiveBinary]) {
|
|
5620
|
+
if (!candidateBinary) continue;
|
|
5621
|
+
const mappedPackage = binToPackage.get(candidateBinary);
|
|
5622
|
+
if (mappedPackage && declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
|
|
5623
|
+
for (const fallbackPackage of CLI_BINARY_FALLBACK_PACKAGES[candidateBinary] ?? []) if (declaredNames.has(fallbackPackage)) referenced.add(fallbackPackage);
|
|
5624
|
+
if (declaredNames.has(candidateBinary)) referenced.add(candidateBinary);
|
|
5625
|
+
}
|
|
5626
|
+
}
|
|
5627
|
+
return referenced;
|
|
5628
|
+
};
|
|
4941
5629
|
const CONFIG_FILE_GLOBS = [
|
|
4942
5630
|
"postcss.config.{js,cjs,mjs,ts}",
|
|
4943
5631
|
".babelrc",
|
|
@@ -5034,6 +5722,39 @@ const collectPackageJsonConfigReferences = (packageJsonPath, declaredNames) => {
|
|
|
5034
5722
|
}
|
|
5035
5723
|
return referenced;
|
|
5036
5724
|
};
|
|
5725
|
+
const collectNxProjectJsonReferences = (rootDir, declaredNames, binToPackage) => {
|
|
5726
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
5727
|
+
const projectJsonPaths = fast_glob.default.sync(["project.json", "**/project.json"], {
|
|
5728
|
+
cwd: rootDir,
|
|
5729
|
+
absolute: true,
|
|
5730
|
+
onlyFiles: true,
|
|
5731
|
+
ignore: [
|
|
5732
|
+
"**/node_modules/**",
|
|
5733
|
+
"**/dist/**",
|
|
5734
|
+
"**/build/**"
|
|
5735
|
+
],
|
|
5736
|
+
deep: 5
|
|
5737
|
+
});
|
|
5738
|
+
for (const projectJsonPath of projectJsonPaths) try {
|
|
5739
|
+
const content = (0, node_fs.readFileSync)(projectJsonPath, "utf-8");
|
|
5740
|
+
const projectJson = JSON.parse(content);
|
|
5741
|
+
const projectText = JSON.stringify(projectJson);
|
|
5742
|
+
for (const packageName of declaredNames) if (projectText.includes(packageName)) referenced.add(packageName);
|
|
5743
|
+
for (const stringValue of collectStringValues(projectJson)) {
|
|
5744
|
+
const commandReferenced = collectCommandReferencedPackages(stringValue, declaredNames, binToPackage);
|
|
5745
|
+
for (const packageName of commandReferenced) referenced.add(packageName);
|
|
5746
|
+
}
|
|
5747
|
+
} catch {
|
|
5748
|
+
continue;
|
|
5749
|
+
}
|
|
5750
|
+
return referenced;
|
|
5751
|
+
};
|
|
5752
|
+
const collectStringValues = (value) => {
|
|
5753
|
+
if (typeof value === "string") return [value];
|
|
5754
|
+
if (!value || typeof value !== "object") return [];
|
|
5755
|
+
if (Array.isArray(value)) return value.flatMap(collectStringValues);
|
|
5756
|
+
return Object.values(value).flatMap(collectStringValues);
|
|
5757
|
+
};
|
|
5037
5758
|
const TSCONFIG_GLOBS = [
|
|
5038
5759
|
"tsconfig.json",
|
|
5039
5760
|
"tsconfig.*.json",
|
|
@@ -5392,7 +6113,13 @@ const defineConfig = (options) => ({
|
|
|
5392
6113
|
const analyze = async (config) => {
|
|
5393
6114
|
const pipelineStartTime = performance.now();
|
|
5394
6115
|
const workspaceDiscovery = resolveWorkspaces((0, node_path.resolve)(config.rootDir));
|
|
5395
|
-
const workspacePackages = workspaceDiscovery.packages;
|
|
6116
|
+
const workspacePackages = [...workspaceDiscovery.packages];
|
|
6117
|
+
const monorepoRoot = findMonorepoRoot(config.rootDir);
|
|
6118
|
+
if (monorepoRoot) {
|
|
6119
|
+
const monorepoWorkspaces = resolveWorkspaces(monorepoRoot);
|
|
6120
|
+
const existingDirectories = new Set(workspacePackages.map((workspacePackage) => workspacePackage.directory));
|
|
6121
|
+
for (const monorepoPackage of monorepoWorkspaces.packages) if (!existingDirectories.has(monorepoPackage.directory)) workspacePackages.push(monorepoPackage);
|
|
6122
|
+
}
|
|
5396
6123
|
const frameworkIgnorePatterns = getFrameworkExclusions(config.rootDir);
|
|
5397
6124
|
const absoluteRoot = (0, node_path.resolve)(config.rootDir);
|
|
5398
6125
|
const outputDirectoryExclusions = OUTPUT_DIRECTORIES.flatMap((outputDirectory) => {
|
|
@@ -5418,7 +6145,10 @@ const analyze = async (config) => {
|
|
|
5418
6145
|
const moduleResolver = createResolver(config, workspacePackages.map((workspacePackage) => ({
|
|
5419
6146
|
name: workspacePackage.name,
|
|
5420
6147
|
directory: workspacePackage.directory
|
|
5421
|
-
})), {
|
|
6148
|
+
})), {
|
|
6149
|
+
hasReactNative,
|
|
6150
|
+
monorepoRoot
|
|
6151
|
+
});
|
|
5422
6152
|
const graphInputs = [];
|
|
5423
6153
|
for (const file of files) {
|
|
5424
6154
|
const parsedModule = parseSourceFile(file.path);
|