knowhub
Version:
Synchronize AI coding–agent knowledge files (rules, templates, guidelines) across your project.
130 lines • 4.12 kB
JavaScript
import { resolve } from "node:path";
import { PluginNotFoundError } from "./errors.js";
/**
* Registry for managing available plugins
*/
export class PluginRegistry {
plugins = new Map();
/**
* Register a plugin in the registry
*/
register(plugin) {
this.plugins.set(plugin.name, plugin);
}
/**
* Resolve a plugin by name
*/
resolve(name) {
const plugin = this.plugins.get(name);
if (!plugin) {
throw new PluginNotFoundError(name);
}
return plugin;
}
/**
* Check if a plugin is registered
*/
has(name) {
return this.plugins.has(name);
}
/**
* Get all registered plugin names
*/
listAvailable() {
return Array.from(this.plugins.keys()).sort();
}
/**
* Get all registered plugins
*/
getAll() {
return Array.from(this.plugins.values());
}
/**
* Unregister a plugin
*/
unregister(name) {
return this.plugins.delete(name);
}
/**
* Clear all registered plugins
*/
clear() {
this.plugins.clear();
}
/**
* Get the number of registered plugins
*/
size() {
return this.plugins.size;
}
/**
* Dynamically load and register a plugin from a file path
*/
async loadPlugin(pluginPath, projectRoot) {
try {
const absolutePath = resolve(projectRoot, pluginPath);
const pluginModule = await import(absolutePath);
let pluginInstance;
if (pluginModule.default && typeof pluginModule.default === "function") {
try {
const instance = new pluginModule.default();
if (instance.name && typeof instance.fetch === "function") {
pluginInstance = instance;
}
}
catch {
// Not a valid plugin constructor
}
}
else if (pluginModule.default &&
typeof pluginModule.default === "object" &&
pluginModule.default.name &&
typeof pluginModule.default.fetch === "function") {
pluginInstance = pluginModule.default;
}
else {
for (const exportName of Object.keys(pluginModule)) {
const exportValue = pluginModule[exportName];
if (exportValue && typeof exportValue === "function") {
try {
const instance = new exportValue();
if (instance.name && typeof instance.fetch === "function") {
pluginInstance = instance;
break;
}
}
catch { }
}
else if (exportValue &&
typeof exportValue === "object" &&
exportValue.name &&
typeof exportValue.fetch === "function") {
pluginInstance = exportValue;
break;
}
}
}
if (!pluginInstance) {
throw new Error(`No valid plugin found in ${pluginPath}. Plugin must export a class or instance implementing the Plugin interface.`);
}
this.register(pluginInstance);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(`Failed to load plugin from ${pluginPath}: ${errorMessage}`);
}
}
/**
* Load multiple plugins from file paths
*/
async loadPlugins(pluginPaths, projectRoot) {
for (const pluginPath of pluginPaths) {
await this.loadPlugin(pluginPath, projectRoot);
}
}
}
/**
* Default global plugin registry
*/
export const pluginRegistry = new PluginRegistry();
//# sourceMappingURL=registry.js.map