@splitsoftware/splitio-commons 3.0.0-rc.0 → 3.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.txt +8 -3
- package/cjs/evaluator/index.js +11 -11
- package/cjs/logger/constants.js +4 -4
- package/cjs/logger/messages/warn.js +0 -1
- package/cjs/readiness/constants.js +4 -4
- package/cjs/readiness/readinessManager.js +22 -22
- package/cjs/readiness/sdkReadinessManager.js +0 -16
- package/cjs/sdkClient/sdkLifecycle.js +2 -1
- package/cjs/sdkClient/trackMethod.js +2 -2
- package/cjs/sdkFactory/index.js +5 -5
- package/cjs/sdkManager/index.js +2 -2
- package/cjs/services/authProvider.js +67 -0
- package/cjs/services/secureSplitHttpClient.js +39 -0
- package/cjs/services/splitApi.js +7 -2
- package/cjs/storages/AbstractDefinitionsCacheAsync.js +51 -0
- package/cjs/storages/AbstractDefinitionsCacheSync.js +76 -0
- package/cjs/storages/KeyBuilder.js +6 -6
- package/cjs/storages/KeyBuilderCS.js +5 -5
- package/cjs/storages/KeyBuilderSS.js +2 -2
- package/cjs/storages/getRolloutPlan.js +3 -3
- package/cjs/storages/inLocalStorage/DefinitionsCacheInLocal.js +194 -0
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +9 -9
- package/cjs/storages/inLocalStorage/index.js +6 -6
- package/cjs/storages/inLocalStorage/validateCache.js +3 -3
- package/cjs/storages/inMemory/DefinitionsCacheInMemory.js +121 -0
- package/cjs/storages/inMemory/InMemoryStorage.js +4 -4
- package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +4 -4
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +3 -3
- package/cjs/storages/inRedis/{SplitsCacheInRedis.js → DefinitionsCacheInRedis.js} +77 -77
- package/cjs/storages/inRedis/index.js +2 -2
- package/cjs/storages/pluggable/DefinitionsCachePluggable.js +212 -0
- package/cjs/storages/pluggable/index.js +2 -2
- package/cjs/storages/setRolloutPlan.js +5 -5
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +5 -5
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +1 -1
- package/cjs/sync/polling/pollingManagerCS.js +7 -7
- package/cjs/sync/polling/syncTasks/definitionsSyncTask.js +1 -1
- package/cjs/sync/polling/updaters/definitionChangesUpdater.js +8 -8
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +1 -1
- package/cjs/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.js → DefinitionsUpdateWorker.js} +15 -15
- package/cjs/sync/streaming/constants.js +3 -3
- package/cjs/sync/streaming/pushManager.js +13 -13
- package/cjs/sync/submitters/telemetrySubmitter.js +1 -2
- package/cjs/sync/syncManagerOnline.js +4 -4
- package/cjs/utils/Backoff.js +20 -0
- package/cjs/utils/lang/sets.js +4 -4
- package/cjs/utils/settingsValidation/url.js +1 -1
- package/esm/evaluator/index.js +11 -11
- package/esm/logger/constants.js +1 -1
- package/esm/logger/messages/warn.js +0 -1
- package/esm/readiness/constants.js +3 -3
- package/esm/readiness/readinessManager.js +23 -23
- package/esm/readiness/sdkReadinessManager.js +1 -17
- package/esm/sdkClient/sdkLifecycle.js +2 -1
- package/esm/sdkClient/trackMethod.js +2 -2
- package/esm/sdkFactory/index.js +6 -6
- package/esm/sdkManager/index.js +2 -2
- package/esm/services/authProvider.js +63 -0
- package/esm/services/secureSplitHttpClient.js +35 -0
- package/esm/services/splitApi.js +7 -2
- package/esm/storages/AbstractDefinitionsCacheAsync.js +48 -0
- package/esm/storages/AbstractDefinitionsCacheSync.js +71 -0
- package/esm/storages/KeyBuilder.js +6 -6
- package/esm/storages/KeyBuilderCS.js +5 -5
- package/esm/storages/KeyBuilderSS.js +2 -2
- package/esm/storages/getRolloutPlan.js +3 -3
- package/esm/storages/inLocalStorage/DefinitionsCacheInLocal.js +191 -0
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +6 -6
- package/esm/storages/inLocalStorage/index.js +6 -6
- package/esm/storages/inLocalStorage/validateCache.js +3 -3
- package/esm/storages/inMemory/DefinitionsCacheInMemory.js +118 -0
- package/esm/storages/inMemory/InMemoryStorage.js +4 -4
- package/esm/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +3 -3
- package/esm/storages/inRedis/{SplitsCacheInRedis.js → DefinitionsCacheInRedis.js} +76 -76
- package/esm/storages/inRedis/index.js +2 -2
- package/esm/storages/pluggable/DefinitionsCachePluggable.js +209 -0
- package/esm/storages/pluggable/index.js +2 -2
- package/esm/storages/setRolloutPlan.js +5 -5
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +6 -6
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +1 -1
- package/esm/sync/polling/pollingManagerCS.js +4 -4
- package/esm/sync/polling/syncTasks/definitionsSyncTask.js +1 -1
- package/esm/sync/polling/updaters/definitionChangesUpdater.js +9 -9
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +1 -1
- package/esm/sync/streaming/SSEHandler/NotificationKeeper.js +2 -2
- package/esm/sync/streaming/SSEHandler/index.js +2 -2
- package/esm/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.js → DefinitionsUpdateWorker.js} +14 -14
- package/esm/sync/streaming/constants.js +2 -2
- package/esm/sync/streaming/pushManager.js +14 -14
- package/esm/sync/submitters/telemetrySubmitter.js +1 -2
- package/esm/sync/syncManagerOnline.js +3 -3
- package/esm/utils/Backoff.js +20 -0
- package/esm/utils/lang/sets.js +4 -4
- package/esm/utils/settingsValidation/url.js +1 -1
- package/package.json +1 -1
- package/src/dtos/types.ts +2 -2
- package/src/evaluator/index.ts +11 -11
- package/src/logger/constants.ts +1 -1
- package/src/logger/messages/warn.ts +0 -1
- package/src/readiness/constants.ts +3 -3
- package/src/readiness/readinessManager.ts +22 -22
- package/src/readiness/sdkReadinessManager.ts +1 -16
- package/src/readiness/types.ts +10 -16
- package/src/sdkClient/sdkLifecycle.ts +2 -1
- package/src/sdkClient/trackMethod.ts +2 -2
- package/src/sdkFactory/index.ts +5 -5
- package/src/sdkManager/index.ts +6 -6
- package/src/services/authProvider.ts +86 -0
- package/src/services/secureSplitHttpClient.ts +44 -0
- package/src/services/splitApi.ts +9 -3
- package/src/services/types.ts +4 -0
- package/src/storages/AbstractDefinitionsCacheAsync.ts +63 -0
- package/src/storages/AbstractDefinitionsCacheSync.ts +95 -0
- package/src/storages/KeyBuilder.ts +6 -6
- package/src/storages/KeyBuilderCS.ts +6 -6
- package/src/storages/KeyBuilderSS.ts +2 -2
- package/src/storages/getRolloutPlan.ts +3 -3
- package/src/storages/inLocalStorage/DefinitionsCacheInLocal.ts +234 -0
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +6 -6
- package/src/storages/inLocalStorage/index.ts +6 -6
- package/src/storages/inLocalStorage/validateCache.ts +4 -4
- package/src/storages/inMemory/DefinitionsCacheInMemory.ts +130 -0
- package/src/storages/inMemory/InMemoryStorage.ts +4 -4
- package/src/storages/inMemory/InMemoryStorageCS.ts +5 -5
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +1 -1
- package/src/storages/inMemory/SegmentsCacheInMemory.ts +1 -1
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +3 -3
- package/src/storages/inRedis/{SplitsCacheInRedis.ts → DefinitionsCacheInRedis.ts} +67 -67
- package/src/storages/inRedis/index.ts +2 -2
- package/src/storages/pluggable/DefinitionsCachePluggable.ts +230 -0
- package/src/storages/pluggable/index.ts +2 -2
- package/src/storages/setRolloutPlan.ts +7 -7
- package/src/storages/types.ts +19 -19
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +8 -8
- package/src/sync/polling/fetchers/splitChangesFetcher.ts +3 -3
- package/src/sync/polling/pollingManagerCS.ts +4 -4
- package/src/sync/polling/syncTasks/definitionsSyncTask.ts +1 -1
- package/src/sync/polling/types.ts +1 -1
- package/src/sync/polling/updaters/definitionChangesUpdater.ts +11 -11
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +1 -1
- package/src/sync/streaming/AuthClient/index.ts +2 -2
- package/src/sync/streaming/AuthClient/types.ts +14 -11
- package/src/sync/streaming/SSEClient/index.ts +2 -2
- package/src/sync/streaming/SSEClient/types.ts +2 -2
- package/src/sync/streaming/SSEHandler/NotificationKeeper.ts +2 -2
- package/src/sync/streaming/SSEHandler/index.ts +2 -2
- package/src/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.ts → DefinitionsUpdateWorker.ts} +16 -16
- package/src/sync/streaming/constants.ts +2 -2
- package/src/sync/streaming/pushManager.ts +16 -16
- package/src/sync/streaming/types.ts +2 -2
- package/src/sync/submitters/telemetrySubmitter.ts +1 -2
- package/src/sync/syncManagerOnline.ts +3 -3
- package/src/utils/Backoff.ts +21 -0
- package/src/utils/inputValidation/trafficTypeExistence.ts +2 -2
- package/src/utils/jwt/types.ts +1 -1
- package/src/utils/lang/sets.ts +4 -2
- package/src/utils/settingsValidation/url.ts +1 -1
- package/types/splitio.d.ts +23 -5
- package/cjs/storages/AbstractSplitsCacheAsync.js +0 -51
- package/cjs/storages/AbstractSplitsCacheSync.js +0 -76
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +0 -194
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +0 -121
- package/cjs/storages/pluggable/SplitsCachePluggable.js +0 -212
- package/esm/storages/AbstractSplitsCacheAsync.js +0 -48
- package/esm/storages/AbstractSplitsCacheSync.js +0 -71
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +0 -191
- package/esm/storages/inMemory/SplitsCacheInMemory.js +0 -118
- package/esm/storages/pluggable/SplitsCachePluggable.js +0 -209
- package/src/storages/AbstractSplitsCacheAsync.ts +0 -63
- package/src/storages/AbstractSplitsCacheSync.ts +0 -95
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +0 -234
- package/src/storages/inMemory/SplitsCacheInMemory.ts +0 -130
- package/src/storages/pluggable/SplitsCachePluggable.ts +0 -230
package/CHANGES.txt
CHANGED
|
@@ -4,13 +4,18 @@
|
|
|
4
4
|
- Added a bloom filter utility and platform-specific modules (`src/platform/`) for reuse across SDKs.
|
|
5
5
|
- Added support for the Configs SDK:
|
|
6
6
|
- new type declarations,
|
|
7
|
-
-
|
|
7
|
+
- fallback calculator with sanitizer,
|
|
8
8
|
- default treatment evaluation (without a target),
|
|
9
|
-
-
|
|
10
|
-
-
|
|
9
|
+
- new `CONFIGS_UPDATE` metadata type for `SDK_UPDATE` event,
|
|
10
|
+
- optional `entityType` field in the `/testImpressions/bulk` payload,
|
|
11
11
|
- input validation for the target object.
|
|
12
|
+
- Removed the misleading warning log 'No listeners for SDK_READY event detected', since users can use the `whenReady` method to wait for the SDK to be ready.
|
|
12
13
|
- BREAKING CHANGES: Renamed some types and modules, and updated the signatures of others for clarity and reusability.
|
|
13
14
|
|
|
15
|
+
2.12.1 (April 30, 2026)
|
|
16
|
+
- Updated internal modules to handle `null` values from `/splitChanges` response.
|
|
17
|
+
- Updated some dependencies for vulnerability fixes.
|
|
18
|
+
|
|
14
19
|
2.12.0 (February 24, 2026)
|
|
15
20
|
- Added support for ioredis v5 (Related to issue https://github.com/splitio/javascript-commons/issues/471).
|
|
16
21
|
|
package/cjs/evaluator/index.js
CHANGED
|
@@ -27,15 +27,15 @@ function treatmentsException(definitionNames) {
|
|
|
27
27
|
function evaluateFeature(log, key, definitionName, attributes, storage, options) {
|
|
28
28
|
var definition;
|
|
29
29
|
try {
|
|
30
|
-
definition = storage.
|
|
30
|
+
definition = storage.definitions.get(definitionName);
|
|
31
31
|
}
|
|
32
32
|
catch (e) {
|
|
33
|
-
// Exception on sync
|
|
33
|
+
// Exception on sync storage. Not possible ATM with InMemory and InLocal storages.
|
|
34
34
|
return EVALUATION_EXCEPTION;
|
|
35
35
|
}
|
|
36
36
|
if ((0, thenable_1.thenable)(definition)) {
|
|
37
37
|
return definition.then(function (definition) { return getEvaluation(log, key, definition, attributes, storage, options); }).catch(
|
|
38
|
-
// Exception on async
|
|
38
|
+
// Exception on async storage. For example, when the storage is redis or
|
|
39
39
|
// pluggable and there is a connection issue and we can't retrieve the split to be evaluated
|
|
40
40
|
function () { return EVALUATION_EXCEPTION; });
|
|
41
41
|
}
|
|
@@ -45,16 +45,16 @@ exports.evaluateFeature = evaluateFeature;
|
|
|
45
45
|
function evaluateFeatures(log, key, definitionNames, attributes, storage, options) {
|
|
46
46
|
var definitions;
|
|
47
47
|
try {
|
|
48
|
-
definitions = storage.
|
|
48
|
+
definitions = storage.definitions.getMany(definitionNames);
|
|
49
49
|
}
|
|
50
50
|
catch (e) {
|
|
51
|
-
// Exception on sync
|
|
51
|
+
// Exception on sync storage. Not possible ATM with InMemory and InLocal storages.
|
|
52
52
|
return treatmentsException(definitionNames);
|
|
53
53
|
}
|
|
54
54
|
return (0, thenable_1.thenable)(definitions) ?
|
|
55
55
|
definitions.then(function (definitions) { return getEvaluations(log, key, definitionNames, definitions, attributes, storage, options); })
|
|
56
56
|
.catch(function () {
|
|
57
|
-
// Exception on async
|
|
57
|
+
// Exception on async storage. For example, when the storage is redis or
|
|
58
58
|
// pluggable and there is a connection issue and we can't retrieve the split to be evaluated
|
|
59
59
|
return treatmentsException(definitionNames);
|
|
60
60
|
}) :
|
|
@@ -80,7 +80,7 @@ function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, storage, met
|
|
|
80
80
|
}
|
|
81
81
|
// get features by flag sets
|
|
82
82
|
try {
|
|
83
|
-
storedFlagNames = storage.
|
|
83
|
+
storedFlagNames = storage.definitions.getNamesBySets(flagSets);
|
|
84
84
|
}
|
|
85
85
|
catch (e) {
|
|
86
86
|
// return empty evaluations
|
|
@@ -99,7 +99,7 @@ function getEvaluation(log, key, definition, attributes, storage, options) {
|
|
|
99
99
|
if (definition) {
|
|
100
100
|
var split = (0, Engine_1.engineParser)(log, definition, storage);
|
|
101
101
|
var evaluation = split.getTreatment(key, attributes, evaluateFeature);
|
|
102
|
-
// If the storage is async and the evaluated
|
|
102
|
+
// If the storage is async and the evaluated definition uses segments or dependencies, evaluation is thenable
|
|
103
103
|
if ((0, thenable_1.thenable)(evaluation)) {
|
|
104
104
|
return evaluation.then(function (result) {
|
|
105
105
|
result.changeNumber = definition.changeNumber;
|
|
@@ -119,11 +119,11 @@ function getEvaluation(log, key, definition, attributes, storage, options) {
|
|
|
119
119
|
}
|
|
120
120
|
return EVALUATION_DEFINITION_NOT_FOUND;
|
|
121
121
|
}
|
|
122
|
-
function getEvaluations(log, key, definitionNames,
|
|
122
|
+
function getEvaluations(log, key, definitionNames, definitions, attributes, storage, options) {
|
|
123
123
|
var result = {};
|
|
124
124
|
var thenables = [];
|
|
125
125
|
definitionNames.forEach(function (definitionName) {
|
|
126
|
-
var evaluation = getEvaluation(log, key,
|
|
126
|
+
var evaluation = getEvaluation(log, key, definitions[definitionName], attributes, storage, options);
|
|
127
127
|
if ((0, thenable_1.thenable)(evaluation)) {
|
|
128
128
|
thenables.push(evaluation.then(function (res) {
|
|
129
129
|
result[definitionName] = res;
|
|
@@ -138,7 +138,7 @@ function getEvaluations(log, key, definitionNames, splits, attributes, storage,
|
|
|
138
138
|
function evaluateDefaultTreatment(definitionName, storage) {
|
|
139
139
|
var definition;
|
|
140
140
|
try {
|
|
141
|
-
definition = storage.
|
|
141
|
+
definition = storage.definitions.get(definitionName);
|
|
142
142
|
}
|
|
143
143
|
catch (e) {
|
|
144
144
|
return EVALUATION_EXCEPTION;
|
package/cjs/logger/constants.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.ERROR_STORAGE_INVALID = exports.ERROR_HTTP = exports.ERROR_INVALID_CONFIG_PARAM = exports.ERROR_EMPTY_ARRAY = exports.ERROR_EMPTY = exports.ERROR_INVALID = exports.ERROR_INVALID_KEY_OBJECT = exports.ERROR_TOO_LONG = exports.ERROR_NULL = exports.ERROR_CLIENT_DESTROYED = exports.ERROR_NOT_FINITE = exports.ERROR_SIZE_EXCEEDED = exports.ERROR_NOT_PLAIN_OBJECT = exports.ERROR_EVENT_TYPE_FORMAT = exports.ERROR_EVENTS_TRACKER = exports.ERROR_IMPRESSIONS_LISTENER = exports.ERROR_IMPRESSIONS_TRACKER = exports.ERROR_STREAMING_AUTH = exports.ERROR_STREAMING_SSE = exports.ERROR_SYNC_OFFLINE_LOADING = exports.ERROR_CLIENT_CANNOT_GET_READY = exports.ERROR_CLIENT_LISTENER = exports.ERROR_LOGLEVEL_INVALID = exports.ERROR_ENGINE_COMBINER_IFELSEIF = exports.WARN_FLAGSET_WITHOUT_FLAGS = exports.WARN_FLAGSET_NOT_CONFIGURED = exports.WARN_LOWERCASE_FLAGSET = exports.WARN_INVALID_FLAGSET = exports.STREAMING_PARSING_SPLIT_UPDATE = exports.STREAMING_PARSING_MEMBERSHIPS_UPDATE = exports.WARN_SDK_KEY = exports.WARN_SPLITS_FILTER_EMPTY = exports.WARN_SPLITS_FILTER_INVALID = exports.WARN_SPLITS_FILTER_IGNORED = exports.WARN_INTEGRATION_INVALID = exports.WARN_NOT_EXISTENT_TT = exports.WARN_LOWERCASE_TRAFFIC_TYPE = exports.WARN_NOT_EXISTENT_DEFINITION = exports.WARN_TRIMMING = exports.WARN_CONVERTING = exports.WARN_TRIMMING_PROPERTIES = exports.WARN_SETTING_NULL = exports.SUBMITTERS_PUSH_RETRY = exports.SUBMITTERS_PUSH_FAILS = exports.STREAMING_FALLBACK = exports.STREAMING_PARSING_MESSAGE_FAILS = exports.STREAMING_PARSING_ERROR_FAILS = exports.SYNC_FETCH_FAILS = exports.SYNC_FETCH_RETRY =
|
|
5
|
-
exports.LOG_PREFIX_CLEANUP = exports.LOG_PREFIX_UNIQUE_KEYS_TRACKER = exports.LOG_PREFIX_EVENTS_TRACKER = exports.LOG_PREFIX_IMPRESSIONS_TRACKER = exports.LOG_PREFIX_SYNC_SUBMITTERS = exports.LOG_PREFIX_SYNC_POLLING = exports.LOG_PREFIX_SYNC_STREAMING = exports.LOG_PREFIX_SYNC_OFFLINE = exports.LOG_PREFIX_SYNC_MANAGER = exports.LOG_PREFIX_SYNC = exports.LOG_PREFIX_ENGINE_VALUE = exports.LOG_PREFIX_ENGINE_MATCHER = exports.LOG_PREFIX_ENGINE_COMBINER = exports.LOG_PREFIX_ENGINE = exports.LOG_PREFIX_CLIENT_INSTANTIATION = exports.LOG_PREFIX_INSTANTIATION = exports.LOG_PREFIX_SETTINGS = exports.ENGINE_MATCHER_ERROR = exports.ERROR_SETS_FILTER_EXCLUSIVE = exports.ERROR_TOO_MANY_SETS = exports.ERROR_MIN_CONFIG_PARAM =
|
|
3
|
+
exports.CLIENT_NOT_READY_FROM_CACHE = exports.ENGINE_VALUE_NO_ATTRIBUTES = exports.ENGINE_VALUE_INVALID = exports.SUBMITTERS_PUSH_PAGE_HIDDEN = exports.USER_CONSENT_INITIAL = exports.USER_CONSENT_NOT_UPDATED = exports.USER_CONSENT_UPDATED = exports.IMPRESSIONS_TRACKER_SUCCESS = exports.EVENTS_TRACKER_SUCCESS = exports.SYNC_STOP_POLLING = exports.SYNC_CONTINUE_POLLING = exports.SYNC_START_POLLING = exports.SUBMITTERS_PUSH = exports.SUBMITTERS_PUSH_FULL_QUEUE = exports.STREAMING_DISCONNECTING = exports.STREAMING_DISABLED = exports.STREAMING_CONNECTING = exports.STREAMING_RECONNECT = exports.STREAMING_REFRESH_TOKEN = exports.POLLING_STOP = exports.POLLING_START = exports.POLLING_SMART_PAUSING = exports.NEW_FACTORY = exports.NEW_SHARED_CLIENT = exports.IMPRESSION_QUEUEING = exports.CLIENT_READY = exports.CLIENT_READY_FROM_CACHE = exports.ENGINE_DEFAULT = exports.ENGINE_MATCHER_RESULT = exports.SETTINGS_SPLITS_FILTER = exports.SYNC_TASK_STOP = exports.SYNC_TASK_EXECUTE = exports.SYNC_TASK_START = exports.STREAMING_NEW_MESSAGE = exports.SYNC_UPDATE = exports.SYNC_FETCH = exports.SYNC_OFFLINE_DATA = exports.RETRIEVE_MANAGER = exports.RETRIEVE_CLIENT_EXISTING = exports.RETRIEVE_CLIENT_DEFAULT = exports.CLEANUP_DEREGISTERING = exports.CLEANUP_REGISTERING = exports.ENGINE_SANITIZE = exports.ENGINE_VALUE = exports.ENGINE_MATCHER_DEPENDENCY_PRE = exports.ENGINE_MATCHER_DEPENDENCY = exports.ENGINE_BUCKET = exports.ENGINE_COMBINER_IFELSEIF_NO_TREATMENT = exports.ENGINE_COMBINER_IFELSEIF = exports.ENGINE_COMBINER_AND = void 0;
|
|
4
|
+
exports.ERROR_NOT_BOOLEAN = exports.ERROR_STORAGE_INVALID = exports.ERROR_HTTP = exports.ERROR_INVALID_CONFIG_PARAM = exports.ERROR_EMPTY_ARRAY = exports.ERROR_EMPTY = exports.ERROR_INVALID = exports.ERROR_INVALID_KEY_OBJECT = exports.ERROR_TOO_LONG = exports.ERROR_NULL = exports.ERROR_CLIENT_DESTROYED = exports.ERROR_NOT_FINITE = exports.ERROR_SIZE_EXCEEDED = exports.ERROR_NOT_PLAIN_OBJECT = exports.ERROR_EVENT_TYPE_FORMAT = exports.ERROR_EVENTS_TRACKER = exports.ERROR_IMPRESSIONS_LISTENER = exports.ERROR_IMPRESSIONS_TRACKER = exports.ERROR_STREAMING_AUTH = exports.ERROR_STREAMING_SSE = exports.ERROR_SYNC_OFFLINE_LOADING = exports.ERROR_CLIENT_CANNOT_GET_READY = exports.ERROR_CLIENT_LISTENER = exports.ERROR_LOGLEVEL_INVALID = exports.ERROR_ENGINE_COMBINER_IFELSEIF = exports.WARN_FLAGSET_WITHOUT_FLAGS = exports.WARN_FLAGSET_NOT_CONFIGURED = exports.WARN_LOWERCASE_FLAGSET = exports.WARN_INVALID_FLAGSET = exports.STREAMING_PARSING_SPLIT_UPDATE = exports.STREAMING_PARSING_MEMBERSHIPS_UPDATE = exports.WARN_SDK_KEY = exports.WARN_SPLITS_FILTER_EMPTY = exports.WARN_SPLITS_FILTER_INVALID = exports.WARN_SPLITS_FILTER_IGNORED = exports.WARN_INTEGRATION_INVALID = exports.WARN_NOT_EXISTENT_TT = exports.WARN_LOWERCASE_TRAFFIC_TYPE = exports.WARN_NOT_EXISTENT_DEFINITION = exports.WARN_TRIMMING = exports.WARN_CONVERTING = exports.WARN_TRIMMING_PROPERTIES = exports.WARN_SETTING_NULL = exports.SUBMITTERS_PUSH_RETRY = exports.SUBMITTERS_PUSH_FAILS = exports.STREAMING_FALLBACK = exports.STREAMING_PARSING_MESSAGE_FAILS = exports.STREAMING_PARSING_ERROR_FAILS = exports.SYNC_FETCH_FAILS = exports.SYNC_FETCH_RETRY = void 0;
|
|
5
|
+
exports.LOG_PREFIX_CLEANUP = exports.LOG_PREFIX_UNIQUE_KEYS_TRACKER = exports.LOG_PREFIX_EVENTS_TRACKER = exports.LOG_PREFIX_IMPRESSIONS_TRACKER = exports.LOG_PREFIX_SYNC_SUBMITTERS = exports.LOG_PREFIX_SYNC_POLLING = exports.LOG_PREFIX_SYNC_STREAMING = exports.LOG_PREFIX_SYNC_OFFLINE = exports.LOG_PREFIX_SYNC_MANAGER = exports.LOG_PREFIX_SYNC_AUTH = exports.LOG_PREFIX_SYNC = exports.LOG_PREFIX_ENGINE_VALUE = exports.LOG_PREFIX_ENGINE_MATCHER = exports.LOG_PREFIX_ENGINE_COMBINER = exports.LOG_PREFIX_ENGINE = exports.LOG_PREFIX_CLIENT_INSTANTIATION = exports.LOG_PREFIX_INSTANTIATION = exports.LOG_PREFIX_SETTINGS = exports.ENGINE_MATCHER_ERROR = exports.ERROR_SETS_FILTER_EXCLUSIVE = exports.ERROR_TOO_MANY_SETS = exports.ERROR_MIN_CONFIG_PARAM = void 0;
|
|
6
6
|
/**
|
|
7
7
|
* Message codes used to trim string log messages from commons and client-side API modules,
|
|
8
8
|
* in order to reduce the minimal SDK size for Browser and eventually other client-side environments.
|
|
@@ -59,7 +59,6 @@ exports.USER_CONSENT_INITIAL = 124;
|
|
|
59
59
|
exports.SUBMITTERS_PUSH_PAGE_HIDDEN = 125;
|
|
60
60
|
exports.ENGINE_VALUE_INVALID = 200;
|
|
61
61
|
exports.ENGINE_VALUE_NO_ATTRIBUTES = 201;
|
|
62
|
-
exports.CLIENT_NO_LISTENER = 202;
|
|
63
62
|
exports.CLIENT_NOT_READY_FROM_CACHE = 203;
|
|
64
63
|
exports.SYNC_FETCH_RETRY = 204;
|
|
65
64
|
exports.SYNC_FETCH_FAILS = 205;
|
|
@@ -124,6 +123,7 @@ exports.LOG_PREFIX_ENGINE_COMBINER = exports.LOG_PREFIX_ENGINE + ':combiner: ';
|
|
|
124
123
|
exports.LOG_PREFIX_ENGINE_MATCHER = exports.LOG_PREFIX_ENGINE + ':matcher: ';
|
|
125
124
|
exports.LOG_PREFIX_ENGINE_VALUE = exports.LOG_PREFIX_ENGINE + ':value: ';
|
|
126
125
|
exports.LOG_PREFIX_SYNC = 'sync: ';
|
|
126
|
+
exports.LOG_PREFIX_SYNC_AUTH = 'sync:auth: ';
|
|
127
127
|
exports.LOG_PREFIX_SYNC_MANAGER = 'sync:sync-manager: ';
|
|
128
128
|
exports.LOG_PREFIX_SYNC_OFFLINE = 'sync:offline: ';
|
|
129
129
|
exports.LOG_PREFIX_SYNC_STREAMING = 'sync:streaming: ';
|
|
@@ -18,7 +18,6 @@ exports.codesWarn = error_1.codesError.concat([
|
|
|
18
18
|
[c.SUBMITTERS_PUSH_RETRY, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Failed to push %s, keeping data to retry on next iteration. Reason: %s'],
|
|
19
19
|
// client status
|
|
20
20
|
[c.CLIENT_NOT_READY_FROM_CACHE, '%s: the SDK is not ready to evaluate. Results may be incorrect. Make sure to wait for SDK readiness before using this method.'],
|
|
21
|
-
[c.CLIENT_NO_LISTENER, 'No listeners for SDK_READY event detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet synchronized with the backend.'],
|
|
22
21
|
// input validation
|
|
23
22
|
[c.WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'],
|
|
24
23
|
[c.WARN_TRIMMING_PROPERTIES, '%s: more than 300 properties were provided. Some of them will be trimmed when processed.'],
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CONFIGS_UPDATE = exports.SEGMENTS_UPDATE = exports.FLAGS_UPDATE = exports.SDK_UPDATE = exports.SDK_READY_FROM_CACHE = exports.SDK_READY = exports.SDK_READY_TIMED_OUT = exports.SDK_SEGMENTS_ARRIVED = exports.
|
|
4
|
-
//
|
|
5
|
-
exports.
|
|
6
|
-
exports.
|
|
3
|
+
exports.CONFIGS_UPDATE = exports.SEGMENTS_UPDATE = exports.FLAGS_UPDATE = exports.SDK_UPDATE = exports.SDK_READY_FROM_CACHE = exports.SDK_READY = exports.SDK_READY_TIMED_OUT = exports.SDK_SEGMENTS_ARRIVED = exports.SDK_DEFINITIONS_CACHE_LOADED = exports.SDK_DEFINITIONS_ARRIVED = void 0;
|
|
4
|
+
// Definitions events:
|
|
5
|
+
exports.SDK_DEFINITIONS_ARRIVED = 'state::splits-arrived';
|
|
6
|
+
exports.SDK_DEFINITIONS_CACHE_LOADED = 'state::splits-cache-loaded';
|
|
7
7
|
// Segments events:
|
|
8
8
|
exports.SDK_SEGMENTS_ARRIVED = 'state::segments-arrived';
|
|
9
9
|
// Readiness events:
|
|
@@ -3,20 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.readinessManagerFactory = void 0;
|
|
4
4
|
var objectAssign_1 = require("../utils/lang/objectAssign");
|
|
5
5
|
var constants_1 = require("./constants");
|
|
6
|
-
function
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
function definitionsEventEmitterFactory(EventEmitter) {
|
|
7
|
+
var definitionsEventEmitter = (0, objectAssign_1.objectAssign)(new EventEmitter(), {
|
|
8
|
+
definitionsArrived: false,
|
|
9
|
+
definitionsCacheLoaded: false,
|
|
10
10
|
hasInit: false,
|
|
11
11
|
initCallbacks: []
|
|
12
12
|
});
|
|
13
13
|
// `isSplitKill` condition avoids an edge-case of wrongly emitting SDK_READY if:
|
|
14
14
|
// - `/memberships` fetch and SPLIT_KILL occurs before `/splitChanges` fetch, and
|
|
15
15
|
// - storage has cached splits (for which case `splitsStorage.killLocally` can return true)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return
|
|
16
|
+
definitionsEventEmitter.on(constants_1.SDK_DEFINITIONS_ARRIVED, function (metadata, isSplitKill) { if (!isSplitKill)
|
|
17
|
+
definitionsEventEmitter.definitionsArrived = true; });
|
|
18
|
+
definitionsEventEmitter.once(constants_1.SDK_DEFINITIONS_CACHE_LOADED, function () { definitionsEventEmitter.definitionsCacheLoaded = true; });
|
|
19
|
+
return definitionsEventEmitter;
|
|
20
20
|
}
|
|
21
21
|
function segmentsEventEmitterFactory(EventEmitter) {
|
|
22
22
|
var segmentsEventEmitter = (0, objectAssign_1.objectAssign)(new EventEmitter(), {
|
|
@@ -28,8 +28,8 @@ function segmentsEventEmitterFactory(EventEmitter) {
|
|
|
28
28
|
/**
|
|
29
29
|
* Factory of readiness manager, which handles the ready / update event propagation.
|
|
30
30
|
*/
|
|
31
|
-
function readinessManagerFactory(EventEmitter, settings,
|
|
32
|
-
if (
|
|
31
|
+
function readinessManagerFactory(EventEmitter, settings, definitions, isShared) {
|
|
32
|
+
if (definitions === void 0) { definitions = definitionsEventEmitterFactory(EventEmitter); }
|
|
33
33
|
var readyTimeout = settings.startup.readyTimeout;
|
|
34
34
|
var segments = segmentsEventEmitterFactory(EventEmitter);
|
|
35
35
|
var gate = new EventEmitter();
|
|
@@ -44,10 +44,10 @@ function readinessManagerFactory(EventEmitter, settings, splits, isShared) {
|
|
|
44
44
|
};
|
|
45
45
|
// emit SDK_READY_FROM_CACHE
|
|
46
46
|
var isReadyFromCache = false;
|
|
47
|
-
if (
|
|
47
|
+
if (definitions.definitionsCacheLoaded)
|
|
48
48
|
isReadyFromCache = true; // ready from cache, but doesn't emit SDK_READY_FROM_CACHE
|
|
49
49
|
else
|
|
50
|
-
|
|
50
|
+
definitions.once(constants_1.SDK_DEFINITIONS_CACHE_LOADED, checkIsReadyFromCache);
|
|
51
51
|
// emit SDK_READY_TIMED_OUT
|
|
52
52
|
var hasTimedout = false;
|
|
53
53
|
function timeout() {
|
|
@@ -59,7 +59,7 @@ function readinessManagerFactory(EventEmitter, settings, splits, isShared) {
|
|
|
59
59
|
}
|
|
60
60
|
// emit SDK_READY and SDK_UPDATE
|
|
61
61
|
var isReady = false;
|
|
62
|
-
|
|
62
|
+
definitions.on(constants_1.SDK_DEFINITIONS_ARRIVED, checkIsReadyOrUpdate);
|
|
63
63
|
segments.on(constants_1.SDK_SEGMENTS_ARRIVED, checkIsReadyOrUpdate);
|
|
64
64
|
var isDestroyed = false;
|
|
65
65
|
var readyTimeoutId;
|
|
@@ -68,8 +68,8 @@ function readinessManagerFactory(EventEmitter, settings, splits, isShared) {
|
|
|
68
68
|
if (readyTimeout > 0 && !isReady)
|
|
69
69
|
readyTimeoutId = setTimeout(timeout, readyTimeout);
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
if (
|
|
71
|
+
definitions.initCallbacks.push(__init);
|
|
72
|
+
if (definitions.hasInit)
|
|
73
73
|
__init();
|
|
74
74
|
function checkIsReadyFromCache(cacheMetadata) {
|
|
75
75
|
metadataReady = cacheMetadata;
|
|
@@ -100,7 +100,7 @@ function readinessManagerFactory(EventEmitter, settings, splits, isShared) {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
103
|
-
if (
|
|
103
|
+
if (definitions.definitionsArrived && segments.segmentsArrived) {
|
|
104
104
|
clearTimeout(readyTimeoutId);
|
|
105
105
|
isReady = true;
|
|
106
106
|
try {
|
|
@@ -123,11 +123,11 @@ function readinessManagerFactory(EventEmitter, settings, splits, isShared) {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
return {
|
|
126
|
-
|
|
126
|
+
definitions: definitions,
|
|
127
127
|
segments: segments,
|
|
128
128
|
gate: gate,
|
|
129
129
|
shared: function () {
|
|
130
|
-
return readinessManagerFactory(EventEmitter, settings,
|
|
130
|
+
return readinessManagerFactory(EventEmitter, settings, definitions, true);
|
|
131
131
|
},
|
|
132
132
|
// @TODO review/remove next methods when non-recoverable errors are reworked
|
|
133
133
|
// Called on consumer mode, when storage fails to connect
|
|
@@ -136,17 +136,17 @@ function readinessManagerFactory(EventEmitter, settings, splits, isShared) {
|
|
|
136
136
|
// tracking and evaluations, while keeping event listeners to emit SDK_READY_TIMED_OUT event
|
|
137
137
|
setDestroyed: function () { isDestroyed = true; },
|
|
138
138
|
init: function () {
|
|
139
|
-
if (
|
|
139
|
+
if (definitions.hasInit)
|
|
140
140
|
return;
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
definitions.hasInit = true;
|
|
142
|
+
definitions.initCallbacks.forEach(function (cb) { return cb(); });
|
|
143
143
|
},
|
|
144
144
|
destroy: function () {
|
|
145
145
|
isDestroyed = true;
|
|
146
146
|
syncLastUpdate();
|
|
147
147
|
clearTimeout(readyTimeoutId);
|
|
148
148
|
if (!isShared)
|
|
149
|
-
|
|
149
|
+
definitions.hasInit = false;
|
|
150
150
|
},
|
|
151
151
|
isReady: function () { return isReady; },
|
|
152
152
|
isReadyFromCache: function () { return isReadyFromCache; },
|
|
@@ -7,7 +7,6 @@ var readinessManager_1 = require("./readinessManager");
|
|
|
7
7
|
var constants_1 = require("./constants");
|
|
8
8
|
var constants_2 = require("../logger/constants");
|
|
9
9
|
var NEW_LISTENER_EVENT = 'newListener';
|
|
10
|
-
var REMOVE_LISTENER_EVENT = 'removeListener';
|
|
11
10
|
var TIMEOUT_ERROR = new Error(constants_1.SDK_READY_TIMED_OUT);
|
|
12
11
|
/**
|
|
13
12
|
* SdkReadinessManager factory, which provides the public status API of SDK clients and manager: ready promise, readiness event emitter and constants (SDK_READY, etc).
|
|
@@ -19,21 +18,11 @@ var TIMEOUT_ERROR = new Error(constants_1.SDK_READY_TIMED_OUT);
|
|
|
19
18
|
function sdkReadinessManagerFactory(EventEmitter, settings, readinessManager) {
|
|
20
19
|
if (readinessManager === void 0) { readinessManager = (0, readinessManager_1.readinessManagerFactory)(EventEmitter, settings); }
|
|
21
20
|
var log = settings.log;
|
|
22
|
-
/** Ready callback warning */
|
|
23
|
-
var internalReadyCbCount = 0;
|
|
24
|
-
var readyCbCount = 0;
|
|
25
|
-
readinessManager.gate.on(REMOVE_LISTENER_EVENT, function (event) {
|
|
26
|
-
if (event === constants_1.SDK_READY)
|
|
27
|
-
readyCbCount--;
|
|
28
|
-
});
|
|
29
21
|
readinessManager.gate.on(NEW_LISTENER_EVENT, function (event) {
|
|
30
22
|
if (event === constants_1.SDK_READY || event === constants_1.SDK_READY_TIMED_OUT) {
|
|
31
23
|
if (readinessManager.isReady()) {
|
|
32
24
|
log.error(constants_2.ERROR_CLIENT_LISTENER, [event === constants_1.SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT']);
|
|
33
25
|
}
|
|
34
|
-
else if (event === constants_1.SDK_READY) {
|
|
35
|
-
readyCbCount++;
|
|
36
|
-
}
|
|
37
26
|
}
|
|
38
27
|
else if (event === constants_1.SDK_READY_FROM_CACHE && readinessManager.isReadyFromCache()) {
|
|
39
28
|
log.error(constants_2.ERROR_CLIENT_LISTENER, ['SDK_READY_FROM_CACHE']);
|
|
@@ -52,8 +41,6 @@ function sdkReadinessManagerFactory(EventEmitter, settings, readinessManager) {
|
|
|
52
41
|
var promise = (0, wrapper_1.promiseWrapper)(new Promise(function (resolve, reject) {
|
|
53
42
|
readinessManager.gate.once(constants_1.SDK_READY, function () {
|
|
54
43
|
log.info(constants_2.CLIENT_READY);
|
|
55
|
-
if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled())
|
|
56
|
-
log.warn(constants_2.CLIENT_NO_LISTENER);
|
|
57
44
|
resolve();
|
|
58
45
|
});
|
|
59
46
|
readinessManager.gate.once(constants_1.SDK_READY_TIMED_OUT, function (message) {
|
|
@@ -78,9 +65,6 @@ function sdkReadinessManagerFactory(EventEmitter, settings, readinessManager) {
|
|
|
78
65
|
shared: function () {
|
|
79
66
|
return sdkReadinessManagerFactory(EventEmitter, settings, readinessManager.shared());
|
|
80
67
|
},
|
|
81
|
-
incInternalReadyCbCount: function () {
|
|
82
|
-
internalReadyCbCount++;
|
|
83
|
-
},
|
|
84
68
|
sdkStatus: (0, objectAssign_1.objectAssign)(
|
|
85
69
|
// Expose Event Emitter functionality
|
|
86
70
|
Object.create(readinessManager.gate), {
|
|
@@ -7,7 +7,7 @@ var COOLDOWN_TIME_IN_MILLIS = 1000;
|
|
|
7
7
|
* Creates an Sdk client, i.e., a base client with status, init, flush and destroy interface
|
|
8
8
|
*/
|
|
9
9
|
function sdkLifecycleFactory(params, isSharedClient) {
|
|
10
|
-
var sdkReadinessManager = params.sdkReadinessManager, syncManager = params.syncManager, storage = params.storage, settings = params.settings, telemetryTracker = params.telemetryTracker, impressionsTracker = params.impressionsTracker, platform = params.platform;
|
|
10
|
+
var sdkReadinessManager = params.sdkReadinessManager, syncManager = params.syncManager, storage = params.storage, settings = params.settings, telemetryTracker = params.telemetryTracker, impressionsTracker = params.impressionsTracker, platform = params.platform, splitApi = params.splitApi;
|
|
11
11
|
var hasInit = false;
|
|
12
12
|
var lastActionTime = 0;
|
|
13
13
|
var signalListener = platform.SignalListener && new platform.SignalListener(params);
|
|
@@ -60,6 +60,7 @@ function sdkLifecycleFactory(params, isSharedClient) {
|
|
|
60
60
|
}
|
|
61
61
|
// Stop background jobs
|
|
62
62
|
syncManager && syncManager.stop();
|
|
63
|
+
splitApi && splitApi.stop();
|
|
63
64
|
return __flush().then(function () {
|
|
64
65
|
// Cleanup storage
|
|
65
66
|
return storage.destroy();
|
|
@@ -13,7 +13,7 @@ var mode_1 = require("../utils/settingsValidation/mode");
|
|
|
13
13
|
*/
|
|
14
14
|
function trackMethodFactory(params, warnTTExistence) {
|
|
15
15
|
if (warnTTExistence === void 0) { warnTTExistence = true; }
|
|
16
|
-
var settings = params.settings,
|
|
16
|
+
var settings = params.settings, definitions = params.storage.definitions, telemetryTracker = params.telemetryTracker, eventTracker = params.eventTracker, readinessManager = params.sdkReadinessManager.readinessManager;
|
|
17
17
|
var log = settings.log, mode = settings.mode;
|
|
18
18
|
var isAsync = (0, mode_1.isConsumerMode)(mode);
|
|
19
19
|
return function track(maybeKey, maybeTT, maybeEvent, maybeEventValue, maybeProperties) {
|
|
@@ -39,7 +39,7 @@ function trackMethodFactory(params, warnTTExistence) {
|
|
|
39
39
|
};
|
|
40
40
|
// This may be async but we only warn, we don't actually care if it is valid or not in terms of queueing the event.
|
|
41
41
|
if (warnTTExistence)
|
|
42
|
-
(0, trafficTypeExistence_1.validateTrafficTypeExistence)(log, readinessManager,
|
|
42
|
+
(0, trafficTypeExistence_1.validateTrafficTypeExistence)(log, readinessManager, definitions, mode, trafficTypeName, constants_1.TRACK_FN_LABEL);
|
|
43
43
|
var result = eventTracker.track(eventData, size);
|
|
44
44
|
if ((0, thenable_1.thenable)(result)) {
|
|
45
45
|
return result.then(function (result) {
|
package/cjs/sdkFactory/index.js
CHANGED
|
@@ -30,18 +30,18 @@ function sdkFactory(params) {
|
|
|
30
30
|
readiness.timeout();
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
readiness.
|
|
33
|
+
readiness.definitions.emit(constants_2.SDK_DEFINITIONS_ARRIVED);
|
|
34
34
|
readiness.segments.emit(constants_2.SDK_SEGMENTS_ARRIVED);
|
|
35
35
|
},
|
|
36
36
|
onReadyFromCacheCb: function () {
|
|
37
|
-
readiness.
|
|
37
|
+
readiness.definitions.emit(constants_2.SDK_DEFINITIONS_CACHE_LOADED);
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
var fallbackCalculator = (0, fallbackTreatmentsCalculator_1.FallbackTreatmentsCalculator)(settings.fallbackTreatments);
|
|
41
41
|
if (initialRolloutPlan) {
|
|
42
42
|
(0, setRolloutPlan_1.setRolloutPlan)(log, initialRolloutPlan, storage, key && (0, key_1.getMatching)(key));
|
|
43
|
-
if (storage.
|
|
44
|
-
readiness.
|
|
43
|
+
if (storage.definitions.getChangeNumber() > -1)
|
|
44
|
+
readiness.definitions.emit(constants_2.SDK_DEFINITIONS_CACHE_LOADED, { initialCacheLoad: false /* Not an initial load, cache exists */ });
|
|
45
45
|
}
|
|
46
46
|
var clients = {};
|
|
47
47
|
var telemetryTracker = (0, telemetryTracker_1.telemetryTrackerFactory)(storage.telemetry, platform.now);
|
|
@@ -54,7 +54,7 @@ function sdkFactory(params) {
|
|
|
54
54
|
ctx.syncManager = syncManagerFactory && syncManagerFactory(ctx);
|
|
55
55
|
// SDK client and manager
|
|
56
56
|
var clientMethod = sdkClientMethodFactory(ctx);
|
|
57
|
-
var managerInstance = sdkManagerFactory(settings, storage.
|
|
57
|
+
var managerInstance = sdkManagerFactory(settings, storage.definitions, sdkReadinessManager);
|
|
58
58
|
function init() {
|
|
59
59
|
Object.keys(clients).map(function (key) { return clients[key].init(); });
|
|
60
60
|
}
|
package/cjs/sdkManager/index.js
CHANGED
|
@@ -57,7 +57,7 @@ function sdkManagerFactory(settings, splits, _a) {
|
|
|
57
57
|
if (!(0, inputValidation_1.validateIfOperational)(log, readinessManager, constants_1.SPLIT_FN_LABEL) || !splitName) {
|
|
58
58
|
return isAsync ? Promise.resolve(null) : null;
|
|
59
59
|
}
|
|
60
|
-
var split = splits.
|
|
60
|
+
var split = splits.get(splitName);
|
|
61
61
|
if ((0, thenable_1.thenable)(split)) {
|
|
62
62
|
return split.catch(function () { return null; }).then(function (result) {
|
|
63
63
|
(0, inputValidation_1.validateDefinitionExistence)(log, readinessManager, splitName, result, constants_1.SPLIT_FN_LABEL);
|
|
@@ -86,7 +86,7 @@ function sdkManagerFactory(settings, splits, _a) {
|
|
|
86
86
|
if (!(0, inputValidation_1.validateIfOperational)(log, readinessManager, constants_1.NAMES_FN_LABEL)) {
|
|
87
87
|
return isAsync ? Promise.resolve([]) : [];
|
|
88
88
|
}
|
|
89
|
-
var splitNames = splits.
|
|
89
|
+
var splitNames = splits.getNames();
|
|
90
90
|
return (0, thenable_1.thenable)(splitNames) ?
|
|
91
91
|
splitNames.catch(function () { return []; }) : // handle possible rejections when using pluggable storage
|
|
92
92
|
splitNames;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authProviderFactory = void 0;
|
|
4
|
+
var AuthClient_1 = require("../sync/streaming/AuthClient");
|
|
5
|
+
var Backoff_1 = require("../utils/Backoff");
|
|
6
|
+
var constants_1 = require("../logger/constants");
|
|
7
|
+
var constants_2 = require("../utils/constants");
|
|
8
|
+
var SKEW_SECONDS = 30;
|
|
9
|
+
function isExpired(credential) {
|
|
10
|
+
return Date.now() / 1000 + SKEW_SECONDS >= credential.decodedToken.exp;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Factory of AuthProvider, which provides JWT credentials for authenticated HTTP requests.
|
|
14
|
+
* Credentials are fetched lazily on demand, cached in memory, and retried with backoff on failure.
|
|
15
|
+
*/
|
|
16
|
+
function authProviderFactory(settings, splitHttpClient, telemetryTracker) {
|
|
17
|
+
var urls = settings.urls, log = settings.log;
|
|
18
|
+
function fetchAuth() {
|
|
19
|
+
var url = "".concat(urls.auth, "/v3/auth?capabilities=config");
|
|
20
|
+
return splitHttpClient(url, undefined, telemetryTracker.trackHttp(constants_2.TOKEN));
|
|
21
|
+
}
|
|
22
|
+
var authenticate = (0, AuthClient_1.authenticateFactory)(fetchAuth);
|
|
23
|
+
var backoff = new Backoff_1.Backoff(fetchCredential);
|
|
24
|
+
var cachedCredential;
|
|
25
|
+
var inFlightPromise;
|
|
26
|
+
var stopped = false;
|
|
27
|
+
function fetchCredential() {
|
|
28
|
+
return authenticate().then(function (credential) {
|
|
29
|
+
log.info(constants_1.LOG_PREFIX_SYNC_AUTH + 'credential fetched successfully');
|
|
30
|
+
cachedCredential = credential;
|
|
31
|
+
inFlightPromise = undefined;
|
|
32
|
+
backoff.reset();
|
|
33
|
+
return credential;
|
|
34
|
+
}).catch(function (error) {
|
|
35
|
+
// Avoid rejected promises and unnecessary retries after stop()
|
|
36
|
+
if (stopped)
|
|
37
|
+
return cachedCredential;
|
|
38
|
+
if (error.statusCode && error.statusCode >= 400 && error.statusCode < 500) {
|
|
39
|
+
log.error(constants_1.LOG_PREFIX_SYNC_AUTH + 'non-retryable error fetching credential (status ' + error.statusCode + '): ' + error.message);
|
|
40
|
+
inFlightPromise = undefined;
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
log.warn(constants_1.LOG_PREFIX_SYNC_AUTH + 'credential fetch failed (attempt ' + (backoff.attempts + 1) + '). Error: ' + error.message);
|
|
44
|
+
return backoff.scheduleCallAsync();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
credential: function () {
|
|
49
|
+
if (cachedCredential && !isExpired(cachedCredential)) {
|
|
50
|
+
return Promise.resolve(cachedCredential);
|
|
51
|
+
}
|
|
52
|
+
if (cachedCredential)
|
|
53
|
+
log.debug(constants_1.LOG_PREFIX_SYNC_AUTH + 'cached credential expired');
|
|
54
|
+
return inFlightPromise || (inFlightPromise = fetchCredential());
|
|
55
|
+
},
|
|
56
|
+
invalidate: function () {
|
|
57
|
+
cachedCredential = undefined;
|
|
58
|
+
},
|
|
59
|
+
stop: function () {
|
|
60
|
+
stopped = true;
|
|
61
|
+
cachedCredential = undefined;
|
|
62
|
+
inFlightPromise = undefined;
|
|
63
|
+
backoff.reset();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
exports.authProviderFactory = authProviderFactory;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.secureSplitHttpClientFactory = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var splitHttpClient_1 = require("./splitHttpClient");
|
|
6
|
+
var authProvider_1 = require("./authProvider");
|
|
7
|
+
/**
|
|
8
|
+
* Factory of Secure HTTP client, which authenticates requests using a JWT token.
|
|
9
|
+
* On 401 responses, invalidates the cached credential and retries once with a fresh token.
|
|
10
|
+
*
|
|
11
|
+
* @param settings - SDK settings
|
|
12
|
+
* @param platform - object containing environment-specific dependencies
|
|
13
|
+
* @param fetchAuth - function to fetch auth credentials from the /v2/auth endpoint
|
|
14
|
+
*/
|
|
15
|
+
function secureSplitHttpClientFactory(settings, platform, telemetryTracker) {
|
|
16
|
+
var splitHttpClient = (0, splitHttpClient_1.splitHttpClientFactory)(settings, platform);
|
|
17
|
+
var authProvider = (0, authProvider_1.authProviderFactory)(settings, splitHttpClient, telemetryTracker);
|
|
18
|
+
function makeRequest(url, options, latencyTracker, logErrorsAsInfo, token) {
|
|
19
|
+
return splitHttpClient(url, tslib_1.__assign(tslib_1.__assign({}, options), { headers: tslib_1.__assign(tslib_1.__assign({}, options === null || options === void 0 ? void 0 : options.headers), { Authorization: "Bearer ".concat(token) }) }), latencyTracker, logErrorsAsInfo);
|
|
20
|
+
}
|
|
21
|
+
var httpClient = function (url, options, latencyTracker, logErrorsAsInfo) {
|
|
22
|
+
return authProvider.credential().then(function (credential) {
|
|
23
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, credential.token)
|
|
24
|
+
.catch(function (error) {
|
|
25
|
+
if (error.statusCode === 401) {
|
|
26
|
+
// retry once for 401, in case the token has just expired
|
|
27
|
+
authProvider.invalidate();
|
|
28
|
+
return authProvider.credential().then(function (newCredential) {
|
|
29
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newCredential.token);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
httpClient.stop = function () { return authProvider.stop(); };
|
|
37
|
+
return httpClient;
|
|
38
|
+
}
|
|
39
|
+
exports.secureSplitHttpClientFactory = secureSplitHttpClientFactory;
|
package/cjs/services/splitApi.js
CHANGED
|
@@ -16,11 +16,12 @@ function userKeyToQueryParam(userKey) {
|
|
|
16
16
|
* @param platform - object containing environment-specific dependencies
|
|
17
17
|
* @param telemetryTracker - telemetry tracker
|
|
18
18
|
*/
|
|
19
|
-
function splitApiFactory(settings, platform, telemetryTracker) {
|
|
19
|
+
function splitApiFactory(settings, platform, telemetryTracker, secureSplitHttpClientFactory) {
|
|
20
20
|
var urls = settings.urls;
|
|
21
21
|
var filterQueryString = settings.sync.__splitFiltersValidation && settings.sync.__splitFiltersValidation.queryString;
|
|
22
22
|
var SplitSDKImpressionsMode = settings.sync.impressionsMode;
|
|
23
23
|
var splitHttpClient = (0, splitHttpClient_1.splitHttpClientFactory)(settings, platform);
|
|
24
|
+
var secureSplitHttpClient = secureSplitHttpClientFactory ? secureSplitHttpClientFactory(settings, platform, telemetryTracker) : undefined;
|
|
24
25
|
return {
|
|
25
26
|
// @TODO throw errors if health check requests fail, to log them in the Synchronizer
|
|
26
27
|
getSdkAPIHealthCheck: function () {
|
|
@@ -52,7 +53,7 @@ function splitApiFactory(settings, platform, telemetryTracker) {
|
|
|
52
53
|
// @TODO support filterQueryString and handle ERROR_TOO_MANY_SETS error
|
|
53
54
|
fetchConfigs: function (since, noCache, till) {
|
|
54
55
|
var url = "".concat(urls.sdk, "/v1/configs?since=").concat(since).concat(filterQueryString || '').concat(till ? '&till=' + till : '');
|
|
55
|
-
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined);
|
|
56
|
+
return (secureSplitHttpClient || splitHttpClient)(url, noCache ? noCacheHeaderOptions : undefined);
|
|
56
57
|
},
|
|
57
58
|
fetchSegmentChanges: function (since, segmentName, noCache, till) {
|
|
58
59
|
var url = "".concat(urls.sdk, "/segmentChanges/").concat(segmentName, "?since=").concat(since).concat(till ? '&till=' + till : '');
|
|
@@ -130,6 +131,10 @@ function splitApiFactory(settings, platform, telemetryTracker) {
|
|
|
130
131
|
postMetricsUsage: function (body, headers) {
|
|
131
132
|
var url = "".concat(urls.telemetry, "/v1/metrics/usage");
|
|
132
133
|
return splitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(constants_1.TELEMETRY), true);
|
|
134
|
+
},
|
|
135
|
+
stop: function () {
|
|
136
|
+
if (secureSplitHttpClient)
|
|
137
|
+
secureSplitHttpClient.stop();
|
|
133
138
|
}
|
|
134
139
|
};
|
|
135
140
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractDefinitionsCacheAsync = void 0;
|
|
4
|
+
var objectAssign_1 = require("../utils/lang/objectAssign");
|
|
5
|
+
/**
|
|
6
|
+
* This class provides a skeletal implementation of the IDefinitionsCacheAsync interface
|
|
7
|
+
* to minimize the effort required to implement this interface.
|
|
8
|
+
*/
|
|
9
|
+
var AbstractDefinitionsCacheAsync = /** @class */ (function () {
|
|
10
|
+
function AbstractDefinitionsCacheAsync() {
|
|
11
|
+
}
|
|
12
|
+
AbstractDefinitionsCacheAsync.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
13
|
+
var _this = this;
|
|
14
|
+
return Promise.all([
|
|
15
|
+
this.setChangeNumber(changeNumber),
|
|
16
|
+
Promise.all(toAdd.map(function (addedFF) { return _this.add(addedFF); })),
|
|
17
|
+
Promise.all(toRemove.map(function (removedFF) { return _this.remove(removedFF); }))
|
|
18
|
+
]).then(function (_a) {
|
|
19
|
+
var added = _a[1], removed = _a[2];
|
|
20
|
+
return added.some(function (result) { return result; }) || removed.some(function (result) { return result; });
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
// @TODO revisit segment-related methods ('usesSegments', 'getRegisteredSegments', 'registerSegments')
|
|
24
|
+
// noop, just keeping the interface. This is used by standalone client-side API only, and so only implemented by InMemory and InLocalStorage.
|
|
25
|
+
AbstractDefinitionsCacheAsync.prototype.usesSegments = function () {
|
|
26
|
+
return Promise.resolve(true);
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Kill `name` definition and set `defaultTreatment` and `changeNumber`.
|
|
30
|
+
* Used for SPLIT_KILL push notifications.
|
|
31
|
+
*
|
|
32
|
+
* @returns a promise that is resolved once the definition kill operation is performed. The fulfillment value is a boolean: `true` if the operation succeeded updating the definition or `false` if no definition is updated,
|
|
33
|
+
* for instance, if the `changeNumber` is old, or if the definition is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
|
|
34
|
+
* The promise will never be rejected.
|
|
35
|
+
*/
|
|
36
|
+
AbstractDefinitionsCacheAsync.prototype.killLocally = function (name, defaultTreatment, changeNumber) {
|
|
37
|
+
var _this = this;
|
|
38
|
+
return this.get(name).then(function (definition) {
|
|
39
|
+
if (definition && (!definition.changeNumber || definition.changeNumber < changeNumber)) {
|
|
40
|
+
var newDefinition = (0, objectAssign_1.objectAssign)({}, definition);
|
|
41
|
+
newDefinition.killed = true;
|
|
42
|
+
newDefinition.defaultTreatment = defaultTreatment;
|
|
43
|
+
newDefinition.changeNumber = changeNumber;
|
|
44
|
+
return _this.add(newDefinition);
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}).catch(function () { return false; });
|
|
48
|
+
};
|
|
49
|
+
return AbstractDefinitionsCacheAsync;
|
|
50
|
+
}());
|
|
51
|
+
exports.AbstractDefinitionsCacheAsync = AbstractDefinitionsCacheAsync;
|