react-doctor 0.8.1-dev.5332cb6 → 0.8.1-dev.5774353

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]="24153a3f-aef9-53fd-8dff-9b016a9613fb")}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]="83a484ab-e975-5390-830a-f2f723c71935")}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";
@@ -37361,6 +37361,10 @@ const evaluateManifestFacts = (facts, packageJson, directory) => {
37361
37361
  const spec = getDependencySpec(packageJson, REANIMATED_DEPENDENCY_NAME);
37362
37362
  if (spec !== null) facts.reanimatedVersion = spec;
37363
37363
  }
37364
+ if (facts.valtioVersion === null) {
37365
+ const spec = getDependencySpec(packageJson, "valtio");
37366
+ if (spec !== null) facts.valtioVersion = spec;
37367
+ }
37364
37368
  facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
37365
37369
  facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
37366
37370
  facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
@@ -37383,6 +37387,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
37383
37387
  version: null,
37384
37388
  sourceDirectory: null
37385
37389
  },
37390
+ valtioVersion: null,
37386
37391
  hasReactNativeAwarePackage: false,
37387
37392
  hasReanimatedAwarePackage: false,
37388
37393
  hasSsrDependency: false,
@@ -37623,6 +37628,8 @@ const discoverProjectWithoutPackageJson = (directory) => {
37623
37628
  hasReactCompiler: false,
37624
37629
  hasReactCompilerLintPlugin: false,
37625
37630
  hasTanStackQuery: false,
37631
+ valtioVersion: null,
37632
+ valtioMajorVersion: null,
37626
37633
  hasSsrDependency: false,
37627
37634
  preactVersion: null,
37628
37635
  preactMajorVersion: null,
@@ -37729,6 +37736,12 @@ const discoverProject = (directory) => {
37729
37736
  packageName: "next",
37730
37737
  version: workspaceFacts.next.version
37731
37738
  }) : null;
37739
+ const valtioVersion = resolveCatalogBackedDependencyVersion({
37740
+ rootDirectory: directory,
37741
+ rootPackageJson: packageJson,
37742
+ packageName: "valtio",
37743
+ version: workspaceFacts.valtioVersion
37744
+ });
37732
37745
  const preactVersion = getPreactVersion(packageJson);
37733
37746
  const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
37734
37747
  const projectInfo = {
@@ -37744,6 +37757,8 @@ const discoverProject = (directory) => {
37744
37757
  hasReactCompiler: detectReactCompiler(directory, packageJson),
37745
37758
  hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
37746
37759
  hasTanStackQuery: hasTanStackQuery(packageJson),
37760
+ valtioVersion,
37761
+ valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
37747
37762
  hasSsrDependency: workspaceFacts.hasSsrDependency,
37748
37763
  preactVersion,
37749
37764
  preactMajorVersion: parseReactMajor(preactVersion),
@@ -37977,7 +37992,6 @@ const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
37977
37992
  "react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
37978
37993
  "react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
37979
37994
  "react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
37980
- "react/jsx-no-target-blank": "react-doctor/jsx-no-target-blank",
37981
37995
  "react/jsx-no-undef": "react-doctor/jsx-no-undef",
37982
37996
  "react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
37983
37997
  "react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
@@ -40299,9 +40313,25 @@ const BABEL_CONFIG_FILE_NAMES = [
40299
40313
  ".babelrc.json"
40300
40314
  ];
40301
40315
  const LEGACY_PRESET_SPEC = "module:metro-react-native-babel-preset";
40316
+ const LEGACY_PRESET_PACKAGE = "metro-react-native-babel-preset";
40317
+ const REACT_NATIVE_PACKAGE = "react-native";
40318
+ const PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION = "0.73.0";
40319
+ const LEGACY_PRESET_REFERENCE = new RegExp(`['"]${LEGACY_PRESET_SPEC}['"]`);
40302
40320
  const MODERN_PRESET_REFERENCE = new RegExp(`['"]module:@react-native/babel-preset['"]`);
40303
40321
  const ENABLE_BABEL_RUNTIME_VERSION = /enableBabelRuntime["']?\s*:\s*['"]/;
40322
+ const isReactNativeVersionAtLeastPresetRename = (rootDirectory, packageJson) => {
40323
+ const installedReactNativeManifestPath = Path.join(rootDirectory, "node_modules", REACT_NATIVE_PACKAGE, "package.json");
40324
+ const reactNativeVersionSpec = (isFile(installedReactNativeManifestPath) ? readPackageJson$1(installedReactNativeManifestPath).version : void 0) ?? getDependencySpec(packageJson, REACT_NATIVE_PACKAGE);
40325
+ if (reactNativeVersionSpec === null || reactNativeVersionSpec === void 0) return false;
40326
+ const normalizedVersionRange = import_semver.validRange(reactNativeVersionSpec);
40327
+ if (normalizedVersionRange === null) return false;
40328
+ const minimumVersion = import_semver.minVersion(normalizedVersionRange);
40329
+ return minimumVersion !== null && import_semver.gte(minimumVersion, PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION);
40330
+ };
40331
+ const canResolveLegacyPreset = (rootDirectory, packageJson) => getDependencySpec(packageJson, LEGACY_PRESET_PACKAGE) !== null || isFile(Path.join(rootDirectory, "node_modules", LEGACY_PRESET_PACKAGE, "package.json"));
40304
40332
  const checkReactNativeMetroBabelPreset = (rootDirectory) => {
40333
+ const packageJson = readPackageJson$1(Path.join(rootDirectory, "package.json"));
40334
+ const shouldReportLegacyPreset = isReactNativeVersionAtLeastPresetRename(rootDirectory, packageJson) && !canResolveLegacyPreset(rootDirectory, packageJson);
40305
40335
  for (const fileName of BABEL_CONFIG_FILE_NAMES) {
40306
40336
  const filePath = Path.join(rootDirectory, fileName);
40307
40337
  if (!isFile(filePath)) continue;
@@ -40311,7 +40341,7 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
40311
40341
  } catch {
40312
40342
  continue;
40313
40343
  }
40314
- if (contents.includes(LEGACY_PRESET_SPEC)) return [buildReactNativeDiagnostic({
40344
+ if (shouldReportLegacyPreset && LEGACY_PRESET_REFERENCE.test(contents)) return [buildReactNativeDiagnostic({
40315
40345
  filePath: fileName,
40316
40346
  rule: "rn-no-metro-babel-preset",
40317
40347
  severity: "error",
@@ -40334,12 +40364,6 @@ const checkReactNativeProject = (rootDirectory, project) => {
40334
40364
  return [...checkReactNativeMetroBabelPreset(rootDirectory), ...checkReactNativeLibraryDependencies(rootDirectory)];
40335
40365
  };
40336
40366
  const RULE_KEY = "no-vulnerable-react-server-components";
40337
- const DEPENDENCY_SECTIONS = [
40338
- "dependencies",
40339
- "devDependencies",
40340
- "peerDependencies",
40341
- "optionalDependencies"
40342
- ];
40343
40367
  const REACT_RSC_ADVISORIES_BY_MINOR = {
40344
40368
  "19.0": {
40345
40369
  rceFixedVersion: "19.0.1",
@@ -40386,20 +40410,13 @@ const enumerateWorkspaceDirectories = (workspaceRoot) => {
40386
40410
  for (const pattern of patterns) for (const directory of resolveWorkspaceDirectories(workspaceRoot, pattern)) directories.add(directory);
40387
40411
  return [...directories];
40388
40412
  };
40389
- const readDeclaredSpec = (packageJson, packageName) => {
40390
- for (const section of DEPENDENCY_SECTIONS) {
40391
- const spec = packageJson[section]?.[packageName];
40392
- if (typeof spec === "string") return spec;
40393
- }
40394
- return null;
40395
- };
40396
40413
  const resolveVersionInDirectory = (directory, packageName, declaredSpecOverride) => {
40397
40414
  const manifestPath = Path.join(directory, "node_modules", packageName, "package.json");
40398
40415
  if (isFile(manifestPath)) {
40399
40416
  const installedVersion = import_semver.valid(readPackageJson$1(manifestPath).version ?? null);
40400
40417
  if (installedVersion !== null) return installedVersion;
40401
40418
  }
40402
- const candidateSpecs = [readDeclaredSpec(readPackageJson$1(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
40419
+ const candidateSpecs = [getDependencySpec(readPackageJson$1(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
40403
40420
  for (const spec of candidateSpecs) {
40404
40421
  const pinnedVersion = spec === null ? null : import_semver.valid(spec);
40405
40422
  if (pinnedVersion !== null) return pinnedVersion;
@@ -41082,6 +41099,8 @@ const buildCapabilities = (project) => {
41082
41099
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
41083
41100
  if (project.hasReactCompiler) capabilities.add("react-compiler");
41084
41101
  if (project.hasTanStackQuery) capabilities.add("tanstack-query");
41102
+ if (project.valtioVersion !== null) capabilities.add("valtio");
41103
+ addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
41085
41104
  if (project.hasTypeScript) capabilities.add("typescript");
41086
41105
  if (project.preactVersion !== null) capabilities.add("preact");
41087
41106
  addMajorLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
@@ -47365,7 +47384,7 @@ const makeNoopConsole = () => ({
47365
47384
  });
47366
47385
  //#endregion
47367
47386
  //#region src/cli/utils/version.ts
47368
- const VERSION = "0.8.1-dev.5332cb6";
47387
+ const VERSION = "0.8.1-dev.5774353";
47369
47388
  //#endregion
47370
47389
  //#region src/cli/utils/json-mode.ts
47371
47390
  let context = null;
@@ -47717,13 +47736,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
47717
47736
  * uploads source-map artifacts under, so stack frames symbolicate. Honors the
47718
47737
  * standard `SENTRY_RELEASE` override.
47719
47738
  */
47720
- const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.8.1-dev.5332cb6`;
47739
+ const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.8.1-dev.5774353`;
47721
47740
  /**
47722
47741
  * Deployment environment shown in Sentry's environment filter. Defaults to
47723
47742
  * `production` for tagged releases and `development` for dev/unbuilt versions,
47724
47743
  * overridable via the standard `SENTRY_ENVIRONMENT` env var.
47725
47744
  */
47726
- const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.8.1-dev.5332cb6") ? "development" : "production");
47745
+ const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.8.1-dev.5774353") ? "development" : "production");
47727
47746
  /**
47728
47747
  * Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
47729
47748
  * (set to `0` to disable tracing) and falls back to
@@ -66403,4 +66422,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
66403
66422
  export {};
66404
66423
 
66405
66424
  //# sourceMappingURL=cli.js.map
66406
- //# debugId=24153a3f-aef9-53fd-8dff-9b016a9613fb
66425
+ //# debugId=83a484ab-e975-5390-830a-f2f723c71935
package/dist/index.d.ts CHANGED
@@ -9548,6 +9548,15 @@ interface ProjectInfo {
9548
9548
  hasReactCompiler: boolean;
9549
9549
  hasReactCompilerLintPlugin?: boolean;
9550
9550
  hasTanStackQuery: boolean;
9551
+ /**
9552
+ * The declared `valtio` version spec, or `null` when no package in the
9553
+ * analyzed project declares Valtio. `useSnapshot` has kept the same
9554
+ * render-read contract across Valtio 1 and 2, so presence alone drives the
9555
+ * `valtio` capability and its parsed major-version ladder.
9556
+ */
9557
+ valtioVersion: string | null;
9558
+ /** Parsed major from `valtioVersion`, or `null` when absent/unparseable. */
9559
+ valtioMajorVersion: number | null;
9551
9560
  /**
9552
9561
  * `true` when the project or a workspace declares a Vite-based SSR runtime
9553
9562
  * such as React Router's Node adapter, Vike, or vite-plugin-ssr.
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]="14f17993-c8fc-5c43-a518-2b2055f5d836")}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]="9a89aa42-c62d-57b9-a5d7-36051dd45bb3")}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";
@@ -34165,6 +34165,10 @@ const evaluateManifestFacts = (facts, packageJson, directory) => {
34165
34165
  const spec = getDependencySpec(packageJson, REANIMATED_DEPENDENCY_NAME);
34166
34166
  if (spec !== null) facts.reanimatedVersion = spec;
34167
34167
  }
34168
+ if (facts.valtioVersion === null) {
34169
+ const spec = getDependencySpec(packageJson, "valtio");
34170
+ if (spec !== null) facts.valtioVersion = spec;
34171
+ }
34168
34172
  facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
34169
34173
  facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
34170
34174
  facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
@@ -34187,6 +34191,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34187
34191
  version: null,
34188
34192
  sourceDirectory: null
34189
34193
  },
34194
+ valtioVersion: null,
34190
34195
  hasReactNativeAwarePackage: false,
34191
34196
  hasReanimatedAwarePackage: false,
34192
34197
  hasSsrDependency: false,
@@ -34430,6 +34435,8 @@ const discoverProjectWithoutPackageJson = (directory) => {
34430
34435
  hasReactCompiler: false,
34431
34436
  hasReactCompilerLintPlugin: false,
34432
34437
  hasTanStackQuery: false,
34438
+ valtioVersion: null,
34439
+ valtioMajorVersion: null,
34433
34440
  hasSsrDependency: false,
34434
34441
  preactVersion: null,
34435
34442
  preactMajorVersion: null,
@@ -34536,6 +34543,12 @@ const discoverProject = (directory) => {
34536
34543
  packageName: "next",
34537
34544
  version: workspaceFacts.next.version
34538
34545
  }) : null;
34546
+ const valtioVersion = resolveCatalogBackedDependencyVersion({
34547
+ rootDirectory: directory,
34548
+ rootPackageJson: packageJson,
34549
+ packageName: "valtio",
34550
+ version: workspaceFacts.valtioVersion
34551
+ });
34539
34552
  const preactVersion = getPreactVersion(packageJson);
34540
34553
  const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
34541
34554
  const projectInfo = {
@@ -34551,6 +34564,8 @@ const discoverProject = (directory) => {
34551
34564
  hasReactCompiler: detectReactCompiler(directory, packageJson),
34552
34565
  hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
34553
34566
  hasTanStackQuery: hasTanStackQuery(packageJson),
34567
+ valtioVersion,
34568
+ valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
34554
34569
  hasSsrDependency: workspaceFacts.hasSsrDependency,
34555
34570
  preactVersion,
34556
34571
  preactMajorVersion: parseReactMajor(preactVersion),
@@ -34784,7 +34799,6 @@ const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
34784
34799
  "react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
34785
34800
  "react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
34786
34801
  "react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
34787
- "react/jsx-no-target-blank": "react-doctor/jsx-no-target-blank",
34788
34802
  "react/jsx-no-undef": "react-doctor/jsx-no-undef",
34789
34803
  "react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
34790
34804
  "react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
@@ -37071,9 +37085,25 @@ const BABEL_CONFIG_FILE_NAMES = [
37071
37085
  ".babelrc.json"
37072
37086
  ];
37073
37087
  const LEGACY_PRESET_SPEC = "module:metro-react-native-babel-preset";
37088
+ const LEGACY_PRESET_PACKAGE = "metro-react-native-babel-preset";
37089
+ const REACT_NATIVE_PACKAGE = "react-native";
37090
+ const PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION = "0.73.0";
37091
+ const LEGACY_PRESET_REFERENCE = new RegExp(`['"]${LEGACY_PRESET_SPEC}['"]`);
37074
37092
  const MODERN_PRESET_REFERENCE = new RegExp(`['"]module:@react-native/babel-preset['"]`);
37075
37093
  const ENABLE_BABEL_RUNTIME_VERSION = /enableBabelRuntime["']?\s*:\s*['"]/;
37094
+ const isReactNativeVersionAtLeastPresetRename = (rootDirectory, packageJson) => {
37095
+ const installedReactNativeManifestPath = Path.join(rootDirectory, "node_modules", REACT_NATIVE_PACKAGE, "package.json");
37096
+ const reactNativeVersionSpec = (isFile(installedReactNativeManifestPath) ? readPackageJson(installedReactNativeManifestPath).version : void 0) ?? getDependencySpec(packageJson, REACT_NATIVE_PACKAGE);
37097
+ if (reactNativeVersionSpec === null || reactNativeVersionSpec === void 0) return false;
37098
+ const normalizedVersionRange = import_semver.validRange(reactNativeVersionSpec);
37099
+ if (normalizedVersionRange === null) return false;
37100
+ const minimumVersion = import_semver.minVersion(normalizedVersionRange);
37101
+ return minimumVersion !== null && import_semver.gte(minimumVersion, PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION);
37102
+ };
37103
+ const canResolveLegacyPreset = (rootDirectory, packageJson) => getDependencySpec(packageJson, LEGACY_PRESET_PACKAGE) !== null || isFile(Path.join(rootDirectory, "node_modules", LEGACY_PRESET_PACKAGE, "package.json"));
37076
37104
  const checkReactNativeMetroBabelPreset = (rootDirectory) => {
37105
+ const packageJson = readPackageJson(Path.join(rootDirectory, "package.json"));
37106
+ const shouldReportLegacyPreset = isReactNativeVersionAtLeastPresetRename(rootDirectory, packageJson) && !canResolveLegacyPreset(rootDirectory, packageJson);
37077
37107
  for (const fileName of BABEL_CONFIG_FILE_NAMES) {
37078
37108
  const filePath = Path.join(rootDirectory, fileName);
37079
37109
  if (!isFile(filePath)) continue;
@@ -37083,7 +37113,7 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
37083
37113
  } catch {
37084
37114
  continue;
37085
37115
  }
37086
- if (contents.includes(LEGACY_PRESET_SPEC)) return [buildReactNativeDiagnostic({
37116
+ if (shouldReportLegacyPreset && LEGACY_PRESET_REFERENCE.test(contents)) return [buildReactNativeDiagnostic({
37087
37117
  filePath: fileName,
37088
37118
  rule: "rn-no-metro-babel-preset",
37089
37119
  severity: "error",
@@ -37106,12 +37136,6 @@ const checkReactNativeProject = (rootDirectory, project) => {
37106
37136
  return [...checkReactNativeMetroBabelPreset(rootDirectory), ...checkReactNativeLibraryDependencies(rootDirectory)];
37107
37137
  };
37108
37138
  const RULE_KEY = "no-vulnerable-react-server-components";
37109
- const DEPENDENCY_SECTIONS = [
37110
- "dependencies",
37111
- "devDependencies",
37112
- "peerDependencies",
37113
- "optionalDependencies"
37114
- ];
37115
37139
  const REACT_RSC_ADVISORIES_BY_MINOR = {
37116
37140
  "19.0": {
37117
37141
  rceFixedVersion: "19.0.1",
@@ -37158,20 +37182,13 @@ const enumerateWorkspaceDirectories = (workspaceRoot) => {
37158
37182
  for (const pattern of patterns) for (const directory of resolveWorkspaceDirectories(workspaceRoot, pattern)) directories.add(directory);
37159
37183
  return [...directories];
37160
37184
  };
37161
- const readDeclaredSpec = (packageJson, packageName) => {
37162
- for (const section of DEPENDENCY_SECTIONS) {
37163
- const spec = packageJson[section]?.[packageName];
37164
- if (typeof spec === "string") return spec;
37165
- }
37166
- return null;
37167
- };
37168
37185
  const resolveVersionInDirectory = (directory, packageName, declaredSpecOverride) => {
37169
37186
  const manifestPath = Path.join(directory, "node_modules", packageName, "package.json");
37170
37187
  if (isFile(manifestPath)) {
37171
37188
  const installedVersion = import_semver.valid(readPackageJson(manifestPath).version ?? null);
37172
37189
  if (installedVersion !== null) return installedVersion;
37173
37190
  }
37174
- const candidateSpecs = [readDeclaredSpec(readPackageJson(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
37191
+ const candidateSpecs = [getDependencySpec(readPackageJson(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
37175
37192
  for (const spec of candidateSpecs) {
37176
37193
  const pinnedVersion = spec === null ? null : import_semver.valid(spec);
37177
37194
  if (pinnedVersion !== null) return pinnedVersion;
@@ -37854,6 +37871,8 @@ const buildCapabilities = (project) => {
37854
37871
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
37855
37872
  if (project.hasReactCompiler) capabilities.add("react-compiler");
37856
37873
  if (project.hasTanStackQuery) capabilities.add("tanstack-query");
37874
+ if (project.valtioVersion !== null) capabilities.add("valtio");
37875
+ addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
37857
37876
  if (project.hasTypeScript) capabilities.add("typescript");
37858
37877
  if (project.preactVersion !== null) capabilities.add("preact");
37859
37878
  addMajorLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
@@ -43837,4 +43856,4 @@ const toJsonReport = (result, options) => buildJsonReport({
43837
43856
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
43838
43857
 
43839
43858
  //# sourceMappingURL=index.js.map
43840
- //# debugId=14f17993-c8fc-5c43-a518-2b2055f5d836
43859
+ //# debugId=9a89aa42-c62d-57b9-a5d7-36051dd45bb3
package/dist/lsp.js CHANGED
@@ -34217,6 +34217,10 @@ const evaluateManifestFacts = (facts, packageJson, directory) => {
34217
34217
  const spec = getDependencySpec(packageJson, REANIMATED_DEPENDENCY_NAME);
34218
34218
  if (spec !== null) facts.reanimatedVersion = spec;
34219
34219
  }
34220
+ if (facts.valtioVersion === null) {
34221
+ const spec = getDependencySpec(packageJson, "valtio");
34222
+ if (spec !== null) facts.valtioVersion = spec;
34223
+ }
34220
34224
  facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
34221
34225
  facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
34222
34226
  facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
@@ -34239,6 +34243,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
34239
34243
  version: null,
34240
34244
  sourceDirectory: null
34241
34245
  },
34246
+ valtioVersion: null,
34242
34247
  hasReactNativeAwarePackage: false,
34243
34248
  hasReanimatedAwarePackage: false,
34244
34249
  hasSsrDependency: false,
@@ -34482,6 +34487,8 @@ const discoverProjectWithoutPackageJson = (directory) => {
34482
34487
  hasReactCompiler: false,
34483
34488
  hasReactCompilerLintPlugin: false,
34484
34489
  hasTanStackQuery: false,
34490
+ valtioVersion: null,
34491
+ valtioMajorVersion: null,
34485
34492
  hasSsrDependency: false,
34486
34493
  preactVersion: null,
34487
34494
  preactMajorVersion: null,
@@ -34588,6 +34595,12 @@ const discoverProject = (directory) => {
34588
34595
  packageName: "next",
34589
34596
  version: workspaceFacts.next.version
34590
34597
  }) : null;
34598
+ const valtioVersion = resolveCatalogBackedDependencyVersion({
34599
+ rootDirectory: directory,
34600
+ rootPackageJson: packageJson,
34601
+ packageName: "valtio",
34602
+ version: workspaceFacts.valtioVersion
34603
+ });
34591
34604
  const preactVersion = getPreactVersion(packageJson);
34592
34605
  const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
34593
34606
  const projectInfo = {
@@ -34603,6 +34616,8 @@ const discoverProject = (directory) => {
34603
34616
  hasReactCompiler: detectReactCompiler(directory, packageJson),
34604
34617
  hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
34605
34618
  hasTanStackQuery: hasTanStackQuery(packageJson),
34619
+ valtioVersion,
34620
+ valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
34606
34621
  hasSsrDependency: workspaceFacts.hasSsrDependency,
34607
34622
  preactVersion,
34608
34623
  preactMajorVersion: parseReactMajor(preactVersion),
@@ -34836,7 +34851,6 @@ const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
34836
34851
  "react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
34837
34852
  "react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
34838
34853
  "react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
34839
- "react/jsx-no-target-blank": "react-doctor/jsx-no-target-blank",
34840
34854
  "react/jsx-no-undef": "react-doctor/jsx-no-undef",
34841
34855
  "react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
34842
34856
  "react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
@@ -37049,9 +37063,25 @@ const BABEL_CONFIG_FILE_NAMES = [
37049
37063
  ".babelrc.json"
37050
37064
  ];
37051
37065
  const LEGACY_PRESET_SPEC = "module:metro-react-native-babel-preset";
37066
+ const LEGACY_PRESET_PACKAGE = "metro-react-native-babel-preset";
37067
+ const REACT_NATIVE_PACKAGE = "react-native";
37068
+ const PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION = "0.73.0";
37069
+ const LEGACY_PRESET_REFERENCE = new RegExp(`['"]${LEGACY_PRESET_SPEC}['"]`);
37052
37070
  const MODERN_PRESET_REFERENCE = new RegExp(`['"]module:@react-native/babel-preset['"]`);
37053
37071
  const ENABLE_BABEL_RUNTIME_VERSION = /enableBabelRuntime["']?\s*:\s*['"]/;
37072
+ const isReactNativeVersionAtLeastPresetRename = (rootDirectory, packageJson) => {
37073
+ const installedReactNativeManifestPath = Path.join(rootDirectory, "node_modules", REACT_NATIVE_PACKAGE, "package.json");
37074
+ const reactNativeVersionSpec = (isFile(installedReactNativeManifestPath) ? readPackageJson(installedReactNativeManifestPath).version : void 0) ?? getDependencySpec(packageJson, REACT_NATIVE_PACKAGE);
37075
+ if (reactNativeVersionSpec === null || reactNativeVersionSpec === void 0) return false;
37076
+ const normalizedVersionRange = import_semver.validRange(reactNativeVersionSpec);
37077
+ if (normalizedVersionRange === null) return false;
37078
+ const minimumVersion = import_semver.minVersion(normalizedVersionRange);
37079
+ return minimumVersion !== null && import_semver.gte(minimumVersion, PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION);
37080
+ };
37081
+ const canResolveLegacyPreset = (rootDirectory, packageJson) => getDependencySpec(packageJson, LEGACY_PRESET_PACKAGE) !== null || isFile(Path.join(rootDirectory, "node_modules", LEGACY_PRESET_PACKAGE, "package.json"));
37054
37082
  const checkReactNativeMetroBabelPreset = (rootDirectory) => {
37083
+ const packageJson = readPackageJson(Path.join(rootDirectory, "package.json"));
37084
+ const shouldReportLegacyPreset = isReactNativeVersionAtLeastPresetRename(rootDirectory, packageJson) && !canResolveLegacyPreset(rootDirectory, packageJson);
37055
37085
  for (const fileName of BABEL_CONFIG_FILE_NAMES) {
37056
37086
  const filePath = Path.join(rootDirectory, fileName);
37057
37087
  if (!isFile(filePath)) continue;
@@ -37061,7 +37091,7 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
37061
37091
  } catch {
37062
37092
  continue;
37063
37093
  }
37064
- if (contents.includes(LEGACY_PRESET_SPEC)) return [buildReactNativeDiagnostic({
37094
+ if (shouldReportLegacyPreset && LEGACY_PRESET_REFERENCE.test(contents)) return [buildReactNativeDiagnostic({
37065
37095
  filePath: fileName,
37066
37096
  rule: "rn-no-metro-babel-preset",
37067
37097
  severity: "error",
@@ -37084,12 +37114,6 @@ const checkReactNativeProject = (rootDirectory, project) => {
37084
37114
  return [...checkReactNativeMetroBabelPreset(rootDirectory), ...checkReactNativeLibraryDependencies(rootDirectory)];
37085
37115
  };
37086
37116
  const RULE_KEY = "no-vulnerable-react-server-components";
37087
- const DEPENDENCY_SECTIONS = [
37088
- "dependencies",
37089
- "devDependencies",
37090
- "peerDependencies",
37091
- "optionalDependencies"
37092
- ];
37093
37117
  const REACT_RSC_ADVISORIES_BY_MINOR = {
37094
37118
  "19.0": {
37095
37119
  rceFixedVersion: "19.0.1",
@@ -37136,20 +37160,13 @@ const enumerateWorkspaceDirectories = (workspaceRoot) => {
37136
37160
  for (const pattern of patterns) for (const directory of resolveWorkspaceDirectories(workspaceRoot, pattern)) directories.add(directory);
37137
37161
  return [...directories];
37138
37162
  };
37139
- const readDeclaredSpec = (packageJson, packageName) => {
37140
- for (const section of DEPENDENCY_SECTIONS) {
37141
- const spec = packageJson[section]?.[packageName];
37142
- if (typeof spec === "string") return spec;
37143
- }
37144
- return null;
37145
- };
37146
37163
  const resolveVersionInDirectory = (directory, packageName, declaredSpecOverride) => {
37147
37164
  const manifestPath = Path.join(directory, "node_modules", packageName, "package.json");
37148
37165
  if (isFile(manifestPath)) {
37149
37166
  const installedVersion = import_semver.valid(readPackageJson(manifestPath).version ?? null);
37150
37167
  if (installedVersion !== null) return installedVersion;
37151
37168
  }
37152
- const candidateSpecs = [readDeclaredSpec(readPackageJson(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
37169
+ const candidateSpecs = [getDependencySpec(readPackageJson(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
37153
37170
  for (const spec of candidateSpecs) {
37154
37171
  const pinnedVersion = spec === null ? null : import_semver.valid(spec);
37155
37172
  if (pinnedVersion !== null) return pinnedVersion;
@@ -37832,6 +37849,8 @@ const buildCapabilities = (project) => {
37832
37849
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
37833
37850
  if (project.hasReactCompiler) capabilities.add("react-compiler");
37834
37851
  if (project.hasTanStackQuery) capabilities.add("tanstack-query");
37852
+ if (project.valtioVersion !== null) capabilities.add("valtio");
37853
+ addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
37835
37854
  if (project.hasTypeScript) capabilities.add("typescript");
37836
37855
  if (project.preactVersion !== null) capabilities.add("preact");
37837
37856
  addMajorLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
@@ -45457,5 +45476,5 @@ const startLanguageServer = () => {
45457
45476
  };
45458
45477
  //#endregion
45459
45478
  export { startLanguageServer };
45460
- !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]="ecc1704a-4f8c-583e-93b2-78c6feb9cfd6")}catch(e){}}();
45461
- //# debugId=ecc1704a-4f8c-583e-93b2-78c6feb9cfd6
45479
+ !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]="a257778d-cb0a-54d7-909d-889a64e8698c")}catch(e){}}();
45480
+ //# debugId=a257778d-cb0a-54d7-909d-889a64e8698c
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.8.1-dev.5332cb6",
3
+ "version": "0.8.1-dev.5774353",
4
4
  "description": "Your agent writes bad React. This catches it",
5
5
  "keywords": [
6
6
  "accessibility",
@@ -66,7 +66,7 @@
66
66
  "vscode-uri": "^3.1.0",
67
67
  "yaml": "^2.9.0",
68
68
  "deslop-js": "0.8.1",
69
- "oxlint-plugin-react-doctor": "0.8.1-dev.5332cb6"
69
+ "oxlint-plugin-react-doctor": "0.8.1-dev.5774353"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/babel__code-frame": "^7.27.0",
@@ -74,8 +74,8 @@
74
74
  "@xterm/headless": "^6.0.0",
75
75
  "commander": "^14.0.3",
76
76
  "ora": "^9.4.0",
77
- "@react-doctor/core": "0.8.1",
78
77
  "@react-doctor/api": "0.8.1",
78
+ "@react-doctor/core": "0.8.1",
79
79
  "@react-doctor/language-server": "0.8.1"
80
80
  },
81
81
  "engines": {