58 lines
1.5 KiB
JavaScript
58 lines
1.5 KiB
JavaScript
import SQLiteESMFactory from '@journeyapps/wa-sqlite/dist/wa-sqlite.mjs'
|
|
import * as SQLite from '@journeyapps/wa-sqlite'
|
|
import { SCHEMA_SQL } from './schema.js'
|
|
|
|
let db = null
|
|
let sqlite3 = null
|
|
const tableListeners = new Map()
|
|
|
|
let initPromise = null
|
|
|
|
export function initDatabase() {
|
|
if (initPromise) return initPromise
|
|
initPromise = _init()
|
|
return initPromise
|
|
}
|
|
|
|
async function _init() {
|
|
const module = await SQLiteESMFactory()
|
|
sqlite3 = SQLite.Factory(module)
|
|
db = await sqlite3.open_v2(':memory:')
|
|
|
|
for (const sql of SCHEMA_SQL.split(';').filter(s => s.trim())) {
|
|
await sqlite3.exec(db, sql)
|
|
}
|
|
return db
|
|
}
|
|
|
|
export function notifyTableChanged(table) {
|
|
tableListeners.get(table)?.forEach(cb => cb())
|
|
}
|
|
|
|
export function onTableChange(table, cb) {
|
|
if (!tableListeners.has(table)) tableListeners.set(table, new Set())
|
|
tableListeners.get(table).add(cb)
|
|
return () => tableListeners.get(table).delete(cb)
|
|
}
|
|
|
|
export async function execSQL(sql, params = []) {
|
|
if (!db) throw new Error('DB not initialized')
|
|
const results = []
|
|
|
|
if (params.length === 0) {
|
|
await sqlite3.exec(db, sql, (row, cols) => {
|
|
results.push(Object.fromEntries(cols.map((c, i) => [c, row[i]])))
|
|
})
|
|
} else {
|
|
for await (const stmt of sqlite3.statements(db, sql)) {
|
|
sqlite3.bind_collection(stmt, params)
|
|
const cols = sqlite3.column_names(stmt)
|
|
while ((await sqlite3.step(stmt)) === SQLite.SQLITE_ROW) {
|
|
results.push(Object.fromEntries(cols.map((c, i) => [c, sqlite3.column(stmt, i)])))
|
|
}
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|