or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

convenience-functions.mdimport-injector.mdindex.mdutilities.md
tile.json

import-injector.mddocs/

ImportInjector Class

The ImportInjector class provides a stateful interface for managing multiple import operations with shared configuration. It's ideal for complex Babel plugins that need to inject multiple imports with consistent settings.

Capabilities

ImportInjector Constructor

Creates a new ImportInjector instance with optional default configuration.

/**
 * Creates a new ImportInjector instance
 * @param path - Any NodePath within the program (will find the program path automatically)
 * @param importedSource - Optional default imported source for all operations
 * @param opts - Optional default import configuration
 */
constructor(
  path: NodePath,
  importedSource?: string,
  opts?: Partial<ImportOptions>
);

Usage Examples:

import { ImportInjector } from "@babel/helper-module-imports";

// Basic injector
const injector = new ImportInjector(path);

// With default source
const lodashInjector = new ImportInjector(path, "lodash");

// With default options
const reactInjector = new ImportInjector(path, undefined, {
  importedType: "es6",
  nameHint: "react"
});

// With both source and options
const utilsInjector = new ImportInjector(path, "./utils", {
  importedType: "es6",
  importPosition: "after"
});

addDefault Method

Adds a default import using the injector's configuration.

/**
 * Adds default import using configured options
 * @param importedSourceIn - The source of the import
 * @param opts - Additional options (merged with instance defaults)
 * @returns Identifier representing the imported default value
 */
addDefault(
  importedSourceIn: string, 
  opts: Partial<ImportOptions>
): t.Identifier | t.MemberExpression | t.SequenceExpression;

Usage Examples:

const injector = new ImportInjector(path, undefined, { 
  importedType: "es6",
  nameHint: "lib" 
});

// Uses injector's default options
const lodashId = injector.addDefault("lodash", {});
// Generates: import _lib from "lodash";

// Override specific options
const reactId = injector.addDefault("react", { nameHint: "React" });
// Generates: import _React from "react";

addNamed Method

Adds a named import using the injector's configuration.

/**
 * Adds named import using configured options
 * @param importName - The name of the export to import
 * @param importedSourceIn - The source of the import
 * @param opts - Additional options (merged with instance defaults)
 * @returns Different types based on options (Identifier, MemberExpression, or SequenceExpression)
 */
addNamed(
  importName: string,
  importedSourceIn: string,
  opts: Partial<ImportOptions>
): t.Identifier | t.MemberExpression | t.SequenceExpression;

Usage Examples:

const injector = new ImportInjector(path, "lodash", { 
  importedType: "es6" 
});

// Basic named import
const debounceId = injector.addNamed("debounce", "lodash", {});
// Generates: import { debounce as _debounce } from "lodash";

// Multiple named imports from same source (automatically merged)
const throttleId = injector.addNamed("throttle", "lodash", {});
const pickId = injector.addNamed("pick", "lodash", {});
// Generates: import { debounce as _debounce, throttle as _throttle, pick as _pick } from "lodash";

addNamespace Method

Adds a namespace import using the injector's configuration.

/**
 * Adds namespace import using configured options
 * @param importedSourceIn - The source of the import
 * @param opts - Additional options (merged with instance defaults)
 * @returns Identifier representing the imported namespace
 */
addNamespace(
  importedSourceIn: string,
  opts: Partial<ImportOptions>
): t.Identifier | t.MemberExpression | t.SequenceExpression;

Usage Examples:

const injector = new ImportInjector(path, undefined, { 
  importedType: "es6",
  nameHint: "ns" 
});

const reactId = injector.addNamespace("react", {});
// Generates: import * as _ns from "react";

const lodashId = injector.addNamespace("lodash", { nameHint: "lodash" });
// Generates: import * as _lodash from "lodash";

addSideEffect Method

Adds a side-effect import using the injector's configuration.

/**
 * Adds side-effect import using configured options
 * @param importedSourceIn - The source of the import
 * @param opts - Additional options (merged with instance defaults)
 * @returns Identifier representing any incidental binding (usually unused)
 */
addSideEffect(
  importedSourceIn: string,
  opts: Partial<ImportOptions>
): t.Identifier | t.MemberExpression | t.SequenceExpression;

Usage Examples:

const injector = new ImportInjector(path, undefined, { 
  importedType: "es6" 
});

injector.addSideEffect("reflect-metadata", {});
// Generates: import "reflect-metadata";

injector.addSideEffect("./polyfills", {});
// Generates: import "./polyfills";

Instance Properties

The ImportInjector maintains several private properties for state management:

class ImportInjector {
  /** The program path used for manipulation */
  private _programPath: NodePath<t.Program>;
  /** The scope used to generate unique variable names */
  private _programScope: Scope;
  /** The file used to inject helpers and resolve paths */
  private _hub: HubInterface;
  /** Default options for this instance */
  private _defaultOpts: ImportOptions;
}

Advanced Usage Patterns

Reusing Configuration

// Create injector with common configuration
const injector = new ImportInjector(path, undefined, {
  importedType: "es6",
  importPosition: "after",
  nameHint: "imported"
});

// All operations use the shared configuration
const reactId = injector.addDefault("react", {});
const lodashNs = injector.addNamespace("lodash", {});
const debounceId = injector.addNamed("debounce", "lodash", {});

Mixed Module Types

const injector = new ImportInjector(path);

// ES6 imports
const reactId = injector.addDefault("react", { importedType: "es6" });

// CommonJS imports
const lodashId = injector.addDefault("lodash", { 
  importedType: "commonjs",
  importedInterop: "babel"
});

Working with Live References

const injector = new ImportInjector(path, undefined, {
  importedType: "commonjs",
  importedInterop: "babel"
});

// Force live reference for dynamic values
const debounceExpr = injector.addNamed("debounce", "lodash", {
  ensureLiveReference: true
});
// Result: MemberExpression that accesses the live property

Import Positioning

// Module-only: imports added after existing imports
const injector = new ImportInjector(programPath, undefined, {
  importedType: "es6",
  importPosition: "after"
});

// Add imports that will appear after existing imports
const newId = injector.addDefault("new-library", {});

Error Handling

The ImportInjector throws the same errors as convenience functions:

  • Module compatibility errors: Invalid ES6/CommonJS combinations
  • Position errors: Using "after" position in non-module files
  • Interop errors: Invalid interop configuration combinations
  • Live reference errors: Requesting unsupported live references
try {
  const injector = new ImportInjector(path, undefined, {
    importedType: "es6"
  });
  
  // This may throw if the file is not a module
  const id = injector.addDefault("some-module", {});
} catch (error) {
  console.error("Import injection failed:", error.message);
}

Integration with Babel Plugins

export default function myBabelPlugin() {
  return {
    visitor: {
      Program(path) {
        const injector = new ImportInjector(path);
        
        // Store injector in plugin state
        this.injector = injector;
      },
      
      CallExpression(path) {
        if (needsLodashDebounce(path.node)) {
          // Use stored injector
          const debounceId = this.injector.addNamed("debounce", "lodash", {});
          // Replace call with imported function
          path.replaceWith(t.callExpression(debounceId, path.node.arguments));
        }
      }
    }
  };
}