UNPKG

@ithinkdt/core

Version:

iThinkDT Core

111 lines (98 loc) 3.46 kB
import { useEventListener } from '@vueuse/core' import { copy, omitProps } from '@ithinkdt/common' export let STORE_PREFIX = '' export function persistPlugin({ prefix: _prefix, getUsername }) { STORE_PREFIX = _prefix ?? STORE_PREFIX return ({ options, store }) => { if (!options.persist) { return { $clear() { console.debug(`[store] the store '${store.$id}' not set persist, force it.`) }, } } const { prefix = _prefix, userIsolate = false, storage = 'session', version = 1, validate, excludes, saveOnlyChanged, onStore, onRestore, } = options.persist const getKey = () => `${prefix || ''}${store.$id}${userIsolate && getUsername() ? `[${getUsername()}]` : ''}` const _state = saveOnlyChanged ? omitProps({ ...store.$state }, ...(excludes || [])) : undefined let force const parse = () => { let data = parseData(storage, getKey(), version, validate) if (saveOnlyChanged) data = Object.assign({}, _state, data) if (onRestore) data = onRestore(data) if (data) { force = true Object.assign(store.$state, data) } } parse() useEventListener('storage', (e) => { if (e.key !== getKey() || e.newValue === e.oldValue) { return } setTimeout(parse, 0) }) store.$subscribe((_, state) => { if (force) { force = false return } let s = {} for (const key of Object.keys(state)) { if ( typeof key !== 'symbol' && !excludes?.includes(key) && (!saveOnlyChanged || _state[key] !== state[key]) ) { s[key] = state[key] } } s = onStore ? onStore(s) : s saveData(storage, getKey(), s, version) }) return { $clear() { saveData(storage, getKey(), undefined, version) }, } } } export function parseData(storage, key, version, validate) { const $storage = storage === 'local' ? localStorage : sessionStorage const data = $storage.getItem(key) if (data) { const { s, v, t } = JSON.parse(data) console.debug(`[store] parsed '${key}' data from ${storage}, version: ${v}, date: ${t}, data:`, s) if (v !== version || validate?.(s, v, t) === false) { console.debug(`[store] '${key}' data not valid, remove it.`) $storage.removeItem(key) } else { return s } } return } export function saveData(storage, key, data, version) { const $storage = storage === 'local' ? localStorage : sessionStorage const date = Date.now() const s = JSON.stringify({ t: date, v: version, s: data, }) let old = $storage.getItem(key) ?? '' old = old.slice(Math.max(0, old.indexOf('"v":'))) let n = s.slice(Math.max(0, s.indexOf('"v":'))) if (old === n) return $storage.setItem(key, s) console.debug(`[store] save '${key}' data to ${storage}, version: ${version}, date: ${date}, data:`, copy(data)) }