UNPKG

@asimojs/asimo

Version:

Asynchronous dependency manager for Typescript projects

176 lines (169 loc) 7.81 kB
/** * Asimo context object used to asynchronously get or create dependencies * The root context is exposed through the asm global object. Sub-contexts can be created through asm.createChildContext() */ export interface AsmContext { /** * The context name - helps differentiating multiple contexts */ readonly name: string; /** * The parent context where dependencies will be retrieved if not found in the current context */ readonly parent: AsmContext | null; /** * A unique path identifier listing all context names from the top parent context * e.g. "/asm/subContext1/subContext2" */ readonly path: string; /** * The interface definitions that are currently loaded in the context */ readonly definitions: AsmInterfaceDefinition[]; /** * Register an object instance. * Object instances can be retrieved synchronously through the get() method * @see get */ registerObject<T extends object>(iid: InterfaceId<T>, o: T): void; /** * Register a service factory. Services are singleton objects that will be created only once * and stored in the AsmContext. Services will be created on-demand, when retrieved for the first time * Services can be retrieved asynchronoysly through the fetch() method * @param iid the interface id * @param factory a factory that will be called to instanciate the service * @see fetch */ registerService<T>(iid: InterfaceId<T>, factory: (c: AsmContext) => T | Promise<T>): void; /** * Register an object factory. The factory will be called any time the get method is called * for this interface id. On the contrary to services, there is no restriction on the number * of objects that can be created. Besides asimo doesn't keep any reference to the object * created. * Objects produced by factories can be retrieved asynchronoysly through the fetch() method * @param iid the interface id * @param factory a factory that will be called to create an object instance * @see fetch */ registerFactory<T>(iid: InterfaceId<T>, factory: (c: AsmContext) => T | Promise<T>): void; /** * Register a group loader that will be used to asynchronously load multiple * service and object factories on-demand (i.e. the group code will only be loaded when * an explicit get is done on one of its service or object interfaces) * Services or objects produced by service or object factories can be retrieved through the fetch method. * @param iids the list of interface ids that are packaged in this group * @param loader an async factory that should dynamically import() the required modules * @see fetch */ registerGroup(iids: InterfaceId<any>[], loader: () => Promise<unknown>): void; /** * Synchrounsly retrieve an object instance registered with registerObject * For each interface id, asimo will first look in the current context objects - if not found * it will then perform the same lookup in its parent context (recursively, up to the root context). * This method allows to get up to 5 dependencies in one call with type support (more can be retrieved without type inference). * Note: When retrieving 1 resource, the parameters can be either InterfaceId objects or interface namespaces (strings). * When using InterfaceId typescript will automatically infer the right type - otherwise an explicit * type cast will be necessary * Note: this method will throw an error if the targeted object is not found - unless a default value is passed as 2nd argument * (this only works when fetching a single resource - e.g. asm.get(AppModuleIID, null) ) * @see fetch */ get<T>(iid: IidNs<T>): T; get<T, D extends T | null>(iid: IidNs<T>, defaultValue?: D): T | D; get<T1, T2>(iid1: InterfaceId<T1>, InterfaceId: IidNs<T2>): [T1, T2]; get<T1, T2, T3>( iid1: InterfaceId<T1>, iid2: InterfaceId<T2>, iid3: InterfaceId<T3>, ): [T1, T2, T3]; get<T1, T2, T3, T4>( iid1: InterfaceId<T1>, iid2: InterfaceId<T2>, iid3: InterfaceId<T3>, iid4: InterfaceId<T4>, ): [T1, T2, T3, T4]; get<T1, T2, T3, T4, T5>( iid1: InterfaceId<T1>, iid2: InterfaceId<T2>, iid3: InterfaceId<T3>, iid4: InterfaceId<T4>, iid5: InterfaceId<T5>, ): [T1, T2, T3, T4, T5]; get(...iids: (InterfaceId<any> | string)[]): Promise<any[]>; /** * Asynchronously fetch a service or an object produced by a registered factory. For each interface id, asimo will first look in the current * context for services or object factories or groups registered for the interface (in this order) - if not found * it will then perform the same lookup in its parent context (recursively, up to the root context). * This method allows to get up to 5 dependencies in one call with type support (more can be fetched * without type inference). * Note: When fetcing 1 resource, the parameters can be either InterfaceId objects or interface namespaces (strings). * When using InterfaceId typescript will automatically infer the right type - otherwise an explicit * type cast will be necessary * Note: this method will throw an error if the targeted service or object cannot be found/loaded - unless a default value is passed * (this only works when fetching a single resource - e.g. asm.fetch(CalculatorIID, null) ) */ fetch<T>(iid: IidNs<T>): Promise<T>; fetch<T, D extends T | null>(iid: IidNs<T>, defaultValue?: D): Promise<T | D>; fetch<T1, T2>(iid1: InterfaceId<T1>, InterfaceId: IidNs<T2>): Promise<[T1, T2]>; fetch<T1, T2, T3>( iid1: InterfaceId<T1>, iid2: InterfaceId<T2>, iid3: InterfaceId<T3>, ): Promise<[T1, T2, T3]>; fetch<T1, T2, T3, T4>( iid1: InterfaceId<T1>, iid2: InterfaceId<T2>, iid3: InterfaceId<T3>, iid4: InterfaceId<T4>, ): Promise<[T1, T2, T3, T4]>; fetch<T1, T2, T3, T4, T5>( iid1: InterfaceId<T1>, iid2: InterfaceId<T2>, iid3: InterfaceId<T3>, iid4: InterfaceId<T4>, iid5: InterfaceId<T5>, ): Promise<[T1, T2, T3, T4, T5]>; fetch(...iids: (InterfaceId<any> | string)[]): Promise<any[]>; /** * Create a child context that can override some of the dependencies defined in its parent (cf. get behaviour) * @param name a name to identifiy and differentiate this context from other contexts */ createChildContext(name?: string): AsmContext; /** * Define where logs should go - default = console */ logger: Logger | null; /** * Log the asimo state into an array or in the console if no output argument is provided * @param output */ logState(output?: string[]): void; } export interface AsmInterfaceDefinition { /** The interface id */ iid: string; /** The type of of object the interface is going to produce */ type: "service" | "object" | "group"; /** Tell if the service associated to the interface has been loaded (not used for object or groups) */ loaded?: boolean; } /** * Object that will receive the logs */ export interface Logger { log(...data: any[]): void; } /** * String representing an interface namespace - e.g. "myapplication.services.Settings" */ export type InterfaceNamespace = string; /** * Object biding an interface type T with an interface namespace (allows to get typescript validation) */ export interface InterfaceId<T> { ns: InterfaceNamespace; } /** * IID or Namespace: parameter type used to retrieve an object from asimo */ export type IidNs<T> = InterfaceId<T> | string;