/** * @license * Copyright 2025 Steven Roussey * SPDX-License-Identifier: Apache-2.0 */ /** * Simple dependency injection container for managing service instances and dependencies */ export declare class Container { private services; private factories; private singletons; private resolving; /** * Tokens whose cached instance was inherited from a parent container (via * {@link createChildContainer}). These instances are owned by the parent, so * disposing this container must NOT dispose them. */ private inheritedServices; /** * In-flight eviction disposals keyed by token. `register()` and * `registerInstance()` invoke the previous singleton's disposer without * blocking the registration; the returned promise lives here so * {@link dispose} and {@link awaitReplacement} can drain it. When the same * token is replaced again while its prior disposal is still running, the new * entry chains onto the prior one (see {@link trackDisposal}) so a rapid * re-replace never drops an in-flight disposer from the drain set. Entries are * identity-guarded so a subsequent replacement's promise doesn't get erased * by an earlier disposer's `.finally()`. */ private readonly pendingDisposals; /** * Register a service factory. Replacing a factory disposes the previously * cached singleton (if any) so a held resource — DB connection, file * handle, subscriber — is released before the new factory takes effect. * Inherited (parent-owned) instances are skipped here; the parent owns the * lifetime. * @param token The identifier token for the service * @param factory A factory function that creates the service * @param singleton Whether the service should be a singleton (created once) */ register(token: string, factory: () => T, singleton?: boolean): void; /** * Register a service factory only if the token is not already registered. * This is an atomic check-and-register to avoid TOCTOU races. * @param token The identifier token for the service * @param factory A factory function that creates the service * @param singleton Whether the service should be a singleton (created once) */ registerIfAbsent(token: string, factory: () => T, singleton?: boolean): void; /** * Register an instance as a service. If a previously cached singleton exists * under this token (and was not inherited from a parent), it is disposed * before being overwritten. * @param token The identifier token for the service * @param instance The instance to register */ registerInstance(token: string, instance: T): void; /** * Get a service by its token * @param token The identifier token for the service * @returns The service instance */ get(token: string): T; /** * Check if a service is registered * @param token The identifier token for the service * @returns True if the service is registered */ has(token: string): boolean; /** * Remove a service registration * @param token The identifier token for the service */ remove(token: string): void; /** * Dispose all instantiated singleton services and clear registrations. * Services implementing dispose(), Symbol.asyncDispose, or Symbol.dispose will be cleaned up. * * Also drains any eviction disposals scheduled by prior `register` / * `registerInstance` replacements — otherwise the container would clear its * state (and reject subsequent lookups) while asynchronous disposers were * still holding resources open. */ dispose(): Promise; /** * Resolves once the in-flight eviction disposal for `token` (if any) has * settled. Callers that immediately re-`register` and then need to observe * side effects of the prior disposer (e.g. a released DB connection) can * `await awaitReplacement(token)` between the two operations. */ awaitReplacement(token: string): Promise; /** Drains every in-flight eviction disposal. */ awaitRegistrations(): Promise; /** * Track an in-flight eviction disposal so callers (and {@link dispose}) can * drain it. If a prior disposal for the same token is still in flight, the new * one chains onto it so the map's single per-token entry settles only once * BOTH have settled — otherwise a rapid re-replace would overwrite (and thus * orphan) the earlier disposer, and `dispose()`/`awaitRegistrations` would * resolve while it still held its resource open. Identity-guarded: the * `.finally()` only clears the entry if it is still the tracked promise, so a * later replacement's promise is never erased. */ private trackDisposal; /** * Eviction-path disposer used by {@link register} and {@link registerInstance} * when a cached singleton is replaced. Errors are caught here so a buggy * disposer cannot prevent the new registration from taking effect — util has * no logger dependency, hence console.warn. */ private disposeService; /** Invoke whichever disposer protocol the service implements. */ private invokeDisposer; [Symbol.asyncDispose](): Promise; /** * Create a child container that inherits registrations from the parent * @returns A new child container */ createChildContainer(): Container; } export declare const globalContainer: Container; //# sourceMappingURL=Container.d.ts.map