@splitsoftware/splitio-commons 2.4.2-rc.1 → 2.4.2-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.txt +13 -1
- package/cjs/logger/messages/error.js +1 -1
- package/cjs/sdkClient/sdkClient.js +0 -1
- package/cjs/sdkFactory/index.js +3 -10
- package/cjs/services/splitHttpClient.js +1 -1
- package/cjs/storages/AbstractSplitsCacheSync.js +5 -1
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +17 -17
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +33 -37
- package/cjs/storages/inLocalStorage/index.js +31 -13
- package/cjs/storages/inLocalStorage/storageAdapter.js +54 -0
- package/cjs/storages/inLocalStorage/validateCache.js +28 -23
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
- package/cjs/sync/polling/pollingManagerCS.js +5 -4
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +5 -2
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +3 -1
- package/cjs/sync/syncManagerOnline.js +31 -26
- package/cjs/trackers/impressionsTracker.js +4 -4
- package/cjs/utils/env/isLocalStorageAvailable.js +28 -5
- package/cjs/utils/settingsValidation/splitFilters.js +0 -6
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/esm/logger/messages/error.js +1 -1
- package/esm/sdkClient/sdkClient.js +0 -1
- package/esm/sdkFactory/index.js +3 -10
- package/esm/services/splitHttpClient.js +1 -1
- package/esm/storages/AbstractSplitsCacheSync.js +3 -0
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +17 -17
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +33 -37
- package/esm/storages/inLocalStorage/index.js +32 -14
- package/esm/storages/inLocalStorage/storageAdapter.js +50 -0
- package/esm/storages/inLocalStorage/validateCache.js +28 -23
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
- package/esm/sync/polling/pollingManagerCS.js +5 -4
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +5 -2
- package/esm/sync/polling/updaters/splitChangesUpdater.js +3 -1
- package/esm/sync/syncManagerOnline.js +31 -26
- package/esm/trackers/impressionsTracker.js +4 -4
- package/esm/utils/env/isLocalStorageAvailable.js +24 -3
- package/esm/utils/settingsValidation/splitFilters.js +0 -6
- package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
- package/package.json +1 -1
- package/src/logger/messages/error.ts +1 -1
- package/src/sdkClient/sdkClient.ts +0 -1
- package/src/sdkFactory/index.ts +3 -13
- package/src/services/splitHttpClient.ts +1 -1
- package/src/storages/AbstractSplitsCacheSync.ts +5 -1
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +18 -17
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +19 -18
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +34 -37
- package/src/storages/inLocalStorage/index.ts +37 -16
- package/src/storages/inLocalStorage/storageAdapter.ts +62 -0
- package/src/storages/inLocalStorage/validateCache.ts +29 -23
- package/src/storages/types.ts +19 -1
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +1 -2
- package/src/sync/polling/pollingManagerCS.ts +5 -4
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +5 -2
- package/src/sync/polling/updaters/splitChangesUpdater.ts +4 -2
- package/src/sync/syncManagerOnline.ts +30 -24
- package/src/trackers/impressionsTracker.ts +3 -3
- package/src/utils/env/isLocalStorageAvailable.ts +24 -3
- package/src/utils/settingsValidation/splitFilters.ts +0 -6
- package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
- package/types/splitio.d.ts +72 -16
|
@@ -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;
|
|
16
16
|
// Check expiration
|
|
17
|
-
var lastUpdatedTimestamp = parseInt(
|
|
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 =
|
|
28
|
+
var storageHash = storage.getItem(storageHashKey);
|
|
29
29
|
var currentStorageHash = (0, KeyBuilder_1.getStorageHash)(settings);
|
|
30
30
|
if (storageHash !== currentStorageHash) {
|
|
31
31
|
try {
|
|
32
|
-
|
|
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(
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
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 (
|
|
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);
|
|
@@ -7,6 +7,7 @@ var splitsSyncTask_1 = require("./syncTasks/splitsSyncTask");
|
|
|
7
7
|
var key_1 = require("../../utils/key");
|
|
8
8
|
var constants_1 = require("../../readiness/constants");
|
|
9
9
|
var constants_2 = require("../../logger/constants");
|
|
10
|
+
var AbstractSplitsCacheSync_1 = require("../../storages/AbstractSplitsCacheSync");
|
|
10
11
|
/**
|
|
11
12
|
* Expose start / stop mechanism for polling data from services.
|
|
12
13
|
* For client-side API with multiple clients.
|
|
@@ -34,7 +35,7 @@ function pollingManagerCSFactory(params) {
|
|
|
34
35
|
readiness.splits.on(constants_1.SDK_SPLITS_ARRIVED, function () {
|
|
35
36
|
if (!splitsSyncTask.isRunning())
|
|
36
37
|
return; // noop if not doing polling
|
|
37
|
-
var usingSegments =
|
|
38
|
+
var usingSegments = (0, AbstractSplitsCacheSync_1.usesSegmentsSync)(storage);
|
|
38
39
|
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
39
40
|
log.info(constants_2.POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
40
41
|
if (usingSegments) {
|
|
@@ -49,10 +50,10 @@ function pollingManagerCSFactory(params) {
|
|
|
49
50
|
var mySegmentsSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(splitApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
50
51
|
// smart ready
|
|
51
52
|
function smartReady() {
|
|
52
|
-
if (!readiness.isReady() && !
|
|
53
|
+
if (!readiness.isReady() && !(0, AbstractSplitsCacheSync_1.usesSegmentsSync)(storage))
|
|
53
54
|
readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED);
|
|
54
55
|
}
|
|
55
|
-
if (!
|
|
56
|
+
if (!(0, AbstractSplitsCacheSync_1.usesSegmentsSync)(storage))
|
|
56
57
|
setTimeout(smartReady, 0);
|
|
57
58
|
else
|
|
58
59
|
readiness.splits.once(constants_1.SDK_SPLITS_ARRIVED, smartReady);
|
|
@@ -66,7 +67,7 @@ function pollingManagerCSFactory(params) {
|
|
|
66
67
|
start: function () {
|
|
67
68
|
log.info(constants_2.POLLING_START);
|
|
68
69
|
splitsSyncTask.start();
|
|
69
|
-
if (
|
|
70
|
+
if ((0, AbstractSplitsCacheSync_1.usesSegmentsSync)(storage))
|
|
70
71
|
startMySegmentsSyncTasks();
|
|
71
72
|
},
|
|
72
73
|
// Stop periodic fetching (polling)
|
|
@@ -5,6 +5,7 @@ var timeout_1 = require("../../../utils/promise/timeout");
|
|
|
5
5
|
var constants_1 = require("../../../readiness/constants");
|
|
6
6
|
var constants_2 = require("../../../logger/constants");
|
|
7
7
|
var constants_3 = require("../../streaming/constants");
|
|
8
|
+
var AbstractSplitsCacheSync_1 = require("../../../storages/AbstractSplitsCacheSync");
|
|
8
9
|
/**
|
|
9
10
|
* factory of MySegments updater, a task that:
|
|
10
11
|
* - fetches mySegments using `mySegmentsFetcher`
|
|
@@ -12,7 +13,7 @@ var constants_3 = require("../../streaming/constants");
|
|
|
12
13
|
* - uses `segmentsEventEmitter` to emit events related to segments data updates
|
|
13
14
|
*/
|
|
14
15
|
function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmentsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, matchingKey) {
|
|
15
|
-
var
|
|
16
|
+
var segments = storage.segments, largeSegments = storage.largeSegments;
|
|
16
17
|
var readyOnAlreadyExistentState = true;
|
|
17
18
|
var startingUp = true;
|
|
18
19
|
/** timeout and telemetry decorator for `splitChangesFetcher` promise */
|
|
@@ -33,8 +34,10 @@ function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmentsEvent
|
|
|
33
34
|
shouldNotifyUpdate = segments.resetSegments(segmentsData.ms || {});
|
|
34
35
|
shouldNotifyUpdate = largeSegments.resetSegments(segmentsData.ls || {}) || shouldNotifyUpdate;
|
|
35
36
|
}
|
|
37
|
+
if (storage.save)
|
|
38
|
+
storage.save();
|
|
36
39
|
// Notify update if required
|
|
37
|
-
if ((
|
|
40
|
+
if ((0, AbstractSplitsCacheSync_1.usesSegmentsSync)(storage) && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
|
|
38
41
|
readyOnAlreadyExistentState = false;
|
|
39
42
|
segmentsEventEmitter.emit(constants_1.SDK_SEGMENTS_ARRIVED);
|
|
40
43
|
}
|
|
@@ -46,7 +46,7 @@ function parseSegments(ruleEntity, matcherType) {
|
|
|
46
46
|
exports.parseSegments = parseSegments;
|
|
47
47
|
/**
|
|
48
48
|
* If there are defined filters and one feature flag doesn't match with them, its status is changed to 'ARCHIVE' to avoid storing it
|
|
49
|
-
* If there
|
|
49
|
+
* If there is `bySet` filter, `byName` and `byPrefix` filters are ignored
|
|
50
50
|
*
|
|
51
51
|
* @param featureFlag - feature flag to be evaluated
|
|
52
52
|
* @param filters - splitFiltersValidation bySet | byName
|
|
@@ -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))))
|
|
@@ -7,6 +7,7 @@ var constants_2 = require("../logger/constants");
|
|
|
7
7
|
var consent_1 = require("../consent");
|
|
8
8
|
var constants_3 = require("../utils/constants");
|
|
9
9
|
var constants_4 = require("../readiness/constants");
|
|
10
|
+
var AbstractSplitsCacheSync_1 = require("../storages/AbstractSplitsCacheSync");
|
|
10
11
|
/**
|
|
11
12
|
* Online SyncManager factory.
|
|
12
13
|
* Can be used for server-side API, and client-side API with or without multiple clients.
|
|
@@ -68,35 +69,39 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
68
69
|
*/
|
|
69
70
|
start: function () {
|
|
70
71
|
running = true;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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();
|
|
84
95
|
}
|
|
85
|
-
pushManager.start();
|
|
86
96
|
}
|
|
87
97
|
else {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
else {
|
|
92
|
-
if (startFirstTime) {
|
|
93
|
-
pollingManager.syncAll();
|
|
98
|
+
if (startFirstTime) {
|
|
99
|
+
pollingManager.syncAll();
|
|
100
|
+
}
|
|
94
101
|
}
|
|
95
102
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
submitterManager.start(!(0, consent_1.isConsentGranted)(settings));
|
|
99
|
-
startFirstTime = false;
|
|
103
|
+
startFirstTime = false;
|
|
104
|
+
});
|
|
100
105
|
},
|
|
101
106
|
/**
|
|
102
107
|
* Method used to stop/pause the syncManager.
|
|
@@ -130,7 +135,7 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
130
135
|
if (pushManager) {
|
|
131
136
|
if (pollingManager.isRunning()) {
|
|
132
137
|
// if doing polling, we must start the periodic fetch of data
|
|
133
|
-
if (
|
|
138
|
+
if ((0, AbstractSplitsCacheSync_1.usesSegmentsSync)(storage))
|
|
134
139
|
mySegmentsSyncTask.start();
|
|
135
140
|
}
|
|
136
141
|
else {
|
|
@@ -140,7 +145,7 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
140
145
|
}
|
|
141
146
|
}
|
|
142
147
|
else {
|
|
143
|
-
if (
|
|
148
|
+
if ((0, AbstractSplitsCacheSync_1.usesSegmentsSync)(storage))
|
|
144
149
|
mySegmentsSyncTask.start();
|
|
145
150
|
}
|
|
146
151
|
}
|
|
@@ -9,7 +9,7 @@ var constants_2 = require("../utils/constants");
|
|
|
9
9
|
* Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided.
|
|
10
10
|
*/
|
|
11
11
|
function impressionsTrackerFactory(settings, impressionsCache, noneStrategy, strategy, whenInit, integrationsManager, telemetryCache) {
|
|
12
|
-
var log = settings.log, _a = settings.runtime, ip = _a.ip, hostname = _a.hostname, version = settings.version;
|
|
12
|
+
var log = settings.log, impressionListener = settings.impressionListener, _a = settings.runtime, ip = _a.ip, hostname = _a.hostname, version = settings.version;
|
|
13
13
|
return {
|
|
14
14
|
track: function (impressions, attributes) {
|
|
15
15
|
if (settings.userConsent === constants_2.CONSENT_DECLINED)
|
|
@@ -42,7 +42,7 @@ function impressionsTrackerFactory(settings, impressionsCache, noneStrategy, str
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
// @TODO next block might be handled by the integration manager. In that case, the metadata object doesn't need to be passed in the constructor
|
|
45
|
-
if (
|
|
45
|
+
if (impressionListener || integrationsManager) {
|
|
46
46
|
var _loop_1 = function (i) {
|
|
47
47
|
var impressionData = {
|
|
48
48
|
// copy of impression, to avoid unexpected behavior if modified by integrations or impressionListener
|
|
@@ -59,8 +59,8 @@ function impressionsTrackerFactory(settings, impressionsCache, noneStrategy, str
|
|
|
59
59
|
if (integrationsManager)
|
|
60
60
|
integrationsManager.handleImpression(impressionData);
|
|
61
61
|
try { // @ts-ignore. An exception on the listeners should not break the SDK.
|
|
62
|
-
if (
|
|
63
|
-
|
|
62
|
+
if (impressionListener)
|
|
63
|
+
impressionListener.logImpression(impressionData);
|
|
64
64
|
}
|
|
65
65
|
catch (err) {
|
|
66
66
|
log.error(constants_1.ERROR_IMPRESSIONS_LISTENER, [err]);
|
|
@@ -1,16 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isLocalStorageAvailable = void 0;
|
|
4
|
-
/* eslint-disable no-undef */
|
|
3
|
+
exports.isWebStorage = exports.isValidStorageWrapper = exports.isLocalStorageAvailable = void 0;
|
|
5
4
|
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) {
|
|
6
15
|
var mod = '__SPLITSOFTWARE__';
|
|
7
16
|
try {
|
|
8
|
-
|
|
9
|
-
|
|
17
|
+
wrapper.setItem(mod, mod);
|
|
18
|
+
wrapper.getItem(mod);
|
|
19
|
+
wrapper.removeItem(mod);
|
|
10
20
|
return true;
|
|
11
21
|
}
|
|
12
22
|
catch (e) {
|
|
13
23
|
return false;
|
|
14
24
|
}
|
|
15
25
|
}
|
|
16
|
-
exports.
|
|
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;
|
|
@@ -61,12 +61,6 @@ function validateSplitFilter(log, type, values, maxLength) {
|
|
|
61
61
|
/**
|
|
62
62
|
* Returns a string representing the URL encoded query component of /splitChanges URL.
|
|
63
63
|
*
|
|
64
|
-
* The possible formats of the query string are:
|
|
65
|
-
* - null: if all filters are empty
|
|
66
|
-
* - '&names=<comma-separated-values>': if only `byPrefix` filter is undefined
|
|
67
|
-
* - '&prefixes=<comma-separated-values>': if only `byName` filter is undefined
|
|
68
|
-
* - '&names=<comma-separated-values>&prefixes=<comma-separated-values>': if no one is undefined
|
|
69
|
-
*
|
|
70
64
|
* @param groupedFilters - object of filters. Each filter must be a list of valid, unique and ordered string values.
|
|
71
65
|
* @returns null or string with the `split filter query` component of the URL.
|
|
72
66
|
*/
|
|
@@ -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;
|
|
@@ -13,7 +13,7 @@ export var codesError = [
|
|
|
13
13
|
[c.ERROR_SYNC_OFFLINE_LOADING, c.LOG_PREFIX_SYNC_OFFLINE + 'There was an issue loading the mock feature flags data. No changes will be applied to the current cache. %s'],
|
|
14
14
|
[c.ERROR_STREAMING_SSE, c.LOG_PREFIX_SYNC_STREAMING + 'Failed to connect or error on streaming connection, with error message: %s'],
|
|
15
15
|
[c.ERROR_STREAMING_AUTH, c.LOG_PREFIX_SYNC_STREAMING + 'Failed to authenticate for streaming. Error: %s.'],
|
|
16
|
-
[c.ERROR_HTTP, '
|
|
16
|
+
[c.ERROR_HTTP, 'HTTP request failed with %s. URL: %s. Message: %s'],
|
|
17
17
|
// client status
|
|
18
18
|
[c.ERROR_CLIENT_LISTENER, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'],
|
|
19
19
|
[c.ERROR_CLIENT_DESTROYED, '%s: Client has already been destroyed - no calls possible.'],
|
|
@@ -35,7 +35,6 @@ export function sdkClientFactory(params, isSharedClient) {
|
|
|
35
35
|
clientInputValidationDecorator(settings, clientFactory(params), sdkReadinessManager.readinessManager),
|
|
36
36
|
// Sdk destroy
|
|
37
37
|
{
|
|
38
|
-
__ctx: params,
|
|
39
38
|
flush: function () {
|
|
40
39
|
// @TODO define cooldown time
|
|
41
40
|
return __cooldown(__flush, COOLDOWN_TIME_IN_MILLIS);
|
package/esm/sdkFactory/index.js
CHANGED
|
@@ -84,7 +84,8 @@ export function sdkFactory(params) {
|
|
|
84
84
|
initCallbacks.length = 0;
|
|
85
85
|
}
|
|
86
86
|
log.info(NEW_FACTORY);
|
|
87
|
-
|
|
87
|
+
// @ts-ignore
|
|
88
|
+
return objectAssign({
|
|
88
89
|
// Split evaluation and event tracking engine
|
|
89
90
|
client: clientMethod,
|
|
90
91
|
// Manager API to explore available information
|
|
@@ -98,14 +99,6 @@ export function sdkFactory(params) {
|
|
|
98
99
|
destroy: function () {
|
|
99
100
|
hasInit = false;
|
|
100
101
|
return Promise.all(Object.keys(clients).map(function (key) { return clients[key].destroy(); })).then(function () { });
|
|
101
|
-
}
|
|
102
|
-
__ctx: ctx
|
|
102
|
+
}
|
|
103
103
|
}, extraProps && extraProps(ctx), lazyInit ? { init: init } : init());
|
|
104
|
-
// append factory to global
|
|
105
|
-
if (typeof window === 'object') { // @ts-ignore
|
|
106
|
-
// eslint-disable-next-line no-undef
|
|
107
|
-
(window.__HARNESS_FME__ = window.__HARNESS_FME__ || []).push(factory);
|
|
108
|
-
}
|
|
109
|
-
// @ts-ignore
|
|
110
|
-
return factory;
|
|
111
104
|
}
|
|
@@ -66,7 +66,7 @@ export function splitHttpClientFactory(settings, _a) {
|
|
|
66
66
|
msg = error.message || 'Network Error';
|
|
67
67
|
}
|
|
68
68
|
if (!resp || resp.status !== 403) { // 403's log we'll be handled somewhere else.
|
|
69
|
-
log[logErrorsAsInfo ? 'info' : 'error'](ERROR_HTTP, [resp ? resp.status : '
|
|
69
|
+
log[logErrorsAsInfo ? 'info' : 'error'](ERROR_HTTP, [resp ? 'status code ' + resp.status : 'no status code', url, msg]);
|
|
70
70
|
}
|
|
71
71
|
var networkError = new Error(msg);
|
|
72
72
|
// passes `undefined` as statusCode if not an HTTP error (resp === undefined)
|
|
@@ -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 (
|
|
18
|
+
if (this.storage.getItem(segmentKey) === DEFINED)
|
|
18
19
|
return false;
|
|
19
|
-
|
|
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 (
|
|
31
|
+
if (this.storage.getItem(segmentKey) !== DEFINED)
|
|
31
32
|
return false;
|
|
32
|
-
|
|
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
|
|
42
|
+
return this.storage.getItem(this.keys.buildSegmentNameKey(name)) === DEFINED;
|
|
42
43
|
};
|
|
43
44
|
MySegmentsCacheInLocal.prototype.getRegisteredSegments = function () {
|
|
44
|
-
var
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
50
|
-
|
|
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
|
-
|
|
59
|
+
this.storage.setItem(this.keys.buildTillKey(), changeNumber + '');
|
|
60
60
|
else
|
|
61
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
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(
|
|
33
|
-
// @ts-expect-error
|
|
33
|
+
var count = toNumber(this.storage.getItem(segmentsCountKey)) + diff;
|
|
34
34
|
if (count > 0)
|
|
35
|
-
|
|
35
|
+
this.storage.setItem(segmentsCountKey, count + '');
|
|
36
36
|
else
|
|
37
|
-
|
|
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
|
|
44
|
-
var previous =
|
|
45
|
-
|
|
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
|
-
|
|
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 =
|
|
76
|
+
var len = this.storage.length;
|
|
77
77
|
var accum = [];
|
|
78
78
|
var cur = 0;
|
|
79
79
|
while (cur < len) {
|
|
80
|
-
var key =
|
|
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 =
|
|
88
|
+
var item = this.storage.getItem(this.keys.buildRBSegmentKey(name));
|
|
89
89
|
return item && JSON.parse(item);
|
|
90
90
|
};
|
|
91
91
|
RBSegmentsCacheInLocal.prototype.contains = function (names) {
|
|
@@ -95,7 +95,7 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
|
|
|
95
95
|
};
|
|
96
96
|
RBSegmentsCacheInLocal.prototype.getChangeNumber = function () {
|
|
97
97
|
var n = -1;
|
|
98
|
-
var value =
|
|
98
|
+
var value = this.storage.getItem(this.keys.buildRBSegmentsTillKey());
|
|
99
99
|
if (value !== null) {
|
|
100
100
|
value = parseInt(value, 10);
|
|
101
101
|
return isNaNNumber(value) ? n : value;
|
|
@@ -103,7 +103,7 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
|
|
|
103
103
|
return n;
|
|
104
104
|
};
|
|
105
105
|
RBSegmentsCacheInLocal.prototype.usesSegments = function () {
|
|
106
|
-
var storedCount =
|
|
106
|
+
var storedCount = this.storage.getItem(this.keys.buildSplitsWithSegmentCountKey());
|
|
107
107
|
var splitsWithSegmentsCount = storedCount === null ? 0 : toNumber(storedCount);
|
|
108
108
|
return isFiniteNumber(splitsWithSegmentsCount) ?
|
|
109
109
|
splitsWithSegmentsCount > 0 :
|