or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration-options.mdcore-addon-interface.mdindex.mdplugin-generation.mdutility-functions.md
tile.json

utility-functions.mddocs/

Utility Functions

ember-cli-babel provides several utility functions that are useful for addon developers who need to integrate with the transpilation system or perform custom build operations.

Capabilities

Application Discovery

findApp

Locates the root Ember application instance from any addon in the addon tree.

/**
 * Traverses the addon tree to find the root application
 * @param addon - Starting addon instance to search from
 * @returns Root Ember application instance or undefined
 */
function findApp(addon: EmberAddon): EmberApp | undefined;

Usage Examples:

// In an addon's index.js
const findApp = require('ember-cli-babel/lib/find-app');

module.exports = {
  name: 'my-addon',
  
  someMethod() {
    // Find the root app from this addon
    let app = findApp(this);
    
    if (app) {
      // Access app-level configuration
      let appOptions = app.options;
      console.log('App name:', app.name);
    }
  }
};

This is particularly useful when an addon needs to:

  • Access app-level configuration
  • Determine if it's running in the context of an app vs. another addon
  • Get the root application's options or settings

Module Path Resolution

getRelativeModulePath

Converts absolute module paths to relative POSIX-style paths from the current working directory.

/**
 * Converts absolute path to relative POSIX path from cwd
 * @param modulePath - Absolute path to convert
 * @returns POSIX-style relative path from current working directory
 */
function getRelativeModulePath(modulePath: string): string;

Usage Examples:

const { getRelativeModulePath } = require('ember-cli-babel/lib/relative-module-paths');

// Convert absolute path to relative
let absolutePath = '/Users/developer/project/app/components/my-component.js';
let relativePath = getRelativeModulePath(absolutePath);
// Returns: 'app/components/my-component.js'

// Works with nested addon paths
let addonPath = '/Users/developer/project/node_modules/my-addon/addon/services/my-service.js';
let relativeAddonPath = getRelativeModulePath(addonPath);
// Returns: 'node_modules/my-addon/addon/services/my-service.js'

resolveRelativeModulePath

Resolves module paths using AMD name resolution logic for proper module compilation.

/**
 * Resolves module path using AMD name resolver
 * @param name - Module name to resolve
 * @param child - Child module path for resolution context
 * @returns Resolved module path for AMD compilation
 */
function resolveRelativeModulePath(name: string, child: string): string;

Usage Examples:

const { resolveRelativeModulePath } = require('ember-cli-babel/lib/relative-module-paths');

// Resolve relative imports
let resolved = resolveRelativeModulePath('../utils/helper', 'app/components/my-component');
// Returns appropriate AMD module path

// Resolve named imports
let namedResolved = resolveRelativeModulePath('@ember/component', 'app/components/my-component');
// Returns resolved path for Ember's module system

These functions are essential for:

  • Custom Babel plugins that need to manipulate module paths
  • Addons that generate code with proper module resolution
  • Build tools that need to understand Ember's module structure

Helper Detection

defaultShouldIncludeHelpers

Determines whether external Babel helpers should be included based on project analysis and heuristics.

/**
 * Analyzes project to determine if external helpers would be beneficial
 * @param project - Ember project instance
 * @returns true if helpers should be included, false otherwise
 */
function defaultShouldIncludeHelpers(project: EmberProject): boolean;

Usage Examples:

const defaultShouldIncludeHelpers = require('ember-cli-babel/lib/default-should-include-helpers');

module.exports = {
  name: 'my-addon',
  
  someMethod() {
    let shouldInclude = defaultShouldIncludeHelpers(this.project);
    
    if (shouldInclude) {
      console.log('External helpers would reduce bundle size');
    } else {
      console.log('External helpers would increase bundle size');
    }
  }
};

The heuristics consider:

  • Presence of @ember-decorators/babel-transforms
  • Recursive checking of all addon dependencies
  • Helper inclusion pays for itself after usage in 5 files with stage 2+ decorators, or 25 files with stage 1 decorators

Babel Configuration Generation

getBabelOptions

Internal function that generates the complete Babel options object used for transpilation.

/**
 * Generates complete Babel options object from configuration
 * @param config - Configuration object from ember-cli-build.js
 * @param appInstance - Addon instance providing context
 * @returns Complete Babel options with plugins and presets
 */
function getBabelOptions(config: object, appInstance: EmberAddon): object;

Usage Examples:

const getBabelOptions = require('ember-cli-babel/lib/get-babel-options');

// Generally used internally, but addon developers can access it
let babelOptions = getBabelOptions(this._getAddonOptions(), this);
// Returns: { plugins: [...], presets: [...] }

This function orchestrates the assembly of all Babel configuration including:

  • TypeScript handling
  • Decorator plugins
  • Debug macros
  • Module compilation
  • Helper plugins
  • Preset environment configuration

Babel Options Utilities

Several utility functions are available for generating specific parts of Babel configuration:

_shouldCompileModules

/**
 * Determines if ES6 modules should be compiled based on configuration and Ember CLI version
 * @param options - Configuration options
 * @param project - Ember project instance
 * @returns true if modules should be compiled to AMD
 */
function _shouldCompileModules(options: object, project: EmberProject): boolean;

_shouldIncludeHelpers

/**
 * Determines if external helpers should be included based on configuration and heuristics
 * @param options - Configuration options
 * @param appInstance - Addon instance
 * @returns true if external helpers should be included
 */
function _shouldIncludeHelpers(options: object, appInstance: EmberAddon): boolean;

_shouldHandleTypeScript

/**
 * Determines if TypeScript files should be transpiled
 * @param config - Configuration object
 * @param parent - Parent addon/app instance
 * @param project - Project instance
 * @returns true if TypeScript should be handled
 */
function _shouldHandleTypeScript(config: object, parent: EmberAddon, project: EmberProject): boolean;

_getExtensions

/**
 * Gets array of file extensions that should be processed
 * @param config - Configuration object
 * @param parent - Parent addon/app instance
 * @param project - Project instance
 * @returns Array of file extensions to process
 */
function _getExtensions(config: object, parent: EmberAddon, project: EmberProject): string[];

_parentName

/**
 * Gets the name of a parent addon or app
 * @param parent - Parent addon/app instance
 * @returns Name of the parent or undefined
 */
function _parentName(parent: EmberAddon | EmberApp): string | undefined;

Usage Examples:

const {
  _shouldCompileModules,
  _shouldHandleTypeScript,
  _getExtensions,
  _parentName
} = require('ember-cli-babel/lib/babel-options-util');

module.exports = {
  name: 'my-addon',
  
  someMethod() {
    // Check if modules should be compiled
    let shouldCompile = _shouldCompileModules(this.options, this.project);
    
    // Check TypeScript handling
    let handleTS = _shouldHandleTypeScript(this.options, this, this.project);
    
    // Get supported extensions
    let extensions = _getExtensions(this.options, this, this.project);
    
    // Get parent name for debugging
    let parentName = _parentName(this.parent);
    console.log(`Running in context of: ${parentName}`);
  }
};

Parallel Babel Support

The utility functions include support for parallel processing with broccoli-babel-transpiler:

interface ParallelBabelConfig {
  requireFile: string;
  useMethod: string;
}

Each exported function includes a _parallelBabel property that enables parallel processing:

// Functions are automatically configured for parallel processing
getRelativeModulePath._parallelBabel = {
  requireFile: __filename,
  useMethod: 'getRelativeModulePath'
};

This enables the broccoli build system to parallelize transpilation across multiple processes for better performance.

Babel Plugin Utilities

dedupe-internal-decorators-plugin

A specialized Babel plugin that handles decorator syntax parsing conflicts in the transpilation pipeline.

/**
 * Creates a Babel plugin that removes duplicate legacy decorator parser configurations
 * @returns Babel plugin object with manipulateOptions method
 */
function dedupeInternalDecoratorsPlugin(): BabelPlugin;

This plugin:

  • Removes duplicate decorators parser plugin configurations
  • Specifically handles legacy decorator conflicts (decoratorsBeforeExport: true, legacy: true)
  • Used internally when babel-plugin-filter-imports < 3.0.0 is detected
  • Prevents parser conflicts that can occur with multiple decorator configurations

Usage Example:

// Access the plugin factory
const dedupePlugin = require('ember-cli-babel/lib/dedupe-internal-decorators-plugin');

// Create plugin instance (returns Babel plugin object)
const pluginInstance = dedupePlugin();

Integration Examples

Custom Babel Plugin

// babel-plugin-custom-resolver.js
const { resolveRelativeModulePath } = require('ember-cli-babel/lib/relative-module-paths');

module.exports = function() {
  return {
    visitor: {
      ImportDeclaration(path, state) {
        if (path.node.source.value.startsWith('./')) {
          // Resolve relative import
          let resolved = resolveRelativeModulePath(
            path.node.source.value,
            state.filename
          );
          path.node.source.value = resolved;
        }
      }
    }
  };
};

Addon Integration

// addon/index.js
const findApp = require('ember-cli-babel/lib/find-app');
const { _shouldHandleTypeScript } = require('ember-cli-babel/lib/babel-options-util');

module.exports = {
  name: 'my-build-addon',
  
  treeForAddon(tree) {
    let app = findApp(this);
    let shouldHandleTS = _shouldHandleTypeScript(app.options, this, this.project);
    
    if (shouldHandleTS) {
      // Include TypeScript-specific processing
      tree = this.processTypeScriptFiles(tree);
    }
    
    return this._super.treeForAddon.call(this, tree);
  }
};