react-doctor 0.7.4-dev.dfccac4 → 0.7.5-dev.037bd56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/cli.js +335 -88
- package/dist/index.d.ts +58 -9
- package/dist/index.js +310 -73
- package/dist/lsp.js +234 -43
- package/package.json +6 -6
package/dist/lsp.js
CHANGED
|
@@ -5,10 +5,10 @@ import * as OS from "node:os";
|
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import * as Path from "node:path";
|
|
7
7
|
import path from "node:path";
|
|
8
|
+
import reactDoctorPlugin, { 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, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
8
9
|
import * as NodeChildProcess from "node:child_process";
|
|
9
10
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
10
|
-
import
|
|
11
|
-
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
11
|
+
import ts from "typescript";
|
|
12
12
|
import { parseJSON5 } from "confbox";
|
|
13
13
|
import * as NodeUrl from "node:url";
|
|
14
14
|
import { fileURLToPath } from "node:url";
|
|
@@ -19339,6 +19339,31 @@ var Diagnostic = class extends Class("Diagnostic")({
|
|
|
19339
19339
|
relatedLocations: optional(ArraySchema(DiagnosticRelatedLocation)),
|
|
19340
19340
|
fixGroupId: optional(String$1)
|
|
19341
19341
|
}) {};
|
|
19342
|
+
var JsonReportDiagnosticV3 = class extends Class("JsonReportDiagnosticV3")({
|
|
19343
|
+
id: String$1,
|
|
19344
|
+
normalizedFilePath: String$1,
|
|
19345
|
+
filePath: String$1,
|
|
19346
|
+
plugin: String$1,
|
|
19347
|
+
rule: String$1,
|
|
19348
|
+
severity: Severity,
|
|
19349
|
+
tags: ArraySchema(String$1),
|
|
19350
|
+
title: optional(String$1),
|
|
19351
|
+
message: String$1,
|
|
19352
|
+
help: String$1,
|
|
19353
|
+
url: optional(String$1),
|
|
19354
|
+
line: Number$1,
|
|
19355
|
+
column: Number$1,
|
|
19356
|
+
offset: optional(Number$1),
|
|
19357
|
+
length: optional(Number$1),
|
|
19358
|
+
endLine: optional(Number$1),
|
|
19359
|
+
endColumn: optional(Number$1),
|
|
19360
|
+
category: String$1,
|
|
19361
|
+
matchByOccurrence: optional(Boolean$1),
|
|
19362
|
+
fileContext: optional(Literals(["test", "story"])),
|
|
19363
|
+
suppressionHint: optional(String$1),
|
|
19364
|
+
relatedLocations: optional(ArraySchema(DiagnosticRelatedLocation)),
|
|
19365
|
+
fixGroupId: optional(String$1)
|
|
19366
|
+
}) {};
|
|
19342
19367
|
/**
|
|
19343
19368
|
* Deterministic identity string for a diagnostic. Same diagnostic
|
|
19344
19369
|
* across two scans yields the same identity; lets baselines,
|
|
@@ -19352,6 +19377,7 @@ const JsonReportMode = Literals([
|
|
|
19352
19377
|
"staged",
|
|
19353
19378
|
"baseline"
|
|
19354
19379
|
]);
|
|
19380
|
+
const Framework = Literals(FRAMEWORK_TOKENS);
|
|
19355
19381
|
var JsonReportSummary = class extends Class("JsonReportSummary")({
|
|
19356
19382
|
errorCount: Number$1,
|
|
19357
19383
|
warningCount: Number$1,
|
|
@@ -19389,13 +19415,22 @@ var JsonReportProjectEntry = class extends Class("JsonReportProjectEntry")({
|
|
|
19389
19415
|
scannedFileCount: optional(Number$1),
|
|
19390
19416
|
elapsedMilliseconds: Number$1
|
|
19391
19417
|
}) {};
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
|
|
19395
|
-
|
|
19396
|
-
|
|
19397
|
-
|
|
19398
|
-
|
|
19418
|
+
var JsonReportProjectEntryV3 = class extends Class("JsonReportProjectEntryV3")({
|
|
19419
|
+
directory: String$1,
|
|
19420
|
+
packageRoot: String$1,
|
|
19421
|
+
framework: Framework,
|
|
19422
|
+
project: Unknown,
|
|
19423
|
+
diagnostics: ArraySchema(JsonReportDiagnosticV3),
|
|
19424
|
+
score: Unknown,
|
|
19425
|
+
skippedChecks: ArraySchema(String$1),
|
|
19426
|
+
skippedCheckReasons: optional(Record$1(String$1, String$1)),
|
|
19427
|
+
analyzedFiles: ArraySchema(String$1),
|
|
19428
|
+
analyzedFileCount: Number$1,
|
|
19429
|
+
complete: Boolean$1,
|
|
19430
|
+
scannedFileCount: optional(Number$1),
|
|
19431
|
+
elapsedMilliseconds: Number$1
|
|
19432
|
+
}) {};
|
|
19433
|
+
/** Original full, diff, and staged report contract. */
|
|
19399
19434
|
var JsonReportV1 = class extends Class("JsonReportV1")({
|
|
19400
19435
|
schemaVersion: Literal(1),
|
|
19401
19436
|
version: String$1,
|
|
@@ -19456,7 +19491,27 @@ var JsonReportV2 = class extends Class("JsonReportV2")({
|
|
|
19456
19491
|
elapsedMilliseconds: Number$1,
|
|
19457
19492
|
error: NullOr(JsonReportError)
|
|
19458
19493
|
}) {};
|
|
19459
|
-
|
|
19494
|
+
var JsonReportV3 = class extends Class("JsonReportV3")({
|
|
19495
|
+
schemaVersion: Literal(3),
|
|
19496
|
+
version: String$1,
|
|
19497
|
+
ok: Boolean$1,
|
|
19498
|
+
directory: String$1,
|
|
19499
|
+
mode: JsonReportMode,
|
|
19500
|
+
baselineDegraded: optional(Boolean$1),
|
|
19501
|
+
reactDetected: optional(Boolean$1),
|
|
19502
|
+
diff: NullOr(JsonReportDiffInfo),
|
|
19503
|
+
baseline: optional(JsonReportBaseline),
|
|
19504
|
+
projects: ArraySchema(JsonReportProjectEntryV3),
|
|
19505
|
+
diagnostics: ArraySchema(JsonReportDiagnosticV3),
|
|
19506
|
+
summary: JsonReportSummary,
|
|
19507
|
+
elapsedMilliseconds: Number$1,
|
|
19508
|
+
error: NullOr(JsonReportError)
|
|
19509
|
+
}) {};
|
|
19510
|
+
Union([
|
|
19511
|
+
JsonReportV1,
|
|
19512
|
+
JsonReportV2,
|
|
19513
|
+
JsonReportV3
|
|
19514
|
+
]);
|
|
19460
19515
|
//#endregion
|
|
19461
19516
|
//#region ../../node_modules/.pnpm/semver@7.7.4/node_modules/semver/internal/constants.js
|
|
19462
19517
|
var require_constants$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
|
|
@@ -33037,7 +33092,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
33037
33092
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
33038
33093
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
33039
33094
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
33040
|
-
const CORE_PACKAGE_VERSION = "0.7.
|
|
33095
|
+
const CORE_PACKAGE_VERSION = "0.7.5";
|
|
33041
33096
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
33042
33097
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
33043
33098
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -33949,6 +34004,22 @@ const isPackageJsonReanimatedAware = (packageJson) => {
|
|
|
33949
34004
|
};
|
|
33950
34005
|
return Object.hasOwn(allDependencies, REANIMATED_DEPENDENCY_NAME$1);
|
|
33951
34006
|
};
|
|
34007
|
+
const SSR_DEPENDENCY_NAMES = new Set([
|
|
34008
|
+
"@react-router/cloudflare",
|
|
34009
|
+
"@react-router/node",
|
|
34010
|
+
"@react-router/serve",
|
|
34011
|
+
"vike",
|
|
34012
|
+
"vite-plugin-ssr"
|
|
34013
|
+
]);
|
|
34014
|
+
const isPackageJsonSsrAware = (packageJson) => {
|
|
34015
|
+
const allDependencies = {
|
|
34016
|
+
...packageJson.peerDependencies,
|
|
34017
|
+
...packageJson.dependencies,
|
|
34018
|
+
...packageJson.devDependencies,
|
|
34019
|
+
...packageJson.optionalDependencies
|
|
34020
|
+
};
|
|
34021
|
+
return Object.keys(allDependencies).some((packageName) => SSR_DEPENDENCY_NAMES.has(packageName));
|
|
34022
|
+
};
|
|
33952
34023
|
const getWorkspacePatterns = (rootDirectory, packageJson) => {
|
|
33953
34024
|
const pnpmPatterns = parsePnpmWorkspacePatterns(rootDirectory);
|
|
33954
34025
|
if (pnpmPatterns.length > 0) return pnpmPatterns;
|
|
@@ -34089,6 +34160,7 @@ const evaluateManifestFacts = (facts, packageJson, directory) => {
|
|
|
34089
34160
|
}
|
|
34090
34161
|
facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
|
|
34091
34162
|
facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
|
|
34163
|
+
facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
|
|
34092
34164
|
};
|
|
34093
34165
|
const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGroup }) => {
|
|
34094
34166
|
const facts = {
|
|
@@ -34110,6 +34182,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
|
|
|
34110
34182
|
},
|
|
34111
34183
|
hasReactNativeAwarePackage: false,
|
|
34112
34184
|
hasReanimatedAwarePackage: false,
|
|
34185
|
+
hasSsrDependency: false,
|
|
34113
34186
|
reanimatedVersion: null
|
|
34114
34187
|
};
|
|
34115
34188
|
evaluateManifestFacts(facts, rootPackageJson, rootDirectory);
|
|
@@ -34349,6 +34422,7 @@ const discoverProjectWithoutPackageJson = (directory) => {
|
|
|
34349
34422
|
hasTypeScript: hasOwnTsConfig,
|
|
34350
34423
|
hasReactCompiler: false,
|
|
34351
34424
|
hasTanStackQuery: false,
|
|
34425
|
+
hasSsrDependency: false,
|
|
34352
34426
|
preactVersion: null,
|
|
34353
34427
|
preactMajorVersion: null,
|
|
34354
34428
|
hasReactNativeWorkspace: false,
|
|
@@ -34468,6 +34542,7 @@ const discoverProject = (directory) => {
|
|
|
34468
34542
|
hasTypeScript,
|
|
34469
34543
|
hasReactCompiler: detectReactCompiler(directory, packageJson),
|
|
34470
34544
|
hasTanStackQuery: hasTanStackQuery(packageJson),
|
|
34545
|
+
hasSsrDependency: workspaceFacts.hasSsrDependency,
|
|
34471
34546
|
preactVersion,
|
|
34472
34547
|
preactMajorVersion: parseReactMajor(preactVersion),
|
|
34473
34548
|
hasReactNativeWorkspace,
|
|
@@ -35543,6 +35618,14 @@ var AmbiguousProject = class extends TaggedErrorClass()("AmbiguousProject", {
|
|
|
35543
35618
|
return `Ambiguous project at ${this.directory}: found ${this.candidates.length} candidates (${this.candidates.join(", ")})`;
|
|
35544
35619
|
}
|
|
35545
35620
|
};
|
|
35621
|
+
var ProjectDiscoveryFailed = class extends TaggedErrorClass()("ProjectDiscoveryFailed", {
|
|
35622
|
+
directory: String$1,
|
|
35623
|
+
cause: Unknown
|
|
35624
|
+
}) {
|
|
35625
|
+
get message() {
|
|
35626
|
+
return `Project discovery failed for ${this.directory}: ${pretty(fail$6(this.cause))}`;
|
|
35627
|
+
}
|
|
35628
|
+
};
|
|
35546
35629
|
var DeadCodeAnalysisFailed = class extends TaggedErrorClass()("DeadCodeAnalysisFailed", { cause: Unknown }) {
|
|
35547
35630
|
get message() {
|
|
35548
35631
|
return `Dead-code analysis failed: ${pretty(fail$6(this.cause))}`;
|
|
@@ -35577,6 +35660,7 @@ const ReactDoctorErrorReason = Union([
|
|
|
35577
35660
|
ProjectNotFound,
|
|
35578
35661
|
NoReactDependency,
|
|
35579
35662
|
AmbiguousProject,
|
|
35663
|
+
ProjectDiscoveryFailed,
|
|
35580
35664
|
DeadCodeAnalysisFailed,
|
|
35581
35665
|
GitInvocationFailed,
|
|
35582
35666
|
GitBaseBranchMissing,
|
|
@@ -37203,6 +37287,12 @@ const CLIENT_ONLY_FRAMEWORKS = new Set([
|
|
|
37203
37287
|
"react-native",
|
|
37204
37288
|
"expo"
|
|
37205
37289
|
]);
|
|
37290
|
+
const SSR_FRAMEWORKS = new Set([
|
|
37291
|
+
"nextjs",
|
|
37292
|
+
"remix",
|
|
37293
|
+
"gatsby",
|
|
37294
|
+
"tanstack-start"
|
|
37295
|
+
]);
|
|
37206
37296
|
const addMajorLadder = (capabilities, name, major, earliest, latest) => {
|
|
37207
37297
|
if (major === null) return;
|
|
37208
37298
|
const cappedMajor = Math.min(major, latest);
|
|
@@ -37215,6 +37305,7 @@ const buildCapabilities = (project) => {
|
|
|
37215
37305
|
if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
|
|
37216
37306
|
if (project.expoVersion !== null) capabilities.add("expo");
|
|
37217
37307
|
if ((project.framework === "nextjs" || project.framework === "tanstack-start" || project.framework === "remix") && !project.isStaticExport) capabilities.add("server-actions");
|
|
37308
|
+
if (SSR_FRAMEWORKS.has(project.framework) || project.hasSsrDependency) capabilities.add("ssr");
|
|
37218
37309
|
if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
|
|
37219
37310
|
if (project.isStaticExport) capabilities.add("nextjs:static-export");
|
|
37220
37311
|
if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
|
|
@@ -39012,7 +39103,7 @@ const normalizeConfigForHash = (config) => {
|
|
|
39012
39103
|
if (Array.isArray(clone?.jsPlugins)) clone.jsPlugins = clone.jsPlugins.map((_, index) => `<plugin:${index}>`);
|
|
39013
39104
|
return clone;
|
|
39014
39105
|
};
|
|
39015
|
-
const computeRulesetHash = (input) => crypto.createHash("sha1").update(JSON.stringify(normalizeConfigForHash(input.config))).update("\0").update([...input.toolchainVersions].join("\0")).update("\0").update([...input.ignorePatterns].join("\n")).update("\0").update(input.tsconfigContent ?? "").digest("hex");
|
|
39106
|
+
const computeRulesetHash = (input) => crypto.createHash("sha1").update(JSON.stringify(normalizeConfigForHash(input.config))).update("\0").update([...input.toolchainVersions].join("\0")).update("\0").update([...input.ignorePatterns].join("\n")).update("\0").update(input.tsconfigContent ?? "").update("\0").update(input.respectInlineDisables ? "respect-inline-disables" : "audit-mode").digest("hex");
|
|
39016
39107
|
/**
|
|
39017
39108
|
* Loads a plugin module via the local require resolver and extracts
|
|
39018
39109
|
* `(name, ruleNames)` from either `module.exports.meta + rules` or
|
|
@@ -39048,7 +39139,7 @@ const resolveReactHooksJsPlugin = (hasReactCompiler, customRulesOnly) => {
|
|
|
39048
39139
|
} catch {
|
|
39049
39140
|
return null;
|
|
39050
39141
|
}
|
|
39051
|
-
const { ruleNames } = readPluginShape(pluginSpecifier, (
|
|
39142
|
+
const { ruleNames } = readPluginShape(pluginSpecifier, (specifier) => bundledRequire$1(specifier));
|
|
39052
39143
|
return {
|
|
39053
39144
|
entry: {
|
|
39054
39145
|
name: "react-hooks-js",
|
|
@@ -39456,6 +39547,23 @@ const resolveTsConfigRelativePath = (rootDirectory) => {
|
|
|
39456
39547
|
for (const filename of TSCONFIG_FILENAMES) if (NFS.existsSync(Path.join(rootDirectory, filename))) return `./${filename}`;
|
|
39457
39548
|
return null;
|
|
39458
39549
|
};
|
|
39550
|
+
const DERIVED_STATE_RULE_PRIORITY = new Map([
|
|
39551
|
+
["no-initialize-state", 0],
|
|
39552
|
+
["no-adjust-state-on-prop-change", 1],
|
|
39553
|
+
["no-derived-state", 2],
|
|
39554
|
+
["no-derived-state-effect", 3]
|
|
39555
|
+
]);
|
|
39556
|
+
const doDiagnosticSpansOverlap = (first, second) => {
|
|
39557
|
+
if (first.filePath !== second.filePath || first.plugin !== second.plugin) return false;
|
|
39558
|
+
if (first.offset !== void 0 && second.offset !== void 0) {
|
|
39559
|
+
const firstEnd = first.offset + Math.max(first.length ?? 1, 1);
|
|
39560
|
+
const secondEnd = second.offset + Math.max(second.length ?? 1, 1);
|
|
39561
|
+
return first.offset < secondEnd && second.offset < firstEnd;
|
|
39562
|
+
}
|
|
39563
|
+
const firstEndLine = first.endLine ?? first.line;
|
|
39564
|
+
const secondEndLine = second.endLine ?? second.line;
|
|
39565
|
+
return first.line <= secondEndLine && second.line <= firstEndLine;
|
|
39566
|
+
};
|
|
39459
39567
|
const dedupeDiagnostics = (diagnostics) => {
|
|
39460
39568
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
39461
39569
|
const uniqueDiagnostics = [];
|
|
@@ -39463,6 +39571,16 @@ const dedupeDiagnostics = (diagnostics) => {
|
|
|
39463
39571
|
const key = `${diagnostic.filePath}\u0000${diagnostic.line}\u0000${diagnostic.column}\u0000${diagnostic.plugin}\u0000${diagnostic.rule}\u0000${diagnostic.severity}\u0000${diagnostic.message}`;
|
|
39464
39572
|
if (seenKeys.has(key)) continue;
|
|
39465
39573
|
seenKeys.add(key);
|
|
39574
|
+
const priority = DERIVED_STATE_RULE_PRIORITY.get(diagnostic.rule);
|
|
39575
|
+
if (priority !== void 0) {
|
|
39576
|
+
const overlappingDiagnosticIndex = uniqueDiagnostics.findIndex((candidate) => candidate.rule !== diagnostic.rule && candidate.severity === diagnostic.severity && DERIVED_STATE_RULE_PRIORITY.has(candidate.rule) && doDiagnosticSpansOverlap(candidate, diagnostic));
|
|
39577
|
+
if (overlappingDiagnosticIndex >= 0) {
|
|
39578
|
+
const existingDiagnostic = uniqueDiagnostics[overlappingDiagnosticIndex];
|
|
39579
|
+
const existingPriority = existingDiagnostic ? DERIVED_STATE_RULE_PRIORITY.get(existingDiagnostic.rule) : void 0;
|
|
39580
|
+
if (existingPriority !== void 0 && priority < existingPriority) uniqueDiagnostics[overlappingDiagnosticIndex] = diagnostic;
|
|
39581
|
+
continue;
|
|
39582
|
+
}
|
|
39583
|
+
}
|
|
39466
39584
|
uniqueDiagnostics.push(diagnostic);
|
|
39467
39585
|
}
|
|
39468
39586
|
return uniqueDiagnostics;
|
|
@@ -40336,6 +40454,11 @@ const buildOxlintChildEnv = (sourceEnv) => {
|
|
|
40336
40454
|
if (!isCompileCacheDisabled && !isCompileCacheAlreadySet) childEnv.NODE_COMPILE_CACHE = Path.join(os.tmpdir(), NODE_COMPILE_CACHE_DIR_NAME);
|
|
40337
40455
|
return childEnv;
|
|
40338
40456
|
};
|
|
40457
|
+
const buildProfiledNodeArguments = (input) => [
|
|
40458
|
+
...input.cpuProfileDirectory ? ["--cpu-prof", `--cpu-prof-dir=${input.cpuProfileDirectory}`] : [],
|
|
40459
|
+
...input.heapProfileDirectory ? ["--heap-prof", `--heap-prof-dir=${input.heapProfileDirectory}`] : [],
|
|
40460
|
+
...input.argumentsList
|
|
40461
|
+
];
|
|
40339
40462
|
const SANITIZED_ENV = buildOxlintChildEnv(process.env);
|
|
40340
40463
|
/**
|
|
40341
40464
|
* Spawn one oxlint subprocess with hard ceilings on wall time and
|
|
@@ -40360,7 +40483,11 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLIN
|
|
|
40360
40483
|
reject(new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) }));
|
|
40361
40484
|
return;
|
|
40362
40485
|
}
|
|
40363
|
-
const child = spawn(nodeBinaryPath,
|
|
40486
|
+
const child = spawn(nodeBinaryPath, buildProfiledNodeArguments({
|
|
40487
|
+
argumentsList: args,
|
|
40488
|
+
cpuProfileDirectory: SANITIZED_ENV.REACT_DOCTOR_CPU_PROFILE_DIR,
|
|
40489
|
+
heapProfileDirectory: SANITIZED_ENV.REACT_DOCTOR_HEAP_PROFILE_DIR
|
|
40490
|
+
}), {
|
|
40364
40491
|
cwd: rootDirectory,
|
|
40365
40492
|
env: SANITIZED_ENV,
|
|
40366
40493
|
stdio: [
|
|
@@ -40619,6 +40746,8 @@ const spawnLintBatches = async (input) => {
|
|
|
40619
40746
|
const reasonHint = firstDropReason ? ` — first failure: ${firstDropReason}` : "";
|
|
40620
40747
|
reportSkippedFiles(droppedFiles, (fileListPreview) => `${droppedFiles.length} file(s) failed to lint and were skipped (${fileListPreview})${reasonHint}`);
|
|
40621
40748
|
reportSkippedFiles(outcome.deadlineSkippedFiles, (fileListPreview) => `${outcome.deadlineSkippedFiles.length} file(s) skipped — max scan duration reached before they were linted (${fileListPreview})`);
|
|
40749
|
+
const unavailableFiles = new Set([...droppedFiles, ...outcome.deadlineSkippedFiles]);
|
|
40750
|
+
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)))].sort());
|
|
40622
40751
|
return dedupeDiagnostics(diagnostics);
|
|
40623
40752
|
};
|
|
40624
40753
|
let didValidate = false;
|
|
@@ -40875,12 +41004,18 @@ const reactHooksJsPluginDropNote = (error) => {
|
|
|
40875
41004
|
* 6. always restore disable directives + clean up the temp dir
|
|
40876
41005
|
*/
|
|
40877
41006
|
const runOxlint = async (options) => {
|
|
40878
|
-
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, perFileLintCacheEnabled = false, sidecarLintCacheEnabled = false, onCacheStats, onSidecarStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
|
|
41007
|
+
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, onFileCoverage, perFileLintCacheEnabled = false, sidecarLintCacheEnabled = false, onCacheStats, onSidecarStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
|
|
40879
41008
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
40880
41009
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
40881
41010
|
validateRuleRegistration();
|
|
40882
41011
|
resetManifestCaches();
|
|
40883
|
-
if (includePaths !== void 0 && includePaths.length === 0)
|
|
41012
|
+
if (includePaths !== void 0 && includePaths.length === 0) {
|
|
41013
|
+
onFileCoverage?.({
|
|
41014
|
+
candidateFiles: [],
|
|
41015
|
+
analyzedFiles: []
|
|
41016
|
+
});
|
|
41017
|
+
return [];
|
|
41018
|
+
}
|
|
40884
41019
|
const pluginPath = resolvePluginPath();
|
|
40885
41020
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
40886
41021
|
const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
@@ -40941,6 +41076,7 @@ const runOxlint = async (options) => {
|
|
|
40941
41076
|
const runConfigOverFiles = async (buildConfigForPass, configFileName, files, fileProgress) => {
|
|
40942
41077
|
if (files.length === 0) return {
|
|
40943
41078
|
diagnostics: [],
|
|
41079
|
+
analyzedFiles: [],
|
|
40944
41080
|
didDropReactHooksJsPlugin: false,
|
|
40945
41081
|
hadPartialFailure: false
|
|
40946
41082
|
};
|
|
@@ -40952,24 +41088,32 @@ const runOxlint = async (options) => {
|
|
|
40952
41088
|
const passConfigPath = Path.join(configDirectory, configFileName);
|
|
40953
41089
|
const passBaseArgs = makeBaseArgs(passConfigPath);
|
|
40954
41090
|
const passFileBatches = buildFileBatches(passBaseArgs, files);
|
|
40955
|
-
|
|
40956
|
-
|
|
40957
|
-
|
|
40958
|
-
|
|
40959
|
-
|
|
40960
|
-
|
|
40961
|
-
|
|
40962
|
-
|
|
40963
|
-
|
|
40964
|
-
|
|
40965
|
-
|
|
40966
|
-
|
|
40967
|
-
|
|
40968
|
-
|
|
41091
|
+
let analyzedFiles = [];
|
|
41092
|
+
const spawnPass = () => {
|
|
41093
|
+
analyzedFiles = [];
|
|
41094
|
+
return spawnLintBatches({
|
|
41095
|
+
baseArgs: passBaseArgs,
|
|
41096
|
+
fileBatches: passFileBatches,
|
|
41097
|
+
rootDirectory,
|
|
41098
|
+
nodeBinaryPath,
|
|
41099
|
+
project,
|
|
41100
|
+
onPartialFailure: reportPartialFailure,
|
|
41101
|
+
onAnalyzedFiles: (filePaths) => {
|
|
41102
|
+
analyzedFiles = filePaths;
|
|
41103
|
+
},
|
|
41104
|
+
onFileProgress: fileProgress,
|
|
41105
|
+
spawnTimeoutMs,
|
|
41106
|
+
outputMaxBytes,
|
|
41107
|
+
concurrency: options.concurrency,
|
|
41108
|
+
signal: options.signal,
|
|
41109
|
+
deadlineEpochMs: options.deadlineEpochMs
|
|
41110
|
+
});
|
|
41111
|
+
};
|
|
40969
41112
|
writeOxlintConfig(passConfigPath, buildConfigForPass({}));
|
|
40970
41113
|
try {
|
|
40971
41114
|
return {
|
|
40972
41115
|
diagnostics: await spawnPass(),
|
|
41116
|
+
analyzedFiles,
|
|
40973
41117
|
didDropReactHooksJsPlugin: false,
|
|
40974
41118
|
hadPartialFailure
|
|
40975
41119
|
};
|
|
@@ -40981,12 +41125,13 @@ const runOxlint = async (options) => {
|
|
|
40981
41125
|
reportPartialFailure(reactHooksJsDropNote);
|
|
40982
41126
|
return {
|
|
40983
41127
|
diagnostics,
|
|
41128
|
+
analyzedFiles,
|
|
40984
41129
|
didDropReactHooksJsPlugin: true,
|
|
40985
41130
|
hadPartialFailure
|
|
40986
41131
|
};
|
|
40987
41132
|
}
|
|
40988
41133
|
};
|
|
40989
|
-
if (perFileLintCacheEnabled &&
|
|
41134
|
+
if (perFileLintCacheEnabled && !project.hasReactCompiler && extendsPaths.length === 0 && userPlugins.length === 0) {
|
|
40990
41135
|
const rulesetHash = computeRulesetHash({
|
|
40991
41136
|
config: buildConfig({
|
|
40992
41137
|
extendsPaths: [],
|
|
@@ -40994,7 +41139,8 @@ const runOxlint = async (options) => {
|
|
|
40994
41139
|
}),
|
|
40995
41140
|
toolchainVersions: resolveOxlintToolchainVersions(nodeBinaryPath),
|
|
40996
41141
|
ignorePatterns: combinedPatterns,
|
|
40997
|
-
tsconfigContent
|
|
41142
|
+
tsconfigContent,
|
|
41143
|
+
respectInlineDisables
|
|
40998
41144
|
});
|
|
40999
41145
|
const cache = createFileLintCache(resolveReactDoctorCacheDir(rootDirectory), rulesetHash);
|
|
41000
41146
|
const cacheKeyByFile = /* @__PURE__ */ new Map();
|
|
@@ -41037,7 +41183,8 @@ const runOxlint = async (options) => {
|
|
|
41037
41183
|
}),
|
|
41038
41184
|
toolchainVersions: resolveOxlintToolchainVersions(nodeBinaryPath),
|
|
41039
41185
|
ignorePatterns: combinedPatterns,
|
|
41040
|
-
tsconfigContent
|
|
41186
|
+
tsconfigContent,
|
|
41187
|
+
respectInlineDisables
|
|
41041
41188
|
})) : null;
|
|
41042
41189
|
const probeAnswers = createSidecarProbeAnswerResolver({
|
|
41043
41190
|
rootDirectory,
|
|
@@ -41056,6 +41203,7 @@ const runOxlint = async (options) => {
|
|
|
41056
41203
|
const missFileSet = new Set(missFiles);
|
|
41057
41204
|
const hitFiles = candidateFiles.filter((candidateFile) => !missFileSet.has(candidateFile));
|
|
41058
41205
|
const sidecarReplayedDiagnostics = [];
|
|
41206
|
+
const sidecarReplayedFiles = [];
|
|
41059
41207
|
const sidecarLintFiles = [];
|
|
41060
41208
|
if (sidecarCache === null) sidecarLintFiles.push(...hitFiles);
|
|
41061
41209
|
else {
|
|
@@ -41063,8 +41211,10 @@ const runOxlint = async (options) => {
|
|
|
41063
41211
|
for (const hitFile of hitFiles) {
|
|
41064
41212
|
const cacheKey = cacheKeyByFile.get(hitFile);
|
|
41065
41213
|
const entry = cacheKey === void 0 ? null : sidecarCache.lookup(cacheKey);
|
|
41066
|
-
if (entry !== null && entry.probes.every((probe) => probeAnswers.answerFor(probe.kind, probe.path) === probe.answer))
|
|
41067
|
-
|
|
41214
|
+
if (entry !== null && entry.probes.every((probe) => probeAnswers.answerFor(probe.kind, probe.path) === probe.answer)) {
|
|
41215
|
+
sidecarReplayedFiles.push(hitFile);
|
|
41216
|
+
sidecarReplayedDiagnostics.push(...entry.diagnostics);
|
|
41217
|
+
} else sidecarLintFiles.push(hitFile);
|
|
41068
41218
|
if (performance.now() - verifySliceStartedAt >= 12) {
|
|
41069
41219
|
await yieldToEventLoop();
|
|
41070
41220
|
verifySliceStartedAt = performance.now();
|
|
@@ -41090,6 +41240,7 @@ const runOxlint = async (options) => {
|
|
|
41090
41240
|
sidecarRuleIdFilter: new Set(unboundedSidecarRuleIds)
|
|
41091
41241
|
}), "oxlintrc.sidecar-unbounded.json", hitFiles, void 0) : {
|
|
41092
41242
|
diagnostics: [],
|
|
41243
|
+
analyzedFiles: [],
|
|
41093
41244
|
didDropReactHooksJsPlugin: false,
|
|
41094
41245
|
hadPartialFailure: false
|
|
41095
41246
|
};
|
|
@@ -41120,6 +41271,15 @@ const runOxlint = async (options) => {
|
|
|
41120
41271
|
probesByFile: await missProbesTask
|
|
41121
41272
|
}]
|
|
41122
41273
|
});
|
|
41274
|
+
const analyzedFileSet = new Set(fullResult.analyzedFiles);
|
|
41275
|
+
const boundedSidecarAnalyzedFileSet = new Set(boundedSidecarResult.analyzedFiles);
|
|
41276
|
+
const unboundedSidecarAnalyzedFileSet = new Set(unboundedSidecarResult.analyzedFiles);
|
|
41277
|
+
const sidecarReplayedFileSet = new Set(sidecarReplayedFiles);
|
|
41278
|
+
for (const hitFile of hitFiles) if (useSidecarCache ? (sidecarReplayedFileSet.has(hitFile) || boundedSidecarAnalyzedFileSet.has(hitFile)) && (unboundedSidecarRuleIds.length === 0 || unboundedSidecarAnalyzedFileSet.has(hitFile)) : boundedSidecarAnalyzedFileSet.has(hitFile)) analyzedFileSet.add(hitFile);
|
|
41279
|
+
onFileCoverage?.({
|
|
41280
|
+
candidateFiles,
|
|
41281
|
+
analyzedFiles: candidateFiles.filter((candidateFile) => analyzedFileSet.has(candidateFile))
|
|
41282
|
+
});
|
|
41123
41283
|
return dedupeDiagnostics([
|
|
41124
41284
|
...replayedDiagnostics,
|
|
41125
41285
|
...fullResult.diagnostics,
|
|
@@ -41130,6 +41290,7 @@ const runOxlint = async (options) => {
|
|
|
41130
41290
|
}
|
|
41131
41291
|
const baseArgs = makeBaseArgs(configPath);
|
|
41132
41292
|
const fileBatches = buildFileBatches(baseArgs, candidateFiles);
|
|
41293
|
+
let analyzedFiles = [];
|
|
41133
41294
|
const runBatches = () => spawnLintBatches({
|
|
41134
41295
|
baseArgs,
|
|
41135
41296
|
fileBatches,
|
|
@@ -41137,6 +41298,9 @@ const runOxlint = async (options) => {
|
|
|
41137
41298
|
nodeBinaryPath,
|
|
41138
41299
|
project,
|
|
41139
41300
|
onPartialFailure,
|
|
41301
|
+
onAnalyzedFiles: (filePaths) => {
|
|
41302
|
+
analyzedFiles = filePaths;
|
|
41303
|
+
},
|
|
41140
41304
|
onFileProgress: options.onFileProgress,
|
|
41141
41305
|
spawnTimeoutMs,
|
|
41142
41306
|
outputMaxBytes,
|
|
@@ -41146,7 +41310,12 @@ const runOxlint = async (options) => {
|
|
|
41146
41310
|
});
|
|
41147
41311
|
writeOxlintConfig(configPath, buildConfig({ extendsPaths }));
|
|
41148
41312
|
try {
|
|
41149
|
-
|
|
41313
|
+
const diagnostics = await runBatches();
|
|
41314
|
+
onFileCoverage?.({
|
|
41315
|
+
candidateFiles,
|
|
41316
|
+
analyzedFiles
|
|
41317
|
+
});
|
|
41318
|
+
return diagnostics;
|
|
41150
41319
|
} catch (error) {
|
|
41151
41320
|
const reactHooksJsDropNote = reactHooksJsPluginDropNote(error);
|
|
41152
41321
|
if (reactHooksJsDropNote !== null) {
|
|
@@ -41156,11 +41325,20 @@ const runOxlint = async (options) => {
|
|
|
41156
41325
|
}));
|
|
41157
41326
|
const diagnostics = await runBatches();
|
|
41158
41327
|
onPartialFailure?.(reactHooksJsDropNote);
|
|
41328
|
+
onFileCoverage?.({
|
|
41329
|
+
candidateFiles,
|
|
41330
|
+
analyzedFiles
|
|
41331
|
+
});
|
|
41159
41332
|
return diagnostics;
|
|
41160
41333
|
}
|
|
41161
41334
|
if (extendsPaths.length === 0) throw error;
|
|
41162
41335
|
writeOxlintConfig(configPath, buildConfig({ extendsPaths: [] }));
|
|
41163
|
-
|
|
41336
|
+
const diagnostics = await runBatches();
|
|
41337
|
+
onFileCoverage?.({
|
|
41338
|
+
candidateFiles,
|
|
41339
|
+
analyzedFiles
|
|
41340
|
+
});
|
|
41341
|
+
return diagnostics;
|
|
41164
41342
|
}
|
|
41165
41343
|
} finally {
|
|
41166
41344
|
restoreDisableDirectives();
|
|
@@ -41240,6 +41418,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
|
|
|
41240
41418
|
onPartialFailure: (reason) => {
|
|
41241
41419
|
collectedFailures.push(reason);
|
|
41242
41420
|
},
|
|
41421
|
+
onFileCoverage: input.onFileCoverage,
|
|
41243
41422
|
onFileProgress: input.onFileProgress,
|
|
41244
41423
|
perFileLintCacheEnabled,
|
|
41245
41424
|
sidecarLintCacheEnabled,
|
|
@@ -41332,7 +41511,10 @@ const translateProjectInfoError = (cause, directory) => {
|
|
|
41332
41511
|
directory: cause.directory,
|
|
41333
41512
|
candidates: cause.candidates
|
|
41334
41513
|
}) });
|
|
41335
|
-
return new ReactDoctorError({ reason: new
|
|
41514
|
+
return new ReactDoctorError({ reason: new ProjectDiscoveryFailed({
|
|
41515
|
+
directory,
|
|
41516
|
+
cause
|
|
41517
|
+
}) });
|
|
41336
41518
|
};
|
|
41337
41519
|
var Project = class Project extends Service()("react-doctor/Project") {
|
|
41338
41520
|
static layerNode = succeed$3(Project, Project.of({ discover: fn("Project.discover")(function* (directory) {
|
|
@@ -41944,6 +42126,7 @@ const resolveGithubActionsScoreMetadata = (environment = process.env) => {
|
|
|
41944
42126
|
...actorAssociation !== void 0 ? { githubActorAssociation: actorAssociation } : {}
|
|
41945
42127
|
};
|
|
41946
42128
|
};
|
|
42129
|
+
const toNormalizedRelativePath = (filePath, rootDirectory) => Path.relative(Path.resolve(rootDirectory), Path.resolve(rootDirectory, filePath)).replaceAll("\\", "/") || ".";
|
|
41947
42130
|
const NO_HOOKS = {
|
|
41948
42131
|
beforeLint: () => void_,
|
|
41949
42132
|
afterLint: () => void_
|
|
@@ -42042,7 +42225,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42042
42225
|
repo
|
|
42043
42226
|
}).pipe(orElseSucceed(() => null)) : succeed$2(null));
|
|
42044
42227
|
const lintIncludePaths = (input.skipJsxIncludeFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths], project)) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config, project);
|
|
42045
|
-
const
|
|
42228
|
+
const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
|
|
42046
42229
|
const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
|
|
42047
42230
|
const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
|
|
42048
42231
|
yield* beforeLint(project, lintIncludePaths ?? void 0);
|
|
@@ -42147,6 +42330,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42147
42330
|
let deadCodeCacheHit = null;
|
|
42148
42331
|
let deadCodeSummaryCacheHits = null;
|
|
42149
42332
|
let deadCodeSummaryCacheMisses = null;
|
|
42333
|
+
const lintFileCoverageState = { value: null };
|
|
42150
42334
|
const baseLintStream = linterService.run({
|
|
42151
42335
|
rootDirectory: scanDirectory,
|
|
42152
42336
|
project,
|
|
@@ -42162,6 +42346,9 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42162
42346
|
lastReportedTotalFileCount = totalFileCount;
|
|
42163
42347
|
runSync(scanProgress.update(`Scanning files (${scannedFileCount}/${totalFileCount})${workerCountSuffix}...`));
|
|
42164
42348
|
},
|
|
42349
|
+
onFileCoverage: (coverage) => {
|
|
42350
|
+
lintFileCoverageState.value = coverage;
|
|
42351
|
+
},
|
|
42165
42352
|
onCacheStats: (cacheHitFileCount, totalConsideredFileCount) => {
|
|
42166
42353
|
lintCacheHitFileCount = cacheHitFileCount;
|
|
42167
42354
|
lintCacheTotalFileCount = totalConsideredFileCount;
|
|
@@ -42192,7 +42379,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42192
42379
|
const lintFailureState = yield* get$2(lintFailure);
|
|
42193
42380
|
yield* afterLint(lintFailureState.didFail);
|
|
42194
42381
|
if (lintFailureState.didFail) yield* scanProgress.fail(formatLintFailText(lintFailureState.reasonTag, process.version));
|
|
42195
|
-
const
|
|
42382
|
+
const candidateFiles = lintFileCoverageState.value === null ? [] : [...new Set(lintFileCoverageState.value.candidateFiles.map((filePath) => toNormalizedRelativePath(filePath, scanDirectory)))];
|
|
42383
|
+
const analyzedFiles = lintFileCoverageState.value === null ? [] : [...new Set(lintFileCoverageState.value.analyzedFiles.map((filePath) => toNormalizedRelativePath(filePath, scanDirectory)))].sort();
|
|
42384
|
+
const totalFileCount = candidateFiles.length || lastReportedTotalFileCount || (lintIncludePaths?.length ?? project.sourceFileCount);
|
|
42385
|
+
const scannedFilePaths = input.suppressScanSummary ? candidateFiles.length > 0 ? candidateFiles.map((filePath) => Path.resolve(scanDirectory, filePath)) : fallbackScannedFilePaths : [];
|
|
42196
42386
|
const scannedFilesLabel = `${totalFileCount} ${totalFileCount === 1 ? "file" : "files"}`;
|
|
42197
42387
|
let deadCodeCollected = [];
|
|
42198
42388
|
if (lintFailureState.didFail) {
|
|
@@ -42274,6 +42464,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42274
42464
|
deadCodeOverlapped: shouldOverlapDeadCode,
|
|
42275
42465
|
scannedFileCount: totalFileCount,
|
|
42276
42466
|
scannedFilePaths,
|
|
42467
|
+
analyzedFiles,
|
|
42277
42468
|
scanElapsedMilliseconds,
|
|
42278
42469
|
scanConcurrency,
|
|
42279
42470
|
supplyChainOverlapTimedOut: supplyChainResult.timedOut,
|
|
@@ -42612,7 +42803,7 @@ const computeConfigFingerprint = (projectDirectory, version) => {
|
|
|
42612
42803
|
/** Display name used in client-facing messages and progress titles. */
|
|
42613
42804
|
const SERVER_DISPLAY_NAME = "React Doctor";
|
|
42614
42805
|
/** Server version reported in `serverInfo`; injected at build, `dev` from source. */
|
|
42615
|
-
const SERVER_VERSION = "0.7.
|
|
42806
|
+
const SERVER_VERSION = "0.7.5";
|
|
42616
42807
|
/** `Diagnostic.source` shown next to every published diagnostic. */
|
|
42617
42808
|
const DIAGNOSTIC_SOURCE = "react-doctor";
|
|
42618
42809
|
/**
|
|
@@ -44663,5 +44854,5 @@ const startLanguageServer = () => {
|
|
|
44663
44854
|
};
|
|
44664
44855
|
//#endregion
|
|
44665
44856
|
export { startLanguageServer };
|
|
44666
|
-
!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]="
|
|
44667
|
-
//# debugId=
|
|
44857
|
+
!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]="172df417-33ac-5881-af14-5df32c7af09c")}catch(e){}}();
|
|
44858
|
+
//# debugId=172df417-33ac-5881-af14-5df32c7af09c
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5-dev.037bd56",
|
|
4
4
|
"description": "Your agent writes bad React. This catches it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"vscode-languageserver-textdocument": "^1.0.12",
|
|
66
66
|
"vscode-uri": "^3.1.0",
|
|
67
67
|
"yaml": "^2.9.0",
|
|
68
|
-
"
|
|
69
|
-
"
|
|
68
|
+
"oxlint-plugin-react-doctor": "0.7.5-dev.037bd56",
|
|
69
|
+
"deslop-js": "0.7.5"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__code-frame": "^7.27.0",
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"@xterm/headless": "^6.0.0",
|
|
75
75
|
"commander": "^14.0.3",
|
|
76
76
|
"ora": "^9.4.0",
|
|
77
|
-
"@react-doctor/
|
|
78
|
-
"@react-doctor/
|
|
79
|
-
"@react-doctor/
|
|
77
|
+
"@react-doctor/api": "0.7.5",
|
|
78
|
+
"@react-doctor/language-server": "0.7.5",
|
|
79
|
+
"@react-doctor/core": "0.7.5"
|
|
80
80
|
},
|
|
81
81
|
"engines": {
|
|
82
82
|
"node": "^20.19.0 || >=22.13.0"
|