or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-interpret

A dictionary of file extensions and associated module loaders for automatic transpiler registration.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/interpret@3.1.x

To install, run

npx @tessl/cli install tessl/npm-interpret@3.1.0

index.mddocs/

Interpret

Interpret is a comprehensive dictionary of file extensions and their associated module loaders, enabling automatic registration of transpilers and compilers for various JavaScript variants and other file types. It provides mapping from file extensions to the appropriate Node.js require.extensions loaders for seamless transpilation support.

Package Information

  • Package Name: interpret
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install interpret

Core Imports

const { extensions, jsVariants } = require('interpret');

For ESM (requires transpilation):

import { extensions, jsVariants } from 'interpret';

Basic Usage

const interpret = require('interpret');

// Check if a file extension has a loader
const tsLoader = interpret.extensions['.ts'];
console.log(tsLoader); // Array of loader options for TypeScript

// Get only JavaScript variant extensions
const jsOnlyLoaders = interpret.jsVariants;
console.log(jsOnlyLoaders['.jsx']); // Loader options for JSX files

// Implementation pattern for using loaders
function registerLoader(extension) {
  const loader = interpret.extensions[extension];
  
  if (!loader) {
    console.log('No loader for', extension);
    return;
  }
  
  if (loader === null) {
    // Use default Node.js loader
    return;
  }
  
  if (typeof loader === 'string') {
    // Simple module name
    require(loader);
  } else if (Array.isArray(loader)) {
    // Try each loader until one works
    for (const option of loader) {
      try {
        if (typeof option === 'string') {
          require(option);
          break;
        } else if (option.module) {
          const hook = require(option.module);
          if (option.register) {
            option.register(hook);
          }
          break;
        }
      } catch (err) {
        // Try next option
      }
    }
  } else if (loader.module) {
    // Object with module and register function
    const hook = require(loader.module);
    if (loader.register) {
      loader.register(hook);
    }
  }
}

Capabilities

Extensions Dictionary

Complete mapping of file extensions to their associated module loaders.

/**
 * Dictionary mapping file extensions to loader configurations
 * @type {Object<string, LoaderConfig>}
 */
const extensions: {
  [extension: string]: LoaderConfig;
};

/**
 * Loader configuration can be:
 * - null: Use default Node.js loader
 * - string: Module name to require
 * - LoaderObject: Module with custom registration
 * - LoaderConfig[]: Array of fallback options
 */
type LoaderConfig = null | string | LoaderObject | LoaderConfig[];

/**
 * Loader object with module and custom registration function
 */
interface LoaderObject {
  /** Module name to require */
  module: string;
  /** Custom registration function */
  register: (hook: any, config?: any) => void;
}

JavaScript Variants Dictionary

Subset of extensions containing only JavaScript-related file types.

/**
 * Dictionary of JavaScript variant extensions and their loaders
 * Same structure as extensions but filtered to JS-related types only
 * @type {Object<string, LoaderConfig>}
 */
const jsVariants: {
  [extension: string]: LoaderConfig;
};

Supported Extensions

JavaScript Variants (jsVariants)

Extensions included in the jsVariants object for JavaScript and JavaScript-like languages:

// Native Node.js loaders
'.js': null,
'.cjs': 'interpret/cjs-stub',
'.mjs': 'interpret/mjs-stub',

// JSX support  
'.jsx': [
  {
    module: '@babel/register',
    register: (hook, config) => void
  },
  'sucrase/register/jsx'
],

// TypeScript support
'.ts': [
  'ts-node/register',
  'sucrase/register/ts',
  {
    module: '@babel/register',
    register: (hook, config) => void
  },
  {
    module: 'esbuild-register/dist/node',
    register: (mod, config) => void
  },
  {
    module: '@swc/register',
    register: (hook, config) => void
  }
],

'.tsx': [
  'ts-node/register',
  'sucrase/register/tsx',
  {
    module: '@babel/register',
    register: (hook, config) => void
  },
  {
    module: 'esbuild-register/dist/node',
    register: (mod, config) => void
  },
  {
    module: '@swc/register',
    register: (hook, config) => void
  }
],

// CoffeeScript support
'.coffee': 'coffeescript/register',
'.coffee.md': 'coffeescript/register',
'.litcoffee': 'coffeescript/register',

// ESM support
'.esm.js': {
  module: 'esm',
  register: (hook) => void
},

// MDX support
'.mdx': '@mdx-js/register'

Transpiler-Specific Extensions

Extensions that target specific transpilers:

// Babel-specific extensions
'.babel.js': {
  module: '@babel/register',
  register: (hook, config) => void
},
'.babel.jsx': {
  module: '@babel/register',
  register: (hook, config) => void
},
'.babel.ts': [{
  module: '@babel/register',
  register: (hook, config) => void
}],
'.babel.tsx': {
  module: '@babel/register',
  register: (hook, config) => void
},

// ESBuild-specific extensions
'.esbuild.js': {
  module: 'esbuild-register/dist/node',
  register: (mod, config) => void
},
'.esbuild.jsx': {
  module: 'esbuild-register/dist/node',
  register: (mod, config) => void
},
'.esbuild.ts': {
  module: 'esbuild-register/dist/node',
  register: (mod, config) => void
},
'.esbuild.tsx': {
  module: 'esbuild-register/dist/node',
  register: (mod, config) => void
},

// Sucrase-specific extensions
'.sucrase.js': {
  module: 'sucrase/dist/register',
  register: (hook, config) => void
},
'.sucrase.jsx': {
  module: 'sucrase/dist/register',
  register: (hook, config) => void
},
'.sucrase.ts': {
  module: 'sucrase/dist/register',
  register: (hook, config) => void
},
'.sucrase.tsx': {
  module: 'sucrase/dist/register',
  register: (hook, config) => void
},

// SWC-specific extensions
'.swc.js': {
  module: '@swc/register',
  register: (hook, config) => void
},
'.swc.jsx': {
  module: '@swc/register',
  register: (hook, config) => void
},
'.swc.ts': {
  module: '@swc/register',
  register: (hook, config) => void
},
'.swc.tsx': {
  module: '@swc/register',
  register: (hook, config) => void
}

Extensions Only (not in jsVariants)

Extensions available in the main extensions object but not included in jsVariants:

// Native Node.js loaders
'.json': null,
'.node': null,

// TypeScript CommonJS modules
'.cts': ['ts-node/register'],

// Data formats
'.json5': 'json5/lib/register',
'.yaml': 'yaml-hook/register',
'.yml': 'yaml-hook/register',
'.toml': {
  module: 'toml-require',
  register: (hook, config) => void
}

Internal Helper Functions

The package includes internal helper functions used within loader configurations:

/**
 * Helper functions for matching specific file extensions
 * These are used internally by the loader configurations
 */
function endsInJsx(filename: string): boolean;
function endsInTs(filename: string): boolean;
function endsInTsx(filename: string): boolean;
function endsInBabelJs(filename: string): boolean;
function endsInBabelJsx(filename: string): boolean;
function endsInBabelTs(filename: string): boolean;
function endsInBabelTsx(filename: string): boolean;
function endsInEsbuildJs(filename: string): boolean;
function endsInEsbuildJsx(filename: string): boolean;
function endsInEsbuildTs(filename: string): boolean;
function endsInEsbuildTsx(filename: string): boolean;
function endsInSucraseJs(filename: string): boolean;
function endsInSucraseJsx(filename: string): boolean;
function endsInSucraseTs(filename: string): boolean;
function endsInSucraseTsx(filename: string): boolean;
function endsInSwcJs(filename: string): boolean;
function endsInSwcJsx(filename: string): boolean;
function endsInSwcTs(filename: string): boolean;
function endsInSwcTsx(filename: string): boolean;

/**
 * Helper function to check if a file is in node_modules
 * Used for ignoring node_modules in some transpiler configurations
 */
function isNodeModules(file: string): boolean;

Stub Files

The package includes stub files for CommonJS and ES Modules:

/**
 * Path to CommonJS stub file that registers .cjs extension
 * Resolves to: path.join(__dirname, 'cjs-stub')
 * Contents: require.extensions['.cjs'] = null;
 */
const cjsStub: string;

/**
 * Path to ES Module stub file that registers .mjs extension  
 * Resolves to: path.join(__dirname, 'mjs-stub')
 * Contents: require.extensions['.mjs'] = null;
 */
const mjsStub: string;

Usage Patterns

Basic Extension Check

const interpret = require('interpret');

function hasLoader(extension) {
  return extension in interpret.extensions;
}

function isJavaScriptVariant(extension) {
  return extension in interpret.jsVariants;
}

Loader Registration Implementation

const interpret = require('interpret');

function attemptRequire(extension, filepath) {
  const loader = interpret.extensions[extension];
  
  if (!loader) {
    throw new Error(`No loader available for ${extension}`);
  }
  
  if (loader === null) {
    // Use default Node.js loader
    return require(filepath);
  }
  
  // Register the appropriate loader
  registerLoader(loader);
  
  // Now require the file
  return require(filepath);
}

function registerLoader(loader) {
  if (typeof loader === 'string') {
    require(loader);
  } else if (Array.isArray(loader)) {
    // Try each loader until one succeeds
    for (const option of loader) {
      try {
        registerSingleLoader(option);
        return;
      } catch (err) {
        // Continue to next option
      }
    }
    throw new Error('No working loader found');
  } else if (loader && loader.module) {
    registerSingleLoader(loader);
  }
}

function registerSingleLoader(loader) {
  if (typeof loader === 'string') {
    require(loader);
  } else if (loader.module) {
    const hook = require(loader.module);
    if (loader.register) {
      loader.register(hook);
    }
  }
}

Configuration Examples

Most loaders accept configuration through the register function's second parameter:

// Babel configuration example
const babelLoader = {
  module: '@babel/register',
  register: (hook, config) => {
    const defaultConfig = {
      rootMode: 'upward-optional',
      overrides: [{
        only: [filename => filename.endsWith('.tsx')],
        presets: [
          '@babel/preset-env',
          '@babel/preset-react',
          ['@babel/preset-typescript', { isTSX: true, allExtensions: true }]
        ]
      }]
    };
    
    hook(Object.assign({}, defaultConfig, config, { extensions: '.tsx' }));
  }
};

// ESBuild configuration example
const esbuildLoader = {
  module: 'esbuild-register/dist/node',
  register: (mod, config) => {
    const defaultConfig = {
      target: 'node' + process.version.slice(1),
      hookMatcher: filename => filename.endsWith('.ts')
    };
    
    mod.register(Object.assign({}, defaultConfig, config, { extensions: ['.ts'] }));
  }
};

// SWC configuration example
const swcLoader = {
  module: '@swc/register',
  register: (hook, config) => {
    const defaultConfig = {
      only: [filename => filename.endsWith('.ts')],
      ignore: [filepath => filepath.includes('node_modules')],
      jsc: {
        parser: { syntax: 'typescript' }
      },
      module: { type: 'commonjs' }
    };
    
    hook(Object.assign({}, defaultConfig, config, { extensions: '.ts' }));
  }
};

Error Handling

The package itself does not throw errors - it provides configuration data. However, when implementing loader registration, common error scenarios include:

  • Missing dependencies: Loader modules not installed
  • Configuration errors: Invalid configuration passed to register functions
  • Loader conflicts: Multiple loaders registering for the same extension
  • Syntax errors: Files that don't match the expected syntax for their extension
function safeRegisterLoader(extension, filepath) {
  try {
    return attemptRequire(extension, filepath);
  } catch (err) {
    if (err.code === 'MODULE_NOT_FOUND') {
      console.warn(`Loader for ${extension} not installed:`, err.message);
      // Optionally fall back to default loader
      return require(filepath);
    }
    throw err;
  }
}