CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-metro-resolver

Implementation of Metro's resolution logic for JavaScript modules, assets, and packages within React Native and Metro bundler projects.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

resolution-context.mddocs/

Resolution Context

The ResolutionContext provides all the configuration settings, file system operations, and helper functions needed for module resolution. It serves as the central configuration object that controls how the resolver behaves.

Capabilities

ResolutionContext Interface

The main configuration interface for the resolver.

interface ResolutionContext {
  /** Whether to allow Haste module resolution */
  readonly allowHaste: boolean;
  
  /** File extensions considered as assets */
  readonly assetExts: ReadonlyArray<string>;
  
  /** File extensions considered as source files */
  readonly sourceExts: ReadonlyArray<string>;
  
  /** Options passed to custom resolvers */
  readonly customResolverOptions: CustomResolverOptions;
  
  /** Whether to disable hierarchical node_modules lookup */
  readonly disableHierarchicalLookup: boolean;
  
  /** Function to check if a file exists (deprecated, prefer fileSystemLookup) */
  readonly doesFileExist: DoesFileExist;
  
  /** Additional node_modules paths for resolution */
  readonly extraNodeModules?: { [key: string]: string };
  
  /** Function to perform file system lookups */
  readonly fileSystemLookup: FileSystemLookup;
  
  /** Function to parse package.json files */
  readonly getPackage: (packageJsonPath: string) => PackageJson | null;
  
  /** Function to get package info for a module path (deprecated) */
  readonly getPackageForModule: (absoluteModulePath: string) => PackageForModule | null;
  
  /** Dependency descriptor for diagnostic purposes */
  readonly dependency?: any;
  
  /** Whether the dependency was declared with ESM import syntax */
  readonly isESMImport?: boolean;
  
  /** Ordered list of package.json fields to check for main entry point */
  readonly mainFields: ReadonlyArray<string>;
  
  /** Path of the module requesting the resolution */
  readonly originModulePath: string;
  
  /** Global node_modules paths to search */
  readonly nodeModulesPaths: ReadonlyArray<string>;
  
  /** Whether to prefer .native files over platform-specific files */
  readonly preferNativePlatform: boolean;
  
  /** Function to resolve asset files */
  readonly resolveAsset: ResolveAsset;
  
  /** Function to redirect module paths */
  readonly redirectModulePath: (modulePath: string) => string | false;
  
  /** Function to resolve Haste modules */
  readonly resolveHasteModule: (name: string) => string | undefined;
  
  /** Function to resolve Haste packages */
  readonly resolveHastePackage: (name: string) => string | undefined;
  
  /** Custom resolver function */
  readonly resolveRequest?: CustomResolver;
  
  /** Condition names for package exports resolution */
  unstable_conditionNames: ReadonlyArray<string>;
  
  /** Platform-specific condition names */
  unstable_conditionsByPlatform: Readonly<{ [platform: string]: ReadonlyArray<string> }>;
  
  /** Whether to enable package.json exports field support */
  unstable_enablePackageExports: boolean;
  
  /** Function to log warnings */
  unstable_logWarning: (message: string) => void;
}

Helper Function Types

Functions that integrate with the file system and package resolution.

/** Check if a file exists at the given path */
type DoesFileExist = (filePath: string) => boolean;

/** Perform file system lookup with type information */
type FileSystemLookup = (
  absoluteOrProjectRelativePath: string
) => { exists: false } | { exists: true; type: 'f' | 'd'; realPath: string };

/** Resolve asset files in a directory */
type ResolveAsset = (
  dirPath: string,
  assetName: string,
  extension: string
) => ReadonlyArray<string> | undefined;

Custom Resolver Options

Configuration options for custom resolvers.

type CustomResolverOptions = Readonly<{
  [option: string]: unknown;
}>;

Creating Default Context

Helper function to create a ResolutionContext with default settings.

/**
 * Helper function to create a ResolutionContext with default values
 * @param context - Partial context with custom overrides
 * @param dependency - Dependency information for diagnostics
 * @returns Complete ResolutionContext
 */
function createDefaultContext(
  context: Partial<ResolutionContext>,
  dependency: any
): ResolutionContext;

Usage Examples:

const { createDefaultContext } = require("metro-resolver");

// Create context with common settings
const context = createDefaultContext({
  allowHaste: false,
  assetExts: ['png', 'jpg', 'gif', 'webp'],
  sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json'],
  mainFields: ['browser', 'main', 'module'],
  originModulePath: '/app/src/index.js',
  nodeModulesPaths: ['/app/node_modules'],
  fileSystemLookup: (path) => {
    const fs = require('fs');
    try {
      const stats = fs.lstatSync(path);
      return {
        exists: true,
        type: stats.isDirectory() ? 'd' : 'f',
        realPath: fs.realpathSync(path)
      };
    } catch {
      return { exists: false };
    }
  },
  getPackage: (packagePath) => {
    try {
      return require(packagePath);
    } catch {
      return null;
    }
  },
  resolveAsset: (dirPath, name, ext) => {
    // Custom asset resolution logic
    return [`${dirPath}/${name}${ext}`];
  },
  unstable_enablePackageExports: true,
  unstable_logWarning: console.warn
}, null);

File System Integration

The context provides abstracted file system operations for flexibility.

interface FileSystemLookupResult {
  exists: boolean;
  type?: 'f' | 'd';
  realPath?: string;
}

Usage Example:

const context = {
  // ... other config
  fileSystemLookup: (path) => {
    const fs = require('fs');
    try {
      const stats = fs.lstatSync(path);
      return {
        exists: true,
        type: stats.isDirectory() ? 'd' : 'f',
        realPath: fs.realpathSync(path)
      };
    } catch (error) {
      return { exists: false };
    }
  }
};

Package Integration

Functions for working with package.json files and package structure.

interface PackageJson {
  readonly name?: string;
  readonly main?: string;
  readonly exports?: string | ExportMap;
  readonly imports?: ExportMap;
  readonly browser?: string | { [key: string]: string | false };
  readonly module?: string;
}

interface PackageInfo {
  readonly packageJson: PackageJson;
  readonly rootPath: string;
}

interface PackageForModule extends PackageInfo {
  readonly packageRelativePath: string;
}

Main Fields Configuration

Controls the order of package.json fields checked for entry points.

Common Configurations:

// Browser-first (for web bundling)
mainFields: ['browser', 'module', 'main']

// Node.js-first
mainFields: ['main', 'module']

// React Native
mainFields: ['react-native', 'browser', 'main']

Platform-Specific Configuration

Settings for handling platform-specific resolution.

interface PlatformConfiguration {
  /** Whether to prefer .native files over platform-specific files */
  preferNativePlatform: boolean;
  
  /** Condition names for exports resolution */
  unstable_conditionNames: ReadonlyArray<string>;
  
  /** Platform-specific condition names */
  unstable_conditionsByPlatform: Readonly<{ [platform: string]: ReadonlyArray<string> }>;
}

Usage Example:

const context = {
  // ... other config
  preferNativePlatform: true,
  unstable_conditionNames: ['import', 'require'],
  unstable_conditionsByPlatform: {
    ios: ['react-native', 'ios', 'native', 'import'],
    android: ['react-native', 'android', 'native', 'import'],
    web: ['browser', 'import']
  }
};

Haste Configuration

Settings for Haste module system integration.

interface HasteConfiguration {
  /** Whether to allow Haste module resolution */
  allowHaste: boolean;
  
  /** Function to resolve Haste modules by name */
  resolveHasteModule: (name: string) => string | undefined;
  
  /** Function to resolve Haste packages by name */
  resolveHastePackage: (name: string) => string | undefined;
}

Asset Configuration

Settings for asset file resolution.

interface AssetConfiguration {
  /** File extensions considered as assets */
  assetExts: ReadonlyArray<string>;
  
  /** Function to resolve asset files */
  resolveAsset: ResolveAsset;
}

Common Asset Extensions:

assetExts: [
  'png', 'jpg', 'jpeg', 'gif', 'webp', 'svg',
  'mp4', 'webm', 'wav', 'mp3', 'm4a', 'aac',
  'otf', 'ttf', 'woff', 'woff2'
]

docs

asset-resolution.md

custom-resolvers.md

error-handling.md

index.md

package-resolution.md

resolution-context.md

resolution-engine.md

tile.json