@mparticle/web-sdk 2.28.1 → 2.28.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mparticle.common.js +52 -43
- package/dist/mparticle.esm.js +52 -43
- package/dist/mparticle.js +240 -137
- package/package.json +1 -1
- package/src/aliasRequestApiClient.ts +89 -0
- package/src/constants.ts +7 -1
- package/src/identity-user-interfaces.ts +8 -0
- package/src/identity-utils.ts +93 -40
- package/src/identity.interfaces.ts +11 -1
- package/src/identity.js +14 -10
- package/src/identityApiClient.js +8 -54
- package/src/sdkRuntimeModels.ts +10 -1
- package/src/uploaders.ts +10 -5
package/package.json
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { IAliasRequest, IAliasCallback } from "./identity.interfaces";
|
|
2
|
+
import { MParticleWebSDK } from "./sdkRuntimeModels";
|
|
3
|
+
import Constants from './constants';
|
|
4
|
+
import { FetchUploader, XHRUploader } from './uploaders';
|
|
5
|
+
import { HTTP_ACCEPTED, HTTP_OK } from "./constants";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const { HTTPCodes, Messages } = Constants;
|
|
9
|
+
|
|
10
|
+
interface IAliasResponseBody {
|
|
11
|
+
message?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function sendAliasRequest (mpInstance: MParticleWebSDK, aliasRequest: IAliasRequest, aliasCallback: IAliasCallback) {
|
|
15
|
+
const { verbose, error } = mpInstance.Logger;
|
|
16
|
+
const { invokeAliasCallback } = mpInstance._Helpers;
|
|
17
|
+
const { aliasUrl } = mpInstance._Store.SDKConfig;
|
|
18
|
+
const { devToken: apiKey } = mpInstance._Store;
|
|
19
|
+
|
|
20
|
+
verbose(Messages.InformationMessages.SendAliasHttp);
|
|
21
|
+
|
|
22
|
+
// https://go.mparticle.com/work/SQDSDKS-6750
|
|
23
|
+
const uploadUrl = `https://${aliasUrl}${apiKey}/Alias`;
|
|
24
|
+
const uploader = window.fetch
|
|
25
|
+
? new FetchUploader(uploadUrl)
|
|
26
|
+
: new XHRUploader(uploadUrl);
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
// https://go.mparticle.com/work/SQDSDKS-6568
|
|
30
|
+
const uploadPayload = {
|
|
31
|
+
method: 'post',
|
|
32
|
+
headers: {
|
|
33
|
+
Accept: 'text/plain;charset=UTF-8',
|
|
34
|
+
'Content-Type': 'application/json',
|
|
35
|
+
},
|
|
36
|
+
body: JSON.stringify(aliasRequest),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const response = await uploader.upload(uploadPayload);
|
|
41
|
+
|
|
42
|
+
let message: string;
|
|
43
|
+
let aliasResponseBody: IAliasResponseBody;
|
|
44
|
+
|
|
45
|
+
// FetchUploader returns the response as a JSON object that we have to await
|
|
46
|
+
if (response.json) {
|
|
47
|
+
// HTTP responses of 202, 200, and 403 do not have a response. response.json will always exist on a fetch, but can only be await-ed when the response is not empty, otherwise it will throw an error.
|
|
48
|
+
try {
|
|
49
|
+
aliasResponseBody = await response.json();
|
|
50
|
+
} catch (e) {
|
|
51
|
+
verbose('The request has no response body');
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
// https://go.mparticle.com/work/SQDSDKS-6568
|
|
55
|
+
// XHRUploader returns the response as a string that we need to parse
|
|
56
|
+
const xhrResponse = response as unknown as XMLHttpRequest;
|
|
57
|
+
// debugger;
|
|
58
|
+
aliasResponseBody = xhrResponse.responseText
|
|
59
|
+
? JSON.parse(xhrResponse.responseText)
|
|
60
|
+
: '';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let errorMessage: string;
|
|
64
|
+
|
|
65
|
+
switch (response.status) {
|
|
66
|
+
case HTTP_OK:
|
|
67
|
+
case HTTP_ACCEPTED:
|
|
68
|
+
// https://go.mparticle.com/work/SQDSDKS-6670
|
|
69
|
+
message =
|
|
70
|
+
'Successfully sent forwarding stats to mParticle Servers';
|
|
71
|
+
break;
|
|
72
|
+
default:
|
|
73
|
+
// 400 has an error message, but 403 doesn't
|
|
74
|
+
if (aliasResponseBody?.message) {
|
|
75
|
+
errorMessage = aliasResponseBody.message;
|
|
76
|
+
}
|
|
77
|
+
message =
|
|
78
|
+
'Issue with sending Alias Request to mParticle Servers, received HTTP Code of ' +
|
|
79
|
+
response.status;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
verbose(message);
|
|
83
|
+
invokeAliasCallback(aliasCallback, response.status, errorMessage);
|
|
84
|
+
} catch (e) {
|
|
85
|
+
const err = e as Error;
|
|
86
|
+
error('Error sending alias request to mParticle servers. ' + err);
|
|
87
|
+
invokeAliasCallback(aliasCallback, HTTPCodes.noHttpCoverage, (err.message));
|
|
88
|
+
}
|
|
89
|
+
};
|
package/src/constants.ts
CHANGED
|
@@ -189,4 +189,10 @@ export default Constants;
|
|
|
189
189
|
|
|
190
190
|
// https://go.mparticle.com/work/SQDSDKS-6080
|
|
191
191
|
export const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
|
|
192
|
-
export const MILLIS_IN_ONE_SEC = 1000;
|
|
192
|
+
export const MILLIS_IN_ONE_SEC = 1000;
|
|
193
|
+
|
|
194
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
|
|
195
|
+
export const HTTP_OK = 200 as const;
|
|
196
|
+
export const HTTP_ACCEPTED = 202 as const;
|
|
197
|
+
export const HTTP_BAD_REQUEST = 400 as const;
|
|
198
|
+
export const HTTP_FORBIDDEN = 403 as const;
|
|
@@ -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;
|
package/src/identity-utils.ts
CHANGED
|
@@ -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 {
|
|
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:
|
|
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
|
-
|
|
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) {
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
108
|
+
identityResponse: IIdentityResponse
|
|
76
109
|
): void => {
|
|
77
|
-
const
|
|
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 } =
|
|
82
|
-
const
|
|
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] = {
|
|
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 =
|
|
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
|
-
):
|
|
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
|
|
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 = (
|
|
204
|
-
|
|
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
|
|
|
@@ -114,6 +115,15 @@ export interface IAliasRequest {
|
|
|
114
115
|
scope?: string;
|
|
115
116
|
}
|
|
116
117
|
|
|
118
|
+
export interface IAliasCallback {
|
|
119
|
+
(result: IAliasResult): void;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface IAliasResult {
|
|
123
|
+
httpCode: number;
|
|
124
|
+
message: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
117
127
|
export interface SDKIdentityApi {
|
|
118
128
|
HTTPCodes: typeof HTTPCodes;
|
|
119
129
|
identify?(
|
|
@@ -170,7 +180,7 @@ export interface IIdentity {
|
|
|
170
180
|
userInMemory: IMParticleUser
|
|
171
181
|
): IUserIdentityChangeEvent;
|
|
172
182
|
parseIdentityResponse(
|
|
173
|
-
|
|
183
|
+
identityResponse: IIdentityResponse,
|
|
174
184
|
previousMPID: MPID,
|
|
175
185
|
callback: IdentityCallback,
|
|
176
186
|
identityApiData: IdentityApiData,
|
package/src/identity.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import Constants from './constants';
|
|
1
|
+
import Constants, { HTTP_OK } from './constants';
|
|
2
2
|
import Types from './types';
|
|
3
3
|
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;
|
|
@@ -1460,7 +1461,7 @@ export default function Identity(mpInstance) {
|
|
|
1460
1461
|
|
|
1461
1462
|
// https://go.mparticle.com/work/SQDSDKS-6355
|
|
1462
1463
|
this.parseIdentityResponse = function(
|
|
1463
|
-
|
|
1464
|
+
identityResponse,
|
|
1464
1465
|
previousMPID,
|
|
1465
1466
|
callback,
|
|
1466
1467
|
identityApiData,
|
|
@@ -1486,9 +1487,7 @@ export default function Identity(mpInstance) {
|
|
|
1486
1487
|
'Parsing "' + method + '" identity response from server'
|
|
1487
1488
|
);
|
|
1488
1489
|
|
|
1489
|
-
identityApiResult =
|
|
1490
|
-
? JSON.parse(xhr.responseText)
|
|
1491
|
-
: null;
|
|
1490
|
+
identityApiResult = identityResponse.responseText ?? null;
|
|
1492
1491
|
|
|
1493
1492
|
mpInstance._Store.isLoggedIn =
|
|
1494
1493
|
identityApiResult?.is_logged_in || false;
|
|
@@ -1513,13 +1512,16 @@ export default function Identity(mpInstance) {
|
|
|
1513
1512
|
);
|
|
1514
1513
|
}
|
|
1515
1514
|
|
|
1516
|
-
if (
|
|
1515
|
+
if (identityResponse.status === HTTP_OK) {
|
|
1517
1516
|
if (getFeatureFlag(CacheIdentity)) {
|
|
1517
|
+
const identityResponseForCache = xhrIdentityResponseAdapter(
|
|
1518
|
+
identityResponse
|
|
1519
|
+
);
|
|
1518
1520
|
cacheOrClearIdCache(
|
|
1519
1521
|
method,
|
|
1520
1522
|
knownIdentities,
|
|
1521
1523
|
self.idCache,
|
|
1522
|
-
|
|
1524
|
+
identityResponseForCache,
|
|
1523
1525
|
parsingCachedResponse
|
|
1524
1526
|
);
|
|
1525
1527
|
}
|
|
@@ -1642,7 +1644,9 @@ export default function Identity(mpInstance) {
|
|
|
1642
1644
|
|
|
1643
1645
|
if (callback) {
|
|
1644
1646
|
const callbackCode =
|
|
1645
|
-
|
|
1647
|
+
identityResponse.status === 0
|
|
1648
|
+
? HTTPCodes.noHttpCoverage
|
|
1649
|
+
: identityResponse.status;
|
|
1646
1650
|
|
|
1647
1651
|
mpInstance._Helpers.invokeCallback(
|
|
1648
1652
|
callback,
|
|
@@ -1657,7 +1661,7 @@ export default function Identity(mpInstance) {
|
|
|
1657
1661
|
// https://go.mparticle.com/work/SQDSDKS-6500
|
|
1658
1662
|
mpInstance.Logger.error(
|
|
1659
1663
|
'Received HTTP response code of ' +
|
|
1660
|
-
|
|
1664
|
+
identityResponse.status +
|
|
1661
1665
|
' - ' +
|
|
1662
1666
|
identityApiResult.errors[0].message
|
|
1663
1667
|
);
|
|
@@ -1671,7 +1675,7 @@ export default function Identity(mpInstance) {
|
|
|
1671
1675
|
if (callback) {
|
|
1672
1676
|
mpInstance._Helpers.invokeCallback(
|
|
1673
1677
|
callback,
|
|
1674
|
-
|
|
1678
|
+
identityResponse.status,
|
|
1675
1679
|
identityApiResult || null
|
|
1676
1680
|
);
|
|
1677
1681
|
}
|
package/src/identityApiClient.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import Constants from './constants';
|
|
2
|
+
import { xhrIdentityResponseAdapter } from './identity-utils';
|
|
3
|
+
import { sendAliasRequest } from './aliasRequestApiClient';
|
|
2
4
|
|
|
3
5
|
var HTTPCodes = Constants.HTTPCodes,
|
|
4
6
|
Messages = Constants.Messages;
|
|
@@ -6,59 +8,8 @@ var HTTPCodes = Constants.HTTPCodes,
|
|
|
6
8
|
const { Modify } = Constants.IdentityMethods;
|
|
7
9
|
|
|
8
10
|
export default function IdentityAPIClient(mpInstance) {
|
|
9
|
-
this.sendAliasRequest = function(aliasRequest, callback) {
|
|
10
|
-
|
|
11
|
-
xhrCallback = function() {
|
|
12
|
-
if (xhr.readyState === 4) {
|
|
13
|
-
// https://go.mparticle.com/work/SQDSDKS-6368
|
|
14
|
-
mpInstance.Logger.verbose(
|
|
15
|
-
'Received ' + xhr.statusText + ' from server'
|
|
16
|
-
);
|
|
17
|
-
//only parse error messages from failing requests
|
|
18
|
-
if (xhr.status !== 200 && xhr.status !== 202) {
|
|
19
|
-
if (xhr.responseText) {
|
|
20
|
-
var response = JSON.parse(xhr.responseText);
|
|
21
|
-
if (response.hasOwnProperty('message')) {
|
|
22
|
-
var errorMessage = response.message;
|
|
23
|
-
mpInstance._Helpers.invokeAliasCallback(
|
|
24
|
-
callback,
|
|
25
|
-
xhr.status,
|
|
26
|
-
errorMessage
|
|
27
|
-
);
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
mpInstance._Helpers.invokeAliasCallback(
|
|
33
|
-
callback,
|
|
34
|
-
xhr.status
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
mpInstance.Logger.verbose(Messages.InformationMessages.SendAliasHttp);
|
|
39
|
-
|
|
40
|
-
xhr = mpInstance._Helpers.createXHR(xhrCallback);
|
|
41
|
-
if (xhr) {
|
|
42
|
-
try {
|
|
43
|
-
xhr.open(
|
|
44
|
-
'post',
|
|
45
|
-
mpInstance._Helpers.createServiceUrl(
|
|
46
|
-
mpInstance._Store.SDKConfig.aliasUrl,
|
|
47
|
-
mpInstance._Store.devToken
|
|
48
|
-
) + '/Alias'
|
|
49
|
-
);
|
|
50
|
-
xhr.send(JSON.stringify(aliasRequest));
|
|
51
|
-
} catch (e) {
|
|
52
|
-
mpInstance._Helpers.invokeAliasCallback(
|
|
53
|
-
callback,
|
|
54
|
-
HTTPCodes.noHttpCoverage,
|
|
55
|
-
e
|
|
56
|
-
);
|
|
57
|
-
mpInstance.Logger.error(
|
|
58
|
-
'Error sending alias request to mParticle servers. ' + e
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
11
|
+
this.sendAliasRequest = async function(aliasRequest, callback) {
|
|
12
|
+
await sendAliasRequest(mpInstance, aliasRequest, callback);
|
|
62
13
|
};
|
|
63
14
|
|
|
64
15
|
this.sendIdentityRequest = function(
|
|
@@ -78,8 +29,11 @@ export default function IdentityAPIClient(mpInstance) {
|
|
|
78
29
|
mpInstance.Logger.verbose(
|
|
79
30
|
'Received ' + xhr.statusText + ' from server'
|
|
80
31
|
);
|
|
32
|
+
|
|
33
|
+
// https://go.mparticle.com/work/SQDSDKS-6565
|
|
34
|
+
const identityResponse = xhrIdentityResponseAdapter(xhr);
|
|
81
35
|
parseIdentityResponse(
|
|
82
|
-
|
|
36
|
+
identityResponse,
|
|
83
37
|
previousMPID,
|
|
84
38
|
callback,
|
|
85
39
|
originalIdentityApiData,
|
package/src/sdkRuntimeModels.ts
CHANGED
|
@@ -16,7 +16,11 @@ import { IPersistence } from './persistence.interfaces';
|
|
|
16
16
|
import { IMPSideloadedKit } from './sideloadedKit';
|
|
17
17
|
import { ISessionManager } from './sessionManager';
|
|
18
18
|
import { Kit, MPForwarder } from './forwarders.interfaces';
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
IIdentity,
|
|
21
|
+
SDKIdentityApi,
|
|
22
|
+
IAliasCallback,
|
|
23
|
+
} from './identity.interfaces';
|
|
20
24
|
import {
|
|
21
25
|
ISDKUserAttributeChangeData,
|
|
22
26
|
ISDKUserIdentityChanges,
|
|
@@ -265,6 +269,11 @@ export interface SDKHelpersApi {
|
|
|
265
269
|
generateHash?(value: string): string;
|
|
266
270
|
// https://go.mparticle.com/work/SQDSDKS-6317
|
|
267
271
|
getFeatureFlag?(feature: string): boolean | string; // TODO: Feature Constants should be converted to enum
|
|
272
|
+
invokeAliasCallback(
|
|
273
|
+
aliasCallback: IAliasCallback,
|
|
274
|
+
number: number,
|
|
275
|
+
errorMessage: string
|
|
276
|
+
): void;
|
|
268
277
|
isDelayedByIntegration?(
|
|
269
278
|
delayedIntegrations: Dictionary<boolean>,
|
|
270
279
|
timeoutStart: number,
|
package/src/uploaders.ts
CHANGED
|
@@ -47,6 +47,7 @@ export class XHRUploader extends AsyncUploader {
|
|
|
47
47
|
// 3 LOADING Downloading; responseText holds partial data.
|
|
48
48
|
// 4 DONE The operation is complete.
|
|
49
49
|
|
|
50
|
+
// https://go.mparticle.com/work/SQDSDKS-6736
|
|
50
51
|
private async makeRequest(
|
|
51
52
|
url: string,
|
|
52
53
|
data: string,
|
|
@@ -58,13 +59,17 @@ export class XHRUploader extends AsyncUploader {
|
|
|
58
59
|
if (xhr.readyState !== 4) return;
|
|
59
60
|
|
|
60
61
|
// Process the response
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
reject(xhr);
|
|
65
|
-
}
|
|
62
|
+
// We resolve all xhr responses whose ready state is 4 regardless of HTTP codes that may be errors (400+)
|
|
63
|
+
// because these are valid HTTP responses.
|
|
64
|
+
resolve((xhr as unknown) as Response);
|
|
66
65
|
};
|
|
67
66
|
|
|
67
|
+
// Reject a promise only when there is an xhr error
|
|
68
|
+
xhr.onerror = () => {
|
|
69
|
+
reject((xhr as unknown) as Response);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
|
|
68
73
|
xhr.open(method, url);
|
|
69
74
|
xhr.send(data);
|
|
70
75
|
});
|