react-doctor 0.7.6-dev.88ef7fd → 0.7.6-dev.8c9a6c4
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 +54 -221
- package/dist/index.d.ts +1 -1
- package/dist/index.js +30 -83
- package/dist/lsp.js +28 -81
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="bc56f5c4-5b95-5727-8e86-d43a534abbbc")}catch(e){}}();
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as NodeChildProcess from "node:child_process";
|
|
5
5
|
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
|
|
@@ -36341,12 +36341,10 @@ const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
|
36341
36341
|
const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort());
|
|
36342
36342
|
const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
|
|
36343
36343
|
const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
|
|
36344
|
-
const UTF8_BOM_CHARACTER = "";
|
|
36345
|
-
const stripUtf8Bom = (content) => content.startsWith(UTF8_BOM_CHARACTER) ? content.slice(1) : content;
|
|
36346
36344
|
const cachedPackageJsons = /* @__PURE__ */ new Map();
|
|
36347
36345
|
const readPackageJsonUncached = (packageJsonPath) => {
|
|
36348
36346
|
try {
|
|
36349
|
-
return JSON.parse(
|
|
36347
|
+
return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
36350
36348
|
} catch (error) {
|
|
36351
36349
|
if (error instanceof SyntaxError) return {};
|
|
36352
36350
|
if (isErrnoException(error)) {
|
|
@@ -40019,6 +40017,7 @@ const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
|
|
|
40019
40017
|
const PNPM_LOCKFILE = "pnpm-lock.yaml";
|
|
40020
40018
|
const PACKAGE_JSON_FILE = "package.json";
|
|
40021
40019
|
const PNPM_HARDENING_RULE_KEY = "require-pnpm-hardening";
|
|
40020
|
+
const UTF8_BOM_CHAR = "";
|
|
40022
40021
|
const HARDENING_SETTING_KEYS = new Set([
|
|
40023
40022
|
"minimumReleaseAge",
|
|
40024
40023
|
"blockExoticSubdeps",
|
|
@@ -40043,11 +40042,12 @@ const stripInlineComment = (rawValue) => {
|
|
|
40043
40042
|
return rawValue;
|
|
40044
40043
|
};
|
|
40045
40044
|
const unquote = (rawValue) => rawValue.replace(/^["']|["']$/g, "");
|
|
40045
|
+
const stripBom = (rawContent) => rawContent.startsWith(UTF8_BOM_CHAR) ? rawContent.slice(1) : rawContent;
|
|
40046
40046
|
const parseHardeningSettings = (content) => {
|
|
40047
40047
|
let minimumReleaseAge = null;
|
|
40048
40048
|
let blockExoticSubdeps = null;
|
|
40049
40049
|
let trustPolicy = null;
|
|
40050
|
-
const lines =
|
|
40050
|
+
const lines = stripBom(content).split(/\r?\n/);
|
|
40051
40051
|
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
40052
40052
|
const lineText = lines[lineIndex];
|
|
40053
40053
|
if (lineText === void 0) continue;
|
|
@@ -40081,7 +40081,7 @@ const isPnpmManagedProject = (rootDirectory) => {
|
|
|
40081
40081
|
const packageJsonPath = Path.join(rootDirectory, PACKAGE_JSON_FILE);
|
|
40082
40082
|
if (!isFile(packageJsonPath)) return false;
|
|
40083
40083
|
try {
|
|
40084
|
-
const packageJsonRaw =
|
|
40084
|
+
const packageJsonRaw = NFS.readFileSync(packageJsonPath, "utf-8");
|
|
40085
40085
|
const packageJson = JSON.parse(packageJsonRaw);
|
|
40086
40086
|
if (packageJson !== null && typeof packageJson === "object" && "packageManager" in packageJson && typeof packageJson.packageManager === "string" && packageJson.packageManager.startsWith("pnpm@")) return true;
|
|
40087
40087
|
} catch {
|
|
@@ -41823,7 +41823,6 @@ const parseGithubViewerPermission = (stdout) => {
|
|
|
41823
41823
|
return /^[A-Z_]+$/.test(value) ? value.toLowerCase() : null;
|
|
41824
41824
|
};
|
|
41825
41825
|
const splitNullSeparated = (value) => value.split("\0").filter((entry) => entry.length > 0);
|
|
41826
|
-
const UNTRACKED_FILE_LAST_LINE = Number.MAX_SAFE_INTEGER;
|
|
41827
41826
|
/**
|
|
41828
41827
|
* `Git` wraps every `git`-via-subprocess call react-doctor makes
|
|
41829
41828
|
* behind a `Context.Service`. The production layer (`layerNode`)
|
|
@@ -41894,14 +41893,6 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
41894
41893
|
args,
|
|
41895
41894
|
directory
|
|
41896
41895
|
});
|
|
41897
|
-
const listUntrackedFilePaths = (directory, includePaths = []) => runGit(directory, [
|
|
41898
|
-
"ls-files",
|
|
41899
|
-
"-z",
|
|
41900
|
-
"--others",
|
|
41901
|
-
"--exclude-standard",
|
|
41902
|
-
...includePaths.length > 0 ? ["--", ...includePaths] : []
|
|
41903
|
-
]).pipe(map$3((result) => result.status === 0 ? splitNullSeparated(result.stdout) : null));
|
|
41904
|
-
const mergeUntracked = (directory, trackedFilePaths, includeUntracked) => includeUntracked ? listUntrackedFilePaths(directory).pipe(map$3((untracked) => untracked === null ? trackedFilePaths : [...new Set([...trackedFilePaths, ...untracked])])) : succeed$2(trackedFilePaths);
|
|
41905
41896
|
const currentBranch = (directory) => runGit(directory, [
|
|
41906
41897
|
"rev-parse",
|
|
41907
41898
|
"--abbrev-ref",
|
|
@@ -42024,7 +42015,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
42024
42015
|
githubViewerPermission,
|
|
42025
42016
|
branchExists,
|
|
42026
42017
|
mergeBase,
|
|
42027
|
-
diffSelection: ({ directory, explicitBaseBranch
|
|
42018
|
+
diffSelection: ({ directory, explicitBaseBranch }) => gen(function* () {
|
|
42028
42019
|
if (explicitBaseBranch !== void 0 && explicitBaseBranch.trim().length === 0) return yield* fail$4(new ReactDoctorError({ reason: new GitBaseBranchInvalid({ detail: "Diff base branch cannot be empty." }) }));
|
|
42029
42020
|
if (explicitBaseBranch !== void 0) {
|
|
42030
42021
|
const range = parseGitDiffRange(explicitBaseBranch);
|
|
@@ -42053,7 +42044,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
42053
42044
|
"HEAD"
|
|
42054
42045
|
]);
|
|
42055
42046
|
if (uncommitted.status !== 0) return null;
|
|
42056
|
-
const files =
|
|
42047
|
+
const files = splitNullSeparated(uncommitted.stdout);
|
|
42057
42048
|
if (files.length === 0) return null;
|
|
42058
42049
|
return {
|
|
42059
42050
|
currentBranch: resolvedCurrentBranch,
|
|
@@ -42083,7 +42074,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
42083
42074
|
currentBranch: resolvedCurrentBranch,
|
|
42084
42075
|
baseBranch,
|
|
42085
42076
|
diffBaseRef: mergeBaseRef,
|
|
42086
|
-
changedFiles:
|
|
42077
|
+
changedFiles: splitNullSeparated(diff.stdout),
|
|
42087
42078
|
isCurrentChanges: false
|
|
42088
42079
|
};
|
|
42089
42080
|
}).pipe(withSpan("Git.diffSelection")),
|
|
@@ -42129,7 +42120,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
42129
42120
|
stdout: result.stdout
|
|
42130
42121
|
};
|
|
42131
42122
|
}).pipe(withSpan("Git.grep")),
|
|
42132
|
-
changedLineRanges: ({ directory, baseRef, cached, files
|
|
42123
|
+
changedLineRanges: ({ directory, baseRef, cached, files }) => gen(function* () {
|
|
42133
42124
|
if (files.length === 0) return [];
|
|
42134
42125
|
if (baseRef !== void 0 && !isSafeGitRevision(baseRef)) return null;
|
|
42135
42126
|
const result = yield* runGit(directory, [
|
|
@@ -42143,14 +42134,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
42143
42134
|
...files
|
|
42144
42135
|
]);
|
|
42145
42136
|
if (result.status !== 0) return null;
|
|
42146
|
-
|
|
42147
|
-
if (cached || !includeUntracked) return changedLineRanges;
|
|
42148
|
-
const untrackedFilePaths = yield* listUntrackedFilePaths(directory, files);
|
|
42149
|
-
if (untrackedFilePaths === null) return changedLineRanges;
|
|
42150
|
-
return [...changedLineRanges, ...untrackedFilePaths.map((file) => ({
|
|
42151
|
-
file,
|
|
42152
|
-
ranges: [[1, UNTRACKED_FILE_LAST_LINE]]
|
|
42153
|
-
}))];
|
|
42137
|
+
return parseChangedLineRanges(result.stdout);
|
|
42154
42138
|
}).pipe(catch_$1((error) => error.reason._tag === "GitInvocationFailed" ? succeed$2(null) : fail$4(error)), withSpan("Git.changedLineRanges"))
|
|
42155
42139
|
});
|
|
42156
42140
|
})).pipe(provide$2(layer$3.pipe(provide$2(mergeAll$1(layer$2, layer$1)))));
|
|
@@ -42902,12 +42886,6 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
42902
42886
|
if (errors.length > 0) throw errors[0];
|
|
42903
42887
|
return results;
|
|
42904
42888
|
};
|
|
42905
|
-
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
42906
|
-
let lineNumber = 1;
|
|
42907
|
-
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
42908
|
-
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === 10) lineNumber++;
|
|
42909
|
-
return lineNumber;
|
|
42910
|
-
};
|
|
42911
42889
|
const REANIMATED_SHARED_VALUE_HINT = "If this is a Reanimated shared value, prefer its React Compiler-compatible `.get()` / `.set()` accessors over `.value` — https://docs.swmansion.com/react-native-reanimated/docs/core/useSharedValue/#react-compiler-support";
|
|
42912
42890
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
42913
42891
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -43479,6 +43457,13 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
43479
43457
|
visit(sourceFile);
|
|
43480
43458
|
return foundRange;
|
|
43481
43459
|
};
|
|
43460
|
+
const NEWLINE_BYTE = 10;
|
|
43461
|
+
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
43462
|
+
let lineNumber = 1;
|
|
43463
|
+
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
43464
|
+
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
|
|
43465
|
+
return lineNumber;
|
|
43466
|
+
};
|
|
43482
43467
|
/**
|
|
43483
43468
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
43484
43469
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -43659,11 +43644,11 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
43659
43644
|
}
|
|
43660
43645
|
return related;
|
|
43661
43646
|
};
|
|
43662
|
-
const
|
|
43663
|
-
|
|
43664
|
-
const
|
|
43665
|
-
|
|
43666
|
-
|
|
43647
|
+
const isOxlintOutput = (value) => {
|
|
43648
|
+
if (typeof value !== "object" || value === null) return false;
|
|
43649
|
+
const candidate = value;
|
|
43650
|
+
return Array.isArray(candidate.diagnostics);
|
|
43651
|
+
};
|
|
43667
43652
|
/**
|
|
43668
43653
|
* Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
|
|
43669
43654
|
* Tolerates the leading-notice-line shape oxlint sometimes prints
|
|
@@ -43682,59 +43667,23 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43682
43667
|
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
43683
43668
|
}
|
|
43684
43669
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
43685
|
-
const engineFailureDiagnostic = parsed.diagnostics.find(isEngineFailureDiagnostic);
|
|
43686
|
-
if (engineFailureDiagnostic !== void 0) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: JSON.stringify(engineFailureDiagnostic).slice(0, 600) }) });
|
|
43687
43670
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
43688
|
-
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
43689
|
-
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
43690
|
-
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
43691
|
-
const readSourceBuffer = (filename) => {
|
|
43692
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
43693
|
-
const cached = sourceBufferCache.get(absolutePath);
|
|
43694
|
-
if (cached !== void 0) return cached;
|
|
43695
|
-
let sourceBuffer;
|
|
43696
|
-
try {
|
|
43697
|
-
sourceBuffer = NFS.readFileSync(absolutePath);
|
|
43698
|
-
} catch {
|
|
43699
|
-
sourceBuffer = null;
|
|
43700
|
-
}
|
|
43701
|
-
sourceBufferCache.set(absolutePath, sourceBuffer);
|
|
43702
|
-
return sourceBuffer;
|
|
43703
|
-
};
|
|
43704
|
-
const readSourceLines = (filename) => {
|
|
43705
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
43706
|
-
const cached = sourceLinesCache.get(absolutePath);
|
|
43707
|
-
if (cached !== void 0) return cached;
|
|
43708
|
-
const sourceBuffer = readSourceBuffer(filename);
|
|
43709
|
-
const sourceLines = sourceBuffer ? sourceBuffer.toString("utf8").split("\n") : null;
|
|
43710
|
-
sourceLinesCache.set(absolutePath, sourceLines);
|
|
43711
|
-
return sourceLines;
|
|
43712
|
-
};
|
|
43713
43671
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
43714
|
-
const absolutePath =
|
|
43672
|
+
const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
43715
43673
|
const cached = minifiedFileCache.get(absolutePath);
|
|
43716
43674
|
if (cached !== void 0) return cached;
|
|
43717
43675
|
const minified = isMinifiedSource(absolutePath);
|
|
43718
43676
|
minifiedFileCache.set(absolutePath, minified);
|
|
43719
43677
|
return minified;
|
|
43720
43678
|
};
|
|
43721
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) =>
|
|
43679
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
43722
43680
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
43723
43681
|
const primaryLabel = diagnostic.labels[0];
|
|
43724
43682
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
43725
43683
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
43726
43684
|
const primarySpan = primaryLabel?.span;
|
|
43727
|
-
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
43728
43685
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
43729
43686
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
43730
|
-
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
43731
|
-
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
43732
|
-
const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
|
|
43733
|
-
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
43734
|
-
const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
|
|
43735
|
-
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
43736
|
-
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
43737
|
-
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
43738
43687
|
return {
|
|
43739
43688
|
filePath: normalizedFilePath,
|
|
43740
43689
|
plugin,
|
|
@@ -43748,11 +43697,10 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43748
43697
|
column: primarySpan?.column ?? 0,
|
|
43749
43698
|
...primarySpan ? {
|
|
43750
43699
|
offset: primarySpan.offset,
|
|
43751
|
-
length: primarySpan.length
|
|
43752
|
-
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
43700
|
+
length: primarySpan.length
|
|
43753
43701
|
} : {},
|
|
43754
43702
|
category,
|
|
43755
|
-
...
|
|
43703
|
+
...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
|
|
43756
43704
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
43757
43705
|
};
|
|
43758
43706
|
}), rootDirectory);
|
|
@@ -46284,11 +46232,10 @@ const computeDiagnosticDelta = (input) => {
|
|
|
46284
46232
|
* render diff-base mistakes (`GitBaseBranchInvalid` /
|
|
46285
46233
|
* `GitBaseBranchMissing`) as clean user errors instead of crashes.
|
|
46286
46234
|
*/
|
|
46287
|
-
const getDiffInfo = (directory, explicitBaseBranch
|
|
46235
|
+
const getDiffInfo = (directory, explicitBaseBranch) => runPromise(gen(function* () {
|
|
46288
46236
|
const selection = yield* (yield* Git).diffSelection({
|
|
46289
46237
|
directory,
|
|
46290
|
-
explicitBaseBranch
|
|
46291
|
-
includeUntracked
|
|
46238
|
+
explicitBaseBranch
|
|
46292
46239
|
});
|
|
46293
46240
|
if (selection === null) return null;
|
|
46294
46241
|
return {
|
|
@@ -46624,43 +46571,6 @@ const isNonInteractiveEnvironment = () => NON_INTERACTIVE_ENVIRONMENT_VARIABLES.
|
|
|
46624
46571
|
//#region src/cli/utils/constants.ts
|
|
46625
46572
|
const REACT_DOCTOR_CONFIG_PROJECT_NAME = "react-doctor";
|
|
46626
46573
|
const STAGED_FILES_TEMP_DIR_PREFIX = "react-doctor-staged-";
|
|
46627
|
-
const STAGED_SNAPSHOT_ADDITIONAL_CONFIG_FILENAMES = [
|
|
46628
|
-
".babelrc",
|
|
46629
|
-
".babelrc.json",
|
|
46630
|
-
".eslintignore",
|
|
46631
|
-
".eslintrc.json",
|
|
46632
|
-
".oxlintignore",
|
|
46633
|
-
"app.config.cjs",
|
|
46634
|
-
"app.config.js",
|
|
46635
|
-
"app.config.json",
|
|
46636
|
-
"app.config.mjs",
|
|
46637
|
-
"app.config.ts",
|
|
46638
|
-
"app.json",
|
|
46639
|
-
"babel.config.cjs",
|
|
46640
|
-
"babel.config.js",
|
|
46641
|
-
"babel.config.json",
|
|
46642
|
-
"babel.config.mjs",
|
|
46643
|
-
"eslint.config.cjs",
|
|
46644
|
-
"eslint.config.cts",
|
|
46645
|
-
"eslint.config.js",
|
|
46646
|
-
"eslint.config.mjs",
|
|
46647
|
-
"eslint.config.mts",
|
|
46648
|
-
"eslint.config.ts",
|
|
46649
|
-
"next.config.cjs",
|
|
46650
|
-
"next.config.js",
|
|
46651
|
-
"next.config.mjs",
|
|
46652
|
-
"next.config.ts",
|
|
46653
|
-
"oxlint.config.json",
|
|
46654
|
-
"react-doctor.config.json",
|
|
46655
|
-
"vite.config.cjs",
|
|
46656
|
-
"vite.config.cts",
|
|
46657
|
-
"vite.config.js",
|
|
46658
|
-
"vite.config.mjs",
|
|
46659
|
-
"vite.config.mts",
|
|
46660
|
-
"vite.config.ts",
|
|
46661
|
-
"vitest.config.js",
|
|
46662
|
-
"vitest.config.ts"
|
|
46663
|
-
];
|
|
46664
46574
|
const BASELINE_FILES_TEMP_DIR_PREFIX = "react-doctor-baseline-";
|
|
46665
46575
|
const SCAN_RESULT_CACHE_FILENAME = "scan-cache.json";
|
|
46666
46576
|
const RUN_GIT_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
|
|
@@ -46675,7 +46585,6 @@ const METRIC = {
|
|
|
46675
46585
|
cliInvoked: "cli.invoked",
|
|
46676
46586
|
cliError: "cli.error",
|
|
46677
46587
|
cliEnvironmentError: "cli.env_error",
|
|
46678
|
-
stagedSnapshotDivergence: "staged.snapshot_divergence",
|
|
46679
46588
|
projectDetected: "project.detected",
|
|
46680
46589
|
projectPathSelected: "project.path_selected",
|
|
46681
46590
|
projectConfigSelected: "project.config_selected",
|
|
@@ -46756,7 +46665,7 @@ const makeNoopConsole = () => ({
|
|
|
46756
46665
|
});
|
|
46757
46666
|
//#endregion
|
|
46758
46667
|
//#region src/cli/utils/version.ts
|
|
46759
|
-
const VERSION = "0.7.6-dev.
|
|
46668
|
+
const VERSION = "0.7.6-dev.8c9a6c4";
|
|
46760
46669
|
//#endregion
|
|
46761
46670
|
//#region src/cli/utils/json-mode.ts
|
|
46762
46671
|
let context = null;
|
|
@@ -47125,13 +47034,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
47125
47034
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
47126
47035
|
* standard `SENTRY_RELEASE` override.
|
|
47127
47036
|
*/
|
|
47128
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.6-dev.
|
|
47037
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.6-dev.8c9a6c4`;
|
|
47129
47038
|
/**
|
|
47130
47039
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
47131
47040
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
47132
47041
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
47133
47042
|
*/
|
|
47134
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.
|
|
47043
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.8c9a6c4") ? "development" : "production");
|
|
47135
47044
|
/**
|
|
47136
47045
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
47137
47046
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -47323,7 +47232,7 @@ const NON_BLOCKING_REACT_DOCTOR_COMMAND = [
|
|
|
47323
47232
|
"fi"
|
|
47324
47233
|
].join(" ");
|
|
47325
47234
|
const PACKAGE_JSON_FILE_NAME = "package.json";
|
|
47326
|
-
const
|
|
47235
|
+
const runGit = (projectRoot, args) => {
|
|
47327
47236
|
try {
|
|
47328
47237
|
return execFileSync("git", [...args], {
|
|
47329
47238
|
cwd: projectRoot,
|
|
@@ -47334,12 +47243,11 @@ const runGitRaw = (projectRoot, args) => {
|
|
|
47334
47243
|
"ignore"
|
|
47335
47244
|
],
|
|
47336
47245
|
maxBuffer: RUN_GIT_MAX_BUFFER_BYTES
|
|
47337
|
-
});
|
|
47246
|
+
}).trim();
|
|
47338
47247
|
} catch {
|
|
47339
47248
|
return null;
|
|
47340
47249
|
}
|
|
47341
47250
|
};
|
|
47342
|
-
const runGit = (projectRoot, args) => runGitRaw(projectRoot, args)?.trim() ?? null;
|
|
47343
47251
|
const resolveGitPath = (baseDirectory, value) => Path.isAbsolute(value) ? value : Path.resolve(baseDirectory, value);
|
|
47344
47252
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47345
47253
|
const getPackageJsonPath = (projectRoot) => Path.join(projectRoot, PACKAGE_JSON_FILE_NAME);
|
|
@@ -50897,7 +50805,7 @@ const BLOCKING_SUMMARY = {
|
|
|
50897
50805
|
const SCOPE_SUMMARY = {
|
|
50898
50806
|
full: "Scan the whole project on every run",
|
|
50899
50807
|
files: "Report every issue in changed files",
|
|
50900
|
-
lines: "Report issues
|
|
50808
|
+
lines: "Report issues on changed lines",
|
|
50901
50809
|
changed: "Report only the issues a change introduces"
|
|
50902
50810
|
};
|
|
50903
50811
|
const gatesEqual = (left, right) => left.blocking === right.blocking && left.scope === right.scope && left.comment === right.comment && left.reviewComments === right.reviewComments && left.commitStatus === right.commitStatus;
|
|
@@ -59210,17 +59118,6 @@ const buildRuleBlastRadii = (diagnostics) => buildSortedRuleGroups(diagnostics).
|
|
|
59210
59118
|
})).toSorted((left, right) => right.fileCount - left.fileCount);
|
|
59211
59119
|
const findMigrationScaleBuckets = (diagnostics) => buildRuleBlastRadii(diagnostics).filter((bucket) => bucket.fileCount >= 40);
|
|
59212
59120
|
//#endregion
|
|
59213
|
-
//#region src/cli/utils/has-lint-hard-failure.ts
|
|
59214
|
-
const hasLintHardFailure = (result) => result.skippedChecks.includes("lint");
|
|
59215
|
-
//#endregion
|
|
59216
|
-
//#region src/cli/utils/is-inspect-result-complete.ts
|
|
59217
|
-
const isInspectResultComplete = (result) => isScanComplete({
|
|
59218
|
-
analyzedFileCount: result.analyzedFiles?.length,
|
|
59219
|
-
scannedFileCount: result.scannedFileCount,
|
|
59220
|
-
skippedCheckCount: result.skippedChecks.length,
|
|
59221
|
-
skippedCheckReasonCount: Object.keys(result.skippedCheckReasons ?? {}).length
|
|
59222
|
-
});
|
|
59223
|
-
//#endregion
|
|
59224
59121
|
//#region src/cli/utils/scan-result-cache.ts
|
|
59225
59122
|
const CACHE_DISABLED_VALUES = new Set(["1", "true"]);
|
|
59226
59123
|
const TOOLCHAIN_PACKAGE_SPECIFIERS = [
|
|
@@ -59626,12 +59523,15 @@ const buildOutcomeAttributes = (input) => {
|
|
|
59626
59523
|
const summary = summarizeDiagnostics(result.diagnostics);
|
|
59627
59524
|
const blockingLevel = resolveTelemetryBlocking(input.userConfig);
|
|
59628
59525
|
const gateDiagnostics = filterDiagnosticsForSurface(result.diagnostics, "ciFailure", input.userConfig);
|
|
59629
|
-
const complete = isInspectResultComplete(result);
|
|
59630
|
-
const didLintHardFail = hasLintHardFailure(result);
|
|
59631
|
-
const failsOnHardFailure = didLintHardFail && blockingLevel !== "none";
|
|
59632
59526
|
const wouldBlock = !input.scoreOnly && !input.gateExempt && shouldBlockCi(gateDiagnostics, blockingLevel);
|
|
59527
|
+
const complete = isScanComplete({
|
|
59528
|
+
analyzedFileCount: result.analyzedFiles?.length,
|
|
59529
|
+
scannedFileCount: result.scannedFileCount,
|
|
59530
|
+
skippedCheckCount: result.skippedChecks.length,
|
|
59531
|
+
skippedCheckReasonCount: Object.keys(result.skippedCheckReasons ?? {}).length
|
|
59532
|
+
});
|
|
59633
59533
|
const isClean = result.diagnostics.length === 0 && complete;
|
|
59634
|
-
const outcome =
|
|
59534
|
+
const outcome = wouldBlock ? "blocked" : isClean ? "clean" : "ok";
|
|
59635
59535
|
const firings = summarizeRuleFirings(result.diagnostics);
|
|
59636
59536
|
const countByRule = /* @__PURE__ */ new Map();
|
|
59637
59537
|
const countByCategory = /* @__PURE__ */ new Map();
|
|
@@ -59676,7 +59576,7 @@ const buildOutcomeAttributes = (input) => {
|
|
|
59676
59576
|
const attributes = {
|
|
59677
59577
|
...withNamespace("outcome", {
|
|
59678
59578
|
status: outcome,
|
|
59679
|
-
exitCode:
|
|
59579
|
+
exitCode: wouldBlock ? 1 : 0,
|
|
59680
59580
|
wouldBlock,
|
|
59681
59581
|
blocking: blockingLevel,
|
|
59682
59582
|
clean: isClean,
|
|
@@ -59775,8 +59675,7 @@ const buildScanAttributes = (input) => {
|
|
|
59775
59675
|
rulesConfigured: ruleKeys.length,
|
|
59776
59676
|
rulesDisabled: ruleKeys.filter((key) => ruleOverrides[key] === "off").length,
|
|
59777
59677
|
fileCount: input.result?.scannedFileCount ?? null,
|
|
59778
|
-
nonJsxFileCount: input.result?.analyzedFiles?.filter((filePath) => !JSX_FILE_PATTERN.test(filePath)).length ?? null
|
|
59779
|
-
multilineDiagnosticCount: input.result?.diagnostics.filter((diagnostic) => (diagnostic.endLine ?? diagnostic.line) > diagnostic.line).length ?? null
|
|
59678
|
+
nonJsxFileCount: input.result?.analyzedFiles?.filter((filePath) => !JSX_FILE_PATTERN.test(filePath)).length ?? null
|
|
59780
59679
|
});
|
|
59781
59680
|
};
|
|
59782
59681
|
/**
|
|
@@ -59845,12 +59744,6 @@ const countDeadlineSkippedFiles = (lintPartialFailures) => sumFileCountsMatching
|
|
|
59845
59744
|
const DROPPED_FILES_MESSAGE_PATTERN = /^(\d+) file\(s\) failed to lint and were skipped/;
|
|
59846
59745
|
const countDroppedLintFiles = (lintPartialFailures) => sumFileCountsMatching(lintPartialFailures, DROPPED_FILES_MESSAGE_PATTERN);
|
|
59847
59746
|
//#endregion
|
|
59848
|
-
//#region src/cli/utils/diagnostic-intersects-line-ranges.ts
|
|
59849
|
-
const diagnosticIntersectsLineRanges = (diagnostic, lineRanges) => {
|
|
59850
|
-
const diagnosticEndLine = Math.max(diagnostic.line, diagnostic.endLine ?? diagnostic.line);
|
|
59851
|
-
return lineRanges.some(([rangeStartLine, rangeEndLine]) => diagnostic.line <= rangeEndLine && diagnosticEndLine >= rangeStartLine);
|
|
59852
|
-
};
|
|
59853
|
-
//#endregion
|
|
59854
59747
|
//#region src/cli/utils/materialize-baseline-files.ts
|
|
59855
59748
|
/**
|
|
59856
59749
|
* Materializes the `ref` version of `files` into `tempDirectory` (via
|
|
@@ -61036,7 +60929,7 @@ const buildChangedLineMatcher = (directory, changedLineRanges) => {
|
|
|
61036
60929
|
const relativePath = toForwardSlashes(path.isAbsolute(diagnostic.filePath) ? path.relative(directory, diagnostic.filePath) : diagnostic.filePath);
|
|
61037
60930
|
const ranges = rangesByFile.get(relativePath);
|
|
61038
60931
|
if (ranges === void 0) return false;
|
|
61039
|
-
return
|
|
60932
|
+
return ranges.some(([start, end]) => diagnostic.line >= start && diagnostic.line <= end);
|
|
61040
60933
|
};
|
|
61041
60934
|
};
|
|
61042
60935
|
const buildIgnoredTags = (userConfig) => {
|
|
@@ -63858,15 +63751,10 @@ const warnIfAiTrainingEnvironment = () => {
|
|
|
63858
63751
|
//#region src/cli/utils/validate-mode-flags.ts
|
|
63859
63752
|
const usedDiffAlias = (flags) => flags.diff !== void 0 && flags.diff !== false && flags.diff !== "false" && flags.diff !== "";
|
|
63860
63753
|
const usedScope = (flags) => typeof flags.scope === "string" && flags.scope.length > 0;
|
|
63861
|
-
const validateIncludeUntrackedScope = (includeUntracked, scope) => {
|
|
63862
|
-
if (!includeUntracked || scope !== void 0 && scope !== "full") return;
|
|
63863
|
-
throw new CliInputError("--include-untracked requires the files, changed, or lines scope (via --scope, --diff, or config).");
|
|
63864
|
-
};
|
|
63865
63754
|
const validateModeFlags = (flags) => {
|
|
63866
63755
|
if (usedScope(flags) && usedDiffAlias(flags)) throw new CliInputError("Cannot combine --scope and --diff; --diff is the deprecated alias.");
|
|
63867
63756
|
if (flags.staged && usedDiffAlias(flags)) throw new CliInputError("Cannot combine --staged and --diff; pick one mode.");
|
|
63868
63757
|
if (flags.staged && (flags.scope === "full" || flags.scope === "changed")) throw new CliInputError(`Cannot combine --staged with --scope ${flags.scope}; use --scope files or --scope lines, or drop --scope.`);
|
|
63869
|
-
if (flags.includeUntracked && flags.staged) throw new CliInputError("Cannot combine --include-untracked with --staged; the git index never holds untracked files.");
|
|
63870
63758
|
if (flags.score && flags.json) throw new CliInputError("Cannot combine --score and --json; pick one output mode.");
|
|
63871
63759
|
if (flags.score && flags.telemetry === false) throw new CliInputError("Cannot combine --score with --no-telemetry; --score prints the score that --no-telemetry disables.");
|
|
63872
63760
|
if (flags.debug && (flags.score === false || flags.telemetry === false)) {
|
|
@@ -63875,39 +63763,6 @@ const validateModeFlags = (flags) => {
|
|
|
63875
63763
|
}
|
|
63876
63764
|
};
|
|
63877
63765
|
//#endregion
|
|
63878
|
-
//#region src/cli/utils/parse-staged-snapshot-divergences.ts
|
|
63879
|
-
const SNAPSHOT_CONFIG_FILENAMES = new Set([...STAGED_FILES_PROJECT_CONFIG_FILENAMES, ...STAGED_SNAPSHOT_ADDITIONAL_CONFIG_FILENAMES]);
|
|
63880
|
-
const parseStagedSnapshotDivergences = (statusOutput) => {
|
|
63881
|
-
const divergentConfigFiles = /* @__PURE__ */ new Set();
|
|
63882
|
-
const statusEntries = statusOutput.split("\0").filter((entry) => entry.length > 0);
|
|
63883
|
-
for (let entryIndex = 0; entryIndex < statusEntries.length; entryIndex += 1) {
|
|
63884
|
-
const entry = statusEntries[entryIndex];
|
|
63885
|
-
const [indexStatus, worktreeStatus] = entry;
|
|
63886
|
-
const filePath = entry.slice(3);
|
|
63887
|
-
const hasRenameOrCopySource = indexStatus === "R" || indexStatus === "C" || worktreeStatus === "R" || worktreeStatus === "C";
|
|
63888
|
-
const sourcePath = hasRenameOrCopySource ? statusEntries[entryIndex + 1] : void 0;
|
|
63889
|
-
const worktreePaths = worktreeStatus === "R" || worktreeStatus === "C" ? [filePath, sourcePath] : [filePath];
|
|
63890
|
-
if (worktreeStatus !== " ") {
|
|
63891
|
-
for (const worktreePath of worktreePaths) if (worktreePath && SNAPSHOT_CONFIG_FILENAMES.has(Path.basename(worktreePath))) divergentConfigFiles.add(worktreePath);
|
|
63892
|
-
}
|
|
63893
|
-
if (hasRenameOrCopySource) entryIndex += 1;
|
|
63894
|
-
}
|
|
63895
|
-
return [...divergentConfigFiles].sort();
|
|
63896
|
-
};
|
|
63897
|
-
//#endregion
|
|
63898
|
-
//#region src/cli/utils/find-staged-snapshot-divergences.ts
|
|
63899
|
-
const findStagedSnapshotDivergences = (directory) => {
|
|
63900
|
-
const statusOutput = runGitRaw(directory, [
|
|
63901
|
-
"status",
|
|
63902
|
-
"--porcelain=v1",
|
|
63903
|
-
"-z",
|
|
63904
|
-
"--untracked-files=all",
|
|
63905
|
-
"--ignored=matching"
|
|
63906
|
-
]);
|
|
63907
|
-
if (statusOutput === null) return null;
|
|
63908
|
-
return parseStagedSnapshotDivergences(statusOutput);
|
|
63909
|
-
};
|
|
63910
|
-
//#endregion
|
|
63911
63766
|
//#region src/cli/commands/inspect.ts
|
|
63912
63767
|
const filterCompletedScansByCategories = (completedScans, categoryFilters) => {
|
|
63913
63768
|
if (categoryFilters.size === 0) return [...completedScans];
|
|
@@ -63922,14 +63777,9 @@ const filterCompletedScansByCategories = (completedScans, categoryFilters) => {
|
|
|
63922
63777
|
/**
|
|
63923
63778
|
* Post-scan finalization shared by the staged-arm and project-loop
|
|
63924
63779
|
* paths of `inspectAction`: emit the JSON report (when in JSON mode)
|
|
63925
|
-
* and set `process.exitCode = 1` when
|
|
63926
|
-
* (
|
|
63927
|
-
*
|
|
63928
|
-
* threshold (default `"error"`) reaches the `ciFailure` surface.
|
|
63929
|
-
* `--blocking none` keeps the scan advisory (always exits 0), and
|
|
63930
|
-
* fail-open degradations — `--no-lint`, `--max-duration` truncation,
|
|
63931
|
-
* supply-chain/security skips — stay advisory too, surfaced through
|
|
63932
|
-
* `complete: false` in the JSON report.
|
|
63780
|
+
* and set `process.exitCode = 1` when a diagnostic at or above the
|
|
63781
|
+
* `--blocking` threshold (default `"error"`) reaches the `ciFailure`
|
|
63782
|
+
* surface. `--blocking none` keeps the scan advisory (always exits 0).
|
|
63933
63783
|
*/
|
|
63934
63784
|
const finalizeScans = (input) => {
|
|
63935
63785
|
const baselineDeltas = input.completedScans.flatMap((scan) => scan.result.baselineDelta ? [scan.result.baselineDelta] : []);
|
|
@@ -63959,13 +63809,8 @@ const finalizeScans = (input) => {
|
|
|
63959
63809
|
baselineDegraded
|
|
63960
63810
|
}));
|
|
63961
63811
|
}
|
|
63962
|
-
const blockingLevel = resolveBlockingLevel(input.flags, input.userConfig);
|
|
63963
|
-
if (input.completedScans.some(({ result }) => hasLintHardFailure(result)) && blockingLevel !== "none") {
|
|
63964
|
-
process.exitCode = 1;
|
|
63965
|
-
return;
|
|
63966
|
-
}
|
|
63967
63812
|
if (input.isScoreOnly || baselineDegraded) return;
|
|
63968
|
-
if (shouldBlockCi(filterScansForSurface(input.completedScans, "ciFailure"),
|
|
63813
|
+
if (shouldBlockCi(filterScansForSurface(input.completedScans, "ciFailure"), resolveBlockingLevel(input.flags, input.userConfig))) process.exitCode = 1;
|
|
63969
63814
|
};
|
|
63970
63815
|
const buildChangedFilesDiffInfo = (changedFiles) => ({
|
|
63971
63816
|
currentBranch: process.env.GITHUB_HEAD_REF?.trim() || null,
|
|
@@ -64003,7 +63848,6 @@ const inspectAction = async (directory, flags) => {
|
|
|
64003
63848
|
recordCount(METRIC.cliInvoked, 1, { command: "inspect" });
|
|
64004
63849
|
try {
|
|
64005
63850
|
validateModeFlags(flags);
|
|
64006
|
-
if (flags.staged) setJsonReportMode("staged");
|
|
64007
63851
|
await maybeMigrateLegacyConfig(requestedDirectory, {
|
|
64008
63852
|
isQuiet,
|
|
64009
63853
|
isStaged: Boolean(flags.staged)
|
|
@@ -64019,14 +63863,6 @@ const inspectAction = async (directory, flags) => {
|
|
|
64019
63863
|
cliLogger.dim(`Redirected to ${highlighter.info(toRelativePath(resolvedDirectory, requestedDirectory))} via react-doctor config "rootDir".`);
|
|
64020
63864
|
cliLogger.break();
|
|
64021
63865
|
}
|
|
64022
|
-
if (flags.staged) {
|
|
64023
|
-
const divergentConfigFiles = findStagedSnapshotDivergences(resolvedDirectory);
|
|
64024
|
-
if (divergentConfigFiles === null) throw new CliInputError("Could not verify that staged configuration matches the worktree. Run the command from a Git worktree with Git available.");
|
|
64025
|
-
if (divergentConfigFiles.length > 0) {
|
|
64026
|
-
recordCount(METRIC.stagedSnapshotDivergence, 1, { divergentInputCount: divergentConfigFiles.length });
|
|
64027
|
-
throw new CliInputError(`Cannot scan staged files while configuration differs between the index and worktree: ${divergentConfigFiles.join(", ")}. Stage or restore those files, then rerun react-doctor --staged.`);
|
|
64028
|
-
}
|
|
64029
|
-
}
|
|
64030
63866
|
const explainArgument = flags.explain;
|
|
64031
63867
|
if (explainArgument !== void 0) {
|
|
64032
63868
|
await runExplain(explainArgument, {
|
|
@@ -64047,6 +63883,7 @@ const inspectAction = async (directory, flags) => {
|
|
|
64047
63883
|
json: flags.json
|
|
64048
63884
|
});
|
|
64049
63885
|
if (flags.staged) {
|
|
63886
|
+
setJsonReportMode("staged");
|
|
64050
63887
|
const stagedFiles = await getStagedSourceFiles(resolvedDirectory);
|
|
64051
63888
|
if (stagedFiles.length === 0) {
|
|
64052
63889
|
if (isJsonMode) writeJsonReport(buildJsonReport({
|
|
@@ -64127,15 +63964,13 @@ const inspectAction = async (directory, flags) => {
|
|
|
64127
63964
|
const projectDirectories = await selectProjects(resolvedDirectory, flags.project, skipPrompts, userConfig?.projects);
|
|
64128
63965
|
const changedFilesDiffInfo = flags.changedFilesFrom ? buildChangedFilesDiffInfo(readChangedFilesFrom(Path.resolve(flags.changedFilesFrom))) : null;
|
|
64129
63966
|
const requestedScope = resolveScope(flags, userConfig);
|
|
64130
|
-
const includeUntracked = flags.includeUntracked ?? false;
|
|
64131
63967
|
const scopeRequest = requestedScope.scope === void 0 && changedFilesDiffInfo !== null ? {
|
|
64132
63968
|
...requestedScope,
|
|
64133
63969
|
scope: "changed"
|
|
64134
63970
|
} : requestedScope;
|
|
64135
|
-
validateIncludeUntrackedScope(includeUntracked, scopeRequest.scope);
|
|
64136
63971
|
const wantsDiffMode = scopeRequest.scope !== void 0 && scopeRequest.scope !== "full";
|
|
64137
63972
|
const shouldDetectDiff = changedFilesDiffInfo === null && (wantsDiffMode || scopeRequest.scope === void 0 && !skipPrompts && !isQuiet);
|
|
64138
|
-
const diffInfo = changedFilesDiffInfo ?? (shouldDetectDiff ? await getDiffInfo(resolvedDirectory, scopeRequest.base
|
|
63973
|
+
const diffInfo = changedFilesDiffInfo ?? (shouldDetectDiff ? await getDiffInfo(resolvedDirectory, scopeRequest.base) : null);
|
|
64139
63974
|
const scope = await finalizeScope({
|
|
64140
63975
|
requested: scopeRequest,
|
|
64141
63976
|
diffInfo,
|
|
@@ -64149,8 +63984,7 @@ const inspectAction = async (directory, flags) => {
|
|
|
64149
63984
|
const changedLineRanges = scope === "lines" && diffInfo !== null && (diffInfo.isCurrentChanges || linesBaseRef !== null) && diffInfo !== null ? await getChangedLineRanges({
|
|
64150
63985
|
directory: resolvedDirectory,
|
|
64151
63986
|
baseRef: linesBaseRef ?? void 0,
|
|
64152
|
-
files: [...diffInfo.changedFiles]
|
|
64153
|
-
includeUntracked
|
|
63987
|
+
files: [...diffInfo.changedFiles]
|
|
64154
63988
|
}) : null;
|
|
64155
63989
|
if (scope === "lines" && changedLineRanges === null && !isQuiet) {
|
|
64156
63990
|
cliLogger.warn("Could not determine changed lines (no base ref or git diff failed); reporting all issues in changed files.");
|
|
@@ -65083,7 +64917,6 @@ const ROOT_FLAG_SPEC = {
|
|
|
65083
64917
|
"--dead-code",
|
|
65084
64918
|
"--debug",
|
|
65085
64919
|
"--help",
|
|
65086
|
-
"--include-untracked",
|
|
65087
64920
|
"--json",
|
|
65088
64921
|
"--json-compact",
|
|
65089
64922
|
"--lint",
|
|
@@ -65347,7 +65180,7 @@ ${highlighter.dim("Learn more:")}
|
|
|
65347
65180
|
${highlighter.info(CI_URL)}
|
|
65348
65181
|
`;
|
|
65349
65182
|
const collectCategoryOption = (value, previousValues) => [...previousValues ?? [], value];
|
|
65350
|
-
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS source to scan/report: full (default), files, changed (only new issues vs base), or lines (
|
|
65183
|
+
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS source to scan/report: full (default), files, changed (only new issues vs base), or lines (only changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").addOption(new Option("--diff [base]", "[deprecated] alias for --scope changed (pass `false` to force a full scan)").hideHelp()).addOption(new Option("--changed-files-from <file>", "scan source files listed in a newline-delimited changed-files file").hideHelp()).option("--no-score", "skip the score API, the share URL, and crash reporting").addOption(new Option("--category <category>", "only show diagnostics in a category (repeatable; e.g. Security)").argParser(collectCategoryOption)).option("--no-telemetry", "alias for --no-score (skip the score API, share URL, and crash reporting)").option("--staged", "scan only staged (git index) files for pre-commit hooks").option("--max-duration <seconds>", "scan time budget for the whole run, shared across workspace projects: past it, remaining lint batches and dead-code are skipped and partial results are reported (skipped files are listed in the JSON report)").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").addOption(new Option("--fail-on <level>", "[deprecated] alias for --blocking <level>").hideHelp()).option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").option("--warnings", "show warning-severity diagnostics (default)").option("--no-warnings", "hide warning-severity diagnostics (errors only)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderRootHelpEpilog);
|
|
65351
65184
|
program.action(inspectAction);
|
|
65352
65185
|
program.command("why <location>").description("Explain why a rule fired (or why a suppression didn't apply) at a file:line").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple)").option("-c, --cwd <cwd>", "working directory", process.cwd()).option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").action((location, options) => whyAction(location, options));
|
|
65353
65186
|
program.command("install").alias("setup").description("Install the react-doctor skill into your coding agents and optional git hook").option("-y, --yes", "skip prompts, install for all detected agents").option("--dry-run", "show what would be installed without writing files").option("--agent-hooks", "install native non-blocking agent hooks for Claude Code and Cursor").option("-c, --cwd <cwd>", "working directory", process.cwd()).option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderInstallHelpEpilog).action(installAction);
|
|
@@ -65397,4 +65230,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
65397
65230
|
export {};
|
|
65398
65231
|
|
|
65399
65232
|
//# sourceMappingURL=cli.js.map
|
|
65400
|
-
//# debugId=
|
|
65233
|
+
//# debugId=bc56f5c4-5b95-5727-8e86-d43a534abbbc
|
package/dist/index.d.ts
CHANGED
|
@@ -10256,7 +10256,7 @@ declare const buildJsonReport: (input: BuildJsonReportInput) => JsonReportV3$1;
|
|
|
10256
10256
|
* render diff-base mistakes (`GitBaseBranchInvalid` /
|
|
10257
10257
|
* `GitBaseBranchMissing`) as clean user errors instead of crashes.
|
|
10258
10258
|
*/
|
|
10259
|
-
declare const getDiffInfo: (directory: string, explicitBaseBranch?: string
|
|
10259
|
+
declare const getDiffInfo: (directory: string, explicitBaseBranch?: string) => Promise<DiffInfo | null>;
|
|
10260
10260
|
declare const filterSourceFiles: (filePaths: string[]) => string[];
|
|
10261
10261
|
/**
|
|
10262
10262
|
* Programmatic façade over `Git.changedLineRanges` (the `lines` scope). Diffs
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3e7262c1-34a6-5fd7-a4a2-5e7a15ca735d")}catch(e){}}();
|
|
3
3
|
import { r as __toESM$1, t as __commonJSMin$1 } from "./chunk-N93fKeF6.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
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";
|
|
@@ -33142,15 +33142,13 @@ const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
|
33142
33142
|
const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort());
|
|
33143
33143
|
const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
|
|
33144
33144
|
const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
|
|
33145
|
-
const UTF8_BOM_CHARACTER = "";
|
|
33146
|
-
const stripUtf8Bom = (content) => content.startsWith(UTF8_BOM_CHARACTER) ? content.slice(1) : content;
|
|
33147
33145
|
const cachedPackageJsons = /* @__PURE__ */ new Map();
|
|
33148
33146
|
const clearPackageJsonCache = () => {
|
|
33149
33147
|
cachedPackageJsons.clear();
|
|
33150
33148
|
};
|
|
33151
33149
|
const readPackageJsonUncached = (packageJsonPath) => {
|
|
33152
33150
|
try {
|
|
33153
|
-
return JSON.parse(
|
|
33151
|
+
return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
33154
33152
|
} catch (error) {
|
|
33155
33153
|
if (error instanceof SyntaxError) return {};
|
|
33156
33154
|
if (isErrnoException(error)) {
|
|
@@ -36791,6 +36789,7 @@ const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
|
|
|
36791
36789
|
const PNPM_LOCKFILE = "pnpm-lock.yaml";
|
|
36792
36790
|
const PACKAGE_JSON_FILE = "package.json";
|
|
36793
36791
|
const PNPM_HARDENING_RULE_KEY = "require-pnpm-hardening";
|
|
36792
|
+
const UTF8_BOM_CHAR = "";
|
|
36794
36793
|
const HARDENING_SETTING_KEYS = new Set([
|
|
36795
36794
|
"minimumReleaseAge",
|
|
36796
36795
|
"blockExoticSubdeps",
|
|
@@ -36815,11 +36814,12 @@ const stripInlineComment = (rawValue) => {
|
|
|
36815
36814
|
return rawValue;
|
|
36816
36815
|
};
|
|
36817
36816
|
const unquote = (rawValue) => rawValue.replace(/^["']|["']$/g, "");
|
|
36817
|
+
const stripBom = (rawContent) => rawContent.startsWith(UTF8_BOM_CHAR) ? rawContent.slice(1) : rawContent;
|
|
36818
36818
|
const parseHardeningSettings = (content) => {
|
|
36819
36819
|
let minimumReleaseAge = null;
|
|
36820
36820
|
let blockExoticSubdeps = null;
|
|
36821
36821
|
let trustPolicy = null;
|
|
36822
|
-
const lines =
|
|
36822
|
+
const lines = stripBom(content).split(/\r?\n/);
|
|
36823
36823
|
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
36824
36824
|
const lineText = lines[lineIndex];
|
|
36825
36825
|
if (lineText === void 0) continue;
|
|
@@ -36853,7 +36853,7 @@ const isPnpmManagedProject = (rootDirectory) => {
|
|
|
36853
36853
|
const packageJsonPath = Path.join(rootDirectory, PACKAGE_JSON_FILE);
|
|
36854
36854
|
if (!isFile(packageJsonPath)) return false;
|
|
36855
36855
|
try {
|
|
36856
|
-
const packageJsonRaw =
|
|
36856
|
+
const packageJsonRaw = NFS.readFileSync(packageJsonPath, "utf-8");
|
|
36857
36857
|
const packageJson = JSON.parse(packageJsonRaw);
|
|
36858
36858
|
if (packageJson !== null && typeof packageJson === "object" && "packageManager" in packageJson && typeof packageJson.packageManager === "string" && packageJson.packageManager.startsWith("pnpm@")) return true;
|
|
36859
36859
|
} catch {
|
|
@@ -38579,7 +38579,6 @@ const parseGithubViewerPermission = (stdout) => {
|
|
|
38579
38579
|
return /^[A-Z_]+$/.test(value) ? value.toLowerCase() : null;
|
|
38580
38580
|
};
|
|
38581
38581
|
const splitNullSeparated = (value) => value.split("\0").filter((entry) => entry.length > 0);
|
|
38582
|
-
const UNTRACKED_FILE_LAST_LINE = Number.MAX_SAFE_INTEGER;
|
|
38583
38582
|
/**
|
|
38584
38583
|
* `Git` wraps every `git`-via-subprocess call react-doctor makes
|
|
38585
38584
|
* behind a `Context.Service`. The production layer (`layerNode`)
|
|
@@ -38650,14 +38649,6 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38650
38649
|
args,
|
|
38651
38650
|
directory
|
|
38652
38651
|
});
|
|
38653
|
-
const listUntrackedFilePaths = (directory, includePaths = []) => runGit(directory, [
|
|
38654
|
-
"ls-files",
|
|
38655
|
-
"-z",
|
|
38656
|
-
"--others",
|
|
38657
|
-
"--exclude-standard",
|
|
38658
|
-
...includePaths.length > 0 ? ["--", ...includePaths] : []
|
|
38659
|
-
]).pipe(map$3((result) => result.status === 0 ? splitNullSeparated(result.stdout) : null));
|
|
38660
|
-
const mergeUntracked = (directory, trackedFilePaths, includeUntracked) => includeUntracked ? listUntrackedFilePaths(directory).pipe(map$3((untracked) => untracked === null ? trackedFilePaths : [...new Set([...trackedFilePaths, ...untracked])])) : succeed$2(trackedFilePaths);
|
|
38661
38652
|
const currentBranch = (directory) => runGit(directory, [
|
|
38662
38653
|
"rev-parse",
|
|
38663
38654
|
"--abbrev-ref",
|
|
@@ -38780,7 +38771,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38780
38771
|
githubViewerPermission,
|
|
38781
38772
|
branchExists,
|
|
38782
38773
|
mergeBase,
|
|
38783
|
-
diffSelection: ({ directory, explicitBaseBranch
|
|
38774
|
+
diffSelection: ({ directory, explicitBaseBranch }) => gen(function* () {
|
|
38784
38775
|
if (explicitBaseBranch !== void 0 && explicitBaseBranch.trim().length === 0) return yield* fail$4(new ReactDoctorError({ reason: new GitBaseBranchInvalid({ detail: "Diff base branch cannot be empty." }) }));
|
|
38785
38776
|
if (explicitBaseBranch !== void 0) {
|
|
38786
38777
|
const range = parseGitDiffRange(explicitBaseBranch);
|
|
@@ -38809,7 +38800,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38809
38800
|
"HEAD"
|
|
38810
38801
|
]);
|
|
38811
38802
|
if (uncommitted.status !== 0) return null;
|
|
38812
|
-
const files =
|
|
38803
|
+
const files = splitNullSeparated(uncommitted.stdout);
|
|
38813
38804
|
if (files.length === 0) return null;
|
|
38814
38805
|
return {
|
|
38815
38806
|
currentBranch: resolvedCurrentBranch,
|
|
@@ -38839,7 +38830,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38839
38830
|
currentBranch: resolvedCurrentBranch,
|
|
38840
38831
|
baseBranch,
|
|
38841
38832
|
diffBaseRef: mergeBaseRef,
|
|
38842
|
-
changedFiles:
|
|
38833
|
+
changedFiles: splitNullSeparated(diff.stdout),
|
|
38843
38834
|
isCurrentChanges: false
|
|
38844
38835
|
};
|
|
38845
38836
|
}).pipe(withSpan("Git.diffSelection")),
|
|
@@ -38885,7 +38876,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38885
38876
|
stdout: result.stdout
|
|
38886
38877
|
};
|
|
38887
38878
|
}).pipe(withSpan("Git.grep")),
|
|
38888
|
-
changedLineRanges: ({ directory, baseRef, cached, files
|
|
38879
|
+
changedLineRanges: ({ directory, baseRef, cached, files }) => gen(function* () {
|
|
38889
38880
|
if (files.length === 0) return [];
|
|
38890
38881
|
if (baseRef !== void 0 && !isSafeGitRevision(baseRef)) return null;
|
|
38891
38882
|
const result = yield* runGit(directory, [
|
|
@@ -38899,14 +38890,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38899
38890
|
...files
|
|
38900
38891
|
]);
|
|
38901
38892
|
if (result.status !== 0) return null;
|
|
38902
|
-
|
|
38903
|
-
if (cached || !includeUntracked) return changedLineRanges;
|
|
38904
|
-
const untrackedFilePaths = yield* listUntrackedFilePaths(directory, files);
|
|
38905
|
-
if (untrackedFilePaths === null) return changedLineRanges;
|
|
38906
|
-
return [...changedLineRanges, ...untrackedFilePaths.map((file) => ({
|
|
38907
|
-
file,
|
|
38908
|
-
ranges: [[1, UNTRACKED_FILE_LAST_LINE]]
|
|
38909
|
-
}))];
|
|
38893
|
+
return parseChangedLineRanges(result.stdout);
|
|
38910
38894
|
}).pipe(catch_$1((error) => error.reason._tag === "GitInvocationFailed" ? succeed$2(null) : fail$4(error)), withSpan("Git.changedLineRanges"))
|
|
38911
38895
|
});
|
|
38912
38896
|
})).pipe(provide$2(layer$2.pipe(provide$2(mergeAll$1(layer$1, layer)))));
|
|
@@ -39658,12 +39642,6 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
39658
39642
|
if (errors.length > 0) throw errors[0];
|
|
39659
39643
|
return results;
|
|
39660
39644
|
};
|
|
39661
|
-
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
39662
|
-
let lineNumber = 1;
|
|
39663
|
-
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
39664
|
-
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === 10) lineNumber++;
|
|
39665
|
-
return lineNumber;
|
|
39666
|
-
};
|
|
39667
39645
|
const REANIMATED_SHARED_VALUE_HINT = "If this is a Reanimated shared value, prefer its React Compiler-compatible `.get()` / `.set()` accessors over `.value` — https://docs.swmansion.com/react-native-reanimated/docs/core/useSharedValue/#react-compiler-support";
|
|
39668
39646
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
39669
39647
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -40235,6 +40213,13 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
40235
40213
|
visit(sourceFile);
|
|
40236
40214
|
return foundRange;
|
|
40237
40215
|
};
|
|
40216
|
+
const NEWLINE_BYTE = 10;
|
|
40217
|
+
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
40218
|
+
let lineNumber = 1;
|
|
40219
|
+
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
40220
|
+
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
|
|
40221
|
+
return lineNumber;
|
|
40222
|
+
};
|
|
40238
40223
|
/**
|
|
40239
40224
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
40240
40225
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -40415,11 +40400,11 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
40415
40400
|
}
|
|
40416
40401
|
return related;
|
|
40417
40402
|
};
|
|
40418
|
-
const
|
|
40419
|
-
|
|
40420
|
-
const
|
|
40421
|
-
|
|
40422
|
-
|
|
40403
|
+
const isOxlintOutput = (value) => {
|
|
40404
|
+
if (typeof value !== "object" || value === null) return false;
|
|
40405
|
+
const candidate = value;
|
|
40406
|
+
return Array.isArray(candidate.diagnostics);
|
|
40407
|
+
};
|
|
40423
40408
|
/**
|
|
40424
40409
|
* Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
|
|
40425
40410
|
* Tolerates the leading-notice-line shape oxlint sometimes prints
|
|
@@ -40438,59 +40423,23 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40438
40423
|
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40439
40424
|
}
|
|
40440
40425
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40441
|
-
const engineFailureDiagnostic = parsed.diagnostics.find(isEngineFailureDiagnostic);
|
|
40442
|
-
if (engineFailureDiagnostic !== void 0) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: JSON.stringify(engineFailureDiagnostic).slice(0, 600) }) });
|
|
40443
40426
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
40444
|
-
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
40445
|
-
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
40446
|
-
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
40447
|
-
const readSourceBuffer = (filename) => {
|
|
40448
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
40449
|
-
const cached = sourceBufferCache.get(absolutePath);
|
|
40450
|
-
if (cached !== void 0) return cached;
|
|
40451
|
-
let sourceBuffer;
|
|
40452
|
-
try {
|
|
40453
|
-
sourceBuffer = NFS.readFileSync(absolutePath);
|
|
40454
|
-
} catch {
|
|
40455
|
-
sourceBuffer = null;
|
|
40456
|
-
}
|
|
40457
|
-
sourceBufferCache.set(absolutePath, sourceBuffer);
|
|
40458
|
-
return sourceBuffer;
|
|
40459
|
-
};
|
|
40460
|
-
const readSourceLines = (filename) => {
|
|
40461
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
40462
|
-
const cached = sourceLinesCache.get(absolutePath);
|
|
40463
|
-
if (cached !== void 0) return cached;
|
|
40464
|
-
const sourceBuffer = readSourceBuffer(filename);
|
|
40465
|
-
const sourceLines = sourceBuffer ? sourceBuffer.toString("utf8").split("\n") : null;
|
|
40466
|
-
sourceLinesCache.set(absolutePath, sourceLines);
|
|
40467
|
-
return sourceLines;
|
|
40468
|
-
};
|
|
40469
40427
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
40470
|
-
const absolutePath =
|
|
40428
|
+
const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
40471
40429
|
const cached = minifiedFileCache.get(absolutePath);
|
|
40472
40430
|
if (cached !== void 0) return cached;
|
|
40473
40431
|
const minified = isMinifiedSource(absolutePath);
|
|
40474
40432
|
minifiedFileCache.set(absolutePath, minified);
|
|
40475
40433
|
return minified;
|
|
40476
40434
|
};
|
|
40477
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) =>
|
|
40435
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
40478
40436
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
40479
40437
|
const primaryLabel = diagnostic.labels[0];
|
|
40480
40438
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
40481
40439
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
40482
40440
|
const primarySpan = primaryLabel?.span;
|
|
40483
|
-
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
40484
40441
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
40485
40442
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
40486
|
-
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
40487
|
-
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
40488
|
-
const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
|
|
40489
|
-
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
40490
|
-
const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
|
|
40491
|
-
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
40492
|
-
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
40493
|
-
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
40494
40443
|
return {
|
|
40495
40444
|
filePath: normalizedFilePath,
|
|
40496
40445
|
plugin,
|
|
@@ -40504,11 +40453,10 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40504
40453
|
column: primarySpan?.column ?? 0,
|
|
40505
40454
|
...primarySpan ? {
|
|
40506
40455
|
offset: primarySpan.offset,
|
|
40507
|
-
length: primarySpan.length
|
|
40508
|
-
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
40456
|
+
length: primarySpan.length
|
|
40509
40457
|
} : {},
|
|
40510
40458
|
category,
|
|
40511
|
-
...
|
|
40459
|
+
...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
|
|
40512
40460
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
40513
40461
|
};
|
|
40514
40462
|
}), rootDirectory);
|
|
@@ -42966,11 +42914,10 @@ const buildSkippedChecks = (input) => {
|
|
|
42966
42914
|
* render diff-base mistakes (`GitBaseBranchInvalid` /
|
|
42967
42915
|
* `GitBaseBranchMissing`) as clean user errors instead of crashes.
|
|
42968
42916
|
*/
|
|
42969
|
-
const getDiffInfo = (directory, explicitBaseBranch
|
|
42917
|
+
const getDiffInfo = (directory, explicitBaseBranch) => runPromise(gen(function* () {
|
|
42970
42918
|
const selection = yield* (yield* Git).diffSelection({
|
|
42971
42919
|
directory,
|
|
42972
|
-
explicitBaseBranch
|
|
42973
|
-
includeUntracked
|
|
42920
|
+
explicitBaseBranch
|
|
42974
42921
|
});
|
|
42975
42922
|
if (selection === null) return null;
|
|
42976
42923
|
return {
|
|
@@ -43260,4 +43207,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
43260
43207
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
43261
43208
|
|
|
43262
43209
|
//# sourceMappingURL=index.js.map
|
|
43263
|
-
//# debugId=
|
|
43210
|
+
//# debugId=3e7262c1-34a6-5fd7-a4a2-5e7a15ca735d
|
package/dist/lsp.js
CHANGED
|
@@ -33194,15 +33194,13 @@ const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
|
33194
33194
|
const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort());
|
|
33195
33195
|
const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
|
|
33196
33196
|
const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
|
|
33197
|
-
const UTF8_BOM_CHARACTER = "";
|
|
33198
|
-
const stripUtf8Bom = (content) => content.startsWith(UTF8_BOM_CHARACTER) ? content.slice(1) : content;
|
|
33199
33197
|
const cachedPackageJsons = /* @__PURE__ */ new Map();
|
|
33200
33198
|
const clearPackageJsonCache = () => {
|
|
33201
33199
|
cachedPackageJsons.clear();
|
|
33202
33200
|
};
|
|
33203
33201
|
const readPackageJsonUncached = (packageJsonPath) => {
|
|
33204
33202
|
try {
|
|
33205
|
-
return JSON.parse(
|
|
33203
|
+
return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
33206
33204
|
} catch (error) {
|
|
33207
33205
|
if (error instanceof SyntaxError) return {};
|
|
33208
33206
|
if (isErrnoException(error)) {
|
|
@@ -36769,6 +36767,7 @@ const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
|
|
|
36769
36767
|
const PNPM_LOCKFILE = "pnpm-lock.yaml";
|
|
36770
36768
|
const PACKAGE_JSON_FILE = "package.json";
|
|
36771
36769
|
const PNPM_HARDENING_RULE_KEY = "require-pnpm-hardening";
|
|
36770
|
+
const UTF8_BOM_CHAR = "";
|
|
36772
36771
|
const HARDENING_SETTING_KEYS = new Set([
|
|
36773
36772
|
"minimumReleaseAge",
|
|
36774
36773
|
"blockExoticSubdeps",
|
|
@@ -36793,11 +36792,12 @@ const stripInlineComment = (rawValue) => {
|
|
|
36793
36792
|
return rawValue;
|
|
36794
36793
|
};
|
|
36795
36794
|
const unquote = (rawValue) => rawValue.replace(/^["']|["']$/g, "");
|
|
36795
|
+
const stripBom = (rawContent) => rawContent.startsWith(UTF8_BOM_CHAR) ? rawContent.slice(1) : rawContent;
|
|
36796
36796
|
const parseHardeningSettings = (content) => {
|
|
36797
36797
|
let minimumReleaseAge = null;
|
|
36798
36798
|
let blockExoticSubdeps = null;
|
|
36799
36799
|
let trustPolicy = null;
|
|
36800
|
-
const lines =
|
|
36800
|
+
const lines = stripBom(content).split(/\r?\n/);
|
|
36801
36801
|
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
36802
36802
|
const lineText = lines[lineIndex];
|
|
36803
36803
|
if (lineText === void 0) continue;
|
|
@@ -36831,7 +36831,7 @@ const isPnpmManagedProject = (rootDirectory) => {
|
|
|
36831
36831
|
const packageJsonPath = Path.join(rootDirectory, PACKAGE_JSON_FILE);
|
|
36832
36832
|
if (!isFile(packageJsonPath)) return false;
|
|
36833
36833
|
try {
|
|
36834
|
-
const packageJsonRaw =
|
|
36834
|
+
const packageJsonRaw = NFS.readFileSync(packageJsonPath, "utf-8");
|
|
36835
36835
|
const packageJson = JSON.parse(packageJsonRaw);
|
|
36836
36836
|
if (packageJson !== null && typeof packageJson === "object" && "packageManager" in packageJson && typeof packageJson.packageManager === "string" && packageJson.packageManager.startsWith("pnpm@")) return true;
|
|
36837
36837
|
} catch {
|
|
@@ -38557,7 +38557,6 @@ const parseGithubViewerPermission = (stdout) => {
|
|
|
38557
38557
|
return /^[A-Z_]+$/.test(value) ? value.toLowerCase() : null;
|
|
38558
38558
|
};
|
|
38559
38559
|
const splitNullSeparated = (value) => value.split("\0").filter((entry) => entry.length > 0);
|
|
38560
|
-
const UNTRACKED_FILE_LAST_LINE = Number.MAX_SAFE_INTEGER;
|
|
38561
38560
|
/**
|
|
38562
38561
|
* `Git` wraps every `git`-via-subprocess call react-doctor makes
|
|
38563
38562
|
* behind a `Context.Service`. The production layer (`layerNode`)
|
|
@@ -38628,14 +38627,6 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38628
38627
|
args,
|
|
38629
38628
|
directory
|
|
38630
38629
|
});
|
|
38631
|
-
const listUntrackedFilePaths = (directory, includePaths = []) => runGit(directory, [
|
|
38632
|
-
"ls-files",
|
|
38633
|
-
"-z",
|
|
38634
|
-
"--others",
|
|
38635
|
-
"--exclude-standard",
|
|
38636
|
-
...includePaths.length > 0 ? ["--", ...includePaths] : []
|
|
38637
|
-
]).pipe(map$3((result) => result.status === 0 ? splitNullSeparated(result.stdout) : null));
|
|
38638
|
-
const mergeUntracked = (directory, trackedFilePaths, includeUntracked) => includeUntracked ? listUntrackedFilePaths(directory).pipe(map$3((untracked) => untracked === null ? trackedFilePaths : [...new Set([...trackedFilePaths, ...untracked])])) : succeed$2(trackedFilePaths);
|
|
38639
38630
|
const currentBranch = (directory) => runGit(directory, [
|
|
38640
38631
|
"rev-parse",
|
|
38641
38632
|
"--abbrev-ref",
|
|
@@ -38758,7 +38749,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38758
38749
|
githubViewerPermission,
|
|
38759
38750
|
branchExists,
|
|
38760
38751
|
mergeBase,
|
|
38761
|
-
diffSelection: ({ directory, explicitBaseBranch
|
|
38752
|
+
diffSelection: ({ directory, explicitBaseBranch }) => gen(function* () {
|
|
38762
38753
|
if (explicitBaseBranch !== void 0 && explicitBaseBranch.trim().length === 0) return yield* fail$4(new ReactDoctorError({ reason: new GitBaseBranchInvalid({ detail: "Diff base branch cannot be empty." }) }));
|
|
38763
38754
|
if (explicitBaseBranch !== void 0) {
|
|
38764
38755
|
const range = parseGitDiffRange(explicitBaseBranch);
|
|
@@ -38787,7 +38778,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38787
38778
|
"HEAD"
|
|
38788
38779
|
]);
|
|
38789
38780
|
if (uncommitted.status !== 0) return null;
|
|
38790
|
-
const files =
|
|
38781
|
+
const files = splitNullSeparated(uncommitted.stdout);
|
|
38791
38782
|
if (files.length === 0) return null;
|
|
38792
38783
|
return {
|
|
38793
38784
|
currentBranch: resolvedCurrentBranch,
|
|
@@ -38817,7 +38808,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38817
38808
|
currentBranch: resolvedCurrentBranch,
|
|
38818
38809
|
baseBranch,
|
|
38819
38810
|
diffBaseRef: mergeBaseRef,
|
|
38820
|
-
changedFiles:
|
|
38811
|
+
changedFiles: splitNullSeparated(diff.stdout),
|
|
38821
38812
|
isCurrentChanges: false
|
|
38822
38813
|
};
|
|
38823
38814
|
}).pipe(withSpan("Git.diffSelection")),
|
|
@@ -38863,7 +38854,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38863
38854
|
stdout: result.stdout
|
|
38864
38855
|
};
|
|
38865
38856
|
}).pipe(withSpan("Git.grep")),
|
|
38866
|
-
changedLineRanges: ({ directory, baseRef, cached, files
|
|
38857
|
+
changedLineRanges: ({ directory, baseRef, cached, files }) => gen(function* () {
|
|
38867
38858
|
if (files.length === 0) return [];
|
|
38868
38859
|
if (baseRef !== void 0 && !isSafeGitRevision(baseRef)) return null;
|
|
38869
38860
|
const result = yield* runGit(directory, [
|
|
@@ -38877,14 +38868,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38877
38868
|
...files
|
|
38878
38869
|
]);
|
|
38879
38870
|
if (result.status !== 0) return null;
|
|
38880
|
-
|
|
38881
|
-
if (cached || !includeUntracked) return changedLineRanges;
|
|
38882
|
-
const untrackedFilePaths = yield* listUntrackedFilePaths(directory, files);
|
|
38883
|
-
if (untrackedFilePaths === null) return changedLineRanges;
|
|
38884
|
-
return [...changedLineRanges, ...untrackedFilePaths.map((file) => ({
|
|
38885
|
-
file,
|
|
38886
|
-
ranges: [[1, UNTRACKED_FILE_LAST_LINE]]
|
|
38887
|
-
}))];
|
|
38871
|
+
return parseChangedLineRanges(result.stdout);
|
|
38888
38872
|
}).pipe(catch_$1((error) => error.reason._tag === "GitInvocationFailed" ? succeed$2(null) : fail$4(error)), withSpan("Git.changedLineRanges"))
|
|
38889
38873
|
});
|
|
38890
38874
|
})).pipe(provide$2(layer$2.pipe(provide$2(mergeAll$1(layer$1, layer)))));
|
|
@@ -39636,12 +39620,6 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
39636
39620
|
if (errors.length > 0) throw errors[0];
|
|
39637
39621
|
return results;
|
|
39638
39622
|
};
|
|
39639
|
-
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
39640
|
-
let lineNumber = 1;
|
|
39641
|
-
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
39642
|
-
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === 10) lineNumber++;
|
|
39643
|
-
return lineNumber;
|
|
39644
|
-
};
|
|
39645
39623
|
const REANIMATED_SHARED_VALUE_HINT = "If this is a Reanimated shared value, prefer its React Compiler-compatible `.get()` / `.set()` accessors over `.value` — https://docs.swmansion.com/react-native-reanimated/docs/core/useSharedValue/#react-compiler-support";
|
|
39646
39624
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
39647
39625
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -40213,6 +40191,13 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
40213
40191
|
visit(sourceFile);
|
|
40214
40192
|
return foundRange;
|
|
40215
40193
|
};
|
|
40194
|
+
const NEWLINE_BYTE = 10;
|
|
40195
|
+
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
40196
|
+
let lineNumber = 1;
|
|
40197
|
+
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
40198
|
+
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
|
|
40199
|
+
return lineNumber;
|
|
40200
|
+
};
|
|
40216
40201
|
/**
|
|
40217
40202
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
40218
40203
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -40393,11 +40378,11 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
40393
40378
|
}
|
|
40394
40379
|
return related;
|
|
40395
40380
|
};
|
|
40396
|
-
const
|
|
40397
|
-
|
|
40398
|
-
const
|
|
40399
|
-
|
|
40400
|
-
|
|
40381
|
+
const isOxlintOutput = (value) => {
|
|
40382
|
+
if (typeof value !== "object" || value === null) return false;
|
|
40383
|
+
const candidate = value;
|
|
40384
|
+
return Array.isArray(candidate.diagnostics);
|
|
40385
|
+
};
|
|
40401
40386
|
/**
|
|
40402
40387
|
* Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
|
|
40403
40388
|
* Tolerates the leading-notice-line shape oxlint sometimes prints
|
|
@@ -40416,59 +40401,23 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40416
40401
|
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40417
40402
|
}
|
|
40418
40403
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40419
|
-
const engineFailureDiagnostic = parsed.diagnostics.find(isEngineFailureDiagnostic);
|
|
40420
|
-
if (engineFailureDiagnostic !== void 0) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: JSON.stringify(engineFailureDiagnostic).slice(0, 600) }) });
|
|
40421
40404
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
40422
|
-
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
40423
|
-
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
40424
|
-
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
40425
|
-
const readSourceBuffer = (filename) => {
|
|
40426
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
40427
|
-
const cached = sourceBufferCache.get(absolutePath);
|
|
40428
|
-
if (cached !== void 0) return cached;
|
|
40429
|
-
let sourceBuffer;
|
|
40430
|
-
try {
|
|
40431
|
-
sourceBuffer = NFS.readFileSync(absolutePath);
|
|
40432
|
-
} catch {
|
|
40433
|
-
sourceBuffer = null;
|
|
40434
|
-
}
|
|
40435
|
-
sourceBufferCache.set(absolutePath, sourceBuffer);
|
|
40436
|
-
return sourceBuffer;
|
|
40437
|
-
};
|
|
40438
|
-
const readSourceLines = (filename) => {
|
|
40439
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
40440
|
-
const cached = sourceLinesCache.get(absolutePath);
|
|
40441
|
-
if (cached !== void 0) return cached;
|
|
40442
|
-
const sourceBuffer = readSourceBuffer(filename);
|
|
40443
|
-
const sourceLines = sourceBuffer ? sourceBuffer.toString("utf8").split("\n") : null;
|
|
40444
|
-
sourceLinesCache.set(absolutePath, sourceLines);
|
|
40445
|
-
return sourceLines;
|
|
40446
|
-
};
|
|
40447
40405
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
40448
|
-
const absolutePath =
|
|
40406
|
+
const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
40449
40407
|
const cached = minifiedFileCache.get(absolutePath);
|
|
40450
40408
|
if (cached !== void 0) return cached;
|
|
40451
40409
|
const minified = isMinifiedSource(absolutePath);
|
|
40452
40410
|
minifiedFileCache.set(absolutePath, minified);
|
|
40453
40411
|
return minified;
|
|
40454
40412
|
};
|
|
40455
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) =>
|
|
40413
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
40456
40414
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
40457
40415
|
const primaryLabel = diagnostic.labels[0];
|
|
40458
40416
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
40459
40417
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
40460
40418
|
const primarySpan = primaryLabel?.span;
|
|
40461
|
-
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
40462
40419
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
40463
40420
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
40464
|
-
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
40465
|
-
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
40466
|
-
const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
|
|
40467
|
-
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
40468
|
-
const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
|
|
40469
|
-
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
40470
|
-
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
40471
|
-
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
40472
40421
|
return {
|
|
40473
40422
|
filePath: normalizedFilePath,
|
|
40474
40423
|
plugin,
|
|
@@ -40482,11 +40431,10 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40482
40431
|
column: primarySpan?.column ?? 0,
|
|
40483
40432
|
...primarySpan ? {
|
|
40484
40433
|
offset: primarySpan.offset,
|
|
40485
|
-
length: primarySpan.length
|
|
40486
|
-
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
40434
|
+
length: primarySpan.length
|
|
40487
40435
|
} : {},
|
|
40488
40436
|
category,
|
|
40489
|
-
...
|
|
40437
|
+
...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
|
|
40490
40438
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
40491
40439
|
};
|
|
40492
40440
|
}), rootDirectory);
|
|
@@ -44542,7 +44490,6 @@ const METRIC = {
|
|
|
44542
44490
|
cliInvoked: "cli.invoked",
|
|
44543
44491
|
cliError: "cli.error",
|
|
44544
44492
|
cliEnvironmentError: "cli.env_error",
|
|
44545
|
-
stagedSnapshotDivergence: "staged.snapshot_divergence",
|
|
44546
44493
|
projectDetected: "project.detected",
|
|
44547
44494
|
projectPathSelected: "project.path_selected",
|
|
44548
44495
|
projectConfigSelected: "project.config_selected",
|
|
@@ -44897,5 +44844,5 @@ const startLanguageServer = () => {
|
|
|
44897
44844
|
};
|
|
44898
44845
|
//#endregion
|
|
44899
44846
|
export { startLanguageServer };
|
|
44900
|
-
!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]="
|
|
44901
|
-
//# debugId=
|
|
44847
|
+
!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]="a3135dfe-cc85-5d34-adea-93f5c29d9bcb")}catch(e){}}();
|
|
44848
|
+
//# debugId=a3135dfe-cc85-5d34-adea-93f5c29d9bcb
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.7.6-dev.
|
|
3
|
+
"version": "0.7.6-dev.8c9a6c4",
|
|
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
|
+
"deslop-js": "0.7.6",
|
|
69
|
+
"oxlint-plugin-react-doctor": "0.7.6-dev.8c9a6c4"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__code-frame": "^7.27.0",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"@xterm/headless": "^6.0.0",
|
|
75
75
|
"commander": "^14.0.3",
|
|
76
76
|
"ora": "^9.4.0",
|
|
77
|
-
"@react-doctor/core": "0.7.6",
|
|
78
77
|
"@react-doctor/api": "0.7.6",
|
|
78
|
+
"@react-doctor/core": "0.7.6",
|
|
79
79
|
"@react-doctor/language-server": "0.7.6"
|
|
80
80
|
},
|
|
81
81
|
"engines": {
|