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:
thzxx
2026-07-26 15:00:01 +08:00
commit e2a590c5b1
60 changed files with 16359 additions and 0 deletions
+91
View File
@@ -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();
}
}