react-doctor 0.7.6-dev.b36e439 → 0.7.6-dev.c5a06bd
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 +36 -162
- package/dist/index.d.ts +1 -1
- package/dist/index.js +15 -34
- package/dist/lsp.js +13 -32
- package/package.json +2 -2
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]="9a5c1a3c-7706-5a23-bca4-ddddd2f085af")}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";
|
|
@@ -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)))));
|
|
@@ -43659,11 +43643,11 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
43659
43643
|
}
|
|
43660
43644
|
return related;
|
|
43661
43645
|
};
|
|
43662
|
-
const
|
|
43663
|
-
|
|
43664
|
-
const
|
|
43665
|
-
|
|
43666
|
-
|
|
43646
|
+
const isOxlintOutput = (value) => {
|
|
43647
|
+
if (typeof value !== "object" || value === null) return false;
|
|
43648
|
+
const candidate = value;
|
|
43649
|
+
return Array.isArray(candidate.diagnostics);
|
|
43650
|
+
};
|
|
43667
43651
|
/**
|
|
43668
43652
|
* Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
|
|
43669
43653
|
* Tolerates the leading-notice-line shape oxlint sometimes prints
|
|
@@ -43682,8 +43666,6 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43682
43666
|
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
43683
43667
|
}
|
|
43684
43668
|
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
43669
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
43688
43670
|
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
43689
43671
|
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
@@ -43718,7 +43700,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43718
43700
|
minifiedFileCache.set(absolutePath, minified);
|
|
43719
43701
|
return minified;
|
|
43720
43702
|
};
|
|
43721
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) =>
|
|
43703
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
43722
43704
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
43723
43705
|
const primaryLabel = diagnostic.labels[0];
|
|
43724
43706
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
@@ -46284,11 +46266,10 @@ const computeDiagnosticDelta = (input) => {
|
|
|
46284
46266
|
* render diff-base mistakes (`GitBaseBranchInvalid` /
|
|
46285
46267
|
* `GitBaseBranchMissing`) as clean user errors instead of crashes.
|
|
46286
46268
|
*/
|
|
46287
|
-
const getDiffInfo = (directory, explicitBaseBranch
|
|
46269
|
+
const getDiffInfo = (directory, explicitBaseBranch) => runPromise(gen(function* () {
|
|
46288
46270
|
const selection = yield* (yield* Git).diffSelection({
|
|
46289
46271
|
directory,
|
|
46290
|
-
explicitBaseBranch
|
|
46291
|
-
includeUntracked
|
|
46272
|
+
explicitBaseBranch
|
|
46292
46273
|
});
|
|
46293
46274
|
if (selection === null) return null;
|
|
46294
46275
|
return {
|
|
@@ -46624,43 +46605,6 @@ const isNonInteractiveEnvironment = () => NON_INTERACTIVE_ENVIRONMENT_VARIABLES.
|
|
|
46624
46605
|
//#region src/cli/utils/constants.ts
|
|
46625
46606
|
const REACT_DOCTOR_CONFIG_PROJECT_NAME = "react-doctor";
|
|
46626
46607
|
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
46608
|
const BASELINE_FILES_TEMP_DIR_PREFIX = "react-doctor-baseline-";
|
|
46665
46609
|
const SCAN_RESULT_CACHE_FILENAME = "scan-cache.json";
|
|
46666
46610
|
const RUN_GIT_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
|
|
@@ -46675,7 +46619,6 @@ const METRIC = {
|
|
|
46675
46619
|
cliInvoked: "cli.invoked",
|
|
46676
46620
|
cliError: "cli.error",
|
|
46677
46621
|
cliEnvironmentError: "cli.env_error",
|
|
46678
|
-
stagedSnapshotDivergence: "staged.snapshot_divergence",
|
|
46679
46622
|
projectDetected: "project.detected",
|
|
46680
46623
|
projectPathSelected: "project.path_selected",
|
|
46681
46624
|
projectConfigSelected: "project.config_selected",
|
|
@@ -46756,7 +46699,7 @@ const makeNoopConsole = () => ({
|
|
|
46756
46699
|
});
|
|
46757
46700
|
//#endregion
|
|
46758
46701
|
//#region src/cli/utils/version.ts
|
|
46759
|
-
const VERSION = "0.7.6-dev.
|
|
46702
|
+
const VERSION = "0.7.6-dev.c5a06bd";
|
|
46760
46703
|
//#endregion
|
|
46761
46704
|
//#region src/cli/utils/json-mode.ts
|
|
46762
46705
|
let context = null;
|
|
@@ -47125,13 +47068,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
47125
47068
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
47126
47069
|
* standard `SENTRY_RELEASE` override.
|
|
47127
47070
|
*/
|
|
47128
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.6-dev.
|
|
47071
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.6-dev.c5a06bd`;
|
|
47129
47072
|
/**
|
|
47130
47073
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
47131
47074
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
47132
47075
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
47133
47076
|
*/
|
|
47134
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.
|
|
47077
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.c5a06bd") ? "development" : "production");
|
|
47135
47078
|
/**
|
|
47136
47079
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
47137
47080
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -47323,7 +47266,7 @@ const NON_BLOCKING_REACT_DOCTOR_COMMAND = [
|
|
|
47323
47266
|
"fi"
|
|
47324
47267
|
].join(" ");
|
|
47325
47268
|
const PACKAGE_JSON_FILE_NAME = "package.json";
|
|
47326
|
-
const
|
|
47269
|
+
const runGit = (projectRoot, args) => {
|
|
47327
47270
|
try {
|
|
47328
47271
|
return execFileSync("git", [...args], {
|
|
47329
47272
|
cwd: projectRoot,
|
|
@@ -47334,12 +47277,11 @@ const runGitRaw = (projectRoot, args) => {
|
|
|
47334
47277
|
"ignore"
|
|
47335
47278
|
],
|
|
47336
47279
|
maxBuffer: RUN_GIT_MAX_BUFFER_BYTES
|
|
47337
|
-
});
|
|
47280
|
+
}).trim();
|
|
47338
47281
|
} catch {
|
|
47339
47282
|
return null;
|
|
47340
47283
|
}
|
|
47341
47284
|
};
|
|
47342
|
-
const runGit = (projectRoot, args) => runGitRaw(projectRoot, args)?.trim() ?? null;
|
|
47343
47285
|
const resolveGitPath = (baseDirectory, value) => Path.isAbsolute(value) ? value : Path.resolve(baseDirectory, value);
|
|
47344
47286
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47345
47287
|
const getPackageJsonPath = (projectRoot) => Path.join(projectRoot, PACKAGE_JSON_FILE_NAME);
|
|
@@ -59210,17 +59152,6 @@ const buildRuleBlastRadii = (diagnostics) => buildSortedRuleGroups(diagnostics).
|
|
|
59210
59152
|
})).toSorted((left, right) => right.fileCount - left.fileCount);
|
|
59211
59153
|
const findMigrationScaleBuckets = (diagnostics) => buildRuleBlastRadii(diagnostics).filter((bucket) => bucket.fileCount >= 40);
|
|
59212
59154
|
//#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
59155
|
//#region src/cli/utils/scan-result-cache.ts
|
|
59225
59156
|
const CACHE_DISABLED_VALUES = new Set(["1", "true"]);
|
|
59226
59157
|
const TOOLCHAIN_PACKAGE_SPECIFIERS = [
|
|
@@ -59626,12 +59557,15 @@ const buildOutcomeAttributes = (input) => {
|
|
|
59626
59557
|
const summary = summarizeDiagnostics(result.diagnostics);
|
|
59627
59558
|
const blockingLevel = resolveTelemetryBlocking(input.userConfig);
|
|
59628
59559
|
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
59560
|
const wouldBlock = !input.scoreOnly && !input.gateExempt && shouldBlockCi(gateDiagnostics, blockingLevel);
|
|
59561
|
+
const complete = isScanComplete({
|
|
59562
|
+
analyzedFileCount: result.analyzedFiles?.length,
|
|
59563
|
+
scannedFileCount: result.scannedFileCount,
|
|
59564
|
+
skippedCheckCount: result.skippedChecks.length,
|
|
59565
|
+
skippedCheckReasonCount: Object.keys(result.skippedCheckReasons ?? {}).length
|
|
59566
|
+
});
|
|
59633
59567
|
const isClean = result.diagnostics.length === 0 && complete;
|
|
59634
|
-
const outcome =
|
|
59568
|
+
const outcome = wouldBlock ? "blocked" : isClean ? "clean" : "ok";
|
|
59635
59569
|
const firings = summarizeRuleFirings(result.diagnostics);
|
|
59636
59570
|
const countByRule = /* @__PURE__ */ new Map();
|
|
59637
59571
|
const countByCategory = /* @__PURE__ */ new Map();
|
|
@@ -59676,7 +59610,7 @@ const buildOutcomeAttributes = (input) => {
|
|
|
59676
59610
|
const attributes = {
|
|
59677
59611
|
...withNamespace("outcome", {
|
|
59678
59612
|
status: outcome,
|
|
59679
|
-
exitCode:
|
|
59613
|
+
exitCode: wouldBlock ? 1 : 0,
|
|
59680
59614
|
wouldBlock,
|
|
59681
59615
|
blocking: blockingLevel,
|
|
59682
59616
|
clean: isClean,
|
|
@@ -63858,15 +63792,10 @@ const warnIfAiTrainingEnvironment = () => {
|
|
|
63858
63792
|
//#region src/cli/utils/validate-mode-flags.ts
|
|
63859
63793
|
const usedDiffAlias = (flags) => flags.diff !== void 0 && flags.diff !== false && flags.diff !== "false" && flags.diff !== "";
|
|
63860
63794
|
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
63795
|
const validateModeFlags = (flags) => {
|
|
63866
63796
|
if (usedScope(flags) && usedDiffAlias(flags)) throw new CliInputError("Cannot combine --scope and --diff; --diff is the deprecated alias.");
|
|
63867
63797
|
if (flags.staged && usedDiffAlias(flags)) throw new CliInputError("Cannot combine --staged and --diff; pick one mode.");
|
|
63868
63798
|
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
63799
|
if (flags.score && flags.json) throw new CliInputError("Cannot combine --score and --json; pick one output mode.");
|
|
63871
63800
|
if (flags.score && flags.telemetry === false) throw new CliInputError("Cannot combine --score with --no-telemetry; --score prints the score that --no-telemetry disables.");
|
|
63872
63801
|
if (flags.debug && (flags.score === false || flags.telemetry === false)) {
|
|
@@ -63875,39 +63804,6 @@ const validateModeFlags = (flags) => {
|
|
|
63875
63804
|
}
|
|
63876
63805
|
};
|
|
63877
63806
|
//#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
63807
|
//#region src/cli/commands/inspect.ts
|
|
63912
63808
|
const filterCompletedScansByCategories = (completedScans, categoryFilters) => {
|
|
63913
63809
|
if (categoryFilters.size === 0) return [...completedScans];
|
|
@@ -63922,14 +63818,9 @@ const filterCompletedScansByCategories = (completedScans, categoryFilters) => {
|
|
|
63922
63818
|
/**
|
|
63923
63819
|
* Post-scan finalization shared by the staged-arm and project-loop
|
|
63924
63820
|
* 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.
|
|
63821
|
+
* and set `process.exitCode = 1` when a diagnostic at or above the
|
|
63822
|
+
* `--blocking` threshold (default `"error"`) reaches the `ciFailure`
|
|
63823
|
+
* surface. `--blocking none` keeps the scan advisory (always exits 0).
|
|
63933
63824
|
*/
|
|
63934
63825
|
const finalizeScans = (input) => {
|
|
63935
63826
|
const baselineDeltas = input.completedScans.flatMap((scan) => scan.result.baselineDelta ? [scan.result.baselineDelta] : []);
|
|
@@ -63959,13 +63850,8 @@ const finalizeScans = (input) => {
|
|
|
63959
63850
|
baselineDegraded
|
|
63960
63851
|
}));
|
|
63961
63852
|
}
|
|
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
63853
|
if (input.isScoreOnly || baselineDegraded) return;
|
|
63968
|
-
if (shouldBlockCi(filterScansForSurface(input.completedScans, "ciFailure"),
|
|
63854
|
+
if (shouldBlockCi(filterScansForSurface(input.completedScans, "ciFailure"), resolveBlockingLevel(input.flags, input.userConfig))) process.exitCode = 1;
|
|
63969
63855
|
};
|
|
63970
63856
|
const buildChangedFilesDiffInfo = (changedFiles) => ({
|
|
63971
63857
|
currentBranch: process.env.GITHUB_HEAD_REF?.trim() || null,
|
|
@@ -64003,7 +63889,6 @@ const inspectAction = async (directory, flags) => {
|
|
|
64003
63889
|
recordCount(METRIC.cliInvoked, 1, { command: "inspect" });
|
|
64004
63890
|
try {
|
|
64005
63891
|
validateModeFlags(flags);
|
|
64006
|
-
if (flags.staged) setJsonReportMode("staged");
|
|
64007
63892
|
await maybeMigrateLegacyConfig(requestedDirectory, {
|
|
64008
63893
|
isQuiet,
|
|
64009
63894
|
isStaged: Boolean(flags.staged)
|
|
@@ -64019,14 +63904,6 @@ const inspectAction = async (directory, flags) => {
|
|
|
64019
63904
|
cliLogger.dim(`Redirected to ${highlighter.info(toRelativePath(resolvedDirectory, requestedDirectory))} via react-doctor config "rootDir".`);
|
|
64020
63905
|
cliLogger.break();
|
|
64021
63906
|
}
|
|
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
63907
|
const explainArgument = flags.explain;
|
|
64031
63908
|
if (explainArgument !== void 0) {
|
|
64032
63909
|
await runExplain(explainArgument, {
|
|
@@ -64047,6 +63924,7 @@ const inspectAction = async (directory, flags) => {
|
|
|
64047
63924
|
json: flags.json
|
|
64048
63925
|
});
|
|
64049
63926
|
if (flags.staged) {
|
|
63927
|
+
setJsonReportMode("staged");
|
|
64050
63928
|
const stagedFiles = await getStagedSourceFiles(resolvedDirectory);
|
|
64051
63929
|
if (stagedFiles.length === 0) {
|
|
64052
63930
|
if (isJsonMode) writeJsonReport(buildJsonReport({
|
|
@@ -64127,15 +64005,13 @@ const inspectAction = async (directory, flags) => {
|
|
|
64127
64005
|
const projectDirectories = await selectProjects(resolvedDirectory, flags.project, skipPrompts, userConfig?.projects);
|
|
64128
64006
|
const changedFilesDiffInfo = flags.changedFilesFrom ? buildChangedFilesDiffInfo(readChangedFilesFrom(Path.resolve(flags.changedFilesFrom))) : null;
|
|
64129
64007
|
const requestedScope = resolveScope(flags, userConfig);
|
|
64130
|
-
const includeUntracked = flags.includeUntracked ?? false;
|
|
64131
64008
|
const scopeRequest = requestedScope.scope === void 0 && changedFilesDiffInfo !== null ? {
|
|
64132
64009
|
...requestedScope,
|
|
64133
64010
|
scope: "changed"
|
|
64134
64011
|
} : requestedScope;
|
|
64135
|
-
validateIncludeUntrackedScope(includeUntracked, scopeRequest.scope);
|
|
64136
64012
|
const wantsDiffMode = scopeRequest.scope !== void 0 && scopeRequest.scope !== "full";
|
|
64137
64013
|
const shouldDetectDiff = changedFilesDiffInfo === null && (wantsDiffMode || scopeRequest.scope === void 0 && !skipPrompts && !isQuiet);
|
|
64138
|
-
const diffInfo = changedFilesDiffInfo ?? (shouldDetectDiff ? await getDiffInfo(resolvedDirectory, scopeRequest.base
|
|
64014
|
+
const diffInfo = changedFilesDiffInfo ?? (shouldDetectDiff ? await getDiffInfo(resolvedDirectory, scopeRequest.base) : null);
|
|
64139
64015
|
const scope = await finalizeScope({
|
|
64140
64016
|
requested: scopeRequest,
|
|
64141
64017
|
diffInfo,
|
|
@@ -64149,8 +64025,7 @@ const inspectAction = async (directory, flags) => {
|
|
|
64149
64025
|
const changedLineRanges = scope === "lines" && diffInfo !== null && (diffInfo.isCurrentChanges || linesBaseRef !== null) && diffInfo !== null ? await getChangedLineRanges({
|
|
64150
64026
|
directory: resolvedDirectory,
|
|
64151
64027
|
baseRef: linesBaseRef ?? void 0,
|
|
64152
|
-
files: [...diffInfo.changedFiles]
|
|
64153
|
-
includeUntracked
|
|
64028
|
+
files: [...diffInfo.changedFiles]
|
|
64154
64029
|
}) : null;
|
|
64155
64030
|
if (scope === "lines" && changedLineRanges === null && !isQuiet) {
|
|
64156
64031
|
cliLogger.warn("Could not determine changed lines (no base ref or git diff failed); reporting all issues in changed files.");
|
|
@@ -65083,7 +64958,6 @@ const ROOT_FLAG_SPEC = {
|
|
|
65083
64958
|
"--dead-code",
|
|
65084
64959
|
"--debug",
|
|
65085
64960
|
"--help",
|
|
65086
|
-
"--include-untracked",
|
|
65087
64961
|
"--json",
|
|
65088
64962
|
"--json-compact",
|
|
65089
64963
|
"--lint",
|
|
@@ -65347,7 +65221,7 @@ ${highlighter.dim("Learn more:")}
|
|
|
65347
65221
|
${highlighter.info(CI_URL)}
|
|
65348
65222
|
`;
|
|
65349
65223
|
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 (issues whose source spans touch changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").
|
|
65224
|
+
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 (issues whose source spans touch 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
65225
|
program.action(inspectAction);
|
|
65352
65226
|
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
65227
|
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 +65271,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
65397
65271
|
export {};
|
|
65398
65272
|
|
|
65399
65273
|
//# sourceMappingURL=cli.js.map
|
|
65400
|
-
//# debugId=
|
|
65274
|
+
//# debugId=9a5c1a3c-7706-5a23-bca4-ddddd2f085af
|
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]="11364a34-6c8b-5bd3-b9e8-aaa7c0ea264c")}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";
|
|
@@ -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)))));
|
|
@@ -40415,11 +40399,11 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
40415
40399
|
}
|
|
40416
40400
|
return related;
|
|
40417
40401
|
};
|
|
40418
|
-
const
|
|
40419
|
-
|
|
40420
|
-
const
|
|
40421
|
-
|
|
40422
|
-
|
|
40402
|
+
const isOxlintOutput = (value) => {
|
|
40403
|
+
if (typeof value !== "object" || value === null) return false;
|
|
40404
|
+
const candidate = value;
|
|
40405
|
+
return Array.isArray(candidate.diagnostics);
|
|
40406
|
+
};
|
|
40423
40407
|
/**
|
|
40424
40408
|
* Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
|
|
40425
40409
|
* Tolerates the leading-notice-line shape oxlint sometimes prints
|
|
@@ -40438,8 +40422,6 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40438
40422
|
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40439
40423
|
}
|
|
40440
40424
|
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
40425
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
40444
40426
|
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
40445
40427
|
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
@@ -40474,7 +40456,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40474
40456
|
minifiedFileCache.set(absolutePath, minified);
|
|
40475
40457
|
return minified;
|
|
40476
40458
|
};
|
|
40477
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) =>
|
|
40459
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
40478
40460
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
40479
40461
|
const primaryLabel = diagnostic.labels[0];
|
|
40480
40462
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
@@ -42966,11 +42948,10 @@ const buildSkippedChecks = (input) => {
|
|
|
42966
42948
|
* render diff-base mistakes (`GitBaseBranchInvalid` /
|
|
42967
42949
|
* `GitBaseBranchMissing`) as clean user errors instead of crashes.
|
|
42968
42950
|
*/
|
|
42969
|
-
const getDiffInfo = (directory, explicitBaseBranch
|
|
42951
|
+
const getDiffInfo = (directory, explicitBaseBranch) => runPromise(gen(function* () {
|
|
42970
42952
|
const selection = yield* (yield* Git).diffSelection({
|
|
42971
42953
|
directory,
|
|
42972
|
-
explicitBaseBranch
|
|
42973
|
-
includeUntracked
|
|
42954
|
+
explicitBaseBranch
|
|
42974
42955
|
});
|
|
42975
42956
|
if (selection === null) return null;
|
|
42976
42957
|
return {
|
|
@@ -43260,4 +43241,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
43260
43241
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
43261
43242
|
|
|
43262
43243
|
//# sourceMappingURL=index.js.map
|
|
43263
|
-
//# debugId=
|
|
43244
|
+
//# debugId=11364a34-6c8b-5bd3-b9e8-aaa7c0ea264c
|
package/dist/lsp.js
CHANGED
|
@@ -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)))));
|
|
@@ -40393,11 +40377,11 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
40393
40377
|
}
|
|
40394
40378
|
return related;
|
|
40395
40379
|
};
|
|
40396
|
-
const
|
|
40397
|
-
|
|
40398
|
-
const
|
|
40399
|
-
|
|
40400
|
-
|
|
40380
|
+
const isOxlintOutput = (value) => {
|
|
40381
|
+
if (typeof value !== "object" || value === null) return false;
|
|
40382
|
+
const candidate = value;
|
|
40383
|
+
return Array.isArray(candidate.diagnostics);
|
|
40384
|
+
};
|
|
40401
40385
|
/**
|
|
40402
40386
|
* Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
|
|
40403
40387
|
* Tolerates the leading-notice-line shape oxlint sometimes prints
|
|
@@ -40416,8 +40400,6 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40416
40400
|
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40417
40401
|
}
|
|
40418
40402
|
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
40403
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
40422
40404
|
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
40423
40405
|
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
@@ -40452,7 +40434,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40452
40434
|
minifiedFileCache.set(absolutePath, minified);
|
|
40453
40435
|
return minified;
|
|
40454
40436
|
};
|
|
40455
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) =>
|
|
40437
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
40456
40438
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
40457
40439
|
const primaryLabel = diagnostic.labels[0];
|
|
40458
40440
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
@@ -44542,7 +44524,6 @@ const METRIC = {
|
|
|
44542
44524
|
cliInvoked: "cli.invoked",
|
|
44543
44525
|
cliError: "cli.error",
|
|
44544
44526
|
cliEnvironmentError: "cli.env_error",
|
|
44545
|
-
stagedSnapshotDivergence: "staged.snapshot_divergence",
|
|
44546
44527
|
projectDetected: "project.detected",
|
|
44547
44528
|
projectPathSelected: "project.path_selected",
|
|
44548
44529
|
projectConfigSelected: "project.config_selected",
|
|
@@ -44897,5 +44878,5 @@ const startLanguageServer = () => {
|
|
|
44897
44878
|
};
|
|
44898
44879
|
//#endregion
|
|
44899
44880
|
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=
|
|
44881
|
+
!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]="f9337714-b38f-5f28-ac00-c9d7d79ebaea")}catch(e){}}();
|
|
44882
|
+
//# debugId=f9337714-b38f-5f28-ac00-c9d7d79ebaea
|
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.c5a06bd",
|
|
4
4
|
"description": "Your agent writes bad React. This catches it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"vscode-uri": "^3.1.0",
|
|
67
67
|
"yaml": "^2.9.0",
|
|
68
68
|
"deslop-js": "0.7.6",
|
|
69
|
-
"oxlint-plugin-react-doctor": "0.7.6-dev.
|
|
69
|
+
"oxlint-plugin-react-doctor": "0.7.6-dev.c5a06bd"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__code-frame": "^7.27.0",
|