sqlocal
Version:
SQLocal makes it easy to run SQLite3 in the browser, backed by the origin private file system.
94 lines (78 loc) • 2.17 kB
text/typescript
import type { JsStorageDb } from '@sqlite.org/sqlite-wasm';
import type {
DriverConfig,
Sqlite3InitModule,
SQLocalDriver,
} from '../types.js';
import { SQLiteMemoryDriver } from './sqlite-memory-driver.js';
/**
* A SQLocal driver that implements the interface needed for
* interacting with SQLite databases in localStorage or sessionStorage.
*/
export class SQLiteKvvfsDriver
extends SQLiteMemoryDriver
implements SQLocalDriver
{
declare protected db?: JsStorageDb;
constructor(
override readonly storageType: 'local' | 'session',
sqlite3InitModule?: Sqlite3InitModule
) {
super(sqlite3InitModule);
}
override async init(config: DriverConfig): Promise<void> {
const flags = this.getFlags(config);
if (config.readOnly) {
throw new Error(
`SQLite storage type "${this.storageType}" does not support read-only mode.`
);
}
if (!this.sqlite3InitModule) {
const { default: sqlite3InitModule } =
await import('@sqlite.org/sqlite-wasm');
this.sqlite3InitModule = sqlite3InitModule;
}
if (!this.sqlite3) {
this.sqlite3 = await this.sqlite3InitModule();
}
if (this.db) {
await this.destroy();
}
this.db = new this.sqlite3.oo1.JsStorageDb({
filename: this.storageType,
flags,
});
this.config = config;
this.initWriteHook();
}
override async isDatabasePersisted(): Promise<boolean> {
return navigator.storage?.persisted();
}
override async getDatabaseSizeBytes(): Promise<number> {
if (!this.db) throw new Error('Driver not initialized');
return this.db.storageSize();
}
override async import(
database:
| ArrayBuffer
| Uint8Array<ArrayBuffer>
| ReadableStream<Uint8Array<ArrayBuffer>>
): Promise<void> {
const memdb = new SQLiteMemoryDriver();
await memdb.init({});
await memdb.import(database);
await this.clear();
await memdb.exec({
sql: `VACUUM INTO 'file:${this.storageType}?vfs=kvvfs'`,
});
await memdb.destroy();
}
override async clear(): Promise<void> {
if (!this.db) throw new Error('Driver not initialized');
this.db.clearStorage();
}
override async destroy(): Promise<void> {
this.closeDb();
this.writeCallbacks.clear();
}
}