react-doctor 0.9.3 → 0.9.4-dev.25dbf6d
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 +1456 -695
- package/dist/index.d.ts +10 -2
- package/dist/index.js +820 -393
- package/dist/lsp.js +861 -355
- package/dist/run-scan-app-C8iWVgvR.js +2326 -0
- package/package.json +7 -6
- package/dist/run-scan-app-DHRvqfkX.js +0 -1733
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
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]="6d2e43de-ae97-5213-b1a7-a9905ce4b1d5")}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";
|
|
6
6
|
import * as Crypto from "node:crypto";
|
|
7
7
|
import crypto, { createHash } from "node:crypto";
|
|
8
|
-
import * as NFS from "node:fs";
|
|
9
|
-
import fs from "node:fs";
|
|
10
8
|
import * as Path from "node:path";
|
|
11
9
|
import path from "node:path";
|
|
10
|
+
import * as NFS from "node:fs";
|
|
11
|
+
import fs from "node:fs";
|
|
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 = [
|
|
@@ -62216,7 +62285,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
62216
62285
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
62217
62286
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
62218
62287
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
62219
|
-
const CORE_PACKAGE_VERSION = "0.9.
|
|
62288
|
+
const CORE_PACKAGE_VERSION = "0.9.4";
|
|
62220
62289
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
62221
62290
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
62222
62291
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -62229,17 +62298,20 @@ const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
|
|
|
62229
62298
|
const isErrnoException = (error) => error instanceof Error && "code" in error;
|
|
62230
62299
|
const IGNORABLE_READDIR_ERROR_CODES = new Set([
|
|
62231
62300
|
"EACCES",
|
|
62301
|
+
"EBUSY",
|
|
62232
62302
|
"EPERM",
|
|
62233
62303
|
"ENOENT",
|
|
62234
62304
|
"ENOTDIR",
|
|
62235
62305
|
"EINVAL",
|
|
62236
62306
|
"ELOOP",
|
|
62237
|
-
"ENAMETOOLONG"
|
|
62307
|
+
"ENAMETOOLONG",
|
|
62308
|
+
"ETIMEDOUT",
|
|
62309
|
+
"UNKNOWN"
|
|
62238
62310
|
]);
|
|
62239
62311
|
const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
|
|
62240
62312
|
const readDirectoryEntries = (directoryPath) => {
|
|
62241
62313
|
try {
|
|
62242
|
-
return
|
|
62314
|
+
return fs.readdirSync(directoryPath, { withFileTypes: true });
|
|
62243
62315
|
} catch (error) {
|
|
62244
62316
|
if (isIgnorableReaddirError(error)) return [];
|
|
62245
62317
|
throw error;
|
|
@@ -62247,14 +62319,14 @@ const readDirectoryEntries = (directoryPath) => {
|
|
|
62247
62319
|
};
|
|
62248
62320
|
const isFile = (filePath) => {
|
|
62249
62321
|
try {
|
|
62250
|
-
return
|
|
62322
|
+
return fs.statSync(filePath).isFile();
|
|
62251
62323
|
} catch {
|
|
62252
62324
|
return false;
|
|
62253
62325
|
}
|
|
62254
62326
|
};
|
|
62255
62327
|
const isDirectory = (directoryPath) => {
|
|
62256
62328
|
try {
|
|
62257
|
-
return
|
|
62329
|
+
return fs.statSync(directoryPath).isDirectory();
|
|
62258
62330
|
} catch {
|
|
62259
62331
|
return false;
|
|
62260
62332
|
}
|
|
@@ -62264,6 +62336,66 @@ const isPlainObject = (value) => {
|
|
|
62264
62336
|
const prototype = Object.getPrototypeOf(value);
|
|
62265
62337
|
return prototype === null || prototype === Object.prototype;
|
|
62266
62338
|
};
|
|
62339
|
+
const LINGUIST_ATTRIBUTES = ["linguist-generated", "linguist-vendored"];
|
|
62340
|
+
const DISABLED_ATTRIBUTE_VALUES = new Set([
|
|
62341
|
+
"unspecified",
|
|
62342
|
+
"unset",
|
|
62343
|
+
"false",
|
|
62344
|
+
"0",
|
|
62345
|
+
"off",
|
|
62346
|
+
"no"
|
|
62347
|
+
]);
|
|
62348
|
+
const buildInput = (relativePaths) => `${relativePaths.join("\0")}\0`;
|
|
62349
|
+
const parseIgnoredPaths = (output) => {
|
|
62350
|
+
const ignoredPaths = /* @__PURE__ */ new Set();
|
|
62351
|
+
const fields = output.split("\0");
|
|
62352
|
+
for (let fieldIndex = 0; fieldIndex + 2 < fields.length; fieldIndex += 3) {
|
|
62353
|
+
const filePath = fields[fieldIndex];
|
|
62354
|
+
const value = fields[fieldIndex + 2]?.toLowerCase();
|
|
62355
|
+
if (filePath && value && !DISABLED_ATTRIBUTE_VALUES.has(value)) ignoredPaths.add(filePath);
|
|
62356
|
+
}
|
|
62357
|
+
return ignoredPaths;
|
|
62358
|
+
};
|
|
62359
|
+
const collectGitLinguistIgnoredPaths = (rootDirectory, relativePaths) => {
|
|
62360
|
+
if (relativePaths.length === 0) return /* @__PURE__ */ new Set();
|
|
62361
|
+
const result = spawnSync("git", [
|
|
62362
|
+
"check-attr",
|
|
62363
|
+
"-z",
|
|
62364
|
+
"--stdin",
|
|
62365
|
+
...LINGUIST_ATTRIBUTES
|
|
62366
|
+
], {
|
|
62367
|
+
cwd: rootDirectory,
|
|
62368
|
+
encoding: "utf-8",
|
|
62369
|
+
input: buildInput(relativePaths),
|
|
62370
|
+
maxBuffer: GIT_CHECK_ATTR_MAX_BUFFER_BYTES
|
|
62371
|
+
});
|
|
62372
|
+
if (result.error || result.status !== 0) return /* @__PURE__ */ new Set();
|
|
62373
|
+
return parseIgnoredPaths(result.stdout);
|
|
62374
|
+
};
|
|
62375
|
+
const collectGitLinguistIgnoredPathsCooperative = (rootDirectory, relativePaths, signal) => {
|
|
62376
|
+
if (relativePaths.length === 0) return Promise.resolve(/* @__PURE__ */ new Set());
|
|
62377
|
+
return new Promise((resolve, reject) => {
|
|
62378
|
+
signal?.throwIfAborted();
|
|
62379
|
+
execFile("git", [
|
|
62380
|
+
"check-attr",
|
|
62381
|
+
"-z",
|
|
62382
|
+
"--stdin",
|
|
62383
|
+
...LINGUIST_ATTRIBUTES
|
|
62384
|
+
], {
|
|
62385
|
+
cwd: rootDirectory,
|
|
62386
|
+
encoding: "utf-8",
|
|
62387
|
+
killSignal: "SIGKILL",
|
|
62388
|
+
maxBuffer: GIT_CHECK_ATTR_MAX_BUFFER_BYTES,
|
|
62389
|
+
signal
|
|
62390
|
+
}, (error, stdout) => {
|
|
62391
|
+
if (signal?.aborted) {
|
|
62392
|
+
reject(signal.reason);
|
|
62393
|
+
return;
|
|
62394
|
+
}
|
|
62395
|
+
resolve(error ? /* @__PURE__ */ new Set() : parseIgnoredPaths(stdout));
|
|
62396
|
+
}).stdin?.end(buildInput(relativePaths));
|
|
62397
|
+
});
|
|
62398
|
+
};
|
|
62267
62399
|
const lastSourceMappingUrl = (fileContent) => {
|
|
62268
62400
|
const lastReference = [...fileContent.matchAll(/\/\/# sourceMappingURL=(\S+)/g)].at(-1);
|
|
62269
62401
|
return lastReference ? lastReference[1] : null;
|
|
@@ -62368,6 +62500,9 @@ function* walkSourceTreeFiles(rootDirectory) {
|
|
|
62368
62500
|
}
|
|
62369
62501
|
}
|
|
62370
62502
|
}
|
|
62503
|
+
const yieldToEventLoop = () => new Promise((resolve) => {
|
|
62504
|
+
setImmediate(resolve);
|
|
62505
|
+
});
|
|
62371
62506
|
const collectSizedSourceFiles = (rootDirectory, relativePaths) => {
|
|
62372
62507
|
const entries = [];
|
|
62373
62508
|
for (const relativePath of relativePaths) {
|
|
@@ -62381,23 +62516,55 @@ const collectSizedSourceFiles = (rootDirectory, relativePaths) => {
|
|
|
62381
62516
|
}
|
|
62382
62517
|
return entries;
|
|
62383
62518
|
};
|
|
62384
|
-
const
|
|
62519
|
+
const collectSizedSourceFilesCooperative = async (rootDirectory, relativePaths, signal) => {
|
|
62520
|
+
const entries = [];
|
|
62521
|
+
let sliceStartedAt = performance.now();
|
|
62522
|
+
for (const relativePath of relativePaths) {
|
|
62523
|
+
signal?.throwIfAborted();
|
|
62524
|
+
const absolutePath = Path.resolve(rootDirectory, relativePath);
|
|
62525
|
+
const sizeBytes = statSourceFileSize(absolutePath);
|
|
62526
|
+
if (!isLargeMinifiedFile(absolutePath, sizeBytes)) entries.push({
|
|
62527
|
+
path: relativePath,
|
|
62528
|
+
sizeBytes: sizeBytes ?? 0
|
|
62529
|
+
});
|
|
62530
|
+
if (performance.now() - sliceStartedAt >= 12) {
|
|
62531
|
+
await yieldToEventLoop();
|
|
62532
|
+
sliceStartedAt = performance.now();
|
|
62533
|
+
}
|
|
62534
|
+
}
|
|
62535
|
+
return entries;
|
|
62536
|
+
};
|
|
62537
|
+
const parseGitSourceFilePaths = (output) => {
|
|
62538
|
+
const trackedPaths = /* @__PURE__ */ new Set();
|
|
62539
|
+
const untrackedPaths = [];
|
|
62540
|
+
for (const entry of output.split("\0")) {
|
|
62541
|
+
if (entry.length === 0) continue;
|
|
62542
|
+
const trackedPath = /^[0-7]{6} [0-9a-f]+ [0-3]\t([\s\S]+)$/.exec(entry)?.[1];
|
|
62543
|
+
if (trackedPath === void 0) untrackedPaths.push(entry);
|
|
62544
|
+
else trackedPaths.add(trackedPath);
|
|
62545
|
+
}
|
|
62546
|
+
return {
|
|
62547
|
+
trackedPaths: [...trackedPaths],
|
|
62548
|
+
untrackedPaths
|
|
62549
|
+
};
|
|
62550
|
+
};
|
|
62551
|
+
const listGitSourceFilePaths = (rootDirectory) => {
|
|
62385
62552
|
const result = spawnSync("git", [
|
|
62386
62553
|
"ls-files",
|
|
62387
62554
|
"-z",
|
|
62388
|
-
|
|
62555
|
+
"--stage",
|
|
62556
|
+
"--others",
|
|
62557
|
+
"--exclude-standard"
|
|
62389
62558
|
], {
|
|
62390
62559
|
cwd: rootDirectory,
|
|
62391
62560
|
encoding: "utf-8",
|
|
62392
62561
|
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES
|
|
62393
62562
|
});
|
|
62394
62563
|
if (result.error || result.status !== 0) return null;
|
|
62395
|
-
return result.stdout
|
|
62564
|
+
return parseGitSourceFilePaths(result.stdout);
|
|
62396
62565
|
};
|
|
62397
|
-
const
|
|
62398
|
-
const trackedPaths =
|
|
62399
|
-
const untrackedPaths = gitLsFiles(rootDirectory, ["--others", "--exclude-standard"]);
|
|
62400
|
-
if (trackedPaths === null || untrackedPaths === null) return null;
|
|
62566
|
+
const collectGitCandidateSourceFilePaths = (rootDirectory, paths) => {
|
|
62567
|
+
const { trackedPaths, untrackedPaths } = paths;
|
|
62401
62568
|
const emitDuplicateJsPaths = collectTypeScriptEmitDuplicateJsPaths({
|
|
62402
62569
|
trackedPaths: new Set(trackedPaths),
|
|
62403
62570
|
untrackedPaths,
|
|
@@ -62405,12 +62572,65 @@ const listSourceFilesViaGit = (rootDirectory) => {
|
|
|
62405
62572
|
});
|
|
62406
62573
|
return [...trackedPaths, ...untrackedPaths].filter((filePath) => isLintableSourceFile(filePath) && !hasIgnoredPathSegment(filePath) && !emitDuplicateJsPaths.has(filePath));
|
|
62407
62574
|
};
|
|
62575
|
+
const filterGitSourceFilePaths = (rootDirectory, paths) => {
|
|
62576
|
+
const candidatePaths = collectGitCandidateSourceFilePaths(rootDirectory, paths);
|
|
62577
|
+
const linguistIgnoredPaths = collectGitLinguistIgnoredPaths(rootDirectory, candidatePaths);
|
|
62578
|
+
return candidatePaths.filter((filePath) => !linguistIgnoredPaths.has(filePath));
|
|
62579
|
+
};
|
|
62580
|
+
const listSourceFilesViaGit = (rootDirectory) => {
|
|
62581
|
+
const paths = listGitSourceFilePaths(rootDirectory);
|
|
62582
|
+
return paths === null ? null : filterGitSourceFilePaths(rootDirectory, paths);
|
|
62583
|
+
};
|
|
62584
|
+
const listSourceFilesViaGitCooperative = async (rootDirectory, signal) => {
|
|
62585
|
+
const paths = await new Promise((resolve, reject) => {
|
|
62586
|
+
signal?.throwIfAborted();
|
|
62587
|
+
execFile("git", [
|
|
62588
|
+
"ls-files",
|
|
62589
|
+
"-z",
|
|
62590
|
+
"--stage",
|
|
62591
|
+
"--others",
|
|
62592
|
+
"--exclude-standard"
|
|
62593
|
+
], {
|
|
62594
|
+
cwd: rootDirectory,
|
|
62595
|
+
encoding: "utf-8",
|
|
62596
|
+
killSignal: "SIGKILL",
|
|
62597
|
+
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES,
|
|
62598
|
+
signal
|
|
62599
|
+
}, (error, stdout) => {
|
|
62600
|
+
if (signal?.aborted) {
|
|
62601
|
+
reject(signal.reason);
|
|
62602
|
+
return;
|
|
62603
|
+
}
|
|
62604
|
+
resolve(error ? null : parseGitSourceFilePaths(stdout));
|
|
62605
|
+
});
|
|
62606
|
+
});
|
|
62607
|
+
if (paths === null) return null;
|
|
62608
|
+
const candidatePaths = collectGitCandidateSourceFilePaths(rootDirectory, paths);
|
|
62609
|
+
const linguistIgnoredPaths = await collectGitLinguistIgnoredPathsCooperative(rootDirectory, candidatePaths, signal);
|
|
62610
|
+
return candidatePaths.filter((filePath) => !linguistIgnoredPaths.has(filePath));
|
|
62611
|
+
};
|
|
62408
62612
|
const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
62409
62613
|
const filePaths = [];
|
|
62410
62614
|
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) if (isLintableSourceFile(name)) filePaths.push(Path.relative(rootDirectory, absolutePath).replace(/\\/g, "/"));
|
|
62411
62615
|
return filePaths;
|
|
62412
62616
|
};
|
|
62413
|
-
const
|
|
62617
|
+
const listSourceFilesViaFilesystemCooperative = async (rootDirectory, signal) => {
|
|
62618
|
+
const filePaths = [];
|
|
62619
|
+
let sliceStartedAt = performance.now();
|
|
62620
|
+
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) {
|
|
62621
|
+
signal?.throwIfAborted();
|
|
62622
|
+
if (isLintableSourceFile(name)) filePaths.push(Path.relative(rootDirectory, absolutePath).replace(/\\/g, "/"));
|
|
62623
|
+
if (performance.now() - sliceStartedAt >= 12) {
|
|
62624
|
+
await yieldToEventLoop();
|
|
62625
|
+
sliceStartedAt = performance.now();
|
|
62626
|
+
}
|
|
62627
|
+
}
|
|
62628
|
+
return filePaths;
|
|
62629
|
+
};
|
|
62630
|
+
const listSourceFilePaths = (rootDirectory) => (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort();
|
|
62631
|
+
const listSourceFilePathsCooperative = async (rootDirectory, signal) => (await listSourceFilesViaGitCooperative(rootDirectory, signal) ?? await listSourceFilesViaFilesystemCooperative(rootDirectory, signal)).sort();
|
|
62632
|
+
const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, listSourceFilePaths(rootDirectory));
|
|
62633
|
+
const listSourceFilesCooperative = async (rootDirectory, signal) => (await collectSizedSourceFilesCooperative(rootDirectory, await listSourceFilePathsCooperative(rootDirectory, signal), signal)).map((entry) => entry.path);
|
|
62414
62634
|
const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
|
|
62415
62635
|
const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
|
|
62416
62636
|
const UTF8_BOM_CHARACTER = "";
|
|
@@ -62536,7 +62756,12 @@ const mergeCompilerOptions = (inherited, current) => {
|
|
|
62536
62756
|
};
|
|
62537
62757
|
};
|
|
62538
62758
|
const readResolvedCompilerOptions = (tsConfigPath, extendsDepth, visitedPaths) => {
|
|
62539
|
-
|
|
62759
|
+
let realPath;
|
|
62760
|
+
try {
|
|
62761
|
+
realPath = NFS.realpathSync.native(tsConfigPath);
|
|
62762
|
+
} catch {
|
|
62763
|
+
return null;
|
|
62764
|
+
}
|
|
62540
62765
|
if (visitedPaths.has(realPath)) return null;
|
|
62541
62766
|
const tsConfig = readTsConfig(realPath);
|
|
62542
62767
|
if (!tsConfig) return null;
|
|
@@ -63064,27 +63289,30 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
|
|
|
63064
63289
|
}
|
|
63065
63290
|
return null;
|
|
63066
63291
|
};
|
|
63067
|
-
const configExpressionMayDefineProperty = (expression, propertyName, analysis) => {
|
|
63292
|
+
const configExpressionMayDefineProperty = (expression, propertyName, analysis, visitedExpressions = /* @__PURE__ */ new Set()) => {
|
|
63068
63293
|
let resolvedExpression = expression;
|
|
63069
63294
|
while (ts.isParenthesizedExpression(resolvedExpression) || ts.isAsExpression(resolvedExpression) || ts.isTypeAssertionExpression(resolvedExpression) || ts.isSatisfiesExpression(resolvedExpression) || ts.isNonNullExpression(resolvedExpression)) resolvedExpression = resolvedExpression.expression;
|
|
63295
|
+
if (visitedExpressions.has(resolvedExpression)) return true;
|
|
63296
|
+
const nextVisitedExpressions = new Set(visitedExpressions);
|
|
63297
|
+
nextVisitedExpressions.add(resolvedExpression);
|
|
63070
63298
|
if (ts.isIdentifier(resolvedExpression)) {
|
|
63071
63299
|
if (analysis.localBindings.has(resolvedExpression.text)) {
|
|
63072
63300
|
const localReference = analysis.localBindings.get(resolvedExpression.text);
|
|
63073
|
-
return localReference?.expression ? configExpressionMayDefineProperty(localReference.expression, propertyName, localReference.analysis) : true;
|
|
63301
|
+
return localReference?.expression ? configExpressionMayDefineProperty(localReference.expression, propertyName, localReference.analysis, nextVisitedExpressions) : true;
|
|
63074
63302
|
}
|
|
63075
63303
|
const scopedBinding = getScopedConfigBinding(resolvedExpression);
|
|
63076
|
-
if (scopedBinding.wasFound) return scopedBinding.initializer ? configExpressionMayDefineProperty(scopedBinding.initializer, propertyName, analysis) : true;
|
|
63304
|
+
if (scopedBinding.wasFound) return scopedBinding.initializer ? configExpressionMayDefineProperty(scopedBinding.initializer, propertyName, analysis, nextVisitedExpressions) : true;
|
|
63077
63305
|
const topLevelBinding = getTopLevelBinding(analysis.sourceFile, resolvedExpression.text);
|
|
63078
|
-
return topLevelBinding && ts.isExpression(topLevelBinding) ? configExpressionMayDefineProperty(topLevelBinding, propertyName, analysis) : true;
|
|
63306
|
+
return topLevelBinding && ts.isExpression(topLevelBinding) ? configExpressionMayDefineProperty(topLevelBinding, propertyName, analysis, nextVisitedExpressions) : true;
|
|
63079
63307
|
}
|
|
63080
63308
|
if (ts.isConditionalExpression(resolvedExpression)) {
|
|
63081
|
-
if (isStaticallyTruthyConfigExpression(resolvedExpression.condition, analysis)) return configExpressionMayDefineProperty(resolvedExpression.whenTrue, propertyName, analysis);
|
|
63082
|
-
if (isStaticallyDisabledConfigExpression(resolvedExpression.condition, analysis)) return configExpressionMayDefineProperty(resolvedExpression.whenFalse, propertyName, analysis);
|
|
63083
|
-
return configExpressionMayDefineProperty(resolvedExpression.whenTrue, propertyName, analysis) || configExpressionMayDefineProperty(resolvedExpression.whenFalse, propertyName, analysis);
|
|
63309
|
+
if (isStaticallyTruthyConfigExpression(resolvedExpression.condition, analysis)) return configExpressionMayDefineProperty(resolvedExpression.whenTrue, propertyName, analysis, nextVisitedExpressions);
|
|
63310
|
+
if (isStaticallyDisabledConfigExpression(resolvedExpression.condition, analysis)) return configExpressionMayDefineProperty(resolvedExpression.whenFalse, propertyName, analysis, nextVisitedExpressions);
|
|
63311
|
+
return configExpressionMayDefineProperty(resolvedExpression.whenTrue, propertyName, analysis, nextVisitedExpressions) || configExpressionMayDefineProperty(resolvedExpression.whenFalse, propertyName, analysis, nextVisitedExpressions);
|
|
63084
63312
|
}
|
|
63085
63313
|
if (!ts.isObjectLiteralExpression(resolvedExpression)) return true;
|
|
63086
63314
|
return resolvedExpression.properties.some((property) => {
|
|
63087
|
-
if (ts.isSpreadAssignment(property)) return configExpressionMayDefineProperty(property.expression, propertyName, analysis);
|
|
63315
|
+
if (ts.isSpreadAssignment(property)) return configExpressionMayDefineProperty(property.expression, propertyName, analysis, nextVisitedExpressions);
|
|
63088
63316
|
if (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property) || ts.isMethodDeclaration(property) || ts.isGetAccessorDeclaration(property) || ts.isSetAccessorDeclaration(property)) {
|
|
63089
63317
|
const staticPropertyName = getStaticPropertyName$2(property.name);
|
|
63090
63318
|
return staticPropertyName === null || staticPropertyName === propertyName;
|
|
@@ -63160,7 +63388,13 @@ const analyzeConfigModuleExport = (filePath, exportName, allowCompilerTransform,
|
|
|
63160
63388
|
if (visitedModules.has(moduleVisitKey)) return false;
|
|
63161
63389
|
const nextVisitedModules = new Set(visitedModules);
|
|
63162
63390
|
nextVisitedModules.add(moduleVisitKey);
|
|
63163
|
-
|
|
63391
|
+
let sourceText;
|
|
63392
|
+
try {
|
|
63393
|
+
sourceText = NFS.readFileSync(filePath, "utf-8");
|
|
63394
|
+
} catch {
|
|
63395
|
+
return false;
|
|
63396
|
+
}
|
|
63397
|
+
return analyzeConfigSourceFileExport(parseConfigSourceFile(filePath, sourceText), filePath, exportName, allowCompilerTransform, importDepth, nextVisitedModules, argumentsList, argumentAnalysis);
|
|
63164
63398
|
};
|
|
63165
63399
|
const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = [], argumentAnalysis) => {
|
|
63166
63400
|
const analysis = {
|
|
@@ -63988,13 +64222,7 @@ const hasReactDependency = (packageJson) => {
|
|
|
63988
64222
|
};
|
|
63989
64223
|
return Object.keys(allDependencies).some((packageName) => REACT_DEPENDENCY_NAMES.has(packageName));
|
|
63990
64224
|
};
|
|
63991
|
-
const getPreactVersion = (packageJson) =>
|
|
63992
|
-
return {
|
|
63993
|
-
...packageJson.peerDependencies,
|
|
63994
|
-
...packageJson.dependencies,
|
|
63995
|
-
...packageJson.devDependencies
|
|
63996
|
-
}.preact ?? null;
|
|
63997
|
-
};
|
|
64225
|
+
const getPreactVersion = (packageJson) => getDependencySpec(packageJson, "preact");
|
|
63998
64226
|
const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, sourceDirectory = rootDirectory, sourcePackageJson = rootPackageJson, version }) => {
|
|
63999
64227
|
if (version === null || !isCatalogReference(version)) return version;
|
|
64000
64228
|
const catalogName = extractCatalogName(version);
|
|
@@ -64739,7 +64967,16 @@ const getBrowserslistProtectionRequirement = (directory) => {
|
|
|
64739
64967
|
if (!queries) return void 0;
|
|
64740
64968
|
let requirement;
|
|
64741
64969
|
let hasUnsupportedTarget = false;
|
|
64742
|
-
|
|
64970
|
+
const previousIgnoreOldData = process.env.BROWSERSLIST_IGNORE_OLD_DATA;
|
|
64971
|
+
let browserTargets = [];
|
|
64972
|
+
try {
|
|
64973
|
+
process.env.BROWSERSLIST_IGNORE_OLD_DATA = "true";
|
|
64974
|
+
browserTargets = (0, import_browserslist.default)(queries);
|
|
64975
|
+
} finally {
|
|
64976
|
+
if (previousIgnoreOldData === void 0) delete process.env.BROWSERSLIST_IGNORE_OLD_DATA;
|
|
64977
|
+
else process.env.BROWSERSLIST_IGNORE_OLD_DATA = previousIgnoreOldData;
|
|
64978
|
+
}
|
|
64979
|
+
for (const browserTarget of browserTargets) {
|
|
64743
64980
|
const browserRequirement = getBrowserProtectionRequirement(browserTarget);
|
|
64744
64981
|
if (browserRequirement === "unsupported") hasUnsupportedTarget = true;
|
|
64745
64982
|
if (browserRequirement === "noreferrer") requirement = "noreferrer";
|
|
@@ -64849,9 +65086,9 @@ const clearProjectCache = () => {
|
|
|
64849
65086
|
* framework-agnostic rules. Throws only when the directory has nothing
|
|
64850
65087
|
* to scan (no enclosing project and no source files of its own).
|
|
64851
65088
|
*/
|
|
64852
|
-
const discoverProjectWithoutPackageJson = (directory) => {
|
|
64853
|
-
const sourceFileCount = countSourceFiles(directory);
|
|
64854
|
-
const hasOwnTsConfig =
|
|
65089
|
+
const discoverProjectWithoutPackageJson = (directory, options) => {
|
|
65090
|
+
const sourceFileCount = options.sourceFileCount ?? countSourceFiles(directory);
|
|
65091
|
+
const hasOwnTsConfig = isFile(Path.join(directory, "tsconfig.json"));
|
|
64855
65092
|
const enclosingProjectRoot = findNearestAncestorPackageJson(directory);
|
|
64856
65093
|
const enclosingProject = enclosingProjectRoot !== null ? discoverProject(enclosingProjectRoot) : null;
|
|
64857
65094
|
if (enclosingProject !== null) return {
|
|
@@ -64917,12 +65154,15 @@ const discoverProjectWithoutPackageJson = (directory) => {
|
|
|
64917
65154
|
sourceFileCount
|
|
64918
65155
|
};
|
|
64919
65156
|
};
|
|
64920
|
-
const discoverProject = (directory) => {
|
|
65157
|
+
const discoverProject = (directory, options = {}) => {
|
|
64921
65158
|
const cached = cachedProjectInfos.get(directory);
|
|
64922
|
-
if (cached !== void 0) return cached
|
|
65159
|
+
if (cached !== void 0) return options.sourceFileCount === void 0 ? cached : {
|
|
65160
|
+
...cached,
|
|
65161
|
+
sourceFileCount: options.sourceFileCount
|
|
65162
|
+
};
|
|
64923
65163
|
const packageJsonPath = Path.join(directory, "package.json");
|
|
64924
65164
|
if (!isFile(packageJsonPath)) {
|
|
64925
|
-
const synthesized = discoverProjectWithoutPackageJson(directory);
|
|
65165
|
+
const synthesized = discoverProjectWithoutPackageJson(directory, options);
|
|
64926
65166
|
cachedProjectInfos.set(directory, synthesized);
|
|
64927
65167
|
return synthesized;
|
|
64928
65168
|
}
|
|
@@ -64984,8 +65224,8 @@ const discoverProject = (directory) => {
|
|
|
64984
65224
|
const tailwindVersion = tailwindcss.version;
|
|
64985
65225
|
const zodVersion = zod.version;
|
|
64986
65226
|
const projectName = packageJson.name ?? Path.basename(directory);
|
|
64987
|
-
const hasTypeScript =
|
|
64988
|
-
const sourceFileCount = countSourceFiles(directory);
|
|
65227
|
+
const hasTypeScript = isFile(Path.join(directory, "tsconfig.json"));
|
|
65228
|
+
const sourceFileCount = options.sourceFileCount ?? countSourceFiles(directory);
|
|
64989
65229
|
const hasReactNativeWorkspace = framework === "expo" || framework === "react-native" || workspaceFacts.hasReactNativeAwarePackage;
|
|
64990
65230
|
const expoVersion = hasReactNativeWorkspace ? resolveCatalogBackedDependencyVersion({
|
|
64991
65231
|
rootDirectory: directory,
|
|
@@ -65114,6 +65354,144 @@ const discoverProject = (directory) => {
|
|
|
65114
65354
|
* single source file has nothing to analyze.
|
|
65115
65355
|
*/
|
|
65116
65356
|
const isAnalyzableProject = (project) => project.reactVersion !== null || project.preactVersion !== null || project.sourceFileCount > 0;
|
|
65357
|
+
const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
|
|
65358
|
+
"effect/no-adjust-state-on-prop-change": "react-doctor/no-adjust-state-on-prop-change",
|
|
65359
|
+
"effect/no-chain-state-updates": "react-doctor/no-chain-state-updates",
|
|
65360
|
+
"effect/no-derived-state": "react-doctor/no-derived-state",
|
|
65361
|
+
"effect/no-event-handler": "react-doctor/no-event-handler",
|
|
65362
|
+
"effect/no-initialize-state": "react-doctor/no-initialize-state",
|
|
65363
|
+
"effect/no-pass-data-to-parent": "react-doctor/no-pass-data-to-parent",
|
|
65364
|
+
"effect/no-pass-live-state-to-parent": "react-doctor/no-pass-live-state-to-parent",
|
|
65365
|
+
"effect/no-reset-all-state-on-prop-change": "react-doctor/no-reset-all-state-on-prop-change",
|
|
65366
|
+
"jsx-a11y/alt-text": "react-doctor/alt-text",
|
|
65367
|
+
"jsx-a11y/anchor-ambiguous-text": "react-doctor/anchor-ambiguous-text",
|
|
65368
|
+
"jsx-a11y/anchor-has-content": "react-doctor/anchor-has-content",
|
|
65369
|
+
"jsx-a11y/anchor-is-valid": "react-doctor/anchor-is-valid",
|
|
65370
|
+
"jsx-a11y/aria-activedescendant-has-tabindex": "react-doctor/aria-activedescendant-has-tabindex",
|
|
65371
|
+
"jsx-a11y/aria-props": "react-doctor/aria-props",
|
|
65372
|
+
"jsx-a11y/aria-proptypes": "react-doctor/aria-proptypes",
|
|
65373
|
+
"jsx-a11y/aria-role": "react-doctor/aria-role",
|
|
65374
|
+
"jsx-a11y/aria-unsupported-elements": "react-doctor/aria-unsupported-elements",
|
|
65375
|
+
"jsx-a11y/autocomplete-valid": "react-doctor/autocomplete-valid",
|
|
65376
|
+
"jsx-a11y/click-events-have-key-events": "react-doctor/click-events-have-key-events",
|
|
65377
|
+
"jsx-a11y/control-has-associated-label": "react-doctor/control-has-associated-label",
|
|
65378
|
+
"jsx-a11y/heading-has-content": "react-doctor/heading-has-content",
|
|
65379
|
+
"jsx-a11y/html-has-lang": "react-doctor/html-has-lang",
|
|
65380
|
+
"jsx-a11y/iframe-has-title": "react-doctor/iframe-has-title",
|
|
65381
|
+
"jsx-a11y/img-redundant-alt": "react-doctor/img-redundant-alt",
|
|
65382
|
+
"jsx-a11y/interactive-supports-focus": "react-doctor/interactive-supports-focus",
|
|
65383
|
+
"jsx-a11y/label-has-associated-control": "react-doctor/label-has-associated-control",
|
|
65384
|
+
"jsx-a11y/lang": "react-doctor/lang",
|
|
65385
|
+
"jsx-a11y/media-has-caption": "react-doctor/media-has-caption",
|
|
65386
|
+
"jsx-a11y/mouse-events-have-key-events": "react-doctor/mouse-events-have-key-events",
|
|
65387
|
+
"jsx-a11y/no-access-key": "react-doctor/no-access-key",
|
|
65388
|
+
"jsx-a11y/no-aria-hidden-on-focusable": "react-doctor/no-aria-hidden-on-focusable",
|
|
65389
|
+
"jsx-a11y/no-autofocus": "react-doctor/no-autofocus",
|
|
65390
|
+
"jsx-a11y/no-distracting-elements": "react-doctor/no-distracting-elements",
|
|
65391
|
+
"jsx-a11y/no-interactive-element-to-noninteractive-role": "react-doctor/no-interactive-element-to-noninteractive-role",
|
|
65392
|
+
"jsx-a11y/no-noninteractive-element-interactions": "react-doctor/no-noninteractive-element-interactions",
|
|
65393
|
+
"jsx-a11y/no-noninteractive-element-to-interactive-role": "react-doctor/no-noninteractive-element-to-interactive-role",
|
|
65394
|
+
"jsx-a11y/no-noninteractive-tabindex": "react-doctor/no-noninteractive-tabindex",
|
|
65395
|
+
"jsx-a11y/no-redundant-roles": "react-doctor/no-redundant-roles",
|
|
65396
|
+
"jsx-a11y/no-static-element-interactions": "react-doctor/no-static-element-interactions",
|
|
65397
|
+
"jsx-a11y/prefer-tag-over-role": "react-doctor/prefer-tag-over-role",
|
|
65398
|
+
"jsx-a11y/role-has-required-aria-props": "react-doctor/role-has-required-aria-props",
|
|
65399
|
+
"jsx-a11y/role-supports-aria-props": "react-doctor/role-supports-aria-props",
|
|
65400
|
+
"jsx-a11y/scope": "react-doctor/scope",
|
|
65401
|
+
"jsx-a11y/tabindex-no-positive": "react-doctor/tabindex-no-positive",
|
|
65402
|
+
"react-hooks/exhaustive-deps": "react-doctor/exhaustive-deps",
|
|
65403
|
+
"react-hooks/rules-of-hooks": "react-doctor/rules-of-hooks",
|
|
65404
|
+
"react-perf/jsx-no-jsx-as-prop": "react-doctor/jsx-no-jsx-as-prop",
|
|
65405
|
+
"react-perf/jsx-no-new-array-as-prop": "react-doctor/jsx-no-new-array-as-prop",
|
|
65406
|
+
"react-perf/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
|
|
65407
|
+
"react-perf/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
|
|
65408
|
+
"react-refresh/only-export-components": "react-doctor/only-export-components",
|
|
65409
|
+
"react/button-has-type": "react-doctor/button-has-type",
|
|
65410
|
+
"react/checked-requires-onchange-or-readonly": "react-doctor/checked-requires-onchange-or-readonly",
|
|
65411
|
+
"react/display-name": "react-doctor/display-name",
|
|
65412
|
+
"react/exhaustive-deps": "react-doctor/exhaustive-deps",
|
|
65413
|
+
"react/forbid-component-props": "react-doctor/forbid-component-props",
|
|
65414
|
+
"react/forbid-dom-props": "react-doctor/forbid-dom-props",
|
|
65415
|
+
"react/forbid-elements": "react-doctor/forbid-elements",
|
|
65416
|
+
"react/forward-ref-uses-ref": "react-doctor/forward-ref-uses-ref",
|
|
65417
|
+
"react/hook-use-state": "react-doctor/hook-use-state",
|
|
65418
|
+
"react/iframe-missing-sandbox": "react-doctor/iframe-missing-sandbox",
|
|
65419
|
+
"react/jsx-boolean-value": "react-doctor/jsx-boolean-value",
|
|
65420
|
+
"react/jsx-curly-brace-presence": "react-doctor/jsx-curly-brace-presence",
|
|
65421
|
+
"react/jsx-filename-extension": "react-doctor/jsx-filename-extension",
|
|
65422
|
+
"react/jsx-fragments": "react-doctor/jsx-fragments",
|
|
65423
|
+
"react/jsx-handler-names": "react-doctor/jsx-handler-names",
|
|
65424
|
+
"react/jsx-key": "react-doctor/jsx-key",
|
|
65425
|
+
"react/jsx-max-depth": "react-doctor/jsx-max-depth",
|
|
65426
|
+
"react/jsx-no-comment-textnodes": "react-doctor/jsx-no-comment-textnodes",
|
|
65427
|
+
"react/jsx-no-constructed-context-values": "react-doctor/jsx-no-constructed-context-values",
|
|
65428
|
+
"react/jsx-no-duplicate-props": "react-doctor/jsx-no-duplicate-props",
|
|
65429
|
+
"react/jsx-no-jsx-as-prop": "react-doctor/jsx-no-jsx-as-prop",
|
|
65430
|
+
"react/jsx-no-new-array-as-prop": "react-doctor/jsx-no-new-array-as-prop",
|
|
65431
|
+
"react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
|
|
65432
|
+
"react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
|
|
65433
|
+
"react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
|
|
65434
|
+
"react/jsx-no-undef": "react-doctor/jsx-no-undef",
|
|
65435
|
+
"react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
|
|
65436
|
+
"react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
|
|
65437
|
+
"react/jsx-props-no-spread-multi": "react-doctor/jsx-props-no-spread-multi",
|
|
65438
|
+
"react/jsx-props-no-spreading": "react-doctor/jsx-props-no-spreading",
|
|
65439
|
+
"react/no-array-index-key": "react-doctor/no-array-index-key",
|
|
65440
|
+
"react/no-children-prop": "react-doctor/no-children-prop",
|
|
65441
|
+
"react/no-clone-element": "react-doctor/no-clone-element",
|
|
65442
|
+
"react/no-danger": "react-doctor/no-danger",
|
|
65443
|
+
"react/no-danger-with-children": "react-doctor/no-danger-with-children",
|
|
65444
|
+
"react/no-did-mount-set-state": "react-doctor/no-did-mount-set-state",
|
|
65445
|
+
"react/no-did-update-set-state": "react-doctor/no-did-update-set-state",
|
|
65446
|
+
"react/no-direct-mutation-state": "react-doctor/no-direct-mutation-state",
|
|
65447
|
+
"react/no-find-dom-node": "react-doctor/no-find-dom-node",
|
|
65448
|
+
"react/no-is-mounted": "react-doctor/no-is-mounted",
|
|
65449
|
+
"react/no-multi-comp": "react-doctor/no-multi-comp",
|
|
65450
|
+
"react/no-namespace": "react-doctor/no-namespace",
|
|
65451
|
+
"react/no-react-children": "react-doctor/no-react-children",
|
|
65452
|
+
"react/no-redundant-should-component-update": "react-doctor/no-redundant-should-component-update",
|
|
65453
|
+
"react/no-render-return-value": "react-doctor/no-render-return-value",
|
|
65454
|
+
"react/no-set-state": "react-doctor/no-set-state",
|
|
65455
|
+
"react/no-string-refs": "react-doctor/no-string-refs",
|
|
65456
|
+
"react/no-this-in-sfc": "react-doctor/no-this-in-sfc",
|
|
65457
|
+
"react/no-unescaped-entities": "react-doctor/no-unescaped-entities",
|
|
65458
|
+
"react/no-unknown-property": "react-doctor/no-unknown-property",
|
|
65459
|
+
"react/no-unsafe": "react-doctor/no-unsafe",
|
|
65460
|
+
"react/no-unstable-nested-components": "react-doctor/no-unstable-nested-components",
|
|
65461
|
+
"react/no-will-update-set-state": "react-doctor/no-will-update-set-state",
|
|
65462
|
+
"react/only-export-components": "react-doctor/only-export-components",
|
|
65463
|
+
"react/prefer-es6-class": "react-doctor/prefer-es6-class",
|
|
65464
|
+
"react/prefer-function-component": "react-doctor/prefer-function-component",
|
|
65465
|
+
"react/react-in-jsx-scope": "react-doctor/react-in-jsx-scope",
|
|
65466
|
+
"react/require-render-return": "react-doctor/require-render-return",
|
|
65467
|
+
"react/rules-of-hooks": "react-doctor/rules-of-hooks",
|
|
65468
|
+
"react/self-closing-comp": "react-doctor/self-closing-comp",
|
|
65469
|
+
"react/state-in-constructor": "react-doctor/state-in-constructor",
|
|
65470
|
+
"react/style-prop-object": "react-doctor/style-prop-object",
|
|
65471
|
+
"react/void-dom-elements-no-children": "react-doctor/void-dom-elements-no-children"
|
|
65472
|
+
};
|
|
65473
|
+
const NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS = /* @__PURE__ */ new Map();
|
|
65474
|
+
for (const [legacyRuleKey, nativeRuleKey] of Object.entries(LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY)) {
|
|
65475
|
+
const aliases = NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.get(nativeRuleKey) ?? [];
|
|
65476
|
+
aliases.push(legacyRuleKey);
|
|
65477
|
+
NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.set(nativeRuleKey, aliases);
|
|
65478
|
+
}
|
|
65479
|
+
const getLegacyRuleKeysForNative = (ruleKey) => NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.get(ruleKey) ?? [];
|
|
65480
|
+
const canonicalizeRuleKey = (ruleKey) => {
|
|
65481
|
+
const nativeRuleKey = LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY[ruleKey];
|
|
65482
|
+
return typeof nativeRuleKey === "string" ? nativeRuleKey : ruleKey;
|
|
65483
|
+
};
|
|
65484
|
+
const isReactDoctorShortIdOf = (bareRuleKey, qualifiedRuleKey) => !bareRuleKey.includes("/") && qualifiedRuleKey === `react-doctor/${bareRuleKey}`;
|
|
65485
|
+
const isSameRuleKey = (candidateRuleKey, targetRuleKey) => {
|
|
65486
|
+
const canonicalCandidate = canonicalizeRuleKey(candidateRuleKey);
|
|
65487
|
+
const canonicalTarget = canonicalizeRuleKey(targetRuleKey);
|
|
65488
|
+
if (canonicalCandidate === canonicalTarget) return true;
|
|
65489
|
+
return isReactDoctorShortIdOf(canonicalCandidate, canonicalTarget) || isReactDoctorShortIdOf(canonicalTarget, canonicalCandidate);
|
|
65490
|
+
};
|
|
65491
|
+
const getEquivalentRuleKeys = (ruleKey) => {
|
|
65492
|
+
const nativeRuleKey = canonicalizeRuleKey(ruleKey);
|
|
65493
|
+
return [nativeRuleKey, ...getLegacyRuleKeysForNative(nativeRuleKey)];
|
|
65494
|
+
};
|
|
65117
65495
|
const messageFromUnknown = (error) => error instanceof Error ? error.message : String(error);
|
|
65118
65496
|
var InvalidGlobPatternError = class extends Error {
|
|
65119
65497
|
pattern;
|
|
@@ -65167,6 +65545,11 @@ const warnConfigIssue = (message) => {
|
|
|
65167
65545
|
};
|
|
65168
65546
|
const isStringArray = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
65169
65547
|
const collectStringList = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
65548
|
+
const hasMatchingRuleOverride = (ruleIds, ruleIdentifier) => {
|
|
65549
|
+
if (ruleIds.size === 0) return true;
|
|
65550
|
+
for (const ruleId of ruleIds) if (isSameRuleKey(ruleId, ruleIdentifier)) return true;
|
|
65551
|
+
return false;
|
|
65552
|
+
};
|
|
65170
65553
|
const validateOverrideEntry = (entry, index) => {
|
|
65171
65554
|
if (!isPlainObject(entry)) {
|
|
65172
65555
|
warnConfigIssue(`ignore.overrides[${index}] must be an object with { files, rules }; ignoring this entry.`);
|
|
@@ -65207,7 +65590,7 @@ const isDiagnosticIgnoredByOverrides = (diagnostic, rootDirectory, overrides) =>
|
|
|
65207
65590
|
if (overrides.length === 0) return false;
|
|
65208
65591
|
const relativeFilePath = toRelativePath(diagnostic.filePath, rootDirectory);
|
|
65209
65592
|
const ruleIdentifier = `${diagnostic.plugin}/${diagnostic.rule}`;
|
|
65210
|
-
return overrides.some((override) => override.filePatterns.some((pattern) => pattern.test(relativeFilePath)) && (override.ruleIds
|
|
65593
|
+
return overrides.some((override) => override.filePatterns.some((pattern) => pattern.test(relativeFilePath)) && hasMatchingRuleOverride(override.ruleIds, ruleIdentifier));
|
|
65211
65594
|
};
|
|
65212
65595
|
const SEVERITY_FOR_OVERRIDE = {
|
|
65213
65596
|
error: "error",
|
|
@@ -65242,144 +65625,6 @@ const buildRuleSeverityControls = (config) => {
|
|
|
65242
65625
|
const FOREIGN_INLINE_DISABLE_PATTERN = /(?:\/\/|\/\*)[ \t]*(eslint|oxlint)-disable-(next-line|line)(?![\w-])([^\r\n]*)/;
|
|
65243
65626
|
const FOREIGN_BLOCK_DISABLE_PATTERN = /\/\*[ \t]*(eslint|oxlint)-disable(?![\w-])([^*\r\n]*)/;
|
|
65244
65627
|
const FOREIGN_BLOCK_ENABLE_PATTERN = /\/\*[ \t]*(?:eslint|oxlint)-enable(?![\w-])([^*\r\n]*)/;
|
|
65245
|
-
const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
|
|
65246
|
-
"effect/no-adjust-state-on-prop-change": "react-doctor/no-adjust-state-on-prop-change",
|
|
65247
|
-
"effect/no-chain-state-updates": "react-doctor/no-chain-state-updates",
|
|
65248
|
-
"effect/no-derived-state": "react-doctor/no-derived-state",
|
|
65249
|
-
"effect/no-event-handler": "react-doctor/no-event-handler",
|
|
65250
|
-
"effect/no-initialize-state": "react-doctor/no-initialize-state",
|
|
65251
|
-
"effect/no-pass-data-to-parent": "react-doctor/no-pass-data-to-parent",
|
|
65252
|
-
"effect/no-pass-live-state-to-parent": "react-doctor/no-pass-live-state-to-parent",
|
|
65253
|
-
"effect/no-reset-all-state-on-prop-change": "react-doctor/no-reset-all-state-on-prop-change",
|
|
65254
|
-
"jsx-a11y/alt-text": "react-doctor/alt-text",
|
|
65255
|
-
"jsx-a11y/anchor-ambiguous-text": "react-doctor/anchor-ambiguous-text",
|
|
65256
|
-
"jsx-a11y/anchor-has-content": "react-doctor/anchor-has-content",
|
|
65257
|
-
"jsx-a11y/anchor-is-valid": "react-doctor/anchor-is-valid",
|
|
65258
|
-
"jsx-a11y/aria-activedescendant-has-tabindex": "react-doctor/aria-activedescendant-has-tabindex",
|
|
65259
|
-
"jsx-a11y/aria-props": "react-doctor/aria-props",
|
|
65260
|
-
"jsx-a11y/aria-proptypes": "react-doctor/aria-proptypes",
|
|
65261
|
-
"jsx-a11y/aria-role": "react-doctor/aria-role",
|
|
65262
|
-
"jsx-a11y/aria-unsupported-elements": "react-doctor/aria-unsupported-elements",
|
|
65263
|
-
"jsx-a11y/autocomplete-valid": "react-doctor/autocomplete-valid",
|
|
65264
|
-
"jsx-a11y/click-events-have-key-events": "react-doctor/click-events-have-key-events",
|
|
65265
|
-
"jsx-a11y/control-has-associated-label": "react-doctor/control-has-associated-label",
|
|
65266
|
-
"jsx-a11y/heading-has-content": "react-doctor/heading-has-content",
|
|
65267
|
-
"jsx-a11y/html-has-lang": "react-doctor/html-has-lang",
|
|
65268
|
-
"jsx-a11y/iframe-has-title": "react-doctor/iframe-has-title",
|
|
65269
|
-
"jsx-a11y/img-redundant-alt": "react-doctor/img-redundant-alt",
|
|
65270
|
-
"jsx-a11y/interactive-supports-focus": "react-doctor/interactive-supports-focus",
|
|
65271
|
-
"jsx-a11y/label-has-associated-control": "react-doctor/label-has-associated-control",
|
|
65272
|
-
"jsx-a11y/lang": "react-doctor/lang",
|
|
65273
|
-
"jsx-a11y/media-has-caption": "react-doctor/media-has-caption",
|
|
65274
|
-
"jsx-a11y/mouse-events-have-key-events": "react-doctor/mouse-events-have-key-events",
|
|
65275
|
-
"jsx-a11y/no-access-key": "react-doctor/no-access-key",
|
|
65276
|
-
"jsx-a11y/no-aria-hidden-on-focusable": "react-doctor/no-aria-hidden-on-focusable",
|
|
65277
|
-
"jsx-a11y/no-autofocus": "react-doctor/no-autofocus",
|
|
65278
|
-
"jsx-a11y/no-distracting-elements": "react-doctor/no-distracting-elements",
|
|
65279
|
-
"jsx-a11y/no-interactive-element-to-noninteractive-role": "react-doctor/no-interactive-element-to-noninteractive-role",
|
|
65280
|
-
"jsx-a11y/no-noninteractive-element-interactions": "react-doctor/no-noninteractive-element-interactions",
|
|
65281
|
-
"jsx-a11y/no-noninteractive-element-to-interactive-role": "react-doctor/no-noninteractive-element-to-interactive-role",
|
|
65282
|
-
"jsx-a11y/no-noninteractive-tabindex": "react-doctor/no-noninteractive-tabindex",
|
|
65283
|
-
"jsx-a11y/no-redundant-roles": "react-doctor/no-redundant-roles",
|
|
65284
|
-
"jsx-a11y/no-static-element-interactions": "react-doctor/no-static-element-interactions",
|
|
65285
|
-
"jsx-a11y/prefer-tag-over-role": "react-doctor/prefer-tag-over-role",
|
|
65286
|
-
"jsx-a11y/role-has-required-aria-props": "react-doctor/role-has-required-aria-props",
|
|
65287
|
-
"jsx-a11y/role-supports-aria-props": "react-doctor/role-supports-aria-props",
|
|
65288
|
-
"jsx-a11y/scope": "react-doctor/scope",
|
|
65289
|
-
"jsx-a11y/tabindex-no-positive": "react-doctor/tabindex-no-positive",
|
|
65290
|
-
"react-hooks/exhaustive-deps": "react-doctor/exhaustive-deps",
|
|
65291
|
-
"react-hooks/rules-of-hooks": "react-doctor/rules-of-hooks",
|
|
65292
|
-
"react-perf/jsx-no-jsx-as-prop": "react-doctor/jsx-no-jsx-as-prop",
|
|
65293
|
-
"react-perf/jsx-no-new-array-as-prop": "react-doctor/jsx-no-new-array-as-prop",
|
|
65294
|
-
"react-perf/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
|
|
65295
|
-
"react-perf/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
|
|
65296
|
-
"react-refresh/only-export-components": "react-doctor/only-export-components",
|
|
65297
|
-
"react/button-has-type": "react-doctor/button-has-type",
|
|
65298
|
-
"react/checked-requires-onchange-or-readonly": "react-doctor/checked-requires-onchange-or-readonly",
|
|
65299
|
-
"react/display-name": "react-doctor/display-name",
|
|
65300
|
-
"react/exhaustive-deps": "react-doctor/exhaustive-deps",
|
|
65301
|
-
"react/forbid-component-props": "react-doctor/forbid-component-props",
|
|
65302
|
-
"react/forbid-dom-props": "react-doctor/forbid-dom-props",
|
|
65303
|
-
"react/forbid-elements": "react-doctor/forbid-elements",
|
|
65304
|
-
"react/forward-ref-uses-ref": "react-doctor/forward-ref-uses-ref",
|
|
65305
|
-
"react/hook-use-state": "react-doctor/hook-use-state",
|
|
65306
|
-
"react/iframe-missing-sandbox": "react-doctor/iframe-missing-sandbox",
|
|
65307
|
-
"react/jsx-boolean-value": "react-doctor/jsx-boolean-value",
|
|
65308
|
-
"react/jsx-curly-brace-presence": "react-doctor/jsx-curly-brace-presence",
|
|
65309
|
-
"react/jsx-filename-extension": "react-doctor/jsx-filename-extension",
|
|
65310
|
-
"react/jsx-fragments": "react-doctor/jsx-fragments",
|
|
65311
|
-
"react/jsx-handler-names": "react-doctor/jsx-handler-names",
|
|
65312
|
-
"react/jsx-key": "react-doctor/jsx-key",
|
|
65313
|
-
"react/jsx-max-depth": "react-doctor/jsx-max-depth",
|
|
65314
|
-
"react/jsx-no-comment-textnodes": "react-doctor/jsx-no-comment-textnodes",
|
|
65315
|
-
"react/jsx-no-constructed-context-values": "react-doctor/jsx-no-constructed-context-values",
|
|
65316
|
-
"react/jsx-no-duplicate-props": "react-doctor/jsx-no-duplicate-props",
|
|
65317
|
-
"react/jsx-no-jsx-as-prop": "react-doctor/jsx-no-jsx-as-prop",
|
|
65318
|
-
"react/jsx-no-new-array-as-prop": "react-doctor/jsx-no-new-array-as-prop",
|
|
65319
|
-
"react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
|
|
65320
|
-
"react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
|
|
65321
|
-
"react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
|
|
65322
|
-
"react/jsx-no-undef": "react-doctor/jsx-no-undef",
|
|
65323
|
-
"react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
|
|
65324
|
-
"react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
|
|
65325
|
-
"react/jsx-props-no-spread-multi": "react-doctor/jsx-props-no-spread-multi",
|
|
65326
|
-
"react/jsx-props-no-spreading": "react-doctor/jsx-props-no-spreading",
|
|
65327
|
-
"react/no-array-index-key": "react-doctor/no-array-index-key",
|
|
65328
|
-
"react/no-children-prop": "react-doctor/no-children-prop",
|
|
65329
|
-
"react/no-clone-element": "react-doctor/no-clone-element",
|
|
65330
|
-
"react/no-danger": "react-doctor/no-danger",
|
|
65331
|
-
"react/no-danger-with-children": "react-doctor/no-danger-with-children",
|
|
65332
|
-
"react/no-did-mount-set-state": "react-doctor/no-did-mount-set-state",
|
|
65333
|
-
"react/no-did-update-set-state": "react-doctor/no-did-update-set-state",
|
|
65334
|
-
"react/no-direct-mutation-state": "react-doctor/no-direct-mutation-state",
|
|
65335
|
-
"react/no-find-dom-node": "react-doctor/no-find-dom-node",
|
|
65336
|
-
"react/no-is-mounted": "react-doctor/no-is-mounted",
|
|
65337
|
-
"react/no-multi-comp": "react-doctor/no-multi-comp",
|
|
65338
|
-
"react/no-namespace": "react-doctor/no-namespace",
|
|
65339
|
-
"react/no-react-children": "react-doctor/no-react-children",
|
|
65340
|
-
"react/no-redundant-should-component-update": "react-doctor/no-redundant-should-component-update",
|
|
65341
|
-
"react/no-render-return-value": "react-doctor/no-render-return-value",
|
|
65342
|
-
"react/no-set-state": "react-doctor/no-set-state",
|
|
65343
|
-
"react/no-string-refs": "react-doctor/no-string-refs",
|
|
65344
|
-
"react/no-this-in-sfc": "react-doctor/no-this-in-sfc",
|
|
65345
|
-
"react/no-unescaped-entities": "react-doctor/no-unescaped-entities",
|
|
65346
|
-
"react/no-unknown-property": "react-doctor/no-unknown-property",
|
|
65347
|
-
"react/no-unsafe": "react-doctor/no-unsafe",
|
|
65348
|
-
"react/no-unstable-nested-components": "react-doctor/no-unstable-nested-components",
|
|
65349
|
-
"react/no-will-update-set-state": "react-doctor/no-will-update-set-state",
|
|
65350
|
-
"react/only-export-components": "react-doctor/only-export-components",
|
|
65351
|
-
"react/prefer-es6-class": "react-doctor/prefer-es6-class",
|
|
65352
|
-
"react/prefer-function-component": "react-doctor/prefer-function-component",
|
|
65353
|
-
"react/react-in-jsx-scope": "react-doctor/react-in-jsx-scope",
|
|
65354
|
-
"react/require-render-return": "react-doctor/require-render-return",
|
|
65355
|
-
"react/rules-of-hooks": "react-doctor/rules-of-hooks",
|
|
65356
|
-
"react/self-closing-comp": "react-doctor/self-closing-comp",
|
|
65357
|
-
"react/state-in-constructor": "react-doctor/state-in-constructor",
|
|
65358
|
-
"react/style-prop-object": "react-doctor/style-prop-object",
|
|
65359
|
-
"react/void-dom-elements-no-children": "react-doctor/void-dom-elements-no-children"
|
|
65360
|
-
};
|
|
65361
|
-
const NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS = /* @__PURE__ */ new Map();
|
|
65362
|
-
for (const [legacyRuleKey, nativeRuleKey] of Object.entries(LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY)) {
|
|
65363
|
-
const aliases = NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.get(nativeRuleKey) ?? [];
|
|
65364
|
-
aliases.push(legacyRuleKey);
|
|
65365
|
-
NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.set(nativeRuleKey, aliases);
|
|
65366
|
-
}
|
|
65367
|
-
const getLegacyRuleKeysForNative = (ruleKey) => NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.get(ruleKey) ?? [];
|
|
65368
|
-
const canonicalizeRuleKey = (ruleKey) => {
|
|
65369
|
-
const nativeRuleKey = LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY[ruleKey];
|
|
65370
|
-
return typeof nativeRuleKey === "string" ? nativeRuleKey : ruleKey;
|
|
65371
|
-
};
|
|
65372
|
-
const isReactDoctorShortIdOf = (bareRuleKey, qualifiedRuleKey) => !bareRuleKey.includes("/") && qualifiedRuleKey === `react-doctor/${bareRuleKey}`;
|
|
65373
|
-
const isSameRuleKey = (candidateRuleKey, targetRuleKey) => {
|
|
65374
|
-
const canonicalCandidate = canonicalizeRuleKey(candidateRuleKey);
|
|
65375
|
-
const canonicalTarget = canonicalizeRuleKey(targetRuleKey);
|
|
65376
|
-
if (canonicalCandidate === canonicalTarget) return true;
|
|
65377
|
-
return isReactDoctorShortIdOf(canonicalCandidate, canonicalTarget) || isReactDoctorShortIdOf(canonicalTarget, canonicalCandidate);
|
|
65378
|
-
};
|
|
65379
|
-
const getEquivalentRuleKeys = (ruleKey) => {
|
|
65380
|
-
const nativeRuleKey = canonicalizeRuleKey(ruleKey);
|
|
65381
|
-
return [nativeRuleKey, ...getLegacyRuleKeysForNative(nativeRuleKey)];
|
|
65382
|
-
};
|
|
65383
65628
|
const stripDescriptionTail = (ruleList) => {
|
|
65384
65629
|
const descriptionMatch = ruleList.match(/(?:^|\s)--\s/);
|
|
65385
65630
|
if (!descriptionMatch || descriptionMatch.index === void 0) return ruleList;
|
|
@@ -66030,12 +66275,8 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
66030
66275
|
if (rule.tags.includes("migration-hint")) return false;
|
|
66031
66276
|
return getFileContext(diagnostic.filePath) !== "production";
|
|
66032
66277
|
};
|
|
66033
|
-
const
|
|
66034
|
-
for (const
|
|
66035
|
-
return false;
|
|
66036
|
-
};
|
|
66037
|
-
const isAppOnlyRule = (ruleIdentifier) => {
|
|
66038
|
-
for (const appOnlyRuleKey of APP_ONLY_RULE_KEYS) if (isSameRuleKey(appOnlyRuleKey, ruleIdentifier)) return true;
|
|
66278
|
+
const matchesRuleKey = (ruleIdentifier, candidates) => {
|
|
66279
|
+
for (const candidate of candidates) if (isSameRuleKey(candidate, ruleIdentifier)) return true;
|
|
66039
66280
|
return false;
|
|
66040
66281
|
};
|
|
66041
66282
|
const isRnRawTextSuppressedByConfig = (diagnostic) => {
|
|
@@ -66077,12 +66318,13 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
66077
66318
|
if (explicitSeverityOverride === "off") return suppress(current, "config");
|
|
66078
66319
|
if (explicitSeverityOverride !== void 0) current = restampSeverity(current, explicitSeverityOverride);
|
|
66079
66320
|
}
|
|
66321
|
+
const ruleIdentifier = `${current.plugin}/${current.rule}`;
|
|
66080
66322
|
if (explicitRuleOverride === void 0) {
|
|
66081
|
-
if (
|
|
66323
|
+
if (matchesRuleKey(ruleIdentifier, APP_ONLY_RULE_KEYS) && isLibraryFile(current.filePath)) return null;
|
|
66082
66324
|
}
|
|
66083
66325
|
if (!showWarnings && current.severity === "warning" && explicitSeverityOverride !== "warn") return null;
|
|
66084
66326
|
if (userConfig) {
|
|
66085
|
-
if (
|
|
66327
|
+
if (matchesRuleKey(ruleIdentifier, ignoredRules)) return suppress(current, "config");
|
|
66086
66328
|
if (isFileIgnoredByPatterns(current.filePath, rootDirectory, ignoredFilePatterns)) return null;
|
|
66087
66329
|
if (isDiagnosticIgnoredByOverrides(current, rootDirectory, compiledOverrides)) return suppress(current, "override");
|
|
66088
66330
|
if (isRnRawTextSuppressedByConfig(current)) return null;
|
|
@@ -66091,7 +66333,6 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
66091
66333
|
if (respectInlineDisables && current.line > 0) {
|
|
66092
66334
|
const lines = getFileLines(current.filePath);
|
|
66093
66335
|
if (lines) {
|
|
66094
|
-
const ruleIdentifier = `${current.plugin}/${current.rule}`;
|
|
66095
66336
|
const evaluation = evaluateSuppression(lines, current.line - 1, ruleIdentifier);
|
|
66096
66337
|
if (evaluation.isSuppressed) return suppress(current, evaluation.isForeignDirective ? "foreign-inline" : "inline");
|
|
66097
66338
|
if (evaluation.nearMissHint) current = {
|
|
@@ -66367,7 +66608,8 @@ const readSystemFacts$1 = () => ({
|
|
|
66367
66608
|
/**
|
|
66368
66609
|
* Auto lint-worker count: the smaller of the (cgroup-CPU-aware) core count and
|
|
66369
66610
|
* the number of `PER_WORKER_MEM_BUDGET_BYTES` workers that fit in available
|
|
66370
|
-
* memory,
|
|
66611
|
+
* memory, and the measured automatic parallel-efficiency ceiling, then clamped
|
|
66612
|
+
* to `[MIN, HARD_MAX]` by `resolveScanConcurrency`.
|
|
66371
66613
|
*
|
|
66372
66614
|
* `os.availableParallelism()` already respects cgroup CPU quotas, so the core
|
|
66373
66615
|
* term needs no help. Available memory is `os.totalmem()` floored by the cgroup
|
|
@@ -66383,7 +66625,7 @@ const readSystemFacts$1 = () => ({
|
|
|
66383
66625
|
const resolveAutoScanConcurrency = (facts = readSystemFacts$1()) => {
|
|
66384
66626
|
const availableMemoryBytes = Math.min(facts.totalMemoryBytes, facts.cgroupMemoryLimitBytes ?? Number.POSITIVE_INFINITY);
|
|
66385
66627
|
const memoryBoundedWorkers = Math.floor(availableMemoryBytes / PER_WORKER_MEM_BUDGET_BYTES);
|
|
66386
|
-
return resolveScanConcurrency(Math.min(facts.availableCores, memoryBoundedWorkers));
|
|
66628
|
+
return resolveScanConcurrency(Math.min(facts.availableCores, memoryBoundedWorkers, 10));
|
|
66387
66629
|
};
|
|
66388
66630
|
const resolveLintBatchOrdering = () => {
|
|
66389
66631
|
return process.env["REACT_DOCTOR_LINT_BATCH_ORDERING"]?.trim().toLowerCase() === "arrival" ? "arrival" : "cost";
|
|
@@ -66396,24 +66638,22 @@ const resolveLintBatchOrdering = () => {
|
|
|
66396
66638
|
*/
|
|
66397
66639
|
var OxlintSpawnTimeoutMs = class extends Reference("react-doctor/OxlintSpawnTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_OXLINT_SPAWN_TIMEOUT_MS", OXLINT_SPAWN_TIMEOUT_MS) }) {};
|
|
66398
66640
|
/**
|
|
66399
|
-
* Effect-side cap on the lint phase.
|
|
66400
|
-
*
|
|
66641
|
+
* Optional Effect-side cap on the lint phase. Unbounded unless explicitly
|
|
66642
|
+
* configured through the env var or a test layer.
|
|
66401
66643
|
* Tests override via `Layer.succeed(LintPhaseTimeoutMs, ...)`.
|
|
66402
66644
|
*/
|
|
66403
|
-
var LintPhaseTimeoutMs = class extends Reference("react-doctor/LintPhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_LINT_PHASE_TIMEOUT_MS",
|
|
66645
|
+
var LintPhaseTimeoutMs = class extends Reference("react-doctor/LintPhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_LINT_PHASE_TIMEOUT_MS", null) }) {};
|
|
66404
66646
|
/**
|
|
66405
|
-
* Effect-side cap on the dead-code phase
|
|
66406
|
-
*
|
|
66407
|
-
* type-heavy projects; tests override via
|
|
66647
|
+
* Optional Effect-side cap on the dead-code phase. Unbounded unless explicitly
|
|
66648
|
+
* configured through the env var or a test layer. Tests override via
|
|
66408
66649
|
* `Layer.succeed(DeadCodePhaseTimeoutMs, ...)`.
|
|
66409
66650
|
*/
|
|
66410
|
-
var DeadCodePhaseTimeoutMs = class extends Reference("react-doctor/DeadCodePhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_DEAD_CODE_PHASE_TIMEOUT_MS",
|
|
66651
|
+
var DeadCodePhaseTimeoutMs = class extends Reference("react-doctor/DeadCodePhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_DEAD_CODE_PHASE_TIMEOUT_MS", null) }) {};
|
|
66411
66652
|
/**
|
|
66412
|
-
*
|
|
66413
|
-
*
|
|
66414
|
-
* large repos; tests override via `Layer.succeed(ScanDeadlineMs, ...)`.
|
|
66653
|
+
* Optional overall scan deadline. Unbounded unless explicitly configured
|
|
66654
|
+
* through the env var or a test layer.
|
|
66415
66655
|
*/
|
|
66416
|
-
var ScanDeadlineMs = class extends Reference("react-doctor/ScanDeadlineMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_SCAN_DEADLINE_MS",
|
|
66656
|
+
var ScanDeadlineMs = class extends Reference("react-doctor/ScanDeadlineMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_SCAN_DEADLINE_MS", null) }) {};
|
|
66417
66657
|
/**
|
|
66418
66658
|
* Wall-clock budget for the supply-chain check when it runs on a background
|
|
66419
66659
|
* fiber overlapping the lint pass. Reads from the env var on startup so the
|
|
@@ -66486,14 +66726,14 @@ var DeadCodeOverlap = class extends Reference("react-doctor/DeadCodeOverlap", {
|
|
|
66486
66726
|
/**
|
|
66487
66727
|
* How the full-scan lint pass plans its file batches. `"cost"` (the default)
|
|
66488
66728
|
* builds size-balanced LPT batches (`planLintBatches`): the same mandatory
|
|
66489
|
-
* batch count as greedy chunking
|
|
66490
|
-
*
|
|
66729
|
+
* batch count as greedy chunking, but every batch gets an even share of files
|
|
66730
|
+
* AND bytes, so no full chunk is a straggler while
|
|
66491
66731
|
* the remainder-batch worker idles — and the heavy files are SPREAD across
|
|
66492
66732
|
* batches, the precondition the old sort-desc-then-chunk-100 `cost` mode
|
|
66493
66733
|
* lacked (it packed the heaviest files into one wave-1 straggler batch,
|
|
66494
66734
|
* measurably regressing size-skewed repos, which is why it never earned the
|
|
66495
66735
|
* default). `"arrival"` (`REACT_DOCTOR_LINT_BATCH_ORDERING=arrival`) is the
|
|
66496
|
-
* rollback hatch to plain greedy
|
|
66736
|
+
* rollback hatch to plain greedy fixed-size chunking in discovery order. Tests
|
|
66497
66737
|
* override via `Layer.succeed(LintBatchOrdering, ...)`. Diff / staged scans
|
|
66498
66738
|
* never reach this — they pass user-scoped `includePaths` that skip discovery
|
|
66499
66739
|
* and stay in arrival order; only the full-scan branch reads it.
|
|
@@ -66588,6 +66828,7 @@ const DEFAULT_SURFACE_EXCLUDED_TAGS = {
|
|
|
66588
66828
|
score: ["design"],
|
|
66589
66829
|
ciFailure: ["design"]
|
|
66590
66830
|
};
|
|
66831
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
66591
66832
|
const VALID_RULE_SEVERITIES = [
|
|
66592
66833
|
"error",
|
|
66593
66834
|
"warn",
|
|
@@ -66630,7 +66871,6 @@ const SURFACE_CONTROL_FIELD_NAMES = [
|
|
|
66630
66871
|
];
|
|
66631
66872
|
const isIncludedFileContext = (value) => VALID_INCLUDED_FILE_CONTEXTS.some((fileContext) => fileContext === value);
|
|
66632
66873
|
const SEVERITY_FIELD_NAMES = ["rules", "categories"];
|
|
66633
|
-
const isPlainObject$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
66634
66874
|
const formatType = (value) => typeof value === "string" ? `"${value}"` : typeof value;
|
|
66635
66875
|
const isRuleSeverity = (value) => typeof value === "string" && VALID_RULE_SEVERITIES.includes(value);
|
|
66636
66876
|
const coerceMaybeBooleanString = (fieldName, value) => {
|
|
@@ -66657,8 +66897,45 @@ const validateStringArrayField = (fieldName, value) => {
|
|
|
66657
66897
|
return false;
|
|
66658
66898
|
});
|
|
66659
66899
|
};
|
|
66900
|
+
const validateIgnoreOverride = (rawOverride, index) => {
|
|
66901
|
+
const fieldName = `ignore.overrides[${index}]`;
|
|
66902
|
+
if (!isRecord(rawOverride)) {
|
|
66903
|
+
warnConfigIssue(`config field "${fieldName}" must be an object (got ${typeof rawOverride}); ignoring this override.`);
|
|
66904
|
+
return;
|
|
66905
|
+
}
|
|
66906
|
+
const files = validateStringArrayField(`${fieldName}.files`, rawOverride.files);
|
|
66907
|
+
if (files === void 0) return void 0;
|
|
66908
|
+
const validatedOverride = { files };
|
|
66909
|
+
if (rawOverride.rules !== void 0) {
|
|
66910
|
+
const rules = validateStringArrayField(`${fieldName}.rules`, rawOverride.rules);
|
|
66911
|
+
if (rules !== void 0) validatedOverride.rules = rules;
|
|
66912
|
+
}
|
|
66913
|
+
return validatedOverride;
|
|
66914
|
+
};
|
|
66915
|
+
const validateIgnoreField = (rawIgnore) => {
|
|
66916
|
+
if (!isRecord(rawIgnore)) {
|
|
66917
|
+
warnConfigIssue(`config field "ignore" must be an object (got ${typeof rawIgnore}); ignoring this field.`);
|
|
66918
|
+
return;
|
|
66919
|
+
}
|
|
66920
|
+
const validatedIgnore = {};
|
|
66921
|
+
for (const fieldName of [
|
|
66922
|
+
"rules",
|
|
66923
|
+
"files",
|
|
66924
|
+
"tags"
|
|
66925
|
+
]) {
|
|
66926
|
+
if (rawIgnore[fieldName] === void 0) continue;
|
|
66927
|
+
const validatedValues = validateStringArrayField(`ignore.${fieldName}`, rawIgnore[fieldName]);
|
|
66928
|
+
if (validatedValues !== void 0) validatedIgnore[fieldName] = validatedValues;
|
|
66929
|
+
}
|
|
66930
|
+
if (rawIgnore.overrides !== void 0) if (!Array.isArray(rawIgnore.overrides)) warnConfigIssue(`config field "ignore.overrides" must be an array (got ${typeof rawIgnore.overrides}); ignoring this field.`);
|
|
66931
|
+
else validatedIgnore.overrides = rawIgnore.overrides.flatMap((rawOverride, index) => {
|
|
66932
|
+
const validatedOverride = validateIgnoreOverride(rawOverride, index);
|
|
66933
|
+
return validatedOverride ? [validatedOverride] : [];
|
|
66934
|
+
});
|
|
66935
|
+
return validatedIgnore;
|
|
66936
|
+
};
|
|
66660
66937
|
const validateSurfaceControls = (surface, rawControls) => {
|
|
66661
|
-
if (!
|
|
66938
|
+
if (!isRecord(rawControls)) {
|
|
66662
66939
|
warnConfigIssue(`config field "surfaces.${surface}" must be an object (got ${typeof rawControls}); ignoring this surface.`);
|
|
66663
66940
|
return;
|
|
66664
66941
|
}
|
|
@@ -66682,7 +66959,7 @@ const validateSurfaceControls = (surface, rawControls) => {
|
|
|
66682
66959
|
return validatedSurfaceControls;
|
|
66683
66960
|
};
|
|
66684
66961
|
const validateSurfacesField = (rawSurfaces) => {
|
|
66685
|
-
if (!
|
|
66962
|
+
if (!isRecord(rawSurfaces)) {
|
|
66686
66963
|
warnConfigIssue(`config field "surfaces" must be an object (got ${typeof rawSurfaces}); ignoring this field.`);
|
|
66687
66964
|
return;
|
|
66688
66965
|
}
|
|
@@ -66698,7 +66975,7 @@ const validateSurfacesField = (rawSurfaces) => {
|
|
|
66698
66975
|
return validated;
|
|
66699
66976
|
};
|
|
66700
66977
|
const validateSeverityMap = (fieldName, rawMap, keysAreCategories = false) => {
|
|
66701
|
-
if (!
|
|
66978
|
+
if (!isRecord(rawMap)) {
|
|
66702
66979
|
warnConfigIssue(`config field "${fieldName}" must be an object (got ${typeof rawMap}); ignoring this field.`);
|
|
66703
66980
|
return;
|
|
66704
66981
|
}
|
|
@@ -66732,6 +67009,7 @@ const validateConfigTypes = (config) => {
|
|
|
66732
67009
|
for (const fieldName of BOOLEAN_FIELD_NAMES) applyFieldValidator(config, validated, fieldName, (value) => coerceMaybeBooleanString(fieldName, value));
|
|
66733
67010
|
for (const fieldName of STRING_FIELD_NAMES) applyFieldValidator(config, validated, fieldName, (value) => validateString(fieldName, value));
|
|
66734
67011
|
for (const fieldName of STRING_ARRAY_FIELD_NAMES) applyFieldValidator(config, validated, fieldName, (value) => validateStringArrayField(fieldName, value));
|
|
67012
|
+
applyFieldValidator(config, validated, "ignore", validateIgnoreField);
|
|
66735
67013
|
applyFieldValidator(config, validated, "surfaces", validateSurfacesField);
|
|
66736
67014
|
for (const fieldName of SEVERITY_FIELD_NAMES) applyFieldValidator(config, validated, fieldName, (value) => validateSeverityMap(fieldName, value, fieldName === "categories"));
|
|
66737
67015
|
applyFieldValidator(config, validated, "plugins", (value) => validateStringArrayField("plugins", value));
|
|
@@ -67031,6 +67309,10 @@ const dedupeRelatedDiagnostics = (diagnostics) => {
|
|
|
67031
67309
|
}
|
|
67032
67310
|
return uniqueDiagnostics;
|
|
67033
67311
|
};
|
|
67312
|
+
const isPathInsideDirectory = (childAbsolutePath, parentAbsolutePath) => {
|
|
67313
|
+
const relativePath = Path.relative(parentAbsolutePath, childAbsolutePath);
|
|
67314
|
+
return Boolean(relativePath) && !relativePath.startsWith("..") && !Path.isAbsolute(relativePath);
|
|
67315
|
+
};
|
|
67034
67316
|
const compareStrings = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
67035
67317
|
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
67318
|
const getDirectDependencyNames = (packageJson) => new Set([...Object.keys(packageJson.dependencies ?? {}), ...Object.keys(packageJson.devDependencies ?? {})]);
|
|
@@ -68392,7 +68674,7 @@ const collectScriptMotionEvidence = (sourceFile, typeChecker, program) => {
|
|
|
68392
68674
|
if (calleeEvidence.isReducedMotionHook && isExpressionValueConsumed(node)) evidence.hasReducedMotionHandling = true;
|
|
68393
68675
|
}
|
|
68394
68676
|
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
68395
|
-
const tagEvidence = ts.
|
|
68677
|
+
const tagEvidence = ts.isIdentifier(node.tagName) || ts.isPropertyAccessExpression(node.tagName) ? resolveMotionExpressionEvidence(node.tagName, typeChecker, program) : EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
68396
68678
|
if (tagEvidence.isMotionComponent || tagEvidence.isMotionComponentFactory) evidence.hasMotionUse = true;
|
|
68397
68679
|
if (tagEvidence.isMotionConfig && jsxElementHasReducedMotionConfiguration(node.attributes, typeChecker)) evidence.hasReducedMotionHandling = true;
|
|
68398
68680
|
}
|
|
@@ -68607,7 +68889,7 @@ const readScannedFile = (candidate) => {
|
|
|
68607
68889
|
return null;
|
|
68608
68890
|
}
|
|
68609
68891
|
};
|
|
68610
|
-
function* collectSecurityScanFiles(rootDirectory) {
|
|
68892
|
+
function* collectSecurityScanFiles(rootDirectory, excludedDirectories = /* @__PURE__ */ new Set()) {
|
|
68611
68893
|
const priorityCandidates = [];
|
|
68612
68894
|
const artifactCandidates = [];
|
|
68613
68895
|
const otherCandidates = [];
|
|
@@ -68622,7 +68904,7 @@ function* collectSecurityScanFiles(rootDirectory) {
|
|
|
68622
68904
|
for (const entry of readDirectoryEntries(current.absolutePath)) {
|
|
68623
68905
|
const absolutePath = Path.join(current.absolutePath, entry.name);
|
|
68624
68906
|
if (entry.isDirectory()) {
|
|
68625
|
-
if (!SKIPPED_DIRECTORY_NAMES.has(entry.name)) stack.push({
|
|
68907
|
+
if (!SKIPPED_DIRECTORY_NAMES.has(entry.name) && !excludedDirectories.has(Path.resolve(absolutePath))) stack.push({
|
|
68626
68908
|
absolutePath,
|
|
68627
68909
|
depth: current.depth + 1
|
|
68628
68910
|
});
|
|
@@ -68803,10 +69085,8 @@ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhe
|
|
|
68803
69085
|
}
|
|
68804
69086
|
return true;
|
|
68805
69087
|
};
|
|
69088
|
+
const remainingDeadlineBudgetMs = (deadlineEpochMs) => Math.max(deadlineEpochMs - Date.now(), 0);
|
|
68806
69089
|
const shouldEnableRuleByDefaultStatus = (options) => options.defaultEnabled !== false || options.hasExplicitOverride === true || options.includeTagDefaults && options.hasIncludedTags;
|
|
68807
|
-
const yieldToEventLoop = () => new Promise((resolve) => {
|
|
68808
|
-
setImmediate(resolve);
|
|
68809
|
-
});
|
|
68810
69090
|
const createSecurityScanSession = (rootDirectory, options) => {
|
|
68811
69091
|
const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
|
|
68812
69092
|
const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
|
|
@@ -68859,19 +69139,35 @@ const createSecurityScanSession = (rootDirectory, options) => {
|
|
|
68859
69139
|
};
|
|
68860
69140
|
};
|
|
68861
69141
|
const checkSecurityScanCooperative = async (rootDirectory, options = {}) => {
|
|
69142
|
+
const throwIfScanAborted = () => {
|
|
69143
|
+
options.signal?.throwIfAborted();
|
|
69144
|
+
};
|
|
69145
|
+
const didReachDeadline = () => {
|
|
69146
|
+
const hasDeadlineElapsed = options.deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(options.deadlineEpochMs) === 0;
|
|
69147
|
+
if (hasDeadlineElapsed) options.onDeadlineExceeded?.();
|
|
69148
|
+
return hasDeadlineElapsed;
|
|
69149
|
+
};
|
|
69150
|
+
throwIfScanAborted();
|
|
68862
69151
|
const session = createSecurityScanSession(rootDirectory, options);
|
|
68863
69152
|
if (session === null) return [];
|
|
69153
|
+
if (didReachDeadline()) return [];
|
|
68864
69154
|
let sliceStartedAt = performance.now();
|
|
68865
|
-
for (const file of collectSecurityScanFiles(rootDirectory)) {
|
|
69155
|
+
for (const file of collectSecurityScanFiles(rootDirectory, options.excludedDirectories)) {
|
|
69156
|
+
throwIfScanAborted();
|
|
69157
|
+
if (didReachDeadline()) return session.diagnostics;
|
|
68866
69158
|
if (file === null) {
|
|
68867
69159
|
if (performance.now() - sliceStartedAt >= 12) {
|
|
68868
69160
|
await yieldToEventLoop();
|
|
69161
|
+
throwIfScanAborted();
|
|
69162
|
+
if (didReachDeadline()) return session.diagnostics;
|
|
68869
69163
|
sliceStartedAt = performance.now();
|
|
68870
69164
|
}
|
|
68871
69165
|
continue;
|
|
68872
69166
|
}
|
|
68873
69167
|
for (const _ruleStep of session.scanFileByRule(file)) if (performance.now() - sliceStartedAt >= 12) {
|
|
68874
69168
|
await yieldToEventLoop();
|
|
69169
|
+
throwIfScanAborted();
|
|
69170
|
+
if (didReachDeadline()) return session.diagnostics;
|
|
68875
69171
|
sliceStartedAt = performance.now();
|
|
68876
69172
|
}
|
|
68877
69173
|
}
|
|
@@ -69034,25 +69330,18 @@ const collectIgnorePatterns = (rootDirectory) => {
|
|
|
69034
69330
|
cachedPatternsByRoot.set(rootDirectory, patterns);
|
|
69035
69331
|
return patterns;
|
|
69036
69332
|
};
|
|
69037
|
-
const
|
|
69038
|
-
const KNIP_JSON_FILENAME = "knip.json";
|
|
69039
|
-
const readJsonFileSafe = (filePath) => {
|
|
69040
|
-
let rawContents;
|
|
69041
|
-
try {
|
|
69042
|
-
rawContents = fs.readFileSync(filePath, "utf-8");
|
|
69043
|
-
} catch {
|
|
69044
|
-
return null;
|
|
69045
|
-
}
|
|
69333
|
+
const failOpenReadJson = (filePath, fallback) => {
|
|
69046
69334
|
try {
|
|
69047
|
-
return JSON.parse(
|
|
69335
|
+
return JSON.parse(NFS.readFileSync(filePath, "utf8"));
|
|
69048
69336
|
} catch {
|
|
69049
|
-
return
|
|
69337
|
+
return fallback;
|
|
69050
69338
|
}
|
|
69051
69339
|
};
|
|
69340
|
+
const KNIP_JSON_FILENAME = "knip.json";
|
|
69052
69341
|
const readKnipConfig = (rootDirectory) => {
|
|
69053
|
-
const knipJson =
|
|
69342
|
+
const knipJson = failOpenReadJson(path.join(rootDirectory, KNIP_JSON_FILENAME), null);
|
|
69054
69343
|
if (isRecord(knipJson)) return knipJson;
|
|
69055
|
-
const packageJson =
|
|
69344
|
+
const packageJson = failOpenReadJson(path.join(rootDirectory, "package.json"), null);
|
|
69056
69345
|
const packageKnipConfig = isRecord(packageJson) ? packageJson.knip : null;
|
|
69057
69346
|
return isRecord(packageKnipConfig) ? packageKnipConfig : null;
|
|
69058
69347
|
};
|
|
@@ -69100,13 +69389,6 @@ const atomicWriteJson = (filePath, value) => {
|
|
|
69100
69389
|
return;
|
|
69101
69390
|
}
|
|
69102
69391
|
};
|
|
69103
|
-
const failOpenReadJson = (filePath, fallback) => {
|
|
69104
|
-
try {
|
|
69105
|
-
return JSON.parse(NFS.readFileSync(filePath, "utf8"));
|
|
69106
|
-
} catch {
|
|
69107
|
-
return fallback;
|
|
69108
|
-
}
|
|
69109
|
-
};
|
|
69110
69392
|
const hashFileContents = (filePath) => {
|
|
69111
69393
|
try {
|
|
69112
69394
|
return crypto.createHash("sha1").update(NFS.readFileSync(filePath)).digest("hex");
|
|
@@ -69785,7 +70067,6 @@ const isDiagnosticOnSurface = (diagnostic, surface, config) => {
|
|
|
69785
70067
|
return true;
|
|
69786
70068
|
};
|
|
69787
70069
|
const filterDiagnosticsForSurface = (diagnostics, surface, config) => diagnostics.filter((diagnostic) => isDiagnosticOnSurface(diagnostic, surface, config));
|
|
69788
|
-
const remainingDeadlineBudgetMs = (deadlineEpochMs) => Math.max(deadlineEpochMs - Date.now(), 0);
|
|
69789
70070
|
/**
|
|
69790
70071
|
* Budget for the dead-code phase, scaled to the work. deslop's graph build is
|
|
69791
70072
|
* CPU-bound and roughly linear in file count, so a fixed 120s cap is too tight
|
|
@@ -69793,25 +70074,28 @@ const remainingDeadlineBudgetMs = (deadlineEpochMs) => Math.max(deadlineEpochMs
|
|
|
69793
70074
|
* tipped over by any concurrent load — silently dropping every dead-code
|
|
69794
70075
|
* finding. Scaling the budget with file count (and inversely with the core
|
|
69795
70076
|
* 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.
|
|
70077
|
+
* reclaims a genuinely wedged worker.
|
|
69798
70078
|
*/
|
|
69799
70079
|
const resolveDeadCodeTimeout = (input) => {
|
|
69800
70080
|
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
|
-
};
|
|
70081
|
+
return { workerTimeoutMs: Math.min(DEAD_CODE_TIMEOUT_CEILING_MS, Math.max(DEAD_CODE_WORKER_TIMEOUT_MS, Math.ceil(input.sourceFileCount * 30 * coreShareFactor))) };
|
|
69806
70082
|
};
|
|
69807
|
-
const resolveLintIncludePaths = (rootDirectory, userConfig) => {
|
|
70083
|
+
const resolveLintIncludePaths = (rootDirectory, userConfig, sourceFiles) => {
|
|
69808
70084
|
if (!Array.isArray(userConfig?.ignore?.files) || userConfig.ignore.files.length === 0) return;
|
|
69809
70085
|
const ignoredPatterns = compileIgnoredFilePatterns(userConfig);
|
|
69810
|
-
return listSourceFiles(rootDirectory).filter((filePath) => {
|
|
70086
|
+
return (sourceFiles ?? listSourceFiles(rootDirectory)).filter((filePath) => {
|
|
69811
70087
|
if (!isLintableSourceFile(filePath)) return false;
|
|
69812
70088
|
return !isFileIgnoredByPatterns(filePath, rootDirectory, ignoredPatterns);
|
|
69813
70089
|
});
|
|
69814
70090
|
};
|
|
70091
|
+
const filterPathsOutsideDirectories = (input) => {
|
|
70092
|
+
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}/`)));
|
|
70093
|
+
if (excludedPrefixes.length === 0) return [...input.relativePaths];
|
|
70094
|
+
return input.relativePaths.filter((relativePath) => {
|
|
70095
|
+
const normalizedRelativePath = relativePath.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
70096
|
+
return !excludedPrefixes.some((excludedPrefix) => normalizedRelativePath === excludedPrefix || normalizedRelativePath.startsWith(`${excludedPrefix}/`));
|
|
70097
|
+
});
|
|
70098
|
+
};
|
|
69815
70099
|
var Config = class Config extends Service()("react-doctor/Config") {
|
|
69816
70100
|
static layerNode = effect(Config, gen(function* () {
|
|
69817
70101
|
const cache = yield* make$3({
|
|
@@ -69873,6 +70157,7 @@ var Files = class Files extends Service()("react-doctor/Files") {
|
|
|
69873
70157
|
static layerNode = succeed$3(Files, Files.of({
|
|
69874
70158
|
readLines: (input) => sync(() => createNodeReadFileLinesSync(input.rootDirectory)(input.filePath)),
|
|
69875
70159
|
listSourceFiles: (rootDirectory) => sync(() => listSourceFiles(rootDirectory)),
|
|
70160
|
+
listSourceFilesCooperative: (input) => promise(() => listSourceFilesCooperative(input.rootDirectory, input.signal)),
|
|
69876
70161
|
isFile: (filePath) => sync(() => isFile(filePath)),
|
|
69877
70162
|
isDirectory: (filePath) => sync(() => isDirectory(filePath))
|
|
69878
70163
|
}));
|
|
@@ -69899,6 +70184,16 @@ var Files = class Files extends Service()("react-doctor/Files") {
|
|
|
69899
70184
|
}
|
|
69900
70185
|
return files;
|
|
69901
70186
|
}),
|
|
70187
|
+
listSourceFilesCooperative: (input) => sync(() => {
|
|
70188
|
+
const rootDirectory = input.rootDirectory;
|
|
70189
|
+
const prefix = rootDirectory.endsWith("/") ? rootDirectory : `${rootDirectory}/`;
|
|
70190
|
+
const files = [];
|
|
70191
|
+
for (const absolute of tree.keys()) {
|
|
70192
|
+
if (!absolute.startsWith(prefix)) continue;
|
|
70193
|
+
files.push(absolute.slice(prefix.length));
|
|
70194
|
+
}
|
|
70195
|
+
return files;
|
|
70196
|
+
}),
|
|
69902
70197
|
isFile: (filePath) => sync(() => tree.has(filePath)),
|
|
69903
70198
|
isDirectory: (filePath) => sync(() => {
|
|
69904
70199
|
const prefix = filePath.endsWith("/") ? filePath : `${filePath}/`;
|
|
@@ -70363,7 +70658,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
70363
70658
|
changedFiles: yield* mergeUntracked(directory, splitNullSeparated(diff.stdout), includeUntracked),
|
|
70364
70659
|
isCurrentChanges: false
|
|
70365
70660
|
};
|
|
70366
|
-
}).pipe(withSpan("Git.diffSelection")),
|
|
70661
|
+
}).pipe(catchReasons("ReactDoctorError", { GitInvocationFailed: () => succeed$2(null) }, (_reason, error) => fail$4(error)), withSpan("Git.diffSelection")),
|
|
70367
70662
|
stagedFilePaths: (directory) => runGit(directory, [
|
|
70368
70663
|
"diff",
|
|
70369
70664
|
"--no-ext-diff",
|
|
@@ -70474,7 +70769,7 @@ const batchIncludePaths = (baseArgs, includePaths) => {
|
|
|
70474
70769
|
for (const filePath of includePaths) {
|
|
70475
70770
|
const entryLength = filePath.length + 1;
|
|
70476
70771
|
const exceedsArgLength = currentBatch.length > 0 && currentBatchLength + entryLength > 24e3;
|
|
70477
|
-
const exceedsFileCount = currentBatch.length >=
|
|
70772
|
+
const exceedsFileCount = currentBatch.length >= 200;
|
|
70478
70773
|
if (exceedsArgLength || exceedsFileCount) {
|
|
70479
70774
|
batches.push(currentBatch);
|
|
70480
70775
|
currentBatch = [];
|
|
@@ -70579,6 +70874,33 @@ const detectUserLintConfigPaths = (rootDirectory) => {
|
|
|
70579
70874
|
return [];
|
|
70580
70875
|
};
|
|
70581
70876
|
const DISABLE_DIRECTIVE_PATTERN = /(eslint|oxlint)-disable/;
|
|
70877
|
+
const neutralizedFileLeases = /* @__PURE__ */ new Map();
|
|
70878
|
+
const activeNeutralizationInitializations = /* @__PURE__ */ new Set();
|
|
70879
|
+
const directoriesOverlap = (left, right) => {
|
|
70880
|
+
const isWithin = (parent, candidate) => {
|
|
70881
|
+
const relativePath = Path.relative(parent, candidate);
|
|
70882
|
+
return relativePath.length === 0 || !relativePath.startsWith(`..${Path.sep}`) && relativePath !== ".." && !Path.isAbsolute(relativePath);
|
|
70883
|
+
};
|
|
70884
|
+
return isWithin(left, right) || isWithin(right, left);
|
|
70885
|
+
};
|
|
70886
|
+
const withOverlappingInitializationLock = async (rootDirectory, operation) => {
|
|
70887
|
+
const blockers = [...activeNeutralizationInitializations].filter((initialization) => directoriesOverlap(initialization.rootDirectory, rootDirectory)).map((initialization) => initialization.done);
|
|
70888
|
+
let release;
|
|
70889
|
+
const initialization = {
|
|
70890
|
+
rootDirectory,
|
|
70891
|
+
done: new Promise((resolve) => {
|
|
70892
|
+
release = resolve;
|
|
70893
|
+
})
|
|
70894
|
+
};
|
|
70895
|
+
activeNeutralizationInitializations.add(initialization);
|
|
70896
|
+
await Promise.all(blockers);
|
|
70897
|
+
try {
|
|
70898
|
+
return await operation();
|
|
70899
|
+
} finally {
|
|
70900
|
+
activeNeutralizationInitializations.delete(initialization);
|
|
70901
|
+
release();
|
|
70902
|
+
}
|
|
70903
|
+
};
|
|
70582
70904
|
const findFilesWithDisableDirectivesViaGit = async (rootDirectory, includePaths) => {
|
|
70583
70905
|
const program = gen(function* () {
|
|
70584
70906
|
return yield* (yield* Git).grep({
|
|
@@ -70621,34 +70943,84 @@ const findFilesWithDisableDirectivesViaFilesystem = (rootDirectory, includePaths
|
|
|
70621
70943
|
};
|
|
70622
70944
|
const findFilesWithDisableDirectives = async (rootDirectory, includePaths) => await findFilesWithDisableDirectivesViaGit(rootDirectory, includePaths) ?? findFilesWithDisableDirectivesViaFilesystem(rootDirectory, includePaths);
|
|
70623
70945
|
const neutralizeContent = (content) => content.replaceAll("eslint-disable", "eslint_disable").replaceAll("oxlint-disable", "oxlint_disable");
|
|
70624
|
-
const
|
|
70625
|
-
const
|
|
70626
|
-
const
|
|
70946
|
+
const collectNeutralizationCandidatePaths = (rootDirectory, discoveredRelativePaths, includePaths) => {
|
|
70947
|
+
const resolvedRootDirectory = NFS.realpathSync(rootDirectory);
|
|
70948
|
+
const requestedPaths = includePaths && includePaths.length > 0 ? new Set(includePaths.flatMap((includePath) => {
|
|
70949
|
+
try {
|
|
70950
|
+
return [NFS.realpathSync(Path.resolve(resolvedRootDirectory, includePath))];
|
|
70951
|
+
} catch {
|
|
70952
|
+
return [];
|
|
70953
|
+
}
|
|
70954
|
+
})) : null;
|
|
70955
|
+
const candidatePaths = /* @__PURE__ */ new Set();
|
|
70956
|
+
for (const relativePath of discoveredRelativePaths) try {
|
|
70957
|
+
candidatePaths.add(NFS.realpathSync(Path.resolve(resolvedRootDirectory, relativePath)));
|
|
70958
|
+
} catch {
|
|
70959
|
+
continue;
|
|
70960
|
+
}
|
|
70961
|
+
for (const leasedPath of neutralizedFileLeases.keys()) {
|
|
70962
|
+
const relativePath = Path.relative(resolvedRootDirectory, leasedPath);
|
|
70963
|
+
if (!(relativePath.length === 0 || !relativePath.startsWith(`..${Path.sep}`) && relativePath !== ".." && !Path.isAbsolute(relativePath)) || requestedPaths && !requestedPaths.has(leasedPath)) continue;
|
|
70964
|
+
candidatePaths.add(leasedPath);
|
|
70965
|
+
}
|
|
70966
|
+
return candidatePaths;
|
|
70967
|
+
};
|
|
70968
|
+
const neutralizeDisableDirectives = async (rootDirectory, includePaths, options = {}) => {
|
|
70969
|
+
const resolvedRootDirectory = NFS.realpathSync(rootDirectory);
|
|
70970
|
+
const leasedPaths = /* @__PURE__ */ new Set();
|
|
70627
70971
|
let isRestored = false;
|
|
70628
70972
|
const restore = () => {
|
|
70629
70973
|
if (isRestored) return;
|
|
70630
70974
|
isRestored = true;
|
|
70631
|
-
for (const
|
|
70632
|
-
|
|
70633
|
-
|
|
70634
|
-
|
|
70975
|
+
for (const absolutePath of leasedPaths) {
|
|
70976
|
+
const lease = neutralizedFileLeases.get(absolutePath);
|
|
70977
|
+
if (!lease) continue;
|
|
70978
|
+
lease.referenceCount -= 1;
|
|
70979
|
+
if (lease.referenceCount > 0) continue;
|
|
70980
|
+
neutralizedFileLeases.delete(absolutePath);
|
|
70981
|
+
try {
|
|
70982
|
+
NFS.writeFileSync(absolutePath, lease.originalContent);
|
|
70983
|
+
} catch (error) {
|
|
70984
|
+
process.stderr.write(`[react-doctor] Failed to restore inline disable directives in ${absolutePath}: ${messageFromUnknown(error)}\n[react-doctor] Run: git checkout -- ${absolutePath}\n`);
|
|
70985
|
+
}
|
|
70635
70986
|
}
|
|
70636
70987
|
};
|
|
70637
70988
|
const onExit = () => restore();
|
|
70638
70989
|
process.once("exit", onExit);
|
|
70639
|
-
|
|
70640
|
-
|
|
70990
|
+
const leaseCandidatePath = (absolutePath) => {
|
|
70991
|
+
if (leasedPaths.has(absolutePath)) return;
|
|
70992
|
+
const existingLease = neutralizedFileLeases.get(absolutePath);
|
|
70993
|
+
if (existingLease) {
|
|
70994
|
+
existingLease.referenceCount += 1;
|
|
70995
|
+
leasedPaths.add(absolutePath);
|
|
70996
|
+
return;
|
|
70997
|
+
}
|
|
70641
70998
|
let originalContent;
|
|
70642
70999
|
try {
|
|
70643
71000
|
originalContent = NFS.readFileSync(absolutePath, "utf-8");
|
|
70644
71001
|
} catch {
|
|
70645
|
-
|
|
71002
|
+
return;
|
|
70646
71003
|
}
|
|
70647
71004
|
const neutralizedContent = neutralizeContent(originalContent);
|
|
70648
71005
|
if (neutralizedContent !== originalContent) {
|
|
70649
|
-
originalContents.set(absolutePath, originalContent);
|
|
70650
71006
|
NFS.writeFileSync(absolutePath, neutralizedContent);
|
|
71007
|
+
neutralizedFileLeases.set(absolutePath, {
|
|
71008
|
+
originalContent,
|
|
71009
|
+
referenceCount: 1
|
|
71010
|
+
});
|
|
71011
|
+
leasedPaths.add(absolutePath);
|
|
70651
71012
|
}
|
|
71013
|
+
};
|
|
71014
|
+
try {
|
|
71015
|
+
await withOverlappingInitializationLock(resolvedRootDirectory, async () => {
|
|
71016
|
+
for (const absolutePath of collectNeutralizationCandidatePaths(resolvedRootDirectory, [], includePaths)) if (neutralizedFileLeases.has(absolutePath)) leaseCandidatePath(absolutePath);
|
|
71017
|
+
const discoveredRelativePaths = await (options.findFiles ?? findFilesWithDisableDirectives)(resolvedRootDirectory, includePaths);
|
|
71018
|
+
for (const absolutePath of collectNeutralizationCandidatePaths(resolvedRootDirectory, discoveredRelativePaths, includePaths)) leaseCandidatePath(absolutePath);
|
|
71019
|
+
});
|
|
71020
|
+
} catch (error) {
|
|
71021
|
+
restore();
|
|
71022
|
+
process.removeListener("exit", onExit);
|
|
71023
|
+
throw error;
|
|
70652
71024
|
}
|
|
70653
71025
|
return () => {
|
|
70654
71026
|
restore();
|
|
@@ -70821,7 +71193,7 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
70821
71193
|
}
|
|
70822
71194
|
return enabled;
|
|
70823
71195
|
};
|
|
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 }) => {
|
|
71196
|
+
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
71197
|
const hasIncludedTags = includedTags.size > 0;
|
|
70826
71198
|
const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
|
|
70827
71199
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
@@ -70885,7 +71257,8 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
70885
71257
|
}))
|
|
70886
71258
|
} : {},
|
|
70887
71259
|
...project.shopifyFlashListMajorVersion !== null ? { shopifyFlashListMajorVersion: project.shopifyFlashListMajorVersion } : {},
|
|
70888
|
-
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {}
|
|
71260
|
+
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {},
|
|
71261
|
+
...projectIndexModuleSources !== void 0 ? { projectIndexModuleSources: [...projectIndexModuleSources] } : {}
|
|
70889
71262
|
} },
|
|
70890
71263
|
rules: {
|
|
70891
71264
|
...reactCompilerRules,
|
|
@@ -71134,11 +71507,17 @@ const collectUnpluginAutoImportGlobalScopes = ({ rootDirectory, candidateFiles }
|
|
|
71134
71507
|
return scopes.some((scope) => scope.names.length > 0) ? scopes : [];
|
|
71135
71508
|
};
|
|
71136
71509
|
const validateDiagnostic$1 = decodeUnknownSync(Diagnostic);
|
|
71510
|
+
const decodeDiagnostic = (raw) => {
|
|
71511
|
+
const diagnostic = validateDiagnostic$1(raw);
|
|
71512
|
+
return {
|
|
71513
|
+
...diagnostic,
|
|
71514
|
+
relatedLocations: diagnostic.relatedLocations?.map((location) => ({ ...location }))
|
|
71515
|
+
};
|
|
71516
|
+
};
|
|
71137
71517
|
const decodeFileDiagnostics = (raw) => {
|
|
71138
71518
|
if (!Array.isArray(raw)) return null;
|
|
71139
71519
|
try {
|
|
71140
|
-
|
|
71141
|
-
return raw;
|
|
71520
|
+
return raw.map((entry) => decodeDiagnostic(entry));
|
|
71142
71521
|
} catch {
|
|
71143
71522
|
return null;
|
|
71144
71523
|
}
|
|
@@ -72370,6 +72749,12 @@ const buildProfiledNodeArguments = (input) => [
|
|
|
72370
72749
|
...input.heapProfileDirectory ? ["--heap-prof", `--heap-prof-dir=${input.heapProfileDirectory}`] : [],
|
|
72371
72750
|
...input.argumentsList
|
|
72372
72751
|
];
|
|
72752
|
+
const lowerChildProcessPriority = (processId) => {
|
|
72753
|
+
if (processId === void 0) return;
|
|
72754
|
+
try {
|
|
72755
|
+
OS.setPriority(processId, OS.constants.priority.PRIORITY_BELOW_NORMAL);
|
|
72756
|
+
} catch {}
|
|
72757
|
+
};
|
|
72373
72758
|
const SANITIZED_ENV = buildOxlintChildEnv(process.env);
|
|
72374
72759
|
/**
|
|
72375
72760
|
* Spawn one oxlint subprocess with hard ceilings on wall time and
|
|
@@ -72408,6 +72793,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLIN
|
|
|
72408
72793
|
"pipe"
|
|
72409
72794
|
]
|
|
72410
72795
|
});
|
|
72796
|
+
lowerChildProcessPriority(child.pid);
|
|
72411
72797
|
const onAbort = () => {
|
|
72412
72798
|
child.kill("SIGKILL");
|
|
72413
72799
|
reject(new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) }));
|
|
@@ -72530,7 +72916,7 @@ const isParallelismRelatedSpawnError = (error) => {
|
|
|
72530
72916
|
* loop with a slimmer config in that case.
|
|
72531
72917
|
*/
|
|
72532
72918
|
const spawnLintBatches = async (input) => {
|
|
72533
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, sourceMapByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth =
|
|
72919
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, sourceMapByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 9, signal, deadlineEpochMs } = input;
|
|
72534
72920
|
const resolveSourcePath = (filePath) => {
|
|
72535
72921
|
const absoluteFilePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory, filePath);
|
|
72536
72922
|
return sourcePathByLintPath?.get(Path.normalize(absoluteFilePath)) ?? filePath;
|
|
@@ -72538,6 +72924,12 @@ const spawnLintBatches = async (input) => {
|
|
|
72538
72924
|
const requestedConcurrency = resolveScanConcurrency(input.concurrency ?? 1);
|
|
72539
72925
|
let rescueDeadlineEpochMs;
|
|
72540
72926
|
const isPastDeadline = () => deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(deadlineEpochMs) === 0 || rescueDeadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(rescueDeadlineEpochMs) === 0;
|
|
72927
|
+
const resolveSpawnTimeoutMs = () => {
|
|
72928
|
+
const deadlineBudgets = [deadlineEpochMs, rescueDeadlineEpochMs].filter((deadline) => deadline !== void 0).map(remainingDeadlineBudgetMs);
|
|
72929
|
+
if (deadlineBudgets.length === 0) return spawnTimeoutMs;
|
|
72930
|
+
const remainingDeadlineMs = Math.min(...deadlineBudgets);
|
|
72931
|
+
return spawnTimeoutMs === void 0 ? remainingDeadlineMs : Math.min(spawnTimeoutMs, remainingDeadlineMs);
|
|
72932
|
+
};
|
|
72541
72933
|
const runBatchPass = async (concurrency, passBatches, passOnFileProgress) => {
|
|
72542
72934
|
const totalFileCount = passBatches.reduce((sum, batch) => sum + batch.length, 0);
|
|
72543
72935
|
const allDiagnostics = [];
|
|
@@ -72555,12 +72947,13 @@ const spawnLintBatches = async (input) => {
|
|
|
72555
72947
|
const batchArgs = [...baseArgs, ...batch];
|
|
72556
72948
|
try {
|
|
72557
72949
|
const spawnBatch = () => {
|
|
72558
|
-
|
|
72950
|
+
const effectiveSpawnTimeoutMs = resolveSpawnTimeoutMs();
|
|
72951
|
+
if (effectiveSpawnTimeoutMs === 0) {
|
|
72559
72952
|
deadlineSkippedFiles.push(...batch);
|
|
72560
72953
|
batchState.deadlineSkippedFileCount += batch.length;
|
|
72561
72954
|
return Promise.resolve(null);
|
|
72562
72955
|
}
|
|
72563
|
-
return spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath,
|
|
72956
|
+
return spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, effectiveSpawnTimeoutMs, outputMaxBytes, signal, () => {
|
|
72564
72957
|
if (batchState.didStart) return;
|
|
72565
72958
|
batchState.didStart = true;
|
|
72566
72959
|
startedFileCount += batchState.initialFileCount;
|
|
@@ -72715,11 +73108,36 @@ const validateRuleRegistration = () => {
|
|
|
72715
73108
|
].filter((entry) => entry !== null).join("; ");
|
|
72716
73109
|
console.warn(`[react-doctor] rule-registration drift: ${detail}`);
|
|
72717
73110
|
};
|
|
73111
|
+
const PROJECT_INDEX_MODULE_SOURCES = [
|
|
73112
|
+
"next/og",
|
|
73113
|
+
"@vercel/og",
|
|
73114
|
+
"satori",
|
|
73115
|
+
"remotion"
|
|
73116
|
+
];
|
|
73117
|
+
const collectProjectIndexModuleSources = async (rootDirectory, candidateFiles) => {
|
|
73118
|
+
const foundModuleSources = /* @__PURE__ */ new Set();
|
|
73119
|
+
let sliceStartedAt = performance.now();
|
|
73120
|
+
for (const candidateFile of candidateFiles) {
|
|
73121
|
+
let sourceBuffer;
|
|
73122
|
+
try {
|
|
73123
|
+
sourceBuffer = NFS.readFileSync(Path.isAbsolute(candidateFile) ? candidateFile : Path.resolve(rootDirectory, candidateFile));
|
|
73124
|
+
} catch {
|
|
73125
|
+
continue;
|
|
73126
|
+
}
|
|
73127
|
+
for (const moduleSource of PROJECT_INDEX_MODULE_SOURCES) if (sourceBuffer.includes(`"${moduleSource}"`) || sourceBuffer.includes(`'${moduleSource}'`)) foundModuleSources.add(moduleSource);
|
|
73128
|
+
if (foundModuleSources.size === PROJECT_INDEX_MODULE_SOURCES.length) break;
|
|
73129
|
+
if (performance.now() - sliceStartedAt >= 12) {
|
|
73130
|
+
await yieldToEventLoop();
|
|
73131
|
+
sliceStartedAt = performance.now();
|
|
73132
|
+
}
|
|
73133
|
+
}
|
|
73134
|
+
return [...foundModuleSources].sort();
|
|
73135
|
+
};
|
|
72718
73136
|
/**
|
|
72719
73137
|
* Balanced LPT (longest-processing-time-first) lint batch planner. Where
|
|
72720
|
-
* `batchIncludePaths` greedily fills
|
|
72721
|
-
* remainder batch
|
|
72722
|
-
*
|
|
73138
|
+
* `batchIncludePaths` greedily fills fixed-size batches and leaves a small
|
|
73139
|
+
* remainder batch, so the parallel pool's wall clock is set by whichever
|
|
73140
|
+
* full chunk happened to collect the most work while
|
|
72723
73141
|
* the remainder's worker idles), this planner keeps the SAME mandatory batch
|
|
72724
73142
|
* count — `ceil(files / OXLINT_MAX_FILES_PER_BATCH)`, the JS-plugin
|
|
72725
73143
|
* perf-cliff / native-binding SIGABRT guard — and assigns files largest-first,
|
|
@@ -72748,7 +73166,7 @@ const validateRuleRegistration = () => {
|
|
|
72748
73166
|
*/
|
|
72749
73167
|
const planLintBatches = ({ baseArgs, files, sizeByFile }) => {
|
|
72750
73168
|
if (files.length === 0) return [];
|
|
72751
|
-
const batchCount = Math.ceil(files.length /
|
|
73169
|
+
const batchCount = Math.ceil(files.length / 200);
|
|
72752
73170
|
const maxFilesPerBatch = Math.ceil(files.length / batchCount);
|
|
72753
73171
|
const baseArgsLengthChars = estimateArgsLength(baseArgs);
|
|
72754
73172
|
const descendingSizeIndexes = [...files.keys()].sort((leftIndex, rightIndex) => (sizeByFile.get(files[rightIndex]) ?? 0) - (sizeByFile.get(files[leftIndex]) ?? 0));
|
|
@@ -73277,6 +73695,7 @@ const runOxlint = async (options) => {
|
|
|
73277
73695
|
await yieldToEventLoop();
|
|
73278
73696
|
const sizedScanFiles = includePaths === void 0 ? listSourceFilesWithSize(rootDirectory) : null;
|
|
73279
73697
|
const candidateFiles = includePaths !== void 0 ? includePaths : (sizedScanFiles ?? []).map((entry) => entry.path);
|
|
73698
|
+
const projectIndexModuleSources = includePaths === void 0 && options.deadlineEpochMs === void 0 ? await collectProjectIndexModuleSources(rootDirectory, candidateFiles) : void 0;
|
|
73280
73699
|
unpluginAutoImportGlobalScopes = collectUnpluginAutoImportGlobalScopes({
|
|
73281
73700
|
rootDirectory,
|
|
73282
73701
|
candidateFiles
|
|
@@ -73299,6 +73718,7 @@ const runOxlint = async (options) => {
|
|
|
73299
73718
|
runtimeGlobals,
|
|
73300
73719
|
unpluginAutoImportGlobalScopes,
|
|
73301
73720
|
serverAuthFunctionNames,
|
|
73721
|
+
projectIndexModuleSources,
|
|
73302
73722
|
severityControls,
|
|
73303
73723
|
userPlugins,
|
|
73304
73724
|
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
@@ -73766,10 +74186,10 @@ const translateProjectInfoError = (cause, directory) => {
|
|
|
73766
74186
|
}) });
|
|
73767
74187
|
};
|
|
73768
74188
|
var Project = class Project extends Service()("react-doctor/Project") {
|
|
73769
|
-
static layerNode = succeed$3(Project, Project.of({ discover: fn("Project.discover")(function* (
|
|
74189
|
+
static layerNode = succeed$3(Project, Project.of({ discover: fn("Project.discover")(function* (input) {
|
|
73770
74190
|
return yield* try_({
|
|
73771
|
-
try: () => discoverProject(directory),
|
|
73772
|
-
catch: (cause) => translateProjectInfoError(cause, directory)
|
|
74191
|
+
try: () => discoverProject(input.directory, { sourceFileCount: input.sourceFileCount }),
|
|
74192
|
+
catch: (cause) => translateProjectInfoError(cause, input.directory)
|
|
73773
74193
|
});
|
|
73774
74194
|
}) }));
|
|
73775
74195
|
static layerOf = (projectInfo) => succeed$3(Project, Project.of({ discover: () => succeed$2(projectInfo) }));
|
|
@@ -74354,9 +74774,10 @@ const checkSupplyChain = (input) => gen(function* () {
|
|
|
74354
74774
|
* outage.
|
|
74355
74775
|
*/
|
|
74356
74776
|
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
|
-
|
|
74777
|
+
static layerNode = succeed$3(SupplyChain, SupplyChain.of({ run: (input) => unwrap(flatMap$2(SupplyChainOverlapTimeoutMs, (configuredTimeoutMs) => checkSupplyChain({
|
|
74778
|
+
rootDirectory: input.rootDirectory,
|
|
74779
|
+
userConfig: input.userConfig,
|
|
74780
|
+
totalTimeoutMs: input.timeoutMs ?? configuredTimeoutMs
|
|
74360
74781
|
})).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), withSpan("SupplyChain.run"))) }));
|
|
74361
74782
|
static layerOf = (diagnostics) => succeed$3(SupplyChain, SupplyChain.of({ run: () => fromIterable$1(diagnostics) }));
|
|
74362
74783
|
};
|
|
@@ -74391,10 +74812,6 @@ const NO_HOOKS = {
|
|
|
74391
74812
|
beforeLint: () => void_,
|
|
74392
74813
|
afterLint: () => void_
|
|
74393
74814
|
};
|
|
74394
|
-
const filterMapNullable = (transform) => fromPredicateOption((value) => {
|
|
74395
|
-
const result = transform(value);
|
|
74396
|
-
return result === null ? none() : some(result);
|
|
74397
|
-
});
|
|
74398
74815
|
const fileReader = (filesService, rootDirectory) => (filePath) => {
|
|
74399
74816
|
const lines = runSync(filesService.readLines({
|
|
74400
74817
|
filePath,
|
|
@@ -74418,7 +74835,7 @@ const formatLintFailText = (reasonTag, nodeVersion) => {
|
|
|
74418
74835
|
* The GitHub viewer-permission lookup is forked onto a background
|
|
74419
74836
|
* fiber here and joined late (it feeds score metadata, not
|
|
74420
74837
|
* diagnostics).
|
|
74421
|
-
* 2. beforeLint hook (e.g. CLI
|
|
74838
|
+
* 2. beforeLint hook (e.g. CLI records project telemetry)
|
|
74422
74839
|
* 3. environment checks (reduced-motion + pnpm hardening +
|
|
74423
74840
|
* expo/react-native), collected synchronously. The heavier
|
|
74424
74841
|
* content-regex security scan is forked instead (like supply-chain
|
|
@@ -74431,13 +74848,11 @@ const formatLintFailText = (reasonTag, nodeVersion) => {
|
|
|
74431
74848
|
* `SupplyChainOverlapTimeoutMs` (measured from fork) so a hung
|
|
74432
74849
|
* socket can't drag out its join; on timeout it fails open to no
|
|
74433
74850
|
* 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
|
|
74851
|
+
* 5. Linter.run runs; DeadCode.run forks only when
|
|
74852
|
+
* REACT_DOCTOR_DEAD_CODE_OVERLAP=on. The default "auto" and explicit
|
|
74853
|
+
* "off" paths stay sequential. The fiber is joined (or interrupted,
|
|
74854
|
+
* SIGKILLing its worker, on lint failure) before diagnostics are
|
|
74855
|
+
* concatenated. The afterLint hook
|
|
74441
74856
|
* fires between lint and dead-code. Progress spinner labels AND the
|
|
74442
74857
|
* final diagnostic / score order stay independent of execution
|
|
74443
74858
|
* order, so terminal output is identical either way; supply-chain
|
|
@@ -74472,8 +74887,28 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74472
74887
|
const partialFailuresRef = yield* LintPartialFailures;
|
|
74473
74888
|
const resolvedConfig = yield* configService.resolve(input.directory);
|
|
74474
74889
|
const scanDirectory = resolvedConfig.resolvedDirectory;
|
|
74475
|
-
const
|
|
74890
|
+
const excludedProjectDirectories = (input.excludedProjectDirectories ?? []).map((excludedDirectory) => Path.resolve(excludedDirectory)).filter((excludedDirectory) => isPathInsideDirectory(excludedDirectory, scanDirectory));
|
|
74891
|
+
const excludedProjectRelativePaths = excludedProjectDirectories.map((excludedDirectory) => Path.relative(scanDirectory, excludedDirectory).replaceAll("\\", "/"));
|
|
74892
|
+
const isExcludedProjectDiagnostic = (diagnostic) => {
|
|
74893
|
+
const relativeFilePath = toNormalizedRelativePath(diagnostic.filePath, scanDirectory);
|
|
74894
|
+
return excludedProjectRelativePaths.some((excludedRelativePath) => relativeFilePath === excludedRelativePath || relativeFilePath.startsWith(`${excludedRelativePath}/`));
|
|
74895
|
+
};
|
|
74896
|
+
const precomputedSourceFiles = input.suppressScanSummary === true || excludedProjectDirectories.length > 0 ? yield* filesService.listSourceFilesCooperative({
|
|
74897
|
+
rootDirectory: scanDirectory,
|
|
74898
|
+
signal: input.signal
|
|
74899
|
+
}) : null;
|
|
74900
|
+
const includedPrecomputedSourceFiles = precomputedSourceFiles !== null && excludedProjectDirectories.length > 0 ? filterPathsOutsideDirectories({
|
|
74901
|
+
rootDirectory: scanDirectory,
|
|
74902
|
+
relativePaths: precomputedSourceFiles,
|
|
74903
|
+
excludedDirectories: excludedProjectDirectories
|
|
74904
|
+
}) : precomputedSourceFiles;
|
|
74905
|
+
const sourceFileCount = excludedProjectDirectories.length > 0 ? includedPrecomputedSourceFiles?.length : input.precomputedSourceFileCount ?? includedPrecomputedSourceFiles?.length;
|
|
74906
|
+
const project = yield* projectService.discover({
|
|
74907
|
+
directory: scanDirectory,
|
|
74908
|
+
sourceFileCount
|
|
74909
|
+
});
|
|
74476
74910
|
if (!isAnalyzableProject(project)) return yield* new ReactDoctorError({ reason: new NoReactDependency({ directory: scanDirectory }) });
|
|
74911
|
+
const deadCodeSourceFileCount = input.retainExcludedProjectDeadCodeDiagnostics === true && precomputedSourceFiles !== null ? precomputedSourceFiles.length : project.sourceFileCount;
|
|
74477
74912
|
const [repo, sha, defaultBranch] = yield* all([
|
|
74478
74913
|
gitService.githubRepo(scanDirectory).pipe(orElseSucceed(() => null)),
|
|
74479
74914
|
gitService.headSha(scanDirectory).pipe(orElseSucceed(() => null)),
|
|
@@ -74484,11 +74919,16 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74484
74919
|
directory: scanDirectory,
|
|
74485
74920
|
repo
|
|
74486
74921
|
}).pipe(orElseSucceed(() => null)) : succeed$2(null));
|
|
74487
|
-
|
|
74488
|
-
|
|
74922
|
+
let lintIncludePaths = (input.skipExplicitIncludePathFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths])) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config, includedPrecomputedSourceFiles ?? void 0);
|
|
74923
|
+
if (excludedProjectDirectories.length > 0) lintIncludePaths = filterPathsOutsideDirectories({
|
|
74924
|
+
rootDirectory: scanDirectory,
|
|
74925
|
+
relativePaths: lintIncludePaths ?? includedPrecomputedSourceFiles ?? (yield* filesService.listSourceFiles(scanDirectory)),
|
|
74926
|
+
excludedDirectories: excludedProjectDirectories
|
|
74927
|
+
});
|
|
74928
|
+
const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? includedPrecomputedSourceFiles ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
|
|
74489
74929
|
const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
|
|
74490
74930
|
const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
|
|
74491
|
-
yield* beforeLint(project
|
|
74931
|
+
yield* beforeLint(project);
|
|
74492
74932
|
const isDiffMode = input.includePaths.length > 0;
|
|
74493
74933
|
const showWarnings = input.warnings ?? resolvedConfig.config?.warnings ?? true;
|
|
74494
74934
|
const transform = buildDiagnosticPipeline({
|
|
@@ -74498,7 +74938,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74498
74938
|
respectInlineDisables: input.respectInlineDisables,
|
|
74499
74939
|
showWarnings
|
|
74500
74940
|
});
|
|
74501
|
-
const filterPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(
|
|
74941
|
+
const filterPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(fromPredicateOption((diagnostic) => {
|
|
74942
|
+
const filteredDiagnostic = transform.apply(diagnostic);
|
|
74943
|
+
return filteredDiagnostic === null ? none() : some(filteredDiagnostic);
|
|
74944
|
+
})));
|
|
74502
74945
|
const applyPerElementPipeline = (rawStream) => filterPerElementPipeline(rawStream).pipe(tap((diagnostic) => reporterService.emit(diagnostic)));
|
|
74503
74946
|
const envCollected = yield* runCollect(applyPerElementPipeline(fromIterable$1(isDiffMode ? [] : [
|
|
74504
74947
|
...checkReducedMotion(scanDirectory),
|
|
@@ -74508,17 +74951,31 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74508
74951
|
...checkReactNativeProject(scanDirectory, project)
|
|
74509
74952
|
])));
|
|
74510
74953
|
const securityScanFailedRef = yield* make$13(false);
|
|
74511
|
-
|
|
74954
|
+
let didSecurityScanReachDeadline = false;
|
|
74955
|
+
const securityScanFiber = yield* forkChild(runCollect(applyPerElementPipeline(isDiffMode ? empty$4 : unwrap(tryPromise((signal) => checkSecurityScanCooperative(scanDirectory, {
|
|
74512
74956
|
project,
|
|
74513
74957
|
ignoredTags: input.ignoredTags,
|
|
74514
74958
|
includedTags: input.includedTags,
|
|
74515
|
-
includeTagDefaults: input.includeTagDefaults
|
|
74959
|
+
includeTagDefaults: input.includeTagDefaults,
|
|
74960
|
+
excludedDirectories: new Set(excludedProjectDirectories),
|
|
74961
|
+
deadlineEpochMs: input.deadlineEpochMs,
|
|
74962
|
+
signal,
|
|
74963
|
+
onDeadlineExceeded: () => {
|
|
74964
|
+
didSecurityScanReachDeadline = true;
|
|
74965
|
+
}
|
|
74516
74966
|
})).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), catch_$1(() => set(securityScanFailedRef, true).pipe(as(empty$4))))))).pipe(withSpan("SecurityScan.run")));
|
|
74967
|
+
const capToDeadline = (phaseTimeoutMs) => input.deadlineEpochMs === void 0 ? phaseTimeoutMs : Math.min(phaseTimeoutMs, remainingDeadlineBudgetMs(input.deadlineEpochMs));
|
|
74968
|
+
const capOptionalToDeadline = (phaseTimeoutMs) => {
|
|
74969
|
+
if (input.deadlineEpochMs === void 0) return phaseTimeoutMs;
|
|
74970
|
+
const remainingBudgetMs = remainingDeadlineBudgetMs(input.deadlineEpochMs);
|
|
74971
|
+
return phaseTimeoutMs === null ? remainingBudgetMs : Math.min(phaseTimeoutMs, remainingBudgetMs);
|
|
74972
|
+
};
|
|
74517
74973
|
const shouldRunSupplyChain = !isDiffMode || (input.supplyChainManifestChanged ?? false);
|
|
74518
|
-
const supplyChainOverlapTimeout = yield* SupplyChainOverlapTimeoutMs;
|
|
74974
|
+
const supplyChainOverlapTimeout = capToDeadline(yield* SupplyChainOverlapTimeoutMs);
|
|
74519
74975
|
const supplyChainFiber = yield* forkChild(shouldRunSupplyChain ? runCollect(applyPerElementPipeline(supplyChainService.run({
|
|
74520
74976
|
rootDirectory: scanDirectory,
|
|
74521
|
-
userConfig: resolvedConfig.config
|
|
74977
|
+
userConfig: resolvedConfig.config,
|
|
74978
|
+
timeoutMs: supplyChainOverlapTimeout
|
|
74522
74979
|
}))).pipe(map$3((diagnostics) => ({
|
|
74523
74980
|
diagnostics,
|
|
74524
74981
|
timedOut: false
|
|
@@ -74542,46 +74999,49 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74542
74999
|
const scanConcurrency = resolveScanConcurrency(yield* OxlintConcurrency);
|
|
74543
75000
|
const lintPhaseTimeoutMs = yield* LintPhaseTimeoutMs;
|
|
74544
75001
|
const deadCodePhaseTimeoutMs = yield* DeadCodePhaseTimeoutMs;
|
|
74545
|
-
const resolveDeadCodePhaseTimeoutMs = (scaledPhaseTimeoutMs) => deadCodePhaseTimeoutMs === 15e4 ? scaledPhaseTimeoutMs : deadCodePhaseTimeoutMs;
|
|
74546
75002
|
const workerCountSuffix = scanConcurrency > 1 ? ` ${highlighter.dim(`[~${scanConcurrency} workers]`)}` : "";
|
|
74547
|
-
const capToDeadline = (phaseTimeoutMs) => input.deadlineEpochMs === void 0 ? phaseTimeoutMs : Math.min(phaseTimeoutMs, remainingDeadlineBudgetMs(input.deadlineEpochMs));
|
|
74548
75003
|
const shouldRunDeadCode = input.runDeadCode && !isDiffMode && (showWarnings || deadCodeMaySurfaceWhenWarningsHidden(resolvedConfig.config));
|
|
74549
75004
|
const deadCodeOverlapMode = yield* DeadCodeOverlap;
|
|
74550
75005
|
const shouldOverlapDeadCode = shouldRunDeadCode && deadCodeOverlapMode === "on";
|
|
74551
75006
|
const deadCodeParseConcurrency = shouldOverlapDeadCode ? Math.max(1, Math.floor(scanConcurrency * DEAD_CODE_OVERLAP_PARSE_SHARE)) : void 0;
|
|
74552
75007
|
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
|
-
|
|
75008
|
+
const buildCollectDeadCode = (deadCodeTimeout) => {
|
|
75009
|
+
const collectDeadCode = runCollect(applyPerElementPipeline(deadCodeService.run({
|
|
75010
|
+
rootDirectory: scanDirectory,
|
|
75011
|
+
parseConcurrency: deadCodeParseConcurrency,
|
|
75012
|
+
workerTimeoutMs: deadCodeTimeout.workerTimeoutMs,
|
|
75013
|
+
onCacheOutcome: (didHitCache) => {
|
|
75014
|
+
deadCodeCacheHit = didHitCache;
|
|
75015
|
+
},
|
|
75016
|
+
onSummaryCacheStats: (stats) => {
|
|
75017
|
+
deadCodeSummaryCacheHits = stats.hits;
|
|
75018
|
+
deadCodeSummaryCacheMisses = stats.misses;
|
|
75019
|
+
}
|
|
75020
|
+
}).pipe(filter((diagnostic) => input.retainExcludedProjectDeadCodeDiagnostics === true || !isExcludedProjectDiagnostic(diagnostic)), catchTag("ReactDoctorError", (error) => unwrap(gen(function* () {
|
|
75021
|
+
yield* set(deadCodeFailure, {
|
|
75022
|
+
didFail: true,
|
|
75023
|
+
reason: error.message
|
|
75024
|
+
});
|
|
75025
|
+
return empty$4;
|
|
75026
|
+
}))))));
|
|
75027
|
+
const phaseTimeoutMs = deadCodeTimeout.phaseTimeoutMs;
|
|
75028
|
+
if (phaseTimeoutMs === null) return collectDeadCode;
|
|
75029
|
+
return collectDeadCode.pipe(timeoutOption(phaseTimeoutMs), flatMap$2(match$3({
|
|
75030
|
+
onNone: () => set(deadCodeFailure, {
|
|
75031
|
+
didFail: true,
|
|
75032
|
+
reason: `Dead-code analysis exceeded ${Math.round(phaseTimeoutMs / MILLISECONDS_PER_SECOND)}s and was skipped.`
|
|
75033
|
+
}).pipe(as([])),
|
|
75034
|
+
onSome: succeed$2
|
|
75035
|
+
})));
|
|
75036
|
+
};
|
|
74577
75037
|
const overlapDeadCodeTimeout = resolveDeadCodeTimeout({
|
|
74578
|
-
sourceFileCount:
|
|
75038
|
+
sourceFileCount: deadCodeSourceFileCount,
|
|
74579
75039
|
deadCodeConcurrency: deadCodeParseConcurrency ?? scanConcurrency,
|
|
74580
75040
|
fullConcurrency: scanConcurrency
|
|
74581
75041
|
});
|
|
74582
75042
|
const deadCodeFiber = shouldOverlapDeadCode ? yield* forkChild(buildCollectDeadCode({
|
|
74583
75043
|
workerTimeoutMs: overlapDeadCodeTimeout.workerTimeoutMs,
|
|
74584
|
-
phaseTimeoutMs:
|
|
75044
|
+
phaseTimeoutMs: capOptionalToDeadline(deadCodePhaseTimeoutMs)
|
|
74585
75045
|
})) : null;
|
|
74586
75046
|
const scanProgress = yield* progressService.start("Scanning...");
|
|
74587
75047
|
const scanStartTime = Date.now();
|
|
@@ -74632,7 +75092,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74632
75092
|
});
|
|
74633
75093
|
return empty$4;
|
|
74634
75094
|
}))));
|
|
74635
|
-
const
|
|
75095
|
+
const collectLintDiagnostics = runCollect(filterPerElementPipeline(shouldOverlapDeadCode ? baseLintStream.pipe(provideService(OxlintConcurrency, lintConcurrency)) : baseLintStream));
|
|
75096
|
+
const lintCollected = dedupeRelatedDiagnostics(yield* lintPhaseTimeoutMs === null ? collectLintDiagnostics : collectLintDiagnostics.pipe(timeoutOption(lintPhaseTimeoutMs), flatMap$2(match$3({
|
|
74636
75097
|
onNone: () => set(lintFailure, {
|
|
74637
75098
|
didFail: true,
|
|
74638
75099
|
reason: `Lint analysis exceeded ${lintPhaseTimeoutMs / MILLISECONDS_PER_SECOND}s and was skipped.`,
|
|
@@ -74662,13 +75123,13 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74662
75123
|
} else {
|
|
74663
75124
|
yield* scanProgress.update(`Scanned ${scannedFilesLabel}, analyzing dead code...`);
|
|
74664
75125
|
const sequentialDeadCodeTimeout = resolveDeadCodeTimeout({
|
|
74665
|
-
sourceFileCount: totalFileCount,
|
|
75126
|
+
sourceFileCount: input.retainExcludedProjectDeadCodeDiagnostics === true ? deadCodeSourceFileCount : totalFileCount,
|
|
74666
75127
|
deadCodeConcurrency: scanConcurrency,
|
|
74667
75128
|
fullConcurrency: scanConcurrency
|
|
74668
75129
|
});
|
|
74669
75130
|
deadCodeCollected = deadCodeFiber !== null ? yield* join(deadCodeFiber) : yield* buildCollectDeadCode({
|
|
74670
75131
|
workerTimeoutMs: sequentialDeadCodeTimeout.workerTimeoutMs,
|
|
74671
|
-
phaseTimeoutMs:
|
|
75132
|
+
phaseTimeoutMs: capOptionalToDeadline(deadCodePhaseTimeoutMs)
|
|
74672
75133
|
});
|
|
74673
75134
|
}
|
|
74674
75135
|
const deadCodeFailureState = lintFailureState.didFail ? {
|
|
@@ -74712,7 +75173,11 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74712
75173
|
metadata: scoreMetadata
|
|
74713
75174
|
});
|
|
74714
75175
|
const lintPartialFailures = yield* get$2(partialFailuresRef);
|
|
74715
|
-
const
|
|
75176
|
+
const didSecurityScanFail = yield* get$2(securityScanFailedRef);
|
|
75177
|
+
const securityScanFailed = didSecurityScanFail || didSecurityScanReachDeadline;
|
|
75178
|
+
let securityScanFailureReason = null;
|
|
75179
|
+
if (didSecurityScanReachDeadline) securityScanFailureReason = "Security scan reached the max scan duration; findings collected before the deadline were preserved.";
|
|
75180
|
+
else if (didSecurityScanFail) securityScanFailureReason = "Security scan failed and was skipped.";
|
|
74716
75181
|
return {
|
|
74717
75182
|
project,
|
|
74718
75183
|
userConfig: resolvedConfig.config,
|
|
@@ -74735,6 +75200,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74735
75200
|
scanConcurrency,
|
|
74736
75201
|
supplyChainOverlapTimedOut: supplyChainResult.timedOut,
|
|
74737
75202
|
securityScanFailed,
|
|
75203
|
+
securityScanFailureReason,
|
|
74738
75204
|
lintCacheHitFileCount,
|
|
74739
75205
|
lintCacheTotalFileCount,
|
|
74740
75206
|
lintSidecarReplayedFileCount,
|
|
@@ -74750,7 +75216,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74750
75216
|
"inspect.runDeadCode": input.runDeadCode,
|
|
74751
75217
|
"inspect.isCi": input.isCi,
|
|
74752
75218
|
"inspect.scoreSurface": input.scoreSurface ?? "score"
|
|
74753
|
-
} }), (scanProgram) => flatMap$2(ScanDeadlineMs, (scanDeadlineMs) =>
|
|
75219
|
+
} }), (scanProgram) => flatMap$2(ScanDeadlineMs, (scanDeadlineMs) => {
|
|
75220
|
+
if (scanDeadlineMs === null) return scanProgram;
|
|
75221
|
+
return scanProgram.pipe(timeout(scanDeadlineMs), catchTag$1("TimeoutError", () => new ReactDoctorError({ reason: new ScanDeadlineExceeded({ detail: `${scanDeadlineMs / MILLISECONDS_PER_SECOND}s elapsed` }) })));
|
|
75222
|
+
}));
|
|
74754
75223
|
const parseNodeVersion = (versionString) => {
|
|
74755
75224
|
const [major = 0, minor = 0, patch = 0] = versionString.replace(/^v/, "").trim().split(".").map(Number);
|
|
74756
75225
|
return {
|
|
@@ -74851,16 +75320,6 @@ const resolveNodeForOxlint = () => {
|
|
|
74851
75320
|
});
|
|
74852
75321
|
});
|
|
74853
75322
|
/**
|
|
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
75323
|
* Writes a set of source files (supplied by `readContent` — e.g.
|
|
74865
75324
|
* `git show <ref>:<path>` for a baseline tree, or `git show :<path>` for the
|
|
74866
75325
|
* index) into a temp tree that mirrors the project layout, copying the
|
|
@@ -74896,7 +75355,7 @@ const materializeSourceTree = (input) => gen(function* () {
|
|
|
74896
75355
|
const sourcePath = path.join(input.directory, subdirectory, configFilename);
|
|
74897
75356
|
const targetPath = path.resolve(resolvedTempDirectory, subdirectory, configFilename);
|
|
74898
75357
|
if (!isPathInsideDirectory(targetPath, resolvedTempDirectory)) continue;
|
|
74899
|
-
if (
|
|
75358
|
+
if (isFile(sourcePath) && !fs.existsSync(targetPath)) {
|
|
74900
75359
|
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
74901
75360
|
fs.cpSync(sourcePath, targetPath);
|
|
74902
75361
|
}
|
|
@@ -75135,6 +75594,7 @@ const buildJsonReport = (input) => {
|
|
|
75135
75594
|
directory: input.directory,
|
|
75136
75595
|
diff: toJsonDiff(input.diff),
|
|
75137
75596
|
projects,
|
|
75597
|
+
...input.skippedProjects && input.skippedProjects.length > 0 ? { skippedProjects: [...input.skippedProjects] } : {},
|
|
75138
75598
|
diagnostics: flattenedDiagnostics,
|
|
75139
75599
|
summary,
|
|
75140
75600
|
elapsedMilliseconds: input.totalElapsedMilliseconds,
|
|
@@ -75159,7 +75619,7 @@ const buildSkippedChecks = (input) => {
|
|
|
75159
75619
|
else if (input.lintPartialFailures.length > 0) skippedCheckReasons["lint:partial"] = input.lintPartialFailures.join("; ");
|
|
75160
75620
|
if (input.didDeadCodeFail && input.deadCodeFailureReason !== null) skippedCheckReasons["dead-code"] = input.deadCodeFailureReason;
|
|
75161
75621
|
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.";
|
|
75622
|
+
if (input.securityScanFailed) skippedCheckReasons["security-scan"] = input.securityScanFailureReason ?? "Security scan failed and was skipped.";
|
|
75163
75623
|
return {
|
|
75164
75624
|
skippedChecks,
|
|
75165
75625
|
skippedCheckReasons
|
|
@@ -75194,14 +75654,6 @@ const getDiffInfo = (directory, explicitBaseBranch, includeUntracked) => runProm
|
|
|
75194
75654
|
};
|
|
75195
75655
|
}).pipe(provide(Git.layerNode)));
|
|
75196
75656
|
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
75657
|
const createLintPhaseAbortError = () => new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) });
|
|
75206
75658
|
const createOxlintSpawnSlots = (concurrency) => createWorkerSlots({
|
|
75207
75659
|
slotCount: resolveScanConcurrency(concurrency),
|
|
@@ -75214,71 +75666,47 @@ const createOxlintSpawnSlots = (concurrency) => createWorkerSlots({
|
|
|
75214
75666
|
* untouched so the loader sees the same plain object either way.
|
|
75215
75667
|
*/
|
|
75216
75668
|
const defineConfig = (config) => config;
|
|
75217
|
-
const
|
|
75218
|
-
["HF_DATASETS_CACHE", "huggingface"],
|
|
75219
|
-
["HF_HOME", "huggingface"],
|
|
75220
|
-
["HUGGINGFACE_HUB_CACHE", "huggingface"],
|
|
75221
|
-
["SPACE_ID", "huggingface-spaces"],
|
|
75222
|
-
["CUDA_VISIBLE_DEVICES", "cuda"],
|
|
75223
|
-
["NVIDIA_VISIBLE_DEVICES", "nvidia"],
|
|
75224
|
-
["ROCR_VISIBLE_DEVICES", "rocm"],
|
|
75225
|
-
["TPU_NAME", "google-tpu"],
|
|
75669
|
+
const AI_TRAINING_BY_ENVIRONMENT_VARIABLE = [
|
|
75226
75670
|
["WANDB_RUN_ID", "wandb"],
|
|
75227
75671
|
["WANDB_SWEEP_ID", "wandb"],
|
|
75228
75672
|
["MLFLOW_RUN_ID", "mlflow"],
|
|
75229
|
-
["MLFLOW_TRACKING_URI", "mlflow"],
|
|
75230
75673
|
["COMET_EXPERIMENT_KEY", "comet"],
|
|
75231
75674
|
["NEPTUNE_RUN_ID", "neptune"],
|
|
75232
75675
|
["CLEARML_TASK_ID", "clearml"],
|
|
75233
75676
|
["DVC_STAGE", "dvc"],
|
|
75234
75677
|
["RAY_WORKER_PROCESS", "ray"],
|
|
75235
|
-
["RAY_ADDRESS", "ray"],
|
|
75236
|
-
["MUJOCO_GL", "mujoco"],
|
|
75237
|
-
["MUJOCO_PATH", "mujoco"],
|
|
75238
|
-
["GYM_DISABLE_ENV_CHECKER", "gymnasium"],
|
|
75239
75678
|
["SM_TRAINING_ENV", "sagemaker"],
|
|
75240
75679
|
["TRAINING_JOB_ARN", "sagemaker"],
|
|
75241
|
-
["SAGEMAKER_BASE_DIR", "sagemaker"],
|
|
75242
75680
|
["AZUREML_RUN_ID", "azure-ml"],
|
|
75243
|
-
["AZURE_ML_MODEL_DIR", "azure-ml"],
|
|
75244
|
-
["CLOUD_ML_PROJECT_ID", "vertex-ai"],
|
|
75245
|
-
["VERTEX_AI_LOG_LEVEL", "vertex-ai"],
|
|
75246
|
-
["DET_MASTER", "determined-ai"],
|
|
75247
|
-
["LIGHTNING_USER_ID", "lightning-ai"],
|
|
75248
75681
|
["FLYTE_INTERNAL_EXECUTION_ID", "flyte"],
|
|
75249
|
-
["ARGO_WORKFLOW_NAME", "argo-workflows"],
|
|
75250
75682
|
["KFP_POD_NAME", "kubeflow-pipelines"],
|
|
75251
75683
|
["KAGGLE_KERNEL_RUN_TYPE", "kaggle"],
|
|
75252
75684
|
["COLAB_BACKEND_VERSION", "google-colab"],
|
|
75253
|
-
["DATABRICKS_RUNTIME_VERSION", "databricks"],
|
|
75254
75685
|
["DAYTONA_WS_ID", "daytona"],
|
|
75255
|
-
["DAYTONA_WS_NAME", "daytona"],
|
|
75256
75686
|
["E2B_SANDBOX_ID", "e2b"],
|
|
75257
75687
|
["MODAL_FUNCTION_ID", "modal"],
|
|
75258
75688
|
["MODAL_TASK_ID", "modal"],
|
|
75259
75689
|
["RUNPOD_POD_ID", "runpod"],
|
|
75260
|
-
["REPLICATE_USERNAME", "replicate"],
|
|
75261
75690
|
["VAST_CONTAINERLABEL", "vast-ai"],
|
|
75262
|
-
["HARBOR_URL", "harbor"],
|
|
75263
|
-
["HARBOR_HOSTNAME", "harbor"],
|
|
75264
75691
|
["SWE_BENCH_TASK", "swe-bench"],
|
|
75265
75692
|
["SWEBENCH_TASK", "swe-bench"],
|
|
75266
75693
|
["SWE_AGENT_MODEL", "swe-agent"]
|
|
75267
75694
|
];
|
|
75268
|
-
const detectAiTrainingEnvironment = () => {
|
|
75269
|
-
for (const [
|
|
75695
|
+
const detectAiTrainingEnvironment = (environment = process.env) => {
|
|
75696
|
+
for (const [environmentVariable, label] of AI_TRAINING_BY_ENVIRONMENT_VARIABLE) if (environment[environmentVariable]?.trim()) return label;
|
|
75270
75697
|
return null;
|
|
75271
75698
|
};
|
|
75272
|
-
const
|
|
75699
|
+
const stringValues = (values) => Array.isArray(values) ? values.filter((value) => typeof value === "string") : [];
|
|
75700
|
+
const unionValues = (baseValues, overrideValues) => [...new Set([...stringValues(baseValues), ...stringValues(overrideValues)])];
|
|
75273
75701
|
const mergeIgnores = (baseIgnore, overrideIgnore) => {
|
|
75274
75702
|
const mergedIgnore = {
|
|
75275
75703
|
...baseIgnore,
|
|
75276
75704
|
...overrideIgnore
|
|
75277
75705
|
};
|
|
75278
|
-
if (baseIgnore.rules
|
|
75279
|
-
if (baseIgnore.files
|
|
75280
|
-
if (baseIgnore.tags
|
|
75281
|
-
if (baseIgnore.overrides
|
|
75706
|
+
if (baseIgnore.rules !== void 0 || overrideIgnore.rules !== void 0) mergedIgnore.rules = unionValues(baseIgnore.rules, overrideIgnore.rules);
|
|
75707
|
+
if (baseIgnore.files !== void 0 || overrideIgnore.files !== void 0) mergedIgnore.files = unionValues(baseIgnore.files, overrideIgnore.files);
|
|
75708
|
+
if (baseIgnore.tags !== void 0 || overrideIgnore.tags !== void 0) mergedIgnore.tags = unionValues(baseIgnore.tags, overrideIgnore.tags);
|
|
75709
|
+
if (baseIgnore.overrides !== void 0 || overrideIgnore.overrides !== void 0) mergedIgnore.overrides = [...Array.isArray(baseIgnore.overrides) ? baseIgnore.overrides : [], ...Array.isArray(overrideIgnore.overrides) ? overrideIgnore.overrides : []];
|
|
75282
75710
|
return mergedIgnore;
|
|
75283
75711
|
};
|
|
75284
75712
|
/**
|
|
@@ -75460,7 +75888,6 @@ const clearCaches = () => {
|
|
|
75460
75888
|
clearPackageJsonCache();
|
|
75461
75889
|
clearIgnorePatternsCache();
|
|
75462
75890
|
clearPackageRoleCache();
|
|
75463
|
-
clearAutoSuppressionCaches();
|
|
75464
75891
|
clearMinifiedFileCache();
|
|
75465
75892
|
};
|
|
75466
75893
|
const toJsonReport = (result, options) => buildJsonReport({
|
|
@@ -75487,4 +75914,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
75487
75914
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
75488
75915
|
|
|
75489
75916
|
//# sourceMappingURL=index.js.map
|
|
75490
|
-
//# debugId=
|
|
75917
|
+
//# debugId=6d2e43de-ae97-5213-b1a7-a9905ce4b1d5
|