react-doctor 0.5.6-dev.451beeb → 0.5.6-dev.50999f4

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.
Files changed (4) hide show
  1. package/dist/cli.js +468 -260
  2. package/dist/index.js +94 -70
  3. package/dist/lsp.js +113 -92
  4. package/package.json +2 -2
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]="a4394ddc-4e6c-5a18-aeeb-d60322b1c0dd")}catch(e){}}();
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]="ff319d21-ecce-5f79-a822-8cb00c30fea1")}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";
@@ -32724,6 +32724,7 @@ const isLargeMinifiedFile = (absolutePath) => {
32724
32724
  if (sizeBytes < 2e4) return false;
32725
32725
  return isMinifiedSource(absolutePath);
32726
32726
  };
32727
+ const isErrnoException = (error) => error instanceof Error && "code" in error;
32727
32728
  const IGNORABLE_READDIR_ERROR_CODES = new Set([
32728
32729
  "EACCES",
32729
32730
  "EPERM",
@@ -32733,11 +32734,7 @@ const IGNORABLE_READDIR_ERROR_CODES = new Set([
32733
32734
  "ELOOP",
32734
32735
  "ENAMETOOLONG"
32735
32736
  ]);
32736
- const isIgnorableReaddirError = (error) => {
32737
- if (typeof error !== "object" || error === null) return false;
32738
- const errorCode = error.code;
32739
- return typeof errorCode === "string" && IGNORABLE_READDIR_ERROR_CODES.has(errorCode);
32740
- };
32737
+ const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
32741
32738
  const readDirectoryEntries = (directoryPath) => {
32742
32739
  try {
32743
32740
  return NFS.readdirSync(directoryPath, { withFileTypes: true });
@@ -32787,7 +32784,7 @@ const readPackageJsonUncached = (packageJsonPath) => {
32787
32784
  return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
32788
32785
  } catch (error) {
32789
32786
  if (error instanceof SyntaxError) return {};
32790
- if (error instanceof Error && "code" in error) {
32787
+ if (isErrnoException(error)) {
32791
32788
  const { code } = error;
32792
32789
  if (code === "EISDIR" || code === "EACCES" || code === "EPERM" || code === "ENOENT") return {};
32793
32790
  }
@@ -33512,17 +33509,13 @@ const isPackageJsonReactNativeAware = (packageJson) => {
33512
33509
  return false;
33513
33510
  };
33514
33511
  const hasReactNativeWorkspaceAnywhere = (rootDirectory, rootPackageJson) => someWorkspacePackageJson(rootDirectory, rootPackageJson, isPackageJsonReactNativeAware);
33515
- const getExpoDependencySpec = (packageJson) => {
33516
- const spec = packageJson.dependencies?.expo ?? packageJson.devDependencies?.expo ?? packageJson.peerDependencies?.expo ?? packageJson.optionalDependencies?.expo;
33512
+ const getDependencySpec = (packageJson, packageName) => {
33513
+ const spec = packageJson.dependencies?.[packageName] ?? packageJson.devDependencies?.[packageName] ?? packageJson.peerDependencies?.[packageName] ?? packageJson.optionalDependencies?.[packageName];
33517
33514
  return typeof spec === "string" ? spec : null;
33518
33515
  };
33519
- const findExpoVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, getExpoDependencySpec);
33516
+ const findExpoVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, (packageJson) => getDependencySpec(packageJson, "expo"));
33520
33517
  const SHOPIFY_FLASH_LIST_PACKAGE_NAME = "@shopify/flash-list";
33521
- const getShopifyFlashListDependencySpec = (packageJson) => {
33522
- const spec = packageJson.dependencies?.["@shopify/flash-list"] ?? packageJson.devDependencies?.["@shopify/flash-list"] ?? packageJson.peerDependencies?.["@shopify/flash-list"] ?? packageJson.optionalDependencies?.["@shopify/flash-list"];
33523
- return typeof spec === "string" ? spec : null;
33524
- };
33525
- const findShopifyFlashListVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, getShopifyFlashListDependencySpec);
33518
+ const findShopifyFlashListVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, (packageJson) => getDependencySpec(packageJson, SHOPIFY_FLASH_LIST_PACKAGE_NAME));
33526
33519
  const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, version }) => {
33527
33520
  if (version === null || !isCatalogReference(version)) return version;
33528
33521
  const catalogName = extractCatalogName(version);
@@ -33534,11 +33527,7 @@ const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson,
33534
33527
  if (!isFile(monorepoPackageJsonPath)) return version;
33535
33528
  return resolveCatalogVersion(readPackageJson(monorepoPackageJsonPath), packageName, monorepoRoot, catalogName) ?? version;
33536
33529
  };
33537
- const getNextjsDependencySpec = (packageJson) => {
33538
- const spec = packageJson.dependencies?.next ?? packageJson.devDependencies?.next ?? packageJson.peerDependencies?.next ?? packageJson.optionalDependencies?.next;
33539
- return typeof spec === "string" ? spec : null;
33540
- };
33541
- const findNextjsVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, getNextjsDependencySpec);
33530
+ const findNextjsVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, (packageJson) => getDependencySpec(packageJson, "next"));
33542
33531
  const getPreactVersion = (packageJson) => {
33543
33532
  return {
33544
33533
  ...packageJson.peerDependencies,
@@ -33620,6 +33609,11 @@ const ES_TARGET_YEAR_BY_NAME = {
33620
33609
  esnext: 9999
33621
33610
  };
33622
33611
  /**
33612
+ * tsconfig filenames probed when resolving a project's TypeScript
33613
+ * compiler options — the root config first, then a monorepo base config.
33614
+ */
33615
+ const TSCONFIG_FILENAMES = ["tsconfig.json", "tsconfig.base.json"];
33616
+ /**
33623
33617
  * Project-config files that `StagedFiles.materialize` copies into
33624
33618
  * the temp directory alongside staged sources so oxlint resolves
33625
33619
  * `tsconfig` / `package.json` / lint configs the same way it would
@@ -34118,6 +34112,7 @@ const isTailwindAtLeast = (detected, required) => {
34118
34112
  if (detected.major !== required.major) return detected.major > required.major;
34119
34113
  return detected.minor >= required.minor;
34120
34114
  };
34115
+ const messageFromUnknown = (error) => error instanceof Error ? error.message : String(error);
34121
34116
  var InvalidGlobPatternError = class extends Error {
34122
34117
  pattern;
34123
34118
  reason;
@@ -34146,7 +34141,7 @@ const compileGlobPattern = (rawPattern) => {
34146
34141
  try {
34147
34142
  return import_picomatch.default.makeRe(normalizeGlobPattern(rawPattern), PICOMATCH_OPTIONS);
34148
34143
  } catch (caughtError) {
34149
- throw new InvalidGlobPatternError(rawPattern, caughtError instanceof Error ? caughtError.message : String(caughtError));
34144
+ throw new InvalidGlobPatternError(rawPattern, messageFromUnknown(caughtError));
34150
34145
  }
34151
34146
  };
34152
34147
  const compileGlobPatternsLenient = (patterns, onInvalid) => {
@@ -35328,7 +35323,6 @@ const PACKAGE_JSON_FILENAME = "package.json";
35328
35323
  const PACKAGE_JSON_CONFIG_KEY = "reactDoctor";
35329
35324
  const LEGACY_CONFIG_FILENAME = "react-doctor.config.json";
35330
35325
  const jiti = createJiti(import.meta.url);
35331
- const formatError = (error) => error instanceof Error ? error.message : String(error);
35332
35326
  const importDefaultExport = async (jitiInstance, filePath) => {
35333
35327
  const imported = await jitiInstance.import(filePath);
35334
35328
  return imported?.default ?? imported;
@@ -35360,7 +35354,7 @@ const loadModuleConfig = async (filePath) => {
35360
35354
  try {
35361
35355
  return await importDefaultExport(aliasJiti, filePath);
35362
35356
  } catch (retryError) {
35363
- throw new Error(`${formatError(error)} (retry with ${SELF_PACKAGE_IMPORT_SPECIFIER} aliased to the running react-doctor package also failed: ${formatError(retryError)})`, { cause: retryError });
35357
+ throw new Error(`${messageFromUnknown(error)} (retry with ${SELF_PACKAGE_IMPORT_SPECIFIER} aliased to the running react-doctor package also failed: ${messageFromUnknown(retryError)})`, { cause: retryError });
35364
35358
  }
35365
35359
  }
35366
35360
  };
@@ -35409,7 +35403,7 @@ const loadLegacyConfig = (directory) => {
35409
35403
  }
35410
35404
  warn(`${LEGACY_CONFIG_FILENAME} must contain an object, ignoring.`);
35411
35405
  } catch (error) {
35412
- warn(`Failed to load ${LEGACY_CONFIG_FILENAME}: ${formatError(error)}`);
35406
+ warn(`Failed to load ${LEGACY_CONFIG_FILENAME}: ${messageFromUnknown(error)}`);
35413
35407
  }
35414
35408
  return {
35415
35409
  status: "invalid",
@@ -35436,7 +35430,7 @@ const loadConfigFromDirectory = async (directory) => {
35436
35430
  warn(`${CONFIG_BASENAME}.${extension} must export an object, ignoring.`);
35437
35431
  sawBrokenConfigFile = true;
35438
35432
  } catch (error) {
35439
- warn(`Failed to load ${CONFIG_BASENAME}.${extension}: ${formatError(error)}`);
35433
+ warn(`Failed to load ${CONFIG_BASENAME}.${extension}: ${messageFromUnknown(error)}`);
35440
35434
  sawBrokenConfigFile = true;
35441
35435
  }
35442
35436
  }
@@ -36664,7 +36658,7 @@ const readIgnoreFile = (filePath) => {
36664
36658
  try {
36665
36659
  content = NFS.readFileSync(filePath, "utf-8");
36666
36660
  } catch (error) {
36667
- const errnoCode = error?.code;
36661
+ const errnoCode = isErrnoException(error) ? error.code : void 0;
36668
36662
  if (errnoCode && errnoCode !== "ENOENT") runSync(warn$1(`Could not read ignore file ${filePath}: ${errnoCode}`));
36669
36663
  return [];
36670
36664
  }
@@ -36705,8 +36699,8 @@ const collectIgnorePatterns = (rootDirectory) => {
36705
36699
  cachedPatternsByRoot.set(rootDirectory, patterns);
36706
36700
  return patterns;
36707
36701
  };
36702
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
36708
36703
  const KNIP_JSON_FILENAME = "knip.json";
36709
- const isRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
36710
36704
  const readJsonFileSafe = (filePath) => {
36711
36705
  let rawContents;
36712
36706
  try {
@@ -36722,10 +36716,10 @@ const readJsonFileSafe = (filePath) => {
36722
36716
  };
36723
36717
  const readKnipConfig = (rootDirectory) => {
36724
36718
  const knipJson = readJsonFileSafe(path.join(rootDirectory, KNIP_JSON_FILENAME));
36725
- if (isRecord$1(knipJson)) return knipJson;
36719
+ if (isRecord(knipJson)) return knipJson;
36726
36720
  const packageJson = readJsonFileSafe(path.join(rootDirectory, "package.json"));
36727
- const packageKnipConfig = isRecord$1(packageJson) ? packageJson.knip : null;
36728
- return isRecord$1(packageKnipConfig) ? packageKnipConfig : null;
36721
+ const packageKnipConfig = isRecord(packageJson) ? packageJson.knip : null;
36722
+ return isRecord(packageKnipConfig) ? packageKnipConfig : null;
36729
36723
  };
36730
36724
  const normalizePatternList = (value) => {
36731
36725
  if (typeof value === "string" && value.length > 0) return [value];
@@ -36737,10 +36731,10 @@ const prefixWorkspacePatterns = (workspacePattern, patterns) => {
36737
36731
  return patterns.map((pattern) => pattern.startsWith("!") ? `!${normalizedWorkspacePattern}/${pattern.slice(1)}` : `${normalizedWorkspacePattern}/${pattern}`);
36738
36732
  };
36739
36733
  const collectKnipWorkspacePatterns = (workspaces, settingName) => {
36740
- if (!isRecord$1(workspaces)) return [];
36734
+ if (!isRecord(workspaces)) return [];
36741
36735
  const patterns = [];
36742
36736
  for (const [workspacePattern, workspaceConfig] of Object.entries(workspaces)) {
36743
- if (!isRecord$1(workspaceConfig)) continue;
36737
+ if (!isRecord(workspaceConfig)) continue;
36744
36738
  patterns.push(...prefixWorkspacePatterns(workspacePattern, normalizePatternList(workspaceConfig[settingName])));
36745
36739
  }
36746
36740
  return patterns;
@@ -36785,8 +36779,6 @@ const toCanonicalPath = (filePath) => {
36785
36779
  };
36786
36780
  const DEAD_CODE_PLUGIN = "deslop";
36787
36781
  const DEAD_CODE_CATEGORY = "Maintainability";
36788
- const TSCONFIG_FILENAMES$1 = ["tsconfig.json", "tsconfig.base.json"];
36789
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
36790
36782
  const DEAD_CODE_WORKER_SCRIPT = `
36791
36783
  const inputChunks = [];
36792
36784
  process.stdin.on("data", (chunk) => inputChunks.push(chunk));
@@ -36844,7 +36836,7 @@ process.stdin.on("end", () => {
36844
36836
  });
36845
36837
  `;
36846
36838
  const resolveTsConfigPath = (rootDirectory) => {
36847
- for (const filename of TSCONFIG_FILENAMES$1) {
36839
+ for (const filename of TSCONFIG_FILENAMES) {
36848
36840
  const candidate = Path.join(rootDirectory, filename);
36849
36841
  if (NFS.existsSync(candidate)) return candidate;
36850
36842
  }
@@ -37225,15 +37217,13 @@ var DeadCode = class DeadCode extends Service()("react-doctor/DeadCode") {
37225
37217
  })()) }));
37226
37218
  static layerOf = (diagnostics) => succeed$3(DeadCode, DeadCode.of({ run: () => fromIterable$1(diagnostics) }));
37227
37219
  };
37228
- const createNodeReadFileLinesSync = (rootDirectory) => {
37229
- return (filePath) => {
37230
- const absolutePath = Path.isAbsolute(filePath) ? filePath : Path.join(rootDirectory, filePath);
37231
- try {
37232
- return NFS.readFileSync(absolutePath, "utf-8").split("\n");
37233
- } catch {
37234
- return null;
37235
- }
37236
- };
37220
+ const createNodeReadFileLinesSync = (rootDirectory) => (filePath) => {
37221
+ const absolutePath = Path.isAbsolute(filePath) ? filePath : Path.join(rootDirectory, filePath);
37222
+ try {
37223
+ return NFS.readFileSync(absolutePath, "utf-8").split("\n");
37224
+ } catch {
37225
+ return null;
37226
+ }
37237
37227
  };
37238
37228
  var Files = class Files extends Service()("react-doctor/Files") {
37239
37229
  static layerNode = succeed$3(Files, Files.of({
@@ -37444,7 +37434,10 @@ var Git = class Git extends Service()("react-doctor/Git") {
37444
37434
  directory: input.directory,
37445
37435
  cause
37446
37436
  }) });
37447
- }));
37437
+ }), withSpan("git.exec", { attributes: {
37438
+ "git.command": input.command,
37439
+ "git.subcommand": input.args[0] ?? ""
37440
+ } }));
37448
37441
  const runGit = (directory, args) => runCommand({
37449
37442
  command: "git",
37450
37443
  args,
@@ -37472,7 +37465,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
37472
37465
  ]);
37473
37466
  if (candidates.status !== 0) return null;
37474
37467
  return trimOrNull(candidates.stdout.split("\n")[0] ?? "");
37475
- });
37468
+ }).pipe(withSpan("Git.defaultBranch"));
37476
37469
  const branchExists = (directory, branch) => runGit(directory, [
37477
37470
  "rev-parse",
37478
37471
  "--verify",
@@ -37519,7 +37512,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
37519
37512
  const result = resultOption.value;
37520
37513
  if (result.status !== 0) return null;
37521
37514
  return parseGithubViewerPermission(result.stdout);
37522
- }).pipe(catch_$1(() => succeed$2(null)));
37515
+ }).pipe(catch_$1(() => succeed$2(null)), withSpan("Git.githubViewerPermission"));
37523
37516
  /**
37524
37517
  * Resolves a `--diff A..B` / `A...B` commit range into a changed-file
37525
37518
  * selection. Each endpoint is validated with `isSafeGitRevision`
@@ -37633,7 +37626,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
37633
37626
  changedFiles: splitNullSeparated(diff.stdout),
37634
37627
  isCurrentChanges: false
37635
37628
  };
37636
- }),
37629
+ }).pipe(withSpan("Git.diffSelection")),
37637
37630
  stagedFilePaths: (directory) => runGit(directory, [
37638
37631
  "diff",
37639
37632
  "--cached",
@@ -37675,7 +37668,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
37675
37668
  status: result.status,
37676
37669
  stdout: result.stdout
37677
37670
  };
37678
- }),
37671
+ }).pipe(withSpan("Git.grep")),
37679
37672
  changedLineRanges: ({ directory, baseRef, cached, files }) => gen(function* () {
37680
37673
  if (files.length === 0) return [];
37681
37674
  if (baseRef !== void 0 && !isSafeGitRevision(baseRef)) return null;
@@ -37691,7 +37684,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
37691
37684
  ]);
37692
37685
  if (result.status !== 0) return null;
37693
37686
  return parseChangedLineRanges(result.stdout);
37694
- })
37687
+ }).pipe(withSpan("Git.changedLineRanges"))
37695
37688
  });
37696
37689
  })).pipe(provide$2(layer$2.pipe(provide$2(mergeAll$1(layer$1, layer)))));
37697
37690
  /**
@@ -37906,7 +37899,7 @@ const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
37906
37899
  for (const [absolutePath, originalContent] of originalContents) try {
37907
37900
  NFS.writeFileSync(absolutePath, originalContent);
37908
37901
  } catch (error) {
37909
- process.stderr.write(`[react-doctor] Failed to restore inline disable directives in ${absolutePath}: ${error instanceof Error ? error.message : String(error)}\n[react-doctor] Run: git checkout -- ${absolutePath}\n`);
37902
+ process.stderr.write(`[react-doctor] Failed to restore inline disable directives in ${absolutePath}: ${messageFromUnknown(error)}\n[react-doctor] Run: git checkout -- ${absolutePath}\n`);
37910
37903
  }
37911
37904
  };
37912
37905
  const onExit = () => restore();
@@ -38012,7 +38005,7 @@ const resolveUserPlugin = (spec, configSourceDirectory) => {
38012
38005
  try {
38013
38006
  resolvedSpecifier = isRelative ? Path.resolve(configSourceDirectory, spec) : candidateRequire.resolve(spec);
38014
38007
  } catch (error) {
38015
- warnConfigIssue(`config.plugins entry "${spec}" could not be resolved from ${configSourceDirectory}: ${error instanceof Error ? error.message : String(error)}`);
38008
+ warnConfigIssue(`config.plugins entry "${spec}" could not be resolved from ${configSourceDirectory}: ${messageFromUnknown(error)}`);
38016
38009
  return null;
38017
38010
  }
38018
38011
  const { name, ruleNames } = readPluginShape(resolvedSpecifier, (target) => candidateRequire(target));
@@ -38084,8 +38077,8 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
38084
38077
  }
38085
38078
  return enabled;
38086
38079
  };
38087
- const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [] }) => {
38088
- const reactHooksJsPlugin = resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
38080
+ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false }) => {
38081
+ const reactHooksJsPlugin = disableReactHooksJsPlugin ? null : resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
38089
38082
  const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
38090
38083
  const jsPlugins = [];
38091
38084
  if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
@@ -38145,7 +38138,6 @@ const resolveOxlintBinary = () => {
38145
38138
  return Path.join(oxlintPackageDirectory, "bin", "oxlint");
38146
38139
  };
38147
38140
  const resolvePluginPath = () => esmRequire.resolve("oxlint-plugin-react-doctor");
38148
- const TSCONFIG_FILENAMES = ["tsconfig.json", "tsconfig.base.json"];
38149
38141
  const resolveTsConfigRelativePath = (rootDirectory) => {
38150
38142
  for (const filename of TSCONFIG_FILENAMES) if (NFS.existsSync(Path.join(rootDirectory, filename))) return `./${filename}`;
38151
38143
  return null;
@@ -38517,7 +38509,7 @@ const scopeContainsNonImportBinding = (node, scopeNode, identifierName) => {
38517
38509
  const isIdentifierShadowedByLocalBinding = (identifier, sourceFile) => {
38518
38510
  let currentNode = identifier.parent;
38519
38511
  while (currentNode) {
38520
- if (isScopeNode(currentNode)) {
38512
+ if (isScopeBoundary(currentNode)) {
38521
38513
  if (scopeContainsNonImportBinding(currentNode, currentNode, identifier.text)) return true;
38522
38514
  }
38523
38515
  if (currentNode === sourceFile) return false;
@@ -38608,11 +38600,10 @@ const findResolutionInScope = (scopeNode, identifierName, reactImportBindings, s
38608
38600
  });
38609
38601
  return resolution;
38610
38602
  };
38611
- const isScopeNode = isScopeBoundary;
38612
38603
  const resolveIdentifierBinding = (identifier, reactImportBindings, sourceFile, visitedDeclarations = /* @__PURE__ */ new Set()) => {
38613
38604
  let currentNode = identifier.parent;
38614
38605
  while (currentNode) {
38615
- if (isScopeNode(currentNode)) {
38606
+ if (isScopeBoundary(currentNode)) {
38616
38607
  const resolution = findResolutionInScope(currentNode, identifier.text, reactImportBindings, sourceFile, visitedDeclarations);
38617
38608
  if (resolution) return resolution;
38618
38609
  }
@@ -38782,9 +38773,9 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
38782
38773
  try {
38783
38774
  parsed = JSON.parse(sanitizedStdout);
38784
38775
  } catch {
38785
- throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 200) }) });
38776
+ throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
38786
38777
  }
38787
- if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 200) }) });
38778
+ if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
38788
38779
  const minifiedFileCache = /* @__PURE__ */ new Map();
38789
38780
  const isMinifiedDiagnosticFile = (filename) => {
38790
38781
  const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
@@ -38860,7 +38851,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLIN
38860
38851
  child.kill("SIGKILL");
38861
38852
  reject(new ReactDoctorError({ reason: new OxlintBatchExceeded({
38862
38853
  kind: "timeout",
38863
- detail: `${spawnTimeoutMs / 1e3}s budget exceeded`
38854
+ detail: `${spawnTimeoutMs / MILLISECONDS_PER_SECOND}s budget exceeded`
38864
38855
  }) }));
38865
38856
  }, spawnTimeoutMs);
38866
38857
  timeoutHandle.unref?.();
@@ -39075,6 +39066,28 @@ const writeOxlintConfig = (configPath, configToWrite) => {
39075
39066
  NFS.closeSync(fileHandle);
39076
39067
  }
39077
39068
  };
39069
+ const REACT_HOOKS_JS_DROP_PREFIX = "React Compiler rules (react-hooks-js/*) skipped — eslint-plugin-react-hooks failed to load in this environment";
39070
+ /**
39071
+ * Detects an oxlint config-load crash caused by the optional
39072
+ * `react-hooks-js` (eslint-plugin-react-hooks) React Compiler plugin and
39073
+ * builds the partial-failure note for it; returns `null` when the failure
39074
+ * was anything else.
39075
+ *
39076
+ * oxlint prints a framed error to stdout (not stderr) and exits non-zero
39077
+ * when a `jsPlugins` entry can't be imported; that non-JSON stdout
39078
+ * surfaces as `OxlintOutputUnparseable`. Because oxlint fails the WHOLE
39079
+ * config load on it, leaving the plugin in would drop every curated
39080
+ * react-doctor diagnostic too — so the caller retries with the plugin
39081
+ * stripped (issue #833). Both markers sit at the start of oxlint's
39082
+ * message, so they survive the `preview` slice even for deep pnpm paths.
39083
+ */
39084
+ const reactHooksJsPluginDropNote = (error) => {
39085
+ if (!(error instanceof ReactDoctorError) || error.reason._tag !== "OxlintOutputUnparseable") return null;
39086
+ const { preview } = error.reason;
39087
+ if (!preview.includes("Failed to load JS plugin") || !preview.includes("eslint-plugin-react-hooks")) return null;
39088
+ const underlyingReason = preview.match(/Error:[^\n]*/)?.[0]?.trim();
39089
+ return `${REACT_HOOKS_JS_DROP_PREFIX}${underlyingReason ? `: ${underlyingReason}` : ""}. Other rules ran normally.`;
39090
+ };
39078
39091
  /**
39079
39092
  * The oxlint runner. Composed of three pieces in `runners/oxlint/`:
39080
39093
  *
@@ -39102,15 +39115,16 @@ const runOxlint = async (options) => {
39102
39115
  const pluginPath = resolvePluginPath();
39103
39116
  const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
39104
39117
  const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
39105
- const buildConfig = (extendsForThisAttempt) => createOxlintConfig({
39118
+ const buildConfig = (overrides) => createOxlintConfig({
39106
39119
  pluginPath,
39107
39120
  project,
39108
39121
  customRulesOnly,
39109
- extendsPaths: extendsForThisAttempt,
39122
+ extendsPaths: overrides.extendsPaths,
39110
39123
  ignoredTags,
39111
39124
  serverAuthFunctionNames,
39112
39125
  severityControls,
39113
- userPlugins
39126
+ userPlugins,
39127
+ disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin
39114
39128
  });
39115
39129
  const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
39116
39130
  const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
@@ -39146,12 +39160,22 @@ const runOxlint = async (options) => {
39146
39160
  outputMaxBytes,
39147
39161
  concurrency: options.concurrency
39148
39162
  });
39149
- writeOxlintConfig(configPath, buildConfig(extendsPaths));
39163
+ writeOxlintConfig(configPath, buildConfig({ extendsPaths }));
39150
39164
  try {
39151
39165
  return await runBatches();
39152
39166
  } catch (error) {
39167
+ const reactHooksJsDropNote = reactHooksJsPluginDropNote(error);
39168
+ if (reactHooksJsDropNote !== null) {
39169
+ writeOxlintConfig(configPath, buildConfig({
39170
+ extendsPaths,
39171
+ disableReactHooksJsPlugin: true
39172
+ }));
39173
+ const diagnostics = await runBatches();
39174
+ onPartialFailure?.(reactHooksJsDropNote);
39175
+ return diagnostics;
39176
+ }
39153
39177
  if (extendsPaths.length === 0) throw error;
39154
- writeOxlintConfig(configPath, buildConfig([]));
39178
+ writeOxlintConfig(configPath, buildConfig({ extendsPaths: [] }));
39155
39179
  return await runBatches();
39156
39180
  }
39157
39181
  } finally {
@@ -39949,7 +39973,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
39949
39973
  }))))))));
39950
39974
  const deadCodeFailureState = yield* get$2(deadCodeFailure);
39951
39975
  const scanElapsedMilliseconds = Date.now() - scanStartTime;
39952
- const scanElapsedSeconds = (scanElapsedMilliseconds / 1e3).toFixed(1);
39976
+ const scanElapsedSeconds = (scanElapsedMilliseconds / MILLISECONDS_PER_SECOND).toFixed(1);
39953
39977
  if (!lintFailureState.didFail) if (deadCodeFailureState.didFail) yield* scanProgress.fail(DEAD_CODE_FAIL_TEXT);
39954
39978
  else if (input.suppressScanSummary) yield* scanProgress.stop();
39955
39979
  else yield* scanProgress.succeed(`Scanned ${scannedFilesLabel} in ${scanElapsedSeconds}s${workerCountSuffix}`);
@@ -40163,7 +40187,7 @@ const materializeSourceTree = (input) => gen(function* () {
40163
40187
  static layerNode = effect(StagedFiles, gen(function* () {
40164
40188
  const git = yield* Git;
40165
40189
  return StagedFiles.of({
40166
- discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries.filter(isLintableSourceFile))),
40190
+ discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries.filter(isLintableSourceFile)), withSpan("StagedFiles.discoverSourceFiles")),
40167
40191
  materialize: ({ directory, stagedFiles, tempDirectory }) => materializeSourceTree({
40168
40192
  directory,
40169
40193
  files: stagedFiles,
@@ -40173,7 +40197,7 @@ const materializeSourceTree = (input) => gen(function* () {
40173
40197
  tempDirectory: tree.tempDirectory,
40174
40198
  stagedFiles: tree.materializedFiles,
40175
40199
  cleanup: tree.cleanup
40176
- })))
40200
+ })), withSpan("StagedFiles.materialize"))
40177
40201
  });
40178
40202
  }));
40179
40203
  /**
@@ -40571,4 +40595,4 @@ const toJsonReport = (result, options) => buildJsonReport({
40571
40595
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
40572
40596
 
40573
40597
  //# sourceMappingURL=index.js.map
40574
- //# debugId=a4394ddc-4e6c-5a18-aeeb-d60322b1c0dd
40598
+ //# debugId=ff319d21-ecce-5f79-a822-8cb00c30fea1