or run

tessl search
Log in

Version

Files

tile.json

tessl/npm-metro-memory-fs

A memory-based implementation of Node.js fs module for testing purposes

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/metro-memory-fs@0.82.x

Agent Success

Agent success rate when using this tile

96%

Improvement

Agent success rate improvement when using this tile compared to baseline

1.26x

Baseline

Agent success rate without this tile

76%

To install, run

tessl install tessl/npm-metro-memory-fs@0.82.0

index.mddocs/

Metro Memory FS

Metro Memory FS provides a complete in-memory filesystem implementation that mimics the Node.js fs module API for testing purposes. It offers a comprehensive drop-in replacement for the native filesystem API, supporting all standard file operations including reading, writing, creating, deleting files and directories, symbolic links, file descriptors, and file watchers.

Package Information

  • Package Name: metro-memory-fs
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install metro-memory-fs

Core Imports

const MemoryFs = require("metro-memory-fs");

ES Modules:

import MemoryFs from "metro-memory-fs";

Basic Usage

const MemoryFs = require("metro-memory-fs");

// Create a new memory filesystem instance
const fs = new MemoryFs({ 
  cwd: () => "/current/working/dir",
  platform: "posix" // or "win32"
});

// Write and read files
fs.writeFileSync("/hello.txt", "Hello, World!");
const content = fs.readFileSync("/hello.txt", "utf8");
console.log(content); // "Hello, World!"

// Create directories
fs.mkdirSync("/mydir", { recursive: true });

// List directory contents
const files = fs.readdirSync("/");
console.log(files); // ["hello.txt", "mydir"]

// Check if file exists
const exists = fs.existsSync("/hello.txt");
console.log(exists); // true

// Use async operations
fs.readFile("/hello.txt", "utf8", (err, data) => {
  if (!err) {
    console.log(data); // "Hello, World!"
  }
});

// Use promises
const data = await fs.promises.readFile("/hello.txt", "utf8");
console.log(data); // "Hello, World!"

Architecture

Metro Memory FS is built around several key components:

  • Memory Filesystem: Complete in-memory representation of files and directories using Map-based storage
  • Path Resolution: Cross-platform path handling supporting both POSIX and Windows path conventions
  • Node Compatibility: Full API compatibility with Node.js fs module including sync, async, and promise variants
  • File Descriptors: Low-level file descriptor support for fine-grained file operations
  • Streams: Readable and writable stream implementations for large file handling
  • File Watching: Event-based file system monitoring with recursive watching support

Capabilities

File Operations

Core file reading, writing, and manipulation operations supporting both synchronous and asynchronous patterns with full Node.js fs API compatibility.

// Synchronous operations
writeFileSync(path: string | Buffer, data: string | Buffer, options?: WriteFileOptions): void;
readFileSync(path: string | Buffer, options?: ReadFileOptions): string | Buffer;
existsSync(path: string | Buffer): boolean;
unlinkSync(path: string | Buffer): void;
copyFileSync(src: string | Buffer, dest: string | Buffer, flags?: number): void;
accessSync(path: string | Buffer, mode?: number): void;
truncateSync(path: string | Buffer | number, len?: number): void;

// Asynchronous operations
writeFile(path: string | Buffer, data: string | Buffer, options?: WriteFileOptions, callback?: (err?: Error) => void): void;
readFile(path: string | Buffer, options?: ReadFileOptions, callback?: (err?: Error, data?: string | Buffer) => void): void;
unlink(path: string | Buffer, callback: (err?: Error) => void): void;
copyFile(src: string | Buffer, dest: string | Buffer, flags?: number, callback?: (err?: Error) => void): void;
access(path: string | Buffer, mode?: number, callback?: (err?: Error) => void): void;
truncate(path: string | Buffer, len?: number, callback?: (err?: Error) => void): void;

interface WriteFileOptions {
  encoding?: string;
  mode?: number;
  flag?: string;
}

interface ReadFileOptions {
  encoding?: string;
  flag?: string;
}

File Operations

Directory Operations

Directory creation, listing, and removal operations with support for recursive operations and various output formats.

mkdirSync(path: string | Buffer, options?: MkdirOptions): void;
readdirSync(path: string | Buffer, options?: ReaddirOptions): string[] | Buffer[] | Dirent[];
rmdirSync(path: string | Buffer): void;
rmSync(path: string | Buffer, options?: RmOptions): void;
mkdtempSync(prefix: string, options?: MktempOptions): string;

mkdir(path: string | Buffer, options?: MkdirOptions, callback?: (err?: Error) => void): void;
readdir(path: string | Buffer, options?: ReaddirOptions, callback?: (err?: Error, files?: string[] | Buffer[] | Dirent[]) => void): void;

interface MkdirOptions {
  recursive?: boolean;
  mode?: number;
}

interface ReaddirOptions {
  encoding?: string;
  withFileTypes?: boolean;
}

interface RmOptions {
  recursive?: boolean;
  force?: boolean;
}

Directory Operations

File Descriptors

Low-level file descriptor operations for fine-grained control over file access, positioning, and data manipulation.

openSync(path: string | Buffer, flags: string | number, mode?: number): number;
closeSync(fd: number): void;
readSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number): number;
writeSync(fd: number, buffer: Buffer | string, offset?: number, length?: number | string, position?: number): number;
fstatSync(fd: number): Stats;
fchmodSync(fd: number, mode: number | string): void;
fsyncSync(fd: number): void;
fdatasyncSync(fd: number): void;

open(path: string | Buffer, flags: string | number, mode?: number, callback?: (err?: Error, fd?: number) => void): void;
close(fd: number, callback: (err?: Error) => void): void;
read(fd: number, buffer: Buffer, offset: number, length: number, position?: number, callback?: (err?: Error, bytesRead?: number) => void): void;
write(fd: number, buffer: Buffer | string, offset?: number, length?: number, position?: number, callback?: (err?: Error, bytesWritten?: number) => void): void;

File Descriptors

Symbolic Links

Symbolic link and hard link creation, reading, and path resolution with cross-platform support.

symlinkSync(target: string | Buffer, path: string | Buffer, type?: string): void;
readlinkSync(path: string | Buffer, options?: ReadlinkOptions): string | Buffer;
linkSync(existingPath: string | Buffer, newPath: string | Buffer): void;
realpathSync(path: string | Buffer): string;

symlink(target: string | Buffer, path: string | Buffer, type?: string, callback?: (err?: Error) => void): void;
readlink(path: string | Buffer, options?: ReadlinkOptions, callback?: (err?: Error, linkString?: string | Buffer) => void): void;
realpath(path: string | Buffer, callback: (err?: Error, resolvedPath?: string) => void): void;

interface ReadlinkOptions {
  encoding?: string;
}

Symbolic Links

Streams

Readable and writable stream implementations for efficient handling of large files with position control and event handling.

createReadStream(path: string | Buffer, options?: ReadStreamOptions): ReadStream;
createWriteStream(path: string | Buffer, options?: WriteStreamOptions): WriteStream;

interface ReadStreamOptions {
  flags?: string;
  encoding?: string;
  fd?: number;
  mode?: number;
  autoClose?: boolean;
  start?: number;
  end?: number;
  highWaterMark?: number;
}

interface WriteStreamOptions {
  flags?: string;
  encoding?: string;
  fd?: number;
  mode?: number;
  autoClose?: boolean;
  start?: number;
  emitClose?: boolean;
}

Streams

File Watching

File system monitoring capabilities with event-driven notifications for file and directory changes, supporting recursive watching.

watch(filename: string | Buffer, options?: WatchOptions, listener?: WatchListener): FSWatcher;

interface WatchOptions {
  encoding?: string;
  persistent?: boolean;
  recursive?: boolean;
}

type WatchListener = (eventType: 'rename' | 'change', filename?: string | Buffer) => void;

interface FSWatcher {
  close(): void;
  on(event: 'change', listener: WatchListener): this;
  on(event: 'error', listener: (error: Error) => void): this;
  on(event: 'close', listener: () => void): this;
}

File Watching

Stats and Permissions

File statistics, permission checking, and metadata operations with full compatibility for Node.js Stats objects.

statSync(path: string | Buffer): Stats;
lstatSync(path: string | Buffer): Stats;
chmodSync(path: string | Buffer, mode: number | string): void;
lchmodSync(path: string | Buffer, mode: number | string): void;
renameSync(oldPath: string | Buffer, newPath: string | Buffer): void;

stat(path: string | Buffer, callback: (err?: Error, stats?: Stats) => void): void;
lstat(path: string | Buffer, callback: (err?: Error, stats?: Stats) => void): void;
chmod(path: string | Buffer, mode: number | string, callback?: (err?: Error) => void): void;
rename(oldPath: string | Buffer, newPath: string | Buffer, callback?: (err?: Error) => void): void;

interface Stats {
  isFile(): boolean;
  isDirectory(): boolean;
  isSymbolicLink(): boolean;
  isBlockDevice(): boolean;
  isCharacterDevice(): boolean;
  isFIFO(): boolean;
  isSocket(): boolean;
  size: number;
  mode: number;
  uid: number;
  gid: number;
  // ... other stat properties
}

Stats and Permissions

Promise API

interface MemoryFs {
  promises: {
    writeFile(path: string | Buffer, data: string | Buffer, options?: WriteFileOptions): Promise<void>;
    readFile(path: string | Buffer, options?: ReadFileOptions): Promise<string | Buffer>;
    mkdir(path: string | Buffer, options?: MkdirOptions): Promise<void>;
    readdir(path: string | Buffer, options?: ReaddirOptions): Promise<string[] | Buffer[] | Dirent[]>;
    stat(path: string | Buffer): Promise<Stats>;
    lstat(path: string | Buffer): Promise<Stats>;
    access(path: string | Buffer, mode?: number): Promise<void>;
    unlink(path: string | Buffer): Promise<void>;
    copyFile(src: string | Buffer, dest: string | Buffer, flags?: number): Promise<void>;
    symlink(target: string | Buffer, path: string | Buffer, type?: string): Promise<void>;
    readlink(path: string | Buffer, options?: ReadlinkOptions): Promise<string | Buffer>;
    realpath(path: string | Buffer): Promise<string>;
    truncate(path: string | Buffer, len?: number): Promise<void>;
    chmod(path: string | Buffer, mode: number | string): Promise<void>;
    lchmod(path: string | Buffer, mode: number | string): Promise<void>;
    rename(oldPath: string | Buffer, newPath: string | Buffer): Promise<void>;
    open(path: string | Buffer, flags: string | number, mode?: number): Promise<number>;
    rmdir(path: string | Buffer): Promise<void>;
    utimes(path: string | Buffer, atime: number | Date, mtime: number | Date): Promise<void>;
    // ... other promise methods
  };
}

Constructor Options

interface MemoryFsOptions {
  /** Platform type for path handling */
  platform?: 'posix' | 'win32';
  /** Function to get current working directory for relative path resolution */
  cwd?: () => string;
}

class MemoryFs {
  constructor(options?: MemoryFsOptions);
  
  /** Reset filesystem to initial empty state */
  reset(): void;
  
  /** Node.js filesystem constants */
  constants: typeof constants;
  
  /** Dirent class for directory entries */
  Dirent: typeof Dirent;
}

Constants

interface FsConstants {
  // File access constants
  F_OK: number; // File existence
  R_OK: number; // Read permission
  W_OK: number; // Write permission  
  X_OK: number; // Execute permission
  
  // Copy file constants
  COPYFILE_EXCL: number; // Exclusive copy (fail if destination exists)
  COPYFILE_FICLONE: number; // Clone file
  
  // File mode constants
  S_IRUSR: number; // User read permission
  S_IWUSR: number; // User write permission
  S_IXUSR: number; // User execute permission
  S_IRGRP: number; // Group read permission
  S_IWGRP: number; // Group write permission
  S_IXGRP: number; // Group execute permission
  S_IROTH: number; // Other read permission
  S_IWOTH: number; // Other write permission
  S_IXOTH: number; // Other execute permission
  
  // File type constants
  S_IFMT: number;  // File type mask
  S_IFREG: number; // Regular file
  S_IFDIR: number; // Directory
  S_IFLNK: number; // Symbolic link
  // ... other constants
}

Error Handling

Metro Memory FS throws standard Node.js filesystem errors with appropriate error codes:

  • ENOENT - File or directory not found
  • EEXIST - File or directory already exists
  • EISDIR - Is a directory (when file expected)
  • ENOTDIR - Not a directory (when directory expected)
  • EPERM - Operation not permitted
  • EBADF - Bad file descriptor
  • EMFILE - Too many open files
  • ELOOP - Too many symbolic links
  • EINVAL - Invalid argument
  • ENOTEMPTY - Directory not empty
  • ENAMETOOLONG - Filename too long