CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-resolve

Resolve like require.resolve() on behalf of files asynchronously and synchronously

Pending
Overview
Eval results
Files

async-resolution.mddocs/

Asynchronous Resolution

Core asynchronous module resolution functionality that implements the Node.js require.resolve() algorithm with extensive customization options for file system operations, path transformations, and package processing.

Capabilities

Resolve Function

Main asynchronous resolution function that resolves module path strings into absolute file paths.

/**
 * Asynchronously resolve module path string
 * @param {string} id - Module path string to resolve
 * @param {object} [options] - Resolution options
 * @param {function} callback - Callback function (err, res, pkg) => void
 */
function resolve(id, options, callback);
function resolve(id, callback);

Usage Examples:

const resolve = require('resolve');

// Basic resolution
resolve('lodash', { basedir: __dirname }, (err, res) => {
  if (err) throw err;
  console.log(res); // /path/to/node_modules/lodash/index.js
});

// Resolution with package info
resolve('express', { basedir: __dirname }, (err, res, pkg) => {
  if (err) throw err;
  console.log(res); // /path/to/node_modules/express/index.js  
  console.log(pkg); // { name: 'express', version: '4.18.2', ... }
});

// Relative path resolution
resolve('./utils/helper', { basedir: '/project/src' }, (err, res) => {
  if (err) throw err;
  console.log(res); // /project/src/utils/helper.js
});

Resolution Options

Basic Configuration

interface AsyncResolveOptions {
  /** Directory to begin resolving from (default: dirname of calling file) */
  basedir?: string;
  /** File extensions to search in order (default: ['.js']) */
  extensions?: string[];
  /** Include Node.js core modules in search (default: true) */
  includeCoreModules?: boolean;
  /** Don't resolve basedir to real path before resolving (default: true) */
  preserveSymlinks?: boolean;
  /** Directory names to search for modules (default: 'node_modules') */
  moduleDirectory?: string | string[];
}

File System Options

Custom file system operations for testing, virtualization, or alternative storage backends.

interface FileSystemOptions {
  /** Custom async file reading function */
  readFile?: (file: string, callback: (err: Error | null, data: Buffer | string) => void) => void;
  /** Custom async file existence test function */
  isFile?: (file: string, callback: (err: Error | null, exists: boolean) => void) => void;
  /** Custom async directory existence test function */
  isDirectory?: (dir: string, callback: (err: Error | null, exists: boolean) => void) => void;
  /** Custom async symlink resolution function */
  realpath?: (path: string, callback: (err: Error | null, realPath: string) => void) => void;
}

Usage Example:

const fs = require('fs');

resolve('custom-module', {
  basedir: __dirname,
  readFile: (file, cb) => {
    console.log('Reading:', file);
    fs.readFile(file, cb);
  },
  isFile: (file, cb) => {
    fs.stat(file, (err, stat) => {
      if (err) return cb(null, false);
      cb(null, stat.isFile());
    });
  }
}, (err, res) => {
  // Custom file system operations will be used during resolution
});

Package Processing Options

Transform package.json contents and handle custom package processing logic.

interface PackageOptions {
  /** package.json data applicable to module being loaded */
  package?: object;
  /** Custom async package.json reading function */
  readPackage?: ReadPackageFunction;
  /** Transform package.json contents before looking at main field */
  packageFilter?: (pkg: object, pkgfile: string, dir: string) => object;
  /** Transform paths within packages */
  pathFilter?: (pkg: object, path: string, relativePath: string) => string;
  /** Custom package candidate path iterator */
  packageIterator?: PackageIteratorFunction;
}

/**
 * Custom package.json reading function
 */
interface ReadPackageFunction {
  (readFile: Function, pkgfile: string, callback: (err: Error | null, pkg?: object) => void): void;
}

/**
 * Custom package candidate path iterator
 */
interface PackageIteratorFunction {
  (request: string, start: string, getPackageCandidates: () => string[], opts: AsyncResolveOptions): string[];
}

Usage Example:

resolve('my-package', {
  basedir: __dirname,
  packageFilter: (pkg, pkgfile, dir) => {
    // Transform package.json before resolution
    if (pkg.name === 'my-package') {
      pkg.main = 'dist/index.js'; // Override main field
    }
    return pkg;
  },
  pathFilter: (pkg, path, relativePath) => {
    // Transform resolved paths
    if (pkg.name === 'my-package' && path.endsWith('.js')) {
      return path.replace('.js', '.min.js');
    }
    return path;
  }
}, (err, res) => {
  // Resolution will use transformed package data
});

Path Resolution Options

Control module search paths and path resolution behavior.

interface PathOptions {
  /** Custom require.paths array or function for path resolution */
  paths?: string[] | PathsFunction;
}

/**
 * Function for custom path resolution logic
 */
interface PathsFunction {
  (request: string, start: string, getNodeModulesDirs: () => string[], opts: AsyncResolveOptions): string[];
}

Usage Example:

resolve('custom-lib', {
  basedir: __dirname,
  paths: (request, start, getNodeModulesDirs, opts) => {
    const standardPaths = getNodeModulesDirs();
    // Add custom search paths
    return ['/custom/modules', ...standardPaths];
  }
}, (err, res) => {
  // Will search in custom paths in addition to standard locations
});

Error Handling

Error Types

interface ResolveError extends Error {
  /** Error code indicating the type of resolution failure */
  code: 'MODULE_NOT_FOUND' | 'INVALID_PACKAGE_MAIN';
  /** Original error message */
  message: string;
}

Error Scenarios

MODULE_NOT_FOUND: The specified module path could not be resolved after exhausting all search paths.

resolve('nonexistent-module', { basedir: __dirname }, (err, res) => {
  if (err && err.code === 'MODULE_NOT_FOUND') {
    console.error('Module not found:', err.message);
    // "Cannot find module 'nonexistent-module' from '/current/directory'"
  }
});

INVALID_PACKAGE_MAIN: A package.json was encountered with an invalid main property.

// This can occur if a package.json has main: 123 instead of main: "index.js"
resolve('broken-package', { basedir: __dirname }, (err, res) => {
  if (err && err.code === 'INVALID_PACKAGE_MAIN') {
    console.error('Invalid package main:', err.message);
    // 'package "broken-package" `main` must be a string'
  }
});

Install with Tessl CLI

npx tessl i tessl/npm-resolve

docs

async-resolution.md

cli.md

core-modules.md

index.md

sync-resolution.md

tile.json