interface ModuleConfig { [key: string]: { type?: string; options?: any; }; } interface HasDependencies { dependencies?: string[]; } export interface Disposable { dispose: () => Promise; } export interface FunctionService extends HasDependencies { (options: O, deps: D): Promise; } export interface NoDepFunctionService extends HasDependencies { (options: O): Promise; } export interface ClassService extends HasDependencies { new (options: O, deps: D): S; } /** * A service can be either an (async) function or a class. * A service is provided with dependendent services * and the options as defined in configuration. */ export declare type Service = FunctionService | NoDepFunctionService | ClassService; /** * ServiceLoader is a small DI (IoC) container used by CIRCUS Project. * A concrete service can be determined via ModuleConfig. */ export default class ServiceLoader { /** * This holds a configuration typically loaded from some configuration file. */ private config; /** * Registered services. * When a service itself is registered, it will be provided with dependencies. */ private services; private loadedServices; constructor(config?: ModuleConfig); /** * Directly binds a new concrete service. * @param name The service (interface) name. * @param service The concrete service class/function. * It can have a `depends` property that declares its dependencies * as an array of strings. * These dependencies will be automatically injected. */ register(name: K, service: Service): void; /** * Registers a service using a module name. * @param name THe service (interface) name. * @param module The module name passed to dynamic `import()`. */ registerModule(name: K, module: string): void; /** * Registers a service via a loader function. * Use this as a last resort; use `register` whenever possible. * @param name The service (interface) name. * @param factory The async loader function to bind. */ registerFactory(name: K, factory: (config: ModuleConfig) => Promise): void; /** * Registers a service with directory-based autoloading. * The concrete type will be determined based on the * `${name}.type` parameter. * For example, `this.registerDirectory('weapon', './weapons', 'Sword')` * will load the deafault weapon from `'./weapons/Sword'`. * If the config has `{ weapon: { type: 'Shuriken' } }`, * it will load from `'./weapons/Shuriken'` instead. * @param name The service (interface) name. * @param directoryPath The path to the directory which holds the * concrete implementations of the corresponding interface. * @param defaultModuleName The default module name used when * the `type` parameter is omitted. */ registerDirectory(name: K, directoryPath: string, defaultModuleName: string): void; /** * Creates a concrete service from the service name. * @param name The name of the required service. */ get(name: K): Promise; /** * Disposes all loaded services. */ dispose(): Promise; private createFromModule; private instanciateService; } export {};