CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tsyringe

Lightweight dependency injection container for JavaScript/TypeScript

Pending
Overview
Eval results
Files

dependency-container.mddocs/

Dependency Container

Core container interface providing comprehensive dependency registration, resolution, and lifecycle management with support for hierarchical child containers and resource disposal.

Capabilities

Global Container Instance

Pre-configured global container instance ready for immediate use.

/**
 * Global dependency container instance
 * Pre-created container available for immediate dependency registration and resolution
 */
const container: DependencyContainer;

Usage Examples:

import { container } from "tsyringe";

// Register dependencies
container.register("ApiUrl", { useValue: "https://api.example.com" });
container.registerSingleton(DatabaseService);

// Resolve dependencies
const apiUrl = container.resolve<string>("ApiUrl");
const dbService = container.resolve(DatabaseService);

Registration Methods

Register dependencies using various provider types and configuration options.

/**
 * Register a dependency with flexible provider options
 * Multiple overloads support different provider types
 */
register<T>(token: InjectionToken<T>, provider: ValueProvider<T>): DependencyContainer;
register<T>(token: InjectionToken<T>, provider: FactoryProvider<T>): DependencyContainer;
register<T>(token: InjectionToken<T>, provider: TokenProvider<T>, options?: RegistrationOptions): DependencyContainer;
register<T>(token: InjectionToken<T>, provider: ClassProvider<T>, options?: RegistrationOptions): DependencyContainer;
register<T>(token: InjectionToken<T>, provider: constructor<T>, options?: RegistrationOptions): DependencyContainer;

/**
 * Register a singleton dependency (shared instance across container)
 */
registerSingleton<T>(from: InjectionToken<T>, to: constructor<T>): DependencyContainer;
registerSingleton<T>(token: constructor<T>): DependencyContainer;

/**
 * Register a type mapping (alias one token to another)
 */
registerType<T>(from: InjectionToken<T>, to: InjectionToken<T>): DependencyContainer;

/**
 * Register a concrete instance directly
 */
registerInstance<T>(token: InjectionToken<T>, instance: T): DependencyContainer;

Usage Examples:

// Value provider
container.register("config", { useValue: { apiUrl: "https://api.com" } });

// Factory provider
container.register("logger", { 
  useFactory: (c) => new Logger(c.resolve("config"))
});

// Class provider
container.register("UserService", UserService, { lifecycle: Lifecycle.Singleton });

// Constructor shorthand
container.register("UserService", UserService);

// Singleton registration
container.registerSingleton(DatabaseService);
container.registerSingleton("IUserRepo", UserRepository);

// Type mapping
container.registerType("ILogger", "ConsoleLogger");

// Instance registration
container.registerInstance("startTime", new Date());

Resolution Methods

Resolve registered dependencies with single or multiple instance support.

/**
 * Resolve a single instance of the registered dependency
 * @param token - The injection token to resolve
 * @returns Resolved instance of type T
 */
resolve<T>(token: InjectionToken<T>): T;

/**
 * Resolve all registered instances for a token (useful for plugin patterns)
 * @param token - The injection token to resolve all instances for
 * @returns Array of all resolved instances
 */
resolveAll<T>(token: InjectionToken<T>): T[];

Usage Examples:

// Single resolution
const userService = container.resolve<UserService>("UserService");
const logger = container.resolve(Logger);

// Multiple resolution (all registered instances)
const plugins = container.resolveAll<Plugin>("Plugin");
const validators = container.resolveAll<Validator>("Validator");

Container Management

Create child containers and manage container hierarchy for scoped dependency management.

/**
 * Create a child container that inherits from this container
 * Child containers can override parent registrations
 * @returns New child DependencyContainer instance
 */
createChildContainer(): DependencyContainer;

/**
 * Check if a token is registered in this container
 * @param token - Token to check registration for
 * @param recursive - Whether to check parent containers (default: true)
 * @returns True if token is registered
 */
isRegistered<T>(token: InjectionToken<T>, recursive?: boolean): boolean;

/**
 * Clear all registrations from this container
 * Does not affect parent containers
 */
reset(): void;

/**
 * Clear all cached instances but keep registrations
 * Forces fresh instance creation on next resolve
 */
clearInstances(): void;

Usage Examples:

// Child container usage
const childContainer = container.createChildContainer();
childContainer.register("ChildService", ChildService);

const hasService = childContainer.isRegistered("UserService"); // true (inherited)
const hasChild = container.isRegistered("ChildService"); // false (child-only)

// Container management
container.reset(); // Clear all registrations
container.clearInstances(); // Clear cached instances only

Interception Hooks

Register callbacks for pre and post resolution interception to customize dependency behavior.

/**
 * Register a callback to execute before dependency resolution
 * @param token - Token to intercept
 * @param callback - Callback function to execute
 * @param options - Interception options
 */
beforeResolution<T>(
  token: InjectionToken<T>,
  callback: PreResolutionInterceptorCallback<T>,
  options?: InterceptorOptions
): void;

/**
 * Register a callback to execute after dependency resolution
 * @param token - Token to intercept
 * @param callback - Callback function to execute
 * @param options - Interception options
 */
afterResolution<T>(
  token: InjectionToken<T>,
  callback: PostResolutionInterceptorCallback<T>,
  options?: InterceptorOptions
): void;

Usage Examples:

// Logging interceptor
container.beforeResolution("UserService", (token, resolutionType) => {
  console.log(`Resolving ${String(token)} as ${resolutionType}`);
});

container.afterResolution("UserService", (token, result, resolutionType) => {
  console.log(`Resolved ${String(token)}: ${result}`);
});

// One-time interceptor
container.afterResolution(
  "DatabaseService",
  (token, result) => console.log("Database connected"),
  { frequency: "Once" }
);

Resource Disposal

Dispose the container and all registered disposable resources.

/**
 * Dispose the container and all registered disposable resources
 * Calls dispose() on all instances that implement Disposable interface
 * @returns Promise that resolves when all disposals complete
 */
dispose(): Promise<void>;

Usage Examples:

// Proper cleanup
class DatabaseService implements Disposable {
  async dispose() {
    await this.connection.close();
  }
}

container.registerSingleton(DatabaseService);

// Later, cleanup all resources
await container.dispose();

Types

// Main container interface
interface DependencyContainer extends Disposable {
  register<T>(token: InjectionToken<T>, provider: Provider<T>, options?: RegistrationOptions): DependencyContainer;
  registerSingleton<T>(from: InjectionToken<T>, to?: constructor<T>): DependencyContainer;
  registerType<T>(from: InjectionToken<T>, to: InjectionToken<T>): DependencyContainer;
  registerInstance<T>(token: InjectionToken<T>, instance: T): DependencyContainer;
  resolve<T>(token: InjectionToken<T>): T;
  resolveAll<T>(token: InjectionToken<T>): T[];
  isRegistered<T>(token: InjectionToken<T>, recursive?: boolean): boolean;
  reset(): void;
  clearInstances(): void;
  createChildContainer(): DependencyContainer;
  beforeResolution<T>(token: InjectionToken<T>, callback: PreResolutionInterceptorCallback<T>, options?: InterceptorOptions): void;
  afterResolution<T>(token: InjectionToken<T>, callback: PostResolutionInterceptorCallback<T>, options?: InterceptorOptions): void;
  dispose(): Promise<void>;
}

// Interceptor options
interface InterceptorOptions {
  frequency: Frequency;
}

// Callback types
type PreResolutionInterceptorCallback<T> = (token: InjectionToken<T>, resolutionType: ResolutionType) => void;
type PostResolutionInterceptorCallback<T> = (token: InjectionToken<T>, result: T | T[], resolutionType: ResolutionType) => void;

Install with Tessl CLI

npx tessl i tessl/npm-tsyringe

docs

decorators.md

dependency-container.md

factories.md

index.md

lazy-loading.md

lifecycle-management.md

providers.md

tile.json