storageCache.ts
2.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { isNullOrUnDef } from '@wry-smile/utils-is'
import { isProdMode } from '../env'
import { cacheCipher } from '@/settings/encryptionSetting'
import type { EncryptionParams } from '@/utils/cipher'
import { AesEncryption } from '@/utils/cipher'
export interface CreateStorageParams extends EncryptionParams {
prefixKey: string
storage: Storage
hasEncrypt: boolean
timeout?: Nullable<number>
}
export const createStorage = ({
prefixKey = '',
storage = sessionStorage,
key = cacheCipher.key,
iv = cacheCipher.iv,
timeout = null,
hasEncrypt = isProdMode(),
}: Partial<CreateStorageParams> = {}) => {
if (hasEncrypt && [key.length, iv.length].some(item => item !== 16))
throw new Error('When hasEncrypt is true, the key or iv must be 16 bits!')
const encryption = new AesEncryption({ key, iv })
/**
* Cache class
* Construction parameters can be passed into sessionStorage, localStorage,
* @class Cache
* @example
*/
const WebStorage = class WebStorage {
private storage: Storage
private prefixKey?: string
private encryption: AesEncryption
private hasEncrypt: boolean
/**
*
* @param {*} storage
*/
constructor() {
this.storage = storage
this.prefixKey = prefixKey
this.encryption = encryption
this.hasEncrypt = hasEncrypt
}
private getKey(key: string) {
return `${this.prefixKey}${key}`.toUpperCase()
}
/**
* Set cache
* @param {string} key
* @param {*} value
* @param {*} expire Expiration time in seconds
* @memberof Cache
*/
set(key: string, value: any, expire: number | null = timeout) {
const stringData = JSON.stringify({
value,
time: Date.now(),
expire: !isNullOrUnDef(expire) ? new Date().getTime() + expire * 1000 : null,
})
const stringifyValue = this.hasEncrypt
? this.encryption.encryptByAES(stringData)
: stringData
this.storage.setItem(this.getKey(key), stringifyValue)
}
/**
* Read cache
* @param {string} key
* @param {*} def
* @memberof Cache
*/
get(key: string, def: any = null): any {
const val = this.storage.getItem(this.getKey(key))
if (!val) return def
try {
const decVal = this.hasEncrypt ? this.encryption.decryptByAES(val) : val
const data = JSON.parse(decVal)
const { value, expire } = data
if (isNullOrUnDef(expire) || expire >= new Date().getTime())
return value
this.remove(key)
}
catch (e) {
return def
}
}
/**
* Delete cache based on key
* @param {string} key
* @memberof Cache
*/
remove(key: string) {
this.storage.removeItem(this.getKey(key))
}
/**
* Delete all caches of this instance
*/
clear(): void {
this.storage.clear()
}
}
return new WebStorage()
}