UNPKG

docker-pilot

Version:

A powerful, scalable Docker CLI library for managing containerized applications of any size

288 lines 10.3 kB
"use strict"; /** * Plugin Manager for Docker Pilot * Manages plugin loading, initialization, and lifecycle */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.PluginManager = void 0; const path = __importStar(require("path")); const Logger_1 = require("../utils/Logger"); const FileUtils_1 = require("../utils/FileUtils"); const i18n_1 = require("../utils/i18n"); class PluginManager { constructor(options = {}) { this.plugins = new Map(); this.hooks = new Map(); this.logger = new Logger_1.Logger(); this.fileUtils = new FileUtils_1.FileUtils(this.logger); this.i18n = new i18n_1.I18n(); this.options = { pluginDir: options.pluginDir || path.join(process.cwd(), 'plugins'), autoLoad: options.autoLoad ?? true, enabledPlugins: options.enabledPlugins || [] }; } /** * Initialize plugin manager */ async initialize() { this.logger.debug(this.i18n.t('plugin.manager_initialized')); if (this.options.autoLoad) { await this.loadPlugins(); } this.logger.success(this.i18n.t('plugin.manager_initialized')); } /** * Load plugins from directory */ async loadPlugins() { try { if (!(await this.fileUtils.exists(this.options.pluginDir))) { this.logger.debug(this.i18n.t('plugin.dir_not_found', { dir: this.options.pluginDir })); return; } const pluginFiles = await this.fileUtils.findFiles('**/*.js', { cwd: this.options.pluginDir }); for (const pluginFile of pluginFiles) { try { await this.loadPlugin(pluginFile); } catch (error) { this.logger.error(this.i18n.t('plugin.failed_load', { name: pluginFile }), error); } } } catch (error) { this.logger.error(this.i18n.t('plugin.failed_load'), error); } } /** * Load a specific plugin */ async loadPlugin(pluginPath) { const pluginName = path.basename(pluginPath, '.js'); // Check if plugin is enabled if (this.options.enabledPlugins.length > 0 && !this.options.enabledPlugins.includes(pluginName)) { this.logger.debug(this.i18n.t('plugin.not_enabled', { name: pluginName })); throw new Error(this.i18n.t('plugin.not_enabled', { name: pluginName })); } // Dynamic import of plugin const pluginModule = await Promise.resolve(`${pluginPath}`).then(s => __importStar(require(s))); const PluginClass = pluginModule.default || pluginModule; if (typeof PluginClass !== 'function') { throw new Error(this.i18n.t('plugin.invalid', { name: pluginName })); } const plugin = new PluginClass(); // Validate plugin structure if (!this.isValidPlugin(plugin)) { throw new Error(this.i18n.t('plugin.invalid', { name: pluginName })); } // Initialize plugin if (plugin.initialize) { // Create a minimal context for plugin initialization const context = { config: { projectName: '', dockerCompose: 'docker compose', configVersion: '1.0', services: {}, plugins: [], cli: {}, backup: {}, monitoring: {}, development: {}, networks: {}, volumes: {} }, logger: this.logger, workingDirectory: process.cwd() }; await plugin.initialize(context); } // Register plugin hooks if (plugin.hooks) { this.registerPluginHooks(pluginName, plugin.hooks); } this.plugins.set(pluginName, plugin); this.logger.success(this.i18n.t('plugin.loaded', { name: pluginName })); return plugin; } /** * Unload a plugin */ async unloadPlugin(pluginName) { const plugin = this.plugins.get(pluginName); if (!plugin) { throw new Error(this.i18n.t('plugin.not_found', { name: pluginName })); } // Cleanup plugin if (plugin.cleanup) { await plugin.cleanup(); } // Unregister hooks this.unregisterPluginHooks(pluginName); this.plugins.delete(pluginName); this.logger.success(this.i18n.t('plugin.unloaded', { name: pluginName })); } /** * Get loaded plugin */ getPlugin(pluginName) { return this.plugins.get(pluginName) || null; } /** * Get all loaded plugins */ getPlugins() { return Array.from(this.plugins.values()); } /** * Check if plugin is loaded */ hasPlugin(pluginName) { return this.plugins.has(pluginName); } /** * Register plugin hooks */ registerPluginHooks(pluginName, hooks) { for (const [hookName, handler] of Object.entries(hooks)) { if (!this.hooks.has(hookName)) { this.hooks.set(hookName, []); } this.hooks.get(hookName).push(handler); this.logger.debug(`Registered hook: ${hookName} for plugin: ${pluginName}`); } } /** * Unregister plugin hooks */ unregisterPluginHooks(_pluginName) { for (const [_hookName, _handlers] of this.hooks.entries()) { // Remove handlers that belong to this plugin // This is a simplified approach - in a real implementation, // you'd need to track which handlers belong to which plugin this.hooks.set(_hookName, []); } } /** * Execute hook */ async executeHook(hookName, ...args) { const handlers = this.hooks.get(hookName) || []; const results = []; for (const handler of handlers) { try { const result = await handler(...args); results.push(result); } catch (error) { this.logger.error(`Hook execution failed: ${hookName}`, error); results.push(null); } } return results; } /** * Validate plugin structure */ isValidPlugin(plugin) { return (typeof plugin === 'object' && plugin !== null && typeof plugin.metadata === 'object' && typeof plugin.metadata.name === 'string' && typeof plugin.metadata.version === 'string'); } /** * Get plugin metadata */ getPluginMetadata() { return Array.from(this.plugins.values()).map(plugin => plugin.metadata); } /** * Enable plugin */ async enablePlugin(pluginName) { if (!this.options.enabledPlugins.includes(pluginName)) { this.options.enabledPlugins.push(pluginName); } if (!this.hasPlugin(pluginName)) { const pluginPath = path.join(this.options.pluginDir, `${pluginName}.js`); await this.loadPlugin(pluginPath); } } /** * Disable plugin */ async disablePlugin(pluginName) { const index = this.options.enabledPlugins.indexOf(pluginName); if (index > -1) { this.options.enabledPlugins.splice(index, 1); } if (this.hasPlugin(pluginName)) { await this.unloadPlugin(pluginName); } } /** * Update plugin configuration */ async updatePluginConfig(pluginName, config) { const plugin = this.getPlugin(pluginName); if (!plugin) { throw new Error(this.i18n.t('plugin.not_found', { name: pluginName })); } // For now, we just log the config update // In a full implementation, this would notify the plugin this.logger.debug(this.i18n.t('plugin.config_updated', { name: pluginName }), config); } /** * Update language for all plugins */ updateLanguage(language) { this.i18n.setLanguage(language); // Update language for all loaded plugins for (const plugin of this.plugins.values()) { if (plugin && typeof plugin.updateLanguage === 'function') { plugin.updateLanguage(language); } } } /** * Cleanup all plugins */ async cleanup() { this.logger.debug(this.i18n.t('plugin.cleanup_completed')); const pluginNames = Array.from(this.plugins.keys()); for (const pluginName of pluginNames) { try { await this.unloadPlugin(pluginName); } catch (error) { this.logger.error(this.i18n.t('plugin.failed_unload', { name: pluginName }), error); } } this.hooks.clear(); this.logger.success(this.i18n.t('plugin.cleanup_completed')); } } exports.PluginManager = PluginManager; //# sourceMappingURL=PluginManager.js.map