or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

application-engine.mdcomponents.mdcontrollers.mddata-structures.mddebugging-development.mddestroyables-cleanup.mdindex.mdmodifiers.mdobject-model.mdreactivity-tracking.mdrouting.mdservices.mdtemplates-rendering.mdtesting.mdutilities.md
tile.json

services.mddocs/

Services

Singleton service system for managing application-wide state and functionality with dependency injection.

Capabilities

Service Class

Base class for creating singleton services that persist across the application lifecycle.

/**
 * Base class for creating singleton services that persist across the application lifecycle
 */
class Service {
  /**
   * Create new service class with additional properties
   * @param properties - Service properties and methods
   * @returns New Service subclass
   */
  static extend(properties?: object): typeof Service;
  
  /**
   * Initialize service when first accessed
   */
  init(): void;
  
  /**
   * Destroy service and clean up resources
   */
  destroy(): void;
  
  /** Whether service is being destroyed */
  isDestroying: boolean;
  
  /** Whether service has been destroyed */
  isDestroyed: boolean;
}

Service Injection

Decorators and functions for injecting services into objects.

/**
 * Modern decorator for injecting services
 * @param serviceName - Name of service to inject (optional, defaults to property name)
 * @returns Property decorator
 */
function service(serviceName?: string): PropertyDecorator;

/**
 * Legacy service injection object with named injection methods
 */
interface ServiceInjection {
  /**
   * Inject service by name
   * @param serviceName - Name of service to inject (optional)
   * @returns Injected service property
   */
  (serviceName?: string): any;
}

/** Legacy service injection helper */
declare const inject: {
  service: ServiceInjection;
};

Usage Examples:

import Service, { service } from "@ember/service";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";

// Create a service
export default class SessionService extends Service {
  @tracked currentUser = null;
  @tracked isAuthenticated = false;
  
  @action
  async login(username, password) {
    try {
      const response = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username, password })
      });
      
      if (response.ok) {
        this.currentUser = await response.json();
        this.isAuthenticated = true;
        return true;
      }
      return false;
    } catch (error) {
      console.error('Login failed:', error);
      return false;
    }
  }
  
  @action
  logout() {
    this.currentUser = null;
    this.isAuthenticated = false;
  }
}

// Use service in component
import Component from "@glimmer/component";
import { service } from "@ember/service";
import { action } from "@ember/object";

export default class LoginComponent extends Component {
  @service session;
  @service router;
  
  @action
  async handleLogin(event) {
    event.preventDefault();
    const formData = new FormData(event.target);
    const username = formData.get('username');
    const password = formData.get('password');
    
    const success = await this.session.login(username, password);
    if (success) {
      this.router.transitionTo('dashboard');
    }
  }
  
  get isLoggedIn() {
    return this.session.isAuthenticated;
  }
}

// Legacy injection syntax
import Component from "@ember/component";
import { inject as service } from "@ember/service";

export default Component.extend({
  session: service(),
  notifications: service('notification-manager'),
  
  actions: {
    logout() {
      this.session.logout();
      this.notifications.success('Logged out successfully');
    }
  }
});

Built-in Services

Core services provided by Ember.js framework.

/**
 * Router service for programmatic navigation
 */
class RouterService extends Service {
  transitionTo(routeName: string, ...models: any[]): Transition;
  replaceWith(routeName: string, ...models: any[]): Transition;
  urlFor(routeName: string, ...models: any[]): string;
  isActive(routeName: string, ...models: any[]): boolean;
  currentURL: string;
  currentRouteName: string;
}

/**
 * Store service for data management (when using Ember Data)
 */
class StoreService extends Service {
  findRecord(modelName: string, id: string | number): Promise<any>;
  findAll(modelName: string): Promise<any[]>;
  createRecord(modelName: string, properties?: object): any;
  deleteRecord(record: any): void;
}

Service Registration

Functions for registering custom services with the dependency injection container.

/**
 * Register a service with the application container
 * @param application - Application instance
 * @param name - Service name
 * @param serviceClass - Service class to register
 */
function registerService(application: Application, name: string, serviceClass: typeof Service): void;

/**
 * Lookup a service instance from the container
 * @param owner - Container owner
 * @param serviceName - Name of service to lookup
 * @returns Service instance
 */
function lookupService(owner: Owner, serviceName: string): Service;

Usage Examples:

// Register service during application initialization
import Application from "@ember/application";
import ApiService from "./services/api";

const App = Application.create();

// Register service
App.register('service:api', ApiService);

// Or register in an initializer
export function initialize(application) {
  application.register('service:analytics', AnalyticsService);
  
  // Inject into all routes
  application.inject('route', 'analytics', 'service:analytics');
  
  // Inject into all components
  application.inject('component', 'analytics', 'service:analytics');
}

export default {
  name: 'analytics',
  initialize
};

Service Lifecycle

Service lifecycle management and cleanup.

/**
 * Service lifecycle hooks
 */
interface ServiceLifecycle {
  /**
   * Called when service is first accessed
   */
  init(): void;
  
  /**
   * Called when application is being destroyed
   */
  willDestroy(): void;
  
  /**
   * Called after service is destroyed
   */
  destroy(): void;
}

Usage Examples:

import Service from "@ember/service";
import { tracked } from "@glimmer/tracking";

export default class WebSocketService extends Service {
  @tracked isConnected = false;
  
  socket = null;
  
  init() {
    super.init();
    this.connect();
  }
  
  connect() {
    this.socket = new WebSocket('ws://localhost:8080');
    
    this.socket.onopen = () => {
      this.isConnected = true;
      console.log('WebSocket connected');
    };
    
    this.socket.onclose = () => {
      this.isConnected = false;
      console.log('WebSocket disconnected');
    };
  }
  
  send(message) {
    if (this.isConnected) {
      this.socket.send(JSON.stringify(message));
    }
  }
  
  willDestroy() {
    super.willDestroy();
    if (this.socket) {
      this.socket.close();
    }
  }
}

Types

interface ServiceDefinition {
  /** Service class constructor */
  new (): Service;
}

interface InjectedService {
  /** Injected service instance */
  [key: string]: Service;
}

interface ServiceRegistry {
  /** Register service type */
  [serviceName: string]: ServiceDefinition;
}