import type { MaybeRefOrGetter, RemovableRef } from '@vueuse/core' import type { UseIDBOptions } from '@vueuse/integrations/useIDBKeyval' import { del, get, set, update } from '~/utils/elk-idb' export interface UseAsyncIDBKeyvalReturn { set: (value: T) => Promise readIDB: () => Promise } export async function useAsyncIDBKeyval( key: IDBValidKey, initialValue: MaybeRefOrGetter, source: RemovableRef, options: Omit = {}, ): Promise> { const { flush = 'pre', deep = true, writeDefaults = true, onError = (e: unknown) => { console.error(e) }, } = options const rawInit: T = toValue(initialValue) try { const rawValue = await get(key) if (rawValue === undefined) { if (rawInit !== undefined && rawInit !== null && writeDefaults) { await set(key, rawInit) source.value = rawInit } } else { source.value = rawValue } } catch (e) { onError(e) } async function write(data: T) { try { if (data == null) { await del(key) } else { // IndexedDB does not support saving proxies, convert from proxy before saving await update(key, () => toRaw(data)) } } catch (e) { onError(e) } } const { pause: pauseWatch, resume: resumeWatch, } = watchPausable(source, data => write(data), { flush, deep }) async function setData(value: T): Promise { pauseWatch() try { await write(value) source.value = value } finally { resumeWatch() } } return { set: setData, readIDB: () => get(key) } }