CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-metro-transform-worker

Transform worker for Metro bundler that handles JavaScript, TypeScript, JSX, JSON, and asset transformations through a comprehensive Babel-based pipeline.

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

error-handling.mddocs/

Error Handling

Metro Transform Worker provides comprehensive error handling with detailed context and debugging information for transformation failures.

Capabilities

Invalid Require Call Errors

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}`);
  }
}

Common Error Scenarios

Invalid Require Syntax

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");

Reserved String Conflicts

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]}`);
  }
}

Minification Errors

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 Errors

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}`);
  }
}

Error Context and Debugging

File Context

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;
}

Stack Trace Preservation

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 stack

Configuration Debugging

When 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}`
  );
}

Error Recovery Strategies

Graceful Degradation

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}`);
}

Partial Success Handling

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>;
}

Error Reporting Best Practices

Structured Error Information

// 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);
}

Development vs Production Error Handling

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}`);
}

Integration with Metro Error Handling

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);
      }
    },
  },
};

Common Solutions

Fixing Invalid Require Calls

// 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;

Resolving Reserved String Conflicts

// 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

Handling Minification Issues

// Before: Syntax that confuses minifier
eval("some code"); // May fail minification

// After: Avoid problematic constructs
const result = safeEvalAlternative("some code");

docs

cache-management.md

configuration.md

core-transformation.md

error-handling.md

index.md

tile.json