Spaces:
Runtime error
Runtime error
File size: 2,572 Bytes
f102ffd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | export interface QueuePayload {
url: string
method: string
headers: Record<string, string>
body: string
createdAt: number
}
export interface QueuedItem extends QueuePayload {
id: number
}
const DB_NAME = "tans-agents-offline-v1"
const DB_VERSION = 1
const STORE_NAME = "queue"
function openDb(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
if (typeof indexedDB === "undefined") {
reject(new Error("IndexedDB is not available"))
return
}
const request = indexedDB.open(DB_NAME, DB_VERSION)
request.onupgradeneeded = () => {
const db = request.result
if (!db.objectStoreNames.contains(STORE_NAME)) {
db.createObjectStore(STORE_NAME, { keyPath: "id", autoIncrement: true })
}
}
request.onsuccess = () => resolve(request.result)
request.onerror = () => reject(request.error ?? new Error("Failed to open offline queue"))
request.onblocked = () => reject(new Error("Offline queue database upgrade is blocked"))
})
}
function withStore<T>(
mode: IDBTransactionMode,
run: (store: IDBObjectStore) => IDBRequest<T>,
): Promise<T> {
return openDb().then(
(db) =>
new Promise<T>((resolve, reject) => {
const transaction = db.transaction(STORE_NAME, mode)
const store = transaction.objectStore(STORE_NAME)
const request = run(store)
let result: T | undefined
request.onsuccess = () => {
result = request.result
}
request.onerror = () => reject(request.error ?? new Error("Offline queue request failed"))
transaction.oncomplete = () => {
db.close()
resolve(result as T)
}
transaction.onerror = () => {
db.close()
reject(transaction.error ?? new Error("Offline queue transaction failed"))
}
transaction.onabort = () => {
db.close()
reject(transaction.error ?? new Error("Offline queue transaction aborted"))
}
}),
)
}
export async function enqueue(payload: QueuePayload): Promise<number> {
return withStore<IDBValidKey>("readwrite", (store) => store.add(payload)).then((key) => Number(key))
}
export async function list(): Promise<QueuedItem[]> {
return withStore<QueuedItem[]>("readonly", (store) => store.getAll())
}
export async function remove(id: number): Promise<void> {
await withStore<undefined>("readwrite", (store) => store.delete(id))
}
export async function count(): Promise<number> {
return withStore<number>("readonly", (store) => store.count())
}
|