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
+146
View File
@@ -0,0 +1,146 @@
/**
* metona-sqlark Hybrid Engine — 内存 + 磁盘混合存储引擎
* @module hybrid/index
*
* 采用 write-through 策略:
* - 所有写操作同时写入内存和磁盘
* - 所有读操作直接从内存返回
* - 数据库打开时从磁盘加载数据到内存
*/
import type { IStorageEngine } from '../engine/interface';
import type { QueryPlan, TableSchema, DiskEngine } from '../constants';
import { MemoryEngine } from '../engine/memory';
import { IndexedDBEngine } from '../engine/indexeddb';
import { OPFSEngine } from '../engine/opfs';
// ---------------------------------------------------------------------------
// HybridEngine
// ---------------------------------------------------------------------------
export class HybridEngine implements IStorageEngine {
readonly name = 'hybrid';
private memoryEngine: MemoryEngine;
private diskEngine: IStorageEngine;
private diskEngineType: DiskEngine;
constructor(diskEngine: DiskEngine = 'indexeddb') {
this.memoryEngine = new MemoryEngine();
this.diskEngineType = diskEngine;
this.diskEngine = diskEngine === 'opfs' ? new OPFSEngine() : new IndexedDBEngine();
}
// ---- 生命周期 ----
async open(dbName: string, version: number): Promise<void> {
// 先打开磁盘引擎
await this.diskEngine.open(dbName, version);
// 再打开内存引擎
await this.memoryEngine.open(dbName, version);
// 从磁盘加载现存表
const tableNames = await this.diskEngine.getTableNames();
for (const tableName of tableNames) {
const schema = await this.diskEngine.getTableSchema(tableName);
if (!schema) continue;
// 在内存中创建表
await this.memoryEngine.createTable(schema);
// 从磁盘加载数据到内存
const rows = await this.diskEngine.find(tableName, { table: tableName });
if (rows.length > 0) {
try {
await this.memoryEngine.insert(tableName, rows);
} catch (e) {
// eslint-disable-next-line no-console
console.warn(`[metona-sqlark] Failed to load table "${tableName}" data from disk:`, e);
}
}
}
}
async close(): Promise<void> {
await this.memoryEngine.close();
await this.diskEngine.close();
}
isOpen(): boolean {
return this.memoryEngine.isOpen() && this.diskEngine.isOpen();
}
// ---- 表管理 ----
async createTable(schema: TableSchema): Promise<void> {
await this.memoryEngine.createTable(schema);
await this.diskEngine.createTable(schema);
}
async dropTable(tableName: string): Promise<void> {
await this.memoryEngine.dropTable(tableName);
await this.diskEngine.dropTable(tableName);
}
async hasTable(tableName: string): Promise<boolean> {
return this.memoryEngine.hasTable(tableName);
}
async getTableNames(): Promise<string[]> {
return this.memoryEngine.getTableNames();
}
async getTableSchema(tableName: string): Promise<TableSchema | null> {
return this.memoryEngine.getTableSchema(tableName);
}
// ---- CRUDwrite-through 策略) ----
async insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]> {
const pks = await this.memoryEngine.insert(tableName, rows);
// write-through: 同步写入磁盘
await this.diskEngine.insert(tableName, rows);
return pks;
}
async find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]> {
// 直接从内存读取
return this.memoryEngine.find(tableName, query);
}
async update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number> {
const count = await this.memoryEngine.update(tableName, query, updates);
// write-through: 同步更新磁盘
await this.diskEngine.update(tableName, query, updates);
return count;
}
async delete(tableName: string, query: QueryPlan): Promise<number> {
const count = await this.memoryEngine.delete(tableName, query);
// write-through: 同步删除磁盘
await this.diskEngine.delete(tableName, query);
return count;
}
async count(tableName: string, query?: QueryPlan): Promise<number> {
return this.memoryEngine.count(tableName, query);
}
async clear(tableName: string): Promise<void> {
await this.memoryEngine.clear(tableName);
await this.diskEngine.clear(tableName);
}
// ---- 引擎信息 ----
/** 获取磁盘引擎类型 */
getDiskEngineType(): DiskEngine {
return this.diskEngineType;
}
/** 获取内存引擎(供内部使用) */
getMemoryEngine(): MemoryEngine {
return this.memoryEngine;
}
}