Skip to content

Commit ad55417

Browse files
authored
vfs: add ComposableProvider for layered mounts
Allow providers to be layered at one mount point. Reads search layers in priority order, while writes copy lower-layer files to the first provider and deletions hide lower copies without changing them. Assisted-by: pi Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: #66235 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Paolo Insogna <paolo@cowtech.it>
1 parent 149a864 commit ad55417

4 files changed

Lines changed: 586 additions & 0 deletions

File tree

‎doc/api/vfs.md‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,56 @@ provider.setReadOnly();
650650
myVfs.writeFileSync('/x.txt', 'fail'); // throws EROFS
651651
```
652652

653+
## Class: `ComposableProvider`
654+
655+
<!-- YAML
656+
added: REPLACEME
657+
-->
658+
659+
[`ComposableProvider`][] combines one or more providers in priority order. The first
660+
provider is the writable layer; reads search from first to last. Directories
661+
are merged, with entries in higher-priority layers shadowing entries with the
662+
same name in lower layers. Writes to a lower file copy it to the first provider
663+
before changing it. Removing a file hides lower copies without deleting them.
664+
The first provider must be writable to change the composed file system.
665+
666+
### `new ComposableProvider(providers)`
667+
668+
<!-- YAML
669+
added: REPLACEME
670+
-->
671+
672+
* `providers` {VirtualProvider\[]} Non-empty array of providers, ordered from
673+
highest to lowest priority.
674+
675+
```cjs
676+
const vfs = require('node:vfs');
677+
678+
const memory = new vfs.MemoryProvider();
679+
const disk = new vfs.RealFSProvider('/tmp/vfs-root');
680+
const combined = vfs.create(new vfs.ComposableProvider([memory, disk]));
681+
combined.writeFileSync('/config.json', '{"debug":true}');
682+
// The file in memory shadows /tmp/vfs-root/config.json.
683+
```
684+
685+
### `composableProvider.providers`
686+
687+
<!-- YAML
688+
added: REPLACEME
689+
-->
690+
691+
* {VirtualProvider\[]}
692+
693+
A copy of the ordered provider list. Changes to this array do not affect the
694+
composition. File handles opened before a write continue to refer to the layer
695+
on which they were opened. Watching a path watches only its currently selected
696+
provider, not changes across the entire composition. Symbolic links are
697+
resolved by the provider containing them, not across providers. Traversal
698+
through a symbolic-link directory is not supported by the composition. Renaming
699+
a directory over a directory that exists only in a lower layer is not supported.
700+
Layer selection and copy-up use synchronous provider operations, including
701+
when invoked through the asynchronous VFS API.
702+
653703
## Class: `RealFSProvider`
654704

655705
<!-- YAML
@@ -759,6 +809,7 @@ fields use synthetic but stable values:
759809
[`--import`]: cli.md#--importmodule
760810
[`--require`]: cli.md#-r---require-module
761811
[`--vfs-load`]: cli.md#--vfs-loadsource
812+
[`ComposableProvider`]: #class-composableprovider
762813
[`MemoryProvider`]: #class-memoryprovider
763814
[`RealFSProvider`]: #class-realfsprovider
764815
[`VirtualFileSystem`]: #class-virtualfilesystem

0 commit comments

Comments
 (0)