depvitals 0.2.0 → 0.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.
Files changed (89) hide show
  1. package/README.md +95 -30
  2. package/dist/cli/entry.js +8 -21
  3. package/dist/cli/entry.js.map +1 -1
  4. package/dist/cli/parseCliArgs.d.ts +5 -2
  5. package/dist/cli/parseCliArgs.d.ts.map +1 -1
  6. package/dist/cli/parseCliArgs.js +51 -36
  7. package/dist/cli/parseCliArgs.js.map +1 -1
  8. package/dist/cli/runCli.d.ts +4 -5
  9. package/dist/cli/runCli.d.ts.map +1 -1
  10. package/dist/cli/runCli.js +41 -46
  11. package/dist/cli/runCli.js.map +1 -1
  12. package/dist/config/ignoreDependencies.d.ts +9 -0
  13. package/dist/config/ignoreDependencies.d.ts.map +1 -0
  14. package/dist/config/ignoreDependencies.js +22 -0
  15. package/dist/config/ignoreDependencies.js.map +1 -0
  16. package/dist/config/ignorePaths.d.ts +13 -0
  17. package/dist/config/ignorePaths.d.ts.map +1 -0
  18. package/dist/config/ignorePaths.js +47 -0
  19. package/dist/config/ignorePaths.js.map +1 -0
  20. package/dist/config/projectConfigError.d.ts +7 -0
  21. package/dist/config/projectConfigError.d.ts.map +1 -0
  22. package/dist/config/projectConfigError.js +10 -0
  23. package/dist/config/projectConfigError.js.map +1 -0
  24. package/dist/config/readProjectConfig.d.ts +28 -0
  25. package/dist/config/readProjectConfig.d.ts.map +1 -0
  26. package/dist/config/readProjectConfig.js +120 -0
  27. package/dist/config/readProjectConfig.js.map +1 -0
  28. package/dist/core/analyzeProject.d.ts +40 -1
  29. package/dist/core/analyzeProject.d.ts.map +1 -1
  30. package/dist/core/analyzeProject.js +189 -45
  31. package/dist/core/analyzeProject.js.map +1 -1
  32. package/dist/core/evidence.d.ts +67 -0
  33. package/dist/core/evidence.d.ts.map +1 -0
  34. package/dist/core/evidence.js +115 -0
  35. package/dist/core/evidence.js.map +1 -0
  36. package/dist/core/scanContext.d.ts +20 -0
  37. package/dist/core/scanContext.d.ts.map +1 -0
  38. package/dist/core/scanContext.js +43 -0
  39. package/dist/core/scanContext.js.map +1 -0
  40. package/dist/detectors/eslintManifestConfig.d.ts +18 -0
  41. package/dist/detectors/eslintManifestConfig.d.ts.map +1 -1
  42. package/dist/detectors/eslintManifestConfig.js +62 -80
  43. package/dist/detectors/eslintManifestConfig.js.map +1 -1
  44. package/dist/detectors/eslintRcJsonConfig.d.ts +8 -2
  45. package/dist/detectors/eslintRcJsonConfig.d.ts.map +1 -1
  46. package/dist/detectors/eslintRcJsonConfig.js +27 -12
  47. package/dist/detectors/eslintRcJsonConfig.js.map +1 -1
  48. package/dist/detectors/jestManifestConfig.d.ts +15 -3
  49. package/dist/detectors/jestManifestConfig.d.ts.map +1 -1
  50. package/dist/detectors/jestManifestConfig.js +63 -83
  51. package/dist/detectors/jestManifestConfig.js.map +1 -1
  52. package/dist/reporters/jsonReporter.d.ts +39 -0
  53. package/dist/reporters/jsonReporter.d.ts.map +1 -0
  54. package/dist/reporters/jsonReporter.js +91 -0
  55. package/dist/reporters/jsonReporter.js.map +1 -0
  56. package/dist/reporters/terminalReporter.d.ts +15 -4
  57. package/dist/reporters/terminalReporter.d.ts.map +1 -1
  58. package/dist/reporters/terminalReporter.js +64 -4
  59. package/dist/reporters/terminalReporter.js.map +1 -1
  60. package/dist/scanner/moduleSpecifiers.d.ts +12 -2
  61. package/dist/scanner/moduleSpecifiers.d.ts.map +1 -1
  62. package/dist/scanner/moduleSpecifiers.js +1154 -183
  63. package/dist/scanner/moduleSpecifiers.js.map +1 -1
  64. package/dist/scanner/packageSpecifier.d.ts +26 -2
  65. package/dist/scanner/packageSpecifier.d.ts.map +1 -1
  66. package/dist/scanner/packageSpecifier.js +70 -2
  67. package/dist/scanner/packageSpecifier.js.map +1 -1
  68. package/dist/scanner/projectManifest.d.ts +28 -3
  69. package/dist/scanner/projectManifest.d.ts.map +1 -1
  70. package/dist/scanner/projectManifest.js +58 -13
  71. package/dist/scanner/projectManifest.js.map +1 -1
  72. package/dist/scanner/scriptUsage.d.ts +15 -1
  73. package/dist/scanner/scriptUsage.d.ts.map +1 -1
  74. package/dist/scanner/scriptUsage.js +284 -69
  75. package/dist/scanner/scriptUsage.js.map +1 -1
  76. package/dist/scanner/sourceFiles.d.ts +21 -2
  77. package/dist/scanner/sourceFiles.d.ts.map +1 -1
  78. package/dist/scanner/sourceFiles.js +19 -6
  79. package/dist/scanner/sourceFiles.js.map +1 -1
  80. package/package.json +4 -2
  81. package/schemas/README.md +47 -0
  82. package/schemas/examples/README.md +27 -0
  83. package/schemas/examples/explain-excluded.json +53 -0
  84. package/schemas/examples/explain-missing.json +65 -0
  85. package/schemas/examples/explain-node-preload.json +70 -0
  86. package/schemas/examples/explain-unknown.json +53 -0
  87. package/schemas/examples/scan-clean.json +40 -0
  88. package/schemas/examples/scan-findings.json +80 -0
  89. package/schemas/report-v1.schema.json +376 -0
@@ -11,9 +11,9 @@
11
11
  * - execute Jest, `import()`/`require()` its configuration loader, or evaluate any target code;
12
12
  * - implement the Jest configuration schema. Only `preset`, `testEnvironment` and `transform` are
13
13
  * read, and only through the fixed allowlists below;
14
- * - read the `transform` map *keys*. Every key of that map is a regular expression selecting the
15
- * files a transformer applies to, so a key is a pattern and never a package name, even when it
16
- * literally reads `"ts-jest"`; no regular expression is ever evaluated here;
14
+ * - use `transform` map keys as package evidence. Keys are retained only in JSON pointers; they
15
+ * select the transformer field and never name a package, even when a key literally reads
16
+ * `"ts-jest"`. No regular expression is evaluated here;
17
17
  * - expand Jest shorthands. In particular `testEnvironment: "jsdom"` is *not* credited to
18
18
  * `jest-environment-jsdom`: whether that shorthand is a package reference at all depends on the
19
19
  * Jest major version in use, which DepVitals does not read, so it stays outside the supported
@@ -36,9 +36,11 @@
36
36
  * use. Ignoring is deliberate — an unusable `jest` block is not an error, and diagnosing one here would
37
37
  * duplicate the manifest loader.
38
38
  */
39
- import { readFile, readdir } from 'node:fs/promises';
39
+ import { readdir } from 'node:fs/promises';
40
40
  import { resolve } from 'node:path';
41
- import { loadProjectManifest, ProjectManifestError } from '../scanner/projectManifest.js';
41
+ import { compareEvidence, compareStrings, jsonPointer, } from '../core/evidence.js';
42
+ import { loadProjectManifest, ProjectManifestError, readManifestText, } from '../scanner/projectManifest.js';
43
+ import { assertReadableRoot, SourceFilesError } from '../scanner/sourceFiles.js';
42
44
  import { classifyPackageSpecifier } from '../scanner/packageSpecifier.js';
43
45
  /**
44
46
  * The only `preset` packages recognized by this release.
@@ -108,22 +110,50 @@ const JEST_CONFIG_ENTRY_NAMES = new Set([
108
110
  * @param declaredPackageNames - Declared dependency names, the only names this may return.
109
111
  */
110
112
  export function findJestConfigUsage(jestConfig, declaredPackageNames) {
111
- if (!isPlainRecord(jestConfig)) {
112
- return new Set();
113
- }
114
- const candidates = [
115
- ...matchAllowedPackage(jestConfig['preset'], PRESET_PACKAGE_NAMES),
116
- ...matchAllowedPackage(jestConfig['testEnvironment'], TEST_ENVIRONMENT_PACKAGE_NAMES),
117
- ...matchTransformValues(jestConfig['transform'], TRANSFORM_PACKAGE_NAMES),
118
- ];
119
- const used = new Set();
120
- for (const candidate of candidates) {
121
- if (declaredPackageNames.has(candidate)) {
122
- used.add(candidate);
113
+ return new Set(collectJestConfigUsage(jestConfig, declaredPackageNames).map(({ packageName }) => packageName));
114
+ }
115
+ /** Pure collector for standalone readers and the later shared validated-context handoff. */
116
+ export function collectJestConfigUsage(jestConfig, declaredPackageNames) {
117
+ if (!isPlainRecord(jestConfig))
118
+ return [];
119
+ const occurrences = [];
120
+ const add = (value, allowedPackages, pointerTokens) => {
121
+ if (typeof value !== 'string')
122
+ return;
123
+ for (const packageName of matchAllowedPackage(value, allowedPackages)) {
124
+ if (declaredPackageNames.has(packageName)) {
125
+ occurrences.push({
126
+ packageName,
127
+ evidence: {
128
+ kind: 'config',
129
+ file: 'package.json',
130
+ pointer: jsonPointer('jest', ...pointerTokens),
131
+ value,
132
+ detector: 'jest',
133
+ },
134
+ });
135
+ }
136
+ }
137
+ };
138
+ add(jestConfig['preset'], PRESET_PACKAGE_NAMES, ['preset']);
139
+ add(jestConfig['testEnvironment'], TEST_ENVIRONMENT_PACKAGE_NAMES, ['testEnvironment']);
140
+ const transform = jestConfig['transform'];
141
+ if (isPlainRecord(transform)) {
142
+ for (const [key, value] of Object.entries(transform)) {
143
+ // Keys identify fields only. A tuple must have exactly two items and object-shaped options;
144
+ // those options remain opaque, and only its first item can supply a recognized value.
145
+ if (Array.isArray(value)) {
146
+ if (value.length === 2 && isPlainRecord(value[1])) {
147
+ add(value[0], TRANSFORM_PACKAGE_NAMES, ['transform', key, '0']);
148
+ }
149
+ }
150
+ else {
151
+ add(value, TRANSFORM_PACKAGE_NAMES, ['transform', key]);
152
+ }
123
153
  }
124
154
  }
125
- // Rebuilt from sorted names so iteration is deterministic for every input.
126
- return new Set([...used].sort(compareNames));
155
+ // Different fields and transform keys remain distinct, even when their package/value repeats.
156
+ return occurrences.sort((a, b) => compareStrings(a.packageName, b.packageName) || compareEvidence(a.evidence, b.evidence));
127
157
  }
128
158
  /**
129
159
  * Collect the `package.json#jest` hints for the project rooted at `projectRoot`.
@@ -140,9 +170,13 @@ export function findJestConfigUsage(jestConfig, declaredPackageNames) {
140
170
  * @param projectRoot - Project directory to inspect; resolved to an absolute path.
141
171
  */
142
172
  export async function findJestManifestUsage(projectRoot) {
173
+ return new Set((await collectJestManifestUsage(projectRoot)).map(({ packageName }) => packageName));
174
+ }
175
+ /** Retain manifest facts through the existing barrier, validation and text-read path. */
176
+ export async function collectJestManifestUsage(projectRoot) {
143
177
  const root = resolve(projectRoot);
144
178
  if (await hasRootJestConfigEntry(root)) {
145
- return new Set();
179
+ return [];
146
180
  }
147
181
  let packageJsonPath;
148
182
  let declaredPackageNames;
@@ -152,12 +186,12 @@ export async function findJestManifestUsage(projectRoot) {
152
186
  declaredPackageNames = manifest.declaredDependencyNames;
153
187
  }
154
188
  catch (error) {
155
- if (error instanceof ProjectManifestError) {
156
- return new Set();
189
+ if (error instanceof ProjectManifestError || error instanceof SourceFilesError) {
190
+ return [];
157
191
  }
158
192
  throw error;
159
193
  }
160
- return findJestConfigUsage(await readJestConfigValue(packageJsonPath), declaredPackageNames);
194
+ return collectJestConfigUsage(await readJestConfigValue(packageJsonPath), declaredPackageNames);
161
195
  }
162
196
  /**
163
197
  * Whether a root Jest configuration file name exists in the project root.
@@ -170,11 +204,16 @@ export async function findJestManifestUsage(projectRoot) {
170
204
  export async function hasRootJestConfigEntry(root) {
171
205
  let entries;
172
206
  try {
207
+ await assertReadableRoot(root);
173
208
  entries = await readdir(root);
174
209
  }
175
210
  catch {
176
211
  return false;
177
212
  }
213
+ return hasRootJestConfigEntries(entries);
214
+ }
215
+ /** Pure barrier decision for a shared per-scan root listing. */
216
+ export function hasRootJestConfigEntries(entries) {
178
217
  return entries.some((entry) => JEST_CONFIG_ENTRY_NAMES.has(entry.toLowerCase()));
179
218
  }
180
219
  /**
@@ -187,7 +226,7 @@ export async function hasRootJestConfigEntry(root) {
187
226
  async function readJestConfigValue(packageJsonPath) {
188
227
  let text;
189
228
  try {
190
- text = await readFile(packageJsonPath, 'utf8');
229
+ text = await readManifestText(packageJsonPath);
191
230
  }
192
231
  catch {
193
232
  return undefined;
@@ -224,69 +263,10 @@ function matchAllowedPackage(value, allowedPackages) {
224
263
  }
225
264
  return allowedPackages.has(specifier.packageName) ? [specifier.packageName] : [];
226
265
  }
227
- /**
228
- * The allowlisted packages named by the *values* of one `jest.transform` map.
229
- *
230
- * Only values are read: `Object.values` is used precisely so that a key can never become evidence.
231
- * Every key of a Jest transform map is a regular expression such as `"^.+\\.tsx?$"`, and a key that
232
- * happens to read `"ts-jest"` is still only a pattern, so it credits nothing. A `transform` field
233
- * that is not a plain JSON object (an array, a string, a number, `null`, absent) contributes nothing.
234
- */
235
- function matchTransformValues(transform, allowedPackages) {
236
- if (!isPlainRecord(transform)) {
237
- return [];
238
- }
239
- const matches = [];
240
- for (const value of Object.values(transform)) {
241
- matches.push(...matchTransformValue(value, allowedPackages));
242
- }
243
- return matches;
244
- }
245
- /**
246
- * The allowlisted package named by one `jest.transform` value, if any.
247
- *
248
- * Exactly two shapes are supported, and no others:
249
- *
250
- * - the transformer string itself, `"ts-jest"`, matched by the same rules as the other supported
251
- * Jest fields - the value is classified first and must then be an exact member of
252
- * `allowedPackages`, so `"./local-transform.js"`, `"<rootDir>/transform.js"`, `"file:./t.js"`,
253
- * `""`, `"ts jest"`, `"ts-jest-extras"` and every other module yield nothing. As in `preset`, a
254
- * literal subpath of an allowlisted package collapses to its package root
255
- * (`"ts-jest/preprocessor.js"`, the historical ts-jest transformer path), because the first path
256
- * segment still names the package that provides the transformer;
257
- * - the `[transformer, options]` tuple: exactly two elements, the second a JSON options object, the
258
- * first matched as above. The options object is only checked for being an object and is never
259
- * inspected, so a supported package name that appears only inside it - as a label or an option
260
- * value - is not evidence.
261
- *
262
- * A one- or three-element array, a non-object second tuple element, an object used in place of the
263
- * whole value or any other shape is outside the supported subset and yields nothing.
264
- */
265
- function matchTransformValue(value, allowedPackages) {
266
- if (Array.isArray(value)) {
267
- if (value.length !== 2 || !isPlainRecord(value[1])) {
268
- return [];
269
- }
270
- return matchAllowedPackage(value[0], allowedPackages);
271
- }
272
- return matchAllowedPackage(value, allowedPackages);
273
- }
274
266
  /**
275
267
  * A JSON object (not an array, not `null`) whose keys are strings.
276
268
  */
277
269
  function isPlainRecord(value) {
278
270
  return typeof value === 'object' && value !== null && !Array.isArray(value);
279
271
  }
280
- /**
281
- * Locale-independent lexicographic ordering, so the same configuration always yields the same order.
282
- */
283
- function compareNames(a, b) {
284
- if (a < b) {
285
- return -1;
286
- }
287
- if (a > b) {
288
- return 1;
289
- }
290
- return 0;
291
- }
292
272
  //# sourceMappingURL=jestManifestConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"jestManifestConfig.js","sourceRoot":"","sources":["../../src/detectors/jestManifestConfig.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jestManifestConfig.js","sourceRoot":"","sources":["../../src/detectors/jestManifestConfig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /** Pure versioned JSON projection; internal scan objects never cross the document boundary. */
2
+ import type { AnalysisFindings, DetailedAnalysisResult, PackageExplanation } from '../core/analyzeProject.js';
3
+ import { type FindingCategory, type PackageFact } from '../core/evidence.js';
4
+ export type JsonReportInput = {
5
+ readonly mode: 'scan';
6
+ readonly result: DetailedAnalysisResult;
7
+ } | {
8
+ readonly mode: 'explain';
9
+ readonly result: PackageExplanation;
10
+ };
11
+ export type JsonReport = {
12
+ readonly schemaVersion: 1;
13
+ readonly tool: {
14
+ readonly name: 'depvitals';
15
+ readonly version: string;
16
+ };
17
+ readonly mode: 'scan' | 'explain';
18
+ readonly project: {
19
+ readonly root: string;
20
+ };
21
+ readonly scope: {
22
+ readonly sourceExtensions: readonly string[];
23
+ readonly excludedDirectories: readonly string[];
24
+ readonly ignorePaths: readonly string[];
25
+ readonly ignoreDependencies: readonly string[];
26
+ };
27
+ readonly findings: AnalysisFindings;
28
+ readonly counts: Readonly<Record<FindingCategory, number>>;
29
+ readonly packages: readonly PackageFact[];
30
+ readonly query: {
31
+ readonly packageName: string;
32
+ readonly known: boolean;
33
+ } | null;
34
+ };
35
+ /** The caller injects actual metadata version; only completed scan/query facts are accepted. */
36
+ export declare function createJsonReport(input: JsonReportInput, version: string): JsonReport;
37
+ /** Exactly one pretty-printed document and one LF; no process I/O, error envelope or banner. */
38
+ export declare function formatJsonReport(input: JsonReportInput, version: string): string;
39
+ //# sourceMappingURL=jsonReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonReporter.d.ts","sourceRoot":"","sources":["../../src/reporters/jsonReporter.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,OAAO,KAAK,EACV,gBAAgB,EAChB,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAA;CAAE,GAClE;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;QAC7C,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;QAChD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;QACxC,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;KAChD,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CAClF,CAAC;AAEF,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CAiCpF;AAED,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhF"}
@@ -0,0 +1,91 @@
1
+ import { compareStrings, DECLARATION_GROUPS, FINDING_CATEGORIES, sortedUniqueEvidence, } from '../core/evidence.js';
2
+ import { sourceDiscoveryDefaults } from '../scanner/sourceFiles.js';
3
+ /** The caller injects actual metadata version; only completed scan/query facts are accepted. */
4
+ export function createJsonReport(input, version) {
5
+ const { result } = input;
6
+ const defaults = sourceDiscoveryDefaults();
7
+ const findings = {
8
+ unusedDependencies: names(result.findings.unusedDependencies),
9
+ unusedDevDependencies: names(result.findings.unusedDevDependencies),
10
+ missingDependencies: names(result.findings.missingDependencies),
11
+ };
12
+ return {
13
+ schemaVersion: 1,
14
+ tool: { name: 'depvitals', version },
15
+ mode: input.mode,
16
+ project: { root: result.projectRoot },
17
+ scope: {
18
+ sourceExtensions: defaults.sourceExtensions,
19
+ excludedDirectories: defaults.excludedDirectories,
20
+ ignorePaths: names(result.config.ignorePaths),
21
+ ignoreDependencies: names(result.config.ignoreDependencies),
22
+ },
23
+ findings,
24
+ counts: {
25
+ unusedDependencies: findings.unusedDependencies.length,
26
+ unusedDevDependencies: findings.unusedDevDependencies.length,
27
+ missingDependencies: findings.missingDependencies.length,
28
+ },
29
+ packages: [...result.packages]
30
+ .sort((a, b) => compareStrings(a.name, b.name))
31
+ .map(packageRecord),
32
+ query: input.mode === 'explain'
33
+ ? { packageName: input.result.query.packageName, known: input.result.query.known }
34
+ : null,
35
+ };
36
+ }
37
+ /** Exactly one pretty-printed document and one LF; no process I/O, error envelope or banner. */
38
+ export function formatJsonReport(input, version) {
39
+ return JSON.stringify(createJsonReport(input, version), null, 2) + '\n';
40
+ }
41
+ function names(values) {
42
+ return [...new Set(values)].sort(compareStrings);
43
+ }
44
+ function ordered(values, order) {
45
+ return [...values].sort((a, b) => order.indexOf(a) - order.indexOf(b));
46
+ }
47
+ function packageRecord(pkg) {
48
+ return {
49
+ name: pkg.name,
50
+ status: pkg.status,
51
+ declaredIn: ordered(pkg.declaredIn, DECLARATION_GROUPS),
52
+ excluded: pkg.excluded,
53
+ underlyingFindings: ordered(pkg.underlyingFindings, FINDING_CATEGORIES),
54
+ findings: ordered(pkg.findings, FINDING_CATEGORIES),
55
+ evidence: sortedUniqueEvidence(pkg.evidence).map(evidenceRecord),
56
+ };
57
+ }
58
+ function evidenceRecord(fact) {
59
+ switch (fact.kind) {
60
+ case 'source':
61
+ return {
62
+ kind: 'source',
63
+ file: fact.file,
64
+ reference: fact.reference,
65
+ specifier: fact.specifier,
66
+ position: {
67
+ offset: fact.position.offset,
68
+ line: fact.position.line,
69
+ column: fact.position.column,
70
+ },
71
+ };
72
+ case 'script':
73
+ return {
74
+ kind: 'script',
75
+ file: fact.file,
76
+ pointer: fact.pointer,
77
+ command: fact.command,
78
+ via: fact.via,
79
+ occurrence: fact.occurrence,
80
+ };
81
+ case 'config':
82
+ return {
83
+ kind: 'config',
84
+ file: fact.file,
85
+ pointer: fact.pointer,
86
+ value: fact.value,
87
+ detector: fact.detector,
88
+ };
89
+ }
90
+ }
91
+ //# sourceMappingURL=jsonReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonReporter.js","sourceRoot":"","sources":["../../src/reporters/jsonReporter.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Deterministic terminal reporter.
3
3
  *
4
- * Renders an {@link AnalysisResult} as plain terminal text and nothing else: the module performs no
4
+ * Renders legacy findings or a completed package explanation as plain terminal text. The module performs no
5
5
  * process I/O, never imports `node:process`, never writes to a stream, never assigns an exit code,
6
- * and never reads the filesystem. It is a pure `AnalysisResult -> string` transformation, so the
6
+ * and never reads the filesystem. Both formatters are pure transformations, so the
7
7
  * exact output is fully testable and can be reused by any future presentation layer.
8
8
  *
9
9
  * The `v0.1.0` output is intentionally plain. It contains exactly:
@@ -11,7 +11,7 @@
11
11
  * - one section per non-empty findings category, in a fixed order;
12
12
  * - the clean-project message when there are no findings at all.
13
13
  *
14
- * It deliberately does not contain colors, symbols, spinners, tables, terminal-width detection,
14
+ * The legacy scan deliberately does not contain colors, symbols, spinners, tables, terminal-width detection,
15
15
  * links, prompts, source locations, advice, remediation commands, dependency counts, project paths
16
16
  * or any summary footer. Those belong to later releases, if they are added at all.
17
17
  *
@@ -30,7 +30,7 @@
30
30
  * the received arrays, and never uses locale-sensitive comparison. Deduplication stays the analyzer's
31
31
  * responsibility, so a duplicated name inside a category would be rendered twice by design.
32
32
  */
33
- import type { AnalysisResult } from '../core/analyzeProject.js';
33
+ import type { AnalysisResult, PackageExplanation } from '../core/analyzeProject.js';
34
34
  /**
35
35
  * Whether the analysis produced at least one unused or missing dependency finding.
36
36
  *
@@ -46,4 +46,15 @@ export declare function hasDependencyIssues(result: AnalysisResult): boolean;
46
46
  * findings sections in deterministic order.
47
47
  */
48
48
  export declare function formatTerminalReport(result: AnalysisResult): string;
49
+ /** Render one completed package projection without collection, classification or process I/O. */
50
+ export declare function formatTerminalExplanation(result: PackageExplanation): string;
51
+ /**
52
+ * Escape C0/C1 control characters and DEL as `\uXXXX` so a package name extracted from target
53
+ * source can never carry a terminal control sequence (such as an ESC from `"\x1b[2J"`) into the
54
+ * rendered report. Printable characters pass through unchanged.
55
+ *
56
+ * The scan is written as explicit code points instead of a control-character regex range so the
57
+ * ESLint `no-control-regex` rule stays meaningful.
58
+ */
59
+ export declare function escapeControlCharacters(value: string): string;
49
60
  //# sourceMappingURL=terminalReporter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"terminalReporter.d.ts","sourceRoot":"","sources":["../../src/reporters/terminalReporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAchE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAMnE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAQnE"}
1
+ {"version":3,"file":"terminalReporter.d.ts","sourceRoot":"","sources":["../../src/reporters/terminalReporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAsBpF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAMnE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAQnE;AAgBD,iGAAiG;AACjG,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAuB5E;AAiED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAe7D"}
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Deterministic terminal reporter.
3
3
  *
4
- * Renders an {@link AnalysisResult} as plain terminal text and nothing else: the module performs no
4
+ * Renders legacy findings or a completed package explanation as plain terminal text. The module performs no
5
5
  * process I/O, never imports `node:process`, never writes to a stream, never assigns an exit code,
6
- * and never reads the filesystem. It is a pure `AnalysisResult -> string` transformation, so the
6
+ * and never reads the filesystem. Both formatters are pure transformations, so the
7
7
  * exact output is fully testable and can be reused by any future presentation layer.
8
8
  *
9
9
  * The `v0.1.0` output is intentionally plain. It contains exactly:
@@ -11,7 +11,7 @@
11
11
  * - one section per non-empty findings category, in a fixed order;
12
12
  * - the clean-project message when there are no findings at all.
13
13
  *
14
- * It deliberately does not contain colors, symbols, spinners, tables, terminal-width detection,
14
+ * The legacy scan deliberately does not contain colors, symbols, spinners, tables, terminal-width detection,
15
15
  * links, prompts, source locations, advice, remediation commands, dependency counts, project paths
16
16
  * or any summary footer. Those belong to later releases, if they are added at all.
17
17
  *
@@ -30,6 +30,7 @@
30
30
  * the received arrays, and never uses locale-sensitive comparison. Deduplication stays the analyzer's
31
31
  * responsibility, so a duplicated name inside a category would be rendered twice by design.
32
32
  */
33
+ import { compareEvidence, DECLARATION_GROUPS, FINDING_CATEGORIES, } from '../core/evidence.js';
33
34
  /** Heading printed as the first line of every report. */
34
35
  const HEADER = 'DepVitals';
35
36
  /** Exact report returned when the analysis contains no findings at all. */
@@ -59,6 +60,65 @@ export function formatTerminalReport(result) {
59
60
  const sections = findingsSections(result).filter((section) => section.names.length > 0);
60
61
  return `${HEADER}\n\n${sections.map(renderSection).join('\n\n')}\n`;
61
62
  }
63
+ const EXPLANATION_REASONS = {
64
+ used: 'Supported usage evidence was found within the effective scope.',
65
+ unused: 'No supported usage evidence was found within the effective scope. Review before removing the package.',
66
+ missing: 'Supported source evidence references this package, but no dependency group declares it.',
67
+ excluded: 'An exact ignoreDependencies rule suppresses findings for this package. Exclusion is not usage evidence.',
68
+ declared: 'Declared only in peerDependencies and/or optionalDependencies without supported usage evidence. These groups are not checked for unused.',
69
+ unknown: 'No declaration, supported source reference or dependency exclusion was found for this package.',
70
+ };
71
+ /** Render one completed package projection without collection, classification or process I/O. */
72
+ export function formatTerminalExplanation(result) {
73
+ const pkg = result.packages[0];
74
+ const evidence = [...pkg.evidence].sort(compareEvidence);
75
+ const summary = [
76
+ `Package: ${escapeControlCharacters(pkg.name)}`,
77
+ `Status: ${pkg.status}`,
78
+ `Declared in: ${orderedSummary(pkg.declaredIn, DECLARATION_GROUPS)}`,
79
+ `Excluded: ${pkg.excluded ? 'yes' : 'no'}`,
80
+ `Underlying findings: ${orderedSummary(pkg.underlyingFindings, FINDING_CATEGORIES)}`,
81
+ `Findings: ${orderedSummary(pkg.findings, FINDING_CATEGORIES)}`,
82
+ ].join('\n');
83
+ const evidenceSection = [
84
+ `Evidence (${String(evidence.length)})`,
85
+ ...(evidence.length === 0 ? [' none'] : evidence.map(renderEvidence)),
86
+ ].join('\n');
87
+ const scope = [
88
+ 'Scope',
89
+ ` Ignored source paths: ${quotedRules(result.config.ignorePaths)}`,
90
+ ` Ignored dependency names: ${quotedRules(result.config.ignoreDependencies)}`,
91
+ ].join('\n');
92
+ return ([HEADER, summary, EXPLANATION_REASONS[pkg.status], evidenceSection, scope].join('\n\n') + '\n');
93
+ }
94
+ function orderedSummary(values, order) {
95
+ return values.length === 0
96
+ ? 'none'
97
+ : [...values]
98
+ .sort((a, b) => order.indexOf(a) - order.indexOf(b))
99
+ .map(escapeControlCharacters)
100
+ .join(', ');
101
+ }
102
+ function quotedRules(values) {
103
+ return values.length === 0
104
+ ? 'none'
105
+ : [...values].sort(compareNames).map(quoteTerminalValue).join(', ');
106
+ }
107
+ function renderEvidence(evidence) {
108
+ const file = quoteTerminalValue(evidence.file);
109
+ switch (evidence.kind) {
110
+ case 'source':
111
+ return ` source ${file}:${String(evidence.position.line)}:${String(evidence.position.column)} ${evidence.reference} ${quoteTerminalValue(evidence.specifier)}`;
112
+ case 'script':
113
+ return ` script ${file}#${quoteTerminalValue(evidence.pointer)} ${evidence.via} ${quoteTerminalValue(evidence.command)} (occurrence ${String(evidence.occurrence)})`;
114
+ case 'config':
115
+ return ` config ${file}#${quoteTerminalValue(evidence.pointer)} ${evidence.detector} ${quoteTerminalValue(evidence.value)}`;
116
+ }
117
+ }
118
+ /** Quote printable text first, then reuse the legacy control escape without double-escaping it. */
119
+ function quoteTerminalValue(value) {
120
+ return '"' + escapeControlCharacters(value.replaceAll('\\', '\\\\').replaceAll('"', '\\"')) + '"';
121
+ }
62
122
  /**
63
123
  * The findings categories in their fixed rendering order. Keeping the order here means the section
64
124
  * sequence can never depend on the shape or key order of the incoming result.
@@ -95,7 +155,7 @@ function renderSection(section) {
95
155
  * The scan is written as explicit code points instead of a control-character regex range so the
96
156
  * ESLint `no-control-regex` rule stays meaningful.
97
157
  */
98
- function escapeControlCharacters(value) {
158
+ export function escapeControlCharacters(value) {
99
159
  let out = '';
100
160
  for (let index = 0; index < value.length; index += 1) {
101
161
  const code = value.charCodeAt(index);
@@ -1 +1 @@
1
- {"version":3,"file":"terminalReporter.js","sourceRoot":"","sources":["../../src/reporters/terminalReporter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"terminalReporter.js","sourceRoot":"","sources":["../../src/reporters/terminalReporter.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,7 @@
18
18
  * template literal text and regex literals so they never produce false findings. JavaScript inside
19
19
  * template interpolations (`${...}`) is still lexed, so specifiers there are found.
20
20
  */
21
+ import type { SourceEvidence } from '../core/evidence.js';
21
22
  /**
22
23
  * The kind of module construct a specifier came from.
23
24
  */
@@ -29,6 +30,10 @@ export type ModuleSpecifierOccurrence = {
29
30
  readonly specifier: string;
30
31
  readonly kind: ModuleSpecifierKind;
31
32
  };
33
+ /** A retained occurrence measured in the original, unnormalized UTF-16 source text. */
34
+ export type PositionedModuleSpecifierOccurrence = ModuleSpecifierOccurrence & {
35
+ readonly position: Readonly<SourceEvidence['position']>;
36
+ };
32
37
  /**
33
38
  * Error code for the module specifier scanner.
34
39
  *
@@ -53,8 +58,8 @@ export declare class ModuleSpecifierError extends Error {
53
58
  */
54
59
  export type ExtractModuleSpecifiersOptions = {
55
60
  jsx?: boolean;
56
- /** Treat top-level `await` as a keyword. Omitted and false retain script/CommonJS behavior. */
57
- module?: boolean;
61
+ /** Explicit module/script grammar, or bounded syntax detection for ambiguous `.js` input. */
62
+ module?: boolean | 'detect';
58
63
  };
59
64
  /**
60
65
  * Extract the statically knowable module specifiers from `source`.
@@ -65,4 +70,9 @@ export type ExtractModuleSpecifiersOptions = {
65
70
  * from which the scanner cannot safely continue.
66
71
  */
67
72
  export declare function extractModuleSpecifiers(source: string, options?: ExtractModuleSpecifiersOptions): readonly ModuleSpecifierOccurrence[];
73
+ /**
74
+ * Authoritative occurrence collector. The lexer must finish successfully before locations escape.
75
+ * Recognition is shared with the legacy projection above; no additional extraction is performed.
76
+ */
77
+ export declare function collectModuleSpecifiers(source: string, options?: ExtractModuleSpecifiersOptions): readonly PositionedModuleSpecifierOccurrence[];
68
78
  //# sourceMappingURL=moduleSpecifiers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"moduleSpecifiers.d.ts","sourceRoot":"","sources":["../../src/scanner/moduleSpecifiers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,aAAa,GAAG,gBAAgB,GAAG,SAAS,CAAC;AAE1F;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;CACpC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAAG,gBAAgB,CAAC;AAExD;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,EAAE,MAAM,EAAE,MAAM;CAM5E;AAED;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAI3C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,+FAA+F;IAC/F,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,8BAAmC,GAC3C,SAAS,yBAAyB,EAAE,CAEtC"}
1
+ {"version":3,"file":"moduleSpecifiers.d.ts","sourceRoot":"","sources":["../../src/scanner/moduleSpecifiers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,aAAa,GAAG,gBAAgB,GAAG,SAAS,CAAC;AAE1F;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;CACpC,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,mCAAmC,GAAG,yBAAyB,GAAG;IAC5E,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;CACzD,CAAC;AAIF;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAAG,gBAAgB,CAAC;AAExD;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,EAAE,MAAM,EAAE,MAAM;CAM5E;AAED;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAI3C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,6FAA6F;IAC7F,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,8BAAmC,GAC3C,SAAS,yBAAyB,EAAE,CAKtC;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,8BAAmC,GAC3C,SAAS,mCAAmC,EAAE,CA8BhD"}