@mparticle/web-sdk 2.18.2 → 2.19.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.
@@ -1,12 +1,12 @@
1
1
  import * as EventsApi from '@mparticle/event-models';
2
- import { Batch } from '@mparticle/event-models';
3
- import { DataPlanVersion, DataPlan } from '@mparticle/data-planning-models';
2
+ import { DataPlanVersion } from '@mparticle/data-planning-models';
4
3
  import { MPConfiguration, IdentityApiData } from '@mparticle/web-sdk';
5
- import { IStore, SDKConfig } from './store';
4
+ import { IStore } from './store';
6
5
  import Validators from './validators';
7
6
  import { Dictionary } from './utils';
8
7
  import { IServerModel } from './serverModel';
9
8
  import { IKitConfigs } from './configAPIClient';
9
+ import { SDKConsentApi, SDKConsentState } from './consent.interfaces';
10
10
 
11
11
  // TODO: Resolve this with version in @mparticle/web-sdk
12
12
  export type SDKEventCustomFlags = Dictionary<any>;
@@ -131,12 +131,17 @@ export interface MParticleWebSDK {
131
131
  Logger: SDKLoggerApi;
132
132
  _APIClient: any; // TODO: Set up API Client
133
133
  _Store: IStore;
134
+ _Forwarders: any;
134
135
  _Helpers: SDKHelpersApi;
135
136
  config: SDKInitConfig;
136
137
  _ServerModel: IServerModel;
137
138
  _SessionManager: any; // TODO: Set up Session Manager
138
- _Consent: any; // TODO: Set up Consent SDK
139
- _resetForTests(MPConfig?: SDKConfig): void;
139
+ _Consent: SDKConsentApi;
140
+ Consent: SDKConsentApi;
141
+ _NativeSdkHelpers: any; // TODO: Set up API
142
+ _Persistence: any; // TODO: Set up Persistence API
143
+ _preInit: any; // TODO: Set up API
144
+ _resetForTests(MPConfig?: SDKInitConfig): void;
140
145
  init(apiKey: string, config: SDKInitConfig, instanceName?: string): void;
141
146
  getAppName(): string;
142
147
  getAppVersion(): string;
@@ -220,12 +225,19 @@ export interface SDKIdentityApi {
220
225
  export interface SDKHelpersApi {
221
226
  createServiceUrl(arg0: string, arg1: string): void;
222
227
  createXHR?(cb: () => void): XMLHttpRequest;
223
- extend(...args: any[]);
224
- parseNumber(value: string | number): number;
228
+ extend?(...args: any[]);
229
+ parseNumber?(value: string | number): number;
225
230
  generateUniqueId();
226
- isObject(item: any);
231
+ getFeatureFlag?(feature: string); // TODO: Feature Constants should be converted to enum
232
+ getRampNumber?(deviceId: string): number;
233
+ isDelayedByIntegration?(
234
+ delayedIntegrations: Dictionary<boolean>,
235
+ timeoutStart: number,
236
+ now: number
237
+ ): boolean;
238
+ isObject?(item: any);
227
239
  returnConvertedBoolean(data: string | boolean | number): boolean;
228
- sanitizeAttributes(
240
+ sanitizeAttributes?(
229
241
  attrs: Dictionary<string>,
230
242
  name: string
231
243
  ): Dictionary<string> | null;
@@ -254,6 +266,9 @@ export interface SDKConfigApi {
254
266
  appVersion?: string;
255
267
  onCreateBatch(batch: EventsApi.Batch): EventsApi.Batch;
256
268
  }
269
+
270
+ // FIXME: Resolve with User in @types/mparticle-web-sdk
271
+ // https://go.mparticle.com/work/SQDSDKS-5033
257
272
  export interface MParticleUser {
258
273
  getMPID(): string;
259
274
  getConsentState(): any; // FIXME:
@@ -261,25 +276,6 @@ export interface MParticleUser {
261
276
  getUserIdentities(): IdentityApiData; // FIXME: Is this correct?
262
277
  }
263
278
 
264
- export interface SDKConsentState {
265
- getGDPRConsentState(): SDKGDPRConsentState;
266
- getCCPAConsentState(): SDKCCPAConsentState;
267
- }
268
-
269
- export interface SDKGDPRConsentState {
270
- [key: string]: SDKConsentStateData;
271
- }
272
-
273
- export interface SDKConsentStateData {
274
- Consented: boolean;
275
- Timestamp?: number;
276
- ConsentDocument?: string;
277
- Location?: string;
278
- HardwareId?: string;
279
- }
280
-
281
- export interface SDKCCPAConsentState extends SDKConsentStateData {}
282
-
283
279
  export interface SDKUserIdentityChangeData {
284
280
  New: Identity;
285
281
  Old: Identity;
@@ -1,9 +1,6 @@
1
1
  import {
2
2
  SDKEvent,
3
- SDKConsentState,
4
- SDKGDPRConsentState,
5
3
  SDKGeoLocation,
6
- SDKCCPAConsentState,
7
4
  SDKProduct,
8
5
  SDKPromotion,
9
6
  SDKUserIdentity,
@@ -12,7 +9,13 @@ import {
12
9
  SDKIdentityTypeEnum,
13
10
  } from './sdkRuntimeModels';
14
11
  import * as EventsApi from '@mparticle/event-models';
12
+ import {
13
+ SDKConsentState,
14
+ SDKGDPRConsentState,
15
+ SDKCCPAConsentState,
16
+ } from './consent.interfaces';
15
17
  import Types from './types';
18
+ import { isEmpty } from './utils';
16
19
 
17
20
  export function convertEvents(
18
21
  mpid: string,
@@ -26,6 +29,8 @@ export function convertEvents(
26
29
  return null;
27
30
  }
28
31
 
32
+ const user = mpInstance.Identity.getCurrentUser();
33
+
29
34
  const uploadEvents: EventsApi.BaseEvent[] = [];
30
35
  let lastEvent: SDKEvent = null;
31
36
  for (const sdkEvent of sdkEvents) {
@@ -42,6 +47,15 @@ export function convertEvents(
42
47
  return null;
43
48
  }
44
49
 
50
+ let currentConsentState: SDKConsentState = null;
51
+
52
+ // Add the consent state from either the Last Event or the user
53
+ if (!isEmpty(lastEvent.ConsentState)) {
54
+ currentConsentState = lastEvent.ConsentState;
55
+ } else if (!isEmpty(user)) {
56
+ currentConsentState = user.getConsentState();
57
+ }
58
+
45
59
  const upload: EventsApi.Batch = {
46
60
  source_request_id: mpInstance._Helpers.generateUniqueId(),
47
61
  mpid,
@@ -64,7 +78,7 @@ export function convertEvents(
64
78
  },
65
79
  user_attributes: lastEvent.UserAttributes,
66
80
  user_identities: convertUserIdentities(lastEvent.UserIdentities),
67
- consent_state: convertConsentState(lastEvent.ConsentState),
81
+ consent_state: convertConsentState(currentConsentState),
68
82
  integration_attributes: lastEvent.IntegrationAttributes,
69
83
  };
70
84
 
@@ -82,7 +96,7 @@ export function convertEvents(
82
96
  export function convertConsentState(
83
97
  sdkConsentState?: SDKConsentState
84
98
  ): EventsApi.ConsentState | null {
85
- if (!sdkConsentState) {
99
+ if (isEmpty(sdkConsentState)) {
86
100
  return null;
87
101
  }
88
102
  const consentState: EventsApi.ConsentState = {
@@ -327,7 +341,8 @@ export function convertPromotionAction(
327
341
  return null;
328
342
  }
329
343
  const promotionAction: EventsApi.PromotionAction = {
330
- action: sdkEvent.PromotionAction.PromotionActionType as EventsApi.PromotionActionActionEnum,
344
+ action: sdkEvent.PromotionAction
345
+ .PromotionActionType as EventsApi.PromotionActionActionEnum,
331
346
  promotions: convertPromotions(sdkEvent.PromotionAction.PromotionList),
332
347
  };
333
348
  return promotionAction;
@@ -388,9 +403,8 @@ export function convertShoppingCart(
388
403
  export function convertCommerceEvent(
389
404
  sdkEvent: SDKEvent
390
405
  ): EventsApi.CommerceEvent {
391
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
392
- sdkEvent
393
- );
406
+ const commonEventData: EventsApi.CommonEventData =
407
+ convertBaseEventData(sdkEvent);
394
408
  let commerceEventData: EventsApi.CommerceEventData = {
395
409
  custom_flags: sdkEvent.CustomFlags,
396
410
  product_action: convertProductAction(sdkEvent),
@@ -409,9 +423,8 @@ export function convertCommerceEvent(
409
423
  export function convertCrashReportEvent(
410
424
  sdkEvent: SDKEvent
411
425
  ): EventsApi.CrashReportEvent {
412
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
413
- sdkEvent
414
- );
426
+ const commonEventData: EventsApi.CommonEventData =
427
+ convertBaseEventData(sdkEvent);
415
428
  let crashReportEventData: EventsApi.CrashReportEventData = {
416
429
  message: sdkEvent.EventName,
417
430
  };
@@ -425,9 +438,8 @@ export function convertCrashReportEvent(
425
438
  export function convertAST(
426
439
  sdkEvent: SDKEvent
427
440
  ): EventsApi.ApplicationStateTransitionEvent {
428
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
429
- sdkEvent
430
- );
441
+ const commonEventData: EventsApi.CommonEventData =
442
+ convertBaseEventData(sdkEvent);
431
443
  let astEventData: EventsApi.ApplicationStateTransitionEventData = {
432
444
  application_transition_type:
433
445
  EventsApi
@@ -447,9 +459,8 @@ export function convertAST(
447
459
  export function convertSessionEndEvent(
448
460
  sdkEvent: SDKEvent
449
461
  ): EventsApi.SessionEndEvent {
450
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
451
- sdkEvent
452
- );
462
+ const commonEventData: EventsApi.CommonEventData =
463
+ convertBaseEventData(sdkEvent);
453
464
  let sessionEndEventData: EventsApi.SessionEndEventData = {
454
465
  session_duration_ms: sdkEvent.SessionLength,
455
466
  //note: External Events DTO does not support the session mpids array as of this time.
@@ -465,9 +476,8 @@ export function convertSessionEndEvent(
465
476
  export function convertSessionStartEvent(
466
477
  sdkEvent: SDKEvent
467
478
  ): EventsApi.SessionStartEvent {
468
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
469
- sdkEvent
470
- );
479
+ const commonEventData: EventsApi.CommonEventData =
480
+ convertBaseEventData(sdkEvent);
471
481
  let sessionStartEventData: EventsApi.SessionStartEventData = {};
472
482
  sessionStartEventData = Object.assign(
473
483
  sessionStartEventData,
@@ -482,9 +492,8 @@ export function convertSessionStartEvent(
482
492
  export function convertPageViewEvent(
483
493
  sdkEvent: SDKEvent
484
494
  ): EventsApi.ScreenViewEvent {
485
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
486
- sdkEvent
487
- );
495
+ const commonEventData: EventsApi.CommonEventData =
496
+ convertBaseEventData(sdkEvent);
488
497
  let screenViewEventData: EventsApi.ScreenViewEventData = {
489
498
  custom_flags: sdkEvent.CustomFlags,
490
499
  screen_name: sdkEvent.EventName,
@@ -497,9 +506,8 @@ export function convertPageViewEvent(
497
506
  }
498
507
 
499
508
  export function convertOptOutEvent(sdkEvent: SDKEvent): EventsApi.OptOutEvent {
500
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
501
- sdkEvent
502
- );
509
+ const commonEventData: EventsApi.CommonEventData =
510
+ convertBaseEventData(sdkEvent);
503
511
  let optOutEventData: EventsApi.OptOutEventData = {
504
512
  is_opted_out: sdkEvent.OptOut,
505
513
  };
@@ -511,9 +519,8 @@ export function convertOptOutEvent(sdkEvent: SDKEvent): EventsApi.OptOutEvent {
511
519
  }
512
520
 
513
521
  export function convertCustomEvent(sdkEvent: SDKEvent): EventsApi.CustomEvent {
514
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
515
- sdkEvent
516
- );
522
+ const commonEventData: EventsApi.CommonEventData =
523
+ convertBaseEventData(sdkEvent);
517
524
  let customEventData: EventsApi.CustomEventData = {
518
525
  custom_event_type: convertSdkEventType(
519
526
  sdkEvent.EventCategory
@@ -596,7 +603,7 @@ export function convertBaseEventData(
596
603
  session_start_unixtime_ms: sdkEvent.SessionStartDate,
597
604
  custom_attributes: sdkEvent.EventAttributes,
598
605
  location: convertSDKLocation(sdkEvent.Location),
599
- source_message_id: sdkEvent.SourceMessageId
606
+ source_message_id: sdkEvent.SourceMessageId,
600
607
  };
601
608
 
602
609
  return commonEventData;
@@ -617,9 +624,8 @@ export function convertSDKLocation(
617
624
  export function convertUserAttributeChangeEvent(
618
625
  sdkEvent: SDKEvent
619
626
  ): EventsApi.UserAttributeChangeEvent | null {
620
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
621
- sdkEvent
622
- );
627
+ const commonEventData: EventsApi.CommonEventData =
628
+ convertBaseEventData(sdkEvent);
623
629
  let userAttributeChangeEvent: EventsApi.UserAttributeChangeEventData = {
624
630
  user_attribute_name: sdkEvent.UserAttributeChanges.UserAttributeName,
625
631
  new: sdkEvent.UserAttributeChanges.New,
@@ -642,9 +648,8 @@ export function convertUserAttributeChangeEvent(
642
648
  export function convertUserIdentityChangeEvent(
643
649
  sdkEvent: SDKEvent
644
650
  ): EventsApi.UserIdentityChangeEvent | null {
645
- const commonEventData: EventsApi.CommonEventData = convertBaseEventData(
646
- sdkEvent
647
- );
651
+ const commonEventData: EventsApi.CommonEventData =
652
+ convertBaseEventData(sdkEvent);
648
653
 
649
654
  let userIdentityChangeEvent: EventsApi.UserIdentityChangeEventData = {
650
655
  new: {
@@ -683,48 +688,48 @@ export function convertUserIdentityTypeToServerIdentityType(
683
688
  ): EventsApi.IdentityType {
684
689
  switch (identityType) {
685
690
  case SDKIdentityTypeEnum.other:
686
- return EventsApi.IdentityTypeEnum.other
691
+ return EventsApi.IdentityTypeEnum.other;
687
692
  case SDKIdentityTypeEnum.customerId:
688
- return EventsApi.IdentityTypeEnum.customerId
693
+ return EventsApi.IdentityTypeEnum.customerId;
689
694
  case SDKIdentityTypeEnum.facebook:
690
- return EventsApi.IdentityTypeEnum.facebook
695
+ return EventsApi.IdentityTypeEnum.facebook;
691
696
  case SDKIdentityTypeEnum.twitter:
692
- return EventsApi.IdentityTypeEnum.twitter
697
+ return EventsApi.IdentityTypeEnum.twitter;
693
698
  case SDKIdentityTypeEnum.google:
694
- return EventsApi.IdentityTypeEnum.google
699
+ return EventsApi.IdentityTypeEnum.google;
695
700
  case SDKIdentityTypeEnum.microsoft:
696
- return EventsApi.IdentityTypeEnum.microsoft
701
+ return EventsApi.IdentityTypeEnum.microsoft;
697
702
  case SDKIdentityTypeEnum.yahoo:
698
- return EventsApi.IdentityTypeEnum.yahoo
703
+ return EventsApi.IdentityTypeEnum.yahoo;
699
704
  case SDKIdentityTypeEnum.email:
700
- return EventsApi.IdentityTypeEnum.email
705
+ return EventsApi.IdentityTypeEnum.email;
701
706
  case SDKIdentityTypeEnum.alias:
702
- return EventsApi.IdentityTypeEnum.alias
707
+ return EventsApi.IdentityTypeEnum.alias;
703
708
  case SDKIdentityTypeEnum.facebookCustomAudienceId:
704
- return EventsApi.IdentityTypeEnum.facebookCustomAudienceId
709
+ return EventsApi.IdentityTypeEnum.facebookCustomAudienceId;
705
710
  case SDKIdentityTypeEnum.otherId2:
706
- return EventsApi.IdentityTypeEnum.otherId2
711
+ return EventsApi.IdentityTypeEnum.otherId2;
707
712
  case SDKIdentityTypeEnum.otherId3:
708
- return EventsApi.IdentityTypeEnum.otherId3
713
+ return EventsApi.IdentityTypeEnum.otherId3;
709
714
  case SDKIdentityTypeEnum.otherId4:
710
- return EventsApi.IdentityTypeEnum.otherId4
715
+ return EventsApi.IdentityTypeEnum.otherId4;
711
716
  case SDKIdentityTypeEnum.otherId5:
712
- return EventsApi.IdentityTypeEnum.otherId5
717
+ return EventsApi.IdentityTypeEnum.otherId5;
713
718
  case SDKIdentityTypeEnum.otherId6:
714
- return EventsApi.IdentityTypeEnum.otherId6
719
+ return EventsApi.IdentityTypeEnum.otherId6;
715
720
  case SDKIdentityTypeEnum.otherId7:
716
- return EventsApi.IdentityTypeEnum.otherId7
721
+ return EventsApi.IdentityTypeEnum.otherId7;
717
722
  case SDKIdentityTypeEnum.otherId8:
718
- return EventsApi.IdentityTypeEnum.otherId8
723
+ return EventsApi.IdentityTypeEnum.otherId8;
719
724
  case SDKIdentityTypeEnum.otherId9:
720
- return EventsApi.IdentityTypeEnum.otherId9
725
+ return EventsApi.IdentityTypeEnum.otherId9;
721
726
  case SDKIdentityTypeEnum.otherId10:
722
- return EventsApi.IdentityTypeEnum.otherId10
727
+ return EventsApi.IdentityTypeEnum.otherId10;
723
728
  case SDKIdentityTypeEnum.mobileNumber:
724
- return EventsApi.IdentityTypeEnum.mobileNumber
729
+ return EventsApi.IdentityTypeEnum.mobileNumber;
725
730
  case SDKIdentityTypeEnum.phoneNumber2:
726
- return EventsApi.IdentityTypeEnum.phoneNumber2
731
+ return EventsApi.IdentityTypeEnum.phoneNumber2;
727
732
  case SDKIdentityTypeEnum.phoneNumber3:
728
- return EventsApi.IdentityTypeEnum.phoneNumber3
733
+ return EventsApi.IdentityTypeEnum.phoneNumber3;
729
734
  }
730
735
  }
@@ -8,7 +8,6 @@ import {
8
8
  BaseEvent,
9
9
  MParticleUser,
10
10
  MParticleWebSDK,
11
- SDKConsentState,
12
11
  SDKEvent,
13
12
  SDKGeoLocation,
14
13
  SDKProduct,
@@ -17,35 +16,16 @@ import {
17
16
  import { parseNumber, parseStringOrNumber, Dictionary } from './utils';
18
17
  import { ServerSettings } from './store';
19
18
  import { MPID } from '@mparticle/web-sdk';
19
+ import {
20
+ IConsentStateDTO,
21
+ IGDPRConsentStateDTO,
22
+ IPrivacyV2DTO,
23
+ SDKConsentState,
24
+ } from './consent.interfaces';
20
25
 
21
26
  const MessageType = Types.MessageType;
22
27
  const ApplicationTransitionType = Types.ApplicationTransitionType;
23
28
 
24
- // TODO: Move to Consent Module
25
- export interface IPrivacyV2DTO {
26
- c: boolean; // Consented
27
- ts: number; // Timestamp
28
- d: string; // Document
29
- l: string; // Location
30
- h: string; // HardwareID
31
- }
32
-
33
- // TODO: Move to Consent Module
34
- export interface IGDPRConsentStateDTO {
35
- [key: string]: IPrivacyV2DTO;
36
- }
37
-
38
- // TODO: Move to Consent Module
39
- export interface ICCPAConsentStateDTO {
40
- data_sale_opt_out: IPrivacyV2DTO;
41
- }
42
-
43
- // TODO: Break this up into GDPR and CCPA interfaces
44
- export interface IConsentStateDTO {
45
- gdpr?: IGDPRConsentStateDTO;
46
- ccpa?: ICCPAConsentStateDTO;
47
- }
48
-
49
29
  // TODO: Confirm which attributes are optional
50
30
  export interface IServerDTO {
51
31
  id: string | number;
package/src/store.ts CHANGED
@@ -16,7 +16,6 @@ import {
16
16
  LogLevelType,
17
17
  MParticleWebSDK,
18
18
  MPForwarder,
19
- SDKConsentState,
20
19
  SDKDataPlan,
21
20
  SDKEvent,
22
21
  SDKGeoLocation,
@@ -24,6 +23,7 @@ import {
24
23
  SDKProduct,
25
24
  } from './sdkRuntimeModels';
26
25
  import { isNumber, isDataPlanSlug, Dictionary } from './utils';
26
+ import { SDKConsentState } from './consent.interfaces';
27
27
 
28
28
  // This represents the runtime configuration of the SDK AFTER
29
29
  // initialization has been complete and all settings and
package/src/vault.ts ADDED
@@ -0,0 +1,141 @@
1
+ import { Logger } from '@mparticle/web-sdk';
2
+ import { Dictionary, isEmpty } from './utils';
3
+
4
+ interface IVaultOptions {
5
+ logger?: Logger;
6
+ offlineStorageEnabled?: boolean;
7
+ }
8
+
9
+ export default class Vault<StorableItem extends Dictionary> {
10
+ public contents: Dictionary<StorableItem>;
11
+ private readonly _storageKey: string;
12
+ private readonly _itemKey: keyof StorableItem;
13
+ private logger?: Logger;
14
+ private offlineStorageEnabled: boolean = false;
15
+
16
+ /**
17
+ *
18
+ * @param {string} storageKey the local storage key string
19
+ * @param {string} itemKey an element within your StorableItem to use as a key
20
+ * @param {IVaultOptions} options A Dictionary of IVaultOptions
21
+ */
22
+ constructor(
23
+ storageKey: string,
24
+ itemKey: keyof StorableItem,
25
+ options?: IVaultOptions
26
+ ) {
27
+ this._storageKey = storageKey;
28
+ this._itemKey = itemKey;
29
+ this.contents = this.getItems() || {};
30
+
31
+ this.offlineStorageEnabled = options?.offlineStorageEnabled;
32
+
33
+ // Add a fake logger in case one is not provided or needed
34
+ this.logger = options?.logger || {
35
+ verbose: () => {},
36
+ warning: () => {},
37
+ error: () => {},
38
+ };
39
+ }
40
+
41
+ /**
42
+ * Stores a single Item using `itemId` as an index
43
+ * @method storeItem
44
+ * @param item {StorableItem} a Dictonary with key to store
45
+ */
46
+ public storeItem(item: StorableItem): void {
47
+ this.contents = this.getItems();
48
+
49
+ if (item[this._itemKey]) {
50
+ this.contents[item[this._itemKey]] = item;
51
+ this.logger.verbose(
52
+ `Saved items to vault with key: ${item[this._itemKey]}`
53
+ );
54
+ }
55
+
56
+ this.saveItems(this.contents);
57
+ }
58
+
59
+ /**
60
+ * Stores Items using `itemId` as an index
61
+ * @method storeItems
62
+ * @param {StorableItem[]} an Array of StorableItems
63
+ */
64
+ public storeItems(items: StorableItem[]): void {
65
+ items.forEach((item) => this.storeItem(item));
66
+ }
67
+
68
+ /**
69
+ * Removes a single StorableItem based on `indexId`
70
+ * @method removeItem
71
+ * @param {String} indexId
72
+ */
73
+ public removeItem(indexId: string): void {
74
+ this.logger.verbose(`Removing from vault: ${indexId}`);
75
+ this.contents = this.getItems() || {};
76
+
77
+ try {
78
+ delete this.contents[indexId];
79
+
80
+ this.saveItems(this.contents);
81
+ } catch (error) {
82
+ this.logger.error(
83
+ `Unable to remove item without a matching ID ${indexId}`
84
+ );
85
+ this.logger.error(error as string);
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Retrieves all StorableItems from local storage as an array
91
+ * @method retrieveItems
92
+ * @returns {StorableItem[]} an array of Items
93
+ */
94
+ public retrieveItems(): StorableItem[] {
95
+ this.contents = this.getItems();
96
+
97
+ return Object.keys(this.contents).map((item) => this.contents[item]);
98
+ }
99
+
100
+ /**
101
+ * Removes all persisted data from local storage based on this vault's `key`
102
+ * @method purge
103
+ */
104
+ public purge(): void {
105
+ this.contents = {};
106
+ this.removeItems();
107
+ }
108
+
109
+ private saveItems(items: Dictionary<StorableItem>): void {
110
+ if (!this.offlineStorageEnabled) {
111
+ return;
112
+ }
113
+ try {
114
+ window.localStorage.setItem(
115
+ this._storageKey,
116
+ !isEmpty(items) ? JSON.stringify(items) : ''
117
+ );
118
+ } catch (error) {
119
+ this.logger.error(`Cannot Save items to Local Storage: ${items}`);
120
+ this.logger.error(error as string);
121
+ }
122
+ }
123
+
124
+ private getItems(): Dictionary<StorableItem> {
125
+ if (!this.offlineStorageEnabled) {
126
+ return this.contents;
127
+ }
128
+ // TODO: Handle cases where Local Storage is unavailable
129
+ // https://go.mparticle.com/work/SQDSDKS-5022
130
+ const itemString = window.localStorage.getItem(this._storageKey);
131
+
132
+ return itemString ? JSON.parse(itemString) : {};
133
+ }
134
+
135
+ private removeItems(): void {
136
+ if (!this.offlineStorageEnabled) {
137
+ return;
138
+ }
139
+ window.localStorage.removeItem(this._storageKey);
140
+ }
141
+ }