Files
MetonaSqlark/src/plugin/index.ts
T
thzxx eb79b2198e
CI / test (18.x) (push) Successful in 10m4s
CI / test (20.x) (push) Successful in 10m0s
CI / test (22.x) (push) Successful in 9m58s
CI / test (24.x) (push) Successful in 9m58s
release: v0.2.5 — 质量加固 + Bug修复 + 性能优化 + SQL扩展
2026-07-29 21:50:53 +08:00

92 lines
2.5 KiB
TypeScript

/**
* metona-sqlark Plugin — 插件系统
* @module plugin
*
* 管理插件的注册、生命周期和钩子调度。
*/
import type { MetonaPlugin, HookName } from '../constants';
// ---------------------------------------------------------------------------
// Hook 回调类型
// ---------------------------------------------------------------------------
export type HookCallback = (...args: unknown[]) => void | Promise<void>;
// ---------------------------------------------------------------------------
// PluginManager
// ---------------------------------------------------------------------------
export class PluginManager {
private plugins: MetonaPlugin[] = [];
private hooks: Map<HookName, HookCallback[]> = 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<void> {
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();
}
}