@tracelog/lib 0.10.0 → 0.11.1

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 (124) hide show
  1. package/README.md +128 -407
  2. package/dist/browser/tracelog.esm.js +1173 -771
  3. package/dist/browser/tracelog.esm.js.map +1 -1
  4. package/dist/browser/tracelog.js +2 -2
  5. package/dist/browser/tracelog.js.map +1 -1
  6. package/dist/cjs/app.d.ts +2 -0
  7. package/dist/cjs/app.d.ts.map +1 -1
  8. package/dist/cjs/app.js +5 -0
  9. package/dist/cjs/app.js.map +1 -1
  10. package/dist/cjs/constants/config.constants.d.ts +26 -1
  11. package/dist/cjs/constants/config.constants.d.ts.map +1 -1
  12. package/dist/cjs/constants/config.constants.js +30 -3
  13. package/dist/cjs/constants/config.constants.js.map +1 -1
  14. package/dist/cjs/constants/error.constants.d.ts +15 -0
  15. package/dist/cjs/constants/error.constants.d.ts.map +1 -1
  16. package/dist/cjs/constants/error.constants.js +19 -1
  17. package/dist/cjs/constants/error.constants.js.map +1 -1
  18. package/dist/cjs/handlers/click.handler.d.ts +15 -0
  19. package/dist/cjs/handlers/click.handler.d.ts.map +1 -1
  20. package/dist/cjs/handlers/click.handler.js +69 -0
  21. package/dist/cjs/handlers/click.handler.js.map +1 -1
  22. package/dist/cjs/handlers/error.handler.d.ts +7 -0
  23. package/dist/cjs/handlers/error.handler.d.ts.map +1 -1
  24. package/dist/cjs/handlers/error.handler.js +35 -0
  25. package/dist/cjs/handlers/error.handler.js.map +1 -1
  26. package/dist/cjs/handlers/page-view.handler.d.ts +1 -0
  27. package/dist/cjs/handlers/page-view.handler.d.ts.map +1 -1
  28. package/dist/cjs/handlers/page-view.handler.js +11 -0
  29. package/dist/cjs/handlers/page-view.handler.js.map +1 -1
  30. package/dist/cjs/handlers/performance.handler.js +5 -5
  31. package/dist/cjs/handlers/performance.handler.js.map +1 -1
  32. package/dist/cjs/handlers/viewport.handler.d.ts +44 -0
  33. package/dist/cjs/handlers/viewport.handler.d.ts.map +1 -0
  34. package/dist/cjs/handlers/viewport.handler.js +286 -0
  35. package/dist/cjs/handlers/viewport.handler.js.map +1 -0
  36. package/dist/cjs/managers/event.manager.d.ts +23 -3
  37. package/dist/cjs/managers/event.manager.d.ts.map +1 -1
  38. package/dist/cjs/managers/event.manager.js +166 -10
  39. package/dist/cjs/managers/event.manager.js.map +1 -1
  40. package/dist/cjs/managers/sender.manager.d.ts.map +1 -1
  41. package/dist/cjs/managers/sender.manager.js +12 -0
  42. package/dist/cjs/managers/sender.manager.js.map +1 -1
  43. package/dist/cjs/types/config.types.d.ts +9 -0
  44. package/dist/cjs/types/config.types.d.ts.map +1 -1
  45. package/dist/cjs/types/config.types.js.map +1 -1
  46. package/dist/cjs/types/event.types.d.ts +140 -16
  47. package/dist/cjs/types/event.types.d.ts.map +1 -1
  48. package/dist/cjs/types/event.types.js +23 -9
  49. package/dist/cjs/types/event.types.js.map +1 -1
  50. package/dist/cjs/types/index.d.ts +2 -0
  51. package/dist/cjs/types/index.d.ts.map +1 -1
  52. package/dist/cjs/types/index.js +2 -0
  53. package/dist/cjs/types/index.js.map +1 -1
  54. package/dist/cjs/types/scroll.types.d.ts +16 -0
  55. package/dist/cjs/types/scroll.types.d.ts.map +1 -0
  56. package/dist/cjs/types/scroll.types.js +12 -0
  57. package/dist/cjs/types/scroll.types.js.map +1 -0
  58. package/dist/cjs/types/viewport.types.d.ts +55 -0
  59. package/dist/cjs/types/viewport.types.d.ts.map +1 -0
  60. package/dist/cjs/types/viewport.types.js +3 -0
  61. package/dist/cjs/types/viewport.types.js.map +1 -0
  62. package/dist/cjs/utils/validations/config-validations.utils.d.ts.map +1 -1
  63. package/dist/cjs/utils/validations/config-validations.utils.js +91 -0
  64. package/dist/cjs/utils/validations/config-validations.utils.js.map +1 -1
  65. package/dist/esm/app.d.ts +2 -0
  66. package/dist/esm/app.d.ts.map +1 -1
  67. package/dist/esm/app.js +5 -0
  68. package/dist/esm/app.js.map +1 -1
  69. package/dist/esm/constants/config.constants.d.ts +26 -1
  70. package/dist/esm/constants/config.constants.d.ts.map +1 -1
  71. package/dist/esm/constants/config.constants.js +28 -1
  72. package/dist/esm/constants/config.constants.js.map +1 -1
  73. package/dist/esm/constants/error.constants.d.ts +15 -0
  74. package/dist/esm/constants/error.constants.d.ts.map +1 -1
  75. package/dist/esm/constants/error.constants.js +18 -0
  76. package/dist/esm/constants/error.constants.js.map +1 -1
  77. package/dist/esm/handlers/click.handler.d.ts +15 -0
  78. package/dist/esm/handlers/click.handler.d.ts.map +1 -1
  79. package/dist/esm/handlers/click.handler.js +70 -1
  80. package/dist/esm/handlers/click.handler.js.map +1 -1
  81. package/dist/esm/handlers/error.handler.d.ts +7 -0
  82. package/dist/esm/handlers/error.handler.d.ts.map +1 -1
  83. package/dist/esm/handlers/error.handler.js +36 -1
  84. package/dist/esm/handlers/error.handler.js.map +1 -1
  85. package/dist/esm/handlers/page-view.handler.d.ts +1 -0
  86. package/dist/esm/handlers/page-view.handler.d.ts.map +1 -1
  87. package/dist/esm/handlers/page-view.handler.js +11 -0
  88. package/dist/esm/handlers/page-view.handler.js.map +1 -1
  89. package/dist/esm/handlers/performance.handler.js +5 -5
  90. package/dist/esm/handlers/performance.handler.js.map +1 -1
  91. package/dist/esm/handlers/viewport.handler.d.ts +44 -0
  92. package/dist/esm/handlers/viewport.handler.d.ts.map +1 -0
  93. package/dist/esm/handlers/viewport.handler.js +282 -0
  94. package/dist/esm/handlers/viewport.handler.js.map +1 -0
  95. package/dist/esm/managers/event.manager.d.ts +23 -3
  96. package/dist/esm/managers/event.manager.d.ts.map +1 -1
  97. package/dist/esm/managers/event.manager.js +167 -11
  98. package/dist/esm/managers/event.manager.js.map +1 -1
  99. package/dist/esm/managers/sender.manager.d.ts.map +1 -1
  100. package/dist/esm/managers/sender.manager.js +13 -1
  101. package/dist/esm/managers/sender.manager.js.map +1 -1
  102. package/dist/esm/types/config.types.d.ts +9 -0
  103. package/dist/esm/types/config.types.d.ts.map +1 -1
  104. package/dist/esm/types/config.types.js.map +1 -1
  105. package/dist/esm/types/event.types.d.ts +140 -16
  106. package/dist/esm/types/event.types.d.ts.map +1 -1
  107. package/dist/esm/types/event.types.js +23 -7
  108. package/dist/esm/types/event.types.js.map +1 -1
  109. package/dist/esm/types/index.d.ts +2 -0
  110. package/dist/esm/types/index.d.ts.map +1 -1
  111. package/dist/esm/types/index.js +2 -0
  112. package/dist/esm/types/index.js.map +1 -1
  113. package/dist/esm/types/scroll.types.d.ts +16 -0
  114. package/dist/esm/types/scroll.types.d.ts.map +1 -0
  115. package/dist/esm/types/scroll.types.js +8 -0
  116. package/dist/esm/types/scroll.types.js.map +1 -0
  117. package/dist/esm/types/viewport.types.d.ts +55 -0
  118. package/dist/esm/types/viewport.types.d.ts.map +1 -0
  119. package/dist/esm/types/viewport.types.js +2 -0
  120. package/dist/esm/types/viewport.types.js.map +1 -0
  121. package/dist/esm/utils/validations/config-validations.utils.d.ts.map +1 -1
  122. package/dist/esm/utils/validations/config-validations.utils.js +92 -1
  123. package/dist/esm/utils/validations/config-validations.utils.js.map +1 -1
  124. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
- const Ft = 120, Gt = 8192, $t = 10, zt = 10, Qt = 20, Bt = 1;
2
- const jt = 1e3, Xt = 500, Wt = 100;
3
- const A = "data-tlog", Pe = [
1
+ const jt = 120, Yt = 8192, Kt = 10, qt = 10, Zt = 20, Jt = 1;
2
+ const er = 1e3, tr = 500, rr = 100;
3
+ const v = "data-tlog", Ue = [
4
4
  "button",
5
5
  "a",
6
6
  'input[type="button"]',
@@ -32,7 +32,7 @@ const A = "data-tlog", Pe = [
32
32
  ".menu-item",
33
33
  "[data-testid]",
34
34
  '[tabindex="0"]'
35
- ], De = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"], ke = [
35
+ ], He = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"], xe = [
36
36
  "token",
37
37
  "auth",
38
38
  "key",
@@ -48,7 +48,7 @@ const A = "data-tlog", Pe = [
48
48
  "code",
49
49
  "otp"
50
50
  ];
51
- const S = {
51
+ const h = {
52
52
  INVALID_SESSION_TIMEOUT: "Session timeout must be between 30000ms (30 seconds) and 86400000ms (24 hours)",
53
53
  INVALID_SAMPLING_RATE: "Sampling rate must be between 0 and 1",
54
54
  INVALID_ERROR_SAMPLING_RATE: "Error sampling must be between 0 and 1",
@@ -58,8 +58,20 @@ const S = {
58
58
  INVALID_GLOBAL_METADATA: "Global metadata must be an object",
59
59
  INVALID_SENSITIVE_QUERY_PARAMS: "Sensitive query params must be an array of strings",
60
60
  INVALID_PRIMARY_SCROLL_SELECTOR: "Primary scroll selector must be a non-empty string",
61
- INVALID_PRIMARY_SCROLL_SELECTOR_SYNTAX: "Invalid CSS selector syntax for primaryScrollSelector"
62
- }, Ue = [
61
+ INVALID_PRIMARY_SCROLL_SELECTOR_SYNTAX: "Invalid CSS selector syntax for primaryScrollSelector",
62
+ INVALID_PAGE_VIEW_THROTTLE: "Page view throttle must be a non-negative number",
63
+ INVALID_CLICK_THROTTLE: "Click throttle must be a non-negative number",
64
+ INVALID_MAX_SAME_EVENT_PER_MINUTE: "Max same event per minute must be a positive number",
65
+ INVALID_VIEWPORT_CONFIG: "Viewport config must be an object",
66
+ INVALID_VIEWPORT_ELEMENTS: "Viewport elements must be a non-empty array",
67
+ INVALID_VIEWPORT_ELEMENT: "Each viewport element must have a valid selector string",
68
+ INVALID_VIEWPORT_ELEMENT_ID: "Viewport element id must be a non-empty string",
69
+ INVALID_VIEWPORT_ELEMENT_NAME: "Viewport element name must be a non-empty string",
70
+ INVALID_VIEWPORT_THRESHOLD: "Viewport threshold must be a number between 0 and 1",
71
+ INVALID_VIEWPORT_MIN_DWELL_TIME: "Viewport minDwellTime must be a non-negative number",
72
+ INVALID_VIEWPORT_COOLDOWN_PERIOD: "Viewport cooldownPeriod must be a non-negative number",
73
+ INVALID_VIEWPORT_MAX_TRACKED_ELEMENTS: "Viewport maxTrackedElements must be a positive number"
74
+ }, Fe = [
63
75
  /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
64
76
  /javascript:/gi,
65
77
  /on\w+\s*=/gi,
@@ -67,96 +79,95 @@ const S = {
67
79
  /<embed\b[^>]*>/gi,
68
80
  /<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi
69
81
  ];
70
- var Y = /* @__PURE__ */ ((s) => (s.Localhost = "localhost:8080", s.Fail = "localhost:9999", s))(Y || {}), T = /* @__PURE__ */ ((s) => (s.Mobile = "mobile", s.Tablet = "tablet", s.Desktop = "desktop", s.Unknown = "unknown", s))(T || {}), K = /* @__PURE__ */ ((s) => (s.EVENT = "event", s.QUEUE = "queue", s))(K || {});
71
- class M extends Error {
82
+ var q = /* @__PURE__ */ ((n) => (n.Localhost = "localhost:8080", n.Fail = "localhost:9999", n))(q || {}), w = /* @__PURE__ */ ((n) => (n.Mobile = "mobile", n.Tablet = "tablet", n.Desktop = "desktop", n.Unknown = "unknown", n))(w || {}), Z = /* @__PURE__ */ ((n) => (n.EVENT = "event", n.QUEUE = "queue", n))(Z || {});
83
+ class R extends Error {
72
84
  constructor(e, t) {
73
- super(e), this.statusCode = t, this.name = "PermanentError", Error.captureStackTrace && Error.captureStackTrace(this, M);
85
+ super(e), this.statusCode = t, this.name = "PermanentError", Error.captureStackTrace && Error.captureStackTrace(this, R);
74
86
  }
75
87
  }
76
- var d = /* @__PURE__ */ ((s) => (s.PAGE_VIEW = "page_view", s.CLICK = "click", s.SCROLL = "scroll", s.SESSION_START = "session_start", s.SESSION_END = "session_end", s.CUSTOM = "custom", s.WEB_VITALS = "web_vitals", s.ERROR = "error", s))(d || {}), U = /* @__PURE__ */ ((s) => (s.UP = "up", s.DOWN = "down", s))(U || {}), b = /* @__PURE__ */ ((s) => (s.JS_ERROR = "js_error", s.PROMISE_REJECTION = "promise_rejection", s))(b || {});
77
- function Yt(s) {
78
- return s.type === "scroll" && "scroll_data" in s && s.scroll_data.is_primary === !0;
88
+ var u = /* @__PURE__ */ ((n) => (n.PAGE_VIEW = "page_view", n.CLICK = "click", n.SCROLL = "scroll", n.SESSION_START = "session_start", n.SESSION_END = "session_end", n.CUSTOM = "custom", n.WEB_VITALS = "web_vitals", n.ERROR = "error", n.VIEWPORT_VISIBLE = "viewport_visible", n))(u || {}), H = /* @__PURE__ */ ((n) => (n.UP = "up", n.DOWN = "down", n))(H || {}), P = /* @__PURE__ */ ((n) => (n.JS_ERROR = "js_error", n.PROMISE_REJECTION = "promise_rejection", n))(P || {}), D = /* @__PURE__ */ ((n) => (n.QA = "qa", n))(D || {});
89
+ function nr(n) {
90
+ return n.type === u.SCROLL && "scroll_data" in n && n.scroll_data.is_primary === !0;
79
91
  }
80
- function Kt(s) {
81
- return s.type === "scroll" && "scroll_data" in s && s.scroll_data.is_primary === !1;
92
+ function sr(n) {
93
+ return n.type === u.SCROLL && "scroll_data" in n && n.scroll_data.is_primary === !1;
82
94
  }
83
- var C = /* @__PURE__ */ ((s) => (s.QA = "qa", s))(C || {});
84
- class O extends Error {
95
+ class V extends Error {
85
96
  constructor(e, t, r) {
86
97
  super(e), this.errorCode = t, this.layer = r, this.name = this.constructor.name, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
87
98
  }
88
99
  }
89
- class w extends O {
100
+ class E extends V {
90
101
  constructor(e, t = "config") {
91
102
  super(e, "APP_CONFIG_INVALID", t);
92
103
  }
93
104
  }
94
- class He extends O {
105
+ class Ge extends V {
95
106
  constructor(e, t = "config") {
96
107
  super(e, "SESSION_TIMEOUT_INVALID", t);
97
108
  }
98
109
  }
99
- class de extends O {
110
+ class he extends V {
100
111
  constructor(e, t = "config") {
101
112
  super(e, "SAMPLING_RATE_INVALID", t);
102
113
  }
103
114
  }
104
- class v extends O {
115
+ class M extends V {
105
116
  constructor(e, t = "config") {
106
117
  super(e, "INTEGRATION_INVALID", t);
107
118
  }
108
119
  }
109
- class qt extends O {
120
+ class ir extends V {
110
121
  constructor(e, t, r = "runtime") {
111
122
  super(e, "INITIALIZATION_TIMEOUT", r), this.timeoutMs = t;
112
123
  }
113
124
  }
114
- const xe = (s, e) => {
125
+ const We = (n, e) => {
115
126
  if (e) {
116
127
  if (e instanceof Error) {
117
128
  const t = e.message.replace(/\s+at\s+.*$/gm, "").replace(/\(.*?:\d+:\d+\)/g, "");
118
- return `[TraceLog] ${s}: ${t}`;
119
- }
120
- return `[TraceLog] ${s}: ${e instanceof Error ? e.message : "Unknown error"}`;
121
- }
122
- return `[TraceLog] ${s}`;
123
- }, l = (s, e, t) => {
124
- const { error: r, data: n, showToClient: i = !1 } = t ?? {}, a = r ? xe(e, r) : `[TraceLog] ${e}`, o = s === "error" ? "error" : s === "warn" ? "warn" : "log";
125
- if (!(s === "debug" || s === "info" && !i))
126
- if (n !== void 0) {
127
- const c = Ve(n);
128
- console[o](a, c);
129
- } else n !== void 0 ? console[o](a, n) : console[o](a);
130
- }, Ve = (s) => {
129
+ return `[TraceLog] ${n}: ${t}`;
130
+ }
131
+ return `[TraceLog] ${n}: ${e instanceof Error ? e.message : "Unknown error"}`;
132
+ }
133
+ return `[TraceLog] ${n}`;
134
+ }, a = (n, e, t) => {
135
+ const { error: r, data: s, showToClient: i = !1 } = t ?? {}, o = r ? We(e, r) : `[TraceLog] ${e}`, l = n === "error" ? "error" : n === "warn" ? "warn" : "log";
136
+ if (!(n === "debug" || n === "info" && !i))
137
+ if (s !== void 0) {
138
+ const c = Be(s);
139
+ console[l](o, c);
140
+ } else s !== void 0 ? console[l](o, s) : console[l](o);
141
+ }, Be = (n) => {
131
142
  const e = {}, t = ["token", "password", "secret", "key", "apikey", "api_key", "sessionid", "session_id"];
132
- for (const [r, n] of Object.entries(s)) {
143
+ for (const [r, s] of Object.entries(n)) {
133
144
  const i = r.toLowerCase();
134
- t.some((a) => i.includes(a)) ? e[r] = "[REDACTED]" : e[r] = n;
145
+ t.some((o) => i.includes(o)) ? e[r] = "[REDACTED]" : e[r] = s;
135
146
  }
136
147
  return e;
137
148
  };
138
- let q, ve;
139
- const Fe = () => {
140
- typeof window < "u" && !q && (q = window.matchMedia("(pointer: coarse)"), ve = window.matchMedia("(hover: none)"));
141
- }, Ge = () => {
149
+ let J, we;
150
+ const Xe = () => {
151
+ typeof window < "u" && !J && (J = window.matchMedia("(pointer: coarse)"), we = window.matchMedia("(hover: none)"));
152
+ }, $e = () => {
142
153
  try {
143
- const s = navigator;
144
- if (s.userAgentData && typeof s.userAgentData.mobile == "boolean")
145
- return s.userAgentData.platform && /ipad|tablet/i.test(s.userAgentData.platform) ? T.Tablet : s.userAgentData.mobile ? T.Mobile : T.Desktop;
146
- Fe();
147
- const e = window.innerWidth, t = q?.matches ?? !1, r = ve?.matches ?? !1, n = "ontouchstart" in window || navigator.maxTouchPoints > 0, i = navigator.userAgent.toLowerCase(), a = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(i), o = /tablet|ipad|android(?!.*mobile)/.test(i);
148
- return e <= 767 || a && n ? T.Mobile : e >= 768 && e <= 1024 || o || t && r && n ? T.Tablet : T.Desktop;
149
- } catch (s) {
150
- return l("warn", "Device detection failed, defaulting to desktop", { error: s }), T.Desktop;
151
- }
152
- }, I = "tlog", he = `${I}:qa_mode`, $e = `${I}:uid`, ze = (s) => s ? `${I}:${s}:queue` : `${I}:queue`, Qe = (s) => s ? `${I}:${s}:session` : `${I}:session`, Be = (s) => s ? `${I}:${s}:broadcast` : `${I}:broadcast`, ye = {
154
+ const n = navigator;
155
+ if (n.userAgentData && typeof n.userAgentData.mobile == "boolean")
156
+ return n.userAgentData.platform && /ipad|tablet/i.test(n.userAgentData.platform) ? w.Tablet : n.userAgentData.mobile ? w.Mobile : w.Desktop;
157
+ Xe();
158
+ const e = window.innerWidth, t = J?.matches ?? !1, r = we?.matches ?? !1, s = "ontouchstart" in window || navigator.maxTouchPoints > 0, i = navigator.userAgent.toLowerCase(), o = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(i), l = /tablet|ipad|android(?!.*mobile)/.test(i);
159
+ return e <= 767 || o && s ? w.Mobile : e >= 768 && e <= 1024 || l || t && r && s ? w.Tablet : w.Desktop;
160
+ } catch (n) {
161
+ return a("warn", "Device detection failed, defaulting to desktop", { error: n }), w.Desktop;
162
+ }
163
+ }, y = "tlog", Ee = `${y}:qa_mode`, ze = `${y}:uid`, Qe = (n) => n ? `${y}:${n}:queue` : `${y}:queue`, je = (n) => n ? `${y}:${n}:session` : `${y}:session`, Ye = (n) => n ? `${y}:${n}:broadcast` : `${y}:broadcast`, ye = {
153
164
  LCP: 4e3,
154
165
  FCP: 1800,
155
166
  CLS: 0.25,
156
167
  INP: 200,
157
168
  TTFB: 800,
158
169
  LONG_TASK: 50
159
- }, je = 1e3, ae = [
170
+ }, Ke = 1e3, le = [
160
171
  // Email addresses
161
172
  /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/gi,
162
173
  // US Phone numbers (various formats)
@@ -171,17 +182,17 @@ const Fe = () => {
171
182
  /Bearer\s+[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)?(?:\.[A-Za-z0-9_-]+)?/gi,
172
183
  // Passwords in connection strings (protocol://user:password@host)
173
184
  /:\/\/[^:/]+:([^@]+)@/gi
174
- ], fe = 500, ge = 5e3, H = 50, Xe = H * 2, Ae = 1, We = 6e4, Se = "tlog_mode", Ye = "qa", Ke = () => {
175
- if (sessionStorage.getItem(he) === "true")
185
+ ], fe = 500, ge = 5e3, x = 50, qe = x * 2, Le = 1, Ze = 1e3, Je = 10, me = 5e3, et = 6e4, Se = "tlog_mode", tt = "qa", rt = () => {
186
+ if (sessionStorage.getItem(Ee) === "true")
176
187
  return !0;
177
- const e = new URLSearchParams(window.location.search), r = e.get(Se) === Ye;
188
+ const e = new URLSearchParams(window.location.search), r = e.get(Se) === tt;
178
189
  if (r) {
179
- sessionStorage.setItem(he, "true"), e.delete(Se);
180
- const n = e.toString(), i = `${window.location.pathname}${n ? "?" + n : ""}${window.location.hash}`;
190
+ sessionStorage.setItem(Ee, "true"), e.delete(Se);
191
+ const s = e.toString(), i = `${window.location.pathname}${s ? "?" + s : ""}${window.location.hash}`;
181
192
  try {
182
193
  window.history.replaceState({}, "", i);
183
- } catch (a) {
184
- l("warn", "History API not available, cannot replace URL", { error: a });
194
+ } catch (o) {
195
+ a("warn", "History API not available, cannot replace URL", { error: o });
185
196
  }
186
197
  console.log(
187
198
  "%c[TraceLog] QA Mode ACTIVE",
@@ -189,20 +200,20 @@ const Fe = () => {
189
200
  );
190
201
  }
191
202
  return r;
192
- }, Ee = () => {
193
- const s = new URLSearchParams(window.location.search), e = {};
194
- return De.forEach((r) => {
195
- const n = s.get(r);
196
- if (n) {
203
+ }, _e = () => {
204
+ const n = new URLSearchParams(window.location.search), e = {};
205
+ return He.forEach((r) => {
206
+ const s = n.get(r);
207
+ if (s) {
197
208
  const i = r.split("utm_")[1];
198
- e[i] = n;
209
+ e[i] = s;
199
210
  }
200
211
  }), Object.keys(e).length ? e : void 0;
201
- }, qe = () => typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (s) => {
212
+ }, nt = () => typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (n) => {
202
213
  const e = Math.random() * 16 | 0;
203
- return (s === "x" ? e : e & 3 | 8).toString(16);
204
- }), Je = () => {
205
- const s = Date.now();
214
+ return (n === "x" ? e : e & 3 | 8).toString(16);
215
+ }), st = () => {
216
+ const n = Date.now();
206
217
  let e = "";
207
218
  try {
208
219
  if (typeof crypto < "u" && crypto.getRandomValues) {
@@ -211,169 +222,215 @@ const Fe = () => {
211
222
  }
212
223
  } catch {
213
224
  }
214
- return e || (e = Math.floor(Math.random() * 4294967295).toString(16).padStart(8, "0")), `${s}-${e}`;
215
- }, me = (s, e = !1) => {
225
+ return e || (e = Math.floor(Math.random() * 4294967295).toString(16).padStart(8, "0")), `${n}-${e}`;
226
+ }, Te = (n, e = !1) => {
216
227
  try {
217
- const t = new URL(s), r = t.protocol === "https:", n = t.protocol === "http:";
218
- return r || e && n;
228
+ const t = new URL(n), r = t.protocol === "https:", s = t.protocol === "http:";
229
+ return r || e && s;
219
230
  } catch {
220
231
  return !1;
221
232
  }
222
- }, Ze = (s) => {
223
- if (s.integrations?.tracelog?.projectId) {
224
- const n = new URL(window.location.href).hostname.split(".");
225
- if (n.length === 0)
233
+ }, it = (n) => {
234
+ if (n.integrations?.tracelog?.projectId) {
235
+ const s = new URL(window.location.href).hostname.split(".");
236
+ if (s.length === 0)
226
237
  throw new Error("Invalid URL");
227
- const i = s.integrations.tracelog.projectId, a = n.slice(-2).join("."), o = `https://${i}.${a}/collect`;
228
- if (!me(o))
238
+ const i = n.integrations.tracelog.projectId, o = s.slice(-2).join("."), l = `https://${i}.${o}/collect`;
239
+ if (!Te(l))
229
240
  throw new Error("Invalid URL");
230
- return o;
241
+ return l;
231
242
  }
232
- const e = s.integrations?.custom?.collectApiUrl;
243
+ const e = n.integrations?.custom?.collectApiUrl;
233
244
  if (e) {
234
- const t = s.integrations?.custom?.allowHttp ?? !1;
235
- if (!me(e, t))
245
+ const t = n.integrations?.custom?.allowHttp ?? !1;
246
+ if (!Te(e, t))
236
247
  throw new Error("Invalid URL");
237
248
  return e;
238
249
  }
239
250
  return "";
240
- }, J = (s, e = []) => {
251
+ }, ee = (n, e = []) => {
241
252
  try {
242
- const t = new URL(s), r = t.searchParams, n = [.../* @__PURE__ */ new Set([...ke, ...e])];
253
+ const t = new URL(n), r = t.searchParams, s = [.../* @__PURE__ */ new Set([...xe, ...e])];
243
254
  let i = !1;
244
- const a = [];
245
- return n.forEach((c) => {
246
- r.has(c) && (r.delete(c), i = !0, a.push(c));
247
- }), !i && s.includes("?") ? s : (t.search = r.toString(), t.toString());
255
+ const o = [];
256
+ return s.forEach((c) => {
257
+ r.has(c) && (r.delete(c), i = !0, o.push(c));
258
+ }), !i && n.includes("?") ? n : (t.search = r.toString(), t.toString());
248
259
  } catch (t) {
249
- return l("warn", "URL normalization failed, returning original", { error: t, data: { url: s.slice(0, 100) } }), s;
260
+ return a("warn", "URL normalization failed, returning original", { error: t, data: { url: n.slice(0, 100) } }), n;
250
261
  }
251
- }, pe = (s) => {
252
- if (!s || typeof s != "string" || s.trim().length === 0)
262
+ }, pe = (n) => {
263
+ if (!n || typeof n != "string" || n.trim().length === 0)
253
264
  return "";
254
- let e = s;
255
- s.length > 1e3 && (e = s.slice(0, Math.max(0, 1e3)));
265
+ let e = n;
266
+ n.length > 1e3 && (e = n.slice(0, Math.max(0, 1e3)));
256
267
  let t = 0;
257
- for (const n of Ue) {
268
+ for (const s of Fe) {
258
269
  const i = e;
259
- e = e.replace(n, ""), i !== e && t++;
270
+ e = e.replace(s, ""), i !== e && t++;
260
271
  }
261
- return t > 0 && l("warn", "XSS patterns detected and removed", {
272
+ return t > 0 && a("warn", "XSS patterns detected and removed", {
262
273
  data: {
263
274
  patternMatches: t,
264
- originalValue: s.slice(0, 100)
275
+ originalValue: n.slice(0, 100)
265
276
  }
266
277
  }), e = e.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#x27;").replaceAll("/", "&#x2F;"), e.trim();
267
- }, Z = (s, e = 0) => {
268
- if (e > 3 || s == null)
278
+ }, te = (n, e = 0) => {
279
+ if (e > 3 || n == null)
269
280
  return null;
270
- if (typeof s == "string")
271
- return pe(s);
272
- if (typeof s == "number")
273
- return !Number.isFinite(s) || s < -Number.MAX_SAFE_INTEGER || s > Number.MAX_SAFE_INTEGER ? 0 : s;
274
- if (typeof s == "boolean")
275
- return s;
276
- if (Array.isArray(s))
277
- return s.slice(0, 100).map((n) => Z(n, e + 1)).filter((n) => n !== null);
278
- if (typeof s == "object") {
279
- const t = {}, n = Object.entries(s).slice(0, 20);
280
- for (const [i, a] of n) {
281
- const o = pe(i);
282
- if (o) {
283
- const c = Z(a, e + 1);
284
- c !== null && (t[o] = c);
281
+ if (typeof n == "string")
282
+ return pe(n);
283
+ if (typeof n == "number")
284
+ return !Number.isFinite(n) || n < -Number.MAX_SAFE_INTEGER || n > Number.MAX_SAFE_INTEGER ? 0 : n;
285
+ if (typeof n == "boolean")
286
+ return n;
287
+ if (Array.isArray(n))
288
+ return n.slice(0, 100).map((s) => te(s, e + 1)).filter((s) => s !== null);
289
+ if (typeof n == "object") {
290
+ const t = {}, s = Object.entries(n).slice(0, 20);
291
+ for (const [i, o] of s) {
292
+ const l = pe(i);
293
+ if (l) {
294
+ const c = te(o, e + 1);
295
+ c !== null && (t[l] = c);
285
296
  }
286
297
  }
287
298
  return t;
288
299
  }
289
300
  return null;
290
- }, et = (s) => {
291
- if (typeof s != "object" || s === null)
301
+ }, ot = (n) => {
302
+ if (typeof n != "object" || n === null)
292
303
  return {};
293
304
  try {
294
- const e = Z(s);
305
+ const e = te(n);
295
306
  return typeof e == "object" && e !== null ? e : {};
296
307
  } catch (e) {
297
308
  const t = e instanceof Error ? e.message : String(e);
298
309
  throw new Error(`[TraceLog] Metadata sanitization failed: ${t}`);
299
310
  }
300
- }, tt = (s) => {
301
- if (s !== void 0 && (s === null || typeof s != "object"))
302
- throw new w("Configuration must be an object", "config");
303
- if (s) {
304
- if (s.sessionTimeout !== void 0 && (typeof s.sessionTimeout != "number" || s.sessionTimeout < 3e4 || s.sessionTimeout > 864e5))
305
- throw new He(S.INVALID_SESSION_TIMEOUT, "config");
306
- if (s.globalMetadata !== void 0 && (typeof s.globalMetadata != "object" || s.globalMetadata === null))
307
- throw new w(S.INVALID_GLOBAL_METADATA, "config");
308
- if (s.integrations && rt(s.integrations), s.sensitiveQueryParams !== void 0) {
309
- if (!Array.isArray(s.sensitiveQueryParams))
310
- throw new w(S.INVALID_SENSITIVE_QUERY_PARAMS, "config");
311
- for (const e of s.sensitiveQueryParams)
311
+ }, at = (n) => {
312
+ if (n !== void 0 && (n === null || typeof n != "object"))
313
+ throw new E("Configuration must be an object", "config");
314
+ if (n) {
315
+ if (n.sessionTimeout !== void 0 && (typeof n.sessionTimeout != "number" || n.sessionTimeout < 3e4 || n.sessionTimeout > 864e5))
316
+ throw new Ge(h.INVALID_SESSION_TIMEOUT, "config");
317
+ if (n.globalMetadata !== void 0 && (typeof n.globalMetadata != "object" || n.globalMetadata === null))
318
+ throw new E(h.INVALID_GLOBAL_METADATA, "config");
319
+ if (n.integrations && ct(n.integrations), n.sensitiveQueryParams !== void 0) {
320
+ if (!Array.isArray(n.sensitiveQueryParams))
321
+ throw new E(h.INVALID_SENSITIVE_QUERY_PARAMS, "config");
322
+ for (const e of n.sensitiveQueryParams)
312
323
  if (typeof e != "string")
313
- throw new w("All sensitive query params must be strings", "config");
314
- }
315
- if (s.errorSampling !== void 0 && (typeof s.errorSampling != "number" || s.errorSampling < 0 || s.errorSampling > 1))
316
- throw new de(S.INVALID_ERROR_SAMPLING_RATE, "config");
317
- if (s.samplingRate !== void 0 && (typeof s.samplingRate != "number" || s.samplingRate < 0 || s.samplingRate > 1))
318
- throw new de(S.INVALID_SAMPLING_RATE, "config");
319
- if (s.primaryScrollSelector !== void 0) {
320
- if (typeof s.primaryScrollSelector != "string" || !s.primaryScrollSelector.trim())
321
- throw new w(S.INVALID_PRIMARY_SCROLL_SELECTOR, "config");
322
- if (s.primaryScrollSelector !== "window")
324
+ throw new E("All sensitive query params must be strings", "config");
325
+ }
326
+ if (n.errorSampling !== void 0 && (typeof n.errorSampling != "number" || n.errorSampling < 0 || n.errorSampling > 1))
327
+ throw new he(h.INVALID_ERROR_SAMPLING_RATE, "config");
328
+ if (n.samplingRate !== void 0 && (typeof n.samplingRate != "number" || n.samplingRate < 0 || n.samplingRate > 1))
329
+ throw new he(h.INVALID_SAMPLING_RATE, "config");
330
+ if (n.primaryScrollSelector !== void 0) {
331
+ if (typeof n.primaryScrollSelector != "string" || !n.primaryScrollSelector.trim())
332
+ throw new E(h.INVALID_PRIMARY_SCROLL_SELECTOR, "config");
333
+ if (n.primaryScrollSelector !== "window")
323
334
  try {
324
- document.querySelector(s.primaryScrollSelector);
335
+ document.querySelector(n.primaryScrollSelector);
325
336
  } catch {
326
- throw new w(
327
- `${S.INVALID_PRIMARY_SCROLL_SELECTOR_SYNTAX}: "${s.primaryScrollSelector}"`,
337
+ throw new E(
338
+ `${h.INVALID_PRIMARY_SCROLL_SELECTOR_SYNTAX}: "${n.primaryScrollSelector}"`,
328
339
  "config"
329
340
  );
330
341
  }
331
342
  }
332
- }
333
- }, rt = (s) => {
334
- if (s) {
335
- if (s.tracelog && (!s.tracelog.projectId || typeof s.tracelog.projectId != "string" || s.tracelog.projectId.trim() === ""))
336
- throw new v(S.INVALID_TRACELOG_PROJECT_ID, "config");
337
- if (s.custom) {
338
- if (!s.custom.collectApiUrl || typeof s.custom.collectApiUrl != "string" || s.custom.collectApiUrl.trim() === "")
339
- throw new v(S.INVALID_CUSTOM_API_URL, "config");
340
- if (s.custom.allowHttp !== void 0 && typeof s.custom.allowHttp != "boolean")
341
- throw new v("allowHttp must be a boolean", "config");
342
- const e = s.custom.collectApiUrl.trim();
343
+ if (n.pageViewThrottleMs !== void 0 && (typeof n.pageViewThrottleMs != "number" || n.pageViewThrottleMs < 0))
344
+ throw new E(h.INVALID_PAGE_VIEW_THROTTLE, "config");
345
+ if (n.clickThrottleMs !== void 0 && (typeof n.clickThrottleMs != "number" || n.clickThrottleMs < 0))
346
+ throw new E(h.INVALID_CLICK_THROTTLE, "config");
347
+ if (n.maxSameEventPerMinute !== void 0 && (typeof n.maxSameEventPerMinute != "number" || n.maxSameEventPerMinute <= 0))
348
+ throw new E(h.INVALID_MAX_SAME_EVENT_PER_MINUTE, "config");
349
+ n.viewport !== void 0 && lt(n.viewport);
350
+ }
351
+ }, lt = (n) => {
352
+ if (typeof n != "object" || n === null)
353
+ throw new E(h.INVALID_VIEWPORT_CONFIG, "config");
354
+ if (!n.elements || !Array.isArray(n.elements))
355
+ throw new E(h.INVALID_VIEWPORT_ELEMENTS, "config");
356
+ if (n.elements.length === 0)
357
+ throw new E(h.INVALID_VIEWPORT_ELEMENTS, "config");
358
+ const e = /* @__PURE__ */ new Set();
359
+ for (const t of n.elements) {
360
+ if (!t.selector || typeof t.selector != "string" || !t.selector.trim())
361
+ throw new E(h.INVALID_VIEWPORT_ELEMENT, "config");
362
+ const r = t.selector.trim();
363
+ if (e.has(r))
364
+ throw new E(
365
+ `Duplicate viewport selector found: "${r}". Each selector should appear only once.`,
366
+ "config"
367
+ );
368
+ if (e.add(r), t.id !== void 0 && (typeof t.id != "string" || !t.id.trim()))
369
+ throw new E(h.INVALID_VIEWPORT_ELEMENT_ID, "config");
370
+ if (t.name !== void 0 && (typeof t.name != "string" || !t.name.trim()))
371
+ throw new E(h.INVALID_VIEWPORT_ELEMENT_NAME, "config");
372
+ }
373
+ if (n.threshold !== void 0 && (typeof n.threshold != "number" || n.threshold < 0 || n.threshold > 1))
374
+ throw new E(h.INVALID_VIEWPORT_THRESHOLD, "config");
375
+ if (n.minDwellTime !== void 0 && (typeof n.minDwellTime != "number" || n.minDwellTime < 0))
376
+ throw new E(h.INVALID_VIEWPORT_MIN_DWELL_TIME, "config");
377
+ if (n.cooldownPeriod !== void 0 && (typeof n.cooldownPeriod != "number" || n.cooldownPeriod < 0))
378
+ throw new E(h.INVALID_VIEWPORT_COOLDOWN_PERIOD, "config");
379
+ if (n.maxTrackedElements !== void 0 && (typeof n.maxTrackedElements != "number" || n.maxTrackedElements <= 0))
380
+ throw new E(h.INVALID_VIEWPORT_MAX_TRACKED_ELEMENTS, "config");
381
+ }, ct = (n) => {
382
+ if (n) {
383
+ if (n.tracelog && (!n.tracelog.projectId || typeof n.tracelog.projectId != "string" || n.tracelog.projectId.trim() === ""))
384
+ throw new M(h.INVALID_TRACELOG_PROJECT_ID, "config");
385
+ if (n.custom) {
386
+ if (!n.custom.collectApiUrl || typeof n.custom.collectApiUrl != "string" || n.custom.collectApiUrl.trim() === "")
387
+ throw new M(h.INVALID_CUSTOM_API_URL, "config");
388
+ if (n.custom.allowHttp !== void 0 && typeof n.custom.allowHttp != "boolean")
389
+ throw new M("allowHttp must be a boolean", "config");
390
+ const e = n.custom.collectApiUrl.trim();
343
391
  if (!e.startsWith("http://") && !e.startsWith("https://"))
344
- throw new v('Custom API URL must start with "http://" or "https://"', "config");
345
- if (!(s.custom.allowHttp ?? !1) && e.startsWith("http://"))
346
- throw new v(
392
+ throw new M('Custom API URL must start with "http://" or "https://"', "config");
393
+ if (!(n.custom.allowHttp ?? !1) && e.startsWith("http://"))
394
+ throw new M(
347
395
  "Custom API URL must use HTTPS in production. Set allowHttp: true in integration config to allow HTTP (not recommended)",
348
396
  "config"
349
397
  );
350
398
  }
351
- if (s.googleAnalytics) {
352
- if (!s.googleAnalytics.measurementId || typeof s.googleAnalytics.measurementId != "string" || s.googleAnalytics.measurementId.trim() === "")
353
- throw new v(S.INVALID_GOOGLE_ANALYTICS_ID, "config");
354
- if (!s.googleAnalytics.measurementId.trim().match(/^(G-|UA-)/))
355
- throw new v('Google Analytics measurement ID must start with "G-" or "UA-"', "config");
399
+ if (n.googleAnalytics) {
400
+ if (!n.googleAnalytics.measurementId || typeof n.googleAnalytics.measurementId != "string" || n.googleAnalytics.measurementId.trim() === "")
401
+ throw new M(h.INVALID_GOOGLE_ANALYTICS_ID, "config");
402
+ if (!n.googleAnalytics.measurementId.trim().match(/^(G-|UA-)/))
403
+ throw new M('Google Analytics measurement ID must start with "G-" or "UA-"', "config");
356
404
  }
357
405
  }
358
- }, st = (s) => {
359
- tt(s);
406
+ }, ut = (n) => {
407
+ at(n);
360
408
  const e = {
361
- ...s ?? {},
362
- sessionTimeout: s?.sessionTimeout ?? 9e5,
363
- globalMetadata: s?.globalMetadata ?? {},
364
- sensitiveQueryParams: s?.sensitiveQueryParams ?? [],
365
- errorSampling: s?.errorSampling ?? Ae,
366
- samplingRate: s?.samplingRate ?? 1
409
+ ...n ?? {},
410
+ sessionTimeout: n?.sessionTimeout ?? 9e5,
411
+ globalMetadata: n?.globalMetadata ?? {},
412
+ sensitiveQueryParams: n?.sensitiveQueryParams ?? [],
413
+ errorSampling: n?.errorSampling ?? Le,
414
+ samplingRate: n?.samplingRate ?? 1,
415
+ pageViewThrottleMs: n?.pageViewThrottleMs ?? 1e3,
416
+ clickThrottleMs: n?.clickThrottleMs ?? 300,
417
+ maxSameEventPerMinute: n?.maxSameEventPerMinute ?? 60
367
418
  };
368
419
  return e.integrations?.custom && (e.integrations.custom = {
369
420
  ...e.integrations.custom,
370
421
  allowHttp: e.integrations.custom.allowHttp ?? !1
422
+ }), e.viewport && (e.viewport = {
423
+ ...e.viewport,
424
+ threshold: e.viewport.threshold ?? 0.5,
425
+ minDwellTime: e.viewport.minDwellTime ?? 2e3,
426
+ cooldownPeriod: e.viewport.cooldownPeriod ?? 6e4,
427
+ maxTrackedElements: e.viewport.maxTrackedElements ?? 100
371
428
  }), e;
372
- }, nt = (s) => {
373
- if (typeof s == "string")
429
+ }, dt = (n) => {
430
+ if (typeof n == "string")
374
431
  return !0;
375
- if (typeof s == "object" && s !== null && !Array.isArray(s)) {
376
- const e = Object.entries(s);
432
+ if (typeof n == "object" && n !== null && !Array.isArray(n)) {
433
+ const e = Object.entries(n);
377
434
  if (e.length > 20)
378
435
  return !1;
379
436
  for (const [, t] of e) {
@@ -386,10 +443,10 @@ const Fe = () => {
386
443
  return !0;
387
444
  }
388
445
  return !1;
389
- }, we = (s, e = 0) => {
390
- if (typeof s != "object" || s === null || e > 1)
446
+ }, Me = (n, e = 0) => {
447
+ if (typeof n != "object" || n === null || e > 1)
391
448
  return !1;
392
- for (const t of Object.values(s)) {
449
+ for (const t of Object.values(n)) {
393
450
  if (t == null)
394
451
  continue;
395
452
  const r = typeof t;
@@ -398,14 +455,14 @@ const Fe = () => {
398
455
  if (t.length === 0)
399
456
  continue;
400
457
  if (typeof t[0] == "string") {
401
- if (!t.every((a) => typeof a == "string"))
458
+ if (!t.every((o) => typeof o == "string"))
402
459
  return !1;
403
- } else if (!t.every((a) => nt(a)))
460
+ } else if (!t.every((o) => dt(o)))
404
461
  return !1;
405
462
  continue;
406
463
  }
407
464
  if (r === "object" && e === 0) {
408
- if (!we(t, e + 1))
465
+ if (!Me(t, e + 1))
409
466
  return !1;
410
467
  continue;
411
468
  }
@@ -413,27 +470,27 @@ const Fe = () => {
413
470
  }
414
471
  }
415
472
  return !0;
416
- }, it = (s) => typeof s != "string" ? {
473
+ }, ht = (n) => typeof n != "string" ? {
417
474
  valid: !1,
418
475
  error: "Event name must be a string"
419
- } : s.length === 0 ? {
476
+ } : n.length === 0 ? {
420
477
  valid: !1,
421
478
  error: "Event name cannot be empty"
422
- } : s.length > 120 ? {
479
+ } : n.length > 120 ? {
423
480
  valid: !1,
424
481
  error: "Event name is too long (max 120 characters)"
425
- } : s.includes("<") || s.includes(">") || s.includes("&") ? {
482
+ } : n.includes("<") || n.includes(">") || n.includes("&") ? {
426
483
  valid: !1,
427
484
  error: "Event name contains invalid characters"
428
- } : ["constructor", "prototype", "__proto__", "eval", "function", "var", "let", "const"].includes(s.toLowerCase()) ? {
485
+ } : ["constructor", "prototype", "__proto__", "eval", "function", "var", "let", "const"].includes(n.toLowerCase()) ? {
429
486
  valid: !1,
430
487
  error: "Event name cannot be a reserved word"
431
- } : { valid: !0 }, _e = (s, e, t) => {
432
- const r = et(e), n = `${t} "${s}" metadata error`;
433
- if (!we(r))
488
+ } : { valid: !0 }, Ie = (n, e, t) => {
489
+ const r = ot(e), s = `${t} "${n}" metadata error`;
490
+ if (!Me(r))
434
491
  return {
435
492
  valid: !1,
436
- error: `${n}: object has invalid types. Valid types are string, number, boolean or string arrays.`
493
+ error: `${s}: object has invalid types. Valid types are string, number, boolean or string arrays.`
437
494
  };
438
495
  let i;
439
496
  try {
@@ -441,86 +498,86 @@ const Fe = () => {
441
498
  } catch {
442
499
  return {
443
500
  valid: !1,
444
- error: `${n}: object contains circular references or cannot be serialized.`
501
+ error: `${s}: object contains circular references or cannot be serialized.`
445
502
  };
446
503
  }
447
504
  if (i.length > 8192)
448
505
  return {
449
506
  valid: !1,
450
- error: `${n}: object is too large (max ${8192 / 1024} KB).`
507
+ error: `${s}: object is too large (max ${8192 / 1024} KB).`
451
508
  };
452
509
  if (Object.keys(r).length > 10)
453
510
  return {
454
511
  valid: !1,
455
- error: `${n}: object has too many keys (max 10 keys).`
512
+ error: `${s}: object has too many keys (max 10 keys).`
456
513
  };
457
- for (const [o, c] of Object.entries(r)) {
514
+ for (const [l, c] of Object.entries(r)) {
458
515
  if (Array.isArray(c)) {
459
516
  if (c.length > 10)
460
517
  return {
461
518
  valid: !1,
462
- error: `${n}: array property "${o}" is too large (max 10 items).`
519
+ error: `${s}: array property "${l}" is too large (max 10 items).`
463
520
  };
464
- for (const u of c)
465
- if (typeof u == "string" && u.length > 500)
521
+ for (const d of c)
522
+ if (typeof d == "string" && d.length > 500)
466
523
  return {
467
524
  valid: !1,
468
- error: `${n}: array property "${o}" contains strings that are too long (max 500 characters).`
525
+ error: `${s}: array property "${l}" contains strings that are too long (max 500 characters).`
469
526
  };
470
527
  }
471
528
  if (typeof c == "string" && c.length > 1e3)
472
529
  return {
473
530
  valid: !1,
474
- error: `${n}: property "${o}" is too long (max 1000 characters).`
531
+ error: `${s}: property "${l}" is too long (max 1000 characters).`
475
532
  };
476
533
  }
477
534
  return {
478
535
  valid: !0,
479
536
  sanitizedMetadata: r
480
537
  };
481
- }, at = (s, e, t) => {
538
+ }, Et = (n, e, t) => {
482
539
  if (Array.isArray(e)) {
483
- const r = [], n = `${t} "${s}" metadata error`;
540
+ const r = [], s = `${t} "${n}" metadata error`;
484
541
  for (let i = 0; i < e.length; i++) {
485
- const a = e[i];
486
- if (typeof a != "object" || a === null || Array.isArray(a))
542
+ const o = e[i];
543
+ if (typeof o != "object" || o === null || Array.isArray(o))
487
544
  return {
488
545
  valid: !1,
489
- error: `${n}: array item at index ${i} must be an object.`
546
+ error: `${s}: array item at index ${i} must be an object.`
490
547
  };
491
- const o = _e(s, a, t);
492
- if (!o.valid)
548
+ const l = Ie(n, o, t);
549
+ if (!l.valid)
493
550
  return {
494
551
  valid: !1,
495
- error: `${n}: array item at index ${i} is invalid: ${o.error}`
552
+ error: `${s}: array item at index ${i} is invalid: ${l.error}`
496
553
  };
497
- o.sanitizedMetadata && r.push(o.sanitizedMetadata);
554
+ l.sanitizedMetadata && r.push(l.sanitizedMetadata);
498
555
  }
499
556
  return {
500
557
  valid: !0,
501
558
  sanitizedMetadata: r
502
559
  };
503
560
  }
504
- return _e(s, e, t);
505
- }, ot = (s, e) => {
506
- const t = it(s);
561
+ return Ie(n, e, t);
562
+ }, ft = (n, e) => {
563
+ const t = ht(n);
507
564
  if (!t.valid)
508
- return l("error", "Event name validation failed", {
565
+ return a("error", "Event name validation failed", {
509
566
  showToClient: !0,
510
- data: { eventName: s, error: t.error }
567
+ data: { eventName: n, error: t.error }
511
568
  }), t;
512
569
  if (!e)
513
570
  return { valid: !0 };
514
- const r = at(s, e, "customEvent");
515
- return r.valid || l("error", "Event metadata validation failed", {
571
+ const r = Et(n, e, "customEvent");
572
+ return r.valid || a("error", "Event metadata validation failed", {
516
573
  showToClient: !0,
517
574
  data: {
518
- eventName: s,
575
+ eventName: n,
519
576
  error: r.error
520
577
  }
521
578
  }), r;
522
579
  };
523
- class lt {
580
+ class gt {
524
581
  listeners = /* @__PURE__ */ new Map();
525
582
  on(e, t) {
526
583
  this.listeners.has(e) || this.listeners.set(e, []), this.listeners.get(e).push(t);
@@ -528,14 +585,14 @@ class lt {
528
585
  off(e, t) {
529
586
  const r = this.listeners.get(e);
530
587
  if (r) {
531
- const n = r.indexOf(t);
532
- n > -1 && r.splice(n, 1);
588
+ const s = r.indexOf(t);
589
+ s > -1 && r.splice(s, 1);
533
590
  }
534
591
  }
535
592
  emit(e, t) {
536
593
  const r = this.listeners.get(e);
537
- r && r.forEach((n) => {
538
- n(t);
594
+ r && r.forEach((s) => {
595
+ s(t);
539
596
  });
540
597
  }
541
598
  removeAllListeners() {
@@ -543,7 +600,7 @@ class lt {
543
600
  }
544
601
  }
545
602
  const j = {};
546
- class g {
603
+ class S {
547
604
  get(e) {
548
605
  return j[e];
549
606
  }
@@ -554,7 +611,7 @@ class g {
554
611
  return { ...j };
555
612
  }
556
613
  }
557
- class ct extends g {
614
+ class mt extends S {
558
615
  storeManager;
559
616
  lastPermanentErrorLog = null;
560
617
  constructor(e) {
@@ -562,10 +619,10 @@ class ct extends g {
562
619
  }
563
620
  getQueueStorageKey() {
564
621
  const e = this.get("userId") || "anonymous";
565
- return ze(e);
622
+ return Qe(e);
566
623
  }
567
624
  sendEventsQueueSync(e) {
568
- return this.shouldSkipSend() ? !0 : this.get("config")?.integrations?.custom?.collectApiUrl === Y.Fail ? (l("warn", "Fail mode: simulating network failure (sync)", {
625
+ return this.shouldSkipSend() ? !0 : this.get("config")?.integrations?.custom?.collectApiUrl === q.Fail ? (a("warn", "Fail mode: simulating network failure (sync)", {
569
626
  data: { events: e.events.length }
570
627
  }), !1) : this.sendQueueSyncInternal(e);
571
628
  }
@@ -574,7 +631,7 @@ class ct extends g {
574
631
  const r = await this.send(e);
575
632
  return r ? (this.clearPersistedEvents(), t?.onSuccess?.(e.events.length, e.events, e)) : (this.persistEvents(e), t?.onFailure?.()), r;
576
633
  } catch (r) {
577
- return r instanceof M ? (this.logPermanentError("Permanent error, not retrying", r), this.clearPersistedEvents(), t?.onFailure?.(), !1) : (this.persistEvents(e), t?.onFailure?.(), !1);
634
+ return r instanceof R ? (this.logPermanentError("Permanent error, not retrying", r), this.clearPersistedEvents(), t?.onFailure?.(), !1) : (this.persistEvents(e), t?.onFailure?.(), !1);
578
635
  }
579
636
  }
580
637
  async recoverPersistedEvents(e) {
@@ -587,11 +644,11 @@ class ct extends g {
587
644
  const r = this.createRecoveryBody(t);
588
645
  await this.send(r) ? (this.clearPersistedEvents(), e?.onSuccess?.(t.events.length, t.events, r)) : e?.onFailure?.();
589
646
  } catch (t) {
590
- if (t instanceof M) {
647
+ if (t instanceof R) {
591
648
  this.logPermanentError("Permanent error during recovery, clearing persisted events", t), this.clearPersistedEvents(), e?.onFailure?.();
592
649
  return;
593
650
  }
594
- l("error", "Failed to recover persisted events", { error: t });
651
+ a("error", "Failed to recover persisted events", { error: t });
595
652
  }
596
653
  }
597
654
  stop() {
@@ -599,17 +656,17 @@ class ct extends g {
599
656
  async send(e) {
600
657
  if (this.shouldSkipSend())
601
658
  return this.simulateSuccessfulSend();
602
- if (this.get("config")?.integrations?.custom?.collectApiUrl === Y.Fail)
603
- return l("warn", "Fail mode: simulating network failure", {
659
+ if (this.get("config")?.integrations?.custom?.collectApiUrl === q.Fail)
660
+ return a("warn", "Fail mode: simulating network failure", {
604
661
  data: { events: e.events.length }
605
662
  }), !1;
606
- const { url: r, payload: n } = this.prepareRequest(e);
663
+ const { url: r, payload: s } = this.prepareRequest(e);
607
664
  try {
608
- return (await this.sendWithTimeout(r, n)).ok;
665
+ return (await this.sendWithTimeout(r, s)).ok;
609
666
  } catch (i) {
610
- if (i instanceof M)
667
+ if (i instanceof R)
611
668
  throw i;
612
- return l("error", "Send request failed", {
669
+ return a("error", "Send request failed", {
613
670
  error: i,
614
671
  data: {
615
672
  events: e.events.length,
@@ -619,7 +676,7 @@ class ct extends g {
619
676
  }
620
677
  }
621
678
  async sendWithTimeout(e, t) {
622
- const r = new AbortController(), n = setTimeout(() => {
679
+ const r = new AbortController(), s = setTimeout(() => {
623
680
  r.abort();
624
681
  }, 1e4);
625
682
  try {
@@ -634,18 +691,27 @@ class ct extends g {
634
691
  }
635
692
  });
636
693
  if (!i.ok)
637
- throw i.status >= 400 && i.status < 500 ? new M(`HTTP ${i.status}: ${i.statusText}`, i.status) : new Error(`HTTP ${i.status}: ${i.statusText}`);
694
+ throw i.status >= 400 && i.status < 500 ? new R(`HTTP ${i.status}: ${i.statusText}`, i.status) : new Error(`HTTP ${i.status}: ${i.statusText}`);
638
695
  return i;
639
696
  } finally {
640
- clearTimeout(n);
697
+ clearTimeout(s);
641
698
  }
642
699
  }
643
700
  sendQueueSyncInternal(e) {
644
- const { url: t, payload: r } = this.prepareRequest(e), n = new Blob([r], { type: "application/json" });
701
+ const { url: t, payload: r } = this.prepareRequest(e);
702
+ if (r.length > 65536)
703
+ return a("warn", "Payload exceeds sendBeacon limit, persisting for recovery", {
704
+ data: {
705
+ size: r.length,
706
+ limit: 65536,
707
+ events: e.events.length
708
+ }
709
+ }), this.persistEvents(e), !1;
710
+ const s = new Blob([r], { type: "application/json" });
645
711
  if (!this.isSendBeaconAvailable())
646
- return l("warn", "sendBeacon not available, persisting events for recovery"), this.persistEvents(e), !1;
647
- const i = navigator.sendBeacon(t, n);
648
- return i || (l("warn", "sendBeacon rejected request, persisting events for recovery"), this.persistEvents(e)), i;
712
+ return a("warn", "sendBeacon not available, persisting events for recovery"), this.persistEvents(e), !1;
713
+ const i = navigator.sendBeacon(t, s);
714
+ return i || (a("warn", "sendBeacon rejected request, persisting events for recovery"), this.persistEvents(e)), i;
649
715
  }
650
716
  prepareRequest(e) {
651
717
  const t = {
@@ -666,7 +732,7 @@ class ct extends g {
666
732
  if (t)
667
733
  return JSON.parse(t);
668
734
  } catch (e) {
669
- l("warn", "Failed to parse persisted data", { error: e }), this.clearPersistedEvents();
735
+ a("warn", "Failed to parse persisted data", { error: e }), this.clearPersistedEvents();
670
736
  }
671
737
  return null;
672
738
  }
@@ -694,7 +760,7 @@ class ct extends g {
694
760
  }, r = this.getQueueStorageKey();
695
761
  return this.storeManager.setItem(r, JSON.stringify(t)), !!this.storeManager.getItem(r);
696
762
  } catch (t) {
697
- return l("warn", "Failed to persist events", { error: t }), !1;
763
+ return a("warn", "Failed to persist events", { error: t }), !1;
698
764
  }
699
765
  }
700
766
  clearPersistedEvents() {
@@ -702,7 +768,7 @@ class ct extends g {
702
768
  const e = this.getQueueStorageKey();
703
769
  this.storeManager.removeItem(e);
704
770
  } catch (e) {
705
- l("warn", "Failed to clear persisted events", { error: e });
771
+ a("warn", "Failed to clear persisted events", { error: e });
706
772
  }
707
773
  }
708
774
  shouldSkipSend() {
@@ -717,35 +783,45 @@ class ct extends g {
717
783
  }
718
784
  logPermanentError(e, t) {
719
785
  const r = Date.now();
720
- (!this.lastPermanentErrorLog || this.lastPermanentErrorLog.statusCode !== t.statusCode || r - this.lastPermanentErrorLog.timestamp >= We) && (l("error", e, {
786
+ (!this.lastPermanentErrorLog || this.lastPermanentErrorLog.statusCode !== t.statusCode || r - this.lastPermanentErrorLog.timestamp >= et) && (a("error", e, {
721
787
  data: { status: t.statusCode, message: t.message }
722
788
  }), this.lastPermanentErrorLog = { statusCode: t.statusCode, timestamp: r });
723
789
  }
724
790
  }
725
- class ut extends g {
791
+ class St extends S {
726
792
  googleAnalytics;
727
793
  dataSender;
728
794
  emitter;
729
795
  eventsQueue = [];
730
796
  pendingEventsBuffer = [];
731
- lastEventFingerprint = null;
732
- lastEventTime = 0;
797
+ recentEventFingerprints = /* @__PURE__ */ new Map();
798
+ // Time-based deduplication cache
733
799
  sendIntervalId = null;
734
800
  rateLimitCounter = 0;
735
801
  rateLimitWindowStart = 0;
802
+ perEventRateLimits = /* @__PURE__ */ new Map();
803
+ sessionEventCounts = {
804
+ total: 0,
805
+ [u.CLICK]: 0,
806
+ [u.PAGE_VIEW]: 0,
807
+ [u.CUSTOM]: 0,
808
+ [u.VIEWPORT_VISIBLE]: 0,
809
+ [u.SCROLL]: 0
810
+ };
811
+ lastSessionId = null;
736
812
  constructor(e, t = null, r = null) {
737
- super(), this.googleAnalytics = t, this.dataSender = new ct(e), this.emitter = r;
813
+ super(), this.googleAnalytics = t, this.dataSender = new mt(e), this.emitter = r;
738
814
  }
739
815
  async recoverPersistedEvents() {
740
816
  await this.dataSender.recoverPersistedEvents({
741
817
  onSuccess: (e, t, r) => {
742
818
  if (t && t.length > 0) {
743
- const n = t.map((i) => i.id);
744
- this.removeProcessedEvents(n), r && this.emitEventsQueue(r);
819
+ const s = t.map((i) => i.id);
820
+ this.removeProcessedEvents(s), r && this.emitEventsQueue(r);
745
821
  }
746
822
  },
747
823
  onFailure: () => {
748
- l("warn", "Failed to recover persisted events");
824
+ a("warn", "Failed to recover persisted events");
749
825
  }
750
826
  });
751
827
  }
@@ -753,76 +829,127 @@ class ut extends g {
753
829
  type: e,
754
830
  page_url: t,
755
831
  from_page_url: r,
756
- scroll_data: n,
832
+ scroll_data: s,
757
833
  click_data: i,
758
- custom_event: a,
759
- web_vitals: o,
834
+ custom_event: o,
835
+ web_vitals: l,
760
836
  error_data: c,
761
- session_end_reason: u
837
+ session_end_reason: d,
838
+ viewport_data: _
762
839
  }) {
763
840
  if (!e) {
764
- l("error", "Event type is required - event will be ignored");
841
+ a("error", "Event type is required - event will be ignored");
765
842
  return;
766
843
  }
767
- if (!this.get("sessionId")) {
768
- this.pendingEventsBuffer.length >= 100 && (this.pendingEventsBuffer.shift(), l("warn", "Pending events buffer full - dropping oldest event", {
844
+ const g = this.get("sessionId");
845
+ if (!g) {
846
+ this.pendingEventsBuffer.length >= 100 && (this.pendingEventsBuffer.shift(), a("warn", "Pending events buffer full - dropping oldest event", {
769
847
  data: { maxBufferSize: 100 }
770
848
  })), this.pendingEventsBuffer.push({
771
849
  type: e,
772
850
  page_url: t,
773
851
  from_page_url: r,
774
- scroll_data: n,
852
+ scroll_data: s,
775
853
  click_data: i,
776
- custom_event: a,
777
- web_vitals: o,
854
+ custom_event: o,
855
+ web_vitals: l,
778
856
  error_data: c,
779
- session_end_reason: u
857
+ session_end_reason: d,
858
+ viewport_data: _
780
859
  });
781
860
  return;
782
861
  }
783
- const f = e === d.SESSION_START || e === d.SESSION_END;
784
- if (!f && !this.checkRateLimit())
862
+ this.lastSessionId !== g && (this.lastSessionId = g, this.sessionEventCounts = {
863
+ total: 0,
864
+ [u.CLICK]: 0,
865
+ [u.PAGE_VIEW]: 0,
866
+ [u.CUSTOM]: 0,
867
+ [u.VIEWPORT_VISIBLE]: 0,
868
+ [u.SCROLL]: 0
869
+ });
870
+ const L = e === u.SESSION_START || e === u.SESSION_END;
871
+ if (!L && !this.checkRateLimit())
785
872
  return;
786
- const _ = e, D = _ === d.SESSION_START, Q = t || this.get("pageUrl"), B = this.buildEventPayload({
787
- type: _,
788
- page_url: Q,
873
+ const m = e;
874
+ if (!L) {
875
+ if (this.sessionEventCounts.total >= 1e3) {
876
+ a("warn", "Session event limit reached", {
877
+ data: {
878
+ type: m,
879
+ total: this.sessionEventCounts.total,
880
+ limit: 1e3
881
+ }
882
+ });
883
+ return;
884
+ }
885
+ const A = this.getTypeLimitForEvent(m);
886
+ if (A) {
887
+ const Q = this.sessionEventCounts[m];
888
+ if (Q !== void 0 && Q >= A) {
889
+ a("warn", "Session event type limit reached", {
890
+ data: {
891
+ type: m,
892
+ count: Q,
893
+ limit: A
894
+ }
895
+ });
896
+ return;
897
+ }
898
+ }
899
+ }
900
+ if (m === u.CUSTOM && o?.name) {
901
+ const A = this.get("config")?.maxSameEventPerMinute ?? 60;
902
+ if (!this.checkPerEventRateLimit(o.name, A))
903
+ return;
904
+ }
905
+ const Ve = m === u.SESSION_START, ke = t || this.get("pageUrl"), z = this.buildEventPayload({
906
+ type: m,
907
+ page_url: ke,
789
908
  from_page_url: r,
790
- scroll_data: n,
909
+ scroll_data: s,
791
910
  click_data: i,
792
- custom_event: a,
793
- web_vitals: o,
911
+ custom_event: o,
912
+ web_vitals: l,
794
913
  error_data: c,
795
- session_end_reason: u
914
+ session_end_reason: d,
915
+ viewport_data: _
796
916
  });
797
- if (!(!f && !this.shouldSample())) {
798
- if (D) {
799
- const ue = this.get("sessionId");
800
- if (!ue) {
801
- l("error", "Session start event requires sessionId - event will be ignored");
917
+ if (!(!L && !this.shouldSample())) {
918
+ if (Ve) {
919
+ const A = this.get("sessionId");
920
+ if (!A) {
921
+ a("error", "Session start event requires sessionId - event will be ignored");
802
922
  return;
803
923
  }
804
924
  if (this.get("hasStartSession")) {
805
- l("warn", "Duplicate session_start detected", {
806
- data: { sessionId: ue }
925
+ a("warn", "Duplicate session_start detected", {
926
+ data: { sessionId: A }
807
927
  });
808
928
  return;
809
929
  }
810
930
  this.set("hasStartSession", !0);
811
931
  }
812
- if (!this.isDuplicateEvent(B)) {
813
- if (this.get("mode") === C.QA && _ === d.CUSTOM && a) {
932
+ if (!this.isDuplicateEvent(z)) {
933
+ if (this.get("mode") === D.QA && m === u.CUSTOM && o) {
814
934
  console.log("[TraceLog] Event", {
815
- name: a.name,
816
- ...a.metadata && { metadata: a.metadata }
817
- }), this.emitEvent(B);
935
+ name: o.name,
936
+ ...o.metadata && { metadata: o.metadata }
937
+ }), this.emitEvent(z);
818
938
  return;
819
939
  }
820
- this.addToQueue(B);
940
+ this.addToQueue(z), L || (this.sessionEventCounts.total++, this.sessionEventCounts[m] !== void 0 && this.sessionEventCounts[m]++);
821
941
  }
822
942
  }
823
943
  }
824
944
  stop() {
825
- this.sendIntervalId && (clearInterval(this.sendIntervalId), this.sendIntervalId = null), this.eventsQueue = [], this.pendingEventsBuffer = [], this.lastEventFingerprint = null, this.lastEventTime = 0, this.rateLimitCounter = 0, this.rateLimitWindowStart = 0, this.dataSender.stop();
945
+ this.sendIntervalId && (clearInterval(this.sendIntervalId), this.sendIntervalId = null), this.eventsQueue = [], this.pendingEventsBuffer = [], this.recentEventFingerprints.clear(), this.rateLimitCounter = 0, this.rateLimitWindowStart = 0, this.perEventRateLimits.clear(), this.sessionEventCounts = {
946
+ total: 0,
947
+ [u.CLICK]: 0,
948
+ [u.PAGE_VIEW]: 0,
949
+ [u.CUSTOM]: 0,
950
+ [u.VIEWPORT_VISIBLE]: 0,
951
+ [u.SCROLL]: 0
952
+ }, this.lastSessionId = null, this.dataSender.stop();
826
953
  }
827
954
  async flushImmediately() {
828
955
  return this.flushEvents(!1);
@@ -837,7 +964,7 @@ class ut extends g {
837
964
  if (this.pendingEventsBuffer.length === 0)
838
965
  return;
839
966
  if (!this.get("sessionId")) {
840
- l("warn", "Cannot flush pending events: session not initialized - keeping in buffer", {
967
+ a("warn", "Cannot flush pending events: session not initialized - keeping in buffer", {
841
968
  data: { bufferedEventCount: this.pendingEventsBuffer.length }
842
969
  });
843
970
  return;
@@ -853,17 +980,17 @@ class ut extends g {
853
980
  flushEvents(e) {
854
981
  if (this.eventsQueue.length === 0)
855
982
  return e ? !0 : Promise.resolve(!0);
856
- const t = this.buildEventsPayload(), r = [...this.eventsQueue], n = r.map((i) => i.id);
983
+ const t = this.buildEventsPayload(), r = [...this.eventsQueue], s = r.map((i) => i.id);
857
984
  if (e) {
858
985
  const i = this.dataSender.sendEventsQueueSync(t);
859
- return i && (this.removeProcessedEvents(n), this.clearSendInterval(), this.emitEventsQueue(t)), i;
986
+ return i && (this.removeProcessedEvents(s), this.clearSendInterval(), this.emitEventsQueue(t)), i;
860
987
  } else
861
988
  return this.dataSender.sendEventsQueue(t, {
862
989
  onSuccess: () => {
863
- this.removeProcessedEvents(n), this.clearSendInterval(), this.emitEventsQueue(t);
990
+ this.removeProcessedEvents(s), this.clearSendInterval(), this.emitEventsQueue(t);
864
991
  },
865
992
  onFailure: () => {
866
- l("warn", "Async flush failed", {
993
+ a("warn", "Async flush failed", {
867
994
  data: { eventCount: r.length }
868
995
  });
869
996
  }
@@ -872,13 +999,13 @@ class ut extends g {
872
999
  async sendEventsQueue() {
873
1000
  if (!this.get("sessionId") || this.eventsQueue.length === 0)
874
1001
  return;
875
- const e = this.buildEventsPayload(), t = [...this.eventsQueue], r = t.map((n) => n.id);
1002
+ const e = this.buildEventsPayload(), t = [...this.eventsQueue], r = t.map((s) => s.id);
876
1003
  await this.dataSender.sendEventsQueue(e, {
877
1004
  onSuccess: () => {
878
1005
  this.removeProcessedEvents(r), this.emitEventsQueue(e);
879
1006
  },
880
1007
  onFailure: () => {
881
- l("warn", "Events send failed, keeping in queue", {
1008
+ a("warn", "Events send failed, keeping in queue", {
882
1009
  data: { eventCount: t.length }
883
1010
  });
884
1011
  }
@@ -886,11 +1013,11 @@ class ut extends g {
886
1013
  }
887
1014
  buildEventsPayload() {
888
1015
  const e = /* @__PURE__ */ new Map(), t = [];
889
- for (const n of this.eventsQueue) {
890
- const i = this.createEventSignature(n);
891
- e.has(i) || t.push(i), e.set(i, n);
1016
+ for (const s of this.eventsQueue) {
1017
+ const i = this.createEventSignature(s);
1018
+ e.has(i) || t.push(i), e.set(i, s);
892
1019
  }
893
- const r = t.map((n) => e.get(n)).filter((n) => !!n).sort((n, i) => n.timestamp - i.timestamp);
1020
+ const r = t.map((s) => e.get(s)).filter((s) => !!s).sort((s, i) => s.timestamp - i.timestamp);
894
1021
  return {
895
1022
  user_id: this.get("userId"),
896
1023
  session_id: this.get("sessionId"),
@@ -900,9 +1027,9 @@ class ut extends g {
900
1027
  };
901
1028
  }
902
1029
  buildEventPayload(e) {
903
- const t = e.type === d.SESSION_START, r = e.page_url ?? this.get("pageUrl");
1030
+ const t = e.type === u.SESSION_START, r = e.page_url ?? this.get("pageUrl");
904
1031
  return {
905
- id: Je(),
1032
+ id: st(),
906
1033
  type: e.type,
907
1034
  page_url: r,
908
1035
  timestamp: Date.now(),
@@ -914,18 +1041,40 @@ class ut extends g {
914
1041
  ...e.web_vitals && { web_vitals: e.web_vitals },
915
1042
  ...e.error_data && { error_data: e.error_data },
916
1043
  ...e.session_end_reason && { session_end_reason: e.session_end_reason },
917
- ...t && Ee() && { utm: Ee() }
1044
+ ...e.viewport_data && { viewport_data: e.viewport_data },
1045
+ ...t && _e() && { utm: _e() }
918
1046
  };
919
1047
  }
1048
+ /**
1049
+ * Checks if event is a duplicate using time-based cache
1050
+ * Tracks recent event fingerprints with timestamp-based cleanup
1051
+ */
920
1052
  isDuplicateEvent(e) {
921
- const t = Date.now(), r = this.createEventFingerprint(e);
922
- return this.lastEventFingerprint === r && t - this.lastEventTime < 500 ? !0 : (this.lastEventFingerprint = r, this.lastEventTime = t, !1);
1053
+ const t = Date.now(), r = this.createEventFingerprint(e), s = this.recentEventFingerprints.get(r);
1054
+ return s && t - s < 500 ? (this.recentEventFingerprints.set(r, t), !0) : (this.recentEventFingerprints.set(r, t), this.recentEventFingerprints.size > 1e3 && this.pruneOldFingerprints(), this.recentEventFingerprints.size > 2e3 && (this.recentEventFingerprints.clear(), this.recentEventFingerprints.set(r, t), a("warn", "Event fingerprint cache exceeded hard limit, cleared", {
1055
+ data: { hardLimit: 2e3 }
1056
+ })), !1);
1057
+ }
1058
+ /**
1059
+ * Prunes old fingerprints from cache based on timestamp
1060
+ * Removes entries older than 10x the duplicate threshold (5 seconds)
1061
+ */
1062
+ pruneOldFingerprints() {
1063
+ const e = Date.now(), t = 500 * 10;
1064
+ for (const [r, s] of this.recentEventFingerprints.entries())
1065
+ e - s > t && this.recentEventFingerprints.delete(r);
1066
+ a("debug", "Pruned old event fingerprints", {
1067
+ data: {
1068
+ remaining: this.recentEventFingerprints.size,
1069
+ cutoffMs: t
1070
+ }
1071
+ });
923
1072
  }
924
1073
  createEventFingerprint(e) {
925
1074
  let t = `${e.type}_${e.page_url}`;
926
1075
  if (e.click_data) {
927
- const r = Math.round((e.click_data.x || 0) / 10) * 10, n = Math.round((e.click_data.y || 0) / 10) * 10;
928
- t += `_click_${r}_${n}`;
1076
+ const r = Math.round((e.click_data.x || 0) / 10) * 10, s = Math.round((e.click_data.y || 0) / 10) * 10;
1077
+ t += `_click_${r}_${s}`;
929
1078
  }
930
1079
  return e.scroll_data && (t += `_scroll_${e.scroll_data.depth}_${e.scroll_data.direction}`), e.custom_event && (t += `_custom_${e.custom_event.name}`), e.web_vitals && (t += `_vitals_${e.web_vitals.type}`), e.error_data && (t += `_error_${e.error_data.type}_${e.error_data.message}`), t;
931
1080
  }
@@ -935,18 +1084,18 @@ class ut extends g {
935
1084
  addToQueue(e) {
936
1085
  if (this.eventsQueue.push(e), this.emitEvent(e), this.eventsQueue.length > 100) {
937
1086
  const t = this.eventsQueue.findIndex(
938
- (n) => n.type !== d.SESSION_START && n.type !== d.SESSION_END
1087
+ (s) => s.type !== u.SESSION_START && s.type !== u.SESSION_END
939
1088
  ), r = t >= 0 ? this.eventsQueue.splice(t, 1)[0] : this.eventsQueue.shift();
940
- l("warn", "Event queue overflow, oldest non-critical event removed", {
1089
+ a("warn", "Event queue overflow, oldest non-critical event removed", {
941
1090
  data: {
942
1091
  maxLength: 100,
943
1092
  currentLength: this.eventsQueue.length,
944
1093
  removedEventType: r?.type,
945
- wasCritical: r?.type === d.SESSION_START || r?.type === d.SESSION_END
1094
+ wasCritical: r?.type === u.SESSION_START || r?.type === u.SESSION_END
946
1095
  }
947
1096
  });
948
1097
  }
949
- this.sendIntervalId || this.startSendInterval(), this.handleGoogleAnalyticsIntegration(e);
1098
+ this.sendIntervalId || this.startSendInterval(), this.eventsQueue.length >= 50 && this.sendEventsQueue(), this.handleGoogleAnalyticsIntegration(e);
950
1099
  }
951
1100
  startSendInterval() {
952
1101
  this.sendIntervalId = window.setInterval(() => {
@@ -954,8 +1103,8 @@ class ut extends g {
954
1103
  }, 1e4);
955
1104
  }
956
1105
  handleGoogleAnalyticsIntegration(e) {
957
- if (this.googleAnalytics && e.type === d.CUSTOM && e.custom_event) {
958
- if (this.get("mode") === C.QA)
1106
+ if (this.googleAnalytics && e.type === u.CUSTOM && e.custom_event) {
1107
+ if (this.get("mode") === D.QA)
959
1108
  return;
960
1109
  this.googleAnalytics.trackEvent(e.custom_event.name, e.custom_event.metadata ?? {});
961
1110
  }
@@ -966,20 +1115,46 @@ class ut extends g {
966
1115
  }
967
1116
  checkRateLimit() {
968
1117
  const e = Date.now();
969
- return e - this.rateLimitWindowStart > 1e3 && (this.rateLimitCounter = 0, this.rateLimitWindowStart = e), this.rateLimitCounter >= 200 ? !1 : (this.rateLimitCounter++, !0);
1118
+ return e - this.rateLimitWindowStart > 1e3 && (this.rateLimitCounter = 0, this.rateLimitWindowStart = e), this.rateLimitCounter >= 50 ? !1 : (this.rateLimitCounter++, !0);
1119
+ }
1120
+ /**
1121
+ * Checks per-event-name rate limiting to prevent infinite loops in user code
1122
+ * Tracks timestamps per event name and limits to maxSameEventPerMinute per minute
1123
+ */
1124
+ checkPerEventRateLimit(e, t) {
1125
+ const r = Date.now(), i = (this.perEventRateLimits.get(e) ?? []).filter((o) => r - o < 6e4);
1126
+ return i.length >= t ? (a("warn", "Per-event rate limit exceeded for custom event", {
1127
+ data: {
1128
+ eventName: e,
1129
+ limit: t,
1130
+ window: `${6e4 / 1e3}s`
1131
+ }
1132
+ }), !1) : (i.push(r), this.perEventRateLimits.set(e, i), !0);
1133
+ }
1134
+ /**
1135
+ * Gets the per-session limit for a specific event type (Phase 3)
1136
+ */
1137
+ getTypeLimitForEvent(e) {
1138
+ return {
1139
+ [u.CLICK]: 500,
1140
+ [u.PAGE_VIEW]: 100,
1141
+ [u.CUSTOM]: 500,
1142
+ [u.VIEWPORT_VISIBLE]: 200,
1143
+ [u.SCROLL]: 120
1144
+ }[e] ?? null;
970
1145
  }
971
1146
  removeProcessedEvents(e) {
972
1147
  const t = new Set(e);
973
1148
  this.eventsQueue = this.eventsQueue.filter((r) => !t.has(r.id));
974
1149
  }
975
1150
  emitEvent(e) {
976
- this.emitter && this.emitter.emit(K.EVENT, e);
1151
+ this.emitter && this.emitter.emit(Z.EVENT, e);
977
1152
  }
978
1153
  emitEventsQueue(e) {
979
- this.emitter && this.emitter.emit(K.QUEUE, e);
1154
+ this.emitter && this.emitter.emit(Z.QUEUE, e);
980
1155
  }
981
1156
  }
982
- class dt {
1157
+ class _t {
983
1158
  /**
984
1159
  * Gets or creates a unique user ID for the given project.
985
1160
  * The user ID is persisted in localStorage and reused across sessions.
@@ -989,14 +1164,14 @@ class dt {
989
1164
  * @returns Persistent unique user ID
990
1165
  */
991
1166
  static getId(e) {
992
- const t = $e, r = e.getItem(t);
1167
+ const t = ze, r = e.getItem(t);
993
1168
  if (r)
994
1169
  return r;
995
- const n = qe();
996
- return e.setItem(t, n), n;
1170
+ const s = nt();
1171
+ return e.setItem(t, s), s;
997
1172
  }
998
1173
  }
999
- class ht extends g {
1174
+ class Tt extends S {
1000
1175
  storageManager;
1001
1176
  eventManager;
1002
1177
  projectId;
@@ -1011,18 +1186,18 @@ class ht extends g {
1011
1186
  }
1012
1187
  initCrossTabSync() {
1013
1188
  if (typeof BroadcastChannel > "u") {
1014
- l("warn", "BroadcastChannel not supported");
1189
+ a("warn", "BroadcastChannel not supported");
1015
1190
  return;
1016
1191
  }
1017
1192
  const e = this.getProjectId();
1018
- this.broadcastChannel = new BroadcastChannel(Be(e)), this.broadcastChannel.onmessage = (t) => {
1019
- const { action: r, sessionId: n, timestamp: i, projectId: a } = t.data ?? {};
1020
- if (a === e) {
1193
+ this.broadcastChannel = new BroadcastChannel(Ye(e)), this.broadcastChannel.onmessage = (t) => {
1194
+ const { action: r, sessionId: s, timestamp: i, projectId: o } = t.data ?? {};
1195
+ if (o === e) {
1021
1196
  if (r === "session_end") {
1022
1197
  this.resetSessionState();
1023
1198
  return;
1024
1199
  }
1025
- n && typeof i == "number" && i > Date.now() - 5e3 && (this.set("sessionId", n), this.set("hasStartSession", !0), this.persistSession(n, i), this.isTracking && this.setupSessionTimeout());
1200
+ s && typeof i == "number" && i > Date.now() - 5e3 && (this.set("sessionId", s), this.set("hasStartSession", !0), this.persistSession(s, i), this.isTracking && this.setupSessionTimeout());
1026
1201
  }
1027
1202
  };
1028
1203
  }
@@ -1045,7 +1220,7 @@ class ht extends g {
1045
1220
  timestamp: Date.now()
1046
1221
  });
1047
1222
  } catch (r) {
1048
- l("warn", "Failed to broadcast session end", { error: r, data: { sessionId: e, reason: t } });
1223
+ a("warn", "Failed to broadcast session end", { error: r, data: { sessionId: e, reason: t } });
1049
1224
  }
1050
1225
  }
1051
1226
  cleanupCrossTabSync() {
@@ -1084,24 +1259,24 @@ class ht extends g {
1084
1259
  this.storageManager.setItem(t, JSON.stringify(e));
1085
1260
  }
1086
1261
  getSessionStorageKey() {
1087
- return Qe(this.getProjectId());
1262
+ return je(this.getProjectId());
1088
1263
  }
1089
1264
  getProjectId() {
1090
1265
  return this.projectId;
1091
1266
  }
1092
1267
  startTracking() {
1093
1268
  if (this.isTracking) {
1094
- l("warn", "Session tracking already active");
1269
+ a("warn", "Session tracking already active");
1095
1270
  return;
1096
1271
  }
1097
1272
  const e = this.recoverSession(), t = e ?? this.generateSessionId(), r = !!e;
1098
1273
  this.isTracking = !0;
1099
1274
  try {
1100
1275
  this.set("sessionId", t), this.persistSession(t), r || this.eventManager.track({
1101
- type: d.SESSION_START
1276
+ type: u.SESSION_START
1102
1277
  }), this.initCrossTabSync(), this.shareSession(t), this.setupSessionTimeout(), this.setupActivityListeners(), this.setupLifecycleListeners();
1103
- } catch (n) {
1104
- throw this.isTracking = !1, this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupLifecycleListeners(), this.cleanupCrossTabSync(), this.set("sessionId", null), n;
1278
+ } catch (s) {
1279
+ throw this.isTracking = !1, this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupLifecycleListeners(), this.cleanupCrossTabSync(), this.set("sessionId", null), s;
1105
1280
  }
1106
1281
  }
1107
1282
  generateSessionId() {
@@ -1143,13 +1318,13 @@ class ht extends g {
1143
1318
  endSession(e) {
1144
1319
  const t = this.get("sessionId");
1145
1320
  if (!t) {
1146
- l("warn", "endSession called without active session", { data: { reason: e } }), this.resetSessionState(e);
1321
+ a("warn", "endSession called without active session", { data: { reason: e } }), this.resetSessionState(e);
1147
1322
  return;
1148
1323
  }
1149
1324
  this.eventManager.track({
1150
- type: d.SESSION_END,
1325
+ type: u.SESSION_END,
1151
1326
  session_end_reason: e
1152
- }), this.eventManager.flushImmediatelySync() || l("warn", "Sync flush failed during session end, events persisted for recovery", {
1327
+ }), this.eventManager.flushImmediatelySync() || a("warn", "Sync flush failed during session end, events persisted for recovery", {
1153
1328
  data: { reason: e, sessionId: t }
1154
1329
  }), this.broadcastSessionEnd(t, e), this.resetSessionState(e);
1155
1330
  }
@@ -1163,7 +1338,7 @@ class ht extends g {
1163
1338
  this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupCrossTabSync(), this.cleanupLifecycleListeners(), this.isTracking = !1, this.set("hasStartSession", !1);
1164
1339
  }
1165
1340
  }
1166
- class ft extends g {
1341
+ class pt extends S {
1167
1342
  eventManager;
1168
1343
  storageManager;
1169
1344
  sessionManager = null;
@@ -1175,14 +1350,14 @@ class ft extends g {
1175
1350
  if (this.isActive())
1176
1351
  return;
1177
1352
  if (this.destroyed) {
1178
- l("warn", "Cannot start tracking on destroyed handler");
1353
+ a("warn", "Cannot start tracking on destroyed handler");
1179
1354
  return;
1180
1355
  }
1181
1356
  const e = this.get("config"), t = e?.integrations?.tracelog?.projectId ?? e?.integrations?.custom?.collectApiUrl ?? "default";
1182
1357
  if (!t)
1183
1358
  throw new Error("Cannot start session tracking: config not available");
1184
1359
  try {
1185
- this.sessionManager = new ht(this.storageManager, this.eventManager, t), this.sessionManager.startTracking(), this.eventManager.flushPendingEvents();
1360
+ this.sessionManager = new Tt(this.storageManager, this.eventManager, t), this.sessionManager.startTracking(), this.eventManager.flushPendingEvents();
1186
1361
  } catch (r) {
1187
1362
  if (this.sessionManager) {
1188
1363
  try {
@@ -1191,7 +1366,7 @@ class ft extends g {
1191
1366
  }
1192
1367
  this.sessionManager = null;
1193
1368
  }
1194
- throw l("error", "Failed to start session tracking", { error: r }), r;
1369
+ throw a("error", "Failed to start session tracking", { error: r }), r;
1195
1370
  }
1196
1371
  }
1197
1372
  isActive() {
@@ -1207,11 +1382,12 @@ class ft extends g {
1207
1382
  this.destroyed || (this.sessionManager && (this.sessionManager.destroy(), this.sessionManager = null), this.destroyed = !0, this.set("hasStartSession", !1));
1208
1383
  }
1209
1384
  }
1210
- class gt extends g {
1385
+ class It extends S {
1211
1386
  eventManager;
1212
1387
  onTrack;
1213
1388
  originalPushState;
1214
1389
  originalReplaceState;
1390
+ lastPageViewTime = 0;
1215
1391
  constructor(e, t) {
1216
1392
  super(), this.eventManager = e, this.onTrack = t;
1217
1393
  }
@@ -1219,7 +1395,7 @@ class gt extends g {
1219
1395
  this.trackInitialPageView(), window.addEventListener("popstate", this.trackCurrentPage, !0), window.addEventListener("hashchange", this.trackCurrentPage, !0), this.patchHistory("pushState"), this.patchHistory("replaceState");
1220
1396
  }
1221
1397
  stopTracking() {
1222
- window.removeEventListener("popstate", this.trackCurrentPage, !0), window.removeEventListener("hashchange", this.trackCurrentPage, !0), this.originalPushState && (window.history.pushState = this.originalPushState), this.originalReplaceState && (window.history.replaceState = this.originalReplaceState);
1398
+ window.removeEventListener("popstate", this.trackCurrentPage, !0), window.removeEventListener("hashchange", this.trackCurrentPage, !0), this.originalPushState && (window.history.pushState = this.originalPushState), this.originalReplaceState && (window.history.replaceState = this.originalReplaceState), this.lastPageViewTime = 0;
1223
1399
  }
1224
1400
  patchHistory(e) {
1225
1401
  const t = window.history[e];
@@ -1228,32 +1404,35 @@ class gt extends g {
1228
1404
  };
1229
1405
  }
1230
1406
  trackCurrentPage = () => {
1231
- const e = window.location.href, t = J(e, this.get("config").sensitiveQueryParams);
1407
+ const e = window.location.href, t = ee(e, this.get("config").sensitiveQueryParams);
1232
1408
  if (this.get("pageUrl") === t)
1233
1409
  return;
1234
- this.onTrack();
1235
- const r = this.get("pageUrl");
1410
+ const r = Date.now(), s = this.get("config").pageViewThrottleMs ?? 1e3;
1411
+ if (r - this.lastPageViewTime < s)
1412
+ return;
1413
+ this.lastPageViewTime = r, this.onTrack();
1414
+ const i = this.get("pageUrl");
1236
1415
  this.set("pageUrl", t);
1237
- const n = this.extractPageViewData();
1416
+ const o = this.extractPageViewData();
1238
1417
  this.eventManager.track({
1239
- type: d.PAGE_VIEW,
1418
+ type: u.PAGE_VIEW,
1240
1419
  page_url: this.get("pageUrl"),
1241
- from_page_url: r,
1242
- ...n && { page_view: n }
1420
+ from_page_url: i,
1421
+ ...o && { page_view: o }
1243
1422
  });
1244
1423
  };
1245
1424
  trackInitialPageView() {
1246
- const e = J(window.location.href, this.get("config").sensitiveQueryParams), t = this.extractPageViewData();
1247
- this.eventManager.track({
1248
- type: d.PAGE_VIEW,
1425
+ const e = ee(window.location.href, this.get("config").sensitiveQueryParams), t = this.extractPageViewData();
1426
+ this.lastPageViewTime = Date.now(), this.eventManager.track({
1427
+ type: u.PAGE_VIEW,
1249
1428
  page_url: e,
1250
1429
  ...t && { page_view: t }
1251
1430
  }), this.onTrack();
1252
1431
  }
1253
1432
  extractPageViewData() {
1254
- const { pathname: e, search: t, hash: r } = window.location, { referrer: n } = document, { title: i } = document;
1255
- return !n && !i && !e && !t && !r ? void 0 : {
1256
- ...n && { referrer: n },
1433
+ const { pathname: e, search: t, hash: r } = window.location, { referrer: s } = document, { title: i } = document;
1434
+ return !s && !i && !e && !t && !r ? void 0 : {
1435
+ ...s && { referrer: s },
1257
1436
  ...i && { title: i },
1258
1437
  ...e && { pathname: e },
1259
1438
  ...t && { search: t },
@@ -1261,53 +1440,99 @@ class gt extends g {
1261
1440
  };
1262
1441
  }
1263
1442
  }
1264
- class St extends g {
1443
+ class vt extends S {
1265
1444
  eventManager;
1266
1445
  clickHandler;
1446
+ lastClickTimes = /* @__PURE__ */ new Map();
1267
1447
  constructor(e) {
1268
1448
  super(), this.eventManager = e;
1269
1449
  }
1270
1450
  startTracking() {
1271
1451
  this.clickHandler || (this.clickHandler = (e) => {
1272
- const t = e, r = t.target, n = typeof HTMLElement < "u" && r instanceof HTMLElement ? r : typeof HTMLElement < "u" && r instanceof Node && r.parentElement instanceof HTMLElement ? r.parentElement : null;
1273
- if (!n) {
1274
- l("warn", "Click target not found or not an element");
1452
+ const t = e, r = t.target, s = typeof HTMLElement < "u" && r instanceof HTMLElement ? r : typeof HTMLElement < "u" && r instanceof Node && r.parentElement instanceof HTMLElement ? r.parentElement : null;
1453
+ if (!s) {
1454
+ a("warn", "Click target not found or not an element");
1275
1455
  return;
1276
1456
  }
1277
- if (this.shouldIgnoreElement(n))
1457
+ if (this.shouldIgnoreElement(s))
1458
+ return;
1459
+ const i = this.get("config")?.clickThrottleMs ?? 300;
1460
+ if (i > 0 && !this.checkClickThrottle(s, i))
1278
1461
  return;
1279
- const i = this.findTrackingElement(n), a = this.getRelevantClickElement(n), o = this.calculateClickCoordinates(t, n);
1280
- if (i) {
1281
- const u = this.extractTrackingData(i);
1282
- if (u) {
1283
- const f = this.createCustomEventData(u);
1462
+ const o = this.findTrackingElement(s), l = this.getRelevantClickElement(s), c = this.calculateClickCoordinates(t, s);
1463
+ if (o) {
1464
+ const _ = this.extractTrackingData(o);
1465
+ if (_) {
1466
+ const g = this.createCustomEventData(_);
1284
1467
  this.eventManager.track({
1285
- type: d.CUSTOM,
1468
+ type: u.CUSTOM,
1286
1469
  custom_event: {
1287
- name: f.name,
1288
- ...f.value && { metadata: { value: f.value } }
1470
+ name: g.name,
1471
+ ...g.value && { metadata: { value: g.value } }
1289
1472
  }
1290
1473
  });
1291
1474
  }
1292
1475
  }
1293
- const c = this.generateClickData(n, a, o);
1476
+ const d = this.generateClickData(s, l, c);
1294
1477
  this.eventManager.track({
1295
- type: d.CLICK,
1296
- click_data: c
1478
+ type: u.CLICK,
1479
+ click_data: d
1297
1480
  });
1298
1481
  }, window.addEventListener("click", this.clickHandler, !0));
1299
1482
  }
1300
1483
  stopTracking() {
1301
- this.clickHandler && (window.removeEventListener("click", this.clickHandler, !0), this.clickHandler = void 0);
1484
+ this.clickHandler && (window.removeEventListener("click", this.clickHandler, !0), this.clickHandler = void 0), this.lastClickTimes.clear();
1302
1485
  }
1303
1486
  shouldIgnoreElement(e) {
1304
- return e.hasAttribute(`${A}-ignore`) ? !0 : e.closest(`[${A}-ignore]`) !== null;
1487
+ return e.hasAttribute(`${v}-ignore`) ? !0 : e.closest(`[${v}-ignore]`) !== null;
1488
+ }
1489
+ /**
1490
+ * Checks per-element click throttling to prevent double-clicks and rapid spam
1491
+ * Returns true if the click should be tracked, false if throttled
1492
+ */
1493
+ checkClickThrottle(e, t) {
1494
+ const r = this.getElementSignature(e), s = Date.now(), i = this.lastClickTimes.get(r);
1495
+ return i !== void 0 && s - i < t ? (a("debug", "ClickHandler: Click suppressed by throttle", {
1496
+ data: {
1497
+ signature: r,
1498
+ throttleRemaining: t - (s - i)
1499
+ }
1500
+ }), !1) : (this.lastClickTimes.set(r, s), !0);
1501
+ }
1502
+ /**
1503
+ * Creates a stable signature for an element to track throttling
1504
+ * Priority: id > data-testid > data-tlog-name > DOM path
1505
+ */
1506
+ getElementSignature(e) {
1507
+ if (e.id)
1508
+ return `#${e.id}`;
1509
+ const t = e.getAttribute("data-testid");
1510
+ if (t)
1511
+ return `[data-testid="${t}"]`;
1512
+ const r = e.getAttribute(`${v}-name`);
1513
+ return r ? `[${v}-name="${r}"]` : this.getElementPath(e);
1514
+ }
1515
+ /**
1516
+ * Generates a DOM path for an element (e.g., "body>div>button")
1517
+ */
1518
+ getElementPath(e) {
1519
+ const t = [];
1520
+ let r = e;
1521
+ for (; r && r !== document.body; ) {
1522
+ let s = r.tagName.toLowerCase();
1523
+ if (r.className) {
1524
+ const i = r.className.split(" ")[0];
1525
+ i && (s += `.${i}`);
1526
+ }
1527
+ t.unshift(s), r = r.parentElement;
1528
+ }
1529
+ return t.join(">") || "unknown";
1305
1530
  }
1306
1531
  findTrackingElement(e) {
1307
- return e.hasAttribute(`${A}-name`) ? e : e.closest(`[${A}-name]`);
1532
+ return e.hasAttribute(`${v}-name`) ? e : e.closest(`[${v}-name]`);
1308
1533
  }
1309
1534
  getRelevantClickElement(e) {
1310
- for (const t of Pe)
1535
+ for (const t of Ue)
1311
1536
  try {
1312
1537
  if (e.matches(t))
1313
1538
  return e;
@@ -1315,7 +1540,7 @@ class St extends g {
1315
1540
  if (r)
1316
1541
  return r;
1317
1542
  } catch (r) {
1318
- l("warn", "Invalid selector in element search", { error: r, data: { selector: t } });
1543
+ a("warn", "Invalid selector in element search", { error: r, data: { selector: t } });
1319
1544
  continue;
1320
1545
  }
1321
1546
  return e;
@@ -1324,11 +1549,11 @@ class St extends g {
1324
1549
  return Math.max(0, Math.min(1, Number(e.toFixed(3))));
1325
1550
  }
1326
1551
  calculateClickCoordinates(e, t) {
1327
- const r = t.getBoundingClientRect(), n = e.clientX, i = e.clientY, a = r.width > 0 ? this.clamp((n - r.left) / r.width) : 0, o = r.height > 0 ? this.clamp((i - r.top) / r.height) : 0;
1328
- return { x: n, y: i, relativeX: a, relativeY: o };
1552
+ const r = t.getBoundingClientRect(), s = e.clientX, i = e.clientY, o = r.width > 0 ? this.clamp((s - r.left) / r.width) : 0, l = r.height > 0 ? this.clamp((i - r.top) / r.height) : 0;
1553
+ return { x: s, y: i, relativeX: o, relativeY: l };
1329
1554
  }
1330
1555
  extractTrackingData(e) {
1331
- const t = e.getAttribute(`${A}-name`), r = e.getAttribute(`${A}-value`);
1556
+ const t = e.getAttribute(`${v}-name`), r = e.getAttribute(`${v}-value`);
1332
1557
  if (t)
1333
1558
  return {
1334
1559
  element: e,
@@ -1337,38 +1562,38 @@ class St extends g {
1337
1562
  };
1338
1563
  }
1339
1564
  generateClickData(e, t, r) {
1340
- const { x: n, y: i, relativeX: a, relativeY: o } = r, c = this.getRelevantText(e, t), u = this.extractElementAttributes(t);
1565
+ const { x: s, y: i, relativeX: o, relativeY: l } = r, c = this.getRelevantText(e, t), d = this.extractElementAttributes(t);
1341
1566
  return {
1342
- x: n,
1567
+ x: s,
1343
1568
  y: i,
1344
- relativeX: a,
1345
- relativeY: o,
1569
+ relativeX: o,
1570
+ relativeY: l,
1346
1571
  tag: t.tagName.toLowerCase(),
1347
1572
  ...t.id && { id: t.id },
1348
1573
  ...t.className && { class: t.className },
1349
1574
  ...c && { text: c },
1350
- ...u.href && { href: u.href },
1351
- ...u.title && { title: u.title },
1352
- ...u.alt && { alt: u.alt },
1353
- ...u.role && { role: u.role },
1354
- ...u["aria-label"] && { ariaLabel: u["aria-label"] },
1355
- ...Object.keys(u).length > 0 && { dataAttributes: u }
1575
+ ...d.href && { href: d.href },
1576
+ ...d.title && { title: d.title },
1577
+ ...d.alt && { alt: d.alt },
1578
+ ...d.role && { role: d.role },
1579
+ ...d["aria-label"] && { ariaLabel: d["aria-label"] },
1580
+ ...Object.keys(d).length > 0 && { dataAttributes: d }
1356
1581
  };
1357
1582
  }
1358
1583
  sanitizeText(e) {
1359
1584
  let t = e;
1360
- for (const r of ae) {
1361
- const n = new RegExp(r.source, r.flags);
1362
- t = t.replace(n, "[REDACTED]");
1585
+ for (const r of le) {
1586
+ const s = new RegExp(r.source, r.flags);
1587
+ t = t.replace(s, "[REDACTED]");
1363
1588
  }
1364
1589
  return t;
1365
1590
  }
1366
1591
  getRelevantText(e, t) {
1367
- const r = e.textContent?.trim() ?? "", n = t.textContent?.trim() ?? "";
1368
- if (!r && !n)
1592
+ const r = e.textContent?.trim() ?? "", s = t.textContent?.trim() ?? "";
1593
+ if (!r && !s)
1369
1594
  return "";
1370
1595
  let i = "";
1371
- return r && r.length <= 255 ? i = r : n.length <= 255 ? i = n : i = n.slice(0, 252) + "...", this.sanitizeText(i);
1596
+ return r && r.length <= 255 ? i = r : s.length <= 255 ? i = s : i = s.slice(0, 252) + "...", this.sanitizeText(i);
1372
1597
  }
1373
1598
  extractElementAttributes(e) {
1374
1599
  const t = [
@@ -1383,9 +1608,9 @@ class St extends g {
1383
1608
  "alt",
1384
1609
  "role"
1385
1610
  ], r = {};
1386
- for (const n of t) {
1387
- const i = e.getAttribute(n);
1388
- i && (r[n] = i);
1611
+ for (const s of t) {
1612
+ const i = e.getAttribute(s);
1613
+ i && (r[s] = i);
1389
1614
  }
1390
1615
  return r;
1391
1616
  }
@@ -1396,7 +1621,7 @@ class St extends g {
1396
1621
  };
1397
1622
  }
1398
1623
  }
1399
- class Et extends g {
1624
+ class At extends S {
1400
1625
  eventManager;
1401
1626
  containers = [];
1402
1627
  limitWarningLogged = !1;
@@ -1421,8 +1646,8 @@ class Et extends g {
1421
1646
  const t = this.findScrollableElements();
1422
1647
  if (t.length > 0) {
1423
1648
  for (const r of t) {
1424
- const n = this.getElementSelector(r);
1425
- this.setupScrollContainer(r, n);
1649
+ const s = this.getElementSelector(r);
1650
+ this.setupScrollContainer(r, s);
1426
1651
  }
1427
1652
  this.applyPrimaryScrollSelectorIfConfigured();
1428
1653
  return;
@@ -1443,18 +1668,18 @@ class Et extends g {
1443
1668
  if (!document.body)
1444
1669
  return [];
1445
1670
  const e = [], t = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
1446
- acceptNode: (n) => {
1447
- const i = n;
1671
+ acceptNode: (s) => {
1672
+ const i = s;
1448
1673
  if (!i.isConnected || !i.offsetParent)
1449
1674
  return NodeFilter.FILTER_SKIP;
1450
- const a = getComputedStyle(i);
1451
- return a.overflowY === "auto" || a.overflowY === "scroll" || a.overflow === "auto" || a.overflow === "scroll" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
1675
+ const o = getComputedStyle(i);
1676
+ return o.overflowY === "auto" || o.overflowY === "scroll" || o.overflow === "auto" || o.overflow === "scroll" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
1452
1677
  }
1453
1678
  });
1454
1679
  let r;
1455
1680
  for (; (r = t.nextNode()) && e.length < 10; ) {
1456
- const n = r;
1457
- this.isElementScrollable(n) && e.push(n);
1681
+ const s = r;
1682
+ this.isElementScrollable(s) && e.push(s);
1458
1683
  }
1459
1684
  return e;
1460
1685
  }
@@ -1465,7 +1690,7 @@ class Et extends g {
1465
1690
  if (t.id)
1466
1691
  return `#${t.id}`;
1467
1692
  if (t.className && typeof t.className == "string") {
1468
- const r = t.className.split(" ").filter((n) => n.trim())[0];
1693
+ const r = t.className.split(" ").filter((s) => s.trim())[0];
1469
1694
  if (r)
1470
1695
  return `.${r}`;
1471
1696
  }
@@ -1475,42 +1700,42 @@ class Et extends g {
1475
1700
  return this.isWindowScrollable() ? e === window : this.containers.length === 0;
1476
1701
  }
1477
1702
  setupScrollContainer(e, t) {
1478
- if (this.containers.some((u) => u.element === e) || e !== window && !this.isElementScrollable(e))
1703
+ if (this.containers.some((d) => d.element === e) || e !== window && !this.isElementScrollable(e))
1479
1704
  return;
1480
- const n = () => {
1705
+ const s = () => {
1481
1706
  this.get("suppressNextScroll") || (this.clearContainerTimer(c), c.debounceTimer = window.setTimeout(() => {
1482
- const u = this.calculateScrollData(c);
1483
- if (u) {
1484
- const f = Date.now();
1485
- this.processScrollEvent(c, u, f);
1707
+ const d = this.calculateScrollData(c);
1708
+ if (d) {
1709
+ const _ = Date.now();
1710
+ this.processScrollEvent(c, d, _);
1486
1711
  }
1487
1712
  c.debounceTimer = null;
1488
1713
  }, 250));
1489
- }, i = this.getScrollTop(e), a = this.calculateScrollDepth(
1714
+ }, i = this.getScrollTop(e), o = this.calculateScrollDepth(
1490
1715
  i,
1491
1716
  this.getScrollHeight(e),
1492
1717
  this.getViewportHeight(e)
1493
- ), o = this.determineIfPrimary(e), c = {
1718
+ ), l = this.determineIfPrimary(e), c = {
1494
1719
  element: e,
1495
1720
  selector: t,
1496
- isPrimary: o,
1721
+ isPrimary: l,
1497
1722
  lastScrollPos: i,
1498
- lastDepth: a,
1499
- lastDirection: U.DOWN,
1723
+ lastDepth: o,
1724
+ lastDirection: H.DOWN,
1500
1725
  lastEventTime: 0,
1501
- maxDepthReached: a,
1726
+ maxDepthReached: o,
1502
1727
  debounceTimer: null,
1503
- listener: n
1728
+ listener: s
1504
1729
  };
1505
- this.containers.push(c), e instanceof Window ? window.addEventListener("scroll", n, { passive: !0 }) : e.addEventListener("scroll", n, { passive: !0 });
1730
+ this.containers.push(c), e instanceof Window ? window.addEventListener("scroll", s, { passive: !0 }) : e.addEventListener("scroll", s, { passive: !0 });
1506
1731
  }
1507
1732
  processScrollEvent(e, t, r) {
1508
1733
  if (!this.shouldEmitScrollEvent(e, t, r))
1509
1734
  return;
1510
1735
  e.lastEventTime = r, e.lastDepth = t.depth, e.lastDirection = t.direction;
1511
- const n = this.get("scrollEventCount") ?? 0;
1512
- this.set("scrollEventCount", n + 1), this.eventManager.track({
1513
- type: d.SCROLL,
1736
+ const s = this.get("scrollEventCount") ?? 0;
1737
+ this.set("scrollEventCount", s + 1), this.eventManager.track({
1738
+ type: u.SCROLL,
1514
1739
  scroll_data: {
1515
1740
  ...t,
1516
1741
  container_selector: e.selector,
@@ -1531,7 +1756,7 @@ class Et extends g {
1531
1756
  return Math.abs(t - e.lastDepth) >= this.minDepthChange;
1532
1757
  }
1533
1758
  logLimitOnce() {
1534
- this.limitWarningLogged || (this.limitWarningLogged = !0, l("warn", "Max scroll events per session reached", {
1759
+ this.limitWarningLogged || (this.limitWarningLogged = !0, a("warn", "Max scroll events per session reached", {
1535
1760
  data: { limit: this.maxEventsPerSession }
1536
1761
  }));
1537
1762
  }
@@ -1545,23 +1770,23 @@ class Et extends g {
1545
1770
  e.debounceTimer !== null && (clearTimeout(e.debounceTimer), e.debounceTimer = null);
1546
1771
  }
1547
1772
  getScrollDirection(e, t) {
1548
- return e > t ? U.DOWN : U.UP;
1773
+ return e > t ? H.DOWN : H.UP;
1549
1774
  }
1550
1775
  calculateScrollDepth(e, t, r) {
1551
1776
  if (t <= r)
1552
1777
  return 0;
1553
- const n = t - r;
1554
- return Math.min(100, Math.max(0, Math.floor(e / n * 100)));
1778
+ const s = t - r;
1779
+ return Math.min(100, Math.max(0, Math.floor(e / s * 100)));
1555
1780
  }
1556
1781
  calculateScrollData(e) {
1557
- const { element: t, lastScrollPos: r, lastEventTime: n } = e, i = this.getScrollTop(t), a = Date.now(), o = Math.abs(i - r);
1558
- if (o < 10 || t === window && !this.isWindowScrollable())
1782
+ const { element: t, lastScrollPos: r, lastEventTime: s } = e, i = this.getScrollTop(t), o = Date.now(), l = Math.abs(i - r);
1783
+ if (l < 10 || t === window && !this.isWindowScrollable())
1559
1784
  return null;
1560
- const c = this.getViewportHeight(t), u = this.getScrollHeight(t), f = this.getScrollDirection(i, r), _ = this.calculateScrollDepth(i, u, c), D = n > 0 ? a - n : 0, Q = D > 0 ? Math.round(o / D * 1e3) : 0;
1561
- return _ > e.maxDepthReached && (e.maxDepthReached = _), e.lastScrollPos = i, {
1562
- depth: _,
1563
- direction: f,
1564
- velocity: Q,
1785
+ const c = this.getViewportHeight(t), d = this.getScrollHeight(t), _ = this.getScrollDirection(i, r), g = this.calculateScrollDepth(i, d, c), L = s > 0 ? o - s : 0, m = L > 0 ? Math.round(l / L * 1e3) : 0;
1786
+ return g > e.maxDepthReached && (e.maxDepthReached = g), e.lastScrollPos = i, {
1787
+ depth: g,
1788
+ direction: _,
1789
+ velocity: m,
1565
1790
  max_depth_reached: e.maxDepthReached
1566
1791
  };
1567
1792
  }
@@ -1575,30 +1800,190 @@ class Et extends g {
1575
1800
  return e instanceof Window ? document.documentElement.scrollHeight : e.scrollHeight;
1576
1801
  }
1577
1802
  isElementScrollable(e) {
1578
- const t = getComputedStyle(e), r = t.overflowY === "auto" || t.overflowY === "scroll" || t.overflowX === "auto" || t.overflowX === "scroll" || t.overflow === "auto" || t.overflow === "scroll", n = e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth;
1579
- return r && n;
1803
+ const t = getComputedStyle(e), r = t.overflowY === "auto" || t.overflowY === "scroll" || t.overflowX === "auto" || t.overflowX === "scroll" || t.overflow === "auto" || t.overflow === "scroll", s = e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth;
1804
+ return r && s;
1580
1805
  }
1581
1806
  applyPrimaryScrollSelector(e) {
1582
1807
  let t;
1583
1808
  if (e === "window")
1584
1809
  t = window;
1585
1810
  else {
1586
- const n = document.querySelector(e);
1587
- if (!(n instanceof HTMLElement)) {
1588
- l("warn", `Selector "${e}" did not match an HTMLElement`);
1811
+ const s = document.querySelector(e);
1812
+ if (!(s instanceof HTMLElement)) {
1813
+ a("warn", `Selector "${e}" did not match an HTMLElement`);
1589
1814
  return;
1590
1815
  }
1591
- t = n;
1816
+ t = s;
1592
1817
  }
1593
- this.containers.forEach((n) => {
1594
- this.updateContainerPrimary(n, n.element === t);
1595
- }), !this.containers.some((n) => n.element === t) && t instanceof HTMLElement && this.isElementScrollable(t) && this.setupScrollContainer(t, e);
1818
+ this.containers.forEach((s) => {
1819
+ this.updateContainerPrimary(s, s.element === t);
1820
+ }), !this.containers.some((s) => s.element === t) && t instanceof HTMLElement && this.isElementScrollable(t) && this.setupScrollContainer(t, e);
1596
1821
  }
1597
1822
  updateContainerPrimary(e, t) {
1598
1823
  e.isPrimary = t;
1599
1824
  }
1600
1825
  }
1601
- class mt extends g {
1826
+ class wt extends S {
1827
+ eventManager;
1828
+ trackedElements = /* @__PURE__ */ new Map();
1829
+ observer = null;
1830
+ mutationObserver = null;
1831
+ mutationDebounceTimer = null;
1832
+ config = null;
1833
+ constructor(e) {
1834
+ super(), this.eventManager = e;
1835
+ }
1836
+ /**
1837
+ * Starts tracking viewport visibility for configured elements
1838
+ */
1839
+ startTracking() {
1840
+ const e = this.get("config");
1841
+ if (this.config = e.viewport ?? null, !this.config?.elements || this.config.elements.length === 0)
1842
+ return;
1843
+ const t = this.config.threshold ?? 0.5, r = this.config.minDwellTime ?? 1e3;
1844
+ if (t < 0 || t > 1) {
1845
+ a("warn", "ViewportHandler: Invalid threshold, must be between 0 and 1");
1846
+ return;
1847
+ }
1848
+ if (r < 0) {
1849
+ a("warn", "ViewportHandler: Invalid minDwellTime, must be non-negative");
1850
+ return;
1851
+ }
1852
+ if (typeof IntersectionObserver > "u") {
1853
+ a("warn", "ViewportHandler: IntersectionObserver not supported in this browser");
1854
+ return;
1855
+ }
1856
+ this.observer = new IntersectionObserver(this.handleIntersection, {
1857
+ threshold: t
1858
+ }), this.observeElements(), this.setupMutationObserver();
1859
+ }
1860
+ /**
1861
+ * Stops tracking and cleans up resources
1862
+ */
1863
+ stopTracking() {
1864
+ this.observer && (this.observer.disconnect(), this.observer = null), this.mutationObserver && (this.mutationObserver.disconnect(), this.mutationObserver = null), this.mutationDebounceTimer !== null && (window.clearTimeout(this.mutationDebounceTimer), this.mutationDebounceTimer = null);
1865
+ for (const e of this.trackedElements.values())
1866
+ e.timeoutId !== null && window.clearTimeout(e.timeoutId);
1867
+ this.trackedElements.clear();
1868
+ }
1869
+ /**
1870
+ * Query and observe all elements matching configured elements
1871
+ */
1872
+ observeElements() {
1873
+ if (!this.config || !this.observer) return;
1874
+ const e = this.config.maxTrackedElements ?? 100;
1875
+ let t = this.trackedElements.size;
1876
+ for (const r of this.config.elements)
1877
+ try {
1878
+ const s = document.querySelectorAll(r.selector);
1879
+ for (const i of Array.from(s)) {
1880
+ if (t >= e) {
1881
+ a("warn", "ViewportHandler: Maximum tracked elements reached", {
1882
+ data: {
1883
+ limit: e,
1884
+ selector: r.selector,
1885
+ message: "Some elements will not be tracked. Consider more specific selectors."
1886
+ }
1887
+ });
1888
+ return;
1889
+ }
1890
+ i.hasAttribute(`${v}-ignore`) || this.trackedElements.has(i) || (this.trackedElements.set(i, {
1891
+ element: i,
1892
+ selector: r.selector,
1893
+ id: r.id,
1894
+ name: r.name,
1895
+ startTime: null,
1896
+ timeoutId: null,
1897
+ lastFiredTime: null
1898
+ }), this.observer?.observe(i), t++);
1899
+ }
1900
+ } catch (s) {
1901
+ a("warn", `ViewportHandler: Invalid selector "${r.selector}"`, { error: s });
1902
+ }
1903
+ a("debug", "ViewportHandler: Elements tracked", {
1904
+ data: { count: t, limit: e }
1905
+ });
1906
+ }
1907
+ /**
1908
+ * Handles intersection events from IntersectionObserver
1909
+ */
1910
+ handleIntersection = (e) => {
1911
+ if (!this.config) return;
1912
+ const t = this.config.minDwellTime ?? 1e3;
1913
+ for (const r of e) {
1914
+ const s = this.trackedElements.get(r.target);
1915
+ s && (r.isIntersecting ? s.startTime === null && (s.startTime = performance.now(), s.timeoutId = window.setTimeout(() => {
1916
+ this.fireViewportEvent(s, r.intersectionRatio);
1917
+ }, t)) : s.startTime !== null && (s.timeoutId !== null && (window.clearTimeout(s.timeoutId), s.timeoutId = null), s.startTime = null));
1918
+ }
1919
+ };
1920
+ /**
1921
+ * Fires a viewport visible event
1922
+ */
1923
+ fireViewportEvent(e, t) {
1924
+ if (e.startTime === null) return;
1925
+ const r = Math.round(performance.now() - e.startTime);
1926
+ if (e.element.hasAttribute("data-tlog-ignore"))
1927
+ return;
1928
+ const s = this.config?.cooldownPeriod ?? 6e4, i = Date.now();
1929
+ if (e.lastFiredTime !== null && i - e.lastFiredTime < s) {
1930
+ a("debug", "ViewportHandler: Event suppressed by cooldown period", {
1931
+ data: {
1932
+ selector: e.selector,
1933
+ cooldownRemaining: s - (i - e.lastFiredTime)
1934
+ }
1935
+ }), e.startTime = null, e.timeoutId = null;
1936
+ return;
1937
+ }
1938
+ const o = {
1939
+ selector: e.selector,
1940
+ dwellTime: r,
1941
+ visibilityRatio: t,
1942
+ ...e.id !== void 0 && { id: e.id },
1943
+ ...e.name !== void 0 && { name: e.name }
1944
+ };
1945
+ this.eventManager.track({
1946
+ type: u.VIEWPORT_VISIBLE,
1947
+ viewport_data: o
1948
+ }), e.startTime = null, e.timeoutId = null, e.lastFiredTime = i;
1949
+ }
1950
+ /**
1951
+ * Sets up MutationObserver to detect dynamically added elements
1952
+ */
1953
+ setupMutationObserver() {
1954
+ if (!(!this.config || typeof MutationObserver > "u")) {
1955
+ if (!document.body) {
1956
+ a("warn", "ViewportHandler: document.body not available, skipping MutationObserver setup");
1957
+ return;
1958
+ }
1959
+ this.mutationObserver = new MutationObserver((e) => {
1960
+ let t = !1;
1961
+ for (const r of e)
1962
+ r.type === "childList" && (r.addedNodes.length > 0 && (t = !0), r.removedNodes.length > 0 && this.cleanupRemovedNodes(r.removedNodes));
1963
+ t && (this.mutationDebounceTimer !== null && window.clearTimeout(this.mutationDebounceTimer), this.mutationDebounceTimer = window.setTimeout(() => {
1964
+ this.observeElements(), this.mutationDebounceTimer = null;
1965
+ }, 100));
1966
+ }), this.mutationObserver.observe(document.body, {
1967
+ childList: !0,
1968
+ subtree: !0
1969
+ });
1970
+ }
1971
+ }
1972
+ /**
1973
+ * Cleans up tracking for removed DOM nodes
1974
+ */
1975
+ cleanupRemovedNodes(e) {
1976
+ e.forEach((t) => {
1977
+ if (t.nodeType !== 1) return;
1978
+ const r = t, s = this.trackedElements.get(r);
1979
+ s && (s.timeoutId !== null && window.clearTimeout(s.timeoutId), this.observer?.unobserve(r), this.trackedElements.delete(r)), Array.from(this.trackedElements.keys()).filter((o) => r.contains(o)).forEach((o) => {
1980
+ const l = this.trackedElements.get(o);
1981
+ l && l.timeoutId !== null && window.clearTimeout(l.timeoutId), this.observer?.unobserve(o), this.trackedElements.delete(o);
1982
+ });
1983
+ });
1984
+ }
1985
+ }
1986
+ class yt extends S {
1602
1987
  isInitialized = !1;
1603
1988
  async initialize() {
1604
1989
  if (this.isInitialized)
@@ -1612,7 +1997,7 @@ class mt extends g {
1612
1997
  }
1613
1998
  await this.loadScript(e), this.configureGtag(e, t), this.isInitialized = !0;
1614
1999
  } catch (r) {
1615
- l("error", "Google Analytics initialization failed", { error: r });
2000
+ a("error", "Google Analytics initialization failed", { error: r });
1616
2001
  }
1617
2002
  }
1618
2003
  trackEvent(e, t) {
@@ -1621,7 +2006,7 @@ class mt extends g {
1621
2006
  const r = Array.isArray(t) ? { items: t } : t;
1622
2007
  window.gtag("event", e, r);
1623
2008
  } catch (r) {
1624
- l("error", "Google Analytics event tracking failed", { error: r });
2009
+ a("error", "Google Analytics event tracking failed", { error: r });
1625
2010
  }
1626
2011
  }
1627
2012
  cleanup() {
@@ -1634,12 +2019,12 @@ class mt extends g {
1634
2019
  }
1635
2020
  async loadScript(e) {
1636
2021
  return new Promise((t, r) => {
1637
- const n = document.createElement("script");
1638
- n.id = "tracelog-ga-script", n.async = !0, n.src = `https://www.googletagmanager.com/gtag/js?id=${e}`, n.onload = () => {
2022
+ const s = document.createElement("script");
2023
+ s.id = "tracelog-ga-script", s.async = !0, s.src = `https://www.googletagmanager.com/gtag/js?id=${e}`, s.onload = () => {
1639
2024
  t();
1640
- }, n.onerror = () => {
2025
+ }, s.onerror = () => {
1641
2026
  r(new Error("Failed to load Google Analytics script"));
1642
- }, document.head.appendChild(n);
2027
+ }, document.head.appendChild(s);
1643
2028
  });
1644
2029
  }
1645
2030
  configureGtag(e, t) {
@@ -1654,14 +2039,14 @@ class mt extends g {
1654
2039
  `, document.head.appendChild(r);
1655
2040
  }
1656
2041
  }
1657
- class pt {
2042
+ class Lt {
1658
2043
  storage;
1659
2044
  sessionStorageRef;
1660
2045
  fallbackStorage = /* @__PURE__ */ new Map();
1661
2046
  fallbackSessionStorage = /* @__PURE__ */ new Map();
1662
2047
  hasQuotaExceededError = !1;
1663
2048
  constructor() {
1664
- this.storage = this.initializeStorage("localStorage"), this.sessionStorageRef = this.initializeStorage("sessionStorage"), this.storage || l("warn", "localStorage not available, using memory fallback"), this.sessionStorageRef || l("warn", "sessionStorage not available, using memory fallback");
2049
+ this.storage = this.initializeStorage("localStorage"), this.sessionStorageRef = this.initializeStorage("sessionStorage"), this.storage || a("warn", "localStorage not available, using memory fallback"), this.sessionStorageRef || a("warn", "sessionStorage not available, using memory fallback");
1665
2050
  }
1666
2051
  /**
1667
2052
  * Retrieves an item from storage
@@ -1685,7 +2070,7 @@ class pt {
1685
2070
  }
1686
2071
  } catch (r) {
1687
2072
  if (r instanceof DOMException && r.name === "QuotaExceededError")
1688
- if (this.hasQuotaExceededError = !0, l("warn", "localStorage quota exceeded, attempting cleanup", {
2073
+ if (this.hasQuotaExceededError = !0, a("warn", "localStorage quota exceeded, attempting cleanup", {
1689
2074
  data: { key: e, valueSize: t.length }
1690
2075
  }), this.cleanupOldData())
1691
2076
  try {
@@ -1694,13 +2079,13 @@ class pt {
1694
2079
  return;
1695
2080
  }
1696
2081
  } catch (i) {
1697
- l("error", "localStorage quota exceeded even after cleanup - data will not persist", {
2082
+ a("error", "localStorage quota exceeded even after cleanup - data will not persist", {
1698
2083
  error: i,
1699
2084
  data: { key: e, valueSize: t.length }
1700
2085
  });
1701
2086
  }
1702
2087
  else
1703
- l("error", "localStorage quota exceeded and no data to cleanup - data will not persist", {
2088
+ a("error", "localStorage quota exceeded and no data to cleanup - data will not persist", {
1704
2089
  error: r,
1705
2090
  data: { key: e, valueSize: t.length }
1706
2091
  });
@@ -1734,7 +2119,7 @@ class pt {
1734
2119
  this.storage.removeItem(t);
1735
2120
  }), this.fallbackStorage.clear();
1736
2121
  } catch (e) {
1737
- l("error", "Failed to clear storage", { error: e }), this.fallbackStorage.clear();
2122
+ a("error", "Failed to clear storage", { error: e }), this.fallbackStorage.clear();
1738
2123
  }
1739
2124
  }
1740
2125
  /**
@@ -1760,8 +2145,8 @@ class pt {
1760
2145
  try {
1761
2146
  const e = [], t = [];
1762
2147
  for (let i = 0; i < this.storage.length; i++) {
1763
- const a = this.storage.key(i);
1764
- a?.startsWith("tracelog_") && (e.push(a), a.startsWith("tracelog_persisted_events_") && t.push(a));
2148
+ const o = this.storage.key(i);
2149
+ o?.startsWith("tracelog_") && (e.push(o), o.startsWith("tracelog_persisted_events_") && t.push(o));
1765
2150
  }
1766
2151
  if (t.length > 0)
1767
2152
  return t.forEach((i) => {
@@ -1770,15 +2155,15 @@ class pt {
1770
2155
  } catch {
1771
2156
  }
1772
2157
  }), !0;
1773
- const r = ["tracelog_session_", "tracelog_user_id", "tracelog_device_id", "tracelog_config"], n = e.filter((i) => !r.some((a) => i.startsWith(a)));
1774
- return n.length > 0 ? (n.slice(0, 5).forEach((a) => {
2158
+ const r = ["tracelog_session_", "tracelog_user_id", "tracelog_device_id", "tracelog_config"], s = e.filter((i) => !r.some((o) => i.startsWith(o)));
2159
+ return s.length > 0 ? (s.slice(0, 5).forEach((o) => {
1775
2160
  try {
1776
- this.storage.removeItem(a);
2161
+ this.storage.removeItem(o);
1777
2162
  } catch {
1778
2163
  }
1779
2164
  }), !0) : !1;
1780
2165
  } catch (e) {
1781
- return l("error", "Failed to cleanup old data", { error: e }), !1;
2166
+ return a("error", "Failed to cleanup old data", { error: e }), !1;
1782
2167
  }
1783
2168
  }
1784
2169
  /**
@@ -1815,7 +2200,7 @@ class pt {
1815
2200
  return;
1816
2201
  }
1817
2202
  } catch (r) {
1818
- r instanceof DOMException && r.name === "QuotaExceededError" && l("error", "sessionStorage quota exceeded - data will not persist", {
2203
+ r instanceof DOMException && r.name === "QuotaExceededError" && a("error", "sessionStorage quota exceeded - data will not persist", {
1819
2204
  error: r,
1820
2205
  data: { key: e, valueSize: t.length }
1821
2206
  });
@@ -1832,7 +2217,7 @@ class pt {
1832
2217
  this.fallbackSessionStorage.delete(e);
1833
2218
  }
1834
2219
  }
1835
- class _t extends g {
2220
+ class Mt extends S {
1836
2221
  eventManager;
1837
2222
  reportedByNav = /* @__PURE__ */ new Map();
1838
2223
  observers = [];
@@ -1849,7 +2234,7 @@ class _t extends g {
1849
2234
  try {
1850
2235
  e.disconnect();
1851
2236
  } catch (r) {
1852
- l("warn", "Failed to disconnect performance observer", { error: r, data: { observerIndex: t } });
2237
+ a("warn", "Failed to disconnect performance observer", { error: r, data: { observerIndex: t } });
1853
2238
  }
1854
2239
  }), this.observers.length = 0, this.reportedByNav.clear();
1855
2240
  }
@@ -1857,7 +2242,7 @@ class _t extends g {
1857
2242
  this.reportTTFB(), this.safeObserve(
1858
2243
  "largest-contentful-paint",
1859
2244
  (r) => {
1860
- const n = r.getEntries(), i = n[n.length - 1];
2245
+ const s = r.getEntries(), i = s[s.length - 1];
1861
2246
  i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(2)) });
1862
2247
  },
1863
2248
  { type: "largest-contentful-paint", buffered: !0 },
@@ -1867,14 +2252,14 @@ class _t extends g {
1867
2252
  this.safeObserve(
1868
2253
  "layout-shift",
1869
2254
  (r) => {
1870
- const n = this.getNavigationId();
1871
- n !== t && (e = 0, t = n);
2255
+ const s = this.getNavigationId();
2256
+ s !== t && (e = 0, t = s);
1872
2257
  const i = r.getEntries();
1873
- for (const a of i) {
1874
- if (a.hadRecentInput === !0)
2258
+ for (const o of i) {
2259
+ if (o.hadRecentInput === !0)
1875
2260
  continue;
1876
- const o = typeof a.value == "number" ? a.value : 0;
1877
- e += o;
2261
+ const l = typeof o.value == "number" ? o.value : 0;
2262
+ e += l;
1878
2263
  }
1879
2264
  this.sendVital({ type: "CLS", value: Number(e.toFixed(2)) });
1880
2265
  },
@@ -1882,34 +2267,34 @@ class _t extends g {
1882
2267
  ), this.safeObserve(
1883
2268
  "paint",
1884
2269
  (r) => {
1885
- for (const n of r.getEntries())
1886
- n.name === "first-contentful-paint" && this.sendVital({ type: "FCP", value: Number(n.startTime.toFixed(2)) });
2270
+ for (const s of r.getEntries())
2271
+ s.name === "first-contentful-paint" && this.sendVital({ type: "FCP", value: Number(s.startTime.toFixed(2)) });
1887
2272
  },
1888
2273
  { type: "paint", buffered: !0 },
1889
2274
  !0
1890
2275
  ), this.safeObserve(
1891
2276
  "event",
1892
2277
  (r) => {
1893
- let n = 0;
2278
+ let s = 0;
1894
2279
  const i = r.getEntries();
1895
- for (const a of i) {
1896
- const o = (a.processingEnd ?? 0) - (a.startTime ?? 0);
1897
- n = Math.max(n, o);
2280
+ for (const o of i) {
2281
+ const l = (o.processingEnd ?? 0) - (o.startTime ?? 0);
2282
+ s = Math.max(s, l);
1898
2283
  }
1899
- n > 0 && this.sendVital({ type: "INP", value: Number(n.toFixed(2)) });
2284
+ s > 0 && this.sendVital({ type: "INP", value: Number(s.toFixed(2)) });
1900
2285
  },
1901
2286
  { type: "event", buffered: !0 }
1902
2287
  );
1903
2288
  }
1904
2289
  async initWebVitals() {
1905
2290
  try {
1906
- const { onLCP: e, onCLS: t, onFCP: r, onTTFB: n, onINP: i } = await Promise.resolve().then(() => Vt), a = (o) => (c) => {
1907
- const u = Number(c.value.toFixed(2));
1908
- this.sendVital({ type: o, value: u });
2291
+ const { onLCP: e, onCLS: t, onFCP: r, onTTFB: s, onINP: i } = await Promise.resolve().then(() => Qt), o = (l) => (c) => {
2292
+ const d = Number(c.value.toFixed(2));
2293
+ this.sendVital({ type: l, value: d });
1909
2294
  };
1910
- e(a("LCP")), t(a("CLS")), r(a("FCP")), n(a("TTFB")), i(a("INP"));
2295
+ e(o("LCP"), { reportAllChanges: !1 }), t(o("CLS"), { reportAllChanges: !1 }), r(o("FCP"), { reportAllChanges: !1 }), s(o("TTFB"), { reportAllChanges: !1 }), i(o("INP"), { reportAllChanges: !1 });
1911
2296
  } catch (e) {
1912
- l("warn", "Failed to load web-vitals library, using fallback", { error: e }), this.observeWebVitalsFallback();
2297
+ a("warn", "Failed to load web-vitals library, using fallback", { error: e }), this.observeWebVitalsFallback();
1913
2298
  }
1914
2299
  }
1915
2300
  reportTTFB() {
@@ -1920,7 +2305,7 @@ class _t extends g {
1920
2305
  const t = e.responseStart;
1921
2306
  typeof t == "number" && Number.isFinite(t) && this.sendVital({ type: "TTFB", value: Number(t.toFixed(2)) });
1922
2307
  } catch (e) {
1923
- l("warn", "Failed to report TTFB", { error: e });
2308
+ a("warn", "Failed to report TTFB", { error: e });
1924
2309
  }
1925
2310
  }
1926
2311
  observeLongTasks() {
@@ -1929,8 +2314,8 @@ class _t extends g {
1929
2314
  (e) => {
1930
2315
  const t = e.getEntries();
1931
2316
  for (const r of t) {
1932
- const n = Number(r.duration.toFixed(2)), i = Date.now();
1933
- i - this.lastLongTaskSentAt >= je && (this.shouldSendVital("LONG_TASK", n) && this.trackWebVital("LONG_TASK", n), this.lastLongTaskSentAt = i);
2317
+ const s = Number(r.duration.toFixed(2)), i = Date.now();
2318
+ i - this.lastLongTaskSentAt >= Ke && (this.shouldSendVital("LONG_TASK", s) && this.trackWebVital("LONG_TASK", s), this.lastLongTaskSentAt = i);
1934
2319
  }
1935
2320
  },
1936
2321
  { type: "longtask", buffered: !0 }
@@ -1950,11 +2335,11 @@ class _t extends g {
1950
2335
  }
1951
2336
  trackWebVital(e, t) {
1952
2337
  if (!Number.isFinite(t)) {
1953
- l("warn", "Invalid web vital value", { data: { type: e, value: t } });
2338
+ a("warn", "Invalid web vital value", { data: { type: e, value: t } });
1954
2339
  return;
1955
2340
  }
1956
2341
  this.eventManager.track({
1957
- type: d.WEB_VITALS,
2342
+ type: u.WEB_VITALS,
1958
2343
  web_vitals: {
1959
2344
  type: e,
1960
2345
  value: t
@@ -1969,7 +2354,7 @@ class _t extends g {
1969
2354
  const t = e.startTime || performance.now(), r = Math.random().toString(36).substr(2, 5);
1970
2355
  return `${t.toFixed(2)}_${window.location.pathname}_${r}`;
1971
2356
  } catch (e) {
1972
- return l("warn", "Failed to get navigation ID", { error: e }), null;
2357
+ return a("warn", "Failed to get navigation ID", { error: e }), null;
1973
2358
  }
1974
2359
  }
1975
2360
  isObserverSupported(e) {
@@ -1977,28 +2362,28 @@ class _t extends g {
1977
2362
  const t = PerformanceObserver.supportedEntryTypes;
1978
2363
  return !t || t.includes(e);
1979
2364
  }
1980
- safeObserve(e, t, r, n = !1) {
2365
+ safeObserve(e, t, r, s = !1) {
1981
2366
  try {
1982
2367
  if (!this.isObserverSupported(e))
1983
2368
  return !1;
1984
- const i = new PerformanceObserver((a, o) => {
2369
+ const i = new PerformanceObserver((o, l) => {
1985
2370
  try {
1986
- t(a, o);
2371
+ t(o, l);
1987
2372
  } catch (c) {
1988
- l("warn", "Observer callback failed", {
2373
+ a("warn", "Observer callback failed", {
1989
2374
  error: c,
1990
2375
  data: { type: e }
1991
2376
  });
1992
2377
  }
1993
- if (n)
2378
+ if (s)
1994
2379
  try {
1995
- o.disconnect();
2380
+ l.disconnect();
1996
2381
  } catch {
1997
2382
  }
1998
2383
  });
1999
- return i.observe(r ?? { type: e, buffered: !0 }), n || this.observers.push(i), !0;
2384
+ return i.observe(r ?? { type: e, buffered: !0 }), s || this.observers.push(i), !0;
2000
2385
  } catch (i) {
2001
- return l("warn", "Failed to create performance observer", {
2386
+ return a("warn", "Failed to create performance observer", {
2002
2387
  error: i,
2003
2388
  data: { type: e }
2004
2389
  }), !1;
@@ -2006,14 +2391,17 @@ class _t extends g {
2006
2391
  }
2007
2392
  shouldSendVital(e, t) {
2008
2393
  if (typeof t != "number" || !Number.isFinite(t))
2009
- return l("warn", "Invalid web vital value", { data: { type: e, value: t } }), !1;
2394
+ return a("warn", "Invalid web vital value", { data: { type: e, value: t } }), !1;
2010
2395
  const r = this.vitalThresholds[e];
2011
2396
  return !(typeof r == "number" && t <= r);
2012
2397
  }
2013
2398
  }
2014
- class Tt extends g {
2399
+ class Nt extends S {
2015
2400
  eventManager;
2016
2401
  recentErrors = /* @__PURE__ */ new Map();
2402
+ errorBurstCounter = 0;
2403
+ burstWindowStart = 0;
2404
+ burstBackoffUntil = 0;
2017
2405
  constructor(e) {
2018
2406
  super(), this.eventManager = e;
2019
2407
  }
@@ -2021,20 +2409,34 @@ class Tt extends g {
2021
2409
  window.addEventListener("error", this.handleError), window.addEventListener("unhandledrejection", this.handleRejection);
2022
2410
  }
2023
2411
  stopTracking() {
2024
- window.removeEventListener("error", this.handleError), window.removeEventListener("unhandledrejection", this.handleRejection), this.recentErrors.clear();
2412
+ window.removeEventListener("error", this.handleError), window.removeEventListener("unhandledrejection", this.handleRejection), this.recentErrors.clear(), this.errorBurstCounter = 0, this.burstWindowStart = 0, this.burstBackoffUntil = 0;
2025
2413
  }
2414
+ /**
2415
+ * Checks sampling rate and burst detection (Phase 3)
2416
+ * Returns false if in cooldown period after burst detection
2417
+ */
2026
2418
  shouldSample() {
2027
- const t = this.get("config")?.errorSampling ?? Ae;
2028
- return Math.random() < t;
2419
+ const e = Date.now();
2420
+ if (e < this.burstBackoffUntil)
2421
+ return !1;
2422
+ if (e - this.burstWindowStart > Ze && (this.errorBurstCounter = 0, this.burstWindowStart = e), this.errorBurstCounter++, this.errorBurstCounter > Je)
2423
+ return this.burstBackoffUntil = e + me, a("warn", "Error burst detected - entering cooldown", {
2424
+ data: {
2425
+ errorsInWindow: this.errorBurstCounter,
2426
+ cooldownMs: me
2427
+ }
2428
+ }), !1;
2429
+ const r = this.get("config")?.errorSampling ?? Le;
2430
+ return Math.random() < r;
2029
2431
  }
2030
2432
  handleError = (e) => {
2031
2433
  if (!this.shouldSample())
2032
2434
  return;
2033
2435
  const t = this.sanitize(e.message || "Unknown error");
2034
- this.shouldSuppressError(b.JS_ERROR, t) || this.eventManager.track({
2035
- type: d.ERROR,
2436
+ this.shouldSuppressError(P.JS_ERROR, t) || this.eventManager.track({
2437
+ type: u.ERROR,
2036
2438
  error_data: {
2037
- type: b.JS_ERROR,
2439
+ type: P.JS_ERROR,
2038
2440
  message: t,
2039
2441
  ...e.filename && { filename: e.filename },
2040
2442
  ...e.lineno && { line: e.lineno },
@@ -2046,10 +2448,10 @@ class Tt extends g {
2046
2448
  if (!this.shouldSample())
2047
2449
  return;
2048
2450
  const t = this.extractRejectionMessage(e.reason), r = this.sanitize(t);
2049
- this.shouldSuppressError(b.PROMISE_REJECTION, r) || this.eventManager.track({
2050
- type: d.ERROR,
2451
+ this.shouldSuppressError(P.PROMISE_REJECTION, r) || this.eventManager.track({
2452
+ type: u.ERROR,
2051
2453
  error_data: {
2052
- type: b.PROMISE_REJECTION,
2454
+ type: P.PROMISE_REJECTION,
2053
2455
  message: r
2054
2456
  }
2055
2457
  });
@@ -2069,33 +2471,33 @@ class Tt extends g {
2069
2471
  }
2070
2472
  sanitize(e) {
2071
2473
  let t = e.length > fe ? e.slice(0, fe) + "..." : e;
2072
- for (const r of ae) {
2073
- const n = new RegExp(r.source, r.flags);
2074
- t = t.replace(n, "[REDACTED]");
2474
+ for (const r of le) {
2475
+ const s = new RegExp(r.source, r.flags);
2476
+ t = t.replace(s, "[REDACTED]");
2075
2477
  }
2076
2478
  return t;
2077
2479
  }
2078
2480
  shouldSuppressError(e, t) {
2079
- const r = Date.now(), n = `${e}:${t}`, i = this.recentErrors.get(n);
2080
- return i && r - i < ge ? (this.recentErrors.set(n, r), !0) : (this.recentErrors.set(n, r), this.recentErrors.size > Xe ? (this.recentErrors.clear(), this.recentErrors.set(n, r), !1) : (this.recentErrors.size > H && this.pruneOldErrors(), !1));
2481
+ const r = Date.now(), s = `${e}:${t}`, i = this.recentErrors.get(s);
2482
+ return i && r - i < ge ? (this.recentErrors.set(s, r), !0) : (this.recentErrors.set(s, r), this.recentErrors.size > qe ? (this.recentErrors.clear(), this.recentErrors.set(s, r), !1) : (this.recentErrors.size > x && this.pruneOldErrors(), !1));
2081
2483
  }
2082
2484
  pruneOldErrors() {
2083
2485
  const e = Date.now();
2084
- for (const [n, i] of this.recentErrors.entries())
2085
- e - i > ge && this.recentErrors.delete(n);
2086
- if (this.recentErrors.size <= H)
2486
+ for (const [s, i] of this.recentErrors.entries())
2487
+ e - i > ge && this.recentErrors.delete(s);
2488
+ if (this.recentErrors.size <= x)
2087
2489
  return;
2088
- const t = Array.from(this.recentErrors.entries()).sort((n, i) => n[1] - i[1]), r = this.recentErrors.size - H;
2089
- for (let n = 0; n < r; n += 1) {
2090
- const i = t[n];
2490
+ const t = Array.from(this.recentErrors.entries()).sort((s, i) => s[1] - i[1]), r = this.recentErrors.size - x;
2491
+ for (let s = 0; s < r; s += 1) {
2492
+ const i = t[s];
2091
2493
  i && this.recentErrors.delete(i[0]);
2092
2494
  }
2093
2495
  }
2094
2496
  }
2095
- class It extends g {
2497
+ class Rt extends S {
2096
2498
  isInitialized = !1;
2097
2499
  suppressNextScrollTimer = null;
2098
- emitter = new lt();
2500
+ emitter = new gt();
2099
2501
  managers = {};
2100
2502
  handlers = {};
2101
2503
  integrations = {};
@@ -2104,10 +2506,10 @@ class It extends g {
2104
2506
  }
2105
2507
  async init(e = {}) {
2106
2508
  if (!this.isInitialized) {
2107
- this.managers.storage = new pt();
2509
+ this.managers.storage = new Lt();
2108
2510
  try {
2109
- this.setupState(e), await this.setupIntegrations(), this.managers.event = new ut(this.managers.storage, this.integrations.googleAnalytics, this.emitter), this.initializeHandlers(), await this.managers.event.recoverPersistedEvents().catch((t) => {
2110
- l("warn", "Failed to recover persisted events", { error: t });
2511
+ this.setupState(e), await this.setupIntegrations(), this.managers.event = new St(this.managers.storage, this.integrations.googleAnalytics, this.emitter), this.initializeHandlers(), await this.managers.event.recoverPersistedEvents().catch((t) => {
2512
+ a("warn", "Failed to recover persisted events", { error: t });
2111
2513
  }), this.isInitialized = !0;
2112
2514
  } catch (t) {
2113
2515
  this.destroy(!0);
@@ -2119,14 +2521,14 @@ class It extends g {
2119
2521
  sendCustomEvent(e, t) {
2120
2522
  if (!this.managers.event)
2121
2523
  return;
2122
- const { valid: r, error: n, sanitizedMetadata: i } = ot(e, t);
2524
+ const { valid: r, error: s, sanitizedMetadata: i } = ft(e, t);
2123
2525
  if (!r) {
2124
- if (this.get("mode") === C.QA)
2125
- throw new Error(`[TraceLog] Custom event "${e}" validation failed: ${n}`);
2526
+ if (this.get("mode") === D.QA)
2527
+ throw new Error(`[TraceLog] Custom event "${e}" validation failed: ${s}`);
2126
2528
  return;
2127
2529
  }
2128
2530
  this.managers.event.track({
2129
- type: d.CUSTOM,
2531
+ type: u.CUSTOM,
2130
2532
  custom_event: {
2131
2533
  name: e,
2132
2534
  ...i && { metadata: i }
@@ -2144,33 +2546,33 @@ class It extends g {
2144
2546
  try {
2145
2547
  t.stopTracking();
2146
2548
  } catch (r) {
2147
- l("warn", "Failed to stop tracking", { error: r });
2549
+ a("warn", "Failed to stop tracking", { error: r });
2148
2550
  }
2149
2551
  }), this.suppressNextScrollTimer && (clearTimeout(this.suppressNextScrollTimer), this.suppressNextScrollTimer = null), this.managers.event?.flushImmediatelySync(), this.managers.event?.stop(), this.emitter.removeAllListeners(), this.set("hasStartSession", !1), this.set("suppressNextScroll", !1), this.set("sessionId", null), this.isInitialized = !1, this.handlers = {});
2150
2552
  }
2151
2553
  setupState(e = {}) {
2152
2554
  this.set("config", e);
2153
- const t = dt.getId(this.managers.storage);
2555
+ const t = _t.getId(this.managers.storage);
2154
2556
  this.set("userId", t);
2155
- const r = Ze(e);
2557
+ const r = it(e);
2156
2558
  this.set("collectApiUrl", r);
2157
- const n = Ge();
2158
- this.set("device", n);
2159
- const i = J(window.location.href, e.sensitiveQueryParams);
2559
+ const s = $e();
2560
+ this.set("device", s);
2561
+ const i = ee(window.location.href, e.sensitiveQueryParams);
2160
2562
  this.set("pageUrl", i);
2161
- const a = Ke() ? C.QA : void 0;
2162
- a && this.set("mode", a);
2563
+ const o = rt() ? D.QA : void 0;
2564
+ o && this.set("mode", o);
2163
2565
  }
2164
2566
  async setupIntegrations() {
2165
2567
  if (this.get("config").integrations?.googleAnalytics?.measurementId?.trim())
2166
2568
  try {
2167
- this.integrations.googleAnalytics = new mt(), await this.integrations.googleAnalytics.initialize();
2569
+ this.integrations.googleAnalytics = new yt(), await this.integrations.googleAnalytics.initialize();
2168
2570
  } catch {
2169
2571
  this.integrations.googleAnalytics = void 0;
2170
2572
  }
2171
2573
  }
2172
2574
  initializeHandlers() {
2173
- this.handlers.session = new ft(
2575
+ this.handlers.session = new pt(
2174
2576
  this.managers.storage,
2175
2577
  this.managers.event
2176
2578
  ), this.handlers.session.startTracking();
@@ -2179,83 +2581,83 @@ class It extends g {
2179
2581
  this.set("suppressNextScroll", !1);
2180
2582
  }, 500);
2181
2583
  };
2182
- this.handlers.pageView = new gt(this.managers.event, e), this.handlers.pageView.startTracking(), this.handlers.click = new St(this.managers.event), this.handlers.click.startTracking(), this.handlers.scroll = new Et(this.managers.event), this.handlers.scroll.startTracking(), this.handlers.performance = new _t(this.managers.event), this.handlers.performance.startTracking().catch((t) => {
2183
- l("warn", "Failed to start performance tracking", { error: t });
2184
- }), this.handlers.error = new Tt(this.managers.event), this.handlers.error.startTracking();
2584
+ this.handlers.pageView = new It(this.managers.event, e), this.handlers.pageView.startTracking(), this.handlers.click = new vt(this.managers.event), this.handlers.click.startTracking(), this.handlers.scroll = new At(this.managers.event), this.handlers.scroll.startTracking(), this.handlers.performance = new Mt(this.managers.event), this.handlers.performance.startTracking().catch((t) => {
2585
+ a("warn", "Failed to start performance tracking", { error: t });
2586
+ }), this.handlers.error = new Nt(this.managers.event), this.handlers.error.startTracking(), this.get("config").viewport && (this.handlers.viewport = new wt(this.managers.event), this.handlers.viewport.startTracking());
2185
2587
  }
2186
2588
  }
2187
- const y = [];
2188
- let h = null, L = !1, x = !1;
2189
- const vt = async (s) => {
2589
+ const N = [];
2590
+ let f = null, b = !1, F = !1;
2591
+ const Ot = async (n) => {
2190
2592
  if (typeof window > "u" || typeof document > "u")
2191
2593
  throw new Error("[TraceLog] This library can only be used in a browser environment");
2192
- if (!window.__traceLogDisabled && !h && !L) {
2193
- L = !0;
2594
+ if (!window.__traceLogDisabled && !f && !b) {
2595
+ b = !0;
2194
2596
  try {
2195
- const e = st(s ?? {}), t = new It();
2597
+ const e = ut(n ?? {}), t = new Rt();
2196
2598
  try {
2197
- y.forEach(({ event: i, callback: a }) => {
2198
- t.on(i, a);
2199
- }), y.length = 0;
2200
- const r = t.init(e), n = new Promise((i, a) => {
2599
+ N.forEach(({ event: i, callback: o }) => {
2600
+ t.on(i, o);
2601
+ }), N.length = 0;
2602
+ const r = t.init(e), s = new Promise((i, o) => {
2201
2603
  setTimeout(() => {
2202
- a(new Error("[TraceLog] Initialization timeout after 10000ms"));
2604
+ o(new Error("[TraceLog] Initialization timeout after 10000ms"));
2203
2605
  }, 1e4);
2204
2606
  });
2205
- await Promise.race([r, n]), h = t;
2607
+ await Promise.race([r, s]), f = t;
2206
2608
  } catch (r) {
2207
2609
  try {
2208
2610
  t.destroy(!0);
2209
- } catch (n) {
2210
- l("error", "Failed to cleanup partially initialized app", { error: n });
2611
+ } catch (s) {
2612
+ a("error", "Failed to cleanup partially initialized app", { error: s });
2211
2613
  }
2212
2614
  throw r;
2213
2615
  }
2214
2616
  } catch (e) {
2215
- throw h = null, e;
2617
+ throw f = null, e;
2216
2618
  } finally {
2217
- L = !1;
2619
+ b = !1;
2218
2620
  }
2219
2621
  }
2220
- }, yt = (s, e) => {
2221
- if (!h)
2622
+ }, bt = (n, e) => {
2623
+ if (!f)
2222
2624
  throw new Error("[TraceLog] TraceLog not initialized. Please call init() first.");
2223
- if (x)
2625
+ if (F)
2224
2626
  throw new Error("[TraceLog] Cannot send events while TraceLog is being destroyed");
2225
- h.sendCustomEvent(s, e);
2226
- }, At = (s, e) => {
2227
- if (!h || L) {
2228
- y.push({ event: s, callback: e });
2627
+ f.sendCustomEvent(n, e);
2628
+ }, Ct = (n, e) => {
2629
+ if (!f || b) {
2630
+ N.push({ event: n, callback: e });
2229
2631
  return;
2230
2632
  }
2231
- h.on(s, e);
2232
- }, wt = (s, e) => {
2233
- if (!h) {
2234
- const t = y.findIndex((r) => r.event === s && r.callback === e);
2235
- t !== -1 && y.splice(t, 1);
2633
+ f.on(n, e);
2634
+ }, Pt = (n, e) => {
2635
+ if (!f) {
2636
+ const t = N.findIndex((r) => r.event === n && r.callback === e);
2637
+ t !== -1 && N.splice(t, 1);
2236
2638
  return;
2237
2639
  }
2238
- h.off(s, e);
2239
- }, Mt = () => h !== null, Nt = () => {
2240
- if (x)
2640
+ f.off(n, e);
2641
+ }, Dt = () => f !== null, Vt = () => {
2642
+ if (F)
2241
2643
  throw new Error("[TraceLog] Destroy operation already in progress");
2242
- if (!h)
2644
+ if (!f)
2243
2645
  throw new Error("[TraceLog] App not initialized");
2244
- x = !0;
2646
+ F = !0;
2245
2647
  try {
2246
- h.destroy(), h = null, L = !1, y.length = 0;
2247
- } catch (s) {
2248
- h = null, L = !1, y.length = 0, l("warn", "Error during destroy, forced cleanup completed", { error: s });
2648
+ f.destroy(), f = null, b = !1, N.length = 0;
2649
+ } catch (n) {
2650
+ f = null, b = !1, N.length = 0, a("warn", "Error during destroy, forced cleanup completed", { error: n });
2249
2651
  } finally {
2250
- x = !1;
2652
+ F = !1;
2251
2653
  }
2252
- }, Jt = {
2654
+ }, or = {
2253
2655
  WEB_VITALS_THRESHOLDS: ye
2254
2656
  // Business thresholds for performance analysis
2255
- }, Zt = {
2256
- PII_PATTERNS: ae
2657
+ }, ar = {
2658
+ PII_PATTERNS: le
2257
2659
  // Patterns for sensitive data protection
2258
- }, er = {
2660
+ }, lr = {
2259
2661
  LOW_ACTIVITY_EVENT_COUNT: 50,
2260
2662
  HIGH_ACTIVITY_EVENT_COUNT: 1e3,
2261
2663
  MIN_EVENTS_FOR_DYNAMIC_CALCULATION: 100,
@@ -2265,7 +2667,7 @@ const vt = async (s) => {
2265
2667
  MIN_ENGAGED_SESSION_DURATION_MS: 30 * 1e3,
2266
2668
  MIN_SCROLL_DEPTH_ENGAGEMENT: 25
2267
2669
  // 25% scroll depth for engagement
2268
- }, tr = {
2670
+ }, cr = {
2269
2671
  INACTIVITY_TIMEOUT_MS: 1800 * 1e3,
2270
2672
  // 30min for analytics (vs 15min client)
2271
2673
  SHORT_SESSION_THRESHOLD_MS: 30 * 1e3,
@@ -2273,20 +2675,20 @@ const vt = async (s) => {
2273
2675
  LONG_SESSION_THRESHOLD_MS: 1800 * 1e3,
2274
2676
  MAX_REALISTIC_SESSION_DURATION_MS: 480 * 60 * 1e3
2275
2677
  // Filter outliers
2276
- }, rr = {
2678
+ }, ur = {
2277
2679
  MOBILE_MAX_WIDTH: 768,
2278
2680
  TABLET_MAX_WIDTH: 1024,
2279
2681
  MOBILE_PERFORMANCE_FACTOR: 1.5,
2280
2682
  // Mobile typically 1.5x slower
2281
2683
  TABLET_PERFORMANCE_FACTOR: 1.2
2282
- }, sr = {
2684
+ }, dr = {
2283
2685
  MIN_TEXT_LENGTH_FOR_ANALYSIS: 10,
2284
2686
  MIN_CLICKS_FOR_HOT_ELEMENT: 10,
2285
2687
  // Popular element threshold
2286
2688
  MIN_SCROLL_COMPLETION_PERCENT: 80,
2287
2689
  // Page consumption threshold
2288
2690
  MIN_TIME_ON_PAGE_FOR_READ_MS: 15 * 1e3
2289
- }, nr = {
2691
+ }, hr = {
2290
2692
  SIGNIFICANT_CHANGE_PERCENT: 20,
2291
2693
  MAJOR_CHANGE_PERCENT: 50,
2292
2694
  MIN_EVENTS_FOR_INSIGHT: 100,
@@ -2296,19 +2698,19 @@ const vt = async (s) => {
2296
2698
  LOW_ERROR_RATE_PERCENT: 1,
2297
2699
  HIGH_ERROR_RATE_PERCENT: 5,
2298
2700
  CRITICAL_ERROR_RATE_PERCENT: 10
2299
- }, ir = {
2701
+ }, Er = {
2300
2702
  SHORT_TERM_TREND_HOURS: 24,
2301
2703
  MEDIUM_TERM_TREND_DAYS: 7,
2302
2704
  LONG_TERM_TREND_DAYS: 30,
2303
2705
  MIN_DATA_POINTS_FOR_TREND: 5,
2304
2706
  WEEKLY_PATTERN_MIN_WEEKS: 4,
2305
2707
  DAILY_PATTERN_MIN_DAYS: 14
2306
- }, ar = {
2708
+ }, fr = {
2307
2709
  MIN_SEGMENT_SIZE: 10,
2308
2710
  MIN_COHORT_SIZE: 5,
2309
2711
  COHORT_ANALYSIS_DAYS: [1, 3, 7, 14, 30],
2310
2712
  MIN_FUNNEL_EVENTS: 20
2311
- }, or = {
2713
+ }, gr = {
2312
2714
  DEFAULT_EVENTS_LIMIT: 5,
2313
2715
  DEFAULT_SESSIONS_LIMIT: 5,
2314
2716
  DEFAULT_PAGES_LIMIT: 5,
@@ -2316,260 +2718,260 @@ const vt = async (s) => {
2316
2718
  MAX_TIME_RANGE_DAYS: 365,
2317
2719
  ANALYTICS_BATCH_SIZE: 1e3
2318
2720
  // For historical analysis
2319
- }, lr = {
2721
+ }, mr = {
2320
2722
  ANOMALY_THRESHOLD_SIGMA: 2.5,
2321
2723
  STRONG_ANOMALY_THRESHOLD_SIGMA: 3,
2322
2724
  TRAFFIC_DROP_ALERT_PERCENT: -30,
2323
2725
  TRAFFIC_SPIKE_ALERT_PERCENT: 200,
2324
2726
  MIN_BASELINE_DAYS: 7,
2325
2727
  MIN_EVENTS_FOR_ANOMALY_DETECTION: 50
2326
- }, cr = {
2728
+ }, Sr = {
2327
2729
  PAGE_URL_EXCLUDED: "excluded",
2328
2730
  PAGE_URL_UNKNOWN: "unknown"
2329
- }, ur = {
2330
- init: vt,
2331
- event: yt,
2332
- on: At,
2333
- off: wt,
2334
- isInitialized: Mt,
2335
- destroy: Nt
2731
+ }, _r = {
2732
+ init: Ot,
2733
+ event: bt,
2734
+ on: Ct,
2735
+ off: Pt,
2736
+ isInitialized: Dt,
2737
+ destroy: Vt
2336
2738
  };
2337
- var ee, Me = -1, R = function(s) {
2739
+ var re, Ne = -1, C = function(n) {
2338
2740
  addEventListener("pageshow", (function(e) {
2339
- e.persisted && (Me = e.timeStamp, s(e));
2741
+ e.persisted && (Ne = e.timeStamp, n(e));
2340
2742
  }), !0);
2341
- }, oe = function() {
2342
- var s = self.performance && performance.getEntriesByType && performance.getEntriesByType("navigation")[0];
2343
- if (s && s.responseStart > 0 && s.responseStart < performance.now()) return s;
2344
- }, G = function() {
2345
- var s = oe();
2346
- return s && s.activationStart || 0;
2347
- }, m = function(s, e) {
2348
- var t = oe(), r = "navigate";
2349
- return Me >= 0 ? r = "back-forward-cache" : t && (document.prerendering || G() > 0 ? r = "prerender" : document.wasDiscarded ? r = "restore" : t.type && (r = t.type.replace(/_/g, "-"))), { name: s, value: e === void 0 ? -1 : e, rating: "good", delta: 0, entries: [], id: "v4-".concat(Date.now(), "-").concat(Math.floor(8999999999999 * Math.random()) + 1e12), navigationType: r };
2350
- }, P = function(s, e, t) {
2743
+ }, ce = function() {
2744
+ var n = self.performance && performance.getEntriesByType && performance.getEntriesByType("navigation")[0];
2745
+ if (n && n.responseStart > 0 && n.responseStart < performance.now()) return n;
2746
+ }, B = function() {
2747
+ var n = ce();
2748
+ return n && n.activationStart || 0;
2749
+ }, p = function(n, e) {
2750
+ var t = ce(), r = "navigate";
2751
+ return Ne >= 0 ? r = "back-forward-cache" : t && (document.prerendering || B() > 0 ? r = "prerender" : document.wasDiscarded ? r = "restore" : t.type && (r = t.type.replace(/_/g, "-"))), { name: n, value: e === void 0 ? -1 : e, rating: "good", delta: 0, entries: [], id: "v4-".concat(Date.now(), "-").concat(Math.floor(8999999999999 * Math.random()) + 1e12), navigationType: r };
2752
+ }, k = function(n, e, t) {
2351
2753
  try {
2352
- if (PerformanceObserver.supportedEntryTypes.includes(s)) {
2353
- var r = new PerformanceObserver((function(n) {
2754
+ if (PerformanceObserver.supportedEntryTypes.includes(n)) {
2755
+ var r = new PerformanceObserver((function(s) {
2354
2756
  Promise.resolve().then((function() {
2355
- e(n.getEntries());
2757
+ e(s.getEntries());
2356
2758
  }));
2357
2759
  }));
2358
- return r.observe(Object.assign({ type: s, buffered: !0 }, t || {})), r;
2760
+ return r.observe(Object.assign({ type: n, buffered: !0 }, t || {})), r;
2359
2761
  }
2360
2762
  } catch {
2361
2763
  }
2362
- }, p = function(s, e, t, r) {
2363
- var n, i;
2364
- return function(a) {
2365
- e.value >= 0 && (a || r) && ((i = e.value - (n || 0)) || n === void 0) && (n = e.value, e.delta = i, e.rating = (function(o, c) {
2366
- return o > c[1] ? "poor" : o > c[0] ? "needs-improvement" : "good";
2367
- })(e.value, t), s(e));
2764
+ }, I = function(n, e, t, r) {
2765
+ var s, i;
2766
+ return function(o) {
2767
+ e.value >= 0 && (o || r) && ((i = e.value - (s || 0)) || s === void 0) && (s = e.value, e.delta = i, e.rating = (function(l, c) {
2768
+ return l > c[1] ? "poor" : l > c[0] ? "needs-improvement" : "good";
2769
+ })(e.value, t), n(e));
2368
2770
  };
2369
- }, le = function(s) {
2771
+ }, ue = function(n) {
2370
2772
  requestAnimationFrame((function() {
2371
2773
  return requestAnimationFrame((function() {
2372
- return s();
2774
+ return n();
2373
2775
  }));
2374
2776
  }));
2375
- }, $ = function(s) {
2777
+ }, X = function(n) {
2376
2778
  document.addEventListener("visibilitychange", (function() {
2377
- document.visibilityState === "hidden" && s();
2779
+ document.visibilityState === "hidden" && n();
2378
2780
  }));
2379
- }, ce = function(s) {
2781
+ }, de = function(n) {
2380
2782
  var e = !1;
2381
2783
  return function() {
2382
- e || (s(), e = !0);
2784
+ e || (n(), e = !0);
2383
2785
  };
2384
- }, N = -1, Te = function() {
2786
+ }, O = -1, ve = function() {
2385
2787
  return document.visibilityState !== "hidden" || document.prerendering ? 1 / 0 : 0;
2386
- }, F = function(s) {
2387
- document.visibilityState === "hidden" && N > -1 && (N = s.type === "visibilitychange" ? s.timeStamp : 0, Lt());
2388
- }, Ie = function() {
2389
- addEventListener("visibilitychange", F, !0), addEventListener("prerenderingchange", F, !0);
2390
- }, Lt = function() {
2391
- removeEventListener("visibilitychange", F, !0), removeEventListener("prerenderingchange", F, !0);
2392
- }, Ne = function() {
2393
- return N < 0 && (N = Te(), Ie(), R((function() {
2788
+ }, W = function(n) {
2789
+ document.visibilityState === "hidden" && O > -1 && (O = n.type === "visibilitychange" ? n.timeStamp : 0, kt());
2790
+ }, Ae = function() {
2791
+ addEventListener("visibilitychange", W, !0), addEventListener("prerenderingchange", W, !0);
2792
+ }, kt = function() {
2793
+ removeEventListener("visibilitychange", W, !0), removeEventListener("prerenderingchange", W, !0);
2794
+ }, Re = function() {
2795
+ return O < 0 && (O = ve(), Ae(), C((function() {
2394
2796
  setTimeout((function() {
2395
- N = Te(), Ie();
2797
+ O = ve(), Ae();
2396
2798
  }), 0);
2397
2799
  }))), { get firstHiddenTime() {
2398
- return N;
2800
+ return O;
2399
2801
  } };
2400
- }, z = function(s) {
2802
+ }, $ = function(n) {
2401
2803
  document.prerendering ? addEventListener("prerenderingchange", (function() {
2402
- return s();
2403
- }), !0) : s();
2404
- }, te = [1800, 3e3], Le = function(s, e) {
2405
- e = e || {}, z((function() {
2406
- var t, r = Ne(), n = m("FCP"), i = P("paint", (function(a) {
2407
- a.forEach((function(o) {
2408
- o.name === "first-contentful-paint" && (i.disconnect(), o.startTime < r.firstHiddenTime && (n.value = Math.max(o.startTime - G(), 0), n.entries.push(o), t(!0)));
2804
+ return n();
2805
+ }), !0) : n();
2806
+ }, ne = [1800, 3e3], Oe = function(n, e) {
2807
+ e = e || {}, $((function() {
2808
+ var t, r = Re(), s = p("FCP"), i = k("paint", (function(o) {
2809
+ o.forEach((function(l) {
2810
+ l.name === "first-contentful-paint" && (i.disconnect(), l.startTime < r.firstHiddenTime && (s.value = Math.max(l.startTime - B(), 0), s.entries.push(l), t(!0)));
2409
2811
  }));
2410
2812
  }));
2411
- i && (t = p(s, n, te, e.reportAllChanges), R((function(a) {
2412
- n = m("FCP"), t = p(s, n, te, e.reportAllChanges), le((function() {
2413
- n.value = performance.now() - a.timeStamp, t(!0);
2813
+ i && (t = I(n, s, ne, e.reportAllChanges), C((function(o) {
2814
+ s = p("FCP"), t = I(n, s, ne, e.reportAllChanges), ue((function() {
2815
+ s.value = performance.now() - o.timeStamp, t(!0);
2414
2816
  }));
2415
2817
  })));
2416
2818
  }));
2417
- }, re = [0.1, 0.25], Rt = function(s, e) {
2418
- e = e || {}, Le(ce((function() {
2419
- var t, r = m("CLS", 0), n = 0, i = [], a = function(c) {
2420
- c.forEach((function(u) {
2421
- if (!u.hadRecentInput) {
2422
- var f = i[0], _ = i[i.length - 1];
2423
- n && u.startTime - _.startTime < 1e3 && u.startTime - f.startTime < 5e3 ? (n += u.value, i.push(u)) : (n = u.value, i = [u]);
2819
+ }, se = [0.1, 0.25], Ut = function(n, e) {
2820
+ e = e || {}, Oe(de((function() {
2821
+ var t, r = p("CLS", 0), s = 0, i = [], o = function(c) {
2822
+ c.forEach((function(d) {
2823
+ if (!d.hadRecentInput) {
2824
+ var _ = i[0], g = i[i.length - 1];
2825
+ s && d.startTime - g.startTime < 1e3 && d.startTime - _.startTime < 5e3 ? (s += d.value, i.push(d)) : (s = d.value, i = [d]);
2424
2826
  }
2425
- })), n > r.value && (r.value = n, r.entries = i, t());
2426
- }, o = P("layout-shift", a);
2427
- o && (t = p(s, r, re, e.reportAllChanges), $((function() {
2428
- a(o.takeRecords()), t(!0);
2429
- })), R((function() {
2430
- n = 0, r = m("CLS", 0), t = p(s, r, re, e.reportAllChanges), le((function() {
2827
+ })), s > r.value && (r.value = s, r.entries = i, t());
2828
+ }, l = k("layout-shift", o);
2829
+ l && (t = I(n, r, se, e.reportAllChanges), X((function() {
2830
+ o(l.takeRecords()), t(!0);
2831
+ })), C((function() {
2832
+ s = 0, r = p("CLS", 0), t = I(n, r, se, e.reportAllChanges), ue((function() {
2431
2833
  return t();
2432
2834
  }));
2433
2835
  })), setTimeout(t, 0));
2434
2836
  })));
2435
- }, Re = 0, X = 1 / 0, k = 0, bt = function(s) {
2436
- s.forEach((function(e) {
2437
- e.interactionId && (X = Math.min(X, e.interactionId), k = Math.max(k, e.interactionId), Re = k ? (k - X) / 7 + 1 : 0);
2837
+ }, be = 0, Y = 1 / 0, U = 0, Ht = function(n) {
2838
+ n.forEach((function(e) {
2839
+ e.interactionId && (Y = Math.min(Y, e.interactionId), U = Math.max(U, e.interactionId), be = U ? (U - Y) / 7 + 1 : 0);
2438
2840
  }));
2439
- }, be = function() {
2440
- return ee ? Re : performance.interactionCount || 0;
2441
- }, Ct = function() {
2442
- "interactionCount" in performance || ee || (ee = P("event", bt, { type: "event", buffered: !0, durationThreshold: 0 }));
2443
- }, E = [], V = /* @__PURE__ */ new Map(), Ce = 0, Ot = function() {
2444
- var s = Math.min(E.length - 1, Math.floor((be() - Ce) / 50));
2445
- return E[s];
2446
- }, Pt = [], Dt = function(s) {
2447
- if (Pt.forEach((function(n) {
2448
- return n(s);
2449
- })), s.interactionId || s.entryType === "first-input") {
2450
- var e = E[E.length - 1], t = V.get(s.interactionId);
2451
- if (t || E.length < 10 || s.duration > e.latency) {
2452
- if (t) s.duration > t.latency ? (t.entries = [s], t.latency = s.duration) : s.duration === t.latency && s.startTime === t.entries[0].startTime && t.entries.push(s);
2841
+ }, Ce = function() {
2842
+ return re ? be : performance.interactionCount || 0;
2843
+ }, xt = function() {
2844
+ "interactionCount" in performance || re || (re = k("event", Ht, { type: "event", buffered: !0, durationThreshold: 0 }));
2845
+ }, T = [], G = /* @__PURE__ */ new Map(), Pe = 0, Ft = function() {
2846
+ var n = Math.min(T.length - 1, Math.floor((Ce() - Pe) / 50));
2847
+ return T[n];
2848
+ }, Gt = [], Wt = function(n) {
2849
+ if (Gt.forEach((function(s) {
2850
+ return s(n);
2851
+ })), n.interactionId || n.entryType === "first-input") {
2852
+ var e = T[T.length - 1], t = G.get(n.interactionId);
2853
+ if (t || T.length < 10 || n.duration > e.latency) {
2854
+ if (t) n.duration > t.latency ? (t.entries = [n], t.latency = n.duration) : n.duration === t.latency && n.startTime === t.entries[0].startTime && t.entries.push(n);
2453
2855
  else {
2454
- var r = { id: s.interactionId, latency: s.duration, entries: [s] };
2455
- V.set(r.id, r), E.push(r);
2856
+ var r = { id: n.interactionId, latency: n.duration, entries: [n] };
2857
+ G.set(r.id, r), T.push(r);
2456
2858
  }
2457
- E.sort((function(n, i) {
2458
- return i.latency - n.latency;
2459
- })), E.length > 10 && E.splice(10).forEach((function(n) {
2460
- return V.delete(n.id);
2859
+ T.sort((function(s, i) {
2860
+ return i.latency - s.latency;
2861
+ })), T.length > 10 && T.splice(10).forEach((function(s) {
2862
+ return G.delete(s.id);
2461
2863
  }));
2462
2864
  }
2463
2865
  }
2464
- }, Oe = function(s) {
2866
+ }, De = function(n) {
2465
2867
  var e = self.requestIdleCallback || self.setTimeout, t = -1;
2466
- return s = ce(s), document.visibilityState === "hidden" ? s() : (t = e(s), $(s)), t;
2467
- }, se = [200, 500], kt = function(s, e) {
2468
- "PerformanceEventTiming" in self && "interactionId" in PerformanceEventTiming.prototype && (e = e || {}, z((function() {
2868
+ return n = de(n), document.visibilityState === "hidden" ? n() : (t = e(n), X(n)), t;
2869
+ }, ie = [200, 500], Bt = function(n, e) {
2870
+ "PerformanceEventTiming" in self && "interactionId" in PerformanceEventTiming.prototype && (e = e || {}, $((function() {
2469
2871
  var t;
2470
- Ct();
2471
- var r, n = m("INP"), i = function(o) {
2472
- Oe((function() {
2473
- o.forEach(Dt);
2474
- var c = Ot();
2475
- c && c.latency !== n.value && (n.value = c.latency, n.entries = c.entries, r());
2872
+ xt();
2873
+ var r, s = p("INP"), i = function(l) {
2874
+ De((function() {
2875
+ l.forEach(Wt);
2876
+ var c = Ft();
2877
+ c && c.latency !== s.value && (s.value = c.latency, s.entries = c.entries, r());
2476
2878
  }));
2477
- }, a = P("event", i, { durationThreshold: (t = e.durationThreshold) !== null && t !== void 0 ? t : 40 });
2478
- r = p(s, n, se, e.reportAllChanges), a && (a.observe({ type: "first-input", buffered: !0 }), $((function() {
2479
- i(a.takeRecords()), r(!0);
2480
- })), R((function() {
2481
- Ce = be(), E.length = 0, V.clear(), n = m("INP"), r = p(s, n, se, e.reportAllChanges);
2879
+ }, o = k("event", i, { durationThreshold: (t = e.durationThreshold) !== null && t !== void 0 ? t : 40 });
2880
+ r = I(n, s, ie, e.reportAllChanges), o && (o.observe({ type: "first-input", buffered: !0 }), X((function() {
2881
+ i(o.takeRecords()), r(!0);
2882
+ })), C((function() {
2883
+ Pe = Ce(), T.length = 0, G.clear(), s = p("INP"), r = I(n, s, ie, e.reportAllChanges);
2482
2884
  })));
2483
2885
  })));
2484
- }, ne = [2500, 4e3], W = {}, Ut = function(s, e) {
2485
- e = e || {}, z((function() {
2486
- var t, r = Ne(), n = m("LCP"), i = function(c) {
2487
- e.reportAllChanges || (c = c.slice(-1)), c.forEach((function(u) {
2488
- u.startTime < r.firstHiddenTime && (n.value = Math.max(u.startTime - G(), 0), n.entries = [u], t());
2886
+ }, oe = [2500, 4e3], K = {}, Xt = function(n, e) {
2887
+ e = e || {}, $((function() {
2888
+ var t, r = Re(), s = p("LCP"), i = function(c) {
2889
+ e.reportAllChanges || (c = c.slice(-1)), c.forEach((function(d) {
2890
+ d.startTime < r.firstHiddenTime && (s.value = Math.max(d.startTime - B(), 0), s.entries = [d], t());
2489
2891
  }));
2490
- }, a = P("largest-contentful-paint", i);
2491
- if (a) {
2492
- t = p(s, n, ne, e.reportAllChanges);
2493
- var o = ce((function() {
2494
- W[n.id] || (i(a.takeRecords()), a.disconnect(), W[n.id] = !0, t(!0));
2892
+ }, o = k("largest-contentful-paint", i);
2893
+ if (o) {
2894
+ t = I(n, s, oe, e.reportAllChanges);
2895
+ var l = de((function() {
2896
+ K[s.id] || (i(o.takeRecords()), o.disconnect(), K[s.id] = !0, t(!0));
2495
2897
  }));
2496
2898
  ["keydown", "click"].forEach((function(c) {
2497
2899
  addEventListener(c, (function() {
2498
- return Oe(o);
2900
+ return De(l);
2499
2901
  }), { once: !0, capture: !0 });
2500
- })), $(o), R((function(c) {
2501
- n = m("LCP"), t = p(s, n, ne, e.reportAllChanges), le((function() {
2502
- n.value = performance.now() - c.timeStamp, W[n.id] = !0, t(!0);
2902
+ })), X(l), C((function(c) {
2903
+ s = p("LCP"), t = I(n, s, oe, e.reportAllChanges), ue((function() {
2904
+ s.value = performance.now() - c.timeStamp, K[s.id] = !0, t(!0);
2503
2905
  }));
2504
2906
  }));
2505
2907
  }
2506
2908
  }));
2507
- }, ie = [800, 1800], Ht = function s(e) {
2508
- document.prerendering ? z((function() {
2509
- return s(e);
2909
+ }, ae = [800, 1800], $t = function n(e) {
2910
+ document.prerendering ? $((function() {
2911
+ return n(e);
2510
2912
  })) : document.readyState !== "complete" ? addEventListener("load", (function() {
2511
- return s(e);
2913
+ return n(e);
2512
2914
  }), !0) : setTimeout(e, 0);
2513
- }, xt = function(s, e) {
2915
+ }, zt = function(n, e) {
2514
2916
  e = e || {};
2515
- var t = m("TTFB"), r = p(s, t, ie, e.reportAllChanges);
2516
- Ht((function() {
2517
- var n = oe();
2518
- n && (t.value = Math.max(n.responseStart - G(), 0), t.entries = [n], r(!0), R((function() {
2519
- t = m("TTFB", 0), (r = p(s, t, ie, e.reportAllChanges))(!0);
2917
+ var t = p("TTFB"), r = I(n, t, ae, e.reportAllChanges);
2918
+ $t((function() {
2919
+ var s = ce();
2920
+ s && (t.value = Math.max(s.responseStart - B(), 0), t.entries = [s], r(!0), C((function() {
2921
+ t = p("TTFB", 0), (r = I(n, t, ae, e.reportAllChanges))(!0);
2520
2922
  })));
2521
2923
  }));
2522
2924
  };
2523
- const Vt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2925
+ const Qt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2524
2926
  __proto__: null,
2525
- CLSThresholds: re,
2526
- FCPThresholds: te,
2527
- INPThresholds: se,
2528
- LCPThresholds: ne,
2529
- TTFBThresholds: ie,
2530
- onCLS: Rt,
2531
- onFCP: Le,
2532
- onINP: kt,
2533
- onLCP: Ut,
2534
- onTTFB: xt
2927
+ CLSThresholds: se,
2928
+ FCPThresholds: ne,
2929
+ INPThresholds: ie,
2930
+ LCPThresholds: oe,
2931
+ TTFBThresholds: ae,
2932
+ onCLS: Ut,
2933
+ onFCP: Oe,
2934
+ onINP: Bt,
2935
+ onLCP: Xt,
2936
+ onTTFB: zt
2535
2937
  }, Symbol.toStringTag, { value: "Module" }));
2536
2938
  export {
2537
- or as ANALYTICS_QUERY_LIMITS,
2538
- lr as ANOMALY_DETECTION,
2539
- w as AppConfigValidationError,
2540
- sr as CONTENT_ANALYTICS,
2541
- Zt as DATA_PROTECTION,
2542
- rr as DEVICE_ANALYTICS,
2543
- T as DeviceType,
2544
- er as ENGAGEMENT_THRESHOLDS,
2545
- K as EmitterEvent,
2546
- b as ErrorType,
2547
- d as EventType,
2548
- nr as INSIGHT_THRESHOLDS,
2549
- qt as InitializationTimeoutError,
2550
- v as IntegrationValidationError,
2551
- Wt as MAX_ARRAY_LENGTH,
2552
- zt as MAX_CUSTOM_EVENT_ARRAY_SIZE,
2553
- $t as MAX_CUSTOM_EVENT_KEYS,
2554
- Ft as MAX_CUSTOM_EVENT_NAME_LENGTH,
2555
- Gt as MAX_CUSTOM_EVENT_STRING_SIZE,
2556
- Bt as MAX_METADATA_NESTING_DEPTH,
2557
- Qt as MAX_NESTED_OBJECT_KEYS,
2558
- jt as MAX_STRING_LENGTH,
2559
- Xt as MAX_STRING_LENGTH_IN_ARRAY,
2560
- C as Mode,
2561
- Jt as PERFORMANCE_CONFIG,
2562
- M as PermanentError,
2563
- ar as SEGMENTATION_ANALYTICS,
2564
- tr as SESSION_ANALYTICS,
2565
- cr as SPECIAL_PAGE_URLS,
2566
- de as SamplingRateValidationError,
2567
- U as ScrollDirection,
2568
- He as SessionTimeoutValidationError,
2569
- Y as SpecialApiUrl,
2570
- ir as TEMPORAL_ANALYSIS,
2571
- O as TraceLogValidationError,
2572
- Yt as isPrimaryScrollEvent,
2573
- Kt as isSecondaryScrollEvent,
2574
- ur as tracelog
2939
+ gr as ANALYTICS_QUERY_LIMITS,
2940
+ mr as ANOMALY_DETECTION,
2941
+ E as AppConfigValidationError,
2942
+ dr as CONTENT_ANALYTICS,
2943
+ ar as DATA_PROTECTION,
2944
+ ur as DEVICE_ANALYTICS,
2945
+ w as DeviceType,
2946
+ lr as ENGAGEMENT_THRESHOLDS,
2947
+ Z as EmitterEvent,
2948
+ P as ErrorType,
2949
+ u as EventType,
2950
+ hr as INSIGHT_THRESHOLDS,
2951
+ ir as InitializationTimeoutError,
2952
+ M as IntegrationValidationError,
2953
+ rr as MAX_ARRAY_LENGTH,
2954
+ qt as MAX_CUSTOM_EVENT_ARRAY_SIZE,
2955
+ Kt as MAX_CUSTOM_EVENT_KEYS,
2956
+ jt as MAX_CUSTOM_EVENT_NAME_LENGTH,
2957
+ Yt as MAX_CUSTOM_EVENT_STRING_SIZE,
2958
+ Jt as MAX_METADATA_NESTING_DEPTH,
2959
+ Zt as MAX_NESTED_OBJECT_KEYS,
2960
+ er as MAX_STRING_LENGTH,
2961
+ tr as MAX_STRING_LENGTH_IN_ARRAY,
2962
+ D as Mode,
2963
+ or as PERFORMANCE_CONFIG,
2964
+ R as PermanentError,
2965
+ fr as SEGMENTATION_ANALYTICS,
2966
+ cr as SESSION_ANALYTICS,
2967
+ Sr as SPECIAL_PAGE_URLS,
2968
+ he as SamplingRateValidationError,
2969
+ H as ScrollDirection,
2970
+ Ge as SessionTimeoutValidationError,
2971
+ q as SpecialApiUrl,
2972
+ Er as TEMPORAL_ANALYSIS,
2973
+ V as TraceLogValidationError,
2974
+ nr as isPrimaryScrollEvent,
2975
+ sr as isSecondaryScrollEvent,
2976
+ _r as tracelog
2575
2977
  };