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