@kameleoon/javascript-sdk-core 5.16.1 → 5.17.1
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 +16 -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 +208 -101
- package/dist/javascript-sdk-core-browser.cjs.js.map +1 -1
- package/dist/javascript-sdk-core-browser.es.js +208 -101
- package/dist/javascript-sdk-core-browser.es.js.map +1 -1
- package/dist/javascript-sdk-core.cjs.js +208 -101
- package/dist/javascript-sdk-core.cjs.js.map +1 -1
- package/dist/javascript-sdk-core.es.js +208 -101
- 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/kameleoonData/visitProcessor.d.ts +8 -8
- package/dist/kameleoonData/visitsData.d.ts +3 -2
- package/dist/requester/constants.d.ts +1 -1
- package/dist/requester/types.d.ts +2 -2
- 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 {
|
|
@@ -2861,7 +2905,10 @@ class VisitsData {
|
|
|
2861
2905
|
constructor(visits) {
|
|
2862
2906
|
this.status = TrackingStatus.Sent;
|
|
2863
2907
|
this.visits = visits;
|
|
2864
|
-
this.
|
|
2908
|
+
this._visitNumber = visits.length ? visits.length - 1 : 0;
|
|
2909
|
+
}
|
|
2910
|
+
get visitNumber() {
|
|
2911
|
+
return this._visitNumber;
|
|
2865
2912
|
}
|
|
2866
2913
|
get url() {
|
|
2867
2914
|
return '';
|
|
@@ -2869,7 +2916,7 @@ class VisitsData {
|
|
|
2869
2916
|
get data() {
|
|
2870
2917
|
return {
|
|
2871
2918
|
visits: this.visits,
|
|
2872
|
-
visitNumber: this.
|
|
2919
|
+
visitNumber: this._visitNumber,
|
|
2873
2920
|
type: KameleoonData.VisitsData,
|
|
2874
2921
|
status: this.status,
|
|
2875
2922
|
};
|
|
@@ -2886,11 +2933,11 @@ class VisitsData {
|
|
|
2886
2933
|
list: this.visits,
|
|
2887
2934
|
visit,
|
|
2888
2935
|
});
|
|
2889
|
-
this.
|
|
2936
|
+
this._visitNumber = this.visits.length ? this.visits.length - 1 : 0;
|
|
2890
2937
|
}
|
|
2891
2938
|
updateVisitNumber(visitNumber) {
|
|
2892
|
-
if (visitNumber > this.
|
|
2893
|
-
this.
|
|
2939
|
+
if (visitNumber > this._visitNumber) {
|
|
2940
|
+
this._visitNumber = visitNumber;
|
|
2894
2941
|
}
|
|
2895
2942
|
}
|
|
2896
2943
|
}
|
|
@@ -3097,10 +3144,12 @@ class VisitProcessor {
|
|
|
3097
3144
|
timeLastActivity: (_a = visit.timeLastEvent) !== null && _a !== void 0 ? _a : visit.timeStarted,
|
|
3098
3145
|
};
|
|
3099
3146
|
}
|
|
3100
|
-
processVisitNumber(visit,
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3147
|
+
processVisitNumber(visit, visitOffset) {
|
|
3148
|
+
var _a, _b, _c;
|
|
3149
|
+
if (this.visitsData.visitNumber <= visitOffset &&
|
|
3150
|
+
((_a = visit.staticDataEvent) === null || _a === void 0 ? void 0 : _a.data.visitNumber)) {
|
|
3151
|
+
const visitNumber = (_c = (_b = visit.staticDataEvent) === null || _b === void 0 ? void 0 : _b.data.visitNumber) !== null && _c !== void 0 ? _c : 0;
|
|
3152
|
+
this.visitsData.updateVisitNumber(visitNumber + visitOffset);
|
|
3104
3153
|
}
|
|
3105
3154
|
}
|
|
3106
3155
|
processCbs(cbsData) {
|
|
@@ -3274,12 +3323,12 @@ class Parser {
|
|
|
3274
3323
|
}
|
|
3275
3324
|
if (currentVisit) {
|
|
3276
3325
|
visitProcessor.processVisit(currentVisit);
|
|
3277
|
-
visitProcessor.processVisitNumber(currentVisit,
|
|
3326
|
+
visitProcessor.processVisitNumber(currentVisit, 0);
|
|
3278
3327
|
}
|
|
3279
|
-
previousVisits === null || previousVisits === void 0 ? void 0 : previousVisits.forEach((visit) => {
|
|
3328
|
+
previousVisits === null || previousVisits === void 0 ? void 0 : previousVisits.forEach((visit, index) => {
|
|
3280
3329
|
visitProcessor.processVisit(visit);
|
|
3281
3330
|
visitProcessor.processVisitsData(visit);
|
|
3282
|
-
visitProcessor.processVisitNumber(visit,
|
|
3331
|
+
visitProcessor.processVisitNumber(visit, index + 1);
|
|
3283
3332
|
});
|
|
3284
3333
|
visitProcessor.processKcs(kcs);
|
|
3285
3334
|
visitProcessor.processCbs(cbs);
|
|
@@ -3520,7 +3569,7 @@ class DataProcessor {
|
|
|
3520
3569
|
this.cleanupInterval = cleanupInterval;
|
|
3521
3570
|
this.packageInfo = packageInfo;
|
|
3522
3571
|
}
|
|
3523
|
-
mutUpdateData({ infoData, visitorCode, mutData, dataItem, }) {
|
|
3572
|
+
mutUpdateData({ infoData, visitorCode, mutData, dataItem, extendTtl, }) {
|
|
3524
3573
|
let { visitorReference, data, isReference } = this.dereferenceData(mutData, visitorCode);
|
|
3525
3574
|
if (this.packageInfo.isServer &&
|
|
3526
3575
|
isReference &&
|
|
@@ -3531,9 +3580,12 @@ class DataProcessor {
|
|
|
3531
3580
|
delete mutData[visitorCode];
|
|
3532
3581
|
visitorReference = visitorCode;
|
|
3533
3582
|
}
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3583
|
+
let expirationTime;
|
|
3584
|
+
if (extendTtl) {
|
|
3585
|
+
expirationTime = this.cleanupInterval
|
|
3586
|
+
? Date.now() + this.cleanupInterval
|
|
3587
|
+
: 0;
|
|
3588
|
+
}
|
|
3537
3589
|
switch (dataItem.data.type) {
|
|
3538
3590
|
case KameleoonData.CustomData: {
|
|
3539
3591
|
this.updateCustomData({
|
|
@@ -3888,13 +3940,17 @@ class DataProcessor {
|
|
|
3888
3940
|
return closestCleanupTime;
|
|
3889
3941
|
}
|
|
3890
3942
|
updateField({ key, value, data, visitorCode, expirationTime, }) {
|
|
3891
|
-
|
|
3943
|
+
var _a;
|
|
3944
|
+
const existing = data[visitorCode][key];
|
|
3945
|
+
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
3946
|
}
|
|
3893
3947
|
createField({ key, value, data, visitorCode, expirationTime, }) {
|
|
3894
3948
|
data[visitorCode] = Object.assign(Object.assign({}, data[visitorCode]), { [key]: Object.assign(Object.assign({}, value), { expirationTime }) });
|
|
3895
3949
|
}
|
|
3896
3950
|
updateNestedField({ key, nestedKey, value, data, visitorCode, expirationTime, }) {
|
|
3897
|
-
|
|
3951
|
+
var _a;
|
|
3952
|
+
const existing = data[visitorCode][key][nestedKey];
|
|
3953
|
+
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
3954
|
}
|
|
3899
3955
|
createNestedField({ key, nestedKey, value, data, visitorCode, expirationTime, }) {
|
|
3900
3956
|
var _a;
|
|
@@ -5160,15 +5216,7 @@ var KameleoonStorageKey;
|
|
|
5160
5216
|
KameleoonStorageKey["ForcedExperimentVariation"] = "kameleoonForcedExperimentVariation";
|
|
5161
5217
|
})(KameleoonStorageKey || (KameleoonStorageKey = {}));
|
|
5162
5218
|
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
|
-
},
|
|
5219
|
+
data: DEFAULT_DATA_FILE_CONFIGURATION,
|
|
5172
5220
|
lastUpdate: '',
|
|
5173
5221
|
};
|
|
5174
5222
|
// --- Note ---
|
|
@@ -5680,7 +5728,7 @@ class DataManager {
|
|
|
5680
5728
|
return resultData;
|
|
5681
5729
|
}
|
|
5682
5730
|
storeTrackedData(data) {
|
|
5683
|
-
this.storeData(data);
|
|
5731
|
+
this.storeData(data, false);
|
|
5684
5732
|
const infoResult = this.infoStorage.read();
|
|
5685
5733
|
if (!infoResult.ok) {
|
|
5686
5734
|
return;
|
|
@@ -5732,15 +5780,18 @@ class DataManager {
|
|
|
5732
5780
|
targetingData,
|
|
5733
5781
|
visitorCode: firstParameter,
|
|
5734
5782
|
kameleoonData: secondParameter,
|
|
5783
|
+
extendTtl: true,
|
|
5735
5784
|
});
|
|
5736
5785
|
}
|
|
5737
5786
|
else {
|
|
5738
5787
|
for (const [visitorCode, kameleoonData] of Object.entries(firstParameter)) {
|
|
5788
|
+
const extendTtl = typeof secondParameter[0] === 'boolean' ? secondParameter[0] : true;
|
|
5739
5789
|
this.mutUpdateTargetingData({
|
|
5740
5790
|
infoData,
|
|
5741
5791
|
targetingData,
|
|
5742
5792
|
visitorCode,
|
|
5743
5793
|
kameleoonData,
|
|
5794
|
+
extendTtl,
|
|
5744
5795
|
});
|
|
5745
5796
|
}
|
|
5746
5797
|
}
|
|
@@ -5857,8 +5908,8 @@ class DataManager {
|
|
|
5857
5908
|
}
|
|
5858
5909
|
return null;
|
|
5859
5910
|
}
|
|
5860
|
-
mutUpdateTargetingData({ infoData, visitorCode, kameleoonData, targetingData, }) {
|
|
5861
|
-
var _a;
|
|
5911
|
+
mutUpdateTargetingData({ infoData, visitorCode, kameleoonData, targetingData, extendTtl, }) {
|
|
5912
|
+
var _a, _b, _c;
|
|
5862
5913
|
for (const dataItem of kameleoonData) {
|
|
5863
5914
|
// process custom data
|
|
5864
5915
|
if (dataItem.data.type === KameleoonData.CustomData) {
|
|
@@ -5874,16 +5925,21 @@ class DataManager {
|
|
|
5874
5925
|
}
|
|
5875
5926
|
// process metadata of conversions
|
|
5876
5927
|
if (dataItem.data.type === KameleoonData.Conversion) {
|
|
5877
|
-
|
|
5928
|
+
const conversion = dataItem;
|
|
5929
|
+
if (((_b = (_a = conversion._metadata) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0) {
|
|
5930
|
+
conversion._metadata = (_c = conversion._metadata) === null || _c === void 0 ? void 0 : _c.filter((item) => this.trySetCustomDataIndexByName(item));
|
|
5931
|
+
}
|
|
5878
5932
|
}
|
|
5879
5933
|
const expirationTime = this.dataProcessor.mutUpdateData({
|
|
5880
5934
|
infoData,
|
|
5881
5935
|
visitorCode,
|
|
5882
5936
|
mutData: targetingData,
|
|
5883
5937
|
dataItem,
|
|
5938
|
+
extendTtl,
|
|
5884
5939
|
});
|
|
5885
5940
|
const nextCleanup = infoData.nextDataCleanup;
|
|
5886
|
-
if (!nextCleanup ||
|
|
5941
|
+
if (!nextCleanup ||
|
|
5942
|
+
(nextCleanup && expirationTime && expirationTime < nextCleanup)) {
|
|
5887
5943
|
infoData.nextDataCleanup = expirationTime;
|
|
5888
5944
|
}
|
|
5889
5945
|
if (dataItem.data.status === TrackingStatus.Unsent) {
|
|
@@ -5915,7 +5971,9 @@ class DataManager {
|
|
|
5915
5971
|
var _a;
|
|
5916
5972
|
const { data } = customData;
|
|
5917
5973
|
const isDataValid = Boolean(data.value.length && data.value[0].length);
|
|
5918
|
-
this.trySetCustomDataIndexByName(customData)
|
|
5974
|
+
if (!this.trySetCustomDataIndexByName(customData)) {
|
|
5975
|
+
return false;
|
|
5976
|
+
}
|
|
5919
5977
|
if (data.index == CustomData$1.UNDEFINED_INDEX) {
|
|
5920
5978
|
data.index = customData.index;
|
|
5921
5979
|
}
|
|
@@ -5945,13 +6003,15 @@ class DataManager {
|
|
|
5945
6003
|
return true;
|
|
5946
6004
|
}
|
|
5947
6005
|
trySetCustomDataIndexByName(customData) {
|
|
5948
|
-
if (customData.index
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
6006
|
+
if (customData.index !== CustomData$1.UNDEFINED_INDEX)
|
|
6007
|
+
return true;
|
|
6008
|
+
if (!customData.name)
|
|
6009
|
+
return false;
|
|
6010
|
+
const cdIndex = this.customDataIndexByName.get(customData.name);
|
|
6011
|
+
if (cdIndex == null)
|
|
6012
|
+
return false;
|
|
6013
|
+
customData.index = cdIndex;
|
|
6014
|
+
return true;
|
|
5955
6015
|
}
|
|
5956
6016
|
get unsentDataVisitors() {
|
|
5957
6017
|
const infoResult = this.infoStorage.read();
|
|
@@ -7055,6 +7115,13 @@ class Hasher {
|
|
|
7055
7115
|
}
|
|
7056
7116
|
}
|
|
7057
7117
|
|
|
7118
|
+
var LegalConsent;
|
|
7119
|
+
(function (LegalConsent) {
|
|
7120
|
+
LegalConsent[LegalConsent["Unknown"] = 0] = "Unknown";
|
|
7121
|
+
LegalConsent[LegalConsent["Given"] = 1] = "Given";
|
|
7122
|
+
LegalConsent[LegalConsent["NotGiven"] = 2] = "NotGiven";
|
|
7123
|
+
})(LegalConsent || (LegalConsent = {}));
|
|
7124
|
+
|
|
7058
7125
|
class VariationConfiguration {
|
|
7059
7126
|
constructor(externalStorage, externalStorageForcedExperimentVariations, externalStorageForcedFeatureVariations, visitorCodeManager, clientConfiguration) {
|
|
7060
7127
|
this.storage = externalStorage;
|
|
@@ -7113,9 +7180,12 @@ class VariationConfiguration {
|
|
|
7113
7180
|
}
|
|
7114
7181
|
return buildExports.Ok(featureFlagVariations);
|
|
7115
7182
|
}
|
|
7116
|
-
getVariation({ visitorCode, visitorIdentifier, featureFlag, targetingData, packageInfo, clientConfiguration, dataManager, track = true, withAssignment = false, }) {
|
|
7183
|
+
getVariation({ visitorCode, visitorIdentifier, featureFlag, targetingData, packageInfo, clientConfiguration, dataManager, legalConsent, track = true, withAssignment = false, }) {
|
|
7117
7184
|
KameleoonLogger.debug `CALL: VariationConfiguration.getVariation(visitorCode: ${visitorCode}, visitorIdentifier: ${visitorIdentifier}, featureFlag: ${featureFlag}, targetingData: ${targetingData}, packageInfo: ${packageInfo}, clientConfiguration, dataManager, withAssignment: ${withAssignment})`;
|
|
7118
7185
|
const { rules, featureKey, id: featureFlagId, defaultVariationKey, } = featureFlag;
|
|
7186
|
+
const consent = clientConfiguration.isConsentRequired
|
|
7187
|
+
? legalConsent
|
|
7188
|
+
: LegalConsent.Given;
|
|
7119
7189
|
for (const rule of rules) {
|
|
7120
7190
|
const { segment, experimentId, id, exposition, respoolTime, variationByExposition, } = rule;
|
|
7121
7191
|
const forcedVariationData = this.getForcedExperimentVariation(visitorCode, rule.experimentId);
|
|
@@ -7162,6 +7232,16 @@ class VariationConfiguration {
|
|
|
7162
7232
|
});
|
|
7163
7233
|
KameleoonLogger.debug `Calculated ruleHash: ${ruleHash} for code: ${visitorIdentifier}`;
|
|
7164
7234
|
if (ruleHash <= exposition) {
|
|
7235
|
+
// Checking if the evaluation is blocked due to the consent policy
|
|
7236
|
+
if (consent == LegalConsent.NotGiven &&
|
|
7237
|
+
rule.type == RuleType.EXPERIMENTATION) {
|
|
7238
|
+
const behaviour = clientConfiguration.consentBlockingBehaviour;
|
|
7239
|
+
if (behaviour == ConsentBlockingBehaviour.PartiallyBlocked) {
|
|
7240
|
+
break;
|
|
7241
|
+
}
|
|
7242
|
+
return buildExports.Err(new KameleoonError(KameleoonException.FeatureFlagEnvironmentDisabled, `Evaluation of ${rule} is blocked because consent is not provided for visitor '${visitorCode}'`));
|
|
7243
|
+
}
|
|
7244
|
+
// evaluate with CB scores if applicable
|
|
7165
7245
|
let variation = this.evaluateCBScores(rule, visitorIdentifier, targetingData);
|
|
7166
7246
|
if (!variation) {
|
|
7167
7247
|
const variationHash = Hasher.getHashDouble({
|
|
@@ -7523,7 +7603,6 @@ class KameleoonEventSource {
|
|
|
7523
7603
|
const VISITOR_CODE_LENGTH = 16;
|
|
7524
7604
|
const VISITOR_CODE_MAX_LENGTH = 255;
|
|
7525
7605
|
const DEFAULT_MAX_AGE = 60 * 60 * 24 * 365;
|
|
7526
|
-
const ZERO_MAX_AGE = 0;
|
|
7527
7606
|
const PATH = '/';
|
|
7528
7607
|
|
|
7529
7608
|
/**
|
|
@@ -7991,7 +8070,7 @@ class Tracker {
|
|
|
7991
8070
|
this.dataManager.storeTrackedData(updatedData);
|
|
7992
8071
|
}
|
|
7993
8072
|
else {
|
|
7994
|
-
this.dataManager.storeData(updatedData);
|
|
8073
|
+
this.dataManager.storeData(updatedData, false);
|
|
7995
8074
|
}
|
|
7996
8075
|
}
|
|
7997
8076
|
getUnsentVisitorData(visitorCode, isConsentProvided) {
|
|
@@ -8343,16 +8422,23 @@ class KameleoonClient {
|
|
|
8343
8422
|
const variations = new Map();
|
|
8344
8423
|
const featureFlags = this.clientConfiguration.featureFlags;
|
|
8345
8424
|
for (const featureFlag of featureFlags.values()) {
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
if (
|
|
8425
|
+
try {
|
|
8426
|
+
const variation = this._getFeatureVariation({
|
|
8427
|
+
visitorCode,
|
|
8428
|
+
featureKey: featureFlag.featureKey,
|
|
8429
|
+
track,
|
|
8430
|
+
});
|
|
8431
|
+
if (variation.ok &&
|
|
8432
|
+
(!onlyActive || variation.data.key !== OFF_VARIATION_KEY)) {
|
|
8353
8433
|
variations.set(featureFlag.featureKey, variation.data);
|
|
8354
8434
|
}
|
|
8355
8435
|
}
|
|
8436
|
+
catch (err) {
|
|
8437
|
+
if (err instanceof KameleoonError &&
|
|
8438
|
+
err.type !== KameleoonException.FeatureFlagEnvironmentDisabled) {
|
|
8439
|
+
throw err;
|
|
8440
|
+
}
|
|
8441
|
+
}
|
|
8356
8442
|
}
|
|
8357
8443
|
KameleoonLogger.info `RETURN: KameleoonClient.getVariations(visitorCode: ${visitorCode}, onlyActive: ${onlyActive}, track: ${track}) -> (variations: ${variations})`;
|
|
8358
8444
|
return variations;
|
|
@@ -8672,25 +8758,16 @@ class KameleoonClient {
|
|
|
8672
8758
|
path: PATH,
|
|
8673
8759
|
});
|
|
8674
8760
|
}
|
|
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
8761
|
KameleoonLogger.info `RETURN: KameleoonClient.setUserConsent(visitorCode: ${visitorCode}, consent: ${consent}, setData: ${setData})`;
|
|
8686
8762
|
}
|
|
8687
8763
|
updateConsentData(visitorCode, consent) {
|
|
8688
8764
|
const readResult = this.consentDataStorage.read();
|
|
8765
|
+
const legalConsent = consent ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8689
8766
|
if (!readResult.ok) {
|
|
8690
8767
|
if (readResult.error.type === KameleoonException.StorageEmpty) {
|
|
8691
8768
|
this.consentDataStorage.write({
|
|
8692
8769
|
[visitorCode]: {
|
|
8693
|
-
consent,
|
|
8770
|
+
consent: legalConsent,
|
|
8694
8771
|
},
|
|
8695
8772
|
});
|
|
8696
8773
|
}
|
|
@@ -8698,28 +8775,36 @@ class KameleoonClient {
|
|
|
8698
8775
|
}
|
|
8699
8776
|
const data = readResult.data;
|
|
8700
8777
|
data[visitorCode] = {
|
|
8701
|
-
consent,
|
|
8778
|
+
consent: legalConsent,
|
|
8702
8779
|
};
|
|
8703
8780
|
this.consentDataStorage.write(data);
|
|
8704
8781
|
}
|
|
8782
|
+
getLegalConsent(visitorCode) {
|
|
8783
|
+
KameleoonLogger.debug `CALL: KameleoonClient.getLegalConsent(visitorCode: ${visitorCode})`;
|
|
8784
|
+
let legalConsent;
|
|
8785
|
+
const consentDataResult = this.consentDataStorage.read();
|
|
8786
|
+
legalConsent = consentDataResult.ok
|
|
8787
|
+
? this.extractLegalConsent(consentDataResult.data[visitorCode])
|
|
8788
|
+
: LegalConsent.Unknown;
|
|
8789
|
+
KameleoonLogger.debug `RETURN: KameleoonClient.getLegalConsent(visitorCode: ${visitorCode}) -> (legalConsent: ${legalConsent})`;
|
|
8790
|
+
return legalConsent;
|
|
8791
|
+
}
|
|
8792
|
+
extractLegalConsent(consentData) {
|
|
8793
|
+
if (consentData === undefined)
|
|
8794
|
+
return LegalConsent.Unknown;
|
|
8795
|
+
if (typeof consentData === 'boolean') {
|
|
8796
|
+
return consentData ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8797
|
+
}
|
|
8798
|
+
const value = consentData.consent;
|
|
8799
|
+
if (typeof value === 'boolean')
|
|
8800
|
+
return value ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8801
|
+
return value;
|
|
8802
|
+
}
|
|
8705
8803
|
_isConsentProvided(visitorCode) {
|
|
8706
8804
|
KameleoonLogger.debug `CALL: KameleoonClient._isConsentProvided(visitorCode: ${visitorCode})`;
|
|
8707
8805
|
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
|
-
}
|
|
8806
|
+
const isConsentProvided = !isConsentRequired ||
|
|
8807
|
+
this.getLegalConsent(visitorCode) == LegalConsent.Given;
|
|
8723
8808
|
KameleoonLogger.debug `RETURN: KameleoonClient._isConsentProvided(visitorCode: ${visitorCode}) -> (isConsentProvided: ${isConsentProvided})`;
|
|
8724
8809
|
return isConsentProvided;
|
|
8725
8810
|
}
|
|
@@ -8747,22 +8832,32 @@ class KameleoonClient {
|
|
|
8747
8832
|
if (!featureFlag.environmentEnabled) {
|
|
8748
8833
|
continue;
|
|
8749
8834
|
}
|
|
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,
|
|
8835
|
+
try {
|
|
8836
|
+
const evalExp = this._evaluate({
|
|
8837
|
+
visitorCode,
|
|
8838
|
+
featureFlag,
|
|
8839
|
+
track: false,
|
|
8840
|
+
save: false,
|
|
8765
8841
|
});
|
|
8842
|
+
if (evalExp.variationKey !== OFF_VARIATION_KEY) {
|
|
8843
|
+
activeVariations.push({
|
|
8844
|
+
variationKey: evalExp.variationKey,
|
|
8845
|
+
variationId: evalExp.variationId,
|
|
8846
|
+
experimentId: evalExp.experimentId,
|
|
8847
|
+
featureFlagId: featureFlag.id,
|
|
8848
|
+
featureKey: featureFlag.featureKey,
|
|
8849
|
+
rule: null,
|
|
8850
|
+
isTargetedRule: evalExp.ruleType === RuleType.TARGETED_DELIVERY,
|
|
8851
|
+
});
|
|
8852
|
+
}
|
|
8853
|
+
}
|
|
8854
|
+
catch (err) {
|
|
8855
|
+
if (err instanceof KameleoonError) {
|
|
8856
|
+
if (err.type != KameleoonException.FeatureFlagEnvironmentDisabled) {
|
|
8857
|
+
KameleoonLogger.error `Unexpected error: ${err}`;
|
|
8858
|
+
}
|
|
8859
|
+
continue;
|
|
8860
|
+
}
|
|
8766
8861
|
}
|
|
8767
8862
|
}
|
|
8768
8863
|
KameleoonLogger.debug `RETURN: KameleoonClient._getActiveFeatureVariations(visitorCode: ${visitorCode}) -> (activeVariations: ${activeVariations})`;
|
|
@@ -8783,6 +8878,7 @@ class KameleoonClient {
|
|
|
8783
8878
|
else if (this._isVisitorNotInHoldout(visitorCode, track, save, featureFlag, visitorData) &&
|
|
8784
8879
|
this._isFFUnrestrictedByMEGroup(visitorCode, featureFlag, visitorData)) {
|
|
8785
8880
|
const visitorIdentifier = this._getCodeForHash(visitorCode, featureFlag.bucketingCustomDataIndex, visitorData);
|
|
8881
|
+
const legalConsent = this.getLegalConsent(visitorCode);
|
|
8786
8882
|
const variationData = this.variationConfiguration
|
|
8787
8883
|
.getVariation({
|
|
8788
8884
|
visitorCode,
|
|
@@ -8794,6 +8890,7 @@ class KameleoonClient {
|
|
|
8794
8890
|
clientConfiguration: this.clientConfiguration,
|
|
8795
8891
|
dataManager: this.dataManager,
|
|
8796
8892
|
packageInfo: this.externalPackageInfo,
|
|
8893
|
+
legalConsent,
|
|
8797
8894
|
})
|
|
8798
8895
|
.throw();
|
|
8799
8896
|
evalExp =
|
|
@@ -8912,6 +9009,16 @@ class KameleoonClient {
|
|
|
8912
9009
|
}
|
|
8913
9010
|
KameleoonLogger.debug `CALL: KameleoonClient._isVisitorNotInHoldout(visitorCode: ${visitorCode}, track: ${track}, save: ${save}, featureFlag: ${featureFlag}, visitorData: ${visitorData})`;
|
|
8914
9011
|
let isNotInHoldout = true;
|
|
9012
|
+
// Checking if the evaluation is blocked due to the consent policy
|
|
9013
|
+
const legalConsent = this.clientConfiguration.isConsentRequired
|
|
9014
|
+
? this.getLegalConsent(visitorCode)
|
|
9015
|
+
: LegalConsent.Given;
|
|
9016
|
+
if (legalConsent == LegalConsent.NotGiven) {
|
|
9017
|
+
const behaviour = this.clientConfiguration.consentBlockingBehaviour;
|
|
9018
|
+
if (behaviour == ConsentBlockingBehaviour.CompletelyBlocked) {
|
|
9019
|
+
throw new KameleoonError(KameleoonException.FeatureFlagEnvironmentDisabled, `Evaluation of holdout is blocked because consent is not provided for visitor '${visitorCode}'`);
|
|
9020
|
+
}
|
|
9021
|
+
}
|
|
8915
9022
|
const codeForHash = this._getCodeForHash(visitorCode, featureFlag === null || featureFlag === void 0 ? void 0 : featureFlag.bucketingCustomDataIndex, visitorData);
|
|
8916
9023
|
const holdoutHash = Hasher.getHashDouble({
|
|
8917
9024
|
visitorIdentifier: codeForHash,
|