release: v0.2.2 AriaEngine OPFS 自研存储后端 — 零依赖纯文件系统
This commit is contained in:
@@ -25,6 +25,7 @@ import { WAL } from './wal/log';
|
||||
import { WALRecordType, type WALRecord } from './types';
|
||||
import { CheckpointManager } from './wal/checkpoint';
|
||||
import { IndexedDBBackend, MemoryBackend, type IStorageBackend } from './store/backend';
|
||||
import { OPFSBackend } from './store/opfs_backend';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// AriaEngine
|
||||
@@ -63,7 +64,9 @@ export class AriaEngine implements IStorageEngine {
|
||||
this.dbName = dbName;
|
||||
|
||||
// 1. 存储后端
|
||||
if (this.config.storageBackend === 'indexeddb') {
|
||||
if (this.config.storageBackend === 'opfs') {
|
||||
this.backend = new OPFSBackend();
|
||||
} else if (this.config.storageBackend === 'indexeddb') {
|
||||
this.backend = new IndexedDBBackend();
|
||||
} else {
|
||||
this.backend = new MemoryBackend();
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* AriaEngine OPFS Backend — 基于 Origin Private File System 的自研存储后端
|
||||
* @module engine/aria/store/opfs_backend
|
||||
*
|
||||
* 零外部依赖,纯浏览器文件系统 API。
|
||||
* 每个 key 对应 OPFS 目录下的一个二进制文件。
|
||||
*
|
||||
* 浏览器要求:Chrome 102+ / Edge 102+
|
||||
*/
|
||||
import type { IStorageBackend } from './backend';
|
||||
|
||||
export class OPFSBackend implements IStorageBackend {
|
||||
private root: FileSystemDirectoryHandle | null = null;
|
||||
private dbDir: FileSystemDirectoryHandle | null = null;
|
||||
private dbName = '';
|
||||
|
||||
async open(name: string): Promise<void> {
|
||||
this.dbName = name;
|
||||
this.root = await navigator.storage.getDirectory();
|
||||
this.dbDir = await this.root.getDirectoryHandle(name, { create: true });
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
this.dbDir = null;
|
||||
this.root = null;
|
||||
}
|
||||
|
||||
isOpen(): boolean {
|
||||
return this.dbDir !== null;
|
||||
}
|
||||
|
||||
async read(key: string): Promise<ArrayBuffer | null> {
|
||||
if (!this.dbDir) return null;
|
||||
try {
|
||||
const fh = await this.dbDir.getFileHandle(key);
|
||||
const file = await fh.getFile();
|
||||
return await file.arrayBuffer();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async write(key: string, data: ArrayBuffer): Promise<void> {
|
||||
if (!this.dbDir) return;
|
||||
const fh = await this.dbDir.getFileHandle(key, { create: true });
|
||||
const writable = await fh.createWritable();
|
||||
await writable.write(data);
|
||||
await writable.close();
|
||||
}
|
||||
|
||||
async delete(key: string): Promise<void> {
|
||||
if (!this.dbDir) return;
|
||||
try {
|
||||
await this.dbDir.removeEntry(key);
|
||||
} catch {
|
||||
// 文件不存在则忽略
|
||||
}
|
||||
}
|
||||
|
||||
async listKeys(): Promise<string[]> {
|
||||
if (!this.dbDir) return [];
|
||||
const keys: string[] = [];
|
||||
// FileSystemDirectoryHandle.entries() 返回 AsyncIterable,使用 any 绕过 dts 生成限制
|
||||
const dir = this.dbDir as any;
|
||||
for await (const [name] of dir.entries()) {
|
||||
keys.push(name);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
async exists(key: string): Promise<boolean> {
|
||||
if (!this.dbDir) return false;
|
||||
try {
|
||||
await this.dbDir.getFileHandle(key);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async clear(): Promise<void> {
|
||||
if (!this.dbDir) return;
|
||||
const dir = this.dbDir as any;
|
||||
for await (const [name] of dir.entries()) {
|
||||
try { await this.dbDir!.removeEntry(name); } catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -86,5 +86,6 @@ export { Table } from './table/table';
|
||||
export { parse } from './sql/parser';
|
||||
export { tokenize } from './sql/lexer';
|
||||
|
||||
// AriaEngine 类型
|
||||
// AriaEngine 类型 & 后端
|
||||
export type { AriaEngineConfig } from './engine/aria/types';
|
||||
export { OPFSBackend } from './engine/aria/store/opfs_backend';
|
||||
|
||||
Reference in New Issue
Block a user