react-doctor 0.8.1-dev.f4aa821 → 0.8.1-dev.fc1b3a3

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/cli.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]="1b59ca76-9135-54e6-9391-ce7fec27b699")}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]="d92b0964-cd34-5965-a1bf-ce1d06faf742")}catch(e){}}();
3
3
  import { createRequire } from "node:module";
4
4
  import * as NodeChildProcess from "node:child_process";
5
5
  import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
@@ -36022,44 +36022,6 @@ var AmbiguousProjectError = class extends Error {
36022
36022
  }
36023
36023
  };
36024
36024
  const isProjectDiscoveryError = (value) => value instanceof ProjectNotFoundError || value instanceof NoReactDependencyError || value instanceof PackageJsonNotFoundError || value instanceof NotADirectoryError || value instanceof AmbiguousProjectError;
36025
- const isErrnoException = (error) => error instanceof Error && "code" in error;
36026
- const IGNORABLE_READDIR_ERROR_CODES = new Set([
36027
- "EACCES",
36028
- "EPERM",
36029
- "ENOENT",
36030
- "ENOTDIR",
36031
- "EINVAL",
36032
- "ELOOP",
36033
- "ENAMETOOLONG"
36034
- ]);
36035
- const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
36036
- const readDirectoryEntries = (directoryPath) => {
36037
- try {
36038
- return NFS.readdirSync(directoryPath, { withFileTypes: true });
36039
- } catch (error) {
36040
- if (isIgnorableReaddirError(error)) return [];
36041
- throw error;
36042
- }
36043
- };
36044
- const isFile = (filePath) => {
36045
- try {
36046
- return NFS.statSync(filePath).isFile();
36047
- } catch {
36048
- return false;
36049
- }
36050
- };
36051
- const isDirectory = (directoryPath) => {
36052
- try {
36053
- return NFS.statSync(directoryPath).isDirectory();
36054
- } catch {
36055
- return false;
36056
- }
36057
- };
36058
- const isPlainObject = (value) => {
36059
- if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
36060
- const prototype = Object.getPrototypeOf(value);
36061
- return prototype === null || prototype === Object.prototype;
36062
- };
36063
36025
  const SOURCE_FILE_PATTERN = /\.(tsx?|jsx?|mts|mjs)$/;
36064
36026
  const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
36065
36027
  const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
@@ -36252,6 +36214,44 @@ const SUPPLY_CHAIN_OVERLAP_TIMEOUT_MS = 9e4;
36252
36214
  const SUPPLY_CHAIN_CACHE_TTL_MS = 864e5;
36253
36215
  const SUPPLY_CHAIN_CACHE_SUBDIR = "supply-chain";
36254
36216
  const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
36217
+ const isErrnoException = (error) => error instanceof Error && "code" in error;
36218
+ const IGNORABLE_READDIR_ERROR_CODES = new Set([
36219
+ "EACCES",
36220
+ "EPERM",
36221
+ "ENOENT",
36222
+ "ENOTDIR",
36223
+ "EINVAL",
36224
+ "ELOOP",
36225
+ "ENAMETOOLONG"
36226
+ ]);
36227
+ const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
36228
+ const readDirectoryEntries = (directoryPath) => {
36229
+ try {
36230
+ return NFS.readdirSync(directoryPath, { withFileTypes: true });
36231
+ } catch (error) {
36232
+ if (isIgnorableReaddirError(error)) return [];
36233
+ throw error;
36234
+ }
36235
+ };
36236
+ const isFile = (filePath) => {
36237
+ try {
36238
+ return NFS.statSync(filePath).isFile();
36239
+ } catch {
36240
+ return false;
36241
+ }
36242
+ };
36243
+ const isDirectory = (directoryPath) => {
36244
+ try {
36245
+ return NFS.statSync(directoryPath).isDirectory();
36246
+ } catch {
36247
+ return false;
36248
+ }
36249
+ };
36250
+ const isPlainObject = (value) => {
36251
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
36252
+ const prototype = Object.getPrototypeOf(value);
36253
+ return prototype === null || prototype === Object.prototype;
36254
+ };
36255
36255
  const lastSourceMappingUrl = (fileContent) => {
36256
36256
  const lastReference = [...fileContent.matchAll(/\/\/# sourceMappingURL=(\S+)/g)].at(-1);
36257
36257
  return lastReference ? lastReference[1] : null;
@@ -36571,10 +36571,10 @@ const FALLBACK_TSCONFIG_FILENAMES = ["tsconfig.app.json", "tsconfig.build.json"]
36571
36571
  const FRAMEWORK_PACKAGES = {
36572
36572
  next: "nextjs",
36573
36573
  "@tanstack/react-start": "tanstack-start",
36574
- vite: "vite",
36575
- "react-scripts": "cra",
36576
36574
  "@remix-run/react": "remix",
36577
36575
  gatsby: "gatsby",
36576
+ vite: "vite",
36577
+ "react-scripts": "cra",
36578
36578
  expo: "expo",
36579
36579
  "react-native": "react-native"
36580
36580
  };
@@ -36598,11 +36598,17 @@ const NEXT_CONFIG_FILENAMES = [
36598
36598
  ];
36599
36599
  const BABEL_CONFIG_FILENAMES = [
36600
36600
  ".babelrc",
36601
+ ".babelrc.js",
36601
36602
  ".babelrc.json",
36603
+ ".babelrc.cjs",
36604
+ ".babelrc.mjs",
36605
+ ".babelrc.cts",
36602
36606
  "babel.config.js",
36603
36607
  "babel.config.json",
36604
36608
  "babel.config.cjs",
36605
- "babel.config.mjs"
36609
+ "babel.config.mjs",
36610
+ "babel.config.ts",
36611
+ "babel.config.cts"
36606
36612
  ];
36607
36613
  const VITE_CONFIG_FILENAMES = [
36608
36614
  "vite.config.js",
@@ -36614,12 +36620,28 @@ const VITE_CONFIG_FILENAMES = [
36614
36620
  "vitest.config.ts",
36615
36621
  "vitest.config.js"
36616
36622
  ];
36623
+ const RSBUILD_CONFIG_FILENAMES = [
36624
+ "rsbuild.config.ts",
36625
+ "rsbuild.config.js",
36626
+ "rsbuild.config.mts",
36627
+ "rsbuild.config.mjs",
36628
+ "rsbuild.config.cts",
36629
+ "rsbuild.config.cjs"
36630
+ ];
36631
+ const RSPACK_CONFIG_FILENAMES = [
36632
+ "rspack.config.ts",
36633
+ "rspack.config.js",
36634
+ "rspack.config.mts",
36635
+ "rspack.config.mjs",
36636
+ "rspack.config.cts",
36637
+ "rspack.config.cjs"
36638
+ ];
36617
36639
  const EXPO_APP_CONFIG_FILENAMES = [
36618
36640
  "app.json",
36619
36641
  "app.config.js",
36620
36642
  "app.config.ts"
36621
36643
  ];
36622
- const REACT_COMPILER_PACKAGE_REFERENCE_PATTERN = /babel-plugin-react-compiler|react-compiler-runtime|["']react-compiler["']/;
36644
+ const REACT_COMPILER_PACKAGE_REFERENCE_PATTERN = /babel-plugin-react-compiler|react-compiler-runtime|reactCompilerPreset\s*\(|["']react-compiler["']/;
36623
36645
  const REACT_COMPILER_ENABLED_FLAG_PATTERN = /["']?reactCompiler["']?\s*:\s*(?:true\b|\{)/;
36624
36646
  const STATIC_EXPORT_OUTPUT_PATTERN = /(?:^|[^.\w])["']?output["']?\s*:\s*["']export["']/m;
36625
36647
  const hasCompilerPackage = (packageJson, compilerPackages) => {
@@ -36654,6 +36676,8 @@ const detectReactCompiler = (directory, packageJson) => {
36654
36676
  if (hasCompilerInConfigFiles(directory, NEXT_CONFIG_FILENAMES)) return true;
36655
36677
  if (hasCompilerInConfigFiles(directory, BABEL_CONFIG_FILENAMES)) return true;
36656
36678
  if (hasCompilerInConfigFiles(directory, VITE_CONFIG_FILENAMES)) return true;
36679
+ if (hasCompilerInConfigFiles(directory, RSBUILD_CONFIG_FILENAMES)) return true;
36680
+ if (hasCompilerInConfigFiles(directory, RSPACK_CONFIG_FILENAMES)) return true;
36657
36681
  if (hasCompilerInConfigFiles(directory, EXPO_APP_CONFIG_FILENAMES)) return true;
36658
36682
  return hasCompilerPackageInAncestors(directory, REACT_COMPILER_TRANSFORM_PACKAGES);
36659
36683
  };
@@ -36795,6 +36819,16 @@ const getLowestDependencyMajor = (version) => {
36795
36819
  }
36796
36820
  return lowestMajor;
36797
36821
  };
36822
+ const getDependencyMajorWithinSupportedRange = (version, latestSupportedMajor) => {
36823
+ const normalizedVersion = normalizeDependencyVersion(version);
36824
+ if (normalizedVersion === null) return null;
36825
+ const validRange = import_semver.validRange(normalizedVersion);
36826
+ if (validRange === null) return null;
36827
+ const minimumVersion = import_semver.minVersion(validRange);
36828
+ if (minimumVersion === null || minimumVersion.major > latestSupportedMajor) return null;
36829
+ if (import_semver.intersects(validRange, `>=${latestSupportedMajor + 1}.0.0`)) return null;
36830
+ return minimumVersion.major;
36831
+ };
36798
36832
  const isConcreteDependencyVersion = (version) => {
36799
36833
  const normalizedVersion = normalizeDependencyVersion(version);
36800
36834
  return normalizedVersion !== null && /\d/.test(normalizedVersion);
@@ -36838,9 +36872,9 @@ const parseReactMajorMinor = (reactVersion) => {
36838
36872
  };
36839
36873
  };
36840
36874
  const parseLowerBoundVersion = (versionSpec) => import_semver.validRange(versionSpec) !== null ? import_semver.minVersion(versionSpec) : import_semver.coerce(versionSpec);
36841
- const parseTailwindMajorMinor = (tailwindVersion) => {
36842
- if (typeof tailwindVersion !== "string") return null;
36843
- const trimmed = tailwindVersion.trim();
36875
+ const parseDependencyMajorMinor = (dependencyVersion) => {
36876
+ if (typeof dependencyVersion !== "string") return null;
36877
+ const trimmed = dependencyVersion.trim();
36844
36878
  if (trimmed.length === 0) return null;
36845
36879
  const lowerBound = parseLowerBoundVersion(trimmed);
36846
36880
  if (lowerBound === null || lowerBound.major <= 0) return null;
@@ -36849,6 +36883,7 @@ const parseTailwindMajorMinor = (tailwindVersion) => {
36849
36883
  minor: lowerBound.minor
36850
36884
  };
36851
36885
  };
36886
+ const parseTailwindMajorMinor = (tailwindVersion) => parseDependencyMajorMinor(tailwindVersion);
36852
36887
  const hasUpperBoundOnlyPeerRange = (range) => {
36853
36888
  if (typeof range !== "string") return false;
36854
36889
  const normalizedRange = normalizeDependencyVersion(range);
@@ -37101,19 +37136,6 @@ const getPreactVersion = (packageJson) => {
37101
37136
  ...packageJson.devDependencies
37102
37137
  }.preact ?? null;
37103
37138
  };
37104
- const TANSTACK_QUERY_PACKAGES = new Set([
37105
- "@tanstack/react-query",
37106
- "@tanstack/query-core",
37107
- "react-query"
37108
- ]);
37109
- const hasTanStackQuery = (packageJson) => {
37110
- const allDependencies = {
37111
- ...packageJson.peerDependencies,
37112
- ...packageJson.dependencies,
37113
- ...packageJson.devDependencies
37114
- };
37115
- return Object.keys(allDependencies).some((packageName) => TANSTACK_QUERY_PACKAGES.has(packageName));
37116
- };
37117
37139
  const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, version }) => {
37118
37140
  if (version === null || !isCatalogReference(version)) return version;
37119
37141
  const catalogName = extractCatalogName(version);
@@ -37316,7 +37338,60 @@ const listWorkspacePackages = (rootDirectory) => {
37316
37338
  }
37317
37339
  return packages;
37318
37340
  };
37341
+ const getPreferredDependencyVersion = ({ packageJson, packageNames }) => {
37342
+ const allDependencies = {
37343
+ ...packageJson.devDependencies,
37344
+ ...packageJson.peerDependencies,
37345
+ ...packageJson.dependencies
37346
+ };
37347
+ for (const packageName of packageNames) {
37348
+ const version = allDependencies[packageName];
37349
+ if (version !== void 0) return version;
37350
+ }
37351
+ return null;
37352
+ };
37353
+ const TANSTACK_REACT_QUERY_PACKAGES = ["@tanstack/react-query", "react-query"];
37354
+ const getTanStackQueryVersion = (packageJson) => {
37355
+ return getPreferredDependencyVersion({
37356
+ packageJson,
37357
+ packageNames: TANSTACK_REACT_QUERY_PACKAGES
37358
+ });
37359
+ };
37360
+ const STYLED_COMPONENTS_PACKAGES = ["styled-components"];
37361
+ const getStyledComponentsVersion = (packageJson) => {
37362
+ return getPreferredDependencyVersion({
37363
+ packageJson,
37364
+ packageNames: STYLED_COMPONENTS_PACKAGES
37365
+ });
37366
+ };
37367
+ const I18N_PACKAGES = [
37368
+ "i18next",
37369
+ "react-i18next",
37370
+ "next-i18next",
37371
+ "react-intl",
37372
+ "next-intl",
37373
+ "use-intl",
37374
+ "@formatjs/intl",
37375
+ "@lingui/core",
37376
+ "@lingui/react",
37377
+ "typesafe-i18n",
37378
+ "@tolgee/react",
37379
+ "react-intl-universal"
37380
+ ];
37381
+ const hasI18nDependency = (packageJson) => {
37382
+ const allDependencies = {
37383
+ ...packageJson.peerDependencies,
37384
+ ...packageJson.dependencies,
37385
+ ...packageJson.devDependencies,
37386
+ ...packageJson.optionalDependencies
37387
+ };
37388
+ return I18N_PACKAGES.some((packageName) => allDependencies[packageName] !== void 0);
37389
+ };
37319
37390
  const REANIMATED_DEPENDENCY_NAME = "react-native-reanimated";
37391
+ const MOBX_REACT_PACKAGE_NAME = "mobx-react";
37392
+ const MOBX_REACT_LITE_PACKAGE_NAME = "mobx-react-lite";
37393
+ const MOBX_STATE_TREE_PACKAGE_NAME = "mobx-state-tree";
37394
+ const MOBX_REACT_OBSERVER_PACKAGE_NAME = "mobx-react-observer";
37320
37395
  const SHOPIFY_FLASH_LIST_PACKAGE_NAME = "@shopify/flash-list";
37321
37396
  const resolveWorkspaceDependencyVersion = ({ concreteVersion, packageName, rootDirectory, rootPackageJson, sections, workspaceDirectory, workspacePackageJson }) => {
37322
37397
  const dependencyDeclaration = getDependencyDeclaration({
@@ -37335,6 +37410,61 @@ const shouldReplaceReactVersion = (currentVersion, nextVersion) => {
37335
37410
  if (nextMajor === null) return false;
37336
37411
  return nextMajor < currentMajor;
37337
37412
  };
37413
+ const shouldReplaceSupportedDependencyFact = (currentFact, nextFact, latestSupportedMajor) => {
37414
+ if (currentFact.version === null) return true;
37415
+ if (nextFact.version === null) return false;
37416
+ const currentMajor = getLowestDependencyMajor(currentFact.version);
37417
+ const nextMajor = getLowestDependencyMajor(nextFact.version);
37418
+ if (currentMajor === null) return false;
37419
+ if (nextMajor === null) return true;
37420
+ if (currentMajor > latestSupportedMajor) return false;
37421
+ if (nextMajor > latestSupportedMajor) return true;
37422
+ return nextMajor < currentMajor;
37423
+ };
37424
+ const shouldReplaceStyledComponentsVersion = (currentVersion, nextVersion) => {
37425
+ if (!currentVersion) return true;
37426
+ const currentMajor = getLowestDependencyMajor(currentVersion);
37427
+ const nextMajor = getLowestDependencyMajor(nextVersion);
37428
+ if (currentMajor === null) return nextMajor !== null && nextMajor < 6;
37429
+ if (nextMajor === null) return currentMajor >= 6;
37430
+ return nextMajor < currentMajor;
37431
+ };
37432
+ const selectOldestDependencyVersion = (currentVersion, nextVersion) => {
37433
+ if (currentVersion === null || nextVersion === null) return null;
37434
+ const current = parseDependencyMajorMinor(currentVersion);
37435
+ const next = parseDependencyMajorMinor(nextVersion);
37436
+ if (current === null) return currentVersion;
37437
+ if (next === null) return nextVersion;
37438
+ if (next.major !== current.major) return next.major < current.major ? nextVersion : currentVersion;
37439
+ return next.minor < current.minor ? nextVersion : currentVersion;
37440
+ };
37441
+ const shouldReplaceMobxFact = (currentFact, nextFact) => {
37442
+ if (currentFact.sourceDirectory === null) return true;
37443
+ if (currentFact.version === null) return false;
37444
+ if (nextFact.version === null) return true;
37445
+ const currentMajor = getDependencyMajorWithinSupportedRange(currentFact.version, 6);
37446
+ const nextMajor = getDependencyMajorWithinSupportedRange(nextFact.version, 6);
37447
+ if (currentMajor === null) return false;
37448
+ if (nextMajor === null) return true;
37449
+ return selectOldestDependencyVersion(currentFact.version, nextFact.version) === nextFact.version;
37450
+ };
37451
+ const collectBindingVersion = (facts, packageJson, directory, packageName) => {
37452
+ const version = getDependencySpec(packageJson, packageName);
37453
+ if (version === null) return;
37454
+ const resolvedVersion = resolveCatalogBackedDependencyVersion({
37455
+ rootDirectory: directory,
37456
+ rootPackageJson: packageJson,
37457
+ packageName,
37458
+ version
37459
+ });
37460
+ if (packageName === MOBX_REACT_PACKAGE_NAME) {
37461
+ facts.mobxReactVersion = facts.hasMobxReact ? selectOldestDependencyVersion(facts.mobxReactVersion, resolvedVersion) : resolvedVersion;
37462
+ facts.hasMobxReact = true;
37463
+ return;
37464
+ }
37465
+ facts.mobxReactLiteVersion = facts.hasMobxReactLite ? selectOldestDependencyVersion(facts.mobxReactLiteVersion, resolvedVersion) : resolvedVersion;
37466
+ facts.hasMobxReactLite = true;
37467
+ };
37338
37468
  const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, rootPackageJson) => {
37339
37469
  if (facts.expo.version === null) {
37340
37470
  const spec = getDependencySpec(packageJson, "expo");
@@ -37357,6 +37487,36 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
37357
37487
  sourceDirectory: directory
37358
37488
  };
37359
37489
  }
37490
+ const mobxSpec = getDependencySpec(packageJson, "mobx");
37491
+ if (mobxSpec !== null) {
37492
+ const nextMobxFact = {
37493
+ version: resolveCatalogBackedDependencyVersion({
37494
+ rootDirectory: directory,
37495
+ rootPackageJson: packageJson,
37496
+ packageName: "mobx",
37497
+ version: mobxSpec
37498
+ }),
37499
+ sourceDirectory: directory
37500
+ };
37501
+ if (shouldReplaceMobxFact(facts.mobx, nextMobxFact)) facts.mobx = nextMobxFact;
37502
+ }
37503
+ collectBindingVersion(facts, packageJson, directory, MOBX_REACT_PACKAGE_NAME);
37504
+ collectBindingVersion(facts, packageJson, directory, MOBX_REACT_LITE_PACKAGE_NAME);
37505
+ facts.hasMobxStateTree = facts.hasMobxStateTree || getDependencySpec(packageJson, MOBX_STATE_TREE_PACKAGE_NAME) !== null;
37506
+ facts.hasMobxReactObserver = facts.hasMobxReactObserver || getDependencySpec(packageJson, MOBX_REACT_OBSERVER_PACKAGE_NAME) !== null;
37507
+ const zustandSpec = getDependencySpec(packageJson, "zustand");
37508
+ if (zustandSpec !== null) {
37509
+ const nextZustandFact = {
37510
+ version: resolveCatalogBackedDependencyVersion({
37511
+ rootDirectory: directory,
37512
+ rootPackageJson: packageJson,
37513
+ packageName: "zustand",
37514
+ version: zustandSpec
37515
+ }),
37516
+ sourceDirectory: directory
37517
+ };
37518
+ if (shouldReplaceSupportedDependencyFact(facts.zustand, nextZustandFact, 5)) facts.zustand = nextZustandFact;
37519
+ }
37360
37520
  if (facts.reanimatedVersion === null) {
37361
37521
  const spec = getDependencySpec(packageJson, REANIMATED_DEPENDENCY_NAME);
37362
37522
  if (spec !== null) facts.reanimatedVersion = spec;
@@ -37365,6 +37525,15 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
37365
37525
  const spec = getDependencySpec(packageJson, "valtio");
37366
37526
  if (spec !== null) facts.valtioVersion = spec;
37367
37527
  }
37528
+ facts.tanstackQueryVersion ??= getTanStackQueryVersion(packageJson);
37529
+ const styledComponentsVersion = resolveCatalogBackedDependencyVersion({
37530
+ rootDirectory: directory,
37531
+ rootPackageJson: packageJson,
37532
+ packageName: "styled-components",
37533
+ version: getStyledComponentsVersion(packageJson)
37534
+ });
37535
+ if (styledComponentsVersion && shouldReplaceStyledComponentsVersion(facts.styledComponentsVersion, styledComponentsVersion)) facts.styledComponentsVersion = styledComponentsVersion;
37536
+ facts.hasI18nLibrary = facts.hasI18nLibrary || hasI18nDependency(packageJson);
37368
37537
  facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
37369
37538
  facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
37370
37539
  facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
@@ -37406,6 +37575,23 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
37406
37575
  sourceDirectory: null
37407
37576
  },
37408
37577
  valtioVersion: null,
37578
+ mobx: {
37579
+ version: null,
37580
+ sourceDirectory: null
37581
+ },
37582
+ hasMobxReact: false,
37583
+ mobxReactVersion: null,
37584
+ hasMobxReactLite: false,
37585
+ mobxReactLiteVersion: null,
37586
+ hasMobxStateTree: false,
37587
+ hasMobxReactObserver: false,
37588
+ zustand: {
37589
+ version: null,
37590
+ sourceDirectory: null
37591
+ },
37592
+ tanstackQueryVersion: null,
37593
+ styledComponentsVersion: null,
37594
+ hasI18nLibrary: false,
37409
37595
  hasReactNativeAwarePackage: false,
37410
37596
  hasReanimatedAwarePackage: false,
37411
37597
  hasSsrDependency: false,
@@ -37644,6 +37830,16 @@ const discoverProjectWithoutPackageJson = (directory) => {
37644
37830
  tailwindVersion: null,
37645
37831
  zodVersion: null,
37646
37832
  zodMajorVersion: null,
37833
+ mobxVersion: null,
37834
+ mobxMajorVersion: null,
37835
+ hasMobxReact: false,
37836
+ mobxReactVersion: null,
37837
+ hasMobxReactLite: false,
37838
+ mobxReactLiteVersion: null,
37839
+ hasMobxStateTree: false,
37840
+ hasMobxReactObserver: false,
37841
+ zustandVersion: null,
37842
+ zustandMajorVersion: null,
37647
37843
  framework: "unknown",
37648
37844
  hasTypeScript: hasOwnTsConfig,
37649
37845
  hasReactCompiler: false,
@@ -37654,6 +37850,9 @@ const discoverProjectWithoutPackageJson = (directory) => {
37654
37850
  hasRemotion: false,
37655
37851
  remotionVersion: null,
37656
37852
  remotionMajorVersion: null,
37853
+ hasI18nLibrary: false,
37854
+ tanstackQueryVersion: null,
37855
+ styledComponentsVersion: null,
37657
37856
  hasSsrDependency: false,
37658
37857
  preactVersion: null,
37659
37858
  preactMajorVersion: null,
@@ -37752,6 +37951,12 @@ const discoverProject = (directory) => {
37752
37951
  packageName: SHOPIFY_FLASH_LIST_PACKAGE_NAME,
37753
37952
  version: workspaceFacts.shopifyFlashList.version
37754
37953
  }) : null;
37954
+ const zustandVersion = resolveCatalogBackedDependencyVersion({
37955
+ rootDirectory: directory,
37956
+ rootPackageJson: packageJson,
37957
+ packageName: "zustand",
37958
+ version: workspaceFacts.zustand.version
37959
+ });
37755
37960
  const hasReanimated = hasReactNativeWorkspace && workspaceFacts.hasReanimatedAwarePackage;
37756
37961
  const reanimatedVersion = hasReanimated ? workspaceFacts.reanimatedVersion : null;
37757
37962
  const nextjsVersion = framework === "nextjs" ? resolveCatalogBackedDependencyVersion({
@@ -37766,8 +37971,15 @@ const discoverProject = (directory) => {
37766
37971
  packageName: "valtio",
37767
37972
  version: workspaceFacts.valtioVersion
37768
37973
  });
37974
+ const mobxVersion = resolveCatalogBackedDependencyVersion({
37975
+ rootDirectory: directory,
37976
+ rootPackageJson: packageJson,
37977
+ packageName: "mobx",
37978
+ version: workspaceFacts.mobx.version
37979
+ });
37769
37980
  const preactVersion = getPreactVersion(packageJson);
37770
37981
  const remotionVersion = workspaceFacts.remotionVersion;
37982
+ const tanstackQueryVersion = getTanStackQueryVersion(packageJson) ?? workspaceFacts.tanstackQueryVersion;
37771
37983
  const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
37772
37984
  const projectInfo = {
37773
37985
  rootDirectory: directory,
@@ -37777,11 +37989,24 @@ const discoverProject = (directory) => {
37777
37989
  tailwindVersion,
37778
37990
  zodVersion,
37779
37991
  zodMajorVersion: zodVersion === null ? null : getLowestDependencyMajor(zodVersion),
37992
+ mobxVersion,
37993
+ mobxMajorVersion: mobxVersion === null ? null : getDependencyMajorWithinSupportedRange(mobxVersion, 6),
37994
+ hasMobxReact: workspaceFacts.hasMobxReact,
37995
+ mobxReactVersion: workspaceFacts.mobxReactVersion,
37996
+ hasMobxReactLite: workspaceFacts.hasMobxReactLite,
37997
+ mobxReactLiteVersion: workspaceFacts.mobxReactLiteVersion,
37998
+ hasMobxStateTree: workspaceFacts.hasMobxStateTree,
37999
+ hasMobxReactObserver: workspaceFacts.hasMobxReactObserver,
38000
+ zustandVersion,
38001
+ zustandMajorVersion: zustandVersion === null ? null : getLowestDependencyMajor(zustandVersion),
37780
38002
  framework,
37781
38003
  hasTypeScript,
37782
38004
  hasReactCompiler: detectReactCompiler(directory, packageJson),
37783
38005
  hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
37784
- hasTanStackQuery: hasTanStackQuery(packageJson),
38006
+ hasTanStackQuery: tanstackQueryVersion !== null,
38007
+ hasI18nLibrary: workspaceFacts.hasI18nLibrary,
38008
+ tanstackQueryVersion,
38009
+ styledComponentsVersion: workspaceFacts.styledComponentsVersion,
37785
38010
  valtioVersion,
37786
38011
  valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
37787
38012
  hasRemotion: workspaceFacts.hasRemotionDependency,
@@ -41112,21 +41337,62 @@ const buildCapabilities = (project) => {
41112
41337
  if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
41113
41338
  if (project.isStaticExport) capabilities.add("nextjs:static-export");
41114
41339
  if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
41340
+ if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 16) capabilities.add("nextjs:16");
41115
41341
  addMajorLadder(capabilities, "react", project.reactMajorVersion, 17, 30);
41116
41342
  if (project.reactMajorVersion !== null && project.reactMajorVersion >= 19 && isMajorMinorAtLeast(parseReactMajorMinor(project.reactVersion), {
41117
41343
  major: 19,
41118
41344
  minor: 2
41119
41345
  })) capabilities.add("react:19.2");
41120
- if (project.tailwindVersion !== null) capabilities.add("tailwind");
41121
- if (project.tailwindVersion !== null && isMajorMinorAtLeast(parseTailwindMajorMinor(project.tailwindVersion), {
41122
- major: 3,
41123
- minor: 4
41124
- })) capabilities.add("tailwind:3.4");
41346
+ if (project.tailwindVersion !== null) {
41347
+ capabilities.add("tailwind");
41348
+ const tailwindVersion = parseTailwindMajorMinor(project.tailwindVersion);
41349
+ if (isMajorMinorAtLeast(tailwindVersion, {
41350
+ major: 3,
41351
+ minor: 4
41352
+ })) capabilities.add("tailwind:3.4");
41353
+ if (tailwindVersion !== null && isMajorMinorAtLeast(tailwindVersion, {
41354
+ major: 4,
41355
+ minor: 0
41356
+ })) capabilities.add("tailwind:4");
41357
+ }
41125
41358
  if (project.zodVersion !== null) capabilities.add("zod");
41126
41359
  if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
41360
+ if (project.mobxVersion !== void 0 && project.mobxVersion !== null || project.hasMobxReact === true || project.hasMobxReactLite === true || project.hasMobxStateTree === true || project.hasMobxReactObserver === true) capabilities.add("mobx");
41361
+ if (project.hasMobxReact === true) capabilities.add("mobx-react");
41362
+ if (project.hasMobxReactLite === true) capabilities.add("mobx-react-lite");
41363
+ if (project.hasMobxReact === true || project.hasMobxReactLite === true) capabilities.add("mobx-react-binding");
41364
+ const mobxReactVersion = parseDependencyMajorMinor(project.mobxReactVersion);
41365
+ const mobxReactLiteVersion = parseDependencyMajorMinor(project.mobxReactLiteVersion);
41366
+ const hasMobxReactObserverMemoGuard = mobxReactVersion !== null && isMajorMinorAtLeast(mobxReactVersion, {
41367
+ major: 7,
41368
+ minor: 3
41369
+ });
41370
+ const hasMobxReactLiteObserverMemoGuard = mobxReactLiteVersion !== null && isMajorMinorAtLeast(mobxReactLiteVersion, {
41371
+ major: 3,
41372
+ minor: 3
41373
+ });
41374
+ if (hasMobxReactObserverMemoGuard) capabilities.add("mobx-react-observer-memo-guard");
41375
+ if (hasMobxReactLiteObserverMemoGuard) capabilities.add("mobx-react-lite-observer-memo-guard");
41376
+ if (hasMobxReactObserverMemoGuard || hasMobxReactLiteObserverMemoGuard) capabilities.add("mobx-react-binding-observer-memo-guard");
41377
+ if (project.hasMobxStateTree === true) capabilities.add("mobx-state-tree");
41378
+ if (project.hasMobxReactObserver === true) capabilities.add("mobx-react-observer");
41379
+ if (project.mobxMajorVersion !== void 0 && project.mobxMajorVersion !== null && project.mobxMajorVersion >= 4 && project.mobxMajorVersion <= 6) addMajorLadder(capabilities, "mobx", project.mobxMajorVersion, 4, 6);
41380
+ const mobxVersion = parseDependencyMajorMinor(project.mobxVersion);
41381
+ if (project.mobxMajorVersion === 6 && mobxVersion !== null && isMajorMinorAtLeast(mobxVersion, {
41382
+ major: 6,
41383
+ minor: 10
41384
+ })) capabilities.add("mobx:6.10");
41385
+ if (project.zustandVersion !== void 0 && project.zustandVersion !== null) capabilities.add("zustand");
41386
+ if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addMajorLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
41127
41387
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
41128
41388
  if (project.hasReactCompiler) capabilities.add("react-compiler");
41129
- if (project.hasTanStackQuery) capabilities.add("tanstack-query");
41389
+ if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
41390
+ if (project.styledComponentsVersion) {
41391
+ capabilities.add("styled-components");
41392
+ const styledComponentsMajor = getLowestDependencyMajor(project.styledComponentsVersion);
41393
+ if (styledComponentsMajor !== null && styledComponentsMajor >= 6) capabilities.add("styled-components:6");
41394
+ }
41395
+ if (project.hasI18nLibrary) capabilities.add("i18n");
41130
41396
  if (project.valtioVersion !== null) capabilities.add("valtio");
41131
41397
  addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
41132
41398
  if (project.hasRemotion) {
@@ -41147,7 +41413,7 @@ const getCapabilities = (project) => {
41147
41413
  capabilitiesByProject.set(project, capabilities);
41148
41414
  return capabilities;
41149
41415
  };
41150
- const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhen) => {
41416
+ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhen, includedTags) => {
41151
41417
  if (requires) {
41152
41418
  for (const capability of requires) if (!capabilities.has(capability)) return false;
41153
41419
  }
@@ -41158,20 +41424,29 @@ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhe
41158
41424
  if (tags) {
41159
41425
  for (const tag of tags) if (ignoredTags.has(tag)) return false;
41160
41426
  }
41427
+ if (includedTags && includedTags.size > 0) {
41428
+ if (!tags?.some((tag) => includedTags.has(tag))) return false;
41429
+ }
41161
41430
  return true;
41162
41431
  };
41432
+ const shouldEnableRuleByDefaultStatus = (options) => options.defaultEnabled !== false || options.hasExplicitOverride === true || options.includeTagDefaults && options.hasIncludedTags;
41163
41433
  const yieldToEventLoop = () => new Promise((resolve) => {
41164
41434
  setImmediate(resolve);
41165
41435
  });
41166
41436
  const createSecurityScanSession = (rootDirectory, options) => {
41167
41437
  const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
41168
41438
  const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
41439
+ const includedTags = options.includedTags ?? /* @__PURE__ */ new Set();
41169
41440
  const enabledScanRules = REACT_DOCTOR_RULES.flatMap((entry) => {
41170
41441
  const rule = entry.rule;
41171
41442
  const scan = rule.scan;
41172
41443
  if (typeof scan !== "function") return [];
41173
- if (rule.defaultEnabled === false) return [];
41174
- if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen)) return [];
41444
+ if (!shouldEnableRuleByDefaultStatus({
41445
+ defaultEnabled: rule.defaultEnabled,
41446
+ includeTagDefaults: options.includeTagDefaults === true,
41447
+ hasIncludedTags: includedTags.size > 0
41448
+ })) return [];
41449
+ if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) return [];
41175
41450
  return [{
41176
41451
  entry,
41177
41452
  scan,
@@ -43173,8 +43448,9 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
43173
43448
  }
43174
43449
  return enabled;
43175
43450
  };
43176
- const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
43177
- const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
43451
+ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
43452
+ const hasIncludedTags = includedTags.size > 0;
43453
+ const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
43178
43454
  const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
43179
43455
  const jsPlugins = [];
43180
43456
  if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
@@ -43189,9 +43465,14 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
43189
43465
  if (rule.scan !== void 0) continue;
43190
43466
  if (customRulesOnly && registryEntry.originallyExternal) continue;
43191
43467
  if (rule.framework !== "global" && !rule.requires) continue;
43192
- if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen)) continue;
43468
+ if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) continue;
43193
43469
  const explicitRuleOverride = resolveRuleSeverityOverride({ ruleKey: registryEntry.key }, severityControls);
43194
- if (rule.defaultEnabled === false && explicitRuleOverride === void 0) continue;
43470
+ if (!shouldEnableRuleByDefaultStatus({
43471
+ defaultEnabled: rule.defaultEnabled,
43472
+ includeTagDefaults,
43473
+ hasIncludedTags,
43474
+ hasExplicitOverride: explicitRuleOverride !== void 0
43475
+ })) continue;
43195
43476
  const severity = resolveRuleSeverityOverride({
43196
43477
  ruleKey: registryEntry.key,
43197
43478
  category: rule.category
@@ -43200,7 +43481,7 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
43200
43481
  enabledReactDoctorRules[registryEntry.key] = severity;
43201
43482
  }
43202
43483
  const userPluginRules = {};
43203
- if (ruleSelection !== "sidecar") for (const userPlugin of userPlugins) {
43484
+ if (ruleSelection !== "sidecar" && !hasIncludedTags) for (const userPlugin of userPlugins) {
43204
43485
  Object.assign(userPluginRules, buildUserPluginRules(userPlugin, severityControls));
43205
43486
  jsPlugins.push(userPlugin.entry);
43206
43487
  }
@@ -43417,6 +43698,19 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
43417
43698
  }
43418
43699
  };
43419
43700
  };
43701
+ const fingerprintCacheByFilePath = /* @__PURE__ */ new Map();
43702
+ const fingerprintFileContents = (filePath, fingerprintLength) => {
43703
+ const fileStats = NFS.statSync(filePath, { bigint: true });
43704
+ const cachedFingerprint = fingerprintCacheByFilePath.get(filePath);
43705
+ if (cachedFingerprint?.modifiedTimeNanoseconds === fileStats.mtimeNs && cachedFingerprint.sizeBytes === fileStats.size) return cachedFingerprint.fingerprint;
43706
+ const fingerprint = crypto.createHash("sha256").update(NFS.readFileSync(filePath)).digest("hex").slice(0, fingerprintLength);
43707
+ fingerprintCacheByFilePath.set(filePath, {
43708
+ fingerprint,
43709
+ modifiedTimeNanoseconds: fileStats.mtimeNs,
43710
+ sizeBytes: fileStats.size
43711
+ });
43712
+ return fingerprint;
43713
+ };
43420
43714
  const bundledRequire$3 = createRequire(import.meta.url);
43421
43715
  const childNodeVersionByBinaryPath = /* @__PURE__ */ new Map();
43422
43716
  const resolveChildNodeVersion = (nodeBinaryPath) => {
@@ -43440,6 +43734,13 @@ const TOOLCHAIN_PACKAGE_SPECIFIERS$1 = [
43440
43734
  "oxlint-plugin-react-doctor/package.json",
43441
43735
  "eslint-plugin-react-hooks/package.json"
43442
43736
  ];
43737
+ const resolvePluginFingerprint = () => {
43738
+ try {
43739
+ return fingerprintFileContents(bundledRequire$3.resolve("oxlint-plugin-react-doctor"), 16);
43740
+ } catch {
43741
+ return "unresolved";
43742
+ }
43743
+ };
43443
43744
  const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
43444
43745
  const versions = [`node=${resolveChildNodeVersion(nodeBinaryPath)}`];
43445
43746
  for (const specifier of TOOLCHAIN_PACKAGE_SPECIFIERS$1) try {
@@ -43449,6 +43750,7 @@ const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
43449
43750
  } catch {
43450
43751
  versions.push(`${specifier}=missing`);
43451
43752
  }
43753
+ versions.push(`oxlint-plugin-react-doctor#fingerprint=${resolvePluginFingerprint()}`);
43452
43754
  return versions;
43453
43755
  };
43454
43756
  const esmRequire = createRequire(import.meta.url);
@@ -44924,7 +45226,7 @@ const reactHooksJsPluginDropNote = (error) => {
44924
45226
  * 6. always restore disable directives + clean up the temp dir
44925
45227
  */
44926
45228
  const runOxlint = async (options) => {
44927
- 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;
45229
+ 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;
44928
45230
  const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
44929
45231
  const severityControls = buildRuleSeverityControls(userConfig);
44930
45232
  validateRuleRegistration();
@@ -44938,13 +45240,15 @@ const runOxlint = async (options) => {
44938
45240
  }
44939
45241
  const pluginPath = resolvePluginPath();
44940
45242
  const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
44941
- const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
45243
+ const userPlugins = includedTags.size > 0 ? [] : resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
44942
45244
  const buildConfig = (overrides) => createOxlintConfig({
44943
45245
  pluginPath,
44944
45246
  project,
44945
45247
  customRulesOnly,
44946
45248
  extendsPaths: overrides.extendsPaths,
44947
45249
  ignoredTags,
45250
+ includedTags,
45251
+ includeTagDefaults,
44948
45252
  serverAuthFunctionNames,
44949
45253
  severityControls,
44950
45254
  userPlugins,
@@ -45333,6 +45637,8 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
45333
45637
  respectInlineDisables: input.respectInlineDisables,
45334
45638
  adoptExistingLintConfig: input.adoptExistingLintConfig,
45335
45639
  ignoredTags: input.ignoredTags,
45640
+ includedTags: input.includedTags,
45641
+ includeTagDefaults: input.includeTagDefaults,
45336
45642
  userConfig: input.userConfig ?? null,
45337
45643
  configSourceDirectory: input.configSourceDirectory,
45338
45644
  onPartialFailure: (reason) => {
@@ -46181,7 +46487,9 @@ const runInspect = (input, hooks = {}) => gen(function* () {
46181
46487
  const securityScanFailedRef = yield* make$13(false);
46182
46488
  const securityScanFiber = yield* forkChild(runCollect(applyPerElementPipeline(isDiffMode ? empty$4 : unwrap(tryPromise(() => checkSecurityScanCooperative(scanDirectory, {
46183
46489
  project,
46184
- ignoredTags: input.ignoredTags
46490
+ ignoredTags: input.ignoredTags,
46491
+ includedTags: input.includedTags,
46492
+ includeTagDefaults: input.includeTagDefaults
46185
46493
  })).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), catch_$1(() => set(securityScanFailedRef, true).pipe(as(empty$4))))))).pipe(withSpan("SecurityScan.run")));
46186
46494
  const shouldRunSupplyChain = !isDiffMode || (input.supplyChainManifestChanged ?? false);
46187
46495
  const supplyChainOverlapTimeout = yield* SupplyChainOverlapTimeoutMs;
@@ -46272,6 +46580,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
46272
46580
  respectInlineDisables: input.respectInlineDisables,
46273
46581
  adoptExistingLintConfig: input.adoptExistingLintConfig,
46274
46582
  ignoredTags: input.ignoredTags,
46583
+ includedTags: input.includedTags,
46584
+ includeTagDefaults: input.includeTagDefaults,
46275
46585
  userConfig: resolvedConfig.config ?? void 0,
46276
46586
  configSourceDirectory: resolvedConfig.configSourceDirectory ?? void 0,
46277
46587
  onFileProgress: (scannedFileCount, totalFileCount) => {
@@ -47416,7 +47726,7 @@ const makeNoopConsole = () => ({
47416
47726
  });
47417
47727
  //#endregion
47418
47728
  //#region src/cli/utils/version.ts
47419
- const VERSION = "0.8.1-dev.f4aa821";
47729
+ const VERSION = "0.8.1-dev.fc1b3a3";
47420
47730
  //#endregion
47421
47731
  //#region src/cli/utils/json-mode.ts
47422
47732
  let context = null;
@@ -47503,7 +47813,11 @@ const getRunId = () => {
47503
47813
  };
47504
47814
  //#endregion
47505
47815
  //#region src/cli/utils/build-run-context.ts
47506
- const ROOT_SUBCOMMANDS = new Set(["install", "setup"]);
47816
+ const ROOT_SUBCOMMANDS = new Set([
47817
+ "design",
47818
+ "install",
47819
+ "setup"
47820
+ ]);
47507
47821
  const detectInvokedVia = () => {
47508
47822
  const userAgent = process.env.npm_config_user_agent;
47509
47823
  if (!userAgent) return "unknown";
@@ -47587,7 +47901,9 @@ const buildSentryProjectContext = (projectInfo) => ({
47587
47901
  reactMajorVersion: projectInfo.reactMajorVersion,
47588
47902
  hasTypeScript: projectInfo.hasTypeScript,
47589
47903
  hasReactCompiler: projectInfo.hasReactCompiler,
47590
- hasTanStackQuery: projectInfo.hasTanStackQuery,
47904
+ tanstackQueryVersion: projectInfo.tanstackQueryVersion,
47905
+ mobxVersion: projectInfo.mobxVersion,
47906
+ styledComponentsVersion: projectInfo.styledComponentsVersion,
47591
47907
  tailwindVersion: projectInfo.tailwindVersion,
47592
47908
  zodVersion: projectInfo.zodVersion,
47593
47909
  preactVersion: projectInfo.preactVersion,
@@ -47768,13 +48084,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
47768
48084
  * uploads source-map artifacts under, so stack frames symbolicate. Honors the
47769
48085
  * standard `SENTRY_RELEASE` override.
47770
48086
  */
47771
- const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.8.1-dev.f4aa821`;
48087
+ const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.8.1-dev.fc1b3a3`;
47772
48088
  /**
47773
48089
  * Deployment environment shown in Sentry's environment filter. Defaults to
47774
48090
  * `production` for tagged releases and `development` for dev/unbuilt versions,
47775
48091
  * overridable via the standard `SENTRY_ENVIRONMENT` env var.
47776
48092
  */
47777
- const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.8.1-dev.f4aa821") ? "development" : "production");
48093
+ const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.8.1-dev.fc1b3a3") ? "development" : "production");
47778
48094
  /**
47779
48095
  * Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
47780
48096
  * (set to `0` to disable tracing) and falls back to
@@ -60100,6 +60416,8 @@ const buildScanResultCacheKey = (input) => {
60100
60416
  warnings: input.options.warnings,
60101
60417
  adoptExistingLintConfig: input.options.adoptExistingLintConfig,
60102
60418
  ignoredTags: [...input.options.ignoredTags].sort(),
60419
+ includedTags: [...input.options.includedTags].sort(),
60420
+ includeTagDefaults: input.options.includeTagDefaults,
60103
60421
  concurrency: input.options.concurrency,
60104
60422
  lintBatchOrdering: resolveLintBatchOrdering(),
60105
60423
  baselineRef: input.options.baseline?.ref,
@@ -60926,8 +61244,8 @@ const createDiagnosticEvidenceReader = (rootDirectory, options = {}) => {
60926
61244
  //#endregion
60927
61245
  //#region src/cli/utils/build-no-score-message.ts
60928
61246
  const ENTERPRISE_CONTACT_HINT = `Want something custom to your company? Contact us at ${ENTERPRISE_CONTACT_URL}.`;
60929
- const buildNoScoreMessage = (isScoreDisabled) => {
60930
- return `${isScoreDisabled ? "Score disabled by --no-score." : "Score unavailable (could not reach the score API)."} ${ENTERPRISE_CONTACT_HINT}`;
61247
+ const buildNoScoreMessage = (isScoreDisabled, disabledMessage) => {
61248
+ return `${isScoreDisabled ? disabledMessage ?? "Score disabled by --no-score." : "Score unavailable (could not reach the score API)."} ${ENTERPRISE_CONTACT_HINT}`;
60931
61249
  };
60932
61250
  //#endregion
60933
61251
  //#region src/cli/utils/render-agent-guidance.ts
@@ -62052,40 +62370,47 @@ const buildChangedLineMatcher = (directory, changedLineRanges) => {
62052
62370
  return diagnosticIntersectsLineRanges(diagnostic, ranges);
62053
62371
  };
62054
62372
  };
62055
- const buildIgnoredTags = (userConfig) => {
62373
+ const buildIgnoredTags = (userConfig, includedTags) => {
62056
62374
  const tags = /* @__PURE__ */ new Set();
62057
62375
  if (userConfig?.ignore?.tags) for (const tag of userConfig.ignore.tags) tags.add(tag);
62376
+ for (const tag of includedTags) tags.delete(tag);
62058
62377
  return tags;
62059
62378
  };
62060
- const mergeInspectOptions = (inputOptions, userConfig) => ({
62061
- lint: inputOptions.lint ?? userConfig?.lint ?? true,
62062
- deadCode: inputOptions.deadCode ?? userConfig?.deadCode ?? true,
62063
- supplyChain: inputOptions.supplyChain ?? userConfig?.supplyChain?.enabled ?? true,
62064
- verbose: inputOptions.verbose ?? userConfig?.verbose ?? false,
62065
- outputDirectory: inputOptions.outputDirectory || null,
62066
- scoreOnly: inputOptions.scoreOnly ?? false,
62067
- noScore: inputOptions.noScore ?? userConfig?.noScore ?? false,
62068
- isCi: inputOptions.isCi ?? false,
62069
- isCiOrCodingAgentEnvironment: isCiOrCodingAgentEnvironment(),
62070
- isNonInteractiveEnvironment: isNonInteractiveEnvironment(),
62071
- silent: inputOptions.silent ?? false,
62072
- includePaths: inputOptions.includePaths ?? [],
62073
- customRulesOnly: userConfig?.customRulesOnly ?? false,
62074
- share: userConfig?.share ?? true,
62075
- respectInlineDisables: inputOptions.respectInlineDisables ?? userConfig?.respectInlineDisables ?? true,
62076
- warnings: inputOptions.warnings ?? userConfig?.warnings ?? true,
62077
- categoryFilters: new Set(resolveCliCategories(inputOptions.categoryFilters) ?? []),
62078
- adoptExistingLintConfig: userConfig?.adoptExistingLintConfig ?? true,
62079
- ignoredTags: buildIgnoredTags(userConfig),
62080
- outputSurface: inputOptions.outputSurface ?? "cli",
62081
- suppressRendering: inputOptions.suppressRendering ?? false,
62082
- concurrentScan: inputOptions.concurrentScan ?? false,
62083
- concurrency: inputOptions.concurrency,
62084
- maxDurationMs: inputOptions.maxDurationMs ?? null,
62085
- baseline: inputOptions.baseline ?? null,
62086
- changedLineRanges: inputOptions.changedLineRanges ?? null,
62087
- supplyChainManifestChanged: inputOptions.supplyChainManifestChanged ?? false
62088
- });
62379
+ const mergeInspectOptions = (inputOptions, userConfig) => {
62380
+ const includedTags = inputOptions.includedTags ?? /* @__PURE__ */ new Set();
62381
+ return {
62382
+ lint: inputOptions.lint ?? userConfig?.lint ?? true,
62383
+ deadCode: inputOptions.deadCode ?? userConfig?.deadCode ?? true,
62384
+ supplyChain: inputOptions.supplyChain ?? userConfig?.supplyChain?.enabled ?? true,
62385
+ verbose: inputOptions.verbose ?? userConfig?.verbose ?? false,
62386
+ outputDirectory: inputOptions.outputDirectory || null,
62387
+ scoreOnly: inputOptions.scoreOnly ?? false,
62388
+ noScore: inputOptions.noScore ?? userConfig?.noScore ?? false,
62389
+ isCi: inputOptions.isCi ?? false,
62390
+ isCiOrCodingAgentEnvironment: isCiOrCodingAgentEnvironment(),
62391
+ isNonInteractiveEnvironment: isNonInteractiveEnvironment(),
62392
+ silent: inputOptions.silent ?? false,
62393
+ includePaths: inputOptions.includePaths ?? [],
62394
+ customRulesOnly: includedTags.size > 0 ? false : userConfig?.customRulesOnly ?? false,
62395
+ share: userConfig?.share ?? true,
62396
+ respectInlineDisables: inputOptions.respectInlineDisables ?? userConfig?.respectInlineDisables ?? true,
62397
+ warnings: inputOptions.warnings ?? userConfig?.warnings ?? true,
62398
+ categoryFilters: new Set(resolveCliCategories(inputOptions.categoryFilters) ?? []),
62399
+ adoptExistingLintConfig: includedTags.size > 0 ? false : userConfig?.adoptExistingLintConfig ?? true,
62400
+ ignoredTags: buildIgnoredTags(userConfig, includedTags),
62401
+ includedTags,
62402
+ includeTagDefaults: inputOptions.includeTagDefaults ?? false,
62403
+ scoreDisabledMessage: inputOptions.scoreDisabledMessage,
62404
+ outputSurface: inputOptions.outputSurface ?? "cli",
62405
+ suppressRendering: inputOptions.suppressRendering ?? false,
62406
+ concurrentScan: inputOptions.concurrentScan ?? false,
62407
+ concurrency: inputOptions.concurrency,
62408
+ maxDurationMs: inputOptions.maxDurationMs ?? null,
62409
+ baseline: inputOptions.baseline ?? null,
62410
+ changedLineRanges: inputOptions.changedLineRanges ?? null,
62411
+ supplyChainManifestChanged: inputOptions.supplyChainManifestChanged ?? false
62412
+ };
62413
+ };
62089
62414
  const deriveScope = (options) => {
62090
62415
  if (options.baseline) return "changed";
62091
62416
  if (options.changedLineRanges !== null) return "lines";
@@ -62216,6 +62541,8 @@ const runBaselineComparison = async (params) => {
62216
62541
  warnings: params.options.warnings,
62217
62542
  adoptExistingLintConfig: params.options.adoptExistingLintConfig,
62218
62543
  ignoredTags: params.options.ignoredTags,
62544
+ includedTags: params.options.includedTags,
62545
+ includeTagDefaults: params.options.includeTagDefaults,
62219
62546
  nodeBinaryPath: params.resolvedNodeBinaryPath ?? void 0,
62220
62547
  runDeadCode: false,
62221
62548
  isCi: params.options.isCi,
@@ -62309,6 +62636,8 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
62309
62636
  warnings: options.warnings,
62310
62637
  adoptExistingLintConfig: options.adoptExistingLintConfig,
62311
62638
  ignoredTags: options.ignoredTags,
62639
+ includedTags: options.includedTags,
62640
+ includeTagDefaults: options.includeTagDefaults,
62312
62641
  nodeBinaryPath: resolvedNodeBinaryPath ?? void 0,
62313
62642
  runDeadCode: options.deadCode,
62314
62643
  isCi: options.isCi,
@@ -62497,7 +62826,7 @@ const finalizeAndRender = (input) => gen(function* () {
62497
62826
  securityScanFailed
62498
62827
  });
62499
62828
  const hasSkippedChecks = skippedChecks.length > 0;
62500
- const noScoreMessage = buildNoScoreMessage(options.noScore);
62829
+ const noScoreMessage = buildNoScoreMessage(options.noScore, options.scoreDisabledMessage);
62501
62830
  const buildResult = () => ({
62502
62831
  diagnostics: [...diagnostics],
62503
62832
  score,
@@ -64602,21 +64931,25 @@ const resolveParallelFlag = (parallel) => parallel === false ? 1 : void 0;
64602
64931
  */
64603
64932
  const resolveCliInspectOptions = (flags, userConfig) => {
64604
64933
  const wantsWarningGate = pickBlockingLevel(flags, userConfig) === "warning";
64934
+ const isDesignScan = flags.design === true;
64605
64935
  return {
64606
64936
  lint: flags.lint,
64607
- deadCode: flags.deadCode,
64608
- supplyChain: flags.supplyChain,
64937
+ deadCode: isDesignScan ? false : flags.deadCode,
64938
+ supplyChain: isDesignScan ? false : flags.supplyChain,
64609
64939
  verbose: flags.verbose,
64610
64940
  outputDirectory: flags.outputDir,
64611
64941
  respectInlineDisables: flags.respectInlineDisables === false ? false : void 0,
64612
64942
  warnings: wantsWarningGate ? true : flags.warnings,
64613
64943
  scoreOnly: flags.score === true,
64614
- noScore: flags.score === false || flags.telemetry === false ? true : void 0,
64944
+ noScore: isDesignScan || flags.score === false || flags.telemetry === false ? true : void 0,
64615
64945
  isCi: isCiEnvironment(),
64616
64946
  silent: Boolean(flags.json),
64617
64947
  concurrency: resolveParallelFlag(flags.parallel),
64618
64948
  maxDurationMs: resolveMaxDurationFlag(flags.maxDuration),
64619
- categoryFilters: resolveCliCategories(flags.category)
64949
+ categoryFilters: resolveCliCategories(flags.category),
64950
+ includedTags: isDesignScan ? new Set(["design"]) : void 0,
64951
+ includeTagDefaults: isDesignScan ? true : void 0,
64952
+ scoreDisabledMessage: isDesignScan ? "Design scans do not affect the React health score." : void 0
64620
64953
  };
64621
64954
  };
64622
64955
  //#endregion
@@ -65034,7 +65367,7 @@ const maybeMigrateLegacyConfig = async (requestedDirectory, { isQuiet, isStaged
65034
65367
  if (!(!isQuiet && !isStaged && process.stdout.isTTY === true && !isCiOrCodingAgentEnvironment())) return;
65035
65368
  await runProjectMigrations(requestedDirectory);
65036
65369
  };
65037
- const inspectAction = async (directory, flags) => {
65370
+ const inspectAction = async (directory, flags, invocationCommand = "inspect") => {
65038
65371
  const isScoreOnly = Boolean(flags.score);
65039
65372
  const isJsonMode = Boolean(flags.json);
65040
65373
  const isQuiet = isScoreOnly || isJsonMode;
@@ -65048,7 +65381,7 @@ const inspectAction = async (directory, flags) => {
65048
65381
  });
65049
65382
  if (flags.jsonOut) recordCount(METRIC.jsonOutUsed, 1);
65050
65383
  }
65051
- recordCount(METRIC.cliInvoked, 1, { command: "inspect" });
65384
+ recordCount(METRIC.cliInvoked, 1, { command: invocationCommand });
65052
65385
  try {
65053
65386
  validateModeFlags(flags);
65054
65387
  if (flags.staged) setJsonReportMode("staged");
@@ -65360,6 +65693,13 @@ const inspectAction = async (directory, flags) => {
65360
65693
  }
65361
65694
  };
65362
65695
  //#endregion
65696
+ //#region src/cli/commands/design.ts
65697
+ const designAction = async (directory, flags) => inspectAction(directory, {
65698
+ ...flags,
65699
+ design: true,
65700
+ lint: flags.lint ?? true
65701
+ }, "design");
65702
+ //#endregion
65363
65703
  //#region src/cli/commands/install.ts
65364
65704
  const installAction = async (options, command) => {
65365
65705
  recordCount(METRIC.cliInvoked, 1, { command: "install" });
@@ -66196,6 +66536,7 @@ const INSTALL_FLAG_SPEC = {
66196
66536
  shortOptionsWithRequiredValues: new Set(["-c"])
66197
66537
  };
66198
66538
  const COMMAND_FLAG_SPECS = new Map([
66539
+ ["design", ROOT_FLAG_SPEC],
66199
66540
  ["install", INSTALL_FLAG_SPEC],
66200
66541
  ["setup", INSTALL_FLAG_SPEC],
66201
66542
  ["version", {
@@ -66352,6 +66693,7 @@ ${formatExampleLines([
66352
66693
  ["react-doctor --scope changed --base main", "scan only new issues vs. main"],
66353
66694
  ["react-doctor --project modules/a,modules/b", "score each module separately (names or paths)"],
66354
66695
  ["react-doctor --staged", "scan staged files (pre-commit hook)"],
66696
+ ["react-doctor design", "run the focused UI design audit"],
66355
66697
  ["react-doctor --category Security", "show only one diagnostic category"],
66356
66698
  ["react-doctor --blocking warning", "fail CI on warnings too (default: error)"],
66357
66699
  ["react-doctor --json > report.json", "write a machine-readable report"],
@@ -66385,6 +66727,20 @@ ${highlighter.dim("Managing CI:")}
66385
66727
  ${highlighter.dim("Learn more:")}
66386
66728
  ${highlighter.info(CANONICAL_GITHUB_URL)}
66387
66729
  `;
66730
+ const renderDesignHelpEpilog = () => `
66731
+ ${highlighter.dim("Examples:")}
66732
+ ${formatExampleLines([
66733
+ ["react-doctor design", "audit UI design in the current project"],
66734
+ ["react-doctor design ./apps/web", "audit one application"],
66735
+ ["react-doctor design --verbose", "show every design finding"],
66736
+ ["react-doctor design --json", "write a design-only JSON report"]
66737
+ ])}
66738
+
66739
+ ${highlighter.dim("Scope:")}
66740
+ Runs only rules tagged ${highlighter.info("design")}, including focused rules that stay opt-in during a general health scan.
66741
+ Dead-code, supply-chain, external lint-config, custom-plugin, and health-score passes are skipped.
66742
+ Standard scan flags such as ${highlighter.info("--scope")}, ${highlighter.info("--project")}, ${highlighter.info("--verbose")}, and ${highlighter.info("--json")} still work.
66743
+ `;
66388
66744
  const renderCiHelpEpilog = () => `
66389
66745
  ${highlighter.dim("Examples:")}
66390
66746
  ${formatExampleLines([
@@ -66406,6 +66762,7 @@ ${highlighter.dim("Learn more:")}
66406
66762
  const collectCategoryOption = (value, previousValues) => [...previousValues ?? [], value];
66407
66763
  const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS source to scan/report: full (default), files, changed (only new issues vs base), or lines (issues whose source spans touch changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").option("--include-untracked", "with --scope files/changed/lines, also scan ordinary untracked files (respects .gitignore)").addOption(new Option("--diff [base]", "[deprecated] alias for --scope changed (pass `false` to force a full scan)").hideHelp()).addOption(new Option("--changed-files-from <file>", "scan source files listed in a newline-delimited changed-files file").hideHelp()).option("--no-score", "skip the score API, the share URL, and crash reporting").addOption(new Option("--category <category>", "only show diagnostics in a category (repeatable; e.g. Security)").argParser(collectCategoryOption)).option("--no-telemetry", "alias for --no-score (skip the score API, share URL, and crash reporting)").option("--staged", "scan only staged (git index) files for pre-commit hooks").option("--max-duration <seconds>", "scan time budget for the whole run, shared across workspace projects: past it, remaining lint batches and dead-code are skipped and partial results are reported (skipped files are listed in the JSON report)").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").addOption(new Option("--fail-on <level>", "[deprecated] alias for --blocking <level>").hideHelp()).option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").option("--warnings", "show warning-severity diagnostics (default)").option("--no-warnings", "hide warning-severity diagnostics (errors only)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderRootHelpEpilog);
66408
66764
  program.action(inspectAction);
66765
+ program.command("design [directory]").description("Run only the focused UI design diagnostics").addHelpText("after", renderDesignHelpEpilog).action((directory, _options, command) => designAction(directory ?? ".", command.optsWithGlobals()));
66409
66766
  program.command("why <location>").description("Explain why a rule fired (or why a suppression didn't apply) at a file:line").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple)").option("-c, --cwd <cwd>", "working directory", process.cwd()).option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").action((location, options) => whyAction(location, options));
66410
66767
  program.command("install").alias("setup").description("Install the react-doctor skill into your coding agents and optional git hook").option("-y, --yes", "skip prompts, install for all detected agents").option("--dry-run", "show what would be installed without writing files").option("--agent-hooks", "install native non-blocking agent hooks for Claude Code and Cursor").option("-c, --cwd <cwd>", "working directory", process.cwd()).option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderInstallHelpEpilog).action(installAction);
66411
66768
  const providerOption = ["--provider <name>", "ci provider: github-actions or gitlab-ci (auto-detected by default)"];
@@ -66454,4 +66811,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
66454
66811
  export {};
66455
66812
 
66456
66813
  //# sourceMappingURL=cli.js.map
66457
- //# debugId=1b59ca76-9135-54e6-9391-ce7fec27b699
66814
+ //# debugId=d92b0964-cd34-5965-a1bf-ce1d06faf742