UNPKG

@adonisjs/fold

Version:

Dependency manager and IoC container for your next NodeJs application

253 lines (252 loc) 12.2 kB
declare type Function = (...args: any[]) => any; export declare type ExtractFunctions<T> = { [P in keyof T]: T[P] extends Function ? P : never; }[keyof T]; /** * Unwraps the promise */ declare type UnWrapPromise<T> = T extends Promise<infer U> ? U : T; /** * Shape of the bind callback method */ export declare type BindCallback<ReturnValue extends any, Container extends IocContract> = (container: Container) => ReturnValue; /** * Shape of the fake callback method */ export declare type FakeCallback<ReturnValue extends any, Container extends IocContract> = (container: Container, originalValue: ReturnValue) => ReturnValue; /** * Shape of resolved lookup node, resolved using `getResolver().resolve()` * method. */ export declare type IocResolverLookupNode<Namespace extends string> = { namespace: Namespace; type: 'binding' | 'alias'; method: string; }; /** * Shape of class constructor */ export declare type Constructor<T> = new (...args: any[]) => T; /** * Shape of class constructor with `makePlain` property */ export declare type PlainConstructor = { makePlain: true; }; /** * Type of the "withBindings" method */ export interface WithBindings<ContainerBindings extends any> { <Bindings extends (keyof ContainerBindings)[]>(namespaces: [...Bindings], cb: (...args: { [M in keyof Bindings]: Bindings[M] extends keyof ContainerBindings ? ContainerBindings[Bindings[M]] : any; }) => void): void; <Namespace extends (keyof ContainerBindings | string)[]>(namespaces: readonly [...Namespace], cb: (...args: { [M in keyof Namespace]: Namespace[M] extends keyof ContainerBindings ? ContainerBindings[Namespace[M]] : any; }) => void): void; } /** * Finding return type of the `ioc.make` method based upon the * input argument. * * - String and LookupNode = Returns any * - Class constructor with "makePlain" are returned as it is * - Otherwise an instance of the class constructor is returned * - All other values are returned as it is */ export declare type InferMakeType<T> = T extends string | LookupNode<string> ? any : T extends PlainConstructor ? T : T extends Constructor<infer A> ? A : T; /** * Shape of lookup node pulled using `ioc.lookup` method. This node * can be passed to `ioc.use`, or `ioc.make` to skip many checks * and resolve the binding right away. */ export declare type LookupNode<Namespace extends string> = { namespace: Namespace; type: 'binding' | 'alias'; }; /** * Ioc container interface */ export interface IocContract<ContainerBindings extends any = any> { /** * Registered aliases. The key is the alias and value is the * absolute directory path */ importAliases: { [alias: string]: string; }; /** * Enable/disable proxies. Proxies are mainly required for fakes to * work */ useProxies(enable?: boolean): this; /** * Define the module type for resolving auto import aliases. Defaults * to `cjs` */ module: 'cjs' | 'esm'; /** * Register a binding with a callback. The callback return value will be * used when binding is resolved */ bind<Binding extends keyof ContainerBindings>(binding: Binding, callback: BindCallback<ContainerBindings[Binding], this>): this; bind<Binding extends string>(binding: Binding, callback: BindCallback<Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any, this>): this; /** * Same as the [[bind]] method, but registers a singleton only. Singleton's callback * is invoked only for the first time and then the cached value is used */ singleton<Binding extends keyof ContainerBindings>(binding: Binding, callback: BindCallback<ContainerBindings[Binding], this>): this; singleton<Binding extends string>(binding: Binding, callback: BindCallback<Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any, this>): this; /** * Define an import alias */ alias(absolutePath: string, alias: string): this; /** * Register a fake for a namespace. Fakes works both for "bindings" and "import aliases". * Fakes only work when proxies are enabled using "useProxies". */ fake<Namespace extends keyof ContainerBindings>(namespace: Namespace, callback: FakeCallback<ContainerBindings[Namespace], this>): this; fake<Namespace extends string>(namespace: Namespace, callback: FakeCallback<Namespace extends keyof ContainerBindings ? ContainerBindings[Namespace] : any, this>): this; /** * Clear selected or all the fakes. Calling the method with no arguments * will clear all the fakes */ restore<Namespace extends keyof ContainerBindings>(namespace?: Namespace): this; restore(namespace?: string): this; /** * Find if a fake has been registered for a given namespace */ hasFake<Namespace extends keyof ContainerBindings>(namespace: Namespace): boolean; hasFake(namespace: string): boolean; /** * Find if a binding exists for a given namespace */ hasBinding<Binding extends keyof ContainerBindings>(namespace: Binding): boolean; hasBinding(namespace: string): boolean; /** * Find if a namespace is part of the auto import aliases. Returns false, when namespace * is an alias path but has an explicit binding too */ isAliasPath(namespace: string): boolean; /** * Lookup a namespace. The output contains the complete namespace, * along with its type. The type is an "alias" or a "binding". * * Null is returned when unable to lookup the namespace inside the container * * Note: This method just checks if a namespace is registered or binding * or can be it resolved from auto import aliases or not. However, * it doesn't check for the module existence on the disk. * * Optionally you can define a prefix namespace * to be used to build the complete namespace. For example: * * - namespace: UsersController * - prefixNamespace: App/Controllers/Http * - Output: App/Controllers/Http/UsersController * * Prefix namespace is ignored for absolute namespaces. For example: * * - namespace: /App/UsersController * - prefixNamespace: App/Controllers/Http * - Output: App/UsersController */ lookup<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: Namespace | LookupNode<Namespace>, prefixNamespace?: string): LookupNode<Namespace>; lookup<Namespace extends string>(namespace: Namespace | LookupNode<Namespace>, prefixNamespace?: string): Namespace extends keyof ContainerBindings ? LookupNode<Namespace> : LookupNode<string> | null; /** * Same as [[lookup]]. But raises exception instead of returning null */ lookupOrFail<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: Namespace | LookupNode<Namespace>, prefixNamespace?: string): LookupNode<Namespace>; lookupOrFail<Namespace extends string>(namespace: Namespace | LookupNode<Namespace>, prefixNamespace?: string): Namespace extends keyof ContainerBindings ? LookupNode<Namespace> : LookupNode<string>; /** * Resolve a binding by invoking the binding factory function. An exception * is raised, if the binding namespace is unregistered. */ resolveBinding<Binding extends Extract<keyof ContainerBindings, string>>(binding: Binding): ContainerBindings[Binding]; resolveBinding<Binding extends string>(namespace: Binding): Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any; /** * Import namespace from the auto import aliases. This method assumes you are * using native ES modules */ import(namespace: string): Promise<any>; /** * Same as the "import" method, but uses CJS for requiring the module from its * path */ require(namespace: string): any; /** * The use method looks up a namespace inside both the bindings and the * auto import aliases */ use<Binding extends Extract<keyof ContainerBindings, string>>(lookupNode: Binding | LookupNode<Binding>): ContainerBindings[Binding]; use<Binding extends string>(lookupNode: Binding | LookupNode<Binding>): Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any; /** * Same as the [[use]] method, but instead uses ES modules for resolving * the auto import aliases */ useAsync<Binding extends Extract<keyof ContainerBindings, string>>(lookupNode: Binding | LookupNode<Binding>): Promise<ContainerBindings[Binding]>; useAsync<Binding extends string>(lookupNode: Binding | LookupNode<Binding>): Promise<Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any>; /** * Makes an instance of the class by first resolving it. */ make<Binding extends Extract<keyof ContainerBindings, string>>(lookupNode: Binding | LookupNode<Binding>, args?: any[]): ContainerBindings[Binding]; make<T extends any>(value: T | LookupNode<string>, args?: any[]): T extends keyof ContainerBindings ? ContainerBindings[T] : InferMakeType<T>; /** * Same as the [[make]] method, but instead uses ES modules for resolving * the auto import aliases */ makeAsync<Binding extends Extract<keyof ContainerBindings, string>>(lookupNode: Binding | LookupNode<Binding>, args?: any[]): Promise<ContainerBindings[Binding]>; makeAsync<T extends any>(value: T | LookupNode<string>, args?: any[]): Promise<T extends keyof ContainerBindings ? ContainerBindings[T] : InferMakeType<T>>; /** * The "withBindings" method invokes the defined callback when it is * able to resolve all the mentioned bindings. */ withBindings: WithBindings<ContainerBindings>; /** * @deprecated: Use "withBindings" instead */ with: WithBindings<ContainerBindings>; /** * Call a method on an object and automatically inject its depdencies */ call<T extends any, Method extends ExtractFunctions<T>>(target: T, method: Method, args?: any[]): T[Method] extends Function ? ReturnType<T[Method]> : any; /** * Call a method on an object and automatically inject its depdencies */ callAsync<T extends any, Method extends ExtractFunctions<T>>(target: T, method: Method, args?: any[]): T[Method] extends Function ? Promise<UnWrapPromise<ReturnType<T[Method]>>> : Promise<any>; /** * Trap container lookup calls. It includes * * - Ioc.use * - Ioc.useAsync * - Ioc.make * - Ioc.makeAsync * - Ioc.require * - Ioc.import * - Ioc.resolveBinding */ trap(callback: (namespace: string) => any): this; /** * Returns the resolver instance to resolve Ioc container bindings with * little ease. Since, the IocResolver uses an in-memory cache to * improve the lookup speed, we suggest keeping a reference to * the output of this method to leverage caching */ getResolver(fallbackMethod?: string, rcNamespaceKey?: string, fallbackNamespace?: string): IocResolverContract<ContainerBindings>; } /** * IoC resolver allows resolving IoC container bindings by defining * prefix namespaces */ export interface IocResolverContract<ContainerBindings extends any> { /** * Resolve IoC container binding */ resolve<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: Namespace, prefixNamespace?: string): IocResolverLookupNode<Namespace>; resolve<Namespace extends string>(namespace: Namespace, prefixNamespace?: string): Namespace extends keyof ContainerBindings ? IocResolverLookupNode<Namespace> : IocResolverLookupNode<string>; /** * Call method on an IoC container binding */ call<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: Namespace | string, prefixNamespace?: string, args?: any[] | ((instance: any) => any[])): Promise<any>; call<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: IocResolverLookupNode<Namespace | string>, prefixNamespace: undefined, args?: any[] | ((instance: any) => any[])): Promise<any>; } export {};