Skip to content

Commit

Permalink
refactor: Migrate mParticle Instance to TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
alexs-mparticle committed Jan 28, 2025
1 parent c9a2723 commit feab01f
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 91 deletions.
15 changes: 8 additions & 7 deletions src/batchUploader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
IFetchPayload,
} from './uploaders';
import { IMParticleUser } from './identity-user-interfaces';
import { IMParticleWebSDKInstance } from './mp-instance';

/**
* BatchUploader contains all the logic to store/retrieve events and batches
Expand All @@ -36,7 +37,7 @@ export class BatchUploader {
uploadIntervalMillis: number;
eventsQueuedForProcessing: SDKEvent[];
batchesQueuedForProcessing: Batch[];
mpInstance: MParticleWebSDK;
mpInstance: IMParticleWebSDKInstance;
uploadUrl: string;
batchingEnabled: boolean;
private eventVault: SessionStorageVault<SDKEvent[]>;
Expand All @@ -46,10 +47,10 @@ export class BatchUploader {

/**
* Creates an instance of a BatchUploader
* @param {MParticleWebSDK} mpInstance - the mParticle SDK instance
* @param {IMParticleWebSDKInstance} mpInstance - the mParticle SDK instance
* @param {number} uploadInterval - the desired upload interval in milliseconds
*/
constructor(mpInstance: MParticleWebSDK, uploadInterval: number) {
constructor(mpInstance: IMParticleWebSDKInstance, uploadInterval: number) {
this.mpInstance = mpInstance;
this.uploadIntervalMillis = uploadInterval;
this.batchingEnabled =
Expand Down Expand Up @@ -208,7 +209,7 @@ export class BatchUploader {
private static createNewBatches(
sdkEvents: SDKEvent[],
defaultUser: IMParticleUser,
mpInstance: MParticleWebSDK
mpInstance: IMParticleWebSDKInstance
): Batch[] | null {
if (!defaultUser || !sdkEvents || !sdkEvents.length) {
return null;
Expand Down Expand Up @@ -280,9 +281,9 @@ export class BatchUploader {
* @param triggerFuture whether to trigger the loop again - for manual/forced uploads this should be false
* @param useBeacon whether to use the beacon API - used when the page is being unloaded
*/
private async prepareAndUpload(
triggerFuture: boolean,
useBeacon: boolean
public async prepareAndUpload(
triggerFuture?: boolean,
useBeacon?: boolean
): Promise<void> {
// Fetch current user so that events can be grouped by MPID
const currentUser = this.mpInstance.Identity.getCurrentUser();
Expand Down
6 changes: 0 additions & 6 deletions src/consent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@ export interface SDKConsentApi {
createGDPRConsent: ICreatePrivacyConsentFunction;
createCCPAConsent: ICreatePrivacyConsentFunction;
createConsentState: (consentState?: ConsentState) => ConsentState;
ConsentSerialization: IConsentSerialization;
createPrivacyConsent: ICreatePrivacyConsentFunction;
isEnabledForUserConsent: (
consentRules: IConsentRules,
user: IMParticleUser
) => boolean;
}

export interface IConsentSerialization {
Expand Down
6 changes: 3 additions & 3 deletions src/events.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export interface IEvents {
logOptOut(): void;
logProductActionEvent(
productActionType: valueof<typeof ProductActionType>,
product: SDKProduct,
product: SDKProduct | SDKProduct[],
attrs?: SDKEventAttrs,
customFlags?: SDKEventCustomFlags,
transactionAttributes?: TransactionAttributes,
Expand All @@ -68,13 +68,13 @@ export interface IEvents {
): void;
logPurchaseEvent(
transactionAttributes: TransactionAttributes,
product: SDKProduct,
product: SDKProduct | SDKProduct[],
attrs?: SDKEventAttrs,
customFlags?: SDKEventCustomFlags
): void;
logRefundEvent(
transactionAttributes: TransactionAttributes,
product: SDKProduct,
product: SDKProduct | SDKProduct[],
attrs?: SDKEventAttrs,
customFlags?: SDKEventCustomFlags
): void;
Expand Down
6 changes: 3 additions & 3 deletions src/identity-user-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ export interface IdentityModifyResultBody {
}

export interface mParticleUserCart {
add(product: Product, logEvent: boolean): void;
remove(product: Product, logEvent: boolean): void;
add(product: SDKProduct | SDKProduct[], logEvent: boolean): void;
remove(product: SDKProduct | SDKProduct[], logEvent: boolean): void;
clear(): void;
getCartProducts(): Product[];
getCartProducts(): SDKProduct[];
}

// https://go.mparticle.com/work/SQDSDKS-5196
Expand Down
127 changes: 99 additions & 28 deletions src/mp-instance.js → src/mp-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,99 @@
// Uses portions of code from jQuery
// jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license

import Types from './types';
import { EventType, IdentityType, CommerceEventType, PromotionActionType, ProductActionType, MessageType } from './types';
import Constants from './constants';
import APIClient from './apiClient';
import APIClient, { IAPIClient } from './apiClient';
import Helpers from './helpers';
import NativeSdkHelpers from './nativeSdkHelpers';
import CookieSyncManager from './cookieSyncManager';
import SessionManager from './sessionManager';
import CookieSyncManager, { ICookieSyncManager, IPixelConfiguration } from './cookieSyncManager';
import SessionManager, { ISessionManager } from './sessionManager';
import Ecommerce from './ecommerce';
import Store from './store';
import Store, { IntegrationAttribute, IStore } from './store';
import Logger from './logger';
import Persistence from './persistence';
import Events from './events';
import Forwarders from './forwarders';
import ServerModel from './serverModel';
import ServerModel, { IServerModel } from './serverModel';
import ForwardingStatsUploader from './forwardingStatsUploader';
import Identity from './identity';
import Consent from './consent';
import Consent, { IConsent } from './consent';
import KitBlocker from './kitBlocking';
import ConfigAPIClient from './configAPIClient';
import IdentityAPIClient from './identityApiClient';
import { isFunction } from './utils';
import { isFunction, valueof } from './utils';
import { LocalStorageVault } from './vault';
import { removeExpiredIdentityCacheDates } from './identity-utils';
import IntegrationCapture from './integrationCapture';
import { processReadyQueue } from './pre-init-utils';
import { IPreInit, processReadyQueue } from './pre-init-utils';
import { BaseEvent, MParticleWebSDK, SDKEventCustomFlags, SDKHelpersApi, } from './sdkRuntimeModels';
import { Callback, SDKEventAttrs, SDKEventOptions } from '@mparticle/web-sdk';
import { IIdentity } from './identity.interfaces';
import { IEvents } from './events.interfaces';
import { IECommerce } from './ecommerce.interfaces';
import { INativeSdkHelpers } from './nativeSdkHelpers.interfaces';
import { IPersistence } from './persistence.interfaces';

export interface IErrorLogMessage {
message?: string;
name?: string;
stack?: string;
}

export interface IErrorLogMessageMinified {
m?: string;
s?: string;
t?: string;
}

export type IntegrationDelays = { [key: number]: boolean };

// https://go.mparticle.com/work/SQDSDKS-6949
export interface IMParticleWebSDKInstance extends MParticleWebSDK {
_instanceName: string;
_preInit: IPreInit;

_APIClient: IAPIClient;
_CookieSyncManager: ICookieSyncManager;
_Consent: IConsent;
_Ecommerce: IECommerce;
_Events: IEvents;
_Forwarders: any;
_ForwardingStatsUploader: ForwardingStatsUploader;
_Helpers: SDKHelpersApi;
_Identity: IIdentity;
_IdentityAPIClient: typeof IdentityAPIClient;
_IntegrationCapture: IntegrationCapture;
_NativeSdkHelpers: INativeSdkHelpers;
_Persistence: IPersistence;
_SessionManager: ISessionManager;
_Store: IStore;
_ServerModel: IServerModel;



configurePixel(config: IPixelConfiguration): void;
reset(instance: IMParticleWebSDKInstance): void;
ready(f: Function): void;
isInitialized(): boolean;
getEnvironment(): valueof<typeof Constants.Environment>;
getVersion(): string;
setAppVersion(version: string): void;
setAppName(name: string): void;
startTrackingLocation(callback?: Callback): void;
stopTrackingLocation(): void;
logError(error: IErrorLogMessage | string, attrs?: any): void;

// TODO: Define EventInfo
logLink(selector: string, eventName: string, eventType: valueof<typeof EventType>, eventInfo: any): void;
logForm(selector: string, eventName: string, eventType: valueof<typeof EventType>, eventInfo: any): void;
logPageView(eventName: string, attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions): void;
setOptOut(isOptingOut: boolean): void;

// QUESTION: Should integration ID be a number or a string?
setIntegrationAttribute(integrationId: number, attrs: IntegrationAttribute): void;
getIntegrationAttributes(integrationId: number): IntegrationAttribute;
}

const { Messages, HTTPCodes, FeatureFlags } = Constants;
const { ReportBatching, CaptureIntegrationSpecificIds } = FeatureFlags;
Expand All @@ -59,7 +127,7 @@ const { StartingInitialization } = Messages.InformationMessages;
* @class mParticle & mParticleInstance
*/

export default function mParticleInstance(instanceName) {
export default function mParticleInstance(this: IMParticleWebSDKInstance, instanceName: string) {
var self = this;
// These classes are for internal use only. Not documented for public consumption
this._instanceName = instanceName;
Expand All @@ -82,11 +150,12 @@ export default function mParticleInstance(instanceName) {
this._IntegrationCapture = new IntegrationCapture();

// required for forwarders once they reference the mparticle instance
this.IdentityType = Types.IdentityType;
this.EventType = Types.EventType;
this.CommerceEventType = Types.CommerceEventType;
this.PromotionType = Types.PromotionActionType;
this.ProductActionType = Types.ProductActionType;
this.IdentityType = IdentityType;
this.EventType = EventType as unknown as valueof<typeof EventType>;
this.CommerceEventType = CommerceEventType as unknown as valueof<typeof CommerceEventType>;
this.PromotionType = PromotionActionType as unknown as valueof<typeof PromotionActionType>;
this.ProductActionType = ProductActionType as unknown as valueof<typeof ProductActionType>;


this._Identity = new Identity(this);
this.Identity = this._Identity.IdentityAPI;
Expand Down Expand Up @@ -372,7 +441,7 @@ export default function mParticleInstance(instanceName) {
}

if (!event.eventType) {
event.eventType = Types.EventType.Unknown;
event.eventType = EventType.Unknown;
}

if (!self._Helpers.canLog()) {
Expand Down Expand Up @@ -417,15 +486,15 @@ export default function mParticleInstance(instanceName) {
}

if (!eventType) {
eventType = Types.EventType.Unknown;
eventType = EventType.Unknown;
}

if (!self._Helpers.isEventType(eventType)) {
self.Logger.error(
'Invalid event type: ' +
eventType +
', must be one of: \n' +
JSON.stringify(Types.EventType)
JSON.stringify(EventType)
);
return;
}
Expand All @@ -437,12 +506,12 @@ export default function mParticleInstance(instanceName) {

self._Events.logEvent(
{
messageType: Types.MessageType.PageEvent,
messageType: MessageType.PageEvent,
name: eventName,
data: eventInfo,
eventType: eventType,
customFlags: customFlags,
},
} as BaseEvent,
eventOptions
);
};
Expand Down Expand Up @@ -471,8 +540,9 @@ export default function mParticleInstance(instanceName) {
};
}

var data = {
m: error.message ? error.message : error,
// FIXME: Replace var with const/let
var data: IErrorLogMessageMinified = {
m: error.message ? error.message : error as string,
s: 'Error',
t: error.stack || null,
};
Expand All @@ -485,10 +555,11 @@ export default function mParticleInstance(instanceName) {
}

self._Events.logEvent({
messageType: Types.MessageType.CrashReport,
messageType: MessageType.CrashReport,
name: error.name ? error.name : 'Error',
data: data,
eventType: Types.EventType.Other,
// data: data, // QUESTION: Is this a bug? This should be eventType
eventType: EventType.Other,
data: data as { [key: string]: string },
});
};
/**
Expand Down Expand Up @@ -571,10 +642,10 @@ export default function mParticleInstance(instanceName) {

self._Events.logEvent(
{
messageType: Types.MessageType.PageView,
messageType: MessageType.PageView,
name: eventName,
data: attrs,
eventType: Types.EventType.Unknown,
data: attrs as { [key: string]: string },
eventType: EventType.Unknown,
customFlags: customFlags,
},
eventOptions
Expand Down
2 changes: 1 addition & 1 deletion src/nativeSdkHelpers.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface INativeSdkHelpers {
minWebviewBridgeVersion: number
) => boolean;
isBridgeV1Available: () => boolean;
sendToNative: (path: string, value: string) => void;
sendToNative: (path: string, value?: string) => void;
sendViaBridgeV1: (path: string, value: string) => void;
sendViaIframeToIOS: (path: string, value: string) => void;
sendViaBridgeV2: (path: string, value: string, requiredWebviewBridgeName: boolean) => void;
Expand Down
11 changes: 11 additions & 0 deletions src/pre-init-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import { IPixelConfiguration } from './cookieSyncManager';
import { MPForwarder } from './forwarders.interfaces';
import { IntegrationDelays } from './mp-instance';
import { isEmpty, isFunction } from './utils';

export interface IPreInit {
readyQueue: Function[];
integrationDelays: IntegrationDelays;
forwarderConstructors: MPForwarder[];
pixelConfigurations?: IPixelConfiguration[];
isDevelopmentMode?: boolean;
}

export const processReadyQueue = (readyQueue): Function[] => {
if (!isEmpty(readyQueue)) {
readyQueue.forEach(readyQueueItem => {
Expand Down
Loading

0 comments on commit feab01f

Please sign in to comment.