@adonisjs/fold
Version:
Dependency manager and IoC container for your next NodeJs application
253 lines (252 loc) • 12.2 kB
TypeScript
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 {};