@kameleoon/javascript-sdk-core 5.16.1 → 5.17.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/CHANGELOG.md +10 -1
- package/dist/clientConfiguration/clientConfiguration.d.ts +4 -1
- package/dist/clientConfiguration/constants.d.ts +2 -3
- package/dist/clientConfiguration/types.d.ts +5 -0
- package/dist/javascript-sdk-core-browser.cjs.js +189 -89
- package/dist/javascript-sdk-core-browser.cjs.js.map +1 -1
- package/dist/javascript-sdk-core-browser.es.js +189 -89
- package/dist/javascript-sdk-core-browser.es.js.map +1 -1
- package/dist/javascript-sdk-core.cjs.js +189 -89
- package/dist/javascript-sdk-core.cjs.js.map +1 -1
- package/dist/javascript-sdk-core.es.js +189 -89
- package/dist/javascript-sdk-core.es.js.map +1 -1
- package/dist/kameleoonClient.d.ts +2 -0
- package/dist/kameleoonData/conversion.d.ts +10 -0
- package/dist/kameleoonData/customData.d.ts +5 -0
- package/dist/kameleoonData/dataManager.d.ts +2 -2
- package/dist/kameleoonData/dataProcessor.d.ts +2 -2
- package/dist/kameleoonData/types.d.ts +5 -3
- package/dist/requester/constants.d.ts +1 -1
- package/dist/requester/urlProvider.d.ts +1 -0
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/types.d.ts +13 -5
- package/dist/variationConfiguration/types.d.ts +2 -0
- package/dist/variationConfiguration/variationConfiguration.d.ts +1 -1
- package/package.json +1 -1
|
@@ -220,10 +220,17 @@ class KameleoonError extends Error {
|
|
|
220
220
|
this.message = ERROR_MESSAGES[type](secondParam, thirdParam);
|
|
221
221
|
break;
|
|
222
222
|
case exports.KameleoonException.FeatureFlagVariationNotFound:
|
|
223
|
-
case exports.KameleoonException.FeatureFlagEnvironmentDisabled:
|
|
224
223
|
case exports.KameleoonException.FeatureFlagVariableNotFound:
|
|
225
224
|
this.message = ERROR_MESSAGES[type](secondParam, thirdParam);
|
|
226
225
|
break;
|
|
226
|
+
case exports.KameleoonException.FeatureFlagEnvironmentDisabled:
|
|
227
|
+
if (thirdParam !== undefined) {
|
|
228
|
+
this.message = ERROR_MESSAGES[type](secondParam, thirdParam);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
this.message = secondParam;
|
|
232
|
+
}
|
|
233
|
+
break;
|
|
227
234
|
case exports.KameleoonException.StorageWrite:
|
|
228
235
|
case exports.KameleoonException.JSONParse:
|
|
229
236
|
this.message = ERROR_MESSAGES[type](secondParam);
|
|
@@ -279,7 +286,7 @@ exports.RequestType = void 0;
|
|
|
279
286
|
RequestType["RemoteData"] = "remoteData";
|
|
280
287
|
})(exports.RequestType || (exports.RequestType = {}));
|
|
281
288
|
|
|
282
|
-
const NUMBER_OF_RETRIES =
|
|
289
|
+
const NUMBER_OF_RETRIES = 1;
|
|
283
290
|
exports.Header = void 0;
|
|
284
291
|
(function (Header) {
|
|
285
292
|
Header["UserAgent"] = "User-Agent";
|
|
@@ -858,6 +865,9 @@ class UrlProvider {
|
|
|
858
865
|
const currentDomain = this.domains[UrlType.DataApi];
|
|
859
866
|
this.domains[UrlType.DataApi] = currentDomain.replace(/^[^.]+/, subDomain);
|
|
860
867
|
}
|
|
868
|
+
get dataApiDomain() {
|
|
869
|
+
return this.domains[UrlType.DataApi];
|
|
870
|
+
}
|
|
861
871
|
getClientConfigurationUrl(timeStamp) {
|
|
862
872
|
this.isInitialized();
|
|
863
873
|
const baseUrl = `https://${this.domains[UrlType.ClientConfiguration]}/v3/`;
|
|
@@ -1117,6 +1127,11 @@ var ConsentType;
|
|
|
1117
1127
|
ConsentType["Required"] = "REQUIRED";
|
|
1118
1128
|
ConsentType["NotRequired"] = "NOT_REQUIRED";
|
|
1119
1129
|
})(ConsentType || (ConsentType = {}));
|
|
1130
|
+
var ConsentBlockingBehaviour;
|
|
1131
|
+
(function (ConsentBlockingBehaviour) {
|
|
1132
|
+
ConsentBlockingBehaviour["PartiallyBlocked"] = "PARTIALLY_BLOCK";
|
|
1133
|
+
ConsentBlockingBehaviour["CompletelyBlocked"] = "FULLY_BLOCK";
|
|
1134
|
+
})(ConsentBlockingBehaviour || (ConsentBlockingBehaviour = {}));
|
|
1120
1135
|
|
|
1121
1136
|
class EventManager {
|
|
1122
1137
|
addEventHandler(eventType, callback) {
|
|
@@ -1144,17 +1159,14 @@ exports.EventType = void 0;
|
|
|
1144
1159
|
EventType["ConfigurationUpdate"] = "configurationUpdate";
|
|
1145
1160
|
})(exports.EventType || (exports.EventType = {}));
|
|
1146
1161
|
|
|
1147
|
-
|
|
1148
|
-
configuration: {
|
|
1149
|
-
consentType: ConsentType.NotRequired},
|
|
1150
|
-
});
|
|
1151
|
-
const DEFAULT_CLIENT_CONFIGURATION$1 = {
|
|
1162
|
+
const DEFAULT_DATA_FILE_CONFIGURATION = {
|
|
1152
1163
|
customData: [],
|
|
1153
1164
|
featureFlags: [],
|
|
1154
1165
|
configuration: {
|
|
1155
1166
|
realTimeUpdate: false,
|
|
1156
1167
|
consentType: ConsentType.NotRequired,
|
|
1157
1168
|
dataApiDomain: 'data.kameleoon.io',
|
|
1169
|
+
consentOptOutBehavior: ConsentBlockingBehaviour.PartiallyBlocked,
|
|
1158
1170
|
},
|
|
1159
1171
|
};
|
|
1160
1172
|
|
|
@@ -1178,7 +1190,7 @@ class ClientConfiguration {
|
|
|
1178
1190
|
constructor({ updateInterval, urlProvider, storage, requester, dataManager, eventSource, externalVisitorCodeManager, eventManager, externalPackageInfo, defaultDataFile, }) {
|
|
1179
1191
|
this.updateConfigurationIntervalId = null;
|
|
1180
1192
|
this.updateType = UpdateType.Polling;
|
|
1181
|
-
this.configurationData =
|
|
1193
|
+
this.configurationData = DEFAULT_DATA_FILE_CONFIGURATION;
|
|
1182
1194
|
this.featureFlagsData = new Map();
|
|
1183
1195
|
this.isTargetedDeliveryRule = null;
|
|
1184
1196
|
this.segmentsData = null;
|
|
@@ -1187,6 +1199,7 @@ class ClientConfiguration {
|
|
|
1187
1199
|
this.mappedRules = null;
|
|
1188
1200
|
this.mappedExperiments = null;
|
|
1189
1201
|
this.usedDefaultDataFile = false;
|
|
1202
|
+
this.blockingBehaviourMode = ConsentBlockingBehaviour.PartiallyBlocked;
|
|
1190
1203
|
this.CACHE_REVALIDATE_PERIOD = 90 * exports.Milliseconds.Minute;
|
|
1191
1204
|
this.urlProvider = urlProvider;
|
|
1192
1205
|
this.requester = requester;
|
|
@@ -1361,6 +1374,9 @@ class ClientConfiguration {
|
|
|
1361
1374
|
get isConsentRequired() {
|
|
1362
1375
|
return this.configuration.consentType === ConsentType.Required;
|
|
1363
1376
|
}
|
|
1377
|
+
get consentBlockingBehaviour() {
|
|
1378
|
+
return this.blockingBehaviourMode;
|
|
1379
|
+
}
|
|
1364
1380
|
get hasAnyTargetedDeliveryRule() {
|
|
1365
1381
|
if (this.isTargetedDeliveryRule !== null) {
|
|
1366
1382
|
return this.isTargetedDeliveryRule;
|
|
@@ -1489,6 +1505,7 @@ class ClientConfiguration {
|
|
|
1489
1505
|
KameleoonLogger.info `Configuration update type was toggled to ${UpdateType[updateType]}`;
|
|
1490
1506
|
yield this.initialize();
|
|
1491
1507
|
}
|
|
1508
|
+
this.blockingBehaviourMode = this.consentBlockingBehaviourFromStr(clientConfigurationData.configuration.consentOptOutBehavior);
|
|
1492
1509
|
return buildExports.Ok(toggleUpdateType);
|
|
1493
1510
|
});
|
|
1494
1511
|
}
|
|
@@ -1595,6 +1612,14 @@ class ClientConfiguration {
|
|
|
1595
1612
|
this.visitorCodeManager.consentRequired =
|
|
1596
1613
|
this.isConsentRequired && !this.hasAnyTargetedDeliveryRule;
|
|
1597
1614
|
}
|
|
1615
|
+
consentBlockingBehaviourFromStr(str) {
|
|
1616
|
+
if (str === ConsentBlockingBehaviour.PartiallyBlocked ||
|
|
1617
|
+
str === ConsentBlockingBehaviour.CompletelyBlocked) {
|
|
1618
|
+
return str;
|
|
1619
|
+
}
|
|
1620
|
+
KameleoonLogger.error(`Unexpected consent blocking type '${str}'`);
|
|
1621
|
+
return ConsentBlockingBehaviour.PartiallyBlocked;
|
|
1622
|
+
}
|
|
1598
1623
|
}
|
|
1599
1624
|
|
|
1600
1625
|
function constructTypeMap(indexMap) {
|
|
@@ -2389,6 +2414,13 @@ let CustomData$1 = class CustomData {
|
|
|
2389
2414
|
get name() {
|
|
2390
2415
|
return this._name;
|
|
2391
2416
|
}
|
|
2417
|
+
/**
|
|
2418
|
+
* @private
|
|
2419
|
+
* @method name - an internal getter for a name of custom data
|
|
2420
|
+
* */
|
|
2421
|
+
get values() {
|
|
2422
|
+
return this.value;
|
|
2423
|
+
}
|
|
2392
2424
|
};
|
|
2393
2425
|
CustomData$1.UNDEFINED_INDEX = -1;
|
|
2394
2426
|
|
|
@@ -2406,7 +2438,7 @@ let Conversion$1 = class Conversion {
|
|
|
2406
2438
|
this.negative = negative;
|
|
2407
2439
|
this.status = exports.TrackingStatus.Unsent;
|
|
2408
2440
|
this.id = Math.floor(Math.random() * 1000000);
|
|
2409
|
-
this.
|
|
2441
|
+
this._metadata = metadata;
|
|
2410
2442
|
}
|
|
2411
2443
|
set _id(id) {
|
|
2412
2444
|
this.id = id;
|
|
@@ -2427,9 +2459,21 @@ let Conversion$1 = class Conversion {
|
|
|
2427
2459
|
? UrlParameter.Metadata + this._encodeMetadata()
|
|
2428
2460
|
: ''));
|
|
2429
2461
|
}
|
|
2462
|
+
/**
|
|
2463
|
+
* @private
|
|
2464
|
+
* @method metadata - an internal getter for a metadata of conversion
|
|
2465
|
+
* */
|
|
2430
2466
|
get _metadata() {
|
|
2431
2467
|
return this.metadata;
|
|
2432
2468
|
}
|
|
2469
|
+
/**
|
|
2470
|
+
* @private
|
|
2471
|
+
* @method metadata - an internal setter for setting metadata of conversion
|
|
2472
|
+
* @param {number} value - an index value
|
|
2473
|
+
* */
|
|
2474
|
+
set _metadata(value) {
|
|
2475
|
+
this.metadata = value;
|
|
2476
|
+
}
|
|
2433
2477
|
get data() {
|
|
2434
2478
|
var _a;
|
|
2435
2479
|
return {
|
|
@@ -3522,7 +3566,7 @@ class DataProcessor {
|
|
|
3522
3566
|
this.cleanupInterval = cleanupInterval;
|
|
3523
3567
|
this.packageInfo = packageInfo;
|
|
3524
3568
|
}
|
|
3525
|
-
mutUpdateData({ infoData, visitorCode, mutData, dataItem, }) {
|
|
3569
|
+
mutUpdateData({ infoData, visitorCode, mutData, dataItem, extendTtl, }) {
|
|
3526
3570
|
let { visitorReference, data, isReference } = this.dereferenceData(mutData, visitorCode);
|
|
3527
3571
|
if (this.packageInfo.isServer &&
|
|
3528
3572
|
isReference &&
|
|
@@ -3533,9 +3577,12 @@ class DataProcessor {
|
|
|
3533
3577
|
delete mutData[visitorCode];
|
|
3534
3578
|
visitorReference = visitorCode;
|
|
3535
3579
|
}
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3580
|
+
let expirationTime;
|
|
3581
|
+
if (extendTtl) {
|
|
3582
|
+
expirationTime = this.cleanupInterval
|
|
3583
|
+
? Date.now() + this.cleanupInterval
|
|
3584
|
+
: 0;
|
|
3585
|
+
}
|
|
3539
3586
|
switch (dataItem.data.type) {
|
|
3540
3587
|
case exports.KameleoonData.CustomData: {
|
|
3541
3588
|
this.updateCustomData({
|
|
@@ -3890,13 +3937,17 @@ class DataProcessor {
|
|
|
3890
3937
|
return closestCleanupTime;
|
|
3891
3938
|
}
|
|
3892
3939
|
updateField({ key, value, data, visitorCode, expirationTime, }) {
|
|
3893
|
-
|
|
3940
|
+
var _a;
|
|
3941
|
+
const existing = data[visitorCode][key];
|
|
3942
|
+
data[visitorCode][key] = Object.assign(Object.assign({}, value), { expirationTime: (_a = expirationTime !== null && expirationTime !== void 0 ? expirationTime : (existing.expirationTime && existing.expirationTime)) !== null && _a !== void 0 ? _a : Date.now() });
|
|
3894
3943
|
}
|
|
3895
3944
|
createField({ key, value, data, visitorCode, expirationTime, }) {
|
|
3896
3945
|
data[visitorCode] = Object.assign(Object.assign({}, data[visitorCode]), { [key]: Object.assign(Object.assign({}, value), { expirationTime }) });
|
|
3897
3946
|
}
|
|
3898
3947
|
updateNestedField({ key, nestedKey, value, data, visitorCode, expirationTime, }) {
|
|
3899
|
-
|
|
3948
|
+
var _a;
|
|
3949
|
+
const existing = data[visitorCode][key][nestedKey];
|
|
3950
|
+
data[visitorCode][key][nestedKey] = Object.assign(Object.assign({}, value), { expirationTime: (_a = expirationTime !== null && expirationTime !== void 0 ? expirationTime : existing === null || existing === void 0 ? void 0 : existing.expirationTime) !== null && _a !== void 0 ? _a : Date.now() });
|
|
3900
3951
|
}
|
|
3901
3952
|
createNestedField({ key, nestedKey, value, data, visitorCode, expirationTime, }) {
|
|
3902
3953
|
var _a;
|
|
@@ -5162,15 +5213,7 @@ exports.KameleoonStorageKey = void 0;
|
|
|
5162
5213
|
KameleoonStorageKey["ForcedExperimentVariation"] = "kameleoonForcedExperimentVariation";
|
|
5163
5214
|
})(exports.KameleoonStorageKey || (exports.KameleoonStorageKey = {}));
|
|
5164
5215
|
const DEFAULT_CLIENT_CONFIGURATION = {
|
|
5165
|
-
data:
|
|
5166
|
-
customData: [],
|
|
5167
|
-
featureFlags: [],
|
|
5168
|
-
configuration: {
|
|
5169
|
-
realTimeUpdate: false,
|
|
5170
|
-
consentType: ConsentType.NotRequired,
|
|
5171
|
-
dataApiDomain: 'data.kameleoon.io',
|
|
5172
|
-
},
|
|
5173
|
-
},
|
|
5216
|
+
data: DEFAULT_DATA_FILE_CONFIGURATION,
|
|
5174
5217
|
lastUpdate: '',
|
|
5175
5218
|
};
|
|
5176
5219
|
// --- Note ---
|
|
@@ -5682,7 +5725,7 @@ class DataManager {
|
|
|
5682
5725
|
return resultData;
|
|
5683
5726
|
}
|
|
5684
5727
|
storeTrackedData(data) {
|
|
5685
|
-
this.storeData(data);
|
|
5728
|
+
this.storeData(data, false);
|
|
5686
5729
|
const infoResult = this.infoStorage.read();
|
|
5687
5730
|
if (!infoResult.ok) {
|
|
5688
5731
|
return;
|
|
@@ -5734,15 +5777,18 @@ class DataManager {
|
|
|
5734
5777
|
targetingData,
|
|
5735
5778
|
visitorCode: firstParameter,
|
|
5736
5779
|
kameleoonData: secondParameter,
|
|
5780
|
+
extendTtl: true,
|
|
5737
5781
|
});
|
|
5738
5782
|
}
|
|
5739
5783
|
else {
|
|
5740
5784
|
for (const [visitorCode, kameleoonData] of Object.entries(firstParameter)) {
|
|
5785
|
+
const extendTtl = typeof secondParameter[0] === 'boolean' ? secondParameter[0] : true;
|
|
5741
5786
|
this.mutUpdateTargetingData({
|
|
5742
5787
|
infoData,
|
|
5743
5788
|
targetingData,
|
|
5744
5789
|
visitorCode,
|
|
5745
5790
|
kameleoonData,
|
|
5791
|
+
extendTtl,
|
|
5746
5792
|
});
|
|
5747
5793
|
}
|
|
5748
5794
|
}
|
|
@@ -5859,8 +5905,8 @@ class DataManager {
|
|
|
5859
5905
|
}
|
|
5860
5906
|
return null;
|
|
5861
5907
|
}
|
|
5862
|
-
mutUpdateTargetingData({ infoData, visitorCode, kameleoonData, targetingData, }) {
|
|
5863
|
-
var _a;
|
|
5908
|
+
mutUpdateTargetingData({ infoData, visitorCode, kameleoonData, targetingData, extendTtl, }) {
|
|
5909
|
+
var _a, _b, _c;
|
|
5864
5910
|
for (const dataItem of kameleoonData) {
|
|
5865
5911
|
// process custom data
|
|
5866
5912
|
if (dataItem.data.type === exports.KameleoonData.CustomData) {
|
|
@@ -5876,16 +5922,21 @@ class DataManager {
|
|
|
5876
5922
|
}
|
|
5877
5923
|
// process metadata of conversions
|
|
5878
5924
|
if (dataItem.data.type === exports.KameleoonData.Conversion) {
|
|
5879
|
-
|
|
5925
|
+
const conversion = dataItem;
|
|
5926
|
+
if (((_b = (_a = conversion._metadata) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0) {
|
|
5927
|
+
conversion._metadata = (_c = conversion._metadata) === null || _c === void 0 ? void 0 : _c.filter((item) => this.trySetCustomDataIndexByName(item));
|
|
5928
|
+
}
|
|
5880
5929
|
}
|
|
5881
5930
|
const expirationTime = this.dataProcessor.mutUpdateData({
|
|
5882
5931
|
infoData,
|
|
5883
5932
|
visitorCode,
|
|
5884
5933
|
mutData: targetingData,
|
|
5885
5934
|
dataItem,
|
|
5935
|
+
extendTtl,
|
|
5886
5936
|
});
|
|
5887
5937
|
const nextCleanup = infoData.nextDataCleanup;
|
|
5888
|
-
if (!nextCleanup ||
|
|
5938
|
+
if (!nextCleanup ||
|
|
5939
|
+
(nextCleanup && expirationTime && expirationTime < nextCleanup)) {
|
|
5889
5940
|
infoData.nextDataCleanup = expirationTime;
|
|
5890
5941
|
}
|
|
5891
5942
|
if (dataItem.data.status === exports.TrackingStatus.Unsent) {
|
|
@@ -5917,7 +5968,9 @@ class DataManager {
|
|
|
5917
5968
|
var _a;
|
|
5918
5969
|
const { data } = customData;
|
|
5919
5970
|
const isDataValid = Boolean(data.value.length && data.value[0].length);
|
|
5920
|
-
this.trySetCustomDataIndexByName(customData)
|
|
5971
|
+
if (!this.trySetCustomDataIndexByName(customData)) {
|
|
5972
|
+
return false;
|
|
5973
|
+
}
|
|
5921
5974
|
if (data.index == CustomData$1.UNDEFINED_INDEX) {
|
|
5922
5975
|
data.index = customData.index;
|
|
5923
5976
|
}
|
|
@@ -5947,13 +6000,15 @@ class DataManager {
|
|
|
5947
6000
|
return true;
|
|
5948
6001
|
}
|
|
5949
6002
|
trySetCustomDataIndexByName(customData) {
|
|
5950
|
-
if (customData.index
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
6003
|
+
if (customData.index !== CustomData$1.UNDEFINED_INDEX)
|
|
6004
|
+
return true;
|
|
6005
|
+
if (!customData.name)
|
|
6006
|
+
return false;
|
|
6007
|
+
const cdIndex = this.customDataIndexByName.get(customData.name);
|
|
6008
|
+
if (cdIndex == null)
|
|
6009
|
+
return false;
|
|
6010
|
+
customData.index = cdIndex;
|
|
6011
|
+
return true;
|
|
5957
6012
|
}
|
|
5958
6013
|
get unsentDataVisitors() {
|
|
5959
6014
|
const infoResult = this.infoStorage.read();
|
|
@@ -7057,6 +7112,13 @@ class Hasher {
|
|
|
7057
7112
|
}
|
|
7058
7113
|
}
|
|
7059
7114
|
|
|
7115
|
+
var LegalConsent;
|
|
7116
|
+
(function (LegalConsent) {
|
|
7117
|
+
LegalConsent[LegalConsent["Unknown"] = 0] = "Unknown";
|
|
7118
|
+
LegalConsent[LegalConsent["Given"] = 1] = "Given";
|
|
7119
|
+
LegalConsent[LegalConsent["NotGiven"] = 2] = "NotGiven";
|
|
7120
|
+
})(LegalConsent || (LegalConsent = {}));
|
|
7121
|
+
|
|
7060
7122
|
class VariationConfiguration {
|
|
7061
7123
|
constructor(externalStorage, externalStorageForcedExperimentVariations, externalStorageForcedFeatureVariations, visitorCodeManager, clientConfiguration) {
|
|
7062
7124
|
this.storage = externalStorage;
|
|
@@ -7115,9 +7177,12 @@ class VariationConfiguration {
|
|
|
7115
7177
|
}
|
|
7116
7178
|
return buildExports.Ok(featureFlagVariations);
|
|
7117
7179
|
}
|
|
7118
|
-
getVariation({ visitorCode, visitorIdentifier, featureFlag, targetingData, packageInfo, clientConfiguration, dataManager, track = true, withAssignment = false, }) {
|
|
7180
|
+
getVariation({ visitorCode, visitorIdentifier, featureFlag, targetingData, packageInfo, clientConfiguration, dataManager, legalConsent, track = true, withAssignment = false, }) {
|
|
7119
7181
|
KameleoonLogger.debug `CALL: VariationConfiguration.getVariation(visitorCode: ${visitorCode}, visitorIdentifier: ${visitorIdentifier}, featureFlag: ${featureFlag}, targetingData: ${targetingData}, packageInfo: ${packageInfo}, clientConfiguration, dataManager, withAssignment: ${withAssignment})`;
|
|
7120
7182
|
const { rules, featureKey, id: featureFlagId, defaultVariationKey, } = featureFlag;
|
|
7183
|
+
const consent = clientConfiguration.isConsentRequired
|
|
7184
|
+
? legalConsent
|
|
7185
|
+
: LegalConsent.Given;
|
|
7121
7186
|
for (const rule of rules) {
|
|
7122
7187
|
const { segment, experimentId, id, exposition, respoolTime, variationByExposition, } = rule;
|
|
7123
7188
|
const forcedVariationData = this.getForcedExperimentVariation(visitorCode, rule.experimentId);
|
|
@@ -7164,6 +7229,16 @@ class VariationConfiguration {
|
|
|
7164
7229
|
});
|
|
7165
7230
|
KameleoonLogger.debug `Calculated ruleHash: ${ruleHash} for code: ${visitorIdentifier}`;
|
|
7166
7231
|
if (ruleHash <= exposition) {
|
|
7232
|
+
// Checking if the evaluation is blocked due to the consent policy
|
|
7233
|
+
if (consent == LegalConsent.NotGiven &&
|
|
7234
|
+
rule.type == RuleType.EXPERIMENTATION) {
|
|
7235
|
+
const behaviour = clientConfiguration.consentBlockingBehaviour;
|
|
7236
|
+
if (behaviour == ConsentBlockingBehaviour.PartiallyBlocked) {
|
|
7237
|
+
break;
|
|
7238
|
+
}
|
|
7239
|
+
return buildExports.Err(new KameleoonError(exports.KameleoonException.FeatureFlagEnvironmentDisabled, `Evaluation of ${rule} is blocked because consent is not provided for visitor '${visitorCode}'`));
|
|
7240
|
+
}
|
|
7241
|
+
// evaluate with CB scores if applicable
|
|
7167
7242
|
let variation = this.evaluateCBScores(rule, visitorIdentifier, targetingData);
|
|
7168
7243
|
if (!variation) {
|
|
7169
7244
|
const variationHash = Hasher.getHashDouble({
|
|
@@ -7525,7 +7600,6 @@ class KameleoonEventSource {
|
|
|
7525
7600
|
const VISITOR_CODE_LENGTH = 16;
|
|
7526
7601
|
const VISITOR_CODE_MAX_LENGTH = 255;
|
|
7527
7602
|
const DEFAULT_MAX_AGE = 60 * 60 * 24 * 365;
|
|
7528
|
-
const ZERO_MAX_AGE = 0;
|
|
7529
7603
|
const PATH = '/';
|
|
7530
7604
|
|
|
7531
7605
|
/**
|
|
@@ -7993,7 +8067,7 @@ class Tracker {
|
|
|
7993
8067
|
this.dataManager.storeTrackedData(updatedData);
|
|
7994
8068
|
}
|
|
7995
8069
|
else {
|
|
7996
|
-
this.dataManager.storeData(updatedData);
|
|
8070
|
+
this.dataManager.storeData(updatedData, false);
|
|
7997
8071
|
}
|
|
7998
8072
|
}
|
|
7999
8073
|
getUnsentVisitorData(visitorCode, isConsentProvided) {
|
|
@@ -8345,16 +8419,23 @@ class KameleoonClient {
|
|
|
8345
8419
|
const variations = new Map();
|
|
8346
8420
|
const featureFlags = this.clientConfiguration.featureFlags;
|
|
8347
8421
|
for (const featureFlag of featureFlags.values()) {
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
if (
|
|
8422
|
+
try {
|
|
8423
|
+
const variation = this._getFeatureVariation({
|
|
8424
|
+
visitorCode,
|
|
8425
|
+
featureKey: featureFlag.featureKey,
|
|
8426
|
+
track,
|
|
8427
|
+
});
|
|
8428
|
+
if (variation.ok &&
|
|
8429
|
+
(!onlyActive || variation.data.key !== OFF_VARIATION_KEY)) {
|
|
8355
8430
|
variations.set(featureFlag.featureKey, variation.data);
|
|
8356
8431
|
}
|
|
8357
8432
|
}
|
|
8433
|
+
catch (err) {
|
|
8434
|
+
if (err instanceof KameleoonError &&
|
|
8435
|
+
err.type !== exports.KameleoonException.FeatureFlagEnvironmentDisabled) {
|
|
8436
|
+
throw err;
|
|
8437
|
+
}
|
|
8438
|
+
}
|
|
8358
8439
|
}
|
|
8359
8440
|
KameleoonLogger.info `RETURN: KameleoonClient.getVariations(visitorCode: ${visitorCode}, onlyActive: ${onlyActive}, track: ${track}) -> (variations: ${variations})`;
|
|
8360
8441
|
return variations;
|
|
@@ -8674,25 +8755,16 @@ class KameleoonClient {
|
|
|
8674
8755
|
path: PATH,
|
|
8675
8756
|
});
|
|
8676
8757
|
}
|
|
8677
|
-
else {
|
|
8678
|
-
if (this.visitorCodeManager.consentRequired) {
|
|
8679
|
-
setData({
|
|
8680
|
-
visitorCode: '',
|
|
8681
|
-
key: exports.KameleoonStorageKey.VisitorCode,
|
|
8682
|
-
maxAge: ZERO_MAX_AGE,
|
|
8683
|
-
path: PATH,
|
|
8684
|
-
});
|
|
8685
|
-
}
|
|
8686
|
-
}
|
|
8687
8758
|
KameleoonLogger.info `RETURN: KameleoonClient.setUserConsent(visitorCode: ${visitorCode}, consent: ${consent}, setData: ${setData})`;
|
|
8688
8759
|
}
|
|
8689
8760
|
updateConsentData(visitorCode, consent) {
|
|
8690
8761
|
const readResult = this.consentDataStorage.read();
|
|
8762
|
+
const legalConsent = consent ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8691
8763
|
if (!readResult.ok) {
|
|
8692
8764
|
if (readResult.error.type === exports.KameleoonException.StorageEmpty) {
|
|
8693
8765
|
this.consentDataStorage.write({
|
|
8694
8766
|
[visitorCode]: {
|
|
8695
|
-
consent,
|
|
8767
|
+
consent: legalConsent,
|
|
8696
8768
|
},
|
|
8697
8769
|
});
|
|
8698
8770
|
}
|
|
@@ -8700,28 +8772,36 @@ class KameleoonClient {
|
|
|
8700
8772
|
}
|
|
8701
8773
|
const data = readResult.data;
|
|
8702
8774
|
data[visitorCode] = {
|
|
8703
|
-
consent,
|
|
8775
|
+
consent: legalConsent,
|
|
8704
8776
|
};
|
|
8705
8777
|
this.consentDataStorage.write(data);
|
|
8706
8778
|
}
|
|
8779
|
+
getLegalConsent(visitorCode) {
|
|
8780
|
+
KameleoonLogger.debug `CALL: KameleoonClient.getLegalConsent(visitorCode: ${visitorCode})`;
|
|
8781
|
+
let legalConsent;
|
|
8782
|
+
const consentDataResult = this.consentDataStorage.read();
|
|
8783
|
+
legalConsent = consentDataResult.ok
|
|
8784
|
+
? this.extractLegalConsent(consentDataResult.data[visitorCode])
|
|
8785
|
+
: LegalConsent.Unknown;
|
|
8786
|
+
KameleoonLogger.debug `RETURN: KameleoonClient.getLegalConsent(visitorCode: ${visitorCode}) -> (legalConsent: ${legalConsent})`;
|
|
8787
|
+
return legalConsent;
|
|
8788
|
+
}
|
|
8789
|
+
extractLegalConsent(consentData) {
|
|
8790
|
+
if (consentData === undefined)
|
|
8791
|
+
return LegalConsent.Unknown;
|
|
8792
|
+
if (typeof consentData === 'boolean') {
|
|
8793
|
+
return consentData ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8794
|
+
}
|
|
8795
|
+
const value = consentData.consent;
|
|
8796
|
+
if (typeof value === 'boolean')
|
|
8797
|
+
return value ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8798
|
+
return value;
|
|
8799
|
+
}
|
|
8707
8800
|
_isConsentProvided(visitorCode) {
|
|
8708
8801
|
KameleoonLogger.debug `CALL: KameleoonClient._isConsentProvided(visitorCode: ${visitorCode})`;
|
|
8709
8802
|
const { isConsentRequired } = this.clientConfiguration;
|
|
8710
|
-
const
|
|
8711
|
-
|
|
8712
|
-
if (!isConsentRequired) {
|
|
8713
|
-
isConsentProvided = true;
|
|
8714
|
-
}
|
|
8715
|
-
else if (consentDataResult.ok) {
|
|
8716
|
-
const consentData = consentDataResult.data[visitorCode];
|
|
8717
|
-
// for consistency with the old data in the storage
|
|
8718
|
-
if (typeof consentData === 'boolean') {
|
|
8719
|
-
isConsentProvided = consentData;
|
|
8720
|
-
}
|
|
8721
|
-
else {
|
|
8722
|
-
isConsentProvided = consentData && consentData.consent;
|
|
8723
|
-
}
|
|
8724
|
-
}
|
|
8803
|
+
const isConsentProvided = !isConsentRequired ||
|
|
8804
|
+
this.getLegalConsent(visitorCode) == LegalConsent.Given;
|
|
8725
8805
|
KameleoonLogger.debug `RETURN: KameleoonClient._isConsentProvided(visitorCode: ${visitorCode}) -> (isConsentProvided: ${isConsentProvided})`;
|
|
8726
8806
|
return isConsentProvided;
|
|
8727
8807
|
}
|
|
@@ -8749,22 +8829,32 @@ class KameleoonClient {
|
|
|
8749
8829
|
if (!featureFlag.environmentEnabled) {
|
|
8750
8830
|
continue;
|
|
8751
8831
|
}
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
if (evalExp.variationKey !== OFF_VARIATION_KEY) {
|
|
8759
|
-
activeVariations.push({
|
|
8760
|
-
variationKey: evalExp.variationKey,
|
|
8761
|
-
variationId: evalExp.variationId,
|
|
8762
|
-
experimentId: evalExp.experimentId,
|
|
8763
|
-
featureFlagId: featureFlag.id,
|
|
8764
|
-
featureKey: featureFlag.featureKey,
|
|
8765
|
-
rule: null,
|
|
8766
|
-
isTargetedRule: evalExp.ruleType === RuleType.TARGETED_DELIVERY,
|
|
8832
|
+
try {
|
|
8833
|
+
const evalExp = this._evaluate({
|
|
8834
|
+
visitorCode,
|
|
8835
|
+
featureFlag,
|
|
8836
|
+
track: false,
|
|
8837
|
+
save: false,
|
|
8767
8838
|
});
|
|
8839
|
+
if (evalExp.variationKey !== OFF_VARIATION_KEY) {
|
|
8840
|
+
activeVariations.push({
|
|
8841
|
+
variationKey: evalExp.variationKey,
|
|
8842
|
+
variationId: evalExp.variationId,
|
|
8843
|
+
experimentId: evalExp.experimentId,
|
|
8844
|
+
featureFlagId: featureFlag.id,
|
|
8845
|
+
featureKey: featureFlag.featureKey,
|
|
8846
|
+
rule: null,
|
|
8847
|
+
isTargetedRule: evalExp.ruleType === RuleType.TARGETED_DELIVERY,
|
|
8848
|
+
});
|
|
8849
|
+
}
|
|
8850
|
+
}
|
|
8851
|
+
catch (err) {
|
|
8852
|
+
if (err instanceof KameleoonError) {
|
|
8853
|
+
if (err.type != exports.KameleoonException.FeatureFlagEnvironmentDisabled) {
|
|
8854
|
+
KameleoonLogger.error `Unexpected error: ${err}`;
|
|
8855
|
+
}
|
|
8856
|
+
continue;
|
|
8857
|
+
}
|
|
8768
8858
|
}
|
|
8769
8859
|
}
|
|
8770
8860
|
KameleoonLogger.debug `RETURN: KameleoonClient._getActiveFeatureVariations(visitorCode: ${visitorCode}) -> (activeVariations: ${activeVariations})`;
|
|
@@ -8785,6 +8875,7 @@ class KameleoonClient {
|
|
|
8785
8875
|
else if (this._isVisitorNotInHoldout(visitorCode, track, save, featureFlag, visitorData) &&
|
|
8786
8876
|
this._isFFUnrestrictedByMEGroup(visitorCode, featureFlag, visitorData)) {
|
|
8787
8877
|
const visitorIdentifier = this._getCodeForHash(visitorCode, featureFlag.bucketingCustomDataIndex, visitorData);
|
|
8878
|
+
const legalConsent = this.getLegalConsent(visitorCode);
|
|
8788
8879
|
const variationData = this.variationConfiguration
|
|
8789
8880
|
.getVariation({
|
|
8790
8881
|
visitorCode,
|
|
@@ -8796,6 +8887,7 @@ class KameleoonClient {
|
|
|
8796
8887
|
clientConfiguration: this.clientConfiguration,
|
|
8797
8888
|
dataManager: this.dataManager,
|
|
8798
8889
|
packageInfo: this.externalPackageInfo,
|
|
8890
|
+
legalConsent,
|
|
8799
8891
|
})
|
|
8800
8892
|
.throw();
|
|
8801
8893
|
evalExp =
|
|
@@ -8914,6 +9006,14 @@ class KameleoonClient {
|
|
|
8914
9006
|
}
|
|
8915
9007
|
KameleoonLogger.debug `CALL: KameleoonClient._isVisitorNotInHoldout(visitorCode: ${visitorCode}, track: ${track}, save: ${save}, featureFlag: ${featureFlag}, visitorData: ${visitorData})`;
|
|
8916
9008
|
let isNotInHoldout = true;
|
|
9009
|
+
// Checking if the evaluation is blocked due to the consent policy
|
|
9010
|
+
const legalConsent = this.getLegalConsent(visitorCode);
|
|
9011
|
+
if (legalConsent == LegalConsent.NotGiven) {
|
|
9012
|
+
const behaviour = this.clientConfiguration.consentBlockingBehaviour;
|
|
9013
|
+
if (behaviour == ConsentBlockingBehaviour.CompletelyBlocked) {
|
|
9014
|
+
throw new KameleoonError(exports.KameleoonException.FeatureFlagEnvironmentDisabled, `Evaluation of holdout is blocked because consent is not provided for visitor '${visitorCode}'`);
|
|
9015
|
+
}
|
|
9016
|
+
}
|
|
8917
9017
|
const codeForHash = this._getCodeForHash(visitorCode, featureFlag === null || featureFlag === void 0 ? void 0 : featureFlag.bucketingCustomDataIndex, visitorData);
|
|
8918
9018
|
const holdoutHash = Hasher.getHashDouble({
|
|
8919
9019
|
visitorIdentifier: codeForHash,
|