or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

blueprint-system.mdcli-commands.mdindex.mdmodels-utilities.mdprogrammatic-api.md
tile.json

models-utilities.mddocs/

Models and Utilities

Ember CLI provides a comprehensive set of models and utility functions that power its core functionality. These components handle project management, addon discovery, build coordination, file system operations, and various development workflow tasks.

Capabilities

Core Models

Project Model

Represents an Ember.js project with access to configuration, addons, and project metadata.

class Project {
  /**
   * Find the closest project from a given path by walking up the directory tree
   * @param pathName - Starting path to search from
   * @returns Project instance or null if no project found
   */
  static closestSync(pathName: string): Project | null;
  
  /**
   * Get project instance or create a null project for commands that work outside projects
   * @param ui - UI instance for user interaction
   * @param cli - CLI instance
   * @returns Project instance (real project or null project)
   */
  static projectOrnullProject(ui: UI, cli: CLI): Project;
  
  /**
   * Require a module relative to the project root
   * @param module - Module path to require
   * @returns Required module
   */
  require(module: string): any;
  
  /**
   * Discover and instantiate all project addons
   * @returns Promise resolving when addon discovery is complete
   */
  addonDiscovery(): Promise<void>;
  
  /**
   * Get project configuration for given environment
   * @param env - Environment name
   * @returns Configuration object
   */
  config(env: string): any;
  
  /**
   * Resolve a module path relative to the project root
   * @param module - Module path to resolve
   * @returns Resolved module path
   */
  resolveSync(module: string): string;
  
  /**
   * Get project dependencies (combines dependencies and devDependencies)
   * @returns Object with all project dependencies
   */
  dependencies(): { [key: string]: string };
  
  /**
   * Check if project has dependencies installed
   * @returns True if dependencies are available
   */
  hasDependencies(): boolean;
  
  /**
   * Check if this is an Ember CLI project
   * @returns True if ember-cli is in dependencies
   */
  isEmberCLIProject(): boolean;
  
  /**
   * Check if this is an Ember CLI addon
   * @returns True if package has ember-addon keyword
   */
  isEmberCLIAddon(): boolean;
  
  /**
   * Get the project name from package.json
   * @returns Project name
   */
  name(): string;
  
  /** Project root directory */
  root: string;
  /** Package.json contents */
  pkg: any;
  /** Array of discovered addons */
  addons: Addon[];
  /** UI instance for user interaction */
  ui: UI;
  /** CLI instance */
  cli: CLI;
  /** Addon packages object */
  addonPackages: { [key: string]: any };
  /** Live reload filter patterns */
  liveReloadFilterPatterns: string[];
}

Addon Model

Represents an Ember CLI addon with lifecycle hooks and build integration.

class Addon {
  /**
   * Extend the Addon class to create custom addons
   * @param options - Addon configuration options
   * @returns Extended Addon class
   */
  static extend(options: AddonOptions): typeof Addon;
  
  /**
   * Hook called when addon is included in build
   * @param app - Application or parent addon instance
   */
  included(app: any): void;
  
  /**
   * Provide trees for different build stages
   * @param name - Tree name (app, vendor, test-support, etc.)
   * @returns Broccoli tree or undefined
   */
  treeFor(name: string): any;
  
  /**
   * Provide content for HTML insertion points
   * @param type - Content type (head, head-footer, body-footer, test-head, etc.)
   * @returns HTML string or undefined
   */
  contentFor(type: string): string | undefined;
  
  /**
   * Modify application configuration
   * @param env - Environment name
   * @param config - Configuration object to modify
   */
  config(env: string, config: any): void;
  
  /** Addon name */
  name: string;
  /** Addon root directory */
  root: string;
  /** Addon package.json contents */
  pkg: any;
  /** Parent application or addon */
  app: any;
  /** Project instance */
  project: Project;
}

interface AddonOptions {
  /** Addon name */
  name: string;
  /** Lifecycle hooks */
  included?: (app: any) => void;
  treeFor?: (name: string) => any;
  contentFor?: (type: string) => string;
  config?: (env: string, config: any) => void;
}

Builder Model

Manages the build process with asset compilation and optimization.

class Builder {
  /**
   * Create a new builder instance
   * @param options - Builder configuration
   */
  constructor(options: BuilderOptions);
  
  /**
   * Build the project and return results
   * @returns Promise resolving to build results
   */
  build(): Promise<BuildResult>;
  
  /**
   * Clean up builder resources and temporary files
   * @returns Promise resolving when cleanup is complete
   */
  cleanup(): Promise<void>;
  
  /** UI instance for user feedback */
  ui: UI;
  /** Output directory path */
  outputPath: string;
  /** Build environment */
  environment: string;
  /** Project instance */
  project: Project;
}

interface BuilderOptions {
  ui: UI;
  outputPath: string;
  environment: string;
  project: Project;
}

interface BuildResult {
  /** Output directory */
  directory: string;
  /** Build dependency graph */
  graph: any;
  /** Total build time in milliseconds */
  totalTime: number;
}

Instrumentation Model

Provides performance monitoring and build timing information.

class Instrumentation {
  /**
   * Create new instrumentation instance
   * @param options - Instrumentation configuration
   */
  constructor(options: InstrumentationOptions);
  
  /**
   * Start timing a named operation
   * @param name - Operation name
   * @param annotation - Optional annotation object
   * @returns Timing token
   */
  start(name: string, annotation?: any): any;
  
  /**
   * Stop timing and generate report
   * @param name - Operation name
   * @param ...args - Additional arguments for report
   */
  stopAndReport(name: string, ...args: any[]): void;
}

interface InstrumentationOptions {
  ui: UI;
  initInstrumentation?: any;
}

Watcher Model

Handles file system watching for live-reload functionality.

class Watcher {
  /**
   * Start watching files for changes
   * @param paths - Paths to watch
   * @param options - Watch options
   * @returns Promise resolving when watching starts
   */
  watch(paths: string[], options?: WatchOptions): Promise<void>;
  
  /**
   * Stop watching files
   * @returns Promise resolving when watching stops
   */
  unwatch(): Promise<void>;
  
  /**
   * Add event listener for file changes
   * @param event - Event name (change, add, delete)
   * @param listener - Event handler function
   */
  on(event: string, listener: Function): void;
}

interface WatchOptions {
  /** Polling interval in milliseconds */
  interval?: number;
  /** Ignored file patterns */
  ignored?: string[];
}

File System Utilities

File Operations

/**
 * Insert content into an existing file at specified location
 * @param file - Target file path
 * @param searchString - String to search for insertion point
 * @param content - Content to insert
 * @param options - Insertion options
 * @returns Promise resolving when insertion is complete
 */
function insertIntoFile(
  file: string, 
  searchString: string, 
  content: string, 
  options?: InsertOptions
): Promise<void>;

interface InsertOptions {
  /** Insert after the search string (default: true) */
  after?: boolean;
  /** Insert at the beginning of the file */
  prepend?: boolean;
  /** Insert at the end of the file */
  append?: boolean;
}

/**
 * Clean removal of files and directories with parent cleanup
 * @param fileInfo - File information object with paths
 * @returns Promise resolving when removal is complete
 */
function cleanRemove(fileInfo: FileInfo): Promise<void>;

interface FileInfo {
  /** Output path to remove */
  outputPath: string;
  /** Display path for the file */
  displayPath: string;
  /** Base output path */
  outputBasePath: string;
}

/**
 * Walk up directory tree to find a file
 * @param paths - File paths to search for
 * @param start - Starting directory
 * @returns Found file path or null
 */
function walkUpPath(paths: string[], start?: string): string | null;

Path and Name Utilities

/**
 * Convert package name to directory name
 * @param packageName - NPM package name
 * @returns Directory-safe name
 */
function directoryForPackageName(packageName: string): string;

/**
 * Validate project name for Ember conventions
 * @param projectName - Proposed project name
 * @returns True if valid, false otherwise
 */
function isValidProjectName(projectName: string): boolean;

/**
 * Get base name from package name (remove scoping)
 * @param packageName - Full package name
 * @returns Base package name
 */
function getPackageBaseName(packageName: string): string;

String Processing Utilities

/**
 * Stringify and normalize data for consistent output
 * @param contents - Data to stringify
 * @returns Normalized string representation
 */
function stringifyAndNormalize(contents: any): string;

/**
 * Process template with variable substitution
 * @param template - Template string
 * @param context - Variable context
 * @returns Processed template string
 */
function processTemplate(template: string, context: any): string;

/**
 * Prepend emoji to message for better UX
 * @param emoji - Emoji character
 * @param message - Message string
 * @returns Message with emoji prefix
 */
function prependEmoji(emoji: string, message: string): string;

Build and Asset Utilities

/**
 * Find and import ember-cli-build.js file in project
 * @param dir - Directory to search from
 * @returns Build function or null if not found
 */
function findBuildFile(dir: string): Promise<Function | null>;

/**
 * Format package list for display
 * @param packages - Array of package information
 * @returns Formatted string
 */
function formatPackageList(packages: PackageInfo[]): string;

interface PackageInfo {
  name: string;
  version: string;
  description?: string;
}

/**
 * Determine install command for package manager
 * @param packageManager - Package manager type
 * @returns Install command string
 */
function determineInstallCommand(packageManager: 'npm' | 'pnpm' | 'yarn'): string;

Development Utilities

/**
 * Check if package keywords indicate it's an addon
 * @param keywords - Package.json keywords array
 * @returns True if package is an addon
 */
function isAddon(keywords: string[]): boolean;

/**
 * Check if package is an Ember engine
 * @param keywords - Package.json keywords array
 * @returns True if package is an engine
 */
function isEngine(keywords: string[]): boolean;

/**
 * Check if package is a lazy engine
 * @param pkg - Package.json contents
 * @returns True if package is a lazy engine
 */
function isLazyEngine(pkg: any): boolean;

/**
 * Open file in configured editor
 * @param file - File path to open
 * @param line - Line number (optional)
 * @returns Promise resolving when editor opens
 */
function openEditor(file: string, line?: number): Promise<void>;

Command Line Utilities

/**
 * Parse and extract option arguments from command line
 * @param option - Option name to extract
 * @param args - Command line arguments array
 * @returns Array of option values
 */
function getOptionArgs(option: string, args: string[]): string[];

/**
 * Get language argument with validation
 * @param args - Command line arguments
 * @returns Language code or null
 */
function getLangArg(args: string[]): string | null;

/**
 * Generate serve URL from options
 * @param options - Server options
 * @returns Complete server URL
 */
function getServeUrl(options: ServeOptions): string;

interface ServeOptions {
  host?: string;
  port?: number;
  ssl?: boolean;
  protocol?: string;
}

Configuration Utilities

/**
 * Get ember-cli configuration with optional override
 * @param override - Override configuration
 * @returns Configuration object
 */
function getConfig(override?: string): any;

/**
 * Merge blueprint options with defaults
 * @param rawArgs - Raw command arguments
 * @returns Merged options object
 */
function mergeBlueprintOptions(rawArgs: string[]): any;

/**
 * Normalize blueprint name and options
 * @param blueprint - Blueprint specification
 * @returns Normalized blueprint name
 */
function normalizeBlueprint(blueprint: string): string;

System Integration Utilities

/**
 * Execute external process with proper error handling
 * @param command - Command to execute
 * @param args - Command arguments
 * @param options - Execution options
 * @returns Promise resolving to process result
 */
function execa(command: string, args: string[], options?: ExecaOptions): Promise<ExecaResult>;

interface ExecaOptions {
  cwd?: string;
  env?: { [key: string]: string };
  stdio?: string;
  timeout?: number;
}

interface ExecaResult {
  stdout: string;
  stderr: string;
  exitCode: number;
}

/**
 * Handle process interruption gracefully
 * @param handler - Interrupt handler function
 */
function willInterruptProcess(handler: () => void): void;

Platform-Specific Utilities

/**
 * Windows-specific utilities for symlink administration
 */
class WindowsSymlinkChecker {
  /**
   * Check if symlinks need to be enabled on Windows
   * @param ui - UI instance for user prompts
   * @returns Promise resolving when check is complete
   */
  static checkIfSymlinksNeedToBeEnabled(ui: UI): Promise<void>;
  
  /**
   * Check if current user has admin privileges
   * @returns True if user is administrator
   */
  static isAdmin(): boolean;
}

Ember App Utilities

Specialized utilities for Ember application development and build processes.

/**
 * Process addon tree for build pipeline
 * @param projectOrAddon - Project or addon instance
 * @param hook - Hook name
 * @param processType - Process type
 * @param tree - Broccoli tree
 * @returns Processed tree
 */
function addonProcessTree(
  projectOrAddon: Project | Addon,
  hook: string,
  processType: string,
  tree: any
): any;

/**
 * Require modules as hash object
 * @param pattern - Glob pattern for files
 * @param Constructor - Constructor function for instances
 * @returns Hash object with loaded modules
 */
function requireAsHash(pattern: string, Constructor?: Function): { [key: string]: any };

/**
 * Run operations in sequence with proper error handling
 * @param operations - Array of operation functions
 * @returns Promise resolving when all operations complete
 */
function sequence(operations: Array<() => Promise<any>>): Promise<any>;

Usage Examples

Project Discovery and Management

const Project = require('ember-cli/lib/models/project');
const path = require('path');

// Find project from current directory
const project = Project.closestSync(process.cwd());

if (project) {
  console.log('Project root:', project.root);
  console.log('Project name:', project.pkg.name);
  
  // Access configuration
  const config = project.config('development');
  console.log('App configuration:', config.APP);
  
  // Require project module
  const buildFile = project.require('./ember-cli-build.js');
} else {
  console.log('No Ember project found');
}

Addon Development

const Addon = require('ember-cli/lib/models/addon');

module.exports = Addon.extend({
  name: 'my-custom-addon',
  
  included(app) {
    this._super.included.apply(this, arguments);
    
    // Add custom dependencies
    app.import('vendor/my-library.js');
  },
  
  treeFor(name) {
    if (name === 'vendor') {
      // Return custom vendor tree
      return this.treeGenerator(path.join(this.root, 'vendor'));
    }
    
    return this._super.treeFor.call(this, name);
  },
  
  contentFor(type) {
    if (type === 'head') {
      return '<meta name="my-addon" content="active">';
    }
  }
});

File System Operations

const { insertIntoFile, cleanRemove } = require('ember-cli/lib/utilities');
const path = require('path');

async function modifyAppFile() {
  const appFile = path.join(process.cwd(), 'app/app.js');
  
  // Insert import statement
  await insertIntoFile(
    appFile,
    'import Application from \'@ember/application\';',
    'import config from \'./config/environment\';',
    { after: true }
  );
  
  console.log('Modified app.js successfully');
}

async function cleanup() {
  // Clean remove temporary files
  await cleanRemove(path.join(process.cwd(), 'tmp'));
  console.log('Cleanup completed');
}

Build Integration

const Builder = require('ember-cli/lib/models/builder');

async function customBuild() {
  const builder = new Builder({
    ui: project.ui,
    outputPath: 'dist-custom',
    environment: 'production',
    project: project
  });
  
  try {
    const result = await builder.build();
    console.log('Build completed in:', result.totalTime, 'ms');
    console.log('Output directory:', result.directory);
  } finally {
    await builder.cleanup();
  }
}

String and Path Processing

const { 
  directoryForPackageName, 
  isValidProjectName,
  stringifyAndNormalize 
} = require('ember-cli/lib/utilities');

// Convert package name to directory
const dirName = directoryForPackageName('@scope/my-package');
console.log(dirName); // 'scope-my-package'

// Validate project name
const isValid = isValidProjectName('my-ember-app');
console.log('Valid project name:', isValid);

// Normalize data for output
const normalized = stringifyAndNormalize({ foo: 'bar', nested: { value: 123 } });
console.log('Normalized:', normalized);

Process and System Integration

const { execa, willInterruptProcess } = require('ember-cli/lib/utilities');

// Execute external command
async function runTests() {
  try {
    const result = await execa('npm', ['test'], {
      cwd: process.cwd(),
      stdio: 'inherit'
    });
    
    console.log('Tests completed with exit code:', result.exitCode);
  } catch (error) {
    console.error('Test execution failed:', error.message);
  }
}

// Handle process interruption
willInterruptProcess(() => {
  console.log('Cleaning up before exit...');
  // Perform cleanup operations
});

Integration Patterns

The models and utilities are designed to work together in common patterns:

Plugin Development

// Custom command using models and utilities
const Command = require('ember-cli/lib/models/command');
const { isValidProjectName, execa } = require('ember-cli/lib/utilities');

module.exports = Command.extend({
  name: 'custom-deploy',
  
  async run(options) {
    const project = this.project;
    
    if (!project || !isValidProjectName(project.pkg.name)) {
      throw new Error('Invalid project configuration');
    }
    
    // Build project
    await execa('ember', ['build', '--environment', 'production']);
    
    // Custom deployment logic
    this.ui.writeLine('Deployment completed');
  }
});

Build Pipeline Extension

// Custom build process using models
const Project = require('ember-cli/lib/models/project');
const Builder = require('ember-cli/lib/models/builder');

async function customBuildPipeline() {
  const project = Project.closestSync(process.cwd());
  const builder = new Builder({
    ui: project.ui,
    outputPath: 'dist',
    environment: 'production',
    project
  });
  
  // Pre-build hook
  await project.addonDiscovery();
  
  // Build
  const result = await builder.build();
  
  // Post-build processing
  await processAssets(result.directory);
  
  return result;
}