@splitsoftware/splitio-commons 1.10.0 → 1.10.1-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.
Files changed (131) hide show
  1. package/CHANGES.txt +9 -0
  2. package/cjs/evaluator/index.js +18 -1
  3. package/cjs/logger/constants.js +7 -3
  4. package/cjs/logger/messages/error.js +2 -0
  5. package/cjs/logger/messages/warn.js +4 -2
  6. package/cjs/sdkClient/client.js +33 -0
  7. package/cjs/sdkClient/clientAttributesDecoration.js +20 -0
  8. package/cjs/sdkClient/clientCS.js +4 -0
  9. package/cjs/sdkClient/clientInputValidation.js +52 -3
  10. package/cjs/sdkManager/index.js +1 -0
  11. package/cjs/services/splitApi.js +7 -1
  12. package/cjs/storages/KeyBuilder.js +3 -0
  13. package/cjs/storages/KeyBuilderSS.js +4 -0
  14. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +63 -27
  15. package/cjs/storages/inLocalStorage/index.js +2 -2
  16. package/cjs/storages/inMemory/InMemoryStorage.js +2 -2
  17. package/cjs/storages/inMemory/InMemoryStorageCS.js +3 -3
  18. package/cjs/storages/inMemory/SplitsCacheInMemory.js +47 -2
  19. package/cjs/storages/inRedis/SplitsCacheInRedis.js +11 -0
  20. package/cjs/storages/pluggable/SplitsCachePluggable.js +11 -0
  21. package/cjs/sync/polling/syncTasks/splitsSyncTask.js +1 -1
  22. package/cjs/sync/polling/updaters/splitChangesUpdater.js +39 -5
  23. package/cjs/sync/submitters/telemetrySubmitter.js +15 -1
  24. package/cjs/utils/constants/index.js +6 -2
  25. package/cjs/utils/lang/sets.js +9 -1
  26. package/cjs/utils/settingsValidation/index.js +1 -1
  27. package/cjs/utils/settingsValidation/splitFilters.js +78 -15
  28. package/esm/evaluator/index.js +16 -0
  29. package/esm/logger/constants.js +5 -1
  30. package/esm/logger/messages/error.js +2 -0
  31. package/esm/logger/messages/warn.js +4 -2
  32. package/esm/sdkClient/client.js +35 -2
  33. package/esm/sdkClient/clientAttributesDecoration.js +20 -0
  34. package/esm/sdkClient/clientCS.js +4 -0
  35. package/esm/sdkClient/clientInputValidation.js +52 -3
  36. package/esm/sdkManager/index.js +1 -0
  37. package/esm/services/splitApi.js +7 -1
  38. package/esm/storages/KeyBuilder.js +3 -0
  39. package/esm/storages/KeyBuilderSS.js +4 -0
  40. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +63 -27
  41. package/esm/storages/inLocalStorage/index.js +2 -2
  42. package/esm/storages/inMemory/InMemoryStorage.js +2 -2
  43. package/esm/storages/inMemory/InMemoryStorageCS.js +3 -3
  44. package/esm/storages/inMemory/SplitsCacheInMemory.js +47 -2
  45. package/esm/storages/inRedis/SplitsCacheInRedis.js +11 -0
  46. package/esm/storages/pluggable/SplitsCachePluggable.js +11 -0
  47. package/esm/sync/polling/syncTasks/splitsSyncTask.js +1 -1
  48. package/esm/sync/polling/updaters/splitChangesUpdater.js +39 -5
  49. package/esm/sync/submitters/telemetrySubmitter.js +15 -1
  50. package/esm/utils/constants/index.js +4 -0
  51. package/esm/utils/lang/sets.js +7 -0
  52. package/esm/utils/settingsValidation/index.js +1 -1
  53. package/esm/utils/settingsValidation/splitFilters.js +72 -10
  54. package/package.json +2 -2
  55. package/src/dtos/types.ts +3 -2
  56. package/src/evaluator/index.ts +24 -0
  57. package/src/logger/constants.ts +5 -1
  58. package/src/logger/messages/error.ts +2 -0
  59. package/src/logger/messages/warn.ts +4 -2
  60. package/src/sdkClient/client.ts +42 -2
  61. package/src/sdkClient/clientAttributesDecoration.ts +24 -0
  62. package/src/sdkClient/clientCS.ts +4 -0
  63. package/src/sdkClient/clientInputValidation.ts +56 -3
  64. package/src/sdkManager/index.ts +1 -0
  65. package/src/services/splitApi.ts +6 -1
  66. package/src/storages/AbstractSplitsCacheAsync.ts +2 -0
  67. package/src/storages/AbstractSplitsCacheSync.ts +3 -0
  68. package/src/storages/KeyBuilder.ts +4 -0
  69. package/src/storages/KeyBuilderSS.ts +4 -0
  70. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +74 -28
  71. package/src/storages/inLocalStorage/index.ts +2 -2
  72. package/src/storages/inMemory/InMemoryStorage.ts +2 -2
  73. package/src/storages/inMemory/InMemoryStorageCS.ts +3 -3
  74. package/src/storages/inMemory/SplitsCacheInMemory.ts +50 -1
  75. package/src/storages/inRedis/SplitsCacheInRedis.ts +12 -0
  76. package/src/storages/pluggable/SplitsCachePluggable.ts +12 -0
  77. package/src/storages/types.ts +7 -3
  78. package/src/sync/polling/syncTasks/splitsSyncTask.ts +1 -0
  79. package/src/sync/polling/updaters/splitChangesUpdater.ts +40 -6
  80. package/src/sync/submitters/telemetrySubmitter.ts +19 -2
  81. package/src/sync/submitters/types.ts +7 -1
  82. package/src/types.ts +115 -2
  83. package/src/utils/constants/index.ts +4 -0
  84. package/src/utils/lang/sets.ts +8 -0
  85. package/src/utils/settingsValidation/index.ts +1 -1
  86. package/src/utils/settingsValidation/splitFilters.ts +78 -10
  87. package/types/dtos/types.d.ts +1 -0
  88. package/types/evaluator/index.d.ts +1 -0
  89. package/types/logger/constants.d.ts +5 -1
  90. package/types/myLogger.d.ts +5 -0
  91. package/types/sdkClient/clientAttributesDecoration.d.ts +4 -0
  92. package/types/sdkClient/types.d.ts +18 -0
  93. package/types/storages/AbstractSplitsCacheAsync.d.ts +2 -0
  94. package/types/storages/AbstractSplitsCacheSync.d.ts +2 -0
  95. package/types/storages/KeyBuilder.d.ts +1 -0
  96. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +6 -1
  97. package/types/storages/inMemory/CountsCacheInMemory.d.ts +20 -0
  98. package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +20 -0
  99. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +9 -1
  100. package/types/storages/inRedis/CountsCacheInRedis.d.ts +9 -0
  101. package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +9 -0
  102. package/types/storages/inRedis/SplitsCacheInRedis.d.ts +8 -0
  103. package/types/storages/metadataBuilder.d.ts +3 -0
  104. package/types/storages/pluggable/SplitsCachePluggable.d.ts +8 -0
  105. package/types/storages/types.d.ts +4 -0
  106. package/types/sync/offline/LocalhostFromFile.d.ts +2 -0
  107. package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +2 -0
  108. package/types/sync/offline/updaters/splitChangesUpdater.d.ts +0 -0
  109. package/types/sync/polling/updaters/splitChangesUpdater.d.ts +3 -3
  110. package/types/sync/submitters/eventsSyncTask.d.ts +8 -0
  111. package/types/sync/submitters/impressionCountsSubmitterInRedis.d.ts +5 -0
  112. package/types/sync/submitters/impressionCountsSyncTask.d.ts +13 -0
  113. package/types/sync/submitters/impressionsSyncTask.d.ts +14 -0
  114. package/types/sync/submitters/metricsSyncTask.d.ts +12 -0
  115. package/types/sync/submitters/submitterSyncTask.d.ts +10 -0
  116. package/types/sync/submitters/types.d.ts +7 -1
  117. package/types/sync/submitters/uniqueKeysSubmitterInRedis.d.ts +5 -0
  118. package/types/sync/syncTaskComposite.d.ts +5 -0
  119. package/types/trackers/filter/bloomFilter.d.ts +10 -0
  120. package/types/trackers/filter/dictionaryFilter.d.ts +8 -0
  121. package/types/trackers/filter/types.d.ts +5 -0
  122. package/types/types.d.ts +114 -1
  123. package/types/utils/constants/index.d.ts +4 -0
  124. package/types/utils/lang/sets.d.ts +1 -0
  125. package/types/utils/settingsValidation/splitFilters.d.ts +2 -2
  126. package/types/utils/timeTracker/index.d.ts +70 -0
  127. package/types/sdkClient/identity.d.ts +0 -6
  128. package/types/utils/inputValidation/sdkKey.d.ts +0 -7
  129. /package/types/storages/inMemory/{UniqueKeysCacheInMemory.d.ts → uniqueKeysCacheInMemory.d.ts} +0 -0
  130. /package/types/storages/inMemory/{UniqueKeysCacheInMemoryCS.d.ts → uniqueKeysCacheInMemoryCS.d.ts} +0 -0
  131. /package/types/storages/inRedis/{UniqueKeysCacheInRedis.d.ts → uniqueKeysCacheInRedis.d.ts} +0 -0
package/CHANGES.txt CHANGED
@@ -1,3 +1,12 @@
1
+ 1.11.0 (November XX, 2023)
2
+ - Added support for Flag Sets on the SDK, which enables grouping feature flags and interacting with the group rather than individually (more details in our documentation):
3
+ - Added new variations of the get treatment methods to support evaluating flags in given flag set/s.
4
+ - getTreatmentsByFlagSet and getTreatmentsByFlagSets
5
+ - getTreatmentsWithConfigByFlagSets and getTreatmentsWithConfigByFlagSets
6
+ - Added a new optional Split Filter configuration option. This allows the SDK and Split services to only synchronize the flags in the specified flag sets, avoiding unused or unwanted flags from being synced on the SDK instance, bringing all the benefits from a reduced payload.
7
+ - Note: Only applicable when the SDK is in charge of the rollout data synchronization. When not applicable, the SDK will log a warning on init.
8
+ - Added `sets` property to the `SplitView` object returned by the `split` and `splits` methods of the SDK manager to expose flag sets on flag views.
9
+
1
10
  1.10.0 (October 20, 2023)
2
11
  - Added `defaultTreatment` property to the `SplitView` object returned by the `split` and `splits` methods of the SDK manager (Related to issue https://github.com/splitio/javascript-commons/issues/225).
3
12
  - Updated log warning message to include the feature flag name when `getTreatment` method is called and the SDK client is not ready.
@@ -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,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.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.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_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_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_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_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 = 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.
@@ -94,12 +94,14 @@ exports.WARN_NOT_EXISTENT_SPLIT = 215;
94
94
  exports.WARN_LOWERCASE_TRAFFIC_TYPE = 216;
95
95
  exports.WARN_NOT_EXISTENT_TT = 217;
96
96
  exports.WARN_INTEGRATION_INVALID = 218;
97
- exports.WARN_SPLITS_FILTER_IGNORED = 219;
98
97
  exports.WARN_SPLITS_FILTER_INVALID = 220;
99
98
  exports.WARN_SPLITS_FILTER_EMPTY = 221;
100
99
  exports.WARN_SDK_KEY = 222;
101
100
  exports.STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 = 223;
102
101
  exports.STREAMING_PARSING_SPLIT_UPDATE = 224;
102
+ exports.WARN_SPLITS_FILTER_INVALID_SET = 225;
103
+ exports.WARN_SPLITS_FILTER_LOWERCASE_SET = 226;
104
+ exports.WARN_FLAGSET_NOT_CONFIGURED = 227;
103
105
  exports.ERROR_ENGINE_COMBINER_IFELSEIF = 300;
104
106
  exports.ERROR_LOGLEVEL_INVALID = 301;
105
107
  exports.ERROR_CLIENT_LISTENER = 302;
@@ -127,6 +129,8 @@ exports.ERROR_LOCALHOST_MODULE_REQUIRED = 323;
127
129
  exports.ERROR_STORAGE_INVALID = 324;
128
130
  exports.ERROR_NOT_BOOLEAN = 325;
129
131
  exports.ERROR_MIN_CONFIG_PARAM = 326;
132
+ exports.ERROR_TOO_MANY_SETS = 327;
133
+ exports.ERROR_SETS_FILTER_EXCLUSIVE = 328;
130
134
  // Log prefixes (a.k.a. tags or categories)
131
135
  exports.LOG_PREFIX_SETTINGS = 'settings';
132
136
  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
  ];
@@ -27,12 +27,14 @@ exports.codesWarn = error_1.codesError.concat([
27
27
  [c.WARN_NOT_EXISTENT_SPLIT, '%s: feature flag "%s" does not exist in this environment. Please double check what feature flags exist in the Split user interface.'],
28
28
  [c.WARN_LOWERCASE_TRAFFIC_TYPE, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'],
29
29
  [c.WARN_NOT_EXISTENT_TT, '%s: traffic type "%s" does not have any corresponding feature flag in this environment, make sure you\'re tracking your events to a valid traffic type defined in the Split user interface.'],
30
+ [c.WARN_FLAGSET_NOT_CONFIGURED, '%s: : you passed %s wich is not part of the configured FlagSetsFilter, ignoring Flag Set.'],
30
31
  // initialization / settings validation
31
32
  [c.WARN_INTEGRATION_INVALID, c.LOG_PREFIX_SETTINGS + ': %s integration item(s) at settings is invalid. %s'],
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
  ]);
@@ -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,6 +18,10 @@ 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
27
  // Not part of the public API. These properties are used to support other modules (e.g., Split Suite)
@@ -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 = multi ? (0, inputValidation_1.validateSplits)(log, maybeFeatureFlagNameOrNames, methodName) : (0, inputValidation_1.validateSplit)(log, maybeFeatureFlagNameOrNames, methodName);
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, splitOrSplits);
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
  }
@@ -28,6 +28,7 @@ function objectToView(splitObject) {
28
28
  changeNumber: splitObject.changeNumber || 0,
29
29
  treatments: collectTreatments(splitObject),
30
30
  configs: splitObject.configurations || {},
31
+ sets: splitObject.sets || [],
31
32
  defaultTreatment: splitObject.defaultTreatment
32
33
  };
33
34
  }
@@ -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 || this.cacheReadyButNeedsToFlush;
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 _this = this;
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 cache is ready:
223
- if (this.checkCache()) {
224
- // * set change number to -1, to fetch splits with -1 `since` value.
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;
@@ -46,7 +46,7 @@ function InLocalStorage(options) {
46
46
  uniqueKeys: impressionsMode === constants_2.NONE ? new UniqueKeysCacheInMemoryCS_1.UniqueKeysCacheInMemoryCS() : undefined,
47
47
  destroy: function () {
48
48
  var _a;
49
- this.splits = new SplitsCacheInMemory_1.SplitsCacheInMemory();
49
+ this.splits = new SplitsCacheInMemory_1.SplitsCacheInMemory(__splitFiltersValidation);
50
50
  this.segments = new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory();
51
51
  this.impressions.clear();
52
52
  this.impressionCounts && this.impressionCounts.clear();
@@ -64,7 +64,7 @@ function InLocalStorage(options) {
64
64
  events: this.events,
65
65
  telemetry: this.telemetry,
66
66
  destroy: function () {
67
- this.splits = new SplitsCacheInMemory_1.SplitsCacheInMemory();
67
+ this.splits = new SplitsCacheInMemory_1.SplitsCacheInMemory(__splitFiltersValidation);
68
68
  this.segments = new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory();
69
69
  }
70
70
  };
@@ -15,8 +15,8 @@ var UniqueKeysCacheInMemory_1 = require("./UniqueKeysCacheInMemory");
15
15
  * @param params parameters required by EventsCacheSync
16
16
  */
17
17
  function InMemoryStorageFactory(params) {
18
- var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, impressionsMode = _a.sync.impressionsMode;
19
- var splits = new SplitsCacheInMemory_1.SplitsCacheInMemory();
18
+ var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, _c = _a.sync, impressionsMode = _c.impressionsMode, __splitFiltersValidation = _c.__splitFiltersValidation;
19
+ var splits = new SplitsCacheInMemory_1.SplitsCacheInMemory(__splitFiltersValidation);
20
20
  var segments = new SegmentsCacheInMemory_1.SegmentsCacheInMemory();
21
21
  var storage = {
22
22
  splits: splits,
@@ -15,8 +15,8 @@ var UniqueKeysCacheInMemoryCS_1 = require("./UniqueKeysCacheInMemoryCS");
15
15
  * @param params parameters required by EventsCacheSync
16
16
  */
17
17
  function InMemoryStorageCSFactory(params) {
18
- var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, impressionsMode = _a.sync.impressionsMode;
19
- var splits = new SplitsCacheInMemory_1.SplitsCacheInMemory();
18
+ var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, _c = _a.sync, impressionsMode = _c.impressionsMode, __splitFiltersValidation = _c.__splitFiltersValidation;
19
+ var splits = new SplitsCacheInMemory_1.SplitsCacheInMemory(__splitFiltersValidation);
20
20
  var segments = new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory();
21
21
  var storage = {
22
22
  splits: splits,
@@ -46,7 +46,7 @@ function InMemoryStorageCSFactory(params) {
46
46
  telemetry: this.telemetry,
47
47
  // Set a new splits cache to clean it for the client without affecting other clients
48
48
  destroy: function () {
49
- this.splits = new SplitsCacheInMemory_1.SplitsCacheInMemory();
49
+ this.splits = new SplitsCacheInMemory_1.SplitsCacheInMemory(__splitFiltersValidation);
50
50
  this.segments.clear();
51
51
  }
52
52
  };