@xylabs/ts-scripts-yarn3 7.3.1 → 7.4.0
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/actions/cycle.mjs +1 -1
- package/dist/actions/cycle.mjs.map +1 -1
- package/dist/actions/deplint/checkPackage/checkPackage.mjs +278 -35
- package/dist/actions/deplint/checkPackage/checkPackage.mjs.map +1 -1
- package/dist/actions/deplint/checkPackage/getUnlistedDependencies.mjs +13 -6
- package/dist/actions/deplint/checkPackage/getUnlistedDependencies.mjs.map +1 -1
- package/dist/actions/deplint/checkPackage/getUnlistedDevDependencies.mjs +3 -1
- package/dist/actions/deplint/checkPackage/getUnlistedDevDependencies.mjs.map +1 -1
- package/dist/actions/deplint/checkPackage/getUnusedDevDependencies.mjs +175 -0
- package/dist/actions/deplint/checkPackage/getUnusedDevDependencies.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/index.mjs +278 -35
- package/dist/actions/deplint/checkPackage/index.mjs.map +1 -1
- package/dist/actions/deplint/deplint.mjs +281 -38
- package/dist/actions/deplint/deplint.mjs.map +1 -1
- package/dist/actions/deplint/findFiles.mjs +8 -2
- package/dist/actions/deplint/findFiles.mjs.map +1 -1
- package/dist/actions/deplint/getExtendsFromTsconfigs.mjs +44 -0
- package/dist/actions/deplint/getExtendsFromTsconfigs.mjs.map +1 -0
- package/dist/actions/deplint/getExternalImportsFromFiles.mjs +15 -1
- package/dist/actions/deplint/getExternalImportsFromFiles.mjs.map +1 -1
- package/dist/actions/deplint/getRequiredPeerDependencies.mjs +36 -0
- package/dist/actions/deplint/getRequiredPeerDependencies.mjs.map +1 -0
- package/dist/actions/deplint/getScriptReferencedPackages.mjs +81 -0
- package/dist/actions/deplint/getScriptReferencedPackages.mjs.map +1 -0
- package/dist/actions/deplint/implicitDevDependencies.mjs +25 -0
- package/dist/actions/deplint/implicitDevDependencies.mjs.map +1 -0
- package/dist/actions/deplint/index.mjs +281 -38
- package/dist/actions/deplint/index.mjs.map +1 -1
- package/dist/actions/index.mjs +385 -142
- package/dist/actions/index.mjs.map +1 -1
- package/dist/bin/xy.mjs +328 -85
- package/dist/bin/xy.mjs.map +1 -1
- package/dist/index.mjs +397 -154
- package/dist/index.mjs.map +1 -1
- package/dist/xy/index.mjs +328 -85
- package/dist/xy/index.mjs.map +1 -1
- package/dist/xy/xy.mjs +328 -85
- package/dist/xy/xy.mjs.map +1 -1
- package/dist/xy/xyLintCommands.mjs +301 -58
- package/dist/xy/xyLintCommands.mjs.map +1 -1
- package/package.json +15 -16
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// src/actions/deplint/checkPackage/getUnlistedDependencies.ts
|
|
2
2
|
import { builtinModules } from "module";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
+
function isListedOrBuiltin(imp, name, dependencies, peerDependencies) {
|
|
5
|
+
return dependencies.includes(imp) || imp === name || dependencies.includes(`@types/${imp}`) || peerDependencies.includes(imp) || peerDependencies.includes(`@types/${imp}`) || builtinModules.includes(imp) || builtinModules.includes(`@types/${imp}`);
|
|
6
|
+
}
|
|
7
|
+
function logMissing(name, imp, importPaths) {
|
|
8
|
+
console.log(`[${chalk.blue(name)}] Missing dependency in package.json: ${chalk.red(imp)}`);
|
|
9
|
+
if (importPaths[imp]) {
|
|
10
|
+
console.log(` ${importPaths[imp].join("\n ")}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
4
13
|
function getUnlistedDependencies({ name, location }, { dependencies, peerDependencies }, {
|
|
5
14
|
externalDistImports,
|
|
6
15
|
externalDistTypeImports,
|
|
@@ -8,17 +17,15 @@ function getUnlistedDependencies({ name, location }, { dependencies, peerDepende
|
|
|
8
17
|
}) {
|
|
9
18
|
let unlistedDependencies = 0;
|
|
10
19
|
for (const imp of externalDistImports) {
|
|
11
|
-
if (!
|
|
20
|
+
if (!isListedOrBuiltin(imp, name, dependencies, peerDependencies)) {
|
|
12
21
|
unlistedDependencies++;
|
|
13
|
-
|
|
14
|
-
console.log(` ${distImportPaths[imp].join("\n ")}`);
|
|
22
|
+
logMissing(name, imp, distImportPaths);
|
|
15
23
|
}
|
|
16
24
|
}
|
|
17
25
|
for (const imp of externalDistTypeImports) {
|
|
18
|
-
if (!
|
|
26
|
+
if (!isListedOrBuiltin(imp, name, dependencies, peerDependencies)) {
|
|
19
27
|
unlistedDependencies++;
|
|
20
|
-
|
|
21
|
-
console.log(` ${distImportPaths[imp].join("\n ")}`);
|
|
28
|
+
logMissing(name, imp, distImportPaths);
|
|
22
29
|
}
|
|
23
30
|
}
|
|
24
31
|
if (unlistedDependencies > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/actions/deplint/checkPackage/getUnlistedDependencies.ts"],"sourcesContent":["import { builtinModules } from 'node:module'\n\nimport chalk from 'chalk'\n\nimport type { Workspace } from '../../../lib/index.ts'\nimport type { CheckPackageParams, CheckSourceParams } from './checkPackageTypes.ts'\n\
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/deplint/checkPackage/getUnlistedDependencies.ts"],"sourcesContent":["import { builtinModules } from 'node:module'\n\nimport chalk from 'chalk'\n\nimport type { Workspace } from '../../../lib/index.ts'\nimport type { CheckPackageParams, CheckSourceParams } from './checkPackageTypes.ts'\n\nfunction isListedOrBuiltin(\n imp: string,\n name: string,\n dependencies: string[],\n peerDependencies: string[],\n) {\n return dependencies.includes(imp)\n || imp === name\n || dependencies.includes(`@types/${imp}`)\n || peerDependencies.includes(imp)\n || peerDependencies.includes(`@types/${imp}`)\n || builtinModules.includes(imp)\n || builtinModules.includes(`@types/${imp}`)\n}\n\nfunction logMissing(name: string, imp: string, importPaths: Record<string, string[]>) {\n console.log(`[${chalk.blue(name)}] Missing dependency in package.json: ${chalk.red(imp)}`)\n if (importPaths[imp]) {\n console.log(` ${importPaths[imp].join('\\n ')}`)\n }\n}\n\nexport function getUnlistedDependencies(\n { name, location }: Workspace,\n { dependencies, peerDependencies }: CheckPackageParams,\n {\n externalDistImports, externalDistTypeImports, distImportPaths,\n }: CheckSourceParams,\n) {\n let unlistedDependencies = 0\n\n for (const imp of externalDistImports) {\n if (!isListedOrBuiltin(imp, name, dependencies, peerDependencies)) {\n unlistedDependencies++\n logMissing(name, imp, distImportPaths)\n }\n }\n\n for (const imp of externalDistTypeImports) {\n if (!isListedOrBuiltin(imp, name, dependencies, peerDependencies)) {\n unlistedDependencies++\n logMissing(name, imp, distImportPaths)\n }\n }\n\n if (unlistedDependencies > 0) {\n const packageLocation = `${location}/package.json`\n console.log(` ${chalk.yellow(packageLocation)}\\n`)\n }\n return unlistedDependencies\n}\n"],"mappings":";AAAA,SAAS,sBAAsB;AAE/B,OAAO,WAAW;AAKlB,SAAS,kBACP,KACA,MACA,cACA,kBACA;AACA,SAAO,aAAa,SAAS,GAAG,KAC3B,QAAQ,QACR,aAAa,SAAS,UAAU,GAAG,EAAE,KACrC,iBAAiB,SAAS,GAAG,KAC7B,iBAAiB,SAAS,UAAU,GAAG,EAAE,KACzC,eAAe,SAAS,GAAG,KAC3B,eAAe,SAAS,UAAU,GAAG,EAAE;AAC9C;AAEA,SAAS,WAAW,MAAc,KAAa,aAAuC;AACpF,UAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,yCAAyC,MAAM,IAAI,GAAG,CAAC,EAAE;AACzF,MAAI,YAAY,GAAG,GAAG;AACpB,YAAQ,IAAI,KAAK,YAAY,GAAG,EAAE,KAAK,KAAK,CAAC,EAAE;AAAA,EACjD;AACF;AAEO,SAAS,wBACd,EAAE,MAAM,SAAS,GACjB,EAAE,cAAc,iBAAiB,GACjC;AAAA,EACE;AAAA,EAAqB;AAAA,EAAyB;AAChD,GACA;AACA,MAAI,uBAAuB;AAE3B,aAAW,OAAO,qBAAqB;AACrC,QAAI,CAAC,kBAAkB,KAAK,MAAM,cAAc,gBAAgB,GAAG;AACjE;AACA,iBAAW,MAAM,KAAK,eAAe;AAAA,IACvC;AAAA,EACF;AAEA,aAAW,OAAO,yBAAyB;AACzC,QAAI,CAAC,kBAAkB,KAAK,MAAM,cAAc,gBAAgB,GAAG;AACjE;AACA,iBAAW,MAAM,KAAK,eAAe;AAAA,IACvC;AAAA,EACF;AAEA,MAAI,uBAAuB,GAAG;AAC5B,UAAM,kBAAkB,GAAG,QAAQ;AACnC,YAAQ,IAAI,KAAK,MAAM,OAAO,eAAe,CAAC;AAAA,CAAI;AAAA,EACpD;AACA,SAAO;AACT;","names":[]}
|
|
@@ -15,7 +15,9 @@ function getUnlistedDevDependencies({ name, location }, {
|
|
|
15
15
|
if (!distImports.includes(imp) && imp !== name && !dependencies.includes(imp) && !dependencies.includes(`@types/${imp}`) && !peerDependencies.includes(imp) && !peerDependencies.includes(`@types/${imp}`) && !devDependencies.includes(imp) && !devDependencies.includes(`@types/${imp}`) && !builtinModules.includes(imp)) {
|
|
16
16
|
unlistedDevDependencies++;
|
|
17
17
|
console.log(`[${chalk.blue(name)}] Missing devDependency in package.json: ${chalk.red(imp)}`);
|
|
18
|
-
|
|
18
|
+
if (srcImportPaths[imp]) {
|
|
19
|
+
console.log(` ${srcImportPaths[imp].join("\n ")}`);
|
|
20
|
+
}
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
if (unlistedDevDependencies > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/actions/deplint/checkPackage/getUnlistedDevDependencies.ts"],"sourcesContent":["import { builtinModules } from 'node:module'\n\nimport chalk from 'chalk'\n\nimport type { Workspace } from '../../../lib/index.ts'\nimport type { CheckPackageParams, CheckSourceParams } from './checkPackageTypes.ts'\n\nexport function getUnlistedDevDependencies(\n { name, location }: Workspace,\n {\n devDependencies, dependencies, peerDependencies,\n }: CheckPackageParams,\n {\n srcImportPaths, externalSrcImports, distImports,\n }: CheckSourceParams,\n) {\n let unlistedDevDependencies = 0\n for (const imp of externalSrcImports) {\n if (!distImports.includes(imp)\n && imp !== name\n && !dependencies.includes(imp)\n && !dependencies.includes(`@types/${imp}`)\n && !peerDependencies.includes(imp)\n && !peerDependencies.includes(`@types/${imp}`)\n && !devDependencies.includes(imp)\n && !devDependencies.includes(`@types/${imp}`)\n && !builtinModules.includes(imp)\n ) {\n unlistedDevDependencies++\n console.log(`[${chalk.blue(name)}] Missing devDependency in package.json: ${chalk.red(imp)}`)\n console.log(` ${srcImportPaths[imp].join('\\n ')}`)\n }\n }\n if (unlistedDevDependencies > 0) {\n const packageLocation = `${location}/package.json`\n console.log(` ${chalk.yellow(packageLocation)}\\n`)\n }\n return unlistedDevDependencies\n}\n"],"mappings":";AAAA,SAAS,sBAAsB;AAE/B,OAAO,WAAW;AAKX,SAAS,2BACd,EAAE,MAAM,SAAS,GACjB;AAAA,EACE;AAAA,EAAiB;AAAA,EAAc;AACjC,GACA;AAAA,EACE;AAAA,EAAgB;AAAA,EAAoB;AACtC,GACA;AACA,MAAI,0BAA0B;AAC9B,aAAW,OAAO,oBAAoB;AACpC,QAAI,CAAC,YAAY,SAAS,GAAG,KACxB,QAAQ,QACR,CAAC,aAAa,SAAS,GAAG,KAC1B,CAAC,aAAa,SAAS,UAAU,GAAG,EAAE,KACtC,CAAC,iBAAiB,SAAS,GAAG,KAC9B,CAAC,iBAAiB,SAAS,UAAU,GAAG,EAAE,KAC1C,CAAC,gBAAgB,SAAS,GAAG,KAC7B,CAAC,gBAAgB,SAAS,UAAU,GAAG,EAAE,KACzC,CAAC,eAAe,SAAS,GAAG,GAC/B;AACA;AACA,cAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,4CAA4C,MAAM,IAAI,GAAG,CAAC,EAAE;AAC5F,
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/deplint/checkPackage/getUnlistedDevDependencies.ts"],"sourcesContent":["import { builtinModules } from 'node:module'\n\nimport chalk from 'chalk'\n\nimport type { Workspace } from '../../../lib/index.ts'\nimport type { CheckPackageParams, CheckSourceParams } from './checkPackageTypes.ts'\n\nexport function getUnlistedDevDependencies(\n { name, location }: Workspace,\n {\n devDependencies, dependencies, peerDependencies,\n }: CheckPackageParams,\n {\n srcImportPaths, externalSrcImports, distImports,\n }: CheckSourceParams,\n) {\n let unlistedDevDependencies = 0\n for (const imp of externalSrcImports) {\n if (!distImports.includes(imp)\n && imp !== name\n && !dependencies.includes(imp)\n && !dependencies.includes(`@types/${imp}`)\n && !peerDependencies.includes(imp)\n && !peerDependencies.includes(`@types/${imp}`)\n && !devDependencies.includes(imp)\n && !devDependencies.includes(`@types/${imp}`)\n && !builtinModules.includes(imp)\n ) {\n unlistedDevDependencies++\n console.log(`[${chalk.blue(name)}] Missing devDependency in package.json: ${chalk.red(imp)}`)\n if (srcImportPaths[imp]) {\n console.log(` ${srcImportPaths[imp].join('\\n ')}`)\n }\n }\n }\n if (unlistedDevDependencies > 0) {\n const packageLocation = `${location}/package.json`\n console.log(` ${chalk.yellow(packageLocation)}\\n`)\n }\n return unlistedDevDependencies\n}\n"],"mappings":";AAAA,SAAS,sBAAsB;AAE/B,OAAO,WAAW;AAKX,SAAS,2BACd,EAAE,MAAM,SAAS,GACjB;AAAA,EACE;AAAA,EAAiB;AAAA,EAAc;AACjC,GACA;AAAA,EACE;AAAA,EAAgB;AAAA,EAAoB;AACtC,GACA;AACA,MAAI,0BAA0B;AAC9B,aAAW,OAAO,oBAAoB;AACpC,QAAI,CAAC,YAAY,SAAS,GAAG,KACxB,QAAQ,QACR,CAAC,aAAa,SAAS,GAAG,KAC1B,CAAC,aAAa,SAAS,UAAU,GAAG,EAAE,KACtC,CAAC,iBAAiB,SAAS,GAAG,KAC9B,CAAC,iBAAiB,SAAS,UAAU,GAAG,EAAE,KAC1C,CAAC,gBAAgB,SAAS,GAAG,KAC7B,CAAC,gBAAgB,SAAS,UAAU,GAAG,EAAE,KACzC,CAAC,eAAe,SAAS,GAAG,GAC/B;AACA;AACA,cAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,4CAA4C,MAAM,IAAI,GAAG,CAAC,EAAE;AAC5F,UAAI,eAAe,GAAG,GAAG;AACvB,gBAAQ,IAAI,KAAK,eAAe,GAAG,EAAE,KAAK,KAAK,CAAC,EAAE;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACA,MAAI,0BAA0B,GAAG;AAC/B,UAAM,kBAAkB,GAAG,QAAQ;AACnC,YAAQ,IAAI,KAAK,MAAM,OAAO,eAAe,CAAC;AAAA,CAAI;AAAA,EACpD;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// src/actions/deplint/checkPackage/getUnusedDevDependencies.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
|
|
4
|
+
// src/actions/deplint/getRequiredPeerDependencies.ts
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
function findDepPackageJson(location, dep) {
|
|
8
|
+
let dir = location;
|
|
9
|
+
while (true) {
|
|
10
|
+
const candidate = path.join(dir, "node_modules", dep, "package.json");
|
|
11
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
12
|
+
const parent = path.dirname(dir);
|
|
13
|
+
if (parent === dir) return void 0;
|
|
14
|
+
dir = parent;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function getRequiredPeerDependencies(location, allDeps) {
|
|
18
|
+
const required = /* @__PURE__ */ new Set();
|
|
19
|
+
for (const dep of allDeps) {
|
|
20
|
+
const depPkgPath = findDepPackageJson(location, dep);
|
|
21
|
+
if (!depPkgPath) continue;
|
|
22
|
+
try {
|
|
23
|
+
const raw = fs.readFileSync(depPkgPath, "utf8");
|
|
24
|
+
const pkg = JSON.parse(raw);
|
|
25
|
+
if (pkg.peerDependencies) {
|
|
26
|
+
for (const peer of Object.keys(pkg.peerDependencies)) {
|
|
27
|
+
required.add(peer);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
} catch {
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return required;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/actions/deplint/getScriptReferencedPackages.ts
|
|
37
|
+
import fs2 from "fs";
|
|
38
|
+
import path2 from "path";
|
|
39
|
+
|
|
40
|
+
// src/actions/deplint/getBasePackageName.ts
|
|
41
|
+
function getBasePackageName(importName) {
|
|
42
|
+
const importNameScrubbed = importName.replaceAll('"', "").trim();
|
|
43
|
+
if (importNameScrubbed.startsWith("@")) {
|
|
44
|
+
const parts = importNameScrubbed.split("/");
|
|
45
|
+
return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : importNameScrubbed;
|
|
46
|
+
}
|
|
47
|
+
return importNameScrubbed.split("/")[0];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/actions/deplint/getScriptReferencedPackages.ts
|
|
51
|
+
function getBinNames(location, dep) {
|
|
52
|
+
const depPkgPath = findDepPackageJson(location, dep);
|
|
53
|
+
if (!depPkgPath) return [];
|
|
54
|
+
try {
|
|
55
|
+
const raw = fs2.readFileSync(depPkgPath, "utf8");
|
|
56
|
+
const pkg = JSON.parse(raw);
|
|
57
|
+
if (!pkg.bin) return [];
|
|
58
|
+
if (typeof pkg.bin === "string") return [pkg.name?.split("/").pop() ?? dep];
|
|
59
|
+
return Object.keys(pkg.bin);
|
|
60
|
+
} catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function tokenizeScript(script) {
|
|
65
|
+
return script.split(/[&|;$()"`\s]+/).map((t) => t.trim()).filter(Boolean);
|
|
66
|
+
}
|
|
67
|
+
function getScriptReferencedPackages(location, allDeps) {
|
|
68
|
+
const pkgPath = path2.join(location, "package.json");
|
|
69
|
+
let scripts = {};
|
|
70
|
+
try {
|
|
71
|
+
const raw = fs2.readFileSync(pkgPath, "utf8");
|
|
72
|
+
const pkg = JSON.parse(raw);
|
|
73
|
+
scripts = pkg.scripts ?? {};
|
|
74
|
+
} catch {
|
|
75
|
+
return /* @__PURE__ */ new Set();
|
|
76
|
+
}
|
|
77
|
+
const scriptText = Object.values(scripts).join(" ");
|
|
78
|
+
const tokens = new Set(tokenizeScript(scriptText));
|
|
79
|
+
const binToPackage = /* @__PURE__ */ new Map();
|
|
80
|
+
for (const dep of allDeps) {
|
|
81
|
+
const bins = getBinNames(location, dep);
|
|
82
|
+
for (const bin of bins) {
|
|
83
|
+
binToPackage.set(bin, dep);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
87
|
+
for (const token of tokens) {
|
|
88
|
+
const baseName = getBasePackageName(token);
|
|
89
|
+
if (allDeps.includes(baseName)) {
|
|
90
|
+
referenced.add(baseName);
|
|
91
|
+
}
|
|
92
|
+
const pkg = binToPackage.get(token);
|
|
93
|
+
if (pkg) {
|
|
94
|
+
referenced.add(pkg);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return referenced;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/actions/deplint/implicitDevDependencies.ts
|
|
101
|
+
var hasFileWithExtension = (files, extensions) => files.some((f) => extensions.some((ext) => f.endsWith(ext)));
|
|
102
|
+
var rules = [
|
|
103
|
+
{
|
|
104
|
+
package: "typescript",
|
|
105
|
+
isNeeded: ({ srcFiles, configFiles }) => hasFileWithExtension([...srcFiles, ...configFiles], [".ts", ".tsx", ".mts", ".cts"])
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
package: "eslint-import-resolver-typescript",
|
|
109
|
+
isNeeded: ({ srcFiles, configFiles }) => hasFileWithExtension([...srcFiles, ...configFiles], [".ts", ".tsx", ".mts", ".cts"])
|
|
110
|
+
}
|
|
111
|
+
];
|
|
112
|
+
function getImplicitDevDependencies(context) {
|
|
113
|
+
const implicit = /* @__PURE__ */ new Set();
|
|
114
|
+
for (const rule of rules) {
|
|
115
|
+
if (rule.isNeeded(context)) {
|
|
116
|
+
implicit.add(rule.package);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return implicit;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/actions/deplint/checkPackage/getUnusedDevDependencies.ts
|
|
123
|
+
var allExternalImports = ({
|
|
124
|
+
externalSrcImports,
|
|
125
|
+
externalDistImports,
|
|
126
|
+
externalDistTypeImports,
|
|
127
|
+
externalConfigImports
|
|
128
|
+
}) => {
|
|
129
|
+
const all = /* @__PURE__ */ new Set([
|
|
130
|
+
...externalSrcImports,
|
|
131
|
+
...externalDistImports,
|
|
132
|
+
...externalDistTypeImports,
|
|
133
|
+
...externalConfigImports
|
|
134
|
+
]);
|
|
135
|
+
return all;
|
|
136
|
+
};
|
|
137
|
+
function isDevDepUsed(dep, allImports, implicitDeps, requiredPeers, scriptRefs) {
|
|
138
|
+
if (implicitDeps.has(dep)) return true;
|
|
139
|
+
if (requiredPeers.has(dep)) return true;
|
|
140
|
+
if (scriptRefs.has(dep)) return true;
|
|
141
|
+
if (dep.startsWith("@types/")) {
|
|
142
|
+
const baseName = dep.replace(/^@types\//, "");
|
|
143
|
+
return allImports.has(baseName) || allImports.has(dep) || implicitDeps.has(baseName);
|
|
144
|
+
}
|
|
145
|
+
return allImports.has(dep);
|
|
146
|
+
}
|
|
147
|
+
function getUnusedDevDependencies({ name, location }, {
|
|
148
|
+
devDependencies,
|
|
149
|
+
dependencies,
|
|
150
|
+
peerDependencies
|
|
151
|
+
}, sourceParams, fileContext) {
|
|
152
|
+
const allImports = allExternalImports(sourceParams);
|
|
153
|
+
const implicitDeps = getImplicitDevDependencies(fileContext);
|
|
154
|
+
const allDeps = [...dependencies, ...devDependencies, ...peerDependencies];
|
|
155
|
+
const requiredPeers = getRequiredPeerDependencies(location, allDeps);
|
|
156
|
+
const scriptRefs = getScriptReferencedPackages(location, allDeps);
|
|
157
|
+
let unusedDevDependencies = 0;
|
|
158
|
+
for (const dep of devDependencies) {
|
|
159
|
+
if (dependencies.includes(dep) || peerDependencies.includes(dep)) continue;
|
|
160
|
+
if (!isDevDepUsed(dep, allImports, implicitDeps, requiredPeers, scriptRefs)) {
|
|
161
|
+
unusedDevDependencies++;
|
|
162
|
+
console.log(`[${chalk.blue(name)}] Unused devDependency in package.json: ${chalk.red(dep)}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (unusedDevDependencies > 0) {
|
|
166
|
+
const packageLocation = `${location}/package.json`;
|
|
167
|
+
console.log(` ${chalk.yellow(packageLocation)}
|
|
168
|
+
`);
|
|
169
|
+
}
|
|
170
|
+
return unusedDevDependencies;
|
|
171
|
+
}
|
|
172
|
+
export {
|
|
173
|
+
getUnusedDevDependencies
|
|
174
|
+
};
|
|
175
|
+
//# sourceMappingURL=getUnusedDevDependencies.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/deplint/checkPackage/getUnusedDevDependencies.ts","../../../../src/actions/deplint/getRequiredPeerDependencies.ts","../../../../src/actions/deplint/getScriptReferencedPackages.ts","../../../../src/actions/deplint/getBasePackageName.ts","../../../../src/actions/deplint/implicitDevDependencies.ts"],"sourcesContent":["import chalk from 'chalk'\n\nimport type { Workspace } from '../../../lib/index.ts'\nimport { getRequiredPeerDependencies } from '../getRequiredPeerDependencies.ts'\nimport { getScriptReferencedPackages } from '../getScriptReferencedPackages.ts'\nimport type { ImplicitDepContext } from '../implicitDevDependencies.ts'\nimport { getImplicitDevDependencies } from '../implicitDevDependencies.ts'\nimport type { CheckPackageParams, CheckSourceParams } from './checkPackageTypes.ts'\n\nconst allExternalImports = ({\n externalSrcImports,\n externalDistImports,\n externalDistTypeImports,\n externalConfigImports,\n}: CheckSourceParams) => {\n const all = new Set<string>([\n ...externalSrcImports,\n ...externalDistImports,\n ...externalDistTypeImports,\n ...externalConfigImports,\n ])\n return all\n}\n\nfunction isDevDepUsed(\n dep: string,\n allImports: Set<string>,\n implicitDeps: Set<string>,\n requiredPeers: Set<string>,\n scriptRefs: Set<string>,\n) {\n if (implicitDeps.has(dep)) return true\n if (requiredPeers.has(dep)) return true\n if (scriptRefs.has(dep)) return true\n\n if (dep.startsWith('@types/')) {\n const baseName = dep.replace(/^@types\\//, '')\n return allImports.has(baseName) || allImports.has(dep) || implicitDeps.has(baseName)\n }\n\n return allImports.has(dep)\n}\n\nexport function getUnusedDevDependencies(\n { name, location }: Workspace,\n {\n devDependencies, dependencies, peerDependencies,\n }: CheckPackageParams,\n sourceParams: CheckSourceParams,\n fileContext: ImplicitDepContext,\n) {\n const allImports = allExternalImports(sourceParams)\n const implicitDeps = getImplicitDevDependencies(fileContext)\n const allDeps = [...dependencies, ...devDependencies, ...peerDependencies]\n const requiredPeers = getRequiredPeerDependencies(location, allDeps)\n const scriptRefs = getScriptReferencedPackages(location, allDeps)\n let unusedDevDependencies = 0\n for (const dep of devDependencies) {\n // Skip devDeps that are also declared as dependencies or peerDependencies\n if (dependencies.includes(dep) || peerDependencies.includes(dep)) continue\n\n if (!isDevDepUsed(dep, allImports, implicitDeps, requiredPeers, scriptRefs)) {\n unusedDevDependencies++\n console.log(`[${chalk.blue(name)}] Unused devDependency in package.json: ${chalk.red(dep)}`)\n }\n }\n if (unusedDevDependencies > 0) {\n const packageLocation = `${location}/package.json`\n console.log(` ${chalk.yellow(packageLocation)}\\n`)\n }\n return unusedDevDependencies\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport function findDepPackageJson(location: string, dep: string): string | undefined {\n let dir = location\n while (true) {\n const candidate = path.join(dir, 'node_modules', dep, 'package.json')\n if (fs.existsSync(candidate)) return candidate\n const parent = path.dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\n/**\n * Collects the peerDependencies declared by all of a package's\n * dependencies and devDependencies. A devDependency that satisfies\n * one of these peer requirements should not be flagged as unused.\n */\nexport function getRequiredPeerDependencies(\n location: string,\n allDeps: string[],\n): Set<string> {\n const required = new Set<string>()\n for (const dep of allDeps) {\n const depPkgPath = findDepPackageJson(location, dep)\n if (!depPkgPath) continue\n try {\n const raw = fs.readFileSync(depPkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n if (pkg.peerDependencies) {\n for (const peer of Object.keys(pkg.peerDependencies)) {\n required.add(peer)\n }\n }\n } catch {\n // Package not readable — skip\n }\n }\n return required\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nimport { getBasePackageName } from './getBasePackageName.ts'\nimport { findDepPackageJson } from './getRequiredPeerDependencies.ts'\n\nfunction getBinNames(location: string, dep: string): string[] {\n const depPkgPath = findDepPackageJson(location, dep)\n if (!depPkgPath) return []\n try {\n const raw = fs.readFileSync(depPkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n if (!pkg.bin) return []\n if (typeof pkg.bin === 'string') return [pkg.name?.split('/').pop() ?? dep]\n return Object.keys(pkg.bin)\n } catch {\n return []\n }\n}\n\nfunction tokenizeScript(script: string): string[] {\n // Split on shell operators and whitespace to get command tokens\n return script\n .split(/[&|;$()\"`\\s]+/)\n .map(t => t.trim())\n .filter(Boolean)\n}\n\n/**\n * Scans package.json scripts for references to installed packages,\n * either by package name or by binary name they provide.\n */\nexport function getScriptReferencedPackages(\n location: string,\n allDeps: string[],\n): Set<string> {\n const pkgPath = path.join(location, 'package.json')\n let scripts: Record<string, string> = {}\n try {\n const raw = fs.readFileSync(pkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n scripts = pkg.scripts ?? {}\n } catch {\n return new Set()\n }\n\n const scriptText = Object.values(scripts).join(' ')\n const tokens = new Set(tokenizeScript(scriptText))\n\n // Build a map from bin name -> package name\n const binToPackage = new Map<string, string>()\n for (const dep of allDeps) {\n const bins = getBinNames(location, dep)\n for (const bin of bins) {\n binToPackage.set(bin, dep)\n }\n }\n\n const referenced = new Set<string>()\n for (const token of tokens) {\n // Direct package name match (e.g. \"yarn rimraf\" -> token \"rimraf\")\n const baseName = getBasePackageName(token)\n if (allDeps.includes(baseName)) {\n referenced.add(baseName)\n }\n // Binary name match (e.g. \"tsup\" -> @xylabs/ts-scripts-yarn3 provides \"tsup\"? no, tsup provides \"tsup\")\n const pkg = binToPackage.get(token)\n if (pkg) {\n referenced.add(pkg)\n }\n }\n\n return referenced\n}\n","export function getBasePackageName(importName: string) {\n const importNameScrubbed = importName.replaceAll('\"', '').trim()\n if (importNameScrubbed.startsWith('@')) {\n const parts = importNameScrubbed.split('/')\n return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : importNameScrubbed\n }\n return importNameScrubbed.split('/')[0]\n}\n","export interface ImplicitDevDependencyRule {\n isNeeded: (context: ImplicitDepContext) => boolean\n package: string\n}\n\nexport interface ImplicitDepContext {\n configFiles: string[]\n distFiles: string[]\n srcFiles: string[]\n}\n\nconst hasFileWithExtension = (files: string[], extensions: string[]) =>\n files.some(f => extensions.some(ext => f.endsWith(ext)))\n\nconst rules: ImplicitDevDependencyRule[] = [\n {\n package: 'typescript',\n isNeeded: ({ srcFiles, configFiles }) =>\n hasFileWithExtension([...srcFiles, ...configFiles], ['.ts', '.tsx', '.mts', '.cts']),\n },\n {\n package: 'eslint-import-resolver-typescript',\n isNeeded: ({ srcFiles, configFiles }) =>\n hasFileWithExtension([...srcFiles, ...configFiles], ['.ts', '.tsx', '.mts', '.cts']),\n },\n]\n\nexport function getImplicitDevDependencies(context: ImplicitDepContext): Set<string> {\n const implicit = new Set<string>()\n for (const rule of rules) {\n if (rule.isNeeded(context)) {\n implicit.add(rule.package)\n }\n }\n return implicit\n}\n"],"mappings":"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","names":["fs","path","fs","path"]}
|