@tracelog/lib 0.12.0 → 0.12.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.
@@ -831,6 +831,11 @@ declare global {
831
831
  }
832
832
  }
833
833
 
834
+ /**
835
+ * Consolidated configuration constants for TraceLog
836
+ * This file centralizes all timing, limits, browser, and initialization constants
837
+ */
838
+ declare const DEFAULT_SESSION_TIMEOUT: number;
834
839
  declare const MAX_CUSTOM_EVENT_NAME_LENGTH = 120;
835
840
  declare const MAX_CUSTOM_EVENT_STRING_SIZE: number;
836
841
  declare const MAX_CUSTOM_EVENT_KEYS = 10;
@@ -900,18 +905,7 @@ declare const SESSION_ANALYTICS: {
900
905
  readonly MEDIUM_SESSION_THRESHOLD_MS: number;
901
906
  readonly LONG_SESSION_THRESHOLD_MS: number;
902
907
  readonly MAX_REALISTIC_SESSION_DURATION_MS: number;
903
- };
904
- declare const DEVICE_ANALYTICS: {
905
- readonly MOBILE_MAX_WIDTH: 768;
906
- readonly TABLET_MAX_WIDTH: 1024;
907
- readonly MOBILE_PERFORMANCE_FACTOR: 1.5;
908
- readonly TABLET_PERFORMANCE_FACTOR: 1.2;
909
- };
910
- declare const CONTENT_ANALYTICS: {
911
- readonly MIN_TEXT_LENGTH_FOR_ANALYSIS: 10;
912
- readonly MIN_CLICKS_FOR_HOT_ELEMENT: 10;
913
- readonly MIN_SCROLL_COMPLETION_PERCENT: 80;
914
- readonly MIN_TIME_ON_PAGE_FOR_READ_MS: number;
908
+ readonly MIN_EVENTS_FOR_DURATION: 2;
915
909
  };
916
910
  declare const INSIGHT_THRESHOLDS: {
917
911
  readonly SIGNIFICANT_CHANGE_PERCENT: 20;
@@ -923,20 +917,6 @@ declare const INSIGHT_THRESHOLDS: {
923
917
  readonly HIGH_ERROR_RATE_PERCENT: 5;
924
918
  readonly CRITICAL_ERROR_RATE_PERCENT: 10;
925
919
  };
926
- declare const TEMPORAL_ANALYSIS: {
927
- readonly SHORT_TERM_TREND_HOURS: 24;
928
- readonly MEDIUM_TERM_TREND_DAYS: 7;
929
- readonly LONG_TERM_TREND_DAYS: 30;
930
- readonly MIN_DATA_POINTS_FOR_TREND: 5;
931
- readonly WEEKLY_PATTERN_MIN_WEEKS: 4;
932
- readonly DAILY_PATTERN_MIN_DAYS: 14;
933
- };
934
- declare const SEGMENTATION_ANALYTICS: {
935
- readonly MIN_SEGMENT_SIZE: 10;
936
- readonly MIN_COHORT_SIZE: 5;
937
- readonly COHORT_ANALYSIS_DAYS: readonly [1, 3, 7, 14, 30];
938
- readonly MIN_FUNNEL_EVENTS: 20;
939
- };
940
920
  declare const ANALYTICS_QUERY_LIMITS: {
941
921
  readonly DEFAULT_EVENTS_LIMIT: 5;
942
922
  readonly DEFAULT_SESSIONS_LIMIT: 5;
@@ -945,14 +925,6 @@ declare const ANALYTICS_QUERY_LIMITS: {
945
925
  readonly MAX_TIME_RANGE_DAYS: 365;
946
926
  readonly ANALYTICS_BATCH_SIZE: 1000;
947
927
  };
948
- declare const ANOMALY_DETECTION: {
949
- readonly ANOMALY_THRESHOLD_SIGMA: 2.5;
950
- readonly STRONG_ANOMALY_THRESHOLD_SIGMA: 3;
951
- readonly TRAFFIC_DROP_ALERT_PERCENT: -30;
952
- readonly TRAFFIC_SPIKE_ALERT_PERCENT: 200;
953
- readonly MIN_BASELINE_DAYS: 7;
954
- readonly MIN_EVENTS_FOR_ANOMALY_DETECTION: 50;
955
- };
956
928
  declare const SPECIAL_PAGE_URLS: {
957
929
  readonly PAGE_URL_EXCLUDED: "excluded";
958
930
  readonly PAGE_URL_UNKNOWN: "unknown";
@@ -965,6 +937,7 @@ declare const tracelog: {
965
937
  off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
966
938
  isInitialized: () => boolean;
967
939
  destroy: () => void;
940
+ setQaMode: (enabled: boolean) => void;
968
941
  };
969
942
 
970
- export { ANALYTICS_QUERY_LIMITS, ANOMALY_DETECTION, AppConfigValidationError, CONTENT_ANALYTICS, type ClickCoordinates, type ClickData, type ClickTrackingElementData, type Config, type CustomEventData, DEFAULT_WEB_VITALS_MODE, DEVICE_ANALYTICS, DeviceType, ENGAGEMENT_THRESHOLDS, type EmitterCallback, EmitterEvent, type EmitterMap, type ErrorData, ErrorType, type EventData, EventType, type EventsQueue, INSIGHT_THRESHOLDS, InitializationTimeoutError, IntegrationValidationError, type LogLevel, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, type MetadataType, Mode, PII_PATTERNS, type PageViewData, PermanentError, type PersistedEventsQueue, type PrimaryScrollEvent, SEGMENTATION_ANALYTICS, SESSION_ANALYTICS, SPECIAL_PAGE_URLS, SamplingRateValidationError, type ScrollData, ScrollDirection, type SecondaryScrollEvent, type SessionEndReason, SessionTimeoutValidationError, SpecialApiUrl, type State, TEMPORAL_ANALYSIS, type TraceLogTestBridge, TraceLogValidationError, type UTM, type ViewportConfig, type ViewportElement, type ViewportEventData, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, type WebVitalType, type WebVitalsData, type WebVitalsMode, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
943
+ export { ANALYTICS_QUERY_LIMITS, AppConfigValidationError, type ClickCoordinates, type ClickData, type ClickTrackingElementData, type Config, type CustomEventData, DEFAULT_SESSION_TIMEOUT, DEFAULT_WEB_VITALS_MODE, DeviceType, ENGAGEMENT_THRESHOLDS, type EmitterCallback, EmitterEvent, type EmitterMap, type ErrorData, ErrorType, type EventData, EventType, type EventsQueue, INSIGHT_THRESHOLDS, InitializationTimeoutError, IntegrationValidationError, type LogLevel, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, type MetadataType, Mode, PII_PATTERNS, type PageViewData, PermanentError, type PersistedEventsQueue, type PrimaryScrollEvent, SESSION_ANALYTICS, SPECIAL_PAGE_URLS, SamplingRateValidationError, type ScrollData, ScrollDirection, type SecondaryScrollEvent, type SessionEndReason, SessionTimeoutValidationError, SpecialApiUrl, type State, type TraceLogTestBridge, TraceLogValidationError, type UTM, type ViewportConfig, type ViewportElement, type ViewportEventData, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, type WebVitalType, type WebVitalsData, type WebVitalsMode, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
@@ -831,6 +831,11 @@ declare global {
831
831
  }
832
832
  }
833
833
 
834
+ /**
835
+ * Consolidated configuration constants for TraceLog
836
+ * This file centralizes all timing, limits, browser, and initialization constants
837
+ */
838
+ declare const DEFAULT_SESSION_TIMEOUT: number;
834
839
  declare const MAX_CUSTOM_EVENT_NAME_LENGTH = 120;
835
840
  declare const MAX_CUSTOM_EVENT_STRING_SIZE: number;
836
841
  declare const MAX_CUSTOM_EVENT_KEYS = 10;
@@ -900,18 +905,7 @@ declare const SESSION_ANALYTICS: {
900
905
  readonly MEDIUM_SESSION_THRESHOLD_MS: number;
901
906
  readonly LONG_SESSION_THRESHOLD_MS: number;
902
907
  readonly MAX_REALISTIC_SESSION_DURATION_MS: number;
903
- };
904
- declare const DEVICE_ANALYTICS: {
905
- readonly MOBILE_MAX_WIDTH: 768;
906
- readonly TABLET_MAX_WIDTH: 1024;
907
- readonly MOBILE_PERFORMANCE_FACTOR: 1.5;
908
- readonly TABLET_PERFORMANCE_FACTOR: 1.2;
909
- };
910
- declare const CONTENT_ANALYTICS: {
911
- readonly MIN_TEXT_LENGTH_FOR_ANALYSIS: 10;
912
- readonly MIN_CLICKS_FOR_HOT_ELEMENT: 10;
913
- readonly MIN_SCROLL_COMPLETION_PERCENT: 80;
914
- readonly MIN_TIME_ON_PAGE_FOR_READ_MS: number;
908
+ readonly MIN_EVENTS_FOR_DURATION: 2;
915
909
  };
916
910
  declare const INSIGHT_THRESHOLDS: {
917
911
  readonly SIGNIFICANT_CHANGE_PERCENT: 20;
@@ -923,20 +917,6 @@ declare const INSIGHT_THRESHOLDS: {
923
917
  readonly HIGH_ERROR_RATE_PERCENT: 5;
924
918
  readonly CRITICAL_ERROR_RATE_PERCENT: 10;
925
919
  };
926
- declare const TEMPORAL_ANALYSIS: {
927
- readonly SHORT_TERM_TREND_HOURS: 24;
928
- readonly MEDIUM_TERM_TREND_DAYS: 7;
929
- readonly LONG_TERM_TREND_DAYS: 30;
930
- readonly MIN_DATA_POINTS_FOR_TREND: 5;
931
- readonly WEEKLY_PATTERN_MIN_WEEKS: 4;
932
- readonly DAILY_PATTERN_MIN_DAYS: 14;
933
- };
934
- declare const SEGMENTATION_ANALYTICS: {
935
- readonly MIN_SEGMENT_SIZE: 10;
936
- readonly MIN_COHORT_SIZE: 5;
937
- readonly COHORT_ANALYSIS_DAYS: readonly [1, 3, 7, 14, 30];
938
- readonly MIN_FUNNEL_EVENTS: 20;
939
- };
940
920
  declare const ANALYTICS_QUERY_LIMITS: {
941
921
  readonly DEFAULT_EVENTS_LIMIT: 5;
942
922
  readonly DEFAULT_SESSIONS_LIMIT: 5;
@@ -945,14 +925,6 @@ declare const ANALYTICS_QUERY_LIMITS: {
945
925
  readonly MAX_TIME_RANGE_DAYS: 365;
946
926
  readonly ANALYTICS_BATCH_SIZE: 1000;
947
927
  };
948
- declare const ANOMALY_DETECTION: {
949
- readonly ANOMALY_THRESHOLD_SIGMA: 2.5;
950
- readonly STRONG_ANOMALY_THRESHOLD_SIGMA: 3;
951
- readonly TRAFFIC_DROP_ALERT_PERCENT: -30;
952
- readonly TRAFFIC_SPIKE_ALERT_PERCENT: 200;
953
- readonly MIN_BASELINE_DAYS: 7;
954
- readonly MIN_EVENTS_FOR_ANOMALY_DETECTION: 50;
955
- };
956
928
  declare const SPECIAL_PAGE_URLS: {
957
929
  readonly PAGE_URL_EXCLUDED: "excluded";
958
930
  readonly PAGE_URL_UNKNOWN: "unknown";
@@ -965,6 +937,7 @@ declare const tracelog: {
965
937
  off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
966
938
  isInitialized: () => boolean;
967
939
  destroy: () => void;
940
+ setQaMode: (enabled: boolean) => void;
968
941
  };
969
942
 
970
- export { ANALYTICS_QUERY_LIMITS, ANOMALY_DETECTION, AppConfigValidationError, CONTENT_ANALYTICS, type ClickCoordinates, type ClickData, type ClickTrackingElementData, type Config, type CustomEventData, DEFAULT_WEB_VITALS_MODE, DEVICE_ANALYTICS, DeviceType, ENGAGEMENT_THRESHOLDS, type EmitterCallback, EmitterEvent, type EmitterMap, type ErrorData, ErrorType, type EventData, EventType, type EventsQueue, INSIGHT_THRESHOLDS, InitializationTimeoutError, IntegrationValidationError, type LogLevel, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, type MetadataType, Mode, PII_PATTERNS, type PageViewData, PermanentError, type PersistedEventsQueue, type PrimaryScrollEvent, SEGMENTATION_ANALYTICS, SESSION_ANALYTICS, SPECIAL_PAGE_URLS, SamplingRateValidationError, type ScrollData, ScrollDirection, type SecondaryScrollEvent, type SessionEndReason, SessionTimeoutValidationError, SpecialApiUrl, type State, TEMPORAL_ANALYSIS, type TraceLogTestBridge, TraceLogValidationError, type UTM, type ViewportConfig, type ViewportElement, type ViewportEventData, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, type WebVitalType, type WebVitalsData, type WebVitalsMode, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
943
+ export { ANALYTICS_QUERY_LIMITS, AppConfigValidationError, type ClickCoordinates, type ClickData, type ClickTrackingElementData, type Config, type CustomEventData, DEFAULT_SESSION_TIMEOUT, DEFAULT_WEB_VITALS_MODE, DeviceType, ENGAGEMENT_THRESHOLDS, type EmitterCallback, EmitterEvent, type EmitterMap, type ErrorData, ErrorType, type EventData, EventType, type EventsQueue, INSIGHT_THRESHOLDS, InitializationTimeoutError, IntegrationValidationError, type LogLevel, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, type MetadataType, Mode, PII_PATTERNS, type PageViewData, PermanentError, type PersistedEventsQueue, type PrimaryScrollEvent, SESSION_ANALYTICS, SPECIAL_PAGE_URLS, SamplingRateValidationError, type ScrollData, ScrollDirection, type SecondaryScrollEvent, type SessionEndReason, SessionTimeoutValidationError, SpecialApiUrl, type State, type TraceLogTestBridge, TraceLogValidationError, type UTM, type ViewportConfig, type ViewportElement, type ViewportEventData, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, type WebVitalType, type WebVitalsData, type WebVitalsMode, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
@@ -255,12 +255,25 @@ var formatLogMsg = (msg, error) => {
255
255
  const sanitizedMessage = error.message.replace(/\s+at\s+.*$/gm, "").replace(/\(.*?:\d+:\d+\)/g, "");
256
256
  return `[TraceLog] ${msg}: ${sanitizedMessage}`;
257
257
  }
258
- return `[TraceLog] ${msg}: ${error instanceof Error ? error.message : "Unknown error"}`;
258
+ if (error instanceof Error) {
259
+ return `[TraceLog] ${msg}: ${error.message}`;
260
+ }
261
+ if (typeof error === "string") {
262
+ return `[TraceLog] ${msg}: ${error}`;
263
+ }
264
+ if (typeof error === "object") {
265
+ try {
266
+ return `[TraceLog] ${msg}: ${JSON.stringify(error)}`;
267
+ } catch {
268
+ return `[TraceLog] ${msg}: [Unable to serialize error]`;
269
+ }
270
+ }
271
+ return `[TraceLog] ${msg}: ${String(error)}`;
259
272
  }
260
273
  return `[TraceLog] ${msg}`;
261
274
  };
262
275
  var log = (type, msg, extra) => {
263
- const { error, data, showToClient = false } = extra ?? {};
276
+ const { error, data, showToClient = false, style } = extra ?? {};
264
277
  const formattedMsg = error ? formatLogMsg(msg, error) : `[TraceLog] ${msg}`;
265
278
  const method = type === "error" ? "error" : type === "warn" ? "warn" : "log";
266
279
  const isProduction = process.env.NODE_ENV !== "development";
@@ -272,13 +285,21 @@ var log = (type, msg, extra) => {
272
285
  return;
273
286
  }
274
287
  }
275
- if (isProduction && data !== void 0) {
276
- const sanitizedData = sanitizeLogData(data);
277
- console[method](formattedMsg, sanitizedData);
278
- } else if (data !== void 0) {
279
- console[method](formattedMsg, data);
288
+ const hasStyle = style !== void 0 && style !== "";
289
+ const styledMsg = hasStyle ? `%c${formattedMsg}` : formattedMsg;
290
+ if (data !== void 0) {
291
+ const sanitizedData = isProduction ? sanitizeLogData(data) : data;
292
+ if (hasStyle) {
293
+ console[method](styledMsg, style, sanitizedData);
294
+ } else {
295
+ console[method](styledMsg, sanitizedData);
296
+ }
280
297
  } else {
281
- console[method](formattedMsg);
298
+ if (hasStyle) {
299
+ console[method](styledMsg, style);
300
+ } else {
301
+ console[method](styledMsg);
302
+ }
282
303
  }
283
304
  };
284
305
  var sanitizeLogData = (data) => {
@@ -288,6 +309,14 @@ var sanitizeLogData = (data) => {
288
309
  const lowerKey = key.toLowerCase();
289
310
  if (sensitiveKeys.some((sensitiveKey) => lowerKey.includes(sensitiveKey))) {
290
311
  sanitized[key] = "[REDACTED]";
312
+ continue;
313
+ }
314
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
315
+ sanitized[key] = sanitizeLogData(value);
316
+ } else if (Array.isArray(value)) {
317
+ sanitized[key] = value.map(
318
+ (item) => item !== null && typeof item === "object" && !Array.isArray(item) ? sanitizeLogData(item) : item
319
+ );
291
320
  } else {
292
321
  sanitized[key] = value;
293
322
  }
@@ -335,10 +364,17 @@ var getDeviceType = () => {
335
364
  }
336
365
  };
337
366
 
367
+ // src/constants/app.constants.ts
368
+ var LOG_STYLE_ACTIVE = "background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;";
369
+ var LOG_STYLE_DISABLED = "background: #9e9e9e; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;";
370
+
338
371
  // src/constants/storage.constants.ts
339
372
  var STORAGE_BASE_KEY = "tlog";
340
373
  var QA_MODE_KEY = `${STORAGE_BASE_KEY}:qa_mode`;
341
374
  var USER_ID_KEY = `${STORAGE_BASE_KEY}:uid`;
375
+ var QA_MODE_URL_PARAM = "tlog_mode";
376
+ var QA_MODE_ENABLE_VALUE = "qa";
377
+ var QA_MODE_DISABLE_VALUE = "qa_off";
342
378
  var QUEUE_KEY = (id) => id ? `${STORAGE_BASE_KEY}:${id}:queue` : `${STORAGE_BASE_KEY}:queue`;
343
379
  var SESSION_STORAGE_KEY = (id) => id ? `${STORAGE_BASE_KEY}:${id}:session` : `${STORAGE_BASE_KEY}:session`;
344
380
  var BROADCAST_CHANNEL_NAME = (id) => id ? `${STORAGE_BASE_KEY}:${id}:broadcast` : `${STORAGE_BASE_KEY}:broadcast`;
@@ -428,32 +464,65 @@ var ERROR_BURST_BACKOFF_MS = 5e3;
428
464
  var PERMANENT_ERROR_LOG_THROTTLE_MS = 6e4;
429
465
 
430
466
  // src/utils/browser/qa-mode.utils.ts
431
- var QA_MODE_PARAM = "tlog_mode";
432
- var QA_MODE_VALUE = "qa";
433
467
  var detectQaMode = () => {
434
- const stored = sessionStorage.getItem(QA_MODE_KEY);
435
- if (stored === "true") {
436
- return true;
468
+ if (typeof window === "undefined" || typeof document === "undefined") {
469
+ return false;
437
470
  }
438
- const params = new URLSearchParams(window.location.search);
439
- const modeParam = params.get(QA_MODE_PARAM);
440
- const isQaMode = modeParam === QA_MODE_VALUE;
441
- if (isQaMode) {
442
- sessionStorage.setItem(QA_MODE_KEY, "true");
443
- params.delete(QA_MODE_PARAM);
444
- const newSearch = params.toString();
445
- const newUrl = `${window.location.pathname}${newSearch ? "?" + newSearch : ""}${window.location.hash}`;
446
- try {
447
- window.history.replaceState({}, "", newUrl);
448
- } catch (error) {
449
- log("warn", "History API not available, cannot replace URL", { error });
471
+ try {
472
+ const params = new URLSearchParams(window.location.search);
473
+ const urlParam = params.get(QA_MODE_URL_PARAM);
474
+ const storedState = sessionStorage.getItem(QA_MODE_KEY);
475
+ let newState = null;
476
+ if (urlParam === QA_MODE_ENABLE_VALUE) {
477
+ newState = true;
478
+ sessionStorage.setItem(QA_MODE_KEY, "true");
479
+ log("info", "QA Mode ACTIVE", {
480
+ showToClient: true,
481
+ style: LOG_STYLE_ACTIVE
482
+ });
483
+ } else if (urlParam === QA_MODE_DISABLE_VALUE) {
484
+ newState = false;
485
+ sessionStorage.removeItem(QA_MODE_KEY);
486
+ log("info", "QA Mode DISABLED", {
487
+ showToClient: true,
488
+ style: LOG_STYLE_DISABLED
489
+ });
450
490
  }
451
- console.log(
452
- "%c[TraceLog] QA Mode ACTIVE",
453
- "background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;"
454
- );
491
+ if (urlParam === QA_MODE_ENABLE_VALUE || urlParam === QA_MODE_DISABLE_VALUE) {
492
+ try {
493
+ params.delete(QA_MODE_URL_PARAM);
494
+ const search = params.toString();
495
+ const url = window.location.pathname + (search ? "?" + search : "") + window.location.hash;
496
+ window.history.replaceState({}, "", url);
497
+ } catch {
498
+ }
499
+ }
500
+ return newState ?? storedState === "true";
501
+ } catch {
502
+ return false;
503
+ }
504
+ };
505
+ var setQaMode = (enabled) => {
506
+ if (typeof window === "undefined" || typeof document === "undefined") {
507
+ return;
508
+ }
509
+ try {
510
+ if (enabled) {
511
+ sessionStorage.setItem(QA_MODE_KEY, "true");
512
+ log("info", "QA Mode ENABLED", {
513
+ showToClient: true,
514
+ style: LOG_STYLE_ACTIVE
515
+ });
516
+ } else {
517
+ sessionStorage.removeItem(QA_MODE_KEY);
518
+ log("info", "QA Mode DISABLED", {
519
+ showToClient: true,
520
+ style: LOG_STYLE_DISABLED
521
+ });
522
+ }
523
+ } catch {
524
+ log("warn", "Cannot set QA mode: sessionStorage unavailable");
455
525
  }
456
- return isQaMode;
457
526
  };
458
527
 
459
528
  // src/utils/browser/utm-params.utils.ts
@@ -1580,9 +1649,12 @@ var EventManager = class extends StateManager {
1580
1649
  return;
1581
1650
  }
1582
1651
  if (this.get("mode") === "qa" /* QA */ && eventType === "custom" /* CUSTOM */ && custom_event) {
1583
- console.log("[TraceLog] Event", {
1584
- name: custom_event.name,
1585
- ...custom_event.metadata && { metadata: custom_event.metadata }
1652
+ log("info", "Event", {
1653
+ showToClient: true,
1654
+ data: {
1655
+ name: custom_event.name,
1656
+ ...custom_event.metadata && { metadata: custom_event.metadata }
1657
+ }
1586
1658
  });
1587
1659
  this.emitEvent(payload);
1588
1660
  return;
@@ -3973,7 +4045,13 @@ var App = class extends StateManager {
3973
4045
  if (!this.managers.event) {
3974
4046
  return;
3975
4047
  }
3976
- const { valid, error, sanitizedMetadata } = isEventValid(name, metadata);
4048
+ let normalizedMetadata = metadata;
4049
+ if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
4050
+ if (Object.getPrototypeOf(metadata) !== Object.prototype) {
4051
+ normalizedMetadata = Object.assign({}, metadata);
4052
+ }
4053
+ }
4054
+ const { valid, error, sanitizedMetadata } = isEventValid(name, normalizedMetadata);
3977
4055
  if (!valid) {
3978
4056
  if (this.get("mode") === "qa" /* QA */) {
3979
4057
  throw new Error(`[TraceLog] Custom event "${name}" validation failed: ${error}`);
@@ -4358,6 +4436,12 @@ var __setAppInstance = (instance) => {
4358
4436
  }
4359
4437
  app = instance;
4360
4438
  };
4439
+ var setQaMode2 = (enabled) => {
4440
+ if (typeof window === "undefined" || typeof document === "undefined") {
4441
+ return;
4442
+ }
4443
+ setQaMode(enabled);
4444
+ };
4361
4445
  if (process.env.NODE_ENV === "development" && typeof window !== "undefined" && typeof document !== "undefined") {
4362
4446
  const injectTestingBridge = () => {
4363
4447
  window.__traceLogBridge = new TestBridge(isInitializing, isDestroying);
@@ -4387,23 +4471,10 @@ var SESSION_ANALYTICS = {
4387
4471
  SHORT_SESSION_THRESHOLD_MS: 30 * 1e3,
4388
4472
  MEDIUM_SESSION_THRESHOLD_MS: 5 * 60 * 1e3,
4389
4473
  LONG_SESSION_THRESHOLD_MS: 30 * 60 * 1e3,
4390
- MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1e3
4474
+ MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1e3,
4391
4475
  // Filter outliers
4392
- };
4393
- var DEVICE_ANALYTICS = {
4394
- MOBILE_MAX_WIDTH: 768,
4395
- TABLET_MAX_WIDTH: 1024,
4396
- MOBILE_PERFORMANCE_FACTOR: 1.5,
4397
- // Mobile typically 1.5x slower
4398
- TABLET_PERFORMANCE_FACTOR: 1.2
4399
- };
4400
- var CONTENT_ANALYTICS = {
4401
- MIN_TEXT_LENGTH_FOR_ANALYSIS: 10,
4402
- MIN_CLICKS_FOR_HOT_ELEMENT: 10,
4403
- // Popular element threshold
4404
- MIN_SCROLL_COMPLETION_PERCENT: 80,
4405
- // Page consumption threshold
4406
- MIN_TIME_ON_PAGE_FOR_READ_MS: 15 * 1e3
4476
+ MIN_EVENTS_FOR_DURATION: 2
4477
+ // Minimum events required to calculate session duration
4407
4478
  };
4408
4479
  var INSIGHT_THRESHOLDS = {
4409
4480
  SIGNIFICANT_CHANGE_PERCENT: 20,
@@ -4416,20 +4487,6 @@ var INSIGHT_THRESHOLDS = {
4416
4487
  HIGH_ERROR_RATE_PERCENT: 5,
4417
4488
  CRITICAL_ERROR_RATE_PERCENT: 10
4418
4489
  };
4419
- var TEMPORAL_ANALYSIS = {
4420
- SHORT_TERM_TREND_HOURS: 24,
4421
- MEDIUM_TERM_TREND_DAYS: 7,
4422
- LONG_TERM_TREND_DAYS: 30,
4423
- MIN_DATA_POINTS_FOR_TREND: 5,
4424
- WEEKLY_PATTERN_MIN_WEEKS: 4,
4425
- DAILY_PATTERN_MIN_DAYS: 14
4426
- };
4427
- var SEGMENTATION_ANALYTICS = {
4428
- MIN_SEGMENT_SIZE: 10,
4429
- MIN_COHORT_SIZE: 5,
4430
- COHORT_ANALYSIS_DAYS: [1, 3, 7, 14, 30],
4431
- MIN_FUNNEL_EVENTS: 20
4432
- };
4433
4490
  var ANALYTICS_QUERY_LIMITS = {
4434
4491
  DEFAULT_EVENTS_LIMIT: 5,
4435
4492
  DEFAULT_SESSIONS_LIMIT: 5,
@@ -4439,14 +4496,6 @@ var ANALYTICS_QUERY_LIMITS = {
4439
4496
  ANALYTICS_BATCH_SIZE: 1e3
4440
4497
  // For historical analysis
4441
4498
  };
4442
- var ANOMALY_DETECTION = {
4443
- ANOMALY_THRESHOLD_SIGMA: 2.5,
4444
- STRONG_ANOMALY_THRESHOLD_SIGMA: 3,
4445
- TRAFFIC_DROP_ALERT_PERCENT: -30,
4446
- TRAFFIC_SPIKE_ALERT_PERCENT: 200,
4447
- MIN_BASELINE_DAYS: 7,
4448
- MIN_EVENTS_FOR_ANOMALY_DETECTION: 50
4449
- };
4450
4499
  var SPECIAL_PAGE_URLS = {
4451
4500
  PAGE_URL_EXCLUDED: "excluded",
4452
4501
  PAGE_URL_UNKNOWN: "unknown"
@@ -4459,9 +4508,10 @@ var tracelog = {
4459
4508
  on,
4460
4509
  off,
4461
4510
  isInitialized,
4462
- destroy
4511
+ destroy,
4512
+ setQaMode: setQaMode2
4463
4513
  };
4464
4514
 
4465
- export { ANALYTICS_QUERY_LIMITS, ANOMALY_DETECTION, AppConfigValidationError, CONTENT_ANALYTICS, DEFAULT_WEB_VITALS_MODE, DEVICE_ANALYTICS, DeviceType, ENGAGEMENT_THRESHOLDS, EmitterEvent, ErrorType, EventType, INSIGHT_THRESHOLDS, InitializationTimeoutError, IntegrationValidationError, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, Mode, PII_PATTERNS, PermanentError, SEGMENTATION_ANALYTICS, SESSION_ANALYTICS, SPECIAL_PAGE_URLS, SamplingRateValidationError, ScrollDirection, SessionTimeoutValidationError, SpecialApiUrl, TEMPORAL_ANALYSIS, TraceLogValidationError, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
4515
+ export { ANALYTICS_QUERY_LIMITS, AppConfigValidationError, DEFAULT_SESSION_TIMEOUT, DEFAULT_WEB_VITALS_MODE, DeviceType, ENGAGEMENT_THRESHOLDS, EmitterEvent, ErrorType, EventType, INSIGHT_THRESHOLDS, InitializationTimeoutError, IntegrationValidationError, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_METADATA_NESTING_DEPTH, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, Mode, PII_PATTERNS, PermanentError, SESSION_ANALYTICS, SPECIAL_PAGE_URLS, SamplingRateValidationError, ScrollDirection, SessionTimeoutValidationError, SpecialApiUrl, TraceLogValidationError, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, getWebVitalsThresholds, isPrimaryScrollEvent, isSecondaryScrollEvent, tracelog };
4466
4516
  //# sourceMappingURL=public-api.js.map
4467
4517
  //# sourceMappingURL=public-api.js.map