/** * metona-sqlark Plugin — 插件系统 * @module plugin * * 管理插件的注册、生命周期和钩子调度。 */ import type { MetonaPlugin, HookName } from '../constants'; // --------------------------------------------------------------------------- // Hook 回调类型 // --------------------------------------------------------------------------- export type HookCallback = (...args: unknown[]) => void | Promise; // --------------------------------------------------------------------------- // PluginManager // --------------------------------------------------------------------------- export class PluginManager { private plugins: MetonaPlugin[] = []; private hooks: Map = new Map(); /** 注册插件 */ register(plugin: MetonaPlugin, db?: unknown): void { // 按优先级插入 const priority = plugin.priority ?? 0; const insertIndex = this.plugins.findIndex( (p) => (p.priority ?? 0) < priority, ); if (insertIndex === -1) { this.plugins.push(plugin); } else { this.plugins.splice(insertIndex, 0, plugin); } // 安装(传入 db 实例) plugin.install(db); } /** 卸载插件 */ unregister(pluginName: string): void { const idx = this.plugins.findIndex((p) => p.name === pluginName); if (idx !== -1) { this.plugins[idx].destroy(); this.plugins.splice(idx, 1); } } /** 获取所有已注册插件 */ getPlugins(): MetonaPlugin[] { return [...this.plugins]; } /** 添加钩子回调 */ on(hook: HookName, callback: HookCallback): void { const callbacks = this.hooks.get(hook) ?? []; callbacks.push(callback); this.hooks.set(hook, callbacks); } /** 移除钩子回调 */ off(hook: HookName, callback: HookCallback): void { const callbacks = this.hooks.get(hook); if (callbacks) { const idx = callbacks.indexOf(callback); if (idx !== -1) callbacks.splice(idx, 1); } } /** 触发钩子 */ async trigger(hook: HookName, ...args: unknown[]): Promise { const callbacks = this.hooks.get(hook); if (callbacks) { for (const cb of callbacks) { await cb(...args); } } } /** 销毁所有插件 */ destroy(): void { for (const plugin of this.plugins) { try { plugin.destroy(); } catch (e) { // eslint-disable-next-line no-console console.warn(`[metona-sqlark] Plugin "${plugin.name}" destroy error:`, e); } } this.plugins = []; this.hooks.clear(); } }