/** * Core dependency injection container. * * DiContainer provides: * - Token-based dependency registration and resolution * - Hierarchical provider lookup (parent-child registries) * - GLOBAL and CONTEXT scoped providers * - Dependency graph with cycle detection * - Topological sorting for initialization order * * This is the base container that can be extended with additional * features like session caching. */ import 'reflect-metadata'; import type { Token } from '../interfaces/base.interface.js'; import type { ProviderType } from '../interfaces/provider.interface.js'; import type { DiContainerInterface, DiViews } from '../interfaces/registry.interface.js'; import { type ProviderRecord, type ProviderInjectedRecord } from '../records/provider.record.js'; import { ProviderScope } from '../metadata/provider.metadata.js'; import { RegistryAbstract, type RegistryBuildMapResult } from './registry.base.js'; import { type ProviderTokens } from '../utils/provider.utils.js'; /** * Entry wrapper for provider instances. * Can be extended by subclasses with additional metadata. */ export interface ProviderEntry { instance: unknown; } /** * Options for creating a DiContainer. */ export interface DiContainerOptions { /** * Metadata tokens for reading provider information from decorated classes. * If not provided, only static metadata and object-style providers are supported. */ providerTokens?: ProviderTokens; /** * Timeout for async operations in milliseconds. * @default 30000 */ asyncTimeoutMs?: number; } /** * Core dependency injection container. * * @typeParam ParentType - Type of the parent container (for hierarchy) * * @example * ```typescript * class MyService { * static metadata = { name: 'MyService', scope: ProviderScope.GLOBAL }; * } * * const container = new DiContainer([MyService]); * await container.ready; * * const service = container.get(MyService); * ``` */ export declare class DiContainer | undefined = undefined> extends RegistryAbstract implements DiContainerInterface { /** Topological order for initialization (deps first) */ private order; /** Provider normalizer function */ private readonly normalizeProvider; /** Parent container for hierarchical lookup */ private readonly parentContainer; /** * Create a new DI container. * * @param providers - Array of provider definitions * @param parent - Optional parent container for hierarchical lookup * @param options - Container configuration options */ constructor(providers: ProviderType[], parent?: ParentType, options?: DiContainerOptions); /** * Walk up the registry chain to find a def for a token. */ private lookupDefInHierarchy; /** * Resolve a GLOBAL-scoped dependency from the hierarchy. */ private resolveDefaultFromHierarchy; protected buildMap(list: ProviderType[]): RegistryBuildMapResult; protected buildGraph(): void; /** * Topological sort with cycle detection. */ protected topoSort(): void; protected initialize(opts?: { force?: boolean; onlyTokens?: Iterable; }): Promise; private withTimeout; private resolveFactoryArg; private instantiateOne; /** * Build a scoped provider into the given store. */ protected buildIntoStore(token: Token, rec: ProviderRecord, store: Map): Promise; private resolveManagedForClass; /** * Get a GLOBAL-scoped provider by token. * * @throws If the provider is scoped or not registered */ get(token: Token): T; /** * Resolve a dependency by token or class. * If not registered, attempts to construct the class directly. */ resolve(cls: Token): T; /** * Try to get a provider, returning undefined if not found. */ tryGet(token: Token): T | undefined; /** * Normalize deprecated scopes to their modern equivalents. */ private normalizeScope; /** * Get the scope of a provider record. */ getProviderScope(rec: ProviderRecord): ProviderScope; /** * Get all discovered dependencies for a provider record. */ discoveryDeps(rec: ProviderRecord): Token[]; /** * Get invocation tokens for a provider record. */ invocationTokens(_token: Token, rec: ProviderRecord): Token[]; /** * Return the singleton map as a read-only view. */ getAllSingletons(): ReadonlyMap; /** * Build provider views for different scopes. * * @param sessionKey - Unique key for this context/session * @param contextProviders - Optional pre-built CONTEXT providers * @returns Views with global and context provider maps */ buildViews(sessionKey: string, contextProviders?: Map): Promise; private buildIntoStoreWithViews; private resolveFromViews; /** * Get a provider from views. */ getScoped(token: Token, views: DiViews): T; /** * Inject a pre-instantiated provider. */ injectProvider(injected: Omit): void; }