mirror of https://github.com/elk-zone/elk.git
66 lines
1.5 KiB
TypeScript
66 lines
1.5 KiB
TypeScript
|
import type { MaybeComputedRef, RemovableRef } from '@vueuse/core'
|
||
|
import type { Ref } from 'vue'
|
||
|
import { del, get, set, update } from 'idb-keyval'
|
||
|
import type { UseIDBOptions } from '@vueuse/integrations/useIDBKeyval'
|
||
|
|
||
|
export async function useAsyncIDBKeyval<T>(
|
||
|
key: IDBValidKey,
|
||
|
initialValue: MaybeComputedRef<T>,
|
||
|
options: UseIDBOptions = {},
|
||
|
): Promise<RemovableRef<T>> {
|
||
|
const {
|
||
|
flush = 'pre',
|
||
|
deep = true,
|
||
|
shallow,
|
||
|
onError = (e: unknown) => {
|
||
|
console.error(e)
|
||
|
},
|
||
|
} = options
|
||
|
|
||
|
const data = (shallow ? shallowRef : ref)(initialValue) as Ref<T>
|
||
|
|
||
|
const rawInit: T = resolveUnref(initialValue)
|
||
|
|
||
|
async function read() {
|
||
|
try {
|
||
|
const rawValue = await get<T>(key)
|
||
|
if (rawValue === undefined) {
|
||
|
if (rawInit !== undefined && rawInit !== null)
|
||
|
await set(key, rawInit)
|
||
|
}
|
||
|
else {
|
||
|
data.value = rawValue
|
||
|
}
|
||
|
}
|
||
|
catch (e) {
|
||
|
onError(e)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
await read()
|
||
|
|
||
|
async function write() {
|
||
|
try {
|
||
|
if (data.value == null) {
|
||
|
await del(key)
|
||
|
}
|
||
|
else {
|
||
|
// IndexedDB does not support saving proxies, convert from proxy before saving
|
||
|
if (Array.isArray(data.value))
|
||
|
await update(key, () => (JSON.parse(JSON.stringify(data.value))))
|
||
|
else if (typeof data.value === 'object')
|
||
|
await update(key, () => ({ ...data.value }))
|
||
|
else
|
||
|
await update(key, () => (data.value))
|
||
|
}
|
||
|
}
|
||
|
catch (e) {
|
||
|
onError(e)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
watch(data, () => write(), { flush, deep })
|
||
|
|
||
|
return data as RemovableRef<T>
|
||
|
}
|