react-doctor 0.8.1-dev.f4aa821 → 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/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="92325f1f-c593-5b4c-af5a-c8b7177212e1")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c65f1825-0401-518f-840a-c33df84ebafc")}catch(e){}}();
3
3
  import { r as __toESM$1, t as __commonJSMin$1 } from "./chunk-N93fKeF6.js";
4
4
  import { createRequire } from "node:module";
5
5
  import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, FRAMEWORK_TOKENS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
@@ -32854,44 +32854,6 @@ var AmbiguousProjectError = class extends Error {
32854
32854
  }
32855
32855
  };
32856
32856
  const isProjectDiscoveryError = (value) => value instanceof ProjectNotFoundError || value instanceof NoReactDependencyError || value instanceof PackageJsonNotFoundError || value instanceof NotADirectoryError || value instanceof AmbiguousProjectError;
32857
- const isErrnoException = (error) => error instanceof Error && "code" in error;
32858
- const IGNORABLE_READDIR_ERROR_CODES = new Set([
32859
- "EACCES",
32860
- "EPERM",
32861
- "ENOENT",
32862
- "ENOTDIR",
32863
- "EINVAL",
32864
- "ELOOP",
32865
- "ENAMETOOLONG"
32866
- ]);
32867
- const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
32868
- const readDirectoryEntries = (directoryPath) => {
32869
- try {
32870
- return NFS.readdirSync(directoryPath, { withFileTypes: true });
32871
- } catch (error) {
32872
- if (isIgnorableReaddirError(error)) return [];
32873
- throw error;
32874
- }
32875
- };
32876
- const isFile = (filePath) => {
32877
- try {
32878
- return NFS.statSync(filePath).isFile();
32879
- } catch {
32880
- return false;
32881
- }
32882
- };
32883
- const isDirectory = (directoryPath) => {
32884
- try {
32885
- return NFS.statSync(directoryPath).isDirectory();
32886
- } catch {
32887
- return false;
32888
- }
32889
- };
32890
- const isPlainObject = (value) => {
32891
- if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
32892
- const prototype = Object.getPrototypeOf(value);
32893
- return prototype === null || prototype === Object.prototype;
32894
- };
32895
32857
  const SOURCE_FILE_PATTERN = /\.(tsx?|jsx?|mts|mjs)$/;
32896
32858
  const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
32897
32859
  const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
@@ -32932,6 +32894,58 @@ const IGNORED_DIRECTORIES = new Set([
32932
32894
  "storybook-static"
32933
32895
  ]);
32934
32896
  const MILLISECONDS_PER_SECOND = 1e3;
32897
+ const REACT_ROUTER_CAPABILITY_THRESHOLDS = [
32898
+ {
32899
+ capability: "react-router:6.4",
32900
+ major: 6,
32901
+ minor: 4
32902
+ },
32903
+ {
32904
+ capability: "react-router:6.7",
32905
+ major: 6,
32906
+ minor: 7
32907
+ },
32908
+ {
32909
+ capability: "react-router:6.9",
32910
+ major: 6,
32911
+ minor: 9
32912
+ },
32913
+ {
32914
+ capability: "react-router:6.19",
32915
+ major: 6,
32916
+ minor: 19
32917
+ },
32918
+ {
32919
+ capability: "react-router:7",
32920
+ major: 7,
32921
+ minor: 0
32922
+ },
32923
+ {
32924
+ capability: "react-router:7.8",
32925
+ major: 7,
32926
+ minor: 8
32927
+ },
32928
+ {
32929
+ capability: "react-router:7.9",
32930
+ major: 7,
32931
+ minor: 9
32932
+ },
32933
+ {
32934
+ capability: "react-router:7.10",
32935
+ major: 7,
32936
+ minor: 10
32937
+ },
32938
+ {
32939
+ capability: "react-router:7.15",
32940
+ major: 7,
32941
+ minor: 15
32942
+ },
32943
+ {
32944
+ capability: "react-router:8",
32945
+ major: 8,
32946
+ minor: 0
32947
+ }
32948
+ ];
32935
32949
  const SCORE_API_URL = "https://www.react.doctor/api/score";
32936
32950
  const FETCH_TIMEOUT_MS = 1e4;
32937
32951
  const GITHUB_VIEWER_PERMISSION_TIMEOUT_MS = 2e3;
@@ -33050,6 +33064,44 @@ const SUPPLY_CHAIN_OVERLAP_TIMEOUT_MS = 9e4;
33050
33064
  const SUPPLY_CHAIN_CACHE_TTL_MS = 864e5;
33051
33065
  const SUPPLY_CHAIN_CACHE_SUBDIR = "supply-chain";
33052
33066
  const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
33067
+ const isErrnoException = (error) => error instanceof Error && "code" in error;
33068
+ const IGNORABLE_READDIR_ERROR_CODES = new Set([
33069
+ "EACCES",
33070
+ "EPERM",
33071
+ "ENOENT",
33072
+ "ENOTDIR",
33073
+ "EINVAL",
33074
+ "ELOOP",
33075
+ "ENAMETOOLONG"
33076
+ ]);
33077
+ const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
33078
+ const readDirectoryEntries = (directoryPath) => {
33079
+ try {
33080
+ return NFS.readdirSync(directoryPath, { withFileTypes: true });
33081
+ } catch (error) {
33082
+ if (isIgnorableReaddirError(error)) return [];
33083
+ throw error;
33084
+ }
33085
+ };
33086
+ const isFile = (filePath) => {
33087
+ try {
33088
+ return NFS.statSync(filePath).isFile();
33089
+ } catch {
33090
+ return false;
33091
+ }
33092
+ };
33093
+ const isDirectory = (directoryPath) => {
33094
+ try {
33095
+ return NFS.statSync(directoryPath).isDirectory();
33096
+ } catch {
33097
+ return false;
33098
+ }
33099
+ };
33100
+ const isPlainObject = (value) => {
33101
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
33102
+ const prototype = Object.getPrototypeOf(value);
33103
+ return prototype === null || prototype === Object.prototype;
33104
+ };
33053
33105
  const lastSourceMappingUrl = (fileContent) => {
33054
33106
  const lastReference = [...fileContent.matchAll(/\/\/# sourceMappingURL=(\S+)/g)].at(-1);
33055
33107
  return lastReference ? lastReference[1] : null;
@@ -33375,10 +33427,10 @@ const FALLBACK_TSCONFIG_FILENAMES = ["tsconfig.app.json", "tsconfig.build.json"]
33375
33427
  const FRAMEWORK_PACKAGES = {
33376
33428
  next: "nextjs",
33377
33429
  "@tanstack/react-start": "tanstack-start",
33378
- vite: "vite",
33379
- "react-scripts": "cra",
33380
33430
  "@remix-run/react": "remix",
33381
33431
  gatsby: "gatsby",
33432
+ vite: "vite",
33433
+ "react-scripts": "cra",
33382
33434
  expo: "expo",
33383
33435
  "react-native": "react-native"
33384
33436
  };
@@ -33402,11 +33454,17 @@ const NEXT_CONFIG_FILENAMES = [
33402
33454
  ];
33403
33455
  const BABEL_CONFIG_FILENAMES = [
33404
33456
  ".babelrc",
33457
+ ".babelrc.js",
33405
33458
  ".babelrc.json",
33459
+ ".babelrc.cjs",
33460
+ ".babelrc.mjs",
33461
+ ".babelrc.cts",
33406
33462
  "babel.config.js",
33407
33463
  "babel.config.json",
33408
33464
  "babel.config.cjs",
33409
- "babel.config.mjs"
33465
+ "babel.config.mjs",
33466
+ "babel.config.ts",
33467
+ "babel.config.cts"
33410
33468
  ];
33411
33469
  const VITE_CONFIG_FILENAMES = [
33412
33470
  "vite.config.js",
@@ -33418,12 +33476,28 @@ const VITE_CONFIG_FILENAMES = [
33418
33476
  "vitest.config.ts",
33419
33477
  "vitest.config.js"
33420
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
+ ];
33421
33495
  const EXPO_APP_CONFIG_FILENAMES = [
33422
33496
  "app.json",
33423
33497
  "app.config.js",
33424
33498
  "app.config.ts"
33425
33499
  ];
33426
- 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["']/;
33427
33501
  const REACT_COMPILER_ENABLED_FLAG_PATTERN = /["']?reactCompiler["']?\s*:\s*(?:true\b|\{)/;
33428
33502
  const STATIC_EXPORT_OUTPUT_PATTERN = /(?:^|[^.\w])["']?output["']?\s*:\s*["']export["']/m;
33429
33503
  const hasCompilerPackage = (packageJson, compilerPackages) => {
@@ -33458,6 +33532,8 @@ const detectReactCompiler = (directory, packageJson) => {
33458
33532
  if (hasCompilerInConfigFiles(directory, NEXT_CONFIG_FILENAMES)) return true;
33459
33533
  if (hasCompilerInConfigFiles(directory, BABEL_CONFIG_FILENAMES)) return true;
33460
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;
33461
33537
  if (hasCompilerInConfigFiles(directory, EXPO_APP_CONFIG_FILENAMES)) return true;
33462
33538
  return hasCompilerPackageInAncestors(directory, REACT_COMPILER_TRANSFORM_PACKAGES);
33463
33539
  };
@@ -33466,7 +33542,7 @@ const detectNextjsStaticExport = (directory) => NEXT_CONFIG_FILENAMES.some((file
33466
33542
  const filePath = Path.join(directory, filename);
33467
33543
  return isFile(filePath) && STATIC_EXPORT_OUTPUT_PATTERN.test(NFS.readFileSync(filePath, "utf-8"));
33468
33544
  });
33469
- const UNRESOLVABLE_PROTOCOL_VERSION = /^(?:file|git|github|https?|link|patch|portal|workspace|npm):/i;
33545
+ const UNRESOLVABLE_PROTOCOL_VERSION = /^(?:catalog|file|git|github|https?|link|patch|portal|workspace|npm):/i;
33470
33546
  const DIST_TAG_VERSION = /^[a-z][a-z0-9._-]*$/i;
33471
33547
  const WILDCARD_VERSION = /^[*xX](?:\.[*xX])*$/;
33472
33548
  const NPM_ALIAS_VERSION = /^npm:(?:@[^/]+\/[^@]+|[^@]+)@(.+)$/i;
@@ -33599,6 +33675,16 @@ const getLowestDependencyMajor = (version) => {
33599
33675
  }
33600
33676
  return lowestMajor;
33601
33677
  };
33678
+ const getDependencyMajorWithinSupportedRange = (version, latestSupportedMajor) => {
33679
+ const normalizedVersion = normalizeDependencyVersion(version);
33680
+ if (normalizedVersion === null) return null;
33681
+ const validRange = import_semver.validRange(normalizedVersion);
33682
+ if (validRange === null) return null;
33683
+ const minimumVersion = import_semver.minVersion(validRange);
33684
+ if (minimumVersion === null || minimumVersion.major > latestSupportedMajor) return null;
33685
+ if (import_semver.intersects(validRange, `>=${latestSupportedMajor + 1}.0.0`)) return null;
33686
+ return minimumVersion.major;
33687
+ };
33602
33688
  const isConcreteDependencyVersion = (version) => {
33603
33689
  const normalizedVersion = normalizeDependencyVersion(version);
33604
33690
  return normalizedVersion !== null && /\d/.test(normalizedVersion);
@@ -33642,9 +33728,18 @@ const parseReactMajorMinor = (reactVersion) => {
33642
33728
  };
33643
33729
  };
33644
33730
  const parseLowerBoundVersion = (versionSpec) => import_semver.validRange(versionSpec) !== null ? import_semver.minVersion(versionSpec) : import_semver.coerce(versionSpec);
33645
- const parseTailwindMajorMinor = (tailwindVersion) => {
33646
- if (typeof tailwindVersion !== "string") return null;
33647
- const trimmed = tailwindVersion.trim();
33731
+ const parseThreeRelease = (threeVersion) => {
33732
+ if (typeof threeVersion !== "string") return null;
33733
+ const normalizedVersion = normalizeDependencyVersion(threeVersion);
33734
+ if (normalizedVersion === null) return null;
33735
+ const lowerBound = parseLowerBoundVersion(normalizedVersion);
33736
+ if (lowerBound === null) return null;
33737
+ if (lowerBound.major > 0) return Number.MAX_SAFE_INTEGER;
33738
+ return lowerBound.minor > 0 ? lowerBound.minor : null;
33739
+ };
33740
+ const parseDependencyMajorMinor = (dependencyVersion) => {
33741
+ if (typeof dependencyVersion !== "string") return null;
33742
+ const trimmed = dependencyVersion.trim();
33648
33743
  if (trimmed.length === 0) return null;
33649
33744
  const lowerBound = parseLowerBoundVersion(trimmed);
33650
33745
  if (lowerBound === null || lowerBound.major <= 0) return null;
@@ -33653,6 +33748,7 @@ const parseTailwindMajorMinor = (tailwindVersion) => {
33653
33748
  minor: lowerBound.minor
33654
33749
  };
33655
33750
  };
33751
+ const parseTailwindMajorMinor = (tailwindVersion) => parseDependencyMajorMinor(tailwindVersion);
33656
33752
  const hasUpperBoundOnlyPeerRange = (range) => {
33657
33753
  if (typeof range !== "string") return false;
33658
33754
  const normalizedRange = normalizeDependencyVersion(range);
@@ -33674,7 +33770,7 @@ const resolveEffectiveReactMajor = (reactVersion, packageJson) => {
33674
33770
  if (peerFloor === null) return hasUpperBoundOnlyPeerRange(peerReactRange) ? null : installedReactMajor;
33675
33771
  return installedReactMajor !== null ? Math.min(installedReactMajor, peerFloor) : peerFloor;
33676
33772
  };
33677
- const isCatalogReference = (version) => version.startsWith("catalog:");
33773
+ const isCatalogReference = (version) => typeof version === "string" && version.startsWith("catalog:");
33678
33774
  const extractCatalogName = (version) => {
33679
33775
  if (!isCatalogReference(version)) return null;
33680
33776
  const name = version.slice(8).trim();
@@ -33824,6 +33920,12 @@ const TAILWIND_ZOD_SECTIONS = [
33824
33920
  "devDependencies",
33825
33921
  "peerDependencies"
33826
33922
  ];
33923
+ const DEPENDENCY_SPEC_SECTIONS = [
33924
+ "dependencies",
33925
+ "devDependencies",
33926
+ "peerDependencies",
33927
+ "optionalDependencies"
33928
+ ];
33827
33929
  const EMPTY_DEPENDENCY_INFO = {
33828
33930
  reactVersion: null,
33829
33931
  tailwindVersion: null,
@@ -33833,7 +33935,7 @@ const EMPTY_DEPENDENCY_INFO = {
33833
33935
  const pickConcreteVersion = (packageJson, packageName, sections) => {
33834
33936
  for (const section of sections) {
33835
33937
  const version = packageJson[section]?.[packageName];
33836
- if (version === void 0) continue;
33938
+ if (typeof version !== "string") continue;
33837
33939
  if (isCatalogReference(version)) return null;
33838
33940
  if (isConcreteDependencyVersion(version)) return version;
33839
33941
  }
@@ -33865,13 +33967,16 @@ const extractDependencyInfo = (packageJson) => {
33865
33967
  };
33866
33968
  };
33867
33969
  const getDependencySpec = (packageJson, packageName) => {
33868
- const spec = packageJson.dependencies?.[packageName] ?? packageJson.devDependencies?.[packageName] ?? packageJson.peerDependencies?.[packageName] ?? packageJson.optionalDependencies?.[packageName];
33869
- return typeof spec === "string" ? spec : null;
33970
+ for (const section of DEPENDENCY_SPEC_SECTIONS) {
33971
+ const spec = packageJson[section]?.[packageName];
33972
+ if (typeof spec === "string") return spec;
33973
+ }
33974
+ return null;
33870
33975
  };
33871
33976
  const getDependencyDeclaration = ({ packageJson, packageName, sections }) => {
33872
33977
  for (const section of sections) {
33873
33978
  const version = packageJson[section]?.[packageName];
33874
- if (version === void 0) continue;
33979
+ if (typeof version !== "string") continue;
33875
33980
  return {
33876
33981
  catalogReference: extractCatalogName(version) ?? null,
33877
33982
  hasDeclaration: true,
@@ -33905,24 +34010,15 @@ const getPreactVersion = (packageJson) => {
33905
34010
  ...packageJson.devDependencies
33906
34011
  }.preact ?? null;
33907
34012
  };
33908
- const TANSTACK_QUERY_PACKAGES = new Set([
33909
- "@tanstack/react-query",
33910
- "@tanstack/query-core",
33911
- "react-query"
33912
- ]);
33913
- const hasTanStackQuery = (packageJson) => {
33914
- const allDependencies = {
33915
- ...packageJson.peerDependencies,
33916
- ...packageJson.dependencies,
33917
- ...packageJson.devDependencies
33918
- };
33919
- return Object.keys(allDependencies).some((packageName) => TANSTACK_QUERY_PACKAGES.has(packageName));
33920
- };
33921
- const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, version }) => {
34013
+ const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, sourceDirectory = rootDirectory, sourcePackageJson = rootPackageJson, version }) => {
33922
34014
  if (version === null || !isCatalogReference(version)) return version;
33923
34015
  const catalogName = extractCatalogName(version);
33924
- const resolvedLocalVersion = resolveCatalogVersion(rootPackageJson, packageName, rootDirectory, catalogName);
33925
- if (resolvedLocalVersion) return resolvedLocalVersion;
34016
+ const resolvedSourceVersion = resolveCatalogVersion(sourcePackageJson, packageName, sourceDirectory, catalogName);
34017
+ if (resolvedSourceVersion) return resolvedSourceVersion;
34018
+ if (sourceDirectory !== rootDirectory || sourcePackageJson !== rootPackageJson) {
34019
+ const resolvedRootVersion = resolveCatalogVersion(rootPackageJson, packageName, rootDirectory, catalogName);
34020
+ if (resolvedRootVersion) return resolvedRootVersion;
34021
+ }
33926
34022
  const monorepoRoot = findMonorepoRoot(rootDirectory);
33927
34023
  if (!monorepoRoot) return version;
33928
34024
  const monorepoPackageJsonPath = Path.join(monorepoRoot, "package.json");
@@ -34120,7 +34216,84 @@ const listWorkspacePackages = (rootDirectory) => {
34120
34216
  }
34121
34217
  return packages;
34122
34218
  };
34219
+ const PREFERRED_DEPENDENCY_SECTIONS = [
34220
+ "dependencies",
34221
+ "peerDependencies",
34222
+ "devDependencies"
34223
+ ];
34224
+ const getPreferredDependencyVersion = ({ packageJson, packageNames }) => {
34225
+ for (const packageName of packageNames) {
34226
+ const declaration = getDependencyDeclaration({
34227
+ packageJson,
34228
+ packageName,
34229
+ sections: PREFERRED_DEPENDENCY_SECTIONS
34230
+ });
34231
+ if (declaration.version !== null) return declaration.version;
34232
+ }
34233
+ return null;
34234
+ };
34235
+ const TANSTACK_REACT_QUERY_PACKAGES = ["@tanstack/react-query", "react-query"];
34236
+ const getTanStackQueryVersion = (packageJson) => {
34237
+ return getPreferredDependencyVersion({
34238
+ packageJson,
34239
+ packageNames: TANSTACK_REACT_QUERY_PACKAGES
34240
+ });
34241
+ };
34242
+ const STYLED_COMPONENTS_PACKAGES = ["styled-components"];
34243
+ const getStyledComponentsVersion = (packageJson) => {
34244
+ return getPreferredDependencyVersion({
34245
+ packageJson,
34246
+ packageNames: STYLED_COMPONENTS_PACKAGES
34247
+ });
34248
+ };
34249
+ const I18N_PACKAGES = [
34250
+ "i18next",
34251
+ "react-i18next",
34252
+ "next-i18next",
34253
+ "react-intl",
34254
+ "next-intl",
34255
+ "use-intl",
34256
+ "@formatjs/intl",
34257
+ "@lingui/core",
34258
+ "@lingui/react",
34259
+ "typesafe-i18n",
34260
+ "@tolgee/react",
34261
+ "react-intl-universal"
34262
+ ];
34263
+ const hasI18nDependency = (packageJson) => {
34264
+ const allDependencies = {
34265
+ ...packageJson.peerDependencies,
34266
+ ...packageJson.dependencies,
34267
+ ...packageJson.devDependencies,
34268
+ ...packageJson.optionalDependencies
34269
+ };
34270
+ return I18N_PACKAGES.some((packageName) => allDependencies[packageName] !== void 0);
34271
+ };
34123
34272
  const REANIMATED_DEPENDENCY_NAME = "react-native-reanimated";
34273
+ const MOBX_REACT_PACKAGE_NAME = "mobx-react";
34274
+ const MOBX_REACT_LITE_PACKAGE_NAME = "mobx-react-lite";
34275
+ const MOBX_STATE_TREE_PACKAGE_NAME = "mobx-state-tree";
34276
+ const MOBX_REACT_OBSERVER_PACKAGE_NAME = "mobx-react-observer";
34277
+ const REACT_THREE_FIBER_DEPENDENCY_NAMES = ["@react-three/fiber", "react-three-fiber"];
34278
+ const REACT_THREE_FIBER_SECTIONS = [
34279
+ "dependencies",
34280
+ "peerDependencies",
34281
+ "optionalDependencies",
34282
+ "devDependencies"
34283
+ ];
34284
+ const THREE_DEPENDENCY_SECTIONS = [
34285
+ "dependencies",
34286
+ "peerDependencies",
34287
+ "optionalDependencies",
34288
+ "devDependencies"
34289
+ ];
34290
+ const REACT_THREE_FIBER_ECOSYSTEM_DEPENDENCY_NAMES = [...REACT_THREE_FIBER_DEPENDENCY_NAMES, "@react-three/drei"];
34291
+ const THREE_DEPENDENCY_NAMES = [...REACT_THREE_FIBER_ECOSYSTEM_DEPENDENCY_NAMES, "three"];
34292
+ const REACT_ROUTER_DEPENDENCY_NAMES = [
34293
+ "@react-router/dev",
34294
+ "react-router-dom",
34295
+ "react-router"
34296
+ ];
34124
34297
  const SHOPIFY_FLASH_LIST_PACKAGE_NAME = "@shopify/flash-list";
34125
34298
  const resolveWorkspaceDependencyVersion = ({ concreteVersion, packageName, rootDirectory, rootPackageJson, sections, workspaceDirectory, workspacePackageJson }) => {
34126
34299
  const dependencyDeclaration = getDependencyDeclaration({
@@ -34131,7 +34304,7 @@ const resolveWorkspaceDependencyVersion = ({ concreteVersion, packageName, rootD
34131
34304
  if (!dependencyDeclaration.hasDeclaration) return null;
34132
34305
  return concreteVersion ?? resolveCatalogVersion(workspacePackageJson, packageName, workspaceDirectory, dependencyDeclaration.catalogReference) ?? resolveCatalogVersion(rootPackageJson, packageName, rootDirectory, dependencyDeclaration.catalogReference);
34133
34306
  };
34134
- const shouldReplaceReactVersion = (currentVersion, nextVersion) => {
34307
+ const shouldReplaceWithLowerMajor = (currentVersion, nextVersion) => {
34135
34308
  if (!currentVersion) return true;
34136
34309
  const currentMajor = parseReactMajor(currentVersion);
34137
34310
  const nextMajor = parseReactMajor(nextVersion);
@@ -34139,6 +34312,70 @@ const shouldReplaceReactVersion = (currentVersion, nextVersion) => {
34139
34312
  if (nextMajor === null) return false;
34140
34313
  return nextMajor < currentMajor;
34141
34314
  };
34315
+ const shouldReplaceSupportedDependencyFact = (currentFact, nextFact, latestSupportedMajor) => {
34316
+ if (currentFact.version === null) return true;
34317
+ if (nextFact.version === null) return false;
34318
+ const currentMajor = getLowestDependencyMajor(currentFact.version);
34319
+ const nextMajor = getLowestDependencyMajor(nextFact.version);
34320
+ if (currentMajor === null) return false;
34321
+ if (nextMajor === null) return true;
34322
+ if (currentMajor > latestSupportedMajor) return false;
34323
+ if (nextMajor > latestSupportedMajor) return true;
34324
+ return nextMajor < currentMajor;
34325
+ };
34326
+ const shouldReplaceStyledComponentsVersion = (currentVersion, nextVersion) => {
34327
+ if (!currentVersion) return true;
34328
+ const currentMajor = getLowestDependencyMajor(currentVersion);
34329
+ const nextMajor = getLowestDependencyMajor(nextVersion);
34330
+ if (currentMajor === null) return nextMajor !== null && nextMajor < 6;
34331
+ if (nextMajor === null) return currentMajor >= 6;
34332
+ return nextMajor < currentMajor;
34333
+ };
34334
+ const selectOldestDependencyVersion = (currentVersion, nextVersion) => {
34335
+ if (currentVersion === null || nextVersion === null) return null;
34336
+ const current = parseDependencyMajorMinor(currentVersion);
34337
+ const next = parseDependencyMajorMinor(nextVersion);
34338
+ if (current === null) return currentVersion;
34339
+ if (next === null) return nextVersion;
34340
+ if (next.major !== current.major) return next.major < current.major ? nextVersion : currentVersion;
34341
+ return next.minor < current.minor ? nextVersion : currentVersion;
34342
+ };
34343
+ const shouldReplaceMobxFact = (currentFact, nextFact) => {
34344
+ if (currentFact.sourceDirectory === null) return true;
34345
+ if (currentFact.version === null) return false;
34346
+ if (nextFact.version === null) return true;
34347
+ const currentMajor = getDependencyMajorWithinSupportedRange(currentFact.version, 6);
34348
+ const nextMajor = getDependencyMajorWithinSupportedRange(nextFact.version, 6);
34349
+ if (currentMajor === null) return false;
34350
+ if (nextMajor === null) return true;
34351
+ return selectOldestDependencyVersion(currentFact.version, nextFact.version) === nextFact.version;
34352
+ };
34353
+ const collectBindingVersion = (facts, packageJson, directory, packageName) => {
34354
+ const version = getDependencySpec(packageJson, packageName);
34355
+ if (version === null) return;
34356
+ const resolvedVersion = resolveCatalogBackedDependencyVersion({
34357
+ rootDirectory: directory,
34358
+ rootPackageJson: packageJson,
34359
+ packageName,
34360
+ version
34361
+ });
34362
+ if (packageName === MOBX_REACT_PACKAGE_NAME) {
34363
+ facts.mobxReactVersion = facts.hasMobxReact ? selectOldestDependencyVersion(facts.mobxReactVersion, resolvedVersion) : resolvedVersion;
34364
+ facts.hasMobxReact = true;
34365
+ return;
34366
+ }
34367
+ facts.mobxReactLiteVersion = facts.hasMobxReactLite ? selectOldestDependencyVersion(facts.mobxReactLiteVersion, resolvedVersion) : resolvedVersion;
34368
+ facts.hasMobxReactLite = true;
34369
+ };
34370
+ const shouldReplaceReactRouterVersion = (currentVersion, nextVersion) => {
34371
+ if (currentVersion === null) return true;
34372
+ const current = parseReactMajorMinor(currentVersion);
34373
+ const next = parseReactMajorMinor(nextVersion);
34374
+ if (current === null) return next !== null;
34375
+ if (next === null) return false;
34376
+ if (next.major !== current.major) return next.major < current.major;
34377
+ return next.minor < current.minor;
34378
+ };
34142
34379
  const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, rootPackageJson) => {
34143
34380
  if (facts.expo.version === null) {
34144
34381
  const spec = getDependencySpec(packageJson, "expo");
@@ -34154,6 +34391,23 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
34154
34391
  sourceDirectory: directory
34155
34392
  };
34156
34393
  }
34394
+ for (const packageName of REACT_ROUTER_DEPENDENCY_NAMES) {
34395
+ const resolvedSpec = resolveCatalogBackedDependencyVersion({
34396
+ rootDirectory,
34397
+ rootPackageJson,
34398
+ sourceDirectory: directory,
34399
+ sourcePackageJson: packageJson,
34400
+ packageName,
34401
+ version: getDependencySpec(packageJson, packageName)
34402
+ });
34403
+ if (resolvedSpec === null || !shouldReplaceReactRouterVersion(facts.reactRouter.version, resolvedSpec)) continue;
34404
+ facts.reactRouter = {
34405
+ version: resolvedSpec,
34406
+ sourceDirectory: directory,
34407
+ packageName
34408
+ };
34409
+ }
34410
+ facts.hasReactRouterFramework = facts.hasReactRouterFramework || getDependencySpec(packageJson, "@react-router/dev") !== null;
34157
34411
  if (facts.shopifyFlashList.version === null) {
34158
34412
  const spec = getDependencySpec(packageJson, SHOPIFY_FLASH_LIST_PACKAGE_NAME);
34159
34413
  if (spec !== null) facts.shopifyFlashList = {
@@ -34161,6 +34415,36 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
34161
34415
  sourceDirectory: directory
34162
34416
  };
34163
34417
  }
34418
+ const mobxSpec = getDependencySpec(packageJson, "mobx");
34419
+ if (mobxSpec !== null) {
34420
+ const nextMobxFact = {
34421
+ version: resolveCatalogBackedDependencyVersion({
34422
+ rootDirectory: directory,
34423
+ rootPackageJson: packageJson,
34424
+ packageName: "mobx",
34425
+ version: mobxSpec
34426
+ }),
34427
+ sourceDirectory: directory
34428
+ };
34429
+ if (shouldReplaceMobxFact(facts.mobx, nextMobxFact)) facts.mobx = nextMobxFact;
34430
+ }
34431
+ collectBindingVersion(facts, packageJson, directory, MOBX_REACT_PACKAGE_NAME);
34432
+ collectBindingVersion(facts, packageJson, directory, MOBX_REACT_LITE_PACKAGE_NAME);
34433
+ facts.hasMobxStateTree = facts.hasMobxStateTree || getDependencySpec(packageJson, MOBX_STATE_TREE_PACKAGE_NAME) !== null;
34434
+ facts.hasMobxReactObserver = facts.hasMobxReactObserver || getDependencySpec(packageJson, MOBX_REACT_OBSERVER_PACKAGE_NAME) !== null;
34435
+ const zustandSpec = getDependencySpec(packageJson, "zustand");
34436
+ if (zustandSpec !== null) {
34437
+ const nextZustandFact = {
34438
+ version: resolveCatalogBackedDependencyVersion({
34439
+ rootDirectory: directory,
34440
+ rootPackageJson: packageJson,
34441
+ packageName: "zustand",
34442
+ version: zustandSpec
34443
+ }),
34444
+ sourceDirectory: directory
34445
+ };
34446
+ if (shouldReplaceSupportedDependencyFact(facts.zustand, nextZustandFact, 5)) facts.zustand = nextZustandFact;
34447
+ }
34164
34448
  if (facts.reanimatedVersion === null) {
34165
34449
  const spec = getDependencySpec(packageJson, REANIMATED_DEPENDENCY_NAME);
34166
34450
  if (spec !== null) facts.reanimatedVersion = spec;
@@ -34169,6 +34453,52 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
34169
34453
  const spec = getDependencySpec(packageJson, "valtio");
34170
34454
  if (spec !== null) facts.valtioVersion = spec;
34171
34455
  }
34456
+ facts.tanstackQueryVersion ??= getTanStackQueryVersion(packageJson);
34457
+ const styledComponentsVersion = resolveCatalogBackedDependencyVersion({
34458
+ rootDirectory: directory,
34459
+ rootPackageJson: packageJson,
34460
+ packageName: "styled-components",
34461
+ version: getStyledComponentsVersion(packageJson)
34462
+ });
34463
+ if (styledComponentsVersion && shouldReplaceStyledComponentsVersion(facts.styledComponentsVersion, styledComponentsVersion)) facts.styledComponentsVersion = styledComponentsVersion;
34464
+ facts.hasI18nLibrary = facts.hasI18nLibrary || hasI18nDependency(packageJson);
34465
+ for (const packageName of REACT_THREE_FIBER_DEPENDENCY_NAMES) {
34466
+ const version = resolveCatalogBackedDependencyVersion({
34467
+ rootDirectory,
34468
+ rootPackageJson,
34469
+ sourceDirectory: directory,
34470
+ sourcePackageJson: packageJson,
34471
+ packageName,
34472
+ version: getDependencyDeclaration({
34473
+ packageName,
34474
+ packageJson,
34475
+ sections: REACT_THREE_FIBER_SECTIONS
34476
+ }).version
34477
+ });
34478
+ if (version === null) continue;
34479
+ if (shouldReplaceWithLowerMajor(facts.reactThreeFiber.version, version)) facts.reactThreeFiber = {
34480
+ packageName,
34481
+ version,
34482
+ sourceDirectory: directory
34483
+ };
34484
+ }
34485
+ const threeVersion = resolveCatalogBackedDependencyVersion({
34486
+ rootDirectory,
34487
+ rootPackageJson,
34488
+ sourceDirectory: directory,
34489
+ sourcePackageJson: packageJson,
34490
+ packageName: "three",
34491
+ version: getDependencyDeclaration({
34492
+ packageName: "three",
34493
+ packageJson,
34494
+ sections: THREE_DEPENDENCY_SECTIONS
34495
+ }).version
34496
+ });
34497
+ if (threeVersion !== null) {
34498
+ const currentRelease = parseThreeRelease(facts.threeVersion);
34499
+ const nextRelease = parseThreeRelease(threeVersion);
34500
+ if (facts.threeVersion === null || nextRelease !== null && (currentRelease === null || nextRelease < currentRelease)) facts.threeVersion = threeVersion;
34501
+ }
34172
34502
  facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
34173
34503
  facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
34174
34504
  facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
@@ -34190,6 +34520,8 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
34190
34520
  if (currentRemotionMajorVersion === null || remotionMajorVersion < currentRemotionMajorVersion) facts.remotionVersion = resolvedRemotionVersion;
34191
34521
  }
34192
34522
  }
34523
+ facts.hasThree = facts.hasThree || THREE_DEPENDENCY_NAMES.some((dependencyName) => getDependencySpec(packageJson, dependencyName) !== null);
34524
+ facts.hasReactThreeFiber = facts.hasReactThreeFiber || REACT_THREE_FIBER_ECOSYSTEM_DEPENDENCY_NAMES.some((dependencyName) => getDependencySpec(packageJson, dependencyName) !== null);
34193
34525
  };
34194
34526
  const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGroup }) => {
34195
34527
  const facts = {
@@ -34205,24 +34537,55 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34205
34537
  version: null,
34206
34538
  sourceDirectory: null
34207
34539
  },
34540
+ reactRouter: {
34541
+ version: null,
34542
+ sourceDirectory: null,
34543
+ packageName: null
34544
+ },
34208
34545
  shopifyFlashList: {
34209
34546
  version: null,
34210
34547
  sourceDirectory: null
34211
34548
  },
34212
34549
  valtioVersion: null,
34550
+ mobx: {
34551
+ version: null,
34552
+ sourceDirectory: null
34553
+ },
34554
+ hasMobxReact: false,
34555
+ mobxReactVersion: null,
34556
+ hasMobxReactLite: false,
34557
+ mobxReactLiteVersion: null,
34558
+ hasMobxStateTree: false,
34559
+ hasMobxReactObserver: false,
34560
+ zustand: {
34561
+ version: null,
34562
+ sourceDirectory: null
34563
+ },
34564
+ tanstackQueryVersion: null,
34565
+ styledComponentsVersion: null,
34566
+ hasI18nLibrary: false,
34213
34567
  hasReactNativeAwarePackage: false,
34214
34568
  hasReanimatedAwarePackage: false,
34215
34569
  hasSsrDependency: false,
34216
34570
  hasRemotionDependency: false,
34217
34571
  hasUnknownRemotionVersion: false,
34218
34572
  remotionVersion: null,
34573
+ hasThree: false,
34574
+ threeVersion: null,
34575
+ hasReactThreeFiber: false,
34576
+ reactThreeFiber: {
34577
+ packageName: null,
34578
+ version: null,
34579
+ sourceDirectory: null
34580
+ },
34581
+ hasReactRouterFramework: false,
34219
34582
  reanimatedVersion: null
34220
34583
  };
34221
34584
  evaluateManifestFacts(facts, rootPackageJson, rootDirectory, rootDirectory, rootPackageJson);
34222
34585
  let isReactGroupSettled = !collectReactGroup;
34223
34586
  const visitedDirectories = /* @__PURE__ */ new Set();
34224
34587
  for (const pattern of getWorkspacePatterns(rootDirectory, rootPackageJson)) {
34225
- const directories = [...resolveWorkspaceDirectories(rootDirectory, pattern)].sort();
34588
+ const directories = resolveWorkspaceDirectories(rootDirectory, pattern).toSorted();
34226
34589
  for (const workspaceDirectory of directories) {
34227
34590
  if (visitedDirectories.has(workspaceDirectory)) continue;
34228
34591
  visitedDirectories.add(workspaceDirectory);
@@ -34258,7 +34621,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34258
34621
  workspaceDirectory,
34259
34622
  workspacePackageJson
34260
34623
  });
34261
- if (reactVersion && shouldReplaceReactVersion(facts.reactVersion, reactVersion)) facts.reactVersion = reactVersion;
34624
+ if (reactVersion && shouldReplaceWithLowerMajor(facts.reactVersion, reactVersion)) facts.reactVersion = reactVersion;
34262
34625
  if (tailwindVersion && !facts.tailwindVersion) facts.tailwindVersion = tailwindVersion;
34263
34626
  if (zodVersion && !facts.zodVersion) facts.zodVersion = zodVersion;
34264
34627
  const settledReactMajor = parseReactMajor(facts.reactVersion);
@@ -34451,6 +34814,16 @@ const discoverProjectWithoutPackageJson = (directory) => {
34451
34814
  tailwindVersion: null,
34452
34815
  zodVersion: null,
34453
34816
  zodMajorVersion: null,
34817
+ mobxVersion: null,
34818
+ mobxMajorVersion: null,
34819
+ hasMobxReact: false,
34820
+ mobxReactVersion: null,
34821
+ hasMobxReactLite: false,
34822
+ mobxReactLiteVersion: null,
34823
+ hasMobxStateTree: false,
34824
+ hasMobxReactObserver: false,
34825
+ zustandVersion: null,
34826
+ zustandMajorVersion: null,
34454
34827
  framework: "unknown",
34455
34828
  hasTypeScript: hasOwnTsConfig,
34456
34829
  hasReactCompiler: false,
@@ -34461,12 +34834,23 @@ const discoverProjectWithoutPackageJson = (directory) => {
34461
34834
  hasRemotion: false,
34462
34835
  remotionVersion: null,
34463
34836
  remotionMajorVersion: null,
34837
+ hasI18nLibrary: false,
34838
+ tanstackQueryVersion: null,
34839
+ styledComponentsVersion: null,
34840
+ hasThree: false,
34841
+ threeVersion: null,
34842
+ threeRelease: null,
34843
+ hasReactThreeFiber: false,
34844
+ reactThreeFiberVersion: null,
34845
+ reactThreeFiberMajorVersion: null,
34464
34846
  hasSsrDependency: false,
34465
34847
  preactVersion: null,
34466
34848
  preactMajorVersion: null,
34467
34849
  hasReactNativeWorkspace: false,
34468
34850
  nextjsVersion: null,
34469
34851
  nextjsMajorVersion: null,
34852
+ reactRouterVersion: null,
34853
+ hasReactRouterFramework: false,
34470
34854
  expoVersion: null,
34471
34855
  shopifyFlashListVersion: null,
34472
34856
  shopifyFlashListMajorVersion: null,
@@ -34559,6 +34943,12 @@ const discoverProject = (directory) => {
34559
34943
  packageName: SHOPIFY_FLASH_LIST_PACKAGE_NAME,
34560
34944
  version: workspaceFacts.shopifyFlashList.version
34561
34945
  }) : null;
34946
+ const zustandVersion = resolveCatalogBackedDependencyVersion({
34947
+ rootDirectory: directory,
34948
+ rootPackageJson: packageJson,
34949
+ packageName: "zustand",
34950
+ version: workspaceFacts.zustand.version
34951
+ });
34562
34952
  const hasReanimated = hasReactNativeWorkspace && workspaceFacts.hasReanimatedAwarePackage;
34563
34953
  const reanimatedVersion = hasReanimated ? workspaceFacts.reanimatedVersion : null;
34564
34954
  const nextjsVersion = framework === "nextjs" ? resolveCatalogBackedDependencyVersion({
@@ -34573,8 +34963,33 @@ const discoverProject = (directory) => {
34573
34963
  packageName: "valtio",
34574
34964
  version: workspaceFacts.valtioVersion
34575
34965
  });
34966
+ const mobxVersion = resolveCatalogBackedDependencyVersion({
34967
+ rootDirectory: directory,
34968
+ rootPackageJson: packageJson,
34969
+ packageName: "mobx",
34970
+ version: workspaceFacts.mobx.version
34971
+ });
34972
+ const reactRouterVersion = workspaceFacts.reactRouter.packageName === null ? null : resolveCatalogBackedDependencyVersion({
34973
+ rootDirectory: directory,
34974
+ rootPackageJson: packageJson,
34975
+ packageName: workspaceFacts.reactRouter.packageName,
34976
+ version: workspaceFacts.reactRouter.version
34977
+ });
34576
34978
  const preactVersion = getPreactVersion(packageJson);
34577
34979
  const remotionVersion = workspaceFacts.remotionVersion;
34980
+ const tanstackQueryVersion = getTanStackQueryVersion(packageJson) ?? workspaceFacts.tanstackQueryVersion;
34981
+ const reactThreeFiberVersion = workspaceFacts.reactThreeFiber.packageName ? resolveCatalogBackedDependencyVersion({
34982
+ rootDirectory: directory,
34983
+ rootPackageJson: packageJson,
34984
+ packageName: workspaceFacts.reactThreeFiber.packageName,
34985
+ version: workspaceFacts.reactThreeFiber.version
34986
+ }) : null;
34987
+ const threeVersion = resolveCatalogBackedDependencyVersion({
34988
+ rootDirectory: directory,
34989
+ rootPackageJson: packageJson,
34990
+ packageName: "three",
34991
+ version: workspaceFacts.threeVersion
34992
+ });
34578
34993
  const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
34579
34994
  const projectInfo = {
34580
34995
  rootDirectory: directory,
@@ -34584,22 +34999,43 @@ const discoverProject = (directory) => {
34584
34999
  tailwindVersion,
34585
35000
  zodVersion,
34586
35001
  zodMajorVersion: zodVersion === null ? null : getLowestDependencyMajor(zodVersion),
35002
+ mobxVersion,
35003
+ mobxMajorVersion: mobxVersion === null ? null : getDependencyMajorWithinSupportedRange(mobxVersion, 6),
35004
+ hasMobxReact: workspaceFacts.hasMobxReact,
35005
+ mobxReactVersion: workspaceFacts.mobxReactVersion,
35006
+ hasMobxReactLite: workspaceFacts.hasMobxReactLite,
35007
+ mobxReactLiteVersion: workspaceFacts.mobxReactLiteVersion,
35008
+ hasMobxStateTree: workspaceFacts.hasMobxStateTree,
35009
+ hasMobxReactObserver: workspaceFacts.hasMobxReactObserver,
35010
+ zustandVersion,
35011
+ zustandMajorVersion: zustandVersion === null ? null : getLowestDependencyMajor(zustandVersion),
34587
35012
  framework,
34588
35013
  hasTypeScript,
34589
35014
  hasReactCompiler: detectReactCompiler(directory, packageJson),
34590
35015
  hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
34591
- hasTanStackQuery: hasTanStackQuery(packageJson),
35016
+ hasTanStackQuery: tanstackQueryVersion !== null,
35017
+ hasI18nLibrary: workspaceFacts.hasI18nLibrary,
35018
+ tanstackQueryVersion,
35019
+ styledComponentsVersion: workspaceFacts.styledComponentsVersion,
34592
35020
  valtioVersion,
34593
35021
  valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
34594
35022
  hasRemotion: workspaceFacts.hasRemotionDependency,
34595
35023
  remotionVersion,
34596
35024
  remotionMajorVersion: remotionVersion === null ? null : getLowestDependencyMajor(remotionVersion),
35025
+ hasThree: workspaceFacts.hasThree,
35026
+ threeVersion,
35027
+ threeRelease: parseThreeRelease(threeVersion),
35028
+ hasReactThreeFiber: workspaceFacts.hasReactThreeFiber,
35029
+ reactThreeFiberVersion,
35030
+ reactThreeFiberMajorVersion: reactThreeFiberVersion === null ? null : getLowestDependencyMajor(reactThreeFiberVersion),
34597
35031
  hasSsrDependency: workspaceFacts.hasSsrDependency,
34598
35032
  preactVersion,
34599
35033
  preactMajorVersion: parseReactMajor(preactVersion),
34600
35034
  hasReactNativeWorkspace,
34601
35035
  nextjsVersion,
34602
35036
  nextjsMajorVersion: nextjsVersion === null ? null : getLowestDependencyMajor(nextjsVersion),
35037
+ reactRouterVersion,
35038
+ hasReactRouterFramework: workspaceFacts.hasReactRouterFramework,
34603
35039
  expoVersion,
34604
35040
  shopifyFlashListVersion,
34605
35041
  shopifyFlashListMajorVersion: shopifyFlashListVersion === null ? null : getLowestDependencyMajor(shopifyFlashListVersion),
@@ -37868,10 +38304,10 @@ const SSR_FRAMEWORKS = new Set([
37868
38304
  "gatsby",
37869
38305
  "tanstack-start"
37870
38306
  ]);
37871
- const addMajorLadder = (capabilities, name, major, earliest, latest) => {
37872
- if (major === null) return;
37873
- const cappedMajor = Math.min(major, latest);
37874
- for (let candidate = earliest; candidate <= cappedMajor; candidate += 1) capabilities.add(`${name}:${candidate}`);
38307
+ const addVersionCapabilityLadder = (capabilities, name, detectedVersion, earliest, latest) => {
38308
+ if (detectedVersion === null) return;
38309
+ const cappedVersion = Math.min(detectedVersion, latest);
38310
+ for (let candidate = earliest; candidate <= cappedVersion; candidate += 1) capabilities.add(`${name}:${candidate}`);
37875
38311
  };
37876
38312
  const buildCapabilities = (project) => {
37877
38313
  const capabilities = /* @__PURE__ */ new Set();
@@ -37884,30 +38320,86 @@ const buildCapabilities = (project) => {
37884
38320
  if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
37885
38321
  if (project.isStaticExport) capabilities.add("nextjs:static-export");
37886
38322
  if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
37887
- addMajorLadder(capabilities, "react", project.reactMajorVersion, 17, 30);
38323
+ if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 16) capabilities.add("nextjs:16");
38324
+ const reactRouterVersion = project.reactRouterVersion ?? null;
38325
+ if (reactRouterVersion !== null) {
38326
+ capabilities.add("react-router");
38327
+ if (project.hasReactRouterFramework === true) capabilities.add("react-router-framework");
38328
+ const detectedVersion = parseReactMajorMinor(reactRouterVersion);
38329
+ if (detectedVersion !== null) {
38330
+ for (const threshold of REACT_ROUTER_CAPABILITY_THRESHOLDS) if (isMajorMinorAtLeast(detectedVersion, threshold)) capabilities.add(threshold.capability);
38331
+ }
38332
+ }
38333
+ addVersionCapabilityLadder(capabilities, "react", project.reactMajorVersion, 17, 30);
37888
38334
  if (project.reactMajorVersion !== null && project.reactMajorVersion >= 19 && isMajorMinorAtLeast(parseReactMajorMinor(project.reactVersion), {
37889
38335
  major: 19,
37890
38336
  minor: 2
37891
38337
  })) capabilities.add("react:19.2");
37892
- if (project.tailwindVersion !== null) capabilities.add("tailwind");
37893
- if (project.tailwindVersion !== null && isMajorMinorAtLeast(parseTailwindMajorMinor(project.tailwindVersion), {
37894
- major: 3,
37895
- minor: 4
37896
- })) capabilities.add("tailwind:3.4");
38338
+ if (project.tailwindVersion !== null) {
38339
+ capabilities.add("tailwind");
38340
+ const tailwindVersion = parseTailwindMajorMinor(project.tailwindVersion);
38341
+ if (isMajorMinorAtLeast(tailwindVersion, {
38342
+ major: 3,
38343
+ minor: 4
38344
+ })) capabilities.add("tailwind:3.4");
38345
+ if (tailwindVersion !== null && isMajorMinorAtLeast(tailwindVersion, {
38346
+ major: 4,
38347
+ minor: 0
38348
+ })) capabilities.add("tailwind:4");
38349
+ }
37897
38350
  if (project.zodVersion !== null) capabilities.add("zod");
37898
38351
  if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
38352
+ if (project.mobxVersion !== void 0 && project.mobxVersion !== null || project.hasMobxReact === true || project.hasMobxReactLite === true || project.hasMobxStateTree === true || project.hasMobxReactObserver === true) capabilities.add("mobx");
38353
+ if (project.hasMobxReact === true) capabilities.add("mobx-react");
38354
+ if (project.hasMobxReactLite === true) capabilities.add("mobx-react-lite");
38355
+ if (project.hasMobxReact === true || project.hasMobxReactLite === true) capabilities.add("mobx-react-binding");
38356
+ const mobxReactVersion = parseDependencyMajorMinor(project.mobxReactVersion);
38357
+ const mobxReactLiteVersion = parseDependencyMajorMinor(project.mobxReactLiteVersion);
38358
+ const hasMobxReactObserverMemoGuard = mobxReactVersion !== null && isMajorMinorAtLeast(mobxReactVersion, {
38359
+ major: 7,
38360
+ minor: 3
38361
+ });
38362
+ const hasMobxReactLiteObserverMemoGuard = mobxReactLiteVersion !== null && isMajorMinorAtLeast(mobxReactLiteVersion, {
38363
+ major: 3,
38364
+ minor: 3
38365
+ });
38366
+ if (hasMobxReactObserverMemoGuard) capabilities.add("mobx-react-observer-memo-guard");
38367
+ if (hasMobxReactLiteObserverMemoGuard) capabilities.add("mobx-react-lite-observer-memo-guard");
38368
+ if (hasMobxReactObserverMemoGuard || hasMobxReactLiteObserverMemoGuard) capabilities.add("mobx-react-binding-observer-memo-guard");
38369
+ if (project.hasMobxStateTree === true) capabilities.add("mobx-state-tree");
38370
+ if (project.hasMobxReactObserver === true) capabilities.add("mobx-react-observer");
38371
+ if (project.mobxMajorVersion !== void 0 && project.mobxMajorVersion !== null && project.mobxMajorVersion >= 4 && project.mobxMajorVersion <= 6) addVersionCapabilityLadder(capabilities, "mobx", project.mobxMajorVersion, 4, 6);
38372
+ const mobxVersion = parseDependencyMajorMinor(project.mobxVersion);
38373
+ if (project.mobxMajorVersion === 6 && mobxVersion !== null && isMajorMinorAtLeast(mobxVersion, {
38374
+ major: 6,
38375
+ minor: 10
38376
+ })) capabilities.add("mobx:6.10");
38377
+ if (project.zustandVersion !== void 0 && project.zustandVersion !== null) capabilities.add("zustand");
38378
+ if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addVersionCapabilityLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
37899
38379
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
37900
38380
  if (project.hasReactCompiler) capabilities.add("react-compiler");
37901
- if (project.hasTanStackQuery) capabilities.add("tanstack-query");
38381
+ if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
38382
+ if (project.styledComponentsVersion) {
38383
+ capabilities.add("styled-components");
38384
+ const styledComponentsMajor = getLowestDependencyMajor(project.styledComponentsVersion);
38385
+ if (styledComponentsMajor !== null && styledComponentsMajor >= 6) capabilities.add("styled-components:6");
38386
+ }
38387
+ if (project.hasI18nLibrary) capabilities.add("i18n");
37902
38388
  if (project.valtioVersion !== null) capabilities.add("valtio");
37903
- addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
38389
+ addVersionCapabilityLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
37904
38390
  if (project.hasRemotion) {
37905
38391
  capabilities.add("remotion");
37906
- addMajorLadder(capabilities, "remotion", project.remotionMajorVersion ?? null, 4, 30);
38392
+ addVersionCapabilityLadder(capabilities, "remotion", project.remotionMajorVersion ?? null, 4, 30);
38393
+ }
38394
+ if (project.hasThree || project.hasReactThreeFiber) capabilities.add("three");
38395
+ addVersionCapabilityLadder(capabilities, "three", project.threeRelease ?? null, 145, 250);
38396
+ if (project.hasReactThreeFiber) {
38397
+ capabilities.add("r3f");
38398
+ addVersionCapabilityLadder(capabilities, "r3f", project.reactThreeFiberMajorVersion ?? null, 3, 10);
37907
38399
  }
37908
38400
  if (project.hasTypeScript) capabilities.add("typescript");
37909
38401
  if (project.preactVersion !== null) capabilities.add("preact");
37910
- addMajorLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
38402
+ addVersionCapabilityLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
37911
38403
  if (project.preactVersion !== null && project.reactVersion === null) capabilities.add("pure-preact");
37912
38404
  return capabilities;
37913
38405
  };
@@ -37919,7 +38411,7 @@ const getCapabilities = (project) => {
37919
38411
  capabilitiesByProject.set(project, capabilities);
37920
38412
  return capabilities;
37921
38413
  };
37922
- const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhen) => {
38414
+ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhen, includedTags) => {
37923
38415
  if (requires) {
37924
38416
  for (const capability of requires) if (!capabilities.has(capability)) return false;
37925
38417
  }
@@ -37930,20 +38422,29 @@ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhe
37930
38422
  if (tags) {
37931
38423
  for (const tag of tags) if (ignoredTags.has(tag)) return false;
37932
38424
  }
38425
+ if (includedTags && includedTags.size > 0) {
38426
+ if (!tags?.some((tag) => includedTags.has(tag))) return false;
38427
+ }
37933
38428
  return true;
37934
38429
  };
38430
+ const shouldEnableRuleByDefaultStatus = (options) => options.defaultEnabled !== false || options.hasExplicitOverride === true || options.includeTagDefaults && options.hasIncludedTags;
37935
38431
  const yieldToEventLoop = () => new Promise((resolve) => {
37936
38432
  setImmediate(resolve);
37937
38433
  });
37938
38434
  const createSecurityScanSession = (rootDirectory, options) => {
37939
38435
  const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
37940
38436
  const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
38437
+ const includedTags = options.includedTags ?? /* @__PURE__ */ new Set();
37941
38438
  const enabledScanRules = REACT_DOCTOR_RULES.flatMap((entry) => {
37942
38439
  const rule = entry.rule;
37943
38440
  const scan = rule.scan;
37944
38441
  if (typeof scan !== "function") return [];
37945
- if (rule.defaultEnabled === false) return [];
37946
- if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen)) return [];
38442
+ if (!shouldEnableRuleByDefaultStatus({
38443
+ defaultEnabled: rule.defaultEnabled,
38444
+ includeTagDefaults: options.includeTagDefaults === true,
38445
+ hasIncludedTags: includedTags.size > 0
38446
+ })) return [];
38447
+ if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) return [];
37947
38448
  return [{
37948
38449
  entry,
37949
38450
  scan,
@@ -39929,8 +40430,9 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
39929
40430
  }
39930
40431
  return enabled;
39931
40432
  };
39932
- const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
39933
- const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
40433
+ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
40434
+ const hasIncludedTags = includedTags.size > 0;
40435
+ const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
39934
40436
  const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
39935
40437
  const jsPlugins = [];
39936
40438
  if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
@@ -39945,9 +40447,14 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
39945
40447
  if (rule.scan !== void 0) continue;
39946
40448
  if (customRulesOnly && registryEntry.originallyExternal) continue;
39947
40449
  if (rule.framework !== "global" && !rule.requires) continue;
39948
- if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen)) continue;
40450
+ if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) continue;
39949
40451
  const explicitRuleOverride = resolveRuleSeverityOverride({ ruleKey: registryEntry.key }, severityControls);
39950
- if (rule.defaultEnabled === false && explicitRuleOverride === void 0) continue;
40452
+ if (!shouldEnableRuleByDefaultStatus({
40453
+ defaultEnabled: rule.defaultEnabled,
40454
+ includeTagDefaults,
40455
+ hasIncludedTags,
40456
+ hasExplicitOverride: explicitRuleOverride !== void 0
40457
+ })) continue;
39951
40458
  const severity = resolveRuleSeverityOverride({
39952
40459
  ruleKey: registryEntry.key,
39953
40460
  category: rule.category
@@ -39956,7 +40463,7 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
39956
40463
  enabledReactDoctorRules[registryEntry.key] = severity;
39957
40464
  }
39958
40465
  const userPluginRules = {};
39959
- if (ruleSelection !== "sidecar") for (const userPlugin of userPlugins) {
40466
+ if (ruleSelection !== "sidecar" && !hasIncludedTags) for (const userPlugin of userPlugins) {
39960
40467
  Object.assign(userPluginRules, buildUserPluginRules(userPlugin, severityControls));
39961
40468
  jsPlugins.push(userPlugin.entry);
39962
40469
  }
@@ -40173,6 +40680,19 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
40173
40680
  }
40174
40681
  };
40175
40682
  };
40683
+ const fingerprintCacheByFilePath = /* @__PURE__ */ new Map();
40684
+ const fingerprintFileContents = (filePath, fingerprintLength) => {
40685
+ const fileStats = NFS.statSync(filePath, { bigint: true });
40686
+ const cachedFingerprint = fingerprintCacheByFilePath.get(filePath);
40687
+ if (cachedFingerprint?.modifiedTimeNanoseconds === fileStats.mtimeNs && cachedFingerprint.sizeBytes === fileStats.size) return cachedFingerprint.fingerprint;
40688
+ const fingerprint = crypto.createHash("sha256").update(NFS.readFileSync(filePath)).digest("hex").slice(0, fingerprintLength);
40689
+ fingerprintCacheByFilePath.set(filePath, {
40690
+ fingerprint,
40691
+ modifiedTimeNanoseconds: fileStats.mtimeNs,
40692
+ sizeBytes: fileStats.size
40693
+ });
40694
+ return fingerprint;
40695
+ };
40176
40696
  const bundledRequire = createRequire(import.meta.url);
40177
40697
  const childNodeVersionByBinaryPath = /* @__PURE__ */ new Map();
40178
40698
  const resolveChildNodeVersion = (nodeBinaryPath) => {
@@ -40196,6 +40716,13 @@ const TOOLCHAIN_PACKAGE_SPECIFIERS = [
40196
40716
  "oxlint-plugin-react-doctor/package.json",
40197
40717
  "eslint-plugin-react-hooks/package.json"
40198
40718
  ];
40719
+ const resolvePluginFingerprint = () => {
40720
+ try {
40721
+ return fingerprintFileContents(bundledRequire.resolve("oxlint-plugin-react-doctor"), 16);
40722
+ } catch {
40723
+ return "unresolved";
40724
+ }
40725
+ };
40199
40726
  const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
40200
40727
  const versions = [`node=${resolveChildNodeVersion(nodeBinaryPath)}`];
40201
40728
  for (const specifier of TOOLCHAIN_PACKAGE_SPECIFIERS) try {
@@ -40205,6 +40732,7 @@ const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
40205
40732
  } catch {
40206
40733
  versions.push(`${specifier}=missing`);
40207
40734
  }
40735
+ versions.push(`oxlint-plugin-react-doctor#fingerprint=${resolvePluginFingerprint()}`);
40208
40736
  return versions;
40209
40737
  };
40210
40738
  const esmRequire = createRequire(import.meta.url);
@@ -41680,7 +42208,7 @@ const reactHooksJsPluginDropNote = (error) => {
41680
42208
  * 6. always restore disable directives + clean up the temp dir
41681
42209
  */
41682
42210
  const runOxlint = async (options) => {
41683
- 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;
42211
+ 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;
41684
42212
  const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
41685
42213
  const severityControls = buildRuleSeverityControls(userConfig);
41686
42214
  validateRuleRegistration();
@@ -41694,13 +42222,15 @@ const runOxlint = async (options) => {
41694
42222
  }
41695
42223
  const pluginPath = resolvePluginPath();
41696
42224
  const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
41697
- const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
42225
+ const userPlugins = includedTags.size > 0 ? [] : resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
41698
42226
  const buildConfig = (overrides) => createOxlintConfig({
41699
42227
  pluginPath,
41700
42228
  project,
41701
42229
  customRulesOnly,
41702
42230
  extendsPaths: overrides.extendsPaths,
41703
42231
  ignoredTags,
42232
+ includedTags,
42233
+ includeTagDefaults,
41704
42234
  serverAuthFunctionNames,
41705
42235
  severityControls,
41706
42236
  userPlugins,
@@ -42089,6 +42619,8 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
42089
42619
  respectInlineDisables: input.respectInlineDisables,
42090
42620
  adoptExistingLintConfig: input.adoptExistingLintConfig,
42091
42621
  ignoredTags: input.ignoredTags,
42622
+ includedTags: input.includedTags,
42623
+ includeTagDefaults: input.includeTagDefaults,
42092
42624
  userConfig: input.userConfig ?? null,
42093
42625
  configSourceDirectory: input.configSourceDirectory,
42094
42626
  onPartialFailure: (reason) => {
@@ -42937,7 +43469,9 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42937
43469
  const securityScanFailedRef = yield* make$13(false);
42938
43470
  const securityScanFiber = yield* forkChild(runCollect(applyPerElementPipeline(isDiffMode ? empty$4 : unwrap(tryPromise(() => checkSecurityScanCooperative(scanDirectory, {
42939
43471
  project,
42940
- ignoredTags: input.ignoredTags
43472
+ ignoredTags: input.ignoredTags,
43473
+ includedTags: input.includedTags,
43474
+ includeTagDefaults: input.includeTagDefaults
42941
43475
  })).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), catch_$1(() => set(securityScanFailedRef, true).pipe(as(empty$4))))))).pipe(withSpan("SecurityScan.run")));
42942
43476
  const shouldRunSupplyChain = !isDiffMode || (input.supplyChainManifestChanged ?? false);
42943
43477
  const supplyChainOverlapTimeout = yield* SupplyChainOverlapTimeoutMs;
@@ -43028,6 +43562,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
43028
43562
  respectInlineDisables: input.respectInlineDisables,
43029
43563
  adoptExistingLintConfig: input.adoptExistingLintConfig,
43030
43564
  ignoredTags: input.ignoredTags,
43565
+ includedTags: input.includedTags,
43566
+ includeTagDefaults: input.includeTagDefaults,
43031
43567
  userConfig: resolvedConfig.config ?? void 0,
43032
43568
  configSourceDirectory: resolvedConfig.configSourceDirectory ?? void 0,
43033
43569
  onFileProgress: (scannedFileCount, totalFileCount) => {
@@ -43888,4 +44424,4 @@ const toJsonReport = (result, options) => buildJsonReport({
43888
44424
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
43889
44425
 
43890
44426
  //# sourceMappingURL=index.js.map
43891
- //# debugId=92325f1f-c593-5b4c-af5a-c8b7177212e1
44427
+ //# debugId=c65f1825-0401-518f-840a-c33df84ebafc