@kwiz/common 1.0.78 → 1.0.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/npm-publish.yml +24 -0
- package/.madgerc +2 -2
- package/LICENSE +21 -21
- package/fix-folder-imports.js +26 -26
- package/lib/cjs/helpers/sharepoint.js +5 -1
- package/lib/cjs/helpers/sharepoint.js.map +1 -1
- package/lib/cjs/helpers/typecheckers.js +5 -1
- package/lib/cjs/helpers/typecheckers.js.map +1 -1
- package/lib/cjs/types/libs/msal.types.js +26 -26
- package/lib/cjs/utils/sharepoint.rest/list.js +1 -1
- package/lib/cjs/utils/sharepoint.rest/list.js.map +1 -1
- package/lib/cjs/utils/sharepoint.rest/user.js +11 -11
- package/lib/esm/helpers/sharepoint.js +3 -0
- package/lib/esm/helpers/sharepoint.js.map +1 -1
- package/lib/esm/helpers/typecheckers.js +3 -0
- package/lib/esm/helpers/typecheckers.js.map +1 -1
- package/lib/esm/types/libs/msal.types.js +26 -26
- package/lib/esm/utils/sharepoint.rest/list.js +2 -2
- package/lib/esm/utils/sharepoint.rest/list.js.map +1 -1
- package/lib/esm/utils/sharepoint.rest/user.js +11 -11
- package/lib/types/helpers/sharepoint.d.ts +1 -0
- package/lib/types/helpers/typecheckers.d.ts +1 -0
- package/package.json +77 -77
- package/readme.md +17 -17
- package/src/_dependencies.ts +12 -12
- package/src/config.ts +17 -17
- package/src/helpers/Guid.ts +181 -181
- package/src/helpers/base64.ts +173 -173
- package/src/helpers/browser.test.js +13 -13
- package/src/helpers/browser.ts +1348 -1348
- package/src/helpers/browserinfo.ts +292 -292
- package/src/helpers/collections.base.test.js +25 -25
- package/src/helpers/collections.base.ts +437 -437
- package/src/helpers/collections.ts +107 -107
- package/src/helpers/color.ts +54 -54
- package/src/helpers/cookies.ts +59 -59
- package/src/helpers/date.test.js +119 -119
- package/src/helpers/date.ts +188 -188
- package/src/helpers/debug.ts +186 -186
- package/src/helpers/emails.ts +6 -6
- package/src/helpers/eval.ts +5 -5
- package/src/helpers/file.test.js +50 -50
- package/src/helpers/file.ts +58 -58
- package/src/helpers/flatted.ts +149 -149
- package/src/helpers/functions.ts +16 -16
- package/src/helpers/graph/calendar.types.ts +10 -10
- package/src/helpers/http.ts +69 -69
- package/src/helpers/images.ts +22 -22
- package/src/helpers/json.ts +38 -38
- package/src/helpers/md5.ts +189 -189
- package/src/helpers/objects.test.js +33 -33
- package/src/helpers/objects.ts +270 -270
- package/src/helpers/promises.test.js +37 -37
- package/src/helpers/promises.ts +165 -165
- package/src/helpers/random.ts +27 -27
- package/src/helpers/scheduler/scheduler.test.js +103 -103
- package/src/helpers/scheduler/scheduler.ts +131 -131
- package/src/helpers/sharepoint.ts +776 -772
- package/src/helpers/strings.test.js +101 -101
- package/src/helpers/strings.ts +317 -317
- package/src/helpers/typecheckers.test.js +34 -34
- package/src/helpers/typecheckers.ts +266 -262
- package/src/helpers/url.test.js +43 -43
- package/src/helpers/url.ts +207 -207
- package/src/helpers/urlhelper.ts +111 -111
- package/src/index.ts +6 -6
- package/src/types/auth.ts +54 -54
- package/src/types/common.types.ts +15 -15
- package/src/types/flatted.types.ts +59 -59
- package/src/types/globals.types.ts +6 -6
- package/src/types/graph/calendar.types.ts +80 -80
- package/src/types/knownscript.types.ts +18 -18
- package/src/types/libs/datajs.types.ts +28 -28
- package/src/types/libs/ics.types.ts +30 -30
- package/src/types/libs/msal.types.ts +49 -49
- package/src/types/locales.ts +124 -124
- package/src/types/localstoragecache.types.ts +8 -8
- package/src/types/location.types.ts +27 -27
- package/src/types/moment.ts +11 -11
- package/src/types/regex.types.ts +16 -16
- package/src/types/rest.types.ts +95 -95
- package/src/types/sharepoint.types.ts +1465 -1465
- package/src/types/sharepoint.utils.types.ts +287 -287
- package/src/utils/auth/common.ts +74 -74
- package/src/utils/auth/discovery.test.js +12 -12
- package/src/utils/auth/discovery.ts +132 -132
- package/src/utils/base64.ts +27 -27
- package/src/utils/consolelogger.ts +320 -320
- package/src/utils/date.ts +35 -35
- package/src/utils/emails.ts +24 -24
- package/src/utils/knownscript.ts +286 -286
- package/src/utils/localstoragecache.ts +441 -441
- package/src/utils/rest.ts +501 -501
- package/src/utils/script.ts +170 -170
- package/src/utils/sharepoint.rest/common.ts +154 -154
- package/src/utils/sharepoint.rest/date.ts +62 -62
- package/src/utils/sharepoint.rest/file.folder.ts +598 -598
- package/src/utils/sharepoint.rest/item.ts +547 -547
- package/src/utils/sharepoint.rest/list.ts +1388 -1388
- package/src/utils/sharepoint.rest/listutils/GetListItemsByCaml.ts +774 -774
- package/src/utils/sharepoint.rest/listutils/GetListItemsById.ts +275 -275
- package/src/utils/sharepoint.rest/listutils/common.ts +206 -206
- package/src/utils/sharepoint.rest/location.ts +141 -141
- package/src/utils/sharepoint.rest/navigation-links.ts +86 -86
- package/src/utils/sharepoint.rest/user-search.ts +252 -252
- package/src/utils/sharepoint.rest/user.ts +491 -491
- package/src/utils/sharepoint.rest/web.ts +1384 -1384
- package/src/utils/sod.ts +194 -194
- package/lib/cjs/helpers/_dependencies.js +0 -21
- package/lib/cjs/helpers/_dependencies.js.map +0 -1
- package/lib/cjs/utils/_dependencies.js +0 -24
- package/lib/cjs/utils/_dependencies.js.map +0 -1
- package/lib/esm/helpers/_dependencies.js +0 -3
- package/lib/esm/helpers/_dependencies.js.map +0 -1
- package/lib/esm/utils/_dependencies.js +0 -4
- package/lib/esm/utils/_dependencies.js.map +0 -1
- package/lib/types/helpers/_dependencies.d.ts +0 -2
- package/lib/types/utils/_dependencies.d.ts +0 -3
|
@@ -1,442 +1,442 @@
|
|
|
1
|
-
import { sizeOf } from "../helpers/collections.base";
|
|
2
|
-
import { isDebug } from "../helpers/debug";
|
|
3
|
-
import { flatted } from "../helpers/flatted";
|
|
4
|
-
import { jsonParse } from "../helpers/json";
|
|
5
|
-
import { getGlobal } from "../helpers/objects";
|
|
6
|
-
import { isDate, isNullOrEmptyString, isNullOrUndefined, isNumber } from "../helpers/typecheckers";
|
|
7
|
-
import { ILocalStorageCacheLifetime } from "../types/localstoragecache.types";
|
|
8
|
-
import { ConsoleLogger } from "./consolelogger";
|
|
9
|
-
|
|
10
|
-
/**key with prefix, value is a date string */
|
|
11
|
-
interface IExpirationsDictionary {
|
|
12
|
-
[keyWithPRefix: string]: string;
|
|
13
|
-
build: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
let logger = ConsoleLogger.get("localstoragecache");
|
|
17
|
-
|
|
18
|
-
export const keyPrefix = "kw$_";
|
|
19
|
-
export const LOCAL_STORAGE_PREFIX = "kwizcom-localstorage-cache";
|
|
20
|
-
export const LOCAL_STORGAGE_EXPIRATIONS_KEY = LOCAL_STORAGE_PREFIX + "-expirations";
|
|
21
|
-
export const DEFAULT_EXPIRATION = 20 * 60 * 1000; // 20 minutes;
|
|
22
|
-
/** When caching logic changes (serialization methods, format, schema), the MODULE_REVISION should be incremented
|
|
23
|
-
* and all client side apps will need to be rebuilt */
|
|
24
|
-
export const MODULE_REVISION = "1";
|
|
25
|
-
/** key (no prefix) is kept in lower case. not case sensitive */
|
|
26
|
-
|
|
27
|
-
function _getCache() {
|
|
28
|
-
let _cache = getGlobal<{
|
|
29
|
-
purgeCalled: boolean;
|
|
30
|
-
expirations: IExpirationsDictionary;
|
|
31
|
-
[keyNoPrefixToLower: string]: any;
|
|
32
|
-
}>("common_utils_localstoragecache_module_cache");
|
|
33
|
-
|
|
34
|
-
if (!_cache.purgeCalled) {
|
|
35
|
-
//issue 7081 - purge all orphans/expired items
|
|
36
|
-
_cache.purgeCalled = true;
|
|
37
|
-
//clear expired cache items.
|
|
38
|
-
(globalThis || window).setTimeout(() => {
|
|
39
|
-
purgeCache();
|
|
40
|
-
if (isDebug()) {
|
|
41
|
-
let size = _getStoredSize();
|
|
42
|
-
logger.debug(`Size of items in local storage: ${size}KB`);
|
|
43
|
-
}
|
|
44
|
-
}, 5000);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return _cache;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
var _supportsLocalStorage: boolean = null;
|
|
51
|
-
|
|
52
|
-
function _parseExpiration(exp: number | ILocalStorageCacheLifetime | Date): Date {
|
|
53
|
-
var expirationDate: Date;
|
|
54
|
-
|
|
55
|
-
if (isNumber(exp) && exp > 0) {
|
|
56
|
-
expirationDate = new Date();
|
|
57
|
-
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + exp);
|
|
58
|
-
} else if (exp instanceof Date) {
|
|
59
|
-
expirationDate = exp;
|
|
60
|
-
} else if (exp) {
|
|
61
|
-
var tempexp = exp as ILocalStorageCacheLifetime;
|
|
62
|
-
var seconds = typeof (tempexp.seconds) === "number" ? tempexp.seconds : undefined;
|
|
63
|
-
var minutes = typeof (tempexp.minutes) === "number" ? tempexp.minutes : undefined;
|
|
64
|
-
var hours = typeof (tempexp.hours) === "number" ? tempexp.hours : undefined;
|
|
65
|
-
var days = typeof (tempexp.days) === "number" ? tempexp.days : undefined;
|
|
66
|
-
var months = typeof (tempexp.months) === "number" ? tempexp.months : undefined;
|
|
67
|
-
var years = typeof (tempexp.years) === "number" ? tempexp.years : undefined;
|
|
68
|
-
|
|
69
|
-
if (seconds || minutes || hours || days || months || years) {
|
|
70
|
-
expirationDate = new Date();
|
|
71
|
-
|
|
72
|
-
if (seconds) {
|
|
73
|
-
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + (seconds * 1000));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (minutes) {
|
|
77
|
-
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + (minutes * 60 * 1000));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (hours) {
|
|
81
|
-
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + (hours * 60 * 60 * 1000));
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (days) {
|
|
85
|
-
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + (days * 24 * 60 * 60 * 1000));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (months) {
|
|
89
|
-
expirationDate.setMonth(expirationDate.getMonth() + months);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (years) {
|
|
93
|
-
expirationDate.setFullYear(expirationDate.getFullYear() + years);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (!expirationDate) {
|
|
99
|
-
expirationDate = new Date();
|
|
100
|
-
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + DEFAULT_EXPIRATION);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return expirationDate;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function _getCacheExpirations(): IExpirationsDictionary {
|
|
107
|
-
let _cache = _getCache();
|
|
108
|
-
if (isNullOrUndefined(_cache.expirations)) {
|
|
109
|
-
_cache.expirations = jsonParse<IExpirationsDictionary>(_getItem(LOCAL_STORGAGE_EXPIRATIONS_KEY));
|
|
110
|
-
|
|
111
|
-
//ISSUE: 1525 - expire the cache if it was built with a different version number so that the cache
|
|
112
|
-
//is compatible with the current build
|
|
113
|
-
if (!isNullOrUndefined(_cache.expirations) && _cache.expirations.build !== MODULE_REVISION) {
|
|
114
|
-
logger.log(`Purging cache because of build number change`)
|
|
115
|
-
purgeCache(true);
|
|
116
|
-
_cache.expirations = null;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (isNullOrUndefined(_cache.expirations)) {
|
|
120
|
-
_cache.expirations = {
|
|
121
|
-
build: MODULE_REVISION
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return _cache.expirations;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function _saveCacheExpirations() {
|
|
130
|
-
let _cache = _getCache();
|
|
131
|
-
if (!isNullOrUndefined(_cache.expirations) && sizeOf(_cache.expirations) > 0) {
|
|
132
|
-
_setItem(LOCAL_STORGAGE_EXPIRATIONS_KEY, JSON.stringify(_cache.expirations));
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
_removeItem(LOCAL_STORGAGE_EXPIRATIONS_KEY);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function _setCacheExpiration(keyWithPrefix: string, expireDate: Date) {
|
|
140
|
-
var expirations = _getCacheExpirations();
|
|
141
|
-
expirations[keyWithPrefix] = expireDate.toISOString();
|
|
142
|
-
_saveCacheExpirations();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function _isKeyExpired(keyWithPrefix: string) {
|
|
146
|
-
var expirations = _getCacheExpirations();
|
|
147
|
-
if (expirations && expirations[keyWithPrefix]) {
|
|
148
|
-
var now = new Date();
|
|
149
|
-
var eDate = new Date(expirations[keyWithPrefix]);
|
|
150
|
-
if (now > eDate) {
|
|
151
|
-
try {
|
|
152
|
-
delete expirations[keyWithPrefix];
|
|
153
|
-
} catch (ex) {
|
|
154
|
-
expirations[keyWithPrefix] = undefined; // undefined variables are removed when passed to JSON.stringify
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
_saveCacheExpirations();
|
|
158
|
-
//has a date, it is expired.
|
|
159
|
-
return true;
|
|
160
|
-
}
|
|
161
|
-
//has a date, it is not expired yet.
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
//has no date or not in expirations at all - say it is expired...
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function _getItem(key: string) {
|
|
169
|
-
try {
|
|
170
|
-
return localStorage.getItem(key);
|
|
171
|
-
} catch {
|
|
172
|
-
}
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function _setItem(key: string, value: string) {
|
|
177
|
-
try {
|
|
178
|
-
localStorage.setItem(key, value);
|
|
179
|
-
return true;
|
|
180
|
-
} catch {
|
|
181
|
-
}
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function _removeItem(key: string) {
|
|
186
|
-
try {
|
|
187
|
-
localStorage.removeItem(key);
|
|
188
|
-
return true;
|
|
189
|
-
} catch {
|
|
190
|
-
}
|
|
191
|
-
return false;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**Get the size (KB) of all entries in local storage. Only returns the size for entries with kwizcom key prefix. */
|
|
195
|
-
function _getStoredSize() {
|
|
196
|
-
let keys = getCacheKeys();
|
|
197
|
-
let total = 0;
|
|
198
|
-
let length = 0;
|
|
199
|
-
let useBlob = 'Blob' in (globalThis || window);
|
|
200
|
-
|
|
201
|
-
keys.forEach((key) => {
|
|
202
|
-
let v = _getItem(`${keyPrefix}${key}`);
|
|
203
|
-
if (!isNullOrEmptyString(v)) {
|
|
204
|
-
if (useBlob) {
|
|
205
|
-
length = (new Blob([v + key])).size;
|
|
206
|
-
} else {
|
|
207
|
-
length = ((v.length + key.length) * 2);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
total += length;
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
return Number((total / 1024).toFixed(2));
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export function isLocalStorageSupported() {
|
|
217
|
-
if (_supportsLocalStorage !== null) {
|
|
218
|
-
return _supportsLocalStorage;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
var result;
|
|
222
|
-
try {
|
|
223
|
-
_setItem(LOCAL_STORAGE_PREFIX, LOCAL_STORAGE_PREFIX);
|
|
224
|
-
result = _getItem(LOCAL_STORAGE_PREFIX) === LOCAL_STORAGE_PREFIX;
|
|
225
|
-
_removeItem(LOCAL_STORAGE_PREFIX);
|
|
226
|
-
_supportsLocalStorage = result;
|
|
227
|
-
} catch (ex) {
|
|
228
|
-
_supportsLocalStorage = false;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return _supportsLocalStorage;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
//#region exported methods
|
|
235
|
-
export function getCacheItem<T>(key: string, options?: {
|
|
236
|
-
/** Flatted allows serizlising circular dependency objects */
|
|
237
|
-
useFlatted?: boolean;
|
|
238
|
-
}): T {
|
|
239
|
-
key = key.toLowerCase();
|
|
240
|
-
let keyWithPrefix = keyPrefix + key;
|
|
241
|
-
|
|
242
|
-
let _cache = _getCache();
|
|
243
|
-
|
|
244
|
-
if (typeof (_cache[key]) !== "undefined"
|
|
245
|
-
&& _cache[key] !== null) {
|
|
246
|
-
return _cache[key] as T;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (isLocalStorageSupported()) {
|
|
250
|
-
var value: string = _getItem(keyWithPrefix);
|
|
251
|
-
if (isNullOrUndefined(value)) {
|
|
252
|
-
return null;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
let isExpired = _isKeyExpired(keyWithPrefix);
|
|
256
|
-
|
|
257
|
-
if (!isExpired) {
|
|
258
|
-
let valueAsT: T = options && options.useFlatted ? flatted.parse(value) as T : jsonParse<T>(value);
|
|
259
|
-
if (valueAsT !== null) {
|
|
260
|
-
_cache[key] = valueAsT;
|
|
261
|
-
return valueAsT;
|
|
262
|
-
} else {
|
|
263
|
-
_cache[key] = value;
|
|
264
|
-
return value as any as T;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
//else remove it from cache
|
|
268
|
-
removeCacheItem(key);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return null;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
export function setCacheItem(key: string, value: any, expiration: number | ILocalStorageCacheLifetime | Date, options?: {
|
|
275
|
-
/** Flatted allows serizlising circular dependency objects */
|
|
276
|
-
useFlatted?: boolean;
|
|
277
|
-
}): void {
|
|
278
|
-
if (isLocalStorageSupported()) {
|
|
279
|
-
key = key.toLowerCase();
|
|
280
|
-
removeCacheItem(key);
|
|
281
|
-
|
|
282
|
-
var val = null;
|
|
283
|
-
try {
|
|
284
|
-
if (options && options.useFlatted)
|
|
285
|
-
val = flatted.stringify(value);
|
|
286
|
-
else
|
|
287
|
-
val = JSON.stringify(value);
|
|
288
|
-
} catch (ex) {
|
|
289
|
-
logger.debug(`Object cannot be stored in local storage: ${ex && ex.message || ex} ${key}`);
|
|
290
|
-
return;//this put [object] in cache for me if object can't be stringified!
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
let keyWithPrefix = keyPrefix + key;
|
|
294
|
-
|
|
295
|
-
var expireDate = _parseExpiration(expiration);
|
|
296
|
-
|
|
297
|
-
let saved = _setItem(keyWithPrefix, val);
|
|
298
|
-
if (saved) {
|
|
299
|
-
_setCacheExpiration(keyWithPrefix, expireDate);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
let _cache = _getCache();
|
|
303
|
-
|
|
304
|
-
_cache[key] = value;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
export function removeCacheItem(key: string) {
|
|
309
|
-
key = key.toLowerCase();
|
|
310
|
-
let _cache = _getCache();
|
|
311
|
-
delete _cache[key];
|
|
312
|
-
let keyWithPrefix = keyPrefix + key;
|
|
313
|
-
|
|
314
|
-
if (isLocalStorageSupported()) {
|
|
315
|
-
_removeItem(key);//in case we have an old one
|
|
316
|
-
_removeItem(keyWithPrefix);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
export function removeCacheItems(keys: string[]) {
|
|
321
|
-
keys.forEach((key) => {
|
|
322
|
-
removeCacheItem(key);
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
export function getCacheKeys() {
|
|
327
|
-
let keys: string[] = [];
|
|
328
|
-
|
|
329
|
-
if (isLocalStorageSupported()) {
|
|
330
|
-
keys = Object.keys(localStorage).filter((key) => {
|
|
331
|
-
return key.startsWith(keyPrefix);
|
|
332
|
-
}).map((key) => {
|
|
333
|
-
return key.substring(keyPrefix.length);
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
return keys;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/** remove expired cache keys created by this utility.
|
|
341
|
-
* to remove all keys (non-expired too) send removeAll=true
|
|
342
|
-
*/
|
|
343
|
-
function purgeCache(removeAll?: boolean) {
|
|
344
|
-
if (!isLocalStorageSupported()) return;
|
|
345
|
-
|
|
346
|
-
var cacheExpirationsKeys = [
|
|
347
|
-
LOCAL_STORGAGE_EXPIRATIONS_KEY,
|
|
348
|
-
"kwizcom-aplfe-caching-expirations", // old clean up
|
|
349
|
-
"localStorageExpirations" // old clean up
|
|
350
|
-
];
|
|
351
|
-
|
|
352
|
-
let now = new Date();
|
|
353
|
-
|
|
354
|
-
let nonExpiredKeys: string[] = [];
|
|
355
|
-
|
|
356
|
-
//get all expiration keys (key/expiration date/time)
|
|
357
|
-
for (let j = 0; j < cacheExpirationsKeys.length; j++) {
|
|
358
|
-
try {
|
|
359
|
-
let expirations = null;
|
|
360
|
-
let cacheExpirationsKey = cacheExpirationsKeys[j];
|
|
361
|
-
|
|
362
|
-
let removeAllForKey = removeAll || cacheExpirationsKey !== LOCAL_STORGAGE_EXPIRATIONS_KEY;
|
|
363
|
-
|
|
364
|
-
if (cacheExpirationsKey === "localStorageExpirations") {
|
|
365
|
-
//old format - load expirations from this one as well
|
|
366
|
-
expirations = _getItem(cacheExpirationsKey); // "key1^11/18/2011 5pm|key2^3/10/2012 3pm"
|
|
367
|
-
if (expirations) {
|
|
368
|
-
let arr = expirations.split("|"); // ["key1^11/18/2011 5pm","key2^3/10/2012 3pm"]
|
|
369
|
-
for (let i = 0; i < arr.length; i++) {
|
|
370
|
-
try {
|
|
371
|
-
let key_expiration_format = arr[i]; // "key1^11/18/2011 5pm"
|
|
372
|
-
let key = key_expiration_format.split("^")[0];
|
|
373
|
-
//old keys - remove all, all the time
|
|
374
|
-
_removeItem(key);//remove key from cache
|
|
375
|
-
} catch (e) { }
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
} else {
|
|
379
|
-
//new format
|
|
380
|
-
expirations = cacheExpirationsKey === LOCAL_STORGAGE_EXPIRATIONS_KEY ? _getCacheExpirations() : jsonParse(_getItem(cacheExpirationsKey));
|
|
381
|
-
if (expirations) {
|
|
382
|
-
let expirationKeys = Object.keys(expirations);
|
|
383
|
-
logger.group(() => {
|
|
384
|
-
expirationKeys.forEach(keyWithPrefix => {
|
|
385
|
-
try {
|
|
386
|
-
let shouldRemoveKey = removeAllForKey || !keyWithPrefix.startsWith(keyPrefix);
|
|
387
|
-
if (!shouldRemoveKey) {
|
|
388
|
-
//check specific key expiration
|
|
389
|
-
let expirationDate = new Date(expirations[keyWithPrefix]);
|
|
390
|
-
if (!isDate(expirationDate) || expirationDate < now) {
|
|
391
|
-
shouldRemoveKey = true;
|
|
392
|
-
delete expirations[keyWithPrefix];
|
|
393
|
-
logger.info(`purging key ${keyWithPrefix}`);
|
|
394
|
-
}
|
|
395
|
-
else {
|
|
396
|
-
nonExpiredKeys.push(keyWithPrefix);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
if (shouldRemoveKey) _removeItem(keyWithPrefix);
|
|
400
|
-
} catch (e) {
|
|
401
|
-
logger.warn(`failed to remove key ${keyWithPrefix}`);
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
}, "Checking expired items", true);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
if (cacheExpirationsKey === LOCAL_STORGAGE_EXPIRATIONS_KEY)
|
|
409
|
-
_saveCacheExpirations();
|
|
410
|
-
else//older keys - just remove them.
|
|
411
|
-
_removeItem(cacheExpirationsKey);
|
|
412
|
-
} catch (e) {
|
|
413
|
-
logger.warn(`something went terribly wrong ${e}`);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
logger.group(() => {
|
|
418
|
-
logger.table(nonExpiredKeys);
|
|
419
|
-
//cleanup orphans
|
|
420
|
-
//loop on all keys
|
|
421
|
-
//if stats with: jsr_, kwfs| or keyPrefix - and not in nonExpiredKeys, it is an orphan. Remove it.
|
|
422
|
-
let localStorageKeys = Object.keys(localStorage);
|
|
423
|
-
for (let keyIdx = 0; keyIdx < localStorageKeys.length; keyIdx++) {
|
|
424
|
-
let key = localStorageKeys[keyIdx];
|
|
425
|
-
if (key.startsWith("jsr_") || key.startsWith("kwfs|")) {
|
|
426
|
-
logger.log(`removing old key ${key}`);
|
|
427
|
-
_removeItem(key);//old key
|
|
428
|
-
}
|
|
429
|
-
else if (key.startsWith(keyPrefix) && !nonExpiredKeys.includes(key))//orphan!
|
|
430
|
-
{
|
|
431
|
-
logger.log(`removing orphan key ${key}`);
|
|
432
|
-
_removeItem(key);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}, "Expired keys", true);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
/** cleanup - remove all local storage keys created by this utility */
|
|
439
|
-
export function clearCache(): void {
|
|
440
|
-
return purgeCache(true);
|
|
441
|
-
}
|
|
1
|
+
import { sizeOf } from "../helpers/collections.base";
|
|
2
|
+
import { isDebug } from "../helpers/debug";
|
|
3
|
+
import { flatted } from "../helpers/flatted";
|
|
4
|
+
import { jsonParse } from "../helpers/json";
|
|
5
|
+
import { getGlobal } from "../helpers/objects";
|
|
6
|
+
import { isDate, isNullOrEmptyString, isNullOrUndefined, isNumber } from "../helpers/typecheckers";
|
|
7
|
+
import { ILocalStorageCacheLifetime } from "../types/localstoragecache.types";
|
|
8
|
+
import { ConsoleLogger } from "./consolelogger";
|
|
9
|
+
|
|
10
|
+
/**key with prefix, value is a date string */
|
|
11
|
+
interface IExpirationsDictionary {
|
|
12
|
+
[keyWithPRefix: string]: string;
|
|
13
|
+
build: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let logger = ConsoleLogger.get("localstoragecache");
|
|
17
|
+
|
|
18
|
+
export const keyPrefix = "kw$_";
|
|
19
|
+
export const LOCAL_STORAGE_PREFIX = "kwizcom-localstorage-cache";
|
|
20
|
+
export const LOCAL_STORGAGE_EXPIRATIONS_KEY = LOCAL_STORAGE_PREFIX + "-expirations";
|
|
21
|
+
export const DEFAULT_EXPIRATION = 20 * 60 * 1000; // 20 minutes;
|
|
22
|
+
/** When caching logic changes (serialization methods, format, schema), the MODULE_REVISION should be incremented
|
|
23
|
+
* and all client side apps will need to be rebuilt */
|
|
24
|
+
export const MODULE_REVISION = "1";
|
|
25
|
+
/** key (no prefix) is kept in lower case. not case sensitive */
|
|
26
|
+
|
|
27
|
+
function _getCache() {
|
|
28
|
+
let _cache = getGlobal<{
|
|
29
|
+
purgeCalled: boolean;
|
|
30
|
+
expirations: IExpirationsDictionary;
|
|
31
|
+
[keyNoPrefixToLower: string]: any;
|
|
32
|
+
}>("common_utils_localstoragecache_module_cache");
|
|
33
|
+
|
|
34
|
+
if (!_cache.purgeCalled) {
|
|
35
|
+
//issue 7081 - purge all orphans/expired items
|
|
36
|
+
_cache.purgeCalled = true;
|
|
37
|
+
//clear expired cache items.
|
|
38
|
+
(globalThis || window).setTimeout(() => {
|
|
39
|
+
purgeCache();
|
|
40
|
+
if (isDebug()) {
|
|
41
|
+
let size = _getStoredSize();
|
|
42
|
+
logger.debug(`Size of items in local storage: ${size}KB`);
|
|
43
|
+
}
|
|
44
|
+
}, 5000);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return _cache;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
var _supportsLocalStorage: boolean = null;
|
|
51
|
+
|
|
52
|
+
function _parseExpiration(exp: number | ILocalStorageCacheLifetime | Date): Date {
|
|
53
|
+
var expirationDate: Date;
|
|
54
|
+
|
|
55
|
+
if (isNumber(exp) && exp > 0) {
|
|
56
|
+
expirationDate = new Date();
|
|
57
|
+
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + exp);
|
|
58
|
+
} else if (exp instanceof Date) {
|
|
59
|
+
expirationDate = exp;
|
|
60
|
+
} else if (exp) {
|
|
61
|
+
var tempexp = exp as ILocalStorageCacheLifetime;
|
|
62
|
+
var seconds = typeof (tempexp.seconds) === "number" ? tempexp.seconds : undefined;
|
|
63
|
+
var minutes = typeof (tempexp.minutes) === "number" ? tempexp.minutes : undefined;
|
|
64
|
+
var hours = typeof (tempexp.hours) === "number" ? tempexp.hours : undefined;
|
|
65
|
+
var days = typeof (tempexp.days) === "number" ? tempexp.days : undefined;
|
|
66
|
+
var months = typeof (tempexp.months) === "number" ? tempexp.months : undefined;
|
|
67
|
+
var years = typeof (tempexp.years) === "number" ? tempexp.years : undefined;
|
|
68
|
+
|
|
69
|
+
if (seconds || minutes || hours || days || months || years) {
|
|
70
|
+
expirationDate = new Date();
|
|
71
|
+
|
|
72
|
+
if (seconds) {
|
|
73
|
+
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + (seconds * 1000));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (minutes) {
|
|
77
|
+
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + (minutes * 60 * 1000));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (hours) {
|
|
81
|
+
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + (hours * 60 * 60 * 1000));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (days) {
|
|
85
|
+
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + (days * 24 * 60 * 60 * 1000));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (months) {
|
|
89
|
+
expirationDate.setMonth(expirationDate.getMonth() + months);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (years) {
|
|
93
|
+
expirationDate.setFullYear(expirationDate.getFullYear() + years);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!expirationDate) {
|
|
99
|
+
expirationDate = new Date();
|
|
100
|
+
expirationDate.setMilliseconds(expirationDate.getMilliseconds() + DEFAULT_EXPIRATION);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return expirationDate;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function _getCacheExpirations(): IExpirationsDictionary {
|
|
107
|
+
let _cache = _getCache();
|
|
108
|
+
if (isNullOrUndefined(_cache.expirations)) {
|
|
109
|
+
_cache.expirations = jsonParse<IExpirationsDictionary>(_getItem(LOCAL_STORGAGE_EXPIRATIONS_KEY));
|
|
110
|
+
|
|
111
|
+
//ISSUE: 1525 - expire the cache if it was built with a different version number so that the cache
|
|
112
|
+
//is compatible with the current build
|
|
113
|
+
if (!isNullOrUndefined(_cache.expirations) && _cache.expirations.build !== MODULE_REVISION) {
|
|
114
|
+
logger.log(`Purging cache because of build number change`)
|
|
115
|
+
purgeCache(true);
|
|
116
|
+
_cache.expirations = null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (isNullOrUndefined(_cache.expirations)) {
|
|
120
|
+
_cache.expirations = {
|
|
121
|
+
build: MODULE_REVISION
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return _cache.expirations;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function _saveCacheExpirations() {
|
|
130
|
+
let _cache = _getCache();
|
|
131
|
+
if (!isNullOrUndefined(_cache.expirations) && sizeOf(_cache.expirations) > 0) {
|
|
132
|
+
_setItem(LOCAL_STORGAGE_EXPIRATIONS_KEY, JSON.stringify(_cache.expirations));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
_removeItem(LOCAL_STORGAGE_EXPIRATIONS_KEY);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function _setCacheExpiration(keyWithPrefix: string, expireDate: Date) {
|
|
140
|
+
var expirations = _getCacheExpirations();
|
|
141
|
+
expirations[keyWithPrefix] = expireDate.toISOString();
|
|
142
|
+
_saveCacheExpirations();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function _isKeyExpired(keyWithPrefix: string) {
|
|
146
|
+
var expirations = _getCacheExpirations();
|
|
147
|
+
if (expirations && expirations[keyWithPrefix]) {
|
|
148
|
+
var now = new Date();
|
|
149
|
+
var eDate = new Date(expirations[keyWithPrefix]);
|
|
150
|
+
if (now > eDate) {
|
|
151
|
+
try {
|
|
152
|
+
delete expirations[keyWithPrefix];
|
|
153
|
+
} catch (ex) {
|
|
154
|
+
expirations[keyWithPrefix] = undefined; // undefined variables are removed when passed to JSON.stringify
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
_saveCacheExpirations();
|
|
158
|
+
//has a date, it is expired.
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
//has a date, it is not expired yet.
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
//has no date or not in expirations at all - say it is expired...
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function _getItem(key: string) {
|
|
169
|
+
try {
|
|
170
|
+
return localStorage.getItem(key);
|
|
171
|
+
} catch {
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function _setItem(key: string, value: string) {
|
|
177
|
+
try {
|
|
178
|
+
localStorage.setItem(key, value);
|
|
179
|
+
return true;
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function _removeItem(key: string) {
|
|
186
|
+
try {
|
|
187
|
+
localStorage.removeItem(key);
|
|
188
|
+
return true;
|
|
189
|
+
} catch {
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**Get the size (KB) of all entries in local storage. Only returns the size for entries with kwizcom key prefix. */
|
|
195
|
+
function _getStoredSize() {
|
|
196
|
+
let keys = getCacheKeys();
|
|
197
|
+
let total = 0;
|
|
198
|
+
let length = 0;
|
|
199
|
+
let useBlob = 'Blob' in (globalThis || window);
|
|
200
|
+
|
|
201
|
+
keys.forEach((key) => {
|
|
202
|
+
let v = _getItem(`${keyPrefix}${key}`);
|
|
203
|
+
if (!isNullOrEmptyString(v)) {
|
|
204
|
+
if (useBlob) {
|
|
205
|
+
length = (new Blob([v + key])).size;
|
|
206
|
+
} else {
|
|
207
|
+
length = ((v.length + key.length) * 2);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
total += length;
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
return Number((total / 1024).toFixed(2));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function isLocalStorageSupported() {
|
|
217
|
+
if (_supportsLocalStorage !== null) {
|
|
218
|
+
return _supportsLocalStorage;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
var result;
|
|
222
|
+
try {
|
|
223
|
+
_setItem(LOCAL_STORAGE_PREFIX, LOCAL_STORAGE_PREFIX);
|
|
224
|
+
result = _getItem(LOCAL_STORAGE_PREFIX) === LOCAL_STORAGE_PREFIX;
|
|
225
|
+
_removeItem(LOCAL_STORAGE_PREFIX);
|
|
226
|
+
_supportsLocalStorage = result;
|
|
227
|
+
} catch (ex) {
|
|
228
|
+
_supportsLocalStorage = false;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return _supportsLocalStorage;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
//#region exported methods
|
|
235
|
+
export function getCacheItem<T>(key: string, options?: {
|
|
236
|
+
/** Flatted allows serizlising circular dependency objects */
|
|
237
|
+
useFlatted?: boolean;
|
|
238
|
+
}): T {
|
|
239
|
+
key = key.toLowerCase();
|
|
240
|
+
let keyWithPrefix = keyPrefix + key;
|
|
241
|
+
|
|
242
|
+
let _cache = _getCache();
|
|
243
|
+
|
|
244
|
+
if (typeof (_cache[key]) !== "undefined"
|
|
245
|
+
&& _cache[key] !== null) {
|
|
246
|
+
return _cache[key] as T;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (isLocalStorageSupported()) {
|
|
250
|
+
var value: string = _getItem(keyWithPrefix);
|
|
251
|
+
if (isNullOrUndefined(value)) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
let isExpired = _isKeyExpired(keyWithPrefix);
|
|
256
|
+
|
|
257
|
+
if (!isExpired) {
|
|
258
|
+
let valueAsT: T = options && options.useFlatted ? flatted.parse(value) as T : jsonParse<T>(value);
|
|
259
|
+
if (valueAsT !== null) {
|
|
260
|
+
_cache[key] = valueAsT;
|
|
261
|
+
return valueAsT;
|
|
262
|
+
} else {
|
|
263
|
+
_cache[key] = value;
|
|
264
|
+
return value as any as T;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
//else remove it from cache
|
|
268
|
+
removeCacheItem(key);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export function setCacheItem(key: string, value: any, expiration: number | ILocalStorageCacheLifetime | Date, options?: {
|
|
275
|
+
/** Flatted allows serizlising circular dependency objects */
|
|
276
|
+
useFlatted?: boolean;
|
|
277
|
+
}): void {
|
|
278
|
+
if (isLocalStorageSupported()) {
|
|
279
|
+
key = key.toLowerCase();
|
|
280
|
+
removeCacheItem(key);
|
|
281
|
+
|
|
282
|
+
var val = null;
|
|
283
|
+
try {
|
|
284
|
+
if (options && options.useFlatted)
|
|
285
|
+
val = flatted.stringify(value);
|
|
286
|
+
else
|
|
287
|
+
val = JSON.stringify(value);
|
|
288
|
+
} catch (ex) {
|
|
289
|
+
logger.debug(`Object cannot be stored in local storage: ${ex && ex.message || ex} ${key}`);
|
|
290
|
+
return;//this put [object] in cache for me if object can't be stringified!
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
let keyWithPrefix = keyPrefix + key;
|
|
294
|
+
|
|
295
|
+
var expireDate = _parseExpiration(expiration);
|
|
296
|
+
|
|
297
|
+
let saved = _setItem(keyWithPrefix, val);
|
|
298
|
+
if (saved) {
|
|
299
|
+
_setCacheExpiration(keyWithPrefix, expireDate);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
let _cache = _getCache();
|
|
303
|
+
|
|
304
|
+
_cache[key] = value;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function removeCacheItem(key: string) {
|
|
309
|
+
key = key.toLowerCase();
|
|
310
|
+
let _cache = _getCache();
|
|
311
|
+
delete _cache[key];
|
|
312
|
+
let keyWithPrefix = keyPrefix + key;
|
|
313
|
+
|
|
314
|
+
if (isLocalStorageSupported()) {
|
|
315
|
+
_removeItem(key);//in case we have an old one
|
|
316
|
+
_removeItem(keyWithPrefix);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function removeCacheItems(keys: string[]) {
|
|
321
|
+
keys.forEach((key) => {
|
|
322
|
+
removeCacheItem(key);
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export function getCacheKeys() {
|
|
327
|
+
let keys: string[] = [];
|
|
328
|
+
|
|
329
|
+
if (isLocalStorageSupported()) {
|
|
330
|
+
keys = Object.keys(localStorage).filter((key) => {
|
|
331
|
+
return key.startsWith(keyPrefix);
|
|
332
|
+
}).map((key) => {
|
|
333
|
+
return key.substring(keyPrefix.length);
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return keys;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/** remove expired cache keys created by this utility.
|
|
341
|
+
* to remove all keys (non-expired too) send removeAll=true
|
|
342
|
+
*/
|
|
343
|
+
function purgeCache(removeAll?: boolean) {
|
|
344
|
+
if (!isLocalStorageSupported()) return;
|
|
345
|
+
|
|
346
|
+
var cacheExpirationsKeys = [
|
|
347
|
+
LOCAL_STORGAGE_EXPIRATIONS_KEY,
|
|
348
|
+
"kwizcom-aplfe-caching-expirations", // old clean up
|
|
349
|
+
"localStorageExpirations" // old clean up
|
|
350
|
+
];
|
|
351
|
+
|
|
352
|
+
let now = new Date();
|
|
353
|
+
|
|
354
|
+
let nonExpiredKeys: string[] = [];
|
|
355
|
+
|
|
356
|
+
//get all expiration keys (key/expiration date/time)
|
|
357
|
+
for (let j = 0; j < cacheExpirationsKeys.length; j++) {
|
|
358
|
+
try {
|
|
359
|
+
let expirations = null;
|
|
360
|
+
let cacheExpirationsKey = cacheExpirationsKeys[j];
|
|
361
|
+
|
|
362
|
+
let removeAllForKey = removeAll || cacheExpirationsKey !== LOCAL_STORGAGE_EXPIRATIONS_KEY;
|
|
363
|
+
|
|
364
|
+
if (cacheExpirationsKey === "localStorageExpirations") {
|
|
365
|
+
//old format - load expirations from this one as well
|
|
366
|
+
expirations = _getItem(cacheExpirationsKey); // "key1^11/18/2011 5pm|key2^3/10/2012 3pm"
|
|
367
|
+
if (expirations) {
|
|
368
|
+
let arr = expirations.split("|"); // ["key1^11/18/2011 5pm","key2^3/10/2012 3pm"]
|
|
369
|
+
for (let i = 0; i < arr.length; i++) {
|
|
370
|
+
try {
|
|
371
|
+
let key_expiration_format = arr[i]; // "key1^11/18/2011 5pm"
|
|
372
|
+
let key = key_expiration_format.split("^")[0];
|
|
373
|
+
//old keys - remove all, all the time
|
|
374
|
+
_removeItem(key);//remove key from cache
|
|
375
|
+
} catch (e) { }
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
} else {
|
|
379
|
+
//new format
|
|
380
|
+
expirations = cacheExpirationsKey === LOCAL_STORGAGE_EXPIRATIONS_KEY ? _getCacheExpirations() : jsonParse(_getItem(cacheExpirationsKey));
|
|
381
|
+
if (expirations) {
|
|
382
|
+
let expirationKeys = Object.keys(expirations);
|
|
383
|
+
logger.group(() => {
|
|
384
|
+
expirationKeys.forEach(keyWithPrefix => {
|
|
385
|
+
try {
|
|
386
|
+
let shouldRemoveKey = removeAllForKey || !keyWithPrefix.startsWith(keyPrefix);
|
|
387
|
+
if (!shouldRemoveKey) {
|
|
388
|
+
//check specific key expiration
|
|
389
|
+
let expirationDate = new Date(expirations[keyWithPrefix]);
|
|
390
|
+
if (!isDate(expirationDate) || expirationDate < now) {
|
|
391
|
+
shouldRemoveKey = true;
|
|
392
|
+
delete expirations[keyWithPrefix];
|
|
393
|
+
logger.info(`purging key ${keyWithPrefix}`);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
nonExpiredKeys.push(keyWithPrefix);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (shouldRemoveKey) _removeItem(keyWithPrefix);
|
|
400
|
+
} catch (e) {
|
|
401
|
+
logger.warn(`failed to remove key ${keyWithPrefix}`);
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}, "Checking expired items", true);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (cacheExpirationsKey === LOCAL_STORGAGE_EXPIRATIONS_KEY)
|
|
409
|
+
_saveCacheExpirations();
|
|
410
|
+
else//older keys - just remove them.
|
|
411
|
+
_removeItem(cacheExpirationsKey);
|
|
412
|
+
} catch (e) {
|
|
413
|
+
logger.warn(`something went terribly wrong ${e}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
logger.group(() => {
|
|
418
|
+
logger.table(nonExpiredKeys);
|
|
419
|
+
//cleanup orphans
|
|
420
|
+
//loop on all keys
|
|
421
|
+
//if stats with: jsr_, kwfs| or keyPrefix - and not in nonExpiredKeys, it is an orphan. Remove it.
|
|
422
|
+
let localStorageKeys = Object.keys(localStorage);
|
|
423
|
+
for (let keyIdx = 0; keyIdx < localStorageKeys.length; keyIdx++) {
|
|
424
|
+
let key = localStorageKeys[keyIdx];
|
|
425
|
+
if (key.startsWith("jsr_") || key.startsWith("kwfs|")) {
|
|
426
|
+
logger.log(`removing old key ${key}`);
|
|
427
|
+
_removeItem(key);//old key
|
|
428
|
+
}
|
|
429
|
+
else if (key.startsWith(keyPrefix) && !nonExpiredKeys.includes(key))//orphan!
|
|
430
|
+
{
|
|
431
|
+
logger.log(`removing orphan key ${key}`);
|
|
432
|
+
_removeItem(key);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}, "Expired keys", true);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/** cleanup - remove all local storage keys created by this utility */
|
|
439
|
+
export function clearCache(): void {
|
|
440
|
+
return purgeCache(true);
|
|
441
|
+
}
|
|
442
442
|
//#endregion
|