Internal API for managing import analysis, package resolution, and bundle generation. These APIs are primarily used internally by ember-auto-import but are exposed for advanced use cases and addon coordination.
Core class managing auto-import functionality and leader election between multiple addon instances:
/**
* Core AutoImport class managing import analysis and bundling
* Implements leader election pattern for multi-addon coordination
*/
class AutoImport implements AutoImportSharedAPI {
/** Register an addon instance with leader election system */
static register(addon: AddonInstance): void;
/** Lookup the leader instance for an addon */
static lookup(addon: AddonInstance): AutoImportSharedAPI;
/** Create new AutoImport instance for an addon */
constructor(addonInstance: AddonInstance);
/** Install app filter for allowAppImports patterns */
installAppFilter(host: AppInstance): void;
/** Check if addon is primary (legacy, always returns false) */
isPrimary(addon: AddonInstance): boolean;
/** Analyze tree for import statements */
analyze(tree: Node, addon: AddonInstance, treeType?: TreeType, supportsFastAnalyzer?: true): Analyzer;
/** Register v2 addon for Embroider compatibility */
registerV2Addon(packageName: string, packageRoot: string, options?: CompatOptions): void;
/** Get v2 addon resolver interface */
get v2AddonResolver(): V2AddonResolver;
/** Add auto-import bundles to build tree */
addTo(allAppTree: Node): Node;
/** Handle addon inclusion in build process */
included(addonInstance: AddonInstance): void;
}Usage Example:
// Internal usage by ember-auto-import addon
AutoImport.register(this); // Register addon instance
// Lookup leader instance
const leader = AutoImport.lookup(this);
const analyzer = leader.analyze(tree, this, 'app');Stable API interface for cross-version compatibility between different ember-auto-import versions:
/**
* Shared API interface for cross-version compatibility
* Ensures consistent behavior across different addon versions
*/
interface AutoImportSharedAPI {
/** Check if addon instance is primary (legacy method) */
isPrimary(addonInstance: AddonInstance): boolean;
/**
* Analyze tree for import statements and return analyzer
* Creates new Analyzer instance for the package
*/
analyze(
tree: Node,
addon: AddonInstance,
treeType?: TreeType,
supportsFastAnalyzer?: true
): Node;
/** Handle addon inclusion, install babel plugin and configure build */
included(addonInstance: AddonInstance): void;
/** Add webpack bundles to the final build tree */
addTo(tree: Node): Node;
/** Register v2 addon with optional compatibility options */
registerV2Addon(
packageName: string,
packageRoot: string,
compatOptions?: CompatOptions
): void;
}Manages individual Ember packages/addons and their auto-import configuration:
/**
* Represents an Ember package/addon with auto-import configuration
* Handles package resolution, babel config, and import categorization
*/
class Package {
/** Package name */
name: string;
/** Package root directory */
root: string;
/** Package root directory (may differ from root for dummy apps) */
pkgRoot: string;
/** Whether this package is an addon */
isAddon: boolean;
/** Whether this package is in development mode */
isDeveloping: boolean;
/** Package cache object */
pkgCache: any;
/** Package generation for cache invalidation */
pkgGeneration: number;
/** Create new Package instance for addon child */
constructor(child: AddonInstance, extraResolve: V2AddonResolver);
/** Lookup parent package of a child addon */
static lookupParentOf(child: AddonInstance, extraResolve: V2AddonResolver): Package;
/** Categorize import path type */
static categorize(importedPath: string, partial?: boolean): "local" | "url" | "imprecise" | "dep";
/** Check if package has a dependency */
hasDependency(name: string): boolean;
/** Get requested version range for a package */
requestedRange(packageName: string): string | undefined;
/** Resolve import path to package or local file */
resolve(importedPath: string, fromPath: string): DepResolution | LocalResolution | URLResolution | undefined;
/** Resolve with partial matching support */
resolve(importedPath: string, fromPath: string, partial: true): Resolution | undefined;
/** Get public asset URL for the package */
publicAssetURL(): string;
/** Get browserslist configuration */
browserslist(): string;
/** Get clean babel configuration without ember-specific settings */
cleanBabelConfig(): TransformOptions;
/** Get babel options for the package */
get babelOptions(): TransformOptions;
/** Get babel major version */
get babelMajorVersion(): number | undefined;
/** Check if FastBoot is enabled */
get isFastBootEnabled(): boolean;
/** Get webpack configuration */
get webpackConfig(): any;
/** Get packages to skip babel transformation */
get skipBabel(): Options['skipBabel'];
/** Get import aliases */
get aliases(): Record<string, string> | undefined;
/** Get supported file extensions */
get fileExtensions(): string[];
/** Get style loader options */
get styleLoaderOptions(): Record<string, unknown> | undefined;
/** Get CSS loader options */
get cssLoaderOptions(): Record<string, unknown> | undefined;
/** Get mini CSS extract plugin options */
get miniCssExtractPluginOptions(): Record<string, unknown> | undefined;
/** Check if eval is forbidden */
get forbidsEval(): boolean;
/** Get custom script insertion location */
get insertScriptsAt(): string | undefined;
/** Get custom style insertion location */
get insertStylesAt(): string | undefined;
/** Get directories to watch for changes */
get watchedDirectories(): string[] | undefined;
/** Get app import patterns to handle */
get allowAppImports(): string[];
}Usage Examples:
// Package resolution and categorization
const category = Package.categorize('lodash'); // 'dep'
const category2 = Package.categorize('./utils'); // 'local'
const category3 = Package.categorize('https://cdn.com/lib.js'); // 'url'
// Package lookup and dependency checking
const pkg = Package.lookupParentOf(addonInstance, v2Resolver);
const hasLodash = pkg.hasDependency('lodash');
const lodashVersion = pkg.requestedRange('lodash'); // '^4.17.0'Analyzes JavaScript/TypeScript files for import statements and categorizes them:
/**
* Analyzes source files for import statements
* Extends Broccoli Funnel for file processing
*/
class Analyzer extends Funnel {
/** All discovered imports from analyzed files */
get imports(): Import[];
/** Build and analyze files for imports */
build(...args: unknown[]): Promise<void>;
/** Remove imports from a specific file */
removeImports(relativePath: string): void;
/** Update imports from a specific file */
updateImports(relativePath: string): Promise<void>;
/** Get parser function for import analysis */
parser(): Promise<(source: string, relativePath: string) => ImportSyntax[]>;
}Support for Embroider v2 addons with renaming and compatibility options:
/**
* V2 addon resolver interface for Embroider compatibility
* Handles module renaming and v2 addon registration
*/
interface V2AddonResolver {
/** Check if a v2 addon is registered */
hasV2Addon(name: string): boolean;
/** Get root directory of a v2 addon */
v2AddonRoot(name: string): string | undefined;
/** Handle module renaming for v2 addons */
handleRenaming(name: string): string;
}
/**
* Compatibility options for v2 addon registration
* Allows customization of addon metadata
*/
interface CompatOptions {
/** Hook to customize addon metadata before processing */
customizeMeta?: (meta: AddonMeta) => AddonMeta;
}Usage Example:
// Register v2 addon with custom metadata handling
autoImport.registerV2Addon('my-v2-addon', '/path/to/addon', {
customizeMeta(meta) {
// Customize how the addon metadata is processed
return {
...meta,
'renamed-modules': {
'old-name': 'new-name'
}
};
}
});Different types of import resolution results:
/**
* NPM package dependency resolution
*/
interface DepResolution {
type: 'package';
packageName: string;
packageRoot: string;
resolvedSpecifier: string;
}
/**
* Local file resolution
*/
interface LocalResolution {
type: 'local';
local: string;
}
/**
* URL resolution for external resources
*/
interface URLResolution {
type: 'url';
url: string;
}
/**
* Imprecise resolution when path cannot be fully resolved
*/
interface ImpreciseResolution {
type: 'imprecise';
}
/**
* Union type for all resolution results
*/
type Resolution = DepResolution | LocalResolution | URLResolution | ImpreciseResolution;Different types of import statements discovered during analysis:
/**
* Static string import statement with package context
*/
interface LiteralImport {
path: string;
package: Package;
treeType: TreeType | undefined;
// Additional import syntax properties
}
/**
* Template literal import statement with package context
*/
interface TemplateImport {
path: string;
package: Package;
treeType: TreeType | undefined;
// Template literal specific properties
}
/**
* Union type for all import types
*/
type Import = LiteralImport | TemplateImport;
/**
* Tree type indicating which part of the Ember app the import is from
*/
type TreeType = 'app' | 'addon' | 'addon-templates' | 'addon-test-support' | 'styles' | 'templates' | 'test';
/**
* Base interface for import syntax discovered during analysis
*/
interface ImportSyntax {
/** File path where the import was found */
path: string;
/** Whether this is a dynamic import() call */
isDynamic: boolean;
}
/**
* String literal import syntax (static imports and simple dynamic imports)
*/
interface LiteralImportSyntax extends ImportSyntax {
/** The imported module specifier */
specifier: string;
}
/**
* Template literal import syntax (dynamic imports with template strings)
*/
interface TemplateImportSyntax extends ImportSyntax {
/** Cooked template literal parts */
cookedQuasis: string[];
/** Expression name hints for template variables */
expressionNameHints: string[];
}Utility functions for package management and analysis:
/**
* Reload dev packages cache
* Used during development to refresh package information
* Increments global package generation counter to invalidate caches
*/
function reloadDevPackages(): void;Usage Example:
// Force refresh of package cache during development
// Useful when package.json or dependencies change during development
reloadDevPackages();For addon authors who need to integrate with ember-auto-import:
// In your addon's index.js
module.exports = {
name: 'my-addon',
init() {
this._super.init.apply(this, arguments);
// Register with ember-auto-import if present
if (this.project.findAddonByName('ember-auto-import')) {
AutoImport.register(this);
}
},
included() {
this._super.included.apply(this, arguments);
// Get leader instance and configure
const autoImport = AutoImport.lookup(this);
if (autoImport) {
autoImport.included(this);
}
}
};Access import analysis results for build-time processing:
// Access discovered imports after analysis
const analyzer = autoImport.analyze(tree, this, 'app');
// analyzer.imports contains all discovered imports
analyzer.imports.forEach(importItem => {
console.log(`Found import: ${importItem.path} in ${importItem.package.name}`);
});