Transform worker for Metro bundler that handles JavaScript, TypeScript, JSX, JSON, and asset transformations through a comprehensive Babel-based pipeline.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Metro Transform Worker provides comprehensive error handling with detailed context and debugging information for transformation failures.
Specialized error handling for malformed require() calls detected during dependency analysis.
class InvalidRequireCallError extends Error {
/** Original error from Metro's dependency collection system */
innerError: InternalInvalidRequireCallError;
/** File path where the invalid require call was found */
filename: string;
/**
* Creates an error for invalid require() call syntax
* @param innerError - Original error from dependency analysis
* @param filename - File containing the invalid require call
*/
constructor(innerError: InternalInvalidRequireCallError, filename: string);
}Usage Examples:
const { transform } = require("metro-transform-worker");
try {
const result = await transform(config, projectRoot, filename, data, options);
} catch (error) {
if (error instanceof InvalidRequireCallError) {
console.error(`Invalid require call in ${error.filename}`);
console.error(`Details: ${error.innerError.message}`);
console.error(`Location: Line ${error.innerError.line}, Column ${error.innerError.column}`);
}
}Metro Transform Worker detects and reports various invalid require() call patterns:
// Invalid: Dynamic require with non-literal argument
const moduleName = "some-module";
require(moduleName); // Throws InvalidRequireCallError
// Invalid: Computed property access in require
require("module")[computedProperty]; // Throws InvalidRequireCallError
// Invalid: Require in unsupported context
if (condition) {
require("conditional-module"); // May throw depending on config
}
// Valid: Static require calls
require("some-module");
const { method } = require("some-module");Metro reserves certain strings for internal use and validates source code doesn't contain them:
// Reserved strings that trigger SyntaxError:
const reservedStrings = [
"_$$_METRO_MODULE_ID", // Used when unstable_staticHermesOptimizedRequire is enabled
// Custom dependency map name from config.unstable_dependencyMapReservedName
];Error handling:
try {
const result = await transform(config, projectRoot, filename, data, options);
} catch (error) {
if (error instanceof SyntaxError && error.message.includes("reserved string")) {
console.error("Source code contains reserved Metro string");
console.error(`String: ${error.message.match(/`([^`]+)`/)[1]}`);
console.error(`Position: ${error.message.match(/character offset (\d+)/)[1]}`);
}
}Detailed error reporting for minification failures with file context:
// Minification error handling
try {
const result = await transform(config, projectRoot, filename, data, {
...options,
minify: true,
});
} catch (error) {
if (error.constructor.name === "JS_Parse_Error") {
// Terser/minifier syntax error with enhanced context
console.error(`Minification failed in ${filename}`);
console.error(`Error: ${error.message}`);
console.error(`Location: Line ${error.line}, Column ${error.col}`);
}
}Babel transformation failures are propagated with original error context:
try {
const result = await transform(config, projectRoot, filename, data, options);
} catch (error) {
if (error.name === "SyntaxError" && error.loc) {
console.error(`Babel transformation failed in ${filename}`);
console.error(`Error: ${error.message}`);
console.error(`Location: Line ${error.loc.line}, Column ${error.loc.column}`);
}
}All transformation errors include comprehensive file context:
interface ErrorContext {
/** Original filename being transformed */
filename: string;
/** Project root directory */
projectRoot: string;
/** Transformation configuration */
config: JsTransformerConfig;
/** Transform options that led to error */
options: JsTransformOptions;
}Metro Transform Worker preserves original error stack traces while adding context:
// Original error from Babel or minifier
const originalError = new SyntaxError("Unexpected token");
originalError.line = 42;
originalError.column = 15;
// Enhanced error with file context
const enhancedError = new Error(
`${originalError.message} in file ${filename} at ${originalError.line}:${originalError.column}`
);
enhancedError.stack = originalError.stack; // Preserve original stackWhen errors occur due to configuration issues:
// Configuration validation errors
try {
const minifier = getMinifier(config.minifierPath);
} catch (error) {
throw new Error(
`A problem occurred while trying to fetch the minifier. ` +
`Path: "${config.minifierPath}", error message: ${error.message}`
);
}Metro Transform Worker attempts graceful degradation for non-critical failures:
// Optional feature failures don't crash entire transformation
try {
// Apply optimization plugins
applyOptimizations(ast, config);
} catch (optimizationError) {
// Continue without optimizations
console.warn(`Optimization failed: ${optimizationError.message}`);
}Some transformations can succeed partially:
interface PartialTransformResult {
/** Successfully transformed output (may be incomplete) */
output: ReadonlyArray<JsOutput>;
/** Dependencies that were successfully extracted */
dependencies: ReadonlyArray<TransformResultDependency>;
/** Non-fatal warnings and issues */
warnings: ReadonlyArray<string>;
}// Comprehensive error reporting
function handleTransformError(error, context) {
const errorReport = {
type: error.constructor.name,
message: error.message,
filename: context.filename,
location: error.loc || { line: error.line, column: error.column },
transformOptions: context.options,
configHash: getCacheKey(context.config),
stack: error.stack,
};
console.error("Transform Error:", JSON.stringify(errorReport, null, 2));
// Report to error tracking service
reportError(errorReport);
}if (options.dev) {
// Development: Detailed error information
throw new Error(`
Transformation failed: ${error.message}
File: ${filename}
Line: ${error.line}, Column: ${error.column}
Config: ${JSON.stringify(config, null, 2)}
Stack: ${error.stack}
`);
} else {
// Production: Concise error without sensitive information
throw new Error(`Transformation failed in ${path.basename(filename)}: ${error.message}`);
}Metro Transform Worker errors integrate with Metro's error reporting system:
// Metro configuration for error handling
const metroConfig = {
transformer: {
// Transform worker will throw errors that Metro catches and reports
getTransformOptions: () => transformOptions,
},
reporter: {
// Custom reporter can handle transform worker errors
update: (event) => {
if (event.type === "transform_failed") {
handleTransformError(event.error, event.context);
}
},
},
};// Before: Dynamic require (will fail)
const moduleName = getModuleName();
require(moduleName);
// After: Static require with conditional logic
const moduleA = require("module-a");
const moduleB = require("module-b");
const selectedModule = condition ? moduleA : moduleB;// Before: Code contains reserved string
const _$$_METRO_MODULE_ID = "my-id"; // Will fail
// After: Use different variable name
const MY_MODULE_ID = "my-id"; // Will succeed// Before: Syntax that confuses minifier
eval("some code"); // May fail minification
// After: Avoid problematic constructs
const result = safeEvalAlternative("some code");