react-doctor 0.8.1-dev.c9f2c4b → 0.8.1-dev.cd9ca68

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/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]="f645a3f8-ff1c-5f09-a174-8281db00eaa4")}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]="44c11483-7e3b-5388-9124-551e272d5e2d")}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";
@@ -33375,10 +33375,10 @@ const FALLBACK_TSCONFIG_FILENAMES = ["tsconfig.app.json", "tsconfig.build.json"]
33375
33375
  const FRAMEWORK_PACKAGES = {
33376
33376
  next: "nextjs",
33377
33377
  "@tanstack/react-start": "tanstack-start",
33378
- vite: "vite",
33379
- "react-scripts": "cra",
33380
33378
  "@remix-run/react": "remix",
33381
33379
  gatsby: "gatsby",
33380
+ vite: "vite",
33381
+ "react-scripts": "cra",
33382
33382
  expo: "expo",
33383
33383
  "react-native": "react-native"
33384
33384
  };
@@ -33905,19 +33905,6 @@ const getPreactVersion = (packageJson) => {
33905
33905
  ...packageJson.devDependencies
33906
33906
  }.preact ?? null;
33907
33907
  };
33908
- const TANSTACK_QUERY_PACKAGES = new Set([
33909
- "@tanstack/react-query",
33910
- "@tanstack/query-core",
33911
- "react-query"
33912
- ]);
33913
- const hasTanStackQuery = (packageJson) => {
33914
- const allDependencies = {
33915
- ...packageJson.peerDependencies,
33916
- ...packageJson.dependencies,
33917
- ...packageJson.devDependencies
33918
- };
33919
- return Object.keys(allDependencies).some((packageName) => TANSTACK_QUERY_PACKAGES.has(packageName));
33920
- };
33921
33908
  const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, version }) => {
33922
33909
  if (version === null || !isCatalogReference(version)) return version;
33923
33910
  const catalogName = extractCatalogName(version);
@@ -34120,7 +34107,60 @@ const listWorkspacePackages = (rootDirectory) => {
34120
34107
  }
34121
34108
  return packages;
34122
34109
  };
34110
+ const getPreferredDependencyVersion = ({ packageJson, packageNames }) => {
34111
+ const allDependencies = {
34112
+ ...packageJson.devDependencies,
34113
+ ...packageJson.peerDependencies,
34114
+ ...packageJson.dependencies
34115
+ };
34116
+ for (const packageName of packageNames) {
34117
+ const version = allDependencies[packageName];
34118
+ if (version !== void 0) return version;
34119
+ }
34120
+ return null;
34121
+ };
34122
+ const TANSTACK_REACT_QUERY_PACKAGES = ["@tanstack/react-query", "react-query"];
34123
+ const getTanStackQueryVersion = (packageJson) => {
34124
+ return getPreferredDependencyVersion({
34125
+ packageJson,
34126
+ packageNames: TANSTACK_REACT_QUERY_PACKAGES
34127
+ });
34128
+ };
34129
+ const STYLED_COMPONENTS_PACKAGES = ["styled-components"];
34130
+ const getStyledComponentsVersion = (packageJson) => {
34131
+ return getPreferredDependencyVersion({
34132
+ packageJson,
34133
+ packageNames: STYLED_COMPONENTS_PACKAGES
34134
+ });
34135
+ };
34136
+ const I18N_PACKAGES = [
34137
+ "i18next",
34138
+ "react-i18next",
34139
+ "next-i18next",
34140
+ "react-intl",
34141
+ "next-intl",
34142
+ "use-intl",
34143
+ "@formatjs/intl",
34144
+ "@lingui/core",
34145
+ "@lingui/react",
34146
+ "typesafe-i18n",
34147
+ "@tolgee/react",
34148
+ "react-intl-universal"
34149
+ ];
34150
+ const hasI18nDependency = (packageJson) => {
34151
+ const allDependencies = {
34152
+ ...packageJson.peerDependencies,
34153
+ ...packageJson.dependencies,
34154
+ ...packageJson.devDependencies,
34155
+ ...packageJson.optionalDependencies
34156
+ };
34157
+ return I18N_PACKAGES.some((packageName) => allDependencies[packageName] !== void 0);
34158
+ };
34123
34159
  const REANIMATED_DEPENDENCY_NAME = "react-native-reanimated";
34160
+ const MOBX_REACT_PACKAGE_NAME = "mobx-react";
34161
+ const MOBX_REACT_LITE_PACKAGE_NAME = "mobx-react-lite";
34162
+ const MOBX_STATE_TREE_PACKAGE_NAME = "mobx-state-tree";
34163
+ const MOBX_REACT_OBSERVER_PACKAGE_NAME = "mobx-react-observer";
34124
34164
  const SHOPIFY_FLASH_LIST_PACKAGE_NAME = "@shopify/flash-list";
34125
34165
  const resolveWorkspaceDependencyVersion = ({ concreteVersion, packageName, rootDirectory, rootPackageJson, sections, workspaceDirectory, workspacePackageJson }) => {
34126
34166
  const dependencyDeclaration = getDependencyDeclaration({
@@ -34139,7 +34179,26 @@ const shouldReplaceReactVersion = (currentVersion, nextVersion) => {
34139
34179
  if (nextMajor === null) return false;
34140
34180
  return nextMajor < currentMajor;
34141
34181
  };
34142
- const evaluateManifestFacts = (facts, packageJson, directory) => {
34182
+ const shouldReplaceSupportedDependencyFact = (currentFact, nextFact, latestSupportedMajor) => {
34183
+ if (currentFact.version === null) return true;
34184
+ if (nextFact.version === null) return false;
34185
+ const currentMajor = getLowestDependencyMajor(currentFact.version);
34186
+ const nextMajor = getLowestDependencyMajor(nextFact.version);
34187
+ if (currentMajor === null) return false;
34188
+ if (nextMajor === null) return true;
34189
+ if (currentMajor > latestSupportedMajor) return false;
34190
+ if (nextMajor > latestSupportedMajor) return true;
34191
+ return nextMajor < currentMajor;
34192
+ };
34193
+ const shouldReplaceStyledComponentsVersion = (currentVersion, nextVersion) => {
34194
+ if (!currentVersion) return true;
34195
+ const currentMajor = getLowestDependencyMajor(currentVersion);
34196
+ const nextMajor = getLowestDependencyMajor(nextVersion);
34197
+ if (currentMajor === null) return nextMajor !== null && nextMajor < 6;
34198
+ if (nextMajor === null) return currentMajor >= 6;
34199
+ return nextMajor < currentMajor;
34200
+ };
34201
+ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, rootPackageJson) => {
34143
34202
  if (facts.expo.version === null) {
34144
34203
  const spec = getDependencySpec(packageJson, "expo");
34145
34204
  if (spec !== null) facts.expo = {
@@ -34161,13 +34220,74 @@ const evaluateManifestFacts = (facts, packageJson, directory) => {
34161
34220
  sourceDirectory: directory
34162
34221
  };
34163
34222
  }
34223
+ const mobxSpec = getDependencySpec(packageJson, "mobx");
34224
+ if (mobxSpec !== null) {
34225
+ const nextMobxFact = {
34226
+ version: resolveCatalogBackedDependencyVersion({
34227
+ rootDirectory: directory,
34228
+ rootPackageJson: packageJson,
34229
+ packageName: "mobx",
34230
+ version: mobxSpec
34231
+ }),
34232
+ sourceDirectory: directory
34233
+ };
34234
+ if (shouldReplaceSupportedDependencyFact(facts.mobx, nextMobxFact, 6)) facts.mobx = nextMobxFact;
34235
+ }
34236
+ facts.hasMobxReact = facts.hasMobxReact || getDependencySpec(packageJson, MOBX_REACT_PACKAGE_NAME) !== null;
34237
+ facts.hasMobxReactLite = facts.hasMobxReactLite || getDependencySpec(packageJson, MOBX_REACT_LITE_PACKAGE_NAME) !== null;
34238
+ facts.hasMobxStateTree = facts.hasMobxStateTree || getDependencySpec(packageJson, MOBX_STATE_TREE_PACKAGE_NAME) !== null;
34239
+ facts.hasMobxReactObserver = facts.hasMobxReactObserver || getDependencySpec(packageJson, MOBX_REACT_OBSERVER_PACKAGE_NAME) !== null;
34240
+ const zustandSpec = getDependencySpec(packageJson, "zustand");
34241
+ if (zustandSpec !== null) {
34242
+ const nextZustandFact = {
34243
+ version: resolveCatalogBackedDependencyVersion({
34244
+ rootDirectory: directory,
34245
+ rootPackageJson: packageJson,
34246
+ packageName: "zustand",
34247
+ version: zustandSpec
34248
+ }),
34249
+ sourceDirectory: directory
34250
+ };
34251
+ if (shouldReplaceSupportedDependencyFact(facts.zustand, nextZustandFact, 5)) facts.zustand = nextZustandFact;
34252
+ }
34164
34253
  if (facts.reanimatedVersion === null) {
34165
34254
  const spec = getDependencySpec(packageJson, REANIMATED_DEPENDENCY_NAME);
34166
34255
  if (spec !== null) facts.reanimatedVersion = spec;
34167
34256
  }
34257
+ if (facts.valtioVersion === null) {
34258
+ const spec = getDependencySpec(packageJson, "valtio");
34259
+ if (spec !== null) facts.valtioVersion = spec;
34260
+ }
34261
+ facts.tanstackQueryVersion ??= getTanStackQueryVersion(packageJson);
34262
+ const styledComponentsVersion = resolveCatalogBackedDependencyVersion({
34263
+ rootDirectory: directory,
34264
+ rootPackageJson: packageJson,
34265
+ packageName: "styled-components",
34266
+ version: getStyledComponentsVersion(packageJson)
34267
+ });
34268
+ if (styledComponentsVersion && shouldReplaceStyledComponentsVersion(facts.styledComponentsVersion, styledComponentsVersion)) facts.styledComponentsVersion = styledComponentsVersion;
34269
+ facts.hasI18nLibrary = facts.hasI18nLibrary || hasI18nDependency(packageJson);
34168
34270
  facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
34169
34271
  facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
34170
34272
  facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
34273
+ const remotionSpec = getDependencySpec(packageJson, "remotion");
34274
+ if (remotionSpec !== null) {
34275
+ facts.hasRemotionDependency = true;
34276
+ const resolvedRemotionVersion = resolveCatalogBackedDependencyVersion({
34277
+ rootDirectory,
34278
+ rootPackageJson,
34279
+ packageName: "remotion",
34280
+ version: remotionSpec
34281
+ });
34282
+ const remotionMajorVersion = resolvedRemotionVersion === null ? null : getLowestDependencyMajor(resolvedRemotionVersion);
34283
+ if (remotionMajorVersion === null) {
34284
+ facts.hasUnknownRemotionVersion = true;
34285
+ facts.remotionVersion = null;
34286
+ } else if (!facts.hasUnknownRemotionVersion) {
34287
+ const currentRemotionMajorVersion = facts.remotionVersion === null ? null : getLowestDependencyMajor(facts.remotionVersion);
34288
+ if (currentRemotionMajorVersion === null || remotionMajorVersion < currentRemotionMajorVersion) facts.remotionVersion = resolvedRemotionVersion;
34289
+ }
34290
+ }
34171
34291
  };
34172
34292
  const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGroup }) => {
34173
34293
  const facts = {
@@ -34187,12 +34307,31 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34187
34307
  version: null,
34188
34308
  sourceDirectory: null
34189
34309
  },
34310
+ valtioVersion: null,
34311
+ mobx: {
34312
+ version: null,
34313
+ sourceDirectory: null
34314
+ },
34315
+ hasMobxReact: false,
34316
+ hasMobxReactLite: false,
34317
+ hasMobxStateTree: false,
34318
+ hasMobxReactObserver: false,
34319
+ zustand: {
34320
+ version: null,
34321
+ sourceDirectory: null
34322
+ },
34323
+ tanstackQueryVersion: null,
34324
+ styledComponentsVersion: null,
34325
+ hasI18nLibrary: false,
34190
34326
  hasReactNativeAwarePackage: false,
34191
34327
  hasReanimatedAwarePackage: false,
34192
34328
  hasSsrDependency: false,
34329
+ hasRemotionDependency: false,
34330
+ hasUnknownRemotionVersion: false,
34331
+ remotionVersion: null,
34193
34332
  reanimatedVersion: null
34194
34333
  };
34195
- evaluateManifestFacts(facts, rootPackageJson, rootDirectory);
34334
+ evaluateManifestFacts(facts, rootPackageJson, rootDirectory, rootDirectory, rootPackageJson);
34196
34335
  let isReactGroupSettled = !collectReactGroup;
34197
34336
  const visitedDirectories = /* @__PURE__ */ new Set();
34198
34337
  for (const pattern of getWorkspacePatterns(rootDirectory, rootPackageJson)) {
@@ -34201,7 +34340,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34201
34340
  if (visitedDirectories.has(workspaceDirectory)) continue;
34202
34341
  visitedDirectories.add(workspaceDirectory);
34203
34342
  const workspacePackageJson = readPackageJson(Path.join(workspaceDirectory, "package.json"));
34204
- evaluateManifestFacts(facts, workspacePackageJson, workspaceDirectory);
34343
+ evaluateManifestFacts(facts, workspacePackageJson, workspaceDirectory, rootDirectory, rootPackageJson);
34205
34344
  const info = extractDependencyInfo(workspacePackageJson);
34206
34345
  if (info.framework !== "unknown" && frameworkMergeRank(info.framework) < frameworkMergeRank(facts.framework)) facts.framework = info.framework;
34207
34346
  if (isReactGroupSettled) continue;
@@ -34425,11 +34564,27 @@ const discoverProjectWithoutPackageJson = (directory) => {
34425
34564
  tailwindVersion: null,
34426
34565
  zodVersion: null,
34427
34566
  zodMajorVersion: null,
34567
+ mobxVersion: null,
34568
+ mobxMajorVersion: null,
34569
+ hasMobxReact: false,
34570
+ hasMobxReactLite: false,
34571
+ hasMobxStateTree: false,
34572
+ hasMobxReactObserver: false,
34573
+ zustandVersion: null,
34574
+ zustandMajorVersion: null,
34428
34575
  framework: "unknown",
34429
34576
  hasTypeScript: hasOwnTsConfig,
34430
34577
  hasReactCompiler: false,
34431
34578
  hasReactCompilerLintPlugin: false,
34432
34579
  hasTanStackQuery: false,
34580
+ valtioVersion: null,
34581
+ valtioMajorVersion: null,
34582
+ hasRemotion: false,
34583
+ remotionVersion: null,
34584
+ remotionMajorVersion: null,
34585
+ hasI18nLibrary: false,
34586
+ tanstackQueryVersion: null,
34587
+ styledComponentsVersion: null,
34433
34588
  hasSsrDependency: false,
34434
34589
  preactVersion: null,
34435
34590
  preactMajorVersion: null,
@@ -34528,6 +34683,12 @@ const discoverProject = (directory) => {
34528
34683
  packageName: SHOPIFY_FLASH_LIST_PACKAGE_NAME,
34529
34684
  version: workspaceFacts.shopifyFlashList.version
34530
34685
  }) : null;
34686
+ const zustandVersion = resolveCatalogBackedDependencyVersion({
34687
+ rootDirectory: directory,
34688
+ rootPackageJson: packageJson,
34689
+ packageName: "zustand",
34690
+ version: workspaceFacts.zustand.version
34691
+ });
34531
34692
  const hasReanimated = hasReactNativeWorkspace && workspaceFacts.hasReanimatedAwarePackage;
34532
34693
  const reanimatedVersion = hasReanimated ? workspaceFacts.reanimatedVersion : null;
34533
34694
  const nextjsVersion = framework === "nextjs" ? resolveCatalogBackedDependencyVersion({
@@ -34536,7 +34697,21 @@ const discoverProject = (directory) => {
34536
34697
  packageName: "next",
34537
34698
  version: workspaceFacts.next.version
34538
34699
  }) : null;
34700
+ const valtioVersion = resolveCatalogBackedDependencyVersion({
34701
+ rootDirectory: directory,
34702
+ rootPackageJson: packageJson,
34703
+ packageName: "valtio",
34704
+ version: workspaceFacts.valtioVersion
34705
+ });
34706
+ const mobxVersion = resolveCatalogBackedDependencyVersion({
34707
+ rootDirectory: directory,
34708
+ rootPackageJson: packageJson,
34709
+ packageName: "mobx",
34710
+ version: workspaceFacts.mobx.version
34711
+ });
34539
34712
  const preactVersion = getPreactVersion(packageJson);
34713
+ const remotionVersion = workspaceFacts.remotionVersion;
34714
+ const tanstackQueryVersion = getTanStackQueryVersion(packageJson) ?? workspaceFacts.tanstackQueryVersion;
34540
34715
  const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
34541
34716
  const projectInfo = {
34542
34717
  rootDirectory: directory,
@@ -34546,11 +34721,27 @@ const discoverProject = (directory) => {
34546
34721
  tailwindVersion,
34547
34722
  zodVersion,
34548
34723
  zodMajorVersion: zodVersion === null ? null : getLowestDependencyMajor(zodVersion),
34724
+ mobxVersion,
34725
+ mobxMajorVersion: mobxVersion === null ? null : getLowestDependencyMajor(mobxVersion),
34726
+ hasMobxReact: workspaceFacts.hasMobxReact,
34727
+ hasMobxReactLite: workspaceFacts.hasMobxReactLite,
34728
+ hasMobxStateTree: workspaceFacts.hasMobxStateTree,
34729
+ hasMobxReactObserver: workspaceFacts.hasMobxReactObserver,
34730
+ zustandVersion,
34731
+ zustandMajorVersion: zustandVersion === null ? null : getLowestDependencyMajor(zustandVersion),
34549
34732
  framework,
34550
34733
  hasTypeScript,
34551
34734
  hasReactCompiler: detectReactCompiler(directory, packageJson),
34552
34735
  hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
34553
- hasTanStackQuery: hasTanStackQuery(packageJson),
34736
+ hasTanStackQuery: tanstackQueryVersion !== null,
34737
+ hasI18nLibrary: workspaceFacts.hasI18nLibrary,
34738
+ tanstackQueryVersion,
34739
+ styledComponentsVersion: workspaceFacts.styledComponentsVersion,
34740
+ valtioVersion,
34741
+ valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
34742
+ hasRemotion: workspaceFacts.hasRemotionDependency,
34743
+ remotionVersion,
34744
+ remotionMajorVersion: remotionVersion === null ? null : getLowestDependencyMajor(remotionVersion),
34554
34745
  hasSsrDependency: workspaceFacts.hasSsrDependency,
34555
34746
  preactVersion,
34556
34747
  preactMajorVersion: parseReactMajor(preactVersion),
@@ -34784,7 +34975,6 @@ const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
34784
34975
  "react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
34785
34976
  "react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
34786
34977
  "react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
34787
- "react/jsx-no-target-blank": "react-doctor/jsx-no-target-blank",
34788
34978
  "react/jsx-no-undef": "react-doctor/jsx-no-undef",
34789
34979
  "react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
34790
34980
  "react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
@@ -37071,9 +37261,25 @@ const BABEL_CONFIG_FILE_NAMES = [
37071
37261
  ".babelrc.json"
37072
37262
  ];
37073
37263
  const LEGACY_PRESET_SPEC = "module:metro-react-native-babel-preset";
37264
+ const LEGACY_PRESET_PACKAGE = "metro-react-native-babel-preset";
37265
+ const REACT_NATIVE_PACKAGE = "react-native";
37266
+ const PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION = "0.73.0";
37267
+ const LEGACY_PRESET_REFERENCE = new RegExp(`['"]${LEGACY_PRESET_SPEC}['"]`);
37074
37268
  const MODERN_PRESET_REFERENCE = new RegExp(`['"]module:@react-native/babel-preset['"]`);
37075
37269
  const ENABLE_BABEL_RUNTIME_VERSION = /enableBabelRuntime["']?\s*:\s*['"]/;
37270
+ const isReactNativeVersionAtLeastPresetRename = (rootDirectory, packageJson) => {
37271
+ const installedReactNativeManifestPath = Path.join(rootDirectory, "node_modules", REACT_NATIVE_PACKAGE, "package.json");
37272
+ const reactNativeVersionSpec = (isFile(installedReactNativeManifestPath) ? readPackageJson(installedReactNativeManifestPath).version : void 0) ?? getDependencySpec(packageJson, REACT_NATIVE_PACKAGE);
37273
+ if (reactNativeVersionSpec === null || reactNativeVersionSpec === void 0) return false;
37274
+ const normalizedVersionRange = import_semver.validRange(reactNativeVersionSpec);
37275
+ if (normalizedVersionRange === null) return false;
37276
+ const minimumVersion = import_semver.minVersion(normalizedVersionRange);
37277
+ return minimumVersion !== null && import_semver.gte(minimumVersion, PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION);
37278
+ };
37279
+ const canResolveLegacyPreset = (rootDirectory, packageJson) => getDependencySpec(packageJson, LEGACY_PRESET_PACKAGE) !== null || isFile(Path.join(rootDirectory, "node_modules", LEGACY_PRESET_PACKAGE, "package.json"));
37076
37280
  const checkReactNativeMetroBabelPreset = (rootDirectory) => {
37281
+ const packageJson = readPackageJson(Path.join(rootDirectory, "package.json"));
37282
+ const shouldReportLegacyPreset = isReactNativeVersionAtLeastPresetRename(rootDirectory, packageJson) && !canResolveLegacyPreset(rootDirectory, packageJson);
37077
37283
  for (const fileName of BABEL_CONFIG_FILE_NAMES) {
37078
37284
  const filePath = Path.join(rootDirectory, fileName);
37079
37285
  if (!isFile(filePath)) continue;
@@ -37083,7 +37289,7 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
37083
37289
  } catch {
37084
37290
  continue;
37085
37291
  }
37086
- if (contents.includes(LEGACY_PRESET_SPEC)) return [buildReactNativeDiagnostic({
37292
+ if (shouldReportLegacyPreset && LEGACY_PRESET_REFERENCE.test(contents)) return [buildReactNativeDiagnostic({
37087
37293
  filePath: fileName,
37088
37294
  rule: "rn-no-metro-babel-preset",
37089
37295
  severity: "error",
@@ -37106,12 +37312,6 @@ const checkReactNativeProject = (rootDirectory, project) => {
37106
37312
  return [...checkReactNativeMetroBabelPreset(rootDirectory), ...checkReactNativeLibraryDependencies(rootDirectory)];
37107
37313
  };
37108
37314
  const RULE_KEY = "no-vulnerable-react-server-components";
37109
- const DEPENDENCY_SECTIONS = [
37110
- "dependencies",
37111
- "devDependencies",
37112
- "peerDependencies",
37113
- "optionalDependencies"
37114
- ];
37115
37315
  const REACT_RSC_ADVISORIES_BY_MINOR = {
37116
37316
  "19.0": {
37117
37317
  rceFixedVersion: "19.0.1",
@@ -37158,20 +37358,13 @@ const enumerateWorkspaceDirectories = (workspaceRoot) => {
37158
37358
  for (const pattern of patterns) for (const directory of resolveWorkspaceDirectories(workspaceRoot, pattern)) directories.add(directory);
37159
37359
  return [...directories];
37160
37360
  };
37161
- const readDeclaredSpec = (packageJson, packageName) => {
37162
- for (const section of DEPENDENCY_SECTIONS) {
37163
- const spec = packageJson[section]?.[packageName];
37164
- if (typeof spec === "string") return spec;
37165
- }
37166
- return null;
37167
- };
37168
37361
  const resolveVersionInDirectory = (directory, packageName, declaredSpecOverride) => {
37169
37362
  const manifestPath = Path.join(directory, "node_modules", packageName, "package.json");
37170
37363
  if (isFile(manifestPath)) {
37171
37364
  const installedVersion = import_semver.valid(readPackageJson(manifestPath).version ?? null);
37172
37365
  if (installedVersion !== null) return installedVersion;
37173
37366
  }
37174
- const candidateSpecs = [readDeclaredSpec(readPackageJson(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
37367
+ const candidateSpecs = [getDependencySpec(readPackageJson(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
37175
37368
  for (const spec of candidateSpecs) {
37176
37369
  const pinnedVersion = spec === null ? null : import_semver.valid(spec);
37177
37370
  if (pinnedVersion !== null) return pinnedVersion;
@@ -37839,6 +38032,7 @@ const buildCapabilities = (project) => {
37839
38032
  if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
37840
38033
  if (project.isStaticExport) capabilities.add("nextjs:static-export");
37841
38034
  if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
38035
+ if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 16) capabilities.add("nextjs:16");
37842
38036
  addMajorLadder(capabilities, "react", project.reactMajorVersion, 17, 30);
37843
38037
  if (project.reactMajorVersion !== null && project.reactMajorVersion >= 19 && isMajorMinorAtLeast(parseReactMajorMinor(project.reactVersion), {
37844
38038
  major: 19,
@@ -37851,9 +38045,30 @@ const buildCapabilities = (project) => {
37851
38045
  })) capabilities.add("tailwind:3.4");
37852
38046
  if (project.zodVersion !== null) capabilities.add("zod");
37853
38047
  if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
38048
+ if (project.mobxVersion !== void 0 && project.mobxVersion !== null || project.hasMobxReact === true || project.hasMobxReactLite === true || project.hasMobxStateTree === true || project.hasMobxReactObserver === true) capabilities.add("mobx");
38049
+ if (project.hasMobxReact === true) capabilities.add("mobx-react");
38050
+ if (project.hasMobxReactLite === true) capabilities.add("mobx-react-lite");
38051
+ if (project.hasMobxReact === true || project.hasMobxReactLite === true) capabilities.add("mobx-react-binding");
38052
+ if (project.hasMobxStateTree === true) capabilities.add("mobx-state-tree");
38053
+ if (project.hasMobxReactObserver === true) capabilities.add("mobx-react-observer");
38054
+ if (project.mobxMajorVersion !== void 0 && project.mobxMajorVersion !== null && project.mobxMajorVersion >= 4 && project.mobxMajorVersion <= 6) addMajorLadder(capabilities, "mobx", project.mobxMajorVersion, 4, 6);
38055
+ if (project.zustandVersion !== void 0 && project.zustandVersion !== null) capabilities.add("zustand");
38056
+ if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addMajorLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
37854
38057
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
37855
38058
  if (project.hasReactCompiler) capabilities.add("react-compiler");
37856
- if (project.hasTanStackQuery) capabilities.add("tanstack-query");
38059
+ if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
38060
+ if (project.styledComponentsVersion) {
38061
+ capabilities.add("styled-components");
38062
+ const styledComponentsMajor = getLowestDependencyMajor(project.styledComponentsVersion);
38063
+ if (styledComponentsMajor !== null && styledComponentsMajor >= 6) capabilities.add("styled-components:6");
38064
+ }
38065
+ if (project.hasI18nLibrary) capabilities.add("i18n");
38066
+ if (project.valtioVersion !== null) capabilities.add("valtio");
38067
+ addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
38068
+ if (project.hasRemotion) {
38069
+ capabilities.add("remotion");
38070
+ addMajorLadder(capabilities, "remotion", project.remotionMajorVersion ?? null, 4, 30);
38071
+ }
37857
38072
  if (project.hasTypeScript) capabilities.add("typescript");
37858
38073
  if (project.preactVersion !== null) capabilities.add("preact");
37859
38074
  addMajorLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
@@ -40122,6 +40337,19 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
40122
40337
  }
40123
40338
  };
40124
40339
  };
40340
+ const fingerprintCacheByFilePath = /* @__PURE__ */ new Map();
40341
+ const fingerprintFileContents = (filePath, fingerprintLength) => {
40342
+ const fileStats = NFS.statSync(filePath, { bigint: true });
40343
+ const cachedFingerprint = fingerprintCacheByFilePath.get(filePath);
40344
+ if (cachedFingerprint?.modifiedTimeNanoseconds === fileStats.mtimeNs && cachedFingerprint.sizeBytes === fileStats.size) return cachedFingerprint.fingerprint;
40345
+ const fingerprint = crypto.createHash("sha256").update(NFS.readFileSync(filePath)).digest("hex").slice(0, fingerprintLength);
40346
+ fingerprintCacheByFilePath.set(filePath, {
40347
+ fingerprint,
40348
+ modifiedTimeNanoseconds: fileStats.mtimeNs,
40349
+ sizeBytes: fileStats.size
40350
+ });
40351
+ return fingerprint;
40352
+ };
40125
40353
  const bundledRequire = createRequire(import.meta.url);
40126
40354
  const childNodeVersionByBinaryPath = /* @__PURE__ */ new Map();
40127
40355
  const resolveChildNodeVersion = (nodeBinaryPath) => {
@@ -40145,6 +40373,13 @@ const TOOLCHAIN_PACKAGE_SPECIFIERS = [
40145
40373
  "oxlint-plugin-react-doctor/package.json",
40146
40374
  "eslint-plugin-react-hooks/package.json"
40147
40375
  ];
40376
+ const resolvePluginFingerprint = () => {
40377
+ try {
40378
+ return fingerprintFileContents(bundledRequire.resolve("oxlint-plugin-react-doctor"), 16);
40379
+ } catch {
40380
+ return "unresolved";
40381
+ }
40382
+ };
40148
40383
  const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
40149
40384
  const versions = [`node=${resolveChildNodeVersion(nodeBinaryPath)}`];
40150
40385
  for (const specifier of TOOLCHAIN_PACKAGE_SPECIFIERS) try {
@@ -40154,6 +40389,7 @@ const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
40154
40389
  } catch {
40155
40390
  versions.push(`${specifier}=missing`);
40156
40391
  }
40392
+ versions.push(`oxlint-plugin-react-doctor#fingerprint=${resolvePluginFingerprint()}`);
40157
40393
  return versions;
40158
40394
  };
40159
40395
  const esmRequire = createRequire(import.meta.url);
@@ -40847,12 +41083,17 @@ const REACT_ERROR_BOUNDARY_MESSAGE = "This try/catch cannot catch errors thrown
40847
41083
  const REACT_COMPILER_IMPACT = "This component misses React Compiler's automatic memoization & re-renders more than it should";
40848
41084
  const REACT_COMPILER_ACTION = "Rewrite the flagged code so the compiler can optimize it.";
40849
41085
  const REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION = "It's how the library works, not a bug in your code. Memoize values you pass from it into other memoized components, or suppress it with `// react-doctor-disable-next-line react-hooks-js/incompatible-library`.";
41086
+ const SET_STATE_IN_EFFECT_ACTION = "Prefer deriving or initializing the value before render. If the effect must read a browser API after mount, treat this as advisory or suppress it with `// react-doctor-disable-next-line react-hooks-js/set-state-in-effect`.";
40850
41087
  const REACT_COMPILER_GENERIC_MESSAGE = `${REACT_COMPILER_IMPACT}. ${REACT_COMPILER_ACTION}`;
40851
41088
  const buildReactCompilerMessage = (reasonSummary, action = REACT_COMPILER_ACTION) => {
40852
41089
  const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
40853
41090
  if (!normalizedSummary) return `${REACT_COMPILER_IMPACT}. ${action}`;
40854
41091
  return `${REACT_COMPILER_IMPACT}: ${normalizedSummary}. ${action}`;
40855
41092
  };
41093
+ const buildSetStateInEffectMessage = (reasonSummary) => {
41094
+ const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
41095
+ return `This synchronous effect update causes an extra render${normalizedSummary ? `: ${normalizedSummary}` : ""}. ${SET_STATE_IN_EFFECT_ACTION}`;
41096
+ };
40856
41097
  const PLUGIN_CATEGORY_MAP = {
40857
41098
  react: "Bugs",
40858
41099
  "react-hooks": "Bugs",
@@ -40910,6 +41151,10 @@ const resolveCleanedDiagnostic = (message, help, plugin, rule, project) => {
40910
41151
  message: REACT_ERROR_BOUNDARY_MESSAGE,
40911
41152
  help: reasonDetail || help
40912
41153
  };
41154
+ if (rule === "set-state-in-effect") return {
41155
+ message: buildSetStateInEffectMessage(reasonSummary.trim()),
41156
+ help: reasonDetail || help
41157
+ };
40913
41158
  return {
40914
41159
  message: buildReactCompilerMessage(reasonSummary.trim(), rule === "incompatible-library" ? REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION : REACT_COMPILER_ACTION),
40915
41160
  help: appendReanimatedSharedValueHint(reasonDetail || help, rule, project)
@@ -43828,4 +44073,4 @@ const toJsonReport = (result, options) => buildJsonReport({
43828
44073
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
43829
44074
 
43830
44075
  //# sourceMappingURL=index.js.map
43831
- //# debugId=f645a3f8-ff1c-5f09-a174-8281db00eaa4
44076
+ //# debugId=44c11483-7e3b-5388-9124-551e272d5e2d