UNPKG

bb-inspired

Version:

Core library for BB-inspired NestJS backend

201 lines 8.97 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var PluginManagerMain_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.PluginManagerMain = void 0; const common_1 = require("@nestjs/common"); const core_1 = require("@nestjs/core"); const hook_service_1 = require("./hook.service"); const logger_1 = require("../../utils/logger"); let PluginManagerMain = PluginManagerMain_1 = class PluginManagerMain { constructor(options = {}, hookService, moduleRef) { this.options = options; this.hookService = hookService; this.moduleRef = moduleRef; this.logger = new logger_1.AppLogger(PluginManagerMain_1.name); this.plugins = new Map(); this.enabledPlugins = new Set(); this.moduleContexts = new Map(); } async onModuleInit() { this.logger.log('Initializing plugin system'); if (this.options.autoDiscovery && this.options.pluginsDir) { this.logger.log(`Plugin auto-discovery enabled from directory: ${this.options.pluginsDir}`); } if (this.options.customHooks && this.options.customHooks.length > 0) { for (const hookName of this.options.customHooks) { this.hookService.registerHookPoint(hookName); } this.logger.log(`Registered ${this.options.customHooks.length} custom hooks`); } } async onModuleDestroy() { this.logger.log('Shutting down plugin system'); for (const pluginName of this.enabledPlugins) { await this.disable(pluginName); } } async register(plugin) { var _a; const { metadata } = plugin; if (!metadata || !metadata.name || !metadata.version) { throw new Error('Plugin registration requires valid metadata with name and version'); } if (this.plugins.has(metadata.name)) { this.logger.warn(`Plugin ${metadata.name} is already registered. Skipping registration.`); return; } this.plugins.set(metadata.name, plugin); this.logger.log(`Registered plugin: ${metadata.name} v${metadata.version}`); const context = { name: metadata.name, version: metadata.version, config: plugin.config || {}, get: (token) => this.moduleRef.get(token, { strict: false }), logger: { log: (message) => this.logger.log(message, { context: metadata.name }), error: (message, trace) => this.logger.error(message, trace, { context: metadata.name }), warn: (message) => this.logger.warn(message, { context: metadata.name }), debug: (message) => this.logger.debug(message, { context: metadata.name }), verbose: (message) => this.logger.verbose(message, { context: metadata.name }), }, emit: async (eventName, payload) => { await this.hookService.executeHook(`${metadata.name}:${eventName}`, payload); } }; this.moduleContexts.set(metadata.name, context); if (plugin.hooks) { for (const [hookName, handler] of Object.entries(plugin.hooks)) { this.registerHook(hookName, handler); } } if ((_a = plugin.lifecycle) === null || _a === void 0 ? void 0 : _a.onLoad) { try { await plugin.lifecycle.onLoad(context); } catch (error) { this.logger.error(`Error initializing plugin ${metadata.name}: ${error.message}`, error.stack); } } if (this.options.loadOnStartup) { await this.enable(metadata.name); } } async enable(pluginName) { var _a; if (!this.plugins.has(pluginName)) { this.logger.warn(`Cannot enable plugin ${pluginName}: Plugin not registered`); return false; } if (this.enabledPlugins.has(pluginName)) { return true; } const plugin = this.plugins.get(pluginName); const context = this.moduleContexts.get(pluginName); if (plugin.metadata.dependencies && plugin.metadata.dependencies.length > 0) { for (const dependency of plugin.metadata.dependencies) { if (!this.isEnabled(dependency)) { try { const success = await this.enable(dependency); if (!success) { this.logger.error(`Cannot enable plugin ${pluginName}: Dependency ${dependency} could not be enabled`); return false; } } catch (error) { this.logger.error(`Cannot enable plugin ${pluginName}: Dependency ${dependency} error: ${error.message}`); return false; } } } } if ((_a = plugin.lifecycle) === null || _a === void 0 ? void 0 : _a.onEnable) { try { await plugin.lifecycle.onEnable(context); } catch (error) { this.logger.error(`Error enabling plugin ${pluginName}: ${error.message}`, error.stack); return false; } } this.enabledPlugins.add(pluginName); this.logger.log(`Enabled plugin: ${pluginName}`); return true; } async disable(pluginName) { var _a; if (!this.plugins.has(pluginName)) { this.logger.warn(`Cannot disable plugin ${pluginName}: Plugin not registered`); return false; } if (!this.enabledPlugins.has(pluginName)) { return true; } const plugin = this.plugins.get(pluginName); const context = this.moduleContexts.get(pluginName); for (const [name, p] of this.plugins.entries()) { if (this.enabledPlugins.has(name) && p.metadata.dependencies && p.metadata.dependencies.includes(pluginName)) { try { const success = await this.disable(name); if (!success) { this.logger.error(`Cannot disable plugin ${pluginName}: Dependent plugin ${name} could not be disabled`); return false; } } catch (error) { this.logger.error(`Cannot disable plugin ${pluginName}: Error disabling dependent plugin ${name}: ${error.message}`); return false; } } } if ((_a = plugin.lifecycle) === null || _a === void 0 ? void 0 : _a.onDisable) { try { await plugin.lifecycle.onDisable(context); } catch (error) { this.logger.error(`Error disabling plugin ${pluginName}: ${error.message}`, error.stack); return false; } } this.enabledPlugins.delete(pluginName); this.logger.log(`Disabled plugin: ${pluginName}`); return true; } getPlugins() { return Array.from(this.plugins.values()).map(p => p.metadata); } getPlugin(name) { return this.plugins.has(name) ? this.plugins.get(name).metadata : undefined; } isEnabled(name) { return this.enabledPlugins.has(name); } registerHook(hookName, handler) { this.hookService.registerHandler(hookName, handler); } async executeHook(hookName, data) { return this.hookService.executeHook(hookName, data); } }; exports.PluginManagerMain = PluginManagerMain; exports.PluginManagerMain = PluginManagerMain = PluginManagerMain_1 = __decorate([ (0, common_1.Injectable)(), __param(0, (0, common_1.Optional)()), __param(0, (0, common_1.Inject)('PLUGIN_OPTIONS')), __metadata("design:paramtypes", [Object, hook_service_1.HookService, core_1.ModuleRef]) ], PluginManagerMain); //# sourceMappingURL=plugin.manager.js.map