depvitals 0.1.2 → 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 (60) hide show
  1. package/README.md +37 -55
  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.js +35 -3
  59. package/dist/scanner/scriptUsage.js.map +1 -1
  60. package/package.json +7 -7
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Pure version comparison for the optional CLI update notifier.
3
+ *
4
+ * The notifier may only point an interactive user at a strictly newer *stable* DepVitals release,
5
+ * so the ordering rule here is intentionally bounded to `major.minor.patch` with decimal digits.
6
+ * Full semver ordering (prerelease precedence such as `-rc.1` < `-rc.2`, numeric-vs-alphanumeric
7
+ * identifiers, build metadata significance) is deliberately **not** implemented: the update-notifier
8
+ * contract requires skipping the notification for such versions instead of inventing an unreliable
9
+ * comparison, so every prerelease or build-tagged version is rejected conservatively.
10
+ *
11
+ * The module is pure by design: no filesystem, no network, no environment, no cache, no output and
12
+ * no `semver` dependency. Untrusted strings are validated by strict pattern matching, never parsed
13
+ * leniently, and no input can make these functions throw.
14
+ *
15
+ * This helper performs no eligibility decision and activates nothing; callers (later notifier code)
16
+ * decide whether a lookup happened and whether the notice may be printed.
17
+ */
18
+ /** A parsed stable version; tuple order is `major`, `minor`, `patch`. */
19
+ type ParsedVersion = readonly [major: number, minor: number, patch: number];
20
+ /**
21
+ * Parses an exact `major.minor.patch` string.
22
+ *
23
+ * Returns `undefined` for a `v` prefix, empty input, whitespace, missing or extra components
24
+ * (`0.2`, `1.2.3.4`), prerelease tags (`0.2.0-rc.1`), build metadata (`1.2.3+build.5`), partial
25
+ * tokens (`1.x.3`), leading zeros (`01.2.3`) and any other malformed metadata.
26
+ *
27
+ * Exported for the notifier's own consumers (Step 66 validates untrusted registry text with this
28
+ * single grammar) so exactly one place defines what "an exact stable DepVitals version" means.
29
+ */
30
+ export declare function parseStableVersion(value: string): ParsedVersion | undefined;
31
+ /**
32
+ * Reports whether a registry `latest` version is strictly newer than the installed DepVitals
33
+ * version, using numeric comparison in `major`, `minor`, `patch` order (never string ordering, so
34
+ * `0.2.10` is newer than `0.2.9`).
35
+ *
36
+ * Returns `false` — never a notification — when the versions are equal, when `latest` is older, or
37
+ * when either input is not an exact stable version. That includes a prerelease installed build
38
+ * (e.g. a local `0.2.0-rc.1`), which silently skips notification rather than relying on ordering
39
+ * this helper does not implement.
40
+ *
41
+ * @param current - The installed DepVitals CLI version; callers must validate untrusted strings
42
+ * (for example registry JSON) before passing them here.
43
+ * @param latest - The `latest` dist-tag reported for the package.
44
+ * @returns `true` only for a strictly newer stable `latest`; `false` for everything else.
45
+ */
46
+ export declare function isNewerStableVersion(current: string, latest: string): boolean;
47
+ export {};
48
+ //# sourceMappingURL=versionCompare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versionCompare.d.ts","sourceRoot":"","sources":["../../../src/cli/notifier/versionCompare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,yEAAyE;AACzE,KAAK,aAAa,GAAG,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAiB5E;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAgB3E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAoB7E"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Pure version comparison for the optional CLI update notifier.
3
+ *
4
+ * The notifier may only point an interactive user at a strictly newer *stable* DepVitals release,
5
+ * so the ordering rule here is intentionally bounded to `major.minor.patch` with decimal digits.
6
+ * Full semver ordering (prerelease precedence such as `-rc.1` < `-rc.2`, numeric-vs-alphanumeric
7
+ * identifiers, build metadata significance) is deliberately **not** implemented: the update-notifier
8
+ * contract requires skipping the notification for such versions instead of inventing an unreliable
9
+ * comparison, so every prerelease or build-tagged version is rejected conservatively.
10
+ *
11
+ * The module is pure by design: no filesystem, no network, no environment, no cache, no output and
12
+ * no `semver` dependency. Untrusted strings are validated by strict pattern matching, never parsed
13
+ * leniently, and no input can make these functions throw.
14
+ *
15
+ * This helper performs no eligibility decision and activates nothing; callers (later notifier code)
16
+ * decide whether a lookup happened and whether the notice may be printed.
17
+ */
18
+ /**
19
+ * One strictly numeric version component: no sign, no whitespace, no exponent, no leading zeros
20
+ * (padding is ambiguous and is not part of how npm publishes stable versions).
21
+ */
22
+ const COMPONENT = /^(?:0|[1-9][0-9]*)$/;
23
+ /**
24
+ * Parses one numeric component, returning `undefined` when it is not strictly numeric or when its
25
+ * value is not a safe integer (absurdly large digit strings must never be compared by floating-point
26
+ * rounding).
27
+ */
28
+ function parseComponent(value) {
29
+ if (value === undefined || !COMPONENT.test(value)) {
30
+ return undefined;
31
+ }
32
+ const parsed = Number.parseInt(value, 10);
33
+ return Number.isSafeInteger(parsed) ? parsed : undefined;
34
+ }
35
+ /**
36
+ * Parses an exact `major.minor.patch` string.
37
+ *
38
+ * Returns `undefined` for a `v` prefix, empty input, whitespace, missing or extra components
39
+ * (`0.2`, `1.2.3.4`), prerelease tags (`0.2.0-rc.1`), build metadata (`1.2.3+build.5`), partial
40
+ * tokens (`1.x.3`), leading zeros (`01.2.3`) and any other malformed metadata.
41
+ *
42
+ * Exported for the notifier's own consumers (Step 66 validates untrusted registry text with this
43
+ * single grammar) so exactly one place defines what "an exact stable DepVitals version" means.
44
+ */
45
+ export function parseStableVersion(value) {
46
+ const parts = value.split('.');
47
+ if (parts.length !== 3) {
48
+ return undefined;
49
+ }
50
+ const major = parseComponent(parts[0]);
51
+ const minor = parseComponent(parts[1]);
52
+ const patch = parseComponent(parts[2]);
53
+ if (major === undefined || minor === undefined || patch === undefined) {
54
+ return undefined;
55
+ }
56
+ return [major, minor, patch];
57
+ }
58
+ /**
59
+ * Reports whether a registry `latest` version is strictly newer than the installed DepVitals
60
+ * version, using numeric comparison in `major`, `minor`, `patch` order (never string ordering, so
61
+ * `0.2.10` is newer than `0.2.9`).
62
+ *
63
+ * Returns `false` — never a notification — when the versions are equal, when `latest` is older, or
64
+ * when either input is not an exact stable version. That includes a prerelease installed build
65
+ * (e.g. a local `0.2.0-rc.1`), which silently skips notification rather than relying on ordering
66
+ * this helper does not implement.
67
+ *
68
+ * @param current - The installed DepVitals CLI version; callers must validate untrusted strings
69
+ * (for example registry JSON) before passing them here.
70
+ * @param latest - The `latest` dist-tag reported for the package.
71
+ * @returns `true` only for a strictly newer stable `latest`; `false` for everything else.
72
+ */
73
+ export function isNewerStableVersion(current, latest) {
74
+ const installed = parseStableVersion(current);
75
+ const published = parseStableVersion(latest);
76
+ if (installed === undefined || published === undefined) {
77
+ return false;
78
+ }
79
+ const [installedMajor, installedMinor, installedPatch] = installed;
80
+ const [publishedMajor, publishedMinor, publishedPatch] = published;
81
+ if (publishedMajor !== installedMajor) {
82
+ return publishedMajor > installedMajor;
83
+ }
84
+ if (publishedMinor !== installedMinor) {
85
+ return publishedMinor > installedMinor;
86
+ }
87
+ return publishedPatch > installedPatch;
88
+ }
89
+ //# sourceMappingURL=versionCompare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versionCompare.js","sourceRoot":"","sources":["../../../src/cli/notifier/versionCompare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;GAGG;AACH,MAAM,SAAS,GAAG,qBAAqB,CAAC;AAKxC;;;;GAIG;AACH,SAAS,cAAc,CAAC,KAAyB;IAC/C,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAE1C,OAAO,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,MAAc;IAClE,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE7C,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,CAAC,cAAc,EAAE,cAAc,EAAE,cAAc,CAAC,GAAG,SAAS,CAAC;IACnE,MAAM,CAAC,cAAc,EAAE,cAAc,EAAE,cAAc,CAAC,GAAG,SAAS,CAAC;IAEnE,IAAI,cAAc,KAAK,cAAc,EAAE,CAAC;QACtC,OAAO,cAAc,GAAG,cAAc,CAAC;IACzC,CAAC;IAED,IAAI,cAAc,KAAK,cAAc,EAAE,CAAC;QACtC,OAAO,cAAc,GAAG,cAAc,CAAC;IACzC,CAAC;IAED,OAAO,cAAc,GAAG,cAAc,CAAC;AACzC,CAAC"}
@@ -7,6 +7,8 @@
7
7
  *
8
8
  * The responsibilities here are:
9
9
  * - delegate argument validation to the pure {@link parseCliArgs};
10
+ * - hand the configuration-only package names recognized in the project to the analyzer, which is
11
+ * the only component allowed to turn evidence into an unused/missing category;
10
12
  * - run the static dependency scan with `analyzeProject`;
11
13
  * - render the report with the pure terminal reporter;
12
14
  * - decide the scan exit code from `hasDependencyIssues`, not from the report string;
@@ -1 +1 @@
1
- {"version":3,"file":"runCli.d.ts","sourceRoot":"","sources":["../../src/cli/runCli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAkBF;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAa7F"}
1
+ {"version":3,"file":"runCli.d.ts","sourceRoot":"","sources":["../../src/cli/runCli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAYH;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAkBF;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAa7F"}
@@ -7,6 +7,8 @@
7
7
  *
8
8
  * The responsibilities here are:
9
9
  * - delegate argument validation to the pure {@link parseCliArgs};
10
+ * - hand the configuration-only package names recognized in the project to the analyzer, which is
11
+ * the only component allowed to turn evidence into an unused/missing category;
10
12
  * - run the static dependency scan with `analyzeProject`;
11
13
  * - render the report with the pure terminal reporter;
12
14
  * - decide the scan exit code from `hasDependencyIssues`, not from the report string;
@@ -16,6 +18,9 @@
16
18
  * `src/core`, and the reporter stays in `src/reporters`.
17
19
  */
18
20
  import { AnalysisError, analyzeProject } from '../core/analyzeProject.js';
21
+ import { findEslintManifestUsage } from '../detectors/eslintManifestConfig.js';
22
+ import { EslintRcJsonError, findEslintRcJsonUsage } from '../detectors/eslintRcJsonConfig.js';
23
+ import { findJestManifestUsage } from '../detectors/jestManifestConfig.js';
19
24
  import { formatTerminalReport, hasDependencyIssues } from '../reporters/terminalReporter.js';
20
25
  import { ProjectManifestError } from '../scanner/projectManifest.js';
21
26
  import { SourceFilesError } from '../scanner/sourceFiles.js';
@@ -65,7 +70,11 @@ export async function runCli(args, options) {
65
70
  async function runScan(projectPath) {
66
71
  let result;
67
72
  try {
68
- result = await analyzeProject(projectPath);
73
+ // Legacy ESLint configuration contributes configuration-only names. They are passed through the
74
+ // analyzer's config handoff, which merges them into `usedNames` only, so they can suppress an
75
+ // unused finding and can never create a missing one.
76
+ const configUsedNames = await collectConfigUsedNames(projectPath);
77
+ result = await analyzeProject(projectPath, { configUsedNames });
69
78
  }
70
79
  catch (error) {
71
80
  if (isOperationalError(error)) {
@@ -80,14 +89,32 @@ async function runScan(projectPath) {
80
89
  const hasIssues = hasDependencyIssues(result);
81
90
  return { exitCode: hasIssues ? 1 : 0, stdout: formatTerminalReport(result), stderr: '' };
82
91
  }
92
+ /**
93
+ * Collect the configuration-only package names of one project.
94
+ *
95
+ * Both legacy ESLint sources share one precedence computation: a hard barrier disables both, and
96
+ * otherwise `.eslintrc.json` wins over the `package.json#eslintConfig` block, so the two readers are
97
+ * mutually exclusive and the union never combines contradictory configuration. The `package.json#jest`
98
+ * reader is independent of the ESLint rules but obeys the same style of guard, producing nothing once
99
+ * a root `jest.config.*` file exists. The analyzer re-validates and sorts the merged hints, so no
100
+ * ordering is imposed here.
101
+ */
102
+ async function collectConfigUsedNames(projectPath) {
103
+ const manifestNames = await findEslintManifestUsage(projectPath);
104
+ const eslintRcJsonNames = await findEslintRcJsonUsage(projectPath);
105
+ const jestNames = await findJestManifestUsage(projectPath);
106
+ return new Set([...manifestNames, ...eslintRcJsonNames, ...jestNames]);
107
+ }
83
108
  /**
84
109
  * Whether the thrown value is a scanner error the CLI knows how to render. Only the existing typed
85
- * error classes count; everything else is treated as an unexpected internal failure.
110
+ * error classes plus the unusable-`.eslintrc.json` error count; everything else is treated as an
111
+ * unexpected internal failure.
86
112
  */
87
113
  function isOperationalError(error) {
88
114
  return (error instanceof ProjectManifestError ||
89
115
  error instanceof SourceFilesError ||
90
- error instanceof AnalysisError);
116
+ error instanceof AnalysisError ||
117
+ error instanceof EslintRcJsonError);
91
118
  }
92
119
  /**
93
120
  * The fallback message for an unexpected thrown value. The path is always included so the failure
@@ -1 +1 @@
1
- {"version":3,"file":"runCli.js","sourceRoot":"","sources":["../../src/cli/runCli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runCli.js","sourceRoot":"","sources":["../../src/cli/runCli.ts"],"names":[],"mappings":"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"}
@@ -24,20 +24,27 @@
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 and script-used
28
- * package names; `declaredDependencyNames` is the union of every declared dependency section):
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
- * usedNames = sourceUsedNames ∪ scriptUsedNames
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
- * Scripts never generate missing-dependency findings, and peer/optional declarations suppress false
40
- * missing results through `declaredDependencyNames`.
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
  /**
43
50
  * The structured outcome of a dependency analysis.
@@ -57,6 +64,35 @@ export type AnalysisResult = {
57
64
  /** External packages referenced by source but not declared anywhere, sorted alphabetically. */
58
65
  missingDependencies: readonly string[];
59
66
  };
67
+ /**
68
+ * Internal handoff for package names recognized by a validated static configuration reader.
69
+ *
70
+ * This is deliberately not the future public `why` evidence model: it carries no location, kind, or
71
+ * explanation, and it is never rendered or exposed. A configuration reader hands the package names it
72
+ * recognized to the analyzer through this set; only {@link analyzeProject} turns them into final
73
+ * unused/missing categories, so no configuration reader may edit report arrays directly.
74
+ *
75
+ * The analyzer validates every entry with {@link classifyPackageSpecifier} before using it, so
76
+ * arbitrary configuration text can never be treated as a package name. Accepted entries are collapsed
77
+ * to their package root and deduplicated case-sensitively, matching package-specifier classification
78
+ * (names are compared case-sensitively throughout DepVitals).
79
+ *
80
+ * The set may only suppress unused findings; it is never merged into the source-derived names that
81
+ * produce missing findings.
82
+ */
83
+ export type ConfigUsageHints = ReadonlySet<string>;
84
+ /**
85
+ * Optional inputs for {@link analyzeProject}.
86
+ */
87
+ export type AnalysisOptions = {
88
+ /**
89
+ * Validated configuration-only package names, see {@link ConfigUsageHints}.
90
+ *
91
+ * Omitted or empty is the default, which is the state of the released product: no configuration
92
+ * rule is active yet, so the default keeps every report byte-for-byte identical.
93
+ */
94
+ readonly configUsedNames?: ConfigUsageHints | undefined;
95
+ };
60
96
  /**
61
97
  * Why the analysis could not complete.
62
98
  *
@@ -84,9 +120,11 @@ export declare class AnalysisError extends Error {
84
120
  * The supplied root is resolved to an absolute path; `process.cwd()` is never changed and the target
85
121
  * project is never written to.
86
122
  *
123
+ * @param projectRoot - Directory to analyze.
124
+ * @param options - Optional {@link ConfigUsageHints}; an omitted or empty set changes nothing.
87
125
  * @throws {AnalysisError} when a discovered source file cannot be read or cannot be safely analyzed.
88
126
  * @throws {ProjectManifestError} when the manifest is missing, unreadable, invalid or malformed.
89
127
  * @throws {SourceFilesError} when the root is missing, is not a directory, or cannot be read.
90
128
  */
91
- export declare function analyzeProject(projectRoot: string): Promise<AnalysisResult>;
129
+ export declare function analyzeProject(projectRoot: string, options?: AnalysisOptions): Promise<AnalysisResult>;
92
130
  //# sourceMappingURL=analyzeProject.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"analyzeProject.d.ts","sourceRoot":"","sources":["../../src/core/analyzeProject.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAUH;;;;;;;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;;;;;;;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;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA6CjF"}
1
+ {"version":3,"file":"analyzeProject.d.ts","sourceRoot":"","sources":["../../src/core/analyzeProject.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAWH;;;;;;;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;CACzD,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,CAqDzB"}
@@ -24,23 +24,31 @@
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 and script-used
28
- * package names; `declaredDependencyNames` is the union of every declared dependency section):
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
- * usedNames = sourceUsedNames ∪ scriptUsedNames
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
- * Scripts never generate missing-dependency findings, and peer/optional declarations suppress false
40
- * missing results through `declaredDependencyNames`.
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 { loadProjectManifest } from '../scanner/projectManifest.js';
50
+ import { dirname } from 'node:path';
51
+ import { loadPackageTypeHint, loadProjectManifest } from '../scanner/projectManifest.js';
44
52
  import { discoverSourceFiles } from '../scanner/sourceFiles.js';
45
53
  import { extractModuleSpecifiers } from '../scanner/moduleSpecifiers.js';
46
54
  import { classifyPackageSpecifier } from '../scanner/packageSpecifier.js';
@@ -67,17 +75,23 @@ 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 {@link ConfigUsageHints}; an omitted or empty set changes 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
86
  const sourceFiles = await discoverSourceFiles(manifest.root);
77
87
  // External package roots referenced by source files, collapsed to their package root.
78
88
  const sourceUsedNames = new Set();
89
+ const packageTypeByDirectory = new Map([
90
+ [manifest.root, manifest.packageType],
91
+ ]);
79
92
  for (const file of sourceFiles) {
80
- const specifiers = await readAndExtract(file);
93
+ const packageType = await packageTypeForFile(file, manifest.root, packageTypeByDirectory);
94
+ const specifiers = await readAndExtract(file, packageType);
81
95
  for (const specifier of specifiers) {
82
96
  const classified = classifyPackageSpecifier(specifier);
83
97
  if (classified.kind === 'external') {
@@ -92,7 +106,10 @@ export async function analyzeProject(projectRoot) {
92
106
  Object.keys(manifest.devDependencies),
93
107
  ]);
94
108
  const scriptUsedNames = findPackageScriptUsage(manifest.scripts, declaredCandidates);
95
- const usedNames = unionNames([[...sourceUsedNames], [...scriptUsedNames]]);
109
+ // Configuration evidence never reaches `sourceUsedNames`, which is the only input able to produce
110
+ // a missing finding; it can only make `usedNames` bigger and therefore suppress unused findings.
111
+ const configUsedNames = normalizeConfigHints(options.configUsedNames);
112
+ const usedNames = unionNames([[...sourceUsedNames], [...scriptUsedNames], [...configUsedNames]]);
96
113
  const unusedDependencies = declaredMinus(Object.keys(manifest.dependencies), usedNames);
97
114
  const unusedDevDependencies = declaredMinus(Object.keys(manifest.devDependencies), usedNames);
98
115
  // An external root is missing only when it is absent from every declared dependency section.
@@ -105,6 +122,26 @@ export async function analyzeProject(projectRoot) {
105
122
  missingDependencies,
106
123
  };
107
124
  }
125
+ /**
126
+ * Resolve the nearest package scope for one discovered source file.
127
+ *
128
+ * An existing nested `package.json` starts a new scope even when it omits `type`; directories
129
+ * without one inherit their parent. Results are cached per directory for the rest of the scan.
130
+ */
131
+ async function packageTypeForFile(file, projectRoot, cache) {
132
+ return packageTypeForDirectory(dirname(file), projectRoot, cache);
133
+ }
134
+ async function packageTypeForDirectory(directory, projectRoot, cache) {
135
+ if (cache.has(directory)) {
136
+ return cache.get(directory);
137
+ }
138
+ const hint = await loadPackageTypeHint(directory);
139
+ const packageType = hint === undefined
140
+ ? await packageTypeForDirectory(dirname(directory), projectRoot, cache)
141
+ : hint.packageType;
142
+ cache.set(directory, packageType);
143
+ return packageType;
144
+ }
108
145
  /**
109
146
  * Read a discovered source file and extract its statically known specifiers.
110
147
  *
@@ -113,7 +150,7 @@ export async function analyzeProject(projectRoot) {
113
150
  * preserve the original error as `cause` and include the affected path, so a broken file never
114
151
  * yields a partial result or a misleading "clean" analysis.
115
152
  */
116
- async function readAndExtract(file) {
153
+ async function readAndExtract(file, packageType) {
117
154
  let source;
118
155
  try {
119
156
  source = await readFile(file, 'utf8');
@@ -121,8 +158,32 @@ async function readAndExtract(file) {
121
158
  catch (error) {
122
159
  throw new AnalysisError(`Could not read source file ${file}: ${messageOf(error)}`, 'unreadable-source', error);
123
160
  }
161
+ /**
162
+ * Determine the narrow Node source mode needed for top-level `await`.
163
+ *
164
+ * Explicit module extensions win over the package type. CommonJS extensions remain scripts even
165
+ * under a module package, while `.js` and `.ts` follow the nearest package scope's exact
166
+ * `type: "module"` declaration.
167
+ */
168
+ function isModuleSource(file, packageType) {
169
+ const lower = file.toLowerCase();
170
+ if (lower.endsWith('.mjs') || lower.endsWith('.mts')) {
171
+ return true;
172
+ }
173
+ if (lower.endsWith('.cjs') || lower.endsWith('.cts')) {
174
+ return false;
175
+ }
176
+ return ((lower.endsWith('.js') ||
177
+ lower.endsWith('.jsx') ||
178
+ lower.endsWith('.ts') ||
179
+ lower.endsWith('.tsx')) &&
180
+ packageType === 'module');
181
+ }
124
182
  try {
125
- const occurrences = extractModuleSpecifiers(source);
183
+ const occurrences = extractModuleSpecifiers(source, {
184
+ jsx: usesJsxSyntax(file, source),
185
+ module: isModuleSource(file, packageType),
186
+ });
126
187
  return occurrences.map((occurrence) => occurrence.specifier);
127
188
  }
128
189
  catch (error) {
@@ -132,6 +193,44 @@ async function readAndExtract(file) {
132
193
  throw error;
133
194
  }
134
195
  }
196
+ /**
197
+ * Whether a discovered source file may contain JSX syntax.
198
+ *
199
+ * `.jsx` and `.tsx` always enable the extractor's bounded JSX mode. Plain JavaScript extensions
200
+ * (`.js`, `.mjs` and `.cjs`) enable it only when the source contains a JSX-like closing or
201
+ * self-closing tag. TypeScript extensions other than `.tsx` stay in plain mode, so a `.ts` type
202
+ * assertion (`<Foo>value`) is never mistaken for markup. Extension checks are case-insensitive.
203
+ */
204
+ function usesJsxSyntax(file, source) {
205
+ const lower = file.toLowerCase();
206
+ if (lower.endsWith('.jsx') || lower.endsWith('.tsx')) {
207
+ return true;
208
+ }
209
+ return /\.(?:js|mjs|cjs)$/.test(lower) && /<\/[A-Za-z]|\/>/.test(source);
210
+ }
211
+ /**
212
+ * Turn the internal configuration handoff into validated package roots.
213
+ *
214
+ * The entries come from configuration reading code, not from the trusted analyzer, so each one is
215
+ * re-validated with the same utility that classifies source specifiers. Builtins, relative or
216
+ * absolute paths, malformed scoped names, URIs, whitespace and version suffixes are dropped instead
217
+ * of being trusted as package names. Accepted entries collapse to their package root and are
218
+ * deduplicated case-sensitively; an omitted set behaves exactly like an empty one.
219
+ */
220
+ function normalizeConfigHints(hints) {
221
+ const names = new Set();
222
+ if (hints === undefined) {
223
+ return names;
224
+ }
225
+ for (const hint of hints) {
226
+ const classified = classifyPackageSpecifier(hint);
227
+ if (classified.kind === 'external') {
228
+ names.add(classified.packageName);
229
+ }
230
+ }
231
+ // Rebuilt from sorted names so iteration order never depends on the caller's set insertion order.
232
+ return new Set([...names].sort(compareNames));
233
+ }
135
234
  /**
136
235
  * Union of the names of every supplied list, sorted alphabetically.
137
236
  */
@@ -1 +1 @@
1
- {"version":3,"file":"analyzeProject.js","sourceRoot":"","sources":["../../src/core/analyzeProject.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyzeProject.js","sourceRoot":"","sources":["../../src/core/analyzeProject.ts"],"names":[],"mappings":"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"}