depvitals 0.3.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.
- package/README.md +72 -3
- package/dist/cli/entry.js +8 -21
- package/dist/cli/entry.js.map +1 -1
- package/dist/cli/parseCliArgs.d.ts +5 -2
- package/dist/cli/parseCliArgs.d.ts.map +1 -1
- package/dist/cli/parseCliArgs.js +51 -36
- package/dist/cli/parseCliArgs.js.map +1 -1
- package/dist/cli/runCli.d.ts +4 -5
- package/dist/cli/runCli.d.ts.map +1 -1
- package/dist/cli/runCli.js +39 -49
- package/dist/cli/runCli.js.map +1 -1
- package/dist/config/ignoreDependencies.d.ts +2 -0
- package/dist/config/ignoreDependencies.d.ts.map +1 -1
- package/dist/config/ignoreDependencies.js +5 -1
- package/dist/config/ignoreDependencies.js.map +1 -1
- package/dist/config/readProjectConfig.d.ts +5 -0
- package/dist/config/readProjectConfig.d.ts.map +1 -1
- package/dist/config/readProjectConfig.js +24 -10
- package/dist/config/readProjectConfig.js.map +1 -1
- package/dist/core/analyzeProject.d.ts +35 -0
- package/dist/core/analyzeProject.d.ts.map +1 -1
- package/dist/core/analyzeProject.js +161 -25
- package/dist/core/analyzeProject.js.map +1 -1
- package/dist/core/evidence.d.ts +67 -0
- package/dist/core/evidence.d.ts.map +1 -0
- package/dist/core/evidence.js +115 -0
- package/dist/core/evidence.js.map +1 -0
- package/dist/core/scanContext.d.ts +20 -0
- package/dist/core/scanContext.d.ts.map +1 -0
- package/dist/core/scanContext.js +43 -0
- package/dist/core/scanContext.js.map +1 -0
- package/dist/detectors/eslintManifestConfig.d.ts +18 -0
- package/dist/detectors/eslintManifestConfig.d.ts.map +1 -1
- package/dist/detectors/eslintManifestConfig.js +55 -76
- package/dist/detectors/eslintManifestConfig.js.map +1 -1
- package/dist/detectors/eslintRcJsonConfig.d.ts +8 -2
- package/dist/detectors/eslintRcJsonConfig.d.ts.map +1 -1
- package/dist/detectors/eslintRcJsonConfig.js +25 -11
- package/dist/detectors/eslintRcJsonConfig.js.map +1 -1
- package/dist/detectors/jestManifestConfig.d.ts +15 -3
- package/dist/detectors/jestManifestConfig.d.ts.map +1 -1
- package/dist/detectors/jestManifestConfig.js +57 -79
- package/dist/detectors/jestManifestConfig.js.map +1 -1
- package/dist/reporters/jsonReporter.d.ts +39 -0
- package/dist/reporters/jsonReporter.d.ts.map +1 -0
- package/dist/reporters/jsonReporter.js +91 -0
- package/dist/reporters/jsonReporter.js.map +1 -0
- package/dist/reporters/terminalReporter.d.ts +15 -4
- package/dist/reporters/terminalReporter.d.ts.map +1 -1
- package/dist/reporters/terminalReporter.js +64 -4
- package/dist/reporters/terminalReporter.js.map +1 -1
- package/dist/scanner/moduleSpecifiers.d.ts +10 -0
- package/dist/scanner/moduleSpecifiers.d.ts.map +1 -1
- package/dist/scanner/moduleSpecifiers.js +46 -8
- package/dist/scanner/moduleSpecifiers.js.map +1 -1
- package/dist/scanner/projectManifest.d.ts +9 -0
- package/dist/scanner/projectManifest.d.ts.map +1 -1
- package/dist/scanner/projectManifest.js +7 -1
- package/dist/scanner/projectManifest.js.map +1 -1
- package/dist/scanner/scriptUsage.d.ts +13 -0
- package/dist/scanner/scriptUsage.d.ts.map +1 -1
- package/dist/scanner/scriptUsage.js +102 -32
- package/dist/scanner/scriptUsage.js.map +1 -1
- package/dist/scanner/sourceFiles.d.ts +5 -0
- package/dist/scanner/sourceFiles.d.ts.map +1 -1
- package/dist/scanner/sourceFiles.js +7 -0
- package/dist/scanner/sourceFiles.js.map +1 -1
- package/package.json +4 -2
- package/schemas/README.md +47 -0
- package/schemas/examples/README.md +27 -0
- package/schemas/examples/explain-excluded.json +53 -0
- package/schemas/examples/explain-missing.json +65 -0
- package/schemas/examples/explain-node-preload.json +70 -0
- package/schemas/examples/explain-unknown.json +53 -0
- package/schemas/examples/scan-clean.json +40 -0
- package/schemas/examples/scan-findings.json +80 -0
- package/schemas/report-v1.schema.json +376 -0
package/README.md
CHANGED
|
@@ -11,6 +11,15 @@ DepVitals is a lightweight, [Depcheck](https://github.com/depcheck/depcheck)-ins
|
|
|
11
11
|
|
|
12
12
|
Designed for fast, zero-config dependency checks during development, maintenance and CI, its CLI can also be used in scripts and AI coding-agent workflows. It analyzes one project root at a time; review findings before changing `package.json`.
|
|
13
13
|
|
|
14
|
+
## What's new in v0.4.0
|
|
15
|
+
|
|
16
|
+
Export a versioned JSON report, explain why a package was used or flagged, and run a
|
|
17
|
+
[version-pinned CI check](#ci-with-a-fixed-version) that preserves reports and diagnostics.
|
|
18
|
+
Explanations point to supported source, script and configuration evidence. Supported explicit
|
|
19
|
+
Node preloads now count as script usage for declared packages. See the
|
|
20
|
+
[v0.4.0 release notes](https://github.com/MatiasRicardi/depvitals/blob/main/docs/releases/v0.4.0.md)
|
|
21
|
+
for compatibility details and remaining limits.
|
|
22
|
+
|
|
14
23
|
## Quick start
|
|
15
24
|
|
|
16
25
|
Requires **Node.js 22.13.0 or newer**. Scan the current directory containing `package.json`, or pass a project path:
|
|
@@ -40,10 +49,70 @@ These commands use the npm release. Documentation on `main` can describe unrelea
|
|
|
40
49
|
| Unused devDependencies | The same check for `devDependencies`. |
|
|
41
50
|
| Missing dependencies | Referenced by supported source imports/exports/requires, but undeclared in all groups. |
|
|
42
51
|
|
|
43
|
-
**Missing means undeclared
|
|
52
|
+
**Missing means undeclared.** DepVitals checks the manifest and supported evidence. Review each unused finding before editing your manifest. Peer and optional dependencies suppress missing findings and are never reported unused.
|
|
44
53
|
|
|
45
54
|
Reports use stdout; operational errors use stderr without a partial report. Exit **0** means clean/help/version; **1** means findings/errors. An optional update notice can use stderr without changing the status.
|
|
46
55
|
|
|
56
|
+
## JSON reports and package explanations
|
|
57
|
+
|
|
58
|
+
These examples require **v0.4.0 or newer**. To try them from a checkout, use
|
|
59
|
+
`node /path/to/depvitals/dist/cli/index.js` in place of `depvitals` after
|
|
60
|
+
[building the development checkout](https://github.com/MatiasRicardi/depvitals/blob/main/CONTRIBUTING.md#local-setup).
|
|
61
|
+
|
|
62
|
+
For example, suppose `./project` declares `unused` as a dependency and `unused-tool` as a
|
|
63
|
+
devDependency, and `src/index.ts` contains `import item from 'missing';`.
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
depvitals ./project
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
DepVitals
|
|
71
|
+
|
|
72
|
+
Unused dependencies (1)
|
|
73
|
+
unused
|
|
74
|
+
|
|
75
|
+
Unused devDependencies (1)
|
|
76
|
+
unused-tool
|
|
77
|
+
|
|
78
|
+
Missing dependencies (1)
|
|
79
|
+
missing
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Run these commands from outside the selected project.
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
depvitals ./project --format json > depvitals-report.json
|
|
86
|
+
depvitals ./project --explain missing
|
|
87
|
+
depvitals --format json --explain missing ./project
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
1. Start with a full scan. This example reports findings and returns exit 1, including when stdout
|
|
91
|
+
is redirected to JSON.
|
|
92
|
+
2. Explain the package and check its evidence. Here `missing` is undeclared and its explanation
|
|
93
|
+
points to the import in `src/index.ts:1:18`. Check which package owns the file and whether the
|
|
94
|
+
import belongs in that project.
|
|
95
|
+
3. For an unused finding, review actual uses and test the project before changing the manifest.
|
|
96
|
+
Use an exclusion only to record a deliberate scope or reporting decision.
|
|
97
|
+
|
|
98
|
+
An explanation reports one exact package. Its exit status follows that package's result. Use a full
|
|
99
|
+
scan to enforce a project-wide check. The v0.4.0 [report schema and examples](https://github.com/MatiasRicardi/depvitals/blob/main/schemas/README.md)
|
|
100
|
+
are shipped in the npm package under `schemas/`. See the [CLI and report contract](https://github.com/MatiasRicardi/depvitals/blob/main/docs/reference.md#cli-and-json-reports).
|
|
101
|
+
|
|
102
|
+
## CI with a fixed version
|
|
103
|
+
|
|
104
|
+
Install v0.4.0 from npm as an exact development dependency. If you are testing a candidate before
|
|
105
|
+
publication, use the local tarball procedure in the CI recipe below.
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
npm install --save-dev --save-exact depvitals@0.4.0
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Commit the generated lockfile and use `"check:dependencies": "depvitals --format json"` in the
|
|
112
|
+
manifest's `scripts`. The [tested CI recipe](https://github.com/MatiasRicardi/depvitals/blob/main/docs/examples/ci/README.md)
|
|
113
|
+
captures the installed executable's report, diagnostics and status. It preserves those artifacts
|
|
114
|
+
on failure.
|
|
115
|
+
|
|
47
116
|
## Optional configuration
|
|
48
117
|
|
|
49
118
|
Requires DepVitals **0.3.0 or newer**. Create `depvitals.config.json` at the scanned project root:
|
|
@@ -59,8 +128,8 @@ Requires DepVitals **0.3.0 or newer**. Create `depvitals.config.json` at the sca
|
|
|
59
128
|
|
|
60
129
|
## Scope and privacy
|
|
61
130
|
|
|
62
|
-
Scans cover JS/TS, JSX/TSX and declaration files, literal ESM/CommonJS references, supported script commands and bounded ESLint/Jest hints. Only source evidence creates missing findings. There is no workspace aggregation, alias/tsconfig resolution, blanket `@types` inference
|
|
131
|
+
Scans cover JS/TS, JSX/TSX and declaration files, literal ESM/CommonJS references, supported script commands and bounded ESLint/Jest hints. Only source evidence creates missing findings. There is no workspace aggregation, alias/tsconfig resolution, blanket `@types` inference or automatic fix; see [supported patterns and limits](https://github.com/MatiasRicardi/depvitals/blob/main/docs/reference.md).
|
|
63
132
|
|
|
64
|
-
Core analysis is offline and never executes or modifies the project or inspects `node_modules`. After completed interactive scans, an optional update check requests public metadata for **DepVitals itself**, caches it outside the project and uploads no project data. CI, non-TTY, help/version and failed scans skip it. Set `DEPVITALS_NO_UPDATE_CHECK=1` to disable it; see [privacy and shell examples](https://github.com/MatiasRicardi/depvitals/blob/main/docs/reference.md#update-notice-and-privacy).
|
|
133
|
+
Core analysis is offline and never executes or modifies the project or inspects `node_modules`. After completed interactive scans, an optional update check requests public metadata for **DepVitals itself**, caches it outside the project and uploads no project data. CI, non-TTY, help/version and failed scans skip it. In v0.4.0, JSON scans and all explanations also skip it before any cache or network access. Set `DEPVITALS_NO_UPDATE_CHECK=1` to disable it; see [privacy and shell examples](https://github.com/MatiasRicardi/depvitals/blob/main/docs/reference.md#update-notice-and-privacy).
|
|
65
134
|
|
|
66
135
|
[Technical reference](https://github.com/MatiasRicardi/depvitals/blob/main/docs/reference.md) · [Contributing](https://github.com/MatiasRicardi/depvitals/blob/main/CONTRIBUTING.md) · [Changelog](https://github.com/MatiasRicardi/depvitals/blob/main/CHANGELOG.md) · [MIT license](https://github.com/MatiasRicardi/depvitals/blob/main/LICENSE)
|
package/dist/cli/entry.js
CHANGED
|
@@ -56,10 +56,17 @@ export async function runCliEntry(args, options) {
|
|
|
56
56
|
* stand on their own. An unexpected type is discarded rather than printed.
|
|
57
57
|
*/
|
|
58
58
|
async function collectNotice(args, result, options) {
|
|
59
|
+
const command = parseCliArgs(args, options.cwd);
|
|
60
|
+
if (command.kind !== 'scan' ||
|
|
61
|
+
command.format === 'json' ||
|
|
62
|
+
command.explain !== undefined ||
|
|
63
|
+
result.stdout.length === 0 ||
|
|
64
|
+
result.stderr.length > 0)
|
|
65
|
+
return undefined;
|
|
59
66
|
try {
|
|
60
67
|
const collect = options.updateNotice ?? collectUpdateNotice;
|
|
61
68
|
const notice = await collect({
|
|
62
|
-
commandKind:
|
|
69
|
+
commandKind: 'scan',
|
|
63
70
|
currentVersion: options.version,
|
|
64
71
|
env: options.env,
|
|
65
72
|
stdoutTTY: options.stdout.isTTY === true,
|
|
@@ -72,24 +79,4 @@ async function collectNotice(args, result, options) {
|
|
|
72
79
|
return undefined;
|
|
73
80
|
}
|
|
74
81
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Classify the invocation in the vocabulary the eligibility predicate expects.
|
|
77
|
-
*
|
|
78
|
-
* The argument parser is the single source of truth for `help`, `version` and usage errors, so it is
|
|
79
|
-
* consulted again here (a pure, deterministic function of the same arguments and the same working
|
|
80
|
-
* directory) instead of widening {@link CliResult}, whose three keys are pinned by the contract gate.
|
|
81
|
-
* A parsed `scan` is then split by what the scan produced: {@link runCli} renders a report whenever
|
|
82
|
-
* the scan completed - clean or with findings - and leaves stdout empty for an operational failure,
|
|
83
|
-
* so an empty report means the scan never finished and nothing may be suggested to the user.
|
|
84
|
-
*
|
|
85
|
-
* Only the literal kind crosses the boundary; the parsed project path stays here and is never passed
|
|
86
|
-
* into notifier code.
|
|
87
|
-
*/
|
|
88
|
-
function commandKindOf(args, cwd, result) {
|
|
89
|
-
const command = parseCliArgs(args, cwd);
|
|
90
|
-
if (command.kind !== 'scan') {
|
|
91
|
-
return command.kind;
|
|
92
|
-
}
|
|
93
|
-
return result.stdout.length === 0 ? 'scan-failure' : 'scan';
|
|
94
|
-
}
|
|
95
82
|
//# sourceMappingURL=entry.js.map
|
package/dist/cli/entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/cli/entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EACL,mBAAmB,GAGpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAmC,MAAM,EAAE,MAAM,aAAa,CAAC;AA2BtE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAuB,EACvB,OAAwB;IAExB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAElF,sEAAsE;IACtE,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAE1D,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,MAAM,CAAC,QAAQ,CAAC;AACzB,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,aAAa,CAC1B,IAAuB,EACvB,MAAiB,EACjB,OAAwB;IAExB,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/cli/entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EACL,mBAAmB,GAGpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAmC,MAAM,EAAE,MAAM,aAAa,CAAC;AA2BtE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAuB,EACvB,OAAwB;IAExB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAElF,sEAAsE;IACtE,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAE1D,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,MAAM,CAAC,QAAQ,CAAC;AACzB,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,aAAa,CAC1B,IAAuB,EACvB,MAAiB,EACjB,OAAwB;IAExB,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAChD,IACE,OAAO,CAAC,IAAI,KAAK,MAAM;QACvB,OAAO,CAAC,MAAM,KAAK,MAAM;QACzB,OAAO,CAAC,OAAO,KAAK,SAAS;QAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAExB,OAAO,SAAS,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,IAAI,mBAAmB,CAAC;QAE5D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC;YAC3B,WAAW,EAAE,MAAM;YACnB,cAAc,EAAE,OAAO,CAAC,OAAO;YAC/B,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI;YACxC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI;SACzC,CAAC,CAAC;QAEH,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;QAC/D,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pure, deterministic argument parsing
|
|
2
|
+
* Pure, deterministic CLI argument parsing.
|
|
3
3
|
*
|
|
4
4
|
* This module only validates the argument shape and resolves the selected project path. It never
|
|
5
5
|
* touches the filesystem, never calls the analyzer, and never accesses `process`, so the parsing
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* - no arguments -> scan the injected `cwd`
|
|
10
10
|
* - exactly one positional -> scan the resolved project directory
|
|
11
11
|
* - exactly one meta flag -> help or version (exit 0, no scan)
|
|
12
|
-
* -
|
|
12
|
+
* - separated format/explain options may surround the single project path
|
|
13
|
+
* - malformed or unsupported shapes produce a deterministic error message
|
|
13
14
|
*
|
|
14
15
|
* `--help`/`-h`/`--version`/`-v` must stay standalone: combining them with any other token, or
|
|
15
16
|
* combining them with each other, is rejected rather than given precedence.
|
|
@@ -22,6 +23,8 @@ export type ParsedCommand = {
|
|
|
22
23
|
} | {
|
|
23
24
|
kind: 'scan';
|
|
24
25
|
projectPath: string;
|
|
26
|
+
format?: 'terminal' | 'json';
|
|
27
|
+
explain?: string;
|
|
25
28
|
} | {
|
|
26
29
|
kind: 'error';
|
|
27
30
|
message: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseCliArgs.d.ts","sourceRoot":"","sources":["../../src/cli/parseCliArgs.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"parseCliArgs.d.ts","sourceRoot":"","sources":["../../src/cli/parseCliArgs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,wDAAwD;AACxD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACrF;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAiBvC;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,CA+ChF"}
|
package/dist/cli/parseCliArgs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pure, deterministic argument parsing
|
|
2
|
+
* Pure, deterministic CLI argument parsing.
|
|
3
3
|
*
|
|
4
4
|
* This module only validates the argument shape and resolves the selected project path. It never
|
|
5
5
|
* touches the filesystem, never calls the analyzer, and never accesses `process`, so the parsing
|
|
@@ -9,12 +9,15 @@
|
|
|
9
9
|
* - no arguments -> scan the injected `cwd`
|
|
10
10
|
* - exactly one positional -> scan the resolved project directory
|
|
11
11
|
* - exactly one meta flag -> help or version (exit 0, no scan)
|
|
12
|
-
* -
|
|
12
|
+
* - separated format/explain options may surround the single project path
|
|
13
|
+
* - malformed or unsupported shapes produce a deterministic error message
|
|
13
14
|
*
|
|
14
15
|
* `--help`/`-h`/`--version`/`-v` must stay standalone: combining them with any other token, or
|
|
15
16
|
* combining them with each other, is rejected rather than given precedence.
|
|
16
17
|
*/
|
|
17
18
|
import { resolve } from 'node:path';
|
|
19
|
+
import { isExactPackageRoot } from '../config/ignoreDependencies.js';
|
|
20
|
+
import { escapeControlCharacters } from '../reporters/terminalReporter.js';
|
|
18
21
|
/** Help/version flags that must be used alone. */
|
|
19
22
|
const HELP_FLAGS = new Set(['--help', '-h']);
|
|
20
23
|
/** Version flags that must be used alone. */
|
|
@@ -33,48 +36,60 @@ const TOO_MANY_ARGUMENTS = 'Too many arguments: expected at most one project pat
|
|
|
33
36
|
* the default project when no argument is supplied.
|
|
34
37
|
*/
|
|
35
38
|
export function parseCliArgs(args, cwd) {
|
|
36
|
-
if (args.length === 0)
|
|
37
|
-
return { kind: '
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const arg = args[0];
|
|
41
|
-
// An empty string (or the unreachable undefined) is an explicit, invalid positional: it must
|
|
42
|
-
// not silently become `cwd`.
|
|
43
|
-
if (arg === undefined || arg === '') {
|
|
44
|
-
return { kind: 'error', message: INVALID_EMPTY_PROJECT_PATH };
|
|
45
|
-
}
|
|
46
|
-
if (HELP_FLAGS.has(arg)) {
|
|
47
|
-
return { kind: 'help' };
|
|
48
|
-
}
|
|
49
|
-
if (VERSION_FLAGS.has(arg)) {
|
|
50
|
-
return { kind: 'version' };
|
|
51
|
-
}
|
|
52
|
-
// Anything else that is not an option is treated as a project path.
|
|
53
|
-
if (!arg.startsWith('-')) {
|
|
54
|
-
return { kind: 'scan', projectPath: resolve(cwd, arg) };
|
|
55
|
-
}
|
|
56
|
-
return { kind: 'error', message: unknownOptionMessage(arg) };
|
|
57
|
-
}
|
|
58
|
-
// Two or more tokens: help/version must remain standalone, so any meta flag combined with
|
|
59
|
-
// additional tokens (including other meta flags) is rejected as used alone.
|
|
39
|
+
if (args.length === 1 && HELP_FLAGS.has(args[0] ?? ''))
|
|
40
|
+
return { kind: 'help' };
|
|
41
|
+
if (args.length === 1 && VERSION_FLAGS.has(args[0] ?? ''))
|
|
42
|
+
return { kind: 'version' };
|
|
60
43
|
const metaFlag = args.find((arg) => HELP_FLAGS.has(arg) || VERSION_FLAGS.has(arg));
|
|
61
|
-
if (metaFlag !== undefined)
|
|
44
|
+
if (metaFlag !== undefined)
|
|
62
45
|
return { kind: 'error', message: metaFlagMustBeUsedAlone(metaFlag) };
|
|
46
|
+
let format;
|
|
47
|
+
let explain;
|
|
48
|
+
const paths = [];
|
|
49
|
+
const error = (body) => ({ kind: 'error', message: body + '\n' + HINT });
|
|
50
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
51
|
+
const arg = args[index] ?? '';
|
|
52
|
+
if (arg === '--format' || arg === '--explain') {
|
|
53
|
+
if ((arg === '--format' && format !== undefined) ||
|
|
54
|
+
(arg === '--explain' && explain !== undefined)) {
|
|
55
|
+
return error(`Option ${arg} may be specified only once.`);
|
|
56
|
+
}
|
|
57
|
+
const value = args[index + 1];
|
|
58
|
+
if (value === undefined || value === '' || value.startsWith('-'))
|
|
59
|
+
return error(`Option ${arg} requires a value.`);
|
|
60
|
+
if (arg === '--format') {
|
|
61
|
+
if (value !== 'terminal' && value !== 'json')
|
|
62
|
+
return error(`Invalid value for --format: ${escapeControlCharacters(value)}. Expected terminal or json.`);
|
|
63
|
+
format = value;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
if (!isExactPackageRoot(value))
|
|
67
|
+
return error('Invalid value for --explain: expected an exact package root (name or @scope/name), at most 214 characters.');
|
|
68
|
+
explain = value;
|
|
69
|
+
}
|
|
70
|
+
index += 1;
|
|
71
|
+
}
|
|
72
|
+
else if (arg.startsWith('-'))
|
|
73
|
+
return { kind: 'error', message: unknownOptionMessage(arg) };
|
|
74
|
+
else
|
|
75
|
+
paths.push(arg);
|
|
63
76
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
if (paths.length > 1)
|
|
78
|
+
return { kind: 'error', message: TOO_MANY_ARGUMENTS };
|
|
79
|
+
if (paths[0] === '')
|
|
80
|
+
return { kind: 'error', message: INVALID_EMPTY_PROJECT_PATH };
|
|
81
|
+
return {
|
|
82
|
+
kind: 'scan',
|
|
83
|
+
projectPath: paths[0] === undefined ? cwd : resolve(cwd, paths[0]),
|
|
84
|
+
...(format === undefined ? {} : { format }),
|
|
85
|
+
...(explain === undefined ? {} : { explain }),
|
|
86
|
+
};
|
|
72
87
|
}
|
|
73
88
|
/**
|
|
74
89
|
* The error message for an unrecognized option.
|
|
75
90
|
*/
|
|
76
91
|
function unknownOptionMessage(option) {
|
|
77
|
-
return `Unknown option: ${option}\n${HINT}`;
|
|
92
|
+
return `Unknown option: ${escapeControlCharacters(option)}\n${HINT}`;
|
|
78
93
|
}
|
|
79
94
|
/**
|
|
80
95
|
* The error message when a meta flag is combined with additional tokens.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseCliArgs.js","sourceRoot":"","sources":["../../src/cli/parseCliArgs.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"parseCliArgs.js","sourceRoot":"","sources":["../../src/cli/parseCliArgs.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/runCli.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Asynchronous CLI orchestration
|
|
2
|
+
* Asynchronous CLI orchestration.
|
|
3
3
|
*
|
|
4
4
|
* `runCli` turns parsed arguments into a plain {@link CliResult}. It performs no process I/O of its
|
|
5
5
|
* own: it never writes to stdout/stderr and never touches `process`. The thin adapter in
|
|
@@ -7,10 +7,9 @@
|
|
|
7
7
|
*
|
|
8
8
|
* The responsibilities here are:
|
|
9
9
|
* - delegate argument validation to the pure {@link parseCliArgs};
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
12
|
-
* -
|
|
13
|
-
* - render the report with the pure terminal reporter;
|
|
10
|
+
* - prepare one validated root/policy/detector context for the analyzer, which alone owns findings;
|
|
11
|
+
* - run one full detailed dependency scan;
|
|
12
|
+
* - render the selected terminal or JSON scan/query projection;
|
|
14
13
|
* - decide the scan exit code from `hasDependencyIssues`, not from the report string;
|
|
15
14
|
* - convert operational failures into a concise CLI error result.
|
|
16
15
|
*
|
package/dist/cli/runCli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runCli.d.ts","sourceRoot":"","sources":["../../src/cli/runCli.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"runCli.d.ts","sourceRoot":"","sources":["../../src/cli/runCli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAsBH;;;;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;AAoBF;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAa7F"}
|
package/dist/cli/runCli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Asynchronous CLI orchestration
|
|
2
|
+
* Asynchronous CLI orchestration.
|
|
3
3
|
*
|
|
4
4
|
* `runCli` turns parsed arguments into a plain {@link CliResult}. It performs no process I/O of its
|
|
5
5
|
* own: it never writes to stdout/stderr and never touches `process`. The thin adapter in
|
|
@@ -7,24 +7,23 @@
|
|
|
7
7
|
*
|
|
8
8
|
* The responsibilities here are:
|
|
9
9
|
* - delegate argument validation to the pure {@link parseCliArgs};
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
12
|
-
* -
|
|
13
|
-
* - render the report with the pure terminal reporter;
|
|
10
|
+
* - prepare one validated root/policy/detector context for the analyzer, which alone owns findings;
|
|
11
|
+
* - run one full detailed dependency scan;
|
|
12
|
+
* - render the selected terminal or JSON scan/query projection;
|
|
14
13
|
* - decide the scan exit code from `hasDependencyIssues`, not from the report string;
|
|
15
14
|
* - convert operational failures into a concise CLI error result.
|
|
16
15
|
*
|
|
17
16
|
* It deliberately does not implement any scanning or dependency-analysis logic: that stays in
|
|
18
17
|
* `src/core`, and the reporter stays in `src/reporters`.
|
|
19
18
|
*/
|
|
20
|
-
import {
|
|
21
|
-
import { AnalysisError,
|
|
22
|
-
import {
|
|
23
|
-
import { EslintRcJsonError
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import { loadProjectManifest, ProjectManifestError } from '../scanner/projectManifest.js';
|
|
19
|
+
import { ProjectConfigError } from '../config/readProjectConfig.js';
|
|
20
|
+
import { AnalysisError, analyzeProjectDetailed, projectAnalysisResult, projectPackageExplanation, } from '../core/analyzeProject.js';
|
|
21
|
+
import { createScanContext } from '../core/scanContext.js';
|
|
22
|
+
import { EslintRcJsonError } from '../detectors/eslintRcJsonConfig.js';
|
|
23
|
+
import { formatTerminalExplanation, formatTerminalReport, hasDependencyIssues, } from '../reporters/terminalReporter.js';
|
|
24
|
+
import { ProjectManifestError } from '../scanner/projectManifest.js';
|
|
27
25
|
import { SourceFilesError } from '../scanner/sourceFiles.js';
|
|
26
|
+
import { formatJsonReport } from '../reporters/jsonReporter.js';
|
|
28
27
|
import { parseCliArgs } from './parseCliArgs.js';
|
|
29
28
|
const HELP_MESSAGE = [
|
|
30
29
|
'DepVitals',
|
|
@@ -32,12 +31,14 @@ const HELP_MESSAGE = [
|
|
|
32
31
|
'A simple, lightweight dependency health checker for Node.js projects.',
|
|
33
32
|
'',
|
|
34
33
|
'Usage:',
|
|
35
|
-
' depvitals [project]',
|
|
34
|
+
' depvitals [project] [--format terminal|json] [--explain <package>]',
|
|
36
35
|
'',
|
|
37
36
|
'Arguments:',
|
|
38
37
|
' project Project directory to analyze (default: current directory)',
|
|
39
38
|
'',
|
|
40
39
|
'Options:',
|
|
40
|
+
' --format <format> Output format: terminal or json (default: terminal)',
|
|
41
|
+
' --explain <package> Explain one exact package root (default: full scan)',
|
|
41
42
|
' -h, --help Show help',
|
|
42
43
|
' -v, --version Show version',
|
|
43
44
|
].join('\n');
|
|
@@ -58,7 +59,7 @@ export async function runCli(args, options) {
|
|
|
58
59
|
case 'error':
|
|
59
60
|
return { exitCode: 1, stdout: '', stderr: `${command.message}\n` };
|
|
60
61
|
case 'scan':
|
|
61
|
-
return await runScan(command.
|
|
62
|
+
return await runScan(command, options.version);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
@@ -68,46 +69,35 @@ export async function runCli(args, options) {
|
|
|
68
69
|
* empty stdout). Any other thrown value is surfaced through a generic fallback message so the CLI
|
|
69
70
|
* never leaks internal error objects and never leaves an unhandled rejection.
|
|
70
71
|
*/
|
|
71
|
-
async function runScan(
|
|
72
|
-
|
|
72
|
+
async function runScan(command, version) {
|
|
73
|
+
const projectPath = command.projectPath;
|
|
73
74
|
try {
|
|
74
|
-
|
|
75
|
-
await
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return { exitCode: 1, stdout: '', stderr: `${error.message}\n` };
|
|
75
|
+
const context = await createScanContext(projectPath);
|
|
76
|
+
const detailed = await analyzeProjectDetailed(context);
|
|
77
|
+
if (command.explain !== undefined) {
|
|
78
|
+
const result = projectPackageExplanation(detailed, command.explain);
|
|
79
|
+
return {
|
|
80
|
+
exitCode: result.exitCode,
|
|
81
|
+
stdout: command.format === 'json'
|
|
82
|
+
? formatJsonReport({ mode: 'explain', result }, version)
|
|
83
|
+
: formatTerminalExplanation(result),
|
|
84
|
+
stderr: '',
|
|
85
|
+
};
|
|
86
86
|
}
|
|
87
|
+
const result = projectAnalysisResult(detailed);
|
|
87
88
|
return {
|
|
88
|
-
exitCode: 1,
|
|
89
|
-
stdout: ''
|
|
90
|
-
|
|
89
|
+
exitCode: hasDependencyIssues(result) ? 1 : 0,
|
|
90
|
+
stdout: command.format === 'json'
|
|
91
|
+
? formatJsonReport({ mode: 'scan', result: detailed }, version)
|
|
92
|
+
: formatTerminalReport(result),
|
|
93
|
+
stderr: '',
|
|
91
94
|
};
|
|
92
95
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
*
|
|
99
|
-
* Both legacy ESLint sources share one precedence computation: a hard barrier disables both, and
|
|
100
|
-
* otherwise `.eslintrc.json` wins over the `package.json#eslintConfig` block, so the two readers are
|
|
101
|
-
* mutually exclusive and the union never combines contradictory configuration. The `package.json#jest`
|
|
102
|
-
* reader is independent of the ESLint rules but obeys the same style of guard, producing nothing once
|
|
103
|
-
* a root `jest.config.*` file exists. The analyzer re-validates and sorts the merged hints, so no
|
|
104
|
-
* ordering is imposed here.
|
|
105
|
-
*/
|
|
106
|
-
async function collectConfigUsedNames(projectPath) {
|
|
107
|
-
const manifestNames = await findEslintManifestUsage(projectPath);
|
|
108
|
-
const eslintRcJsonNames = await findEslintRcJsonUsage(projectPath);
|
|
109
|
-
const jestNames = await findJestManifestUsage(projectPath);
|
|
110
|
-
return new Set([...manifestNames, ...eslintRcJsonNames, ...jestNames]);
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (isOperationalError(error))
|
|
98
|
+
return { exitCode: 1, stdout: '', stderr: `${error.message}\n` };
|
|
99
|
+
return { exitCode: 1, stdout: '', stderr: `${unexpectedErrorMessage(projectPath, error)}\n` };
|
|
100
|
+
}
|
|
111
101
|
}
|
|
112
102
|
/**
|
|
113
103
|
* Whether the thrown value is a scanner error the CLI knows how to render. Only the existing typed
|
package/dist/cli/runCli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runCli.js","sourceRoot":"","sources":["../../src/cli/runCli.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"runCli.js","sourceRoot":"","sources":["../../src/cli/runCli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Shared exact-root grammar for dependency exclusions and explanation input; no normalization. */
|
|
2
|
+
export declare function isExactPackageRoot(name: string): boolean;
|
|
1
3
|
/**
|
|
2
4
|
* Preserve exact case and spelling; validate whole entries before sorting/deduplicating.
|
|
3
5
|
* This bounded grammar is independent of source subpath normalization and builtin classification.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ignoreDependencies.d.ts","sourceRoot":"","sources":["../../src/config/ignoreDependencies.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,UAAU,EAAE,MAAM,GACjB,SAAS,MAAM,EAAE,CAUnB"}
|
|
1
|
+
{"version":3,"file":"ignoreDependencies.d.ts","sourceRoot":"","sources":["../../src/config/ignoreDependencies.ts"],"names":[],"mappings":"AAMA,mGAAmG;AACnG,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,UAAU,EAAE,MAAM,GACjB,SAAS,MAAM,EAAE,CAUnB"}
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
import { ProjectConfigError } from './projectConfigError.js';
|
|
3
3
|
const COMPONENT = '[A-Za-z0-9][A-Za-z0-9._-]*';
|
|
4
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
|
+
}
|
|
5
9
|
/**
|
|
6
10
|
* Preserve exact case and spelling; validate whole entries before sorting/deduplicating.
|
|
7
11
|
* This bounded grammar is independent of source subpath normalization and builtin classification.
|
|
@@ -9,7 +13,7 @@ const IDENTIFIER = new RegExp(`^(?:${COMPONENT}|@${COMPONENT}/${COMPONENT})$`, '
|
|
|
9
13
|
*/
|
|
10
14
|
export function normalizeIgnoreDependencies(rawNames, configPath) {
|
|
11
15
|
for (const [index, name] of rawNames.entries()) {
|
|
12
|
-
if (
|
|
16
|
+
if (!isExactPackageRoot(name)) {
|
|
13
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');
|
|
14
18
|
}
|
|
15
19
|
}
|
|
@@ -1 +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;;;;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,
|
|
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"}
|
|
@@ -20,4 +20,9 @@ export type ProjectConfig = {
|
|
|
20
20
|
};
|
|
21
21
|
/** Read once, validate all path/name rules, and return no partial configuration on failure. */
|
|
22
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
|
+
}>;
|
|
23
28
|
//# sourceMappingURL=readProjectConfig.d.ts.map
|
|
@@ -1 +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,
|
|
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"}
|