Virtual File System | Node.js v26.5.0 Documentation

Skip to content
Table of contents

- Virtual File System
  - Security
  - Basic usage
  - `vfs.create([provider][, options])`
  - Class: `VirtualFileSystem`
    - `new VirtualFileSystem([provider][, options])`
    - `vfs.provider`
    - `vfs.readonly`
    - APIs
      - Synchronous API
      - Callback API
      - Promise API
  - Class: `VirtualProvider`
    - Capability flags
    - Creating custom providers
  - Class: `MemoryProvider`
    - `memoryProvider.setReadOnly()`
  - Class: `RealFSProvider`
    - `new RealFSProvider(rootPath)`
    - `realFSProvider.rootPath`
  - Implementation details
    - `Stats` objects

## Virtual File System#

Source Code: lib/vfs.js Added in: v26.4.0

Stability: 1 - Experimental

The `node:vfs` module provides a 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:

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

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

### Security#

The VFS API is not a sandbox, permission system, or access-control mechanism. It does not isolate untrusted code from the host file system or from other Node.js capabilities. Code that can access a `VirtualFileSystem` instance, mount it, select its provider, or pass paths to it is trusted application code.

Mounting a VFS only redirects supported `node:fs` calls whose resolved paths are under the mount point. It does not prevent code from using other paths or other Node.js APIs to access resources available to the process. `RealFSProvider` maps VFS paths under its configured root and rejects paths that resolve outside that root, but that check is not a security boundary. Do not rely on VFS to run untrusted code; use operating-system-level isolation, such as separate users, containers, or platform sandboxes, when a security boundary is required.

### Basic usage#

    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!'
    cjs

`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])`#

Added in: 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)`.

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

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

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

### Class: `VirtualFileSystem`#

Added in: 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])`#

Added in: 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`#

Added in: v26.4.0

- {VirtualProvider}

The provider backing this VFS instance.

#### `vfs.readonly`#

Added in: 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:

    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();
    cjs

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`#

Added in: 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#

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

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

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

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`#

Added in: 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()`#

Added in: 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.

    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
    cjs

### Class: `RealFSProvider`#

Added in: 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. This path mapping is not a sandbox or access-control mechanism.

#### `new RealFSProvider(rootPath)`#

Added in: v26.4.0

- `rootPath` `<string>` The absolute file-system path to use as the root. Must be a non-empty string.

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

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

#### `realFSProvider.rootPath`#

Added in: 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.