react-doctor 0.5.6-dev.81bbfcc → 0.5.6-dev.937a7ca
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 +257 -84
- package/dist/index.js +45 -17
- package/dist/lsp.js +45 -17
- 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]="ad091b20-c3e2-5c96-93ac-9a910745a035")}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";
|
|
@@ -14,7 +14,7 @@ import * as OS from "node:os";
|
|
|
14
14
|
import os, { tmpdir } from "node:os";
|
|
15
15
|
import { parseJSON5 } from "confbox";
|
|
16
16
|
import * as NodeUrl from "node:url";
|
|
17
|
-
import { fileURLToPath } from "node:url";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
18
|
import { createJiti } from "jiti";
|
|
19
19
|
import * as Crypto from "node:crypto";
|
|
20
20
|
import crypto, { createHash, randomUUID } from "node:crypto";
|
|
@@ -39692,15 +39692,10 @@ const buildCapabilities = (project) => {
|
|
|
39692
39692
|
}
|
|
39693
39693
|
if (project.tailwindVersion !== null) {
|
|
39694
39694
|
capabilities.add("tailwind");
|
|
39695
|
-
|
|
39696
|
-
if (isTailwindAtLeast(tailwind, {
|
|
39695
|
+
if (isTailwindAtLeast(parseTailwindMajorMinor(project.tailwindVersion), {
|
|
39697
39696
|
major: 3,
|
|
39698
39697
|
minor: 4
|
|
39699
39698
|
})) capabilities.add("tailwind:3.4");
|
|
39700
|
-
if (tailwind !== null && isTailwindAtLeast(tailwind, {
|
|
39701
|
-
major: 4,
|
|
39702
|
-
minor: 0
|
|
39703
|
-
})) capabilities.add("tailwind:4");
|
|
39704
39699
|
}
|
|
39705
39700
|
if (project.zodVersion !== null) {
|
|
39706
39701
|
capabilities.add("zod");
|
|
@@ -41325,8 +41320,8 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
41325
41320
|
}
|
|
41326
41321
|
return enabled;
|
|
41327
41322
|
};
|
|
41328
|
-
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [] }) => {
|
|
41329
|
-
const reactHooksJsPlugin = resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
|
|
41323
|
+
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false }) => {
|
|
41324
|
+
const reactHooksJsPlugin = disableReactHooksJsPlugin ? null : resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
|
|
41330
41325
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
41331
41326
|
const jsPlugins = [];
|
|
41332
41327
|
if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
|
|
@@ -42023,9 +42018,9 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
42023
42018
|
try {
|
|
42024
42019
|
parsed = JSON.parse(sanitizedStdout);
|
|
42025
42020
|
} catch {
|
|
42026
|
-
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0,
|
|
42021
|
+
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
42027
42022
|
}
|
|
42028
|
-
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0,
|
|
42023
|
+
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
42029
42024
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
42030
42025
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
42031
42026
|
const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
@@ -42316,6 +42311,28 @@ const writeOxlintConfig = (configPath, configToWrite) => {
|
|
|
42316
42311
|
NFS.closeSync(fileHandle);
|
|
42317
42312
|
}
|
|
42318
42313
|
};
|
|
42314
|
+
const REACT_HOOKS_JS_DROP_PREFIX = "React Compiler rules (react-hooks-js/*) skipped — eslint-plugin-react-hooks failed to load in this environment";
|
|
42315
|
+
/**
|
|
42316
|
+
* Detects an oxlint config-load crash caused by the optional
|
|
42317
|
+
* `react-hooks-js` (eslint-plugin-react-hooks) React Compiler plugin and
|
|
42318
|
+
* builds the partial-failure note for it; returns `null` when the failure
|
|
42319
|
+
* was anything else.
|
|
42320
|
+
*
|
|
42321
|
+
* oxlint prints a framed error to stdout (not stderr) and exits non-zero
|
|
42322
|
+
* when a `jsPlugins` entry can't be imported; that non-JSON stdout
|
|
42323
|
+
* surfaces as `OxlintOutputUnparseable`. Because oxlint fails the WHOLE
|
|
42324
|
+
* config load on it, leaving the plugin in would drop every curated
|
|
42325
|
+
* react-doctor diagnostic too — so the caller retries with the plugin
|
|
42326
|
+
* stripped (issue #833). Both markers sit at the start of oxlint's
|
|
42327
|
+
* message, so they survive the `preview` slice even for deep pnpm paths.
|
|
42328
|
+
*/
|
|
42329
|
+
const reactHooksJsPluginDropNote = (error) => {
|
|
42330
|
+
if (!(error instanceof ReactDoctorError) || error.reason._tag !== "OxlintOutputUnparseable") return null;
|
|
42331
|
+
const { preview } = error.reason;
|
|
42332
|
+
if (!preview.includes("Failed to load JS plugin") || !preview.includes("eslint-plugin-react-hooks")) return null;
|
|
42333
|
+
const underlyingReason = preview.match(/Error:[^\n]*/)?.[0]?.trim();
|
|
42334
|
+
return `${REACT_HOOKS_JS_DROP_PREFIX}${underlyingReason ? `: ${underlyingReason}` : ""}. Other rules ran normally.`;
|
|
42335
|
+
};
|
|
42319
42336
|
/**
|
|
42320
42337
|
* The oxlint runner. Composed of three pieces in `runners/oxlint/`:
|
|
42321
42338
|
*
|
|
@@ -42343,15 +42360,16 @@ const runOxlint = async (options) => {
|
|
|
42343
42360
|
const pluginPath = resolvePluginPath();
|
|
42344
42361
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
42345
42362
|
const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
42346
|
-
const buildConfig = (
|
|
42363
|
+
const buildConfig = (overrides) => createOxlintConfig({
|
|
42347
42364
|
pluginPath,
|
|
42348
42365
|
project,
|
|
42349
42366
|
customRulesOnly,
|
|
42350
|
-
extendsPaths:
|
|
42367
|
+
extendsPaths: overrides.extendsPaths,
|
|
42351
42368
|
ignoredTags,
|
|
42352
42369
|
serverAuthFunctionNames,
|
|
42353
42370
|
severityControls,
|
|
42354
|
-
userPlugins
|
|
42371
|
+
userPlugins,
|
|
42372
|
+
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin
|
|
42355
42373
|
});
|
|
42356
42374
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
42357
42375
|
const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
@@ -42387,12 +42405,22 @@ const runOxlint = async (options) => {
|
|
|
42387
42405
|
outputMaxBytes,
|
|
42388
42406
|
concurrency: options.concurrency
|
|
42389
42407
|
});
|
|
42390
|
-
writeOxlintConfig(configPath, buildConfig(extendsPaths));
|
|
42408
|
+
writeOxlintConfig(configPath, buildConfig({ extendsPaths }));
|
|
42391
42409
|
try {
|
|
42392
42410
|
return await runBatches();
|
|
42393
42411
|
} catch (error) {
|
|
42412
|
+
const reactHooksJsDropNote = reactHooksJsPluginDropNote(error);
|
|
42413
|
+
if (reactHooksJsDropNote !== null) {
|
|
42414
|
+
writeOxlintConfig(configPath, buildConfig({
|
|
42415
|
+
extendsPaths,
|
|
42416
|
+
disableReactHooksJsPlugin: true
|
|
42417
|
+
}));
|
|
42418
|
+
const diagnostics = await runBatches();
|
|
42419
|
+
onPartialFailure?.(reactHooksJsDropNote);
|
|
42420
|
+
return diagnostics;
|
|
42421
|
+
}
|
|
42394
42422
|
if (extendsPaths.length === 0) throw error;
|
|
42395
|
-
writeOxlintConfig(configPath, buildConfig([]));
|
|
42423
|
+
writeOxlintConfig(configPath, buildConfig({ extendsPaths: [] }));
|
|
42396
42424
|
return await runBatches();
|
|
42397
42425
|
}
|
|
42398
42426
|
} finally {
|
|
@@ -43844,7 +43872,7 @@ const FALSY_CI_FLAG_VALUES = new Set([
|
|
|
43844
43872
|
"false"
|
|
43845
43873
|
]);
|
|
43846
43874
|
const isCiFlagSet = (value) => value !== void 0 && !FALSY_CI_FLAG_VALUES.has(value.toLowerCase());
|
|
43847
|
-
const isCiEnvironment = () => CI_ENVIRONMENT_VARIABLES.some((environmentVariable) => Boolean(
|
|
43875
|
+
const isCiEnvironment = (env = process.env) => CI_ENVIRONMENT_VARIABLES.some((environmentVariable) => Boolean(env[environmentVariable])) || isCiFlagSet(env.CI);
|
|
43848
43876
|
const detectCiProvider = () => {
|
|
43849
43877
|
for (const [environmentVariable, provider] of CI_PROVIDER_BY_ENVIRONMENT_VARIABLE) if (process.env[environmentVariable]) return provider;
|
|
43850
43878
|
return isCiFlagSet(process.env.CI) ? "unknown" : null;
|
|
@@ -43869,6 +43897,42 @@ const detectCodingAgent = () => {
|
|
|
43869
43897
|
const isCodingAgentEnvironment = () => detectCodingAgent() !== null;
|
|
43870
43898
|
const isCiOrCodingAgentEnvironment = () => isCiEnvironment() || isCodingAgentEnvironment();
|
|
43871
43899
|
//#endregion
|
|
43900
|
+
//#region src/cli/utils/detect-terminal-kind.ts
|
|
43901
|
+
const TERMINAL_BY_TERM_PROGRAM = [
|
|
43902
|
+
["vscode", "vscode"],
|
|
43903
|
+
["iTerm.app", "iterm"],
|
|
43904
|
+
["Apple_Terminal", "apple-terminal"],
|
|
43905
|
+
["WezTerm", "wezterm"],
|
|
43906
|
+
["ghostty", "ghostty"],
|
|
43907
|
+
["Hyper", "hyper"],
|
|
43908
|
+
["Tabby", "tabby"],
|
|
43909
|
+
["rio", "rio"]
|
|
43910
|
+
];
|
|
43911
|
+
/**
|
|
43912
|
+
* Best-effort label for the terminal emulator / editor hosting the CLI,
|
|
43913
|
+
* derived from terminal-identity env vars. Recorded as the `terminalKind` run
|
|
43914
|
+
* tag so we can see where React Doctor is actually run (nvim, VS Code, iTerm,
|
|
43915
|
+
* …) — the split Sentry can't otherwise see. Low-cardinality and free of any
|
|
43916
|
+
* username/path/secret, so it's safe as a tag. Editor terminals (nvim/vim)
|
|
43917
|
+
* win over the outer emulator because that's the surface a user is reading in;
|
|
43918
|
+
* "ci" marks a run with no interactive terminal; "unknown" when nothing matches.
|
|
43919
|
+
*/
|
|
43920
|
+
const detectTerminalKind = (env = process.env) => {
|
|
43921
|
+
if (env.NVIM) return "neovim";
|
|
43922
|
+
if (env.VIM_TERMINAL) return "vim";
|
|
43923
|
+
const termProgram = env.TERM_PROGRAM;
|
|
43924
|
+
if (termProgram) {
|
|
43925
|
+
for (const [marker, label] of TERMINAL_BY_TERM_PROGRAM) if (termProgram === marker) return label;
|
|
43926
|
+
}
|
|
43927
|
+
if (env.KITTY_WINDOW_ID || env.TERM === "xterm-kitty") return "kitty";
|
|
43928
|
+
if (env.WT_SESSION) return "windows-terminal";
|
|
43929
|
+
if (env.ALACRITTY_WINDOW_ID || env.TERM === "alacritty") return "alacritty";
|
|
43930
|
+
if (env.VTE_VERSION) return "vte";
|
|
43931
|
+
if (env.TMUX) return "tmux";
|
|
43932
|
+
if (isCiEnvironment(env)) return "ci";
|
|
43933
|
+
return "unknown";
|
|
43934
|
+
};
|
|
43935
|
+
//#endregion
|
|
43872
43936
|
//#region src/cli/utils/is-git-hook-environment.ts
|
|
43873
43937
|
const isGitHookEnvironment = () => Boolean(process.env.GIT_DIR);
|
|
43874
43938
|
//#endregion
|
|
@@ -43891,6 +43955,7 @@ const NON_INTERACTIVE_ENVIRONMENT_VARIABLES = [
|
|
|
43891
43955
|
const isNonInteractiveEnvironment = () => NON_INTERACTIVE_ENVIRONMENT_VARIABLES.some((envVariable) => Boolean(process.env[envVariable])) || isCodingAgentEnvironment();
|
|
43892
43956
|
//#endregion
|
|
43893
43957
|
//#region src/cli/utils/constants.ts
|
|
43958
|
+
const REACT_DOCTOR_CONFIG_PROJECT_NAME = "react-doctor";
|
|
43894
43959
|
const STAGED_FILES_TEMP_DIR_PREFIX = "react-doctor-staged-";
|
|
43895
43960
|
const BASELINE_FILES_TEMP_DIR_PREFIX = "react-doctor-baseline-";
|
|
43896
43961
|
const GH_DEFAULT_BRANCH_PROBE_TIMEOUT_MS = 5e3;
|
|
@@ -43975,7 +44040,7 @@ const makeNoopConsole = () => ({
|
|
|
43975
44040
|
});
|
|
43976
44041
|
//#endregion
|
|
43977
44042
|
//#region src/cli/utils/version.ts
|
|
43978
|
-
const VERSION = "0.5.6-dev.
|
|
44043
|
+
const VERSION = "0.5.6-dev.937a7ca";
|
|
43979
44044
|
//#endregion
|
|
43980
44045
|
//#region src/cli/utils/json-mode.ts
|
|
43981
44046
|
let context = null;
|
|
@@ -44125,6 +44190,7 @@ const buildRunContext = () => {
|
|
|
44125
44190
|
viaAction: isOfficialGithubAction(),
|
|
44126
44191
|
codingAgent: detectCodingAgent(),
|
|
44127
44192
|
interactive: !isNonInteractiveEnvironment(),
|
|
44193
|
+
terminalKind: detectTerminalKind(),
|
|
44128
44194
|
jsonMode: isJsonModeActive(),
|
|
44129
44195
|
invokedVia: detectInvokedVia()
|
|
44130
44196
|
};
|
|
@@ -44195,6 +44261,7 @@ const buildSentryScope = (runContext = buildRunContext()) => {
|
|
|
44195
44261
|
viaAction: runContext.viaAction,
|
|
44196
44262
|
codingAgent: runContext.codingAgent,
|
|
44197
44263
|
interactive: runContext.interactive,
|
|
44264
|
+
terminalKind: runContext.terminalKind,
|
|
44198
44265
|
jsonMode: runContext.jsonMode,
|
|
44199
44266
|
invokedVia: runContext.invokedVia,
|
|
44200
44267
|
nodeMajor: runContext.nodeMajor
|
|
@@ -44333,13 +44400,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
44333
44400
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
44334
44401
|
* standard `SENTRY_RELEASE` override.
|
|
44335
44402
|
*/
|
|
44336
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.5.6-dev.
|
|
44403
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.5.6-dev.937a7ca`;
|
|
44337
44404
|
/**
|
|
44338
44405
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
44339
44406
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
44340
44407
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
44341
44408
|
*/
|
|
44342
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.5.6-dev.
|
|
44409
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.5.6-dev.937a7ca") ? "development" : "production");
|
|
44343
44410
|
/**
|
|
44344
44411
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
44345
44412
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -48196,6 +48263,15 @@ const boxText = (content, innerWidth) => {
|
|
|
48196
48263
|
].join("\n");
|
|
48197
48264
|
};
|
|
48198
48265
|
//#endregion
|
|
48266
|
+
//#region src/cli/utils/resolve-absolute-path.ts
|
|
48267
|
+
/**
|
|
48268
|
+
* Resolves a diagnostic's `filePath` (relative to its project root, or
|
|
48269
|
+
* already absolute) to an absolute path. Shared by the code-frame reader and
|
|
48270
|
+
* the terminal hyperlink builder so both turn a relative path into the same
|
|
48271
|
+
* on-disk location.
|
|
48272
|
+
*/
|
|
48273
|
+
const resolveAbsolutePath = (filePath, rootDirectory) => Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory || ".", filePath);
|
|
48274
|
+
//#endregion
|
|
48199
48275
|
//#region src/cli/utils/build-code-frame.ts
|
|
48200
48276
|
/**
|
|
48201
48277
|
* Renders a syntax-highlighted source excerpt around a diagnostic site
|
|
@@ -48206,7 +48282,7 @@ const boxText = (content, innerWidth) => {
|
|
|
48206
48282
|
*/
|
|
48207
48283
|
const buildCodeFrame = (input) => {
|
|
48208
48284
|
if (input.line <= 0) return null;
|
|
48209
|
-
const absolutePath =
|
|
48285
|
+
const absolutePath = resolveAbsolutePath(input.filePath, input.rootDirectory);
|
|
48210
48286
|
let source;
|
|
48211
48287
|
try {
|
|
48212
48288
|
source = NFS.readFileSync(absolutePath, "utf8");
|
|
@@ -48246,6 +48322,16 @@ const resolveMeasureWidth = (reservedColumns = 0) => resolveClampedWidth({
|
|
|
48246
48322
|
const DIVIDER_INDENT = " ";
|
|
48247
48323
|
const buildSectionDivider = () => highlighter.dim(`${DIVIDER_INDENT}${"─".repeat(resolveMeasureWidth(2))}`);
|
|
48248
48324
|
//#endregion
|
|
48325
|
+
//#region src/cli/utils/format-hyperlink.ts
|
|
48326
|
+
const OSC = "\x1B]";
|
|
48327
|
+
const ST = "\x1B\\";
|
|
48328
|
+
/**
|
|
48329
|
+
* Wraps `text` in an OSC 8 hyperlink pointing at `uri`. The visible characters
|
|
48330
|
+
* are exactly `text`; the link is carried in escape sequences a capable
|
|
48331
|
+
* terminal turns into a click target.
|
|
48332
|
+
*/
|
|
48333
|
+
const formatHyperlink = (text, uri) => `${OSC}8;;${uri}${ST}${text}${OSC}8;;${ST}`;
|
|
48334
|
+
//#endregion
|
|
48249
48335
|
//#region src/cli/utils/indent-multiline-text.ts
|
|
48250
48336
|
const indentMultilineText = (text, linePrefix) => text.split("\n").map((lineText) => `${linePrefix}${lineText}`).join("\n");
|
|
48251
48337
|
//#endregion
|
|
@@ -48399,17 +48485,23 @@ const clusterNearbyDiagnostics = (diagnostics) => {
|
|
|
48399
48485
|
}
|
|
48400
48486
|
return clusters;
|
|
48401
48487
|
};
|
|
48402
|
-
const
|
|
48488
|
+
const formatClusterLocationText = (cluster) => {
|
|
48489
|
+
const { filePath } = cluster.diagnostics[0];
|
|
48490
|
+
if (cluster.startLine <= 0) return filePath;
|
|
48491
|
+
if (cluster.endLine > cluster.startLine) return `${filePath}:${cluster.startLine}-${cluster.endLine}`;
|
|
48492
|
+
return `${filePath}:${cluster.startLine}`;
|
|
48493
|
+
};
|
|
48494
|
+
const formatClusterLocation = (cluster, resolveSourceRoot, hyperlinks) => {
|
|
48403
48495
|
const lead = cluster.diagnostics[0];
|
|
48404
48496
|
const contextTag = formatFileContextTag(lead);
|
|
48405
|
-
|
|
48406
|
-
if (
|
|
48407
|
-
return `${lead.filePath
|
|
48497
|
+
const location = formatClusterLocationText(cluster);
|
|
48498
|
+
if (!hyperlinks) return `${location}${contextTag}`;
|
|
48499
|
+
return `${formatHyperlink(location, pathToFileURL(resolveAbsolutePath(lead.filePath, resolveSourceRoot(lead))).href)}${contextTag}`;
|
|
48408
48500
|
};
|
|
48409
|
-
const buildDiagnosticClusterLines = (cluster, resolveSourceRoot, renderCodeFrame) => {
|
|
48501
|
+
const buildDiagnosticClusterLines = (cluster, resolveSourceRoot, renderCodeFrame, hyperlinks) => {
|
|
48410
48502
|
const lead = cluster.diagnostics[0];
|
|
48411
48503
|
const isMultiSite = cluster.diagnostics.length > 1;
|
|
48412
|
-
const lines = ["", highlighter.gray(`${TOP_ERROR_DETAIL_INDENT}${formatClusterLocation(cluster)}`)];
|
|
48504
|
+
const lines = ["", highlighter.gray(`${TOP_ERROR_DETAIL_INDENT}${formatClusterLocation(cluster, resolveSourceRoot, hyperlinks)}`)];
|
|
48413
48505
|
const codeFrame = renderCodeFrame ? buildCodeFrame({
|
|
48414
48506
|
filePath: lead.filePath,
|
|
48415
48507
|
line: cluster.startLine,
|
|
@@ -48428,7 +48520,7 @@ const buildDiagnosticClusterLines = (cluster, resolveSourceRoot, renderCodeFrame
|
|
|
48428
48520
|
}
|
|
48429
48521
|
return lines;
|
|
48430
48522
|
};
|
|
48431
|
-
const buildRuleDetailBlock = (ruleKey, ruleDiagnostics, resolveSourceRoot, renderEverySite, isAgentEnvironment) => {
|
|
48523
|
+
const buildRuleDetailBlock = (ruleKey, ruleDiagnostics, resolveSourceRoot, renderEverySite, isAgentEnvironment, hyperlinks) => {
|
|
48432
48524
|
const representative = pickRepresentativeDiagnostic(ruleDiagnostics);
|
|
48433
48525
|
const { severity } = representative;
|
|
48434
48526
|
const trailingBadge = formatTrailingSiteBadge(ruleDiagnostics.length);
|
|
@@ -48448,7 +48540,7 @@ const buildRuleDetailBlock = (ruleKey, ruleDiagnostics, resolveSourceRoot, rende
|
|
|
48448
48540
|
}
|
|
48449
48541
|
const renderCodeFrame = severity === "error";
|
|
48450
48542
|
const sites = renderEverySite ? ruleDiagnostics : [representative];
|
|
48451
|
-
if (!(isCollapsedWarningGroup && representative.help.includes(representative.filePath))) for (const cluster of clusterNearbyDiagnostics(sites)) lines.push(...buildDiagnosticClusterLines(cluster, resolveSourceRoot, renderCodeFrame));
|
|
48543
|
+
if (!(isCollapsedWarningGroup && representative.help.includes(representative.filePath))) for (const cluster of clusterNearbyDiagnostics(sites)) lines.push(...buildDiagnosticClusterLines(cluster, resolveSourceRoot, renderCodeFrame, hyperlinks));
|
|
48452
48544
|
return lines;
|
|
48453
48545
|
};
|
|
48454
48546
|
const selectErrorRuleGroups = (diagnostics, rulePriority) => buildSortedRuleGroups(diagnostics.filter((diagnostic) => diagnostic.severity === "error"), rulePriority);
|
|
@@ -48461,7 +48553,7 @@ const buildOverflowSummaryLine = (diagnostics, rulePriority) => {
|
|
|
48461
48553
|
return ` ${highlighter.dim("Run")} ${command} ${highlighter.dim("to list every error and warning")}`;
|
|
48462
48554
|
};
|
|
48463
48555
|
const getTopErrorRuleKeys = (diagnostics, limit, rulePriority) => new Set(selectTopErrorRuleGroups(diagnostics, limit, rulePriority).map(([ruleKey]) => ruleKey));
|
|
48464
|
-
const buildTopErrorsSection = (diagnostics, resolveSourceRoot, rulePriority) => {
|
|
48556
|
+
const buildTopErrorsSection = (diagnostics, resolveSourceRoot, hyperlinks, rulePriority) => {
|
|
48465
48557
|
const topRuleGroups = selectErrorRuleGroups(diagnostics, rulePriority).slice(0, 3);
|
|
48466
48558
|
if (topRuleGroups.length === 0) return {
|
|
48467
48559
|
lines: [],
|
|
@@ -48471,7 +48563,7 @@ const buildTopErrorsSection = (diagnostics, resolveSourceRoot, rulePriority) =>
|
|
|
48471
48563
|
const blockOffsets = [];
|
|
48472
48564
|
for (const [ruleKey, ruleDiagnostics] of topRuleGroups) {
|
|
48473
48565
|
blockOffsets.push(lines.length);
|
|
48474
|
-
lines.push(...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, false, false));
|
|
48566
|
+
lines.push(...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, false, false, hyperlinks));
|
|
48475
48567
|
lines.push("");
|
|
48476
48568
|
}
|
|
48477
48569
|
return {
|
|
@@ -48509,18 +48601,18 @@ const buildOverviewHeaderLines = (diagnostics) => {
|
|
|
48509
48601
|
* single Effect.forEach over Console.log so failures or fiber
|
|
48510
48602
|
* interruption produce predictable partial output.
|
|
48511
48603
|
*/
|
|
48512
|
-
const printDiagnostics = (diagnostics, isVerbose, sourceRoot, rulePriority, isAgentEnvironment = false, onboarding = {}) => gen(function* () {
|
|
48604
|
+
const printDiagnostics = (diagnostics, isVerbose, sourceRoot, rulePriority, isAgentEnvironment = false, onboarding = {}, hyperlinks = false) => gen(function* () {
|
|
48513
48605
|
const sectionPause = onboarding.sectionPause ?? void_;
|
|
48514
48606
|
const animateCountUp = onboarding.animateCountUp ?? false;
|
|
48515
48607
|
const resolveSourceRoot = typeof sourceRoot === "function" ? sourceRoot : () => sourceRoot;
|
|
48516
48608
|
let detailLines;
|
|
48517
48609
|
let topErrorBlockOffsets = [];
|
|
48518
48610
|
if (!isVerbose) {
|
|
48519
|
-
const topErrors = buildTopErrorsSection(diagnostics, resolveSourceRoot, rulePriority);
|
|
48611
|
+
const topErrors = buildTopErrorsSection(diagnostics, resolveSourceRoot, hyperlinks, rulePriority);
|
|
48520
48612
|
detailLines = topErrors.lines;
|
|
48521
48613
|
topErrorBlockOffsets = topErrors.blockOffsets;
|
|
48522
48614
|
} else detailLines = buildSortedRuleGroups(diagnostics, rulePriority).flatMap(([ruleKey, ruleDiagnostics]) => {
|
|
48523
|
-
return [...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, true, isAgentEnvironment), ""];
|
|
48615
|
+
return [...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, true, isAgentEnvironment, hyperlinks), ""];
|
|
48524
48616
|
});
|
|
48525
48617
|
const overflowLine = isVerbose ? void 0 : buildOverflowSummaryLine(diagnostics, rulePriority);
|
|
48526
48618
|
const categoryTallies = buildCategoryDiagnosticGroups(diagnostics, rulePriority).map(buildCategoryTally);
|
|
@@ -48581,6 +48673,48 @@ const computeProjectedScore = async (topErrorSource, rescoreSource, currentScore
|
|
|
48581
48673
|
//#endregion
|
|
48582
48674
|
//#region src/cli/utils/filter-diagnostics-by-categories.ts
|
|
48583
48675
|
const filterDiagnosticsByCategories = (diagnostics, categories) => categories.size === 0 ? [...diagnostics] : diagnostics.filter((diagnostic) => categories.has(diagnostic.category));
|
|
48676
|
+
//#endregion
|
|
48677
|
+
//#region src/cli/utils/supports-hyperlinks.ts
|
|
48678
|
+
const HYPERLINK_CAPABLE_TERM_PROGRAMS = new Set([
|
|
48679
|
+
"iTerm.app",
|
|
48680
|
+
"WezTerm",
|
|
48681
|
+
"vscode",
|
|
48682
|
+
"Hyper",
|
|
48683
|
+
"ghostty",
|
|
48684
|
+
"Tabby",
|
|
48685
|
+
"rio"
|
|
48686
|
+
]);
|
|
48687
|
+
const parseVteVersion = (raw) => {
|
|
48688
|
+
const parsed = Number.parseInt(raw ?? "", 10);
|
|
48689
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
48690
|
+
};
|
|
48691
|
+
/**
|
|
48692
|
+
* Whether `stream` is a terminal that renders OSC 8 hyperlinks. Auto-detected
|
|
48693
|
+
* from terminal-identity env vars; the de-facto `FORCE_HYPERLINK` env var
|
|
48694
|
+
* overrides detection (`FORCE_HYPERLINK=0`/`false` forces off, any other value
|
|
48695
|
+
* forces on), mirroring how the ecosystem's terminal libraries gate the same
|
|
48696
|
+
* feature. Off for non-TTYs, `TERM=dumb`, and CI (whose log viewers render the
|
|
48697
|
+
* raw escape rather than a link). Unknown terminals default to off.
|
|
48698
|
+
*/
|
|
48699
|
+
const supportsHyperlinks = (stream = process.stdout, env = process.env) => {
|
|
48700
|
+
const forced = env.FORCE_HYPERLINK;
|
|
48701
|
+
if (forced !== void 0 && forced !== "") return forced !== "0" && forced.toLowerCase() !== "false";
|
|
48702
|
+
if (stream.isTTY !== true) return false;
|
|
48703
|
+
if (env.TERM === "dumb") return false;
|
|
48704
|
+
if (isCiEnvironment(env)) return false;
|
|
48705
|
+
if (env.WT_SESSION) return true;
|
|
48706
|
+
if (env.KITTY_WINDOW_ID || env.TERM === "xterm-kitty") return true;
|
|
48707
|
+
if (parseVteVersion(env.VTE_VERSION) >= 5e3) return true;
|
|
48708
|
+
return Boolean(env.TERM_PROGRAM && HYPERLINK_CAPABLE_TERM_PROGRAMS.has(env.TERM_PROGRAM));
|
|
48709
|
+
};
|
|
48710
|
+
//#endregion
|
|
48711
|
+
//#region src/cli/utils/should-render-hyperlinks.ts
|
|
48712
|
+
/**
|
|
48713
|
+
* Whether to emit OSC 8 clickable `file:line` locations for this run: a
|
|
48714
|
+
* hyperlink-capable terminal AND not a coding agent (whose output parsers
|
|
48715
|
+
* would choke on the escape sequences).
|
|
48716
|
+
*/
|
|
48717
|
+
const shouldRenderHyperlinks = (stream = process.stdout) => supportsHyperlinks(stream) && !isCodingAgentEnvironment();
|
|
48584
48718
|
const FORCE_ONBOARDING_ENV_VAR = "REACT_DOCTOR_FORCE_ONBOARDING";
|
|
48585
48719
|
const FALSY_FLAG_VALUES = new Set([
|
|
48586
48720
|
"",
|
|
@@ -48600,10 +48734,9 @@ const canAnimateOnboarding = (stream = process.stdout) => {
|
|
|
48600
48734
|
};
|
|
48601
48735
|
//#endregion
|
|
48602
48736
|
//#region src/cli/utils/onboarding-state.ts
|
|
48603
|
-
const GLOBAL_CONFIG_PROJECT_NAME$2 = "react-doctor";
|
|
48604
48737
|
const ONBOARDED_AT_KEY = "onboardedAt";
|
|
48605
48738
|
const getOnboardingStore = (options = {}) => new Conf({
|
|
48606
|
-
projectName:
|
|
48739
|
+
projectName: REACT_DOCTOR_CONFIG_PROJECT_NAME,
|
|
48607
48740
|
cwd: options.cwd
|
|
48608
48741
|
});
|
|
48609
48742
|
const hasCompletedOnboarding = (options = {}) => {
|
|
@@ -49679,6 +49812,7 @@ const finalizeAndRender = (input) => gen(function* () {
|
|
|
49679
49812
|
}
|
|
49680
49813
|
const animateRender = !options.silent && !options.verbose && canAnimateOnboarding(process.stdout);
|
|
49681
49814
|
const pause = onboardingSectionPause(animateRender);
|
|
49815
|
+
const useHyperlinks = shouldRenderHyperlinks(process.stdout);
|
|
49682
49816
|
const demotedDiagnosticCount = diagnostics.length - surfaceDiagnostics.length;
|
|
49683
49817
|
const lintSourceFileCount = options.includePaths.length > 0 ? options.includePaths.length : project.sourceFileCount;
|
|
49684
49818
|
if (printedDiagnostics.length === 0) {
|
|
@@ -49704,7 +49838,7 @@ const finalizeAndRender = (input) => gen(function* () {
|
|
|
49704
49838
|
yield* printDiagnostics([...printedDiagnostics], options.verbose, directory, buildRulePriorityMap([score]), isCodingAgentEnvironment(), {
|
|
49705
49839
|
sectionPause: pause,
|
|
49706
49840
|
animateCountUp: animateRender
|
|
49707
|
-
});
|
|
49841
|
+
}, useHyperlinks);
|
|
49708
49842
|
if (options.isNonInteractiveEnvironment && options.outputSurface !== "prComment") yield* printAgentGuidance();
|
|
49709
49843
|
if (options.categoryFilters.size === 0 && demotedDiagnosticCount > 0) {
|
|
49710
49844
|
yield* log(highlighter.gray(` ${demotedDiagnosticCount} demoted from the ${options.outputSurface} surface (e.g. design cleanup) — run \`npx react-doctor@latest .\` locally for the full list.`));
|
|
@@ -49897,16 +50031,7 @@ const buildHandoffPayload = (input) => {
|
|
|
49897
50031
|
try {
|
|
49898
50032
|
outputDirectory = writeDiagnosticsDirectory([...input.diagnostics], input.outputDirectory);
|
|
49899
50033
|
} catch {}
|
|
49900
|
-
const lines = [
|
|
49901
|
-
"Before fixing anything, first ask me whether I'd like to add React Doctor to CI so every pull request is scanned automatically. Explain that:",
|
|
49902
|
-
`- It's used by teams at ${CI_TRUST_COMPANIES}.`,
|
|
49903
|
-
"- I don't have to fix everything at once; CI keeps new PRs clean while I incrementally pay down the existing issues.",
|
|
49904
|
-
`- Setup guide: ${CI_URL}`,
|
|
49905
|
-
"If I say yes, run `npx react-doctor install` (or add the GitHub Actions workflow). Either way, then continue with the fixes below.",
|
|
49906
|
-
"",
|
|
49907
|
-
`Fix the top ${topGroups.length} React Doctor ${topGroups.length === 1 ? "issue" : "issues"} in ${input.projectName} on this pass — leave the rest for a follow-up.`,
|
|
49908
|
-
""
|
|
49909
|
-
];
|
|
50034
|
+
const lines = [`Fix the top ${topGroups.length} React Doctor ${topGroups.length === 1 ? "issue" : "issues"} in ${input.projectName} on this pass — leave the rest for a follow-up.`, ""];
|
|
49910
50035
|
topGroups.forEach(([ruleKey, ruleDiagnostics], index) => {
|
|
49911
50036
|
const representative = ruleDiagnostics[0];
|
|
49912
50037
|
const severityLabel = representative.severity === "error" ? "ERROR" : "WARN";
|
|
@@ -50276,38 +50401,52 @@ const upgradeReactDoctorWorkflowInPlace = (projectRoot) => {
|
|
|
50276
50401
|
//#region src/cli/utils/hash-project-root.ts
|
|
50277
50402
|
const hashProjectRoot = (projectRoot) => createHash("sha256").update(Path.resolve(projectRoot)).digest("hex");
|
|
50278
50403
|
//#endregion
|
|
50279
|
-
//#region src/cli/utils/
|
|
50280
|
-
const
|
|
50281
|
-
const
|
|
50282
|
-
|
|
50283
|
-
|
|
50284
|
-
});
|
|
50285
|
-
|
|
50286
|
-
|
|
50287
|
-
|
|
50288
|
-
|
|
50289
|
-
|
|
50290
|
-
|
|
50291
|
-
|
|
50292
|
-
};
|
|
50293
|
-
const recordActionUpgradeDecision = (projectRoot, outcome, storeOptions = {}) => {
|
|
50294
|
-
try {
|
|
50295
|
-
const store = getActionUpgradeStore(storeOptions);
|
|
50296
|
-
const upgrades = store.get("actionUpgrades", {});
|
|
50297
|
-
store.set("actionUpgrades", {
|
|
50298
|
-
...upgrades,
|
|
50299
|
-
[hashProjectRoot(projectRoot)]: {
|
|
50300
|
-
rootDirectory: Path.resolve(projectRoot),
|
|
50301
|
-
outcome,
|
|
50302
|
-
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
50404
|
+
//#region src/cli/utils/project-decision-store.ts
|
|
50405
|
+
const createProjectDecisionStore = (storeKey) => {
|
|
50406
|
+
const getStore = (options = {}) => new Conf({
|
|
50407
|
+
projectName: REACT_DOCTOR_CONFIG_PROJECT_NAME,
|
|
50408
|
+
cwd: options.cwd
|
|
50409
|
+
});
|
|
50410
|
+
return {
|
|
50411
|
+
getConfigPath: (options = {}) => getStore(options).path,
|
|
50412
|
+
hasHandled: (projectRoot, options = {}) => {
|
|
50413
|
+
try {
|
|
50414
|
+
return Boolean(getStore(options).get(storeKey, {})[hashProjectRoot(projectRoot)]);
|
|
50415
|
+
} catch {
|
|
50416
|
+
return true;
|
|
50303
50417
|
}
|
|
50304
|
-
}
|
|
50305
|
-
|
|
50306
|
-
|
|
50307
|
-
|
|
50308
|
-
|
|
50418
|
+
},
|
|
50419
|
+
record: (projectRoot, outcome, options = {}) => {
|
|
50420
|
+
try {
|
|
50421
|
+
const store = getStore(options);
|
|
50422
|
+
store.set(storeKey, {
|
|
50423
|
+
...store.get(storeKey, {}),
|
|
50424
|
+
[hashProjectRoot(projectRoot)]: {
|
|
50425
|
+
rootDirectory: Path.resolve(projectRoot),
|
|
50426
|
+
outcome,
|
|
50427
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
50428
|
+
}
|
|
50429
|
+
});
|
|
50430
|
+
return true;
|
|
50431
|
+
} catch {
|
|
50432
|
+
return false;
|
|
50433
|
+
}
|
|
50434
|
+
}
|
|
50435
|
+
};
|
|
50309
50436
|
};
|
|
50310
50437
|
//#endregion
|
|
50438
|
+
//#region src/cli/utils/action-upgrade-prompt.ts
|
|
50439
|
+
const store$1 = createProjectDecisionStore("actionUpgrades");
|
|
50440
|
+
store$1.getConfigPath;
|
|
50441
|
+
const hasHandledActionUpgrade = store$1.hasHandled;
|
|
50442
|
+
const recordActionUpgradeDecision = store$1.record;
|
|
50443
|
+
//#endregion
|
|
50444
|
+
//#region src/cli/utils/ci-prompt-decision.ts
|
|
50445
|
+
const store = createProjectDecisionStore("ciPrompts");
|
|
50446
|
+
store.getConfigPath;
|
|
50447
|
+
const hasHandledCiPrompt = store.hasHandled;
|
|
50448
|
+
const recordCiPromptDecision = store.record;
|
|
50449
|
+
//#endregion
|
|
50311
50450
|
//#region src/cli/utils/open-url.ts
|
|
50312
50451
|
const resolveOpenCommand = (url) => {
|
|
50313
50452
|
if (process$1.platform === "darwin") return {
|
|
@@ -51524,10 +51663,12 @@ const runInstallReactDoctor = async (options = {}) => {
|
|
|
51524
51663
|
const existingWorkflow = readReactDoctorWorkflow(projectRoot);
|
|
51525
51664
|
const canInstallWorkflow = !NFS.existsSync(workflowTargetPath);
|
|
51526
51665
|
const canUpgradeWorkflow = existingWorkflow !== null && workflowUsesV1Action(existingWorkflow.content) && !hasHandledActionUpgrade(projectRoot);
|
|
51527
|
-
const
|
|
51666
|
+
const ciPromptOutcome = canInstallWorkflow && !options.yes && !skipPrompts && !hasHandledCiPrompt(projectRoot) ? await askAddToGitHubActions(prompt) : null;
|
|
51667
|
+
const shouldInstallWorkflow = canInstallWorkflow && (Boolean(options.yes) || ciPromptOutcome === "yes");
|
|
51528
51668
|
const upgradePromptOutcome = canUpgradeWorkflow && !options.yes && !skipPrompts ? await askUpgradeActionVersion(prompt) : null;
|
|
51529
51669
|
const shouldUpgradeWorkflow = canUpgradeWorkflow && (Boolean(options.yes) || upgradePromptOutcome === "yes");
|
|
51530
51670
|
if (upgradePromptOutcome === "no" && !options.dryRun) recordActionUpgradeDecision(projectRoot, "declined");
|
|
51671
|
+
if ((ciPromptOutcome === "yes" || ciPromptOutcome === "no") && !options.dryRun) recordCiPromptDecision(projectRoot, ciPromptOutcome === "yes" ? "accepted" : "declined");
|
|
51531
51672
|
const selectedAgents = skipPrompts ? detectedAgents : (await prompt({
|
|
51532
51673
|
type: "multiselect",
|
|
51533
51674
|
name: "agents",
|
|
@@ -51774,18 +51915,24 @@ const handoffToAgent = async (input) => {
|
|
|
51774
51915
|
if (!input.interactive || input.diagnostics.length === 0) return;
|
|
51775
51916
|
cliLogger.break();
|
|
51776
51917
|
const projectRootForCi = findNearestPackageDirectory(input.rootDirectory) ?? input.rootDirectory;
|
|
51777
|
-
|
|
51918
|
+
const isGitHubActionsConfigured = isReactDoctorWorkflowInstalled(projectRootForCi);
|
|
51919
|
+
if (!isGitHubActionsConfigured && !hasHandledCiPrompt(projectRootForCi)) {
|
|
51778
51920
|
const ciOutcome = await askAddToGitHubActions();
|
|
51779
51921
|
recordCount(METRIC.agentHandoff, 1, {
|
|
51780
51922
|
outcome: `ci-${ciOutcome}`,
|
|
51781
51923
|
diagnosticsCount: input.diagnostics.length
|
|
51782
51924
|
});
|
|
51783
51925
|
if (ciOutcome === "cancel") return;
|
|
51926
|
+
recordCiPromptDecision(projectRootForCi, ciOutcome === "yes" ? "accepted" : "declined");
|
|
51784
51927
|
if (ciOutcome === "yes") {
|
|
51785
51928
|
await setUpGitHubActions({ rootDirectory: input.rootDirectory });
|
|
51786
51929
|
cliLogger.break();
|
|
51787
51930
|
}
|
|
51788
|
-
} else await maybeOfferActionUpgrade(projectRootForCi);
|
|
51931
|
+
} else if (isGitHubActionsConfigured) await maybeOfferActionUpgrade(projectRootForCi);
|
|
51932
|
+
else recordCount(METRIC.agentHandoff, 1, {
|
|
51933
|
+
outcome: "ci-suppressed",
|
|
51934
|
+
diagnosticsCount: input.diagnostics.length
|
|
51935
|
+
});
|
|
51789
51936
|
const { handoffTarget } = await prompts({
|
|
51790
51937
|
type: "select",
|
|
51791
51938
|
name: "handoffTarget",
|
|
@@ -52091,7 +52238,7 @@ const printMultiProjectSummary = (input) => gen(function* () {
|
|
|
52091
52238
|
yield* log(`${highlighter.success("✔")} Scanned ${totalScannedFileCount} ${totalScannedFileCount === 1 ? "file" : "files"} in ${formatElapsedTime(totalElapsedMilliseconds)}`);
|
|
52092
52239
|
if (displayDiagnostics.length > 0) {
|
|
52093
52240
|
yield* log("");
|
|
52094
|
-
yield* printDiagnostics(displayDiagnostics, verbose, resolveDiagnosticSourceRoot, buildRulePriorityMap(completedScans.map((scan) => scan.result.score)), isCodingAgentEnvironment(), { animateCountUp: animateRender });
|
|
52241
|
+
yield* printDiagnostics(displayDiagnostics, verbose, resolveDiagnosticSourceRoot, buildRulePriorityMap(completedScans.map((scan) => scan.result.score)), isCodingAgentEnvironment(), { animateCountUp: animateRender }, shouldRenderHyperlinks(process.stdout));
|
|
52095
52242
|
}
|
|
52096
52243
|
const lowestScoredScan = findLowestScoredScan(completedScans);
|
|
52097
52244
|
const aggregateScore = lowestScoredScan?.result.score ?? null;
|
|
@@ -52129,9 +52276,8 @@ const printMultiProjectSummary = (input) => gen(function* () {
|
|
|
52129
52276
|
});
|
|
52130
52277
|
//#endregion
|
|
52131
52278
|
//#region src/cli/utils/prompt-install-setup.ts
|
|
52132
|
-
const GLOBAL_CONFIG_PROJECT_NAME = "react-doctor";
|
|
52133
52279
|
const getSetupPromptStore = (options = {}) => new Conf({
|
|
52134
|
-
projectName:
|
|
52280
|
+
projectName: REACT_DOCTOR_CONFIG_PROJECT_NAME,
|
|
52135
52281
|
cwd: options.cwd
|
|
52136
52282
|
});
|
|
52137
52283
|
const getSetupPromptProjectKey = (projectRoot) => hashProjectRoot(projectRoot);
|
|
@@ -52142,6 +52288,24 @@ const hasDisabledSetupPrompt = (projectRoot, storeOptions = {}) => {
|
|
|
52142
52288
|
return false;
|
|
52143
52289
|
}
|
|
52144
52290
|
};
|
|
52291
|
+
const disableSetupPrompt = (projectRoot, storeOptions = {}) => {
|
|
52292
|
+
try {
|
|
52293
|
+
const store = getSetupPromptStore(storeOptions);
|
|
52294
|
+
const projects = store.get("projects", {});
|
|
52295
|
+
const projectKey = getSetupPromptProjectKey(projectRoot);
|
|
52296
|
+
store.set("projects", {
|
|
52297
|
+
...projects,
|
|
52298
|
+
[projectKey]: {
|
|
52299
|
+
...projects[projectKey] ?? {},
|
|
52300
|
+
rootDirectory: Path.resolve(projectRoot),
|
|
52301
|
+
setupPrompt: false
|
|
52302
|
+
}
|
|
52303
|
+
});
|
|
52304
|
+
return true;
|
|
52305
|
+
} catch {
|
|
52306
|
+
return false;
|
|
52307
|
+
}
|
|
52308
|
+
};
|
|
52145
52309
|
const resolveInstallSetupProjectRoot = (options) => {
|
|
52146
52310
|
if (options.scanDirectories.length === 0) return findNearestPackageDirectory(options.scanRoot) ?? options.scanRoot;
|
|
52147
52311
|
const packageDirectories = /* @__PURE__ */ new Set();
|
|
@@ -52548,6 +52712,14 @@ const runExplain = async (fileLineArgument, context) => {
|
|
|
52548
52712
|
const colorizedRule = colorizeRuleByDiagnostic(ruleIdentifier, diagnostic.severity);
|
|
52549
52713
|
const severityLabel = colorizeRuleByDiagnostic(diagnostic.severity, diagnostic.severity);
|
|
52550
52714
|
cliLogger.log(`${severitySymbol} ${colorizedRule} ${highlighter.dim(`(${severityLabel})`)} — ${diagnostic.message}`);
|
|
52715
|
+
const codeFrame = buildCodeFrame({
|
|
52716
|
+
filePath: diagnostic.filePath,
|
|
52717
|
+
line: diagnostic.line,
|
|
52718
|
+
column: diagnostic.column,
|
|
52719
|
+
endLine: diagnostic.endLine,
|
|
52720
|
+
rootDirectory: targetDirectory
|
|
52721
|
+
});
|
|
52722
|
+
if (codeFrame) cliLogger.log(indentMultilineText(codeFrame, " "));
|
|
52551
52723
|
if (diagnostic.category) cliLogger.dim(` Category: ${diagnostic.category}`);
|
|
52552
52724
|
if (diagnostic.help) cliLogger.dim(` ${diagnostic.help}`);
|
|
52553
52725
|
cliLogger.dim(` If this needs follow-up or looks like a false positive, open: ${buildDiagnosticIssueUrl({
|
|
@@ -52944,6 +53116,7 @@ const inspectAction = async (directory, flags) => {
|
|
|
52944
53116
|
})) {
|
|
52945
53117
|
printAgentInstallHint();
|
|
52946
53118
|
recordCount(METRIC.agentInstallHintShown, 1);
|
|
53119
|
+
disableSetupPrompt(setupProjectRoot);
|
|
52947
53120
|
}
|
|
52948
53121
|
}
|
|
52949
53122
|
} catch (error) {
|
|
@@ -53951,4 +54124,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
53951
54124
|
export {};
|
|
53952
54125
|
|
|
53953
54126
|
//# sourceMappingURL=cli.js.map
|
|
53954
|
-
//# debugId=
|
|
54127
|
+
//# debugId=ad091b20-c3e2-5c96-93ac-9a910745a035
|
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]="4e83db09-9255-525f-b6fd-405784826e7d")}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 * as NFS from "node:fs";
|
|
@@ -36472,15 +36472,10 @@ const buildCapabilities = (project) => {
|
|
|
36472
36472
|
}
|
|
36473
36473
|
if (project.tailwindVersion !== null) {
|
|
36474
36474
|
capabilities.add("tailwind");
|
|
36475
|
-
|
|
36476
|
-
if (isTailwindAtLeast(tailwind, {
|
|
36475
|
+
if (isTailwindAtLeast(parseTailwindMajorMinor(project.tailwindVersion), {
|
|
36477
36476
|
major: 3,
|
|
36478
36477
|
minor: 4
|
|
36479
36478
|
})) capabilities.add("tailwind:3.4");
|
|
36480
|
-
if (tailwind !== null && isTailwindAtLeast(tailwind, {
|
|
36481
|
-
major: 4,
|
|
36482
|
-
minor: 0
|
|
36483
|
-
})) capabilities.add("tailwind:4");
|
|
36484
36479
|
}
|
|
36485
36480
|
if (project.zodVersion !== null) {
|
|
36486
36481
|
capabilities.add("zod");
|
|
@@ -38089,8 +38084,8 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
38089
38084
|
}
|
|
38090
38085
|
return enabled;
|
|
38091
38086
|
};
|
|
38092
|
-
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [] }) => {
|
|
38093
|
-
const reactHooksJsPlugin = resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
|
|
38087
|
+
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false }) => {
|
|
38088
|
+
const reactHooksJsPlugin = disableReactHooksJsPlugin ? null : resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
|
|
38094
38089
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
38095
38090
|
const jsPlugins = [];
|
|
38096
38091
|
if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
|
|
@@ -38787,9 +38782,9 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
38787
38782
|
try {
|
|
38788
38783
|
parsed = JSON.parse(sanitizedStdout);
|
|
38789
38784
|
} catch {
|
|
38790
|
-
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0,
|
|
38785
|
+
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
38791
38786
|
}
|
|
38792
|
-
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0,
|
|
38787
|
+
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
38793
38788
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
38794
38789
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
38795
38790
|
const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
@@ -39080,6 +39075,28 @@ const writeOxlintConfig = (configPath, configToWrite) => {
|
|
|
39080
39075
|
NFS.closeSync(fileHandle);
|
|
39081
39076
|
}
|
|
39082
39077
|
};
|
|
39078
|
+
const REACT_HOOKS_JS_DROP_PREFIX = "React Compiler rules (react-hooks-js/*) skipped — eslint-plugin-react-hooks failed to load in this environment";
|
|
39079
|
+
/**
|
|
39080
|
+
* Detects an oxlint config-load crash caused by the optional
|
|
39081
|
+
* `react-hooks-js` (eslint-plugin-react-hooks) React Compiler plugin and
|
|
39082
|
+
* builds the partial-failure note for it; returns `null` when the failure
|
|
39083
|
+
* was anything else.
|
|
39084
|
+
*
|
|
39085
|
+
* oxlint prints a framed error to stdout (not stderr) and exits non-zero
|
|
39086
|
+
* when a `jsPlugins` entry can't be imported; that non-JSON stdout
|
|
39087
|
+
* surfaces as `OxlintOutputUnparseable`. Because oxlint fails the WHOLE
|
|
39088
|
+
* config load on it, leaving the plugin in would drop every curated
|
|
39089
|
+
* react-doctor diagnostic too — so the caller retries with the plugin
|
|
39090
|
+
* stripped (issue #833). Both markers sit at the start of oxlint's
|
|
39091
|
+
* message, so they survive the `preview` slice even for deep pnpm paths.
|
|
39092
|
+
*/
|
|
39093
|
+
const reactHooksJsPluginDropNote = (error) => {
|
|
39094
|
+
if (!(error instanceof ReactDoctorError) || error.reason._tag !== "OxlintOutputUnparseable") return null;
|
|
39095
|
+
const { preview } = error.reason;
|
|
39096
|
+
if (!preview.includes("Failed to load JS plugin") || !preview.includes("eslint-plugin-react-hooks")) return null;
|
|
39097
|
+
const underlyingReason = preview.match(/Error:[^\n]*/)?.[0]?.trim();
|
|
39098
|
+
return `${REACT_HOOKS_JS_DROP_PREFIX}${underlyingReason ? `: ${underlyingReason}` : ""}. Other rules ran normally.`;
|
|
39099
|
+
};
|
|
39083
39100
|
/**
|
|
39084
39101
|
* The oxlint runner. Composed of three pieces in `runners/oxlint/`:
|
|
39085
39102
|
*
|
|
@@ -39107,15 +39124,16 @@ const runOxlint = async (options) => {
|
|
|
39107
39124
|
const pluginPath = resolvePluginPath();
|
|
39108
39125
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
39109
39126
|
const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
39110
|
-
const buildConfig = (
|
|
39127
|
+
const buildConfig = (overrides) => createOxlintConfig({
|
|
39111
39128
|
pluginPath,
|
|
39112
39129
|
project,
|
|
39113
39130
|
customRulesOnly,
|
|
39114
|
-
extendsPaths:
|
|
39131
|
+
extendsPaths: overrides.extendsPaths,
|
|
39115
39132
|
ignoredTags,
|
|
39116
39133
|
serverAuthFunctionNames,
|
|
39117
39134
|
severityControls,
|
|
39118
|
-
userPlugins
|
|
39135
|
+
userPlugins,
|
|
39136
|
+
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin
|
|
39119
39137
|
});
|
|
39120
39138
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
39121
39139
|
const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
@@ -39151,12 +39169,22 @@ const runOxlint = async (options) => {
|
|
|
39151
39169
|
outputMaxBytes,
|
|
39152
39170
|
concurrency: options.concurrency
|
|
39153
39171
|
});
|
|
39154
|
-
writeOxlintConfig(configPath, buildConfig(extendsPaths));
|
|
39172
|
+
writeOxlintConfig(configPath, buildConfig({ extendsPaths }));
|
|
39155
39173
|
try {
|
|
39156
39174
|
return await runBatches();
|
|
39157
39175
|
} catch (error) {
|
|
39176
|
+
const reactHooksJsDropNote = reactHooksJsPluginDropNote(error);
|
|
39177
|
+
if (reactHooksJsDropNote !== null) {
|
|
39178
|
+
writeOxlintConfig(configPath, buildConfig({
|
|
39179
|
+
extendsPaths,
|
|
39180
|
+
disableReactHooksJsPlugin: true
|
|
39181
|
+
}));
|
|
39182
|
+
const diagnostics = await runBatches();
|
|
39183
|
+
onPartialFailure?.(reactHooksJsDropNote);
|
|
39184
|
+
return diagnostics;
|
|
39185
|
+
}
|
|
39158
39186
|
if (extendsPaths.length === 0) throw error;
|
|
39159
|
-
writeOxlintConfig(configPath, buildConfig([]));
|
|
39187
|
+
writeOxlintConfig(configPath, buildConfig({ extendsPaths: [] }));
|
|
39160
39188
|
return await runBatches();
|
|
39161
39189
|
}
|
|
39162
39190
|
} finally {
|
|
@@ -40576,4 +40604,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
40576
40604
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
40577
40605
|
|
|
40578
40606
|
//# sourceMappingURL=index.js.map
|
|
40579
|
-
//# debugId=
|
|
40607
|
+
//# debugId=4e83db09-9255-525f-b6fd-405784826e7d
|
package/dist/lsp.js
CHANGED
|
@@ -36458,15 +36458,10 @@ const buildCapabilities = (project) => {
|
|
|
36458
36458
|
}
|
|
36459
36459
|
if (project.tailwindVersion !== null) {
|
|
36460
36460
|
capabilities.add("tailwind");
|
|
36461
|
-
|
|
36462
|
-
if (isTailwindAtLeast(tailwind, {
|
|
36461
|
+
if (isTailwindAtLeast(parseTailwindMajorMinor(project.tailwindVersion), {
|
|
36463
36462
|
major: 3,
|
|
36464
36463
|
minor: 4
|
|
36465
36464
|
})) capabilities.add("tailwind:3.4");
|
|
36466
|
-
if (tailwind !== null && isTailwindAtLeast(tailwind, {
|
|
36467
|
-
major: 4,
|
|
36468
|
-
minor: 0
|
|
36469
|
-
})) capabilities.add("tailwind:4");
|
|
36470
36465
|
}
|
|
36471
36466
|
if (project.zodVersion !== null) {
|
|
36472
36467
|
capabilities.add("zod");
|
|
@@ -38075,8 +38070,8 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
38075
38070
|
}
|
|
38076
38071
|
return enabled;
|
|
38077
38072
|
};
|
|
38078
|
-
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [] }) => {
|
|
38079
|
-
const reactHooksJsPlugin = resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
|
|
38073
|
+
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false }) => {
|
|
38074
|
+
const reactHooksJsPlugin = disableReactHooksJsPlugin ? null : resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
|
|
38080
38075
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
38081
38076
|
const jsPlugins = [];
|
|
38082
38077
|
if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
|
|
@@ -38773,9 +38768,9 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
38773
38768
|
try {
|
|
38774
38769
|
parsed = JSON.parse(sanitizedStdout);
|
|
38775
38770
|
} catch {
|
|
38776
|
-
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0,
|
|
38771
|
+
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
38777
38772
|
}
|
|
38778
|
-
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0,
|
|
38773
|
+
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
38779
38774
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
38780
38775
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
38781
38776
|
const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
@@ -39066,6 +39061,28 @@ const writeOxlintConfig = (configPath, configToWrite) => {
|
|
|
39066
39061
|
NFS.closeSync(fileHandle);
|
|
39067
39062
|
}
|
|
39068
39063
|
};
|
|
39064
|
+
const REACT_HOOKS_JS_DROP_PREFIX = "React Compiler rules (react-hooks-js/*) skipped — eslint-plugin-react-hooks failed to load in this environment";
|
|
39065
|
+
/**
|
|
39066
|
+
* Detects an oxlint config-load crash caused by the optional
|
|
39067
|
+
* `react-hooks-js` (eslint-plugin-react-hooks) React Compiler plugin and
|
|
39068
|
+
* builds the partial-failure note for it; returns `null` when the failure
|
|
39069
|
+
* was anything else.
|
|
39070
|
+
*
|
|
39071
|
+
* oxlint prints a framed error to stdout (not stderr) and exits non-zero
|
|
39072
|
+
* when a `jsPlugins` entry can't be imported; that non-JSON stdout
|
|
39073
|
+
* surfaces as `OxlintOutputUnparseable`. Because oxlint fails the WHOLE
|
|
39074
|
+
* config load on it, leaving the plugin in would drop every curated
|
|
39075
|
+
* react-doctor diagnostic too — so the caller retries with the plugin
|
|
39076
|
+
* stripped (issue #833). Both markers sit at the start of oxlint's
|
|
39077
|
+
* message, so they survive the `preview` slice even for deep pnpm paths.
|
|
39078
|
+
*/
|
|
39079
|
+
const reactHooksJsPluginDropNote = (error) => {
|
|
39080
|
+
if (!(error instanceof ReactDoctorError) || error.reason._tag !== "OxlintOutputUnparseable") return null;
|
|
39081
|
+
const { preview } = error.reason;
|
|
39082
|
+
if (!preview.includes("Failed to load JS plugin") || !preview.includes("eslint-plugin-react-hooks")) return null;
|
|
39083
|
+
const underlyingReason = preview.match(/Error:[^\n]*/)?.[0]?.trim();
|
|
39084
|
+
return `${REACT_HOOKS_JS_DROP_PREFIX}${underlyingReason ? `: ${underlyingReason}` : ""}. Other rules ran normally.`;
|
|
39085
|
+
};
|
|
39069
39086
|
/**
|
|
39070
39087
|
* The oxlint runner. Composed of three pieces in `runners/oxlint/`:
|
|
39071
39088
|
*
|
|
@@ -39093,15 +39110,16 @@ const runOxlint = async (options) => {
|
|
|
39093
39110
|
const pluginPath = resolvePluginPath();
|
|
39094
39111
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
39095
39112
|
const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
39096
|
-
const buildConfig = (
|
|
39113
|
+
const buildConfig = (overrides) => createOxlintConfig({
|
|
39097
39114
|
pluginPath,
|
|
39098
39115
|
project,
|
|
39099
39116
|
customRulesOnly,
|
|
39100
|
-
extendsPaths:
|
|
39117
|
+
extendsPaths: overrides.extendsPaths,
|
|
39101
39118
|
ignoredTags,
|
|
39102
39119
|
serverAuthFunctionNames,
|
|
39103
39120
|
severityControls,
|
|
39104
|
-
userPlugins
|
|
39121
|
+
userPlugins,
|
|
39122
|
+
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin
|
|
39105
39123
|
});
|
|
39106
39124
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
39107
39125
|
const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
@@ -39137,12 +39155,22 @@ const runOxlint = async (options) => {
|
|
|
39137
39155
|
outputMaxBytes,
|
|
39138
39156
|
concurrency: options.concurrency
|
|
39139
39157
|
});
|
|
39140
|
-
writeOxlintConfig(configPath, buildConfig(extendsPaths));
|
|
39158
|
+
writeOxlintConfig(configPath, buildConfig({ extendsPaths }));
|
|
39141
39159
|
try {
|
|
39142
39160
|
return await runBatches();
|
|
39143
39161
|
} catch (error) {
|
|
39162
|
+
const reactHooksJsDropNote = reactHooksJsPluginDropNote(error);
|
|
39163
|
+
if (reactHooksJsDropNote !== null) {
|
|
39164
|
+
writeOxlintConfig(configPath, buildConfig({
|
|
39165
|
+
extendsPaths,
|
|
39166
|
+
disableReactHooksJsPlugin: true
|
|
39167
|
+
}));
|
|
39168
|
+
const diagnostics = await runBatches();
|
|
39169
|
+
onPartialFailure?.(reactHooksJsDropNote);
|
|
39170
|
+
return diagnostics;
|
|
39171
|
+
}
|
|
39144
39172
|
if (extendsPaths.length === 0) throw error;
|
|
39145
|
-
writeOxlintConfig(configPath, buildConfig([]));
|
|
39173
|
+
writeOxlintConfig(configPath, buildConfig({ extendsPaths: [] }));
|
|
39146
39174
|
return await runBatches();
|
|
39147
39175
|
}
|
|
39148
39176
|
} finally {
|
|
@@ -42361,5 +42389,5 @@ const startLanguageServer = () => {
|
|
|
42361
42389
|
};
|
|
42362
42390
|
//#endregion
|
|
42363
42391
|
export { startLanguageServer };
|
|
42364
|
-
!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]="
|
|
42365
|
-
//# debugId=
|
|
42392
|
+
!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]="7deadb2d-94c2-54e2-bd0d-808ee8d4c380")}catch(e){}}();
|
|
42393
|
+
//# debugId=7deadb2d-94c2-54e2-bd0d-808ee8d4c380
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.5.6-dev.
|
|
3
|
+
"version": "0.5.6-dev.937a7ca",
|
|
4
4
|
"description": "Your agent writes bad React. This catches it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"vscode-languageserver": "^9.0.1",
|
|
65
65
|
"vscode-languageserver-textdocument": "^1.0.12",
|
|
66
66
|
"vscode-uri": "^3.1.0",
|
|
67
|
-
"oxlint-plugin-react-doctor": "0.5.6-dev.
|
|
67
|
+
"oxlint-plugin-react-doctor": "0.5.6-dev.937a7ca"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@types/babel__code-frame": "^7.27.0",
|
|
@@ -72,9 +72,9 @@
|
|
|
72
72
|
"@xterm/headless": "^6.0.0",
|
|
73
73
|
"commander": "^14.0.3",
|
|
74
74
|
"ora": "^9.4.0",
|
|
75
|
-
"@react-doctor/
|
|
75
|
+
"@react-doctor/api": "0.5.6",
|
|
76
76
|
"@react-doctor/language-server": "0.5.6",
|
|
77
|
-
"@react-doctor/
|
|
77
|
+
"@react-doctor/core": "0.5.6"
|
|
78
78
|
},
|
|
79
79
|
"engines": {
|
|
80
80
|
"node": "^20.19.0 || >=22.13.0"
|