diff --git a/src/consent.ts b/src/consent.ts index 81ae944cd..bcf1f6258 100644 --- a/src/consent.ts +++ b/src/consent.ts @@ -9,6 +9,7 @@ import KitFilterHelper from './kitFilterHelper'; import Constants from './constants'; import { IMParticleUser } from './identity-user-interfaces'; import { IMParticleWebSDKInstance } from './mp-instance'; +import { logDeprecatedMethodUsage } from './reporting/deprecatedMethodLogger'; const { CCPAPurpose } = Constants; @@ -505,8 +506,13 @@ export default function Consent(this: IConsent, mpInstance: IMParticleWebSDKInst // TODO: Can we remove this? It is deprecated. function removeCCPAState(this: ConsentState) { - mpInstance.Logger.warning( - 'removeCCPAState is deprecated and will be removed in a future release; use removeCCPAConsentState instead' + logDeprecatedMethodUsage( + { + methodName: 'Consent.removeCCPAState', + warningMessage: 'removeCCPAState is deprecated and will be removed in a future release; use removeCCPAConsentState instead', + }, + mpInstance.Logger, + mpInstance._LoggingDispatcher ); // @ts-ignore return removeCCPAConsentState(); diff --git a/src/forwarders.interfaces.ts b/src/forwarders.interfaces.ts index 17caa1a67..76651219b 100644 --- a/src/forwarders.interfaces.ts +++ b/src/forwarders.interfaces.ts @@ -1,8 +1,16 @@ -import { SDKEvent, SDKEventCustomFlags } from './sdkRuntimeModels'; +import { SDKEvent, SDKEventCustomFlags, SDKLoggerApi } from './sdkRuntimeModels'; import { Dictionary } from './utils'; -import { IKitConfigs, IKitFilterSettings } from './configAPIClient'; +import { + IKitConfigs, + IKitFilterSettings, + IConfigResponse, + IFilteringUserAttributeValue, +} from './configAPIClient'; +import { IForwardingStatsData } from './apiClient'; import { IdentityApiData, IdentityType } from '@mparticle/web-sdk'; import { Batch } from '@mparticle/event-models'; +import { AsyncUploader } from './uploaders'; +import { IPixelConfiguration } from './cookieSyncManager'; import { IMParticleUser, @@ -31,6 +39,11 @@ export interface UnregisteredKit { suffix?: string; } +export interface SideloadedKit { + kitInstance: UnregisteredKit; + filterDictionary: IKitFilterSettings; +} + // The state of the kit after being added to forwarderConstructors in the CDN // or after registered to SDKConfig.kits via NPM // Sideloaded Kits would also be considered registered @@ -81,6 +94,7 @@ export interface ConfiguredKit ): string; onUserIdentified(user: IMParticleUser): string; process(event: SDKEvent): string; + processBatch?(batch: Batch): string; setOptOut(isOptingOut: boolean): string; removeUserAttribute(key: string): string; setUserAttribute(key: string, value: string): string; @@ -89,6 +103,9 @@ export interface ConfiguredKit // TODO: https://go.mparticle.com/work/SQDSDKS-5156 isSandbox: boolean; hasSandbox: boolean; + + initialized?: boolean; + logger?: SDKLoggerApi; } export interface KitInterface { @@ -140,3 +157,57 @@ export type forwardingStatsCallback = ( forwarder: ConfiguredKit, event: SDKEvent ) => void; + +export interface IForwarders { + forwarderStatsUploader: AsyncUploader; + initForwarders( + userIdentities: ISDKUserIdentity[], + forwardingStatsCallback: forwardingStatsCallback + ): void; + isEnabledForUserAttributes( + filterObject: IFilteringUserAttributeValue, + user: IMParticleUser + ): boolean; + isEnabledForUnknownUser( + excludeAnonymousUserBoolean: boolean, + user: IMParticleUser + ): boolean; + applyToForwarders(functionName: string, functionArgs: unknown): void; + sendEventToForwarders(event: SDKEvent): void; + sendBatchToForwarders(batch: Batch): void; + handleForwarderUserAttributes( + functionNameKey: string, + key: string, + value: string + ): void; + setForwarderUserIdentities(userIdentities: ISDKUserIdentity[]): void; + setForwarderOnUserIdentified(user: IMParticleUser): void; + setForwarderOnIdentityComplete( + user: IMParticleUser, + identityMethod: string + ): void; + getForwarderStatsQueue(): IForwardingStatsData[]; + setForwarderStatsQueue(queue: IForwardingStatsData[]): void; + processForwarders( + config: IConfigResponse, + forwardingStatsCallback: forwardingStatsCallback + ): void; + processUIEnabledKits(config: IConfigResponse): void; + returnKitConstructors(): Dictionary; + configureUIEnabledKit( + configuration: IKitConfigs, + kits: Dictionary + ): void; + processSideloadedKits(mpConfig: IConfigResponse & { sideloadedKits?: SideloadedKit[] }): void; + configureSideloadedKit(kitConstructor: RegisteredKit): void; + returnConfiguredKit( + forwarder: RegisteredKit, + config: Partial + ): MPForwarder; + configurePixel(settings: IPixelConfiguration): void; + processPixelConfigs(config: IConfigResponse): void; + sendSingleForwardingStatsToServer( + forwardingStatsData: IForwardingStatsData + ): Promise; +} + diff --git a/src/forwarders.js b/src/forwarders.ts similarity index 74% rename from src/forwarders.js rename to src/forwarders.ts index 889e339dc..fcbfdce44 100644 --- a/src/forwarders.js +++ b/src/forwarders.ts @@ -1,8 +1,8 @@ import filteredMparticleUser from './filteredMparticleUser'; -import { isEmpty, extend } from './utils'; +import { isEmpty, extend, Dictionary } from './utils'; import KitFilterHelper from './kitFilterHelper'; import Constants from './constants'; -import APIClient from './apiClient'; +import APIClient, { IForwardingStatsData } from './apiClient'; import { isBlockedByForwardingRule, isBlockedByEventFilter, @@ -12,11 +12,34 @@ import { filterBatchEventAttributes, filterBatchIdentities, } from './forwarder-utils'; +import { IMParticleWebSDKInstance } from './mp-instance'; +import { SDKEvent } from './sdkRuntimeModels'; +import { + IForwarders, + MPForwarder, + RegisteredKit, + ConfiguredKit, + forwardingStatsCallback as ForwardingStatsCallback, + SideloadedKit, +} from './forwarders.interfaces'; +import { + IConfigResponse, + IKitConfigs, + IFilteringUserAttributeValue, + IKitFilterSettings, +} from './configAPIClient'; +import { IPixelConfiguration } from './cookieSyncManager'; +import { Batch } from '@mparticle/event-models'; +import { IMParticleUser, ISDKUserIdentity } from './identity-user-interfaces'; +import KitBlocker from './kitBlocking'; const { Modify, Identify, Login, Logout } = Constants.IdentityMethods; -export default function Forwarders(mpInstance, kitBlocker) { - var self = this; +export default function Forwarders( + this: IForwarders, + mpInstance: IMParticleWebSDKInstance, + kitBlocker: KitBlocker +): void { this.forwarderStatsUploader = new APIClient( mpInstance, kitBlocker @@ -27,8 +50,11 @@ export default function Forwarders(mpInstance, kitBlocker) { removeUserAttribute: 'removeUserAttribute', }; - this.initForwarders = function(userIdentities, forwardingStatsCallback) { - var user = mpInstance.Identity.getCurrentUser(); + this.initForwarders = function( + userIdentities: ISDKUserIdentity[], + forwardingStatsCallback: ForwardingStatsCallback + ): void { + const user = mpInstance.Identity.getCurrentUser(); if ( !mpInstance._Store.webviewBridgeEnabled && mpInstance._Store.configuredForwarders @@ -42,8 +68,8 @@ export default function Forwarders(mpInstance, kitBlocker) { ); }); - mpInstance._Store.activeForwarders = mpInstance._Store.configuredForwarders.filter( - function(forwarder) { + mpInstance._Store.activeForwarders = (mpInstance._Store.configuredForwarders as unknown as ConfiguredKit[]).filter( + (forwarder) => { if ( !mpInstance._Consent.isEnabledForUserConsent( forwarder.filteringConsentRuleValues, @@ -53,7 +79,7 @@ export default function Forwarders(mpInstance, kitBlocker) { return false; } if ( - !self.isEnabledForUserAttributes( + !(this.isEnabledForUserAttributes as Function)( forwarder.filteringUserAttributeValue, user ) @@ -61,7 +87,7 @@ export default function Forwarders(mpInstance, kitBlocker) { return false; } if ( - !self.isEnabledForUnknownUser( + !(this.isEnabledForUnknownUser as Function)( forwarder.excludeAnonymousUser, user ) @@ -69,7 +95,7 @@ export default function Forwarders(mpInstance, kitBlocker) { return false; } - var filteredUserIdentities = mpInstance._Helpers.filterUserIdentities( + const filteredUserIdentities = (mpInstance._Helpers.filterUserIdentities as Function)( userIdentities, forwarder.userIdentityFilters ); @@ -100,7 +126,10 @@ export default function Forwarders(mpInstance, kitBlocker) { } }; - this.isEnabledForUserAttributes = function(filterObject, user) { + this.isEnabledForUserAttributes = function( + filterObject: IFilteringUserAttributeValue, + user: IMParticleUser + ): boolean { if ( !filterObject || !mpInstance._Helpers.isObject(filterObject) || @@ -109,7 +138,9 @@ export default function Forwarders(mpInstance, kitBlocker) { return true; } - var attrHash, valueHash, userAttributes; + let attrHash: string; + let valueHash: string; + let userAttributes: Record; if (!user) { return false; @@ -117,7 +148,7 @@ export default function Forwarders(mpInstance, kitBlocker) { userAttributes = user.getAllUserAttributes(); } - var isMatch = false; + let isMatch = false; try { if ( @@ -125,7 +156,7 @@ export default function Forwarders(mpInstance, kitBlocker) { mpInstance._Helpers.isObject(userAttributes) && Object.keys(userAttributes).length ) { - for (var attrName in userAttributes) { + for (const attrName in userAttributes) { if (userAttributes.hasOwnProperty(attrName)) { attrHash = KitFilterHelper.hashAttributeConditionalForwarding( attrName @@ -156,7 +187,10 @@ export default function Forwarders(mpInstance, kitBlocker) { } }; - this.isEnabledForUnknownUser = function(excludeAnonymousUserBoolean, user) { + this.isEnabledForUnknownUser = function( + excludeAnonymousUserBoolean: boolean, + user: IMParticleUser + ): boolean { if (!user || !user.isLoggedIn()) { if (excludeAnonymousUserBoolean) { return false; @@ -165,39 +199,42 @@ export default function Forwarders(mpInstance, kitBlocker) { return true; }; - this.applyToForwarders = function(functionName, functionArgs) { + this.applyToForwarders = function( + functionName: string, + functionArgs: string[] + ): void { if (mpInstance._Store.activeForwarders.length) { mpInstance._Store.activeForwarders.forEach(function(forwarder) { - var forwarderFunction = forwarder[functionName]; + const forwarderFunction = forwarder[functionName]; if (forwarderFunction) { try { - var result = forwarder[functionName](functionArgs); + const result = forwarder[functionName](functionArgs); if (result) { - mpInstance.Logger.verbose(result); + mpInstance.Logger.verbose(result as string); } } catch (e) { - mpInstance.Logger.verbose(e); + mpInstance.Logger.verbose(e as string); } } }); } }; - this.sendEventToForwarders = function(event) { - let clonedEvent; - let hashedEventName; - let hashedEventType; + this.sendEventToForwarders = function(event: SDKEvent): void { + let clonedEvent: SDKEvent; + let hashedEventName: number; + let hashedEventType: number; if ( !mpInstance._Store.webviewBridgeEnabled && mpInstance._Store.activeForwarders ) { - hashedEventName = KitFilterHelper.hashEventName( + hashedEventName = (KitFilterHelper.hashEventName as Function)( event.EventName, event.EventCategory ); - hashedEventType = KitFilterHelper.hashEventType( + hashedEventType = (KitFilterHelper.hashEventType as Function)( event.EventCategory ); @@ -209,7 +246,7 @@ export default function Forwarders(mpInstance, kitBlocker) { const forwarder = mpInstance._Store.activeForwarders[i]; if ( - isBlockedByForwardingRule( + (isBlockedByForwardingRule as Function)( event.EventDataType, event.EventAttributes, forwarder @@ -222,7 +259,7 @@ export default function Forwarders(mpInstance, kitBlocker) { clonedEvent = extend(true, {}, event); if ( - isBlockedByEventFilter( + (isBlockedByEventFilter as Function)( event.EventDataType, hashedEventName, hashedEventType, @@ -232,7 +269,7 @@ export default function Forwarders(mpInstance, kitBlocker) { continue; } - clonedEvent.EventAttributes = filterEventAttributes( + clonedEvent.EventAttributes = (filterEventAttributes as Function)( event.EventDataType, event.EventCategory, event.EventName, @@ -241,13 +278,13 @@ export default function Forwarders(mpInstance, kitBlocker) { ); // Check user identity filtering rules - clonedEvent.UserIdentities = filterUserIdentities( + clonedEvent.UserIdentities = (filterUserIdentities as Function)( clonedEvent.UserIdentities, forwarder.userIdentityFilters ); // Check user attribute filtering rules - clonedEvent.UserAttributes = KitFilterHelper.filterUserAttributes( + clonedEvent.UserAttributes = (KitFilterHelper.filterUserAttributes as Function)( clonedEvent.UserAttributes, forwarder.userAttributeFilters ); @@ -266,7 +303,7 @@ export default function Forwarders(mpInstance, kitBlocker) { } }; - this.sendBatchToForwarders = function(batch) { + this.sendBatchToForwarders = function(batch: Batch): void { if ( mpInstance._Store.webviewBridgeEnabled || !mpInstance._Store.activeForwarders @@ -274,7 +311,13 @@ export default function Forwarders(mpInstance, kitBlocker) { return; } - for (const forwarder of mpInstance._Store.activeForwarders) { + for ( + let i = 0; + i < mpInstance._Store.activeForwarders.length; + i++ + ) { + const forwarder = mpInstance._Store.activeForwarders[i]; + if (!forwarder.processBatch) { continue; } @@ -286,15 +329,15 @@ export default function Forwarders(mpInstance, kitBlocker) { batchCopy.events = batchCopy.events.filter(function( batchEvent ) { - return isBatchEventAllowed(batchEvent, forwarder); + return (isBatchEventAllowed as Function)(batchEvent, forwarder); }); batchCopy.events.forEach(function(batchEvent) { - filterBatchEventAttributes(batchEvent, forwarder); + (filterBatchEventAttributes as Function)(batchEvent, forwarder); }); } - batchCopy.user_identities = filterBatchIdentities( + batchCopy.user_identities = (filterBatchIdentities as Function)( batchCopy.user_identities, forwarder.userIdentityFilters ); @@ -316,12 +359,16 @@ export default function Forwarders(mpInstance, kitBlocker) { mpInstance.Logger.verbose(result); } } catch (e) { - mpInstance.Logger.verbose(e); + mpInstance.Logger.verbose(e as string); } } }; - this.handleForwarderUserAttributes = function(functionNameKey, key, value) { + this.handleForwarderUserAttributes = function( + functionNameKey: string, + key: string, + value: string + ): void { if ( (kitBlocker && kitBlocker.isAttributeKeyBlocked(key)) || !mpInstance._Store.activeForwarders.length @@ -341,7 +388,7 @@ export default function Forwarders(mpInstance, kitBlocker) { return; } try { - let result; + let result: string; if ( functionNameKey === @@ -359,24 +406,28 @@ 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) { + this.setForwarderUserIdentities = function( + userIdentities: ISDKUserIdentity[] + ): void { mpInstance._Store.activeForwarders.forEach(function(forwarder) { - var filteredUserIdentities = mpInstance._Helpers.filterUserIdentities( + const filteredUserIdentities = (mpInstance._Helpers.filterUserIdentities as Function)( userIdentities, forwarder.userIdentityFilters - ); + ) as ISDKUserIdentity[]; if (forwarder.setUserIdentity) { - filteredUserIdentities.forEach(function(identity) { - var result = forwarder.setUserIdentity( + filteredUserIdentities.forEach(function( + identity: ISDKUserIdentity + ) { + const result = (forwarder.setUserIdentity as Function)( identity.Identity, identity.Type - ); + ) as string; if (result) { mpInstance.Logger.verbose(result); } @@ -385,16 +436,18 @@ export default function Forwarders(mpInstance, kitBlocker) { }); }; - this.setForwarderOnUserIdentified = function(user) { + this.setForwarderOnUserIdentified = function( + user: IMParticleUser + ): void { mpInstance._Store.activeForwarders.forEach(function(forwarder) { - var filteredUser = filteredMparticleUser( + const filteredUser = filteredMparticleUser( user.getMPID(), forwarder, mpInstance, kitBlocker ); if (forwarder.onUserIdentified) { - var result = forwarder.onUserIdentified(filteredUser); + const result = forwarder.onUserIdentified(filteredUser); if (result) { mpInstance.Logger.verbose(result); } @@ -402,11 +455,14 @@ export default function Forwarders(mpInstance, kitBlocker) { }); }; - this.setForwarderOnIdentityComplete = function(user, identityMethod) { - var result; + this.setForwarderOnIdentityComplete = function( + user: IMParticleUser, + identityMethod: string + ): void { + let result: string; mpInstance._Store.activeForwarders.forEach(function(forwarder) { - var filteredUser = filteredMparticleUser( + const filteredUser = filteredMparticleUser( user.getMPID(), forwarder, mpInstance, @@ -459,12 +515,14 @@ export default function Forwarders(mpInstance, kitBlocker) { }); }; - this.getForwarderStatsQueue = function() { + this.getForwarderStatsQueue = function(): IForwardingStatsData[] { return mpInstance._Persistence.forwardingStatsBatches .forwardingStatsEventQueue; }; - this.setForwarderStatsQueue = function(queue) { + this.setForwarderStatsQueue = function( + queue: IForwardingStatsData[] + ): void { mpInstance._Persistence.forwardingStatsBatches.forwardingStatsEventQueue = queue; }; @@ -474,16 +532,19 @@ 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 = function( + config: IConfigResponse, + forwardingStatsCallback: ForwardingStatsCallback + ): void { if (!config) { mpInstance.Logger.warning( 'No config was passed. Cannot process forwarders' ); } else { - this.processUIEnabledKits(config); - this.processSideloadedKits(config); + (this.processUIEnabledKits as Function)(config); + (this.processSideloadedKits as Function)(config); - self.initForwarders( + (this.initForwarders as Function)( mpInstance._Store.SDKConfig.identifyRequest.userIdentities, forwardingStatsCallback ); @@ -496,13 +557,13 @@ 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 = function(config: IConfigResponse): void { + const kits = (this.returnKitConstructors as Function)() as Dictionary; try { if (Array.isArray(config.kitConfigs) && config.kitConfigs.length) { - config.kitConfigs.forEach(function(kitConfig) { - self.configureUIEnabledKit(kitConfig, kits); + config.kitConfigs.forEach((kitConfig: IKitConfigs) => { + (this.configureUIEnabledKit as Function)(kitConfig, kits); }); } } catch (e) { @@ -513,8 +574,8 @@ export default function Forwarders(mpInstance, kitBlocker) { } }; - this.returnKitConstructors = function() { - let kits = {}; + this.returnKitConstructors = function(): Dictionary { + let kits: Dictionary = {}; // If there are kits inside of mpInstance._Store.SDKConfig.kits, then mParticle is self hosted if (!isEmpty(mpInstance._Store.SDKConfig.kits)) { kits = mpInstance._Store.SDKConfig.kits; @@ -532,23 +593,26 @@ export default function Forwarders(mpInstance, kitBlocker) { // a suffix allows the SDK to distinguish the two. if (kitConstructor.suffix) { const kitNameWithConstructorSuffix = `${kitConstructor.name}-${kitConstructor.suffix}`; - kits[kitNameWithConstructorSuffix] = kitConstructor; + kits[kitNameWithConstructorSuffix] = kitConstructor as RegisteredKit; } else { - kits[kitConstructor.name] = kitConstructor; + kits[kitConstructor.name] = kitConstructor as RegisteredKit; } }); } return kits; }; - this.configureUIEnabledKit = function(configuration, kits) { - let newKit = null; + this.configureUIEnabledKit = function( + configuration: IKitConfigs, + kits: Dictionary + ): void { + let newKit: MPForwarder | null = null; const config = configuration; - for (let name in kits) { + for (const name in kits) { // Configs are returned with suffixes also. We need to consider the // config suffix here to match the constructor suffix - let kitNameWithConfigSuffix; + let kitNameWithConfigSuffix: string; if (config.suffix) { kitNameWithConfigSuffix = `${config.name}-${config.suffix}`; } @@ -557,10 +621,10 @@ export default function Forwarders(mpInstance, kitBlocker) { if ( config.isDebug === mpInstance._Store.SDKConfig.isDevelopmentMode || - config.isSandbox === + (config as IKitConfigs & { isSandbox?: boolean }).isSandbox === mpInstance._Store.SDKConfig.isDevelopmentMode ) { - newKit = this.returnConfiguredKit(kits[name], config); + newKit = (this.returnConfiguredKit as Function)(kits[name], config); mpInstance._Store.configuredForwarders.push(newKit); break; @@ -576,10 +640,12 @@ 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) { + this.processSideloadedKits = function( + mpConfig: IConfigResponse & { sideloadedKits?: SideloadedKit[] } + ): void { try { if (Array.isArray(mpConfig.sideloadedKits)) { - const registeredSideloadedKits = { kits: {} }; + const registeredSideloadedKits: { kits: Dictionary } = { kits: {} }; const unregisteredSideloadedKits = mpConfig.sideloadedKits; unregisteredSideloadedKits.forEach(function(unregisteredKit) { @@ -605,7 +671,7 @@ export default function Forwarders(mpInstance, kitBlocker) { for (const registeredKitKey in registeredSideloadedKits.kits) { const registeredKit = registeredSideloadedKits.kits[registeredKitKey]; - self.configureSideloadedKit(registeredKit); + (this.configureSideloadedKit as Function)(registeredKit); } // If Sideloaded Kits are successfully registered, @@ -624,14 +690,19 @@ 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 = function( + kitConstructor: RegisteredKit + ): void { mpInstance._Store.configuredForwarders.push( - this.returnConfiguredKit(kitConstructor, kitConstructor.filters) + (this.returnConfiguredKit as Function)(kitConstructor, kitConstructor.filters) ); }; - this.returnConfiguredKit = function(forwarder, config = {}) { - const newForwarder = new forwarder.constructor(); + this.returnConfiguredKit = function( + forwarder: RegisteredKit, + config: Partial = {} + ): MPForwarder { + const newForwarder = new forwarder.constructor() as MPForwarder; newForwarder.id = config.moduleId; // TODO: isSandbox, hasSandbox is never used in any kit or in core SDK. @@ -666,7 +737,7 @@ export default function Forwarders(mpInstance, kitBlocker) { return newForwarder; }; - this.configurePixel = function(settings) { + this.configurePixel = function(settings: IPixelConfiguration): void { if ( settings.isDebug === mpInstance._Store.SDKConfig.isDevelopmentMode || @@ -677,11 +748,11 @@ export default function Forwarders(mpInstance, kitBlocker) { } }; - this.processPixelConfigs = function(config) { + this.processPixelConfigs = function(config: IConfigResponse): void { try { if (!isEmpty(config.pixelConfigs)) { - config.pixelConfigs.forEach(function(pixelConfig) { - self.configurePixel(pixelConfig); + config.pixelConfigs.forEach((pixelConfig: IPixelConfiguration) => { + (this.configurePixel as Function)(pixelConfig); }); } } catch (e) { @@ -692,10 +763,12 @@ export default function Forwarders(mpInstance, kitBlocker) { } }; - this.sendSingleForwardingStatsToServer = async forwardingStatsData => { + this.sendSingleForwardingStatsToServer = async ( + forwardingStatsData: IForwardingStatsData + ): Promise => { // https://go.mparticle.com/work/SQDSDKS-6568 const fetchPayload = { - method: 'post', + method: 'post' as const, body: JSON.stringify(forwardingStatsData), headers: { Accept: 'text/plain;charset=UTF-8', @@ -705,7 +778,7 @@ export default function Forwarders(mpInstance, kitBlocker) { const 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.js b/src/identity.js index 29c9dacb9..c9e5dbe4d 100644 --- a/src/identity.js +++ b/src/identity.js @@ -20,6 +20,7 @@ import { } from './utils'; import { hasMPIDAndUserLoginChanged, hasMPIDChanged } from './user-utils'; import { processReadyQueue } from './pre-init-utils'; +import { logDeprecatedMethodUsage } from './reporting/deprecatedMethodLogger'; export default function Identity(mpInstance) { const { getFeatureFlag, extend } = mpInstance._Helpers; @@ -1252,8 +1253,14 @@ export default function Identity(mpInstance) { * @return a cart object */ getCart: function() { - mpInstance.Logger.warning( - 'Deprecated function Identity.getCurrentUser().getCart() will be removed in future releases' + logDeprecatedMethodUsage( + { + methodName: 'Identity.getCurrentUser().getCart()', + warningMessage: + 'Deprecated function Identity.getCurrentUser().getCart() will be removed in future releases', + }, + mpInstance.Logger, + mpInstance._LoggingDispatcher ); return self.mParticleUserCart(); }, @@ -1334,13 +1341,18 @@ export default function Identity(mpInstance) { * @deprecated */ add: function() { - mpInstance.Logger.warning( - generateDeprecationMessage( - 'Identity.getCurrentUser().getCart().add()', - true, - 'eCommerce.logProductAction()', - 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' - ) + logDeprecatedMethodUsage( + { + methodName: 'Identity.getCurrentUser().getCart().add()', + warningMessage: generateDeprecationMessage( + 'Identity.getCurrentUser().getCart().add()', + true, + 'eCommerce.logProductAction()', + 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' + ), + }, + mpInstance.Logger, + mpInstance._LoggingDispatcher ); }, /** @@ -1349,13 +1361,19 @@ export default function Identity(mpInstance) { * @deprecated */ remove: function() { - mpInstance.Logger.warning( - generateDeprecationMessage( - 'Identity.getCurrentUser().getCart().remove()', - true, - 'eCommerce.logProductAction()', - 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' - ) + logDeprecatedMethodUsage( + { + methodName: + 'Identity.getCurrentUser().getCart().remove()', + warningMessage: generateDeprecationMessage( + 'Identity.getCurrentUser().getCart().remove()', + true, + 'eCommerce.logProductAction()', + 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' + ), + }, + mpInstance.Logger, + mpInstance._LoggingDispatcher ); }, /** @@ -1364,13 +1382,19 @@ export default function Identity(mpInstance) { * @deprecated */ clear: function() { - mpInstance.Logger.warning( - generateDeprecationMessage( - 'Identity.getCurrentUser().getCart().clear()', - true, - '', - 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' - ) + logDeprecatedMethodUsage( + { + methodName: + 'Identity.getCurrentUser().getCart().clear()', + warningMessage: generateDeprecationMessage( + 'Identity.getCurrentUser().getCart().clear()', + true, + '', + 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' + ), + }, + mpInstance.Logger, + mpInstance._LoggingDispatcher ); }, /** @@ -1380,13 +1404,19 @@ export default function Identity(mpInstance) { * @deprecated */ getCartProducts: function() { - mpInstance.Logger.warning( - generateDeprecationMessage( - 'Identity.getCurrentUser().getCart().getCartProducts()', - true, - 'eCommerce.logProductAction()', - 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' - ) + logDeprecatedMethodUsage( + { + methodName: + 'Identity.getCurrentUser().getCart().getCartProducts()', + warningMessage: generateDeprecationMessage( + 'Identity.getCurrentUser().getCart().getCartProducts()', + true, + 'eCommerce.logProductAction()', + 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' + ), + }, + mpInstance.Logger, + mpInstance._LoggingDispatcher ); return []; }, @@ -1540,7 +1570,8 @@ export default function Identity(mpInstance) { prevUser, newUser, identityApiData, - mpInstance.Logger + mpInstance.Logger, + mpInstance._LoggingDispatcher ); const persistence = mpInstance._Persistence.getPersistence(); @@ -1775,14 +1806,27 @@ export default function Identity(mpInstance) { } // https://go.mparticle.com/work/SQDSDKS-6359 -function tryOnUserAlias(previousUser, newUser, identityApiData, logger) { +function tryOnUserAlias( + previousUser, + newUser, + identityApiData, + logger, + loggingDispatcher +) { if ( identityApiData && identityApiData.onUserAlias && isFunction(identityApiData.onUserAlias) ) { try { - logger.warning(generateDeprecationMessage('onUserAlias')); + logDeprecatedMethodUsage( + { + methodName: 'onUserAlias', + warningMessage: generateDeprecationMessage('onUserAlias'), + }, + logger, + loggingDispatcher + ); identityApiData.onUserAlias(previousUser, newUser); } catch (e) { logger.error( diff --git a/src/mp-instance.ts b/src/mp-instance.ts index 618b19ab3..4b9078573 100644 --- a/src/mp-instance.ts +++ b/src/mp-instance.ts @@ -55,6 +55,7 @@ import CookieConsentManager, { ICookieConsentManager } from './cookieConsentMana import { ErrorReportingDispatcher } from './reporting/errorReportingDispatcher'; import { LoggingDispatcher } from './reporting/loggingDispatcher'; import { IErrorReportingService, ILoggingService } from './reporting/types'; +import { logDeprecatedMethodUsage } from './reporting/deprecatedMethodLogger'; export interface IErrorLogMessage { message?: string; @@ -772,13 +773,18 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan * @deprecated */ add: function(product, logEventBoolean) { - self.Logger.warning( - generateDeprecationMessage( - 'eCommerce.Cart.add()', - true, - 'eCommerce.logProductAction()', - 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' - ) + logDeprecatedMethodUsage( + { + methodName: 'mPInstance.eCommerce.Cart.add()', + warningMessage: generateDeprecationMessage( + 'eCommerce.Cart.add()', + true, + 'eCommerce.logProductAction()', + 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' + ), + }, + self.Logger, + self._LoggingDispatcher ); }, /** @@ -789,13 +795,18 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan * @deprecated */ remove: function(product, logEventBoolean) { - self.Logger.warning( - generateDeprecationMessage( - 'eCommerce.Cart.remove()', - true, - 'eCommerce.logProductAction()', - 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' - ) + logDeprecatedMethodUsage( + { + methodName: 'mPInstance.eCommerce.Cart.remove()', + warningMessage: generateDeprecationMessage( + 'eCommerce.Cart.remove()', + true, + 'eCommerce.logProductAction()', + 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' + ), + }, + self.Logger, + self._LoggingDispatcher ); }, /** @@ -804,13 +815,18 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan * @deprecated */ clear: function() { - self.Logger.warning( - generateDeprecationMessage( - 'eCommerce.Cart.clear()', - true, - '', - 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' - ) + logDeprecatedMethodUsage( + { + methodName: 'mPInstance.eCommerce.Cart.clear()', + warningMessage: generateDeprecationMessage( + 'eCommerce.Cart.clear()', + true, + '', + 'https://docs.mparticle.com/developers/sdk/web/commerce-tracking' + ), + }, + self.Logger, + self._LoggingDispatcher ); }, }, @@ -940,8 +956,13 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan * @deprecated */ logCheckout: function(step, option, attrs, customFlags) { - self.Logger.warning( - 'mParticle.logCheckout is deprecated, please use mParticle.logProductAction instead' + logDeprecatedMethodUsage( + { + methodName: 'mParticle.logCheckout', + warningMessage: 'mParticle.logCheckout is deprecated, please use mParticle.logProductAction instead', + }, + self.Logger, + self._LoggingDispatcher ); if (!self._Store.isInitialized) { @@ -1020,8 +1041,13 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan attrs, customFlags ) { - self.Logger.warning( - 'mParticle.logPurchase is deprecated, please use mParticle.logProductAction instead' + logDeprecatedMethodUsage( + { + methodName: 'mParticle.logPurchase', + warningMessage: 'mParticle.logPurchase is deprecated, please use mParticle.logProductAction instead', + }, + self.Logger, + self._LoggingDispatcher ); if (!self._Store.isInitialized) { self.ready(function() { @@ -1132,8 +1158,13 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan attrs, customFlags ) { - self.Logger.warning( - 'mParticle.logRefund is deprecated, please use mParticle.logProductAction instead' + logDeprecatedMethodUsage( + { + methodName: 'mParticle.logRefund', + warningMessage: 'mParticle.logRefund is deprecated, please use mParticle.logProductAction instead', + }, + self.Logger, + self._LoggingDispatcher ); if (!self._Store.isInitialized) { self.ready(function() { @@ -1741,4 +1772,3 @@ function queueIfNotInitialized(func, self) { }); return true; } - diff --git a/src/reporting/deprecatedMethodLogger.ts b/src/reporting/deprecatedMethodLogger.ts new file mode 100644 index 000000000..33a9b55ed --- /dev/null +++ b/src/reporting/deprecatedMethodLogger.ts @@ -0,0 +1,19 @@ +import { ErrorCodes, ILoggingService } from './types'; +import { SDKLoggerApi } from '../sdkRuntimeModels'; + +interface DeprecatedMethodUsage { + methodName: string; + warningMessage: string; +} + +export function logDeprecatedMethodUsage( + usage: DeprecatedMethodUsage, + logger: Pick, + loggingDispatcher: ILoggingService | undefined +): void { + logger.warning(usage.warningMessage); + loggingDispatcher?.log({ + message: usage.methodName, + code: ErrorCodes.MP_DEPRECATED_METHOD_USAGE, + }); +} diff --git a/src/reporting/types.ts b/src/reporting/types.ts index 7378ca8f0..ba06ef73d 100644 --- a/src/reporting/types.ts +++ b/src/reporting/types.ts @@ -6,6 +6,7 @@ export const ErrorCodes = { IDENTITY_REQUEST: 'IDENTITY_REQUEST', IDENTITY_MISMATCH: 'IDENTITY_MISMATCH', ROKT_KIT_ATTACHED: 'ROKT_KIT_ATTACHED', + MP_DEPRECATED_METHOD_USAGE: 'MP_DEPRECATED_METHOD_USAGE', } as const; export type ErrorCodes = valueof; diff --git a/src/sdkRuntimeModels.ts b/src/sdkRuntimeModels.ts index e31084228..73a127aba 100644 --- a/src/sdkRuntimeModels.ts +++ b/src/sdkRuntimeModels.ts @@ -389,6 +389,10 @@ export interface SDKHelpersApi { attrs: SDKEventAttrs, name: string ): Dictionary | null; + filterUserIdentities?( + userIdentitiesObject: Dictionary, + filterList: number[] + ): ISDKUserIdentity[]; Validators: typeof Validators; } diff --git a/src/sessionManager.ts b/src/sessionManager.ts index 4b6cf68a4..418c4507e 100644 --- a/src/sessionManager.ts +++ b/src/sessionManager.ts @@ -6,6 +6,7 @@ import { generateDeprecationMessage } from './utils'; import { IMParticleUser } from './identity-user-interfaces'; import { IMParticleWebSDKInstance } from './mp-instance'; import { hasIdentityRequestChanged, hasExplicitIdentifier } from './identity-utils'; +import { logDeprecatedMethodUsage } from './reporting/deprecatedMethodLogger'; const { Messages } = Constants; @@ -67,12 +68,17 @@ export default function SessionManager( }; this.getSession = function (): string { - mpInstance.Logger.warning( - generateDeprecationMessage( - 'SessionManager.getSession()', - false, - 'SessionManager.getSessionId()' - ) + logDeprecatedMethodUsage( + { + methodName: 'SessionManager.getSession()', + warningMessage: generateDeprecationMessage( + 'SessionManager.getSession()', + false, + 'SessionManager.getSessionId()' + ), + }, + mpInstance.Logger, + mpInstance._LoggingDispatcher ); return this.getSessionId(); }; diff --git a/test/jest/reportingLogger.spec.ts b/test/jest/reportingLogger.spec.ts index 82ee5204d..ca4e1d700 100644 --- a/test/jest/reportingLogger.spec.ts +++ b/test/jest/reportingLogger.spec.ts @@ -1,6 +1,7 @@ import { ErrorReportingDispatcher } from '../../src/reporting/errorReportingDispatcher'; import { LoggingDispatcher } from '../../src/reporting/loggingDispatcher'; import { IErrorReportingService, ILoggingService, ISDKError, ISDKLogEntry, WSDKErrorSeverity, ErrorCodes } from '../../src/reporting/types'; +import { logDeprecatedMethodUsage } from '../../src/reporting/deprecatedMethodLogger'; describe('ErrorReportingDispatcher', () => { let dispatcher: ErrorReportingDispatcher; @@ -128,3 +129,43 @@ describe('LoggingDispatcher', () => { expect(service2.log).toHaveBeenCalledWith(entry); }); }); + +describe('logDeprecatedMethodUsage', () => { + it('keeps the console warning and emits structured usage details', () => { + const warning = jest.fn(); + const log = jest.fn(); + + logDeprecatedMethodUsage( + { + methodName: 'mParticle.logCheckout', + warningMessage: 'mParticle.logCheckout is deprecated, please use mParticle.logProductAction instead', + }, + { warning }, + { log } + ); + + expect(warning).toHaveBeenCalledWith( + 'mParticle.logCheckout is deprecated, please use mParticle.logProductAction instead' + ); + expect(log).toHaveBeenCalledWith({ + message: 'mParticle.logCheckout', + code: ErrorCodes.MP_DEPRECATED_METHOD_USAGE, + }); + }); + + it('does not require a registered logging dispatcher', () => { + const warning = jest.fn(); + + expect(() => logDeprecatedMethodUsage( + { + methodName: 'onUserAlias', + warningMessage: 'onUserAlias is a deprecated method and will be removed in future releases.', + }, + { warning }, + undefined + )).not.toThrow(); + expect(warning).toHaveBeenCalledWith( + 'onUserAlias is a deprecated method and will be removed in future releases.' + ); + }); +});