@mparticle/web-sdk 2.43.0 → 2.43.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/identity.js CHANGED
@@ -33,8 +33,14 @@ export default function Identity(mpInstance) {
33
33
  Messages.InformationMessages.StartingLogEvent + ': ' + method
34
34
  );
35
35
 
36
- var identityValidationResult = mpInstance._Helpers.Validators.validateIdentities(
36
+ // First, remove any falsy identity values and warn about them
37
+ const cleanedIdentityApiData = mpInstance._Helpers.Validators.removeFalsyIdentityValues(
37
38
  identityApiData,
39
+ mpInstance.Logger
40
+ );
41
+
42
+ var identityValidationResult = mpInstance._Helpers.Validators.validateIdentities(
43
+ cleanedIdentityApiData,
38
44
  method
39
45
  );
40
46
 
@@ -64,6 +70,7 @@ export default function Identity(mpInstance) {
64
70
 
65
71
  return {
66
72
  valid: true,
73
+ cleanedIdentities: cleanedIdentityApiData,
67
74
  };
68
75
  },
69
76
 
@@ -237,7 +244,7 @@ export default function Identity(mpInstance) {
237
244
 
238
245
  if (preProcessResult.valid) {
239
246
  var identityApiRequest = mpInstance._Identity.IdentityRequest.createIdentityRequest(
240
- identityApiData,
247
+ preProcessResult.cleanedIdentities,
241
248
  Constants.platform,
242
249
  Constants.sdkVendor,
243
250
  Constants.sdkVersion,
@@ -332,7 +339,7 @@ export default function Identity(mpInstance) {
332
339
  if (preProcessResult.valid) {
333
340
  var evt,
334
341
  identityApiRequest = mpInstance._Identity.IdentityRequest.createIdentityRequest(
335
- identityApiData,
342
+ preProcessResult.cleanedIdentities,
336
343
  Constants.platform,
337
344
  Constants.sdkVendor,
338
345
  Constants.sdkVersion,
@@ -422,7 +429,7 @@ export default function Identity(mpInstance) {
422
429
 
423
430
  if (preProcessResult.valid) {
424
431
  var identityApiRequest = mpInstance._Identity.IdentityRequest.createIdentityRequest(
425
- identityApiData,
432
+ preProcessResult.cleanedIdentities,
426
433
  Constants.platform,
427
434
  Constants.sdkVendor,
428
435
  Constants.sdkVersion,
@@ -514,11 +521,11 @@ export default function Identity(mpInstance) {
514
521
  if (currentUser) {
515
522
  mpid = currentUser.getMPID();
516
523
  }
517
- var newUserIdentities =
518
- identityApiData && identityApiData.userIdentities
519
- ? identityApiData.userIdentities
520
- : {};
521
524
  if (preProcessResult.valid) {
525
+ var newUserIdentities =
526
+ identityApiData && identityApiData.userIdentities
527
+ ? preProcessResult.cleanedIdentities.userIdentities
528
+ : {};
522
529
  var identityApiRequest = mpInstance._Identity.IdentityRequest.createModifyIdentityRequest(
523
530
  currentUser
524
531
  ? currentUser.getUserIdentities().userIdentities
@@ -2,7 +2,7 @@ import { IKitConfigs } from "./configAPIClient";
2
2
  import { UserAttributeFilters } from "./forwarders.interfaces";
3
3
  import { IMParticleUser } from "./identity-user-interfaces";
4
4
  import KitFilterHelper from "./kitFilterHelper";
5
- import { Dictionary, parseSettingsString } from "./utils";
5
+ import { Dictionary, parseSettingsString, generateUniqueId, isFunction } from "./utils";
6
6
  import { SDKIdentityApi } from "./identity.interfaces";
7
7
  import { SDKLoggerApi } from "./sdkRuntimeModels";
8
8
 
@@ -34,8 +34,11 @@ export interface IRoktLauncher {
34
34
  }
35
35
 
36
36
  export interface IRoktMessage {
37
+ messageId: string;
37
38
  methodName: string;
38
39
  payload: any;
40
+ resolve?: Function;
41
+ reject?: Function;
39
42
  }
40
43
 
41
44
  export interface RoktKitFilterSettings {
@@ -76,7 +79,7 @@ export default class RoktManager {
76
79
  public kit: IRoktKit = null;
77
80
  public filters: RoktKitFilterSettings = {};
78
81
  private currentUser: IMParticleUser | null = null;
79
- private messageQueue: IRoktMessage[] = [];
82
+ private messageQueue: Map<string, IRoktMessage> = new Map();
80
83
  private sandbox: boolean | null = null;
81
84
  private placementAttributesMapping: Dictionary<string>[] = [];
82
85
  private identityService: SDKIdentityApi;
@@ -156,11 +159,7 @@ export default class RoktManager {
156
159
  */
157
160
  public async selectPlacements(options: IRoktSelectPlacementsOptions): Promise<IRoktSelection> {
158
161
  if (!this.isReady()) {
159
- this.queueMessage({
160
- methodName: 'selectPlacements',
161
- payload: options,
162
- });
163
- return Promise.resolve({} as IRoktSelection);
162
+ return this.deferredCall<IRoktSelection>('selectPlacements', options);
164
163
  }
165
164
 
166
165
  try {
@@ -216,13 +215,9 @@ export default class RoktManager {
216
215
  }
217
216
  }
218
217
 
219
- public hashAttributes(attributes: IRoktPartnerAttributes): Promise<Record<string, string>> {
218
+ public hashAttributes(attributes: IRoktPartnerAttributes): Promise<IRoktPartnerAttributes> {
220
219
  if (!this.isReady()) {
221
- this.queueMessage({
222
- methodName: 'hashAttributes',
223
- payload: attributes,
224
- });
225
- return Promise.resolve({} as Record<string, string>);
220
+ return this.deferredCall<IRoktPartnerAttributes>('hashAttributes', attributes);
226
221
  }
227
222
 
228
223
  try {
@@ -234,10 +229,7 @@ export default class RoktManager {
234
229
 
235
230
  public setExtensionData<T>(extensionData: IRoktPartnerExtensionData<T>): void {
236
231
  if (!this.isReady()) {
237
- this.queueMessage({
238
- methodName: 'setExtensionData',
239
- payload: extensionData,
240
- });
232
+ this.deferredCall<void>('setExtensionData', extensionData);
241
233
  return;
242
234
  }
243
235
 
@@ -288,17 +280,62 @@ export default class RoktManager {
288
280
  }
289
281
 
290
282
  private processMessageQueue(): void {
291
- if (this.messageQueue.length > 0 && this.isReady()) {
292
- this.messageQueue.forEach(async (message) => {
293
- if (this.kit && message.methodName in this.kit) {
294
- await (this.kit[message.methodName] as Function)(message.payload);
295
- }
296
- });
297
- this.messageQueue = [];
283
+ if (!this.isReady() || this.messageQueue.size === 0) {
284
+ return;
298
285
  }
286
+
287
+ this.logger?.verbose(`RoktManager: Processing ${this.messageQueue.size} queued messages`);
288
+
289
+ this.messageQueue.forEach((message) => {
290
+ if(!(message.methodName in this.kit) || !isFunction(this.kit[message.methodName])) {
291
+ this.logger?.error(`RoktManager: Method ${message.methodName} not found in kit`);
292
+ return;
293
+ }
294
+
295
+ this.logger?.verbose(`RoktManager: Processing queued message: ${message.methodName} with payload: ${JSON.stringify(message.payload)}`);
296
+
297
+ try {
298
+ const result = (this.kit[message.methodName] as Function)(message.payload);
299
+ this.completePendingPromise(message.messageId, result);
300
+ } catch (error) {
301
+ const errorMessage = error instanceof Error ? error.message : String(error);
302
+ this.logger?.error(`RoktManager: Error processing message '${message.methodName}': ${errorMessage}`);
303
+ this.completePendingPromise(message.messageId, Promise.reject(error));
304
+ }
305
+ });
299
306
  }
300
307
 
301
308
  private queueMessage(message: IRoktMessage): void {
302
- this.messageQueue.push(message);
309
+ this.messageQueue.set(message.messageId, message);
310
+ }
311
+
312
+ private deferredCall<T>(methodName: string, payload: any): Promise<T> {
313
+ return new Promise<T>((resolve, reject) => {
314
+ const messageId = `${methodName}_${generateUniqueId()}`;
315
+
316
+ this.queueMessage({
317
+ messageId,
318
+ methodName,
319
+ payload,
320
+ resolve,
321
+ reject,
322
+ });
323
+ });
324
+ }
325
+
326
+ private completePendingPromise(messageId: string | undefined, resultOrError: any): void {
327
+ if (!messageId || !this.messageQueue.has(messageId)) {
328
+ return;
329
+ }
330
+
331
+ const message = this.messageQueue.get(messageId)!;
332
+
333
+ if (message.resolve) {
334
+ Promise.resolve(resultOrError)
335
+ .then((result) => message.resolve!(result))
336
+ .catch((error) => message.reject!(error));
337
+ }
338
+
339
+ this.messageQueue.delete(messageId);
303
340
  }
304
341
  }
@@ -5,6 +5,7 @@ import Types from './types';
5
5
  import { generateDeprecationMessage } from './utils';
6
6
  import { IMParticleUser } from './identity-user-interfaces';
7
7
  import { IMParticleWebSDKInstance } from './mp-instance';
8
+ import { hasIdentityRequestChanged } from './identity-utils';
8
9
 
9
10
  const { Messages } = Constants;
10
11
 
@@ -30,7 +31,7 @@ export default function SessionManager(
30
31
  ) {
31
32
  const self = this;
32
33
 
33
- this.initialize = function(): void {
34
+ this.initialize = function (): void {
34
35
  if (mpInstance._Store.sessionId) {
35
36
  const sessionTimeoutInMilliseconds: number =
36
37
  mpInstance._Store.SDKConfig.sessionTimeout * 60000;
@@ -46,9 +47,14 @@ export default function SessionManager(
46
47
  self.startNewSession();
47
48
  } else {
48
49
  // https://go.mparticle.com/work/SQDSDKS-6045
49
- const persistence: IPersistenceMinified = mpInstance._Persistence.getPersistence();
50
- if (persistence && !persistence.cu) {
51
- // https://go.mparticle.com/work/SQDSDKS-6323
50
+ // https://go.mparticle.com/work/SQDSDKS-6323
51
+ const currentUser = mpInstance.Identity.getCurrentUser();
52
+ const sdkIdentityRequest =
53
+ mpInstance._Store.SDKConfig.identifyRequest;
54
+
55
+ if (
56
+ hasIdentityRequestChanged(currentUser, sdkIdentityRequest)
57
+ ) {
52
58
  mpInstance.Identity.identify(
53
59
  mpInstance._Store.SDKConfig.identifyRequest,
54
60
  mpInstance._Store.SDKConfig.identityCallback
@@ -62,7 +68,7 @@ export default function SessionManager(
62
68
  }
63
69
  };
64
70
 
65
- this.getSession = function(): string {
71
+ this.getSession = function (): string {
66
72
  mpInstance.Logger.warning(
67
73
  generateDeprecationMessage(
68
74
  'SessionManager.getSession()',
@@ -73,11 +79,11 @@ export default function SessionManager(
73
79
  return this.getSessionId();
74
80
  };
75
81
 
76
- this.getSessionId = function(): string {
82
+ this.getSessionId = function (): string {
77
83
  return mpInstance._Store.sessionId;
78
84
  };
79
85
 
80
- this.startNewSession = function(): void {
86
+ this.startNewSession = function (): void {
81
87
  mpInstance.Logger.verbose(
82
88
  Messages.InformationMessages.StartingNewSession
83
89
  );
@@ -87,7 +93,8 @@ export default function SessionManager(
87
93
  .generateUniqueId()
88
94
  .toUpperCase();
89
95
 
90
- const currentUser: IMParticleUser = mpInstance.Identity.getCurrentUser();
96
+ const currentUser: IMParticleUser =
97
+ mpInstance.Identity.getCurrentUser();
91
98
  const mpid: MPID = currentUser ? currentUser.getMPID() : null;
92
99
 
93
100
  if (mpid) {
@@ -121,7 +128,7 @@ export default function SessionManager(
121
128
  }
122
129
  };
123
130
 
124
- this.endSession = function(override: boolean): void {
131
+ this.endSession = function (override: boolean): void {
125
132
  mpInstance.Logger.verbose(
126
133
  Messages.InformationMessages.StartingEndSession
127
134
  );
@@ -152,9 +159,10 @@ export default function SessionManager(
152
159
  let sessionTimeoutInMilliseconds: number;
153
160
  let timeSinceLastEventSent: number;
154
161
 
155
- const cookies: IPersistenceMinified = mpInstance._Persistence.getPersistence();
162
+ const cookies: IPersistenceMinified =
163
+ mpInstance._Persistence.getPersistence();
156
164
 
157
- if (!cookies || cookies.gs && !cookies.gs.sid) {
165
+ if (!cookies || (cookies.gs && !cookies.gs.sid)) {
158
166
  mpInstance.Logger.verbose(
159
167
  Messages.InformationMessages.NoSessionToEnd
160
168
  );
@@ -189,16 +197,16 @@ export default function SessionManager(
189
197
  mpInstance._timeOnSiteTimer?.resetTimer();
190
198
  };
191
199
 
192
- this.setSessionTimer = function(): void {
200
+ this.setSessionTimer = function (): void {
193
201
  const sessionTimeoutInMilliseconds: number =
194
202
  mpInstance._Store.SDKConfig.sessionTimeout * 60000;
195
203
 
196
- mpInstance._Store.globalTimer = window.setTimeout(function() {
204
+ mpInstance._Store.globalTimer = window.setTimeout(function () {
197
205
  self.endSession();
198
206
  }, sessionTimeoutInMilliseconds);
199
207
  };
200
208
 
201
- this.resetSessionTimer = function(): void {
209
+ this.resetSessionTimer = function (): void {
202
210
  if (!mpInstance._Store.webviewBridgeEnabled) {
203
211
  if (!mpInstance._Store.sessionId) {
204
212
  self.startNewSession();
@@ -209,7 +217,7 @@ export default function SessionManager(
209
217
  self.startNewSessionIfNeeded();
210
218
  };
211
219
 
212
- this.clearSessionTimeout = function(): void {
220
+ this.clearSessionTimeout = function (): void {
213
221
  clearTimeout(mpInstance._Store.globalTimer);
214
222
  };
215
223
 
package/src/validators.ts CHANGED
@@ -40,7 +40,37 @@ const Validators = {
40
40
  );
41
41
  },
42
42
 
43
- validateIdentities: function(
43
+ removeFalsyIdentityValues: function (
44
+ identityApiData: IdentityApiData,
45
+ logger: any
46
+ ): IdentityApiData {
47
+ if (!identityApiData || !identityApiData.userIdentities) {
48
+ return identityApiData;
49
+ }
50
+
51
+ const cleanedData = {} as IdentityApiData;
52
+ const cleanedUserIdentities = { ...identityApiData.userIdentities };
53
+
54
+ for (const identityType in identityApiData.userIdentities) {
55
+ if (identityApiData.userIdentities.hasOwnProperty(identityType)) {
56
+ const value = identityApiData.userIdentities[identityType];
57
+
58
+ // Check if value is falsy (undefined, false, 0, '', etc.) but not null
59
+ if (value !== null && !value) {
60
+ logger.warning(
61
+ `Identity value for '${identityType}' is falsy (${value}). This value will be removed from the request.`
62
+ );
63
+ delete cleanedUserIdentities[identityType];
64
+ }
65
+ }
66
+ }
67
+
68
+ cleanedData.userIdentities = cleanedUserIdentities;
69
+
70
+ return cleanedData;
71
+ },
72
+
73
+ validateIdentities: function (
44
74
  identityApiData: IdentityApiData,
45
75
  method?: IdentityAPIMethod
46
76
  ): ValidationIdentitiesReturn {