UNPKG

concept-lang

Version:

A semantic network system for defining concepts, relationships, and building knowledge graphs with automatic inference

266 lines (255 loc) 9.33 kB
"use strict"; 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.ConceptPluginManager = void 0; const path = __importStar(require("path")); const fs = __importStar(require("fs")); class ConceptPluginManager { constructor(block) { this.plugins = new Map(); this.listeners = new Map(); this.block = block; this.initializeEventTypes(); } initializeEventTypes() { const eventTypes = [ 'concept:added', 'concept:updated', 'pair:added', 'pair:updated', 'data:added', 'data:updated', 'inference:completed', 'block:state:changed', ]; eventTypes.forEach(eventType => { this.listeners.set(eventType, new Set()); }); } async loadPlugin(pathOrName) { try { let pluginPath; // Check if it's a local path if (path.isAbsolute(pathOrName) || pathOrName.startsWith('./') || pathOrName.startsWith('../')) { pluginPath = path.resolve(pathOrName); } else { // Try to resolve as npm package pluginPath = require.resolve(pathOrName); } // Load the plugin const pluginModule = require(pluginPath); const PluginClass = pluginModule.default || pluginModule; if (!PluginClass || typeof PluginClass !== 'function') { throw new Error(`Invalid plugin at ${pluginPath}: must export a ConceptPlugin class`); } // Instantiate the plugin const plugin = new PluginClass(); if (!plugin || typeof plugin !== 'object') { throw new Error(`Invalid plugin at ${pluginPath}: must export a ConceptPlugin object`); } if (!plugin.config || !plugin.config.name) { throw new Error(`Plugin at ${pluginPath} must have a valid config with name`); } if (typeof plugin.registerListeners !== 'function') { throw new Error(`Plugin ${plugin.config.name} must implement registerListeners method`); } // Initialize plugin if method exists if (plugin.initialize) { await plugin.initialize(); } // Set block instance for concept execution if (plugin.setBlock) { plugin.setBlock(this.block); } // Register plugin listeners const pluginListeners = plugin.registerListeners(); for (const [eventType, listener] of pluginListeners) { this.registerListener(eventType, listener); } // Store plugin this.plugins.set(plugin.config.name, plugin); console.log(`✅ Loaded plugin: ${plugin.config.name} v${plugin.config.version}`); return plugin; } catch (error) { console.error(`❌ Failed to load plugin ${pathOrName}:`, error); throw error; } } async unloadPlugin(name) { const plugin = this.plugins.get(name); if (!plugin) { throw new Error(`Plugin ${name} is not loaded`); } // Cleanup plugin if method exists if (plugin.cleanup) { await plugin.cleanup(); } // Remove plugin listeners const pluginListeners = plugin.registerListeners(); for (const [eventType, listener] of pluginListeners) { this.unregisterListener(eventType, listener); } // Remove plugin this.plugins.delete(name); console.log(`✅ Unloaded plugin: ${name}`); } getLoadedPlugins() { return Array.from(this.plugins.values()); } getLoadedPluginNames() { return Array.from(this.plugins.keys()); } registerListener(eventType, listener) { const listeners = this.listeners.get(eventType); if (listeners) { listeners.add(listener); } } unregisterListener(eventType, listener) { const listeners = this.listeners.get(eventType); if (listeners) { listeners.delete(listener); } } async emitEvent(event) { const listeners = this.listeners.get(event.type); if (listeners && listeners.size > 0) { const promises = Array.from(listeners).map(async (listener) => { try { await listener(event); } catch (error) { console.error(`Error in plugin listener for ${event.type}:`, error); } }); await Promise.all(promises); } } getListeners(eventType) { const listeners = this.listeners.get(eventType); return listeners ? Array.from(listeners) : []; } /** * Get all plugin hooks */ getAllPluginHooks() { const hooks = {}; for (const [name, plugin] of this.plugins) { if (plugin.getHooks) { const pluginHooks = plugin.getHooks(); Object.entries(pluginHooks).forEach(([hookName, hookFn]) => { hooks[`${name}:${hookName}`] = hookFn; }); } } return hooks; } /** * Create a plugin configuration file template */ static createPluginTemplate(pluginName, outputDir = './plugins') { const template = `import { ConceptPlugin, PluginConfig, ConceptEvent, ConceptEventType, ConceptListener } from 'concept-lang'; const config: PluginConfig = { name: '${pluginName}', version: '3.0.0', description: 'A concept language plugin', author: 'Your Name', license: 'MIT', main: 'index.js', conceptListeners: ['concept:added', 'data:added'] }; class ${pluginName}Plugin implements ConceptPlugin { readonly config = config; async initialize(): Promise<void> { console.log(\`Initializing \${this.config.name} plugin\`); } async cleanup(): Promise<void> { console.log(\`Cleaning up \${this.config.name} plugin\`); } registerListeners(): Map<ConceptEventType, ConceptListener> { const listeners = new Map<ConceptEventType, ConceptListener>(); // Example: Listen to concept additions listeners.set('concept:added', (event: ConceptEvent) => { console.log('New concept added:', event.data); }); // Example: Listen to data additions listeners.set('data:added', (event: ConceptEvent) => { console.log('New data added:', event.data); }); return listeners; } getHooks() { return { // Example hook that processes 'hello' commands hello: (params: any[]) => { console.log('Hello hook triggered with params:', params); return params; } }; } } export default ${pluginName}Plugin; `; const pluginDir = path.resolve(outputDir, pluginName); if (!fs.existsSync(pluginDir)) { fs.mkdirSync(pluginDir, { recursive: true }); } const filePath = path.join(pluginDir, 'index.ts'); fs.writeFileSync(filePath, template); // Create package.json for the plugin const packageJson = { name: pluginName, version: '3.0.0', description: 'A concept language plugin', main: 'index.js', types: 'index.d.ts', dependencies: { 'concept-lang': '^1.0.0', }, scripts: { build: 'tsc', dev: 'tsc --watch', }, }; fs.writeFileSync(path.join(pluginDir, 'package.json'), JSON.stringify(packageJson, null, 2)); console.log(`✅ Created plugin template at: ${filePath}`); } } exports.ConceptPluginManager = ConceptPluginManager; //# sourceMappingURL=plugin-manager.js.map