@mparticle/web-sdk 2.28.0 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-sdk",
3
- "version": "2.28.0",
3
+ "version": "2.28.2",
4
4
  "description": "mParticle core SDK for web applications",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/src/apiClient.ts CHANGED
@@ -1,14 +1,13 @@
1
1
  import Constants from './constants';
2
2
  import Types from './types';
3
3
  import { BatchUploader } from './batchUploader';
4
- import { MParticleWebSDK, SDKEvent } from './sdkRuntimeModels';
4
+ import { MParticleWebSDK, SDKEvent, SDKDataPlan } from './sdkRuntimeModels';
5
5
  import KitBlocker from './kitBlocking';
6
6
  import { Dictionary, getRampNumber, isEmpty, parseNumber } from './utils';
7
7
  import { IUploadObject } from './serverModel';
8
8
  import { MPForwarder } from './forwarders.interfaces';
9
- import { IMParticleUser } from './identity-user-interfaces';
10
-
11
- export type ForwardingStatsData = Dictionary<any>;
9
+ import { IMParticleUser, ISDKUserAttributes } from './identity-user-interfaces';
10
+ import { AsyncUploader, FetchUploader, XHRUploader } from './uploaders';
12
11
 
13
12
  export interface IAPIClient {
14
13
  uploader: BatchUploader | null;
@@ -18,18 +17,30 @@ export interface IAPIClient {
18
17
  sendEventToServer: (event: SDKEvent, _options?: Dictionary<any>) => void;
19
18
  sendSingleEventToServer: (event: SDKEvent) => void;
20
19
  sendBatchForwardingStatsToServer: (
21
- forwardingStatsData: ForwardingStatsData,
20
+ forwardingStatsData: IForwardingStatsData,
22
21
  xhr: XMLHttpRequest
23
22
  ) => void;
24
- sendSingleForwardingStatsToServer: (
25
- forwardingStatsData: ForwardingStatsData
26
- ) => void;
23
+ initializeForwarderStatsUploader: () => AsyncUploader;
27
24
  prepareForwardingStats: (
28
25
  forwarder: MPForwarder,
29
26
  event: IUploadObject
30
27
  ) => void;
31
28
  }
32
29
 
30
+ export interface IForwardingStatsData {
31
+ mid: number; // Module Id
32
+ esid: number; // Event Subscription Id
33
+ n: string; // Event Name
34
+ attrs: ISDKUserAttributes; // User Attributes
35
+ sdk: string; // SDK Version
36
+ dt: number; // Data Type
37
+ et: number; // Event Type
38
+ dbg: boolean; // Development Mode (for debugging in Live Stream)
39
+ ct: number; // Current Timestamp
40
+ eec: number; // Expanded Event Count
41
+ dp: SDKDataPlan; // Data Plan
42
+ }
43
+
33
44
  export default function APIClient(
34
45
  this: IAPIClient,
35
46
  mpInstance: MParticleWebSDK,
@@ -161,41 +172,26 @@ export default function APIClient(
161
172
  }
162
173
  };
163
174
 
164
- this.sendSingleForwardingStatsToServer = function(forwardingStatsData) {
165
- let url;
166
- let data;
167
- try {
168
- const xhrCallback = function() {
169
- if (xhr.readyState === 4) {
170
- if (xhr.status === 202) {
171
- mpInstance.Logger.verbose(
172
- 'Successfully sent ' +
173
- xhr.statusText +
174
- ' from server'
175
- );
176
- }
177
- }
178
- };
179
- const xhr = mpInstance._Helpers.createXHR(xhrCallback);
180
- url = mpInstance._Helpers.createServiceUrl(
181
- mpInstance._Store.SDKConfig.v1SecureServiceUrl,
182
- mpInstance._Store.devToken
183
- );
184
- data = forwardingStatsData;
175
+ this.initializeForwarderStatsUploader = (): AsyncUploader => {
176
+ const {
177
+ v1SecureServiceUrl: forwardingDomain,
178
+ } = mpInstance._Store.SDKConfig;
179
+ const { devToken } = mpInstance._Store;
185
180
 
186
- if (xhr) {
187
- xhr.open('post', url + '/Forwarding');
188
- xhr.send(JSON.stringify(data));
189
- }
190
- } catch (e) {
191
- mpInstance.Logger.error(
192
- 'Error sending forwarding stats to mParticle servers.'
193
- );
194
- }
181
+ const uploadUrl: string = `https://${forwardingDomain}${devToken}/Forwarding`;
182
+
183
+ const uploader: AsyncUploader = window.fetch
184
+ ? new FetchUploader(uploadUrl)
185
+ : new XHRUploader(uploadUrl);
186
+
187
+ return uploader;
195
188
  };
196
189
 
197
- this.prepareForwardingStats = function(forwarder, event) {
198
- let forwardingStatsData;
190
+ this.prepareForwardingStats = function(
191
+ forwarder: MPForwarder,
192
+ event:SDKEvent,
193
+ ) : void {
194
+ let forwardingStatsData: IForwardingStatsData;
199
195
  const queue = mpInstance._Forwarders.getForwarderStatsQueue();
200
196
 
201
197
  if (forwarder && forwarder.isVisible) {
@@ -212,6 +208,11 @@ export default function APIClient(
212
208
  eec: event.ExpandedEventCount,
213
209
  dp: event.DataPlan,
214
210
  };
211
+
212
+ const {
213
+ sendSingleForwardingStatsToServer,
214
+ setForwarderStatsQueue,
215
+ } = mpInstance._Forwarders;
215
216
 
216
217
  if (
217
218
  mpInstance._Helpers.getFeatureFlag(
@@ -219,9 +220,9 @@ export default function APIClient(
219
220
  )
220
221
  ) {
221
222
  queue.push(forwardingStatsData);
222
- mpInstance._Forwarders.setForwarderStatsQueue(queue);
223
+ setForwarderStatsQueue(queue);
223
224
  } else {
224
- self.sendSingleForwardingStatsToServer(forwardingStatsData);
225
+ sendSingleForwardingStatsToServer(forwardingStatsData);
225
226
  }
226
227
  }
227
228
  };
package/src/forwarders.js CHANGED
@@ -3,11 +3,16 @@ import filteredMparticleUser from './filteredMparticleUser';
3
3
  import { isEmpty } from './utils';
4
4
  import KitFilterHelper from './kitFilterHelper';
5
5
  import Constants from './constants';
6
+ import APIClient from './apiClient';
6
7
 
7
8
  const { Modify, Identify, Login, Logout } = Constants.IdentityMethods;
8
9
 
9
10
  export default function Forwarders(mpInstance, kitBlocker) {
10
11
  var self = this;
12
+ this.forwarderStatsUploader = new APIClient(
13
+ mpInstance,
14
+ kitBlocker
15
+ ).initializeForwarderStatsUploader();
11
16
 
12
17
  const UserAttributeActionTypes = {
13
18
  setUserAttribute: 'setUserAttribute',
@@ -771,4 +776,31 @@ export default function Forwarders(mpInstance, kitBlocker) {
771
776
  );
772
777
  }
773
778
  };
779
+
780
+ this.sendSingleForwardingStatsToServer = async forwardingStatsData => {
781
+ // https://go.mparticle.com/work/SQDSDKS-6568
782
+ const fetchPayload = {
783
+ method: 'post',
784
+ body: JSON.stringify(forwardingStatsData),
785
+ headers: {
786
+ Accept: 'text/plain;charset=UTF-8',
787
+ 'Content-Type': 'text/plain;charset=UTF-8',
788
+ },
789
+ };
790
+
791
+ const response = await this.forwarderStatsUploader.upload(fetchPayload);
792
+
793
+ let message;
794
+ // This is a fire and forget, so we only need to log the response based on the code, and not return any response body
795
+ if (response.status === 202) {
796
+ // https://go.mparticle.com/work/SQDSDKS-6670
797
+ message = 'Successfully sent forwarding stats to mParticle Servers';
798
+ } else {
799
+ message =
800
+ 'Issue with forwarding stats to mParticle Servers, received HTTP Code of ' +
801
+ response.statusText;
802
+ }
803
+
804
+ mpInstance?.Logger?.verbose(message);
805
+ };
774
806
  }
@@ -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,
@@ -5,7 +5,7 @@ import {
5
5
  Product,
6
6
  UserIdentities,
7
7
  } from '@mparticle/web-sdk';
8
- import { ForwardingStatsData } from './apiClient';
8
+ import { IForwardingStatsData } from './apiClient';
9
9
  import {
10
10
  IntegrationAttributes,
11
11
  ServerSettings,
@@ -18,7 +18,7 @@ import { UserAttributes } from './identity-user-interfaces';
18
18
  export type UploadsTable = Dictionary<any>;
19
19
  export interface iForwardingStatsBatches {
20
20
  uploadsTable: UploadsTable;
21
- forwardingStatsEventQueue: ForwardingStatsData[];
21
+ forwardingStatsEventQueue: IForwardingStatsData[];
22
22
  }
23
23
 
24
24
  export interface IGlobalStoreV2MinifiedKeys {
@@ -65,6 +65,7 @@ export interface SDKEvent {
65
65
  CurrencyCode: string;
66
66
  DataPlan?: SDKDataPlan;
67
67
  LaunchReferral?: string;
68
+ ExpandedEventCount: number;
68
69
  }
69
70
  export interface SDKGeoLocation {
70
71
  lat: number | string;
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