import { ActivationContext } from "./ActivationContext"; import { key } from "./traits"; export interface IDestroyable { destroy(): void; } /** * @template S Карта доступных зависимостей */ export interface Resolver { /** * Функция для разрешения зависимостей, поддерживает создание фабричных методов, * отложенную активацию и значение по-умолчанию для сервисов * @template K Ключ сервиса из {@link S} * @template O Тип параметра {@link opts} используется для выведения типа * возвращаемого значения. * @param name Ключ сервиса, который будет разрешен. * @param {boolean=} opts.lazy Признак того, что требуется отложенная активация, * будет возвращен фабричный метод для получения зависимости. Если не указан, * то считается `false`. * @param {any=} opts.default Значение по умолчанию, если в контейнере указанный * сервис не зарегистрирован * @returns Либо фабричный метод для получения зависимости, либо значение зависимости * @throws Error Если зависимость не найдена и не предоставлено значение по-умолчанию */ (name: K, opts?: O): () => (O extends { default: infer T } ? T : never) | NonNullable; (name: K, opts?: O): (O extends { default: infer T } ? T : never) | NonNullable; } export type DepsMap = { [k in K]: SK | Ref }; export type Ref = { name: K, lazy?: L } | { name: K, lazy?: L, default: D }; export type Resolved = L extends true ? () => NonNullable | (unknown extends D ? never : D) : NonNullable | (unknown extends D ? never : D); export interface IDescriptorBuilder { /** * * @param f */ factory(f: (refs: R) => T): void; wants, keyof S>>(refs: X): IDescriptorBuilder : X[k] extends Ref ? Resolved : never }> override>(name: K, builder: RegistrationBuilder>): this; override>(services: { [name in K]: RegistrationBuilder> }): this; lifetime(lifetime: "singleton", typeId: string | number | object): this; lifetime(lifetime: ILifetime | Exclude): this; cleanup(cb: (item: T) => void): this; value(v: T): void; } export type RegistrationBuilder = (d: IDescriptorBuilder) => void; export type RegistrationBuildersMap = ConfigurableKeys> = { [k in K]-?: RegistrationBuilder, NonNullable> }; export interface Descriptor { activate(context: IActivationContext): T; } export interface IActivationContext extends ServiceLocator { createLifetime(): ILifetime; createContainerLifetime(): ILifetime; } export type ConfigurableDescriptor> = Descriptor, S[K]>; export type RegistrationMap = { [k in K]-?: Descriptor; }; export interface ContainerProvided> { container: ServiceLocator>; childContainer: IContainerBuilder; } export type Configurable = { [k in keyof S & (keyof ContainerProvided)]: never; }; export type ProvidedKeys = keyof ContainerProvided; export type ContainerServices> = S & ContainerProvided; export type ConfigurableKeys = Exclude; export type ConfigurableServices = Pick>; export type ContainerKeys> = keyof S | keyof ContainerProvided; export interface ServiceLocator { resolve(name: K): NonNullable; resolve(name: K, def: T): NonNullable | T; } export interface LifetimeContainer { createLifetime(): ILifetime; } export interface ServiceContainer> extends ServiceLocator>, IDestroyable { createChildContainer(): IContainerBuilder; } export interface IContainerBuilder> { createServiceBuilder(name: K): IDescriptorBuilder>; build(): ServiceContainer; } export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call"; /** * Интерфейс для управления жизнью экземпляра объекта. Каждая регистрация имеет * свой собственный объект `ILifetime`, который создается при первой активации */ export interface ILifetime { /** Проверяет, что уже создан экземпляр объекта */ has(): boolean; get(): T; initialize(context: IActivationContext): void; store(item: T, cleanup?: (item: T) => void): void; } export type ExtractRequired = { [p in K as (undefined extends T[p] ? never : p)]-?: T[p] };