import { ActivationContext } from "./ActivationContext"; export type primitive = number | string | null | undefined | symbol; 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 interface DescriptorBuilder { /** * * @param f */ factory(f: (resolve: Resolver) => T): void; 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: DescriptorBuilder) => void; export type RegistrationBuildersMap = ConfigurableKeys> = { [k in K]-?: RegistrationBuilder, NonNullable[k]>> }; export interface Descriptor { activate(context: ActivationContext): T; } export type ConfigurableDescriptor> = Descriptor, ConfigurableServices[K]>; export type RegistrationMap = { [k in K]-?: Descriptor; }; export interface ProvidedServices { container: ServiceLocator>; childContainer: ServiceContainer; } export type ProvidedKeys = keyof ProvidedServices; export type ContainerKeys = keyof ContainerServices; export type Mix = { [k in keyof (S & X)]: k extends keyof X ? X[k] : S[k & keyof S] }; export type ContainerServices = Mix>; export type ConfigurableKeys = Exclude; export type ConfigurableServices = Pick>; export interface ServiceLocator { resolve(name: K): NonNullable; resolve(name: K, def: T): NonNullable | T; } export interface LifetimeContainer { createLifetime(): ILifetime; } export interface ServiceContainer extends ServiceLocator>, LifetimeContainer, IDestroyable { register>(name: K, service: ConfigurableDescriptor): void; register>(services: { [k in K]: ConfigurableDescriptor }): void; createChildContainer(): ServiceContainer; } export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call"; /** * Интерфейс для управления жизнью экземпляра объекта. Каждая регистрация имеет * свой собственный объект `ILifetime`, который создается при первой активации */ export interface ILifetime { /** Проверяет, что уже создан экземпляр объекта */ has(): boolean; get(): T; initialize(context: ActivationContext): void; store(item: T, cleanup?: (item: T) => void): void; } export type RequiredKeys = keyof { [p in K as (T[p] extends undefined ? never : p)]-?: T[p] };