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.
Files changed (3) hide show
  1. package/dist/index.cjs +860 -130
  2. package/dist/index.mjs +861 -131
  3. 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: ["vite", "rolldown-vite"],
3160
- enablerPrefixes: ["@vitejs/"],
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) if (isRunnerEnabled(runner, allDependencies, directory)) {
3477
- const isVitestRunner = runner.enablers.includes("vitest");
3478
- const isJestRunner = runner.enablers.includes("jest");
3479
- let customPatterns = [];
3480
- if (isVitestRunner) customPatterns = extractVitestIncludePatterns(directory);
3481
- else if (isJestRunner) customPatterns = extractJestTestMatchPatterns(directory);
3482
- if (customPatterns.length > 0) activatedPatterns.push(...customPatterns);
3483
- else activatedPatterns.push(...runner.entryPatterns);
3484
- activatedFixturePatterns.push(...runner.fixturePatterns);
3485
- activatedAlwaysUsed.push(...runner.alwaysUsed);
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 mergedDependencies = directory === rootDir ? rootDependencies : workspaceDependencies;
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 normalizedRoot = (0, node_path.resolve)(rootDir);
3727
- while (currentDirectory.length >= normalizedRoot.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 for (const candidate of [
3805
- "tsconfig.json",
3806
- "tsconfig.web.json",
3807
- "tsconfig.app.json",
3808
- "tsconfig.base.json"
3809
- ]) {
3810
- const candidatePath = (0, node_path.resolve)(config.rootDir, candidate);
3811
- if (cachedExistsSync(candidatePath)) {
3812
- rootTsconfigPath = candidatePath;
3813
- break;
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 getBaseUrlDirectory = (tsconfigFile) => {
3828
- const cached = tsconfigBaseUrlCache.get(tsconfigFile);
3829
- if (cached !== void 0) return cached;
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 baseUrl = JSON.parse(cleanedContent).compilerOptions?.baseUrl;
3833
- if (baseUrl) {
3834
- const absoluteBaseUrl = (0, node_path.resolve)((0, node_path.dirname)(tsconfigFile), baseUrl);
3835
- tsconfigBaseUrlCache.set(tsconfigFile, absoluteBaseUrl);
3836
- return absoluteBaseUrl;
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
- tsconfigBaseUrlCache.set(tsconfigFile, void 0);
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 getPathAliases = (tsconfigFile) => {
3853
- const cached = tsconfigPathAliasCache.get(tsconfigFile);
4372
+ const packageDependencyCache = /* @__PURE__ */ new Map();
4373
+ const readPackageDependencies = (directory) => {
4374
+ const cached = packageDependencyCache.get(directory);
3854
4375
  if (cached) return cached;
3855
- const aliasMap = /* @__PURE__ */ new Map();
3856
- const tsconfigDir = (0, node_path.dirname)(tsconfigFile);
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 > 0) {
3860
- const cleanedContent = stripJsonComments(tsconfigContent);
3861
- const tsconfigJson = JSON.parse(cleanedContent);
3862
- const paths = tsconfigJson.compilerOptions?.paths;
3863
- const baseUrl = tsconfigJson.compilerOptions?.baseUrl ?? ".";
3864
- if (paths && typeof paths === "object") {
3865
- for (const [pattern, targets] of Object.entries(paths)) if (Array.isArray(targets)) aliasMap.set(pattern, targets.map((target) => (0, node_path.resolve)(tsconfigDir, baseUrl, target)));
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
- if (aliasMap.size === 0 && hasNextJsDependency) if (cachedExistsSync((0, node_path.resolve)(tsconfigDir, "src"))) aliasMap.set("@/*", [(0, node_path.resolve)(tsconfigDir, "src/*")]);
3870
- else aliasMap.set("@/*", [(0, node_path.resolve)(tsconfigDir, "*")]);
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 (!usageMap.has(usageKey)) unusedExports.push({
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
- if (specifier.startsWith(".") || specifier.startsWith("/")) return void 0;
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 (specifier.startsWith("@")) {
4690
- const parts = specifier.split("/");
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 specifier.split("/")[0];
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 segments = scriptCommand.split(SHELL_SPLIT_PATTERN);
4912
- for (const segment of segments) {
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
- })), { hasReactNative });
6148
+ })), {
6149
+ hasReactNative,
6150
+ monorepoRoot
6151
+ });
5422
6152
  const graphInputs = [];
5423
6153
  for (const file of files) {
5424
6154
  const parsedModule = parseSourceFile(file.path);