react-doctor 0.8.1-dev.e6a1557 → 0.8.1-dev.f5f13b8

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
@@ -32883,44 +32883,6 @@ var AmbiguousProjectError = class extends Error {
32883
32883
  }
32884
32884
  };
32885
32885
  const isProjectDiscoveryError = (value) => value instanceof ProjectNotFoundError || value instanceof NoReactDependencyError || value instanceof PackageJsonNotFoundError || value instanceof NotADirectoryError || value instanceof AmbiguousProjectError;
32886
- const isErrnoException = (error) => error instanceof Error && "code" in error;
32887
- const IGNORABLE_READDIR_ERROR_CODES = new Set([
32888
- "EACCES",
32889
- "EPERM",
32890
- "ENOENT",
32891
- "ENOTDIR",
32892
- "EINVAL",
32893
- "ELOOP",
32894
- "ENAMETOOLONG"
32895
- ]);
32896
- const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
32897
- const readDirectoryEntries = (directoryPath) => {
32898
- try {
32899
- return NFS.readdirSync(directoryPath, { withFileTypes: true });
32900
- } catch (error) {
32901
- if (isIgnorableReaddirError(error)) return [];
32902
- throw error;
32903
- }
32904
- };
32905
- const isFile = (filePath) => {
32906
- try {
32907
- return NFS.statSync(filePath).isFile();
32908
- } catch {
32909
- return false;
32910
- }
32911
- };
32912
- const isDirectory = (directoryPath) => {
32913
- try {
32914
- return NFS.statSync(directoryPath).isDirectory();
32915
- } catch {
32916
- return false;
32917
- }
32918
- };
32919
- const isPlainObject = (value) => {
32920
- if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
32921
- const prototype = Object.getPrototypeOf(value);
32922
- return prototype === null || prototype === Object.prototype;
32923
- };
32924
32886
  const SOURCE_FILE_PATTERN = /\.(tsx?|jsx?|mts|mjs)$/;
32925
32887
  const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
32926
32888
  const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
@@ -32961,6 +32923,58 @@ const IGNORED_DIRECTORIES = new Set([
32961
32923
  "storybook-static"
32962
32924
  ]);
32963
32925
  const MILLISECONDS_PER_SECOND = 1e3;
32926
+ const REACT_ROUTER_CAPABILITY_THRESHOLDS = [
32927
+ {
32928
+ capability: "react-router:6.4",
32929
+ major: 6,
32930
+ minor: 4
32931
+ },
32932
+ {
32933
+ capability: "react-router:6.7",
32934
+ major: 6,
32935
+ minor: 7
32936
+ },
32937
+ {
32938
+ capability: "react-router:6.9",
32939
+ major: 6,
32940
+ minor: 9
32941
+ },
32942
+ {
32943
+ capability: "react-router:6.19",
32944
+ major: 6,
32945
+ minor: 19
32946
+ },
32947
+ {
32948
+ capability: "react-router:7",
32949
+ major: 7,
32950
+ minor: 0
32951
+ },
32952
+ {
32953
+ capability: "react-router:7.8",
32954
+ major: 7,
32955
+ minor: 8
32956
+ },
32957
+ {
32958
+ capability: "react-router:7.9",
32959
+ major: 7,
32960
+ minor: 9
32961
+ },
32962
+ {
32963
+ capability: "react-router:7.10",
32964
+ major: 7,
32965
+ minor: 10
32966
+ },
32967
+ {
32968
+ capability: "react-router:7.15",
32969
+ major: 7,
32970
+ minor: 15
32971
+ },
32972
+ {
32973
+ capability: "react-router:8",
32974
+ major: 8,
32975
+ minor: 0
32976
+ }
32977
+ ];
32964
32978
  const SCORE_API_URL = "https://www.react.doctor/api/score";
32965
32979
  const FETCH_TIMEOUT_MS = 1e4;
32966
32980
  const GITHUB_VIEWER_PERMISSION_TIMEOUT_MS = 2e3;
@@ -33102,6 +33116,44 @@ const SUPPLY_CHAIN_OVERLAP_TIMEOUT_MS = 9e4;
33102
33116
  const SUPPLY_CHAIN_CACHE_TTL_MS = 864e5;
33103
33117
  const SUPPLY_CHAIN_CACHE_SUBDIR = "supply-chain";
33104
33118
  const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
33119
+ const isErrnoException = (error) => error instanceof Error && "code" in error;
33120
+ const IGNORABLE_READDIR_ERROR_CODES = new Set([
33121
+ "EACCES",
33122
+ "EPERM",
33123
+ "ENOENT",
33124
+ "ENOTDIR",
33125
+ "EINVAL",
33126
+ "ELOOP",
33127
+ "ENAMETOOLONG"
33128
+ ]);
33129
+ const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
33130
+ const readDirectoryEntries = (directoryPath) => {
33131
+ try {
33132
+ return NFS.readdirSync(directoryPath, { withFileTypes: true });
33133
+ } catch (error) {
33134
+ if (isIgnorableReaddirError(error)) return [];
33135
+ throw error;
33136
+ }
33137
+ };
33138
+ const isFile = (filePath) => {
33139
+ try {
33140
+ return NFS.statSync(filePath).isFile();
33141
+ } catch {
33142
+ return false;
33143
+ }
33144
+ };
33145
+ const isDirectory = (directoryPath) => {
33146
+ try {
33147
+ return NFS.statSync(directoryPath).isDirectory();
33148
+ } catch {
33149
+ return false;
33150
+ }
33151
+ };
33152
+ const isPlainObject = (value) => {
33153
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
33154
+ const prototype = Object.getPrototypeOf(value);
33155
+ return prototype === null || prototype === Object.prototype;
33156
+ };
33105
33157
  const lastSourceMappingUrl = (fileContent) => {
33106
33158
  const lastReference = [...fileContent.matchAll(/\/\/# sourceMappingURL=(\S+)/g)].at(-1);
33107
33159
  return lastReference ? lastReference[1] : null;
@@ -33427,10 +33479,10 @@ const FALLBACK_TSCONFIG_FILENAMES = ["tsconfig.app.json", "tsconfig.build.json"]
33427
33479
  const FRAMEWORK_PACKAGES = {
33428
33480
  next: "nextjs",
33429
33481
  "@tanstack/react-start": "tanstack-start",
33430
- vite: "vite",
33431
- "react-scripts": "cra",
33432
33482
  "@remix-run/react": "remix",
33433
33483
  gatsby: "gatsby",
33484
+ vite: "vite",
33485
+ "react-scripts": "cra",
33434
33486
  expo: "expo",
33435
33487
  "react-native": "react-native"
33436
33488
  };
@@ -33454,11 +33506,17 @@ const NEXT_CONFIG_FILENAMES = [
33454
33506
  ];
33455
33507
  const BABEL_CONFIG_FILENAMES = [
33456
33508
  ".babelrc",
33509
+ ".babelrc.js",
33457
33510
  ".babelrc.json",
33511
+ ".babelrc.cjs",
33512
+ ".babelrc.mjs",
33513
+ ".babelrc.cts",
33458
33514
  "babel.config.js",
33459
33515
  "babel.config.json",
33460
33516
  "babel.config.cjs",
33461
- "babel.config.mjs"
33517
+ "babel.config.mjs",
33518
+ "babel.config.ts",
33519
+ "babel.config.cts"
33462
33520
  ];
33463
33521
  const VITE_CONFIG_FILENAMES = [
33464
33522
  "vite.config.js",
@@ -33470,12 +33528,28 @@ const VITE_CONFIG_FILENAMES = [
33470
33528
  "vitest.config.ts",
33471
33529
  "vitest.config.js"
33472
33530
  ];
33531
+ const RSBUILD_CONFIG_FILENAMES = [
33532
+ "rsbuild.config.ts",
33533
+ "rsbuild.config.js",
33534
+ "rsbuild.config.mts",
33535
+ "rsbuild.config.mjs",
33536
+ "rsbuild.config.cts",
33537
+ "rsbuild.config.cjs"
33538
+ ];
33539
+ const RSPACK_CONFIG_FILENAMES = [
33540
+ "rspack.config.ts",
33541
+ "rspack.config.js",
33542
+ "rspack.config.mts",
33543
+ "rspack.config.mjs",
33544
+ "rspack.config.cts",
33545
+ "rspack.config.cjs"
33546
+ ];
33473
33547
  const EXPO_APP_CONFIG_FILENAMES = [
33474
33548
  "app.json",
33475
33549
  "app.config.js",
33476
33550
  "app.config.ts"
33477
33551
  ];
33478
- const REACT_COMPILER_PACKAGE_REFERENCE_PATTERN = /babel-plugin-react-compiler|react-compiler-runtime|["']react-compiler["']/;
33552
+ const REACT_COMPILER_PACKAGE_REFERENCE_PATTERN = /babel-plugin-react-compiler|react-compiler-runtime|reactCompilerPreset\s*\(|["']react-compiler["']/;
33479
33553
  const REACT_COMPILER_ENABLED_FLAG_PATTERN = /["']?reactCompiler["']?\s*:\s*(?:true\b|\{)/;
33480
33554
  const STATIC_EXPORT_OUTPUT_PATTERN = /(?:^|[^.\w])["']?output["']?\s*:\s*["']export["']/m;
33481
33555
  const hasCompilerPackage = (packageJson, compilerPackages) => {
@@ -33510,6 +33584,8 @@ const detectReactCompiler = (directory, packageJson) => {
33510
33584
  if (hasCompilerInConfigFiles(directory, NEXT_CONFIG_FILENAMES)) return true;
33511
33585
  if (hasCompilerInConfigFiles(directory, BABEL_CONFIG_FILENAMES)) return true;
33512
33586
  if (hasCompilerInConfigFiles(directory, VITE_CONFIG_FILENAMES)) return true;
33587
+ if (hasCompilerInConfigFiles(directory, RSBUILD_CONFIG_FILENAMES)) return true;
33588
+ if (hasCompilerInConfigFiles(directory, RSPACK_CONFIG_FILENAMES)) return true;
33513
33589
  if (hasCompilerInConfigFiles(directory, EXPO_APP_CONFIG_FILENAMES)) return true;
33514
33590
  return hasCompilerPackageInAncestors(directory, REACT_COMPILER_TRANSFORM_PACKAGES);
33515
33591
  };
@@ -33518,7 +33594,7 @@ const detectNextjsStaticExport = (directory) => NEXT_CONFIG_FILENAMES.some((file
33518
33594
  const filePath = Path.join(directory, filename);
33519
33595
  return isFile(filePath) && STATIC_EXPORT_OUTPUT_PATTERN.test(NFS.readFileSync(filePath, "utf-8"));
33520
33596
  });
33521
- const UNRESOLVABLE_PROTOCOL_VERSION = /^(?:file|git|github|https?|link|patch|portal|workspace|npm):/i;
33597
+ const UNRESOLVABLE_PROTOCOL_VERSION = /^(?:catalog|file|git|github|https?|link|patch|portal|workspace|npm):/i;
33522
33598
  const DIST_TAG_VERSION = /^[a-z][a-z0-9._-]*$/i;
33523
33599
  const WILDCARD_VERSION = /^[*xX](?:\.[*xX])*$/;
33524
33600
  const NPM_ALIAS_VERSION = /^npm:(?:@[^/]+\/[^@]+|[^@]+)@(.+)$/i;
@@ -33651,6 +33727,16 @@ const getLowestDependencyMajor = (version) => {
33651
33727
  }
33652
33728
  return lowestMajor;
33653
33729
  };
33730
+ const getDependencyMajorWithinSupportedRange = (version, latestSupportedMajor) => {
33731
+ const normalizedVersion = normalizeDependencyVersion(version);
33732
+ if (normalizedVersion === null) return null;
33733
+ const validRange = import_semver.validRange(normalizedVersion);
33734
+ if (validRange === null) return null;
33735
+ const minimumVersion = import_semver.minVersion(validRange);
33736
+ if (minimumVersion === null || minimumVersion.major > latestSupportedMajor) return null;
33737
+ if (import_semver.intersects(validRange, `>=${latestSupportedMajor + 1}.0.0`)) return null;
33738
+ return minimumVersion.major;
33739
+ };
33654
33740
  const isConcreteDependencyVersion = (version) => {
33655
33741
  const normalizedVersion = normalizeDependencyVersion(version);
33656
33742
  return normalizedVersion !== null && /\d/.test(normalizedVersion);
@@ -33694,9 +33780,18 @@ const parseReactMajorMinor = (reactVersion) => {
33694
33780
  };
33695
33781
  };
33696
33782
  const parseLowerBoundVersion = (versionSpec) => import_semver.validRange(versionSpec) !== null ? import_semver.minVersion(versionSpec) : import_semver.coerce(versionSpec);
33697
- const parseTailwindMajorMinor = (tailwindVersion) => {
33698
- if (typeof tailwindVersion !== "string") return null;
33699
- const trimmed = tailwindVersion.trim();
33783
+ const parseThreeRelease = (threeVersion) => {
33784
+ if (typeof threeVersion !== "string") return null;
33785
+ const normalizedVersion = normalizeDependencyVersion(threeVersion);
33786
+ if (normalizedVersion === null) return null;
33787
+ const lowerBound = parseLowerBoundVersion(normalizedVersion);
33788
+ if (lowerBound === null) return null;
33789
+ if (lowerBound.major > 0) return Number.MAX_SAFE_INTEGER;
33790
+ return lowerBound.minor > 0 ? lowerBound.minor : null;
33791
+ };
33792
+ const parseDependencyMajorMinor = (dependencyVersion) => {
33793
+ if (typeof dependencyVersion !== "string") return null;
33794
+ const trimmed = dependencyVersion.trim();
33700
33795
  if (trimmed.length === 0) return null;
33701
33796
  const lowerBound = parseLowerBoundVersion(trimmed);
33702
33797
  if (lowerBound === null || lowerBound.major <= 0) return null;
@@ -33705,6 +33800,7 @@ const parseTailwindMajorMinor = (tailwindVersion) => {
33705
33800
  minor: lowerBound.minor
33706
33801
  };
33707
33802
  };
33803
+ const parseTailwindMajorMinor = (tailwindVersion) => parseDependencyMajorMinor(tailwindVersion);
33708
33804
  const hasUpperBoundOnlyPeerRange = (range) => {
33709
33805
  if (typeof range !== "string") return false;
33710
33806
  const normalizedRange = normalizeDependencyVersion(range);
@@ -33726,7 +33822,7 @@ const resolveEffectiveReactMajor = (reactVersion, packageJson) => {
33726
33822
  if (peerFloor === null) return hasUpperBoundOnlyPeerRange(peerReactRange) ? null : installedReactMajor;
33727
33823
  return installedReactMajor !== null ? Math.min(installedReactMajor, peerFloor) : peerFloor;
33728
33824
  };
33729
- const isCatalogReference = (version) => version.startsWith("catalog:");
33825
+ const isCatalogReference = (version) => typeof version === "string" && version.startsWith("catalog:");
33730
33826
  const extractCatalogName = (version) => {
33731
33827
  if (!isCatalogReference(version)) return null;
33732
33828
  const name = version.slice(8).trim();
@@ -33876,6 +33972,12 @@ const TAILWIND_ZOD_SECTIONS = [
33876
33972
  "devDependencies",
33877
33973
  "peerDependencies"
33878
33974
  ];
33975
+ const DEPENDENCY_SPEC_SECTIONS = [
33976
+ "dependencies",
33977
+ "devDependencies",
33978
+ "peerDependencies",
33979
+ "optionalDependencies"
33980
+ ];
33879
33981
  const EMPTY_DEPENDENCY_INFO = {
33880
33982
  reactVersion: null,
33881
33983
  tailwindVersion: null,
@@ -33885,7 +33987,7 @@ const EMPTY_DEPENDENCY_INFO = {
33885
33987
  const pickConcreteVersion = (packageJson, packageName, sections) => {
33886
33988
  for (const section of sections) {
33887
33989
  const version = packageJson[section]?.[packageName];
33888
- if (version === void 0) continue;
33990
+ if (typeof version !== "string") continue;
33889
33991
  if (isCatalogReference(version)) return null;
33890
33992
  if (isConcreteDependencyVersion(version)) return version;
33891
33993
  }
@@ -33917,13 +34019,16 @@ const extractDependencyInfo = (packageJson) => {
33917
34019
  };
33918
34020
  };
33919
34021
  const getDependencySpec = (packageJson, packageName) => {
33920
- const spec = packageJson.dependencies?.[packageName] ?? packageJson.devDependencies?.[packageName] ?? packageJson.peerDependencies?.[packageName] ?? packageJson.optionalDependencies?.[packageName];
33921
- return typeof spec === "string" ? spec : null;
34022
+ for (const section of DEPENDENCY_SPEC_SECTIONS) {
34023
+ const spec = packageJson[section]?.[packageName];
34024
+ if (typeof spec === "string") return spec;
34025
+ }
34026
+ return null;
33922
34027
  };
33923
34028
  const getDependencyDeclaration = ({ packageJson, packageName, sections }) => {
33924
34029
  for (const section of sections) {
33925
34030
  const version = packageJson[section]?.[packageName];
33926
- if (version === void 0) continue;
34031
+ if (typeof version !== "string") continue;
33927
34032
  return {
33928
34033
  catalogReference: extractCatalogName(version) ?? null,
33929
34034
  hasDeclaration: true,
@@ -33957,24 +34062,15 @@ const getPreactVersion = (packageJson) => {
33957
34062
  ...packageJson.devDependencies
33958
34063
  }.preact ?? null;
33959
34064
  };
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
- const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, version }) => {
34065
+ const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, sourceDirectory = rootDirectory, sourcePackageJson = rootPackageJson, version }) => {
33974
34066
  if (version === null || !isCatalogReference(version)) return version;
33975
34067
  const catalogName = extractCatalogName(version);
33976
- const resolvedLocalVersion = resolveCatalogVersion(rootPackageJson, packageName, rootDirectory, catalogName);
33977
- if (resolvedLocalVersion) return resolvedLocalVersion;
34068
+ const resolvedSourceVersion = resolveCatalogVersion(sourcePackageJson, packageName, sourceDirectory, catalogName);
34069
+ if (resolvedSourceVersion) return resolvedSourceVersion;
34070
+ if (sourceDirectory !== rootDirectory || sourcePackageJson !== rootPackageJson) {
34071
+ const resolvedRootVersion = resolveCatalogVersion(rootPackageJson, packageName, rootDirectory, catalogName);
34072
+ if (resolvedRootVersion) return resolvedRootVersion;
34073
+ }
33978
34074
  const monorepoRoot = findMonorepoRoot(rootDirectory);
33979
34075
  if (!monorepoRoot) return version;
33980
34076
  const monorepoPackageJsonPath = Path.join(monorepoRoot, "package.json");
@@ -34172,11 +34268,84 @@ const listWorkspacePackages = (rootDirectory) => {
34172
34268
  }
34173
34269
  return packages;
34174
34270
  };
34271
+ const PREFERRED_DEPENDENCY_SECTIONS = [
34272
+ "dependencies",
34273
+ "peerDependencies",
34274
+ "devDependencies"
34275
+ ];
34276
+ const getPreferredDependencyVersion = ({ packageJson, packageNames }) => {
34277
+ for (const packageName of packageNames) {
34278
+ const declaration = getDependencyDeclaration({
34279
+ packageJson,
34280
+ packageName,
34281
+ sections: PREFERRED_DEPENDENCY_SECTIONS
34282
+ });
34283
+ if (declaration.version !== null) return declaration.version;
34284
+ }
34285
+ return null;
34286
+ };
34287
+ const TANSTACK_REACT_QUERY_PACKAGES = ["@tanstack/react-query", "react-query"];
34288
+ const getTanStackQueryVersion = (packageJson) => {
34289
+ return getPreferredDependencyVersion({
34290
+ packageJson,
34291
+ packageNames: TANSTACK_REACT_QUERY_PACKAGES
34292
+ });
34293
+ };
34294
+ const STYLED_COMPONENTS_PACKAGES = ["styled-components"];
34295
+ const getStyledComponentsVersion = (packageJson) => {
34296
+ return getPreferredDependencyVersion({
34297
+ packageJson,
34298
+ packageNames: STYLED_COMPONENTS_PACKAGES
34299
+ });
34300
+ };
34301
+ const I18N_PACKAGES = [
34302
+ "i18next",
34303
+ "react-i18next",
34304
+ "next-i18next",
34305
+ "react-intl",
34306
+ "next-intl",
34307
+ "use-intl",
34308
+ "@formatjs/intl",
34309
+ "@lingui/core",
34310
+ "@lingui/react",
34311
+ "typesafe-i18n",
34312
+ "@tolgee/react",
34313
+ "react-intl-universal"
34314
+ ];
34315
+ const hasI18nDependency = (packageJson) => {
34316
+ const allDependencies = {
34317
+ ...packageJson.peerDependencies,
34318
+ ...packageJson.dependencies,
34319
+ ...packageJson.devDependencies,
34320
+ ...packageJson.optionalDependencies
34321
+ };
34322
+ return I18N_PACKAGES.some((packageName) => allDependencies[packageName] !== void 0);
34323
+ };
34175
34324
  const REANIMATED_DEPENDENCY_NAME = "react-native-reanimated";
34176
34325
  const MOBX_REACT_PACKAGE_NAME = "mobx-react";
34177
34326
  const MOBX_REACT_LITE_PACKAGE_NAME = "mobx-react-lite";
34178
34327
  const MOBX_STATE_TREE_PACKAGE_NAME = "mobx-state-tree";
34179
34328
  const MOBX_REACT_OBSERVER_PACKAGE_NAME = "mobx-react-observer";
34329
+ const REACT_THREE_FIBER_DEPENDENCY_NAMES = ["@react-three/fiber", "react-three-fiber"];
34330
+ const REACT_THREE_FIBER_SECTIONS = [
34331
+ "dependencies",
34332
+ "peerDependencies",
34333
+ "optionalDependencies",
34334
+ "devDependencies"
34335
+ ];
34336
+ const THREE_DEPENDENCY_SECTIONS = [
34337
+ "dependencies",
34338
+ "peerDependencies",
34339
+ "optionalDependencies",
34340
+ "devDependencies"
34341
+ ];
34342
+ const REACT_THREE_FIBER_ECOSYSTEM_DEPENDENCY_NAMES = [...REACT_THREE_FIBER_DEPENDENCY_NAMES, "@react-three/drei"];
34343
+ const THREE_DEPENDENCY_NAMES = [...REACT_THREE_FIBER_ECOSYSTEM_DEPENDENCY_NAMES, "three"];
34344
+ const REACT_ROUTER_DEPENDENCY_NAMES = [
34345
+ "@react-router/dev",
34346
+ "react-router-dom",
34347
+ "react-router"
34348
+ ];
34180
34349
  const SHOPIFY_FLASH_LIST_PACKAGE_NAME = "@shopify/flash-list";
34181
34350
  const resolveWorkspaceDependencyVersion = ({ concreteVersion, packageName, rootDirectory, rootPackageJson, sections, workspaceDirectory, workspacePackageJson }) => {
34182
34351
  const dependencyDeclaration = getDependencyDeclaration({
@@ -34187,7 +34356,7 @@ const resolveWorkspaceDependencyVersion = ({ concreteVersion, packageName, rootD
34187
34356
  if (!dependencyDeclaration.hasDeclaration) return null;
34188
34357
  return concreteVersion ?? resolveCatalogVersion(workspacePackageJson, packageName, workspaceDirectory, dependencyDeclaration.catalogReference) ?? resolveCatalogVersion(rootPackageJson, packageName, rootDirectory, dependencyDeclaration.catalogReference);
34189
34358
  };
34190
- const shouldReplaceReactVersion = (currentVersion, nextVersion) => {
34359
+ const shouldReplaceWithLowerMajor = (currentVersion, nextVersion) => {
34191
34360
  if (!currentVersion) return true;
34192
34361
  const currentMajor = parseReactMajor(currentVersion);
34193
34362
  const nextMajor = parseReactMajor(nextVersion);
@@ -34206,6 +34375,59 @@ const shouldReplaceSupportedDependencyFact = (currentFact, nextFact, latestSuppo
34206
34375
  if (nextMajor > latestSupportedMajor) return true;
34207
34376
  return nextMajor < currentMajor;
34208
34377
  };
34378
+ const shouldReplaceStyledComponentsVersion = (currentVersion, nextVersion) => {
34379
+ if (!currentVersion) return true;
34380
+ const currentMajor = getLowestDependencyMajor(currentVersion);
34381
+ const nextMajor = getLowestDependencyMajor(nextVersion);
34382
+ if (currentMajor === null) return nextMajor !== null && nextMajor < 6;
34383
+ if (nextMajor === null) return currentMajor >= 6;
34384
+ return nextMajor < currentMajor;
34385
+ };
34386
+ const selectOldestDependencyVersion = (currentVersion, nextVersion) => {
34387
+ if (currentVersion === null || nextVersion === null) return null;
34388
+ const current = parseDependencyMajorMinor(currentVersion);
34389
+ const next = parseDependencyMajorMinor(nextVersion);
34390
+ if (current === null) return currentVersion;
34391
+ if (next === null) return nextVersion;
34392
+ if (next.major !== current.major) return next.major < current.major ? nextVersion : currentVersion;
34393
+ return next.minor < current.minor ? nextVersion : currentVersion;
34394
+ };
34395
+ const shouldReplaceMobxFact = (currentFact, nextFact) => {
34396
+ if (currentFact.sourceDirectory === null) return true;
34397
+ if (currentFact.version === null) return false;
34398
+ if (nextFact.version === null) return true;
34399
+ const currentMajor = getDependencyMajorWithinSupportedRange(currentFact.version, 6);
34400
+ const nextMajor = getDependencyMajorWithinSupportedRange(nextFact.version, 6);
34401
+ if (currentMajor === null) return false;
34402
+ if (nextMajor === null) return true;
34403
+ return selectOldestDependencyVersion(currentFact.version, nextFact.version) === nextFact.version;
34404
+ };
34405
+ const collectBindingVersion = (facts, packageJson, directory, packageName) => {
34406
+ const version = getDependencySpec(packageJson, packageName);
34407
+ if (version === null) return;
34408
+ const resolvedVersion = resolveCatalogBackedDependencyVersion({
34409
+ rootDirectory: directory,
34410
+ rootPackageJson: packageJson,
34411
+ packageName,
34412
+ version
34413
+ });
34414
+ if (packageName === MOBX_REACT_PACKAGE_NAME) {
34415
+ facts.mobxReactVersion = facts.hasMobxReact ? selectOldestDependencyVersion(facts.mobxReactVersion, resolvedVersion) : resolvedVersion;
34416
+ facts.hasMobxReact = true;
34417
+ return;
34418
+ }
34419
+ facts.mobxReactLiteVersion = facts.hasMobxReactLite ? selectOldestDependencyVersion(facts.mobxReactLiteVersion, resolvedVersion) : resolvedVersion;
34420
+ facts.hasMobxReactLite = true;
34421
+ };
34422
+ const shouldReplaceReactRouterVersion = (currentVersion, nextVersion) => {
34423
+ if (currentVersion === null) return true;
34424
+ const current = parseReactMajorMinor(currentVersion);
34425
+ const next = parseReactMajorMinor(nextVersion);
34426
+ if (current === null) return next !== null;
34427
+ if (next === null) return false;
34428
+ if (next.major !== current.major) return next.major < current.major;
34429
+ return next.minor < current.minor;
34430
+ };
34209
34431
  const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, rootPackageJson) => {
34210
34432
  if (facts.expo.version === null) {
34211
34433
  const spec = getDependencySpec(packageJson, "expo");
@@ -34221,6 +34443,23 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
34221
34443
  sourceDirectory: directory
34222
34444
  };
34223
34445
  }
34446
+ for (const packageName of REACT_ROUTER_DEPENDENCY_NAMES) {
34447
+ const resolvedSpec = resolveCatalogBackedDependencyVersion({
34448
+ rootDirectory,
34449
+ rootPackageJson,
34450
+ sourceDirectory: directory,
34451
+ sourcePackageJson: packageJson,
34452
+ packageName,
34453
+ version: getDependencySpec(packageJson, packageName)
34454
+ });
34455
+ if (resolvedSpec === null || !shouldReplaceReactRouterVersion(facts.reactRouter.version, resolvedSpec)) continue;
34456
+ facts.reactRouter = {
34457
+ version: resolvedSpec,
34458
+ sourceDirectory: directory,
34459
+ packageName
34460
+ };
34461
+ }
34462
+ facts.hasReactRouterFramework = facts.hasReactRouterFramework || getDependencySpec(packageJson, "@react-router/dev") !== null;
34224
34463
  if (facts.shopifyFlashList.version === null) {
34225
34464
  const spec = getDependencySpec(packageJson, SHOPIFY_FLASH_LIST_PACKAGE_NAME);
34226
34465
  if (spec !== null) facts.shopifyFlashList = {
@@ -34239,10 +34478,10 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
34239
34478
  }),
34240
34479
  sourceDirectory: directory
34241
34480
  };
34242
- if (shouldReplaceSupportedDependencyFact(facts.mobx, nextMobxFact, 6)) facts.mobx = nextMobxFact;
34481
+ if (shouldReplaceMobxFact(facts.mobx, nextMobxFact)) facts.mobx = nextMobxFact;
34243
34482
  }
34244
- facts.hasMobxReact = facts.hasMobxReact || getDependencySpec(packageJson, MOBX_REACT_PACKAGE_NAME) !== null;
34245
- facts.hasMobxReactLite = facts.hasMobxReactLite || getDependencySpec(packageJson, MOBX_REACT_LITE_PACKAGE_NAME) !== null;
34483
+ collectBindingVersion(facts, packageJson, directory, MOBX_REACT_PACKAGE_NAME);
34484
+ collectBindingVersion(facts, packageJson, directory, MOBX_REACT_LITE_PACKAGE_NAME);
34246
34485
  facts.hasMobxStateTree = facts.hasMobxStateTree || getDependencySpec(packageJson, MOBX_STATE_TREE_PACKAGE_NAME) !== null;
34247
34486
  facts.hasMobxReactObserver = facts.hasMobxReactObserver || getDependencySpec(packageJson, MOBX_REACT_OBSERVER_PACKAGE_NAME) !== null;
34248
34487
  const zustandSpec = getDependencySpec(packageJson, "zustand");
@@ -34266,6 +34505,52 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
34266
34505
  const spec = getDependencySpec(packageJson, "valtio");
34267
34506
  if (spec !== null) facts.valtioVersion = spec;
34268
34507
  }
34508
+ facts.tanstackQueryVersion ??= getTanStackQueryVersion(packageJson);
34509
+ const styledComponentsVersion = resolveCatalogBackedDependencyVersion({
34510
+ rootDirectory: directory,
34511
+ rootPackageJson: packageJson,
34512
+ packageName: "styled-components",
34513
+ version: getStyledComponentsVersion(packageJson)
34514
+ });
34515
+ if (styledComponentsVersion && shouldReplaceStyledComponentsVersion(facts.styledComponentsVersion, styledComponentsVersion)) facts.styledComponentsVersion = styledComponentsVersion;
34516
+ facts.hasI18nLibrary = facts.hasI18nLibrary || hasI18nDependency(packageJson);
34517
+ for (const packageName of REACT_THREE_FIBER_DEPENDENCY_NAMES) {
34518
+ const version = resolveCatalogBackedDependencyVersion({
34519
+ rootDirectory,
34520
+ rootPackageJson,
34521
+ sourceDirectory: directory,
34522
+ sourcePackageJson: packageJson,
34523
+ packageName,
34524
+ version: getDependencyDeclaration({
34525
+ packageName,
34526
+ packageJson,
34527
+ sections: REACT_THREE_FIBER_SECTIONS
34528
+ }).version
34529
+ });
34530
+ if (version === null) continue;
34531
+ if (shouldReplaceWithLowerMajor(facts.reactThreeFiber.version, version)) facts.reactThreeFiber = {
34532
+ packageName,
34533
+ version,
34534
+ sourceDirectory: directory
34535
+ };
34536
+ }
34537
+ const threeVersion = resolveCatalogBackedDependencyVersion({
34538
+ rootDirectory,
34539
+ rootPackageJson,
34540
+ sourceDirectory: directory,
34541
+ sourcePackageJson: packageJson,
34542
+ packageName: "three",
34543
+ version: getDependencyDeclaration({
34544
+ packageName: "three",
34545
+ packageJson,
34546
+ sections: THREE_DEPENDENCY_SECTIONS
34547
+ }).version
34548
+ });
34549
+ if (threeVersion !== null) {
34550
+ const currentRelease = parseThreeRelease(facts.threeVersion);
34551
+ const nextRelease = parseThreeRelease(threeVersion);
34552
+ if (facts.threeVersion === null || nextRelease !== null && (currentRelease === null || nextRelease < currentRelease)) facts.threeVersion = threeVersion;
34553
+ }
34269
34554
  facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
34270
34555
  facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
34271
34556
  facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
@@ -34287,6 +34572,8 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
34287
34572
  if (currentRemotionMajorVersion === null || remotionMajorVersion < currentRemotionMajorVersion) facts.remotionVersion = resolvedRemotionVersion;
34288
34573
  }
34289
34574
  }
34575
+ facts.hasThree = facts.hasThree || THREE_DEPENDENCY_NAMES.some((dependencyName) => getDependencySpec(packageJson, dependencyName) !== null);
34576
+ facts.hasReactThreeFiber = facts.hasReactThreeFiber || REACT_THREE_FIBER_ECOSYSTEM_DEPENDENCY_NAMES.some((dependencyName) => getDependencySpec(packageJson, dependencyName) !== null);
34290
34577
  };
34291
34578
  const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGroup }) => {
34292
34579
  const facts = {
@@ -34302,6 +34589,11 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34302
34589
  version: null,
34303
34590
  sourceDirectory: null
34304
34591
  },
34592
+ reactRouter: {
34593
+ version: null,
34594
+ sourceDirectory: null,
34595
+ packageName: null
34596
+ },
34305
34597
  shopifyFlashList: {
34306
34598
  version: null,
34307
34599
  sourceDirectory: null
@@ -34312,26 +34604,40 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34312
34604
  sourceDirectory: null
34313
34605
  },
34314
34606
  hasMobxReact: false,
34607
+ mobxReactVersion: null,
34315
34608
  hasMobxReactLite: false,
34609
+ mobxReactLiteVersion: null,
34316
34610
  hasMobxStateTree: false,
34317
34611
  hasMobxReactObserver: false,
34318
34612
  zustand: {
34319
34613
  version: null,
34320
34614
  sourceDirectory: null
34321
34615
  },
34616
+ tanstackQueryVersion: null,
34617
+ styledComponentsVersion: null,
34618
+ hasI18nLibrary: false,
34322
34619
  hasReactNativeAwarePackage: false,
34323
34620
  hasReanimatedAwarePackage: false,
34324
34621
  hasSsrDependency: false,
34325
34622
  hasRemotionDependency: false,
34326
34623
  hasUnknownRemotionVersion: false,
34327
34624
  remotionVersion: null,
34625
+ hasThree: false,
34626
+ threeVersion: null,
34627
+ hasReactThreeFiber: false,
34628
+ reactThreeFiber: {
34629
+ packageName: null,
34630
+ version: null,
34631
+ sourceDirectory: null
34632
+ },
34633
+ hasReactRouterFramework: false,
34328
34634
  reanimatedVersion: null
34329
34635
  };
34330
34636
  evaluateManifestFacts(facts, rootPackageJson, rootDirectory, rootDirectory, rootPackageJson);
34331
34637
  let isReactGroupSettled = !collectReactGroup;
34332
34638
  const visitedDirectories = /* @__PURE__ */ new Set();
34333
34639
  for (const pattern of getWorkspacePatterns(rootDirectory, rootPackageJson)) {
34334
- const directories = [...resolveWorkspaceDirectories(rootDirectory, pattern)].sort();
34640
+ const directories = resolveWorkspaceDirectories(rootDirectory, pattern).toSorted();
34335
34641
  for (const workspaceDirectory of directories) {
34336
34642
  if (visitedDirectories.has(workspaceDirectory)) continue;
34337
34643
  visitedDirectories.add(workspaceDirectory);
@@ -34367,7 +34673,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34367
34673
  workspaceDirectory,
34368
34674
  workspacePackageJson
34369
34675
  });
34370
- if (reactVersion && shouldReplaceReactVersion(facts.reactVersion, reactVersion)) facts.reactVersion = reactVersion;
34676
+ if (reactVersion && shouldReplaceWithLowerMajor(facts.reactVersion, reactVersion)) facts.reactVersion = reactVersion;
34371
34677
  if (tailwindVersion && !facts.tailwindVersion) facts.tailwindVersion = tailwindVersion;
34372
34678
  if (zodVersion && !facts.zodVersion) facts.zodVersion = zodVersion;
34373
34679
  const settledReactMajor = parseReactMajor(facts.reactVersion);
@@ -34563,7 +34869,9 @@ const discoverProjectWithoutPackageJson = (directory) => {
34563
34869
  mobxVersion: null,
34564
34870
  mobxMajorVersion: null,
34565
34871
  hasMobxReact: false,
34872
+ mobxReactVersion: null,
34566
34873
  hasMobxReactLite: false,
34874
+ mobxReactLiteVersion: null,
34567
34875
  hasMobxStateTree: false,
34568
34876
  hasMobxReactObserver: false,
34569
34877
  zustandVersion: null,
@@ -34578,12 +34886,23 @@ const discoverProjectWithoutPackageJson = (directory) => {
34578
34886
  hasRemotion: false,
34579
34887
  remotionVersion: null,
34580
34888
  remotionMajorVersion: null,
34889
+ hasI18nLibrary: false,
34890
+ tanstackQueryVersion: null,
34891
+ styledComponentsVersion: null,
34892
+ hasThree: false,
34893
+ threeVersion: null,
34894
+ threeRelease: null,
34895
+ hasReactThreeFiber: false,
34896
+ reactThreeFiberVersion: null,
34897
+ reactThreeFiberMajorVersion: null,
34581
34898
  hasSsrDependency: false,
34582
34899
  preactVersion: null,
34583
34900
  preactMajorVersion: null,
34584
34901
  hasReactNativeWorkspace: false,
34585
34902
  nextjsVersion: null,
34586
34903
  nextjsMajorVersion: null,
34904
+ reactRouterVersion: null,
34905
+ hasReactRouterFramework: false,
34587
34906
  expoVersion: null,
34588
34907
  shopifyFlashListVersion: null,
34589
34908
  shopifyFlashListMajorVersion: null,
@@ -34702,8 +35021,27 @@ const discoverProject = (directory) => {
34702
35021
  packageName: "mobx",
34703
35022
  version: workspaceFacts.mobx.version
34704
35023
  });
35024
+ const reactRouterVersion = workspaceFacts.reactRouter.packageName === null ? null : resolveCatalogBackedDependencyVersion({
35025
+ rootDirectory: directory,
35026
+ rootPackageJson: packageJson,
35027
+ packageName: workspaceFacts.reactRouter.packageName,
35028
+ version: workspaceFacts.reactRouter.version
35029
+ });
34705
35030
  const preactVersion = getPreactVersion(packageJson);
34706
35031
  const remotionVersion = workspaceFacts.remotionVersion;
35032
+ const tanstackQueryVersion = getTanStackQueryVersion(packageJson) ?? workspaceFacts.tanstackQueryVersion;
35033
+ const reactThreeFiberVersion = workspaceFacts.reactThreeFiber.packageName ? resolveCatalogBackedDependencyVersion({
35034
+ rootDirectory: directory,
35035
+ rootPackageJson: packageJson,
35036
+ packageName: workspaceFacts.reactThreeFiber.packageName,
35037
+ version: workspaceFacts.reactThreeFiber.version
35038
+ }) : null;
35039
+ const threeVersion = resolveCatalogBackedDependencyVersion({
35040
+ rootDirectory: directory,
35041
+ rootPackageJson: packageJson,
35042
+ packageName: "three",
35043
+ version: workspaceFacts.threeVersion
35044
+ });
34707
35045
  const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
34708
35046
  const projectInfo = {
34709
35047
  rootDirectory: directory,
@@ -34714,9 +35052,11 @@ const discoverProject = (directory) => {
34714
35052
  zodVersion,
34715
35053
  zodMajorVersion: zodVersion === null ? null : getLowestDependencyMajor(zodVersion),
34716
35054
  mobxVersion,
34717
- mobxMajorVersion: mobxVersion === null ? null : getLowestDependencyMajor(mobxVersion),
35055
+ mobxMajorVersion: mobxVersion === null ? null : getDependencyMajorWithinSupportedRange(mobxVersion, 6),
34718
35056
  hasMobxReact: workspaceFacts.hasMobxReact,
35057
+ mobxReactVersion: workspaceFacts.mobxReactVersion,
34719
35058
  hasMobxReactLite: workspaceFacts.hasMobxReactLite,
35059
+ mobxReactLiteVersion: workspaceFacts.mobxReactLiteVersion,
34720
35060
  hasMobxStateTree: workspaceFacts.hasMobxStateTree,
34721
35061
  hasMobxReactObserver: workspaceFacts.hasMobxReactObserver,
34722
35062
  zustandVersion,
@@ -34725,18 +35065,29 @@ const discoverProject = (directory) => {
34725
35065
  hasTypeScript,
34726
35066
  hasReactCompiler: detectReactCompiler(directory, packageJson),
34727
35067
  hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
34728
- hasTanStackQuery: hasTanStackQuery(packageJson),
35068
+ hasTanStackQuery: tanstackQueryVersion !== null,
35069
+ hasI18nLibrary: workspaceFacts.hasI18nLibrary,
35070
+ tanstackQueryVersion,
35071
+ styledComponentsVersion: workspaceFacts.styledComponentsVersion,
34729
35072
  valtioVersion,
34730
35073
  valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
34731
35074
  hasRemotion: workspaceFacts.hasRemotionDependency,
34732
35075
  remotionVersion,
34733
35076
  remotionMajorVersion: remotionVersion === null ? null : getLowestDependencyMajor(remotionVersion),
35077
+ hasThree: workspaceFacts.hasThree,
35078
+ threeVersion,
35079
+ threeRelease: parseThreeRelease(threeVersion),
35080
+ hasReactThreeFiber: workspaceFacts.hasReactThreeFiber,
35081
+ reactThreeFiberVersion,
35082
+ reactThreeFiberMajorVersion: reactThreeFiberVersion === null ? null : getLowestDependencyMajor(reactThreeFiberVersion),
34734
35083
  hasSsrDependency: workspaceFacts.hasSsrDependency,
34735
35084
  preactVersion,
34736
35085
  preactMajorVersion: parseReactMajor(preactVersion),
34737
35086
  hasReactNativeWorkspace,
34738
35087
  nextjsVersion,
34739
35088
  nextjsMajorVersion: nextjsVersion === null ? null : getLowestDependencyMajor(nextjsVersion),
35089
+ reactRouterVersion,
35090
+ hasReactRouterFramework: workspaceFacts.hasReactRouterFramework,
34740
35091
  expoVersion,
34741
35092
  shopifyFlashListVersion,
34742
35093
  shopifyFlashListMajorVersion: shopifyFlashListVersion === null ? null : getLowestDependencyMajor(shopifyFlashListVersion),
@@ -37931,10 +38282,10 @@ const SSR_FRAMEWORKS = new Set([
37931
38282
  "gatsby",
37932
38283
  "tanstack-start"
37933
38284
  ]);
37934
- const addMajorLadder = (capabilities, name, major, earliest, latest) => {
37935
- if (major === null) return;
37936
- const cappedMajor = Math.min(major, latest);
37937
- for (let candidate = earliest; candidate <= cappedMajor; candidate += 1) capabilities.add(`${name}:${candidate}`);
38285
+ const addVersionCapabilityLadder = (capabilities, name, detectedVersion, earliest, latest) => {
38286
+ if (detectedVersion === null) return;
38287
+ const cappedVersion = Math.min(detectedVersion, latest);
38288
+ for (let candidate = earliest; candidate <= cappedVersion; candidate += 1) capabilities.add(`${name}:${candidate}`);
37938
38289
  };
37939
38290
  const buildCapabilities = (project) => {
37940
38291
  const capabilities = /* @__PURE__ */ new Set();
@@ -37947,39 +38298,86 @@ const buildCapabilities = (project) => {
37947
38298
  if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
37948
38299
  if (project.isStaticExport) capabilities.add("nextjs:static-export");
37949
38300
  if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
37950
- addMajorLadder(capabilities, "react", project.reactMajorVersion, 17, 30);
38301
+ if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 16) capabilities.add("nextjs:16");
38302
+ const reactRouterVersion = project.reactRouterVersion ?? null;
38303
+ if (reactRouterVersion !== null) {
38304
+ capabilities.add("react-router");
38305
+ if (project.hasReactRouterFramework === true) capabilities.add("react-router-framework");
38306
+ const detectedVersion = parseReactMajorMinor(reactRouterVersion);
38307
+ if (detectedVersion !== null) {
38308
+ for (const threshold of REACT_ROUTER_CAPABILITY_THRESHOLDS) if (isMajorMinorAtLeast(detectedVersion, threshold)) capabilities.add(threshold.capability);
38309
+ }
38310
+ }
38311
+ addVersionCapabilityLadder(capabilities, "react", project.reactMajorVersion, 17, 30);
37951
38312
  if (project.reactMajorVersion !== null && project.reactMajorVersion >= 19 && isMajorMinorAtLeast(parseReactMajorMinor(project.reactVersion), {
37952
38313
  major: 19,
37953
38314
  minor: 2
37954
38315
  })) capabilities.add("react:19.2");
37955
- if (project.tailwindVersion !== null) capabilities.add("tailwind");
37956
- if (project.tailwindVersion !== null && isMajorMinorAtLeast(parseTailwindMajorMinor(project.tailwindVersion), {
37957
- major: 3,
37958
- minor: 4
37959
- })) capabilities.add("tailwind:3.4");
38316
+ if (project.tailwindVersion !== null) {
38317
+ capabilities.add("tailwind");
38318
+ const tailwindVersion = parseTailwindMajorMinor(project.tailwindVersion);
38319
+ if (isMajorMinorAtLeast(tailwindVersion, {
38320
+ major: 3,
38321
+ minor: 4
38322
+ })) capabilities.add("tailwind:3.4");
38323
+ if (tailwindVersion !== null && isMajorMinorAtLeast(tailwindVersion, {
38324
+ major: 4,
38325
+ minor: 0
38326
+ })) capabilities.add("tailwind:4");
38327
+ }
37960
38328
  if (project.zodVersion !== null) capabilities.add("zod");
37961
38329
  if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
37962
38330
  if (project.mobxVersion !== void 0 && project.mobxVersion !== null || project.hasMobxReact === true || project.hasMobxReactLite === true || project.hasMobxStateTree === true || project.hasMobxReactObserver === true) capabilities.add("mobx");
37963
38331
  if (project.hasMobxReact === true) capabilities.add("mobx-react");
37964
38332
  if (project.hasMobxReactLite === true) capabilities.add("mobx-react-lite");
37965
38333
  if (project.hasMobxReact === true || project.hasMobxReactLite === true) capabilities.add("mobx-react-binding");
38334
+ const mobxReactVersion = parseDependencyMajorMinor(project.mobxReactVersion);
38335
+ const mobxReactLiteVersion = parseDependencyMajorMinor(project.mobxReactLiteVersion);
38336
+ const hasMobxReactObserverMemoGuard = mobxReactVersion !== null && isMajorMinorAtLeast(mobxReactVersion, {
38337
+ major: 7,
38338
+ minor: 3
38339
+ });
38340
+ const hasMobxReactLiteObserverMemoGuard = mobxReactLiteVersion !== null && isMajorMinorAtLeast(mobxReactLiteVersion, {
38341
+ major: 3,
38342
+ minor: 3
38343
+ });
38344
+ if (hasMobxReactObserverMemoGuard) capabilities.add("mobx-react-observer-memo-guard");
38345
+ if (hasMobxReactLiteObserverMemoGuard) capabilities.add("mobx-react-lite-observer-memo-guard");
38346
+ if (hasMobxReactObserverMemoGuard || hasMobxReactLiteObserverMemoGuard) capabilities.add("mobx-react-binding-observer-memo-guard");
37966
38347
  if (project.hasMobxStateTree === true) capabilities.add("mobx-state-tree");
37967
38348
  if (project.hasMobxReactObserver === true) capabilities.add("mobx-react-observer");
37968
- if (project.mobxMajorVersion !== void 0 && project.mobxMajorVersion !== null && project.mobxMajorVersion >= 4 && project.mobxMajorVersion <= 6) addMajorLadder(capabilities, "mobx", project.mobxMajorVersion, 4, 6);
38349
+ if (project.mobxMajorVersion !== void 0 && project.mobxMajorVersion !== null && project.mobxMajorVersion >= 4 && project.mobxMajorVersion <= 6) addVersionCapabilityLadder(capabilities, "mobx", project.mobxMajorVersion, 4, 6);
38350
+ const mobxVersion = parseDependencyMajorMinor(project.mobxVersion);
38351
+ if (project.mobxMajorVersion === 6 && mobxVersion !== null && isMajorMinorAtLeast(mobxVersion, {
38352
+ major: 6,
38353
+ minor: 10
38354
+ })) capabilities.add("mobx:6.10");
37969
38355
  if (project.zustandVersion !== void 0 && project.zustandVersion !== null) capabilities.add("zustand");
37970
- if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addMajorLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
38356
+ if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addVersionCapabilityLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
37971
38357
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
37972
38358
  if (project.hasReactCompiler) capabilities.add("react-compiler");
37973
- if (project.hasTanStackQuery) capabilities.add("tanstack-query");
38359
+ if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
38360
+ if (project.styledComponentsVersion) {
38361
+ capabilities.add("styled-components");
38362
+ const styledComponentsMajor = getLowestDependencyMajor(project.styledComponentsVersion);
38363
+ if (styledComponentsMajor !== null && styledComponentsMajor >= 6) capabilities.add("styled-components:6");
38364
+ }
38365
+ if (project.hasI18nLibrary) capabilities.add("i18n");
37974
38366
  if (project.valtioVersion !== null) capabilities.add("valtio");
37975
- addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
38367
+ addVersionCapabilityLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
37976
38368
  if (project.hasRemotion) {
37977
38369
  capabilities.add("remotion");
37978
- addMajorLadder(capabilities, "remotion", project.remotionMajorVersion ?? null, 4, 30);
38370
+ addVersionCapabilityLadder(capabilities, "remotion", project.remotionMajorVersion ?? null, 4, 30);
38371
+ }
38372
+ if (project.hasThree || project.hasReactThreeFiber) capabilities.add("three");
38373
+ addVersionCapabilityLadder(capabilities, "three", project.threeRelease ?? null, 145, 250);
38374
+ if (project.hasReactThreeFiber) {
38375
+ capabilities.add("r3f");
38376
+ addVersionCapabilityLadder(capabilities, "r3f", project.reactThreeFiberMajorVersion ?? null, 3, 10);
37979
38377
  }
37980
38378
  if (project.hasTypeScript) capabilities.add("typescript");
37981
38379
  if (project.preactVersion !== null) capabilities.add("preact");
37982
- addMajorLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
38380
+ addVersionCapabilityLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
37983
38381
  if (project.preactVersion !== null && project.reactVersion === null) capabilities.add("pure-preact");
37984
38382
  return capabilities;
37985
38383
  };
@@ -37991,7 +38389,7 @@ const getCapabilities = (project) => {
37991
38389
  capabilitiesByProject.set(project, capabilities);
37992
38390
  return capabilities;
37993
38391
  };
37994
- const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhen) => {
38392
+ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhen, includedTags) => {
37995
38393
  if (requires) {
37996
38394
  for (const capability of requires) if (!capabilities.has(capability)) return false;
37997
38395
  }
@@ -38002,20 +38400,29 @@ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhe
38002
38400
  if (tags) {
38003
38401
  for (const tag of tags) if (ignoredTags.has(tag)) return false;
38004
38402
  }
38403
+ if (includedTags && includedTags.size > 0) {
38404
+ if (!tags?.some((tag) => includedTags.has(tag))) return false;
38405
+ }
38005
38406
  return true;
38006
38407
  };
38408
+ const shouldEnableRuleByDefaultStatus = (options) => options.defaultEnabled !== false || options.hasExplicitOverride === true || options.includeTagDefaults && options.hasIncludedTags;
38007
38409
  const yieldToEventLoop = () => new Promise((resolve) => {
38008
38410
  setImmediate(resolve);
38009
38411
  });
38010
38412
  const createSecurityScanSession = (rootDirectory, options) => {
38011
38413
  const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
38012
38414
  const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
38415
+ const includedTags = options.includedTags ?? /* @__PURE__ */ new Set();
38013
38416
  const enabledScanRules = REACT_DOCTOR_RULES.flatMap((entry) => {
38014
38417
  const rule = entry.rule;
38015
38418
  const scan = rule.scan;
38016
38419
  if (typeof scan !== "function") return [];
38017
- if (rule.defaultEnabled === false) return [];
38018
- if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen)) return [];
38420
+ if (!shouldEnableRuleByDefaultStatus({
38421
+ defaultEnabled: rule.defaultEnabled,
38422
+ includeTagDefaults: options.includeTagDefaults === true,
38423
+ hasIncludedTags: includedTags.size > 0
38424
+ })) return [];
38425
+ if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) return [];
38019
38426
  return [{
38020
38427
  entry,
38021
38428
  scan,
@@ -40001,8 +40408,9 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
40001
40408
  }
40002
40409
  return enabled;
40003
40410
  };
40004
- const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
40005
- const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
40411
+ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
40412
+ const hasIncludedTags = includedTags.size > 0;
40413
+ const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
40006
40414
  const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
40007
40415
  const jsPlugins = [];
40008
40416
  if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
@@ -40017,9 +40425,14 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
40017
40425
  if (rule.scan !== void 0) continue;
40018
40426
  if (customRulesOnly && registryEntry.originallyExternal) continue;
40019
40427
  if (rule.framework !== "global" && !rule.requires) continue;
40020
- if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen)) continue;
40428
+ if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) continue;
40021
40429
  const explicitRuleOverride = resolveRuleSeverityOverride({ ruleKey: registryEntry.key }, severityControls);
40022
- if (rule.defaultEnabled === false && explicitRuleOverride === void 0) continue;
40430
+ if (!shouldEnableRuleByDefaultStatus({
40431
+ defaultEnabled: rule.defaultEnabled,
40432
+ includeTagDefaults,
40433
+ hasIncludedTags,
40434
+ hasExplicitOverride: explicitRuleOverride !== void 0
40435
+ })) continue;
40023
40436
  const severity = resolveRuleSeverityOverride({
40024
40437
  ruleKey: registryEntry.key,
40025
40438
  category: rule.category
@@ -40028,7 +40441,7 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
40028
40441
  enabledReactDoctorRules[registryEntry.key] = severity;
40029
40442
  }
40030
40443
  const userPluginRules = {};
40031
- if (ruleSelection !== "sidecar") for (const userPlugin of userPlugins) {
40444
+ if (ruleSelection !== "sidecar" && !hasIncludedTags) for (const userPlugin of userPlugins) {
40032
40445
  Object.assign(userPluginRules, buildUserPluginRules(userPlugin, severityControls));
40033
40446
  jsPlugins.push(userPlugin.entry);
40034
40447
  }
@@ -40245,6 +40658,19 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
40245
40658
  }
40246
40659
  };
40247
40660
  };
40661
+ const fingerprintCacheByFilePath = /* @__PURE__ */ new Map();
40662
+ const fingerprintFileContents = (filePath, fingerprintLength) => {
40663
+ const fileStats = NFS.statSync(filePath, { bigint: true });
40664
+ const cachedFingerprint = fingerprintCacheByFilePath.get(filePath);
40665
+ if (cachedFingerprint?.modifiedTimeNanoseconds === fileStats.mtimeNs && cachedFingerprint.sizeBytes === fileStats.size) return cachedFingerprint.fingerprint;
40666
+ const fingerprint = crypto.createHash("sha256").update(NFS.readFileSync(filePath)).digest("hex").slice(0, fingerprintLength);
40667
+ fingerprintCacheByFilePath.set(filePath, {
40668
+ fingerprint,
40669
+ modifiedTimeNanoseconds: fileStats.mtimeNs,
40670
+ sizeBytes: fileStats.size
40671
+ });
40672
+ return fingerprint;
40673
+ };
40248
40674
  const bundledRequire = createRequire(import.meta.url);
40249
40675
  const childNodeVersionByBinaryPath = /* @__PURE__ */ new Map();
40250
40676
  const resolveChildNodeVersion = (nodeBinaryPath) => {
@@ -40268,6 +40694,13 @@ const TOOLCHAIN_PACKAGE_SPECIFIERS = [
40268
40694
  "oxlint-plugin-react-doctor/package.json",
40269
40695
  "eslint-plugin-react-hooks/package.json"
40270
40696
  ];
40697
+ const resolvePluginFingerprint = () => {
40698
+ try {
40699
+ return fingerprintFileContents(bundledRequire.resolve("oxlint-plugin-react-doctor"), 16);
40700
+ } catch {
40701
+ return "unresolved";
40702
+ }
40703
+ };
40271
40704
  const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
40272
40705
  const versions = [`node=${resolveChildNodeVersion(nodeBinaryPath)}`];
40273
40706
  for (const specifier of TOOLCHAIN_PACKAGE_SPECIFIERS) try {
@@ -40277,6 +40710,7 @@ const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
40277
40710
  } catch {
40278
40711
  versions.push(`${specifier}=missing`);
40279
40712
  }
40713
+ versions.push(`oxlint-plugin-react-doctor#fingerprint=${resolvePluginFingerprint()}`);
40280
40714
  return versions;
40281
40715
  };
40282
40716
  const esmRequire = createRequire(import.meta.url);
@@ -41752,7 +42186,7 @@ const reactHooksJsPluginDropNote = (error) => {
41752
42186
  * 6. always restore disable directives + clean up the temp dir
41753
42187
  */
41754
42188
  const runOxlint = async (options) => {
41755
- 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;
42189
+ 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;
41756
42190
  const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
41757
42191
  const severityControls = buildRuleSeverityControls(userConfig);
41758
42192
  validateRuleRegistration();
@@ -41766,13 +42200,15 @@ const runOxlint = async (options) => {
41766
42200
  }
41767
42201
  const pluginPath = resolvePluginPath();
41768
42202
  const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
41769
- const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
42203
+ const userPlugins = includedTags.size > 0 ? [] : resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
41770
42204
  const buildConfig = (overrides) => createOxlintConfig({
41771
42205
  pluginPath,
41772
42206
  project,
41773
42207
  customRulesOnly,
41774
42208
  extendsPaths: overrides.extendsPaths,
41775
42209
  ignoredTags,
42210
+ includedTags,
42211
+ includeTagDefaults,
41776
42212
  serverAuthFunctionNames,
41777
42213
  severityControls,
41778
42214
  userPlugins,
@@ -42161,6 +42597,8 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
42161
42597
  respectInlineDisables: input.respectInlineDisables,
42162
42598
  adoptExistingLintConfig: input.adoptExistingLintConfig,
42163
42599
  ignoredTags: input.ignoredTags,
42600
+ includedTags: input.includedTags,
42601
+ includeTagDefaults: input.includeTagDefaults,
42164
42602
  userConfig: input.userConfig ?? null,
42165
42603
  configSourceDirectory: input.configSourceDirectory,
42166
42604
  onPartialFailure: (reason) => {
@@ -43009,7 +43447,9 @@ const runInspect = (input, hooks = {}) => gen(function* () {
43009
43447
  const securityScanFailedRef = yield* make$13(false);
43010
43448
  const securityScanFiber = yield* forkChild(runCollect(applyPerElementPipeline(isDiffMode ? empty$4 : unwrap(tryPromise(() => checkSecurityScanCooperative(scanDirectory, {
43011
43449
  project,
43012
- ignoredTags: input.ignoredTags
43450
+ ignoredTags: input.ignoredTags,
43451
+ includedTags: input.includedTags,
43452
+ includeTagDefaults: input.includeTagDefaults
43013
43453
  })).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), catch_$1(() => set(securityScanFailedRef, true).pipe(as(empty$4))))))).pipe(withSpan("SecurityScan.run")));
43014
43454
  const shouldRunSupplyChain = !isDiffMode || (input.supplyChainManifestChanged ?? false);
43015
43455
  const supplyChainOverlapTimeout = yield* SupplyChainOverlapTimeoutMs;
@@ -43100,6 +43540,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
43100
43540
  respectInlineDisables: input.respectInlineDisables,
43101
43541
  adoptExistingLintConfig: input.adoptExistingLintConfig,
43102
43542
  ignoredTags: input.ignoredTags,
43543
+ includedTags: input.includedTags,
43544
+ includeTagDefaults: input.includeTagDefaults,
43103
43545
  userConfig: resolvedConfig.config ?? void 0,
43104
43546
  configSourceDirectory: resolvedConfig.configSourceDirectory ?? void 0,
43105
43547
  onFileProgress: (scannedFileCount, totalFileCount) => {
@@ -45602,5 +46044,5 @@ const startLanguageServer = () => {
45602
46044
  };
45603
46045
  //#endregion
45604
46046
  export { startLanguageServer };
45605
- !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]="f2369b82-a22a-50e5-b71b-2ceb30eaee9f")}catch(e){}}();
45606
- //# debugId=f2369b82-a22a-50e5-b71b-2ceb30eaee9f
46047
+ !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]="f391589f-4666-5b19-95b9-028be54a868d")}catch(e){}}();
46048
+ //# debugId=f391589f-4666-5b19-95b9-028be54a868d