feat: MetonaSqlark v0.1.12 — 前端TypeScript关系型数据库
- 4种存储引擎:Memory / IndexedDB / OPFS / Hybrid - 完整SQL:SELECT/INSERT/UPDATE/DELETE/JOIN/GROUP BY/HAVING/DISTINCT - Query Builder链式API + TypeScript泛型 - 聚合/事务/插件/发布订阅/迁移/导入导出 - React/Vue集成,264测试,93.46%覆盖率,零运行时依赖
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
node_modules/
|
||||
dist/
|
||||
coverage/
|
||||
.DS_Store
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# metona-sqlark
|
||||
# MetonaSqlark
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/version-0.1.12-blue?style=flat-square" alt="version">
|
||||
@@ -11,35 +11,74 @@
|
||||
|
||||
---
|
||||
|
||||
## ✨ 核心特性
|
||||
|
||||
- 🧠 **双模式存储** — Memory / Disk / Hybrid,内存极速 + 磁盘持久化
|
||||
- ⚡ **完整 SQL** — SELECT / INSERT / UPDATE / DELETE / JOIN / GROUP BY / HAVING / DISTINCT
|
||||
- 🔗 **Query Builder** — 链式 API,TypeScript 类型友好
|
||||
- 📊 **聚合函数** — COUNT / SUM / AVG / MIN / MAX
|
||||
- 🔒 **事务支持** — 原子性操作,失败自动回滚
|
||||
- 🧩 **插件系统** — 14 种生命周期钩子
|
||||
- 📡 **发布订阅** — 表级变更监听
|
||||
- 🔄 **数据迁移** — 版本化 migration 系统
|
||||
- 📤 **导入导出** — JSON 格式全库/单表导入导出
|
||||
- ⚛️ **React / Vue** — 原生 hooks & composables
|
||||
- 📦 **零运行时依赖** — 纯 TypeScript,约 42KB min+gzip
|
||||
|
||||
---
|
||||
|
||||
## 📦 安装
|
||||
|
||||
```bash
|
||||
npm install @metona-team/metona-sqlark
|
||||
```
|
||||
|
||||
```typescript
|
||||
// ESM / TypeScript
|
||||
import { MetonaSqlark, MeSqlark } from '@metona-team/metona-sqlark';
|
||||
> 如果提示找不到包,先配置 scope registry(一次性):
|
||||
> ```bash
|
||||
> npm config set @metona-team:registry https://git.metona.cn/api/packages/MetonaTeam/npm/
|
||||
> ```
|
||||
|
||||
// Browser UMD
|
||||
### CDN / 直接下载
|
||||
|
||||
```html
|
||||
<!-- UMD 格式,暴露 window.MetonaSqlark 和 window.MeSqlark -->
|
||||
<script src="https://git.metona.cn/MetonaTeam/MetonaSqlark/raw/branch/master/dist/metona-sqlark.min.js"></script>
|
||||
```
|
||||
|
||||
或从 [`dist/`](./dist/) 目录下载:
|
||||
- `metona-sqlark.js` — UMD 开发版(含 sourcemap)
|
||||
- `metona-sqlark.min.js` — UMD 压缩版(~42KB)
|
||||
- `metona-sqlark.esm.js` — ES Module
|
||||
- `metona-sqlark.cjs.js` — CommonJS
|
||||
- `metona-sqlark.d.ts` — TypeScript 类型声明
|
||||
|
||||
---
|
||||
|
||||
## 🚀 引入方式
|
||||
|
||||
### ESM / TypeScript
|
||||
|
||||
```typescript
|
||||
import { MetonaSqlark } from '@metona-team/metona-sqlark';
|
||||
// 别名
|
||||
import { MeSqlark } from '@metona-team/metona-sqlark';
|
||||
|
||||
const db = await MetonaSqlark.create({ name: 'my-app', mode: 'hybrid' });
|
||||
```
|
||||
|
||||
### CommonJS
|
||||
|
||||
```javascript
|
||||
const { MetonaSqlark } = require('@metona-team/metona-sqlark');
|
||||
|
||||
(async () => {
|
||||
const db = await MetonaSqlark.create({ name: 'my-app', mode: 'hybrid' });
|
||||
})();
|
||||
```
|
||||
|
||||
### Browser UMD
|
||||
|
||||
```html
|
||||
<script src="metona-sqlark.min.js"></script>
|
||||
// → window.MetonaSqlark / window.MeSqlark
|
||||
<script>
|
||||
(async () => {
|
||||
const db = await window.MetonaSqlark.create({ name: 'my-app', mode: 'hybrid' });
|
||||
// 或 window.MeSqlark(完全等价)
|
||||
})();
|
||||
</script>
|
||||
```
|
||||
|
||||
### ES Module in Browser
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import { MetonaSqlark } from './metona-sqlark.esm.js';
|
||||
const db = await MetonaSqlark.create({ name: 'my-app', mode: 'hybrid' });
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
@@ -49,11 +88,10 @@ import { MetonaSqlark, MeSqlark } from '@metona-team/metona-sqlark';
|
||||
```typescript
|
||||
import { MetonaSqlark } from '@metona-team/metona-sqlark';
|
||||
|
||||
// 创建数据库
|
||||
const db = await MetonaSqlark.create({
|
||||
name: 'my-app',
|
||||
mode: 'hybrid',
|
||||
diskEngine: 'indexeddb',
|
||||
mode: 'hybrid', // 'memory' | 'disk' | 'hybrid'
|
||||
diskEngine: 'indexeddb', // 'indexeddb' | 'opfs'
|
||||
});
|
||||
|
||||
// 定义表
|
||||
@@ -69,9 +107,12 @@ await db.query("INSERT INTO users VALUES ('1', 'Alice', 30, 'alice@demo.com')");
|
||||
const rows = await db.query('SELECT * FROM users WHERE age > 18 ORDER BY name');
|
||||
|
||||
// Query Builder
|
||||
const users = db.table('users');
|
||||
await users.insert({ id: '2', name: 'Bob', age: 25, email: 'bob@demo.com' });
|
||||
const result = await users.select().where({ age: { $gt: 18 } }).orderBy('age', 'desc').execute();
|
||||
const result = await db.table('users')
|
||||
.select(['name', 'age'])
|
||||
.where({ age: { $gt: 18 } })
|
||||
.orderBy('age', 'desc')
|
||||
.limit(10)
|
||||
.execute();
|
||||
|
||||
// JOIN
|
||||
await db.query(`SELECT u.name, o.product FROM users u INNER JOIN orders o ON u.id = o.user_id`);
|
||||
@@ -116,7 +157,8 @@ await db.transaction(async (trx) => {
|
||||
| `db.table(name)` | 获取表操作对象 |
|
||||
| `db.defineTable(name, cols)` | 定义表结构 |
|
||||
| `db.transaction(fn)` | 执行事务 |
|
||||
| `db.exportTable(name)` / `db.exportAll()` | 导出数据 |
|
||||
| `db.exportTable(name)` / `db.exportAll()` | 导出数据 JSON |
|
||||
| `db.importTable(name, data)` | 导入数据 |
|
||||
| `db.addMigration(v, fn)` / `db.migrateTo(v)` | 数据迁移 |
|
||||
| `db.subscribe(table, fn)` | 订阅表变更 |
|
||||
| `db.on(hook, fn)` | 注册钩子 |
|
||||
@@ -135,6 +177,19 @@ const { data, loading, refresh } = useSqlarkQuery(db, 'SELECT * FROM users');
|
||||
|
||||
---
|
||||
|
||||
## 🛠 开发
|
||||
|
||||
```bash
|
||||
npm install # 安装依赖
|
||||
npm run dev # 开发模式(localhost:3001)
|
||||
npm run build # 生产构建(生成 dist/)
|
||||
npm test # 运行测试
|
||||
npm run lint # 代码检查
|
||||
npm run typecheck # 类型检查
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 项目状态
|
||||
|
||||
| 指标 | 数值 |
|
||||
@@ -147,19 +202,6 @@ const { data, loading, refresh } = useSqlarkQuery(db, 'SELECT * FROM users');
|
||||
|
||||
---
|
||||
|
||||
## 🛠 开发
|
||||
|
||||
```bash
|
||||
npm install # 安装依赖
|
||||
npm run dev # 开发模式(localhost:3001)
|
||||
npm run build # 生产构建
|
||||
npm test # 运行测试
|
||||
npm run lint # 代码检查
|
||||
npm run typecheck # 类型检查
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📂 项目结构
|
||||
|
||||
```
|
||||
@@ -181,4 +223,4 @@ src/
|
||||
|
||||
## 📄 License
|
||||
|
||||
MIT © [MetonaTeam](https://git.metona.cn/MetonaTeam)
|
||||
MIT © [MetonaTeam](https://git.metona.cn/MetonaTeam/MetonaSqlark)
|
||||
|
||||
Vendored
+2732
File diff suppressed because it is too large
Load Diff
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+733
@@ -0,0 +1,733 @@
|
||||
/**
|
||||
* metona-sqlark Constants — 类型定义 / 默认配置 / 枚举
|
||||
* @module constants
|
||||
*/
|
||||
/** 存储模式 */
|
||||
type StorageMode = 'memory' | 'disk' | 'hybrid';
|
||||
/** 磁盘引擎类型 */
|
||||
type DiskEngine = 'indexeddb' | 'opfs';
|
||||
/** 字段数据类型 */
|
||||
type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'json';
|
||||
/** 列定义 */
|
||||
interface ColumnDef {
|
||||
/** 字段类型 */
|
||||
type: FieldType;
|
||||
/** 是否主键 */
|
||||
primaryKey?: boolean;
|
||||
/** 是否必填 */
|
||||
required?: boolean;
|
||||
/** 是否唯一 */
|
||||
unique?: boolean;
|
||||
/** 默认值 */
|
||||
default?: unknown;
|
||||
/** 是否创建索引 */
|
||||
index?: boolean;
|
||||
/** 外键引用: 'table.column' */
|
||||
references?: string;
|
||||
/** 字符串最大长度 */
|
||||
maxLength?: number;
|
||||
/** 数字最小值 */
|
||||
min?: number;
|
||||
/** 数字最大值 */
|
||||
max?: number;
|
||||
}
|
||||
/** 表结构定义 */
|
||||
interface TableSchema {
|
||||
/** 表名 */
|
||||
name: string;
|
||||
/** 列定义映射 */
|
||||
columns: Record<string, ColumnDef>;
|
||||
}
|
||||
/** 数据库配置 */
|
||||
interface DatabaseConfig {
|
||||
/** 数据库名称 */
|
||||
name: string;
|
||||
/** 存储模式 */
|
||||
mode?: StorageMode;
|
||||
/** 磁盘引擎(仅 mode='disk'|'hybrid' 时生效) */
|
||||
diskEngine?: DiskEngine;
|
||||
/** 版本号 */
|
||||
version?: number;
|
||||
/** 插件列表 */
|
||||
plugins?: MetonaPlugin[];
|
||||
/** 数据库就绪回调 */
|
||||
onReady?: (db: unknown) => void;
|
||||
/** 错误回调 */
|
||||
onError?: (error: Error) => void;
|
||||
}
|
||||
/** Where 条件操作符 */
|
||||
type WhereOperator = '$eq' | '$ne' | '$gt' | '$gte' | '$lt' | '$lte' | '$in' | '$nin' | '$like' | '$and' | '$or' | '$not';
|
||||
/** 简单条件值:直接相等 */
|
||||
type SimpleCondition = unknown;
|
||||
/** 操作符条件 */
|
||||
type OperatorCondition = Partial<Record<WhereOperator, unknown>>;
|
||||
/** 字段条件:简单值 | 操作符对象 */
|
||||
type FieldCondition = SimpleCondition | OperatorCondition;
|
||||
/** Where 条件对象 */
|
||||
type WhereCondition = Record<string, FieldCondition>;
|
||||
/** 排序方向 */
|
||||
type SortDirection = 'asc' | 'desc';
|
||||
/** 排序定义 */
|
||||
interface OrderBy {
|
||||
/** 列名 */
|
||||
column: string;
|
||||
/** 排序方向 */
|
||||
direction: SortDirection;
|
||||
}
|
||||
/** 查询计划 — 由 Executor 编译 AST 后生成 */
|
||||
interface QueryPlan {
|
||||
/** 表名 */
|
||||
table: string;
|
||||
/** 要返回的列(undefined = 全部,['*'] = 全部) */
|
||||
columns?: string[];
|
||||
/** 过滤条件 */
|
||||
where?: WhereCondition;
|
||||
/** 排序 */
|
||||
orderBy?: OrderBy[];
|
||||
/** 限制条数 */
|
||||
limit?: number;
|
||||
/** 偏移量 */
|
||||
offset?: number;
|
||||
}
|
||||
/** 钩子名称 */
|
||||
type HookName = 'beforeCreateTable' | 'afterCreateTable' | 'beforeDropTable' | 'afterDropTable' | 'beforeInsert' | 'afterInsert' | 'beforeUpdate' | 'afterUpdate' | 'beforeDelete' | 'afterDelete' | 'beforeQuery' | 'afterQuery' | 'beforeTransaction' | 'afterTransaction';
|
||||
/** 插件定义 */
|
||||
interface MetonaPlugin {
|
||||
/** 插件名称 */
|
||||
name: string;
|
||||
/** 插件版本 */
|
||||
version: string;
|
||||
/** 描述 */
|
||||
description?: string;
|
||||
/** 优先级,越大越先执行 */
|
||||
priority?: number;
|
||||
/** 安装 */
|
||||
install(db: unknown): void;
|
||||
/** 销毁 */
|
||||
destroy(): void;
|
||||
}
|
||||
declare const VERSION = "0.1.12";
|
||||
|
||||
/**
|
||||
* metona-sqlark Plugin — 插件系统
|
||||
* @module plugin
|
||||
*
|
||||
* 管理插件的注册、生命周期和钩子调度。
|
||||
*/
|
||||
|
||||
type HookCallback = (...args: unknown[]) => void | Promise<void>;
|
||||
declare class PluginManager {
|
||||
private plugins;
|
||||
private hooks;
|
||||
/** 注册插件 */
|
||||
register(plugin: MetonaPlugin): void;
|
||||
/** 卸载插件 */
|
||||
unregister(pluginName: string): void;
|
||||
/** 获取所有已注册插件 */
|
||||
getPlugins(): MetonaPlugin[];
|
||||
/** 添加钩子回调 */
|
||||
on(hook: HookName, callback: HookCallback): void;
|
||||
/** 移除钩子回调 */
|
||||
off(hook: HookName, callback: HookCallback): void;
|
||||
/** 触发钩子 */
|
||||
trigger(hook: HookName, ...args: unknown[]): Promise<void>;
|
||||
/** 销毁所有插件 */
|
||||
destroy(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark Engine Interface — 存储引擎抽象接口
|
||||
* @module engine/interface
|
||||
*/
|
||||
|
||||
interface IStorageEngine {
|
||||
/** 引擎名称 */
|
||||
readonly name: string;
|
||||
/** 打开数据库 */
|
||||
open(dbName: string, version: number): Promise<void>;
|
||||
/** 关闭数据库 */
|
||||
close(): Promise<void>;
|
||||
/** 检查数据库是否已打开 */
|
||||
isOpen(): boolean;
|
||||
/** 创建表 */
|
||||
createTable(schema: TableSchema): Promise<void>;
|
||||
/** 删除表 */
|
||||
dropTable(tableName: string): Promise<void>;
|
||||
/** 检查表是否存在 */
|
||||
hasTable(tableName: string): Promise<boolean>;
|
||||
/** 获取所有表名 */
|
||||
getTableNames(): Promise<string[]>;
|
||||
/** 获取表结构 */
|
||||
getTableSchema(tableName: string): Promise<TableSchema | null>;
|
||||
/** 插入行,返回主键值列表 */
|
||||
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
|
||||
/** 查询行 */
|
||||
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
|
||||
/** 更新行,返回影响行数 */
|
||||
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
|
||||
/** 删除行,返回影响行数 */
|
||||
delete(tableName: string, query: QueryPlan): Promise<number>;
|
||||
/** 计数 */
|
||||
count(tableName: string, query?: QueryPlan): Promise<number>;
|
||||
/** 清空表数据(保留结构) */
|
||||
clear(tableName: string): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark Query AST — 查询抽象语法树类型定义
|
||||
* @module query/ast
|
||||
*
|
||||
* QueryBuilder 和 SQL Parser 统一输出此 AST,
|
||||
* Executor 只认 AST,保证两种查询接口行为一致。
|
||||
*/
|
||||
|
||||
/** 列引用,'*' 表示所有列;支持 'table.column' 格式 */
|
||||
type ColumnRef = string;
|
||||
/** JOIN 类型 */
|
||||
type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'CROSS';
|
||||
/** JOIN 子句 */
|
||||
interface JoinClause {
|
||||
type: JoinType;
|
||||
table: string;
|
||||
alias?: string;
|
||||
on: WhereCondition;
|
||||
}
|
||||
interface ASTColumnDef {
|
||||
name: string;
|
||||
type: string;
|
||||
primaryKey?: boolean;
|
||||
unique?: boolean;
|
||||
required?: boolean;
|
||||
default?: unknown;
|
||||
index?: boolean;
|
||||
maxLength?: number;
|
||||
min?: number;
|
||||
max?: number;
|
||||
}
|
||||
interface CreateTableStatement {
|
||||
type: 'CREATE_TABLE';
|
||||
name: string;
|
||||
columns: ASTColumnDef[];
|
||||
}
|
||||
interface DropTableStatement {
|
||||
type: 'DROP_TABLE';
|
||||
name: string;
|
||||
}
|
||||
interface InsertStatement {
|
||||
type: 'INSERT';
|
||||
into: string;
|
||||
columns?: string[];
|
||||
values: unknown[][];
|
||||
}
|
||||
interface UpdateStatement {
|
||||
type: 'UPDATE';
|
||||
table: string;
|
||||
sets: Record<string, unknown>;
|
||||
where: WhereCondition;
|
||||
}
|
||||
interface DeleteStatement {
|
||||
type: 'DELETE';
|
||||
from: string;
|
||||
where: WhereCondition;
|
||||
}
|
||||
interface SelectStatement {
|
||||
type: 'SELECT';
|
||||
columns: ColumnRef[];
|
||||
distinct?: boolean;
|
||||
from: string;
|
||||
/** 主表别名 */
|
||||
alias?: string;
|
||||
/** JOIN 子句列表 */
|
||||
joins?: JoinClause[];
|
||||
where: WhereCondition;
|
||||
/** GROUP BY */
|
||||
groupBy?: string[];
|
||||
/** HAVING */
|
||||
having?: WhereCondition;
|
||||
orderBy?: OrderBy[];
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
type Statement = SelectStatement | InsertStatement | UpdateStatement | DeleteStatement | CreateTableStatement | DropTableStatement;
|
||||
|
||||
/**
|
||||
* metona-sqlark Query Executor — AST 执行器
|
||||
* @module query/executor
|
||||
*
|
||||
* JOIN / GROUP BY / DISTINCT 逻辑在此层处理。
|
||||
*/
|
||||
|
||||
declare class QueryExecutor {
|
||||
private engine;
|
||||
constructor(engine: IStorageEngine);
|
||||
execute(stmt: Statement): Promise<unknown>;
|
||||
private executeSelect;
|
||||
private executeJoinSelect;
|
||||
private prefixRow;
|
||||
/** 嵌套循环连接(优化:避免 ON 时对象扩散) */
|
||||
private joinRows;
|
||||
private executeGroupBy;
|
||||
private computeAggregate;
|
||||
private executeDistinct;
|
||||
private executeInsert;
|
||||
private executeUpdate;
|
||||
private executeDelete;
|
||||
private executeCreateTable;
|
||||
private executeDropTable;
|
||||
getEngine(): IStorageEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark Query Builder — 链式查询构建器
|
||||
* @module query/builder
|
||||
*
|
||||
* 链式调用 → 构建 AST → 执行引擎操作。
|
||||
* 支持 JOIN(需要 Executor)。
|
||||
*/
|
||||
|
||||
declare class SelectQueryBuilder {
|
||||
private engine;
|
||||
private tableName;
|
||||
private _columns;
|
||||
private _where;
|
||||
private _orderBy;
|
||||
private _limit?;
|
||||
private _offset?;
|
||||
private _joins;
|
||||
private _alias?;
|
||||
private _executor?;
|
||||
constructor(engine: IStorageEngine, tableName: string, _columns?: string[], executor?: QueryExecutor);
|
||||
/** 主表别名 */
|
||||
as(alias: string): this;
|
||||
/** INNER JOIN */
|
||||
innerJoin(table: string, on: WhereCondition, alias?: string): this;
|
||||
/** LEFT JOIN */
|
||||
leftJoin(table: string, on: WhereCondition, alias?: string): this;
|
||||
/** RIGHT JOIN */
|
||||
rightJoin(table: string, on: WhereCondition, alias?: string): this;
|
||||
/** CROSS JOIN */
|
||||
crossJoin(table: string, alias?: string): this;
|
||||
/** 通用 JOIN */
|
||||
join(table: string, on: WhereCondition, alias?: string): this;
|
||||
private _addJoin;
|
||||
/** 添加过滤条件 */
|
||||
where(condition: WhereCondition): this;
|
||||
/** 排序 */
|
||||
orderBy(column: string, direction?: SortDirection): this;
|
||||
/** 限制返回条数 */
|
||||
limit(n: number): this;
|
||||
/** 偏移量 */
|
||||
offset(n: number): this;
|
||||
/** 执行查询 */
|
||||
execute(): Promise<Record<string, unknown>[]>;
|
||||
/** 获取 AST */
|
||||
toAST(): SelectStatement;
|
||||
}
|
||||
declare class UpdateQueryBuilder {
|
||||
private engine;
|
||||
private tableName;
|
||||
private _updates;
|
||||
private _where;
|
||||
constructor(engine: IStorageEngine, tableName: string, _updates: Record<string, unknown>);
|
||||
where(condition: WhereCondition): this;
|
||||
execute(): Promise<number>;
|
||||
toAST(): UpdateStatement;
|
||||
}
|
||||
declare class DeleteQueryBuilder {
|
||||
private engine;
|
||||
private tableName;
|
||||
private _where;
|
||||
constructor(engine: IStorageEngine, tableName: string);
|
||||
where(condition: WhereCondition): this;
|
||||
execute(): Promise<number>;
|
||||
toAST(): DeleteStatement;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark Table — 表操作 API
|
||||
* @module table/table
|
||||
*/
|
||||
|
||||
declare class Table<T = Record<string, unknown>> {
|
||||
readonly name: string;
|
||||
private engine;
|
||||
private schema;
|
||||
private executor;
|
||||
constructor(engine: IStorageEngine, tableName: string, executor?: QueryExecutor);
|
||||
getSchema(): Promise<TableSchema>;
|
||||
insert(row: T & Record<string, unknown>): Promise<string>;
|
||||
insertMany(rows: (T & Record<string, unknown>)[]): Promise<string[]>;
|
||||
select(columns?: string[]): SelectQueryBuilder;
|
||||
update(updates: Partial<T> & Record<string, unknown>): UpdateQueryBuilder;
|
||||
delete(): DeleteQueryBuilder;
|
||||
count(where?: Record<string, unknown>): Promise<number>;
|
||||
clear(): Promise<void>;
|
||||
drop(): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark Transaction — 事务管理
|
||||
* @module transaction
|
||||
*
|
||||
* 封装多操作事务,保证原子性。
|
||||
* v0.0.1: 基于引擎层操作实现,IndexedDB 引擎利用原生事务。
|
||||
*/
|
||||
|
||||
declare class Transaction {
|
||||
private engine;
|
||||
private tables;
|
||||
private completed;
|
||||
constructor(engine: IStorageEngine);
|
||||
/** 获取表操作对象 */
|
||||
table(tableName: string): Table;
|
||||
/** 标记事务完成(由 TransactionManager 调用) */
|
||||
_markCompleted(): void;
|
||||
/** 是否已完成 */
|
||||
isCompleted(): boolean;
|
||||
}
|
||||
|
||||
declare class MetonaSqlark {
|
||||
/** 数据库名称 */
|
||||
readonly name: string;
|
||||
/** 存储模式 */
|
||||
readonly mode: string;
|
||||
/** 版本号 */
|
||||
private _version;
|
||||
/** 获取版本号 */
|
||||
get version(): number;
|
||||
private engine;
|
||||
private executor;
|
||||
private transactionManager;
|
||||
private pluginManager;
|
||||
private config;
|
||||
private ready;
|
||||
private tableCache;
|
||||
constructor(config: DatabaseConfig);
|
||||
/** 初始化数据库(创建引擎、打开连接) */
|
||||
init(): Promise<void>;
|
||||
/** 检查是否就绪 */
|
||||
isReady(): boolean;
|
||||
/** 创建表 */
|
||||
defineTable(name: string, columns: Record<string, ColumnDef>): Promise<void>;
|
||||
/** 获取表操作对象 */
|
||||
table(name: string): Table;
|
||||
/** 删除表 */
|
||||
dropTable(name: string): Promise<void>;
|
||||
/** 获取所有表名 */
|
||||
getTableNames(): Promise<string[]>;
|
||||
/** 执行 SQL 字符串查询 */
|
||||
query(sql: string): Promise<unknown>;
|
||||
/** 执行事务 */
|
||||
transaction<T>(fn: (trx: Transaction) => Promise<T>): Promise<T>;
|
||||
/** 导出表数据为 JSON */
|
||||
exportTable(tableName: string): Promise<Record<string, unknown>[]>;
|
||||
/** 导入 JSON 数据到表 */
|
||||
importTable(tableName: string, data: Record<string, unknown>[]): Promise<string[]>;
|
||||
/** 导出整个数据库为 JSON */
|
||||
exportAll(): Promise<Record<string, Record<string, unknown>[]>>;
|
||||
private listeners;
|
||||
/** 订阅表变更 */
|
||||
subscribe(tableName: string, callback: (event: {
|
||||
type: string;
|
||||
row?: unknown;
|
||||
}) => void): () => void;
|
||||
/** 触发变更事件 */
|
||||
emit(tableName: string, event: {
|
||||
type: string;
|
||||
row?: unknown;
|
||||
}): void;
|
||||
private migrations;
|
||||
/** 注册迁移 */
|
||||
addMigration(version: number, up: (db: MetonaSqlark) => Promise<void>): void;
|
||||
/** 执行迁移到指定版本 */
|
||||
migrateTo(targetVersion: number): Promise<void>;
|
||||
/** 获取插件管理器 */
|
||||
getPluginManager(): PluginManager;
|
||||
/** 注册钩子 */
|
||||
on(hook: HookName, callback: HookCallback): void;
|
||||
/** 关闭数据库 */
|
||||
close(): Promise<void>;
|
||||
/** 获取底层引擎 */
|
||||
getEngine(): IStorageEngine;
|
||||
private createEngine;
|
||||
private ensureReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark Memory Engine — 基于 Map 的内存存储引擎
|
||||
* @module engine/memory
|
||||
*/
|
||||
|
||||
declare class MemoryEngine implements IStorageEngine {
|
||||
readonly name = "memory";
|
||||
private tables;
|
||||
private schemas;
|
||||
private indexes;
|
||||
private opened;
|
||||
open(_dbName: string, _version: number): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
isOpen(): boolean;
|
||||
createTable(schema: TableSchema): Promise<void>;
|
||||
dropTable(tableName: string): Promise<void>;
|
||||
hasTable(tableName: string): Promise<boolean>;
|
||||
getTableNames(): Promise<string[]>;
|
||||
getTableSchema(tableName: string): Promise<TableSchema | null>;
|
||||
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
|
||||
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
|
||||
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
|
||||
delete(tableName: string, query: QueryPlan): Promise<number>;
|
||||
count(tableName: string, query?: QueryPlan): Promise<number>;
|
||||
clear(tableName: string): Promise<void>;
|
||||
private ensureTable;
|
||||
private getPrimaryKey;
|
||||
private validateRow;
|
||||
private checkType;
|
||||
/** O(1) 唯一性检查:利用哈希索引 */
|
||||
private checkUniqueness;
|
||||
/** 索引查找 */
|
||||
private tryIndexLookup;
|
||||
/** 更新索引 */
|
||||
private updateIndexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark IndexedDB Engine — 基于 IndexedDB 的持久化存储引擎
|
||||
* @module engine/indexeddb
|
||||
*/
|
||||
|
||||
declare class IndexedDBEngine implements IStorageEngine {
|
||||
readonly name = "indexeddb";
|
||||
private db;
|
||||
private dbName;
|
||||
private version;
|
||||
private memoryCache;
|
||||
open(dbName: string, version: number): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
isOpen(): boolean;
|
||||
createTable(schema: TableSchema): Promise<void>;
|
||||
dropTable(tableName: string): Promise<void>;
|
||||
hasTable(tableName: string): Promise<boolean>;
|
||||
getTableNames(): Promise<string[]>;
|
||||
getTableSchema(tableName: string): Promise<TableSchema | null>;
|
||||
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
|
||||
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
|
||||
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
|
||||
delete(tableName: string, query: QueryPlan): Promise<number>;
|
||||
count(tableName: string, query?: QueryPlan): Promise<number>;
|
||||
clear(tableName: string): Promise<void>;
|
||||
private ensureDB;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark OPFS Engine — 基于 Origin Private File System 的持久化存储引擎
|
||||
* @module engine/opfs
|
||||
*
|
||||
* 使用 JSON-per-table 文件存储方案。
|
||||
* 目录结构:{dbName}/tables/{tableName}.json
|
||||
*/
|
||||
|
||||
declare class OPFSEngine implements IStorageEngine {
|
||||
readonly name = "opfs";
|
||||
private root;
|
||||
private tablesDir;
|
||||
private dbName;
|
||||
private memoryCache;
|
||||
open(dbName: string, version: number): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
isOpen(): boolean;
|
||||
createTable(schema: TableSchema): Promise<void>;
|
||||
dropTable(tableName: string): Promise<void>;
|
||||
hasTable(tableName: string): Promise<boolean>;
|
||||
getTableNames(): Promise<string[]>;
|
||||
getTableSchema(tableName: string): Promise<TableSchema | null>;
|
||||
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
|
||||
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
|
||||
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
|
||||
delete(tableName: string, query: QueryPlan): Promise<number>;
|
||||
count(tableName: string, query?: QueryPlan): Promise<number>;
|
||||
clear(tableName: string): Promise<void>;
|
||||
private ensureDir;
|
||||
private writeTableData;
|
||||
private readTableData;
|
||||
/** 从 OPFS 加载表数据到内存缓存 */
|
||||
loadTableIntoMemory(tableName: string, schema: TableSchema): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark Hybrid Engine — 内存 + 磁盘混合存储引擎
|
||||
* @module hybrid/index
|
||||
*
|
||||
* 采用 write-through 策略:
|
||||
* - 所有写操作同时写入内存和磁盘
|
||||
* - 所有读操作直接从内存返回
|
||||
* - 数据库打开时从磁盘加载数据到内存
|
||||
*/
|
||||
|
||||
declare class HybridEngine implements IStorageEngine {
|
||||
readonly name = "hybrid";
|
||||
private memoryEngine;
|
||||
private diskEngine;
|
||||
private diskEngineType;
|
||||
constructor(diskEngine?: DiskEngine);
|
||||
open(dbName: string, version: number): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
isOpen(): boolean;
|
||||
createTable(schema: TableSchema): Promise<void>;
|
||||
dropTable(tableName: string): Promise<void>;
|
||||
hasTable(tableName: string): Promise<boolean>;
|
||||
getTableNames(): Promise<string[]>;
|
||||
getTableSchema(tableName: string): Promise<TableSchema | null>;
|
||||
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
|
||||
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
|
||||
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
|
||||
delete(tableName: string, query: QueryPlan): Promise<number>;
|
||||
count(tableName: string, query?: QueryPlan): Promise<number>;
|
||||
clear(tableName: string): Promise<void>;
|
||||
/** 获取磁盘引擎类型 */
|
||||
getDiskEngineType(): DiskEngine;
|
||||
/** 获取内存引擎(供内部使用) */
|
||||
getMemoryEngine(): MemoryEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark SQL Parser — 递归下降语法分析器
|
||||
* @module sql/parser
|
||||
*
|
||||
* Token 流 → AST Statement。
|
||||
* 支持的语法是标准 SQL 的子集。
|
||||
*/
|
||||
|
||||
/** 解析 SQL 字符串为 AST Statement */
|
||||
declare function parse(sql: string): Statement;
|
||||
|
||||
/**
|
||||
* metona-sqlark SQL Token Types — 词法单元定义
|
||||
* @module sql/tokens
|
||||
*/
|
||||
declare enum TokenType {
|
||||
SELECT = "SELECT",
|
||||
FROM = "FROM",
|
||||
WHERE = "WHERE",
|
||||
INSERT = "INSERT",
|
||||
INTO = "INTO",
|
||||
VALUES = "VALUES",
|
||||
UPDATE = "UPDATE",
|
||||
SET = "SET",
|
||||
DELETE = "DELETE",
|
||||
CREATE = "CREATE",
|
||||
TABLE = "TABLE",
|
||||
DROP = "DROP",
|
||||
ORDER = "ORDER",
|
||||
BY = "BY",
|
||||
ASC = "ASC",
|
||||
DESC = "DESC",
|
||||
LIMIT = "LIMIT",
|
||||
OFFSET = "OFFSET",
|
||||
AND = "AND",
|
||||
OR = "OR",
|
||||
NOT = "NOT",
|
||||
LIKE = "LIKE",
|
||||
IN = "IN",
|
||||
PRIMARY = "PRIMARY",
|
||||
KEY = "KEY",
|
||||
UNIQUE = "UNIQUE",
|
||||
DEFAULT = "DEFAULT",
|
||||
NULL = "NULL",
|
||||
TRUE = "TRUE",
|
||||
FALSE = "FALSE",
|
||||
INNER = "INNER",
|
||||
LEFT = "LEFT",
|
||||
RIGHT = "RIGHT",
|
||||
CROSS = "CROSS",
|
||||
JOIN = "JOIN",
|
||||
ON = "ON",
|
||||
AS = "AS",
|
||||
OUTER = "OUTER",
|
||||
GROUP = "GROUP",
|
||||
HAVING = "HAVING",
|
||||
COUNT = "COUNT",
|
||||
SUM = "SUM",
|
||||
AVG = "AVG",
|
||||
MIN = "MIN",
|
||||
MAX = "MAX",
|
||||
DISTINCT = "DISTINCT",
|
||||
IDENTIFIER = "IDENTIFIER",
|
||||
STRING = "STRING",
|
||||
NUMBER = "NUMBER",
|
||||
COMMA = "COMMA",
|
||||
LPAREN = "LPAREN",
|
||||
RPAREN = "RPAREN",
|
||||
SEMICOLON = "SEMICOLON",
|
||||
EQ = "EQ",
|
||||
NEQ = "NEQ",
|
||||
GT = "GT",
|
||||
GTE = "GTE",
|
||||
LT = "LT",
|
||||
LTE = "LTE",
|
||||
STAR = "STAR",
|
||||
DOT = "DOT",
|
||||
EOF = "EOF",
|
||||
ILLEGAL = "ILLEGAL"
|
||||
}
|
||||
interface Token {
|
||||
type: TokenType;
|
||||
value: string;
|
||||
position: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* metona-sqlark SQL Lexer — 词法分析器
|
||||
* @module sql/lexer
|
||||
*
|
||||
* 将 SQL 字符串切分为 Token 流。
|
||||
*/
|
||||
|
||||
/** 将 SQL 字符串解析为 Token 列表 */
|
||||
declare function tokenize(sql: string): Token[];
|
||||
|
||||
/**
|
||||
* metona-sqlark — 入口文件
|
||||
* @module metona-sqlark
|
||||
* @version 0.1.12
|
||||
*
|
||||
* 前端关系型数据库,内存与磁盘双模式。
|
||||
* 支持 Query Builder 链式 API 和 SQL 字符串查询。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 创建数据库实例并初始化
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const db = await MetonaSqlark.create({
|
||||
* name: 'my-app',
|
||||
* mode: 'hybrid',
|
||||
* });
|
||||
*
|
||||
* await db.defineTable('users', {
|
||||
* id: { type: 'string', primaryKey: true },
|
||||
* name: { type: 'string', required: true },
|
||||
* });
|
||||
*
|
||||
* await db.table('users').insert({ id: '1', name: 'Alice' });
|
||||
* const results = await db.query('SELECT * FROM users');
|
||||
* ```
|
||||
*/
|
||||
declare function create(config: DatabaseConfig): Promise<MetonaSqlark>;
|
||||
declare const api: {
|
||||
VERSION: string;
|
||||
version: string;
|
||||
create: typeof create;
|
||||
MetonaSqlark: typeof MetonaSqlark;
|
||||
MeSqlark: typeof MetonaSqlark;
|
||||
};
|
||||
declare global {
|
||||
interface Window {
|
||||
MetonaSqlark: typeof api;
|
||||
MeSqlark: typeof api;
|
||||
}
|
||||
}
|
||||
|
||||
declare const MeSqlark: typeof MetonaSqlark;
|
||||
|
||||
export { ColumnDef, DatabaseConfig, DeleteStatement, DiskEngine, FieldType, HybridEngine, IStorageEngine, IndexedDBEngine, InsertStatement, MeSqlark, MemoryEngine, MetonaSqlark, OPFSEngine, SelectStatement, Statement, StorageMode, Table, TableSchema, UpdateStatement, VERSION, api, create, api as default, parse, tokenize };
|
||||
Vendored
+2716
File diff suppressed because it is too large
Load Diff
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+2738
File diff suppressed because it is too large
Load Diff
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
+3
-3
@@ -34,7 +34,7 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://git.metona.cn/MetonaTeam/metona-sqlark.git"
|
||||
"url": "git+https://git.metona.cn/MetonaTeam/MetonaSqlark.git"
|
||||
},
|
||||
"keywords": [
|
||||
"database",
|
||||
@@ -49,9 +49,9 @@
|
||||
"author": "thzxx",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://git.metona.cn/MetonaTeam/metona-sqlark/issues"
|
||||
"url": "https://git.metona.cn/MetonaTeam/MetonaSqlark/issues"
|
||||
},
|
||||
"homepage": "https://git.metona.cn/MetonaTeam/metona-sqlark#readme",
|
||||
"homepage": "https://git.metona.cn/MetonaTeam/MetonaSqlark#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.0",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.22.0",
|
||||
|
||||
+4
-4
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>在线演示 — metona-sqlark</title>
|
||||
<title>在线演示 — MetonaSqlark</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg:#0a0a0f; --surface:#0d1117; --surface2:#161b22; --border:#30363d;
|
||||
@@ -87,7 +87,7 @@
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<div class="logo"><div class="icon">◈</div><span>metona-sqlark</span></div>
|
||||
<div class="logo"><div class="icon">◈</div><span>MetonaSqlark</span></div>
|
||||
<nav>
|
||||
<a href="index.html">首页</a>
|
||||
<a href="docs.html">文档</a>
|
||||
@@ -104,7 +104,7 @@
|
||||
<div class="tab" data-tab="builder">Query Builder</div>
|
||||
</div>
|
||||
<div class="editor-area">
|
||||
<textarea id="sql-input" placeholder="输入 SQL 语句... SELECT * FROM users WHERE age > 18 INSERT INTO users VALUES ('4', 'Diana', 'diana@test.com', 28) SELECT u.name, o.amount FROM users u INNER JOIN orders o ON u.id = o.user_id">-- 欢迎使用 metona-sqlark 在线演示 🚀
|
||||
<textarea id="sql-input" placeholder="输入 SQL 语句... SELECT * FROM users WHERE age > 18 INSERT INTO users VALUES ('4', 'Diana', 'diana@test.com', 28) SELECT u.name, o.amount FROM users u INNER JOIN orders o ON u.id = o.user_id">-- 欢迎使用 MetonaSqlark 在线演示 🚀
|
||||
-- 已预置 users / orders 表数据,试试以下查询:
|
||||
|
||||
SELECT * FROM users;
|
||||
@@ -335,7 +335,7 @@ document.querySelectorAll('.tab').forEach(tab => {
|
||||
|
||||
// Boot
|
||||
initDB().then(() => {
|
||||
console.log('✅ metona-sqlark demo ready');
|
||||
console.log('✅ MetonaSqlark demo ready');
|
||||
// Auto-run initial query
|
||||
setTimeout(runQuery, 200);
|
||||
});
|
||||
|
||||
+5
-5
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>API 文档 — metona-sqlark</title>
|
||||
<title>API 文档 — MetonaSqlark</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg:#0a0a0f; --surface:#14141f; --surface2:#1a1a2e; --border:#2a2a45;
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
<header>
|
||||
<div class="inner">
|
||||
<div class="logo"><div class="icon">◈</div><span>metona-sqlark</span></div>
|
||||
<div class="logo"><div class="icon">◈</div><span>MetonaSqlark</span></div>
|
||||
<nav>
|
||||
<a href="index.html">首页</a>
|
||||
<a href="docs.html" class="nav-active">文档</a>
|
||||
@@ -102,10 +102,10 @@
|
||||
|
||||
<h2 id="install">📦 安装</h2>
|
||||
<pre><span class="c">// npm</span>
|
||||
npm install @metona-team/metona-sqlark
|
||||
npm install @metona-team/MetonaSqlark
|
||||
|
||||
<span class="c">// ESM</span>
|
||||
<span class="k">import</span> { MetonaSqlark, MeSqlark } <span class="k">from</span> <span class="s">'metona-sqlark'</span>;
|
||||
<span class="k">import</span> { MetonaSqlark, MeSqlark } <span class="k">from</span> <span class="s">'MetonaSqlark'</span>;
|
||||
|
||||
<span class="c">// Browser</span>
|
||||
<script src=<span class="s">"metona-sqlark.min.js"</span>></script>
|
||||
@@ -273,7 +273,7 @@ db.<span class="f">on</span>(<span class="s">'afterQuery'</span>, <span class="k
|
||||
<span class="k">await</span> users.<span class="f">insert</span>({ <span class="s">id</span>: <span class="s">'1'</span>, <span class="s">name</span>: <span class="s">'Alice'</span>, <span class="s">age</span>: <span class="n">30</span> }); <span class="c">// ✅ 类型安全</span></pre>
|
||||
|
||||
<h2 id="config">⚙️ 配置项</h2>
|
||||
<pre><span class="k">import</span> { MetonaSqlark, MeSqlark } <span class="k">from</span> <span class="s">'metona-sqlark'</span>;
|
||||
<pre><span class="k">import</span> { MetonaSqlark, MeSqlark } <span class="k">from</span> <span class="s">'MetonaSqlark'</span>;
|
||||
<span class="c">// MeSqlark 是 MetonaSqlark 的别名,完全等价</span></pre>
|
||||
|
||||
</main>
|
||||
|
||||
+66
-6
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>metona-sqlark — 前端 TypeScript 数据库</title>
|
||||
<title>MetonaSqlark — 前端 TypeScript 数据库</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0a0a0f;
|
||||
@@ -136,13 +136,13 @@
|
||||
<div class="container">
|
||||
<div class="logo">
|
||||
<div class="icon">◈</div>
|
||||
<span>metona-sqlark</span>
|
||||
<span>MetonaSqlark</span>
|
||||
</div>
|
||||
<nav>
|
||||
<a href="index.html">首页</a>
|
||||
<a href="docs.html">文档</a>
|
||||
<a href="demo.html">演示</a>
|
||||
<a href="https://git.metona.cn/MetonaTeam/metona-sqlark" target="_blank">GitHub</a>
|
||||
<a href="https://git.metona.cn/MetonaTeam/MetonaSqlark" target="_blank">GitHub</a>
|
||||
</nav>
|
||||
<a href="demo.html" class="btn btn-primary">立即体验</a>
|
||||
</div>
|
||||
@@ -161,11 +161,71 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Install -->
|
||||
<section style="padding:20px 0 60px;">
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2>📦 <span>安装</span>引入</h2>
|
||||
<p>多种方式,按需选择</p>
|
||||
</div>
|
||||
<div class="feature-grid">
|
||||
<div class="feature-card">
|
||||
<div class="icon">📦</div>
|
||||
<h3>npm (Gitea Registry)</h3>
|
||||
<div class="code-block" style="font-size:0.8rem;margin-top:12px;padding:14px;">
|
||||
<span class="comment"># 配置 registry</span>
|
||||
npm config set @metona-team:registry https://git.metona.cn/api/packages/MetonaTeam/npm/
|
||||
|
||||
<span class="comment"># 安装</span>
|
||||
npm install @metona-team/metona-sqlark
|
||||
</div>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="icon">🌐</div>
|
||||
<h3>CDN / Browser UMD</h3>
|
||||
<div class="code-block" style="font-size:0.8rem;margin-top:12px;padding:14px;">
|
||||
<span class="comment"><!-- 直接引用 dist 产物 --></span>
|
||||
<<span class="keyword">script</span> src=<span class="string">"metona-sqlark.min.js"</span>></script>
|
||||
<<span class="keyword">script</span>>
|
||||
<span class="keyword">const</span> db = <span class="keyword">await</span> window.<span class="func">MetonaSqlark</span>.create({...});
|
||||
<span class="comment">// 或 window.MeSqlark(别名)</span>
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="icon">⚡</div>
|
||||
<h3>ESM / TypeScript</h3>
|
||||
<div class="code-block" style="font-size:0.8rem;margin-top:12px;padding:14px;">
|
||||
<span class="keyword">import</span> { MetonaSqlark, MeSqlark }
|
||||
<span class="keyword">from</span> <span class="string">'@metona-team/metona-sqlark'</span>;
|
||||
|
||||
<span class="keyword">const</span> db = <span class="keyword">await</span> <span class="func">MetonaSqlark</span>.create({
|
||||
<span class="string">name</span>: <span class="string">'my-app'</span>,
|
||||
<span class="string">mode</span>: <span class="string">'hybrid'</span>,
|
||||
});
|
||||
</div>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="icon">🔧</div>
|
||||
<h3>CommonJS</h3>
|
||||
<div class="code-block" style="font-size:0.8rem;margin-top:12px;padding:14px;">
|
||||
<span class="keyword">const</span> { MetonaSqlark } =
|
||||
<span class="func">require</span>(<span class="string">'@metona-team/metona-sqlark'</span>);
|
||||
|
||||
(<span class="keyword">async</span> () => {
|
||||
<span class="keyword">const</span> db = <span class="keyword">await</span> <span class="func">MetonaSqlark</span>.create({...});
|
||||
})();
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Features -->
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2>为什么选择 <span>metona-sqlark</span></h2>
|
||||
<h2>为什么选择 <span>MetonaSqlark</span></h2>
|
||||
<p>专为前端打造的数据库引擎</p>
|
||||
</div>
|
||||
<div class="feature-grid">
|
||||
@@ -238,7 +298,7 @@
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2>用<span>数字</span>说话</h2>
|
||||
<p>metona-sqlark 的核心指标</p>
|
||||
<p>MetonaSqlark 的核心指标</p>
|
||||
</div>
|
||||
<div class="stats">
|
||||
<div class="stat-card"><div class="num">235+</div><div class="label">测试用例</div></div>
|
||||
@@ -251,7 +311,7 @@
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p>© 2026 <a href="https://git.metona.cn/MetonaTeam/metona-sqlark">MetonaTeam</a>. MIT License. Built with TypeScript.</p>
|
||||
<p>© 2026 <a href="https://git.metona.cn/MetonaTeam/MetonaSqlark">MetonaTeam</a>. MIT License. Built with TypeScript.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user