depvitals 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -54
- package/dist/cli/entry.d.ts +59 -0
- package/dist/cli/entry.d.ts.map +1 -0
- package/dist/cli/entry.js +95 -0
- package/dist/cli/entry.js.map +1 -0
- package/dist/cli/index.js +14 -18
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/notifier/eligibility.d.ts +65 -0
- package/dist/cli/notifier/eligibility.d.ts.map +1 -0
- package/dist/cli/notifier/eligibility.js +123 -0
- package/dist/cli/notifier/eligibility.js.map +1 -0
- package/dist/cli/notifier/registryLookup.d.ts +111 -0
- package/dist/cli/notifier/registryLookup.d.ts.map +1 -0
- package/dist/cli/notifier/registryLookup.js +211 -0
- package/dist/cli/notifier/registryLookup.js.map +1 -0
- package/dist/cli/notifier/updateCache.d.ts +101 -0
- package/dist/cli/notifier/updateCache.d.ts.map +1 -0
- package/dist/cli/notifier/updateCache.js +352 -0
- package/dist/cli/notifier/updateCache.js.map +1 -0
- package/dist/cli/notifier/updateCheck.d.ts +88 -0
- package/dist/cli/notifier/updateCheck.d.ts.map +1 -0
- package/dist/cli/notifier/updateCheck.js +166 -0
- package/dist/cli/notifier/updateCheck.js.map +1 -0
- package/dist/cli/notifier/versionCompare.d.ts +48 -0
- package/dist/cli/notifier/versionCompare.d.ts.map +1 -0
- package/dist/cli/notifier/versionCompare.js +89 -0
- package/dist/cli/notifier/versionCompare.js.map +1 -0
- package/dist/cli/runCli.d.ts +2 -0
- package/dist/cli/runCli.d.ts.map +1 -1
- package/dist/cli/runCli.js +30 -3
- package/dist/cli/runCli.js.map +1 -1
- package/dist/core/analyzeProject.d.ts +44 -6
- package/dist/core/analyzeProject.d.ts.map +1 -1
- package/dist/core/analyzeProject.js +110 -11
- package/dist/core/analyzeProject.js.map +1 -1
- package/dist/detectors/eslintManifestConfig.d.ts +111 -0
- package/dist/detectors/eslintManifestConfig.d.ts.map +1 -0
- package/dist/detectors/eslintManifestConfig.js +348 -0
- package/dist/detectors/eslintManifestConfig.js.map +1 -0
- package/dist/detectors/eslintRcJsonConfig.d.ts +85 -0
- package/dist/detectors/eslintRcJsonConfig.d.ts.map +1 -0
- package/dist/detectors/eslintRcJsonConfig.js +188 -0
- package/dist/detectors/eslintRcJsonConfig.js.map +1 -0
- package/dist/detectors/jestManifestConfig.d.ts +76 -0
- package/dist/detectors/jestManifestConfig.d.ts.map +1 -0
- package/dist/detectors/jestManifestConfig.js +292 -0
- package/dist/detectors/jestManifestConfig.js.map +1 -0
- package/dist/reporters/terminalReporter.js +27 -1
- package/dist/reporters/terminalReporter.js.map +1 -1
- package/dist/scanner/moduleSpecifiers.d.ts +9 -1
- package/dist/scanner/moduleSpecifiers.d.ts.map +1 -1
- package/dist/scanner/moduleSpecifiers.js +2352 -173
- package/dist/scanner/moduleSpecifiers.js.map +1 -1
- package/dist/scanner/projectManifest.d.ts +14 -0
- package/dist/scanner/projectManifest.d.ts.map +1 -1
- package/dist/scanner/projectManifest.js +40 -0
- package/dist/scanner/projectManifest.js.map +1 -1
- package/dist/scanner/scriptUsage.d.ts +11 -5
- package/dist/scanner/scriptUsage.d.ts.map +1 -1
- package/dist/scanner/scriptUsage.js +320 -16
- package/dist/scanner/scriptUsage.js.map +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy external `.eslintrc.json` usage detection.
|
|
3
|
+
*
|
|
4
|
+
* This module adds exactly one static data source to the ESLint rules proven in Step 57: the single
|
|
5
|
+
* file `<projectRoot>/.eslintrc.json`. Its parsed JSON document is handed to the same pure matcher
|
|
6
|
+
* ({@link findEslintConfigUsage}) that reads `package.json#eslintConfig`, so the fixed allowlists,
|
|
7
|
+
* the exact-string lookup and the "declared packages only" rule are reused instead of duplicated.
|
|
8
|
+
* The result is a set of configuration-only package names for the Step 56 analyzer seam, so a
|
|
9
|
+
* recognized name can only suppress an `unused` finding and can never create a `missing` one.
|
|
10
|
+
*
|
|
11
|
+
* It deliberately does not:
|
|
12
|
+
* - evaluate, `import()`, `require()` or otherwise run ESLint, a config loader or any target code.
|
|
13
|
+
* The file is read as UTF-8 text and parsed with `JSON.parse`;
|
|
14
|
+
* - support any other legacy format: `.eslintrc.js` / `.cjs` / `.mjs` (JavaScript config modules),
|
|
15
|
+
* `.eslintrc.yml` / `.yaml` and extensionless `.eslintrc` are explicitly dismissed in this
|
|
16
|
+
* release, as is JSON5 or comment-tolerant JSON. A `.eslintrc.json` that uses JavaScript-style
|
|
17
|
+
* comments is therefore reported as the operational error described below rather than parsed by a
|
|
18
|
+
* second JSON dialect: DepVitals reads one strict JSON document, and a hand-written comment
|
|
19
|
+
* stripper that mis-handled a `//` inside a string value could alter the document and invent
|
|
20
|
+
* evidence. A leading UTF-8 BOM is different - it is an encoding artifact of the very same
|
|
21
|
+
* document, so it is removed before parsing;
|
|
22
|
+
* - traverse parent directories, nested packages or workspaces looking for further config files, or
|
|
23
|
+
* resolve `extends` references to other configuration files;
|
|
24
|
+
* - read anything besides the `extends`/`plugins` subset that {@link findEslintConfigUsage} accepts;
|
|
25
|
+
* every other ESLint field (`env`, `globals`, `rules`, `parserOptions`, `overrides`, ...) is
|
|
26
|
+
* ignored, and no unknown value produces evidence;
|
|
27
|
+
* - report anything about a package the manifest does not declare, or mutate the analyzed project.
|
|
28
|
+
*
|
|
29
|
+
* Two conservative file rules keep the reader honest:
|
|
30
|
+
*
|
|
31
|
+
* - only a regular file at exactly `<projectRoot>/.eslintrc.json` is read. The path is built from a
|
|
32
|
+
* fixed file name joined to the resolved root, so it cannot point outside the project, and
|
|
33
|
+
* `lstat` (not `stat`) is used so a symlinked `.eslintrc.json` is skipped rather than followed.
|
|
34
|
+
* Following a link could read content that lives outside the analyzed tree, which the scan policy
|
|
35
|
+
* forbids; skipping is the safe answer and is a documented limitation;
|
|
36
|
+
* - a file that exists and is a regular file but cannot be read or parsed is reported as an
|
|
37
|
+
* operational {@link EslintRcJsonError}. Silently ignoring it would drop the only evidence for a
|
|
38
|
+
* package that the broken configuration may well reference, and would let the scan present a
|
|
39
|
+
* misleadingly clean or wrongly `unused` result. Valid JSON with an unusable top-level shape
|
|
40
|
+
* (array, string, number, `null`) is different: it is not an ESLint configuration at all, so it
|
|
41
|
+
* contributes no evidence and is never an error, exactly like the unknown-field case.
|
|
42
|
+
*
|
|
43
|
+
* Precedence follows the legacy ESLint rule that one active configuration wins: a hard barrier (a
|
|
44
|
+
* modern flat config or `.eslintrc.js`/`.cjs`/`.yaml`/`.yml`) disables every legacy hint, and
|
|
45
|
+
* otherwise this file wins over `package.json#eslintConfig`. The precedence is computed once by a
|
|
46
|
+
* helper both legacy readers share; the barrier is presence-based and never reads the displaced
|
|
47
|
+
* source for evidence, so two contradictory legacy sources are never unioned.
|
|
48
|
+
*/
|
|
49
|
+
import { lstat, readFile } from 'node:fs/promises';
|
|
50
|
+
import { join, resolve } from 'node:path';
|
|
51
|
+
import { loadProjectManifest, ProjectManifestError } from '../scanner/projectManifest.js';
|
|
52
|
+
import { findEslintConfigUsage, readLegacyEslintPrecedence } from './eslintManifestConfig.js';
|
|
53
|
+
/**
|
|
54
|
+
* The one file name this reader looks for, relative to the resolved project root.
|
|
55
|
+
*
|
|
56
|
+
* There is intentionally no list of alternative legacy names: `.eslintrc.yml`, `.eslintrc.js` and
|
|
57
|
+
* the extensionless `.eslintrc` are out of scope for this release, so no reader is added for them.
|
|
58
|
+
*/
|
|
59
|
+
const ESLINTRC_FILENAME = '.eslintrc.json';
|
|
60
|
+
/**
|
|
61
|
+
* Operational error for an unusable `.eslintrc.json`.
|
|
62
|
+
*
|
|
63
|
+
* The `code` lets callers render a clean message without matching on error strings, following the
|
|
64
|
+
* existing `ProjectManifestError` / `SourceFilesError` convention. Throwing is deliberate: an
|
|
65
|
+
* unreadable or unparsable configuration that DepVitals silently skipped could otherwise turn into
|
|
66
|
+
* an unfounded `unused` finding.
|
|
67
|
+
*/
|
|
68
|
+
export class EslintRcJsonError extends Error {
|
|
69
|
+
code;
|
|
70
|
+
constructor(message, code, cause) {
|
|
71
|
+
super(message, cause === undefined ? undefined : { cause });
|
|
72
|
+
this.name = 'EslintRcJsonError';
|
|
73
|
+
this.code = code;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Collect the external `.eslintrc.json` hints for the project rooted at `projectRoot`.
|
|
78
|
+
*
|
|
79
|
+
* The returned set is shaped for the analyzer's `configUsedNames` option (the Step 56 handoff),
|
|
80
|
+
* which is the only way configuration evidence reaches the analyzer. Nothing is decided here: the
|
|
81
|
+
* analyzer stays the sole owner of the unused/missing categories, and an undeclared package can
|
|
82
|
+
* never appear in the result.
|
|
83
|
+
*
|
|
84
|
+
* @param projectRoot - Project directory to inspect; resolved to an absolute path.
|
|
85
|
+
* @throws {EslintRcJsonError} when a regular `.eslintrc.json` file exists but cannot be read or
|
|
86
|
+
* parsed as JSON. Absent, skipped and unusable-but-parsable files return the empty set.
|
|
87
|
+
*/
|
|
88
|
+
export async function findEslintRcJsonUsage(projectRoot) {
|
|
89
|
+
const root = resolve(projectRoot);
|
|
90
|
+
// A hard barrier disables every legacy hint, external file included. Precedence is computed once
|
|
91
|
+
// by a helper both legacy readers share, so this file always wins over `package.json#eslintConfig`
|
|
92
|
+
// and the two legacy sources are never combined into one hint set.
|
|
93
|
+
const precedence = await readLegacyEslintPrecedence(root);
|
|
94
|
+
if (precedence.hardBarrier) {
|
|
95
|
+
return new Set();
|
|
96
|
+
}
|
|
97
|
+
let declaredPackageNames;
|
|
98
|
+
try {
|
|
99
|
+
const manifest = await loadProjectManifest(root);
|
|
100
|
+
declaredPackageNames = manifest.declaredDependencyNames;
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
if (error instanceof ProjectManifestError) {
|
|
104
|
+
// Manifest failures stay with the manifest loader and the analyzer, which report them as they
|
|
105
|
+
// always have; this detector never duplicates that diagnosis.
|
|
106
|
+
return new Set();
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
// Reuse the on-disk entry name when the legacy `.eslintrc.json` was found under a different
|
|
111
|
+
// casing, so the reader opens the file that actually exists instead of assuming the canonical
|
|
112
|
+
// lowercase spelling.
|
|
113
|
+
const eslintRcFilename = precedence.legacyRcJsonEntryName ?? ESLINTRC_FILENAME;
|
|
114
|
+
const eslintRcPath = join(root, eslintRcFilename);
|
|
115
|
+
const text = await readEslintRcText(eslintRcPath);
|
|
116
|
+
if (text === undefined) {
|
|
117
|
+
return new Set();
|
|
118
|
+
}
|
|
119
|
+
let parsed;
|
|
120
|
+
try {
|
|
121
|
+
parsed = JSON.parse(withoutByteOrderMark(text));
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
throw new EslintRcJsonError(`${eslintRcFilename} at ${eslintRcPath} is not valid JSON. DepVitals reads strict JSON ` +
|
|
125
|
+
`only, so JavaScript-style comments inside ${eslintRcFilename} are not supported.`, 'invalid-json', error);
|
|
126
|
+
}
|
|
127
|
+
// The whole document is the legacy config object, so the proven matcher is reused verbatim. A
|
|
128
|
+
// top-level value that is not an object simply matches nothing, and nothing undeclared is added.
|
|
129
|
+
return findEslintConfigUsage(parsed, declaredPackageNames);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Read `.eslintrc.json` as text, returning `undefined` when there is no usable file.
|
|
133
|
+
*
|
|
134
|
+
* `undefined` means "no external configuration to consult": the file is absent, or it is not a
|
|
135
|
+
* regular file. Anything else that prevents reading a real configuration file is an explicit error,
|
|
136
|
+
* because guessing that a broken file declares nothing is how a false `unused` finding starts.
|
|
137
|
+
*/
|
|
138
|
+
async function readEslintRcText(eslintRcPath) {
|
|
139
|
+
let stats;
|
|
140
|
+
try {
|
|
141
|
+
// `lstat`, not `stat`: a symlinked `.eslintrc.json` is not followed, so content outside the
|
|
142
|
+
// analyzed project tree is never read. The path is `<root>/.eslintrc.json` built from a fixed
|
|
143
|
+
// file name, so it cannot address anything outside the resolved root by construction.
|
|
144
|
+
stats = await lstat(eslintRcPath);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (isNotFoundError(error)) {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
throw toUnreadableError(eslintRcPath, error);
|
|
151
|
+
}
|
|
152
|
+
// Only a regular file is read: a directory, FIFO, socket or symlink contributes no evidence.
|
|
153
|
+
if (!stats.isFile()) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
return await readFile(eslintRcPath, 'utf8');
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
if (isNotFoundError(error)) {
|
|
161
|
+
// The file disappeared between the two calls: that is an absent configuration, not a broken one.
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
throw toUnreadableError(eslintRcPath, error);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Remove a leading UTF-8 BOM, which `readFile(..., 'utf8')` keeps verbatim.
|
|
169
|
+
*
|
|
170
|
+
* A BOM is an encoding artifact of the same JSON document rather than a different configuration
|
|
171
|
+
* format, so it must not turn a readable configuration into an `invalid-json` failure.
|
|
172
|
+
*/
|
|
173
|
+
function withoutByteOrderMark(text) {
|
|
174
|
+
return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Wrap a filesystem failure on a real `.eslintrc.json` file as an operational error.
|
|
178
|
+
*/
|
|
179
|
+
function toUnreadableError(eslintRcPath, error) {
|
|
180
|
+
return new EslintRcJsonError(`Could not read ${ESLINTRC_FILENAME} at ${eslintRcPath}`, 'unreadable', error);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Whether an unknown thrown value is the filesystem `ENOENT` error.
|
|
184
|
+
*/
|
|
185
|
+
function isNotFoundError(error) {
|
|
186
|
+
return error instanceof Error && 'code' in error && error.code === 'ENOENT';
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=eslintRcJsonConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eslintRcJsonConfig.js","sourceRoot":"","sources":["../../src/detectors/eslintRcJsonConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `package.json#jest` usage detection.
|
|
3
|
+
*
|
|
4
|
+
* This module answers exactly one narrow question: which declared dependencies are named by the three
|
|
5
|
+
* explicit Jest fields this release understands inside the `jest` block of `package.json` — the
|
|
6
|
+
* top-level `preset` and `testEnvironment` strings and the values of the top-level `transform` map?
|
|
7
|
+
* The result is a set of configuration-only package names handed to the Step 56 analyzer seam, so a
|
|
8
|
+
* recognized name can only suppress an `unused` finding and can never create a `missing` one.
|
|
9
|
+
*
|
|
10
|
+
* It deliberately does not:
|
|
11
|
+
* - execute Jest, `import()`/`require()` its configuration loader, or evaluate any target code;
|
|
12
|
+
* - implement the Jest configuration schema. Only `preset`, `testEnvironment` and `transform` are
|
|
13
|
+
* read, and only through the fixed allowlists below;
|
|
14
|
+
* - read the `transform` map *keys*. Every key of that map is a regular expression selecting the
|
|
15
|
+
* files a transformer applies to, so a key is a pattern and never a package name, even when it
|
|
16
|
+
* literally reads `"ts-jest"`; no regular expression is ever evaluated here;
|
|
17
|
+
* - expand Jest shorthands. In particular `testEnvironment: "jsdom"` is *not* credited to
|
|
18
|
+
* `jest-environment-jsdom`: whether that shorthand is a package reference at all depends on the
|
|
19
|
+
* Jest major version in use, which DepVitals does not read, so it stays outside the supported
|
|
20
|
+
* subset of explicit package names;
|
|
21
|
+
* - interpret `<rootDir>/...`, `./...`, absolute paths, URLs or any other resolver-looking string as a
|
|
22
|
+
* package reference;
|
|
23
|
+
* - read `jest.config.js`/`.cjs`/`.mjs`/`.ts`/`.json` contents. Those files are only checked for
|
|
24
|
+
* presence, never opened here (source detection already handles their imports on its own);
|
|
25
|
+
* - guess a package from arbitrary configuration text, substring-match a value, or invent a name;
|
|
26
|
+
* - report anything about a package the manifest does not declare;
|
|
27
|
+
* - mutate the analyzed project.
|
|
28
|
+
*
|
|
29
|
+
* A conservative precedence guard applies before anything is read: when a root `jest.config.*` file
|
|
30
|
+
* exists, it is not provable which configuration Jest actually loads, so no `package.json#jest`
|
|
31
|
+
* hints are produced. Presence is checked by directory entry name only.
|
|
32
|
+
*
|
|
33
|
+
* The manifest model intentionally does not carry `jest`, so `package.json` is read a second time here
|
|
34
|
+
* as plain text (same trade-off as the legacy ESLint readers): the loader stays the validity gate and
|
|
35
|
+
* the single reporter of a broken manifest, while this detector silently ignores every shape it cannot
|
|
36
|
+
* use. Ignoring is deliberate — an unusable `jest` block is not an error, and diagnosing one here would
|
|
37
|
+
* duplicate the manifest loader.
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* Match the allowlisted subset of one `jest` configuration against the declared packages.
|
|
41
|
+
*
|
|
42
|
+
* Pure and side-effect free: it takes the raw `package.json#jest` JSON value (any shape, including
|
|
43
|
+
* something that is not an object) and the declared dependency names, and returns the declared
|
|
44
|
+
* packages named by `preset`, `testEnvironment` or the values of `transform`, in alphabetical order.
|
|
45
|
+
* Neither argument is mutated, and a candidate that is not declared is dropped, so this function can
|
|
46
|
+
* never describe an undeclared package as used.
|
|
47
|
+
*
|
|
48
|
+
* @param jestConfig - The raw `package.json#jest` value, validated here and never trusted.
|
|
49
|
+
* @param declaredPackageNames - Declared dependency names, the only names this may return.
|
|
50
|
+
*/
|
|
51
|
+
export declare function findJestConfigUsage(jestConfig: unknown, declaredPackageNames: ReadonlySet<string>): ReadonlySet<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Collect the `package.json#jest` hints for the project rooted at `projectRoot`.
|
|
54
|
+
*
|
|
55
|
+
* The returned set is shaped for the analyzer's `configUsedNames` option (the Step 56 handoff), which
|
|
56
|
+
* is the only way configuration evidence reaches the analyzer. Nothing is decided here: the analyzer
|
|
57
|
+
* stays the sole owner of the unused/missing categories.
|
|
58
|
+
*
|
|
59
|
+
* No configuration problem is reported as an error. A missing manifest, an unreadable or invalid
|
|
60
|
+
* `package.json`, an unusable `jest` shape or an unreadable root all yield the empty set; the analyzer
|
|
61
|
+
* loads the manifest itself and remains the component that reports manifest failures, so this detector
|
|
62
|
+
* never replaces or duplicates that diagnosis.
|
|
63
|
+
*
|
|
64
|
+
* @param projectRoot - Project directory to inspect; resolved to an absolute path.
|
|
65
|
+
*/
|
|
66
|
+
export declare function findJestManifestUsage(projectRoot: string): Promise<ReadonlySet<string>>;
|
|
67
|
+
/**
|
|
68
|
+
* Whether a root Jest configuration file name exists in the project root.
|
|
69
|
+
*
|
|
70
|
+
* The root directory is listed by name only (`readdir`), so no entry is opened, stat-followed, read or
|
|
71
|
+
* executed. An unreadable or missing root simply means no root Jest config is known to be present.
|
|
72
|
+
* Names are compared case-insensitively so a case-insensitive filesystem (typical on Windows and
|
|
73
|
+
* macOS) cannot hide a root Jest config from this guard.
|
|
74
|
+
*/
|
|
75
|
+
export declare function hasRootJestConfigEntry(root: string): Promise<boolean>;
|
|
76
|
+
//# sourceMappingURL=jestManifestConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jestManifestConfig.d.ts","sourceRoot":"","sources":["../../src/detectors/jestManifestConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAmEH;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,OAAO,EACnB,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,GACxC,WAAW,CAAC,MAAM,CAAC,CAqBrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAuB7F;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU3E"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `package.json#jest` usage detection.
|
|
3
|
+
*
|
|
4
|
+
* This module answers exactly one narrow question: which declared dependencies are named by the three
|
|
5
|
+
* explicit Jest fields this release understands inside the `jest` block of `package.json` — the
|
|
6
|
+
* top-level `preset` and `testEnvironment` strings and the values of the top-level `transform` map?
|
|
7
|
+
* The result is a set of configuration-only package names handed to the Step 56 analyzer seam, so a
|
|
8
|
+
* recognized name can only suppress an `unused` finding and can never create a `missing` one.
|
|
9
|
+
*
|
|
10
|
+
* It deliberately does not:
|
|
11
|
+
* - execute Jest, `import()`/`require()` its configuration loader, or evaluate any target code;
|
|
12
|
+
* - implement the Jest configuration schema. Only `preset`, `testEnvironment` and `transform` are
|
|
13
|
+
* read, and only through the fixed allowlists below;
|
|
14
|
+
* - read the `transform` map *keys*. Every key of that map is a regular expression selecting the
|
|
15
|
+
* files a transformer applies to, so a key is a pattern and never a package name, even when it
|
|
16
|
+
* literally reads `"ts-jest"`; no regular expression is ever evaluated here;
|
|
17
|
+
* - expand Jest shorthands. In particular `testEnvironment: "jsdom"` is *not* credited to
|
|
18
|
+
* `jest-environment-jsdom`: whether that shorthand is a package reference at all depends on the
|
|
19
|
+
* Jest major version in use, which DepVitals does not read, so it stays outside the supported
|
|
20
|
+
* subset of explicit package names;
|
|
21
|
+
* - interpret `<rootDir>/...`, `./...`, absolute paths, URLs or any other resolver-looking string as a
|
|
22
|
+
* package reference;
|
|
23
|
+
* - read `jest.config.js`/`.cjs`/`.mjs`/`.ts`/`.json` contents. Those files are only checked for
|
|
24
|
+
* presence, never opened here (source detection already handles their imports on its own);
|
|
25
|
+
* - guess a package from arbitrary configuration text, substring-match a value, or invent a name;
|
|
26
|
+
* - report anything about a package the manifest does not declare;
|
|
27
|
+
* - mutate the analyzed project.
|
|
28
|
+
*
|
|
29
|
+
* A conservative precedence guard applies before anything is read: when a root `jest.config.*` file
|
|
30
|
+
* exists, it is not provable which configuration Jest actually loads, so no `package.json#jest`
|
|
31
|
+
* hints are produced. Presence is checked by directory entry name only.
|
|
32
|
+
*
|
|
33
|
+
* The manifest model intentionally does not carry `jest`, so `package.json` is read a second time here
|
|
34
|
+
* as plain text (same trade-off as the legacy ESLint readers): the loader stays the validity gate and
|
|
35
|
+
* the single reporter of a broken manifest, while this detector silently ignores every shape it cannot
|
|
36
|
+
* use. Ignoring is deliberate — an unusable `jest` block is not an error, and diagnosing one here would
|
|
37
|
+
* duplicate the manifest loader.
|
|
38
|
+
*/
|
|
39
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
40
|
+
import { resolve } from 'node:path';
|
|
41
|
+
import { loadProjectManifest, ProjectManifestError } from '../scanner/projectManifest.js';
|
|
42
|
+
import { classifyPackageSpecifier } from '../scanner/packageSpecifier.js';
|
|
43
|
+
/**
|
|
44
|
+
* The only `preset` packages recognized by this release.
|
|
45
|
+
*
|
|
46
|
+
* A fixed allowlist, not a resolution algorithm: `ts-jest` is supported because it is the published
|
|
47
|
+
* package name of the preset itself, so the string is already a complete package reference and needs
|
|
48
|
+
* no Jest-version knowledge to interpret. Any other preset name is unsupported and contributes no
|
|
49
|
+
* evidence, since guessing what an unknown preset string resolves to would create false confidence.
|
|
50
|
+
*
|
|
51
|
+
* A literal subpath of an allowlisted package (`"ts-jest/presets/default-esm"`) is accepted too,
|
|
52
|
+
* through the existing package-root normalization in {@link classifyPackageSpecifier}: the first path
|
|
53
|
+
* segment of such a specifier is the package that provides the preset.
|
|
54
|
+
*/
|
|
55
|
+
const PRESET_PACKAGE_NAMES = new Set(['ts-jest']);
|
|
56
|
+
/**
|
|
57
|
+
* The only `testEnvironment` packages recognized by this release.
|
|
58
|
+
*
|
|
59
|
+
* Again the complete package name only; the `"jsdom"` shorthand is deliberately absent from this
|
|
60
|
+
* release. Where Jest accepts `"jsdom"`, it does resolve it to the separately installed
|
|
61
|
+
* `jest-environment-jsdom` package - but whether that shorthand is available at all depends on the
|
|
62
|
+
* Jest major version (up to v27 the jsdom environment shipped inside Jest itself, so such a project
|
|
63
|
+
* declares no package to credit), and DepVitals neither reads nor resolves the Jest version of an
|
|
64
|
+
* analyzed project. The supported subset is therefore fixed to the exact package name; shorthand
|
|
65
|
+
* resolution is a separate change that must first define which Jest versions it applies to.
|
|
66
|
+
*/
|
|
67
|
+
const TEST_ENVIRONMENT_PACKAGE_NAMES = new Set(['jest-environment-jsdom']);
|
|
68
|
+
/**
|
|
69
|
+
* The only `transform` packages recognized by this release.
|
|
70
|
+
*
|
|
71
|
+
* A separate fixed allowlist rather than a reuse of the `preset` one: `ts-jest` is the only
|
|
72
|
+
* transformer credited, and it is supported for the same reason as the preset — the string is already
|
|
73
|
+
* the complete published package name, so nothing has to be resolved or versioned to interpret it.
|
|
74
|
+
* `jest-environment-jsdom` is deliberately absent, because a test environment is not a transformer;
|
|
75
|
+
* no other transform module is resolved, guessed, searched for in `node_modules` or matched by
|
|
76
|
+
* prefix, and transform maps are never flattened or searched recursively.
|
|
77
|
+
*/
|
|
78
|
+
const TRANSFORM_PACKAGE_NAMES = new Set(['ts-jest']);
|
|
79
|
+
/**
|
|
80
|
+
* Root Jest configuration file names that disable `package.json#jest` hints.
|
|
81
|
+
*
|
|
82
|
+
* The list is fixed to the extensions named by the supported contract; `jest.config.mts` and other
|
|
83
|
+
* spellings are not part of it, which only makes the guard narrower (it can drop hints, never add
|
|
84
|
+
* them). Presence of any listed name at the project root is enough; the file itself is never read or
|
|
85
|
+
* executed.
|
|
86
|
+
*
|
|
87
|
+
* Compared case-insensitively (see {@link hasRootJestConfigEntry}) because a case-insensitive
|
|
88
|
+
* filesystem treats `Jest.Config.JS` as the same file, and DepVitals must not disagree with itself
|
|
89
|
+
* about one project depending on the platform it runs on.
|
|
90
|
+
*/
|
|
91
|
+
const JEST_CONFIG_ENTRY_NAMES = new Set([
|
|
92
|
+
'jest.config.js',
|
|
93
|
+
'jest.config.mjs',
|
|
94
|
+
'jest.config.cjs',
|
|
95
|
+
'jest.config.ts',
|
|
96
|
+
'jest.config.json',
|
|
97
|
+
]);
|
|
98
|
+
/**
|
|
99
|
+
* Match the allowlisted subset of one `jest` configuration against the declared packages.
|
|
100
|
+
*
|
|
101
|
+
* Pure and side-effect free: it takes the raw `package.json#jest` JSON value (any shape, including
|
|
102
|
+
* something that is not an object) and the declared dependency names, and returns the declared
|
|
103
|
+
* packages named by `preset`, `testEnvironment` or the values of `transform`, in alphabetical order.
|
|
104
|
+
* Neither argument is mutated, and a candidate that is not declared is dropped, so this function can
|
|
105
|
+
* never describe an undeclared package as used.
|
|
106
|
+
*
|
|
107
|
+
* @param jestConfig - The raw `package.json#jest` value, validated here and never trusted.
|
|
108
|
+
* @param declaredPackageNames - Declared dependency names, the only names this may return.
|
|
109
|
+
*/
|
|
110
|
+
export function findJestConfigUsage(jestConfig, declaredPackageNames) {
|
|
111
|
+
if (!isPlainRecord(jestConfig)) {
|
|
112
|
+
return new Set();
|
|
113
|
+
}
|
|
114
|
+
const candidates = [
|
|
115
|
+
...matchAllowedPackage(jestConfig['preset'], PRESET_PACKAGE_NAMES),
|
|
116
|
+
...matchAllowedPackage(jestConfig['testEnvironment'], TEST_ENVIRONMENT_PACKAGE_NAMES),
|
|
117
|
+
...matchTransformValues(jestConfig['transform'], TRANSFORM_PACKAGE_NAMES),
|
|
118
|
+
];
|
|
119
|
+
const used = new Set();
|
|
120
|
+
for (const candidate of candidates) {
|
|
121
|
+
if (declaredPackageNames.has(candidate)) {
|
|
122
|
+
used.add(candidate);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Rebuilt from sorted names so iteration is deterministic for every input.
|
|
126
|
+
return new Set([...used].sort(compareNames));
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Collect the `package.json#jest` hints for the project rooted at `projectRoot`.
|
|
130
|
+
*
|
|
131
|
+
* The returned set is shaped for the analyzer's `configUsedNames` option (the Step 56 handoff), which
|
|
132
|
+
* is the only way configuration evidence reaches the analyzer. Nothing is decided here: the analyzer
|
|
133
|
+
* stays the sole owner of the unused/missing categories.
|
|
134
|
+
*
|
|
135
|
+
* No configuration problem is reported as an error. A missing manifest, an unreadable or invalid
|
|
136
|
+
* `package.json`, an unusable `jest` shape or an unreadable root all yield the empty set; the analyzer
|
|
137
|
+
* loads the manifest itself and remains the component that reports manifest failures, so this detector
|
|
138
|
+
* never replaces or duplicates that diagnosis.
|
|
139
|
+
*
|
|
140
|
+
* @param projectRoot - Project directory to inspect; resolved to an absolute path.
|
|
141
|
+
*/
|
|
142
|
+
export async function findJestManifestUsage(projectRoot) {
|
|
143
|
+
const root = resolve(projectRoot);
|
|
144
|
+
if (await hasRootJestConfigEntry(root)) {
|
|
145
|
+
return new Set();
|
|
146
|
+
}
|
|
147
|
+
let packageJsonPath;
|
|
148
|
+
let declaredPackageNames;
|
|
149
|
+
try {
|
|
150
|
+
const manifest = await loadProjectManifest(root);
|
|
151
|
+
packageJsonPath = manifest.packageJsonPath;
|
|
152
|
+
declaredPackageNames = manifest.declaredDependencyNames;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
if (error instanceof ProjectManifestError) {
|
|
156
|
+
return new Set();
|
|
157
|
+
}
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
return findJestConfigUsage(await readJestConfigValue(packageJsonPath), declaredPackageNames);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Whether a root Jest configuration file name exists in the project root.
|
|
164
|
+
*
|
|
165
|
+
* The root directory is listed by name only (`readdir`), so no entry is opened, stat-followed, read or
|
|
166
|
+
* executed. An unreadable or missing root simply means no root Jest config is known to be present.
|
|
167
|
+
* Names are compared case-insensitively so a case-insensitive filesystem (typical on Windows and
|
|
168
|
+
* macOS) cannot hide a root Jest config from this guard.
|
|
169
|
+
*/
|
|
170
|
+
export async function hasRootJestConfigEntry(root) {
|
|
171
|
+
let entries;
|
|
172
|
+
try {
|
|
173
|
+
entries = await readdir(root);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
return entries.some((entry) => JEST_CONFIG_ENTRY_NAMES.has(entry.toLowerCase()));
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Read the raw `package.json#jest` value, ignoring everything that cannot be used.
|
|
182
|
+
*
|
|
183
|
+
* The manifest is read as text and parsed with `JSON.parse`, so no target-project code runs. An
|
|
184
|
+
* unreadable file, invalid JSON, a non-object document or an absent `jest` key all yield `undefined`;
|
|
185
|
+
* the loader-facing diagnosis of a broken manifest stays in {@link loadProjectManifest}.
|
|
186
|
+
*/
|
|
187
|
+
async function readJestConfigValue(packageJsonPath) {
|
|
188
|
+
let text;
|
|
189
|
+
try {
|
|
190
|
+
text = await readFile(packageJsonPath, 'utf8');
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
let parsed;
|
|
196
|
+
try {
|
|
197
|
+
parsed = JSON.parse(text);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
return isPlainRecord(parsed) ? parsed['jest'] : undefined;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* The single allowlisted package named by one static string value, if any.
|
|
206
|
+
*
|
|
207
|
+
* Only strings are considered: a number, `null`, an array or an object contributes nothing, so a
|
|
208
|
+
* malformed field never becomes evidence. The string is classified with the shared package-specifier
|
|
209
|
+
* rules, which reject relative and absolute paths (`"./local.js"`, `"/opt/preset.js"`) and URI forms
|
|
210
|
+
* such as `"file:./preset.js"` as internal or unsupported. Whatever package root survives must then
|
|
211
|
+
* be an exact member of `allowedPackages`, and that exact-name rule is what rejects the remaining
|
|
212
|
+
* resolver-shaped values, including `<rootDir>/presets/x.js` (its first segment `<rootDir>` is not a
|
|
213
|
+
* package name DepVitals will ever allow) and `"ts-jest-extras"`. There is no prefix, suffix,
|
|
214
|
+
* substring or case-insensitive matching, so `"jsdom"`, `"TS-Jest"` and
|
|
215
|
+
* `"jest-environment-node"` never match an entry.
|
|
216
|
+
*/
|
|
217
|
+
function matchAllowedPackage(value, allowedPackages) {
|
|
218
|
+
if (typeof value !== 'string') {
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
const specifier = classifyPackageSpecifier(value);
|
|
222
|
+
if (specifier.kind !== 'external') {
|
|
223
|
+
return [];
|
|
224
|
+
}
|
|
225
|
+
return allowedPackages.has(specifier.packageName) ? [specifier.packageName] : [];
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* The allowlisted packages named by the *values* of one `jest.transform` map.
|
|
229
|
+
*
|
|
230
|
+
* Only values are read: `Object.values` is used precisely so that a key can never become evidence.
|
|
231
|
+
* Every key of a Jest transform map is a regular expression such as `"^.+\\.tsx?$"`, and a key that
|
|
232
|
+
* happens to read `"ts-jest"` is still only a pattern, so it credits nothing. A `transform` field
|
|
233
|
+
* that is not a plain JSON object (an array, a string, a number, `null`, absent) contributes nothing.
|
|
234
|
+
*/
|
|
235
|
+
function matchTransformValues(transform, allowedPackages) {
|
|
236
|
+
if (!isPlainRecord(transform)) {
|
|
237
|
+
return [];
|
|
238
|
+
}
|
|
239
|
+
const matches = [];
|
|
240
|
+
for (const value of Object.values(transform)) {
|
|
241
|
+
matches.push(...matchTransformValue(value, allowedPackages));
|
|
242
|
+
}
|
|
243
|
+
return matches;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The allowlisted package named by one `jest.transform` value, if any.
|
|
247
|
+
*
|
|
248
|
+
* Exactly two shapes are supported, and no others:
|
|
249
|
+
*
|
|
250
|
+
* - the transformer string itself, `"ts-jest"`, matched by the same rules as the other supported
|
|
251
|
+
* Jest fields - the value is classified first and must then be an exact member of
|
|
252
|
+
* `allowedPackages`, so `"./local-transform.js"`, `"<rootDir>/transform.js"`, `"file:./t.js"`,
|
|
253
|
+
* `""`, `"ts jest"`, `"ts-jest-extras"` and every other module yield nothing. As in `preset`, a
|
|
254
|
+
* literal subpath of an allowlisted package collapses to its package root
|
|
255
|
+
* (`"ts-jest/preprocessor.js"`, the historical ts-jest transformer path), because the first path
|
|
256
|
+
* segment still names the package that provides the transformer;
|
|
257
|
+
* - the `[transformer, options]` tuple: exactly two elements, the second a JSON options object, the
|
|
258
|
+
* first matched as above. The options object is only checked for being an object and is never
|
|
259
|
+
* inspected, so a supported package name that appears only inside it - as a label or an option
|
|
260
|
+
* value - is not evidence.
|
|
261
|
+
*
|
|
262
|
+
* A one- or three-element array, a non-object second tuple element, an object used in place of the
|
|
263
|
+
* whole value or any other shape is outside the supported subset and yields nothing.
|
|
264
|
+
*/
|
|
265
|
+
function matchTransformValue(value, allowedPackages) {
|
|
266
|
+
if (Array.isArray(value)) {
|
|
267
|
+
if (value.length !== 2 || !isPlainRecord(value[1])) {
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
return matchAllowedPackage(value[0], allowedPackages);
|
|
271
|
+
}
|
|
272
|
+
return matchAllowedPackage(value, allowedPackages);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* A JSON object (not an array, not `null`) whose keys are strings.
|
|
276
|
+
*/
|
|
277
|
+
function isPlainRecord(value) {
|
|
278
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Locale-independent lexicographic ordering, so the same configuration always yields the same order.
|
|
282
|
+
*/
|
|
283
|
+
function compareNames(a, b) {
|
|
284
|
+
if (a < b) {
|
|
285
|
+
return -1;
|
|
286
|
+
}
|
|
287
|
+
if (a > b) {
|
|
288
|
+
return 1;
|
|
289
|
+
}
|
|
290
|
+
return 0;
|
|
291
|
+
}
|
|
292
|
+
//# sourceMappingURL=jestManifestConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jestManifestConfig.js","sourceRoot":"","sources":["../../src/detectors/jestManifestConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -79,7 +79,33 @@ function findingsSections(result) {
|
|
|
79
79
|
function renderSection(section) {
|
|
80
80
|
const names = [...section.names].sort(compareNames);
|
|
81
81
|
const count = String(names.length);
|
|
82
|
-
|
|
82
|
+
// Package names come from target-project source, so a hostile name may carry a terminal control
|
|
83
|
+
// sequence (for example an ESC decoded from `"\x1b[2J"`). Escape C0/C1 control codes and DEL as
|
|
84
|
+
// `\uXXXX` before rendering, so the report can never alter the user's display.
|
|
85
|
+
return [
|
|
86
|
+
`${section.heading} (${count})`,
|
|
87
|
+
...names.map((name) => ` ${escapeControlCharacters(name)}`),
|
|
88
|
+
].join('\n');
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Escape C0/C1 control characters and DEL as `\uXXXX` so a package name extracted from target
|
|
92
|
+
* source can never carry a terminal control sequence (such as an ESC from `"\x1b[2J"`) into the
|
|
93
|
+
* rendered report. Printable characters pass through unchanged.
|
|
94
|
+
*
|
|
95
|
+
* The scan is written as explicit code points instead of a control-character regex range so the
|
|
96
|
+
* ESLint `no-control-regex` rule stays meaningful.
|
|
97
|
+
*/
|
|
98
|
+
function escapeControlCharacters(value) {
|
|
99
|
+
let out = '';
|
|
100
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
101
|
+
const code = value.charCodeAt(index);
|
|
102
|
+
if (code < 0x20 || (code >= 0x7f && code <= 0x9f)) {
|
|
103
|
+
out += `\\u${code.toString(16).padStart(4, '0')}`;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
out += value[index] ?? '';
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
83
109
|
}
|
|
84
110
|
/**
|
|
85
111
|
* Locale-independent lexicographic (codepoint) ordering, matching the comparator convention already
|
|
@@ -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,OAAO,
|
|
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,SAAS,uBAAuB,CAAC,KAAa;IAC5C,IAAI,GAAG,GAAG,EAAE,CAAC;IAEb,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAErC,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YAClD,GAAG,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YAClD,SAAS;QACX,CAAC;QAED,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,CAAS,EAAE,CAAS;IACxC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACV,OAAO,CAAC,CAAC,CAAC;IACZ,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACV,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -48,6 +48,14 @@ export declare class ModuleSpecifierError extends Error {
|
|
|
48
48
|
readonly offset: number;
|
|
49
49
|
constructor(message: string, code: ModuleSpecifierErrorCode, offset: number);
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Options for {@link extractModuleSpecifiers}.
|
|
53
|
+
*/
|
|
54
|
+
export type ExtractModuleSpecifiersOptions = {
|
|
55
|
+
jsx?: boolean;
|
|
56
|
+
/** Treat top-level `await` as a keyword. Omitted and false retain script/CommonJS behavior. */
|
|
57
|
+
module?: boolean;
|
|
58
|
+
};
|
|
51
59
|
/**
|
|
52
60
|
* Extract the statically knowable module specifiers from `source`.
|
|
53
61
|
*
|
|
@@ -56,5 +64,5 @@ export declare class ModuleSpecifierError extends Error {
|
|
|
56
64
|
* @throws {ModuleSpecifierError} when the source reaches an unterminated or malformed lexical state
|
|
57
65
|
* from which the scanner cannot safely continue.
|
|
58
66
|
*/
|
|
59
|
-
export declare function extractModuleSpecifiers(source: string): readonly ModuleSpecifierOccurrence[];
|
|
67
|
+
export declare function extractModuleSpecifiers(source: string, options?: ExtractModuleSpecifiersOptions): readonly ModuleSpecifierOccurrence[];
|
|
60
68
|
//# 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;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,
|
|
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,+FAA+F;IAC/F,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,8BAAmC,GAC3C,SAAS,yBAAyB,EAAE,CAEtC"}
|