@splitsoftware/splitio-commons 1.13.2-rc.0 → 1.13.2-rc.10

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 (180) hide show
  1. package/CHANGES.txt +4 -3
  2. package/cjs/evaluator/Engine.js +5 -6
  3. package/cjs/evaluator/combiners/ifelseif.js +3 -4
  4. package/cjs/evaluator/condition/index.js +2 -3
  5. package/cjs/evaluator/index.js +4 -5
  6. package/cjs/evaluator/matchers/all.js +1 -3
  7. package/cjs/evaluator/matchers/between.js +1 -3
  8. package/cjs/evaluator/matchers/boolean.js +1 -3
  9. package/cjs/evaluator/matchers/cont_all.js +1 -3
  10. package/cjs/evaluator/matchers/cont_any.js +1 -3
  11. package/cjs/evaluator/matchers/cont_str.js +1 -3
  12. package/cjs/evaluator/matchers/dependency.js +1 -1
  13. package/cjs/evaluator/matchers/eq.js +1 -3
  14. package/cjs/evaluator/matchers/eq_set.js +1 -3
  15. package/cjs/evaluator/matchers/ew.js +1 -3
  16. package/cjs/evaluator/matchers/gte.js +3 -5
  17. package/cjs/evaluator/matchers/index.js +12 -2
  18. package/cjs/evaluator/matchers/lte.js +3 -5
  19. package/cjs/evaluator/matchers/matcherTypes.js +6 -1
  20. package/cjs/evaluator/matchers/part_of.js +1 -3
  21. package/cjs/evaluator/matchers/segment.js +1 -6
  22. package/cjs/evaluator/matchers/semver_between.js +14 -0
  23. package/cjs/evaluator/matchers/semver_eq.js +13 -0
  24. package/cjs/evaluator/matchers/semver_gte.js +13 -0
  25. package/cjs/evaluator/matchers/semver_inlist.js +17 -0
  26. package/cjs/evaluator/matchers/semver_lte.js +13 -0
  27. package/cjs/evaluator/matchers/string.js +3 -12
  28. package/cjs/evaluator/matchers/sw.js +1 -3
  29. package/cjs/evaluator/matchers/whitelist.js +3 -4
  30. package/cjs/evaluator/matchersTransform/index.js +21 -16
  31. package/cjs/evaluator/matchersTransform/whitelist.js +2 -3
  32. package/cjs/evaluator/parser/index.js +24 -9
  33. package/cjs/logger/constants.js +5 -20
  34. package/cjs/logger/index.js +8 -1
  35. package/cjs/logger/messages/debug.js +5 -21
  36. package/cjs/logger/messages/error.js +2 -1
  37. package/cjs/logger/messages/warn.js +1 -1
  38. package/cjs/sdkClient/sdkClient.js +1 -6
  39. package/cjs/services/splitApi.js +5 -5
  40. package/cjs/storages/KeyBuilder.js +2 -1
  41. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +1 -1
  42. package/cjs/storages/pluggable/index.js +1 -1
  43. package/cjs/utils/Semver.js +103 -0
  44. package/cjs/utils/constants/index.js +2 -1
  45. package/cjs/utils/labels/index.js +1 -1
  46. package/cjs/utils/settingsValidation/index.js +1 -1
  47. package/cjs/utils/settingsValidation/logger/pluggableLogger.js +1 -1
  48. package/esm/evaluator/Engine.js +5 -5
  49. package/esm/evaluator/combiners/ifelseif.js +3 -3
  50. package/esm/evaluator/condition/index.js +2 -2
  51. package/esm/evaluator/index.js +4 -4
  52. package/esm/evaluator/matchers/all.js +1 -3
  53. package/esm/evaluator/matchers/between.js +1 -3
  54. package/esm/evaluator/matchers/boolean.js +1 -3
  55. package/esm/evaluator/matchers/cont_all.js +1 -3
  56. package/esm/evaluator/matchers/cont_any.js +1 -3
  57. package/esm/evaluator/matchers/cont_str.js +1 -3
  58. package/esm/evaluator/matchers/dependency.js +1 -1
  59. package/esm/evaluator/matchers/eq.js +1 -3
  60. package/esm/evaluator/matchers/eq_set.js +1 -3
  61. package/esm/evaluator/matchers/ew.js +1 -3
  62. package/esm/evaluator/matchers/gte.js +3 -5
  63. package/esm/evaluator/matchers/index.js +12 -2
  64. package/esm/evaluator/matchers/lte.js +3 -5
  65. package/esm/evaluator/matchers/matcherTypes.js +6 -1
  66. package/esm/evaluator/matchers/part_of.js +1 -3
  67. package/esm/evaluator/matchers/segment.js +1 -6
  68. package/esm/evaluator/matchers/semver_between.js +10 -0
  69. package/esm/evaluator/matchers/semver_eq.js +9 -0
  70. package/esm/evaluator/matchers/semver_gte.js +9 -0
  71. package/esm/evaluator/matchers/semver_inlist.js +13 -0
  72. package/esm/evaluator/matchers/semver_lte.js +9 -0
  73. package/esm/evaluator/matchers/string.js +3 -12
  74. package/esm/evaluator/matchers/sw.js +1 -3
  75. package/esm/evaluator/matchers/whitelist.js +4 -5
  76. package/esm/evaluator/matchersTransform/index.js +21 -16
  77. package/esm/evaluator/matchersTransform/whitelist.js +2 -3
  78. package/esm/evaluator/parser/index.js +24 -9
  79. package/esm/logger/constants.js +2 -17
  80. package/esm/logger/index.js +9 -2
  81. package/esm/logger/messages/debug.js +5 -21
  82. package/esm/logger/messages/error.js +2 -1
  83. package/esm/logger/messages/warn.js +1 -1
  84. package/esm/sdkClient/sdkClient.js +1 -6
  85. package/esm/services/splitApi.js +6 -6
  86. package/esm/storages/KeyBuilder.js +2 -1
  87. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +1 -1
  88. package/esm/storages/pluggable/index.js +1 -1
  89. package/esm/utils/Semver.js +100 -0
  90. package/esm/utils/constants/index.js +1 -0
  91. package/esm/utils/labels/index.js +1 -1
  92. package/esm/utils/settingsValidation/index.js +1 -1
  93. package/esm/utils/settingsValidation/logger/pluggableLogger.js +1 -1
  94. package/package.json +1 -2
  95. package/src/dtos/types.ts +34 -1
  96. package/src/evaluator/Engine.ts +5 -6
  97. package/src/evaluator/combiners/ifelseif.ts +3 -3
  98. package/src/evaluator/condition/index.ts +2 -2
  99. package/src/evaluator/index.ts +4 -4
  100. package/src/evaluator/matchers/all.ts +1 -5
  101. package/src/evaluator/matchers/between.ts +3 -7
  102. package/src/evaluator/matchers/boolean.ts +2 -6
  103. package/src/evaluator/matchers/cont_all.ts +1 -5
  104. package/src/evaluator/matchers/cont_any.ts +1 -5
  105. package/src/evaluator/matchers/cont_str.ts +2 -6
  106. package/src/evaluator/matchers/dependency.ts +1 -1
  107. package/src/evaluator/matchers/eq.ts +2 -6
  108. package/src/evaluator/matchers/eq_set.ts +1 -5
  109. package/src/evaluator/matchers/ew.ts +2 -6
  110. package/src/evaluator/matchers/gte.ts +3 -7
  111. package/src/evaluator/matchers/index.ts +29 -19
  112. package/src/evaluator/matchers/lte.ts +3 -7
  113. package/src/evaluator/matchers/matcherTypes.ts +6 -1
  114. package/src/evaluator/matchers/part_of.ts +1 -5
  115. package/src/evaluator/matchers/segment.ts +1 -8
  116. package/src/evaluator/matchers/semver_between.ts +15 -0
  117. package/src/evaluator/matchers/semver_eq.ts +13 -0
  118. package/src/evaluator/matchers/semver_gte.ts +13 -0
  119. package/src/evaluator/matchers/semver_inlist.ts +17 -0
  120. package/src/evaluator/matchers/semver_lte.ts +13 -0
  121. package/src/evaluator/matchers/string.ts +3 -16
  122. package/src/evaluator/matchers/sw.ts +2 -6
  123. package/src/evaluator/matchers/whitelist.ts +5 -7
  124. package/src/evaluator/matchersTransform/index.ts +31 -23
  125. package/src/evaluator/matchersTransform/whitelist.ts +4 -5
  126. package/src/evaluator/parser/index.ts +25 -10
  127. package/src/evaluator/types.ts +3 -3
  128. package/src/logger/constants.ts +2 -17
  129. package/src/logger/index.ts +8 -2
  130. package/src/logger/messages/debug.ts +5 -21
  131. package/src/logger/messages/error.ts +2 -1
  132. package/src/logger/messages/warn.ts +1 -1
  133. package/src/sdkClient/sdkClient.ts +1 -8
  134. package/src/services/splitApi.ts +5 -6
  135. package/src/storages/KeyBuilder.ts +2 -1
  136. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +1 -1
  137. package/src/storages/pluggable/index.ts +1 -1
  138. package/src/types.ts +3 -3
  139. package/src/utils/Semver.ts +111 -0
  140. package/src/utils/constants/index.ts +2 -0
  141. package/src/utils/labels/index.ts +1 -1
  142. package/src/utils/settingsValidation/index.ts +1 -1
  143. package/src/utils/settingsValidation/logger/pluggableLogger.ts +1 -1
  144. package/types/dtos/types.d.ts +26 -1
  145. package/types/evaluator/matchers/all.d.ts +1 -2
  146. package/types/evaluator/matchers/between.d.ts +1 -2
  147. package/types/evaluator/matchers/boolean.d.ts +1 -2
  148. package/types/evaluator/matchers/cont_all.d.ts +1 -2
  149. package/types/evaluator/matchers/cont_any.d.ts +1 -2
  150. package/types/evaluator/matchers/cont_str.d.ts +1 -2
  151. package/types/evaluator/matchers/dependency.d.ts +1 -1
  152. package/types/evaluator/matchers/eq.d.ts +1 -2
  153. package/types/evaluator/matchers/eq_set.d.ts +1 -2
  154. package/types/evaluator/matchers/ew.d.ts +1 -2
  155. package/types/evaluator/matchers/gte.d.ts +1 -2
  156. package/types/evaluator/matchers/lte.d.ts +1 -2
  157. package/types/evaluator/matchers/part_of.d.ts +1 -2
  158. package/types/evaluator/matchers/segment.d.ts +1 -2
  159. package/types/evaluator/matchers/sember_inlist.d.ts +3 -0
  160. package/types/evaluator/matchers/semver_between.d.ts +2 -0
  161. package/types/evaluator/matchers/semver_eq.d.ts +1 -0
  162. package/types/evaluator/matchers/semver_gte.d.ts +1 -0
  163. package/types/evaluator/matchers/semver_inlist.d.ts +1 -0
  164. package/types/evaluator/matchers/semver_lte.d.ts +1 -0
  165. package/types/evaluator/matchers/string.d.ts +1 -2
  166. package/types/evaluator/matchers/sw.d.ts +1 -2
  167. package/types/evaluator/matchers/whitelist.d.ts +1 -3
  168. package/types/evaluator/matchersTransform/set.d.ts +2 -2
  169. package/types/evaluator/matchersTransform/string.d.ts +7 -0
  170. package/types/evaluator/matchersTransform/whitelist.d.ts +3 -3
  171. package/types/evaluator/types.d.ts +3 -3
  172. package/types/logger/constants.d.ts +2 -17
  173. package/types/types.d.ts +3 -3
  174. package/types/utils/constants/index.d.ts +1 -0
  175. package/types/utils/labels/index.d.ts +1 -1
  176. package/types/utils/semVer.d.ts +15 -0
  177. package/types/utils/settingsValidation/logger/globalLogLevel.d.ts +8 -0
  178. package/cjs/evaluator/matchersTransform/set.js +0 -10
  179. package/esm/evaluator/matchersTransform/set.js +0 -6
  180. package/src/evaluator/matchersTransform/set.ts +0 -8
@@ -2,7 +2,8 @@ import * as c from '../constants';
2
2
 
3
3
  export const codesError: [number, string][] = [
4
4
  // evaluator
5
- [c.ERROR_ENGINE_COMBINER_IFELSEIF, c.LOG_PREFIX_ENGINE_COMBINER + 'Invalid feature flag, no valid rules found'],
5
+ [c.ERROR_ENGINE_COMBINER_IFELSEIF, c.LOG_PREFIX_ENGINE_COMBINER + 'Invalid feature flag, no valid rules or unsupported targeting rule type found'],
6
+ [c.ENGINE_MATCHER_ERROR, c.LOG_PREFIX_ENGINE_MATCHER + '[%s] %s'],
6
7
  // SDK
7
8
  [c.ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'],
8
9
  [c.ERROR_CLIENT_CANNOT_GET_READY, 'The SDK will not get ready. Reason: %s'],
@@ -4,7 +4,7 @@ import { codesError } from './error';
4
4
  export const codesWarn: [number, string][] = codesError.concat([
5
5
  // evaluator
6
6
  [c.ENGINE_VALUE_INVALID, c.LOG_PREFIX_ENGINE_VALUE + 'Value %s doesn\'t match with expected type.'],
7
- [c.ENGINE_VALUE_NO_ATTRIBUTES, c.LOG_PREFIX_ENGINE_VALUE + 'Defined attribute [%s], no attributes received.'],
7
+ [c.ENGINE_VALUE_NO_ATTRIBUTES, c.LOG_PREFIX_ENGINE_VALUE + 'Defined attribute `%s`. No attributes received.'],
8
8
  // synchronizer
9
9
  [c.SYNC_MYSEGMENTS_FETCH_RETRY, c.LOG_PREFIX_SYNC_MYSEGMENTS + 'Retrying download of segments #%s. Reason: %s'],
10
10
  [c.SYNC_SPLITS_FETCH_FAILS, c.LOG_PREFIX_SYNC_SPLITS + 'Error while doing fetch of feature flags. %s'],
@@ -35,9 +35,6 @@ export function sdkClientFactory(params: ISdkFactoryContext, isSharedClient?: bo
35
35
  return syncManager ? syncManager.flush() : Promise.resolve();
36
36
  }
37
37
 
38
- // Same promise if `destroy` is called multiple times
39
- let destroyPromise: Promise<void> | undefined;
40
-
41
38
  return objectAssign(
42
39
  // Proto-linkage of the readiness Event Emitter
43
40
  Object.create(sdkReadinessManager.sdkStatus) as IStatusInterface,
@@ -56,8 +53,6 @@ export function sdkClientFactory(params: ISdkFactoryContext, isSharedClient?: bo
56
53
  return __cooldown(__flush, COOLDOWN_TIME_IN_MILLIS);
57
54
  },
58
55
  destroy() {
59
- if (destroyPromise) return destroyPromise;
60
-
61
56
  // Mark the SDK as destroyed immediately
62
57
  sdkReadinessManager.readinessManager.destroy();
63
58
 
@@ -70,7 +65,7 @@ export function sdkClientFactory(params: ISdkFactoryContext, isSharedClient?: bo
70
65
  // Stop background jobs
71
66
  syncManager && syncManager.stop();
72
67
 
73
- destroyPromise = __flush().then(() => {
68
+ return __flush().then(() => {
74
69
  // Cleanup event listeners
75
70
  signalListener && signalListener.stop();
76
71
 
@@ -80,8 +75,6 @@ export function sdkClientFactory(params: ISdkFactoryContext, isSharedClient?: bo
80
75
  // Cleanup storage
81
76
  return storage.destroy();
82
77
  });
83
-
84
- return destroyPromise;
85
78
  }
86
79
  }
87
80
  );
@@ -4,7 +4,7 @@ import { splitHttpClientFactory } from './splitHttpClient';
4
4
  import { ISplitApi } from './types';
5
5
  import { objectAssign } from '../utils/lang/objectAssign';
6
6
  import { ITelemetryTracker } from '../trackers/types';
7
- import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MY_SEGMENT } from '../utils/constants';
7
+ import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MY_SEGMENT, FLAGS_SPEC } from '../utils/constants';
8
8
  import { ERROR_TOO_MANY_SETS } from '../logger/constants';
9
9
 
10
10
  const noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
@@ -44,17 +44,16 @@ export function splitApiFactory(
44
44
  },
45
45
 
46
46
  fetchAuth(userMatchingKeys?: string[]) {
47
- let url = `${urls.auth}/v2/auth`;
48
- if (userMatchingKeys) { // accounting the possibility that `userMatchingKeys` is undefined (server-side API)
47
+ let url = `${urls.auth}/v2/auth?s=${FLAGS_SPEC}`;
48
+ if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
49
49
  const queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
50
- if (queryParams) // accounting the possibility that `userKeys` and thus `queryParams` are empty
51
- url += '?' + queryParams;
50
+ if (queryParams) url += '&' + queryParams;
52
51
  }
53
52
  return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN));
54
53
  },
55
54
 
56
55
  fetchSplitChanges(since: number, noCache?: boolean, till?: number) {
57
- const url = `${urls.sdk}/splitChanges?v=1.0&since=${since}${till ? '&till=' + till : ''}${filterQueryString || ''}`;
56
+ const url = `${urls.sdk}/splitChanges?s=${FLAGS_SPEC}&since=${since}${filterQueryString || ''}${till ? '&till=' + till : ''}`;
58
57
  return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SPLITS))
59
58
  .catch((err) => {
60
59
  if (err.statusCode === 414) settings.log.error(ERROR_TOO_MANY_SETS);
@@ -1,4 +1,5 @@
1
1
  import { ISettings } from '../types';
2
+ import { FLAGS_SPEC } from '../utils/constants';
2
3
  import { startsWith } from '../utils/lang';
3
4
  import { hash } from '../utils/murmur3/murmur3';
4
5
 
@@ -85,5 +86,5 @@ export class KeyBuilder {
85
86
  * The hash is in hexadecimal format (8 characters max, 32 bits).
86
87
  */
87
88
  export function getStorageHash(settings: ISettings) {
88
- return hash(`${settings.core.authorizationKey}::${settings.sync.__splitFiltersValidation.queryString}::1.0`).toString(16);
89
+ return hash(`${settings.core.authorizationKey}::${settings.sync.__splitFiltersValidation.queryString}::${FLAGS_SPEC}`).toString(16);
89
90
  }
@@ -146,7 +146,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
146
146
 
147
147
  // when using a new split query, we must update it at the store
148
148
  if (this.updateNewFilter) {
149
- this.log.info(LOG_PREFIX + 'SDK key or feature flag filter criteria was modified. Updating cache');
149
+ this.log.info(LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
150
150
  const storageHashKey = this.keys.buildHashKey();
151
151
  try {
152
152
  localStorage.setItem(storageHashKey, this.storageHash);
@@ -96,7 +96,7 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
96
96
  return wrapper.get(keys.buildHashKey()).then((hash) => {
97
97
  const currentHash = getStorageHash(settings);
98
98
  if (hash !== currentHash) {
99
- log.info(LOG_PREFIX + 'Storage HASH has changed (SDK key or feature flag filter criteria was modified). Clearing cache');
99
+ log.info(LOG_PREFIX + 'Storage HASH has changed (SDK key, flags filter criteria or flags spec version was modified). Clearing cache');
100
100
  return wrapper.getKeysByPrefix(`${keys.prefix}.`).then(storageKeys => {
101
101
  return Promise.all(storageKeys.map(storageKey => wrapper.del(storageKey)));
102
102
  }).then(() => wrapper.set(keys.buildHashKey(), currentHash));
package/src/types.ts CHANGED
@@ -353,7 +353,7 @@ interface INodeBasicSettings extends ISharedSettings {
353
353
  IPAddressesEnabled?: boolean
354
354
  },
355
355
  /**
356
- * Defines which kind of storage we should instanciate.
356
+ * Defines which kind of storage we should instantiate.
357
357
  * @property {Object} storage
358
358
  */
359
359
  storage?: (params: any) => any,
@@ -918,7 +918,7 @@ export namespace SplitIO {
918
918
  */
919
919
  features?: MockedFeaturesMap,
920
920
  /**
921
- * Defines which kind of storage we should instanciate.
921
+ * Defines which kind of storage we should instantiate.
922
922
  * @property {Object} storage
923
923
  */
924
924
  storage?: (params: IStorageFactoryParams) => IStorageSync | IStorageAsync,
@@ -944,7 +944,7 @@ export namespace SplitIO {
944
944
  */
945
945
  urls?: UrlSettings,
946
946
  /**
947
- * Defines which kind of storage we should instanciate.
947
+ * Defines which kind of storage we should instantiate.
948
948
  * @property {Object} storage
949
949
  */
950
950
  storage?: (params: IStorageFactoryParams) => IStorageSync,
@@ -0,0 +1,111 @@
1
+ import { isString } from '../utils/lang';
2
+
3
+ const NUMERIC_IDENTIFIER_REGEX = /^[0-9]+$/;
4
+
5
+ const METADATA_DELIMITER = '+';
6
+ const PRERELEASE_DELIMITER = '-';
7
+ const VALUE_DELIMITER = '.';
8
+
9
+ /**
10
+ * Compares two strings. If both strings are numeric identifiers, they are compared numerically. Otherwise, they are compared lexicographically.
11
+ * This could be implemented using `a.localeCompare(b, undefined, { numeric: true })` but locale options are not broadly supported.
12
+ */
13
+ function compareStrings(a: string, b: string): number {
14
+ if (NUMERIC_IDENTIFIER_REGEX.test(a) && NUMERIC_IDENTIFIER_REGEX.test(b)) {
15
+ const result = a.length - b.length;
16
+ if (result !== 0) {
17
+ return result;
18
+ }
19
+ }
20
+ return a < b ? -1 : a > b ? 1 : 0;
21
+ }
22
+
23
+ // Sanitizes a numeric identifier by removing leading zeros
24
+ function sanitizeNumericIdentifier(value: string): string {
25
+ return value.replace(/^0+(?=\d)/, '');
26
+ }
27
+
28
+ function throwError(version: string) {
29
+ throw new Error('Unable to convert to Semver, incorrect format: ' + version);
30
+ }
31
+
32
+ export class Semver {
33
+
34
+ private readonly _major: string;
35
+ private readonly _minor: string;
36
+ private readonly _patch: string;
37
+ private readonly _preRelease: string[];
38
+ private readonly _isStable: boolean;
39
+
40
+ // Version string for 'equal' and 'in list' comparisons
41
+ public readonly version: string;
42
+
43
+ public constructor(version: string) {
44
+ if (!isString(version)) throwError(version);
45
+
46
+ // Separate metadata if exists
47
+ let index = version.indexOf(METADATA_DELIMITER);
48
+ let [vWithoutMetadata, metadata] = index === -1 ? [version] : [version.slice(0, index), version.slice(index + 1)];
49
+ if (metadata === '') throwError(version);
50
+
51
+ // Set pre-release versions if exists
52
+ index = vWithoutMetadata.indexOf(PRERELEASE_DELIMITER);
53
+ if (index === -1) {
54
+ this._isStable = true;
55
+ this._preRelease = [];
56
+ } else {
57
+ this._isStable = false;
58
+ this._preRelease = vWithoutMetadata.slice(index + 1).split(VALUE_DELIMITER).map((value) => {
59
+ if (!value) throwError(version);
60
+ return NUMERIC_IDENTIFIER_REGEX.test(value) ?
61
+ sanitizeNumericIdentifier(value) :
62
+ value;
63
+ });
64
+ vWithoutMetadata = vWithoutMetadata.slice(0, index);
65
+ }
66
+
67
+ // Set major, minor, and patch versions
68
+ const vParts = vWithoutMetadata.split(VALUE_DELIMITER).map((value) => {
69
+ if (!value || !NUMERIC_IDENTIFIER_REGEX.test(value)) throwError(version);
70
+ return sanitizeNumericIdentifier(value);
71
+ });
72
+
73
+ if (vParts.length !== 3) throwError(version);
74
+ this._major = vParts[0];
75
+ this._minor = vParts[1];
76
+ this._patch = vParts[2];
77
+
78
+ // Set version string
79
+ this.version = vParts.join(VALUE_DELIMITER);
80
+ if (this._preRelease.length) this.version += PRERELEASE_DELIMITER + this._preRelease.join(VALUE_DELIMITER);
81
+ if (metadata) this.version += METADATA_DELIMITER + metadata;
82
+ }
83
+
84
+ /**
85
+ * Precedence comparision between 2 Semver objects.
86
+ *
87
+ * @return `0` if `this === toCompare`, `-1` if `this < toCompare`, and `1` if `this > toCompare`
88
+ */
89
+ public compare(toCompare: Semver): number {
90
+ if (this.version === toCompare.version) return 0;
91
+
92
+ let result = compareStrings(this._major, toCompare._major);
93
+ if (result !== 0) return result;
94
+
95
+ result = compareStrings(this._minor, toCompare._minor);
96
+ if (result !== 0) return result;
97
+
98
+ result = compareStrings(this._patch, toCompare._patch);
99
+ if (result !== 0) return result;
100
+
101
+ if (!this._isStable && toCompare._isStable) return -1;
102
+ if (this._isStable && !toCompare._isStable) return 1;
103
+
104
+ for (let i = 0, length = Math.min(this._preRelease.length, toCompare._preRelease.length); i < length; i++) {
105
+ const result = compareStrings(this._preRelease[i], toCompare._preRelease[i]);
106
+ if (result !== 0) return result;
107
+ }
108
+
109
+ return this._preRelease.length - toCompare._preRelease.length;
110
+ }
111
+ }
@@ -104,3 +104,5 @@ export const NON_REQUESTED = 1;
104
104
  export const DISABLED = 0;
105
105
  export const ENABLED = 1;
106
106
  export const PAUSED = 2;
107
+
108
+ export const FLAGS_SPEC = '1.1';
@@ -5,4 +5,4 @@ export const SDK_NOT_READY = 'not ready';
5
5
  export const EXCEPTION = 'exception';
6
6
  export const SPLIT_ARCHIVED = 'archived';
7
7
  export const NOT_IN_SPLIT = 'not in split';
8
- export const UNSUPPORTED_MATCHER_TYPE = 'unsupported matcher type';
8
+ export const UNSUPPORTED_MATCHER_TYPE = 'targeting rule type unsupported by sdk';
@@ -61,7 +61,7 @@ export const base = {
61
61
  telemetry: 'https://telemetry.split.io/api',
62
62
  },
63
63
 
64
- // Defines which kind of storage we should instanciate.
64
+ // Defines which kind of storage we should instantiate.
65
65
  storage: undefined,
66
66
 
67
67
  // Defines if the logs are enabled, SDK wide.
@@ -4,7 +4,7 @@ import { LogLevel } from '../../../types';
4
4
  import { getLogLevel } from './commons';
5
5
 
6
6
  function isLogger(log: any): log is ILogger {
7
- return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function' && typeof log.setLogLevel === 'function';
7
+ return log !== null && typeof log === 'object' && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function' && typeof log.setLogLevel === 'function';
8
8
  }
9
9
 
10
10
  // By default it starts disabled.
@@ -11,6 +11,10 @@ export interface IBetweenMatcherData {
11
11
  start: number;
12
12
  end: number;
13
13
  }
14
+ export interface IBetweenStringMatcherData {
15
+ start: string;
16
+ end: string;
17
+ }
14
18
  export interface IWhitelistMatcherData {
15
19
  whitelist: string[];
16
20
  }
@@ -35,6 +39,7 @@ interface ISplitMatcherBase {
35
39
  dependencyMatcherData?: null | IDependencyMatcherData;
36
40
  booleanMatcherData?: null | boolean;
37
41
  stringMatcherData?: null | string;
42
+ betweenStringMatcherData?: null | IBetweenStringMatcherData;
38
43
  }
39
44
  interface IAllKeysMatcher extends ISplitMatcherBase {
40
45
  matcherType: 'ALL_KEYS';
@@ -103,7 +108,27 @@ interface IMatchesStringMatcher extends ISplitMatcherBase {
103
108
  matcherType: 'MATCHES_STRING';
104
109
  stringMatcherData: string;
105
110
  }
106
- export declare type ISplitMatcher = IAllKeysMatcher | IInSegmentMatcher | IWhitelistMatcher | IEqualToMatcher | IGreaterThanOrEqualToMatcher | ILessThanOrEqualToMatcher | IBetweenMatcher | IEqualToSetMatcher | IContainsAnyOfSetMatcher | IContainsAllOfSetMatcher | IPartOfSetMatcher | IStartsWithMatcher | IEndsWithMatcher | IContainsStringMatcher | IInSplitTreatmentMatcher | IEqualToBooleanMatcher | IMatchesStringMatcher;
111
+ interface IEqualToSemverMatcher extends ISplitMatcherBase {
112
+ matcherType: 'EQUAL_TO_SEMVER';
113
+ stringMatcherData: string;
114
+ }
115
+ interface IGreaterThanOrEqualToSemverMatcher extends ISplitMatcherBase {
116
+ matcherType: 'GREATER_THAN_OR_EQUAL_TO_SEMVER';
117
+ stringMatcherData: string;
118
+ }
119
+ interface ILessThanOrEqualToSemverMatcher extends ISplitMatcherBase {
120
+ matcherType: 'LESS_THAN_OR_EQUAL_TO_SEMVER';
121
+ stringMatcherData: string;
122
+ }
123
+ interface IBetweenSemverMatcher extends ISplitMatcherBase {
124
+ matcherType: 'BETWEEN_SEMVER';
125
+ betweenStringMatcherData: IBetweenStringMatcherData;
126
+ }
127
+ interface IInListSemverMatcher extends ISplitMatcherBase {
128
+ matcherType: 'IN_LIST_SEMVER';
129
+ whitelistMatcherData: IWhitelistMatcherData;
130
+ }
131
+ export declare type ISplitMatcher = IAllKeysMatcher | IInSegmentMatcher | IWhitelistMatcher | IEqualToMatcher | IGreaterThanOrEqualToMatcher | ILessThanOrEqualToMatcher | IBetweenMatcher | IEqualToSetMatcher | IContainsAnyOfSetMatcher | IContainsAllOfSetMatcher | IPartOfSetMatcher | IStartsWithMatcher | IEndsWithMatcher | IContainsStringMatcher | IInSplitTreatmentMatcher | IEqualToBooleanMatcher | IMatchesStringMatcher | IEqualToSemverMatcher | IGreaterThanOrEqualToSemverMatcher | ILessThanOrEqualToSemverMatcher | IBetweenSemverMatcher | IInListSemverMatcher;
107
132
  /** Split object */
108
133
  export interface ISplitPartition {
109
134
  treatment: string;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function allMatcherContext(log: ILogger): (runtimeAttr: string) => boolean;
1
+ export declare function allMatcherContext(): (runtimeAttr: string) => boolean;
@@ -1,3 +1,2 @@
1
1
  import { IBetweenMatcherData } from '../../dtos/types';
2
- import { ILogger } from '../../logger/types';
3
- export declare function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatcherData): (runtimeAttr: number) => boolean;
2
+ export declare function betweenMatcherContext(ruleVO: IBetweenMatcherData): (runtimeAttr: number) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function booleanMatcherContext(log: ILogger, ruleAttr: boolean): (runtimeAttr: boolean) => boolean;
1
+ export declare function booleanMatcherContext(ruleAttr: boolean): (runtimeAttr: boolean) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function containsAllSetMatcherContext(log: ILogger, ruleAttr: string[]): (runtimeAttr: string[]) => boolean;
1
+ export declare function containsAllSetMatcherContext(ruleAttr: string[]): (runtimeAttr: string[]) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function containsAnySetMatcherContext(log: ILogger, ruleAttr: string[]): (runtimeAttr: string[]) => boolean;
1
+ export declare function containsAnySetMatcherContext(ruleAttr: string[]): (runtimeAttr: string[]) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function containsStringMatcherContext(log: ILogger, ruleAttr: string[]): (runtimeAttr: string) => boolean;
1
+ export declare function containsStringMatcherContext(ruleAttr: string[]): (runtimeAttr: string) => boolean;
@@ -2,4 +2,4 @@ import { IDependencyMatcherData, MaybeThenable } from '../../dtos/types';
2
2
  import { IStorageAsync, IStorageSync } from '../../storages/types';
3
3
  import { ILogger } from '../../logger/types';
4
4
  import { IDependencyMatcherValue, ISplitEvaluator } from '../types';
5
- export declare function dependencyMatcherContext(log: ILogger, { split, treatments }: IDependencyMatcherData, storage: IStorageSync | IStorageAsync): ({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator) => MaybeThenable<boolean>;
5
+ export declare function dependencyMatcherContext({ split, treatments }: IDependencyMatcherData, storage: IStorageSync | IStorageAsync, log: ILogger): ({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator) => MaybeThenable<boolean>;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function equalToMatcherContext(log: ILogger, ruleAttr: number): (runtimeAttr: number) => boolean;
1
+ export declare function equalToMatcherContext(ruleAttr: number): (runtimeAttr: number) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function equalToSetMatcherContext(log: ILogger, ruleAttr: string[]): (runtimeAttr: string[]) => boolean;
1
+ export declare function equalToSetMatcherContext(ruleAttr: string[]): (runtimeAttr: string[]) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function endsWithMatcherContext(log: ILogger, ruleAttr: string[]): (runtimeAttr: string) => boolean;
1
+ export declare function endsWithMatcherContext(ruleAttr: string[]): (runtimeAttr: string) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: number): (runtimeAttr: number) => boolean;
1
+ export declare function greaterThanEqualMatcherContext(ruleAttr: number): (runtimeAttr: number) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function lessThanEqualMatcherContext(log: ILogger, ruleAttr: number): (runtimeAttr: number) => boolean;
1
+ export declare function lessThanEqualMatcherContext(ruleAttr: number): (runtimeAttr: number) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function partOfSetMatcherContext(log: ILogger, ruleAttr: string[]): (runtimeAttr: string[]) => boolean;
1
+ export declare function partOfSetMatcherContext(ruleAttr: string[]): (runtimeAttr: string[]) => boolean;
@@ -1,6 +1,5 @@
1
1
  import { MaybeThenable } from '../../dtos/types';
2
2
  import { ISegmentsCacheBase } from '../../storages/types';
3
- import { ILogger } from '../../logger/types';
4
- export declare function segmentMatcherContext(log: ILogger, segmentName: string, storage: {
3
+ export declare function segmentMatcherContext(segmentName: string, storage: {
5
4
  segments: ISegmentsCacheBase;
6
5
  }): (key: string) => MaybeThenable<boolean>;
@@ -0,0 +1,3 @@
1
+ import { ISet } from '../../utils/lang/sets';
2
+ import { ILogger } from '../../logger/types';
3
+ export declare function inListSemverMatcherContext(log: ILogger, ruleAttr: ISet<string>): (runtimeAttr: string) => boolean;
@@ -0,0 +1,2 @@
1
+ import { IBetweenStringMatcherData } from '../../dtos/types';
2
+ export declare function betweenSemverMatcherContext(ruleAttr: IBetweenStringMatcherData): (runtimeAttr: string) => boolean;
@@ -0,0 +1 @@
1
+ export declare function equalToSemverMatcherContext(ruleAttr: string): (runtimeAttr: string) => boolean;
@@ -0,0 +1 @@
1
+ export declare function greaterThanEqualToSemverMatcherContext(ruleAttr: string): (runtimeAttr: string) => boolean;
@@ -0,0 +1 @@
1
+ export declare function inListSemverMatcherContext(ruleAttr: string[]): (runtimeAttr: string) => boolean;
@@ -0,0 +1 @@
1
+ export declare function lessThanEqualToSemverMatcherContext(ruleAttr: string): (runtimeAttr: string) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function stringMatcherContext(log: ILogger, ruleAttr: string): (runtimeAttr: string) => boolean;
1
+ export declare function stringMatcherContext(ruleAttr: string): (runtimeAttr: string) => boolean;
@@ -1,2 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- export declare function startsWithMatcherContext(log: ILogger, ruleAttr: string[]): (runtimeAttr: string) => boolean;
1
+ export declare function startsWithMatcherContext(ruleAttr: string[]): (runtimeAttr: string) => boolean;
@@ -1,3 +1 @@
1
- import { ISet } from '../../utils/lang/sets';
2
- import { ILogger } from '../../logger/types';
3
- export declare function whitelistMatcherContext(log: ILogger, ruleAttr: ISet<string>): (runtimeAttr: string) => boolean;
1
+ export declare function whitelistMatcherContext(ruleAttr: string[]): (runtimeAttr: string) => boolean;
@@ -1,5 +1,5 @@
1
- import { IWhitelistMatcherData } from '../../dtos/types';
1
+ import { ISplitMatcher } from '../../dtos/types';
2
2
  /**
3
3
  * Extract whitelist array. Used by set and string matchers
4
4
  */
5
- export declare function setTransform(whitelistObject: IWhitelistMatcherData): string[];
5
+ export declare function setTransform(whitelistObject: ISplitMatcher['whitelistMatcherData']): string[] | null | undefined;
@@ -0,0 +1,7 @@
1
+ import { ISplitMatcher } from '../../dtos/types';
2
+ /**
3
+ * Extract value from string matcher data.
4
+ */
5
+ export declare function stringTransform({ stringMatcherData }: ISplitMatcher): {
6
+ value: string | null | undefined;
7
+ };
@@ -1,5 +1,5 @@
1
- import { IWhitelistMatcherData } from '../../dtos/types';
1
+ import { ISplitMatcher } from '../../dtos/types';
2
2
  /**
3
- * Extract whitelist as a set. Used by 'WHITELIST' matcher.
3
+ * Extract whitelist array.
4
4
  */
5
- export declare function whitelistTransform(whitelistObject: IWhitelistMatcherData): import("../../utils/lang/sets").ISet<string>;
5
+ export declare function whitelistTransform(whitelistObject: ISplitMatcher['whitelistMatcherData']): string[] | null | undefined;
@@ -1,6 +1,5 @@
1
- import { IBetweenMatcherData, IDependencyMatcherData, MaybeThenable } from '../dtos/types';
1
+ import { IBetweenMatcherData, IBetweenStringMatcherData, IDependencyMatcherData, MaybeThenable } from '../dtos/types';
2
2
  import { IStorageAsync, IStorageSync } from '../storages/types';
3
- import { ISet } from '../utils/lang/sets';
4
3
  import { SplitIO } from '../types';
5
4
  import { ILogger } from '../logger/types';
6
5
  export interface IDependencyMatcherValue {
@@ -9,7 +8,8 @@ export interface IDependencyMatcherValue {
9
8
  }
10
9
  export interface IMatcherDto {
11
10
  type: number;
12
- value?: string | number | boolean | string[] | IDependencyMatcherData | ISet<string> | IBetweenMatcherData | null;
11
+ name: string;
12
+ value?: string | number | boolean | string[] | IDependencyMatcherData | IBetweenMatcherData | IBetweenStringMatcherData | null;
13
13
  attribute: string | null;
14
14
  negate: boolean;
15
15
  dataType: string;
@@ -9,25 +9,8 @@ export declare const ENGINE_COMBINER_AND = 0;
9
9
  export declare const ENGINE_COMBINER_IFELSEIF = 1;
10
10
  export declare const ENGINE_COMBINER_IFELSEIF_NO_TREATMENT = 2;
11
11
  export declare const ENGINE_BUCKET = 3;
12
- export declare const ENGINE_MATCHER_ALL = 4;
13
- export declare const ENGINE_MATCHER_BETWEEN = 5;
14
- export declare const ENGINE_MATCHER_BOOLEAN = 6;
15
- export declare const ENGINE_MATCHER_CONTAINS_ALL = 7;
16
- export declare const ENGINE_MATCHER_CONTAINS_ANY = 8;
17
- export declare const ENGINE_MATCHER_CONTAINS_STRING = 9;
18
12
  export declare const ENGINE_MATCHER_DEPENDENCY = 10;
19
13
  export declare const ENGINE_MATCHER_DEPENDENCY_PRE = 11;
20
- export declare const ENGINE_MATCHER_EQUAL = 12;
21
- export declare const ENGINE_MATCHER_EQUAL_TO_SET = 13;
22
- export declare const ENGINE_MATCHER_ENDS_WITH = 14;
23
- export declare const ENGINE_MATCHER_GREATER = 15;
24
- export declare const ENGINE_MATCHER_LESS = 16;
25
- export declare const ENGINE_MATCHER_PART_OF = 17;
26
- export declare const ENGINE_MATCHER_SEGMENT = 18;
27
- export declare const ENGINE_MATCHER_STRING = 19;
28
- export declare const ENGINE_MATCHER_STRING_INVALID = 20;
29
- export declare const ENGINE_MATCHER_STARTS_WITH = 21;
30
- export declare const ENGINE_MATCHER_WHITELIST = 22;
31
14
  export declare const ENGINE_VALUE = 23;
32
15
  export declare const ENGINE_SANITIZE = 24;
33
16
  export declare const CLEANUP_REGISTERING = 25;
@@ -45,6 +28,7 @@ export declare const SYNC_TASK_START = 36;
45
28
  export declare const SYNC_TASK_EXECUTE = 37;
46
29
  export declare const SYNC_TASK_STOP = 38;
47
30
  export declare const SETTINGS_SPLITS_FILTER = 39;
31
+ export declare const ENGINE_MATCHER_RESULT = 40;
48
32
  export declare const CLIENT_READY_FROM_CACHE = 100;
49
33
  export declare const CLIENT_READY = 101;
50
34
  export declare const IMPRESSION = 102;
@@ -128,6 +112,7 @@ export declare const ERROR_NOT_BOOLEAN = 325;
128
112
  export declare const ERROR_MIN_CONFIG_PARAM = 326;
129
113
  export declare const ERROR_TOO_MANY_SETS = 327;
130
114
  export declare const ERROR_SETS_FILTER_EXCLUSIVE = 328;
115
+ export declare const ENGINE_MATCHER_ERROR = 329;
131
116
  export declare const LOG_PREFIX_SETTINGS = "settings";
132
117
  export declare const LOG_PREFIX_INSTANTIATION = "Factory instantiation";
133
118
  export declare const LOG_PREFIX_ENGINE = "engine";
package/types/types.d.ts CHANGED
@@ -347,7 +347,7 @@ interface INodeBasicSettings extends ISharedSettings {
347
347
  IPAddressesEnabled?: boolean;
348
348
  };
349
349
  /**
350
- * Defines which kind of storage we should instanciate.
350
+ * Defines which kind of storage we should instantiate.
351
351
  * @property {Object} storage
352
352
  */
353
353
  storage?: (params: any) => any;
@@ -915,7 +915,7 @@ export declare namespace SplitIO {
915
915
  */
916
916
  features?: MockedFeaturesMap;
917
917
  /**
918
- * Defines which kind of storage we should instanciate.
918
+ * Defines which kind of storage we should instantiate.
919
919
  * @property {Object} storage
920
920
  */
921
921
  storage?: (params: IStorageFactoryParams) => IStorageSync | IStorageAsync;
@@ -941,7 +941,7 @@ export declare namespace SplitIO {
941
941
  */
942
942
  urls?: UrlSettings;
943
943
  /**
944
- * Defines which kind of storage we should instanciate.
944
+ * Defines which kind of storage we should instantiate.
945
945
  * @property {Object} storage
946
946
  */
947
947
  storage?: (params: IStorageFactoryParams) => IStorageSync;
@@ -78,3 +78,4 @@ export declare const NON_REQUESTED = 1;
78
78
  export declare const DISABLED = 0;
79
79
  export declare const ENABLED = 1;
80
80
  export declare const PAUSED = 2;
81
+ export declare const FLAGS_SPEC = "1.1";
@@ -5,4 +5,4 @@ export declare const SDK_NOT_READY = "not ready";
5
5
  export declare const EXCEPTION = "exception";
6
6
  export declare const SPLIT_ARCHIVED = "archived";
7
7
  export declare const NOT_IN_SPLIT = "not in split";
8
- export declare const UNSUPPORTED_MATCHER_TYPE = "unsupported matcher type";
8
+ export declare const UNSUPPORTED_MATCHER_TYPE = "targeting rule type unsupported by sdk";
@@ -0,0 +1,15 @@
1
+ export declare class Semver {
2
+ private readonly _major;
3
+ private readonly _minor;
4
+ private readonly _patch;
5
+ private readonly _preRelease;
6
+ private readonly _isStable;
7
+ readonly version: string;
8
+ constructor(version: string);
9
+ /**
10
+ * Precedence comparision between 2 Semver objects.
11
+ *
12
+ * @return `0` if `this === toCompare`, `-1` if `this < toCompare`, and `1` if `this > toCompare`
13
+ */
14
+ compare(toCompare: Semver): number;
15
+ }
@@ -0,0 +1,8 @@
1
+ import { LogLevel } from '../../../types';
2
+ /**
3
+ * The debug level can be set globally via the `localStorage.splitio_debug` item in browser, or the `SPLITIO_DEBUG` env var in NodeJS.
4
+ * Acceptable values are: 'DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE'.
5
+ * Other acceptable values are 'on', 'enable' and 'enabled', which are equivalent to 'DEBUG'.
6
+ * Any other value, like undefined, null or an invalid string, returns `undefined` and means that the global log level is not set.
7
+ */
8
+ export declare function getGlobalLogLevel(): LogLevel | undefined;