Skip to content

Commit

Permalink
feat: add pinia persist plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
kirklin committed Oct 12, 2023
1 parent ec5c4c6 commit ed1012d
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 19 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@
"colord": "^2.9.3",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.10",
"destr": "^2.0.1",
"iso-639-1": "^3.1.0",
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
"path-to-regexp": "^6.2.1",
"pinia": "^2.1.6",
"pinia-plugin-persistedstate": "^3.2.0",
"postcss-px-to-viewport": "^1.1.1",
"vant": "^4.7.1",
"vue": "^3.3.4",
Expand Down
15 changes: 14 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import { useLocalStorage } from "@vueuse/core";
import { createApp } from "vue";

// Vue Router
import { createPinia } from "pinia";
import { createI18n } from "vue-i18n";

import messages from "@intlify/unplugin-vue-i18n/messages";
import { router } from "./router";

import { registerStore } from "./store";
import { setupStore } from "./store";
import App from "~/App.vue";

// reset css
Expand All @@ -23,7 +22,8 @@ app.use(createI18n({
locale: unref(useLocalStorage("locale", "zh")),
messages,
}));
app.use(createPinia());
registerStore();
// Configure store
// 配置 store
setupStore(app);
app.use(router);
app.mount("#app");
12 changes: 12 additions & 0 deletions src/setting/encryptionSetting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This constant sets the default cache time for the system, measured in seconds
export const DEFAULT_STORAGE_TIME = 60 * 60 * 24 * 7;

// This constant defines the key used for AES encryption of storage
export const STORAGE_CIPHER_KEY = "boot-vant@";

// This constant defines the initialization vector used for AES encryption of storage
export const STORAGE_CIPHER_IV = "@boot-vant";

// This constant determines whether storage encryption using AES should be enabled in the system
// It is set to true in production mode and false in development mode
export const SHOULD_ENABLE_STORAGE_ENCRYPTION = !import.meta.env.DEV;
18 changes: 9 additions & 9 deletions src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { counter } from "./counter";
import type { App } from "vue";
import { createPinia } from "pinia";
import { registerPiniaPersistPlugin } from "~/store/plugin/persist";

const appStore: any = {};
const store = createPinia();
registerPiniaPersistPlugin(store);

/**
* 注册app状态库
*/
export const registerStore = () => {
appStore.counter = counter();
};
export function setupStore(app: App<Element>) {
app.use(store);
}

export default appStore;
export { store };
78 changes: 78 additions & 0 deletions src/store/plugin/persist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* Pinia Persist Plugin
* Pinia 持久化插件
* @link https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/
*
*/
import type { Pinia } from "pinia";
import destr from "destr";
import { createPersistedState } from "pinia-plugin-persistedstate";
import type { PersistedStateFactoryOptions, Serializer } from "pinia-plugin-persistedstate";
import {
SHOULD_ENABLE_STORAGE_ENCRYPTION,
STORAGE_CIPHER_IV,
STORAGE_CIPHER_KEY,
} from "~/setting/encryptionSetting";
import type { Encryption } from "~/utils";
import { EncryptionFactory, createStorageName } from "~/utils";
import type { GlobEnvConfig } from "#/config";

const persistEncryption: Encryption = EncryptionFactory.createAesEncryption({ key: STORAGE_CIPHER_KEY, iv: STORAGE_CIPHER_IV });

export const PERSIST_KEY_PREFIX = createStorageName(<GlobEnvConfig>import.meta.env);

/**
* Custom serializer for serialization and deserialization of storage data
* 自定义序列化器,用于序列化和反序列化存储数据
*
* @param shouldEnableEncryption whether to enable encryption for storage data 是否启用存储数据加密
* @returns serializer
*/
const customSerializer = (shouldEnableEncryption: boolean): Serializer => {
if (shouldEnableEncryption) {
return {
deserialize: (value) => {
const decrypted = persistEncryption.decrypt(value);
return destr(decrypted);
},
serialize: (value) => {
const serialized = JSON.stringify(value);
return persistEncryption.encrypt(serialized);
},
};
} else {
return {
deserialize: (value) => {
return destr(value);
},
serialize: (value) => {
return JSON.stringify(value);
},
};
}
};

/**
* Register Pinia Persist Plugin
* 注册 Pinia 持久化插件
*
* @param pinia Pinia instance Pinia 实例
*/
export function registerPiniaPersistPlugin(pinia: Pinia) {
pinia.use(createPersistedState(createPersistedStateOptions(PERSIST_KEY_PREFIX)));
}

/**
* Create Persisted State Options
* 创建持久化状态选项
*
* @param keyPrefix prefix for storage key 储存键前缀
* @returns persisted state factory options
*/
export function createPersistedStateOptions(keyPrefix: string): PersistedStateFactoryOptions {
return {
storage: localStorage,
key: id => `${keyPrefix}__${id}`,
serializer: customSerializer(SHOULD_ENABLE_STORAGE_ENCRYPTION),
};
}
11 changes: 6 additions & 5 deletions types/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ declare global {
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const setupStore: typeof import('../src/store/index')['setupStore']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const store: typeof import('../src/store/index')['default']
const store: typeof import('../src/store/index')['store']
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
Expand Down Expand Up @@ -391,14 +392,14 @@ declare module 'vue' {
readonly refDefault: UnwrapRef<typeof import('@vueuse/core')['refDefault']>
readonly refThrottled: UnwrapRef<typeof import('@vueuse/core')['refThrottled']>
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']>
readonly registerStore: UnwrapRef<typeof import('../src/store/index')['registerStore']>
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
readonly setupStore: UnwrapRef<typeof import('../src/store/index')['setupStore']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
readonly store: UnwrapRef<typeof import('../src/store/index')['default']>
readonly store: UnwrapRef<typeof import('../src/store/index')['store']>
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
Expand Down Expand Up @@ -686,14 +687,14 @@ declare module '@vue/runtime-core' {
readonly refDefault: UnwrapRef<typeof import('@vueuse/core')['refDefault']>
readonly refThrottled: UnwrapRef<typeof import('@vueuse/core')['refThrottled']>
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']>
readonly registerStore: UnwrapRef<typeof import('../src/store/index')['registerStore']>
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
readonly setupStore: UnwrapRef<typeof import('../src/store/index')['setupStore']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
readonly store: UnwrapRef<typeof import('../src/store/index')['default']>
readonly store: UnwrapRef<typeof import('../src/store/index')['store']>
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
Expand Down

0 comments on commit ed1012d

Please sign in to comment.