UNPKG

skayn-trading-sdk

Version:

Professional Bitcoin trading strategy backtesting framework with institutional-grade architecture

192 lines (162 loc) 4.89 kB
/** * Plugin Registry System * Central registry for all pluggable components in the trading framework */ class PluginRegistry { constructor() { this.plugins = new Map(); this.instances = new Map(); this.dependencies = new Map(); this.hooks = new Map(); } /** * Register a plugin type and its interface */ registerPluginType(type, interfaceClass, config = {}) { this.plugins.set(type, { interface: interfaceClass, implementations: new Map(), config: { singleton: config.singleton || false, required: config.required || false, dependencies: config.dependencies || [] } }); } /** * Register a plugin implementation */ registerPlugin(type, name, pluginClass, metadata = {}) { if (!this.plugins.has(type)) { throw new Error(`Plugin type '${type}' not registered. Register the type first.`); } const plugin = this.plugins.get(type); // Validate plugin implements required interface if (!this.validateInterface(pluginClass, plugin.interface)) { throw new Error(`Plugin '${name}' does not implement required interface for type '${type}'`); } plugin.implementations.set(name, { class: pluginClass, metadata: { name, version: metadata.version || '1.0.0', description: metadata.description || '', author: metadata.author || 'Unknown', dependencies: metadata.dependencies || [], ...metadata } }); console.log(`🔌 Registered plugin: ${type}/${name} v${metadata.version || '1.0.0'}`); } /** * Get plugin instance (with dependency injection) */ getInstance(type, name, config = {}) { const instanceKey = `${type}:${name}`; // Return existing instance if singleton const pluginType = this.plugins.get(type); if (pluginType?.config.singleton && this.instances.has(instanceKey)) { return this.instances.get(instanceKey); } if (!this.plugins.has(type)) { throw new Error(`Plugin type '${type}' not registered`); } const plugin = this.plugins.get(type); if (!plugin.implementations.has(name)) { throw new Error(`Plugin '${name}' not found for type '${type}'`); } const implementation = plugin.implementations.get(name); // Resolve dependencies const dependencies = this.resolveDependencies(implementation.metadata.dependencies); // Create instance with dependency injection const instance = new implementation.class(config, dependencies); // Cache if singleton if (pluginType.config.singleton) { this.instances.set(instanceKey, instance); } return instance; } /** * List available plugins for a type */ listPlugins(type) { if (!this.plugins.has(type)) { return []; } const plugin = this.plugins.get(type); return Array.from(plugin.implementations.entries()).map(([name, impl]) => ({ name, ...impl.metadata })); } /** * Check if plugin exists */ hasPlugin(type, name) { return this.plugins.has(type) && this.plugins.get(type).implementations.has(name); } /** * Validate plugin implements interface */ validateInterface(pluginClass, interfaceClass) { const requiredMethods = Object.getOwnPropertyNames(interfaceClass.prototype) .filter(method => method !== 'constructor'); const pluginMethods = Object.getOwnPropertyNames(pluginClass.prototype) .filter(method => method !== 'constructor'); return requiredMethods.every(method => pluginMethods.includes(method)); } /** * Resolve plugin dependencies */ resolveDependencies(dependencies) { const resolved = {}; for (const dep of dependencies) { const [type, name] = dep.split(':'); resolved[dep] = this.getInstance(type, name); } return resolved; } /** * Register hook for plugin events */ registerHook(event, callback) { if (!this.hooks.has(event)) { this.hooks.set(event, []); } this.hooks.get(event).push(callback); } /** * Trigger hook event */ triggerHook(event, data = {}) { if (this.hooks.has(event)) { for (const callback of this.hooks.get(event)) { try { callback(data); } catch (error) { console.error(`Hook error for event '${event}':`, error); } } } } /** * Get registry stats */ getStats() { const stats = { pluginTypes: this.plugins.size, totalPlugins: 0, activeInstances: this.instances.size, hooks: this.hooks.size, types: {} }; for (const [type, plugin] of this.plugins) { const count = plugin.implementations.size; stats.totalPlugins += count; stats.types[type] = count; } return stats; } } module.exports = PluginRegistry;