@splitsoftware/splitio-commons 1.10.1-rc.4 → 1.12.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CHANGES.txt +16 -10
  2. package/cjs/evaluator/index.js +22 -3
  3. package/cjs/logger/constants.js +6 -4
  4. package/cjs/logger/messages/warn.js +5 -3
  5. package/cjs/sdkClient/client.js +19 -16
  6. package/cjs/sdkClient/clientInputValidation.js +16 -16
  7. package/cjs/sdkFactory/index.js +1 -1
  8. package/cjs/sdkManager/index.js +14 -13
  9. package/cjs/storages/KeyBuilder.js +1 -1
  10. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +3 -10
  11. package/cjs/storages/inMemory/SplitsCacheInMemory.js +2 -10
  12. package/cjs/storages/inRedis/RedisAdapter.js +32 -13
  13. package/cjs/storages/inRedis/SegmentsCacheInRedis.js +2 -2
  14. package/cjs/storages/inRedis/SplitsCacheInRedis.js +38 -22
  15. package/cjs/storages/inRedis/index.js +1 -1
  16. package/cjs/storages/pluggable/SplitsCachePluggable.js +27 -11
  17. package/cjs/storages/pluggable/index.js +1 -1
  18. package/cjs/utils/constants/index.js +16 -2
  19. package/cjs/utils/inputValidation/index.js +5 -5
  20. package/cjs/utils/inputValidation/{splitExistance.js → splitExistence.js} +3 -3
  21. package/cjs/utils/inputValidation/{trafficTypeExistance.js → trafficTypeExistence.js} +6 -6
  22. package/cjs/utils/lang/sets.js +11 -1
  23. package/cjs/utils/settingsValidation/index.js +1 -1
  24. package/cjs/utils/settingsValidation/splitFilters.js +25 -17
  25. package/esm/evaluator/index.js +23 -4
  26. package/esm/logger/constants.js +4 -2
  27. package/esm/logger/messages/warn.js +5 -3
  28. package/esm/sdkClient/client.js +20 -17
  29. package/esm/sdkClient/clientInputValidation.js +18 -18
  30. package/esm/sdkFactory/index.js +1 -1
  31. package/esm/sdkManager/index.js +11 -10
  32. package/esm/storages/KeyBuilder.js +1 -1
  33. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +4 -11
  34. package/esm/storages/inMemory/SplitsCacheInMemory.js +3 -11
  35. package/esm/storages/inRedis/RedisAdapter.js +32 -13
  36. package/esm/storages/inRedis/SegmentsCacheInRedis.js +2 -2
  37. package/esm/storages/inRedis/SplitsCacheInRedis.js +40 -24
  38. package/esm/storages/inRedis/index.js +1 -1
  39. package/esm/storages/pluggable/SplitsCachePluggable.js +29 -13
  40. package/esm/storages/pluggable/index.js +1 -1
  41. package/esm/utils/constants/index.js +14 -0
  42. package/esm/utils/inputValidation/index.js +2 -2
  43. package/esm/utils/inputValidation/{splitExistance.js → splitExistence.js} +1 -1
  44. package/esm/utils/inputValidation/{trafficTypeExistance.js → trafficTypeExistence.js} +4 -4
  45. package/esm/utils/lang/sets.js +9 -0
  46. package/esm/utils/settingsValidation/index.js +1 -1
  47. package/esm/utils/settingsValidation/splitFilters.js +17 -9
  48. package/package.json +1 -1
  49. package/src/evaluator/index.ts +28 -5
  50. package/src/logger/constants.ts +4 -2
  51. package/src/logger/messages/warn.ts +9 -7
  52. package/src/sdkClient/client.ts +18 -18
  53. package/src/sdkClient/clientInputValidation.ts +18 -18
  54. package/src/sdkFactory/index.ts +1 -1
  55. package/src/sdkFactory/types.ts +3 -7
  56. package/src/sdkManager/index.ts +14 -14
  57. package/src/storages/AbstractSplitsCacheAsync.ts +1 -1
  58. package/src/storages/AbstractSplitsCacheSync.ts +1 -1
  59. package/src/storages/KeyBuilder.ts +1 -1
  60. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +8 -15
  61. package/src/storages/inMemory/SplitsCacheInMemory.ts +6 -14
  62. package/src/storages/inRedis/EventsCacheInRedis.ts +3 -3
  63. package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +3 -3
  64. package/src/storages/inRedis/ImpressionsCacheInRedis.ts +3 -3
  65. package/src/storages/inRedis/RedisAdapter.ts +38 -16
  66. package/src/storages/inRedis/SegmentsCacheInRedis.ts +5 -5
  67. package/src/storages/inRedis/SplitsCacheInRedis.ts +49 -28
  68. package/src/storages/inRedis/TelemetryCacheInRedis.ts +2 -2
  69. package/src/storages/inRedis/UniqueKeysCacheInRedis.ts +3 -3
  70. package/src/storages/inRedis/index.ts +1 -1
  71. package/src/storages/pluggable/SplitsCachePluggable.ts +35 -13
  72. package/src/storages/pluggable/index.ts +1 -1
  73. package/src/storages/types.ts +5 -5
  74. package/src/trackers/impressionObserver/utils.ts +1 -1
  75. package/src/types.ts +0 -2
  76. package/src/utils/constants/index.ts +16 -0
  77. package/src/utils/inputValidation/index.ts +2 -2
  78. package/src/utils/inputValidation/{splitExistance.ts → splitExistence.ts} +1 -1
  79. package/src/utils/inputValidation/{trafficTypeExistance.ts → trafficTypeExistence.ts} +4 -4
  80. package/src/utils/lang/sets.ts +9 -1
  81. package/src/utils/redis/RedisMock.ts +1 -3
  82. package/src/utils/settingsValidation/index.ts +1 -1
  83. package/src/utils/settingsValidation/splitFilters.ts +19 -11
  84. package/types/evaluator/index.d.ts +1 -1
  85. package/types/logger/constants.d.ts +4 -2
  86. package/types/sdkFactory/types.d.ts +3 -3
  87. package/types/sdkManager/index.d.ts +2 -3
  88. package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
  89. package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
  90. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +1 -1
  91. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +1 -1
  92. package/types/storages/inRedis/EventsCacheInRedis.d.ts +2 -2
  93. package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +3 -2
  94. package/types/storages/inRedis/ImpressionsCacheInRedis.d.ts +2 -2
  95. package/types/storages/inRedis/RedisAdapter.d.ts +1 -1
  96. package/types/storages/inRedis/SegmentsCacheInRedis.d.ts +3 -3
  97. package/types/storages/inRedis/SplitsCacheInRedis.d.ts +10 -14
  98. package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +2 -2
  99. package/types/storages/inRedis/UniqueKeysCacheInRedis.d.ts +3 -2
  100. package/types/storages/pluggable/SplitsCachePluggable.d.ts +10 -9
  101. package/types/storages/types.d.ts +5 -5
  102. package/types/trackers/impressionObserver/utils.d.ts +1 -1
  103. package/types/types.d.ts +0 -2
  104. package/types/utils/constants/index.d.ts +12 -0
  105. package/types/utils/inputValidation/index.d.ts +2 -2
  106. package/types/utils/inputValidation/splitExistence.d.ts +7 -0
  107. package/types/utils/inputValidation/trafficTypeExistence.d.ts +9 -0
  108. package/types/utils/lang/sets.d.ts +1 -0
  109. package/types/utils/settingsValidation/splitFilters.d.ts +3 -2
@@ -1,10 +1,10 @@
1
1
  import { evaluateFeature, evaluateFeatures, evaluateFeaturesByFlagSets } from '../evaluator';
2
2
  import { thenable } from '../utils/promise/thenable';
3
3
  import { getMatching, getBucketing } from '../utils/key';
4
- import { validateSplitExistance } from '../utils/inputValidation/splitExistance';
5
- import { validateTrafficTypeExistance } from '../utils/inputValidation/trafficTypeExistance';
4
+ import { validateSplitExistence } from '../utils/inputValidation/splitExistence';
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';
@@ -29,12 +29,12 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
29
29
  const { sdkReadinessManager: { readinessManager }, storage, settings, impressionsTracker, eventTracker, telemetryTracker } = params;
30
30
  const { log, mode } = settings;
31
31
 
32
- function getTreatment(key: SplitIO.SplitKey, featureFlagName: string, attributes: SplitIO.Attributes | undefined, withConfig = false) {
32
+ function getTreatment(key: SplitIO.SplitKey, featureFlagName: string, attributes: SplitIO.Attributes | undefined, withConfig = false, methodName = GET_TREATMENT) {
33
33
  const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENT_WITH_CONFIG : TREATMENT);
34
34
 
35
35
  const wrapUp = (evaluationResult: IEvaluationResult) => {
36
36
  const queue: ImpressionDTO[] = [];
37
- const treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig, `getTreatment${withConfig ? 'withConfig' : ''}`, queue);
37
+ const treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig, methodName, queue);
38
38
  impressionsTracker.track(queue, attributes);
39
39
 
40
40
  stopTelemetryTracker(queue[0] && queue[0].label);
@@ -51,17 +51,17 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
51
51
  }
52
52
 
53
53
  function getTreatmentWithConfig(key: SplitIO.SplitKey, featureFlagName: string, attributes: SplitIO.Attributes | undefined) {
54
- return getTreatment(key, featureFlagName, attributes, true);
54
+ return getTreatment(key, featureFlagName, attributes, true, GET_TREATMENT_WITH_CONFIG);
55
55
  }
56
56
 
57
- function getTreatments(key: SplitIO.SplitKey, featureFlagNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false) {
57
+ function getTreatments(key: SplitIO.SplitKey, featureFlagNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false, methodName = GET_TREATMENTS) {
58
58
  const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENTS_WITH_CONFIG : TREATMENTS);
59
59
 
60
60
  const wrapUp = (evaluationResults: Record<string, IEvaluationResult>) => {
61
61
  const queue: ImpressionDTO[] = [];
62
62
  const treatments: Record<string, SplitIO.Treatment | SplitIO.TreatmentWithConfig> = {};
63
63
  Object.keys(evaluationResults).forEach(featureFlagName => {
64
- treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig, `getTreatments${withConfig ? 'withConfig' : ''}`, queue);
64
+ treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
65
65
  });
66
66
  impressionsTracker.track(queue, attributes);
67
67
 
@@ -79,18 +79,18 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
79
79
  }
80
80
 
81
81
  function getTreatmentsWithConfig(key: SplitIO.SplitKey, featureFlagNames: string[], attributes: SplitIO.Attributes | undefined) {
82
- return getTreatments(key, featureFlagNames, attributes, true);
82
+ return getTreatments(key, featureFlagNames, attributes, true, GET_TREATMENTS_WITH_CONFIG);
83
83
  }
84
84
 
85
- function getTreatmentsByFlagSets(key: SplitIO.SplitKey, flagSetNames: string[], attributes: SplitIO.Attributes | undefined, withConfig = false, method: Method = TREATMENTS_BY_FLAGSETS) {
85
+ 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
86
  const stopTelemetryTracker = telemetryTracker.trackEval(method);
87
87
 
88
- const wrapUp = (evaluationResults: Record<string,IEvaluationResult>) => {
88
+ const wrapUp = (evaluationResults: Record<string, IEvaluationResult>) => {
89
89
  const queue: ImpressionDTO[] = [];
90
90
  const treatments: Record<string, SplitIO.Treatment | SplitIO.TreatmentWithConfig> = {};
91
91
  const evaluations = evaluationResults;
92
92
  Object.keys(evaluations).forEach(featureFlagName => {
93
- treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig, `getTreatmentsByFlagSets${withConfig ? 'WithConfig' : ''}`, queue);
93
+ treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
94
94
  });
95
95
  impressionsTracker.track(queue, attributes);
96
96
 
@@ -99,22 +99,22 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
99
99
  };
100
100
 
101
101
  const evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
102
- evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage) :
102
+ evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage, methodName) :
103
103
  isStorageSync(settings) ? {} : Promise.resolve({}); // Promisify if async
104
104
 
105
105
  return thenable(evaluations) ? evaluations.then((res) => wrapUp(res)) : wrapUp(evaluations);
106
106
  }
107
107
 
108
108
  function getTreatmentsWithConfigByFlagSets(key: SplitIO.SplitKey, flagSetNames: string[], attributes: SplitIO.Attributes | undefined) {
109
- return getTreatmentsByFlagSets(key, flagSetNames, attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSETS);
109
+ return getTreatmentsByFlagSets(key, flagSetNames, attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSETS, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS);
110
110
  }
111
111
 
112
112
  function getTreatmentsByFlagSet(key: SplitIO.SplitKey, flagSetName: string, attributes: SplitIO.Attributes | undefined) {
113
- return getTreatmentsByFlagSets(key, [flagSetName], attributes, false, TREATMENTS_BY_FLAGSET);
113
+ return getTreatmentsByFlagSets(key, [flagSetName], attributes, false, TREATMENTS_BY_FLAGSET, GET_TREATMENTS_BY_FLAG_SET);
114
114
  }
115
115
 
116
116
  function getTreatmentsWithConfigByFlagSet(key: SplitIO.SplitKey, flagSetName: string, attributes: SplitIO.Attributes | undefined) {
117
- return getTreatmentsByFlagSets(key, [flagSetName], attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSET);
117
+ return getTreatmentsByFlagSets(key, [flagSetName], attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET);
118
118
  }
119
119
 
120
120
  // Internal function
@@ -133,7 +133,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
133
133
  const { treatment, label, changeNumber, config = null } = evaluation;
134
134
  log.info(IMPRESSION, [featureFlagName, matchingKey, treatment, label]);
135
135
 
136
- if (validateSplitExistance(log, readinessManager, featureFlagName, label, invokingMethodName)) {
136
+ if (validateSplitExistence(log, readinessManager, featureFlagName, label, invokingMethodName)) {
137
137
  log.info(IMPRESSION_QUEUEING);
138
138
  queue.push({
139
139
  feature: featureFlagName,
@@ -171,7 +171,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
171
171
  };
172
172
 
173
173
  // 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
- validateTrafficTypeExistance(log, readinessManager, storage.splits, mode, trafficTypeName, 'track');
174
+ validateTrafficTypeExistence(log, readinessManager, storage.splits, mode, trafficTypeName, TRACK_FN_LABEL);
175
175
 
176
176
  const result = eventTracker.track(eventData, size);
177
177
 
@@ -12,12 +12,12 @@ import {
12
12
  validateIfOperational
13
13
  } from '../utils/inputValidation';
14
14
  import { startsWith } from '../utils/lang';
15
- import { CONTROL, CONTROL_WITH_CONFIG } from '../utils/constants';
15
+ import { CONTROL, CONTROL_WITH_CONFIG, GET_TREATMENT, GET_TREATMENTS, GET_TREATMENTS_BY_FLAG_SET, GET_TREATMENTS_BY_FLAG_SETS, GET_TREATMENTS_WITH_CONFIG, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, GET_TREATMENT_WITH_CONFIG, TRACK_FN_LABEL } from '../utils/constants';
16
16
  import { IReadinessManager } from '../readiness/types';
17
17
  import { MaybeThenable } from '../dtos/types';
18
18
  import { ISettings, SplitIO } from '../types';
19
19
  import { isStorageSync } from '../trackers/impressionObserver/utils';
20
- import { flagSetsAreValid } from '../utils/settingsValidation/splitFilters';
20
+ import { validateFlagSets } from '../utils/settingsValidation/splitFilters';
21
21
 
22
22
  /**
23
23
  * Decorator that validates the input before actually executing the client methods.
@@ -32,7 +32,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
32
32
  * Avoid repeating this validations code
33
33
  */
34
34
  function validateEvaluationParams(maybeKey: SplitIO.SplitKey, maybeFeatureFlagNameOrNames: string | string[] | undefined, maybeAttributes: SplitIO.Attributes | undefined, methodName: string, maybeFlagSetNameOrNames?: string[]) {
35
- const multi = startsWith(methodName, 'getTreatments');
35
+ const multi = startsWith(methodName, GET_TREATMENTS);
36
36
  const key = validateKey(log, maybeKey, methodName);
37
37
  let splitOrSplits: string | string[] | false = false;
38
38
  let flagSetOrFlagSets: string[] = [];
@@ -42,7 +42,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
42
42
  const attributes = validateAttributes(log, maybeAttributes, methodName);
43
43
  const isNotDestroyed = validateIfNotDestroyed(log, readinessManager, methodName);
44
44
  if (maybeFlagSetNameOrNames) {
45
- flagSetOrFlagSets = flagSetsAreValid(log, methodName, maybeFlagSetNameOrNames, settings.sync.__splitFiltersValidation.groupedFilters.bySet);
45
+ flagSetOrFlagSets = validateFlagSets(log, methodName, maybeFlagSetNameOrNames, settings.sync.__splitFiltersValidation.groupedFilters.bySet);
46
46
  }
47
47
 
48
48
  validateIfOperational(log, readinessManager, methodName, splitOrSplits);
@@ -63,7 +63,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
63
63
  }
64
64
 
65
65
  function getTreatment(maybeKey: SplitIO.SplitKey, maybeFeatureFlagName: string, maybeAttributes?: SplitIO.Attributes) {
66
- const params = validateEvaluationParams(maybeKey, maybeFeatureFlagName, maybeAttributes, 'getTreatment');
66
+ const params = validateEvaluationParams(maybeKey, maybeFeatureFlagName, maybeAttributes, GET_TREATMENT);
67
67
 
68
68
  if (params.valid) {
69
69
  return client.getTreatment(params.key as SplitIO.SplitKey, params.splitOrSplits as string, params.attributes as SplitIO.Attributes | undefined);
@@ -73,7 +73,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
73
73
  }
74
74
 
75
75
  function getTreatmentWithConfig(maybeKey: SplitIO.SplitKey, maybeFeatureFlagName: string, maybeAttributes?: SplitIO.Attributes) {
76
- const params = validateEvaluationParams(maybeKey, maybeFeatureFlagName, maybeAttributes, 'getTreatmentWithConfig');
76
+ const params = validateEvaluationParams(maybeKey, maybeFeatureFlagName, maybeAttributes, GET_TREATMENT_WITH_CONFIG);
77
77
 
78
78
  if (params.valid) {
79
79
  return client.getTreatmentWithConfig(params.key as SplitIO.SplitKey, params.splitOrSplits as string, params.attributes as SplitIO.Attributes | undefined);
@@ -83,7 +83,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
83
83
  }
84
84
 
85
85
  function getTreatments(maybeKey: SplitIO.SplitKey, maybeFeatureFlagNames: string[], maybeAttributes?: SplitIO.Attributes) {
86
- const params = validateEvaluationParams(maybeKey, maybeFeatureFlagNames, maybeAttributes, 'getTreatments');
86
+ const params = validateEvaluationParams(maybeKey, maybeFeatureFlagNames, maybeAttributes, GET_TREATMENTS);
87
87
 
88
88
  if (params.valid) {
89
89
  return client.getTreatments(params.key as SplitIO.SplitKey, params.splitOrSplits as string[], params.attributes as SplitIO.Attributes | undefined);
@@ -96,7 +96,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
96
96
  }
97
97
 
98
98
  function getTreatmentsWithConfig(maybeKey: SplitIO.SplitKey, maybeFeatureFlagNames: string[], maybeAttributes?: SplitIO.Attributes) {
99
- const params = validateEvaluationParams(maybeKey, maybeFeatureFlagNames, maybeAttributes, 'getTreatmentsWithConfig');
99
+ const params = validateEvaluationParams(maybeKey, maybeFeatureFlagNames, maybeAttributes, GET_TREATMENTS_WITH_CONFIG);
100
100
 
101
101
  if (params.valid) {
102
102
  return client.getTreatmentsWithConfig(params.key as SplitIO.SplitKey, params.splitOrSplits as string[], params.attributes as SplitIO.Attributes | undefined);
@@ -109,7 +109,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
109
109
  }
110
110
 
111
111
  function getTreatmentsByFlagSets(maybeKey: SplitIO.SplitKey, maybeFlagSets: string[], maybeAttributes?: SplitIO.Attributes) {
112
- const params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, 'getTreatmentsByFlagSets', maybeFlagSets);
112
+ const params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, GET_TREATMENTS_BY_FLAG_SETS, maybeFlagSets);
113
113
 
114
114
  if (params.valid) {
115
115
  return client.getTreatmentsByFlagSets(params.key as SplitIO.SplitKey, params.flagSetOrFlagSets as string[], params.attributes as SplitIO.Attributes | undefined);
@@ -119,7 +119,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
119
119
  }
120
120
 
121
121
  function getTreatmentsWithConfigByFlagSets(maybeKey: SplitIO.SplitKey, maybeFlagSets: string[], maybeAttributes?: SplitIO.Attributes) {
122
- const params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, 'getTreatmentsWithConfigByFlagSets', maybeFlagSets);
122
+ const params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, maybeFlagSets);
123
123
 
124
124
  if (params.valid) {
125
125
  return client.getTreatmentsWithConfigByFlagSets(params.key as SplitIO.SplitKey, params.flagSetOrFlagSets as string[], params.attributes as SplitIO.Attributes | undefined);
@@ -129,7 +129,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
129
129
  }
130
130
 
131
131
  function getTreatmentsByFlagSet(maybeKey: SplitIO.SplitKey, maybeFlagSet: string, maybeAttributes?: SplitIO.Attributes) {
132
- const params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, 'getTreatmentsByFlagSet', [maybeFlagSet]);
132
+ const params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, GET_TREATMENTS_BY_FLAG_SET, [maybeFlagSet]);
133
133
 
134
134
  if (params.valid) {
135
135
  return client.getTreatmentsByFlagSet(params.key as SplitIO.SplitKey, params.flagSetOrFlagSets[0] as string, params.attributes as SplitIO.Attributes | undefined);
@@ -139,7 +139,7 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
139
139
  }
140
140
 
141
141
  function getTreatmentsWithConfigByFlagSet(maybeKey: SplitIO.SplitKey, maybeFlagSet: string, maybeAttributes?: SplitIO.Attributes) {
142
- const params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, 'getTreatmentsWithConfigByFlagSet', [maybeFlagSet]);
142
+ const params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, [maybeFlagSet]);
143
143
 
144
144
  if (params.valid) {
145
145
  return client.getTreatmentsWithConfigByFlagSet(params.key as SplitIO.SplitKey, params.flagSetOrFlagSets[0] as string, params.attributes as SplitIO.Attributes | undefined);
@@ -149,12 +149,12 @@ export function clientInputValidationDecorator<TClient extends SplitIO.IClient |
149
149
  }
150
150
 
151
151
  function track(maybeKey: SplitIO.SplitKey, maybeTT: string, maybeEvent: string, maybeEventValue?: number, maybeProperties?: SplitIO.Properties) {
152
- const key = validateKey(log, maybeKey, 'track');
153
- const tt = validateTrafficType(log, maybeTT, 'track');
154
- const event = validateEvent(log, maybeEvent, 'track');
155
- const eventValue = validateEventValue(log, maybeEventValue, 'track');
156
- const { properties, size } = validateEventProperties(log, maybeProperties, 'track');
157
- const isNotDestroyed = validateIfNotDestroyed(log, readinessManager, 'track');
152
+ const key = validateKey(log, maybeKey, TRACK_FN_LABEL);
153
+ const tt = validateTrafficType(log, maybeTT, TRACK_FN_LABEL);
154
+ const event = validateEvent(log, maybeEvent, TRACK_FN_LABEL);
155
+ const eventValue = validateEventValue(log, maybeEventValue, TRACK_FN_LABEL);
156
+ const { properties, size } = validateEventProperties(log, maybeProperties, TRACK_FN_LABEL);
157
+ const isNotDestroyed = validateIfNotDestroyed(log, readinessManager, TRACK_FN_LABEL);
158
158
 
159
159
  if (isNotDestroyed && key && tt && event && eventValue !== false && properties !== false) { // @ts-expect-error
160
160
  return client.track(key, tt, event, eventValue, properties, size);
@@ -83,7 +83,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
83
83
 
84
84
  // SDK client and manager
85
85
  const clientMethod = sdkClientMethodFactory(ctx);
86
- const managerInstance = sdkManagerFactory(log, storage.splits, sdkReadinessManager);
86
+ const managerInstance = sdkManagerFactory(settings, storage.splits, sdkReadinessManager);
87
87
 
88
88
  syncManager && syncManager.start();
89
89
  signalListener && signalListener.start();
@@ -1,9 +1,9 @@
1
1
  import { IIntegrationManager, IIntegrationFactoryParams } from '../integrations/types';
2
2
  import { ISignalListener } from '../listeners/types';
3
- import { ILogger } from '../logger/types';
4
3
  import { IReadinessManager, ISdkReadinessManager } from '../readiness/types';
4
+ import type { sdkManagerFactory } from '../sdkManager';
5
5
  import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types';
6
- import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types';
6
+ import { IStorageAsync, IStorageSync, IStorageFactoryParams } from '../storages/types';
7
7
  import { ISyncManager } from '../sync/types';
8
8
  import { IImpressionObserver } from '../trackers/impressionObserver/types';
9
9
  import { IImpressionsTracker, IEventTracker, ITelemetryTracker, IFilterAdapter, IUniqueKeysTracker } from '../trackers/types';
@@ -87,11 +87,7 @@ export interface ISdkFactoryParams {
87
87
  syncManagerFactory?: (params: ISdkFactoryContextSync) => ISyncManager,
88
88
 
89
89
  // Sdk manager factory
90
- sdkManagerFactory: (
91
- log: ILogger,
92
- splits: ISplitsCacheSync | ISplitsCacheAsync,
93
- sdkReadinessManager: ISdkReadinessManager
94
- ) => SplitIO.IManager | SplitIO.IAsyncManager,
90
+ sdkManagerFactory: typeof sdkManagerFactory,
95
91
 
96
92
  // Sdk client method factory (ISDK::client method).
97
93
  // It Allows to distinguish SDK clients with the client-side API (`ICsSDK`) or server-side API (`ISDK` or `IAsyncSDK`).
@@ -1,16 +1,13 @@
1
1
  import { objectAssign } from '../utils/lang/objectAssign';
2
2
  import { thenable } from '../utils/promise/thenable';
3
3
  import { find } from '../utils/lang';
4
- import { validateSplit, validateSplitExistance, validateIfNotDestroyed, validateIfOperational } from '../utils/inputValidation';
4
+ import { validateSplit, validateSplitExistence, validateIfNotDestroyed, validateIfOperational } from '../utils/inputValidation';
5
5
  import { ISplitsCacheAsync, ISplitsCacheSync } from '../storages/types';
6
6
  import { ISdkReadinessManager } from '../readiness/types';
7
7
  import { ISplit } from '../dtos/types';
8
- import { SplitIO } from '../types';
9
- import { ILogger } from '../logger/types';
10
-
11
- const SPLIT_FN_LABEL = 'split';
12
- const SPLITS_FN_LABEL = 'splits';
13
- const NAMES_FN_LABEL = 'names';
8
+ import { ISettings, SplitIO } from '../types';
9
+ import { isStorageSync } from '../trackers/impressionObserver/utils';
10
+ import { SPLIT_FN_LABEL, SPLITS_FN_LABEL, NAMES_FN_LABEL } from '../utils/constants';
14
11
 
15
12
  function collectTreatments(splitObject: ISplit) {
16
13
  const conditions = splitObject.conditions;
@@ -49,11 +46,14 @@ function objectsToViews(splitObjects: ISplit[]) {
49
46
  }
50
47
 
51
48
  export function sdkManagerFactory<TSplitCache extends ISplitsCacheSync | ISplitsCacheAsync>(
52
- log: ILogger,
49
+ settings: Pick<ISettings, 'log' | 'mode'>,
53
50
  splits: TSplitCache,
54
- { readinessManager, sdkStatus }: ISdkReadinessManager
51
+ { readinessManager, sdkStatus }: ISdkReadinessManager,
55
52
  ): TSplitCache extends ISplitsCacheAsync ? SplitIO.IAsyncManager : SplitIO.IManager {
56
53
 
54
+ const log = settings.log;
55
+ const isSync = isStorageSync(settings);
56
+
57
57
  return objectAssign(
58
58
  // Proto-linkage of the readiness Event Emitter
59
59
  Object.create(sdkStatus),
@@ -64,19 +64,19 @@ export function sdkManagerFactory<TSplitCache extends ISplitsCacheSync | ISplits
64
64
  split(featureFlagName: string) {
65
65
  const splitName = validateSplit(log, featureFlagName, SPLIT_FN_LABEL);
66
66
  if (!validateIfNotDestroyed(log, readinessManager, SPLIT_FN_LABEL) || !validateIfOperational(log, readinessManager, SPLIT_FN_LABEL) || !splitName) {
67
- return null;
67
+ return isSync ? null : Promise.resolve(null);
68
68
  }
69
69
 
70
70
  const split = splits.getSplit(splitName);
71
71
 
72
72
  if (thenable(split)) {
73
73
  return split.catch(() => null).then(result => { // handle possible rejections when using pluggable storage
74
- validateSplitExistance(log, readinessManager, splitName, result, SPLIT_FN_LABEL);
74
+ validateSplitExistence(log, readinessManager, splitName, result, SPLIT_FN_LABEL);
75
75
  return objectToView(result);
76
76
  });
77
77
  }
78
78
 
79
- validateSplitExistance(log, readinessManager, splitName, split, SPLIT_FN_LABEL);
79
+ validateSplitExistence(log, readinessManager, splitName, split, SPLIT_FN_LABEL);
80
80
 
81
81
  return objectToView(split);
82
82
  },
@@ -85,7 +85,7 @@ export function sdkManagerFactory<TSplitCache extends ISplitsCacheSync | ISplits
85
85
  */
86
86
  splits() {
87
87
  if (!validateIfNotDestroyed(log, readinessManager, SPLITS_FN_LABEL) || !validateIfOperational(log, readinessManager, SPLITS_FN_LABEL)) {
88
- return [];
88
+ return isSync ? [] : Promise.resolve([]);
89
89
  }
90
90
  const currentSplits = splits.getAll();
91
91
 
@@ -98,7 +98,7 @@ export function sdkManagerFactory<TSplitCache extends ISplitsCacheSync | ISplits
98
98
  */
99
99
  names() {
100
100
  if (!validateIfNotDestroyed(log, readinessManager, NAMES_FN_LABEL) || !validateIfOperational(log, readinessManager, NAMES_FN_LABEL)) {
101
- return [];
101
+ return isSync ? [] : Promise.resolve([]);
102
102
  }
103
103
  const splitNames = splits.getSplitNames();
104
104
 
@@ -18,7 +18,7 @@ export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
18
18
  abstract getChangeNumber(): Promise<number>
19
19
  abstract getAll(): Promise<ISplit[]>
20
20
  abstract getSplitNames(): Promise<string[]>
21
- abstract getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>>
21
+ abstract getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>[]>
22
22
  abstract trafficTypeExists(trafficType: string): Promise<boolean>
23
23
  abstract clear(): Promise<boolean | void>
24
24
 
@@ -79,7 +79,7 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
79
79
  return false;
80
80
  }
81
81
 
82
- abstract getNamesByFlagSets(flagSets: string[]): ISet<string>
82
+ abstract getNamesByFlagSets(flagSets: string[]): ISet<string>[]
83
83
 
84
84
  }
85
85
 
@@ -21,7 +21,7 @@ export class KeyBuilder {
21
21
  }
22
22
 
23
23
  buildFlagSetKey(flagSet: string) {
24
- return `${this.prefix}.flagset.${flagSet}`;
24
+ return `${this.prefix}.flagSet.${flagSet}`;
25
25
  }
26
26
 
27
27
  buildSplitKey(splitName: string) {
@@ -4,7 +4,7 @@ import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
4
4
  import { KeyBuilderCS } from '../KeyBuilderCS';
5
5
  import { ILogger } from '../../logger/types';
6
6
  import { LOG_PREFIX } from './constants';
7
- import { ISet, _Set, returnSetsUnion, setToArray } from '../../utils/lang/sets';
7
+ import { ISet, _Set, setToArray } from '../../utils/lang/sets';
8
8
 
9
9
  /**
10
10
  * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
@@ -257,19 +257,13 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
257
257
  // if the filter didn't change, nothing is done
258
258
  }
259
259
 
260
- getNamesByFlagSets(flagSets: string[]): ISet<string>{
261
- let toReturn: ISet<string> = new _Set([]);
262
- flagSets.forEach(flagSet => {
260
+ getNamesByFlagSets(flagSets: string[]): ISet<string>[] {
261
+ return flagSets.map(flagSet => {
263
262
  const flagSetKey = this.keys.buildFlagSetKey(flagSet);
264
- let flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
263
+ const flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
265
264
 
266
- if (flagSetFromLocalStorage) {
267
- const flagSetCache = new _Set(JSON.parse(flagSetFromLocalStorage));
268
- toReturn = returnSetsUnion(toReturn, flagSetCache);
269
- }
265
+ return new _Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
270
266
  });
271
- return toReturn;
272
-
273
267
  }
274
268
 
275
269
  private addToFlagSets(featureFlag: ISplit) {
@@ -281,10 +275,9 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
281
275
 
282
276
  const flagSetKey = this.keys.buildFlagSetKey(featureFlagSet);
283
277
 
284
- let flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
285
- if (!flagSetFromLocalStorage) flagSetFromLocalStorage = '[]';
278
+ const flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
286
279
 
287
- const flagSetCache = new _Set(JSON.parse(flagSetFromLocalStorage));
280
+ const flagSetCache = new _Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
288
281
  flagSetCache.add(featureFlag.name);
289
282
 
290
283
  localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
@@ -302,7 +295,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
302
295
  private removeNames(flagSetName: string, featureFlagName: string) {
303
296
  const flagSetKey = this.keys.buildFlagSetKey(flagSetName);
304
297
 
305
- let flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
298
+ const flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
306
299
 
307
300
  if (!flagSetFromLocalStorage) return;
308
301
 
@@ -1,7 +1,7 @@
1
1
  import { ISplit, ISplitFiltersValidation } from '../../dtos/types';
2
2
  import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
3
3
  import { isFiniteNumber } from '../../utils/lang';
4
- import { ISet, _Set, returnSetsUnion } from '../../utils/lang/sets';
4
+ import { ISet, _Set } from '../../utils/lang/sets';
5
5
 
6
6
  /**
7
7
  * Default ISplitsCacheSync implementation that stores split definitions in memory.
@@ -16,9 +16,9 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
16
16
  private splitsWithSegmentsCount: number = 0;
17
17
  private flagSetsCache: Record<string, ISet<string>> = {};
18
18
 
19
- constructor(splitFiltersValidation: ISplitFiltersValidation = { queryString: null, groupedFilters: { bySet: [], byName: [], byPrefix: [] }, validFilters: [] }) {
19
+ constructor(splitFiltersValidation?: ISplitFiltersValidation) {
20
20
  super();
21
- this.flagSetsFilter = splitFiltersValidation.groupedFilters.bySet;
21
+ this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
22
22
  }
23
23
 
24
24
  clear() {
@@ -105,16 +105,8 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
105
105
  return this.getChangeNumber() === -1 || this.splitsWithSegmentsCount > 0;
106
106
  }
107
107
 
108
- getNamesByFlagSets(flagSets: string[]): ISet<string>{
109
- let toReturn: ISet<string> = new _Set([]);
110
- flagSets.forEach(flagSet => {
111
- const featureFlagNames = this.flagSetsCache[flagSet];
112
- if (featureFlagNames) {
113
- toReturn = returnSetsUnion(toReturn, featureFlagNames);
114
- }
115
- });
116
- return toReturn;
117
-
108
+ getNamesByFlagSets(flagSets: string[]): ISet<string>[] {
109
+ return flagSets.map(flagSet => this.flagSetsCache[flagSet] || new _Set());
118
110
  }
119
111
 
120
112
  private addToFlagSets(featureFlag: ISplit) {
@@ -129,7 +121,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
129
121
  });
130
122
  }
131
123
 
132
- private removeFromFlagSets(featureFlagName :string, flagSets: string[] | undefined) {
124
+ private removeFromFlagSets(featureFlagName: string, flagSets: string[] | undefined) {
133
125
  if (!flagSets) return;
134
126
  flagSets.forEach(flagSet => {
135
127
  this.removeNames(flagSet, featureFlagName);
@@ -1,19 +1,19 @@
1
1
  import { IEventsCacheAsync } from '../types';
2
2
  import { IMetadata } from '../../dtos/types';
3
- import { Redis } from 'ioredis';
4
3
  import { SplitIO } from '../../types';
5
4
  import { ILogger } from '../../logger/types';
6
5
  import { LOG_PREFIX } from './constants';
7
6
  import { StoredEventWithMetadata } from '../../sync/submitters/types';
7
+ import type { RedisAdapter } from './RedisAdapter';
8
8
 
9
9
  export class EventsCacheInRedis implements IEventsCacheAsync {
10
10
 
11
11
  private readonly log: ILogger;
12
12
  private readonly key: string;
13
- private readonly redis: Redis;
13
+ private readonly redis: RedisAdapter;
14
14
  private readonly metadata: IMetadata;
15
15
 
16
- constructor(log: ILogger, key: string, redis: Redis, metadata: IMetadata) {
16
+ constructor(log: ILogger, key: string, redis: RedisAdapter, metadata: IMetadata) {
17
17
  this.log = log;
18
18
  this.key = key;
19
19
  this.redis = redis;
@@ -1,19 +1,19 @@
1
- import { Redis } from 'ioredis';
2
1
  import { ILogger } from '../../logger/types';
3
2
  import { ImpressionCountsPayload } from '../../sync/submitters/types';
4
3
  import { forOwn } from '../../utils/lang';
5
4
  import { ImpressionCountsCacheInMemory } from '../inMemory/ImpressionCountsCacheInMemory';
6
5
  import { LOG_PREFIX, REFRESH_RATE, TTL_REFRESH } from './constants';
6
+ import type { RedisAdapter } from './RedisAdapter';
7
7
 
8
8
  export class ImpressionCountsCacheInRedis extends ImpressionCountsCacheInMemory {
9
9
 
10
10
  private readonly log: ILogger;
11
11
  private readonly key: string;
12
- private readonly redis: Redis;
12
+ private readonly redis: RedisAdapter;
13
13
  private readonly refreshRate: number;
14
14
  private intervalId: any;
15
15
 
16
- constructor(log: ILogger, key: string, redis: Redis, impressionCountsCacheSize?: number, refreshRate = REFRESH_RATE) {
16
+ constructor(log: ILogger, key: string, redis: RedisAdapter, impressionCountsCacheSize?: number, refreshRate = REFRESH_RATE) {
17
17
  super(impressionCountsCacheSize);
18
18
  this.log = log;
19
19
  this.key = key;
@@ -1,10 +1,10 @@
1
1
  import { IImpressionsCacheAsync } from '../types';
2
2
  import { IMetadata } from '../../dtos/types';
3
3
  import { ImpressionDTO } from '../../types';
4
- import { Redis } from 'ioredis';
5
4
  import { StoredImpressionWithMetadata } from '../../sync/submitters/types';
6
5
  import { ILogger } from '../../logger/types';
7
6
  import { impressionsToJSON } from '../utils';
7
+ import type { RedisAdapter } from './RedisAdapter';
8
8
 
9
9
  const IMPRESSIONS_TTL_REFRESH = 3600; // 1 hr
10
10
 
@@ -12,10 +12,10 @@ export class ImpressionsCacheInRedis implements IImpressionsCacheAsync {
12
12
 
13
13
  private readonly log: ILogger;
14
14
  private readonly key: string;
15
- private readonly redis: Redis;
15
+ private readonly redis: RedisAdapter;
16
16
  private readonly metadata: IMetadata;
17
17
 
18
- constructor(log: ILogger, key: string, redis: Redis, metadata: IMetadata) {
18
+ constructor(log: ILogger, key: string, redis: RedisAdapter, metadata: IMetadata) {
19
19
  this.log = log;
20
20
  this.key = key;
21
21
  this.redis = redis;