Back to Node

Virtual File System

doc/api/vfs.md

26.4.07.9 KB
Original Source

Virtual File System

<!--introduced_in=v26.4.0--> <!-- YAML added: v26.4.0 -->

Stability: 1 - Experimental

<!-- source_link=lib/vfs.js -->

The node:vfs module provides an in-memory virtual file system with a node:fs-like API. It is useful for tests, fixtures, embedded assets, and other scenarios where you need a self-contained file system without touching the actual file-system.

To access it:

mjs
import vfs from 'node:vfs';
cjs
const vfs = require('node:vfs');

This module is only available under the node: scheme, and only when Node.js is started with the --experimental-vfs flag.

Basic usage

cjs
const vfs = require('node:vfs');

const myVfs = vfs.create();
myVfs.mkdirSync('/dir', { recursive: true });
myVfs.writeFileSync('/dir/hello.txt', 'Hello, VFS!');

console.log(myVfs.readFileSync('/dir/hello.txt', 'utf8')); // 'Hello, VFS!'

vfs.create() returns a VirtualFileSystem instance backed by a MemoryProvider by default. The instance exposes synchronous, callback-based, and promise-based file system methods that mirror the shape of the node:fs API. All paths are POSIX-style and absolute (starting with /).

vfs.create([provider][, options])

<!-- YAML added: v26.4.0 -->
  • provider {VirtualProvider} The provider to use. Default: new MemoryProvider().
  • options {Object}
    • emitExperimentalWarning {boolean} Whether to emit the experimental warning when the instance is created. Default: true.
  • Returns: {VirtualFileSystem}

Convenience factory equivalent to new VirtualFileSystem(provider, options).

cjs
const vfs = require('node:vfs');

// Default in-memory provider
const memoryVfs = vfs.create();

// Explicit provider
const realVfs = vfs.create(new vfs.RealFSProvider('/tmp/sandbox'));

Class: VirtualFileSystem

<!-- YAML added: v26.4.0 -->

A VirtualFileSystem wraps a VirtualProvider and exposes a node:fs-like API. Each instance maintains its own file tree.

new VirtualFileSystem([provider][, options])

<!-- YAML added: v26.4.0 -->
  • provider {VirtualProvider} The provider to use. Default: new MemoryProvider().
  • options {Object}
    • emitExperimentalWarning {boolean} Whether to emit the experimental warning. Default: true.

vfs.provider

<!-- YAML added: v26.4.0 -->
  • {VirtualProvider}

The provider backing this VFS instance.

vfs.readonly

<!-- YAML added: v26.4.0 -->
  • {boolean}

true when the underlying provider is read-only.

APIs

VirtualFileSystem implements the following methods, with the same signatures as their node:fs counterparts:

Synchronous API

  • existsSync(path)
  • statSync(path[, options])
  • lstatSync(path[, options])
  • readFileSync(path[, options])
  • writeFileSync(path, data[, options])
  • appendFileSync(path, data[, options])
  • readdirSync(path[, options])
  • mkdirSync(path[, options])
  • rmdirSync(path)
  • unlinkSync(path)
  • renameSync(oldPath, newPath)
  • copyFileSync(src, dest[, mode])
  • realpathSync(path[, options])
  • readlinkSync(path[, options])
  • symlinkSync(target, path[, type])
  • accessSync(path[, mode])
  • rmSync(path[, options])
  • truncateSync(path[, len])
  • ftruncateSync(fd[, len])
  • linkSync(existingPath, newPath)
  • chmodSync(path, mode)
  • chownSync(path, uid, gid)
  • utimesSync(path, atime, mtime)
  • lutimesSync(path, atime, mtime)
  • mkdtempSync(prefix)
  • opendirSync(path[, options])
  • openAsBlob(path[, options])
  • File-descriptor ops: openSync, closeSync, readSync, writeSync, fstatSync
  • Streams: createReadStream, createWriteStream
  • Watchers: watch, watchFile, unwatchFile

Callback API

readFile, writeFile, stat, lstat, readdir, realpath, readlink, access, open, close, read, write, rm, fstat, truncate, ftruncate, link, mkdtemp, opendir. Each takes a Node.js-style callback (err, ...result) => {}.

Promise API

vfs.promises exposes the promise-based variants:

cjs
const vfs = require('node:vfs');

async function example() {
  const myVfs = vfs.create();
  await myVfs.promises.writeFile('/file.txt', 'hello');
  const data = await myVfs.promises.readFile('/file.txt', 'utf8');
  return data;
}
example();

The promise namespace mirrors fs.promises and includes readFile, writeFile, appendFile, stat, lstat, readdir, mkdir, rmdir, unlink, rename, copyFile, realpath, readlink, symlink, access, rm, truncate, link, mkdtemp, chmod, chown, lchown, utimes, lutimes, open, lchmod, and watch.

Class: VirtualProvider

<!-- YAML added: v26.4.0 -->

The base class for all VFS providers. Subclasses implement the essential primitives (open, stat, readdir, mkdir, rmdir, unlink, rename, ...) and inherit default implementations of the derived The base class for all VFS providers. Subclasses implement the essential primitives (such as open, stat, readdir, mkdir, rmdir, unlink, rename, etc.) and inherit default implementations of the derived methods (such as readFile, writeFile, exists, copyFile, access, etc.).

Capability flags

  • provider.readonly {boolean} Default: false.
  • provider.supportsSymlinks {boolean} Default: false.
  • provider.supportsWatch {boolean} Default: false.

Creating custom providers

cjs
const { VirtualProvider } = require('node:vfs');

class StaticProvider extends VirtualProvider {
  get readonly() { return true; }

  statSync(path) { /* ... */ }
  openSync(path, flags) { /* ... */ }
  readdirSync(path, options) { /* ... */ }
  // ...
}

The base class throws ERR_METHOD_NOT_IMPLEMENTED for any primitive that has not been overridden, and rejects writes from a readonly provider with EROFS.

Class: MemoryProvider

<!-- YAML added: v26.4.0 -->

The default in-memory provider. Stores files, directories, and symbolic links in a Map-backed tree, supports symlinks (supportsSymlinks === true), and supports watching (supportsWatch === true).

memoryProvider.setReadOnly()

<!-- YAML added: v26.4.0 -->

Locks the provider into read-only mode. Subsequent writes through any VirtualFileSystem using this provider throw EROFS. There is no way to revert the provider to writable.

cjs
const vfs = require('node:vfs');

const provider = new vfs.MemoryProvider();
const myVfs = vfs.create(provider);
myVfs.writeFileSync('/seed.txt', 'initial');

provider.setReadOnly();

myVfs.writeFileSync('/x.txt', 'fail'); // throws EROFS

Class: RealFSProvider

<!-- YAML added: v26.4.0 -->

A provider that wraps a directory (i.e. one on the actual file system) and exposes its contents through the VFS API. All VFS paths are resolved relative to the root and verified to stay inside it; symbolic links resolving outside the root are rejected.

new RealFSProvider(rootPath)

<!-- YAML added: v26.4.0 -->
  • rootPath {string} The absolute file-system path to use as the root. Must be a non-empty string.
cjs
const vfs = require('node:vfs');

const realVfs = vfs.create(new vfs.RealFSProvider('/tmp/sandbox'));
realVfs.writeFileSync('/file.txt', 'hello'); // writes /tmp/sandbox/file.txt

realFSProvider.rootPath

<!-- YAML added: v26.4.0 -->
  • {string}

The resolved absolute path used as the root.

Implementation details

Stats objects

VFS Stats objects are real instances of fs.Stats (or fs.BigIntStats when { bigint: true } is requested). Their fields use synthetic but stable values:

  • dev is 4085 (the VFS device id).
  • ino is monotonically increasing per process.
  • blksize is 4096.
  • blocks is Math.ceil(size / 512).
  • Times default to the moment the entry was created/last modified.