@mparticle/web-sdk 2.20.3 → 2.21.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/src/vault.ts CHANGED
@@ -1,25 +1,30 @@
1
1
  import { Logger } from '@mparticle/web-sdk';
2
- import { Dictionary, isEmpty } from './utils';
2
+ import { isEmpty } from './utils';
3
3
 
4
- interface IVaultOptions {
4
+ export interface IVaultOptions {
5
5
  logger?: Logger;
6
6
  offlineStorageEnabled?: boolean;
7
7
  }
8
8
 
9
- export default class Vault<StorableItem> {
9
+ export abstract class BaseVault<StorableItem> {
10
10
  public contents: StorableItem;
11
- private readonly _storageKey: string;
12
- private logger?: Logger;
11
+ protected readonly _storageKey: string;
12
+ protected logger?: Logger;
13
+ protected storageObject: Storage;
13
14
 
14
15
  /**
15
16
  *
16
17
  * @param {string} storageKey the local storage key string
17
- * @param {string} itemKey an element within your StorableItem to use as a key
18
+ * @param {Storage} Web API Storage object that is being used
18
19
  * @param {IVaultOptions} options A Dictionary of IVaultOptions
19
20
  */
20
- constructor(storageKey: string, options?: IVaultOptions) {
21
+ constructor(
22
+ storageKey: string,
23
+ storageObject: Storage,
24
+ options?: IVaultOptions
25
+ ) {
21
26
  this._storageKey = storageKey;
22
- this.contents = this.getFromLocalStorage();
27
+ this.storageObject = storageObject;
23
28
 
24
29
  // Add a fake logger in case one is not provided or needed
25
30
  this.logger = options?.logger || {
@@ -27,62 +32,69 @@ export default class Vault<StorableItem> {
27
32
  warning: () => {},
28
33
  error: () => {},
29
34
  };
35
+
36
+ this.contents = this.retrieve();
30
37
  }
31
38
 
32
39
  /**
33
- * Stores a StorableItem to Local Storage
34
- * @method storeItem
40
+ * Stores a StorableItem to Storage
41
+ * @method store
35
42
  * @param item {StorableItem}
36
43
  */
37
44
  public store(item: StorableItem): void {
38
45
  this.contents = item;
39
46
 
40
- this.logger.verbose(`Saved to local storage: ${item}`);
47
+ const stringifiedItem = !isEmpty(item) ? JSON.stringify(item) : '';
48
+
49
+ try {
50
+ this.storageObject.setItem(this._storageKey, stringifiedItem);
41
51
 
42
- this.saveToLocalStorage(this.contents);
52
+ this.logger.verbose(`Saving item to Storage: ${stringifiedItem}`);
53
+ } catch (error) {
54
+ this.logger.error(
55
+ `Cannot Save items to Storage: ${stringifiedItem}`
56
+ );
57
+ this.logger.error(error as string);
58
+ }
43
59
  }
44
60
 
45
61
  /**
46
- * Retrieves all StorableItems from local storage as an array
47
- * @method retrieveItems
48
- * @returns {StorableItem[]} an array of Items
62
+ * Retrieve StorableItem from Storage
63
+ * @method retrieve
64
+ * @returns {StorableItem}
49
65
  */
50
- public retrieve(): StorableItem {
51
- this.contents = this.getFromLocalStorage();
66
+ public retrieve(): StorableItem | null {
67
+ // TODO: Handle cases where Local Storage is unavailable
68
+ // https://go.mparticle.com/work/SQDSDKS-5022
69
+ const item: string = this.storageObject.getItem(this._storageKey);
70
+
71
+ this.contents = item ? JSON.parse(item) : null;
72
+
73
+ this.logger.verbose(`Retrieving item from Storage: ${item}`);
52
74
 
53
75
  return this.contents;
54
76
  }
55
77
 
56
78
  /**
57
- * Removes all persisted data from local storage based on this vault's `key`
79
+ * Removes all persisted data from Storage based on this vault's `key`
80
+ * Will remove storage key from Storage as well
58
81
  * @method purge
59
82
  */
60
83
  public purge(): void {
84
+ this.logger.verbose('Purging Storage');
61
85
  this.contents = null;
62
- this.removeFromLocalStorage();
63
- }
64
-
65
- private saveToLocalStorage(items: StorableItem): void {
66
- try {
67
- window.localStorage.setItem(
68
- this._storageKey,
69
- !isEmpty(items) ? JSON.stringify(items) : ''
70
- );
71
- } catch (error) {
72
- this.logger.error(`Cannot Save items to Local Storage: ${items}`);
73
- this.logger.error(error as string);
74
- }
86
+ this.storageObject.removeItem(this._storageKey);
75
87
  }
88
+ }
76
89
 
77
- private getFromLocalStorage(): StorableItem | null {
78
- // TODO: Handle cases where Local Storage is unavailable
79
- // https://go.mparticle.com/work/SQDSDKS-5022
80
- const item: string = window.localStorage.getItem(this._storageKey);
81
-
82
- return item ? JSON.parse(item) : null;
90
+ export class LocalStorageVault<StorableItem> extends BaseVault<StorableItem> {
91
+ constructor(storageKey: string, options?: IVaultOptions) {
92
+ super(storageKey, window.localStorage, options);
83
93
  }
94
+ }
84
95
 
85
- private removeFromLocalStorage(): void {
86
- window.localStorage.removeItem(this._storageKey);
96
+ export class SessionStorageVault<StorableItem> extends BaseVault<StorableItem> {
97
+ constructor(storageKey: string, options?: IVaultOptions) {
98
+ super(storageKey, window.sessionStorage, options);
87
99
  }
88
100
  }
package/src/migrations.js DELETED
@@ -1,279 +0,0 @@
1
- import Constants from './constants';
2
- import Polyfill from './polyfill';
3
-
4
- var StorageNames = Constants.StorageNames,
5
- Base64 = Polyfill.Base64,
6
- CookiesGlobalSettingsKeys = {
7
- das: 1,
8
- },
9
- MPIDKeys = {
10
- ui: 1,
11
- };
12
-
13
- export default function Migrations(mpInstance) {
14
- var self = this;
15
- // if there is a cookie or localStorage:
16
- // 1. determine which version it is ('mprtcl-api', 'mprtcl-v2', 'mprtcl-v3', 'mprtcl-v4')
17
- // 2. return if 'mprtcl-v4', otherwise migrate to mprtclv4 schema
18
- // 3. if 'mprtcl-api', could be JSSDKv2 or JSSDKv1. JSSDKv2 cookie has a 'globalSettings' key on it
19
- this.migrate = function() {
20
- try {
21
- migrateCookies();
22
- } catch (e) {
23
- mpInstance._Persistence.expireCookies(StorageNames.cookieNameV3);
24
- mpInstance._Persistence.expireCookies(StorageNames.cookieNameV4);
25
- mpInstance.Logger.error('Error migrating cookie: ' + e);
26
- }
27
-
28
- if (mpInstance._Store.isLocalStorageAvailable) {
29
- try {
30
- migrateLocalStorage();
31
- } catch (e) {
32
- localStorage.removeItem(StorageNames.localStorageNameV3);
33
- localStorage.removeItem(StorageNames.localStorageNameV4);
34
- mpInstance.Logger.error('Error migrating localStorage: ' + e);
35
- }
36
- }
37
- };
38
-
39
- function migrateCookies() {
40
- var cookies = window.document.cookie.split('; '),
41
- foundCookie,
42
- i,
43
- l,
44
- parts,
45
- name,
46
- cookie;
47
-
48
- mpInstance.Logger.verbose(
49
- Constants.Messages.InformationMessages.CookieSearch
50
- );
51
-
52
- for (i = 0, l = cookies.length; i < l; i++) {
53
- try {
54
- parts = cookies[i].split('=');
55
- name = mpInstance._Helpers.decoded(parts.shift());
56
- cookie = mpInstance._Helpers.decoded(parts.join('='));
57
- } catch (e) {
58
- mpInstance.Logger.verbose(
59
- 'Unable to parse cookie: ' + name + '. Skipping.'
60
- );
61
- }
62
-
63
- //most recent version needs no migration
64
- if (name === mpInstance._Store.storageName) {
65
- return;
66
- }
67
- if (name === StorageNames.cookieNameV4) {
68
- // adds cookies to new namespace, removes previous cookie
69
- finishCookieMigration(cookie, StorageNames.cookieNameV4);
70
- if (mpInstance._Store.isLocalStorageAvailable) {
71
- migrateProductsToNameSpace();
72
- }
73
- return;
74
- // migration path for SDKv1CookiesV3, doesn't need to be encoded
75
- }
76
- if (name === StorageNames.cookieNameV3) {
77
- foundCookie = self.convertSDKv1CookiesV3ToSDKv2CookiesV4(
78
- cookie
79
- );
80
- finishCookieMigration(foundCookie, StorageNames.cookieNameV3);
81
- break;
82
- }
83
- }
84
- }
85
-
86
- function finishCookieMigration(cookie, cookieName) {
87
- var date = new Date(),
88
- cookieDomain = mpInstance._Persistence.getCookieDomain(),
89
- expires,
90
- domain;
91
-
92
- expires = new Date(
93
- date.getTime() + StorageNames.CookieExpiration * 24 * 60 * 60 * 1000
94
- ).toGMTString();
95
-
96
- if (cookieDomain === '') {
97
- domain = '';
98
- } else {
99
- domain = ';domain=' + cookieDomain;
100
- }
101
-
102
- mpInstance.Logger.verbose(
103
- Constants.Messages.InformationMessages.CookieSet
104
- );
105
-
106
- window.document.cookie =
107
- encodeURIComponent(mpInstance._Store.storageName) +
108
- '=' +
109
- cookie +
110
- ';expires=' +
111
- expires +
112
- ';path=/' +
113
- domain;
114
-
115
- mpInstance._Persistence.expireCookies(cookieName);
116
- mpInstance._Store.migratingToIDSyncCookies = true;
117
- }
118
-
119
- this.convertSDKv1CookiesV3ToSDKv2CookiesV4 = function(SDKv1CookiesV3) {
120
- SDKv1CookiesV3 = mpInstance._Persistence.replacePipesWithCommas(
121
- mpInstance._Persistence.replaceApostrophesWithQuotes(SDKv1CookiesV3)
122
- );
123
- var parsedSDKv1CookiesV3 = JSON.parse(SDKv1CookiesV3);
124
- var parsedCookiesV4 = JSON.parse(restructureToV4Cookie(SDKv1CookiesV3));
125
-
126
- if (parsedSDKv1CookiesV3.mpid) {
127
- parsedCookiesV4.gs.csm.push(parsedSDKv1CookiesV3.mpid);
128
- // all other values are already encoded, so we have to encode any new values
129
- parsedCookiesV4.gs.csm = Base64.encode(
130
- JSON.stringify(parsedCookiesV4.gs.csm)
131
- );
132
- migrateProductsFromSDKv1ToSDKv2CookiesV4(
133
- parsedSDKv1CookiesV3,
134
- parsedSDKv1CookiesV3.mpid
135
- );
136
- }
137
-
138
- return JSON.stringify(parsedCookiesV4);
139
- };
140
-
141
- function restructureToV4Cookie(cookies) {
142
- try {
143
- var cookiesV4Schema = { gs: { csm: [] } };
144
- cookies = JSON.parse(cookies);
145
-
146
- for (var key in cookies) {
147
- if (cookies.hasOwnProperty(key)) {
148
- if (CookiesGlobalSettingsKeys[key]) {
149
- cookiesV4Schema.gs[key] = cookies[key];
150
- } else if (key === 'mpid') {
151
- cookiesV4Schema.cu = cookies[key];
152
- } else if (cookies.mpid) {
153
- cookiesV4Schema[cookies.mpid] =
154
- cookiesV4Schema[cookies.mpid] || {};
155
- if (MPIDKeys[key]) {
156
- cookiesV4Schema[cookies.mpid][key] = cookies[key];
157
- }
158
- }
159
- }
160
- }
161
- return JSON.stringify(cookiesV4Schema);
162
- } catch (e) {
163
- mpInstance.Logger.error(
164
- 'Failed to restructure previous cookie into most current cookie schema'
165
- );
166
- }
167
- }
168
-
169
- function migrateProductsToNameSpace() {
170
- var lsProdV4Name = StorageNames.localStorageProductsV4;
171
- var products = localStorage.getItem(
172
- StorageNames.localStorageProductsV4
173
- );
174
- localStorage.setItem(mpInstance._Store.prodStorageName, products);
175
- localStorage.removeItem(lsProdV4Name);
176
- }
177
-
178
- function migrateProductsFromSDKv1ToSDKv2CookiesV4(cookies, mpid) {
179
- if (!mpInstance._Store.isLocalStorageAvailable) {
180
- return;
181
- }
182
-
183
- var localStorageProducts = {};
184
- localStorageProducts[mpid] = {};
185
- if (cookies.cp) {
186
- try {
187
- localStorageProducts[mpid].cp = JSON.parse(
188
- Base64.decode(cookies.cp)
189
- );
190
- } catch (e) {
191
- localStorageProducts[mpid].cp = cookies.cp;
192
- }
193
-
194
- if (!Array.isArray(localStorageProducts[mpid].cp)) {
195
- localStorageProducts[mpid].cp = [];
196
- }
197
- }
198
-
199
- localStorage.setItem(
200
- mpInstance._Store.prodStorageName,
201
- Base64.encode(JSON.stringify(localStorageProducts))
202
- );
203
- }
204
-
205
- function migrateLocalStorage() {
206
- var cookies,
207
- v3LSName = StorageNames.localStorageNameV3,
208
- v4LSName = StorageNames.localStorageNameV4,
209
- currentVersionLSData = window.localStorage.getItem(
210
- mpInstance._Store.storageName
211
- ),
212
- v4LSData,
213
- v3LSData,
214
- v3LSDataStringCopy;
215
-
216
- if (currentVersionLSData) {
217
- return;
218
- }
219
-
220
- v4LSData = window.localStorage.getItem(v4LSName);
221
- if (v4LSData) {
222
- finishLSMigration(v4LSData, v4LSName);
223
- migrateProductsToNameSpace();
224
- return;
225
- }
226
-
227
- v3LSData = window.localStorage.getItem(v3LSName);
228
- if (v3LSData) {
229
- mpInstance._Store.migratingToIDSyncCookies = true;
230
- v3LSDataStringCopy = v3LSData.slice();
231
- v3LSData = JSON.parse(
232
- mpInstance._Persistence.replacePipesWithCommas(
233
- mpInstance._Persistence.replaceApostrophesWithQuotes(
234
- v3LSData
235
- )
236
- )
237
- );
238
- // localStorage may contain only products, or the full persistence
239
- // when there is an MPID on the cookie, it is the full persistence
240
- if (v3LSData.mpid) {
241
- v3LSData = JSON.parse(
242
- self.convertSDKv1CookiesV3ToSDKv2CookiesV4(
243
- v3LSDataStringCopy
244
- )
245
- );
246
- finishLSMigration(JSON.stringify(v3LSData), v3LSName);
247
- return;
248
- // if no MPID, it is only the products
249
- } else if ((v3LSData.cp || v3LSData.pb) && !v3LSData.mpid) {
250
- cookies = mpInstance._Persistence.getCookie();
251
- if (cookies) {
252
- migrateProductsFromSDKv1ToSDKv2CookiesV4(
253
- v3LSData,
254
- cookies.cu
255
- );
256
- localStorage.removeItem(StorageNames.localStorageNameV3);
257
- return;
258
- } else {
259
- localStorage.removeItem(StorageNames.localStorageNameV3);
260
- return;
261
- }
262
- }
263
- }
264
-
265
- function finishLSMigration(data, lsName) {
266
- try {
267
- window.localStorage.setItem(
268
- encodeURIComponent(mpInstance._Store.storageName),
269
- data
270
- );
271
- } catch (e) {
272
- mpInstance.Logger.error(
273
- 'Error with setting localStorage item.'
274
- );
275
- }
276
- window.localStorage.removeItem(encodeURIComponent(lsName));
277
- }
278
- }
279
- }