@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/src/store.ts
CHANGED
|
@@ -20,7 +20,15 @@ import {
|
|
|
20
20
|
SDKInitConfig,
|
|
21
21
|
SDKProduct,
|
|
22
22
|
} from './sdkRuntimeModels';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
Dictionary,
|
|
25
|
+
isDataPlanSlug,
|
|
26
|
+
isEmpty,
|
|
27
|
+
isNumber,
|
|
28
|
+
isObject,
|
|
29
|
+
parseNumber,
|
|
30
|
+
returnConvertedBoolean,
|
|
31
|
+
} from './utils';
|
|
24
32
|
import { SDKConsentState } from './consent';
|
|
25
33
|
import { Kit, MPForwarder } from './forwarders.interfaces';
|
|
26
34
|
import { IPersistenceMinified } from './persistence.interfaces';
|
|
@@ -61,6 +69,7 @@ export interface SDKConfig {
|
|
|
61
69
|
aliasUrl?: string;
|
|
62
70
|
configUrl?: string;
|
|
63
71
|
identityUrl?: string;
|
|
72
|
+
userAudienceUrl?: string;
|
|
64
73
|
isIOS?: boolean;
|
|
65
74
|
maxProducts: number;
|
|
66
75
|
requestConfig?: boolean;
|
|
@@ -70,6 +79,9 @@ export interface SDKConfig {
|
|
|
70
79
|
v1SecureServiceUrl?: string;
|
|
71
80
|
v2SecureServiceUrl?: string;
|
|
72
81
|
v3SecureServiceUrl?: string;
|
|
82
|
+
webviewBridgeName?: string;
|
|
83
|
+
workspaceToken?: string;
|
|
84
|
+
requiredWebviewBridgeName?: string;
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
function createSDKConfig(config: SDKInitConfig): SDKConfig {
|
|
@@ -113,7 +125,7 @@ interface WrapperSDKInfo {
|
|
|
113
125
|
|
|
114
126
|
// https://go.mparticle.com/work/SQDSDKS-5954
|
|
115
127
|
export interface IFeatureFlags {
|
|
116
|
-
reportBatching?:
|
|
128
|
+
reportBatching?: boolean;
|
|
117
129
|
eventBatchingIntervalMillis?: number;
|
|
118
130
|
offlineStorage?: string;
|
|
119
131
|
directURLRouting?: boolean;
|
|
@@ -168,8 +180,14 @@ export interface IStore {
|
|
|
168
180
|
|
|
169
181
|
getDeviceId?(): string;
|
|
170
182
|
setDeviceId?(deviceId: string): void;
|
|
183
|
+
getFirstSeenTime?(mpid: MPID): number;
|
|
184
|
+
setFirstSeenTime?(mpid: MPID, time?: number): void;
|
|
185
|
+
getLastSeenTime?(mpid: MPID): number;
|
|
186
|
+
setLastSeenTime?(mpid: MPID, time?: number): void;
|
|
171
187
|
|
|
188
|
+
hasInvalidIdentifyRequest?: () => boolean;
|
|
172
189
|
nullifySession?: () => void;
|
|
190
|
+
processConfig(config: SDKInitConfig): void;
|
|
173
191
|
}
|
|
174
192
|
|
|
175
193
|
// TODO: Merge this with SDKStoreApi in sdkRuntimeModels
|
|
@@ -179,6 +197,13 @@ export default function Store(
|
|
|
179
197
|
mpInstance: MParticleWebSDK,
|
|
180
198
|
apiKey?: string
|
|
181
199
|
) {
|
|
200
|
+
const {
|
|
201
|
+
createMainStorageName,
|
|
202
|
+
createProductStorageName,
|
|
203
|
+
} = mpInstance._Helpers;
|
|
204
|
+
|
|
205
|
+
const { isWebviewEnabled } = mpInstance._NativeSdkHelpers;
|
|
206
|
+
|
|
182
207
|
const defaultStore: Partial<IStore> = {
|
|
183
208
|
isEnabled: true,
|
|
184
209
|
sessionAttributes: {},
|
|
@@ -260,19 +285,19 @@ export default function Store(
|
|
|
260
285
|
this.SDKConfig.flags = {};
|
|
261
286
|
}
|
|
262
287
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
288
|
+
// We process the initial config that is passed via the SDK init
|
|
289
|
+
// and then we will reprocess the config within the processConfig
|
|
290
|
+
// function when the config is updated from the server
|
|
291
|
+
// https://go.mparticle.com/work/SQDSDKS-6317
|
|
292
|
+
this.SDKConfig.flags = processFlags(config);
|
|
267
293
|
|
|
268
294
|
if (config.deviceId) {
|
|
269
295
|
this.deviceId = config.deviceId;
|
|
270
296
|
}
|
|
271
297
|
if (config.hasOwnProperty('isDevelopmentMode')) {
|
|
272
|
-
this.SDKConfig.isDevelopmentMode =
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
);
|
|
298
|
+
this.SDKConfig.isDevelopmentMode = returnConvertedBoolean(
|
|
299
|
+
config.isDevelopmentMode
|
|
300
|
+
);
|
|
276
301
|
} else {
|
|
277
302
|
this.SDKConfig.isDevelopmentMode = false;
|
|
278
303
|
}
|
|
@@ -451,6 +476,16 @@ export default function Store(
|
|
|
451
476
|
}
|
|
452
477
|
}
|
|
453
478
|
|
|
479
|
+
this.hasInvalidIdentifyRequest = (): boolean => {
|
|
480
|
+
const { identifyRequest } = this.SDKConfig;
|
|
481
|
+
return (
|
|
482
|
+
(isObject(identifyRequest) &&
|
|
483
|
+
isObject(identifyRequest.userIdentities) &&
|
|
484
|
+
isEmpty(identifyRequest.userIdentities)) ||
|
|
485
|
+
!identifyRequest
|
|
486
|
+
);
|
|
487
|
+
};
|
|
488
|
+
|
|
454
489
|
this.getDeviceId = () => this.deviceId;
|
|
455
490
|
this.setDeviceId = (deviceId: string) => {
|
|
456
491
|
this.deviceId = deviceId;
|
|
@@ -458,18 +493,118 @@ export default function Store(
|
|
|
458
493
|
mpInstance._Persistence.update();
|
|
459
494
|
};
|
|
460
495
|
|
|
496
|
+
this.getFirstSeenTime = (mpid: MPID) => {
|
|
497
|
+
if (!mpid) {
|
|
498
|
+
return null;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
if (
|
|
502
|
+
this.persistenceData &&
|
|
503
|
+
this.persistenceData[mpid] &&
|
|
504
|
+
this.persistenceData[mpid].fst
|
|
505
|
+
) {
|
|
506
|
+
return this.persistenceData[mpid].fst;
|
|
507
|
+
} else {
|
|
508
|
+
return null;
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
this.setFirstSeenTime = (mpid: MPID, _time?: number) => {
|
|
513
|
+
if (!mpid) {
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const time = _time || new Date().getTime();
|
|
518
|
+
|
|
519
|
+
if (this.persistenceData) {
|
|
520
|
+
if (!this.persistenceData[mpid]) {
|
|
521
|
+
this.persistenceData[mpid] = {};
|
|
522
|
+
}
|
|
523
|
+
if (!this.persistenceData[mpid].fst) {
|
|
524
|
+
this.persistenceData[mpid].fst = time;
|
|
525
|
+
mpInstance._Persistence.savePersistence(this.persistenceData);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
this.getLastSeenTime = (mpid: MPID) => {
|
|
531
|
+
if (!mpid) {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
// // https://go.mparticle.com/work/SQDSDKS-6315
|
|
535
|
+
const currentUser = mpInstance.Identity.getCurrentUser();
|
|
536
|
+
if (mpid === currentUser?.getMPID()) {
|
|
537
|
+
// if the mpid is the current user, its last seen time is the current time
|
|
538
|
+
return new Date().getTime();
|
|
539
|
+
} else if (
|
|
540
|
+
this.persistenceData &&
|
|
541
|
+
this.persistenceData[mpid] &&
|
|
542
|
+
this.persistenceData[mpid].lst
|
|
543
|
+
) {
|
|
544
|
+
return this.persistenceData[mpid].lst;
|
|
545
|
+
} else {
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
this.setLastSeenTime = (mpid: MPID, _time?: number) => {
|
|
551
|
+
if (!mpid) {
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
const time = _time || new Date().getTime();
|
|
556
|
+
|
|
557
|
+
if (this.persistenceData) {
|
|
558
|
+
if (!this.persistenceData[mpid]) {
|
|
559
|
+
this.persistenceData[mpid] = {};
|
|
560
|
+
}
|
|
561
|
+
if (!this.persistenceData[mpid].lst) {
|
|
562
|
+
this.persistenceData[mpid].lst = time;
|
|
563
|
+
mpInstance._Persistence.savePersistence(this.persistenceData);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
|
|
461
568
|
this.nullifySession = (): void => {
|
|
462
569
|
this.sessionId = null;
|
|
463
570
|
this.dateLastEventSent = null;
|
|
464
571
|
this.sessionAttributes = {};
|
|
465
572
|
mpInstance._Persistence.update();
|
|
466
573
|
};
|
|
574
|
+
|
|
575
|
+
this.processConfig = (config: SDKInitConfig) => {
|
|
576
|
+
const { workspaceToken, requiredWebviewBridgeName } = config;
|
|
577
|
+
|
|
578
|
+
// We should reprocess the flags in case they have changed when we request an updated config
|
|
579
|
+
// such as if the SDK is being self-hosted and the flags are different on the server config
|
|
580
|
+
// https://go.mparticle.com/work/SQDSDKS-6317
|
|
581
|
+
this.SDKConfig.flags = processFlags(config);
|
|
582
|
+
|
|
583
|
+
if (workspaceToken) {
|
|
584
|
+
this.SDKConfig.workspaceToken = workspaceToken;
|
|
585
|
+
} else {
|
|
586
|
+
mpInstance.Logger.warning(
|
|
587
|
+
'You should have a workspaceToken on your config object for security purposes.'
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
// add a new function to apply items to the store that require config to be returned
|
|
591
|
+
this.storageName = createMainStorageName(workspaceToken);
|
|
592
|
+
this.prodStorageName = createProductStorageName(workspaceToken);
|
|
593
|
+
|
|
594
|
+
this.SDKConfig.requiredWebviewBridgeName =
|
|
595
|
+
requiredWebviewBridgeName || workspaceToken;
|
|
596
|
+
|
|
597
|
+
this.webviewBridgeEnabled = isWebviewEnabled(
|
|
598
|
+
this.SDKConfig.requiredWebviewBridgeName,
|
|
599
|
+
this.SDKConfig.minWebviewBridgeVersion
|
|
600
|
+
);
|
|
601
|
+
|
|
602
|
+
this.configurationLoaded = true;
|
|
603
|
+
};
|
|
467
604
|
}
|
|
468
605
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
SDKConfig: SDKConfig
|
|
472
|
-
): IFeatureFlags {
|
|
606
|
+
// https://go.mparticle.com/work/SQDSDKS-6317
|
|
607
|
+
export function processFlags(config: SDKInitConfig): IFeatureFlags {
|
|
473
608
|
const flags: IFeatureFlags = {};
|
|
474
609
|
const {
|
|
475
610
|
ReportBatching,
|
|
@@ -477,12 +612,14 @@ export function processFlags(
|
|
|
477
612
|
OfflineStorage,
|
|
478
613
|
DirectUrlRouting,
|
|
479
614
|
CacheIdentity,
|
|
615
|
+
AudienceAPI,
|
|
480
616
|
} = Constants.FeatureFlags;
|
|
481
617
|
|
|
482
618
|
if (!config.flags) {
|
|
483
619
|
return {};
|
|
484
620
|
}
|
|
485
621
|
|
|
622
|
+
// https://go.mparticle.com/work/SQDSDKS-6317
|
|
486
623
|
// Passed in config flags take priority over defaults
|
|
487
624
|
flags[ReportBatching] = config.flags[ReportBatching] || false;
|
|
488
625
|
// The server returns stringified numbers, sowe need to parse
|
|
@@ -492,6 +629,7 @@ export function processFlags(
|
|
|
492
629
|
flags[OfflineStorage] = config.flags[OfflineStorage] || '0';
|
|
493
630
|
flags[DirectUrlRouting] = config.flags[DirectUrlRouting] === 'True';
|
|
494
631
|
flags[CacheIdentity] = config.flags[CacheIdentity] === 'True';
|
|
632
|
+
flags[AudienceAPI] = config.flags[AudienceAPI] === 'True';
|
|
495
633
|
|
|
496
634
|
return flags;
|
|
497
635
|
}
|
package/src/uploaders.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export interface fetchPayload {
|
|
2
|
+
method: string;
|
|
3
|
+
headers: {
|
|
4
|
+
Accept: string;
|
|
5
|
+
'Content-Type'?: string;
|
|
6
|
+
};
|
|
7
|
+
body?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export abstract class AsyncUploader {
|
|
11
|
+
url: string;
|
|
12
|
+
public abstract upload(
|
|
13
|
+
fetchPayload: fetchPayload,
|
|
14
|
+
url?: string
|
|
15
|
+
): Promise<Response>;
|
|
16
|
+
|
|
17
|
+
constructor(url: string) {
|
|
18
|
+
this.url = url;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class FetchUploader extends AsyncUploader {
|
|
23
|
+
public async upload(
|
|
24
|
+
fetchPayload: fetchPayload,
|
|
25
|
+
_url?: string
|
|
26
|
+
): Promise<Response> {
|
|
27
|
+
const url = _url || this.url;
|
|
28
|
+
return await fetch(url, fetchPayload);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class XHRUploader extends AsyncUploader {
|
|
33
|
+
public async upload(fetchPayload: fetchPayload): Promise<Response> {
|
|
34
|
+
const response: Response = await this.makeRequest(
|
|
35
|
+
this.url,
|
|
36
|
+
fetchPayload.body
|
|
37
|
+
);
|
|
38
|
+
return response;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private async makeRequest(url: string, data: string): Promise<Response> {
|
|
42
|
+
const xhr: XMLHttpRequest = new XMLHttpRequest();
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
xhr.onreadystatechange = () => {
|
|
45
|
+
if (xhr.readyState !== 4) return;
|
|
46
|
+
|
|
47
|
+
// Process the response
|
|
48
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
49
|
+
resolve((xhr as unknown) as Response);
|
|
50
|
+
} else {
|
|
51
|
+
reject(xhr);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
xhr.open('post', url);
|
|
56
|
+
xhr.send(data);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|