Files
zpan/server/db/transaction.ts
T
saltbo 3abf4f231e fix(storage): preserve purge history and track usage deltas
Retain purged matter and image metadata while hiding tombstones from live reads. Record exact storage deltas and build hourly trends only after the opening balance.
2026-07-21 00:29:27 -04:00

56 lines
1.7 KiB
TypeScript

import type { Database } from '../platform/interface'
export type AtomicQuery = {
all?: () => unknown
run?: () => unknown
}
type RowsQuery<T> = PromiseLike<T[]> | { all(): T[] }
export async function executeRows<T>(query: RowsQuery<T>): Promise<T[]> {
if (typeof (query as PromiseLike<T[]>).then === 'function') return await (query as PromiseLike<T[]>)
return (query as { all(): T[] }).all()
}
function isSyncDatabase(db: Database): boolean {
return db.constructor.name === 'BetterSQLite3Database'
}
export async function executeWriteTransaction(db: Database, queries: AtomicQuery[]): Promise<void> {
const batch = (db as unknown as { batch?: (queries: AtomicQuery[]) => Promise<unknown[]> }).batch
if (batch) {
await batch.call(db, queries)
return
}
if (!isSyncDatabase(db)) throw new Error('db_transaction_unavailable')
;(db as unknown as { transaction<T>(fn: () => T): T }).transaction(() => {
for (const query of queries) {
if (query.run) {
query.run()
continue
}
query.all?.()
}
})
}
export async function executeWriteTransactionWithResults(
db: Database,
queries: AtomicQuery[],
returningQueryIndexes: readonly number[],
): Promise<unknown[]> {
const batch = (db as unknown as { batch?: (queries: AtomicQuery[]) => Promise<unknown[]> }).batch
if (batch) return await batch.call(db, queries)
if (!isSyncDatabase(db)) throw new Error('db_transaction_unavailable')
return (db as unknown as { transaction<T>(fn: () => T): T }).transaction(() =>
queries.map((query, index) => {
if (returningQueryIndexes.includes(index)) return query.all?.()
return query.run?.()
}),
)
}