@splitsoftware/splitio-commons 2.5.0 → 2.5.1-rc.1

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.
Files changed (47) hide show
  1. package/CHANGES.txt +12 -0
  2. package/README.md +18 -18
  3. package/cjs/logger/messages/info.js +1 -1
  4. package/cjs/sdkFactory/index.js +1 -1
  5. package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
  6. package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +17 -17
  7. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +33 -37
  8. package/cjs/storages/inLocalStorage/index.js +31 -13
  9. package/cjs/storages/inLocalStorage/storageAdapter.js +54 -0
  10. package/cjs/storages/inLocalStorage/validateCache.js +28 -23
  11. package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
  12. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +2 -0
  13. package/cjs/sync/polling/updaters/splitChangesUpdater.js +2 -0
  14. package/cjs/sync/syncManagerOnline.js +28 -24
  15. package/cjs/utils/env/isLocalStorageAvailable.js +22 -1
  16. package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
  17. package/esm/logger/messages/info.js +1 -1
  18. package/esm/sdkFactory/index.js +1 -1
  19. package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
  20. package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +17 -17
  21. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +33 -37
  22. package/esm/storages/inLocalStorage/index.js +32 -14
  23. package/esm/storages/inLocalStorage/storageAdapter.js +50 -0
  24. package/esm/storages/inLocalStorage/validateCache.js +28 -23
  25. package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
  26. package/esm/sync/polling/updaters/mySegmentsUpdater.js +2 -0
  27. package/esm/sync/polling/updaters/splitChangesUpdater.js +2 -0
  28. package/esm/sync/syncManagerOnline.js +28 -24
  29. package/esm/utils/env/isLocalStorageAvailable.js +19 -0
  30. package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
  31. package/package.json +1 -1
  32. package/src/logger/messages/info.ts +1 -1
  33. package/src/sdkFactory/index.ts +1 -1
  34. package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +18 -17
  35. package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +19 -18
  36. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +34 -37
  37. package/src/storages/inLocalStorage/index.ts +37 -16
  38. package/src/storages/inLocalStorage/storageAdapter.ts +62 -0
  39. package/src/storages/inLocalStorage/validateCache.ts +29 -23
  40. package/src/storages/types.ts +19 -1
  41. package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +1 -2
  42. package/src/sync/polling/updaters/mySegmentsUpdater.ts +2 -0
  43. package/src/sync/polling/updaters/splitChangesUpdater.ts +3 -1
  44. package/src/sync/syncManagerOnline.ts +27 -22
  45. package/src/utils/env/isLocalStorageAvailable.ts +20 -0
  46. package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
  47. package/types/splitio.d.ts +52 -22
@@ -11,10 +11,10 @@ var MILLIS_IN_A_DAY = 86400000;
11
11
  *
12
12
  * @returns `true` if cache should be cleared, `false` otherwise
13
13
  */
14
- function validateExpiration(options, settings, keys, currentTimestamp, isThereCache) {
14
+ function validateExpiration(options, storage, settings, keys, currentTimestamp, isThereCache) {
15
15
  var log = settings.log, initialRolloutPlan = settings.initialRolloutPlan;
16
16
  // Check expiration
17
- var lastUpdatedTimestamp = parseInt(localStorage.getItem(keys.buildLastUpdatedKey()), 10);
17
+ var lastUpdatedTimestamp = parseInt(storage.getItem(keys.buildLastUpdatedKey()), 10);
18
18
  if (!(0, lang_1.isNaNNumber)(lastUpdatedTimestamp)) {
19
19
  var cacheExpirationInDays = (0, lang_1.isFiniteNumber)(options.expirationDays) && options.expirationDays >= 1 ? options.expirationDays : DEFAULT_CACHE_EXPIRATION_IN_DAYS;
20
20
  var expirationTimestamp = currentTimestamp - MILLIS_IN_A_DAY * cacheExpirationInDays;
@@ -25,11 +25,11 @@ function validateExpiration(options, settings, keys, currentTimestamp, isThereCa
25
25
  }
26
26
  // Check hash
27
27
  var storageHashKey = keys.buildHashKey();
28
- var storageHash = localStorage.getItem(storageHashKey);
28
+ var storageHash = storage.getItem(storageHashKey);
29
29
  var currentStorageHash = (0, KeyBuilder_1.getStorageHash)(settings);
30
30
  if (storageHash !== currentStorageHash) {
31
31
  try {
32
- localStorage.setItem(storageHashKey, currentStorageHash);
32
+ storage.setItem(storageHashKey, currentStorageHash);
33
33
  }
34
34
  catch (e) {
35
35
  log.error(constants_1.LOG_PREFIX + e);
@@ -42,7 +42,7 @@ function validateExpiration(options, settings, keys, currentTimestamp, isThereCa
42
42
  }
43
43
  // Clear on init
44
44
  if (options.clearOnInit) {
45
- var lastClearTimestamp = parseInt(localStorage.getItem(keys.buildLastClear()), 10);
45
+ var lastClearTimestamp = parseInt(storage.getItem(keys.buildLastClear()), 10);
46
46
  if ((0, lang_1.isNaNNumber)(lastClearTimestamp) || lastClearTimestamp < currentTimestamp - MILLIS_IN_A_DAY) {
47
47
  log.info(constants_1.LOG_PREFIX + 'clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
48
48
  return true;
@@ -57,24 +57,29 @@ function validateExpiration(options, settings, keys, currentTimestamp, isThereCa
57
57
  *
58
58
  * @returns `true` if cache is ready to be used, `false` otherwise (cache was cleared or there is no cache)
59
59
  */
60
- function validateCache(options, settings, keys, splits, rbSegments, segments, largeSegments) {
61
- var currentTimestamp = Date.now();
62
- var isThereCache = splits.getChangeNumber() > -1;
63
- if (validateExpiration(options, settings, keys, currentTimestamp, isThereCache)) {
64
- splits.clear();
65
- rbSegments.clear();
66
- segments.clear();
67
- largeSegments.clear();
68
- // Update last clear timestamp
69
- try {
70
- localStorage.setItem(keys.buildLastClear(), currentTimestamp + '');
71
- }
72
- catch (e) {
73
- settings.log.error(constants_1.LOG_PREFIX + e);
60
+ function validateCache(options, storage, settings, keys, splits, rbSegments, segments, largeSegments) {
61
+ return Promise.resolve(storage.load && storage.load()).then(function () {
62
+ var currentTimestamp = Date.now();
63
+ var isThereCache = splits.getChangeNumber() > -1;
64
+ if (validateExpiration(options, storage, settings, keys, currentTimestamp, isThereCache)) {
65
+ splits.clear();
66
+ rbSegments.clear();
67
+ segments.clear();
68
+ largeSegments.clear();
69
+ // Update last clear timestamp
70
+ try {
71
+ storage.setItem(keys.buildLastClear(), currentTimestamp + '');
72
+ }
73
+ catch (e) {
74
+ settings.log.error(constants_1.LOG_PREFIX + e);
75
+ }
76
+ // Persist clear
77
+ if (storage.save)
78
+ storage.save();
79
+ return false;
74
80
  }
75
- return false;
76
- }
77
- // Check if ready from cache
78
- return isThereCache;
81
+ // Check if ready from cache
82
+ return isThereCache;
83
+ });
79
84
  }
80
85
  exports.validateCache = validateCache;
@@ -45,10 +45,9 @@ function fromObjectUpdaterFactory(splitsParser, storage, readiness, settings) {
45
45
  readiness.splits.emit(constants_2.SDK_SPLITS_ARRIVED);
46
46
  if (startingUp) {
47
47
  startingUp = false;
48
- var isCacheLoaded_1 = storage.validateCache ? storage.validateCache() : false;
49
- Promise.resolve().then(function () {
48
+ Promise.resolve(storage.validateCache ? storage.validateCache() : false).then(function (isCacheLoaded) {
50
49
  // Emits SDK_READY_FROM_CACHE
51
- if (isCacheLoaded_1)
50
+ if (isCacheLoaded)
52
51
  readiness.splits.emit(constants_2.SDK_SPLITS_CACHE_LOADED);
53
52
  // Emits SDK_READY
54
53
  readiness.segments.emit(constants_2.SDK_SEGMENTS_ARRIVED);
@@ -34,6 +34,8 @@ function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmentsEvent
34
34
  shouldNotifyUpdate = segments.resetSegments(segmentsData.ms || {});
35
35
  shouldNotifyUpdate = largeSegments.resetSegments(segmentsData.ls || {}) || shouldNotifyUpdate;
36
36
  }
37
+ if (storage.save)
38
+ storage.save();
37
39
  // Notify update if required
38
40
  if ((0, AbstractSplitsCacheSync_1.usesSegmentsSync)(storage) && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
39
41
  readyOnAlreadyExistentState = false;
@@ -154,6 +154,8 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, splitFilt
154
154
  segments.registerSegments((0, sets_1.setToArray)(usedSegments))
155
155
  ]).then(function (_a) {
156
156
  var ffChanged = _a[0], rbsChanged = _a[1];
157
+ if (storage.save)
158
+ storage.save();
157
159
  if (splitsEventEmitter) {
158
160
  // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
159
161
  return Promise.resolve(!splitsEventEmitter.splitsArrived || ((ffChanged || rbsChanged) && (isClientSide || checkAllSegmentsExist(segments))))
@@ -69,35 +69,39 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
69
69
  */
70
70
  start: function () {
71
71
  running = true;
72
- if (startFirstTime) {
73
- var isCacheLoaded = storage.validateCache ? storage.validateCache() : false;
74
- if (isCacheLoaded)
75
- Promise.resolve().then(function () { readiness.splits.emit(constants_4.SDK_SPLITS_CACHE_LOADED); });
76
- }
77
- // start syncing splits and segments
78
- if (pollingManager) {
79
- // If synchronization is disabled pushManager and pollingManager should not start
80
- if (syncEnabled) {
81
- if (pushManager) {
82
- // Doesn't call `syncAll` when the syncManager is resuming
83
- if (startFirstTime) {
84
- pollingManager.syncAll();
72
+ // @TODO once event, impression and telemetry storages support persistence, call when `validateCache` promise is resolved
73
+ submitterManager.start(!(0, consent_1.isConsentGranted)(settings));
74
+ return Promise.resolve(storage.validateCache ? storage.validateCache() : false).then(function (isCacheLoaded) {
75
+ if (!running)
76
+ return;
77
+ if (startFirstTime) {
78
+ // Emits SDK_READY_FROM_CACHE
79
+ if (isCacheLoaded)
80
+ readiness.splits.emit(constants_4.SDK_SPLITS_CACHE_LOADED);
81
+ }
82
+ // start syncing splits and segments
83
+ if (pollingManager) {
84
+ // If synchronization is disabled pushManager and pollingManager should not start
85
+ if (syncEnabled) {
86
+ if (pushManager) {
87
+ // Doesn't call `syncAll` when the syncManager is resuming
88
+ if (startFirstTime) {
89
+ pollingManager.syncAll();
90
+ }
91
+ pushManager.start();
92
+ }
93
+ else {
94
+ pollingManager.start();
85
95
  }
86
- pushManager.start();
87
96
  }
88
97
  else {
89
- pollingManager.start();
90
- }
91
- }
92
- else {
93
- if (startFirstTime) {
94
- pollingManager.syncAll();
98
+ if (startFirstTime) {
99
+ pollingManager.syncAll();
100
+ }
95
101
  }
96
102
  }
97
- }
98
- // start periodic data recording (events, impressions, telemetry).
99
- submitterManager.start(!(0, consent_1.isConsentGranted)(settings));
100
- startFirstTime = false;
103
+ startFirstTime = false;
104
+ });
101
105
  },
102
106
  /**
103
107
  * Method used to stop/pause the syncManager.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isLocalStorageAvailable = void 0;
3
+ exports.isWebStorage = exports.isValidStorageWrapper = exports.isLocalStorageAvailable = void 0;
4
4
  /* eslint-disable no-undef */
5
5
  function isLocalStorageAvailable() {
6
6
  var mod = '__SPLITSOFTWARE__';
@@ -14,3 +14,24 @@ function isLocalStorageAvailable() {
14
14
  }
15
15
  }
16
16
  exports.isLocalStorageAvailable = isLocalStorageAvailable;
17
+ function isValidStorageWrapper(wrapper) {
18
+ return wrapper !== null &&
19
+ typeof wrapper === 'object' &&
20
+ typeof wrapper.setItem === 'function' &&
21
+ typeof wrapper.getItem === 'function' &&
22
+ typeof wrapper.removeItem === 'function';
23
+ }
24
+ exports.isValidStorageWrapper = isValidStorageWrapper;
25
+ function isWebStorage(wrapper) {
26
+ if (typeof wrapper.length === 'number') {
27
+ try {
28
+ wrapper.key(0);
29
+ return true;
30
+ }
31
+ catch (e) {
32
+ return false;
33
+ }
34
+ }
35
+ return false;
36
+ }
37
+ exports.isWebStorage = isWebStorage;
@@ -6,7 +6,7 @@ var constants_1 = require("../../../logger/constants");
6
6
  var constants_2 = require("../../../utils/constants");
7
7
  function __InLocalStorageMockFactory(params) {
8
8
  var result = (0, InMemoryStorageCS_1.InMemoryStorageCSFactory)(params);
9
- result.validateCache = function () { return true; }; // to emit SDK_READY_FROM_CACHE
9
+ result.validateCache = function () { return Promise.resolve(true); }; // to emit SDK_READY_FROM_CACHE
10
10
  return result;
11
11
  }
12
12
  exports.__InLocalStorageMockFactory = __InLocalStorageMockFactory;
@@ -9,7 +9,7 @@ export var codesInfo = codesWarn.concat([
9
9
  [c.IMPRESSION, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Feature flag: %s. Key: %s. Evaluation: %s. Label: %s'],
10
10
  [c.IMPRESSION_QUEUEING, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Queueing corresponding impression.'],
11
11
  [c.NEW_SHARED_CLIENT, 'New shared client instance created.'],
12
- [c.NEW_FACTORY, 'New Split SDK instance created.'],
12
+ [c.NEW_FACTORY, 'New Split SDK instance created. %s'],
13
13
  [c.EVENTS_TRACKER_SUCCESS, c.LOG_PREFIX_EVENTS_TRACKER + 'Successfully queued %s'],
14
14
  [c.IMPRESSIONS_TRACKER_SUCCESS, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Successfully stored %s impression(s).'],
15
15
  [c.USER_CONSENT_UPDATED, 'UserConsent: consent status changed from %s to %s.'],
@@ -89,7 +89,7 @@ export function sdkFactory(params) {
89
89
  initCallbacks.forEach(function (cb) { return cb(); });
90
90
  initCallbacks.length = 0;
91
91
  }
92
- log.info(NEW_FACTORY);
92
+ log.info(NEW_FACTORY, [settings.version]);
93
93
  // @ts-ignore
94
94
  return objectAssign({
95
95
  // Split evaluation and event tracking engine
@@ -4,19 +4,20 @@ import { AbstractMySegmentsCacheSync } from '../AbstractMySegmentsCacheSync';
4
4
  import { LOG_PREFIX, DEFINED } from './constants';
5
5
  var MySegmentsCacheInLocal = /** @class */ (function (_super) {
6
6
  __extends(MySegmentsCacheInLocal, _super);
7
- function MySegmentsCacheInLocal(log, keys) {
7
+ function MySegmentsCacheInLocal(log, keys, storage) {
8
8
  var _this = _super.call(this) || this;
9
9
  _this.log = log;
10
10
  _this.keys = keys;
11
+ _this.storage = storage;
11
12
  return _this;
12
13
  // There is not need to flush segments cache like splits cache, since resetSegments receives the up-to-date list of active segments
13
14
  }
14
15
  MySegmentsCacheInLocal.prototype.addSegment = function (name) {
15
16
  var segmentKey = this.keys.buildSegmentNameKey(name);
16
17
  try {
17
- if (localStorage.getItem(segmentKey) === DEFINED)
18
+ if (this.storage.getItem(segmentKey) === DEFINED)
18
19
  return false;
19
- localStorage.setItem(segmentKey, DEFINED);
20
+ this.storage.setItem(segmentKey, DEFINED);
20
21
  return true;
21
22
  }
22
23
  catch (e) {
@@ -27,9 +28,9 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
27
28
  MySegmentsCacheInLocal.prototype.removeSegment = function (name) {
28
29
  var segmentKey = this.keys.buildSegmentNameKey(name);
29
30
  try {
30
- if (localStorage.getItem(segmentKey) !== DEFINED)
31
+ if (this.storage.getItem(segmentKey) !== DEFINED)
31
32
  return false;
32
- localStorage.removeItem(segmentKey);
33
+ this.storage.removeItem(segmentKey);
33
34
  return true;
34
35
  }
35
36
  catch (e) {
@@ -38,17 +39,16 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
38
39
  }
39
40
  };
40
41
  MySegmentsCacheInLocal.prototype.isInSegment = function (name) {
41
- return localStorage.getItem(this.keys.buildSegmentNameKey(name)) === DEFINED;
42
+ return this.storage.getItem(this.keys.buildSegmentNameKey(name)) === DEFINED;
42
43
  };
43
44
  MySegmentsCacheInLocal.prototype.getRegisteredSegments = function () {
44
- var _this = this;
45
- // Scan current values from localStorage
46
- return Object.keys(localStorage).reduce(function (accum, key) {
47
- var segmentName = _this.keys.extractSegmentName(key);
45
+ var registeredSegments = [];
46
+ for (var i = 0, len = this.storage.length; i < len; i++) {
47
+ var segmentName = this.keys.extractSegmentName(this.storage.key(i));
48
48
  if (segmentName)
49
- accum.push(segmentName);
50
- return accum;
51
- }, []);
49
+ registeredSegments.push(segmentName);
50
+ }
51
+ return registeredSegments;
52
52
  };
53
53
  MySegmentsCacheInLocal.prototype.getKeysCount = function () {
54
54
  return 1;
@@ -56,9 +56,9 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
56
56
  MySegmentsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
57
57
  try {
58
58
  if (changeNumber)
59
- localStorage.setItem(this.keys.buildTillKey(), changeNumber + '');
59
+ this.storage.setItem(this.keys.buildTillKey(), changeNumber + '');
60
60
  else
61
- localStorage.removeItem(this.keys.buildTillKey());
61
+ this.storage.removeItem(this.keys.buildTillKey());
62
62
  }
63
63
  catch (e) {
64
64
  this.log.error(e);
@@ -66,7 +66,7 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
66
66
  };
67
67
  MySegmentsCacheInLocal.prototype.getChangeNumber = function () {
68
68
  var n = -1;
69
- var value = localStorage.getItem(this.keys.buildTillKey());
69
+ var value = this.storage.getItem(this.keys.buildTillKey());
70
70
  if (value !== null) {
71
71
  value = parseInt(value, 10);
72
72
  return isNaNNumber(value) ? n : value;
@@ -3,14 +3,15 @@ import { setToArray } from '../../utils/lang/sets';
3
3
  import { usesSegments } from '../AbstractSplitsCacheSync';
4
4
  import { LOG_PREFIX } from './constants';
5
5
  var RBSegmentsCacheInLocal = /** @class */ (function () {
6
- function RBSegmentsCacheInLocal(settings, keys) {
6
+ function RBSegmentsCacheInLocal(settings, keys, storage) {
7
7
  this.keys = keys;
8
8
  this.log = settings.log;
9
+ this.storage = storage;
9
10
  }
10
11
  RBSegmentsCacheInLocal.prototype.clear = function () {
11
12
  var _this = this;
12
13
  this.getNames().forEach(function (name) { return _this.remove(name); });
13
- localStorage.removeItem(this.keys.buildRBSegmentsTillKey());
14
+ this.storage.removeItem(this.keys.buildRBSegmentsTillKey());
14
15
  };
15
16
  RBSegmentsCacheInLocal.prototype.update = function (toAdd, toRemove, changeNumber) {
16
17
  var _this = this;
@@ -20,8 +21,8 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
20
21
  };
21
22
  RBSegmentsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
22
23
  try {
23
- localStorage.setItem(this.keys.buildRBSegmentsTillKey(), changeNumber + '');
24
- localStorage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
24
+ this.storage.setItem(this.keys.buildRBSegmentsTillKey(), changeNumber + '');
25
+ this.storage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
25
26
  }
26
27
  catch (e) {
27
28
  this.log.error(LOG_PREFIX + e);
@@ -29,20 +30,19 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
29
30
  };
30
31
  RBSegmentsCacheInLocal.prototype.updateSegmentCount = function (diff) {
31
32
  var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
32
- var count = toNumber(localStorage.getItem(segmentsCountKey)) + diff;
33
- // @ts-expect-error
33
+ var count = toNumber(this.storage.getItem(segmentsCountKey)) + diff;
34
34
  if (count > 0)
35
- localStorage.setItem(segmentsCountKey, count);
35
+ this.storage.setItem(segmentsCountKey, count + '');
36
36
  else
37
- localStorage.removeItem(segmentsCountKey);
37
+ this.storage.removeItem(segmentsCountKey);
38
38
  };
39
39
  RBSegmentsCacheInLocal.prototype.add = function (rbSegment) {
40
40
  try {
41
41
  var name_1 = rbSegment.name;
42
42
  var rbSegmentKey = this.keys.buildRBSegmentKey(name_1);
43
- var rbSegmentFromLocalStorage = localStorage.getItem(rbSegmentKey);
44
- var previous = rbSegmentFromLocalStorage ? JSON.parse(rbSegmentFromLocalStorage) : null;
45
- localStorage.setItem(rbSegmentKey, JSON.stringify(rbSegment));
43
+ var rbSegmentFromStorage = this.storage.getItem(rbSegmentKey);
44
+ var previous = rbSegmentFromStorage ? JSON.parse(rbSegmentFromStorage) : null;
45
+ this.storage.setItem(rbSegmentKey, JSON.stringify(rbSegment));
46
46
  var usesSegmentsDiff = 0;
47
47
  if (previous && usesSegments(previous))
48
48
  usesSegmentsDiff--;
@@ -62,7 +62,7 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
62
62
  var rbSegment = this.get(name);
63
63
  if (!rbSegment)
64
64
  return false;
65
- localStorage.removeItem(this.keys.buildRBSegmentKey(name));
65
+ this.storage.removeItem(this.keys.buildRBSegmentKey(name));
66
66
  if (usesSegments(rbSegment))
67
67
  this.updateSegmentCount(-1);
68
68
  return true;
@@ -73,11 +73,11 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
73
73
  }
74
74
  };
75
75
  RBSegmentsCacheInLocal.prototype.getNames = function () {
76
- var len = localStorage.length;
76
+ var len = this.storage.length;
77
77
  var accum = [];
78
78
  var cur = 0;
79
79
  while (cur < len) {
80
- var key = localStorage.key(cur);
80
+ var key = this.storage.key(cur);
81
81
  if (key != null && this.keys.isRBSegmentKey(key))
82
82
  accum.push(this.keys.extractKey(key));
83
83
  cur++;
@@ -85,7 +85,7 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
85
85
  return accum;
86
86
  };
87
87
  RBSegmentsCacheInLocal.prototype.get = function (name) {
88
- var item = localStorage.getItem(this.keys.buildRBSegmentKey(name));
88
+ var item = this.storage.getItem(this.keys.buildRBSegmentKey(name));
89
89
  return item && JSON.parse(item);
90
90
  };
91
91
  RBSegmentsCacheInLocal.prototype.getAll = function () {
@@ -99,7 +99,7 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
99
99
  };
100
100
  RBSegmentsCacheInLocal.prototype.getChangeNumber = function () {
101
101
  var n = -1;
102
- var value = localStorage.getItem(this.keys.buildRBSegmentsTillKey());
102
+ var value = this.storage.getItem(this.keys.buildRBSegmentsTillKey());
103
103
  if (value !== null) {
104
104
  value = parseInt(value, 10);
105
105
  return isNaNNumber(value) ? n : value;
@@ -107,7 +107,7 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
107
107
  return n;
108
108
  };
109
109
  RBSegmentsCacheInLocal.prototype.usesSegments = function () {
110
- var storedCount = localStorage.getItem(this.keys.buildSplitsWithSegmentCountKey());
110
+ var storedCount = this.storage.getItem(this.keys.buildSplitsWithSegmentCountKey());
111
111
  var splitsWithSegmentsCount = storedCount === null ? 0 : toNumber(storedCount);
112
112
  return isFiniteNumber(splitsWithSegmentsCount) ?
113
113
  splitsWithSegmentsCount > 0 :
@@ -3,25 +3,22 @@ import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSyn
3
3
  import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
4
4
  import { LOG_PREFIX } from './constants';
5
5
  import { setToArray } from '../../utils/lang/sets';
6
- /**
7
- * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
8
- */
9
6
  var SplitsCacheInLocal = /** @class */ (function (_super) {
10
7
  __extends(SplitsCacheInLocal, _super);
11
- function SplitsCacheInLocal(settings, keys) {
8
+ function SplitsCacheInLocal(settings, keys, storage) {
12
9
  var _this = _super.call(this) || this;
13
10
  _this.keys = keys;
14
11
  _this.log = settings.log;
15
12
  _this.flagSetsFilter = settings.sync.__splitFiltersValidation.groupedFilters.bySet;
13
+ _this.storage = storage;
16
14
  return _this;
17
15
  }
18
16
  SplitsCacheInLocal.prototype._decrementCount = function (key) {
19
- var count = toNumber(localStorage.getItem(key)) - 1;
20
- // @ts-expect-error
17
+ var count = toNumber(this.storage.getItem(key)) - 1;
21
18
  if (count > 0)
22
- localStorage.setItem(key, count);
19
+ this.storage.setItem(key, count + '');
23
20
  else
24
- localStorage.removeItem(key);
21
+ this.storage.removeItem(key);
25
22
  };
26
23
  SplitsCacheInLocal.prototype._decrementCounts = function (split) {
27
24
  try {
@@ -39,12 +36,10 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
39
36
  SplitsCacheInLocal.prototype._incrementCounts = function (split) {
40
37
  try {
41
38
  var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
42
- // @ts-expect-error
43
- localStorage.setItem(ttKey, toNumber(localStorage.getItem(ttKey)) + 1);
39
+ this.storage.setItem(ttKey, (toNumber(this.storage.getItem(ttKey)) + 1) + '');
44
40
  if (usesSegments(split)) {
45
41
  var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
46
- // @ts-expect-error
47
- localStorage.setItem(segmentsCountKey, toNumber(localStorage.getItem(segmentsCountKey)) + 1);
42
+ this.storage.setItem(segmentsCountKey, (toNumber(this.storage.getItem(segmentsCountKey)) + 1) + '');
48
43
  }
49
44
  }
50
45
  catch (e) {
@@ -56,17 +51,18 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
56
51
  * We cannot simply call `localStorage.clear()` since that implies removing user items from the storage.
57
52
  */
58
53
  SplitsCacheInLocal.prototype.clear = function () {
54
+ var _this = this;
59
55
  // collect item keys
60
- var len = localStorage.length;
56
+ var len = this.storage.length;
61
57
  var accum = [];
62
58
  for (var cur = 0; cur < len; cur++) {
63
- var key = localStorage.key(cur);
59
+ var key = this.storage.key(cur);
64
60
  if (key != null && this.keys.isSplitsCacheKey(key))
65
61
  accum.push(key);
66
62
  }
67
63
  // remove items
68
64
  accum.forEach(function (key) {
69
- localStorage.removeItem(key);
65
+ _this.storage.removeItem(key);
70
66
  });
71
67
  this.hasSync = false;
72
68
  };
@@ -74,13 +70,13 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
74
70
  try {
75
71
  var name_1 = split.name;
76
72
  var splitKey = this.keys.buildSplitKey(name_1);
77
- var splitFromLocalStorage = localStorage.getItem(splitKey);
78
- var previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
73
+ var splitFromStorage = this.storage.getItem(splitKey);
74
+ var previousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : null;
79
75
  if (previousSplit) {
80
76
  this._decrementCounts(previousSplit);
81
77
  this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
82
78
  }
83
- localStorage.setItem(splitKey, JSON.stringify(split));
79
+ this.storage.setItem(splitKey, JSON.stringify(split));
84
80
  this._incrementCounts(split);
85
81
  this.addToFlagSets(split);
86
82
  return true;
@@ -95,7 +91,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
95
91
  var split = this.getSplit(name);
96
92
  if (!split)
97
93
  return false;
98
- localStorage.removeItem(this.keys.buildSplitKey(name));
94
+ this.storage.removeItem(this.keys.buildSplitKey(name));
99
95
  this._decrementCounts(split);
100
96
  this.removeFromFlagSets(split.name, split.sets);
101
97
  return true;
@@ -106,14 +102,14 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
106
102
  }
107
103
  };
108
104
  SplitsCacheInLocal.prototype.getSplit = function (name) {
109
- var item = localStorage.getItem(this.keys.buildSplitKey(name));
105
+ var item = this.storage.getItem(this.keys.buildSplitKey(name));
110
106
  return item && JSON.parse(item);
111
107
  };
112
108
  SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
113
109
  try {
114
- localStorage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
110
+ this.storage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
115
111
  // update "last updated" timestamp with current time
116
- localStorage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
112
+ this.storage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
117
113
  this.hasSync = true;
118
114
  return true;
119
115
  }
@@ -124,7 +120,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
124
120
  };
125
121
  SplitsCacheInLocal.prototype.getChangeNumber = function () {
126
122
  var n = -1;
127
- var value = localStorage.getItem(this.keys.buildSplitsTillKey());
123
+ var value = this.storage.getItem(this.keys.buildSplitsTillKey());
128
124
  if (value !== null) {
129
125
  value = parseInt(value, 10);
130
126
  return isNaNNumber(value) ? n : value;
@@ -132,11 +128,11 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
132
128
  return n;
133
129
  };
134
130
  SplitsCacheInLocal.prototype.getSplitNames = function () {
135
- var len = localStorage.length;
131
+ var len = this.storage.length;
136
132
  var accum = [];
137
133
  var cur = 0;
138
134
  while (cur < len) {
139
- var key = localStorage.key(cur);
135
+ var key = this.storage.key(cur);
140
136
  if (key != null && this.keys.isSplitKey(key))
141
137
  accum.push(this.keys.extractKey(key));
142
138
  cur++;
@@ -144,14 +140,14 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
144
140
  return accum;
145
141
  };
146
142
  SplitsCacheInLocal.prototype.trafficTypeExists = function (trafficType) {
147
- var ttCount = toNumber(localStorage.getItem(this.keys.buildTrafficTypeKey(trafficType)));
143
+ var ttCount = toNumber(this.storage.getItem(this.keys.buildTrafficTypeKey(trafficType)));
148
144
  return isFiniteNumber(ttCount) && ttCount > 0;
149
145
  };
150
146
  SplitsCacheInLocal.prototype.usesSegments = function () {
151
147
  // If cache hasn't been synchronized with the cloud, assume we need them.
152
148
  if (!this.hasSync)
153
149
  return true;
154
- var storedCount = localStorage.getItem(this.keys.buildSplitsWithSegmentCountKey());
150
+ var storedCount = this.storage.getItem(this.keys.buildSplitsWithSegmentCountKey());
155
151
  var splitsWithSegmentsCount = storedCount === null ? 0 : toNumber(storedCount);
156
152
  return isFiniteNumber(splitsWithSegmentsCount) ?
157
153
  splitsWithSegmentsCount > 0 :
@@ -161,8 +157,8 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
161
157
  var _this = this;
162
158
  return flagSets.map(function (flagSet) {
163
159
  var flagSetKey = _this.keys.buildFlagSetKey(flagSet);
164
- var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
165
- return new Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
160
+ var flagSetFromStorage = _this.storage.getItem(flagSetKey);
161
+ return new Set(flagSetFromStorage ? JSON.parse(flagSetFromStorage) : []);
166
162
  });
167
163
  };
168
164
  SplitsCacheInLocal.prototype.addToFlagSets = function (featureFlag) {
@@ -173,10 +169,10 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
173
169
  if (_this.flagSetsFilter.length > 0 && !_this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === featureFlagSet; }))
174
170
  return;
175
171
  var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
176
- var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
177
- var flagSetCache = new Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
172
+ var flagSetFromStorage = _this.storage.getItem(flagSetKey);
173
+ var flagSetCache = new Set(flagSetFromStorage ? JSON.parse(flagSetFromStorage) : []);
178
174
  flagSetCache.add(featureFlag.name);
179
- localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
175
+ _this.storage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
180
176
  });
181
177
  };
182
178
  SplitsCacheInLocal.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
@@ -189,16 +185,16 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
189
185
  };
190
186
  SplitsCacheInLocal.prototype.removeNames = function (flagSetName, featureFlagName) {
191
187
  var flagSetKey = this.keys.buildFlagSetKey(flagSetName);
192
- var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
193
- if (!flagSetFromLocalStorage)
188
+ var flagSetFromStorage = this.storage.getItem(flagSetKey);
189
+ if (!flagSetFromStorage)
194
190
  return;
195
- var flagSetCache = new Set(JSON.parse(flagSetFromLocalStorage));
191
+ var flagSetCache = new Set(JSON.parse(flagSetFromStorage));
196
192
  flagSetCache.delete(featureFlagName);
197
193
  if (flagSetCache.size === 0) {
198
- localStorage.removeItem(flagSetKey);
194
+ this.storage.removeItem(flagSetKey);
199
195
  return;
200
196
  }
201
- localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
197
+ this.storage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
202
198
  };
203
199
  return SplitsCacheInLocal;
204
200
  }(AbstractSplitsCacheSync));