depvitals 0.1.1 → 0.2.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.
Files changed (62) hide show
  1. package/README.md +37 -54
  2. package/dist/cli/entry.d.ts +59 -0
  3. package/dist/cli/entry.d.ts.map +1 -0
  4. package/dist/cli/entry.js +95 -0
  5. package/dist/cli/entry.js.map +1 -0
  6. package/dist/cli/index.js +14 -18
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/notifier/eligibility.d.ts +65 -0
  9. package/dist/cli/notifier/eligibility.d.ts.map +1 -0
  10. package/dist/cli/notifier/eligibility.js +123 -0
  11. package/dist/cli/notifier/eligibility.js.map +1 -0
  12. package/dist/cli/notifier/registryLookup.d.ts +111 -0
  13. package/dist/cli/notifier/registryLookup.d.ts.map +1 -0
  14. package/dist/cli/notifier/registryLookup.js +211 -0
  15. package/dist/cli/notifier/registryLookup.js.map +1 -0
  16. package/dist/cli/notifier/updateCache.d.ts +101 -0
  17. package/dist/cli/notifier/updateCache.d.ts.map +1 -0
  18. package/dist/cli/notifier/updateCache.js +352 -0
  19. package/dist/cli/notifier/updateCache.js.map +1 -0
  20. package/dist/cli/notifier/updateCheck.d.ts +88 -0
  21. package/dist/cli/notifier/updateCheck.d.ts.map +1 -0
  22. package/dist/cli/notifier/updateCheck.js +166 -0
  23. package/dist/cli/notifier/updateCheck.js.map +1 -0
  24. package/dist/cli/notifier/versionCompare.d.ts +48 -0
  25. package/dist/cli/notifier/versionCompare.d.ts.map +1 -0
  26. package/dist/cli/notifier/versionCompare.js +89 -0
  27. package/dist/cli/notifier/versionCompare.js.map +1 -0
  28. package/dist/cli/runCli.d.ts +2 -0
  29. package/dist/cli/runCli.d.ts.map +1 -1
  30. package/dist/cli/runCli.js +30 -3
  31. package/dist/cli/runCli.js.map +1 -1
  32. package/dist/core/analyzeProject.d.ts +44 -6
  33. package/dist/core/analyzeProject.d.ts.map +1 -1
  34. package/dist/core/analyzeProject.js +110 -11
  35. package/dist/core/analyzeProject.js.map +1 -1
  36. package/dist/detectors/eslintManifestConfig.d.ts +111 -0
  37. package/dist/detectors/eslintManifestConfig.d.ts.map +1 -0
  38. package/dist/detectors/eslintManifestConfig.js +348 -0
  39. package/dist/detectors/eslintManifestConfig.js.map +1 -0
  40. package/dist/detectors/eslintRcJsonConfig.d.ts +85 -0
  41. package/dist/detectors/eslintRcJsonConfig.d.ts.map +1 -0
  42. package/dist/detectors/eslintRcJsonConfig.js +188 -0
  43. package/dist/detectors/eslintRcJsonConfig.js.map +1 -0
  44. package/dist/detectors/jestManifestConfig.d.ts +76 -0
  45. package/dist/detectors/jestManifestConfig.d.ts.map +1 -0
  46. package/dist/detectors/jestManifestConfig.js +292 -0
  47. package/dist/detectors/jestManifestConfig.js.map +1 -0
  48. package/dist/reporters/terminalReporter.js +27 -1
  49. package/dist/reporters/terminalReporter.js.map +1 -1
  50. package/dist/scanner/moduleSpecifiers.d.ts +9 -1
  51. package/dist/scanner/moduleSpecifiers.d.ts.map +1 -1
  52. package/dist/scanner/moduleSpecifiers.js +2352 -173
  53. package/dist/scanner/moduleSpecifiers.js.map +1 -1
  54. package/dist/scanner/projectManifest.d.ts +14 -0
  55. package/dist/scanner/projectManifest.d.ts.map +1 -1
  56. package/dist/scanner/projectManifest.js +40 -0
  57. package/dist/scanner/projectManifest.js.map +1 -1
  58. package/dist/scanner/scriptUsage.d.ts +11 -5
  59. package/dist/scanner/scriptUsage.d.ts.map +1 -1
  60. package/dist/scanner/scriptUsage.js +320 -16
  61. package/dist/scanner/scriptUsage.js.map +1 -1
  62. package/package.json +7 -7
@@ -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;AA4FH;;;;;;;;;;;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,CA8BjC;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,CAS9E"}
@@ -0,0 +1,348 @@
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
+ import { readFile, readdir } from 'node:fs/promises';
35
+ import { resolve } from 'node:path';
36
+ import { loadProjectManifest, ProjectManifestError } from '../scanner/projectManifest.js';
37
+ /**
38
+ * The legacy `extends` values recognized by this release and the package each one refers to.
39
+ *
40
+ * The table is a fixed allowlist, not a resolution algorithm. It contains the three documented
41
+ * shorthand aliases (`prettier`, `airbnb` and the single `plugin:react/recommended` form) plus the
42
+ * already complete package name of each shareable config they point at, because a complete
43
+ * `eslint-config-*` name is a valid `extends` value in its own right.
44
+ *
45
+ * There is deliberately no plugin package name in this table. Legacy ESLint resolves `extends` as a
46
+ * shareable config name, so `extends: "eslint-plugin-react"` refers to a package named
47
+ * `eslint-config-eslint-plugin-react`, not to `eslint-plugin-react`; the only valid `extends` form
48
+ * for a plugin is `plugin:<name>/<config>`. A plugin is therefore credited through
49
+ * {@link PLUGIN_PACKAGE_NAMES} (or through an allowlisted `plugin:` form), never through a bare
50
+ * plugin name in `extends`, which would suppress a real `unused` finding based on a value ESLint
51
+ * cannot load.
52
+ *
53
+ * Anything else is unsupported on purpose: `eslint:recommended`, `eslint:all`,
54
+ * `plugin:other/recommended`, `prettier/react`, a scoped config, an unknown alias or any other
55
+ * string contributes no evidence, because a guessed alias would create false confidence.
56
+ */
57
+ const EXTENDS_PACKAGE_NAMES = new Map([
58
+ ['prettier', 'eslint-config-prettier'],
59
+ ['airbnb', 'eslint-config-airbnb'],
60
+ ['plugin:react/recommended', 'eslint-plugin-react'],
61
+ ['eslint-config-prettier', 'eslint-config-prettier'],
62
+ ['eslint-config-airbnb', 'eslint-config-airbnb'],
63
+ ]);
64
+ /**
65
+ * The legacy `plugins` entries recognized by this release and the package each one refers to.
66
+ *
67
+ * Same rule as {@link EXTENDS_PACKAGE_NAMES}: only the documented `react` shorthand and the already
68
+ * complete package name are supported. Invented plugin names, scoped shorthands such as
69
+ * `@acme/eslint-plugin` and any other plugin string produce no evidence.
70
+ *
71
+ * `plugins` is where the complete `eslint-plugin-react` name is valid, unlike in `extends` (see
72
+ * {@link EXTENDS_PACKAGE_NAMES}).
73
+ */
74
+ const PLUGIN_PACKAGE_NAMES = new Map([
75
+ ['react', 'eslint-plugin-react'],
76
+ ['eslint-plugin-react', 'eslint-plugin-react'],
77
+ ]);
78
+ /**
79
+ * Modern flat-config entrypoint names that form a hard barrier: their presence disables every legacy
80
+ * ESLint hint, from both `package.json#eslintConfig` and `.eslintrc.json`.
81
+ *
82
+ * Compared case-insensitively (see {@link readLegacyEslintPrecedence}) because case-insensitive
83
+ * filesystems treat `ESLint.Config.js` as the same file, so DepVitals must not disagree with itself
84
+ * about one project on different platforms. Added in Step 68.1: `mts`/`cts` join the original four.
85
+ */
86
+ const FLAT_CONFIG_ENTRY_NAMES = new Set([
87
+ 'eslint.config.js',
88
+ 'eslint.config.mjs',
89
+ 'eslint.config.cjs',
90
+ 'eslint.config.ts',
91
+ 'eslint.config.mts',
92
+ 'eslint.config.cts',
93
+ ]);
94
+ /**
95
+ * Legacy `.eslintrc.*` names that form a hard barrier for every legacy hint, same rule as the flat
96
+ * configs: `.eslintrc.js`, `.eslintrc.cjs`, `.eslintrc.yaml` and `.eslintrc.yml`.
97
+ *
98
+ * Legacy ESLint ignores `package.json#eslintConfig` once any `.eslintrc.*` file exists by name, so
99
+ * these names disable the manifest block too. Compared case-insensitively, like the flat configs.
100
+ */
101
+ const LEGACY_BARRIER_ENTRY_NAMES = new Set([
102
+ '.eslintrc.js',
103
+ '.eslintrc.cjs',
104
+ '.eslintrc.yaml',
105
+ '.eslintrc.yml',
106
+ ]);
107
+ /**
108
+ * Legacy `.eslintrc` names whose presence displaces the manifest block but does not by itself disable
109
+ * the `.eslintrc.json` reader: the extensionless `.eslintrc` and `.eslintrc.json` itself.
110
+ *
111
+ * Legacy ESLint ignores the manifest block once any `.eslintrc.*` file exists by name, so the
112
+ * extensionless `.eslintrc` displaces only the manifest block. `.eslintrc.json` is the file the JSON
113
+ * reader actually reads, so it is listed here as a pure name check for the manifest block. Compared
114
+ * case-insensitively, like the other legacy tables.
115
+ */
116
+ const LEGACY_RC_BY_NAME_ENTRY_NAMES = new Set(['.eslintrc.json', '.eslintrc']);
117
+ /**
118
+ * Compute the legacy ESLint precedence state for the project rooted at `projectRoot`.
119
+ *
120
+ * The two legacy readers ({@link findEslintManifestUsage} and {@link findEslintRcJsonUsage}) share
121
+ * this so a hard barrier disables both, `.eslintrc.json` wins over the manifest block, and an
122
+ * extensionless `.eslintrc` displaces only the manifest block. Neither reader unions the displaced
123
+ * source, so two contradictory legacy configurations are never combined.
124
+ *
125
+ * The legacy `.eslintrc.json` name is resolved case-insensitively, so the matched directory entry
126
+ * name is returned as `legacyRcJsonEntryName` for the JSON reader to reuse.
127
+ *
128
+ * @param projectRoot - Project directory to inspect; resolved to an absolute path.
129
+ */
130
+ export async function readLegacyEslintPrecedence(projectRoot) {
131
+ const root = resolve(projectRoot);
132
+ let entries;
133
+ try {
134
+ entries = await readdir(root);
135
+ }
136
+ catch {
137
+ return {
138
+ hardBarrier: false,
139
+ legacyRcByName: false,
140
+ legacyRcJsonEntryName: undefined,
141
+ };
142
+ }
143
+ const has = (names) => entries.some((entry) => names.has(entry.toLowerCase()));
144
+ // The legacy `.eslintrc.json` name is matched case-insensitively (Windows/macOS resolve the
145
+ // same file under a different casing), so remember the actual entry that was found. The JSON
146
+ // reader reuses this exact entry name instead of assuming the canonical lowercase spelling.
147
+ // Prefer the canonical lowercase entry when both it and an uppercase copy exist in a
148
+ // case-sensitive root, so directory order cannot make the reader open the wrong file.
149
+ const legacyRcJsonEntryName = entries.includes('.eslintrc.json')
150
+ ? '.eslintrc.json'
151
+ : entries.find((entry) => entry.toLowerCase() === '.eslintrc.json');
152
+ return {
153
+ hardBarrier: has(FLAT_CONFIG_ENTRY_NAMES) || has(LEGACY_BARRIER_ENTRY_NAMES),
154
+ legacyRcByName: has(LEGACY_RC_BY_NAME_ENTRY_NAMES),
155
+ legacyRcJsonEntryName,
156
+ };
157
+ }
158
+ /**
159
+ * Match the allowlisted subset of one legacy `eslintConfig` value against the declared packages.
160
+ *
161
+ * Pure and side-effect free: it takes the raw `eslintConfig` JSON value (any shape, including
162
+ * something that is not an object) and the declared dependency names, and returns the declared
163
+ * packages that have configuration-only evidence, in alphabetical order. Neither argument is
164
+ * mutated, and a candidate that is not declared is dropped, so this function can never describe an
165
+ * undeclared package as used.
166
+ *
167
+ * @param eslintConfig - The raw `package.json#eslintConfig` value, validated here and never trusted.
168
+ * @param declaredPackageNames - Declared dependency names, the only names this may return.
169
+ */
170
+ export function findEslintConfigUsage(eslintConfig, declaredPackageNames) {
171
+ if (!isPlainRecord(eslintConfig)) {
172
+ return new Set();
173
+ }
174
+ const candidates = [
175
+ ...matchTable(extendsValues(eslintConfig['extends']), EXTENDS_PACKAGE_NAMES),
176
+ ...matchTable(pluginsValues(eslintConfig['plugins']), PLUGIN_PACKAGE_NAMES),
177
+ ];
178
+ const used = new Set();
179
+ for (const candidate of candidates) {
180
+ if (declaredPackageNames.has(candidate)) {
181
+ used.add(candidate);
182
+ }
183
+ }
184
+ // Rebuilt from sorted names so iteration is deterministic for every input.
185
+ return new Set([...used].sort(compareNames));
186
+ }
187
+ /**
188
+ * Collect the legacy `package.json#eslintConfig` hints for the project rooted at `projectRoot`.
189
+ *
190
+ * The returned set is shaped for the analyzer's `configUsedNames` option (the Step 56 handoff),
191
+ * which is the only way configuration evidence reaches the analyzer. Nothing is decided here: the
192
+ * analyzer stays the sole owner of the unused/missing categories.
193
+ *
194
+ * No configuration problem is reported as an error. A missing manifest, an unreadable or invalid
195
+ * `package.json`, an unusable `eslintConfig` shape or an unreadable root all yield the empty set;
196
+ * the analyzer loads the manifest itself and remains the component that reports manifest failures,
197
+ * so this detector never replaces or duplicates that diagnosis.
198
+ *
199
+ * Legacy precedence (Step 68.1) is delegated to {@link readLegacyEslintPrecedence}, which both
200
+ * legacy readers share: a hard barrier disables this block outright, and any legacy `.eslintrc.*`
201
+ * by name displaces it in favour of the lower-priority `.eslintrc.json` reader. This reader never
202
+ * unions the displaced source, so the two legacy configurations are never combined.
203
+ *
204
+ * @param projectRoot - Project directory to inspect; resolved to an absolute path.
205
+ */
206
+ export async function findEslintManifestUsage(projectRoot) {
207
+ const root = resolve(projectRoot);
208
+ const precedence = await readLegacyEslintPrecedence(root);
209
+ if (precedence.hardBarrier || precedence.legacyRcByName) {
210
+ return new Set();
211
+ }
212
+ let packageJsonPath;
213
+ let declaredPackageNames;
214
+ try {
215
+ const manifest = await loadProjectManifest(root);
216
+ packageJsonPath = manifest.packageJsonPath;
217
+ declaredPackageNames = manifest.declaredDependencyNames;
218
+ }
219
+ catch (error) {
220
+ if (error instanceof ProjectManifestError) {
221
+ return new Set();
222
+ }
223
+ throw error;
224
+ }
225
+ return findEslintConfigUsage(await readEslintConfigValue(packageJsonPath), declaredPackageNames);
226
+ }
227
+ /**
228
+ * Whether the on-disk directory entries contain a modern flat-config entrypoint (see
229
+ * {@link FLAT_CONFIG_ENTRY_NAMES}).
230
+ *
231
+ * A legacy `.eslintrc.*` file is not a flat-config entrypoint, so this predicate checks only the
232
+ * flat-config names.
233
+ */
234
+ function hasFlatConfigEntryEntries(entries) {
235
+ return entries.some((entry) => FLAT_CONFIG_ENTRY_NAMES.has(entry.toLowerCase()));
236
+ }
237
+ /**
238
+ * Whether the project rooted at `projectRoot` contains a modern flat-config entrypoint (see
239
+ * {@link FLAT_CONFIG_ENTRY_NAMES}).
240
+ *
241
+ * A flat config is a hard barrier: its presence disables every legacy hint, including the
242
+ * `package.json#eslintConfig` block, so it is checked before any legacy reader contributes a hint.
243
+ * This is a thin convenience for callers that only need the flat-config question. Only flat-config
244
+ * entrypoints count: a legacy `.eslintrc.*` file reports `false`, even though it still participates
245
+ * in the hard-barrier check inside the legacy readers.
246
+ *
247
+ * @param projectRoot - Project directory to inspect; resolved to an absolute path.
248
+ */
249
+ export async function hasFlatConfigEntry(projectRoot) {
250
+ let entries;
251
+ try {
252
+ entries = await readdir(resolve(projectRoot));
253
+ }
254
+ catch {
255
+ return false;
256
+ }
257
+ return hasFlatConfigEntryEntries(entries);
258
+ }
259
+ /**
260
+ * Read the raw `package.json#eslintConfig` value, ignoring everything that cannot be used.
261
+ *
262
+ * The manifest is read as text and parsed with `JSON.parse`, so no target-project code runs. An
263
+ * unreadable file, invalid JSON, a non-object document or an absent `eslintConfig` all yield
264
+ * `undefined`; the loader-facing diagnosis of a broken manifest stays in {@link loadProjectManifest}.
265
+ */
266
+ async function readEslintConfigValue(packageJsonPath) {
267
+ let text;
268
+ try {
269
+ text = await readFile(packageJsonPath, 'utf8');
270
+ }
271
+ catch {
272
+ return undefined;
273
+ }
274
+ let parsed;
275
+ try {
276
+ parsed = JSON.parse(text);
277
+ }
278
+ catch {
279
+ return undefined;
280
+ }
281
+ return isPlainRecord(parsed) ? parsed['eslintConfig'] : undefined;
282
+ }
283
+ /**
284
+ * The string values of `extends`, which ESLint accepts as one string or as an array.
285
+ *
286
+ * Non-string array entries contribute nothing on their own, so a malformed array still yields no
287
+ * evidence for the malformed entries. Any other shape (number, object, `null`, ...) contributes
288
+ * nothing at all.
289
+ */
290
+ function extendsValues(value) {
291
+ if (typeof value === 'string') {
292
+ return [value];
293
+ }
294
+ return stringItems(value);
295
+ }
296
+ /**
297
+ * The string values of `plugins`, which ESLint accepts only as an array.
298
+ *
299
+ * A bare string such as `"react"` is not a valid `plugins` value and is deliberately not accepted,
300
+ * so a typo-shaped value never becomes evidence.
301
+ */
302
+ function pluginsValues(value) {
303
+ return stringItems(value);
304
+ }
305
+ /**
306
+ * The string entries of an array value; a non-array value contributes nothing.
307
+ */
308
+ function stringItems(value) {
309
+ if (!Array.isArray(value)) {
310
+ return [];
311
+ }
312
+ return value.filter((entry) => typeof entry === 'string');
313
+ }
314
+ /**
315
+ * Look every value up in one fixed allowlist table.
316
+ *
317
+ * Lookup is exact-string only: no prefix, suffix, substring or case-insensitive matching, so
318
+ * `prettier/react`, `eslint-config-unknown` and `React` never match an entry.
319
+ */
320
+ function matchTable(values, table) {
321
+ const matched = [];
322
+ for (const value of values) {
323
+ const mapped = table.get(value);
324
+ if (mapped !== undefined) {
325
+ matched.push(mapped);
326
+ }
327
+ }
328
+ return matched;
329
+ }
330
+ /**
331
+ * A JSON object (not an array, not `null`) whose keys are strings.
332
+ */
333
+ function isPlainRecord(value) {
334
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
335
+ }
336
+ /**
337
+ * Locale-independent lexicographic ordering, so the same configuration always yields the same order.
338
+ */
339
+ function compareNames(a, b) {
340
+ if (a < b) {
341
+ return -1;
342
+ }
343
+ if (a > b) {
344
+ return 1;
345
+ }
346
+ return 0;
347
+ }
348
+ //# sourceMappingURL=eslintManifestConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslintManifestConfig.js","sourceRoot":"","sources":["../../src/detectors/eslintManifestConfig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Legacy external `.eslintrc.json` usage detection.
3
+ *
4
+ * This module adds exactly one static data source to the ESLint rules proven in Step 57: the single
5
+ * file `<projectRoot>/.eslintrc.json`. Its parsed JSON document is handed to the same pure matcher
6
+ * ({@link findEslintConfigUsage}) that reads `package.json#eslintConfig`, so the fixed allowlists,
7
+ * the exact-string lookup and the "declared packages only" rule are reused instead of duplicated.
8
+ * The result is a set of configuration-only package names for the Step 56 analyzer seam, so a
9
+ * recognized name can only suppress an `unused` finding and can never create a `missing` one.
10
+ *
11
+ * It deliberately does not:
12
+ * - evaluate, `import()`, `require()` or otherwise run ESLint, a config loader or any target code.
13
+ * The file is read as UTF-8 text and parsed with `JSON.parse`;
14
+ * - support any other legacy format: `.eslintrc.js` / `.cjs` / `.mjs` (JavaScript config modules),
15
+ * `.eslintrc.yml` / `.yaml` and extensionless `.eslintrc` are explicitly dismissed in this
16
+ * release, as is JSON5 or comment-tolerant JSON. A `.eslintrc.json` that uses JavaScript-style
17
+ * comments is therefore reported as the operational error described below rather than parsed by a
18
+ * second JSON dialect: DepVitals reads one strict JSON document, and a hand-written comment
19
+ * stripper that mis-handled a `//` inside a string value could alter the document and invent
20
+ * evidence. A leading UTF-8 BOM is different - it is an encoding artifact of the very same
21
+ * document, so it is removed before parsing;
22
+ * - traverse parent directories, nested packages or workspaces looking for further config files, or
23
+ * resolve `extends` references to other configuration files;
24
+ * - read anything besides the `extends`/`plugins` subset that {@link findEslintConfigUsage} accepts;
25
+ * every other ESLint field (`env`, `globals`, `rules`, `parserOptions`, `overrides`, ...) is
26
+ * ignored, and no unknown value produces evidence;
27
+ * - report anything about a package the manifest does not declare, or mutate the analyzed project.
28
+ *
29
+ * Two conservative file rules keep the reader honest:
30
+ *
31
+ * - only a regular file at exactly `<projectRoot>/.eslintrc.json` is read. The path is built from a
32
+ * fixed file name joined to the resolved root, so it cannot point outside the project, and
33
+ * `lstat` (not `stat`) is used so a symlinked `.eslintrc.json` is skipped rather than followed.
34
+ * Following a link could read content that lives outside the analyzed tree, which the scan policy
35
+ * forbids; skipping is the safe answer and is a documented limitation;
36
+ * - a file that exists and is a regular file but cannot be read or parsed is reported as an
37
+ * operational {@link EslintRcJsonError}. Silently ignoring it would drop the only evidence for a
38
+ * package that the broken configuration may well reference, and would let the scan present a
39
+ * misleadingly clean or wrongly `unused` result. Valid JSON with an unusable top-level shape
40
+ * (array, string, number, `null`) is different: it is not an ESLint configuration at all, so it
41
+ * contributes no evidence and is never an error, exactly like the unknown-field case.
42
+ *
43
+ * Precedence follows the legacy ESLint rule that one active configuration wins: a hard barrier (a
44
+ * modern flat config or `.eslintrc.js`/`.cjs`/`.yaml`/`.yml`) disables every legacy hint, and
45
+ * otherwise this file wins over `package.json#eslintConfig`. The precedence is computed once by a
46
+ * helper both legacy readers share; the barrier is presence-based and never reads the displaced
47
+ * source for evidence, so two contradictory legacy sources are never unioned.
48
+ */
49
+ /**
50
+ * Why a present `.eslintrc.json` could not be used as a configuration data source.
51
+ *
52
+ * - `unreadable`: the entry is a regular file but could not be read (permissions, I/O failure, ...).
53
+ * - `invalid-json`: the file content is not valid JSON, so the configuration it intends to declare
54
+ * is unknowable rather than empty.
55
+ *
56
+ * A missing file, a non-regular entry (directory, FIFO, socket, symlink) and valid JSON with an
57
+ * unusable top-level shape are not errors: they simply produce no evidence.
58
+ */
59
+ export type EslintRcJsonErrorCode = 'unreadable' | 'invalid-json';
60
+ /**
61
+ * Operational error for an unusable `.eslintrc.json`.
62
+ *
63
+ * The `code` lets callers render a clean message without matching on error strings, following the
64
+ * existing `ProjectManifestError` / `SourceFilesError` convention. Throwing is deliberate: an
65
+ * unreadable or unparsable configuration that DepVitals silently skipped could otherwise turn into
66
+ * an unfounded `unused` finding.
67
+ */
68
+ export declare class EslintRcJsonError extends Error {
69
+ readonly code: EslintRcJsonErrorCode;
70
+ constructor(message: string, code: EslintRcJsonErrorCode, cause?: unknown);
71
+ }
72
+ /**
73
+ * Collect the external `.eslintrc.json` hints for the project rooted at `projectRoot`.
74
+ *
75
+ * The returned set is shaped for the analyzer's `configUsedNames` option (the Step 56 handoff),
76
+ * which is the only way configuration evidence reaches the analyzer. Nothing is decided here: the
77
+ * analyzer stays the sole owner of the unused/missing categories, and an undeclared package can
78
+ * never appear in the result.
79
+ *
80
+ * @param projectRoot - Project directory to inspect; resolved to an absolute path.
81
+ * @throws {EslintRcJsonError} when a regular `.eslintrc.json` file exists but cannot be read or
82
+ * parsed as JSON. Absent, skipped and unusable-but-parsable files return the empty set.
83
+ */
84
+ export declare function findEslintRcJsonUsage(projectRoot: string): Promise<ReadonlySet<string>>;
85
+ //# sourceMappingURL=eslintRcJsonConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslintRcJsonConfig.d.ts","sourceRoot":"","sources":["../../src/detectors/eslintRcJsonConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAgBH;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG,YAAY,GAAG,cAAc,CAAC;AAElE;;;;;;;GAOG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,EAAE,KAAK,CAAC,EAAE,OAAO;CAK1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAsD7F"}