react-doctor 0.9.2 → 0.9.3-dev.9bb44e7
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 +2 -2
- package/dist/cli.js +1043 -226
- package/dist/index.d.ts +9 -3
- package/dist/index.js +719 -124
- package/dist/lsp.js +706 -120
- package/dist/{run-scan-app-DZ5jGWFf.js → run-scan-app-DHRvqfkX.js} +288 -216
- package/package.json +8 -7
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1a34c548-5d3e-559c-8a3a-8a869ca2847a")}catch(e){}}();
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as NodeChildProcess from "node:child_process";
|
|
5
5
|
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
|
|
@@ -8,18 +8,19 @@ import path from "node:path";
|
|
|
8
8
|
import * as NFS from "node:fs";
|
|
9
9
|
import fs, { mkdtempSync, rmSync } from "node:fs";
|
|
10
10
|
import process$1 from "node:process";
|
|
11
|
-
import
|
|
11
|
+
import { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, FRAMEWORK_TOKENS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, REACT_DOCTOR_RULE_REGISTRY, REACT_DOCTOR_SCAN_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor/core";
|
|
12
12
|
import * as Crypto from "node:crypto";
|
|
13
13
|
import crypto, { createHash, randomUUID } from "node:crypto";
|
|
14
14
|
import { ResolverFactory } from "oxc-resolver";
|
|
15
15
|
import ts from "typescript";
|
|
16
|
+
import * as NodeUrl from "node:url";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
16
18
|
import * as OS from "node:os";
|
|
17
19
|
import os, { tmpdir } from "node:os";
|
|
18
20
|
import { parseJSON5 } from "confbox";
|
|
19
|
-
import * as NodeUrl from "node:url";
|
|
20
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
21
21
|
import { createJiti } from "jiti";
|
|
22
22
|
import { ANALYZED_MANIFEST_FILENAMES, DEFAULT_EXTENSIONS } from "deslop-js/analyzed-inputs";
|
|
23
|
+
import { convertToTSX } from "@astrojs/compiler/sync";
|
|
23
24
|
import { gzipSync } from "node:zlib";
|
|
24
25
|
import * as Sentry from "@sentry/node";
|
|
25
26
|
import { performance as performance$1 } from "node:perf_hooks";
|
|
@@ -13342,7 +13343,7 @@ const Number$4 = globalThis.Number;
|
|
|
13342
13343
|
* @category constructors
|
|
13343
13344
|
* @since 2.0.0
|
|
13344
13345
|
*/
|
|
13345
|
-
const parse = (s) => {
|
|
13346
|
+
const parse$1 = (s) => {
|
|
13346
13347
|
if (s === "NaN") return some(NaN);
|
|
13347
13348
|
if (s === "Infinity") return some(Infinity);
|
|
13348
13349
|
if (s === "-Infinity") return some(-Infinity);
|
|
@@ -17405,12 +17406,12 @@ TaggedError("EncodingError");
|
|
|
17405
17406
|
//#endregion
|
|
17406
17407
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.70/node_modules/effect/dist/internal/schema/annotations.js
|
|
17407
17408
|
/** @internal */
|
|
17408
|
-
function resolve(ast) {
|
|
17409
|
+
function resolve$1(ast) {
|
|
17409
17410
|
return ast.checks ? ast.checks[ast.checks.length - 1].annotations : ast.annotations;
|
|
17410
17411
|
}
|
|
17411
17412
|
/** @internal */
|
|
17412
17413
|
function resolveAt(key) {
|
|
17413
|
-
return (ast) => resolve(ast)?.[key];
|
|
17414
|
+
return (ast) => resolve$1(ast)?.[key];
|
|
17414
17415
|
}
|
|
17415
17416
|
/** @internal */
|
|
17416
17417
|
const resolveIdentifier = /* @__PURE__ */ resolveAt("identifier");
|
|
@@ -21162,7 +21163,7 @@ function asSync(parser) {
|
|
|
21162
21163
|
}
|
|
21163
21164
|
const recur$1 = /* @__PURE__ */ memoize((ast) => {
|
|
21164
21165
|
let parser;
|
|
21165
|
-
const astOptions = resolve(ast)?.["parseOptions"];
|
|
21166
|
+
const astOptions = resolve$1(ast)?.["parseOptions"];
|
|
21166
21167
|
if (!ast.context && !ast.encoding && !ast.checks) return (ou, options) => {
|
|
21167
21168
|
parser ??= ast.getParser(recur$1);
|
|
21168
21169
|
if (astOptions) options = {
|
|
@@ -60767,7 +60768,7 @@ var UrlParamsError = class extends TaggedError("UrlParamsError") {};
|
|
|
60767
60768
|
* @category converting
|
|
60768
60769
|
* @since 4.0.0
|
|
60769
60770
|
*/
|
|
60770
|
-
const makeUrl = (url, params, hash) => {
|
|
60771
|
+
const makeUrl$1 = (url, params, hash) => {
|
|
60771
60772
|
try {
|
|
60772
60773
|
const urlInstance = new URL(url, baseUrl());
|
|
60773
60774
|
for (let i = 0; i < params.params.length; i++) {
|
|
@@ -61401,7 +61402,7 @@ const Proto$2 = {
|
|
|
61401
61402
|
const make$10 = (f) => makeWith$1((effect) => flatMap$2(effect, (request) => withFiber((fiber) => {
|
|
61402
61403
|
const scopedController = scopedRequests.get(request);
|
|
61403
61404
|
const controller = scopedController ?? new AbortController();
|
|
61404
|
-
const urlResult = makeUrl(request.url, request.urlParams, getOrUndefined(request.hash));
|
|
61405
|
+
const urlResult = makeUrl$1(request.url, request.urlParams, getOrUndefined(request.hash));
|
|
61405
61406
|
if (isFailure(urlResult)) return fail$4(new HttpClientError({ reason: new InvalidUrlError({
|
|
61406
61407
|
request,
|
|
61407
61408
|
cause: urlResult.failure
|
|
@@ -61840,7 +61841,7 @@ const layer$8 = (loggers, options) => effect(CurrentLoggers, withFiber$1(fnUntra
|
|
|
61840
61841
|
* @since 4.0.0
|
|
61841
61842
|
*/
|
|
61842
61843
|
const policy = /* @__PURE__ */ forever$1.pipe(passthrough$2, /* @__PURE__ */ addDelay((error) => {
|
|
61843
|
-
if (isHttpClientError(error) && error.reason._tag === "StatusCodeError" && error.reason.response.status === 429) return succeed$2(seconds(fromUndefinedOr(error.reason.response.headers["retry-after"]).pipe(flatMap$5(parse), getOrElse$1(() => 5))));
|
|
61844
|
+
if (isHttpClientError(error) && error.reason._tag === "StatusCodeError" && error.reason.response.status === 429) return succeed$2(seconds(fromUndefinedOr(error.reason.response.headers["retry-after"]).pipe(flatMap$5(parse$1), getOrElse$1(() => 5))));
|
|
61844
61845
|
return succeed$2(seconds(1));
|
|
61845
61846
|
}));
|
|
61846
61847
|
/**
|
|
@@ -64549,6 +64550,428 @@ const layer$1 = /* @__PURE__ */ succeed$3(Path$1)({
|
|
|
64549
64550
|
toFileUrl
|
|
64550
64551
|
});
|
|
64551
64552
|
//#endregion
|
|
64553
|
+
//#region ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
|
|
64554
|
+
var comma = ",".charCodeAt(0);
|
|
64555
|
+
";".charCodeAt(0);
|
|
64556
|
+
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
64557
|
+
var intToChar = new Uint8Array(64);
|
|
64558
|
+
var charToInt = new Uint8Array(128);
|
|
64559
|
+
for (let i = 0; i < chars.length; i++) {
|
|
64560
|
+
const c = chars.charCodeAt(i);
|
|
64561
|
+
intToChar[i] = c;
|
|
64562
|
+
charToInt[c] = i;
|
|
64563
|
+
}
|
|
64564
|
+
function decodeInteger(reader, relative) {
|
|
64565
|
+
let value = 0;
|
|
64566
|
+
let shift = 0;
|
|
64567
|
+
let integer = 0;
|
|
64568
|
+
do {
|
|
64569
|
+
integer = charToInt[reader.next()];
|
|
64570
|
+
value |= (integer & 31) << shift;
|
|
64571
|
+
shift += 5;
|
|
64572
|
+
} while (integer & 32);
|
|
64573
|
+
const shouldNegate = value & 1;
|
|
64574
|
+
value >>>= 1;
|
|
64575
|
+
if (shouldNegate) value = -2147483648 | -value;
|
|
64576
|
+
return relative + value;
|
|
64577
|
+
}
|
|
64578
|
+
function hasMoreVlq(reader, max) {
|
|
64579
|
+
if (reader.pos >= max) return false;
|
|
64580
|
+
return reader.peek() !== comma;
|
|
64581
|
+
}
|
|
64582
|
+
var StringReader = class {
|
|
64583
|
+
constructor(buffer) {
|
|
64584
|
+
this.pos = 0;
|
|
64585
|
+
this.buffer = buffer;
|
|
64586
|
+
}
|
|
64587
|
+
next() {
|
|
64588
|
+
return this.buffer.charCodeAt(this.pos++);
|
|
64589
|
+
}
|
|
64590
|
+
peek() {
|
|
64591
|
+
return this.buffer.charCodeAt(this.pos);
|
|
64592
|
+
}
|
|
64593
|
+
indexOf(char) {
|
|
64594
|
+
const { buffer, pos } = this;
|
|
64595
|
+
const idx = buffer.indexOf(char, pos);
|
|
64596
|
+
return idx === -1 ? buffer.length : idx;
|
|
64597
|
+
}
|
|
64598
|
+
};
|
|
64599
|
+
function decode(mappings) {
|
|
64600
|
+
const { length } = mappings;
|
|
64601
|
+
const reader = new StringReader(mappings);
|
|
64602
|
+
const decoded = [];
|
|
64603
|
+
let genColumn = 0;
|
|
64604
|
+
let sourcesIndex = 0;
|
|
64605
|
+
let sourceLine = 0;
|
|
64606
|
+
let sourceColumn = 0;
|
|
64607
|
+
let namesIndex = 0;
|
|
64608
|
+
do {
|
|
64609
|
+
const semi = reader.indexOf(";");
|
|
64610
|
+
const line = [];
|
|
64611
|
+
let sorted = true;
|
|
64612
|
+
let lastCol = 0;
|
|
64613
|
+
genColumn = 0;
|
|
64614
|
+
while (reader.pos < semi) {
|
|
64615
|
+
let seg;
|
|
64616
|
+
genColumn = decodeInteger(reader, genColumn);
|
|
64617
|
+
if (genColumn < lastCol) sorted = false;
|
|
64618
|
+
lastCol = genColumn;
|
|
64619
|
+
if (hasMoreVlq(reader, semi)) {
|
|
64620
|
+
sourcesIndex = decodeInteger(reader, sourcesIndex);
|
|
64621
|
+
sourceLine = decodeInteger(reader, sourceLine);
|
|
64622
|
+
sourceColumn = decodeInteger(reader, sourceColumn);
|
|
64623
|
+
if (hasMoreVlq(reader, semi)) {
|
|
64624
|
+
namesIndex = decodeInteger(reader, namesIndex);
|
|
64625
|
+
seg = [
|
|
64626
|
+
genColumn,
|
|
64627
|
+
sourcesIndex,
|
|
64628
|
+
sourceLine,
|
|
64629
|
+
sourceColumn,
|
|
64630
|
+
namesIndex
|
|
64631
|
+
];
|
|
64632
|
+
} else seg = [
|
|
64633
|
+
genColumn,
|
|
64634
|
+
sourcesIndex,
|
|
64635
|
+
sourceLine,
|
|
64636
|
+
sourceColumn
|
|
64637
|
+
];
|
|
64638
|
+
} else seg = [genColumn];
|
|
64639
|
+
line.push(seg);
|
|
64640
|
+
reader.pos++;
|
|
64641
|
+
}
|
|
64642
|
+
if (!sorted) sort(line);
|
|
64643
|
+
decoded.push(line);
|
|
64644
|
+
reader.pos = semi + 1;
|
|
64645
|
+
} while (reader.pos <= length);
|
|
64646
|
+
return decoded;
|
|
64647
|
+
}
|
|
64648
|
+
function sort(line) {
|
|
64649
|
+
line.sort(sortComparator$1);
|
|
64650
|
+
}
|
|
64651
|
+
function sortComparator$1(a, b) {
|
|
64652
|
+
return a[0] - b[0];
|
|
64653
|
+
}
|
|
64654
|
+
//#endregion
|
|
64655
|
+
//#region ../../node_modules/.pnpm/@jridgewell+resolve-uri@3.1.2/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs
|
|
64656
|
+
const schemeRegex = /^[\w+.-]+:\/\//;
|
|
64657
|
+
/**
|
|
64658
|
+
* Matches the parts of a URL:
|
|
64659
|
+
* 1. Scheme, including ":", guaranteed.
|
|
64660
|
+
* 2. User/password, including "@", optional.
|
|
64661
|
+
* 3. Host, guaranteed.
|
|
64662
|
+
* 4. Port, including ":", optional.
|
|
64663
|
+
* 5. Path, including "/", optional.
|
|
64664
|
+
* 6. Query, including "?", optional.
|
|
64665
|
+
* 7. Hash, including "#", optional.
|
|
64666
|
+
*/
|
|
64667
|
+
const urlRegex = /^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?/;
|
|
64668
|
+
/**
|
|
64669
|
+
* File URLs are weird. They dont' need the regular `//` in the scheme, they may or may not start
|
|
64670
|
+
* with a leading `/`, they can have a domain (but only if they don't start with a Windows drive).
|
|
64671
|
+
*
|
|
64672
|
+
* 1. Host, optional.
|
|
64673
|
+
* 2. Path, which may include "/", guaranteed.
|
|
64674
|
+
* 3. Query, including "?", optional.
|
|
64675
|
+
* 4. Hash, including "#", optional.
|
|
64676
|
+
*/
|
|
64677
|
+
const fileRegex = /^file:(?:\/\/((?![a-z]:)[^/#?]*)?)?(\/?[^#?]*)(\?[^#]*)?(#.*)?/i;
|
|
64678
|
+
function isAbsoluteUrl(input) {
|
|
64679
|
+
return schemeRegex.test(input);
|
|
64680
|
+
}
|
|
64681
|
+
function isSchemeRelativeUrl(input) {
|
|
64682
|
+
return input.startsWith("//");
|
|
64683
|
+
}
|
|
64684
|
+
function isAbsolutePath(input) {
|
|
64685
|
+
return input.startsWith("/");
|
|
64686
|
+
}
|
|
64687
|
+
function isFileUrl(input) {
|
|
64688
|
+
return input.startsWith("file:");
|
|
64689
|
+
}
|
|
64690
|
+
function isRelative(input) {
|
|
64691
|
+
return /^[.?#]/.test(input);
|
|
64692
|
+
}
|
|
64693
|
+
function parseAbsoluteUrl(input) {
|
|
64694
|
+
const match = urlRegex.exec(input);
|
|
64695
|
+
return makeUrl(match[1], match[2] || "", match[3], match[4] || "", match[5] || "/", match[6] || "", match[7] || "");
|
|
64696
|
+
}
|
|
64697
|
+
function parseFileUrl(input) {
|
|
64698
|
+
const match = fileRegex.exec(input);
|
|
64699
|
+
const path = match[2];
|
|
64700
|
+
return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path) ? path : "/" + path, match[3] || "", match[4] || "");
|
|
64701
|
+
}
|
|
64702
|
+
function makeUrl(scheme, user, host, port, path, query, hash) {
|
|
64703
|
+
return {
|
|
64704
|
+
scheme,
|
|
64705
|
+
user,
|
|
64706
|
+
host,
|
|
64707
|
+
port,
|
|
64708
|
+
path,
|
|
64709
|
+
query,
|
|
64710
|
+
hash,
|
|
64711
|
+
type: 7
|
|
64712
|
+
};
|
|
64713
|
+
}
|
|
64714
|
+
function parseUrl(input) {
|
|
64715
|
+
if (isSchemeRelativeUrl(input)) {
|
|
64716
|
+
const url = parseAbsoluteUrl("http:" + input);
|
|
64717
|
+
url.scheme = "";
|
|
64718
|
+
url.type = 6;
|
|
64719
|
+
return url;
|
|
64720
|
+
}
|
|
64721
|
+
if (isAbsolutePath(input)) {
|
|
64722
|
+
const url = parseAbsoluteUrl("http://foo.com" + input);
|
|
64723
|
+
url.scheme = "";
|
|
64724
|
+
url.host = "";
|
|
64725
|
+
url.type = 5;
|
|
64726
|
+
return url;
|
|
64727
|
+
}
|
|
64728
|
+
if (isFileUrl(input)) return parseFileUrl(input);
|
|
64729
|
+
if (isAbsoluteUrl(input)) return parseAbsoluteUrl(input);
|
|
64730
|
+
const url = parseAbsoluteUrl("http://foo.com/" + input);
|
|
64731
|
+
url.scheme = "";
|
|
64732
|
+
url.host = "";
|
|
64733
|
+
url.type = input ? input.startsWith("?") ? 3 : input.startsWith("#") ? 2 : 4 : 1;
|
|
64734
|
+
return url;
|
|
64735
|
+
}
|
|
64736
|
+
function stripPathFilename(path) {
|
|
64737
|
+
if (path.endsWith("/..")) return path;
|
|
64738
|
+
const index = path.lastIndexOf("/");
|
|
64739
|
+
return path.slice(0, index + 1);
|
|
64740
|
+
}
|
|
64741
|
+
function mergePaths(url, base) {
|
|
64742
|
+
normalizePath(base, base.type);
|
|
64743
|
+
if (url.path === "/") url.path = base.path;
|
|
64744
|
+
else url.path = stripPathFilename(base.path) + url.path;
|
|
64745
|
+
}
|
|
64746
|
+
/**
|
|
64747
|
+
* The path can have empty directories "//", unneeded parents "foo/..", or current directory
|
|
64748
|
+
* "foo/.". We need to normalize to a standard representation.
|
|
64749
|
+
*/
|
|
64750
|
+
function normalizePath(url, type) {
|
|
64751
|
+
const rel = type <= 4;
|
|
64752
|
+
const pieces = url.path.split("/");
|
|
64753
|
+
let pointer = 1;
|
|
64754
|
+
let positive = 0;
|
|
64755
|
+
let addTrailingSlash = false;
|
|
64756
|
+
for (let i = 1; i < pieces.length; i++) {
|
|
64757
|
+
const piece = pieces[i];
|
|
64758
|
+
if (!piece) {
|
|
64759
|
+
addTrailingSlash = true;
|
|
64760
|
+
continue;
|
|
64761
|
+
}
|
|
64762
|
+
addTrailingSlash = false;
|
|
64763
|
+
if (piece === ".") continue;
|
|
64764
|
+
if (piece === "..") {
|
|
64765
|
+
if (positive) {
|
|
64766
|
+
addTrailingSlash = true;
|
|
64767
|
+
positive--;
|
|
64768
|
+
pointer--;
|
|
64769
|
+
} else if (rel) pieces[pointer++] = piece;
|
|
64770
|
+
continue;
|
|
64771
|
+
}
|
|
64772
|
+
pieces[pointer++] = piece;
|
|
64773
|
+
positive++;
|
|
64774
|
+
}
|
|
64775
|
+
let path = "";
|
|
64776
|
+
for (let i = 1; i < pointer; i++) path += "/" + pieces[i];
|
|
64777
|
+
if (!path || addTrailingSlash && !path.endsWith("/..")) path += "/";
|
|
64778
|
+
url.path = path;
|
|
64779
|
+
}
|
|
64780
|
+
/**
|
|
64781
|
+
* Attempts to resolve `input` URL/path relative to `base`.
|
|
64782
|
+
*/
|
|
64783
|
+
function resolve(input, base) {
|
|
64784
|
+
if (!input && !base) return "";
|
|
64785
|
+
const url = parseUrl(input);
|
|
64786
|
+
let inputType = url.type;
|
|
64787
|
+
if (base && inputType !== 7) {
|
|
64788
|
+
const baseUrl = parseUrl(base);
|
|
64789
|
+
const baseType = baseUrl.type;
|
|
64790
|
+
switch (inputType) {
|
|
64791
|
+
case 1: url.hash = baseUrl.hash;
|
|
64792
|
+
case 2: url.query = baseUrl.query;
|
|
64793
|
+
case 3:
|
|
64794
|
+
case 4: mergePaths(url, baseUrl);
|
|
64795
|
+
case 5:
|
|
64796
|
+
url.user = baseUrl.user;
|
|
64797
|
+
url.host = baseUrl.host;
|
|
64798
|
+
url.port = baseUrl.port;
|
|
64799
|
+
case 6: url.scheme = baseUrl.scheme;
|
|
64800
|
+
}
|
|
64801
|
+
if (baseType > inputType) inputType = baseType;
|
|
64802
|
+
}
|
|
64803
|
+
normalizePath(url, inputType);
|
|
64804
|
+
const queryHash = url.query + url.hash;
|
|
64805
|
+
switch (inputType) {
|
|
64806
|
+
case 2:
|
|
64807
|
+
case 3: return queryHash;
|
|
64808
|
+
case 4: {
|
|
64809
|
+
const path = url.path.slice(1);
|
|
64810
|
+
if (!path) return queryHash || ".";
|
|
64811
|
+
if (isRelative(base || input) && !isRelative(path)) return "./" + path + queryHash;
|
|
64812
|
+
return path + queryHash;
|
|
64813
|
+
}
|
|
64814
|
+
case 5: return url.path + queryHash;
|
|
64815
|
+
default: return url.scheme + "//" + url.user + url.host + url.port + url.path + queryHash;
|
|
64816
|
+
}
|
|
64817
|
+
}
|
|
64818
|
+
//#endregion
|
|
64819
|
+
//#region ../../node_modules/.pnpm/@jridgewell+trace-mapping@0.3.31/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs
|
|
64820
|
+
function stripFilename(path) {
|
|
64821
|
+
if (!path) return "";
|
|
64822
|
+
const index = path.lastIndexOf("/");
|
|
64823
|
+
return path.slice(0, index + 1);
|
|
64824
|
+
}
|
|
64825
|
+
function resolver(mapUrl, sourceRoot) {
|
|
64826
|
+
const from = stripFilename(mapUrl);
|
|
64827
|
+
const prefix = sourceRoot ? sourceRoot + "/" : "";
|
|
64828
|
+
return (source) => resolve(prefix + (source || ""), from);
|
|
64829
|
+
}
|
|
64830
|
+
var COLUMN = 0;
|
|
64831
|
+
var SOURCES_INDEX = 1;
|
|
64832
|
+
var SOURCE_LINE = 2;
|
|
64833
|
+
var SOURCE_COLUMN = 3;
|
|
64834
|
+
var NAMES_INDEX = 4;
|
|
64835
|
+
function maybeSort(mappings, owned) {
|
|
64836
|
+
const unsortedIndex = nextUnsortedSegmentLine(mappings, 0);
|
|
64837
|
+
if (unsortedIndex === mappings.length) return mappings;
|
|
64838
|
+
if (!owned) mappings = mappings.slice();
|
|
64839
|
+
for (let i = unsortedIndex; i < mappings.length; i = nextUnsortedSegmentLine(mappings, i + 1)) mappings[i] = sortSegments(mappings[i], owned);
|
|
64840
|
+
return mappings;
|
|
64841
|
+
}
|
|
64842
|
+
function nextUnsortedSegmentLine(mappings, start) {
|
|
64843
|
+
for (let i = start; i < mappings.length; i++) if (!isSorted(mappings[i])) return i;
|
|
64844
|
+
return mappings.length;
|
|
64845
|
+
}
|
|
64846
|
+
function isSorted(line) {
|
|
64847
|
+
for (let j = 1; j < line.length; j++) if (line[j][COLUMN] < line[j - 1][COLUMN]) return false;
|
|
64848
|
+
return true;
|
|
64849
|
+
}
|
|
64850
|
+
function sortSegments(line, owned) {
|
|
64851
|
+
if (!owned) line = line.slice();
|
|
64852
|
+
return line.sort(sortComparator);
|
|
64853
|
+
}
|
|
64854
|
+
function sortComparator(a, b) {
|
|
64855
|
+
return a[COLUMN] - b[COLUMN];
|
|
64856
|
+
}
|
|
64857
|
+
var found = false;
|
|
64858
|
+
function binarySearch(haystack, needle, low, high) {
|
|
64859
|
+
while (low <= high) {
|
|
64860
|
+
const mid = low + (high - low >> 1);
|
|
64861
|
+
const cmp = haystack[mid][COLUMN] - needle;
|
|
64862
|
+
if (cmp === 0) {
|
|
64863
|
+
found = true;
|
|
64864
|
+
return mid;
|
|
64865
|
+
}
|
|
64866
|
+
if (cmp < 0) low = mid + 1;
|
|
64867
|
+
else high = mid - 1;
|
|
64868
|
+
}
|
|
64869
|
+
found = false;
|
|
64870
|
+
return low - 1;
|
|
64871
|
+
}
|
|
64872
|
+
function upperBound(haystack, needle, index) {
|
|
64873
|
+
for (let i = index + 1; i < haystack.length; index = i++) if (haystack[i][COLUMN] !== needle) break;
|
|
64874
|
+
return index;
|
|
64875
|
+
}
|
|
64876
|
+
function lowerBound(haystack, needle, index) {
|
|
64877
|
+
for (let i = index - 1; i >= 0; index = i--) if (haystack[i][COLUMN] !== needle) break;
|
|
64878
|
+
return index;
|
|
64879
|
+
}
|
|
64880
|
+
function memoizedState() {
|
|
64881
|
+
return {
|
|
64882
|
+
lastKey: -1,
|
|
64883
|
+
lastNeedle: -1,
|
|
64884
|
+
lastIndex: -1
|
|
64885
|
+
};
|
|
64886
|
+
}
|
|
64887
|
+
function memoizedBinarySearch(haystack, needle, state, key) {
|
|
64888
|
+
const { lastKey, lastNeedle, lastIndex } = state;
|
|
64889
|
+
let low = 0;
|
|
64890
|
+
let high = haystack.length - 1;
|
|
64891
|
+
if (key === lastKey) {
|
|
64892
|
+
if (needle === lastNeedle) {
|
|
64893
|
+
found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
|
|
64894
|
+
return lastIndex;
|
|
64895
|
+
}
|
|
64896
|
+
if (needle >= lastNeedle) low = lastIndex === -1 ? 0 : lastIndex;
|
|
64897
|
+
else high = lastIndex;
|
|
64898
|
+
}
|
|
64899
|
+
state.lastKey = key;
|
|
64900
|
+
state.lastNeedle = needle;
|
|
64901
|
+
return state.lastIndex = binarySearch(haystack, needle, low, high);
|
|
64902
|
+
}
|
|
64903
|
+
function parse(map) {
|
|
64904
|
+
return typeof map === "string" ? JSON.parse(map) : map;
|
|
64905
|
+
}
|
|
64906
|
+
var LINE_GTR_ZERO = "`line` must be greater than 0 (lines start at line 1)";
|
|
64907
|
+
var COL_GTR_EQ_ZERO = "`column` must be greater than or equal to 0 (columns start at column 0)";
|
|
64908
|
+
var TraceMap = class {
|
|
64909
|
+
constructor(map, mapUrl) {
|
|
64910
|
+
const isString = typeof map === "string";
|
|
64911
|
+
if (!isString && map._decodedMemo) return map;
|
|
64912
|
+
const parsed = parse(map);
|
|
64913
|
+
const { version, file, names, sourceRoot, sources, sourcesContent } = parsed;
|
|
64914
|
+
this.version = version;
|
|
64915
|
+
this.file = file;
|
|
64916
|
+
this.names = names || [];
|
|
64917
|
+
this.sourceRoot = sourceRoot;
|
|
64918
|
+
this.sources = sources;
|
|
64919
|
+
this.sourcesContent = sourcesContent;
|
|
64920
|
+
this.ignoreList = parsed.ignoreList || parsed.x_google_ignoreList || void 0;
|
|
64921
|
+
const resolve = resolver(mapUrl, sourceRoot);
|
|
64922
|
+
this.resolvedSources = sources.map(resolve);
|
|
64923
|
+
const { mappings } = parsed;
|
|
64924
|
+
if (typeof mappings === "string") {
|
|
64925
|
+
this._encoded = mappings;
|
|
64926
|
+
this._decoded = void 0;
|
|
64927
|
+
} else if (Array.isArray(mappings)) {
|
|
64928
|
+
this._encoded = void 0;
|
|
64929
|
+
this._decoded = maybeSort(mappings, isString);
|
|
64930
|
+
} else if (parsed.sections) throw new Error(`TraceMap passed sectioned source map, please use FlattenMap export instead`);
|
|
64931
|
+
else throw new Error(`invalid source map: ${JSON.stringify(parsed)}`);
|
|
64932
|
+
this._decodedMemo = memoizedState();
|
|
64933
|
+
this._bySources = void 0;
|
|
64934
|
+
this._bySourceMemos = void 0;
|
|
64935
|
+
}
|
|
64936
|
+
};
|
|
64937
|
+
function cast(map) {
|
|
64938
|
+
return map;
|
|
64939
|
+
}
|
|
64940
|
+
function decodedMappings(map) {
|
|
64941
|
+
var _a;
|
|
64942
|
+
return (_a = cast(map))._decoded || (_a._decoded = decode(cast(map)._encoded));
|
|
64943
|
+
}
|
|
64944
|
+
function originalPositionFor(map, needle) {
|
|
64945
|
+
let { line, column, bias } = needle;
|
|
64946
|
+
line--;
|
|
64947
|
+
if (line < 0) throw new Error(LINE_GTR_ZERO);
|
|
64948
|
+
if (column < 0) throw new Error(COL_GTR_EQ_ZERO);
|
|
64949
|
+
const decoded = decodedMappings(map);
|
|
64950
|
+
if (line >= decoded.length) return OMapping(null, null, null, null);
|
|
64951
|
+
const segments = decoded[line];
|
|
64952
|
+
const index = traceSegmentInternal(segments, cast(map)._decodedMemo, line, column, bias || 1);
|
|
64953
|
+
if (index === -1) return OMapping(null, null, null, null);
|
|
64954
|
+
const segment = segments[index];
|
|
64955
|
+
if (segment.length === 1) return OMapping(null, null, null, null);
|
|
64956
|
+
const { names, resolvedSources } = map;
|
|
64957
|
+
return OMapping(resolvedSources[segment[SOURCES_INDEX]], segment[SOURCE_LINE] + 1, segment[SOURCE_COLUMN], segment.length === 5 ? names[segment[NAMES_INDEX]] : null);
|
|
64958
|
+
}
|
|
64959
|
+
function OMapping(source, line, column, name) {
|
|
64960
|
+
return {
|
|
64961
|
+
source,
|
|
64962
|
+
line,
|
|
64963
|
+
column,
|
|
64964
|
+
name
|
|
64965
|
+
};
|
|
64966
|
+
}
|
|
64967
|
+
function traceSegmentInternal(segments, memo, line, column, bias) {
|
|
64968
|
+
let index = memoizedBinarySearch(segments, column, memo, line);
|
|
64969
|
+
if (found) index = (bias === -1 ? upperBound : lowerBound)(segments, column, index);
|
|
64970
|
+
else if (bias === -1) index++;
|
|
64971
|
+
if (index === -1 || index === segments.length) return -1;
|
|
64972
|
+
return index;
|
|
64973
|
+
}
|
|
64974
|
+
//#endregion
|
|
64552
64975
|
//#region ../core/dist/index.js
|
|
64553
64976
|
var __create = Object.create;
|
|
64554
64977
|
var __defProp = Object.defineProperty;
|
|
@@ -64618,7 +65041,7 @@ var AmbiguousProjectError = class extends Error {
|
|
|
64618
65041
|
};
|
|
64619
65042
|
const isProjectDiscoveryError = (value) => value instanceof ProjectNotFoundError || value instanceof NoReactDependencyError || value instanceof PackageJsonNotFoundError || value instanceof NotADirectoryError || value instanceof AmbiguousProjectError;
|
|
64620
65043
|
const HTML_FILE_PATTERN = /\.html$/i;
|
|
64621
|
-
const SOURCE_FILE_PATTERN = /\.(?:tsx?|jsx?|mts|mjs|[hH][tT][mM][lL])$/;
|
|
65044
|
+
const SOURCE_FILE_PATTERN = /\.(?:astro|tsx?|jsx?|mts|mjs|[hH][tT][mM][lL])$/;
|
|
64622
65045
|
const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
|
|
64623
65046
|
const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
|
|
64624
65047
|
const MINIFIED_SNIFF_BYTES = 65536;
|
|
@@ -64996,7 +65419,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
64996
65419
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
64997
65420
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
64998
65421
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
64999
|
-
const CORE_PACKAGE_VERSION = "0.9.
|
|
65422
|
+
const CORE_PACKAGE_VERSION = "0.9.3";
|
|
65000
65423
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
65001
65424
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
65002
65425
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -65375,6 +65798,7 @@ const FRAMEWORK_PACKAGES = {
|
|
|
65375
65798
|
"@tanstack/react-start": "tanstack-start",
|
|
65376
65799
|
"@remix-run/react": "remix",
|
|
65377
65800
|
gatsby: "gatsby",
|
|
65801
|
+
astro: "astro",
|
|
65378
65802
|
vite: "vite",
|
|
65379
65803
|
"react-scripts": "cra",
|
|
65380
65804
|
expo: "expo",
|
|
@@ -65596,10 +66020,16 @@ const getTopLevelBinding = (sourceFile, bindingName) => {
|
|
|
65596
66020
|
}
|
|
65597
66021
|
return null;
|
|
65598
66022
|
};
|
|
65599
|
-
const getFunctionLocalBindings = (functionNode, argumentsList) => {
|
|
66023
|
+
const getFunctionLocalBindings = (functionNode, argumentsList, argumentAnalysis, functionAnalysis) => {
|
|
65600
66024
|
const localBindings = /* @__PURE__ */ new Map();
|
|
65601
66025
|
functionNode.parameters.forEach((parameter, parameterIndex) => {
|
|
65602
|
-
if (ts.isIdentifier(parameter.name))
|
|
66026
|
+
if (ts.isIdentifier(parameter.name)) {
|
|
66027
|
+
const argument = argumentsList[parameterIndex];
|
|
66028
|
+
localBindings.set(parameter.name.text, {
|
|
66029
|
+
expression: argument ?? parameter.initializer ?? null,
|
|
66030
|
+
analysis: argument ? argumentAnalysis : functionAnalysis
|
|
66031
|
+
});
|
|
66032
|
+
}
|
|
65603
66033
|
});
|
|
65604
66034
|
return localBindings;
|
|
65605
66035
|
};
|
|
@@ -65735,8 +66165,8 @@ const getStaticConfigValueState = (expression, analysis, visitedExpressions = /*
|
|
|
65735
66165
|
};
|
|
65736
66166
|
if (ts.isIdentifier(unwrappedExpression)) {
|
|
65737
66167
|
if (analysis.localBindings.has(unwrappedExpression.text)) {
|
|
65738
|
-
const
|
|
65739
|
-
return
|
|
66168
|
+
const localReference = analysis.localBindings.get(unwrappedExpression.text);
|
|
66169
|
+
return localReference?.expression ? getStaticConfigValueState(localReference.expression, localReference.analysis, nextVisitedExpressions) : null;
|
|
65740
66170
|
}
|
|
65741
66171
|
const topLevelBinding = getTopLevelBinding(analysis.sourceFile, unwrappedExpression.text);
|
|
65742
66172
|
return topLevelBinding && ts.isExpression(topLevelBinding) ? getStaticConfigValueState(topLevelBinding, analysis, nextVisitedExpressions) : null;
|
|
@@ -65778,8 +66208,8 @@ const getReactCompilerFlagState = (expression, analysis, visitedExpressions = /*
|
|
|
65778
66208
|
const assignedBinding = getAssignedPropertyInitializer(unwrappedExpression, "reactCompiler");
|
|
65779
66209
|
if (assignedBinding.wasFound && assignedBinding.initializer) return { isEnabled: !isStaticallyDisabledConfigExpression(assignedBinding.initializer, analysis) };
|
|
65780
66210
|
if (analysis.localBindings.has(unwrappedExpression.text)) {
|
|
65781
|
-
const
|
|
65782
|
-
return
|
|
66211
|
+
const localReference = analysis.localBindings.get(unwrappedExpression.text);
|
|
66212
|
+
return localReference?.expression ? getReactCompilerFlagState(localReference.expression, localReference.analysis, nextVisitedExpressions) : null;
|
|
65783
66213
|
}
|
|
65784
66214
|
const topLevelBinding = getTopLevelBinding(analysis.sourceFile, unwrappedExpression.text);
|
|
65785
66215
|
return topLevelBinding && ts.isExpression(topLevelBinding) ? getReactCompilerFlagState(topLevelBinding, analysis, nextVisitedExpressions) : null;
|
|
@@ -65802,8 +66232,8 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
|
|
|
65802
66232
|
visitedExpressions.add(resolvedExpression);
|
|
65803
66233
|
if (ts.isIdentifier(resolvedExpression)) {
|
|
65804
66234
|
if (analysis.localBindings.has(resolvedExpression.text)) {
|
|
65805
|
-
const
|
|
65806
|
-
return
|
|
66235
|
+
const localReference = analysis.localBindings.get(resolvedExpression.text);
|
|
66236
|
+
return localReference?.expression ? getSelectedObjectProperty(localReference.expression, propertyName, localReference.analysis, visitedExpressions) : null;
|
|
65807
66237
|
}
|
|
65808
66238
|
const scopedBinding = getScopedConfigBinding(resolvedExpression);
|
|
65809
66239
|
if (scopedBinding.wasFound) return scopedBinding.initializer ? getSelectedObjectProperty(scopedBinding.initializer, propertyName, analysis, visitedExpressions) : null;
|
|
@@ -65812,9 +66242,18 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
|
|
|
65812
66242
|
}
|
|
65813
66243
|
if (!ts.isObjectLiteralExpression(resolvedExpression)) return null;
|
|
65814
66244
|
for (const property of [...resolvedExpression.properties].reverse()) {
|
|
65815
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === propertyName) return
|
|
65816
|
-
|
|
65817
|
-
|
|
66245
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === propertyName) return {
|
|
66246
|
+
node: property.initializer,
|
|
66247
|
+
analysis
|
|
66248
|
+
};
|
|
66249
|
+
if (ts.isMethodDeclaration(property) && getStaticPropertyName$2(property.name) === propertyName) return {
|
|
66250
|
+
node: property,
|
|
66251
|
+
analysis
|
|
66252
|
+
};
|
|
66253
|
+
if (ts.isShorthandPropertyAssignment(property) && property.name.text === propertyName) return {
|
|
66254
|
+
node: property.name,
|
|
66255
|
+
analysis
|
|
66256
|
+
};
|
|
65818
66257
|
if (ts.isSpreadAssignment(property)) {
|
|
65819
66258
|
const spreadProperty = getSelectedObjectProperty(property.expression, propertyName, analysis, visitedExpressions);
|
|
65820
66259
|
if (spreadProperty) return spreadProperty;
|
|
@@ -65827,8 +66266,8 @@ const configExpressionMayDefineProperty = (expression, propertyName, analysis) =
|
|
|
65827
66266
|
while (ts.isParenthesizedExpression(resolvedExpression) || ts.isAsExpression(resolvedExpression) || ts.isTypeAssertionExpression(resolvedExpression) || ts.isSatisfiesExpression(resolvedExpression) || ts.isNonNullExpression(resolvedExpression)) resolvedExpression = resolvedExpression.expression;
|
|
65828
66267
|
if (ts.isIdentifier(resolvedExpression)) {
|
|
65829
66268
|
if (analysis.localBindings.has(resolvedExpression.text)) {
|
|
65830
|
-
const
|
|
65831
|
-
return
|
|
66269
|
+
const localReference = analysis.localBindings.get(resolvedExpression.text);
|
|
66270
|
+
return localReference?.expression ? configExpressionMayDefineProperty(localReference.expression, propertyName, localReference.analysis) : true;
|
|
65832
66271
|
}
|
|
65833
66272
|
const scopedBinding = getScopedConfigBinding(resolvedExpression);
|
|
65834
66273
|
if (scopedBinding.wasFound) return scopedBinding.initializer ? configExpressionMayDefineProperty(scopedBinding.initializer, propertyName, analysis) : true;
|
|
@@ -65912,15 +66351,15 @@ const getReExportedConfigModules = (sourceFile, exportName) => {
|
|
|
65912
66351
|
}
|
|
65913
66352
|
return bindings;
|
|
65914
66353
|
};
|
|
65915
|
-
const analyzeConfigModuleExport = (filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = []) => {
|
|
66354
|
+
const analyzeConfigModuleExport = (filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = [], argumentAnalysis) => {
|
|
65916
66355
|
if (!isFile(filePath) || importDepth > 4) return false;
|
|
65917
66356
|
const moduleVisitKey = `${filePath}:${exportName}:${allowCompilerTransform}`;
|
|
65918
66357
|
if (visitedModules.has(moduleVisitKey)) return false;
|
|
65919
66358
|
const nextVisitedModules = new Set(visitedModules);
|
|
65920
66359
|
nextVisitedModules.add(moduleVisitKey);
|
|
65921
|
-
return analyzeConfigSourceFileExport(parseConfigSourceFile(filePath, NFS.readFileSync(filePath, "utf-8")), filePath, exportName, allowCompilerTransform, importDepth, nextVisitedModules, argumentsList);
|
|
66360
|
+
return analyzeConfigSourceFileExport(parseConfigSourceFile(filePath, NFS.readFileSync(filePath, "utf-8")), filePath, exportName, allowCompilerTransform, importDepth, nextVisitedModules, argumentsList, argumentAnalysis);
|
|
65922
66361
|
};
|
|
65923
|
-
const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = []) => {
|
|
66362
|
+
const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = [], argumentAnalysis) => {
|
|
65924
66363
|
const analysis = {
|
|
65925
66364
|
filePath,
|
|
65926
66365
|
sourceFile,
|
|
@@ -65930,14 +66369,27 @@ const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCo
|
|
|
65930
66369
|
localBindings: /* @__PURE__ */ new Map(),
|
|
65931
66370
|
activeFunctions: /* @__PURE__ */ new Set()
|
|
65932
66371
|
};
|
|
66372
|
+
const resolvedArgumentAnalysis = argumentAnalysis ?? analysis;
|
|
65933
66373
|
const exportedConfigNodes = getExportedConfigNodes(sourceFile, exportName);
|
|
65934
|
-
return exportedConfigNodes.some((node) =>
|
|
66374
|
+
return exportedConfigNodes.some((node) => {
|
|
66375
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) return analyzeConfigFunction(node, analysis, allowCompilerTransform, argumentsList, resolvedArgumentAnalysis);
|
|
66376
|
+
if (argumentsList.length > 0 && ts.isIdentifier(node)) {
|
|
66377
|
+
const topLevelBinding = getTopLevelBinding(sourceFile, node.text);
|
|
66378
|
+
if (topLevelBinding && ts.isFunctionLike(topLevelBinding)) return analyzeConfigFunction(topLevelBinding, analysis, allowCompilerTransform, argumentsList, resolvedArgumentAnalysis);
|
|
66379
|
+
const importBinding = getImportBinding(sourceFile, node.text);
|
|
66380
|
+
if (importBinding) {
|
|
66381
|
+
const importedFilePath = resolveImportedConfigFile(filePath, importBinding.moduleSpecifier);
|
|
66382
|
+
return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, importBinding.exportName, allowCompilerTransform, importDepth + 1, visitedModules, argumentsList, resolvedArgumentAnalysis));
|
|
66383
|
+
}
|
|
66384
|
+
}
|
|
66385
|
+
return analyzeConfigNode(node, analysis, allowCompilerTransform);
|
|
66386
|
+
}) || getReExportedConfigModules(sourceFile, exportName).some((binding) => {
|
|
65935
66387
|
if (exportedConfigNodes.length > 0 && binding.isNamespace) return false;
|
|
65936
66388
|
const importedFilePath = resolveImportedConfigFile(filePath, binding.moduleSpecifier);
|
|
65937
|
-
return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, binding.exportName, allowCompilerTransform, importDepth + 1, visitedModules, argumentsList));
|
|
66389
|
+
return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, binding.exportName, allowCompilerTransform, importDepth + 1, visitedModules, argumentsList, resolvedArgumentAnalysis));
|
|
65938
66390
|
});
|
|
65939
66391
|
};
|
|
65940
|
-
const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, argumentsList = []) => {
|
|
66392
|
+
const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, argumentsList = [], argumentAnalysis = analysis) => {
|
|
65941
66393
|
if (!functionNode.body) return false;
|
|
65942
66394
|
if (analysis.activeFunctions.has(functionNode.pos)) return false;
|
|
65943
66395
|
const activeFunctions = new Set(analysis.activeFunctions);
|
|
@@ -65945,7 +66397,7 @@ const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, a
|
|
|
65945
66397
|
const functionAnalysis = {
|
|
65946
66398
|
...analysis,
|
|
65947
66399
|
visitedNodes: /* @__PURE__ */ new Set(),
|
|
65948
|
-
localBindings: getFunctionLocalBindings(functionNode, argumentsList),
|
|
66400
|
+
localBindings: getFunctionLocalBindings(functionNode, argumentsList, argumentAnalysis, analysis),
|
|
65949
66401
|
activeFunctions
|
|
65950
66402
|
};
|
|
65951
66403
|
if (!ts.isBlock(functionNode.body)) return analyzeConfigNode(functionNode.body, functionAnalysis, allowCompilerTransform);
|
|
@@ -65964,7 +66416,7 @@ const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, a
|
|
|
65964
66416
|
const analyzeImportedConfig = ({ analysis, moduleSpecifier, exportName, allowCompilerTransform, argumentsList }) => {
|
|
65965
66417
|
const importedFilePath = resolveImportedConfigFile(analysis.filePath, moduleSpecifier);
|
|
65966
66418
|
if (!importedFilePath) return null;
|
|
65967
|
-
return analyzeConfigModuleExport(importedFilePath, exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, argumentsList);
|
|
66419
|
+
return analyzeConfigModuleExport(importedFilePath, exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, argumentsList, analysis);
|
|
65968
66420
|
};
|
|
65969
66421
|
const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, isCompilerTransformCollection, excludedPropertyNames) => {
|
|
65970
66422
|
const assignedReactCompiler = getAssignedPropertyInitializer(identifier, "reactCompiler");
|
|
@@ -65978,8 +66430,8 @@ const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, i
|
|
|
65978
66430
|
if (assignedPlugins.wasFound) overriddenPropertyNames.add("plugins");
|
|
65979
66431
|
if (assignedPresets.wasFound) overriddenPropertyNames.add("presets");
|
|
65980
66432
|
if (analysis.localBindings.has(identifier.text)) {
|
|
65981
|
-
const
|
|
65982
|
-
return Boolean(
|
|
66433
|
+
const localReference = analysis.localBindings.get(identifier.text);
|
|
66434
|
+
return Boolean(localReference?.expression && analyzeConfigNode(localReference.expression, localReference.analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
|
|
65983
66435
|
}
|
|
65984
66436
|
const scopedBinding = getScopedConfigBinding(identifier);
|
|
65985
66437
|
if (scopedBinding.wasFound) return Boolean(scopedBinding.initializer && analyzeConfigNode(scopedBinding.initializer, analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
|
|
@@ -66045,7 +66497,7 @@ const analyzeConfigCallTarget = (callExpression, analysis, allowCompilerTransfor
|
|
|
66045
66497
|
}
|
|
66046
66498
|
const selectedProperty = getSelectedObjectProperty(target.expression, propertyName, analysis);
|
|
66047
66499
|
if (selectedProperty === null) return null;
|
|
66048
|
-
return ts.isFunctionLike(selectedProperty) ? analyzeConfigFunction(selectedProperty, analysis, allowCompilerTransform, callExpression.arguments) : analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
|
|
66500
|
+
return ts.isFunctionLike(selectedProperty.node) ? analyzeConfigFunction(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform, callExpression.arguments, analysis) : analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform);
|
|
66049
66501
|
};
|
|
66050
66502
|
const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTransformCollection = false, excludedPropertyNames) => {
|
|
66051
66503
|
const excludedPropertiesVisitKey = excludedPropertyNames ? [...excludedPropertyNames].sort().join(",") : "";
|
|
@@ -66145,7 +66597,7 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
66145
66597
|
if (ts.isIdentifier(node.expression)) {
|
|
66146
66598
|
if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
|
|
66147
66599
|
const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
|
|
66148
|
-
return Boolean(selectedProperty && analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform));
|
|
66600
|
+
return Boolean(selectedProperty && analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform));
|
|
66149
66601
|
}
|
|
66150
66602
|
const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
|
|
66151
66603
|
if (importBinding?.isNamespace) {
|
|
@@ -66159,7 +66611,7 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
66159
66611
|
return false;
|
|
66160
66612
|
}
|
|
66161
66613
|
const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
|
|
66162
|
-
if (selectedProperty) return analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
|
|
66614
|
+
if (selectedProperty) return analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform);
|
|
66163
66615
|
return false;
|
|
66164
66616
|
}
|
|
66165
66617
|
return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
|
|
@@ -66168,7 +66620,7 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
66168
66620
|
if (ts.isIdentifier(node.expression)) {
|
|
66169
66621
|
if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
|
|
66170
66622
|
const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
|
|
66171
|
-
return Boolean(selectedProperty && analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform));
|
|
66623
|
+
return Boolean(selectedProperty && analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform));
|
|
66172
66624
|
}
|
|
66173
66625
|
const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
|
|
66174
66626
|
if (importBinding?.isNamespace) {
|
|
@@ -66181,7 +66633,7 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
66181
66633
|
}));
|
|
66182
66634
|
}
|
|
66183
66635
|
const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
|
|
66184
|
-
if (selectedProperty) return analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
|
|
66636
|
+
if (selectedProperty) return analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform);
|
|
66185
66637
|
return false;
|
|
66186
66638
|
}
|
|
66187
66639
|
return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
|
|
@@ -68422,7 +68874,7 @@ const evaluateSuppression = (lines, diagnosticLineIndex, ruleId) => {
|
|
|
68422
68874
|
const getDiagnosticRuleIdentity = (diagnostic) => ({
|
|
68423
68875
|
ruleKey: `${diagnostic.plugin}/${diagnostic.rule}`,
|
|
68424
68876
|
category: diagnostic.category,
|
|
68425
|
-
tags: diagnostic.plugin === "react-doctor" ?
|
|
68877
|
+
tags: diagnostic.plugin === "react-doctor" ? REACT_DOCTOR_RULE_REGISTRY[diagnostic.rule]?.tags ?? [] : []
|
|
68426
68878
|
});
|
|
68427
68879
|
const compileIgnoredFilePatterns = (userConfig) => {
|
|
68428
68880
|
const files = userConfig?.ignore?.files;
|
|
@@ -68558,6 +69010,7 @@ const classifyPackageRole = (filename) => {
|
|
|
68558
69010
|
* Resolves the absolute path to read for a diagnostic's `filePath`,
|
|
68559
69011
|
* accounting for the various shapes oxlint emits:
|
|
68560
69012
|
*
|
|
69013
|
+
* - `file://` URL — decode to an absolute filesystem path.
|
|
68561
69014
|
* - Absolute POSIX (`/abs/path/file.tsx`) — pass through.
|
|
68562
69015
|
* - Absolute Windows (`C:/...` or `C:\...`) — pass through.
|
|
68563
69016
|
* - `./relative` or bare relative — join against `rootDirectory`.
|
|
@@ -68567,6 +69020,7 @@ const classifyPackageRole = (filename) => {
|
|
|
68567
69020
|
* use one canonical resolution path.
|
|
68568
69021
|
*/
|
|
68569
69022
|
const resolveCandidateReadPath = (rootDirectory, filePath) => {
|
|
69023
|
+
if (filePath.startsWith("file://")) return fileURLToPath(filePath);
|
|
68570
69024
|
const normalizedFile = filePath.replace(/\\/g, "/");
|
|
68571
69025
|
if (normalizedFile.startsWith("/") || /^[a-zA-Z]:\//.test(normalizedFile) || /^[a-zA-Z]:\\/.test(filePath)) return filePath;
|
|
68572
69026
|
return `${rootDirectory.replace(/\\/g, "/").replace(/\/$/, "")}/${normalizedFile.replace(/^\.\//, "")}`;
|
|
@@ -68768,7 +69222,7 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
68768
69222
|
};
|
|
68769
69223
|
const shouldAutoSuppress = (diagnostic) => {
|
|
68770
69224
|
if (diagnostic.plugin !== "react-doctor") return false;
|
|
68771
|
-
const rule =
|
|
69225
|
+
const rule = REACT_DOCTOR_RULE_REGISTRY[diagnostic.rule];
|
|
68772
69226
|
if (!rule?.tags?.includes("test-noise")) return false;
|
|
68773
69227
|
if (rule.tags.includes("migration-hint")) return false;
|
|
68774
69228
|
return getFileContext(diagnostic.filePath) !== "production";
|
|
@@ -69200,6 +69654,7 @@ var OxlintConcurrency = class extends Reference("react-doctor/OxlintConcurrency"
|
|
|
69200
69654
|
if (Number.isInteger(parsed) && parsed > 0) return resolveScanConcurrency(parsed);
|
|
69201
69655
|
return resolveAutoScanConcurrency();
|
|
69202
69656
|
} }) {};
|
|
69657
|
+
var OxlintSpawnSlots = class extends Reference("react-doctor/OxlintSpawnSlots", { defaultValue: () => null }) {};
|
|
69203
69658
|
/**
|
|
69204
69659
|
* Three-state control for overlapping the dead-code pass with the lint pass —
|
|
69205
69660
|
* forking dead-code as a child fiber that runs DURING lint instead of strictly
|
|
@@ -71550,8 +72005,8 @@ const getCapabilities = (project) => {
|
|
|
71550
72005
|
const cached = capabilitiesByProject.get(project);
|
|
71551
72006
|
if (cached !== void 0) return cached;
|
|
71552
72007
|
const capabilities = new Set(buildCapabilities(project));
|
|
71553
|
-
const
|
|
71554
|
-
const targetBlankOpenerProtection = detectTargetBlankOpenerProtection(
|
|
72008
|
+
const capabilityRootDirectory = isFile(Path.join(project.rootDirectory, "package.json")) ? project.rootDirectory : findNearestAncestorPackageJson(project.rootDirectory) ?? project.rootDirectory;
|
|
72009
|
+
const targetBlankOpenerProtection = detectTargetBlankOpenerProtection(capabilityRootDirectory, readPackageJson$1(Path.join(capabilityRootDirectory, "package.json")));
|
|
71555
72010
|
if (targetBlankOpenerProtection !== void 0) capabilities.add("target-blank-needs-explicit-protection");
|
|
71556
72011
|
if (targetBlankOpenerProtection === "noreferrer") capabilities.add("target-blank-needs-noreferrer");
|
|
71557
72012
|
capabilitiesByProject.set(project, capabilities);
|
|
@@ -71581,7 +72036,7 @@ const createSecurityScanSession = (rootDirectory, options) => {
|
|
|
71581
72036
|
const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
|
|
71582
72037
|
const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
|
|
71583
72038
|
const includedTags = options.includedTags ?? /* @__PURE__ */ new Set();
|
|
71584
|
-
const enabledScanRules =
|
|
72039
|
+
const enabledScanRules = REACT_DOCTOR_SCAN_RULES.flatMap((entry) => {
|
|
71585
72040
|
const rule = entry.rule;
|
|
71586
72041
|
const scan = rule.scan;
|
|
71587
72042
|
if (typeof scan !== "function") return [];
|
|
@@ -72042,47 +72497,55 @@ const resolveDeadCodeConcurrency = (facts = readSystemFacts()) => {
|
|
|
72042
72497
|
const memoryBoundedWorkers = Math.floor(availableMemoryBytes / DEAD_CODE_WORKER_MEM_BUDGET_BYTES);
|
|
72043
72498
|
return Math.max(1, Math.min(facts.availableCores, memoryBoundedWorkers));
|
|
72044
72499
|
};
|
|
72045
|
-
|
|
72046
|
-
|
|
72047
|
-
const
|
|
72048
|
-
const
|
|
72049
|
-
|
|
72050
|
-
|
|
72500
|
+
const createWorkerSlots = (input) => {
|
|
72501
|
+
let availableSlotCount = input.slotCount;
|
|
72502
|
+
const waiters = [];
|
|
72503
|
+
const releaseSlot = () => {
|
|
72504
|
+
const nextWaiter = waiters.shift();
|
|
72505
|
+
if (nextWaiter === void 0) {
|
|
72506
|
+
availableSlotCount += 1;
|
|
72507
|
+
return;
|
|
72508
|
+
}
|
|
72509
|
+
nextWaiter.abortSignal?.removeEventListener("abort", nextWaiter.onAbort);
|
|
72510
|
+
nextWaiter.resolve();
|
|
72511
|
+
};
|
|
72512
|
+
const acquireSlot = async (abortSignal) => {
|
|
72513
|
+
if (abortSignal?.aborted) throw input.createAbortError();
|
|
72514
|
+
if (availableSlotCount > 0) {
|
|
72515
|
+
availableSlotCount -= 1;
|
|
72516
|
+
return;
|
|
72517
|
+
}
|
|
72518
|
+
await new Promise((resolve, reject) => {
|
|
72519
|
+
const onAbort = () => {
|
|
72520
|
+
const waiterIndex = waiters.indexOf(waiter);
|
|
72521
|
+
if (waiterIndex !== -1) waiters.splice(waiterIndex, 1);
|
|
72522
|
+
reject(input.createAbortError());
|
|
72523
|
+
};
|
|
72524
|
+
const waiter = {
|
|
72525
|
+
resolve,
|
|
72526
|
+
abortSignal,
|
|
72527
|
+
onAbort
|
|
72528
|
+
};
|
|
72529
|
+
waiters.push(waiter);
|
|
72530
|
+
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
72531
|
+
});
|
|
72532
|
+
};
|
|
72533
|
+
return { run: async (task, abortSignal) => {
|
|
72534
|
+
await acquireSlot(abortSignal);
|
|
72535
|
+
try {
|
|
72536
|
+
return await task();
|
|
72537
|
+
} finally {
|
|
72538
|
+
releaseSlot();
|
|
72539
|
+
}
|
|
72540
|
+
} };
|
|
72051
72541
|
};
|
|
72052
|
-
|
|
72053
|
-
* Runs `task` once a dead-code worker slot is free, releasing the slot when the
|
|
72054
|
-
* task settles (success or failure). With a high cap (roomy machine) every
|
|
72055
|
-
* caller proceeds immediately; with a low cap (constrained runner) callers
|
|
72056
|
-
* queue and run as slots free.
|
|
72057
|
-
*
|
|
72058
|
-
* `abortSignal` short-circuits the WAIT: if it's already aborted, or fires while
|
|
72059
|
-
* this caller is queued, the call rejects without acquiring a slot or running
|
|
72060
|
-
* `task` — so a cancelled scan (e.g. lint failed) doesn't sit in the queue and
|
|
72061
|
-
* then spawn a child only to tear it down. A queued caller that aborts removes
|
|
72062
|
-
* its own waiter so a later release never hands a slot to a dead request.
|
|
72063
|
-
*/
|
|
72542
|
+
let deadCodeWorkerSlots = null;
|
|
72064
72543
|
const withDeadCodeWorkerSlot = async (task, abortSignal) => {
|
|
72065
|
-
|
|
72066
|
-
|
|
72067
|
-
|
|
72068
|
-
else await new Promise((resolve, reject) => {
|
|
72069
|
-
const waiter = () => {
|
|
72070
|
-
abortSignal?.removeEventListener("abort", onAbort);
|
|
72071
|
-
resolve();
|
|
72072
|
-
};
|
|
72073
|
-
const onAbort = () => {
|
|
72074
|
-
const queuedIndex = waiters.indexOf(waiter);
|
|
72075
|
-
if (queuedIndex !== -1) waiters.splice(queuedIndex, 1);
|
|
72076
|
-
reject(/* @__PURE__ */ new Error("Dead-code worker aborted."));
|
|
72077
|
-
};
|
|
72078
|
-
waiters.push(waiter);
|
|
72079
|
-
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
72544
|
+
deadCodeWorkerSlots ??= createWorkerSlots({
|
|
72545
|
+
slotCount: resolveDeadCodeConcurrency(),
|
|
72546
|
+
createAbortError: () => /* @__PURE__ */ new Error("Dead-code worker aborted.")
|
|
72080
72547
|
});
|
|
72081
|
-
|
|
72082
|
-
return await task();
|
|
72083
|
-
} finally {
|
|
72084
|
-
releaseSlot();
|
|
72085
|
-
}
|
|
72548
|
+
return deadCodeWorkerSlots.run(task, abortSignal);
|
|
72086
72549
|
};
|
|
72087
72550
|
const projectCacheSubdir = (projectDirectory) => crypto.createHash("sha256").update(projectDirectory).digest("hex").slice(0, 16);
|
|
72088
72551
|
const resolveReactDoctorCacheDir = (projectDirectory) => {
|
|
@@ -72875,7 +73338,10 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
72875
73338
|
if (argvLengthChars > spawnArgsLengthCap) return yield* foldSpawnFailure(`spawn ENAMETOOLONG (${argvLengthChars} argv chars exceed ${spawnArgsLengthCap})`);
|
|
72876
73339
|
const handle = yield* spawner.spawn(make$1(input.command, [...input.args], {
|
|
72877
73340
|
cwd: input.directory,
|
|
72878
|
-
env: input.
|
|
73341
|
+
env: input.command === "git" ? {
|
|
73342
|
+
...input.env,
|
|
73343
|
+
GIT_DIR: void 0
|
|
73344
|
+
} : input.env,
|
|
72879
73345
|
extendEnv: true
|
|
72880
73346
|
}));
|
|
72881
73347
|
const maxStdoutBytes = input.maxStdoutBytes;
|
|
@@ -73148,7 +73614,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
73148
73614
|
"--diff-filter=ACMR",
|
|
73149
73615
|
"--relative"
|
|
73150
73616
|
]).pipe(map$3((result) => {
|
|
73151
|
-
if (result.status !== 0) return
|
|
73617
|
+
if (result.status !== 0) return null;
|
|
73152
73618
|
return splitNullSeparated(result.stdout);
|
|
73153
73619
|
})),
|
|
73154
73620
|
showStagedContent: (directory, relativePath, options) => runCommand({
|
|
@@ -73606,12 +74072,12 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
73606
74072
|
const settingsRootDirectory = resolveSettingsRootDirectory(project.rootDirectory);
|
|
73607
74073
|
const enabledReactDoctorRules = {};
|
|
73608
74074
|
for (const registryEntry of REACT_DOCTOR_RULES) {
|
|
73609
|
-
const rule =
|
|
74075
|
+
const rule = REACT_DOCTOR_RULE_REGISTRY[registryEntry.id];
|
|
73610
74076
|
if (!rule) continue;
|
|
73611
74077
|
if (ruleSelection === "cacheable" && CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
|
|
73612
74078
|
if (ruleSelection === "sidecar" && !CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
|
|
73613
74079
|
if (ruleSelection === "sidecar" && sidecarRuleIdFilter !== void 0 && !sidecarRuleIdFilter.has(registryEntry.id)) continue;
|
|
73614
|
-
if (rule.
|
|
74080
|
+
if (rule.isScanRule) continue;
|
|
73615
74081
|
if (customRulesOnly && registryEntry.originallyExternal) continue;
|
|
73616
74082
|
if (rule.framework !== "global" && !rule.requires) continue;
|
|
73617
74083
|
if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) continue;
|
|
@@ -74236,6 +74702,50 @@ const columnOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
|
74236
74702
|
while (lineStartOffset > 0 && sourceBuffer[lineStartOffset - 1] !== 10) lineStartOffset--;
|
|
74237
74703
|
return sourceBuffer.subarray(lineStartOffset, boundedOffset).toString("utf8").length + 1;
|
|
74238
74704
|
};
|
|
74705
|
+
const utf8OffsetFromSourcePosition = (sourceBuffer, lineNumber, zeroBasedColumn) => {
|
|
74706
|
+
if (lineNumber < 1 || zeroBasedColumn < 0) return null;
|
|
74707
|
+
const sourceLines = sourceBuffer.toString("utf8").split("\n");
|
|
74708
|
+
const sourceLine = sourceLines[lineNumber - 1];
|
|
74709
|
+
if (sourceLine === void 0 || zeroBasedColumn > sourceLine.length) return null;
|
|
74710
|
+
const precedingLines = sourceLines.slice(0, lineNumber - 1).join("\n");
|
|
74711
|
+
return (lineNumber === 1 ? 0 : Buffer.byteLength(precedingLines) + Buffer.byteLength("\n")) + Buffer.byteLength(sourceLine.slice(0, zeroBasedColumn));
|
|
74712
|
+
};
|
|
74713
|
+
const mapPreparedSourceSpan = (span, preparedSourceMap) => {
|
|
74714
|
+
const generatedLine = lineOfUtf8Offset(preparedSourceMap.generatedBuffer, span.offset);
|
|
74715
|
+
const generatedColumn = columnOfUtf8Offset(preparedSourceMap.generatedBuffer, span.offset) - 1;
|
|
74716
|
+
const originalStart = originalPositionFor(preparedSourceMap.traceMap, {
|
|
74717
|
+
line: generatedLine,
|
|
74718
|
+
column: generatedColumn
|
|
74719
|
+
});
|
|
74720
|
+
if (originalStart.source === null || originalStart.line === null || originalStart.column === null) return null;
|
|
74721
|
+
const originalOffset = utf8OffsetFromSourcePosition(preparedSourceMap.sourceBuffer, originalStart.line, originalStart.column);
|
|
74722
|
+
if (originalOffset === null) return null;
|
|
74723
|
+
const generatedSpan = preparedSourceMap.generatedBuffer.subarray(span.offset, span.offset + span.length);
|
|
74724
|
+
return {
|
|
74725
|
+
offset: originalOffset,
|
|
74726
|
+
length: preparedSourceMap.sourceBuffer.subarray(originalOffset, originalOffset + generatedSpan.length).equals(generatedSpan) ? generatedSpan.length : 0,
|
|
74727
|
+
line: originalStart.line,
|
|
74728
|
+
column: originalStart.column + 1
|
|
74729
|
+
};
|
|
74730
|
+
};
|
|
74731
|
+
const mapPreparedSourceLabels = (labels, preparedSourceMap) => {
|
|
74732
|
+
const primaryLabel = labels[0];
|
|
74733
|
+
if (primaryLabel === void 0) return null;
|
|
74734
|
+
const primarySpan = mapPreparedSourceSpan(primaryLabel.span, preparedSourceMap);
|
|
74735
|
+
if (primarySpan === null) return null;
|
|
74736
|
+
const mappedLabels = [{
|
|
74737
|
+
...primaryLabel,
|
|
74738
|
+
span: primarySpan
|
|
74739
|
+
}];
|
|
74740
|
+
for (const relatedLabel of labels.slice(1)) {
|
|
74741
|
+
const relatedSpan = mapPreparedSourceSpan(relatedLabel.span, preparedSourceMap);
|
|
74742
|
+
if (relatedSpan !== null) mappedLabels.push({
|
|
74743
|
+
...relatedLabel,
|
|
74744
|
+
span: relatedSpan
|
|
74745
|
+
});
|
|
74746
|
+
}
|
|
74747
|
+
return mappedLabels;
|
|
74748
|
+
};
|
|
74239
74749
|
const REDACTED_PLACEHOLDER = "<redacted>";
|
|
74240
74750
|
const KEEP_PREFIX = `$1${REDACTED_PLACEHOLDER}`;
|
|
74241
74751
|
const KNOWN_SECRET_RULES = [
|
|
@@ -74878,7 +75388,7 @@ const PLUGIN_CATEGORY_MAP = {
|
|
|
74878
75388
|
};
|
|
74879
75389
|
const lookupOwnString = (record, key) => Object.hasOwn(record, key) ? record[key] : void 0;
|
|
74880
75390
|
const getRuleRecommendation = (ruleName, project) => {
|
|
74881
|
-
const rule =
|
|
75391
|
+
const rule = REACT_DOCTOR_RULE_REGISTRY[ruleName];
|
|
74882
75392
|
if (!rule) return void 0;
|
|
74883
75393
|
if (rule.recommendationFor) {
|
|
74884
75394
|
const capabilities = getCapabilities(project);
|
|
@@ -74887,8 +75397,8 @@ const getRuleRecommendation = (ruleName, project) => {
|
|
|
74887
75397
|
}
|
|
74888
75398
|
return rule.recommendation;
|
|
74889
75399
|
};
|
|
74890
|
-
const getRuleCategory = (ruleName) =>
|
|
74891
|
-
const getRuleTitle = (ruleName) =>
|
|
75400
|
+
const getRuleCategory = (ruleName) => REACT_DOCTOR_RULE_REGISTRY[ruleName]?.category;
|
|
75401
|
+
const getRuleTitle = (ruleName) => REACT_DOCTOR_RULE_REGISTRY[ruleName]?.title;
|
|
74892
75402
|
const resolveDiagnosticTitle = (plugin, rule) => {
|
|
74893
75403
|
if (plugin !== "react-hooks-js") return getRuleTitle(rule);
|
|
74894
75404
|
if (rule === "error-boundaries") return REACT_ERROR_BOUNDARY_TITLE;
|
|
@@ -74943,7 +75453,7 @@ const resolveDiagnosticCategory = (plugin, rule) => {
|
|
|
74943
75453
|
if (plugin === "react-hooks-js" && rule === "error-boundaries") return "Bugs";
|
|
74944
75454
|
return getRuleCategory(rule) ?? lookupOwnString(PLUGIN_CATEGORY_MAP, plugin) ?? "Bugs";
|
|
74945
75455
|
};
|
|
74946
|
-
const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORIES.has(category) || Boolean(
|
|
75456
|
+
const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORIES.has(category) || Boolean(REACT_DOCTOR_RULE_REGISTRY[rule]?.matchByOccurrence);
|
|
74947
75457
|
/**
|
|
74948
75458
|
* Maps oxlint's non-primary labels (`labels[1..]`) into related source
|
|
74949
75459
|
* locations. Editors surface these as a diagnostic's
|
|
@@ -74980,7 +75490,7 @@ const isOxlintOutput = (value) => isRecord$1(value) && Array.isArray(value.diagn
|
|
|
74980
75490
|
* to the first `{`. Raises `OxlintOutputUnparseable` when the
|
|
74981
75491
|
* stdout isn't valid JSON or doesn't carry a `diagnostics` array.
|
|
74982
75492
|
*/
|
|
74983
|
-
const parseOxlintOutput = (stdout, project, rootDirectory, sourcePathByLintPath) => {
|
|
75493
|
+
const parseOxlintOutput = (stdout, project, rootDirectory, sourcePathByLintPath, sourceMapByLintPath) => {
|
|
74984
75494
|
if (!stdout) return [];
|
|
74985
75495
|
const jsonStart = stdout.indexOf("{");
|
|
74986
75496
|
const sanitizedStdout = jsonStart > 0 ? stdout.slice(jsonStart) : stdout;
|
|
@@ -74998,6 +75508,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory, sourcePathByLintPath)
|
|
|
74998
75508
|
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
74999
75509
|
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
75000
75510
|
const resolveMappedSourceFilename = (filename) => sourcePathByLintPath?.get(Path.normalize(resolveAbsolutePath(filename)));
|
|
75511
|
+
const resolvePreparedSourceMap = (filename) => sourceMapByLintPath?.get(Path.normalize(resolveAbsolutePath(filename)));
|
|
75001
75512
|
const resolveSourceFilename = (filename) => resolveMappedSourceFilename(filename) ?? filename;
|
|
75002
75513
|
const readSourceBuffer = (filename) => {
|
|
75003
75514
|
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
@@ -75029,7 +75540,19 @@ const parseOxlintOutput = (stdout, project, rootDirectory, sourcePathByLintPath)
|
|
|
75029
75540
|
minifiedFileCache.set(absolutePath, minified);
|
|
75030
75541
|
return minified;
|
|
75031
75542
|
};
|
|
75032
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.
|
|
75543
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.flatMap((diagnostic) => {
|
|
75544
|
+
const preparedSourceMap = resolvePreparedSourceMap(diagnostic.filename);
|
|
75545
|
+
if (preparedSourceMap === void 0) return [diagnostic];
|
|
75546
|
+
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
75547
|
+
if (plugin !== "react-doctor" || !REACT_DOCTOR_RULE_REGISTRY[rule]?.tags?.includes("design")) return [];
|
|
75548
|
+
const labels = mapPreparedSourceLabels(diagnostic.labels, preparedSourceMap);
|
|
75549
|
+
const sourceFilename = resolveMappedSourceFilename(diagnostic.filename);
|
|
75550
|
+
return labels === null || sourceFilename === void 0 ? [] : [{
|
|
75551
|
+
...diagnostic,
|
|
75552
|
+
filename: sourceFilename,
|
|
75553
|
+
labels
|
|
75554
|
+
}];
|
|
75555
|
+
}).filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(resolveSourceFilename(diagnostic.filename)) && !(TYPESCRIPT_DECLARATION_FILE_PATTERN.test(diagnostic.filename) && OXLINT_IGNORED_DECLARATION_DIAGNOSTIC_CODES.has(diagnostic.code)) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
75033
75556
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
75034
75557
|
const primaryLabel = diagnostic.labels[0];
|
|
75035
75558
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
@@ -75107,11 +75630,12 @@ const SANITIZED_ENV = buildOxlintChildEnv(process.env);
|
|
|
75107
75630
|
* The first three are splittable (the caller's binary-split retry
|
|
75108
75631
|
* shrinks the batch and re-spawns); the fourth isn't.
|
|
75109
75632
|
*/
|
|
75110
|
-
const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLINT_SPAWN_TIMEOUT_MS, outputMaxBytes = OXLINT_OUTPUT_MAX_BYTES, abortSignal) => new Promise((resolve, reject) => {
|
|
75633
|
+
const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLINT_SPAWN_TIMEOUT_MS, outputMaxBytes = OXLINT_OUTPUT_MAX_BYTES, abortSignal, onSpawn) => new Promise((resolve, reject) => {
|
|
75111
75634
|
if (abortSignal?.aborted) {
|
|
75112
75635
|
reject(new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) }));
|
|
75113
75636
|
return;
|
|
75114
75637
|
}
|
|
75638
|
+
onSpawn?.();
|
|
75115
75639
|
const child = spawn(nodeBinaryPath, buildProfiledNodeArguments({
|
|
75116
75640
|
argumentsList: args,
|
|
75117
75641
|
cpuProfileDirectory: SANITIZED_ENV.REACT_DOCTOR_CPU_PROFILE_DIR,
|
|
@@ -75247,7 +75771,7 @@ const isParallelismRelatedSpawnError = (error) => {
|
|
|
75247
75771
|
* loop with a slimmer config in that case.
|
|
75248
75772
|
*/
|
|
75249
75773
|
const spawnLintBatches = async (input) => {
|
|
75250
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
75774
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, sourceMapByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
75251
75775
|
const resolveSourcePath = (filePath) => {
|
|
75252
75776
|
const absoluteFilePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory, filePath);
|
|
75253
75777
|
return sourcePathByLintPath?.get(Path.normalize(absoluteFilePath)) ?? filePath;
|
|
@@ -75271,7 +75795,21 @@ const spawnLintBatches = async (input) => {
|
|
|
75271
75795
|
}
|
|
75272
75796
|
const batchArgs = [...baseArgs, ...batch];
|
|
75273
75797
|
try {
|
|
75274
|
-
|
|
75798
|
+
const spawnBatch = () => {
|
|
75799
|
+
if (isPastDeadline()) {
|
|
75800
|
+
deadlineSkippedFiles.push(...batch);
|
|
75801
|
+
batchState.deadlineSkippedFileCount += batch.length;
|
|
75802
|
+
return Promise.resolve(null);
|
|
75803
|
+
}
|
|
75804
|
+
return spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal, () => {
|
|
75805
|
+
if (batchState.didStart) return;
|
|
75806
|
+
batchState.didStart = true;
|
|
75807
|
+
startedFileCount += batchState.initialFileCount;
|
|
75808
|
+
});
|
|
75809
|
+
};
|
|
75810
|
+
const stdout = input.spawnSlots === void 0 ? await spawnBatch() : await input.spawnSlots.run(spawnBatch, signal);
|
|
75811
|
+
if (stdout === null) return [];
|
|
75812
|
+
return parseOxlintOutput(stdout, project, rootDirectory, sourcePathByLintPath, sourceMapByLintPath);
|
|
75275
75813
|
} catch (error) {
|
|
75276
75814
|
if (!isSplittableReactDoctorError(error)) throw error;
|
|
75277
75815
|
if (isPastDeadline()) {
|
|
@@ -75315,14 +75853,15 @@ const spawnLintBatches = async (input) => {
|
|
|
75315
75853
|
deadlineSkippedFiles.push(...batch);
|
|
75316
75854
|
return [];
|
|
75317
75855
|
}
|
|
75318
|
-
startedFileCount += batch.length;
|
|
75319
75856
|
const batchState = {
|
|
75320
75857
|
deadlineMs: null,
|
|
75321
|
-
deadlineSkippedFileCount: 0
|
|
75858
|
+
deadlineSkippedFileCount: 0,
|
|
75859
|
+
didStart: false,
|
|
75860
|
+
initialFileCount: batch.length
|
|
75322
75861
|
};
|
|
75323
75862
|
const batchDiagnostics = await spawnLintBatch(batch, 0, batchState);
|
|
75324
75863
|
scannedFileCount += batch.length - batchState.deadlineSkippedFileCount;
|
|
75325
|
-
if (passOnFileProgress) {
|
|
75864
|
+
if (passOnFileProgress && batchState.didStart) {
|
|
75326
75865
|
displayedFileCount = Math.min(Math.max(displayedFileCount, scannedFileCount), totalFileCount);
|
|
75327
75866
|
passOnFileProgress(displayedFileCount, totalFileCount);
|
|
75328
75867
|
}
|
|
@@ -75406,8 +75945,8 @@ const validateRuleRegistration = () => {
|
|
|
75406
75945
|
for (const fullKey of ALL_REACT_DOCTOR_RULE_KEYS) {
|
|
75407
75946
|
const ruleName = fullKey.replace(/^react-doctor\//, "");
|
|
75408
75947
|
if (!getRuleCategory(ruleName)) missingCategory.push(fullKey);
|
|
75409
|
-
if (!
|
|
75410
|
-
if (FRAMEWORK_SPECIFIC_RULE_KEYS.has(fullKey) && !
|
|
75948
|
+
if (!REACT_DOCTOR_RULE_REGISTRY[ruleName]?.recommendation) missingHelp.push(fullKey);
|
|
75949
|
+
if (FRAMEWORK_SPECIFIC_RULE_KEYS.has(fullKey) && !REACT_DOCTOR_RULE_REGISTRY[ruleName]?.requires) missingMetadata.push(fullKey);
|
|
75411
75950
|
}
|
|
75412
75951
|
if (missingCategory.length === 0 && missingHelp.length === 0 && missingMetadata.length === 0) return;
|
|
75413
75952
|
const detail = [
|
|
@@ -75710,20 +76249,47 @@ const prepareHtmlScriptSource = (sourceBuffer) => {
|
|
|
75710
76249
|
lintBuffer: maskedBuffer ?? sourceBuffer
|
|
75711
76250
|
};
|
|
75712
76251
|
};
|
|
75713
|
-
const
|
|
76252
|
+
const ASTRO_FILE_PATTERN = /\.astro$/;
|
|
76253
|
+
const prepareLintSources = (rootDirectory, temporaryDirectory, candidateFiles) => {
|
|
75714
76254
|
const lintFiles = [];
|
|
75715
76255
|
const sourcePathByLintPath = /* @__PURE__ */ new Map();
|
|
76256
|
+
const sourceMapByLintPath = /* @__PURE__ */ new Map();
|
|
75716
76257
|
const sizeByLintPath = /* @__PURE__ */ new Map();
|
|
75717
76258
|
const htmlSourcesDirectory = Path.join(temporaryDirectory, "html-sources");
|
|
76259
|
+
const astroSourcesDirectory = Path.join(temporaryDirectory, "astro-sources");
|
|
75718
76260
|
let htmlFileIndex = 0;
|
|
76261
|
+
let astroFileIndex = 0;
|
|
75719
76262
|
let hasThreeModuleImport = false;
|
|
75720
76263
|
for (const candidateFile of candidateFiles) {
|
|
75721
|
-
if (!HTML_FILE_PATTERN.test(candidateFile)) {
|
|
76264
|
+
if (!HTML_FILE_PATTERN.test(candidateFile) && !ASTRO_FILE_PATTERN.test(candidateFile)) {
|
|
75722
76265
|
lintFiles.push(candidateFile);
|
|
75723
76266
|
continue;
|
|
75724
76267
|
}
|
|
75725
76268
|
const absoluteSourcePath = Path.isAbsolute(candidateFile) ? candidateFile : Path.resolve(rootDirectory, candidateFile);
|
|
75726
76269
|
const sourceBuffer = NFS.readFileSync(absoluteSourcePath);
|
|
76270
|
+
if (ASTRO_FILE_PATTERN.test(candidateFile)) {
|
|
76271
|
+
const compilerSourcePath = absoluteSourcePath.replaceAll("\\", "/");
|
|
76272
|
+
const convertedSource = convertToTSX(sourceBuffer.toString("utf8"), {
|
|
76273
|
+
filename: compilerSourcePath,
|
|
76274
|
+
sourcemap: "external",
|
|
76275
|
+
includeScripts: true
|
|
76276
|
+
});
|
|
76277
|
+
if (astroFileIndex === 0) NFS.mkdirSync(astroSourcesDirectory, { recursive: true });
|
|
76278
|
+
const lintPath = Path.join(astroSourcesDirectory, `${astroFileIndex}.tsx`);
|
|
76279
|
+
const generatedBuffer = Buffer.from(convertedSource.code);
|
|
76280
|
+
NFS.writeFileSync(lintPath, generatedBuffer);
|
|
76281
|
+
lintFiles.push(candidateFile);
|
|
76282
|
+
lintFiles.push(lintPath);
|
|
76283
|
+
sourcePathByLintPath.set(Path.resolve(lintPath), candidateFile);
|
|
76284
|
+
sourceMapByLintPath.set(Path.resolve(lintPath), {
|
|
76285
|
+
traceMap: new TraceMap(JSON.stringify(convertedSource.map)),
|
|
76286
|
+
generatedBuffer,
|
|
76287
|
+
sourceBuffer
|
|
76288
|
+
});
|
|
76289
|
+
sizeByLintPath.set(lintPath, sourceBuffer.length);
|
|
76290
|
+
astroFileIndex++;
|
|
76291
|
+
continue;
|
|
76292
|
+
}
|
|
75727
76293
|
const { executableScriptBodies, lintBuffer } = prepareHtmlScriptSource(sourceBuffer);
|
|
75728
76294
|
if (htmlFileIndex === 0) NFS.mkdirSync(htmlSourcesDirectory, { recursive: true });
|
|
75729
76295
|
const lintPath = Path.join(htmlSourcesDirectory, `${htmlFileIndex}.astro`);
|
|
@@ -75737,6 +76303,7 @@ const prepareHtmlLintSources = (rootDirectory, temporaryDirectory, candidateFile
|
|
|
75737
76303
|
return {
|
|
75738
76304
|
lintFiles,
|
|
75739
76305
|
sourcePathByLintPath,
|
|
76306
|
+
sourceMapByLintPath,
|
|
75740
76307
|
sizeByLintPath,
|
|
75741
76308
|
hasThreeModuleImport
|
|
75742
76309
|
};
|
|
@@ -75955,10 +76522,10 @@ const runOxlint = async (options) => {
|
|
|
75955
76522
|
rootDirectory,
|
|
75956
76523
|
candidateFiles
|
|
75957
76524
|
});
|
|
75958
|
-
const
|
|
75959
|
-
const lintFiles =
|
|
75960
|
-
const
|
|
75961
|
-
const lintProject = !project.hasThree &&
|
|
76525
|
+
const preparedLintSources = prepareLintSources(rootDirectory, configDirectory, candidateFiles);
|
|
76526
|
+
const lintFiles = preparedLintSources.lintFiles;
|
|
76527
|
+
const hasPreparedFiles = preparedLintSources.sourcePathByLintPath.size > 0;
|
|
76528
|
+
const lintProject = !project.hasThree && preparedLintSources.hasThreeModuleImport ? {
|
|
75962
76529
|
...project,
|
|
75963
76530
|
hasThree: true
|
|
75964
76531
|
} : project;
|
|
@@ -75980,7 +76547,7 @@ const runOxlint = async (options) => {
|
|
|
75980
76547
|
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
75981
76548
|
});
|
|
75982
76549
|
const sizeByFile = sizedScanFiles !== null && lintBatchOrdering === "cost" ? new Map(sizedScanFiles.map((entry) => [entry.path, entry.sizeBytes])) : null;
|
|
75983
|
-
if (sizeByFile !== null) for (const [lintPath, sizeBytes] of
|
|
76550
|
+
if (sizeByFile !== null) for (const [lintPath, sizeBytes] of preparedLintSources.sizeByLintPath) sizeByFile.set(lintPath, sizeBytes);
|
|
75984
76551
|
const buildFileBatches = (passBaseArgs, passFiles) => sizeByFile !== null ? planLintBatches({
|
|
75985
76552
|
baseArgs: passBaseArgs,
|
|
75986
76553
|
files: passFiles,
|
|
@@ -76010,7 +76577,8 @@ const runOxlint = async (options) => {
|
|
|
76010
76577
|
rootDirectory,
|
|
76011
76578
|
nodeBinaryPath,
|
|
76012
76579
|
project: lintProject,
|
|
76013
|
-
sourcePathByLintPath:
|
|
76580
|
+
sourcePathByLintPath: preparedLintSources.sourcePathByLintPath,
|
|
76581
|
+
sourceMapByLintPath: preparedLintSources.sourceMapByLintPath,
|
|
76014
76582
|
onPartialFailure: reportPartialFailure,
|
|
76015
76583
|
onAnalyzedFiles: (filePaths) => {
|
|
76016
76584
|
analyzedFiles = filePaths;
|
|
@@ -76019,6 +76587,7 @@ const runOxlint = async (options) => {
|
|
|
76019
76587
|
spawnTimeoutMs,
|
|
76020
76588
|
outputMaxBytes,
|
|
76021
76589
|
concurrency: options.concurrency,
|
|
76590
|
+
spawnSlots: options.spawnSlots,
|
|
76022
76591
|
signal: options.signal,
|
|
76023
76592
|
deadlineEpochMs: options.deadlineEpochMs
|
|
76024
76593
|
});
|
|
@@ -76045,7 +76614,7 @@ const runOxlint = async (options) => {
|
|
|
76045
76614
|
};
|
|
76046
76615
|
}
|
|
76047
76616
|
};
|
|
76048
|
-
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0 && !
|
|
76617
|
+
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0 && !hasPreparedFiles) {
|
|
76049
76618
|
const rulesetHash = computeRulesetHash({
|
|
76050
76619
|
config: buildConfig({
|
|
76051
76620
|
extendsPaths: [],
|
|
@@ -76211,7 +76780,8 @@ const runOxlint = async (options) => {
|
|
|
76211
76780
|
rootDirectory,
|
|
76212
76781
|
nodeBinaryPath,
|
|
76213
76782
|
project: lintProject,
|
|
76214
|
-
sourcePathByLintPath:
|
|
76783
|
+
sourcePathByLintPath: preparedLintSources.sourcePathByLintPath,
|
|
76784
|
+
sourceMapByLintPath: preparedLintSources.sourceMapByLintPath,
|
|
76215
76785
|
onPartialFailure,
|
|
76216
76786
|
onAnalyzedFiles: (filePaths) => {
|
|
76217
76787
|
analyzedFiles = filePaths;
|
|
@@ -76220,6 +76790,7 @@ const runOxlint = async (options) => {
|
|
|
76220
76790
|
spawnTimeoutMs,
|
|
76221
76791
|
outputMaxBytes,
|
|
76222
76792
|
concurrency: options.concurrency,
|
|
76793
|
+
spawnSlots: options.spawnSlots,
|
|
76223
76794
|
signal: options.signal,
|
|
76224
76795
|
deadlineEpochMs: options.deadlineEpochMs
|
|
76225
76796
|
});
|
|
@@ -76314,6 +76885,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
|
|
|
76314
76885
|
const spawnTimeoutMs = yield* OxlintSpawnTimeoutMs;
|
|
76315
76886
|
const outputMaxBytes = yield* OxlintOutputMaxBytes;
|
|
76316
76887
|
const concurrency = yield* OxlintConcurrency;
|
|
76888
|
+
const spawnSlots = yield* OxlintSpawnSlots;
|
|
76317
76889
|
const lintBatchOrdering = yield* LintBatchOrdering;
|
|
76318
76890
|
const perFileLintCacheEnabled = yield* PerFileLintCacheEnabled;
|
|
76319
76891
|
const sidecarLintCacheEnabled = yield* SidecarLintCacheEnabled;
|
|
@@ -76343,6 +76915,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
|
|
|
76343
76915
|
onSidecarStats: input.onSidecarStats,
|
|
76344
76916
|
spawnTimeoutMs,
|
|
76345
76917
|
outputMaxBytes,
|
|
76918
|
+
spawnSlots: spawnSlots ?? void 0,
|
|
76346
76919
|
concurrency,
|
|
76347
76920
|
signal,
|
|
76348
76921
|
lintBatchOrdering,
|
|
@@ -77571,10 +78144,14 @@ const materializeSourceTree = (input) => gen(function* () {
|
|
|
77571
78144
|
materializedFiles.push(relativePath);
|
|
77572
78145
|
}
|
|
77573
78146
|
yield* sync(() => {
|
|
77574
|
-
for (const configFilename of STAGED_FILES_PROJECT_CONFIG_FILENAMES) {
|
|
77575
|
-
const sourcePath = path.join(input.directory, configFilename);
|
|
77576
|
-
const targetPath = path.
|
|
77577
|
-
if (
|
|
78147
|
+
for (const subdirectory of ["", ...input.configSubdirectories ?? []]) for (const configFilename of STAGED_FILES_PROJECT_CONFIG_FILENAMES) {
|
|
78148
|
+
const sourcePath = path.join(input.directory, subdirectory, configFilename);
|
|
78149
|
+
const targetPath = path.resolve(resolvedTempDirectory, subdirectory, configFilename);
|
|
78150
|
+
if (!isPathInsideDirectory(targetPath, resolvedTempDirectory)) continue;
|
|
78151
|
+
if (fs.existsSync(sourcePath) && !fs.existsSync(targetPath)) {
|
|
78152
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
78153
|
+
fs.cpSync(sourcePath, targetPath);
|
|
78154
|
+
}
|
|
77578
78155
|
}
|
|
77579
78156
|
});
|
|
77580
78157
|
return {
|
|
@@ -77607,15 +78184,17 @@ var StagedFiles = class StagedFiles extends Service()("react-doctor/StagedFiles"
|
|
|
77607
78184
|
static layerNode = effect(StagedFiles, gen(function* () {
|
|
77608
78185
|
const git = yield* Git;
|
|
77609
78186
|
return StagedFiles.of({
|
|
77610
|
-
discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries.filter(isLintableSourceFile)), withSpan("StagedFiles.discoverSourceFiles")),
|
|
77611
|
-
materialize: ({ directory, stagedFiles, tempDirectory }) => materializeSourceTree({
|
|
78187
|
+
discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries === null ? null : entries.filter(isLintableSourceFile)), withSpan("StagedFiles.discoverSourceFiles")),
|
|
78188
|
+
materialize: ({ directory, stagedFiles, tempDirectory, configSubdirectories }) => materializeSourceTree({
|
|
77612
78189
|
directory,
|
|
77613
78190
|
files: stagedFiles,
|
|
77614
78191
|
tempDirectory,
|
|
78192
|
+
configSubdirectories,
|
|
77615
78193
|
readContent: (relativePath) => git.showStagedContent(directory, relativePath, { maxBufferBytes: GIT_SHOW_MAX_BUFFER_BYTES })
|
|
77616
78194
|
}).pipe(map$3((tree) => ({
|
|
77617
78195
|
tempDirectory: tree.tempDirectory,
|
|
77618
78196
|
stagedFiles: tree.materializedFiles,
|
|
78197
|
+
unmaterializedFiles: tree.unmaterializedFiles,
|
|
77619
78198
|
cleanup: tree.cleanup
|
|
77620
78199
|
})), withSpan("StagedFiles.materialize"))
|
|
77621
78200
|
});
|
|
@@ -77630,6 +78209,7 @@ var StagedFiles = class StagedFiles extends Service()("react-doctor/StagedFiles"
|
|
|
77630
78209
|
materialize: ({ tempDirectory }) => succeed$2({
|
|
77631
78210
|
tempDirectory,
|
|
77632
78211
|
stagedFiles: snapshot.materializedFiles ?? snapshot.sourceFiles ?? [],
|
|
78212
|
+
unmaterializedFiles: [],
|
|
77633
78213
|
cleanup: () => {}
|
|
77634
78214
|
})
|
|
77635
78215
|
}));
|
|
@@ -77998,6 +78578,11 @@ const computeConfigFingerprint = (projectDirectory, version) => {
|
|
|
77998
78578
|
}
|
|
77999
78579
|
return crypto.createHash("sha1").update(parts.join("|")).digest("hex");
|
|
78000
78580
|
};
|
|
78581
|
+
const createLintPhaseAbortError = () => new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) });
|
|
78582
|
+
const createOxlintSpawnSlots = (concurrency) => createWorkerSlots({
|
|
78583
|
+
slotCount: resolveScanConcurrency(concurrency),
|
|
78584
|
+
createAbortError: createLintPhaseAbortError
|
|
78585
|
+
});
|
|
78001
78586
|
const AI_TRAINING_ENV_VARS = [
|
|
78002
78587
|
["HF_DATASETS_CACHE", "huggingface"],
|
|
78003
78588
|
["HF_HOME", "huggingface"],
|
|
@@ -78077,7 +78662,7 @@ const groupBy = (items, keyFn) => {
|
|
|
78077
78662
|
* recipe, so advertising "fetch the fix recipe" for them sends agents to
|
|
78078
78663
|
* a 404. Gate the directive on this predicate.
|
|
78079
78664
|
*/
|
|
78080
|
-
const hasPublishedFixRecipe = (diagnostic) => diagnostic.plugin === "react-doctor" && Object.hasOwn(
|
|
78665
|
+
const hasPublishedFixRecipe = (diagnostic) => diagnostic.plugin === "react-doctor" && Object.hasOwn(REACT_DOCTOR_RULE_REGISTRY, diagnostic.rule);
|
|
78081
78666
|
const unionValues = (baseValues, overrideValues) => [...new Set([...baseValues, ...overrideValues])];
|
|
78082
78667
|
const mergeIgnores = (baseIgnore, overrideIgnore) => {
|
|
78083
78668
|
const mergedIgnore = {
|
|
@@ -78326,6 +78911,7 @@ const BASELINE_FILES_TEMP_DIR_PREFIX = "react-doctor-baseline-";
|
|
|
78326
78911
|
const SCAN_RESULT_CACHE_FILENAME = "scan-cache.json";
|
|
78327
78912
|
const RUN_GIT_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
|
|
78328
78913
|
const GH_DEFAULT_BRANCH_PROBE_TIMEOUT_MS = 5e3;
|
|
78914
|
+
const TUI_REPORT_COMPACT_MAX_ROWS = 29;
|
|
78329
78915
|
const TUI_REPORT_DETAIL_WIDTH_FRACTION = .6;
|
|
78330
78916
|
const CI_TRUST_COMPANIES = "PayPal, Rippling, and Alibaba";
|
|
78331
78917
|
const WELCOME_EXPLANATION_HOLD_MS = 1e3;
|
|
@@ -78338,11 +78924,13 @@ const METRIC = {
|
|
|
78338
78924
|
cliError: "cli.error",
|
|
78339
78925
|
cliEnvironmentError: "cli.env_error",
|
|
78340
78926
|
stagedSnapshotDivergence: "staged.snapshot_divergence",
|
|
78927
|
+
stagedPerProject: "staged.per_project",
|
|
78341
78928
|
projectDetected: "project.detected",
|
|
78342
78929
|
projectPathSelected: "project.path_selected",
|
|
78343
78930
|
projectConfigSelected: "project.config_selected",
|
|
78344
78931
|
scanCompleted: "scan.completed",
|
|
78345
78932
|
scanDuration: "scan.duration",
|
|
78933
|
+
scanFeedbackDelay: "scan.feedback_delay",
|
|
78346
78934
|
scanPhaseDuration: "scan.phase_duration",
|
|
78347
78935
|
scanFiles: "scan.files",
|
|
78348
78936
|
scanScore: "scan.score",
|
|
@@ -78374,6 +78962,10 @@ const METRIC = {
|
|
|
78374
78962
|
lspScanCompleted: "lsp.scan.completed",
|
|
78375
78963
|
lspScanDuration: "lsp.scan.duration",
|
|
78376
78964
|
lspScanDiagnostics: "lsp.scan.diagnostics",
|
|
78965
|
+
tuiActionMenuOpened: "tui.action_menu_opened",
|
|
78966
|
+
tuiCompactReportShown: "tui.compact_report_shown",
|
|
78967
|
+
tuiFindingNavigated: "tui.finding_navigated",
|
|
78968
|
+
tuiStackedReportCapped: "tui.stacked_report_capped",
|
|
78377
78969
|
aiTrainingWarningShown: "ai.training.warning_shown",
|
|
78378
78970
|
jsonOutUsed: "json.out_used"
|
|
78379
78971
|
};
|
|
@@ -78418,7 +79010,7 @@ const makeNoopConsole = () => ({
|
|
|
78418
79010
|
});
|
|
78419
79011
|
//#endregion
|
|
78420
79012
|
//#region src/cli/utils/version.ts
|
|
78421
|
-
const VERSION = "0.9.
|
|
79013
|
+
const VERSION = "0.9.3-dev.9bb44e7";
|
|
78422
79014
|
//#endregion
|
|
78423
79015
|
//#region src/cli/utils/json-mode.ts
|
|
78424
79016
|
let context = null;
|
|
@@ -78776,13 +79368,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
78776
79368
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
78777
79369
|
* standard `SENTRY_RELEASE` override.
|
|
78778
79370
|
*/
|
|
78779
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.
|
|
79371
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.3-dev.9bb44e7`;
|
|
78780
79372
|
/**
|
|
78781
79373
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
78782
79374
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
78783
79375
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
78784
79376
|
*/
|
|
78785
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.
|
|
79377
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.3-dev.9bb44e7") ? "development" : "production");
|
|
78786
79378
|
/**
|
|
78787
79379
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
78788
79380
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -90636,7 +91228,8 @@ const buildRuntimeLayers = (input) => {
|
|
|
90636
91228
|
resolvedDirectory: input.directory,
|
|
90637
91229
|
configSourceDirectory: input.configSourceDirectory
|
|
90638
91230
|
}) : Config.layerNode, Files.layerNode, Git.layerNode, linterLayer, LintPartialFailures.layerLive, deadCodeLayer, progressLayer, reporterLayer, scoreLayer, supplyChainLayer);
|
|
90639
|
-
|
|
91231
|
+
const layersWithConcurrency = input.oxlintConcurrency === void 0 ? baseLayers : mergeAll$1(baseLayers, succeed$3(OxlintConcurrency, input.oxlintConcurrency));
|
|
91232
|
+
return input.oxlintSpawnSlots === void 0 ? layersWithConcurrency : mergeAll$1(layersWithConcurrency, succeed$3(OxlintSpawnSlots, input.oxlintSpawnSlots));
|
|
90640
91233
|
};
|
|
90641
91234
|
//#endregion
|
|
90642
91235
|
//#region src/cli/utils/with-sentry-run-span.ts
|
|
@@ -92239,16 +92832,19 @@ const formatClusterLocation = (cluster, resolveSourceRoot, hyperlinks) => {
|
|
|
92239
92832
|
if (!hyperlinks) return `${location}${contextTag}`;
|
|
92240
92833
|
return `${formatHyperlink(location, pathToFileURL(resolveAbsolutePath(lead.filePath, resolveSourceRoot(lead))).href)}${contextTag}`;
|
|
92241
92834
|
};
|
|
92242
|
-
const buildDiagnosticClusterLines = (cluster, resolveSourceRoot, renderCodeFrame, hyperlinks) => {
|
|
92835
|
+
const buildDiagnosticClusterLines = (cluster, resolveSourceRoot, resolveFrameSourceRoot, renderCodeFrame, hyperlinks) => {
|
|
92243
92836
|
const lead = cluster.diagnostics[0];
|
|
92244
92837
|
const isMultiSite = cluster.diagnostics.length > 1;
|
|
92838
|
+
const sourceRoot = resolveSourceRoot(lead);
|
|
92839
|
+
const frameSourceRoot = resolveFrameSourceRoot(lead);
|
|
92840
|
+
const frameFilePath = Path.isAbsolute(lead.filePath) && sourceRoot !== frameSourceRoot ? Path.relative(sourceRoot, lead.filePath) : lead.filePath;
|
|
92245
92841
|
const lines = ["", highlighter.gray(`${TOP_ERROR_DETAIL_INDENT}${formatClusterLocation(cluster, resolveSourceRoot, hyperlinks)}`)];
|
|
92246
92842
|
const codeFrame = renderCodeFrame ? buildCodeFrame({
|
|
92247
|
-
filePath:
|
|
92843
|
+
filePath: frameFilePath,
|
|
92248
92844
|
line: cluster.startLine,
|
|
92249
92845
|
column: isMultiSite ? 0 : lead.column,
|
|
92250
92846
|
endLine: isMultiSite ? cluster.endLine : void 0,
|
|
92251
|
-
rootDirectory:
|
|
92847
|
+
rootDirectory: frameSourceRoot
|
|
92252
92848
|
}) : null;
|
|
92253
92849
|
if (codeFrame) {
|
|
92254
92850
|
const boxInnerWidth = resolveMeasureWidth(8);
|
|
@@ -92261,7 +92857,7 @@ const buildDiagnosticClusterLines = (cluster, resolveSourceRoot, renderCodeFrame
|
|
|
92261
92857
|
}
|
|
92262
92858
|
return lines;
|
|
92263
92859
|
};
|
|
92264
|
-
const buildRuleDetailBlock = (ruleKey, ruleDiagnostics, resolveSourceRoot, renderEverySite, isAgentEnvironment, hyperlinks) => {
|
|
92860
|
+
const buildRuleDetailBlock = (ruleKey, ruleDiagnostics, resolveSourceRoot, resolveFrameSourceRoot, renderEverySite, isAgentEnvironment, hyperlinks) => {
|
|
92265
92861
|
const representative = pickRepresentativeDiagnostic(ruleDiagnostics);
|
|
92266
92862
|
const { severity } = representative;
|
|
92267
92863
|
const trailingBadge = formatTrailingSiteBadge(ruleDiagnostics.length);
|
|
@@ -92283,7 +92879,7 @@ const buildRuleDetailBlock = (ruleKey, ruleDiagnostics, resolveSourceRoot, rende
|
|
|
92283
92879
|
}
|
|
92284
92880
|
const renderCodeFrame = severity === "error";
|
|
92285
92881
|
const sites = renderEverySite ? ruleDiagnostics : [representative];
|
|
92286
|
-
if (!(isCollapsedWarningGroup && representative.help.includes(representative.filePath))) for (const cluster of clusterNearbyDiagnostics(sites)) lines.push(...buildDiagnosticClusterLines(cluster, resolveSourceRoot, renderCodeFrame, hyperlinks));
|
|
92882
|
+
if (!(isCollapsedWarningGroup && representative.help.includes(representative.filePath))) for (const cluster of clusterNearbyDiagnostics(sites)) lines.push(...buildDiagnosticClusterLines(cluster, resolveSourceRoot, resolveFrameSourceRoot, renderCodeFrame, hyperlinks));
|
|
92287
92883
|
return lines;
|
|
92288
92884
|
};
|
|
92289
92885
|
const selectErrorRuleGroups = (diagnostics, rulePriority) => buildSortedRuleGroups(diagnostics.filter((diagnostic) => diagnostic.severity === "error"), rulePriority);
|
|
@@ -92309,7 +92905,7 @@ const buildMigrationScaleAdvisoryLines = (diagnostics) => {
|
|
|
92309
92905
|
return lines;
|
|
92310
92906
|
};
|
|
92311
92907
|
const getTopErrorRuleKeys = (diagnostics, limit, rulePriority) => new Set(selectTopErrorRuleGroups(diagnostics, limit, rulePriority).map(([ruleKey]) => ruleKey));
|
|
92312
|
-
const buildTopErrorsSection = (diagnostics, resolveSourceRoot, hyperlinks, rulePriority) => {
|
|
92908
|
+
const buildTopErrorsSection = (diagnostics, resolveSourceRoot, resolveFrameSourceRoot, hyperlinks, rulePriority) => {
|
|
92313
92909
|
const topRuleGroups = selectErrorRuleGroups(diagnostics, rulePriority).slice(0, 3);
|
|
92314
92910
|
if (topRuleGroups.length === 0) return {
|
|
92315
92911
|
lines: [],
|
|
@@ -92319,7 +92915,7 @@ const buildTopErrorsSection = (diagnostics, resolveSourceRoot, hyperlinks, ruleP
|
|
|
92319
92915
|
const blockOffsets = [];
|
|
92320
92916
|
for (const [ruleKey, ruleDiagnostics] of topRuleGroups) {
|
|
92321
92917
|
blockOffsets.push(lines.length);
|
|
92322
|
-
lines.push(...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, false, false, hyperlinks));
|
|
92918
|
+
lines.push(...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, resolveFrameSourceRoot, false, false, hyperlinks));
|
|
92323
92919
|
lines.push("");
|
|
92324
92920
|
}
|
|
92325
92921
|
return {
|
|
@@ -92357,18 +92953,19 @@ const buildOverviewHeaderLines = (diagnostics) => {
|
|
|
92357
92953
|
* single Effect.forEach over Console.log so failures or fiber
|
|
92358
92954
|
* interruption produce predictable partial output.
|
|
92359
92955
|
*/
|
|
92360
|
-
const printDiagnostics = (diagnostics, isVerbose, sourceRoot, rulePriority, isAgentEnvironment = false, onboarding = {}, hyperlinks = false) => gen(function* () {
|
|
92956
|
+
const printDiagnostics = (diagnostics, isVerbose, sourceRoot, rulePriority, isAgentEnvironment = false, onboarding = {}, hyperlinks = false, frameSourceRoot = sourceRoot) => gen(function* () {
|
|
92361
92957
|
const sectionPause = onboarding.sectionPause ?? void_;
|
|
92362
92958
|
const animateCountUp = onboarding.animateCountUp ?? false;
|
|
92363
92959
|
const resolveSourceRoot = typeof sourceRoot === "function" ? sourceRoot : () => sourceRoot;
|
|
92960
|
+
const resolveFrameSourceRoot = typeof frameSourceRoot === "function" ? frameSourceRoot : () => frameSourceRoot;
|
|
92364
92961
|
let detailLines;
|
|
92365
92962
|
let topErrorBlockOffsets = [];
|
|
92366
92963
|
if (!isVerbose) {
|
|
92367
|
-
const topErrors = buildTopErrorsSection(diagnostics, resolveSourceRoot, hyperlinks, rulePriority);
|
|
92964
|
+
const topErrors = buildTopErrorsSection(diagnostics, resolveSourceRoot, resolveFrameSourceRoot, hyperlinks, rulePriority);
|
|
92368
92965
|
detailLines = topErrors.lines;
|
|
92369
92966
|
topErrorBlockOffsets = topErrors.blockOffsets;
|
|
92370
92967
|
} else detailLines = buildSortedRuleGroups(diagnostics, rulePriority).flatMap(([ruleKey, ruleDiagnostics]) => {
|
|
92371
|
-
return [...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, true, isAgentEnvironment, hyperlinks), ""];
|
|
92968
|
+
return [...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, resolveFrameSourceRoot, true, isAgentEnvironment, hyperlinks), ""];
|
|
92372
92969
|
});
|
|
92373
92970
|
const overflowLine = isVerbose ? void 0 : buildOverflowSummaryLine(diagnostics, rulePriority);
|
|
92374
92971
|
const categoryTallies = buildCategoryDiagnosticGroups(diagnostics, rulePriority).map(buildCategoryTally);
|
|
@@ -93136,7 +93733,7 @@ const buildRunEventConfig = (options, userConfig, hasCustomConfig, resolvedWorke
|
|
|
93136
93733
|
userConfig
|
|
93137
93734
|
};
|
|
93138
93735
|
};
|
|
93139
|
-
const
|
|
93736
|
+
const inspectWithOxlintRuntime = async (directory, inputOptions, oxlintRuntime) => {
|
|
93140
93737
|
const startTime = performance$1.now();
|
|
93141
93738
|
const deadlineEpochMs = inputOptions.deadlineEpochMs ?? (inputOptions.maxDurationMs != null ? Date.now() + inputOptions.maxDurationMs : null);
|
|
93142
93739
|
const isConcurrentScan = inputOptions.concurrentScan === true;
|
|
@@ -93162,7 +93759,7 @@ const inspect = async (directory, inputOptions = {}) => {
|
|
|
93162
93759
|
try {
|
|
93163
93760
|
const result = await withSentryRunSpan(async (rootSentrySpan) => {
|
|
93164
93761
|
try {
|
|
93165
|
-
return await runInspectWithRuntime(scanDirectory, options, userConfig, hasConfigOverride, configSourceDirectory, startTime, deadlineEpochMs, rootSentrySpan);
|
|
93762
|
+
return await runInspectWithRuntime(scanDirectory, options, userConfig, hasConfigOverride, configSourceDirectory, startTime, deadlineEpochMs, rootSentrySpan, oxlintRuntime);
|
|
93166
93763
|
} catch (error) {
|
|
93167
93764
|
recordRunEvent(rootSentrySpan, {
|
|
93168
93765
|
...buildRunEventConfig(options, userConfig, userConfig !== null),
|
|
@@ -93178,6 +93775,15 @@ const inspect = async (directory, inputOptions = {}) => {
|
|
|
93178
93775
|
if (ownsSpinnerSilence) setSpinnerSilent(wasSpinnerSilent);
|
|
93179
93776
|
}
|
|
93180
93777
|
};
|
|
93778
|
+
const createInvocationInspect = (requestedOxlintConcurrency) => {
|
|
93779
|
+
const concurrency = resolveScanConcurrency(requestedOxlintConcurrency ?? runSync(OxlintConcurrency));
|
|
93780
|
+
const oxlintRuntime = {
|
|
93781
|
+
concurrency,
|
|
93782
|
+
spawnSlots: createOxlintSpawnSlots(concurrency)
|
|
93783
|
+
};
|
|
93784
|
+
return (directory, inputOptions = {}) => inspectWithOxlintRuntime(directory, inputOptions, oxlintRuntime);
|
|
93785
|
+
};
|
|
93786
|
+
const inspect = async (directory, inputOptions = {}) => createInvocationInspect(inputOptions.concurrency)(directory, inputOptions);
|
|
93181
93787
|
const countIncompleteLintFiles = (lintPartialFailures) => countDroppedLintFiles(lintPartialFailures) + countDeadlineSkippedFiles(lintPartialFailures);
|
|
93182
93788
|
/**
|
|
93183
93789
|
* Runs a second, lint-only scan over the changed files as they existed at the
|
|
@@ -93231,7 +93837,8 @@ const runBaselineComparison = async (params) => {
|
|
|
93231
93837
|
shouldRunSupplyChain: params.options.supplyChain,
|
|
93232
93838
|
shouldComputeScore: false,
|
|
93233
93839
|
shouldShowProgressSpinners: false,
|
|
93234
|
-
oxlintConcurrency: params.
|
|
93840
|
+
oxlintConcurrency: params.oxlintRuntime.concurrency,
|
|
93841
|
+
oxlintSpawnSlots: params.oxlintRuntime.spawnSlots
|
|
93235
93842
|
});
|
|
93236
93843
|
const baseOutput = await runPromise(restoreLegacyThrow(runInspect({
|
|
93237
93844
|
directory: snapshot.tempDirectory,
|
|
@@ -93276,7 +93883,7 @@ const runBaselineComparison = async (params) => {
|
|
|
93276
93883
|
snapshot.cleanup();
|
|
93277
93884
|
}
|
|
93278
93885
|
};
|
|
93279
|
-
const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOverride, configSourceDirectory, startTime, deadlineEpochMs, rootSentrySpan) => {
|
|
93886
|
+
const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOverride, configSourceDirectory, startTime, deadlineEpochMs, rootSentrySpan, oxlintRuntime) => {
|
|
93280
93887
|
const isDiffMode = options.includePaths.length > 0;
|
|
93281
93888
|
const resolvedNodeBinaryPath = await resolveOxlintNode(options.lint, options.scoreOnly || options.silent);
|
|
93282
93889
|
const lintBindingMissing = options.lint && !resolvedNodeBinaryPath;
|
|
@@ -93326,7 +93933,8 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
|
|
|
93326
93933
|
shouldRunSupplyChain: options.supplyChain,
|
|
93327
93934
|
shouldComputeScore: !options.noScore,
|
|
93328
93935
|
shouldShowProgressSpinners,
|
|
93329
|
-
oxlintConcurrency:
|
|
93936
|
+
oxlintConcurrency: oxlintRuntime.concurrency,
|
|
93937
|
+
oxlintSpawnSlots: oxlintRuntime.spawnSlots,
|
|
93330
93938
|
reporterLayer: options.uiLayers?.reporter,
|
|
93331
93939
|
progressLayer: options.uiLayers?.progress
|
|
93332
93940
|
});
|
|
@@ -93383,7 +93991,8 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
|
|
|
93383
93991
|
baseFiles: options.baseline.baseFiles,
|
|
93384
93992
|
headFiles: options.baseline.headFiles,
|
|
93385
93993
|
headAnalyzedFiles: output.analyzedFiles,
|
|
93386
|
-
deadlineEpochMs
|
|
93994
|
+
deadlineEpochMs,
|
|
93995
|
+
oxlintRuntime
|
|
93387
93996
|
});
|
|
93388
93997
|
if (comparison) {
|
|
93389
93998
|
inspectDiagnostics = comparison.displayDiagnostics;
|
|
@@ -93632,26 +94241,26 @@ const finalizeAndRender = (input) => gen(function* () {
|
|
|
93632
94241
|
//#region src/cli/utils/get-staged-files.ts
|
|
93633
94242
|
const stagedFilesLayer = StagedFiles.layerNode.pipe(provide$2(Git.layerNode));
|
|
93634
94243
|
const getStagedSourceFiles = async (directory) => {
|
|
94244
|
+
let stagedSourceFiles;
|
|
93635
94245
|
try {
|
|
93636
|
-
|
|
94246
|
+
stagedSourceFiles = await runPromise(gen(function* () {
|
|
93637
94247
|
return yield* (yield* StagedFiles).discoverSourceFiles(directory);
|
|
93638
|
-
}).pipe(provide(stagedFilesLayer)))
|
|
94248
|
+
}).pipe(provide(stagedFilesLayer)));
|
|
93639
94249
|
} catch (error) {
|
|
93640
94250
|
cliLogger.warn(`Failed to discover staged files: ${messageFromUnknown(error)}`);
|
|
93641
94251
|
return [];
|
|
93642
94252
|
}
|
|
94253
|
+
if (stagedSourceFiles === null) throw new CliInputError("Could not read the git index to list staged files. Check that git can read the index in this directory.");
|
|
94254
|
+
return [...stagedSourceFiles];
|
|
93643
94255
|
};
|
|
93644
|
-
const materializeStagedFiles = async (
|
|
94256
|
+
const materializeStagedFiles = async (input) => {
|
|
93645
94257
|
const snapshot = await runPromise(gen(function* () {
|
|
93646
|
-
return yield* (yield* StagedFiles).materialize(
|
|
93647
|
-
directory,
|
|
93648
|
-
stagedFiles,
|
|
93649
|
-
tempDirectory
|
|
93650
|
-
});
|
|
94258
|
+
return yield* (yield* StagedFiles).materialize(input);
|
|
93651
94259
|
}).pipe(provide(stagedFilesLayer)));
|
|
93652
94260
|
return {
|
|
93653
94261
|
tempDirectory: snapshot.tempDirectory,
|
|
93654
94262
|
stagedFiles: [...snapshot.stagedFiles],
|
|
94263
|
+
unmaterializedFiles: [...snapshot.unmaterializedFiles],
|
|
93655
94264
|
cleanup: snapshot.cleanup
|
|
93656
94265
|
};
|
|
93657
94266
|
};
|
|
@@ -95525,13 +96134,18 @@ const printMultiProjectSummary = (input) => gen(function* () {
|
|
|
95525
96134
|
const scoreDiagnostics = new Set(filterScansForSurface(completedScans, "score"));
|
|
95526
96135
|
const displayedScoreDiagnostics = displayDiagnostics.filter((diagnostic) => scoreDiagnostics.has(diagnostic));
|
|
95527
96136
|
const projectRootByDiagnostic = /* @__PURE__ */ new WeakMap();
|
|
95528
|
-
|
|
96137
|
+
const frameSourceRootByDiagnostic = /* @__PURE__ */ new WeakMap();
|
|
96138
|
+
for (const scan of completedScans) for (const diagnostic of scan.result.diagnostics) {
|
|
96139
|
+
projectRootByDiagnostic.set(diagnostic, scan.result.project.rootDirectory);
|
|
96140
|
+
frameSourceRootByDiagnostic.set(diagnostic, scan.frameSourceRoot ?? scan.result.project.rootDirectory);
|
|
96141
|
+
}
|
|
95529
96142
|
const resolveDiagnosticSourceRoot = (diagnostic) => projectRootByDiagnostic.get(diagnostic) ?? "";
|
|
96143
|
+
const resolveDiagnosticFrameSourceRoot = (diagnostic) => frameSourceRootByDiagnostic.get(diagnostic) ?? resolveDiagnosticSourceRoot(diagnostic);
|
|
95530
96144
|
const totalScannedFileCount = countUniqueScannedFiles(completedScans.map((scan) => scan.result));
|
|
95531
96145
|
yield* log(`${highlighter.success("✔")} Scanned ${totalScannedFileCount} ${totalScannedFileCount === 1 ? "file" : "files"} in ${formatElapsedTime(totalElapsedMilliseconds)}`);
|
|
95532
96146
|
if (displayDiagnostics.length > 0) {
|
|
95533
96147
|
yield* log("");
|
|
95534
|
-
yield* printDiagnostics(displayDiagnostics, verbose, resolveDiagnosticSourceRoot, buildRulePriorityMap(completedScans.map((scan) => scan.result.score)), isCodingAgentEnvironment(), { animateCountUp: animateRender }, shouldRenderHyperlinks(process.stdout));
|
|
96148
|
+
yield* printDiagnostics(displayDiagnostics, verbose, resolveDiagnosticSourceRoot, buildRulePriorityMap(completedScans.map((scan) => scan.result.score)), isCodingAgentEnvironment(), { animateCountUp: animateRender }, shouldRenderHyperlinks(process.stdout), resolveDiagnosticFrameSourceRoot);
|
|
95535
96149
|
}
|
|
95536
96150
|
const lowestScoredScan = findLowestScoredScan(completedScans);
|
|
95537
96151
|
const aggregateScore = lowestScoredScan?.result.score ?? null;
|
|
@@ -95919,6 +96533,45 @@ const runExplain = async (fileLineArgument, context) => {
|
|
|
95919
96533
|
}
|
|
95920
96534
|
};
|
|
95921
96535
|
//#endregion
|
|
96536
|
+
//#region src/cli/utils/run-project-scan-batch.ts
|
|
96537
|
+
/**
|
|
96538
|
+
* Run one scan per project through the same bounded pool as
|
|
96539
|
+
* `diagnose({ projects })`, with the batch spinner and its progress counter.
|
|
96540
|
+
*
|
|
96541
|
+
* Pool members must not toggle the module-level spinner-silent flag themselves —
|
|
96542
|
+
* overlapping save/restore pairs would race — so the batch owns that toggle once
|
|
96543
|
+
* around the whole run.
|
|
96544
|
+
*
|
|
96545
|
+
* A `scanProject` that returns `null` drops the project from the results: diff
|
|
96546
|
+
* mode skips projects with no changed source.
|
|
96547
|
+
*/
|
|
96548
|
+
const runProjectScanBatch = async (input) => {
|
|
96549
|
+
const startTime = performance$1.now();
|
|
96550
|
+
const projectCount = input.projects.length;
|
|
96551
|
+
const isMultiProject = projectCount > 1;
|
|
96552
|
+
const batchSpinner = isMultiProject && !input.isQuiet ? spinner(`Scanning ${projectCount} projects…`).start() : null;
|
|
96553
|
+
const ownsBatchSpinnerSilence = isMultiProject && input.isSilent;
|
|
96554
|
+
const wasSpinnerSilent = isSpinnerSilent();
|
|
96555
|
+
if (ownsBatchSpinnerSilence) setSpinnerSilent(true);
|
|
96556
|
+
let finishedProjectCount = 0;
|
|
96557
|
+
let scanOutcomes;
|
|
96558
|
+
try {
|
|
96559
|
+
scanOutcomes = await mapWithConcurrency(input.projects, isMultiProject ? 4 : 1, async (project) => {
|
|
96560
|
+
const scanOutcome = await input.scanProject(project);
|
|
96561
|
+
finishedProjectCount += 1;
|
|
96562
|
+
batchSpinner?.update(`Scanning ${projectCount} projects… (${finishedProjectCount}/${projectCount})`);
|
|
96563
|
+
return scanOutcome;
|
|
96564
|
+
});
|
|
96565
|
+
} finally {
|
|
96566
|
+
if (ownsBatchSpinnerSilence) setSpinnerSilent(wasSpinnerSilent);
|
|
96567
|
+
batchSpinner?.stop();
|
|
96568
|
+
}
|
|
96569
|
+
return {
|
|
96570
|
+
completedScans: scanOutcomes.filter((scanOutcome) => scanOutcome !== null),
|
|
96571
|
+
elapsedMilliseconds: performance$1.now() - startTime
|
|
96572
|
+
};
|
|
96573
|
+
};
|
|
96574
|
+
//#endregion
|
|
95922
96575
|
//#region src/cli/utils/project-manifest-changed.ts
|
|
95923
96576
|
const PACKAGE_JSON = "package.json";
|
|
95924
96577
|
/**
|
|
@@ -95935,6 +96588,29 @@ const projectManifestChanged = (rootDirectory, projectDirectory, diffInfo) => {
|
|
|
95935
96588
|
return diffInfo.changedFiles.some((filePath) => toForwardSlashes(filePath) === manifestPath);
|
|
95936
96589
|
};
|
|
95937
96590
|
//#endregion
|
|
96591
|
+
//#region src/cli/utils/select-staged-projects.ts
|
|
96592
|
+
/**
|
|
96593
|
+
* Appended to the reason a `--staged` run could not scan per package. Shared so
|
|
96594
|
+
* both fallback sites word it identically.
|
|
96595
|
+
*/
|
|
96596
|
+
const STAGED_PROJECT_FALLBACK_HINT = "Scanning the staged files at the scan root instead — fix the `projects` entries in your config to scan per package.";
|
|
96597
|
+
/**
|
|
96598
|
+
* Resolve the project directories a `--staged` scan owns. The interactive picker
|
|
96599
|
+
* is always skipped: a commit hook has nobody to answer it.
|
|
96600
|
+
*/
|
|
96601
|
+
const selectStagedProjects = async (input) => {
|
|
96602
|
+
if (input.projectFlag) return selectProjects(input.rootDirectory, input.projectFlag, true, void 0);
|
|
96603
|
+
if (input.configProjects === void 0) return [input.rootDirectory];
|
|
96604
|
+
try {
|
|
96605
|
+
return await selectProjects(input.rootDirectory, void 0, true, input.configProjects);
|
|
96606
|
+
} catch (error) {
|
|
96607
|
+
if (!(error instanceof CliInputError)) throw error;
|
|
96608
|
+
cliLogger.warn(`${error.message} ${STAGED_PROJECT_FALLBACK_HINT}`);
|
|
96609
|
+
cliLogger.break();
|
|
96610
|
+
return [input.rootDirectory];
|
|
96611
|
+
}
|
|
96612
|
+
};
|
|
96613
|
+
//#endregion
|
|
95938
96614
|
//#region src/cli/utils/should-fail-scan-gate.ts
|
|
95939
96615
|
const shouldFailScanGate = (input) => {
|
|
95940
96616
|
if (input.blockingLevel === "none") return false;
|
|
@@ -96100,6 +96776,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96100
96776
|
const isQuiet = isScoreOnly || isJsonMode;
|
|
96101
96777
|
const requestedDirectory = Path.resolve(directory);
|
|
96102
96778
|
const startTime = performance$1.now();
|
|
96779
|
+
let scanStartupSpinner = null;
|
|
96103
96780
|
if (isJsonMode) {
|
|
96104
96781
|
enableJsonMode({
|
|
96105
96782
|
compact: Boolean(flags.jsonCompact),
|
|
@@ -96148,6 +96825,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96148
96825
|
if (!isQuiet) if (!flags.verbose && canAnimateOnboarding(process.stdout)) await runPromise(playWelcomeScene({ speedMultiplier: !isOnboardingForced() && hasCompletedOnboarding() ? 2 : 1 }));
|
|
96149
96826
|
else runSync(printBrandedHeader);
|
|
96150
96827
|
const scanOptions = resolveCliInspectOptions(flags, userConfig);
|
|
96828
|
+
const inspectProject = createInvocationInspect(scanOptions.concurrency);
|
|
96151
96829
|
const scanDeadlineEpochMs = scanOptions.maxDurationMs !== void 0 ? Date.now() + scanOptions.maxDurationMs : void 0;
|
|
96152
96830
|
const categoryFilters = new Set(scanOptions.categoryFilters ?? []);
|
|
96153
96831
|
const skipPrompts = shouldSkipPrompts({
|
|
@@ -96155,8 +96833,13 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96155
96833
|
json: flags.json
|
|
96156
96834
|
});
|
|
96157
96835
|
if (flags.staged) {
|
|
96158
|
-
const
|
|
96159
|
-
|
|
96836
|
+
const configProjectsApply = (userConfig?.projects ?? []).some((projectName) => projectName.trim().length > 0) && scanTarget.requestedDirectory === scanTarget.configSourceDirectory;
|
|
96837
|
+
const projectDirectories = await selectStagedProjects({
|
|
96838
|
+
rootDirectory: resolvedDirectory,
|
|
96839
|
+
projectFlag: flags.project,
|
|
96840
|
+
configProjects: configProjectsApply ? userConfig?.projects : void 0
|
|
96841
|
+
});
|
|
96842
|
+
const reportNothingToScan = (input) => {
|
|
96160
96843
|
if (isJsonMode) writeJsonReport(buildJsonReport({
|
|
96161
96844
|
version: VERSION,
|
|
96162
96845
|
directory: resolvedDirectory,
|
|
@@ -96165,75 +96848,214 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96165
96848
|
scans: [],
|
|
96166
96849
|
totalElapsedMilliseconds: performance$1.now() - startTime
|
|
96167
96850
|
}));
|
|
96168
|
-
else if (!isScoreOnly)
|
|
96851
|
+
else if (!isScoreOnly) if (input.severity === "warn") {
|
|
96852
|
+
cliLogger.warn(input.reason);
|
|
96853
|
+
cliLogger.break();
|
|
96854
|
+
} else cliLogger.dim(input.reason);
|
|
96855
|
+
};
|
|
96856
|
+
const rootStagedFiles = await getStagedSourceFiles(resolvedDirectory);
|
|
96857
|
+
if (rootStagedFiles.length === 0) {
|
|
96858
|
+
reportNothingToScan({ reason: "No staged source files found." });
|
|
96169
96859
|
return;
|
|
96170
96860
|
}
|
|
96171
|
-
|
|
96172
|
-
|
|
96861
|
+
const buildProjectScanContext = async (projectDirectory) => {
|
|
96862
|
+
const projectScanTarget = projectDirectory === resolvedDirectory ? scanTarget : await resolveScanTarget(projectDirectory, { allowAmbiguous: true });
|
|
96863
|
+
const scanDirectory = projectScanTarget.resolvedDirectory;
|
|
96864
|
+
const treeRelativeDirectory = resolveProjectRelativeDirectory(resolvedDirectory, scanDirectory);
|
|
96865
|
+
if (treeRelativeDirectory === null) return null;
|
|
96866
|
+
return {
|
|
96867
|
+
projectDirectory,
|
|
96868
|
+
scanDirectory,
|
|
96869
|
+
treeRelativeDirectory,
|
|
96870
|
+
projectConfig: projectDirectory === resolvedDirectory ? userConfig : mergeReactDoctorConfigs(userConfig, projectScanTarget.userConfig ?? void 0),
|
|
96871
|
+
projectConfigSourceDirectory: projectScanTarget.userConfig?.plugins === void 0 ? scanTarget.configSourceDirectory : projectScanTarget.configSourceDirectory
|
|
96872
|
+
};
|
|
96873
|
+
};
|
|
96874
|
+
const projectScanContexts = [];
|
|
96875
|
+
const seenScanDirectories = /* @__PURE__ */ new Set();
|
|
96876
|
+
for (const projectDirectory of projectDirectories) {
|
|
96877
|
+
const projectScanContext = await buildProjectScanContext(projectDirectory);
|
|
96878
|
+
if (projectScanContext === null) {
|
|
96879
|
+
if (flags.project) throw new CliInputError(`Project "${toRelativePath(projectDirectory, resolvedDirectory)}" is outside ${resolvedDirectory}, so it holds none of the staged files. Run --staged from a directory that contains the project.`);
|
|
96880
|
+
continue;
|
|
96881
|
+
}
|
|
96882
|
+
if (seenScanDirectories.has(projectScanContext.scanDirectory)) continue;
|
|
96883
|
+
seenScanDirectories.add(projectScanContext.scanDirectory);
|
|
96884
|
+
projectScanContexts.push(projectScanContext);
|
|
96885
|
+
}
|
|
96886
|
+
if (projectScanContexts.length === 0) {
|
|
96887
|
+
cliLogger.warn(`No configured project is inside ${resolvedDirectory}. ${STAGED_PROJECT_FALLBACK_HINT}`);
|
|
96173
96888
|
cliLogger.break();
|
|
96889
|
+
const rootScanContext = await buildProjectScanContext(resolvedDirectory);
|
|
96890
|
+
if (rootScanContext !== null) projectScanContexts.push(rootScanContext);
|
|
96174
96891
|
}
|
|
96175
|
-
const
|
|
96176
|
-
const
|
|
96177
|
-
|
|
96178
|
-
|
|
96179
|
-
|
|
96892
|
+
const contextsByLongestPathFirst = [...projectScanContexts].sort((left, right) => right.treeRelativeDirectory.length - left.treeRelativeDirectory.length);
|
|
96893
|
+
const ownedStagedFiles = /* @__PURE__ */ new Map();
|
|
96894
|
+
for (const stagedFile of rootStagedFiles) {
|
|
96895
|
+
const owner = contextsByLongestPathFirst.find((context) => context.treeRelativeDirectory.length === 0 || stagedFile.startsWith(`${context.treeRelativeDirectory}/`));
|
|
96896
|
+
if (owner === void 0) continue;
|
|
96897
|
+
const ownedFiles = ownedStagedFiles.get(owner.scanDirectory);
|
|
96898
|
+
if (ownedFiles === void 0) ownedStagedFiles.set(owner.scanDirectory, [stagedFile]);
|
|
96899
|
+
else ownedFiles.push(stagedFile);
|
|
96900
|
+
}
|
|
96901
|
+
const stagedProjectScans = [];
|
|
96902
|
+
for (const projectScanContext of projectScanContexts) {
|
|
96903
|
+
const projectStagedFiles = ownedStagedFiles.get(projectScanContext.scanDirectory);
|
|
96904
|
+
if (projectStagedFiles === void 0) continue;
|
|
96905
|
+
stagedProjectScans.push({
|
|
96906
|
+
...projectScanContext,
|
|
96907
|
+
stagedFiles: projectStagedFiles
|
|
96180
96908
|
});
|
|
96181
|
-
|
|
96182
|
-
|
|
96909
|
+
}
|
|
96910
|
+
if (stagedProjectScans.length === 0) {
|
|
96911
|
+
reportNothingToScan({ reason: "No staged source files in the selected projects." });
|
|
96912
|
+
return;
|
|
96913
|
+
}
|
|
96914
|
+
const selectedStagedFiles = stagedProjectScans.flatMap((projectScan) => projectScan.stagedFiles);
|
|
96915
|
+
const stagedFileCount = selectedStagedFiles.length;
|
|
96916
|
+
const unselectedStagedFileCount = rootStagedFiles.length - stagedFileCount;
|
|
96917
|
+
if (!isQuiet) {
|
|
96918
|
+
cliLogger.log(`Scanning ${highlighter.info(`${stagedFileCount}`)} staged files...`);
|
|
96919
|
+
if (unselectedStagedFileCount > 0) cliLogger.dim(`${unselectedStagedFileCount} more staged file${unselectedStagedFileCount === 1 ? "" : "s"} outside the selected projects.`);
|
|
96920
|
+
cliLogger.break();
|
|
96921
|
+
}
|
|
96183
96922
|
const stagedWantsLines = resolveScope(flags, userConfig).scope === "lines";
|
|
96184
96923
|
const stagedLineRanges = stagedWantsLines ? await getChangedLineRanges({
|
|
96185
96924
|
directory: resolvedDirectory,
|
|
96186
96925
|
cached: true,
|
|
96187
|
-
files:
|
|
96926
|
+
files: selectedStagedFiles
|
|
96188
96927
|
}) : null;
|
|
96189
96928
|
if (stagedWantsLines && stagedLineRanges === null && !isQuiet) {
|
|
96190
96929
|
cliLogger.warn("Could not determine staged changed lines; reporting all issues in staged files.");
|
|
96191
96930
|
cliLogger.break();
|
|
96192
96931
|
}
|
|
96193
|
-
|
|
96194
|
-
|
|
96932
|
+
if (stagedProjectScans.some((projectScan) => projectScan.treeRelativeDirectory.length > 0)) recordCount(METRIC.stagedPerProject, 1, { projectCount: stagedProjectScans.length });
|
|
96933
|
+
const tempDirectory = NFS.mkdtempSync(Path.join(tmpdir(), STAGED_FILES_TEMP_DIR_PREFIX));
|
|
96934
|
+
const configSubdirectories = /* @__PURE__ */ new Set();
|
|
96935
|
+
for (const projectScan of stagedProjectScans) {
|
|
96936
|
+
configSubdirectories.add(projectScan.treeRelativeDirectory);
|
|
96937
|
+
const projectRelativeDirectory = resolveProjectRelativeDirectory(resolvedDirectory, projectScan.projectDirectory);
|
|
96938
|
+
if (projectRelativeDirectory !== null) configSubdirectories.add(projectRelativeDirectory);
|
|
96939
|
+
}
|
|
96940
|
+
const snapshot = await materializeStagedFiles({
|
|
96941
|
+
directory: resolvedDirectory,
|
|
96942
|
+
stagedFiles: selectedStagedFiles,
|
|
96943
|
+
tempDirectory,
|
|
96944
|
+
configSubdirectories: [...configSubdirectories]
|
|
96945
|
+
}).catch((error) => {
|
|
96946
|
+
NFS.rmSync(tempDirectory, {
|
|
96947
|
+
recursive: true,
|
|
96948
|
+
force: true
|
|
96949
|
+
});
|
|
96950
|
+
throw error;
|
|
96951
|
+
});
|
|
96952
|
+
const materializedStagedFiles = new Set(snapshot.stagedFiles);
|
|
96953
|
+
const stagedProjectRuns = stagedProjectScans.map((projectScan) => ({
|
|
96954
|
+
projectScan,
|
|
96955
|
+
includePaths: resolveProjectSourceFilePaths(resolvedDirectory, projectScan.scanDirectory, projectScan.stagedFiles.filter((stagedFile) => materializedStagedFiles.has(stagedFile)))
|
|
96956
|
+
})).filter((projectRun) => projectRun.includePaths.length > 0);
|
|
96957
|
+
const isMultiProject = stagedProjectRuns.length > 1;
|
|
96958
|
+
if (stagedProjectRuns.length === 0) {
|
|
96959
|
+
snapshot.cleanup();
|
|
96960
|
+
reportNothingToScan({
|
|
96961
|
+
reason: `Could not read any of the ${stagedFileCount} staged file${stagedFileCount === 1 ? "" : "s"} out of the index, so nothing was scanned. An unusually large staged file is the usual cause.`,
|
|
96962
|
+
severity: "warn"
|
|
96963
|
+
});
|
|
96964
|
+
return;
|
|
96965
|
+
}
|
|
96966
|
+
if (snapshot.unmaterializedFiles.length > 0 && !isQuiet) {
|
|
96967
|
+
const stagedFileLabel = `staged file${stagedFileCount === 1 ? "" : "s"}`;
|
|
96968
|
+
cliLogger.warn(`Skipped ${snapshot.unmaterializedFiles.length} of ${stagedFileCount} ${stagedFileLabel}; they could not be snapshotted from the index.`);
|
|
96969
|
+
cliLogger.break();
|
|
96970
|
+
}
|
|
96971
|
+
const scanStagedProject = async (projectRun) => {
|
|
96972
|
+
const { projectScan, includePaths } = projectRun;
|
|
96973
|
+
const projectTempDirectory = Path.join(snapshot.tempDirectory, projectScan.treeRelativeDirectory);
|
|
96974
|
+
const scanResult = await inspectProject(projectTempDirectory, {
|
|
96195
96975
|
...scanOptions,
|
|
96196
96976
|
deadlineEpochMs: scanDeadlineEpochMs,
|
|
96197
|
-
includePaths:
|
|
96198
|
-
configOverride:
|
|
96199
|
-
configSourceDirectory:
|
|
96200
|
-
changedLineRanges: stagedLineRanges
|
|
96977
|
+
includePaths: [...includePaths],
|
|
96978
|
+
configOverride: projectScan.projectConfig,
|
|
96979
|
+
configSourceDirectory: projectScan.projectConfigSourceDirectory ?? void 0,
|
|
96980
|
+
changedLineRanges: stagedLineRanges === null ? void 0 : resolveProjectChangedLineRanges(resolvedDirectory, projectScan.scanDirectory, stagedLineRanges),
|
|
96981
|
+
suppressRendering: isMultiProject,
|
|
96982
|
+
concurrentScan: isMultiProject
|
|
96201
96983
|
});
|
|
96202
96984
|
const remappedDiagnostics = scanResult.diagnostics.map((diagnostic) => ({
|
|
96203
96985
|
...diagnostic,
|
|
96204
|
-
filePath: Path.isAbsolute(diagnostic.filePath) ? diagnostic.filePath.replaceAll(
|
|
96986
|
+
filePath: Path.isAbsolute(diagnostic.filePath) ? diagnostic.filePath.replaceAll(projectTempDirectory, () => projectScan.scanDirectory) : diagnostic.filePath
|
|
96205
96987
|
}));
|
|
96206
|
-
|
|
96207
|
-
|
|
96208
|
-
|
|
96209
|
-
|
|
96210
|
-
|
|
96211
|
-
|
|
96212
|
-
project
|
|
96213
|
-
|
|
96214
|
-
|
|
96215
|
-
|
|
96216
|
-
|
|
96217
|
-
|
|
96218
|
-
|
|
96219
|
-
|
|
96220
|
-
|
|
96221
|
-
|
|
96222
|
-
|
|
96223
|
-
|
|
96224
|
-
|
|
96225
|
-
|
|
96226
|
-
|
|
96227
|
-
|
|
96228
|
-
|
|
96229
|
-
|
|
96988
|
+
return {
|
|
96989
|
+
directory: projectScan.scanDirectory,
|
|
96990
|
+
result: {
|
|
96991
|
+
...scanResult,
|
|
96992
|
+
diagnostics: remappedDiagnostics,
|
|
96993
|
+
project: {
|
|
96994
|
+
...scanResult.project,
|
|
96995
|
+
rootDirectory: projectScan.scanDirectory
|
|
96996
|
+
}
|
|
96997
|
+
},
|
|
96998
|
+
config: projectScan.projectConfig,
|
|
96999
|
+
frameSourceRoot: projectTempDirectory
|
|
97000
|
+
};
|
|
97001
|
+
};
|
|
97002
|
+
const stagedBatch = await runProjectScanBatch({
|
|
97003
|
+
projects: stagedProjectRuns,
|
|
97004
|
+
isQuiet,
|
|
97005
|
+
isSilent: scanOptions.silent === true,
|
|
97006
|
+
scanProject: scanStagedProject
|
|
97007
|
+
}).catch((error) => {
|
|
97008
|
+
snapshot.cleanup();
|
|
97009
|
+
throw error;
|
|
97010
|
+
});
|
|
97011
|
+
const completedScans = stagedBatch.completedScans;
|
|
97012
|
+
try {
|
|
97013
|
+
if (!isQuiet && isMultiProject) {
|
|
97014
|
+
const showShareLink = !isShareOptedOut(completedScans, scanOptions.noScore) && !scanOptions.isCi;
|
|
97015
|
+
await runPromise(printMultiProjectSummary({
|
|
97016
|
+
completedScans,
|
|
97017
|
+
categoryFilters,
|
|
97018
|
+
verbose: Boolean(flags.verbose),
|
|
97019
|
+
outputDirectory: flags.outputDir,
|
|
97020
|
+
isOffline: !showShareLink,
|
|
97021
|
+
projectName: Path.basename(resolvedDirectory),
|
|
97022
|
+
totalElapsedMilliseconds: stagedBatch.elapsedMilliseconds
|
|
97023
|
+
}));
|
|
97024
|
+
}
|
|
97025
|
+
if (flags.outputDir && isMultiProject && isQuiet) await runPromise(printDiagnosticsDump(filterDiagnosticsByCategories(filterScansForSurface(completedScans, scanOptions.outputSurface ?? "cli"), categoryFilters), flags.outputDir, false, "stderr"));
|
|
96230
97026
|
} finally {
|
|
96231
97027
|
snapshot.cleanup();
|
|
96232
97028
|
}
|
|
97029
|
+
finalizeScans({
|
|
97030
|
+
completedScans,
|
|
97031
|
+
mode: "staged",
|
|
97032
|
+
diff: null,
|
|
97033
|
+
baselineIntended: false,
|
|
97034
|
+
isJsonMode,
|
|
97035
|
+
isScoreOnly,
|
|
97036
|
+
flags,
|
|
97037
|
+
categoryFilters,
|
|
97038
|
+
userConfig,
|
|
97039
|
+
resolvedDirectory,
|
|
97040
|
+
startTime
|
|
97041
|
+
});
|
|
96233
97042
|
return;
|
|
96234
97043
|
}
|
|
96235
97044
|
const projectDirectories = await selectProjects(resolvedDirectory, flags.project, skipPrompts, userConfig?.projects);
|
|
96236
|
-
const
|
|
97045
|
+
const projectSelectionCompletedTime = performance$1.now();
|
|
97046
|
+
let changedFilesDiffInfo = flags.changedFilesFrom ? buildChangedFilesDiffInfo(readChangedFilesFrom(Path.resolve(flags.changedFilesFrom))) : null;
|
|
97047
|
+
if (changedFilesDiffInfo !== null && scanTarget.didRedirectViaRootDir) {
|
|
97048
|
+
const relativeProjectDirectory = resolveProjectRelativeDirectory(requestedDirectory, resolvedDirectory);
|
|
97049
|
+
if (relativeProjectDirectory) {
|
|
97050
|
+
const projectPrefix = `${relativeProjectDirectory}/`;
|
|
97051
|
+
changedFilesDiffInfo = {
|
|
97052
|
+
...changedFilesDiffInfo,
|
|
97053
|
+
changedFiles: changedFilesDiffInfo.changedFiles.flatMap((filePath) => {
|
|
97054
|
+
return filePath.startsWith(projectPrefix) ? [filePath.slice(projectPrefix.length)] : [];
|
|
97055
|
+
})
|
|
97056
|
+
};
|
|
97057
|
+
}
|
|
97058
|
+
}
|
|
96237
97059
|
const requestedScope = resolveScope(flags, userConfig);
|
|
96238
97060
|
const includeUntracked = flags.includeUntracked ?? false;
|
|
96239
97061
|
const scopeRequest = requestedScope.scope === void 0 && changedFilesDiffInfo !== null ? {
|
|
@@ -96241,15 +97063,20 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96241
97063
|
scope: "changed"
|
|
96242
97064
|
} : requestedScope;
|
|
96243
97065
|
validateIncludeUntrackedScope(includeUntracked, scopeRequest.scope);
|
|
97066
|
+
scanStartupSpinner = !isQuiet ? spinner("Scanning...").start() : null;
|
|
97067
|
+
if (scanStartupSpinner !== null) recordDistribution(METRIC.scanFeedbackDelay, performance$1.now() - projectSelectionCompletedTime, { unit: "millisecond" });
|
|
96244
97068
|
const wantsDiffMode = scopeRequest.scope !== void 0 && scopeRequest.scope !== "full";
|
|
96245
97069
|
const shouldDetectDiff = changedFilesDiffInfo === null && (wantsDiffMode || scopeRequest.scope === void 0 && !skipPrompts && !isQuiet);
|
|
96246
97070
|
const diffInfo = changedFilesDiffInfo ?? (shouldDetectDiff ? await getDiffInfo(resolvedDirectory, scopeRequest.base, includeUntracked) : null);
|
|
97071
|
+
scanStartupSpinner?.stop();
|
|
97072
|
+
scanStartupSpinner = null;
|
|
96247
97073
|
const scope = await finalizeScope({
|
|
96248
97074
|
requested: scopeRequest,
|
|
96249
97075
|
diffInfo,
|
|
96250
97076
|
skipPrompts,
|
|
96251
97077
|
isQuiet
|
|
96252
97078
|
});
|
|
97079
|
+
scanStartupSpinner = !isQuiet ? spinner("Scanning...").start() : null;
|
|
96253
97080
|
const isDiffMode = scope !== "full";
|
|
96254
97081
|
const comparisonBaseRef = isDiffMode && diffInfo && !diffInfo.isCurrentChanges ? diffInfo.baseSha ? await resolveMergeBaseRef(resolvedDirectory, diffInfo.baseSha) : diffInfo.diffBaseRef ?? await resolveMergeBaseRef(resolvedDirectory, diffInfo.baseBranch) : null;
|
|
96255
97082
|
const baselineRef = scope === "changed" ? comparisonBaseRef : null;
|
|
@@ -96261,6 +97088,8 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96261
97088
|
files: [...diffInfo.changedFiles],
|
|
96262
97089
|
includeUntracked
|
|
96263
97090
|
}) : null;
|
|
97091
|
+
scanStartupSpinner?.stop();
|
|
97092
|
+
scanStartupSpinner = null;
|
|
96264
97093
|
if (scope === "lines" && changedLineRanges === null && !isQuiet) {
|
|
96265
97094
|
cliLogger.warn("Could not determine changed lines (no base ref or git diff failed); reporting all issues in changed files.");
|
|
96266
97095
|
cliLogger.break();
|
|
@@ -96274,7 +97103,6 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96274
97103
|
}
|
|
96275
97104
|
cliLogger.break();
|
|
96276
97105
|
}
|
|
96277
|
-
const completedScans = [];
|
|
96278
97106
|
const isMultiProject = projectDirectories.length > 1;
|
|
96279
97107
|
const scanProject = async (projectDirectory) => {
|
|
96280
97108
|
const projectScanTarget = projectDirectory === resolvedDirectory ? scanTarget : await resolveScanTarget(projectDirectory, { allowAmbiguous: true });
|
|
@@ -96302,7 +97130,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96302
97130
|
if (supplyChainManifestChanged) includePaths.push("package.json");
|
|
96303
97131
|
}
|
|
96304
97132
|
if (!isQuiet && !isMultiProject) cliLogger.dim(" ");
|
|
96305
|
-
const scanResult = await
|
|
97133
|
+
const scanResult = await inspectProject(scanDirectory, {
|
|
96306
97134
|
...scanOptions,
|
|
96307
97135
|
deadlineEpochMs: scanDeadlineEpochMs,
|
|
96308
97136
|
includePaths,
|
|
@@ -96325,29 +97153,13 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96325
97153
|
config: projectConfig
|
|
96326
97154
|
};
|
|
96327
97155
|
};
|
|
96328
|
-
const
|
|
96329
|
-
|
|
96330
|
-
|
|
96331
|
-
|
|
96332
|
-
|
|
96333
|
-
|
|
96334
|
-
|
|
96335
|
-
let scanOutcomes;
|
|
96336
|
-
try {
|
|
96337
|
-
scanOutcomes = await mapWithConcurrency(projectDirectories, isMultiProject ? 4 : 1, async (projectDirectory) => {
|
|
96338
|
-
const scanOutcome = await scanProject(projectDirectory);
|
|
96339
|
-
finishedProjectCount += 1;
|
|
96340
|
-
batchSpinner?.update(`Scanning ${projectCount} projects… (${finishedProjectCount}/${projectCount})`);
|
|
96341
|
-
return scanOutcome;
|
|
96342
|
-
});
|
|
96343
|
-
} finally {
|
|
96344
|
-
if (ownsBatchSpinnerSilence) setSpinnerSilent(wasSpinnerSilent);
|
|
96345
|
-
batchSpinner?.stop();
|
|
96346
|
-
}
|
|
96347
|
-
for (const scanOutcome of scanOutcomes) {
|
|
96348
|
-
if (scanOutcome === null) continue;
|
|
96349
|
-
completedScans.push(scanOutcome);
|
|
96350
|
-
}
|
|
97156
|
+
const projectBatch = await runProjectScanBatch({
|
|
97157
|
+
projects: projectDirectories,
|
|
97158
|
+
isQuiet,
|
|
97159
|
+
isSilent: scanOptions.silent === true,
|
|
97160
|
+
scanProject
|
|
97161
|
+
});
|
|
97162
|
+
const completedScans = projectBatch.completedScans;
|
|
96351
97163
|
if (!isQuiet && isMultiProject && completedScans.length > 0) {
|
|
96352
97164
|
const showShareLink = !isShareOptedOut(completedScans, scanOptions.noScore) && !scanOptions.isCi;
|
|
96353
97165
|
await runPromise(printMultiProjectSummary({
|
|
@@ -96357,7 +97169,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96357
97169
|
outputDirectory: flags.outputDir,
|
|
96358
97170
|
isOffline: !showShareLink,
|
|
96359
97171
|
projectName: Path.basename(resolvedDirectory),
|
|
96360
|
-
totalElapsedMilliseconds:
|
|
97172
|
+
totalElapsedMilliseconds: projectBatch.elapsedMilliseconds
|
|
96361
97173
|
}));
|
|
96362
97174
|
}
|
|
96363
97175
|
const selectedSurfaceDiagnostics = filterDiagnosticsByCategories(filterScansForSurface(completedScans, scanOptions.outputSurface ?? "cli"), categoryFilters);
|
|
@@ -96404,6 +97216,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
96404
97216
|
}
|
|
96405
97217
|
}
|
|
96406
97218
|
} catch (error) {
|
|
97219
|
+
scanStartupSpinner?.stop();
|
|
96407
97220
|
const isUserError = isExpectedUserError(error);
|
|
96408
97221
|
const sentryEventId = isUserError ? void 0 : await reportErrorToSentry(error);
|
|
96409
97222
|
if (isDebugFlagEnabled()) await flushSentry();
|
|
@@ -97338,6 +98151,7 @@ const COMMAND_FLAG_SPECS = new Map([
|
|
|
97338
98151
|
"--no-color",
|
|
97339
98152
|
"--no-dead-code",
|
|
97340
98153
|
"--no-score",
|
|
98154
|
+
"--no-supply-chain",
|
|
97341
98155
|
"--yes"
|
|
97342
98156
|
]),
|
|
97343
98157
|
longOptionsWithRequiredValues: new Set(["--blocking", "--project"]),
|
|
@@ -97501,7 +98315,7 @@ ${highlighter.dim("Learn more:")}
|
|
|
97501
98315
|
${highlighter.info(CI_URL)}
|
|
97502
98316
|
`;
|
|
97503
98317
|
const collectCategoryOption = (value, previousValues) => [...previousValues ?? [], value];
|
|
97504
|
-
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS and inline HTML script source to scan/report: full (default), files, changed (only new issues vs base), or lines (issues whose source spans touch changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").option("--include-untracked", "with --scope files/changed/lines, also scan ordinary untracked files (respects .gitignore)").addOption(new Option("--diff [base]", "[deprecated] alias for --scope changed (pass `false` to force a full scan)").hideHelp()).addOption(new Option("--changed-files-from <file>", "scan source files listed in a newline-delimited changed-files file").hideHelp()).option("--no-score", "skip the score API, the share URL, and crash reporting").addOption(new Option("--category <category>", "only show diagnostics in a category (repeatable; e.g. Security)").argParser(collectCategoryOption)).option("--no-telemetry", "alias for --no-score (skip the score API, share URL, and crash reporting)").option("--staged", "scan only staged (git index) files for pre-commit hooks").option("--max-duration <seconds>", "scan time budget for the whole run, shared across workspace projects: past it, remaining lint batches and dead-code are skipped and partial results are reported (skipped files are listed in the JSON report)").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").addOption(new Option("--fail-on <level>", "[deprecated] alias for --blocking <level>").hideHelp()).option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").option("--warnings", "show warning-severity diagnostics (default)").option("--no-warnings", "hide warning-severity diagnostics (errors only)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderRootHelpEpilog);
|
|
98318
|
+
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS and inline HTML script source to scan/report: full (default), files, changed (only new issues vs base), or lines (issues whose source spans touch changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").option("--include-untracked", "with --scope files/changed/lines, also scan ordinary untracked files (respects .gitignore)").addOption(new Option("--diff [base]", "[deprecated] alias for --scope changed (pass `false` to force a full scan)").hideHelp()).addOption(new Option("--changed-files-from <file>", "scan source files listed in a newline-delimited changed-files file").hideHelp()).option("--no-score", "skip the score API, the share URL, and crash reporting").addOption(new Option("--category <category>", "only show diagnostics in a category (repeatable; e.g. Security)").argParser(collectCategoryOption)).option("--no-telemetry", "alias for --no-score (skip the score API, share URL, and crash reporting)").option("--staged", "scan only staged (git index) files for pre-commit hooks (honors --project and config `projects`; exits 0 when nothing is staged)").option("--max-duration <seconds>", "scan time budget for the whole run, shared across workspace projects: past it, remaining lint batches and dead-code are skipped and partial results are reported (skipped files are listed in the JSON report)").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").addOption(new Option("--fail-on <level>", "[deprecated] alias for --blocking <level>").hideHelp()).option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").option("--warnings", "show warning-severity diagnostics (default)").option("--no-warnings", "hide warning-severity diagnostics (errors only)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderRootHelpEpilog);
|
|
97505
98319
|
program.action(inspectAction);
|
|
97506
98320
|
program.command("design [directory]").description("Run only the focused UI design diagnostics").addHelpText("after", renderDesignHelpEpilog).action((directory, _options, command) => designAction(directory ?? ".", command.optsWithGlobals()));
|
|
97507
98321
|
program.command("why <location>").description("Explain why a rule fired (or why a suppression didn't apply) at a file:line").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple)").option("-c, --cwd <cwd>", "working directory", process.cwd()).option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").action((location, options) => whyAction(location, options));
|
|
@@ -97523,15 +98337,17 @@ rules.command("category <category> <severity>").description("Set the severity fo
|
|
|
97523
98337
|
rules.command("ignore-tag <tag>").description("Skip a whole rule family by tag before linting (e.g. design)").option("-c, --cwd <cwd>", "working directory", process.cwd()).action((tag, _options, command) => rulesIgnoreTagAction(tag, command.optsWithGlobals()));
|
|
97524
98338
|
rules.command("unignore-tag <tag>").description("Stop ignoring a tag previously skipped via ignore-tag").option("-c, --cwd <cwd>", "working directory", process.cwd()).action((tag, _options, command) => rulesUnignoreTagAction(tag, command.optsWithGlobals()));
|
|
97525
98339
|
program.command("experimental-lsp", { hidden: false }).description("[experimental] run the React Doctor language server over stdio (for editors)").allowUnknownOption().action(() => {});
|
|
97526
|
-
program.command("experimental-tui [directory]", { hidden: true }).description("[experimental] interactive, scrollable scan report").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").option("--no-dead-code", "skip dead-code analysis").option("--no-score", "skip the score API, the share URL, and crash reporting").option("-p, --project <names>", "scan specific workspace projects (comma-separated, or *)").option("-y, --yes", "skip the project prompt and scan every discovered project").action(async (directory = ".", _localOptions, command) => {
|
|
98340
|
+
program.command("experimental-tui [directory]", { hidden: true }).description("[experimental] interactive, scrollable scan report").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").option("--no-dead-code", "skip dead-code analysis").option("--no-supply-chain", "skip the dependency supply-chain scan").option("--no-score", "skip the score API, the share URL, and crash reporting").option("-p, --project <names>", "scan specific workspace projects (comma-separated, or *)").option("-y, --yes", "skip the project prompt and scan every discovered project").action(async (directory = ".", _localOptions, command) => {
|
|
97527
98341
|
const options = command.optsWithGlobals();
|
|
97528
98342
|
const deadCode = options.deadCode === false ? false : void 0;
|
|
97529
98343
|
const noScore = options.score === false ? true : void 0;
|
|
98344
|
+
const supplyChain = options.supplyChain === false ? false : void 0;
|
|
97530
98345
|
const nodeMajorVersion = Number(process.versions.node.split(".")[0]);
|
|
97531
98346
|
if (process.stdout.isTTY !== true || process.stdin.isTTY !== true || isNonInteractiveEnvironment() || nodeMajorVersion < 22) {
|
|
97532
98347
|
await inspectAction(directory, {
|
|
97533
98348
|
deadCode,
|
|
97534
98349
|
score: options.score === false ? false : void 0,
|
|
98350
|
+
supplyChain,
|
|
97535
98351
|
project: options.project,
|
|
97536
98352
|
yes: options.yes,
|
|
97537
98353
|
blocking: options.blocking
|
|
@@ -97539,12 +98355,13 @@ program.command("experimental-tui [directory]", { hidden: true }).description("[
|
|
|
97539
98355
|
return;
|
|
97540
98356
|
}
|
|
97541
98357
|
recordCount(METRIC.cliInvoked, 1, { command: "experimental-tui" });
|
|
97542
|
-
const { runScanApp } = await import("./run-scan-app-
|
|
98358
|
+
const { runScanApp } = await import("./run-scan-app-DHRvqfkX.js");
|
|
97543
98359
|
const { shouldFail } = await runScanApp({
|
|
97544
98360
|
directory,
|
|
97545
98361
|
options: {
|
|
97546
98362
|
deadCode,
|
|
97547
|
-
noScore
|
|
98363
|
+
noScore,
|
|
98364
|
+
supplyChain
|
|
97548
98365
|
},
|
|
97549
98366
|
projectFlag: options.project,
|
|
97550
98367
|
skipPrompts: options.yes ?? false,
|
|
@@ -97578,7 +98395,7 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
97578
98395
|
handleError(error, { sentryEventId });
|
|
97579
98396
|
});
|
|
97580
98397
|
//#endregion
|
|
97581
|
-
export { toForwardSlashes as A,
|
|
98398
|
+
export { toForwardSlashes as A, getCategoryImpact as B, buildRulePriorityMap as C, resolveBlockingLevel as D, formatLearnMoreLine as E, TUI_REPORT_DETAIL_WIDTH_FRACTION as F, runPromise as G, mapWithConcurrency as H, isCiEnvironment as I, succeed$3 as J, sync as K, DIAGNOSTIC_CATEGORY_BUCKETS as L, isUnicodeSupported as M, METRIC as N, isReactDoctorWorkflowInstalled as O, TUI_REPORT_COMPACT_MAX_ROWS as P, Progress as R, hasLintHardFailure as S, formatFixRecipeLine as T, mergeReactDoctorConfigs as U, highlighter as V, resolveScanTarget as W, canAnimateOnboarding as _, resolveCliInspectOptions as a, buildCodeFrame as b, detectLaunchableAgents as c, launchCliAgent as d, isShareOptedOut as f, doctorFace as g, easeOutCubic as h, selectProjects as i, findNearestPackageDirectory as j, recordCount as k, CLI_AGENT_BINARIES as l, printFooter as m, shouldFailScanGate as n, countUniqueScannedFiles as o, createInvocationInspect as p, void_ as q, discoverWorkspacePackages as r, setUpGitHubActions as s, exitGracefully as t, copyToClipboard as u, computeProjectedScore as v, buildSortedRuleGroups as w, buildNoScoreMessage as x, formatElapsedTime as y, Reporter as z };
|
|
97582
98399
|
|
|
97583
98400
|
//# sourceMappingURL=cli.js.map
|
|
97584
|
-
//# debugId=
|
|
98401
|
+
//# debugId=1a34c548-5d3e-559c-8a3a-8a869ca2847a
|