@posiwise/common-services 0.1.40 → 0.1.42

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.
Files changed (64) hide show
  1. package/esm2022/lib/ab-test.service.mjs +1 -1
  2. package/esm2022/lib/ahoy.service.mjs +1 -1
  3. package/esm2022/lib/auth.service.mjs +1 -1
  4. package/esm2022/lib/base-http.service.mjs +2 -2
  5. package/esm2022/lib/common-services.interface.mjs +1 -1
  6. package/esm2022/lib/common.service.mjs +1 -1
  7. package/esm2022/lib/custom-preloading.service.mjs +1 -1
  8. package/esm2022/lib/dashboard.service.mjs +1 -1
  9. package/esm2022/lib/data.service.mjs +1 -1
  10. package/esm2022/lib/date-formatter.service.mjs +8 -4
  11. package/esm2022/lib/effects/user.effects.mjs +1 -1
  12. package/esm2022/lib/geo.service.mjs +1 -1
  13. package/esm2022/lib/google-analytics.service.mjs +13 -9
  14. package/esm2022/lib/group.service.mjs +1 -1
  15. package/esm2022/lib/hopscotch.service.mjs +1 -1
  16. package/esm2022/lib/link-loader.service.mjs +1 -1
  17. package/esm2022/lib/mailbox.service.mjs +1 -1
  18. package/esm2022/lib/notification.service.mjs +9 -5
  19. package/esm2022/lib/permission.service.mjs +4 -4
  20. package/esm2022/lib/product.service.mjs +1 -1
  21. package/esm2022/lib/profile.service.mjs +1 -1
  22. package/esm2022/lib/qualification.service.mjs +1 -1
  23. package/esm2022/lib/script-loader.service.mjs +5 -4
  24. package/esm2022/lib/sentry.service.mjs +127 -108
  25. package/esm2022/lib/socket.service.mjs +1 -1
  26. package/esm2022/lib/subscription.service.mjs +4 -4
  27. package/esm2022/lib/tag.service.mjs +1 -1
  28. package/esm2022/lib/tips.service.mjs +1 -1
  29. package/esm2022/lib/toast.service.mjs +1 -1
  30. package/esm2022/lib/user.service.mjs +1 -1
  31. package/esm2022/lib/validation.service.mjs +2 -2
  32. package/fesm2022/posiwise-common-services.mjs +165 -133
  33. package/fesm2022/posiwise-common-services.mjs.map +1 -1
  34. package/lib/ab-test.service.d.ts +1 -1
  35. package/lib/ahoy.service.d.ts +3 -3
  36. package/lib/auth.service.d.ts +10 -10
  37. package/lib/base-http.service.d.ts +1 -1
  38. package/lib/common-services.interface.d.ts +2 -3
  39. package/lib/common.service.d.ts +1 -1
  40. package/lib/custom-preloading.service.d.ts +1 -1
  41. package/lib/dashboard.service.d.ts +1 -1
  42. package/lib/data.service.d.ts +1 -1
  43. package/lib/effects/user.effects.d.ts +2 -2
  44. package/lib/geo.service.d.ts +3 -3
  45. package/lib/google-analytics.service.d.ts +4 -3
  46. package/lib/group.service.d.ts +5 -5
  47. package/lib/hopscotch.service.d.ts +3 -3
  48. package/lib/link-loader.service.d.ts +2 -2
  49. package/lib/mailbox.service.d.ts +3 -3
  50. package/lib/notification.service.d.ts +7 -6
  51. package/lib/permission.service.d.ts +1 -1
  52. package/lib/product.service.d.ts +2 -2
  53. package/lib/profile.service.d.ts +4 -4
  54. package/lib/qualification.service.d.ts +2 -2
  55. package/lib/script-loader.service.d.ts +1 -1
  56. package/lib/sentry.service.d.ts +9 -1
  57. package/lib/socket.service.d.ts +2 -2
  58. package/lib/subscription.service.d.ts +1 -1
  59. package/lib/tag.service.d.ts +1 -1
  60. package/lib/tips.service.d.ts +1 -1
  61. package/lib/toast.service.d.ts +1 -1
  62. package/lib/user.service.d.ts +4 -4
  63. package/lib/validation.service.d.ts +1 -1
  64. package/package.json +1 -1
@@ -33,7 +33,7 @@ import { fromError } from 'stacktrace-js';
33
33
  class ScriptLoaderService {
34
34
  constructor(document) {
35
35
  this.document = document;
36
- this._scripts = [];
36
+ this._scripts = {};
37
37
  }
38
38
  load(tag, ...scripts) {
39
39
  scripts.forEach((src) => {
@@ -57,13 +57,14 @@ class ScriptLoaderService {
57
57
  return Promise.all(promises);
58
58
  }
59
59
  loadScript(tag, src, loadOnce) {
60
- loadOnce = loadOnce || false;
60
+ const isLoad = loadOnce || false;
61
61
  if (!this._scripts[src]) {
62
62
  this._scripts[src] = { src, loaded: false };
63
63
  }
64
64
  return new Promise((resolve, _reject) => {
65
65
  // resolve if already loaded
66
- if (this._scripts[src].loaded && loadOnce) {
66
+ if (this._scripts[src].loaded && isLoad) {
67
+ // NOSONAR
67
68
  resolve({ src, loaded: true });
68
69
  }
69
70
  else {
@@ -124,13 +125,7 @@ class GoogleAnalyticsService {
124
125
  this.scriptLoader
125
126
  .loadScript('head', 'https://www.google-analytics.com/analytics.js', true)
126
127
  .then(() => {
127
- ga =
128
- ga ||
129
- // eslint-disable-next-line func-names
130
- function () {
131
- // eslint-disable-next-line prefer-rest-params
132
- (ga.q = ga.q || []).push(arguments);
133
- };
128
+ this.pushArgumentsGA();
134
129
  ga.l = Date.now();
135
130
  GoogleAnalyticsService.trackingId = config.integrations.google_analytics;
136
131
  ga('create', GoogleAnalyticsService.trackingId, 'auto');
@@ -138,11 +133,21 @@ class GoogleAnalyticsService {
138
133
  })
139
134
  .catch(error => {
140
135
  console.error('Error loading Google Analytics script:', error);
141
- reject(error);
136
+ reject(error instanceof Error ? error : new Error(error));
142
137
  });
143
138
  });
144
139
  });
145
140
  }
141
+ pushArgumentsGA() {
142
+ ga =
143
+ ga ||
144
+ // eslint-disable-next-line func-names
145
+ function () {
146
+ ga.q = ga.q = ga.q || [];
147
+ // eslint-disable-next-line prefer-rest-params
148
+ ga.q.push(arguments);
149
+ };
150
+ }
146
151
  subscribe() {
147
152
  if (!this.subscription) {
148
153
  this.subscription = this.router.events.subscribe(e => {
@@ -354,7 +359,7 @@ class BaseHttpService {
354
359
  const formData = new FormData();
355
360
  // eslint-disable-next-line no-restricted-syntax
356
361
  for (const item in data) {
357
- if (Object.prototype.hasOwnProperty.call(data, item)) {
362
+ if (Object.hasOwn(data, item)) {
358
363
  formData.append(item, data[item]);
359
364
  }
360
365
  }
@@ -874,7 +879,7 @@ class PermissionService {
874
879
  // Returning true if user has a given permission
875
880
  // E.g., Pages.Role.CloudOlive.SalesManager
876
881
  // or Pages.Beta or Pages.Alpha
877
- if (user['auth'] && user['auth']['granted'][permissionName]) {
882
+ if (user['auth']?.['granted'][permissionName]) {
878
883
  return true;
879
884
  }
880
885
  if (productKey) {
@@ -934,7 +939,6 @@ class PermissionService {
934
939
  return this.isUserSubscriptionOwner();
935
940
  }
936
941
  if (permission === PERMISSION_NAMES.SubscriptionSuperAdmin) {
937
- // SubscriptionAdmin: Product SuperAdmin
938
942
  return (this.isUserSubscriptionSuperAdmin() ||
939
943
  this.isUserSubscriptionSuperOwner() ||
940
944
  this.isSuperAdmin());
@@ -961,7 +965,8 @@ class PermissionService {
961
965
  expr += `${raw} `;
962
966
  }, this);
963
967
  // eslint-disable-next-line no-eval
964
- return eval(expr);
968
+ // NOSONAR: Trusted eval function is handled safely here
969
+ return eval(expr); // NOSONAR
965
970
  }
966
971
  getPermissionByRole(roleId) {
967
972
  return this.api.get(`/admin/role_permissions/${roleId}`);
@@ -1263,7 +1268,7 @@ class SubscriptionService {
1263
1268
  const formData = new FormData();
1264
1269
  // eslint-disable-next-line no-restricted-syntax
1265
1270
  for (const key in data) {
1266
- if (Object.prototype.hasOwnProperty.call(data, key)) {
1271
+ if (Object.hasOwn(data, key)) {
1267
1272
  formData.append(key, data[key]);
1268
1273
  }
1269
1274
  }
@@ -1279,7 +1284,7 @@ class SubscriptionService {
1279
1284
  const formData = new FormData();
1280
1285
  // eslint-disable-next-line no-restricted-syntax
1281
1286
  for (const key in data) {
1282
- if (Object.prototype.hasOwnProperty.call(data, key)) {
1287
+ if (Object.hasOwn(data, key)) {
1283
1288
  formData.append(key, data[key]);
1284
1289
  }
1285
1290
  }
@@ -1289,7 +1294,7 @@ class SubscriptionService {
1289
1294
  const formData = new FormData();
1290
1295
  // eslint-disable-next-line no-restricted-syntax
1291
1296
  for (const key in data) {
1292
- if (Object.prototype.hasOwnProperty.call(data, key)) {
1297
+ if (Object.hasOwn(data, key)) {
1293
1298
  formData.append(key, data[key]);
1294
1299
  }
1295
1300
  }
@@ -1425,7 +1430,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
1425
1430
 
1426
1431
  class ValidationService {
1427
1432
  static { this.CustomValidatorPatterns = {
1428
- StrongPassword: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/,
1433
+ StrongPassword: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])(?=.{8,})/,
1429
1434
  Year: '[0-9]{4}$'
1430
1435
  }; }
1431
1436
  /**
@@ -1748,9 +1753,13 @@ class NgbDateCustomParserFormatter extends NgbDateParserFormatter {
1748
1753
  'Nov',
1749
1754
  'Dec'
1750
1755
  ];
1751
- return date
1752
- ? `${isNumber(date.day) ? padNumber(date.day) : ''}-${isNumber(date.month) ? monthNames[date.month] : ''}-${date.year}`
1753
- : '';
1756
+ if (!date) {
1757
+ return '';
1758
+ }
1759
+ const day = isNumber(date.day) ? padNumber(date.day) : '';
1760
+ const month = isNumber(date.month) ? monthNames[date.month] : '';
1761
+ const year = date.year;
1762
+ return `${day}-${month}-${year}`;
1754
1763
  }
1755
1764
  dateFormatForPicker(date) {
1756
1765
  return {
@@ -2159,11 +2168,15 @@ class NotificationService {
2159
2168
  this.endpoint = 'notes_read';
2160
2169
  this.notificationSubject$ = new BehaviorSubject([]);
2161
2170
  }
2162
- getNotifications() {
2163
- return this.api.get('/notes?show_on_dashboard=true');
2171
+ getNotifications(paging) {
2172
+ return this.api.getWithParams(`/notes?show_on_dashboard=true`, {
2173
+ ...paging
2174
+ });
2164
2175
  }
2165
- getDismissedNotifications() {
2166
- return this.api.get('/notes?dismissed=true');
2176
+ getDismissedNotifications(paging) {
2177
+ return this.api.getWithParams(`/notes?dismissed=true`, {
2178
+ ...paging
2179
+ });
2167
2180
  }
2168
2181
  showNotifications(data) {
2169
2182
  this.notificationSubject$.next(data);
@@ -2306,13 +2319,13 @@ class SentryErrorHandler {
2306
2319
  tracesSampleRate: 0.1,
2307
2320
  beforeSend(event, hint) {
2308
2321
  // Check if the event is of type CloseEvent and ignore it
2309
- if (event && event.exception && event.exception.values) {
2322
+ if (event?.exception?.values) {
2310
2323
  event.exception.values = event.exception.values.filter(value => {
2311
2324
  // Update the condition based on the actual structure of the event
2312
2325
  return !(value.type === 'CloseEvent' || value.value.includes('CloseEvent'));
2313
2326
  });
2314
2327
  }
2315
- if (event && event.exception && event.exception.values) {
2328
+ if (event?.exception?.values) {
2316
2329
  event.exception.values = event.exception.values.filter(value => {
2317
2330
  // Check for the specific error message and ignore it
2318
2331
  return !(value.type === 'Error' &&
@@ -2320,43 +2333,41 @@ class SentryErrorHandler {
2320
2333
  });
2321
2334
  }
2322
2335
  // originates from vendor.js file
2323
- if (event && event.exception && event.exception.values) {
2336
+ if (event?.exception?.values) {
2324
2337
  const isJsonParsingError = event.exception.values.some(value => {
2325
2338
  return (value.type === 'SyntaxError' &&
2326
- value.value &&
2327
- value.value.includes("expected ':' after property name in"));
2339
+ value?.value?.includes("expected ':' after property name in"));
2328
2340
  });
2329
2341
  if (isJsonParsingError) {
2330
2342
  return null;
2331
2343
  }
2332
2344
  }
2333
2345
  // Check if the event is a ChunkLoadError and ignore it (it could be because of poor network)
2334
- if (event && event.exception && event.exception.values) {
2346
+ if (event?.exception?.values) {
2335
2347
  event.exception.values = event.exception.values.filter(value => {
2336
2348
  return !(value.type === 'ChunkLoadError' ||
2337
2349
  value.value.includes('ChunkLoadError: Loading chunk'));
2338
2350
  });
2339
2351
  }
2340
2352
  // Check if the event is a script loading error and ignore it
2341
- if (event && event.exception && event.exception.values) {
2353
+ if (event?.exception?.values) {
2342
2354
  event.exception.values = event.exception.values.filter(value => {
2343
2355
  return !(value.type === 'Error' &&
2344
2356
  value.value.includes('Could not load "util"'));
2345
2357
  });
2346
2358
  }
2347
2359
  // Check if the event is a timeout error and ignore it
2348
- if (event && event.exception && event.exception.values) {
2360
+ if (event?.exception?.values) {
2349
2361
  event.exception.values = event.exception.values.filter(value => {
2350
2362
  return !(value.type === 'Error' &&
2351
2363
  value.value.includes('Error loading plotly.js library from'));
2352
2364
  });
2353
2365
  }
2354
2366
  // Check if the event is related to cross-origin frame access
2355
- if (event && event.exception && event.exception.values) {
2367
+ if (event?.exception?.values) {
2356
2368
  const isCrossOriginFrameError = event.exception.values.some(value => {
2357
2369
  return (value.type === 'SecurityError' &&
2358
- value.value &&
2359
- value.value.includes("Failed to read a named property 'navigator' from 'Window': Blocked a frame with origin"));
2370
+ value?.value?.includes("Failed to read a named property 'navigator' from 'Window': Blocked a frame with origin"));
2360
2371
  });
2361
2372
  if (isCrossOriginFrameError) {
2362
2373
  // Exclude cross-origin frame errors from being reported to Sentry
@@ -2364,7 +2375,7 @@ class SentryErrorHandler {
2364
2375
  }
2365
2376
  }
2366
2377
  // Check if the event has an exception and values array
2367
- if (event && event.exception && event.exception.values) {
2378
+ if (event?.exception?.values) {
2368
2379
  // Filter out events generated by TryCatch and GlobalHandlers
2369
2380
  event.exception.values = event.exception.values.filter(value => {
2370
2381
  const mechanism = value.mechanism;
@@ -2459,125 +2470,146 @@ class SentryErrorHandler {
2459
2470
  return;
2460
2471
  }
2461
2472
  }
2473
+ this.handleExceptionError(incomingError);
2474
+ }
2475
+ handleExceptionError(incomingError) {
2462
2476
  if (incomingError) {
2463
2477
  let error = incomingError; // The actual error to log
2464
2478
  while ('originalError' in error && error.originalError instanceof Error) {
2465
2479
  this.logToConsole(error);
2466
2480
  error = error.originalError;
2467
2481
  }
2468
- // Exclude specific errors
2469
- if (error instanceof HttpErrorResponse) {
2470
- if (error.status === StatusCodes.NOT_FOUND) {
2471
- console.warn('Excluded 404 error:', error);
2472
- return; // Skip logging to Sentry
2473
- }
2474
- if (error.status === 0 && error.statusText === 'Unknown Error') {
2475
- // Handle network-related errors differently or suppress them
2476
- console.warn('Network-related error:', error);
2477
- return; // Don't rethrow the error
2478
- }
2479
- let { message } = error;
2480
- if (!message) {
2481
- try {
2482
- message = JSON.stringify(error);
2483
- }
2484
- catch (e) {
2485
- message = error.toString();
2486
- console.log(e);
2487
- }
2488
- }
2489
- error = new Error(`Got HttpErrorResponse on URL ${error.url} message: ${message}`);
2482
+ this.extractOriginalError(error, incomingError);
2483
+ }
2484
+ }
2485
+ extractOriginalError(error, incomingError) {
2486
+ // Exclude specific errors
2487
+ if (error instanceof HttpErrorResponse) {
2488
+ if (error.status === StatusCodes.NOT_FOUND) {
2489
+ console.warn('Excluded 404 error:', error);
2490
+ return; // Skip logging to Sentry
2490
2491
  }
2491
- // Handle non-HttpErrorResponse cases
2492
- if (typeof error === 'object' && 'message' in error) {
2493
- if (error instanceof HttpErrorResponse) {
2494
- if (error.status !== StatusCodes.UNAUTHORIZED) {
2495
- error = new Error(`Object captured as exception: ${error}`);
2496
- }
2492
+ if (error.status === 0 && error.statusText === 'Unknown Error') {
2493
+ // Handle network-related errors differently or suppress them
2494
+ console.warn('Network-related error:', error);
2495
+ return; // Don't rethrow the error
2496
+ }
2497
+ let { message } = error;
2498
+ if (!message) {
2499
+ try {
2500
+ message = JSON.stringify(error);
2501
+ }
2502
+ catch (e) {
2503
+ message = error.toString();
2504
+ console.log(e);
2497
2505
  }
2498
- // Exclude reporting 401 errors
2499
2506
  }
2500
- // Ensure all errors have a proper message
2501
- if (!(error instanceof Error) || !error.message) {
2502
- const defaultMessage = 'Captured an unlabeled event';
2503
- if (error && 'isTrusted' in error) {
2504
- console.warn('Ignored isTrusted browser event:', error);
2505
- return;
2507
+ error = new Error(`Got HttpErrorResponse on URL ${error.url} message: ${message}`);
2508
+ }
2509
+ this.handleNonHttpErrorResponse(error);
2510
+ // Ensure all errors have a proper message
2511
+ this.errorMessageFormatter(error);
2512
+ // Existing Sentry initialization logic
2513
+ this.sentryIntilization(error, incomingError);
2514
+ }
2515
+ handleNonHttpErrorResponse(error) {
2516
+ if (typeof error === 'object' && 'message' in error) {
2517
+ if (error instanceof HttpErrorResponse) {
2518
+ if (error.status !== StatusCodes.UNAUTHORIZED) {
2519
+ error = new Error(`Object captured as exception: ${error}`); // NOSONAR
2506
2520
  }
2507
- const errorDetails = error
2508
- ? JSON.stringify(error)
2509
- : 'No more additional error info';
2510
- const enhancedErrorMessage = `${defaultMessage} | Original error detail: ${errorDetails}`;
2511
- error = new Error(enhancedErrorMessage);
2512
2521
  }
2513
- // Existing Sentry initialization logic
2514
- if (!SentryErrorHandler.sentryInitialized) {
2515
- this.initializeSentryAsync()
2516
- .then(() => {
2517
- this.logToSentry(error);
2518
- throw incomingError;
2519
- })
2520
- .catch(err => {
2521
- console.error('Error initializing Sentry:', err);
2522
- this.logToConsole(error);
2523
- });
2522
+ // Exclude reporting 401 errors
2523
+ }
2524
+ }
2525
+ errorMessageFormatter(error) {
2526
+ if (!(error instanceof Error) || !error.message) {
2527
+ const defaultMessage = 'Captured an unlabeled event';
2528
+ if (error && 'isTrusted' in error) {
2529
+ console.warn('Ignored isTrusted browser event:', error);
2530
+ return;
2524
2531
  }
2525
- else {
2532
+ const errorDetails = error ? JSON.stringify(error) : 'No more additional error info';
2533
+ const enhancedErrorMessage = `${defaultMessage} | Original error detail: ${errorDetails}`;
2534
+ error = new Error(enhancedErrorMessage); // NOSONAR
2535
+ }
2536
+ }
2537
+ sentryIntilization(error, incomingError) {
2538
+ if (!SentryErrorHandler.sentryInitialized) {
2539
+ this.initializeSentryAsync()
2540
+ .then(() => {
2526
2541
  this.logToSentry(error);
2527
- }
2542
+ throw incomingError;
2543
+ })
2544
+ .catch(err => {
2545
+ console.error('Error initializing Sentry:', err);
2546
+ this.logToConsole(error);
2547
+ });
2548
+ }
2549
+ else {
2550
+ this.logToSentry(error);
2528
2551
  }
2529
2552
  }
2530
2553
  logToSentry(error) {
2531
2554
  try {
2532
2555
  const user = SentryErrorHandler.user;
2533
- Sentry.withScope(scope => {
2534
- // Appends user details for sentry log
2535
- scope.setUser({
2536
- ...user
2537
- });
2538
- // Ensure error is properly formatted
2539
- if (error instanceof Error && error.message) {
2540
- Sentry.captureException(error);
2541
- }
2542
- else if (typeof error === 'object' && error !== null) {
2543
- // If it's an object but not a standard Error, attempt to log its properties safely
2544
- let errorMessage = 'Captured non-standard error with no message';
2545
- // Try to extract any message-like property safely
2546
- if ('message' in error) {
2547
- errorMessage = `Error message: ${error.message}`;
2548
- }
2549
- else {
2550
- // Attempt to capture key properties safely
2551
- try {
2552
- errorMessage = `Captured non-standard error: ${JSON.stringify(error, Object.getOwnPropertyNames(error))}`;
2553
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2554
- }
2555
- catch (jsonError) {
2556
- errorMessage = `Captured non-standard error with serialization issue: ${jsonError.message}`;
2557
- }
2558
- }
2559
- // Create a new Error object with the enhanced message
2560
- const errorObject = new Error(errorMessage);
2561
- Sentry.captureException(errorObject);
2562
- }
2563
- else {
2564
- const defaultMessage = 'Captured an unlabeled event';
2565
- if (error && 'isTrusted' in error) {
2566
- console.warn('Ignored isTrusted browser event:', error);
2567
- return;
2568
- }
2569
- const errorDetails = error ? JSON.stringify(error) : 'No additional error info';
2570
- const enhancedErrorMessage = `${defaultMessage} | Original error details: ${errorDetails}`;
2571
- const enhancedError = new Error(enhancedErrorMessage);
2572
- Sentry.captureException(enhancedError);
2573
- }
2574
- });
2556
+ this.scopeWithSentry(error, user);
2575
2557
  }
2576
2558
  catch (e) {
2577
2559
  console.error('Unable to log the error to Sentry. An exception occurred:');
2578
2560
  console.error(e);
2579
2561
  }
2580
2562
  }
2563
+ scopeWithSentry(error, user) {
2564
+ Sentry.withScope(scope => {
2565
+ // Appends user details for sentry log
2566
+ scope.setUser({
2567
+ ...user
2568
+ });
2569
+ // Ensure error is properly formatted
2570
+ if (error instanceof Error && error.message) {
2571
+ Sentry.captureException(error);
2572
+ }
2573
+ else if (typeof error === 'object' && error !== null) {
2574
+ this.handleNonStandardError(error);
2575
+ }
2576
+ else {
2577
+ this.handleUnlabeledEvent(error);
2578
+ }
2579
+ });
2580
+ }
2581
+ handleNonStandardError(error) {
2582
+ // If it's an object but not a standard Error, attempt to log its properties safely
2583
+ let errorMessage = 'Captured non-standard error with no message'; // NOSONAR
2584
+ // Try to extract any message-like property safely
2585
+ if ('message' in error) {
2586
+ errorMessage = `Error message: ${String(error.message)}`;
2587
+ }
2588
+ else {
2589
+ // Attempt to capture key properties safely
2590
+ try {
2591
+ errorMessage = `Captured non-standard error: ${JSON.stringify(error, Object.getOwnPropertyNames(error))}`;
2592
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2593
+ }
2594
+ catch (jsonError) {
2595
+ errorMessage = `Captured non-standard error with serialization issue: ${jsonError.message}`;
2596
+ }
2597
+ }
2598
+ // Create a new Error object with the enhanced message
2599
+ const errorObject = new Error(errorMessage);
2600
+ Sentry.captureException(errorObject);
2601
+ }
2602
+ handleUnlabeledEvent(error) {
2603
+ const defaultMessage = 'Captured an unlabeled event';
2604
+ if (error && 'isTrusted' in error) {
2605
+ console.warn('Ignored isTrusted browser event:', error);
2606
+ return;
2607
+ }
2608
+ const errorDetails = error ? JSON.stringify(error) : 'No additional error info';
2609
+ const enhancedErrorMessage = `${defaultMessage} | Original error details: ${errorDetails}`;
2610
+ const enhancedError = new Error(enhancedErrorMessage);
2611
+ Sentry.captureException(enhancedError);
2612
+ }
2581
2613
  logToConsole(error) {
2582
2614
  // Attempt to print in the console
2583
2615
  try {