@mparticle/web-sdk 2.18.3 → 2.19.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/dist/mparticle.js CHANGED
@@ -725,7 +725,7 @@ var mParticle = (function () {
725
725
  Environment: Environment
726
726
  };
727
727
 
728
- var version = "2.18.3";
728
+ var version = "2.19.1";
729
729
 
730
730
  var Constants = {
731
731
  sdkVersion: version,
@@ -2111,12 +2111,27 @@ var mParticle = (function () {
2111
2111
  }
2112
2112
  }
2113
2113
 
2114
+ /**
2115
+ * BatchUploader contains all the logic to upload batches to mParticle.
2116
+ * It queues events as they come in and at set intervals turns them into batches.
2117
+ * It then attempts to upload them to mParticle.
2118
+ *
2119
+ * These uploads happen on an interval basis using window.fetch or XHR
2120
+ * requests, depending on what is available in the browser.
2121
+ *
2122
+ * Uploads can also be triggered on browser visibility/focus changes via an
2123
+ * event listener, which then uploads to mPartice via the browser's Beacon API.
2124
+ */
2125
+
2114
2126
  var BatchUploader =
2115
2127
  /** @class */
2116
2128
  function () {
2129
+ /**
2130
+ * Creates an instance of a BatchUploader
2131
+ * @param {MParticleWebSDK} mpInstance - the mParticle SDK instance
2132
+ * @param {number} uploadInterval - the desired upload interval in milliseconds
2133
+ */
2117
2134
  function BatchUploader(mpInstance, uploadInterval) {
2118
- var _this_1 = this;
2119
-
2120
2135
  this.mpInstance = mpInstance;
2121
2136
  this.uploadIntervalMillis = uploadInterval;
2122
2137
  this.batchingEnabled = uploadInterval >= BatchUploader.MINIMUM_INTERVAL_MILLIS;
@@ -2125,8 +2140,8 @@ var mParticle = (function () {
2125
2140
  this.uploadIntervalMillis = BatchUploader.MINIMUM_INTERVAL_MILLIS;
2126
2141
  }
2127
2142
 
2128
- this.pendingEvents = [];
2129
- this.pendingUploads = [];
2143
+ this.eventsQueuedForProcessing = [];
2144
+ this.batchesQueuedForProcessing = [];
2130
2145
  var _a = this.mpInstance._Store,
2131
2146
  SDKConfig = _a.SDKConfig,
2132
2147
  devToken = _a.devToken;
@@ -2134,14 +2149,16 @@ var mParticle = (function () {
2134
2149
  var baseUrl = this.mpInstance._Helpers.createServiceUrl(SDKConfig.v3SecureServiceUrl, devToken);
2135
2150
 
2136
2151
  this.uploadUrl = "".concat(baseUrl, "/events");
2137
- setTimeout(function () {
2138
- _this_1.prepareAndUpload(true, false);
2139
- }, this.uploadIntervalMillis);
2152
+ this.uploader = window.fetch ? new FetchUploader(this.uploadUrl) : new XHRUploader(this.uploadUrl);
2153
+ this.triggerUploadInterval(true, false);
2140
2154
  this.addEventListeners();
2141
- }
2155
+ } // Adds listeners to be used trigger Navigator.sendBeacon if the browser
2156
+ // loses focus for any reason, such as closing browser tab or minimizing window
2157
+
2142
2158
 
2143
2159
  BatchUploader.prototype.addEventListeners = function () {
2144
- var _this = this;
2160
+ var _this = this; // visibility change is a document property, not window
2161
+
2145
2162
 
2146
2163
  document.addEventListener('visibilitychange', function () {
2147
2164
  _this.prepareAndUpload(false, _this.isBeaconAvailable());
@@ -2160,13 +2177,36 @@ var mParticle = (function () {
2160
2177
  }
2161
2178
 
2162
2179
  return false;
2180
+ }; // Triggers a setTimeout for prepareAndUpload
2181
+
2182
+
2183
+ BatchUploader.prototype.triggerUploadInterval = function (triggerFuture, useBeacon) {
2184
+ var _this_1 = this;
2185
+
2186
+ if (triggerFuture === void 0) {
2187
+ triggerFuture = false;
2188
+ }
2189
+
2190
+ if (useBeacon === void 0) {
2191
+ useBeacon = false;
2192
+ }
2193
+
2194
+ setTimeout(function () {
2195
+ _this_1.prepareAndUpload(triggerFuture, useBeacon);
2196
+ }, this.uploadIntervalMillis);
2163
2197
  };
2198
+ /**
2199
+ * This method will queue a single Event which will eventually be processed into a Batch
2200
+ * @param event event that should be queued
2201
+ */
2202
+
2164
2203
 
2165
2204
  BatchUploader.prototype.queueEvent = function (event) {
2166
2205
  if (!isEmpty(event)) {
2167
- this.pendingEvents.push(event);
2206
+ this.eventsQueuedForProcessing.push(event);
2168
2207
  this.mpInstance.Logger.verbose("Queuing event: ".concat(JSON.stringify(event)));
2169
- this.mpInstance.Logger.verbose("Queued event count: ".concat(this.pendingEvents.length));
2208
+ this.mpInstance.Logger.verbose("Queued event count: ".concat(this.eventsQueuedForProcessing.length)); // TODO: Remove this check once the v2 code path is removed
2209
+ // https://go.mparticle.com/work/SQDSDKS-3720
2170
2210
 
2171
2211
  if (!this.batchingEnabled || Types.TriggerUploadType[event.EventDataType]) {
2172
2212
  this.prepareAndUpload(false, false);
@@ -2184,7 +2224,7 @@ var mParticle = (function () {
2184
2224
  */
2185
2225
 
2186
2226
 
2187
- BatchUploader.createNewUploads = function (sdkEvents, defaultUser, mpInstance) {
2227
+ BatchUploader.createNewBatches = function (sdkEvents, defaultUser, mpInstance) {
2188
2228
  if (!defaultUser || !sdkEvents || !sdkEvents.length) {
2189
2229
  return null;
2190
2230
  } //bucket by MPID, and then by session, ordered by timestamp
@@ -2264,157 +2304,139 @@ var mParticle = (function () {
2264
2304
 
2265
2305
  BatchUploader.prototype.prepareAndUpload = function (triggerFuture, useBeacon) {
2266
2306
  return __awaiter(this, void 0, void 0, function () {
2267
- var currentUser, currentEvents, newUploads, currentUploads, remainingUploads;
2307
+ var currentUser, currentEvents, newBatches, batchesToUpload, batchesThatDidNotUpload, promises;
2268
2308
 
2269
- var _a, _b;
2309
+ var _a;
2270
2310
 
2271
2311
  var _this_1 = this;
2272
2312
 
2273
- return __generator(this, function (_c) {
2274
- switch (_c.label) {
2275
- case 0:
2276
- currentUser = this.mpInstance.Identity.getCurrentUser();
2277
- currentEvents = this.pendingEvents;
2278
- this.pendingEvents = [];
2279
- newUploads = BatchUploader.createNewUploads(currentEvents, currentUser, this.mpInstance);
2313
+ return __generator(this, function (_b) {
2314
+ currentUser = this.mpInstance.Identity.getCurrentUser();
2315
+ currentEvents = this.eventsQueuedForProcessing;
2316
+ this.eventsQueuedForProcessing = [];
2317
+ newBatches = BatchUploader.createNewBatches(currentEvents, currentUser, this.mpInstance);
2280
2318
 
2281
- if (newUploads && newUploads.length) {
2282
- (_a = this.pendingUploads).push.apply(_a, newUploads);
2283
- }
2319
+ if (!isEmpty(newBatches)) {
2320
+ (_a = this.batchesQueuedForProcessing).push.apply(_a, newBatches);
2321
+ }
2284
2322
 
2285
- currentUploads = this.pendingUploads;
2286
- this.pendingUploads = [];
2287
- return [4
2288
- /*yield*/
2289
- , this.upload(this.mpInstance.Logger, currentUploads, useBeacon)];
2323
+ batchesToUpload = this.batchesQueuedForProcessing;
2324
+ batchesThatDidNotUpload = [];
2325
+ this.batchesQueuedForProcessing = [];
2326
+ promises = batchesToUpload.map(function (upload) {
2327
+ return _this_1.upload(_this_1.mpInstance.Logger, upload, useBeacon);
2328
+ }); // Iterate through fulfilled promises and store any remaining batches
2329
+ // for future re-transmission attempts
2290
2330
 
2291
- case 1:
2292
- remainingUploads = _c.sent();
2331
+ if (!isEmpty(promises)) {
2332
+ Promise.all(promises).then(function (batchResponses) {
2333
+ batchResponses.forEach(function (batch) {
2334
+ return !isEmpty(batch) ? batchesThatDidNotUpload.push(batch) : null;
2335
+ });
2336
+ })["catch"](function (error) {
2337
+ _this_1.mpInstance.Logger.error("Error processing batches during upload attempt: ".concat(error));
2338
+ })["finally"](function () {
2339
+ var _a; // Any batches that did not upload should be put back into the queue for processing
2293
2340
 
2294
- if (remainingUploads && remainingUploads.length) {
2295
- (_b = this.pendingUploads).unshift.apply(_b, remainingUploads);
2296
- }
2297
2341
 
2298
- if (triggerFuture) {
2299
- setTimeout(function () {
2300
- _this_1.prepareAndUpload(true, false);
2301
- }, this.uploadIntervalMillis);
2342
+ if (!isEmpty(batchesThatDidNotUpload)) {
2343
+ (_a = _this_1.batchesQueuedForProcessing).unshift.apply(_a, batchesThatDidNotUpload);
2302
2344
  }
2345
+ });
2346
+ }
2303
2347
 
2304
- return [2
2305
- /*return*/
2306
- ];
2348
+ if (triggerFuture) {
2349
+ this.triggerUploadInterval(triggerFuture, false);
2307
2350
  }
2351
+
2352
+ return [2
2353
+ /*return*/
2354
+ ];
2308
2355
  });
2309
2356
  });
2310
2357
  };
2311
2358
 
2312
- BatchUploader.prototype.upload = function (logger, _uploads, useBeacon) {
2359
+ BatchUploader.prototype.upload = function (logger, batch, useBeacon) {
2313
2360
  return __awaiter(this, void 0, void 0, function () {
2314
- var uploader, uploads, i, fetchPayload, blob, response, e_1;
2361
+ var fetchPayload, blob, response, error_1;
2315
2362
  return __generator(this, function (_a) {
2316
2363
  switch (_a.label) {
2317
2364
  case 0:
2318
- uploads = _uploads.filter(function (upload) {
2319
- return !isEmpty(upload.events);
2320
- });
2321
-
2322
- if (isEmpty(uploads)) {
2365
+ if (isEmpty(batch) || isEmpty(batch.events)) {
2323
2366
  return [2
2324
2367
  /*return*/
2325
2368
  , null];
2326
2369
  }
2327
2370
 
2328
- logger.verbose("Uploading batches: ".concat(JSON.stringify(uploads)));
2329
- logger.verbose("Batch count: ".concat(uploads.length));
2330
- i = 0;
2331
- _a.label = 1;
2332
-
2333
- case 1:
2334
- if (!(i < uploads.length)) return [3
2335
- /*break*/
2336
- , 7];
2371
+ logger.verbose("Uploading batches: ".concat(JSON.stringify(batch)));
2337
2372
  fetchPayload = {
2338
2373
  method: 'POST',
2339
2374
  headers: {
2340
2375
  Accept: BatchUploader.CONTENT_TYPE,
2341
2376
  'Content-Type': 'text/plain;charset=UTF-8'
2342
2377
  },
2343
- body: JSON.stringify(uploads[i])
2378
+ body: JSON.stringify(batch)
2344
2379
  };
2345
2380
  if (!(useBeacon && this.isBeaconAvailable())) return [3
2346
2381
  /*break*/
2347
- , 2];
2382
+ , 1];
2348
2383
  blob = new Blob([fetchPayload.body], {
2349
2384
  type: 'text/plain;charset=UTF-8'
2350
2385
  });
2351
2386
  navigator.sendBeacon(this.uploadUrl, blob);
2352
2387
  return [3
2353
2388
  /*break*/
2354
- , 6];
2355
-
2356
- case 2:
2357
- if (!uploader) {
2358
- if (window.fetch) {
2359
- uploader = new FetchUploader(this.uploadUrl, logger);
2360
- } else {
2361
- uploader = new XHRUploader(this.uploadUrl, logger);
2362
- }
2363
- }
2364
-
2365
- _a.label = 3;
2389
+ , 4];
2366
2390
 
2367
- case 3:
2368
- _a.trys.push([3, 5,, 6]);
2391
+ case 1:
2392
+ _a.trys.push([1, 3,, 4]);
2369
2393
 
2370
2394
  return [4
2371
2395
  /*yield*/
2372
- , uploader.upload(fetchPayload, uploads, i)];
2396
+ , this.uploader.upload(fetchPayload)];
2373
2397
 
2374
- case 4:
2375
- response = _a.sent();
2398
+ case 2:
2399
+ response = _a.sent(); // TODO: Should we make this a switch statement instead?
2376
2400
 
2377
2401
  if (response.status >= 200 && response.status < 300) {
2378
- logger.verbose("Upload success for request ID: ".concat(uploads[i].source_request_id));
2402
+ logger.verbose("Upload success for request ID: ".concat(batch.source_request_id));
2403
+ return [2
2404
+ /*return*/
2405
+ , null];
2379
2406
  } else if (response.status >= 500 || response.status === 429) {
2380
- logger.error("HTTP error status ".concat(response.status, " received")); //server error, add back current events and try again later
2407
+ logger.error("HTTP error status ".concat(response.status, " received")); // Server error, return current batch and try again later
2381
2408
 
2382
2409
  return [2
2383
2410
  /*return*/
2384
- , uploads.slice(i, uploads.length)];
2411
+ , batch];
2385
2412
  } else if (response.status >= 401) {
2386
- logger.error("HTTP error status ".concat(response.status, " while uploading - please verify your API key.")); //if we're getting a 401, assume we'll keep getting a 401 and clear the uploads.
2413
+ logger.error("HTTP error status ".concat(response.status, " while uploading - please verify your API key.")); // if we're getting a 401, assume we'll keep getting a 401
2414
+ // so return the upload so it can be stored for later use
2387
2415
 
2388
2416
  return [2
2389
2417
  /*return*/
2390
- , null];
2418
+ , batch];
2391
2419
  }
2392
2420
 
2393
2421
  return [3
2394
2422
  /*break*/
2395
- , 6];
2423
+ , 4];
2396
2424
 
2397
- case 5:
2398
- e_1 = _a.sent();
2399
- logger.error("Error sending event to mParticle servers. ".concat(e_1));
2425
+ case 3:
2426
+ error_1 = _a.sent();
2427
+ logger.error("Error sending event to mParticle servers. ".concat(error_1));
2400
2428
  return [2
2401
2429
  /*return*/
2402
- , uploads.slice(i, uploads.length)];
2430
+ , batch];
2403
2431
 
2404
- case 6:
2405
- i++;
2406
- return [3
2407
- /*break*/
2408
- , 1];
2409
-
2410
- case 7:
2432
+ case 4:
2411
2433
  return [2
2412
2434
  /*return*/
2413
2435
  , null];
2414
2436
  }
2415
2437
  });
2416
2438
  });
2417
- }; //we upload JSON, but this content type is required to avoid a CORS preflight request
2439
+ }; // We upload JSON, but this content type is required to avoid a CORS preflight request
2418
2440
 
2419
2441
 
2420
2442
  BatchUploader.CONTENT_TYPE = 'text/plain;charset=UTF-8';
@@ -2425,9 +2447,8 @@ var mParticle = (function () {
2425
2447
  var AsyncUploader =
2426
2448
  /** @class */
2427
2449
  function () {
2428
- function AsyncUploader(url, logger) {
2450
+ function AsyncUploader(url) {
2429
2451
  this.url = url;
2430
- this.logger = logger;
2431
2452
  }
2432
2453
 
2433
2454
  return AsyncUploader;
@@ -2442,7 +2463,7 @@ var mParticle = (function () {
2442
2463
  return _super !== null && _super.apply(this, arguments) || this;
2443
2464
  }
2444
2465
 
2445
- FetchUploader.prototype.upload = function (fetchPayload, uploads, i) {
2466
+ FetchUploader.prototype.upload = function (fetchPayload) {
2446
2467
  return __awaiter(this, void 0, void 0, function () {
2447
2468
  var response;
2448
2469
  return __generator(this, function (_a) {
@@ -2474,7 +2495,7 @@ var mParticle = (function () {
2474
2495
  return _super !== null && _super.apply(this, arguments) || this;
2475
2496
  }
2476
2497
 
2477
- XHRUploader.prototype.upload = function (fetchPayload, uploads, i) {
2498
+ XHRUploader.prototype.upload = function (fetchPayload) {
2478
2499
  return __awaiter(this, void 0, void 0, function () {
2479
2500
  var response;
2480
2501
  return __generator(this, function (_a) {
@@ -2482,7 +2503,7 @@ var mParticle = (function () {
2482
2503
  case 0:
2483
2504
  return [4
2484
2505
  /*yield*/
2485
- , this.makeRequest(this.url, this.logger, fetchPayload.body)];
2506
+ , this.makeRequest(this.url, fetchPayload.body)];
2486
2507
 
2487
2508
  case 1:
2488
2509
  response = _a.sent();
@@ -2494,7 +2515,7 @@ var mParticle = (function () {
2494
2515
  });
2495
2516
  };
2496
2517
 
2497
- XHRUploader.prototype.makeRequest = function (url, logger, data) {
2518
+ XHRUploader.prototype.makeRequest = function (url, data) {
2498
2519
  return __awaiter(this, void 0, void 0, function () {
2499
2520
  var xhr;
2500
2521
  return __generator(this, function (_a) {
@@ -2658,7 +2679,7 @@ var mParticle = (function () {
2658
2679
  if (xhr) {
2659
2680
  try {
2660
2681
  xhr.open('post', mpInstance._Helpers.createServiceUrl(mpInstance._Store.SDKConfig.v2SecureServiceUrl, mpInstance._Store.devToken) + '/Events');
2661
- xhr.send(JSON.stringify(mpInstance._ServerModel.convertEventToDTO(event)));
2682
+ xhr.send(JSON.stringify(mpInstance._ServerModel.convertEventToV2DTO(event)));
2662
2683
  } catch (e) {
2663
2684
  mpInstance.Logger.error('Error sending event to mParticle servers. ' + e);
2664
2685
  }
@@ -3414,33 +3435,43 @@ var mParticle = (function () {
3414
3435
 
3415
3436
  var Messages$7 = Constants.Messages;
3416
3437
  function cookieSyncManager(mpInstance) {
3417
- var self = this;
3438
+ var self = this; // Public
3418
3439
 
3419
3440
  this.attemptCookieSync = function (previousMPID, mpid, mpidIsNotInCookies) {
3420
- var pixelConfig, lastSyncDateForModule, url, redirect, urlWithRedirect, requiresConsent;
3441
+ // TODO: These should move inside the for loop
3442
+ var pixelConfig, lastSyncDateForModule, url, redirect, urlWithRedirect, requiresConsent; // TODO: Make this exit quicker instead of nested
3421
3443
 
3422
3444
  if (mpid && !mpInstance._Store.webviewBridgeEnabled) {
3423
3445
  mpInstance._Store.pixelConfigurations.forEach(function (pixelSettings) {
3424
3446
  // set requiresConsent to false to start each additional pixel configuration
3425
3447
  // set to true only if filteringConsenRuleValues.values.length exists
3426
- requiresConsent = false;
3448
+ requiresConsent = false; // TODO: Replace with isEmpty
3427
3449
 
3428
3450
  if (pixelSettings.filteringConsentRuleValues && pixelSettings.filteringConsentRuleValues.values && pixelSettings.filteringConsentRuleValues.values.length) {
3429
3451
  requiresConsent = true;
3430
3452
  }
3431
3453
 
3432
3454
  pixelConfig = {
3455
+ // Kit Module ID
3433
3456
  moduleId: pixelSettings.moduleId,
3457
+ // Tells you how often we should do a cookie sync (in days)
3434
3458
  frequencyCap: pixelSettings.frequencyCap,
3459
+ // Url for cookie sync pixel
3435
3460
  pixelUrl: self.replaceAmp(pixelSettings.pixelUrl),
3461
+ // TODO: Document requirements for redirectUrl
3436
3462
  redirectUrl: pixelSettings.redirectUrl ? self.replaceAmp(pixelSettings.redirectUrl) : null,
3463
+ // Filtering rules as defined in UI
3437
3464
  filteringConsentRuleValues: pixelSettings.filteringConsentRuleValues
3438
- };
3465
+ }; // TODO: combine replaceMPID and replaceAmp into sanitizeUrl function
3466
+
3439
3467
  url = self.replaceMPID(pixelConfig.pixelUrl, mpid);
3440
3468
  redirect = pixelConfig.redirectUrl ? self.replaceMPID(pixelConfig.redirectUrl, mpid) : '';
3441
- urlWithRedirect = url + encodeURIComponent(redirect);
3469
+ urlWithRedirect = url + encodeURIComponent(redirect); // TODO: Refactor so that Persistence is only called once
3470
+ // outside of the loop
3471
+
3472
+ var persistence = mpInstance._Persistence.getPersistence(); // TODO: Is there a historic reason for checking for previousMPID?
3473
+ // it does not appear to be passed in anywhere
3442
3474
 
3443
- var persistence = mpInstance._Persistence.getPersistence();
3444
3475
 
3445
3476
  if (previousMPID && previousMPID !== mpid) {
3446
3477
  if (persistence && persistence[mpid]) {
@@ -3453,6 +3484,8 @@ var mParticle = (function () {
3453
3484
 
3454
3485
  return;
3455
3486
  } else {
3487
+ // TODO: Refactor to check for the inverse and exit early
3488
+ // rather than nesting
3456
3489
  if (persistence[mpid]) {
3457
3490
  if (!persistence[mpid].csd) {
3458
3491
  persistence[mpid].csd = {};
@@ -3462,7 +3495,12 @@ var mParticle = (function () {
3462
3495
 
3463
3496
  if (lastSyncDateForModule) {
3464
3497
  // Check to see if we need to refresh cookieSync
3465
- if (new Date().getTime() > new Date(lastSyncDateForModule).getTime() + pixelConfig.frequencyCap * 60 * 1000 * 60 * 24) {
3498
+ if ( // TODO: Turn this into a convenience method for readability?
3499
+ // We use similar comparisons elsewhere in the SDK,
3500
+ // so perhaps we can make a time comparison convenience method
3501
+ new Date().getTime() > new Date(lastSyncDateForModule).getTime() + pixelConfig.frequencyCap * // TODO: Turn these numbers into a constant so
3502
+ // we can remember what this number is for
3503
+ 60 * 1000 * 60 * 24) {
3466
3504
  self.performCookieSync(urlWithRedirect, pixelConfig.moduleId, mpid, persistence[mpid].csd, pixelConfig.filteringConsentRuleValues, mpidIsNotInCookies, requiresConsent);
3467
3505
  }
3468
3506
  } else {
@@ -3472,29 +3510,40 @@ var mParticle = (function () {
3472
3510
  }
3473
3511
  });
3474
3512
  }
3475
- };
3513
+ }; // Private
3514
+
3476
3515
 
3477
3516
  this.replaceMPID = function (string, mpid) {
3478
3517
  return string.replace('%%mpid%%', mpid);
3479
- };
3518
+ }; // Private
3519
+ // TODO: Rename function to replaceAmpWithAmpersand
3520
+
3480
3521
 
3481
3522
  this.replaceAmp = function (string) {
3482
3523
  return string.replace(/&amp;/g, '&');
3483
- };
3524
+ }; // Private
3525
+
3484
3526
 
3485
3527
  this.performCookieSync = function (url, moduleId, mpid, cookieSyncDates, filteringConsentRuleValues, mpidIsNotInCookies, requiresConsent) {
3486
3528
  // if MPID is new to cookies, we should not try to perform the cookie sync
3487
3529
  // because a cookie sync can only occur once a user either consents or doesn't
3488
3530
  // we should not check if its enabled if the user has a blank consent
3531
+ // TODO: We should do this check outside of this function
3489
3532
  if (requiresConsent && mpidIsNotInCookies) {
3490
3533
  return;
3491
- }
3534
+ } // TODO: Refactor so that check is made outside of the function.
3535
+ // Cache or store the boolean so that it only gets called once per
3536
+ // cookie sync attempt per module.
3537
+ // Currently, attemptCookieSync is called as a loop and therefore this
3538
+ // function polls the user object and consent multiple times.
3539
+
3492
3540
 
3493
3541
  if (mpInstance._Consent.isEnabledForUserConsent(filteringConsentRuleValues, mpInstance.Identity.getCurrentUser())) {
3494
3542
  var img = document.createElement('img');
3495
3543
  mpInstance.Logger.verbose(Messages$7.InformationMessages.CookieSync);
3496
3544
 
3497
3545
  img.onload = function () {
3546
+ // TODO: Break this out into a convenience method so we can unit test
3498
3547
  cookieSyncDates[moduleId.toString()] = new Date().getTime();
3499
3548
 
3500
3549
  mpInstance._Persistence.saveUserCookieSyncDatesToPersistence(mpid, cookieSyncDates);
@@ -6564,7 +6613,7 @@ var mParticle = (function () {
6564
6613
  }
6565
6614
  }
6566
6615
 
6567
- function convertProductToDTO(product) {
6616
+ function convertProductToV2DTO(product) {
6568
6617
  return {
6569
6618
  id: parseStringOrNumber(product.Sku),
6570
6619
  nm: parseStringOrNumber(product.Name),
@@ -6580,13 +6629,13 @@ var mParticle = (function () {
6580
6629
  };
6581
6630
  }
6582
6631
 
6583
- function convertProductListToDTO(productList) {
6632
+ function convertProductListToV2DTO(productList) {
6584
6633
  if (!productList) {
6585
6634
  return [];
6586
6635
  }
6587
6636
 
6588
6637
  return productList.map(function (product) {
6589
- return convertProductToDTO(product);
6638
+ return convertProductToV2DTO(product);
6590
6639
  });
6591
6640
  }
6592
6641
 
@@ -6640,7 +6689,7 @@ var mParticle = (function () {
6640
6689
  event.UserIdentities = validUserIdentities;
6641
6690
  };
6642
6691
 
6643
- this.convertToConsentStateDTO = function (state) {
6692
+ this.convertToConsentStateV2DTO = function (state) {
6644
6693
  if (!state) {
6645
6694
  return null;
6646
6695
  }
@@ -6780,7 +6829,7 @@ var mParticle = (function () {
6780
6829
  return null;
6781
6830
  };
6782
6831
 
6783
- this.convertEventToDTO = function (event) {
6832
+ this.convertEventToV2DTO = function (event) {
6784
6833
  var dto = {
6785
6834
  n: event.EventName,
6786
6835
  et: event.EventCategory,
@@ -6814,7 +6863,7 @@ var mParticle = (function () {
6814
6863
  }
6815
6864
  }
6816
6865
 
6817
- var consent = self.convertToConsentStateDTO(event.ConsentState);
6866
+ var consent = self.convertToConsentStateV2DTO(event.ConsentState);
6818
6867
 
6819
6868
  if (consent) {
6820
6869
  dto.con = consent;
@@ -6839,7 +6888,7 @@ var mParticle = (function () {
6839
6888
 
6840
6889
  if (event.ShoppingCart) {
6841
6890
  dto.sc = {
6842
- pl: convertProductListToDTO(event.ShoppingCart.ProductList)
6891
+ pl: convertProductListToV2DTO(event.ShoppingCart.ProductList)
6843
6892
  };
6844
6893
  }
6845
6894
 
@@ -6848,7 +6897,7 @@ var mParticle = (function () {
6848
6897
  an: event.ProductAction.ProductActionType,
6849
6898
  cs: mpInstance._Helpers.parseNumber(event.ProductAction.CheckoutStep),
6850
6899
  co: event.ProductAction.CheckoutOptions,
6851
- pl: convertProductListToDTO(event.ProductAction.ProductList),
6900
+ pl: convertProductListToV2DTO(event.ProductAction.ProductList),
6852
6901
  ti: event.ProductAction.TransactionId,
6853
6902
  ta: event.ProductAction.Affiliation,
6854
6903
  tcc: event.ProductAction.CouponCode,
@@ -6872,7 +6921,7 @@ var mParticle = (function () {
6872
6921
  dto.pi = event.ProductImpressions.map(function (impression) {
6873
6922
  return {
6874
6923
  pil: impression.ProductImpressionList,
6875
- pl: convertProductListToDTO(impression.ProductList)
6924
+ pl: convertProductListToV2DTO(impression.ProductList)
6876
6925
  };
6877
6926
  });
6878
6927
  }
@@ -8220,9 +8269,11 @@ var mParticle = (function () {
8220
8269
  };
8221
8270
  }
8222
8271
 
8272
+ var CCPAPurpose = 'data_sale_opt_out';
8223
8273
  function Consent(mpInstance) {
8224
- var self = this;
8225
- var CCPAPurpose = 'data_sale_opt_out'; // this function is called when consent is required to determine if a cookie sync should happen, or a forwarder should be initialized
8274
+ var self = this; // this function is called when consent is required to
8275
+ // determine if a cookie sync should happen, or a
8276
+ // forwarder should be initialized
8226
8277
 
8227
8278
  this.isEnabledForUserConsent = function (consentRules, user) {
8228
8279
  if (!consentRules || !consentRules.values || !consentRules.values.length) {
@@ -8233,16 +8284,15 @@ var mParticle = (function () {
8233
8284
  return false;
8234
8285
  }
8235
8286
 
8236
- var purposeHashes = {},
8237
- consentState = user.getConsentState(),
8238
- purposeHash;
8287
+ var purposeHashes = {};
8288
+ var consentState = user.getConsentState();
8289
+ var purposeHash;
8239
8290
 
8240
8291
  if (consentState) {
8241
8292
  // the server hashes consent purposes in the following way:
8242
8293
  // GDPR - '1' + purpose name
8243
8294
  // CCPA - '2data_sale_opt_out' (there is only 1 purpose of data_sale_opt_out for CCPA)
8244
8295
  var GDPRConsentHashPrefix = '1';
8245
- var CCPAPurpose = 'data_sale_opt_out';
8246
8296
  var CCPAHashString = '2' + CCPAPurpose;
8247
8297
  var gdprConsentState = consentState.getGDPRConsentState();
8248
8298
 
@@ -8270,6 +8320,8 @@ var mParticle = (function () {
8270
8320
  if (purposeHashes.hasOwnProperty(consentPurposeHash)) {
8271
8321
  return purposeHashes[consentPurposeHash] === hasConsented;
8272
8322
  }
8323
+
8324
+ return false;
8273
8325
  });
8274
8326
  return consentRules.includeOnMatch === isMatch;
8275
8327
  };
@@ -8311,6 +8363,8 @@ var mParticle = (function () {
8311
8363
 
8312
8364
  this.ConsentSerialization = {
8313
8365
  toMinifiedJsonObject: function toMinifiedJsonObject(state) {
8366
+ var _a;
8367
+
8314
8368
  var jsonObject = {};
8315
8369
 
8316
8370
  if (state) {
@@ -8350,8 +8404,7 @@ var mParticle = (function () {
8350
8404
  var ccpaConsentState = state.getCCPAConsentState();
8351
8405
 
8352
8406
  if (ccpaConsentState) {
8353
- jsonObject.ccpa = {};
8354
- jsonObject.ccpa[CCPAPurpose] = {};
8407
+ jsonObject.ccpa = (_a = {}, _a[CCPAPurpose] = {}, _a);
8355
8408
 
8356
8409
  if (typeof ccpaConsentState.Consented === 'boolean') {
8357
8410
  jsonObject.ccpa[CCPAPurpose].c = ccpaConsentState.Consented;
@@ -8398,15 +8451,18 @@ var mParticle = (function () {
8398
8451
 
8399
8452
  return state;
8400
8453
  }
8401
- };
8454
+ }; // TODO: Refactor this method into a constructor
8402
8455
 
8403
8456
  this.createConsentState = function (consentState) {
8404
8457
  var gdpr = {};
8405
8458
  var ccpa = {};
8406
8459
 
8407
8460
  if (consentState) {
8408
- setGDPRConsentState(consentState.getGDPRConsentState());
8409
- setCCPAConsentState(consentState.getCCPAConsentState());
8461
+ var consentStateCopy = self.createConsentState();
8462
+ consentStateCopy.setGDPRConsentState(consentState.getGDPRConsentState());
8463
+ consentStateCopy.setCCPAConsentState(consentState.getCCPAConsentState()); // TODO: Remove casting once `removeCCPAState` is removed;
8464
+
8465
+ return consentStateCopy;
8410
8466
  }
8411
8467
 
8412
8468
  function canonicalizeForDeduplication(purpose) {
@@ -8425,7 +8481,7 @@ var mParticle = (function () {
8425
8481
  /**
8426
8482
  * Invoke these methods on a consent state object.
8427
8483
  * <p>
8428
- * Usage: var consent = mParticle.Consent.createConsentState()
8484
+ * Usage: const consent = mParticle.Consent.createConsentState()
8429
8485
  * <br>
8430
8486
  * consent.setGDPRCoonsentState()
8431
8487
  *
@@ -8449,7 +8505,7 @@ var mParticle = (function () {
8449
8505
  return this;
8450
8506
  }
8451
8507
 
8452
- if (!mpInstance._Helpers.isObject(gdprConsent)) {
8508
+ if (!isObject(gdprConsent)) {
8453
8509
  mpInstance.Logger.error('Invoked with a bad or empty consent object.');
8454
8510
  return this;
8455
8511
  }
@@ -8466,12 +8522,12 @@ var mParticle = (function () {
8466
8522
  function setGDPRConsentState(gdprConsentState) {
8467
8523
  if (!gdprConsentState) {
8468
8524
  gdpr = {};
8469
- } else if (mpInstance._Helpers.isObject(gdprConsentState)) {
8525
+ } else if (isObject(gdprConsentState)) {
8470
8526
  gdpr = {};
8471
8527
 
8472
8528
  for (var purpose in gdprConsentState) {
8473
8529
  if (gdprConsentState.hasOwnProperty(purpose)) {
8474
- addGDPRConsentState(purpose, gdprConsentState[purpose]);
8530
+ this.addGDPRConsentState(purpose, gdprConsentState[purpose]);
8475
8531
  }
8476
8532
  }
8477
8533
  }
@@ -8505,7 +8561,7 @@ var mParticle = (function () {
8505
8561
 
8506
8562
 
8507
8563
  function getGDPRConsentState() {
8508
- return mpInstance._Helpers.extend({}, gdpr);
8564
+ return Object.assign({}, gdpr);
8509
8565
  }
8510
8566
  /**
8511
8567
  * Sets a CCPA Consent state (has a single purpose of 'data_sale_opt_out')
@@ -8516,7 +8572,7 @@ var mParticle = (function () {
8516
8572
 
8517
8573
 
8518
8574
  function setCCPAConsentState(ccpaConsent) {
8519
- if (!mpInstance._Helpers.isObject(ccpaConsent)) {
8575
+ if (!isObject(ccpaConsent)) {
8520
8576
  mpInstance.Logger.error('Invoked with a bad or empty CCPA consent object.');
8521
8577
  return this;
8522
8578
  }
@@ -8550,10 +8606,12 @@ var mParticle = (function () {
8550
8606
  function removeCCPAConsentState() {
8551
8607
  delete ccpa[CCPAPurpose];
8552
8608
  return this;
8553
- }
8609
+ } // TODO: Can we remove this? It is deprecated.
8610
+
8554
8611
 
8555
8612
  function removeCCPAState() {
8556
- mpInstance.Logger.warning('removeCCPAState is deprecated and will be removed in a future release; use removeCCPAConsentState instead');
8613
+ mpInstance.Logger.warning('removeCCPAState is deprecated and will be removed in a future release; use removeCCPAConsentState instead'); // @ts-ignore
8614
+
8557
8615
  return removeCCPAConsentState();
8558
8616
  }
8559
8617
 
@@ -10645,6 +10703,9 @@ var mParticle = (function () {
10645
10703
  // Certain Helper, Store, and Identity properties need to be mocked to be used in the `returnBatch` method
10646
10704
  _Helpers: {
10647
10705
  sanitizeAttributes: window.mParticle.getInstance()._Helpers.sanitizeAttributes,
10706
+ generateHash: function generateHash() {
10707
+ return 'mockHash';
10708
+ },
10648
10709
  generateUniqueId: function generateUniqueId() {
10649
10710
  return 'mockId';
10650
10711
  },