fix(deps): declare react-native-fs so npm stops pruning alasql's optional subtree - #159
Merged
Merged
Conversation
…onal subtree `npm ci` has failed on nine consecutive `renovate/all-minor-patch` heads (#158, occurrences 1-9) with ~246 `Missing: ... from lock file` errors for the react-native / metro / jest / babel tree. Root cause: `alasql`, nested under `harper`, declares `optionalDependencies: { "react-native-fs": "^2.20.0" }`. npm omits optional subtrees when it resolves a tree with **no lockfile present**, but materializes them when reifying against an existing lock. Renovate regenerates `package-lock.json` from scratch, so it hits the omitting path and writes a lock that `npm ci` then rejects. Reproduced on main (Node 24.19.0, npm 11.17.0) by deleting the lock and regenerating: keys 1649 -> 1383, `react-native*` entries 28 -> 0, `npm ci` exit 1 with 246 `Missing:`. Declaring `react-native-fs` at the root makes it survive that resolve, because root-level entries are not subject to the omission. Same test on this branch: keys -> 1653, `react-native*` -> 37, `npm ci` exit 0. It goes in `devDependencies`, not `optionalDependencies`, on purpose. `harper` is a devDependency here and this package is published, so an optional root entry would flip the react-native subtree from `dev: true` to a production dep and ship React Native to everyone who installs the CLI. As a devDependency the subtree keeps `dev: true` and production installs are untouched. The lockfile diff is metadata only: 0 entries added, 0 removed, 0 version changes - just `dev`/`optional` flag reclassification on 249 entries. Renovate is set to ignore the package, since nothing here imports it and its only job is to keep npm honest. Verified locally: npm ci, lint, format, build, and 53 files / 345 tests all pass.
There was a problem hiding this comment.
Code Review
This pull request adds react-native-fs as a root dependency in package.json and package-lock.json, and configures renovate.json to ignore updates for it. This change is a workaround to prevent npm from dropping optional subtrees (specifically react-native-fs under alasql/harper) when Renovate regenerates the lockfile without an existing lockfile, which previously resulted in a lockfile missing many entries and causing npm ci failures. There are no review comments to assess, and I have no feedback to provide.
|
🎉 This PR is included in version 0.16.50 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
react-native-fstodevDependenciesand tells Renovate to ignore it. That's the whole fix —package.json+1 line,renovate.json+5, and a metadata-only lockfile diff.Why
npm cihas failed on nine consecutiverenovate/all-minor-patchheads (#158) with ~246Missing: ... from lock fileerrors. Each one was healed by hand. This stops it happening again.Root cause
alasql, nested underharper, declares:npm omits optional subtrees when it resolves a tree with no lockfile present, but materializes them when reifying against an existing lock. Renovate regenerates
package-lock.jsonfrom scratch, so it takes the omitting path and writes a lock thatnpm cithen rejects.That last part is what took nine occurrences to pin down. Earlier attempts to reproduce it kept "failing" because they started from a lockfile that already had the subtree — that path always keeps it. Deleting the lock first reproduces it every time.
Measured on
main, Node 24.19.0 / npm 11.17.0:react-native*npm cimainas committedmain, lock deleted + regeneratedMissing:Root-level entries aren't subject to the omission, so declaring it at the root is enough.
Why
devDependenciesand notoptionalDependenciesI tried
optionalDependenciesfirst. It fixes the prune, butharperis a devDependency here and this package is published, so an optional root entry flips the whole react-native subtree fromdev: trueto a production dependency — shipping React Native to everyone who runsnpm i -g @harperfast/agent. The lockfile showed it plainly: 307 entries changing theirdevflag.As a
devDependencythe subtree keepsdev: trueand production installs are untouched. Dev install weight doesn't change either —react-nativeandreact-native-fsare already innode_modulestoday.The lockfile diff is metadata only
The 250 deleted lines are
"optional": true/"dev": trueflags being reclassified, not packages going away.Alternatives ruled out
postUpdateOptions: ["npmDedupe"]— does fix the prune, butnpm dedupere-resolves to latest-in-range: 71 version changes even on a perfectly healthy lock (esbuild0.27.2→0.27.7,zod4.5.4→4.6.2,agent-base7→9, …). Every dependency PR would silently carry ~70 unrelated bumps.skipInstalls: false— already set in this repo; doesn't help (occurrences 1-9 all happened with it on).--package-lock-onlyregeneration — never materializes the subtree, however many passes.Verification
On this branch, Node 24.19.0 / npm 11.17.0:
Plus the from-scratch regenerate test in the table above — the one that actually proves the fix.
Note for whoever merges
This does not retroactively fix #158. That branch still carries a pruned lock and needs one full
npm install(or a rebase once this is onmain).🤖 Generated with Claude Code