@mparticle/web-sdk 2.17.3 → 2.18.0
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 +44 -16
- package/dist/mparticle.esm.js +44 -16
- package/dist/mparticle.js +116 -56
- package/package.json +1 -1
- package/src/helpers.js +1 -13
- package/src/mp-instance.js +55 -2
- package/src/mparticle-instance-manager.js +3 -0
- package/src/sdkRuntimeModels.ts +84 -60
- package/src/{store.js → store.ts} +151 -35
- package/src/stub/mparticle.stub.js +1 -0
- package/src/types.js +6 -0
- package/src/utils.ts +32 -0
- package/src/validators.ts +8 -14
|
@@ -1,30 +1,156 @@
|
|
|
1
|
+
import { Batch } from '@mparticle/event-models';
|
|
2
|
+
import { Context } from '@mparticle/event-models';
|
|
3
|
+
import {
|
|
4
|
+
DataPlanConfig,
|
|
5
|
+
MPID,
|
|
6
|
+
IdentifyRequest,
|
|
7
|
+
IdentityCallback,
|
|
8
|
+
SDKEventCustomFlags,
|
|
9
|
+
} from '@mparticle/web-sdk';
|
|
1
10
|
import Constants from './constants';
|
|
11
|
+
import {
|
|
12
|
+
DataPlanResult,
|
|
13
|
+
Kit,
|
|
14
|
+
KitBlockerOptions,
|
|
15
|
+
KitConfigs,
|
|
16
|
+
LogLevelType,
|
|
17
|
+
MParticleWebSDK,
|
|
18
|
+
MPForwarder,
|
|
19
|
+
SDKConsentState,
|
|
20
|
+
SDKDataPlan,
|
|
21
|
+
SDKEvent,
|
|
22
|
+
SDKGeoLocation,
|
|
23
|
+
SDKInitConfig,
|
|
24
|
+
SDKProduct,
|
|
25
|
+
} from './sdkRuntimeModels';
|
|
26
|
+
import { isNumber, isDataPlanSlug, Dictionary } from './utils';
|
|
27
|
+
|
|
28
|
+
// This represents the runtime configuration of the SDK AFTER
|
|
29
|
+
// initialization has been complete and all settings and
|
|
30
|
+
// configurations have been stitched together.
|
|
31
|
+
export interface SDKConfig {
|
|
32
|
+
isDevelopmentMode?: boolean;
|
|
33
|
+
logger: {
|
|
34
|
+
error?(msg);
|
|
35
|
+
warning?(msg);
|
|
36
|
+
verbose?(msg);
|
|
37
|
+
};
|
|
38
|
+
onCreateBatch(batch: Batch): Batch;
|
|
39
|
+
customFlags?: SDKEventCustomFlags;
|
|
40
|
+
dataPlan: SDKDataPlan;
|
|
41
|
+
dataPlanOptions: KitBlockerOptions; // when the user provides their own data plan
|
|
42
|
+
dataPlanResult?: DataPlanResult; // when the data plan comes from the server via /config
|
|
43
|
+
|
|
44
|
+
appName?: string;
|
|
45
|
+
appVersion?: string;
|
|
46
|
+
package?: string;
|
|
47
|
+
flags?: { [key: string]: string | number | boolean };
|
|
48
|
+
kitConfigs: KitConfigs[];
|
|
49
|
+
kits: Dictionary<Kit>;
|
|
50
|
+
logLevel?: LogLevelType;
|
|
51
|
+
cookieDomain?: string;
|
|
52
|
+
maxCookieSize?: number | undefined;
|
|
53
|
+
minWebviewBridgeVersion: 1 | 2 | undefined;
|
|
54
|
+
identifyRequest: IdentifyRequest;
|
|
55
|
+
identityCallback: IdentityCallback;
|
|
56
|
+
integrationDelayTimeout: number;
|
|
57
|
+
|
|
58
|
+
aliasMaxWindow: number;
|
|
59
|
+
deviceId?: string;
|
|
60
|
+
forceHttps?: boolean;
|
|
61
|
+
aliasUrl?: string;
|
|
62
|
+
configUrl?: string;
|
|
63
|
+
identityUrl?: string;
|
|
64
|
+
isIOS?: boolean;
|
|
65
|
+
maxProducts: number;
|
|
66
|
+
requestConfig?: boolean;
|
|
67
|
+
sessionTimeout?: number;
|
|
68
|
+
useNativeSdk?: boolean;
|
|
69
|
+
useCookieStorage?: boolean;
|
|
70
|
+
v1SecureServiceUrl?: string;
|
|
71
|
+
v2SecureServiceUrl?: string;
|
|
72
|
+
v3SecureServiceUrl?: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function createSDKConfig(config: SDKInitConfig): SDKConfig {
|
|
76
|
+
// TODO: Refactor to create a default config object
|
|
77
|
+
const sdkConfig = {} as SDKConfig;
|
|
2
78
|
|
|
3
|
-
|
|
4
|
-
var sdkConfig = {};
|
|
5
|
-
for (var prop in Constants.DefaultConfig) {
|
|
79
|
+
for (const prop in Constants.DefaultConfig) {
|
|
6
80
|
if (Constants.DefaultConfig.hasOwnProperty(prop)) {
|
|
7
81
|
sdkConfig[prop] = Constants.DefaultConfig[prop];
|
|
8
82
|
}
|
|
9
83
|
}
|
|
10
84
|
|
|
11
85
|
if (config) {
|
|
12
|
-
for (prop in config) {
|
|
86
|
+
for (const prop in config) {
|
|
13
87
|
if (config.hasOwnProperty(prop)) {
|
|
14
88
|
sdkConfig[prop] = config[prop];
|
|
15
89
|
}
|
|
16
90
|
}
|
|
17
91
|
}
|
|
18
92
|
|
|
19
|
-
for (prop in Constants.DefaultUrls) {
|
|
93
|
+
for (const prop in Constants.DefaultUrls) {
|
|
20
94
|
sdkConfig[prop] = Constants.DefaultUrls[prop];
|
|
21
95
|
}
|
|
22
96
|
|
|
23
97
|
return sdkConfig;
|
|
24
98
|
}
|
|
25
99
|
|
|
26
|
-
|
|
27
|
-
|
|
100
|
+
// TODO: Placeholder Types, MigrationData is temporary and will be removed in the future to reduce SDK size
|
|
101
|
+
export type PixelConfiguration = Dictionary;
|
|
102
|
+
export type MigrationData = Dictionary;
|
|
103
|
+
export type ServerSettings = Dictionary;
|
|
104
|
+
|
|
105
|
+
// Temporary Interface until Store can be refactored as a class
|
|
106
|
+
export interface IStore {
|
|
107
|
+
isEnabled: boolean;
|
|
108
|
+
sessionAttributes: Dictionary;
|
|
109
|
+
currentSessionMPIDs: MPID[];
|
|
110
|
+
consentState: SDKConsentState | null;
|
|
111
|
+
sessionId: string | null;
|
|
112
|
+
isFirstRun: boolean;
|
|
113
|
+
clientId: string;
|
|
114
|
+
deviceId: string;
|
|
115
|
+
devToken: string | null;
|
|
116
|
+
migrationData: MigrationData;
|
|
117
|
+
serverSettings: ServerSettings;
|
|
118
|
+
dateLastEventSent: number | null;
|
|
119
|
+
sessionStartDate: number | null;
|
|
120
|
+
currentPosition: SDKGeoLocation | null;
|
|
121
|
+
isTracking: boolean;
|
|
122
|
+
watchPositionId: number | null;
|
|
123
|
+
cartProducts: SDKProduct[];
|
|
124
|
+
eventQueue: SDKEvent[];
|
|
125
|
+
currencyCode: string | null;
|
|
126
|
+
globalTimer: number | null;
|
|
127
|
+
context: Context | null;
|
|
128
|
+
configurationLoaded: boolean;
|
|
129
|
+
identityCallInFlight: boolean;
|
|
130
|
+
SDKConfig: Partial<SDKConfig>;
|
|
131
|
+
migratingToIDSyncCookies: boolean; // TODO: Remove when we archive Web SDK v1
|
|
132
|
+
nonCurrentUserMPIDs: Record<MPID, Dictionary>;
|
|
133
|
+
identifyCalled: boolean;
|
|
134
|
+
isLoggedIn: boolean;
|
|
135
|
+
cookieSyncDates: Dictionary<number>;
|
|
136
|
+
integrationAttributes: Dictionary<Dictionary<string>>;
|
|
137
|
+
requireDelay: boolean;
|
|
138
|
+
isLocalStorageAvailable: boolean | null;
|
|
139
|
+
storageName: string | null;
|
|
140
|
+
prodStorageName: string | null;
|
|
141
|
+
activeForwarders: MPForwarder[];
|
|
142
|
+
kits: Dictionary<MPForwarder>;
|
|
143
|
+
configuredForwarders: MPForwarder[];
|
|
144
|
+
pixelConfigurations: PixelConfiguration[];
|
|
145
|
+
integrationDelayTimeoutStart: number; // UNIX Timestamp
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export default function Store(
|
|
149
|
+
this: IStore,
|
|
150
|
+
config: SDKInitConfig,
|
|
151
|
+
mpInstance: MParticleWebSDK
|
|
152
|
+
) {
|
|
153
|
+
const defaultStore: Partial<IStore> = {
|
|
28
154
|
isEnabled: true,
|
|
29
155
|
sessionAttributes: {},
|
|
30
156
|
currentSessionMPIDs: [],
|
|
@@ -45,7 +171,7 @@ export default function Store(config, mpInstance) {
|
|
|
45
171
|
eventQueue: [],
|
|
46
172
|
currencyCode: null,
|
|
47
173
|
globalTimer: null,
|
|
48
|
-
context:
|
|
174
|
+
context: null,
|
|
49
175
|
configurationLoaded: false,
|
|
50
176
|
identityCallInFlight: false,
|
|
51
177
|
SDKConfig: {},
|
|
@@ -113,14 +239,9 @@ export default function Store(config, mpInstance) {
|
|
|
113
239
|
this.SDKConfig.logLevel = config.logLevel;
|
|
114
240
|
}
|
|
115
241
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.SDKConfig.useNativeSdk = false;
|
|
120
|
-
}
|
|
121
|
-
if (config.hasOwnProperty('kits')) {
|
|
122
|
-
this.SDKConfig.kits = config.kits;
|
|
123
|
-
}
|
|
242
|
+
this.SDKConfig.useNativeSdk = !!config.useNativeSdk;
|
|
243
|
+
|
|
244
|
+
this.SDKConfig.kits = config.kits || {};
|
|
124
245
|
|
|
125
246
|
if (config.hasOwnProperty('isIOS')) {
|
|
126
247
|
this.SDKConfig.isIOS = config.isIOS;
|
|
@@ -177,8 +298,8 @@ export default function Store(config, mpInstance) {
|
|
|
177
298
|
} else {
|
|
178
299
|
mpInstance.Logger.warning(
|
|
179
300
|
'The optional callback must be a function. You tried entering a(n) ' +
|
|
180
|
-
typeof callback
|
|
181
|
-
|
|
301
|
+
typeof callback +
|
|
302
|
+
' . Callback not set. Please set your callback again.'
|
|
182
303
|
);
|
|
183
304
|
}
|
|
184
305
|
}
|
|
@@ -200,32 +321,29 @@ export default function Store(config, mpInstance) {
|
|
|
200
321
|
PlanVersion: null,
|
|
201
322
|
PlanId: null,
|
|
202
323
|
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
mpInstance.Logger.error(
|
|
209
|
-
'Your data plan id must be in a slug format'
|
|
210
|
-
);
|
|
211
|
-
}
|
|
324
|
+
|
|
325
|
+
const dataPlan = config.dataPlan as DataPlanConfig;
|
|
326
|
+
if (dataPlan.planId) {
|
|
327
|
+
if (isDataPlanSlug(dataPlan.planId)) {
|
|
328
|
+
this.SDKConfig.dataPlan.PlanId = dataPlan.planId;
|
|
212
329
|
} else {
|
|
213
330
|
mpInstance.Logger.error(
|
|
214
|
-
'Your data plan id must be a string'
|
|
331
|
+
'Your data plan id must be a string and match the data plan slug format (i.e. under_case_slug)'
|
|
215
332
|
);
|
|
216
333
|
}
|
|
217
334
|
}
|
|
218
335
|
|
|
219
|
-
if (
|
|
220
|
-
if (
|
|
221
|
-
this.SDKConfig.dataPlan.PlanVersion =
|
|
222
|
-
config.dataPlan.planVersion;
|
|
336
|
+
if (dataPlan.planVersion) {
|
|
337
|
+
if (isNumber(dataPlan.planVersion)) {
|
|
338
|
+
this.SDKConfig.dataPlan.PlanVersion = dataPlan.planVersion;
|
|
223
339
|
} else {
|
|
224
340
|
mpInstance.Logger.error(
|
|
225
341
|
'Your data plan version must be a number'
|
|
226
342
|
);
|
|
227
343
|
}
|
|
228
344
|
}
|
|
345
|
+
} else {
|
|
346
|
+
this.SDKConfig.dataPlan = {};
|
|
229
347
|
}
|
|
230
348
|
|
|
231
349
|
if (config.hasOwnProperty('forceHttps')) {
|
|
@@ -235,9 +353,7 @@ export default function Store(config, mpInstance) {
|
|
|
235
353
|
}
|
|
236
354
|
|
|
237
355
|
// Some forwarders require custom flags on initialization, so allow them to be set using config object
|
|
238
|
-
|
|
239
|
-
this.SDKConfig.customFlags = config.customFlags;
|
|
240
|
-
}
|
|
356
|
+
this.SDKConfig.customFlags = config.customFlags || {};
|
|
241
357
|
|
|
242
358
|
if (config.hasOwnProperty('minWebviewBridgeVersion')) {
|
|
243
359
|
this.SDKConfig.minWebviewBridgeVersion =
|
package/src/types.js
CHANGED
|
@@ -361,6 +361,11 @@ var ApplicationTransitionType = {
|
|
|
361
361
|
AppInit: 1,
|
|
362
362
|
};
|
|
363
363
|
|
|
364
|
+
const Environment = {
|
|
365
|
+
Production: 'production',
|
|
366
|
+
Development: 'development',
|
|
367
|
+
};
|
|
368
|
+
|
|
364
369
|
export default {
|
|
365
370
|
MessageType: MessageType,
|
|
366
371
|
EventType: EventType,
|
|
@@ -371,4 +376,5 @@ export default {
|
|
|
371
376
|
ProductActionType: ProductActionType,
|
|
372
377
|
PromotionActionType: PromotionActionType,
|
|
373
378
|
TriggerUploadType: TriggerUploadType,
|
|
379
|
+
Environment,
|
|
374
380
|
};
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import slugify from 'slugify';
|
|
2
|
+
|
|
1
3
|
type valueof<T> = T[keyof T];
|
|
2
4
|
|
|
5
|
+
// Placeholder for Dictionary-like Types
|
|
6
|
+
export type Dictionary<V = any> = Record<string, V>;
|
|
7
|
+
|
|
3
8
|
const inArray = (items: any[], name: string): boolean => {
|
|
4
9
|
let i = 0;
|
|
5
10
|
|
|
@@ -44,6 +49,16 @@ const parseNumber = (value: string | number): number => {
|
|
|
44
49
|
return isNaN(floatValue) ? 0 : floatValue;
|
|
45
50
|
};
|
|
46
51
|
|
|
52
|
+
const parseStringOrNumber = (
|
|
53
|
+
value: string | number
|
|
54
|
+
): string | number | null => {
|
|
55
|
+
if (isStringOrNumber(value)) {
|
|
56
|
+
return value;
|
|
57
|
+
} else {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
47
62
|
// FIXME: REFACTOR for V3
|
|
48
63
|
// only used in store.js to sanitize server-side formatting of
|
|
49
64
|
// booleans when checking for `isDevelopmentMode`
|
|
@@ -70,6 +85,17 @@ const converted = (s: string): string => {
|
|
|
70
85
|
return s;
|
|
71
86
|
};
|
|
72
87
|
|
|
88
|
+
const isString = (value: any): boolean => typeof value === 'string';
|
|
89
|
+
const isNumber = (value: any): boolean => typeof value === 'number';
|
|
90
|
+
const isFunction = (fn: any): boolean => typeof fn === 'function';
|
|
91
|
+
|
|
92
|
+
// TODO: Refactor this to a regex
|
|
93
|
+
const isDataPlanSlug = (str: string): boolean =>
|
|
94
|
+
isString(str) && str === slugify(str);
|
|
95
|
+
|
|
96
|
+
const isStringOrNumber = (value: any): boolean =>
|
|
97
|
+
isString(value) || isNumber(value);
|
|
98
|
+
|
|
73
99
|
export {
|
|
74
100
|
valueof,
|
|
75
101
|
converted,
|
|
@@ -77,6 +103,12 @@ export {
|
|
|
77
103
|
findKeyInObject,
|
|
78
104
|
inArray,
|
|
79
105
|
isObject,
|
|
106
|
+
isStringOrNumber,
|
|
80
107
|
parseNumber,
|
|
108
|
+
parseStringOrNumber,
|
|
81
109
|
returnConvertedBoolean,
|
|
110
|
+
isString,
|
|
111
|
+
isNumber,
|
|
112
|
+
isFunction,
|
|
113
|
+
isDataPlanSlug,
|
|
82
114
|
};
|
package/src/validators.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import Types from './types';
|
|
2
|
-
import { isObject } from './utils';
|
|
2
|
+
import { isFunction, isNumber, isObject, isStringOrNumber, valueof } from './utils';
|
|
3
3
|
import Constants from './constants';
|
|
4
4
|
import { IdentityApiData } from '@mparticle/web-sdk';
|
|
5
|
-
import { valueof } from './utils';
|
|
6
5
|
|
|
7
6
|
type IdentityAPIMethod = 'login' | 'logout' | 'identify' | 'modify';
|
|
8
7
|
|
|
@@ -12,10 +11,17 @@ type ValidationIdentitiesReturn = {
|
|
|
12
11
|
};
|
|
13
12
|
|
|
14
13
|
const Validators = {
|
|
14
|
+
// From ./utils
|
|
15
|
+
// Utility Functions for backwards compatability
|
|
16
|
+
isNumber,
|
|
17
|
+
isFunction,
|
|
18
|
+
isStringOrNumber,
|
|
19
|
+
|
|
15
20
|
isValidAttributeValue: function(value: any): boolean {
|
|
16
21
|
return value !== undefined && !isObject(value) && !Array.isArray(value);
|
|
17
22
|
},
|
|
18
23
|
|
|
24
|
+
// Validator Functions
|
|
19
25
|
// Neither null nor undefined can be a valid Key
|
|
20
26
|
isValidKeyValue: function(key: any): boolean {
|
|
21
27
|
return Boolean(
|
|
@@ -26,18 +32,6 @@ const Validators = {
|
|
|
26
32
|
);
|
|
27
33
|
},
|
|
28
34
|
|
|
29
|
-
isStringOrNumber: function(value: any): boolean {
|
|
30
|
-
return typeof value === 'string' || typeof value === 'number';
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
isNumber: function(value: any): boolean {
|
|
34
|
-
return typeof value === 'number';
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
isFunction: (fn: any): boolean => {
|
|
38
|
-
return typeof fn === 'function';
|
|
39
|
-
},
|
|
40
|
-
|
|
41
35
|
validateIdentities: function(
|
|
42
36
|
identityApiData: IdentityApiData,
|
|
43
37
|
method?: IdentityAPIMethod
|