Skip to content

fix(react-doctor): resolve React from Bun grouped catalogs#192

Open
invivek26 wants to merge 1 commit into
millionco:mainfrom
invivek26:fix/bun-grouped-catalogs
Open

fix(react-doctor): resolve React from Bun grouped catalogs#192
invivek26 wants to merge 1 commit into
millionco:mainfrom
invivek26:fix/bun-grouped-catalogs

Conversation

@invivek26
Copy link
Copy Markdown

@invivek26 invivek26 commented May 9, 2026

Summary

Closes #191.

resolveCatalogVersion already supports Bun's general catalog (workspaces.catalog) and pnpm catalogs, but ignores Bun's grouped/named catalogs at workspaces.catalogs.<group>. Any dependency declared as "react": "catalog:<group>" therefore resolved to null and the user got the misleading No React dependency found error.

This PR adds a parallel branch in resolveCatalogVersion that walks workspaces.catalogs, mirroring the existing handling of the top-level packageJson.catalogs key:

  • Try the named catalog matching the catalog:<name> reference first.
  • Fall back to scanning all named catalogs (matching the existing fallback behavior used elsewhere).

Bun's grouped catalogs are documented at https://bun.com/docs/install/catalogs.

Repro (added as a test)

Root package.json:

{
  "workspaces": {
    "packages": ["apps/*"],
    "catalogs": {
      "react19": { "react": "^19.1.4", "react-dom": "^19.1.4" }
    }
  }
}

App package.json:

{ "dependencies": { "react": "catalog:react19" } }
  • Before: discoverProject(...).reactVersion === null → throws No React dependency found.
  • After: discoverProject(...).reactVersion === "^19.1.4".

Changes

  • src/utils/discover-project.ts — new branch in resolveCatalogVersion for workspaces.catalogs.
  • src/types.ts — extend PackageJson["workspaces"] with catalogs?: Record<string, Record<string, string>>.
  • tests/discover-project.test.ts — new test mirroring the existing Bun default-catalog test.
  • tests/fixtures/bun-named-catalog-workspace/ — minimal fixture.
  • .changeset/fix-bun-grouped-catalogs.md — patch changeset.

Test plan

  • pnpm typecheck
  • pnpm exec vp test run discover-project — 27 passed (was 26)
  • Negative check: stashed only src/utils/discover-project.ts + src/types.ts, the new test fails (reactVersion is null); reapplied, passes.
  • pnpm format
  • pnpm lint — 0 warnings, 0 errors
  • Full pnpm test was not run cleanly; on a fresh checkout the regression suite fails for an unrelated reason (Cannot find module .../utils/react-doctor-plugin.js — the oxlint JS plugin appears to need a build step before tests). Happy to chase down the right pre-test command if you can point me at it.

Note

Low Risk
Low risk: small, additive change to dependency version resolution logic with a focused test/fixture; main risk is unintended precedence when multiple catalogs define the same package.

Overview
Fixes React version detection for Bun workspaces that use grouped/named catalogs under workspaces.catalogs.<name> when dependencies are declared as "react": "catalog:<name>".

resolveCatalogVersion now checks workspaces.catalogs by first trying the referenced named catalog and then falling back to scanning all catalogs, and PackageJson typing plus tests/fixtures and a patch changeset are updated accordingly.

Reviewed by Cursor Bugbot for commit f36880f. Bugbot is set up for automated code reviews on this repo. Configure here.

Adds a branch in resolveCatalogVersion that walks workspaces.catalogs
(Bun's named/grouped catalog map) in addition to workspaces.catalog.
Previously, dependencies declared as 'react: catalog:<group>' against
a Bun grouped catalog failed version resolution and threw the
misleading 'No React dependency found' error.

Closes millionco#191
@vercel
Copy link
Copy Markdown

vercel Bot commented May 9, 2026

@invivek26 is attempting to deploy a commit to the Million Team on Vercel.

A member of the Team first needs to authorize it.

@reactreview
Copy link
Copy Markdown

reactreview Bot commented May 9, 2026

Merging this PR does not change React health

➡️ 0 score
❌ 0 errors
⚠️ 1 warnings

BASE HEAD Change
Score 0 0 0
Errors 26 26 0
Warnings 261 261 0
View top issues (1 of 1)
File Rule Message
../../../../../var/task/packages/react-doctor/src/utils/discover-project.ts:423 js-combine-iterations .map().filter() iterates the array twice — combine into a single loop with .reduce() or for...of
Analysis details

analyzed in 0.7s · nextjs · React 19.2.5 · TypeScript · 210 source files · powered by react-doctor

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f36880f. Configure here.

if (version) return version;
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Named catalog lookup is always skipped for root resolution

Medium Severity

The catalogName at line 279 is derived from the passed packageJson's own dependencies. In the primary call path (line 632), resolveCatalogVersion receives the root package.json, which typically has no react dependency — so catalogName is always null. This makes the specific named-catalog lookup at line 307 dead code. The fallback loop at lines 312–317 then scans all catalogs and returns the first match, which can resolve the wrong version when multiple named catalogs define the same package (e.g. react18 and react19 both declaring react).

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f36880f. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

React version detection fails for Bun grouped catalogs (workspaces.catalogs.<group>)

1 participant