UNPKG

async-injection

Version:

A robust lightweight dependency injection library for TypeScript.

90 lines (89 loc) 4.98 kB
import { AsyncFactory, BindAs, Binder, SyncFactory } from './binder.js'; import { AbstractConstructor, ClassConstructor, InjectableId, Injector } from './injector.js'; import { Provider } from './provider.js'; import { State } from './state.js'; /** * Binder and Injector (aka Container) to handle (a)synchronous dependency management. */ export declare class Container implements Binder { protected parent?: Injector; /** * Create a new Container, with an optional parent Injector which will be searched if any given InjectableId is not bound within this Container. */ constructor(parent?: Injector); protected providers: Map<InjectableId<any>, Provider<any>>; /** * @inheritDoc */ isIdKnown<T>(id: InjectableId<T>, ascending?: boolean): boolean; /** * @inheritDoc */ get<T>(id: InjectableId<T>): T; /** * @inheritDoc */ resolve<T>(id: InjectableId<T>): Promise<T>; /** * This method is not part of the Binding interface, because it is highly unusual. * But that doesn't mean we can't imagine scenarios where you might require it. * * @param id The id to be removed. * @param ascending If true, this will remove all bindings of the specified id all the way up the parent container chain (if it exists). * @param releaseIfSingleton If true, @Provider.releaseIfSingleton will be invoked before the binding is removed. */ removeBinding<T>(id: InjectableId<T>, ascending?: boolean, releaseIfSingleton?: boolean): void; /** * @inheritDoc */ bindConstant<T>(id: InjectableId<T>, value: T): T; /** * @inheritDoc */ bindClass<T>(id: ClassConstructor<T>, constructor?: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>; bindClass<T>(id: string | symbol | AbstractConstructor<T> | InjectableId<T>, constructor: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>; /** * @inheritDoc */ bindFactory<T>(id: InjectableId<T>, factory: SyncFactory<T>): BindAs<T, SyncFactory<T>>; /** * @inheritDoc */ bindAsyncFactory<T>(id: InjectableId<T>, factory: AsyncFactory<T>): BindAs<T, AsyncFactory<T>>; /** * @inheritDoc */ resolveSingletons(asyncOnly?: boolean, parentRecursion?: boolean): Promise<this>; /** * As implied by the name prefix, this is a factored out method invoked only by the 'resolve' method. * It makes searching our parent (if it exists) easier (and quicker) IF our parent is a fellow instance of Container. */ protected resolveState<T>(id: InjectableId<T>): State<T>; /** * Convenience method to assist in releasing non-garbage-collectable resources that Singletons in this Container may have allocated. * It will walk through all registered Providers (of this Container only), and invoke their @see Provider.releaseIfSingleton method. * This method is not part of the Binding interface, because you normally only create (and release) Containers. * NOTE: * This *only* releases active/pending Singleton's that have already been created by this Container. * The most likely use of this method would be when you have created a new child Container for a limited duration transaction, and you want to easily cleanup temporary resources. * For example, your service object may need to know when it should unsubscribe from an RxJs stream (failure to do so can result in your Singleton not being garbage collected at the end of a transaction). * In theory, you could handle all unsubscription and cleanup yourself, but the @Release decorator and this method are meant to simply make that easier. */ releaseSingletons(): void; /** * Make a copy of this @see Container. * This is an experimental feature! * I have not thought through all the dark corners, so use at your own peril! * Here are some notes: * The injector parameter for SyncFactory and AsyncFactory callbacks will be the Container invoking the factory. * So a factory that uses a parent closure instead of the supplied injector may get unexpected results. * The injector parameter for OnSuccess and OnError callbacks will be the Container performing the resolution. * Singletons are cloned at their *existing* state.. * If resolved in "this" container, they will not be re-resolved for the clone. * If released by the clone, they will be considered released by "this" container. * If a singleton is currently being asynchronously constructed any callbacks will reference "this" Container, however both Containers should have no problem awaiting resolution. * If a singleton is not resolved when the container is cloned, then if both containers resolve, you will create *two* "singletons". * The way to avoid this last effect is to @see resolveSingletons */ clone(clazz?: ClassConstructor<Container>): Container; }