@splitsoftware/splitio-commons 1.9.1-rc.0 → 1.9.2-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 +5 -2
- package/cjs/evaluator/index.js +18 -1
- package/cjs/integrations/ga/GaToSplit.js +1 -1
- package/cjs/listeners/browser.js +3 -13
- package/cjs/logger/constants.js +7 -2
- package/cjs/logger/messages/error.js +2 -0
- package/cjs/logger/messages/warn.js +3 -1
- package/cjs/myLogger.js +34 -0
- package/cjs/sdkClient/client.js +33 -0
- package/cjs/sdkClient/clientAttributesDecoration.js +20 -0
- package/cjs/sdkClient/clientCS.js +5 -4
- package/cjs/sdkClient/clientInputValidation.js +52 -3
- package/cjs/sdkManager/index.js +2 -1
- package/cjs/services/splitApi.js +7 -1
- package/cjs/storages/KeyBuilder.js +3 -0
- package/cjs/storages/KeyBuilderSS.js +4 -0
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +63 -27
- package/cjs/storages/inLocalStorage/index.js +2 -2
- package/cjs/storages/inMemory/InMemoryStorage.js +2 -2
- package/cjs/storages/inMemory/InMemoryStorageCS.js +3 -3
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +47 -2
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +11 -0
- package/cjs/storages/pluggable/SplitsCachePluggable.js +11 -0
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +24 -4
- package/cjs/sync/streaming/parseUtils.js +1 -0
- package/cjs/sync/submitters/telemetrySubmitter.js +15 -1
- package/cjs/utils/constants/index.js +6 -2
- package/cjs/utils/lang/sets.js +9 -1
- package/cjs/utils/settingsValidation/splitFilters.js +77 -2
- package/esm/evaluator/index.js +16 -0
- package/esm/integrations/ga/GaToSplit.js +1 -1
- package/esm/listeners/browser.js +3 -13
- package/esm/logger/constants.js +5 -0
- package/esm/logger/messages/error.js +2 -0
- package/esm/logger/messages/warn.js +3 -1
- package/esm/myLogger.js +31 -0
- package/esm/sdkClient/client.js +35 -2
- package/esm/sdkClient/clientAttributesDecoration.js +20 -0
- package/esm/sdkClient/clientCS.js +5 -4
- package/esm/sdkClient/clientInputValidation.js +52 -3
- package/esm/sdkManager/index.js +2 -1
- package/esm/services/splitApi.js +7 -1
- package/esm/storages/KeyBuilder.js +3 -0
- package/esm/storages/KeyBuilderSS.js +4 -0
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +63 -27
- package/esm/storages/inLocalStorage/index.js +2 -2
- package/esm/storages/inMemory/InMemoryStorage.js +2 -2
- package/esm/storages/inMemory/InMemoryStorageCS.js +3 -3
- package/esm/storages/inMemory/SplitsCacheInMemory.js +47 -2
- package/esm/storages/inRedis/SplitsCacheInRedis.js +11 -0
- package/esm/storages/pluggable/SplitsCachePluggable.js +11 -0
- package/esm/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/esm/sync/polling/updaters/splitChangesUpdater.js +24 -4
- package/esm/sync/streaming/parseUtils.js +1 -0
- package/esm/sync/submitters/telemetrySubmitter.js +15 -1
- package/esm/utils/constants/index.js +4 -0
- package/esm/utils/lang/sets.js +7 -0
- package/esm/utils/settingsValidation/splitFilters.js +76 -2
- package/package.json +6 -6
- package/src/dtos/types.ts +3 -2
- package/src/evaluator/index.ts +24 -0
- package/src/integrations/ga/GaToSplit.ts +1 -1
- package/src/listeners/browser.ts +3 -13
- package/src/logger/constants.ts +5 -0
- package/src/logger/messages/error.ts +2 -0
- package/src/logger/messages/warn.ts +3 -1
- package/src/myLogger.ts +36 -0
- package/src/sdkClient/client.ts +42 -2
- package/src/sdkClient/clientAttributesDecoration.ts +24 -0
- package/src/sdkClient/clientCS.ts +5 -4
- package/src/sdkClient/clientInputValidation.ts +56 -4
- package/src/sdkManager/index.ts +2 -1
- package/src/services/splitApi.ts +6 -1
- package/src/storages/AbstractSplitsCacheAsync.ts +2 -0
- package/src/storages/AbstractSplitsCacheSync.ts +3 -0
- package/src/storages/KeyBuilder.ts +4 -0
- package/src/storages/KeyBuilderSS.ts +4 -0
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +74 -28
- package/src/storages/inLocalStorage/index.ts +2 -2
- package/src/storages/inMemory/InMemoryStorage.ts +2 -2
- package/src/storages/inMemory/InMemoryStorageCS.ts +3 -3
- package/src/storages/inMemory/SplitsCacheInMemory.ts +50 -1
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +1 -1
- package/src/storages/inRedis/RedisAdapter.ts +1 -1
- package/src/storages/inRedis/SplitsCacheInRedis.ts +12 -0
- package/src/storages/pluggable/SplitsCachePluggable.ts +12 -0
- package/src/storages/types.ts +7 -3
- package/src/sync/polling/syncTasks/splitsSyncTask.ts +1 -0
- package/src/sync/polling/updaters/splitChangesUpdater.ts +27 -4
- package/src/sync/streaming/parseUtils.ts +1 -0
- package/src/sync/submitters/telemetrySubmitter.ts +19 -2
- package/src/sync/submitters/types.ts +7 -1
- package/src/types.ts +118 -1
- package/src/utils/constants/index.ts +4 -0
- package/src/utils/lang/sets.ts +8 -0
- package/src/utils/redis/RedisMock.ts +1 -1
- package/src/utils/settingsValidation/splitFilters.ts +82 -2
- package/types/dtos/types.d.ts +1 -0
- package/types/evaluator/index.d.ts +1 -0
- package/types/listeners/browser.d.ts +0 -1
- package/types/logger/constants.d.ts +5 -0
- package/types/myLogger.d.ts +5 -0
- package/types/sdkClient/clientAttributesDecoration.d.ts +4 -0
- package/types/sdkClient/types.d.ts +18 -0
- package/types/storages/AbstractSplitsCacheAsync.d.ts +2 -0
- package/types/storages/AbstractSplitsCacheSync.d.ts +2 -0
- package/types/storages/KeyBuilder.d.ts +1 -0
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +6 -1
- package/types/storages/inMemory/CountsCacheInMemory.d.ts +20 -0
- package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +20 -0
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +9 -1
- package/types/storages/inRedis/CountsCacheInRedis.d.ts +9 -0
- package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +9 -0
- package/types/storages/inRedis/SplitsCacheInRedis.d.ts +8 -0
- package/types/storages/metadataBuilder.d.ts +3 -0
- package/types/storages/pluggable/SplitsCachePluggable.d.ts +8 -0
- package/types/storages/types.d.ts +4 -0
- package/types/sync/offline/LocalhostFromFile.d.ts +2 -0
- package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +2 -0
- package/types/sync/offline/updaters/splitChangesUpdater.d.ts +0 -0
- package/types/sync/polling/updaters/splitChangesUpdater.d.ts +3 -3
- package/types/sync/submitters/eventsSyncTask.d.ts +8 -0
- package/types/sync/submitters/impressionCountsSubmitterInRedis.d.ts +5 -0
- package/types/sync/submitters/impressionCountsSyncTask.d.ts +13 -0
- package/types/sync/submitters/impressionsSyncTask.d.ts +14 -0
- package/types/sync/submitters/metricsSyncTask.d.ts +12 -0
- package/types/sync/submitters/submitterSyncTask.d.ts +10 -0
- package/types/sync/submitters/types.d.ts +7 -1
- package/types/sync/submitters/uniqueKeysSubmitterInRedis.d.ts +5 -0
- package/types/sync/syncTaskComposite.d.ts +5 -0
- package/types/trackers/filter/bloomFilter.d.ts +10 -0
- package/types/trackers/filter/dictionaryFilter.d.ts +8 -0
- package/types/trackers/filter/types.d.ts +5 -0
- package/types/types.d.ts +118 -1
- package/types/utils/constants/index.d.ts +4 -0
- package/types/utils/lang/sets.d.ts +1 -0
- package/types/utils/settingsValidation/splitFilters.d.ts +1 -0
- package/types/utils/timeTracker/index.d.ts +70 -0
- package/types/sdkClient/identity.d.ts +0 -6
- package/types/utils/inputValidation/sdkKey.d.ts +0 -7
- /package/types/storages/inMemory/{UniqueKeysCacheInMemory.d.ts → uniqueKeysCacheInMemory.d.ts} +0 -0
- /package/types/storages/inMemory/{UniqueKeysCacheInMemoryCS.d.ts → uniqueKeysCacheInMemoryCS.d.ts} +0 -0
- /package/types/storages/inRedis/{UniqueKeysCacheInRedis.d.ts → uniqueKeysCacheInRedis.d.ts} +0 -0
package/CHANGES.txt
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
1.9.1 (September 21, 2023)
|
|
2
|
+
- Updated browser listener to avoid registering a handler for 'unload' DOM events, that can prevent browsers from being able to put pages in the back/forward cache for faster back and forward loads (Related to issue https://github.com/splitio/javascript-client/issues/759).
|
|
3
|
+
|
|
1
4
|
1.9.0 (July 18, 2023)
|
|
2
5
|
- Updated streaming architecture implementation to apply feature flag updates from the notification received which is now enhanced, improving efficiency and reliability of the whole update system.
|
|
3
6
|
|
|
4
7
|
1.8.3 (June 29, 2023)
|
|
5
8
|
- Updated some transitive dependencies for vulnerability fixes.
|
|
6
9
|
- Updated SDK_READY_TIMED_OUT event to be emitted immediately when a connection error occurs using pluggable storage (i.e., when the wrapper `connect` promise is rejected) in consumer and partial consumer modes.
|
|
7
|
-
-
|
|
10
|
+
- Bugfixing - The `destroy` method has been updated to immediately flag the SDK client as destroyed, to prevent unexpected behaviours when `getTreatment` and `track` methods are called synchronously after `destroy` method is called.
|
|
8
11
|
|
|
9
12
|
1.8.2 (May 15, 2023)
|
|
10
13
|
- Updated terminology on the SDKs codebase to be more aligned with current standard without causing a breaking change. The core change is the term split for feature flag on things like logs and IntelliSense comments.
|
|
@@ -90,7 +93,7 @@
|
|
|
90
93
|
- Integration with Auth service V2, connecting to the new channels and applying the received connection delay.
|
|
91
94
|
- Implemented handling of the new MySegmentsV2 notification types (SegmentRemoval, KeyList, Bounded and Unbounded)
|
|
92
95
|
- New control notification for environment scoped streaming reset.
|
|
93
|
-
- Updated localhost mode to emit SDK_READY_FROM_CACHE event in
|
|
96
|
+
- Updated localhost mode to emit SDK_READY_FROM_CACHE event in browser when using localStorage (Related to issue https://github.com/splitio/react-client/issues/34).
|
|
94
97
|
- Updated dependencies for vulnerability fixes.
|
|
95
98
|
|
|
96
99
|
0.1.0 (March 30, 2021)
|
package/cjs/evaluator/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.evaluateFeatures = exports.evaluateFeature = void 0;
|
|
3
|
+
exports.evaluateFeaturesByFlagSets = exports.evaluateFeatures = exports.evaluateFeature = void 0;
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
var Engine_1 = require("./Engine");
|
|
6
6
|
var thenable_1 = require("../utils/promise/thenable");
|
|
7
7
|
var LabelsConstants = (0, tslib_1.__importStar)(require("../utils/labels"));
|
|
8
8
|
var constants_1 = require("../utils/constants");
|
|
9
|
+
var sets_1 = require("../utils/lang/sets");
|
|
9
10
|
var treatmentException = {
|
|
10
11
|
treatment: constants_1.CONTROL,
|
|
11
12
|
label: LabelsConstants.EXCEPTION,
|
|
@@ -55,6 +56,22 @@ function evaluateFeatures(log, key, splitNames, attributes, storage) {
|
|
|
55
56
|
getEvaluations(log, splitNames, parsedSplits, key, attributes, storage);
|
|
56
57
|
}
|
|
57
58
|
exports.evaluateFeatures = evaluateFeatures;
|
|
59
|
+
function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, storage) {
|
|
60
|
+
var storedFlagNames;
|
|
61
|
+
// get features by flag sets
|
|
62
|
+
try {
|
|
63
|
+
storedFlagNames = storage.splits.getNamesByFlagSets(flagSets);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
// return empty evaluations
|
|
67
|
+
return {};
|
|
68
|
+
}
|
|
69
|
+
// evaluate related features
|
|
70
|
+
return (0, thenable_1.thenable)(storedFlagNames) ?
|
|
71
|
+
storedFlagNames.then(function (splitNames) { return evaluateFeatures(log, key, (0, sets_1.setToArray)(splitNames), attributes, storage); }) :
|
|
72
|
+
evaluateFeatures(log, key, (0, sets_1.setToArray)(storedFlagNames), attributes, storage);
|
|
73
|
+
}
|
|
74
|
+
exports.evaluateFeaturesByFlagSets = evaluateFeaturesByFlagSets;
|
|
58
75
|
function getEvaluation(log, splitJSON, key, attributes, storage) {
|
|
59
76
|
var evaluation = {
|
|
60
77
|
treatment: constants_1.CONTROL,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GaToSplit = exports.fixEventTypeId = exports.validateEventData = exports.validateIdentities = exports.defaultPrefix = exports.defaultMapper = void 0;
|
|
4
|
-
/* eslint-disable no-undef */
|
|
5
4
|
var objectAssign_1 = require("../../utils/lang/objectAssign");
|
|
6
5
|
var lang_1 = require("../../utils/lang");
|
|
7
6
|
var inputValidation_1 = require("../../utils/inputValidation");
|
|
@@ -252,6 +251,7 @@ function GaToSplit(sdkOptions, params) {
|
|
|
252
251
|
return SplitTracker;
|
|
253
252
|
}());
|
|
254
253
|
// Register the plugin, even if config is invalid, since, if not provided, it will block `ga` command queue.
|
|
254
|
+
// eslint-disable-next-line no-undef
|
|
255
255
|
providePlugin(window, 'splitTracker', SplitTracker, log, sdkOptions.autoRequire === true, telemetryTracker);
|
|
256
256
|
}
|
|
257
257
|
exports.GaToSplit = GaToSplit;
|
package/cjs/listeners/browser.js
CHANGED
|
@@ -9,8 +9,7 @@ var constants_2 = require("../logger/constants");
|
|
|
9
9
|
var consent_1 = require("../consent");
|
|
10
10
|
var VISIBILITYCHANGE_EVENT = 'visibilitychange';
|
|
11
11
|
var PAGEHIDE_EVENT = 'pagehide';
|
|
12
|
-
var
|
|
13
|
-
var EVENT_NAME = 'for unload page event.';
|
|
12
|
+
var EVENT_NAME = 'for visibilitychange and pagehide events.';
|
|
14
13
|
/**
|
|
15
14
|
* We'll listen for events over the window object.
|
|
16
15
|
*/
|
|
@@ -22,7 +21,6 @@ var BrowserSignalListener = /** @class */ (function () {
|
|
|
22
21
|
this.serviceApi = serviceApi;
|
|
23
22
|
this.flushData = this.flushData.bind(this);
|
|
24
23
|
this.flushDataIfHidden = this.flushDataIfHidden.bind(this);
|
|
25
|
-
this.stopSync = this.stopSync.bind(this);
|
|
26
24
|
this.fromImpressionsCollector = impressionsSubmitter_1.fromImpressionsCollector.bind(undefined, settings.core.labelsEnabled);
|
|
27
25
|
}
|
|
28
26
|
/**
|
|
@@ -36,11 +34,9 @@ var BrowserSignalListener = /** @class */ (function () {
|
|
|
36
34
|
document.addEventListener(VISIBILITYCHANGE_EVENT, this.flushDataIfHidden);
|
|
37
35
|
}
|
|
38
36
|
if (typeof window !== 'undefined' && window.addEventListener) {
|
|
39
|
-
// Some browsers like Safari does not fire the `visibilitychange` event when the page is being unloaded.
|
|
40
|
-
// If both events are triggered, the
|
|
37
|
+
// Some browsers, like Safari, does not fire the `visibilitychange` event when the page is being unloaded. Therefore, we also flush data in the `pagehide` event.
|
|
38
|
+
// If both events are triggered, the latter will find the storage empty, so no duplicate data will be submitted.
|
|
41
39
|
window.addEventListener(PAGEHIDE_EVENT, this.flushData);
|
|
42
|
-
// Stop streaming on 'unload' event. Used instead of 'beforeunload', because 'unload' is not a cancelable event, so no other listeners can stop the event from occurring.
|
|
43
|
-
window.addEventListener(UNLOAD_EVENT, this.stopSync);
|
|
44
40
|
}
|
|
45
41
|
};
|
|
46
42
|
/**
|
|
@@ -54,14 +50,8 @@ var BrowserSignalListener = /** @class */ (function () {
|
|
|
54
50
|
}
|
|
55
51
|
if (typeof window !== 'undefined' && window.removeEventListener) {
|
|
56
52
|
window.removeEventListener(PAGEHIDE_EVENT, this.flushData);
|
|
57
|
-
window.removeEventListener(UNLOAD_EVENT, this.stopSync);
|
|
58
53
|
}
|
|
59
54
|
};
|
|
60
|
-
BrowserSignalListener.prototype.stopSync = function () {
|
|
61
|
-
// Close streaming connection
|
|
62
|
-
if (this.syncManager && this.syncManager.pushManager)
|
|
63
|
-
this.syncManager.pushManager.stop();
|
|
64
|
-
};
|
|
65
55
|
/**
|
|
66
56
|
* flushData method.
|
|
67
57
|
* Called when pagehide event is triggered. It flushed remaining impressions and events to the backend,
|
package/cjs/logger/constants.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SYNC_SPLITS_FETCH_RETRY = exports.POLLING_STOP = exports.POLLING_START = exports.POLLING_SMART_PAUSING = exports.NEW_FACTORY = exports.NEW_SHARED_CLIENT = exports.IMPRESSION_QUEUEING = exports.IMPRESSION = exports.CLIENT_READY = exports.CLIENT_READY_FROM_CACHE = exports.SETTINGS_SPLITS_FILTER = exports.SYNC_TASK_STOP = exports.SYNC_TASK_EXECUTE = exports.SYNC_TASK_START = exports.STREAMING_NEW_MESSAGE = exports.SYNC_SPLITS_SEGMENTS = exports.SYNC_SPLITS_REMOVED = exports.SYNC_SPLITS_NEW = exports.SYNC_SPLITS_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_WHITELIST = exports.ENGINE_MATCHER_STARTS_WITH = exports.ENGINE_MATCHER_STRING_INVALID = exports.ENGINE_MATCHER_STRING = exports.ENGINE_MATCHER_SEGMENT = exports.ENGINE_MATCHER_PART_OF = exports.ENGINE_MATCHER_LESS = exports.ENGINE_MATCHER_GREATER = exports.ENGINE_MATCHER_ENDS_WITH = exports.ENGINE_MATCHER_EQUAL_TO_SET = exports.ENGINE_MATCHER_EQUAL = exports.ENGINE_MATCHER_DEPENDENCY_PRE = exports.ENGINE_MATCHER_DEPENDENCY = exports.ENGINE_MATCHER_CONTAINS_STRING = exports.ENGINE_MATCHER_CONTAINS_ANY = exports.ENGINE_MATCHER_CONTAINS_ALL = exports.ENGINE_MATCHER_BOOLEAN = exports.ENGINE_MATCHER_BETWEEN = exports.ENGINE_MATCHER_ALL = exports.ENGINE_BUCKET = exports.ENGINE_COMBINER_IFELSEIF_NO_TREATMENT = exports.ENGINE_COMBINER_IFELSEIF = exports.ENGINE_COMBINER_AND = void 0;
|
|
4
|
-
exports.
|
|
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_MYSEGMENTS = exports.LOG_PREFIX_SYNC_SEGMENTS = exports.LOG_PREFIX_SYNC_SPLITS = 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_INSTANTIATION = exports.LOG_PREFIX_SETTINGS = exports.ERROR_MIN_CONFIG_PARAM = exports.ERROR_NOT_BOOLEAN = exports.ERROR_STORAGE_INVALID = exports.ERROR_LOCALHOST_MODULE_REQUIRED = 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 = void 0;
|
|
4
|
+
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_NOT_CONFIGURED = exports.WARN_SPLITS_FILTER_LOWERCASE_SET = exports.WARN_SPLITS_FILTER_INVALID_SET = exports.STREAMING_PARSING_SPLIT_UPDATE = exports.STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 = 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_SPLIT = 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_SPLITS_FETCH_FAILS = exports.SYNC_MYSEGMENTS_FETCH_RETRY = exports.CLIENT_NOT_READY = exports.CLIENT_NO_LISTENER = exports.ENGINE_VALUE_NO_ATTRIBUTES = exports.ENGINE_VALUE_INVALID = 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 = 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_MYSEGMENTS = exports.LOG_PREFIX_SYNC_SEGMENTS = exports.LOG_PREFIX_SYNC_SPLITS = 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_INSTANTIATION = exports.LOG_PREFIX_SETTINGS = exports.ERROR_SETS_FILTER_EXCLUSIVE = exports.ERROR_TOO_MANY_SETS = exports.ERROR_MIN_CONFIG_PARAM = exports.ERROR_NOT_BOOLEAN = exports.ERROR_STORAGE_INVALID = exports.ERROR_LOCALHOST_MODULE_REQUIRED = 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 = 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.
|
|
@@ -100,6 +100,9 @@ exports.WARN_SPLITS_FILTER_EMPTY = 221;
|
|
|
100
100
|
exports.WARN_SDK_KEY = 222;
|
|
101
101
|
exports.STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 = 223;
|
|
102
102
|
exports.STREAMING_PARSING_SPLIT_UPDATE = 224;
|
|
103
|
+
exports.WARN_SPLITS_FILTER_INVALID_SET = 225;
|
|
104
|
+
exports.WARN_SPLITS_FILTER_LOWERCASE_SET = 226;
|
|
105
|
+
exports.WARN_FLAGSET_NOT_CONFIGURED = 227;
|
|
103
106
|
exports.ERROR_ENGINE_COMBINER_IFELSEIF = 300;
|
|
104
107
|
exports.ERROR_LOGLEVEL_INVALID = 301;
|
|
105
108
|
exports.ERROR_CLIENT_LISTENER = 302;
|
|
@@ -127,6 +130,8 @@ exports.ERROR_LOCALHOST_MODULE_REQUIRED = 323;
|
|
|
127
130
|
exports.ERROR_STORAGE_INVALID = 324;
|
|
128
131
|
exports.ERROR_NOT_BOOLEAN = 325;
|
|
129
132
|
exports.ERROR_MIN_CONFIG_PARAM = 326;
|
|
133
|
+
exports.ERROR_TOO_MANY_SETS = 327;
|
|
134
|
+
exports.ERROR_SETS_FILTER_EXCLUSIVE = 328;
|
|
130
135
|
// Log prefixes (a.k.a. tags or categories)
|
|
131
136
|
exports.LOG_PREFIX_SETTINGS = 'settings';
|
|
132
137
|
exports.LOG_PREFIX_INSTANTIATION = 'Factory instantiation';
|
|
@@ -37,4 +37,6 @@ exports.codesError = [
|
|
|
37
37
|
[c.ERROR_LOCALHOST_MODULE_REQUIRED, c.LOG_PREFIX_SETTINGS + ': an invalid value was received for "sync.localhostMode" config. A valid entity should be provided for localhost mode.'],
|
|
38
38
|
[c.ERROR_STORAGE_INVALID, c.LOG_PREFIX_SETTINGS + ': the provided storage is invalid.%s Falling back into default MEMORY storage'],
|
|
39
39
|
[c.ERROR_MIN_CONFIG_PARAM, c.LOG_PREFIX_SETTINGS + ': the provided "%s" config param is lower than allowed. Setting to the minimum value %s seconds'],
|
|
40
|
+
[c.ERROR_TOO_MANY_SETS, c.LOG_PREFIX_SETTINGS + ': the amount of flag sets provided are big causing uri length error.'],
|
|
41
|
+
[c.ERROR_SETS_FILTER_EXCLUSIVE, c.LOG_PREFIX_SETTINGS + ': the Set filter is exclusive and cannot be used simultaneously with names or prefix filters. Ignoring names and prefixes.'],
|
|
40
42
|
];
|
|
@@ -30,9 +30,11 @@ exports.codesWarn = error_1.codesError.concat([
|
|
|
30
30
|
// initialization / settings validation
|
|
31
31
|
[c.WARN_INTEGRATION_INVALID, c.LOG_PREFIX_SETTINGS + ': %s integration item(s) at settings is invalid. %s'],
|
|
32
32
|
[c.WARN_SPLITS_FILTER_IGNORED, c.LOG_PREFIX_SETTINGS + ': feature flag filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'],
|
|
33
|
-
[c.WARN_SPLITS_FILTER_INVALID, c.LOG_PREFIX_SETTINGS + ': feature flag filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'],
|
|
33
|
+
[c.WARN_SPLITS_FILTER_INVALID, c.LOG_PREFIX_SETTINGS + ': feature flag filter at position %s is invalid. It must be an object with a valid filter type ("bySet", "byName" or "byPrefix") and a list of "values".'],
|
|
34
34
|
[c.WARN_SPLITS_FILTER_EMPTY, c.LOG_PREFIX_SETTINGS + ': feature flag filter configuration must be a non-empty array of filter objects.'],
|
|
35
35
|
[c.WARN_SDK_KEY, c.LOG_PREFIX_SETTINGS + ': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'],
|
|
36
36
|
[c.STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, c.LOG_PREFIX_SYNC_STREAMING + 'Fetching MySegments due to an error processing %s notification: %s'],
|
|
37
37
|
[c.STREAMING_PARSING_SPLIT_UPDATE, c.LOG_PREFIX_SYNC_STREAMING + 'Fetching SplitChanges due to an error processing SPLIT_UPDATE notification: %s'],
|
|
38
|
+
[c.WARN_SPLITS_FILTER_INVALID_SET, c.LOG_PREFIX_SETTINGS + ': you passed %s, flag set must adhere to the regular expressions %s. This means a flag set must start with a letter or number, be in lowercase, alphanumeric and have a max length of 50 characters. %s was discarded.'],
|
|
39
|
+
[c.WARN_SPLITS_FILTER_LOWERCASE_SET, c.LOG_PREFIX_SETTINGS + ': flag set %s should be all lowercase - converting string to lowercase.'],
|
|
38
40
|
]);
|
package/cjs/myLogger.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.myLogger = void 0;
|
|
4
|
+
// get the Console class
|
|
5
|
+
// const { Console } = require('console');
|
|
6
|
+
// get fs module for creating write streams
|
|
7
|
+
var fs = require('fs');
|
|
8
|
+
var pjson = require('../package.json');
|
|
9
|
+
//@ts-ignore
|
|
10
|
+
var pad = function (value) { return ('00' + value).slice(-2); };
|
|
11
|
+
var getDate = function () {
|
|
12
|
+
var date = new Date();
|
|
13
|
+
return date.getFullYear() + "-" + pad(date.getMonth() + 1) + "-" + pad(date.getDate()) + "_" + pad(date.getHours()) + ":" + pad(date.getMinutes()) + ":" + pad(date.getSeconds());
|
|
14
|
+
};
|
|
15
|
+
//@ts-ignore
|
|
16
|
+
var logToFile = function (file, msg) {
|
|
17
|
+
//@ts-ignore
|
|
18
|
+
fs.appendFileSync(file, msg + "\n", function (err) {
|
|
19
|
+
if (err) {
|
|
20
|
+
return console.log(err);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
// make a new logger
|
|
25
|
+
var version = pjson.version.replace('.', '').replace('.', '');
|
|
26
|
+
var filePath = "logs/" + version + "_" + getDate();
|
|
27
|
+
exports.myLogger = {
|
|
28
|
+
//@ts-ignore
|
|
29
|
+
log: function (msg) { return logToFile(filePath, msg); },
|
|
30
|
+
//@ts-ignore
|
|
31
|
+
logCsv: function (msg) { return logToFile(filePath + ".csv", msg); },
|
|
32
|
+
//@ts-ignore
|
|
33
|
+
logToFile: function (file, msg) { return logToFile("logs/" + file, msg); },
|
|
34
|
+
};
|
package/cjs/sdkClient/client.js
CHANGED
|
@@ -67,6 +67,35 @@ function clientFactory(params) {
|
|
|
67
67
|
function getTreatmentsWithConfig(key, featureFlagNames, attributes) {
|
|
68
68
|
return getTreatments(key, featureFlagNames, attributes, true);
|
|
69
69
|
}
|
|
70
|
+
function getTreatmentsByFlagSets(key, flagSetNames, attributes, withConfig, method) {
|
|
71
|
+
if (withConfig === void 0) { withConfig = false; }
|
|
72
|
+
if (method === void 0) { method = constants_1.TREATMENTS_BY_FLAGSETS; }
|
|
73
|
+
var stopTelemetryTracker = telemetryTracker.trackEval(method);
|
|
74
|
+
var wrapUp = function (evaluationResults) {
|
|
75
|
+
var queue = [];
|
|
76
|
+
var treatments = {};
|
|
77
|
+
var evaluations = evaluationResults;
|
|
78
|
+
Object.keys(evaluations).forEach(function (featureFlagName) {
|
|
79
|
+
treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig, "getTreatmentsByFlagSets" + (withConfig ? 'WithConfig' : ''), queue);
|
|
80
|
+
});
|
|
81
|
+
impressionsTracker.track(queue, attributes);
|
|
82
|
+
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
83
|
+
return treatments;
|
|
84
|
+
};
|
|
85
|
+
var evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
|
|
86
|
+
(0, evaluator_1.evaluateFeaturesByFlagSets)(log, key, flagSetNames, attributes, storage) :
|
|
87
|
+
(0, utils_1.isStorageSync)(settings) ? {} : Promise.resolve({}); // Promisify if async
|
|
88
|
+
return (0, thenable_1.thenable)(evaluations) ? evaluations.then(function (res) { return wrapUp(res); }) : wrapUp(evaluations);
|
|
89
|
+
}
|
|
90
|
+
function getTreatmentsWithConfigByFlagSets(key, flagSetNames, attributes) {
|
|
91
|
+
return getTreatmentsByFlagSets(key, flagSetNames, attributes, true, constants_1.TREATMENTS_WITH_CONFIG_BY_FLAGSETS);
|
|
92
|
+
}
|
|
93
|
+
function getTreatmentsByFlagSet(key, flagSetName, attributes) {
|
|
94
|
+
return getTreatmentsByFlagSets(key, [flagSetName], attributes, false, constants_1.TREATMENTS_BY_FLAGSET);
|
|
95
|
+
}
|
|
96
|
+
function getTreatmentsWithConfigByFlagSet(key, flagSetName, attributes) {
|
|
97
|
+
return getTreatmentsByFlagSets(key, [flagSetName], attributes, true, constants_1.TREATMENTS_WITH_CONFIG_BY_FLAGSET);
|
|
98
|
+
}
|
|
70
99
|
// Internal function
|
|
71
100
|
function processEvaluation(evaluation, featureFlagName, key, attributes, withConfig, invokingMethodName, queue) {
|
|
72
101
|
var matchingKey = (0, key_1.getMatching)(key);
|
|
@@ -125,6 +154,10 @@ function clientFactory(params) {
|
|
|
125
154
|
getTreatmentWithConfig: getTreatmentWithConfig,
|
|
126
155
|
getTreatments: getTreatments,
|
|
127
156
|
getTreatmentsWithConfig: getTreatmentsWithConfig,
|
|
157
|
+
getTreatmentsByFlagSets: getTreatmentsByFlagSets,
|
|
158
|
+
getTreatmentsWithConfigByFlagSets: getTreatmentsWithConfigByFlagSets,
|
|
159
|
+
getTreatmentsByFlagSet: getTreatmentsByFlagSet,
|
|
160
|
+
getTreatmentsWithConfigByFlagSet: getTreatmentsWithConfigByFlagSet,
|
|
128
161
|
track: track,
|
|
129
162
|
isClientSide: false
|
|
130
163
|
};
|
|
@@ -14,6 +14,10 @@ function clientAttributesDecoration(log, client) {
|
|
|
14
14
|
var clientGetTreatmentWithConfig = client.getTreatmentWithConfig;
|
|
15
15
|
var clientGetTreatments = client.getTreatments;
|
|
16
16
|
var clientGetTreatmentsWithConfig = client.getTreatmentsWithConfig;
|
|
17
|
+
var clientGetTreatmentsByFlagSets = client.getTreatmentsByFlagSets;
|
|
18
|
+
var clientGetTreatmentsWithConfigByFlagSets = client.getTreatmentsWithConfigByFlagSets;
|
|
19
|
+
var clientGetTreatmentsByFlagSet = client.getTreatmentsByFlagSet;
|
|
20
|
+
var clientGetTreatmentsWithConfigByFlagSet = client.getTreatmentsWithConfigByFlagSet;
|
|
17
21
|
var clientTrack = client.track;
|
|
18
22
|
function getTreatment(maybeKey, maybeFeatureFlagName, maybeAttributes) {
|
|
19
23
|
return clientGetTreatment(maybeKey, maybeFeatureFlagName, combineAttributes(maybeAttributes));
|
|
@@ -27,6 +31,18 @@ function clientAttributesDecoration(log, client) {
|
|
|
27
31
|
function getTreatmentsWithConfig(maybeKey, maybeFeatureFlagNames, maybeAttributes) {
|
|
28
32
|
return clientGetTreatmentsWithConfig(maybeKey, maybeFeatureFlagNames, combineAttributes(maybeAttributes));
|
|
29
33
|
}
|
|
34
|
+
function getTreatmentsByFlagSets(maybeKey, maybeFlagSets, maybeAttributes) {
|
|
35
|
+
return clientGetTreatmentsByFlagSets(maybeKey, maybeFlagSets, combineAttributes(maybeAttributes));
|
|
36
|
+
}
|
|
37
|
+
function getTreatmentsWithConfigByFlagSets(maybeKey, maybeFlagSets, maybeAttributes) {
|
|
38
|
+
return clientGetTreatmentsWithConfigByFlagSets(maybeKey, maybeFlagSets, combineAttributes(maybeAttributes));
|
|
39
|
+
}
|
|
40
|
+
function getTreatmentsByFlagSet(maybeKey, maybeFlagSet, maybeAttributes) {
|
|
41
|
+
return clientGetTreatmentsByFlagSet(maybeKey, maybeFlagSet, combineAttributes(maybeAttributes));
|
|
42
|
+
}
|
|
43
|
+
function getTreatmentsWithConfigByFlagSet(maybeKey, maybeFlagSet, maybeAttributes) {
|
|
44
|
+
return clientGetTreatmentsWithConfigByFlagSet(maybeKey, maybeFlagSet, combineAttributes(maybeAttributes));
|
|
45
|
+
}
|
|
30
46
|
function track(maybeKey, maybeTT, maybeEvent, maybeEventValue, maybeProperties) {
|
|
31
47
|
return clientTrack(maybeKey, maybeTT, maybeEvent, maybeEventValue, maybeProperties);
|
|
32
48
|
}
|
|
@@ -42,6 +58,10 @@ function clientAttributesDecoration(log, client) {
|
|
|
42
58
|
getTreatmentWithConfig: getTreatmentWithConfig,
|
|
43
59
|
getTreatments: getTreatments,
|
|
44
60
|
getTreatmentsWithConfig: getTreatmentsWithConfig,
|
|
61
|
+
getTreatmentsByFlagSets: getTreatmentsByFlagSets,
|
|
62
|
+
getTreatmentsWithConfigByFlagSets: getTreatmentsWithConfigByFlagSets,
|
|
63
|
+
getTreatmentsByFlagSet: getTreatmentsByFlagSet,
|
|
64
|
+
getTreatmentsWithConfigByFlagSet: getTreatmentsWithConfigByFlagSet,
|
|
45
65
|
track: track,
|
|
46
66
|
/**
|
|
47
67
|
* Add an attribute to client's in memory attributes storage
|
|
@@ -18,12 +18,13 @@ function clientCSDecorator(log, client, key, trafficType) {
|
|
|
18
18
|
getTreatmentWithConfig: clientCS.getTreatmentWithConfig.bind(clientCS, key),
|
|
19
19
|
getTreatments: clientCS.getTreatments.bind(clientCS, key),
|
|
20
20
|
getTreatmentsWithConfig: clientCS.getTreatmentsWithConfig.bind(clientCS, key),
|
|
21
|
+
getTreatmentsByFlagSets: clientCS.getTreatmentsByFlagSets.bind(clientCS, key),
|
|
22
|
+
getTreatmentsWithConfigByFlagSets: clientCS.getTreatmentsWithConfigByFlagSets.bind(clientCS, key),
|
|
23
|
+
getTreatmentsByFlagSet: clientCS.getTreatmentsByFlagSet.bind(clientCS, key),
|
|
24
|
+
getTreatmentsWithConfigByFlagSet: clientCS.getTreatmentsWithConfigByFlagSet.bind(clientCS, key),
|
|
21
25
|
// Key is bound to the `track` method. Same thing happens with trafficType but only if provided
|
|
22
26
|
track: trafficType ? clientCS.track.bind(clientCS, key, trafficType) : clientCS.track.bind(clientCS, key),
|
|
23
|
-
|
|
24
|
-
isClientSide: true,
|
|
25
|
-
key: key,
|
|
26
|
-
trafficType: trafficType
|
|
27
|
+
isClientSide: true
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
30
|
exports.clientCSDecorator = clientCSDecorator;
|
|
@@ -6,6 +6,7 @@ var inputValidation_1 = require("../utils/inputValidation");
|
|
|
6
6
|
var lang_1 = require("../utils/lang");
|
|
7
7
|
var constants_1 = require("../utils/constants");
|
|
8
8
|
var utils_1 = require("../trackers/impressionObserver/utils");
|
|
9
|
+
var splitFilters_1 = require("../utils/settingsValidation/splitFilters");
|
|
9
10
|
/**
|
|
10
11
|
* Decorator that validates the input before actually executing the client methods.
|
|
11
12
|
* We should "guard" the client here, while not polluting the "real" implementation of those methods.
|
|
@@ -16,18 +17,26 @@ function clientInputValidationDecorator(settings, client, readinessManager) {
|
|
|
16
17
|
/**
|
|
17
18
|
* Avoid repeating this validations code
|
|
18
19
|
*/
|
|
19
|
-
function validateEvaluationParams(maybeKey, maybeFeatureFlagNameOrNames, maybeAttributes, methodName) {
|
|
20
|
+
function validateEvaluationParams(maybeKey, maybeFeatureFlagNameOrNames, maybeAttributes, methodName, maybeFlagSetNameOrNames) {
|
|
20
21
|
var multi = (0, lang_1.startsWith)(methodName, 'getTreatments');
|
|
21
22
|
var key = (0, inputValidation_1.validateKey)(log, maybeKey, methodName);
|
|
22
|
-
var splitOrSplits =
|
|
23
|
+
var splitOrSplits = false;
|
|
24
|
+
var flagSetOrFlagSets = [];
|
|
25
|
+
if (maybeFeatureFlagNameOrNames) {
|
|
26
|
+
splitOrSplits = multi ? (0, inputValidation_1.validateSplits)(log, maybeFeatureFlagNameOrNames, methodName) : (0, inputValidation_1.validateSplit)(log, maybeFeatureFlagNameOrNames, methodName);
|
|
27
|
+
}
|
|
23
28
|
var attributes = (0, inputValidation_1.validateAttributes)(log, maybeAttributes, methodName);
|
|
24
29
|
var isNotDestroyed = (0, inputValidation_1.validateIfNotDestroyed)(log, readinessManager, methodName);
|
|
30
|
+
if (maybeFlagSetNameOrNames) {
|
|
31
|
+
flagSetOrFlagSets = (0, splitFilters_1.flagSetsAreValid)(log, methodName, maybeFlagSetNameOrNames, settings.sync.__splitFiltersValidation.groupedFilters.bySet);
|
|
32
|
+
}
|
|
25
33
|
(0, inputValidation_1.validateIfOperational)(log, readinessManager, methodName);
|
|
26
|
-
var valid = isNotDestroyed && key && splitOrSplits && attributes !== false;
|
|
34
|
+
var valid = isNotDestroyed && key && (splitOrSplits || flagSetOrFlagSets.length > 0) && attributes !== false;
|
|
27
35
|
return {
|
|
28
36
|
valid: valid,
|
|
29
37
|
key: key,
|
|
30
38
|
splitOrSplits: splitOrSplits,
|
|
39
|
+
flagSetOrFlagSets: flagSetOrFlagSets,
|
|
31
40
|
attributes: attributes
|
|
32
41
|
};
|
|
33
42
|
}
|
|
@@ -76,6 +85,42 @@ function clientInputValidationDecorator(settings, client, readinessManager) {
|
|
|
76
85
|
return wrapResult(res_2);
|
|
77
86
|
}
|
|
78
87
|
}
|
|
88
|
+
function getTreatmentsByFlagSets(maybeKey, maybeFlagSets, maybeAttributes) {
|
|
89
|
+
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, 'getTreatmentsByFlagSets', maybeFlagSets);
|
|
90
|
+
if (params.valid) {
|
|
91
|
+
return client.getTreatmentsByFlagSets(params.key, params.flagSetOrFlagSets, params.attributes);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
return wrapResult({});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function getTreatmentsWithConfigByFlagSets(maybeKey, maybeFlagSets, maybeAttributes) {
|
|
98
|
+
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, 'getTreatmentsWithConfigByFlagSets', maybeFlagSets);
|
|
99
|
+
if (params.valid) {
|
|
100
|
+
return client.getTreatmentsWithConfigByFlagSets(params.key, params.flagSetOrFlagSets, params.attributes);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
return wrapResult({});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function getTreatmentsByFlagSet(maybeKey, maybeFlagSet, maybeAttributes) {
|
|
107
|
+
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, 'getTreatmentsByFlagSet', [maybeFlagSet]);
|
|
108
|
+
if (params.valid) {
|
|
109
|
+
return client.getTreatmentsByFlagSet(params.key, params.flagSetOrFlagSets[0], params.attributes);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
return wrapResult({});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function getTreatmentsWithConfigByFlagSet(maybeKey, maybeFlagSet, maybeAttributes) {
|
|
116
|
+
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, 'getTreatmentsWithConfigByFlagSet', [maybeFlagSet]);
|
|
117
|
+
if (params.valid) {
|
|
118
|
+
return client.getTreatmentsWithConfigByFlagSet(params.key, params.flagSetOrFlagSets[0], params.attributes);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
return wrapResult({});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
79
124
|
function track(maybeKey, maybeTT, maybeEvent, maybeEventValue, maybeProperties) {
|
|
80
125
|
var key = (0, inputValidation_1.validateKey)(log, maybeKey, 'track');
|
|
81
126
|
var tt = (0, inputValidation_1.validateTrafficType)(log, maybeTT, 'track');
|
|
@@ -95,6 +140,10 @@ function clientInputValidationDecorator(settings, client, readinessManager) {
|
|
|
95
140
|
getTreatmentWithConfig: getTreatmentWithConfig,
|
|
96
141
|
getTreatments: getTreatments,
|
|
97
142
|
getTreatmentsWithConfig: getTreatmentsWithConfig,
|
|
143
|
+
getTreatmentsByFlagSets: getTreatmentsByFlagSets,
|
|
144
|
+
getTreatmentsWithConfigByFlagSets: getTreatmentsWithConfigByFlagSets,
|
|
145
|
+
getTreatmentsByFlagSet: getTreatmentsByFlagSet,
|
|
146
|
+
getTreatmentsWithConfigByFlagSet: getTreatmentsWithConfigByFlagSet,
|
|
98
147
|
track: track
|
|
99
148
|
};
|
|
100
149
|
}
|
package/cjs/sdkManager/index.js
CHANGED
|
@@ -27,7 +27,8 @@ function objectToView(splitObject) {
|
|
|
27
27
|
killed: splitObject.killed,
|
|
28
28
|
changeNumber: splitObject.changeNumber || 0,
|
|
29
29
|
treatments: collectTreatments(splitObject),
|
|
30
|
-
configs: splitObject.configurations || {}
|
|
30
|
+
configs: splitObject.configurations || {},
|
|
31
|
+
sets: splitObject.sets || []
|
|
31
32
|
};
|
|
32
33
|
}
|
|
33
34
|
function objectsToViews(splitObjects) {
|
package/cjs/services/splitApi.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.splitApiFactory = void 0;
|
|
|
4
4
|
var splitHttpClient_1 = require("./splitHttpClient");
|
|
5
5
|
var objectAssign_1 = require("../utils/lang/objectAssign");
|
|
6
6
|
var constants_1 = require("../utils/constants");
|
|
7
|
+
var constants_2 = require("../logger/constants");
|
|
7
8
|
var noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
|
|
8
9
|
function userKeyToQueryParam(userKey) {
|
|
9
10
|
return 'users=' + encodeURIComponent(userKey); // no need to check availability of `encodeURIComponent`, since it is a global highly supported.
|
|
@@ -40,7 +41,12 @@ function splitApiFactory(settings, platform, telemetryTracker) {
|
|
|
40
41
|
},
|
|
41
42
|
fetchSplitChanges: function (since, noCache, till) {
|
|
42
43
|
var url = urls.sdk + "/splitChanges?since=" + since + (till ? '&till=' + till : '') + (filterQueryString || '');
|
|
43
|
-
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(constants_1.SPLITS))
|
|
44
|
+
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(constants_1.SPLITS))
|
|
45
|
+
.catch(function (err) {
|
|
46
|
+
if (err.statusCode === 414)
|
|
47
|
+
settings.log.error(constants_2.ERROR_TOO_MANY_SETS);
|
|
48
|
+
throw err;
|
|
49
|
+
});
|
|
44
50
|
},
|
|
45
51
|
fetchSegmentChanges: function (since, segmentName, noCache, till) {
|
|
46
52
|
var url = urls.sdk + "/segmentChanges/" + segmentName + "?since=" + since + (till ? '&till=' + till : '');
|
|
@@ -16,6 +16,9 @@ var KeyBuilder = /** @class */ (function () {
|
|
|
16
16
|
KeyBuilder.prototype.buildTrafficTypeKey = function (trafficType) {
|
|
17
17
|
return this.prefix + ".trafficType." + trafficType;
|
|
18
18
|
};
|
|
19
|
+
KeyBuilder.prototype.buildFlagSetKey = function (flagSet) {
|
|
20
|
+
return this.prefix + ".flagset." + flagSet;
|
|
21
|
+
};
|
|
19
22
|
KeyBuilder.prototype.buildSplitKey = function (splitName) {
|
|
20
23
|
return this.prefix + ".split." + splitName;
|
|
21
24
|
};
|
|
@@ -8,6 +8,10 @@ exports.METHOD_NAMES = {
|
|
|
8
8
|
ts: 'treatments',
|
|
9
9
|
tc: 'treatmentWithConfig',
|
|
10
10
|
tcs: 'treatmentsWithConfig',
|
|
11
|
+
tf: 'treatmentsByFlagSet',
|
|
12
|
+
tfs: 'treatmentsByFlagSets',
|
|
13
|
+
tcf: 'treatmentsWithConfigByFlagSet',
|
|
14
|
+
tcfs: 'treatmentsWithConfigByFlagSets',
|
|
11
15
|
tr: 'track'
|
|
12
16
|
};
|
|
13
17
|
var KeyBuilderSS = /** @class */ (function (_super) {
|
|
@@ -5,6 +5,7 @@ var tslib_1 = require("tslib");
|
|
|
5
5
|
var AbstractSplitsCacheSync_1 = require("../AbstractSplitsCacheSync");
|
|
6
6
|
var lang_1 = require("../../utils/lang");
|
|
7
7
|
var constants_1 = require("./constants");
|
|
8
|
+
var sets_1 = require("../../utils/lang/sets");
|
|
8
9
|
/**
|
|
9
10
|
* ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
|
|
10
11
|
*/
|
|
@@ -16,12 +17,12 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
16
17
|
* @param {ISplitFiltersValidation} splitFiltersValidation
|
|
17
18
|
*/
|
|
18
19
|
function SplitsCacheInLocal(log, keys, expirationTimestamp, splitFiltersValidation) {
|
|
19
|
-
if (splitFiltersValidation === void 0) { splitFiltersValidation = { queryString: null, groupedFilters: { byName: [], byPrefix: [] }, validFilters: [] }; }
|
|
20
|
+
if (splitFiltersValidation === void 0) { splitFiltersValidation = { queryString: null, groupedFilters: { bySet: [], byName: [], byPrefix: [] }, validFilters: [] }; }
|
|
20
21
|
var _this = _super.call(this) || this;
|
|
21
22
|
_this.log = log;
|
|
22
|
-
_this.cacheReadyButNeedsToFlush = false;
|
|
23
23
|
_this.keys = keys;
|
|
24
24
|
_this.splitFiltersValidation = splitFiltersValidation;
|
|
25
|
+
_this.flagSetsFilter = _this.splitFiltersValidation.groupedFilters.bySet;
|
|
25
26
|
_this._checkExpiration(expirationTimestamp);
|
|
26
27
|
_this._checkFilterQuery();
|
|
27
28
|
return _this;
|
|
@@ -94,6 +95,9 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
94
95
|
localStorage.setItem(splitKey, JSON.stringify(split));
|
|
95
96
|
this._incrementCounts(split);
|
|
96
97
|
this._decrementCounts(previousSplit);
|
|
98
|
+
if (previousSplit)
|
|
99
|
+
this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
|
|
100
|
+
this.addToFlagSets(split);
|
|
97
101
|
return true;
|
|
98
102
|
}
|
|
99
103
|
catch (e) {
|
|
@@ -106,6 +110,8 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
106
110
|
var split = this.getSplit(name);
|
|
107
111
|
localStorage.removeItem(this.keys.buildSplitKey(name));
|
|
108
112
|
this._decrementCounts(split);
|
|
113
|
+
if (split)
|
|
114
|
+
this.removeFromFlagSets(split.name, split.sets);
|
|
109
115
|
return true;
|
|
110
116
|
}
|
|
111
117
|
catch (e) {
|
|
@@ -118,11 +124,6 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
118
124
|
return item && JSON.parse(item);
|
|
119
125
|
};
|
|
120
126
|
SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
|
|
121
|
-
// when cache is ready but using a new split query, we must clear all split data
|
|
122
|
-
if (this.cacheReadyButNeedsToFlush) {
|
|
123
|
-
this.clear();
|
|
124
|
-
this.cacheReadyButNeedsToFlush = false;
|
|
125
|
-
}
|
|
126
127
|
// when using a new split query, we must update it at the store
|
|
127
128
|
if (this.updateNewFilter) {
|
|
128
129
|
this.log.info(constants_1.LOG_PREFIX + 'Split filter query was modified. Updating cache.');
|
|
@@ -195,7 +196,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
195
196
|
* @override
|
|
196
197
|
*/
|
|
197
198
|
SplitsCacheInLocal.prototype.checkCache = function () {
|
|
198
|
-
return this.getChangeNumber() > -1
|
|
199
|
+
return this.getChangeNumber() > -1;
|
|
199
200
|
};
|
|
200
201
|
/**
|
|
201
202
|
* Clean Splits cache if its `lastUpdated` timestamp is older than the given `expirationTimestamp`,
|
|
@@ -211,31 +212,16 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
211
212
|
}
|
|
212
213
|
};
|
|
213
214
|
SplitsCacheInLocal.prototype._checkFilterQuery = function () {
|
|
214
|
-
var
|
|
215
|
-
var _a = this.splitFiltersValidation, queryString = _a.queryString, groupedFilters = _a.groupedFilters;
|
|
215
|
+
var queryString = this.splitFiltersValidation.queryString;
|
|
216
216
|
var queryKey = this.keys.buildSplitsFilterQueryKey();
|
|
217
217
|
var currentQueryString = localStorage.getItem(queryKey);
|
|
218
218
|
if (currentQueryString !== queryString) {
|
|
219
219
|
try {
|
|
220
220
|
// mark cache to update the new query filter on first successful splits fetch
|
|
221
221
|
this.updateNewFilter = true;
|
|
222
|
-
// if
|
|
223
|
-
if (this.checkCache())
|
|
224
|
-
|
|
225
|
-
localStorage.setItem(this.keys.buildSplitsTillKey(), '-1');
|
|
226
|
-
// * remove from cache splits that doesn't match with the new filters
|
|
227
|
-
this.getSplitNames().forEach(function (splitName) {
|
|
228
|
-
if (queryString && (
|
|
229
|
-
// @TODO consider redefining `groupedFilters` to expose a method like `groupedFilters::filter(splitName): boolean`
|
|
230
|
-
groupedFilters.byName.indexOf(splitName) > -1 ||
|
|
231
|
-
groupedFilters.byPrefix.some(function (prefix) { return splitName.startsWith(prefix + '__'); }))) {
|
|
232
|
-
// * set `cacheReadyButNeedsToFlush` so that `checkCache` returns true (the storage is ready to be used) and the data is cleared before updating on first successful splits fetch
|
|
233
|
-
_this.cacheReadyButNeedsToFlush = true;
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
_this.removeSplit(splitName);
|
|
237
|
-
});
|
|
238
|
-
}
|
|
222
|
+
// if there is cache, clear it
|
|
223
|
+
if (this.checkCache())
|
|
224
|
+
this.clear();
|
|
239
225
|
}
|
|
240
226
|
catch (e) {
|
|
241
227
|
this.log.error(constants_1.LOG_PREFIX + e);
|
|
@@ -243,6 +229,56 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
243
229
|
}
|
|
244
230
|
// if the filter didn't change, nothing is done
|
|
245
231
|
};
|
|
232
|
+
SplitsCacheInLocal.prototype.getNamesByFlagSets = function (flagSets) {
|
|
233
|
+
var _this = this;
|
|
234
|
+
var toReturn = new sets_1._Set([]);
|
|
235
|
+
flagSets.forEach(function (flagSet) {
|
|
236
|
+
var flagSetKey = _this.keys.buildFlagSetKey(flagSet);
|
|
237
|
+
var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
|
|
238
|
+
if (flagSetFromLocalStorage) {
|
|
239
|
+
var flagSetCache = new sets_1._Set(JSON.parse(flagSetFromLocalStorage));
|
|
240
|
+
toReturn = (0, sets_1.returnSetsUnion)(toReturn, flagSetCache);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
return toReturn;
|
|
244
|
+
};
|
|
245
|
+
SplitsCacheInLocal.prototype.addToFlagSets = function (featureFlag) {
|
|
246
|
+
var _this = this;
|
|
247
|
+
if (!featureFlag.sets)
|
|
248
|
+
return;
|
|
249
|
+
featureFlag.sets.forEach(function (featureFlagSet) {
|
|
250
|
+
if (_this.flagSetsFilter.length > 0 && !_this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === featureFlagSet; }))
|
|
251
|
+
return;
|
|
252
|
+
var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
|
|
253
|
+
var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
|
|
254
|
+
if (!flagSetFromLocalStorage)
|
|
255
|
+
flagSetFromLocalStorage = '[]';
|
|
256
|
+
var flagSetCache = new sets_1._Set(JSON.parse(flagSetFromLocalStorage));
|
|
257
|
+
flagSetCache.add(featureFlag.name);
|
|
258
|
+
localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
SplitsCacheInLocal.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
|
|
262
|
+
var _this = this;
|
|
263
|
+
if (!flagSets)
|
|
264
|
+
return;
|
|
265
|
+
flagSets.forEach(function (flagSet) {
|
|
266
|
+
_this.removeNames(flagSet, featureFlagName);
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
SplitsCacheInLocal.prototype.removeNames = function (flagSetName, featureFlagName) {
|
|
270
|
+
var flagSetKey = this.keys.buildFlagSetKey(flagSetName);
|
|
271
|
+
var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
|
|
272
|
+
if (!flagSetFromLocalStorage)
|
|
273
|
+
return;
|
|
274
|
+
var flagSetCache = new sets_1._Set(JSON.parse(flagSetFromLocalStorage));
|
|
275
|
+
flagSetCache.delete(featureFlagName);
|
|
276
|
+
if (flagSetCache.size === 0) {
|
|
277
|
+
localStorage.removeItem(flagSetKey);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
|
|
281
|
+
};
|
|
246
282
|
return SplitsCacheInLocal;
|
|
247
283
|
}(AbstractSplitsCacheSync_1.AbstractSplitsCacheSync));
|
|
248
284
|
exports.SplitsCacheInLocal = SplitsCacheInLocal;
|