CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-metro-config

Config parser and resolver for Metro bundler with support for loading, merging, and validating configuration files.

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

config-loading.mddocs/

Configuration Loading

Load Metro configuration from files with automatic discovery, multiple format support, and CLI argument integration.

Capabilities

Load Configuration

Loads Metro configuration from the file system with automatic discovery and validation.

/**
 * Loads Metro configuration from various sources with automatic discovery
 * @param argvInput - CLI arguments and configuration options (optional)
 * @param defaultConfigOverrides - Base config overrides (optional)
 * @returns Promise resolving to complete Metro configuration
 */
function loadConfig(
  argvInput?: YargArguments,
  defaultConfigOverrides?: InputConfigT
): Promise<ConfigT>;

Usage Examples:

import { loadConfig } from "metro-config";

// Auto-discover config file in current directory
const config = await loadConfig();

// Load from specific config file
const config = await loadConfig({
  config: './metro.config.js'
});

// Override with CLI arguments
const config = await loadConfig({
  config: './metro.config.js',
  port: 3000,
  projectRoot: './src',
  resetCache: true
});

// With workspace configuration
const config = await loadConfig({
  cwd: './packages/mobile',
  watchFolders: ['./packages/shared']
});

// With default config overrides
const config = await loadConfig(
  { config: './metro.config.js' },
  { 
    resolver: { sourceExts: ['js', 'jsx', 'ts', 'tsx'] },
    server: { port: 3000 }
  }
);

Resolve Configuration

Finds and loads configuration files from the file system with search hierarchy.

/**
 * Resolves configuration file path and loads the config
 * @param filePath - Explicit path to config file (optional)
 * @param cwd - Current working directory for search (optional)
 * @returns Promise resolving to config resolution result
 */
function resolveConfig(filePath?: string, cwd?: string): Promise<ResolveConfigResult>;

interface ResolveConfigResult {
  /** Absolute path to the resolved config file */
  filepath: string;
  /** Whether the config is empty (no file found) */
  isEmpty: boolean;
  /** The loaded configuration object or function */
  config: (ConfigT => Promise<ConfigT>) | (ConfigT => ConfigT) | InputConfigT;
}

type ResolveConfigResult = $ReadOnly<{
  filepath: string,
  isEmpty: boolean,
  config: (ConfigT => Promise<ConfigT>) | (ConfigT => ConfigT) | InputConfigT,
}>;

Usage Examples:

import { resolveConfig } from "metro-config";

// Auto-discover config file
const result = await resolveConfig();
if (!result.isEmpty) {
  console.log(`Found config at: ${result.filepath}`);
}

// Search from specific directory
const result = await resolveConfig(undefined, './packages/mobile');

// Load specific file
const result = await resolveConfig('./custom-metro.config.js');

Load Configuration File

Directly loads a configuration file from a specific absolute path.

/**
 * Loads a configuration file from an absolute path
 * @param absolutePath - Absolute path to the config file
 * @returns Promise resolving to config resolution result
 */
function loadConfigFile(absolutePath: string): Promise<ResolveConfigResult>;

Usage Examples:

import { loadConfigFile } from "metro-config";

// Load specific config file
const result = await loadConfigFile('/absolute/path/to/metro.config.js');

// Check if config was loaded successfully
if (!result.isEmpty) {
  console.log(`Loaded config from: ${result.filepath}`);
  
  // Handle function vs object config
  if (typeof result.config === 'function') {
    console.log('Config is a function that will receive default config');
  } else {
    console.log('Config is a static object');
  }
}

Configuration File Discovery

Metro Config searches for configuration files in the following order:

Supported File Names

  1. JavaScript/JSON files:

    • metro.config.js
    • metro.config.cjs
    • metro.config.mjs
    • metro.config.json
  2. TypeScript files:

    • metro.config.ts
    • metro.config.cts
    • metro.config.mts
  3. Config directory:

    • .config/metro.js
    • .config/metro.cjs
    • .config/metro.mjs
    • .config/metro.json
    • .config/metro.ts
    • .config/metro.cts
    • .config/metro.mts
  4. Package.json:

    • package.json (using "metro" property)

Search Hierarchy

  1. Explicit file path (if provided)
  2. Current working directory
  3. Parent directories (walking up the file system)
  4. User home directory

Configuration Formats

JavaScript Export (recommended):

// metro.config.js
module.exports = {
  resolver: {
    sourceExts: ['js', 'jsx', 'ts', 'tsx']
  },
  server: {
    port: 8081
  }
};

JavaScript Function:

// metro.config.js
module.exports = async (defaultConfig) => {
  return {
    ...defaultConfig,
    resolver: {
      ...defaultConfig.resolver,
      sourceExts: [...defaultConfig.resolver.sourceExts, 'svg']
    }
  };
};

TypeScript:

// metro.config.ts
import type { ConfigT } from 'metro-config';

const config: ConfigT = {
  resolver: {
    sourceExts: ['js', 'jsx', 'ts', 'tsx']
  }
};

export default config;

Package.json:

{
  "metro": {
    "resolver": {
      "sourceExts": ["js", "jsx", "ts", "tsx"]
    }
  }
}

CLI Arguments Integration

Supported CLI Arguments

type YargArguments = $ReadOnly<{
  /** Path to configuration file */
  config?: string,
  /** Current working directory */
  cwd?: string,
  /** Development server port */
  port?: string | number,
  /** Development server host */
  host?: string,
  /** Project root directory */
  projectRoot?: string,
  /** Additional watch folders */
  watchFolders?: Array<string>,
  /** Asset file extensions */
  assetExts?: Array<string>,
  /** Source file extensions */
  sourceExts?: Array<string>,
  /** Supported platforms */
  platforms?: Array<string>,
  /** Maximum worker processes */
  'max-workers'?: string | number,
  maxWorkers?: string | number,
  /** Transformer module path */
  transformer?: string,
  /** Reset Metro cache */
  'reset-cache'?: boolean,
  resetCache?: boolean,
  /** Verbose logging */
  verbose?: boolean,
}>;

Usage Examples:

// Override configuration with CLI arguments
const config = await loadConfig({
  config: './metro.config.js',
  port: 3000,
  resetCache: true,
  maxWorkers: 4,
  watchFolders: ['./packages/shared', './packages/common'],
  sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json']
});

Error Handling

Configuration loading includes comprehensive error handling:

import { loadConfig } from "metro-config";

try {
  const config = await loadConfig({
    config: './invalid-config.js'
  });
} catch (error) {
  if (error.code === 'MODULE_NOT_FOUND') {
    console.error('Configuration file not found');
  } else if (error.name === 'ValidationError') {
    console.error('Invalid configuration:', error.message);
  } else {
    console.error('Configuration loading failed:', error);
  }
}

Configuration Validation

All loaded configurations are validated using Jest's validation system:

  • Schema validation: Ensures all configuration properties are valid
  • Type checking: Validates property types and structure
  • Warning system: Provides helpful warnings for deprecated options
  • Error reporting: Clear error messages for invalid configurations

docs

config-loading.md

config-merging.md

default-config.md

index.md

tile.json