Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@mparticle/web-sdk

Package Overview
Dependencies
Maintainers
10
Versions
115
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mparticle/web-sdk - npm Package Compare versions

Comparing version 2.20.3 to 2.21.0

2

package.json
{
"name": "@mparticle/web-sdk",
"version": "2.20.3",
"version": "2.21.0",
"description": "mParticle core SDK for web applications",

@@ -5,0 +5,0 @@ "license": "Apache-2.0",

import { Batch } from '@mparticle/event-models';
import Constants from './constants';
import {

@@ -10,8 +11,13 @@ SDKEvent,

import Types from './types';
import { isEmpty } from './utils';
import { getRampNumber, isEmpty } from './utils';
import { SessionStorageVault, LocalStorageVault } from './vault';
/**
* BatchUploader contains all the logic to upload batches to mParticle.
* It queues events as they come in and at set intervals turns them into batches.
* It then attempts to upload them to mParticle.
* BatchUploader contains all the logic to store/retrieve events and batches
* to/from persistence, and upload batches to mParticle.
* It queues events as they come in, storing them in persistence, then at set
* intervals turns them into batches and transfers between event and batch
* persistence.
* It then attempts to upload them to mParticle, purging batch persistence if
* the upload is successful
*

@@ -35,2 +41,5 @@ * These uploads happen on an interval basis using window.fetch or XHR

batchingEnabled: boolean;
private eventVault: SessionStorageVault<SDKEvent[]>;
private batchVault: LocalStorageVault<Batch[]>;
private offlineStorageEnabled: boolean = false;
private uploader: AsyncUploader;

@@ -51,5 +60,34 @@

}
// Events will be queued during `queueEvents` method
this.eventsQueuedForProcessing = [];
// Batch queue should start empty and will be populated during
// `prepareAndUpload` method, either via Local Storage or after
// new batches are created.
this.batchesQueuedForProcessing = [];
// Cache Offline Storage Availability boolean
// so that we don't have to check it every time
this.offlineStorageEnabled = this.isOfflineStorageAvailable();
if (this.offlineStorageEnabled) {
this.eventVault = new SessionStorageVault<SDKEvent[]>(
`${mpInstance._Store.storageName}-events`,
{
logger: mpInstance.Logger,
}
);
this.batchVault = new LocalStorageVault<Batch[]>(
`${mpInstance._Store.storageName}-batches`,
{
logger: mpInstance.Logger,
}
);
// Load Events from Session Storage in case we have any in storage
this.eventsQueuedForProcessing.push(...this.eventVault.retrieve());
}
const { SDKConfig, devToken } = this.mpInstance._Store;

@@ -70,2 +108,25 @@ const baseUrl = this.mpInstance._Helpers.createServiceUrl(

private isOfflineStorageAvailable(): boolean {
const {
_Helpers: { getFeatureFlag },
_Store: { deviceId },
} = this.mpInstance;
const offlineStorageFeatureFlagValue = getFeatureFlag(
Constants.FeatureFlags.OfflineStorage
);
const offlineStoragePercentage = parseInt(
offlineStorageFeatureFlagValue,
10
);
const rampNumber = getRampNumber(deviceId);
// TODO: Handle cases where Local Storage is unavailable
// Potentially shared between Vault and Persistence as well
// https://go.mparticle.com/work/SQDSDKS-5022
return offlineStoragePercentage >= rampNumber;
}
// Adds listeners to be used trigger Navigator.sendBeacon if the browser

@@ -109,5 +170,8 @@ // loses focus for any reason, such as closing browser tab or minimizing window

*/
queueEvent(event: SDKEvent): void {
public queueEvent(event: SDKEvent): void {
if (!isEmpty(event)) {
this.eventsQueuedForProcessing.push(event);
if (this.offlineStorageEnabled && this.eventVault) {
this.eventVault.store(this.eventsQueuedForProcessing);
}
this.mpInstance.Logger.verbose(

@@ -222,11 +286,29 @@ `Queuing event: ${JSON.stringify(event)}`

const currentEvents = this.eventsQueuedForProcessing;
const currentEvents: SDKEvent[] = this.eventsQueuedForProcessing;
this.eventsQueuedForProcessing = [];
if (this.offlineStorageEnabled && this.eventVault) {
this.eventVault.store([]);
}
const newBatches = BatchUploader.createNewBatches(
currentEvents,
currentUser,
this.mpInstance
);
let newBatches: Batch[] = [];
if (!isEmpty(currentEvents)) {
newBatches = BatchUploader.createNewBatches(
currentEvents,
currentUser,
this.mpInstance
);
}
// Top Load any older Batches from Offline Storage so they go out first
if (this.offlineStorageEnabled && this.batchVault) {
this.batchesQueuedForProcessing.unshift(
...this.batchVault.retrieve()
);
// Remove batches from local storage before transmit to
// prevent duplication
this.batchVault.purge();
}
if (!isEmpty(newBatches)) {

@@ -240,2 +322,9 @@ this.batchesQueuedForProcessing.push(...newBatches);

// If `useBeacon` is true, the browser has been closed suddently
// so we should save `batchesToUpload` to Offline Storage before
// an upload is attempted.
if (useBeacon && this.offlineStorageEnabled && this.batchVault) {
this.batchVault.store(batchesToUpload);
}
const batchesThatDidNotUpload = await this.uploadBatches(

@@ -255,2 +344,15 @@ this.mpInstance.Logger,

// Update Offline Storage with current state of batch queue
if (!useBeacon && this.offlineStorageEnabled && this.batchVault) {
// Note: since beacon is "Fire and forget" it will empty `batchesThatDidNotUplod`
// regardless of whether the batches were successfully uploaded or not. We should
// therefore NOT overwrite Offline Storage when beacon returns, so that we can retry
// uploading saved batches at a later time. Batches should only be removed from
// Local Storage once we can confirm they are successfully uploaded.
this.batchVault.store(this.batchesQueuedForProcessing);
// Clear batch queue since everything should be in Offline Storage
this.batchesQueuedForProcessing = [];
}
if (triggerFuture) {

@@ -257,0 +359,0 @@ this.triggerUploadInterval(triggerFuture, false);

@@ -164,2 +164,3 @@ import { version } from '../package.json';

EventBatchingIntervalMillis: 'eventBatchingIntervalMillis',
OfflineStorage: 'offlineStorage',
},

@@ -166,0 +167,0 @@ DefaultInstance: 'default_instance',

@@ -7,2 +7,3 @@ // This file is used ONLY for the mParticle ESLint plugin. It should NOT be used otherwise!

import * as EventsApi from '@mparticle/event-models';
import { Batch } from '@mparticle/event-models';

@@ -123,14 +124,17 @@ const mockFunction = function () {

returnBatch(event: BaseEvent) {
private createSDKEventFunction(event): SDKEvent {
return new ServerModel(this.getMPInstance()).createEventObject(event);
}
public returnBatch(events: BaseEvent | BaseEvent[]): Batch | null {
const mpInstance = this.getMPInstance();
const sdkEvent: SDKEvent = new ServerModel(
mpInstance
).createEventObject(event);
const batch: EventsApi.Batch | null = convertEvents(
'0',
[sdkEvent],
mpInstance as any
);
const sdkEvents: SDKEvent[] = Array.isArray(events)
? events.map((event) => this.createSDKEventFunction(event))
: [this.createSDKEventFunction(events)];
const batch: Batch = convertEvents('0', sdkEvents, mpInstance as any);
return batch;
}
}

@@ -447,3 +447,10 @@ import { Batch } from '@mparticle/event-models';

}
if (
!this.SDKConfig.flags.hasOwnProperty(
Constants.FeatureFlags.OfflineStorage
)
) {
this.SDKConfig.flags[Constants.FeatureFlags.OfflineStorage] = 0;
}
}
}
import { Logger } from '@mparticle/web-sdk';
import { Dictionary, isEmpty } from './utils';
import { isEmpty } from './utils';
interface IVaultOptions {
export interface IVaultOptions {
logger?: Logger;

@@ -9,6 +9,7 @@ offlineStorageEnabled?: boolean;

export default class Vault<StorableItem> {
export abstract class BaseVault<StorableItem> {
public contents: StorableItem;
private readonly _storageKey: string;
private logger?: Logger;
protected readonly _storageKey: string;
protected logger?: Logger;
protected storageObject: Storage;

@@ -18,8 +19,12 @@ /**

* @param {string} storageKey the local storage key string
* @param {string} itemKey an element within your StorableItem to use as a key
* @param {Storage} Web API Storage object that is being used
* @param {IVaultOptions} options A Dictionary of IVaultOptions
*/
constructor(storageKey: string, options?: IVaultOptions) {
constructor(
storageKey: string,
storageObject: Storage,
options?: IVaultOptions
) {
this._storageKey = storageKey;
this.contents = this.getFromLocalStorage();
this.storageObject = storageObject;

@@ -32,7 +37,9 @@ // Add a fake logger in case one is not provided or needed

};
this.contents = this.retrieve();
}
/**
* Stores a StorableItem to Local Storage
* @method storeItem
* Stores a StorableItem to Storage
* @method store
* @param item {StorableItem}

@@ -43,15 +50,30 @@ */

this.logger.verbose(`Saved to local storage: ${item}`);
const stringifiedItem = !isEmpty(item) ? JSON.stringify(item) : '';
this.saveToLocalStorage(this.contents);
try {
this.storageObject.setItem(this._storageKey, stringifiedItem);
this.logger.verbose(`Saving item to Storage: ${stringifiedItem}`);
} catch (error) {
this.logger.error(
`Cannot Save items to Storage: ${stringifiedItem}`
);
this.logger.error(error as string);
}
}
/**
* Retrieves all StorableItems from local storage as an array
* @method retrieveItems
* @returns {StorableItem[]} an array of Items
* Retrieve StorableItem from Storage
* @method retrieve
* @returns {StorableItem}
*/
public retrieve(): StorableItem {
this.contents = this.getFromLocalStorage();
public retrieve(): StorableItem | null {
// TODO: Handle cases where Local Storage is unavailable
// https://go.mparticle.com/work/SQDSDKS-5022
const item: string = this.storageObject.getItem(this._storageKey);
this.contents = item ? JSON.parse(item) : null;
this.logger.verbose(`Retrieving item from Storage: ${item}`);
return this.contents;

@@ -61,33 +83,23 @@ }

/**
* Removes all persisted data from local storage based on this vault's `key`
* Removes all persisted data from Storage based on this vault's `key`
* Will remove storage key from Storage as well
* @method purge
*/
public purge(): void {
this.logger.verbose('Purging Storage');
this.contents = null;
this.removeFromLocalStorage();
this.storageObject.removeItem(this._storageKey);
}
}
private saveToLocalStorage(items: StorableItem): void {
try {
window.localStorage.setItem(
this._storageKey,
!isEmpty(items) ? JSON.stringify(items) : ''
);
} catch (error) {
this.logger.error(`Cannot Save items to Local Storage: ${items}`);
this.logger.error(error as string);
}
export class LocalStorageVault<StorableItem> extends BaseVault<StorableItem> {
constructor(storageKey: string, options?: IVaultOptions) {
super(storageKey, window.localStorage, options);
}
}
private getFromLocalStorage(): StorableItem | null {
// TODO: Handle cases where Local Storage is unavailable
// https://go.mparticle.com/work/SQDSDKS-5022
const item: string = window.localStorage.getItem(this._storageKey);
return item ? JSON.parse(item) : null;
export class SessionStorageVault<StorableItem> extends BaseVault<StorableItem> {
constructor(storageKey: string, options?: IVaultOptions) {
super(storageKey, window.sessionStorage, options);
}
private removeFromLocalStorage(): void {
window.localStorage.removeItem(this._storageKey);
}
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc