import { AesEncryption, cacheCipher, DEFAULT_CACHE_TIME, enableStorageEncryption, getStorageShortName, isNil, Persistent, } from '@eciol/shared'; import { acceptHMRUpdate, createPinia, defineStore } from 'pinia'; import { createPersistedState } from 'pinia-plugin-persistedstate'; import type { App } from 'vue'; interface UseStoreOptions { /** * @description 应用名,由于 @eciol/store 是公用的,后续可能有多个app,为了防止多个app缓存冲突,可在这里配置应用名 * 应用名将被用于持久化的前缀 */ appName?: string; /** * @description 缓存加密配置 * */ cacheCipher?: { key: string; iv: string; }; /** * @description 缓存过期时间,单位为秒 * */ cacheTimeout?: number; /** * @description 是否立即存入storage */ immediate?: boolean; } const pinia = createPinia(); /** * @description 初始化pinia * @param app vue app 实例 */ function useStore(app: App, options: UseStoreOptions = {}) { const { cacheCipher: { key = cacheCipher.key, iv = cacheCipher.iv } = {}, cacheTimeout = DEFAULT_CACHE_TIME, immediate = true, } = options; const encryption = new AesEncryption({ key, iv }); pinia.use( createPersistedState({ storage: { getItem(key) { const v = Persistent.getLocal(key); if (!v) return null; try { const decVal = enableStorageEncryption ? encryption.decryptByAES(v) : v; const data = JSON.parse(decVal); const { value, expire } = data; if (isNil(expire) || expire >= new Date().getTime()) { return value; } return null; } catch (e) { return null; } }, setItem(key, value) { const stringData = JSON.stringify({ value, time: Date.now(), expire: !isNil(cacheTimeout) ? new Date().getTime() + cacheTimeout * 1000 : null, }); const stringified = enableStorageEncryption ? encryption.encryptByAES(stringData) : stringData; Persistent.setLocal(key, stringified, immediate); }, }, // key $store.id-$appName key: (storeKey) => `${getStorageShortName()}__${storeKey.toUpperCase()}`, // serializer: { // serialize(value) { // // if (enableStorageEncryption && [key.length, iv.length].some((item) => item !== 16)) { // // throw new Error('When enableStorageEncryption is true, the key or iv must be 16 bits!'); // // } // const stringData = JSON.stringify({ // value, // time: Date.now(), // expire: !isNil(cacheTimeout) ? new Date().getTime() + cacheTimeout * 1000 : null, // }); // return enableStorageEncryption ? encryption.encryptByAES(stringData) : stringData; // }, // deserialize(v) { // if (!v) return null; // try { // const decVal = enableStorageEncryption ? encryption.decryptByAES(v) : v; // const data = JSON.parse(decVal); // const { value, expire } = data; // if (isNil(expire) || expire >= new Date().getTime()) { // return value; // } // return null; // } catch (e) { // return null; // } // }, // }, }), ); app.use(pinia as any); } export { acceptHMRUpdate, defineStore, pinia, useStore };