@splitsoftware/splitio-commons 2.1.0-rc.2 → 2.1.1-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.
- package/CHANGES.txt +2 -7
- package/README.md +1 -0
- package/cjs/evaluator/combiners/and.js +2 -6
- package/cjs/evaluator/combiners/ifelseif.js +6 -6
- package/cjs/evaluator/condition/index.js +6 -5
- package/cjs/evaluator/index.js +7 -7
- package/cjs/evaluator/matchers/index.js +3 -1
- package/cjs/evaluator/matchers/matcherTypes.js +1 -0
- package/cjs/evaluator/matchers/rbsegment.js +43 -0
- package/cjs/evaluator/matchersTransform/index.js +4 -0
- package/cjs/evaluator/parser/index.js +2 -2
- package/cjs/evaluator/value/sanitize.js +1 -0
- package/cjs/logger/constants.js +5 -6
- package/cjs/logger/messages/debug.js +3 -4
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/readiness/readinessManager.js +0 -6
- package/cjs/services/splitApi.js +2 -2
- package/cjs/storages/AbstractSplitsCacheAsync.js +19 -1
- package/cjs/storages/AbstractSplitsCacheSync.js +17 -9
- package/cjs/storages/KeyBuilder.js +8 -15
- package/cjs/storages/KeyBuilderCS.js +11 -5
- package/cjs/storages/KeyBuilderSS.js +3 -0
- package/cjs/storages/dataLoader.js +3 -5
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +117 -0
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +69 -15
- package/cjs/storages/inLocalStorage/index.js +7 -5
- package/cjs/storages/inMemory/InMemoryStorage.js +3 -0
- package/cjs/storages/inMemory/InMemoryStorageCS.js +4 -0
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +61 -0
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +24 -31
- package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +64 -0
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +4 -21
- package/cjs/storages/inRedis/constants.js +1 -1
- package/cjs/storages/inRedis/index.js +2 -0
- package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +64 -0
- package/cjs/storages/pluggable/SplitsCachePluggable.js +2 -19
- package/cjs/storages/pluggable/index.js +3 -2
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +14 -16
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +2 -2
- package/cjs/sync/polling/pollingManagerCS.js +7 -7
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +1 -1
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +62 -51
- package/cjs/sync/streaming/SSEHandler/index.js +1 -0
- package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +106 -77
- package/cjs/sync/streaming/constants.js +2 -1
- package/cjs/sync/streaming/pushManager.js +3 -16
- package/cjs/sync/syncManagerOnline.js +5 -10
- package/cjs/trackers/uniqueKeysTracker.js +1 -1
- package/cjs/utils/constants/browser.js +5 -0
- package/cjs/utils/constants/index.js +3 -2
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/esm/evaluator/combiners/and.js +2 -6
- package/esm/evaluator/combiners/ifelseif.js +7 -7
- package/esm/evaluator/condition/index.js +6 -5
- package/esm/evaluator/index.js +7 -7
- package/esm/evaluator/matchers/index.js +3 -1
- package/esm/evaluator/matchers/matcherTypes.js +1 -0
- package/esm/evaluator/matchers/rbsegment.js +39 -0
- package/esm/evaluator/matchersTransform/index.js +4 -0
- package/esm/evaluator/parser/index.js +2 -2
- package/esm/evaluator/value/sanitize.js +1 -0
- package/esm/logger/constants.js +2 -3
- package/esm/logger/messages/debug.js +3 -4
- package/esm/logger/messages/warn.js +1 -1
- package/esm/readiness/readinessManager.js +0 -6
- package/esm/services/splitApi.js +2 -2
- package/esm/storages/AbstractSplitsCacheAsync.js +19 -1
- package/esm/storages/AbstractSplitsCacheSync.js +17 -9
- package/esm/storages/KeyBuilder.js +8 -15
- package/esm/storages/KeyBuilderCS.js +11 -5
- package/esm/storages/KeyBuilderSS.js +3 -0
- package/esm/storages/dataLoader.js +2 -4
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +114 -0
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +69 -15
- package/esm/storages/inLocalStorage/index.js +7 -5
- package/esm/storages/inMemory/InMemoryStorage.js +3 -0
- package/esm/storages/inMemory/InMemoryStorageCS.js +4 -0
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +58 -0
- package/esm/storages/inMemory/SplitsCacheInMemory.js +24 -31
- package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +61 -0
- package/esm/storages/inRedis/SplitsCacheInRedis.js +4 -21
- package/esm/storages/inRedis/constants.js +1 -1
- package/esm/storages/inRedis/index.js +2 -0
- package/esm/storages/pluggable/RBSegmentsCachePluggable.js +61 -0
- package/esm/storages/pluggable/SplitsCachePluggable.js +2 -19
- package/esm/storages/pluggable/index.js +3 -2
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +14 -16
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +2 -2
- package/esm/sync/polling/pollingManagerCS.js +7 -7
- package/esm/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +1 -1
- package/esm/sync/polling/updaters/splitChangesUpdater.js +63 -52
- package/esm/sync/streaming/SSEHandler/index.js +2 -1
- package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +102 -73
- package/esm/sync/streaming/constants.js +1 -0
- package/esm/sync/streaming/pushManager.js +6 -19
- package/esm/sync/syncManagerOnline.js +5 -10
- package/esm/trackers/uniqueKeysTracker.js +1 -1
- package/esm/utils/constants/browser.js +2 -0
- package/esm/utils/constants/index.js +2 -1
- package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
- package/package.json +1 -1
- package/src/dtos/types.ts +32 -8
- package/src/evaluator/Engine.ts +1 -1
- package/src/evaluator/combiners/and.ts +5 -4
- package/src/evaluator/combiners/ifelseif.ts +7 -9
- package/src/evaluator/condition/engineUtils.ts +1 -1
- package/src/evaluator/condition/index.ts +12 -12
- package/src/evaluator/index.ts +7 -7
- package/src/evaluator/matchers/index.ts +3 -1
- package/src/evaluator/matchers/matcherTypes.ts +1 -0
- package/src/evaluator/matchers/rbsegment.ts +61 -0
- package/src/evaluator/matchersTransform/index.ts +3 -0
- package/src/evaluator/parser/index.ts +3 -3
- package/src/evaluator/types.ts +2 -2
- package/src/evaluator/value/index.ts +2 -2
- package/src/evaluator/value/sanitize.ts +5 -4
- package/src/logger/constants.ts +2 -3
- package/src/logger/messages/debug.ts +3 -4
- package/src/logger/messages/warn.ts +1 -1
- package/src/readiness/readinessManager.ts +0 -5
- package/src/sdkManager/index.ts +1 -1
- package/src/services/splitApi.ts +2 -2
- package/src/services/types.ts +1 -1
- package/src/storages/AbstractSplitsCacheAsync.ts +23 -5
- package/src/storages/AbstractSplitsCacheSync.ts +22 -15
- package/src/storages/KeyBuilder.ts +9 -17
- package/src/storages/KeyBuilderCS.ts +13 -6
- package/src/storages/KeyBuilderSS.ts +4 -0
- package/src/storages/dataLoader.ts +2 -5
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +136 -0
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +80 -16
- package/src/storages/inLocalStorage/index.ts +12 -8
- package/src/storages/inMemory/InMemoryStorage.ts +3 -0
- package/src/storages/inMemory/InMemoryStorageCS.ts +4 -0
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +68 -0
- package/src/storages/inMemory/SplitsCacheInMemory.ts +22 -27
- package/src/storages/inRedis/RBSegmentsCacheInRedis.ts +79 -0
- package/src/storages/inRedis/SplitsCacheInRedis.ts +4 -21
- package/src/storages/inRedis/constants.ts +1 -1
- package/src/storages/inRedis/index.ts +2 -0
- package/src/storages/pluggable/RBSegmentsCachePluggable.ts +76 -0
- package/src/storages/pluggable/SplitsCachePluggable.ts +2 -19
- package/src/storages/pluggable/index.ts +3 -2
- package/src/storages/types.ts +47 -18
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +19 -21
- package/src/sync/polling/fetchers/splitChangesFetcher.ts +2 -1
- package/src/sync/polling/fetchers/types.ts +1 -0
- package/src/sync/polling/pollingManagerCS.ts +7 -7
- package/src/sync/polling/syncTasks/splitsSyncTask.ts +1 -2
- package/src/sync/polling/types.ts +2 -2
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +2 -2
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +1 -1
- package/src/sync/polling/updaters/splitChangesUpdater.ts +74 -63
- package/src/sync/streaming/SSEHandler/index.ts +2 -1
- package/src/sync/streaming/SSEHandler/types.ts +2 -2
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +98 -68
- package/src/sync/streaming/constants.ts +1 -0
- package/src/sync/streaming/parseUtils.ts +2 -2
- package/src/sync/streaming/pushManager.ts +6 -18
- package/src/sync/streaming/types.ts +3 -2
- package/src/sync/syncManagerOnline.ts +5 -11
- package/src/trackers/uniqueKeysTracker.ts +1 -1
- package/src/utils/constants/browser.ts +2 -0
- package/src/utils/constants/index.ts +2 -1
- package/src/utils/lang/index.ts +2 -2
- package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
- package/types/splitio.d.ts +1 -25
- package/cjs/storages/inLocalStorage/validateCache.js +0 -79
- package/esm/storages/inLocalStorage/validateCache.js +0 -75
- package/src/storages/inLocalStorage/validateCache.ts +0 -91
|
@@ -11,10 +11,10 @@ import { authenticateFactory, hashUserKey } from './AuthClient';
|
|
|
11
11
|
import { forOwn } from '../../utils/lang';
|
|
12
12
|
import { SSEClient } from './SSEClient';
|
|
13
13
|
import { getMatching } from '../../utils/key';
|
|
14
|
-
import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
|
|
15
|
-
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE
|
|
14
|
+
import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, RB_SEGMENT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
|
|
15
|
+
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE } from '../../logger/constants';
|
|
16
16
|
import { IMembershipMSUpdateData, IMembershipLSUpdateData, KeyList, UpdateStrategy } from './SSEHandler/types';
|
|
17
|
-
import { getDelay, isInBitmap, parseBitmap,
|
|
17
|
+
import { getDelay, isInBitmap, parseBitmap, parseKeyList } from './parseUtils';
|
|
18
18
|
import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
|
|
19
19
|
import { IAuthTokenPushEnabled } from './AuthClient/types';
|
|
20
20
|
import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
|
|
@@ -56,7 +56,7 @@ export function pushManagerFactory(
|
|
|
56
56
|
// MySegmentsUpdateWorker (client-side) are initiated in `add` method
|
|
57
57
|
const segmentsUpdateWorker = userKey ? undefined : SegmentsUpdateWorker(log, pollingManager.segmentsSyncTask as ISegmentsSyncTask, storage.segments);
|
|
58
58
|
// For server-side we pass the segmentsSyncTask, used by SplitsUpdateWorker to fetch new segments
|
|
59
|
-
const splitsUpdateWorker = SplitsUpdateWorker(log, storage
|
|
59
|
+
const splitsUpdateWorker = SplitsUpdateWorker(log, storage, pollingManager.splitsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
|
|
60
60
|
|
|
61
61
|
// [Only for client-side] map of hashes to user keys, to dispatch membership update events to the corresponding MySegmentsUpdateWorker
|
|
62
62
|
const userKeyHashes: Record<string, string> = {};
|
|
@@ -219,20 +219,8 @@ export function pushManagerFactory(
|
|
|
219
219
|
/** Functions related to synchronization (Queues and Workers in the spec) */
|
|
220
220
|
|
|
221
221
|
pushEmitter.on(SPLIT_KILL, splitsUpdateWorker.killSplit);
|
|
222
|
-
pushEmitter.on(SPLIT_UPDATE,
|
|
223
|
-
|
|
224
|
-
try {
|
|
225
|
-
const payload = parseFFUpdatePayload(parsedData.c, parsedData.d);
|
|
226
|
-
if (payload) {
|
|
227
|
-
splitsUpdateWorker.put(parsedData, payload);
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
} catch (e) {
|
|
231
|
-
log.warn(STREAMING_PARSING_SPLIT_UPDATE, [e]);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
splitsUpdateWorker.put(parsedData);
|
|
235
|
-
});
|
|
222
|
+
pushEmitter.on(SPLIT_UPDATE, splitsUpdateWorker.put);
|
|
223
|
+
pushEmitter.on(RB_SEGMENT_UPDATE, splitsUpdateWorker.put);
|
|
236
224
|
|
|
237
225
|
function handleMySegmentsUpdate(parsedData: IMembershipMSUpdateData | IMembershipLSUpdateData) {
|
|
238
226
|
switch (parsedData.u) {
|
|
@@ -16,18 +16,19 @@ export type MEMBERSHIPS_LS_UPDATE = 'MEMBERSHIPS_LS_UPDATE';
|
|
|
16
16
|
export type SEGMENT_UPDATE = 'SEGMENT_UPDATE';
|
|
17
17
|
export type SPLIT_KILL = 'SPLIT_KILL';
|
|
18
18
|
export type SPLIT_UPDATE = 'SPLIT_UPDATE';
|
|
19
|
+
export type RB_SEGMENT_UPDATE = 'RB_SEGMENT_UPDATE';
|
|
19
20
|
|
|
20
21
|
// Control-type push notifications, handled by NotificationKeeper
|
|
21
22
|
export type CONTROL = 'CONTROL';
|
|
22
23
|
export type OCCUPANCY = 'OCCUPANCY';
|
|
23
24
|
|
|
24
|
-
export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NONRETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MEMBERSHIPS_MS_UPDATE | MEMBERSHIPS_LS_UPDATE | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | ControlType.STREAMING_RESET
|
|
25
|
+
export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NONRETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MEMBERSHIPS_MS_UPDATE | MEMBERSHIPS_LS_UPDATE | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | RB_SEGMENT_UPDATE | ControlType.STREAMING_RESET
|
|
25
26
|
|
|
26
27
|
type IParsedData<T extends IPushEvent> =
|
|
27
28
|
T extends MEMBERSHIPS_MS_UPDATE ? IMembershipMSUpdateData :
|
|
28
29
|
T extends MEMBERSHIPS_LS_UPDATE ? IMembershipLSUpdateData :
|
|
29
30
|
T extends SEGMENT_UPDATE ? ISegmentUpdateData :
|
|
30
|
-
T extends SPLIT_UPDATE ? ISplitUpdateData :
|
|
31
|
+
T extends SPLIT_UPDATE | RB_SEGMENT_UPDATE ? ISplitUpdateData :
|
|
31
32
|
T extends SPLIT_KILL ? ISplitKillData : INotificationData;
|
|
32
33
|
|
|
33
34
|
/**
|
|
@@ -9,7 +9,6 @@ import { SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING } from '..
|
|
|
9
9
|
import { isConsentGranted } from '../consent';
|
|
10
10
|
import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
|
|
11
11
|
import { ISdkFactoryContextSync } from '../sdkFactory/types';
|
|
12
|
-
import { SDK_SPLITS_CACHE_LOADED } from '../readiness/constants';
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
14
|
* Online SyncManager factory.
|
|
@@ -29,7 +28,7 @@ export function syncManagerOnlineFactory(
|
|
|
29
28
|
*/
|
|
30
29
|
return function (params: ISdkFactoryContextSync): ISyncManagerCS {
|
|
31
30
|
|
|
32
|
-
const { settings, settings: { log, streamingEnabled, sync: { enabled: syncEnabled } },
|
|
31
|
+
const { settings, settings: { log, streamingEnabled, sync: { enabled: syncEnabled } }, telemetryTracker } = params;
|
|
33
32
|
|
|
34
33
|
/** Polling Manager */
|
|
35
34
|
const pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
@@ -88,11 +87,6 @@ export function syncManagerOnlineFactory(
|
|
|
88
87
|
start() {
|
|
89
88
|
running = true;
|
|
90
89
|
|
|
91
|
-
if (startFirstTime) {
|
|
92
|
-
const isCacheLoaded = storage.validateCache ? storage.validateCache() : false;
|
|
93
|
-
if (isCacheLoaded) Promise.resolve().then(() => { readiness.splits.emit(SDK_SPLITS_CACHE_LOADED); });
|
|
94
|
-
}
|
|
95
|
-
|
|
96
90
|
// start syncing splits and segments
|
|
97
91
|
if (pollingManager) {
|
|
98
92
|
|
|
@@ -102,6 +96,7 @@ export function syncManagerOnlineFactory(
|
|
|
102
96
|
// Doesn't call `syncAll` when the syncManager is resuming
|
|
103
97
|
if (startFirstTime) {
|
|
104
98
|
pollingManager.syncAll();
|
|
99
|
+
startFirstTime = false;
|
|
105
100
|
}
|
|
106
101
|
pushManager.start();
|
|
107
102
|
} else {
|
|
@@ -110,14 +105,13 @@ export function syncManagerOnlineFactory(
|
|
|
110
105
|
} else {
|
|
111
106
|
if (startFirstTime) {
|
|
112
107
|
pollingManager.syncAll();
|
|
108
|
+
startFirstTime = false;
|
|
113
109
|
}
|
|
114
110
|
}
|
|
115
111
|
}
|
|
116
112
|
|
|
117
113
|
// start periodic data recording (events, impressions, telemetry).
|
|
118
114
|
submitterManager.start(!isConsentGranted(settings));
|
|
119
|
-
|
|
120
|
-
startFirstTime = false;
|
|
121
115
|
},
|
|
122
116
|
|
|
123
117
|
/**
|
|
@@ -155,14 +149,14 @@ export function syncManagerOnlineFactory(
|
|
|
155
149
|
if (pushManager) {
|
|
156
150
|
if (pollingManager.isRunning()) {
|
|
157
151
|
// if doing polling, we must start the periodic fetch of data
|
|
158
|
-
if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
|
|
152
|
+
if (storage.splits.usesSegments() || storage.rbSegments.usesSegments()) mySegmentsSyncTask.start();
|
|
159
153
|
} else {
|
|
160
154
|
// if not polling, we must execute the sync task for the initial fetch
|
|
161
155
|
// of segments since `syncAll` was already executed when starting the main client
|
|
162
156
|
mySegmentsSyncTask.execute();
|
|
163
157
|
}
|
|
164
158
|
} else {
|
|
165
|
-
if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
|
|
159
|
+
if (storage.splits.usesSegments() || storage.rbSegments.usesSegments()) mySegmentsSyncTask.start();
|
|
166
160
|
}
|
|
167
161
|
} else {
|
|
168
162
|
if (!readinessManager.isReady()) mySegmentsSyncTask.execute();
|
|
@@ -10,7 +10,7 @@ const noopFilterAdapter = {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* Tracks uniques keys
|
|
14
14
|
* Unique Keys Tracker will be in charge of checking if the MTK was already sent to the BE in the last period
|
|
15
15
|
* or schedule to be sent; if not it will be added in an internal cache and sent in the next post.
|
|
16
16
|
*
|
|
@@ -104,8 +104,9 @@ export const DISABLED = 0;
|
|
|
104
104
|
export const ENABLED = 1;
|
|
105
105
|
export const PAUSED = 2;
|
|
106
106
|
|
|
107
|
-
export const FLAG_SPEC_VERSION = '1.
|
|
107
|
+
export const FLAG_SPEC_VERSION = '1.3';
|
|
108
108
|
|
|
109
109
|
// Matcher types
|
|
110
110
|
export const IN_SEGMENT = 'IN_SEGMENT';
|
|
111
111
|
export const IN_LARGE_SEGMENT = 'IN_LARGE_SEGMENT';
|
|
112
|
+
export const IN_RULE_BASED_SEGMENT = 'IN_RULE_BASED_SEGMENT';
|
package/src/utils/lang/index.ts
CHANGED
|
@@ -111,7 +111,7 @@ export function groupBy<T extends Record<string, any>>(source: T[], prop: string
|
|
|
111
111
|
/**
|
|
112
112
|
* Checks if a given value is a boolean.
|
|
113
113
|
*/
|
|
114
|
-
export function isBoolean(val: any): boolean {
|
|
114
|
+
export function isBoolean(val: any): val is boolean {
|
|
115
115
|
return val === true || val === false;
|
|
116
116
|
}
|
|
117
117
|
|
|
@@ -120,7 +120,7 @@ export function isBoolean(val: any): boolean {
|
|
|
120
120
|
* Unlike `Number.isFinite`, it also tests Number object instances.
|
|
121
121
|
* Unlike global `isFinite`, it returns false if the value is not a number or Number object instance.
|
|
122
122
|
*/
|
|
123
|
-
export function isFiniteNumber(val: any):
|
|
123
|
+
export function isFiniteNumber(val: any): boolean {
|
|
124
124
|
if (val instanceof Number) val = val.valueOf();
|
|
125
125
|
return typeof val === 'number' ?
|
|
126
126
|
Number.isFinite ? Number.isFinite(val) : isFinite(val) :
|
|
@@ -8,7 +8,7 @@ import { IStorageFactoryParams, IStorageSync } from '../../../storages/types';
|
|
|
8
8
|
|
|
9
9
|
export function __InLocalStorageMockFactory(params: IStorageFactoryParams): IStorageSync {
|
|
10
10
|
const result = InMemoryStorageCSFactory(params);
|
|
11
|
-
result.
|
|
11
|
+
result.splits.checkCache = () => true; // to emit SDK_READY_FROM_CACHE
|
|
12
12
|
return result;
|
|
13
13
|
}
|
|
14
14
|
__InLocalStorageMockFactory.type = STORAGE_MEMORY;
|
package/types/splitio.d.ts
CHANGED
|
@@ -910,18 +910,6 @@ declare namespace SplitIO {
|
|
|
910
910
|
* @defaultValue `'SPLITIO'`
|
|
911
911
|
*/
|
|
912
912
|
prefix?: string;
|
|
913
|
-
/**
|
|
914
|
-
* Number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
|
|
915
|
-
*
|
|
916
|
-
* @defaultValue `10`
|
|
917
|
-
*/
|
|
918
|
-
expirationDays?: number;
|
|
919
|
-
/**
|
|
920
|
-
* Optional settings to clear the cache. If set to `true`, the SDK clears the cached data on initialization, unless the cache was cleared within the last 24 hours.
|
|
921
|
-
*
|
|
922
|
-
* @defaultValue `false`
|
|
923
|
-
*/
|
|
924
|
-
clearOnInit?: boolean;
|
|
925
913
|
}
|
|
926
914
|
/**
|
|
927
915
|
* Storage for asynchronous (consumer) SDK.
|
|
@@ -1245,23 +1233,11 @@ declare namespace SplitIO {
|
|
|
1245
1233
|
*/
|
|
1246
1234
|
type?: BrowserStorage;
|
|
1247
1235
|
/**
|
|
1248
|
-
* Optional prefix to prevent any kind of data collision between SDK versions
|
|
1236
|
+
* Optional prefix to prevent any kind of data collision between SDK versions.
|
|
1249
1237
|
*
|
|
1250
1238
|
* @defaultValue `'SPLITIO'`
|
|
1251
1239
|
*/
|
|
1252
1240
|
prefix?: string;
|
|
1253
|
-
/**
|
|
1254
|
-
* Optional settings for the 'LOCALSTORAGE' storage type. It specifies the number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
|
|
1255
|
-
*
|
|
1256
|
-
* @defaultValue `10`
|
|
1257
|
-
*/
|
|
1258
|
-
expirationDays?: number;
|
|
1259
|
-
/**
|
|
1260
|
-
* Optional settings for the 'LOCALSTORAGE' storage type. If set to `true`, the SDK clears the cached data on initialization, unless the cache was cleared within the last 24 hours.
|
|
1261
|
-
*
|
|
1262
|
-
* @defaultValue `false`
|
|
1263
|
-
*/
|
|
1264
|
-
clearOnInit?: boolean;
|
|
1265
1241
|
};
|
|
1266
1242
|
}
|
|
1267
1243
|
/**
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateCache = void 0;
|
|
4
|
-
var lang_1 = require("../../utils/lang");
|
|
5
|
-
var KeyBuilder_1 = require("../KeyBuilder");
|
|
6
|
-
var constants_1 = require("./constants");
|
|
7
|
-
var DEFAULT_CACHE_EXPIRATION_IN_DAYS = 10;
|
|
8
|
-
var MILLIS_IN_A_DAY = 86400000;
|
|
9
|
-
/**
|
|
10
|
-
* Validates if cache should be cleared and sets the cache `hash` if needed.
|
|
11
|
-
*
|
|
12
|
-
* @returns `true` if cache should be cleared, `false` otherwise
|
|
13
|
-
*/
|
|
14
|
-
function validateExpiration(options, settings, keys, currentTimestamp, isThereCache) {
|
|
15
|
-
var log = settings.log;
|
|
16
|
-
// Check expiration
|
|
17
|
-
var lastUpdatedTimestamp = parseInt(localStorage.getItem(keys.buildLastUpdatedKey()), 10);
|
|
18
|
-
if (!(0, lang_1.isNaNNumber)(lastUpdatedTimestamp)) {
|
|
19
|
-
var cacheExpirationInDays = (0, lang_1.isFiniteNumber)(options.expirationDays) && options.expirationDays >= 1 ? options.expirationDays : DEFAULT_CACHE_EXPIRATION_IN_DAYS;
|
|
20
|
-
var expirationTimestamp = currentTimestamp - MILLIS_IN_A_DAY * cacheExpirationInDays;
|
|
21
|
-
if (lastUpdatedTimestamp < expirationTimestamp) {
|
|
22
|
-
log.info(constants_1.LOG_PREFIX + 'Cache expired more than ' + cacheExpirationInDays + ' days ago. Cleaning up cache');
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
// Check hash
|
|
27
|
-
var storageHashKey = keys.buildHashKey();
|
|
28
|
-
var storageHash = localStorage.getItem(storageHashKey);
|
|
29
|
-
var currentStorageHash = (0, KeyBuilder_1.getStorageHash)(settings);
|
|
30
|
-
if (storageHash !== currentStorageHash) {
|
|
31
|
-
try {
|
|
32
|
-
localStorage.setItem(storageHashKey, currentStorageHash);
|
|
33
|
-
}
|
|
34
|
-
catch (e) {
|
|
35
|
-
log.error(constants_1.LOG_PREFIX + e);
|
|
36
|
-
}
|
|
37
|
-
if (isThereCache) {
|
|
38
|
-
log.info(constants_1.LOG_PREFIX + 'SDK key, flags filter criteria, or flags spec version has changed. Cleaning up cache');
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
return false; // No cache to clear
|
|
42
|
-
}
|
|
43
|
-
// Clear on init
|
|
44
|
-
if (options.clearOnInit) {
|
|
45
|
-
var lastClearTimestamp = parseInt(localStorage.getItem(keys.buildLastClear()), 10);
|
|
46
|
-
if ((0, lang_1.isNaNNumber)(lastClearTimestamp) || lastClearTimestamp < currentTimestamp - MILLIS_IN_A_DAY) {
|
|
47
|
-
log.info(constants_1.LOG_PREFIX + 'clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Clean cache if:
|
|
54
|
-
* - it has expired, i.e., its `lastUpdated` timestamp is older than the given `expirationTimestamp`
|
|
55
|
-
* - its hash has changed, i.e., the SDK key, flags filter criteria or flags spec version was modified
|
|
56
|
-
* - `clearOnInit` was set and cache was not cleared in the last 24 hours
|
|
57
|
-
*
|
|
58
|
-
* @returns `true` if cache is ready to be used, `false` otherwise (cache was cleared or there is no cache)
|
|
59
|
-
*/
|
|
60
|
-
function validateCache(options, settings, keys, splits, 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
|
-
segments.clear();
|
|
66
|
-
largeSegments.clear();
|
|
67
|
-
// Update last clear timestamp
|
|
68
|
-
try {
|
|
69
|
-
localStorage.setItem(keys.buildLastClear(), currentTimestamp + '');
|
|
70
|
-
}
|
|
71
|
-
catch (e) {
|
|
72
|
-
settings.log.error(constants_1.LOG_PREFIX + e);
|
|
73
|
-
}
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
// Check if ready from cache
|
|
77
|
-
return isThereCache;
|
|
78
|
-
}
|
|
79
|
-
exports.validateCache = validateCache;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
|
|
2
|
-
import { getStorageHash } from '../KeyBuilder';
|
|
3
|
-
import { LOG_PREFIX } from './constants';
|
|
4
|
-
var DEFAULT_CACHE_EXPIRATION_IN_DAYS = 10;
|
|
5
|
-
var MILLIS_IN_A_DAY = 86400000;
|
|
6
|
-
/**
|
|
7
|
-
* Validates if cache should be cleared and sets the cache `hash` if needed.
|
|
8
|
-
*
|
|
9
|
-
* @returns `true` if cache should be cleared, `false` otherwise
|
|
10
|
-
*/
|
|
11
|
-
function validateExpiration(options, settings, keys, currentTimestamp, isThereCache) {
|
|
12
|
-
var log = settings.log;
|
|
13
|
-
// Check expiration
|
|
14
|
-
var lastUpdatedTimestamp = parseInt(localStorage.getItem(keys.buildLastUpdatedKey()), 10);
|
|
15
|
-
if (!isNaNNumber(lastUpdatedTimestamp)) {
|
|
16
|
-
var cacheExpirationInDays = isFiniteNumber(options.expirationDays) && options.expirationDays >= 1 ? options.expirationDays : DEFAULT_CACHE_EXPIRATION_IN_DAYS;
|
|
17
|
-
var expirationTimestamp = currentTimestamp - MILLIS_IN_A_DAY * cacheExpirationInDays;
|
|
18
|
-
if (lastUpdatedTimestamp < expirationTimestamp) {
|
|
19
|
-
log.info(LOG_PREFIX + 'Cache expired more than ' + cacheExpirationInDays + ' days ago. Cleaning up cache');
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
// Check hash
|
|
24
|
-
var storageHashKey = keys.buildHashKey();
|
|
25
|
-
var storageHash = localStorage.getItem(storageHashKey);
|
|
26
|
-
var currentStorageHash = getStorageHash(settings);
|
|
27
|
-
if (storageHash !== currentStorageHash) {
|
|
28
|
-
try {
|
|
29
|
-
localStorage.setItem(storageHashKey, currentStorageHash);
|
|
30
|
-
}
|
|
31
|
-
catch (e) {
|
|
32
|
-
log.error(LOG_PREFIX + e);
|
|
33
|
-
}
|
|
34
|
-
if (isThereCache) {
|
|
35
|
-
log.info(LOG_PREFIX + 'SDK key, flags filter criteria, or flags spec version has changed. Cleaning up cache');
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
return false; // No cache to clear
|
|
39
|
-
}
|
|
40
|
-
// Clear on init
|
|
41
|
-
if (options.clearOnInit) {
|
|
42
|
-
var lastClearTimestamp = parseInt(localStorage.getItem(keys.buildLastClear()), 10);
|
|
43
|
-
if (isNaNNumber(lastClearTimestamp) || lastClearTimestamp < currentTimestamp - MILLIS_IN_A_DAY) {
|
|
44
|
-
log.info(LOG_PREFIX + 'clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Clean cache if:
|
|
51
|
-
* - it has expired, i.e., its `lastUpdated` timestamp is older than the given `expirationTimestamp`
|
|
52
|
-
* - its hash has changed, i.e., the SDK key, flags filter criteria or flags spec version was modified
|
|
53
|
-
* - `clearOnInit` was set and cache was not cleared in the last 24 hours
|
|
54
|
-
*
|
|
55
|
-
* @returns `true` if cache is ready to be used, `false` otherwise (cache was cleared or there is no cache)
|
|
56
|
-
*/
|
|
57
|
-
export function validateCache(options, settings, keys, splits, segments, largeSegments) {
|
|
58
|
-
var currentTimestamp = Date.now();
|
|
59
|
-
var isThereCache = splits.getChangeNumber() > -1;
|
|
60
|
-
if (validateExpiration(options, settings, keys, currentTimestamp, isThereCache)) {
|
|
61
|
-
splits.clear();
|
|
62
|
-
segments.clear();
|
|
63
|
-
largeSegments.clear();
|
|
64
|
-
// Update last clear timestamp
|
|
65
|
-
try {
|
|
66
|
-
localStorage.setItem(keys.buildLastClear(), currentTimestamp + '');
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
settings.log.error(LOG_PREFIX + e);
|
|
70
|
-
}
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
// Check if ready from cache
|
|
74
|
-
return isThereCache;
|
|
75
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { ISettings } from '../../types';
|
|
2
|
-
import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
|
|
3
|
-
import { getStorageHash } from '../KeyBuilder';
|
|
4
|
-
import { LOG_PREFIX } from './constants';
|
|
5
|
-
import type { SplitsCacheInLocal } from './SplitsCacheInLocal';
|
|
6
|
-
import type { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
|
|
7
|
-
import { KeyBuilderCS } from '../KeyBuilderCS';
|
|
8
|
-
import SplitIO from '../../../types/splitio';
|
|
9
|
-
|
|
10
|
-
const DEFAULT_CACHE_EXPIRATION_IN_DAYS = 10;
|
|
11
|
-
const MILLIS_IN_A_DAY = 86400000;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Validates if cache should be cleared and sets the cache `hash` if needed.
|
|
15
|
-
*
|
|
16
|
-
* @returns `true` if cache should be cleared, `false` otherwise
|
|
17
|
-
*/
|
|
18
|
-
function validateExpiration(options: SplitIO.InLocalStorageOptions, settings: ISettings, keys: KeyBuilderCS, currentTimestamp: number, isThereCache: boolean) {
|
|
19
|
-
const { log } = settings;
|
|
20
|
-
|
|
21
|
-
// Check expiration
|
|
22
|
-
const lastUpdatedTimestamp = parseInt(localStorage.getItem(keys.buildLastUpdatedKey()) as string, 10);
|
|
23
|
-
if (!isNaNNumber(lastUpdatedTimestamp)) {
|
|
24
|
-
const cacheExpirationInDays = isFiniteNumber(options.expirationDays) && options.expirationDays >= 1 ? options.expirationDays : DEFAULT_CACHE_EXPIRATION_IN_DAYS;
|
|
25
|
-
const expirationTimestamp = currentTimestamp - MILLIS_IN_A_DAY * cacheExpirationInDays;
|
|
26
|
-
if (lastUpdatedTimestamp < expirationTimestamp) {
|
|
27
|
-
log.info(LOG_PREFIX + 'Cache expired more than ' + cacheExpirationInDays + ' days ago. Cleaning up cache');
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Check hash
|
|
33
|
-
const storageHashKey = keys.buildHashKey();
|
|
34
|
-
const storageHash = localStorage.getItem(storageHashKey);
|
|
35
|
-
const currentStorageHash = getStorageHash(settings);
|
|
36
|
-
|
|
37
|
-
if (storageHash !== currentStorageHash) {
|
|
38
|
-
try {
|
|
39
|
-
localStorage.setItem(storageHashKey, currentStorageHash);
|
|
40
|
-
} catch (e) {
|
|
41
|
-
log.error(LOG_PREFIX + e);
|
|
42
|
-
}
|
|
43
|
-
if (isThereCache) {
|
|
44
|
-
log.info(LOG_PREFIX + 'SDK key, flags filter criteria, or flags spec version has changed. Cleaning up cache');
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
return false; // No cache to clear
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Clear on init
|
|
51
|
-
if (options.clearOnInit) {
|
|
52
|
-
const lastClearTimestamp = parseInt(localStorage.getItem(keys.buildLastClear()) as string, 10);
|
|
53
|
-
|
|
54
|
-
if (isNaNNumber(lastClearTimestamp) || lastClearTimestamp < currentTimestamp - MILLIS_IN_A_DAY) {
|
|
55
|
-
log.info(LOG_PREFIX + 'clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Clean cache if:
|
|
63
|
-
* - it has expired, i.e., its `lastUpdated` timestamp is older than the given `expirationTimestamp`
|
|
64
|
-
* - its hash has changed, i.e., the SDK key, flags filter criteria or flags spec version was modified
|
|
65
|
-
* - `clearOnInit` was set and cache was not cleared in the last 24 hours
|
|
66
|
-
*
|
|
67
|
-
* @returns `true` if cache is ready to be used, `false` otherwise (cache was cleared or there is no cache)
|
|
68
|
-
*/
|
|
69
|
-
export function validateCache(options: SplitIO.InLocalStorageOptions, settings: ISettings, keys: KeyBuilderCS, splits: SplitsCacheInLocal, segments: MySegmentsCacheInLocal, largeSegments: MySegmentsCacheInLocal): boolean {
|
|
70
|
-
|
|
71
|
-
const currentTimestamp = Date.now();
|
|
72
|
-
const isThereCache = splits.getChangeNumber() > -1;
|
|
73
|
-
|
|
74
|
-
if (validateExpiration(options, settings, keys, currentTimestamp, isThereCache)) {
|
|
75
|
-
splits.clear();
|
|
76
|
-
segments.clear();
|
|
77
|
-
largeSegments.clear();
|
|
78
|
-
|
|
79
|
-
// Update last clear timestamp
|
|
80
|
-
try {
|
|
81
|
-
localStorage.setItem(keys.buildLastClear(), currentTimestamp + '');
|
|
82
|
-
} catch (e) {
|
|
83
|
-
settings.log.error(LOG_PREFIX + e);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Check if ready from cache
|
|
90
|
-
return isThereCache;
|
|
91
|
-
}
|