fix: Mark react-native-nitro-modules peer dependency as optional - #1516
Conversation
Semver ranges never match pre-releases, so a required peer of "*" does not match e.g. 0.37.0-beta.0. Package managers then install a second, stable copy of Nitro next to the pre-release, and the native/JS version guard throws "Nitro was installed twice" at runtime. Marking the peer optional stops the package manager from resolving Nitro on the library's behalf, leaving the app in full control of the version.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 682bfc9745
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "overrides": { | ||
| "react-native-nitro-modules": "0.37.0-beta.0" | ||
| } |
There was a problem hiding this comment.
Use an npm-compatible override for the direct dependency
When the app installed the beta normally, npm records a direct dependency such as "react-native-nitro-modules": "^0.37.0-beta.0"; npm 11.4.2 rejects the shown exact-version override before resolution with EOVERRIDE: Override for react-native-nitro-modules@^0.37.0-beta.0 conflicts with direct dependency. Consequently, npm users cannot complete this recovery procedure. Use an override referencing the direct dependency (for example $react-native-nitro-modules) or instruct users to make the direct dependency and override specifications identical.
Useful? React with 👍 / 👎.
| npm install nitrogen --save-dev | ||
| ``` | ||
|
|
||
| Also declare `react-native-nitro-modules` as an **optional peer dependency**, so the app using your library is the one that decides which Nitro version gets installed: |
There was a problem hiding this comment.
Update the package README with the optional-peer metadata
The published packages/react-native-nitro-modules/README.md still tells library authors to add only the required "react-native-nitro-modules": "*" peer (lines 25–37). Authors following the npm/GitHub landing-page instructions instead of this Docusaurus page will therefore continue producing packages that trigger the duplicate installation under Bun with a Nitro prerelease, recreating the exact runtime failure this change is intended to prevent.
Useful? React with 👍 / 👎.
Problem
Semver ranges never match pre-release versions unless a comparator shares the same
major.minor.patchtuple and carries a pre-release tag. So the"react-native-nitro-modules": "*"peer range that every Nitro Module declares does not match0.37.0-beta.0:*>=0.0.0-0>=0.37.0-0Because the peer is required, bun tries to satisfy it itself and installs a second, stable copy of
react-native-nitro-modulesnested inside the library. The native build then links the pre-release while Metro bundles the stable JS, and Nitro's own version guard throws at startup:This is exactly what happened when upgrading react-native-nitro-image to the 0.37 beta (mrousavy/react-native-nitro-image#166) - builds stayed green, only the runtime harness tests caught it.
Fix
Mark the peer as optional. No range can express "anything, including future pre-releases" (see the table -
>=0.37.0-0just moves the breakage to 0.38.0-beta.0), so the fix has to be resolution behaviour rather than a cleverer range.Verified with a minimal repro: bumping an existing lockfile to a pre-release keeps a stale stable copy with a required peer, and resolves to a single copy with an optional one.
Applied to
packages/template(socreate-nitro-moduleand the docs' manual setup produce it), plus the two test libraries.Trade-off
optional: truealso suppresses the missing peer warning. That's an acceptable loss here: a Nitro Module withoutreact-native-nitro-modulesfails loudly at build time (autolinking can't find the pod / Gradle project), and version mismatches are already caught by Nitro's runtime guard - which is strictly stronger than an install-time range check.Docs
Nitro was installed twicesection covering diagnosis (npm ls), the real fix, theoverrides/resolutionsworkaround for app authors stuck on a library that hasn't updated, and the reminder that package managers leave the stale copy on disk after the lockfile is fixed.Note npm is unaffected - it special-cases
*and accepts the pre-release. This is bun-specific behaviour.