deslop-js 0.0.7 → 0.0.8
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 +134 -43
- package/dist/index.mjs +134 -43
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3719,12 +3719,13 @@ const TSCONFIG_FILENAMES = [
|
|
|
3719
3719
|
"tsconfig.json",
|
|
3720
3720
|
"tsconfig.web.json",
|
|
3721
3721
|
"tsconfig.app.json",
|
|
3722
|
-
"tsconfig.base.json"
|
|
3722
|
+
"tsconfig.base.json",
|
|
3723
|
+
"jsconfig.json"
|
|
3723
3724
|
];
|
|
3724
|
-
const findNearestTsconfig = (fromDir, rootDir) => {
|
|
3725
|
+
const findNearestTsconfig = (fromDir, rootDir, monorepoRootDir) => {
|
|
3725
3726
|
let currentDirectory = fromDir;
|
|
3726
|
-
const
|
|
3727
|
-
while (currentDirectory.length >=
|
|
3727
|
+
const stopAt = monorepoRootDir ? (0, node_path.resolve)(monorepoRootDir) : (0, node_path.resolve)(rootDir);
|
|
3728
|
+
while (currentDirectory.length >= stopAt.length) {
|
|
3728
3729
|
for (const tsconfigFilename of TSCONFIG_FILENAMES) {
|
|
3729
3730
|
const tsconfigCandidate = (0, node_path.join)(currentDirectory, tsconfigFilename);
|
|
3730
3731
|
if (cachedExistsSync(tsconfigCandidate)) return tsconfigCandidate;
|
|
@@ -3801,16 +3802,17 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3801
3802
|
for (const workspacePackage of workspacePackages) workspaceNameToDirectory.set(workspacePackage.name, workspacePackage.directory);
|
|
3802
3803
|
let rootTsconfigPath;
|
|
3803
3804
|
if (config.tsConfigPath) rootTsconfigPath = (0, node_path.resolve)(config.rootDir, config.tsConfigPath);
|
|
3804
|
-
else
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3805
|
+
else {
|
|
3806
|
+
const tsconfigSearchDirs = options.monorepoRoot ? [config.rootDir, options.monorepoRoot] : [config.rootDir];
|
|
3807
|
+
for (const searchDir of tsconfigSearchDirs) {
|
|
3808
|
+
for (const candidate of TSCONFIG_FILENAMES) {
|
|
3809
|
+
const candidatePath = (0, node_path.resolve)(searchDir, candidate);
|
|
3810
|
+
if (cachedExistsSync(candidatePath)) {
|
|
3811
|
+
rootTsconfigPath = candidatePath;
|
|
3812
|
+
break;
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
if (rootTsconfigPath) break;
|
|
3814
3816
|
}
|
|
3815
3817
|
}
|
|
3816
3818
|
const tsconfigPathCache = /* @__PURE__ */ new Map();
|
|
@@ -3819,24 +3821,56 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3819
3821
|
const fileDir = (0, node_path.dirname)(filePath);
|
|
3820
3822
|
const cached = tsconfigPathCache.get(fileDir);
|
|
3821
3823
|
if (cached !== void 0) return cached;
|
|
3822
|
-
const tsconfigResult = findNearestTsconfig(fileDir, config.rootDir) ?? rootTsconfigPath;
|
|
3824
|
+
const tsconfigResult = findNearestTsconfig(fileDir, config.rootDir, options.monorepoRoot) ?? rootTsconfigPath;
|
|
3823
3825
|
tsconfigPathCache.set(fileDir, tsconfigResult);
|
|
3824
3826
|
return tsconfigResult;
|
|
3825
3827
|
};
|
|
3826
3828
|
const tsconfigBaseUrlCache = /* @__PURE__ */ new Map();
|
|
3827
|
-
const
|
|
3828
|
-
|
|
3829
|
-
|
|
3829
|
+
const resolveExtendsPath = (extendsValue, fromDir) => {
|
|
3830
|
+
if (extendsValue.startsWith(".")) {
|
|
3831
|
+
const absolutePath = (0, node_path.resolve)(fromDir, extendsValue);
|
|
3832
|
+
if (cachedExistsSync(absolutePath)) return absolutePath;
|
|
3833
|
+
if (cachedExistsSync(absolutePath + ".json")) return absolutePath + ".json";
|
|
3834
|
+
return;
|
|
3835
|
+
}
|
|
3836
|
+
const packagePath = (0, node_path.join)(options.monorepoRoot ?? config.rootDir, "node_modules", extendsValue);
|
|
3837
|
+
if (cachedExistsSync(packagePath)) return packagePath;
|
|
3838
|
+
if (cachedExistsSync(packagePath + ".json")) return packagePath + ".json";
|
|
3839
|
+
const localPackagePath = (0, node_path.join)(fromDir, "node_modules", extendsValue);
|
|
3840
|
+
if (cachedExistsSync(localPackagePath)) return localPackagePath;
|
|
3841
|
+
if (cachedExistsSync(localPackagePath + ".json")) return localPackagePath + ".json";
|
|
3842
|
+
};
|
|
3843
|
+
const collectExtendsEntries = (tsconfigJson) => {
|
|
3844
|
+
if (typeof tsconfigJson.extends === "string") return [tsconfigJson.extends];
|
|
3845
|
+
if (Array.isArray(tsconfigJson.extends)) return tsconfigJson.extends.filter((entry) => typeof entry === "string");
|
|
3846
|
+
return [];
|
|
3847
|
+
};
|
|
3848
|
+
const extractBaseUrlFromTsconfig = (tsconfigFile, visitedFiles) => {
|
|
3849
|
+
if (visitedFiles.has(tsconfigFile)) return void 0;
|
|
3850
|
+
visitedFiles.add(tsconfigFile);
|
|
3830
3851
|
try {
|
|
3831
3852
|
const cleanedContent = stripJsonComments(cachedReadFileSync(tsconfigFile));
|
|
3832
|
-
const
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3853
|
+
const tsconfigJson = JSON.parse(cleanedContent);
|
|
3854
|
+
const tsconfigDir = (0, node_path.dirname)(tsconfigFile);
|
|
3855
|
+
const baseUrl = tsconfigJson.compilerOptions?.baseUrl;
|
|
3856
|
+
if (baseUrl) return (0, node_path.resolve)(tsconfigDir, baseUrl);
|
|
3857
|
+
for (const extendsEntry of collectExtendsEntries(tsconfigJson)) {
|
|
3858
|
+
const resolvedPath = resolveExtendsPath(extendsEntry, tsconfigDir);
|
|
3859
|
+
if (resolvedPath) {
|
|
3860
|
+
const result = extractBaseUrlFromTsconfig(resolvedPath, visitedFiles);
|
|
3861
|
+
if (result) return result;
|
|
3862
|
+
}
|
|
3837
3863
|
}
|
|
3838
|
-
} catch {
|
|
3839
|
-
|
|
3864
|
+
} catch {
|
|
3865
|
+
return;
|
|
3866
|
+
}
|
|
3867
|
+
};
|
|
3868
|
+
const getBaseUrlDirectory = (tsconfigFile) => {
|
|
3869
|
+
const cached = tsconfigBaseUrlCache.get(tsconfigFile);
|
|
3870
|
+
if (cached !== void 0) return cached;
|
|
3871
|
+
const result = extractBaseUrlFromTsconfig(tsconfigFile, /* @__PURE__ */ new Set());
|
|
3872
|
+
tsconfigBaseUrlCache.set(tsconfigFile, result);
|
|
3873
|
+
return result;
|
|
3840
3874
|
};
|
|
3841
3875
|
const hasNextJsDependency = (() => {
|
|
3842
3876
|
try {
|
|
@@ -3849,25 +3883,46 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3849
3883
|
return false;
|
|
3850
3884
|
}
|
|
3851
3885
|
})();
|
|
3852
|
-
const
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
const aliasMap = /* @__PURE__ */ new Map();
|
|
3856
|
-
const tsconfigDir = (0, node_path.dirname)(tsconfigFile);
|
|
3886
|
+
const extractPathsFromTsconfig = (tsconfigFile, visitedFiles) => {
|
|
3887
|
+
if (visitedFiles.has(tsconfigFile)) return void 0;
|
|
3888
|
+
visitedFiles.add(tsconfigFile);
|
|
3857
3889
|
try {
|
|
3858
3890
|
const tsconfigContent = cachedReadFileSync(tsconfigFile).trim();
|
|
3859
|
-
if (tsconfigContent.length
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3891
|
+
if (tsconfigContent.length === 0) return void 0;
|
|
3892
|
+
const cleanedContent = stripJsonComments(tsconfigContent);
|
|
3893
|
+
const tsconfigJson = JSON.parse(cleanedContent);
|
|
3894
|
+
const tsconfigDir = (0, node_path.dirname)(tsconfigFile);
|
|
3895
|
+
const paths = tsconfigJson.compilerOptions?.paths;
|
|
3896
|
+
const baseUrl = tsconfigJson.compilerOptions?.baseUrl;
|
|
3897
|
+
if (paths && typeof paths === "object") return {
|
|
3898
|
+
paths,
|
|
3899
|
+
baseUrl: baseUrl ?? ".",
|
|
3900
|
+
tsconfigDir
|
|
3901
|
+
};
|
|
3902
|
+
for (const extendsEntry of collectExtendsEntries(tsconfigJson)) {
|
|
3903
|
+
const resolvedPath = resolveExtendsPath(extendsEntry, tsconfigDir);
|
|
3904
|
+
if (resolvedPath) {
|
|
3905
|
+
const result = extractPathsFromTsconfig(resolvedPath, visitedFiles);
|
|
3906
|
+
if (result) return result;
|
|
3866
3907
|
}
|
|
3867
3908
|
}
|
|
3868
|
-
} catch {
|
|
3869
|
-
|
|
3870
|
-
|
|
3909
|
+
} catch {
|
|
3910
|
+
return;
|
|
3911
|
+
}
|
|
3912
|
+
};
|
|
3913
|
+
const getPathAliases = (tsconfigFile) => {
|
|
3914
|
+
const cached = tsconfigPathAliasCache.get(tsconfigFile);
|
|
3915
|
+
if (cached) return cached;
|
|
3916
|
+
const aliasMap = /* @__PURE__ */ new Map();
|
|
3917
|
+
const extracted = extractPathsFromTsconfig(tsconfigFile, /* @__PURE__ */ new Set());
|
|
3918
|
+
if (extracted) {
|
|
3919
|
+
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)));
|
|
3920
|
+
}
|
|
3921
|
+
if (aliasMap.size === 0 && hasNextJsDependency) {
|
|
3922
|
+
const tsconfigDir = (0, node_path.dirname)(tsconfigFile);
|
|
3923
|
+
if (cachedExistsSync((0, node_path.resolve)(tsconfigDir, "src"))) aliasMap.set("@/*", [(0, node_path.resolve)(tsconfigDir, "src/*")]);
|
|
3924
|
+
else aliasMap.set("@/*", [(0, node_path.resolve)(tsconfigDir, "*")]);
|
|
3925
|
+
}
|
|
3871
3926
|
tsconfigPathAliasCache.set(tsconfigFile, aliasMap);
|
|
3872
3927
|
return aliasMap;
|
|
3873
3928
|
};
|
|
@@ -4694,7 +4749,7 @@ const extractPackageName = (specifier) => {
|
|
|
4694
4749
|
};
|
|
4695
4750
|
|
|
4696
4751
|
//#endregion
|
|
4697
|
-
//#region src/
|
|
4752
|
+
//#region src/utils/find-monorepo-root.ts
|
|
4698
4753
|
const MONOREPO_ROOT_MARKERS = [
|
|
4699
4754
|
"pnpm-workspace.yaml",
|
|
4700
4755
|
"pnpm-workspace.yml",
|
|
@@ -4740,6 +4795,9 @@ const findMonorepoRoot = (rootDir) => {
|
|
|
4740
4795
|
for (const lockfile of LOCKFILE_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, lockfile))) return currentDirectory;
|
|
4741
4796
|
}
|
|
4742
4797
|
};
|
|
4798
|
+
|
|
4799
|
+
//#endregion
|
|
4800
|
+
//#region src/report/packages.ts
|
|
4743
4801
|
const discoverAllPackageJsonPaths = (rootDir) => {
|
|
4744
4802
|
const paths = [(0, node_path.join)(rootDir, "package.json")];
|
|
4745
4803
|
const workspacePackageJsons = fast_glob.default.sync("**/package.json", {
|
|
@@ -4800,6 +4858,30 @@ const detectStalePackages = (graph, config) => {
|
|
|
4800
4858
|
if (declaredNames.has("react-native")) usedPackageNames.add("react-native");
|
|
4801
4859
|
if (declaredNames.has("react-native-web")) usedPackageNames.add("react-native-web");
|
|
4802
4860
|
}
|
|
4861
|
+
if (declaredNames.has("react-dom")) {
|
|
4862
|
+
if ([
|
|
4863
|
+
"next",
|
|
4864
|
+
"gatsby",
|
|
4865
|
+
"@remix-run/react",
|
|
4866
|
+
"react-router-dom",
|
|
4867
|
+
"vite",
|
|
4868
|
+
"@docusaurus/core",
|
|
4869
|
+
"react-scripts",
|
|
4870
|
+
"astro",
|
|
4871
|
+
"@tanstack/react-router",
|
|
4872
|
+
"@tanstack/react-start",
|
|
4873
|
+
"react-app-rewired"
|
|
4874
|
+
].some((framework) => declaredNames.has(framework) || usedPackageNames.has(framework))) usedPackageNames.add("react-dom");
|
|
4875
|
+
}
|
|
4876
|
+
if (declaredNames.has("react") && declaredNames.has("react-dom")) {
|
|
4877
|
+
const packageJsonPath = (0, node_path.resolve)(config.rootDir, "package.json");
|
|
4878
|
+
try {
|
|
4879
|
+
const content = (0, node_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
4880
|
+
const peerDeps = JSON.parse(content).peerDependencies ?? {};
|
|
4881
|
+
if ("react" in peerDeps && declaredDependencies.get("react") === true) usedPackageNames.add("react");
|
|
4882
|
+
if ("react-dom" in peerDeps && declaredDependencies.get("react-dom") === true) usedPackageNames.add("react-dom");
|
|
4883
|
+
} catch {}
|
|
4884
|
+
}
|
|
4803
4885
|
const peerSatisfied = collectPeerSatisfiedPackages(nodeModulesRoot, declaredNames, usedPackageNames);
|
|
4804
4886
|
for (const packageName of peerSatisfied) usedPackageNames.add(packageName);
|
|
4805
4887
|
const candidateUnused = /* @__PURE__ */ new Set();
|
|
@@ -5392,7 +5474,13 @@ const defineConfig = (options) => ({
|
|
|
5392
5474
|
const analyze = async (config) => {
|
|
5393
5475
|
const pipelineStartTime = performance.now();
|
|
5394
5476
|
const workspaceDiscovery = resolveWorkspaces((0, node_path.resolve)(config.rootDir));
|
|
5395
|
-
const workspacePackages = workspaceDiscovery.packages;
|
|
5477
|
+
const workspacePackages = [...workspaceDiscovery.packages];
|
|
5478
|
+
const monorepoRoot = findMonorepoRoot(config.rootDir);
|
|
5479
|
+
if (monorepoRoot) {
|
|
5480
|
+
const monorepoWorkspaces = resolveWorkspaces(monorepoRoot);
|
|
5481
|
+
const existingDirectories = new Set(workspacePackages.map((workspacePackage) => workspacePackage.directory));
|
|
5482
|
+
for (const monorepoPackage of monorepoWorkspaces.packages) if (!existingDirectories.has(monorepoPackage.directory)) workspacePackages.push(monorepoPackage);
|
|
5483
|
+
}
|
|
5396
5484
|
const frameworkIgnorePatterns = getFrameworkExclusions(config.rootDir);
|
|
5397
5485
|
const absoluteRoot = (0, node_path.resolve)(config.rootDir);
|
|
5398
5486
|
const outputDirectoryExclusions = OUTPUT_DIRECTORIES.flatMap((outputDirectory) => {
|
|
@@ -5418,7 +5506,10 @@ const analyze = async (config) => {
|
|
|
5418
5506
|
const moduleResolver = createResolver(config, workspacePackages.map((workspacePackage) => ({
|
|
5419
5507
|
name: workspacePackage.name,
|
|
5420
5508
|
directory: workspacePackage.directory
|
|
5421
|
-
})), {
|
|
5509
|
+
})), {
|
|
5510
|
+
hasReactNative,
|
|
5511
|
+
monorepoRoot
|
|
5512
|
+
});
|
|
5422
5513
|
const graphInputs = [];
|
|
5423
5514
|
for (const file of files) {
|
|
5424
5515
|
const parsedModule = parseSourceFile(file.path);
|
package/dist/index.mjs
CHANGED
|
@@ -3689,12 +3689,13 @@ const TSCONFIG_FILENAMES = [
|
|
|
3689
3689
|
"tsconfig.json",
|
|
3690
3690
|
"tsconfig.web.json",
|
|
3691
3691
|
"tsconfig.app.json",
|
|
3692
|
-
"tsconfig.base.json"
|
|
3692
|
+
"tsconfig.base.json",
|
|
3693
|
+
"jsconfig.json"
|
|
3693
3694
|
];
|
|
3694
|
-
const findNearestTsconfig = (fromDir, rootDir) => {
|
|
3695
|
+
const findNearestTsconfig = (fromDir, rootDir, monorepoRootDir) => {
|
|
3695
3696
|
let currentDirectory = fromDir;
|
|
3696
|
-
const
|
|
3697
|
-
while (currentDirectory.length >=
|
|
3697
|
+
const stopAt = monorepoRootDir ? resolve(monorepoRootDir) : resolve(rootDir);
|
|
3698
|
+
while (currentDirectory.length >= stopAt.length) {
|
|
3698
3699
|
for (const tsconfigFilename of TSCONFIG_FILENAMES) {
|
|
3699
3700
|
const tsconfigCandidate = join(currentDirectory, tsconfigFilename);
|
|
3700
3701
|
if (cachedExistsSync(tsconfigCandidate)) return tsconfigCandidate;
|
|
@@ -3771,16 +3772,17 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3771
3772
|
for (const workspacePackage of workspacePackages) workspaceNameToDirectory.set(workspacePackage.name, workspacePackage.directory);
|
|
3772
3773
|
let rootTsconfigPath;
|
|
3773
3774
|
if (config.tsConfigPath) rootTsconfigPath = resolve(config.rootDir, config.tsConfigPath);
|
|
3774
|
-
else
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3775
|
+
else {
|
|
3776
|
+
const tsconfigSearchDirs = options.monorepoRoot ? [config.rootDir, options.monorepoRoot] : [config.rootDir];
|
|
3777
|
+
for (const searchDir of tsconfigSearchDirs) {
|
|
3778
|
+
for (const candidate of TSCONFIG_FILENAMES) {
|
|
3779
|
+
const candidatePath = resolve(searchDir, candidate);
|
|
3780
|
+
if (cachedExistsSync(candidatePath)) {
|
|
3781
|
+
rootTsconfigPath = candidatePath;
|
|
3782
|
+
break;
|
|
3783
|
+
}
|
|
3784
|
+
}
|
|
3785
|
+
if (rootTsconfigPath) break;
|
|
3784
3786
|
}
|
|
3785
3787
|
}
|
|
3786
3788
|
const tsconfigPathCache = /* @__PURE__ */ new Map();
|
|
@@ -3789,24 +3791,56 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3789
3791
|
const fileDir = dirname(filePath);
|
|
3790
3792
|
const cached = tsconfigPathCache.get(fileDir);
|
|
3791
3793
|
if (cached !== void 0) return cached;
|
|
3792
|
-
const tsconfigResult = findNearestTsconfig(fileDir, config.rootDir) ?? rootTsconfigPath;
|
|
3794
|
+
const tsconfigResult = findNearestTsconfig(fileDir, config.rootDir, options.monorepoRoot) ?? rootTsconfigPath;
|
|
3793
3795
|
tsconfigPathCache.set(fileDir, tsconfigResult);
|
|
3794
3796
|
return tsconfigResult;
|
|
3795
3797
|
};
|
|
3796
3798
|
const tsconfigBaseUrlCache = /* @__PURE__ */ new Map();
|
|
3797
|
-
const
|
|
3798
|
-
|
|
3799
|
-
|
|
3799
|
+
const resolveExtendsPath = (extendsValue, fromDir) => {
|
|
3800
|
+
if (extendsValue.startsWith(".")) {
|
|
3801
|
+
const absolutePath = resolve(fromDir, extendsValue);
|
|
3802
|
+
if (cachedExistsSync(absolutePath)) return absolutePath;
|
|
3803
|
+
if (cachedExistsSync(absolutePath + ".json")) return absolutePath + ".json";
|
|
3804
|
+
return;
|
|
3805
|
+
}
|
|
3806
|
+
const packagePath = join(options.monorepoRoot ?? config.rootDir, "node_modules", extendsValue);
|
|
3807
|
+
if (cachedExistsSync(packagePath)) return packagePath;
|
|
3808
|
+
if (cachedExistsSync(packagePath + ".json")) return packagePath + ".json";
|
|
3809
|
+
const localPackagePath = join(fromDir, "node_modules", extendsValue);
|
|
3810
|
+
if (cachedExistsSync(localPackagePath)) return localPackagePath;
|
|
3811
|
+
if (cachedExistsSync(localPackagePath + ".json")) return localPackagePath + ".json";
|
|
3812
|
+
};
|
|
3813
|
+
const collectExtendsEntries = (tsconfigJson) => {
|
|
3814
|
+
if (typeof tsconfigJson.extends === "string") return [tsconfigJson.extends];
|
|
3815
|
+
if (Array.isArray(tsconfigJson.extends)) return tsconfigJson.extends.filter((entry) => typeof entry === "string");
|
|
3816
|
+
return [];
|
|
3817
|
+
};
|
|
3818
|
+
const extractBaseUrlFromTsconfig = (tsconfigFile, visitedFiles) => {
|
|
3819
|
+
if (visitedFiles.has(tsconfigFile)) return void 0;
|
|
3820
|
+
visitedFiles.add(tsconfigFile);
|
|
3800
3821
|
try {
|
|
3801
3822
|
const cleanedContent = stripJsonComments(cachedReadFileSync(tsconfigFile));
|
|
3802
|
-
const
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3823
|
+
const tsconfigJson = JSON.parse(cleanedContent);
|
|
3824
|
+
const tsconfigDir = dirname(tsconfigFile);
|
|
3825
|
+
const baseUrl = tsconfigJson.compilerOptions?.baseUrl;
|
|
3826
|
+
if (baseUrl) return resolve(tsconfigDir, baseUrl);
|
|
3827
|
+
for (const extendsEntry of collectExtendsEntries(tsconfigJson)) {
|
|
3828
|
+
const resolvedPath = resolveExtendsPath(extendsEntry, tsconfigDir);
|
|
3829
|
+
if (resolvedPath) {
|
|
3830
|
+
const result = extractBaseUrlFromTsconfig(resolvedPath, visitedFiles);
|
|
3831
|
+
if (result) return result;
|
|
3832
|
+
}
|
|
3807
3833
|
}
|
|
3808
|
-
} catch {
|
|
3809
|
-
|
|
3834
|
+
} catch {
|
|
3835
|
+
return;
|
|
3836
|
+
}
|
|
3837
|
+
};
|
|
3838
|
+
const getBaseUrlDirectory = (tsconfigFile) => {
|
|
3839
|
+
const cached = tsconfigBaseUrlCache.get(tsconfigFile);
|
|
3840
|
+
if (cached !== void 0) return cached;
|
|
3841
|
+
const result = extractBaseUrlFromTsconfig(tsconfigFile, /* @__PURE__ */ new Set());
|
|
3842
|
+
tsconfigBaseUrlCache.set(tsconfigFile, result);
|
|
3843
|
+
return result;
|
|
3810
3844
|
};
|
|
3811
3845
|
const hasNextJsDependency = (() => {
|
|
3812
3846
|
try {
|
|
@@ -3819,25 +3853,46 @@ const createResolver = (config, workspacePackages = [], options = {}) => {
|
|
|
3819
3853
|
return false;
|
|
3820
3854
|
}
|
|
3821
3855
|
})();
|
|
3822
|
-
const
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
const aliasMap = /* @__PURE__ */ new Map();
|
|
3826
|
-
const tsconfigDir = dirname(tsconfigFile);
|
|
3856
|
+
const extractPathsFromTsconfig = (tsconfigFile, visitedFiles) => {
|
|
3857
|
+
if (visitedFiles.has(tsconfigFile)) return void 0;
|
|
3858
|
+
visitedFiles.add(tsconfigFile);
|
|
3827
3859
|
try {
|
|
3828
3860
|
const tsconfigContent = cachedReadFileSync(tsconfigFile).trim();
|
|
3829
|
-
if (tsconfigContent.length
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3861
|
+
if (tsconfigContent.length === 0) return void 0;
|
|
3862
|
+
const cleanedContent = stripJsonComments(tsconfigContent);
|
|
3863
|
+
const tsconfigJson = JSON.parse(cleanedContent);
|
|
3864
|
+
const tsconfigDir = dirname(tsconfigFile);
|
|
3865
|
+
const paths = tsconfigJson.compilerOptions?.paths;
|
|
3866
|
+
const baseUrl = tsconfigJson.compilerOptions?.baseUrl;
|
|
3867
|
+
if (paths && typeof paths === "object") return {
|
|
3868
|
+
paths,
|
|
3869
|
+
baseUrl: baseUrl ?? ".",
|
|
3870
|
+
tsconfigDir
|
|
3871
|
+
};
|
|
3872
|
+
for (const extendsEntry of collectExtendsEntries(tsconfigJson)) {
|
|
3873
|
+
const resolvedPath = resolveExtendsPath(extendsEntry, tsconfigDir);
|
|
3874
|
+
if (resolvedPath) {
|
|
3875
|
+
const result = extractPathsFromTsconfig(resolvedPath, visitedFiles);
|
|
3876
|
+
if (result) return result;
|
|
3836
3877
|
}
|
|
3837
3878
|
}
|
|
3838
|
-
} catch {
|
|
3839
|
-
|
|
3840
|
-
|
|
3879
|
+
} catch {
|
|
3880
|
+
return;
|
|
3881
|
+
}
|
|
3882
|
+
};
|
|
3883
|
+
const getPathAliases = (tsconfigFile) => {
|
|
3884
|
+
const cached = tsconfigPathAliasCache.get(tsconfigFile);
|
|
3885
|
+
if (cached) return cached;
|
|
3886
|
+
const aliasMap = /* @__PURE__ */ new Map();
|
|
3887
|
+
const extracted = extractPathsFromTsconfig(tsconfigFile, /* @__PURE__ */ new Set());
|
|
3888
|
+
if (extracted) {
|
|
3889
|
+
for (const [pattern, targets] of Object.entries(extracted.paths)) if (Array.isArray(targets)) aliasMap.set(pattern, targets.map((target) => resolve(extracted.tsconfigDir, extracted.baseUrl, target)));
|
|
3890
|
+
}
|
|
3891
|
+
if (aliasMap.size === 0 && hasNextJsDependency) {
|
|
3892
|
+
const tsconfigDir = dirname(tsconfigFile);
|
|
3893
|
+
if (cachedExistsSync(resolve(tsconfigDir, "src"))) aliasMap.set("@/*", [resolve(tsconfigDir, "src/*")]);
|
|
3894
|
+
else aliasMap.set("@/*", [resolve(tsconfigDir, "*")]);
|
|
3895
|
+
}
|
|
3841
3896
|
tsconfigPathAliasCache.set(tsconfigFile, aliasMap);
|
|
3842
3897
|
return aliasMap;
|
|
3843
3898
|
};
|
|
@@ -4664,7 +4719,7 @@ const extractPackageName = (specifier) => {
|
|
|
4664
4719
|
};
|
|
4665
4720
|
|
|
4666
4721
|
//#endregion
|
|
4667
|
-
//#region src/
|
|
4722
|
+
//#region src/utils/find-monorepo-root.ts
|
|
4668
4723
|
const MONOREPO_ROOT_MARKERS = [
|
|
4669
4724
|
"pnpm-workspace.yaml",
|
|
4670
4725
|
"pnpm-workspace.yml",
|
|
@@ -4710,6 +4765,9 @@ const findMonorepoRoot = (rootDir) => {
|
|
|
4710
4765
|
for (const lockfile of LOCKFILE_MARKERS) if (existsSync(join(currentDirectory, lockfile))) return currentDirectory;
|
|
4711
4766
|
}
|
|
4712
4767
|
};
|
|
4768
|
+
|
|
4769
|
+
//#endregion
|
|
4770
|
+
//#region src/report/packages.ts
|
|
4713
4771
|
const discoverAllPackageJsonPaths = (rootDir) => {
|
|
4714
4772
|
const paths = [join(rootDir, "package.json")];
|
|
4715
4773
|
const workspacePackageJsons = fg.sync("**/package.json", {
|
|
@@ -4770,6 +4828,30 @@ const detectStalePackages = (graph, config) => {
|
|
|
4770
4828
|
if (declaredNames.has("react-native")) usedPackageNames.add("react-native");
|
|
4771
4829
|
if (declaredNames.has("react-native-web")) usedPackageNames.add("react-native-web");
|
|
4772
4830
|
}
|
|
4831
|
+
if (declaredNames.has("react-dom")) {
|
|
4832
|
+
if ([
|
|
4833
|
+
"next",
|
|
4834
|
+
"gatsby",
|
|
4835
|
+
"@remix-run/react",
|
|
4836
|
+
"react-router-dom",
|
|
4837
|
+
"vite",
|
|
4838
|
+
"@docusaurus/core",
|
|
4839
|
+
"react-scripts",
|
|
4840
|
+
"astro",
|
|
4841
|
+
"@tanstack/react-router",
|
|
4842
|
+
"@tanstack/react-start",
|
|
4843
|
+
"react-app-rewired"
|
|
4844
|
+
].some((framework) => declaredNames.has(framework) || usedPackageNames.has(framework))) usedPackageNames.add("react-dom");
|
|
4845
|
+
}
|
|
4846
|
+
if (declaredNames.has("react") && declaredNames.has("react-dom")) {
|
|
4847
|
+
const packageJsonPath = resolve(config.rootDir, "package.json");
|
|
4848
|
+
try {
|
|
4849
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
4850
|
+
const peerDeps = JSON.parse(content).peerDependencies ?? {};
|
|
4851
|
+
if ("react" in peerDeps && declaredDependencies.get("react") === true) usedPackageNames.add("react");
|
|
4852
|
+
if ("react-dom" in peerDeps && declaredDependencies.get("react-dom") === true) usedPackageNames.add("react-dom");
|
|
4853
|
+
} catch {}
|
|
4854
|
+
}
|
|
4773
4855
|
const peerSatisfied = collectPeerSatisfiedPackages(nodeModulesRoot, declaredNames, usedPackageNames);
|
|
4774
4856
|
for (const packageName of peerSatisfied) usedPackageNames.add(packageName);
|
|
4775
4857
|
const candidateUnused = /* @__PURE__ */ new Set();
|
|
@@ -5362,7 +5444,13 @@ const defineConfig = (options) => ({
|
|
|
5362
5444
|
const analyze = async (config) => {
|
|
5363
5445
|
const pipelineStartTime = performance.now();
|
|
5364
5446
|
const workspaceDiscovery = resolveWorkspaces(resolve(config.rootDir));
|
|
5365
|
-
const workspacePackages = workspaceDiscovery.packages;
|
|
5447
|
+
const workspacePackages = [...workspaceDiscovery.packages];
|
|
5448
|
+
const monorepoRoot = findMonorepoRoot(config.rootDir);
|
|
5449
|
+
if (monorepoRoot) {
|
|
5450
|
+
const monorepoWorkspaces = resolveWorkspaces(monorepoRoot);
|
|
5451
|
+
const existingDirectories = new Set(workspacePackages.map((workspacePackage) => workspacePackage.directory));
|
|
5452
|
+
for (const monorepoPackage of monorepoWorkspaces.packages) if (!existingDirectories.has(monorepoPackage.directory)) workspacePackages.push(monorepoPackage);
|
|
5453
|
+
}
|
|
5366
5454
|
const frameworkIgnorePatterns = getFrameworkExclusions(config.rootDir);
|
|
5367
5455
|
const absoluteRoot = resolve(config.rootDir);
|
|
5368
5456
|
const outputDirectoryExclusions = OUTPUT_DIRECTORIES.flatMap((outputDirectory) => {
|
|
@@ -5388,7 +5476,10 @@ const analyze = async (config) => {
|
|
|
5388
5476
|
const moduleResolver = createResolver(config, workspacePackages.map((workspacePackage) => ({
|
|
5389
5477
|
name: workspacePackage.name,
|
|
5390
5478
|
directory: workspacePackage.directory
|
|
5391
|
-
})), {
|
|
5479
|
+
})), {
|
|
5480
|
+
hasReactNative,
|
|
5481
|
+
monorepoRoot
|
|
5482
|
+
});
|
|
5392
5483
|
const graphInputs = [];
|
|
5393
5484
|
for (const file of files) {
|
|
5394
5485
|
const parsedModule = parseSourceFile(file.path);
|