@splitsoftware/splitio-commons 1.13.2-rc.1 → 1.13.2-rc.3

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 (70) hide show
  1. package/CHANGES.txt +0 -1
  2. package/cjs/evaluator/matchers/gte.js +3 -3
  3. package/cjs/evaluator/matchers/index.js +11 -1
  4. package/cjs/evaluator/matchers/matcherTypes.js +6 -1
  5. package/cjs/evaluator/matchers/semver_between.js +14 -0
  6. package/cjs/evaluator/matchers/semver_eq.js +12 -0
  7. package/cjs/evaluator/matchers/semver_gte.js +12 -0
  8. package/cjs/evaluator/matchers/semver_inlist.js +14 -0
  9. package/cjs/evaluator/matchers/semver_lte.js +12 -0
  10. package/cjs/evaluator/matchersTransform/index.js +20 -13
  11. package/cjs/services/splitApi.js +1 -1
  12. package/cjs/storages/KeyBuilder.js +2 -3
  13. package/cjs/utils/Semver.js +100 -0
  14. package/cjs/utils/constants/index.js +1 -2
  15. package/cjs/utils/settingsValidation/logger/pluggableLogger.js +1 -1
  16. package/esm/evaluator/matchers/gte.js +3 -3
  17. package/esm/evaluator/matchers/index.js +11 -1
  18. package/esm/evaluator/matchers/matcherTypes.js +6 -1
  19. package/esm/evaluator/matchers/semver_between.js +10 -0
  20. package/esm/evaluator/matchers/semver_eq.js +8 -0
  21. package/esm/evaluator/matchers/semver_gte.js +8 -0
  22. package/esm/evaluator/matchers/semver_inlist.js +10 -0
  23. package/esm/evaluator/matchers/semver_lte.js +8 -0
  24. package/esm/evaluator/matchersTransform/index.js +20 -13
  25. package/esm/services/splitApi.js +2 -2
  26. package/esm/storages/KeyBuilder.js +2 -3
  27. package/esm/utils/Semver.js +97 -0
  28. package/esm/utils/constants/index.js +0 -1
  29. package/esm/utils/settingsValidation/logger/pluggableLogger.js +1 -1
  30. package/package.json +1 -2
  31. package/src/dtos/types.ts +34 -1
  32. package/src/evaluator/matchers/between.ts +1 -1
  33. package/src/evaluator/matchers/boolean.ts +1 -1
  34. package/src/evaluator/matchers/cont_all.ts +1 -1
  35. package/src/evaluator/matchers/cont_any.ts +1 -1
  36. package/src/evaluator/matchers/cont_str.ts +1 -1
  37. package/src/evaluator/matchers/eq.ts +1 -1
  38. package/src/evaluator/matchers/eq_set.ts +1 -1
  39. package/src/evaluator/matchers/ew.ts +1 -1
  40. package/src/evaluator/matchers/gte.ts +4 -4
  41. package/src/evaluator/matchers/index.ts +28 -18
  42. package/src/evaluator/matchers/lte.ts +1 -1
  43. package/src/evaluator/matchers/matcherTypes.ts +6 -1
  44. package/src/evaluator/matchers/part_of.ts +1 -1
  45. package/src/evaluator/matchers/semver_between.ts +18 -0
  46. package/src/evaluator/matchers/semver_eq.ts +13 -0
  47. package/src/evaluator/matchers/semver_gte.ts +13 -0
  48. package/src/evaluator/matchers/semver_inlist.ts +15 -0
  49. package/src/evaluator/matchers/semver_lte.ts +13 -0
  50. package/src/evaluator/matchers/string.ts +1 -1
  51. package/src/evaluator/matchers/sw.ts +1 -1
  52. package/src/evaluator/matchers/whitelist.ts +1 -1
  53. package/src/evaluator/matchersTransform/index.ts +32 -21
  54. package/src/evaluator/types.ts +2 -2
  55. package/src/services/splitApi.ts +2 -2
  56. package/src/storages/KeyBuilder.ts +2 -3
  57. package/src/utils/Semver.ts +107 -0
  58. package/src/utils/constants/index.ts +0 -2
  59. package/src/utils/settingsValidation/logger/pluggableLogger.ts +1 -1
  60. package/types/dtos/types.d.ts +26 -1
  61. package/types/evaluator/matchers/sember_inlist.d.ts +3 -0
  62. package/types/evaluator/matchers/semver_between.d.ts +3 -0
  63. package/types/evaluator/matchers/semver_eq.d.ts +2 -0
  64. package/types/evaluator/matchers/semver_gte.d.ts +2 -0
  65. package/types/evaluator/matchers/semver_inlist.d.ts +3 -0
  66. package/types/evaluator/matchers/semver_lte.d.ts +2 -0
  67. package/types/evaluator/types.d.ts +2 -2
  68. package/types/storages/KeyBuilder.d.ts +1 -1
  69. package/types/utils/constants/index.d.ts +0 -1
  70. package/types/utils/semVer.d.ts +15 -0
@@ -0,0 +1,97 @@
1
+ var NUMERIC_IDENTIFIER_REGEX = /^[0-9]+$/;
2
+ var METADATA_DELIMITER = '+';
3
+ var PRERELEASE_DELIMITER = '-';
4
+ var VALUE_DELIMITER = '.';
5
+ /**
6
+ * Compares two strings. If both strings are numeric identifiers, they are compared numerically. Otherwise, they are compared lexicographically.
7
+ * This could be implemented using `a.localeCompare(b, undefined, { numeric: true })` but locale options are not broadly supported.
8
+ */
9
+ function compareStrings(a, b) {
10
+ if (NUMERIC_IDENTIFIER_REGEX.test(a) && NUMERIC_IDENTIFIER_REGEX.test(b)) {
11
+ var result = a.length - b.length;
12
+ if (result !== 0) {
13
+ return result;
14
+ }
15
+ }
16
+ return a < b ? -1 : a > b ? 1 : 0;
17
+ }
18
+ // Sanitizes a numeric identifier by removing leading zeros
19
+ function sanitizeNumericIdentifier(value) {
20
+ return value.replace(/^0+(?=\d)/, '');
21
+ }
22
+ function throwError(version) {
23
+ throw new Error('Unable to convert to Semver, incorrect format: ' + version);
24
+ }
25
+ var Semver = /** @class */ (function () {
26
+ function Semver(version) {
27
+ // Separate metadata if exists
28
+ var index = version.indexOf(METADATA_DELIMITER);
29
+ var _a = index === -1 ? [version] : [version.slice(0, index), version.slice(index + 1)], vWithoutMetadata = _a[0], metadata = _a[1];
30
+ if (metadata === '')
31
+ throwError(version);
32
+ // Set pre-release versions if exists
33
+ index = vWithoutMetadata.indexOf(PRERELEASE_DELIMITER);
34
+ if (index === -1) {
35
+ this._isStable = true;
36
+ this._preRelease = [];
37
+ }
38
+ else {
39
+ this._isStable = false;
40
+ this._preRelease = vWithoutMetadata.slice(index + 1).split(VALUE_DELIMITER).map(function (value) {
41
+ if (!value)
42
+ throwError(version);
43
+ return NUMERIC_IDENTIFIER_REGEX.test(value) ?
44
+ sanitizeNumericIdentifier(value) :
45
+ value;
46
+ });
47
+ vWithoutMetadata = vWithoutMetadata.slice(0, index);
48
+ }
49
+ // Set major, minor, and patch versions
50
+ var vParts = vWithoutMetadata.split(VALUE_DELIMITER).map(function (value) {
51
+ if (!value || !NUMERIC_IDENTIFIER_REGEX.test(value))
52
+ throwError(version);
53
+ return sanitizeNumericIdentifier(value);
54
+ });
55
+ if (vParts.length !== 3)
56
+ throwError(version);
57
+ this._major = vParts[0];
58
+ this._minor = vParts[1];
59
+ this._patch = vParts[2];
60
+ // Set version string
61
+ this.version = vParts.join(VALUE_DELIMITER);
62
+ if (this._preRelease.length)
63
+ this.version += PRERELEASE_DELIMITER + this._preRelease.join(VALUE_DELIMITER);
64
+ if (metadata)
65
+ this.version += METADATA_DELIMITER + metadata;
66
+ }
67
+ /**
68
+ * Precedence comparision between 2 Semver objects.
69
+ *
70
+ * @return `0` if `this === toCompare`, `-1` if `this < toCompare`, and `1` if `this > toCompare`
71
+ */
72
+ Semver.prototype.compare = function (toCompare) {
73
+ if (this.version === toCompare.version)
74
+ return 0;
75
+ var result = compareStrings(this._major, toCompare._major);
76
+ if (result !== 0)
77
+ return result;
78
+ result = compareStrings(this._minor, toCompare._minor);
79
+ if (result !== 0)
80
+ return result;
81
+ result = compareStrings(this._patch, toCompare._patch);
82
+ if (result !== 0)
83
+ return result;
84
+ if (!this._isStable && toCompare._isStable)
85
+ return -1;
86
+ if (this._isStable && !toCompare._isStable)
87
+ return 1;
88
+ for (var i = 0, length_1 = Math.min(this._preRelease.length, toCompare._preRelease.length); i < length_1; i++) {
89
+ var result_1 = compareStrings(this._preRelease[i], toCompare._preRelease[i]);
90
+ if (result_1 !== 0)
91
+ return result_1;
92
+ }
93
+ return this._preRelease.length - toCompare._preRelease.length;
94
+ };
95
+ return Semver;
96
+ }());
97
+ export { Semver };
@@ -86,4 +86,3 @@ export var NON_REQUESTED = 1;
86
86
  export var DISABLED = 0;
87
87
  export var ENABLED = 1;
88
88
  export var PAUSED = 2;
89
- export var FLAGS_SPEC = '1.1';
@@ -1,7 +1,7 @@
1
1
  import { Logger, LogLevels } from '../../../logger';
2
2
  import { getLogLevel } from './commons';
3
3
  function isLogger(log) {
4
- return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function' && typeof log.setLogLevel === 'function';
4
+ 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';
5
5
  }
6
6
  // By default it starts disabled.
7
7
  var initialLogLevel = LogLevels.NONE;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.13.2-rc.1",
3
+ "version": "1.13.2-rc.3",
4
4
  "description": "Split JavaScript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -63,7 +63,6 @@
63
63
  "@typescript-eslint/eslint-plugin": "^6.6.0",
64
64
  "@typescript-eslint/parser": "^6.6.0",
65
65
  "cross-env": "^7.0.2",
66
- "csv-streamify": "^4.0.0",
67
66
  "eslint": "^8.48.0",
68
67
  "eslint-plugin-compat": "^4.2.0",
69
68
  "eslint-plugin-import": "^2.25.3",
package/src/dtos/types.ts CHANGED
@@ -17,6 +17,11 @@ export interface IBetweenMatcherData {
17
17
  end: number
18
18
  }
19
19
 
20
+ export interface IBetweenStringMatcherData {
21
+ start: string
22
+ end: string
23
+ }
24
+
20
25
  export interface IWhitelistMatcherData {
21
26
  whitelist: string[]
22
27
  }
@@ -44,6 +49,7 @@ interface ISplitMatcherBase {
44
49
  dependencyMatcherData?: null | IDependencyMatcherData
45
50
  booleanMatcherData?: null | boolean
46
51
  stringMatcherData?: null | string
52
+ betweenStringMatcherData?: null | IBetweenStringMatcherData
47
53
  }
48
54
 
49
55
  interface IAllKeysMatcher extends ISplitMatcherBase {
@@ -130,9 +136,36 @@ interface IMatchesStringMatcher extends ISplitMatcherBase {
130
136
  stringMatcherData: string
131
137
  }
132
138
 
139
+ interface IEqualToSemverMatcher extends ISplitMatcherBase {
140
+ matcherType: 'EQUAL_TO_SEMVER',
141
+ stringMatcherData: string
142
+ }
143
+
144
+ interface IGreaterThanOrEqualToSemverMatcher extends ISplitMatcherBase {
145
+ matcherType: 'GREATER_THAN_OR_EQUAL_TO_SEMVER',
146
+ stringMatcherData: string
147
+ }
148
+
149
+
150
+ interface ILessThanOrEqualToSemverMatcher extends ISplitMatcherBase {
151
+ matcherType: 'LESS_THAN_OR_EQUAL_TO_SEMVER',
152
+ stringMatcherData: string
153
+ }
154
+
155
+ interface IBetweenSemverMatcher extends ISplitMatcherBase {
156
+ matcherType: 'BETWEEN_SEMVER'
157
+ betweenStringMatcherData: IBetweenStringMatcherData
158
+ }
159
+
160
+ interface IInListSemverMatcher extends ISplitMatcherBase {
161
+ matcherType: 'IN_LIST_SEMVER',
162
+ whitelistMatcherData: IWhitelistMatcherData
163
+ }
164
+
133
165
  export type ISplitMatcher = IAllKeysMatcher | IInSegmentMatcher | IWhitelistMatcher | IEqualToMatcher | IGreaterThanOrEqualToMatcher |
134
166
  ILessThanOrEqualToMatcher | IBetweenMatcher | IEqualToSetMatcher | IContainsAnyOfSetMatcher | IContainsAllOfSetMatcher | IPartOfSetMatcher |
135
- IStartsWithMatcher | IEndsWithMatcher | IContainsStringMatcher | IInSplitTreatmentMatcher | IEqualToBooleanMatcher | IMatchesStringMatcher
167
+ IStartsWithMatcher | IEndsWithMatcher | IContainsStringMatcher | IInSplitTreatmentMatcher | IEqualToBooleanMatcher | IMatchesStringMatcher |
168
+ IEqualToSemverMatcher | IGreaterThanOrEqualToSemverMatcher | ILessThanOrEqualToSemverMatcher | IBetweenSemverMatcher | IInListSemverMatcher
136
169
 
137
170
  /** Split object */
138
171
  export interface ISplitPartition {
@@ -2,7 +2,7 @@ import { IBetweenMatcherData } from '../../dtos/types';
2
2
  import { ENGINE_MATCHER_BETWEEN } from '../../logger/constants';
3
3
  import { ILogger } from '../../logger/types';
4
4
 
5
- export function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatcherData) /*: Function */ {
5
+ export function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatcherData) {
6
6
  return function betweenMatcher(runtimeAttr: number): boolean {
7
7
 
8
8
  let isBetween = runtimeAttr >= ruleVO.start && runtimeAttr <= ruleVO.end;
@@ -1,7 +1,7 @@
1
1
  import { ENGINE_MATCHER_BOOLEAN } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
 
4
- export function booleanMatcherContext(log: ILogger, ruleAttr: boolean) /*: Function */ {
4
+ export function booleanMatcherContext(log: ILogger, ruleAttr: boolean) {
5
5
  return function booleanMatcher(runtimeAttr: boolean): boolean {
6
6
  let booleanMatches = ruleAttr === runtimeAttr;
7
7
 
@@ -2,7 +2,7 @@ import { ENGINE_MATCHER_CONTAINS_ALL } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { findIndex } from '../../utils/lang';
4
4
 
5
- export function containsAllSetMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ {
5
+ export function containsAllSetMatcherContext(log: ILogger, ruleAttr: string[]) {
6
6
  return function containsAllMatcher(runtimeAttr: string[]): boolean {
7
7
  let containsAll = true;
8
8
 
@@ -2,7 +2,7 @@ import { ENGINE_MATCHER_CONTAINS_ANY } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { findIndex } from '../../utils/lang';
4
4
 
5
- export function containsAnySetMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ {
5
+ export function containsAnySetMatcherContext(log: ILogger, ruleAttr: string[]) {
6
6
  return function containsAnyMatcher(runtimeAttr: string[]): boolean {
7
7
  let containsAny = false;
8
8
 
@@ -2,7 +2,7 @@ import { isString } from '../../utils/lang';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { ENGINE_MATCHER_CONTAINS_STRING } from '../../logger/constants';
4
4
 
5
- export function containsStringMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ {
5
+ export function containsStringMatcherContext(log: ILogger, ruleAttr: string[]) {
6
6
  return function containsStringMatcher(runtimeAttr: string): boolean {
7
7
  let contains = ruleAttr.some(e => isString(runtimeAttr) && runtimeAttr.indexOf(e) > -1);
8
8
 
@@ -1,7 +1,7 @@
1
1
  import { ENGINE_MATCHER_EQUAL } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
 
4
- export function equalToMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ {
4
+ export function equalToMatcherContext(log: ILogger, ruleAttr: number) {
5
5
  return function equalToMatcher(runtimeAttr: number): boolean {
6
6
  let isEqual = runtimeAttr === ruleAttr;
7
7
 
@@ -2,7 +2,7 @@ import { ENGINE_MATCHER_EQUAL_TO_SET } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { findIndex } from '../../utils/lang';
4
4
 
5
- export function equalToSetMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ {
5
+ export function equalToSetMatcherContext(log: ILogger, ruleAttr: string[]) {
6
6
  return function equalToSetMatcher(runtimeAttr: string[]): boolean {
7
7
  // Length being the same is the first condition.
8
8
  let isEqual = runtimeAttr.length === ruleAttr.length;
@@ -2,7 +2,7 @@ import { ENGINE_MATCHER_ENDS_WITH } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { endsWith } from '../../utils/lang';
4
4
 
5
- export function endsWithMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ {
5
+ export function endsWithMatcherContext(log: ILogger, ruleAttr: string[]) {
6
6
  return function endsWithMatcher(runtimeAttr: string): boolean {
7
7
  let strEndsWith = ruleAttr.some(e => endsWith(runtimeAttr, e));
8
8
 
@@ -1,12 +1,12 @@
1
1
  import { ENGINE_MATCHER_GREATER } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
 
4
- export function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ {
4
+ export function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: number) {
5
5
  return function greaterThanEqualMatcher(runtimeAttr: number): boolean {
6
- let isGreaterEqualThan = runtimeAttr >= ruleAttr;
6
+ let isGreaterThanEqual = runtimeAttr >= ruleAttr;
7
7
 
8
- log.debug(ENGINE_MATCHER_GREATER, [runtimeAttr, ruleAttr, isGreaterEqualThan]);
8
+ log.debug(ENGINE_MATCHER_GREATER, [runtimeAttr, ruleAttr, isGreaterThanEqual]);
9
9
 
10
- return isGreaterEqualThan;
10
+ return isGreaterThanEqual;
11
11
  };
12
12
  }
@@ -15,29 +15,39 @@ import { containsStringMatcherContext } from './cont_str';
15
15
  import { dependencyMatcherContext } from './dependency';
16
16
  import { booleanMatcherContext } from './boolean';
17
17
  import { stringMatcherContext } from './string';
18
+ import { equalToSemverMatcherContext } from './semver_eq';
19
+ import { greaterThanEqualToSemverMatcherContext } from './semver_gte';
20
+ import { lessThanEqualToSemverMatcherContext } from './semver_lte';
21
+ import { betweenSemverMatcherContext } from './semver_between';
22
+ import { inListSemverMatcherContext } from './semver_inlist';
18
23
  import { IStorageAsync, IStorageSync } from '../../storages/types';
19
24
  import { IMatcher, IMatcherDto } from '../types';
20
25
  import { ILogger } from '../../logger/types';
21
26
 
22
27
  const matchers = [
23
- undefined, // UNDEFINED: 0,
24
- allMatcherContext, // ALL_KEYS: 1,
25
- segmentMatcherContext, // IN_SEGMENT: 2,
26
- whitelistMatcherContext, // WHITELIST: 3,
27
- equalToMatcherContext, // EQUAL_TO: 4,
28
- greaterThanEqualMatcherContext, // GREATER_THAN_OR_EQUAL_TO: 5,
29
- lessThanEqualMatcherContext, // LESS_THAN_OR_EQUAL_TO: 6,
30
- betweenMatcherContext, // BETWEEN: 7,
31
- equalToSetMatcherContext, // EQUAL_TO_SET: 8,
32
- containsAnySetMatcherContext, // CONTAINS_ANY_OF_SET: 9,
33
- containsAllSetMatcherContext, // CONTAINS_ALL_OF_SET: 10,
34
- partOfSetMatcherContext, // PART_OF_SET: 11,
35
- endsWithMatcherContext, // ENDS_WITH: 12,
36
- startsWithMatcherContext, // STARTS_WITH: 13,
37
- containsStringMatcherContext, // CONTAINS_STRING: 14,
38
- dependencyMatcherContext, // IN_SPLIT_TREATMENT: 15,
39
- booleanMatcherContext, // EQUAL_TO_BOOLEAN: 16,
40
- stringMatcherContext // MATCHES_STRING: 17
28
+ undefined, // UNDEFINED: 0
29
+ allMatcherContext, // ALL_KEYS: 1
30
+ segmentMatcherContext, // IN_SEGMENT: 2
31
+ whitelistMatcherContext, // WHITELIST: 3
32
+ equalToMatcherContext, // EQUAL_TO: 4
33
+ greaterThanEqualMatcherContext, // GREATER_THAN_OR_EQUAL_TO: 5
34
+ lessThanEqualMatcherContext, // LESS_THAN_OR_EQUAL_TO: 6
35
+ betweenMatcherContext, // BETWEEN: 7
36
+ equalToSetMatcherContext, // EQUAL_TO_SET: 8
37
+ containsAnySetMatcherContext, // CONTAINS_ANY_OF_SET: 9
38
+ containsAllSetMatcherContext, // CONTAINS_ALL_OF_SET: 10
39
+ partOfSetMatcherContext, // PART_OF_SET: 11
40
+ endsWithMatcherContext, // ENDS_WITH: 12
41
+ startsWithMatcherContext, // STARTS_WITH: 13
42
+ containsStringMatcherContext, // CONTAINS_STRING: 14
43
+ dependencyMatcherContext, // IN_SPLIT_TREATMENT: 15
44
+ booleanMatcherContext, // EQUAL_TO_BOOLEAN: 16
45
+ stringMatcherContext, // MATCHES_STRING: 17
46
+ equalToSemverMatcherContext, // EQUAL_TO_SEMVER: 18
47
+ greaterThanEqualToSemverMatcherContext, // GREATER_THAN_OR_EQUAL_TO_SEMVER: 19
48
+ lessThanEqualToSemverMatcherContext, // LESS_THAN_OR_EQUAL_TO_SEMVER: 20
49
+ betweenSemverMatcherContext, // BETWEEN_SEMVER: 21
50
+ inListSemverMatcherContext, // IN_LIST_SEMVER: 22
41
51
  ];
42
52
 
43
53
  /**
@@ -1,7 +1,7 @@
1
1
  import { ENGINE_MATCHER_LESS } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
 
4
- export function lessThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: function */ {
4
+ export function lessThanEqualMatcherContext(log: ILogger, ruleAttr: number) {
5
5
  return function lessThanEqualMatcher(runtimeAttr: number): boolean {
6
6
  let isLessEqualThan = runtimeAttr <= ruleAttr;
7
7
 
@@ -16,7 +16,12 @@ export const matcherTypes: Record<string, number> = {
16
16
  CONTAINS_STRING: 14,
17
17
  IN_SPLIT_TREATMENT: 15,
18
18
  EQUAL_TO_BOOLEAN: 16,
19
- MATCHES_STRING: 17
19
+ MATCHES_STRING: 17,
20
+ EQUAL_TO_SEMVER: 18,
21
+ GREATER_THAN_OR_EQUAL_TO_SEMVER: 19,
22
+ LESS_THAN_OR_EQUAL_TO_SEMVER: 20,
23
+ BETWEEN_SEMVER: 21,
24
+ IN_LIST_SEMVER: 22,
20
25
  };
21
26
 
22
27
  export const matcherDataTypes = {
@@ -2,7 +2,7 @@ import { findIndex } from '../../utils/lang';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { ENGINE_MATCHER_PART_OF } from '../../logger/constants';
4
4
 
5
- export function partOfSetMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ {
5
+ export function partOfSetMatcherContext(log: ILogger, ruleAttr: string[]) {
6
6
  return function partOfMatcher(runtimeAttr: string[]): boolean {
7
7
  // To be part of the length should be minor or equal.
8
8
  let isPartOf = runtimeAttr.length <= ruleAttr.length;
@@ -0,0 +1,18 @@
1
+ import { IBetweenStringMatcherData } from '../../dtos/types';
2
+ import { ILogger } from '../../logger/types';
3
+ import { Semver } from '../../utils/Semver';
4
+
5
+ export function betweenSemverMatcherContext(log: ILogger, ruleAttr: IBetweenStringMatcherData) {
6
+
7
+ const startSemver = new Semver(ruleAttr.start);
8
+ const endSemver = new Semver(ruleAttr.end);
9
+
10
+ return function betweenSemverMatcher(key: string): boolean {
11
+
12
+ const runtimeSemver = new Semver(key);
13
+
14
+ let isBetween = startSemver.compare(runtimeSemver) <= 0 && endSemver.compare(runtimeSemver) >= 0;
15
+
16
+ return isBetween;
17
+ };
18
+ }
@@ -0,0 +1,13 @@
1
+ import { ILogger } from '../../logger/types';
2
+ import { Semver } from '../../utils/Semver';
3
+
4
+ export function equalToSemverMatcherContext(log: ILogger, ruleAttr: string) {
5
+
6
+ const ruleSemver = new Semver(ruleAttr);
7
+
8
+ return function equalToSemverMatcher(runtimeAttr: string): boolean {
9
+ const isEqual = ruleSemver.version === new Semver(runtimeAttr).version;
10
+
11
+ return isEqual;
12
+ };
13
+ }
@@ -0,0 +1,13 @@
1
+ import { ILogger } from '../../logger/types';
2
+ import { Semver } from '../../utils/Semver';
3
+
4
+ export function greaterThanEqualToSemverMatcherContext(log: ILogger, ruleAttr: string) {
5
+
6
+ const ruleSemver = new Semver(ruleAttr);
7
+
8
+ return function greaterThanEqualToSemverMatcher(runtimeAttr: string): boolean {
9
+ let isGreaterThanEqual = new Semver(runtimeAttr).compare(ruleSemver) >= 0;
10
+
11
+ return isGreaterThanEqual;
12
+ };
13
+ }
@@ -0,0 +1,15 @@
1
+ import { setToArray, ISet, _Set } from '../../utils/lang/sets';
2
+ import { ILogger } from '../../logger/types';
3
+ import { Semver } from '../../utils/Semver';
4
+
5
+ export function inListSemverMatcherContext(log: ILogger, ruleAttr: ISet<string>) {
6
+
7
+ const listOfSemvers = new _Set(setToArray(ruleAttr).map((version) => new Semver(version).version));
8
+
9
+ return function inListSemverMatcher(runtimeAttr: string): boolean {
10
+ const runtimeSemver = new Semver(runtimeAttr).version;
11
+ const isInList = listOfSemvers.has(runtimeSemver);
12
+
13
+ return isInList;
14
+ };
15
+ }
@@ -0,0 +1,13 @@
1
+ import { ILogger } from '../../logger/types';
2
+ import { Semver } from '../../utils/Semver';
3
+
4
+ export function lessThanEqualToSemverMatcherContext(log: ILogger, ruleAttr: string) {
5
+
6
+ const ruleSemver = new Semver(ruleAttr);
7
+
8
+ return function lessThanEqualToSemverMatcher(runtimeAttr: string): boolean {
9
+ let isLessThenEqual = new Semver(runtimeAttr).compare(ruleSemver) <= 0;
10
+
11
+ return isLessThenEqual;
12
+ };
13
+ }
@@ -1,7 +1,7 @@
1
1
  import { ENGINE_MATCHER_STRING_INVALID, ENGINE_MATCHER_STRING } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
 
4
- export function stringMatcherContext(log: ILogger, ruleAttr: string) /*: Function */ {
4
+ export function stringMatcherContext(log: ILogger, ruleAttr: string) {
5
5
  return function stringMatcher(runtimeAttr: string): boolean {
6
6
  let re;
7
7
 
@@ -2,7 +2,7 @@ import { ENGINE_MATCHER_STARTS_WITH } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { startsWith } from '../../utils/lang';
4
4
 
5
- export function startsWithMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ {
5
+ export function startsWithMatcherContext(log: ILogger, ruleAttr: string[]) {
6
6
  return function startsWithMatcher(runtimeAttr: string): boolean {
7
7
  let matches = ruleAttr.some(e => startsWith(runtimeAttr, e));
8
8
 
@@ -2,7 +2,7 @@ import { setToArray, ISet } from '../../utils/lang/sets';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { ENGINE_MATCHER_WHITELIST } from '../../logger/constants';
4
4
 
5
- export function whitelistMatcherContext(log: ILogger, ruleAttr: ISet<string>) /*: Function */ {
5
+ export function whitelistMatcherContext(log: ILogger, ruleAttr: ISet<string>) {
6
6
  return function whitelistMatcher(runtimeAttr: string): boolean {
7
7
  let isInWhitelist = ruleAttr.has(runtimeAttr);
8
8
 
@@ -15,16 +15,17 @@ export function matchersTransform(matchers: ISplitMatcher[]): IMatcherDto[] {
15
15
 
16
16
  let parsedMatchers = matchers.map(matcher => {
17
17
  let {
18
- matcherType /* string */,
19
- negate /* boolean */,
20
- keySelector /* keySelectorObject */,
21
- userDefinedSegmentMatcherData: segmentObject /* segmentObject */,
22
- whitelistMatcherData: whitelistObject /* whiteListObject, provided by 'WHITELIST', set and string matchers */,
23
- unaryNumericMatcherData: unaryNumericObject /* unaryNumericObject */,
24
- betweenMatcherData: betweenObject /* betweenObject */,
25
- dependencyMatcherData: dependencyObject /* dependencyObject */,
18
+ matcherType,
19
+ negate,
20
+ keySelector,
21
+ userDefinedSegmentMatcherData,
22
+ whitelistMatcherData, /* whitelistObject, provided by 'WHITELIST', 'IN_LIST_SEMVER', set and string matchers */
23
+ unaryNumericMatcherData,
24
+ betweenMatcherData,
25
+ dependencyMatcherData,
26
26
  booleanMatcherData,
27
- stringMatcherData
27
+ stringMatcherData,
28
+ betweenStringMatcherData
28
29
  } = matcher;
29
30
 
30
31
  let attribute = keySelector && keySelector.attribute;
@@ -34,28 +35,31 @@ export function matchersTransform(matchers: ISplitMatcher[]): IMatcherDto[] {
34
35
  let value = undefined;
35
36
 
36
37
  if (type === matcherTypes.IN_SEGMENT) {
37
- value = segmentTransform(segmentObject as IInSegmentMatcherData);
38
- } else if (type === matcherTypes.WHITELIST) {
39
- value = whitelistTransform(whitelistObject as IWhitelistMatcherData);
38
+ value = segmentTransform(userDefinedSegmentMatcherData as IInSegmentMatcherData);
39
+ } else if (
40
+ type === matcherTypes.WHITELIST ||
41
+ type === matcherTypes.IN_LIST_SEMVER
42
+ ) {
43
+ value = whitelistTransform(whitelistMatcherData as IWhitelistMatcherData);
40
44
  } else if (type === matcherTypes.EQUAL_TO) {
41
- value = numericTransform(unaryNumericObject as IUnaryNumericMatcherData);
45
+ value = numericTransform(unaryNumericMatcherData as IUnaryNumericMatcherData);
42
46
  dataType = matcherDataTypes.NUMBER;
43
47
 
44
- if ((unaryNumericObject as IUnaryNumericMatcherData).dataType === 'DATETIME') {
48
+ if ((unaryNumericMatcherData as IUnaryNumericMatcherData).dataType === 'DATETIME') {
45
49
  value = zeroSinceHH(value);
46
50
  dataType = matcherDataTypes.DATETIME;
47
51
  }
48
52
  } else if (type === matcherTypes.GREATER_THAN_OR_EQUAL_TO ||
49
53
  type === matcherTypes.LESS_THAN_OR_EQUAL_TO) {
50
- value = numericTransform(unaryNumericObject as IUnaryNumericMatcherData);
54
+ value = numericTransform(unaryNumericMatcherData as IUnaryNumericMatcherData);
51
55
  dataType = matcherDataTypes.NUMBER;
52
56
 
53
- if ((unaryNumericObject as IUnaryNumericMatcherData).dataType === 'DATETIME') {
57
+ if ((unaryNumericMatcherData as IUnaryNumericMatcherData).dataType === 'DATETIME') {
54
58
  value = zeroSinceSS(value);
55
59
  dataType = matcherDataTypes.DATETIME;
56
60
  }
57
61
  } else if (type === matcherTypes.BETWEEN) {
58
- value = betweenObject as IBetweenMatcherData;
62
+ value = betweenMatcherData as IBetweenMatcherData;
59
63
  dataType = matcherDataTypes.NUMBER;
60
64
 
61
65
  if (value.dataType === 'DATETIME') {
@@ -63,27 +67,34 @@ export function matchersTransform(matchers: ISplitMatcher[]): IMatcherDto[] {
63
67
  value.end = zeroSinceSS(value.end);
64
68
  dataType = matcherDataTypes.DATETIME;
65
69
  }
70
+ } else if (type === matcherTypes.BETWEEN_SEMVER) {
71
+ value = betweenStringMatcherData;
66
72
  } else if (
67
73
  type === matcherTypes.EQUAL_TO_SET ||
68
74
  type === matcherTypes.CONTAINS_ANY_OF_SET ||
69
75
  type === matcherTypes.CONTAINS_ALL_OF_SET ||
70
76
  type === matcherTypes.PART_OF_SET
71
77
  ) {
72
- value = setTransform(whitelistObject as IWhitelistMatcherData);
78
+ value = setTransform(whitelistMatcherData as IWhitelistMatcherData);
73
79
  dataType = matcherDataTypes.SET;
74
80
  } else if (
75
81
  type === matcherTypes.STARTS_WITH ||
76
82
  type === matcherTypes.ENDS_WITH ||
77
83
  type === matcherTypes.CONTAINS_STRING
78
84
  ) {
79
- value = setTransform(whitelistObject as IWhitelistMatcherData);
85
+ value = setTransform(whitelistMatcherData as IWhitelistMatcherData);
80
86
  } else if (type === matcherTypes.IN_SPLIT_TREATMENT) {
81
- value = dependencyObject;
87
+ value = dependencyMatcherData;
82
88
  dataType = matcherDataTypes.NOT_SPECIFIED;
83
89
  } else if (type === matcherTypes.EQUAL_TO_BOOLEAN) {
84
90
  dataType = matcherDataTypes.BOOLEAN;
85
91
  value = booleanMatcherData;
86
- } else if (type === matcherTypes.MATCHES_STRING) {
92
+ } else if (
93
+ type === matcherTypes.MATCHES_STRING ||
94
+ type === matcherTypes.EQUAL_TO_SEMVER ||
95
+ type === matcherTypes.GREATER_THAN_OR_EQUAL_TO_SEMVER ||
96
+ type === matcherTypes.LESS_THAN_OR_EQUAL_TO_SEMVER
97
+ ) {
87
98
  value = stringMatcherData;
88
99
  }
89
100
 
@@ -1,4 +1,4 @@
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
3
  import { ISet } from '../utils/lang/sets';
4
4
  import { SplitIO } from '../types';
@@ -11,7 +11,7 @@ export interface IDependencyMatcherValue {
11
11
 
12
12
  export interface IMatcherDto {
13
13
  type: number
14
- value?: string | number | boolean | string[] | IDependencyMatcherData | ISet<string> | IBetweenMatcherData | null
14
+ value?: string | number | boolean | string[] | IDependencyMatcherData | ISet<string> | IBetweenMatcherData | IBetweenStringMatcherData | null
15
15
 
16
16
  attribute: string | null
17
17
  negate: boolean
@@ -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, FLAGS_SPEC } from '../utils/constants';
7
+ import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MY_SEGMENT } from '../utils/constants';
8
8
  import { ERROR_TOO_MANY_SETS } from '../logger/constants';
9
9
 
10
10
  const noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
@@ -54,7 +54,7 @@ export function splitApiFactory(
54
54
  },
55
55
 
56
56
  fetchSplitChanges(since: number, noCache?: boolean, till?: number) {
57
- const url = `${urls.sdk}/splitChanges?s=${FLAGS_SPEC}&since=${since}${till ? '&till=' + till : ''}${filterQueryString || ''}`;
57
+ const url = `${urls.sdk}/splitChanges?since=${since}${till ? '&till=' + till : ''}${filterQueryString || ''}`;
58
58
  return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SPLITS))
59
59
  .catch((err) => {
60
60
  if (err.statusCode === 414) settings.log.error(ERROR_TOO_MANY_SETS);