@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
|
@@ -247,10 +247,17 @@ class KameleoonError extends Error {
|
|
|
247
247
|
this.message = ERROR_MESSAGES[type](secondParam, thirdParam);
|
|
248
248
|
break;
|
|
249
249
|
case KameleoonException.FeatureFlagVariationNotFound:
|
|
250
|
-
case KameleoonException.FeatureFlagEnvironmentDisabled:
|
|
251
250
|
case KameleoonException.FeatureFlagVariableNotFound:
|
|
252
251
|
this.message = ERROR_MESSAGES[type](secondParam, thirdParam);
|
|
253
252
|
break;
|
|
253
|
+
case KameleoonException.FeatureFlagEnvironmentDisabled:
|
|
254
|
+
if (thirdParam !== undefined) {
|
|
255
|
+
this.message = ERROR_MESSAGES[type](secondParam, thirdParam);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
this.message = secondParam;
|
|
259
|
+
}
|
|
260
|
+
break;
|
|
254
261
|
case KameleoonException.StorageWrite:
|
|
255
262
|
case KameleoonException.JSONParse:
|
|
256
263
|
this.message = ERROR_MESSAGES[type](secondParam);
|
|
@@ -306,7 +313,7 @@ var RequestType;
|
|
|
306
313
|
RequestType["RemoteData"] = "remoteData";
|
|
307
314
|
})(RequestType || (RequestType = {}));
|
|
308
315
|
|
|
309
|
-
const NUMBER_OF_RETRIES =
|
|
316
|
+
const NUMBER_OF_RETRIES = 1;
|
|
310
317
|
var Header;
|
|
311
318
|
(function (Header) {
|
|
312
319
|
Header["UserAgent"] = "User-Agent";
|
|
@@ -885,6 +892,9 @@ class UrlProvider {
|
|
|
885
892
|
const currentDomain = this.domains[UrlType.DataApi];
|
|
886
893
|
this.domains[UrlType.DataApi] = currentDomain.replace(/^[^.]+/, subDomain);
|
|
887
894
|
}
|
|
895
|
+
get dataApiDomain() {
|
|
896
|
+
return this.domains[UrlType.DataApi];
|
|
897
|
+
}
|
|
888
898
|
getClientConfigurationUrl(timeStamp) {
|
|
889
899
|
this.isInitialized();
|
|
890
900
|
const baseUrl = `https://${this.domains[UrlType.ClientConfiguration]}/v3/`;
|
|
@@ -1144,6 +1154,11 @@ var ConsentType;
|
|
|
1144
1154
|
ConsentType["Required"] = "REQUIRED";
|
|
1145
1155
|
ConsentType["NotRequired"] = "NOT_REQUIRED";
|
|
1146
1156
|
})(ConsentType || (ConsentType = {}));
|
|
1157
|
+
var ConsentBlockingBehaviour;
|
|
1158
|
+
(function (ConsentBlockingBehaviour) {
|
|
1159
|
+
ConsentBlockingBehaviour["PartiallyBlocked"] = "PARTIALLY_BLOCK";
|
|
1160
|
+
ConsentBlockingBehaviour["CompletelyBlocked"] = "FULLY_BLOCK";
|
|
1161
|
+
})(ConsentBlockingBehaviour || (ConsentBlockingBehaviour = {}));
|
|
1147
1162
|
|
|
1148
1163
|
class EventManager {
|
|
1149
1164
|
addEventHandler(eventType, callback) {
|
|
@@ -1171,17 +1186,14 @@ var EventType;
|
|
|
1171
1186
|
EventType["ConfigurationUpdate"] = "configurationUpdate";
|
|
1172
1187
|
})(EventType || (EventType = {}));
|
|
1173
1188
|
|
|
1174
|
-
|
|
1175
|
-
configuration: {
|
|
1176
|
-
consentType: ConsentType.NotRequired},
|
|
1177
|
-
});
|
|
1178
|
-
const DEFAULT_CLIENT_CONFIGURATION$1 = {
|
|
1189
|
+
const DEFAULT_DATA_FILE_CONFIGURATION = {
|
|
1179
1190
|
customData: [],
|
|
1180
1191
|
featureFlags: [],
|
|
1181
1192
|
configuration: {
|
|
1182
1193
|
realTimeUpdate: false,
|
|
1183
1194
|
consentType: ConsentType.NotRequired,
|
|
1184
1195
|
dataApiDomain: 'data.kameleoon.io',
|
|
1196
|
+
consentOptOutBehavior: ConsentBlockingBehaviour.PartiallyBlocked,
|
|
1185
1197
|
},
|
|
1186
1198
|
};
|
|
1187
1199
|
|
|
@@ -1205,7 +1217,7 @@ class ClientConfiguration {
|
|
|
1205
1217
|
constructor({ updateInterval, urlProvider, storage, requester, dataManager, eventSource, externalVisitorCodeManager, eventManager, externalPackageInfo, defaultDataFile, }) {
|
|
1206
1218
|
this.updateConfigurationIntervalId = null;
|
|
1207
1219
|
this.updateType = UpdateType.Polling;
|
|
1208
|
-
this.configurationData =
|
|
1220
|
+
this.configurationData = DEFAULT_DATA_FILE_CONFIGURATION;
|
|
1209
1221
|
this.featureFlagsData = new Map();
|
|
1210
1222
|
this.isTargetedDeliveryRule = null;
|
|
1211
1223
|
this.segmentsData = null;
|
|
@@ -1214,6 +1226,7 @@ class ClientConfiguration {
|
|
|
1214
1226
|
this.mappedRules = null;
|
|
1215
1227
|
this.mappedExperiments = null;
|
|
1216
1228
|
this.usedDefaultDataFile = false;
|
|
1229
|
+
this.blockingBehaviourMode = ConsentBlockingBehaviour.PartiallyBlocked;
|
|
1217
1230
|
this.CACHE_REVALIDATE_PERIOD = 90 * Milliseconds.Minute;
|
|
1218
1231
|
this.urlProvider = urlProvider;
|
|
1219
1232
|
this.requester = requester;
|
|
@@ -1388,6 +1401,9 @@ class ClientConfiguration {
|
|
|
1388
1401
|
get isConsentRequired() {
|
|
1389
1402
|
return this.configuration.consentType === ConsentType.Required;
|
|
1390
1403
|
}
|
|
1404
|
+
get consentBlockingBehaviour() {
|
|
1405
|
+
return this.blockingBehaviourMode;
|
|
1406
|
+
}
|
|
1391
1407
|
get hasAnyTargetedDeliveryRule() {
|
|
1392
1408
|
if (this.isTargetedDeliveryRule !== null) {
|
|
1393
1409
|
return this.isTargetedDeliveryRule;
|
|
@@ -1516,6 +1532,7 @@ class ClientConfiguration {
|
|
|
1516
1532
|
KameleoonLogger.info `Configuration update type was toggled to ${UpdateType[updateType]}`;
|
|
1517
1533
|
yield this.initialize();
|
|
1518
1534
|
}
|
|
1535
|
+
this.blockingBehaviourMode = this.consentBlockingBehaviourFromStr(clientConfigurationData.configuration.consentOptOutBehavior);
|
|
1519
1536
|
return buildExports.Ok(toggleUpdateType);
|
|
1520
1537
|
});
|
|
1521
1538
|
}
|
|
@@ -1622,6 +1639,14 @@ class ClientConfiguration {
|
|
|
1622
1639
|
this.visitorCodeManager.consentRequired =
|
|
1623
1640
|
this.isConsentRequired && !this.hasAnyTargetedDeliveryRule;
|
|
1624
1641
|
}
|
|
1642
|
+
consentBlockingBehaviourFromStr(str) {
|
|
1643
|
+
if (str === ConsentBlockingBehaviour.PartiallyBlocked ||
|
|
1644
|
+
str === ConsentBlockingBehaviour.CompletelyBlocked) {
|
|
1645
|
+
return str;
|
|
1646
|
+
}
|
|
1647
|
+
KameleoonLogger.error(`Unexpected consent blocking type '${str}'`);
|
|
1648
|
+
return ConsentBlockingBehaviour.PartiallyBlocked;
|
|
1649
|
+
}
|
|
1625
1650
|
}
|
|
1626
1651
|
|
|
1627
1652
|
function constructTypeMap(indexMap) {
|
|
@@ -2416,6 +2441,13 @@ let CustomData$1 = class CustomData {
|
|
|
2416
2441
|
get name() {
|
|
2417
2442
|
return this._name;
|
|
2418
2443
|
}
|
|
2444
|
+
/**
|
|
2445
|
+
* @private
|
|
2446
|
+
* @method name - an internal getter for a name of custom data
|
|
2447
|
+
* */
|
|
2448
|
+
get values() {
|
|
2449
|
+
return this.value;
|
|
2450
|
+
}
|
|
2419
2451
|
};
|
|
2420
2452
|
CustomData$1.UNDEFINED_INDEX = -1;
|
|
2421
2453
|
|
|
@@ -2433,7 +2465,7 @@ let Conversion$1 = class Conversion {
|
|
|
2433
2465
|
this.negative = negative;
|
|
2434
2466
|
this.status = TrackingStatus.Unsent;
|
|
2435
2467
|
this.id = Math.floor(Math.random() * 1000000);
|
|
2436
|
-
this.
|
|
2468
|
+
this._metadata = metadata;
|
|
2437
2469
|
}
|
|
2438
2470
|
set _id(id) {
|
|
2439
2471
|
this.id = id;
|
|
@@ -2454,9 +2486,21 @@ let Conversion$1 = class Conversion {
|
|
|
2454
2486
|
? UrlParameter.Metadata + this._encodeMetadata()
|
|
2455
2487
|
: ''));
|
|
2456
2488
|
}
|
|
2489
|
+
/**
|
|
2490
|
+
* @private
|
|
2491
|
+
* @method metadata - an internal getter for a metadata of conversion
|
|
2492
|
+
* */
|
|
2457
2493
|
get _metadata() {
|
|
2458
2494
|
return this.metadata;
|
|
2459
2495
|
}
|
|
2496
|
+
/**
|
|
2497
|
+
* @private
|
|
2498
|
+
* @method metadata - an internal setter for setting metadata of conversion
|
|
2499
|
+
* @param {number} value - an index value
|
|
2500
|
+
* */
|
|
2501
|
+
set _metadata(value) {
|
|
2502
|
+
this.metadata = value;
|
|
2503
|
+
}
|
|
2460
2504
|
get data() {
|
|
2461
2505
|
var _a;
|
|
2462
2506
|
return {
|
|
@@ -3549,7 +3593,7 @@ class DataProcessor {
|
|
|
3549
3593
|
this.cleanupInterval = cleanupInterval;
|
|
3550
3594
|
this.packageInfo = packageInfo;
|
|
3551
3595
|
}
|
|
3552
|
-
mutUpdateData({ infoData, visitorCode, mutData, dataItem, }) {
|
|
3596
|
+
mutUpdateData({ infoData, visitorCode, mutData, dataItem, extendTtl, }) {
|
|
3553
3597
|
let { visitorReference, data, isReference } = this.dereferenceData(mutData, visitorCode);
|
|
3554
3598
|
if (this.packageInfo.isServer &&
|
|
3555
3599
|
isReference &&
|
|
@@ -3560,9 +3604,12 @@ class DataProcessor {
|
|
|
3560
3604
|
delete mutData[visitorCode];
|
|
3561
3605
|
visitorReference = visitorCode;
|
|
3562
3606
|
}
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3607
|
+
let expirationTime;
|
|
3608
|
+
if (extendTtl) {
|
|
3609
|
+
expirationTime = this.cleanupInterval
|
|
3610
|
+
? Date.now() + this.cleanupInterval
|
|
3611
|
+
: 0;
|
|
3612
|
+
}
|
|
3566
3613
|
switch (dataItem.data.type) {
|
|
3567
3614
|
case KameleoonData.CustomData: {
|
|
3568
3615
|
this.updateCustomData({
|
|
@@ -3917,13 +3964,17 @@ class DataProcessor {
|
|
|
3917
3964
|
return closestCleanupTime;
|
|
3918
3965
|
}
|
|
3919
3966
|
updateField({ key, value, data, visitorCode, expirationTime, }) {
|
|
3920
|
-
|
|
3967
|
+
var _a;
|
|
3968
|
+
const existing = data[visitorCode][key];
|
|
3969
|
+
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() });
|
|
3921
3970
|
}
|
|
3922
3971
|
createField({ key, value, data, visitorCode, expirationTime, }) {
|
|
3923
3972
|
data[visitorCode] = Object.assign(Object.assign({}, data[visitorCode]), { [key]: Object.assign(Object.assign({}, value), { expirationTime }) });
|
|
3924
3973
|
}
|
|
3925
3974
|
updateNestedField({ key, nestedKey, value, data, visitorCode, expirationTime, }) {
|
|
3926
|
-
|
|
3975
|
+
var _a;
|
|
3976
|
+
const existing = data[visitorCode][key][nestedKey];
|
|
3977
|
+
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() });
|
|
3927
3978
|
}
|
|
3928
3979
|
createNestedField({ key, nestedKey, value, data, visitorCode, expirationTime, }) {
|
|
3929
3980
|
var _a;
|
|
@@ -5189,15 +5240,7 @@ var KameleoonStorageKey;
|
|
|
5189
5240
|
KameleoonStorageKey["ForcedExperimentVariation"] = "kameleoonForcedExperimentVariation";
|
|
5190
5241
|
})(KameleoonStorageKey || (KameleoonStorageKey = {}));
|
|
5191
5242
|
const DEFAULT_CLIENT_CONFIGURATION = {
|
|
5192
|
-
data:
|
|
5193
|
-
customData: [],
|
|
5194
|
-
featureFlags: [],
|
|
5195
|
-
configuration: {
|
|
5196
|
-
realTimeUpdate: false,
|
|
5197
|
-
consentType: ConsentType.NotRequired,
|
|
5198
|
-
dataApiDomain: 'data.kameleoon.io',
|
|
5199
|
-
},
|
|
5200
|
-
},
|
|
5243
|
+
data: DEFAULT_DATA_FILE_CONFIGURATION,
|
|
5201
5244
|
lastUpdate: '',
|
|
5202
5245
|
};
|
|
5203
5246
|
// --- Note ---
|
|
@@ -5709,7 +5752,7 @@ class DataManager {
|
|
|
5709
5752
|
return resultData;
|
|
5710
5753
|
}
|
|
5711
5754
|
storeTrackedData(data) {
|
|
5712
|
-
this.storeData(data);
|
|
5755
|
+
this.storeData(data, false);
|
|
5713
5756
|
const infoResult = this.infoStorage.read();
|
|
5714
5757
|
if (!infoResult.ok) {
|
|
5715
5758
|
return;
|
|
@@ -5761,15 +5804,18 @@ class DataManager {
|
|
|
5761
5804
|
targetingData,
|
|
5762
5805
|
visitorCode: firstParameter,
|
|
5763
5806
|
kameleoonData: secondParameter,
|
|
5807
|
+
extendTtl: true,
|
|
5764
5808
|
});
|
|
5765
5809
|
}
|
|
5766
5810
|
else {
|
|
5767
5811
|
for (const [visitorCode, kameleoonData] of Object.entries(firstParameter)) {
|
|
5812
|
+
const extendTtl = typeof secondParameter[0] === 'boolean' ? secondParameter[0] : true;
|
|
5768
5813
|
this.mutUpdateTargetingData({
|
|
5769
5814
|
infoData,
|
|
5770
5815
|
targetingData,
|
|
5771
5816
|
visitorCode,
|
|
5772
5817
|
kameleoonData,
|
|
5818
|
+
extendTtl,
|
|
5773
5819
|
});
|
|
5774
5820
|
}
|
|
5775
5821
|
}
|
|
@@ -5886,8 +5932,8 @@ class DataManager {
|
|
|
5886
5932
|
}
|
|
5887
5933
|
return null;
|
|
5888
5934
|
}
|
|
5889
|
-
mutUpdateTargetingData({ infoData, visitorCode, kameleoonData, targetingData, }) {
|
|
5890
|
-
var _a;
|
|
5935
|
+
mutUpdateTargetingData({ infoData, visitorCode, kameleoonData, targetingData, extendTtl, }) {
|
|
5936
|
+
var _a, _b, _c;
|
|
5891
5937
|
for (const dataItem of kameleoonData) {
|
|
5892
5938
|
// process custom data
|
|
5893
5939
|
if (dataItem.data.type === KameleoonData.CustomData) {
|
|
@@ -5903,16 +5949,21 @@ class DataManager {
|
|
|
5903
5949
|
}
|
|
5904
5950
|
// process metadata of conversions
|
|
5905
5951
|
if (dataItem.data.type === KameleoonData.Conversion) {
|
|
5906
|
-
|
|
5952
|
+
const conversion = dataItem;
|
|
5953
|
+
if (((_b = (_a = conversion._metadata) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0) {
|
|
5954
|
+
conversion._metadata = (_c = conversion._metadata) === null || _c === void 0 ? void 0 : _c.filter((item) => this.trySetCustomDataIndexByName(item));
|
|
5955
|
+
}
|
|
5907
5956
|
}
|
|
5908
5957
|
const expirationTime = this.dataProcessor.mutUpdateData({
|
|
5909
5958
|
infoData,
|
|
5910
5959
|
visitorCode,
|
|
5911
5960
|
mutData: targetingData,
|
|
5912
5961
|
dataItem,
|
|
5962
|
+
extendTtl,
|
|
5913
5963
|
});
|
|
5914
5964
|
const nextCleanup = infoData.nextDataCleanup;
|
|
5915
|
-
if (!nextCleanup ||
|
|
5965
|
+
if (!nextCleanup ||
|
|
5966
|
+
(nextCleanup && expirationTime && expirationTime < nextCleanup)) {
|
|
5916
5967
|
infoData.nextDataCleanup = expirationTime;
|
|
5917
5968
|
}
|
|
5918
5969
|
if (dataItem.data.status === TrackingStatus.Unsent) {
|
|
@@ -5944,7 +5995,9 @@ class DataManager {
|
|
|
5944
5995
|
var _a;
|
|
5945
5996
|
const { data } = customData;
|
|
5946
5997
|
const isDataValid = Boolean(data.value.length && data.value[0].length);
|
|
5947
|
-
this.trySetCustomDataIndexByName(customData)
|
|
5998
|
+
if (!this.trySetCustomDataIndexByName(customData)) {
|
|
5999
|
+
return false;
|
|
6000
|
+
}
|
|
5948
6001
|
if (data.index == CustomData$1.UNDEFINED_INDEX) {
|
|
5949
6002
|
data.index = customData.index;
|
|
5950
6003
|
}
|
|
@@ -5974,13 +6027,15 @@ class DataManager {
|
|
|
5974
6027
|
return true;
|
|
5975
6028
|
}
|
|
5976
6029
|
trySetCustomDataIndexByName(customData) {
|
|
5977
|
-
if (customData.index
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
6030
|
+
if (customData.index !== CustomData$1.UNDEFINED_INDEX)
|
|
6031
|
+
return true;
|
|
6032
|
+
if (!customData.name)
|
|
6033
|
+
return false;
|
|
6034
|
+
const cdIndex = this.customDataIndexByName.get(customData.name);
|
|
6035
|
+
if (cdIndex == null)
|
|
6036
|
+
return false;
|
|
6037
|
+
customData.index = cdIndex;
|
|
6038
|
+
return true;
|
|
5984
6039
|
}
|
|
5985
6040
|
get unsentDataVisitors() {
|
|
5986
6041
|
const infoResult = this.infoStorage.read();
|
|
@@ -7093,6 +7148,13 @@ class Hasher {
|
|
|
7093
7148
|
}
|
|
7094
7149
|
}
|
|
7095
7150
|
|
|
7151
|
+
var LegalConsent;
|
|
7152
|
+
(function (LegalConsent) {
|
|
7153
|
+
LegalConsent[LegalConsent["Unknown"] = 0] = "Unknown";
|
|
7154
|
+
LegalConsent[LegalConsent["Given"] = 1] = "Given";
|
|
7155
|
+
LegalConsent[LegalConsent["NotGiven"] = 2] = "NotGiven";
|
|
7156
|
+
})(LegalConsent || (LegalConsent = {}));
|
|
7157
|
+
|
|
7096
7158
|
class VariationConfiguration {
|
|
7097
7159
|
constructor(externalStorage, externalStorageForcedExperimentVariations, externalStorageForcedFeatureVariations, visitorCodeManager, clientConfiguration) {
|
|
7098
7160
|
this.storage = externalStorage;
|
|
@@ -7151,9 +7213,12 @@ class VariationConfiguration {
|
|
|
7151
7213
|
}
|
|
7152
7214
|
return buildExports.Ok(featureFlagVariations);
|
|
7153
7215
|
}
|
|
7154
|
-
getVariation({ visitorCode, visitorIdentifier, featureFlag, targetingData, packageInfo, clientConfiguration, dataManager, track = true, withAssignment = false, }) {
|
|
7216
|
+
getVariation({ visitorCode, visitorIdentifier, featureFlag, targetingData, packageInfo, clientConfiguration, dataManager, legalConsent, track = true, withAssignment = false, }) {
|
|
7155
7217
|
KameleoonLogger.debug `CALL: VariationConfiguration.getVariation(visitorCode: ${visitorCode}, visitorIdentifier: ${visitorIdentifier}, featureFlag: ${featureFlag}, targetingData: ${targetingData}, packageInfo: ${packageInfo}, clientConfiguration, dataManager, withAssignment: ${withAssignment})`;
|
|
7156
7218
|
const { rules, featureKey, id: featureFlagId, defaultVariationKey, } = featureFlag;
|
|
7219
|
+
const consent = clientConfiguration.isConsentRequired
|
|
7220
|
+
? legalConsent
|
|
7221
|
+
: LegalConsent.Given;
|
|
7157
7222
|
for (const rule of rules) {
|
|
7158
7223
|
const { segment, experimentId, id, exposition, respoolTime, variationByExposition, } = rule;
|
|
7159
7224
|
const forcedVariationData = this.getForcedExperimentVariation(visitorCode, rule.experimentId);
|
|
@@ -7200,6 +7265,16 @@ class VariationConfiguration {
|
|
|
7200
7265
|
});
|
|
7201
7266
|
KameleoonLogger.debug `Calculated ruleHash: ${ruleHash} for code: ${visitorIdentifier}`;
|
|
7202
7267
|
if (ruleHash <= exposition) {
|
|
7268
|
+
// Checking if the evaluation is blocked due to the consent policy
|
|
7269
|
+
if (consent == LegalConsent.NotGiven &&
|
|
7270
|
+
rule.type == RuleType.EXPERIMENTATION) {
|
|
7271
|
+
const behaviour = clientConfiguration.consentBlockingBehaviour;
|
|
7272
|
+
if (behaviour == ConsentBlockingBehaviour.PartiallyBlocked) {
|
|
7273
|
+
break;
|
|
7274
|
+
}
|
|
7275
|
+
return buildExports.Err(new KameleoonError(KameleoonException.FeatureFlagEnvironmentDisabled, `Evaluation of ${rule} is blocked because consent is not provided for visitor '${visitorCode}'`));
|
|
7276
|
+
}
|
|
7277
|
+
// evaluate with CB scores if applicable
|
|
7203
7278
|
let variation = this.evaluateCBScores(rule, visitorIdentifier, targetingData);
|
|
7204
7279
|
if (!variation) {
|
|
7205
7280
|
const variationHash = Hasher.getHashDouble({
|
|
@@ -7561,7 +7636,6 @@ class KameleoonEventSource {
|
|
|
7561
7636
|
const VISITOR_CODE_LENGTH = 16;
|
|
7562
7637
|
const VISITOR_CODE_MAX_LENGTH = 255;
|
|
7563
7638
|
const DEFAULT_MAX_AGE = 60 * 60 * 24 * 365;
|
|
7564
|
-
const ZERO_MAX_AGE = 0;
|
|
7565
7639
|
const PATH = '/';
|
|
7566
7640
|
|
|
7567
7641
|
/**
|
|
@@ -8029,7 +8103,7 @@ class Tracker {
|
|
|
8029
8103
|
this.dataManager.storeTrackedData(updatedData);
|
|
8030
8104
|
}
|
|
8031
8105
|
else {
|
|
8032
|
-
this.dataManager.storeData(updatedData);
|
|
8106
|
+
this.dataManager.storeData(updatedData, false);
|
|
8033
8107
|
}
|
|
8034
8108
|
}
|
|
8035
8109
|
getUnsentVisitorData(visitorCode, isConsentProvided) {
|
|
@@ -8381,16 +8455,23 @@ class KameleoonClient {
|
|
|
8381
8455
|
const variations = new Map();
|
|
8382
8456
|
const featureFlags = this.clientConfiguration.featureFlags;
|
|
8383
8457
|
for (const featureFlag of featureFlags.values()) {
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
if (
|
|
8458
|
+
try {
|
|
8459
|
+
const variation = this._getFeatureVariation({
|
|
8460
|
+
visitorCode,
|
|
8461
|
+
featureKey: featureFlag.featureKey,
|
|
8462
|
+
track,
|
|
8463
|
+
});
|
|
8464
|
+
if (variation.ok &&
|
|
8465
|
+
(!onlyActive || variation.data.key !== OFF_VARIATION_KEY)) {
|
|
8391
8466
|
variations.set(featureFlag.featureKey, variation.data);
|
|
8392
8467
|
}
|
|
8393
8468
|
}
|
|
8469
|
+
catch (err) {
|
|
8470
|
+
if (err instanceof KameleoonError &&
|
|
8471
|
+
err.type !== KameleoonException.FeatureFlagEnvironmentDisabled) {
|
|
8472
|
+
throw err;
|
|
8473
|
+
}
|
|
8474
|
+
}
|
|
8394
8475
|
}
|
|
8395
8476
|
KameleoonLogger.info `RETURN: KameleoonClient.getVariations(visitorCode: ${visitorCode}, onlyActive: ${onlyActive}, track: ${track}) -> (variations: ${variations})`;
|
|
8396
8477
|
return variations;
|
|
@@ -8710,25 +8791,16 @@ class KameleoonClient {
|
|
|
8710
8791
|
path: PATH,
|
|
8711
8792
|
});
|
|
8712
8793
|
}
|
|
8713
|
-
else {
|
|
8714
|
-
if (this.visitorCodeManager.consentRequired) {
|
|
8715
|
-
setData({
|
|
8716
|
-
visitorCode: '',
|
|
8717
|
-
key: KameleoonStorageKey.VisitorCode,
|
|
8718
|
-
maxAge: ZERO_MAX_AGE,
|
|
8719
|
-
path: PATH,
|
|
8720
|
-
});
|
|
8721
|
-
}
|
|
8722
|
-
}
|
|
8723
8794
|
KameleoonLogger.info `RETURN: KameleoonClient.setUserConsent(visitorCode: ${visitorCode}, consent: ${consent}, setData: ${setData})`;
|
|
8724
8795
|
}
|
|
8725
8796
|
updateConsentData(visitorCode, consent) {
|
|
8726
8797
|
const readResult = this.consentDataStorage.read();
|
|
8798
|
+
const legalConsent = consent ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8727
8799
|
if (!readResult.ok) {
|
|
8728
8800
|
if (readResult.error.type === KameleoonException.StorageEmpty) {
|
|
8729
8801
|
this.consentDataStorage.write({
|
|
8730
8802
|
[visitorCode]: {
|
|
8731
|
-
consent,
|
|
8803
|
+
consent: legalConsent,
|
|
8732
8804
|
},
|
|
8733
8805
|
});
|
|
8734
8806
|
}
|
|
@@ -8736,28 +8808,36 @@ class KameleoonClient {
|
|
|
8736
8808
|
}
|
|
8737
8809
|
const data = readResult.data;
|
|
8738
8810
|
data[visitorCode] = {
|
|
8739
|
-
consent,
|
|
8811
|
+
consent: legalConsent,
|
|
8740
8812
|
};
|
|
8741
8813
|
this.consentDataStorage.write(data);
|
|
8742
8814
|
}
|
|
8815
|
+
getLegalConsent(visitorCode) {
|
|
8816
|
+
KameleoonLogger.debug `CALL: KameleoonClient.getLegalConsent(visitorCode: ${visitorCode})`;
|
|
8817
|
+
let legalConsent;
|
|
8818
|
+
const consentDataResult = this.consentDataStorage.read();
|
|
8819
|
+
legalConsent = consentDataResult.ok
|
|
8820
|
+
? this.extractLegalConsent(consentDataResult.data[visitorCode])
|
|
8821
|
+
: LegalConsent.Unknown;
|
|
8822
|
+
KameleoonLogger.debug `RETURN: KameleoonClient.getLegalConsent(visitorCode: ${visitorCode}) -> (legalConsent: ${legalConsent})`;
|
|
8823
|
+
return legalConsent;
|
|
8824
|
+
}
|
|
8825
|
+
extractLegalConsent(consentData) {
|
|
8826
|
+
if (consentData === undefined)
|
|
8827
|
+
return LegalConsent.Unknown;
|
|
8828
|
+
if (typeof consentData === 'boolean') {
|
|
8829
|
+
return consentData ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8830
|
+
}
|
|
8831
|
+
const value = consentData.consent;
|
|
8832
|
+
if (typeof value === 'boolean')
|
|
8833
|
+
return value ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8834
|
+
return value;
|
|
8835
|
+
}
|
|
8743
8836
|
_isConsentProvided(visitorCode) {
|
|
8744
8837
|
KameleoonLogger.debug `CALL: KameleoonClient._isConsentProvided(visitorCode: ${visitorCode})`;
|
|
8745
8838
|
const { isConsentRequired } = this.clientConfiguration;
|
|
8746
|
-
const
|
|
8747
|
-
|
|
8748
|
-
if (!isConsentRequired) {
|
|
8749
|
-
isConsentProvided = true;
|
|
8750
|
-
}
|
|
8751
|
-
else if (consentDataResult.ok) {
|
|
8752
|
-
const consentData = consentDataResult.data[visitorCode];
|
|
8753
|
-
// for consistency with the old data in the storage
|
|
8754
|
-
if (typeof consentData === 'boolean') {
|
|
8755
|
-
isConsentProvided = consentData;
|
|
8756
|
-
}
|
|
8757
|
-
else {
|
|
8758
|
-
isConsentProvided = consentData && consentData.consent;
|
|
8759
|
-
}
|
|
8760
|
-
}
|
|
8839
|
+
const isConsentProvided = !isConsentRequired ||
|
|
8840
|
+
this.getLegalConsent(visitorCode) == LegalConsent.Given;
|
|
8761
8841
|
KameleoonLogger.debug `RETURN: KameleoonClient._isConsentProvided(visitorCode: ${visitorCode}) -> (isConsentProvided: ${isConsentProvided})`;
|
|
8762
8842
|
return isConsentProvided;
|
|
8763
8843
|
}
|
|
@@ -8785,22 +8865,32 @@ class KameleoonClient {
|
|
|
8785
8865
|
if (!featureFlag.environmentEnabled) {
|
|
8786
8866
|
continue;
|
|
8787
8867
|
}
|
|
8788
|
-
|
|
8789
|
-
|
|
8790
|
-
|
|
8791
|
-
|
|
8792
|
-
|
|
8793
|
-
|
|
8794
|
-
if (evalExp.variationKey !== OFF_VARIATION_KEY) {
|
|
8795
|
-
activeVariations.push({
|
|
8796
|
-
variationKey: evalExp.variationKey,
|
|
8797
|
-
variationId: evalExp.variationId,
|
|
8798
|
-
experimentId: evalExp.experimentId,
|
|
8799
|
-
featureFlagId: featureFlag.id,
|
|
8800
|
-
featureKey: featureFlag.featureKey,
|
|
8801
|
-
rule: null,
|
|
8802
|
-
isTargetedRule: evalExp.ruleType === RuleType.TARGETED_DELIVERY,
|
|
8868
|
+
try {
|
|
8869
|
+
const evalExp = this._evaluate({
|
|
8870
|
+
visitorCode,
|
|
8871
|
+
featureFlag,
|
|
8872
|
+
track: false,
|
|
8873
|
+
save: false,
|
|
8803
8874
|
});
|
|
8875
|
+
if (evalExp.variationKey !== OFF_VARIATION_KEY) {
|
|
8876
|
+
activeVariations.push({
|
|
8877
|
+
variationKey: evalExp.variationKey,
|
|
8878
|
+
variationId: evalExp.variationId,
|
|
8879
|
+
experimentId: evalExp.experimentId,
|
|
8880
|
+
featureFlagId: featureFlag.id,
|
|
8881
|
+
featureKey: featureFlag.featureKey,
|
|
8882
|
+
rule: null,
|
|
8883
|
+
isTargetedRule: evalExp.ruleType === RuleType.TARGETED_DELIVERY,
|
|
8884
|
+
});
|
|
8885
|
+
}
|
|
8886
|
+
}
|
|
8887
|
+
catch (err) {
|
|
8888
|
+
if (err instanceof KameleoonError) {
|
|
8889
|
+
if (err.type != KameleoonException.FeatureFlagEnvironmentDisabled) {
|
|
8890
|
+
KameleoonLogger.error `Unexpected error: ${err}`;
|
|
8891
|
+
}
|
|
8892
|
+
continue;
|
|
8893
|
+
}
|
|
8804
8894
|
}
|
|
8805
8895
|
}
|
|
8806
8896
|
KameleoonLogger.debug `RETURN: KameleoonClient._getActiveFeatureVariations(visitorCode: ${visitorCode}) -> (activeVariations: ${activeVariations})`;
|
|
@@ -8821,6 +8911,7 @@ class KameleoonClient {
|
|
|
8821
8911
|
else if (this._isVisitorNotInHoldout(visitorCode, track, save, featureFlag, visitorData) &&
|
|
8822
8912
|
this._isFFUnrestrictedByMEGroup(visitorCode, featureFlag, visitorData)) {
|
|
8823
8913
|
const visitorIdentifier = this._getCodeForHash(visitorCode, featureFlag.bucketingCustomDataIndex, visitorData);
|
|
8914
|
+
const legalConsent = this.getLegalConsent(visitorCode);
|
|
8824
8915
|
const variationData = this.variationConfiguration
|
|
8825
8916
|
.getVariation({
|
|
8826
8917
|
visitorCode,
|
|
@@ -8832,6 +8923,7 @@ class KameleoonClient {
|
|
|
8832
8923
|
clientConfiguration: this.clientConfiguration,
|
|
8833
8924
|
dataManager: this.dataManager,
|
|
8834
8925
|
packageInfo: this.externalPackageInfo,
|
|
8926
|
+
legalConsent,
|
|
8835
8927
|
})
|
|
8836
8928
|
.throw();
|
|
8837
8929
|
evalExp =
|
|
@@ -8950,6 +9042,14 @@ class KameleoonClient {
|
|
|
8950
9042
|
}
|
|
8951
9043
|
KameleoonLogger.debug `CALL: KameleoonClient._isVisitorNotInHoldout(visitorCode: ${visitorCode}, track: ${track}, save: ${save}, featureFlag: ${featureFlag}, visitorData: ${visitorData})`;
|
|
8952
9044
|
let isNotInHoldout = true;
|
|
9045
|
+
// Checking if the evaluation is blocked due to the consent policy
|
|
9046
|
+
const legalConsent = this.getLegalConsent(visitorCode);
|
|
9047
|
+
if (legalConsent == LegalConsent.NotGiven) {
|
|
9048
|
+
const behaviour = this.clientConfiguration.consentBlockingBehaviour;
|
|
9049
|
+
if (behaviour == ConsentBlockingBehaviour.CompletelyBlocked) {
|
|
9050
|
+
throw new KameleoonError(KameleoonException.FeatureFlagEnvironmentDisabled, `Evaluation of holdout is blocked because consent is not provided for visitor '${visitorCode}'`);
|
|
9051
|
+
}
|
|
9052
|
+
}
|
|
8953
9053
|
const codeForHash = this._getCodeForHash(visitorCode, featureFlag === null || featureFlag === void 0 ? void 0 : featureFlag.bucketingCustomDataIndex, visitorData);
|
|
8954
9054
|
const holdoutHash = Hasher.getHashDouble({
|
|
8955
9055
|
visitorIdentifier: codeForHash,
|