Configurable file system abstraction with caching capabilities for performance optimization and custom file system support.
A caching layer for file system operations that improves resolution performance by caching file system calls.
/**
* File system with caching layer for improved performance
* @param fileSystem - Base file system implementation
* @param duration - Cache duration in milliseconds
*/
class CachedInputFileSystem {
constructor(fileSystem: BaseFileSystem, duration: number);
/** Base file system instance */
fileSystem: BaseFileSystem;
/** Cached file system methods */
stat: StatFunction;
statSync: StatSyncFunction;
readdir: ReaddirFunction;
readdirSync: ReaddirSyncFunction;
readFile: ReadFileFunction;
readFileSync: ReadFileSyncFunction;
readlink: ReadlinkFunction;
readlinkSync: ReadlinkSyncFunction;
/** Optional enhanced methods */
lstat?: LStatFunction;
lstatSync?: LStatSyncFunction;
realpath?: RealPathFunction;
realpathSync?: RealPathSyncFunction;
readJson?: ReadJsonFunction;
readJsonSync?: ReadJsonSyncFunction;
/**
* Purge items from cache
* @param what - Files/directories to purge (optional, purges all if not specified)
*/
purge(what?: string | string[] | Set<string>): void;
}Usage Examples:
const { CachedInputFileSystem } = require("enhanced-resolve");
const fs = require("fs");
// Create cached file system with 4 second cache duration
const cachedFs = new CachedInputFileSystem(fs, 4000);
// Use with resolver
const resolve = require("enhanced-resolve").create({
fileSystem: cachedFs,
extensions: [".js", ".json"]
});
// Purge cache for specific files
cachedFs.purge(["/path/to/file.js", "/path/to/dir"]);
// Purge entire cache
cachedFs.purge();Core file system interfaces that can be implemented for custom file systems.
/**
* Async file system interface
*/
interface FileSystem {
/** Read file contents */
readFile: (path: PathLike, callback: (err: Error | null, data?: Buffer) => void) => void;
/** Read directory contents */
readdir: (path: PathLike, callback: (err: Error | null, files?: string[]) => void) => void;
/** Read symbolic link */
readlink: (path: PathLike, callback: (err: Error | null, link?: string) => void) => void;
/** Get file stats */
stat: (path: PathLike, callback: (err: Error | null, stats?: Stats) => void) => void;
/** Get file stats without following symlinks */
lstat?: (path: PathLike, callback: (err: Error | null, stats?: Stats) => void) => void;
/** Resolve real path */
realpath?: (path: PathLike, callback: (err: Error | null, realPath?: string) => void) => void;
/** Read JSON file */
readJson?: (path: PathLike, callback: (err: Error | null, data?: JsonObject) => void) => void;
}
/**
* Sync file system interface
*/
interface SyncFileSystem {
/** Read file contents synchronously */
readFileSync: (path: PathLike) => Buffer;
/** Read directory contents synchronously */
readdirSync: (path: PathLike) => string[];
/** Read symbolic link synchronously */
readlinkSync: (path: PathLike) => string;
/** Get file stats synchronously */
statSync: (path: PathLike) => Stats;
/** Get file stats without following symlinks synchronously */
lstatSync?: (path: PathLike) => Stats;
/** Resolve real path synchronously */
realpathSync?: (path: PathLike) => string;
/** Read JSON file synchronously */
readJsonSync?: (path: PathLike) => JsonObject;
}
/**
* Combined sync and async file system
*/
type BaseFileSystem = FileSystem & SyncFileSystem;Decorator that wraps synchronous file systems to provide async interface.
/**
* Wraps synchronous file systems to provide async interface
*/
class SyncAsyncFileSystemDecorator {
constructor(syncFileSystem: SyncFileSystem);
/** Async methods created from sync counterparts */
readFile: (path: PathLike, callback: (err: Error | null, data?: Buffer) => void) => void;
readdir: (path: PathLike, callback: (err: Error | null, files?: string[]) => void) => void;
readlink: (path: PathLike, callback: (err: Error | null, link?: string) => void) => void;
stat: (path: PathLike, callback: (err: Error | null, stats?: Stats) => void) => void;
lstat?: (path: PathLike, callback: (err: Error | null, stats?: Stats) => void) => void;
realpath?: (path: PathLike, callback: (err: Error | null, realPath?: string) => void) => void;
}Usage Examples:
const { SyncAsyncFileSystemDecorator } = require("enhanced-resolve");
// Create a sync-only file system implementation
const syncFs = {
readFileSync: (path) => require("fs").readFileSync(path),
readdirSync: (path) => require("fs").readdirSync(path),
readlinkSync: (path) => require("fs").readlinkSync(path),
statSync: (path) => require("fs").statSync(path)
};
// Wrap it to provide async interface
const asyncFs = new SyncAsyncFileSystemDecorator(syncFs);
// Now can be used with async resolvers
const resolve = require("enhanced-resolve").create({
fileSystem: asyncFs,
extensions: [".js"]
});Creating a custom file system for testing or special use cases.
// Example: Memory-based file system for testing
class MemoryFileSystem {
constructor() {
this.files = new Map();
this.dirs = new Set();
}
writeFileSync(path, content) {
this.files.set(path, Buffer.from(content));
}
mkdirSync(path) {
this.dirs.add(path);
}
readFileSync(path) {
if (!this.files.has(path)) {
const error = new Error(`ENOENT: no such file '${path}'`);
error.code = "ENOENT";
throw error;
}
return this.files.get(path);
}
readdirSync(path) {
const entries = [];
for (const filePath of this.files.keys()) {
if (filePath.startsWith(path + "/")) {
const relative = filePath.slice(path.length + 1);
if (!relative.includes("/")) {
entries.push(relative);
}
}
}
return entries;
}
statSync(path) {
if (this.files.has(path)) {
return { isFile: () => true, isDirectory: () => false };
}
if (this.dirs.has(path)) {
return { isFile: () => false, isDirectory: () => true };
}
const error = new Error(`ENOENT: no such file or directory '${path}'`);
error.code = "ENOENT";
throw error;
}
readlinkSync(path) {
throw new Error("Symlinks not supported in memory filesystem");
}
}
// Use with enhanced-resolve
const memoryFs = new MemoryFileSystem();
memoryFs.writeFileSync("/virtual/index.js", "module.exports = 'test';");
const resolve = require("enhanced-resolve").create({
fileSystem: memoryFs,
extensions: [".js"]
});type PathLike = string | Buffer | URL;
interface Stats {
isFile(): boolean;
isDirectory(): boolean;
isSymbolicLink(): boolean;
size: number;
mtime: Date;
ctime: Date;
}
interface JsonObject {
[key: string]: any;
}
interface WriteOnlySet<T> {
add(item: T): void;
}