npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@platformatic/vfs

v0.3.0

Published

Virtual File System for Node.js - userland shim for node:vfs

Downloads

279

Readme

@platformatic/vfs

A Virtual File System for Node.js. Provides an in-memory fs-compatible API with mount points, overlay mode, symlinks, module loading hooks, and custom storage providers.

Install

npm install @platformatic/vfs

Requires Node.js >= 22.

Quick start

const { create } = require('@platformatic/vfs');

const vfs = create();

vfs.writeFileSync('/app/index.js', 'module.exports = "hello"');

// Mount the VFS at /app — patches require() and fs so that
// the rest of the process sees virtual files transparently.
vfs.mount('/app');

const mod = require('/app/index.js'); // 'hello'

vfs.unmount();

API

create([provider], [options])

Creates a new VirtualFileSystem instance.

  • provider — a VirtualProvider instance (defaults to MemoryProvider)
  • options.moduleHooks <boolean> — patch require()/import and core fs functions so the process can load modules from the VFS (default true)
  • options.overlay <boolean> — when true, only files that exist in the VFS are intercepted; everything else falls through to the real filesystem (default false)
  • options.virtualCwd <boolean> — enable a virtual working directory that intercepts process.cwd() and process.chdir() (default false)

Returns a VirtualFileSystem.

VirtualFileSystem

Properties

| Property | Type | Description | |---|---|---| | provider | VirtualProvider | The underlying storage provider | | mountPoint | string \| null | Current mount prefix, or null | | mounted | boolean | Whether the VFS is currently mounted | | readonly | boolean | Whether the provider is read-only | | overlay | boolean | Whether overlay mode is enabled |

Mount / Unmount

vfs.mount('/prefix');   // Start intercepting paths under /prefix
vfs.unmount();          // Stop intercepting

mount() returns the VFS instance for chaining. When mounted with moduleHooks: true (the default), require(), import, and core fs functions (readFileSync, statSync, existsSync, readdirSync, realpathSync, watch, etc.) are patched to serve files from the VFS.

Emits vfs-mount and vfs-unmount events on process.

Supports Symbol.dispose — works with using declarations in environments that support it.

shouldHandle(path)

Returns true if the given path would be handled by this VFS instance. In overlay mode, only returns true for paths that actually exist in the VFS.

Sync API

The full synchronous fs API:

vfs.writeFileSync(path, data[, options])
vfs.readFileSync(path[, options])          // returns Buffer or string
vfs.existsSync(path)
vfs.statSync(path[, options])
vfs.lstatSync(path[, options])
vfs.readdirSync(path[, options])           // supports { withFileTypes: true }
vfs.mkdirSync(path[, options])             // supports { recursive: true }
vfs.rmdirSync(path)
vfs.unlinkSync(path)
vfs.renameSync(oldPath, newPath)
vfs.copyFileSync(src, dest)
vfs.appendFileSync(path, data[, options])
vfs.accessSync(path[, mode])
vfs.realpathSync(path[, options])
vfs.symlinkSync(target, path[, type])
vfs.readlinkSync(path[, options])

File descriptors

const fd = vfs.openSync(path[, flags[, mode]]);
vfs.readSync(fd, buffer, offset, length, position);
vfs.fstatSync(fd[, options]);
vfs.closeSync(fd);

Callback API

Every sync method has a callback counterpart following the standard Node.js (err, result) convention:

vfs.readFile(path, options, callback)
vfs.writeFile(path, data, options, callback)
vfs.stat(path, options, callback)
vfs.readdir(path, options, callback)
// ...

Promises API

const content = await vfs.promises.readFile('/file.txt', 'utf8');
await vfs.promises.writeFile('/file.txt', 'data');
await vfs.promises.mkdir('/dir', { recursive: true });
const entries = await vfs.promises.readdir('/dir');
const stats = await vfs.promises.stat('/file.txt');
await vfs.promises.unlink('/file.txt');
await vfs.promises.rename('/old', '/new');
await vfs.promises.copyFile('/src', '/dest');
await vfs.promises.appendFile('/file.txt', 'more');
await vfs.promises.access('/file.txt');
await vfs.promises.symlink('/target', '/link');
const target = await vfs.promises.readlink('/link');
await vfs.promises.lstat('/link');
await vfs.promises.realpath('/link');
await vfs.promises.rmdir('/dir');

Streams

const stream = vfs.createReadStream(path[, options]);

Returns a Readable stream. Options support start, end, and autoClose.

Watch

const watcher = vfs.watch(path[, options][, listener]);
vfs.watchFile(path[, options], listener);
vfs.unwatchFile(path[, listener]);

Virtual working directory

When created with { virtualCwd: true }:

const vfs = create({ virtualCwd: true });
vfs.writeFileSync('/app/file.txt', 'data');
vfs.mount('/app');

vfs.chdir('/app');
vfs.cwd(); // '/app'

When mounted, process.cwd() and process.chdir() are patched to work with the virtual directory.

Providers

MemoryProvider

The default provider. Stores everything in memory. Supports symlinks, watching, and read-only mode.

const { MemoryProvider, create } = require('@platformatic/vfs');

const provider = new MemoryProvider();
const vfs = create(provider);

vfs.writeFileSync('/file.txt', 'hello');

// Freeze the provider to prevent writes
provider.setReadOnly();
vfs.writeFileSync('/other.txt', 'fail'); // throws EROFS

SqliteProvider

A persistent provider backed by Node.js built-in node:sqlite. Stores files, directories, and symlinks in a SQLite database. Supports both in-memory and file-backed databases.

const { SqliteProvider, create } = require('@platformatic/vfs');

// In-memory (default)
const mem = new SqliteProvider();
const vfs1 = create(mem);

// File-backed — data persists across restarts
const disk = new SqliteProvider('/tmp/myfs.db');
const vfs2 = create(disk);

vfs2.writeFileSync('/file.txt', 'hello');
disk.close();

// Reopen later — files are still there
const disk2 = new SqliteProvider('/tmp/myfs.db');
const vfs3 = create(disk2);
vfs3.readFileSync('/file.txt', 'utf8'); // 'hello'
disk2.close();

Requires Node.js >= 22. Call provider.close() when done to close the database.

RealFSProvider

Delegates to the real filesystem, sandboxed under a root directory. Directory traversal outside the root is prevented.

const { RealFSProvider, create } = require('@platformatic/vfs');

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

// All paths are resolved relative to /tmp/sandbox
vfs.writeFileSync('/file.txt', 'data'); // writes to /tmp/sandbox/file.txt

Custom providers

Extend VirtualProvider and implement the essential primitives:

const { VirtualProvider, create } = require('@platformatic/vfs');

class MyProvider extends VirtualProvider {
  openSync(path, flags, mode) { /* ... */ }
  statSync(path, options) { /* ... */ }
  readdirSync(path, options) { /* ... */ }
  mkdirSync(path, options) { /* ... */ }
  rmdirSync(path) { /* ... */ }
  unlinkSync(path) { /* ... */ }
  renameSync(oldPath, newPath) { /* ... */ }
}

const vfs = create(new MyProvider());

Higher-level operations (readFile, writeFile, copyFile, exists, access, etc.) are provided automatically by the base class using the primitives above.

Module hooks

When moduleHooks is enabled (the default), mounting a VFS instance:

  1. Patches require() and import — On Node.js 23.5+ uses Module.registerHooks(). On older versions falls back to Module._resolveFilename + Module._extensions patching.
  2. Patches core fs functionsreadFileSync, statSync, lstatSync, readdirSync, existsSync, realpathSync, watch, watchFile, unwatchFile.

This means third-party code using require() or fs.readFileSync() will transparently pick up files from the VFS.

Module resolution supports package.json exports, main, and bare specifier resolution walking node_modules.

Node.js core VFS support

This package is a direct extraction of the Virtual File System being added to Node.js core (nodejs/node#61478), allowing it to be used on Node.js 22+. Once the core PR lands, this package will no longer be necessary (except for SqliteProvider).

License

MIT