@splitsoftware/splitio-commons 1.12.1-rc.3 → 1.12.1-rc.5

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.
Files changed (78) hide show
  1. package/CHANGES.txt +1 -1
  2. package/cjs/logger/constants.js +3 -3
  3. package/cjs/logger/messages/warn.js +2 -2
  4. package/cjs/sdkClient/client.js +27 -21
  5. package/cjs/sdkClient/clientInputValidation.js +21 -21
  6. package/cjs/sdkManager/index.js +13 -15
  7. package/cjs/storages/KeyBuilder.js +13 -1
  8. package/cjs/storages/KeyBuilderCS.js +1 -4
  9. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +12 -16
  10. package/cjs/storages/inLocalStorage/index.js +1 -1
  11. package/cjs/storages/inRedis/SplitsCacheInRedis.js +2 -2
  12. package/cjs/storages/inRedis/index.js +1 -1
  13. package/cjs/storages/pluggable/SplitsCachePluggable.js +2 -2
  14. package/cjs/storages/pluggable/index.js +14 -3
  15. package/cjs/trackers/eventTracker.js +4 -4
  16. package/cjs/utils/constants/index.js +16 -2
  17. package/cjs/utils/lang/sets.js +3 -3
  18. package/cjs/utils/settingsValidation/index.js +1 -1
  19. package/cjs/utils/settingsValidation/mode.js +10 -3
  20. package/cjs/utils/settingsValidation/splitFilters.js +20 -19
  21. package/esm/logger/constants.js +2 -2
  22. package/esm/logger/messages/warn.js +2 -2
  23. package/esm/sdkClient/client.js +28 -22
  24. package/esm/sdkClient/clientInputValidation.js +23 -23
  25. package/esm/sdkManager/index.js +7 -9
  26. package/esm/storages/KeyBuilder.js +11 -0
  27. package/esm/storages/KeyBuilderCS.js +1 -4
  28. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +12 -16
  29. package/esm/storages/inLocalStorage/index.js +1 -1
  30. package/esm/storages/inRedis/SplitsCacheInRedis.js +3 -3
  31. package/esm/storages/inRedis/index.js +1 -1
  32. package/esm/storages/pluggable/SplitsCachePluggable.js +3 -3
  33. package/esm/storages/pluggable/index.js +15 -4
  34. package/esm/trackers/eventTracker.js +4 -4
  35. package/esm/utils/constants/index.js +14 -0
  36. package/esm/utils/lang/sets.js +1 -1
  37. package/esm/utils/settingsValidation/index.js +2 -2
  38. package/esm/utils/settingsValidation/mode.js +7 -1
  39. package/esm/utils/settingsValidation/splitFilters.js +11 -10
  40. package/package.json +1 -1
  41. package/src/logger/constants.ts +2 -2
  42. package/src/logger/messages/warn.ts +2 -2
  43. package/src/sdkClient/client.ts +26 -23
  44. package/src/sdkClient/clientInputValidation.ts +23 -23
  45. package/src/sdkManager/index.ts +7 -10
  46. package/src/storages/KeyBuilder.ts +14 -1
  47. package/src/storages/KeyBuilderCS.ts +1 -5
  48. package/src/storages/KeyBuilderSS.ts +4 -4
  49. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +16 -14
  50. package/src/storages/inLocalStorage/index.ts +1 -1
  51. package/src/storages/inRedis/SplitsCacheInRedis.ts +3 -3
  52. package/src/storages/inRedis/index.ts +1 -1
  53. package/src/storages/pluggable/SplitsCachePluggable.ts +3 -3
  54. package/src/storages/pluggable/index.ts +15 -5
  55. package/src/storages/types.ts +3 -3
  56. package/src/trackers/eventTracker.ts +4 -4
  57. package/src/utils/constants/index.ts +16 -0
  58. package/src/utils/lang/sets.ts +1 -1
  59. package/src/utils/murmur3/murmur3.ts +0 -1
  60. package/src/utils/settingsValidation/index.ts +2 -2
  61. package/src/utils/settingsValidation/mode.ts +8 -1
  62. package/src/utils/settingsValidation/splitFilters.ts +11 -10
  63. package/types/logger/constants.d.ts +2 -2
  64. package/types/storages/AbstractSplitsCache.d.ts +46 -0
  65. package/types/storages/KeyBuilder.d.ts +8 -1
  66. package/types/storages/KeyBuilderCS.d.ts +0 -1
  67. package/types/storages/KeyBuilderSS.d.ts +4 -4
  68. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +5 -5
  69. package/types/utils/constants/index.d.ts +12 -0
  70. package/types/utils/lang/sets.d.ts +1 -1
  71. package/types/utils/settingsValidation/mode.d.ts +5 -1
  72. package/types/utils/settingsValidation/splitFilters.d.ts +1 -1
  73. package/cjs/trackers/impressionObserver/utils.js +0 -11
  74. package/cjs/utils/redis/RedisMock.js +0 -31
  75. package/esm/trackers/impressionObserver/utils.js +0 -7
  76. package/esm/utils/redis/RedisMock.js +0 -28
  77. package/src/trackers/impressionObserver/utils.ts +0 -9
  78. package/src/utils/redis/RedisMock.ts +0 -31
@@ -3,6 +3,7 @@ import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSyn
3
3
  import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
4
4
  import { LOG_PREFIX } from './constants';
5
5
  import { _Set, setToArray } from '../../utils/lang/sets';
6
+ import { getStorageHash } from '../KeyBuilder';
6
7
  /**
7
8
  * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
8
9
  */
@@ -13,13 +14,12 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
13
14
  * @param {number | undefined} expirationTimestamp
14
15
  * @param {ISplitFiltersValidation} splitFiltersValidation
15
16
  */
16
- function SplitsCacheInLocal(log, keys, expirationTimestamp, splitFiltersValidation) {
17
- if (splitFiltersValidation === void 0) { splitFiltersValidation = { queryString: null, groupedFilters: { bySet: [], byName: [], byPrefix: [] }, validFilters: [] }; }
17
+ function SplitsCacheInLocal(settings, keys, expirationTimestamp) {
18
18
  var _this = _super.call(this) || this;
19
- _this.log = log;
20
19
  _this.keys = keys;
21
- _this.splitFiltersValidation = splitFiltersValidation;
22
- _this.flagSetsFilter = _this.splitFiltersValidation.groupedFilters.bySet;
20
+ _this.log = settings.log;
21
+ _this.storageHash = getStorageHash(settings);
22
+ _this.flagSetsFilter = settings.sync.__splitFiltersValidation.groupedFilters.bySet;
23
23
  _this._checkExpiration(expirationTimestamp);
24
24
  _this._checkFilterQuery();
25
25
  return _this;
@@ -123,14 +123,10 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
123
123
  SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
124
124
  // when using a new split query, we must update it at the store
125
125
  if (this.updateNewFilter) {
126
- this.log.info(LOG_PREFIX + 'Split filter query was modified. Updating cache.');
127
- var queryKey = this.keys.buildSplitsFilterQueryKey();
128
- var queryString = this.splitFiltersValidation.queryString;
126
+ this.log.info(LOG_PREFIX + 'SDK key or feature flag filter criteria was modified. Updating cache.');
127
+ var storageHashKey = this.keys.buildHashKey();
129
128
  try {
130
- if (queryString)
131
- localStorage.setItem(queryKey, queryString);
132
- else
133
- localStorage.removeItem(queryKey);
129
+ localStorage.setItem(storageHashKey, this.storageHash);
134
130
  }
135
131
  catch (e) {
136
132
  this.log.error(LOG_PREFIX + e);
@@ -208,11 +204,11 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
208
204
  this.clear();
209
205
  }
210
206
  };
207
+ // @TODO eventually remove `_checkFilterQuery`. Cache should be cleared at the storage level, reusing same logic than PluggableStorage
211
208
  SplitsCacheInLocal.prototype._checkFilterQuery = function () {
212
- var queryString = this.splitFiltersValidation.queryString;
213
- var queryKey = this.keys.buildSplitsFilterQueryKey();
214
- var currentQueryString = localStorage.getItem(queryKey);
215
- if (currentQueryString !== queryString) {
209
+ var storageHashKey = this.keys.buildHashKey();
210
+ var storageHash = localStorage.getItem(storageHashKey);
211
+ if (storageHash !== this.storageHash) {
216
212
  try {
217
213
  // mark cache to update the new query filter on first successful splits fetch
218
214
  this.updateNewFilter = true;
@@ -31,7 +31,7 @@ export function InLocalStorage(options) {
31
31
  var matchingKey = getMatching(settings.core.key);
32
32
  var keys = new KeyBuilderCS(prefix, matchingKey);
33
33
  var expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
34
- var splits = new SplitsCacheInLocal(log, keys, expirationTimestamp, __splitFiltersValidation);
34
+ var splits = new SplitsCacheInLocal(settings, keys, expirationTimestamp);
35
35
  var segments = new MySegmentsCacheInLocal(log, keys);
36
36
  return {
37
37
  splits: splits,
@@ -2,7 +2,7 @@ import { __extends, __spreadArray } from "tslib";
2
2
  import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
3
3
  import { LOG_PREFIX } from './constants';
4
4
  import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
5
- import { _Set, returnListDifference } from '../../utils/lang/sets';
5
+ import { _Set, returnDifference } from '../../utils/lang/sets';
6
6
  /**
7
7
  * Discard errors for an answer of multiple operations.
8
8
  */
@@ -49,8 +49,8 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
49
49
  };
50
50
  SplitsCacheInRedis.prototype._updateFlagSets = function (featureFlagName, flagSetsOfRemovedFlag, flagSetsOfAddedFlag) {
51
51
  var _this = this;
52
- var removeFromFlagSets = returnListDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag);
53
- var addToFlagSets = returnListDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag);
52
+ var removeFromFlagSets = returnDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag);
53
+ var addToFlagSets = returnDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag);
54
54
  if (this.flagSetsFilter.length > 0) {
55
55
  addToFlagSets = addToFlagSets.filter(function (flagSet) {
56
56
  return _this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === flagSet; });
@@ -36,7 +36,7 @@ export function InRedisStorage(options) {
36
36
  telemetry.recordConfig();
37
37
  });
38
38
  return {
39
- splits: new SplitsCacheInRedis(log, keys, redisClient),
39
+ splits: new SplitsCacheInRedis(log, keys, redisClient, settings.sync.__splitFiltersValidation),
40
40
  segments: new SegmentsCacheInRedis(log, keys, redisClient),
41
41
  impressions: new ImpressionsCacheInRedis(log, keys.buildImpressionsKey(), redisClient, metadata),
42
42
  impressionCounts: impressionCountsCache,
@@ -2,7 +2,7 @@ import { __extends, __spreadArray } from "tslib";
2
2
  import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
3
3
  import { LOG_PREFIX } from './constants';
4
4
  import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
5
- import { _Set, returnListDifference } from '../../utils/lang/sets';
5
+ import { _Set, returnDifference } from '../../utils/lang/sets';
6
6
  /**
7
7
  * ISplitsCacheAsync implementation for pluggable storages.
8
8
  */
@@ -36,8 +36,8 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
36
36
  };
37
37
  SplitsCachePluggable.prototype._updateFlagSets = function (featureFlagName, flagSetsOfRemovedFlag, flagSetsOfAddedFlag) {
38
38
  var _this = this;
39
- var removeFromFlagSets = returnListDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag);
40
- var addToFlagSets = returnListDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag);
39
+ var removeFromFlagSets = returnDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag);
40
+ var addToFlagSets = returnDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag);
41
41
  if (this.flagSetsFilter.length > 0) {
42
42
  addToFlagSets = addToFlagSets.filter(function (flagSet) {
43
43
  return _this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === flagSet; });
@@ -6,7 +6,7 @@ import { ImpressionsCachePluggable } from './ImpressionsCachePluggable';
6
6
  import { EventsCachePluggable } from './EventsCachePluggable';
7
7
  import { wrapperAdapter, METHODS_TO_PROMISE_WRAP } from './wrapperAdapter';
8
8
  import { isObject } from '../../utils/lang';
9
- import { validatePrefix } from '../KeyBuilder';
9
+ import { getStorageHash, validatePrefix } from '../KeyBuilder';
10
10
  import { CONSUMER_PARTIAL_MODE, DEBUG, NONE, STORAGE_PLUGGABLE } from '../../utils/constants';
11
11
  import { ImpressionsCacheInMemory } from '../inMemory/ImpressionsCacheInMemory';
12
12
  import { EventsCacheInMemory } from '../inMemory/EventsCacheInMemory';
@@ -73,15 +73,26 @@ export function PluggableStorage(options) {
73
73
  undefined;
74
74
  // Connects to wrapper and emits SDK_READY event on main client
75
75
  var connectPromise = wrapper.connect().then(function () {
76
- onReadyCb();
77
- // Start periodic flush of async storages if not running synchronizer (producer mode)
78
- if (!isSyncronizer) {
76
+ if (isSyncronizer) {
77
+ // In standalone or producer mode, clear storage if SDK key or feature flag filter has changed
78
+ return wrapper.get(keys.buildHashKey()).then(function (hash) {
79
+ var currentHash = getStorageHash(settings);
80
+ if (hash !== currentHash) {
81
+ return wrapper.getKeysByPrefix(keys.prefix + ".").then(function (storageKeys) {
82
+ return Promise.all(storageKeys.map(function (storageKey) { return wrapper.del(storageKey); }));
83
+ }).then(function () { return wrapper.set(keys.buildHashKey(), currentHash); });
84
+ }
85
+ }).then(onReadyCb);
86
+ }
87
+ else {
88
+ // Start periodic flush of async storages if not running synchronizer (producer mode)
79
89
  if (impressionCountsCache && impressionCountsCache.start)
80
90
  impressionCountsCache.start();
81
91
  if (uniqueKeysCache && uniqueKeysCache.start)
82
92
  uniqueKeysCache.start();
83
93
  if (telemetry && telemetry.recordConfig)
84
94
  telemetry.recordConfig();
95
+ onReadyCb();
85
96
  }
86
97
  }).catch(function (e) {
87
98
  e = e || new Error('Error connecting wrapper');
@@ -2,7 +2,7 @@ import { objectAssign } from '../utils/lang/objectAssign';
2
2
  import { thenable } from '../utils/promise/thenable';
3
3
  import { EVENTS_TRACKER_SUCCESS, ERROR_EVENTS_TRACKER } from '../logger/constants';
4
4
  import { CONSENT_DECLINED, DROPPED, QUEUED } from '../utils/constants';
5
- import { isStorageSync } from './impressionObserver/utils';
5
+ import { isConsumerMode } from '../utils/settingsValidation/mode';
6
6
  /**
7
7
  * Event tracker stores events in cache and pass them to the integrations manager if provided.
8
8
  *
@@ -10,8 +10,8 @@ import { isStorageSync } from './impressionObserver/utils';
10
10
  * @param integrationsManager optional event handler used for integrations
11
11
  */
12
12
  export function eventTrackerFactory(settings, eventsCache, integrationsManager, telemetryCache) {
13
- var log = settings.log;
14
- var isSync = isStorageSync(settings);
13
+ var log = settings.log, mode = settings.mode;
14
+ var isAsync = isConsumerMode(mode);
15
15
  function queueEventsCallback(eventData, tracked) {
16
16
  var eventTypeId = eventData.eventTypeId, trafficTypeName = eventData.trafficTypeName, key = eventData.key, value = eventData.value, timestamp = eventData.timestamp, properties = eventData.properties;
17
17
  // Logging every prop would be too much.
@@ -38,7 +38,7 @@ export function eventTrackerFactory(settings, eventsCache, integrationsManager,
38
38
  return {
39
39
  track: function (eventData, size) {
40
40
  if (settings.userConsent === CONSENT_DECLINED) {
41
- return isSync ? false : Promise.resolve(false);
41
+ return isAsync ? Promise.resolve(false) : false;
42
42
  }
43
43
  var tracked = eventsCache.track(eventData, size);
44
44
  if (thenable(tracked)) {
@@ -29,6 +29,20 @@ export var STORAGE_PLUGGABLE = 'PLUGGABLE';
29
29
  export var CONSENT_GRANTED = 'GRANTED'; // The user has granted consent for tracking events and impressions
30
30
  export var CONSENT_DECLINED = 'DECLINED'; // The user has declined consent for tracking events and impressions
31
31
  export var CONSENT_UNKNOWN = 'UNKNOWN'; // The user has neither granted nor declined consent for tracking events and impressions
32
+ // Client method names
33
+ export var GET_TREATMENT = 'getTreatment';
34
+ export var GET_TREATMENTS = 'getTreatments';
35
+ export var GET_TREATMENT_WITH_CONFIG = 'getTreatmentWithConfig';
36
+ export var GET_TREATMENTS_WITH_CONFIG = 'getTreatmentsWithConfig';
37
+ export var GET_TREATMENTS_BY_FLAG_SET = 'getTreatmentsByFlagSet';
38
+ export var GET_TREATMENTS_BY_FLAG_SETS = 'getTreatmentsByFlagSets';
39
+ export var GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET = 'getTreatmentsWithConfigByFlagSet';
40
+ export var GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS = 'getTreatmentsWithConfigByFlagSets';
41
+ export var TRACK_FN_LABEL = 'track';
42
+ // Manager method names
43
+ export var SPLIT_FN_LABEL = 'split';
44
+ export var SPLITS_FN_LABEL = 'splits';
45
+ export var NAMES_FN_LABEL = 'names';
32
46
  // Telemetry
33
47
  export var QUEUED = 0;
34
48
  export var DROPPED = 1;
@@ -102,7 +102,7 @@ export function returnSetsUnion(set, set2) {
102
102
  });
103
103
  return result;
104
104
  }
105
- export function returnListDifference(list, list2) {
105
+ export function returnDifference(list, list2) {
106
106
  if (list === void 0) { list = []; }
107
107
  if (list2 === void 0) { list2 = []; }
108
108
  var result = new _Set(list);
@@ -1,5 +1,5 @@
1
1
  import { merge, get } from '../lang';
2
- import { mode } from './mode';
2
+ import { validateMode } from './mode';
3
3
  import { validateSplitFilters } from './splitFilters';
4
4
  import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE, DEBUG } from '../constants';
5
5
  import { validImpressionsMode } from './impressionsMode';
@@ -123,7 +123,7 @@ export function settingsValidation(config, validationParams) {
123
123
  startup.eventsFirstPushWindow = fromSecondsToMillis(startup.eventsFirstPushWindow);
124
124
  // ensure a valid SDK mode
125
125
  // @ts-ignore, modify readonly prop
126
- withDefaults.mode = mode(withDefaults.core.authorizationKey, withDefaults.mode);
126
+ withDefaults.mode = validateMode(withDefaults.core.authorizationKey, withDefaults.mode);
127
127
  // ensure a valid Storage based on mode defined.
128
128
  // @ts-ignore, modify readonly prop
129
129
  if (storage)
@@ -1,5 +1,5 @@
1
1
  import { LOCALHOST_MODE, STANDALONE_MODE, PRODUCER_MODE, CONSUMER_MODE, CONSUMER_PARTIAL_MODE } from '../constants';
2
- export function mode(key, mode) {
2
+ export function validateMode(key, mode) {
3
3
  // Leaving the comparison as is, in case we change the mode name but not the setting.
4
4
  if (key === 'localhost')
5
5
  return LOCALHOST_MODE;
@@ -7,3 +7,9 @@ export function mode(key, mode) {
7
7
  throw Error('Invalid mode provided');
8
8
  return mode;
9
9
  }
10
+ /**
11
+ * Storage is async if mode is consumer or partial consumer
12
+ */
13
+ export function isConsumerMode(mode) {
14
+ return CONSUMER_MODE === mode || CONSUMER_PARTIAL_MODE === mode;
15
+ }
@@ -1,8 +1,8 @@
1
- import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE } from '../constants';
2
1
  import { validateSplits } from '../inputValidation/splits';
3
- import { WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_EMPTY, WARN_SPLITS_FILTER_INVALID, SETTINGS_SPLITS_FILTER, LOG_PREFIX_SETTINGS, ERROR_SETS_FILTER_EXCLUSIVE, WARN_SPLITS_FILTER_LOWERCASE_SET, WARN_SPLITS_FILTER_INVALID_SET, WARN_FLAGSET_NOT_CONFIGURED } from '../../logger/constants';
2
+ import { WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_EMPTY, WARN_SPLITS_FILTER_INVALID, SETTINGS_SPLITS_FILTER, LOG_PREFIX_SETTINGS, ERROR_SETS_FILTER_EXCLUSIVE, WARN_LOWERCASE_FLAGSET, WARN_INVALID_FLAGSET, WARN_FLAGSET_NOT_CONFIGURED } from '../../logger/constants';
4
3
  import { objectAssign } from '../lang/objectAssign';
5
4
  import { find, uniq } from '../lang';
5
+ import { isConsumerMode } from './mode';
6
6
  // Split filters metadata.
7
7
  // Ordered according to their precedency when forming the filter query string: `&names=<values>&prefixes=<values>`
8
8
  var FILTERS_METADATA = [
@@ -45,7 +45,7 @@ function validateSplitFilter(log, type, values, maxLength) {
45
45
  var result = validateSplits(log, values, LOG_PREFIX_SETTINGS, type + " filter", type + " filter value");
46
46
  if (result) {
47
47
  if (type === 'bySet') {
48
- result = sanitizeFlagSets(log, result);
48
+ result = sanitizeFlagSets(log, result, LOG_PREFIX_SETTINGS);
49
49
  }
50
50
  // check max length
51
51
  if (result.length > maxLength)
@@ -78,7 +78,7 @@ function queryStringBuilder(groupedFilters) {
78
78
  return queryParams.length > 0 ? '&' + queryParams.join('&') : null;
79
79
  }
80
80
  /**
81
- * Sanitizes set names list taking in account:
81
+ * Sanitizes set names list taking into account:
82
82
  * - It should be lowercase
83
83
  * - Must adhere the following regular expression /^[a-z0-9][_a-z0-9]{0,49}$/ that means
84
84
  * - must start with a letter or number
@@ -88,20 +88,21 @@ function queryStringBuilder(groupedFilters) {
88
88
  *
89
89
  * @param {ILogger} log
90
90
  * @param {string[]} flagSets
91
+ * @param {string} method
91
92
  * @returns sanitized list of set names
92
93
  */
93
- function sanitizeFlagSets(log, flagSets) {
94
+ function sanitizeFlagSets(log, flagSets, method) {
94
95
  var sanitizedSets = flagSets
95
96
  .map(function (flagSet) {
96
97
  if (CAPITAL_LETTERS_REGEX.test(flagSet)) {
97
- log.warn(WARN_SPLITS_FILTER_LOWERCASE_SET, [flagSet]);
98
+ log.warn(WARN_LOWERCASE_FLAGSET, [method, flagSet]);
98
99
  flagSet = flagSet.toLowerCase();
99
100
  }
100
101
  return flagSet;
101
102
  })
102
103
  .filter(function (flagSet) {
103
104
  if (!VALID_FLAGSET_REGEX.test(flagSet)) {
104
- log.warn(WARN_SPLITS_FILTER_INVALID_SET, [flagSet, VALID_FLAGSET_REGEX, flagSet]);
105
+ log.warn(WARN_INVALID_FLAGSET, [method, flagSet, VALID_FLAGSET_REGEX, flagSet]);
105
106
  return false;
106
107
  }
107
108
  if (typeof flagSet !== 'string')
@@ -137,7 +138,7 @@ export function validateSplitFilters(log, maybeSplitFilters, mode) {
137
138
  if (!maybeSplitFilters)
138
139
  return res;
139
140
  // Warn depending on the mode
140
- if (mode === CONSUMER_MODE || mode === CONSUMER_PARTIAL_MODE) {
141
+ if (isConsumerMode(mode)) {
141
142
  log.warn(WARN_SPLITS_FILTER_IGNORED);
142
143
  return res;
143
144
  }
@@ -175,9 +176,9 @@ export function validateSplitFilters(log, maybeSplitFilters, mode) {
175
176
  log.debug(SETTINGS_SPLITS_FILTER, [res.queryString]);
176
177
  return res;
177
178
  }
178
- export function flagSetsAreValid(log, method, flagSets, flagSetsInConfig) {
179
+ export function validateFlagSets(log, method, flagSets, flagSetsInConfig) {
179
180
  var sets = validateSplits(log, flagSets, method, 'flag sets', 'flag set');
180
- var toReturn = sets ? sanitizeFlagSets(log, sets) : [];
181
+ var toReturn = sets ? sanitizeFlagSets(log, sets, method) : [];
181
182
  if (flagSetsInConfig.length > 0) {
182
183
  toReturn = toReturn.filter(function (flagSet) {
183
184
  if (flagSetsInConfig.indexOf(flagSet) > -1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.12.1-rc.3",
3
+ "version": "1.12.1-rc.5",
4
4
  "description": "Split Javascript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -97,8 +97,8 @@ export const WARN_SPLITS_FILTER_EMPTY = 221;
97
97
  export const WARN_SDK_KEY = 222;
98
98
  export const STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 = 223;
99
99
  export const STREAMING_PARSING_SPLIT_UPDATE = 224;
100
- export const WARN_SPLITS_FILTER_INVALID_SET = 225;
101
- export const WARN_SPLITS_FILTER_LOWERCASE_SET = 226;
100
+ export const WARN_INVALID_FLAGSET = 225;
101
+ export const WARN_LOWERCASE_FLAGSET = 226;
102
102
  export const WARN_FLAGSET_NOT_CONFIGURED = 227;
103
103
  export const WARN_FLAGSET_WITHOUT_FLAGS = 228;
104
104
 
@@ -34,7 +34,7 @@ export const codesWarn: [number, string][] = codesError.concat([
34
34
 
35
35
  [c.STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, c.LOG_PREFIX_SYNC_STREAMING + 'Fetching MySegments due to an error processing %s notification: %s'],
36
36
  [c.STREAMING_PARSING_SPLIT_UPDATE, c.LOG_PREFIX_SYNC_STREAMING + 'Fetching SplitChanges due to an error processing SPLIT_UPDATE notification: %s'],
37
- [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.'],
38
- [c.WARN_SPLITS_FILTER_LOWERCASE_SET, c.LOG_PREFIX_SETTINGS + ': flag set %s should be all lowercase - converting string to lowercase.'],
37
+ [c.WARN_INVALID_FLAGSET, '%s: 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.'],
38
+ [c.WARN_LOWERCASE_FLAGSET, '%s: flag set %s should be all lowercase - converting string to lowercase.'],
39
39
  [c.WARN_FLAGSET_WITHOUT_FLAGS, '%s: you passed %s flag set that does not contain cached feature flag names. Please double check what flag sets are in use in the Split user interface.'],
40
40
  ]);
@@ -4,12 +4,12 @@ import { getMatching, getBucketing } from '../utils/key';
4
4
  import { validateSplitExistence } from '../utils/inputValidation/splitExistence';
5
5
  import { validateTrafficTypeExistence } from '../utils/inputValidation/trafficTypeExistence';
6
6
  import { SDK_NOT_READY } from '../utils/labels';
7
- import { CONTROL, TREATMENT, TREATMENTS, TREATMENT_WITH_CONFIG, TREATMENTS_WITH_CONFIG, TRACK, TREATMENTS_WITH_CONFIG_BY_FLAGSETS, TREATMENTS_BY_FLAGSETS, TREATMENTS_BY_FLAGSET, TREATMENTS_WITH_CONFIG_BY_FLAGSET } from '../utils/constants';
7
+ import { CONTROL, TREATMENT, TREATMENTS, TREATMENT_WITH_CONFIG, TREATMENTS_WITH_CONFIG, TRACK, TREATMENTS_WITH_CONFIG_BY_FLAGSETS, TREATMENTS_BY_FLAGSETS, TREATMENTS_BY_FLAGSET, TREATMENTS_WITH_CONFIG_BY_FLAGSET, GET_TREATMENTS_WITH_CONFIG, GET_TREATMENTS_BY_FLAG_SETS, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, GET_TREATMENTS_BY_FLAG_SET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, GET_TREATMENT_WITH_CONFIG, GET_TREATMENT, GET_TREATMENTS, TRACK_FN_LABEL } from '../utils/constants';
8
8
  import { IEvaluationResult } from '../evaluator/types';
9
9
  import { SplitIO, ImpressionDTO } from '../types';
10
10
  import { IMPRESSION, IMPRESSION_QUEUEING } from '../logger/constants';
11
11
  import { ISdkFactoryContext } from '../sdkFactory/types';
12
- import { isStorageSync } from '../trackers/impressionObserver/utils';
12
+ import { isConsumerMode } from '../utils/settingsValidation/mode';
13
13
  import { Method } from '../sync/submitters/types';
14
14
 
15
15
  const treatmentNotReady = { treatment: CONTROL, label: SDK_NOT_READY };
@@ -28,13 +28,14 @@ function treatmentsNotReady(featureFlagNames: string[]) {
28
28
  export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | SplitIO.IAsyncClient {
29
29
  const { sdkReadinessManager: { readinessManager }, storage, settings, impressionsTracker, eventTracker, telemetryTracker } = params;
30
30
  const { log, mode } = settings;
31
+ const isAsync = isConsumerMode(mode);
31
32
 
32
- function getTreatment(key: SplitIO.SplitKey, featureFlagName: string, attributes: SplitIO.Attributes | undefined, withConfig = false) {
33
+ function getTreatment(key: SplitIO.SplitKey, featureFlagName: string, attributes: SplitIO.Attributes | undefined, withConfig = false, methodName = GET_TREATMENT) {
33
34
  const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENT_WITH_CONFIG : TREATMENT);
34
35
 
35
36
  const wrapUp = (evaluationResult: IEvaluationResult) => {
36
37
  const queue: ImpressionDTO[] = [];
37
- const treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig, `getTreatment${withConfig ? 'withConfig' : ''}`, queue);
38
+ const treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig, methodName, queue);
38
39
  impressionsTracker.track(queue, attributes);
39
40
 
40
41
  stopTelemetryTracker(queue[0] && queue[0].label);
@@ -43,25 +44,25 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
43
44
 
44
45
  const evaluation = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
45
46
  evaluateFeature(log, key, featureFlagName, attributes, storage) :
46
- isStorageSync(settings) ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
47
- treatmentNotReady :
48
- Promise.resolve(treatmentNotReady); // Promisify if async
47
+ isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
48
+ Promise.resolve(treatmentNotReady) :
49
+ treatmentNotReady;
49
50
 
50
51
  return thenable(evaluation) ? evaluation.then((res) => wrapUp(res)) : wrapUp(evaluation);
51
52
  }
52
53
 
53
54
  function getTreatmentWithConfig(key: SplitIO.SplitKey, featureFlagName: string, attributes: SplitIO.Attributes | undefined) {
54
- return getTreatment(key, featureFlagName, attributes, true);
55
+ return getTreatment(key, featureFlagName, attributes, true, GET_TREATMENT_WITH_CONFIG);
55
56
  }
56
57
 
57
- function getTreatments(key: SplitIO.SplitKey, featureFlagNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false) {
58
+ function getTreatments(key: SplitIO.SplitKey, featureFlagNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false, methodName = GET_TREATMENTS) {
58
59
  const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENTS_WITH_CONFIG : TREATMENTS);
59
60
 
60
61
  const wrapUp = (evaluationResults: Record<string, IEvaluationResult>) => {
61
62
  const queue: ImpressionDTO[] = [];
62
63
  const treatments: Record<string, SplitIO.Treatment | SplitIO.TreatmentWithConfig> = {};
63
64
  Object.keys(evaluationResults).forEach(featureFlagName => {
64
- treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig, `getTreatments${withConfig ? 'withConfig' : ''}`, queue);
65
+ treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
65
66
  });
66
67
  impressionsTracker.track(queue, attributes);
67
68
 
@@ -71,26 +72,26 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
71
72
 
72
73
  const evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
73
74
  evaluateFeatures(log, key, featureFlagNames, attributes, storage) :
74
- isStorageSync(settings) ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
75
- treatmentsNotReady(featureFlagNames) :
76
- Promise.resolve(treatmentsNotReady(featureFlagNames)); // Promisify if async
75
+ isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
76
+ Promise.resolve(treatmentsNotReady(featureFlagNames)) :
77
+ treatmentsNotReady(featureFlagNames);
77
78
 
78
79
  return thenable(evaluations) ? evaluations.then((res) => wrapUp(res)) : wrapUp(evaluations);
79
80
  }
80
81
 
81
82
  function getTreatmentsWithConfig(key: SplitIO.SplitKey, featureFlagNames: string[], attributes: SplitIO.Attributes | undefined) {
82
- return getTreatments(key, featureFlagNames, attributes, true);
83
+ return getTreatments(key, featureFlagNames, attributes, true, GET_TREATMENTS_WITH_CONFIG);
83
84
  }
84
85
 
85
- function getTreatmentsByFlagSets(key: SplitIO.SplitKey, flagSetNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false, method: Method = TREATMENTS_BY_FLAGSETS) {
86
+ function getTreatmentsByFlagSets(key: SplitIO.SplitKey, flagSetNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false, method: Method = TREATMENTS_BY_FLAGSETS, methodName = GET_TREATMENTS_BY_FLAG_SETS) {
86
87
  const stopTelemetryTracker = telemetryTracker.trackEval(method);
87
88
 
88
- const wrapUp = (evaluationResults: Record<string,IEvaluationResult>) => {
89
+ const wrapUp = (evaluationResults: Record<string, IEvaluationResult>) => {
89
90
  const queue: ImpressionDTO[] = [];
90
91
  const treatments: Record<string, SplitIO.Treatment | SplitIO.TreatmentWithConfig> = {};
91
92
  const evaluations = evaluationResults;
92
93
  Object.keys(evaluations).forEach(featureFlagName => {
93
- treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig, `getTreatmentsByFlagSets${withConfig ? 'WithConfig' : ''}`, queue);
94
+ treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
94
95
  });
95
96
  impressionsTracker.track(queue, attributes);
96
97
 
@@ -99,22 +100,24 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
99
100
  };
100
101
 
101
102
  const evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
102
- evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage, method) :
103
- isStorageSync(settings) ? {} : Promise.resolve({}); // Promisify if async
103
+ evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage, methodName) :
104
+ isAsync ?
105
+ Promise.resolve({}) :
106
+ {};
104
107
 
105
108
  return thenable(evaluations) ? evaluations.then((res) => wrapUp(res)) : wrapUp(evaluations);
106
109
  }
107
110
 
108
111
  function getTreatmentsWithConfigByFlagSets(key: SplitIO.SplitKey, flagSetNames: string[], attributes: SplitIO.Attributes | undefined) {
109
- return getTreatmentsByFlagSets(key, flagSetNames, attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSETS);
112
+ return getTreatmentsByFlagSets(key, flagSetNames, attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSETS, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS);
110
113
  }
111
114
 
112
115
  function getTreatmentsByFlagSet(key: SplitIO.SplitKey, flagSetName: string, attributes: SplitIO.Attributes | undefined) {
113
- return getTreatmentsByFlagSets(key, [flagSetName], attributes, false, TREATMENTS_BY_FLAGSET);
116
+ return getTreatmentsByFlagSets(key, [flagSetName], attributes, false, TREATMENTS_BY_FLAGSET, GET_TREATMENTS_BY_FLAG_SET);
114
117
  }
115
118
 
116
119
  function getTreatmentsWithConfigByFlagSet(key: SplitIO.SplitKey, flagSetName: string, attributes: SplitIO.Attributes | undefined) {
117
- return getTreatmentsByFlagSets(key, [flagSetName], attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSET);
120
+ return getTreatmentsByFlagSets(key, [flagSetName], attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET);
118
121
  }
119
122
 
120
123
  // Internal function
@@ -171,7 +174,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
171
174
  };
172
175
 
173
176
  // 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.
174
- validateTrafficTypeExistence(log, readinessManager, storage.splits, mode, trafficTypeName, 'track');
177
+ validateTrafficTypeExistence(log, readinessManager, storage.splits, mode, trafficTypeName, TRACK_FN_LABEL);
175
178
 
176
179
  const result = eventTracker.track(eventData, size);
177
180