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