1 | /*
|
2 | * Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 | *
|
4 | * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
|
5 | * the License. A copy of the License is located at
|
6 | *
|
7 | * http://aws.amazon.com/apache2.0/
|
8 | *
|
9 | * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
10 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
|
11 | * and limitations under the License.
|
12 | */
|
13 | var __extends = (this && this.__extends) || (function () {
|
14 | var extendStatics = function (d, b) {
|
15 | extendStatics = Object.setPrototypeOf ||
|
16 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
17 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
18 | return extendStatics(d, b);
|
19 | };
|
20 | return function (d, b) {
|
21 | extendStatics(d, b);
|
22 | function __() { this.constructor = d; }
|
23 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
24 | };
|
25 | })();
|
26 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
27 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
28 | return new (P || (P = Promise))(function (resolve, reject) {
|
29 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
30 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
31 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
32 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
33 | });
|
34 | };
|
35 | var __generator = (this && this.__generator) || function (thisArg, body) {
|
36 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
37 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
38 | function verb(n) { return function (v) { return step([n, v]); }; }
|
39 | function step(op) {
|
40 | if (f) throw new TypeError("Generator is already executing.");
|
41 | while (_) try {
|
42 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
43 | if (y = 0, t) op = [op[0] & 2, t.value];
|
44 | switch (op[0]) {
|
45 | case 0: case 1: t = op; break;
|
46 | case 4: _.label++; return { value: op[1], done: false };
|
47 | case 5: _.label++; y = op[1]; op = [0]; continue;
|
48 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
49 | default:
|
50 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
51 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
52 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
53 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
54 | if (t[2]) _.ops.pop();
|
55 | _.trys.pop(); continue;
|
56 | }
|
57 | op = body.call(thisArg, _);
|
58 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
59 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
60 | }
|
61 | };
|
62 | import { StorageCache } from './StorageCache';
|
63 | import { defaultConfig, getCurrTime } from './Utils';
|
64 | import { AsyncStorage } from 'react-native';
|
65 | import { ConsoleLogger as Logger } from '@aws-amplify/core';
|
66 | var logger = new Logger('AsyncStorageCache');
|
67 | /*
|
68 | * Customized cache which based on the AsyncStorage with LRU implemented
|
69 | */
|
70 | var AsyncStorageCache = /** @class */ (function (_super) {
|
71 | __extends(AsyncStorageCache, _super);
|
72 | /**
|
73 | * initialize the cache
|
74 | *
|
75 | * @param {Object} config - the configuration of the cache
|
76 | */
|
77 | function AsyncStorageCache(config) {
|
78 | var _this = this;
|
79 | var cache_config = config
|
80 | ? Object.assign({}, defaultConfig, config)
|
81 | : defaultConfig;
|
82 | _this = _super.call(this, cache_config) || this;
|
83 | _this.getItem = _this.getItem.bind(_this);
|
84 | _this.setItem = _this.setItem.bind(_this);
|
85 | _this.removeItem = _this.removeItem.bind(_this);
|
86 | logger.debug('Using AsyncStorageCache');
|
87 | return _this;
|
88 | }
|
89 | /**
|
90 | * decrease current size of the cache
|
91 | * @private
|
92 | * @param amount - the amount of the cache size which needs to be decreased
|
93 | */
|
94 | AsyncStorageCache.prototype._decreaseCurSizeInBytes = function (amount) {
|
95 | return __awaiter(this, void 0, void 0, function () {
|
96 | var curSize;
|
97 | return __generator(this, function (_a) {
|
98 | switch (_a.label) {
|
99 | case 0: return [4 /*yield*/, this.getCacheCurSize()];
|
100 | case 1:
|
101 | curSize = _a.sent();
|
102 | return [4 /*yield*/, AsyncStorage.setItem(this.cacheCurSizeKey, (curSize - amount).toString())];
|
103 | case 2:
|
104 | _a.sent();
|
105 | return [2 /*return*/];
|
106 | }
|
107 | });
|
108 | });
|
109 | };
|
110 | /**
|
111 | * increase current size of the cache
|
112 | * @private
|
113 | * @param amount - the amount of the cache szie which need to be increased
|
114 | */
|
115 | AsyncStorageCache.prototype._increaseCurSizeInBytes = function (amount) {
|
116 | return __awaiter(this, void 0, void 0, function () {
|
117 | var curSize;
|
118 | return __generator(this, function (_a) {
|
119 | switch (_a.label) {
|
120 | case 0: return [4 /*yield*/, this.getCacheCurSize()];
|
121 | case 1:
|
122 | curSize = _a.sent();
|
123 | return [4 /*yield*/, AsyncStorage.setItem(this.cacheCurSizeKey, (curSize + amount).toString())];
|
124 | case 2:
|
125 | _a.sent();
|
126 | return [2 /*return*/];
|
127 | }
|
128 | });
|
129 | });
|
130 | };
|
131 | /**
|
132 | * update the visited time if item has been visited
|
133 | * @private
|
134 | * @param item - the item which need to be refreshed
|
135 | * @param prefixedKey - the key of the item
|
136 | *
|
137 | * @return the refreshed item
|
138 | */
|
139 | AsyncStorageCache.prototype._refreshItem = function (item, prefixedKey) {
|
140 | return __awaiter(this, void 0, void 0, function () {
|
141 | return __generator(this, function (_a) {
|
142 | switch (_a.label) {
|
143 | case 0:
|
144 | item.visitedTime = getCurrTime();
|
145 | return [4 /*yield*/, AsyncStorage.setItem(prefixedKey, JSON.stringify(item))];
|
146 | case 1:
|
147 | _a.sent();
|
148 | return [2 /*return*/, item];
|
149 | }
|
150 | });
|
151 | });
|
152 | };
|
153 | /**
|
154 | * check wether item is expired
|
155 | * @private
|
156 | * @param key - the key of the item
|
157 | *
|
158 | * @return true if the item is expired.
|
159 | */
|
160 | AsyncStorageCache.prototype._isExpired = function (key) {
|
161 | return __awaiter(this, void 0, void 0, function () {
|
162 | var text, item;
|
163 | return __generator(this, function (_a) {
|
164 | switch (_a.label) {
|
165 | case 0: return [4 /*yield*/, AsyncStorage.getItem(key)];
|
166 | case 1:
|
167 | text = _a.sent();
|
168 | item = JSON.parse(text);
|
169 | if (getCurrTime() >= item.expires) {
|
170 | return [2 /*return*/, true];
|
171 | }
|
172 | return [2 /*return*/, false];
|
173 | }
|
174 | });
|
175 | });
|
176 | };
|
177 | /**
|
178 | * delete item from cache
|
179 | * @private
|
180 | * @param prefixedKey - the key of the item
|
181 | * @param size - optional, the byte size of the item
|
182 | */
|
183 | AsyncStorageCache.prototype._removeItem = function (prefixedKey, size) {
|
184 | return __awaiter(this, void 0, void 0, function () {
|
185 | var itemSize, _a, _b, _c, removeItemError_1;
|
186 | return __generator(this, function (_d) {
|
187 | switch (_d.label) {
|
188 | case 0:
|
189 | if (!size) return [3 /*break*/, 1];
|
190 | _a = size;
|
191 | return [3 /*break*/, 3];
|
192 | case 1:
|
193 | _c = (_b = JSON).parse;
|
194 | return [4 /*yield*/, AsyncStorage.getItem(prefixedKey)];
|
195 | case 2:
|
196 | _a = _c.apply(_b, [_d.sent()]).byteSize;
|
197 | _d.label = 3;
|
198 | case 3:
|
199 | itemSize = _a;
|
200 | // first try to update the current size of the cache
|
201 | return [4 /*yield*/, this._decreaseCurSizeInBytes(itemSize)];
|
202 | case 4:
|
203 | // first try to update the current size of the cache
|
204 | _d.sent();
|
205 | _d.label = 5;
|
206 | case 5:
|
207 | _d.trys.push([5, 7, , 9]);
|
208 | return [4 /*yield*/, AsyncStorage.removeItem(prefixedKey)];
|
209 | case 6:
|
210 | _d.sent();
|
211 | return [3 /*break*/, 9];
|
212 | case 7:
|
213 | removeItemError_1 = _d.sent();
|
214 | // if some error happened, we need to rollback the current size
|
215 | return [4 /*yield*/, this._increaseCurSizeInBytes(itemSize)];
|
216 | case 8:
|
217 | // if some error happened, we need to rollback the current size
|
218 | _d.sent();
|
219 | logger.error("Failed to remove item: " + removeItemError_1);
|
220 | return [3 /*break*/, 9];
|
221 | case 9: return [2 /*return*/];
|
222 | }
|
223 | });
|
224 | });
|
225 | };
|
226 | /**
|
227 | * put item into cache
|
228 | * @private
|
229 | * @param prefixedKey - the key of the item
|
230 | * @param itemData - the value of the item
|
231 | * @param itemSizeInBytes - the byte size of the item
|
232 | */
|
233 | AsyncStorageCache.prototype._setItem = function (prefixedKey, item) {
|
234 | return __awaiter(this, void 0, void 0, function () {
|
235 | var setItemErr_1;
|
236 | return __generator(this, function (_a) {
|
237 | switch (_a.label) {
|
238 | case 0:
|
239 | // first try to update the current size of the cache.
|
240 | return [4 /*yield*/, this._increaseCurSizeInBytes(item.byteSize)];
|
241 | case 1:
|
242 | // first try to update the current size of the cache.
|
243 | _a.sent();
|
244 | _a.label = 2;
|
245 | case 2:
|
246 | _a.trys.push([2, 4, , 6]);
|
247 | return [4 /*yield*/, AsyncStorage.setItem(prefixedKey, JSON.stringify(item))];
|
248 | case 3:
|
249 | _a.sent();
|
250 | return [3 /*break*/, 6];
|
251 | case 4:
|
252 | setItemErr_1 = _a.sent();
|
253 | // if some error happened, we need to rollback the current size
|
254 | return [4 /*yield*/, this._decreaseCurSizeInBytes(item.byteSize)];
|
255 | case 5:
|
256 | // if some error happened, we need to rollback the current size
|
257 | _a.sent();
|
258 | logger.error("Failed to set item " + setItemErr_1);
|
259 | return [3 /*break*/, 6];
|
260 | case 6: return [2 /*return*/];
|
261 | }
|
262 | });
|
263 | });
|
264 | };
|
265 | /**
|
266 | * total space needed when poping out items
|
267 | * @private
|
268 | * @param itemSize
|
269 | *
|
270 | * @return total space needed
|
271 | */
|
272 | AsyncStorageCache.prototype._sizeToPop = function (itemSize) {
|
273 | return __awaiter(this, void 0, void 0, function () {
|
274 | var spaceItemNeed, cacheThresholdSpace;
|
275 | return __generator(this, function (_a) {
|
276 | switch (_a.label) {
|
277 | case 0: return [4 /*yield*/, this.getCacheCurSize()];
|
278 | case 1:
|
279 | spaceItemNeed = (_a.sent()) + itemSize - this.config.capacityInBytes;
|
280 | cacheThresholdSpace = (1 - this.config.warningThreshold) * this.config.capacityInBytes;
|
281 | return [2 /*return*/, spaceItemNeed > cacheThresholdSpace
|
282 | ? spaceItemNeed
|
283 | : cacheThresholdSpace];
|
284 | }
|
285 | });
|
286 | });
|
287 | };
|
288 | /**
|
289 | * see whether cache is full
|
290 | * @private
|
291 | * @param itemSize
|
292 | *
|
293 | * @return true if cache is full
|
294 | */
|
295 | AsyncStorageCache.prototype._isCacheFull = function (itemSize) {
|
296 | return __awaiter(this, void 0, void 0, function () {
|
297 | var _a;
|
298 | return __generator(this, function (_b) {
|
299 | switch (_b.label) {
|
300 | case 0:
|
301 | _a = itemSize;
|
302 | return [4 /*yield*/, this.getCacheCurSize()];
|
303 | case 1: return [2 /*return*/, (_a + (_b.sent()) > this.config.capacityInBytes)];
|
304 | }
|
305 | });
|
306 | });
|
307 | };
|
308 | /**
|
309 | * scan the storage and find out all the keys owned by this cache
|
310 | * also clean the expired keys while scanning
|
311 | * @private
|
312 | * @return array of keys
|
313 | */
|
314 | AsyncStorageCache.prototype._findValidKeys = function () {
|
315 | return __awaiter(this, void 0, void 0, function () {
|
316 | var keys, keyInCache, i, key;
|
317 | return __generator(this, function (_a) {
|
318 | switch (_a.label) {
|
319 | case 0:
|
320 | keys = [];
|
321 | keyInCache = [];
|
322 | return [4 /*yield*/, AsyncStorage.getAllKeys()];
|
323 | case 1:
|
324 | keyInCache = _a.sent();
|
325 | i = 0;
|
326 | _a.label = 2;
|
327 | case 2:
|
328 | if (!(i < keyInCache.length)) return [3 /*break*/, 7];
|
329 | key = keyInCache[i];
|
330 | if (!(key.indexOf(this.config.keyPrefix) === 0 &&
|
331 | key !== this.cacheCurSizeKey)) return [3 /*break*/, 6];
|
332 | return [4 /*yield*/, this._isExpired(key)];
|
333 | case 3:
|
334 | if (!_a.sent()) return [3 /*break*/, 5];
|
335 | return [4 /*yield*/, this._removeItem(key)];
|
336 | case 4:
|
337 | _a.sent();
|
338 | return [3 /*break*/, 6];
|
339 | case 5:
|
340 | keys.push(key);
|
341 | _a.label = 6;
|
342 | case 6:
|
343 | i += 1;
|
344 | return [3 /*break*/, 2];
|
345 | case 7: return [2 /*return*/, keys];
|
346 | }
|
347 | });
|
348 | });
|
349 | };
|
350 | /**
|
351 | * get all the items we have, sort them by their priority,
|
352 | * if priority is same, sort them by their last visited time
|
353 | * pop out items from the low priority (5 is the lowest)
|
354 | * @private
|
355 | * @param keys - all the keys in this cache
|
356 | * @param sizeToPop - the total size of the items which needed to be poped out
|
357 | */
|
358 | AsyncStorageCache.prototype._popOutItems = function (keys, sizeToPop) {
|
359 | return __awaiter(this, void 0, void 0, function () {
|
360 | var items, remainedSize, i, val, item, i;
|
361 | return __generator(this, function (_a) {
|
362 | switch (_a.label) {
|
363 | case 0:
|
364 | items = [];
|
365 | remainedSize = sizeToPop;
|
366 | i = 0;
|
367 | _a.label = 1;
|
368 | case 1:
|
369 | if (!(i < keys.length)) return [3 /*break*/, 4];
|
370 | return [4 /*yield*/, AsyncStorage.getItem(keys[i])];
|
371 | case 2:
|
372 | val = _a.sent();
|
373 | if (val != null) {
|
374 | item = JSON.parse(val);
|
375 | items.push(item);
|
376 | }
|
377 | _a.label = 3;
|
378 | case 3:
|
379 | i += 1;
|
380 | return [3 /*break*/, 1];
|
381 | case 4:
|
382 | // first compare priority
|
383 | // then compare visited time
|
384 | items.sort(function (a, b) {
|
385 | if (a.priority > b.priority) {
|
386 | return -1;
|
387 | }
|
388 | else if (a.priority < b.priority) {
|
389 | return 1;
|
390 | }
|
391 | else {
|
392 | if (a.visitedTime < b.visitedTime) {
|
393 | return -1;
|
394 | }
|
395 | else
|
396 | return 1;
|
397 | }
|
398 | });
|
399 | i = 0;
|
400 | _a.label = 5;
|
401 | case 5:
|
402 | if (!(i < items.length)) return [3 /*break*/, 8];
|
403 | // pop out items until we have enough room for new item
|
404 | return [4 /*yield*/, this._removeItem(items[i].key, items[i].byteSize)];
|
405 | case 6:
|
406 | // pop out items until we have enough room for new item
|
407 | _a.sent();
|
408 | remainedSize -= items[i].byteSize;
|
409 | if (remainedSize <= 0) {
|
410 | return [2 /*return*/];
|
411 | }
|
412 | _a.label = 7;
|
413 | case 7:
|
414 | i += 1;
|
415 | return [3 /*break*/, 5];
|
416 | case 8: return [2 /*return*/];
|
417 | }
|
418 | });
|
419 | });
|
420 | };
|
421 | /**
|
422 | * Set item into cache. You can put number, string, boolean or object.
|
423 | * The cache will first check whether has the same key.
|
424 | * If it has, it will delete the old item and then put the new item in
|
425 | * The cache will pop out items if it is full
|
426 | * You can specify the cache item options. The cache will abort and output a warning:
|
427 | * If the key is invalid
|
428 | * If the size of the item exceeds itemMaxSize.
|
429 | * If the value is undefined
|
430 | * If incorrect cache item configuration
|
431 | * If error happened with browser storage
|
432 | *
|
433 | * @param {String} key - the key of the item
|
434 | * @param {Object} value - the value of the item
|
435 | * @param {Object} [options] - optional, the specified meta-data
|
436 | * @return {Prmoise}
|
437 | */
|
438 | AsyncStorageCache.prototype.setItem = function (key, value, options) {
|
439 | return __awaiter(this, void 0, void 0, function () {
|
440 | var prefixedKey, cacheItemOptions, item, val, validKeys, sizeToPop, e_1;
|
441 | return __generator(this, function (_a) {
|
442 | switch (_a.label) {
|
443 | case 0:
|
444 | logger.debug("Set item: key is " + key + ", value is " + value + " with options: " + options);
|
445 | prefixedKey = this.config.keyPrefix + key;
|
446 | // invalid keys
|
447 | if (prefixedKey === this.config.keyPrefix ||
|
448 | prefixedKey === this.cacheCurSizeKey) {
|
449 | logger.warn("Invalid key: should not be empty or 'CurSize'");
|
450 | return [2 /*return*/];
|
451 | }
|
452 | if (typeof value === 'undefined') {
|
453 | logger.warn("The value of item should not be undefined!");
|
454 | return [2 /*return*/];
|
455 | }
|
456 | cacheItemOptions = {
|
457 | priority: options && options.priority !== undefined
|
458 | ? options.priority
|
459 | : this.config.defaultPriority,
|
460 | expires: options && options.expires !== undefined
|
461 | ? options.expires
|
462 | : this.config.defaultTTL + getCurrTime(),
|
463 | };
|
464 | if (cacheItemOptions.priority < 1 || cacheItemOptions.priority > 5) {
|
465 | logger.warn("Invalid parameter: priority due to out or range. It should be within 1 and 5.");
|
466 | return [2 /*return*/];
|
467 | }
|
468 | item = this.fillCacheItem(prefixedKey, value, cacheItemOptions);
|
469 | // check wether this item is too big;
|
470 | if (item.byteSize > this.config.itemMaxSize) {
|
471 | logger.warn("Item with key: " + key + " you are trying to put into is too big!");
|
472 | return [2 /*return*/];
|
473 | }
|
474 | _a.label = 1;
|
475 | case 1:
|
476 | _a.trys.push([1, 12, , 13]);
|
477 | return [4 /*yield*/, AsyncStorage.getItem(prefixedKey)];
|
478 | case 2:
|
479 | val = _a.sent();
|
480 | if (!val) return [3 /*break*/, 4];
|
481 | return [4 /*yield*/, this._removeItem(prefixedKey, JSON.parse(val).byteSize)];
|
482 | case 3:
|
483 | _a.sent();
|
484 | _a.label = 4;
|
485 | case 4: return [4 /*yield*/, this._isCacheFull(item.byteSize)];
|
486 | case 5:
|
487 | if (!_a.sent()) return [3 /*break*/, 10];
|
488 | return [4 /*yield*/, this._findValidKeys()];
|
489 | case 6:
|
490 | validKeys = _a.sent();
|
491 | return [4 /*yield*/, this._isCacheFull(item.byteSize)];
|
492 | case 7:
|
493 | if (!_a.sent()) return [3 /*break*/, 10];
|
494 | return [4 /*yield*/, this._sizeToPop(item.byteSize)];
|
495 | case 8:
|
496 | sizeToPop = _a.sent();
|
497 | return [4 /*yield*/, this._popOutItems(validKeys, sizeToPop)];
|
498 | case 9:
|
499 | _a.sent();
|
500 | _a.label = 10;
|
501 | case 10:
|
502 | // put item in the cache
|
503 | return [4 /*yield*/, this._setItem(prefixedKey, item)];
|
504 | case 11:
|
505 | // put item in the cache
|
506 | _a.sent();
|
507 | return [3 /*break*/, 13];
|
508 | case 12:
|
509 | e_1 = _a.sent();
|
510 | logger.warn("setItem failed! " + e_1);
|
511 | return [3 /*break*/, 13];
|
512 | case 13: return [2 /*return*/];
|
513 | }
|
514 | });
|
515 | });
|
516 | };
|
517 | /**
|
518 | * Get item from cache. It will return null if item doesn’t exist or it has been expired.
|
519 | * If you specified callback function in the options,
|
520 | * then the function will be executed if no such item in the cache
|
521 | * and finally put the return value into cache.
|
522 | * Please make sure the callback function will return the value you want to put into the cache.
|
523 | * The cache will abort output a warning:
|
524 | * If the key is invalid
|
525 | * If error happened with AsyncStorage
|
526 | *
|
527 | * @param {String} key - the key of the item
|
528 | * @param {Object} [options] - the options of callback function
|
529 | * @return {Promise} - return a promise resolves to be the value of the item
|
530 | */
|
531 | AsyncStorageCache.prototype.getItem = function (key, options) {
|
532 | return __awaiter(this, void 0, void 0, function () {
|
533 | var ret, prefixedKey, item, val, e_2;
|
534 | return __generator(this, function (_a) {
|
535 | switch (_a.label) {
|
536 | case 0:
|
537 | logger.debug("Get item: key is " + key + " with options " + options);
|
538 | ret = null;
|
539 | prefixedKey = this.config.keyPrefix + key;
|
540 | if (prefixedKey === this.config.keyPrefix ||
|
541 | prefixedKey === this.cacheCurSizeKey) {
|
542 | logger.warn("Invalid key: should not be empty or 'CurSize'");
|
543 | return [2 /*return*/, null];
|
544 | }
|
545 | _a.label = 1;
|
546 | case 1:
|
547 | _a.trys.push([1, 8, , 9]);
|
548 | return [4 /*yield*/, AsyncStorage.getItem(prefixedKey)];
|
549 | case 2:
|
550 | ret = _a.sent();
|
551 | if (!(ret != null)) return [3 /*break*/, 7];
|
552 | return [4 /*yield*/, this._isExpired(prefixedKey)];
|
553 | case 3:
|
554 | if (!_a.sent()) return [3 /*break*/, 5];
|
555 | // if expired, remove that item and return null
|
556 | return [4 /*yield*/, this._removeItem(prefixedKey, JSON.parse(ret).byteSize)];
|
557 | case 4:
|
558 | // if expired, remove that item and return null
|
559 | _a.sent();
|
560 | return [3 /*break*/, 7];
|
561 | case 5:
|
562 | item = JSON.parse(ret);
|
563 | return [4 /*yield*/, this._refreshItem(item, prefixedKey)];
|
564 | case 6:
|
565 | item = _a.sent();
|
566 | return [2 /*return*/, item.data];
|
567 | case 7:
|
568 | if (options && options.callback !== undefined) {
|
569 | val = options.callback();
|
570 | if (val !== null) {
|
571 | this.setItem(key, val, options);
|
572 | }
|
573 | return [2 /*return*/, val];
|
574 | }
|
575 | return [2 /*return*/, null];
|
576 | case 8:
|
577 | e_2 = _a.sent();
|
578 | logger.warn("getItem failed! " + e_2);
|
579 | return [2 /*return*/, null];
|
580 | case 9: return [2 /*return*/];
|
581 | }
|
582 | });
|
583 | });
|
584 | };
|
585 | /**
|
586 | * remove item from the cache
|
587 | * The cache will abort output a warning:
|
588 | * If error happened with AsyncStorage
|
589 | * @param {String} key - the key of the item
|
590 | * @return {Promise}
|
591 | */
|
592 | AsyncStorageCache.prototype.removeItem = function (key) {
|
593 | return __awaiter(this, void 0, void 0, function () {
|
594 | var prefixedKey, val, e_3;
|
595 | return __generator(this, function (_a) {
|
596 | switch (_a.label) {
|
597 | case 0:
|
598 | logger.debug("Remove item: key is " + key);
|
599 | prefixedKey = this.config.keyPrefix + key;
|
600 | if (prefixedKey === this.config.keyPrefix ||
|
601 | prefixedKey === this.cacheCurSizeKey) {
|
602 | return [2 /*return*/];
|
603 | }
|
604 | _a.label = 1;
|
605 | case 1:
|
606 | _a.trys.push([1, 5, , 6]);
|
607 | return [4 /*yield*/, AsyncStorage.getItem(prefixedKey)];
|
608 | case 2:
|
609 | val = _a.sent();
|
610 | if (!val) return [3 /*break*/, 4];
|
611 | return [4 /*yield*/, this._removeItem(prefixedKey, JSON.parse(val).byteSize)];
|
612 | case 3:
|
613 | _a.sent();
|
614 | _a.label = 4;
|
615 | case 4: return [3 /*break*/, 6];
|
616 | case 5:
|
617 | e_3 = _a.sent();
|
618 | logger.warn("removeItem failed! " + e_3);
|
619 | return [3 /*break*/, 6];
|
620 | case 6: return [2 /*return*/];
|
621 | }
|
622 | });
|
623 | });
|
624 | };
|
625 | /**
|
626 | * clear the entire cache
|
627 | * The cache will abort output a warning:
|
628 | * If error happened with AsyncStorage
|
629 | * @return {Promise}
|
630 | */
|
631 | AsyncStorageCache.prototype.clear = function () {
|
632 | return __awaiter(this, void 0, void 0, function () {
|
633 | var keys, keysToRemove, i, i, e_4;
|
634 | return __generator(this, function (_a) {
|
635 | switch (_a.label) {
|
636 | case 0:
|
637 | logger.debug("Clear Cache");
|
638 | _a.label = 1;
|
639 | case 1:
|
640 | _a.trys.push([1, 7, , 8]);
|
641 | return [4 /*yield*/, AsyncStorage.getAllKeys()];
|
642 | case 2:
|
643 | keys = _a.sent();
|
644 | keysToRemove = [];
|
645 | for (i = 0; i < keys.length; i += 1) {
|
646 | if (keys[i].indexOf(this.config.keyPrefix) === 0) {
|
647 | keysToRemove.push(keys[i]);
|
648 | }
|
649 | }
|
650 | i = 0;
|
651 | _a.label = 3;
|
652 | case 3:
|
653 | if (!(i < keysToRemove.length)) return [3 /*break*/, 6];
|
654 | return [4 /*yield*/, AsyncStorage.removeItem(keysToRemove[i])];
|
655 | case 4:
|
656 | _a.sent();
|
657 | _a.label = 5;
|
658 | case 5:
|
659 | i += 1;
|
660 | return [3 /*break*/, 3];
|
661 | case 6: return [3 /*break*/, 8];
|
662 | case 7:
|
663 | e_4 = _a.sent();
|
664 | logger.warn("clear failed! " + e_4);
|
665 | return [3 /*break*/, 8];
|
666 | case 8: return [2 /*return*/];
|
667 | }
|
668 | });
|
669 | });
|
670 | };
|
671 | /**
|
672 | * return the current size of the cache
|
673 | * @return {Promise}
|
674 | */
|
675 | AsyncStorageCache.prototype.getCacheCurSize = function () {
|
676 | return __awaiter(this, void 0, void 0, function () {
|
677 | var ret;
|
678 | return __generator(this, function (_a) {
|
679 | switch (_a.label) {
|
680 | case 0: return [4 /*yield*/, AsyncStorage.getItem(this.cacheCurSizeKey)];
|
681 | case 1:
|
682 | ret = _a.sent();
|
683 | if (!!ret) return [3 /*break*/, 3];
|
684 | return [4 /*yield*/, AsyncStorage.setItem(this.cacheCurSizeKey, '0')];
|
685 | case 2:
|
686 | _a.sent();
|
687 | ret = '0';
|
688 | _a.label = 3;
|
689 | case 3: return [2 /*return*/, Number(ret)];
|
690 | }
|
691 | });
|
692 | });
|
693 | };
|
694 | /**
|
695 | * Return all the keys in the cache.
|
696 | * Will return an empty array if error happend.
|
697 | * @return {Promise}
|
698 | */
|
699 | AsyncStorageCache.prototype.getAllKeys = function () {
|
700 | return __awaiter(this, void 0, void 0, function () {
|
701 | var keys, retKeys, i, e_5;
|
702 | return __generator(this, function (_a) {
|
703 | switch (_a.label) {
|
704 | case 0:
|
705 | _a.trys.push([0, 2, , 3]);
|
706 | return [4 /*yield*/, AsyncStorage.getAllKeys()];
|
707 | case 1:
|
708 | keys = _a.sent();
|
709 | retKeys = [];
|
710 | for (i = 0; i < keys.length; i += 1) {
|
711 | if (keys[i].indexOf(this.config.keyPrefix) === 0 &&
|
712 | keys[i] !== this.cacheCurSizeKey) {
|
713 | retKeys.push(keys[i].substring(this.config.keyPrefix.length));
|
714 | }
|
715 | }
|
716 | return [2 /*return*/, retKeys];
|
717 | case 2:
|
718 | e_5 = _a.sent();
|
719 | logger.warn("getALlkeys failed! " + e_5);
|
720 | return [2 /*return*/, []];
|
721 | case 3: return [2 /*return*/];
|
722 | }
|
723 | });
|
724 | });
|
725 | };
|
726 | /**
|
727 | * Return a new instance of cache with customized configuration.
|
728 | * @param {Object} config - the customized configuration
|
729 | * @return {Object} - the new instance of Cache
|
730 | */
|
731 | AsyncStorageCache.prototype.createInstance = function (config) {
|
732 | if (config.keyPrefix === defaultConfig.keyPrefix) {
|
733 | logger.error('invalid keyPrefix, setting keyPrefix with timeStamp');
|
734 | config.keyPrefix = getCurrTime.toString();
|
735 | }
|
736 | return new AsyncStorageCache(config);
|
737 | };
|
738 | return AsyncStorageCache;
|
739 | }(StorageCache));
|
740 | export { AsyncStorageCache };
|
741 | var instance = new AsyncStorageCache();
|
742 | export { AsyncStorage, instance as Cache };
|
743 | export default instance;
|
744 | //# sourceMappingURL=AsyncStorageCache.js.map |
\ | No newline at end of file |