UNPKG

@evolu/web

Version:
86 lines (85 loc) 3 kB
import { bytesToHex, createPreparedStatementsCache, } from "@evolu/common"; import sqlite3InitModule from "@evolu/sqlite-wasm"; // @ts-expect-error Missing types. globalThis.sqlite3ApiConfig = { warn: (arg) => { // Ignore irrelevant warning. // https://github.com/sqlite/sqlite-wasm/issues/62 if (typeof arg === "string" && arg.startsWith("Ignoring inability to install OPFS sqlite3_vfs")) return; // eslint-disable-next-line no-console console.warn(arg); }, }; // Init ASAP. const sqlite3Promise = sqlite3InitModule(); export const createWasmSqliteDriver = async (name, options) => { const sqlite3 = await sqlite3Promise; // This is used to make OPFS default vfs for multipleciphers // @ts-expect-error Missing types (update @evolu/sqlite-wasm types) // eslint-disable-next-line @typescript-eslint/no-unsafe-call sqlite3.capi.sqlite3mc_vfs_create("opfs", 1); let db; if (options?.memory) { db = new sqlite3.oo1.DB(":memory:"); } else if (options?.encryptionKey) { const pool = await sqlite3.installOpfsSAHPoolVfs({ directory: `.${name}` }); db = new pool.OpfsSAHPoolDb("file:evolu1.db?vfs=multipleciphers-opfs-sahpool"); db.exec(` PRAGMA cipher = 'sqlcipher'; PRAGMA legacy = 4; PRAGMA key = "x'${bytesToHex(options.encryptionKey)}'"; `); } else { const pool = await sqlite3.installOpfsSAHPoolVfs({ name }); db = new pool.OpfsSAHPoolDb("file:evolu1.db"); } let isDisposed = false; const cache = createPreparedStatementsCache((sql) => db.prepare(sql), (statement) => { statement.finalize(); }); const driver = { exec: (query, isMutation) => { const prepared = cache.get(query); if (prepared) { prepared.bind(query.parameters); if (isMutation) { prepared.stepReset(); return { rows: [], changes: db.changes(), }; } const rows = []; while (prepared.step()) { rows.push(prepared.get({})); } prepared.reset(); return { rows: rows, changes: 0, }; } const rows = db.exec(query.sql, { returnValue: "resultRows", rowMode: "object", bind: query.parameters, }); const changes = db.changes(); return { rows, changes }; }, export: () => sqlite3.capi.sqlite3_js_db_export(db), [Symbol.dispose]: () => { if (isDisposed) return; isDisposed = true; // poolUtil.unlink? cache[Symbol.dispose](); db.close(); }, }; return driver; };