react-doctor 0.9.3-dev.3a93a34 → 0.9.3-dev.3acb41b
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/dist/cli.js +794 -223
- package/dist/index.d.ts +9 -2
- package/dist/index.js +478 -146
- package/dist/lsp.js +487 -151
- package/dist/{run-scan-app-DtYeufgr.js → run-scan-app-QbtG43NL.js} +243 -112
- package/package.json +2 -2
package/dist/index.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]="76d09448-ef0d-52d4-8c22-005bcb8715c5")}catch(e){}}();
|
|
3
3
|
import { i as __toESM$1, r as __require, t as __commonJSMin$1 } from "./chunk-ChKA3wi6.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
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";
|
|
@@ -10,7 +10,7 @@ import fs from "node:fs";
|
|
|
10
10
|
import * as Path from "node:path";
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
import * as NodeChildProcess from "node:child_process";
|
|
13
|
-
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
13
|
+
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
|
|
14
14
|
import { ResolverFactory } from "oxc-resolver";
|
|
15
15
|
import ts from "typescript";
|
|
16
16
|
import * as NodeUrl from "node:url";
|
|
@@ -3621,7 +3621,7 @@ const flatMap$5 = /* @__PURE__ */ dual(2, (self, f) => isNone(self) ? none() : f
|
|
|
3621
3621
|
* @category filtering
|
|
3622
3622
|
* @since 2.0.0
|
|
3623
3623
|
*/
|
|
3624
|
-
const filter = /* @__PURE__ */ dual(2, (self, predicate) => isNone(self) ? none() : predicate(self.value) ? some(self.value) : none());
|
|
3624
|
+
const filter$1 = /* @__PURE__ */ dual(2, (self, predicate) => isNone(self) ? none() : predicate(self.value) ? some(self.value) : none());
|
|
3625
3625
|
//#endregion
|
|
3626
3626
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.70/node_modules/effect/dist/Result.js
|
|
3627
3627
|
/**
|
|
@@ -15556,7 +15556,7 @@ function transformOptional(f) {
|
|
|
15556
15556
|
*/
|
|
15557
15557
|
function withDefault$1(defaultValue) {
|
|
15558
15558
|
return new Getter((o) => {
|
|
15559
|
-
const filtered = filter(o, isNotUndefined);
|
|
15559
|
+
const filtered = filter$1(o, isNotUndefined);
|
|
15560
15560
|
return isSome(filtered) ? succeed$2(filtered) : mapEager(defaultValue, some);
|
|
15561
15561
|
});
|
|
15562
15562
|
}
|
|
@@ -19404,6 +19404,10 @@ var JsonReportProjectEntryV3 = class extends Class("JsonReportProjectEntryV3")({
|
|
|
19404
19404
|
scannedFileCount: optional(Number$1),
|
|
19405
19405
|
elapsedMilliseconds: Number$1
|
|
19406
19406
|
}) {};
|
|
19407
|
+
var JsonReportSkippedProject = class extends Class("JsonReportSkippedProject")({
|
|
19408
|
+
directory: String$1,
|
|
19409
|
+
reason: Literal("max-duration")
|
|
19410
|
+
}) {};
|
|
19407
19411
|
/** Original full, diff, and staged report contract. */
|
|
19408
19412
|
var JsonReportV1 = class extends Class("JsonReportV1")({
|
|
19409
19413
|
schemaVersion: Literal(1),
|
|
@@ -19432,6 +19436,7 @@ var JsonReportV1 = class extends Class("JsonReportV1")({
|
|
|
19432
19436
|
reactDetected: optional(Boolean$1),
|
|
19433
19437
|
diff: NullOr(JsonReportDiffInfo),
|
|
19434
19438
|
projects: ArraySchema(JsonReportProjectEntry),
|
|
19439
|
+
skippedProjects: optional(ArraySchema(JsonReportSkippedProject)),
|
|
19435
19440
|
diagnostics: ArraySchema(Diagnostic),
|
|
19436
19441
|
summary: JsonReportSummary,
|
|
19437
19442
|
elapsedMilliseconds: Number$1,
|
|
@@ -19460,6 +19465,7 @@ var JsonReportV2 = class extends Class("JsonReportV2")({
|
|
|
19460
19465
|
diff: NullOr(JsonReportDiffInfo),
|
|
19461
19466
|
baseline: JsonReportBaseline,
|
|
19462
19467
|
projects: ArraySchema(JsonReportProjectEntry),
|
|
19468
|
+
skippedProjects: optional(ArraySchema(JsonReportSkippedProject)),
|
|
19463
19469
|
diagnostics: ArraySchema(Diagnostic),
|
|
19464
19470
|
summary: JsonReportSummary,
|
|
19465
19471
|
elapsedMilliseconds: Number$1,
|
|
@@ -19476,6 +19482,7 @@ var JsonReportV3 = class extends Class("JsonReportV3")({
|
|
|
19476
19482
|
diff: NullOr(JsonReportDiffInfo),
|
|
19477
19483
|
baseline: optional(JsonReportBaseline),
|
|
19478
19484
|
projects: ArraySchema(JsonReportProjectEntryV3),
|
|
19485
|
+
skippedProjects: optional(ArraySchema(JsonReportSkippedProject)),
|
|
19479
19486
|
diagnostics: ArraySchema(JsonReportDiagnosticV3),
|
|
19480
19487
|
summary: JsonReportSummary,
|
|
19481
19488
|
elapsedMilliseconds: Number$1,
|
|
@@ -53458,6 +53465,47 @@ const flattenArray = (self) => transformPull$1(self, (pull) => {
|
|
|
53458
53465
|
}));
|
|
53459
53466
|
});
|
|
53460
53467
|
/**
|
|
53468
|
+
* Filters arrays of elements emitted by a channel, applying the filter
|
|
53469
|
+
* to each element within the arrays and only emitting non-empty filtered arrays.
|
|
53470
|
+
*
|
|
53471
|
+
* **Example** (Filtering array output)
|
|
53472
|
+
*
|
|
53473
|
+
* ```ts
|
|
53474
|
+
* import { Array, Channel } from "effect"
|
|
53475
|
+
*
|
|
53476
|
+
* const nonEmptyArrayPredicate = Array.isReadonlyArrayNonEmpty
|
|
53477
|
+
*
|
|
53478
|
+
* // Create a channel that outputs arrays of mixed data
|
|
53479
|
+
* const arrayChannel = Channel.fromIterable([
|
|
53480
|
+
* Array.make(1, 2, 3, 4, 5),
|
|
53481
|
+
* Array.make(6, 7, 8, 9, 10),
|
|
53482
|
+
* Array.make(11, 12, 13, 14, 15)
|
|
53483
|
+
* ]).pipe(Channel.filter(nonEmptyArrayPredicate))
|
|
53484
|
+
*
|
|
53485
|
+
* // Filter arrays to keep only even numbers
|
|
53486
|
+
* const evenArraysChannel = Channel.filterArray(arrayChannel, (n) => n % 2 === 0)
|
|
53487
|
+
* // Outputs: [2, 4], [6, 8, 10], [12, 14]
|
|
53488
|
+
* // Note: Only non-empty filtered arrays are emitted
|
|
53489
|
+
*
|
|
53490
|
+
* // Arrays that would become empty after filtering are discarded entirely
|
|
53491
|
+
* const oddChannel = Channel.fromIterable([
|
|
53492
|
+
* Array.make(1, 3, 5),
|
|
53493
|
+
* Array.make(2, 4),
|
|
53494
|
+
* Array.make(7, 9)
|
|
53495
|
+
* ]).pipe(Channel.filter(nonEmptyArrayPredicate))
|
|
53496
|
+
* const filteredOddChannel = Channel.filterArray(oddChannel, (n) => n % 2 === 0)
|
|
53497
|
+
* // Outputs: [2, 4] (the arrays [1,3,5] and [7,9] are discarded)
|
|
53498
|
+
* ```
|
|
53499
|
+
*
|
|
53500
|
+
* @category filtering
|
|
53501
|
+
* @since 4.0.0
|
|
53502
|
+
*/
|
|
53503
|
+
const filterArray = /* @__PURE__ */ dual(2, (self, predicate) => transformPull$1(self, (pull) => succeed$2(flatMap$2(pull, function loop(arr) {
|
|
53504
|
+
const passes = [];
|
|
53505
|
+
for (let i = 0; i < arr.length; i++) if (predicate(arr[i])) passes.push(arr[i]);
|
|
53506
|
+
return isReadonlyArrayNonEmpty(passes) ? succeed$2(passes) : flatMap$2(pull, loop);
|
|
53507
|
+
}))));
|
|
53508
|
+
/**
|
|
53461
53509
|
* Filters and maps each element inside emitted non-empty arrays using a
|
|
53462
53510
|
* `Filter`.
|
|
53463
53511
|
*
|
|
@@ -55095,6 +55143,30 @@ const concat = /* @__PURE__ */ dual(2, (self, that) => flatten(fromArray([self,
|
|
|
55095
55143
|
*/
|
|
55096
55144
|
const merge$1 = /* @__PURE__ */ dual((args) => isStream(args[0]) && isStream(args[1]), (self, that, options) => fromChannel(merge$2(toChannel(self), toChannel(that), options)));
|
|
55097
55145
|
/**
|
|
55146
|
+
* Filters a stream to the elements that satisfy a predicate.
|
|
55147
|
+
*
|
|
55148
|
+
* **Example** (Filtering stream values)
|
|
55149
|
+
*
|
|
55150
|
+
* ```ts
|
|
55151
|
+
* import { Console, Effect, Stream } from "effect"
|
|
55152
|
+
*
|
|
55153
|
+
* const program = Effect.gen(function*() {
|
|
55154
|
+
* const stream = Stream.make(1, 2, 3, 4).pipe(
|
|
55155
|
+
* Stream.filter((n) => n % 2 === 0)
|
|
55156
|
+
* )
|
|
55157
|
+
* const values = yield* Stream.runCollect(stream)
|
|
55158
|
+
* yield* Console.log(values)
|
|
55159
|
+
* })
|
|
55160
|
+
*
|
|
55161
|
+
* Effect.runPromise(program)
|
|
55162
|
+
* // Output: [ 2, 4 ]
|
|
55163
|
+
* ```
|
|
55164
|
+
*
|
|
55165
|
+
* @category filtering
|
|
55166
|
+
* @since 2.0.0
|
|
55167
|
+
*/
|
|
55168
|
+
const filter = /* @__PURE__ */ dual(2, (self, predicate) => fromChannel(filterArray(toChannel(self), predicate)));
|
|
55169
|
+
/**
|
|
55098
55170
|
* Filters and maps stream elements in one pass using a `Filter`.
|
|
55099
55171
|
*
|
|
55100
55172
|
* @category filtering
|
|
@@ -61878,6 +61950,7 @@ const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
|
|
|
61878
61950
|
const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
|
|
61879
61951
|
const MINIFIED_SNIFF_BYTES = 65536;
|
|
61880
61952
|
const GIT_LS_FILES_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
61953
|
+
const GIT_CHECK_ATTR_MAX_BUFFER_BYTES = GIT_LS_FILES_MAX_BUFFER_BYTES;
|
|
61881
61954
|
const SCANNED_DOT_DIRECTORIES = new Set([".dumi", ".storybook"]);
|
|
61882
61955
|
const IGNORED_DIRECTORIES = new Set([
|
|
61883
61956
|
".angular",
|
|
@@ -62163,13 +62236,9 @@ const DEAD_CODE_WORKER_TIMEOUT_MS = 12e4;
|
|
|
62163
62236
|
const OXLINT_SPLIT_TOTAL_BUDGET_MS = 18e4;
|
|
62164
62237
|
const ABORT_EXIT_CODES = new Set([134, 3221226505]);
|
|
62165
62238
|
const OXLINT_OOM_RESCUE_BUDGET_MS = 6e4;
|
|
62166
|
-
const DEAD_CODE_PHASE_TIMEOUT_MS = 15e4;
|
|
62167
|
-
const LINT_PHASE_TIMEOUT_MS = 3e5;
|
|
62168
|
-
const SCAN_TOTAL_DEADLINE_MS = 9e5;
|
|
62169
62239
|
const DEAD_CODE_WORKER_MAX_OLD_SPACE_MB = 8192;
|
|
62170
62240
|
const DEAD_CODE_WORKER_MEM_BUDGET_BYTES = 2 * 1024 * 1024 * 1024;
|
|
62171
62241
|
const DEAD_CODE_TIMEOUT_CEILING_MS = 6e5;
|
|
62172
|
-
const DEAD_CODE_PHASE_TIMEOUT_OVER_WORKER_MS = 3e4;
|
|
62173
62242
|
const DEAD_CODE_OVERLAP_PARSE_SHARE = .4;
|
|
62174
62243
|
const RECOMMENDED_PNPM_MINIMUM_RELEASE_AGE_MINUTES = 10080;
|
|
62175
62244
|
const REACT_SERVER_DOM_PACKAGES = [
|
|
@@ -62264,6 +62333,66 @@ const isPlainObject = (value) => {
|
|
|
62264
62333
|
const prototype = Object.getPrototypeOf(value);
|
|
62265
62334
|
return prototype === null || prototype === Object.prototype;
|
|
62266
62335
|
};
|
|
62336
|
+
const LINGUIST_ATTRIBUTES = ["linguist-generated", "linguist-vendored"];
|
|
62337
|
+
const DISABLED_ATTRIBUTE_VALUES = new Set([
|
|
62338
|
+
"unspecified",
|
|
62339
|
+
"unset",
|
|
62340
|
+
"false",
|
|
62341
|
+
"0",
|
|
62342
|
+
"off",
|
|
62343
|
+
"no"
|
|
62344
|
+
]);
|
|
62345
|
+
const buildInput = (relativePaths) => `${relativePaths.join("\0")}\0`;
|
|
62346
|
+
const parseIgnoredPaths = (output) => {
|
|
62347
|
+
const ignoredPaths = /* @__PURE__ */ new Set();
|
|
62348
|
+
const fields = output.split("\0");
|
|
62349
|
+
for (let fieldIndex = 0; fieldIndex + 2 < fields.length; fieldIndex += 3) {
|
|
62350
|
+
const filePath = fields[fieldIndex];
|
|
62351
|
+
const value = fields[fieldIndex + 2]?.toLowerCase();
|
|
62352
|
+
if (filePath && value && !DISABLED_ATTRIBUTE_VALUES.has(value)) ignoredPaths.add(filePath);
|
|
62353
|
+
}
|
|
62354
|
+
return ignoredPaths;
|
|
62355
|
+
};
|
|
62356
|
+
const collectGitLinguistIgnoredPaths = (rootDirectory, relativePaths) => {
|
|
62357
|
+
if (relativePaths.length === 0) return /* @__PURE__ */ new Set();
|
|
62358
|
+
const result = spawnSync("git", [
|
|
62359
|
+
"check-attr",
|
|
62360
|
+
"-z",
|
|
62361
|
+
"--stdin",
|
|
62362
|
+
...LINGUIST_ATTRIBUTES
|
|
62363
|
+
], {
|
|
62364
|
+
cwd: rootDirectory,
|
|
62365
|
+
encoding: "utf-8",
|
|
62366
|
+
input: buildInput(relativePaths),
|
|
62367
|
+
maxBuffer: GIT_CHECK_ATTR_MAX_BUFFER_BYTES
|
|
62368
|
+
});
|
|
62369
|
+
if (result.error || result.status !== 0) return /* @__PURE__ */ new Set();
|
|
62370
|
+
return parseIgnoredPaths(result.stdout);
|
|
62371
|
+
};
|
|
62372
|
+
const collectGitLinguistIgnoredPathsCooperative = (rootDirectory, relativePaths, signal) => {
|
|
62373
|
+
if (relativePaths.length === 0) return Promise.resolve(/* @__PURE__ */ new Set());
|
|
62374
|
+
return new Promise((resolve, reject) => {
|
|
62375
|
+
signal?.throwIfAborted();
|
|
62376
|
+
execFile("git", [
|
|
62377
|
+
"check-attr",
|
|
62378
|
+
"-z",
|
|
62379
|
+
"--stdin",
|
|
62380
|
+
...LINGUIST_ATTRIBUTES
|
|
62381
|
+
], {
|
|
62382
|
+
cwd: rootDirectory,
|
|
62383
|
+
encoding: "utf-8",
|
|
62384
|
+
killSignal: "SIGKILL",
|
|
62385
|
+
maxBuffer: GIT_CHECK_ATTR_MAX_BUFFER_BYTES,
|
|
62386
|
+
signal
|
|
62387
|
+
}, (error, stdout) => {
|
|
62388
|
+
if (signal?.aborted) {
|
|
62389
|
+
reject(signal.reason);
|
|
62390
|
+
return;
|
|
62391
|
+
}
|
|
62392
|
+
resolve(error ? /* @__PURE__ */ new Set() : parseIgnoredPaths(stdout));
|
|
62393
|
+
}).stdin?.end(buildInput(relativePaths));
|
|
62394
|
+
});
|
|
62395
|
+
};
|
|
62267
62396
|
const lastSourceMappingUrl = (fileContent) => {
|
|
62268
62397
|
const lastReference = [...fileContent.matchAll(/\/\/# sourceMappingURL=(\S+)/g)].at(-1);
|
|
62269
62398
|
return lastReference ? lastReference[1] : null;
|
|
@@ -62368,6 +62497,9 @@ function* walkSourceTreeFiles(rootDirectory) {
|
|
|
62368
62497
|
}
|
|
62369
62498
|
}
|
|
62370
62499
|
}
|
|
62500
|
+
const yieldToEventLoop = () => new Promise((resolve) => {
|
|
62501
|
+
setImmediate(resolve);
|
|
62502
|
+
});
|
|
62371
62503
|
const collectSizedSourceFiles = (rootDirectory, relativePaths) => {
|
|
62372
62504
|
const entries = [];
|
|
62373
62505
|
for (const relativePath of relativePaths) {
|
|
@@ -62381,23 +62513,55 @@ const collectSizedSourceFiles = (rootDirectory, relativePaths) => {
|
|
|
62381
62513
|
}
|
|
62382
62514
|
return entries;
|
|
62383
62515
|
};
|
|
62384
|
-
const
|
|
62516
|
+
const collectSizedSourceFilesCooperative = async (rootDirectory, relativePaths, signal) => {
|
|
62517
|
+
const entries = [];
|
|
62518
|
+
let sliceStartedAt = performance.now();
|
|
62519
|
+
for (const relativePath of relativePaths) {
|
|
62520
|
+
signal?.throwIfAborted();
|
|
62521
|
+
const absolutePath = Path.resolve(rootDirectory, relativePath);
|
|
62522
|
+
const sizeBytes = statSourceFileSize(absolutePath);
|
|
62523
|
+
if (!isLargeMinifiedFile(absolutePath, sizeBytes)) entries.push({
|
|
62524
|
+
path: relativePath,
|
|
62525
|
+
sizeBytes: sizeBytes ?? 0
|
|
62526
|
+
});
|
|
62527
|
+
if (performance.now() - sliceStartedAt >= 12) {
|
|
62528
|
+
await yieldToEventLoop();
|
|
62529
|
+
sliceStartedAt = performance.now();
|
|
62530
|
+
}
|
|
62531
|
+
}
|
|
62532
|
+
return entries;
|
|
62533
|
+
};
|
|
62534
|
+
const parseGitSourceFilePaths = (output) => {
|
|
62535
|
+
const trackedPaths = /* @__PURE__ */ new Set();
|
|
62536
|
+
const untrackedPaths = [];
|
|
62537
|
+
for (const entry of output.split("\0")) {
|
|
62538
|
+
if (entry.length === 0) continue;
|
|
62539
|
+
const trackedPath = /^[0-7]{6} [0-9a-f]+ [0-3]\t([\s\S]+)$/.exec(entry)?.[1];
|
|
62540
|
+
if (trackedPath === void 0) untrackedPaths.push(entry);
|
|
62541
|
+
else trackedPaths.add(trackedPath);
|
|
62542
|
+
}
|
|
62543
|
+
return {
|
|
62544
|
+
trackedPaths: [...trackedPaths],
|
|
62545
|
+
untrackedPaths
|
|
62546
|
+
};
|
|
62547
|
+
};
|
|
62548
|
+
const listGitSourceFilePaths = (rootDirectory) => {
|
|
62385
62549
|
const result = spawnSync("git", [
|
|
62386
62550
|
"ls-files",
|
|
62387
62551
|
"-z",
|
|
62388
|
-
|
|
62552
|
+
"--stage",
|
|
62553
|
+
"--others",
|
|
62554
|
+
"--exclude-standard"
|
|
62389
62555
|
], {
|
|
62390
62556
|
cwd: rootDirectory,
|
|
62391
62557
|
encoding: "utf-8",
|
|
62392
62558
|
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES
|
|
62393
62559
|
});
|
|
62394
62560
|
if (result.error || result.status !== 0) return null;
|
|
62395
|
-
return result.stdout
|
|
62561
|
+
return parseGitSourceFilePaths(result.stdout);
|
|
62396
62562
|
};
|
|
62397
|
-
const
|
|
62398
|
-
const trackedPaths =
|
|
62399
|
-
const untrackedPaths = gitLsFiles(rootDirectory, ["--others", "--exclude-standard"]);
|
|
62400
|
-
if (trackedPaths === null || untrackedPaths === null) return null;
|
|
62563
|
+
const collectGitCandidateSourceFilePaths = (rootDirectory, paths) => {
|
|
62564
|
+
const { trackedPaths, untrackedPaths } = paths;
|
|
62401
62565
|
const emitDuplicateJsPaths = collectTypeScriptEmitDuplicateJsPaths({
|
|
62402
62566
|
trackedPaths: new Set(trackedPaths),
|
|
62403
62567
|
untrackedPaths,
|
|
@@ -62405,12 +62569,65 @@ const listSourceFilesViaGit = (rootDirectory) => {
|
|
|
62405
62569
|
});
|
|
62406
62570
|
return [...trackedPaths, ...untrackedPaths].filter((filePath) => isLintableSourceFile(filePath) && !hasIgnoredPathSegment(filePath) && !emitDuplicateJsPaths.has(filePath));
|
|
62407
62571
|
};
|
|
62572
|
+
const filterGitSourceFilePaths = (rootDirectory, paths) => {
|
|
62573
|
+
const candidatePaths = collectGitCandidateSourceFilePaths(rootDirectory, paths);
|
|
62574
|
+
const linguistIgnoredPaths = collectGitLinguistIgnoredPaths(rootDirectory, candidatePaths);
|
|
62575
|
+
return candidatePaths.filter((filePath) => !linguistIgnoredPaths.has(filePath));
|
|
62576
|
+
};
|
|
62577
|
+
const listSourceFilesViaGit = (rootDirectory) => {
|
|
62578
|
+
const paths = listGitSourceFilePaths(rootDirectory);
|
|
62579
|
+
return paths === null ? null : filterGitSourceFilePaths(rootDirectory, paths);
|
|
62580
|
+
};
|
|
62581
|
+
const listSourceFilesViaGitCooperative = async (rootDirectory, signal) => {
|
|
62582
|
+
const paths = await new Promise((resolve, reject) => {
|
|
62583
|
+
signal?.throwIfAborted();
|
|
62584
|
+
execFile("git", [
|
|
62585
|
+
"ls-files",
|
|
62586
|
+
"-z",
|
|
62587
|
+
"--stage",
|
|
62588
|
+
"--others",
|
|
62589
|
+
"--exclude-standard"
|
|
62590
|
+
], {
|
|
62591
|
+
cwd: rootDirectory,
|
|
62592
|
+
encoding: "utf-8",
|
|
62593
|
+
killSignal: "SIGKILL",
|
|
62594
|
+
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES,
|
|
62595
|
+
signal
|
|
62596
|
+
}, (error, stdout) => {
|
|
62597
|
+
if (signal?.aborted) {
|
|
62598
|
+
reject(signal.reason);
|
|
62599
|
+
return;
|
|
62600
|
+
}
|
|
62601
|
+
resolve(error ? null : parseGitSourceFilePaths(stdout));
|
|
62602
|
+
});
|
|
62603
|
+
});
|
|
62604
|
+
if (paths === null) return null;
|
|
62605
|
+
const candidatePaths = collectGitCandidateSourceFilePaths(rootDirectory, paths);
|
|
62606
|
+
const linguistIgnoredPaths = await collectGitLinguistIgnoredPathsCooperative(rootDirectory, candidatePaths, signal);
|
|
62607
|
+
return candidatePaths.filter((filePath) => !linguistIgnoredPaths.has(filePath));
|
|
62608
|
+
};
|
|
62408
62609
|
const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
62409
62610
|
const filePaths = [];
|
|
62410
62611
|
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) if (isLintableSourceFile(name)) filePaths.push(Path.relative(rootDirectory, absolutePath).replace(/\\/g, "/"));
|
|
62411
62612
|
return filePaths;
|
|
62412
62613
|
};
|
|
62413
|
-
const
|
|
62614
|
+
const listSourceFilesViaFilesystemCooperative = async (rootDirectory, signal) => {
|
|
62615
|
+
const filePaths = [];
|
|
62616
|
+
let sliceStartedAt = performance.now();
|
|
62617
|
+
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) {
|
|
62618
|
+
signal?.throwIfAborted();
|
|
62619
|
+
if (isLintableSourceFile(name)) filePaths.push(Path.relative(rootDirectory, absolutePath).replace(/\\/g, "/"));
|
|
62620
|
+
if (performance.now() - sliceStartedAt >= 12) {
|
|
62621
|
+
await yieldToEventLoop();
|
|
62622
|
+
sliceStartedAt = performance.now();
|
|
62623
|
+
}
|
|
62624
|
+
}
|
|
62625
|
+
return filePaths;
|
|
62626
|
+
};
|
|
62627
|
+
const listSourceFilePaths = (rootDirectory) => (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort();
|
|
62628
|
+
const listSourceFilePathsCooperative = async (rootDirectory, signal) => (await listSourceFilesViaGitCooperative(rootDirectory, signal) ?? await listSourceFilesViaFilesystemCooperative(rootDirectory, signal)).sort();
|
|
62629
|
+
const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, listSourceFilePaths(rootDirectory));
|
|
62630
|
+
const listSourceFilesCooperative = async (rootDirectory, signal) => (await collectSizedSourceFilesCooperative(rootDirectory, await listSourceFilePathsCooperative(rootDirectory, signal), signal)).map((entry) => entry.path);
|
|
62414
62631
|
const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
|
|
62415
62632
|
const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
|
|
62416
62633
|
const UTF8_BOM_CHARACTER = "";
|
|
@@ -64739,7 +64956,16 @@ const getBrowserslistProtectionRequirement = (directory) => {
|
|
|
64739
64956
|
if (!queries) return void 0;
|
|
64740
64957
|
let requirement;
|
|
64741
64958
|
let hasUnsupportedTarget = false;
|
|
64742
|
-
|
|
64959
|
+
const previousIgnoreOldData = process.env.BROWSERSLIST_IGNORE_OLD_DATA;
|
|
64960
|
+
let browserTargets = [];
|
|
64961
|
+
try {
|
|
64962
|
+
process.env.BROWSERSLIST_IGNORE_OLD_DATA = "true";
|
|
64963
|
+
browserTargets = (0, import_browserslist.default)(queries);
|
|
64964
|
+
} finally {
|
|
64965
|
+
if (previousIgnoreOldData === void 0) delete process.env.BROWSERSLIST_IGNORE_OLD_DATA;
|
|
64966
|
+
else process.env.BROWSERSLIST_IGNORE_OLD_DATA = previousIgnoreOldData;
|
|
64967
|
+
}
|
|
64968
|
+
for (const browserTarget of browserTargets) {
|
|
64743
64969
|
const browserRequirement = getBrowserProtectionRequirement(browserTarget);
|
|
64744
64970
|
if (browserRequirement === "unsupported") hasUnsupportedTarget = true;
|
|
64745
64971
|
if (browserRequirement === "noreferrer") requirement = "noreferrer";
|
|
@@ -64849,8 +65075,8 @@ const clearProjectCache = () => {
|
|
|
64849
65075
|
* framework-agnostic rules. Throws only when the directory has nothing
|
|
64850
65076
|
* to scan (no enclosing project and no source files of its own).
|
|
64851
65077
|
*/
|
|
64852
|
-
const discoverProjectWithoutPackageJson = (directory) => {
|
|
64853
|
-
const sourceFileCount = countSourceFiles(directory);
|
|
65078
|
+
const discoverProjectWithoutPackageJson = (directory, options) => {
|
|
65079
|
+
const sourceFileCount = options.sourceFileCount ?? countSourceFiles(directory);
|
|
64854
65080
|
const hasOwnTsConfig = NFS.existsSync(Path.join(directory, "tsconfig.json"));
|
|
64855
65081
|
const enclosingProjectRoot = findNearestAncestorPackageJson(directory);
|
|
64856
65082
|
const enclosingProject = enclosingProjectRoot !== null ? discoverProject(enclosingProjectRoot) : null;
|
|
@@ -64917,12 +65143,15 @@ const discoverProjectWithoutPackageJson = (directory) => {
|
|
|
64917
65143
|
sourceFileCount
|
|
64918
65144
|
};
|
|
64919
65145
|
};
|
|
64920
|
-
const discoverProject = (directory) => {
|
|
65146
|
+
const discoverProject = (directory, options = {}) => {
|
|
64921
65147
|
const cached = cachedProjectInfos.get(directory);
|
|
64922
|
-
if (cached !== void 0) return cached
|
|
65148
|
+
if (cached !== void 0) return options.sourceFileCount === void 0 ? cached : {
|
|
65149
|
+
...cached,
|
|
65150
|
+
sourceFileCount: options.sourceFileCount
|
|
65151
|
+
};
|
|
64923
65152
|
const packageJsonPath = Path.join(directory, "package.json");
|
|
64924
65153
|
if (!isFile(packageJsonPath)) {
|
|
64925
|
-
const synthesized = discoverProjectWithoutPackageJson(directory);
|
|
65154
|
+
const synthesized = discoverProjectWithoutPackageJson(directory, options);
|
|
64926
65155
|
cachedProjectInfos.set(directory, synthesized);
|
|
64927
65156
|
return synthesized;
|
|
64928
65157
|
}
|
|
@@ -64985,7 +65214,7 @@ const discoverProject = (directory) => {
|
|
|
64985
65214
|
const zodVersion = zod.version;
|
|
64986
65215
|
const projectName = packageJson.name ?? Path.basename(directory);
|
|
64987
65216
|
const hasTypeScript = NFS.existsSync(Path.join(directory, "tsconfig.json"));
|
|
64988
|
-
const sourceFileCount = countSourceFiles(directory);
|
|
65217
|
+
const sourceFileCount = options.sourceFileCount ?? countSourceFiles(directory);
|
|
64989
65218
|
const hasReactNativeWorkspace = framework === "expo" || framework === "react-native" || workspaceFacts.hasReactNativeAwarePackage;
|
|
64990
65219
|
const expoVersion = hasReactNativeWorkspace ? resolveCatalogBackedDependencyVersion({
|
|
64991
65220
|
rootDirectory: directory,
|
|
@@ -66367,7 +66596,8 @@ const readSystemFacts$1 = () => ({
|
|
|
66367
66596
|
/**
|
|
66368
66597
|
* Auto lint-worker count: the smaller of the (cgroup-CPU-aware) core count and
|
|
66369
66598
|
* the number of `PER_WORKER_MEM_BUDGET_BYTES` workers that fit in available
|
|
66370
|
-
* memory,
|
|
66599
|
+
* memory, and the measured automatic parallel-efficiency ceiling, then clamped
|
|
66600
|
+
* to `[MIN, HARD_MAX]` by `resolveScanConcurrency`.
|
|
66371
66601
|
*
|
|
66372
66602
|
* `os.availableParallelism()` already respects cgroup CPU quotas, so the core
|
|
66373
66603
|
* term needs no help. Available memory is `os.totalmem()` floored by the cgroup
|
|
@@ -66383,7 +66613,7 @@ const readSystemFacts$1 = () => ({
|
|
|
66383
66613
|
const resolveAutoScanConcurrency = (facts = readSystemFacts$1()) => {
|
|
66384
66614
|
const availableMemoryBytes = Math.min(facts.totalMemoryBytes, facts.cgroupMemoryLimitBytes ?? Number.POSITIVE_INFINITY);
|
|
66385
66615
|
const memoryBoundedWorkers = Math.floor(availableMemoryBytes / PER_WORKER_MEM_BUDGET_BYTES);
|
|
66386
|
-
return resolveScanConcurrency(Math.min(facts.availableCores, memoryBoundedWorkers));
|
|
66616
|
+
return resolveScanConcurrency(Math.min(facts.availableCores, memoryBoundedWorkers, 10));
|
|
66387
66617
|
};
|
|
66388
66618
|
const resolveLintBatchOrdering = () => {
|
|
66389
66619
|
return process.env["REACT_DOCTOR_LINT_BATCH_ORDERING"]?.trim().toLowerCase() === "arrival" ? "arrival" : "cost";
|
|
@@ -66396,24 +66626,22 @@ const resolveLintBatchOrdering = () => {
|
|
|
66396
66626
|
*/
|
|
66397
66627
|
var OxlintSpawnTimeoutMs = class extends Reference("react-doctor/OxlintSpawnTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_OXLINT_SPAWN_TIMEOUT_MS", OXLINT_SPAWN_TIMEOUT_MS) }) {};
|
|
66398
66628
|
/**
|
|
66399
|
-
* Effect-side cap on the lint phase.
|
|
66400
|
-
*
|
|
66629
|
+
* Optional Effect-side cap on the lint phase. Unbounded unless explicitly
|
|
66630
|
+
* configured through the env var or a test layer.
|
|
66401
66631
|
* Tests override via `Layer.succeed(LintPhaseTimeoutMs, ...)`.
|
|
66402
66632
|
*/
|
|
66403
|
-
var LintPhaseTimeoutMs = class extends Reference("react-doctor/LintPhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_LINT_PHASE_TIMEOUT_MS",
|
|
66633
|
+
var LintPhaseTimeoutMs = class extends Reference("react-doctor/LintPhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_LINT_PHASE_TIMEOUT_MS", null) }) {};
|
|
66404
66634
|
/**
|
|
66405
|
-
* Effect-side cap on the dead-code phase
|
|
66406
|
-
*
|
|
66407
|
-
* type-heavy projects; tests override via
|
|
66635
|
+
* Optional Effect-side cap on the dead-code phase. Unbounded unless explicitly
|
|
66636
|
+
* configured through the env var or a test layer. Tests override via
|
|
66408
66637
|
* `Layer.succeed(DeadCodePhaseTimeoutMs, ...)`.
|
|
66409
66638
|
*/
|
|
66410
|
-
var DeadCodePhaseTimeoutMs = class extends Reference("react-doctor/DeadCodePhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_DEAD_CODE_PHASE_TIMEOUT_MS",
|
|
66639
|
+
var DeadCodePhaseTimeoutMs = class extends Reference("react-doctor/DeadCodePhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_DEAD_CODE_PHASE_TIMEOUT_MS", null) }) {};
|
|
66411
66640
|
/**
|
|
66412
|
-
*
|
|
66413
|
-
*
|
|
66414
|
-
* large repos; tests override via `Layer.succeed(ScanDeadlineMs, ...)`.
|
|
66641
|
+
* Optional overall scan deadline. Unbounded unless explicitly configured
|
|
66642
|
+
* through the env var or a test layer.
|
|
66415
66643
|
*/
|
|
66416
|
-
var ScanDeadlineMs = class extends Reference("react-doctor/ScanDeadlineMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_SCAN_DEADLINE_MS",
|
|
66644
|
+
var ScanDeadlineMs = class extends Reference("react-doctor/ScanDeadlineMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_SCAN_DEADLINE_MS", null) }) {};
|
|
66417
66645
|
/**
|
|
66418
66646
|
* Wall-clock budget for the supply-chain check when it runs on a background
|
|
66419
66647
|
* fiber overlapping the lint pass. Reads from the env var on startup so the
|
|
@@ -66486,14 +66714,14 @@ var DeadCodeOverlap = class extends Reference("react-doctor/DeadCodeOverlap", {
|
|
|
66486
66714
|
/**
|
|
66487
66715
|
* How the full-scan lint pass plans its file batches. `"cost"` (the default)
|
|
66488
66716
|
* builds size-balanced LPT batches (`planLintBatches`): the same mandatory
|
|
66489
|
-
* batch count as greedy chunking
|
|
66490
|
-
*
|
|
66717
|
+
* batch count as greedy chunking, but every batch gets an even share of files
|
|
66718
|
+
* AND bytes, so no full chunk is a straggler while
|
|
66491
66719
|
* the remainder-batch worker idles — and the heavy files are SPREAD across
|
|
66492
66720
|
* batches, the precondition the old sort-desc-then-chunk-100 `cost` mode
|
|
66493
66721
|
* lacked (it packed the heaviest files into one wave-1 straggler batch,
|
|
66494
66722
|
* measurably regressing size-skewed repos, which is why it never earned the
|
|
66495
66723
|
* default). `"arrival"` (`REACT_DOCTOR_LINT_BATCH_ORDERING=arrival`) is the
|
|
66496
|
-
* rollback hatch to plain greedy
|
|
66724
|
+
* rollback hatch to plain greedy fixed-size chunking in discovery order. Tests
|
|
66497
66725
|
* override via `Layer.succeed(LintBatchOrdering, ...)`. Diff / staged scans
|
|
66498
66726
|
* never reach this — they pass user-scoped `includePaths` that skip discovery
|
|
66499
66727
|
* and stay in arrival order; only the full-scan branch reads it.
|
|
@@ -67031,6 +67259,10 @@ const dedupeRelatedDiagnostics = (diagnostics) => {
|
|
|
67031
67259
|
}
|
|
67032
67260
|
return uniqueDiagnostics;
|
|
67033
67261
|
};
|
|
67262
|
+
const isPathInsideDirectory = (childAbsolutePath, parentAbsolutePath) => {
|
|
67263
|
+
const relativePath = Path.relative(parentAbsolutePath, childAbsolutePath);
|
|
67264
|
+
return Boolean(relativePath) && !relativePath.startsWith("..") && !Path.isAbsolute(relativePath);
|
|
67265
|
+
};
|
|
67034
67266
|
const compareStrings = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
67035
67267
|
const sortDiagnosticsStable = (diagnostics) => [...diagnostics].sort((left, right) => compareStrings(left.filePath, right.filePath) || left.line - right.line || left.column - right.column || compareStrings(left.plugin, right.plugin) || compareStrings(left.rule, right.rule) || compareStrings(left.severity, right.severity) || compareStrings(left.message, right.message));
|
|
67036
67268
|
const getDirectDependencyNames = (packageJson) => new Set([...Object.keys(packageJson.dependencies ?? {}), ...Object.keys(packageJson.devDependencies ?? {})]);
|
|
@@ -68607,7 +68839,7 @@ const readScannedFile = (candidate) => {
|
|
|
68607
68839
|
return null;
|
|
68608
68840
|
}
|
|
68609
68841
|
};
|
|
68610
|
-
function* collectSecurityScanFiles(rootDirectory) {
|
|
68842
|
+
function* collectSecurityScanFiles(rootDirectory, excludedDirectories = /* @__PURE__ */ new Set()) {
|
|
68611
68843
|
const priorityCandidates = [];
|
|
68612
68844
|
const artifactCandidates = [];
|
|
68613
68845
|
const otherCandidates = [];
|
|
@@ -68622,7 +68854,7 @@ function* collectSecurityScanFiles(rootDirectory) {
|
|
|
68622
68854
|
for (const entry of readDirectoryEntries(current.absolutePath)) {
|
|
68623
68855
|
const absolutePath = Path.join(current.absolutePath, entry.name);
|
|
68624
68856
|
if (entry.isDirectory()) {
|
|
68625
|
-
if (!SKIPPED_DIRECTORY_NAMES.has(entry.name)) stack.push({
|
|
68857
|
+
if (!SKIPPED_DIRECTORY_NAMES.has(entry.name) && !excludedDirectories.has(Path.resolve(absolutePath))) stack.push({
|
|
68626
68858
|
absolutePath,
|
|
68627
68859
|
depth: current.depth + 1
|
|
68628
68860
|
});
|
|
@@ -68803,10 +69035,8 @@ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhe
|
|
|
68803
69035
|
}
|
|
68804
69036
|
return true;
|
|
68805
69037
|
};
|
|
69038
|
+
const remainingDeadlineBudgetMs = (deadlineEpochMs) => Math.max(deadlineEpochMs - Date.now(), 0);
|
|
68806
69039
|
const shouldEnableRuleByDefaultStatus = (options) => options.defaultEnabled !== false || options.hasExplicitOverride === true || options.includeTagDefaults && options.hasIncludedTags;
|
|
68807
|
-
const yieldToEventLoop = () => new Promise((resolve) => {
|
|
68808
|
-
setImmediate(resolve);
|
|
68809
|
-
});
|
|
68810
69040
|
const createSecurityScanSession = (rootDirectory, options) => {
|
|
68811
69041
|
const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
|
|
68812
69042
|
const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
|
|
@@ -68859,19 +69089,35 @@ const createSecurityScanSession = (rootDirectory, options) => {
|
|
|
68859
69089
|
};
|
|
68860
69090
|
};
|
|
68861
69091
|
const checkSecurityScanCooperative = async (rootDirectory, options = {}) => {
|
|
69092
|
+
const throwIfScanAborted = () => {
|
|
69093
|
+
options.signal?.throwIfAborted();
|
|
69094
|
+
};
|
|
69095
|
+
const didReachDeadline = () => {
|
|
69096
|
+
const hasDeadlineElapsed = options.deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(options.deadlineEpochMs) === 0;
|
|
69097
|
+
if (hasDeadlineElapsed) options.onDeadlineExceeded?.();
|
|
69098
|
+
return hasDeadlineElapsed;
|
|
69099
|
+
};
|
|
69100
|
+
throwIfScanAborted();
|
|
68862
69101
|
const session = createSecurityScanSession(rootDirectory, options);
|
|
68863
69102
|
if (session === null) return [];
|
|
69103
|
+
if (didReachDeadline()) return [];
|
|
68864
69104
|
let sliceStartedAt = performance.now();
|
|
68865
|
-
for (const file of collectSecurityScanFiles(rootDirectory)) {
|
|
69105
|
+
for (const file of collectSecurityScanFiles(rootDirectory, options.excludedDirectories)) {
|
|
69106
|
+
throwIfScanAborted();
|
|
69107
|
+
if (didReachDeadline()) return session.diagnostics;
|
|
68866
69108
|
if (file === null) {
|
|
68867
69109
|
if (performance.now() - sliceStartedAt >= 12) {
|
|
68868
69110
|
await yieldToEventLoop();
|
|
69111
|
+
throwIfScanAborted();
|
|
69112
|
+
if (didReachDeadline()) return session.diagnostics;
|
|
68869
69113
|
sliceStartedAt = performance.now();
|
|
68870
69114
|
}
|
|
68871
69115
|
continue;
|
|
68872
69116
|
}
|
|
68873
69117
|
for (const _ruleStep of session.scanFileByRule(file)) if (performance.now() - sliceStartedAt >= 12) {
|
|
68874
69118
|
await yieldToEventLoop();
|
|
69119
|
+
throwIfScanAborted();
|
|
69120
|
+
if (didReachDeadline()) return session.diagnostics;
|
|
68875
69121
|
sliceStartedAt = performance.now();
|
|
68876
69122
|
}
|
|
68877
69123
|
}
|
|
@@ -69785,7 +70031,6 @@ const isDiagnosticOnSurface = (diagnostic, surface, config) => {
|
|
|
69785
70031
|
return true;
|
|
69786
70032
|
};
|
|
69787
70033
|
const filterDiagnosticsForSurface = (diagnostics, surface, config) => diagnostics.filter((diagnostic) => isDiagnosticOnSurface(diagnostic, surface, config));
|
|
69788
|
-
const remainingDeadlineBudgetMs = (deadlineEpochMs) => Math.max(deadlineEpochMs - Date.now(), 0);
|
|
69789
70034
|
/**
|
|
69790
70035
|
* Budget for the dead-code phase, scaled to the work. deslop's graph build is
|
|
69791
70036
|
* CPU-bound and roughly linear in file count, so a fixed 120s cap is too tight
|
|
@@ -69793,25 +70038,28 @@ const remainingDeadlineBudgetMs = (deadlineEpochMs) => Math.max(deadlineEpochMs
|
|
|
69793
70038
|
* tipped over by any concurrent load — silently dropping every dead-code
|
|
69794
70039
|
* finding. Scaling the budget with file count (and inversely with the core
|
|
69795
70040
|
* share when overlapped) lets the pass complete, while the ceiling still
|
|
69796
|
-
* reclaims a genuinely wedged worker.
|
|
69797
|
-
* and the Effect-side phase backstop that sits a margin above it.
|
|
70041
|
+
* reclaims a genuinely wedged worker.
|
|
69798
70042
|
*/
|
|
69799
70043
|
const resolveDeadCodeTimeout = (input) => {
|
|
69800
70044
|
const coreShareFactor = Math.max(1, input.fullConcurrency / Math.max(1, input.deadCodeConcurrency));
|
|
69801
|
-
|
|
69802
|
-
return {
|
|
69803
|
-
workerTimeoutMs,
|
|
69804
|
-
phaseTimeoutMs: workerTimeoutMs + DEAD_CODE_PHASE_TIMEOUT_OVER_WORKER_MS
|
|
69805
|
-
};
|
|
70045
|
+
return { workerTimeoutMs: Math.min(DEAD_CODE_TIMEOUT_CEILING_MS, Math.max(DEAD_CODE_WORKER_TIMEOUT_MS, Math.ceil(input.sourceFileCount * 30 * coreShareFactor))) };
|
|
69806
70046
|
};
|
|
69807
|
-
const resolveLintIncludePaths = (rootDirectory, userConfig) => {
|
|
70047
|
+
const resolveLintIncludePaths = (rootDirectory, userConfig, sourceFiles) => {
|
|
69808
70048
|
if (!Array.isArray(userConfig?.ignore?.files) || userConfig.ignore.files.length === 0) return;
|
|
69809
70049
|
const ignoredPatterns = compileIgnoredFilePatterns(userConfig);
|
|
69810
|
-
return listSourceFiles(rootDirectory).filter((filePath) => {
|
|
70050
|
+
return (sourceFiles ?? listSourceFiles(rootDirectory)).filter((filePath) => {
|
|
69811
70051
|
if (!isLintableSourceFile(filePath)) return false;
|
|
69812
70052
|
return !isFileIgnoredByPatterns(filePath, rootDirectory, ignoredPatterns);
|
|
69813
70053
|
});
|
|
69814
70054
|
};
|
|
70055
|
+
const filterPathsOutsideDirectories = (input) => {
|
|
70056
|
+
const excludedPrefixes = input.excludedDirectories.map((excludedDirectory) => Path.resolve(excludedDirectory)).filter((excludedDirectory) => isPathInsideDirectory(excludedDirectory, input.rootDirectory)).map((excludedDirectory) => Path.relative(input.rootDirectory, excludedDirectory).replaceAll("\\", "/")).sort((left, right) => left.length - right.length).filter((candidatePrefix, index, prefixes) => !prefixes.slice(0, index).some((prefix) => candidatePrefix.startsWith(`${prefix}/`)));
|
|
70057
|
+
if (excludedPrefixes.length === 0) return [...input.relativePaths];
|
|
70058
|
+
return input.relativePaths.filter((relativePath) => {
|
|
70059
|
+
const normalizedRelativePath = relativePath.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
70060
|
+
return !excludedPrefixes.some((excludedPrefix) => normalizedRelativePath === excludedPrefix || normalizedRelativePath.startsWith(`${excludedPrefix}/`));
|
|
70061
|
+
});
|
|
70062
|
+
};
|
|
69815
70063
|
var Config = class Config extends Service()("react-doctor/Config") {
|
|
69816
70064
|
static layerNode = effect(Config, gen(function* () {
|
|
69817
70065
|
const cache = yield* make$3({
|
|
@@ -69873,6 +70121,7 @@ var Files = class Files extends Service()("react-doctor/Files") {
|
|
|
69873
70121
|
static layerNode = succeed$3(Files, Files.of({
|
|
69874
70122
|
readLines: (input) => sync(() => createNodeReadFileLinesSync(input.rootDirectory)(input.filePath)),
|
|
69875
70123
|
listSourceFiles: (rootDirectory) => sync(() => listSourceFiles(rootDirectory)),
|
|
70124
|
+
listSourceFilesCooperative: (input) => promise(() => listSourceFilesCooperative(input.rootDirectory, input.signal)),
|
|
69876
70125
|
isFile: (filePath) => sync(() => isFile(filePath)),
|
|
69877
70126
|
isDirectory: (filePath) => sync(() => isDirectory(filePath))
|
|
69878
70127
|
}));
|
|
@@ -69899,6 +70148,16 @@ var Files = class Files extends Service()("react-doctor/Files") {
|
|
|
69899
70148
|
}
|
|
69900
70149
|
return files;
|
|
69901
70150
|
}),
|
|
70151
|
+
listSourceFilesCooperative: (input) => sync(() => {
|
|
70152
|
+
const rootDirectory = input.rootDirectory;
|
|
70153
|
+
const prefix = rootDirectory.endsWith("/") ? rootDirectory : `${rootDirectory}/`;
|
|
70154
|
+
const files = [];
|
|
70155
|
+
for (const absolute of tree.keys()) {
|
|
70156
|
+
if (!absolute.startsWith(prefix)) continue;
|
|
70157
|
+
files.push(absolute.slice(prefix.length));
|
|
70158
|
+
}
|
|
70159
|
+
return files;
|
|
70160
|
+
}),
|
|
69902
70161
|
isFile: (filePath) => sync(() => tree.has(filePath)),
|
|
69903
70162
|
isDirectory: (filePath) => sync(() => {
|
|
69904
70163
|
const prefix = filePath.endsWith("/") ? filePath : `${filePath}/`;
|
|
@@ -70474,7 +70733,7 @@ const batchIncludePaths = (baseArgs, includePaths) => {
|
|
|
70474
70733
|
for (const filePath of includePaths) {
|
|
70475
70734
|
const entryLength = filePath.length + 1;
|
|
70476
70735
|
const exceedsArgLength = currentBatch.length > 0 && currentBatchLength + entryLength > 24e3;
|
|
70477
|
-
const exceedsFileCount = currentBatch.length >=
|
|
70736
|
+
const exceedsFileCount = currentBatch.length >= 200;
|
|
70478
70737
|
if (exceedsArgLength || exceedsFileCount) {
|
|
70479
70738
|
batches.push(currentBatch);
|
|
70480
70739
|
currentBatch = [];
|
|
@@ -70821,7 +71080,7 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
70821
71080
|
}
|
|
70822
71081
|
return enabled;
|
|
70823
71082
|
};
|
|
70824
|
-
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, runtimeGlobals, unpluginAutoImportGlobalScopes, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
|
|
71083
|
+
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, runtimeGlobals, unpluginAutoImportGlobalScopes, serverAuthFunctionNames, projectIndexModuleSources, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
|
|
70825
71084
|
const hasIncludedTags = includedTags.size > 0;
|
|
70826
71085
|
const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
|
|
70827
71086
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
@@ -70885,7 +71144,8 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
70885
71144
|
}))
|
|
70886
71145
|
} : {},
|
|
70887
71146
|
...project.shopifyFlashListMajorVersion !== null ? { shopifyFlashListMajorVersion: project.shopifyFlashListMajorVersion } : {},
|
|
70888
|
-
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {}
|
|
71147
|
+
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {},
|
|
71148
|
+
...projectIndexModuleSources !== void 0 ? { projectIndexModuleSources: [...projectIndexModuleSources] } : {}
|
|
70889
71149
|
} },
|
|
70890
71150
|
rules: {
|
|
70891
71151
|
...reactCompilerRules,
|
|
@@ -72370,6 +72630,12 @@ const buildProfiledNodeArguments = (input) => [
|
|
|
72370
72630
|
...input.heapProfileDirectory ? ["--heap-prof", `--heap-prof-dir=${input.heapProfileDirectory}`] : [],
|
|
72371
72631
|
...input.argumentsList
|
|
72372
72632
|
];
|
|
72633
|
+
const lowerChildProcessPriority = (processId) => {
|
|
72634
|
+
if (processId === void 0) return;
|
|
72635
|
+
try {
|
|
72636
|
+
OS.setPriority(processId, OS.constants.priority.PRIORITY_BELOW_NORMAL);
|
|
72637
|
+
} catch {}
|
|
72638
|
+
};
|
|
72373
72639
|
const SANITIZED_ENV = buildOxlintChildEnv(process.env);
|
|
72374
72640
|
/**
|
|
72375
72641
|
* Spawn one oxlint subprocess with hard ceilings on wall time and
|
|
@@ -72408,6 +72674,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLIN
|
|
|
72408
72674
|
"pipe"
|
|
72409
72675
|
]
|
|
72410
72676
|
});
|
|
72677
|
+
lowerChildProcessPriority(child.pid);
|
|
72411
72678
|
const onAbort = () => {
|
|
72412
72679
|
child.kill("SIGKILL");
|
|
72413
72680
|
reject(new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) }));
|
|
@@ -72530,7 +72797,7 @@ const isParallelismRelatedSpawnError = (error) => {
|
|
|
72530
72797
|
* loop with a slimmer config in that case.
|
|
72531
72798
|
*/
|
|
72532
72799
|
const spawnLintBatches = async (input) => {
|
|
72533
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, sourceMapByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth =
|
|
72800
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, sourceMapByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 9, signal, deadlineEpochMs } = input;
|
|
72534
72801
|
const resolveSourcePath = (filePath) => {
|
|
72535
72802
|
const absoluteFilePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory, filePath);
|
|
72536
72803
|
return sourcePathByLintPath?.get(Path.normalize(absoluteFilePath)) ?? filePath;
|
|
@@ -72538,6 +72805,12 @@ const spawnLintBatches = async (input) => {
|
|
|
72538
72805
|
const requestedConcurrency = resolveScanConcurrency(input.concurrency ?? 1);
|
|
72539
72806
|
let rescueDeadlineEpochMs;
|
|
72540
72807
|
const isPastDeadline = () => deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(deadlineEpochMs) === 0 || rescueDeadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(rescueDeadlineEpochMs) === 0;
|
|
72808
|
+
const resolveSpawnTimeoutMs = () => {
|
|
72809
|
+
const deadlineBudgets = [deadlineEpochMs, rescueDeadlineEpochMs].filter((deadline) => deadline !== void 0).map(remainingDeadlineBudgetMs);
|
|
72810
|
+
if (deadlineBudgets.length === 0) return spawnTimeoutMs;
|
|
72811
|
+
const remainingDeadlineMs = Math.min(...deadlineBudgets);
|
|
72812
|
+
return spawnTimeoutMs === void 0 ? remainingDeadlineMs : Math.min(spawnTimeoutMs, remainingDeadlineMs);
|
|
72813
|
+
};
|
|
72541
72814
|
const runBatchPass = async (concurrency, passBatches, passOnFileProgress) => {
|
|
72542
72815
|
const totalFileCount = passBatches.reduce((sum, batch) => sum + batch.length, 0);
|
|
72543
72816
|
const allDiagnostics = [];
|
|
@@ -72555,12 +72828,13 @@ const spawnLintBatches = async (input) => {
|
|
|
72555
72828
|
const batchArgs = [...baseArgs, ...batch];
|
|
72556
72829
|
try {
|
|
72557
72830
|
const spawnBatch = () => {
|
|
72558
|
-
|
|
72831
|
+
const effectiveSpawnTimeoutMs = resolveSpawnTimeoutMs();
|
|
72832
|
+
if (effectiveSpawnTimeoutMs === 0) {
|
|
72559
72833
|
deadlineSkippedFiles.push(...batch);
|
|
72560
72834
|
batchState.deadlineSkippedFileCount += batch.length;
|
|
72561
72835
|
return Promise.resolve(null);
|
|
72562
72836
|
}
|
|
72563
|
-
return spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath,
|
|
72837
|
+
return spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, effectiveSpawnTimeoutMs, outputMaxBytes, signal, () => {
|
|
72564
72838
|
if (batchState.didStart) return;
|
|
72565
72839
|
batchState.didStart = true;
|
|
72566
72840
|
startedFileCount += batchState.initialFileCount;
|
|
@@ -72715,11 +72989,36 @@ const validateRuleRegistration = () => {
|
|
|
72715
72989
|
].filter((entry) => entry !== null).join("; ");
|
|
72716
72990
|
console.warn(`[react-doctor] rule-registration drift: ${detail}`);
|
|
72717
72991
|
};
|
|
72992
|
+
const PROJECT_INDEX_MODULE_SOURCES = [
|
|
72993
|
+
"next/og",
|
|
72994
|
+
"@vercel/og",
|
|
72995
|
+
"satori",
|
|
72996
|
+
"remotion"
|
|
72997
|
+
];
|
|
72998
|
+
const collectProjectIndexModuleSources = async (rootDirectory, candidateFiles) => {
|
|
72999
|
+
const foundModuleSources = /* @__PURE__ */ new Set();
|
|
73000
|
+
let sliceStartedAt = performance.now();
|
|
73001
|
+
for (const candidateFile of candidateFiles) {
|
|
73002
|
+
let sourceBuffer;
|
|
73003
|
+
try {
|
|
73004
|
+
sourceBuffer = NFS.readFileSync(Path.isAbsolute(candidateFile) ? candidateFile : Path.resolve(rootDirectory, candidateFile));
|
|
73005
|
+
} catch {
|
|
73006
|
+
continue;
|
|
73007
|
+
}
|
|
73008
|
+
for (const moduleSource of PROJECT_INDEX_MODULE_SOURCES) if (sourceBuffer.includes(`"${moduleSource}"`) || sourceBuffer.includes(`'${moduleSource}'`)) foundModuleSources.add(moduleSource);
|
|
73009
|
+
if (foundModuleSources.size === PROJECT_INDEX_MODULE_SOURCES.length) break;
|
|
73010
|
+
if (performance.now() - sliceStartedAt >= 12) {
|
|
73011
|
+
await yieldToEventLoop();
|
|
73012
|
+
sliceStartedAt = performance.now();
|
|
73013
|
+
}
|
|
73014
|
+
}
|
|
73015
|
+
return [...foundModuleSources].sort();
|
|
73016
|
+
};
|
|
72718
73017
|
/**
|
|
72719
73018
|
* Balanced LPT (longest-processing-time-first) lint batch planner. Where
|
|
72720
|
-
* `batchIncludePaths` greedily fills
|
|
72721
|
-
* remainder batch
|
|
72722
|
-
*
|
|
73019
|
+
* `batchIncludePaths` greedily fills fixed-size batches and leaves a small
|
|
73020
|
+
* remainder batch, so the parallel pool's wall clock is set by whichever
|
|
73021
|
+
* full chunk happened to collect the most work while
|
|
72723
73022
|
* the remainder's worker idles), this planner keeps the SAME mandatory batch
|
|
72724
73023
|
* count — `ceil(files / OXLINT_MAX_FILES_PER_BATCH)`, the JS-plugin
|
|
72725
73024
|
* perf-cliff / native-binding SIGABRT guard — and assigns files largest-first,
|
|
@@ -72748,7 +73047,7 @@ const validateRuleRegistration = () => {
|
|
|
72748
73047
|
*/
|
|
72749
73048
|
const planLintBatches = ({ baseArgs, files, sizeByFile }) => {
|
|
72750
73049
|
if (files.length === 0) return [];
|
|
72751
|
-
const batchCount = Math.ceil(files.length /
|
|
73050
|
+
const batchCount = Math.ceil(files.length / 200);
|
|
72752
73051
|
const maxFilesPerBatch = Math.ceil(files.length / batchCount);
|
|
72753
73052
|
const baseArgsLengthChars = estimateArgsLength(baseArgs);
|
|
72754
73053
|
const descendingSizeIndexes = [...files.keys()].sort((leftIndex, rightIndex) => (sizeByFile.get(files[rightIndex]) ?? 0) - (sizeByFile.get(files[leftIndex]) ?? 0));
|
|
@@ -73277,6 +73576,7 @@ const runOxlint = async (options) => {
|
|
|
73277
73576
|
await yieldToEventLoop();
|
|
73278
73577
|
const sizedScanFiles = includePaths === void 0 ? listSourceFilesWithSize(rootDirectory) : null;
|
|
73279
73578
|
const candidateFiles = includePaths !== void 0 ? includePaths : (sizedScanFiles ?? []).map((entry) => entry.path);
|
|
73579
|
+
const projectIndexModuleSources = includePaths === void 0 && options.deadlineEpochMs === void 0 ? await collectProjectIndexModuleSources(rootDirectory, candidateFiles) : void 0;
|
|
73280
73580
|
unpluginAutoImportGlobalScopes = collectUnpluginAutoImportGlobalScopes({
|
|
73281
73581
|
rootDirectory,
|
|
73282
73582
|
candidateFiles
|
|
@@ -73299,6 +73599,7 @@ const runOxlint = async (options) => {
|
|
|
73299
73599
|
runtimeGlobals,
|
|
73300
73600
|
unpluginAutoImportGlobalScopes,
|
|
73301
73601
|
serverAuthFunctionNames,
|
|
73602
|
+
projectIndexModuleSources,
|
|
73302
73603
|
severityControls,
|
|
73303
73604
|
userPlugins,
|
|
73304
73605
|
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
@@ -73766,10 +74067,10 @@ const translateProjectInfoError = (cause, directory) => {
|
|
|
73766
74067
|
}) });
|
|
73767
74068
|
};
|
|
73768
74069
|
var Project = class Project extends Service()("react-doctor/Project") {
|
|
73769
|
-
static layerNode = succeed$3(Project, Project.of({ discover: fn("Project.discover")(function* (
|
|
74070
|
+
static layerNode = succeed$3(Project, Project.of({ discover: fn("Project.discover")(function* (input) {
|
|
73770
74071
|
return yield* try_({
|
|
73771
|
-
try: () => discoverProject(directory),
|
|
73772
|
-
catch: (cause) => translateProjectInfoError(cause, directory)
|
|
74072
|
+
try: () => discoverProject(input.directory, { sourceFileCount: input.sourceFileCount }),
|
|
74073
|
+
catch: (cause) => translateProjectInfoError(cause, input.directory)
|
|
73773
74074
|
});
|
|
73774
74075
|
}) }));
|
|
73775
74076
|
static layerOf = (projectInfo) => succeed$3(Project, Project.of({ discover: () => succeed$2(projectInfo) }));
|
|
@@ -74354,9 +74655,10 @@ const checkSupplyChain = (input) => gen(function* () {
|
|
|
74354
74655
|
* outage.
|
|
74355
74656
|
*/
|
|
74356
74657
|
var SupplyChain = class SupplyChain extends Service()("react-doctor/SupplyChain") {
|
|
74357
|
-
static layerNode = succeed$3(SupplyChain, SupplyChain.of({ run: (input) => unwrap(flatMap$2(SupplyChainOverlapTimeoutMs, (
|
|
74358
|
-
|
|
74359
|
-
|
|
74658
|
+
static layerNode = succeed$3(SupplyChain, SupplyChain.of({ run: (input) => unwrap(flatMap$2(SupplyChainOverlapTimeoutMs, (configuredTimeoutMs) => checkSupplyChain({
|
|
74659
|
+
rootDirectory: input.rootDirectory,
|
|
74660
|
+
userConfig: input.userConfig,
|
|
74661
|
+
totalTimeoutMs: input.timeoutMs ?? configuredTimeoutMs
|
|
74360
74662
|
})).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), withSpan("SupplyChain.run"))) }));
|
|
74361
74663
|
static layerOf = (diagnostics) => succeed$3(SupplyChain, SupplyChain.of({ run: () => fromIterable$1(diagnostics) }));
|
|
74362
74664
|
};
|
|
@@ -74391,10 +74693,6 @@ const NO_HOOKS = {
|
|
|
74391
74693
|
beforeLint: () => void_,
|
|
74392
74694
|
afterLint: () => void_
|
|
74393
74695
|
};
|
|
74394
|
-
const filterMapNullable = (transform) => fromPredicateOption((value) => {
|
|
74395
|
-
const result = transform(value);
|
|
74396
|
-
return result === null ? none() : some(result);
|
|
74397
|
-
});
|
|
74398
74696
|
const fileReader = (filesService, rootDirectory) => (filePath) => {
|
|
74399
74697
|
const lines = runSync(filesService.readLines({
|
|
74400
74698
|
filePath,
|
|
@@ -74418,7 +74716,7 @@ const formatLintFailText = (reasonTag, nodeVersion) => {
|
|
|
74418
74716
|
* The GitHub viewer-permission lookup is forked onto a background
|
|
74419
74717
|
* fiber here and joined late (it feeds score metadata, not
|
|
74420
74718
|
* diagnostics).
|
|
74421
|
-
* 2. beforeLint hook (e.g. CLI
|
|
74719
|
+
* 2. beforeLint hook (e.g. CLI records project telemetry)
|
|
74422
74720
|
* 3. environment checks (reduced-motion + pnpm hardening +
|
|
74423
74721
|
* expo/react-native), collected synchronously. The heavier
|
|
74424
74722
|
* content-regex security scan is forked instead (like supply-chain
|
|
@@ -74431,13 +74729,11 @@ const formatLintFailText = (reasonTag, nodeVersion) => {
|
|
|
74431
74729
|
* `SupplyChainOverlapTimeoutMs` (measured from fork) so a hung
|
|
74432
74730
|
* socket can't drag out its join; on timeout it fails open to no
|
|
74433
74731
|
* diagnostics — the same outcome class as a Socket outage.
|
|
74434
|
-
* 5. Linter.run runs; DeadCode.run
|
|
74435
|
-
*
|
|
74436
|
-
*
|
|
74437
|
-
*
|
|
74438
|
-
*
|
|
74439
|
-
* fiber is joined (or interrupted, SIGKILLing its worker, on lint
|
|
74440
|
-
* failure) before diagnostics are concatenated. The afterLint hook
|
|
74732
|
+
* 5. Linter.run runs; DeadCode.run forks only when
|
|
74733
|
+
* REACT_DOCTOR_DEAD_CODE_OVERLAP=on. The default "auto" and explicit
|
|
74734
|
+
* "off" paths stay sequential. The fiber is joined (or interrupted,
|
|
74735
|
+
* SIGKILLing its worker, on lint failure) before diagnostics are
|
|
74736
|
+
* concatenated. The afterLint hook
|
|
74441
74737
|
* fires between lint and dead-code. Progress spinner labels AND the
|
|
74442
74738
|
* final diagnostic / score order stay independent of execution
|
|
74443
74739
|
* order, so terminal output is identical either way; supply-chain
|
|
@@ -74472,8 +74768,28 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74472
74768
|
const partialFailuresRef = yield* LintPartialFailures;
|
|
74473
74769
|
const resolvedConfig = yield* configService.resolve(input.directory);
|
|
74474
74770
|
const scanDirectory = resolvedConfig.resolvedDirectory;
|
|
74475
|
-
const
|
|
74771
|
+
const excludedProjectDirectories = (input.excludedProjectDirectories ?? []).map((excludedDirectory) => Path.resolve(excludedDirectory)).filter((excludedDirectory) => isPathInsideDirectory(excludedDirectory, scanDirectory));
|
|
74772
|
+
const excludedProjectRelativePaths = excludedProjectDirectories.map((excludedDirectory) => Path.relative(scanDirectory, excludedDirectory).replaceAll("\\", "/"));
|
|
74773
|
+
const isExcludedProjectDiagnostic = (diagnostic) => {
|
|
74774
|
+
const relativeFilePath = toNormalizedRelativePath(diagnostic.filePath, scanDirectory);
|
|
74775
|
+
return excludedProjectRelativePaths.some((excludedRelativePath) => relativeFilePath === excludedRelativePath || relativeFilePath.startsWith(`${excludedRelativePath}/`));
|
|
74776
|
+
};
|
|
74777
|
+
const precomputedSourceFiles = input.suppressScanSummary === true || excludedProjectDirectories.length > 0 ? yield* filesService.listSourceFilesCooperative({
|
|
74778
|
+
rootDirectory: scanDirectory,
|
|
74779
|
+
signal: input.signal
|
|
74780
|
+
}) : null;
|
|
74781
|
+
const includedPrecomputedSourceFiles = precomputedSourceFiles !== null && excludedProjectDirectories.length > 0 ? filterPathsOutsideDirectories({
|
|
74782
|
+
rootDirectory: scanDirectory,
|
|
74783
|
+
relativePaths: precomputedSourceFiles,
|
|
74784
|
+
excludedDirectories: excludedProjectDirectories
|
|
74785
|
+
}) : precomputedSourceFiles;
|
|
74786
|
+
const sourceFileCount = excludedProjectDirectories.length > 0 ? includedPrecomputedSourceFiles?.length : input.precomputedSourceFileCount ?? includedPrecomputedSourceFiles?.length;
|
|
74787
|
+
const project = yield* projectService.discover({
|
|
74788
|
+
directory: scanDirectory,
|
|
74789
|
+
sourceFileCount
|
|
74790
|
+
});
|
|
74476
74791
|
if (!isAnalyzableProject(project)) return yield* new ReactDoctorError({ reason: new NoReactDependency({ directory: scanDirectory }) });
|
|
74792
|
+
const deadCodeSourceFileCount = input.retainExcludedProjectDeadCodeDiagnostics === true && precomputedSourceFiles !== null ? precomputedSourceFiles.length : project.sourceFileCount;
|
|
74477
74793
|
const [repo, sha, defaultBranch] = yield* all([
|
|
74478
74794
|
gitService.githubRepo(scanDirectory).pipe(orElseSucceed(() => null)),
|
|
74479
74795
|
gitService.headSha(scanDirectory).pipe(orElseSucceed(() => null)),
|
|
@@ -74484,11 +74800,16 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74484
74800
|
directory: scanDirectory,
|
|
74485
74801
|
repo
|
|
74486
74802
|
}).pipe(orElseSucceed(() => null)) : succeed$2(null));
|
|
74487
|
-
|
|
74488
|
-
|
|
74803
|
+
let lintIncludePaths = (input.skipExplicitIncludePathFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths])) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config, includedPrecomputedSourceFiles ?? void 0);
|
|
74804
|
+
if (excludedProjectDirectories.length > 0) lintIncludePaths = filterPathsOutsideDirectories({
|
|
74805
|
+
rootDirectory: scanDirectory,
|
|
74806
|
+
relativePaths: lintIncludePaths ?? includedPrecomputedSourceFiles ?? (yield* filesService.listSourceFiles(scanDirectory)),
|
|
74807
|
+
excludedDirectories: excludedProjectDirectories
|
|
74808
|
+
});
|
|
74809
|
+
const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? includedPrecomputedSourceFiles ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
|
|
74489
74810
|
const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
|
|
74490
74811
|
const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
|
|
74491
|
-
yield* beforeLint(project
|
|
74812
|
+
yield* beforeLint(project);
|
|
74492
74813
|
const isDiffMode = input.includePaths.length > 0;
|
|
74493
74814
|
const showWarnings = input.warnings ?? resolvedConfig.config?.warnings ?? true;
|
|
74494
74815
|
const transform = buildDiagnosticPipeline({
|
|
@@ -74498,7 +74819,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74498
74819
|
respectInlineDisables: input.respectInlineDisables,
|
|
74499
74820
|
showWarnings
|
|
74500
74821
|
});
|
|
74501
|
-
const filterPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(
|
|
74822
|
+
const filterPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(fromPredicateOption((diagnostic) => {
|
|
74823
|
+
const filteredDiagnostic = transform.apply(diagnostic);
|
|
74824
|
+
return filteredDiagnostic === null ? none() : some(filteredDiagnostic);
|
|
74825
|
+
})));
|
|
74502
74826
|
const applyPerElementPipeline = (rawStream) => filterPerElementPipeline(rawStream).pipe(tap((diagnostic) => reporterService.emit(diagnostic)));
|
|
74503
74827
|
const envCollected = yield* runCollect(applyPerElementPipeline(fromIterable$1(isDiffMode ? [] : [
|
|
74504
74828
|
...checkReducedMotion(scanDirectory),
|
|
@@ -74508,17 +74832,31 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74508
74832
|
...checkReactNativeProject(scanDirectory, project)
|
|
74509
74833
|
])));
|
|
74510
74834
|
const securityScanFailedRef = yield* make$13(false);
|
|
74511
|
-
|
|
74835
|
+
let didSecurityScanReachDeadline = false;
|
|
74836
|
+
const securityScanFiber = yield* forkChild(runCollect(applyPerElementPipeline(isDiffMode ? empty$4 : unwrap(tryPromise((signal) => checkSecurityScanCooperative(scanDirectory, {
|
|
74512
74837
|
project,
|
|
74513
74838
|
ignoredTags: input.ignoredTags,
|
|
74514
74839
|
includedTags: input.includedTags,
|
|
74515
|
-
includeTagDefaults: input.includeTagDefaults
|
|
74840
|
+
includeTagDefaults: input.includeTagDefaults,
|
|
74841
|
+
excludedDirectories: new Set(excludedProjectDirectories),
|
|
74842
|
+
deadlineEpochMs: input.deadlineEpochMs,
|
|
74843
|
+
signal,
|
|
74844
|
+
onDeadlineExceeded: () => {
|
|
74845
|
+
didSecurityScanReachDeadline = true;
|
|
74846
|
+
}
|
|
74516
74847
|
})).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), catch_$1(() => set(securityScanFailedRef, true).pipe(as(empty$4))))))).pipe(withSpan("SecurityScan.run")));
|
|
74848
|
+
const capToDeadline = (phaseTimeoutMs) => input.deadlineEpochMs === void 0 ? phaseTimeoutMs : Math.min(phaseTimeoutMs, remainingDeadlineBudgetMs(input.deadlineEpochMs));
|
|
74849
|
+
const capOptionalToDeadline = (phaseTimeoutMs) => {
|
|
74850
|
+
if (input.deadlineEpochMs === void 0) return phaseTimeoutMs;
|
|
74851
|
+
const remainingBudgetMs = remainingDeadlineBudgetMs(input.deadlineEpochMs);
|
|
74852
|
+
return phaseTimeoutMs === null ? remainingBudgetMs : Math.min(phaseTimeoutMs, remainingBudgetMs);
|
|
74853
|
+
};
|
|
74517
74854
|
const shouldRunSupplyChain = !isDiffMode || (input.supplyChainManifestChanged ?? false);
|
|
74518
|
-
const supplyChainOverlapTimeout = yield* SupplyChainOverlapTimeoutMs;
|
|
74855
|
+
const supplyChainOverlapTimeout = capToDeadline(yield* SupplyChainOverlapTimeoutMs);
|
|
74519
74856
|
const supplyChainFiber = yield* forkChild(shouldRunSupplyChain ? runCollect(applyPerElementPipeline(supplyChainService.run({
|
|
74520
74857
|
rootDirectory: scanDirectory,
|
|
74521
|
-
userConfig: resolvedConfig.config
|
|
74858
|
+
userConfig: resolvedConfig.config,
|
|
74859
|
+
timeoutMs: supplyChainOverlapTimeout
|
|
74522
74860
|
}))).pipe(map$3((diagnostics) => ({
|
|
74523
74861
|
diagnostics,
|
|
74524
74862
|
timedOut: false
|
|
@@ -74542,46 +74880,49 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74542
74880
|
const scanConcurrency = resolveScanConcurrency(yield* OxlintConcurrency);
|
|
74543
74881
|
const lintPhaseTimeoutMs = yield* LintPhaseTimeoutMs;
|
|
74544
74882
|
const deadCodePhaseTimeoutMs = yield* DeadCodePhaseTimeoutMs;
|
|
74545
|
-
const resolveDeadCodePhaseTimeoutMs = (scaledPhaseTimeoutMs) => deadCodePhaseTimeoutMs === 15e4 ? scaledPhaseTimeoutMs : deadCodePhaseTimeoutMs;
|
|
74546
74883
|
const workerCountSuffix = scanConcurrency > 1 ? ` ${highlighter.dim(`[~${scanConcurrency} workers]`)}` : "";
|
|
74547
|
-
const capToDeadline = (phaseTimeoutMs) => input.deadlineEpochMs === void 0 ? phaseTimeoutMs : Math.min(phaseTimeoutMs, remainingDeadlineBudgetMs(input.deadlineEpochMs));
|
|
74548
74884
|
const shouldRunDeadCode = input.runDeadCode && !isDiffMode && (showWarnings || deadCodeMaySurfaceWhenWarningsHidden(resolvedConfig.config));
|
|
74549
74885
|
const deadCodeOverlapMode = yield* DeadCodeOverlap;
|
|
74550
74886
|
const shouldOverlapDeadCode = shouldRunDeadCode && deadCodeOverlapMode === "on";
|
|
74551
74887
|
const deadCodeParseConcurrency = shouldOverlapDeadCode ? Math.max(1, Math.floor(scanConcurrency * DEAD_CODE_OVERLAP_PARSE_SHARE)) : void 0;
|
|
74552
74888
|
const lintConcurrency = deadCodeParseConcurrency === void 0 ? scanConcurrency : Math.max(1, scanConcurrency - deadCodeParseConcurrency);
|
|
74553
|
-
const buildCollectDeadCode = (deadCodeTimeout) =>
|
|
74554
|
-
|
|
74555
|
-
|
|
74556
|
-
|
|
74557
|
-
|
|
74558
|
-
|
|
74559
|
-
|
|
74560
|
-
|
|
74561
|
-
|
|
74562
|
-
|
|
74563
|
-
|
|
74564
|
-
|
|
74565
|
-
|
|
74566
|
-
|
|
74567
|
-
|
|
74568
|
-
|
|
74569
|
-
|
|
74570
|
-
|
|
74571
|
-
|
|
74572
|
-
|
|
74573
|
-
|
|
74574
|
-
|
|
74575
|
-
|
|
74576
|
-
|
|
74889
|
+
const buildCollectDeadCode = (deadCodeTimeout) => {
|
|
74890
|
+
const collectDeadCode = runCollect(applyPerElementPipeline(deadCodeService.run({
|
|
74891
|
+
rootDirectory: scanDirectory,
|
|
74892
|
+
parseConcurrency: deadCodeParseConcurrency,
|
|
74893
|
+
workerTimeoutMs: deadCodeTimeout.workerTimeoutMs,
|
|
74894
|
+
onCacheOutcome: (didHitCache) => {
|
|
74895
|
+
deadCodeCacheHit = didHitCache;
|
|
74896
|
+
},
|
|
74897
|
+
onSummaryCacheStats: (stats) => {
|
|
74898
|
+
deadCodeSummaryCacheHits = stats.hits;
|
|
74899
|
+
deadCodeSummaryCacheMisses = stats.misses;
|
|
74900
|
+
}
|
|
74901
|
+
}).pipe(filter((diagnostic) => input.retainExcludedProjectDeadCodeDiagnostics === true || !isExcludedProjectDiagnostic(diagnostic)), catchTag("ReactDoctorError", (error) => unwrap(gen(function* () {
|
|
74902
|
+
yield* set(deadCodeFailure, {
|
|
74903
|
+
didFail: true,
|
|
74904
|
+
reason: error.message
|
|
74905
|
+
});
|
|
74906
|
+
return empty$4;
|
|
74907
|
+
}))))));
|
|
74908
|
+
const phaseTimeoutMs = deadCodeTimeout.phaseTimeoutMs;
|
|
74909
|
+
if (phaseTimeoutMs === null) return collectDeadCode;
|
|
74910
|
+
return collectDeadCode.pipe(timeoutOption(phaseTimeoutMs), flatMap$2(match$3({
|
|
74911
|
+
onNone: () => set(deadCodeFailure, {
|
|
74912
|
+
didFail: true,
|
|
74913
|
+
reason: `Dead-code analysis exceeded ${Math.round(phaseTimeoutMs / MILLISECONDS_PER_SECOND)}s and was skipped.`
|
|
74914
|
+
}).pipe(as([])),
|
|
74915
|
+
onSome: succeed$2
|
|
74916
|
+
})));
|
|
74917
|
+
};
|
|
74577
74918
|
const overlapDeadCodeTimeout = resolveDeadCodeTimeout({
|
|
74578
|
-
sourceFileCount:
|
|
74919
|
+
sourceFileCount: deadCodeSourceFileCount,
|
|
74579
74920
|
deadCodeConcurrency: deadCodeParseConcurrency ?? scanConcurrency,
|
|
74580
74921
|
fullConcurrency: scanConcurrency
|
|
74581
74922
|
});
|
|
74582
74923
|
const deadCodeFiber = shouldOverlapDeadCode ? yield* forkChild(buildCollectDeadCode({
|
|
74583
74924
|
workerTimeoutMs: overlapDeadCodeTimeout.workerTimeoutMs,
|
|
74584
|
-
phaseTimeoutMs:
|
|
74925
|
+
phaseTimeoutMs: capOptionalToDeadline(deadCodePhaseTimeoutMs)
|
|
74585
74926
|
})) : null;
|
|
74586
74927
|
const scanProgress = yield* progressService.start("Scanning...");
|
|
74587
74928
|
const scanStartTime = Date.now();
|
|
@@ -74632,7 +74973,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74632
74973
|
});
|
|
74633
74974
|
return empty$4;
|
|
74634
74975
|
}))));
|
|
74635
|
-
const
|
|
74976
|
+
const collectLintDiagnostics = runCollect(filterPerElementPipeline(shouldOverlapDeadCode ? baseLintStream.pipe(provideService(OxlintConcurrency, lintConcurrency)) : baseLintStream));
|
|
74977
|
+
const lintCollected = dedupeRelatedDiagnostics(yield* lintPhaseTimeoutMs === null ? collectLintDiagnostics : collectLintDiagnostics.pipe(timeoutOption(lintPhaseTimeoutMs), flatMap$2(match$3({
|
|
74636
74978
|
onNone: () => set(lintFailure, {
|
|
74637
74979
|
didFail: true,
|
|
74638
74980
|
reason: `Lint analysis exceeded ${lintPhaseTimeoutMs / MILLISECONDS_PER_SECOND}s and was skipped.`,
|
|
@@ -74662,13 +75004,13 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74662
75004
|
} else {
|
|
74663
75005
|
yield* scanProgress.update(`Scanned ${scannedFilesLabel}, analyzing dead code...`);
|
|
74664
75006
|
const sequentialDeadCodeTimeout = resolveDeadCodeTimeout({
|
|
74665
|
-
sourceFileCount: totalFileCount,
|
|
75007
|
+
sourceFileCount: input.retainExcludedProjectDeadCodeDiagnostics === true ? deadCodeSourceFileCount : totalFileCount,
|
|
74666
75008
|
deadCodeConcurrency: scanConcurrency,
|
|
74667
75009
|
fullConcurrency: scanConcurrency
|
|
74668
75010
|
});
|
|
74669
75011
|
deadCodeCollected = deadCodeFiber !== null ? yield* join(deadCodeFiber) : yield* buildCollectDeadCode({
|
|
74670
75012
|
workerTimeoutMs: sequentialDeadCodeTimeout.workerTimeoutMs,
|
|
74671
|
-
phaseTimeoutMs:
|
|
75013
|
+
phaseTimeoutMs: capOptionalToDeadline(deadCodePhaseTimeoutMs)
|
|
74672
75014
|
});
|
|
74673
75015
|
}
|
|
74674
75016
|
const deadCodeFailureState = lintFailureState.didFail ? {
|
|
@@ -74712,7 +75054,11 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74712
75054
|
metadata: scoreMetadata
|
|
74713
75055
|
});
|
|
74714
75056
|
const lintPartialFailures = yield* get$2(partialFailuresRef);
|
|
74715
|
-
const
|
|
75057
|
+
const didSecurityScanFail = yield* get$2(securityScanFailedRef);
|
|
75058
|
+
const securityScanFailed = didSecurityScanFail || didSecurityScanReachDeadline;
|
|
75059
|
+
let securityScanFailureReason = null;
|
|
75060
|
+
if (didSecurityScanReachDeadline) securityScanFailureReason = "Security scan reached the max scan duration; findings collected before the deadline were preserved.";
|
|
75061
|
+
else if (didSecurityScanFail) securityScanFailureReason = "Security scan failed and was skipped.";
|
|
74716
75062
|
return {
|
|
74717
75063
|
project,
|
|
74718
75064
|
userConfig: resolvedConfig.config,
|
|
@@ -74735,6 +75081,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74735
75081
|
scanConcurrency,
|
|
74736
75082
|
supplyChainOverlapTimedOut: supplyChainResult.timedOut,
|
|
74737
75083
|
securityScanFailed,
|
|
75084
|
+
securityScanFailureReason,
|
|
74738
75085
|
lintCacheHitFileCount,
|
|
74739
75086
|
lintCacheTotalFileCount,
|
|
74740
75087
|
lintSidecarReplayedFileCount,
|
|
@@ -74750,7 +75097,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74750
75097
|
"inspect.runDeadCode": input.runDeadCode,
|
|
74751
75098
|
"inspect.isCi": input.isCi,
|
|
74752
75099
|
"inspect.scoreSurface": input.scoreSurface ?? "score"
|
|
74753
|
-
} }), (scanProgram) => flatMap$2(ScanDeadlineMs, (scanDeadlineMs) =>
|
|
75100
|
+
} }), (scanProgram) => flatMap$2(ScanDeadlineMs, (scanDeadlineMs) => {
|
|
75101
|
+
if (scanDeadlineMs === null) return scanProgram;
|
|
75102
|
+
return scanProgram.pipe(timeout(scanDeadlineMs), catchTag$1("TimeoutError", () => new ReactDoctorError({ reason: new ScanDeadlineExceeded({ detail: `${scanDeadlineMs / MILLISECONDS_PER_SECOND}s elapsed` }) })));
|
|
75103
|
+
}));
|
|
74754
75104
|
const parseNodeVersion = (versionString) => {
|
|
74755
75105
|
const [major = 0, minor = 0, patch = 0] = versionString.replace(/^v/, "").trim().split(".").map(Number);
|
|
74756
75106
|
return {
|
|
@@ -74851,16 +75201,6 @@ const resolveNodeForOxlint = () => {
|
|
|
74851
75201
|
});
|
|
74852
75202
|
});
|
|
74853
75203
|
/**
|
|
74854
|
-
* Zip-Slip defense: relative paths come from git (`diff --name-only`), which
|
|
74855
|
-
* normalizes during ordinary adds, but a crafted index/pack/symlinked tree can
|
|
74856
|
-
* smuggle `..` segments that escape the temp root. Resolve against the temp dir
|
|
74857
|
-
* and reject anything that lands outside before writing.
|
|
74858
|
-
*/
|
|
74859
|
-
const isPathInsideDirectory = (childAbsolutePath, parentAbsolutePath) => {
|
|
74860
|
-
const relative = path.relative(parentAbsolutePath, childAbsolutePath);
|
|
74861
|
-
return Boolean(relative) && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
74862
|
-
};
|
|
74863
|
-
/**
|
|
74864
75204
|
* Writes a set of source files (supplied by `readContent` — e.g.
|
|
74865
75205
|
* `git show <ref>:<path>` for a baseline tree, or `git show :<path>` for the
|
|
74866
75206
|
* index) into a temp tree that mirrors the project layout, copying the
|
|
@@ -75135,6 +75475,7 @@ const buildJsonReport = (input) => {
|
|
|
75135
75475
|
directory: input.directory,
|
|
75136
75476
|
diff: toJsonDiff(input.diff),
|
|
75137
75477
|
projects,
|
|
75478
|
+
...input.skippedProjects && input.skippedProjects.length > 0 ? { skippedProjects: [...input.skippedProjects] } : {},
|
|
75138
75479
|
diagnostics: flattenedDiagnostics,
|
|
75139
75480
|
summary,
|
|
75140
75481
|
elapsedMilliseconds: input.totalElapsedMilliseconds,
|
|
@@ -75159,7 +75500,7 @@ const buildSkippedChecks = (input) => {
|
|
|
75159
75500
|
else if (input.lintPartialFailures.length > 0) skippedCheckReasons["lint:partial"] = input.lintPartialFailures.join("; ");
|
|
75160
75501
|
if (input.didDeadCodeFail && input.deadCodeFailureReason !== null) skippedCheckReasons["dead-code"] = input.deadCodeFailureReason;
|
|
75161
75502
|
if (input.supplyChainOverlapTimedOut) skippedCheckReasons["supply-chain"] = "Supply-chain analysis timed out and was skipped.";
|
|
75162
|
-
if (input.securityScanFailed) skippedCheckReasons["security-scan"] = "Security scan failed and was skipped.";
|
|
75503
|
+
if (input.securityScanFailed) skippedCheckReasons["security-scan"] = input.securityScanFailureReason ?? "Security scan failed and was skipped.";
|
|
75163
75504
|
return {
|
|
75164
75505
|
skippedChecks,
|
|
75165
75506
|
skippedCheckReasons
|
|
@@ -75194,14 +75535,6 @@ const getDiffInfo = (directory, explicitBaseBranch, includeUntracked) => runProm
|
|
|
75194
75535
|
};
|
|
75195
75536
|
}).pipe(provide(Git.layerNode)));
|
|
75196
75537
|
const filterSourceFiles = (filePaths) => filePaths.filter(isLintableSourceFile);
|
|
75197
|
-
/**
|
|
75198
|
-
* Back-compat alias: the streaming pipeline holds its caches in
|
|
75199
|
-
* per-pipeline closures that are garbage-collected when the pipeline
|
|
75200
|
-
* goes out of scope, so there is nothing to clear at module scope. The
|
|
75201
|
-
* public CLI's `clearCaches()` still calls this for symmetry with the
|
|
75202
|
-
* other `clear*` helpers.
|
|
75203
|
-
*/
|
|
75204
|
-
const clearAutoSuppressionCaches = () => {};
|
|
75205
75538
|
const createLintPhaseAbortError = () => new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) });
|
|
75206
75539
|
const createOxlintSpawnSlots = (concurrency) => createWorkerSlots({
|
|
75207
75540
|
slotCount: resolveScanConcurrency(concurrency),
|
|
@@ -75460,7 +75793,6 @@ const clearCaches = () => {
|
|
|
75460
75793
|
clearPackageJsonCache();
|
|
75461
75794
|
clearIgnorePatternsCache();
|
|
75462
75795
|
clearPackageRoleCache();
|
|
75463
|
-
clearAutoSuppressionCaches();
|
|
75464
75796
|
clearMinifiedFileCache();
|
|
75465
75797
|
};
|
|
75466
75798
|
const toJsonReport = (result, options) => buildJsonReport({
|
|
@@ -75487,4 +75819,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
75487
75819
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
75488
75820
|
|
|
75489
75821
|
//# sourceMappingURL=index.js.map
|
|
75490
|
-
//# debugId=
|
|
75822
|
+
//# debugId=76d09448-ef0d-52d4-8c22-005bcb8715c5
|