feat: metona-sqlark v0.1.12 — 前端TypeScript关系型数据库
- 4种存储引擎:Memory / IndexedDB / OPFS / Hybrid - 完整SQL支持:SELECT/INSERT/UPDATE/DELETE/JOIN/GROUP BY/HAVING/DISTINCT - Query Builder链式API + TypeScript泛型支持 - 聚合函数:COUNT/SUM/AVG/MIN/MAX - 事务、插件系统(14 hooks)、发布订阅、数据迁移、导入导出 - React/Vue框架集成 - 264个测试用例,93.46%覆盖率 - 零运行时依赖
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 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): 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);
|
||||
}
|
||||
// 安装
|
||||
plugin.install(null); // 实际引用由 MetonaSqlark 注入
|
||||
}
|
||||
|
||||
/** 卸载插件 */
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user