@splitsoftware/splitio-commons 2.0.0-rc.0 → 2.0.0-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 (108) hide show
  1. package/CHANGES.txt +2 -1
  2. package/cjs/evaluator/Engine.js +1 -1
  3. package/cjs/evaluator/index.js +1 -1
  4. package/cjs/readiness/readinessManager.js +13 -2
  5. package/cjs/sdkClient/sdkClientMethodCS.js +0 -1
  6. package/cjs/sdkFactory/index.js +26 -8
  7. package/cjs/storages/{AbstractSegmentsCacheSync.js → AbstractMySegmentsCacheSync.js} +15 -17
  8. package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +5 -5
  9. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +3 -2
  10. package/cjs/storages/inLocalStorage/index.js +1 -1
  11. package/cjs/storages/inMemory/InMemoryStorageCS.js +2 -2
  12. package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +5 -5
  13. package/cjs/storages/inMemory/SegmentsCacheInMemory.js +13 -27
  14. package/cjs/storages/inMemory/SplitsCacheInMemory.js +0 -1
  15. package/cjs/storages/inMemory/UniqueKeysCacheInMemory.js +2 -1
  16. package/cjs/storages/inMemory/UniqueKeysCacheInMemoryCS.js +2 -1
  17. package/cjs/storages/inRedis/RedisAdapter.js +2 -1
  18. package/cjs/storages/inRedis/SegmentsCacheInRedis.js +13 -19
  19. package/cjs/storages/inRedis/UniqueKeysCacheInRedis.js +2 -1
  20. package/cjs/storages/pluggable/SegmentsCachePluggable.js +11 -32
  21. package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +2 -1
  22. package/cjs/storages/pluggable/inMemoryWrapper.js +2 -1
  23. package/cjs/sync/offline/syncManagerOffline.js +18 -11
  24. package/cjs/sync/polling/updaters/segmentChangesUpdater.js +12 -28
  25. package/cjs/sync/polling/updaters/splitChangesUpdater.js +2 -1
  26. package/cjs/sync/syncManagerOnline.js +20 -21
  27. package/cjs/trackers/eventTracker.js +12 -10
  28. package/cjs/trackers/impressionsTracker.js +16 -14
  29. package/cjs/trackers/uniqueKeysTracker.js +5 -3
  30. package/cjs/utils/lang/sets.js +12 -2
  31. package/esm/evaluator/Engine.js +1 -1
  32. package/esm/evaluator/index.js +2 -2
  33. package/esm/readiness/readinessManager.js +13 -2
  34. package/esm/sdkClient/sdkClientMethodCS.js +0 -1
  35. package/esm/sdkFactory/index.js +26 -8
  36. package/esm/storages/{AbstractSegmentsCacheSync.js → AbstractMySegmentsCacheSync.js} +14 -16
  37. package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +5 -5
  38. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +3 -2
  39. package/esm/storages/inLocalStorage/index.js +1 -1
  40. package/esm/storages/inMemory/InMemoryStorageCS.js +2 -2
  41. package/esm/storages/inMemory/MySegmentsCacheInMemory.js +5 -5
  42. package/esm/storages/inMemory/SegmentsCacheInMemory.js +13 -27
  43. package/esm/storages/inMemory/SplitsCacheInMemory.js +0 -1
  44. package/esm/storages/inMemory/UniqueKeysCacheInMemory.js +2 -1
  45. package/esm/storages/inMemory/UniqueKeysCacheInMemoryCS.js +2 -1
  46. package/esm/storages/inRedis/RedisAdapter.js +2 -1
  47. package/esm/storages/inRedis/SegmentsCacheInRedis.js +13 -19
  48. package/esm/storages/inRedis/UniqueKeysCacheInRedis.js +2 -1
  49. package/esm/storages/pluggable/SegmentsCachePluggable.js +11 -32
  50. package/esm/storages/pluggable/UniqueKeysCachePluggable.js +2 -1
  51. package/esm/storages/pluggable/inMemoryWrapper.js +2 -1
  52. package/esm/sync/offline/syncManagerOffline.js +18 -11
  53. package/esm/sync/polling/updaters/segmentChangesUpdater.js +12 -28
  54. package/esm/sync/polling/updaters/splitChangesUpdater.js +2 -1
  55. package/esm/sync/syncManagerOnline.js +20 -21
  56. package/esm/trackers/eventTracker.js +12 -10
  57. package/esm/trackers/impressionsTracker.js +16 -14
  58. package/esm/trackers/uniqueKeysTracker.js +5 -3
  59. package/esm/utils/lang/sets.js +10 -1
  60. package/package.json +1 -1
  61. package/src/evaluator/Engine.ts +1 -1
  62. package/src/evaluator/index.ts +2 -2
  63. package/src/readiness/readinessManager.ts +12 -3
  64. package/src/readiness/types.ts +3 -0
  65. package/src/sdkClient/sdkClientMethodCS.ts +0 -2
  66. package/src/sdkFactory/index.ts +28 -9
  67. package/src/sdkFactory/types.ts +2 -0
  68. package/src/storages/{AbstractSegmentsCacheSync.ts → AbstractMySegmentsCacheSync.ts} +13 -28
  69. package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +5 -5
  70. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +3 -2
  71. package/src/storages/inLocalStorage/index.ts +1 -1
  72. package/src/storages/inMemory/InMemoryStorageCS.ts +2 -2
  73. package/src/storages/inMemory/MySegmentsCacheInMemory.ts +5 -5
  74. package/src/storages/inMemory/SegmentsCacheInMemory.ts +12 -26
  75. package/src/storages/inMemory/SplitsCacheInMemory.ts +0 -1
  76. package/src/storages/inMemory/UniqueKeysCacheInMemory.ts +2 -1
  77. package/src/storages/inMemory/UniqueKeysCacheInMemoryCS.ts +2 -1
  78. package/src/storages/inRedis/RedisAdapter.ts +2 -1
  79. package/src/storages/inRedis/SegmentsCacheInRedis.ts +13 -22
  80. package/src/storages/inRedis/UniqueKeysCacheInRedis.ts +2 -1
  81. package/src/storages/pluggable/SegmentsCachePluggable.ts +11 -35
  82. package/src/storages/pluggable/UniqueKeysCachePluggable.ts +2 -1
  83. package/src/storages/pluggable/inMemoryWrapper.ts +2 -1
  84. package/src/storages/types.ts +3 -9
  85. package/src/sync/offline/syncManagerOffline.ts +21 -13
  86. package/src/sync/polling/updaters/segmentChangesUpdater.ts +13 -29
  87. package/src/sync/polling/updaters/splitChangesUpdater.ts +2 -1
  88. package/src/sync/syncManagerOnline.ts +17 -17
  89. package/src/sync/types.ts +1 -1
  90. package/src/trackers/eventTracker.ts +11 -8
  91. package/src/trackers/impressionsTracker.ts +13 -10
  92. package/src/trackers/types.ts +1 -0
  93. package/src/trackers/uniqueKeysTracker.ts +6 -4
  94. package/src/utils/lang/sets.ts +11 -1
  95. package/types/readiness/types.d.ts +3 -0
  96. package/types/sdkFactory/types.d.ts +1 -0
  97. package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +5 -5
  98. package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +5 -5
  99. package/types/storages/inMemory/SegmentsCacheInMemory.d.ts +5 -7
  100. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +0 -1
  101. package/types/storages/inRedis/SegmentsCacheInRedis.d.ts +6 -3
  102. package/types/storages/pluggable/SegmentsCachePluggable.d.ts +4 -16
  103. package/types/storages/types.d.ts +3 -9
  104. package/types/sync/types.d.ts +1 -1
  105. package/types/trackers/eventTracker.d.ts +1 -1
  106. package/types/trackers/impressionsTracker.d.ts +1 -1
  107. package/types/trackers/types.d.ts +1 -0
  108. package/types/utils/lang/sets.d.ts +1 -0
package/CHANGES.txt CHANGED
@@ -1,15 +1,16 @@
1
1
  2.0.0 (October XX, 2024)
2
2
  - Added support for targeting rules based on large segments.
3
3
  - Added `factory.destroy()` method, which invokes the `destroy` method on all SDK clients created by the factory.
4
+ - Updated the handling of timers and async operations inside an `init` factory method to enable lazy initialization of the SDK in standalone mode. This update is intended for the React SDK.
4
5
  - Bugfixing - Fixed an issue with the server-side polling manager that caused dangling timers when the SDK was destroyed before it was ready.
5
6
  - BREAKING CHANGES:
6
7
  - Updated default flag spec version to 1.2.
7
8
  - Removed `/mySegments` endpoint from SplitAPI module, as it is replaced by `/memberships` endpoint.
8
9
  - Removed support for MY_SEGMENTS_UPDATE and MY_SEGMENTS_UPDATE_V2 notification types, as they are replaced by MEMBERSHIPS_MS_UPDATE and MEMBERSHIPS_LS_UPDATE notification types.
9
10
  - Removed the deprecated `GOOGLE_ANALYTICS_TO_SPLIT` and `SPLIT_TO_GOOGLE_ANALYTICS` integrations.
10
- - Removed internal ponyfills for `Map`, `Set` and `Array.from` global objects, dropping support for IE and other outdated browsers. The SDK now requires the runtime environment to support these features natively or to provide a polyfill.
11
11
  - Removed the migration logic for the old format of MySegments keys in LocalStorage introduced in JavaScript SDK v10.17.3.
12
12
  - Removed the `sdkClientMethodCSWithTT` function, which handled the logic to bound an optional traffic type to SDK clients. Client-side SDK implementations must use `sdkClientMethodCS` module, which, unlike the previous function, does not allow passing a traffic type but simplifies the SDK API.
13
+ - Removed internal ponyfills for `Map` and `Set` global objects, dropping support for IE and other outdated browsers. The SDK now requires the runtime environment to support these features natively or to provide a polyfill.
13
14
 
14
15
  1.17.0 (September 6, 2024)
15
16
  - Added `sync.requestOptions.getHeaderOverrides` configuration option to enhance SDK HTTP request Headers for Authorization Frameworks.
@@ -17,7 +17,7 @@ var Engine = /** @class */ (function () {
17
17
  function Engine(baseInfo, evaluator) {
18
18
  this.baseInfo = baseInfo;
19
19
  this.evaluator = evaluator;
20
- // in case we don't have a default treatment in the instanciation, use 'control'
20
+ // in case we don't have a default treatment in the instantiation, use 'control'
21
21
  if (typeof this.baseInfo.defaultTreatment !== 'string') {
22
22
  this.baseInfo.defaultTreatment = constants_1.CONTROL;
23
23
  }
@@ -70,7 +70,7 @@ function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, storage, met
70
70
  }
71
71
  }
72
72
  return featureFlags.size ?
73
- evaluateFeatures(log, key, Array.from(featureFlags), attributes, storage) :
73
+ evaluateFeatures(log, key, (0, sets_1.setToArray)(featureFlags), attributes, storage) :
74
74
  {};
75
75
  }
76
76
  // get features by flag sets
@@ -7,6 +7,8 @@ function splitsEventEmitterFactory(EventEmitter) {
7
7
  var splitsEventEmitter = (0, objectAssign_1.objectAssign)(new EventEmitter(), {
8
8
  splitsArrived: false,
9
9
  splitsCacheLoaded: false,
10
+ initialized: false,
11
+ initCallbacks: []
10
12
  });
11
13
  // `isSplitKill` condition avoids an edge-case of wrongly emitting SDK_READY if:
12
14
  // - `/memberships` fetch and SPLIT_KILL occurs before `/splitChanges` fetch, and
@@ -46,7 +48,7 @@ function readinessManagerFactory(EventEmitter, settings, splits) {
46
48
  // emit SDK_READY_TIMED_OUT
47
49
  var hasTimedout = false;
48
50
  function timeout() {
49
- if (hasTimedout)
51
+ if (hasTimedout || isReady)
50
52
  return;
51
53
  hasTimedout = true;
52
54
  syncLastUpdate();
@@ -54,7 +56,10 @@ function readinessManagerFactory(EventEmitter, settings, splits) {
54
56
  }
55
57
  var readyTimeoutId;
56
58
  if (readyTimeout > 0) {
57
- readyTimeoutId = setTimeout(timeout, readyTimeout);
59
+ if (splits.initialized)
60
+ readyTimeoutId = setTimeout(timeout, readyTimeout);
61
+ else
62
+ splits.initCallbacks.push(function () { readyTimeoutId = setTimeout(timeout, readyTimeout); });
58
63
  }
59
64
  // emit SDK_READY and SDK_UPDATE
60
65
  var isReady = false;
@@ -116,6 +121,12 @@ function readinessManagerFactory(EventEmitter, settings, splits) {
116
121
  // Called on 403 error (client-side SDK key on server-side), to set the SDK as destroyed for
117
122
  // tracking and evaluations, while keeping event listeners to emit SDK_READY_TIMED_OUT event
118
123
  setDestroyed: function () { isDestroyed = true; },
124
+ init: function () {
125
+ if (splits.initialized)
126
+ return;
127
+ splits.initialized = true;
128
+ splits.initCallbacks.forEach(function (cb) { return cb(); });
129
+ },
119
130
  destroy: function () {
120
131
  isDestroyed = true;
121
132
  syncLastUpdate();
@@ -55,7 +55,6 @@ function sdkClientMethodCSFactory(params) {
55
55
  storage: sharedStorage || storage,
56
56
  syncManager: sharedSyncManager,
57
57
  }), true), validKey);
58
- sharedSyncManager && sharedSyncManager.start();
59
58
  log.info(constants_1.NEW_SHARED_CLIENT);
60
59
  }
61
60
  else {
@@ -19,12 +19,19 @@ var constants_3 = require("../utils/constants");
19
19
  * Modular SDK factory
20
20
  */
21
21
  function sdkFactory(params) {
22
- var settings = params.settings, platform = params.platform, storageFactory = params.storageFactory, splitApiFactory = params.splitApiFactory, extraProps = params.extraProps, syncManagerFactory = params.syncManagerFactory, SignalListener = params.SignalListener, impressionsObserverFactory = params.impressionsObserverFactory, integrationsManagerFactory = params.integrationsManagerFactory, sdkManagerFactory = params.sdkManagerFactory, sdkClientMethodFactory = params.sdkClientMethodFactory, filterAdapterFactory = params.filterAdapterFactory;
22
+ var settings = params.settings, platform = params.platform, storageFactory = params.storageFactory, splitApiFactory = params.splitApiFactory, extraProps = params.extraProps, syncManagerFactory = params.syncManagerFactory, SignalListener = params.SignalListener, impressionsObserverFactory = params.impressionsObserverFactory, integrationsManagerFactory = params.integrationsManagerFactory, sdkManagerFactory = params.sdkManagerFactory, sdkClientMethodFactory = params.sdkClientMethodFactory, filterAdapterFactory = params.filterAdapterFactory, lazyInit = params.lazyInit;
23
23
  var log = settings.log, impressionsMode = settings.sync.impressionsMode;
24
24
  // @TODO handle non-recoverable errors, such as, global `fetch` not available, invalid SDK Key, etc.
25
25
  // On non-recoverable errors, we should mark the SDK as destroyed and not start synchronization.
26
- // We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
27
- (0, apiKey_1.validateAndTrackApiKey)(log, settings.core.authorizationKey);
26
+ // initialization
27
+ var hasInit = false;
28
+ var initCallbacks = [];
29
+ function whenInit(cb) {
30
+ if (hasInit)
31
+ cb();
32
+ else
33
+ initCallbacks.push(cb);
34
+ }
28
35
  var sdkReadinessManager = (0, sdkReadinessManager_1.sdkReadinessManagerFactory)(platform.EventEmitter, settings);
29
36
  var readiness = sdkReadinessManager.readinessManager;
30
37
  var storage = storageFactory({
@@ -56,8 +63,8 @@ function sdkFactory(params) {
56
63
  default:
57
64
  strategy = (0, strategyDebug_1.strategyDebugFactory)(observer);
58
65
  }
59
- var impressionsTracker = (0, impressionsTracker_1.impressionsTrackerFactory)(settings, storage.impressions, strategy, integrationsManager, storage.telemetry);
60
- var eventTracker = (0, eventTracker_1.eventTrackerFactory)(settings, storage.events, integrationsManager, storage.telemetry);
66
+ var impressionsTracker = (0, impressionsTracker_1.impressionsTrackerFactory)(settings, storage.impressions, strategy, whenInit, integrationsManager, storage.telemetry);
67
+ var eventTracker = (0, eventTracker_1.eventTrackerFactory)(settings, storage.events, whenInit, integrationsManager, storage.telemetry);
61
68
  // splitApi is used by SyncManager and Browser signal listener
62
69
  var splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
63
70
  var ctx = { clients: clients, splitApi: splitApi, eventTracker: eventTracker, impressionsTracker: impressionsTracker, telemetryTracker: telemetryTracker, uniqueKeysTracker: uniqueKeysTracker, sdkReadinessManager: sdkReadinessManager, readiness: readiness, settings: settings, storage: storage, platform: platform };
@@ -68,8 +75,19 @@ function sdkFactory(params) {
68
75
  // SDK client and manager
69
76
  var clientMethod = sdkClientMethodFactory(ctx);
70
77
  var managerInstance = sdkManagerFactory(settings, storage.splits, sdkReadinessManager);
71
- syncManager && syncManager.start();
72
- signalListener && signalListener.start();
78
+ function init() {
79
+ if (hasInit)
80
+ return;
81
+ hasInit = true;
82
+ // We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
83
+ (0, apiKey_1.validateAndTrackApiKey)(log, settings.core.authorizationKey);
84
+ readiness.init();
85
+ uniqueKeysTracker && uniqueKeysTracker.start();
86
+ syncManager && syncManager.start();
87
+ signalListener && signalListener.start();
88
+ initCallbacks.forEach(function (cb) { return cb(); });
89
+ initCallbacks.length = 0;
90
+ }
73
91
  log.info(constants_1.NEW_FACTORY);
74
92
  // @ts-ignore
75
93
  return (0, objectAssign_1.objectAssign)({
@@ -86,6 +104,6 @@ function sdkFactory(params) {
86
104
  destroy: function () {
87
105
  return Promise.all(Object.keys(clients).map(function (key) { return clients[key].destroy(); })).then(function () { });
88
106
  }
89
- }, extraProps && extraProps(ctx));
107
+ }, extraProps && extraProps(ctx), lazyInit ? { init: init } : init());
90
108
  }
91
109
  exports.sdkFactory = sdkFactory;
@@ -1,39 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AbstractSegmentsCacheSync = void 0;
3
+ exports.AbstractMySegmentsCacheSync = void 0;
4
4
  /**
5
5
  * This class provides a skeletal implementation of the ISegmentsCacheSync interface
6
6
  * to minimize the effort required to implement this interface.
7
7
  */
8
- var AbstractSegmentsCacheSync = /** @class */ (function () {
9
- function AbstractSegmentsCacheSync() {
8
+ var AbstractMySegmentsCacheSync = /** @class */ (function () {
9
+ function AbstractMySegmentsCacheSync() {
10
10
  }
11
11
  /**
12
12
  * clear the cache.
13
13
  */
14
- AbstractSegmentsCacheSync.prototype.clear = function () {
14
+ AbstractMySegmentsCacheSync.prototype.clear = function () {
15
15
  this.resetSegments({});
16
16
  };
17
- /**
18
- * For server-side synchronizer: add the given list of segments to the cache, with an empty list of keys. The segments that already exist are not modified.
19
- * For client-side synchronizer: the method is not used.
20
- */
21
- AbstractSegmentsCacheSync.prototype.registerSegments = function (names) { return false; };
17
+ // No-op. Not used in client-side.
18
+ AbstractMySegmentsCacheSync.prototype.registerSegments = function () { return false; };
19
+ AbstractMySegmentsCacheSync.prototype.update = function () { return false; };
22
20
  /**
23
21
  * For server-side synchronizer: the method is not used.
24
22
  * For client-side synchronizer: it resets or updates the cache.
25
23
  */
26
- AbstractSegmentsCacheSync.prototype.resetSegments = function (segmentsData) {
24
+ AbstractMySegmentsCacheSync.prototype.resetSegments = function (segmentsData) {
27
25
  var _this = this;
28
- this.setChangeNumber(undefined, segmentsData.cn);
26
+ this.setChangeNumber(segmentsData.cn);
29
27
  var _a = segmentsData, added = _a.added, removed = _a.removed;
30
28
  if (added && removed) {
31
29
  var isDiff_1 = false;
32
30
  added.forEach(function (segment) {
33
- isDiff_1 = _this.addToSegment(segment) || isDiff_1;
31
+ isDiff_1 = _this.addSegment(segment) || isDiff_1;
34
32
  });
35
33
  removed.forEach(function (segment) {
36
- isDiff_1 = _this.removeFromSegment(segment) || isDiff_1;
34
+ isDiff_1 = _this.removeSegment(segment) || isDiff_1;
37
35
  });
38
36
  return isDiff_1;
39
37
  }
@@ -50,13 +48,13 @@ var AbstractSegmentsCacheSync = /** @class */ (function () {
50
48
  return false;
51
49
  // Slowest path => add and/or remove segments
52
50
  for (var removeIndex = index; removeIndex < storedSegmentKeys.length; removeIndex++) {
53
- this.removeFromSegment(storedSegmentKeys[removeIndex]);
51
+ this.removeSegment(storedSegmentKeys[removeIndex]);
54
52
  }
55
53
  for (var addIndex = index; addIndex < names.length; addIndex++) {
56
- this.addToSegment(names[addIndex]);
54
+ this.addSegment(names[addIndex]);
57
55
  }
58
56
  return true;
59
57
  };
60
- return AbstractSegmentsCacheSync;
58
+ return AbstractMySegmentsCacheSync;
61
59
  }());
62
- exports.AbstractSegmentsCacheSync = AbstractSegmentsCacheSync;
60
+ exports.AbstractMySegmentsCacheSync = AbstractMySegmentsCacheSync;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MySegmentsCacheInLocal = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var lang_1 = require("../../utils/lang");
6
- var AbstractSegmentsCacheSync_1 = require("../AbstractSegmentsCacheSync");
6
+ var AbstractMySegmentsCacheSync_1 = require("../AbstractMySegmentsCacheSync");
7
7
  var constants_1 = require("./constants");
8
8
  var MySegmentsCacheInLocal = /** @class */ (function (_super) {
9
9
  (0, tslib_1.__extends)(MySegmentsCacheInLocal, _super);
@@ -14,7 +14,7 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
14
14
  return _this;
15
15
  // There is not need to flush segments cache like splits cache, since resetSegments receives the up-to-date list of active segments
16
16
  }
17
- MySegmentsCacheInLocal.prototype.addToSegment = function (name) {
17
+ MySegmentsCacheInLocal.prototype.addSegment = function (name) {
18
18
  var segmentKey = this.keys.buildSegmentNameKey(name);
19
19
  try {
20
20
  if (localStorage.getItem(segmentKey) === constants_1.DEFINED)
@@ -27,7 +27,7 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
27
27
  return false;
28
28
  }
29
29
  };
30
- MySegmentsCacheInLocal.prototype.removeFromSegment = function (name) {
30
+ MySegmentsCacheInLocal.prototype.removeSegment = function (name) {
31
31
  var segmentKey = this.keys.buildSegmentNameKey(name);
32
32
  try {
33
33
  if (localStorage.getItem(segmentKey) !== constants_1.DEFINED)
@@ -56,7 +56,7 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
56
56
  MySegmentsCacheInLocal.prototype.getKeysCount = function () {
57
57
  return 1;
58
58
  };
59
- MySegmentsCacheInLocal.prototype.setChangeNumber = function (name, changeNumber) {
59
+ MySegmentsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
60
60
  try {
61
61
  if (changeNumber)
62
62
  localStorage.setItem(this.keys.buildTillKey(), changeNumber + '');
@@ -77,5 +77,5 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
77
77
  return n;
78
78
  };
79
79
  return MySegmentsCacheInLocal;
80
- }(AbstractSegmentsCacheSync_1.AbstractSegmentsCacheSync));
80
+ }(AbstractMySegmentsCacheSync_1.AbstractMySegmentsCacheSync));
81
81
  exports.MySegmentsCacheInLocal = MySegmentsCacheInLocal;
@@ -6,6 +6,7 @@ var AbstractSplitsCacheSync_1 = require("../AbstractSplitsCacheSync");
6
6
  var lang_1 = require("../../utils/lang");
7
7
  var constants_1 = require("./constants");
8
8
  var KeyBuilder_1 = require("../KeyBuilder");
9
+ var sets_1 = require("../../utils/lang/sets");
9
10
  /**
10
11
  * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
11
12
  */
@@ -243,7 +244,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
243
244
  var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
244
245
  var flagSetCache = new Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
245
246
  flagSetCache.add(featureFlag.name);
246
- localStorage.setItem(flagSetKey, JSON.stringify(Array.from(flagSetCache)));
247
+ localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
247
248
  });
248
249
  };
249
250
  SplitsCacheInLocal.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
@@ -265,7 +266,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
265
266
  localStorage.removeItem(flagSetKey);
266
267
  return;
267
268
  }
268
- localStorage.setItem(flagSetKey, JSON.stringify(Array.from(flagSetCache)));
269
+ localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
269
270
  };
270
271
  return SplitsCacheInLocal;
271
272
  }(AbstractSplitsCacheSync_1.AbstractSplitsCacheSync));
@@ -56,7 +56,7 @@ function InLocalStorage(options) {
56
56
  this.events.clear();
57
57
  (_a = this.uniqueKeys) === null || _a === void 0 ? void 0 : _a.clear();
58
58
  },
59
- // When using shared instanciation with MEMORY we reuse everything but segments (they are customer per key).
59
+ // When using shared instantiation with MEMORY we reuse everything but segments (they are customer per key).
60
60
  shared: function (matchingKey) {
61
61
  return {
62
62
  splits: this.splits,
@@ -38,7 +38,7 @@ function InMemoryStorageCSFactory(params) {
38
38
  this.events.clear();
39
39
  this.uniqueKeys && this.uniqueKeys.clear();
40
40
  },
41
- // When using shared instanciation with MEMORY we reuse everything but segments (they are unique per key)
41
+ // When using shared instantiation with MEMORY we reuse everything but segments (they are unique per key)
42
42
  shared: function () {
43
43
  return {
44
44
  splits: this.splits,
@@ -58,7 +58,7 @@ function InMemoryStorageCSFactory(params) {
58
58
  },
59
59
  };
60
60
  // @TODO revisit storage logic in localhost mode
61
- // No tracking data in localhost mode to avoid memory leaks
61
+ // No tracking in localhost mode to avoid memory leaks: https://github.com/splitio/javascript-commons/issues/181
62
62
  if (params.settings.mode === constants_1.LOCALHOST_MODE) {
63
63
  var noopTrack = function () { return true; };
64
64
  storage.impressions.track = noopTrack;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MySegmentsCacheInMemory = void 0;
4
4
  var tslib_1 = require("tslib");
5
- var AbstractSegmentsCacheSync_1 = require("../AbstractSegmentsCacheSync");
5
+ var AbstractMySegmentsCacheSync_1 = require("../AbstractMySegmentsCacheSync");
6
6
  /**
7
7
  * Default MySegmentsCacheInMemory implementation that stores MySegments in memory.
8
8
  * Supported by all JS runtimes.
@@ -14,13 +14,13 @@ var MySegmentsCacheInMemory = /** @class */ (function (_super) {
14
14
  _this.segmentCache = {};
15
15
  return _this;
16
16
  }
17
- MySegmentsCacheInMemory.prototype.addToSegment = function (name) {
17
+ MySegmentsCacheInMemory.prototype.addSegment = function (name) {
18
18
  if (this.segmentCache[name])
19
19
  return false;
20
20
  this.segmentCache[name] = true;
21
21
  return true;
22
22
  };
23
- MySegmentsCacheInMemory.prototype.removeFromSegment = function (name) {
23
+ MySegmentsCacheInMemory.prototype.removeSegment = function (name) {
24
24
  if (!this.segmentCache[name])
25
25
  return false;
26
26
  delete this.segmentCache[name];
@@ -29,7 +29,7 @@ var MySegmentsCacheInMemory = /** @class */ (function (_super) {
29
29
  MySegmentsCacheInMemory.prototype.isInSegment = function (name) {
30
30
  return this.segmentCache[name] === true;
31
31
  };
32
- MySegmentsCacheInMemory.prototype.setChangeNumber = function (name, changeNumber) {
32
+ MySegmentsCacheInMemory.prototype.setChangeNumber = function (changeNumber) {
33
33
  this.cn = changeNumber;
34
34
  };
35
35
  MySegmentsCacheInMemory.prototype.getChangeNumber = function () {
@@ -42,5 +42,5 @@ var MySegmentsCacheInMemory = /** @class */ (function (_super) {
42
42
  return 1;
43
43
  };
44
44
  return MySegmentsCacheInMemory;
45
- }(AbstractSegmentsCacheSync_1.AbstractSegmentsCacheSync));
45
+ }(AbstractMySegmentsCacheSync_1.AbstractMySegmentsCacheSync));
46
46
  exports.MySegmentsCacheInMemory = MySegmentsCacheInMemory;
@@ -1,34 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SegmentsCacheInMemory = void 0;
4
- var tslib_1 = require("tslib");
5
- var AbstractSegmentsCacheSync_1 = require("../AbstractSegmentsCacheSync");
6
4
  var lang_1 = require("../../utils/lang");
7
5
  /**
8
- * Default ISplitsCacheSync implementation that stores split definitions in memory.
9
- * Supported by all JS runtimes.
6
+ * Default ISplitsCacheSync implementation for server-side that stores segments definitions in memory.
10
7
  */
11
- var SegmentsCacheInMemory = /** @class */ (function (_super) {
12
- (0, tslib_1.__extends)(SegmentsCacheInMemory, _super);
8
+ var SegmentsCacheInMemory = /** @class */ (function () {
13
9
  function SegmentsCacheInMemory() {
14
- var _this = _super !== null && _super.apply(this, arguments) || this;
15
- _this.segmentCache = {};
16
- _this.segmentChangeNumber = {};
17
- return _this;
10
+ this.segmentCache = {};
11
+ this.segmentChangeNumber = {};
18
12
  }
19
- SegmentsCacheInMemory.prototype.addToSegment = function (name, segmentKeys) {
20
- var values = this.segmentCache[name];
21
- var keySet = values ? values : new Set();
22
- segmentKeys.forEach(function (k) { return keySet.add(k); });
23
- this.segmentCache[name] = keySet;
24
- return true;
25
- };
26
- SegmentsCacheInMemory.prototype.removeFromSegment = function (name, segmentKeys) {
27
- var values = this.segmentCache[name];
28
- var keySet = values ? values : new Set();
29
- segmentKeys.forEach(function (k) { return keySet.delete(k); });
13
+ SegmentsCacheInMemory.prototype.update = function (name, addedKeys, removedKeys, changeNumber) {
14
+ var keySet = this.segmentCache[name] || new Set();
15
+ addedKeys.forEach(function (k) { return keySet.add(k); });
16
+ removedKeys.forEach(function (k) { return keySet.delete(k); });
30
17
  this.segmentCache[name] = keySet;
31
- return true;
18
+ this.segmentChangeNumber[name] = changeNumber;
19
+ return addedKeys.length > 0 || removedKeys.length > 0;
32
20
  };
33
21
  SegmentsCacheInMemory.prototype.isInSegment = function (name, key) {
34
22
  var segmentValues = this.segmentCache[name];
@@ -62,14 +50,12 @@ var SegmentsCacheInMemory = /** @class */ (function (_super) {
62
50
  return acum + _this.segmentCache[segmentName].size;
63
51
  }, 0);
64
52
  };
65
- SegmentsCacheInMemory.prototype.setChangeNumber = function (name, changeNumber) {
66
- this.segmentChangeNumber[name] = changeNumber;
67
- return true;
68
- };
69
53
  SegmentsCacheInMemory.prototype.getChangeNumber = function (name) {
70
54
  var value = this.segmentChangeNumber[name];
71
55
  return (0, lang_1.isIntegerNumber)(value) ? value : -1;
72
56
  };
57
+ // No-op. Not used in server-side
58
+ SegmentsCacheInMemory.prototype.resetSegments = function () { return false; };
73
59
  return SegmentsCacheInMemory;
74
- }(AbstractSegmentsCacheSync_1.AbstractSegmentsCacheSync));
60
+ }());
75
61
  exports.SegmentsCacheInMemory = SegmentsCacheInMemory;
@@ -6,7 +6,6 @@ var AbstractSplitsCacheSync_1 = require("../AbstractSplitsCacheSync");
6
6
  var lang_1 = require("../../utils/lang");
7
7
  /**
8
8
  * Default ISplitsCacheSync implementation that stores split definitions in memory.
9
- * Supported by all JS runtimes.
10
9
  */
11
10
  var SplitsCacheInMemory = /** @class */ (function (_super) {
12
11
  (0, tslib_1.__extends)(SplitsCacheInMemory, _super);
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UniqueKeysCacheInMemory = exports.fromUniqueKeysCollector = void 0;
4
4
  var constants_1 = require("../inRedis/constants");
5
+ var sets_1 = require("../../utils/lang/sets");
5
6
  /**
6
7
  * Converts `uniqueKeys` data from cache into request payload for SS.
7
8
  */
@@ -10,7 +11,7 @@ function fromUniqueKeysCollector(uniqueKeys) {
10
11
  var featureNames = Object.keys(uniqueKeys);
11
12
  for (var i = 0; i < featureNames.length; i++) {
12
13
  var featureName = featureNames[i];
13
- var userKeys = Array.from(uniqueKeys[featureName]);
14
+ var userKeys = (0, sets_1.setToArray)(uniqueKeys[featureName]);
14
15
  var uniqueKeysPayload = {
15
16
  f: featureName,
16
17
  ks: userKeys
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UniqueKeysCacheInMemoryCS = void 0;
4
4
  var constants_1 = require("../inRedis/constants");
5
+ var sets_1 = require("../../utils/lang/sets");
5
6
  var UniqueKeysCacheInMemoryCS = /** @class */ (function () {
6
7
  /**
7
8
  *
@@ -61,7 +62,7 @@ var UniqueKeysCacheInMemoryCS = /** @class */ (function () {
61
62
  var userKeys = Object.keys(uniqueKeys);
62
63
  for (var k = 0; k < userKeys.length; k++) {
63
64
  var userKey = userKeys[k];
64
- var featureNames = Array.from(uniqueKeys[userKey]);
65
+ var featureNames = (0, sets_1.setToArray)(uniqueKeys[userKey]);
65
66
  var uniqueKeysPayload = {
66
67
  k: userKey,
67
68
  fs: featureNames
@@ -6,6 +6,7 @@ var ioredis_1 = (0, tslib_1.__importDefault)(require("ioredis"));
6
6
  var lang_1 = require("../../utils/lang");
7
7
  var thenable_1 = require("../../utils/promise/thenable");
8
8
  var timeout_1 = require("../../utils/promise/timeout");
9
+ var sets_1 = require("../../utils/lang/sets");
9
10
  var LOG_PREFIX = 'storage:redis-adapter: ';
10
11
  // If we ever decide to fully wrap every method, there's a Commander.getBuiltinCommands from ioredis.
11
12
  var METHODS_TO_PROMISE_WRAP = ['set', 'exec', 'del', 'get', 'keys', 'sadd', 'srem', 'sismember', 'smembers', 'incr', 'rpush', 'expire', 'mget', 'lrange', 'ltrim', 'hset', 'hincrby', 'popNRaw'];
@@ -128,7 +129,7 @@ var RedisAdapter = /** @class */ (function (_super) {
128
129
  setTimeout(function deferredDisconnect() {
129
130
  if (instance._runningCommands.size > 0) {
130
131
  instance.log.info(LOG_PREFIX + ("Attempting to disconnect but there are " + instance._runningCommands.size + " commands still waiting for resolution. Defering disconnection until those finish."));
131
- Promise.all(Array.from(instance._runningCommands))
132
+ Promise.all((0, sets_1.setToArray)(instance._runningCommands))
132
133
  .then(function () {
133
134
  instance.log.debug(LOG_PREFIX + 'Pending commands finished successfully, disconnecting.');
134
135
  originalMethod.apply(instance, params);
@@ -9,30 +9,24 @@ var SegmentsCacheInRedis = /** @class */ (function () {
9
9
  this.redis = redis;
10
10
  this.keys = keys;
11
11
  }
12
- SegmentsCacheInRedis.prototype.addToSegment = function (name, segmentKeys) {
12
+ /**
13
+ * Update the given segment `name` with the lists of `addedKeys`, `removedKeys` and `changeNumber`.
14
+ * The returned promise is resolved if the operation success, with `true` if the segment was updated (i.e., some key was added or removed),
15
+ * or rejected if it fails (e.g., Redis operation fails).
16
+ */
17
+ SegmentsCacheInRedis.prototype.update = function (name, addedKeys, removedKeys, changeNumber) {
13
18
  var segmentKey = this.keys.buildSegmentNameKey(name);
14
- if (segmentKeys.length) {
15
- return this.redis.sadd(segmentKey, segmentKeys).then(function () { return true; });
16
- }
17
- else {
18
- return Promise.resolve(true);
19
- }
20
- };
21
- SegmentsCacheInRedis.prototype.removeFromSegment = function (name, segmentKeys) {
22
- var segmentKey = this.keys.buildSegmentNameKey(name);
23
- if (segmentKeys.length) {
24
- return this.redis.srem(segmentKey, segmentKeys).then(function () { return true; });
25
- }
26
- else {
27
- return Promise.resolve(true);
28
- }
19
+ return Promise.all([
20
+ addedKeys.length && this.redis.sadd(segmentKey, addedKeys),
21
+ removedKeys.length && this.redis.srem(segmentKey, removedKeys),
22
+ this.redis.set(this.keys.buildSegmentTillKey(name), changeNumber + '')
23
+ ]).then(function () {
24
+ return addedKeys.length > 0 || removedKeys.length > 0;
25
+ });
29
26
  };
30
27
  SegmentsCacheInRedis.prototype.isInSegment = function (name, key) {
31
28
  return this.redis.sismember(this.keys.buildSegmentNameKey(name), key).then(function (matches) { return matches !== 0; });
32
29
  };
33
- SegmentsCacheInRedis.prototype.setChangeNumber = function (name, changeNumber) {
34
- return this.redis.set(this.keys.buildSegmentTillKey(name), changeNumber + '').then(function (status) { return status === 'OK'; });
35
- };
36
30
  SegmentsCacheInRedis.prototype.getChangeNumber = function (name) {
37
31
  var _this = this;
38
32
  return this.redis.get(this.keys.buildSegmentTillKey(name)).then(function (value) {
@@ -5,6 +5,7 @@ var tslib_1 = require("tslib");
5
5
  var UniqueKeysCacheInMemory_1 = require("../inMemory/UniqueKeysCacheInMemory");
6
6
  var constants_1 = require("./constants");
7
7
  var constants_2 = require("./constants");
8
+ var sets_1 = require("../../utils/lang/sets");
8
9
  var UniqueKeysCacheInRedis = /** @class */ (function (_super) {
9
10
  (0, tslib_1.__extends)(UniqueKeysCacheInRedis, _super);
10
11
  function UniqueKeysCacheInRedis(log, key, redis, uniqueKeysQueueSize, refreshRate) {
@@ -24,7 +25,7 @@ var UniqueKeysCacheInRedis = /** @class */ (function (_super) {
24
25
  if (!featureNames.length)
25
26
  return Promise.resolve(false);
26
27
  var uniqueKeysArray = featureNames.map(function (featureName) {
27
- var featureKeys = Array.from(_this.uniqueKeysTracker[featureName]);
28
+ var featureKeys = (0, sets_1.setToArray)(_this.uniqueKeysTracker[featureName]);
28
29
  var uniqueKeysPayload = {
29
30
  f: featureName,
30
31
  ks: featureKeys
@@ -15,32 +15,19 @@ var SegmentsCachePluggable = /** @class */ (function () {
15
15
  this.wrapper = wrapper;
16
16
  }
17
17
  /**
18
- * Add a list of `segmentKeys` to the given segment `name`.
19
- * The returned promise is resolved when the operation success
20
- * or rejected if wrapper operation fails.
21
- */
22
- SegmentsCachePluggable.prototype.addToSegment = function (name, segmentKeys) {
23
- var segmentKey = this.keys.buildSegmentNameKey(name);
24
- if (segmentKeys.length) {
25
- return this.wrapper.addItems(segmentKey, segmentKeys);
26
- }
27
- else {
28
- return Promise.resolve();
29
- }
30
- };
31
- /**
32
- * Remove a list of `segmentKeys` from the given segment `name`.
33
- * The returned promise is resolved when the operation success
34
- * or rejected if wrapper operation fails.
18
+ * Update the given segment `name` with the lists of `addedKeys`, `removedKeys` and `changeNumber`.
19
+ * The returned promise is resolved if the operation success, with `true` if the segment was updated (i.e., some key was added or removed),
20
+ * or rejected if it fails (e.g., wrapper operation fails).
35
21
  */
36
- SegmentsCachePluggable.prototype.removeFromSegment = function (name, segmentKeys) {
22
+ SegmentsCachePluggable.prototype.update = function (name, addedKeys, removedKeys, changeNumber) {
37
23
  var segmentKey = this.keys.buildSegmentNameKey(name);
38
- if (segmentKeys.length) {
39
- return this.wrapper.removeItems(segmentKey, segmentKeys);
40
- }
41
- else {
42
- return Promise.resolve();
43
- }
24
+ return Promise.all([
25
+ addedKeys.length && this.wrapper.addItems(segmentKey, addedKeys),
26
+ removedKeys.length && this.wrapper.removeItems(segmentKey, removedKeys),
27
+ this.wrapper.set(this.keys.buildSegmentTillKey(name), changeNumber + '')
28
+ ]).then(function () {
29
+ return addedKeys.length > 0 || removedKeys.length > 0;
30
+ });
44
31
  };
45
32
  /**
46
33
  * Returns a promise that resolves with a boolean value indicating if `key` is part of `name` segment.
@@ -49,14 +36,6 @@ var SegmentsCachePluggable = /** @class */ (function () {
49
36
  SegmentsCachePluggable.prototype.isInSegment = function (name, key) {
50
37
  return this.wrapper.itemContains(this.keys.buildSegmentNameKey(name), key);
51
38
  };
52
- /**
53
- * Set till number for the given segment `name`.
54
- * The returned promise is resolved when the operation success,
55
- * or rejected if it fails (e.g., wrapper operation fails).
56
- */
57
- SegmentsCachePluggable.prototype.setChangeNumber = function (name, changeNumber) {
58
- return this.wrapper.set(this.keys.buildSegmentTillKey(name), changeNumber + '');
59
- };
60
39
  /**
61
40
  * Get till number or -1 if it's not defined.
62
41
  * The returned promise is resolved with the changeNumber or -1 if it doesn't exist or a wrapper operation fails.
@@ -5,6 +5,7 @@ var tslib_1 = require("tslib");
5
5
  var UniqueKeysCacheInMemory_1 = require("../inMemory/UniqueKeysCacheInMemory");
6
6
  var constants_1 = require("../inRedis/constants");
7
7
  var constants_2 = require("./constants");
8
+ var sets_1 = require("../../utils/lang/sets");
8
9
  var UniqueKeysCachePluggable = /** @class */ (function (_super) {
9
10
  (0, tslib_1.__extends)(UniqueKeysCachePluggable, _super);
10
11
  function UniqueKeysCachePluggable(log, key, wrapper, uniqueKeysQueueSize, refreshRate) {
@@ -24,7 +25,7 @@ var UniqueKeysCachePluggable = /** @class */ (function (_super) {
24
25
  if (!featureNames.length)
25
26
  return Promise.resolve(false);
26
27
  var uniqueKeysArray = featureNames.map(function (featureName) {
27
- var featureKeys = Array.from(_this.uniqueKeysTracker[featureName]);
28
+ var featureKeys = (0, sets_1.setToArray)(_this.uniqueKeysTracker[featureName]);
28
29
  var uniqueKeysPayload = {
29
30
  f: featureName,
30
31
  ks: featureKeys