@mparticle/web-sdk 2.25.3 → 2.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mparticle.common.js +72 -48
- package/dist/mparticle.esm.js +72 -48
- package/dist/mparticle.js +360 -184
- package/package.json +1 -1
- package/src/apiClient.ts +2 -1
- package/src/audience.ts +9 -0
- package/src/audienceManager.ts +88 -0
- package/src/batchUploader.ts +11 -66
- package/src/constants.ts +4 -0
- package/src/helpers.js +0 -1
- package/src/identity.js +32 -2
- package/src/mockBatchCreator.ts +1 -2
- package/src/mp-instance.js +110 -173
- package/src/nativeSdkHelpers.js +18 -0
- package/src/sdkRuntimeModels.ts +18 -4
- package/src/sessionManager.ts +1 -0
- package/src/store.ts +152 -14
- package/src/uploaders.ts +59 -0
package/package.json
CHANGED
package/src/apiClient.ts
CHANGED
|
@@ -38,9 +38,10 @@ export default function APIClient(
|
|
|
38
38
|
const self = this;
|
|
39
39
|
this.queueEventForBatchUpload = function(event: SDKEvent) {
|
|
40
40
|
if (!this.uploader) {
|
|
41
|
+
// https://go.mparticle.com/work/SQDSDKS-6317
|
|
41
42
|
const millis: number = parseNumber(mpInstance._Helpers.getFeatureFlag(
|
|
42
43
|
Constants.FeatureFlags.EventBatchingIntervalMillis
|
|
43
|
-
));
|
|
44
|
+
) as string);
|
|
44
45
|
this.uploader = new BatchUploader(mpInstance, millis);
|
|
45
46
|
}
|
|
46
47
|
this.uploader.queueEvent(event);
|
package/src/audience.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { SDKLoggerApi } from './sdkRuntimeModels';
|
|
2
|
+
import {
|
|
3
|
+
FetchUploader,
|
|
4
|
+
XHRUploader,
|
|
5
|
+
AsyncUploader,
|
|
6
|
+
fetchPayload
|
|
7
|
+
} from './uploaders';
|
|
8
|
+
import Audience from './audience';
|
|
9
|
+
|
|
10
|
+
export interface IAudienceMembershipsServerResponse {
|
|
11
|
+
dt: 'cam'; // current audience memberships
|
|
12
|
+
ct: number; // timestamp
|
|
13
|
+
id: string;
|
|
14
|
+
audience_memberships: Audience[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface IAudienceMemberships {
|
|
18
|
+
currentAudienceMemberships: Audience[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default class AudienceManager {
|
|
22
|
+
public url: string = '';
|
|
23
|
+
public userAudienceAPI: AsyncUploader;
|
|
24
|
+
public logger: SDKLoggerApi;
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
userAudienceUrl: string,
|
|
28
|
+
apiKey: string,
|
|
29
|
+
logger: SDKLoggerApi,
|
|
30
|
+
) {
|
|
31
|
+
this.logger = logger;
|
|
32
|
+
this.url = `https://${userAudienceUrl}${apiKey}/audience`;
|
|
33
|
+
this.userAudienceAPI = window.fetch
|
|
34
|
+
? new FetchUploader(this.url)
|
|
35
|
+
: new XHRUploader(this.url);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async sendGetUserAudienceRequest(mpid: string, callback: (userAudiences: IAudienceMemberships) => void) {
|
|
39
|
+
this.logger.verbose('Fetching user audiences from server');
|
|
40
|
+
|
|
41
|
+
const fetchPayload: fetchPayload = {
|
|
42
|
+
method: 'GET',
|
|
43
|
+
headers: {
|
|
44
|
+
Accept: '*/*',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
const audienceURLWithMPID = `${this.url}?mpid=${mpid}`;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const userAudiencePromise: Response = await this.userAudienceAPI.upload(
|
|
51
|
+
fetchPayload,
|
|
52
|
+
audienceURLWithMPID
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
if (
|
|
56
|
+
userAudiencePromise.status >= 200 &&
|
|
57
|
+
userAudiencePromise.status < 300
|
|
58
|
+
) {
|
|
59
|
+
this.logger.verbose(`User Audiences successfully received`);
|
|
60
|
+
|
|
61
|
+
const userAudienceMembershipsServerResponse: IAudienceMembershipsServerResponse = await userAudiencePromise.json();
|
|
62
|
+
const parsedUserAudienceMemberships: IAudienceMemberships = {
|
|
63
|
+
currentAudienceMemberships: userAudienceMembershipsServerResponse?.audience_memberships
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
callback(parsedUserAudienceMemberships);
|
|
68
|
+
} catch(e) {
|
|
69
|
+
throw new Error('Error invoking callback on user audience response.');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
} else if (userAudiencePromise.status === 401) {
|
|
73
|
+
throw new Error('`HTTP error status ${userAudiencePromise.status} while retrieving User Audiences - please verify your API key.`');
|
|
74
|
+
} else if (userAudiencePromise.status === 403) {
|
|
75
|
+
throw new Error('`HTTP error status ${userAudiencePromise.status} while retrieving User Audiences - please verify your workspace is enabled for audiences.`');
|
|
76
|
+
} else {
|
|
77
|
+
// In case there is an HTTP error we did not anticipate.
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Uncaught HTTP Error ${userAudiencePromise.status}.`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
} catch (e) {
|
|
83
|
+
this.logger.error(
|
|
84
|
+
`Error retrieving audiences. ${e}`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/batchUploader.ts
CHANGED
|
@@ -10,6 +10,12 @@ import { convertEvents } from './sdkToEventsApiConverter';
|
|
|
10
10
|
import Types from './types';
|
|
11
11
|
import { getRampNumber, isEmpty } from './utils';
|
|
12
12
|
import { SessionStorageVault, LocalStorageVault } from './vault';
|
|
13
|
+
import {
|
|
14
|
+
AsyncUploader,
|
|
15
|
+
FetchUploader,
|
|
16
|
+
XHRUploader,
|
|
17
|
+
fetchPayload
|
|
18
|
+
} from './uploaders';
|
|
13
19
|
|
|
14
20
|
/**
|
|
15
21
|
* BatchUploader contains all the logic to store/retrieve events and batches
|
|
@@ -108,11 +114,12 @@ export class BatchUploader {
|
|
|
108
114
|
_Store: { deviceId },
|
|
109
115
|
} = this.mpInstance;
|
|
110
116
|
|
|
111
|
-
|
|
117
|
+
// https://go.mparticle.com/work/SQDSDKS-6317
|
|
118
|
+
const offlineStorageFeatureFlagValue: string = getFeatureFlag(
|
|
112
119
|
Constants.FeatureFlags.OfflineStorage
|
|
113
|
-
);
|
|
120
|
+
) as string;
|
|
114
121
|
|
|
115
|
-
const offlineStoragePercentage = parseInt(
|
|
122
|
+
const offlineStoragePercentage: number = parseInt(
|
|
116
123
|
offlineStorageFeatureFlagValue,
|
|
117
124
|
10
|
|
118
125
|
);
|
|
@@ -422,66 +429,4 @@ export class BatchUploader {
|
|
|
422
429
|
}
|
|
423
430
|
return null;
|
|
424
431
|
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
abstract class AsyncUploader {
|
|
428
|
-
url: string;
|
|
429
|
-
public abstract upload(fetchPayload: fetchPayload): Promise<XHRResponse>;
|
|
430
|
-
|
|
431
|
-
constructor(url: string) {
|
|
432
|
-
this.url = url;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
class FetchUploader extends AsyncUploader {
|
|
437
|
-
public async upload(fetchPayload: fetchPayload): Promise<XHRResponse> {
|
|
438
|
-
const response: XHRResponse = await fetch(this.url, fetchPayload);
|
|
439
|
-
return response;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
class XHRUploader extends AsyncUploader {
|
|
444
|
-
public async upload(fetchPayload: fetchPayload): Promise<XHRResponse> {
|
|
445
|
-
const response: XHRResponse = await this.makeRequest(
|
|
446
|
-
this.url,
|
|
447
|
-
fetchPayload.body
|
|
448
|
-
);
|
|
449
|
-
return response;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
private async makeRequest(
|
|
453
|
-
url: string,
|
|
454
|
-
data: string
|
|
455
|
-
): Promise<XMLHttpRequest> {
|
|
456
|
-
const xhr: XMLHttpRequest = new XMLHttpRequest();
|
|
457
|
-
return new Promise((resolve, reject) => {
|
|
458
|
-
xhr.onreadystatechange = () => {
|
|
459
|
-
if (xhr.readyState !== 4) return;
|
|
460
|
-
|
|
461
|
-
// Process the response
|
|
462
|
-
if (xhr.status >= 200 && xhr.status < 300) {
|
|
463
|
-
resolve(xhr);
|
|
464
|
-
} else {
|
|
465
|
-
reject(xhr);
|
|
466
|
-
}
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
xhr.open('post', url);
|
|
470
|
-
xhr.send(data);
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
interface XHRResponse {
|
|
476
|
-
status: number;
|
|
477
|
-
statusText?: string;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
interface fetchPayload {
|
|
481
|
-
method: string;
|
|
482
|
-
headers: {
|
|
483
|
-
Accept: string;
|
|
484
|
-
'Content-Type': string;
|
|
485
|
-
};
|
|
486
|
-
body: string;
|
|
487
|
-
}
|
|
432
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -26,6 +26,8 @@ const Constants = {
|
|
|
26
26
|
BadKey: 'Key value cannot be object or array',
|
|
27
27
|
BadLogPurchase:
|
|
28
28
|
'Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions',
|
|
29
|
+
AudienceAPINotEnabled:
|
|
30
|
+
'Your workspace is not enabled to retrieve user audiences.',
|
|
29
31
|
},
|
|
30
32
|
InformationMessages: {
|
|
31
33
|
CookieSearch: 'Searching for cookie',
|
|
@@ -135,6 +137,7 @@ const Constants = {
|
|
|
135
137
|
configUrl: 'jssdkcdns.mparticle.com/JS/v2/',
|
|
136
138
|
identityUrl: 'identity.mparticle.com/v1/',
|
|
137
139
|
aliasUrl: 'jssdks.mparticle.com/v1/identity/',
|
|
140
|
+
userAudienceUrl: 'nativesdks.mparticle.com/v1/',
|
|
138
141
|
},
|
|
139
142
|
Base64CookieKeys: {
|
|
140
143
|
csm: 1,
|
|
@@ -170,6 +173,7 @@ const Constants = {
|
|
|
170
173
|
OfflineStorage: 'offlineStorage',
|
|
171
174
|
DirectUrlRouting: 'directURLRouting',
|
|
172
175
|
CacheIdentity: 'cacheIdentity',
|
|
176
|
+
AudienceAPI: 'audienceAPI',
|
|
173
177
|
},
|
|
174
178
|
DefaultInstance: 'default_instance',
|
|
175
179
|
CCPAPurpose: 'data_sale_opt_out',
|
package/src/helpers.js
CHANGED
|
@@ -441,7 +441,6 @@ export default function Helpers(mpInstance) {
|
|
|
441
441
|
this.inArray = utils.inArray;
|
|
442
442
|
this.isObject = utils.isObject;
|
|
443
443
|
this.decoded = utils.decoded;
|
|
444
|
-
this.returnConvertedBoolean = utils.returnConvertedBoolean;
|
|
445
444
|
this.parseStringOrNumber = utils.parseStringOrNumber;
|
|
446
445
|
this.generateHash = utils.generateHash;
|
|
447
446
|
this.generateUniqueId = utils.generateUniqueId;
|
package/src/identity.js
CHANGED
|
@@ -5,15 +5,17 @@ import {
|
|
|
5
5
|
createKnownIdentities,
|
|
6
6
|
tryCacheIdentity,
|
|
7
7
|
} from './identity-utils';
|
|
8
|
+
import AudienceManager from './audienceManager';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
const { Messages, HTTPCodes, FeatureFlags } = Constants;
|
|
11
|
+
const { ErrorMessages } = Messages;
|
|
11
12
|
|
|
12
13
|
const { Identify, Modify, Login, Logout } = Constants.IdentityMethods;
|
|
13
14
|
|
|
14
15
|
export default function Identity(mpInstance) {
|
|
15
16
|
var self = this;
|
|
16
17
|
this.idCache = null;
|
|
18
|
+
this.audienceManager = null;
|
|
17
19
|
|
|
18
20
|
this.checkIdentitySwap = function(
|
|
19
21
|
previousMPID,
|
|
@@ -1265,6 +1267,34 @@ export default function Identity(mpInstance) {
|
|
|
1265
1267
|
getFirstSeenTime: function() {
|
|
1266
1268
|
return mpInstance._Persistence.getFirstSeenTime(mpid);
|
|
1267
1269
|
},
|
|
1270
|
+
/**
|
|
1271
|
+
* Get user audiences
|
|
1272
|
+
* @method getuserAudiences
|
|
1273
|
+
* @param {Function} [callback] A callback function that is invoked when the user audience request completes
|
|
1274
|
+
*/
|
|
1275
|
+
getUserAudiences: function(callback) {
|
|
1276
|
+
// user audience API is feature flagged
|
|
1277
|
+
if (
|
|
1278
|
+
!mpInstance._Helpers.getFeatureFlag(
|
|
1279
|
+
FeatureFlags.AudienceAPI
|
|
1280
|
+
)
|
|
1281
|
+
) {
|
|
1282
|
+
mpInstance.Logger.error(
|
|
1283
|
+
ErrorMessages.AudienceAPINotEnabled
|
|
1284
|
+
);
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
if (self.audienceManager === null) {
|
|
1288
|
+
self.audienceManager = new AudienceManager(
|
|
1289
|
+
mpInstance._Store.SDKConfig.userAudienceUrl,
|
|
1290
|
+
mpInstance._Store.devToken,
|
|
1291
|
+
mpInstance.Logger,
|
|
1292
|
+
mpid
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
self.audienceManager.sendGetUserAudienceRequest(mpid, callback);
|
|
1297
|
+
},
|
|
1268
1298
|
};
|
|
1269
1299
|
};
|
|
1270
1300
|
|
package/src/mockBatchCreator.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { SDKEvent, BaseEvent, MParticleWebSDK } from './sdkRuntimeModels';
|
|
|
5
5
|
import { convertEvents } from './sdkToEventsApiConverter';
|
|
6
6
|
import * as EventsApi from '@mparticle/event-models';
|
|
7
7
|
import { Batch } from '@mparticle/event-models';
|
|
8
|
-
import { IMPSideloadedKit} from './sideloadedKit';
|
|
8
|
+
import { IMPSideloadedKit } from './sideloadedKit';
|
|
9
9
|
|
|
10
10
|
const mockFunction = function() {
|
|
11
11
|
return null;
|
|
@@ -27,7 +27,6 @@ export default class _BatchValidator {
|
|
|
27
27
|
createServiceUrl: mockFunction,
|
|
28
28
|
parseNumber: mockFunction,
|
|
29
29
|
isObject: mockFunction,
|
|
30
|
-
returnConvertedBoolean: mockFunction,
|
|
31
30
|
Validators: null,
|
|
32
31
|
},
|
|
33
32
|
_resetForTests: mockFunction,
|