Config parser and resolver for Metro bundler with support for loading, merging, and validating configuration files.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Load Metro configuration from files with automatic discovery, multiple format support, and CLI argument integration.
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 }
}
);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');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');
}
}Metro Config searches for configuration files in the following order:
JavaScript/JSON files:
metro.config.jsmetro.config.cjsmetro.config.mjsmetro.config.jsonTypeScript files:
metro.config.tsmetro.config.ctsmetro.config.mtsConfig directory:
.config/metro.js.config/metro.cjs.config/metro.mjs.config/metro.json.config/metro.ts.config/metro.cts.config/metro.mtsPackage.json:
package.json (using "metro" property)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"]
}
}
}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']
});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);
}
}All loaded configurations are validated using Jest's validation system: