UNPKG

@lakutata/core

Version:

Lakutata Framework Core

529 lines (494 loc) 17.5 kB
import {BaseObject} from '../BaseObject' import {Container} from '../Container' import {Component} from './Component' import {IComponentsConfig} from '../../interfaces/IComponentsConfig' import {IModulesConfig} from '../../interfaces/IModulesConfig' import {TPluginsConfig} from '../../types/TPluginsConfig' import {Plugin} from '../Plugin' import EventEmitter from 'events' import {IConstructor} from '../../interfaces/IConstructor' import {TWorkflowsConfig} from '../../types/TWorkflowsConfig' import {Workflow} from './Workflow' import {Configurable} from '../../decorators/DependencyInjection' import {ThreadManager} from '../thread/ThreadManager' import {Thread} from '../thread/Thread' import {IThreadConstructor} from '../../interfaces/IThreadConstructor' import {ProcessManager} from '../process/ProcessManager' import {Process} from '../process/Process' import {IProcessConstructor} from '../../interfaces/IProcessConstructor' import {TThreadsConfig} from '../../types/TThreadsConfig' import {TProcessesConfig} from '../../types/TProcessesConfig' import {ModuleNotFoundException} from '../../exceptions/ModuleNotFoundException' import {ComponentNotFoundException} from '../../exceptions/ComponentNotFoundException' export abstract class Module extends BaseObject { /** * 模块事件 * @type {EventEmitter} * @private */ private readonly eventEmitter: EventEmitter = new EventEmitter() /** * 模块ID * @type {string | IConstructor<Module>} */ public readonly id: string | IConstructor<Module> /** * 模块IoC容器 * @type {Container} * @protected */ protected readonly container: Container = new Container() /** * 线程管理器 * @type {ThreadManager} * @protected */ protected readonly threadManager: ThreadManager = new ThreadManager() /** * 进程管理器 * @type {ProcessManager} * @protected */ protected readonly processManager: ProcessManager = new ProcessManager() /** * 组件加载完成回调函数 * @returns {any} */ @Configurable() protected readonly onComponentsLoaded: (module: ThisType<this>) => void | Promise<void> = () => void (0) /** * 模块加载完成回调函数 * @param {Module} module * @returns {any} */ @Configurable() protected readonly onModulesLoaded: (module: ThisType<this>) => void | Promise<void> = () => void (0) /** * 模块初始化方法 * @returns {Promise<void> | void} * @protected */ protected abstract initialize(): Promise<void> | void constructor() { super() this.on('ready', async (module: this) => { if (this.workflows) { for (const workflow of this.workflows) { const WorkflowConstructor: IConstructor<Workflow> = workflow as IConstructor<Workflow> let workflowFunction: (((instance: this) => void) | ((instance: this) => Promise<void>)) | null = null try { const workflowInstance = new WorkflowConstructor(module) if (workflowInstance.run) { await workflowInstance.run() } } catch (e) { workflowFunction = workflow as (((instance: this) => void) | ((instance: this) => Promise<void>)) } if (workflowFunction) await workflowFunction(module) } } }) this.container .on('moduleLoaded', (moduleId, moduleConstructor, loadTime, subModuleId?) => { const moduleStringId: string = typeof this.id === 'function' ? this.id.name : this.id this.eventEmitter.emit('loaded', subModuleId ? `${moduleStringId}/${subModuleId}` : moduleStringId, moduleId, moduleConstructor, loadTime, 'module') }) .on('componentLoaded', (componentId, componentConstructor, loadTime, subModuleId?) => { const moduleStringId: string = typeof this.id === 'function' ? this.id.name : this.id this.eventEmitter.emit('loaded', subModuleId ? `${moduleStringId}/${subModuleId}` : moduleStringId, componentId, componentConstructor, loadTime, 'component') }) } /** * 工作流方法执行列表 * @type {TWorkflowsConfig[]} * @protected */ @Configurable() protected readonly workflows: TWorkflowsConfig = [] /** * 插件加载列表 * @type {TPluginsConfig} */ @Configurable() protected readonly plugins: TPluginsConfig = [] /** * 组件加载列表 * @type {IComponentsConfig} * @protected */ @Configurable() protected readonly components: IComponentsConfig = {} /** * 模块加载列表 * @type {IModulesConfig} * @protected */ @Configurable() protected readonly modules: IModulesConfig = {} /** * 线程加载列表 * @type {TThreadsConfig} * @protected */ @Configurable() protected readonly threads: TThreadsConfig = [] /** * 进程加载列表 * @type {TProcessesConfig} * @protected */ @Configurable() protected readonly processes: TProcessesConfig = [] /** * 加载插件列表 * @protected */ protected bindPlugins(): void { //todo 可能需要合并一下多个相同插件的配置 if (!this.plugins) return const reversedPlugins = this.plugins.reverse() const registeredPluginSet = new Set() for (const pluginConstructorOrConfig of reversedPlugins) { let pluginConstructor let pluginConfig: object & { scope?: 'Transient' | 'Singleton' } = {} if (typeof pluginConstructorOrConfig === 'object') { pluginConstructor = pluginConstructorOrConfig.class for (const configKey of Object.keys(pluginConstructorOrConfig)) { const configValue = pluginConstructorOrConfig[configKey] if (configValue !== pluginConstructor) { pluginConfig[configKey] = configValue } } } else { pluginConstructor = pluginConstructorOrConfig pluginConfig = {} } if (registeredPluginSet.has(pluginConstructor)) continue this.container.bindPlugin(pluginConstructor, pluginConstructor.name, pluginConfig) if (!this.hasProperty(pluginConstructor.name)) { this.defineProperty(pluginConstructor.name, { get() { return this.container.getPlugin(pluginConstructor.name) } }) } registeredPluginSet.add(pluginConstructor) } } /** * 加载组件列表 * @protected */ protected bindComponents(): void { if (!this.components) return for (const key of Object.keys(this.components)) { const componentIdentifier: string = key const componentConstructorOrConfig = this.components[key] let componentConstructor let componentConfig: object = {} if (typeof componentConstructorOrConfig === 'object') { componentConstructor = componentConstructorOrConfig.class for (const configKey of Object.keys(componentConstructorOrConfig)) { const configValue = componentConstructorOrConfig[configKey] if (configValue !== componentConstructor) { componentConfig[configKey] = configValue } } } else { componentConstructor = componentConstructorOrConfig componentConfig = {} } this.container.bindComponent(componentConstructor, componentIdentifier, componentConfig) } } /** * 加载模块列表 * @protected */ protected bindModules(): void { if (!this.modules) { this.emit('modulesReady', this) return } const moduleSize: number = Object.keys(this.modules).length let loadedModuleCount: number = 0 if (moduleSize === loadedModuleCount) { this.emit('modulesReady', this) } else { for (const key of Object.keys(this.modules)) { const moduleIdentifier: string = key const moduleConfig = this.modules[key] const moduleConstructor = moduleConfig.class let moduleConfigs: object = {} for (const configKey of Object.keys(moduleConfig)) { const configValue = moduleConfig[configKey] if (moduleConstructor !== configValue) { moduleConfigs[configKey] = configValue } } this.container.bindModule(moduleConstructor, moduleConfigs, moduleIdentifier, () => { loadedModuleCount += 1 if (loadedModuleCount === moduleSize) { this.emit('modulesReady', this) } }) } } } /** * 加载线程列表 * @returns {Promise<void>} * @protected */ protected async bindThreads(): Promise<void> { if (this.threads) { const threadBindPromises: Promise<boolean>[] = [] this.threads.forEach(threadConstructor => { threadBindPromises.push(new Promise((resolve, reject) => { this.threadManager.createThread(threadConstructor).then(resolve).catch(reject) })) }) await Promise.all(threadBindPromises) } } /** * 加载进程列表 * @returns {Promise<void>} * @protected */ protected async bindProcesses(): Promise<void> { if (this.processes) { const processBindPromises: Promise<boolean>[] = [] this.processes.forEach(processConstructor => { processBindPromises.push(new Promise((resolve, reject) => { this.processManager.createProcess(processConstructor).then(resolve).catch(reject) })) }) await Promise.all(processBindPromises) } } /** * 插件管理 * @returns {{bind: <TPlugin=Plugin extends Plugin>(pluginConstructor: IConstructor<TPlugin>, identifier: string, config: object) => void, get: <T=Plugin extends Plugin>(name: string) => T, has: (name: string) => boolean}} * @constructor */ public get Plugins() { const self = this return { bind: function <TPlugin extends Plugin = Plugin>(pluginConstructor: IConstructor<TPlugin>, identifier: string, config: object): void { self.container.bindPlugin(pluginConstructor, identifier, config) }, get: function <T extends Plugin = Plugin>(name: string): T { return self.container.getPlugin(name) }, has: function (name: string): boolean { try { self.container.getPlugin(name) return true } catch (e) { return false } } } } /** * 对象管理 * @returns {{bind: <TObject=BaseObject extends BaseObject>(objectConstructor: IConstructor<TObject>, config?: {[p: string]: any}) => void, unbind: <TObject=BaseObject extends BaseObject>(objectConstructor: IConstructor<TObject>) => void, get: <TObject=BaseObject extends BaseObject>(objectConstructor: IConstructor<TObject>) => TObject, has: <TObject=BaseObject extends BaseObject>(objectConstructor: IConstructor<TObject>) => boolean}} * @constructor */ public get Objects() { const self = this return { bind: function <TObject extends BaseObject = BaseObject>(objectConstructor: IConstructor<TObject>, config?: { [key: string]: any }): void { self.container.bindObject(objectConstructor, config) }, get: function <TObject extends BaseObject = BaseObject>(objectConstructor: IConstructor<TObject>): TObject { return self.container.getObject(objectConstructor) }, has: function <TObject extends BaseObject = BaseObject>(objectConstructor: IConstructor<TObject>): boolean { return self.container.hasObject(objectConstructor) }, unbind: function <TObject extends BaseObject = BaseObject>(objectConstructor: IConstructor<TObject>): void { self.container.unbindObject(objectConstructor) } } } /** * 组件管理 * @returns {any} * @constructor */ public get Components() { const self = this const baseComponents = { get: function <T extends Component = Component>(name: string): T { if (baseComponents.has(name)) { return self.container.getComponent<T>(name) } else { throw self.generateException(ComponentNotFoundException, name) } }, has: function (name: string): boolean { try { self.container.getComponent(name) return true } catch (e) { return false } } } return new Proxy(baseComponents, { get(target: { get: <T extends Component = Component>(name: string) => T; has: (name: string) => boolean; [key: string]: any }, p: string, receiver: any): any { if (target[p]) { return target[p] } else { if (target.has(p)) { return target.get(p) } else { return undefined } } } }) } /** * 模块管理 * @returns {any} * @constructor */ public get Modules() { const self = this const baseModules = { get: function <T extends Module = Module>(name: string): T { if (baseModules.has(name)) { return self.container.getModule<T>(name) } else { throw self.generateException(ModuleNotFoundException, name) } }, has: function (name: string): boolean { try { self.container.getModule(name) return true } catch (e) { return false } } } return new Proxy(baseModules, { get(target: { get: <T extends Module = Module>(name: string) => T; has: (name: string) => boolean }, p: string): any { if (target[p]) { return target[p] } else { if (target.has(p)) { return target.get(p) } else { return undefined } } } }) } /** * 线程管理 * @returns {{bind: <T=Thread extends Thread>(threadConstructor: IThreadConstructor<T>) => Promise<boolean>, get: <T=Thread extends Thread>(threadConstructor: IThreadConstructor<T>) => T, destroy: <T=Thread extends Thread>(threadConstructor: IThreadConstructor<T>) => Promise<void>, has: <T=Thread extends Thread>(threadConstructor: IThreadConstructor<T>) => boolean}} * @constructor */ public get Threads() { const self = this return { bind: async function <T extends Thread = Thread>(threadConstructor: IThreadConstructor<T>): Promise<boolean> { return await self.threadManager.createThread(threadConstructor) }, get: function <T extends Thread = Thread>(threadConstructor: IThreadConstructor<T>): T { return self.threadManager.get(threadConstructor) as T }, has: function <T extends Thread = Thread>(threadConstructor: IThreadConstructor<T>): boolean { return self.threadManager.has(threadConstructor) }, destroy: async function <T extends Thread = Thread>(threadConstructor: IThreadConstructor<T>): Promise<void> { return await self.threadManager.destroy(threadConstructor) } } } /** * 进程管理 * @returns {{bind: <T=Process extends Process>(processConstructor: IProcessConstructor<T>) => Promise<boolean>, get: <T=Process extends Process>(processConstructor: IProcessConstructor<T>) => T, destroy: <T=Process extends Process>(processConstructor: IProcessConstructor<T>) => Promise<void>, has: <T=Process extends Process>(processConstructor: IProcessConstructor<T>) => boolean}} * @constructor */ public get Processes() { const self = this return { bind: async function <T extends Process = Process>(processConstructor: IProcessConstructor<T>): Promise<boolean> { return await self.processManager.createProcess(processConstructor) }, get: function <T extends Process = Process>(processConstructor: IProcessConstructor<T>): T { return self.processManager.get(processConstructor) as T }, has: function <T extends Process = Process>(processConstructor: IProcessConstructor<T>): boolean { return self.processManager.has(processConstructor) }, destroy: async function <T extends Process = Process>(processConstructor: IProcessConstructor<T>): Promise<void> { return await self.processManager.destroy(processConstructor) } } } public on(event: 'ready', listener: (instance: this) => void): this public on(event: 'loaded', listener: (id: string, identifier: string, constructor: IConstructor<Module> | IConstructor<Component>, loadTime: number, type: 'module' | 'component') => void): this public on(event: string | symbol, listener: (...args: any[]) => void): this public on(a: string | symbol, b: (...args: any[]) => void): this { this.eventEmitter.on(a, b) return this } public once(event: 'ready', listener: (instance: this) => void): this public once(event: 'loaded', listener: (id: string, identifier: string, constructor: IConstructor<Module> | IConstructor<Component>, loadTime: number, type: 'module' | 'component') => void): this public once(event: string | symbol, listener: (...args: any[]) => void): this public once(a: string | symbol, b: (...args: any[]) => void): this { this.eventEmitter.once(a, b) return this } public off(event: string): void public off(event: string | symbol, listener: (...args: any[]) => void): this public off(a: string | symbol, b?: (...args: any[]) => void): this { if (!b) { this.eventEmitter.removeAllListeners(a) } else { this.eventEmitter.removeListener(a, b) } return this } public emit(event: string | symbol, ...args: any[]): boolean { return this.eventEmitter.emit.apply(this.eventEmitter, [event].concat(args) as any) } /** * 绑定对象 * @param {IConstructor<TObject>} objectConstructor * @param {{[p: string]: any}} config */ public bind<TObject extends BaseObject = BaseObject>(objectConstructor: IConstructor<TObject>, config?: { [key: string]: any }): void { return this.Objects.bind(objectConstructor, config) } /** * 获取对象 * @param {IConstructor<TObject>} objectConstructor * @returns {TObject} */ public get<TObject extends BaseObject = BaseObject>(objectConstructor: IConstructor<TObject>): TObject { return this.Objects.get(objectConstructor) } /** * 解除对象绑定 * @param {IConstructor<TObject>} objectConstructor */ public unbind<TObject extends BaseObject = BaseObject>(objectConstructor: IConstructor<TObject>): void { return this.Objects.unbind(objectConstructor) } /** * 判断对象是否已绑定 * @param {IConstructor<TObject>} objectConstructor * @returns {boolean} */ public has<TObject extends BaseObject = BaseObject>(objectConstructor: IConstructor<TObject>): boolean { return this.Objects.has(objectConstructor) } }