@splitsoftware/splitio-commons 1.11.0 → 1.12.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 (81) hide show
  1. package/CHANGES.txt +4 -0
  2. package/cjs/evaluator/index.js +19 -3
  3. package/cjs/logger/constants.js +4 -2
  4. package/cjs/logger/messages/warn.js +3 -1
  5. package/cjs/sdkClient/client.js +1 -1
  6. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +2 -7
  7. package/cjs/storages/inMemory/SplitsCacheInMemory.js +2 -10
  8. package/cjs/storages/inRedis/SplitsCacheInRedis.js +29 -12
  9. package/cjs/storages/pluggable/SplitsCachePluggable.js +25 -8
  10. package/cjs/storages/pluggable/index.js +1 -1
  11. package/cjs/utils/lang/sets.js +11 -1
  12. package/cjs/utils/settingsValidation/index.js +1 -1
  13. package/cjs/utils/settingsValidation/splitFilters.js +17 -10
  14. package/esm/evaluator/index.js +20 -4
  15. package/esm/logger/constants.js +2 -0
  16. package/esm/logger/messages/warn.js +3 -1
  17. package/esm/sdkClient/client.js +1 -1
  18. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +3 -8
  19. package/esm/storages/inMemory/SplitsCacheInMemory.js +3 -11
  20. package/esm/storages/inRedis/SplitsCacheInRedis.js +30 -13
  21. package/esm/storages/pluggable/SplitsCachePluggable.js +26 -9
  22. package/esm/storages/pluggable/index.js +1 -1
  23. package/esm/utils/lang/sets.js +9 -0
  24. package/esm/utils/settingsValidation/index.js +1 -1
  25. package/esm/utils/settingsValidation/splitFilters.js +9 -2
  26. package/package.json +1 -1
  27. package/src/evaluator/index.ts +24 -4
  28. package/src/logger/constants.ts +2 -0
  29. package/src/logger/messages/warn.ts +9 -7
  30. package/src/sdkClient/client.ts +1 -1
  31. package/src/storages/AbstractSplitsCacheAsync.ts +1 -1
  32. package/src/storages/AbstractSplitsCacheSync.ts +1 -1
  33. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +4 -10
  34. package/src/storages/inMemory/SplitsCacheInMemory.ts +6 -14
  35. package/src/storages/inRedis/SplitsCacheInRedis.ts +37 -15
  36. package/src/storages/pluggable/SplitsCachePluggable.ts +32 -10
  37. package/src/storages/pluggable/index.ts +1 -1
  38. package/src/storages/types.ts +5 -5
  39. package/src/types.ts +0 -2
  40. package/src/utils/lang/sets.ts +9 -1
  41. package/src/utils/settingsValidation/index.ts +1 -1
  42. package/src/utils/settingsValidation/splitFilters.ts +13 -6
  43. package/types/evaluator/index.d.ts +1 -1
  44. package/types/logger/constants.d.ts +2 -0
  45. package/types/sdkClient/identity.d.ts +6 -0
  46. package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
  47. package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
  48. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +1 -1
  49. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +1 -1
  50. package/types/storages/inRedis/SplitsCacheInRedis.d.ts +6 -5
  51. package/types/storages/pluggable/SplitsCachePluggable.d.ts +7 -6
  52. package/types/storages/types.d.ts +5 -5
  53. package/types/types.d.ts +0 -2
  54. package/types/utils/inputValidation/sdkKey.d.ts +7 -0
  55. package/types/utils/lang/sets.d.ts +1 -0
  56. package/types/utils/settingsValidation/splitFilters.d.ts +2 -1
  57. package/types/myLogger.d.ts +0 -5
  58. package/types/sdkClient/types.d.ts +0 -18
  59. package/types/storages/inMemory/CountsCacheInMemory.d.ts +0 -20
  60. package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +0 -20
  61. package/types/storages/inRedis/CountsCacheInRedis.d.ts +0 -9
  62. package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +0 -9
  63. package/types/storages/metadataBuilder.d.ts +0 -3
  64. package/types/sync/offline/LocalhostFromFile.d.ts +0 -2
  65. package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +0 -2
  66. package/types/sync/offline/updaters/splitChangesUpdater.d.ts +0 -0
  67. package/types/sync/submitters/eventsSyncTask.d.ts +0 -8
  68. package/types/sync/submitters/impressionCountsSubmitterInRedis.d.ts +0 -5
  69. package/types/sync/submitters/impressionCountsSyncTask.d.ts +0 -13
  70. package/types/sync/submitters/impressionsSyncTask.d.ts +0 -14
  71. package/types/sync/submitters/metricsSyncTask.d.ts +0 -12
  72. package/types/sync/submitters/submitterSyncTask.d.ts +0 -10
  73. package/types/sync/submitters/uniqueKeysSubmitterInRedis.d.ts +0 -5
  74. package/types/sync/syncTaskComposite.d.ts +0 -5
  75. package/types/trackers/filter/bloomFilter.d.ts +0 -10
  76. package/types/trackers/filter/dictionaryFilter.d.ts +0 -8
  77. package/types/trackers/filter/types.d.ts +0 -5
  78. package/types/utils/timeTracker/index.d.ts +0 -70
  79. /package/types/storages/inMemory/{uniqueKeysCacheInMemory.d.ts → UniqueKeysCacheInMemory.d.ts} +0 -0
  80. /package/types/storages/inMemory/{uniqueKeysCacheInMemoryCS.d.ts → UniqueKeysCacheInMemoryCS.d.ts} +0 -0
  81. /package/types/storages/inRedis/{uniqueKeysCacheInRedis.d.ts → UniqueKeysCacheInRedis.d.ts} +0 -0
@@ -2,10 +2,10 @@ import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
2
2
  import { KeyBuilder } from '../KeyBuilder';
3
3
  import { IPluggableStorageWrapper } from '../types';
4
4
  import { ILogger } from '../../logger/types';
5
- import { ISplit } from '../../dtos/types';
5
+ import { ISplit, ISplitFiltersValidation } from '../../dtos/types';
6
6
  import { LOG_PREFIX } from './constants';
7
7
  import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
8
- import { ISet } from '../../utils/lang/sets';
8
+ import { ISet, _Set, returnListDifference } from '../../utils/lang/sets';
9
9
 
10
10
  /**
11
11
  * ISplitsCacheAsync implementation for pluggable storages.
@@ -15,6 +15,7 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
15
15
  private readonly log: ILogger;
16
16
  private readonly keys: KeyBuilder;
17
17
  private readonly wrapper: IPluggableStorageWrapper;
18
+ private readonly flagSetsFilter: string[];
18
19
 
19
20
  /**
20
21
  * Create a SplitsCache that uses a storage wrapper.
@@ -22,11 +23,12 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
22
23
  * @param keys Key builder.
23
24
  * @param wrapper Adapted wrapper storage.
24
25
  */
25
- constructor(log: ILogger, keys: KeyBuilder, wrapper: IPluggableStorageWrapper) {
26
+ constructor(log: ILogger, keys: KeyBuilder, wrapper: IPluggableStorageWrapper, splitFiltersValidation?: ISplitFiltersValidation) {
26
27
  super();
27
28
  this.log = log;
28
29
  this.keys = keys;
29
30
  this.wrapper = wrapper;
31
+ this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
30
32
  }
31
33
 
32
34
  private _decrementCounts(split: ISplit) {
@@ -41,6 +43,24 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
41
43
  return this.wrapper.incr(ttKey);
42
44
  }
43
45
 
46
+ private _updateFlagSets(featureFlagName: string, flagSetsOfRemovedFlag?: string[], flagSetsOfAddedFlag?: string[]) {
47
+ const removeFromFlagSets = returnListDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag);
48
+
49
+ let addToFlagSets = returnListDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag);
50
+ if (this.flagSetsFilter.length > 0) {
51
+ addToFlagSets = addToFlagSets.filter(flagSet => {
52
+ return this.flagSetsFilter.some(filterFlagSet => filterFlagSet === flagSet);
53
+ });
54
+ }
55
+
56
+ const items = [featureFlagName];
57
+
58
+ return Promise.all([
59
+ ...removeFromFlagSets.map(flagSetName => this.wrapper.removeItems(this.keys.buildFlagSetKey(flagSetName), items)),
60
+ ...addToFlagSets.map(flagSetName => this.wrapper.addItems(this.keys.buildFlagSetKey(flagSetName), items))
61
+ ]);
62
+ }
63
+
44
64
  /**
45
65
  * Add a given split.
46
66
  * The returned promise is resolved when the operation success
@@ -67,7 +87,7 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
67
87
  return this._incrementCounts(split).then(() => {
68
88
  if (parsedPreviousSplit) return this._decrementCounts(parsedPreviousSplit);
69
89
  });
70
- });
90
+ }).then(() => this._updateFlagSets(name, parsedPreviousSplit && parsedPreviousSplit.sets, split.sets));
71
91
  }).then(() => true);
72
92
  }
73
93
 
@@ -88,8 +108,9 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
88
108
  removeSplit(name: string) {
89
109
  return this.getSplit(name).then((split) => {
90
110
  if (split) {
91
- this._decrementCounts(split);
111
+ return this._decrementCounts(split).then(() => this._updateFlagSets(name, split.sets));
92
112
  }
113
+ }).then(() => {
93
114
  return this.wrapper.del(this.keys.buildSplitKey(name));
94
115
  });
95
116
  }
@@ -158,12 +179,13 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
158
179
  /**
159
180
  * Get list of split names related to a given flag set names list.
160
181
  * The returned promise is resolved with the list of split names,
161
- * or rejected if wrapper operation fails.
162
- * @todo this is a no-op method to be implemented
182
+ * or rejected if any wrapper operation fails.
163
183
  */
164
- getNamesByFlagSets(): Promise<ISet<string>> {
165
- this.log.error(LOG_PREFIX + 'ByFlagSet/s evaluations are not supported with pluggable storage yet.');
166
- return Promise.reject();
184
+ getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>[]> {
185
+ return Promise.all(flagSets.map(flagSet => {
186
+ const flagSetKey = this.keys.buildFlagSetKey(flagSet);
187
+ return this.wrapper.getItems(flagSetKey);
188
+ })).then(namesByFlagSets => namesByFlagSets.map(namesByFlagSet => new _Set(namesByFlagSet)));
167
189
  }
168
190
 
169
191
  /**
@@ -105,7 +105,7 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
105
105
  });
106
106
 
107
107
  return {
108
- splits: new SplitsCachePluggable(log, keys, wrapper),
108
+ splits: new SplitsCachePluggable(log, keys, wrapper, settings.sync.__splitFiltersValidation),
109
109
  segments: new SegmentsCachePluggable(log, keys, wrapper),
110
110
  impressions: isPartialConsumer ? new ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
111
111
  impressionCounts: impressionCountsCache,
@@ -44,10 +44,10 @@ export interface IPluggableStorageWrapper {
44
44
  *
45
45
  * @function del
46
46
  * @param {string} key Item to delete
47
- * @returns {Promise<void>} A promise that resolves if the operation success, whether the key existed and was removed or it didn't exist.
47
+ * @returns {Promise<boolean>} A promise that resolves if the operation success, whether the key existed and was removed (resolves with true) or it didn't exist (resolves with false).
48
48
  * The promise rejects if the operation fails, for example, if there is a connection error.
49
49
  */
50
- del: (key: string) => Promise<boolean | void>
50
+ del: (key: string) => Promise<boolean>
51
51
  /**
52
52
  * Returns all keys matching the given prefix.
53
53
  *
@@ -210,7 +210,7 @@ export interface ISplitsCacheBase {
210
210
  // should never reject or throw an exception. Instead return false by default, to avoid emitting SDK_READY_FROM_CACHE.
211
211
  checkCache(): MaybeThenable<boolean>,
212
212
  killLocally(name: string, defaultTreatment: string, changeNumber: number): MaybeThenable<boolean>,
213
- getNamesByFlagSets(flagSets: string[]): MaybeThenable<ISet<string>>
213
+ getNamesByFlagSets(flagSets: string[]): MaybeThenable<ISet<string>[]>
214
214
  }
215
215
 
216
216
  export interface ISplitsCacheSync extends ISplitsCacheBase {
@@ -227,7 +227,7 @@ export interface ISplitsCacheSync extends ISplitsCacheBase {
227
227
  clear(): void,
228
228
  checkCache(): boolean,
229
229
  killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean,
230
- getNamesByFlagSets(flagSets: string[]): ISet<string>
230
+ getNamesByFlagSets(flagSets: string[]): ISet<string>[]
231
231
  }
232
232
 
233
233
  export interface ISplitsCacheAsync extends ISplitsCacheBase {
@@ -244,7 +244,7 @@ export interface ISplitsCacheAsync extends ISplitsCacheBase {
244
244
  clear(): Promise<boolean | void>,
245
245
  checkCache(): Promise<boolean>,
246
246
  killLocally(name: string, defaultTreatment: string, changeNumber: number): Promise<boolean>,
247
- getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>>
247
+ getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>[]>
248
248
  }
249
249
 
250
250
  /** Segments cache */
package/src/types.ts CHANGED
@@ -197,8 +197,6 @@ interface ISharedSettings {
197
197
  * List of feature flag filters. These filters are used to fetch a subset of the feature flag definitions in your environment, in order to reduce the delay of the SDK to be ready.
198
198
  * This configuration is only meaningful when the SDK is working in "standalone" mode.
199
199
  *
200
- * At the moment, only one type of feature flag filter is supported: by name.
201
- *
202
200
  * Example:
203
201
  * `splitFilter: [
204
202
  * { type: 'byName', values: ['my_feature_flag_1', 'my_feature_flag_2'] }, // will fetch feature flags named 'my_feature_flag_1' and 'my_feature_flag_2'
@@ -114,8 +114,16 @@ export const _Set = __getSetConstructor();
114
114
 
115
115
  export function returnSetsUnion<T>(set: ISet<T>, set2: ISet<T>): ISet<T> {
116
116
  const result = new _Set(setToArray(set));
117
- set2.forEach( value => {
117
+ set2.forEach(value => {
118
118
  result.add(value);
119
119
  });
120
120
  return result;
121
121
  }
122
+
123
+ export function returnListDifference<T>(list: T[] = [], list2: T[] = []): T[] {
124
+ const result = new _Set(list);
125
+ list2.forEach(item => {
126
+ result.delete(item);
127
+ });
128
+ return setToArray(result);
129
+ }
@@ -202,7 +202,7 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
202
202
  }
203
203
 
204
204
  // validate the `splitFilters` settings and parse splits query
205
- const splitFiltersValidation = validateSplitFilters(log, withDefaults.sync.splitFilters);
205
+ const splitFiltersValidation = validateSplitFilters(log, withDefaults.sync.splitFilters, withDefaults.mode);
206
206
  withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
207
207
  withDefaults.sync.__splitFiltersValidation = splitFiltersValidation;
208
208
 
@@ -1,8 +1,9 @@
1
+ import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE } from '../constants';
1
2
  import { validateSplits } from '../inputValidation/splits';
2
3
  import { ISplitFiltersValidation } from '../../dtos/types';
3
4
  import { SplitIO } from '../../types';
4
5
  import { ILogger } from '../../logger/types';
5
- import { 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';
6
+ 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';
6
7
  import { objectAssign } from '../lang/objectAssign';
7
8
  import { find, uniq } from '../lang';
8
9
 
@@ -102,15 +103,15 @@ function queryStringBuilder(groupedFilters: Record<SplitIO.SplitFilterType, stri
102
103
  function sanitizeFlagSets(log: ILogger, flagSets: string[]) {
103
104
  let sanitizedSets = flagSets
104
105
  .map(flagSet => {
105
- if (CAPITAL_LETTERS_REGEX.test(flagSet)){
106
- log.warn(WARN_SPLITS_FILTER_LOWERCASE_SET,[flagSet]);
106
+ if (CAPITAL_LETTERS_REGEX.test(flagSet)) {
107
+ log.warn(WARN_SPLITS_FILTER_LOWERCASE_SET, [flagSet]);
107
108
  flagSet = flagSet.toLowerCase();
108
109
  }
109
110
  return flagSet;
110
111
  })
111
112
  .filter(flagSet => {
112
- if (!VALID_FLAGSET_REGEX.test(flagSet)){
113
- log.warn(WARN_SPLITS_FILTER_INVALID_SET, [flagSet,VALID_FLAGSET_REGEX,flagSet]);
113
+ if (!VALID_FLAGSET_REGEX.test(flagSet)) {
114
+ log.warn(WARN_SPLITS_FILTER_INVALID_SET, [flagSet, VALID_FLAGSET_REGEX, flagSet]);
114
115
  return false;
115
116
  }
116
117
  if (typeof flagSet !== 'string') return false;
@@ -128,6 +129,7 @@ function configuredFilter(validFilters: SplitIO.SplitFilter[], filterType: Split
128
129
  *
129
130
  * @param {ILogger} log logger
130
131
  * @param {any} maybeSplitFilters split filters configuration param provided by the user
132
+ * @param {string} mode settings mode
131
133
  * @returns it returns an object with the following properties:
132
134
  * - `validFilters`: the validated `splitFilters` configuration object defined by the user.
133
135
  * - `queryString`: the parsed split filter query. it is null if all filters are invalid or all values in filters are invalid.
@@ -135,7 +137,7 @@ function configuredFilter(validFilters: SplitIO.SplitFilter[], filterType: Split
135
137
  *
136
138
  * @throws Error if the some of the grouped list of values per filter exceeds the max allowed length
137
139
  */
138
- export function validateSplitFilters(log: ILogger, maybeSplitFilters: any): ISplitFiltersValidation {
140
+ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: string): ISplitFiltersValidation {
139
141
  // Validation result schema
140
142
  const res = {
141
143
  validFilters: [],
@@ -145,6 +147,11 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any): ISpl
145
147
 
146
148
  // do nothing if `splitFilters` param is not a non-empty array or mode is not STANDALONE
147
149
  if (!maybeSplitFilters) return res;
150
+ // Warn depending on the mode
151
+ if (mode === CONSUMER_MODE || mode === CONSUMER_PARTIAL_MODE) {
152
+ log.warn(WARN_SPLITS_FILTER_IGNORED);
153
+ return res;
154
+ }
148
155
  // Check collection type
149
156
  if (!Array.isArray(maybeSplitFilters) || maybeSplitFilters.length === 0) {
150
157
  log.warn(WARN_SPLITS_FILTER_EMPTY);
@@ -5,4 +5,4 @@ import { SplitIO } from '../types';
5
5
  import { ILogger } from '../logger/types';
6
6
  export declare function evaluateFeature(log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync): MaybeThenable<IEvaluationResult>;
7
7
  export declare function evaluateFeatures(log: ILogger, key: SplitIO.SplitKey, splitNames: string[], attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync): MaybeThenable<Record<string, IEvaluationResult>>;
8
- export declare function evaluateFeaturesByFlagSets(log: ILogger, key: SplitIO.SplitKey, flagSets: string[], attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync): MaybeThenable<Record<string, IEvaluationResult>>;
8
+ export declare function evaluateFeaturesByFlagSets(log: ILogger, key: SplitIO.SplitKey, flagSets: string[], attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync, method: string): MaybeThenable<Record<string, IEvaluationResult>>;
@@ -89,6 +89,7 @@ export declare const WARN_NOT_EXISTENT_SPLIT = 215;
89
89
  export declare const WARN_LOWERCASE_TRAFFIC_TYPE = 216;
90
90
  export declare const WARN_NOT_EXISTENT_TT = 217;
91
91
  export declare const WARN_INTEGRATION_INVALID = 218;
92
+ export declare const WARN_SPLITS_FILTER_IGNORED = 219;
92
93
  export declare const WARN_SPLITS_FILTER_INVALID = 220;
93
94
  export declare const WARN_SPLITS_FILTER_EMPTY = 221;
94
95
  export declare const WARN_SDK_KEY = 222;
@@ -97,6 +98,7 @@ export declare const STREAMING_PARSING_SPLIT_UPDATE = 224;
97
98
  export declare const WARN_SPLITS_FILTER_INVALID_SET = 225;
98
99
  export declare const WARN_SPLITS_FILTER_LOWERCASE_SET = 226;
99
100
  export declare const WARN_FLAGSET_NOT_CONFIGURED = 227;
101
+ export declare const WARN_FLAGSET_WITHOUT_FLAGS = 228;
100
102
  export declare const ERROR_ENGINE_COMBINER_IFELSEIF = 300;
101
103
  export declare const ERROR_LOGLEVEL_INVALID = 301;
102
104
  export declare const ERROR_CLIENT_LISTENER = 302;
@@ -0,0 +1,6 @@
1
+ import { SplitIO } from '../types';
2
+ export declare function buildInstanceId(key: SplitIO.SplitKey, trafficType?: string): string;
3
+ export declare function parseInstanceId(instanceId: string): {
4
+ key: SplitIO.SplitKey;
5
+ trafficType?: string;
6
+ };
@@ -15,7 +15,7 @@ export declare abstract class AbstractSplitsCacheAsync implements ISplitsCacheAs
15
15
  abstract getChangeNumber(): Promise<number>;
16
16
  abstract getAll(): Promise<ISplit[]>;
17
17
  abstract getSplitNames(): Promise<string[]>;
18
- abstract getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>>;
18
+ abstract getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>[]>;
19
19
  abstract trafficTypeExists(trafficType: string): Promise<boolean>;
20
20
  abstract clear(): Promise<boolean | void>;
21
21
  usesSegments(): Promise<boolean>;
@@ -35,7 +35,7 @@ export declare abstract class AbstractSplitsCacheSync implements ISplitsCacheSyn
35
35
  * for instance, if the `changeNumber` is old, or if the split is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
36
36
  */
37
37
  killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean;
38
- abstract getNamesByFlagSets(flagSets: string[]): ISet<string>;
38
+ abstract getNamesByFlagSets(flagSets: string[]): ISet<string>[];
39
39
  }
40
40
  /**
41
41
  * Given a parsed split, it returns a boolean flagging if its conditions use segments matchers (rules & whitelists).
@@ -48,7 +48,7 @@ export declare class SplitsCacheInLocal extends AbstractSplitsCacheSync {
48
48
  */
49
49
  private _checkExpiration;
50
50
  private _checkFilterQuery;
51
- getNamesByFlagSets(flagSets: string[]): ISet<string>;
51
+ getNamesByFlagSets(flagSets: string[]): ISet<string>[];
52
52
  private addToFlagSets;
53
53
  private removeFromFlagSets;
54
54
  private removeNames;
@@ -22,7 +22,7 @@ export declare class SplitsCacheInMemory extends AbstractSplitsCacheSync {
22
22
  getSplitNames(): string[];
23
23
  trafficTypeExists(trafficType: string): boolean;
24
24
  usesSegments(): boolean;
25
- getNamesByFlagSets(flagSets: string[]): ISet<string>;
25
+ getNamesByFlagSets(flagSets: string[]): ISet<string>[];
26
26
  private addToFlagSets;
27
27
  private removeFromFlagSets;
28
28
  private removeNames;
@@ -1,7 +1,7 @@
1
1
  import { KeyBuilderSS } from '../KeyBuilderSS';
2
2
  import { Redis } from 'ioredis';
3
3
  import { ILogger } from '../../logger/types';
4
- import { ISplit } from '../../dtos/types';
4
+ import { ISplit, ISplitFiltersValidation } from '../../dtos/types';
5
5
  import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
6
6
  import { ISet } from '../../utils/lang/sets';
7
7
  /**
@@ -13,9 +13,11 @@ export declare class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
13
13
  private readonly redis;
14
14
  private readonly keys;
15
15
  private redisError?;
16
- constructor(log: ILogger, keys: KeyBuilderSS, redis: Redis);
16
+ private readonly flagSetsFilter;
17
+ constructor(log: ILogger, keys: KeyBuilderSS, redis: Redis, splitFiltersValidation?: ISplitFiltersValidation);
17
18
  private _decrementCounts;
18
19
  private _incrementCounts;
20
+ private _updateFlagSets;
19
21
  /**
20
22
  * Add a given split.
21
23
  * The returned promise is resolved when the operation success
@@ -75,10 +77,9 @@ export declare class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
75
77
  /**
76
78
  * Get list of split names related to a given flag set names list.
77
79
  * The returned promise is resolved with the list of split names,
78
- * or rejected if wrapper operation fails.
79
- * @todo this is a no-op method to be implemented
80
+ * or rejected if any wrapper operation fails.
80
81
  */
81
- getNamesByFlagSets(): Promise<ISet<string>>;
82
+ getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>[]>;
82
83
  /**
83
84
  * Check traffic type existence.
84
85
  * The returned promise is resolved with a boolean indicating whether the TT exist or not.
@@ -1,7 +1,7 @@
1
1
  import { KeyBuilder } from '../KeyBuilder';
2
2
  import { IPluggableStorageWrapper } from '../types';
3
3
  import { ILogger } from '../../logger/types';
4
- import { ISplit } from '../../dtos/types';
4
+ import { ISplit, ISplitFiltersValidation } from '../../dtos/types';
5
5
  import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
6
6
  import { ISet } from '../../utils/lang/sets';
7
7
  /**
@@ -11,15 +11,17 @@ export declare class SplitsCachePluggable extends AbstractSplitsCacheAsync {
11
11
  private readonly log;
12
12
  private readonly keys;
13
13
  private readonly wrapper;
14
+ private readonly flagSetsFilter;
14
15
  /**
15
16
  * Create a SplitsCache that uses a storage wrapper.
16
17
  * @param log Logger instance.
17
18
  * @param keys Key builder.
18
19
  * @param wrapper Adapted wrapper storage.
19
20
  */
20
- constructor(log: ILogger, keys: KeyBuilder, wrapper: IPluggableStorageWrapper);
21
+ constructor(log: ILogger, keys: KeyBuilder, wrapper: IPluggableStorageWrapper, splitFiltersValidation?: ISplitFiltersValidation);
21
22
  private _decrementCounts;
22
23
  private _incrementCounts;
24
+ private _updateFlagSets;
23
25
  /**
24
26
  * Add a given split.
25
27
  * The returned promise is resolved when the operation success
@@ -37,7 +39,7 @@ export declare class SplitsCachePluggable extends AbstractSplitsCacheAsync {
37
39
  * The returned promise is resolved when the operation success, with a boolean indicating if the split existed or not.
38
40
  * or rejected if it fails (e.g., wrapper operation fails).
39
41
  */
40
- removeSplit(name: string): Promise<boolean | void>;
42
+ removeSplit(name: string): Promise<boolean>;
41
43
  /**
42
44
  * Remove a list of splits.
43
45
  * The returned promise is resolved when the operation success, with a boolean array indicating if the splits existed or not.
@@ -71,10 +73,9 @@ export declare class SplitsCachePluggable extends AbstractSplitsCacheAsync {
71
73
  /**
72
74
  * Get list of split names related to a given flag set names list.
73
75
  * The returned promise is resolved with the list of split names,
74
- * or rejected if wrapper operation fails.
75
- * @todo this is a no-op method to be implemented
76
+ * or rejected if any wrapper operation fails.
76
77
  */
77
- getNamesByFlagSets(): Promise<ISet<string>>;
78
+ getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>[]>;
78
79
  /**
79
80
  * Check traffic type existence.
80
81
  * The returned promise is resolved with a boolean indicating whether the TT exist or not.
@@ -41,10 +41,10 @@ export interface IPluggableStorageWrapper {
41
41
  *
42
42
  * @function del
43
43
  * @param {string} key Item to delete
44
- * @returns {Promise<void>} A promise that resolves if the operation success, whether the key existed and was removed or it didn't exist.
44
+ * @returns {Promise<boolean>} A promise that resolves if the operation success, whether the key existed and was removed (resolves with true) or it didn't exist (resolves with false).
45
45
  * The promise rejects if the operation fails, for example, if there is a connection error.
46
46
  */
47
- del: (key: string) => Promise<boolean | void>;
47
+ del: (key: string) => Promise<boolean>;
48
48
  /**
49
49
  * Returns all keys matching the given prefix.
50
50
  *
@@ -193,7 +193,7 @@ export interface ISplitsCacheBase {
193
193
  clear(): MaybeThenable<boolean | void>;
194
194
  checkCache(): MaybeThenable<boolean>;
195
195
  killLocally(name: string, defaultTreatment: string, changeNumber: number): MaybeThenable<boolean>;
196
- getNamesByFlagSets(flagSets: string[]): MaybeThenable<ISet<string>>;
196
+ getNamesByFlagSets(flagSets: string[]): MaybeThenable<ISet<string>[]>;
197
197
  }
198
198
  export interface ISplitsCacheSync extends ISplitsCacheBase {
199
199
  addSplits(entries: [string, ISplit][]): boolean[];
@@ -209,7 +209,7 @@ export interface ISplitsCacheSync extends ISplitsCacheBase {
209
209
  clear(): void;
210
210
  checkCache(): boolean;
211
211
  killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean;
212
- getNamesByFlagSets(flagSets: string[]): ISet<string>;
212
+ getNamesByFlagSets(flagSets: string[]): ISet<string>[];
213
213
  }
214
214
  export interface ISplitsCacheAsync extends ISplitsCacheBase {
215
215
  addSplits(entries: [string, ISplit][]): Promise<boolean[] | void>;
@@ -225,7 +225,7 @@ export interface ISplitsCacheAsync extends ISplitsCacheBase {
225
225
  clear(): Promise<boolean | void>;
226
226
  checkCache(): Promise<boolean>;
227
227
  killLocally(name: string, defaultTreatment: string, changeNumber: number): Promise<boolean>;
228
- getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>>;
228
+ getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>[]>;
229
229
  }
230
230
  /** Segments cache */
231
231
  export interface ISegmentsCacheBase {
package/types/types.d.ts CHANGED
@@ -191,8 +191,6 @@ interface ISharedSettings {
191
191
  * List of feature flag filters. These filters are used to fetch a subset of the feature flag definitions in your environment, in order to reduce the delay of the SDK to be ready.
192
192
  * This configuration is only meaningful when the SDK is working in "standalone" mode.
193
193
  *
194
- * At the moment, only one type of feature flag filter is supported: by name.
195
- *
196
194
  * Example:
197
195
  * `splitFilter: [
198
196
  * { type: 'byName', values: ['my_feature_flag_1', 'my_feature_flag_2'] }, // will fetch feature flags named 'my_feature_flag_1' and 'my_feature_flag_2'
@@ -0,0 +1,7 @@
1
+ import { ILogger } from '../../logger/types';
2
+ /** validates the given SDK key */
3
+ export declare function validateApiKey(log: ILogger, maybeSdkKey: any): string | false;
4
+ export declare const usedKeysMap: Record<string, number>;
5
+ /** validates the given SDK key and also warns if it is in use */
6
+ export declare function validateAndTrackApiKey(log: ILogger, maybeSdkKey: any): string | false;
7
+ export declare function releaseApiKey(sdkKey: string): void;
@@ -58,4 +58,5 @@ interface ISetConstructor {
58
58
  export declare function __getSetConstructor(): ISetConstructor;
59
59
  export declare const _Set: ISetConstructor;
60
60
  export declare function returnSetsUnion<T>(set: ISet<T>, set2: ISet<T>): ISet<T>;
61
+ export declare function returnListDifference<T>(list?: T[], list2?: T[]): T[];
61
62
  export {};
@@ -5,6 +5,7 @@ import { ILogger } from '../../logger/types';
5
5
  *
6
6
  * @param {ILogger} log logger
7
7
  * @param {any} maybeSplitFilters split filters configuration param provided by the user
8
+ * @param {string} mode settings mode
8
9
  * @returns it returns an object with the following properties:
9
10
  * - `validFilters`: the validated `splitFilters` configuration object defined by the user.
10
11
  * - `queryString`: the parsed split filter query. it is null if all filters are invalid or all values in filters are invalid.
@@ -12,5 +13,5 @@ import { ILogger } from '../../logger/types';
12
13
  *
13
14
  * @throws Error if the some of the grouped list of values per filter exceeds the max allowed length
14
15
  */
15
- export declare function validateSplitFilters(log: ILogger, maybeSplitFilters: any): ISplitFiltersValidation;
16
+ export declare function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: string): ISplitFiltersValidation;
16
17
  export declare function flagSetsAreValid(log: ILogger, method: string, flagSets: string[], flagSetsInConfig: string[]): string[];
@@ -1,5 +0,0 @@
1
- export declare const myLogger: {
2
- log: (msg: any) => void;
3
- logCsv: (msg: any) => void;
4
- logToFile: (file: any, msg: any) => void;
5
- };
@@ -1,18 +0,0 @@
1
- import { ISignalListener } from '../listeners/types';
2
- import { ISdkReadinessManager } from '../readiness/types';
3
- import { IStorageAsync, IStorageSync } from '../storages/types';
4
- import { ISyncManager } from '../sync/types';
5
- import { IEventTracker, IImpressionsTracker } from '../trackers/types';
6
- import { ISettings } from '../types';
7
- export interface IClientFactoryParams {
8
- storage: IStorageSync | IStorageAsync;
9
- sdkReadinessManager: ISdkReadinessManager;
10
- settings: ISettings;
11
- impressionsTracker: IImpressionsTracker;
12
- eventTracker: IEventTracker;
13
- }
14
- export interface ISdkClientFactoryParams extends IClientFactoryParams {
15
- signalListener?: ISignalListener;
16
- syncManager?: ISyncManager;
17
- sharedClient?: boolean;
18
- }
@@ -1,20 +0,0 @@
1
- import { ICountsCacheSync } from '../types';
2
- export declare class CountsCacheInMemory implements ICountsCacheSync {
3
- private counters;
4
- /**
5
- * Add counts.
6
- */
7
- track(metricName: string): boolean;
8
- /**
9
- * Clear the collector
10
- */
11
- clear(): void;
12
- /**
13
- * Get the collected data, used as payload for posting.
14
- */
15
- state(): Record<string, number>;
16
- /**
17
- * Check if the cache is empty.
18
- */
19
- isEmpty(): boolean;
20
- }
@@ -1,20 +0,0 @@
1
- import { ILatenciesCacheSync } from '../types';
2
- export declare class LatenciesCacheInMemory implements ILatenciesCacheSync {
3
- private counters;
4
- /**
5
- * Add latencies.
6
- */
7
- track(metricName: string, latency: number): boolean;
8
- /**
9
- * Clear the collector
10
- */
11
- clear(): void;
12
- /**
13
- * Get the collected data, used as payload for posting.
14
- */
15
- state(): Record<string, number[]>;
16
- /**
17
- * Check if the cache is empty.
18
- */
19
- isEmpty(): boolean;
20
- }
@@ -1,9 +0,0 @@
1
- import { ICountsCacheAsync } from '../types';
2
- import { KeyBuilderSS } from '../KeyBuilderSS';
3
- import { Redis } from 'ioredis';
4
- export declare class CountsCacheInRedis implements ICountsCacheAsync {
5
- private readonly redis;
6
- private readonly keys;
7
- constructor(keys: KeyBuilderSS, redis: Redis);
8
- track(metricName: string): Promise<boolean>;
9
- }
@@ -1,9 +0,0 @@
1
- import { ILatenciesCacheAsync } from '../types';
2
- import { KeyBuilderSS } from '../KeyBuilderSS';
3
- import { Redis } from 'ioredis';
4
- export declare class LatenciesCacheInRedis implements ILatenciesCacheAsync {
5
- private readonly redis;
6
- private readonly keys;
7
- constructor(keys: KeyBuilderSS, redis: Redis);
8
- track(metricName: string, latency: number): Promise<boolean>;
9
- }
@@ -1,3 +0,0 @@
1
- import { IMetadata } from '../dtos/types';
2
- import { ISettings } from '../types';
3
- export declare function metadataBuilder(settings: Pick<ISettings, 'version' | 'runtime'>): IMetadata;
@@ -1,2 +0,0 @@
1
- import { SplitIO } from '../../types';
2
- export declare function LocalhostFromFile(): SplitIO.LocalhostFactory;
@@ -1,2 +0,0 @@
1
- import { ISplitsParser } from './types';
2
- export declare function splitsParserFromFileFactory(): ISplitsParser;
@@ -1,8 +0,0 @@
1
- import { IEventsCacheSync } from '../../storages/types';
2
- import { IPostEventsBulk } from '../../services/types';
3
- import { ISyncTask, ITimeTracker } from '../types';
4
- import { ILogger } from '../../logger/types';
5
- /**
6
- * Sync task that periodically posts tracked events
7
- */
8
- export declare function eventsSyncTaskFactory(log: ILogger, postEventsBulk: IPostEventsBulk, eventsCache: IEventsCacheSync, eventsPushRate: number, eventsFirstPushWindow: number, latencyTracker?: ITimeTracker): ISyncTask;
@@ -1,5 +0,0 @@
1
- import { ISdkFactoryContextSync } from '../../sdkFactory/types';
2
- /**
3
- * Submitter that periodically posts impression counts
4
- */
5
- export declare function impressionCountsSubmitterInRedisFactory(params: ISdkFactoryContextSync): import("../types").ISyncTask<[], void>;
@@ -1,13 +0,0 @@
1
- import { ISyncTask, ITimeTracker } from '../types';
2
- import { IPostTestImpressionsCount } from '../../services/types';
3
- import { IImpressionCountsCacheSync } from '../../storages/types';
4
- import { ImpressionCountsPayload } from './types';
5
- import { ILogger } from '../../logger/types';
6
- /**
7
- * Converts `impressionCounts` data from cache into request payload.
8
- */
9
- export declare function fromImpressionCountsCollector(impressionsCount: Record<string, number>): ImpressionCountsPayload;
10
- /**
11
- * Sync task that periodically posts impression counts
12
- */
13
- export declare function impressionCountsSyncTaskFactory(log: ILogger, postTestImpressionsCount: IPostTestImpressionsCount, impressionCountsCache: IImpressionCountsCacheSync, latencyTracker?: ITimeTracker): ISyncTask;