In-memory file-system with Node's fs API providing virtual file systems for testing, mocking, and development purposes.
npx @tessl/cli install tessl/npm-memfs@4.38.0memfs is a comprehensive in-memory file system implementation that mimics Node.js's native fs API, enabling developers to create virtual file systems entirely in memory for testing, mocking, and development purposes. It offers full compatibility with Node.js filesystem operations while also providing browser compatibility through File System Access API adapters and OPFS (Origin Private File System) support.
npm install memfsimport { fs, vol, memfs, Volume } from "memfs";For individual components:
import {
fs, // Default file system instance
vol, // Default volume instance
Volume, // Volume class
memfs, // Factory function
createFsFromVolume, // Factory function
DirectoryJSON, // JSON structure type
NestedDirectoryJSON, // Nested JSON structure type
IFs, // File system interface type
IFsWithVolume // File system with volume type
} from "memfs";CommonJS:
const { fs, vol, memfs, Volume } = require("memfs");import { fs, memfs } from "memfs";
// Use the default file system
fs.writeFileSync("/hello.txt", "Hello World!");
const content = fs.readFileSync("/hello.txt", "utf8");
console.log(content); // "Hello World!"
// Create a new file system from JSON
const { fs: customFs } = memfs({
"/app": {
"package.json": '{"name": "my-app"}',
"src": {
"index.js": "console.log('Hello');"
}
}
});
// Read from the custom file system
const packageJson = customFs.readFileSync("/app/package.json", "utf8");
console.log(JSON.parse(packageJson).name); // "my-app"memfs is built around several key components:
Complete Node.js fs API implementation with synchronous, callback, and promise-based methods. Provides drop-in replacement for Node.js fs module with full compatibility.
// Main exports
export const fs: IFs;
export const vol: Volume;
export function memfs(json?: NestedDirectoryJSON, cwd?: string): { fs: IFs; vol: Volume };
export function createFsFromVolume(vol: Volume): IFs;
// Core volume class providing complete Node.js fs API
export class Volume {
static fromJSON(json: DirectoryJSON, cwd?: string): Volume;
static fromNestedJSON(json: NestedDirectoryJSON, cwd?: string): Volume;
// File operations (synchronous)
readFileSync(path: PathLike, options?: any): string | Buffer;
writeFileSync(path: PathLike, data: any, options?: any): void;
appendFileSync(path: PathLike, data: any, options?: any): void;
copyFileSync(src: PathLike, dest: PathLike, mode?: number): void;
unlinkSync(path: PathLike): void;
existsSync(path: PathLike): boolean;
accessSync(path: PathLike, mode?: number): void;
// File descriptor operations (synchronous)
openSync(path: PathLike, flags: TFlags, mode?: TMode): number;
closeSync(fd: number): void;
readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number | null): number;
writeSync(fd: number, buffer: Buffer, offset?: number, length?: number, position?: number): number;
// Directory operations (synchronous)
mkdirSync(path: PathLike, options?: any): string | undefined;
readdirSync(path: PathLike, options?: any): string[] | Dirent[];
rmdirSync(path: PathLike, options?: any): void;
rmSync(path: PathLike, options?: any): void;
// File status operations (synchronous)
statSync(path: PathLike, options?: any): Stats;
lstatSync(path: PathLike, options?: any): Stats;
fstatSync(fd: number, options?: any): Stats;
// Link operations (synchronous)
linkSync(existingPath: PathLike, newPath: PathLike): void;
symlinkSync(target: PathLike, path: PathLike, type?: string): void;
readlinkSync(path: PathLike, options?: any): string | Buffer;
// Async callback API (all Node.js fs methods available)
readFile(path: PathLike, options: any, callback: (err: Error | null, data?: any) => void): void;
writeFile(path: PathLike, data: any, options: any, callback: (err: Error | null) => void): void;
// ... all Node.js fs callback methods
// Stream operations
createReadStream(path: PathLike, options?: any): ReadStream;
createWriteStream(path: PathLike, options?: any): WriteStream;
// Promise API
promises: FsPromisesApi;
// Watchers
StatWatcher: new () => StatWatcher;
FSWatcher: new () => FSWatcher;
ReadStream: new (...args: any[]) => ReadStream;
WriteStream: new (...args: any[]) => WriteStream;
}
// Core interfaces
export interface IFs extends Volume {
constants: typeof constants;
Stats: new (...args: any[]) => Stats;
Dirent: new (...args: any[]) => Dirent;
}
// JSON structure types
export type NestedDirectoryJSON = { [key: string]: string | Buffer | NestedDirectoryJSON | null };
export type DirectoryJSON = { [key: string]: string | Buffer | null };
// Common types used throughout the API
export type PathLike = string | Buffer | URL;
export type TFlags = string | number;
export type TMode = string | number;File statistics, directory entries, and other utility classes available through the fs object.
// Accessible through fs.Stats constructor
interface Stats {
isFile(): boolean;
isDirectory(): boolean;
isSymbolicLink(): boolean;
size: number;
mode: number;
mtime: Date;
ctime: Date;
// ... other stat properties
}
// Accessible through fs.Dirent constructor
interface Dirent {
name: string;
isFile(): boolean;
isDirectory(): boolean;
isSymbolicLink(): boolean;
}
// Access via fs.Stats and fs.Dirent constructors
const stats = new fs.Stats(/* ... */);
const dirent = new fs.Dirent(/* ... */);File system constants compatible with Node.js fs.constants, accessible through the fs object.
// Access file system constants through fs object
fs.constants.F_OK; // File existence check
fs.constants.R_OK; // Read permission check
fs.constants.W_OK; // Write permission check
fs.constants.X_OK; // Execute permission check
// Open flags
fs.constants.O_RDONLY; // Read-only
fs.constants.O_WRONLY; // Write-only
fs.constants.O_RDWR; // Read-write
fs.constants.O_CREAT; // Create if not exists
fs.constants.O_EXCL; // Exclusive create
fs.constants.O_TRUNC; // Truncate to zero
fs.constants.O_APPEND; // Append mode
// File types and permissions
fs.constants.S_IFMT; // File type mask
fs.constants.S_IFREG; // Regular file
fs.constants.S_IFDIR; // Directory
fs.constants.S_IFLNK; // Symbolic link
// ... all standard Node.js fs constants availablememfs follows Node.js error handling conventions with full error type compatibility:
// Error interface matching Node.js
export interface IError extends Error {
code?: string;
errno?: number;
syscall?: string;
path?: string;
}
// Common error patterns
export interface ErrorPatterns {
// Synchronous methods throw errors
syncError: () => never;
// Callback methods pass errors as first argument
callbackError: (err: IError | null, result?: any) => void;
// Promise methods reject with error objects
promiseError: () => Promise<never>;
}Synchronous API:
try {
const content = fs.readFileSync('/nonexistent.txt', 'utf8');
} catch (error) {
console.log(error.code); // 'ENOENT'
console.log(error.path); // '/nonexistent.txt'
console.log(error.syscall); // 'open'
}Callback API:
fs.readFile('/nonexistent.txt', 'utf8', (err, data) => {
if (err) {
console.log(err.code); // 'ENOENT'
return;
}
console.log(data);
});Promise API:
try {
const content = await fs.promises.readFile('/nonexistent.txt', 'utf8');
} catch (error) {
console.log(error.code); // 'ENOENT'
}| Code | Description | Common Scenarios |
|---|---|---|
ENOENT | File or directory not found | Reading non-existent files, accessing missing directories |
EEXIST | File or directory already exists | Creating files/directories that exist with exclusive flags |
EISDIR | Expected file but found directory | Reading directory as file, writing to directory path |
ENOTDIR | Expected directory but found file | Directory operations on file paths |
EACCES | Permission denied | Accessing files without proper permissions |
EMFILE | Too many open files | Exceeding file descriptor limits |
EBADF | Bad file descriptor | Using invalid or closed file descriptors |
EINVAL | Invalid argument | Invalid parameters or options |
EPERM | Operation not permitted | System-level permission restrictions |