@componentor/fs 3.0.48 → 3.0.50

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@componentor/fs",
3
- "version": "3.0.48",
3
+ "version": "3.0.50",
4
4
  "description": "High-performance OPFS-based Node.js fs polyfill with true sync API, VFS binary format, and bidirectional OPFS mirroring",
5
5
  "license": "MIT",
6
6
  "author": "Componentor",
package/readme.md CHANGED
@@ -604,6 +604,21 @@ Make sure `opfsSync` is enabled (it's `true` by default). Files are mirrored to
604
604
 
605
605
  See [CHANGELOG.md](./CHANGELOG.md) for the full version history.
606
606
 
607
+ ### v3.0.50 (2026)
608
+
609
+ **Fixes:**
610
+ - OPFS mirror no longer diverges from VFS state when the rename source is a directory. `renameInOPFS` previously hard-coded `getFileHandle`, which throws `TypeMismatchError` for directories — so the VFS rename fix in 3.0.49 (e.g. Vite's `deps_temp_<hash>` → `deps`) succeeded in-memory but the on-disk OPFS mirror silently warned-and-skipped, leaving the two diverged until the next full reconcile
611
+ - On `TypeMismatchError`/`NotFoundError`, falls through to a directory-aware path: recursively `removeEntry` the destination (matching the engine's "rm-then-rename" semantics), recreate as an empty dir, walk the source tree copying every file via two sync access handles in 2 MB chunks (peak memory bounded by `RENAME_CHUNK` regardless of subtree size), then `removeEntry` the source
612
+
613
+ ### v3.0.49 (2026)
614
+
615
+ **Fixes:**
616
+ - `rename` over a non-empty directory no longer leaves stale descendants. Previously the target's children survived in `pathIndex` while their inodes were never freed; source descendants were laid on top, leaking inodes and leaving zombies reachable via `read`. Surfaced as corrupt `.vite/deps` after Vite's `deps_temp_<hash>` → `deps` swap (stale chunks for `vue.js`, `@unhead/vue`, etc., or 404s)
617
+ - `rename(x, x)` no longer destroys the file (it used to free its own blocks and mark its inode FREE before re-pointing the index)
618
+ - Same descendant-cleanup logic now applies when the rename target is an *implicit* directory (path with no inode of its own but with descendants in `pathIndex` — the state produced by bulk OPFS import)
619
+ - `write`, `symlink`, `link`, and `copy` (with `COPYFILE_EXCL`) now reject implicit-directory targets (EISDIR for `write`, EEXIST for the others). Previously these silently clobbered the implicit dir, e.g. registering a regular `FILE` inode at a path whose children still existed in `pathIndex` — breaking every subsequent read of that path and its subtree
620
+ - Add 5 regression tests in `implicit-dir-targets.test.ts` covering each fixed call site
621
+
607
622
  ### v3.0.48 (2026)
608
623
 
609
624
  **Fixes:**