From 14c7058735880bfe6284d891ed584cd885c70f93 Mon Sep 17 00:00:00 2001 From: Robert Ing Date: Fri, 15 May 2026 12:03:49 -0400 Subject: [PATCH 1/8] feat(types): own web sdk type surface --- src/configAPIClient.ts | 11 +- src/consent.ts | 10 +- src/cookieSyncManager.ts | 4 +- src/ecommerce.interfaces.ts | 17 +- src/events.interfaces.ts | 12 +- src/forwarders.interfaces.ts | 3 +- src/identity-user-interfaces.ts | 26 ++- src/identity-utils.ts | 4 +- src/identity.interfaces.ts | 36 ++-- src/identity.js | 16 +- src/identity/search.ts | 2 +- src/identityApiClient.ts | 2 +- src/internal-types.ts | 15 ++ src/mp-instance.ts | 5 +- src/mparticle-instance-manager.ts | 6 +- src/persistence.interfaces.ts | 4 +- src/public-types.ts | 110 +++++++++--- src/publicSdkTypes.ts | 268 ++++++++++++++++++++++++++++++ src/roktManager.ts | 46 ++++- src/sdkRuntimeModels.ts | 58 ++++--- src/sdkToEventsApiConverter.ts | 4 +- src/serverModel.ts | 2 +- src/sessionManager.ts | 2 +- src/sideloadedKit.ts | 4 +- src/store.ts | 8 +- src/user-utils.ts | 2 +- src/utils.ts | 4 +- src/validators.ts | 2 +- 28 files changed, 555 insertions(+), 128 deletions(-) create mode 100644 src/publicSdkTypes.ts diff --git a/src/configAPIClient.ts b/src/configAPIClient.ts index b551af5f9..59143b7f0 100644 --- a/src/configAPIClient.ts +++ b/src/configAPIClient.ts @@ -1,11 +1,12 @@ -import { DataPlanConfig } from '@mparticle/web-sdk'; -import { +import type { BooleanStringLowerCase, + DataPlanConfig, DataPlanResult, SDKEventCustomFlags, SDKInitConfig, } from './sdkRuntimeModels'; import { Dictionary } from './utils'; +import type { IConsentRuleValue } from './consent'; import { AsyncUploader, IFetchPayload, @@ -61,12 +62,6 @@ export interface IFilteringConsentRuleValues { values: IConsentRuleValue[]; } -export interface IConsentRuleValue { - consentPurpose: string; - hasConsented: boolean; -} - - export interface IConfigResponse { appName: string; dataPlanResult: DataPlanResult; diff --git a/src/consent.ts b/src/consent.ts index 81ae944cd..87eeb0992 100644 --- a/src/consent.ts +++ b/src/consent.ts @@ -3,7 +3,7 @@ import { ConsentState, GDPRConsentState, PrivacyConsentState, -} from '@mparticle/web-sdk'; +} from './publicSdkTypes'; import { Dictionary, isObject } from './utils'; import KitFilterHelper from './kitFilterHelper'; import Constants from './constants'; @@ -88,13 +88,15 @@ export interface IConsentStateV2DTO { ccpa?: ICCPAConsentStateV2DTO; } -export interface IConsentRulesValues { - consentPurpose: string; +export interface IConsentRuleValue { + // Server-side consent filters can return hashed consent purposes as numbers. + consentPurpose: string | number; hasConsented: boolean; } + export interface IConsentRules { includeOnMatch: boolean; - values: IConsentRulesValues[]; + values: IConsentRuleValue[]; } // TODO: Remove this if we can safely deprecate `removeCCPAState` diff --git a/src/cookieSyncManager.ts b/src/cookieSyncManager.ts index 7a4ea9b63..8bdc019e4 100644 --- a/src/cookieSyncManager.ts +++ b/src/cookieSyncManager.ts @@ -4,7 +4,7 @@ import { createCookieSyncUrl, } from './utils'; import Constants from './constants'; -import { MPID } from '@mparticle/web-sdk'; +import { MPID } from './publicSdkTypes'; import { IConsentRules } from './consent'; import { IMParticleWebSDKInstance } from './mp-instance'; @@ -185,4 +185,4 @@ export const isLastSyncDateExpired = ( new Date().getTime() > new Date(lastSyncDate).getTime() + frequencyCap * DAYS_IN_MILLISECONDS ); -}; \ No newline at end of file +}; diff --git a/src/ecommerce.interfaces.ts b/src/ecommerce.interfaces.ts index 053f848c0..757c99185 100644 --- a/src/ecommerce.interfaces.ts +++ b/src/ecommerce.interfaces.ts @@ -8,7 +8,7 @@ import { SDKEventAttrs, SDKEventOptions, TransactionAttributes, -} from '@mparticle/web-sdk'; +} from './publicSdkTypes'; import { valueof } from './utils'; import { ProductActionType, @@ -38,7 +38,10 @@ interface IECommerceShared { couponCode?: string, attributes?: SDKEventAttrs ): SDKProduct | null; - createImpression(name: string, product: Product): SDKImpression | null; + createImpression( + name: string, + product: SDKProduct | SDKProduct[] + ): SDKImpression | null; createPromotion( id: string | number, creative?: string, @@ -71,7 +74,7 @@ export interface SDKECommerceAPI extends IECommerceShared { customFlags?: SDKEventCustomFlags ): void; logImpression( - impression: SDKProductImpression, + impression: SDKImpression | SDKImpression[], attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions @@ -86,7 +89,7 @@ export interface SDKECommerceAPI extends IECommerceShared { ): void; logPromotion( type: valueof, - promotion: SDKPromotion, + promotion: SDKPromotion | SDKPromotion[], attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions @@ -159,10 +162,12 @@ export interface IECommerce extends IECommerceShared { convertProductActionToEventType( productActionType: valueof ): // https://go.mparticle.com/work/SQDSDKS-4801 - typeof CommerceEventType | typeof EventType | null; + | valueof + | valueof + | null; convertPromotionActionToEventType( promotionActionType: valueof - ): typeof CommerceEventType | null; + ): valueof | null; convertTransactionAttributesToProductAction( transactionAttributes: TransactionAttributes, productAction: ProductAction diff --git a/src/events.interfaces.ts b/src/events.interfaces.ts index 0674e47a8..98b0945d3 100644 --- a/src/events.interfaces.ts +++ b/src/events.interfaces.ts @@ -1,15 +1,15 @@ import { - Callback, SDKEventAttrs, SDKEventOptions, + TrackLocationCallback, TransactionAttributes, -} from '@mparticle/web-sdk'; +} from './publicSdkTypes'; import { BaseEvent, SDKEvent, SDKEventCustomFlags, + SDKImpression, SDKProduct, - SDKProductImpression, SDKPromotion, } from './sdkRuntimeModels'; import { valueof } from './utils'; @@ -45,7 +45,7 @@ export interface IEvents { ): void; logEvent(event: BaseEvent, eventOptions?: SDKEventOptions): void; logImpressionEvent( - impression: SDKProductImpression, + impression: SDKImpression | SDKImpression[], attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions @@ -61,7 +61,7 @@ export interface IEvents { ): void; logPromotionEvent( promotionType: valueof, - promotion: SDKPromotion, + promotion: SDKPromotion | SDKPromotion[], attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions @@ -78,6 +78,6 @@ export interface IEvents { attrs?: SDKEventAttrs, customFlags?: SDKEventCustomFlags ): void; - startTracking(callback: Callback): void; + startTracking(callback?: TrackLocationCallback): void; stopTracking(): void; } diff --git a/src/forwarders.interfaces.ts b/src/forwarders.interfaces.ts index 17caa1a67..755c513ea 100644 --- a/src/forwarders.interfaces.ts +++ b/src/forwarders.interfaces.ts @@ -1,7 +1,8 @@ import { SDKEvent, SDKEventCustomFlags } from './sdkRuntimeModels'; import { Dictionary } from './utils'; import { IKitConfigs, IKitFilterSettings } from './configAPIClient'; -import { IdentityApiData, IdentityType } from '@mparticle/web-sdk'; +import { IdentityApiData } from './publicSdkTypes'; +import { IdentityType } from './types'; import { Batch } from '@mparticle/event-models'; import { diff --git a/src/identity-user-interfaces.ts b/src/identity-user-interfaces.ts index 9a4b673b6..510334b34 100644 --- a/src/identity-user-interfaces.ts +++ b/src/identity-user-interfaces.ts @@ -1,9 +1,11 @@ -import { AllUserAttributes, MPID, User } from '@mparticle/web-sdk'; -import { SDKIdentityTypeEnum } from './identity.interfaces'; +import type { + AllUserAttributes, + MPID, + User, +} from './publicSdkTypes'; +import type { SDKIdentityTypeEnum } from './identity.interfaces'; import { MessageType } from './types'; -import { BaseEvent, SDKProduct } from './sdkRuntimeModels'; -import Constants from './constants'; -const { HTTPCodes } = Constants; +import type { BaseEvent, SDKProduct } from './sdkRuntimeModels'; // Cart is Deprecated and private to mParticle user in @mparticle/web-sdk // but we need to expose it here for type safety in some of our tests @@ -92,8 +94,20 @@ export interface IIdentityResponse { expireTimestamp?: number; } +export type IdentityHTTPCode = + | -1 // noHttpCoverage + | -2 // activeIdentityRequest + | -3 // activeSession + | -4 // validationIssue + | -5 // nativeIdentityRequest + | -6 // loggingDisabledOrMissingAPIKey + | 200 + | 202 + | 400 + | 429; + export interface IdentityResult { - httpCode: typeof HTTPCodes; + httpCode: IdentityHTTPCode; getPreviousUser(): User; getUser(): User; body: IdentityResultBody | IdentityModifyResultBody; diff --git a/src/identity-utils.ts b/src/identity-utils.ts index 59ef35274..0d048e0f3 100644 --- a/src/identity-utils.ts +++ b/src/identity-utils.ts @@ -5,10 +5,10 @@ import Types from './types'; import { IdentityApiData, UserIdentities, - IdentityCallback, -} from '@mparticle/web-sdk'; +} from './publicSdkTypes'; import { IdentityAPIMethod, IIdentityRequest } from './identity.interfaces'; import { + IdentityCallback, IdentityResultBody, IIdentityResponse, IMParticleUser, diff --git a/src/identity.interfaces.ts b/src/identity.interfaces.ts index a223b77d2..b58b13ac1 100644 --- a/src/identity.interfaces.ts +++ b/src/identity.interfaces.ts @@ -1,4 +1,4 @@ -import { IdentityApiData, MPID, UserIdentities } from '@mparticle/web-sdk'; +import { IdentityApiData, MPID, User, UserIdentities } from './publicSdkTypes'; import AudienceManager from './audienceManager'; import { ICachedIdentityCall, IKnownIdentities } from './identity-utils'; import { BaseVault } from './vault'; @@ -56,7 +56,7 @@ export interface IIdentityAPIRequestData { context: string | null; environment: Environment; request_id: string; - request_timestamp_unixtime_ms: number; + request_timestamp_ms: number; previous_mpid: MPID | null; known_identities: IKnownIdentities; } @@ -70,7 +70,7 @@ export interface IIdentityAPIModifyRequestData } export interface IIdentityAPIIdentityChangeData { - identity_type: SDKIdentityTypeEnum; + identity_type: SDKIdentityTypeEnum | string; old_value: string; new_value: string; } @@ -100,7 +100,7 @@ export interface IIdentityRequest { createIdentityChanges( previousIdentities: UserIdentities, newIdentitie: UserIdentities - ): IIdentityAPIIdentityChangeData; + ): IIdentityAPIIdentityChangeData[]; preProcessIdentityRequest( identityApiData: IdentityApiData, callback: IdentityCallback, @@ -129,32 +129,32 @@ export interface IAliasResult { export interface SDKIdentityApi { HTTPCodes: typeof HTTPCodes; - identify?( + identify( identityApiData?: IdentityApiData, callback?: IdentityCallback ): void; - login?( + login( identityApiData?: IdentityApiData, callback?: IdentityCallback ): void; - logout?( - identityApiData?: IdentityApiData, + logout( + identityApiData?: IdentityApiData | null, callback?: IdentityCallback ): void; - modify?( + modify( identityApiData?: IdentityApiData, callback?: IdentityCallback ): void; - getCurrentUser?(): IMParticleUser; - getUser?(mpid: string): IMParticleUser; - getUsers?(): IMParticleUser[]; - aliasUsers?( + getCurrentUser(): IMParticleUser; + getUser(mpid: string): IMParticleUser; + getUsers(): IMParticleUser[]; + aliasUsers( aliasRequest?: IAliasRequest, - callback?: IdentityCallback + callback?: IAliasCallback ): void; - createAliasRequest?( - sourceUser: IMParticleUser, - destinationUser: IMParticleUser, + createAliasRequest( + sourceUser: User, + destinationUser: User, scope?: AliasRequestScope ): IAliasRequest; /** @@ -168,7 +168,7 @@ export interface SDKIdentityApi { * caller (from a kit's settings). It is sent as the `x-mp-key` header. * The SDK's own workspace token is intentionally not used. */ - search?( + search( workspaceApiKey: string, knownIdentities: UserIdentities, callback: IdentitySearchCallback diff --git a/src/identity.js b/src/identity.js index 29c9dacb9..59ef08c2f 100644 --- a/src/identity.js +++ b/src/identity.js @@ -95,6 +95,10 @@ export default function Identity(mpInstance) { context, mpid ) { + var environment = mpInstance._Store.SDKConfig.isDevelopmentMode + ? Constants.Environment.Development + : Constants.Environment.Production; + var APIRequest = { client_sdk: { platform: platform, @@ -102,9 +106,7 @@ export default function Identity(mpInstance) { sdk_version: sdkVersion, }, context: context, - environment: mpInstance._Store.SDKConfig.isDevelopmentMode - ? 'development' - : 'production', + environment: environment, request_id: mpInstance._Helpers.generateUniqueId(), request_timestamp_ms: new Date().getTime(), previous_mpid: mpid || null, @@ -125,6 +127,10 @@ export default function Identity(mpInstance) { sdkVersion, context ) { + var environment = mpInstance._Store.SDKConfig.isDevelopmentMode + ? Constants.Environment.Development + : Constants.Environment.Production; + return { client_sdk: { platform: platform, @@ -132,9 +138,7 @@ export default function Identity(mpInstance) { sdk_version: sdkVersion, }, context: context, - environment: mpInstance._Store.SDKConfig.isDevelopmentMode - ? 'development' - : 'production', + environment: environment, request_id: mpInstance._Helpers.generateUniqueId(), request_timestamp_ms: new Date().getTime(), identity_changes: this.createIdentityChanges( diff --git a/src/identity/search.ts b/src/identity/search.ts index 934cfae1b..8a8afa97b 100644 --- a/src/identity/search.ts +++ b/src/identity/search.ts @@ -12,7 +12,7 @@ import { IErrorReportingService, WSDKErrorSeverity, } from '../reporting/types'; -import { IdentityApiData, UserIdentities } from '@mparticle/web-sdk'; +import { IdentityApiData, UserIdentities } from '../publicSdkTypes'; import Validators from '../validators'; const { HTTPCodes } = Constants; diff --git a/src/identityApiClient.ts b/src/identityApiClient.ts index c26b9bade..a2cf3cdd3 100644 --- a/src/identityApiClient.ts +++ b/src/identityApiClient.ts @@ -18,7 +18,7 @@ import { IdentityApiData, MPID, UserIdentities, -} from '@mparticle/web-sdk'; +} from './publicSdkTypes'; import { IdentityCallback, IdentityResultBody, diff --git a/src/internal-types.ts b/src/internal-types.ts index 8097eda7c..e6609aabe 100644 --- a/src/internal-types.ts +++ b/src/internal-types.ts @@ -17,9 +17,24 @@ export * from './public-types'; export type { + ConfiguredKit, + forwardingStatsCallback, KitInterface, + KitRegistrationConfig, + MPForwarder, + RegisteredKit, + UnregisteredKit, + UserAttributeFilters, + UserIdentityFilters, + UserIdentityId, + UserIdentityType, } from './forwarders.interfaces'; +export type { + IKitConfigs, + IKitFilterSettings, +} from './configAPIClient'; + // Rokt integration types export type { RoktAttributeValue, diff --git a/src/mp-instance.ts b/src/mp-instance.ts index 618b19ab3..bba6eb6f4 100644 --- a/src/mp-instance.ts +++ b/src/mp-instance.ts @@ -36,13 +36,13 @@ import Consent, { IConsent } from './consent'; import KitBlocker from './kitBlocking'; import ConfigAPIClient, { IKitConfigs } from './configAPIClient'; import IdentityAPIClient from './identityApiClient'; -import { isFunction, parseConfig, valueof, generateDeprecationMessage, extend } from './utils'; +import { Dictionary, isFunction, parseConfig, valueof, generateDeprecationMessage, extend } from './utils'; import { DisabledVault, LocalStorageVault } from './vault'; import { removeExpiredIdentityCacheDates, hasExplicitIdentifier } from './identity-utils'; import IntegrationCapture from './integrationCapture'; import { IPreInit, processReadyQueue } from './pre-init-utils'; import { BaseEvent, MParticleWebSDK, SDKHelpersApi } from './sdkRuntimeModels'; -import { Dictionary, SDKEventAttrs } from '@mparticle/web-sdk'; +import { SDKEventAttrs } from './publicSdkTypes'; import { IIdentity } from './identity.interfaces'; import { IEvents } from './events.interfaces'; import { IECommerce } from './ecommerce.interfaces'; @@ -1741,4 +1741,3 @@ function queueIfNotInitialized(func, self) { }); return true; } - diff --git a/src/mparticle-instance-manager.ts b/src/mparticle-instance-manager.ts index 5c51b51bb..1e71f9748 100644 --- a/src/mparticle-instance-manager.ts +++ b/src/mparticle-instance-manager.ts @@ -6,7 +6,7 @@ import _BatchValidator from './mockBatchCreator'; import MPSideloadedKit from './sideloadedKit'; import { IMParticleInstanceManager } from './sdkRuntimeModels'; import { IStore } from './store'; -import { Dictionary } from '@mparticle/web-sdk'; +import { Dictionary } from './utils'; if (!Array.prototype.forEach) { Array.prototype.forEach = Polyfill.forEach; @@ -86,7 +86,7 @@ function mParticleInstanceManager(this: IMParticleInstanceManager) { self.getInstance().captureTiming(metricsName); } - this.getInstance = function getInstance(instanceName) { + this.getInstance = function getInstance(instanceName?: string) { let client: IMParticleWebSDKInstance; if (!instanceName) { instanceName = Constants.DefaultInstance; @@ -515,4 +515,4 @@ if (typeof window !== 'undefined') { window.mParticle._BatchValidator = new _BatchValidator(); } -export default mParticleManager; \ No newline at end of file +export default mParticleManager; diff --git a/src/persistence.interfaces.ts b/src/persistence.interfaces.ts index 639de8a3e..1a8e7b217 100644 --- a/src/persistence.interfaces.ts +++ b/src/persistence.interfaces.ts @@ -4,7 +4,7 @@ import { MPID, Product, UserIdentities, -} from '@mparticle/web-sdk'; +} from './publicSdkTypes'; import { IForwardingStatsData } from './apiClient'; import { IntegrationAttributes, @@ -102,7 +102,7 @@ export interface IPersistence { storeDataInMemory(obj: IPersistenceMinified, currentMPID: MPID): void; determineLocalStorageAvailability(storage: Storage): boolean; setLocalStorage(): void; - getLocalStorage(): IPersistenceMinified | null; + getLocalStorage(): IPersistenceMinified | Dictionary | null; expireCookies(cookieName: string): void; getCookie(): IPersistenceMinified | null; setCookie(): void; diff --git a/src/public-types.ts b/src/public-types.ts index d84f52ab4..82f955d03 100644 --- a/src/public-types.ts +++ b/src/public-types.ts @@ -5,47 +5,105 @@ * to import. Only add types here that are intended for external consumption. * * Usage: - * import type { SDKInitConfig, EventType } from '@mparticle/web-sdk'; + * import type { SDKInitConfig } from '@mparticle/web-sdk'; * - * Note: Types from @types/mparticle__web-sdk (e.g., MPConfiguration, MPID, - * ConsentState) are NOT re-exported here to avoid circular references. - * Consumers get those automatically via DefinitelyTyped until they are - * natively defined in this SDK and the DT package is deprecated. + * These declarations replace the legacy DefinitelyTyped surface. Keep this + * file focused on customer-facing SDK types; kit and SDK implementation types + * belong in internal-types.ts. */ +import type { MParticleWebSDKManager } from './sdkRuntimeModels'; +import type { IMPSideloadedKit } from './sideloadedKit'; + +declare const mParticle: MParticleWebSDKManager; + +export default mParticle; + +interface WindowMParticle extends MParticleWebSDKManager { + [key: string]: any; + getInstance(): any; + getInstance(instanceName: string): any; +} + +declare global { + interface Window { + mParticle: WindowMParticle; + } +} + // Re-export types from @mparticle/event-models // Consumers should not need to install @mparticle/event-models directly export type { Batch, } from '@mparticle/event-models'; -// Enums / Constants (type-only to avoid runtime mismatch with entry point) +// Legacy DefinitelyTyped-owned public primitives now owned by this package +export type { + AliasRequestScope, + AliasUsersCallback, + AllUserAttributes, + Callback, + Cart, + CCPAConsentState, + ConsentState, + GDPRConsentState, + IdentityApiData, + IdentifyRequest, + Impression, + LauncherOptions, + Location, + Logger, + LogLevel, + MPConfiguration, + MPForwarder, + MPID, + OnCreateBatch, + OnUserAlias, + onCreateBatch, + PrivacyConsentState, + Product, + Promotion, + SDKEventAttrs, + SDKEventAttrTypes, + SDKEventCustomFlags, + SDKEventOptions, + TrackLocationCallback, + TransactionAttributes, + User, + UserAliasRequest, + UserAttributesValue, + UserIdentityValue, + UserIdentities, +} from './publicSdkTypes'; + +export type MPSideloadedKit = IMPSideloadedKit; + export type { - EventType, - CommerceEventType, - IdentityType, - ProductActionType, - PromotionActionType, - MessageType, -} from './types'; + IFilteringConsentRuleValues as FilteringConsentRuleValues, + IFilteringEventAttributeValue as FilteringEventAttributeValue, + IFilteringUserAttributeValue as FilteringUserAttributeValue, + IKitFilterSettings as KitFilterSettings, +} from './configAPIClient'; // Configuration export type { SDKInitConfig, - DataPlanConfig, BaseEvent, - SDKEventCustomFlags, + DataPlanConfig, LogLevelType, + MParticleWebSDKInstance, + MParticleWebSDKManager, MParticleWebSDK, } from './sdkRuntimeModels'; // User & Identity export type { - IMParticleUser, IdentityCallback, + IdentityHTTPCode, + IdentityModifyResultBody, IdentityResult, IdentityResultBody, - IdentityModifyResultBody, + IMParticleUser, ISDKUserIdentity, ISDKUserAttributes, } from './identity-user-interfaces'; @@ -59,7 +117,7 @@ export type { IIdentitySearchResult, IIdentitySearchResponseBody, IdentitySearchCallback, - IUserIdentities + IUserIdentities, } from './identity.interfaces'; // eCommerce @@ -68,6 +126,20 @@ export type { SDKCart, } from './ecommerce.interfaces'; +export type { + RoktAttributes, + RoktAttributeValue, + RoktAttributeValueArray, + RoktAttributeValueType, + IRoktPartnerExtensionData as RoktPartnerExtensionData, + RoktPlacement, + RoktPlacementEvent, + IRoktSelectPlacementsOptions as RoktSelectPlacementsOptions, + RoktSelection, + RoktSubscriber, + RoktUnsubscriber, +} from './roktManager'; + export type { SDKProduct, SDKPromotion, @@ -75,7 +147,7 @@ export type { SDKProductImpression, } from './sdkRuntimeModels'; -// Consent +// Consent API facade types export type { SDKConsentApi, SDKConsentState, diff --git a/src/publicSdkTypes.ts b/src/publicSdkTypes.ts new file mode 100644 index 000000000..4a7b23f0f --- /dev/null +++ b/src/publicSdkTypes.ts @@ -0,0 +1,268 @@ +import { Batch } from '@mparticle/event-models'; +import type { IdentityCallback } from './identity-user-interfaces'; +import type { DataPlanConfig } from './sdkRuntimeModels'; +import type { Dictionary } from './utils'; + +export type MPID = string; + +export type SDKEventAttrTypes = string | number | boolean | null | undefined; + +export interface SDKEventAttrs { + [key: string]: SDKEventAttrTypes; +} + +export interface SDKEventCustomFlags { + [key: string]: + | number + | string + | boolean + | unknown[] + | Record; +} + +export interface SDKEventOptions { + shouldUploadEvent?: boolean; + sourceMessageId?: string; +} + +export interface Logger { + error?: (error: string) => void; + warning?: (warning: string) => void; + verbose?: (message: string) => void; +} + +export type MPForwarder = Dictionary; + +export type OnUserAlias = (previousUser: User, newUser: User) => void; + +export interface IdentityApiData { + userIdentities?: UserIdentities | null; + onUserAlias?: OnUserAlias | null; + copyUserAttributes?: boolean; +} + +export interface IdentifyRequest extends IdentityApiData { + userIdentities: UserIdentities; +} + +export type UserIdentityValue = string | null; + +export interface UserIdentities { + customerid?: UserIdentityValue; + email?: UserIdentityValue; + other?: UserIdentityValue; + other2?: UserIdentityValue; + other3?: UserIdentityValue; + other4?: UserIdentityValue; + other5?: UserIdentityValue; + other6?: UserIdentityValue; + other7?: UserIdentityValue; + other8?: UserIdentityValue; + other9?: UserIdentityValue; + other10?: UserIdentityValue; + mobile_number?: UserIdentityValue; + phone_number_2?: UserIdentityValue; + phone_number_3?: UserIdentityValue; + facebook?: UserIdentityValue; + facebookcustomaudienceid?: UserIdentityValue; + google?: UserIdentityValue; + twitter?: UserIdentityValue; + microsoft?: UserIdentityValue; + yahoo?: UserIdentityValue; + email_sha256?: UserIdentityValue; + mobile_sha256?: UserIdentityValue; +} + +export type UserAttributesValue = string | number | boolean | null; + +export type AllUserAttributes = Record< + string, + UserAttributesValue | UserAttributesValue[] +>; + +export interface PrivacyConsentState { + Consented: boolean; + Timestamp?: number; + ConsentDocument?: string; + Location?: string; + HardwareId?: string; +} + +export interface GDPRConsentState { + [key: string]: PrivacyConsentState; +} + +export type CCPAConsentState = PrivacyConsentState; + +export interface ConsentState { + setGDPRConsentState(gdprConsentState: GDPRConsentState): ConsentState; + setCCPAConsentState(ccpaConsentState: CCPAConsentState): ConsentState; + addGDPRConsentState( + purpose: string, + gdprConsent: PrivacyConsentState + ): ConsentState; + getGDPRConsentState(): GDPRConsentState; + getCCPAConsentState(): CCPAConsentState; + removeGDPRConsentState(purpose: string): ConsentState; + removeCCPAConsentState(): ConsentState; + removeCCPAState(): ConsentState; +} + +export interface Product { + Name: string; + Sku: string; + Price: number; + Quantity?: number; + Variant?: string; + Category?: string; + Brand?: string; + Position?: number; + Coupon?: string; + CouponCode?: string; + TotalAmount?: number; + Attributes?: Record; +} + +export interface TransactionAttributes { + Id: string | number; + Affiliation?: string; + CouponCode?: string; + Revenue?: string | number; + Shipping?: string | number; + Tax?: number; +} + +export interface Impression { + Name: string; + Product: Product | Product[]; +} + +export interface Promotion { + Id: string | number; + Creative?: string; + Name?: string; + Position?: string | number; +} + +export interface Cart { + /** + * @deprecated Cart persistence in mParticle has been deprecated. + */ + add(product: Product | Product[], logEventBoolean?: boolean): void; + /** + * @deprecated Cart persistence in mParticle has been deprecated. + */ + remove(product: Product | Product[], logEventBoolean?: boolean): void; + /** + * @deprecated Cart persistence in mParticle has been deprecated. + */ + clear(): void; +} + +export interface User { + getUserIdentities(): IdentifyRequest; + getMPID(): MPID; + setUserTag(tag: string, value?: any): void; + removeUserTag(tag: string): void; + setUserAttribute( + key: string, + value: UserAttributesValue | UserAttributesValue[] | unknown + ): void; + setUserAttributes(attributeObject: Record): void; + removeUserAttribute(key: string): void; + setUserAttributeList(key: string, value: UserAttributesValue[]): void; + removeAllUserAttributes(): void; + getUserAttributesLists(): Record; + getAllUserAttributes(): AllUserAttributes; + /** + * @deprecated Cart persistence in mParticle has been deprecated. + */ + getCart(): Cart; + getConsentState(): ConsentState; + setConsentState(consentState: ConsentState): void; + isLoggedIn(): boolean; + getLastSeenTime(): number; + getFirstSeenTime(): number; + getUserAudiences?(callback?: IdentityCallback): void; +} + +export type AliasRequestScope = 'device' | 'mpid'; + +export interface UserAliasRequest { + destinationMpid: MPID; + sourceMpid: MPID; + startTime: number; + endTime: number; + scope?: AliasRequestScope; +} + +export interface AliasUsersCallback { + (result: { httpCode: number; message: string }): void; +} + +export interface Callback { + (): void; +} + +export interface Location { + coords: { + latitude: number; + longitude: number; + }; + timestamp: number; +} + +export interface TrackLocationCallback { + (location: Location): void; +} + +export interface OnCreateBatch { + (batch: Batch): Batch; +} + +export type onCreateBatch = OnCreateBatch; + +export type LogLevel = 'verbose' | 'warning' | 'error' | 'none'; + +export interface LauncherOptions { + noTargeting?: boolean; + noFunctional?: boolean; + [key: string]: unknown; +} + +export interface MPConfiguration { + isDevelopmentMode?: boolean; + identifyRequest?: IdentityApiData; + identityCallback?: IdentityCallback; + dataPlan?: DataPlanConfig; + appVersion?: string; + appName?: string; + package?: string; + logLevel?: LogLevel; + logger?: Logger; + sessionTimeout?: number; + deviceId?: string; + onCreateBatch?: OnCreateBatch; + useCookieStorage?: boolean; + maxCookieSize?: number; + cookieDomain?: string; + customFlags?: SDKEventCustomFlags; + sideloadedKits?: MPForwarder[]; + workspaceToken?: string; + requiredWebviewBridgeName?: string; + minWebviewBridgeVersion?: 1 | 2; + aliasUrl?: string; + configUrl?: string; + forceHttps?: boolean; + identityUrl?: string; + integrationDelayTimeout?: number; + isIOS?: boolean; + maxProducts?: number; + requestConfig?: boolean; + useNativeSdk?: boolean; + v1SecureServiceUrl?: string; + v2SecureServiceUrl?: string; + v3SecureServiceUrl?: string; + domain?: string; + launcherOptions?: LauncherOptions; +} diff --git a/src/roktManager.ts b/src/roktManager.ts index 844d2a209..bf26cda59 100644 --- a/src/roktManager.ts +++ b/src/roktManager.ts @@ -14,7 +14,7 @@ import { import { SDKIdentityApi } from "./identity.interfaces"; import { SDKLoggerApi } from "./sdkRuntimeModels"; import { IStore, LocalSessionAttributes } from "./store"; -import { UserIdentities } from "@mparticle/web-sdk"; +import { UserIdentities } from './publicSdkTypes'; import { IdentityType, PerformanceMarkType } from "./types"; import { ErrorCodes, IErrorReportingService, ILoggingService, WSDKErrorSeverity } from "./reporting/types"; @@ -34,13 +34,49 @@ export interface IRoktSelectPlacementsOptions { identifier?: string; } -interface IRoktPlacement {} +export interface RoktPlacementEvent { + body: T; + event: string; + placement: RoktPlacement; +} + +export interface RoktUnsubscriber { + unsubscribe(): void; +} + +export interface RoktSubscriber { + subscribe(callback: (event: T) => void): RoktUnsubscriber; +} + +export interface RoktPlacement { + id: string; + element: HTMLIFrameElement; + on(eventName: string): RoktSubscriber>; + ready(): Promise; + send(eventName: string, payload?: T): Promise; + onClose(): Promise; + close(): Promise; +} -export interface IRoktSelection { - close: () => void; - getPlacements: () => Promise; +export interface RoktSelection { + close(): Promise; + on(eventName: string): RoktSubscriber>; + getPlacements(): Promise; + ready(): Promise; + send(eventName: string, payload?: T): Promise; + setAttributes(attributes: RoktAttributes): Promise; + context?: { + sessionId?: Promise; + [key: string]: unknown; + }; } +export type IRoktPlacementEvent = RoktPlacementEvent; +export type IRoktSubscription = RoktUnsubscriber; +export type IRoktEventChannel = RoktSubscriber>; +export type IRoktPlacement = RoktPlacement; +export type IRoktSelection = RoktSelection; + export interface IRoktLauncher { selectPlacements: (options: IRoktSelectPlacementsOptions) => Promise; hashAttributes: (attributes: RoktAttributes) => Promise>; diff --git a/src/sdkRuntimeModels.ts b/src/sdkRuntimeModels.ts index e31084228..708b08a74 100644 --- a/src/sdkRuntimeModels.ts +++ b/src/sdkRuntimeModels.ts @@ -3,10 +3,10 @@ import { DataPlanVersion } from '@mparticle/data-planning-models'; import { MPConfiguration, MPID, - SDKEventOptions, SDKEventAttrs, - Callback, -} from '@mparticle/web-sdk'; + SDKEventOptions, + TrackLocationCallback, +} from './publicSdkTypes'; import { IntegrationAttribute, IntegrationAttributes, @@ -14,8 +14,8 @@ import { WrapperSDKTypes, } from './store'; import Validators from './validators'; -import { Dictionary, valueof } from './utils'; -import { IKitConfigs } from './configAPIClient'; +import { AttributeValue, Dictionary, Environment, valueof } from './utils'; +import type { IKitConfigs } from './configAPIClient'; import { SDKConsentApi, SDKConsentState } from './consent'; import MPSideloadedKit from './sideloadedKit'; import { ISessionManager } from './sessionManager'; @@ -53,7 +53,8 @@ import RoktManager, { IRoktLauncherOptions } from './roktManager'; import { IConsoleLogger } from './logger'; import { ErrorCodes, IErrorReportingService, ILoggingService } from './reporting/types'; -// TODO: Resolve this with version in @mparticle/web-sdk +// Internal SDK custom flags are normalized before upload and may temporarily +// contain arrays or other values supported by the legacy public API. export type SDKEventCustomFlags = Dictionary; export interface SDKEvent { @@ -117,15 +118,15 @@ export interface SDKPromotionAction { } export interface SDKPromotion { - Id?: string; + Id: string | number; Name?: string; Creative?: string; - Position?: string; + Position?: string | number; } export interface SDKImpression { Name: string; - Product: SDKProduct; + Product: SDKProduct | SDKProduct[]; } export interface SDKProductImpression { @@ -203,8 +204,8 @@ export interface MParticleWebSDK { getAppVersion(): string; getDeviceId(): string; setDeviceId(deviceId: string): void; - getEnvironment(): valueof; - setSessionAttribute(key: string, value: string): void; + getEnvironment(): Environment; + setSessionAttribute(key: string, value: AttributeValue): void; getVersion(): string; upload(): void; setLogLevel(logLevel: LogLevelType): void; @@ -219,17 +220,18 @@ export interface MParticleWebSDK { ): void; logBaseEvent(event: BaseEvent, eventOptions?: SDKEventOptions): void; logError(error: IErrorLogMessage, attrs?: SDKEventAttrs): void; + logError(error: string, attrs?: SDKEventAttrs): void; logLink( selector: string, eventName: string, - eventType: valueof, - eventInfo: SDKEventAttrs + eventType?: valueof, + eventInfo?: SDKEventAttrs ): void; logForm( selector: string, eventName: string, - eventType: valueof, - eventInfo: SDKEventAttrs + eventType?: valueof, + eventInfo?: SDKEventAttrs ): void; logPageView( eventName?: string, @@ -250,10 +252,10 @@ export interface MParticleWebSDK { setOptOut(isOptingOut: boolean): void; // https://go.mparticle.com/work/SQDSDKS-7063 - startTrackingLocation(callback?: Callback): void; + startTrackingLocation(callback?: TrackLocationCallback): void; stopTrackingLocation(): void; - generateHash(value: string): string; + generateHash(value: string): number; setIntegrationAttribute( integrationModuleId: number, attrs: IntegrationAttribute @@ -264,10 +266,23 @@ export interface MParticleWebSDK { _registerLoggingService(service: ILoggingService): void; } +export interface MParticleWebSDKInstance extends MParticleWebSDK {} + +export interface MParticleWebSDKManager extends MParticleWebSDK { + config: SDKInitConfig; + isIOS?: boolean; + MPSideloadedKit: typeof MPSideloadedKit; + Rokt: RoktManager; + sessionManager: Pick; + Store: IStore; + getInstance(): MParticleWebSDKInstance; + getInstance(instanceName: string): MParticleWebSDKInstance | null; +} + // https://go.mparticle.com/work/SQDSDKS-4805 // https://go.mparticle.com/work/SQDSDKS-6949 -export interface IMParticleInstanceManager extends MParticleWebSDK { +export interface IMParticleInstanceManager extends MParticleWebSDKManager { // https://go.mparticle.com/work/SQDSDKS-5053 // Private Properties _BatchValidator: _BatchValidator; @@ -284,7 +299,8 @@ export interface IMParticleInstanceManager extends MParticleWebSDK { Store: IStore; // Public Methods - getInstance(instanceName?: string): IMParticleWebSDKInstance; + getInstance(): IMParticleWebSDKInstance; + getInstance(instanceName: string): IMParticleWebSDKInstance | null; } // Used in cases where server requires booleans as strings @@ -363,7 +379,7 @@ export interface SDKHelpersApi { findKeyInObject?(obj: any, key: string): string; parseNumber?(value: string | number): number; generateUniqueId(); - generateHash?(value: string): string; + generateHash?(value: string): number; // https://go.mparticle.com/work/SQDSDKS-6317 getFeatureFlag?(feature: string): boolean | string; // TODO: Feature Constants should be converted to enum invokeAliasCallback( @@ -388,7 +404,7 @@ export interface SDKHelpersApi { sanitizeAttributes?( attrs: SDKEventAttrs, name: string - ): Dictionary | null; + ): Dictionary | null; Validators: typeof Validators; } diff --git a/src/sdkToEventsApiConverter.ts b/src/sdkToEventsApiConverter.ts index 16bb339fa..4b6826c1b 100644 --- a/src/sdkToEventsApiConverter.ts +++ b/src/sdkToEventsApiConverter.ts @@ -406,10 +406,10 @@ export function convertPromotions( const promotions: EventsApi.Promotion[] = []; for (const sdkPromotion of sdkPromotions) { const promotion: EventsApi.Promotion = { - id: sdkPromotion.Id, + id: sdkPromotion.Id as EventsApi.Promotion['id'], name: sdkPromotion.Name, creative: sdkPromotion.Creative, - position: sdkPromotion.Position, + position: sdkPromotion.Position as EventsApi.Promotion['position'], }; promotions.push(promotion); } diff --git a/src/serverModel.ts b/src/serverModel.ts index c21663c9a..10044b67c 100644 --- a/src/serverModel.ts +++ b/src/serverModel.ts @@ -19,7 +19,7 @@ import { extend, } from './utils'; import { IntegrationAttributes, ServerSettings } from './store'; -import { MPID } from '@mparticle/web-sdk'; +import { MPID } from './publicSdkTypes'; import { IConsentStateV2DTO, IGDPRConsentStateV2DTO, diff --git a/src/sessionManager.ts b/src/sessionManager.ts index 4b6cf68a4..2380fb7b5 100644 --- a/src/sessionManager.ts +++ b/src/sessionManager.ts @@ -1,4 +1,4 @@ -import { MPID } from '@mparticle/web-sdk'; +import { MPID } from './publicSdkTypes'; import Constants from './constants'; import { IPersistenceMinified } from './persistence.interfaces'; import Types from './types'; diff --git a/src/sideloadedKit.ts b/src/sideloadedKit.ts index 5bc6d1e63..58e307ed5 100644 --- a/src/sideloadedKit.ts +++ b/src/sideloadedKit.ts @@ -22,7 +22,7 @@ export interface IMPSideloadedKit { ): void; addScreenNameFilter(screenName: string): void; addScreenAttributeFilter(screenName: string, screenAttribute: string): void; - addUserIdentityFilter(userIdentity: typeof IdentityType): void; + addUserIdentityFilter(userIdentity: valueof): void; addUserAttributeFilter(userAttributeKey: string): void; } @@ -109,7 +109,7 @@ export default class MPSideloadedKit implements IMPSideloadedKit{ ); } - public addUserIdentityFilter(userIdentity: typeof IdentityType): void { + public addUserIdentityFilter(userIdentity: valueof): void { const hashedIdentityType = KitFilterHelper.hashUserIdentity( userIdentity ); diff --git a/src/store.ts b/src/store.ts index 4bd1617e1..b10da9a93 100644 --- a/src/store.ts +++ b/src/store.ts @@ -1,15 +1,15 @@ import { Batch, Context } from '@mparticle/event-models'; import { - DataPlanConfig, + IdentityApiData, MPID, - IdentifyRequest, SDKEventCustomFlags, ConsentState, UserIdentities, -} from '@mparticle/web-sdk'; +} from './publicSdkTypes'; import { IKitConfigs } from './configAPIClient'; import Constants from './constants'; import { + DataPlanConfig, DataPlanResult, KitBlockerOptions, LogLevelType, @@ -70,7 +70,7 @@ export interface SDKConfig { cookieDomain?: string; maxCookieSize?: number | undefined; minWebviewBridgeVersion: 1 | 2 | undefined; - identifyRequest: IdentifyRequest; + identifyRequest?: IdentityApiData | null; identityCallback: IdentityCallback; integrationDelayTimeout: number; sideloadedKits: MPForwarder[]; diff --git a/src/user-utils.ts b/src/user-utils.ts index 9e491389b..7283de0fd 100644 --- a/src/user-utils.ts +++ b/src/user-utils.ts @@ -1,4 +1,4 @@ -import { UserIdentities } from '@mparticle/web-sdk'; +import { UserIdentities } from './publicSdkTypes'; import { IMParticleUser, ISDKUserIdentity, IdentityResultBody } from './identity-user-interfaces'; import { SDKEvent } from './sdkRuntimeModels'; import Types from './types'; diff --git a/src/utils.ts b/src/utils.ts index 916043e1a..0ffc3e220 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,4 @@ -import { MPID } from '@mparticle/web-sdk'; +import { MPID } from './publicSdkTypes'; import Constants from './constants'; import { SDKInitConfig } from './sdkRuntimeModels'; import { IKitConfigs } from './configAPIClient'; @@ -12,7 +12,7 @@ type AttributeValue = string | number | boolean | null | undefined; // Placeholder for Dictionary-like Types export type Dictionary = Record; -export type Environment = valueof; +export type Environment = 'development' | 'production'; const createCookieString = (value: string): string => replaceCommasWithPipes(replaceQuotesWithApostrophes(value)); diff --git a/src/validators.ts b/src/validators.ts index a9abf54ac..2c838585d 100644 --- a/src/validators.ts +++ b/src/validators.ts @@ -8,7 +8,7 @@ import { valueof, } from './utils'; import Constants from './constants'; -import { IdentityApiData } from '@mparticle/web-sdk'; +import { IdentityApiData } from './publicSdkTypes'; import { IdentityAPIMethod } from './identity.interfaces'; type ValidationIdentitiesReturn = { From 8b32cc198bcd4d4854a3654108f500df91a14d7b Mon Sep 17 00:00:00 2001 From: Robert Ing Date: Fri, 15 May 2026 12:04:02 -0400 Subject: [PATCH 2/8] test(types): add consumer compatibility checks --- jest.config.js | 19 +- package-lock.json | 11 - package.json | 6 +- test/jest/identity.spec.ts | 4 +- test/src/config/setup.ts | 7 - test/src/tests-apiClient.ts | 7 - test/src/tests-audience-manager.ts | 1 - test/src/tests-batchUploader.ts | 7 - test/src/tests-batchUploader_2.ts | 7 - test/src/tests-batchUploader_3.ts | 7 - test/src/tests-batchUploader_4.ts | 7 - test/src/tests-beaconUpload.ts | 2 - test/src/tests-config-api-client.ts | 7 - test/src/tests-consent.ts | 2 - test/src/tests-cookie-syncing.ts | 2 - test/src/tests-feature-flags.ts | 7 - test/src/tests-forwarders.ts | 1 - test/src/tests-identities-attributes.ts | 6 - test/src/tests-identity.ts | 1 - test/src/tests-identityApiClient.ts | 4 +- test/src/tests-integration-capture.ts | 1 - test/src/tests-kit-blocking.ts | 1 - test/src/tests-legacy-alias-requests.ts | 1 - test/src/tests-mparticle-instance-manager.ts | 6 - test/src/tests-runtimeToBatchEventsDTO.ts | 6 - test/src/tests-search.ts | 1 - test/src/tests-session-manager.ts | 2 - test/src/tests-user.ts | 1 - test/types/definitely-typed/instance.ts | 885 +++++++++++++++++++ test/types/definitely-typed/manager.ts | 885 +++++++++++++++++++ test/types/definitely-typed/tsconfig.json | 19 + test/types/internal-consumer.ts | 78 ++ test/types/public-consumer.ts | 273 ++++++ test/types/tsconfig.json | 20 + tsconfig.json | 11 +- 35 files changed, 2190 insertions(+), 115 deletions(-) create mode 100644 test/types/definitely-typed/instance.ts create mode 100644 test/types/definitely-typed/manager.ts create mode 100644 test/types/definitely-typed/tsconfig.json create mode 100644 test/types/internal-consumer.ts create mode 100644 test/types/public-consumer.ts create mode 100644 test/types/tsconfig.json diff --git a/jest.config.js b/jest.config.js index 5b5aa4cd1..3f74c0dfa 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,11 +4,20 @@ module.exports = { // The built mParticle.js file needs to exist for integration tests setupFiles: ['./test/jest/setup.ts', './dist/mparticle.js'], setupFilesAfterEnv: ['jest-expect-message'], - // Exclude Adobe kit test files — Adobe uses Jest but via its own kit-level - // jest.config.js; running them from the root would be missing kit setup. - // Other kits use Karma and name their tests `tests.js` (plural), which - // doesn't match Jest's default testMatch, so they don't need exclusion. - testPathIgnorePatterns: ['/kits/adobe'], + testPathIgnorePatterns: [ + '/node_modules/', + '/build/', + '/.agents/', + '/.claude/', + // Exclude Adobe kit test files. Adobe uses Jest through its own + // kit-level config; running it from the root skips kit setup. + '/kits/adobe', + ], + modulePathIgnorePatterns: [ + '/build/', + '/.agents/', + '/.claude/', + ], transform: { '^.+\\.(js)$': 'ts-jest', }, diff --git a/package-lock.json b/package-lock.json index 625ce5b87..c2e5d7ac8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,6 @@ "@types/jest": "^29.5.1", "@types/jest-expect-message": "^1.1.0", "@types/mocha": "^9.0.0", - "@types/mparticle__web-sdk": "^2.66.0", "@types/node": "^20.1.0", "babel-preset-minify": "^0.5.1", "browser-sync": "^2.26.3", @@ -4061,16 +4060,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mparticle__web-sdk": { - "version": "2.66.0", - "resolved": "https://registry.npmjs.org/@types/mparticle__web-sdk/-/mparticle__web-sdk-2.66.0.tgz", - "integrity": "sha512-+PwrdQ4Zwt2G3g0NFVfUsU+21+XZT/iiMNIvGtMB7CTu8+hJhNpJ9LiGhEJLdcTA10yZuxp14V3qMlK6eyRusQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@mparticle/event-models": "^1.1.9" - } - }, "node_modules/@types/node": { "version": "20.8.9", "dev": true, diff --git a/package.json b/package.json index 1eff994e6..d29462482 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "repository": "https://github.com/mParticle/mparticle-web-sdk", "scripts": { "build": "cross-env ENVIRONMENT=prod BUILDALL=true rollup --config rollup.config.js && npm run build:types", - "build:types": "rm -rf dist/types && (tsc -p tsconfig.types.json || true) && test -f dist/types/src/public-types.d.ts && test -f dist/types/src/internal-types.d.ts", + "build:types": "rm -rf dist/types && tsc -p tsconfig.types.json && test -f dist/types/src/public-types.d.ts && test -f dist/types/src/internal-types.d.ts", "build:cbt": "rollup --config test/cross-browser-testing/rollup.CBT.config.js", "build:dev": "cross-env ENVIRONMENT=dev BUILD=iife rollup --config rollup.config.js", "build:iife": "cross-env ENVIRONMENT=prod BUILD=iife rollup --config rollup.config.js", @@ -67,6 +67,9 @@ "test:integrations:module": "npm run test:integrations:module:webpack && npm run test:integrations:module:rollup", "test:integrations:module:webpack": "npm run build:webpack:module && npm run test:karma:webpack:module", "test:integrations:module:rollup": "npm run build:rollup:module && npm run test:karma:rollup:module", + "test:types": "npm run build:types && npm run test:types:consumers && npm run test:types:definitely-typed", + "test:types:consumers": "tsc -p test/types/tsconfig.json", + "test:types:definitely-typed": "tsc -p test/types/definitely-typed/tsconfig.json", "test:requirejs": "npm run build:iife && npm run build:rollup:requirejs && npm run test:requirejs:before && npm run test:requirejs:after", "test:requirejs:before": "cross-env FILE_ORDER=before_mp karma start test/integrations/requirejs/karma.requirejs.config.js", "test:requirejs:after": "cross-env FILE_ORDER=after_mp karma start test/integrations/requirejs/karma.requirejs.config.js", @@ -118,7 +121,6 @@ "@types/jest": "^29.5.1", "@types/jest-expect-message": "^1.1.0", "@types/mocha": "^9.0.0", - "@types/mparticle__web-sdk": "^2.66.0", "@types/node": "^20.1.0", "babel-preset-minify": "^0.5.1", "browser-sync": "^2.26.3", diff --git a/test/jest/identity.spec.ts b/test/jest/identity.spec.ts index 22c799e33..c0a494302 100644 --- a/test/jest/identity.spec.ts +++ b/test/jest/identity.spec.ts @@ -125,7 +125,7 @@ describe('Identity', () => { context: 'test-context', environment: 'development', request_id: '123', - request_timestamp_unixtime_ms: Date.now(), + request_timestamp_ms: Date.now(), previous_mpid: null, known_identities: { email: 'user@mparticle.com', @@ -145,7 +145,7 @@ describe('Identity', () => { context: 'test-context', environment: 'development', request_id: '123', - request_timestamp_unixtime_ms: Date.now(), + request_timestamp_ms: Date.now(), identity_changes: [ { identity_type: SDKIdentityTypeEnum.google, diff --git a/test/src/config/setup.ts b/test/src/config/setup.ts index d45ce74b4..4b46408dd 100644 --- a/test/src/config/setup.ts +++ b/test/src/config/setup.ts @@ -1,11 +1,4 @@ import { MPConfig, workspaceToken } from './constants'; -import { IMParticleInstanceManager } from '../../../src/sdkRuntimeModels'; - -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} let userApi = null; diff --git a/test/src/tests-apiClient.ts b/test/src/tests-apiClient.ts index 6082dc93b..c527a2b14 100644 --- a/test/src/tests-apiClient.ts +++ b/test/src/tests-apiClient.ts @@ -2,13 +2,6 @@ import Types from '../../src/types'; import { apiKey, MPConfig } from './config/constants'; import { expect } from 'chai'; import { IMParticleUser } from '../../src/identity-user-interfaces'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; - -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} const mParticle = window.mParticle; diff --git a/test/src/tests-audience-manager.ts b/test/src/tests-audience-manager.ts index db6111fce..3b192aced 100644 --- a/test/src/tests-audience-manager.ts +++ b/test/src/tests-audience-manager.ts @@ -13,7 +13,6 @@ const { fetchMockSuccess } = Utils; declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/src/tests-batchUploader.ts b/test/src/tests-batchUploader.ts index f3f65e705..84eabe068 100644 --- a/test/src/tests-batchUploader.ts +++ b/test/src/tests-batchUploader.ts @@ -2,7 +2,6 @@ import sinon from 'sinon'; import { urls, apiKey, MPConfig, testMPID } from './config/constants'; import { BaseEvent, - IMParticleInstanceManager, SDKEvent, } from '../../src/sdkRuntimeModels'; import { Batch, CustomEventData } from '@mparticle/event-models'; @@ -22,12 +21,6 @@ const { triggerVisibilityHidden } = Utils; -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} - const enableBatchingConfigFlags = { eventBatchingIntervalMillis: 1000, }; diff --git a/test/src/tests-batchUploader_2.ts b/test/src/tests-batchUploader_2.ts index 69642a83f..c9c22f529 100644 --- a/test/src/tests-batchUploader_2.ts +++ b/test/src/tests-batchUploader_2.ts @@ -3,16 +3,9 @@ import Utils from './config/utils'; import { expect } from 'chai'; import _BatchValidator from '../../src/mockBatchCreator'; import fetchMock from 'fetch-mock/esm/client'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; import { CustomEvent } from '@mparticle/event-models'; const { fetchMockSuccess, waitForCondition, hasIdentifyReturned } = Utils; -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} - const enableBatchingConfigFlags = { eventBatchingIntervalMillis: 1000, }; diff --git a/test/src/tests-batchUploader_3.ts b/test/src/tests-batchUploader_3.ts index cff01e436..5e29b59da 100644 --- a/test/src/tests-batchUploader_3.ts +++ b/test/src/tests-batchUploader_3.ts @@ -3,15 +3,8 @@ import Utils from './config/utils'; import { expect } from 'chai'; import fetchMock from 'fetch-mock/esm/client'; import Types, { ProductActionType } from '../../src/types'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; const { fetchMockSuccess, waitForCondition, hasIdentifyReturned } = Utils; -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} - describe('batch uploader', () => { beforeEach(() => { window.mParticle._resetForTests(MPConfig); diff --git a/test/src/tests-batchUploader_4.ts b/test/src/tests-batchUploader_4.ts index a4c0251c7..11872d2e4 100644 --- a/test/src/tests-batchUploader_4.ts +++ b/test/src/tests-batchUploader_4.ts @@ -6,15 +6,8 @@ import { expect } from 'chai'; import _BatchValidator from '../../src/mockBatchCreator'; import fetchMock from 'fetch-mock/esm/client'; import { ProductActionType } from '../../src/types'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; const { fetchMockSuccess, waitForCondition, hasIdentifyReturned } = Utils; -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} - describe('batch uploader', () => { let mockServer; diff --git a/test/src/tests-beaconUpload.ts b/test/src/tests-beaconUpload.ts index cb0df7a3e..e5ce1c98d 100644 --- a/test/src/tests-beaconUpload.ts +++ b/test/src/tests-beaconUpload.ts @@ -6,12 +6,10 @@ import { event0 } from '../fixtures/events'; import { batch1, batch2, batch3 } from '../fixtures/batches'; import _BatchValidator from '../../src/mockBatchCreator'; import Utils from './config/utils'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; const { waitForCondition, fetchMockSuccess, hasIdentifyReturned, triggerVisibilityHidden } = Utils; declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/src/tests-config-api-client.ts b/test/src/tests-config-api-client.ts index 78430e786..ec8b36ac1 100644 --- a/test/src/tests-config-api-client.ts +++ b/test/src/tests-config-api-client.ts @@ -6,16 +6,9 @@ import ConfigAPIClient from '../../src/configAPIClient'; import { DataPlanConfig, DataPlanResult, - IMParticleInstanceManager, SDKInitConfig, } from '../../src/sdkRuntimeModels'; -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} - describe('ConfigAPIClient', () => { let mockServer; let sdkInitCompleteCallback; diff --git a/test/src/tests-consent.ts b/test/src/tests-consent.ts index ad76e2ebe..7d59816dd 100644 --- a/test/src/tests-consent.ts +++ b/test/src/tests-consent.ts @@ -5,12 +5,10 @@ import { urls, apiKey, MPConfig, testMPID } from './config/constants'; import { expect } from 'chai'; import { GDPRConsentState, PrivacyConsentState } from '@mparticle/web-sdk'; import { Dictionary } from '../../src/utils'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; const { hasIdentifyReturned, waitForCondition, fetchMockSuccess } = Utils; declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/src/tests-cookie-syncing.ts b/test/src/tests-cookie-syncing.ts index 02159963b..130006180 100644 --- a/test/src/tests-cookie-syncing.ts +++ b/test/src/tests-cookie-syncing.ts @@ -6,7 +6,6 @@ import { urls, testMPID, MPConfig, v4LSKey, apiKey } from './config/constants'; import { IMParticleUser } from '../../src/identity-user-interfaces'; import { IPixelConfiguration, PARTNER_MODULE_IDS } from '../../src/cookieSyncManager'; import { IConsentRules } from '../../src/consent'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; const { fetchMockSuccess, waitForCondition, @@ -30,7 +29,6 @@ const pixelSettings: IPixelConfiguration = { declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/src/tests-feature-flags.ts b/test/src/tests-feature-flags.ts index 4493c936d..8dedee886 100644 --- a/test/src/tests-feature-flags.ts +++ b/test/src/tests-feature-flags.ts @@ -7,16 +7,9 @@ import { urls, apiKey, MPConfig, } from './config/constants'; import Utils from './config/utils'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; const { waitForCondition, fetchMockSuccess, deleteAllCookies } = Utils; -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} - const hasIdentifyReturned = () => { return window.mParticle.Identity.getCurrentUser()?.getMPID() === testMPID; }; diff --git a/test/src/tests-forwarders.ts b/test/src/tests-forwarders.ts index d487090b3..6aa514ccb 100644 --- a/test/src/tests-forwarders.ts +++ b/test/src/tests-forwarders.ts @@ -80,7 +80,6 @@ interface MockMParticleForForwarders extends IMParticleInstanceManager{ declare global { interface Window { - mParticle: IMParticleInstanceManager; MockForwarder: IMockForwarder; MockForwarder1: IMockForwarder; SideloadedKit11: IMockForwarder; diff --git a/test/src/tests-identities-attributes.ts b/test/src/tests-identities-attributes.ts index 928c066a8..51a4032b7 100644 --- a/test/src/tests-identities-attributes.ts +++ b/test/src/tests-identities-attributes.ts @@ -24,12 +24,6 @@ const { setupLoggerSpy } = Utils; -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} - const mParticle = window.mParticle as IMParticleInstanceManager; const BAD_SESSION_ATTRIBUTE_KEY_AS_OBJECT = ({ diff --git a/test/src/tests-identity.ts b/test/src/tests-identity.ts index e17ecf5cd..0f3819fa1 100644 --- a/test/src/tests-identity.ts +++ b/test/src/tests-identity.ts @@ -50,7 +50,6 @@ const { HTTPCodes } = Constants; declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/src/tests-identityApiClient.ts b/test/src/tests-identityApiClient.ts index 0f3142af2..46adc8326 100644 --- a/test/src/tests-identityApiClient.ts +++ b/test/src/tests-identityApiClient.ts @@ -19,7 +19,6 @@ import IdentityAPIClient, { IIdentityApiClient } from '../../src/identityApiClie import { IIdentityResponse } from '../../src/identity-user-interfaces'; import Utils from './config/utils'; import { IMParticleWebSDKInstance } from '../../src/mp-instance'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; import RoktManager from '../../src/roktManager'; import { ErrorReportingDispatcher } from '../../src/reporting/errorReportingDispatcher'; const { fetchMockSuccess } = Utils; @@ -27,7 +26,6 @@ const { HTTPCodes } = Constants; declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } @@ -45,7 +43,7 @@ describe('Identity Api Client', () => { context: 'test-context', environment: 'development', request_id: '123', - request_timestamp_unixtime_ms: Date.now(), + request_timestamp_ms: Date.now(), previous_mpid: null, known_identities: { email: 'user@mparticle.com', diff --git a/test/src/tests-integration-capture.ts b/test/src/tests-integration-capture.ts index 5ecf04fd3..ebfab75f0 100644 --- a/test/src/tests-integration-capture.ts +++ b/test/src/tests-integration-capture.ts @@ -16,7 +16,6 @@ const { declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/src/tests-kit-blocking.ts b/test/src/tests-kit-blocking.ts index 428e258f2..4d851ab6f 100644 --- a/test/src/tests-kit-blocking.ts +++ b/test/src/tests-kit-blocking.ts @@ -16,7 +16,6 @@ const MockForwarder = Utils.MockForwarder; declare global { interface Window { - mParticle: IMParticleInstanceManager; MockForwarder1: IMockForwarder; } } diff --git a/test/src/tests-legacy-alias-requests.ts b/test/src/tests-legacy-alias-requests.ts index f1c2264cb..51436d853 100644 --- a/test/src/tests-legacy-alias-requests.ts +++ b/test/src/tests-legacy-alias-requests.ts @@ -23,7 +23,6 @@ const { HTTPCodes } = Constants; declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/src/tests-mparticle-instance-manager.ts b/test/src/tests-mparticle-instance-manager.ts index a0fe0dc73..4e192a615 100644 --- a/test/src/tests-mparticle-instance-manager.ts +++ b/test/src/tests-mparticle-instance-manager.ts @@ -11,12 +11,6 @@ const { hasConfigurationReturned } = Utils; -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} - const mParticle = window.mParticle as IMParticleInstanceManager;; let mockServer; diff --git a/test/src/tests-runtimeToBatchEventsDTO.ts b/test/src/tests-runtimeToBatchEventsDTO.ts index d09246482..c1953b712 100644 --- a/test/src/tests-runtimeToBatchEventsDTO.ts +++ b/test/src/tests-runtimeToBatchEventsDTO.ts @@ -7,12 +7,6 @@ import * as EventsApi from '@mparticle/event-models'; import { MPConfig, apiKey } from './config/constants'; import { IMParticleUser } from '../../src/identity-user-interfaces'; -declare global { - interface Window { - mParticle: IMParticleInstanceManager; - } -} - describe('Old model to batch model conversion', () => { beforeEach(function() { window.mParticle._resetForTests(MPConfig); diff --git a/test/src/tests-search.ts b/test/src/tests-search.ts index 011fa5083..8764e87be 100644 --- a/test/src/tests-search.ts +++ b/test/src/tests-search.ts @@ -17,7 +17,6 @@ const { HTTPCodes } = Constants; declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/src/tests-session-manager.ts b/test/src/tests-session-manager.ts index 6bb3f25de..9abb87db6 100644 --- a/test/src/tests-session-manager.ts +++ b/test/src/tests-session-manager.ts @@ -13,13 +13,11 @@ import { import { IdentityApiData } from '@mparticle/web-sdk'; import { MILLIS_IN_ONE_SEC } from '../../src/constants'; import Constants from '../../src/constants'; -import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; const { Messages } = Constants; declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/src/tests-user.ts b/test/src/tests-user.ts index 237c1bd1b..9f534926e 100644 --- a/test/src/tests-user.ts +++ b/test/src/tests-user.ts @@ -8,7 +8,6 @@ const { fetchMockSuccess, waitForCondition } = Utils; declare global { interface Window { - mParticle: IMParticleInstanceManager; fetchMock: any; } } diff --git a/test/types/definitely-typed/instance.ts b/test/types/definitely-typed/instance.ts new file mode 100644 index 000000000..47be57e6e --- /dev/null +++ b/test/types/definitely-typed/instance.ts @@ -0,0 +1,885 @@ +/** + * Legacy DefinitelyTyped compatibility compile test. + * + * This file is based on the old @types/mparticle__web-sdk instance tests. It + * keeps the old mParticle namespace-style type references while importing the + * SDK through this package's default runtime export. + */ + +import mParticle from "@mparticle/web-sdk"; +import type * as MParticleTypes from "@mparticle/web-sdk"; +import { Batch } from "@mparticle/event-models"; + +declare namespace mParticle { + export type AllUserAttributes = MParticleTypes.AllUserAttributes; + export type CCPAConsentState = MParticleTypes.CCPAConsentState; + export type ConsentState = MParticleTypes.ConsentState; + export type DataPlanConfig = MParticleTypes.DataPlanConfig; + export type GDPRConsentState = MParticleTypes.GDPRConsentState; + export type IdentifyRequest = MParticleTypes.IdentifyRequest; + export type IdentityCallback = MParticleTypes.IdentityCallback; + export type IdentityResult = MParticleTypes.IdentityResult; + export type IdentityResultBody = MParticleTypes.IdentityResultBody; + export type Impression = MParticleTypes.Impression; + export type KitFilterSettings = MParticleTypes.KitFilterSettings; + export type Location = MParticleTypes.Location; + export type Logger = MParticleTypes.Logger; + export type MPConfiguration = MParticleTypes.MPConfiguration; + export type MPForwarder = MParticleTypes.MPForwarder; + export type MPID = MParticleTypes.MPID; + export type MPSideloadedKit = MParticleTypes.MPSideloadedKit; + export type Product = MParticleTypes.Product; + export type Promotion = MParticleTypes.Promotion; + export type RoktAttributes = MParticleTypes.RoktAttributes; + export type RoktPlacement = MParticleTypes.RoktPlacement; + export type RoktPlacementEvent = + MParticleTypes.RoktPlacementEvent; + export type RoktSelection = MParticleTypes.RoktSelection; + export type SDKEventAttrs = MParticleTypes.SDKEventAttrs; + export type SDKEventCustomFlags = MParticleTypes.SDKEventCustomFlags; + export type SDKEventOptions = MParticleTypes.SDKEventOptions; + export type TransactionAttributes = MParticleTypes.TransactionAttributes; + export type User = MParticleTypes.User; + export type UserAliasRequest = MParticleTypes.UserAliasRequest; + export type onCreateBatch = MParticleTypes.onCreateBatch; +} + +const instance = mParticle.getInstance("default")!; + +const dataPlan: mParticle.DataPlanConfig = { + planId: "test", + planVersion: 2, +}; + +const customAttrs: mParticle.SDKEventAttrs = { + attr1: "hi", + attr2: 2, + attr3: null, + attr4: undefined, + attr5: true, +}; + +const customFlags: mParticle.SDKEventCustomFlags = { + attr1: "hi", + attr2: 2, + attr3: true, + attr4: [{ foo: "2" }], + attr5: { foo: "bar" }, +}; + +const eventOptions: mParticle.SDKEventOptions = { + shouldUploadEvent: false, + sourceMessageId: "sourceMessageId", +}; + +const eventOptionsOnlyShouldUpload: mParticle.SDKEventOptions = { + shouldUploadEvent: true, +}; + +const eventOptionsOnlySourceMessageId: mParticle.SDKEventOptions = { + sourceMessageId: "test-message-id", +}; + +const eventOptionsEmpty: mParticle.SDKEventOptions = {}; + +const identifyRequest: mParticle.IdentifyRequest = { + userIdentities: { + customerid: "test", + email: "test", + other: "test", + other2: "test", + other3: "test", + other4: "test", + other5: "test", + other6: "test", + other7: "test", + other8: "test", + other9: "test", + other10: "test", + mobile_number: "test", + phone_number_2: "test", + phone_number_3: "test", + facebook: "test", + facebookcustomaudienceid: "test", + google: "test", + twitter: "test", + microsoft: null, + yahoo: null, + }, +}; + +const identityCallback: mParticle.IdentityCallback = (result: mParticle.IdentityResult) => { + if (result.getUser()) { + // IDSync request succeeded, mutate attributes or query for the MPID as needed + const user = result.getUser(); + return; + } + if (result.getPreviousUser()) { + // IDSync request succeeded, mutate attributes or query for the MPID as needed + const user = result.getPreviousUser(); + return; + } + + const codes = mParticle.Identity.HTTPCodes; + switch (result.httpCode) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } +}; + +const logger: mParticle.Logger = { + error: (error: string) => { + console.log(error); + }, + warning: (error: string) => { + console.log(error); + }, + verbose: (error: string) => { + console.log(error); + }, +}; + +const onCreateBatch: mParticle.onCreateBatch = (batch: Batch) => { + return batch; +}; + +const config: mParticle.MPConfiguration = { + isDevelopmentMode: true, + identifyRequest, + identityCallback, + onCreateBatch, + dataPlan, + appVersion: "1.0.0", + appName: "testAppName", + package: "com.mparticle.example", + logLevel: "warning", + logger, + sessionTimeout: 500, + useCookieStorage: true, + maxCookieSize: 300, + cookieDomain: "mparticle.com", + customFlags: { + flag: "foo", + anotherFlag: "bar", + }, + sideloadedKits: [{}, {}], + v1SecureServiceUrl: "mp.mydomain.com/webevents/v1/JS/", + v2SecureServiceUrl: "mp.mydomain.com/webevents/v2/JS/", + v3SecureServiceUrl: "mp.mydomain.com/webevents/v3/JS/", + configUrl: "mp.mydomain.com/tags/JS/v2/", + identityUrl: "mp.mydomain.com/identity/v1/", + aliasUrl: "mp.mydomain.com/webevents/v1/identity/", +}; + +instance.endSession(); + +instance.getAppName(); + +instance.getAppVersion(); + +instance.getDeviceId(); + +instance.getEnvironment(); + +instance.getVersion(); + +instance.init("apiKey", config); +instance.init("apiKey", config, "instance"); + +instance.isInitialized(); + +instance.logBaseEvent({ + data: {}, + name: "baseEventName", + messageType: 1, + eventType: 1, +}); +instance.logBaseEvent( + { + data: {}, + name: "baseEventName", + messageType: 1, + eventType: 1, + }, + eventOptions, +); + +instance.logError("Login Failed", customAttrs); +instance.logError( + { + name: "error", + message: "errorMessage", + stack: "errorStack", + }, + customAttrs, +); + +instance.logEvent("eventName"); +instance.logEvent("eventName", instance.EventType.Location); +instance.logEvent("eventName", instance.EventType.Location, customAttrs); +instance.logEvent("eventName", instance.EventType.Location, customAttrs, customFlags); +instance.logEvent("eventName", mParticle.EventType.Location, customAttrs, customFlags, eventOptions); +instance.logEvent("eventName", mParticle.EventType.Location, customAttrs, customFlags, eventOptionsOnlyShouldUpload); +instance.logEvent("eventName", mParticle.EventType.Location, customAttrs, customFlags, eventOptionsOnlySourceMessageId); +instance.logEvent("eventName", mParticle.EventType.Location, customAttrs, customFlags, eventOptionsEmpty); + +instance.logForm("click", "eventName"); +instance.logForm("click", "eventName", instance.EventType.Location); +instance.logForm("click", "eventName", instance.EventType.Location, customAttrs); + +instance.logLink("click", "eventName"); +instance.logLink("click", "eventName", instance.EventType.Location); +instance.logLink("click", "eventName", instance.EventType.Location, customAttrs); + +instance.logPageView(); +instance.logPageView("pageName"); +instance.logPageView("pageName", customAttrs); +instance.logPageView("pageName", customAttrs, customFlags); +instance.logPageView("pageName", customAttrs, customFlags, eventOptions); + +instance.ready(() => { + console.log("hi"); +}); + +instance.reset(); + +instance.setAppName("appName"); + +instance.setAppVersion("1.0.0"); + +instance.setDeviceId("foo-uuid-v4"); + +instance.setIntegrationAttribute(123, { key: "value" }); + +instance.getIntegrationAttributes(123); + +instance.setLogLevel("verbose"); +instance.setLogLevel("none"); +instance.setLogLevel("warning"); + +instance.setOptOut(true); + +instance.setPosition(1, 2); + +instance.setSessionAttribute("key1", "value1"); +instance.setSessionAttribute("key2", 2); +instance.setSessionAttribute("key3", false); +instance.setSessionAttribute("key4", null); + +instance.startNewSession(); + +instance.startTrackingLocation(); +instance.startTrackingLocation((location: mParticle.Location) => { + console.log(location.coords.latitude); + console.log(location.coords.longitude); +}); + +instance.stopTrackingLocation(); + +instance.upload(); + +mParticle.sessionManager.getSession(); + +// CONSENT START +const user: mParticle.User = instance.Identity.getCurrentUser(); + +const ccpaConsent: mParticle.CCPAConsentState = instance.Consent.createCCPAConsent( + true, + new Date().getTime(), + "consentDocument", + "location", + "hardware", +)!; +const gdprConsent = instance.Consent.createGDPRConsent( + true, + new Date().getTime(), + "consentDocument", + "location", + "hardware", +)!; + +let consentState: mParticle.ConsentState = instance.Consent.createConsentState(); + +consentState.addGDPRConsentState("generalConsent", gdprConsent); +consentState.setCCPAConsentState(ccpaConsent); +user.setConsentState(consentState); + +const ccpaConsentState: mParticle.CCPAConsentState = consentState.getCCPAConsentState(); +user.setConsentState(consentState); + +// Remove consent state +consentState = user.getConsentState(); +const gdprConsentState: mParticle.GDPRConsentState = consentState.getGDPRConsentState(); + +const user2 = instance.Identity.getCurrentUser(); +user2.getConsentState().setGDPRConsentState(gdprConsentState); + +consentState.removeGDPRConsentState("generalConsent"); +consentState.removeCCPAConsentState(); +user.setConsentState(consentState); + +// CONSENT END + +// ECOMMERCE START + +const product1: mParticle.Product = instance.eCommerce.createProduct( + "product1", + "sku1", + 10, + 1, + "variant1", + "category1", + "brand1", + 1, + "coupon1", + { foo: "bar" }, +)!; +const product2: mParticle.Product = instance.eCommerce.createProduct("product2", "sku2", 20)!; +console.log("Product 1 Name", product1.Name); +console.log("Product 1 Sku", product1.Sku); +console.log("Product 1 Price", product1.Price); +console.log("Product 1 Quantity", product1.Quantity); +console.log("Product 1 Variant", product1.Variant); +console.log("Product 1 Category", product1.Category); +console.log("Product 1 Brand", product1.Brand); +console.log("Product 1 Position", product1.Position); +console.log("Product 1 Coupon", product1.Coupon); +console.log("Product 1 Attributes", product1.Attributes); + +const impression1: mParticle.Impression = instance.eCommerce.createImpression("name1", product1)!; +const impression2: mParticle.Impression = instance.eCommerce.createImpression("name2", product2)!; +const impression3: mParticle.Impression = instance.eCommerce.createImpression("name2", [product1, product2])!; +console.log("Impression 1 Name", impression1.Name); +console.log("Impression 1 Product", impression1.Product); + +const promotion1 = instance.eCommerce.createPromotion("id2")!; +const promotion2: mParticle.Promotion = instance.eCommerce.createPromotion("id1", "creative", "name", 1)!; +console.log("Promotion 1 ID", promotion1.Id); +console.log("Promotion 1 Creative", promotion1.Creative); +console.log("Promotion 1 Name", promotion1.Name); +console.log("Promotion 1 Position", promotion1.Position); + +const transactionAttributes1: mParticle.TransactionAttributes = instance.eCommerce.createTransactionAttributes("TAid1")!; +const transactionAttributes2: mParticle.TransactionAttributes = instance.eCommerce.createTransactionAttributes( + "TAid1", + "aff1", + "coupon", + 1798, + 10, + 5, +)!; + +const clearCartBoolean = true; +const eCommerceCustomAttributes = { value: 10 }; +const eCommerceCustomFlags = { CF1: "key" }; + +instance.eCommerce.logCheckout(1); +instance.eCommerce.logCheckout(1, "ok", eCommerceCustomAttributes, eCommerceCustomFlags); + +instance.eCommerce.logProductAction( + instance.ProductActionType.AddToCart, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.AddToWishlist, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.Checkout, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.CheckoutOption, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.Click, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.Purchase, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, + transactionAttributes1, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.Refund, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.RemoveFromCart, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.RemoveFromWishlist, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.Unknown, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logProductAction( + instance.ProductActionType.ViewDetail, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); + +instance.eCommerce.logProductAction(0, [product1, product2], eCommerceCustomAttributes, eCommerceCustomFlags); + +instance.eCommerce.logProductAction( + 0, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, + transactionAttributes1, + eventOptions, +); + +instance.eCommerce.logPurchase( + transactionAttributes1, + [product1, product2], + clearCartBoolean, + eCommerceCustomAttributes, + eCommerceCustomFlags, +); + +instance.eCommerce.logPromotion(instance.PromotionType.PromotionClick, promotion1); + +instance.eCommerce.logPromotion(instance.PromotionType.PromotionClick, [promotion1, promotion2]); + +instance.eCommerce.logPromotion( + instance.PromotionType.PromotionView, + promotion1, + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logPromotion( + instance.PromotionType.Unknown, + promotion1, + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +instance.eCommerce.logPromotion( + instance.PromotionType.Unknown, + promotion1, + eCommerceCustomAttributes, + eCommerceCustomFlags, + eventOptions, +); + +instance.eCommerce.logImpression(impression1); +instance.eCommerce.logImpression([impression1, impression2]); +instance.eCommerce.logImpression(impression1, eCommerceCustomAttributes, eCommerceCustomFlags, eventOptions); + +instance.eCommerce.logRefund( + transactionAttributes1, + [product1, product2], + clearCartBoolean, + eCommerceCustomAttributes, + eCommerceCustomFlags, +); + +instance.eCommerce.setCurrencyCode("usd"); +// ECOMMERCE END + +// Identity Start +const identifyIdentities: mParticle.IdentifyRequest = { + userIdentities: { + customerid: "customerid", + email: "email", + other: "email", + other2: "email", + other3: "email", + other4: "email", + other5: "email", + other6: "email", + other7: "email", + other8: "email", + other9: "email", + other10: "email", + mobile_number: "email", + phone_number_2: "email", + phone_number_3: "email", + facebook: "email", + facebookcustomaudienceid: "email", + google: "email", + twitter: "email", + microsoft: "email", + yahoo: "email", + email_sha256: "email", + mobile_sha256: "email", + }, +}; + +instance.Identity.login(identifyIdentities, (result: mParticle.IdentityResult) => { + const body = result.body as mParticle.IdentityResultBody; + console.log(body.is_ephemeral); + console.log(body.is_logged_in); + console.log(body.matched_identities); + const code = result.httpCode; + const codes = mParticle.Identity.HTTPCodes; + + switch (code) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } + result.getUser().getConsentState(); + + // alias users + const userAliasObject: mParticle.UserAliasRequest = { + destinationMpid: result.getPreviousUser().getMPID(), + sourceMpid: result.getUser().getMPID(), + startTime: new Date().getTime(), + endTime: new Date().getTime(), + }; + + instance.Identity.aliasUsers(userAliasObject, (aliasResult: { httpCode: number; message: string }) => { + const httpCode: number = aliasResult.httpCode; + const message: string = aliasResult.message; + }); + + const aliasRequest: mParticle.UserAliasRequest = instance.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + ); + + result.getPreviousUser().getAllUserAttributes(); + const consentState: mParticle.ConsentState = result.getUser().getConsentState(); +}); + +instance.Identity.logout(identifyIdentities, (result: mParticle.IdentityResult) => { + const body = result.body as mParticle.IdentityResultBody; + console.log(body.is_ephemeral); + console.log(body.is_logged_in); + console.log(body.matched_identities); + const code = result.httpCode; + const codes = mParticle.Identity.HTTPCodes; + + switch (code) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } + result.getUser().getConsentState(); + + // alias users + const userAliasObject: mParticle.UserAliasRequest = { + destinationMpid: result.getPreviousUser().getMPID(), + sourceMpid: result.getUser().getMPID(), + startTime: new Date().getTime(), + endTime: new Date().getTime(), + }; + + instance.Identity.aliasUsers(userAliasObject, (aliasResult: { httpCode: number; message: string }) => { + const httpCode: number = aliasResult.httpCode; + const message: string = aliasResult.message; + }); + + const aliasRequest: mParticle.UserAliasRequest = instance.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + ); + + result.getPreviousUser().getAllUserAttributes(); + const consentState: mParticle.ConsentState = result.getUser().getConsentState(); +}); + +// Logout Identity API Data can be an empty object with no callback +instance.Identity.logout({}); +instance.Identity.logout(null); +instance.Identity.logout(undefined); +instance.Identity.logout(); + +instance.Identity.identify(identifyIdentities, (result: mParticle.IdentityResult) => { + const body = result.body as mParticle.IdentityResultBody; + console.log(body.is_ephemeral); + console.log(body.is_logged_in); + console.log(body.matched_identities); + const code = result.httpCode; + const codes = mParticle.Identity.HTTPCodes; + + switch (code) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } + result.getUser().getConsentState(); + + // alias users + const userAliasObject: mParticle.UserAliasRequest = { + destinationMpid: result.getPreviousUser().getMPID(), + sourceMpid: result.getUser().getMPID(), + startTime: new Date().getTime(), + endTime: new Date().getTime(), + scope: "mpid", + }; + + instance.Identity.aliasUsers(userAliasObject, (aliasResult: { httpCode: number; message: string }) => { + const httpCode: number = aliasResult.httpCode; + const message: string = aliasResult.message; + }); + + const aliasRequest: mParticle.UserAliasRequest = instance.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + ); + + result.getPreviousUser().getAllUserAttributes(); + const consentState: mParticle.ConsentState = result.getUser().getConsentState(); +}); + +instance.Identity.modify(identifyIdentities, (result: mParticle.IdentityResult) => { + const body = result.body as mParticle.IdentityResultBody; + console.log(body.context); + console.log(body.is_ephemeral); + console.log(body.is_logged_in); + console.log(body.matched_identities); + const code = result.httpCode; + const codes = mParticle.Identity.HTTPCodes; + + switch (code) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } + result.getUser().getConsentState(); + + // alias users + const userAliasObject: mParticle.UserAliasRequest = { + destinationMpid: result.getPreviousUser().getMPID(), + sourceMpid: result.getUser().getMPID(), + startTime: new Date().getTime(), + endTime: new Date().getTime(), + }; + + instance.Identity.aliasUsers(userAliasObject, (aliasResult: { httpCode: number; message: string }) => { + const httpCode: number = aliasResult.httpCode; + const message: string = aliasResult.message; + }); + + const aliasRequest: mParticle.UserAliasRequest = instance.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + ); + + result.getPreviousUser().getAllUserAttributes(); + const consentState: mParticle.ConsentState = result.getUser().getConsentState(); +}); + +const user3: mParticle.User = instance.Identity.getCurrentUser(); +const user4: mParticle.User = instance.Identity.getUser("mpid" as mParticle.MPID); + +const identities: mParticle.IdentifyRequest = mParticle.Identity.getCurrentUser().getUserIdentities(); +const { email, customerid, facebook, other } = identities.userIdentities; +const mpid: mParticle.MPID = instance.Identity.getCurrentUser().getMPID(); +const user5: mParticle.User = instance.Identity.getCurrentUser(); +user5.setUserTag("tag"); +user5.removeUserTag("tag"); +user5.setUserAttribute("attr", "value"); +user5.setUserAttributes({ + attr: "value", + foo: "bar", +}); +user5.removeUserAttribute("attr"); +user5.setUserAttributeList("hi", ["hello"]); +user5.removeAllUserAttributes(); +const userAttributesList: mParticle.AllUserAttributes = user5.getUserAttributesLists(); +const userAttributes = user5.getAllUserAttributes(); +const abc = "abc"; + +if (Array.isArray(userAttributes["hi"])) { + userAttributes["hi"].push("ok"); +} else if (typeof userAttributes["hi"] === "number") { + userAttributes["hi"] += 1; +} else if (typeof userAttributes["hi"] === "string") { + userAttributes["hi"].slice(); +} + +const consent: mParticle.ConsentState = user5.getConsentState(); +user5.setConsentState(consent); +const isLoggedIn: boolean = user5.isLoggedIn(); +const lastSeenTime: number = user5.getLastSeenTime(); +const firstSeenTime: number = user5.getFirstSeenTime(); + +user5.getCart().add(product1, true); +user5.getCart().remove(product1, true); +user5.getCart().clear(); + +mParticle.Rokt.selectPlacements({ + attributes: { + "foo": "bar", + "fizz": "buzz", + }, +}).then((selection: mParticle.RoktSelection) => { + // Test event subscription patterns + selection.on("PLACEMENT_INTERACTIVE").subscribe(() => { + console.log("Placement interaction"); + }); + + selection.on("PLACEMENT_COMPLETED").subscribe((event: mParticle.RoktPlacementEvent) => { + console.log("Placement completed", event); + console.log("Event details:", event.body, event.event, event.placement); + }); + + // Test unsubscription + const unsubscriber = selection.on("PLACEMENT_READY").subscribe((event: mParticle.RoktPlacementEvent) => { + console.log("Placement ready:", event.placement.id); + }); + unsubscriber.unsubscribe(); + + // Test selection methods + selection.ready().then(() => { + console.log("Selection is ready"); + }); + + selection.send("custom_event", { data: "test" }); + + selection.setAttributes({ + "dynamic_attr": "updated_value", + "user_segment": "premium", + }); + + // Test getting individual placements + selection.getPlacements().then((placements: mParticle.RoktPlacement[]) => { + placements.forEach((placement: mParticle.RoktPlacement) => { + console.log("Placement ID:", placement.id); + console.log("Placement element:", placement.element); + + // Test placement-specific events + placement.on("PLACEMENT_RENDERED").subscribe((event: mParticle.RoktPlacementEvent) => { + console.log("Placement rendered:", event); + }); + + // Test placement methods + placement.ready().then(() => { + console.log(`Placement ${placement.id} is ready`); + }); + + placement.send("placement_event", { custom: "data" }); + + // Test placement close events + placement.onClose().then(() => { + console.log(`Placement ${placement.id} was closed`); + }); + + // Test manual close + placement.close().then(() => { + console.log(`Placement ${placement.id} closed programmatically`); + }); + }); + }); + + // Test selection close + selection.close(); +}); + +// Test other Rokt methods +mParticle.Rokt.hashAttributes({ + email: "user@example.com", + userId: "12345", + segment: "premium", +}).then((hashedAttrs: mParticle.RoktAttributes) => { + console.log("Hashed attributes:", hashedAttrs); +}); + +mParticle.Rokt.setExtensionData({ + "analytics": { sessionId: "abc123" }, + "personalization": { variant: "A" }, +}); + +mParticle.Rokt.onShoppableAdsReady(() => { + console.log("Shoppable ads ready"); +}); + +// Test with identifier +mParticle.Rokt.selectPlacements({ + attributes: { + "placement_type": "checkout", + "cart_value": 150.00, + }, + identifier: "checkout-flow-2024", +}).then((selection: mParticle.RoktSelection) => { + console.log("Selection with identifier created", selection); +}); diff --git a/test/types/definitely-typed/manager.ts b/test/types/definitely-typed/manager.ts new file mode 100644 index 000000000..9f1bd693e --- /dev/null +++ b/test/types/definitely-typed/manager.ts @@ -0,0 +1,885 @@ +/** + * Legacy DefinitelyTyped compatibility compile test. + * + * This file is based on the old @types/mparticle__web-sdk tests. It + * keeps the old mParticle namespace-style type references while importing the + * SDK through this package's default runtime export. + */ + +import { Batch } from "@mparticle/event-models"; +import mParticle from "@mparticle/web-sdk"; +import type * as MParticleTypes from "@mparticle/web-sdk"; + +declare namespace mParticle { + export type AllUserAttributes = MParticleTypes.AllUserAttributes; + export type CCPAConsentState = MParticleTypes.CCPAConsentState; + export type ConsentState = MParticleTypes.ConsentState; + export type DataPlanConfig = MParticleTypes.DataPlanConfig; + export type GDPRConsentState = MParticleTypes.GDPRConsentState; + export type IdentifyRequest = MParticleTypes.IdentifyRequest; + export type IdentityCallback = MParticleTypes.IdentityCallback; + export type IdentityResult = MParticleTypes.IdentityResult; + export type IdentityResultBody = MParticleTypes.IdentityResultBody; + export type Impression = MParticleTypes.Impression; + export type KitFilterSettings = MParticleTypes.KitFilterSettings; + export type Location = MParticleTypes.Location; + export type Logger = MParticleTypes.Logger; + export type MPConfiguration = MParticleTypes.MPConfiguration; + export type MPForwarder = MParticleTypes.MPForwarder; + export type MPID = MParticleTypes.MPID; + export type MPSideloadedKit = MParticleTypes.MPSideloadedKit; + export type Product = MParticleTypes.Product; + export type Promotion = MParticleTypes.Promotion; + export type RoktAttributes = MParticleTypes.RoktAttributes; + export type RoktPlacement = MParticleTypes.RoktPlacement; + export type RoktPlacementEvent = + MParticleTypes.RoktPlacementEvent; + export type RoktSelection = MParticleTypes.RoktSelection; + export type SDKEventAttrs = MParticleTypes.SDKEventAttrs; + export type SDKEventCustomFlags = MParticleTypes.SDKEventCustomFlags; + export type SDKEventOptions = MParticleTypes.SDKEventOptions; + export type TransactionAttributes = MParticleTypes.TransactionAttributes; + export type User = MParticleTypes.User; + export type UserAliasRequest = MParticleTypes.UserAliasRequest; + export type onCreateBatch = MParticleTypes.onCreateBatch; +} + +const dataPlan: mParticle.DataPlanConfig = { + planId: "test", + planVersion: 2, +}; + +const customAttrs: mParticle.SDKEventAttrs = { + attr1: "hi", + attr2: 2, + attr3: null, + attr4: undefined, + attr5: true, +}; + +const customFlags: mParticle.SDKEventCustomFlags = { + attr1: "hi", + attr2: 2, + attr3: true, + attr4: [{ foo: "2" }], + attr5: { foo: "bar" }, +}; + +const eventOptions: mParticle.SDKEventOptions = { + shouldUploadEvent: false, + sourceMessageId: "sourceMessageId", +}; + +const eventOptionsOnlyShouldUpload: mParticle.SDKEventOptions = { + shouldUploadEvent: true, +}; + +const eventOptionsOnlySourceMessageId: mParticle.SDKEventOptions = { + sourceMessageId: "test-message-id", +}; + +const eventOptionsEmpty: mParticle.SDKEventOptions = {}; + +const identifyRequest: mParticle.IdentifyRequest = { + userIdentities: { + customerid: "test", + email: "test", + other: "test", + other2: "test", + other3: "test", + other4: "test", + other5: "test", + other6: "test", + other7: "test", + other8: "test", + other9: "test", + other10: "test", + mobile_number: "test", + phone_number_2: "test", + phone_number_3: "test", + facebook: "test", + facebookcustomaudienceid: "test", + google: "test", + twitter: "test", + microsoft: null, + yahoo: null, + }, +}; + +const identityCallback: mParticle.IdentityCallback = (result: mParticle.IdentityResult) => { + if (result.getUser()) { + // IDSync request succeeded, mutate attributes or query for the MPID as needed + const user = result.getUser(); + return; + } + if (result.getPreviousUser()) { + // IDSync request succeeded, mutate attributes or query for the MPID as needed + const user = result.getPreviousUser(); + return; + } + + const codes = mParticle.Identity.HTTPCodes; + switch (result.httpCode) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } +}; + +const logger: mParticle.Logger = { + error: (error: string) => { + console.log(error); + }, + warning: (error: string) => { + console.log(error); + }, + verbose: (error: string) => { + console.log(error); + }, +}; + +const onCreateBatch: mParticle.onCreateBatch = (batch: Batch) => { + return batch; +}; + +const config: mParticle.MPConfiguration = { + isDevelopmentMode: true, + identifyRequest, + identityCallback, + dataPlan, + onCreateBatch, + appVersion: "1.0.0", + appName: "testAppName", + package: "com.mparticle.example", + logLevel: "warning", + logger, + sessionTimeout: 500, + useCookieStorage: true, + maxCookieSize: 300, + cookieDomain: "mparticle.com", + customFlags: { + flag: "foo", + anotherFlag: "bar", + }, + sideloadedKits: [{}, {}], + v1SecureServiceUrl: "mp.mydomain.com/webevents/v1/JS/", + v2SecureServiceUrl: "mp.mydomain.com/webevents/v2/JS/", + v3SecureServiceUrl: "mp.mydomain.com/webevents/v3/JS/", + configUrl: "mp.mydomain.com/tags/JS/v2/", + identityUrl: "mp.mydomain.com/identity/v1/", + aliasUrl: "mp.mydomain.com/webevents/v1/identity/", + launcherOptions: { + noTargeting: true, + noFunctional: true, + }, +}; + +mParticle.endSession(); + +mParticle.getAppName(); + +mParticle.getAppVersion(); + +mParticle.getDeviceId(); + +mParticle.getEnvironment(); + +const instance = mParticle.getInstance(); + +mParticle.getVersion(); + +mParticle.init("apiKey", config); +mParticle.init("apiKey", config, "instance"); + +mParticle.isInitialized(); + +mParticle.logBaseEvent({ + data: {}, + name: "baseEventName", + messageType: 1, + eventType: 1, +}); +mParticle.logBaseEvent( + { + data: {}, + name: "baseEventName", + messageType: 1, + eventType: 1, + }, + eventOptions, +); + +// MPSideloadedKit +const mockKitInstance = { + name: "MockKit", + register: () => {}, + constructor: () => {}, +}; + +const sideloadedKit: mParticle.MPSideloadedKit = new mParticle.MPSideloadedKit(mockKitInstance); +sideloadedKit.addEventTypeFilter(mParticle.EventType.Navigation); +sideloadedKit.addEventNameFilter(mParticle.EventType.Navigation, "PageView"); +sideloadedKit.addEventAttributeFilter(mParticle.EventType.Navigation, "PageView", "attributeKey"); +sideloadedKit.addScreenNameFilter("HomePage"); +sideloadedKit.addScreenAttributeFilter("HomePage", "screenAttribute"); +sideloadedKit.addUserIdentityFilter(mParticle.IdentityType.Email); +sideloadedKit.addUserAttributeFilter("userAttributeKey"); +const kitInstance: mParticle.MPForwarder = sideloadedKit.kitInstance; +const filterDictionary: mParticle.KitFilterSettings = sideloadedKit.filterDictionary; + +mParticle.logError("Login Failed", customAttrs); +mParticle.logError( + { + name: "error", + message: "errorMessage", + stack: "errorStack", + }, + customAttrs, +); + +mParticle.logEvent("eventName"); +mParticle.logEvent("eventName", mParticle.EventType.Location); +mParticle.logEvent("eventName", mParticle.EventType.Location, customAttrs); +mParticle.logEvent("eventName", mParticle.EventType.Location, customAttrs, customFlags); +mParticle.logEvent("eventName", mParticle.EventType.Location, customAttrs, customFlags, eventOptions); +mParticle.logEvent("eventName", mParticle.EventType.Location, customAttrs, customFlags, eventOptionsOnlyShouldUpload); +mParticle.logEvent( + "eventName", + mParticle.EventType.Location, + customAttrs, + customFlags, + eventOptionsOnlySourceMessageId, +); +mParticle.logEvent("eventName", mParticle.EventType.Location, customAttrs, customFlags, eventOptionsEmpty); + +mParticle.logForm("click", "eventName"); +mParticle.logForm("click", "eventName", mParticle.EventType.Location); +mParticle.logForm("click", "eventName", mParticle.EventType.Location, customAttrs); + +mParticle.logLink("click", "eventName"); +mParticle.logLink("click", "eventName", mParticle.EventType.Location); +mParticle.logLink("click", "eventName", mParticle.EventType.Location, customAttrs); + +mParticle.logPageView(); +mParticle.logPageView("pageName"); +mParticle.logPageView("pageName", customAttrs); +mParticle.logPageView("pageName", customAttrs, customFlags); +mParticle.logPageView("pageName", customAttrs, customFlags, eventOptions); + +mParticle.Rokt.selectPlacements({ + identifier: "mp-test-identifier", + attributes: { + email: "test@test.com", + price: 100, + taxes: 6.75, + excessbaggage: true, + products: ["product1", "product2"], + cartItems: ["item 1", "item 2", "item 3"], + }, +}); + +mParticle.Rokt.hashAttributes({ + email: "test@test.com", +}); + +mParticle.Rokt.setExtensionData({ + "test-extension": { + "test-key": "test-value", + }, +}); + +mParticle.Rokt.use("test-extension-name"); + +mParticle.Rokt.hashSha256("test@test.com"); +mParticle.Rokt.hashSha256(12345); +mParticle.Rokt.hashSha256(true); +mParticle.Rokt.hashSha256(undefined); +mParticle.Rokt.hashSha256(null); + +mParticle.Rokt.onShoppableAdsReady(() => { + // shoppable ads ready +}); + +mParticle.generateHash("test-string"); + +mParticle.ready(() => { + console.log("hi"); +}); + +mParticle.reset(); + +mParticle.setAppName("appName"); + +mParticle.setAppVersion("1.0.0"); + +mParticle.setDeviceId("foo-uuid-v4"); + +mParticle.setIntegrationAttribute(123, { key: "value" }); + +mParticle.getIntegrationAttributes(123); + +mParticle.setLogLevel("verbose"); +mParticle.setLogLevel("none"); +mParticle.setLogLevel("warning"); + +mParticle.setOptOut(true); + +mParticle.setPosition(1, 2); + +mParticle.setSessionAttribute("key1", "value1"); +mParticle.setSessionAttribute("key2", 2); +mParticle.setSessionAttribute("key3", false); +mParticle.setSessionAttribute("key4", null); + +mParticle.startNewSession(); + +mParticle.startTrackingLocation(); +mParticle.startTrackingLocation((location: mParticle.Location) => { + console.log(location.coords.latitude); + console.log(location.coords.longitude); +}); + +mParticle.stopTrackingLocation(); + +mParticle.upload(); + +mParticle.sessionManager.getSession(); + +// CONSENT START +const user: mParticle.User = mParticle.Identity.getCurrentUser(); + +const ccpaConsent: mParticle.CCPAConsentState = mParticle.Consent.createCCPAConsent( + true, + new Date().getTime(), + "consentDocument", + "location", + "hardware", +)!; +const gdprConsent = mParticle.Consent.createGDPRConsent( + true, + new Date().getTime(), + "consentDocument", + "location", + "hardware", +)!; + +let consentState: mParticle.ConsentState = mParticle.Consent.createConsentState(); + +consentState.addGDPRConsentState("generalConsent", gdprConsent); +consentState.setCCPAConsentState(ccpaConsent); +user.setConsentState(consentState); + +const ccpaConsentState: mParticle.CCPAConsentState = consentState.getCCPAConsentState(); +user.setConsentState(consentState); + +// Remove consent state +consentState = user.getConsentState(); +const gdprConsentState: mParticle.GDPRConsentState = consentState.getGDPRConsentState(); + +const user2 = mParticle.Identity.getCurrentUser(); +user2.getConsentState().setGDPRConsentState(gdprConsentState); + +consentState.removeGDPRConsentState("generalConsent"); +consentState.removeCCPAConsentState(); +user.setConsentState(consentState); + +// CONSENT END + +// ECOMMERCE START + +const product1: mParticle.Product = mParticle.eCommerce.createProduct( + "product1", + "sku1", + 10, + 1, + "variant1", + "category1", + "brand1", + 1, + "coupon1", + { foo: "bar" }, +)!; +const product2: mParticle.Product = mParticle.eCommerce.createProduct("product2", "sku2", 20)!; +console.log("Product 1 Name", product1.Name); +console.log("Product 1 Sku", product1.Sku); +console.log("Product 1 Price", product1.Price); +console.log("Product 1 Quantity", product1.Quantity); +console.log("Product 1 Variant", product1.Variant); +console.log("Product 1 Category", product1.Category); +console.log("Product 1 Brand", product1.Brand); +console.log("Product 1 Position", product1.Position); +console.log("Product 1 Coupon", product1.Coupon); +console.log("Product 1 Attributes", product1.Attributes); + +const impression1: mParticle.Impression = mParticle.eCommerce.createImpression("name1", product1)!; +const impression2: mParticle.Impression = mParticle.eCommerce.createImpression("name2", product2)!; +const impression3: mParticle.Impression = mParticle.eCommerce.createImpression("name2", [product1, product2])!; +console.log("Impression 1 Name", impression1.Name); +console.log("Impression 1 Product", impression1.Product); + +const promotion1 = mParticle.eCommerce.createPromotion("id2")!; +const promotion2: mParticle.Promotion = mParticle.eCommerce.createPromotion("id1", "creative", "name", 1)!; +console.log("Promotion 1 ID", promotion1.Id); +console.log("Promotion 1 Creative", promotion1.Creative); +console.log("Promotion 1 Name", promotion1.Name); +console.log("Promotion 1 Position", promotion1.Position); + +const transactionAttributes1: mParticle.TransactionAttributes = mParticle.eCommerce.createTransactionAttributes( + "TAid1", +)!; +const transactionAttributes2: mParticle.TransactionAttributes = mParticle.eCommerce.createTransactionAttributes( + "TAid1", + "aff1", + "coupon", + 1798, + 10, + 5, +)!; + +const clearCartBoolean = true; +const eCommerceCustomAttributes = { value: 10 }; +const eCommerceCustomFlags = { CF1: "key" }; + +mParticle.eCommerce.logCheckout(1); +mParticle.eCommerce.logCheckout(1, "ok", eCommerceCustomAttributes, eCommerceCustomFlags); + +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.AddToCart, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.AddToWishlist, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Checkout, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.CheckoutOption, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Click, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, + transactionAttributes1, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Refund, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.RemoveFromCart, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.RemoveFromWishlist, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Unknown, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.ViewDetail, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, +); + +mParticle.eCommerce.logProductAction(0, [product1, product2], eCommerceCustomAttributes, eCommerceCustomFlags); + +mParticle.eCommerce.logProductAction( + 0, + [product1, product2], + eCommerceCustomAttributes, + eCommerceCustomFlags, + transactionAttributes1, + eventOptions, +); + +mParticle.eCommerce.logPurchase( + transactionAttributes1, + [product1, product2], + clearCartBoolean, + eCommerceCustomAttributes, + eCommerceCustomFlags, +); + +mParticle.eCommerce.logPromotion(mParticle.PromotionType.PromotionClick, promotion1); + +mParticle.eCommerce.logPromotion(mParticle.PromotionType.PromotionClick, [promotion1, promotion2]); + +mParticle.eCommerce.logPromotion( + mParticle.PromotionType.PromotionView, + promotion1, + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logPromotion( + mParticle.PromotionType.Unknown, + promotion1, + eCommerceCustomAttributes, + eCommerceCustomFlags, +); +mParticle.eCommerce.logPromotion( + mParticle.PromotionType.Unknown, + promotion1, + eCommerceCustomAttributes, + eCommerceCustomFlags, + eventOptions, +); + +mParticle.eCommerce.logImpression(impression1); +mParticle.eCommerce.logImpression([impression1, impression2]); +mParticle.eCommerce.logImpression(impression1, eCommerceCustomAttributes, eCommerceCustomFlags, eventOptions); + +mParticle.eCommerce.logRefund( + transactionAttributes1, + [product1, product2], + clearCartBoolean, + eCommerceCustomAttributes, + eCommerceCustomFlags, +); + +mParticle.eCommerce.setCurrencyCode("usd"); +// ECOMMERCE END + +// Identity Start +const identifyIdentities: mParticle.IdentifyRequest = { + userIdentities: { + customerid: "customerid", + email: "email", + other: "email", + other2: "email", + other3: "email", + other4: "email", + other5: "email", + other6: "email", + other7: "email", + other8: "email", + other9: "email", + other10: "email", + mobile_number: "email", + phone_number_2: "email", + phone_number_3: "email", + facebook: "email", + facebookcustomaudienceid: "email", + google: "email", + twitter: "email", + microsoft: "email", + yahoo: "email", + email_sha256: "email", + mobile_sha256: "email", + }, +}; + +mParticle.Identity.login(identifyIdentities, (result: mParticle.IdentityResult) => { + const body = result.body as mParticle.IdentityResultBody; + console.log(body.is_ephemeral); + console.log(body.is_logged_in); + console.log(body.matched_identities); + const code = result.httpCode; + const codes = mParticle.Identity.HTTPCodes; + + switch (code) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } + result.getUser().getConsentState(); + + // alias users + const userAliasObject: mParticle.UserAliasRequest = { + destinationMpid: result.getPreviousUser().getMPID(), + sourceMpid: result.getUser().getMPID(), + startTime: new Date().getTime(), + endTime: new Date().getTime(), + }; + + mParticle.Identity.aliasUsers(userAliasObject, (aliasResult: { httpCode: number; message: string }) => { + const httpCode: number = aliasResult.httpCode; + const message: string = aliasResult.message; + }); + + const aliasRequest: mParticle.UserAliasRequest = mParticle.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + ); + + // createAliasRequest with scope parameter + const aliasRequestWithScope: mParticle.UserAliasRequest = mParticle.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + "device", + ); + + const aliasRequestWithMpidScope: mParticle.UserAliasRequest = mParticle.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + "mpid", + ); + + // UserAliasRequest with scope + const userAliasWithScope: mParticle.UserAliasRequest = { + destinationMpid: result.getPreviousUser().getMPID(), + sourceMpid: result.getUser().getMPID(), + startTime: new Date().getTime(), + endTime: new Date().getTime(), + scope: "device", + }; + + result.getPreviousUser().getAllUserAttributes(); + const consentState: mParticle.ConsentState = result.getUser().getConsentState(); + + // getUserAudiences + const currentUser = result.getUser(); + if (currentUser.getUserAudiences) { + currentUser.getUserAudiences(); + currentUser.getUserAudiences((audienceResult: mParticle.IdentityResult) => { + console.log(audienceResult); + }); + } +}); + +mParticle.Identity.logout(identifyIdentities, (result: mParticle.IdentityResult) => { + const body = result.body as mParticle.IdentityResultBody; + console.log(body.is_ephemeral); + console.log(body.is_logged_in); + console.log(body.matched_identities); + const code = result.httpCode; + const codes = mParticle.Identity.HTTPCodes; + + switch (code) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } + result.getUser().getConsentState(); + + // alias users + const userAliasObject: mParticle.UserAliasRequest = { + destinationMpid: result.getPreviousUser().getMPID(), + sourceMpid: result.getUser().getMPID(), + startTime: new Date().getTime(), + endTime: new Date().getTime(), + }; + + mParticle.Identity.aliasUsers(userAliasObject, (aliasResult: { httpCode: number; message: string }) => { + const httpCode: number = aliasResult.httpCode; + const message: string = aliasResult.message; + }); + + const aliasRequest: mParticle.UserAliasRequest = mParticle.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + ); + + result.getPreviousUser().getAllUserAttributes(); + const consentState: mParticle.ConsentState = result.getUser().getConsentState(); +}); + +// Logout Identity API Data can be an empty object with no callback +mParticle.Identity.logout({}); +mParticle.Identity.logout(null); +mParticle.Identity.logout(undefined); +mParticle.Identity.logout(); + +mParticle.Identity.identify(identifyIdentities, (result: mParticle.IdentityResult) => { + const body = result.body as mParticle.IdentityResultBody; + console.log(body.is_ephemeral); + console.log(body.is_logged_in); + console.log(body.matched_identities); + const code = result.httpCode; + const codes = mParticle.Identity.HTTPCodes; + + switch (code) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } + result.getUser().getConsentState(); + + // alias users + const userAliasObject: mParticle.UserAliasRequest = { + destinationMpid: result.getPreviousUser().getMPID(), + sourceMpid: result.getUser().getMPID(), + startTime: new Date().getTime(), + endTime: new Date().getTime(), + scope: "mpid", + }; + + mParticle.Identity.aliasUsers(userAliasObject, (aliasResult: { httpCode: number; message: string }) => { + const httpCode: number = aliasResult.httpCode; + const message: string = aliasResult.message; + }); + + const aliasRequest: mParticle.UserAliasRequest = mParticle.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + ); + + result.getPreviousUser().getAllUserAttributes(); + const consentState: mParticle.ConsentState = result.getUser().getConsentState(); +}); + +mParticle.Identity.modify(identifyIdentities, (result: mParticle.IdentityResult) => { + const body = result.body as mParticle.IdentityResultBody; + console.log(body.context); + console.log(body.is_ephemeral); + console.log(body.is_logged_in); + console.log(body.matched_identities); + const code = result.httpCode; + const codes = mParticle.Identity.HTTPCodes; + + switch (code) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case codes.activeSession: + case codes.nativeIdentityRequest: + case codes.loggingDisabledOrMissingAPIKey: + case 400: + case 200: + console.log(result.body); + break; + default: + console.log(result.body); + } + result.getUser().getConsentState(); + + // alias users + const userAliasObject: mParticle.UserAliasRequest = { + destinationMpid: result.getPreviousUser().getMPID(), + sourceMpid: result.getUser().getMPID(), + startTime: new Date().getTime(), + endTime: new Date().getTime(), + }; + + mParticle.Identity.aliasUsers(userAliasObject, (aliasResult: { httpCode: number; message: string }) => { + const httpCode: number = aliasResult.httpCode; + const message: string = aliasResult.message; + }); + + const aliasRequest: mParticle.UserAliasRequest = mParticle.Identity.createAliasRequest( + result.getPreviousUser(), + result.getUser(), + ); + + result.getPreviousUser().getAllUserAttributes(); + const consentState: mParticle.ConsentState = result.getUser().getConsentState(); +}); + +const user3: mParticle.User = mParticle.Identity.getCurrentUser(); +const user4: mParticle.User = mParticle.Identity.getUser("mpid" as mParticle.MPID); + +const identities: mParticle.IdentifyRequest = mParticle.Identity.getCurrentUser().getUserIdentities(); +const { email, customerid, facebook, other } = identities.userIdentities; +const mpid: mParticle.MPID = mParticle.Identity.getCurrentUser().getMPID(); +const user5: mParticle.User = mParticle.Identity.getCurrentUser(); +user5.setUserTag("tag"); +user5.removeUserTag("tag"); +user5.setUserAttribute("attr", "value"); +user5.setUserAttributes({ + attr: "value", + foo: "bar", +}); +user5.removeUserAttribute("attr"); +user5.setUserAttributeList("hi", ["hello"]); +user5.removeAllUserAttributes(); +const userAttributesList: mParticle.AllUserAttributes = user5.getUserAttributesLists(); +const userAttributes = user5.getAllUserAttributes(); +const abc = "abc"; + +if (Array.isArray(userAttributes["hi"])) { + userAttributes["hi"].push("ok"); +} else if (typeof userAttributes["hi"] === "number") { + userAttributes["hi"] += 1; +} else if (typeof userAttributes["hi"] === "string") { + userAttributes["hi"].slice(); +} + +const consent: mParticle.ConsentState = user5.getConsentState(); +user5.setConsentState(consent); +const isLoggedIn: boolean = user5.isLoggedIn(); +const lastSeenTime: number = user5.getLastSeenTime(); +const firstSeenTime: number = user5.getFirstSeenTime(); + +user5.getCart().add(product1, true); +user5.getCart().remove(product1, true); +user5.getCart().clear(); diff --git a/test/types/definitely-typed/tsconfig.json b/test/types/definitely-typed/tsconfig.json new file mode 100644 index 000000000..d1f0ce895 --- /dev/null +++ b/test/types/definitely-typed/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "baseUrl": "../../..", + "esModuleInterop": true, + "lib": ["es5", "es6", "dom"], + "module": "esnext", + "moduleResolution": "node", + "noEmit": true, + "skipLibCheck": false, + "strict": true, + "target": "es5", + "types": [], + "paths": { + "@mparticle/web-sdk": ["dist/types/src/public-types.d.ts"] + } + }, + "files": ["manager.ts", "instance.ts"] +} diff --git a/test/types/internal-consumer.ts b/test/types/internal-consumer.ts new file mode 100644 index 000000000..98f9bc7cc --- /dev/null +++ b/test/types/internal-consumer.ts @@ -0,0 +1,78 @@ +/** + * Package contract smoke test for the internal `@mparticle/web-sdk/internal` + * entry point. + * + * This file is compiled against generated declarations in `dist/types`, not + * source files, so it catches publish-shape regressions for kits and other + * mParticle-owned integrations. The internal entry point should expose kit + * implementation contracts and re-export public types for one-path internal + * consumption. + */ + +import type { + Batch, + ConfiguredKit, + IKitFilterSettings, + IRoktKit, + KitInterface, + SDKInitConfig, + SDKEvent, + UserIdentities, +} from '@mparticle/web-sdk/internal'; + +const filters: IKitFilterSettings = { + attributeFilters: [], + consentRegulationFilters: [], + consentRegulationPurposeFilters: [], + eventNameFilters: [], + eventTypeFilters: [], + messageTypeFilters: [], + messageTypeStateFilters: [], + screenAttributeFilters: [], + screenNameFilters: [], + userAttributeFilters: [], + userIdentityFilters: [], +}; + +const kit: KitInterface = { + id: 123, + name: 'Type Test Kit', + init(settings, service, testMode, trackerId, userAttributes) { + void settings; + void service; + void testMode; + void trackerId; + void userAttributes; + return 'initialized'; + }, + process(event: SDKEvent) { + return event.EventName; + }, + processBatch(batch: Batch) { + return String(batch.events?.length ?? 0); + }, + setUserIdentity(id, type) { + void id; + void type; + }, +}; + +const configuredKit = {} as ConfiguredKit; +const event = {} as SDKEvent; + +const forwarderResult: void = kit.setUserIdentity?.('user-id', 1); +const roktKit = {} as IRoktKit; +const identities: UserIdentities = { + email: 'name@example.com', +}; +const config: SDKInitConfig = { + isDevelopmentMode: true, +}; + +void filters; +void configuredKit; +void event; +void forwarderResult; +void roktKit; +void identities; +void config; diff --git a/test/types/public-consumer.ts b/test/types/public-consumer.ts new file mode 100644 index 000000000..b14b1617d --- /dev/null +++ b/test/types/public-consumer.ts @@ -0,0 +1,273 @@ +/** + * Package contract smoke test for the public `@mparticle/web-sdk` entry point. + * + * This file is compiled against generated declarations in `dist/types`, not + * source files, so it catches publish-shape regressions for normal customers. + * Keep this focused on representative public usage; the legacy DefinitelyTyped + * fixtures cover broader migration compatibility. + */ + +import mParticle, { + type AllUserAttributes, + type IdentityApiData, + type IdentityCallback, + type IdentityHTTPCode, + type IdentifyRequest, + type MPConfiguration, + type MPID, + type PrivacyConsentState, + type RoktAttributeValue, + type RoktAttributeValueArray, + type RoktAttributeValueType, + type RoktAttributes, + type RoktPartnerExtensionData, + type RoktPlacement, + type RoktPlacementEvent, + type RoktSelectPlacementsOptions, + type RoktSubscriber, + type RoktUnsubscriber, + type SDKEventAttrs, + type SDKEventCustomFlags, + type SDKEventOptions, + type SDKInitConfig, + type SDKProduct, + type TransactionAttributes, + type UserIdentities, +} from '@mparticle/web-sdk'; + +// @ts-expect-error The package only exposes a default runtime export. +import { init } from '@mparticle/web-sdk'; + +// @ts-expect-error Kit internals belong to `@mparticle/web-sdk/internal`. +import type { KitInterface } from '@mparticle/web-sdk'; + +// @ts-expect-error Only the DT-compatible MPSideloadedKit type is public. +import type { IMPSideloadedKit } from '@mparticle/web-sdk'; + +// @ts-expect-error Only the DT-compatible MPSideloadedKit type is public. +import type { IMPSideloadedKitConstructor } from '@mparticle/web-sdk'; + +// @ts-expect-error DataPlanResult was not part of the DefinitelyTyped public API. +import type { DataPlanResult } from '@mparticle/web-sdk'; + +// @ts-expect-error RoktEventChannel was not part of the DefinitelyTyped public API. +import type { RoktEventChannel } from '@mparticle/web-sdk'; + +// @ts-expect-error RoktSubscription was not part of the DefinitelyTyped public API. +import type { RoktSubscription } from '@mparticle/web-sdk'; + +const roktAttributeValue: RoktAttributeValue = ['sku-1', 3, true]; +const roktAttributeValueType: RoktAttributeValueType = null; +const roktAttributeValueArray: RoktAttributeValueArray = ['sku-1', 3, true]; +const roktAttributes: RoktAttributes = { + email: 'name@example.com', + products: roktAttributeValueArray, + value: roktAttributeValue, + nullable: roktAttributeValueType, +}; +const roktOptions: RoktSelectPlacementsOptions = { + attributes: roktAttributes, + identifier: 'prod.rokt.conf', +}; +const roktPlacement = {} as RoktPlacement; +const roktPlacementEvent: RoktPlacementEvent<{ accepted: boolean }> = { + body: { accepted: true }, + event: 'OFFER_ENGAGEMENT', + placement: roktPlacement, +}; +const roktUnsubscriber: RoktUnsubscriber = { + unsubscribe() {}, +}; +const roktSubscriber: RoktSubscriber< + RoktPlacementEvent<{ accepted: boolean }> +> = { + subscribe(callback) { + callback(roktPlacementEvent); + return roktUnsubscriber; + }, +}; +const roktExtensionData: RoktPartnerExtensionData> = { + extension: { + key: 'value', + }, +}; + +void roktOptions; +void roktSubscriber; +void roktExtensionData; + +const identities: UserIdentities = { + customerid: 'customer-1', + email: 'name@example.com', + mobile_number: '+15555555555', +}; + +const identifyRequest: IdentifyRequest = { + userIdentities: identities, + copyUserAttributes: true, +}; + +const identityCallback: IdentityCallback = result => { + const mpid: MPID | undefined = + 'mpid' in result.body ? result.body.mpid : undefined; + const code: IdentityHTTPCode = result.httpCode; + const user = result.getUser(); + const attrs: AllUserAttributes = user.getAllUserAttributes(); + + user.setUserTag('vip', true); + user.setUserAttribute('age', 42); + user.setUserAttributeList('plans', ['basic', 'premium']); + user.setConsentState(mParticle.Consent.createConsentState()); + + void mpid; + void code; + void attrs; +}; + +const docsIdentityCallback: IdentityCallback = result => { + if (result.getUser()) { + const user = result.getUser(); + void user; + return; + } + + const codes = mParticle.Identity.HTTPCodes; + + switch (result.httpCode) { + case codes.noHttpCoverage: + break; + case codes.activeIdentityRequest: + case 429: + break; + case codes.validationIssue: + case 400: + void result.body; + break; + default: + void result.body; + } +}; + +const config: SDKInitConfig = { + appName: 'Type Test App', + appVersion: '1.2.3', + dataPlan: { + planId: 'web-plan', + planVersion: 2, + }, + dataPlanOptions: { + dataPlanVersion: { + version: 2, + }, + blockUserAttributes: true, + blockEventAttributes: true, + blockEvents: false, + blockUserIdentities: false, + }, + identityCallback, + identifyRequest, + integrationDelayTimeout: 500, + isDevelopmentMode: true, + launcherOptions: { + noFunctional: false, + noTargeting: true, + }, + logLevel: 'error', + requestConfig: false, + workspaceToken: 'workspace-token', +}; + +const legacyConfig: MPConfiguration = { + appName: 'Legacy Config Shape', + customFlags: { + bool: true, + list: ['a', 1, false], + nested: { source: 'type-test' }, + }, + logLevel: 'error', + onCreateBatch: batch => batch, +}; + +mParticle.init('api-key', config); +mParticle.init('api-key', legacyConfig); +window.mParticle.init('api-key', config); + +const instance = mParticle.getInstance(); + +if (instance) { + const attrs: SDKEventAttrs = { + bool: true, + count: 1, + nullable: null, + string: 'value', + }; + + const customFlags: SDKEventCustomFlags = { + flag: 'value', + values: ['a', 1, false], + }; + + const options: SDKEventOptions = { + shouldUploadEvent: false, + }; + + const product: SDKProduct | null = mParticle.eCommerce.createProduct( + 'Socks', + 'sku-1', + 12.99, + 2, + 'blue', + 'apparel', + 'mParticle', + 1, + 'WELCOME' + ); + + const transactionAttributes: TransactionAttributes | null = mParticle.eCommerce.createTransactionAttributes( + 'txn-1', + 'store', + 'WELCOME', + '25.98', + '0', + 2 + ); + + if (!product || !transactionAttributes) { + throw new Error('Expected ecommerce helpers to return values'); + } + + instance.logEvent( + 'Type Test Event', + mParticle.EventType.Other, + attrs, + customFlags, + options + ); + instance.logPageView('Type Test Page', attrs, customFlags, options); + instance.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, + product, + attrs, + customFlags, + transactionAttributes, + options + ); + instance.Identity.identify(identifyRequest, identityCallback); + instance.Identity.search('workspace-api-key', identities, result => { + if (result.httpCode === 200) { + void result.body?.mpid; + } + }); +} + +const consent: PrivacyConsentState | null = mParticle.Consent.createGDPRConsent( + true, + Date.now() +); + +const state = mParticle.Consent.createConsentState(); +if (consent) { + state.addGDPRConsentState('analytics', consent); +} +state.removeCCPAConsentState(); +state.removeCCPAState(); diff --git a/test/types/tsconfig.json b/test/types/tsconfig.json new file mode 100644 index 000000000..1c83a287f --- /dev/null +++ b/test/types/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "baseUrl": "../..", + "esModuleInterop": true, + "lib": ["es5", "es6", "dom"], + "module": "esnext", + "moduleResolution": "node", + "noEmit": true, + "skipLibCheck": false, + "strict": true, + "target": "es5", + "types": [], + "paths": { + "@mparticle/web-sdk": ["dist/types/src/public-types.d.ts"], + "@mparticle/web-sdk/internal": ["dist/types/src/internal-types.d.ts"] + } + }, + "include": ["*.ts"] +} diff --git a/tsconfig.json b/tsconfig.json index 1ff5be947..7e806a1d6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,13 +6,20 @@ "rootDir": ".", "outDir": "build", "sourceMap": true, + "skipLibCheck": true, "noImplicitAny": false, "strictNullChecks": false, "target": "es5", + "baseUrl": ".", "moduleResolution": "Node", "resolveJsonModule": true, // this is required for importing the 'fetch-mock/esm/client' module, otherwise it errors - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "paths": { + "@mparticle/web-sdk": ["src/public-types.ts"], + "@mparticle/web-sdk/internal": ["src/internal-types.ts"] + } }, - "include": ["src/**/*.ts", "test/**/*.ts"] + "include": ["src/**/*.ts", "test/**/*.ts"], + "exclude": ["test/types/definitely-typed/**/*.ts"], } From 591f643773b8dafd5358e1e48e4c463336a5e4f4 Mon Sep 17 00:00:00 2001 From: Robert Ing Date: Fri, 15 May 2026 12:04:09 -0400 Subject: [PATCH 3/8] ci(types): validate declaration builds --- .github/workflows/pull-request.yml | 25 +++++++++++++++++++++++++ .github/workflows/staging-step-1.yml | 26 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 2a9fb3e00..c18433110 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -84,6 +84,31 @@ jobs: name: npm-logs path: ~/.npm/_logs + test-types: + name: 'Test Type Declarations' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: NPM install + uses: actions/setup-node@v6 + with: + node-version: latest + + - name: Run NPM CI + run: npm ci + + - name: Build and Test Type Declarations + run: npm run test:types + + - name: Archive npm failure logs + uses: actions/upload-artifact@v6 + if: failure() + with: + name: npm-logs + path: ~/.npm/_logs + # Only Core test requires bundle, but we want to make sure # that tests only run when the bundle is successfully built test-core: diff --git a/.github/workflows/staging-step-1.yml b/.github/workflows/staging-step-1.yml index 06f1360d2..acd91b7d8 100644 --- a/.github/workflows/staging-step-1.yml +++ b/.github/workflows/staging-step-1.yml @@ -93,6 +93,31 @@ jobs: name: npm-logs-test-jest-${{ matrix.node-version }} path: ~/.npm/_logs + test-types: + name: 'Test Type Declarations' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: NPM install + uses: actions/setup-node@v6 + with: + node-version: 24.x + + - name: Run NPM CI + run: npm ci + + - name: Build and Test Type Declarations + run: npm run test:types + + - name: Archive npm failure logs + uses: actions/upload-artifact@v6 + if: failure() + with: + name: npm-logs + path: ~/.npm/_logs + # Only Core test requires bundle, but we want to make sure # that tests only run when the bundle is successfully built test-core: @@ -288,6 +313,7 @@ jobs: - load-kit-matrix - run-kit-tests - confirm-staging-branch + - test-types steps: - name: Checkout development branch uses: actions/checkout@v6 From cff57c21c9e5de84e008ceac2bb55c624219be8d Mon Sep 17 00:00:00 2001 From: Robert Ing Date: Fri, 15 May 2026 12:04:17 -0400 Subject: [PATCH 4/8] docs(types): document DefinitelyTyped drift --- DEFINITELY_TYPED_DRIFT.md | 194 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 DEFINITELY_TYPED_DRIFT.md diff --git a/DEFINITELY_TYPED_DRIFT.md b/DEFINITELY_TYPED_DRIFT.md new file mode 100644 index 000000000..a7faf9a87 --- /dev/null +++ b/DEFINITELY_TYPED_DRIFT.md @@ -0,0 +1,194 @@ +# DefinitelyTyped Drift Notes + +This PR moves the Web SDK's public TypeScript surface into +`@mparticle/web-sdk` itself. The previous source of truth was +`@types/mparticle__web-sdk`; the new public entry point is generated from +`src/public-types.ts`. + +The compatibility compile tests at +`test/types/definitely-typed/manager.ts` and +`test/types/definitely-typed/instance.ts` are based on the old DefinitelyTyped +tests. They use this package's real default runtime import and keep the old +namespace-style type examples through a local type-only namespace merge: + +```ts +import mParticle from '@mparticle/web-sdk'; +import type * as MParticleTypes from '@mparticle/web-sdk'; +``` + +Their tsconfig maps that import to this package's generated declarations: + +```json +"paths": { + "@mparticle/web-sdk": ["dist/types/src/public-types.d.ts"] +} +``` + +That verifies existing DT-style type examples can compile against the SDK's +native declarations without depending on `@types/mparticle__web-sdk`, while +avoiding declarations for named runtime imports that the ESM bundle does not +emit. + +The generated `dist/types` output is intentionally not part of this PR's source +diff. CI runs `npm run test:types`, which rebuilds declaration files from source +before compiling the consumer fixtures against the generated package entry +points. + +## Public Type Ownership + +- Added native public definitions for types previously supplied by + `@types/mparticle__web-sdk`, including `MPConfiguration`, `MPID`, + `IdentityApiData`, `UserIdentities`, consent types, ecommerce types, + `SDKEventAttrs`, `SDKEventOptions`, and `SDKEventCustomFlags`. +- Kept the package entry point as a default-only runtime export. TypeScript + consumers should import the SDK object as the default export and access members + such as `mParticle.getInstance`, `mParticle.EventType`, + `mParticle.Identity`, `mParticle.eCommerce`, and `mParticle.Consent`. +- Named runtime exports such as `import { init } from '@mparticle/web-sdk'` are + intentionally not declared because the ESM bundle does not emit them. +- `window.mParticle` is globally augmented by the public entry point so snippet + and browser-global consumers can type direct `window.mParticle` usage without + relying on DefinitelyTyped. + +## Public API Drift From DefinitelyTyped + +### Manager And Instance + +- `getInstance()` creates and returns the default instance when needed. + `getInstance(instanceName)` returns `null` when that named instance has not + already been initialized. +- `generateHash` returns `number`, matching the implementation. DT had this as a + string-returning API. +- `setSessionAttribute` accepts the SDK's valid attribute values: + `string | number | boolean | null | undefined`. +- `logError` supports both the object form and the string form used by existing + consumers. +- `logLink` and `logForm` allow optional `eventType` and `eventInfo`, matching + existing examples and runtime usage. +- `startTrackingLocation` accepts a location callback that receives a location + object. + +### Configuration + +- `logLevel` includes `"error"` in addition to `"verbose"`, `"warning"`, and + `"none"`. +- Added config fields used by the current SDK but absent from DT, including URL + overrides and runtime options such as `aliasUrl`, `configUrl`, `identityUrl`, + `v1SecureServiceUrl`, `v2SecureServiceUrl`, `v3SecureServiceUrl`, + `requestConfig`, `integrationDelayTimeout`, `forceHttps`, `useNativeSdk`, + `maxProducts`, `domain`, `isIOS`, and `launcherOptions`. +- `DataPlanConfig` supports an optional `document`, matching SDK data plan + handling when server/snippet data plan documents are present. +- `SDKInitConfig` continues to expose SDK-specific config beyond legacy + `MPConfiguration`, including kit, pixel, data plan blocking, Rokt launcher, + logging, and feature flag options. + +### Events + +- `SDKEventOptions.shouldUploadEvent` is optional. +- `SDKEventOptions.sourceMessageId` is supported. +- `SDKEventCustomFlags` supports the broader values accepted by the SDK: + primitives, arrays, and records. + +### Identity + +- `Identity.search` is exposed on the public Identity API. +- `IdentityApiData` includes `onUserAlias` and `copyUserAttributes`. +- `IdentityApiData.userIdentities` remains optional/null-capable for broad + identity request compatibility, while `IdentifyRequest` keeps + `userIdentities` required. +- `onUserAlias` is typed as the legacy callback shape + `(previousUser, newUser) => void`, matching runtime behavior. +- `UserIdentities` accepts `null` values for legacy identity-clearing patterns. +- `UserIdentities` includes `email_sha256` and `mobile_sha256` aliases used by + the SDK's identity normalization flow. +- `IdentityResult.body` is a union of the normal identity response body and the + modify response body. +- `IdentityResultBody.mpid` is exposed as optional. +- Alias requests use a typed scope of `'device' | 'mpid'`. +- `Identity.aliasUsers` uses the alias callback result shape + `{ httpCode: number; message: string }`. +- `Identity.logout` accepts `IdentityApiData`, `{}`, `null`, or `undefined`, + matching existing usage. +- `User.getUserAudiences` is exposed as optional, matching runtime behavior. + +### Consent + +- `PrivacyConsentState` metadata fields are optional because the SDK can create + consent objects with only the required `Consented` value. +- `Consent.createGDPRConsent` and `Consent.createCCPAConsent` return + `PrivacyConsentState | null`, reflecting runtime validation failures. +- `ConsentState` includes both `removeCCPAConsentState` and the deprecated + `removeCCPAState` compatibility method. + +### Ecommerce + +- Ecommerce factory methods are typed as nullable where the implementation can + return `null` after validation failure. +- Product creation accepts string or number inputs for SKU, price, quantity, + revenue, and shipping where runtime sanitization/conversion supports it. +- Public product types include SDK-created fields such as `CouponCode` and + `TotalAmount`. +- Impressions support a single product or product arrays. +- Promotions require `Id` on successfully created promotion objects and support + string or number IDs, matching `createPromotion` input validation. +- Promotion and impression logging accept single objects or arrays, matching + runtime behavior. + +### Sideloaded Kits + +- `MPSideloadedKit` is exposed as a public constructor on the package surface, + matching the runtime manager object and the documented sideloaded-kit setup + flow. +- `KitFilterSettings` is exposed so consumers can type + `MPSideloadedKit.filterDictionary`. +- `MPSideloadedKit.addUserIdentityFilter` accepts an `IdentityType` enum value, + matching runtime usage. +- `MPConfiguration.sideloadedKits` remains permissive for this migration. The + documented setup flow, sample app, DefinitelyTyped fixture, and runtime path + are not fully aligned on whether the config array contains raw kit exports or + `MPSideloadedKit` wrappers, so tightening this shape should be handled after + docs, samples, and runtime behavior agree. + +### Rokt + +- Added public Rokt manager typing because `mParticle.Rokt` is part of the + current SDK surface and is documented for direct customer use. +- Kept the DT-compatible Rokt type names used by consumers, including + `RoktSelection`, `RoktPlacement`, `RoktPlacementEvent`, `RoktSubscriber`, + `RoktUnsubscriber`, `RoktSelectPlacementsOptions`, + `RoktPartnerExtensionData`, and `RoktAttributes`. +- Did not expose new public aliases such as `RoktEventChannel` or + `RoktSubscription`; those names were not part of the DT contract. + +## New Public Declarations Not In DefinitelyTyped + +- `MParticleWebSDK` +- `MParticleWebSDKManager` +- `MParticleWebSDKInstance` +- `FilteringConsentRuleValues` +- `FilteringEventAttributeValue` +- `FilteringUserAttributeValue` +- `SDKInitConfig` +- `SDKConsentApi` +- `SDKConsentState` +- `SDKGDPRConsentState` +- `SDKCCPAConsentState` +- `IdentitySearchCallback` +- `IIdentitySearchResult` +- `IIdentitySearchResponseBody` + +## Intentional Compatibility Notes + +- The old DT-style fixture uses non-null assertions for `getInstance()` and + nullable ecommerce/consent factory results. This keeps the compatibility test + close to the original examples while preserving more accurate native SDK + declarations. +- The old DT-style fixture intentionally uses the package default import instead + of `import mParticle = require('@mparticle/web-sdk')`. Supporting the + `export =` declaration shape would make TypeScript accept named runtime + imports that are not emitted by the ESM bundle. +- `publicSdkTypes.ts` is a consolidation point for legacy DT-owned public shapes. + A follow-up refactor can move those types into domain-specific files such as + consent, identity, ecommerce, and config interfaces while keeping + `public-types.ts` as the public barrel. From 89e44204474f8aad234ea3d023570a9ebec68042 Mon Sep 17 00:00:00 2001 From: Robert Ing Date: Fri, 15 May 2026 12:04:25 -0400 Subject: [PATCH 5/8] chore: remove unused release workflow --- .github/workflows/release.yml | 334 ---------------------------------- .gitignore | 5 +- 2 files changed, 4 insertions(+), 335 deletions(-) delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 4e175cff1..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,334 +0,0 @@ -name: Release SDK - -on: - workflow_dispatch: - inputs: - dryRun: - description: 'Do a dry run to preview instead of a real release [true/false]' - required: true - type: boolean - default: true - -jobs: - # SDK release is done from master branch. - confirm-public-repo-master-branch: - name: 'Confirm release is run from public/master branch' - uses: mParticle/mparticle-workflows/.github/workflows/sdk-release-repo-branch-check.yml@main - - build-bundle: - name: Build Distribution Bundle - runs-on: ubuntu-latest - needs: confirm-public-repo-master-branch - steps: - - name: Checkout - uses: actions/checkout@v6 - with: - ref: development - - - name: NPM install - uses: actions/setup-node@v6 - with: - node-version: latest - - - name: Run NPM CI - run: npm ci - - - name: Lint with ESLint - run: npm run lint - - - name: Lint with Prettier - run: npm run prettier - - - name: Run Build IIFE - run: npm run build:iife - - - name: Display Bundle Diff, but Fancy! - run: git diff --unified=3 dist/mparticle.js | npx diff-so-fancy - - - name: Archive npm failure logs - uses: actions/upload-artifact@v6 - if: failure() - with: - name: npm-logs - path: ~/.npm/_logs - - # Currently, we're only using Jest to test TypeScript modules - # and they do not require any built files - test-jest: - name: 'Test Jest' - runs-on: 'ubuntu-latest' - steps: - - name: Checkout - uses: actions/checkout@v6 - - - name: NPM install - uses: actions/setup-node@v6 - with: - node-version: latest - - - name: Run NPM CI - run: npm ci - - - name: Run Jest Tests - run: npm run test:jest - - - name: Archive npm failure logs - uses: actions/upload-artifact@v6 - if: failure() - with: - name: npm-logs - path: ~/.npm/_logs - - # Only Core test requires bundle, but we want to make sure - # that tests only run when the bundle is successfully built - test-core: - name: Core Tests - uses: mParticle/mparticle-workflows/.github/workflows/web-run-test.yml@main - needs: - - test-jest - - build-bundle - with: - test_command_label: Core SDK Tests - test_command: npm run test - build_command: npm run build:iife - branch_name: ${{ vars.GITHUB_SHA }} - - # Test Sub can be run independent of other tests - test-stub: - name: 'Test Stub' - runs-on: ubuntu-latest - needs: - - test-core - - test-jest - - build-bundle - steps: - - name: Checkout - uses: actions/checkout@v6 - - - name: NPM install - uses: actions/setup-node@v6 - with: - node-version: latest - - - name: Run NPM CI - run: npm ci - - - name: Install Firefox Latest - uses: browser-actions/setup-firefox@latest - - - name: Log Firefox Version - run: firefox --version - - - name: Run Stub Tests - run: npm run test:stub - - - name: Archive npm failure logs - uses: actions/upload-artifact@v6 - if: failure() - with: - name: npm-logs - path: ~/.npm/_logs - - # Integration Tests run the same suite of tests against various build systems - # to make sure our SDK will run in different environments - - test-integrations-require-js: - name: 'Integration Tests: Require JS' - uses: mParticle/mparticle-workflows/.github/workflows/web-run-test.yml@main - needs: - - test-core - - test-jest - - build-bundle - with: - test_command_label: Require JS Test - test_command: npm run test:requirejs - branch_name: ${{ vars.GITHUB_SHA }} - - test-integrations-common-js-browserfy: - name: 'Integration Tests: Browserfy Common JS' - uses: mParticle/mparticle-workflows/.github/workflows/web-run-test.yml@main - needs: - - test-core - - test-jest - - build-bundle - with: - test_command_label: Browserfy CJS Test - test_command: npm run test:integrations:cjs:browserfy - branch_name: ${{ vars.GITHUB_SHA }} - build_command: npm run build:npm && npm run build:test-bundle - - test-integrations-common-js-webpack: - name: 'Integration Tests: webpack Common JS' - uses: mParticle/mparticle-workflows/.github/workflows/web-run-test.yml@main - needs: - - test-core - - test-jest - - build-bundle - with: - test_command_label: webpack CJS Test - test_command: npm run test:integrations:cjs:webpack - branch_name: ${{ vars.GITHUB_SHA }} - build_command: npm run build:npm && npm run build:test-bundle - - test-integrations-common-js-rollup: - name: 'Integration Tests: Rollup Common JS' - uses: mParticle/mparticle-workflows/.github/workflows/web-run-test.yml@main - needs: - - test-core - - test-jest - - build-bundle - with: - test_command_label: Rollup CJS Test - test_command: npm run test:integrations:cjs:rollup - branch_name: ${{ vars.GITHUB_SHA }} - build_command: npm run build:npm && npm run build:test-bundle - - test-integrations-module-js-webpack: - name: 'Integration Tests: webpack Module JS' - uses: mParticle/mparticle-workflows/.github/workflows/web-run-test.yml@main - needs: - - test-core - - test-jest - - build-bundle - with: - test_command_label: webpack Module Test - test_command: npm run test:integrations:module:webpack - branch_name: ${{ vars.GITHUB_SHA }} - build_command: npm run build:esm && npm run build:test-bundle - - test-integrations-module-js-rollup: - name: 'Integration Tests: Rollup Module JS' - uses: mParticle/mparticle-workflows/.github/workflows/web-run-test.yml@main - needs: - - test-core - - test-jest - - build-bundle - with: - test_command_label: Rollup Module Test - test_command: npm run test:integrations:module:rollup - branch_name: ${{ vars.GITHUB_SHA }} - build_command: npm run build:esm && npm run build:test-bundle - - create-release-branch: - name: Create release branch - runs-on: ubuntu-latest - needs: - - test-core - - test-stub - - test-integrations-common-js-browserfy - - test-integrations-common-js-webpack - - test-integrations-common-js-rollup - - test-integrations-module-js-webpack - - test-integrations-module-js-rollup - - test-integrations-require-js - - confirm-public-repo-master-branch - steps: - - name: Checkout development branch - uses: actions/checkout@v6 - with: - repository: mparticle/mparticle-web-sdk - ref: development - - - name: Create and push release branch - run: | - git checkout -b release/${{ github.run_number }} - git push origin release/${{ github.run_number }} - - release: - name: Perform Release - runs-on: ubuntu-latest - needs: - - create-release-branch - - # OIDC permissions for npm trusted publishing - permissions: - id-token: write - contents: read - - env: - GITHUB_TOKEN: ${{ secrets.MP_SEMANTIC_RELEASE_BOT }} - GIT_AUTHOR_NAME: mparticle-automation - GIT_AUTHOR_EMAIL: developers@mparticle.com - GIT_COMMITTER_NAME: mparticle-automation - GIT_COMMITTER_EMAIL: developers@mparticle.com - - steps: - - name: Checkout public master branch - uses: actions/checkout@v6 - with: - fetch-depth: 0 - ref: master - - - name: Import GPG Key - uses: crazy-max/ghaction-import-gpg@e00cb83a68c1158b29afc5217dd0582cada6d172 #v4.4.0 - with: - gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} - passphrase: ${{ secrets.GPG_PASSPHRASE }} - git_user_signingkey: true - git_commit_gpgsign: true - - - name: Merge release branch into master branch - run: | - git pull origin release/${{ github.run_number }} - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: latest - registry-url: 'https://registry.npmjs.org' - - - name: Install dependencies - run: npm ci - - - name: Release --dry-run - if: ${{ github.event.inputs.dryRun == 'true'}} - run: | - npx semantic-release --dry-run - - # NPM Publish happens here via OIDC trusted publishing - - name: Release - if: ${{ github.event.inputs.dryRun == 'false'}} - run: | - npx semantic-release - - - name: Archive npm failure logs - uses: actions/upload-artifact@v6 - if: failure() - with: - name: npm-logs - path: ~/.npm/_logs - - - name: Push automated release commits to release branch - if: ${{ github.event.inputs.dryRun == 'false' }} - run: | - git push origin HEAD:release/${{ github.run_number }} - - sync-repository: - name: Sync repositories - needs: release - runs-on: ubuntu-latest - steps: - - name: Checkout master branch - uses: actions/checkout@v6 - with: - fetch-depth: 0 - repository: ${{ github.repository }} - token: ${{ secrets.MP_SEMANTIC_RELEASE_BOT }} - ref: master - - - name: Merge release branch into master branch - if: ${{ github.event.inputs.dryRun == 'false' }} - run: | - git pull origin release/${{ github.run_number }} - - - name: Push release commits to main, master and development branches - if: ${{ github.event.inputs.dryRun == 'false' }} - run: | - git push origin HEAD:development - git push origin HEAD:master - git push origin HEAD:main - - - name: Delete release branch - if: ${{ github.event.inputs.dryRun == 'false' }} - run: | - git push --delete origin release/${{ github.run_number }} diff --git a/.gitignore b/.gitignore index b2296f3bb..833dae62d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ node_modules/ .vscode/ test-bundle.js out/ +build/ test/reports test/cross-browser-testing/reports test/test-bundle.js.map @@ -14,4 +15,6 @@ local.log test/cross-browser-testing/CBT-tests-es5.js test/cross-browser-testing/CBT-tests.js coverage/ -kits/**/test/test-bundle.js \ No newline at end of file +kits/**/test/test-bundle.js +.agents/ +.claude/worktrees/ From 26f2a88490bf200857914862611cd133080193dc Mon Sep 17 00:00:00 2001 From: Robert Ing Date: Fri, 15 May 2026 12:05:46 -0400 Subject: [PATCH 6/8] fix(types): annotate identity JS declaration emit --- src/identity.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/identity.js b/src/identity.js index 59ef08c2f..207dca777 100644 --- a/src/identity.js +++ b/src/identity.js @@ -848,6 +848,9 @@ export default function Identity(mpInstance) { * Example: mParticle.Identity.getCurrentUser().getAllUserAttributes() * @class mParticle.Identity.getCurrentUser() */ + /** + * @returns {import('./identity-user-interfaces').IMParticleUser} + */ this.mParticleUser = function(mpid, isLoggedIn) { var self = this; return { @@ -1330,6 +1333,9 @@ export default function Identity(mpInstance) { * @class mParticle.Identity.getCurrentUser().getCart() * @deprecated */ + /** + * @returns {import('./identity-user-interfaces').mParticleUserCart} + */ this.mParticleUserCart = function() { return { /** From 71f62194731f9bcca974d7d4b7951d69e530f7e9 Mon Sep 17 00:00:00 2001 From: Robert Ing Date: Fri, 15 May 2026 13:17:31 -0400 Subject: [PATCH 7/8] refactor(types): keep consent api facade internal --- DEFINITELY_TYPED_DRIFT.md | 1 - src/public-types.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/DEFINITELY_TYPED_DRIFT.md b/DEFINITELY_TYPED_DRIFT.md index a7faf9a87..61d878e10 100644 --- a/DEFINITELY_TYPED_DRIFT.md +++ b/DEFINITELY_TYPED_DRIFT.md @@ -170,7 +170,6 @@ points. - `FilteringEventAttributeValue` - `FilteringUserAttributeValue` - `SDKInitConfig` -- `SDKConsentApi` - `SDKConsentState` - `SDKGDPRConsentState` - `SDKCCPAConsentState` diff --git a/src/public-types.ts b/src/public-types.ts index 82f955d03..739b404db 100644 --- a/src/public-types.ts +++ b/src/public-types.ts @@ -149,7 +149,6 @@ export type { // Consent API facade types export type { - SDKConsentApi, SDKConsentState, SDKConsentStateData, SDKGDPRConsentState, From d37d8441dd69cafc93c7228336133cda687d235a Mon Sep 17 00:00:00 2001 From: Robert Ing Date: Fri, 15 May 2026 13:19:04 -0400 Subject: [PATCH 8/8] refactor(types): hide base sdk interface --- DEFINITELY_TYPED_DRIFT.md | 1 - src/public-types.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/DEFINITELY_TYPED_DRIFT.md b/DEFINITELY_TYPED_DRIFT.md index 61d878e10..1bf5d7a78 100644 --- a/DEFINITELY_TYPED_DRIFT.md +++ b/DEFINITELY_TYPED_DRIFT.md @@ -163,7 +163,6 @@ points. ## New Public Declarations Not In DefinitelyTyped -- `MParticleWebSDK` - `MParticleWebSDKManager` - `MParticleWebSDKInstance` - `FilteringConsentRuleValues` diff --git a/src/public-types.ts b/src/public-types.ts index 739b404db..ecb2ba7df 100644 --- a/src/public-types.ts +++ b/src/public-types.ts @@ -93,7 +93,6 @@ export type { LogLevelType, MParticleWebSDKInstance, MParticleWebSDKManager, - MParticleWebSDK, } from './sdkRuntimeModels'; // User & Identity