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
@@ -0,0 +1,22 @@
1
+ /** Exact identifier validation; analysis applies validated names only to final findings. */
2
+ import { ProjectConfigError } from './projectConfigError.js';
3
+ const COMPONENT = '[A-Za-z0-9][A-Za-z0-9._-]*';
4
+ const IDENTIFIER = new RegExp(`^(?:${COMPONENT}|@${COMPONENT}/${COMPONENT})$`, 'u');
5
+ /** Shared exact-root grammar for dependency exclusions and explanation input; no normalization. */
6
+ export function isExactPackageRoot(name) {
7
+ return name.length <= 214 && IDENTIFIER.exec(name)?.[0] === name;
8
+ }
9
+ /**
10
+ * Preserve exact case and spelling; validate whole entries before sorting/deduplicating.
11
+ * This bounded grammar is independent of source subpath normalization and builtin classification.
12
+ * configPath is diagnostic context only. No inventory, filesystem or registry is consulted.
13
+ */
14
+ export function normalizeIgnoreDependencies(rawNames, configPath) {
15
+ for (const [index, name] of rawNames.entries()) {
16
+ if (!isExactPackageRoot(name)) {
17
+ throw new ProjectConfigError(`${configPath} field ignoreDependencies[${String(index)}] must be an exact package root (name or @scope/name), at most 214 characters; components must start with ASCII alphanumeric and contain only ASCII alphanumeric, '.', '_' or '-'`, 'invalid-shape');
18
+ }
19
+ }
20
+ return Object.freeze([...new Set(rawNames)].sort());
21
+ }
22
+ //# sourceMappingURL=ignoreDependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignoreDependencies.js","sourceRoot":"","sources":["../../src/config/ignoreDependencies.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,MAAM,SAAS,GAAG,4BAA4B,CAAC;AAC/C,MAAM,UAAU,GAAG,IAAI,MAAM,CAAC,OAAO,SAAS,KAAK,SAAS,IAAI,SAAS,IAAI,EAAE,GAAG,CAAC,CAAC;AAEpF,mGAAmG;AACnG,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CACzC,QAA2B,EAC3B,UAAkB;IAElB,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/C,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,kBAAkB,CAC1B,GAAG,UAAU,6BAA6B,MAAM,CAAC,KAAK,CAAC,mLAAmL,EAC1O,eAAe,CAChB,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Validate every raw rule before returning a normalized, sorted, deduplicated snapshot. Both slash
3
+ * spellings are config separators on every host. No rule destination is probed or resolved.
4
+ * configPath is diagnostic context supplied by the caller, not a file to read here.
5
+ */
6
+ export declare function normalizeIgnorePaths(rawRules: readonly string[], configPath: string): readonly string[];
7
+ /**
8
+ * Compare a canonical '/'-separated project-relative discovery path against validated rules.
9
+ * The caller converts native discovery separators; this matcher does not resolve or normalize
10
+ * candidate filenames. Matching is case-sensitive, extension-independent and segment-bounded.
11
+ */
12
+ export declare function matchesIgnoredPath(projectRelativePath: string, normalizedRules: readonly string[]): boolean;
13
+ //# sourceMappingURL=ignorePaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignorePaths.d.ts","sourceRoot":"","sources":["../../src/config/ignorePaths.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,UAAU,EAAE,MAAM,GACjB,SAAS,MAAM,EAAE,CA8BnB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,mBAAmB,EAAE,MAAM,EAC3B,eAAe,EAAE,SAAS,MAAM,EAAE,GACjC,OAAO,CAIT"}
@@ -0,0 +1,47 @@
1
+ /** Literal path policy shared by configuration validation and source discovery. */
2
+ import { ProjectConfigError } from './projectConfigError.js';
3
+ /**
4
+ * Validate every raw rule before returning a normalized, sorted, deduplicated snapshot. Both slash
5
+ * spellings are config separators on every host. No rule destination is probed or resolved.
6
+ * configPath is diagnostic context supplied by the caller, not a file to read here.
7
+ */
8
+ export function normalizeIgnorePaths(rawRules, configPath) {
9
+ const normalized = rawRules.map((rule, index) => {
10
+ const fail = (reason) => {
11
+ throw new ProjectConfigError(`${configPath} field ignorePaths[${String(index)}] ${reason}`, 'invalid-shape');
12
+ };
13
+ // Check the original spelling: normalization must never hide a rooted or drive-relative rule.
14
+ if (rule.startsWith('/') || rule.startsWith('\\') || /^[A-Za-z]:/.test(rule)) {
15
+ fail('must be project-relative; absolute, rooted, UNC and drive-relative paths are unsupported');
16
+ }
17
+ if (rule !== rule.trim())
18
+ fail('must not have leading or trailing whitespace');
19
+ if (rule.includes(':'))
20
+ fail('must not contain a colon');
21
+ if (/\p{Cc}/u.test(rule))
22
+ fail('must not contain a control character');
23
+ if (['*', '?', '[', ']', '{', '}', '!'].some((character) => rule.includes(character))) {
24
+ fail('contains unsupported pattern characters; use a literal file or subtree path');
25
+ }
26
+ const segments = rule.replaceAll('\\', '/').split('/');
27
+ if (segments.includes('..'))
28
+ fail('must not contain a .. traversal segment');
29
+ const result = segments.filter((segment) => segment !== '' && segment !== '.').join('/');
30
+ if (result.length === 0)
31
+ fail('must name a nonempty path, not the project root');
32
+ // Dot/separator removal can expose whitespace that was interior in the raw spelling.
33
+ if (result !== result.trim())
34
+ fail('must not have leading or trailing whitespace after normalization');
35
+ return result;
36
+ });
37
+ return Object.freeze([...new Set(normalized)].sort());
38
+ }
39
+ /**
40
+ * Compare a canonical '/'-separated project-relative discovery path against validated rules.
41
+ * The caller converts native discovery separators; this matcher does not resolve or normalize
42
+ * candidate filenames. Matching is case-sensitive, extension-independent and segment-bounded.
43
+ */
44
+ export function matchesIgnoredPath(projectRelativePath, normalizedRules) {
45
+ return normalizedRules.some((rule) => projectRelativePath === rule || projectRelativePath.startsWith(`${rule}/`));
46
+ }
47
+ //# sourceMappingURL=ignorePaths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignorePaths.js","sourceRoot":"","sources":["../../src/config/ignorePaths.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAA2B,EAC3B,UAAkB;IAElB,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC9C,MAAM,IAAI,GAAG,CAAC,MAAc,EAAS,EAAE;YACrC,MAAM,IAAI,kBAAkB,CAC1B,GAAG,UAAU,sBAAsB,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,EAAE,EAC7D,eAAe,CAChB,CAAC;QACJ,CAAC,CAAC;QACF,8FAA8F;QAC9F,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7E,IAAI,CACF,0FAA0F,CAC3F,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE;YAAE,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC/E,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACzD,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACvE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YACtF,IAAI,CAAC,6EAA6E,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvD,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,yCAAyC,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,IAAI,CAAC,iDAAiD,CAAC,CAAC;QACjF,qFAAqF;QACrF,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI,EAAE;YAC1B,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAC3E,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,mBAA2B,EAC3B,eAAkC;IAElC,OAAO,eAAe,CAAC,IAAI,CACzB,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,KAAK,IAAI,IAAI,mBAAmB,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CACrF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type ProjectConfigErrorCode = 'unreadable' | 'invalid-json' | 'invalid-shape';
2
+ /** Operational configuration failure; broken present data must never become empty defaults. */
3
+ export declare class ProjectConfigError extends Error {
4
+ readonly code: ProjectConfigErrorCode;
5
+ constructor(message: string, code: ProjectConfigErrorCode, cause?: unknown);
6
+ }
7
+ //# sourceMappingURL=projectConfigError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectConfigError.d.ts","sourceRoot":"","sources":["../../src/config/projectConfigError.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG,cAAc,GAAG,eAAe,CAAC;AAErF,+FAA+F;AAC/F,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;gBAE1B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,CAAC,EAAE,OAAO;CAK3E"}
@@ -0,0 +1,10 @@
1
+ /** Operational configuration failure; broken present data must never become empty defaults. */
2
+ export class ProjectConfigError extends Error {
3
+ code;
4
+ constructor(message, code, cause) {
5
+ super(message, cause === undefined ? undefined : { cause });
6
+ this.name = 'ProjectConfigError';
7
+ this.code = code;
8
+ }
9
+ }
10
+ //# sourceMappingURL=projectConfigError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectConfigError.js","sourceRoot":"","sources":["../../src/config/projectConfigError.ts"],"names":[],"mappings":"AAEA,+FAA+F;AAC/F,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,CAAyB;IAEtC,YAAY,OAAe,EAAE,IAA4B,EAAE,KAAe;QACxE,KAAK,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ export type RawProjectConfig = {
2
+ readonly ignorePaths: readonly string[];
3
+ readonly ignoreDependencies: readonly string[];
4
+ };
5
+ export { ProjectConfigError, type ProjectConfigErrorCode } from './projectConfigError.js';
6
+ /**
7
+ * Read exactly the canonical config entry in the selected root. No parents, alternatives or rule
8
+ * destinations are consulted. Only absence is defaults. Present non-regular/unreadable entries and
9
+ * malformed documents fail as a whole. Existing root errors use the shared SourceFilesError guard.
10
+ *
11
+ * Strings retain their original spelling, order and duplicates for later semantic validators.
12
+ * A single leading UTF-8 BOM is accepted; all remaining syntax is native strict JSON.parse.
13
+ * Stable entry checks do not claim adversarial protection against replacement between I/O calls.
14
+ */
15
+ export declare function readRawProjectConfig(projectRoot: string): Promise<RawProjectConfig>;
16
+ /** Validated internal snapshot; no policy is applied to discovery or findings here. */
17
+ export type ProjectConfig = {
18
+ readonly ignorePaths: readonly string[];
19
+ readonly ignoreDependencies: readonly string[];
20
+ };
21
+ /** Read once, validate all path/name rules, and return no partial configuration on failure. */
22
+ export declare function readProjectConfig(projectRoot: string): Promise<ProjectConfig>;
23
+ /** Per-scan policy and entry names; not an atomic filesystem snapshot or a global cache. */
24
+ export declare function readProjectConfigSnapshot(projectRoot: string): Promise<{
25
+ config: ProjectConfig;
26
+ rootEntries: readonly string[];
27
+ }>;
28
+ //# sourceMappingURL=readProjectConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readProjectConfig.d.ts","sourceRoot":"","sources":["../../src/config/readProjectConfig.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAI1F;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAEzF;AAyGD,uFAAuF;AACvF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD,CAAC;AAEF,+FAA+F;AAC/F,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAEnF;AAED,4FAA4F;AAC5F,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC,CAUpE"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Internal, root-only JSON configuration readers. The CLI loads readProjectConfig on scans only;
3
+ * only that reader returns semantically validated rules.
4
+ */
5
+ import { lstat, readFile, readdir } from 'node:fs/promises';
6
+ import { join, resolve } from 'node:path';
7
+ import { assertReadableRoot } from '../scanner/sourceFiles.js';
8
+ import { normalizeIgnoreDependencies } from './ignoreDependencies.js';
9
+ import { normalizeIgnorePaths } from './ignorePaths.js';
10
+ import { ProjectConfigError } from './projectConfigError.js';
11
+ export { ProjectConfigError } from './projectConfigError.js';
12
+ const CONFIG_FILENAME = 'depvitals.config.json';
13
+ /**
14
+ * Read exactly the canonical config entry in the selected root. No parents, alternatives or rule
15
+ * destinations are consulted. Only absence is defaults. Present non-regular/unreadable entries and
16
+ * malformed documents fail as a whole. Existing root errors use the shared SourceFilesError guard.
17
+ *
18
+ * Strings retain their original spelling, order and duplicates for later semantic validators.
19
+ * A single leading UTF-8 BOM is accepted; all remaining syntax is native strict JSON.parse.
20
+ * Stable entry checks do not claim adversarial protection against replacement between I/O calls.
21
+ */
22
+ export async function readRawProjectConfig(projectRoot) {
23
+ return (await readRawConfigWithEntries(projectRoot)).raw;
24
+ }
25
+ /** Preserve canonical-entry checks and errors while sharing this read's entry names. */
26
+ async function readRawConfigWithEntries(projectRoot) {
27
+ const root = resolve(projectRoot);
28
+ const path = join(root, CONFIG_FILENAME);
29
+ await assertReadableRoot(root);
30
+ let entries;
31
+ try {
32
+ // Exact entry-name comparison also enforces canonical casing on case-insensitive hosts.
33
+ entries = await readdir(root);
34
+ }
35
+ catch (error) {
36
+ throw unreadable(path, error);
37
+ }
38
+ if (!entries.includes(CONFIG_FILENAME))
39
+ return { raw: emptyConfig(), rootEntries: Object.freeze(entries) };
40
+ let info;
41
+ try {
42
+ info = await lstat(path);
43
+ }
44
+ catch (error) {
45
+ // The directory entry was already present, so disappearance is an error, not absence.
46
+ throw unreadable(path, error);
47
+ }
48
+ if (!info.isFile()) {
49
+ throw new ProjectConfigError(`${path} must be a regular file; symlinks and non-regular entries are not read`, 'unreadable');
50
+ }
51
+ let text;
52
+ try {
53
+ text = await readFile(path, 'utf8');
54
+ }
55
+ catch (error) {
56
+ throw unreadable(path, error);
57
+ }
58
+ let parsed;
59
+ try {
60
+ parsed = JSON.parse(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text);
61
+ }
62
+ catch (error) {
63
+ throw new ProjectConfigError(`${path} is not valid JSON`, 'invalid-json', error);
64
+ }
65
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
66
+ throw new ProjectConfigError(`${path} must contain a JSON object`, 'invalid-shape');
67
+ }
68
+ for (const key of Object.keys(parsed)) {
69
+ if (key !== 'ignorePaths' && key !== 'ignoreDependencies') {
70
+ throw new ProjectConfigError(`${path} has unsupported field ${JSON.stringify(key)}; only ignorePaths and ignoreDependencies are supported`, 'invalid-shape');
71
+ }
72
+ }
73
+ const config = parsed;
74
+ return {
75
+ raw: Object.freeze({
76
+ ignorePaths: readStrings(config['ignorePaths'], 'ignorePaths', path),
77
+ ignoreDependencies: readStrings(config['ignoreDependencies'], 'ignoreDependencies', path),
78
+ }),
79
+ rootEntries: Object.freeze(entries),
80
+ };
81
+ }
82
+ function readStrings(value, field, path) {
83
+ if (value === undefined)
84
+ return Object.freeze([]);
85
+ if (!Array.isArray(value)) {
86
+ throw new ProjectConfigError(`${path} field ${field} must be an array of strings`, 'invalid-shape');
87
+ }
88
+ const strings = [];
89
+ for (let index = 0; index < value.length; index++) {
90
+ const entry = value[index];
91
+ if (typeof entry !== 'string' || entry.trim().length === 0) {
92
+ throw new ProjectConfigError(`${path} field ${field}[${String(index)}] must be a nonempty, non-whitespace string`, 'invalid-shape');
93
+ }
94
+ strings.push(entry);
95
+ }
96
+ return Object.freeze(strings);
97
+ }
98
+ function emptyConfig() {
99
+ return Object.freeze({ ignorePaths: Object.freeze([]), ignoreDependencies: Object.freeze([]) });
100
+ }
101
+ function unreadable(path, cause) {
102
+ return new ProjectConfigError(`Could not read ${CONFIG_FILENAME} at ${path}`, 'unreadable', cause);
103
+ }
104
+ /** Read once, validate all path/name rules, and return no partial configuration on failure. */
105
+ export async function readProjectConfig(projectRoot) {
106
+ return (await readProjectConfigSnapshot(projectRoot)).config;
107
+ }
108
+ /** Per-scan policy and entry names; not an atomic filesystem snapshot or a global cache. */
109
+ export async function readProjectConfigSnapshot(projectRoot) {
110
+ const { raw, rootEntries } = await readRawConfigWithEntries(projectRoot);
111
+ const path = join(resolve(projectRoot), CONFIG_FILENAME);
112
+ return {
113
+ config: Object.freeze({
114
+ ignorePaths: normalizeIgnorePaths(raw.ignorePaths, path),
115
+ ignoreDependencies: normalizeIgnoreDependencies(raw.ignoreDependencies, path),
116
+ }),
117
+ rootEntries,
118
+ };
119
+ }
120
+ //# sourceMappingURL=readProjectConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readProjectConfig.js","sourceRoot":"","sources":["../../src/config/readProjectConfig.ts"],"names":[],"mappings":"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"}
@@ -46,6 +46,9 @@
46
46
  *
47
47
  * Peer/optional declarations suppress false missing results through `declaredDependencyNames`.
48
48
  */
49
+ import { type ProjectManifest } from '../scanner/projectManifest.js';
50
+ import type { ScanContext } from './scanContext.js';
51
+ import { type FindingCategory, type PackageFact } from './evidence.js';
49
52
  /**
50
53
  * The structured outcome of a dependency analysis.
51
54
  *
@@ -64,6 +67,17 @@ export type AnalysisResult = {
64
67
  /** External packages referenced by source but not declared anywhere, sorted alphabetically. */
65
68
  missingDependencies: readonly string[];
66
69
  };
70
+ /** Internal categories before or after dependency policy; no additional finding kind. */
71
+ export type AnalysisFindings = Pick<AnalysisResult, 'unusedDependencies' | 'unusedDevDependencies' | 'missingDependencies'>;
72
+ /** Complete internal scan facts. Presentation projects explicit fields instead of serializing this object. */
73
+ export type DetailedAnalysisResult = {
74
+ readonly projectRoot: string;
75
+ readonly manifest: ProjectManifest;
76
+ readonly config: ScanContext['config'];
77
+ readonly underlyingFindings: AnalysisFindings;
78
+ readonly findings: AnalysisFindings;
79
+ readonly packages: readonly PackageFact[];
80
+ };
67
81
  /**
68
82
  * Internal handoff for package names recognized by a validated static configuration reader.
69
83
  *
@@ -92,6 +106,10 @@ export type AnalysisOptions = {
92
106
  * rule is active yet, so the default keeps every report byte-for-byte identical.
93
107
  */
94
108
  readonly configUsedNames?: ConfigUsageHints | undefined;
109
+ /** Validated, normalized literal paths excluded from source discovery only; omitted is empty. */
110
+ readonly ignorePaths?: readonly string[] | undefined;
111
+ /** Validated exact package roots omitted from final findings only; never usage evidence. */
112
+ readonly ignoreDependencies?: readonly string[] | undefined;
95
113
  };
96
114
  /**
97
115
  * Why the analysis could not complete.
@@ -121,10 +139,31 @@ export declare class AnalysisError extends Error {
121
139
  * project is never written to.
122
140
  *
123
141
  * @param projectRoot - Directory to analyze.
124
- * @param options - Optional {@link ConfigUsageHints}; an omitted or empty set changes nothing.
142
+ * @param options - Optional static tool hints and validated source exclusions; omitted inputs change nothing.
125
143
  * @throws {AnalysisError} when a discovered source file cannot be read or cannot be safely analyzed.
126
144
  * @throws {ProjectManifestError} when the manifest is missing, unreadable, invalid or malformed.
127
145
  * @throws {SourceFilesError} when the root is missing, is not a directory, or cannot be read.
128
146
  */
129
147
  export declare function analyzeProject(projectRoot: string, options?: AnalysisOptions): Promise<AnalysisResult>;
148
+ /** Keep the small CLI/legacy result projection while collecting the same complete scan facts. */
149
+ export declare function analyzeProjectWithContext(context: ScanContext): Promise<AnalysisResult>;
150
+ /** Detailed analysis accepts eligible typed facts only, never the legacy names-only hint seam. */
151
+ export declare function analyzeProjectDetailed(context: ScanContext): Promise<DetailedAnalysisResult>;
152
+ /** Pure legacy projection; no collection, reclassification or input reads. */
153
+ export declare function projectAnalysisResult(result: DetailedAnalysisResult): AnalysisResult;
154
+ /** Internal package-local outcome; effective scan policy remains available to later reporters. */
155
+ export type PackageExplanation = {
156
+ readonly projectRoot: string;
157
+ readonly config: DetailedAnalysisResult['config'];
158
+ readonly findings: AnalysisFindings;
159
+ readonly counts: Readonly<Record<FindingCategory, number>>;
160
+ readonly packages: readonly [PackageFact];
161
+ readonly query: {
162
+ readonly packageName: string;
163
+ readonly known: boolean;
164
+ };
165
+ readonly exitCode: 0 | 1;
166
+ };
167
+ /** Project only completed scan facts. This function performs no collection or resolution. */
168
+ export declare function projectPackageExplanation(result: DetailedAnalysisResult, packageName: string): PackageExplanation;
130
169
  //# sourceMappingURL=analyzeProject.d.ts.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"analyzeProject.d.ts","sourceRoot":"","sources":["../../src/core/analyzeProject.ts"],"names":[],"mappings":"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"}