Files
MetonaSqlark/dist/metona-sqlark.d.ts
T
thzxx 7858cf3720
CI / test (18.x) (push) Successful in 9m49s
CI / test (20.x) (push) Successful in 9m50s
CI / test (22.x) (push) Successful in 9m48s
CI / test (24.x) (push) Successful in 9m45s
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%覆盖率,零运行时依赖
2026-07-26 15:18:45 +08:00

734 lines
22 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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 };