Development tools and debugging utilities for inspecting application state and troubleshooting issues.
Core debugging functions for assertions, warnings, and development-time feedback.
/**
* Runtime assertion that throws error if condition is false
* @param message - Error message to display
* @param condition - Condition that must be true
*/
function assert(message: string, condition: boolean): void;
/**
* Display warning message in development builds
* @param message - Warning message
* @param condition - Condition to test (warning shown if false)
* @param options - Additional warning options
*/
function warn(message: string, condition?: boolean, options?: WarnOptions): void;
/**
* Log debug message (only in debug builds)
* @param message - Debug message to log
*/
function debug(message: string): void;
/**
* Display deprecation warning for outdated API usage
* @param message - Deprecation message
* @param condition - Condition to test (deprecation shown if false)
* @param options - Deprecation options including id and until version
*/
function deprecate(message: string, condition?: boolean, options?: DeprecateOptions): void;
/**
* Execute code only in debug builds
* @param fn - Function to execute in debug mode
*/
function runInDebug(fn: () => void): void;Usage Examples:
import { assert, warn, debug, deprecate, runInDebug } from "@ember/debug";
export default class UserService extends Service {
createUser(userData) {
// Assertions for required parameters
assert('User data is required', userData != null);
assert('User must have email', userData.email);
assert('Email must be valid', userData.email.includes('@'));
// Warnings for potentially problematic situations
warn('User age not provided, defaulting to 0', userData.age != null, {
id: 'user-service.missing-age'
});
// Debug logging (only appears in development)
debug(`Creating user: ${userData.email}`);
// Deprecation warning for old API usage
if (userData.userName) {
deprecate('userName is deprecated, use username instead', false, {
id: 'user-service.user-name-deprecated',
until: '4.0.0',
url: 'https://example.com/migration-guide'
});
userData.username = userData.userName;
}
// Development-only code
runInDebug(() => {
console.log('User creation debug info:', {
timestamp: new Date(),
userData: userData,
stackTrace: new Error().stack
});
});
return this.store.createRecord('user', userData);
}
}
// Component example
export default class FormComponent extends Component {
@action
submitForm(event) {
event.preventDefault();
const formData = new FormData(event.target);
const email = formData.get('email');
const password = formData.get('password');
// Validate inputs with assertions
assert('Email is required for form submission', email);
assert('Password is required for form submission', password);
// Warn about potential issues
warn('Password is very short', password.length >= 8, {
id: 'form.weak-password'
});
debug(`Form submitted with email: ${email}`);
this.onSubmit?.({ email, password });
}
}Functions for inspecting and debugging object state.
/**
* Create detailed string representation of object for debugging
* @param obj - Object to inspect
* @param options - Inspection options
* @returns String representation of object
*/
function inspect(obj: any, options?: InspectOptions): string;Usage Examples:
import { inspect } from "@ember/debug";
export default class DebuggingService extends Service {
@tracked debugData = null;
@action
captureState() {
const appState = {
currentUser: this.session.currentUser,
route: this.router.currentRouteName,
queryParams: this.router.currentRoute.queryParams,
timestamp: new Date()
};
// Create detailed inspection for debugging
const inspected = inspect(appState, {
depth: 3,
showHidden: false,
showProxy: true
});
console.log('Application state:', inspected);
this.debugData = inspected;
}
@action
inspectObject(object) {
console.log('Object details:', inspect(object));
// Different inspection levels
console.log('Shallow:', inspect(object, { depth: 1 }));
console.log('Deep:', inspect(object, { depth: 5 }));
}
}Adapter classes for integrating with browser developer tools.
/**
* Container debug adapter for inspecting dependency injection container
*/
class ContainerDebugAdapter extends EmberObject {
/**
* Create container debug adapter
* @param properties - Adapter properties
* @returns ContainerDebugAdapter instance
*/
static create(properties?: object): ContainerDebugAdapter;
/**
* Get all registered factories by type
* @param type - Factory type (e.g., 'service', 'route', 'component')
* @returns Array of factory information
*/
catalogEntriesByType(type: string): FactoryInfo[];
/**
* Get container information
* @returns Container debug information
*/
getContainerInfo(): ContainerInfo;
}
/**
* Data adapter for inspecting data layer (typically for Ember Data)
*/
class DataAdapter extends EmberObject {
/**
* Create data debug adapter
* @param properties - Adapter properties
* @returns DataAdapter instance
*/
static create(properties?: object): DataAdapter;
/**
* Get model types for data inspector
* @returns Array of model type information
*/
getModelTypes(): ModelTypeInfo[];
/**
* Get records for a model type
* @param modelType - Model type to get records for
* @returns Array of record information
*/
getRecords(modelType: string): RecordInfo[];
/**
* Watch model type for changes
* @param modelType - Model type to watch
* @param recordsAdded - Callback for added records
* @param recordsUpdated - Callback for updated records
* @param recordsRemoved - Callback for removed records
* @returns Release function to stop watching
*/
watchModelType(
modelType: string,
recordsAdded: (records: any[]) => void,
recordsUpdated: (records: any[]) => void,
recordsRemoved: (records: any[]) => void
): () => void;
}Development-time error handling and reporting utilities.
/**
* Register global error handler for development debugging
* @param handler - Error handling function
*/
function registerErrorHandler(handler: (error: Error) => void): void;
/**
* Register warning handler for custom warning processing
* @param handler - Warning handling function
*/
function registerWarnHandler(handler: (message: string, options: any, next: Function) => void): void;
/**
* Register deprecation handler for custom deprecation processing
* @param handler - Deprecation handling function
*/
function registerDeprecationHandler(handler: (message: string, options: any, next: Function) => void): void;Usage Examples:
import {
registerErrorHandler,
registerWarnHandler,
registerDeprecationHandler
} from "@ember/debug";
// Custom error tracking in development
if (ENV.environment === 'development') {
registerErrorHandler((error) => {
console.group('🚨 Ember Error');
console.error('Error:', error.message);
console.error('Stack:', error.stack);
console.error('Context:', {
route: window.location.pathname,
timestamp: new Date().toISOString()
});
console.groupEnd();
// Send to error tracking service
this.errorTracking.captureException(error);
});
registerWarnHandler((message, options, next) => {
// Custom warning processing
console.warn(`⚠️ Warning: ${message}`, options);
// Log to analytics
this.analytics.track('ember-warning', {
message,
id: options?.id,
url: options?.url
});
// Call default handler
next(message, options);
});
registerDeprecationHandler((message, options, next) => {
// Track deprecation usage
this.analytics.track('ember-deprecation', {
message,
id: options?.id,
until: options?.until
});
// Call default handler
next(message, options);
});
}Additional utilities for development and debugging workflows.
/**
* Get Ember version information
* @returns Version string
*/
function getEmberVersion(): string;
/**
* Check if running in development environment
* @returns Whether in development mode
*/
function isDevelopment(): boolean;
/**
* Check if running in testing environment
* @returns Whether in testing mode
*/
function isTesting(): boolean;
/**
* Enable or disable specific debug features
* @param feature - Feature name to toggle
* @param enabled - Whether to enable the feature
*/
function toggleDebugFeature(feature: string, enabled: boolean): void;Usage Examples:
import {
getEmberVersion,
isDevelopment,
isTesting,
toggleDebugFeature
} from "@ember/debug";
export default class ApplicationController extends Controller {
init() {
super.init(...arguments);
if (isDevelopment()) {
console.log(`Running Ember ${getEmberVersion()}`);
// Enable additional debugging features
toggleDebugFeature('ds-warn-on-unknown-keys', true);
toggleDebugFeature('ds-improve-debug', true);
// Add global debugging helpers
window.debugApp = this;
window.inspectRoute = () => {
const route = this.router.currentRoute;
console.log('Current route:', inspect(route));
};
}
if (isTesting()) {
// Disable certain features in testing
toggleDebugFeature('ds-warn-on-unknown-keys', false);
}
}
}interface WarnOptions {
/** Unique identifier for this warning */
id?: string;
/** URL with more information */
url?: string;
}
interface DeprecateOptions {
/** Unique identifier for this deprecation */
id: string;
/** Version when this will be removed */
until: string;
/** URL with migration information */
url?: string;
/** Additional context */
for?: string;
/** Since which version this is deprecated */
since?: string;
}
interface InspectOptions {
/** Maximum depth to inspect */
depth?: number;
/** Show hidden properties */
showHidden?: boolean;
/** Show proxy information */
showProxy?: boolean;
/** Custom colors */
colors?: boolean;
}
interface FactoryInfo {
/** Factory name */
name: string;
/** Factory type */
type: string;
/** Whether factory is singleton */
singleton: boolean;
/** Whether factory is instantiable */
instantiate: boolean;
}
interface ContainerInfo {
/** Registered factories */
registrations: Record<string, any>;
/** Container cache */
cache: Record<string, any>;
/** Factory cache */
factoryManagerCache: Record<string, any>;
}
interface ModelTypeInfo {
/** Model name */
name: string;
/** Model count */
count: number;
/** Model columns/attributes */
columns: ColumnInfo[];
}
interface RecordInfo {
/** Record identifier */
id: string;
/** Record attributes */
attributes: Record<string, any>;
/** Record relationships */
relationships: Record<string, any>;
}
interface ColumnInfo {
/** Column name */
name: string;
/** Column description */
desc: string;
}