@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
|
@@ -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 {
|
|
@@ -2890,7 +2934,10 @@ class VisitsData {
|
|
|
2890
2934
|
constructor(visits) {
|
|
2891
2935
|
this.status = TrackingStatus.Sent;
|
|
2892
2936
|
this.visits = visits;
|
|
2893
|
-
this.
|
|
2937
|
+
this._visitNumber = visits.length ? visits.length - 1 : 0;
|
|
2938
|
+
}
|
|
2939
|
+
get visitNumber() {
|
|
2940
|
+
return this._visitNumber;
|
|
2894
2941
|
}
|
|
2895
2942
|
get url() {
|
|
2896
2943
|
return '';
|
|
@@ -2898,7 +2945,7 @@ class VisitsData {
|
|
|
2898
2945
|
get data() {
|
|
2899
2946
|
return {
|
|
2900
2947
|
visits: this.visits,
|
|
2901
|
-
visitNumber: this.
|
|
2948
|
+
visitNumber: this._visitNumber,
|
|
2902
2949
|
type: KameleoonData.VisitsData,
|
|
2903
2950
|
status: this.status,
|
|
2904
2951
|
};
|
|
@@ -2915,11 +2962,11 @@ class VisitsData {
|
|
|
2915
2962
|
list: this.visits,
|
|
2916
2963
|
visit,
|
|
2917
2964
|
});
|
|
2918
|
-
this.
|
|
2965
|
+
this._visitNumber = this.visits.length ? this.visits.length - 1 : 0;
|
|
2919
2966
|
}
|
|
2920
2967
|
updateVisitNumber(visitNumber) {
|
|
2921
|
-
if (visitNumber > this.
|
|
2922
|
-
this.
|
|
2968
|
+
if (visitNumber > this._visitNumber) {
|
|
2969
|
+
this._visitNumber = visitNumber;
|
|
2923
2970
|
}
|
|
2924
2971
|
}
|
|
2925
2972
|
}
|
|
@@ -3126,10 +3173,12 @@ class VisitProcessor {
|
|
|
3126
3173
|
timeLastActivity: (_a = visit.timeLastEvent) !== null && _a !== void 0 ? _a : visit.timeStarted,
|
|
3127
3174
|
};
|
|
3128
3175
|
}
|
|
3129
|
-
processVisitNumber(visit,
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3176
|
+
processVisitNumber(visit, visitOffset) {
|
|
3177
|
+
var _a, _b, _c;
|
|
3178
|
+
if (this.visitsData.visitNumber <= visitOffset &&
|
|
3179
|
+
((_a = visit.staticDataEvent) === null || _a === void 0 ? void 0 : _a.data.visitNumber)) {
|
|
3180
|
+
const visitNumber = (_c = (_b = visit.staticDataEvent) === null || _b === void 0 ? void 0 : _b.data.visitNumber) !== null && _c !== void 0 ? _c : 0;
|
|
3181
|
+
this.visitsData.updateVisitNumber(visitNumber + visitOffset);
|
|
3133
3182
|
}
|
|
3134
3183
|
}
|
|
3135
3184
|
processCbs(cbsData) {
|
|
@@ -3303,12 +3352,12 @@ class Parser {
|
|
|
3303
3352
|
}
|
|
3304
3353
|
if (currentVisit) {
|
|
3305
3354
|
visitProcessor.processVisit(currentVisit);
|
|
3306
|
-
visitProcessor.processVisitNumber(currentVisit,
|
|
3355
|
+
visitProcessor.processVisitNumber(currentVisit, 0);
|
|
3307
3356
|
}
|
|
3308
|
-
previousVisits === null || previousVisits === void 0 ? void 0 : previousVisits.forEach((visit) => {
|
|
3357
|
+
previousVisits === null || previousVisits === void 0 ? void 0 : previousVisits.forEach((visit, index) => {
|
|
3309
3358
|
visitProcessor.processVisit(visit);
|
|
3310
3359
|
visitProcessor.processVisitsData(visit);
|
|
3311
|
-
visitProcessor.processVisitNumber(visit,
|
|
3360
|
+
visitProcessor.processVisitNumber(visit, index + 1);
|
|
3312
3361
|
});
|
|
3313
3362
|
visitProcessor.processKcs(kcs);
|
|
3314
3363
|
visitProcessor.processCbs(cbs);
|
|
@@ -3549,7 +3598,7 @@ class DataProcessor {
|
|
|
3549
3598
|
this.cleanupInterval = cleanupInterval;
|
|
3550
3599
|
this.packageInfo = packageInfo;
|
|
3551
3600
|
}
|
|
3552
|
-
mutUpdateData({ infoData, visitorCode, mutData, dataItem, }) {
|
|
3601
|
+
mutUpdateData({ infoData, visitorCode, mutData, dataItem, extendTtl, }) {
|
|
3553
3602
|
let { visitorReference, data, isReference } = this.dereferenceData(mutData, visitorCode);
|
|
3554
3603
|
if (this.packageInfo.isServer &&
|
|
3555
3604
|
isReference &&
|
|
@@ -3560,9 +3609,12 @@ class DataProcessor {
|
|
|
3560
3609
|
delete mutData[visitorCode];
|
|
3561
3610
|
visitorReference = visitorCode;
|
|
3562
3611
|
}
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3612
|
+
let expirationTime;
|
|
3613
|
+
if (extendTtl) {
|
|
3614
|
+
expirationTime = this.cleanupInterval
|
|
3615
|
+
? Date.now() + this.cleanupInterval
|
|
3616
|
+
: 0;
|
|
3617
|
+
}
|
|
3566
3618
|
switch (dataItem.data.type) {
|
|
3567
3619
|
case KameleoonData.CustomData: {
|
|
3568
3620
|
this.updateCustomData({
|
|
@@ -3917,13 +3969,17 @@ class DataProcessor {
|
|
|
3917
3969
|
return closestCleanupTime;
|
|
3918
3970
|
}
|
|
3919
3971
|
updateField({ key, value, data, visitorCode, expirationTime, }) {
|
|
3920
|
-
|
|
3972
|
+
var _a;
|
|
3973
|
+
const existing = data[visitorCode][key];
|
|
3974
|
+
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
3975
|
}
|
|
3922
3976
|
createField({ key, value, data, visitorCode, expirationTime, }) {
|
|
3923
3977
|
data[visitorCode] = Object.assign(Object.assign({}, data[visitorCode]), { [key]: Object.assign(Object.assign({}, value), { expirationTime }) });
|
|
3924
3978
|
}
|
|
3925
3979
|
updateNestedField({ key, nestedKey, value, data, visitorCode, expirationTime, }) {
|
|
3926
|
-
|
|
3980
|
+
var _a;
|
|
3981
|
+
const existing = data[visitorCode][key][nestedKey];
|
|
3982
|
+
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
3983
|
}
|
|
3928
3984
|
createNestedField({ key, nestedKey, value, data, visitorCode, expirationTime, }) {
|
|
3929
3985
|
var _a;
|
|
@@ -5189,15 +5245,7 @@ var KameleoonStorageKey;
|
|
|
5189
5245
|
KameleoonStorageKey["ForcedExperimentVariation"] = "kameleoonForcedExperimentVariation";
|
|
5190
5246
|
})(KameleoonStorageKey || (KameleoonStorageKey = {}));
|
|
5191
5247
|
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
|
-
},
|
|
5248
|
+
data: DEFAULT_DATA_FILE_CONFIGURATION,
|
|
5201
5249
|
lastUpdate: '',
|
|
5202
5250
|
};
|
|
5203
5251
|
// --- Note ---
|
|
@@ -5709,7 +5757,7 @@ class DataManager {
|
|
|
5709
5757
|
return resultData;
|
|
5710
5758
|
}
|
|
5711
5759
|
storeTrackedData(data) {
|
|
5712
|
-
this.storeData(data);
|
|
5760
|
+
this.storeData(data, false);
|
|
5713
5761
|
const infoResult = this.infoStorage.read();
|
|
5714
5762
|
if (!infoResult.ok) {
|
|
5715
5763
|
return;
|
|
@@ -5761,15 +5809,18 @@ class DataManager {
|
|
|
5761
5809
|
targetingData,
|
|
5762
5810
|
visitorCode: firstParameter,
|
|
5763
5811
|
kameleoonData: secondParameter,
|
|
5812
|
+
extendTtl: true,
|
|
5764
5813
|
});
|
|
5765
5814
|
}
|
|
5766
5815
|
else {
|
|
5767
5816
|
for (const [visitorCode, kameleoonData] of Object.entries(firstParameter)) {
|
|
5817
|
+
const extendTtl = typeof secondParameter[0] === 'boolean' ? secondParameter[0] : true;
|
|
5768
5818
|
this.mutUpdateTargetingData({
|
|
5769
5819
|
infoData,
|
|
5770
5820
|
targetingData,
|
|
5771
5821
|
visitorCode,
|
|
5772
5822
|
kameleoonData,
|
|
5823
|
+
extendTtl,
|
|
5773
5824
|
});
|
|
5774
5825
|
}
|
|
5775
5826
|
}
|
|
@@ -5886,8 +5937,8 @@ class DataManager {
|
|
|
5886
5937
|
}
|
|
5887
5938
|
return null;
|
|
5888
5939
|
}
|
|
5889
|
-
mutUpdateTargetingData({ infoData, visitorCode, kameleoonData, targetingData, }) {
|
|
5890
|
-
var _a;
|
|
5940
|
+
mutUpdateTargetingData({ infoData, visitorCode, kameleoonData, targetingData, extendTtl, }) {
|
|
5941
|
+
var _a, _b, _c;
|
|
5891
5942
|
for (const dataItem of kameleoonData) {
|
|
5892
5943
|
// process custom data
|
|
5893
5944
|
if (dataItem.data.type === KameleoonData.CustomData) {
|
|
@@ -5903,16 +5954,21 @@ class DataManager {
|
|
|
5903
5954
|
}
|
|
5904
5955
|
// process metadata of conversions
|
|
5905
5956
|
if (dataItem.data.type === KameleoonData.Conversion) {
|
|
5906
|
-
|
|
5957
|
+
const conversion = dataItem;
|
|
5958
|
+
if (((_b = (_a = conversion._metadata) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0) {
|
|
5959
|
+
conversion._metadata = (_c = conversion._metadata) === null || _c === void 0 ? void 0 : _c.filter((item) => this.trySetCustomDataIndexByName(item));
|
|
5960
|
+
}
|
|
5907
5961
|
}
|
|
5908
5962
|
const expirationTime = this.dataProcessor.mutUpdateData({
|
|
5909
5963
|
infoData,
|
|
5910
5964
|
visitorCode,
|
|
5911
5965
|
mutData: targetingData,
|
|
5912
5966
|
dataItem,
|
|
5967
|
+
extendTtl,
|
|
5913
5968
|
});
|
|
5914
5969
|
const nextCleanup = infoData.nextDataCleanup;
|
|
5915
|
-
if (!nextCleanup ||
|
|
5970
|
+
if (!nextCleanup ||
|
|
5971
|
+
(nextCleanup && expirationTime && expirationTime < nextCleanup)) {
|
|
5916
5972
|
infoData.nextDataCleanup = expirationTime;
|
|
5917
5973
|
}
|
|
5918
5974
|
if (dataItem.data.status === TrackingStatus.Unsent) {
|
|
@@ -5944,7 +6000,9 @@ class DataManager {
|
|
|
5944
6000
|
var _a;
|
|
5945
6001
|
const { data } = customData;
|
|
5946
6002
|
const isDataValid = Boolean(data.value.length && data.value[0].length);
|
|
5947
|
-
this.trySetCustomDataIndexByName(customData)
|
|
6003
|
+
if (!this.trySetCustomDataIndexByName(customData)) {
|
|
6004
|
+
return false;
|
|
6005
|
+
}
|
|
5948
6006
|
if (data.index == CustomData$1.UNDEFINED_INDEX) {
|
|
5949
6007
|
data.index = customData.index;
|
|
5950
6008
|
}
|
|
@@ -5974,13 +6032,15 @@ class DataManager {
|
|
|
5974
6032
|
return true;
|
|
5975
6033
|
}
|
|
5976
6034
|
trySetCustomDataIndexByName(customData) {
|
|
5977
|
-
if (customData.index
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
6035
|
+
if (customData.index !== CustomData$1.UNDEFINED_INDEX)
|
|
6036
|
+
return true;
|
|
6037
|
+
if (!customData.name)
|
|
6038
|
+
return false;
|
|
6039
|
+
const cdIndex = this.customDataIndexByName.get(customData.name);
|
|
6040
|
+
if (cdIndex == null)
|
|
6041
|
+
return false;
|
|
6042
|
+
customData.index = cdIndex;
|
|
6043
|
+
return true;
|
|
5984
6044
|
}
|
|
5985
6045
|
get unsentDataVisitors() {
|
|
5986
6046
|
const infoResult = this.infoStorage.read();
|
|
@@ -7093,6 +7153,13 @@ class Hasher {
|
|
|
7093
7153
|
}
|
|
7094
7154
|
}
|
|
7095
7155
|
|
|
7156
|
+
var LegalConsent;
|
|
7157
|
+
(function (LegalConsent) {
|
|
7158
|
+
LegalConsent[LegalConsent["Unknown"] = 0] = "Unknown";
|
|
7159
|
+
LegalConsent[LegalConsent["Given"] = 1] = "Given";
|
|
7160
|
+
LegalConsent[LegalConsent["NotGiven"] = 2] = "NotGiven";
|
|
7161
|
+
})(LegalConsent || (LegalConsent = {}));
|
|
7162
|
+
|
|
7096
7163
|
class VariationConfiguration {
|
|
7097
7164
|
constructor(externalStorage, externalStorageForcedExperimentVariations, externalStorageForcedFeatureVariations, visitorCodeManager, clientConfiguration) {
|
|
7098
7165
|
this.storage = externalStorage;
|
|
@@ -7151,9 +7218,12 @@ class VariationConfiguration {
|
|
|
7151
7218
|
}
|
|
7152
7219
|
return buildExports.Ok(featureFlagVariations);
|
|
7153
7220
|
}
|
|
7154
|
-
getVariation({ visitorCode, visitorIdentifier, featureFlag, targetingData, packageInfo, clientConfiguration, dataManager, track = true, withAssignment = false, }) {
|
|
7221
|
+
getVariation({ visitorCode, visitorIdentifier, featureFlag, targetingData, packageInfo, clientConfiguration, dataManager, legalConsent, track = true, withAssignment = false, }) {
|
|
7155
7222
|
KameleoonLogger.debug `CALL: VariationConfiguration.getVariation(visitorCode: ${visitorCode}, visitorIdentifier: ${visitorIdentifier}, featureFlag: ${featureFlag}, targetingData: ${targetingData}, packageInfo: ${packageInfo}, clientConfiguration, dataManager, withAssignment: ${withAssignment})`;
|
|
7156
7223
|
const { rules, featureKey, id: featureFlagId, defaultVariationKey, } = featureFlag;
|
|
7224
|
+
const consent = clientConfiguration.isConsentRequired
|
|
7225
|
+
? legalConsent
|
|
7226
|
+
: LegalConsent.Given;
|
|
7157
7227
|
for (const rule of rules) {
|
|
7158
7228
|
const { segment, experimentId, id, exposition, respoolTime, variationByExposition, } = rule;
|
|
7159
7229
|
const forcedVariationData = this.getForcedExperimentVariation(visitorCode, rule.experimentId);
|
|
@@ -7200,6 +7270,16 @@ class VariationConfiguration {
|
|
|
7200
7270
|
});
|
|
7201
7271
|
KameleoonLogger.debug `Calculated ruleHash: ${ruleHash} for code: ${visitorIdentifier}`;
|
|
7202
7272
|
if (ruleHash <= exposition) {
|
|
7273
|
+
// Checking if the evaluation is blocked due to the consent policy
|
|
7274
|
+
if (consent == LegalConsent.NotGiven &&
|
|
7275
|
+
rule.type == RuleType.EXPERIMENTATION) {
|
|
7276
|
+
const behaviour = clientConfiguration.consentBlockingBehaviour;
|
|
7277
|
+
if (behaviour == ConsentBlockingBehaviour.PartiallyBlocked) {
|
|
7278
|
+
break;
|
|
7279
|
+
}
|
|
7280
|
+
return buildExports.Err(new KameleoonError(KameleoonException.FeatureFlagEnvironmentDisabled, `Evaluation of ${rule} is blocked because consent is not provided for visitor '${visitorCode}'`));
|
|
7281
|
+
}
|
|
7282
|
+
// evaluate with CB scores if applicable
|
|
7203
7283
|
let variation = this.evaluateCBScores(rule, visitorIdentifier, targetingData);
|
|
7204
7284
|
if (!variation) {
|
|
7205
7285
|
const variationHash = Hasher.getHashDouble({
|
|
@@ -7561,7 +7641,6 @@ class KameleoonEventSource {
|
|
|
7561
7641
|
const VISITOR_CODE_LENGTH = 16;
|
|
7562
7642
|
const VISITOR_CODE_MAX_LENGTH = 255;
|
|
7563
7643
|
const DEFAULT_MAX_AGE = 60 * 60 * 24 * 365;
|
|
7564
|
-
const ZERO_MAX_AGE = 0;
|
|
7565
7644
|
const PATH = '/';
|
|
7566
7645
|
|
|
7567
7646
|
/**
|
|
@@ -8029,7 +8108,7 @@ class Tracker {
|
|
|
8029
8108
|
this.dataManager.storeTrackedData(updatedData);
|
|
8030
8109
|
}
|
|
8031
8110
|
else {
|
|
8032
|
-
this.dataManager.storeData(updatedData);
|
|
8111
|
+
this.dataManager.storeData(updatedData, false);
|
|
8033
8112
|
}
|
|
8034
8113
|
}
|
|
8035
8114
|
getUnsentVisitorData(visitorCode, isConsentProvided) {
|
|
@@ -8381,16 +8460,23 @@ class KameleoonClient {
|
|
|
8381
8460
|
const variations = new Map();
|
|
8382
8461
|
const featureFlags = this.clientConfiguration.featureFlags;
|
|
8383
8462
|
for (const featureFlag of featureFlags.values()) {
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
if (
|
|
8463
|
+
try {
|
|
8464
|
+
const variation = this._getFeatureVariation({
|
|
8465
|
+
visitorCode,
|
|
8466
|
+
featureKey: featureFlag.featureKey,
|
|
8467
|
+
track,
|
|
8468
|
+
});
|
|
8469
|
+
if (variation.ok &&
|
|
8470
|
+
(!onlyActive || variation.data.key !== OFF_VARIATION_KEY)) {
|
|
8391
8471
|
variations.set(featureFlag.featureKey, variation.data);
|
|
8392
8472
|
}
|
|
8393
8473
|
}
|
|
8474
|
+
catch (err) {
|
|
8475
|
+
if (err instanceof KameleoonError &&
|
|
8476
|
+
err.type !== KameleoonException.FeatureFlagEnvironmentDisabled) {
|
|
8477
|
+
throw err;
|
|
8478
|
+
}
|
|
8479
|
+
}
|
|
8394
8480
|
}
|
|
8395
8481
|
KameleoonLogger.info `RETURN: KameleoonClient.getVariations(visitorCode: ${visitorCode}, onlyActive: ${onlyActive}, track: ${track}) -> (variations: ${variations})`;
|
|
8396
8482
|
return variations;
|
|
@@ -8710,25 +8796,16 @@ class KameleoonClient {
|
|
|
8710
8796
|
path: PATH,
|
|
8711
8797
|
});
|
|
8712
8798
|
}
|
|
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
8799
|
KameleoonLogger.info `RETURN: KameleoonClient.setUserConsent(visitorCode: ${visitorCode}, consent: ${consent}, setData: ${setData})`;
|
|
8724
8800
|
}
|
|
8725
8801
|
updateConsentData(visitorCode, consent) {
|
|
8726
8802
|
const readResult = this.consentDataStorage.read();
|
|
8803
|
+
const legalConsent = consent ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8727
8804
|
if (!readResult.ok) {
|
|
8728
8805
|
if (readResult.error.type === KameleoonException.StorageEmpty) {
|
|
8729
8806
|
this.consentDataStorage.write({
|
|
8730
8807
|
[visitorCode]: {
|
|
8731
|
-
consent,
|
|
8808
|
+
consent: legalConsent,
|
|
8732
8809
|
},
|
|
8733
8810
|
});
|
|
8734
8811
|
}
|
|
@@ -8736,28 +8813,36 @@ class KameleoonClient {
|
|
|
8736
8813
|
}
|
|
8737
8814
|
const data = readResult.data;
|
|
8738
8815
|
data[visitorCode] = {
|
|
8739
|
-
consent,
|
|
8816
|
+
consent: legalConsent,
|
|
8740
8817
|
};
|
|
8741
8818
|
this.consentDataStorage.write(data);
|
|
8742
8819
|
}
|
|
8820
|
+
getLegalConsent(visitorCode) {
|
|
8821
|
+
KameleoonLogger.debug `CALL: KameleoonClient.getLegalConsent(visitorCode: ${visitorCode})`;
|
|
8822
|
+
let legalConsent;
|
|
8823
|
+
const consentDataResult = this.consentDataStorage.read();
|
|
8824
|
+
legalConsent = consentDataResult.ok
|
|
8825
|
+
? this.extractLegalConsent(consentDataResult.data[visitorCode])
|
|
8826
|
+
: LegalConsent.Unknown;
|
|
8827
|
+
KameleoonLogger.debug `RETURN: KameleoonClient.getLegalConsent(visitorCode: ${visitorCode}) -> (legalConsent: ${legalConsent})`;
|
|
8828
|
+
return legalConsent;
|
|
8829
|
+
}
|
|
8830
|
+
extractLegalConsent(consentData) {
|
|
8831
|
+
if (consentData === undefined)
|
|
8832
|
+
return LegalConsent.Unknown;
|
|
8833
|
+
if (typeof consentData === 'boolean') {
|
|
8834
|
+
return consentData ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8835
|
+
}
|
|
8836
|
+
const value = consentData.consent;
|
|
8837
|
+
if (typeof value === 'boolean')
|
|
8838
|
+
return value ? LegalConsent.Given : LegalConsent.NotGiven;
|
|
8839
|
+
return value;
|
|
8840
|
+
}
|
|
8743
8841
|
_isConsentProvided(visitorCode) {
|
|
8744
8842
|
KameleoonLogger.debug `CALL: KameleoonClient._isConsentProvided(visitorCode: ${visitorCode})`;
|
|
8745
8843
|
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
|
-
}
|
|
8844
|
+
const isConsentProvided = !isConsentRequired ||
|
|
8845
|
+
this.getLegalConsent(visitorCode) == LegalConsent.Given;
|
|
8761
8846
|
KameleoonLogger.debug `RETURN: KameleoonClient._isConsentProvided(visitorCode: ${visitorCode}) -> (isConsentProvided: ${isConsentProvided})`;
|
|
8762
8847
|
return isConsentProvided;
|
|
8763
8848
|
}
|
|
@@ -8785,22 +8870,32 @@ class KameleoonClient {
|
|
|
8785
8870
|
if (!featureFlag.environmentEnabled) {
|
|
8786
8871
|
continue;
|
|
8787
8872
|
}
|
|
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,
|
|
8873
|
+
try {
|
|
8874
|
+
const evalExp = this._evaluate({
|
|
8875
|
+
visitorCode,
|
|
8876
|
+
featureFlag,
|
|
8877
|
+
track: false,
|
|
8878
|
+
save: false,
|
|
8803
8879
|
});
|
|
8880
|
+
if (evalExp.variationKey !== OFF_VARIATION_KEY) {
|
|
8881
|
+
activeVariations.push({
|
|
8882
|
+
variationKey: evalExp.variationKey,
|
|
8883
|
+
variationId: evalExp.variationId,
|
|
8884
|
+
experimentId: evalExp.experimentId,
|
|
8885
|
+
featureFlagId: featureFlag.id,
|
|
8886
|
+
featureKey: featureFlag.featureKey,
|
|
8887
|
+
rule: null,
|
|
8888
|
+
isTargetedRule: evalExp.ruleType === RuleType.TARGETED_DELIVERY,
|
|
8889
|
+
});
|
|
8890
|
+
}
|
|
8891
|
+
}
|
|
8892
|
+
catch (err) {
|
|
8893
|
+
if (err instanceof KameleoonError) {
|
|
8894
|
+
if (err.type != KameleoonException.FeatureFlagEnvironmentDisabled) {
|
|
8895
|
+
KameleoonLogger.error `Unexpected error: ${err}`;
|
|
8896
|
+
}
|
|
8897
|
+
continue;
|
|
8898
|
+
}
|
|
8804
8899
|
}
|
|
8805
8900
|
}
|
|
8806
8901
|
KameleoonLogger.debug `RETURN: KameleoonClient._getActiveFeatureVariations(visitorCode: ${visitorCode}) -> (activeVariations: ${activeVariations})`;
|
|
@@ -8821,6 +8916,7 @@ class KameleoonClient {
|
|
|
8821
8916
|
else if (this._isVisitorNotInHoldout(visitorCode, track, save, featureFlag, visitorData) &&
|
|
8822
8917
|
this._isFFUnrestrictedByMEGroup(visitorCode, featureFlag, visitorData)) {
|
|
8823
8918
|
const visitorIdentifier = this._getCodeForHash(visitorCode, featureFlag.bucketingCustomDataIndex, visitorData);
|
|
8919
|
+
const legalConsent = this.getLegalConsent(visitorCode);
|
|
8824
8920
|
const variationData = this.variationConfiguration
|
|
8825
8921
|
.getVariation({
|
|
8826
8922
|
visitorCode,
|
|
@@ -8832,6 +8928,7 @@ class KameleoonClient {
|
|
|
8832
8928
|
clientConfiguration: this.clientConfiguration,
|
|
8833
8929
|
dataManager: this.dataManager,
|
|
8834
8930
|
packageInfo: this.externalPackageInfo,
|
|
8931
|
+
legalConsent,
|
|
8835
8932
|
})
|
|
8836
8933
|
.throw();
|
|
8837
8934
|
evalExp =
|
|
@@ -8950,6 +9047,16 @@ class KameleoonClient {
|
|
|
8950
9047
|
}
|
|
8951
9048
|
KameleoonLogger.debug `CALL: KameleoonClient._isVisitorNotInHoldout(visitorCode: ${visitorCode}, track: ${track}, save: ${save}, featureFlag: ${featureFlag}, visitorData: ${visitorData})`;
|
|
8952
9049
|
let isNotInHoldout = true;
|
|
9050
|
+
// Checking if the evaluation is blocked due to the consent policy
|
|
9051
|
+
const legalConsent = this.clientConfiguration.isConsentRequired
|
|
9052
|
+
? this.getLegalConsent(visitorCode)
|
|
9053
|
+
: LegalConsent.Given;
|
|
9054
|
+
if (legalConsent == LegalConsent.NotGiven) {
|
|
9055
|
+
const behaviour = this.clientConfiguration.consentBlockingBehaviour;
|
|
9056
|
+
if (behaviour == ConsentBlockingBehaviour.CompletelyBlocked) {
|
|
9057
|
+
throw new KameleoonError(KameleoonException.FeatureFlagEnvironmentDisabled, `Evaluation of holdout is blocked because consent is not provided for visitor '${visitorCode}'`);
|
|
9058
|
+
}
|
|
9059
|
+
}
|
|
8953
9060
|
const codeForHash = this._getCodeForHash(visitorCode, featureFlag === null || featureFlag === void 0 ? void 0 : featureFlag.bucketingCustomDataIndex, visitorData);
|
|
8954
9061
|
const holdoutHash = Hasher.getHashDouble({
|
|
8955
9062
|
visitorIdentifier: codeForHash,
|