In-memory file-system with Node's fs API providing virtual file systems for testing, mocking, and development purposes.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Complete Node.js fs API implementation providing drop-in replacement functionality with synchronous, callback, and promise-based methods for all file system operations.
import { fs, vol, Volume, memfs, createFsFromVolume } from "memfs";Core file system volume that implements the complete Node.js fs API.
/**
* Core file system volume class implementing complete Node.js fs API
*/
export class Volume {
// Static factory methods for creating volumes from JSON
static fromJSON(json: DirectoryJSON, cwd?: string): Volume;
static fromNestedJSON(json: NestedDirectoryJSON, cwd?: string): Volume;
// Promise-based API matching Node.js fs.promises
promises: FsPromisesApi;
// Stream constructors
ReadStream: new (...args: any[]) => ReadStream;
WriteStream: new (...args: any[]) => WriteStream;
StatWatcher: new () => StatWatcher;
FSWatcher: new () => FSWatcher;
}Usage Examples:
import { Volume, memfs } from "memfs";
// Create volume from nested JSON structure
const vol = Volume.fromNestedJSON({
'/app': {
'package.json': '{"name": "my-app"}',
'src': {
'index.js': 'console.log("Hello");'
}
}
});
// Create file system from JSON with current working directory
const { fs, vol: customVol } = memfs({
'config.json': '{"port": 3000}',
'logs': null // empty directory
}, '/app');
// Use volume directly
vol.writeFileSync('/test.txt', 'Hello World!');
const content = vol.readFileSync('/test.txt', 'utf8');All Node.js synchronous file operations with identical signatures and behavior.
// File reading and writing
readFileSync(path: PathLike, options?: { encoding?: BufferEncoding | null; flag?: string } | BufferEncoding | null): string | Buffer;
writeFileSync(path: PathLike, data: string | Buffer | Uint8Array, options?: WriteFileOptions): void;
appendFileSync(path: PathLike, data: string | Buffer | Uint8Array, options?: WriteFileOptions): void;
// File metadata and operations
accessSync(path: PathLike, mode?: number): void;
existsSync(path: PathLike): boolean;
copyFileSync(src: PathLike, dest: PathLike, mode?: number): void;
unlinkSync(path: PathLike): void;
truncateSync(path: PathLike, len?: number): void;
// File descriptor operations
openSync(path: PathLike, flags: string | number, mode?: string | number): number;
closeSync(fd: number): void;
readSync(fd: number, buffer: Buffer | Uint8Array, offset: number, length: number, position: number | null): number;
writeSync(fd: number, buffer: Buffer | Uint8Array, offset?: number, length?: number, position?: number): number;
writeSync(fd: number, string: string, position?: number, encoding?: BufferEncoding): number;
ftruncateSync(fd: number, len?: number): void;
fdatasyncSync(fd: number): void;
fsyncSync(fd: number): void;
// File statistics
statSync(path: PathLike, options?: StatOptions): Stats;
lstatSync(path: PathLike, options?: StatOptions): Stats;
fstatSync(fd: number, options?: StatOptions): Stats;
statfsSync(path: PathLike, options?: StatfsOptions): StatFs;
// File permissions and ownership
chmodSync(path: PathLike, mode: string | number): void;
fchmodSync(fd: number, mode: string | number): void;
lchmodSync(path: PathLike, mode: string | number): void;
chownSync(path: PathLike, uid: number, gid: number): void;
fchownSync(fd: number, uid: number, gid: number): void;
lchownSync(path: PathLike, uid: number, gid: number): void;
// File timestamps
utimesSync(path: PathLike, atime: string | number | Date, mtime: string | number | Date): void;
futimesSync(fd: number, atime: string | number | Date, mtime: string | number | Date): void;
lutimesSync(path: PathLike, atime: string | number | Date, mtime: string | number | Date): void;
// Path resolution
realpathSync(path: PathLike, options?: { encoding?: BufferEncoding | null }): string;
realpathSync.native(path: PathLike, options?: { encoding?: BufferEncoding | null }): string;Usage Examples:
import { fs } from "memfs";
// File operations
fs.writeFileSync('/data.txt', 'Hello World!');
const content = fs.readFileSync('/data.txt', 'utf8');
fs.appendFileSync('/data.txt', '\nNew line');
// File descriptor operations
const fd = fs.openSync('/data.txt', 'r');
const buffer = Buffer.alloc(1024);
const bytesRead = fs.readSync(fd, buffer, 0, 1024, 0);
fs.closeSync(fd);
// File metadata
const stats = fs.statSync('/data.txt');
console.log(stats.size, stats.isFile(), stats.mtime);
// File permissions
fs.chmodSync('/data.txt', 0o644);
fs.utimesSync('/data.txt', new Date(), new Date());Complete directory management with creation, reading, and removal capabilities.
// Directory creation and removal
mkdirSync(path: PathLike, options?: MakeDirectoryOptions | string | number): void;
mkdtempSync(prefix: string, options?: { encoding?: BufferEncoding | null }): string;
rmdirSync(path: PathLike, options?: RmDirOptions): void;
rmSync(path: PathLike, options?: RmOptions): void;
cpSync(src: PathLike, dest: PathLike, options?: CpOptions): void;
// Directory reading
readdirSync(path: PathLike, options?: { encoding?: BufferEncoding | null; withFileTypes?: false }): string[];
readdirSync(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false } | "buffer"): Buffer[];
readdirSync(path: PathLike, options?: { encoding?: BufferEncoding | null; withFileTypes: true }): Dirent[];
opendirSync(path: PathLike, options?: OpenDirOptions): Dir;
// Link operations
linkSync(existingPath: PathLike, newPath: PathLike): void;
symlinkSync(target: PathLike, path: PathLike, type?: string): void;
readlinkSync(path: PathLike, options?: { encoding?: BufferEncoding | null }): string;
// Glob operations
globSync(pattern: string, options?: GlobOptions): string[];Usage Examples:
import { fs } from "memfs";
// Directory operations
fs.mkdirSync('/app/src', { recursive: true });
fs.mkdtempSync('/tmp/temp-');
// Directory reading
const files = fs.readdirSync('/app');
const entries = fs.readdirSync('/app', { withFileTypes: true });
entries.forEach(entry => {
if (entry.isDirectory()) {
console.log(`Directory: ${entry.name}`);
} else {
console.log(`File: ${entry.name}`);
}
});
// Link operations
fs.linkSync('/app/src/index.js', '/app/main.js');
fs.symlinkSync('../config.json', '/app/src/config.json');
const target = fs.readlinkSync('/app/src/config.json');
// Glob pattern matching
const jsFiles = fs.globSync('/app/**/*.js');Complete callback-based API matching Node.js fs module exactly, with error-first callback pattern.
// File operations with callbacks
readFile(path: PathLike, options?: { encoding?: BufferEncoding | null; flag?: string } | BufferEncoding | null, callback?: (err: NodeJS.ErrnoException | null, data: string | Buffer) => void): void;
writeFile(path: PathLike, data: string | Buffer | Uint8Array, options: WriteFileOptions, callback: NoParamCallback): void;
writeFile(path: PathLike, data: string | Buffer | Uint8Array, callback: NoParamCallback): void;
appendFile(path: PathLike, data: string | Buffer | Uint8Array, options: WriteFileOptions, callback: NoParamCallback): void;
appendFile(path: PathLike, data: string | Buffer | Uint8Array, callback: NoParamCallback): void;
// Directory operations with callbacks
mkdir(path: PathLike, options: MakeDirectoryOptions, callback: (err: NodeJS.ErrnoException | null, path?: string) => void): void;
mkdir(path: PathLike, callback: NoParamCallback): void;
readdir(path: PathLike, options: { encoding: BufferEncoding | null; withFileTypes: false } | BufferEncoding | null, callback: (err: NodeJS.ErrnoException | null, files: string[]) => void): void;
readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes: false } | "buffer", callback: (err: NodeJS.ErrnoException | null, files: Buffer[]) => void): void;
readdir(path: PathLike, options: { encoding?: BufferEncoding | null; withFileTypes: true }, callback: (err: NodeJS.ErrnoException | null, files: Dirent[]) => void): void;
readdir(path: PathLike, callback: (err: NodeJS.ErrnoException | null, files: string[]) => void): void;
// Stream creation
createReadStream(path: PathLike, options?: string | { flags?: string; encoding?: BufferEncoding; fd?: number; mode?: number; autoClose?: boolean; start?: number; end?: number; highWaterMark?: number }): ReadStream;
createWriteStream(path: PathLike, options?: string | { flags?: string; encoding?: BufferEncoding; fd?: number; mode?: number; autoClose?: boolean; start?: number; highWaterMark?: number }): WriteStream;
// File watching
watch(filename: PathLike, options?: { encoding?: BufferEncoding | null; persistent?: boolean; recursive?: boolean } | BufferEncoding | null, listener?: (eventType: string, filename: string | Buffer) => void): FSWatcher;
watchFile(filename: PathLike, options: { bigint?: boolean; persistent?: boolean; interval?: number }, listener: (curr: Stats, prev: Stats) => void): StatWatcher;
watchFile(filename: PathLike, listener: (curr: Stats, prev: Stats) => void): StatWatcher;
unwatchFile(filename: PathLike, listener?: (curr: Stats, prev: Stats) => void): void;Usage Examples:
import { fs } from "memfs";
// Callback-based file operations
fs.readFile('/data.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
fs.writeFile('/output.txt', 'Hello', (err) => {
if (err) throw err;
console.log('File written!');
});
// Callback-based directory operations
fs.mkdir('/app/logs', { recursive: true }, (err) => {
if (err) throw err;
fs.readdir('/app', (err, files) => {
if (err) throw err;
console.log('Files:', files);
});
});
// Stream operations
const readStream = fs.createReadStream('/large-file.txt');
const writeStream = fs.createWriteStream('/copy.txt');
readStream.pipe(writeStream);
// File watching
const watcher = fs.watch('/app', { recursive: true }, (eventType, filename) => {
console.log(`File ${filename} ${eventType}`);
});Modern promise-based API available via fs.promises with async/await support.
/**
* Promise-based file system API accessed via fs.promises
*/
export interface FsPromisesApi {
// File operations
readFile(path: PathLike, options?: { encoding?: BufferEncoding | null; flag?: string } | BufferEncoding | null): Promise<string | Buffer>;
writeFile(path: PathLike, data: string | Buffer | Uint8Array, options?: WriteFileOptions): Promise<void>;
appendFile(path: PathLike, data: string | Buffer | Uint8Array, options?: WriteFileOptions): Promise<void>;
access(path: PathLike, mode?: number): Promise<void>;
copyFile(src: PathLike, dest: PathLike, mode?: number): Promise<void>;
unlink(path: PathLike): Promise<void>;
truncate(path: PathLike, len?: number): Promise<void>;
// File handle operations
open(path: PathLike, flags: string | number, mode?: string | number): Promise<FileHandle>;
// Directory operations
mkdir(path: PathLike, options?: MakeDirectoryOptions): Promise<string | void>;
readdir(path: PathLike, options?: { encoding?: BufferEncoding | null; withFileTypes?: false }): Promise<string[]>;
readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false } | "buffer"): Promise<Buffer[]>;
readdir(path: PathLike, options: { encoding?: BufferEncoding | null; withFileTypes: true }): Promise<Dirent[]>;
rmdir(path: PathLike, options?: RmDirOptions): Promise<void>;
rm(path: PathLike, options?: RmOptions): Promise<void>;
// File statistics
stat(path: PathLike, options?: StatOptions): Promise<Stats>;
lstat(path: PathLike, options?: StatOptions): Promise<Stats>;
// File watching
watch(filename: PathLike, options?: { encoding?: BufferEncoding | null; persistent?: boolean; recursive?: boolean }): AsyncIterableIterator<{ eventType: string; filename: string | Buffer }>;
// File handle constructor
FileHandle: new (...args: any[]) => FileHandle;
}Usage Examples:
import { fs } from "memfs";
async function example() {
try {
// File operations with async/await
await fs.promises.writeFile('/data.txt', 'Hello World!');
const content = await fs.promises.readFile('/data.txt', 'utf8');
console.log(content);
// Directory operations
await fs.promises.mkdir('/app/logs', { recursive: true });
const files = await fs.promises.readdir('/app');
// File handle operations
const fileHandle = await fs.promises.open('/data.txt', 'r');
const buffer = Buffer.alloc(1024);
const result = await fileHandle.read(buffer, 0, 1024, 0);
await fileHandle.close();
// File statistics
const stats = await fs.promises.stat('/data.txt');
console.log('File size:', stats.size);
} catch (error) {
console.error('Error:', error);
}
}
// File watching with async iteration
async function watchFiles() {
try {
for await (const { eventType, filename } of fs.promises.watch('/app')) {
console.log(`${filename} ${eventType}`);
}
} catch (error) {
console.error('Watch error:', error);
}
}Type definitions for creating file systems from JSON representations.
/**
* Nested directory structure allowing directories and files
*/
export type NestedDirectoryJSON<T = string | Buffer> = {
[key: string]: T | NestedDirectoryJSON<T> | null;
};
/**
* Flat directory structure with absolute paths
*/
export type DirectoryJSON<T = string | Buffer> = {
[key: string]: T | null;
};
/**
* Utility function to flatten nested JSON to flat structure
*/
export function flattenJSON<T>(
nestedJSON: NestedDirectoryJSON<T>,
prefix?: string
): DirectoryJSON<T>;Usage Examples:
import { memfs, Volume, NestedDirectoryJSON } from "memfs";
// Nested JSON structure
const nestedStructure: NestedDirectoryJSON = {
'/app': {
'package.json': JSON.stringify({ name: 'my-app', version: '1.0.0' }),
'src': {
'index.js': 'console.log("Hello World!");',
'utils': {
'helper.js': 'module.exports = { format: s => s.trim() };'
}
},
'tests': {
'index.test.js': 'test("should work", () => { expect(true).toBe(true); });'
},
'logs': null, // empty directory
'README.md': '# My App\n\nA simple application.'
}
};
// Create file system from nested structure
const { fs } = memfs(nestedStructure);
// Flat JSON structure (direct path mapping)
const flatStructure = {
'/app/package.json': '{"name": "my-app"}',
'/app/src/index.js': 'console.log("Hello");',
'/app/logs': null
};
const vol = Volume.fromJSON(flatStructure);// Path-like types
export type PathLike = string | Buffer | URL;
// Option interfaces
export interface WriteFileOptions {
encoding?: BufferEncoding | null;
mode?: string | number;
flag?: string;
}
export interface StatOptions {
bigint?: boolean;
}
export interface StatfsOptions {
bigint?: boolean;
}
export interface MakeDirectoryOptions {
recursive?: boolean;
mode?: string | number;
}
export interface RmDirOptions {
maxRetries?: number;
recursive?: boolean;
retryDelay?: number;
}
export interface RmOptions {
force?: boolean;
maxRetries?: number;
recursive?: boolean;
retryDelay?: number;
}
export interface CpOptions {
dereference?: boolean;
errorOnExist?: boolean;
filter?: (source: string, destination: string) => boolean | Promise<boolean>;
force?: boolean;
preserveTimestamps?: boolean;
recursive?: boolean;
}
export interface OpenDirOptions {
encoding?: BufferEncoding;
bufferSize?: number;
}
export interface GlobOptions {
cwd?: string;
root?: string;
dot?: boolean;
nomount?: boolean;
mark?: boolean;
nosort?: boolean;
stat?: boolean;
silent?: boolean;
strict?: boolean;
cache?: { [path: string]: any };
statCache?: { [path: string]: Stats | false };
symlinks?: { [path: string]: boolean };
nounique?: boolean;
nonull?: boolean;
debug?: boolean;
nobrace?: boolean;
noglobstar?: boolean;
noext?: boolean;
nocase?: boolean;
matchBase?: boolean;
nodir?: boolean;
ignore?: string | string[];
follow?: boolean;
realpath?: boolean;
nonegate?: boolean;
nocomment?: boolean;
minimatch?: any;
flipNegate?: boolean;
}
// Callback types
export type NoParamCallback = (err: NodeJS.ErrnoException | null) => void;