Skip to content

Commit 11be3bd

Browse files
committed
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>
1 parent e7d8ab5 commit 11be3bd

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
@@ -594,6 +594,56 @@ provider.setReadOnly();
594594
myVfs.writeFileSync('/x.txt', 'fail'); // throws EROFS
595595
```
596596

597+
## Class: `ComposableProvider`
598+
599+
<!-- YAML
600+
added: REPLACEME
601+
-->
602+
603+
[`ComposableProvider`][] combines one or more providers in priority order. The first
604+
provider is the writable layer; reads search from first to last. Directories
605+
are merged, with entries in higher-priority layers shadowing entries with the
606+
same name in lower layers. Writes to a lower file copy it to the first provider
607+
before changing it. Removing a file hides lower copies without deleting them.
608+
The first provider must be writable to change the composed file system.
609+
610+
### `new ComposableProvider(providers)`
611+
612+
<!-- YAML
613+
added: REPLACEME
614+
-->
615+
616+
* `providers` {VirtualProvider\[]} Non-empty array of providers, ordered from
617+
highest to lowest priority.
618+
619+
```cjs
620+
const vfs = require('node:vfs');
621+
622+
const memory = new vfs.MemoryProvider();
623+
const disk = new vfs.RealFSProvider('/tmp/vfs-root');
624+
const combined = vfs.create(new vfs.ComposableProvider([memory, disk]));
625+
combined.writeFileSync('/config.json', '{"debug":true}');
626+
// The file in memory shadows /tmp/vfs-root/config.json.
627+
```
628+
629+
### `composableProvider.providers`
630+
631+
<!-- YAML
632+
added: REPLACEME
633+
-->
634+
635+
* {VirtualProvider\[]}
636+
637+
A copy of the ordered provider list. Changes to this array do not affect the
638+
composition. File handles opened before a write continue to refer to the layer
639+
on which they were opened. Watching a path watches only its currently selected
640+
provider, not changes across the entire composition. Symbolic links are
641+
resolved by the provider containing them, not across providers. Traversal
642+
through a symbolic-link directory is not supported by the composition. Renaming
643+
a directory over a directory that exists only in a lower layer is not supported.
644+
Layer selection and copy-up use synchronous provider operations, including
645+
when invoked through the asynchronous VFS API.
646+
597647
## Class: `RealFSProvider`
598648

599649
<!-- YAML
@@ -703,6 +753,7 @@ fields use synthetic but stable values:
703753
[`--import`]: cli.md#--importmodule
704754
[`--require`]: cli.md#-r---require-module
705755
[`--vfs-load`]: cli.md#--vfs-loadsource
756+
[`ComposableProvider`]: #class-composableprovider
706757
[`MemoryProvider`]: #class-memoryprovider
707758
[`RealFSProvider`]: #class-realfsprovider
708759
[`VirtualFileSystem`]: #class-virtualfilesystem

0 commit comments

Comments
 (0)