feat(database): add database service abstraction with libsql/turso backend (#3472)

This commit is contained in:
Huang Xin
2026-03-05 02:01:35 +08:00
parent bd957a4eb8
commit 5273ef75dc
26 changed files with 2738 additions and 668 deletions
@@ -0,0 +1,66 @@
import { DatabaseService, DatabaseExecResult, DatabaseRow } from '@/types/database';
interface WasmRunResult {
changes: number;
lastInsertRowid: number;
}
interface WasmStatement {
run(...params: unknown[]): Promise<WasmRunResult>;
all(...params: unknown[]): Promise<Record<string, unknown>[]>;
}
interface WasmDatabase {
prepare(sql: string): WasmStatement;
exec(sql: string): Promise<void>;
close(): Promise<void>;
}
export class WebDatabaseService implements DatabaseService {
private db: WasmDatabase;
private constructor(db: WasmDatabase) {
this.db = db;
}
static async open(path: string): Promise<WebDatabaseService> {
const mod = await import('@tursodatabase/database-wasm');
const db = (await mod.connect(path)) as unknown as WasmDatabase;
return new WebDatabaseService(db);
}
async execute(sql: string, params: unknown[] = []): Promise<DatabaseExecResult> {
const stmt = this.db.prepare(sql);
const result = await stmt.run(...params);
return {
rowsAffected: result.changes,
lastInsertId: Number(result.lastInsertRowid),
};
}
async select<T extends DatabaseRow = DatabaseRow>(
sql: string,
params: unknown[] = [],
): Promise<T[]> {
const stmt = this.db.prepare(sql);
const rows = await stmt.all(...params);
return rows as T[];
}
async batch(statements: string[]): Promise<void> {
await this.db.exec('BEGIN');
try {
for (const sql of statements) {
await this.db.exec(sql);
}
await this.db.exec('COMMIT');
} catch (error: unknown) {
await this.db.exec('ROLLBACK');
throw error;
}
}
async close(): Promise<void> {
await this.db.close();
}
}