@splitsoftware/splitio-commons 2.4.2-rc.2 → 2.5.0-rc.0

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 (51) hide show
  1. package/CHANGES.txt +2 -10
  2. package/cjs/storages/AbstractMySegmentsCacheSync.js +23 -31
  3. package/cjs/storages/AbstractSplitsCacheSync.js +2 -3
  4. package/cjs/storages/dataLoader.js +102 -43
  5. package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
  6. package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +23 -20
  7. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +37 -33
  8. package/cjs/storages/inLocalStorage/index.js +13 -28
  9. package/cjs/storages/inLocalStorage/validateCache.js +23 -25
  10. package/cjs/storages/inMemory/InMemoryStorageCS.js +32 -14
  11. package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +4 -0
  12. package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
  13. package/cjs/sync/syncManagerOnline.js +24 -28
  14. package/cjs/utils/env/isLocalStorageAvailable.js +5 -28
  15. package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
  16. package/esm/storages/AbstractMySegmentsCacheSync.js +23 -31
  17. package/esm/storages/AbstractSplitsCacheSync.js +2 -3
  18. package/esm/storages/dataLoader.js +99 -41
  19. package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
  20. package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +23 -20
  21. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +37 -33
  22. package/esm/storages/inLocalStorage/index.js +14 -29
  23. package/esm/storages/inLocalStorage/validateCache.js +23 -25
  24. package/esm/storages/inMemory/InMemoryStorageCS.js +32 -14
  25. package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +4 -0
  26. package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
  27. package/esm/sync/syncManagerOnline.js +24 -28
  28. package/esm/utils/env/isLocalStorageAvailable.js +3 -24
  29. package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
  30. package/package.json +1 -1
  31. package/src/sdkFactory/index.ts +3 -2
  32. package/src/storages/AbstractMySegmentsCacheSync.ts +20 -26
  33. package/src/storages/AbstractSplitsCacheSync.ts +2 -3
  34. package/src/storages/dataLoader.ts +107 -49
  35. package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +17 -18
  36. package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +24 -22
  37. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +37 -34
  38. package/src/storages/inLocalStorage/index.ts +16 -33
  39. package/src/storages/inLocalStorage/validateCache.ts +23 -26
  40. package/src/storages/inMemory/InMemoryStorageCS.ts +37 -14
  41. package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +4 -0
  42. package/src/storages/types.ts +6 -20
  43. package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +2 -1
  44. package/src/sync/syncManagerOnline.ts +22 -27
  45. package/src/types.ts +0 -35
  46. package/src/utils/env/isLocalStorageAvailable.ts +3 -24
  47. package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
  48. package/types/splitio.d.ts +46 -27
  49. package/cjs/storages/inLocalStorage/storageAdapter.js +0 -48
  50. package/esm/storages/inLocalStorage/storageAdapter.js +0 -44
  51. package/src/storages/inLocalStorage/storageAdapter.ts +0 -50
@@ -6,22 +6,25 @@ var AbstractSplitsCacheSync_1 = require("../AbstractSplitsCacheSync");
6
6
  var lang_1 = require("../../utils/lang");
7
7
  var constants_1 = require("./constants");
8
8
  var sets_1 = require("../../utils/lang/sets");
9
+ /**
10
+ * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
11
+ */
9
12
  var SplitsCacheInLocal = /** @class */ (function (_super) {
10
13
  (0, tslib_1.__extends)(SplitsCacheInLocal, _super);
11
- function SplitsCacheInLocal(settings, keys, storage) {
14
+ function SplitsCacheInLocal(settings, keys) {
12
15
  var _this = _super.call(this) || this;
13
16
  _this.keys = keys;
14
17
  _this.log = settings.log;
15
18
  _this.flagSetsFilter = settings.sync.__splitFiltersValidation.groupedFilters.bySet;
16
- _this.storage = storage;
17
19
  return _this;
18
20
  }
19
21
  SplitsCacheInLocal.prototype._decrementCount = function (key) {
20
- var count = (0, lang_1.toNumber)(this.storage.getItem(key)) - 1;
22
+ var count = (0, lang_1.toNumber)(localStorage.getItem(key)) - 1;
23
+ // @ts-expect-error
21
24
  if (count > 0)
22
- this.storage.setItem(key, count + '');
25
+ localStorage.setItem(key, count);
23
26
  else
24
- this.storage.removeItem(key);
27
+ localStorage.removeItem(key);
25
28
  };
26
29
  SplitsCacheInLocal.prototype._decrementCounts = function (split) {
27
30
  try {
@@ -39,10 +42,12 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
39
42
  SplitsCacheInLocal.prototype._incrementCounts = function (split) {
40
43
  try {
41
44
  var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
42
- this.storage.setItem(ttKey, ((0, lang_1.toNumber)(this.storage.getItem(ttKey)) + 1) + '');
45
+ // @ts-expect-error
46
+ localStorage.setItem(ttKey, (0, lang_1.toNumber)(localStorage.getItem(ttKey)) + 1);
43
47
  if ((0, AbstractSplitsCacheSync_1.usesSegments)(split)) {
44
48
  var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
45
- this.storage.setItem(segmentsCountKey, ((0, lang_1.toNumber)(this.storage.getItem(segmentsCountKey)) + 1) + '');
49
+ // @ts-expect-error
50
+ localStorage.setItem(segmentsCountKey, (0, lang_1.toNumber)(localStorage.getItem(segmentsCountKey)) + 1);
46
51
  }
47
52
  }
48
53
  catch (e) {
@@ -54,18 +59,17 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
54
59
  * We cannot simply call `localStorage.clear()` since that implies removing user items from the storage.
55
60
  */
56
61
  SplitsCacheInLocal.prototype.clear = function () {
57
- var _this = this;
58
62
  // collect item keys
59
- var len = this.storage.length;
63
+ var len = localStorage.length;
60
64
  var accum = [];
61
65
  for (var cur = 0; cur < len; cur++) {
62
- var key = this.storage.key(cur);
66
+ var key = localStorage.key(cur);
63
67
  if (key != null && this.keys.isSplitsCacheKey(key))
64
68
  accum.push(key);
65
69
  }
66
70
  // remove items
67
71
  accum.forEach(function (key) {
68
- _this.storage.removeItem(key);
72
+ localStorage.removeItem(key);
69
73
  });
70
74
  this.hasSync = false;
71
75
  };
@@ -73,13 +77,13 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
73
77
  try {
74
78
  var name_1 = split.name;
75
79
  var splitKey = this.keys.buildSplitKey(name_1);
76
- var splitFromStorage = this.storage.getItem(splitKey);
77
- var previousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : null;
80
+ var splitFromLocalStorage = localStorage.getItem(splitKey);
81
+ var previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
78
82
  if (previousSplit) {
79
83
  this._decrementCounts(previousSplit);
80
84
  this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
81
85
  }
82
- this.storage.setItem(splitKey, JSON.stringify(split));
86
+ localStorage.setItem(splitKey, JSON.stringify(split));
83
87
  this._incrementCounts(split);
84
88
  this.addToFlagSets(split);
85
89
  return true;
@@ -94,7 +98,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
94
98
  var split = this.getSplit(name);
95
99
  if (!split)
96
100
  return false;
97
- this.storage.removeItem(this.keys.buildSplitKey(name));
101
+ localStorage.removeItem(this.keys.buildSplitKey(name));
98
102
  this._decrementCounts(split);
99
103
  this.removeFromFlagSets(split.name, split.sets);
100
104
  return true;
@@ -105,14 +109,14 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
105
109
  }
106
110
  };
107
111
  SplitsCacheInLocal.prototype.getSplit = function (name) {
108
- var item = this.storage.getItem(this.keys.buildSplitKey(name));
112
+ var item = localStorage.getItem(this.keys.buildSplitKey(name));
109
113
  return item && JSON.parse(item);
110
114
  };
111
115
  SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
112
116
  try {
113
- this.storage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
117
+ localStorage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
114
118
  // update "last updated" timestamp with current time
115
- this.storage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
119
+ localStorage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
116
120
  this.hasSync = true;
117
121
  return true;
118
122
  }
@@ -123,7 +127,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
123
127
  };
124
128
  SplitsCacheInLocal.prototype.getChangeNumber = function () {
125
129
  var n = -1;
126
- var value = this.storage.getItem(this.keys.buildSplitsTillKey());
130
+ var value = localStorage.getItem(this.keys.buildSplitsTillKey());
127
131
  if (value !== null) {
128
132
  value = parseInt(value, 10);
129
133
  return (0, lang_1.isNaNNumber)(value) ? n : value;
@@ -131,11 +135,11 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
131
135
  return n;
132
136
  };
133
137
  SplitsCacheInLocal.prototype.getSplitNames = function () {
134
- var len = this.storage.length;
138
+ var len = localStorage.length;
135
139
  var accum = [];
136
140
  var cur = 0;
137
141
  while (cur < len) {
138
- var key = this.storage.key(cur);
142
+ var key = localStorage.key(cur);
139
143
  if (key != null && this.keys.isSplitKey(key))
140
144
  accum.push(this.keys.extractKey(key));
141
145
  cur++;
@@ -143,14 +147,14 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
143
147
  return accum;
144
148
  };
145
149
  SplitsCacheInLocal.prototype.trafficTypeExists = function (trafficType) {
146
- var ttCount = (0, lang_1.toNumber)(this.storage.getItem(this.keys.buildTrafficTypeKey(trafficType)));
150
+ var ttCount = (0, lang_1.toNumber)(localStorage.getItem(this.keys.buildTrafficTypeKey(trafficType)));
147
151
  return (0, lang_1.isFiniteNumber)(ttCount) && ttCount > 0;
148
152
  };
149
153
  SplitsCacheInLocal.prototype.usesSegments = function () {
150
154
  // If cache hasn't been synchronized with the cloud, assume we need them.
151
155
  if (!this.hasSync)
152
156
  return true;
153
- var storedCount = this.storage.getItem(this.keys.buildSplitsWithSegmentCountKey());
157
+ var storedCount = localStorage.getItem(this.keys.buildSplitsWithSegmentCountKey());
154
158
  var splitsWithSegmentsCount = storedCount === null ? 0 : (0, lang_1.toNumber)(storedCount);
155
159
  return (0, lang_1.isFiniteNumber)(splitsWithSegmentsCount) ?
156
160
  splitsWithSegmentsCount > 0 :
@@ -160,8 +164,8 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
160
164
  var _this = this;
161
165
  return flagSets.map(function (flagSet) {
162
166
  var flagSetKey = _this.keys.buildFlagSetKey(flagSet);
163
- var flagSetFromStorage = _this.storage.getItem(flagSetKey);
164
- return new Set(flagSetFromStorage ? JSON.parse(flagSetFromStorage) : []);
167
+ var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
168
+ return new Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
165
169
  });
166
170
  };
167
171
  SplitsCacheInLocal.prototype.addToFlagSets = function (featureFlag) {
@@ -172,10 +176,10 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
172
176
  if (_this.flagSetsFilter.length > 0 && !_this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === featureFlagSet; }))
173
177
  return;
174
178
  var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
175
- var flagSetFromStorage = _this.storage.getItem(flagSetKey);
176
- var flagSetCache = new Set(flagSetFromStorage ? JSON.parse(flagSetFromStorage) : []);
179
+ var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
180
+ var flagSetCache = new Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
177
181
  flagSetCache.add(featureFlag.name);
178
- _this.storage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
182
+ localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
179
183
  });
180
184
  };
181
185
  SplitsCacheInLocal.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
@@ -188,16 +192,16 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
188
192
  };
189
193
  SplitsCacheInLocal.prototype.removeNames = function (flagSetName, featureFlagName) {
190
194
  var flagSetKey = this.keys.buildFlagSetKey(flagSetName);
191
- var flagSetFromStorage = this.storage.getItem(flagSetKey);
192
- if (!flagSetFromStorage)
195
+ var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
196
+ if (!flagSetFromLocalStorage)
193
197
  return;
194
- var flagSetCache = new Set(JSON.parse(flagSetFromStorage));
198
+ var flagSetCache = new Set(JSON.parse(flagSetFromLocalStorage));
195
199
  flagSetCache.delete(featureFlagName);
196
200
  if (flagSetCache.size === 0) {
197
- this.storage.removeItem(flagSetKey);
201
+ localStorage.removeItem(flagSetKey);
198
202
  return;
199
203
  }
200
- this.storage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
204
+ localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
201
205
  };
202
206
  return SplitsCacheInLocal;
203
207
  }(AbstractSplitsCacheSync_1.AbstractSplitsCacheSync));
@@ -17,20 +17,6 @@ var TelemetryCacheInMemory_1 = require("../inMemory/TelemetryCacheInMemory");
17
17
  var UniqueKeysCacheInMemoryCS_1 = require("../inMemory/UniqueKeysCacheInMemoryCS");
18
18
  var key_1 = require("../../utils/key");
19
19
  var validateCache_1 = require("./validateCache");
20
- var storageAdapter_1 = require("./storageAdapter");
21
- function validateStorage(log, prefix, wrapper) {
22
- if (wrapper) {
23
- if ((0, isLocalStorageAvailable_1.isValidStorageWrapper)(wrapper)) {
24
- return (0, isLocalStorageAvailable_1.isWebStorage)(wrapper) ?
25
- wrapper : // localStorage and sessionStorage don't need adapter
26
- (0, storageAdapter_1.storageAdapter)(log, prefix, wrapper);
27
- }
28
- log.warn(constants_1.LOG_PREFIX + 'Invalid storage provided. Falling back to LocalStorage API');
29
- }
30
- if ((0, isLocalStorageAvailable_1.isLocalStorageAvailable)())
31
- return localStorage;
32
- log.warn(constants_1.LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
33
- }
34
20
  /**
35
21
  * InLocal storage factory for standalone client-side SplitFactory
36
22
  */
@@ -38,17 +24,18 @@ function InLocalStorage(options) {
38
24
  if (options === void 0) { options = {}; }
39
25
  var prefix = (0, KeyBuilder_1.validatePrefix)(options.prefix);
40
26
  function InLocalStorageCSFactory(params) {
41
- var settings = params.settings, _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize;
42
- var storage = validateStorage(log, prefix, options.wrapper);
43
- if (!storage)
27
+ // Fallback to InMemoryStorage if LocalStorage API is not available
28
+ if (!(0, isLocalStorageAvailable_1.isLocalStorageAvailable)()) {
29
+ params.settings.log.warn(constants_1.LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
44
30
  return (0, InMemoryStorageCS_1.InMemoryStorageCSFactory)(params);
31
+ }
32
+ var settings = params.settings, _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize;
45
33
  var matchingKey = (0, key_1.getMatching)(settings.core.key);
46
34
  var keys = new KeyBuilderCS_1.KeyBuilderCS(prefix, matchingKey);
47
- var splits = new SplitsCacheInLocal_1.SplitsCacheInLocal(settings, keys, storage);
48
- var rbSegments = new RBSegmentsCacheInLocal_1.RBSegmentsCacheInLocal(settings, keys, storage);
49
- var segments = new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, keys, storage);
50
- var largeSegments = new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, (0, KeyBuilderCS_1.myLargeSegmentsKeyBuilder)(prefix, matchingKey), storage);
51
- var validateCachePromise;
35
+ var splits = new SplitsCacheInLocal_1.SplitsCacheInLocal(settings, keys);
36
+ var rbSegments = new RBSegmentsCacheInLocal_1.RBSegmentsCacheInLocal(settings, keys);
37
+ var segments = new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, keys);
38
+ var largeSegments = new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, (0, KeyBuilderCS_1.myLargeSegmentsKeyBuilder)(prefix, matchingKey));
52
39
  return {
53
40
  splits: splits,
54
41
  rbSegments: rbSegments,
@@ -60,18 +47,16 @@ function InLocalStorage(options) {
60
47
  telemetry: (0, TelemetryCacheInMemory_1.shouldRecordTelemetry)(params) ? new TelemetryCacheInMemory_1.TelemetryCacheInMemory(splits, segments) : undefined,
61
48
  uniqueKeys: new UniqueKeysCacheInMemoryCS_1.UniqueKeysCacheInMemoryCS(),
62
49
  validateCache: function () {
63
- return validateCachePromise || (validateCachePromise = (0, validateCache_1.validateCache)(options, storage, settings, keys, splits, rbSegments, segments, largeSegments));
64
- },
65
- destroy: function () {
66
- return storage.save && storage.save();
50
+ return (0, validateCache_1.validateCache)(options, settings, keys, splits, rbSegments, segments, largeSegments);
67
51
  },
52
+ destroy: function () { },
68
53
  // When using shared instantiation with MEMORY we reuse everything but segments (they are customer per key).
69
54
  shared: function (matchingKey) {
70
55
  return {
71
56
  splits: this.splits,
72
57
  rbSegments: this.rbSegments,
73
- segments: new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, new KeyBuilderCS_1.KeyBuilderCS(prefix, matchingKey), storage),
74
- largeSegments: new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, (0, KeyBuilderCS_1.myLargeSegmentsKeyBuilder)(prefix, matchingKey), storage),
58
+ segments: new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, new KeyBuilderCS_1.KeyBuilderCS(prefix, matchingKey)),
59
+ largeSegments: new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, (0, KeyBuilderCS_1.myLargeSegmentsKeyBuilder)(prefix, matchingKey)),
75
60
  impressions: this.impressions,
76
61
  impressionCounts: this.impressionCounts,
77
62
  events: this.events,
@@ -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, storage, settings, keys, currentTimestamp, isThereCache) {
14
+ function validateExpiration(options, settings, keys, currentTimestamp, isThereCache) {
15
15
  var log = settings.log;
16
16
  // Check expiration
17
- var lastUpdatedTimestamp = parseInt(storage.getItem(keys.buildLastUpdatedKey()), 10);
17
+ var lastUpdatedTimestamp = parseInt(localStorage.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, storage, settings, keys, currentTimestamp,
25
25
  }
26
26
  // Check hash
27
27
  var storageHashKey = keys.buildHashKey();
28
- var storageHash = storage.getItem(storageHashKey);
28
+ var storageHash = localStorage.getItem(storageHashKey);
29
29
  var currentStorageHash = (0, KeyBuilder_1.getStorageHash)(settings);
30
30
  if (storageHash !== currentStorageHash) {
31
31
  try {
32
- storage.setItem(storageHashKey, currentStorageHash);
32
+ localStorage.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, storage, settings, keys, currentTimestamp,
42
42
  }
43
43
  // Clear on init
44
44
  if (options.clearOnInit) {
45
- var lastClearTimestamp = parseInt(storage.getItem(keys.buildLastClear()), 10);
45
+ var lastClearTimestamp = parseInt(localStorage.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,26 +57,24 @@ function validateExpiration(options, storage, settings, keys, currentTimestamp,
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, 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
- return false;
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);
77
74
  }
78
- // Check if ready from cache
79
- return isThereCache;
80
- });
75
+ return false;
76
+ }
77
+ // Check if ready from cache
78
+ return isThereCache;
81
79
  }
82
80
  exports.validateCache = validateCache;
@@ -9,6 +9,8 @@ var ImpressionCountsCacheInMemory_1 = require("./ImpressionCountsCacheInMemory")
9
9
  var constants_1 = require("../../utils/constants");
10
10
  var TelemetryCacheInMemory_1 = require("./TelemetryCacheInMemory");
11
11
  var UniqueKeysCacheInMemoryCS_1 = require("./UniqueKeysCacheInMemoryCS");
12
+ var key_1 = require("../../utils/key");
13
+ var dataLoader_1 = require("../dataLoader");
12
14
  var RBSegmentsCacheInMemory_1 = require("./RBSegmentsCacheInMemory");
13
15
  /**
14
16
  * InMemory storage factory for standalone client-side SplitFactory
@@ -16,7 +18,8 @@ var RBSegmentsCacheInMemory_1 = require("./RBSegmentsCacheInMemory");
16
18
  * @param params - parameters required by EventsCacheSync
17
19
  */
18
20
  function InMemoryStorageCSFactory(params) {
19
- var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation;
21
+ var _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation, preloadedData = _a.preloadedData, onReadyFromCacheCb = params.onReadyFromCacheCb;
22
+ var storages = {};
20
23
  var splits = new SplitsCacheInMemory_1.SplitsCacheInMemory(__splitFiltersValidation);
21
24
  var rbSegments = new RBSegmentsCacheInMemory_1.RBSegmentsCacheInMemory();
22
25
  var segments = new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory();
@@ -33,19 +36,27 @@ function InMemoryStorageCSFactory(params) {
33
36
  uniqueKeys: new UniqueKeysCacheInMemoryCS_1.UniqueKeysCacheInMemoryCS(),
34
37
  destroy: function () { },
35
38
  // When using shared instantiation with MEMORY we reuse everything but segments (they are unique per key)
36
- shared: function () {
37
- return {
38
- splits: this.splits,
39
- rbSegments: this.rbSegments,
40
- segments: new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory(),
41
- largeSegments: new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory(),
42
- impressions: this.impressions,
43
- impressionCounts: this.impressionCounts,
44
- events: this.events,
45
- telemetry: this.telemetry,
46
- uniqueKeys: this.uniqueKeys,
47
- destroy: function () { }
48
- };
39
+ shared: function (matchingKey) {
40
+ if (!storages[matchingKey]) {
41
+ var segments_1 = new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory();
42
+ var largeSegments_1 = new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory();
43
+ if (preloadedData) {
44
+ (0, dataLoader_1.setCache)(log, preloadedData, { segments: segments_1, largeSegments: largeSegments_1 }, matchingKey);
45
+ }
46
+ storages[matchingKey] = {
47
+ splits: this.splits,
48
+ rbSegments: this.rbSegments,
49
+ segments: segments_1,
50
+ largeSegments: largeSegments_1,
51
+ impressions: this.impressions,
52
+ impressionCounts: this.impressionCounts,
53
+ events: this.events,
54
+ telemetry: this.telemetry,
55
+ uniqueKeys: this.uniqueKeys,
56
+ destroy: function () { }
57
+ };
58
+ }
59
+ return storages[matchingKey];
49
60
  },
50
61
  };
51
62
  // @TODO revisit storage logic in localhost mode
@@ -57,6 +68,13 @@ function InMemoryStorageCSFactory(params) {
57
68
  storage.impressionCounts.track = noopTrack;
58
69
  storage.uniqueKeys.track = noopTrack;
59
70
  }
71
+ var matchingKey = (0, key_1.getMatching)(params.settings.core.key);
72
+ storages[matchingKey] = storage;
73
+ if (preloadedData) {
74
+ (0, dataLoader_1.setCache)(log, preloadedData, storage, matchingKey);
75
+ if (splits.getChangeNumber() > -1)
76
+ onReadyFromCacheCb();
77
+ }
60
78
  return storage;
61
79
  }
62
80
  exports.InMemoryStorageCSFactory = InMemoryStorageCSFactory;
@@ -45,6 +45,10 @@ var RBSegmentsCacheInMemory = /** @class */ (function () {
45
45
  RBSegmentsCacheInMemory.prototype.get = function (name) {
46
46
  return this.cache[name] || null;
47
47
  };
48
+ RBSegmentsCacheInMemory.prototype.getAll = function () {
49
+ var _this = this;
50
+ return this.getNames().map(function (key) { return _this.get(key); });
51
+ };
48
52
  RBSegmentsCacheInMemory.prototype.contains = function (names) {
49
53
  var namesArray = (0, sets_1.setToArray)(names);
50
54
  var namesInStorage = this.getNames();
@@ -45,9 +45,10 @@ 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
- Promise.resolve(storage.validateCache ? storage.validateCache() : false).then(function (isCacheLoaded) {
48
+ var isCacheLoaded_1 = storage.validateCache ? storage.validateCache() : false;
49
+ Promise.resolve().then(function () {
49
50
  // Emits SDK_READY_FROM_CACHE
50
- if (isCacheLoaded)
51
+ if (isCacheLoaded_1)
51
52
  readiness.splits.emit(constants_2.SDK_SPLITS_CACHE_LOADED);
52
53
  // Emits SDK_READY
53
54
  readiness.segments.emit(constants_2.SDK_SEGMENTS_ARRIVED);
@@ -69,39 +69,35 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
69
69
  */
70
70
  start: function () {
71
71
  running = true;
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();
95
- }
96
- }
97
- else {
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
98
83
  if (startFirstTime) {
99
84
  pollingManager.syncAll();
100
85
  }
86
+ pushManager.start();
87
+ }
88
+ else {
89
+ pollingManager.start();
90
+ }
91
+ }
92
+ else {
93
+ if (startFirstTime) {
94
+ pollingManager.syncAll();
101
95
  }
102
96
  }
103
- startFirstTime = false;
104
- });
97
+ }
98
+ // start periodic data recording (events, impressions, telemetry).
99
+ submitterManager.start(!(0, consent_1.isConsentGranted)(settings));
100
+ startFirstTime = false;
105
101
  },
106
102
  /**
107
103
  * Method used to stop/pause the syncManager.
@@ -1,39 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isWebStorage = exports.isValidStorageWrapper = exports.isLocalStorageAvailable = void 0;
3
+ exports.isLocalStorageAvailable = void 0;
4
+ /* eslint-disable no-undef */
4
5
  function isLocalStorageAvailable() {
5
- try {
6
- // eslint-disable-next-line no-undef
7
- return isValidStorageWrapper(localStorage);
8
- }
9
- catch (e) {
10
- return false;
11
- }
12
- }
13
- exports.isLocalStorageAvailable = isLocalStorageAvailable;
14
- function isValidStorageWrapper(wrapper) {
15
6
  var mod = '__SPLITSOFTWARE__';
16
7
  try {
17
- wrapper.setItem(mod, mod);
18
- wrapper.getItem(mod);
19
- wrapper.removeItem(mod);
8
+ localStorage.setItem(mod, mod);
9
+ localStorage.removeItem(mod);
20
10
  return true;
21
11
  }
22
12
  catch (e) {
23
13
  return false;
24
14
  }
25
15
  }
26
- exports.isValidStorageWrapper = isValidStorageWrapper;
27
- function isWebStorage(wrapper) {
28
- if (typeof wrapper.length === 'number') {
29
- try {
30
- wrapper.key(0);
31
- return true;
32
- }
33
- catch (e) {
34
- return false;
35
- }
36
- }
37
- return false;
38
- }
39
- exports.isWebStorage = isWebStorage;
16
+ exports.isLocalStorageAvailable = isLocalStorageAvailable;
@@ -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 Promise.resolve(true); }; // to emit SDK_READY_FROM_CACHE
9
+ result.validateCache = function () { return true; }; // to emit SDK_READY_FROM_CACHE
10
10
  return result;
11
11
  }
12
12
  exports.__InLocalStorageMockFactory = __InLocalStorageMockFactory;
@@ -20,45 +20,37 @@ var AbstractMySegmentsCacheSync = /** @class */ (function () {
20
20
  */
21
21
  AbstractMySegmentsCacheSync.prototype.resetSegments = function (segmentsData) {
22
22
  var _this = this;
23
+ this.setChangeNumber(segmentsData.cn);
23
24
  var _a = segmentsData, added = _a.added, removed = _a.removed;
24
- var isDiff = false;
25
25
  if (added && removed) {
26
+ var isDiff_1 = false;
26
27
  added.forEach(function (segment) {
27
- isDiff = _this.addSegment(segment) || isDiff;
28
+ isDiff_1 = _this.addSegment(segment) || isDiff_1;
28
29
  });
29
30
  removed.forEach(function (segment) {
30
- isDiff = _this.removeSegment(segment) || isDiff;
31
+ isDiff_1 = _this.removeSegment(segment) || isDiff_1;
31
32
  });
33
+ return isDiff_1;
32
34
  }
33
- else {
34
- var names = (segmentsData.k || []).map(function (s) { return s.n; }).sort();
35
- var storedSegmentKeys = this.getRegisteredSegments().sort();
36
- // Extreme fast => everything is empty
37
- if (!names.length && !storedSegmentKeys.length) {
38
- isDiff = false;
39
- }
40
- else {
41
- var index = 0;
42
- while (index < names.length && index < storedSegmentKeys.length && names[index] === storedSegmentKeys[index])
43
- index++;
44
- // Quick path => no changes
45
- if (index === names.length && index === storedSegmentKeys.length) {
46
- isDiff = false;
47
- }
48
- else {
49
- // Slowest path => add and/or remove segments
50
- for (var removeIndex = index; removeIndex < storedSegmentKeys.length; removeIndex++) {
51
- this.removeSegment(storedSegmentKeys[removeIndex]);
52
- }
53
- for (var addIndex = index; addIndex < names.length; addIndex++) {
54
- this.addSegment(names[addIndex]);
55
- }
56
- isDiff = true;
57
- }
58
- }
35
+ var names = (segmentsData.k || []).map(function (s) { return s.n; }).sort();
36
+ var storedSegmentKeys = this.getRegisteredSegments().sort();
37
+ // Extreme fast => everything is empty
38
+ if (!names.length && !storedSegmentKeys.length)
39
+ return false;
40
+ var index = 0;
41
+ while (index < names.length && index < storedSegmentKeys.length && names[index] === storedSegmentKeys[index])
42
+ index++;
43
+ // Quick path => no changes
44
+ if (index === names.length && index === storedSegmentKeys.length)
45
+ return false;
46
+ // Slowest path => add and/or remove segments
47
+ for (var removeIndex = index; removeIndex < storedSegmentKeys.length; removeIndex++) {
48
+ this.removeSegment(storedSegmentKeys[removeIndex]);
59
49
  }
60
- this.setChangeNumber(segmentsData.cn);
61
- return isDiff;
50
+ for (var addIndex = index; addIndex < names.length; addIndex++) {
51
+ this.addSegment(names[addIndex]);
52
+ }
53
+ return true;
62
54
  };
63
55
  return AbstractMySegmentsCacheSync;
64
56
  }());