@mparticle/web-sdk 2.28.1 → 2.28.2

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.
@@ -154,13 +154,13 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
154
154
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
155
155
  };
156
156
 
157
- var version = "2.28.1";
157
+ var version = "2.28.2";
158
158
 
159
159
  var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodIsDeprecatedPostfix:"is a deprecated method and will be removed in future releases",AlternativeMethodPrefix:"Please use the alternate method:"},ErrorMessages:{NoToken:"A token must be specified.",EventNameInvalidType:"Event name must be a valid string value.",EventDataInvalidType:"Event data must be a valid object hash.",LoggingDisabled:"Event logging is currently disabled.",CookieParseError:"Could not parse cookie",EventEmpty:"Event object is null or undefined, cancelling send",APIRequestEmpty:"APIRequest is null or undefined, cancelling send",NoEventType:"Event type must be specified.",TransactionIdRequired:"Transaction ID is required",TransactionRequired:"A transaction attributes object is required",PromotionIdRequired:"Promotion ID is required",BadAttribute:"Attribute value cannot be object or array",BadKey:"Key value cannot be object or array",BadLogPurchase:"Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions",AudienceAPINotEnabled:"Your workspace is not enabled to retrieve user audiences."},InformationMessages:{CookieSearch:"Searching for cookie",CookieFound:"Cookie found, parsing values",CookieNotFound:"Cookies not found",CookieSet:"Setting cookie",CookieSync:"Performing cookie sync",SendBegin:"Starting to send event",SendIdentityBegin:"Starting to send event to identity server",SendWindowsPhone:"Sending event to Windows Phone container",SendIOS:"Calling iOS path: ",SendAndroid:"Calling Android JS interface method: ",SendHttp:"Sending event to mParticle HTTP service",SendAliasHttp:"Sending alias request to mParticle HTTP service",SendIdentityHttp:"Sending event to mParticle HTTP service",StartingNewSession:"Starting new Session",StartingLogEvent:"Starting to log event",StartingLogOptOut:"Starting to log user opt in/out",StartingEndSession:"Starting to end session",StartingInitialization:"Starting to initialize",StartingLogCommerceEvent:"Starting to log commerce event",StartingAliasRequest:"Starting to Alias MPIDs",LoadingConfig:"Loading configuration options",AbandonLogEvent:"Cannot log event, logging disabled or developer token not set",AbandonAliasUsers:"Cannot Alias Users, logging disabled or developer token not set",AbandonStartSession:"Cannot start session, logging disabled or developer token not set",AbandonEndSession:"Cannot end session, logging disabled or developer token not set",NoSessionToEnd:"Cannot end session, no active session found"},ValidationMessages:{ModifyIdentityRequestUserIdentitiesPresent:"identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again",IdentityRequesetInvalidKey:"There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.",OnUserAliasType:"The onUserAlias value must be a function.",UserIdentities:"The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidKey:"There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidValues:"All user identity values must be strings or null. Request not sent to server. Please fix and try again.",AliasMissingMpid:"Alias Request must contain both a destinationMpid and a sourceMpid",AliasNonUniqueMpid:"Alias Request's destinationMpid and sourceMpid must be unique",AliasMissingTime:"Alias Request must have both a startTime and an endTime",AliasStartBeforeEndTime:"Alias Request's endTime must be later than its startTime"}},NativeSdkPaths:{LogEvent:"logEvent",SetUserTag:"setUserTag",RemoveUserTag:"removeUserTag",SetUserAttribute:"setUserAttribute",RemoveUserAttribute:"removeUserAttribute",SetSessionAttribute:"setSessionAttribute",AddToCart:"addToCart",RemoveFromCart:"removeFromCart",ClearCart:"clearCart",LogOut:"logOut",SetUserAttributeList:"setUserAttributeList",RemoveAllUserAttributes:"removeAllUserAttributes",GetUserAttributesLists:"getUserAttributesLists",GetAllUserAttributes:"getAllUserAttributes",Identify:"identify",Logout:"logout",Login:"login",Modify:"modify",Alias:"aliasUsers",Upload:"upload"},StorageNames:{localStorageName:"mprtcl-api",localStorageNameV3:"mprtcl-v3",cookieName:"mprtcl-api",cookieNameV2:"mprtcl-v2",cookieNameV3:"mprtcl-v3",localStorageNameV4:"mprtcl-v4",localStorageProductsV4:"mprtcl-prodv4",cookieNameV4:"mprtcl-v4",currentStorageName:"mprtcl-v4",currentStorageProductsName:"mprtcl-prodv4"},DefaultConfig:{cookieDomain:null,cookieExpiration:365,logLevel:null,timeout:300,sessionTimeout:30,maxProducts:20,forwarderStatsTimeout:5e3,integrationDelayTimeout:5e3,maxCookieSize:3e3,aliasMaxWindow:90,uploadInterval:0// Maximum milliseconds in between batch uploads, below 500 will mean immediate upload. The server returns this as a string, but we are using it as a number internally
160
160
  },DefaultBaseUrls:{v1SecureServiceUrl:"jssdks.mparticle.com/v1/JS/",v2SecureServiceUrl:"jssdks.mparticle.com/v2/JS/",v3SecureServiceUrl:"jssdks.mparticle.com/v3/JS/",configUrl:"jssdkcdns.mparticle.com/JS/v2/",identityUrl:"identity.mparticle.com/v1/",aliasUrl:"jssdks.mparticle.com/v1/identity/",userAudienceUrl:"nativesdks.mparticle.com/v1/"},Base64CookieKeys:{csm:1,sa:1,ss:1,ua:1,ui:1,csd:1,ia:1,con:1},// https://go.mparticle.com/work/SQDSDKS-6039
161
161
  SDKv2NonMPIDCookieKeys:{gs:1,cu:1,l:1,globalSettings:1,currentUserMPID:1},HTTPCodes:{noHttpCoverage:-1,activeIdentityRequest:-2,activeSession:-3,validationIssue:-4,nativeIdentityRequest:-5,loggingDisabledOrMissingAPIKey:-6,tooManyRequests:429},FeatureFlags:{ReportBatching:"reportBatching",EventBatchingIntervalMillis:"eventBatchingIntervalMillis",OfflineStorage:"offlineStorage",DirectUrlRouting:"directURLRouting",CacheIdentity:"cacheIdentity",AudienceAPI:"audienceAPI"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;
162
162
 
163
- var Messages$9=Constants.Messages,createCookieString=function(a){return replaceCommasWithPipes(replaceQuotesWithApostrophes(a))},revertCookieString=function(a){return replacePipesWithCommas(replaceApostrophesWithQuotes(a))},inArray=function(a,b){var c=0;if(Array.prototype.indexOf)return 0<=a.indexOf(b,0);for(var d=a.length;c<d;c++)if(c in a&&a[c]===b)return !0;return !1},findKeyInObject=function(a,b){if(b&&a)for(var c in a)if(a.hasOwnProperty(c)&&c.toLowerCase()===b.toLowerCase())return c;return null},generateDeprecationMessage=function(a,b){var c=[a,Messages$9.DeprecationMessages.MethodIsDeprecatedPostfix];return b&&(c.push(b),c.push(Messages$9.DeprecationMessages.MethodIsDeprecatedPostfix)),c.join(" ")};function generateHash(a){var b,c=0;if(void 0===a||null===a)return 0;if(a=a.toString().toLowerCase(),Array.prototype.reduce)return a.split("").reduce(function(c,d){return c=(c<<5)-c+d.charCodeAt(0),c&c},0);if(0===a.length)return c;for(var d=0;d<a.length;d++)b=a.charCodeAt(d),c=(c<<5)-c+b,c&=c;return c}var generateRandomValue=function(){var b,c;return window.crypto&&window.crypto.getRandomValues&&(b=window.crypto.getRandomValues(new Uint8Array(1))),b?(c^b[0]%16>>c/4).toString(16):(c^16*Math.random()>>c/4).toString(16)},generateUniqueId=function(b){return void 0===b&&(b=""),b// if the placeholder was passed, return
163
+ var Messages$9=Constants.Messages;var HTTP_SUCCESS=200;var createCookieString=function(a){return replaceCommasWithPipes(replaceQuotesWithApostrophes(a))},revertCookieString=function(a){return replacePipesWithCommas(replaceApostrophesWithQuotes(a))},inArray=function(a,b){var c=0;if(Array.prototype.indexOf)return 0<=a.indexOf(b,0);for(var d=a.length;c<d;c++)if(c in a&&a[c]===b)return !0;return !1},findKeyInObject=function(a,b){if(b&&a)for(var c in a)if(a.hasOwnProperty(c)&&c.toLowerCase()===b.toLowerCase())return c;return null},generateDeprecationMessage=function(a,b){var c=[a,Messages$9.DeprecationMessages.MethodIsDeprecatedPostfix];return b&&(c.push(b),c.push(Messages$9.DeprecationMessages.MethodIsDeprecatedPostfix)),c.join(" ")};function generateHash(a){var b,c=0;if(void 0===a||null===a)return 0;if(a=a.toString().toLowerCase(),Array.prototype.reduce)return a.split("").reduce(function(c,d){return c=(c<<5)-c+d.charCodeAt(0),c&c},0);if(0===a.length)return c;for(var d=0;d<a.length;d++)b=a.charCodeAt(d),c=(c<<5)-c+b,c&=c;return c}var generateRandomValue=function(){var b,c;return window.crypto&&window.crypto.getRandomValues&&(b=window.crypto.getRandomValues(new Uint8Array(1))),b?(c^b[0]%16>>c/4).toString(16):(c^16*Math.random()>>c/4).toString(16)},generateUniqueId=function(b){return void 0===b&&(b=""),b// if the placeholder was passed, return
164
164
  ?generateRandomValue()// if the placeholder was passed, return
165
165
  :// [1e7] -> // 10000000 +
166
166
  // -1e3 -> // -1000 +
@@ -1089,28 +1089,31 @@ Store:a._Store.serverSettings,SDKVersion:Constants.sdkVersion,SessionId:a._Store
1089
1089
 
1090
1090
  function forwardingStatsUploader(a){function b(){var b=a._Forwarders.getForwarderStatsQueue(),c=a._Persistence.forwardingStatsBatches.uploadsTable,d=Date.now();for(var e in b.length&&(c[d]={uploading:!1,data:b},a._Forwarders.setForwarderStatsQueue([])),c)(function(b){if(c.hasOwnProperty(b)&&!1===c[b].uploading){var d=function(){4===e.readyState&&(200===e.status||202===e.status?(a.Logger.verbose("Successfully sent "+e.statusText+" from server"),delete c[b]):"4"===e.status.toString()[0]?429!==e.status&&delete c[b]:c[b].uploading=!1);},e=a._Helpers.createXHR(d),f=c[b].data;c[b].uploading=!0,a._APIClient.sendBatchForwardingStatsToServer(f,e);}})(e);}this.startForwardingStatsTimer=function(){mParticle._forwardingStatsTimer=setInterval(function(){b();},a._Store.SDKConfig.forwarderStatsTimeout);};}
1091
1091
 
1092
- var _a=Constants.IdentityMethods,Identify$1=_a.Identify,Modify$2=_a.Modify,Login$1=_a.Login,Logout$1=_a.Logout;var cacheOrClearIdCache=function(a,b,c,d,e){// when parsing a response that has already been cached, simply return instead of attempting another cache
1092
+ var _a=Constants.IdentityMethods,Identify$1=_a.Identify,Modify$2=_a.Modify,Login$1=_a.Login,Logout$1=_a.Logout,CACHE_HEADER="x-mp-max-age";// https://go.mparticle.com/work/SQDSDKS-6568
1093
+ // Temporary adapter to convert the XMLHttpRequest response to the IIdentityResponse interface
1094
+ var xhrIdentityResponseAdapter=function(a){return a.hasOwnProperty("expireTimestamp")?a:{status:a.status,// Sometimes responseText can be an empty string, such as a 404 response
1095
+ responseText:a.responseText?JSON.parse(a.responseText):{},cacheMaxAge:parseNumber((null===a||void 0===a?void 0:a.getResponseHeader(CACHE_HEADER))||""),expireTimestamp:0}};var cacheOrClearIdCache=function(a,b,c,d,e){// when parsing a response that has already been cached, simply return instead of attempting another cache
1093
1096
  if(!e){// default the expire timestamp to one day in milliseconds unless a header comes back
1094
- var f=new Date().getTime(),g=f+ONE_DAY_IN_SECONDS*MILLIS_IN_ONE_SEC;d.getAllResponseHeaders().includes("x-mp-max-age")&&(g=f+parseNumber(d.getResponseHeader("x-mp-max-age"))*MILLIS_IN_ONE_SEC),a===Login$1||a===Identify$1?cacheIdentityRequest(a,b,g,c,d):a===Modify$2||a===Logout$1?c.purge():void 0;}};var cacheIdentityRequest=function(a,b,c,d,e){var f=d.retrieve()||{},g=concatenateIdentities(a,b),h=generateHash(g),i=JSON.parse(e.responseText),j=i.mpid,k=i.is_logged_in;f[h]={responseText:JSON.stringify({mpid:j,is_logged_in:k}),status:e.status,expireTimestamp:c},d.store(f);};// We need to ensure that identities are concatenated in a deterministic way, so
1097
+ var f=getExpireTimestamp(null===d||void 0===d?void 0:d.cacheMaxAge);a===Login$1||a===Identify$1?cacheIdentityRequest(a,b,f,c,d):a===Modify$2||a===Logout$1?c.purge():void 0;}};var cacheIdentityRequest=function(a,b,c,d,e){var f=e.responseText,g=e.status,h=d.retrieve()||{},i=concatenateIdentities(a,b),j=generateHash(i),k=f.mpid,l=f.is_logged_in;h[j]={responseText:JSON.stringify({mpid:k,is_logged_in:l}),status:g,expireTimestamp:c},d.store(h);};// We need to ensure that identities are concatenated in a deterministic way, so
1095
1098
  // we sort the identities based on their enum.
1096
1099
  // we create an array, set the user identity at the index of the user identity type
1097
1100
  var concatenateIdentities=function(a,b){var c="".concat(a,":").concat("device_application_stamp","=").concat(b.device_application_stamp,";"),d=Object.keys(b).length,e="";// set DAS first since it is not an official identity type
1098
1101
  if(d){var f=[];// create an array where each index is equal to the user identity type
1099
- for(var g in b)if(g==="device_application_stamp")continue;else f[Types.IdentityType.getIdentityType(g)]=b[g];e=f.reduce(function(a,b,c){var d=Types.IdentityType.getIdentityName(c);return "".concat(a).concat(d,"=").concat(b,";")},c);}return e};var hasValidCachedIdentity=function(a,b,c){// There is an edge case where multiple identity calls are taking place
1100
- // before identify fires, so there may not be a cache. See what happens when
1102
+ for(var g in b)if(g==="device_application_stamp")continue;else f[Types.IdentityType.getIdentityType(g)]=b[g];e=f.reduce(function(a,b,c){var d=Types.IdentityType.getIdentityName(c);return "".concat(a).concat(d,"=").concat(b,";")},c);}return e};var hasValidCachedIdentity=function(a,b,c){// There is an edge case where multiple identity calls are taking place
1103
+ // before identify fires, so there may not be a cache. See what happens when
1101
1104
  // the ? in idCache is removed to the following test
1102
- // "queued events contain login mpid instead of identify mpid when calling
1105
+ // "queued events contain login mpid instead of identify mpid when calling
1103
1106
  // login immediately after mParticle initializes"
1104
1107
  var d=null===c||void 0===c?void 0:c.retrieve();// if there is no cache, then there is no valid cached identity
1105
1108
  if(!d)return !1;var e=concatenateIdentities(a,b),f=generateHash(e);// if cache doesn't have the cacheKey, there is no valid cached identity
1106
1109
  if(!d.hasOwnProperty(f))return !1;// If there is a valid cache key, compare the expireTimestamp to the current time.
1107
1110
  // If the current time is greater than the expireTimestamp, it is not a valid
1108
1111
  // cached identity.
1109
- var g=d[f].expireTimestamp;return !(g<new Date().getTime())};var getCachedIdentity=function(a,b,c){var d=concatenateIdentities(a,b),e=generateHash(d),f=c.retrieve(),g=f?f[e]:null;return g};// https://go.mparticle.com/work/SQDSDKS-6079
1112
+ var g=d[f].expireTimestamp;return !(g<new Date().getTime())};var getCachedIdentity=function(a,b,c){var d=concatenateIdentities(a,b),e=generateHash(d),f=c.retrieve(),g=f?f[e]:null;return {responseText:parseIdentityResponse(g.responseText),expireTimestamp:g.expireTimestamp,status:g.status}};// https://go.mparticle.com/work/SQDSDKS-6079
1110
1113
  var createKnownIdentities=function(a,b){var c={};if(isObject(null===a||void 0===a?void 0:a.userIdentities))for(var d in a.userIdentities)c[d]=a.userIdentities[d];return c.device_application_stamp=b,c};var removeExpiredIdentityCacheDates=function(a){var b=a.retrieve()||{},c=new Date().getTime();// Iterate over the cache and remove any key/value pairs that are expired
1111
1114
  for(var d in b)b[d].expireTimestamp<c&&delete b[d];a.store(b);};var tryCacheIdentity=function(a,b,c,d,e,f,g){// https://go.mparticle.com/work/SQDSDKS-6095
1112
1115
  var h=hasValidCachedIdentity(g,a,b);// If Identity is cached, then immediately parse the identity response
1113
- if(h){var i=getCachedIdentity(g,a,b);return c(i,d,e,f,g,a,!0),!0}return !1};
1116
+ if(h){var i=getCachedIdentity(g,a,b);return c(i,d,e,f,g,a,!0),!0}return !1};var getExpireTimestamp=function(a){return void 0===a&&(a=ONE_DAY_IN_SECONDS),new Date().getTime()+a*MILLIS_IN_ONE_SEC},parseIdentityResponse=function(a){return a?JSON.parse(a):{}};
1114
1117
 
1115
1118
  var AudienceManager=/** @class */function(){function a(a,b,c){this.url="",this.logger=c,this.url="https://".concat(a).concat(b,"/audience"),this.userAudienceAPI=window.fetch?new FetchUploader(this.url):new XHRUploader(this.url);}return a.prototype.sendGetUserAudienceRequest=function(a,b){return __awaiter(this,void 0,void 0,function(){var c,d,e,f,g,h;return __generator(this,function(i){switch(i.label){case 0:this.logger.verbose("Fetching user audiences from server"),c={method:"GET",headers:{Accept:"*/*"}},d="".concat(this.url,"?mpid=").concat(a),i.label=1;case 1:return i.trys.push([1,6,,7]),[4/*yield*/,this.userAudienceAPI.upload(c,d)];case 2:return (e=i.sent(),!(200<=e.status&&300>e.status))?[3/*break*/,4]:(this.logger.verbose("User Audiences successfully received"),[4/*yield*/,e.json()]);case 3:f=i.sent(),g={currentAudienceMemberships:null===f||void 0===f?void 0:f.audience_memberships};try{b(g);}catch(a){throw new Error("Error invoking callback on user audience response.")}return [3/*break*/,5];case 4:if(401===e.status)throw new Error("`HTTP error status ${userAudiencePromise.status} while retrieving User Audiences - please verify your API key.`");else if(403===e.status)throw new Error("`HTTP error status ${userAudiencePromise.status} while retrieving User Audiences - please verify your workspace is enabled for audiences.`");else// In case there is an HTTP error we did not anticipate.
1116
1119
  throw new Error("Uncaught HTTP Error ".concat(e.status,"."));case 5:return [3/*break*/,7];case 6:return h=i.sent(),this.logger.error("Error retrieving audiences. ".concat(h)),[3/*break*/,7];case 7:return [2/*return*/]}})})},a}();
@@ -1288,9 +1291,9 @@ return t._Helpers.getFeatureFlag(FeatureFlags$1.AudienceAPI)?void(null===s.audie
1288
1291
  * @method getCartProducts
1289
1292
  * @return {Array} array of cart products
1290
1293
  * @deprecated
1291
- */getCartProducts:function getCartProducts(){return t.Logger.warning("Deprecated function Identity.getCurrentUser().getCart().getCartProducts() will be removed in future releases"),t._Persistence.getCartProducts(e)}}},this.parseIdentityResponse=function(r,i,a,d,o,g,l){var u,p,y,c=t.Identity.getUser(i),I=c?c.getMPID():null,_=c?c.getUserIdentities().userIdentities:{},v={};t._Store.identityCallInFlight=!1;try{var m,S;if(t.Logger.verbose("Parsing \""+o+"\" identity response from server"),p=r.responseText?JSON.parse(r.responseText):null,t._Store.isLoggedIn=(null===(m=p)||void 0===m?void 0:m.is_logged_in)||!1,hasMPIDChanged(c,p)&&(t._Store.mpid=p.mpid,c&&t._Persistence.setLastSeenTime(i),u=!t._Persistence.getFirstSeenTime(p.mpid),t._Persistence.setFirstSeenTime(p.mpid)),200===r.status){s(CacheIdentity)&&cacheOrClearIdCache(o,g,n.idCache,r,l);var b=n.IdentityAPI.getUser(p.mpid),A=b?b.getUserIdentities().userIdentities:{};o===Modify$1?(v=t._Identity.IdentityRequest.combineUserIdentities(_,d.userIdentities),t._Store.setUserIdentities(i,v)):(o===Identify&&c&&p.mpid===I&&t._Persistence.setFirstSeenTime(p.mpid),t._Store.addMpidToSessionHistory(p.mpid,i),t._CookieSyncManager.attemptCookieSync(i,p.mpid,u),t._Persistence.swapCurrentUser(i,p.mpid,t._Store.currentSessionMPIDs),d&&!isEmpty(d.userIdentities)&&(v=n.IdentityRequest.combineUserIdentities(A,d.userIdentities)),t._Store.setUserIdentities(p.mpid,v),t._Persistence.update(),t._Store.syncPersistenceData(),t._Persistence.findPrevCookiesBasedOnUI(d),t._Store.context=p.context||t._Store.context),y=t.Identity.getCurrentUser(),tryOnUserAlias(c,y,d,t.Logger);var P=t._Persistence.getPersistence();y&&(t._Persistence.storeDataInMemory(P,y.getMPID()),n.reinitForwardersOnUserChange(c,y),n.setForwarderCallbacks(y,o));var U=getNewIdentitiesByName(v),C=o===Modify$1?_:A;// https://go.mparticle.com/work/SQDSDKS-6501
1292
- n.sendUserIdentityChangeEvent(U,o,p.mpid,C);}if(a){var k=0===r.status?HTTPCodes$2.noHttpCoverage:r.status;t._Helpers.invokeCallback(a,k,p||null,y);}else p&&!isEmpty(p.errors)&&// https://go.mparticle.com/work/SQDSDKS-6500
1293
- t.Logger.error("Received HTTP response code of "+r.status+" - "+p.errors[0].message);t.Logger.verbose("Successfully parsed Identity Response"),null===(S=t._APIClient)||void 0===S||S.processQueuedEvents();}catch(s){a&&t._Helpers.invokeCallback(a,r.status,p||null),t.Logger.error("Error parsing JSON response from Identity server: "+s);}},this.sendUserIdentityChangeEvent=function(e,r,s,i){if(s||r===Modify$1)// https://go.mparticle.com/work/SQDSDKS-6501
1294
+ */getCartProducts:function getCartProducts(){return t.Logger.warning("Deprecated function Identity.getCurrentUser().getCart().getCartProducts() will be removed in future releases"),t._Persistence.getCartProducts(e)}}},this.parseIdentityResponse=function(r,i,a,d,o,g,l){var u,p,y,c=t.Identity.getUser(i),I=c?c.getMPID():null,_=c?c.getUserIdentities().userIdentities:{},v={};t._Store.identityCallInFlight=!1;try{var m,S,b;if(t.Logger.verbose("Parsing \""+o+"\" identity response from server"),p=null!==(m=r.responseText)&&void 0!==m?m:null,t._Store.isLoggedIn=(null===(S=p)||void 0===S?void 0:S.is_logged_in)||!1,hasMPIDChanged(c,p)&&(t._Store.mpid=p.mpid,c&&t._Persistence.setLastSeenTime(i),u=!t._Persistence.getFirstSeenTime(p.mpid),t._Persistence.setFirstSeenTime(p.mpid)),r.status===HTTP_SUCCESS){if(s(CacheIdentity)){var A=xhrIdentityResponseAdapter(r);cacheOrClearIdCache(o,g,n.idCache,A,l);}var P=n.IdentityAPI.getUser(p.mpid),U=P?P.getUserIdentities().userIdentities:{};o===Modify$1?(v=t._Identity.IdentityRequest.combineUserIdentities(_,d.userIdentities),t._Store.setUserIdentities(i,v)):(o===Identify&&c&&p.mpid===I&&t._Persistence.setFirstSeenTime(p.mpid),t._Store.addMpidToSessionHistory(p.mpid,i),t._CookieSyncManager.attemptCookieSync(i,p.mpid,u),t._Persistence.swapCurrentUser(i,p.mpid,t._Store.currentSessionMPIDs),d&&!isEmpty(d.userIdentities)&&(v=n.IdentityRequest.combineUserIdentities(U,d.userIdentities)),t._Store.setUserIdentities(p.mpid,v),t._Persistence.update(),t._Store.syncPersistenceData(),t._Persistence.findPrevCookiesBasedOnUI(d),t._Store.context=p.context||t._Store.context),y=t.Identity.getCurrentUser(),tryOnUserAlias(c,y,d,t.Logger);var C=t._Persistence.getPersistence();y&&(t._Persistence.storeDataInMemory(C,y.getMPID()),n.reinitForwardersOnUserChange(c,y),n.setForwarderCallbacks(y,o));var k=getNewIdentitiesByName(v),f=o===Modify$1?_:U;// https://go.mparticle.com/work/SQDSDKS-6501
1295
+ n.sendUserIdentityChangeEvent(k,o,p.mpid,f);}if(a){var T=0===r.status?HTTPCodes$2.noHttpCoverage:r.status;t._Helpers.invokeCallback(a,T,p||null,y);}else p&&!isEmpty(p.errors)&&// https://go.mparticle.com/work/SQDSDKS-6500
1296
+ t.Logger.error("Received HTTP response code of "+r.status+" - "+p.errors[0].message);t.Logger.verbose("Successfully parsed Identity Response"),null===(b=t._APIClient)||void 0===b||b.processQueuedEvents();}catch(s){a&&t._Helpers.invokeCallback(a,r.status,p||null),t.Logger.error("Error parsing JSON response from Identity server: "+s);}},this.sendUserIdentityChangeEvent=function(e,r,s,i){if(s||r===Modify$1)// https://go.mparticle.com/work/SQDSDKS-6501
1294
1297
  {// https://go.mparticle.com/work/SQDSDKS-6354
1295
1298
  var a=this.IdentityAPI.getUser(s);for(var d in e)// Verifies a change actually happened
1296
1299
  if(i[d]!==e[d]){var o,g=!i[d],l=n.createUserIdentityChange(d,e[d],i[d],g,a);// If a new identity type was introduced when the identity changes
@@ -1391,7 +1394,8 @@ var buildUrl=function(a,b,c,d){var e=d?"1":"0",f=["env=".concat(e)],g=c||{},h=g.
1391
1394
  return [2/*return*/,b]}})})};}
1392
1395
 
1393
1396
  var HTTPCodes$1=Constants.HTTPCodes,Messages$1=Constants.Messages,Modify=Constants.IdentityMethods.Modify;function IdentityAPIClient(a){this.sendAliasRequest=function(b,c){var d,e=function xhrCallback(){if(4===d.readyState){//only parse error messages from failing requests
1394
- if(a.Logger.verbose("Received "+d.statusText+" from server"),200!==d.status&&202!==d.status&&d.responseText){var b=JSON.parse(d.responseText);if(b.hasOwnProperty("message")){var e=b.message;return void a._Helpers.invokeAliasCallback(c,d.status,e)}}a._Helpers.invokeAliasCallback(c,d.status);}};if(a.Logger.verbose(Messages$1.InformationMessages.SendAliasHttp),d=a._Helpers.createXHR(e),d)try{d.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.aliasUrl,a._Store.devToken)+"/Alias"),d.send(JSON.stringify(b));}catch(b){a._Helpers.invokeAliasCallback(c,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending alias request to mParticle servers. "+b);}},this.sendIdentityRequest=function(b,c,d,e,f,g,h){var i,j,k=function xhrCallback(){4===i.readyState&&(a.Logger.verbose("Received "+i.statusText+" from server"),f(i,j,d,e,c,h,!1));};if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityBegin),!b)return void a.Logger.error(Messages$1.ErrorMessages.APIRequestEmpty);if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityHttp),i=a._Helpers.createXHR(k),i)try{a._Store.identityCallInFlight?a._Helpers.invokeCallback(d,HTTPCodes$1.activeIdentityRequest,"There is currently an Identity request processing. Please wait for this to return before requesting again"):(j=g||null,c===Modify?i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+g+"/"+c):i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+c),i.setRequestHeader("Content-Type","application/json"),i.setRequestHeader("x-mp-key",a._Store.devToken),a._Store.identityCallInFlight=!0,i.send(JSON.stringify(b)));}catch(b){a._Store.identityCallInFlight=!1,a._Helpers.invokeCallback(d,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending identity request to servers with status code "+i.status+" - "+b);}};}
1397
+ if(a.Logger.verbose("Received "+d.statusText+" from server"),200!==d.status&&202!==d.status&&d.responseText){var b=JSON.parse(d.responseText);if(b.hasOwnProperty("message")){var e=b.message;return void a._Helpers.invokeAliasCallback(c,d.status,e)}}a._Helpers.invokeAliasCallback(c,d.status);}};if(a.Logger.verbose(Messages$1.InformationMessages.SendAliasHttp),d=a._Helpers.createXHR(e),d)try{d.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.aliasUrl,a._Store.devToken)+"/Alias"),d.send(JSON.stringify(b));}catch(b){a._Helpers.invokeAliasCallback(c,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending alias request to mParticle servers. "+b);}},this.sendIdentityRequest=function(b,c,d,e,f,g,h){var i,j,k=function xhrCallback(){if(4===i.readyState){a.Logger.verbose("Received "+i.statusText+" from server");// https://go.mparticle.com/work/SQDSDKS-6565
1398
+ var b=xhrIdentityResponseAdapter(i);f(b,j,d,e,c,h,!1);}};if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityBegin),!b)return void a.Logger.error(Messages$1.ErrorMessages.APIRequestEmpty);if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityHttp),i=a._Helpers.createXHR(k),i)try{a._Store.identityCallInFlight?a._Helpers.invokeCallback(d,HTTPCodes$1.activeIdentityRequest,"There is currently an Identity request processing. Please wait for this to return before requesting again"):(j=g||null,c===Modify?i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+g+"/"+c):i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+c),i.setRequestHeader("Content-Type","application/json"),i.setRequestHeader("x-mp-key",a._Store.devToken),a._Store.identityCallInFlight=!0,i.send(JSON.stringify(b)));}catch(b){a._Store.identityCallInFlight=!1,a._Helpers.invokeCallback(d,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending identity request to servers with status code "+i.status+" - "+b);}};}
1395
1399
 
1396
1400
  var Messages=Constants.Messages,HTTPCodes=Constants.HTTPCodes,FeatureFlags=Constants.FeatureFlags,ReportBatching=FeatureFlags.ReportBatching,StartingInitialization=Messages.InformationMessages.StartingInitialization;/**
1397
1401
  * <p>All of the following methods can be called on the primary mParticle class. In version 2.10.0, we introduced <a href="https://docs.mparticle.com/developers/sdk/web/multiple-instances/">multiple instances</a>. If you are using multiple instances (self hosted environments only), you should call these methods on each instance.</p>
@@ -154,13 +154,13 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
154
154
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
155
155
  };
156
156
 
157
- var version = "2.28.1";
157
+ var version = "2.28.2";
158
158
 
159
159
  var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodIsDeprecatedPostfix:"is a deprecated method and will be removed in future releases",AlternativeMethodPrefix:"Please use the alternate method:"},ErrorMessages:{NoToken:"A token must be specified.",EventNameInvalidType:"Event name must be a valid string value.",EventDataInvalidType:"Event data must be a valid object hash.",LoggingDisabled:"Event logging is currently disabled.",CookieParseError:"Could not parse cookie",EventEmpty:"Event object is null or undefined, cancelling send",APIRequestEmpty:"APIRequest is null or undefined, cancelling send",NoEventType:"Event type must be specified.",TransactionIdRequired:"Transaction ID is required",TransactionRequired:"A transaction attributes object is required",PromotionIdRequired:"Promotion ID is required",BadAttribute:"Attribute value cannot be object or array",BadKey:"Key value cannot be object or array",BadLogPurchase:"Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions",AudienceAPINotEnabled:"Your workspace is not enabled to retrieve user audiences."},InformationMessages:{CookieSearch:"Searching for cookie",CookieFound:"Cookie found, parsing values",CookieNotFound:"Cookies not found",CookieSet:"Setting cookie",CookieSync:"Performing cookie sync",SendBegin:"Starting to send event",SendIdentityBegin:"Starting to send event to identity server",SendWindowsPhone:"Sending event to Windows Phone container",SendIOS:"Calling iOS path: ",SendAndroid:"Calling Android JS interface method: ",SendHttp:"Sending event to mParticle HTTP service",SendAliasHttp:"Sending alias request to mParticle HTTP service",SendIdentityHttp:"Sending event to mParticle HTTP service",StartingNewSession:"Starting new Session",StartingLogEvent:"Starting to log event",StartingLogOptOut:"Starting to log user opt in/out",StartingEndSession:"Starting to end session",StartingInitialization:"Starting to initialize",StartingLogCommerceEvent:"Starting to log commerce event",StartingAliasRequest:"Starting to Alias MPIDs",LoadingConfig:"Loading configuration options",AbandonLogEvent:"Cannot log event, logging disabled or developer token not set",AbandonAliasUsers:"Cannot Alias Users, logging disabled or developer token not set",AbandonStartSession:"Cannot start session, logging disabled or developer token not set",AbandonEndSession:"Cannot end session, logging disabled or developer token not set",NoSessionToEnd:"Cannot end session, no active session found"},ValidationMessages:{ModifyIdentityRequestUserIdentitiesPresent:"identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again",IdentityRequesetInvalidKey:"There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.",OnUserAliasType:"The onUserAlias value must be a function.",UserIdentities:"The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidKey:"There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidValues:"All user identity values must be strings or null. Request not sent to server. Please fix and try again.",AliasMissingMpid:"Alias Request must contain both a destinationMpid and a sourceMpid",AliasNonUniqueMpid:"Alias Request's destinationMpid and sourceMpid must be unique",AliasMissingTime:"Alias Request must have both a startTime and an endTime",AliasStartBeforeEndTime:"Alias Request's endTime must be later than its startTime"}},NativeSdkPaths:{LogEvent:"logEvent",SetUserTag:"setUserTag",RemoveUserTag:"removeUserTag",SetUserAttribute:"setUserAttribute",RemoveUserAttribute:"removeUserAttribute",SetSessionAttribute:"setSessionAttribute",AddToCart:"addToCart",RemoveFromCart:"removeFromCart",ClearCart:"clearCart",LogOut:"logOut",SetUserAttributeList:"setUserAttributeList",RemoveAllUserAttributes:"removeAllUserAttributes",GetUserAttributesLists:"getUserAttributesLists",GetAllUserAttributes:"getAllUserAttributes",Identify:"identify",Logout:"logout",Login:"login",Modify:"modify",Alias:"aliasUsers",Upload:"upload"},StorageNames:{localStorageName:"mprtcl-api",localStorageNameV3:"mprtcl-v3",cookieName:"mprtcl-api",cookieNameV2:"mprtcl-v2",cookieNameV3:"mprtcl-v3",localStorageNameV4:"mprtcl-v4",localStorageProductsV4:"mprtcl-prodv4",cookieNameV4:"mprtcl-v4",currentStorageName:"mprtcl-v4",currentStorageProductsName:"mprtcl-prodv4"},DefaultConfig:{cookieDomain:null,cookieExpiration:365,logLevel:null,timeout:300,sessionTimeout:30,maxProducts:20,forwarderStatsTimeout:5e3,integrationDelayTimeout:5e3,maxCookieSize:3e3,aliasMaxWindow:90,uploadInterval:0// Maximum milliseconds in between batch uploads, below 500 will mean immediate upload. The server returns this as a string, but we are using it as a number internally
160
160
  },DefaultBaseUrls:{v1SecureServiceUrl:"jssdks.mparticle.com/v1/JS/",v2SecureServiceUrl:"jssdks.mparticle.com/v2/JS/",v3SecureServiceUrl:"jssdks.mparticle.com/v3/JS/",configUrl:"jssdkcdns.mparticle.com/JS/v2/",identityUrl:"identity.mparticle.com/v1/",aliasUrl:"jssdks.mparticle.com/v1/identity/",userAudienceUrl:"nativesdks.mparticle.com/v1/"},Base64CookieKeys:{csm:1,sa:1,ss:1,ua:1,ui:1,csd:1,ia:1,con:1},// https://go.mparticle.com/work/SQDSDKS-6039
161
161
  SDKv2NonMPIDCookieKeys:{gs:1,cu:1,l:1,globalSettings:1,currentUserMPID:1},HTTPCodes:{noHttpCoverage:-1,activeIdentityRequest:-2,activeSession:-3,validationIssue:-4,nativeIdentityRequest:-5,loggingDisabledOrMissingAPIKey:-6,tooManyRequests:429},FeatureFlags:{ReportBatching:"reportBatching",EventBatchingIntervalMillis:"eventBatchingIntervalMillis",OfflineStorage:"offlineStorage",DirectUrlRouting:"directURLRouting",CacheIdentity:"cacheIdentity",AudienceAPI:"audienceAPI"},DefaultInstance:"default_instance",CCPAPurpose:"data_sale_opt_out",IdentityMethods:{Modify:"modify",Logout:"logout",Login:"login",Identify:"identify"}};var ONE_DAY_IN_SECONDS=86400;var MILLIS_IN_ONE_SEC=1e3;
162
162
 
163
- var Messages$9=Constants.Messages,createCookieString=function(a){return replaceCommasWithPipes(replaceQuotesWithApostrophes(a))},revertCookieString=function(a){return replacePipesWithCommas(replaceApostrophesWithQuotes(a))},inArray=function(a,b){var c=0;if(Array.prototype.indexOf)return 0<=a.indexOf(b,0);for(var d=a.length;c<d;c++)if(c in a&&a[c]===b)return !0;return !1},findKeyInObject=function(a,b){if(b&&a)for(var c in a)if(a.hasOwnProperty(c)&&c.toLowerCase()===b.toLowerCase())return c;return null},generateDeprecationMessage=function(a,b){var c=[a,Messages$9.DeprecationMessages.MethodIsDeprecatedPostfix];return b&&(c.push(b),c.push(Messages$9.DeprecationMessages.MethodIsDeprecatedPostfix)),c.join(" ")};function generateHash(a){var b,c=0;if(void 0===a||null===a)return 0;if(a=a.toString().toLowerCase(),Array.prototype.reduce)return a.split("").reduce(function(c,d){return c=(c<<5)-c+d.charCodeAt(0),c&c},0);if(0===a.length)return c;for(var d=0;d<a.length;d++)b=a.charCodeAt(d),c=(c<<5)-c+b,c&=c;return c}var generateRandomValue=function(){var b,c;return window.crypto&&window.crypto.getRandomValues&&(b=window.crypto.getRandomValues(new Uint8Array(1))),b?(c^b[0]%16>>c/4).toString(16):(c^16*Math.random()>>c/4).toString(16)},generateUniqueId=function(b){return void 0===b&&(b=""),b// if the placeholder was passed, return
163
+ var Messages$9=Constants.Messages;var HTTP_SUCCESS=200;var createCookieString=function(a){return replaceCommasWithPipes(replaceQuotesWithApostrophes(a))},revertCookieString=function(a){return replacePipesWithCommas(replaceApostrophesWithQuotes(a))},inArray=function(a,b){var c=0;if(Array.prototype.indexOf)return 0<=a.indexOf(b,0);for(var d=a.length;c<d;c++)if(c in a&&a[c]===b)return !0;return !1},findKeyInObject=function(a,b){if(b&&a)for(var c in a)if(a.hasOwnProperty(c)&&c.toLowerCase()===b.toLowerCase())return c;return null},generateDeprecationMessage=function(a,b){var c=[a,Messages$9.DeprecationMessages.MethodIsDeprecatedPostfix];return b&&(c.push(b),c.push(Messages$9.DeprecationMessages.MethodIsDeprecatedPostfix)),c.join(" ")};function generateHash(a){var b,c=0;if(void 0===a||null===a)return 0;if(a=a.toString().toLowerCase(),Array.prototype.reduce)return a.split("").reduce(function(c,d){return c=(c<<5)-c+d.charCodeAt(0),c&c},0);if(0===a.length)return c;for(var d=0;d<a.length;d++)b=a.charCodeAt(d),c=(c<<5)-c+b,c&=c;return c}var generateRandomValue=function(){var b,c;return window.crypto&&window.crypto.getRandomValues&&(b=window.crypto.getRandomValues(new Uint8Array(1))),b?(c^b[0]%16>>c/4).toString(16):(c^16*Math.random()>>c/4).toString(16)},generateUniqueId=function(b){return void 0===b&&(b=""),b// if the placeholder was passed, return
164
164
  ?generateRandomValue()// if the placeholder was passed, return
165
165
  :// [1e7] -> // 10000000 +
166
166
  // -1e3 -> // -1000 +
@@ -1089,28 +1089,31 @@ Store:a._Store.serverSettings,SDKVersion:Constants.sdkVersion,SessionId:a._Store
1089
1089
 
1090
1090
  function forwardingStatsUploader(a){function b(){var b=a._Forwarders.getForwarderStatsQueue(),c=a._Persistence.forwardingStatsBatches.uploadsTable,d=Date.now();for(var e in b.length&&(c[d]={uploading:!1,data:b},a._Forwarders.setForwarderStatsQueue([])),c)(function(b){if(c.hasOwnProperty(b)&&!1===c[b].uploading){var d=function(){4===e.readyState&&(200===e.status||202===e.status?(a.Logger.verbose("Successfully sent "+e.statusText+" from server"),delete c[b]):"4"===e.status.toString()[0]?429!==e.status&&delete c[b]:c[b].uploading=!1);},e=a._Helpers.createXHR(d),f=c[b].data;c[b].uploading=!0,a._APIClient.sendBatchForwardingStatsToServer(f,e);}})(e);}this.startForwardingStatsTimer=function(){mParticle._forwardingStatsTimer=setInterval(function(){b();},a._Store.SDKConfig.forwarderStatsTimeout);};}
1091
1091
 
1092
- var _a=Constants.IdentityMethods,Identify$1=_a.Identify,Modify$2=_a.Modify,Login$1=_a.Login,Logout$1=_a.Logout;var cacheOrClearIdCache=function(a,b,c,d,e){// when parsing a response that has already been cached, simply return instead of attempting another cache
1092
+ var _a=Constants.IdentityMethods,Identify$1=_a.Identify,Modify$2=_a.Modify,Login$1=_a.Login,Logout$1=_a.Logout,CACHE_HEADER="x-mp-max-age";// https://go.mparticle.com/work/SQDSDKS-6568
1093
+ // Temporary adapter to convert the XMLHttpRequest response to the IIdentityResponse interface
1094
+ var xhrIdentityResponseAdapter=function(a){return a.hasOwnProperty("expireTimestamp")?a:{status:a.status,// Sometimes responseText can be an empty string, such as a 404 response
1095
+ responseText:a.responseText?JSON.parse(a.responseText):{},cacheMaxAge:parseNumber((null===a||void 0===a?void 0:a.getResponseHeader(CACHE_HEADER))||""),expireTimestamp:0}};var cacheOrClearIdCache=function(a,b,c,d,e){// when parsing a response that has already been cached, simply return instead of attempting another cache
1093
1096
  if(!e){// default the expire timestamp to one day in milliseconds unless a header comes back
1094
- var f=new Date().getTime(),g=f+ONE_DAY_IN_SECONDS*MILLIS_IN_ONE_SEC;d.getAllResponseHeaders().includes("x-mp-max-age")&&(g=f+parseNumber(d.getResponseHeader("x-mp-max-age"))*MILLIS_IN_ONE_SEC),a===Login$1||a===Identify$1?cacheIdentityRequest(a,b,g,c,d):a===Modify$2||a===Logout$1?c.purge():void 0;}};var cacheIdentityRequest=function(a,b,c,d,e){var f=d.retrieve()||{},g=concatenateIdentities(a,b),h=generateHash(g),i=JSON.parse(e.responseText),j=i.mpid,k=i.is_logged_in;f[h]={responseText:JSON.stringify({mpid:j,is_logged_in:k}),status:e.status,expireTimestamp:c},d.store(f);};// We need to ensure that identities are concatenated in a deterministic way, so
1097
+ var f=getExpireTimestamp(null===d||void 0===d?void 0:d.cacheMaxAge);a===Login$1||a===Identify$1?cacheIdentityRequest(a,b,f,c,d):a===Modify$2||a===Logout$1?c.purge():void 0;}};var cacheIdentityRequest=function(a,b,c,d,e){var f=e.responseText,g=e.status,h=d.retrieve()||{},i=concatenateIdentities(a,b),j=generateHash(i),k=f.mpid,l=f.is_logged_in;h[j]={responseText:JSON.stringify({mpid:k,is_logged_in:l}),status:g,expireTimestamp:c},d.store(h);};// We need to ensure that identities are concatenated in a deterministic way, so
1095
1098
  // we sort the identities based on their enum.
1096
1099
  // we create an array, set the user identity at the index of the user identity type
1097
1100
  var concatenateIdentities=function(a,b){var c="".concat(a,":").concat("device_application_stamp","=").concat(b.device_application_stamp,";"),d=Object.keys(b).length,e="";// set DAS first since it is not an official identity type
1098
1101
  if(d){var f=[];// create an array where each index is equal to the user identity type
1099
- for(var g in b)if(g==="device_application_stamp")continue;else f[Types.IdentityType.getIdentityType(g)]=b[g];e=f.reduce(function(a,b,c){var d=Types.IdentityType.getIdentityName(c);return "".concat(a).concat(d,"=").concat(b,";")},c);}return e};var hasValidCachedIdentity=function(a,b,c){// There is an edge case where multiple identity calls are taking place
1100
- // before identify fires, so there may not be a cache. See what happens when
1102
+ for(var g in b)if(g==="device_application_stamp")continue;else f[Types.IdentityType.getIdentityType(g)]=b[g];e=f.reduce(function(a,b,c){var d=Types.IdentityType.getIdentityName(c);return "".concat(a).concat(d,"=").concat(b,";")},c);}return e};var hasValidCachedIdentity=function(a,b,c){// There is an edge case where multiple identity calls are taking place
1103
+ // before identify fires, so there may not be a cache. See what happens when
1101
1104
  // the ? in idCache is removed to the following test
1102
- // "queued events contain login mpid instead of identify mpid when calling
1105
+ // "queued events contain login mpid instead of identify mpid when calling
1103
1106
  // login immediately after mParticle initializes"
1104
1107
  var d=null===c||void 0===c?void 0:c.retrieve();// if there is no cache, then there is no valid cached identity
1105
1108
  if(!d)return !1;var e=concatenateIdentities(a,b),f=generateHash(e);// if cache doesn't have the cacheKey, there is no valid cached identity
1106
1109
  if(!d.hasOwnProperty(f))return !1;// If there is a valid cache key, compare the expireTimestamp to the current time.
1107
1110
  // If the current time is greater than the expireTimestamp, it is not a valid
1108
1111
  // cached identity.
1109
- var g=d[f].expireTimestamp;return !(g<new Date().getTime())};var getCachedIdentity=function(a,b,c){var d=concatenateIdentities(a,b),e=generateHash(d),f=c.retrieve(),g=f?f[e]:null;return g};// https://go.mparticle.com/work/SQDSDKS-6079
1112
+ var g=d[f].expireTimestamp;return !(g<new Date().getTime())};var getCachedIdentity=function(a,b,c){var d=concatenateIdentities(a,b),e=generateHash(d),f=c.retrieve(),g=f?f[e]:null;return {responseText:parseIdentityResponse(g.responseText),expireTimestamp:g.expireTimestamp,status:g.status}};// https://go.mparticle.com/work/SQDSDKS-6079
1110
1113
  var createKnownIdentities=function(a,b){var c={};if(isObject(null===a||void 0===a?void 0:a.userIdentities))for(var d in a.userIdentities)c[d]=a.userIdentities[d];return c.device_application_stamp=b,c};var removeExpiredIdentityCacheDates=function(a){var b=a.retrieve()||{},c=new Date().getTime();// Iterate over the cache and remove any key/value pairs that are expired
1111
1114
  for(var d in b)b[d].expireTimestamp<c&&delete b[d];a.store(b);};var tryCacheIdentity=function(a,b,c,d,e,f,g){// https://go.mparticle.com/work/SQDSDKS-6095
1112
1115
  var h=hasValidCachedIdentity(g,a,b);// If Identity is cached, then immediately parse the identity response
1113
- if(h){var i=getCachedIdentity(g,a,b);return c(i,d,e,f,g,a,!0),!0}return !1};
1116
+ if(h){var i=getCachedIdentity(g,a,b);return c(i,d,e,f,g,a,!0),!0}return !1};var getExpireTimestamp=function(a){return void 0===a&&(a=ONE_DAY_IN_SECONDS),new Date().getTime()+a*MILLIS_IN_ONE_SEC},parseIdentityResponse=function(a){return a?JSON.parse(a):{}};
1114
1117
 
1115
1118
  var AudienceManager=/** @class */function(){function a(a,b,c){this.url="",this.logger=c,this.url="https://".concat(a).concat(b,"/audience"),this.userAudienceAPI=window.fetch?new FetchUploader(this.url):new XHRUploader(this.url);}return a.prototype.sendGetUserAudienceRequest=function(a,b){return __awaiter(this,void 0,void 0,function(){var c,d,e,f,g,h;return __generator(this,function(i){switch(i.label){case 0:this.logger.verbose("Fetching user audiences from server"),c={method:"GET",headers:{Accept:"*/*"}},d="".concat(this.url,"?mpid=").concat(a),i.label=1;case 1:return i.trys.push([1,6,,7]),[4/*yield*/,this.userAudienceAPI.upload(c,d)];case 2:return (e=i.sent(),!(200<=e.status&&300>e.status))?[3/*break*/,4]:(this.logger.verbose("User Audiences successfully received"),[4/*yield*/,e.json()]);case 3:f=i.sent(),g={currentAudienceMemberships:null===f||void 0===f?void 0:f.audience_memberships};try{b(g);}catch(a){throw new Error("Error invoking callback on user audience response.")}return [3/*break*/,5];case 4:if(401===e.status)throw new Error("`HTTP error status ${userAudiencePromise.status} while retrieving User Audiences - please verify your API key.`");else if(403===e.status)throw new Error("`HTTP error status ${userAudiencePromise.status} while retrieving User Audiences - please verify your workspace is enabled for audiences.`");else// In case there is an HTTP error we did not anticipate.
1116
1119
  throw new Error("Uncaught HTTP Error ".concat(e.status,"."));case 5:return [3/*break*/,7];case 6:return h=i.sent(),this.logger.error("Error retrieving audiences. ".concat(h)),[3/*break*/,7];case 7:return [2/*return*/]}})})},a}();
@@ -1288,9 +1291,9 @@ return t._Helpers.getFeatureFlag(FeatureFlags$1.AudienceAPI)?void(null===s.audie
1288
1291
  * @method getCartProducts
1289
1292
  * @return {Array} array of cart products
1290
1293
  * @deprecated
1291
- */getCartProducts:function getCartProducts(){return t.Logger.warning("Deprecated function Identity.getCurrentUser().getCart().getCartProducts() will be removed in future releases"),t._Persistence.getCartProducts(e)}}},this.parseIdentityResponse=function(r,i,a,d,o,g,l){var u,p,y,c=t.Identity.getUser(i),I=c?c.getMPID():null,_=c?c.getUserIdentities().userIdentities:{},v={};t._Store.identityCallInFlight=!1;try{var m,S;if(t.Logger.verbose("Parsing \""+o+"\" identity response from server"),p=r.responseText?JSON.parse(r.responseText):null,t._Store.isLoggedIn=(null===(m=p)||void 0===m?void 0:m.is_logged_in)||!1,hasMPIDChanged(c,p)&&(t._Store.mpid=p.mpid,c&&t._Persistence.setLastSeenTime(i),u=!t._Persistence.getFirstSeenTime(p.mpid),t._Persistence.setFirstSeenTime(p.mpid)),200===r.status){s(CacheIdentity)&&cacheOrClearIdCache(o,g,n.idCache,r,l);var b=n.IdentityAPI.getUser(p.mpid),A=b?b.getUserIdentities().userIdentities:{};o===Modify$1?(v=t._Identity.IdentityRequest.combineUserIdentities(_,d.userIdentities),t._Store.setUserIdentities(i,v)):(o===Identify&&c&&p.mpid===I&&t._Persistence.setFirstSeenTime(p.mpid),t._Store.addMpidToSessionHistory(p.mpid,i),t._CookieSyncManager.attemptCookieSync(i,p.mpid,u),t._Persistence.swapCurrentUser(i,p.mpid,t._Store.currentSessionMPIDs),d&&!isEmpty(d.userIdentities)&&(v=n.IdentityRequest.combineUserIdentities(A,d.userIdentities)),t._Store.setUserIdentities(p.mpid,v),t._Persistence.update(),t._Store.syncPersistenceData(),t._Persistence.findPrevCookiesBasedOnUI(d),t._Store.context=p.context||t._Store.context),y=t.Identity.getCurrentUser(),tryOnUserAlias(c,y,d,t.Logger);var P=t._Persistence.getPersistence();y&&(t._Persistence.storeDataInMemory(P,y.getMPID()),n.reinitForwardersOnUserChange(c,y),n.setForwarderCallbacks(y,o));var U=getNewIdentitiesByName(v),C=o===Modify$1?_:A;// https://go.mparticle.com/work/SQDSDKS-6501
1292
- n.sendUserIdentityChangeEvent(U,o,p.mpid,C);}if(a){var k=0===r.status?HTTPCodes$2.noHttpCoverage:r.status;t._Helpers.invokeCallback(a,k,p||null,y);}else p&&!isEmpty(p.errors)&&// https://go.mparticle.com/work/SQDSDKS-6500
1293
- t.Logger.error("Received HTTP response code of "+r.status+" - "+p.errors[0].message);t.Logger.verbose("Successfully parsed Identity Response"),null===(S=t._APIClient)||void 0===S||S.processQueuedEvents();}catch(s){a&&t._Helpers.invokeCallback(a,r.status,p||null),t.Logger.error("Error parsing JSON response from Identity server: "+s);}},this.sendUserIdentityChangeEvent=function(e,r,s,i){if(s||r===Modify$1)// https://go.mparticle.com/work/SQDSDKS-6501
1294
+ */getCartProducts:function getCartProducts(){return t.Logger.warning("Deprecated function Identity.getCurrentUser().getCart().getCartProducts() will be removed in future releases"),t._Persistence.getCartProducts(e)}}},this.parseIdentityResponse=function(r,i,a,d,o,g,l){var u,p,y,c=t.Identity.getUser(i),I=c?c.getMPID():null,_=c?c.getUserIdentities().userIdentities:{},v={};t._Store.identityCallInFlight=!1;try{var m,S,b;if(t.Logger.verbose("Parsing \""+o+"\" identity response from server"),p=null!==(m=r.responseText)&&void 0!==m?m:null,t._Store.isLoggedIn=(null===(S=p)||void 0===S?void 0:S.is_logged_in)||!1,hasMPIDChanged(c,p)&&(t._Store.mpid=p.mpid,c&&t._Persistence.setLastSeenTime(i),u=!t._Persistence.getFirstSeenTime(p.mpid),t._Persistence.setFirstSeenTime(p.mpid)),r.status===HTTP_SUCCESS){if(s(CacheIdentity)){var A=xhrIdentityResponseAdapter(r);cacheOrClearIdCache(o,g,n.idCache,A,l);}var P=n.IdentityAPI.getUser(p.mpid),U=P?P.getUserIdentities().userIdentities:{};o===Modify$1?(v=t._Identity.IdentityRequest.combineUserIdentities(_,d.userIdentities),t._Store.setUserIdentities(i,v)):(o===Identify&&c&&p.mpid===I&&t._Persistence.setFirstSeenTime(p.mpid),t._Store.addMpidToSessionHistory(p.mpid,i),t._CookieSyncManager.attemptCookieSync(i,p.mpid,u),t._Persistence.swapCurrentUser(i,p.mpid,t._Store.currentSessionMPIDs),d&&!isEmpty(d.userIdentities)&&(v=n.IdentityRequest.combineUserIdentities(U,d.userIdentities)),t._Store.setUserIdentities(p.mpid,v),t._Persistence.update(),t._Store.syncPersistenceData(),t._Persistence.findPrevCookiesBasedOnUI(d),t._Store.context=p.context||t._Store.context),y=t.Identity.getCurrentUser(),tryOnUserAlias(c,y,d,t.Logger);var C=t._Persistence.getPersistence();y&&(t._Persistence.storeDataInMemory(C,y.getMPID()),n.reinitForwardersOnUserChange(c,y),n.setForwarderCallbacks(y,o));var k=getNewIdentitiesByName(v),f=o===Modify$1?_:U;// https://go.mparticle.com/work/SQDSDKS-6501
1295
+ n.sendUserIdentityChangeEvent(k,o,p.mpid,f);}if(a){var T=0===r.status?HTTPCodes$2.noHttpCoverage:r.status;t._Helpers.invokeCallback(a,T,p||null,y);}else p&&!isEmpty(p.errors)&&// https://go.mparticle.com/work/SQDSDKS-6500
1296
+ t.Logger.error("Received HTTP response code of "+r.status+" - "+p.errors[0].message);t.Logger.verbose("Successfully parsed Identity Response"),null===(b=t._APIClient)||void 0===b||b.processQueuedEvents();}catch(s){a&&t._Helpers.invokeCallback(a,r.status,p||null),t.Logger.error("Error parsing JSON response from Identity server: "+s);}},this.sendUserIdentityChangeEvent=function(e,r,s,i){if(s||r===Modify$1)// https://go.mparticle.com/work/SQDSDKS-6501
1294
1297
  {// https://go.mparticle.com/work/SQDSDKS-6354
1295
1298
  var a=this.IdentityAPI.getUser(s);for(var d in e)// Verifies a change actually happened
1296
1299
  if(i[d]!==e[d]){var o,g=!i[d],l=n.createUserIdentityChange(d,e[d],i[d],g,a);// If a new identity type was introduced when the identity changes
@@ -1391,7 +1394,8 @@ var buildUrl=function(a,b,c,d){var e=d?"1":"0",f=["env=".concat(e)],g=c||{},h=g.
1391
1394
  return [2/*return*/,b]}})})};}
1392
1395
 
1393
1396
  var HTTPCodes$1=Constants.HTTPCodes,Messages$1=Constants.Messages,Modify=Constants.IdentityMethods.Modify;function IdentityAPIClient(a){this.sendAliasRequest=function(b,c){var d,e=function xhrCallback(){if(4===d.readyState){//only parse error messages from failing requests
1394
- if(a.Logger.verbose("Received "+d.statusText+" from server"),200!==d.status&&202!==d.status&&d.responseText){var b=JSON.parse(d.responseText);if(b.hasOwnProperty("message")){var e=b.message;return void a._Helpers.invokeAliasCallback(c,d.status,e)}}a._Helpers.invokeAliasCallback(c,d.status);}};if(a.Logger.verbose(Messages$1.InformationMessages.SendAliasHttp),d=a._Helpers.createXHR(e),d)try{d.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.aliasUrl,a._Store.devToken)+"/Alias"),d.send(JSON.stringify(b));}catch(b){a._Helpers.invokeAliasCallback(c,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending alias request to mParticle servers. "+b);}},this.sendIdentityRequest=function(b,c,d,e,f,g,h){var i,j,k=function xhrCallback(){4===i.readyState&&(a.Logger.verbose("Received "+i.statusText+" from server"),f(i,j,d,e,c,h,!1));};if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityBegin),!b)return void a.Logger.error(Messages$1.ErrorMessages.APIRequestEmpty);if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityHttp),i=a._Helpers.createXHR(k),i)try{a._Store.identityCallInFlight?a._Helpers.invokeCallback(d,HTTPCodes$1.activeIdentityRequest,"There is currently an Identity request processing. Please wait for this to return before requesting again"):(j=g||null,c===Modify?i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+g+"/"+c):i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+c),i.setRequestHeader("Content-Type","application/json"),i.setRequestHeader("x-mp-key",a._Store.devToken),a._Store.identityCallInFlight=!0,i.send(JSON.stringify(b)));}catch(b){a._Store.identityCallInFlight=!1,a._Helpers.invokeCallback(d,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending identity request to servers with status code "+i.status+" - "+b);}};}
1397
+ if(a.Logger.verbose("Received "+d.statusText+" from server"),200!==d.status&&202!==d.status&&d.responseText){var b=JSON.parse(d.responseText);if(b.hasOwnProperty("message")){var e=b.message;return void a._Helpers.invokeAliasCallback(c,d.status,e)}}a._Helpers.invokeAliasCallback(c,d.status);}};if(a.Logger.verbose(Messages$1.InformationMessages.SendAliasHttp),d=a._Helpers.createXHR(e),d)try{d.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.aliasUrl,a._Store.devToken)+"/Alias"),d.send(JSON.stringify(b));}catch(b){a._Helpers.invokeAliasCallback(c,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending alias request to mParticle servers. "+b);}},this.sendIdentityRequest=function(b,c,d,e,f,g,h){var i,j,k=function xhrCallback(){if(4===i.readyState){a.Logger.verbose("Received "+i.statusText+" from server");// https://go.mparticle.com/work/SQDSDKS-6565
1398
+ var b=xhrIdentityResponseAdapter(i);f(b,j,d,e,c,h,!1);}};if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityBegin),!b)return void a.Logger.error(Messages$1.ErrorMessages.APIRequestEmpty);if(a.Logger.verbose(Messages$1.InformationMessages.SendIdentityHttp),i=a._Helpers.createXHR(k),i)try{a._Store.identityCallInFlight?a._Helpers.invokeCallback(d,HTTPCodes$1.activeIdentityRequest,"There is currently an Identity request processing. Please wait for this to return before requesting again"):(j=g||null,c===Modify?i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+g+"/"+c):i.open("post",a._Helpers.createServiceUrl(a._Store.SDKConfig.identityUrl)+c),i.setRequestHeader("Content-Type","application/json"),i.setRequestHeader("x-mp-key",a._Store.devToken),a._Store.identityCallInFlight=!0,i.send(JSON.stringify(b)));}catch(b){a._Store.identityCallInFlight=!1,a._Helpers.invokeCallback(d,HTTPCodes$1.noHttpCoverage,b),a.Logger.error("Error sending identity request to servers with status code "+i.status+" - "+b);}};}
1395
1399
 
1396
1400
  var Messages=Constants.Messages,HTTPCodes=Constants.HTTPCodes,FeatureFlags=Constants.FeatureFlags,ReportBatching=FeatureFlags.ReportBatching,StartingInitialization=Messages.InformationMessages.StartingInitialization;/**
1397
1401
  * <p>All of the following methods can be called on the primary mParticle class. In version 2.10.0, we introduced <a href="https://docs.mparticle.com/developers/sdk/web/multiple-instances/">multiple instances</a>. If you are using multiple instances (self hosted environments only), you should call these methods on each instance.</p>
package/dist/mparticle.js CHANGED
@@ -393,7 +393,7 @@ var mParticle = (function () {
393
393
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
394
394
  };
395
395
 
396
- var version = "2.28.1";
396
+ var version = "2.28.2";
397
397
 
398
398
  var Constants = {
399
399
  sdkVersion: version,
@@ -568,6 +568,7 @@ var mParticle = (function () {
568
568
  var MILLIS_IN_ONE_SEC = 1000;
569
569
 
570
570
  var Messages$9 = Constants.Messages;
571
+ var HTTP_SUCCESS = 200;
571
572
  var createCookieString = function createCookieString(value) {
572
573
  return replaceCommasWithPipes(replaceQuotesWithApostrophes(value));
573
574
  };
@@ -6715,22 +6716,35 @@ var mParticle = (function () {
6715
6716
  Modify$2 = _a.Modify,
6716
6717
  Login$1 = _a.Login,
6717
6718
  Logout$1 = _a.Logout;
6718
- var cacheOrClearIdCache = function cacheOrClearIdCache(method, knownIdentities, idCache, xhr, parsingCachedResponse) {
6719
+ var CACHE_HEADER = 'x-mp-max-age';
6720
+ // https://go.mparticle.com/work/SQDSDKS-6568
6721
+ // Temporary adapter to convert the XMLHttpRequest response to the IIdentityResponse interface
6722
+ var xhrIdentityResponseAdapter = function xhrIdentityResponseAdapter(possiblyXhr) {
6723
+ if (possiblyXhr.hasOwnProperty('expireTimestamp')) {
6724
+ // If there is an `expireTimestamp`, it is an IIdentityResponse object, so just return it. This indicates it was a previously cached value.
6725
+ return possiblyXhr;
6726
+ } else {
6727
+ // If there is no `expireTimestamp`, then it is an XHR object and needs to be parsed.
6728
+ return {
6729
+ status: possiblyXhr.status,
6730
+ // Sometimes responseText can be an empty string, such as a 404 response
6731
+ responseText: possiblyXhr.responseText ? JSON.parse(possiblyXhr.responseText) : {},
6732
+ cacheMaxAge: parseNumber((possiblyXhr === null || possiblyXhr === void 0 ? void 0 : possiblyXhr.getResponseHeader(CACHE_HEADER)) || ''),
6733
+ expireTimestamp: 0
6734
+ };
6735
+ }
6736
+ };
6737
+ var cacheOrClearIdCache = function cacheOrClearIdCache(method, knownIdentities, idCache, identityResponse, parsingCachedResponse) {
6719
6738
  // when parsing a response that has already been cached, simply return instead of attempting another cache
6720
6739
  if (parsingCachedResponse) {
6721
6740
  return;
6722
6741
  }
6723
- var CACHE_HEADER = 'x-mp-max-age';
6724
6742
  // default the expire timestamp to one day in milliseconds unless a header comes back
6725
- var now = new Date().getTime();
6726
- var expireTimestamp = now + ONE_DAY_IN_SECONDS * MILLIS_IN_ONE_SEC;
6727
- if (xhr.getAllResponseHeaders().includes(CACHE_HEADER)) {
6728
- expireTimestamp = now + parseNumber(xhr.getResponseHeader(CACHE_HEADER)) * MILLIS_IN_ONE_SEC;
6729
- }
6743
+ var expireTimestamp = getExpireTimestamp(identityResponse === null || identityResponse === void 0 ? void 0 : identityResponse.cacheMaxAge);
6730
6744
  switch (method) {
6731
6745
  case Login$1:
6732
6746
  case Identify$1:
6733
- cacheIdentityRequest(method, knownIdentities, expireTimestamp, idCache, xhr);
6747
+ cacheIdentityRequest(method, knownIdentities, expireTimestamp, idCache, identityResponse);
6734
6748
  break;
6735
6749
  case Modify$2:
6736
6750
  case Logout$1:
@@ -6738,20 +6752,21 @@ var mParticle = (function () {
6738
6752
  break;
6739
6753
  }
6740
6754
  };
6741
- var cacheIdentityRequest = function cacheIdentityRequest(method, identities, expireTimestamp, idCache, xhr) {
6755
+ var cacheIdentityRequest = function cacheIdentityRequest(method, identities, expireTimestamp, idCache, identityResponse) {
6756
+ var responseText = identityResponse.responseText,
6757
+ status = identityResponse.status;
6742
6758
  var cache = idCache.retrieve() || {};
6743
6759
  var cacheKey = concatenateIdentities(method, identities);
6744
6760
  var hashedKey = generateHash(cacheKey);
6745
- var _a = JSON.parse(xhr.responseText),
6746
- mpid = _a.mpid,
6747
- is_logged_in = _a.is_logged_in;
6748
- var cachedResponseText = {
6761
+ var mpid = responseText.mpid,
6762
+ is_logged_in = responseText.is_logged_in;
6763
+ var cachedResponseBody = {
6749
6764
  mpid: mpid,
6750
6765
  is_logged_in: is_logged_in
6751
6766
  };
6752
6767
  cache[hashedKey] = {
6753
- responseText: JSON.stringify(cachedResponseText),
6754
- status: xhr.status,
6768
+ responseText: JSON.stringify(cachedResponseBody),
6769
+ status: status,
6755
6770
  expireTimestamp: expireTimestamp
6756
6771
  };
6757
6772
  idCache.store(cache);
@@ -6783,10 +6798,10 @@ var mParticle = (function () {
6783
6798
  return concatenatedIdentities;
6784
6799
  };
6785
6800
  var hasValidCachedIdentity = function hasValidCachedIdentity(method, proposedUserIdentities, idCache) {
6786
- // There is an edge case where multiple identity calls are taking place
6787
- // before identify fires, so there may not be a cache. See what happens when
6801
+ // There is an edge case where multiple identity calls are taking place
6802
+ // before identify fires, so there may not be a cache. See what happens when
6788
6803
  // the ? in idCache is removed to the following test
6789
- // "queued events contain login mpid instead of identify mpid when calling
6804
+ // "queued events contain login mpid instead of identify mpid when calling
6790
6805
  // login immediately after mParticle initializes"
6791
6806
  var cache = idCache === null || idCache === void 0 ? void 0 : idCache.retrieve();
6792
6807
  // if there is no cache, then there is no valid cached identity
@@ -6814,7 +6829,11 @@ var mParticle = (function () {
6814
6829
  var hashedKey = generateHash(cacheKey);
6815
6830
  var cache = idCache.retrieve();
6816
6831
  var cachedIdentity = cache ? cache[hashedKey] : null;
6817
- return cachedIdentity;
6832
+ return {
6833
+ responseText: parseIdentityResponse(cachedIdentity.responseText),
6834
+ expireTimestamp: cachedIdentity.expireTimestamp,
6835
+ status: cachedIdentity.status
6836
+ };
6818
6837
  };
6819
6838
  // https://go.mparticle.com/work/SQDSDKS-6079
6820
6839
  var createKnownIdentities = function createKnownIdentities(identityApiData, deviceId) {
@@ -6849,6 +6868,15 @@ var mParticle = (function () {
6849
6868
  }
6850
6869
  return false;
6851
6870
  };
6871
+ var getExpireTimestamp = function getExpireTimestamp(maxAge) {
6872
+ if (maxAge === void 0) {
6873
+ maxAge = ONE_DAY_IN_SECONDS;
6874
+ }
6875
+ return new Date().getTime() + maxAge * MILLIS_IN_ONE_SEC;
6876
+ };
6877
+ var parseIdentityResponse = function parseIdentityResponse(responseText) {
6878
+ return responseText ? JSON.parse(responseText) : {};
6879
+ };
6852
6880
 
6853
6881
  var AudienceManager = /** @class */function () {
6854
6882
  function AudienceManager(userAudienceUrl, apiKey, logger) {
@@ -7833,7 +7861,7 @@ var mParticle = (function () {
7833
7861
  };
7834
7862
 
7835
7863
  // https://go.mparticle.com/work/SQDSDKS-6355
7836
- this.parseIdentityResponse = function (xhr, previousMPID, callback, identityApiData, method, knownIdentities, parsingCachedResponse) {
7864
+ this.parseIdentityResponse = function (identityResponse, previousMPID, callback, identityApiData, method, knownIdentities, parsingCachedResponse) {
7837
7865
  var prevUser = mpInstance.Identity.getUser(previousMPID);
7838
7866
  var prevUserMPID = prevUser ? prevUser.getMPID() : null;
7839
7867
  var previousUIByName = prevUser ? prevUser.getUserIdentities().userIdentities : {};
@@ -7843,9 +7871,9 @@ var mParticle = (function () {
7843
7871
  var newIdentitiesByType = {};
7844
7872
  mpInstance._Store.identityCallInFlight = false;
7845
7873
  try {
7846
- var _identityApiResult, _mpInstance$_APIClien;
7874
+ var _identityResponse$res, _identityApiResult, _mpInstance$_APIClien;
7847
7875
  mpInstance.Logger.verbose('Parsing "' + method + '" identity response from server');
7848
- identityApiResult = xhr.responseText ? JSON.parse(xhr.responseText) : null;
7876
+ identityApiResult = (_identityResponse$res = identityResponse.responseText) !== null && _identityResponse$res !== void 0 ? _identityResponse$res : null;
7849
7877
  mpInstance._Store.isLoggedIn = ((_identityApiResult = identityApiResult) === null || _identityApiResult === void 0 ? void 0 : _identityApiResult.is_logged_in) || false;
7850
7878
 
7851
7879
  // https://go.mparticle.com/work/SQDSDKS-6504
@@ -7861,9 +7889,10 @@ var mParticle = (function () {
7861
7889
  // https://go.mparticle.com/work/SQDSDKS-6329
7862
7890
  mpInstance._Persistence.setFirstSeenTime(identityApiResult.mpid);
7863
7891
  }
7864
- if (xhr.status === 200) {
7892
+ if (identityResponse.status === HTTP_SUCCESS) {
7865
7893
  if (getFeatureFlag(CacheIdentity)) {
7866
- cacheOrClearIdCache(method, knownIdentities, self.idCache, xhr, parsingCachedResponse);
7894
+ var identityResponseForCache = xhrIdentityResponseAdapter(identityResponse);
7895
+ cacheOrClearIdCache(method, knownIdentities, self.idCache, identityResponseForCache, parsingCachedResponse);
7867
7896
  }
7868
7897
  var incomingUser = self.IdentityAPI.getUser(identityApiResult.mpid);
7869
7898
  var incomingUIByName = incomingUser ? incomingUser.getUserIdentities().userIdentities : {};
@@ -7912,11 +7941,11 @@ var mParticle = (function () {
7912
7941
  self.sendUserIdentityChangeEvent(newIdentitiesByName, method, identityApiResult.mpid, uiByName);
7913
7942
  }
7914
7943
  if (callback) {
7915
- var callbackCode = xhr.status === 0 ? HTTPCodes$2.noHttpCoverage : xhr.status;
7944
+ var callbackCode = identityResponse.status === 0 ? HTTPCodes$2.noHttpCoverage : identityResponse.status;
7916
7945
  mpInstance._Helpers.invokeCallback(callback, callbackCode, identityApiResult || null, newUser);
7917
7946
  } else if (identityApiResult && !isEmpty(identityApiResult.errors)) {
7918
7947
  // https://go.mparticle.com/work/SQDSDKS-6500
7919
- mpInstance.Logger.error('Received HTTP response code of ' + xhr.status + ' - ' + identityApiResult.errors[0].message);
7948
+ mpInstance.Logger.error('Received HTTP response code of ' + identityResponse.status + ' - ' + identityApiResult.errors[0].message);
7920
7949
  }
7921
7950
  mpInstance.Logger.verbose('Successfully parsed Identity Response');
7922
7951
 
@@ -7924,7 +7953,7 @@ var mParticle = (function () {
7924
7953
  (_mpInstance$_APIClien = mpInstance._APIClient) === null || _mpInstance$_APIClien === void 0 || _mpInstance$_APIClien.processQueuedEvents();
7925
7954
  } catch (e) {
7926
7955
  if (callback) {
7927
- mpInstance._Helpers.invokeCallback(callback, xhr.status, identityApiResult || null);
7956
+ mpInstance._Helpers.invokeCallback(callback, identityResponse.status, identityApiResult || null);
7928
7957
  }
7929
7958
  mpInstance.Logger.error('Error parsing JSON response from Identity server: ' + e);
7930
7959
  }
@@ -8896,7 +8925,10 @@ var mParticle = (function () {
8896
8925
  if (xhr.readyState === 4) {
8897
8926
  // https://go.mparticle.com/work/SQDSDKS-6368
8898
8927
  mpInstance.Logger.verbose('Received ' + xhr.statusText + ' from server');
8899
- parseIdentityResponse(xhr, previousMPID, callback, originalIdentityApiData, method, knownIdentities, false);
8928
+
8929
+ // https://go.mparticle.com/work/SQDSDKS-6565
8930
+ var identityResponse = xhrIdentityResponseAdapter(xhr);
8931
+ parseIdentityResponse(identityResponse, previousMPID, callback, originalIdentityApiData, method, knownIdentities, false);
8900
8932
  }
8901
8933
  };
8902
8934
  mpInstance.Logger.verbose(Messages$1.InformationMessages.SendIdentityBegin);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-sdk",
3
- "version": "2.28.1",
3
+ "version": "2.28.2",
4
4
  "description": "mParticle core SDK for web applications",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -84,6 +84,14 @@ export interface IdentityCallback {
84
84
  (result: IdentityResult): void;
85
85
  }
86
86
 
87
+ export interface IIdentityResponse {
88
+ // https://go.mparticle.com/work/SQDSDKS-6672
89
+ responseText: IdentityResultBody;
90
+ status: number;
91
+ cacheMaxAge?: number; // Default: 86400
92
+ expireTimestamp?: number;
93
+ }
94
+
87
95
  export interface IdentityResult {
88
96
  httpCode: typeof HTTPCodes;
89
97
  getPreviousUser(): User;
@@ -2,62 +2,95 @@ import Constants, { ONE_DAY_IN_SECONDS, MILLIS_IN_ONE_SEC } from './constants';
2
2
  import { Dictionary, parseNumber, isObject, generateHash } from './utils';
3
3
  import { BaseVault } from './vault';
4
4
  import Types from './types';
5
- import { IdentityApiData, UserIdentities, IdentityCallback } from '@mparticle/web-sdk';
5
+ import {
6
+ IdentityApiData,
7
+ UserIdentities,
8
+ IdentityCallback,
9
+ } from '@mparticle/web-sdk';
6
10
  import { IdentityAPIMethod } from './identity.interfaces';
11
+ import {
12
+ IdentityResultBody,
13
+ IIdentityResponse,
14
+ } from './identity-user-interfaces';
7
15
 
8
16
  const { Identify, Modify, Login, Logout } = Constants.IdentityMethods;
17
+ const CACHE_HEADER = 'x-mp-max-age' as const;
9
18
 
10
19
  export type IdentityCache = BaseVault<Dictionary<ICachedIdentityCall>>;
11
20
 
21
+ // https://go.mparticle.com/work/SQDSDKS-6675
12
22
  export type IParseCachedIdentityResponse = (
13
- cachedIdentity: ICachedIdentityCall,
23
+ cachedIdentity: IIdentityResponse,
14
24
  mpid: string,
15
25
  callback: IdentityCallback,
16
26
  identityApiData: IdentityApiData,
17
27
  identityMethod: string,
18
28
  knownIdentities: IKnownIdentities,
19
29
  fromCachedIdentity: boolean
20
- ) => void
30
+ ) => void;
21
31
 
22
32
  export interface IKnownIdentities extends UserIdentities {
23
33
  device_application_stamp?: string;
24
34
  }
25
35
 
26
36
  export interface ICachedIdentityCall {
37
+ // https://go.mparticle.com/work/SQDSDKS-6672
27
38
  responseText: string;
28
39
  status: number;
29
40
  expireTimestamp: number;
30
41
  }
31
42
 
43
+ // https://go.mparticle.com/work/SQDSDKS-6568
44
+ // Temporary adapter to convert the XMLHttpRequest response to the IIdentityResponse interface
45
+ export const xhrIdentityResponseAdapter = (
46
+ possiblyXhr: XMLHttpRequest | IIdentityResponse
47
+ ): IIdentityResponse => {
48
+ if (possiblyXhr.hasOwnProperty('expireTimestamp')) {
49
+ // If there is an `expireTimestamp`, it is an IIdentityResponse object, so just return it. This indicates it was a previously cached value.
50
+ return possiblyXhr as IIdentityResponse;
51
+ } else {
52
+ // If there is no `expireTimestamp`, then it is an XHR object and needs to be parsed.
53
+ return {
54
+ status: possiblyXhr.status,
55
+
56
+ // Sometimes responseText can be an empty string, such as a 404 response
57
+ responseText: (possiblyXhr as XMLHttpRequest).responseText
58
+ ? JSON.parse((possiblyXhr as XMLHttpRequest).responseText)
59
+ : {},
60
+ cacheMaxAge: parseNumber(
61
+ (possiblyXhr as XMLHttpRequest)?.getResponseHeader(
62
+ CACHE_HEADER
63
+ ) || ''
64
+ ),
65
+ expireTimestamp: 0,
66
+ };
67
+ }
68
+ };
69
+
32
70
  export const cacheOrClearIdCache = (
33
71
  method: string,
34
72
  knownIdentities: IKnownIdentities,
35
73
  idCache: BaseVault<Dictionary<ICachedIdentityCall>>,
36
- xhr: XMLHttpRequest,
37
- parsingCachedResponse: boolean,
74
+ identityResponse: IIdentityResponse,
75
+ parsingCachedResponse: boolean
38
76
  ): void => {
39
77
  // when parsing a response that has already been cached, simply return instead of attempting another cache
40
- if (parsingCachedResponse) { return; }
41
-
42
- const CACHE_HEADER = 'x-mp-max-age';
78
+ if (parsingCachedResponse) {
79
+ return;
80
+ }
43
81
 
44
82
  // default the expire timestamp to one day in milliseconds unless a header comes back
45
- let now = new Date().getTime();
46
- let expireTimestamp = now + ONE_DAY_IN_SECONDS * MILLIS_IN_ONE_SEC;
47
- if (xhr.getAllResponseHeaders().includes(CACHE_HEADER)) {
48
- expireTimestamp =
49
- now + (parseNumber(xhr.getResponseHeader(CACHE_HEADER)) * MILLIS_IN_ONE_SEC);
50
- }
83
+ const expireTimestamp = getExpireTimestamp(identityResponse?.cacheMaxAge);
51
84
 
52
85
  switch (method) {
53
- case Login:
54
- case Identify:
86
+ case Login:
87
+ case Identify:
55
88
  cacheIdentityRequest(
56
89
  method,
57
90
  knownIdentities,
58
91
  expireTimestamp,
59
92
  idCache,
60
- xhr
93
+ identityResponse
61
94
  );
62
95
  break;
63
96
  case Modify:
@@ -65,26 +98,32 @@ export const cacheOrClearIdCache = (
65
98
  idCache.purge();
66
99
  break;
67
100
  }
68
- }
101
+ };
69
102
 
70
103
  export const cacheIdentityRequest = (
71
104
  method: IdentityAPIMethod,
72
105
  identities: IKnownIdentities,
73
106
  expireTimestamp: number,
74
107
  idCache: IdentityCache,
75
- xhr: XMLHttpRequest
108
+ identityResponse: IIdentityResponse
76
109
  ): void => {
77
- const cache: Dictionary<ICachedIdentityCall> = idCache.retrieve() || ({} as Dictionary<ICachedIdentityCall>);
110
+ const { responseText, status } = identityResponse;
111
+ const cache: Dictionary<ICachedIdentityCall> =
112
+ idCache.retrieve() || ({} as Dictionary<ICachedIdentityCall>);
78
113
  const cacheKey = concatenateIdentities(method, identities);
79
114
  const hashedKey = generateHash(cacheKey);
80
115
 
81
- const { mpid, is_logged_in } = JSON.parse(xhr.responseText);
82
- const cachedResponseText = {
116
+ const { mpid, is_logged_in } = responseText;
117
+ const cachedResponseBody = {
83
118
  mpid,
84
119
  is_logged_in,
85
120
  };
86
121
 
87
- cache[hashedKey] = { responseText: JSON.stringify(cachedResponseText), status: xhr.status, expireTimestamp};
122
+ cache[hashedKey] = {
123
+ responseText: JSON.stringify(cachedResponseBody),
124
+ status,
125
+ expireTimestamp,
126
+ };
88
127
  idCache.store(cache);
89
128
  };
90
129
 
@@ -115,7 +154,8 @@ export const concatenateIdentities = (
115
154
 
116
155
  concatenatedIdentities = userIDArray.reduce(
117
156
  (prevValue: string, currentValue: string, index: number) => {
118
- const idName: string = Types.IdentityType.getIdentityName(index);
157
+ const idName: string =
158
+ Types.IdentityType.getIdentityName(index);
119
159
  return `${prevValue}${idName}=${currentValue};`;
120
160
  },
121
161
  cacheKey
@@ -128,12 +168,12 @@ export const concatenateIdentities = (
128
168
  export const hasValidCachedIdentity = (
129
169
  method: IdentityAPIMethod,
130
170
  proposedUserIdentities: IKnownIdentities,
131
- idCache?: IdentityCache,
171
+ idCache?: IdentityCache
132
172
  ): boolean => {
133
- // There is an edge case where multiple identity calls are taking place
134
- // before identify fires, so there may not be a cache. See what happens when
173
+ // There is an edge case where multiple identity calls are taking place
174
+ // before identify fires, so there may not be a cache. See what happens when
135
175
  // the ? in idCache is removed to the following test
136
- // "queued events contain login mpid instead of identify mpid when calling
176
+ // "queued events contain login mpid instead of identify mpid when calling
137
177
  // login immediately after mParticle initializes"
138
178
  const cache = idCache?.retrieve();
139
179
 
@@ -152,12 +192,12 @@ export const hasValidCachedIdentity = (
152
192
  if (!cache.hasOwnProperty(hashedKey)) {
153
193
  return false;
154
194
  }
155
-
195
+
156
196
  // If there is a valid cache key, compare the expireTimestamp to the current time.
157
197
  // If the current time is greater than the expireTimestamp, it is not a valid
158
198
  // cached identity.
159
199
  const expireTimestamp = cache[hashedKey].expireTimestamp;
160
-
200
+
161
201
  if (expireTimestamp < new Date().getTime()) {
162
202
  return false;
163
203
  } else {
@@ -168,8 +208,8 @@ export const hasValidCachedIdentity = (
168
208
  export const getCachedIdentity = (
169
209
  method: IdentityAPIMethod,
170
210
  proposedUserIdentities: IKnownIdentities,
171
- idCache: IdentityCache,
172
- ): ICachedIdentityCall | null => {
211
+ idCache: IdentityCache
212
+ ): IIdentityResponse | null => {
173
213
  const cacheKey: string = concatenateIdentities(
174
214
  method,
175
215
  proposedUserIdentities
@@ -179,7 +219,11 @@ export const getCachedIdentity = (
179
219
  const cache = idCache.retrieve();
180
220
  const cachedIdentity = cache ? cache[hashedKey] : null;
181
221
 
182
- return cachedIdentity;
222
+ return {
223
+ responseText: parseIdentityResponse(cachedIdentity.responseText),
224
+ expireTimestamp: cachedIdentity.expireTimestamp,
225
+ status: cachedIdentity.status,
226
+ };
183
227
  };
184
228
 
185
229
  // https://go.mparticle.com/work/SQDSDKS-6079
@@ -200,9 +244,12 @@ export const createKnownIdentities = (
200
244
  return identitiesResult;
201
245
  };
202
246
 
203
- export const removeExpiredIdentityCacheDates = (idCache: BaseVault<Dictionary<ICachedIdentityCall>>) => {
204
- const cache: Dictionary<ICachedIdentityCall> = idCache.retrieve() || {} as Dictionary<ICachedIdentityCall>;
205
-
247
+ export const removeExpiredIdentityCacheDates = (
248
+ idCache: BaseVault<Dictionary<ICachedIdentityCall>>
249
+ ) => {
250
+ const cache: Dictionary<ICachedIdentityCall> =
251
+ idCache.retrieve() || ({} as Dictionary<ICachedIdentityCall>);
252
+
206
253
  const currentTime: number = new Date().getTime();
207
254
 
208
255
  // Iterate over the cache and remove any key/value pairs that are expired
@@ -210,10 +257,10 @@ export const removeExpiredIdentityCacheDates = (idCache: BaseVault<Dictionary<IC
210
257
  if (cache[key].expireTimestamp < currentTime) {
211
258
  delete cache[key];
212
259
  }
213
- };
260
+ }
214
261
 
215
262
  idCache.store(cache);
216
- }
263
+ };
217
264
 
218
265
  export const tryCacheIdentity = (
219
266
  knownIdentities: IKnownIdentities,
@@ -223,7 +270,7 @@ export const tryCacheIdentity = (
223
270
  callback: IdentityCallback,
224
271
  identityApiData: IdentityApiData,
225
272
  identityMethod: IdentityAPIMethod
226
- ): boolean => {
273
+ ): boolean => {
227
274
  // https://go.mparticle.com/work/SQDSDKS-6095
228
275
  const shouldReturnCachedIdentity = hasValidCachedIdentity(
229
276
  identityMethod,
@@ -252,4 +299,10 @@ export const tryCacheIdentity = (
252
299
  return true;
253
300
  }
254
301
  return false;
255
- }
302
+ };
303
+
304
+ const getExpireTimestamp = (maxAge: number = ONE_DAY_IN_SECONDS): number =>
305
+ new Date().getTime() + maxAge * MILLIS_IN_ONE_SEC;
306
+
307
+ const parseIdentityResponse = (responseText: string): IdentityResultBody =>
308
+ responseText ? JSON.parse(responseText) : ({} as IdentityResultBody);
@@ -10,6 +10,7 @@ import {
10
10
  IUserIdentityChangeEvent,
11
11
  IMParticleUser,
12
12
  mParticleUserCart,
13
+ IIdentityResponse,
13
14
  } from './identity-user-interfaces';
14
15
  const { platform, sdkVendor, sdkVersion, HTTPCodes } = Constants;
15
16
 
@@ -170,7 +171,7 @@ export interface IIdentity {
170
171
  userInMemory: IMParticleUser
171
172
  ): IUserIdentityChangeEvent;
172
173
  parseIdentityResponse(
173
- xhr: XMLHttpRequest,
174
+ identityResponse: IIdentityResponse,
174
175
  previousMPID: MPID,
175
176
  callback: IdentityCallback,
176
177
  identityApiData: IdentityApiData,
package/src/identity.js CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  cacheOrClearIdCache,
5
5
  createKnownIdentities,
6
6
  tryCacheIdentity,
7
+ xhrIdentityResponseAdapter,
7
8
  } from './identity-utils';
8
9
  import AudienceManager from './audienceManager';
9
10
  const { Messages, HTTPCodes, FeatureFlags, IdentityMethods } = Constants;
@@ -12,6 +13,7 @@ const { CacheIdentity } = FeatureFlags;
12
13
  const { Identify, Modify, Login, Logout } = IdentityMethods;
13
14
  import {
14
15
  generateDeprecationMessage,
16
+ HTTP_SUCCESS,
15
17
  isEmpty,
16
18
  isFunction,
17
19
  isObject,
@@ -1460,7 +1462,7 @@ export default function Identity(mpInstance) {
1460
1462
 
1461
1463
  // https://go.mparticle.com/work/SQDSDKS-6355
1462
1464
  this.parseIdentityResponse = function(
1463
- xhr,
1465
+ identityResponse,
1464
1466
  previousMPID,
1465
1467
  callback,
1466
1468
  identityApiData,
@@ -1486,9 +1488,7 @@ export default function Identity(mpInstance) {
1486
1488
  'Parsing "' + method + '" identity response from server'
1487
1489
  );
1488
1490
 
1489
- identityApiResult = xhr.responseText
1490
- ? JSON.parse(xhr.responseText)
1491
- : null;
1491
+ identityApiResult = identityResponse.responseText ?? null;
1492
1492
 
1493
1493
  mpInstance._Store.isLoggedIn =
1494
1494
  identityApiResult?.is_logged_in || false;
@@ -1513,13 +1513,16 @@ export default function Identity(mpInstance) {
1513
1513
  );
1514
1514
  }
1515
1515
 
1516
- if (xhr.status === 200) {
1516
+ if (identityResponse.status === HTTP_SUCCESS) {
1517
1517
  if (getFeatureFlag(CacheIdentity)) {
1518
+ const identityResponseForCache = xhrIdentityResponseAdapter(
1519
+ identityResponse
1520
+ );
1518
1521
  cacheOrClearIdCache(
1519
1522
  method,
1520
1523
  knownIdentities,
1521
1524
  self.idCache,
1522
- xhr,
1525
+ identityResponseForCache,
1523
1526
  parsingCachedResponse
1524
1527
  );
1525
1528
  }
@@ -1642,7 +1645,9 @@ export default function Identity(mpInstance) {
1642
1645
 
1643
1646
  if (callback) {
1644
1647
  const callbackCode =
1645
- xhr.status === 0 ? HTTPCodes.noHttpCoverage : xhr.status;
1648
+ identityResponse.status === 0
1649
+ ? HTTPCodes.noHttpCoverage
1650
+ : identityResponse.status;
1646
1651
 
1647
1652
  mpInstance._Helpers.invokeCallback(
1648
1653
  callback,
@@ -1657,7 +1662,7 @@ export default function Identity(mpInstance) {
1657
1662
  // https://go.mparticle.com/work/SQDSDKS-6500
1658
1663
  mpInstance.Logger.error(
1659
1664
  'Received HTTP response code of ' +
1660
- xhr.status +
1665
+ identityResponse.status +
1661
1666
  ' - ' +
1662
1667
  identityApiResult.errors[0].message
1663
1668
  );
@@ -1671,7 +1676,7 @@ export default function Identity(mpInstance) {
1671
1676
  if (callback) {
1672
1677
  mpInstance._Helpers.invokeCallback(
1673
1678
  callback,
1674
- xhr.status,
1679
+ identityResponse.status,
1675
1680
  identityApiResult || null
1676
1681
  );
1677
1682
  }
@@ -1,4 +1,5 @@
1
1
  import Constants from './constants';
2
+ import { xhrIdentityResponseAdapter } from './identity-utils';
2
3
 
3
4
  var HTTPCodes = Constants.HTTPCodes,
4
5
  Messages = Constants.Messages;
@@ -78,8 +79,11 @@ export default function IdentityAPIClient(mpInstance) {
78
79
  mpInstance.Logger.verbose(
79
80
  'Received ' + xhr.statusText + ' from server'
80
81
  );
82
+
83
+ // https://go.mparticle.com/work/SQDSDKS-6565
84
+ const identityResponse = xhrIdentityResponseAdapter(xhr);
81
85
  parseIdentityResponse(
82
- xhr,
86
+ identityResponse,
83
87
  previousMPID,
84
88
  callback,
85
89
  originalIdentityApiData,
package/src/utils.ts CHANGED
@@ -9,6 +9,8 @@ export type Dictionary<V = any> = Record<string, V>;
9
9
 
10
10
  export type Environment = 'development' | 'production';
11
11
 
12
+ export const HTTP_SUCCESS = 200 as const;
13
+
12
14
  const createCookieString = (value: string): string =>
13
15
  replaceCommasWithPipes(replaceQuotesWithApostrophes(value));
14
16