@splitsoftware/splitio-commons 1.4.2-rc.2 → 1.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/cjs/sdkFactory/index.js +2 -20
- package/cjs/storages/AbstractSplitsCacheSync.js +1 -1
- package/cjs/storages/dataLoader.js +15 -23
- package/cjs/storages/inMemory/InMemoryStorage.js +1 -15
- package/cjs/storages/inMemory/InMemoryStorageCS.js +0 -12
- package/cjs/sync/syncManagerOnline.js +2 -2
- package/cjs/trackers/impressionObserver/impressionObserverCS.js +1 -1
- package/cjs/utils/settingsValidation/index.js +1 -8
- package/esm/sdkFactory/index.js +3 -21
- package/esm/storages/AbstractSplitsCacheSync.js +1 -1
- package/esm/storages/dataLoader.js +13 -21
- package/esm/storages/inMemory/InMemoryStorage.js +1 -15
- package/esm/storages/inMemory/InMemoryStorageCS.js +0 -12
- package/esm/sync/syncManagerOnline.js +2 -2
- package/esm/trackers/impressionObserver/impressionObserverCS.js +1 -1
- package/esm/utils/settingsValidation/index.js +1 -8
- package/package.json +1 -1
- package/src/sdkFactory/index.ts +4 -23
- package/src/storages/AbstractSplitsCacheSync.ts +1 -1
- package/src/storages/dataLoader.ts +13 -20
- package/src/storages/inMemory/InMemoryStorage.ts +1 -16
- package/src/storages/inMemory/InMemoryStorageCS.ts +0 -13
- package/src/sync/syncManagerOnline.ts +2 -2
- package/src/trackers/impressionObserver/impressionObserverCS.ts +1 -1
- package/src/types.ts +3 -5
- package/src/utils/settingsValidation/index.ts +1 -9
- package/types/logger/browser/{debugLogger.d.ts → DebugLogger.d.ts} +0 -0
- package/types/logger/browser/{errorLogger.d.ts → ErrorLogger.d.ts} +0 -0
- package/types/logger/browser/{infoLogger.d.ts → InfoLogger.d.ts} +0 -0
- package/types/logger/browser/{warnLogger.d.ts → WarnLogger.d.ts} +0 -0
- package/types/storages/dataLoader.d.ts +2 -2
- package/types/trackers/impressionObserver/impressionObserverCS.d.ts +2 -2
- package/types/types.d.ts +2 -4
- package/types/utils/timeTracker/index.d.ts +70 -1
- package/src/logger/.DS_Store +0 -0
- package/types/integrations/ga/GaToSplitPlugin.d.ts +0 -3
- package/types/integrations/ga/SplitToGaPlugin.d.ts +0 -4
- package/types/integrations/ga/autoRequire.d.ts +0 -4
- package/types/logger/codes.d.ts +0 -2
- package/types/logger/codesConstants.d.ts +0 -117
- package/types/logger/codesConstantsBrowser.d.ts +0 -2
- package/types/logger/codesConstantsNode.d.ts +0 -14
- package/types/logger/codesDebug.d.ts +0 -1
- package/types/logger/codesDebugBrowser.d.ts +0 -1
- package/types/logger/codesDebugNode.d.ts +0 -1
- package/types/logger/codesError.d.ts +0 -1
- package/types/logger/codesErrorNode.d.ts +0 -1
- package/types/logger/codesInfo.d.ts +0 -1
- package/types/logger/codesWarn.d.ts +0 -1
- package/types/logger/codesWarnNode.d.ts +0 -1
- package/types/logger/debugLogger.d.ts +0 -2
- package/types/logger/errorLogger.d.ts +0 -2
- package/types/logger/infoLogger.d.ts +0 -2
- package/types/logger/messages/debugBrowser.d.ts +0 -1
- package/types/logger/messages/debugNode.d.ts +0 -1
- package/types/logger/messages/errorNode.d.ts +0 -1
- package/types/logger/messages/warnNode.d.ts +0 -1
- package/types/logger/noopLogger.d.ts +0 -2
- package/types/logger/warnLogger.d.ts +0 -2
- package/types/sdkFactory/userConsentProps.d.ts +0 -6
- package/types/sdkManager/sdkManagerMethod.d.ts +0 -6
- package/types/storages/getRegisteredSegments.d.ts +0 -10
- package/types/storages/inMemory/index.d.ts +0 -10
- package/types/storages/parseSegments.d.ts +0 -6
- package/types/sync/polling/syncTasks/splitsSyncTask.copy.d.ts +0 -35
- package/types/sync/polling/syncTasks/splitsSyncTask.morelikeoriginal.d.ts +0 -35
- package/types/sync/streaming/AuthClient/indexV1.d.ts +0 -12
- package/types/sync/streaming/AuthClient/indexV2.d.ts +0 -8
- package/types/sync/streaming/pushManagerCS.d.ts +0 -1
- package/types/sync/streaming/pushManagerNoUsers.d.ts +0 -13
- package/types/sync/streaming/pushManagerSS.d.ts +0 -1
- package/types/sync/submitters/telemetrySyncTask.d.ts +0 -0
- package/types/sync/syncManagerFromFile.d.ts +0 -2
- package/types/sync/syncManagerFromObject.d.ts +0 -2
- package/types/sync/syncManagerOffline.d.ts +0 -9
- package/types/trackers/telemetryRecorder.d.ts +0 -0
- package/types/utils/EventEmitter.d.ts +0 -4
- package/types/utils/consent.d.ts +0 -2
- package/types/utils/lang/errors.d.ts +0 -10
- package/types/utils/murmur3/commons.d.ts +0 -12
- package/types/utils/settingsValidation/buildMetadata.d.ts +0 -3
- package/types/utils/settingsValidation/localhost/index.d.ts +0 -9
- package/types/utils/settingsValidation/logger.d.ts +0 -11
- package/types/utils/settingsValidation/runtime/browser.d.ts +0 -2
- package/types/utils/settingsValidation/runtime/node.d.ts +0 -2
- package/types/utils/settingsValidation/userConsent.d.ts +0 -5
package/cjs/sdkFactory/index.js
CHANGED
|
@@ -25,14 +25,13 @@ function sdkFactory(params) {
|
|
|
25
25
|
(0, apiKey_1.validateAndTrackApiKey)(log, settings.core.authorizationKey);
|
|
26
26
|
var sdkReadinessManager = (0, sdkReadinessManager_1.sdkReadinessManagerFactory)(log, platform.EventEmitter, settings.startup.readyTimeout);
|
|
27
27
|
var readiness = sdkReadinessManager.readinessManager;
|
|
28
|
-
var matchingKey = (0, key_1.getMatching)(settings.core.key);
|
|
29
28
|
// @TODO consider passing the settings object, so that each storage access only what it needs
|
|
30
29
|
var storageFactoryParams = {
|
|
31
30
|
impressionsQueueSize: settings.scheduler.impressionsQueueSize,
|
|
32
31
|
eventsQueueSize: settings.scheduler.eventsQueueSize,
|
|
33
32
|
optimize: (0, utils_1.shouldBeOptimized)(settings),
|
|
34
33
|
// ATM, only used by InLocalStorage
|
|
35
|
-
matchingKey:
|
|
34
|
+
matchingKey: (0, key_1.getMatching)(settings.core.key),
|
|
36
35
|
splitFiltersValidation: settings.sync.__splitFiltersValidation,
|
|
37
36
|
// ATM, only used by PluggableStorage
|
|
38
37
|
mode: settings.mode,
|
|
@@ -48,21 +47,7 @@ function sdkFactory(params) {
|
|
|
48
47
|
log: log
|
|
49
48
|
};
|
|
50
49
|
var storage = storageFactory(storageFactoryParams);
|
|
51
|
-
// @TODO dataLoader
|
|
52
|
-
if (settings.dataLoader) {
|
|
53
|
-
settings.dataLoader(storage, matchingKey);
|
|
54
|
-
Promise.resolve(storage.splits.checkCache()).then(function (cacheReady) {
|
|
55
|
-
if (cacheReady) {
|
|
56
|
-
if (settings.sync.onlySubmitters) { // emit SDK_READY to not timeout when not synchronizing splits & segments
|
|
57
|
-
readiness.splits.emit(constants_2.SDK_SPLITS_ARRIVED);
|
|
58
|
-
readiness.segments.emit(constants_2.SDK_SEGMENTS_ARRIVED);
|
|
59
|
-
}
|
|
60
|
-
else { // emit SDK_READY_FROM_CACHE
|
|
61
|
-
readiness.splits.emit(constants_2.SDK_SPLITS_CACHE_LOADED);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
}
|
|
50
|
+
// @TODO add support for dataloader: `if (params.dataLoader) params.dataLoader(storage);`
|
|
66
51
|
var integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings: settings, storage: storage });
|
|
67
52
|
// trackers
|
|
68
53
|
var observer = impressionsObserverFactory && impressionsObserverFactory();
|
|
@@ -94,9 +79,6 @@ function sdkFactory(params) {
|
|
|
94
79
|
// Logger wrapper API
|
|
95
80
|
Logger: (0, sdkLogger_1.createLoggerAPI)(settings.log),
|
|
96
81
|
settings: settings,
|
|
97
|
-
// @TODO remove
|
|
98
|
-
__storage: storage,
|
|
99
|
-
__ctx: ctx
|
|
100
82
|
}, extraProps && extraProps(ctx));
|
|
101
83
|
}
|
|
102
84
|
exports.sdkFactory = sdkFactory;
|
|
@@ -33,7 +33,7 @@ var AbstractSplitsCacheSync = /** @class */ (function () {
|
|
|
33
33
|
* It is used as condition to emit SDK_SPLITS_CACHE_LOADED, and then SDK_READY_FROM_CACHE.
|
|
34
34
|
*/
|
|
35
35
|
AbstractSplitsCacheSync.prototype.checkCache = function () {
|
|
36
|
-
return
|
|
36
|
+
return false;
|
|
37
37
|
};
|
|
38
38
|
/**
|
|
39
39
|
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.dataLoaderFactory = void 0;
|
|
4
4
|
var browser_1 = require("../utils/constants/browser");
|
|
5
5
|
/**
|
|
6
|
-
* Factory of storage loader
|
|
6
|
+
* Factory of client-side storage loader
|
|
7
7
|
*
|
|
8
8
|
* @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader
|
|
9
9
|
* and extended with a `mySegmentsData` property.
|
|
10
10
|
* @returns function to preload the storage
|
|
11
11
|
*/
|
|
12
|
-
function
|
|
12
|
+
function dataLoaderFactory(preloadedData) {
|
|
13
13
|
/**
|
|
14
14
|
* Storage-agnostic adaptation of `loadDataIntoLocalStorage` function
|
|
15
15
|
* (https://github.com/godaddy/split-javascript-data-loader/blob/master/src/load-data.js)
|
|
16
16
|
*
|
|
17
17
|
* @param storage object containing `splits` and `segments` cache (client-side variant)
|
|
18
|
-
* @param
|
|
18
|
+
* @param userId user key string of the provided MySegmentsCache
|
|
19
19
|
*
|
|
20
|
+
* @TODO extend to support SegmentsCache (server-side variant) by making `userId` optional and adding the corresponding logic.
|
|
20
21
|
* @TODO extend to load data on shared mySegments storages. Be specific when emitting SDK_READY_FROM_CACHE on shared clients. Maybe the serializer should provide the `useSegments` flag.
|
|
21
|
-
* @TODO add logs, and input validation in this module, in favor of size reduction.
|
|
22
|
-
* @TODO unit tests
|
|
23
22
|
*/
|
|
24
|
-
return function loadData(storage,
|
|
23
|
+
return function loadData(storage, userId) {
|
|
25
24
|
// Do not load data if current preloadedData is empty
|
|
26
25
|
if (Object.keys(preloadedData).length === 0)
|
|
27
26
|
return;
|
|
@@ -37,23 +36,16 @@ function DataLoaderFactory(preloadedData) {
|
|
|
37
36
|
storage.splits.setChangeNumber(since);
|
|
38
37
|
// splitsData in an object where the property is the split name and the pertaining value is a stringified json of its data
|
|
39
38
|
storage.splits.addSplits(Object.keys(splitsData).map(function (splitName) { return [splitName, splitsData[splitName]]; }));
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
storage.segments.resetSegments(mySegmentsData);
|
|
50
|
-
}
|
|
51
|
-
else { // add segments data (server-side)
|
|
52
|
-
Object.keys(segmentsData).filter(function (segmentName) {
|
|
53
|
-
var userKeys = segmentsData[segmentName];
|
|
54
|
-
storage.segments.addToSegment(segmentName, userKeys);
|
|
39
|
+
// add mySegments data
|
|
40
|
+
var mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[userId];
|
|
41
|
+
if (!mySegmentsData) {
|
|
42
|
+
// segmentsData in an object where the property is the segment name and the pertaining value is a stringified object that contains the `added` array of userIds
|
|
43
|
+
mySegmentsData = Object.keys(segmentsData).filter(function (segmentName) {
|
|
44
|
+
var userIds = JSON.parse(segmentsData[segmentName]).added;
|
|
45
|
+
return Array.isArray(userIds) && userIds.indexOf(userId) > -1;
|
|
55
46
|
});
|
|
56
47
|
}
|
|
48
|
+
storage.segments.resetSegments(mySegmentsData);
|
|
57
49
|
};
|
|
58
50
|
}
|
|
59
|
-
exports.
|
|
51
|
+
exports.dataLoaderFactory = dataLoaderFactory;
|
|
@@ -8,7 +8,6 @@ var EventsCacheInMemory_1 = require("./EventsCacheInMemory");
|
|
|
8
8
|
var ImpressionCountsCacheInMemory_1 = require("./ImpressionCountsCacheInMemory");
|
|
9
9
|
var constants_1 = require("../../utils/constants");
|
|
10
10
|
var TelemetryCacheInMemory_1 = require("./TelemetryCacheInMemory");
|
|
11
|
-
var sets_1 = require("../../utils/lang/sets");
|
|
12
11
|
/**
|
|
13
12
|
* InMemory storage factory for standalone server-side SplitFactory
|
|
14
13
|
*
|
|
@@ -29,20 +28,7 @@ function InMemoryStorageFactory(params) {
|
|
|
29
28
|
this.impressions.clear();
|
|
30
29
|
this.impressionCounts && this.impressionCounts.clear();
|
|
31
30
|
this.events.clear();
|
|
32
|
-
}
|
|
33
|
-
// @ts-ignore, private method, for POC
|
|
34
|
-
getSnapshot: function () {
|
|
35
|
-
var _this = this;
|
|
36
|
-
return {
|
|
37
|
-
lastUpdated: Date.now(),
|
|
38
|
-
since: this.splits.changeNumber,
|
|
39
|
-
splitsData: this.splits.splitsCache,
|
|
40
|
-
segmentsData: Object.keys(this.segments.segmentCache).reduce(function (prev, cur) {
|
|
41
|
-
prev[cur] = (0, sets_1.setToArray)(_this.segments.segmentCache[cur]);
|
|
42
|
-
return prev;
|
|
43
|
-
}, {})
|
|
44
|
-
};
|
|
45
|
-
},
|
|
31
|
+
}
|
|
46
32
|
};
|
|
47
33
|
}
|
|
48
34
|
exports.InMemoryStorageFactory = InMemoryStorageFactory;
|
|
@@ -29,18 +29,6 @@ function InMemoryStorageCSFactory(params) {
|
|
|
29
29
|
this.impressionCounts && this.impressionCounts.clear();
|
|
30
30
|
this.events.clear();
|
|
31
31
|
},
|
|
32
|
-
// @ts-ignore, private method, for POC
|
|
33
|
-
getSnapshot: function () {
|
|
34
|
-
var _a;
|
|
35
|
-
return {
|
|
36
|
-
lastUpdated: Date.now(),
|
|
37
|
-
since: this.splits.changeNumber,
|
|
38
|
-
splitsData: this.splits.splitsCache,
|
|
39
|
-
mySegmentsData: (_a = {},
|
|
40
|
-
_a[params.matchingKey] = Object.keys(this.segments.segmentCache),
|
|
41
|
-
_a)
|
|
42
|
-
};
|
|
43
|
-
},
|
|
44
32
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are unique per key)
|
|
45
33
|
shared: function () {
|
|
46
34
|
return {
|
|
@@ -19,9 +19,9 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
19
19
|
* SyncManager factory for modular SDK
|
|
20
20
|
*/
|
|
21
21
|
return function (params) {
|
|
22
|
-
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled,
|
|
22
|
+
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker;
|
|
23
23
|
/** Polling Manager */
|
|
24
|
-
var pollingManager =
|
|
24
|
+
var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
25
25
|
/** Push Manager */
|
|
26
26
|
var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
|
27
27
|
pushManagerFactory(params, pollingManager) :
|
|
@@ -5,7 +5,7 @@ var ImpressionObserver_1 = require("./ImpressionObserver");
|
|
|
5
5
|
var murmur3_1 = require("../../utils/murmur3/murmur3");
|
|
6
6
|
var buildKey_1 = require("./buildKey");
|
|
7
7
|
function hashImpression32(impression) {
|
|
8
|
-
return (0, murmur3_1.hash)((0, buildKey_1.buildKey)(impression))
|
|
8
|
+
return (0, murmur3_1.hash)((0, buildKey_1.buildKey)(impression));
|
|
9
9
|
}
|
|
10
10
|
exports.hashImpression32 = hashImpression32;
|
|
11
11
|
var LAST_SEEN_CACHE_SIZE = 500; // cache up to 500 impression hashes
|
|
@@ -127,9 +127,6 @@ function settingsValidation(config, validationParams) {
|
|
|
127
127
|
// ensure a valid SDK mode
|
|
128
128
|
// @ts-ignore, modify readonly prop
|
|
129
129
|
withDefaults.mode = (0, mode_1.mode)(withDefaults.core.authorizationKey, withDefaults.mode);
|
|
130
|
-
if (withDefaults.sync.onlySubmitters && withDefaults.mode === constants_1.STANDALONE_MODE && !withDefaults.dataLoader) {
|
|
131
|
-
throw new Error('To use `onlySubmitters` param in standalone mode, DataLoader is required to preload data into the storage');
|
|
132
|
-
}
|
|
133
130
|
// ensure a valid Storage based on mode defined.
|
|
134
131
|
// @ts-ignore, modify readonly prop
|
|
135
132
|
if (storage)
|
|
@@ -172,13 +169,9 @@ function settingsValidation(config, validationParams) {
|
|
|
172
169
|
scheduler.pushRetryBackoffBase = fromSecondsToMillis(scheduler.pushRetryBackoffBase);
|
|
173
170
|
}
|
|
174
171
|
// validate sync enabled
|
|
175
|
-
if (withDefaults.sync.enabled !== false) {
|
|
172
|
+
if (withDefaults.sync.enabled !== false) { // @ts-ignore, modify readonly prop
|
|
176
173
|
withDefaults.sync.enabled = true;
|
|
177
174
|
}
|
|
178
|
-
// validate sync onlySubmitters
|
|
179
|
-
if (withDefaults.sync.onlySubmitters !== true) {
|
|
180
|
-
withDefaults.sync.onlySubmitters = false;
|
|
181
|
-
}
|
|
182
175
|
// validate the `splitFilters` settings and parse splits query
|
|
183
176
|
var splitFiltersValidation = (0, splitFilters_1.validateSplitFilters)(log, withDefaults.sync.splitFilters, withDefaults.mode);
|
|
184
177
|
withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
|
package/esm/sdkFactory/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey';
|
|
|
8
8
|
import { createLoggerAPI } from '../logger/sdkLogger';
|
|
9
9
|
import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
|
|
10
10
|
import { metadataBuilder } from '../storages/metadataBuilder';
|
|
11
|
-
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED
|
|
11
|
+
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
|
|
12
12
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
13
13
|
/**
|
|
14
14
|
* Modular SDK factory
|
|
@@ -22,14 +22,13 @@ export function sdkFactory(params) {
|
|
|
22
22
|
validateAndTrackApiKey(log, settings.core.authorizationKey);
|
|
23
23
|
var sdkReadinessManager = sdkReadinessManagerFactory(log, platform.EventEmitter, settings.startup.readyTimeout);
|
|
24
24
|
var readiness = sdkReadinessManager.readinessManager;
|
|
25
|
-
var matchingKey = getMatching(settings.core.key);
|
|
26
25
|
// @TODO consider passing the settings object, so that each storage access only what it needs
|
|
27
26
|
var storageFactoryParams = {
|
|
28
27
|
impressionsQueueSize: settings.scheduler.impressionsQueueSize,
|
|
29
28
|
eventsQueueSize: settings.scheduler.eventsQueueSize,
|
|
30
29
|
optimize: shouldBeOptimized(settings),
|
|
31
30
|
// ATM, only used by InLocalStorage
|
|
32
|
-
matchingKey:
|
|
31
|
+
matchingKey: getMatching(settings.core.key),
|
|
33
32
|
splitFiltersValidation: settings.sync.__splitFiltersValidation,
|
|
34
33
|
// ATM, only used by PluggableStorage
|
|
35
34
|
mode: settings.mode,
|
|
@@ -45,21 +44,7 @@ export function sdkFactory(params) {
|
|
|
45
44
|
log: log
|
|
46
45
|
};
|
|
47
46
|
var storage = storageFactory(storageFactoryParams);
|
|
48
|
-
// @TODO dataLoader
|
|
49
|
-
if (settings.dataLoader) {
|
|
50
|
-
settings.dataLoader(storage, matchingKey);
|
|
51
|
-
Promise.resolve(storage.splits.checkCache()).then(function (cacheReady) {
|
|
52
|
-
if (cacheReady) {
|
|
53
|
-
if (settings.sync.onlySubmitters) { // emit SDK_READY to not timeout when not synchronizing splits & segments
|
|
54
|
-
readiness.splits.emit(SDK_SPLITS_ARRIVED);
|
|
55
|
-
readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
56
|
-
}
|
|
57
|
-
else { // emit SDK_READY_FROM_CACHE
|
|
58
|
-
readiness.splits.emit(SDK_SPLITS_CACHE_LOADED);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
}
|
|
47
|
+
// @TODO add support for dataloader: `if (params.dataLoader) params.dataLoader(storage);`
|
|
63
48
|
var integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings: settings, storage: storage });
|
|
64
49
|
// trackers
|
|
65
50
|
var observer = impressionsObserverFactory && impressionsObserverFactory();
|
|
@@ -91,8 +76,5 @@ export function sdkFactory(params) {
|
|
|
91
76
|
// Logger wrapper API
|
|
92
77
|
Logger: createLoggerAPI(settings.log),
|
|
93
78
|
settings: settings,
|
|
94
|
-
// @TODO remove
|
|
95
|
-
__storage: storage,
|
|
96
|
-
__ctx: ctx
|
|
97
79
|
}, extraProps && extraProps(ctx));
|
|
98
80
|
}
|
|
@@ -30,7 +30,7 @@ var AbstractSplitsCacheSync = /** @class */ (function () {
|
|
|
30
30
|
* It is used as condition to emit SDK_SPLITS_CACHE_LOADED, and then SDK_READY_FROM_CACHE.
|
|
31
31
|
*/
|
|
32
32
|
AbstractSplitsCacheSync.prototype.checkCache = function () {
|
|
33
|
-
return
|
|
33
|
+
return false;
|
|
34
34
|
};
|
|
35
35
|
/**
|
|
36
36
|
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../utils/constants/browser';
|
|
2
2
|
/**
|
|
3
|
-
* Factory of storage loader
|
|
3
|
+
* Factory of client-side storage loader
|
|
4
4
|
*
|
|
5
5
|
* @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader
|
|
6
6
|
* and extended with a `mySegmentsData` property.
|
|
7
7
|
* @returns function to preload the storage
|
|
8
8
|
*/
|
|
9
|
-
export function
|
|
9
|
+
export function dataLoaderFactory(preloadedData) {
|
|
10
10
|
/**
|
|
11
11
|
* Storage-agnostic adaptation of `loadDataIntoLocalStorage` function
|
|
12
12
|
* (https://github.com/godaddy/split-javascript-data-loader/blob/master/src/load-data.js)
|
|
13
13
|
*
|
|
14
14
|
* @param storage object containing `splits` and `segments` cache (client-side variant)
|
|
15
|
-
* @param
|
|
15
|
+
* @param userId user key string of the provided MySegmentsCache
|
|
16
16
|
*
|
|
17
|
+
* @TODO extend to support SegmentsCache (server-side variant) by making `userId` optional and adding the corresponding logic.
|
|
17
18
|
* @TODO extend to load data on shared mySegments storages. Be specific when emitting SDK_READY_FROM_CACHE on shared clients. Maybe the serializer should provide the `useSegments` flag.
|
|
18
|
-
* @TODO add logs, and input validation in this module, in favor of size reduction.
|
|
19
|
-
* @TODO unit tests
|
|
20
19
|
*/
|
|
21
|
-
return function loadData(storage,
|
|
20
|
+
return function loadData(storage, userId) {
|
|
22
21
|
// Do not load data if current preloadedData is empty
|
|
23
22
|
if (Object.keys(preloadedData).length === 0)
|
|
24
23
|
return;
|
|
@@ -34,22 +33,15 @@ export function DataLoaderFactory(preloadedData) {
|
|
|
34
33
|
storage.splits.setChangeNumber(since);
|
|
35
34
|
// splitsData in an object where the property is the split name and the pertaining value is a stringified json of its data
|
|
36
35
|
storage.splits.addSplits(Object.keys(splitsData).map(function (splitName) { return [splitName, splitsData[splitName]]; }));
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
storage.segments.resetSegments(mySegmentsData);
|
|
47
|
-
}
|
|
48
|
-
else { // add segments data (server-side)
|
|
49
|
-
Object.keys(segmentsData).filter(function (segmentName) {
|
|
50
|
-
var userKeys = segmentsData[segmentName];
|
|
51
|
-
storage.segments.addToSegment(segmentName, userKeys);
|
|
36
|
+
// add mySegments data
|
|
37
|
+
var mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[userId];
|
|
38
|
+
if (!mySegmentsData) {
|
|
39
|
+
// segmentsData in an object where the property is the segment name and the pertaining value is a stringified object that contains the `added` array of userIds
|
|
40
|
+
mySegmentsData = Object.keys(segmentsData).filter(function (segmentName) {
|
|
41
|
+
var userIds = JSON.parse(segmentsData[segmentName]).added;
|
|
42
|
+
return Array.isArray(userIds) && userIds.indexOf(userId) > -1;
|
|
52
43
|
});
|
|
53
44
|
}
|
|
45
|
+
storage.segments.resetSegments(mySegmentsData);
|
|
54
46
|
};
|
|
55
47
|
}
|
|
@@ -5,7 +5,6 @@ import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
|
5
5
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
6
6
|
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
7
7
|
import { TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
8
|
-
import { setToArray } from '../../utils/lang/sets';
|
|
9
8
|
/**
|
|
10
9
|
* InMemory storage factory for standalone server-side SplitFactory
|
|
11
10
|
*
|
|
@@ -26,20 +25,7 @@ export function InMemoryStorageFactory(params) {
|
|
|
26
25
|
this.impressions.clear();
|
|
27
26
|
this.impressionCounts && this.impressionCounts.clear();
|
|
28
27
|
this.events.clear();
|
|
29
|
-
}
|
|
30
|
-
// @ts-ignore, private method, for POC
|
|
31
|
-
getSnapshot: function () {
|
|
32
|
-
var _this = this;
|
|
33
|
-
return {
|
|
34
|
-
lastUpdated: Date.now(),
|
|
35
|
-
since: this.splits.changeNumber,
|
|
36
|
-
splitsData: this.splits.splitsCache,
|
|
37
|
-
segmentsData: Object.keys(this.segments.segmentCache).reduce(function (prev, cur) {
|
|
38
|
-
prev[cur] = setToArray(_this.segments.segmentCache[cur]);
|
|
39
|
-
return prev;
|
|
40
|
-
}, {})
|
|
41
|
-
};
|
|
42
|
-
},
|
|
28
|
+
}
|
|
43
29
|
};
|
|
44
30
|
}
|
|
45
31
|
InMemoryStorageFactory.type = STORAGE_MEMORY;
|
|
@@ -26,18 +26,6 @@ export function InMemoryStorageCSFactory(params) {
|
|
|
26
26
|
this.impressionCounts && this.impressionCounts.clear();
|
|
27
27
|
this.events.clear();
|
|
28
28
|
},
|
|
29
|
-
// @ts-ignore, private method, for POC
|
|
30
|
-
getSnapshot: function () {
|
|
31
|
-
var _a;
|
|
32
|
-
return {
|
|
33
|
-
lastUpdated: Date.now(),
|
|
34
|
-
since: this.splits.changeNumber,
|
|
35
|
-
splitsData: this.splits.splitsCache,
|
|
36
|
-
mySegmentsData: (_a = {},
|
|
37
|
-
_a[params.matchingKey] = Object.keys(this.segments.segmentCache),
|
|
38
|
-
_a)
|
|
39
|
-
};
|
|
40
|
-
},
|
|
41
29
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are unique per key)
|
|
42
30
|
shared: function () {
|
|
43
31
|
return {
|
|
@@ -16,9 +16,9 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
|
|
|
16
16
|
* SyncManager factory for modular SDK
|
|
17
17
|
*/
|
|
18
18
|
return function (params) {
|
|
19
|
-
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled,
|
|
19
|
+
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker;
|
|
20
20
|
/** Polling Manager */
|
|
21
|
-
var pollingManager =
|
|
21
|
+
var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
22
22
|
/** Push Manager */
|
|
23
23
|
var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
|
24
24
|
pushManagerFactory(params, pollingManager) :
|
|
@@ -2,7 +2,7 @@ import { ImpressionObserver } from './ImpressionObserver';
|
|
|
2
2
|
import { hash } from '../../utils/murmur3/murmur3';
|
|
3
3
|
import { buildKey } from './buildKey';
|
|
4
4
|
export function hashImpression32(impression) {
|
|
5
|
-
return hash(buildKey(impression))
|
|
5
|
+
return hash(buildKey(impression));
|
|
6
6
|
}
|
|
7
7
|
var LAST_SEEN_CACHE_SIZE = 500; // cache up to 500 impression hashes
|
|
8
8
|
export function impressionObserverCSFactory() {
|
|
@@ -124,9 +124,6 @@ export function settingsValidation(config, validationParams) {
|
|
|
124
124
|
// ensure a valid SDK mode
|
|
125
125
|
// @ts-ignore, modify readonly prop
|
|
126
126
|
withDefaults.mode = mode(withDefaults.core.authorizationKey, withDefaults.mode);
|
|
127
|
-
if (withDefaults.sync.onlySubmitters && withDefaults.mode === STANDALONE_MODE && !withDefaults.dataLoader) {
|
|
128
|
-
throw new Error('To use `onlySubmitters` param in standalone mode, DataLoader is required to preload data into the storage');
|
|
129
|
-
}
|
|
130
127
|
// ensure a valid Storage based on mode defined.
|
|
131
128
|
// @ts-ignore, modify readonly prop
|
|
132
129
|
if (storage)
|
|
@@ -169,13 +166,9 @@ export function settingsValidation(config, validationParams) {
|
|
|
169
166
|
scheduler.pushRetryBackoffBase = fromSecondsToMillis(scheduler.pushRetryBackoffBase);
|
|
170
167
|
}
|
|
171
168
|
// validate sync enabled
|
|
172
|
-
if (withDefaults.sync.enabled !== false) {
|
|
169
|
+
if (withDefaults.sync.enabled !== false) { // @ts-ignore, modify readonly prop
|
|
173
170
|
withDefaults.sync.enabled = true;
|
|
174
171
|
}
|
|
175
|
-
// validate sync onlySubmitters
|
|
176
|
-
if (withDefaults.sync.onlySubmitters !== true) {
|
|
177
|
-
withDefaults.sync.onlySubmitters = false;
|
|
178
|
-
}
|
|
179
172
|
// validate the `splitFilters` settings and parse splits query
|
|
180
173
|
var splitFiltersValidation = validateSplitFilters(log, withDefaults.sync.splitFilters, withDefaults.mode);
|
|
181
174
|
withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
|
package/package.json
CHANGED
package/src/sdkFactory/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { sdkReadinessManagerFactory } from '../readiness/sdkReadinessManager';
|
|
|
3
3
|
import { impressionsTrackerFactory } from '../trackers/impressionsTracker';
|
|
4
4
|
import { eventTrackerFactory } from '../trackers/eventTracker';
|
|
5
5
|
import { telemetryTrackerFactory } from '../trackers/telemetryTracker';
|
|
6
|
-
import { IStorageFactoryParams
|
|
6
|
+
import { IStorageFactoryParams } from '../storages/types';
|
|
7
7
|
import { SplitIO } from '../types';
|
|
8
8
|
import { getMatching } from '../utils/key';
|
|
9
9
|
import { shouldBeOptimized } from '../trackers/impressionObserver/utils';
|
|
@@ -11,7 +11,7 @@ import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey';
|
|
|
11
11
|
import { createLoggerAPI } from '../logger/sdkLogger';
|
|
12
12
|
import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
|
|
13
13
|
import { metadataBuilder } from '../storages/metadataBuilder';
|
|
14
|
-
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED
|
|
14
|
+
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
|
|
15
15
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -32,7 +32,6 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
32
32
|
|
|
33
33
|
const sdkReadinessManager = sdkReadinessManagerFactory(log, platform.EventEmitter, settings.startup.readyTimeout);
|
|
34
34
|
const readiness = sdkReadinessManager.readinessManager;
|
|
35
|
-
const matchingKey = getMatching(settings.core.key);
|
|
36
35
|
|
|
37
36
|
// @TODO consider passing the settings object, so that each storage access only what it needs
|
|
38
37
|
const storageFactoryParams: IStorageFactoryParams = {
|
|
@@ -41,7 +40,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
41
40
|
optimize: shouldBeOptimized(settings),
|
|
42
41
|
|
|
43
42
|
// ATM, only used by InLocalStorage
|
|
44
|
-
matchingKey,
|
|
43
|
+
matchingKey: getMatching(settings.core.key),
|
|
45
44
|
splitFiltersValidation: settings.sync.__splitFiltersValidation,
|
|
46
45
|
|
|
47
46
|
// ATM, only used by PluggableStorage
|
|
@@ -59,21 +58,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
59
58
|
};
|
|
60
59
|
|
|
61
60
|
const storage = storageFactory(storageFactoryParams);
|
|
62
|
-
|
|
63
|
-
// @TODO dataLoader requires validation
|
|
64
|
-
if (settings.dataLoader) {
|
|
65
|
-
settings.dataLoader(storage as IStorageSync, matchingKey);
|
|
66
|
-
Promise.resolve(storage.splits.checkCache()).then(cacheReady => {
|
|
67
|
-
if (cacheReady) {
|
|
68
|
-
if (settings.sync.onlySubmitters) { // emit SDK_READY to not timeout when not synchronizing splits & segments
|
|
69
|
-
readiness.splits.emit(SDK_SPLITS_ARRIVED);
|
|
70
|
-
readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
71
|
-
} else { // emit SDK_READY_FROM_CACHE
|
|
72
|
-
readiness.splits.emit(SDK_SPLITS_CACHE_LOADED);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
}
|
|
61
|
+
// @TODO add support for dataloader: `if (params.dataLoader) params.dataLoader(storage);`
|
|
77
62
|
|
|
78
63
|
const integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings, storage });
|
|
79
64
|
|
|
@@ -118,9 +103,5 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
118
103
|
Logger: createLoggerAPI(settings.log),
|
|
119
104
|
|
|
120
105
|
settings,
|
|
121
|
-
|
|
122
|
-
// @TODO remove
|
|
123
|
-
__storage: storage,
|
|
124
|
-
__ctx: ctx
|
|
125
106
|
}, extraProps && extraProps(ctx));
|
|
126
107
|
}
|
|
@@ -50,7 +50,7 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
50
50
|
* It is used as condition to emit SDK_SPLITS_CACHE_LOADED, and then SDK_READY_FROM_CACHE.
|
|
51
51
|
*/
|
|
52
52
|
checkCache(): boolean {
|
|
53
|
-
return
|
|
53
|
+
return false;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
@@ -3,26 +3,25 @@ import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../utils/constants/browser';
|
|
|
3
3
|
import { DataLoader, ISegmentsCacheSync, ISplitsCacheSync } from './types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Factory of storage loader
|
|
6
|
+
* Factory of client-side storage loader
|
|
7
7
|
*
|
|
8
8
|
* @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader
|
|
9
9
|
* and extended with a `mySegmentsData` property.
|
|
10
10
|
* @returns function to preload the storage
|
|
11
11
|
*/
|
|
12
|
-
export function
|
|
12
|
+
export function dataLoaderFactory(preloadedData: SplitIO.PreloadedData): DataLoader {
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Storage-agnostic adaptation of `loadDataIntoLocalStorage` function
|
|
16
16
|
* (https://github.com/godaddy/split-javascript-data-loader/blob/master/src/load-data.js)
|
|
17
17
|
*
|
|
18
18
|
* @param storage object containing `splits` and `segments` cache (client-side variant)
|
|
19
|
-
* @param
|
|
19
|
+
* @param userId user key string of the provided MySegmentsCache
|
|
20
20
|
*
|
|
21
|
+
* @TODO extend to support SegmentsCache (server-side variant) by making `userId` optional and adding the corresponding logic.
|
|
21
22
|
* @TODO extend to load data on shared mySegments storages. Be specific when emitting SDK_READY_FROM_CACHE on shared clients. Maybe the serializer should provide the `useSegments` flag.
|
|
22
|
-
* @TODO add logs, and input validation in this module, in favor of size reduction.
|
|
23
|
-
* @TODO unit tests
|
|
24
23
|
*/
|
|
25
|
-
return function loadData(storage: { splits: ISplitsCacheSync, segments: ISegmentsCacheSync },
|
|
24
|
+
return function loadData(storage: { splits: ISplitsCacheSync, segments: ISegmentsCacheSync }, userId: string) {
|
|
26
25
|
// Do not load data if current preloadedData is empty
|
|
27
26
|
if (Object.keys(preloadedData).length === 0) return;
|
|
28
27
|
|
|
@@ -42,21 +41,15 @@ export function DataLoaderFactory(preloadedData: SplitIO.PreloadedData): DataLoa
|
|
|
42
41
|
// splitsData in an object where the property is the split name and the pertaining value is a stringified json of its data
|
|
43
42
|
storage.splits.addSplits(Object.keys(splitsData).map(splitName => [splitName, splitsData[splitName]]));
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
storage.segments.resetSegments(mySegmentsData);
|
|
55
|
-
} else { // add segments data (server-side)
|
|
56
|
-
Object.keys(segmentsData).filter(segmentName => {
|
|
57
|
-
const userKeys = segmentsData[segmentName];
|
|
58
|
-
storage.segments.addToSegment(segmentName, userKeys);
|
|
44
|
+
// add mySegments data
|
|
45
|
+
let mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[userId];
|
|
46
|
+
if (!mySegmentsData) {
|
|
47
|
+
// segmentsData in an object where the property is the segment name and the pertaining value is a stringified object that contains the `added` array of userIds
|
|
48
|
+
mySegmentsData = Object.keys(segmentsData).filter(segmentName => {
|
|
49
|
+
const userIds = JSON.parse(segmentsData[segmentName]).added;
|
|
50
|
+
return Array.isArray(userIds) && userIds.indexOf(userId) > -1;
|
|
59
51
|
});
|
|
60
52
|
}
|
|
53
|
+
storage.segments.resetSegments(mySegmentsData);
|
|
61
54
|
};
|
|
62
55
|
}
|
|
@@ -6,8 +6,6 @@ import { IStorageFactoryParams, IStorageSync } from '../types';
|
|
|
6
6
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
7
7
|
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
8
8
|
import { TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
|
-
import { SplitIO } from '../../types';
|
|
10
|
-
import { setToArray, ISet } from '../../utils/lang/sets';
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* InMemory storage factory for standalone server-side SplitFactory
|
|
@@ -31,20 +29,7 @@ export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageS
|
|
|
31
29
|
this.impressions.clear();
|
|
32
30
|
this.impressionCounts && this.impressionCounts.clear();
|
|
33
31
|
this.events.clear();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// @ts-ignore, private method, for POC
|
|
37
|
-
getSnapshot(): SplitIO.PreloadedData {
|
|
38
|
-
return {
|
|
39
|
-
lastUpdated: Date.now(), // @ts-ignore accessing private prop
|
|
40
|
-
since: this.splits.changeNumber, // @ts-ignore accessing private prop
|
|
41
|
-
splitsData: this.splits.splitsCache, // @ts-ignore accessing private prop
|
|
42
|
-
segmentsData: Object.keys(this.segments.segmentCache).reduce((prev, cur) => { // @ts-ignore accessing private prop
|
|
43
|
-
prev[cur] = setToArray(this.segments.segmentCache[cur] as ISet<string>);
|
|
44
|
-
return prev;
|
|
45
|
-
}, {})
|
|
46
|
-
};
|
|
47
|
-
},
|
|
32
|
+
}
|
|
48
33
|
};
|
|
49
34
|
}
|
|
50
35
|
|