/** * Container — dependency injection with explicit bind / override / decorate. * * Invariants: * bind() — throws if token already bound * override() — throws if nothing to replace * decorate() — stacks; cached value cleared on register */ export type Token = symbol & { readonly __type?: T; }; export type Factory = (c: Container) => T; export type Decorator = (inner: T, c: Container) => T; export interface BindOptions { singleton?: boolean | undefined; owner?: string | undefined; } export declare class Container { private readonly entries; /** * Tokens currently mid-resolve. Tracked so we can detect circular * dependencies (A → B → A) and throw a structured error instead of * overflowing the call stack with "Maximum call stack size exceeded". * * Not a memoization cache — the per-entry `cache` field is the source * of truth for "have I built this before?". This set only lives for * the duration of a single resolve call. */ private readonly resolving; bind(token: Token, factory: Factory, opts?: BindOptions): void; override(token: Token, factory: Factory, opts?: BindOptions): void; decorate(token: Token, decorator: Decorator, owner?: string): void; resolve(token: Token): T; /** * Build a human-readable description of the dependency cycle that * caused the resolution to re-enter. Lists the tokens in the order * they were entered, then appends the re-entered token to close the * loop. Falls back to a generic message if the resolving set is * somehow empty (shouldn't happen, but defensive). */ private describeCycle; has(token: Token): boolean; /** * Resolve a token if it is bound, otherwise return undefined. * Unlike `resolve()`, this does not throw if the token is unbound. * * Single map lookup — `has()` + `resolve()` would walk the entries * map twice. The bound check is folded into the resolve path so a * non-existent token can never enter the `resolving` cycle-detection * set. */ safeResolve(token: Token): T | undefined; ownerOf(token: Token): string | undefined; /** * Remove a token's binding (along with any decorators stacked on it). * Returns true if the token existed. Use this to withdraw temporary * bindings installed by a short-lived run or plugin — without it, the * entry persists in the map forever. */ unbind(token: Token): boolean; /** * Drop every binding. Intended for tests and short-lived CLI invocations * that rebuild the container from scratch. Production code should prefer * `unbind` on the specific tokens it owns. */ clear(): void; list(): Array<{ token: symbol; owner: string; }>; /** * Inspect a binding's full shape, including decorator count and whether * a singleton value is cached. Returns null if the token is unbound. * Decorator and factory function references are not exposed — only counts * and metadata, to keep internal state hidden. */ inspect(token: Token): { owner: string; singleton: boolean; decoratorCount: number; cached: boolean; } | null; } //# sourceMappingURL=container.d.ts.map