UNPKG

@dataql/node

Version:

DataQL core SDK for unified data management with MongoDB and GraphQL - Production Multi-Cloud Ready

329 lines (328 loc) 11.2 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.PluginRegistry = void 0; /** * Plugin Registry Implementation * * Handles plugin discovery, installation, and management. * This is the foundation for a plugin ecosystem around DataQL. */ class PluginRegistry { constructor(registryUrl = "https://registry.dataql.dev") { this.cache = new Map(); this.installed = new Map(); this.registryUrl = registryUrl; } /** * Search for plugins in the registry */ async search(query, type) { try { const params = new URLSearchParams({ q: query }); if (type) params.append("type", type); const response = await fetch(`${this.registryUrl}/search?${params}`); if (!response.ok) { throw new Error(`Registry search failed: ${response.statusText}`); } const results = await response.json(); return results.plugins || []; } catch (error) { console.error("Plugin search failed:", error); return this.searchLocal(query, type); } } /** * Get detailed information about a plugin */ async getPluginInfo(pluginId) { // Check cache first const cached = this.cache.get(pluginId); if (cached) { return cached; } try { const response = await fetch(`${this.registryUrl}/plugins/${pluginId}`); if (!response.ok) { throw new Error(`Plugin not found: ${pluginId}`); } const info = await response.json(); this.cache.set(pluginId, info); return info; } catch (error) { throw new Error(`Failed to get plugin info: ${error.message}`); } } /** * Install a plugin from the registry */ async install(pluginId, version) { try { console.log(`Installing plugin: ${pluginId}${version ? `@${version}` : ""}`); // Get plugin info const info = await this.getPluginInfo(pluginId); const targetVersion = version || info.version; // Download and install plugin await this.downloadPlugin(pluginId, targetVersion); console.log(`Plugin installed successfully: ${pluginId}@${targetVersion}`); } catch (error) { throw new Error(`Plugin installation failed: ${error.message}`); } } /** * Uninstall a plugin */ async uninstall(pluginId) { try { this.installed.delete(pluginId); this.cache.delete(pluginId); // Remove from local storage/filesystem await this.removePluginFiles(pluginId); console.log(`Plugin uninstalled: ${pluginId}`); } catch (error) { throw new Error(`Plugin uninstallation failed: ${error.message}`); } } /** * List installed plugins */ async listInstalled() { const installed = []; for (const [pluginId, plugin] of this.installed) { installed.push({ id: plugin.id, name: plugin.name, description: plugin.description, version: plugin.version, author: plugin.author, type: plugin.type, downloads: 0, rating: 0, tags: [], repository: "", homepage: "", license: "", dependencies: plugin.dependencies || [], peerDependencies: [], createdAt: new Date(), updatedAt: new Date(), }); } return installed; } /** * Update a plugin to a new version */ async update(pluginId, version) { await this.uninstall(pluginId); await this.install(pluginId, version); } /** * Publish a plugin to the registry */ async publish(plugin, manifest) { try { const publishData = { plugin: { id: plugin.id, name: plugin.name, description: plugin.description, version: plugin.version, author: plugin.author, type: plugin.type, dependencies: plugin.dependencies, }, manifest, }; const response = await fetch(`${this.registryUrl}/publish`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(publishData), }); if (!response.ok) { throw new Error(`Publish failed: ${response.statusText}`); } console.log(`Plugin published successfully: ${plugin.id}@${plugin.version}`); } catch (error) { throw new Error(`Plugin publishing failed: ${error.message}`); } } /** * Discover plugins from various sources */ async discoverPlugins(options) { const discovered = []; // Search in specified directories for (const directory of options.directories) { const plugins = await this.discoverFromDirectory(directory, options.patterns); discovered.push(...plugins); } // Auto-install missing plugins if enabled if (options.autoInstall) { for (const plugin of discovered) { if (!this.installed.has(plugin.id)) { try { await this.installLocalPlugin(plugin); } catch (error) { console.warn(`Failed to auto-install plugin ${plugin.id}:`, error.message); } } } } return discovered; } /** * Load a plugin from a manifest */ async loadFromManifest(manifest) { const { plugin: pluginConfig } = manifest.dataql; // Dynamic import of plugin const pluginModule = await Promise.resolve(`${pluginConfig.entry}`).then(s => __importStar(require(s))); const PluginClass = pluginModule.default || pluginModule[pluginConfig.name]; if (!PluginClass) { throw new Error(`Plugin class not found in ${pluginConfig.entry}`); } return new PluginClass(); } /** * Validate plugin compatibility */ validateCompatibility(plugin, dataqlVersion) { // Check if plugin is compatible with current DataQL version // This would implement semver compatibility checking return true; // Simplified for now } /** * Private: Search locally cached plugins */ searchLocal(query, type) { const results = []; const searchTerm = query.toLowerCase(); for (const info of this.cache.values()) { if (type && info.type !== type) continue; if (info.name.toLowerCase().includes(searchTerm) || info.description.toLowerCase().includes(searchTerm) || info.tags.some((tag) => tag.toLowerCase().includes(searchTerm))) { results.push(info); } } return results; } /** * Private: Download plugin from registry */ async downloadPlugin(pluginId, version) { // In a real implementation, this would: // 1. Download the plugin package // 2. Verify signatures/checksums // 3. Extract to local plugin directory // 4. Install dependencies // 5. Register plugin console.log(`Downloading ${pluginId}@${version}...`); // Simulated download await new Promise((resolve) => setTimeout(resolve, 1000)); } /** * Private: Remove plugin files */ async removePluginFiles(pluginId) { // Remove plugin files from local storage/filesystem console.log(`Removing plugin files for ${pluginId}`); } /** * Private: Discover plugins from directory */ async discoverFromDirectory(directory, patterns) { const plugins = []; try { // In a real implementation, this would: // 1. Scan directory for package.json files // 2. Check if they contain dataql.plugin configuration // 3. Load and validate plugins // 4. Return discovered plugins console.log(`Scanning directory for plugins: ${directory}`); // Simulated discovery return plugins; } catch (error) { console.warn(`Failed to discover plugins in ${directory}:`, error.message); return []; } } /** * Private: Install a locally discovered plugin */ async installLocalPlugin(plugin) { this.installed.set(plugin.id, plugin); console.log(`Auto-installed local plugin: ${plugin.id}`); } /** * Get registry statistics */ async getStats() { try { const response = await fetch(`${this.registryUrl}/stats`); if (!response.ok) { throw new Error("Failed to get registry stats"); } return await response.json(); } catch (error) { return { totalPlugins: this.cache.size, pluginsByType: {}, recentlyUpdated: [], popular: [], }; } } /** * Clear registry cache */ clearCache() { this.cache.clear(); } } exports.PluginRegistry = PluginRegistry;