@kameleoon/javascript-sdk-core 1.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/campaignConfiguration/campaignConfiguration.d.ts +2 -1
- package/dist/campaignConfiguration/campaignConfiguration.js +239 -197
- package/dist/campaignConfiguration/campaignConfiguration.js.map +1 -1
- package/dist/campaignConfiguration/constants.js +20 -14
- package/dist/campaignConfiguration/constants.js.map +1 -1
- package/dist/campaignConfiguration/index.js +78 -6
- package/dist/campaignConfiguration/index.js.map +1 -1
- package/dist/campaignConfiguration/types.d.ts +3 -2
- package/dist/campaignConfiguration/types.js +53 -45
- package/dist/campaignConfiguration/types.js.map +1 -1
- package/dist/clientSettings/clientSettings.d.ts +1 -1
- package/dist/clientSettings/clientSettings.js +28 -21
- package/dist/clientSettings/clientSettings.js.map +1 -1
- package/dist/clientSettings/index.js +18 -4
- package/dist/clientSettings/index.js.map +1 -1
- package/dist/clientSettings/types.d.ts +1 -1
- package/dist/clientSettings/types.js +4 -1
- package/dist/clientSettings/types.js.map +1 -1
- package/dist/constants.js +22 -14
- package/dist/constants.js.map +1 -1
- package/dist/eventSource/constants.js +6 -2
- package/dist/eventSource/constants.js.map +1 -1
- package/dist/eventSource/externalEventSource.js +28 -20
- package/dist/eventSource/externalEventSource.js.map +1 -1
- package/dist/eventSource/index.js +49 -6
- package/dist/eventSource/index.js.map +1 -1
- package/dist/eventSource/types.d.ts +1 -1
- package/dist/eventSource/types.js +4 -1
- package/dist/eventSource/types.js.map +1 -1
- package/dist/hasher/constants.js +6 -2
- package/dist/hasher/constants.js.map +1 -1
- package/dist/hasher/hasher.js +35 -24
- package/dist/hasher/hasher.js.map +1 -1
- package/dist/hasher/index.js +11 -4
- package/dist/hasher/index.js.map +1 -1
- package/dist/hasher/types.js +4 -1
- package/dist/hasher/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +297 -28
- package/dist/index.js.map +1 -1
- package/dist/kameleoonClient.d.ts +16 -16
- package/dist/kameleoonClient.js +307 -236
- package/dist/kameleoonClient.js.map +1 -1
- package/dist/kameleoonData/browser.js +37 -32
- package/dist/kameleoonData/browser.js.map +1 -1
- package/dist/kameleoonData/constants.js +6 -2
- package/dist/kameleoonData/constants.js.map +1 -1
- package/dist/kameleoonData/conversion.js +47 -40
- package/dist/kameleoonData/conversion.js.map +1 -1
- package/dist/kameleoonData/customData.js +62 -58
- package/dist/kameleoonData/customData.js.map +1 -1
- package/dist/kameleoonData/device.js +37 -32
- package/dist/kameleoonData/device.js.map +1 -1
- package/dist/kameleoonData/index.js +101 -18
- package/dist/kameleoonData/index.js.map +1 -1
- package/dist/kameleoonData/nonce.js +25 -13
- package/dist/kameleoonData/nonce.js.map +1 -1
- package/dist/kameleoonData/pageView.js +52 -44
- package/dist/kameleoonData/pageView.js.map +1 -1
- package/dist/kameleoonData/types.js +41 -26
- package/dist/kameleoonData/types.js.map +1 -1
- package/dist/kameleoonData/userAgent.js +33 -24
- package/dist/kameleoonData/userAgent.js.map +1 -1
- package/dist/kameleoonError/constants.js +25 -21
- package/dist/kameleoonError/constants.js.map +1 -1
- package/dist/kameleoonError/helpers.js +6 -4
- package/dist/kameleoonError/helpers.js.map +1 -1
- package/dist/kameleoonError/index.js +25 -8
- package/dist/kameleoonError/index.js.map +1 -1
- package/dist/kameleoonError/kameleoonError.js +64 -53
- package/dist/kameleoonError/kameleoonError.js.map +1 -1
- package/dist/kameleoonError/types.js +26 -22
- package/dist/kameleoonError/types.js.map +1 -1
- package/dist/kameleoonUtils.js +34 -33
- package/dist/kameleoonUtils.js.map +1 -1
- package/dist/requester/constants.d.ts +6 -7
- package/dist/requester/constants.js +58 -45
- package/dist/requester/constants.js.map +1 -1
- package/dist/requester/index.d.ts +2 -2
- package/dist/requester/index.js +67 -8
- package/dist/requester/index.js.map +1 -1
- package/dist/requester/requester.d.ts +7 -7
- package/dist/requester/requester.js +100 -113
- package/dist/requester/requester.js.map +1 -1
- package/dist/requester/types.d.ts +38 -10
- package/dist/requester/types.js +14 -36
- package/dist/requester/types.js.map +1 -1
- package/dist/storage/constants.js +11 -7
- package/dist/storage/constants.js.map +1 -1
- package/dist/storage/externalStorage.js +33 -26
- package/dist/storage/externalStorage.js.map +1 -1
- package/dist/storage/index.js +55 -6
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/types.js +4 -1
- package/dist/storage/types.js.map +1 -1
- package/dist/targeting/conditions/conditionFactory.js +24 -19
- package/dist/targeting/conditions/conditionFactory.js.map +1 -1
- package/dist/targeting/conditions/customDataCondition.js +99 -88
- package/dist/targeting/conditions/customDataCondition.js.map +1 -1
- package/dist/targeting/conditions/exclusiveExperimentCondition.js +27 -15
- package/dist/targeting/conditions/exclusiveExperimentCondition.js.map +1 -1
- package/dist/targeting/conditions/index.js +45 -10
- package/dist/targeting/conditions/index.js.map +1 -1
- package/dist/targeting/conditions/targetExperimentCondition.js +54 -32
- package/dist/targeting/conditions/targetExperimentCondition.js.map +1 -1
- package/dist/targeting/conditions/types.js +4 -1
- package/dist/targeting/conditions/types.js.map +1 -1
- package/dist/targeting/index.js +79 -13
- package/dist/targeting/index.js.map +1 -1
- package/dist/targeting/targetingNode.js +41 -33
- package/dist/targeting/targetingNode.js.map +1 -1
- package/dist/targeting/targetingTree.js +125 -104
- package/dist/targeting/targetingTree.js.map +1 -1
- package/dist/targeting/types.js +99 -91
- package/dist/targeting/types.js.map +1 -1
- package/dist/types.d.ts +17 -2
- package/dist/types.js +50 -21
- package/dist/types.js.map +1 -1
- package/dist/utilities/constants.js +6 -2
- package/dist/utilities/constants.js.map +1 -1
- package/dist/utilities/index.js +11 -4
- package/dist/utilities/index.js.map +1 -1
- package/dist/utilities/types.d.ts +1 -1
- package/dist/utilities/types.js +4 -1
- package/dist/utilities/types.js.map +1 -1
- package/dist/utilities/utilities.d.ts +2 -2
- package/dist/utilities/utilities.js +117 -105
- package/dist/utilities/utilities.js.map +1 -1
- package/dist/variationConfiguration/index.js +24 -4
- package/dist/variationConfiguration/index.js.map +1 -1
- package/dist/variationConfiguration/types.js +4 -1
- package/dist/variationConfiguration/types.js.map +1 -1
- package/dist/variationConfiguration/variation.js +35 -28
- package/dist/variationConfiguration/variation.js.map +1 -1
- package/dist/variationConfiguration/variationConfiguration.d.ts +5 -5
- package/dist/variationConfiguration/variationConfiguration.js +270 -228
- package/dist/variationConfiguration/variationConfiguration.js.map +1 -1
- package/package.json +6 -4
|
@@ -1,42 +1,64 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
3
6
|
exports.TargetExperimentCondition = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
var _tsRes = require("ts-res");
|
|
8
|
+
var _types = require("../types");
|
|
9
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
10
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
11
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
6
12
|
class TargetExperimentCondition {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
constructor({
|
|
14
|
+
variation,
|
|
15
|
+
experiment,
|
|
16
|
+
isInclude,
|
|
17
|
+
variationMatchType
|
|
18
|
+
}) {
|
|
19
|
+
_defineProperty(this, "inverseResult", void 0);
|
|
20
|
+
_defineProperty(this, "experimentId", void 0);
|
|
21
|
+
_defineProperty(this, "variationId", void 0);
|
|
22
|
+
_defineProperty(this, "matchType", void 0);
|
|
23
|
+
this.inverseResult = !(isInclude ?? true);
|
|
24
|
+
this.experimentId = experiment;
|
|
25
|
+
this.variationId = variation;
|
|
26
|
+
this.matchType = variationMatchType;
|
|
27
|
+
}
|
|
28
|
+
evaluate({
|
|
29
|
+
variationData
|
|
30
|
+
}) {
|
|
31
|
+
if (!this.experimentId) {
|
|
32
|
+
return (0, _tsRes.Ok)(false);
|
|
12
33
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return (0, ts_res_1.Ok)(false);
|
|
16
|
-
}
|
|
17
|
-
if (this.matchType === types_1.MatchTypeVariation.EXACT && !this.variationId) {
|
|
18
|
-
(0, ts_res_1.Ok)(false);
|
|
19
|
-
}
|
|
20
|
-
const result = this.checkCondition({
|
|
21
|
-
variationId: this.variationId,
|
|
22
|
-
experimentId: this.experimentId,
|
|
23
|
-
variationData,
|
|
24
|
-
});
|
|
25
|
-
return (0, ts_res_1.Ok)(this.inverseResult ? !result : result);
|
|
34
|
+
if (this.matchType === _types.MatchTypeVariation.EXACT && !this.variationId) {
|
|
35
|
+
(0, _tsRes.Ok)(false);
|
|
26
36
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const result = this.checkCondition({
|
|
38
|
+
variationId: this.variationId,
|
|
39
|
+
experimentId: this.experimentId,
|
|
40
|
+
variationData
|
|
41
|
+
});
|
|
42
|
+
return (0, _tsRes.Ok)(this.inverseResult ? !result : result);
|
|
43
|
+
}
|
|
44
|
+
checkCondition({
|
|
45
|
+
variationId,
|
|
46
|
+
experimentId,
|
|
47
|
+
variationData
|
|
48
|
+
}) {
|
|
49
|
+
const experimentIdString = String(experimentId);
|
|
50
|
+
const variation = variationData[experimentIdString];
|
|
51
|
+
switch (this.matchType) {
|
|
52
|
+
case _types.MatchTypeVariation.EXACT:
|
|
53
|
+
{
|
|
54
|
+
return variation?.variationId === variationId;
|
|
38
55
|
}
|
|
56
|
+
case _types.MatchTypeVariation.ANY:
|
|
57
|
+
return Boolean(variation);
|
|
58
|
+
default:
|
|
59
|
+
return false;
|
|
39
60
|
}
|
|
61
|
+
}
|
|
40
62
|
}
|
|
41
63
|
exports.TargetExperimentCondition = TargetExperimentCondition;
|
|
42
64
|
//# sourceMappingURL=targetExperimentCondition.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"targetExperimentCondition.js","
|
|
1
|
+
{"version":3,"file":"targetExperimentCondition.js","names":["_tsRes","require","_types","_defineProperty","obj","key","value","_toPropertyKey","Object","defineProperty","enumerable","configurable","writable","arg","_toPrimitive","String","input","hint","prim","Symbol","toPrimitive","undefined","res","call","TypeError","Number","TargetExperimentCondition","constructor","variation","experiment","isInclude","variationMatchType","inverseResult","experimentId","variationId","matchType","evaluate","variationData","Ok","MatchTypeVariation","EXACT","result","checkCondition","experimentIdString","ANY","Boolean","exports"],"sources":["../../../src/targeting/conditions/targetExperimentCondition.ts"],"sourcesContent":["import { Ok, Result } from 'ts-res';\nimport { KameleoonError } from '../../kameleoonError';\nimport { ExperimentVariationsType } from '../../storage';\nimport { EvaluationDataType, MatchTypeVariation } from '../types';\nimport { ConditionDataType, ICondition } from './types';\n\nexport class TargetExperimentCondition implements ICondition {\n private inverseResult: boolean;\n private experimentId?: number | null;\n private variationId?: number | null;\n private matchType?: MatchTypeVariation | null;\n\n constructor({\n variation,\n experiment,\n isInclude,\n variationMatchType,\n }: ConditionDataType) {\n this.inverseResult = !(isInclude ?? true);\n this.experimentId = experiment;\n this.variationId = variation;\n this.matchType = variationMatchType;\n }\n\n evaluate({\n variationData,\n }: EvaluationDataType): Result<boolean, KameleoonError> {\n if (!this.experimentId) {\n return Ok(false);\n }\n\n if (this.matchType === MatchTypeVariation.EXACT && !this.variationId) {\n Ok(false);\n }\n\n const result = this.checkCondition({\n variationId: this.variationId,\n experimentId: this.experimentId,\n variationData,\n });\n\n return Ok(this.inverseResult ? !result : result);\n }\n\n private checkCondition({\n variationId,\n experimentId,\n variationData,\n }: {\n variationId?: number | null;\n experimentId: number;\n variationData: ExperimentVariationsType;\n }): boolean {\n const experimentIdString = String(experimentId);\n const variation = variationData[experimentIdString];\n\n switch (this.matchType) {\n case MatchTypeVariation.EXACT: {\n return variation?.variationId === variationId;\n }\n case MatchTypeVariation.ANY:\n return Boolean(variation);\n default:\n return false;\n }\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAGA,IAAAC,MAAA,GAAAD,OAAA;AAAkE,SAAAE,gBAAAC,GAAA,EAAAC,GAAA,EAAAC,KAAA,IAAAD,GAAA,GAAAE,cAAA,CAAAF,GAAA,OAAAA,GAAA,IAAAD,GAAA,IAAAI,MAAA,CAAAC,cAAA,CAAAL,GAAA,EAAAC,GAAA,IAAAC,KAAA,EAAAA,KAAA,EAAAI,UAAA,QAAAC,YAAA,QAAAC,QAAA,oBAAAR,GAAA,CAAAC,GAAA,IAAAC,KAAA,WAAAF,GAAA;AAAA,SAAAG,eAAAM,GAAA,QAAAR,GAAA,GAAAS,YAAA,CAAAD,GAAA,2BAAAR,GAAA,gBAAAA,GAAA,GAAAU,MAAA,CAAAV,GAAA;AAAA,SAAAS,aAAAE,KAAA,EAAAC,IAAA,eAAAD,KAAA,iBAAAA,KAAA,kBAAAA,KAAA,MAAAE,IAAA,GAAAF,KAAA,CAAAG,MAAA,CAAAC,WAAA,OAAAF,IAAA,KAAAG,SAAA,QAAAC,GAAA,GAAAJ,IAAA,CAAAK,IAAA,CAAAP,KAAA,EAAAC,IAAA,2BAAAK,GAAA,sBAAAA,GAAA,YAAAE,SAAA,4DAAAP,IAAA,gBAAAF,MAAA,GAAAU,MAAA,EAAAT,KAAA;AAG3D,MAAMU,yBAAyB,CAAuB;EAM3DC,WAAWA,CAAC;IACVC,SAAS;IACTC,UAAU;IACVC,SAAS;IACTC;EACiB,CAAC,EAAE;IAAA5B,eAAA;IAAAA,eAAA;IAAAA,eAAA;IAAAA,eAAA;IACpB,IAAI,CAAC6B,aAAa,GAAG,EAAEF,SAAS,IAAI,IAAI,CAAC;IACzC,IAAI,CAACG,YAAY,GAAGJ,UAAU;IAC9B,IAAI,CAACK,WAAW,GAAGN,SAAS;IAC5B,IAAI,CAACO,SAAS,GAAGJ,kBAAkB;EACrC;EAEAK,QAAQA,CAAC;IACPC;EACkB,CAAC,EAAmC;IACtD,IAAI,CAAC,IAAI,CAACJ,YAAY,EAAE;MACtB,OAAO,IAAAK,SAAE,EAAC,KAAK,CAAC;IAClB;IAEA,IAAI,IAAI,CAACH,SAAS,KAAKI,yBAAkB,CAACC,KAAK,IAAI,CAAC,IAAI,CAACN,WAAW,EAAE;MACpE,IAAAI,SAAE,EAAC,KAAK,CAAC;IACX;IAEA,MAAMG,MAAM,GAAG,IAAI,CAACC,cAAc,CAAC;MACjCR,WAAW,EAAE,IAAI,CAACA,WAAW;MAC7BD,YAAY,EAAE,IAAI,CAACA,YAAY;MAC/BI;IACF,CAAC,CAAC;IAEF,OAAO,IAAAC,SAAE,EAAC,IAAI,CAACN,aAAa,GAAG,CAACS,MAAM,GAAGA,MAAM,CAAC;EAClD;EAEQC,cAAcA,CAAC;IACrBR,WAAW;IACXD,YAAY;IACZI;EAKF,CAAC,EAAW;IACV,MAAMM,kBAAkB,GAAG5B,MAAM,CAACkB,YAAY,CAAC;IAC/C,MAAML,SAAS,GAAGS,aAAa,CAACM,kBAAkB,CAAC;IAEnD,QAAQ,IAAI,CAACR,SAAS;MACpB,KAAKI,yBAAkB,CAACC,KAAK;QAAE;UAC7B,OAAOZ,SAAS,EAAEM,WAAW,KAAKA,WAAW;QAC/C;MACA,KAAKK,yBAAkB,CAACK,GAAG;QACzB,OAAOC,OAAO,CAACjB,SAAS,CAAC;MAC3B;QACE,OAAO,KAAK;IAAC;EAEnB;AACF;AAACkB,OAAA,CAAApB,yBAAA,GAAAA,yBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../../src/targeting/conditions/types.ts"],"sourcesContent":["import { Result } from 'ts-res';\nimport { KameleoonError } from '../../kameleoonError';\nimport {\n EvaluationDataType,\n MatchTypeCustomData,\n MatchTypeTest,\n MatchTypeVariation,\n TargetingType,\n} from '../types';\nimport { CustomDataCondition } from './customDataCondition';\nimport { ExclusiveExperimentCondition } from './exclusiveExperimentCondition';\nimport { TargetExperimentCondition } from './targetExperimentCondition';\n\nexport interface ICondition {\n evaluate: (data: EvaluationDataType) => Result<boolean, KameleoonError>;\n}\n\nexport type ConditionType =\n | CustomDataCondition\n | ExclusiveExperimentCondition\n | TargetExperimentCondition;\n\nexport type ConditionDataType = {\n id: number;\n targetingType: TargetingType;\n isInclude: boolean | null;\n weight: number;\n customDataIndex: string | null;\n value: string | null;\n valueMatchType: MatchTypeCustomData | null;\n experiment?: number | null;\n variation?: number | null;\n variationMatchType?: MatchTypeVariation | null;\n testMatchType?: MatchTypeTest | null;\n};\n"],"mappings":""}
|
package/dist/targeting/index.js
CHANGED
|
@@ -1,15 +1,81 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Object.defineProperty(exports, "
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "CustomDataCondition", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _conditions.CustomDataCondition;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "EvaluationDataType", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _types.EvaluationDataType;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "ExclusiveExperimentCondition", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _conditions.ExclusiveExperimentCondition;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "MatchTypeCustomData", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _types.MatchTypeCustomData;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "MatchTypeVariation", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _types.MatchTypeVariation;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "Operator", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () {
|
|
39
|
+
return _types.Operator;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(exports, "SegmentType", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function () {
|
|
45
|
+
return _types.SegmentType;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "TargetExperimentCondition", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return _conditions.TargetExperimentCondition;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(exports, "TargetingDataItemType", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return _types.TargetingDataItemType;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "TargetingDataType", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () {
|
|
63
|
+
return _types.TargetingDataType;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(exports, "TargetingTree", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () {
|
|
69
|
+
return _targetingTree.TargetingTree;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, "TargetingType", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () {
|
|
75
|
+
return _types.TargetingType;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
var _targetingTree = require("./targetingTree");
|
|
79
|
+
var _types = require("./types");
|
|
80
|
+
var _conditions = require("./conditions");
|
|
15
81
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","
|
|
1
|
+
{"version":3,"file":"index.js","names":["_targetingTree","require","_types","_conditions"],"sources":["../../src/targeting/index.ts"],"sourcesContent":["export { TargetingTree } from './targetingTree';\nexport {\n Operator,\n TargetingType,\n SegmentType,\n TargetingDataType,\n EvaluationDataType,\n MatchTypeCustomData,\n MatchTypeVariation,\n TargetingDataItemType,\n} from './types';\nexport {\n CustomDataCondition,\n TargetExperimentCondition,\n ExclusiveExperimentCondition,\n} from './conditions';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AAUA,IAAAE,WAAA,GAAAF,OAAA"}
|
|
@@ -1,40 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
3
6
|
exports.TargetingNode = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
var _conditions = require("./conditions");
|
|
8
|
+
var _types = require("./types");
|
|
9
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
10
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
11
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
6
12
|
class TargetingNode {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
this.rightChild = right;
|
|
22
|
-
}
|
|
23
|
-
get value() {
|
|
24
|
-
return this.nodeValue;
|
|
25
|
-
}
|
|
26
|
-
get error() {
|
|
27
|
-
return this.nodeError;
|
|
28
|
-
}
|
|
29
|
-
get left() {
|
|
30
|
-
return this.leftChild;
|
|
31
|
-
}
|
|
32
|
-
get right() {
|
|
33
|
-
return this.rightChild;
|
|
34
|
-
}
|
|
35
|
-
isOperator(value) {
|
|
36
|
-
return value === types_1.Operator.And || value === types_1.Operator.Or;
|
|
13
|
+
constructor(value, left, right) {
|
|
14
|
+
_defineProperty(this, "nodeValue", void 0);
|
|
15
|
+
_defineProperty(this, "nodeError", void 0);
|
|
16
|
+
_defineProperty(this, "leftChild", void 0);
|
|
17
|
+
_defineProperty(this, "rightChild", void 0);
|
|
18
|
+
if (this.isOperator(value)) {
|
|
19
|
+
this.nodeValue = value;
|
|
20
|
+
} else {
|
|
21
|
+
const result = _conditions.ConditionFactory.createCondition(value);
|
|
22
|
+
if (result.ok) {
|
|
23
|
+
this.nodeValue = result.data;
|
|
24
|
+
} else {
|
|
25
|
+
this.nodeError = result.error;
|
|
26
|
+
}
|
|
37
27
|
}
|
|
28
|
+
this.leftChild = left;
|
|
29
|
+
this.rightChild = right;
|
|
30
|
+
}
|
|
31
|
+
get value() {
|
|
32
|
+
return this.nodeValue;
|
|
33
|
+
}
|
|
34
|
+
get error() {
|
|
35
|
+
return this.nodeError;
|
|
36
|
+
}
|
|
37
|
+
get left() {
|
|
38
|
+
return this.leftChild;
|
|
39
|
+
}
|
|
40
|
+
get right() {
|
|
41
|
+
return this.rightChild;
|
|
42
|
+
}
|
|
43
|
+
isOperator(value) {
|
|
44
|
+
return value === _types.Operator.And || value === _types.Operator.Or;
|
|
45
|
+
}
|
|
38
46
|
}
|
|
39
47
|
exports.TargetingNode = TargetingNode;
|
|
40
48
|
//# sourceMappingURL=targetingNode.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"targetingNode.js","
|
|
1
|
+
{"version":3,"file":"targetingNode.js","names":["_conditions","require","_types","_defineProperty","obj","key","value","_toPropertyKey","Object","defineProperty","enumerable","configurable","writable","arg","_toPrimitive","String","input","hint","prim","Symbol","toPrimitive","undefined","res","call","TypeError","Number","TargetingNode","constructor","left","right","isOperator","nodeValue","result","ConditionFactory","createCondition","ok","data","nodeError","error","leftChild","rightChild","Operator","And","Or","exports"],"sources":["../../src/targeting/targetingNode.ts"],"sourcesContent":["import { KameleoonError } from '../kameleoonError';\nimport { ConditionFactory, ConditionDataType } from './conditions';\nimport { NodeValueType, Operator } from './types';\n\nexport interface ITargetingNode {\n readonly value?: NodeValueType;\n readonly left?: ITargetingNode;\n readonly right?: ITargetingNode;\n readonly error?: KameleoonError;\n}\n\nexport class TargetingNode implements ITargetingNode {\n private nodeValue?: NodeValueType;\n private nodeError?: KameleoonError;\n private leftChild?: ITargetingNode;\n private rightChild?: ITargetingNode;\n\n constructor(\n value: ConditionDataType | Operator,\n left?: ITargetingNode,\n right?: ITargetingNode,\n ) {\n if (this.isOperator(value)) {\n this.nodeValue = value;\n } else {\n const result = ConditionFactory.createCondition(value);\n\n if (result.ok) {\n this.nodeValue = result.data;\n } else {\n this.nodeError = result.error;\n }\n }\n\n this.leftChild = left;\n this.rightChild = right;\n }\n\n get value(): NodeValueType | undefined {\n return this.nodeValue;\n }\n\n get error(): KameleoonError | undefined {\n return this.nodeError;\n }\n\n get left(): ITargetingNode | undefined {\n return this.leftChild;\n }\n\n get right(): ITargetingNode | undefined {\n return this.rightChild;\n }\n\n private isOperator(value: ConditionDataType | Operator): value is Operator {\n return value === Operator.And || value === Operator.Or;\n }\n}\n"],"mappings":";;;;;;AACA,IAAAA,WAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AAAkD,SAAAE,gBAAAC,GAAA,EAAAC,GAAA,EAAAC,KAAA,IAAAD,GAAA,GAAAE,cAAA,CAAAF,GAAA,OAAAA,GAAA,IAAAD,GAAA,IAAAI,MAAA,CAAAC,cAAA,CAAAL,GAAA,EAAAC,GAAA,IAAAC,KAAA,EAAAA,KAAA,EAAAI,UAAA,QAAAC,YAAA,QAAAC,QAAA,oBAAAR,GAAA,CAAAC,GAAA,IAAAC,KAAA,WAAAF,GAAA;AAAA,SAAAG,eAAAM,GAAA,QAAAR,GAAA,GAAAS,YAAA,CAAAD,GAAA,2BAAAR,GAAA,gBAAAA,GAAA,GAAAU,MAAA,CAAAV,GAAA;AAAA,SAAAS,aAAAE,KAAA,EAAAC,IAAA,eAAAD,KAAA,iBAAAA,KAAA,kBAAAA,KAAA,MAAAE,IAAA,GAAAF,KAAA,CAAAG,MAAA,CAAAC,WAAA,OAAAF,IAAA,KAAAG,SAAA,QAAAC,GAAA,GAAAJ,IAAA,CAAAK,IAAA,CAAAP,KAAA,EAAAC,IAAA,2BAAAK,GAAA,sBAAAA,GAAA,YAAAE,SAAA,4DAAAP,IAAA,gBAAAF,MAAA,GAAAU,MAAA,EAAAT,KAAA;AAS3C,MAAMU,aAAa,CAA2B;EAMnDC,WAAWA,CACTrB,KAAmC,EACnCsB,IAAqB,EACrBC,KAAsB,EACtB;IAAA1B,eAAA;IAAAA,eAAA;IAAAA,eAAA;IAAAA,eAAA;IACA,IAAI,IAAI,CAAC2B,UAAU,CAACxB,KAAK,CAAC,EAAE;MAC1B,IAAI,CAACyB,SAAS,GAAGzB,KAAK;IACxB,CAAC,MAAM;MACL,MAAM0B,MAAM,GAAGC,4BAAgB,CAACC,eAAe,CAAC5B,KAAK,CAAC;MAEtD,IAAI0B,MAAM,CAACG,EAAE,EAAE;QACb,IAAI,CAACJ,SAAS,GAAGC,MAAM,CAACI,IAAI;MAC9B,CAAC,MAAM;QACL,IAAI,CAACC,SAAS,GAAGL,MAAM,CAACM,KAAK;MAC/B;IACF;IAEA,IAAI,CAACC,SAAS,GAAGX,IAAI;IACrB,IAAI,CAACY,UAAU,GAAGX,KAAK;EACzB;EAEA,IAAIvB,KAAKA,CAAA,EAA8B;IACrC,OAAO,IAAI,CAACyB,SAAS;EACvB;EAEA,IAAIO,KAAKA,CAAA,EAA+B;IACtC,OAAO,IAAI,CAACD,SAAS;EACvB;EAEA,IAAIT,IAAIA,CAAA,EAA+B;IACrC,OAAO,IAAI,CAACW,SAAS;EACvB;EAEA,IAAIV,KAAKA,CAAA,EAA+B;IACtC,OAAO,IAAI,CAACW,UAAU;EACxB;EAEQV,UAAUA,CAACxB,KAAmC,EAAqB;IACzE,OAAOA,KAAK,KAAKmC,eAAQ,CAACC,GAAG,IAAIpC,KAAK,KAAKmC,eAAQ,CAACE,EAAE;EACxD;AACF;AAACC,OAAA,CAAAlB,aAAA,GAAAA,aAAA"}
|
|
@@ -1,115 +1,136 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
3
6
|
exports.TargetingTree = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
var _tsRes = require("ts-res");
|
|
8
|
+
var _targetingNode = require("./targetingNode");
|
|
9
|
+
var _types = require("./types");
|
|
10
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
11
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
12
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
7
13
|
class TargetingTree {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
14
|
+
constructor(segment) {
|
|
15
|
+
_defineProperty(this, "tree", void 0);
|
|
16
|
+
_defineProperty(this, "error", null);
|
|
17
|
+
const {
|
|
18
|
+
conditions,
|
|
19
|
+
operators
|
|
20
|
+
} = this.flattenSegment(segment);
|
|
21
|
+
const nodes = conditions.map(condition => new _targetingNode.TargetingNode(condition));
|
|
22
|
+
|
|
23
|
+
// --- Note ---
|
|
24
|
+
// - Targeting tree is built bottom-up, it's the only way to both get the consistent logic
|
|
25
|
+
// (grouping nested conditions) and have human readable tree representation.
|
|
26
|
+
// - Here is an example of how tree is built (we use strict complete binary tree)
|
|
27
|
+
// Let's say we have such a condition `value < 10 || value > 20 && value < 30`
|
|
28
|
+
// Code-wise it looks as follows (this is not real code, real tree is more complicated and can have more
|
|
29
|
+
// levels of deeply nested conditions):
|
|
30
|
+
//
|
|
31
|
+
// `const operators = [Operator.Or, Operator.And]`
|
|
32
|
+
// `const conditions = [
|
|
33
|
+
// {type: Condition.Less, value: 10},
|
|
34
|
+
// {type: Condition.Greater, value: 20},
|
|
35
|
+
// {type: Condition.Less, value: 30},
|
|
36
|
+
// ]`
|
|
37
|
+
//
|
|
38
|
+
// After the first iteration we have node like this:
|
|
39
|
+
// AND
|
|
40
|
+
// / \
|
|
41
|
+
// <30 >20
|
|
42
|
+
//
|
|
43
|
+
// After the second iteration tree looks as follows:
|
|
44
|
+
// OR
|
|
45
|
+
// / \
|
|
46
|
+
// AND <10
|
|
47
|
+
// / \
|
|
48
|
+
// <30 >20
|
|
49
|
+
// As you can see Leaf Nodes contain conditions and Non-Leaf Nodes contain logical operators
|
|
50
|
+
for (const operator of operators) {
|
|
51
|
+
const left = nodes.shift();
|
|
52
|
+
const right = nodes.shift();
|
|
53
|
+
nodes.unshift(new _targetingNode.TargetingNode(operator, left, right));
|
|
48
54
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
|
|
56
|
+
// --- Note ---
|
|
57
|
+
// It's guaranteed that only one root node will remain after iterations
|
|
58
|
+
// (as soon as the backend `operators-conditions` relation doesn't change)
|
|
59
|
+
this.tree = nodes[0];
|
|
60
|
+
}
|
|
61
|
+
evaluate(data) {
|
|
62
|
+
const result = this.evaluateNode(this.tree, data);
|
|
63
|
+
if (this.error) {
|
|
64
|
+
return (0, _tsRes.Err)(this.error);
|
|
55
65
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.error = result.error;
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
return result.data;
|
|
68
|
-
}
|
|
69
|
-
if (this.isNonLeafNode(node)) {
|
|
70
|
-
switch (node.value) {
|
|
71
|
-
case types_1.Operator.And: {
|
|
72
|
-
return (this.evaluateNode(node.left, data) &&
|
|
73
|
-
this.evaluateNode(node.right, data));
|
|
74
|
-
}
|
|
75
|
-
case types_1.Operator.Or: {
|
|
76
|
-
return (this.evaluateNode(node.left, data) ||
|
|
77
|
-
this.evaluateNode(node.right, data));
|
|
78
|
-
}
|
|
79
|
-
default:
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
66
|
+
return (0, _tsRes.Ok)(result);
|
|
67
|
+
}
|
|
68
|
+
evaluateNode(node, data) {
|
|
69
|
+
if (this.isLeafNode(node)) {
|
|
70
|
+
if (node.error) {
|
|
71
|
+
// --- Note ---
|
|
72
|
+
// Non-existing condition should not break targeting tree
|
|
73
|
+
// instead it should be treated as `false` condition
|
|
83
74
|
return false;
|
|
75
|
+
}
|
|
76
|
+
const result = node.value.evaluate(data);
|
|
77
|
+
if (!result.ok) {
|
|
78
|
+
this.error = result.error;
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return result.data;
|
|
84
82
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const { conditions: conditionList, orOperators } = condition;
|
|
99
|
-
// --- Note ---
|
|
100
|
-
// if `condition` has nested conditions and operators in it, they go to the
|
|
101
|
-
// beginning of list, otherwise we just add it to the end
|
|
102
|
-
if (orOperators.length) {
|
|
103
|
-
orOperators.forEach((item) => resultOperators.unshift(item));
|
|
104
|
-
conditionList.forEach((item) => resultConditions.unshift(item));
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
conditionList.forEach((item) => resultConditions.push(item));
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
const convertedOperators = resultOperators.map((operator) => operator ? types_1.Operator.Or : types_1.Operator.And);
|
|
111
|
-
return { conditions: resultConditions, operators: convertedOperators };
|
|
83
|
+
if (this.isNonLeafNode(node)) {
|
|
84
|
+
switch (node.value) {
|
|
85
|
+
case _types.Operator.And:
|
|
86
|
+
{
|
|
87
|
+
return this.evaluateNode(node.left, data) && this.evaluateNode(node.right, data);
|
|
88
|
+
}
|
|
89
|
+
case _types.Operator.Or:
|
|
90
|
+
{
|
|
91
|
+
return this.evaluateNode(node.left, data) || this.evaluateNode(node.right, data);
|
|
92
|
+
}
|
|
93
|
+
default:
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
112
96
|
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
isLeafNode(node) {
|
|
100
|
+
return !Boolean(node.left && node.right);
|
|
101
|
+
}
|
|
102
|
+
isNonLeafNode(node) {
|
|
103
|
+
return Boolean(node.left && node.right && (node.value === _types.Operator.Or || node.value === _types.Operator.And));
|
|
104
|
+
}
|
|
105
|
+
flattenSegment(segment) {
|
|
106
|
+
const {
|
|
107
|
+
firstLevel: conditions,
|
|
108
|
+
firstLevelOrOperators: operators
|
|
109
|
+
} = segment.conditionsData;
|
|
110
|
+
const resultOperators = [...operators];
|
|
111
|
+
const resultConditions = [];
|
|
112
|
+
conditions.forEach(condition => {
|
|
113
|
+
const {
|
|
114
|
+
conditions: conditionList,
|
|
115
|
+
orOperators
|
|
116
|
+
} = condition;
|
|
117
|
+
|
|
118
|
+
// --- Note ---
|
|
119
|
+
// if `condition` has nested conditions and operators in it, they go to the
|
|
120
|
+
// beginning of list, otherwise we just add it to the end
|
|
121
|
+
if (orOperators.length) {
|
|
122
|
+
orOperators.forEach(item => resultOperators.unshift(item));
|
|
123
|
+
conditionList.forEach(item => resultConditions.unshift(item));
|
|
124
|
+
} else {
|
|
125
|
+
conditionList.forEach(item => resultConditions.push(item));
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
const convertedOperators = resultOperators.map(operator => operator ? _types.Operator.Or : _types.Operator.And);
|
|
129
|
+
return {
|
|
130
|
+
conditions: resultConditions,
|
|
131
|
+
operators: convertedOperators
|
|
132
|
+
};
|
|
133
|
+
}
|
|
113
134
|
}
|
|
114
135
|
exports.TargetingTree = TargetingTree;
|
|
115
136
|
//# sourceMappingURL=targetingTree.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"targetingTree.js","
|
|
1
|
+
{"version":3,"file":"targetingTree.js","names":["_tsRes","require","_targetingNode","_types","_defineProperty","obj","key","value","_toPropertyKey","Object","defineProperty","enumerable","configurable","writable","arg","_toPrimitive","String","input","hint","prim","Symbol","toPrimitive","undefined","res","call","TypeError","Number","TargetingTree","constructor","segment","conditions","operators","flattenSegment","nodes","map","condition","TargetingNode","operator","left","shift","right","unshift","tree","evaluate","data","result","evaluateNode","error","Err","Ok","node","isLeafNode","ok","isNonLeafNode","Operator","And","Or","Boolean","firstLevel","firstLevelOrOperators","conditionsData","resultOperators","resultConditions","forEach","conditionList","orOperators","length","item","push","convertedOperators","exports"],"sources":["../../src/targeting/targetingTree.ts"],"sourcesContent":["import { Result, Ok, Err } from 'ts-res';\nimport { KameleoonError } from '../kameleoonError';\nimport { ConditionDataType } from './conditions';\nimport { ITargetingNode, TargetingNode } from './targetingNode';\nimport {\n EvaluationDataType,\n FlatSegmentType,\n LeafNodeType,\n NonLeafNodeType,\n Operator,\n SegmentType,\n} from './types';\n\ninterface ITargetingTree {\n evaluate: (data: EvaluationDataType) => Result<boolean, KameleoonError>;\n}\n\nexport class TargetingTree implements ITargetingTree {\n private tree: TargetingNode;\n private error: KameleoonError | null = null;\n\n constructor(segment: SegmentType) {\n const { conditions, operators } = this.flattenSegment(segment);\n const nodes = conditions.map((condition) => new TargetingNode(condition));\n\n // --- Note ---\n // - Targeting tree is built bottom-up, it's the only way to both get the consistent logic\n // (grouping nested conditions) and have human readable tree representation.\n // - Here is an example of how tree is built (we use strict complete binary tree)\n // Let's say we have such a condition `value < 10 || value > 20 && value < 30`\n // Code-wise it looks as follows (this is not real code, real tree is more complicated and can have more\n // levels of deeply nested conditions):\n //\n // `const operators = [Operator.Or, Operator.And]`\n // `const conditions = [\n // {type: Condition.Less, value: 10},\n // {type: Condition.Greater, value: 20},\n // {type: Condition.Less, value: 30},\n // ]`\n //\n // After the first iteration we have node like this:\n // AND\n // / \\\n // <30 >20\n //\n // After the second iteration tree looks as follows:\n // OR\n // / \\\n // AND <10\n // / \\\n // <30 >20\n // As you can see Leaf Nodes contain conditions and Non-Leaf Nodes contain logical operators\n for (const operator of operators) {\n const left = nodes.shift();\n const right = nodes.shift();\n\n nodes.unshift(new TargetingNode(operator, left, right));\n }\n\n // --- Note ---\n // It's guaranteed that only one root node will remain after iterations\n // (as soon as the backend `operators-conditions` relation doesn't change)\n this.tree = nodes[0];\n }\n\n public evaluate(data: EvaluationDataType): Result<boolean, KameleoonError> {\n const result = this.evaluateNode(this.tree, data);\n\n if (this.error) {\n return Err(this.error);\n }\n\n return Ok(result);\n }\n\n private evaluateNode(node: TargetingNode, data: EvaluationDataType): boolean {\n if (this.isLeafNode(node)) {\n if (node.error) {\n // --- Note ---\n // Non-existing condition should not break targeting tree\n // instead it should be treated as `false` condition\n return false;\n }\n\n const result = node.value.evaluate(data);\n\n if (!result.ok) {\n this.error = result.error;\n\n return false;\n }\n\n return result.data;\n }\n\n if (this.isNonLeafNode(node)) {\n switch (node.value) {\n case Operator.And: {\n return (\n this.evaluateNode(node.left, data) &&\n this.evaluateNode(node.right, data)\n );\n }\n case Operator.Or: {\n return (\n this.evaluateNode(node.left, data) ||\n this.evaluateNode(node.right, data)\n );\n }\n default:\n break;\n }\n }\n\n return false;\n }\n\n private isLeafNode(node: ITargetingNode): node is LeafNodeType {\n return !Boolean(node.left && node.right);\n }\n\n private isNonLeafNode(node: ITargetingNode): node is NonLeafNodeType {\n return Boolean(\n node.left &&\n node.right &&\n (node.value === Operator.Or || node.value === Operator.And),\n );\n }\n\n private flattenSegment(segment: SegmentType): FlatSegmentType {\n const { firstLevel: conditions, firstLevelOrOperators: operators } =\n segment.conditionsData;\n\n const resultOperators: boolean[] = [...operators];\n const resultConditions: ConditionDataType[] = [];\n\n conditions.forEach((condition) => {\n const { conditions: conditionList, orOperators } = condition;\n\n // --- Note ---\n // if `condition` has nested conditions and operators in it, they go to the\n // beginning of list, otherwise we just add it to the end\n if (orOperators.length) {\n orOperators.forEach((item) => resultOperators.unshift(item));\n conditionList.forEach((item) => resultConditions.unshift(item));\n } else {\n conditionList.forEach((item) => resultConditions.push(item));\n }\n });\n\n const convertedOperators = resultOperators.map((operator) =>\n operator ? Operator.Or : Operator.And,\n );\n\n return { conditions: resultConditions, operators: convertedOperators };\n }\n}\n"],"mappings":"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"}
|