@mparticle/web-sdk 2.15.4 → 2.16.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-sdk",
3
- "version": "2.15.4",
3
+ "version": "2.16.1",
4
4
  "description": "mParticle core SDK for web applications",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -27,7 +27,6 @@
27
27
  "build:npm": "cross-env ENVIRONMENT=prod BUILD=cjs rollup --config rollup.config.js",
28
28
  "build:esm": "cross-env ENVIRONMENT=prod BUILD=esm rollup --config rollup.config.js",
29
29
  "build:stub": "cross-env ENVIRONMENT=prod BUILD=stub rollup --config rollup.config.js",
30
- "build:docs": "yuidoc src/",
31
30
  "build:snippet": "uglifyjs snippet.js -nm -o snippet.min.js",
32
31
  "build:browserify:cjs": "browserify test/integrations/cjs/browserify/index.js -o test/integrations/cjs/dist/browserify-output.js && npm run test:karma:browserify:cjs",
33
32
  "build:rollup:cjs": "rollup --config test/integrations/cjs/rollup/rollup.config.js && npm run test:karma:rollup:cjs",
@@ -68,7 +67,7 @@
68
67
  "@babel/preset-env": "^7.6.0",
69
68
  "@babel/preset-typescript": "^7.6.0",
70
69
  "@mparticle/data-planning-models": "^0.1.0",
71
- "@mparticle/event-models": "^1.1.2",
70
+ "@mparticle/event-models": "^1.1.4",
72
71
  "@rollup/plugin-json": "^4.1.0",
73
72
  "@semantic-release/changelog": "^5.0.1",
74
73
  "@semantic-release/exec": "^5.0.0",
@@ -112,8 +111,7 @@
112
111
  "typescript": "^4.2.4",
113
112
  "uglify-js": "^3.4.9",
114
113
  "webpack": "^5.36.2",
115
- "webpack-cli": "^4.6.0",
116
- "yuidocjs": "^0.10.2"
114
+ "webpack-cli": "^4.6.0"
117
115
  },
118
116
  "dependencies": {
119
117
  "@babel/runtime": "^7.6.0",
@@ -131,9 +131,16 @@ export class BatchUploader {
131
131
  eventsBySession.set(sdkEvent.SessionId, events);
132
132
  }
133
133
  for (const entry of Array.from(eventsBySession.entries())) {
134
- const upload = convertEvents(mpid, entry[1], mpInstance);
135
- if (upload) {
136
- newUploads.push(upload);
134
+ let uploadBatchObject = convertEvents(mpid, entry[1], mpInstance);
135
+ const onCreateBatchCallback = mpInstance._Store.SDKConfig.onCreateBatch;
136
+
137
+ if (onCreateBatchCallback) {
138
+ uploadBatchObject = onCreateBatchCallback(uploadBatchObject);
139
+ uploadBatchObject.mutated = true;
140
+ }
141
+
142
+ if (uploadBatchObject) {
143
+ newUploads.push(uploadBatchObject);
137
144
  }
138
145
  }
139
146
  }
@@ -1,6 +1,6 @@
1
1
  import { version } from '../package.json';
2
2
 
3
- var Constants = {
3
+ const Constants = {
4
4
  sdkVersion: version,
5
5
  sdkVendor: 'mparticle',
6
6
  platform: 'web',
@@ -164,6 +164,6 @@ var Constants = {
164
164
  EventBatchingIntervalMillis: 'eventBatchingIntervalMillis',
165
165
  },
166
166
  DefaultInstance: 'default_instance',
167
- };
167
+ } as const;
168
168
 
169
169
  export default Constants;
package/src/helpers.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import Types from './types';
2
2
  import Constants from './constants';
3
3
  import Slugify from 'slugify';
4
+ import * as utils from './utils';
5
+ import Validators from './validators';
4
6
 
5
- var StorageNames = Constants.StorageNames,
6
- pluses = /\+/g;
7
+ var StorageNames = Constants.StorageNames;
7
8
 
8
9
  export default function Helpers(mpInstance) {
9
10
  var self = this;
@@ -19,14 +20,6 @@ export default function Helpers(mpInstance) {
19
20
  return false;
20
21
  };
21
22
 
22
- this.returnConvertedBoolean = function(data) {
23
- if (data === 'false' || data === '0') {
24
- return false;
25
- } else {
26
- return Boolean(data);
27
- }
28
- };
29
-
30
23
  this.getFeatureFlag = function(feature) {
31
24
  if (mpInstance._Store.SDKConfig.flags.hasOwnProperty(feature)) {
32
25
  return mpInstance._Store.SDKConfig.flags[feature];
@@ -250,26 +243,6 @@ export default function Helpers(mpInstance) {
250
243
  return target;
251
244
  };
252
245
 
253
- this.isObject = function(value) {
254
- var objType = Object.prototype.toString.call(value);
255
-
256
- return objType === '[object Object]' || objType === '[object Error]';
257
- };
258
-
259
- this.inArray = function(items, name) {
260
- var i = 0;
261
-
262
- if (Array.prototype.indexOf) {
263
- return items.indexOf(name, 0) >= 0;
264
- } else {
265
- for (var n = items.length; i < n; i++) {
266
- if (i in items && items[i] === name) {
267
- return true;
268
- }
269
- }
270
- }
271
- };
272
-
273
246
  this.createServiceUrl = function(secureServiceUrl, devToken) {
274
247
  var serviceScheme =
275
248
  window.mParticle && mpInstance._Store.SDKConfig.forceHttps
@@ -415,36 +388,6 @@ export default function Helpers(mpInstance) {
415
388
  return filteredUserAttributes;
416
389
  };
417
390
 
418
- this.findKeyInObject = function(obj, key) {
419
- if (key && obj) {
420
- for (var prop in obj) {
421
- if (
422
- obj.hasOwnProperty(prop) &&
423
- prop.toLowerCase() === key.toLowerCase()
424
- ) {
425
- return prop;
426
- }
427
- }
428
- }
429
-
430
- return null;
431
- };
432
-
433
- this.decoded = function(s) {
434
- return decodeURIComponent(s.replace(pluses, ' '));
435
- };
436
-
437
- this.converted = function(s) {
438
- if (s.indexOf('"') === 0) {
439
- s = s
440
- .slice(1, -1)
441
- .replace(/\\"/g, '"')
442
- .replace(/\\\\/g, '\\');
443
- }
444
-
445
- return s;
446
- };
447
-
448
391
  this.isEventType = function(type) {
449
392
  for (var prop in Types.EventType) {
450
393
  if (Types.EventType.hasOwnProperty(prop)) {
@@ -456,16 +399,8 @@ export default function Helpers(mpInstance) {
456
399
  return false;
457
400
  };
458
401
 
459
- this.parseNumber = function(value) {
460
- if (isNaN(value) || !isFinite(value)) {
461
- return 0;
462
- }
463
- var floatValue = parseFloat(value);
464
- return isNaN(floatValue) ? 0 : floatValue;
465
- };
466
-
467
402
  this.parseStringOrNumber = function(value) {
468
- if (self.Validators.isStringOrNumber(value)) {
403
+ if (Validators.isStringOrNumber(value)) {
469
404
  return value;
470
405
  } else {
471
406
  return null;
@@ -531,157 +466,6 @@ export default function Helpers(mpInstance) {
531
466
  return sanitizedAttrs;
532
467
  };
533
468
 
534
- this.Validators = {
535
- isValidAttributeValue: function(value) {
536
- return (
537
- value !== undefined &&
538
- !self.isObject(value) &&
539
- !Array.isArray(value)
540
- );
541
- },
542
-
543
- // Neither null nor undefined can be a valid Key
544
- isValidKeyValue: function(key) {
545
- return Boolean(key && !self.isObject(key) && !Array.isArray(key));
546
- },
547
-
548
- isStringOrNumber: function(value) {
549
- return typeof value === 'string' || typeof value === 'number';
550
- },
551
-
552
- isNumber: function(value) {
553
- return typeof value === 'number';
554
- },
555
-
556
- isFunction: function(fn) {
557
- return typeof fn === 'function';
558
- },
559
-
560
- validateIdentities: function(identityApiData, method) {
561
- var validIdentityRequestKeys = {
562
- userIdentities: 1,
563
- onUserAlias: 1,
564
- copyUserAttributes: 1,
565
- };
566
- if (identityApiData) {
567
- if (method === 'modify') {
568
- if (
569
- (self.isObject(identityApiData.userIdentities) &&
570
- !Object.keys(identityApiData.userIdentities)
571
- .length) ||
572
- !self.isObject(identityApiData.userIdentities)
573
- ) {
574
- return {
575
- valid: false,
576
- error:
577
- Constants.Messages.ValidationMessages
578
- .ModifyIdentityRequestUserIdentitiesPresent,
579
- };
580
- }
581
- }
582
- for (var key in identityApiData) {
583
- if (identityApiData.hasOwnProperty(key)) {
584
- if (!validIdentityRequestKeys[key]) {
585
- return {
586
- valid: false,
587
- error:
588
- Constants.Messages.ValidationMessages
589
- .IdentityRequesetInvalidKey,
590
- };
591
- }
592
- if (
593
- key === 'onUserAlias' &&
594
- !mpInstance._Helpers.Validators.isFunction(
595
- identityApiData[key]
596
- )
597
- ) {
598
- return {
599
- valid: false,
600
- error:
601
- Constants.Messages.ValidationMessages
602
- .OnUserAliasType +
603
- typeof identityApiData[key],
604
- };
605
- }
606
- }
607
- }
608
- if (Object.keys(identityApiData).length === 0) {
609
- return {
610
- valid: true,
611
- };
612
- } else {
613
- // identityApiData.userIdentities can't be undefined
614
- if (identityApiData.userIdentities === undefined) {
615
- return {
616
- valid: false,
617
- error:
618
- Constants.Messages.ValidationMessages
619
- .UserIdentities,
620
- };
621
- // identityApiData.userIdentities can be null, but if it isn't null or undefined (above conditional), it must be an object
622
- } else if (
623
- identityApiData.userIdentities !== null &&
624
- !self.isObject(identityApiData.userIdentities)
625
- ) {
626
- return {
627
- valid: false,
628
- error:
629
- Constants.Messages.ValidationMessages
630
- .UserIdentities,
631
- };
632
- }
633
- if (
634
- self.isObject(identityApiData.userIdentities) &&
635
- Object.keys(identityApiData.userIdentities).length
636
- ) {
637
- for (var identityType in identityApiData.userIdentities) {
638
- if (
639
- identityApiData.userIdentities.hasOwnProperty(
640
- identityType
641
- )
642
- ) {
643
- if (
644
- Types.IdentityType.getIdentityType(
645
- identityType
646
- ) === false
647
- ) {
648
- return {
649
- valid: false,
650
- error:
651
- Constants.Messages
652
- .ValidationMessages
653
- .UserIdentitiesInvalidKey,
654
- };
655
- }
656
- if (
657
- !(
658
- typeof identityApiData.userIdentities[
659
- identityType
660
- ] === 'string' ||
661
- identityApiData.userIdentities[
662
- identityType
663
- ] === null
664
- )
665
- ) {
666
- return {
667
- valid: false,
668
- error:
669
- Constants.Messages
670
- .ValidationMessages
671
- .UserIdentitiesInvalidValues,
672
- };
673
- }
674
- }
675
- }
676
- }
677
- }
678
- }
679
- return {
680
- valid: true,
681
- };
682
- },
683
- };
684
-
685
469
  this.isDelayedByIntegration = function(
686
470
  delayedIntegrations,
687
471
  timeoutStart,
@@ -724,4 +508,16 @@ export default function Helpers(mpInstance) {
724
508
  this.isSlug = function(str) {
725
509
  return str === Slugify(str);
726
510
  };
511
+
512
+ // Utility Functions
513
+ this.converted = utils.converted;
514
+ this.findKeyInObject = utils.findKeyInObject;
515
+ this.parseNumber = utils.parseNumber;
516
+ this.inArray = utils.inArray;
517
+ this.isObject = utils.isObject;
518
+ this.decoded = utils.decoded;
519
+ this.returnConvertedBoolean = utils.returnConvertedBoolean;
520
+
521
+ // Imported Validators
522
+ this.Validators = Validators;
727
523
  }
@@ -1218,6 +1218,14 @@ function completeSDKInitialization(apiKey, config, mpInstance) {
1218
1218
  mpInstance._Forwarders = new Forwarders(mpInstance, kitBlocker);
1219
1219
  if (config.flags) {
1220
1220
  if (config.flags.hasOwnProperty(Constants.FeatureFlags.EventsV3)) {
1221
+ // TODO: Remove this after 8/12/2022
1222
+ if (config.flags[Constants.FeatureFlags.EventsV3] !== '100') {
1223
+ var message =
1224
+ 'mParticle will be enabling Event Batching for all customers on July 12, 2022. ' +
1225
+ 'For more details, please see our docs: https://docs.mparticle.com/developers/sdk/web/getting-started/';
1226
+ mpInstance.Logger.warning(message);
1227
+ }
1228
+
1221
1229
  mpInstance._Store.SDKConfig.flags[Constants.FeatureFlags.EventsV3] =
1222
1230
  config.flags[Constants.FeatureFlags.EventsV3];
1223
1231
  }
@@ -24,6 +24,7 @@ export interface SDKEvent {
24
24
  CustomFlags?: { [key: string]: string };
25
25
  AppVersion?: string;
26
26
  AppName?: string;
27
+ Package?: string;
27
28
  ConsentState?: SDKConsentState;
28
29
  IntegrationAttributes?: { [key: string]: { [key: string]: string } };
29
30
  ProductAction?: SDKProductAction;
@@ -142,8 +143,10 @@ export interface SDKConfig {
142
143
  warning?(msg)
143
144
  verbose?(msg)
144
145
  };
146
+ onCreateBatch(batch: EventsApi.Batch): EventsApi.Batch;
145
147
  dataPlan: DataPlanConfig;
146
148
  appVersion?: string;
149
+ package?: string;
147
150
  flags?: { [key: string]: string | number };
148
151
  kitConfigs: any;
149
152
  appName?: string;
@@ -202,6 +205,7 @@ export interface SDKConfigApi {
202
205
  v3SecureServiceUrl?: string;
203
206
  isDevelopmentMode: boolean;
204
207
  appVersion?: string;
208
+ onCreateBatch(batch: EventsApi.Batch): EventsApi.Batch
205
209
  }
206
210
  export interface MParticleUser {
207
211
  getMPID(): string;
@@ -55,6 +55,7 @@ export function convertEvents(
55
55
  application_info: {
56
56
  application_version: lastEvent.AppVersion,
57
57
  application_name: lastEvent.AppName,
58
+ package: lastEvent.Package,
58
59
  },
59
60
  device_info: {
60
61
  platform: EventsApi.DeviceInformationPlatformEnum.web,
@@ -207,6 +207,7 @@ export default function ServerModel(mpInstance) {
207
207
  ExpandedEventCount: 0,
208
208
  AppVersion: mpInstance.getAppVersion(),
209
209
  AppName: mpInstance.getAppName(),
210
+ Package: mpInstance._Store.SDKConfig.package,
210
211
  ClientGeneratedId: mpInstance._Store.clientId,
211
212
  DeviceId: mpInstance._Store.deviceId,
212
213
  IntegrationAttributes: mpInstance._Store.integrationAttributes,
package/src/store.js CHANGED
@@ -154,6 +154,10 @@ export default function Store(config, mpInstance) {
154
154
  this.SDKConfig.appName = config.appName;
155
155
  }
156
156
 
157
+ if (config.hasOwnProperty('package')) {
158
+ this.SDKConfig.package = config.package;
159
+ }
160
+
157
161
  if (config.hasOwnProperty('integrationDelayTimeout')) {
158
162
  this.SDKConfig.integrationDelayTimeout =
159
163
  config.integrationDelayTimeout;
@@ -264,6 +268,18 @@ export default function Store(config, mpInstance) {
264
268
  }
265
269
  }
266
270
 
271
+ if (config.hasOwnProperty('onCreateBatch')) {
272
+ if (typeof config.onCreateBatch === 'function') {
273
+ this.SDKConfig.onCreateBatch = config.onCreateBatch;
274
+ } else {
275
+ mpInstance.Logger.error(
276
+ 'config.onCreateBatch must be a function'
277
+ );
278
+ // set to undefined because all items are set on createSDKConfig
279
+ this.SDKConfig.onCreateBatch = undefined;
280
+ }
281
+ }
282
+
267
283
  if (!config.hasOwnProperty('flags')) {
268
284
  this.SDKConfig.flags = {};
269
285
  }
package/src/utils.ts ADDED
@@ -0,0 +1,82 @@
1
+ type valueof<T> = T[keyof T];
2
+
3
+ const inArray = (items: any[], name: string): boolean => {
4
+ const i = 0;
5
+
6
+ if (Array.prototype.indexOf) {
7
+ return items.indexOf(name, 0) >= 0;
8
+ } else {
9
+ for (var n = items.length; i < n; i++) {
10
+ if (i in items && items[i] === name) {
11
+ return true;
12
+ }
13
+ }
14
+ }
15
+
16
+ return false;
17
+ };
18
+
19
+ const findKeyInObject = (obj: any, key: string): string => {
20
+ if (key && obj) {
21
+ for (var prop in obj) {
22
+ if (
23
+ obj.hasOwnProperty(prop) &&
24
+ prop.toLowerCase() === key.toLowerCase()
25
+ ) {
26
+ return prop;
27
+ }
28
+ }
29
+ }
30
+
31
+ return null;
32
+ };
33
+
34
+ const isObject = (value: any): boolean => {
35
+ var objType = Object.prototype.toString.call(value);
36
+ return objType === '[object Object]' || objType === '[object Error]';
37
+ };
38
+
39
+ const parseNumber = (value: string | number): number => {
40
+ if (isNaN(value as number) || !isFinite(value as number)) {
41
+ return 0;
42
+ }
43
+ var floatValue = parseFloat(value as string);
44
+ return isNaN(floatValue) ? 0 : floatValue;
45
+ };
46
+
47
+ // FIXME: REFACTOR for V3
48
+ // only used in store.js to sanitize server-side formatting of
49
+ // booleans when checking for `isDevelopmentMode`
50
+ // Should be removed in v3
51
+ const returnConvertedBoolean = (data: string | boolean | number) => {
52
+ if (data === 'false' || data === '0') {
53
+ return false;
54
+ } else {
55
+ return Boolean(data);
56
+ }
57
+ };
58
+
59
+ const decoded = (s: string): string =>
60
+ decodeURIComponent(s.replace(/\+/g, ' '));
61
+
62
+ const converted = (s: string): string => {
63
+ if (s.indexOf('"') === 0) {
64
+ s = s
65
+ .slice(1, -1)
66
+ .replace(/\\"/g, '"')
67
+ .replace(/\\\\/g, '\\');
68
+ }
69
+
70
+ return s;
71
+ };
72
+
73
+ export {
74
+ valueof,
75
+ converted,
76
+ decoded,
77
+ findKeyInObject,
78
+ inArray,
79
+ isObject,
80
+ parseNumber,
81
+ returnConvertedBoolean,
82
+ };
@@ -0,0 +1,165 @@
1
+ import Types from './types';
2
+ import { isObject } from './utils';
3
+ import Constants from './constants';
4
+ import { IdentityApiData } from '@mparticle/web-sdk';
5
+ import { valueof } from './utils';
6
+
7
+ type IdentityAPIMethod = 'login' | 'logout' | 'identify' | 'modify';
8
+
9
+ type ValidationIdentitiesReturn = {
10
+ valid: boolean;
11
+ error?: valueof<typeof Constants.Messages.ValidationMessages>;
12
+ };
13
+
14
+ const Validators = {
15
+ isValidAttributeValue: function(value: any): boolean {
16
+ return value !== undefined && !isObject(value) && !Array.isArray(value);
17
+ },
18
+
19
+ // Neither null nor undefined can be a valid Key
20
+ isValidKeyValue: function(key: any): boolean {
21
+ return Boolean(
22
+ key &&
23
+ !isObject(key) &&
24
+ !Array.isArray(key) &&
25
+ !this.isFunction(key)
26
+ );
27
+ },
28
+
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
+ validateIdentities: function(
42
+ identityApiData: IdentityApiData,
43
+ method?: IdentityAPIMethod
44
+ ): ValidationIdentitiesReturn {
45
+ var validIdentityRequestKeys = {
46
+ userIdentities: 1,
47
+ onUserAlias: 1,
48
+ copyUserAttributes: 1,
49
+ };
50
+ if (identityApiData) {
51
+ if (method === 'modify') {
52
+ if (
53
+ (isObject(identityApiData.userIdentities) &&
54
+ !Object.keys(identityApiData.userIdentities).length) ||
55
+ !isObject(identityApiData.userIdentities)
56
+ ) {
57
+ return {
58
+ valid: false,
59
+ error:
60
+ Constants.Messages.ValidationMessages
61
+ .ModifyIdentityRequestUserIdentitiesPresent,
62
+ };
63
+ }
64
+ }
65
+ for (var key in identityApiData) {
66
+ if (identityApiData.hasOwnProperty(key)) {
67
+ if (!validIdentityRequestKeys[key]) {
68
+ return {
69
+ valid: false,
70
+ error:
71
+ Constants.Messages.ValidationMessages
72
+ .IdentityRequesetInvalidKey,
73
+ };
74
+ }
75
+ if (
76
+ key === 'onUserAlias' &&
77
+ !Validators.isFunction(identityApiData[key])
78
+ ) {
79
+ return {
80
+ valid: false,
81
+ // FIXME: Validates type safety
82
+ error:
83
+ Constants.Messages.ValidationMessages
84
+ .OnUserAliasType +
85
+ typeof identityApiData[key],
86
+ };
87
+ }
88
+ }
89
+ }
90
+ if (Object.keys(identityApiData).length === 0) {
91
+ return {
92
+ valid: true,
93
+ };
94
+ } else {
95
+ // identityApiData.userIdentities can't be undefined
96
+ if (identityApiData.userIdentities === undefined) {
97
+ return {
98
+ valid: false,
99
+ error:
100
+ Constants.Messages.ValidationMessages
101
+ .UserIdentities,
102
+ };
103
+ // identityApiData.userIdentities can be null, but if it isn't null or undefined (above conditional), it must be an object
104
+ } else if (
105
+ identityApiData.userIdentities !== null &&
106
+ !isObject(identityApiData.userIdentities)
107
+ ) {
108
+ return {
109
+ valid: false,
110
+ error:
111
+ Constants.Messages.ValidationMessages
112
+ .UserIdentities,
113
+ };
114
+ }
115
+ if (
116
+ isObject(identityApiData.userIdentities) &&
117
+ Object.keys(identityApiData.userIdentities).length
118
+ ) {
119
+ for (var identityType in identityApiData.userIdentities) {
120
+ if (
121
+ identityApiData.userIdentities.hasOwnProperty(
122
+ identityType
123
+ )
124
+ ) {
125
+ if (
126
+ Types.IdentityType.getIdentityType(
127
+ identityType
128
+ ) === false
129
+ ) {
130
+ return {
131
+ valid: false,
132
+ error:
133
+ Constants.Messages.ValidationMessages
134
+ .UserIdentitiesInvalidKey,
135
+ };
136
+ }
137
+ if (
138
+ !(
139
+ typeof identityApiData.userIdentities[
140
+ identityType
141
+ ] === 'string' ||
142
+ identityApiData.userIdentities[
143
+ identityType
144
+ ] === null
145
+ )
146
+ ) {
147
+ return {
148
+ valid: false,
149
+ error:
150
+ Constants.Messages.ValidationMessages
151
+ .UserIdentitiesInvalidValues,
152
+ };
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
158
+ }
159
+ return {
160
+ valid: true,
161
+ };
162
+ },
163
+ };
164
+
165
+ export default Validators;