react-doctor 0.8.0-dev.eb2d687 → 0.8.1-dev.0b0b5ac

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/lsp.js CHANGED
@@ -33092,7 +33092,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
33092
33092
  const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
33093
33093
  const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
33094
33094
  const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
33095
- const CORE_PACKAGE_VERSION = "0.8.0";
33095
+ const CORE_PACKAGE_VERSION = "0.8.1";
33096
33096
  const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
33097
33097
  const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
33098
33098
  const SUPPLY_CHAIN_PLUGIN = "socket";
@@ -33427,10 +33427,10 @@ const FALLBACK_TSCONFIG_FILENAMES = ["tsconfig.app.json", "tsconfig.build.json"]
33427
33427
  const FRAMEWORK_PACKAGES = {
33428
33428
  next: "nextjs",
33429
33429
  "@tanstack/react-start": "tanstack-start",
33430
- vite: "vite",
33431
- "react-scripts": "cra",
33432
33430
  "@remix-run/react": "remix",
33433
33431
  gatsby: "gatsby",
33432
+ vite: "vite",
33433
+ "react-scripts": "cra",
33434
33434
  expo: "expo",
33435
33435
  "react-native": "react-native"
33436
33436
  };
@@ -33454,11 +33454,17 @@ const NEXT_CONFIG_FILENAMES = [
33454
33454
  ];
33455
33455
  const BABEL_CONFIG_FILENAMES = [
33456
33456
  ".babelrc",
33457
+ ".babelrc.js",
33457
33458
  ".babelrc.json",
33459
+ ".babelrc.cjs",
33460
+ ".babelrc.mjs",
33461
+ ".babelrc.cts",
33458
33462
  "babel.config.js",
33459
33463
  "babel.config.json",
33460
33464
  "babel.config.cjs",
33461
- "babel.config.mjs"
33465
+ "babel.config.mjs",
33466
+ "babel.config.ts",
33467
+ "babel.config.cts"
33462
33468
  ];
33463
33469
  const VITE_CONFIG_FILENAMES = [
33464
33470
  "vite.config.js",
@@ -33470,12 +33476,28 @@ const VITE_CONFIG_FILENAMES = [
33470
33476
  "vitest.config.ts",
33471
33477
  "vitest.config.js"
33472
33478
  ];
33479
+ const RSBUILD_CONFIG_FILENAMES = [
33480
+ "rsbuild.config.ts",
33481
+ "rsbuild.config.js",
33482
+ "rsbuild.config.mts",
33483
+ "rsbuild.config.mjs",
33484
+ "rsbuild.config.cts",
33485
+ "rsbuild.config.cjs"
33486
+ ];
33487
+ const RSPACK_CONFIG_FILENAMES = [
33488
+ "rspack.config.ts",
33489
+ "rspack.config.js",
33490
+ "rspack.config.mts",
33491
+ "rspack.config.mjs",
33492
+ "rspack.config.cts",
33493
+ "rspack.config.cjs"
33494
+ ];
33473
33495
  const EXPO_APP_CONFIG_FILENAMES = [
33474
33496
  "app.json",
33475
33497
  "app.config.js",
33476
33498
  "app.config.ts"
33477
33499
  ];
33478
- const REACT_COMPILER_PACKAGE_REFERENCE_PATTERN = /babel-plugin-react-compiler|react-compiler-runtime|["']react-compiler["']/;
33500
+ const REACT_COMPILER_PACKAGE_REFERENCE_PATTERN = /babel-plugin-react-compiler|react-compiler-runtime|reactCompilerPreset\s*\(|["']react-compiler["']/;
33479
33501
  const REACT_COMPILER_ENABLED_FLAG_PATTERN = /["']?reactCompiler["']?\s*:\s*(?:true\b|\{)/;
33480
33502
  const STATIC_EXPORT_OUTPUT_PATTERN = /(?:^|[^.\w])["']?output["']?\s*:\s*["']export["']/m;
33481
33503
  const hasCompilerPackage = (packageJson, compilerPackages) => {
@@ -33510,6 +33532,8 @@ const detectReactCompiler = (directory, packageJson) => {
33510
33532
  if (hasCompilerInConfigFiles(directory, NEXT_CONFIG_FILENAMES)) return true;
33511
33533
  if (hasCompilerInConfigFiles(directory, BABEL_CONFIG_FILENAMES)) return true;
33512
33534
  if (hasCompilerInConfigFiles(directory, VITE_CONFIG_FILENAMES)) return true;
33535
+ if (hasCompilerInConfigFiles(directory, RSBUILD_CONFIG_FILENAMES)) return true;
33536
+ if (hasCompilerInConfigFiles(directory, RSPACK_CONFIG_FILENAMES)) return true;
33513
33537
  if (hasCompilerInConfigFiles(directory, EXPO_APP_CONFIG_FILENAMES)) return true;
33514
33538
  return hasCompilerPackageInAncestors(directory, REACT_COMPILER_TRANSFORM_PACKAGES);
33515
33539
  };
@@ -33957,19 +33981,6 @@ const getPreactVersion = (packageJson) => {
33957
33981
  ...packageJson.devDependencies
33958
33982
  }.preact ?? null;
33959
33983
  };
33960
- const TANSTACK_QUERY_PACKAGES = new Set([
33961
- "@tanstack/react-query",
33962
- "@tanstack/query-core",
33963
- "react-query"
33964
- ]);
33965
- const hasTanStackQuery = (packageJson) => {
33966
- const allDependencies = {
33967
- ...packageJson.peerDependencies,
33968
- ...packageJson.dependencies,
33969
- ...packageJson.devDependencies
33970
- };
33971
- return Object.keys(allDependencies).some((packageName) => TANSTACK_QUERY_PACKAGES.has(packageName));
33972
- };
33973
33984
  const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, version }) => {
33974
33985
  if (version === null || !isCatalogReference(version)) return version;
33975
33986
  const catalogName = extractCatalogName(version);
@@ -34172,7 +34183,60 @@ const listWorkspacePackages = (rootDirectory) => {
34172
34183
  }
34173
34184
  return packages;
34174
34185
  };
34186
+ const getPreferredDependencyVersion = ({ packageJson, packageNames }) => {
34187
+ const allDependencies = {
34188
+ ...packageJson.devDependencies,
34189
+ ...packageJson.peerDependencies,
34190
+ ...packageJson.dependencies
34191
+ };
34192
+ for (const packageName of packageNames) {
34193
+ const version = allDependencies[packageName];
34194
+ if (version !== void 0) return version;
34195
+ }
34196
+ return null;
34197
+ };
34198
+ const TANSTACK_REACT_QUERY_PACKAGES = ["@tanstack/react-query", "react-query"];
34199
+ const getTanStackQueryVersion = (packageJson) => {
34200
+ return getPreferredDependencyVersion({
34201
+ packageJson,
34202
+ packageNames: TANSTACK_REACT_QUERY_PACKAGES
34203
+ });
34204
+ };
34205
+ const STYLED_COMPONENTS_PACKAGES = ["styled-components"];
34206
+ const getStyledComponentsVersion = (packageJson) => {
34207
+ return getPreferredDependencyVersion({
34208
+ packageJson,
34209
+ packageNames: STYLED_COMPONENTS_PACKAGES
34210
+ });
34211
+ };
34212
+ const I18N_PACKAGES = [
34213
+ "i18next",
34214
+ "react-i18next",
34215
+ "next-i18next",
34216
+ "react-intl",
34217
+ "next-intl",
34218
+ "use-intl",
34219
+ "@formatjs/intl",
34220
+ "@lingui/core",
34221
+ "@lingui/react",
34222
+ "typesafe-i18n",
34223
+ "@tolgee/react",
34224
+ "react-intl-universal"
34225
+ ];
34226
+ const hasI18nDependency = (packageJson) => {
34227
+ const allDependencies = {
34228
+ ...packageJson.peerDependencies,
34229
+ ...packageJson.dependencies,
34230
+ ...packageJson.devDependencies,
34231
+ ...packageJson.optionalDependencies
34232
+ };
34233
+ return I18N_PACKAGES.some((packageName) => allDependencies[packageName] !== void 0);
34234
+ };
34175
34235
  const REANIMATED_DEPENDENCY_NAME = "react-native-reanimated";
34236
+ const MOBX_REACT_PACKAGE_NAME = "mobx-react";
34237
+ const MOBX_REACT_LITE_PACKAGE_NAME = "mobx-react-lite";
34238
+ const MOBX_STATE_TREE_PACKAGE_NAME = "mobx-state-tree";
34239
+ const MOBX_REACT_OBSERVER_PACKAGE_NAME = "mobx-react-observer";
34176
34240
  const SHOPIFY_FLASH_LIST_PACKAGE_NAME = "@shopify/flash-list";
34177
34241
  const resolveWorkspaceDependencyVersion = ({ concreteVersion, packageName, rootDirectory, rootPackageJson, sections, workspaceDirectory, workspacePackageJson }) => {
34178
34242
  const dependencyDeclaration = getDependencyDeclaration({
@@ -34191,7 +34255,26 @@ const shouldReplaceReactVersion = (currentVersion, nextVersion) => {
34191
34255
  if (nextMajor === null) return false;
34192
34256
  return nextMajor < currentMajor;
34193
34257
  };
34194
- const evaluateManifestFacts = (facts, packageJson, directory) => {
34258
+ const shouldReplaceSupportedDependencyFact = (currentFact, nextFact, latestSupportedMajor) => {
34259
+ if (currentFact.version === null) return true;
34260
+ if (nextFact.version === null) return false;
34261
+ const currentMajor = getLowestDependencyMajor(currentFact.version);
34262
+ const nextMajor = getLowestDependencyMajor(nextFact.version);
34263
+ if (currentMajor === null) return false;
34264
+ if (nextMajor === null) return true;
34265
+ if (currentMajor > latestSupportedMajor) return false;
34266
+ if (nextMajor > latestSupportedMajor) return true;
34267
+ return nextMajor < currentMajor;
34268
+ };
34269
+ const shouldReplaceStyledComponentsVersion = (currentVersion, nextVersion) => {
34270
+ if (!currentVersion) return true;
34271
+ const currentMajor = getLowestDependencyMajor(currentVersion);
34272
+ const nextMajor = getLowestDependencyMajor(nextVersion);
34273
+ if (currentMajor === null) return nextMajor !== null && nextMajor < 6;
34274
+ if (nextMajor === null) return currentMajor >= 6;
34275
+ return nextMajor < currentMajor;
34276
+ };
34277
+ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, rootPackageJson) => {
34195
34278
  if (facts.expo.version === null) {
34196
34279
  const spec = getDependencySpec(packageJson, "expo");
34197
34280
  if (spec !== null) facts.expo = {
@@ -34213,13 +34296,74 @@ const evaluateManifestFacts = (facts, packageJson, directory) => {
34213
34296
  sourceDirectory: directory
34214
34297
  };
34215
34298
  }
34299
+ const mobxSpec = getDependencySpec(packageJson, "mobx");
34300
+ if (mobxSpec !== null) {
34301
+ const nextMobxFact = {
34302
+ version: resolveCatalogBackedDependencyVersion({
34303
+ rootDirectory: directory,
34304
+ rootPackageJson: packageJson,
34305
+ packageName: "mobx",
34306
+ version: mobxSpec
34307
+ }),
34308
+ sourceDirectory: directory
34309
+ };
34310
+ if (shouldReplaceSupportedDependencyFact(facts.mobx, nextMobxFact, 6)) facts.mobx = nextMobxFact;
34311
+ }
34312
+ facts.hasMobxReact = facts.hasMobxReact || getDependencySpec(packageJson, MOBX_REACT_PACKAGE_NAME) !== null;
34313
+ facts.hasMobxReactLite = facts.hasMobxReactLite || getDependencySpec(packageJson, MOBX_REACT_LITE_PACKAGE_NAME) !== null;
34314
+ facts.hasMobxStateTree = facts.hasMobxStateTree || getDependencySpec(packageJson, MOBX_STATE_TREE_PACKAGE_NAME) !== null;
34315
+ facts.hasMobxReactObserver = facts.hasMobxReactObserver || getDependencySpec(packageJson, MOBX_REACT_OBSERVER_PACKAGE_NAME) !== null;
34316
+ const zustandSpec = getDependencySpec(packageJson, "zustand");
34317
+ if (zustandSpec !== null) {
34318
+ const nextZustandFact = {
34319
+ version: resolveCatalogBackedDependencyVersion({
34320
+ rootDirectory: directory,
34321
+ rootPackageJson: packageJson,
34322
+ packageName: "zustand",
34323
+ version: zustandSpec
34324
+ }),
34325
+ sourceDirectory: directory
34326
+ };
34327
+ if (shouldReplaceSupportedDependencyFact(facts.zustand, nextZustandFact, 5)) facts.zustand = nextZustandFact;
34328
+ }
34216
34329
  if (facts.reanimatedVersion === null) {
34217
34330
  const spec = getDependencySpec(packageJson, REANIMATED_DEPENDENCY_NAME);
34218
34331
  if (spec !== null) facts.reanimatedVersion = spec;
34219
34332
  }
34333
+ if (facts.valtioVersion === null) {
34334
+ const spec = getDependencySpec(packageJson, "valtio");
34335
+ if (spec !== null) facts.valtioVersion = spec;
34336
+ }
34337
+ facts.tanstackQueryVersion ??= getTanStackQueryVersion(packageJson);
34338
+ const styledComponentsVersion = resolveCatalogBackedDependencyVersion({
34339
+ rootDirectory: directory,
34340
+ rootPackageJson: packageJson,
34341
+ packageName: "styled-components",
34342
+ version: getStyledComponentsVersion(packageJson)
34343
+ });
34344
+ if (styledComponentsVersion && shouldReplaceStyledComponentsVersion(facts.styledComponentsVersion, styledComponentsVersion)) facts.styledComponentsVersion = styledComponentsVersion;
34345
+ facts.hasI18nLibrary = facts.hasI18nLibrary || hasI18nDependency(packageJson);
34220
34346
  facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
34221
34347
  facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
34222
34348
  facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
34349
+ const remotionSpec = getDependencySpec(packageJson, "remotion");
34350
+ if (remotionSpec !== null) {
34351
+ facts.hasRemotionDependency = true;
34352
+ const resolvedRemotionVersion = resolveCatalogBackedDependencyVersion({
34353
+ rootDirectory,
34354
+ rootPackageJson,
34355
+ packageName: "remotion",
34356
+ version: remotionSpec
34357
+ });
34358
+ const remotionMajorVersion = resolvedRemotionVersion === null ? null : getLowestDependencyMajor(resolvedRemotionVersion);
34359
+ if (remotionMajorVersion === null) {
34360
+ facts.hasUnknownRemotionVersion = true;
34361
+ facts.remotionVersion = null;
34362
+ } else if (!facts.hasUnknownRemotionVersion) {
34363
+ const currentRemotionMajorVersion = facts.remotionVersion === null ? null : getLowestDependencyMajor(facts.remotionVersion);
34364
+ if (currentRemotionMajorVersion === null || remotionMajorVersion < currentRemotionMajorVersion) facts.remotionVersion = resolvedRemotionVersion;
34365
+ }
34366
+ }
34223
34367
  };
34224
34368
  const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGroup }) => {
34225
34369
  const facts = {
@@ -34239,12 +34383,31 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34239
34383
  version: null,
34240
34384
  sourceDirectory: null
34241
34385
  },
34386
+ valtioVersion: null,
34387
+ mobx: {
34388
+ version: null,
34389
+ sourceDirectory: null
34390
+ },
34391
+ hasMobxReact: false,
34392
+ hasMobxReactLite: false,
34393
+ hasMobxStateTree: false,
34394
+ hasMobxReactObserver: false,
34395
+ zustand: {
34396
+ version: null,
34397
+ sourceDirectory: null
34398
+ },
34399
+ tanstackQueryVersion: null,
34400
+ styledComponentsVersion: null,
34401
+ hasI18nLibrary: false,
34242
34402
  hasReactNativeAwarePackage: false,
34243
34403
  hasReanimatedAwarePackage: false,
34244
34404
  hasSsrDependency: false,
34405
+ hasRemotionDependency: false,
34406
+ hasUnknownRemotionVersion: false,
34407
+ remotionVersion: null,
34245
34408
  reanimatedVersion: null
34246
34409
  };
34247
- evaluateManifestFacts(facts, rootPackageJson, rootDirectory);
34410
+ evaluateManifestFacts(facts, rootPackageJson, rootDirectory, rootDirectory, rootPackageJson);
34248
34411
  let isReactGroupSettled = !collectReactGroup;
34249
34412
  const visitedDirectories = /* @__PURE__ */ new Set();
34250
34413
  for (const pattern of getWorkspacePatterns(rootDirectory, rootPackageJson)) {
@@ -34253,7 +34416,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34253
34416
  if (visitedDirectories.has(workspaceDirectory)) continue;
34254
34417
  visitedDirectories.add(workspaceDirectory);
34255
34418
  const workspacePackageJson = readPackageJson(Path.join(workspaceDirectory, "package.json"));
34256
- evaluateManifestFacts(facts, workspacePackageJson, workspaceDirectory);
34419
+ evaluateManifestFacts(facts, workspacePackageJson, workspaceDirectory, rootDirectory, rootPackageJson);
34257
34420
  const info = extractDependencyInfo(workspacePackageJson);
34258
34421
  if (info.framework !== "unknown" && frameworkMergeRank(info.framework) < frameworkMergeRank(facts.framework)) facts.framework = info.framework;
34259
34422
  if (isReactGroupSettled) continue;
@@ -34477,11 +34640,27 @@ const discoverProjectWithoutPackageJson = (directory) => {
34477
34640
  tailwindVersion: null,
34478
34641
  zodVersion: null,
34479
34642
  zodMajorVersion: null,
34643
+ mobxVersion: null,
34644
+ mobxMajorVersion: null,
34645
+ hasMobxReact: false,
34646
+ hasMobxReactLite: false,
34647
+ hasMobxStateTree: false,
34648
+ hasMobxReactObserver: false,
34649
+ zustandVersion: null,
34650
+ zustandMajorVersion: null,
34480
34651
  framework: "unknown",
34481
34652
  hasTypeScript: hasOwnTsConfig,
34482
34653
  hasReactCompiler: false,
34483
34654
  hasReactCompilerLintPlugin: false,
34484
34655
  hasTanStackQuery: false,
34656
+ valtioVersion: null,
34657
+ valtioMajorVersion: null,
34658
+ hasRemotion: false,
34659
+ remotionVersion: null,
34660
+ remotionMajorVersion: null,
34661
+ hasI18nLibrary: false,
34662
+ tanstackQueryVersion: null,
34663
+ styledComponentsVersion: null,
34485
34664
  hasSsrDependency: false,
34486
34665
  preactVersion: null,
34487
34666
  preactMajorVersion: null,
@@ -34580,6 +34759,12 @@ const discoverProject = (directory) => {
34580
34759
  packageName: SHOPIFY_FLASH_LIST_PACKAGE_NAME,
34581
34760
  version: workspaceFacts.shopifyFlashList.version
34582
34761
  }) : null;
34762
+ const zustandVersion = resolveCatalogBackedDependencyVersion({
34763
+ rootDirectory: directory,
34764
+ rootPackageJson: packageJson,
34765
+ packageName: "zustand",
34766
+ version: workspaceFacts.zustand.version
34767
+ });
34583
34768
  const hasReanimated = hasReactNativeWorkspace && workspaceFacts.hasReanimatedAwarePackage;
34584
34769
  const reanimatedVersion = hasReanimated ? workspaceFacts.reanimatedVersion : null;
34585
34770
  const nextjsVersion = framework === "nextjs" ? resolveCatalogBackedDependencyVersion({
@@ -34588,7 +34773,21 @@ const discoverProject = (directory) => {
34588
34773
  packageName: "next",
34589
34774
  version: workspaceFacts.next.version
34590
34775
  }) : null;
34776
+ const valtioVersion = resolveCatalogBackedDependencyVersion({
34777
+ rootDirectory: directory,
34778
+ rootPackageJson: packageJson,
34779
+ packageName: "valtio",
34780
+ version: workspaceFacts.valtioVersion
34781
+ });
34782
+ const mobxVersion = resolveCatalogBackedDependencyVersion({
34783
+ rootDirectory: directory,
34784
+ rootPackageJson: packageJson,
34785
+ packageName: "mobx",
34786
+ version: workspaceFacts.mobx.version
34787
+ });
34591
34788
  const preactVersion = getPreactVersion(packageJson);
34789
+ const remotionVersion = workspaceFacts.remotionVersion;
34790
+ const tanstackQueryVersion = getTanStackQueryVersion(packageJson) ?? workspaceFacts.tanstackQueryVersion;
34592
34791
  const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
34593
34792
  const projectInfo = {
34594
34793
  rootDirectory: directory,
@@ -34598,11 +34797,27 @@ const discoverProject = (directory) => {
34598
34797
  tailwindVersion,
34599
34798
  zodVersion,
34600
34799
  zodMajorVersion: zodVersion === null ? null : getLowestDependencyMajor(zodVersion),
34800
+ mobxVersion,
34801
+ mobxMajorVersion: mobxVersion === null ? null : getLowestDependencyMajor(mobxVersion),
34802
+ hasMobxReact: workspaceFacts.hasMobxReact,
34803
+ hasMobxReactLite: workspaceFacts.hasMobxReactLite,
34804
+ hasMobxStateTree: workspaceFacts.hasMobxStateTree,
34805
+ hasMobxReactObserver: workspaceFacts.hasMobxReactObserver,
34806
+ zustandVersion,
34807
+ zustandMajorVersion: zustandVersion === null ? null : getLowestDependencyMajor(zustandVersion),
34601
34808
  framework,
34602
34809
  hasTypeScript,
34603
34810
  hasReactCompiler: detectReactCompiler(directory, packageJson),
34604
34811
  hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
34605
- hasTanStackQuery: hasTanStackQuery(packageJson),
34812
+ hasTanStackQuery: tanstackQueryVersion !== null,
34813
+ hasI18nLibrary: workspaceFacts.hasI18nLibrary,
34814
+ tanstackQueryVersion,
34815
+ styledComponentsVersion: workspaceFacts.styledComponentsVersion,
34816
+ valtioVersion,
34817
+ valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
34818
+ hasRemotion: workspaceFacts.hasRemotionDependency,
34819
+ remotionVersion,
34820
+ remotionMajorVersion: remotionVersion === null ? null : getLowestDependencyMajor(remotionVersion),
34606
34821
  hasSsrDependency: workspaceFacts.hasSsrDependency,
34607
34822
  preactVersion,
34608
34823
  preactMajorVersion: parseReactMajor(preactVersion),
@@ -34836,7 +35051,6 @@ const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
34836
35051
  "react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
34837
35052
  "react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
34838
35053
  "react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
34839
- "react/jsx-no-target-blank": "react-doctor/jsx-no-target-blank",
34840
35054
  "react/jsx-no-undef": "react-doctor/jsx-no-undef",
34841
35055
  "react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
34842
35056
  "react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
@@ -37049,9 +37263,25 @@ const BABEL_CONFIG_FILE_NAMES = [
37049
37263
  ".babelrc.json"
37050
37264
  ];
37051
37265
  const LEGACY_PRESET_SPEC = "module:metro-react-native-babel-preset";
37266
+ const LEGACY_PRESET_PACKAGE = "metro-react-native-babel-preset";
37267
+ const REACT_NATIVE_PACKAGE = "react-native";
37268
+ const PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION = "0.73.0";
37269
+ const LEGACY_PRESET_REFERENCE = new RegExp(`['"]${LEGACY_PRESET_SPEC}['"]`);
37052
37270
  const MODERN_PRESET_REFERENCE = new RegExp(`['"]module:@react-native/babel-preset['"]`);
37053
37271
  const ENABLE_BABEL_RUNTIME_VERSION = /enableBabelRuntime["']?\s*:\s*['"]/;
37272
+ const isReactNativeVersionAtLeastPresetRename = (rootDirectory, packageJson) => {
37273
+ const installedReactNativeManifestPath = Path.join(rootDirectory, "node_modules", REACT_NATIVE_PACKAGE, "package.json");
37274
+ const reactNativeVersionSpec = (isFile(installedReactNativeManifestPath) ? readPackageJson(installedReactNativeManifestPath).version : void 0) ?? getDependencySpec(packageJson, REACT_NATIVE_PACKAGE);
37275
+ if (reactNativeVersionSpec === null || reactNativeVersionSpec === void 0) return false;
37276
+ const normalizedVersionRange = import_semver.validRange(reactNativeVersionSpec);
37277
+ if (normalizedVersionRange === null) return false;
37278
+ const minimumVersion = import_semver.minVersion(normalizedVersionRange);
37279
+ return minimumVersion !== null && import_semver.gte(minimumVersion, PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION);
37280
+ };
37281
+ const canResolveLegacyPreset = (rootDirectory, packageJson) => getDependencySpec(packageJson, LEGACY_PRESET_PACKAGE) !== null || isFile(Path.join(rootDirectory, "node_modules", LEGACY_PRESET_PACKAGE, "package.json"));
37054
37282
  const checkReactNativeMetroBabelPreset = (rootDirectory) => {
37283
+ const packageJson = readPackageJson(Path.join(rootDirectory, "package.json"));
37284
+ const shouldReportLegacyPreset = isReactNativeVersionAtLeastPresetRename(rootDirectory, packageJson) && !canResolveLegacyPreset(rootDirectory, packageJson);
37055
37285
  for (const fileName of BABEL_CONFIG_FILE_NAMES) {
37056
37286
  const filePath = Path.join(rootDirectory, fileName);
37057
37287
  if (!isFile(filePath)) continue;
@@ -37061,7 +37291,7 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
37061
37291
  } catch {
37062
37292
  continue;
37063
37293
  }
37064
- if (contents.includes(LEGACY_PRESET_SPEC)) return [buildReactNativeDiagnostic({
37294
+ if (shouldReportLegacyPreset && LEGACY_PRESET_REFERENCE.test(contents)) return [buildReactNativeDiagnostic({
37065
37295
  filePath: fileName,
37066
37296
  rule: "rn-no-metro-babel-preset",
37067
37297
  severity: "error",
@@ -37084,12 +37314,6 @@ const checkReactNativeProject = (rootDirectory, project) => {
37084
37314
  return [...checkReactNativeMetroBabelPreset(rootDirectory), ...checkReactNativeLibraryDependencies(rootDirectory)];
37085
37315
  };
37086
37316
  const RULE_KEY = "no-vulnerable-react-server-components";
37087
- const DEPENDENCY_SECTIONS = [
37088
- "dependencies",
37089
- "devDependencies",
37090
- "peerDependencies",
37091
- "optionalDependencies"
37092
- ];
37093
37317
  const REACT_RSC_ADVISORIES_BY_MINOR = {
37094
37318
  "19.0": {
37095
37319
  rceFixedVersion: "19.0.1",
@@ -37136,20 +37360,13 @@ const enumerateWorkspaceDirectories = (workspaceRoot) => {
37136
37360
  for (const pattern of patterns) for (const directory of resolveWorkspaceDirectories(workspaceRoot, pattern)) directories.add(directory);
37137
37361
  return [...directories];
37138
37362
  };
37139
- const readDeclaredSpec = (packageJson, packageName) => {
37140
- for (const section of DEPENDENCY_SECTIONS) {
37141
- const spec = packageJson[section]?.[packageName];
37142
- if (typeof spec === "string") return spec;
37143
- }
37144
- return null;
37145
- };
37146
37363
  const resolveVersionInDirectory = (directory, packageName, declaredSpecOverride) => {
37147
37364
  const manifestPath = Path.join(directory, "node_modules", packageName, "package.json");
37148
37365
  if (isFile(manifestPath)) {
37149
37366
  const installedVersion = import_semver.valid(readPackageJson(manifestPath).version ?? null);
37150
37367
  if (installedVersion !== null) return installedVersion;
37151
37368
  }
37152
- const candidateSpecs = [readDeclaredSpec(readPackageJson(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
37369
+ const candidateSpecs = [getDependencySpec(readPackageJson(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
37153
37370
  for (const spec of candidateSpecs) {
37154
37371
  const pinnedVersion = spec === null ? null : import_semver.valid(spec);
37155
37372
  if (pinnedVersion !== null) return pinnedVersion;
@@ -37817,21 +38034,50 @@ const buildCapabilities = (project) => {
37817
38034
  if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
37818
38035
  if (project.isStaticExport) capabilities.add("nextjs:static-export");
37819
38036
  if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
38037
+ if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 16) capabilities.add("nextjs:16");
37820
38038
  addMajorLadder(capabilities, "react", project.reactMajorVersion, 17, 30);
37821
38039
  if (project.reactMajorVersion !== null && project.reactMajorVersion >= 19 && isMajorMinorAtLeast(parseReactMajorMinor(project.reactVersion), {
37822
38040
  major: 19,
37823
38041
  minor: 2
37824
38042
  })) capabilities.add("react:19.2");
37825
- if (project.tailwindVersion !== null) capabilities.add("tailwind");
37826
- if (project.tailwindVersion !== null && isMajorMinorAtLeast(parseTailwindMajorMinor(project.tailwindVersion), {
37827
- major: 3,
37828
- minor: 4
37829
- })) capabilities.add("tailwind:3.4");
38043
+ if (project.tailwindVersion !== null) {
38044
+ capabilities.add("tailwind");
38045
+ const tailwindVersion = parseTailwindMajorMinor(project.tailwindVersion);
38046
+ if (isMajorMinorAtLeast(tailwindVersion, {
38047
+ major: 3,
38048
+ minor: 4
38049
+ })) capabilities.add("tailwind:3.4");
38050
+ if (tailwindVersion !== null && isMajorMinorAtLeast(tailwindVersion, {
38051
+ major: 4,
38052
+ minor: 0
38053
+ })) capabilities.add("tailwind:4");
38054
+ }
37830
38055
  if (project.zodVersion !== null) capabilities.add("zod");
37831
38056
  if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
38057
+ if (project.mobxVersion !== void 0 && project.mobxVersion !== null || project.hasMobxReact === true || project.hasMobxReactLite === true || project.hasMobxStateTree === true || project.hasMobxReactObserver === true) capabilities.add("mobx");
38058
+ if (project.hasMobxReact === true) capabilities.add("mobx-react");
38059
+ if (project.hasMobxReactLite === true) capabilities.add("mobx-react-lite");
38060
+ if (project.hasMobxReact === true || project.hasMobxReactLite === true) capabilities.add("mobx-react-binding");
38061
+ if (project.hasMobxStateTree === true) capabilities.add("mobx-state-tree");
38062
+ if (project.hasMobxReactObserver === true) capabilities.add("mobx-react-observer");
38063
+ if (project.mobxMajorVersion !== void 0 && project.mobxMajorVersion !== null && project.mobxMajorVersion >= 4 && project.mobxMajorVersion <= 6) addMajorLadder(capabilities, "mobx", project.mobxMajorVersion, 4, 6);
38064
+ if (project.zustandVersion !== void 0 && project.zustandVersion !== null) capabilities.add("zustand");
38065
+ if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addMajorLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
37832
38066
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
37833
38067
  if (project.hasReactCompiler) capabilities.add("react-compiler");
37834
- if (project.hasTanStackQuery) capabilities.add("tanstack-query");
38068
+ if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
38069
+ if (project.styledComponentsVersion) {
38070
+ capabilities.add("styled-components");
38071
+ const styledComponentsMajor = getLowestDependencyMajor(project.styledComponentsVersion);
38072
+ if (styledComponentsMajor !== null && styledComponentsMajor >= 6) capabilities.add("styled-components:6");
38073
+ }
38074
+ if (project.hasI18nLibrary) capabilities.add("i18n");
38075
+ if (project.valtioVersion !== null) capabilities.add("valtio");
38076
+ addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
38077
+ if (project.hasRemotion) {
38078
+ capabilities.add("remotion");
38079
+ addMajorLadder(capabilities, "remotion", project.remotionMajorVersion ?? null, 4, 30);
38080
+ }
37835
38081
  if (project.hasTypeScript) capabilities.add("typescript");
37836
38082
  if (project.preactVersion !== null) capabilities.add("preact");
37837
38083
  addMajorLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
@@ -37846,7 +38092,7 @@ const getCapabilities = (project) => {
37846
38092
  capabilitiesByProject.set(project, capabilities);
37847
38093
  return capabilities;
37848
38094
  };
37849
- const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhen) => {
38095
+ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhen, includedTags) => {
37850
38096
  if (requires) {
37851
38097
  for (const capability of requires) if (!capabilities.has(capability)) return false;
37852
38098
  }
@@ -37857,20 +38103,29 @@ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhe
37857
38103
  if (tags) {
37858
38104
  for (const tag of tags) if (ignoredTags.has(tag)) return false;
37859
38105
  }
38106
+ if (includedTags && includedTags.size > 0) {
38107
+ if (!tags?.some((tag) => includedTags.has(tag))) return false;
38108
+ }
37860
38109
  return true;
37861
38110
  };
38111
+ const shouldEnableRuleByDefaultStatus = (options) => options.defaultEnabled !== false || options.hasExplicitOverride === true || options.includeTagDefaults && options.hasIncludedTags;
37862
38112
  const yieldToEventLoop = () => new Promise((resolve) => {
37863
38113
  setImmediate(resolve);
37864
38114
  });
37865
38115
  const createSecurityScanSession = (rootDirectory, options) => {
37866
38116
  const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
37867
38117
  const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
38118
+ const includedTags = options.includedTags ?? /* @__PURE__ */ new Set();
37868
38119
  const enabledScanRules = REACT_DOCTOR_RULES.flatMap((entry) => {
37869
38120
  const rule = entry.rule;
37870
38121
  const scan = rule.scan;
37871
38122
  if (typeof scan !== "function") return [];
37872
- if (rule.defaultEnabled === false) return [];
37873
- if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen)) return [];
38123
+ if (!shouldEnableRuleByDefaultStatus({
38124
+ defaultEnabled: rule.defaultEnabled,
38125
+ includeTagDefaults: options.includeTagDefaults === true,
38126
+ hasIncludedTags: includedTags.size > 0
38127
+ })) return [];
38128
+ if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) return [];
37874
38129
  return [{
37875
38130
  entry,
37876
38131
  scan,
@@ -39068,6 +39323,35 @@ const parseGithubViewerPermission = (stdout) => {
39068
39323
  return /^[A-Z_]+$/.test(value) ? value.toLowerCase() : null;
39069
39324
  };
39070
39325
  const splitNullSeparated = (value) => value.split("\0").filter((entry) => entry.length > 0);
39326
+ const parseBaselineDiffPlan = (value) => {
39327
+ const entries = splitNullSeparated(value);
39328
+ const baseFiles = /* @__PURE__ */ new Set();
39329
+ const headFiles = /* @__PURE__ */ new Set();
39330
+ for (let entryIndex = 0; entryIndex < entries.length; entryIndex += 2) {
39331
+ const status = entries[entryIndex];
39332
+ const filePath = entries[entryIndex + 1];
39333
+ if (status === void 0 || filePath === void 0 || status.length !== 1) return null;
39334
+ if (status === "A") {
39335
+ headFiles.add(filePath);
39336
+ continue;
39337
+ }
39338
+ if (status === "D") {
39339
+ baseFiles.add(filePath);
39340
+ continue;
39341
+ }
39342
+ if (status === "M" || status === "T") {
39343
+ baseFiles.add(filePath);
39344
+ headFiles.add(filePath);
39345
+ continue;
39346
+ }
39347
+ return null;
39348
+ }
39349
+ return {
39350
+ baseFiles: [...baseFiles],
39351
+ headFiles: [...headFiles],
39352
+ untrackedFiles: []
39353
+ };
39354
+ };
39071
39355
  const UNTRACKED_FILE_LAST_LINE = Number.MAX_SAFE_INTEGER;
39072
39356
  /**
39073
39357
  * `Git` wraps every `git`-via-subprocess call react-doctor makes
@@ -39270,6 +39554,45 @@ var Git = class Git extends Service()("react-doctor/Git") {
39270
39554
  githubViewerPermission,
39271
39555
  branchExists,
39272
39556
  mergeBase,
39557
+ baselineDiffPlan: (input) => {
39558
+ if (!isSafeGitRevision(input.ref)) return succeed$2(null);
39559
+ return gen(function* () {
39560
+ const unmerged = yield* runGit(input.directory, [
39561
+ "diff",
39562
+ "--no-ext-diff",
39563
+ "-z",
39564
+ "--name-only",
39565
+ "--diff-filter=U",
39566
+ "--relative"
39567
+ ]);
39568
+ if (unmerged.status !== 0 || unmerged.stdout.length > 0) return null;
39569
+ const result = yield* runGit(input.directory, [
39570
+ "diff",
39571
+ "--no-ext-diff",
39572
+ "--no-textconv",
39573
+ "--no-renames",
39574
+ "-z",
39575
+ "--name-status",
39576
+ "--relative",
39577
+ input.ref
39578
+ ]);
39579
+ if (result.status !== 0) return null;
39580
+ const plan = parseBaselineDiffPlan(result.stdout);
39581
+ if (plan === null) return null;
39582
+ const untracked = yield* runGit(input.directory, [
39583
+ "ls-files",
39584
+ "--others",
39585
+ "--exclude-standard",
39586
+ "-z"
39587
+ ]);
39588
+ if (untracked.status !== 0) return null;
39589
+ return {
39590
+ baseFiles: plan.baseFiles,
39591
+ headFiles: plan.headFiles,
39592
+ untrackedFiles: splitNullSeparated(untracked.stdout)
39593
+ };
39594
+ }).pipe(catch_$1(() => succeed$2(null)), withSpan("Git.baselineDiffPlan"));
39595
+ },
39273
39596
  diffSelection: ({ directory, explicitBaseBranch, includeUntracked = false }) => gen(function* () {
39274
39597
  if (explicitBaseBranch !== void 0 && explicitBaseBranch.trim().length === 0) return yield* fail$4(new ReactDoctorError({ reason: new GitBaseBranchInvalid({ detail: "Diff base branch cannot be empty." }) }));
39275
39598
  if (explicitBaseBranch !== void 0) {
@@ -39419,6 +39742,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
39419
39742
  githubViewerPermission: () => succeed$2(snapshot.githubViewerPermission ?? null),
39420
39743
  branchExists: (_directory, branch) => succeed$2(snapshot.branchExists?.get(branch) ?? false),
39421
39744
  mergeBase: ({ ref }) => succeed$2(snapshot.mergeBase?.get(ref) ?? null),
39745
+ baselineDiffPlan: () => succeed$2(snapshot.baselineDiffPlan ?? null),
39422
39746
  diffSelection: () => succeed$2(snapshot.diffSelection ?? null),
39423
39747
  stagedFilePaths: () => succeed$2(snapshot.stagedFiles ?? []),
39424
39748
  showStagedContent: (_directory, relativePath) => succeed$2(snapshot.stagedContent?.get(relativePath) ?? null),
@@ -39787,8 +40111,9 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
39787
40111
  }
39788
40112
  return enabled;
39789
40113
  };
39790
- const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
39791
- const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
40114
+ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
40115
+ const hasIncludedTags = includedTags.size > 0;
40116
+ const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
39792
40117
  const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
39793
40118
  const jsPlugins = [];
39794
40119
  if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
@@ -39803,9 +40128,14 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
39803
40128
  if (rule.scan !== void 0) continue;
39804
40129
  if (customRulesOnly && registryEntry.originallyExternal) continue;
39805
40130
  if (rule.framework !== "global" && !rule.requires) continue;
39806
- if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen)) continue;
40131
+ if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) continue;
39807
40132
  const explicitRuleOverride = resolveRuleSeverityOverride({ ruleKey: registryEntry.key }, severityControls);
39808
- if (rule.defaultEnabled === false && explicitRuleOverride === void 0) continue;
40133
+ if (!shouldEnableRuleByDefaultStatus({
40134
+ defaultEnabled: rule.defaultEnabled,
40135
+ includeTagDefaults,
40136
+ hasIncludedTags,
40137
+ hasExplicitOverride: explicitRuleOverride !== void 0
40138
+ })) continue;
39809
40139
  const severity = resolveRuleSeverityOverride({
39810
40140
  ruleKey: registryEntry.key,
39811
40141
  category: rule.category
@@ -39814,7 +40144,7 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
39814
40144
  enabledReactDoctorRules[registryEntry.key] = severity;
39815
40145
  }
39816
40146
  const userPluginRules = {};
39817
- if (ruleSelection !== "sidecar") for (const userPlugin of userPlugins) {
40147
+ if (ruleSelection !== "sidecar" && !hasIncludedTags) for (const userPlugin of userPlugins) {
39818
40148
  Object.assign(userPluginRules, buildUserPluginRules(userPlugin, severityControls));
39819
40149
  jsPlugins.push(userPlugin.entry);
39820
40150
  }
@@ -40031,6 +40361,19 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
40031
40361
  }
40032
40362
  };
40033
40363
  };
40364
+ const fingerprintCacheByFilePath = /* @__PURE__ */ new Map();
40365
+ const fingerprintFileContents = (filePath, fingerprintLength) => {
40366
+ const fileStats = NFS.statSync(filePath, { bigint: true });
40367
+ const cachedFingerprint = fingerprintCacheByFilePath.get(filePath);
40368
+ if (cachedFingerprint?.modifiedTimeNanoseconds === fileStats.mtimeNs && cachedFingerprint.sizeBytes === fileStats.size) return cachedFingerprint.fingerprint;
40369
+ const fingerprint = crypto.createHash("sha256").update(NFS.readFileSync(filePath)).digest("hex").slice(0, fingerprintLength);
40370
+ fingerprintCacheByFilePath.set(filePath, {
40371
+ fingerprint,
40372
+ modifiedTimeNanoseconds: fileStats.mtimeNs,
40373
+ sizeBytes: fileStats.size
40374
+ });
40375
+ return fingerprint;
40376
+ };
40034
40377
  const bundledRequire = createRequire(import.meta.url);
40035
40378
  const childNodeVersionByBinaryPath = /* @__PURE__ */ new Map();
40036
40379
  const resolveChildNodeVersion = (nodeBinaryPath) => {
@@ -40054,6 +40397,13 @@ const TOOLCHAIN_PACKAGE_SPECIFIERS = [
40054
40397
  "oxlint-plugin-react-doctor/package.json",
40055
40398
  "eslint-plugin-react-hooks/package.json"
40056
40399
  ];
40400
+ const resolvePluginFingerprint = () => {
40401
+ try {
40402
+ return fingerprintFileContents(bundledRequire.resolve("oxlint-plugin-react-doctor"), 16);
40403
+ } catch {
40404
+ return "unresolved";
40405
+ }
40406
+ };
40057
40407
  const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
40058
40408
  const versions = [`node=${resolveChildNodeVersion(nodeBinaryPath)}`];
40059
40409
  for (const specifier of TOOLCHAIN_PACKAGE_SPECIFIERS) try {
@@ -40063,6 +40413,7 @@ const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
40063
40413
  } catch {
40064
40414
  versions.push(`${specifier}=missing`);
40065
40415
  }
40416
+ versions.push(`oxlint-plugin-react-doctor#fingerprint=${resolvePluginFingerprint()}`);
40066
40417
  return versions;
40067
40418
  };
40068
40419
  const esmRequire = createRequire(import.meta.url);
@@ -40756,12 +41107,17 @@ const REACT_ERROR_BOUNDARY_MESSAGE = "This try/catch cannot catch errors thrown
40756
41107
  const REACT_COMPILER_IMPACT = "This component misses React Compiler's automatic memoization & re-renders more than it should";
40757
41108
  const REACT_COMPILER_ACTION = "Rewrite the flagged code so the compiler can optimize it.";
40758
41109
  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`.";
41110
+ 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`.";
40759
41111
  const REACT_COMPILER_GENERIC_MESSAGE = `${REACT_COMPILER_IMPACT}. ${REACT_COMPILER_ACTION}`;
40760
41112
  const buildReactCompilerMessage = (reasonSummary, action = REACT_COMPILER_ACTION) => {
40761
41113
  const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
40762
41114
  if (!normalizedSummary) return `${REACT_COMPILER_IMPACT}. ${action}`;
40763
41115
  return `${REACT_COMPILER_IMPACT}: ${normalizedSummary}. ${action}`;
40764
41116
  };
41117
+ const buildSetStateInEffectMessage = (reasonSummary) => {
41118
+ const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
41119
+ return `This synchronous effect update causes an extra render${normalizedSummary ? `: ${normalizedSummary}` : ""}. ${SET_STATE_IN_EFFECT_ACTION}`;
41120
+ };
40765
41121
  const PLUGIN_CATEGORY_MAP = {
40766
41122
  react: "Bugs",
40767
41123
  "react-hooks": "Bugs",
@@ -40819,6 +41175,10 @@ const resolveCleanedDiagnostic = (message, help, plugin, rule, project) => {
40819
41175
  message: REACT_ERROR_BOUNDARY_MESSAGE,
40820
41176
  help: reasonDetail || help
40821
41177
  };
41178
+ if (rule === "set-state-in-effect") return {
41179
+ message: buildSetStateInEffectMessage(reasonSummary.trim()),
41180
+ help: reasonDetail || help
41181
+ };
40822
41182
  return {
40823
41183
  message: buildReactCompilerMessage(reasonSummary.trim(), rule === "incompatible-library" ? REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION : REACT_COMPILER_ACTION),
40824
41184
  help: appendReanimatedSharedValueHint(reasonDetail || help, rule, project)
@@ -41529,7 +41889,7 @@ const reactHooksJsPluginDropNote = (error) => {
41529
41889
  * 6. always restore disable directives + clean up the temp dir
41530
41890
  */
41531
41891
  const runOxlint = async (options) => {
41532
- const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, onFileCoverage, perFileLintCacheEnabled = false, sidecarLintCacheEnabled = false, onCacheStats, onSidecarStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
41892
+ const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, userConfig, configSourceDirectory = rootDirectory, onPartialFailure, onFileCoverage, perFileLintCacheEnabled = false, sidecarLintCacheEnabled = false, onCacheStats, onSidecarStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
41533
41893
  const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
41534
41894
  const severityControls = buildRuleSeverityControls(userConfig);
41535
41895
  validateRuleRegistration();
@@ -41543,13 +41903,15 @@ const runOxlint = async (options) => {
41543
41903
  }
41544
41904
  const pluginPath = resolvePluginPath();
41545
41905
  const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
41546
- const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
41906
+ const userPlugins = includedTags.size > 0 ? [] : resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
41547
41907
  const buildConfig = (overrides) => createOxlintConfig({
41548
41908
  pluginPath,
41549
41909
  project,
41550
41910
  customRulesOnly,
41551
41911
  extendsPaths: overrides.extendsPaths,
41552
41912
  ignoredTags,
41913
+ includedTags,
41914
+ includeTagDefaults,
41553
41915
  serverAuthFunctionNames,
41554
41916
  severityControls,
41555
41917
  userPlugins,
@@ -41938,6 +42300,8 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
41938
42300
  respectInlineDisables: input.respectInlineDisables,
41939
42301
  adoptExistingLintConfig: input.adoptExistingLintConfig,
41940
42302
  ignoredTags: input.ignoredTags,
42303
+ includedTags: input.includedTags,
42304
+ includeTagDefaults: input.includeTagDefaults,
41941
42305
  userConfig: input.userConfig ?? null,
41942
42306
  configSourceDirectory: input.configSourceDirectory,
41943
42307
  onPartialFailure: (reason) => {
@@ -42786,7 +43150,9 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42786
43150
  const securityScanFailedRef = yield* make$13(false);
42787
43151
  const securityScanFiber = yield* forkChild(runCollect(applyPerElementPipeline(isDiffMode ? empty$4 : unwrap(tryPromise(() => checkSecurityScanCooperative(scanDirectory, {
42788
43152
  project,
42789
- ignoredTags: input.ignoredTags
43153
+ ignoredTags: input.ignoredTags,
43154
+ includedTags: input.includedTags,
43155
+ includeTagDefaults: input.includeTagDefaults
42790
43156
  })).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), catch_$1(() => set(securityScanFailedRef, true).pipe(as(empty$4))))))).pipe(withSpan("SecurityScan.run")));
42791
43157
  const shouldRunSupplyChain = !isDiffMode || (input.supplyChainManifestChanged ?? false);
42792
43158
  const supplyChainOverlapTimeout = yield* SupplyChainOverlapTimeoutMs;
@@ -42877,6 +43243,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42877
43243
  respectInlineDisables: input.respectInlineDisables,
42878
43244
  adoptExistingLintConfig: input.adoptExistingLintConfig,
42879
43245
  ignoredTags: input.ignoredTags,
43246
+ includedTags: input.includedTags,
43247
+ includeTagDefaults: input.includeTagDefaults,
42880
43248
  userConfig: resolvedConfig.config ?? void 0,
42881
43249
  configSourceDirectory: resolvedConfig.configSourceDirectory ?? void 0,
42882
43250
  onFileProgress: (scannedFileCount, totalFileCount) => {
@@ -43144,12 +43512,19 @@ const isPathInsideDirectory = (childAbsolutePath, parentAbsolutePath) => {
43144
43512
  */
43145
43513
  const materializeSourceTree = (input) => gen(function* () {
43146
43514
  const materializedFiles = [];
43515
+ const unmaterializedFiles = [];
43147
43516
  const resolvedTempDirectory = path.resolve(input.tempDirectory);
43148
43517
  for (const relativePath of input.files) {
43149
43518
  const content = yield* input.readContent(relativePath).pipe(orElseSucceed(() => null));
43150
- if (content === null) continue;
43519
+ if (content === null) {
43520
+ unmaterializedFiles.push(relativePath);
43521
+ continue;
43522
+ }
43151
43523
  const candidateTargetPath = path.resolve(resolvedTempDirectory, relativePath);
43152
- if (!isPathInsideDirectory(candidateTargetPath, resolvedTempDirectory)) continue;
43524
+ if (!isPathInsideDirectory(candidateTargetPath, resolvedTempDirectory)) {
43525
+ unmaterializedFiles.push(relativePath);
43526
+ continue;
43527
+ }
43153
43528
  yield* sync(() => {
43154
43529
  fs.mkdirSync(path.dirname(candidateTargetPath), { recursive: true });
43155
43530
  fs.writeFileSync(candidateTargetPath, content);
@@ -43166,6 +43541,7 @@ const materializeSourceTree = (input) => gen(function* () {
43166
43541
  return {
43167
43542
  tempDirectory: input.tempDirectory,
43168
43543
  materializedFiles,
43544
+ unmaterializedFiles,
43169
43545
  cleanup: () => {
43170
43546
  try {
43171
43547
  fs.rmSync(input.tempDirectory, {
@@ -43341,7 +43717,7 @@ const computeConfigFingerprint = (projectDirectory, version) => {
43341
43717
  /** Display name used in client-facing messages and progress titles. */
43342
43718
  const SERVER_DISPLAY_NAME = "React Doctor";
43343
43719
  /** Server version reported in `serverInfo`; injected at build, `dev` from source. */
43344
- const SERVER_VERSION = "0.8.0";
43720
+ const SERVER_VERSION = "0.8.1";
43345
43721
  /** `Diagnostic.source` shown next to every published diagnostic. */
43346
43722
  const DIAGNOSTIC_SOURCE = "react-doctor";
43347
43723
  /**
@@ -45371,5 +45747,5 @@ const startLanguageServer = () => {
45371
45747
  };
45372
45748
  //#endregion
45373
45749
  export { startLanguageServer };
45374
- !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]="2dde2cd1-f390-5e9f-8370-937973c22f36")}catch(e){}}();
45375
- //# debugId=2dde2cd1-f390-5e9f-8370-937973c22f36
45750
+ !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]="6c3f6717-c00e-5081-bb66-501f2fd8a0d1")}catch(e){}}();
45751
+ //# debugId=6c3f6717-c00e-5081-bb66-501f2fd8a0d1