diff --git a/src/apiClient.ts b/src/apiClient.ts index 5e0a2fe76..ba35e1b2c 100644 --- a/src/apiClient.ts +++ b/src/apiClient.ts @@ -1,15 +1,15 @@ import Constants from './constants'; -import Types from './types'; +import Types, { MessageType } from './types'; import { BatchUploader } from './batchUploader'; import { SDKEvent, SDKDataPlan } from './sdkRuntimeModels'; import KitBlocker from './kitBlocking'; import { Dictionary, isEmpty, parseNumber } from './utils'; import { IUploadObject } from './serverModel'; -import { MPForwarder } from './forwarders.interfaces'; import { IMParticleUser, ISDKUserAttributes } from './identity-user-interfaces'; import { AsyncUploader, FetchUploader, XHRUploader } from './uploaders'; import { IMParticleWebSDKInstance } from './mp-instance'; import { appendUserInfo } from './user-utils'; +import { ConfiguredKit } from './forwarders.interfaces'; export interface IAPIClient { uploader: BatchUploader | null; @@ -24,7 +24,7 @@ export interface IAPIClient { ) => void; initializeForwarderStatsUploader: () => AsyncUploader; prepareForwardingStats: ( - forwarder: MPForwarder, + forwarder: ConfiguredKit, event: IUploadObject ) => void; } @@ -140,7 +140,7 @@ export default function APIClient( // https://go.mparticle.com/work/SQDSDKS-6935 // While Event Name is 'usually' a string, there are some cases where it is a number // in that it could be a type of MessageType Enum - if (event.EventName as unknown as number !== Types.MessageType.AppStateTransition) { + if (event.EventName as unknown as number !== MessageType.AppStateTransition) { if (kitBlocker && kitBlocker.kitBlockingEnabled) { event = kitBlocker.createBlockedEvent(event); } @@ -193,7 +193,7 @@ export default function APIClient( }; this.prepareForwardingStats = function( - forwarder: MPForwarder, + forwarder: ConfiguredKit, event:SDKEvent, ) : void { let forwardingStatsData: IForwardingStatsData; @@ -206,8 +206,8 @@ export default function APIClient( n: event.EventName, attrs: event.EventAttributes, sdk: event.SDKVersion, - dt: event.EventDataType, - et: event.EventCategory, + dt: event.EventDataType as number, + et: event.EventCategory as number, dbg: event.Debug, ct: event.Timestamp, eec: event.ExpandedEventCount, diff --git a/src/configAPIClient.ts b/src/configAPIClient.ts index b551af5f9..33752098e 100644 --- a/src/configAPIClient.ts +++ b/src/configAPIClient.ts @@ -5,7 +5,6 @@ import { SDKEventCustomFlags, SDKInitConfig, } from './sdkRuntimeModels'; -import { Dictionary } from './utils'; import { AsyncUploader, IFetchPayload, @@ -14,6 +13,11 @@ import { } from './uploaders'; import { IPixelConfiguration } from './cookieSyncManager'; import { IMParticleWebSDKInstance } from './mp-instance'; +import { + ForwarderSettings, + UserAttributeFilters, + UserIdentityFilters, +} from './forwarders.interfaces'; export interface IKitConfigs extends IKitFilterSettings { name: string; @@ -23,9 +27,13 @@ export interface IKitConfigs extends IKitFilterSettings { isVisible: boolean; isDebugString: BooleanStringLowerCase; hasDebugString: BooleanStringLowerCase; - settings: Dictionary; + settings: ForwarderSettings; eventSubscriptionId: number; excludeAnonymousUser: boolean; + + // https://go.mparticle.com/work/SQDSDKS-5156 + isSandbox?: boolean; + hasSandbox?: boolean; } export interface IKitFilterSettings { @@ -33,8 +41,8 @@ export interface IKitFilterSettings { eventNameFilters: number[]; screenNameFilters: number[]; screenAttributeFilters: number[]; - userIdentityFilters: number[]; - userAttributeFilters: number[]; + userIdentityFilters: UserIdentityFilters; + userAttributeFilters: UserAttributeFilters; attributeFilters: number[]; filteringEventAttributeValue?: IFilteringEventAttributeValue; filteringUserAttributeValue?: IFilteringUserAttributeValue; diff --git a/src/forwarders.interfaces.ts b/src/forwarders.interfaces.ts index 6f8231623..586b4dd5d 100644 --- a/src/forwarders.interfaces.ts +++ b/src/forwarders.interfaces.ts @@ -1,15 +1,28 @@ -import { SDKEvent, SDKEventCustomFlags } from './sdkRuntimeModels'; +import { SDKEvent, SDKEventCustomFlags, SDKInitConfig } from './sdkRuntimeModels'; import { Dictionary } from './utils'; -import { IKitConfigs, IKitFilterSettings } from './configAPIClient'; -import { IdentityApiData } from '@mparticle/web-sdk'; +import { + IFilteringConsentRuleValues, + IFilteringEventAttributeValue, + IFilteringUserAttributeValue, + IKitConfigs, + IKitFilterSettings +} from './configAPIClient'; +import { + Callback, + IdentityApiData, + Logger, + UserIdentities +} from '@mparticle/web-sdk'; import { IMParticleUser, - ISDKUserIdentity, - UserAttributes, + ISDKUserAttributes, + ISDKUserIdentity } from './identity-user-interfaces'; - -// TODO: https://go.mparticle.com/work/SQDSDKS-4475 -export type MPForwarder = Dictionary; +import { IForwardingStatsData } from './apiClient'; +import { IPixelConfiguration } from './cookieSyncManager'; +import { IdentityAPIMethod } from './identity.interfaces'; +import { AsyncUploader } from './uploaders'; +import { IdentityType } from './types'; // The state of the kit when accessed via window.KitName via CDN // or imported as an NPM package @@ -40,17 +53,17 @@ export interface ConfiguredKit common: Dictionary; id: number; init( - settings: Dictionary, + settings: ForwarderSettings, service: forwardingStatsCallback, testMode: boolean, trackerId: string | null, - userAttributes: UserAttributes, - userIdentities: ISDKUserIdentity, + userAttributes: ISDKUserAttributes, + userIdentities: ISDKUserIdentity[], appVersion: string, appName: string, customFlags: SDKEventCustomFlags, clientId: string - ): string; + ): string; onIdentifyComplete( user: IMParticleUser, filteredIdentityRequest: IdentityApiData @@ -67,16 +80,27 @@ export interface ConfiguredKit user: IMParticleUser, filteredIdentityRequest: IdentityApiData ): string; - onUserIdentified(user: IMParticleUser): string; + + // Techically these do not return a value, but we sometimes use a string as a debug message + onUserIdentified(user: IMParticleUser, identityApiData?: IdentityApiData): string; process(event: SDKEvent): string; setOptOut(isOptingOut: boolean): string; removeUserAttribute(key: string): string; - setUserAttribute(key: string, value: string): string; - setUserIdentity(id: UserIdentityId, type: UserIdentityType): void; + setUserAttribute(key: string, value: string | string[]): string; + setUserIdentity(id: UserIdentityId, type: UserIdentityType): string; // TODO: https://go.mparticle.com/work/SQDSDKS-5156 isSandbox: boolean; hasSandbox: boolean; + + filteringConsentRuleValues: IFilteringConsentRuleValues; + filteringUserAttributeValue: IFilteringUserAttributeValue; + filteringEventAttributeValue: IFilteringEventAttributeValue; + excludeAnonymousUser: boolean; + userIdentityFilters: UserIdentityFilters; + userAttributeFilters: UserAttributeFilters; + initialized: boolean; + logger: Logger; } export type UserIdentityId = string; @@ -86,3 +110,104 @@ export type forwardingStatsCallback = ( forwarder: ConfiguredKit, event: SDKEvent ) => void; + + +export type UserIdentityFilters = typeof IdentityType[]; +export type UserAttributeFilters = number[]; + +// FIXME: Remove in favor of IKitConfigs.settings +// https://go.mparticle.com/work/SQDSDKS-7113 +export interface ForwarderSettings { + PriorityValue?: number; +} + +// Represents the Forwarder Module in the SDK +export interface IMPForwarder { + // @deprecated + setForwarderUserIdentities: (userIdentities: UserIdentities) => void; + + setForwarderOnUserIdentified: (user: IMParticleUser) => void; + setForwarderOnIdentityComplete: (user: IMParticleUser, identityMethod: IdentityAPIMethod) => void; + handleForwarderUserAttributes: (functionNameKey: string, key: string, value: string | string[]) => void; + id: number; + settings: ForwarderSettings; + forwarderStatsUploader: AsyncUploader; + isInitialized: boolean; + // filteringConsentRuleValues: IFilteringConsentRuleValues; + // filteringUserAttributeValue: IFilteringUserAttributeValue; + // filteringEventAttributeValue: IFilteringEventAttributeValue; + // excludeAnonymousUser: boolean; + // userIdentityFilters: UserIdentityFilters; + // userAttributeFilters: UserAttributeFilters; + // initialized: boolean; + // logger: Logger; + + suffix?: string; + + eventSubscriptionId: number; + + eventNameFilters: number[]; + eventTypeFilters: number[]; + attributeFilters: number[]; + + screenNameFilters: number[]; + screenAttributeFilters: number[]; + + + // Side loaded kit functionality in Forwarder methods + kitInstance: UnregisteredKit; + + // https://go.mparticle.com/work/SQDSDKS-5156 + isSandbox?: boolean; + hasSandbox?: boolean; + isVisible?: boolean; + + configureSideloadedKit: (kitConstructor: RegisteredKit) => void; + + sendSingleForwardingStatsToServer: (forwardingStatsData: IForwardingStatsData) => void; + applyToForwarders: (functionName: string, functionArgs: any[]) => void; + sendEventToForwarders: (event: SDKEvent) => void; + processPixelConfigs: (pixelConfigs: SDKInitConfig) => void; + configurePixel: (pixelConfig: IPixelConfiguration) => void; + returnConfiguredKit: (forwarder: RegisteredKit, config: IKitConfigs) => ConfiguredKit; + + processSideloadedKits: (mpConfig: SDKInitConfig) => void; + + // init: ( + // setting: ForwarderSettings, + // forwarderSettingsCallback: Callback, + // testMode: boolean, + // trackerId: string | number | null, + // filteredUserAttributes: ISDKUserAttributes, + // filteredUserIdentities: ISDKUserIdentity[], + // appVersion: string, + // appName: string, + // customFlags: SDKEventCustomFlags, + // clientId: string + // ) => void; + + initForwarders: (userIdentities: UserIdentities, forwarderStatsCallback: Callback) => void; + isEnabledForUserAttributes: (filterObject?: IFilteringUserAttributeValue, user?: IMParticleUser) => boolean; + isEnabledForUnknownUser: (excludeAnonymousUserBoolean: boolean, user: IMParticleUser) => boolean; + + name?: string; + + // Techically these do not return a value, but we sometimes use a string as a debug message + // onUserIdentified?: (user: IMParticleUser, identityApiData?: IdentityApiData) => string; + // onIdentifyComplete?: (user: IMParticleUser, identityApiData: IdentityApiData) => string; + // onLoginComplete?: (user: IMParticleUser, identityApiData: IdentityApiData) => string; + // onLogoutComplete?: (user: IMParticleUser, identityApiData: IdentityApiData) => string; + // onModifyComplete?: (user: IMParticleUser, identityApiData: IdentityApiData) => string; + // setOptOut: (optOut: boolean) => string; + // setUserAttribute?: (key: string, value: string | string[]) => string; + // removeUserAttribute?: (key: string) => string; + // process?: (event: SDKEvent) => string; + // setUserIdentity?: (identity: string, type: number) => string; + + getForwarderStatsQueue: () => IForwardingStatsData[]; + setForwarderStatsQueue: (queue: IForwardingStatsData[]) => void; + processForwarders: (config: SDKInitConfig, forwardingStatsCallback: Callback) => void; + processUIEnabledKits: (config: SDKInitConfig) => void; + returnKitConstructors: () => Dictionary; + configureUIEnabledKit: (config: IKitConfigs, kitConstructor: Dictionary) => void; +} \ No newline at end of file diff --git a/src/forwarders.js b/src/forwarders.ts similarity index 56% rename from src/forwarders.js rename to src/forwarders.ts index 2847020bf..b451163d7 100644 --- a/src/forwarders.js +++ b/src/forwarders.ts @@ -1,13 +1,23 @@ -import Types from './types'; +import { EventType, IdentityType, MessageType } from './types'; import filteredMparticleUser from './filteredMparticleUser'; -import { isEmpty } from './utils'; +import { Dictionary, inArray, isEmpty, valueof } from './utils'; import KitFilterHelper from './kitFilterHelper'; import Constants from './constants'; -import APIClient from './apiClient'; +import APIClient, { IForwardingStatsData } from './apiClient'; +import { ConfiguredKit, IMPForwarder, KitRegistrationConfig, RegisteredKit, UserAttributeFilters, UserIdentityFilters } from './forwarders.interfaces'; +import { IMParticleWebSDKInstance } from './mp-instance'; +import KitBlocker from './kitBlocking'; +import { IFilteringConsentRuleValues, IFilteringEventAttributeValue, IFilteringUserAttributeValue, IKitConfigs } from './configAPIClient'; +import { IMParticleUser, ISDKUserAttributes, ISDKUserIdentity, UserAttributes } from './identity-user-interfaces'; +import { SDKEvent, SDKInitConfig } from './sdkRuntimeModels'; +import { Callback, IdentityApiData, UserIdentities } from '@mparticle/web-sdk'; +import { IdentityAPIMethod } from './identity.interfaces'; +import { IPixelConfiguration } from './cookieSyncManager'; +import { IFetchPayload } from './uploaders'; const { Modify, Identify, Login, Logout } = Constants.IdentityMethods; -export default function Forwarders(mpInstance, kitBlocker) { +export default function Forwarders(this: IMPForwarder, mpInstance: IMParticleWebSDKInstance, kitBlocker: KitBlocker) { var self = this; this.forwarderStatsUploader = new APIClient( mpInstance, @@ -19,14 +29,19 @@ export default function Forwarders(mpInstance, kitBlocker) { removeUserAttribute: 'removeUserAttribute', }; - this.initForwarders = function(userIdentities, forwardingStatsCallback) { - var user = mpInstance.Identity.getCurrentUser(); - if ( - !mpInstance._Store.webviewBridgeEnabled && - mpInstance._Store.configuredForwarders - ) { + this.initForwarders = (userIdentities: UserIdentities, forwardingStatsCallback: Callback) => { + const user: IMParticleUser = mpInstance.Identity.getCurrentUser(); + const { + webviewBridgeEnabled, + configuredForwarders, + } = mpInstance._Store; + + const { filterUserAttributes, filterUserIdentities } = mpInstance._Helpers; + const { isEnabledForUserConsent } = mpInstance._Consent; + if (!webviewBridgeEnabled && configuredForwarders) { // Some js libraries require that they be loaded first, or last, etc - mpInstance._Store.configuredForwarders.sort(function(x, y) { + configuredForwarders.sort(function(x, y) { + // https://go.mparticle.com/work/SQDSDKS-7113 x.settings.PriorityValue = x.settings.PriorityValue || 0; y.settings.PriorityValue = y.settings.PriorityValue || 0; return ( @@ -34,74 +49,66 @@ export default function Forwarders(mpInstance, kitBlocker) { ); }); - mpInstance._Store.activeForwarders = mpInstance._Store.configuredForwarders.filter( - function(forwarder) { - if ( - !mpInstance._Consent.isEnabledForUserConsent( - forwarder.filteringConsentRuleValues, - user - ) - ) { - return false; - } - if ( - !self.isEnabledForUserAttributes( - forwarder.filteringUserAttributeValue, - user - ) - ) { - return false; - } - if ( - !self.isEnabledForUnknownUser( - forwarder.excludeAnonymousUser, - user - ) - ) { - return false; - } + mpInstance._Store.activeForwarders = configuredForwarders.filter((forwarder: ConfiguredKit) => { + const { SDKConfig, clientId } = mpInstance._Store; + const { + filteringConsentRuleValues, + filteringUserAttributeValue, + excludeAnonymousUser, + userAttributeFilters, + userIdentityFilters, + initialized, + } = forwarder; + + if (!isEnabledForUserConsent(filteringConsentRuleValues, user)) { + return false; + } + if (!self.isEnabledForUserAttributes(filteringUserAttributeValue, user)) { + return false; + } + if (!self.isEnabledForUnknownUser(excludeAnonymousUser, user)) { + return false; + } - var filteredUserIdentities = mpInstance._Helpers.filterUserIdentities( - userIdentities, - forwarder.userIdentityFilters - ); - var filteredUserAttributes = mpInstance._Helpers.filterUserAttributes( - user ? user.getAllUserAttributes() : {}, - forwarder.userAttributeFilters + const filteredUserIdentities: ISDKUserIdentity[] = filterUserIdentities( + userIdentities, + userIdentityFilters + ); + const filteredUserAttributes: ISDKUserAttributes = filterUserAttributes( + user ? user.getAllUserAttributes() : {}, + userAttributeFilters + ); + if (!initialized) { + forwarder.logger = mpInstance.Logger; + forwarder.init( + forwarder.settings, + forwardingStatsCallback, + false, + null, + filteredUserAttributes, + filteredUserIdentities, + SDKConfig.appVersion, + SDKConfig.appName, + SDKConfig.customFlags, + clientId ); - if (!forwarder.initialized) { - forwarder.logger = mpInstance.Logger; - forwarder.init( - forwarder.settings, - forwardingStatsCallback, - false, - null, - filteredUserAttributes, - filteredUserIdentities, - mpInstance._Store.SDKConfig.appVersion, - mpInstance._Store.SDKConfig.appName, - mpInstance._Store.SDKConfig.customFlags, - mpInstance._Store.clientId - ); - forwarder.initialized = true; - } - - return true; + forwarder.initialized = true; } - ); + + return true; + }); } }; - this.isEnabledForUserAttributes = function(filterObject, user) { - if ( - !filterObject || - !mpInstance._Helpers.isObject(filterObject) || - !Object.keys(filterObject).length - ) { + this.isEnabledForUserAttributes = (filterObject: IFilteringUserAttributeValue, user: IMParticleUser) => { + const { hashAttributeConditionalForwarding } = KitFilterHelper; + if (isEmpty(filterObject)) { return true; } - var attrHash, valueHash, userAttributes; + let attrHash: string; + let valueHash: string; + let userAttributes: UserAttributes; if (!user) { return false; @@ -109,27 +116,22 @@ export default function Forwarders(mpInstance, kitBlocker) { userAttributes = user.getAllUserAttributes(); } - var isMatch = false; + const { + userAttributeName, + userAttributeValue, + includeOnMatch + } = filterObject; + + let isMatch = false; try { - if ( - userAttributes && - mpInstance._Helpers.isObject(userAttributes) && - Object.keys(userAttributes).length - ) { - for (var attrName in userAttributes) { + if (!isEmpty(userAttributes)) { + for (const attrName in userAttributes) { if (userAttributes.hasOwnProperty(attrName)) { - attrHash = KitFilterHelper.hashAttributeConditionalForwarding( - attrName - ); - valueHash = KitFilterHelper.hashAttributeConditionalForwarding( - userAttributes[attrName] - ); + attrHash = hashAttributeConditionalForwarding(attrName); + valueHash = hashAttributeConditionalForwarding(userAttributes[attrName] as string); - if ( - attrHash === filterObject.userAttributeName && - valueHash === filterObject.userAttributeValue - ) { + if (attrHash === userAttributeName && valueHash === userAttributeValue) { isMatch = true; break; } @@ -137,18 +139,14 @@ export default function Forwarders(mpInstance, kitBlocker) { } } - if (filterObject) { - return filterObject.includeOnMatch === isMatch; - } else { - return true; - } + return filterObject ? includeOnMatch === isMatch : true; } catch (e) { // in any error scenario, err on side of returning true and forwarding event return true; } }; - this.isEnabledForUnknownUser = function(excludeAnonymousUserBoolean, user) { + this.isEnabledForUnknownUser = (excludeAnonymousUserBoolean: boolean, user: IMParticleUser) => { if (!user || !user.isLoggedIn()) { if (excludeAnonymousUserBoolean) { return false; @@ -157,127 +155,120 @@ export default function Forwarders(mpInstance, kitBlocker) { return true; }; - this.applyToForwarders = function(functionName, functionArgs) { - if (mpInstance._Store.activeForwarders.length) { - mpInstance._Store.activeForwarders.forEach(function(forwarder) { - var forwarderFunction = forwarder[functionName]; - if (forwarderFunction) { - try { - var result = forwarder[functionName](functionArgs); + this.applyToForwarders = (functionName: string, functionArgs: any[]) => { + const activeForwarders: ConfiguredKit[] = mpInstance._Store.activeForwarders; - if (result) { - mpInstance.Logger.verbose(result); - } - } catch (e) { - mpInstance.Logger.verbose(e); + if (!activeForwarders) { + return; + } + activeForwarders.forEach(function(forwarder: ConfiguredKit) { + const forwarderFunction: IMPForwarder = forwarder[functionName]; + if (forwarderFunction) { + try { + const result: string = forwarder[functionName](functionArgs); + + if (result) { + mpInstance.Logger.verbose(result); } + } catch (e) { + mpInstance.Logger.verbose(e as string); } - }); - } + } + }); }; - this.sendEventToForwarders = function(event) { - var clonedEvent, - hashedEventName, - hashedEventType, - filterUserIdentities = function(event, filterList) { - if (event.UserIdentities && event.UserIdentities.length) { - event.UserIdentities.forEach(function(userIdentity, i) { - if ( - mpInstance._Helpers.inArray( - filterList, - KitFilterHelper.hashUserIdentity( - userIdentity.Type - ) - ) - ) { - event.UserIdentities.splice(i, 1); - - if (i > 0) { - i--; - } - } - }); - } - }, - filterAttributes = function(event, filterList) { - var hash; + this.sendEventToForwarders = (event: SDKEvent) => { + const { webviewBridgeEnabled, activeForwarders } = mpInstance._Store; - if (!filterList) { - return; - } + let clonedEvent: SDKEvent; + let hashedEventName: number; + let hashedEventType: number; - for (var attrName in event.EventAttributes) { - if (event.EventAttributes.hasOwnProperty(attrName)) { - hash = KitFilterHelper.hashEventAttributeKey( - event.EventCategory, - event.EventName, - attrName - ); + const { hashUserIdentity } = KitFilterHelper; - if (mpInstance._Helpers.inArray(filterList, hash)) { - delete event.EventAttributes[attrName]; - } + const filterUserIdentities = (event: SDKEvent, filterList: UserIdentityFilters) => { + if (isEmpty(event.UserIdentities)) { + return; + } + event.UserIdentities.forEach(function(userIdentity: typeof IdentityType, index: number) { + const hash: number = hashUserIdentity(userIdentity.Type); + if (inArray(filterList, hash)) { + event.UserIdentities.splice(index, 1); + + if (index > 0) { + index--; } } - }, - inFilteredList = function(filterList, hash) { - if (filterList && filterList.length) { - if (mpInstance._Helpers.inArray(filterList, hash)) { - return true; + }); + }; + + const filterAttributes = (event: SDKEvent, filterList: UserAttributeFilters) => { + let hash: number; + + if (isEmpty(filterList)) { + return; + } + + for (const attrName in event.EventAttributes) { + if (event.EventAttributes.hasOwnProperty(attrName)) { + hash = KitFilterHelper.hashEventAttributeKey( + event.EventCategory as valueof, + event.EventName, + attrName + ); + + if (inArray(filterList, hash)) { + delete event.EventAttributes[attrName]; } } + } + }; - return false; - }, - forwardingRuleMessageTypes = [ - Types.MessageType.PageEvent, - Types.MessageType.PageView, - Types.MessageType.Commerce, - ]; + const inFilteredList = (filterList: UserAttributeFilters, hash: number) => !isEmpty(filterList) && inArray(filterList, hash); - if ( - !mpInstance._Store.webviewBridgeEnabled && - mpInstance._Store.activeForwarders - ) { - hashedEventName = KitFilterHelper.hashEventName( + const forwardingRuleMessageTypes = [ + MessageType.PageEvent, + MessageType.PageView, + MessageType.Commerce, + ]; + + if (!webviewBridgeEnabled && activeForwarders) { + const { hashEventName, hashEventType, hashAttributeConditionalForwarding } = KitFilterHelper; + hashedEventName = hashEventName( event.EventName, - event.EventCategory + + // FIXME: Set up union of EventType and EventCategory + event.EventCategory as valueof ); - hashedEventType = KitFilterHelper.hashEventType( - event.EventCategory + hashedEventType = hashEventType( + // FIXME: Set up union of EventType and EventCategory + event.EventCategory as valueof ); - for ( - var i = 0; - i < mpInstance._Store.activeForwarders.length; - i++ - ) { + for (let i = 0; i < activeForwarders.length; i++) { // Check attribute forwarding rule. This rule allows users to only forward an event if a // specific attribute exists and has a specific value. Alternatively, they can specify // that an event not be forwarded if the specified attribute name and value exists. // The two cases are controlled by the "includeOnMatch" boolean value. // Supported message types for attribute forwarding rules are defined in the forwardingRuleMessageTypes array + const { filteringEventAttributeValue } = activeForwarders[i]; + if ( + // FIXME: + // @ts-expect-error forwardingRuleMessageTypes.indexOf(event.EventDataType) > -1 && - mpInstance._Store.activeForwarders[i] - .filteringEventAttributeValue && - mpInstance._Store.activeForwarders[i] - .filteringEventAttributeValue.eventAttributeName && - mpInstance._Store.activeForwarders[i] - .filteringEventAttributeValue.eventAttributeValue + filteringEventAttributeValue && + filteringEventAttributeValue.eventAttributeName && + filteringEventAttributeValue.eventAttributeValue ) { - var foundProp = null; + let foundProp = null; // Attempt to find the attribute in the collection of event attributes if (event.EventAttributes) { - for (var prop in event.EventAttributes) { - var hashedEventAttributeName; - hashedEventAttributeName = KitFilterHelper.hashAttributeConditionalForwarding( - prop - ); + for (const prop in event.EventAttributes) { + const hashedEventAttributeName = hashAttributeConditionalForwarding(prop); if ( hashedEventAttributeName === @@ -299,19 +290,11 @@ export default function Forwarders(mpInstance, kitBlocker) { } } - var isMatch = - foundProp !== null && - foundProp.value === - mpInstance._Store.activeForwarders[i] - .filteringEventAttributeValue - .eventAttributeValue; + const isMatch = foundProp !== null && foundProp.value === activeForwarders[i].filteringEventAttributeValue.eventAttributeValue; - var shouldInclude = - mpInstance._Store.activeForwarders[i] - .filteringEventAttributeValue.includeOnMatch === - true - ? isMatch - : !isMatch; + const shouldInclude = activeForwarders[i].filteringEventAttributeValue.includeOnMatch === true + ? isMatch + : !isMatch; if (!shouldInclude) { continue; @@ -319,7 +302,7 @@ export default function Forwarders(mpInstance, kitBlocker) { } // Clone the event object, as we could be sending different attributes to each forwarder - clonedEvent = {}; + clonedEvent = {} as SDKEvent; clonedEvent = mpInstance._Helpers.extend( true, clonedEvent, @@ -327,20 +310,20 @@ export default function Forwarders(mpInstance, kitBlocker) { ); // Check event filtering rules if ( - event.EventDataType === Types.MessageType.PageEvent && + event.EventDataType === MessageType.PageEvent && (inFilteredList( - mpInstance._Store.activeForwarders[i].eventNameFilters, + activeForwarders[i].eventNameFilters, hashedEventName ) || inFilteredList( - mpInstance._Store.activeForwarders[i] + activeForwarders[i] .eventTypeFilters, hashedEventType )) ) { continue; } else if ( - event.EventDataType === Types.MessageType.Commerce && + event.EventDataType === MessageType.Commerce && inFilteredList( mpInstance._Store.activeForwarders[i].eventTypeFilters, hashedEventType @@ -348,7 +331,7 @@ export default function Forwarders(mpInstance, kitBlocker) { ) { continue; } else if ( - event.EventDataType === Types.MessageType.PageView && + event.EventDataType === MessageType.PageView && inFilteredList( mpInstance._Store.activeForwarders[i].screenNameFilters, hashedEventName @@ -359,14 +342,14 @@ export default function Forwarders(mpInstance, kitBlocker) { // Check attribute filtering rules if (clonedEvent.EventAttributes) { - if (event.EventDataType === Types.MessageType.PageEvent) { + if (event.EventDataType === MessageType.PageEvent) { filterAttributes( clonedEvent, mpInstance._Store.activeForwarders[i] .attributeFilters ); } else if ( - event.EventDataType === Types.MessageType.PageView + event.EventDataType === MessageType.PageView ) { filterAttributes( clonedEvent, @@ -379,23 +362,21 @@ export default function Forwarders(mpInstance, kitBlocker) { // Check user identity filtering rules filterUserIdentities( clonedEvent, - mpInstance._Store.activeForwarders[i].userIdentityFilters + activeForwarders[i].userIdentityFilters ); // Check user attribute filtering rules clonedEvent.UserAttributes = mpInstance._Helpers.filterUserAttributes( clonedEvent.UserAttributes, - mpInstance._Store.activeForwarders[i].userAttributeFilters + activeForwarders[i].userAttributeFilters ); - if (mpInstance._Store.activeForwarders[i].process) { + if (activeForwarders[i].process) { mpInstance.Logger.verbose( 'Sending message to forwarder: ' + - mpInstance._Store.activeForwarders[i].name - ); - var result = mpInstance._Store.activeForwarders[i].process( - clonedEvent + activeForwarders[i].name ); + const result = activeForwarders[i].process(clonedEvent); if (result) { mpInstance.Logger.verbose(result); @@ -405,7 +386,7 @@ export default function Forwarders(mpInstance, kitBlocker) { } }; - this.handleForwarderUserAttributes = function(functionNameKey, key, value) { + this.handleForwarderUserAttributes = (functionNameKey: string, key: string, value: string | string[]) => { if ( (kitBlocker && kitBlocker.isAttributeKeyBlocked(key)) || !mpInstance._Store.activeForwarders.length @@ -414,7 +395,7 @@ export default function Forwarders(mpInstance, kitBlocker) { } mpInstance._Store.activeForwarders.forEach(function(forwarder) { - const forwarderFunction = forwarder[functionNameKey]; + const forwarderFunction: IMPForwarder = forwarder[functionNameKey]; if ( !forwarderFunction || mpInstance._Helpers.isFilteredUserAttribute( @@ -425,7 +406,7 @@ export default function Forwarders(mpInstance, kitBlocker) { return; } try { - let result; + let result: string; if ( functionNameKey === @@ -443,21 +424,22 @@ export default function Forwarders(mpInstance, kitBlocker) { mpInstance.Logger.verbose(result); } } catch (e) { - mpInstance.Logger.error(e); + mpInstance.Logger.error(e as string); } }); }; // TODO: https://go.mparticle.com/work/SQDSDKS-6036 - this.setForwarderUserIdentities = function(userIdentities) { - mpInstance._Store.activeForwarders.forEach(function(forwarder) { - var filteredUserIdentities = mpInstance._Helpers.filterUserIdentities( + // @deprecated + this.setForwarderUserIdentities = (userIdentities: UserIdentities) => { + mpInstance._Store.activeForwarders.forEach((forwarder) => { + const filteredUserIdentities: ISDKUserIdentity[] = mpInstance._Helpers.filterUserIdentities( userIdentities, forwarder.userIdentityFilters ); if (forwarder.setUserIdentity) { - filteredUserIdentities.forEach(function(identity) { - var result = forwarder.setUserIdentity( + filteredUserIdentities.forEach((identity) => { + const result: string = forwarder.setUserIdentity( identity.Identity, identity.Type ); @@ -469,16 +451,16 @@ export default function Forwarders(mpInstance, kitBlocker) { }); }; - this.setForwarderOnUserIdentified = function(user) { - mpInstance._Store.activeForwarders.forEach(function(forwarder) { - var filteredUser = filteredMparticleUser( + this.setForwarderOnUserIdentified = (user: IMParticleUser) => { + mpInstance._Store.activeForwarders.forEach((forwarder: ConfiguredKit) => { + const filteredUser = filteredMparticleUser( user.getMPID(), forwarder, mpInstance, kitBlocker ); if (forwarder.onUserIdentified) { - var result = forwarder.onUserIdentified(filteredUser); + const result: string = forwarder.onUserIdentified(filteredUser); if (result) { mpInstance.Logger.verbose(result); } @@ -486,18 +468,18 @@ export default function Forwarders(mpInstance, kitBlocker) { }); }; - this.setForwarderOnIdentityComplete = function(user, identityMethod) { - var result; + this.setForwarderOnIdentityComplete = (user: IMParticleUser, identityMethod: IdentityAPIMethod) => { + let result: string; - mpInstance._Store.activeForwarders.forEach(function(forwarder) { - var filteredUser = filteredMparticleUser( + mpInstance._Store.activeForwarders.forEach((forwarder: ConfiguredKit) => { + const filteredUser: IMParticleUser = filteredMparticleUser( user.getMPID(), forwarder, mpInstance, kitBlocker ); - const filteredUserIdentities = filteredUser.getUserIdentities(); + const filteredUserIdentities: IdentityApiData = filteredUser.getUserIdentities(); if (identityMethod === Identify) { if (forwarder.onIdentifyComplete) { @@ -543,14 +525,11 @@ export default function Forwarders(mpInstance, kitBlocker) { }); }; - this.getForwarderStatsQueue = function() { - return mpInstance._Persistence.forwardingStatsBatches - .forwardingStatsEventQueue; - }; + this.getForwarderStatsQueue = () => + mpInstance._Persistence.forwardingStatsBatches.forwardingStatsEventQueue; - this.setForwarderStatsQueue = function(queue) { + this.setForwarderStatsQueue = (queue: IForwardingStatsData[]) => mpInstance._Persistence.forwardingStatsBatches.forwardingStatsEventQueue = queue; - }; // Processing forwarders is a 2 step process: // 1. Configure the kit @@ -558,20 +537,21 @@ export default function Forwarders(mpInstance, kitBlocker) { // There are 2 types of kits: // 1. UI-enabled kits // 2. Sideloaded kits. - this.processForwarders = function(config, forwardingStatsCallback) { + this.processForwarders = (config: SDKInitConfig, forwardingStatsCallback: Callback) => { if (!config) { mpInstance.Logger.warning( 'No config was passed. Cannot process forwarders' ); - } else { - this.processUIEnabledKits(config); - this.processSideloadedKits(config); - - self.initForwarders( - mpInstance._Store.SDKConfig.identifyRequest.userIdentities, - forwardingStatsCallback - ); + return; } + + this.processUIEnabledKits(config); + this.processSideloadedKits(config); + + self.initForwarders( + mpInstance._Store.SDKConfig.identifyRequest.userIdentities, + forwardingStatsCallback + ); }; // These are kits that are enabled via the mParticle UI. @@ -580,14 +560,12 @@ export default function Forwarders(mpInstance, kitBlocker) { // The kit configuration will be compared with the kit constructors to determine // if there is a match before being initialized. // Only kits that are configured properly can be active and used for kit forwarding. - this.processUIEnabledKits = function(config) { - let kits = this.returnKitConstructors(); + this.processUIEnabledKits = (config: SDKInitConfig) => { + const kits: Dictionary = this.returnKitConstructors(); try { - if (Array.isArray(config.kitConfigs) && config.kitConfigs.length) { - config.kitConfigs.forEach(function(kitConfig) { - self.configureUIEnabledKit(kitConfig, kits); - }); + if (Array.isArray(config.kitConfigs) && !isEmpty(config.kitConfigs)) { + config.kitConfigs.forEach((kitConfig) => self.configureUIEnabledKit(kitConfig, kits)); } } catch (e) { mpInstance.Logger.error( @@ -597,7 +575,8 @@ export default function Forwarders(mpInstance, kitBlocker) { } }; - this.returnKitConstructors = function() { + this.returnKitConstructors = () => { + // FIXME: Try to set this up with registered kits or something similar let kits = {}; // If there are kits inside of mpInstance._Store.SDKConfig.kits, then mParticle is self hosted if (!isEmpty(mpInstance._Store.SDKConfig.kits)) { @@ -625,26 +604,24 @@ export default function Forwarders(mpInstance, kitBlocker) { return kits; }; - this.configureUIEnabledKit = function(configuration, kits) { - let newKit = null; - const config = configuration; + this.configureUIEnabledKit = (config: IKitConfigs, kits: Dictionary) => { + let newKit: ConfiguredKit | null = null; + const { SDKConfig } = mpInstance._Store; + + for (let kitName in kits) { + const { suffix, name, isDebug, isSandbox } = config; - for (let name in kits) { // Configs are returned with suffixes also. We need to consider the // config suffix here to match the constructor suffix - let kitNameWithConfigSuffix; - if (config.suffix) { - kitNameWithConfigSuffix = `${config.name}-${config.suffix}`; - } + const kitNameWithConfigSuffix: string = suffix ? `${name}-${suffix}` : undefined; - if (name === kitNameWithConfigSuffix || name === config.name) { - if ( - config.isDebug === - mpInstance._Store.SDKConfig.isDevelopmentMode || - config.isSandbox === - mpInstance._Store.SDKConfig.isDevelopmentMode - ) { - newKit = this.returnConfiguredKit(kits[name], config); + const isDevelopmentMode: boolean = + isDebug === SDKConfig.isDevelopmentMode || + isSandbox === SDKConfig.isDevelopmentMode; + + if (kitName === kitNameWithConfigSuffix || kitName === name) { + if (isDevelopmentMode) { + newKit = this.returnConfiguredKit(kits[kitName], config); mpInstance._Store.configuredForwarders.push(newKit); break; @@ -660,20 +637,24 @@ export default function Forwarders(mpInstance, kitBlocker) { // In the future, when all kits are moved to the mpConfig rather than // there being a separate process for MP configured kits and // sideloaded kits, this will need to be refactored. - this.processSideloadedKits = function(mpConfig) { + // FIXME: Fix types here + this.processSideloadedKits = (mpConfig: SDKInitConfig) => { try { if (Array.isArray(mpConfig.sideloadedKits)) { - const registeredSideloadedKits = { kits: {} }; + const registeredSideloadedKits: KitRegistrationConfig = { kits: {} }; + + // FIXME: Expected type causes error const unregisteredSideloadedKits = mpConfig.sideloadedKits; - unregisteredSideloadedKits.forEach(function(unregisteredKit) { + // FIXME: Define type + unregisteredSideloadedKits.forEach((unregisteredKit) => { try { // Register each sideloaded kit, which adds a key of the sideloaded kit name // and a value of the sideloaded kit constructor. unregisteredKit.kitInstance.register( registeredSideloadedKits ); - const kitName = unregisteredKit.kitInstance.name; + const kitName: string = unregisteredKit.kitInstance.name; // Then add the kit filters to each registered kit. registeredSideloadedKits.kits[kitName].filters = unregisteredKit.filterDictionary; @@ -708,14 +689,16 @@ export default function Forwarders(mpInstance, kitBlocker) { }; // kits can be included via mParticle UI, or via sideloaded kit config API - this.configureSideloadedKit = function(kitConstructor) { + this.configureSideloadedKit = (kitConstructor: RegisteredKit) => { mpInstance._Store.configuredForwarders.push( - this.returnConfiguredKit(kitConstructor, kitConstructor.filters) + // FIXME: Figure out why filters should be typed as IKitConfigs + this.returnConfiguredKit(kitConstructor, kitConstructor.filters as IKitConfigs) ); }; - this.returnConfiguredKit = function(forwarder, config = {}) { - const newForwarder = new forwarder.constructor(); + this.returnConfiguredKit = (forwarder: RegisteredKit, config: IKitConfigs) => { + // FIXME: Make this a real type + const newForwarder: ConfiguredKit = new forwarder.constructor() as ConfiguredKit; newForwarder.id = config.moduleId; // TODO: isSandbox, hasSandbox is never used in any kit or in core SDK. @@ -739,33 +722,33 @@ export default function Forwarders(mpInstance, kitBlocker) { newForwarder.userAttributeFilters = config.userAttributeFilters || []; newForwarder.filteringEventAttributeValue = - config.filteringEventAttributeValue || {}; + config.filteringEventAttributeValue || {} as IFilteringEventAttributeValue; newForwarder.filteringUserAttributeValue = - config.filteringUserAttributeValue || {}; + config.filteringUserAttributeValue || {} as IFilteringUserAttributeValue; newForwarder.eventSubscriptionId = config.eventSubscriptionId || null; newForwarder.filteringConsentRuleValues = - config.filteringConsentRuleValues || {}; + config.filteringConsentRuleValues || {} as IFilteringConsentRuleValues; newForwarder.excludeAnonymousUser = config.excludeAnonymousUser || false; return newForwarder; }; - this.configurePixel = function(settings) { + this.configurePixel = (settings: IPixelConfiguration) => { + const { SDKConfig } = mpInstance._Store; + if ( - settings.isDebug === - mpInstance._Store.SDKConfig.isDevelopmentMode || - settings.isProduction !== - mpInstance._Store.SDKConfig.isDevelopmentMode + settings.isDebug === SDKConfig.isDevelopmentMode || + settings.isProduction !== SDKConfig.isDevelopmentMode ) { mpInstance._Store.pixelConfigurations.push(settings); } }; - this.processPixelConfigs = function(config) { + this.processPixelConfigs = (config: SDKInitConfig) => { try { if (!isEmpty(config.pixelConfigs)) { - config.pixelConfigs.forEach(function(pixelConfig) { + config.pixelConfigs.forEach((pixelConfig: IPixelConfiguration) => { self.configurePixel(pixelConfig); }); } @@ -777,9 +760,9 @@ export default function Forwarders(mpInstance, kitBlocker) { } }; - this.sendSingleForwardingStatsToServer = async forwardingStatsData => { + this.sendSingleForwardingStatsToServer = async (forwardingStatsData: IForwardingStatsData) => { // https://go.mparticle.com/work/SQDSDKS-6568 - const fetchPayload = { + const fetchPayload: IFetchPayload = { method: 'post', body: JSON.stringify(forwardingStatsData), headers: { @@ -788,9 +771,9 @@ export default function Forwarders(mpInstance, kitBlocker) { }, }; - const response = await this.forwarderStatsUploader.upload(fetchPayload); + const response: Response = await this.forwarderStatsUploader.upload(fetchPayload); - let message; + let message: string; // This is a fire and forget, so we only need to log the response based on the code, and not return any response body if (response.status === 202) { // https://go.mparticle.com/work/SQDSDKS-6670 diff --git a/src/identity-user-interfaces.ts b/src/identity-user-interfaces.ts index fe2022746..c82116eba 100644 --- a/src/identity-user-interfaces.ts +++ b/src/identity-user-interfaces.ts @@ -29,7 +29,7 @@ interface ICart { // https://go.mparticle.com/work/SQDSDKS-5033 // https://go.mparticle.com/work/SQDSDKS-6354 export interface IMParticleUser extends User { - getAllUserAttributes(): any; + getAllUserAttributes(): UserAttributes; setUserTag(tagName: string, value?: any): void; setUserAttribute(key: string, value: any): void; getUserAudiences?(callback?: IdentityCallback): void; diff --git a/src/kitBlocking.ts b/src/kitBlocking.ts index 17622faca..956677ee6 100644 --- a/src/kitBlocking.ts +++ b/src/kitBlocking.ts @@ -1,7 +1,7 @@ import { convertEvent } from './sdkToEventsApiConverter'; -import { SDKEvent, MParticleWebSDK, KitBlockerDataPlan, SDKProduct } from './sdkRuntimeModels'; +import { SDKEvent, KitBlockerDataPlan, SDKProduct } from './sdkRuntimeModels'; import { BaseEvent, EventTypeEnum, CommerceEvent, ScreenViewEvent, CustomEvent } from '@mparticle/event-models'; -import Types from './types' +import Types, { CommerceEventType } from './types' import { DataPlanPoint } from '@mparticle/data-planning-models'; import { IMParticleWebSDKInstance } from './mp-instance'; @@ -415,12 +415,12 @@ export default class KitBlocker { } if (matchedEvent) { switch (event.EventCategory) { - case Types.CommerceEventType.ProductImpression: + case CommerceEventType.ProductImpression: clonedEvent.ProductImpressions.forEach(impression=> { removeAttribute(matchedEvent, impression?.ProductList) }); break; - case Types.CommerceEventType.ProductPurchase: + case CommerceEventType.ProductPurchase: removeAttribute(matchedEvent, clonedEvent.ProductAction?.ProductList) break; default: diff --git a/src/kitFilterHelper.ts b/src/kitFilterHelper.ts index 0bbb44ba6..160b28033 100644 --- a/src/kitFilterHelper.ts +++ b/src/kitFilterHelper.ts @@ -1,16 +1,19 @@ import { generateHash, valueof } from "./utils"; // TODO: https://mparticle-eng.atlassian.net/browse/SQDSDKS-5381 -import { EventType, IdentityType } from "./types"; +import { CommerceEventType, EventType, IdentityType } from "./types"; export default class KitFilterHelper { + // static hashEventType(eventType: valueof | valueof): number { static hashEventType(eventType: valueof): number { return generateHash(eventType as unknown as string); }; + // static hashEventName(eventName: string, eventType: valueof | valueof): number { static hashEventName(eventName: string, eventType: valueof): number { return generateHash(eventType + eventName); }; + // static hashEventAttributeKey(eventType: valueof | valueof, eventName: string, customAttributeName: string): number { static hashEventAttributeKey(eventType: valueof, eventName: string, customAttributeName: string): number { return generateHash(eventType + eventName + customAttributeName); } diff --git a/src/mp-instance.ts b/src/mp-instance.ts index ff74a52d9..b1258c2bf 100644 --- a/src/mp-instance.ts +++ b/src/mp-instance.ts @@ -49,6 +49,7 @@ import { IECommerce } from './ecommerce.interfaces'; import { INativeSdkHelpers } from './nativeSdkHelpers.interfaces'; import { IPersistence } from './persistence.interfaces'; import ForegroundTimer from './foregroundTimeTracker'; +import { IMPForwarder } from './forwarders.interfaces'; import RoktManager from './roktManager'; export interface IErrorLogMessage { @@ -73,7 +74,7 @@ export interface IMParticleWebSDKInstance extends MParticleWebSDK { _CookieSyncManager: ICookieSyncManager; _Ecommerce: IECommerce; _Events: IEvents; - _Forwarders: any; // https://go.mparticle.com/work/SQDSDKS-5767 + _Forwarders: IMPForwarder _ForwardingStatsUploader: ForwardingStatsUploader; _Helpers: SDKHelpersApi; _Identity: IIdentity; diff --git a/src/pre-init-utils.ts b/src/pre-init-utils.ts index 63505e25e..3d2ac42ba 100644 --- a/src/pre-init-utils.ts +++ b/src/pre-init-utils.ts @@ -1,12 +1,12 @@ import { IPixelConfiguration } from './cookieSyncManager'; -import { MPForwarder } from './forwarders.interfaces'; +import { UnregisteredKit } from './forwarders.interfaces'; import { IntegrationDelays } from './mp-instance'; import { isEmpty, isFunction } from './utils'; export interface IPreInit { readyQueue: Function[] | any[]; integrationDelays: IntegrationDelays; - forwarderConstructors: MPForwarder[]; + forwarderConstructors: UnregisteredKit[]; pixelConfigurations?: IPixelConfiguration[]; isDevelopmentMode?: boolean; } diff --git a/src/sdkRuntimeModels.ts b/src/sdkRuntimeModels.ts index 5a3e238e3..2e77c8d66 100644 --- a/src/sdkRuntimeModels.ts +++ b/src/sdkRuntimeModels.ts @@ -6,15 +6,16 @@ import { SDKEventOptions, SDKEventAttrs, Callback, + UserIdentities, } from '@mparticle/web-sdk'; import { IntegrationAttribute, IntegrationAttributes, IStore, WrapperSDKTypes } from './store'; import Validators from './validators'; import { Dictionary, valueof } from './utils'; import { IKitConfigs } from './configAPIClient'; import { SDKConsentApi, SDKConsentState } from './consent'; -import MPSideloadedKit from './sideloadedKit'; +import MPSideloadedKit, { IMPSideloadedKit } from './sideloadedKit'; import { ISessionManager } from './sessionManager'; -import { ConfiguredKit, MPForwarder, UnregisteredKit } from './forwarders.interfaces'; +import { ConfiguredKit, UnregisteredKit, UserAttributeFilters, UserIdentityFilters } from './forwarders.interfaces'; import { SDKIdentityApi, IAliasCallback, @@ -26,6 +27,7 @@ import { ISDKUserIdentity, IdentityCallback, ISDKUserAttributes, + UserAttributes, } from './identity-user-interfaces'; import { CommerceEventType, @@ -48,8 +50,9 @@ export interface SDKEvent { DeviceId: string; IsFirstRun: boolean; EventName: string; + // EventCategory: valueof | valueof; EventCategory: number; - UserAttributes?: ISDKUserAttributes; + UserAttributes?: UserAttributes; UserIdentities?: ISDKUserIdentity[]; SourceMessageId: string; MPID: string; @@ -60,6 +63,7 @@ export interface SDKEvent { SessionLength?: number; currentSessionMPIDs?: string[]; Timestamp: number; + // EventDataType: valueof; EventDataType: number; Debug: boolean; Location?: SDKGeoLocation; @@ -273,7 +277,7 @@ export interface SDKInitConfig kitConfigs?: IKitConfigs[]; kits?: Dictionary; - sideloadedKits?: MPForwarder[]; + sideloadedKits?: IMPSideloadedKit[]; dataPlanOptions?: KitBlockerOptions; flags?: Dictionary; pixelConfigs?: IPixelConfiguration[]; @@ -317,6 +321,9 @@ export interface SDKHelpersApi { createServiceUrl(url: string, devToken?: string): string; createXHR?(cb: () => void): XMLHttpRequest; extend?(...args: any[]); + isFilteredUserAttribute?: (key: string, filterList: UserAttributeFilters) => boolean; + filterUserAttributes?: (userAttributes: UserAttributes, filterList: UserAttributeFilters) => ISDKUserAttributes; + filterUserIdentities?: (userIdentities: UserIdentities, filterList: UserIdentityFilters) => ISDKUserIdentity[]; findKeyInObject?(obj: any, key: string): string; parseNumber?(value: string | number): number; generateUniqueId(); @@ -374,8 +381,10 @@ export interface SDKConfigApi { } export interface BaseEvent { + // messageType: valueof; messageType: number; name?: string; + // eventType?: valueof | valueof; eventType?: number; data?: SDKEventAttrs; customFlags?: { [key: string]: string }; diff --git a/src/sdkToEventsApiConverter.ts b/src/sdkToEventsApiConverter.ts index 1bfe59d1e..c2c2acbbe 100644 --- a/src/sdkToEventsApiConverter.ts +++ b/src/sdkToEventsApiConverter.ts @@ -11,8 +11,8 @@ import { SDKGDPRConsentState, SDKCCPAConsentState, } from './consent'; -import Types from './types'; -import { Dictionary, isEmpty } from './utils'; +import Types, { CommerceEventType, EventType } from './types'; +import { Dictionary, isEmpty, valueof } from './utils'; import { ISDKUserIdentity } from './identity-user-interfaces'; import { SDKIdentityTypeEnum } from './identity.interfaces'; import Constants from './constants'; @@ -113,7 +113,7 @@ export function convertEvents( ? window.screen.height : 0, }, - user_attributes: lastEvent.UserAttributes, + user_attributes: lastEvent.UserAttributes as Record, user_identities: convertUserIdentities(lastEvent.UserIdentities), consent_state: convertConsentState(currentConsentState), integration_attributes: lastEvent.IntegrationAttributes, @@ -592,6 +592,7 @@ export function convertCustomEvent(sdkEvent: SDKEvent): EventsApi.CustomEvent { } export function convertSdkEventType( + // sdkEventType: valueof | valueof sdkEventType: number ): | EventsApi.CustomEventDataCustomEventTypeEnum diff --git a/src/serverModel.ts b/src/serverModel.ts index c7cd2c9bd..598ef67ee 100644 --- a/src/serverModel.ts +++ b/src/serverModel.ts @@ -384,8 +384,8 @@ export default function ServerModel( this.convertEventToV2DTO = function(event: IUploadObject): IServerV2DTO { var dto: Partial = { n: event.EventName, - et: event.EventCategory, - ua: event.UserAttributes, + et: event.EventCategory as number, + ua: event.UserAttributes as Record, ui: event.UserIdentities, ia: event.IntegrationAttributes, str: event.Store, diff --git a/src/sideloadedKit.ts b/src/sideloadedKit.ts index 5bc6d1e63..05abdb67a 100644 --- a/src/sideloadedKit.ts +++ b/src/sideloadedKit.ts @@ -9,10 +9,12 @@ import { UnregisteredKit } from './forwarders.interfaces'; import { EventType, IdentityType } from './types'; import { valueof } from './utils'; +// FIXME: Decide if this should extend Kit or RegisteredKit depending on the overlap export interface IMPSideloadedKit { kitInstance: UnregisteredKit; filterDictionary: IKitFilterSettings; + // Custom filter methods used only for sideloaded kits addEventTypeFilter(eventType: valueof): void; addEventNameFilter(eventType: valueof, eventName: string): void; addEventAttributeFilter( @@ -120,6 +122,10 @@ export default class MPSideloadedKit implements IMPSideloadedKit{ const hashedUserAttributeKey = KitFilterHelper.hashUserAttribute( userAttributeKey ); + + // FIXME: this should technically be a string, but we are expecting a number + // and is bvreaking tests + // @ts-ignore this.filterDictionary.userAttributeFilters.push(hashedUserAttributeKey); } } diff --git a/src/store.ts b/src/store.ts index 1f6179323..f76ab3ec6 100644 --- a/src/store.ts +++ b/src/store.ts @@ -30,7 +30,7 @@ import { returnConvertedBoolean, } from './utils'; import { IMinifiedConsentJSONObject, SDKConsentState } from './consent'; -import { ConfiguredKit, MPForwarder, UnregisteredKit } from './forwarders.interfaces'; +import { ConfiguredKit, UnregisteredKit } from './forwarders.interfaces'; import { IdentityCallback, UserAttributes } from './identity-user-interfaces'; import { IGlobalStoreV2MinifiedKeys, @@ -39,6 +39,7 @@ import { import { CookieSyncDates, IPixelConfiguration } from './cookieSyncManager'; import { IMParticleWebSDKInstance } from './mp-instance'; import ForegroundTimer from './foregroundTimeTracker'; +import { IMPSideloadedKit } from './sideloadedKit'; // This represents the runtime configuration of the SDK AFTER // initialization has been complete and all settings and @@ -69,7 +70,7 @@ export interface SDKConfig { identifyRequest: IdentifyRequest; identityCallback: IdentityCallback; integrationDelayTimeout: number; - sideloadedKits: MPForwarder[]; + sideloadedKits: IMPSideloadedKit[]; aliasMaxWindow: number; deviceId?: string; forceHttps?: boolean; @@ -179,9 +180,9 @@ export interface IStore { storageName: string | null; prodStorageName: string | null; activeForwarders: ConfiguredKit[]; - kits: Dictionary; - sideloadedKits: MPForwarder[]; - configuredForwarders: MPForwarder[]; + kits: Dictionary; + sideloadedKits: IMPSideloadedKit[]; + configuredForwarders: ConfiguredKit[]; pixelConfigurations: IPixelConfiguration[]; integrationDelayTimeoutStart: number; // UNIX Timestamp webviewBridgeEnabled?: boolean; diff --git a/src/utils.ts b/src/utils.ts index a5e6fbc6a..21f1d816a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -16,7 +16,7 @@ const createCookieString = (value: string): string => const revertCookieString = (value: string): string => replacePipesWithCommas(replaceApostrophesWithQuotes(value)); -const inArray = (items: any[], name: string): boolean => { +const inArray = (items: any[], name: any): boolean => { let i = 0; if (Array.prototype.indexOf) { diff --git a/test/jest/utils.spec.ts b/test/jest/utils.spec.ts index d6d427c9c..f348fe2f0 100644 --- a/test/jest/utils.spec.ts +++ b/test/jest/utils.spec.ts @@ -5,6 +5,7 @@ import { replaceMPID, replaceAmpWithAmpersand, createCookieSyncUrl, + inArray, } from '../../src/utils'; import { deleteAllCookies } from './utils'; @@ -185,6 +186,24 @@ describe('Utils', () => { }); }); + describe('inArray', () => { + it('returns true if the item is in the array', () => { + expect(inArray(['foo', 'bar'], 'foo')).toBe(true); + expect(inArray([1, 2], 2)).toBe(true); + }); + + it('returns false if the item is not in the array', () => { + expect(inArray(['foo', 'bar'], 'baz')).toBe(false); + expect(inArray([1, 2], 3)).toBe(false); + }); + + it('returns false if the array is empty', () => { + expect(inArray([], 'foo')).toBe(false); + expect(inArray([], 1)).toBe(false); + }); + + }); + describe('#replaceMPID', () => { it('replaces the MPID in a string', () => { const mpid = '1234'; diff --git a/test/src/tests-apiClient.ts b/test/src/tests-apiClient.ts index 614045fbb..06473a720 100644 --- a/test/src/tests-apiClient.ts +++ b/test/src/tests-apiClient.ts @@ -93,7 +93,7 @@ describe('Api Client', () => { getConsentState: () => { return consentState; }, - } as IMParticleUser; + } as unknown as IMParticleUser; }; mParticle diff --git a/test/src/tests-forwarders.ts b/test/src/tests-forwarders.ts index 11156d7cf..df1333eae 100644 --- a/test/src/tests-forwarders.ts +++ b/test/src/tests-forwarders.ts @@ -16,6 +16,9 @@ import { IdentityType } from '../../src/types'; import { IntegrationAttribute } from '../../src/store'; import { IConsentRules } from '../../src/consent'; import { UserIdentities } from '@mparticle/web-sdk'; +import { IMPSideloadedKit } from '../../src/sideloadedKit'; +import { UnregisteredKit } from '../../src/forwarders.interfaces'; +import { IFilteringUserAttributeValue } from '../../src/configAPIClient'; const { @@ -2048,7 +2051,7 @@ describe('forwarders', function() { enabled = mParticle .getInstance() - ._Forwarders.isEnabledForUserAttributes({}, null); + ._Forwarders.isEnabledForUserAttributes({} as IFilteringUserAttributeValue, null); expect(enabled).to.be.ok; }); @@ -3155,10 +3158,10 @@ describe('forwarders', function() { }); describe('filter dictionary integration tests', function() { - let sideloadedKit1; - let sideloadedKit2; - let mpSideloadedKit1; - let mpSideloadedKit2; + let sideloadedKit1: UnregisteredKit; + let sideloadedKit2: UnregisteredKit; + let mpSideloadedKit1: IMPSideloadedKit; + let mpSideloadedKit2: IMPSideloadedKit; beforeEach(function() { sideloadedKit1 = new MockSideloadedKit('SideloadedKit1', 1); @@ -3201,6 +3204,7 @@ describe('forwarders', function() { // The received event gets replaced by the last event sent to the forwarder // SideloadedKit11 has received the session start event, but not the Test Event // SideloadedKit22 will receive the Test Event + window.SideloadedKit11.instance.receivedEvent.EventName.should.not.equal( 'Test Event' ); diff --git a/test/src/tests-identities-attributes.ts b/test/src/tests-identities-attributes.ts index 1c9fdd222..1f8cff916 100644 --- a/test/src/tests-identities-attributes.ts +++ b/test/src/tests-identities-attributes.ts @@ -643,7 +643,7 @@ describe('identities and attributes', function() { const userAttributes = mParticle.Identity.getCurrentUser().getAllUserAttributes(); userAttributes.blah = 'test'; - userAttributes['numbers'].push(6); + (userAttributes['numbers'] as number[]).push(6); const userAttributes1 = mParticle.Identity.getCurrentUser().getAllUserAttributes(); diff --git a/test/src/tests-runtimeToBatchEventsDTO.ts b/test/src/tests-runtimeToBatchEventsDTO.ts index fb4522209..9dca1f019 100644 --- a/test/src/tests-runtimeToBatchEventsDTO.ts +++ b/test/src/tests-runtimeToBatchEventsDTO.ts @@ -66,7 +66,7 @@ describe('Old model to batch model conversion', () => { getConsentState: () => { return null; }, - } as IMParticleUser; + } as unknown as IMParticleUser; }; const publicEvent = { @@ -143,7 +143,7 @@ describe('Old model to batch model conversion', () => { getConsentState: () => { return null; }, - } as IMParticleUser; + } as unknown as IMParticleUser; }; const publicEvent = { messageType: Types.MessageType.PageEvent, diff --git a/test/src/tests-serverModel.ts b/test/src/tests-serverModel.ts index 3e96e630f..724dd0622 100644 --- a/test/src/tests-serverModel.ts +++ b/test/src/tests-serverModel.ts @@ -1319,7 +1319,7 @@ describe('ServerModel', () => { getConsentState: () => { return consentState; }, - } as IMParticleUser; + } as unknown as IMParticleUser; }; let sdkEvent = mParticle .getInstance() diff --git a/test/src/tests-utils.ts b/test/src/tests-utils.ts index 3e224eb42..1ca10fa1b 100644 --- a/test/src/tests-utils.ts +++ b/test/src/tests-utils.ts @@ -6,7 +6,6 @@ import { generateHash, generateUniqueId, getRampNumber, - inArray, isDataPlanSlug, isEmpty, isObject, @@ -228,20 +227,6 @@ describe('Utils', () => { }); }); - describe('#inArray', () => { - it('returns true if element is in the array', ()=> { - const things = ['people', 'places', 'things']; - - expect(inArray(things, 'people')).to.eq(true); - }); - - it('returns false if element is not in the array', ()=> { - const things = ['people', 'places', 'things']; - - expect(inArray(things, 'cats')).to.eq(false); - }); - }); - describe('#findKeyInObject', () => { it('returns the key if it exists in the object', () => { const things = {