91 lines
2.2 KiB
TypeScript

import { defineStore } from 'pinia'
import { ref } from 'vue'
const cloneJson = <T>(value: T): T => JSON.parse(JSON.stringify(value)) as T
export const useKvStore = defineStore('kv', () => {
const entries = ref<Record<string, unknown>>({})
const ready = ref(false)
const loading = ref<Promise<void> | null>(null)
const ensureReady = async () => {
if (ready.value) return
if (loading.value) {
await loading.value
return
}
loading.value = (async () => {
ready.value = true
})()
await loading.value
loading.value = null
}
const getItem = async <T = unknown>(keyRaw: string | number): Promise<T | null> => {
await ensureReady()
const key = String(keyRaw || '').trim()
if (!key) return null
if (!Object.prototype.hasOwnProperty.call(entries.value, key)) return null
return cloneJson(entries.value[key] as T)
}
const setItem = async <T = unknown>(keyRaw: string | number, value: T): Promise<void> => {
await ensureReady()
const key = String(keyRaw || '').trim()
if (!key) return
entries.value[key] = cloneJson(value)
}
const removeItem = async (keyRaw: string | number): Promise<void> => {
await ensureReady()
const key = String(keyRaw || '').trim()
if (!key) return
delete entries.value[key]
}
const keys = async (): Promise<string[]> => {
await ensureReady()
return Object.keys(entries.value)
}
const clear = async (): Promise<void> => {
await ensureReady()
entries.value = {}
}
const exportEntries = async () => {
await ensureReady()
return Object.entries(entries.value).map(([key, value]) => ({ key, value: cloneJson(value) }))
}
const importEntries = async (
incoming: Array<{ key: string; value: unknown }>,
options?: { replace?: boolean }
) => {
await ensureReady()
if (options?.replace !== false) {
entries.value = {}
}
for (const item of incoming || []) {
const key = String(item?.key || '').trim()
if (!key) continue
entries.value[key] = cloneJson(item.value)
}
}
return {
entries,
ready,
ensureReady,
getItem,
setItem,
removeItem,
keys,
clear,
exportEntries,
importEntries
}
}, {
persist: true
})