import { AnyFn } from '#types/mix.js'; import { InjectionToken } from './injection-token.js'; import { DualKey } from './key-registry.js'; import { Class, Dependency, NormalizedProvider, ParamsMeta, Provider, RegistryOfInjector, ResolvedFactory, ResolvedProvider, Visibility } from './types-and-models.js'; /** * A dependency injection container used for instantiating objects and resolving * dependencies. * * An `Injector` is a replacement for a `new` operator, which can automatically resolve the * constructor dependencies. * * In typical use, application code asks for the dependencies in the constructor and they are * resolved by the `Injector`. * * ### Example * * The following example creates an `Injector` configured to create `Engine` and `Car`. * ```ts @injectable() class Engine { } @injectable() class Car { constructor(public engine:Engine) {} } const injector = Injector.resolveAndCreate([Car, Engine]); const car = injector.get(Car); expect(car instanceof Car).toBe(true); expect(car.engine instanceof Engine).toBe(true); ``` * * Notice, we don't use the `new` operator because we explicitly want to have the `Injector` * resolve all of the object's dependencies automatically. */ export declare class Injector { #private; protected readonly injectorName?: string | undefined; /** * @param injectorName Injector name. Useful for debugging. */ constructor(Registry: typeof RegistryOfInjector, parent?: Injector, injectorName?: string | undefined); /** * Turns an array of provider definitions into an array of resolved providers. * * A resolution is a process of converting individual * providers into an array of `ResolvedProvider`. * * ### Example * ```ts import { injectable, Injector } from '@ditsmod/core'; @injectable() class Engine {} @injectable() class Car { constructor(public engine: Engine) {} } const providers = Injector.resolve([Car, Engine]); console.log(providers[0].resolvedFactories[0].dependencies); ``` * * See `fromResolvedProviders` for more info. */ static resolve(providers: Provider[]): ResolvedProvider[]; /** * Create new or extends existing class of registry. Where "class of registry" means * just class that has resolved providers in its prototype, * where property names are taken from resolved providers IDs. * * @param Registry If provided, `providers` extends the `Registry`. */ static prepareRegistry(providers: ResolvedProvider[], Registry?: typeof RegistryOfInjector): typeof RegistryOfInjector; /** * Resolves an array of providers and creates an injector from those providers. * * The passed-in providers can be an array of `Class`, `Provider`. * * ### Example * ```ts @injectable() class Engine { } @injectable() class Car { constructor(public engine:Engine) {} } const injector = Injector.resolveAndCreate([Car, Engine]); expect(injector.get(Car) instanceof Car).toBe(true); ``` * * This function is slower than the corresponding `fromResolvedProviders` * because it needs to resolve the passed-in providers first. * See `Injector.resolve()` and `Injector.fromResolvedProviders()`. * * @param injectorName Injector name. Useful for debugging. */ static resolveAndCreate(providers: Provider[], injectorName?: string): Injector; /** * Creates an injector from previously resolved providers. * * This API is the recommended way to construct injectors in performance-sensitive parts. * * ### Example * ```ts @injectable() class Engine { } @injectable() class Car { constructor(public engine:Engine) {} } const providers = Injector.resolve([Car, Engine]); const injector = Injector.fromResolvedProviders(providers); expect(injector.get(Car) instanceof Car).toBe(true); ``` * * @param injectorName Injector name. Useful for debugging. */ static fromResolvedProviders(providers: ResolvedProvider[], injectorName?: string): Injector; protected static normalizeProviders(providers: Provider[], normProviders: NormalizedProvider[]): NormalizedProvider[]; /** * Resolve a single provider. */ protected static resolveProvider(provider: NormalizedProvider): ResolvedProvider[]; protected static getResolvedProvider(token: NonNullable, factoryFn: AnyFn, resolvedDeps: Dependency[], isMulti?: boolean): ResolvedProvider; /** * When an user give a class factory provider (eg. `{ useFactory: [Class, Class.prototype.factoryKey] }`), * "factory key" means "property key in class that has factory". */ protected static getFactoryKey(Cls: Class, factory: AnyFn): string | symbol; protected static getDependencies(Cls: Class, propertyKey?: string | symbol): Dependency[]; protected static extractPayload(paramsMeta: ParamsMeta): { token: any; ctx: any; isOptional: boolean; visibility: Visibility; }; /** * Merges a list of ResolvedProviders into a list where * each token is contained exactly once and multi providers * have been merged. */ protected static mergeResolvedProviders(resolvedProviders: ResolvedProvider[], normalizedProvidersMap: Map): Map; /** * Parent of this injector. * * ### Example * ```ts const parent = Injector.resolveAndCreate([]); const child = parent.resolveAndCreateChild([]); expect(child.parent).toBe(parent); ``` * */ get parent(): Injector | null; protected parentGetter(): Injector | null; setParentGetter(parentGetter: () => Injector | null): this; /** * Resolves an array of providers and creates a child injector from those providers. * * The passed-in providers can be an array of `Class` or `Provider`. * * ### Example * ```ts class ParentProvider {} class ChildProvider {} const parent = Injector.resolveAndCreate([ParentProvider]); const child = parent.resolveAndCreateChild([ChildProvider]); expect(child.get(ParentProvider) instanceof ParentProvider).toBe(true); expect(child.get(ChildProvider) instanceof ChildProvider).toBe(true); expect(child.get(ParentProvider)).toBe(parent.get(ParentProvider)); ``` * * This function is slower than the corresponding `createChildFromResolved` * because it needs to resolve the passed-in providers first. * * See `Injector.resolve()` and `Injector.createChildFromResolved()`. * * @param injectorName Injector name. Useful for debugging. */ resolveAndCreateChild(providers: Provider[], injectorName?: string): Injector; /** * Creates a child injector from previously resolved providers. * * This API is the recommended way to construct injectors in performance-sensitive parts. * * ### Example * ```ts class ParentProvider {} class ChildProvider {} const parentProviders = Injector.resolve([ParentProvider]); const childProviders = Injector.resolve([ChildProvider]); const parent = Injector.fromResolvedProviders(parentProviders); const child = parent.createChildFromResolved(childProviders); expect(child.get(ParentProvider) instanceof ParentProvider).toBe(true); expect(child.get(ChildProvider) instanceof ChildProvider).toBe(true); expect(child.get(ParentProvider)).toBe(parent.get(ParentProvider)); ``` * * @param injectorName Injector name. Useful for debugging. */ createChildFromResolved(providers: ResolvedProvider[], injectorName?: string): Injector; /** * Sets value in injector registry by its ID that is * generated by `KeyRegistry.get()` for given token. * * @param id The ID from KeyRegistry for some token. * @param value New value for this ID. */ setById(id: number, value: any): this; /** * Sets value in injector registry by its token. * * @param value New value for this ID. */ setByToken(token: NonNullable, value: any): this; clear(): void; /** * Resolves a provider and instantiates an object in the context of the injector. * * The created object does not get cached by the injector, but create the cache of its dependecies. * * ### Example * ```ts @injectable() class Engine { } @injectable() class Car { constructor(public engine:Engine) {} } const injector = Injector.resolveAndCreate([Engine]); const car = injector.resolveAndInstantiate(Car); expect(car.engine).toBe(injector.get(Engine)); expect(car).not.toBe(injector.resolveAndInstantiate(Car)); ``` */ resolveAndInstantiate(provider: Provider): any; /** * Retrieves an instance from the injector based on the provided token. * If not found, returns the `defaultValue` otherwise. */ get(token: Class | InjectionToken, visibility?: Visibility, defaultValue?: T): T; get(token: T, visibility?: Visibility, defaultValue?: T): ReturnType; get(token: NonNullable, visibility?: Visibility, defaultValue?: any): any; protected selectInjectorAndGet(dualKey: DualKey, parentTokens: any[], visibility: Visibility, defaultValue: any, ctx?: NonNullable): any; protected getOrThrow(injector: Injector | null, dualKey: DualKey, parentTokens: any[], defaultValue: any, visibility?: Visibility, ctx?: NonNullable): any; /** * Instantiates an object using a resolved provider in the context of the injector. * * The created object does not get cached by the injector, but create the cache of its dependecies. * * ### Example * ```ts @injectable() class Engine { } @injectable() class Car { constructor(public engine:Engine) {} } const injector = Injector.resolveAndCreate([Engine]); const carProvider = Injector.resolve([Car])[0]; const car = injector.instantiateResolved(carProvider); expect(car.engine).toBe(injector.get(Engine)); expect(car).not.toBe(injector.instantiateResolved(carProvider)); ``` */ instantiateResolved(provider: ResolvedProvider, parentTokens?: any[], ctx?: NonNullable): T; protected instantiate(token: NonNullable, parentTokens: any[], resolvedFactory: ResolvedFactory, ctx?: NonNullable): any; /** * If the nearest provider with the given token is in the parent injector, then * this method pulls that provider into the current injector. After that, it works * the same as `injector.get()`. If the nearest provider with the given token * is in the current injector, then this method behaves exactly like `injector.get()`. * * This method is useful if you don't use `ValueProvider` for requested token. And this method * is primarily useful because it allows you, in the context of the current injector, to create * instances of providers that depend on a particular configuration that may be different in * the current and parent injectors. * * ## Example * * ```ts import { injectable, Injector } from '@ditsmod/core'; class Config { one: any; two: any; } @injectable() class Service { constructor(public config: Config) {} } const parent = Injector.resolveAndCreate([Service, { token: Config, useValue: { one: 1, two: 2 } }]); const child = parent.resolveAndCreateChild([{ token: Config, useValue: { one: 11, two: 22 } }]); child.get(Service).config; // returns from parent injector: { one: 1, two: 2 } child.pull(Service).config; // pulls Service in current injector: { one: 11, two: 22 } child.get(Service).config; // now, in current injector, works cache: { one: 11, two: 22 } * ``` * __Attention:__ Try to avoid using the `child.pull()` method when you can easily achieve the same * result with the `child.get()` method, by passing the appropriate provider to the child injector * during its creation. Use `child.pull()` only in exceptional cases, such as when you dynamically * create an injector and do not know the dependencies of a specific provider whose value you need * to create. */ pull(token: Class | InjectionToken, defaultValue?: T): T; pull(token: T, defaultValue?: T): ReturnType; pull(token: NonNullable, defaultValue?: any): any; protected getResolvedProvider(injector: Injector, dualKey: DualKey): ResolvedProvider | void; /** * Returns provider's value from registry by ID. */ getValue(id: number): ResolvedProvider; hasId(id: number): boolean; } //# sourceMappingURL=injector.d.ts.map