react-doctor 0.2.11-dev.b2934f9 → 0.2.11-dev.b5cf767

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.
@@ -2281,91 +2281,15 @@ const detectFramework = (dependencies) => {
2281
2281
  if (dependencies.preact && !dependencies.react) return "preact";
2282
2282
  return "unknown";
2283
2283
  };
2284
+ const UPPER_BOUND_COMPARATOR = /<\s*=?\s*\d+(?:\.\d+){0,2}(?:-[^\s,|]+)?/g;
2285
+ const HAS_UPPER_BOUND_COMPARATOR = /<\s*=?\s*\d+(?:\.\d+){0,2}(?:-[^\s,|]+)?/;
2286
+ const OR_SEPARATOR = /\s*\|\|\s*/;
2284
2287
  const UNRESOLVABLE_PROTOCOL_VERSION = /^(?:file|git|github|https?|link|patch|portal|workspace|npm):/i;
2285
2288
  const DIST_TAG_VERSION = /^[a-z][a-z0-9._-]*$/i;
2286
2289
  const WILDCARD_VERSION = /^[*xX](?:\.[*xX])*$/;
2290
+ const NON_LOWER_BOUND_COMPARATOR = /(?:^|[\s,|])(?:>(?!=)|!={0,2})\s*\d/;
2291
+ const LOWER_BOUND_MAJOR = /(?:^|[\s,|])(?:>=\s*|[~^=v]\s*)?(\d+)(?=$|[\s,|.*xX-])/g;
2287
2292
  const NPM_ALIAS_VERSION = /^npm:(?:@[^/]+\/[^@]+|[^@]+)@(.+)$/i;
2288
- const isDigit = (value) => value !== void 0 && value >= "0" && value <= "9";
2289
- const isWhitespace = (value) => value === " " || value === " " || value === "\n" || value === "\r" || value === "\f" || value === "\v";
2290
- const isSeparator = (value) => isWhitespace(value) || value === "," || value === "|";
2291
- const skipWhitespace = (value, start) => {
2292
- let index = start;
2293
- while (isWhitespace(value[index])) index += 1;
2294
- return index;
2295
- };
2296
- const skipSeparators = (value, start) => {
2297
- let index = start;
2298
- while (isSeparator(value[index])) index += 1;
2299
- return index;
2300
- };
2301
- const readDigits = (value, start) => {
2302
- let index = start;
2303
- while (isDigit(value[index])) index += 1;
2304
- return index;
2305
- };
2306
- const getUpperBoundComparatorEnd = (version, start) => {
2307
- if (version[start] !== "<") return null;
2308
- let index = skipWhitespace(version, start + 1);
2309
- if (version[index] === "=") index = skipWhitespace(version, index + 1);
2310
- const majorStart = index;
2311
- index = readDigits(version, index);
2312
- if (index === majorStart) return null;
2313
- for (let segments = 0; segments < 2 && version[index] === "."; segments += 1) {
2314
- const segmentStart = index + 1;
2315
- const segmentEnd = readDigits(version, segmentStart);
2316
- if (segmentEnd === segmentStart) break;
2317
- index = segmentEnd;
2318
- }
2319
- if (version[index] === "-") {
2320
- index += 1;
2321
- while (index < version.length && !isSeparator(version[index])) index += 1;
2322
- }
2323
- return index;
2324
- };
2325
- const stripUpperBoundComparators = (version) => {
2326
- let stripped = "";
2327
- let index = 0;
2328
- while (index < version.length) {
2329
- const comparatorEnd = getUpperBoundComparatorEnd(version, index);
2330
- if (comparatorEnd === null) {
2331
- stripped += version[index];
2332
- index += 1;
2333
- continue;
2334
- }
2335
- stripped += " ";
2336
- index = comparatorEnd;
2337
- }
2338
- return stripped;
2339
- };
2340
- const hasNonLowerBoundComparator = (branch) => {
2341
- for (let index = 0; index < branch.length; index += 1) {
2342
- if (index > 0 && !isSeparator(branch[index - 1])) continue;
2343
- if (branch[index] === ">" && branch[index + 1] !== "=") {
2344
- if (isDigit(branch[skipWhitespace(branch, index + 1)])) return true;
2345
- continue;
2346
- }
2347
- if (branch[index] !== "!") continue;
2348
- let valueIndex = index + 1;
2349
- if (branch[valueIndex] === "=") valueIndex += 1;
2350
- if (branch[valueIndex] === "=") valueIndex += 1;
2351
- valueIndex = skipWhitespace(branch, valueIndex);
2352
- if (isDigit(branch[valueIndex])) return true;
2353
- }
2354
- return false;
2355
- };
2356
- const isMajorTerminator = (value) => value === void 0 || isSeparator(value) || value === "." || value === "*" || value === "x" || value === "X" || value === "-";
2357
- const getLowerBoundMajorAt = (branch, start) => {
2358
- let index = start;
2359
- if (branch[index] === ">" && branch[index + 1] === "=") index = skipWhitespace(branch, index + 2);
2360
- else if (branch[index] === "~" || branch[index] === "^" || branch[index] === "=" || branch[index] === "v") index = skipWhitespace(branch, index + 1);
2361
- const majorStart = index;
2362
- const majorEnd = readDigits(branch, majorStart);
2363
- if (majorEnd === majorStart || !isMajorTerminator(branch[majorEnd])) return null;
2364
- return {
2365
- end: majorEnd,
2366
- major: Number.parseInt(branch.slice(majorStart, majorEnd), 10)
2367
- };
2368
- };
2369
2293
  const normalizeDependencyVersion = (version) => {
2370
2294
  const trimmed = version.trim();
2371
2295
  if (trimmed.length === 0) return null;
@@ -2375,29 +2299,17 @@ const normalizeDependencyVersion = (version) => {
2375
2299
  if (WILDCARD_VERSION.test(normalizedVersion)) return null;
2376
2300
  return normalizedVersion;
2377
2301
  };
2378
- const splitDependencyVersionBranches = (version) => version.split("||").map((branch) => branch.trim()).filter(Boolean);
2379
- const hasUpperBoundComparator = (version) => {
2380
- for (let index = 0; index < version.length; index += 1) if (getUpperBoundComparatorEnd(version, index) !== null) return true;
2381
- return false;
2382
- };
2302
+ const splitDependencyVersionBranches = (version) => version.split(OR_SEPARATOR).filter(Boolean);
2303
+ const hasUpperBoundComparator = (version) => HAS_UPPER_BOUND_COMPARATOR.test(version);
2383
2304
  const getBranchLowestMajor = (branch) => {
2384
- if (hasNonLowerBoundComparator(branch)) return null;
2385
- const lowerBoundComparators = stripUpperBoundComparators(branch).trim();
2305
+ if (NON_LOWER_BOUND_COMPARATOR.test(branch)) return null;
2306
+ const lowerBoundComparators = branch.replace(UPPER_BOUND_COMPARATOR, " ").trim();
2386
2307
  if (lowerBoundComparators.length === 0) return null;
2387
2308
  let branchLowestMajor = null;
2388
- let index = 0;
2389
- while (index < lowerBoundComparators.length) {
2390
- const lowerBoundStart = skipSeparators(lowerBoundComparators, index);
2391
- if (lowerBoundStart > 0 && !isSeparator(lowerBoundComparators[lowerBoundStart - 1])) {
2392
- index = lowerBoundStart + 1;
2393
- continue;
2394
- }
2395
- const lowerBoundMajor = getLowerBoundMajorAt(lowerBoundComparators, lowerBoundStart);
2396
- if (lowerBoundMajor !== null && Number.isFinite(lowerBoundMajor.major) && lowerBoundMajor.major > 0) {
2397
- const major = lowerBoundMajor.major;
2398
- if (branchLowestMajor === null || major < branchLowestMajor) branchLowestMajor = major;
2399
- }
2400
- index = lowerBoundMajor?.end ?? lowerBoundStart + 1;
2309
+ for (const match of lowerBoundComparators.matchAll(LOWER_BOUND_MAJOR)) {
2310
+ const major = Number.parseInt(match[1], 10);
2311
+ if (!Number.isFinite(major) || major <= 0) continue;
2312
+ if (branchLowestMajor === null || major < branchLowestMajor) branchLowestMajor = major;
2401
2313
  }
2402
2314
  return branchLowestMajor;
2403
2315
  };
@@ -2566,7 +2478,6 @@ const resolveCatalogVersion = (packageJson, packageName, rootDirectory, explicit
2566
2478
  const EMPTY_DEPENDENCY_INFO = {
2567
2479
  reactVersion: null,
2568
2480
  tailwindVersion: null,
2569
- zodVersion: null,
2570
2481
  framework: "unknown"
2571
2482
  };
2572
2483
  const pickConcreteVersion = (packageJson, packageName, sections) => {
@@ -2595,11 +2506,6 @@ const extractDependencyInfo = (packageJson) => {
2595
2506
  "devDependencies",
2596
2507
  "peerDependencies"
2597
2508
  ]),
2598
- zodVersion: pickConcreteVersion(packageJson, "zod", [
2599
- "dependencies",
2600
- "devDependencies",
2601
- "peerDependencies"
2602
- ]),
2603
2509
  framework: detectFramework(allDependencies)
2604
2510
  };
2605
2511
  };
@@ -2744,22 +2650,8 @@ const findReactInWorkspaces = (rootDirectory, packageJson) => {
2744
2650
  workspaceDirectory,
2745
2651
  workspacePackageJson
2746
2652
  });
2747
- const zodVersion = resolveWorkspaceDependencyVersion({
2748
- concreteVersion: info.zodVersion,
2749
- packageName: "zod",
2750
- rootDirectory,
2751
- rootPackageJson: packageJson,
2752
- sections: [
2753
- "dependencies",
2754
- "devDependencies",
2755
- "peerDependencies"
2756
- ],
2757
- workspaceDirectory,
2758
- workspacePackageJson
2759
- });
2760
2653
  if (reactVersion && shouldReplaceReactVersion(result.reactVersion, reactVersion)) result.reactVersion = reactVersion;
2761
2654
  if (tailwindVersion && !result.tailwindVersion) result.tailwindVersion = tailwindVersion;
2762
- if (zodVersion && !result.zodVersion) result.zodVersion = zodVersion;
2763
2655
  if (info.framework !== "unknown" && result.framework === "unknown") result.framework = info.framework;
2764
2656
  const resultReactMajor = parseReactMajor(result.reactVersion);
2765
2657
  if (result.reactVersion && result.tailwindVersion && result.framework !== "unknown" && resultReactMajor !== null && resultReactMajor <= 17) return result;
@@ -2794,26 +2686,14 @@ const findDependencyInfoFromMonorepoRoot = (directory) => {
2794
2686
  "peerDependencies"
2795
2687
  ]
2796
2688
  }) : null;
2797
- const leafZodDeclaration = leafPackageJson ? getDependencyDeclaration({
2798
- packageJson: leafPackageJson,
2799
- packageName: "zod",
2800
- sections: [
2801
- "dependencies",
2802
- "devDependencies",
2803
- "peerDependencies"
2804
- ]
2805
- }) : null;
2806
2689
  const shouldUseReactFallback = !leafReactDeclaration?.hasDeclaration;
2807
2690
  const shouldUseTailwindFallback = leafTailwindDeclaration?.hasDeclaration ?? true;
2808
- const shouldUseZodFallback = leafZodDeclaration?.hasDeclaration ?? true;
2809
2691
  const reactCatalogVersion = shouldUseReactFallback ? resolveCatalogVersion(rootPackageJson, "react", monorepoRoot, leafReactDeclaration?.catalogReference) : null;
2810
2692
  const tailwindCatalogVersion = shouldUseTailwindFallback ? resolveCatalogVersion(rootPackageJson, "tailwindcss", monorepoRoot, leafTailwindDeclaration?.catalogReference) : null;
2811
- const zodCatalogVersion = shouldUseZodFallback ? resolveCatalogVersion(rootPackageJson, "zod", monorepoRoot, leafZodDeclaration?.catalogReference) : null;
2812
2693
  const workspaceInfo = findReactInWorkspaces(monorepoRoot, rootPackageJson);
2813
2694
  return {
2814
2695
  reactVersion: shouldUseReactFallback ? reactCatalogVersion ?? rootInfo.reactVersion ?? workspaceInfo.reactVersion : rootInfo.reactVersion ?? workspaceInfo.reactVersion,
2815
2696
  tailwindVersion: shouldUseTailwindFallback ? tailwindCatalogVersion ?? rootInfo.tailwindVersion ?? workspaceInfo.tailwindVersion : null,
2816
- zodVersion: shouldUseZodFallback ? zodCatalogVersion ?? rootInfo.zodVersion ?? workspaceInfo.zodVersion : null,
2817
2697
  framework: rootInfo.framework !== "unknown" ? rootInfo.framework : workspaceInfo.framework
2818
2698
  };
2819
2699
  };
@@ -2893,10 +2773,6 @@ const isPackageJsonReanimatedAware = (packageJson) => {
2893
2773
  };
2894
2774
  return Object.hasOwn(allDependencies, REANIMATED_DEPENDENCY_NAME);
2895
2775
  };
2896
- const parseZodMajor = (zodVersion) => {
2897
- if (typeof zodVersion !== "string") return null;
2898
- return getLowestDependencyMajor(zodVersion);
2899
- };
2900
2776
  const hasUpperBoundOnlyPeerRange = (range) => {
2901
2777
  if (typeof range !== "string") return false;
2902
2778
  const normalizedRange = normalizeDependencyVersion(range);
@@ -3035,7 +2911,7 @@ const discoverProject = (directory) => {
3035
2911
  const packageJsonPath = path.join(directory, "package.json");
3036
2912
  if (!isFile(packageJsonPath)) throw new PackageJsonNotFoundError(directory);
3037
2913
  const packageJson = readPackageJson(packageJsonPath);
3038
- let { reactVersion, tailwindVersion, zodVersion, framework } = extractDependencyInfo(packageJson);
2914
+ let { reactVersion, tailwindVersion, framework } = extractDependencyInfo(packageJson);
3039
2915
  const reactDeclaration = getDependencyDeclaration({
3040
2916
  packageJson,
3041
2917
  packageName: "react",
@@ -3054,19 +2930,9 @@ const discoverProject = (directory) => {
3054
2930
  "peerDependencies"
3055
2931
  ]
3056
2932
  });
3057
- const zodDeclaration = getDependencyDeclaration({
3058
- packageJson,
3059
- packageName: "zod",
3060
- sections: [
3061
- "dependencies",
3062
- "devDependencies",
3063
- "peerDependencies"
3064
- ]
3065
- });
3066
2933
  if (!reactVersion && reactDeclaration.hasDeclaration) reactVersion = resolveCatalogVersion(packageJson, "react", directory, reactDeclaration.catalogReference);
3067
2934
  if (!tailwindVersion && tailwindDeclaration.hasDeclaration) tailwindVersion = resolveCatalogVersion(packageJson, "tailwindcss", directory, tailwindDeclaration.catalogReference);
3068
- if (!zodVersion && zodDeclaration.hasDeclaration) zodVersion = resolveCatalogVersion(packageJson, "zod", directory, zodDeclaration.catalogReference);
3069
- if (!reactVersion || !tailwindVersion || !zodVersion) {
2935
+ if (!reactVersion || !tailwindVersion) {
3070
2936
  const monorepoRoot = findMonorepoRoot(directory);
3071
2937
  if (monorepoRoot) {
3072
2938
  const monorepoPackageJsonPath = path.join(monorepoRoot, "package.json");
@@ -3074,7 +2940,6 @@ const discoverProject = (directory) => {
3074
2940
  const rootPackageJson = readPackageJson(monorepoPackageJsonPath);
3075
2941
  if (!reactVersion && reactDeclaration.hasDeclaration) reactVersion = resolveCatalogVersion(rootPackageJson, "react", monorepoRoot, reactDeclaration.catalogReference);
3076
2942
  if (!tailwindVersion && tailwindDeclaration.hasDeclaration) tailwindVersion = resolveCatalogVersion(rootPackageJson, "tailwindcss", monorepoRoot, tailwindDeclaration.catalogReference);
3077
- if (!zodVersion && zodDeclaration.hasDeclaration) zodVersion = resolveCatalogVersion(rootPackageJson, "zod", monorepoRoot, zodDeclaration.catalogReference);
3078
2943
  }
3079
2944
  }
3080
2945
  }
@@ -3082,19 +2947,16 @@ const discoverProject = (directory) => {
3082
2947
  const workspaceInfo = findReactInWorkspaces(directory, packageJson);
3083
2948
  if (!reactVersion && workspaceInfo.reactVersion) reactVersion = workspaceInfo.reactVersion;
3084
2949
  if (!tailwindVersion && workspaceInfo.tailwindVersion) tailwindVersion = workspaceInfo.tailwindVersion;
3085
- if (!zodVersion && workspaceInfo.zodVersion) zodVersion = workspaceInfo.zodVersion;
3086
2950
  if (framework === "unknown" && workspaceInfo.framework !== "unknown") framework = workspaceInfo.framework;
3087
2951
  }
3088
2952
  if ((!reactVersion || framework === "unknown") && !isMonorepoRoot(directory)) {
3089
2953
  const monorepoInfo = findDependencyInfoFromMonorepoRoot(directory);
3090
2954
  if (!reactVersion) reactVersion = monorepoInfo.reactVersion;
3091
2955
  if (!tailwindVersion) tailwindVersion = monorepoInfo.tailwindVersion;
3092
- if (!zodVersion) zodVersion = monorepoInfo.zodVersion;
3093
2956
  if (framework === "unknown") framework = monorepoInfo.framework;
3094
2957
  }
3095
2958
  if (!reactVersion && reactDeclaration.version && !isCatalogReference(reactDeclaration.version)) reactVersion = reactDeclaration.version;
3096
2959
  if (!tailwindVersion && tailwindDeclaration.version && !isCatalogReference(tailwindDeclaration.version)) tailwindVersion = tailwindDeclaration.version;
3097
- if (!zodVersion && zodDeclaration.version && !isCatalogReference(zodDeclaration.version)) zodVersion = zodDeclaration.version;
3098
2960
  const projectName = packageJson.name ?? path.basename(directory);
3099
2961
  const hasTypeScript = fs.existsSync(path.join(directory, "tsconfig.json"));
3100
2962
  const sourceFileCount = countSourceFiles(directory);
@@ -3107,8 +2969,6 @@ const discoverProject = (directory) => {
3107
2969
  reactVersion,
3108
2970
  reactMajorVersion: resolveEffectiveReactMajor(reactVersion, packageJson),
3109
2971
  tailwindVersion,
3110
- zodVersion,
3111
- zodMajorVersion: parseZodMajor(zodVersion),
3112
2972
  framework,
3113
2973
  hasTypeScript,
3114
2974
  hasReactCompiler: detectReactCompiler(directory, packageJson),
@@ -5632,10 +5492,6 @@ const buildCapabilities = (project) => {
5632
5492
  minor: 4
5633
5493
  })) capabilities.add("tailwind:3.4");
5634
5494
  }
5635
- if (project.zodVersion !== null) {
5636
- capabilities.add("zod");
5637
- if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
5638
- }
5639
5495
  if (project.hasReactCompiler) capabilities.add("react-compiler");
5640
5496
  if (project.hasTanStackQuery) capabilities.add("tanstack-query");
5641
5497
  if (project.hasTypeScript) capabilities.add("typescript");
@@ -7561,4 +7417,4 @@ const cliLogger = {
7561
7417
  //#endregion
7562
7418
  export { isMonorepoRoot as A, filterDiagnosticsForSurface as C, getDiffInfo as D, formatReactDoctorError as E, restoreLegacyThrow as F, runInspect as I, toRelativePath as L, layerOtlp as M, listWorkspacePackages as N, groupBy as O, resolveScanTarget as P, discoverReactSubprojects as S, formatErrorChain as T, Score as _, DeadCode as a, buildJsonReportError as b, LintPartialFailures as c, OXLINT_NODE_REQUIREMENT as d, Progress as f, SKILL_NAME as g, SHARE_BASE_URL as h, Config as i, isReactDoctorError as j, highlighter as k, Linter as l, Reporter as m, cli_logger_exports as n, Files as o, Project as p, CANONICAL_GITHUB_URL as r, Git as s, cliLogger as t, NodeResolver as u, StagedFiles as v, filterSourceFiles as w, buildRulePromptUrl as x, buildJsonReport as y };
7563
7419
 
7564
- //# sourceMappingURL=cli-logger-CSZagq1E.js.map
7420
+ //# sourceMappingURL=cli-logger-CmMJBgYF.js.map
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { i as __toESM, n as __exportAll, r as __require, t as __commonJSMin } from "./rolldown-runtime-uZX_iqCz.js";
2
- import { A as isMonorepoRoot, C as filterDiagnosticsForSurface, D as getDiffInfo, E as formatReactDoctorError, F as restoreLegacyThrow, I as runInspect, L as toRelativePath, M as layerOtlp, N as listWorkspacePackages, O as groupBy, P as resolveScanTarget, S as discoverReactSubprojects, T as formatErrorChain, _ as Score, a as DeadCode, b as buildJsonReportError, c as LintPartialFailures, d as OXLINT_NODE_REQUIREMENT, f as Progress, g as SKILL_NAME, h as SHARE_BASE_URL, i as Config, j as isReactDoctorError, k as highlighter, l as Linter, m as Reporter, o as Files, p as Project, r as CANONICAL_GITHUB_URL, s as Git, t as cliLogger, u as NodeResolver, v as StagedFiles, w as filterSourceFiles, x as buildRulePromptUrl, y as buildJsonReport } from "./cli-logger-CSZagq1E.js";
2
+ import { A as isMonorepoRoot, C as filterDiagnosticsForSurface, D as getDiffInfo, E as formatReactDoctorError, F as restoreLegacyThrow, I as runInspect, L as toRelativePath, M as layerOtlp, N as listWorkspacePackages, O as groupBy, P as resolveScanTarget, S as discoverReactSubprojects, T as formatErrorChain, _ as Score, a as DeadCode, b as buildJsonReportError, c as LintPartialFailures, d as OXLINT_NODE_REQUIREMENT, f as Progress, g as SKILL_NAME, h as SHARE_BASE_URL, i as Config, j as isReactDoctorError, k as highlighter, l as Linter, m as Reporter, o as Files, p as Project, r as CANONICAL_GITHUB_URL, s as Git, t as cliLogger, u as NodeResolver, v as StagedFiles, w as filterSourceFiles, x as buildRulePromptUrl, y as buildJsonReport } from "./cli-logger-CmMJBgYF.js";
3
3
  import { createRequire } from "node:module";
4
4
  import { execFileSync, execSync } from "node:child_process";
5
5
  import path, { join } from "node:path";
@@ -6674,7 +6674,7 @@ const resolveOxlintNodeEffect = (isLintEnabled, isQuiet) => Effect.gen(function*
6674
6674
  const resolveOxlintNode = (isLintEnabled, isQuiet) => Effect.runPromise(resolveOxlintNodeEffect(isLintEnabled, isQuiet).pipe(Effect.provide(NodeResolver.layerNode)));
6675
6675
  //#endregion
6676
6676
  //#region src/cli/utils/version.ts
6677
- const VERSION = "0.2.11-dev.b2934f9";
6677
+ const VERSION = "0.2.11-dev.b5cf767";
6678
6678
  //#endregion
6679
6679
  //#region src/inspect.ts
6680
6680
  const silentConsole = makeNoopConsole();
@@ -7495,7 +7495,7 @@ const warnSetupPromptFailure = async (options, error) => {
7495
7495
  return;
7496
7496
  }
7497
7497
  try {
7498
- const { cliLogger } = await import("./cli-logger-CSZagq1E.js").then((n) => n.n);
7498
+ const { cliLogger } = await import("./cli-logger-CmMJBgYF.js").then((n) => n.n);
7499
7499
  cliLogger.warn(message);
7500
7500
  } catch {}
7501
7501
  };
package/dist/index.d.ts CHANGED
@@ -305,9 +305,6 @@ interface ProjectInfo {
305
305
  reactVersion: string | null;
306
306
  reactMajorVersion: number | null;
307
307
  tailwindVersion: string | null;
308
- zodVersion: string | null;
309
- /** Parsed major from `zodVersion`, or `null` when absent/unparseable. Mirrors `reactMajorVersion`. */
310
- zodMajorVersion: number | null;
311
308
  framework: Framework;
312
309
  hasTypeScript: boolean;
313
310
  hasReactCompiler: boolean;
package/dist/index.js CHANGED
@@ -2307,91 +2307,15 @@ const detectFramework = (dependencies) => {
2307
2307
  if (dependencies.preact && !dependencies.react) return "preact";
2308
2308
  return "unknown";
2309
2309
  };
2310
+ const UPPER_BOUND_COMPARATOR = /<\s*=?\s*\d+(?:\.\d+){0,2}(?:-[^\s,|]+)?/g;
2311
+ const HAS_UPPER_BOUND_COMPARATOR = /<\s*=?\s*\d+(?:\.\d+){0,2}(?:-[^\s,|]+)?/;
2312
+ const OR_SEPARATOR = /\s*\|\|\s*/;
2310
2313
  const UNRESOLVABLE_PROTOCOL_VERSION = /^(?:file|git|github|https?|link|patch|portal|workspace|npm):/i;
2311
2314
  const DIST_TAG_VERSION = /^[a-z][a-z0-9._-]*$/i;
2312
2315
  const WILDCARD_VERSION = /^[*xX](?:\.[*xX])*$/;
2316
+ const NON_LOWER_BOUND_COMPARATOR = /(?:^|[\s,|])(?:>(?!=)|!={0,2})\s*\d/;
2317
+ const LOWER_BOUND_MAJOR = /(?:^|[\s,|])(?:>=\s*|[~^=v]\s*)?(\d+)(?=$|[\s,|.*xX-])/g;
2313
2318
  const NPM_ALIAS_VERSION = /^npm:(?:@[^/]+\/[^@]+|[^@]+)@(.+)$/i;
2314
- const isDigit = (value) => value !== void 0 && value >= "0" && value <= "9";
2315
- const isWhitespace = (value) => value === " " || value === " " || value === "\n" || value === "\r" || value === "\f" || value === "\v";
2316
- const isSeparator = (value) => isWhitespace(value) || value === "," || value === "|";
2317
- const skipWhitespace = (value, start) => {
2318
- let index = start;
2319
- while (isWhitespace(value[index])) index += 1;
2320
- return index;
2321
- };
2322
- const skipSeparators = (value, start) => {
2323
- let index = start;
2324
- while (isSeparator(value[index])) index += 1;
2325
- return index;
2326
- };
2327
- const readDigits = (value, start) => {
2328
- let index = start;
2329
- while (isDigit(value[index])) index += 1;
2330
- return index;
2331
- };
2332
- const getUpperBoundComparatorEnd = (version, start) => {
2333
- if (version[start] !== "<") return null;
2334
- let index = skipWhitespace(version, start + 1);
2335
- if (version[index] === "=") index = skipWhitespace(version, index + 1);
2336
- const majorStart = index;
2337
- index = readDigits(version, index);
2338
- if (index === majorStart) return null;
2339
- for (let segments = 0; segments < 2 && version[index] === "."; segments += 1) {
2340
- const segmentStart = index + 1;
2341
- const segmentEnd = readDigits(version, segmentStart);
2342
- if (segmentEnd === segmentStart) break;
2343
- index = segmentEnd;
2344
- }
2345
- if (version[index] === "-") {
2346
- index += 1;
2347
- while (index < version.length && !isSeparator(version[index])) index += 1;
2348
- }
2349
- return index;
2350
- };
2351
- const stripUpperBoundComparators = (version) => {
2352
- let stripped = "";
2353
- let index = 0;
2354
- while (index < version.length) {
2355
- const comparatorEnd = getUpperBoundComparatorEnd(version, index);
2356
- if (comparatorEnd === null) {
2357
- stripped += version[index];
2358
- index += 1;
2359
- continue;
2360
- }
2361
- stripped += " ";
2362
- index = comparatorEnd;
2363
- }
2364
- return stripped;
2365
- };
2366
- const hasNonLowerBoundComparator = (branch) => {
2367
- for (let index = 0; index < branch.length; index += 1) {
2368
- if (index > 0 && !isSeparator(branch[index - 1])) continue;
2369
- if (branch[index] === ">" && branch[index + 1] !== "=") {
2370
- if (isDigit(branch[skipWhitespace(branch, index + 1)])) return true;
2371
- continue;
2372
- }
2373
- if (branch[index] !== "!") continue;
2374
- let valueIndex = index + 1;
2375
- if (branch[valueIndex] === "=") valueIndex += 1;
2376
- if (branch[valueIndex] === "=") valueIndex += 1;
2377
- valueIndex = skipWhitespace(branch, valueIndex);
2378
- if (isDigit(branch[valueIndex])) return true;
2379
- }
2380
- return false;
2381
- };
2382
- const isMajorTerminator = (value) => value === void 0 || isSeparator(value) || value === "." || value === "*" || value === "x" || value === "X" || value === "-";
2383
- const getLowerBoundMajorAt = (branch, start) => {
2384
- let index = start;
2385
- if (branch[index] === ">" && branch[index + 1] === "=") index = skipWhitespace(branch, index + 2);
2386
- else if (branch[index] === "~" || branch[index] === "^" || branch[index] === "=" || branch[index] === "v") index = skipWhitespace(branch, index + 1);
2387
- const majorStart = index;
2388
- const majorEnd = readDigits(branch, majorStart);
2389
- if (majorEnd === majorStart || !isMajorTerminator(branch[majorEnd])) return null;
2390
- return {
2391
- end: majorEnd,
2392
- major: Number.parseInt(branch.slice(majorStart, majorEnd), 10)
2393
- };
2394
- };
2395
2319
  const normalizeDependencyVersion = (version) => {
2396
2320
  const trimmed = version.trim();
2397
2321
  if (trimmed.length === 0) return null;
@@ -2401,29 +2325,17 @@ const normalizeDependencyVersion = (version) => {
2401
2325
  if (WILDCARD_VERSION.test(normalizedVersion)) return null;
2402
2326
  return normalizedVersion;
2403
2327
  };
2404
- const splitDependencyVersionBranches = (version) => version.split("||").map((branch) => branch.trim()).filter(Boolean);
2405
- const hasUpperBoundComparator = (version) => {
2406
- for (let index = 0; index < version.length; index += 1) if (getUpperBoundComparatorEnd(version, index) !== null) return true;
2407
- return false;
2408
- };
2328
+ const splitDependencyVersionBranches = (version) => version.split(OR_SEPARATOR).filter(Boolean);
2329
+ const hasUpperBoundComparator = (version) => HAS_UPPER_BOUND_COMPARATOR.test(version);
2409
2330
  const getBranchLowestMajor = (branch) => {
2410
- if (hasNonLowerBoundComparator(branch)) return null;
2411
- const lowerBoundComparators = stripUpperBoundComparators(branch).trim();
2331
+ if (NON_LOWER_BOUND_COMPARATOR.test(branch)) return null;
2332
+ const lowerBoundComparators = branch.replace(UPPER_BOUND_COMPARATOR, " ").trim();
2412
2333
  if (lowerBoundComparators.length === 0) return null;
2413
2334
  let branchLowestMajor = null;
2414
- let index = 0;
2415
- while (index < lowerBoundComparators.length) {
2416
- const lowerBoundStart = skipSeparators(lowerBoundComparators, index);
2417
- if (lowerBoundStart > 0 && !isSeparator(lowerBoundComparators[lowerBoundStart - 1])) {
2418
- index = lowerBoundStart + 1;
2419
- continue;
2420
- }
2421
- const lowerBoundMajor = getLowerBoundMajorAt(lowerBoundComparators, lowerBoundStart);
2422
- if (lowerBoundMajor !== null && Number.isFinite(lowerBoundMajor.major) && lowerBoundMajor.major > 0) {
2423
- const major = lowerBoundMajor.major;
2424
- if (branchLowestMajor === null || major < branchLowestMajor) branchLowestMajor = major;
2425
- }
2426
- index = lowerBoundMajor?.end ?? lowerBoundStart + 1;
2335
+ for (const match of lowerBoundComparators.matchAll(LOWER_BOUND_MAJOR)) {
2336
+ const major = Number.parseInt(match[1], 10);
2337
+ if (!Number.isFinite(major) || major <= 0) continue;
2338
+ if (branchLowestMajor === null || major < branchLowestMajor) branchLowestMajor = major;
2427
2339
  }
2428
2340
  return branchLowestMajor;
2429
2341
  };
@@ -2592,7 +2504,6 @@ const resolveCatalogVersion = (packageJson, packageName, rootDirectory, explicit
2592
2504
  const EMPTY_DEPENDENCY_INFO = {
2593
2505
  reactVersion: null,
2594
2506
  tailwindVersion: null,
2595
- zodVersion: null,
2596
2507
  framework: "unknown"
2597
2508
  };
2598
2509
  const pickConcreteVersion = (packageJson, packageName, sections) => {
@@ -2621,11 +2532,6 @@ const extractDependencyInfo = (packageJson) => {
2621
2532
  "devDependencies",
2622
2533
  "peerDependencies"
2623
2534
  ]),
2624
- zodVersion: pickConcreteVersion(packageJson, "zod", [
2625
- "dependencies",
2626
- "devDependencies",
2627
- "peerDependencies"
2628
- ]),
2629
2535
  framework: detectFramework(allDependencies)
2630
2536
  };
2631
2537
  };
@@ -2770,22 +2676,8 @@ const findReactInWorkspaces = (rootDirectory, packageJson) => {
2770
2676
  workspaceDirectory,
2771
2677
  workspacePackageJson
2772
2678
  });
2773
- const zodVersion = resolveWorkspaceDependencyVersion({
2774
- concreteVersion: info.zodVersion,
2775
- packageName: "zod",
2776
- rootDirectory,
2777
- rootPackageJson: packageJson,
2778
- sections: [
2779
- "dependencies",
2780
- "devDependencies",
2781
- "peerDependencies"
2782
- ],
2783
- workspaceDirectory,
2784
- workspacePackageJson
2785
- });
2786
2679
  if (reactVersion && shouldReplaceReactVersion(result.reactVersion, reactVersion)) result.reactVersion = reactVersion;
2787
2680
  if (tailwindVersion && !result.tailwindVersion) result.tailwindVersion = tailwindVersion;
2788
- if (zodVersion && !result.zodVersion) result.zodVersion = zodVersion;
2789
2681
  if (info.framework !== "unknown" && result.framework === "unknown") result.framework = info.framework;
2790
2682
  const resultReactMajor = parseReactMajor(result.reactVersion);
2791
2683
  if (result.reactVersion && result.tailwindVersion && result.framework !== "unknown" && resultReactMajor !== null && resultReactMajor <= 17) return result;
@@ -2820,26 +2712,14 @@ const findDependencyInfoFromMonorepoRoot = (directory) => {
2820
2712
  "peerDependencies"
2821
2713
  ]
2822
2714
  }) : null;
2823
- const leafZodDeclaration = leafPackageJson ? getDependencyDeclaration({
2824
- packageJson: leafPackageJson,
2825
- packageName: "zod",
2826
- sections: [
2827
- "dependencies",
2828
- "devDependencies",
2829
- "peerDependencies"
2830
- ]
2831
- }) : null;
2832
2715
  const shouldUseReactFallback = !leafReactDeclaration?.hasDeclaration;
2833
2716
  const shouldUseTailwindFallback = leafTailwindDeclaration?.hasDeclaration ?? true;
2834
- const shouldUseZodFallback = leafZodDeclaration?.hasDeclaration ?? true;
2835
2717
  const reactCatalogVersion = shouldUseReactFallback ? resolveCatalogVersion(rootPackageJson, "react", monorepoRoot, leafReactDeclaration?.catalogReference) : null;
2836
2718
  const tailwindCatalogVersion = shouldUseTailwindFallback ? resolveCatalogVersion(rootPackageJson, "tailwindcss", monorepoRoot, leafTailwindDeclaration?.catalogReference) : null;
2837
- const zodCatalogVersion = shouldUseZodFallback ? resolveCatalogVersion(rootPackageJson, "zod", monorepoRoot, leafZodDeclaration?.catalogReference) : null;
2838
2719
  const workspaceInfo = findReactInWorkspaces(monorepoRoot, rootPackageJson);
2839
2720
  return {
2840
2721
  reactVersion: shouldUseReactFallback ? reactCatalogVersion ?? rootInfo.reactVersion ?? workspaceInfo.reactVersion : rootInfo.reactVersion ?? workspaceInfo.reactVersion,
2841
2722
  tailwindVersion: shouldUseTailwindFallback ? tailwindCatalogVersion ?? rootInfo.tailwindVersion ?? workspaceInfo.tailwindVersion : null,
2842
- zodVersion: shouldUseZodFallback ? zodCatalogVersion ?? rootInfo.zodVersion ?? workspaceInfo.zodVersion : null,
2843
2723
  framework: rootInfo.framework !== "unknown" ? rootInfo.framework : workspaceInfo.framework
2844
2724
  };
2845
2725
  };
@@ -2919,10 +2799,6 @@ const isPackageJsonReanimatedAware = (packageJson) => {
2919
2799
  };
2920
2800
  return Object.hasOwn(allDependencies, REANIMATED_DEPENDENCY_NAME);
2921
2801
  };
2922
- const parseZodMajor = (zodVersion) => {
2923
- if (typeof zodVersion !== "string") return null;
2924
- return getLowestDependencyMajor(zodVersion);
2925
- };
2926
2802
  const hasUpperBoundOnlyPeerRange = (range) => {
2927
2803
  if (typeof range !== "string") return false;
2928
2804
  const normalizedRange = normalizeDependencyVersion(range);
@@ -3064,7 +2940,7 @@ const discoverProject = (directory) => {
3064
2940
  const packageJsonPath = path.join(directory, "package.json");
3065
2941
  if (!isFile(packageJsonPath)) throw new PackageJsonNotFoundError(directory);
3066
2942
  const packageJson = readPackageJson(packageJsonPath);
3067
- let { reactVersion, tailwindVersion, zodVersion, framework } = extractDependencyInfo(packageJson);
2943
+ let { reactVersion, tailwindVersion, framework } = extractDependencyInfo(packageJson);
3068
2944
  const reactDeclaration = getDependencyDeclaration({
3069
2945
  packageJson,
3070
2946
  packageName: "react",
@@ -3083,19 +2959,9 @@ const discoverProject = (directory) => {
3083
2959
  "peerDependencies"
3084
2960
  ]
3085
2961
  });
3086
- const zodDeclaration = getDependencyDeclaration({
3087
- packageJson,
3088
- packageName: "zod",
3089
- sections: [
3090
- "dependencies",
3091
- "devDependencies",
3092
- "peerDependencies"
3093
- ]
3094
- });
3095
2962
  if (!reactVersion && reactDeclaration.hasDeclaration) reactVersion = resolveCatalogVersion(packageJson, "react", directory, reactDeclaration.catalogReference);
3096
2963
  if (!tailwindVersion && tailwindDeclaration.hasDeclaration) tailwindVersion = resolveCatalogVersion(packageJson, "tailwindcss", directory, tailwindDeclaration.catalogReference);
3097
- if (!zodVersion && zodDeclaration.hasDeclaration) zodVersion = resolveCatalogVersion(packageJson, "zod", directory, zodDeclaration.catalogReference);
3098
- if (!reactVersion || !tailwindVersion || !zodVersion) {
2964
+ if (!reactVersion || !tailwindVersion) {
3099
2965
  const monorepoRoot = findMonorepoRoot(directory);
3100
2966
  if (monorepoRoot) {
3101
2967
  const monorepoPackageJsonPath = path.join(monorepoRoot, "package.json");
@@ -3103,7 +2969,6 @@ const discoverProject = (directory) => {
3103
2969
  const rootPackageJson = readPackageJson(monorepoPackageJsonPath);
3104
2970
  if (!reactVersion && reactDeclaration.hasDeclaration) reactVersion = resolveCatalogVersion(rootPackageJson, "react", monorepoRoot, reactDeclaration.catalogReference);
3105
2971
  if (!tailwindVersion && tailwindDeclaration.hasDeclaration) tailwindVersion = resolveCatalogVersion(rootPackageJson, "tailwindcss", monorepoRoot, tailwindDeclaration.catalogReference);
3106
- if (!zodVersion && zodDeclaration.hasDeclaration) zodVersion = resolveCatalogVersion(rootPackageJson, "zod", monorepoRoot, zodDeclaration.catalogReference);
3107
2972
  }
3108
2973
  }
3109
2974
  }
@@ -3111,19 +2976,16 @@ const discoverProject = (directory) => {
3111
2976
  const workspaceInfo = findReactInWorkspaces(directory, packageJson);
3112
2977
  if (!reactVersion && workspaceInfo.reactVersion) reactVersion = workspaceInfo.reactVersion;
3113
2978
  if (!tailwindVersion && workspaceInfo.tailwindVersion) tailwindVersion = workspaceInfo.tailwindVersion;
3114
- if (!zodVersion && workspaceInfo.zodVersion) zodVersion = workspaceInfo.zodVersion;
3115
2979
  if (framework === "unknown" && workspaceInfo.framework !== "unknown") framework = workspaceInfo.framework;
3116
2980
  }
3117
2981
  if ((!reactVersion || framework === "unknown") && !isMonorepoRoot(directory)) {
3118
2982
  const monorepoInfo = findDependencyInfoFromMonorepoRoot(directory);
3119
2983
  if (!reactVersion) reactVersion = monorepoInfo.reactVersion;
3120
2984
  if (!tailwindVersion) tailwindVersion = monorepoInfo.tailwindVersion;
3121
- if (!zodVersion) zodVersion = monorepoInfo.zodVersion;
3122
2985
  if (framework === "unknown") framework = monorepoInfo.framework;
3123
2986
  }
3124
2987
  if (!reactVersion && reactDeclaration.version && !isCatalogReference(reactDeclaration.version)) reactVersion = reactDeclaration.version;
3125
2988
  if (!tailwindVersion && tailwindDeclaration.version && !isCatalogReference(tailwindDeclaration.version)) tailwindVersion = tailwindDeclaration.version;
3126
- if (!zodVersion && zodDeclaration.version && !isCatalogReference(zodDeclaration.version)) zodVersion = zodDeclaration.version;
3127
2989
  const projectName = packageJson.name ?? path.basename(directory);
3128
2990
  const hasTypeScript = fs.existsSync(path.join(directory, "tsconfig.json"));
3129
2991
  const sourceFileCount = countSourceFiles(directory);
@@ -3136,8 +2998,6 @@ const discoverProject = (directory) => {
3136
2998
  reactVersion,
3137
2999
  reactMajorVersion: resolveEffectiveReactMajor(reactVersion, packageJson),
3138
3000
  tailwindVersion,
3139
- zodVersion,
3140
- zodMajorVersion: parseZodMajor(zodVersion),
3141
3001
  framework,
3142
3002
  hasTypeScript,
3143
3003
  hasReactCompiler: detectReactCompiler(directory, packageJson),
@@ -5662,10 +5522,6 @@ const buildCapabilities = (project) => {
5662
5522
  minor: 4
5663
5523
  })) capabilities.add("tailwind:3.4");
5664
5524
  }
5665
- if (project.zodVersion !== null) {
5666
- capabilities.add("zod");
5667
- if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
5668
- }
5669
5525
  if (project.hasReactCompiler) capabilities.add("react-compiler");
5670
5526
  if (project.hasTanStackQuery) capabilities.add("tanstack-query");
5671
5527
  if (project.hasTypeScript) capabilities.add("typescript");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.2.11-dev.b2934f9",
3
+ "version": "0.2.11-dev.b5cf767",
4
4
  "description": "Diagnose and fix React codebases for security, performance, correctness, accessibility, bundle-size, and architecture issues",
5
5
  "keywords": [
6
6
  "accessibility",
@@ -58,7 +58,7 @@
58
58
  "oxlint": "^1.66.0",
59
59
  "prompts": "^2.4.2",
60
60
  "typescript": ">=5.0.4 <7",
61
- "oxlint-plugin-react-doctor": "0.2.11-dev.b2934f9"
61
+ "oxlint-plugin-react-doctor": "0.2.11-dev.b5cf767"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@types/prompts": "^2.4.9",