spb/zyquo-cloud-web Public MIT
Zyquo Cloud Web — every cloud model, one beautiful chat, entirely in your browser.
TypeScript 81.9%
CSS 8.9%
JavaScript 7.5%
Shell 1.1%
HTML 0.6%
1/*2 * db.ts3 * Zyquo Cloud Web4 *5 * Author: Simon-Pierre Boucher6 * Mail: contact@spboucher.ai7 *8 * Tiny promise wrapper around IndexedDB — no external dependency (every9 * dependency is key-theft surface). One database, versioned schema.10 */1112const DB_NAME = 'zyquo.cloud.web'13const DB_VERSION = 114export const STORE_CONVERSATIONS = 'conversations'1516let dbPromise: Promise<IDBDatabase> | null = null1718export function openDB(): Promise<IDBDatabase> {19 if (dbPromise) return dbPromise20 dbPromise = new Promise((resolve, reject) => {21 const request = indexedDB.open(DB_NAME, DB_VERSION)22 request.onupgradeneeded = () => {23 const db = request.result24 // v1: conversations store keyed by id, indexed by updatedAt for sorting.25 if (!db.objectStoreNames.contains(STORE_CONVERSATIONS)) {26 const store = db.createObjectStore(STORE_CONVERSATIONS, { keyPath: 'id' })27 store.createIndex('updatedAt', 'updatedAt')28 }29 }30 request.onsuccess = () => {31 request.result.onversionchange = () => request.result.close()32 resolve(request.result)33 }34 request.onerror = () => reject(request.error ?? new Error('IndexedDB open failed'))35 request.onblocked = () => reject(new Error('IndexedDB open blocked'))36 })37 return dbPromise38}3940function requestToPromise<T>(request: IDBRequest<T>): Promise<T> {41 return new Promise((resolve, reject) => {42 request.onsuccess = () => resolve(request.result)43 request.onerror = () => reject(request.error ?? new Error('IndexedDB request failed'))44 })45}4647export async function dbGet<T>(store: string, key: string): Promise<T | undefined> {48 const db = await openDB()49 const tx = db.transaction(store, 'readonly')50 return requestToPromise(tx.objectStore(store).get(key) as IDBRequest<T | undefined>)51}5253export async function dbGetAll<T>(store: string): Promise<T[]> {54 const db = await openDB()55 const tx = db.transaction(store, 'readonly')56 return requestToPromise(tx.objectStore(store).getAll() as IDBRequest<T[]>)57}5859export async function dbPut(store: string, value: unknown): Promise<void> {60 const db = await openDB()61 const tx = db.transaction(store, 'readwrite')62 await requestToPromise(tx.objectStore(store).put(value))63}6465export async function dbDelete(store: string, key: string): Promise<void> {66 const db = await openDB()67 const tx = db.transaction(store, 'readwrite')68 await requestToPromise(tx.objectStore(store).delete(key))69}7071export async function dbClear(store: string): Promise<void> {72 const db = await openDB()73 const tx = db.transaction(store, 'readwrite')74 await requestToPromise(tx.objectStore(store).clear())75}76