📦 安装

// npm
npm install @metona-team/metona-sqlark

// ESM
import { MetonaSqlark, MeSqlark } from 'metona-sqlark';

// Browser
<script src="metona-sqlark.min.js"></script>
// → window.MetonaSqlark / window.MeSqlark

🏗 创建数据库

MetonaSqlark.create(config) 工厂函数,返回初始化好的实例。

const db = await MetonaSqlark.create({
  name: 'my-app',
  mode: 'hybrid',       // 'memory' | 'disk' | 'hybrid'
  diskEngine: 'indexeddb', // 'indexeddb' | 'opfs'
  version: 1,
});
属性类型默认说明
namestring-数据库名称
mode'memory'|'disk'|'hybrid''hybrid'存储模式
diskEngine'indexeddb'|'opfs''indexeddb'磁盘引擎
versionnumber1版本号

📋 定义表

await db.defineTable('users', {
  id: { type: 'string', primaryKey: true },
  name: { type: 'string', required: true },
  email: { type: 'string', unique: true, index: true },
  age: { type: 'number', default: 0 },
  dept_id: { type: 'number', references: 'departments.id' },
});
字段类型说明
typestring|number|boolean|date|json数据类型
primaryKeyboolean主键
requiredboolean必填
uniqueboolean唯一约束
indexboolean创建索引
defaultunknown默认值
referencesstring外键引用

🔍 SQL 查询

// INSERT
await db.query("INSERT INTO users (id, name, age) VALUES ('1', 'Alice', 30)");

// SELECT
const rows = await db.query('SELECT * FROM users WHERE age > 18 ORDER BY name LIMIT 10');

// UPDATE
await db.query("UPDATE users SET age = 31 WHERE id = '1'");

// DELETE
await db.query("DELETE FROM users WHERE id = '1'");

// DDL
await db.query('DROP TABLE users');

⛓ Query Builder

const users = db.table('users');

// 插入
await users.insert({ id: '1', name: 'Alice' });
await users.insertMany([...]);

// 查询
const result = await users
  .select(['name', 'age'])
  .where({ age: { $gt: 18 }, name: { $like: 'A%' } })
  .orderBy('age', 'desc')
  .limit(10).offset(0)
  .execute();

// 更新/删除
await users.update({ age: 31 }).where({ id: '1' }).execute();
await users.delete().where({ id: '1' }).execute();

🔗 JOIN 查询

// SQL
await db.query(`SELECT u.name, d.name
  FROM users u
  INNER JOIN departments d ON u.dept_id = d.id
  WHERE d.name = 'Engineering'`);

// QueryBuilder
await db.table('users').select()
  .innerJoin('departments', { 'users.dept_id': { $col: 'departments.id' } })
  .execute();

// LEFT JOIN / RIGHT JOIN / CROSS JOIN
.leftJoin('table', on)
.rightJoin('table', on)
.crossJoin('table')

📊 GROUP BY & 聚合

await db.query(`SELECT dept, COUNT(*) as cnt, SUM(salary) as total
  FROM employees
  GROUP BY dept
  HAVING COUNT(*) > 1
  ORDER BY total DESC`);

// 支持的聚合函数:COUNT, SUM, AVG, MIN, MAX
// 支持别名:COUNT(*) AS cnt

🔒 事务

await db.transaction(async (trx) => {
  await trx.table('users').insert({ id: '3', name: 'Charlie' });
  await trx.table('orders').insert({ id: 'o1', userId: '3', amount: 99 });
  // 任何一步失败 → 全部回滚
});

🔄 数据迁移

db.addMigration(2, async (db) => {
  await db.defineTable('products', { ... });
});
await db.migrateTo(2); // 执行所有未执行的迁移

📤 导入导出

// 导出单表
const data = await db.exportTable('users');

// 导出全库
const all = await db.exportAll();

// 导入
await db.importTable('users', data);

🧩 插件钩子

// 14 个生命周期钩子
db.on('beforeInsert', async (row) => {
  console.log('即将插入:', row);
});

db.on('afterQuery', async (sql, result) => {
  console.log('查询完成:', sql);
});
钩子触发时机
beforeCreateTable / afterCreateTable创建表前后
beforeDropTable / afterDropTable删除表前后
beforeInsert / afterInsert插入前后
beforeUpdate / afterUpdate更新前后
beforeDelete / afterDelete删除前后
beforeQuery / afterQuery查询前后
beforeTransaction / afterTransaction事务前后

📡 发布订阅

// 订阅表变更
const unsubscribe = db.subscribe('users', (event) => {
  // event: { type: 'insert'|'update'|'delete', row: {...} }
});

// 取消订阅
unsubscribe();

🔷 TypeScript 泛型

interface User {
  id: string;
  name: string;
  age: number;
}

const users = db.table<User>('users');
await users.insert({ id: '1', name: 'Alice', age: 30 }); // ✅ 类型安全

⚙️ 配置项

import { MetonaSqlark, MeSqlark } from 'metona-sqlark';
// MeSqlark 是 MetonaSqlark 的别名,完全等价