deslop-js 0.0.5 → 0.0.6
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 +85 -7
- package/dist/index.mjs +85 -7
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -193,7 +193,10 @@ const IMPLICIT_DEPENDENCIES = new Set([
|
|
|
193
193
|
"dotenv-cli",
|
|
194
194
|
"webpack",
|
|
195
195
|
"rollup",
|
|
196
|
-
"terser"
|
|
196
|
+
"terser",
|
|
197
|
+
"autoprefixer",
|
|
198
|
+
"tailwindcss",
|
|
199
|
+
"react-test-renderer"
|
|
197
200
|
]);
|
|
198
201
|
const BUILTIN_MODULES = new Set([
|
|
199
202
|
"assert",
|
|
@@ -4498,13 +4501,21 @@ const buildSourceTargetMap = (graph) => {
|
|
|
4498
4501
|
const EXCLUDED_EXTENSIONS = new Set([
|
|
4499
4502
|
".html",
|
|
4500
4503
|
".mdx",
|
|
4501
|
-
".md"
|
|
4504
|
+
".md",
|
|
4505
|
+
".css",
|
|
4506
|
+
".scss",
|
|
4507
|
+
".less",
|
|
4508
|
+
".sass",
|
|
4509
|
+
".graphql",
|
|
4510
|
+
".gql"
|
|
4502
4511
|
]);
|
|
4512
|
+
const TEST_FILE_PATTERN = /(?:\.(?:test|spec|stories|story)\.|(?:^|\/)__tests__\/)/;
|
|
4503
4513
|
const hasExcludedExtension = (filePath) => {
|
|
4504
4514
|
const lastDot = filePath.lastIndexOf(".");
|
|
4505
4515
|
if (lastDot === -1) return false;
|
|
4506
4516
|
return EXCLUDED_EXTENSIONS.has(filePath.slice(lastDot));
|
|
4507
4517
|
};
|
|
4518
|
+
const isTestFile = (filePath) => TEST_FILE_PATTERN.test(filePath);
|
|
4508
4519
|
const detectOrphanFiles = (graph) => {
|
|
4509
4520
|
const unusedFiles = [];
|
|
4510
4521
|
for (const module of graph.modules) {
|
|
@@ -4513,6 +4524,7 @@ const detectOrphanFiles = (graph) => {
|
|
|
4513
4524
|
if (module.isDeclarationFile) continue;
|
|
4514
4525
|
if (module.isConfigFile) continue;
|
|
4515
4526
|
if (hasExcludedExtension(module.fileId.path)) continue;
|
|
4527
|
+
if (isTestFile(module.fileId.path)) continue;
|
|
4516
4528
|
if (isBarrelWithReachableSources(module, graph)) continue;
|
|
4517
4529
|
if (hasReachableDirectImporter(module.fileId.index, graph)) continue;
|
|
4518
4530
|
unusedFiles.push({ path: module.fileId.path });
|
|
@@ -4692,12 +4704,25 @@ const LOCKFILE_MARKERS = [
|
|
|
4692
4704
|
"bun.lockb",
|
|
4693
4705
|
"bun.lock"
|
|
4694
4706
|
];
|
|
4707
|
+
const MAX_MONOREPO_WALK_DEPTH = 5;
|
|
4695
4708
|
const findMonorepoRoot = (rootDir) => {
|
|
4696
4709
|
let currentDirectory = (0, node_path.resolve)(rootDir);
|
|
4697
|
-
|
|
4710
|
+
let walkedDepth = 0;
|
|
4711
|
+
while (walkedDepth < MAX_MONOREPO_WALK_DEPTH) {
|
|
4698
4712
|
const parentDirectory = (0, node_path.dirname)(currentDirectory);
|
|
4699
4713
|
if (parentDirectory === currentDirectory) break;
|
|
4700
4714
|
currentDirectory = parentDirectory;
|
|
4715
|
+
walkedDepth++;
|
|
4716
|
+
if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, ".git"))) {
|
|
4717
|
+
for (const marker of MONOREPO_ROOT_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, marker))) return currentDirectory;
|
|
4718
|
+
const packageJsonPath = (0, node_path.join)(currentDirectory, "package.json");
|
|
4719
|
+
if ((0, node_fs.existsSync)(packageJsonPath)) try {
|
|
4720
|
+
const content = (0, node_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
4721
|
+
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
4722
|
+
} catch {}
|
|
4723
|
+
for (const lockfile of LOCKFILE_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, lockfile))) return currentDirectory;
|
|
4724
|
+
return;
|
|
4725
|
+
}
|
|
4701
4726
|
for (const marker of MONOREPO_ROOT_MARKERS) if ((0, node_fs.existsSync)((0, node_path.join)(currentDirectory, marker))) return currentDirectory;
|
|
4702
4727
|
const packageJsonPath = (0, node_path.join)(currentDirectory, "package.json");
|
|
4703
4728
|
if ((0, node_fs.existsSync)(packageJsonPath)) try {
|
|
@@ -4771,10 +4796,23 @@ const detectStalePackages = (graph, config) => {
|
|
|
4771
4796
|
}
|
|
4772
4797
|
const peerSatisfied = collectPeerSatisfiedPackages(nodeModulesRoot, declaredNames, usedPackageNames);
|
|
4773
4798
|
for (const packageName of peerSatisfied) usedPackageNames.add(packageName);
|
|
4774
|
-
const
|
|
4775
|
-
for (const [dependencyName
|
|
4799
|
+
const candidateUnused = /* @__PURE__ */ new Set();
|
|
4800
|
+
for (const [dependencyName] of declaredDependencies) {
|
|
4776
4801
|
if (isAlwaysConsideredUsed(dependencyName)) continue;
|
|
4777
|
-
if (
|
|
4802
|
+
if (usedPackageNames.has(dependencyName)) continue;
|
|
4803
|
+
candidateUnused.add(dependencyName);
|
|
4804
|
+
}
|
|
4805
|
+
if (candidateUnused.size > 0) {
|
|
4806
|
+
const sourceFileRescued = scanSourceFilesForPackageImports(config.rootDir, candidateUnused);
|
|
4807
|
+
for (const packageName of sourceFileRescued) {
|
|
4808
|
+
usedPackageNames.add(packageName);
|
|
4809
|
+
candidateUnused.delete(packageName);
|
|
4810
|
+
}
|
|
4811
|
+
}
|
|
4812
|
+
const unusedDependencies = [];
|
|
4813
|
+
for (const dependencyName of candidateUnused) {
|
|
4814
|
+
const isDevDependency = declaredDependencies.get(dependencyName) ?? false;
|
|
4815
|
+
unusedDependencies.push({
|
|
4778
4816
|
name: dependencyName,
|
|
4779
4817
|
isDevDependency
|
|
4780
4818
|
});
|
|
@@ -5037,6 +5075,41 @@ const extractExtendsPackageName = (extendsValue) => {
|
|
|
5037
5075
|
}
|
|
5038
5076
|
return extendsValue.split("/")[0];
|
|
5039
5077
|
};
|
|
5078
|
+
const SOURCE_FILE_GLOBS = ["**/*.{ts,tsx,js,jsx,mts,mjs,cts,cjs}"];
|
|
5079
|
+
const SOURCE_FILE_IGNORES = [
|
|
5080
|
+
"**/node_modules/**",
|
|
5081
|
+
"**/dist/**",
|
|
5082
|
+
"**/build/**",
|
|
5083
|
+
"**/out/**",
|
|
5084
|
+
"**/.git/**",
|
|
5085
|
+
"**/coverage/**",
|
|
5086
|
+
"**/*.min.js",
|
|
5087
|
+
"**/*.d.ts"
|
|
5088
|
+
];
|
|
5089
|
+
const scanSourceFilesForPackageImports = (rootDir, candidatePackages) => {
|
|
5090
|
+
const found = /* @__PURE__ */ new Set();
|
|
5091
|
+
if (candidatePackages.size === 0) return found;
|
|
5092
|
+
const sourceFiles = fast_glob.default.sync(SOURCE_FILE_GLOBS, {
|
|
5093
|
+
cwd: rootDir,
|
|
5094
|
+
absolute: true,
|
|
5095
|
+
onlyFiles: true,
|
|
5096
|
+
ignore: SOURCE_FILE_IGNORES,
|
|
5097
|
+
deep: 15
|
|
5098
|
+
});
|
|
5099
|
+
for (const filePath of sourceFiles) {
|
|
5100
|
+
if (candidatePackages.size === 0) break;
|
|
5101
|
+
try {
|
|
5102
|
+
const content = (0, node_fs.readFileSync)(filePath, "utf-8");
|
|
5103
|
+
for (const packageName of candidatePackages) if (content.includes(`'${packageName}'`) || content.includes(`"${packageName}"`) || content.includes(`'${packageName}/`) || content.includes(`"${packageName}/`)) {
|
|
5104
|
+
found.add(packageName);
|
|
5105
|
+
candidatePackages.delete(packageName);
|
|
5106
|
+
}
|
|
5107
|
+
} catch {
|
|
5108
|
+
continue;
|
|
5109
|
+
}
|
|
5110
|
+
}
|
|
5111
|
+
return found;
|
|
5112
|
+
};
|
|
5040
5113
|
const ALWAYS_USED_PREFIXES = [
|
|
5041
5114
|
"@types/",
|
|
5042
5115
|
"eslint-config-",
|
|
@@ -5080,15 +5153,20 @@ const ALWAYS_USED_PREFIXES = [
|
|
|
5080
5153
|
"@lingui/",
|
|
5081
5154
|
"@emotion/",
|
|
5082
5155
|
"tslint-config-",
|
|
5156
|
+
"eslint-import-resolver-",
|
|
5083
5157
|
"@changesets/",
|
|
5158
|
+
"@react-navigation/",
|
|
5084
5159
|
"@vercel/",
|
|
5085
5160
|
"@expo/",
|
|
5086
5161
|
"expo-",
|
|
5087
5162
|
"react-native-"
|
|
5088
5163
|
];
|
|
5164
|
+
const ALWAYS_USED_SUFFIXES = ["-loader"];
|
|
5089
5165
|
const isAlwaysConsideredUsed = (dependencyName) => {
|
|
5090
5166
|
if (IMPLICIT_DEPENDENCIES.has(dependencyName)) return true;
|
|
5091
|
-
|
|
5167
|
+
if (ALWAYS_USED_PREFIXES.some((prefix) => dependencyName.startsWith(prefix))) return true;
|
|
5168
|
+
if (ALWAYS_USED_SUFFIXES.some((suffix) => dependencyName.endsWith(suffix))) return true;
|
|
5169
|
+
return false;
|
|
5092
5170
|
};
|
|
5093
5171
|
|
|
5094
5172
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -163,7 +163,10 @@ const IMPLICIT_DEPENDENCIES = new Set([
|
|
|
163
163
|
"dotenv-cli",
|
|
164
164
|
"webpack",
|
|
165
165
|
"rollup",
|
|
166
|
-
"terser"
|
|
166
|
+
"terser",
|
|
167
|
+
"autoprefixer",
|
|
168
|
+
"tailwindcss",
|
|
169
|
+
"react-test-renderer"
|
|
167
170
|
]);
|
|
168
171
|
const BUILTIN_MODULES = new Set([
|
|
169
172
|
"assert",
|
|
@@ -4468,13 +4471,21 @@ const buildSourceTargetMap = (graph) => {
|
|
|
4468
4471
|
const EXCLUDED_EXTENSIONS = new Set([
|
|
4469
4472
|
".html",
|
|
4470
4473
|
".mdx",
|
|
4471
|
-
".md"
|
|
4474
|
+
".md",
|
|
4475
|
+
".css",
|
|
4476
|
+
".scss",
|
|
4477
|
+
".less",
|
|
4478
|
+
".sass",
|
|
4479
|
+
".graphql",
|
|
4480
|
+
".gql"
|
|
4472
4481
|
]);
|
|
4482
|
+
const TEST_FILE_PATTERN = /(?:\.(?:test|spec|stories|story)\.|(?:^|\/)__tests__\/)/;
|
|
4473
4483
|
const hasExcludedExtension = (filePath) => {
|
|
4474
4484
|
const lastDot = filePath.lastIndexOf(".");
|
|
4475
4485
|
if (lastDot === -1) return false;
|
|
4476
4486
|
return EXCLUDED_EXTENSIONS.has(filePath.slice(lastDot));
|
|
4477
4487
|
};
|
|
4488
|
+
const isTestFile = (filePath) => TEST_FILE_PATTERN.test(filePath);
|
|
4478
4489
|
const detectOrphanFiles = (graph) => {
|
|
4479
4490
|
const unusedFiles = [];
|
|
4480
4491
|
for (const module of graph.modules) {
|
|
@@ -4483,6 +4494,7 @@ const detectOrphanFiles = (graph) => {
|
|
|
4483
4494
|
if (module.isDeclarationFile) continue;
|
|
4484
4495
|
if (module.isConfigFile) continue;
|
|
4485
4496
|
if (hasExcludedExtension(module.fileId.path)) continue;
|
|
4497
|
+
if (isTestFile(module.fileId.path)) continue;
|
|
4486
4498
|
if (isBarrelWithReachableSources(module, graph)) continue;
|
|
4487
4499
|
if (hasReachableDirectImporter(module.fileId.index, graph)) continue;
|
|
4488
4500
|
unusedFiles.push({ path: module.fileId.path });
|
|
@@ -4662,12 +4674,25 @@ const LOCKFILE_MARKERS = [
|
|
|
4662
4674
|
"bun.lockb",
|
|
4663
4675
|
"bun.lock"
|
|
4664
4676
|
];
|
|
4677
|
+
const MAX_MONOREPO_WALK_DEPTH = 5;
|
|
4665
4678
|
const findMonorepoRoot = (rootDir) => {
|
|
4666
4679
|
let currentDirectory = resolve(rootDir);
|
|
4667
|
-
|
|
4680
|
+
let walkedDepth = 0;
|
|
4681
|
+
while (walkedDepth < MAX_MONOREPO_WALK_DEPTH) {
|
|
4668
4682
|
const parentDirectory = dirname(currentDirectory);
|
|
4669
4683
|
if (parentDirectory === currentDirectory) break;
|
|
4670
4684
|
currentDirectory = parentDirectory;
|
|
4685
|
+
walkedDepth++;
|
|
4686
|
+
if (existsSync(join(currentDirectory, ".git"))) {
|
|
4687
|
+
for (const marker of MONOREPO_ROOT_MARKERS) if (existsSync(join(currentDirectory, marker))) return currentDirectory;
|
|
4688
|
+
const packageJsonPath = join(currentDirectory, "package.json");
|
|
4689
|
+
if (existsSync(packageJsonPath)) try {
|
|
4690
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
4691
|
+
if (JSON.parse(content).workspaces) return currentDirectory;
|
|
4692
|
+
} catch {}
|
|
4693
|
+
for (const lockfile of LOCKFILE_MARKERS) if (existsSync(join(currentDirectory, lockfile))) return currentDirectory;
|
|
4694
|
+
return;
|
|
4695
|
+
}
|
|
4671
4696
|
for (const marker of MONOREPO_ROOT_MARKERS) if (existsSync(join(currentDirectory, marker))) return currentDirectory;
|
|
4672
4697
|
const packageJsonPath = join(currentDirectory, "package.json");
|
|
4673
4698
|
if (existsSync(packageJsonPath)) try {
|
|
@@ -4741,10 +4766,23 @@ const detectStalePackages = (graph, config) => {
|
|
|
4741
4766
|
}
|
|
4742
4767
|
const peerSatisfied = collectPeerSatisfiedPackages(nodeModulesRoot, declaredNames, usedPackageNames);
|
|
4743
4768
|
for (const packageName of peerSatisfied) usedPackageNames.add(packageName);
|
|
4744
|
-
const
|
|
4745
|
-
for (const [dependencyName
|
|
4769
|
+
const candidateUnused = /* @__PURE__ */ new Set();
|
|
4770
|
+
for (const [dependencyName] of declaredDependencies) {
|
|
4746
4771
|
if (isAlwaysConsideredUsed(dependencyName)) continue;
|
|
4747
|
-
if (
|
|
4772
|
+
if (usedPackageNames.has(dependencyName)) continue;
|
|
4773
|
+
candidateUnused.add(dependencyName);
|
|
4774
|
+
}
|
|
4775
|
+
if (candidateUnused.size > 0) {
|
|
4776
|
+
const sourceFileRescued = scanSourceFilesForPackageImports(config.rootDir, candidateUnused);
|
|
4777
|
+
for (const packageName of sourceFileRescued) {
|
|
4778
|
+
usedPackageNames.add(packageName);
|
|
4779
|
+
candidateUnused.delete(packageName);
|
|
4780
|
+
}
|
|
4781
|
+
}
|
|
4782
|
+
const unusedDependencies = [];
|
|
4783
|
+
for (const dependencyName of candidateUnused) {
|
|
4784
|
+
const isDevDependency = declaredDependencies.get(dependencyName) ?? false;
|
|
4785
|
+
unusedDependencies.push({
|
|
4748
4786
|
name: dependencyName,
|
|
4749
4787
|
isDevDependency
|
|
4750
4788
|
});
|
|
@@ -5007,6 +5045,41 @@ const extractExtendsPackageName = (extendsValue) => {
|
|
|
5007
5045
|
}
|
|
5008
5046
|
return extendsValue.split("/")[0];
|
|
5009
5047
|
};
|
|
5048
|
+
const SOURCE_FILE_GLOBS = ["**/*.{ts,tsx,js,jsx,mts,mjs,cts,cjs}"];
|
|
5049
|
+
const SOURCE_FILE_IGNORES = [
|
|
5050
|
+
"**/node_modules/**",
|
|
5051
|
+
"**/dist/**",
|
|
5052
|
+
"**/build/**",
|
|
5053
|
+
"**/out/**",
|
|
5054
|
+
"**/.git/**",
|
|
5055
|
+
"**/coverage/**",
|
|
5056
|
+
"**/*.min.js",
|
|
5057
|
+
"**/*.d.ts"
|
|
5058
|
+
];
|
|
5059
|
+
const scanSourceFilesForPackageImports = (rootDir, candidatePackages) => {
|
|
5060
|
+
const found = /* @__PURE__ */ new Set();
|
|
5061
|
+
if (candidatePackages.size === 0) return found;
|
|
5062
|
+
const sourceFiles = fg.sync(SOURCE_FILE_GLOBS, {
|
|
5063
|
+
cwd: rootDir,
|
|
5064
|
+
absolute: true,
|
|
5065
|
+
onlyFiles: true,
|
|
5066
|
+
ignore: SOURCE_FILE_IGNORES,
|
|
5067
|
+
deep: 15
|
|
5068
|
+
});
|
|
5069
|
+
for (const filePath of sourceFiles) {
|
|
5070
|
+
if (candidatePackages.size === 0) break;
|
|
5071
|
+
try {
|
|
5072
|
+
const content = readFileSync(filePath, "utf-8");
|
|
5073
|
+
for (const packageName of candidatePackages) if (content.includes(`'${packageName}'`) || content.includes(`"${packageName}"`) || content.includes(`'${packageName}/`) || content.includes(`"${packageName}/`)) {
|
|
5074
|
+
found.add(packageName);
|
|
5075
|
+
candidatePackages.delete(packageName);
|
|
5076
|
+
}
|
|
5077
|
+
} catch {
|
|
5078
|
+
continue;
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
return found;
|
|
5082
|
+
};
|
|
5010
5083
|
const ALWAYS_USED_PREFIXES = [
|
|
5011
5084
|
"@types/",
|
|
5012
5085
|
"eslint-config-",
|
|
@@ -5050,15 +5123,20 @@ const ALWAYS_USED_PREFIXES = [
|
|
|
5050
5123
|
"@lingui/",
|
|
5051
5124
|
"@emotion/",
|
|
5052
5125
|
"tslint-config-",
|
|
5126
|
+
"eslint-import-resolver-",
|
|
5053
5127
|
"@changesets/",
|
|
5128
|
+
"@react-navigation/",
|
|
5054
5129
|
"@vercel/",
|
|
5055
5130
|
"@expo/",
|
|
5056
5131
|
"expo-",
|
|
5057
5132
|
"react-native-"
|
|
5058
5133
|
];
|
|
5134
|
+
const ALWAYS_USED_SUFFIXES = ["-loader"];
|
|
5059
5135
|
const isAlwaysConsideredUsed = (dependencyName) => {
|
|
5060
5136
|
if (IMPLICIT_DEPENDENCIES.has(dependencyName)) return true;
|
|
5061
|
-
|
|
5137
|
+
if (ALWAYS_USED_PREFIXES.some((prefix) => dependencyName.startsWith(prefix))) return true;
|
|
5138
|
+
if (ALWAYS_USED_SUFFIXES.some((suffix) => dependencyName.endsWith(suffix))) return true;
|
|
5139
|
+
return false;
|
|
5062
5140
|
};
|
|
5063
5141
|
|
|
5064
5142
|
//#endregion
|