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.
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:
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'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 systemThese functions are essential for:
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:
@ember-decorators/babel-transformsInternal 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:
Several utility functions are available for generating specific parts of Babel configuration:
/**
* 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;/**
* 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;/**
* 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;/**
* 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[];/**
* 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}`);
}
};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.
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:
decorators parser plugin configurationsdecoratorsBeforeExport: true, legacy: true)babel-plugin-filter-imports < 3.0.0 is detectedUsage 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();// 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/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);
}
};