CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-enhanced-resolve

Highly configurable async require.resolve function with extensive customization options for module resolution

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

file-system.mddocs/

File System Integration

Configurable file system abstraction with caching capabilities for performance optimization and custom file system support.

Capabilities

CachedInputFileSystem

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();

File System Interfaces

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;

SyncAsyncFileSystemDecorator

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"]
});

Custom File System Example

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"]
});

Types

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;
}

Install with Tessl CLI

npx tessl i tessl/npm-enhanced-resolve

docs

core-resolution.md

file-system.md

index.md

modern-features.md

plugin-system.md

resolver-factory.md

tile.json