fix(installer): replace fs-extra with native node:fs to prevent file loss#2253
fix(installer): replace fs-extra with native node:fs to prevent file loss#2253
Conversation
…loss fs-extra routes all operations through graceful-fs, which globally monkey-patches node:fs with a deferred retry queue. During multi-module installs (~500+ file ops), retried unlink operations from one module's remove phase can fire after the next module's copy phase has written files, silently deleting them non-deterministically. Replace fs-extra with a thin fs-native.js wrapper over node:fs/promises and node:fs. All 21 consumers now use native APIs with no global monkey-patching, eliminating the retry-queue race condition entirely. Closes #1779
🤖 Augment PR SummarySummary: This PR replaces the installer’s use of Changes:
Technical Notes: The intent is to avoid 🤖 Was this summary useful? React with 👍 or 👎 |
Add missing move() with cross-device fallback (rename → copy+rm on EXDEV), needed by OfficialModules.createModuleDirectories for directory migrations during upgrades. Honor overwrite/errorOnExist options in copy() to match fs-extra behavior for callers that pass these flags.
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThe PR systematically replaces the Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
fs-extradependency with a thinfs-native.jswrapper over nativenode:fs/promisesandnode:fsgraceful-fsmonkey-patching that causes non-deterministic file loss during multi-module installs on macOS (APFS)fs-extrafrompackage.jsondependenciesRoot Cause
fs-extraroutes all operations throughgraceful-fs, which globally monkey-patchesnode:fswith a deferred EMFILE retry queue (setTimeout(retry, 0)). During multi-module installs (~500+ file ops), each module goes through a remove-then-copy cycle. Retried unlink operations from the remove phase can fire after subsequent copy operations have written files, silently deleting them. The exact files lost vary between runs (non-deterministic), and the installer reports success.Fix
fs-native.jsprovides the same API surface (pathExists,ensureDir,remove,copy, etc.) using only stable native Node.js APIs with no global state or monkey-patching. File operations execute and complete in the order they are awaited.Test plan
require('fs-extra')in source codeCloses #1779