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
+134
View File
@@ -0,0 +1,134 @@
/**
* Core 全覆盖测试 — 导入导出、迁移、发布订阅、钩子
*/
import { MetonaSqlark } from '../src/core';
describe('Core 全覆盖', () => {
let db: MetonaSqlark;
beforeEach(async () => {
db = new MetonaSqlark({ name: 'test-coverage', mode: 'memory' });
await db.init();
await db.defineTable('users', {
id: { type: 'string', primaryKey: true },
name: { type: 'string', required: true },
});
await db.table('users').insertMany([
{ id: '1', name: 'Alice' },
{ id: '2', name: 'Bob' },
]);
});
afterEach(async () => { await db.close(); });
// ---- 导入导出 ----
describe('导入导出', () => {
it('exportTable 导出单表', async () => {
const data = await db.exportTable('users');
expect(data).toHaveLength(2);
expect(data[0].name).toBe('Alice');
});
it('exportAll 导出全库', async () => {
const all = await db.exportAll();
expect(all.users).toHaveLength(2);
});
it('importTable 导入数据', async () => {
await db.defineTable('temp', { id: { type: 'string', primaryKey: true }, val: { type: 'number' } });
await db.importTable('temp', [{ id: 'a', val: 1 }, { id: 'b', val: 2 }]);
expect(await db.table('temp').count()).toBe(2);
});
});
// ---- 发布订阅 ----
describe('发布订阅', () => {
it('subscribe 注册监听', () => {
const fn = jest.fn();
const unsub = db.subscribe('users', fn);
expect(typeof unsub).toBe('function');
});
it('unsubscribe 取消监听', () => {
const fn = jest.fn();
const unsub = db.subscribe('users', fn);
unsub();
db.emit('users', { type: 'insert', row: { id: '3' } });
expect(fn).not.toHaveBeenCalled();
});
it('emit 触发监听', () => {
const fn = jest.fn();
db.subscribe('users', fn);
db.emit('users', { type: 'insert', row: { id: '3', name: 'Charlie' } });
expect(fn).toHaveBeenCalledWith({ type: 'insert', row: { id: '3', name: 'Charlie' } });
});
});
// ---- 迁移 ----
describe('迁移系统', () => {
it('addMigration + migrateTo', async () => {
let migrated = false;
db.addMigration(2, async (d) => {
migrated = true;
await d.defineTable('new_table', { id: { type: 'string', primaryKey: true } });
});
await db.migrateTo(2);
expect(migrated).toBe(true);
const tables = await db.getTableNames();
expect(tables).toContain('new_table');
});
it('不执行已过期的迁移', async () => {
let count = 0;
db.addMigration(1, async () => { count++; }); // version <= current
db.addMigration(2, async () => { count++; });
await db.migrateTo(2);
// version 1 <= current version 1, should be skipped
expect(count).toBe(1);
});
});
// ---- 钩子 ----
describe('钩子系统', () => {
it('on 注册钩子 (通过 pluginManager)', () => {
const fn = jest.fn();
db.getPluginManager().on('beforeInsert', fn);
db.getPluginManager().trigger('beforeInsert', { id: '3' });
expect(fn).toHaveBeenCalled();
});
it('getPluginManager 返回插件管理器', () => {
const pm = db.getPluginManager();
expect(pm).toBeDefined();
expect(typeof pm.on).toBe('function');
});
});
// ---- 生命周期 ----
describe('生命周期', () => {
it('close 关闭数据库', async () => {
await db.close();
expect(db.isReady()).toBe(false);
});
it('getEngine 返回引擎', () => {
const engine = db.getEngine();
expect(engine).toBeDefined();
expect(engine.name).toBe('memory');
});
it('未初始化时操作抛出错误', () => {
const db2 = new MetonaSqlark({ name: 'x', mode: 'memory' });
expect(() => db2.table('x')).toThrow('not initialized');
});
});
// ---- 别名 ----
describe('MeSqlark 别名', () => {
it('MeSqlark === MetonaSqlark', () => {
const { MeSqlark } = require('../src/index');
expect(MeSqlark).toBe(MetonaSqlark);
});
});
});