depvitals 0.1.2 → 0.3.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/README.md +39 -61
- package/dist/cli/entry.d.ts +59 -0
- package/dist/cli/entry.d.ts.map +1 -0
- package/dist/cli/entry.js +95 -0
- package/dist/cli/entry.js.map +1 -0
- package/dist/cli/index.js +14 -18
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/notifier/eligibility.d.ts +65 -0
- package/dist/cli/notifier/eligibility.d.ts.map +1 -0
- package/dist/cli/notifier/eligibility.js +123 -0
- package/dist/cli/notifier/eligibility.js.map +1 -0
- package/dist/cli/notifier/registryLookup.d.ts +111 -0
- package/dist/cli/notifier/registryLookup.d.ts.map +1 -0
- package/dist/cli/notifier/registryLookup.js +211 -0
- package/dist/cli/notifier/registryLookup.js.map +1 -0
- package/dist/cli/notifier/updateCache.d.ts +101 -0
- package/dist/cli/notifier/updateCache.d.ts.map +1 -0
- package/dist/cli/notifier/updateCache.js +352 -0
- package/dist/cli/notifier/updateCache.js.map +1 -0
- package/dist/cli/notifier/updateCheck.d.ts +88 -0
- package/dist/cli/notifier/updateCheck.d.ts.map +1 -0
- package/dist/cli/notifier/updateCheck.js +166 -0
- package/dist/cli/notifier/updateCheck.js.map +1 -0
- package/dist/cli/notifier/versionCompare.d.ts +48 -0
- package/dist/cli/notifier/versionCompare.d.ts.map +1 -0
- package/dist/cli/notifier/versionCompare.js +89 -0
- package/dist/cli/notifier/versionCompare.js.map +1 -0
- package/dist/cli/runCli.d.ts +2 -0
- package/dist/cli/runCli.d.ts.map +1 -1
- package/dist/cli/runCli.js +36 -4
- package/dist/cli/runCli.js.map +1 -1
- package/dist/config/ignoreDependencies.d.ts +7 -0
- package/dist/config/ignoreDependencies.d.ts.map +1 -0
- package/dist/config/ignoreDependencies.js +18 -0
- package/dist/config/ignoreDependencies.js.map +1 -0
- package/dist/config/ignorePaths.d.ts +13 -0
- package/dist/config/ignorePaths.d.ts.map +1 -0
- package/dist/config/ignorePaths.js +47 -0
- package/dist/config/ignorePaths.js.map +1 -0
- package/dist/config/projectConfigError.d.ts +7 -0
- package/dist/config/projectConfigError.d.ts.map +1 -0
- package/dist/config/projectConfigError.js +10 -0
- package/dist/config/projectConfigError.js.map +1 -0
- package/dist/config/readProjectConfig.d.ts +23 -0
- package/dist/config/readProjectConfig.d.ts.map +1 -0
- package/dist/config/readProjectConfig.js +106 -0
- package/dist/config/readProjectConfig.js.map +1 -0
- package/dist/core/analyzeProject.d.ts +48 -6
- package/dist/core/analyzeProject.d.ts.map +1 -1
- package/dist/core/analyzeProject.js +123 -16
- package/dist/core/analyzeProject.js.map +1 -1
- package/dist/detectors/eslintManifestConfig.d.ts +111 -0
- package/dist/detectors/eslintManifestConfig.d.ts.map +1 -0
- package/dist/detectors/eslintManifestConfig.js +351 -0
- package/dist/detectors/eslintManifestConfig.js.map +1 -0
- package/dist/detectors/eslintRcJsonConfig.d.ts +85 -0
- package/dist/detectors/eslintRcJsonConfig.d.ts.map +1 -0
- package/dist/detectors/eslintRcJsonConfig.js +189 -0
- package/dist/detectors/eslintRcJsonConfig.js.map +1 -0
- package/dist/detectors/jestManifestConfig.d.ts +76 -0
- package/dist/detectors/jestManifestConfig.d.ts.map +1 -0
- package/dist/detectors/jestManifestConfig.js +294 -0
- package/dist/detectors/jestManifestConfig.js.map +1 -0
- package/dist/reporters/terminalReporter.js +27 -1
- package/dist/reporters/terminalReporter.js.map +1 -1
- package/dist/scanner/moduleSpecifiers.d.ts +9 -1
- package/dist/scanner/moduleSpecifiers.d.ts.map +1 -1
- package/dist/scanner/moduleSpecifiers.js +3317 -205
- package/dist/scanner/moduleSpecifiers.js.map +1 -1
- package/dist/scanner/packageSpecifier.d.ts +26 -2
- package/dist/scanner/packageSpecifier.d.ts.map +1 -1
- package/dist/scanner/packageSpecifier.js +70 -2
- package/dist/scanner/packageSpecifier.js.map +1 -1
- package/dist/scanner/projectManifest.d.ts +31 -1
- package/dist/scanner/projectManifest.d.ts.map +1 -1
- package/dist/scanner/projectManifest.js +83 -4
- package/dist/scanner/projectManifest.js.map +1 -1
- package/dist/scanner/scriptUsage.d.ts +2 -1
- package/dist/scanner/scriptUsage.d.ts.map +1 -1
- package/dist/scanner/scriptUsage.js +216 -39
- package/dist/scanner/scriptUsage.js.map +1 -1
- package/dist/scanner/sourceFiles.d.ts +16 -2
- package/dist/scanner/sourceFiles.d.ts.map +1 -1
- package/dist/scanner/sourceFiles.js +12 -6
- package/dist/scanner/sourceFiles.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzeProject.d.ts","sourceRoot":"","sources":["../../src/core/analyzeProject.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"analyzeProject.d.ts","sourceRoot":"","sources":["../../src/core/analyzeProject.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAeH;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,uDAAuD;IACvD,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,+FAA+F;IAC/F,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACxD,iGAAiG;IACjG,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACrD,4FAA4F;IAC5F,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAC7D,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,GAAG,gBAAgB,CAAC;AAEvE;;;;;;;GAOG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;gBAErB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,OAAO;CAKtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CA6DzB"}
|
|
@@ -24,26 +24,34 @@
|
|
|
24
24
|
* once and parsed once. No concurrency pool, cache or index is introduced before a measured need
|
|
25
25
|
* appears.
|
|
26
26
|
*
|
|
27
|
-
* Usage/missing formulas (`usedNames` is the union of source-external package roots
|
|
28
|
-
* package names; `declaredDependencyNames` is the
|
|
27
|
+
* Usage/missing formulas (`usedNames` is the union of source-external package roots, script-used
|
|
28
|
+
* package names and validated configuration-only package names; `declaredDependencyNames` is the
|
|
29
|
+
* union of every declared dependency section):
|
|
29
30
|
*
|
|
30
31
|
* ```text
|
|
31
32
|
* sourceUsedNames = external package roots extracted from source files
|
|
32
33
|
* scriptUsedNames = findPackageScriptUsage(scripts, dependencies ∪ devDependencies)
|
|
33
|
-
*
|
|
34
|
+
* configUsedNames = validated configuration-only names handed to the analyzer (empty for now)
|
|
35
|
+
* usedNames = sourceUsedNames ∪ scriptUsedNames ∪ configUsedNames
|
|
34
36
|
* unusedDependencies = dependencies − usedNames
|
|
35
37
|
* unusedDevDependencies = devDependencies − usedNames
|
|
36
38
|
* missingDependencies = sourceUsedNames − declaredDependencyNames
|
|
37
39
|
* ```
|
|
38
40
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
+
* The evidence sources are deliberately asymmetric:
|
|
42
|
+
* - source imports and requires may contribute to `missingDependencies`;
|
|
43
|
+
* - package scripts and validated static tool configuration may only suppress an unused finding and
|
|
44
|
+
* can never create a missing finding, because a command or configuration string is not evidence
|
|
45
|
+
* that source code references the package.
|
|
46
|
+
*
|
|
47
|
+
* Peer/optional declarations suppress false missing results through `declaredDependencyNames`.
|
|
41
48
|
*/
|
|
42
49
|
import { readFile } from 'node:fs/promises';
|
|
43
|
-
import {
|
|
50
|
+
import { dirname } from 'node:path';
|
|
51
|
+
import { loadPackageScope, loadProjectManifest, } from '../scanner/projectManifest.js';
|
|
44
52
|
import { discoverSourceFiles } from '../scanner/sourceFiles.js';
|
|
45
53
|
import { extractModuleSpecifiers } from '../scanner/moduleSpecifiers.js';
|
|
46
|
-
import { classifyPackageSpecifier } from '../scanner/packageSpecifier.js';
|
|
54
|
+
import { classifyPackageSpecifier, isPackageSelfReference } from '../scanner/packageSpecifier.js';
|
|
47
55
|
import { findPackageScriptUsage } from '../scanner/scriptUsage.js';
|
|
48
56
|
/**
|
|
49
57
|
* Operational error for the dependency-analysis engine.
|
|
@@ -67,18 +75,29 @@ export class AnalysisError extends Error {
|
|
|
67
75
|
* The supplied root is resolved to an absolute path; `process.cwd()` is never changed and the target
|
|
68
76
|
* project is never written to.
|
|
69
77
|
*
|
|
78
|
+
* @param projectRoot - Directory to analyze.
|
|
79
|
+
* @param options - Optional static tool hints and validated source exclusions; omitted inputs change nothing.
|
|
70
80
|
* @throws {AnalysisError} when a discovered source file cannot be read or cannot be safely analyzed.
|
|
71
81
|
* @throws {ProjectManifestError} when the manifest is missing, unreadable, invalid or malformed.
|
|
72
82
|
* @throws {SourceFilesError} when the root is missing, is not a directory, or cannot be read.
|
|
73
83
|
*/
|
|
74
|
-
export async function analyzeProject(projectRoot) {
|
|
84
|
+
export async function analyzeProject(projectRoot, options = {}) {
|
|
75
85
|
const manifest = await loadProjectManifest(projectRoot);
|
|
76
|
-
const sourceFiles = await discoverSourceFiles(manifest.root
|
|
86
|
+
const sourceFiles = await discoverSourceFiles(manifest.root, {
|
|
87
|
+
ignorePaths: options.ignorePaths,
|
|
88
|
+
});
|
|
77
89
|
// External package roots referenced by source files, collapsed to their package root.
|
|
78
90
|
const sourceUsedNames = new Set();
|
|
91
|
+
// Seed the selected root so scope lookup never consults a parent outside the scan.
|
|
92
|
+
const scopeByDirectory = new Map([
|
|
93
|
+
[manifest.root, { packageType: manifest.packageType, selfReference: manifest.selfReference }],
|
|
94
|
+
]);
|
|
79
95
|
for (const file of sourceFiles) {
|
|
80
|
-
const
|
|
96
|
+
const scope = await packageScopeForDirectory(dirname(file), scopeByDirectory);
|
|
97
|
+
const specifiers = await readAndExtract(file, scope.packageType);
|
|
81
98
|
for (const specifier of specifiers) {
|
|
99
|
+
if (isPackageSelfReference(specifier, scope.selfReference))
|
|
100
|
+
continue;
|
|
82
101
|
const classified = classifyPackageSpecifier(specifier);
|
|
83
102
|
if (classified.kind === 'external') {
|
|
84
103
|
sourceUsedNames.add(classified.packageName);
|
|
@@ -92,19 +111,42 @@ export async function analyzeProject(projectRoot) {
|
|
|
92
111
|
Object.keys(manifest.devDependencies),
|
|
93
112
|
]);
|
|
94
113
|
const scriptUsedNames = findPackageScriptUsage(manifest.scripts, declaredCandidates);
|
|
95
|
-
|
|
114
|
+
// Configuration evidence never reaches `sourceUsedNames`, which is the only input able to produce
|
|
115
|
+
// a missing finding; it can only make `usedNames` bigger and therefore suppress unused findings.
|
|
116
|
+
const configUsedNames = normalizeConfigHints(options.configUsedNames);
|
|
117
|
+
const usedNames = unionNames([[...sourceUsedNames], [...scriptUsedNames], [...configUsedNames]]);
|
|
96
118
|
const unusedDependencies = declaredMinus(Object.keys(manifest.dependencies), usedNames);
|
|
97
119
|
const unusedDevDependencies = declaredMinus(Object.keys(manifest.devDependencies), usedNames);
|
|
98
120
|
// An external root is missing only when it is absent from every declared dependency section.
|
|
99
121
|
// Peer/optional declarations therefore suppress false missing results.
|
|
100
122
|
const missingDependencies = declaredMinus([...sourceUsedNames], manifest.declaredDependencyNames);
|
|
123
|
+
// Exclusions are policy, not evidence: classify against the complete inventory first so script
|
|
124
|
+
// collisions and all other packages keep their ordinary meaning. Retained sources must already
|
|
125
|
+
// have been read and parsed successfully before any finding can be suppressed.
|
|
126
|
+
const ignoredDependencies = new Set(options.ignoreDependencies ?? []);
|
|
101
127
|
return {
|
|
102
128
|
projectRoot: manifest.root,
|
|
103
|
-
unusedDependencies,
|
|
104
|
-
unusedDevDependencies,
|
|
105
|
-
missingDependencies,
|
|
129
|
+
unusedDependencies: unusedDependencies.filter((name) => !ignoredDependencies.has(name)),
|
|
130
|
+
unusedDevDependencies: unusedDevDependencies.filter((name) => !ignoredDependencies.has(name)),
|
|
131
|
+
missingDependencies: missingDependencies.filter((name) => !ignoredDependencies.has(name)),
|
|
106
132
|
};
|
|
107
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Resolve the nearest package scope for one discovered source file.
|
|
136
|
+
*
|
|
137
|
+
* An existing nested `package.json` starts a new scope even when it omits `type`; directories
|
|
138
|
+
* without one inherit their parent. Ownership and module mode share this walk and cache. The
|
|
139
|
+
* selected root is always seeded before lookup, so traversal stops there.
|
|
140
|
+
*/
|
|
141
|
+
async function packageScopeForDirectory(directory, cache) {
|
|
142
|
+
const cached = cache.get(directory);
|
|
143
|
+
if (cached !== undefined)
|
|
144
|
+
return cached;
|
|
145
|
+
const ownScope = await loadPackageScope(directory);
|
|
146
|
+
const scope = ownScope ?? (await packageScopeForDirectory(dirname(directory), cache));
|
|
147
|
+
cache.set(directory, scope);
|
|
148
|
+
return scope;
|
|
149
|
+
}
|
|
108
150
|
/**
|
|
109
151
|
* Read a discovered source file and extract its statically known specifiers.
|
|
110
152
|
*
|
|
@@ -113,7 +155,7 @@ export async function analyzeProject(projectRoot) {
|
|
|
113
155
|
* preserve the original error as `cause` and include the affected path, so a broken file never
|
|
114
156
|
* yields a partial result or a misleading "clean" analysis.
|
|
115
157
|
*/
|
|
116
|
-
async function readAndExtract(file) {
|
|
158
|
+
async function readAndExtract(file, packageType) {
|
|
117
159
|
let source;
|
|
118
160
|
try {
|
|
119
161
|
source = await readFile(file, 'utf8');
|
|
@@ -121,8 +163,35 @@ async function readAndExtract(file) {
|
|
|
121
163
|
catch (error) {
|
|
122
164
|
throw new AnalysisError(`Could not read source file ${file}: ${messageOf(error)}`, 'unreadable-source', error);
|
|
123
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Determine the narrow Node source mode needed for top-level `await`.
|
|
168
|
+
*
|
|
169
|
+
* Explicit module extensions win over the package type. CommonJS extensions remain scripts even
|
|
170
|
+
* under a module package. Ambiguous `.js` scopes use bounded syntax detection; JSX/TypeScript
|
|
171
|
+
* extensions retain the existing nearest-scope `type: "module"` policy.
|
|
172
|
+
*/
|
|
173
|
+
function sourceModuleMode(file, packageType) {
|
|
174
|
+
const lower = file.toLowerCase();
|
|
175
|
+
if (lower.endsWith('.mjs') || lower.endsWith('.mts')) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
if (lower.endsWith('.cjs') || lower.endsWith('.cts')) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
if (lower.endsWith('.js') && packageType !== 'module' && packageType !== 'commonjs') {
|
|
182
|
+
return 'detect';
|
|
183
|
+
}
|
|
184
|
+
return ((lower.endsWith('.js') ||
|
|
185
|
+
lower.endsWith('.jsx') ||
|
|
186
|
+
lower.endsWith('.ts') ||
|
|
187
|
+
lower.endsWith('.tsx')) &&
|
|
188
|
+
packageType === 'module');
|
|
189
|
+
}
|
|
124
190
|
try {
|
|
125
|
-
const occurrences = extractModuleSpecifiers(source
|
|
191
|
+
const occurrences = extractModuleSpecifiers(source, {
|
|
192
|
+
jsx: usesJsxSyntax(file, source),
|
|
193
|
+
module: sourceModuleMode(file, packageType),
|
|
194
|
+
});
|
|
126
195
|
return occurrences.map((occurrence) => occurrence.specifier);
|
|
127
196
|
}
|
|
128
197
|
catch (error) {
|
|
@@ -132,6 +201,44 @@ async function readAndExtract(file) {
|
|
|
132
201
|
throw error;
|
|
133
202
|
}
|
|
134
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Whether a discovered source file may contain JSX syntax.
|
|
206
|
+
*
|
|
207
|
+
* `.jsx` and `.tsx` always enable the extractor's bounded JSX mode. Plain JavaScript extensions
|
|
208
|
+
* (`.js`, `.mjs` and `.cjs`) enable it only when the source contains a JSX-like closing or
|
|
209
|
+
* self-closing tag. TypeScript extensions other than `.tsx` stay in plain mode, so a `.ts` type
|
|
210
|
+
* assertion (`<Foo>value`) is never mistaken for markup. Extension checks are case-insensitive.
|
|
211
|
+
*/
|
|
212
|
+
function usesJsxSyntax(file, source) {
|
|
213
|
+
const lower = file.toLowerCase();
|
|
214
|
+
if (lower.endsWith('.jsx') || lower.endsWith('.tsx')) {
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
return /\.(?:js|mjs|cjs)$/.test(lower) && /<\/[A-Za-z]|\/>/.test(source);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Turn the internal configuration handoff into validated package roots.
|
|
221
|
+
*
|
|
222
|
+
* The entries come from configuration reading code, not from the trusted analyzer, so each one is
|
|
223
|
+
* re-validated with the same utility that classifies source specifiers. Builtins, relative or
|
|
224
|
+
* absolute paths, malformed scoped names, URIs, whitespace and version suffixes are dropped instead
|
|
225
|
+
* of being trusted as package names. Accepted entries collapse to their package root and are
|
|
226
|
+
* deduplicated case-sensitively; an omitted set behaves exactly like an empty one.
|
|
227
|
+
*/
|
|
228
|
+
function normalizeConfigHints(hints) {
|
|
229
|
+
const names = new Set();
|
|
230
|
+
if (hints === undefined) {
|
|
231
|
+
return names;
|
|
232
|
+
}
|
|
233
|
+
for (const hint of hints) {
|
|
234
|
+
const classified = classifyPackageSpecifier(hint);
|
|
235
|
+
if (classified.kind === 'external') {
|
|
236
|
+
names.add(classified.packageName);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// Rebuilt from sorted names so iteration order never depends on the caller's set insertion order.
|
|
240
|
+
return new Set([...names].sort(compareNames));
|
|
241
|
+
}
|
|
135
242
|
/**
|
|
136
243
|
* Union of the names of every supplied list, sorted alphabetically.
|
|
137
244
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzeProject.js","sourceRoot":"","sources":["../../src/core/analyzeProject.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"analyzeProject.js","sourceRoot":"","sources":["../../src/core/analyzeProject.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAEpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAClG,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAkEnE;;;;;;;GAOG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC7B,IAAI,CAAoB;IAEjC,YAAY,OAAe,EAAE,IAAuB,EAAE,KAAe;QACnE,KAAK,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAmB,EACnB,UAA2B,EAAE;IAE7B,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAExD,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,IAAI,EAAE;QAC3D,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC,CAAC;IAEH,sFAAsF;IACtF,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAC1C,mFAAmF;IACnF,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAA+B;QAC7D,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,aAAa,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC;KAC9F,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,gBAAgB,CAAC,CAAC;QAC9E,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QAEjE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,sBAAsB,CAAC,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC;gBAAE,SAAS;YACrE,MAAM,UAAU,GAAG,wBAAwB,CAAC,SAAS,CAAC,CAAC;YAEvD,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACnC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAED,gGAAgG;IAChG,0FAA0F;IAC1F,MAAM,kBAAkB,GAAG,UAAU,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;KACtC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,sBAAsB,CAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;IAErF,kGAAkG;IAClG,iGAAiG;IACjG,MAAM,eAAe,GAAG,oBAAoB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAEtE,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAEjG,MAAM,kBAAkB,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;IAExF,MAAM,qBAAqB,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,CAAC,CAAC;IAE9F,6FAA6F;IAC7F,uEAAuE;IACvE,MAAM,mBAAmB,GAAG,aAAa,CAAC,CAAC,GAAG,eAAe,CAAC,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAAC;IAElG,+FAA+F;IAC/F,+FAA+F;IAC/F,+EAA+E;IAC/E,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;IACtE,OAAO;QACL,WAAW,EAAE,QAAQ,CAAC,IAAI;QAC1B,kBAAkB,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvF,qBAAqB,EAAE,qBAAqB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7F,mBAAmB,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KAC1F,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,wBAAwB,CACrC,SAAiB,EACjB,KAAwC;IAExC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAExC,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,QAAQ,IAAI,CAAC,MAAM,wBAAwB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACtF,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC5B,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,cAAc,CAC3B,IAAY,EACZ,WAA+B;IAE/B,IAAI,MAAc,CAAC;IAEnB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,aAAa,CACrB,8BAA8B,IAAI,KAAK,SAAS,CAAC,KAAK,CAAC,EAAE,EACzD,mBAAmB,EACnB,KAAK,CACN,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,SAAS,gBAAgB,CAAC,IAAY,EAAE,WAA+B;QACrE,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAEjC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACrD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,WAAW,KAAK,QAAQ,IAAI,WAAW,KAAK,UAAU,EAAE,CAAC;YACpF,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,OAAO,CACL,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;YACpB,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;YACrB,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACzB,WAAW,KAAK,QAAQ,CACzB,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,uBAAuB,CAAC,MAAM,EAAE;YAClD,GAAG,EAAE,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC;YAChC,MAAM,EAAE,gBAAgB,CAAC,IAAI,EAAE,WAAW,CAAC;SAC5C,CAAC,CAAC;QACH,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;YACpE,MAAM,IAAI,aAAa,CACrB,eAAe,IAAI,2BAA2B,SAAS,CAAC,KAAK,CAAC,EAAE,EAChE,gBAAgB,EAChB,KAAK,CACN,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,aAAa,CAAC,IAAY,EAAE,MAAc;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAEjC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,oBAAoB,CAAC,KAAmC;IAC/D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAElD,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACnC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,kGAAkG;IAClG,OAAO,IAAI,GAAG,CAAS,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,KAAqC;IACvD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;YACxB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,QAA2B,EAAE,IAAyB;IAC3E,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,CAAS,EAAE,CAAS;IACxC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACV,OAAO,CAAC,CAAC,CAAC;IACZ,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACV,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy `package.json#eslintConfig` usage detection.
|
|
3
|
+
*
|
|
4
|
+
* This module answers exactly one narrow question: which declared dependencies are referenced by a
|
|
5
|
+
* small, explicitly enumerated subset of the legacy ESLint configuration block stored inside
|
|
6
|
+
* `package.json`? The result is a set of configuration-only package names that is handed to the
|
|
7
|
+
* Step 56 analyzer seam, so a recognized name can only suppress an `unused` finding and can never
|
|
8
|
+
* create a `missing` one.
|
|
9
|
+
*
|
|
10
|
+
* It deliberately does not:
|
|
11
|
+
* - evaluate, `import()`, `require()` or otherwise run ESLint, a config loader or any target code;
|
|
12
|
+
* - implement the ESLint configuration schema. Only `extends` and `plugins` are read, and only
|
|
13
|
+
* through the fixed allowlists below;
|
|
14
|
+
* - resolve `overrides`, scoped plugin shorthands, `plugin:<name>/<config>` forms other than the one
|
|
15
|
+
* allowlisted string, shareable-config subpaths, or external `.eslintrc.*` files, which are read
|
|
16
|
+
* by the sibling `findEslintRcJsonUsage` reader instead of duplicating these tables;
|
|
17
|
+
* - guess a package from arbitrary configuration text, substring-match a value, or invent a name;
|
|
18
|
+
* - report anything about a package the manifest does not declare;
|
|
19
|
+
* - mutate the analyzed project.
|
|
20
|
+
*
|
|
21
|
+
* The manifest model intentionally does not carry `eslintConfig`, so `package.json` is read a second
|
|
22
|
+
* time here as plain text: the loader is reused as the validity gate, and one extra small read beats
|
|
23
|
+
* widening the manifest model for one detector. Every unusable shape is ignored rather than
|
|
24
|
+
* diagnosed: manifest validity stays with the manifest loader and the analyzer, which report a
|
|
25
|
+
* genuinely invalid `package.json` as they always have.
|
|
26
|
+
*
|
|
27
|
+
* A conservative precedence guard applies before anything is read: when a hard barrier (a modern
|
|
28
|
+
* flat-config entrypoint, or a legacy `.eslintrc.js`/`.cjs`/`.yaml`/`.yml`) exists at the project
|
|
29
|
+
* root, the legacy block is not provably the active configuration, so no legacy hints are produced
|
|
30
|
+
* from either source. Presence is checked by directory entry name only; no entry is read,
|
|
31
|
+
* interpreted or executed. The precedence is computed once by {@link readLegacyEslintPrecedence},
|
|
32
|
+
* shared by both legacy readers, so the two sources obey exactly one set of rules.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* The legacy ESLint precedence state for one project root, computed once by both readers so the two
|
|
36
|
+
* legacy sources obey exactly one set of rules.
|
|
37
|
+
*
|
|
38
|
+
* - `hardBarrier`: a flat config or `.eslintrc.js`/`.cjs`/`.yaml`/`.yml` exists, which disables every
|
|
39
|
+
* legacy hint from both sources;
|
|
40
|
+
* - `legacyRcByName`: a legacy `.eslintrc.json` or extensionless `.eslintrc` exists by name, which
|
|
41
|
+
* displaces the manifest block but does not by itself stop the `.eslintrc.json` reader.
|
|
42
|
+
*
|
|
43
|
+
* Presence is checked by directory entry name only; no entry is opened, stat-followed, read or
|
|
44
|
+
* executed, and an unreadable root simply means no barrier is known to exist.
|
|
45
|
+
*/
|
|
46
|
+
export type LegacyEslintPrecedence = {
|
|
47
|
+
readonly hardBarrier: boolean;
|
|
48
|
+
readonly legacyRcByName: boolean;
|
|
49
|
+
readonly legacyRcJsonEntryName: string | undefined;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Compute the legacy ESLint precedence state for the project rooted at `projectRoot`.
|
|
53
|
+
*
|
|
54
|
+
* The two legacy readers ({@link findEslintManifestUsage} and {@link findEslintRcJsonUsage}) share
|
|
55
|
+
* this so a hard barrier disables both, `.eslintrc.json` wins over the manifest block, and an
|
|
56
|
+
* extensionless `.eslintrc` displaces only the manifest block. Neither reader unions the displaced
|
|
57
|
+
* source, so two contradictory legacy configurations are never combined.
|
|
58
|
+
*
|
|
59
|
+
* The legacy `.eslintrc.json` name is resolved case-insensitively, so the matched directory entry
|
|
60
|
+
* name is returned as `legacyRcJsonEntryName` for the JSON reader to reuse.
|
|
61
|
+
*
|
|
62
|
+
* @param projectRoot - Project directory to inspect; resolved to an absolute path.
|
|
63
|
+
*/
|
|
64
|
+
export declare function readLegacyEslintPrecedence(projectRoot: string): Promise<LegacyEslintPrecedence>;
|
|
65
|
+
/**
|
|
66
|
+
* Match the allowlisted subset of one legacy `eslintConfig` value against the declared packages.
|
|
67
|
+
*
|
|
68
|
+
* Pure and side-effect free: it takes the raw `eslintConfig` JSON value (any shape, including
|
|
69
|
+
* something that is not an object) and the declared dependency names, and returns the declared
|
|
70
|
+
* packages that have configuration-only evidence, in alphabetical order. Neither argument is
|
|
71
|
+
* mutated, and a candidate that is not declared is dropped, so this function can never describe an
|
|
72
|
+
* undeclared package as used.
|
|
73
|
+
*
|
|
74
|
+
* @param eslintConfig - The raw `package.json#eslintConfig` value, validated here and never trusted.
|
|
75
|
+
* @param declaredPackageNames - Declared dependency names, the only names this may return.
|
|
76
|
+
*/
|
|
77
|
+
export declare function findEslintConfigUsage(eslintConfig: unknown, declaredPackageNames: ReadonlySet<string>): ReadonlySet<string>;
|
|
78
|
+
/**
|
|
79
|
+
* Collect the legacy `package.json#eslintConfig` hints for the project rooted at `projectRoot`.
|
|
80
|
+
*
|
|
81
|
+
* The returned set is shaped for the analyzer's `configUsedNames` option (the Step 56 handoff),
|
|
82
|
+
* which is the only way configuration evidence reaches the analyzer. Nothing is decided here: the
|
|
83
|
+
* analyzer stays the sole owner of the unused/missing categories.
|
|
84
|
+
*
|
|
85
|
+
* No configuration problem is reported as an error. A missing manifest, an unreadable or invalid
|
|
86
|
+
* `package.json`, an unusable `eslintConfig` shape or an unreadable root all yield the empty set;
|
|
87
|
+
* the analyzer loads the manifest itself and remains the component that reports manifest failures,
|
|
88
|
+
* so this detector never replaces or duplicates that diagnosis.
|
|
89
|
+
*
|
|
90
|
+
* Legacy precedence (Step 68.1) is delegated to {@link readLegacyEslintPrecedence}, which both
|
|
91
|
+
* legacy readers share: a hard barrier disables this block outright, and any legacy `.eslintrc.*`
|
|
92
|
+
* by name displaces it in favour of the lower-priority `.eslintrc.json` reader. This reader never
|
|
93
|
+
* unions the displaced source, so the two legacy configurations are never combined.
|
|
94
|
+
*
|
|
95
|
+
* @param projectRoot - Project directory to inspect; resolved to an absolute path.
|
|
96
|
+
*/
|
|
97
|
+
export declare function findEslintManifestUsage(projectRoot: string): Promise<ReadonlySet<string>>;
|
|
98
|
+
/**
|
|
99
|
+
* Whether the project rooted at `projectRoot` contains a modern flat-config entrypoint (see
|
|
100
|
+
* {@link FLAT_CONFIG_ENTRY_NAMES}).
|
|
101
|
+
*
|
|
102
|
+
* A flat config is a hard barrier: its presence disables every legacy hint, including the
|
|
103
|
+
* `package.json#eslintConfig` block, so it is checked before any legacy reader contributes a hint.
|
|
104
|
+
* This is a thin convenience for callers that only need the flat-config question. Only flat-config
|
|
105
|
+
* entrypoints count: a legacy `.eslintrc.*` file reports `false`, even though it still participates
|
|
106
|
+
* in the hard-barrier check inside the legacy readers.
|
|
107
|
+
*
|
|
108
|
+
* @param projectRoot - Project directory to inspect; resolved to an absolute path.
|
|
109
|
+
*/
|
|
110
|
+
export declare function hasFlatConfigEntry(projectRoot: string): Promise<boolean>;
|
|
111
|
+
//# sourceMappingURL=eslintManifestConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eslintManifestConfig.d.ts","sourceRoot":"","sources":["../../src/detectors/eslintManifestConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAiGH;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAC;CACpD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,sBAAsB,CAAC,CA+BjC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,OAAO,EACrB,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,GACxC,WAAW,CAAC,MAAM,CAAC,CAoBrB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAwB/F;AAaD;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU9E"}
|