A memory-based implementation of Node.js fs module for testing purposes
Overall
score
96%
Symbolic link and hard link creation, reading, and path resolution with cross-platform support. Provides complete symlink functionality including link creation, target reading, and real path resolution.
Create symbolic links pointing to other files or directories.
/**
* Synchronously create a symbolic link
* @param target - Path that the symlink points to (can be relative or absolute)
* @param path - Path where the symlink will be created
* @param type - Link type (defaults to 'file', only 'file' is supported)
*/
symlinkSync(target: string | Buffer, path: string | Buffer, type?: string): void;
/**
* Asynchronously create a symbolic link
* @param target - Path that the symlink points to
* @param path - Path where the symlink will be created
* @param type - Link type (defaults to 'file')
* @param callback - Completion callback
*/
symlink(target: string | Buffer, path: string | Buffer, type?: string, callback?: (err?: Error) => void): void;
symlink(target: string | Buffer, path: string | Buffer, callback: (err?: Error) => void): void;Usage Examples:
// Create symlink to a file
fs.writeFileSync('/original.txt', 'Original content');
fs.symlinkSync('/original.txt', '/link-to-original.txt');
// Create symlink with relative target
fs.symlinkSync('../data/config.json', '/app/config.json');
// Create symlink to directory
fs.mkdirSync('/source-dir');
fs.symlinkSync('/source-dir', '/link-to-dir');
// Async symlink creation
fs.symlink('/target/file.txt', '/links/symlink.txt', (err) => {
if (!err) {
console.log('Symbolic link created');
}
});
// Promise-based symlink creation
await fs.promises.symlink('/source', '/destination-link');Read the target path of symbolic links.
/**
* Synchronously read the target of a symbolic link
* @param path - Path to the symbolic link
* @param options - Read options including encoding
* @returns Target path as string or Buffer
*/
readlinkSync(path: string | Buffer, options?: ReadlinkOptions): string | Buffer;
readlinkSync(path: string | Buffer, encoding: string): string | Buffer;
/**
* Asynchronously read the target of a symbolic link
* @param path - Path to the symbolic link
* @param options - Read options including encoding
* @param callback - Completion callback with target path
*/
readlink(path: string | Buffer, options?: ReadlinkOptions, callback?: (err?: Error, linkString?: string | Buffer) => void): void;
readlink(path: string | Buffer, encoding: string, callback: (err?: Error, linkString?: string | Buffer) => void): void;
readlink(path: string | Buffer, callback: (err?: Error, linkString?: string) => void): void;
interface ReadlinkOptions {
/** Encoding for returned path */
encoding?: string;
}Usage Examples:
// Create and read a symlink
fs.symlinkSync('/etc/config.conf', '/app/config.conf');
const target = fs.readlinkSync('/app/config.conf');
console.log('Symlink points to:', target); // '/etc/config.conf'
// Read with specific encoding
const targetBuffer = fs.readlinkSync('/app/config.conf', { encoding: 'buffer' });
console.log('Target as buffer:', targetBuffer);
// Read as UTF-8 string
const targetStr = fs.readlinkSync('/app/config.conf', 'utf8');
// Async readlink
fs.readlink('/app/config.conf', (err, target) => {
if (!err) {
console.log('Symlink target:', target);
}
});
// Promise-based readlink
const target = await fs.promises.readlink('/app/config.conf');Create hard links that reference the same file data.
/**
* Synchronously create a hard link
* @param existingPath - Path to existing file
* @param newPath - Path for the new hard link
*/
linkSync(existingPath: string | Buffer, newPath: string | Buffer): void;
/**
* Asynchronously create a hard link
* @param existingPath - Path to existing file
* @param newPath - Path for the new hard link
* @param callback - Completion callback
*/
link(existingPath: string | Buffer, newPath: string | Buffer, callback?: (err?: Error) => void): void;Usage Examples:
// Create original file
fs.writeFileSync('/original.txt', 'Shared content');
// Create hard link
fs.linkSync('/original.txt', '/hardlink.txt');
// Both files share the same content
console.log(fs.readFileSync('/original.txt', 'utf8')); // 'Shared content'
console.log(fs.readFileSync('/hardlink.txt', 'utf8')); // 'Shared content'
// Modifying one affects the other
fs.writeFileSync('/hardlink.txt', 'Modified content');
console.log(fs.readFileSync('/original.txt', 'utf8')); // 'Modified content'
// Async hard link creation
fs.link('/source.txt', '/another-link.txt', (err) => {
if (!err) {
console.log('Hard link created');
}
});
// Promise-based hard link
await fs.promises.link('/existing.txt', '/new-hardlink.txt');Resolve absolute paths by following symbolic links.
/**
* Synchronously resolve a path to its absolute real path
* @param path - Path to resolve (may contain symlinks)
* @returns Absolute real path with symlinks resolved
*/
realpathSync(path: string | Buffer): string;
/**
* Asynchronously resolve a path to its absolute real path
* @param path - Path to resolve (may contain symlinks)
* @param callback - Completion callback with resolved path
*/
realpath(path: string | Buffer, callback: (err?: Error, resolvedPath?: string) => void): void;
/**
* Native realpath implementation (same as realpath)
*/
realpathSync.native(path: string | Buffer): string;
realpath.native(path: string | Buffer, callback: (err?: Error, resolvedPath?: string) => void): void;Usage Examples:
// Create a chain of symlinks
fs.writeFileSync('/real-file.txt', 'content');
fs.symlinkSync('/real-file.txt', '/link1.txt');
fs.symlinkSync('/link1.txt', '/link2.txt');
// Resolve the real path
const realPath = fs.realpathSync('/link2.txt');
console.log(realPath); // '/real-file.txt'
// Resolve relative paths
fs.symlinkSync('../config/app.json', '/app/config.json');
const resolved = fs.realpathSync('/app/config.json');
console.log(resolved); // Absolute path to the actual file
// Async realpath
fs.realpath('/complex/symlink/path', (err, resolvedPath) => {
if (!err) {
console.log('Real path:', resolvedPath);
}
});
// Promise-based realpath
const realPath = await fs.promises.realpath('/symlink/chain');
// Use native implementation
const nativeRealPath = fs.realpathSync.native('/symlink');Detect symbolic links and get their statistics.
/**
* Get stats for a path without following symbolic links
* @param path - Path to get stats for
* @returns Stats object (symlinks return symlink stats, not target stats)
*/
lstatSync(path: string | Buffer): Stats;
/**
* Asynchronously get stats without following symbolic links
* @param path - Path to get stats for
* @param callback - Completion callback with stats
*/
lstat(path: string | Buffer, callback: (err?: Error, stats?: Stats) => void): void;
interface Stats {
/** Check if this is a symbolic link */
isSymbolicLink(): boolean;
/** Check if this is a regular file */
isFile(): boolean;
/** Check if this is a directory */
isDirectory(): boolean;
size: number;
mode: number;
// ... other properties
}Usage Examples:
// Create file and symlink
fs.writeFileSync('/target.txt', 'Hello World');
fs.symlinkSync('/target.txt', '/link.txt');
// Compare stat vs lstat
const fileStats = fs.statSync('/link.txt'); // Stats of target file
const linkStats = fs.lstatSync('/link.txt'); // Stats of symlink itself
console.log('File is symlink:', fileStats.isSymbolicLink()); // false
console.log('Link is symlink:', linkStats.isSymbolicLink()); // true
console.log('File size:', fileStats.size); // 11 (length of "Hello World")
console.log('Link size:', linkStats.size); // Length of target path string
// Check if path is a symlink
function isSymlink(path) {
try {
return fs.lstatSync(path).isSymbolicLink();
} catch (err) {
return false;
}
}
console.log('Is symlink:', isSymlink('/link.txt')); // true
// Async lstat
fs.lstat('/maybe-symlink.txt', (err, stats) => {
if (!err) {
if (stats.isSymbolicLink()) {
console.log('This is a symbolic link');
} else {
console.log('This is not a symbolic link');
}
}
});// Follow symlink chain manually
function followSymlinkChain(path, maxDepth = 10) {
const chain = [];
let current = path;
let depth = 0;
while (depth < maxDepth) {
chain.push(current);
try {
const stats = fs.lstatSync(current);
if (!stats.isSymbolicLink()) {
break; // Reached the end
}
current = fs.readlinkSync(current);
depth++;
} catch (err) {
break;
}
}
return chain;
}
// Create backup with hard link
function createBackupHardLink(originalPath, backupPath) {
try {
fs.linkSync(originalPath, backupPath);
console.log('Backup created with hard link');
} catch (err) {
// Fallback to copy if hard link fails
fs.copyFileSync(originalPath, backupPath);
console.log('Backup created with copy');
}
}
// Safe symlink creation (check if target exists)
function createSafeSymlink(target, linkPath) {
// Check if target exists
if (!fs.existsSync(target)) {
throw new Error(`Target does not exist: ${target}`);
}
// Remove existing link if present
if (fs.existsSync(linkPath)) {
const stats = fs.lstatSync(linkPath);
if (stats.isSymbolicLink()) {
fs.unlinkSync(linkPath);
} else {
throw new Error(`Cannot create symlink: ${linkPath} already exists and is not a symlink`);
}
}
fs.symlinkSync(target, linkPath);
}// Handle both Windows and POSIX paths in symlinks
function createCrossPlatformSymlink(target, linkPath) {
// Normalize path separators for the platform
const normalizedTarget = target.replace(/[/\\]/g, path.sep);
fs.symlinkSync(normalizedTarget, linkPath);
}
// Resolve symlinks with proper path handling
function resolveWithPlatformPaths(symlinkPath) {
const realPath = fs.realpathSync(symlinkPath);
return path.normalize(realPath);
}Common symbolic link errors:
ENOENT - Target file/directory doesn't exist (readlink, realpath)EEXIST - Link path already exists (symlink, link)EINVAL - Path is not a symbolic link (readlink)EPERM - Cannot create hard link to directoryELOOP - Too many symbolic links (realpath)ENOTDIR - Component in path is not a directoryInstall with Tessl CLI
npx tessl i tessl/npm-metro-memory-fsdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10