@api-buddy/plugin-utils
Version:
Shared utilities for API Buddy plugins
136 lines (119 loc) • 3.53 kB
text/typescript
import type {
Plugin,
PluginContext,
PluginHook,
Logger
} from '@api-buddy/types';
export interface PluginManagerOptions {
cwd?: string;
logger?: Partial<Logger>;
pluginsDir?: string | string[];
nodeModulesDirs?: string[];
}
/**
* A simple plugin manager that handles loading and managing plugins.
* Can be extended to add custom plugin functionality.
*/
export class SimplePluginManager {
protected plugins: Map<string, Plugin> = new Map();
protected context: PluginContext;
protected options: {
pluginsDir: string[];
nodeModulesDirs: string[];
};
private defaultLogger: Logger = {
info: console.log,
warn: console.warn,
error: console.error,
debug: console.debug,
};
constructor(options: PluginManagerOptions = {}) {
this.options = {
pluginsDir: Array.isArray(options.pluginsDir)
? options.pluginsDir
: options.pluginsDir
? [options.pluginsDir]
: [],
nodeModulesDirs: options.nodeModulesDirs || [],
};
this.context = {
cwd: options.cwd || process.cwd(),
logger: { ...this.defaultLogger, ...(options.logger || {}) },
config: {},
data: new Map(),
utils: {
registerHook: () => {},
unregisterHook: () => {},
callHook: async () => undefined,
},
};
}
/**
* Register a plugin
*/
async registerPlugin(plugin: Plugin): Promise<void> {
if (this.plugins.has(plugin.name)) {
throw new Error(`Plugin with name '${plugin.name}' is already registered`);
}
try {
// Initialize the plugin if it has an initialize method
if (typeof plugin.initialize === 'function') {
await plugin.initialize(this.context);
}
this.plugins.set(plugin.name, plugin);
this.context.logger.info(`Registered plugin: ${plugin.name}@${plugin.version}`);
} catch (error) {
this.context.logger.error(`Failed to initialize plugin ${plugin.name}:`, error);
throw error;
}
}
/**
* Get a registered plugin by name
*/
getPlugin<T extends Plugin = Plugin>(name: string): T | undefined {
return this.plugins.get(name) as T | undefined;
}
/**
* Get all registered plugins
*/
getPlugins(): Plugin[] {
return Array.from(this.plugins.values());
}
/**
* Check if a plugin is registered
*/
hasPlugin(name: string): boolean {
return this.plugins.has(name);
}
/**
* Unregister a plugin
*/
async unregisterPlugin(name: string): Promise<boolean> {
const plugin = this.plugins.get(name);
if (!plugin) return false;
try {
// Clean up the plugin if it has a cleanup method
if (typeof plugin.cleanup === 'function') {
await plugin.cleanup(this.context);
}
this.plugins.delete(name);
this.context.logger.info(`Unregistered plugin: ${name}`);
return true;
} catch (error) {
this.context.logger.error(`Failed to cleanup plugin ${name}:`, error);
return false;
}
}
/**
* Load plugins from the specified directories
*/
async loadPlugins(): Promise<void> {
// Implementation for loading plugins from directories
// This is a simplified version - in a real implementation, you would:
// 1. Scan the plugin directories for plugin modules
// 2. Import and initialize each plugin
// 3. Register them with the plugin manager
this.context.logger.info('Loading plugins...');
// Actual implementation would go here
}
}