@splitsoftware/splitio-commons 1.13.2-rc.2 → 1.13.2-rc.4
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.
- package/CHANGES.txt +0 -1
- package/cjs/evaluator/matchers/gte.js +3 -3
- package/cjs/evaluator/matchers/index.js +11 -1
- package/cjs/evaluator/matchers/matcherTypes.js +6 -1
- package/cjs/evaluator/matchers/semver_between.js +14 -0
- package/cjs/evaluator/matchers/semver_eq.js +13 -0
- package/cjs/evaluator/matchers/semver_gte.js +13 -0
- package/cjs/evaluator/matchers/semver_inlist.js +14 -0
- package/cjs/evaluator/matchers/semver_lte.js +13 -0
- package/cjs/evaluator/matchers/string.js +2 -9
- package/cjs/evaluator/matchersTransform/index.js +20 -13
- package/cjs/evaluator/parser/index.js +27 -10
- package/cjs/logger/constants.js +4 -4
- package/cjs/logger/messages/debug.js +0 -1
- package/cjs/logger/messages/error.js +1 -0
- package/cjs/services/splitApi.js +5 -5
- package/cjs/storages/KeyBuilder.js +2 -3
- package/cjs/utils/Semver.js +103 -0
- package/cjs/utils/constants/index.js +1 -2
- package/cjs/utils/settingsValidation/logger/pluggableLogger.js +1 -1
- package/esm/evaluator/matchers/gte.js +3 -3
- package/esm/evaluator/matchers/index.js +11 -1
- package/esm/evaluator/matchers/matcherTypes.js +6 -1
- package/esm/evaluator/matchers/semver_between.js +10 -0
- package/esm/evaluator/matchers/semver_eq.js +9 -0
- package/esm/evaluator/matchers/semver_gte.js +9 -0
- package/esm/evaluator/matchers/semver_inlist.js +10 -0
- package/esm/evaluator/matchers/semver_lte.js +9 -0
- package/esm/evaluator/matchers/string.js +3 -10
- package/esm/evaluator/matchersTransform/index.js +20 -13
- package/esm/evaluator/parser/index.js +27 -10
- package/esm/logger/constants.js +1 -1
- package/esm/logger/messages/debug.js +0 -1
- package/esm/logger/messages/error.js +1 -0
- package/esm/services/splitApi.js +6 -6
- package/esm/storages/KeyBuilder.js +2 -3
- package/esm/utils/Semver.js +100 -0
- package/esm/utils/constants/index.js +0 -1
- package/esm/utils/settingsValidation/logger/pluggableLogger.js +1 -1
- package/package.json +1 -2
- package/src/dtos/types.ts +34 -1
- package/src/evaluator/matchers/between.ts +1 -1
- package/src/evaluator/matchers/boolean.ts +1 -1
- package/src/evaluator/matchers/cont_all.ts +1 -1
- package/src/evaluator/matchers/cont_any.ts +1 -1
- package/src/evaluator/matchers/cont_str.ts +1 -1
- package/src/evaluator/matchers/eq.ts +1 -1
- package/src/evaluator/matchers/eq_set.ts +1 -1
- package/src/evaluator/matchers/ew.ts +1 -1
- package/src/evaluator/matchers/gte.ts +4 -4
- package/src/evaluator/matchers/index.ts +28 -18
- package/src/evaluator/matchers/lte.ts +1 -1
- package/src/evaluator/matchers/matcherTypes.ts +6 -1
- package/src/evaluator/matchers/part_of.ts +1 -1
- package/src/evaluator/matchers/semver_between.ts +16 -0
- package/src/evaluator/matchers/semver_eq.ts +14 -0
- package/src/evaluator/matchers/semver_gte.ts +14 -0
- package/src/evaluator/matchers/semver_inlist.ts +15 -0
- package/src/evaluator/matchers/semver_lte.ts +14 -0
- package/src/evaluator/matchers/string.ts +5 -13
- package/src/evaluator/matchers/sw.ts +1 -1
- package/src/evaluator/matchers/whitelist.ts +1 -1
- package/src/evaluator/matchersTransform/index.ts +32 -21
- package/src/evaluator/parser/index.ts +20 -8
- package/src/evaluator/types.ts +2 -2
- package/src/logger/constants.ts +1 -1
- package/src/logger/messages/debug.ts +0 -1
- package/src/logger/messages/error.ts +1 -0
- package/src/services/splitApi.ts +6 -5
- package/src/storages/KeyBuilder.ts +2 -3
- package/src/utils/Semver.ts +111 -0
- package/src/utils/constants/index.ts +0 -2
- package/src/utils/settingsValidation/logger/pluggableLogger.ts +1 -1
- package/types/dtos/types.d.ts +26 -1
- package/types/evaluator/matchers/semver_between.d.ts +2 -2
- package/types/evaluator/matchers/semver_inlist.d.ts +3 -0
- package/types/evaluator/matchersTransform/string.d.ts +7 -0
- package/types/evaluator/types.d.ts +2 -2
- package/types/logger/constants.d.ts +1 -1
- package/types/storages/KeyBuilder.d.ts +1 -1
- package/types/utils/constants/index.d.ts +0 -1
- package/types/utils/semVer.d.ts +8 -15
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Semver } from '../../utils/Semver';
|
|
2
|
+
export function greaterThanEqualToSemverMatcherContext(log, ruleAttr) {
|
|
3
|
+
var ruleSemver = new Semver(ruleAttr);
|
|
4
|
+
return function greaterThanEqualToSemverMatcher(runtimeAttr) {
|
|
5
|
+
var runtimeSemver = new Semver(runtimeAttr);
|
|
6
|
+
var isGreaterThanEqual = runtimeSemver.compare(ruleSemver) >= 0;
|
|
7
|
+
return isGreaterThanEqual;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { setToArray, _Set } from '../../utils/lang/sets';
|
|
2
|
+
import { Semver } from '../../utils/Semver';
|
|
3
|
+
export function inListSemverMatcherContext(log, ruleAttr) {
|
|
4
|
+
var listOfSemvers = new _Set(setToArray(ruleAttr).map(function (version) { return new Semver(version).version; }));
|
|
5
|
+
return function inListSemverMatcher(runtimeAttr) {
|
|
6
|
+
var runtimeSemver = new Semver(runtimeAttr).version;
|
|
7
|
+
var isInList = listOfSemvers.has(runtimeSemver);
|
|
8
|
+
return isInList;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Semver } from '../../utils/Semver';
|
|
2
|
+
export function lessThanEqualToSemverMatcherContext(log, ruleAttr) {
|
|
3
|
+
var ruleSemver = new Semver(ruleAttr);
|
|
4
|
+
return function lessThanEqualToSemverMatcher(runtimeAttr) {
|
|
5
|
+
var runtimeSemver = new Semver(runtimeAttr);
|
|
6
|
+
var isLessThenEqual = runtimeSemver.compare(ruleSemver) <= 0;
|
|
7
|
+
return isLessThenEqual;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ENGINE_MATCHER_STRING } from '../../logger/constants';
|
|
2
2
|
export function stringMatcherContext(log, ruleAttr) {
|
|
3
|
+
var regex = new RegExp(ruleAttr);
|
|
3
4
|
return function stringMatcher(runtimeAttr) {
|
|
4
|
-
var
|
|
5
|
-
try {
|
|
6
|
-
re = new RegExp(ruleAttr);
|
|
7
|
-
}
|
|
8
|
-
catch (e) {
|
|
9
|
-
log.debug(ENGINE_MATCHER_STRING_INVALID, [ruleAttr]);
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
var regexMatches = re.test(runtimeAttr);
|
|
5
|
+
var regexMatches = regex.test(runtimeAttr);
|
|
13
6
|
log.debug(ENGINE_MATCHER_STRING, [runtimeAttr, ruleAttr, regexMatches ? 'yes' : 'no']);
|
|
14
7
|
return regexMatches;
|
|
15
8
|
};
|
|
@@ -10,37 +10,38 @@ import { zeroSinceHH, zeroSinceSS } from '../convertions';
|
|
|
10
10
|
*/
|
|
11
11
|
export function matchersTransform(matchers) {
|
|
12
12
|
var parsedMatchers = matchers.map(function (matcher) {
|
|
13
|
-
var matcherType = matcher.matcherType
|
|
13
|
+
var matcherType = matcher.matcherType, negate = matcher.negate, keySelector = matcher.keySelector, userDefinedSegmentMatcherData = matcher.userDefinedSegmentMatcherData, whitelistMatcherData = matcher.whitelistMatcherData, /* whitelistObject, provided by 'WHITELIST', 'IN_LIST_SEMVER', set and string matchers */ unaryNumericMatcherData = matcher.unaryNumericMatcherData, betweenMatcherData = matcher.betweenMatcherData, dependencyMatcherData = matcher.dependencyMatcherData, booleanMatcherData = matcher.booleanMatcherData, stringMatcherData = matcher.stringMatcherData, betweenStringMatcherData = matcher.betweenStringMatcherData;
|
|
14
14
|
var attribute = keySelector && keySelector.attribute;
|
|
15
15
|
var type = matcherTypesMapper(matcherType);
|
|
16
16
|
// As default input data type we use string (even for ALL_KEYS)
|
|
17
17
|
var dataType = matcherDataTypes.STRING;
|
|
18
18
|
var value = undefined;
|
|
19
19
|
if (type === matcherTypes.IN_SEGMENT) {
|
|
20
|
-
value = segmentTransform(
|
|
20
|
+
value = segmentTransform(userDefinedSegmentMatcherData);
|
|
21
21
|
}
|
|
22
|
-
else if (type === matcherTypes.WHITELIST
|
|
23
|
-
|
|
22
|
+
else if (type === matcherTypes.WHITELIST ||
|
|
23
|
+
type === matcherTypes.IN_LIST_SEMVER) {
|
|
24
|
+
value = whitelistTransform(whitelistMatcherData);
|
|
24
25
|
}
|
|
25
26
|
else if (type === matcherTypes.EQUAL_TO) {
|
|
26
|
-
value = numericTransform(
|
|
27
|
+
value = numericTransform(unaryNumericMatcherData);
|
|
27
28
|
dataType = matcherDataTypes.NUMBER;
|
|
28
|
-
if (
|
|
29
|
+
if (unaryNumericMatcherData.dataType === 'DATETIME') {
|
|
29
30
|
value = zeroSinceHH(value);
|
|
30
31
|
dataType = matcherDataTypes.DATETIME;
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
else if (type === matcherTypes.GREATER_THAN_OR_EQUAL_TO ||
|
|
34
35
|
type === matcherTypes.LESS_THAN_OR_EQUAL_TO) {
|
|
35
|
-
value = numericTransform(
|
|
36
|
+
value = numericTransform(unaryNumericMatcherData);
|
|
36
37
|
dataType = matcherDataTypes.NUMBER;
|
|
37
|
-
if (
|
|
38
|
+
if (unaryNumericMatcherData.dataType === 'DATETIME') {
|
|
38
39
|
value = zeroSinceSS(value);
|
|
39
40
|
dataType = matcherDataTypes.DATETIME;
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
else if (type === matcherTypes.BETWEEN) {
|
|
43
|
-
value =
|
|
44
|
+
value = betweenMatcherData;
|
|
44
45
|
dataType = matcherDataTypes.NUMBER;
|
|
45
46
|
if (value.dataType === 'DATETIME') {
|
|
46
47
|
value.start = zeroSinceSS(value.start);
|
|
@@ -48,27 +49,33 @@ export function matchersTransform(matchers) {
|
|
|
48
49
|
dataType = matcherDataTypes.DATETIME;
|
|
49
50
|
}
|
|
50
51
|
}
|
|
52
|
+
else if (type === matcherTypes.BETWEEN_SEMVER) {
|
|
53
|
+
value = betweenStringMatcherData;
|
|
54
|
+
}
|
|
51
55
|
else if (type === matcherTypes.EQUAL_TO_SET ||
|
|
52
56
|
type === matcherTypes.CONTAINS_ANY_OF_SET ||
|
|
53
57
|
type === matcherTypes.CONTAINS_ALL_OF_SET ||
|
|
54
58
|
type === matcherTypes.PART_OF_SET) {
|
|
55
|
-
value = setTransform(
|
|
59
|
+
value = setTransform(whitelistMatcherData);
|
|
56
60
|
dataType = matcherDataTypes.SET;
|
|
57
61
|
}
|
|
58
62
|
else if (type === matcherTypes.STARTS_WITH ||
|
|
59
63
|
type === matcherTypes.ENDS_WITH ||
|
|
60
64
|
type === matcherTypes.CONTAINS_STRING) {
|
|
61
|
-
value = setTransform(
|
|
65
|
+
value = setTransform(whitelistMatcherData);
|
|
62
66
|
}
|
|
63
67
|
else if (type === matcherTypes.IN_SPLIT_TREATMENT) {
|
|
64
|
-
value =
|
|
68
|
+
value = dependencyMatcherData;
|
|
65
69
|
dataType = matcherDataTypes.NOT_SPECIFIED;
|
|
66
70
|
}
|
|
67
71
|
else if (type === matcherTypes.EQUAL_TO_BOOLEAN) {
|
|
68
72
|
dataType = matcherDataTypes.BOOLEAN;
|
|
69
73
|
value = booleanMatcherData;
|
|
70
74
|
}
|
|
71
|
-
else if (type === matcherTypes.MATCHES_STRING
|
|
75
|
+
else if (type === matcherTypes.MATCHES_STRING ||
|
|
76
|
+
type === matcherTypes.EQUAL_TO_SEMVER ||
|
|
77
|
+
type === matcherTypes.GREATER_THAN_OR_EQUAL_TO_SEMVER ||
|
|
78
|
+
type === matcherTypes.LESS_THAN_OR_EQUAL_TO_SEMVER) {
|
|
72
79
|
value = stringMatcherData;
|
|
73
80
|
}
|
|
74
81
|
return {
|
|
@@ -6,24 +6,37 @@ import { conditionContext } from '../condition';
|
|
|
6
6
|
import { ifElseIfCombinerContext } from '../combiners/ifelseif';
|
|
7
7
|
import { andCombinerContext } from '../combiners/and';
|
|
8
8
|
import { thenable } from '../../utils/promise/thenable';
|
|
9
|
+
import { ENGINE_MATCHER_ERROR } from '../../logger/constants';
|
|
9
10
|
export function parser(log, conditions, storage) {
|
|
10
11
|
var predicates = [];
|
|
11
|
-
|
|
12
|
+
var _loop_1 = function (i) {
|
|
12
13
|
var _a = conditions[i], matcherGroup = _a.matcherGroup, partitions = _a.partitions, label = _a.label, conditionType = _a.conditionType;
|
|
13
14
|
// transform data structure
|
|
14
15
|
var matchers = matchersTransform(matcherGroup.matchers);
|
|
15
16
|
// create a set of pure functions from the matcher's dto
|
|
16
|
-
var expressions = matchers.map(function (matcherDto) {
|
|
17
|
-
var matcher
|
|
17
|
+
var expressions = matchers.map(function (matcherDto, index) {
|
|
18
|
+
var matcher;
|
|
19
|
+
try {
|
|
20
|
+
matcher = matcherFactory(log, matcherDto, storage);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
log.error(ENGINE_MATCHER_ERROR, [matcherGroup.matchers[index].matcherType, error]);
|
|
24
|
+
}
|
|
18
25
|
// Evaluator function.
|
|
19
26
|
return function (key, attributes, splitEvaluator) {
|
|
20
27
|
var value = sanitizeValue(log, key, matcherDto, attributes);
|
|
21
|
-
var result =
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
var result = false;
|
|
29
|
+
if (value !== undefined && matcher) {
|
|
30
|
+
try {
|
|
31
|
+
result = matcher(value, splitEvaluator);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
log.error(ENGINE_MATCHER_ERROR, [matcherGroup.matchers[index].matcherType, error]);
|
|
35
|
+
}
|
|
25
36
|
}
|
|
26
|
-
// @ts-ignore
|
|
37
|
+
if (thenable(result)) { // @ts-ignore
|
|
38
|
+
return result.then(function (res) { return Boolean(res ^ matcherDto.negate); });
|
|
39
|
+
} // @ts-ignore
|
|
27
40
|
return Boolean(result ^ matcherDto.negate);
|
|
28
41
|
};
|
|
29
42
|
});
|
|
@@ -31,10 +44,14 @@ export function parser(log, conditions, storage) {
|
|
|
31
44
|
if (expressions.length === 0) {
|
|
32
45
|
// reset any data collected during parsing
|
|
33
46
|
predicates = [];
|
|
34
|
-
|
|
35
|
-
break;
|
|
47
|
+
return "break";
|
|
36
48
|
}
|
|
37
49
|
predicates.push(conditionContext(log, andCombinerContext(log, expressions), Treatments.parse(partitions), label, conditionType));
|
|
50
|
+
};
|
|
51
|
+
for (var i = 0; i < conditions.length; i++) {
|
|
52
|
+
var state_1 = _loop_1(i);
|
|
53
|
+
if (state_1 === "break")
|
|
54
|
+
break;
|
|
38
55
|
}
|
|
39
56
|
// Instanciate evaluator given the set of conditions using if else if logic
|
|
40
57
|
return ifElseIfCombinerContext(log, predicates);
|
package/esm/logger/constants.js
CHANGED
|
@@ -25,7 +25,6 @@ export var ENGINE_MATCHER_LESS = 16;
|
|
|
25
25
|
export var ENGINE_MATCHER_PART_OF = 17;
|
|
26
26
|
export var ENGINE_MATCHER_SEGMENT = 18;
|
|
27
27
|
export var ENGINE_MATCHER_STRING = 19;
|
|
28
|
-
export var ENGINE_MATCHER_STRING_INVALID = 20;
|
|
29
28
|
export var ENGINE_MATCHER_STARTS_WITH = 21;
|
|
30
29
|
export var ENGINE_MATCHER_WHITELIST = 22;
|
|
31
30
|
export var ENGINE_VALUE = 23;
|
|
@@ -128,6 +127,7 @@ export var ERROR_NOT_BOOLEAN = 325;
|
|
|
128
127
|
export var ERROR_MIN_CONFIG_PARAM = 326;
|
|
129
128
|
export var ERROR_TOO_MANY_SETS = 327;
|
|
130
129
|
export var ERROR_SETS_FILTER_EXCLUSIVE = 328;
|
|
130
|
+
export var ENGINE_MATCHER_ERROR = 329;
|
|
131
131
|
// Log prefixes (a.k.a. tags or categories)
|
|
132
132
|
export var LOG_PREFIX_SETTINGS = 'settings';
|
|
133
133
|
export var LOG_PREFIX_INSTANTIATION = 'Factory instantiation';
|
|
@@ -22,7 +22,6 @@ export var codesDebug = codesInfo.concat([
|
|
|
22
22
|
[c.ENGINE_MATCHER_PART_OF, c.LOG_PREFIX_ENGINE_MATCHER + '[partOfMatcher] %s is part of %s? %s'],
|
|
23
23
|
[c.ENGINE_MATCHER_SEGMENT, c.LOG_PREFIX_ENGINE_MATCHER + '[segmentMatcher] evaluated %s / %s => %s'],
|
|
24
24
|
[c.ENGINE_MATCHER_STRING, c.LOG_PREFIX_ENGINE_MATCHER + '[stringMatcher] does %s matches with %s? %s'],
|
|
25
|
-
[c.ENGINE_MATCHER_STRING_INVALID, c.LOG_PREFIX_ENGINE_MATCHER + '[stringMatcher] %s is an invalid regex'],
|
|
26
25
|
[c.ENGINE_MATCHER_STARTS_WITH, c.LOG_PREFIX_ENGINE_MATCHER + '[startsWithMatcher] %s starts with %s? %s'],
|
|
27
26
|
[c.ENGINE_MATCHER_WHITELIST, c.LOG_PREFIX_ENGINE_MATCHER + '[whitelistMatcher] evaluated %s in [%s] => %s'],
|
|
28
27
|
[c.ENGINE_VALUE, c.LOG_PREFIX_ENGINE_VALUE + 'Extracted attribute [%s], [%s] will be used for matching.'],
|
|
@@ -2,6 +2,7 @@ import * as c from '../constants';
|
|
|
2
2
|
export var codesError = [
|
|
3
3
|
// evaluator
|
|
4
4
|
[c.ERROR_ENGINE_COMBINER_IFELSEIF, c.LOG_PREFIX_ENGINE_COMBINER + 'Invalid feature flag, no valid rules or unsupported matcher type found'],
|
|
5
|
+
[c.ENGINE_MATCHER_ERROR, c.LOG_PREFIX_ENGINE_MATCHER + '[%s] %s'],
|
|
5
6
|
// SDK
|
|
6
7
|
[c.ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'],
|
|
7
8
|
[c.ERROR_CLIENT_CANNOT_GET_READY, 'The SDK will not get ready. Reason: %s'],
|
package/esm/services/splitApi.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { splitHttpClientFactory } from './splitHttpClient';
|
|
2
2
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
3
|
-
import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MY_SEGMENT
|
|
3
|
+
import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MY_SEGMENT } from '../utils/constants';
|
|
4
4
|
import { ERROR_TOO_MANY_SETS } from '../logger/constants';
|
|
5
5
|
var noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
|
|
6
6
|
function userKeyToQueryParam(userKey) {
|
|
@@ -29,16 +29,16 @@ export function splitApiFactory(settings, platform, telemetryTracker) {
|
|
|
29
29
|
return splitHttpClient(url).then(function () { return true; }).catch(function () { return false; });
|
|
30
30
|
},
|
|
31
31
|
fetchAuth: function (userMatchingKeys) {
|
|
32
|
-
var url = urls.auth + "/v2/auth
|
|
33
|
-
if (userMatchingKeys) { // `userMatchingKeys` is undefined
|
|
32
|
+
var url = urls.auth + "/v2/auth";
|
|
33
|
+
if (userMatchingKeys) { // accounting the possibility that `userMatchingKeys` is undefined (server-side API)
|
|
34
34
|
var queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
|
|
35
|
-
if (queryParams)
|
|
36
|
-
url += '
|
|
35
|
+
if (queryParams) // accounting the possibility that `userKeys` and thus `queryParams` are empty
|
|
36
|
+
url += '?' + queryParams;
|
|
37
37
|
}
|
|
38
38
|
return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN));
|
|
39
39
|
},
|
|
40
40
|
fetchSplitChanges: function (since, noCache, till) {
|
|
41
|
-
var url = urls.sdk + "/splitChanges?
|
|
41
|
+
var url = urls.sdk + "/splitChanges?since=" + since + (till ? '&till=' + till : '') + (filterQueryString || '');
|
|
42
42
|
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SPLITS))
|
|
43
43
|
.catch(function (err) {
|
|
44
44
|
if (err.statusCode === 414)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FLAGS_SPEC } from '../utils/constants';
|
|
2
1
|
import { startsWith } from '../utils/lang';
|
|
3
2
|
import { hash } from '../utils/murmur3/murmur3';
|
|
4
3
|
var everythingAtTheEnd = /[^.]+$/;
|
|
@@ -63,9 +62,9 @@ var KeyBuilder = /** @class */ (function () {
|
|
|
63
62
|
}());
|
|
64
63
|
export { KeyBuilder };
|
|
65
64
|
/**
|
|
66
|
-
* Generates a murmur32 hash based on the authorization key
|
|
65
|
+
* Generates a murmur32 hash based on the authorization key and the feature flags filter query.
|
|
67
66
|
* The hash is in hexadecimal format (8 characters max, 32 bits).
|
|
68
67
|
*/
|
|
69
68
|
export function getStorageHash(settings) {
|
|
70
|
-
return hash(settings.core.authorizationKey + "::" + settings.sync.__splitFiltersValidation.queryString
|
|
69
|
+
return hash(settings.core.authorizationKey + "::" + settings.sync.__splitFiltersValidation.queryString).toString(16);
|
|
71
70
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { isString } from '../utils/lang';
|
|
2
|
+
var NUMERIC_IDENTIFIER_REGEX = /^[0-9]+$/;
|
|
3
|
+
var METADATA_DELIMITER = '+';
|
|
4
|
+
var PRERELEASE_DELIMITER = '-';
|
|
5
|
+
var VALUE_DELIMITER = '.';
|
|
6
|
+
/**
|
|
7
|
+
* Compares two strings. If both strings are numeric identifiers, they are compared numerically. Otherwise, they are compared lexicographically.
|
|
8
|
+
* This could be implemented using `a.localeCompare(b, undefined, { numeric: true })` but locale options are not broadly supported.
|
|
9
|
+
*/
|
|
10
|
+
function compareStrings(a, b) {
|
|
11
|
+
if (NUMERIC_IDENTIFIER_REGEX.test(a) && NUMERIC_IDENTIFIER_REGEX.test(b)) {
|
|
12
|
+
var result = a.length - b.length;
|
|
13
|
+
if (result !== 0) {
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
18
|
+
}
|
|
19
|
+
// Sanitizes a numeric identifier by removing leading zeros
|
|
20
|
+
function sanitizeNumericIdentifier(value) {
|
|
21
|
+
return value.replace(/^0+(?=\d)/, '');
|
|
22
|
+
}
|
|
23
|
+
function throwError(version) {
|
|
24
|
+
throw new Error('Unable to convert to Semver, incorrect format: ' + version);
|
|
25
|
+
}
|
|
26
|
+
var Semver = /** @class */ (function () {
|
|
27
|
+
function Semver(version) {
|
|
28
|
+
if (!isString(version))
|
|
29
|
+
throwError(version);
|
|
30
|
+
// Separate metadata if exists
|
|
31
|
+
var index = version.indexOf(METADATA_DELIMITER);
|
|
32
|
+
var _a = index === -1 ? [version] : [version.slice(0, index), version.slice(index + 1)], vWithoutMetadata = _a[0], metadata = _a[1];
|
|
33
|
+
if (metadata === '')
|
|
34
|
+
throwError(version);
|
|
35
|
+
// Set pre-release versions if exists
|
|
36
|
+
index = vWithoutMetadata.indexOf(PRERELEASE_DELIMITER);
|
|
37
|
+
if (index === -1) {
|
|
38
|
+
this._isStable = true;
|
|
39
|
+
this._preRelease = [];
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
this._isStable = false;
|
|
43
|
+
this._preRelease = vWithoutMetadata.slice(index + 1).split(VALUE_DELIMITER).map(function (value) {
|
|
44
|
+
if (!value)
|
|
45
|
+
throwError(version);
|
|
46
|
+
return NUMERIC_IDENTIFIER_REGEX.test(value) ?
|
|
47
|
+
sanitizeNumericIdentifier(value) :
|
|
48
|
+
value;
|
|
49
|
+
});
|
|
50
|
+
vWithoutMetadata = vWithoutMetadata.slice(0, index);
|
|
51
|
+
}
|
|
52
|
+
// Set major, minor, and patch versions
|
|
53
|
+
var vParts = vWithoutMetadata.split(VALUE_DELIMITER).map(function (value) {
|
|
54
|
+
if (!value || !NUMERIC_IDENTIFIER_REGEX.test(value))
|
|
55
|
+
throwError(version);
|
|
56
|
+
return sanitizeNumericIdentifier(value);
|
|
57
|
+
});
|
|
58
|
+
if (vParts.length !== 3)
|
|
59
|
+
throwError(version);
|
|
60
|
+
this._major = vParts[0];
|
|
61
|
+
this._minor = vParts[1];
|
|
62
|
+
this._patch = vParts[2];
|
|
63
|
+
// Set version string
|
|
64
|
+
this.version = vParts.join(VALUE_DELIMITER);
|
|
65
|
+
if (this._preRelease.length)
|
|
66
|
+
this.version += PRERELEASE_DELIMITER + this._preRelease.join(VALUE_DELIMITER);
|
|
67
|
+
if (metadata)
|
|
68
|
+
this.version += METADATA_DELIMITER + metadata;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Precedence comparision between 2 Semver objects.
|
|
72
|
+
*
|
|
73
|
+
* @return `0` if `this === toCompare`, `-1` if `this < toCompare`, and `1` if `this > toCompare`
|
|
74
|
+
*/
|
|
75
|
+
Semver.prototype.compare = function (toCompare) {
|
|
76
|
+
if (this.version === toCompare.version)
|
|
77
|
+
return 0;
|
|
78
|
+
var result = compareStrings(this._major, toCompare._major);
|
|
79
|
+
if (result !== 0)
|
|
80
|
+
return result;
|
|
81
|
+
result = compareStrings(this._minor, toCompare._minor);
|
|
82
|
+
if (result !== 0)
|
|
83
|
+
return result;
|
|
84
|
+
result = compareStrings(this._patch, toCompare._patch);
|
|
85
|
+
if (result !== 0)
|
|
86
|
+
return result;
|
|
87
|
+
if (!this._isStable && toCompare._isStable)
|
|
88
|
+
return -1;
|
|
89
|
+
if (this._isStable && !toCompare._isStable)
|
|
90
|
+
return 1;
|
|
91
|
+
for (var i = 0, length_1 = Math.min(this._preRelease.length, toCompare._preRelease.length); i < length_1; i++) {
|
|
92
|
+
var result_1 = compareStrings(this._preRelease[i], toCompare._preRelease[i]);
|
|
93
|
+
if (result_1 !== 0)
|
|
94
|
+
return result_1;
|
|
95
|
+
}
|
|
96
|
+
return this._preRelease.length - toCompare._preRelease.length;
|
|
97
|
+
};
|
|
98
|
+
return Semver;
|
|
99
|
+
}());
|
|
100
|
+
export { Semver };
|
|
@@ -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.
|
|
3
|
+
"version": "1.13.2-rc.4",
|
|
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)
|
|
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)
|
|
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[])
|
|
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[])
|
|
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[])
|
|
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)
|
|
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[])
|
|
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[])
|
|
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)
|
|
4
|
+
export function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: number) {
|
|
5
5
|
return function greaterThanEqualMatcher(runtimeAttr: number): boolean {
|
|
6
|
-
let
|
|
6
|
+
let isGreaterThanEqual = runtimeAttr >= ruleAttr;
|
|
7
7
|
|
|
8
|
-
log.debug(ENGINE_MATCHER_GREATER, [runtimeAttr, ruleAttr,
|
|
8
|
+
log.debug(ENGINE_MATCHER_GREATER, [runtimeAttr, ruleAttr, isGreaterThanEqual]);
|
|
9
9
|
|
|
10
|
-
return
|
|
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
|
/**
|