import 'reflect-metadata'; import { ProxyTarget } from '../serviceProxy'; import * as symbols from './container.symbols'; export type TypeConstructor = { new (...args: any[]): T; [symbols.DecoratedCtor]?: DecoratedTypeConstructor; }; export type DecoratedTypeConstructor = TypeConstructor & { [symbols.OriginalCtor]: TypeConstructor; [symbols.IsDecorated]: boolean; [symbols.TypeIdentity]: string; }; export type ObjectType = { name: string; prototype: T; } | string; export type LazyObjectType = () => ObjectType; export type TypeFactory = () => T; export interface ServiceProvider { get(): T; get(receiver?: any): T; get(...args: any[]): T; } type PartialArray, X = any> = Partial & Array; export declare enum LifecyclePolicy { /** * Only a single instance is created and a reference of that instance is kept alive in the container until it is destroyed */ singleton = 1, /** * Opposite of the singleton Lifecycle; components with this lifecycle do not get registered and will be * destroyed once there re no more references to them in memory. */ transient = 2 } export interface ServiceOptions { /** * Determines how a service is created and maintained in the container. * A service with a lifecycle of `singleton` will be created once and is reused across resolutions. * A service with a lifecycle of `transient` will be created each time it is resolved. * @default LifecyclePolicy.singleton */ lifecycle: LifecyclePolicy; /** * Optional ordinal priority that determines the preferred implementation when multiple implementations are available; * a higher number is preferred over a lower number. Services are registered with a priority of 0 by default. * * _Note: Negative numbers are allowed and supported_ */ priority: number; } /** * The DI container can be used to register and resolve dependencies automatically. It supports constructor injection * and property injection of dependencies. There are two built-in lifecycle policies: {@link LifecyclePolicy.singleton} and {@link LifecyclePolicy.transient}. * * The DI framework uses two decorators to mark classes and properties as injectable: * - {@link injectable} to mark a class as injectable * - {@link inject} to mark a property or constructor parameter as injectable * * When creating a class through the container, constructor parameters will automatically be resolved by type. When creating * a class outside of the container, constructor parameters will __not__ be resolved. * * Injectable properties are resolved lazily when they are first accessed and are cached for subsequent access on a unique symbol on the instance for which they are resolved. Resolution of injectable properties uses the container that created the instance. If the instance was created outside of a container, the root container is used to try and resolve the dependency. * * When the container cannot resolve a dependency it will return `undefined` for properties and constructor parameters marked with {@link inject} decorator. * * The DI framework requires the following tsconfig settings to be enabled: * - `emitDecoratorMetadata: true` (required to emit type metadata for decorated classes and properties) * - `experimentalDecorators: true` (required to use decorators at all) * - `useDefineForClassFields: false` (required in order to use inject) * * @example: * ``` * @injectable() * class Bar { * constructor(private foo: Foo) { * } * * public helloFooBar() { * this.foo.helloBar(); * } * * public hello() { * console.log('Hello!'); * } * } * * @injectable() * class Foo { * constructor(public bar: Bar) { * } * * public helloBar() { * this.bar.hello(); * } * } * * container.new(Foo).helloBar(); // prints 'Hello!' * container.new(Foo).bar.helloFooBar(); // prints 'Hello!' * ``` */ export declare class Container { private readonly logger; private readonly parent?; /** * Global root container; by default all services are contained in there */ static readonly root: Container; /** * Get's the current container instance from which dependencies are resolved. * Set during resolution phase allowing child entities to be resolved from the same context as their parent. */ static get scope(): Container; private readonly instances; private readonly resolveStack; private readonly serviceDependencies; private readonly servicesProvided; private readonly containerGuid; private readonly factories; private readonly serviceTypes; private readonly providers; private readonly containerPath; /** * Returns `true` if this container is the root container of the application. The root container is the container that is created * by default and contains all services by default. */ get isRoot(): boolean; /** * Wrap all instance created by this container in Proxies. When set to `true` each service instance created by this container is wrapped in * a Proxy. Proxied service instances behave the same way as non-proxied service instances but each call will be routed through the proxy * which can impact performance. * * For now the recommended setting is `false` unless you need to dynamically swap service instances without recreated the dependencies that use them. * * For circular references proxies will always be used even when {@link useInstanceProxies} is set to `false` */ useInstanceProxies: boolean; constructor(logger?: import("../logging").Logger, parent?: Container | undefined); /** * Create a new container that inherits all configuration form the parent but on top of that can register or overwrite dependencies; * by default dependency resolution is first attempted using the providers, factories and registered service instance in the new container; * if that fails it resolution is delegated to the parent until the root container which will throw an exception in case it cannot resolve the requested module. */ create(options?: { isolated?: boolean; }): Container; /** * Dispose all services; factories and provides in this container. */ dispose(): void; /** * Resolve requested type to a concrete implementation. * @param type Service type for which to resolve a concrete class * @param receiver Class ctor for which we are resolving this */ resolve(type: ObjectType | LazyObjectType, receiver?: new (...args: any[]) => object, resolver?: Container): T | undefined; /** * Safe version of {@link Container.resolve} that **never** returns `undefined` and throws an Error for services that cannot be resolved. * @param service Service type for which to resolve the concrete class */ get(service: ObjectType): T; /** * Create a new instance of a type resolving constructor parameters as dependencies using the container. * The returned class is not added in the container even when the lifecycle policy is singleton. * @param ctor Constructor/Type to instantiate * @param params Constructor params provided * @returns New instance of an object who's dependencies are resolved by the container */ new(ctor: T, ...params: PartialArray>): InstanceType; /** * Create a new instance of the given type, with construction wrapped in a deferred initializer. * * The type and any provided partial constructor arguments are forwarded to the container's * createInstance method. The actual construction is wrapped with `lazy(...)` so the creation logic * is executed by the lazy initializer; this method invokes that initializer and returns the created * instance. * * @typeParam T - The constructor type to instantiate. * @param ctor - The constructor (class or function) to instantiate. * @param params - A partial array of constructor arguments that will be forwarded to createInstance. * @returns The constructed instance of the specified constructor type. */ newDeferred(ctor: T, ...params: PartialArray>): InstanceType; /** * Creates a new instance of the specified type resolving dependencies using the current container context. The returned class is not registered * in the container as dependency. * @param ctor Constructor type/prototype class definition */ private createInstance; /** * Decorates a class type with additional metadata for dependency injection. * @param ctor Constructor type to decorate * @returns Decorated constructor type */ decorateType(ctor: TypeConstructor, serviceTypes?: Array): DecoratedTypeConstructor; /** * Get's the container that owns or created the specified instance. */ static get(instance: object): Container | undefined; /** * Resolves constructor parameters for a type using this container. * * Explicit values in `args` are preserved. Missing values are resolved from * the container, unless the parameter was decorated with `@inject.new(...)`; * in that case the parameter type is created as a new instance with the * recorded constructor arguments. * * @param ctor Constructor whose parameters should be resolved. * @param args Existing constructor arguments to keep or complete. * @param instanceGuid Optional service id used to track resolved dependencies. * @returns The completed constructor argument list. */ resolveParameters any>(ctor: T, args?: any[], instanceGuid?: string): any[]; /** * Resolve injectable properties for a service using this container. * @param instance Instance object * @returns instance */ resolveProperties(instance: T): T; /** * Internal function to get the property descriptor for an injectable property; used by the {@link inject} decorator. * @param propertyKey Key of the property to get the descriptor for * @returns Defined property descriptor */ getInjectablePropertyDescriptor(propertyKey: string | symbol): { [symbols.InjectedPropertyKey]: string | symbol; configurable: boolean; enumerable: boolean; get(): any; set(): never; }; /** * Resolves a single injected property value for an instance. * * The property type comes from `@inject(Type)` metadata when present, * otherwise from emitted design-time metadata. Properties decorated with * `@inject.new(...)` are created as new instances with the recorded * constructor arguments. * * @param instance Instance containing the injected property. * @param property Name or symbol of the property to resolve. * @param options Optional resolution behavior. * @returns The resolved property value. */ resolveProperty(instance: object, property: string | symbol, options?: { trackAsDependency?: boolean; }): any; private getInjectType; private getMetadata; private generateServiceGuid; private decorateWithServiceGuid; /** * Register a new dependency between two services * @param serviceGuid the instance guid of the object that owns the dependency * @param dependsOn instance of the dependency */ private trackServiceDependencies; /** * Register a new service instance or type in this container. * If the added entity is an instance it will be treated as singleton even if the lifecycle is transient. * @param instanceOrType the service instance * @param options optional service options * @returns */ add(instanceOrType: TypeConstructor | I, options?: Partial>; }>): void; /** * Use the specified instance to provided the specified service types. * If an existing service is already registered for a type, it will be replaced with the new instance. * @param instance the service instance * @param types the service types to provide * @returns */ use(instance: object, types?: Array | ObjectType): void; private addInstance; private addType; private getServicesFromInstance; private getServicesFromType; private getPrototypes; /** * Drops an active singleton service instance from the container causing subsequent resolutions to * create a new instances instead of reusing the existing one. * @param instance the instance to remove */ removeInstance(instance: unknown): void; /** * Register a factory that can provide an instance of the specified factory * @param services list of services to register * @param factory factory that produces the an instance */ registerFactory(services: ObjectType | Array>, factory: TypeFactory, lifecycle?: LifecyclePolicy): void; /** * Register a service proxy that can be manually set with a concrete instance later on. * Any instance that request a service of type T will receive the proxy instance. * * The proxy is not registered as a factory type. * * The proxy instance can be set using the `setInstance` method on the ProxyTarget returned by this method. * * @param type Service type to register * @returns ProxyTarget instance that can be used to set the concrete instance */ registerProxyService(type: { name: string; prototype: T; }): ProxyTarget; registerProvider(service: ObjectType, provider: (receiver: any) => I | Promise | undefined): void; private getTypeName; } /** * Root container; by default all services are contained in there */ export declare const container: Container; export {}; //# sourceMappingURL=container.d.ts.map