dependency-radar 0.6.1 → 0.8.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 +189 -25
- package/dist/aggregator.js +35 -9
- package/dist/cli.js +501 -103
- package/dist/compare.js +79 -0
- package/dist/explain.js +193 -0
- package/dist/failOn.js +16 -2
- package/dist/findings.js +166 -0
- package/dist/generated/spdx.js +3 -0
- package/dist/nodeEngine.js +181 -0
- package/dist/outputFormats.js +185 -0
- package/dist/report-assets.js +2 -2
- package/dist/report.js +138 -72
- package/dist/runners/importGraphRunner.js +9 -5
- package/dist/runners/lockfileGraph.js +144 -1
- package/dist/runners/lockfileSignals.js +303 -0
- package/dist/runners/npmLs.js +15 -0
- package/dist/schema.js +107 -0
- package/dist/utils.js +62 -3
- package/dist/why.js +69 -0
- package/dist/workspaceFilter.js +25 -0
- package/package.json +8 -5
- package/dist/runners/depcheckRunner.js +0 -23
- package/dist/runners/licenseChecker.js +0 -33
- package/dist/runners/madgeRunner.js +0 -29
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Dependency Radar inspects your Node.js dependency graph and makes structural ris
|
|
|
4
4
|
|
|
5
5
|
Unlike basic audit tools, it builds the graph from lockfiles, understands PNPM workspaces, validates declared vs inferred licences, and highlights structural risks before they become production problems.
|
|
6
6
|
|
|
7
|
-
No accounts. No uploads.
|
|
7
|
+
No accounts. No uploads. Nothing leaves your machine.
|
|
8
8
|
|
|
9
9
|
The simplest way to get started is to go to your project root and run:
|
|
10
10
|
|
|
@@ -27,13 +27,16 @@ This runs a scan against the current project and writes a self-contained `depend
|
|
|
27
27
|
## What you get
|
|
28
28
|
|
|
29
29
|
- **Vulnerability scanning** — runs `npm audit` / `pnpm audit` / `yarn audit` and surfaces advisories with severity, fix availability, and reachability heuristics
|
|
30
|
-
- **
|
|
30
|
+
- **License analysis** — validates SPDX declarations, infers licences from `LICENSE` files, and flags mismatches, unknown licences, and strong copyleft
|
|
31
31
|
- **Interactive dependency graph** — explore your full dependency tree visually, including direct, dev, and transitive relationships
|
|
32
32
|
- **Upgrade friction analysis** — identifies upgrade blockers: peer constraints, engine ranges, native bindings, install scripts, deprecated packages
|
|
33
33
|
- **Import usage heuristics** — classifies each dependency's runtime impact (`runtime`, `build`, `testing`, `tooling`, `mixed`) based on where it's imported in your source
|
|
34
34
|
- **Full transitive tree** — shows depth, parent relationships, fan-in/fan-out, and dependency origins
|
|
35
35
|
- **Workspace support** — works across npm, pnpm, and Yarn workspaces
|
|
36
36
|
- **CI-friendly** — `--fail-on` flag lets you enforce licence and vulnerability policies in pipelines
|
|
37
|
+
- **Review-friendly outputs** — emit JSON, SARIF, CycloneDX SBOM, or SPDX SBOM artifacts from the same local scan
|
|
38
|
+
- **Change comparison** — compare a fresh scan with a previous `dependency-radar.json` to see added dependencies, removed dependencies, version changes, and new findings
|
|
39
|
+
- **Lockfile supply-chain signals** — flags git/local/tarball sources, missing integrity, unexpected registry hosts, and optional npm signature/provenance verification
|
|
37
40
|
- **Completely offline-capable** — use `--offline` to skip registry calls; all package metadata is read from local `node_modules`
|
|
38
41
|
- **Single self-contained HTML file** — no server needed; open it locally, attach it to a ticket, or share it with your team
|
|
39
42
|
|
|
@@ -57,7 +60,7 @@ This runs a scan against the current project and writes a self-contained `depend
|
|
|
57
60
|
Modern Node projects pull in hundreds (or thousands) of transitive dependencies, and most of the risk is structural, not obvious.
|
|
58
61
|
|
|
59
62
|
- `npm audit` tells you about known vulnerabilities, but it does not explain how a dependency got there, whether it is reachable at runtime, or how deep it sits in your graph.
|
|
60
|
-
-
|
|
63
|
+
- License tooling often trusts `package.json` declarations, even though they can be missing, invalid, or wrong, and rarely checks what is actually in the installed `LICENSE` file.
|
|
61
64
|
- Monorepos and PNPM workspaces make the tree harder to reason about, especially when package manager outputs include optional platform variants that are not installed on your machine.
|
|
62
65
|
- Upgrade pain usually shows up late, when a Node major bump or a package update breaks due to peer dependency constraints, engine ranges, native bindings, or install scripts.
|
|
63
66
|
|
|
@@ -92,15 +95,85 @@ The `scan` command is the default and can also be run explicitly as `npx depende
|
|
|
92
95
|
| Flag | Description |
|
|
93
96
|
|---|---|
|
|
94
97
|
| `--project <path>` | Path to the project to scan (defaults to current directory) |
|
|
98
|
+
| `--quiet` | Suppress progress/info logs, browser opening, and footer messaging while keeping the final summary and failures visible |
|
|
95
99
|
| `--out <path>` | Output path for the report file |
|
|
100
|
+
| `--format <format>` | Output format: `html`, `json`, `sarif`, `cyclonedx`, or `spdx` |
|
|
101
|
+
| `--sbom <format>` | Convenience alias for SBOM output: `cyclonedx` or `spdx` |
|
|
102
|
+
| `--target-node <major>` | Add Node major compatibility findings based on local `engines.node` metadata |
|
|
103
|
+
| `--audit-signatures` | Run `npm audit signatures` for registry signature/provenance verification (opt-in; skipped with `--offline`) |
|
|
104
|
+
| `--schema` | Print the current Dependency Radar JSON schema, or write it with `--out <path>` |
|
|
96
105
|
| `--offline` | Skip `npm audit` and `npm outdated` (useful for offline/air-gapped scans) |
|
|
97
106
|
| `--json` | Output JSON instead of HTML (`dependency-radar.json`) |
|
|
107
|
+
| `--timestamp` | Add a local timestamp to generated report filenames (`dependency-radar.YYYY-MM-DD_HH-mm-ss.html`) |
|
|
98
108
|
| `--no-report` | Run analysis only; no HTML/JSON output written |
|
|
99
109
|
| `--keep-temp` | Keep the temporary `.dependency-radar/` folder for debugging |
|
|
100
110
|
| `--open` | Open the generated report using the system default browser |
|
|
101
111
|
| `--fail-on <rules>` | Fail with exit code 1 when selected policy rules are violated (see below) |
|
|
102
112
|
| `--help` | Show all options |
|
|
103
113
|
|
|
114
|
+
### Explain one dependency in the terminal
|
|
115
|
+
|
|
116
|
+
Use `explain` when you want a fast terminal view for one package without generating HTML or JSON output:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npx dependency-radar explain lodash
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This reuses the normal scan model and then filters it in memory. `explain` does not add its own extra lookup pipeline and does not write `dependency-radar.html`, but it can still trigger the same network-dependent `audit` and `outdated` steps as a normal scan unless you pass `--offline`.
|
|
123
|
+
|
|
124
|
+
`explain` shows the signals already present in Dependency Radar's scan model, including:
|
|
125
|
+
|
|
126
|
+
- direct vs transitive
|
|
127
|
+
- scope and introduction classification
|
|
128
|
+
- runtime impact heuristics
|
|
129
|
+
- root packages and direct parents
|
|
130
|
+
- static import evidence and top import locations
|
|
131
|
+
- vulnerability summary when audit data is available
|
|
132
|
+
- licence status
|
|
133
|
+
- upgrade blockers
|
|
134
|
+
- other detected versions of the same package
|
|
135
|
+
|
|
136
|
+
Examples:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
npx dependency-radar explain lodash
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
npx dependency-radar explain lodash --project ./my-app
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npx dependency-radar explain lodash --project ./my-app --offline
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Notes:
|
|
151
|
+
|
|
152
|
+
- `explain` matches by package name only. If multiple installed versions exist, each version is shown in its own block.
|
|
153
|
+
- Vulnerabilities are reported only when audit data is available. With `--offline`, the command prints `not available (--offline)` instead of implying `none`.
|
|
154
|
+
- "Static import evidence" means Dependency Radar found local source imports for that package. It is a code-usage heuristic, not exploit reachability analysis.
|
|
155
|
+
- "Introduced via root packages" and "Direct parents" are shown from the current scan model. The command does not currently print full ancestry chains.
|
|
156
|
+
|
|
157
|
+
### Show why a dependency is present
|
|
158
|
+
|
|
159
|
+
Use `why` to print shortest dependency paths from direct dependencies to a package:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
npx dependency-radar why lodash
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
This uses the same local scan model as the HTML report. When full paths are unavailable, it falls back to the package origins and direct parent evidence available in the report model.
|
|
166
|
+
|
|
167
|
+
### Compare against a previous report
|
|
168
|
+
|
|
169
|
+
Use `compare` to scan the current project and compare it with an earlier JSON report:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
npx dependency-radar compare ./dependency-radar-before.json --json --offline
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The comparison highlights added dependencies, removed dependencies, one-version package changes, new findings, and resolved findings. This is useful in pull requests and release checks.
|
|
176
|
+
|
|
104
177
|
### CI policy enforcement (`--fail-on`)
|
|
105
178
|
|
|
106
179
|
```
|
|
@@ -117,6 +190,7 @@ Supported rules:
|
|
|
117
190
|
| `licence-mismatch` | Fail if at least one dependency has a declared-vs-inferred licence mismatch |
|
|
118
191
|
| `copyleft-detected` | Fail if strong copyleft (GPL/AGPL) appears in runtime dependencies |
|
|
119
192
|
| `unknown-licence` | Fail if at least one dependency has neither declared nor inferred licence data |
|
|
193
|
+
| `supply-chain-source` | Fail if lockfile source signals detect git/local/tarball sources, missing integrity, or unexpected registry hosts |
|
|
120
194
|
|
|
121
195
|
When rules are violated, Dependency Radar prints `✖ Policy violations detected:` and exits `1`. Unknown rules also exit `1` with a clear error message.
|
|
122
196
|
|
|
@@ -132,6 +206,42 @@ npx dependency-radar --open
|
|
|
132
206
|
npx dependency-radar --project ./my-app --out ./reports/dependency-radar.html
|
|
133
207
|
```
|
|
134
208
|
|
|
209
|
+
### Example: write SARIF for CI/code scanning
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
npx dependency-radar --format sarif --out ./reports/dependency-radar.sarif
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Example: write an SBOM
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
npx dependency-radar --sbom cyclonedx --out ./reports/bom.cdx.json
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
npx dependency-radar --sbom spdx --out ./reports/bom.spdx.json
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Example: check Node upgrade readiness signals
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
npx dependency-radar --target-node 22
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Example: verify npm registry signatures/provenance
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
npx dependency-radar --audit-signatures
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
This runs `npm audit signatures` as an opt-in online check. It is skipped when `--offline` is used.
|
|
238
|
+
|
|
239
|
+
### Example: write the JSON schema
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
npx dependency-radar --schema --out ./reports/dependency-radar.schema.json
|
|
243
|
+
```
|
|
244
|
+
|
|
135
245
|
### Example: keep temp files for debugging
|
|
136
246
|
```bash
|
|
137
247
|
npx dependency-radar --keep-temp
|
|
@@ -149,6 +259,20 @@ npx dependency-radar --offline
|
|
|
149
259
|
npx dependency-radar --no-report --fail-on reachable-vuln,licence-mismatch
|
|
150
260
|
```
|
|
151
261
|
|
|
262
|
+
### Example: quiet mode for CI or scripting
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
npx dependency-radar scan --quiet --no-report
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
`--quiet` is quiet, not silent:
|
|
269
|
+
|
|
270
|
+
- the scan still runs fully
|
|
271
|
+
- reports are still generated unless `--no-report` is set
|
|
272
|
+
- the final summary block is still printed
|
|
273
|
+
- policy failures are still printed
|
|
274
|
+
- progress/info logs, automatic browser opening, and the promotional footer are suppressed
|
|
275
|
+
|
|
152
276
|
__Note:__ When used with `--no-report`, the `--keep-temp` flag is ignored.
|
|
153
277
|
Temporary files are normally deleted automatically.
|
|
154
278
|
If you intentionally use `--keep-temp` (without `--no-report`) for debugging,
|
|
@@ -160,16 +284,16 @@ At the end of each scan, the CLI prints a summary block with high-level counts,
|
|
|
160
284
|
|
|
161
285
|
```text
|
|
162
286
|
Summary:
|
|
163
|
-
• Direct
|
|
164
|
-
• Transitive
|
|
165
|
-
• Vulnerable packages:
|
|
166
|
-
•
|
|
167
|
-
•
|
|
168
|
-
• Major upgrade blockers:
|
|
169
|
-
-
|
|
170
|
-
-
|
|
171
|
-
-
|
|
172
|
-
-
|
|
287
|
+
• Direct dependencies scanned: 6
|
|
288
|
+
• Transitive dependencies scanned: 62
|
|
289
|
+
• Vulnerable packages: 1 (0 reachable)
|
|
290
|
+
• Dependencies with no static import reference: 0
|
|
291
|
+
• License mismatches: 3
|
|
292
|
+
• Major upgrade blockers: 24
|
|
293
|
+
- 1 strict peer dependency constraint
|
|
294
|
+
- 22 narrow engine ranges
|
|
295
|
+
- 2 native bindings
|
|
296
|
+
- 1 install lifecycle script
|
|
173
297
|
```
|
|
174
298
|
|
|
175
299
|
The blocker detail counts can overlap: a single package may contribute to multiple blocker categories.
|
|
@@ -183,23 +307,25 @@ The blocker detail counts can overlap: a single package may contribute to multip
|
|
|
183
307
|
| pnpm | ✅ Lockfile-first (`pnpm-lock.yaml`) | ✅ | ✅ | ✅ |
|
|
184
308
|
| Yarn Classic (v1) | ✅ Lockfile-first (`yarn.lock`) | ✅ | ✅ | ✅ |
|
|
185
309
|
| Yarn Berry (v2+, node-modules linker) | ✅ Lockfile-first (`yarn.lock`) | ✅ | ⚠️ Plugin-dependent | ✅ |
|
|
186
|
-
| Yarn Plug'n'Play |
|
|
310
|
+
| Yarn Plug'n'Play | ⚠️ Lockfile-derived graph only; package metadata may be incomplete without `node_modules` | ✅ | ⚠️ Plugin-dependent | ✅ |
|
|
311
|
+
| Bun | ⚠️ Text `bun.lock` parsing; binary `bun.lockb` is reported with a migration hint | N/A | ❌ | ⚠️ package.json workspaces only |
|
|
187
312
|
|
|
188
313
|
## Requirements
|
|
189
314
|
|
|
190
|
-
- Node.js 14.14
|
|
315
|
+
- Node.js 14.21.3 is currently the oldest version verified by our Docker release smoke test (`node:14.21.3-bullseye`)
|
|
191
316
|
- Dependencies must be installed (`npm install` / `pnpm install` / `yarn install`) before scanning
|
|
192
317
|
|
|
193
318
|
## How a scan works
|
|
194
319
|
|
|
195
320
|
When you run `npx dependency-radar` (or `dependency-radar scan`), the CLI executes this pipeline:
|
|
196
321
|
|
|
197
|
-
1. Parse CLI options (`--project`, `--out`, `--offline`, `--json`, `--no-report`, `--keep-temp`, `--open`, `--fail-on`).
|
|
322
|
+
1. Parse CLI options (`--project`, `--out`, `--offline`, `--json`, `--timestamp`, `--no-report`, `--keep-temp`, `--open`, `--fail-on`, `--audit-signatures`, `--schema`).
|
|
198
323
|
2. Detect workspace/package-manager context:
|
|
199
324
|
- Workspace roots from `pnpm-workspace.yaml` or `package.json#workspaces`
|
|
200
325
|
- Dependency policy from `package.json` and `pnpm-workspace.yaml` overrides/resolutions
|
|
201
326
|
- Package manager from `packageManager`, lockfiles, and installed metadata
|
|
202
327
|
- Yarn Plug'n'Play detection (`.pnp.cjs`/`.pnp.js` or `.yarnrc.yml nodeLinker: pnp`)
|
|
328
|
+
- Bun text lockfile detection (`bun.lock`; binary `bun.lockb` is not parsed)
|
|
203
329
|
3. Create a temporary `.dependency-radar/` directory inside the scanned project.
|
|
204
330
|
4. For each workspace package (or just the project root in single-package mode), collect dependency graph data:
|
|
205
331
|
- Lockfile-first graph parsing (`pnpm-lock.yaml`, `npm-shrinkwrap.json`/`package-lock.json`, `yarn.lock`)
|
|
@@ -209,6 +335,8 @@ When you run `npx dependency-radar` (or `dependency-radar scan`), the CLI execut
|
|
|
209
335
|
- Vulnerabilities (`npm audit` / `pnpm audit` / `yarn audit` or `yarn npm audit`)
|
|
210
336
|
- Version drift (`npm outdated` / `pnpm outdated` / `yarn outdated`, where available)
|
|
211
337
|
- Source import graph (static import/require parsing in `src/` or project root)
|
|
338
|
+
- Lockfile supply-chain source signals
|
|
339
|
+
- Optional npm registry signature/provenance verification (`--audit-signatures`)
|
|
212
340
|
6. Normalize outputs into one internal shape and merge workspace package results.
|
|
213
341
|
- PNPM lock/CLI dependency trees are filtered to installed-only packages (non-installed optional/platform variants are dropped)
|
|
214
342
|
7. Resolve and crawl installed package directories in `node_modules` to collect local metadata:
|
|
@@ -220,13 +348,20 @@ When you run `npx dependency-radar` (or `dependency-radar scan`), the CLI execut
|
|
|
220
348
|
- Root-cause/origin and runtime-impact heuristics
|
|
221
349
|
- Install-time execution signals
|
|
222
350
|
- Local package metadata (`description`, links, deprecation, TypeScript type availability, installed file count, CLI `bin` presence)
|
|
223
|
-
9.
|
|
351
|
+
9. Build normalized findings from the aggregated dependency model:
|
|
352
|
+
- Vulnerabilities, license review items, install-time execution surface, native bindings, deprecated packages, target Node compatibility findings, lockfile source signals, and npm signature/provenance failures
|
|
353
|
+
10. Write final output as one of:
|
|
224
354
|
- `dependency-radar.html` (self-contained report), or
|
|
225
355
|
- `dependency-radar.json` (raw aggregated model)
|
|
226
|
-
|
|
356
|
+
- SARIF (`--format sarif`)
|
|
357
|
+
- CycloneDX SBOM (`--format cyclonedx` / `--sbom cyclonedx`)
|
|
358
|
+
- SPDX SBOM (`--format spdx` / `--sbom spdx`)
|
|
359
|
+
11. Remove `.dependency-radar/` unless `--keep-temp` is set.
|
|
227
360
|
|
|
228
361
|
The scan is local-first: package metadata is read from `node_modules`; only audit/outdated commands require registry access.
|
|
229
362
|
|
|
363
|
+
The `explain` command reuses this same pipeline with report writing disabled, then filters the in-memory model down to a single package for terminal output.
|
|
364
|
+
|
|
230
365
|
### `node_modules` crawling details
|
|
231
366
|
|
|
232
367
|
- Dependency metadata is read from installed package directories, not from registry documents.
|
|
@@ -340,7 +475,7 @@ The JSON schema matches the `AggregatedData` TypeScript interface in `src/types.
|
|
|
340
475
|
|
|
341
476
|
```ts
|
|
342
477
|
export interface AggregatedData {
|
|
343
|
-
schemaVersion: '1.
|
|
478
|
+
schemaVersion: '1.4'; // Report schema version for compatibility checks
|
|
344
479
|
generatedAt: string; // ISO timestamp when the scan finished
|
|
345
480
|
dependencyRadarVersion: string; // CLI version that produced the report
|
|
346
481
|
git: {
|
|
@@ -378,11 +513,12 @@ export interface AggregatedData {
|
|
|
378
513
|
nodeVersion: string; // Node.js version from process.versions.node
|
|
379
514
|
runtimeVersion: string; // Node.js runtime version from process.version
|
|
380
515
|
minRequiredMajor: number; // Strictest Node major required by dependency engines (0 if unknown)
|
|
516
|
+
targetNodeMajor?: number; // Node major passed through --target-node
|
|
381
517
|
platform?: string; // OS platform (process.platform)
|
|
382
518
|
arch?: string; // CPU architecture (process.arch)
|
|
383
519
|
ci?: boolean; // True when CI indicators are detected
|
|
384
520
|
packageManagerField?: string; // package.json packageManager field (e.g. pnpm@9.1.0)
|
|
385
|
-
packageManager?: 'npm' | 'pnpm' | 'yarn'; // Package manager used for dependency/audit/outdated collection
|
|
521
|
+
packageManager?: 'npm' | 'pnpm' | 'yarn' | 'bun'; // Package manager used for dependency/audit/outdated collection
|
|
386
522
|
packageManagerVersion?: string; // Version of the selected package manager (when available)
|
|
387
523
|
toolVersions?: {
|
|
388
524
|
npm?: string;
|
|
@@ -392,7 +528,7 @@ export interface AggregatedData {
|
|
|
392
528
|
};
|
|
393
529
|
workspaces: {
|
|
394
530
|
enabled: boolean; // True when the scan used workspace aggregation
|
|
395
|
-
type?: 'npm' | 'pnpm' | 'yarn' | 'none'; // Workspace mode (CLI currently always emits this)
|
|
531
|
+
type?: 'npm' | 'pnpm' | 'yarn' | 'bun' | 'none'; // Workspace mode (CLI currently always emits this)
|
|
396
532
|
packageCount?: number; // Number of workspace packages scanned (CLI currently always emits this)
|
|
397
533
|
workspacePackages?: WorkspacePackage[]; // Lightweight first-party workspace metadata
|
|
398
534
|
};
|
|
@@ -400,7 +536,32 @@ export interface AggregatedData {
|
|
|
400
536
|
dependencyCount: number; // Total EXTERNAL dependencies in the graph
|
|
401
537
|
directCount: number; // External dependencies listed in package.json
|
|
402
538
|
transitiveCount: number; // External dependencies pulled in by other dependencies
|
|
539
|
+
findingCount?: number; // Number of normalized findings generated from the dependency model
|
|
540
|
+
};
|
|
541
|
+
supplyChain?: {
|
|
542
|
+
signals: Array<{
|
|
543
|
+
type:
|
|
544
|
+
| 'git-dependency'
|
|
545
|
+
| 'file-dependency'
|
|
546
|
+
| 'non-registry-tarball'
|
|
547
|
+
| 'missing-integrity'
|
|
548
|
+
| 'unexpected-registry-host'
|
|
549
|
+
| 'signature-verification-failed'
|
|
550
|
+
| 'signature-verification-unavailable';
|
|
551
|
+
packageName?: string;
|
|
552
|
+
packageVersion?: string;
|
|
553
|
+
packageId?: string;
|
|
554
|
+
source: string;
|
|
555
|
+
detail: string;
|
|
556
|
+
}>;
|
|
557
|
+
signatureAudit?: {
|
|
558
|
+
attempted: boolean;
|
|
559
|
+
ok: boolean;
|
|
560
|
+
output?: string;
|
|
561
|
+
error?: string;
|
|
562
|
+
};
|
|
403
563
|
};
|
|
564
|
+
findings?: DependencyFinding[]; // Normalized review/CI findings
|
|
404
565
|
dependencies: Record<string, DependencyRecord>; // External third-party packages keyed by name@version
|
|
405
566
|
}
|
|
406
567
|
|
|
@@ -536,9 +697,6 @@ export interface DependencyRecord {
|
|
|
536
697
|
|
|
537
698
|
For full details and any future changes, see `src/types.ts`.
|
|
538
699
|
|
|
539
|
-
Environment data includes Node.js version, OS platform, CPU architecture, and package manager versions.
|
|
540
|
-
No personal information, usernames, paths, or environment variables are collected.
|
|
541
|
-
|
|
542
700
|
## Notes
|
|
543
701
|
|
|
544
702
|
- The target project must have dependencies installed (run `npm install`, `pnpm install`, or `yarn install` first).
|
|
@@ -548,6 +706,8 @@ No personal information, usernames, paths, or environment variables are collecte
|
|
|
548
706
|
- A temporary `.dependency-radar/` folder is created during the scan to store intermediate tool output.
|
|
549
707
|
- Use `--keep-temp` to retain this folder for debugging; otherwise it is deleted automatically.
|
|
550
708
|
- If some per-package tools fail (common in large workspaces), the scan continues and reports warnings; missing sections are marked unavailable where applicable.
|
|
709
|
+
- Environment data includes Node.js version, OS platform, CPU architecture, and package manager versions.
|
|
710
|
+
- No personal information, usernames, paths, or environment variables are collected.
|
|
551
711
|
|
|
552
712
|
---
|
|
553
713
|
|
|
@@ -576,11 +736,15 @@ npm run build
|
|
|
576
736
|
| `npm run test:fixtures` | Run curated fixture integration tests (mostly offline scans) |
|
|
577
737
|
| `npm run test:fixtures:online` | Run online fixture checks (audit/outdated regression coverage) |
|
|
578
738
|
| `npm run test:fixtures:all` | Run all fixture integration tests |
|
|
579
|
-
| `npm run test:
|
|
739
|
+
| `npm run test:docker:node14` | Pack the published artifact and smoke-test it in Docker on Node `14.21.3` |
|
|
740
|
+
| `npm run test:docker` | Alias for the Node `14.21.3` Docker compatibility smoke test |
|
|
741
|
+
| `npm run test:release` | Full pre-release gate (`build` + unit + fixture + Docker Node 14 smoke test + package dry run) |
|
|
580
742
|
|
|
581
743
|
|
|
582
744
|
Fixture orchestration lives in `/test-fixtures/package.json` with helper scripts under `/test-fixtures/scripts`.
|
|
583
745
|
|
|
746
|
+
The Docker smoke test uses the packed tarball, installs it inside `node:14.21.3-bullseye`, and runs an offline scan against `test-fixtures/license-edge-cases`. This verifies the published CLI on the oldest Node version we currently exercise in automation without requiring local Node 14 installation.
|
|
747
|
+
|
|
584
748
|
### Report UI Development
|
|
585
749
|
|
|
586
750
|
The HTML report UI is developed in a separate Vite project located in `report-ui/`. This provides a proper development environment with hot reload, TypeScript support, and sample data.
|
package/dist/aggregator.js
CHANGED
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.aggregateData = aggregateData;
|
|
7
7
|
const utils_1 = require("./utils");
|
|
8
8
|
const license_1 = require("./license");
|
|
9
|
+
const findings_1 = require("./findings");
|
|
10
|
+
const nodeEngine_1 = require("./nodeEngine");
|
|
9
11
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
10
12
|
const path_1 = __importDefault(require("path"));
|
|
11
13
|
const os_1 = __importDefault(require("os"));
|
|
@@ -286,7 +288,7 @@ function isWorkspacePackageNode(node, input) {
|
|
|
286
288
|
return false;
|
|
287
289
|
}
|
|
288
290
|
async function aggregateData(input) {
|
|
289
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
291
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
290
292
|
const pkg = input.pkgOverride || (await (0, utils_1.readPackageJson)(input.projectPath));
|
|
291
293
|
let projectPkg = input.projectPackageJson;
|
|
292
294
|
if (!projectPkg) {
|
|
@@ -305,7 +307,8 @@ async function aggregateData(input) {
|
|
|
305
307
|
const importGraph = normalizeImportGraph((_c = input.importGraphResult) === null || _c === void 0 ? void 0 : _c.data);
|
|
306
308
|
const usageResult = buildUsageSummary(importGraph, input.projectPath);
|
|
307
309
|
const outdatedById = buildOutdatedMap(input.outdatedResult);
|
|
308
|
-
const
|
|
310
|
+
const supplyChain = normalizeSupplyChain((_d = input.supplyChainResult) === null || _d === void 0 ? void 0 : _d.data);
|
|
311
|
+
const outdatedUnknownNames = new Set(((_e = input.outdatedResult) === null || _e === void 0 ? void 0 : _e.unknownNames) || []);
|
|
309
312
|
const packageMetaCache = new Map();
|
|
310
313
|
const resolvePaths = input.resolvePaths && input.resolvePaths.length > 0
|
|
311
314
|
? input.resolvePaths
|
|
@@ -346,7 +349,7 @@ async function aggregateData(input) {
|
|
|
346
349
|
const runtimeImpact = usageResult.runtimeImpact.get(node.name);
|
|
347
350
|
const introduction = determineIntroduction(direct, scope, rootCauses, runtimeImpact);
|
|
348
351
|
const parentIds = Array.from(node.parents).sort();
|
|
349
|
-
const origins = buildOrigins(rootCauses, parentIds, (
|
|
352
|
+
const origins = buildOrigins(rootCauses, parentIds, (_f = input.workspaceUsage) === null || _f === void 0 ? void 0 : _f.get(node.name), input.workspaceEnabled, MAX_TOP_ROOT_PACKAGES, MAX_TOP_PARENT_PACKAGES);
|
|
350
353
|
const execution = packageInsights.execution;
|
|
351
354
|
const id = node.key;
|
|
352
355
|
const upgrade = buildUpgradeBlock(packageInsights);
|
|
@@ -359,7 +362,10 @@ async function aggregateData(input) {
|
|
|
359
362
|
...(outdated ? { outdatedStatus: outdated.status } : {}),
|
|
360
363
|
...((outdated === null || outdated === void 0 ? void 0 : outdated.latestVersion) ? { latestVersion: outdated.latestVersion } : {}),
|
|
361
364
|
...((upgrade === null || upgrade === void 0 ? void 0 : upgrade.blockers) ? { blockers: upgrade.blockers } : {}),
|
|
362
|
-
...((upgrade === null || upgrade === void 0 ? void 0 : upgrade.blocksNodeMajor) ? { blocksNodeMajor: upgrade.blocksNodeMajor } : {})
|
|
365
|
+
...((upgrade === null || upgrade === void 0 ? void 0 : upgrade.blocksNodeMajor) ? { blocksNodeMajor: upgrade.blocksNodeMajor } : {}),
|
|
366
|
+
...(typeof input.targetNodeMajor === 'number' && packageInsights.nodeEngine
|
|
367
|
+
? { targetNodeCompatible: (0, nodeEngine_1.isNodeEngineTargetCompatible)(packageInsights.nodeEngine, input.targetNodeMajor) }
|
|
368
|
+
: {})
|
|
363
369
|
};
|
|
364
370
|
dependencies[id] = {
|
|
365
371
|
package: {
|
|
@@ -372,9 +378,9 @@ async function aggregateData(input) {
|
|
|
372
378
|
deprecated: packageInsights.deprecated,
|
|
373
379
|
links: {
|
|
374
380
|
npm: `https://www.npmjs.com/package/${node.name}`,
|
|
375
|
-
...(((
|
|
376
|
-
...(((
|
|
377
|
-
...(((
|
|
381
|
+
...(((_g = packageInsights.links) === null || _g === void 0 ? void 0 : _g.repository) ? { repository: packageInsights.links.repository } : {}),
|
|
382
|
+
...(((_h = packageInsights.links) === null || _h === void 0 ? void 0 : _h.homepage) ? { homepage: packageInsights.links.homepage } : {}),
|
|
383
|
+
...(((_j = packageInsights.links) === null || _j === void 0 ? void 0 : _j.bugs) ? { bugs: packageInsights.links.bugs } : {})
|
|
378
384
|
}
|
|
379
385
|
},
|
|
380
386
|
compliance: {
|
|
@@ -416,8 +422,8 @@ async function aggregateData(input) {
|
|
|
416
422
|
const nodeVersion = process.versions.node;
|
|
417
423
|
const dependencyCount = nodes.length;
|
|
418
424
|
const transitiveCount = dependencyCount - directCount;
|
|
419
|
-
|
|
420
|
-
schemaVersion: '1.
|
|
425
|
+
const aggregated = {
|
|
426
|
+
schemaVersion: '1.4',
|
|
421
427
|
generatedAt: new Date().toISOString(),
|
|
422
428
|
dependencyRadarVersion,
|
|
423
429
|
git: {
|
|
@@ -428,6 +434,7 @@ async function aggregateData(input) {
|
|
|
428
434
|
nodeVersion,
|
|
429
435
|
runtimeVersion,
|
|
430
436
|
minRequiredMajor: minRequiredMajor !== null && minRequiredMajor !== void 0 ? minRequiredMajor : 0,
|
|
437
|
+
...(typeof input.targetNodeMajor === 'number' ? { targetNodeMajor: input.targetNodeMajor } : {}),
|
|
431
438
|
...(input.platform ? { platform: input.platform } : {}),
|
|
432
439
|
...(input.arch ? { arch: input.arch } : {}),
|
|
433
440
|
...(typeof input.ci === 'boolean' ? { ci: input.ci } : {}),
|
|
@@ -449,8 +456,27 @@ async function aggregateData(input) {
|
|
|
449
456
|
directCount,
|
|
450
457
|
transitiveCount
|
|
451
458
|
},
|
|
459
|
+
...(supplyChain ? { supplyChain } : {}),
|
|
452
460
|
dependencies
|
|
453
461
|
};
|
|
462
|
+
const findings = (0, findings_1.buildDependencyFindings)(aggregated, { targetNodeMajor: input.targetNodeMajor });
|
|
463
|
+
aggregated.findings = findings;
|
|
464
|
+
aggregated.summary.findingCount = findings.length;
|
|
465
|
+
return aggregated;
|
|
466
|
+
}
|
|
467
|
+
function normalizeSupplyChain(data) {
|
|
468
|
+
if (!data || typeof data !== 'object')
|
|
469
|
+
return undefined;
|
|
470
|
+
const signals = Array.isArray(data.signals) ? data.signals : [];
|
|
471
|
+
const signatureAudit = data.signatureAudit && typeof data.signatureAudit === 'object'
|
|
472
|
+
? data.signatureAudit
|
|
473
|
+
: undefined;
|
|
474
|
+
if (signals.length === 0 && !signatureAudit)
|
|
475
|
+
return undefined;
|
|
476
|
+
return {
|
|
477
|
+
signals,
|
|
478
|
+
...(signatureAudit ? { signatureAudit } : {})
|
|
479
|
+
};
|
|
454
480
|
}
|
|
455
481
|
function deriveMinRequiredMajor(engineRanges) {
|
|
456
482
|
let strictest;
|