@tracelog/lib 0.4.1 → 0.5.0

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 (98) hide show
  1. package/dist/browser/tracelog.js +576 -610
  2. package/dist/cjs/api.d.ts +1 -53
  3. package/dist/cjs/api.js +0 -59
  4. package/dist/cjs/app.constants.d.ts +1 -1
  5. package/dist/cjs/app.d.ts +1 -5
  6. package/dist/cjs/app.js +4 -12
  7. package/dist/cjs/constants/api.constants.d.ts +5 -2
  8. package/dist/cjs/constants/api.constants.js +5 -14
  9. package/dist/cjs/constants/config.constants.d.ts +3 -3
  10. package/dist/cjs/constants/config.constants.js +3 -3
  11. package/dist/cjs/constants/error.constants.d.ts +7 -2
  12. package/dist/cjs/constants/error.constants.js +13 -2
  13. package/dist/cjs/handlers/click.handler.js +0 -6
  14. package/dist/cjs/handlers/error.handler.js +9 -0
  15. package/dist/cjs/handlers/scroll.handler.js +0 -5
  16. package/dist/cjs/handlers/session.handler.js +5 -2
  17. package/dist/cjs/integrations/google-analytics.integration.d.ts +1 -1
  18. package/dist/cjs/integrations/google-analytics.integration.js +2 -1
  19. package/dist/cjs/managers/api.manager.d.ts +1 -1
  20. package/dist/cjs/managers/api.manager.js +3 -3
  21. package/dist/cjs/managers/config.builder.d.ts +33 -0
  22. package/dist/cjs/managers/config.builder.js +116 -0
  23. package/dist/cjs/managers/config.manager.d.ts +13 -14
  24. package/dist/cjs/managers/config.manager.js +52 -58
  25. package/dist/cjs/managers/event.manager.d.ts +0 -45
  26. package/dist/cjs/managers/event.manager.js +14 -67
  27. package/dist/cjs/managers/sender.manager.d.ts +1 -28
  28. package/dist/cjs/managers/sender.manager.js +43 -73
  29. package/dist/cjs/managers/session.manager.d.ts +2 -49
  30. package/dist/cjs/managers/session.manager.js +37 -79
  31. package/dist/cjs/managers/state.manager.d.ts +1 -28
  32. package/dist/cjs/managers/state.manager.js +5 -33
  33. package/dist/cjs/managers/storage.manager.d.ts +6 -0
  34. package/dist/cjs/managers/storage.manager.js +18 -1
  35. package/dist/cjs/public-api.d.ts +1 -1
  36. package/dist/cjs/test-bridge.d.ts +3 -2
  37. package/dist/cjs/test-bridge.js +34 -7
  38. package/dist/cjs/types/api.types.d.ts +24 -8
  39. package/dist/cjs/types/api.types.js +24 -8
  40. package/dist/cjs/types/event.types.d.ts +2 -3
  41. package/dist/cjs/types/event.types.js +0 -1
  42. package/dist/cjs/types/test-bridge.types.d.ts +2 -1
  43. package/dist/cjs/utils/logging/debug-logger.utils.d.ts +1 -2
  44. package/dist/cjs/utils/logging/debug-logger.utils.js +2 -3
  45. package/dist/cjs/utils/validations/config-validations.utils.d.ts +1 -26
  46. package/dist/cjs/utils/validations/config-validations.utils.js +5 -117
  47. package/dist/cjs/utils/validations/event-validations.utils.d.ts +2 -2
  48. package/dist/cjs/utils/validations/metadata-validations.utils.d.ts +3 -3
  49. package/dist/cjs/utils/validations/metadata-validations.utils.js +41 -3
  50. package/dist/esm/api.d.ts +1 -53
  51. package/dist/esm/api.js +0 -59
  52. package/dist/esm/app.constants.d.ts +1 -1
  53. package/dist/esm/app.d.ts +1 -5
  54. package/dist/esm/app.js +5 -13
  55. package/dist/esm/constants/api.constants.d.ts +5 -2
  56. package/dist/esm/constants/api.constants.js +5 -13
  57. package/dist/esm/constants/config.constants.d.ts +3 -3
  58. package/dist/esm/constants/config.constants.js +3 -3
  59. package/dist/esm/constants/error.constants.d.ts +7 -2
  60. package/dist/esm/constants/error.constants.js +12 -1
  61. package/dist/esm/handlers/click.handler.js +0 -6
  62. package/dist/esm/handlers/error.handler.js +10 -1
  63. package/dist/esm/handlers/scroll.handler.js +0 -5
  64. package/dist/esm/handlers/session.handler.js +5 -2
  65. package/dist/esm/integrations/google-analytics.integration.d.ts +1 -1
  66. package/dist/esm/integrations/google-analytics.integration.js +2 -1
  67. package/dist/esm/managers/api.manager.d.ts +1 -1
  68. package/dist/esm/managers/api.manager.js +3 -3
  69. package/dist/esm/managers/config.builder.d.ts +33 -0
  70. package/dist/esm/managers/config.builder.js +112 -0
  71. package/dist/esm/managers/config.manager.d.ts +13 -14
  72. package/dist/esm/managers/config.manager.js +54 -60
  73. package/dist/esm/managers/event.manager.d.ts +0 -45
  74. package/dist/esm/managers/event.manager.js +14 -67
  75. package/dist/esm/managers/sender.manager.d.ts +1 -28
  76. package/dist/esm/managers/sender.manager.js +44 -74
  77. package/dist/esm/managers/session.manager.d.ts +2 -49
  78. package/dist/esm/managers/session.manager.js +37 -79
  79. package/dist/esm/managers/state.manager.d.ts +1 -28
  80. package/dist/esm/managers/state.manager.js +4 -33
  81. package/dist/esm/managers/storage.manager.d.ts +6 -0
  82. package/dist/esm/managers/storage.manager.js +18 -1
  83. package/dist/esm/public-api.d.ts +1 -1
  84. package/dist/esm/test-bridge.d.ts +3 -2
  85. package/dist/esm/test-bridge.js +34 -7
  86. package/dist/esm/types/api.types.d.ts +24 -8
  87. package/dist/esm/types/api.types.js +24 -8
  88. package/dist/esm/types/event.types.d.ts +2 -3
  89. package/dist/esm/types/event.types.js +0 -1
  90. package/dist/esm/types/test-bridge.types.d.ts +2 -1
  91. package/dist/esm/utils/logging/debug-logger.utils.d.ts +1 -2
  92. package/dist/esm/utils/logging/debug-logger.utils.js +3 -4
  93. package/dist/esm/utils/validations/config-validations.utils.d.ts +1 -26
  94. package/dist/esm/utils/validations/config-validations.utils.js +5 -114
  95. package/dist/esm/utils/validations/event-validations.utils.d.ts +2 -2
  96. package/dist/esm/utils/validations/metadata-validations.utils.d.ts +3 -3
  97. package/dist/esm/utils/validations/metadata-validations.utils.js +41 -3
  98. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
- var y = /* @__PURE__ */ ((r) => (r.Mobile = "mobile", r.Tablet = "tablet", r.Desktop = "desktop", r.Unknown = "unknown", r))(y || {});
2
- const ee = 15 * 60 * 1e3, Je = 1e3, Ze = 1e4, ke = 250, et = 24, Se = 500, Ee = 3, tt = 5e3, Ue = 1e4, rt = 10, ve = 5, ye = 500, Te = 120, A = 1, nt = 0, st = 1, z = 3e4, G = 864e5, Ie = 120, _e = 8 * 1024, we = 10, Ae = 10, Y = 255, T = 1e3, K = 100, be = 3, _ = 2, it = 2e3, k = "data-tl", at = [
1
+ var I = /* @__PURE__ */ ((r) => (r.Mobile = "mobile", r.Tablet = "tablet", r.Desktop = "desktop", r.Unknown = "unknown", r))(I || {});
2
+ const P = 15 * 60 * 1e3, Je = 500, Ze = 1e4, xe = 250, et = 24, pe = 100, Se = 3, tt = 5e3, Ue = 1e4, rt = 10, Ee = 5, ve = 500, ye = 120, M = 1, nt = 0, st = 1, k = 3e4, x = 864e5, Ie = 120, Te = 8 * 1024, _e = 10, we = 10, X = 255, T = 1e3, q = 100, Ae = 3, w = 2, F = "data-tl", it = [
3
3
  "button",
4
4
  "a",
5
5
  'input[type="button"]',
@@ -31,20 +31,18 @@ const ee = 15 * 60 * 1e3, Je = 1e3, Ze = 1e4, ke = 250, et = 24, Se = 500, Ee =
31
31
  ".menu-item",
32
32
  "[data-testid]",
33
33
  '[tabindex="0"]'
34
- ], ot = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"], lt = 2, ct = /* @__PURE__ */ new Set([
34
+ ], at = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"], ot = 2, lt = /* @__PURE__ */ new Set([
35
35
  "mode",
36
36
  "tags",
37
37
  "samplingRate",
38
38
  "excludedUrlPaths",
39
39
  "ipExcluded"
40
- ]), p = {
40
+ ]), y = {
41
41
  // Project ID validation - consistent message across all layers
42
42
  MISSING_PROJECT_ID: "Project ID is required",
43
43
  PROJECT_ID_EMPTY_AFTER_TRIM: "Project ID is required",
44
44
  // Session timeout validation
45
- INVALID_SESSION_TIMEOUT: `Session timeout must be between ${z}ms (30 seconds) and ${G}ms (24 hours)`,
46
- // Sampling rate validation
47
- INVALID_SAMPLING_RATE: "Sampling rate must be greater than 0 and less than or equal to 1",
45
+ INVALID_SESSION_TIMEOUT: `Session timeout must be between ${k}ms (30 seconds) and ${x}ms (24 hours)`,
48
46
  INVALID_ERROR_SAMPLING_RATE: "Error sampling must be between 0 and 1",
49
47
  // Integration validation
50
48
  INVALID_GOOGLE_ANALYTICS_ID: "Google Analytics measurement ID is required when integration is enabled",
@@ -54,35 +52,26 @@ const ee = 15 * 60 * 1e3, Je = 1e3, Ze = 1e4, ke = 250, et = 24, Se = 500, Ee =
54
52
  INVALID_GLOBAL_METADATA: "Global metadata must be an object",
55
53
  // Array validation
56
54
  INVALID_SENSITIVE_QUERY_PARAMS: "Sensitive query params must be an array of strings"
57
- }, xe = [
55
+ }, He = [
58
56
  /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
59
57
  /javascript:/gi,
60
58
  /on\w+\s*=/gi,
61
59
  /<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,
62
60
  /<embed\b[^>]*>/gi,
63
61
  /<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi
64
- ], He = {
65
- samplingRate: A,
62
+ ], N = {
63
+ samplingRate: M,
66
64
  excludedUrlPaths: [],
67
65
  tags: [],
68
66
  ipExcluded: !1
69
- }, Me = (r) => ({
70
- ...He,
71
- ...r,
72
- allowHttp: !1,
73
- sessionTimeout: ee,
74
- samplingRate: r.samplingRate && r.samplingRate > nt && r.samplingRate <= st ? r.samplingRate : A,
75
- excludedUrlPaths: r.excludedUrlPaths ?? [],
76
- tags: r.tags ?? [],
77
- ipExcluded: r.ipExcluded ?? !1
78
- }), I = "tl", ut = (r) => r ? `${I}:${r}:uid` : `${I}:uid`, dt = (r) => r ? `${I}:${r}:queue` : `${I}:queue`, ht = (r) => r ? `${I}:${r}:session` : `${I}:session`, gt = (r) => r ? `${I}:${r}:broadcast` : `${I}:broadcast`, Ve = {
67
+ }, _ = "tl", ct = (r) => r ? `${_}:${r}:uid` : `${_}:uid`, ut = (r) => r ? `${_}:${r}:queue` : `${_}:queue`, dt = (r) => r ? `${_}:${r}:session` : `${_}:session`, ht = (r) => r ? `${_}:${r}:broadcast` : `${_}:broadcast`, Ve = {
79
68
  LCP: 4e3,
80
69
  FCP: 1800,
81
70
  CLS: 0.25,
82
71
  INP: 200,
83
72
  TTFB: 600,
84
73
  LONG_TASK: 50
85
- }, ft = 1e3, Fe = [
74
+ }, gt = 1e3, Fe = [
86
75
  // Email addresses
87
76
  /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/gi,
88
77
  // US Phone numbers (various formats)
@@ -90,65 +79,56 @@ const ee = 15 * 60 * 1e3, Je = 1e3, Ze = 1e4, ke = 250, et = 24, Se = 500, Ee =
90
79
  // Credit card numbers (16 digits with optional separators)
91
80
  /\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g,
92
81
  // IBAN (International Bank Account Number)
93
- /\b[A-Z]{2}\d{2}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/gi
94
- ], Re = 500, Le = 6e4, X = 50, v = {};
95
- class f {
96
- /**
97
- * Gets a value from the global state
98
- */
82
+ /\b[A-Z]{2}\d{2}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/gi,
83
+ // API keys/tokens (sk_test_, sk_live_, pk_test_, pk_live_, etc.)
84
+ /\b[sp]k_(test|live)_[a-zA-Z0-9]{10,}\b/gi,
85
+ // Bearer tokens (JWT-like patterns - matches complete and partial tokens)
86
+ /Bearer\s+[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)?(?:\.[A-Za-z0-9_-]+)?/gi,
87
+ // Passwords in connection strings (protocol://user:password@host)
88
+ /:\/\/[^:/]+:([^@]+)@/gi
89
+ ], be = 500, Me = 5e3, G = 50, Re = G * 2, p = {};
90
+ function ft() {
91
+ return p;
92
+ }
93
+ class m {
99
94
  get(e) {
100
- return v[e];
95
+ return p[e];
101
96
  }
102
- /**
103
- * Sets a value in the global state
104
- */
105
97
  set(e, t) {
106
- const n = v[e];
98
+ const n = p[e];
107
99
  if (e === "config" && t) {
108
100
  const s = t;
109
101
  if (s) {
110
- const i = s.samplingRate ?? A, o = i > 0 ? i : A;
102
+ const i = s.samplingRate ?? M, o = i < 0 || i > 1 ? M : i;
111
103
  if (o !== i) {
112
104
  const l = { ...s, samplingRate: o };
113
- v[e] = l;
105
+ p[e] = l;
114
106
  } else
115
- v[e] = s;
107
+ p[e] = s;
116
108
  } else
117
- v[e] = t;
109
+ p[e] = t;
118
110
  } else
119
- v[e] = t;
120
- this.isCriticalStateKey(e) && this.shouldLog(n, v[e]) && a.debug("StateManager", "State updated", {
111
+ p[e] = t;
112
+ this.isCriticalStateKey(e) && this.shouldLog(n, p[e]) && a.debug("StateManager", "State updated", {
121
113
  key: e,
122
114
  oldValue: this.formatLogValue(e, n),
123
- newValue: this.formatLogValue(e, v[e])
115
+ newValue: this.formatLogValue(e, p[e])
124
116
  });
125
117
  }
126
- /**
127
- * Gets the entire state object (for debugging purposes)
128
- */
129
118
  getState() {
130
- return { ...v };
119
+ return { ...p };
131
120
  }
132
- /**
133
- * Checks if a state key is considered critical for logging
134
- */
135
121
  isCriticalStateKey(e) {
136
122
  return e === "sessionId" || e === "config" || e === "hasStartSession";
137
123
  }
138
- /**
139
- * Determines if a state change should be logged
140
- */
141
124
  shouldLog(e, t) {
142
125
  return e !== t;
143
126
  }
144
- /**
145
- * Formats values for logging (avoiding large object dumps)
146
- */
147
127
  formatLogValue(e, t) {
148
128
  return e === "config" ? t ? "(configured)" : "(not configured)" : t;
149
129
  }
150
130
  }
151
- class mt extends f {
131
+ class mt {
152
132
  clientError = (e, t, n) => this.log("CLIENT_ERROR", e, t, n);
153
133
  clientWarn = (e, t, n) => this.log("CLIENT_WARN", e, t, n);
154
134
  info = (e, t, n) => this.log("INFO", e, t, n);
@@ -157,7 +137,7 @@ class mt extends f {
157
137
  debug = (e, t, n) => this.log("DEBUG", e, t, n);
158
138
  verbose = (e, t, n) => this.log("VERBOSE", e, t, n);
159
139
  log(e, t, n, s) {
160
- const i = this.get("config")?.mode;
140
+ const i = ft()?.config?.mode;
161
141
  if (!this.shouldShow(e, i)) return;
162
142
  const o = `[TraceLog:${t}] ${n}`, c = this.getMethod(e);
163
143
  s !== void 0 ? console[c](o, s) : console[c](o);
@@ -182,8 +162,8 @@ const pt = () => {
182
162
  mobile: r.userAgentData.mobile,
183
163
  platform: r.userAgentData.platform
184
164
  }), r.userAgentData.platform && /ipad|tablet/i.test(r.userAgentData.platform))
185
- return a.debug("DeviceDetector", "Device detected as tablet via platform hint"), y.Tablet;
186
- const u = r.userAgentData.mobile ? y.Mobile : y.Desktop;
165
+ return a.debug("DeviceDetector", "Device detected as tablet via platform hint"), I.Tablet;
166
+ const u = r.userAgentData.mobile ? I.Mobile : I.Desktop;
187
167
  return a.debug("DeviceDetector", "Device detected via User-Agent hints", { result: u }), u;
188
168
  }
189
169
  a.debug("DeviceDetector", "Using fallback detection methods"), pt();
@@ -196,19 +176,19 @@ const pt = () => {
196
176
  isTabletUA: c,
197
177
  maxTouchPoints: navigator.maxTouchPoints
198
178
  };
199
- return e <= 767 || o && s ? (a.debug("DeviceDetector", "Device detected as mobile", l), y.Mobile) : e >= 768 && e <= 1024 || c || t && n && s ? (a.debug("DeviceDetector", "Device detected as tablet", l), y.Tablet) : (a.debug("DeviceDetector", "Device detected as desktop", l), y.Desktop);
179
+ return e <= 767 || o && s ? (a.debug("DeviceDetector", "Device detected as mobile", l), I.Mobile) : e >= 768 && e <= 1024 || c || t && n && s ? (a.debug("DeviceDetector", "Device detected as tablet", l), I.Tablet) : (a.debug("DeviceDetector", "Device detected as desktop", l), I.Desktop);
200
180
  } catch (r) {
201
181
  return a.warn("DeviceDetector", "Device detection failed, defaulting to desktop", {
202
182
  error: r instanceof Error ? r.message : r
203
- }), y.Desktop;
183
+ }), I.Desktop;
204
184
  }
205
- }, Ne = () => {
185
+ }, Le = () => {
206
186
  a.debug("UTMParams", "Extracting UTM parameters from URL", {
207
187
  url: window.location.href,
208
188
  search: window.location.search
209
189
  });
210
190
  const r = new URLSearchParams(window.location.search), e = {};
211
- ot.forEach((n) => {
191
+ at.forEach((n) => {
212
192
  const s = r.get(n);
213
193
  if (s) {
214
194
  const i = n.split("utm_")[1];
@@ -224,76 +204,76 @@ const pt = () => {
224
204
  const e = Math.random() * 16 | 0;
225
205
  return (r === "x" ? e : e & 3 | 8).toString(16);
226
206
  });
227
- var w = /* @__PURE__ */ ((r) => (r.Skip = "skip", r.Localhost = "localhost:", r))(w || {}), re = /* @__PURE__ */ ((r) => (r.EVENT = "event", r.QUEUE = "queue", r))(re || {}), d = /* @__PURE__ */ ((r) => (r.PAGE_VIEW = "page_view", r.CLICK = "click", r.SCROLL = "scroll", r.SESSION_START = "session_start", r.SESSION_END = "session_end", r.CUSTOM = "custom", r.WEB_VITALS = "web_vitals", r.ERROR = "error", r))(d || {}), x = /* @__PURE__ */ ((r) => (r.UP = "up", r.DOWN = "down", r))(x || {}), N = /* @__PURE__ */ ((r) => (r.JS_ERROR = "js_error", r.PROMISE_REJECTION = "promise_rejection", r.NETWORK_ERROR = "network_error", r))(N || {}), H = /* @__PURE__ */ ((r) => (r.QA = "qa", r.DEBUG = "debug", r))(H || {}), vt = /* @__PURE__ */ ((r) => (r.AND = "AND", r.OR = "OR", r))(vt || {}), yt = /* @__PURE__ */ ((r) => (r.URL_MATCHES = "url_matches", r.ELEMENT_MATCHES = "element_matches", r.DEVICE_TYPE = "device_type", r.ELEMENT_TEXT = "element_text", r.ELEMENT_ATTRIBUTE = "element_attribute", r.UTM_SOURCE = "utm_source", r.UTM_MEDIUM = "utm_medium", r.UTM_CAMPAIGN = "utm_campaign", r))(yt || {}), Tt = /* @__PURE__ */ ((r) => (r.EQUALS = "equals", r.CONTAINS = "contains", r.STARTS_WITH = "starts_with", r.ENDS_WITH = "ends_with", r.REGEX = "regex", r.GREATER_THAN = "greater_than", r.LESS_THAN = "less_than", r.EXISTS = "exists", r.NOT_EXISTS = "not_exists", r))(Tt || {});
228
- class O extends Error {
207
+ var f = /* @__PURE__ */ ((r) => (r.Skip = "skip", r.Localhost = "localhost:8080", r.Fail = "localhost:9999", r))(f || {}), re = /* @__PURE__ */ ((r) => (r.EVENT = "event", r.QUEUE = "queue", r))(re || {}), d = /* @__PURE__ */ ((r) => (r.PAGE_VIEW = "page_view", r.CLICK = "click", r.SCROLL = "scroll", r.SESSION_START = "session_start", r.SESSION_END = "session_end", r.CUSTOM = "custom", r.WEB_VITALS = "web_vitals", r.ERROR = "error", r))(d || {}), j = /* @__PURE__ */ ((r) => (r.UP = "up", r.DOWN = "down", r))(j || {}), C = /* @__PURE__ */ ((r) => (r.JS_ERROR = "js_error", r.PROMISE_REJECTION = "promise_rejection", r))(C || {}), O = /* @__PURE__ */ ((r) => (r.QA = "qa", r.DEBUG = "debug", r))(O || {}), vt = /* @__PURE__ */ ((r) => (r.AND = "AND", r.OR = "OR", r))(vt || {}), yt = /* @__PURE__ */ ((r) => (r.URL_MATCHES = "url_matches", r.ELEMENT_MATCHES = "element_matches", r.DEVICE_TYPE = "device_type", r.ELEMENT_TEXT = "element_text", r.ELEMENT_ATTRIBUTE = "element_attribute", r.UTM_SOURCE = "utm_source", r.UTM_MEDIUM = "utm_medium", r.UTM_CAMPAIGN = "utm_campaign", r))(yt || {}), It = /* @__PURE__ */ ((r) => (r.EQUALS = "equals", r.CONTAINS = "contains", r.STARTS_WITH = "starts_with", r.ENDS_WITH = "ends_with", r.REGEX = "regex", r.GREATER_THAN = "greater_than", r.LESS_THAN = "less_than", r.EXISTS = "exists", r.NOT_EXISTS = "not_exists", r))(It || {});
208
+ class H extends Error {
229
209
  constructor(e, t, n) {
230
210
  super(e), this.errorCode = t, this.layer = n, this.name = this.constructor.name, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
231
211
  }
232
212
  }
233
- class ne extends O {
213
+ class ne extends H {
234
214
  constructor(e = "Project ID is required", t = "config") {
235
215
  super(e, "PROJECT_ID_INVALID", t);
236
216
  }
237
217
  }
238
- class b extends O {
218
+ class A extends H {
239
219
  constructor(e, t = "config") {
240
220
  super(e, "APP_CONFIG_INVALID", t);
241
221
  }
242
222
  }
243
- class It extends O {
223
+ class Tt extends H {
244
224
  constructor(e, t = "config") {
245
225
  super(e, "SESSION_TIMEOUT_INVALID", t);
246
226
  }
247
227
  }
248
- class _t extends O {
228
+ class _t extends H {
249
229
  constructor(e, t = "config") {
250
230
  super(e, "SAMPLING_RATE_INVALID", t);
251
231
  }
252
232
  }
253
- class Ce extends O {
233
+ class Ne extends H {
254
234
  constructor(e, t = "config") {
255
235
  super(e, "INTEGRATION_INVALID", t);
256
236
  }
257
237
  }
258
238
  const wt = (r) => {
259
239
  if (!r || typeof r != "object")
260
- throw a.clientError("ConfigValidation", "Configuration must be an object", { config: r }), new b("Configuration must be an object", "config");
240
+ throw a.clientError("ConfigValidation", "Configuration must be an object", { config: r }), new A("Configuration must be an object", "config");
261
241
  if (!("id" in r))
262
- throw a.clientError("ConfigValidation", "Project ID is missing from configuration"), new ne(p.MISSING_PROJECT_ID, "config");
242
+ throw a.clientError("ConfigValidation", "Project ID is missing from configuration"), new ne(y.MISSING_PROJECT_ID, "config");
263
243
  if (r.id === null || r.id === void 0 || typeof r.id != "string")
264
244
  throw a.clientError("ConfigValidation", "Project ID must be a non-empty string", {
265
245
  providedId: r.id,
266
246
  type: typeof r.id
267
- }), new ne(p.MISSING_PROJECT_ID, "config");
268
- if (r.sessionTimeout !== void 0 && (typeof r.sessionTimeout != "number" || r.sessionTimeout < z || r.sessionTimeout > G))
247
+ }), new ne(y.MISSING_PROJECT_ID, "config");
248
+ if (r.sessionTimeout !== void 0 && (typeof r.sessionTimeout != "number" || r.sessionTimeout < k || r.sessionTimeout > x))
269
249
  throw a.clientError("ConfigValidation", "Invalid session timeout", {
270
250
  provided: r.sessionTimeout,
271
- min: z,
272
- max: G
273
- }), new It(p.INVALID_SESSION_TIMEOUT, "config");
251
+ min: k,
252
+ max: x
253
+ }), new Tt(y.INVALID_SESSION_TIMEOUT, "config");
274
254
  if (r.globalMetadata !== void 0 && (typeof r.globalMetadata != "object" || r.globalMetadata === null))
275
255
  throw a.clientError("ConfigValidation", "Global metadata must be an object", {
276
256
  provided: r.globalMetadata,
277
257
  type: typeof r.globalMetadata
278
- }), new b(p.INVALID_GLOBAL_METADATA, "config");
258
+ }), new A(y.INVALID_GLOBAL_METADATA, "config");
279
259
  if (r.scrollContainerSelectors !== void 0 && bt(r.scrollContainerSelectors), r.integrations && Mt(r.integrations), r.sensitiveQueryParams !== void 0) {
280
260
  if (!Array.isArray(r.sensitiveQueryParams))
281
261
  throw a.clientError("ConfigValidation", "Sensitive query params must be an array", {
282
262
  provided: r.sensitiveQueryParams,
283
263
  type: typeof r.sensitiveQueryParams
284
- }), new b(p.INVALID_SENSITIVE_QUERY_PARAMS, "config");
264
+ }), new A(y.INVALID_SENSITIVE_QUERY_PARAMS, "config");
285
265
  for (const e of r.sensitiveQueryParams)
286
266
  if (typeof e != "string")
287
267
  throw a.clientError("ConfigValidation", "All sensitive query params must be strings", {
288
268
  param: e,
289
269
  type: typeof e
290
- }), new b("All sensitive query params must be strings", "config");
270
+ }), new A("All sensitive query params must be strings", "config");
291
271
  }
292
272
  if (r.errorSampling !== void 0 && (typeof r.errorSampling != "number" || r.errorSampling < 0 || r.errorSampling > 1))
293
273
  throw a.clientError("ConfigValidation", "Invalid error sampling rate", {
294
274
  provided: r.errorSampling,
295
275
  expected: "0-1"
296
- }), new _t(p.INVALID_ERROR_SAMPLING_RATE, "config");
276
+ }), new _t(y.INVALID_ERROR_SAMPLING_RATE, "config");
297
277
  }, At = (r) => {
298
278
  if (r.includes("<") || r.includes(">") || /on\w+\s*=/i.test(r) || !/^[a-zA-Z0-9\-_#.[\]="':, >+~*()]+$/.test(r))
299
279
  return !1;
@@ -313,12 +293,12 @@ const wt = (r) => {
313
293
  selector: t,
314
294
  type: typeof t,
315
295
  isEmpty: t === "" || typeof t == "string" && t.trim() === ""
316
- }), new b(p.INVALID_SCROLL_CONTAINER_SELECTORS, "config");
296
+ }), new A(y.INVALID_SCROLL_CONTAINER_SELECTORS, "config");
317
297
  if (!At(t))
318
298
  throw a.clientError("ConfigValidation", "Invalid or potentially unsafe CSS selector", {
319
299
  selector: t,
320
300
  reason: "Failed security validation"
321
- }), new b("Invalid or potentially unsafe CSS selector", "config");
301
+ }), new A("Invalid or potentially unsafe CSS selector", "config");
322
302
  }
323
303
  }, Mt = (r) => {
324
304
  if (r && r.googleAnalytics) {
@@ -326,12 +306,12 @@ const wt = (r) => {
326
306
  throw a.clientError("ConfigValidation", "Invalid Google Analytics measurement ID", {
327
307
  provided: r.googleAnalytics.measurementId,
328
308
  type: typeof r.googleAnalytics.measurementId
329
- }), new Ce(p.INVALID_GOOGLE_ANALYTICS_ID, "config");
309
+ }), new Ne(y.INVALID_GOOGLE_ANALYTICS_ID, "config");
330
310
  const e = r.googleAnalytics.measurementId.trim();
331
311
  if (!e.match(/^(G-|UA-)/))
332
312
  throw a.clientError("ConfigValidation", 'Google Analytics measurement ID must start with "G-" or "UA-"', {
333
313
  provided: e
334
- }), new Ce('Google Analytics measurement ID must start with "G-" or "UA-"', "config");
314
+ }), new Ne('Google Analytics measurement ID must start with "G-" or "UA-"', "config");
335
315
  }
336
316
  }, Rt = (r) => {
337
317
  wt(r);
@@ -345,41 +325,9 @@ const wt = (r) => {
345
325
  throw a.clientError("ConfigValidation", "Project ID is empty after trimming whitespace", {
346
326
  originalId: r.id,
347
327
  normalizedId: e.id
348
- }), new ne(p.PROJECT_ID_EMPTY_AFTER_TRIM, "config");
328
+ }), new ne(y.PROJECT_ID_EMPTY_AFTER_TRIM, "config");
349
329
  return e;
350
- }, Lt = (r, e) => {
351
- if (r !== void 0)
352
- return typeof r != "number" ? (e.push("samplingRate must be a number"), A) : Number.isNaN(r) || r <= 0 || r > 1 ? (e.push(p.INVALID_SAMPLING_RATE), A) : r;
353
- }, Nt = (r, e, t = "") => {
354
- if (r !== void 0)
355
- if (Array.isArray(r))
356
- for (const [n, s] of r.entries())
357
- if (typeof s == "string")
358
- try {
359
- new RegExp(s);
360
- } catch {
361
- e.push(`${t}excludedUrlPaths[${n}] is not a valid regex pattern`);
362
- }
363
- else
364
- e.push(`${t}excludedUrlPaths[${n}] must be a string`);
365
- else
366
- e.push(`${t}excludedUrlPaths must be an array`);
367
- }, Ct = (r) => {
368
- const e = [], t = [];
369
- r.sessionTimeout !== void 0 && (typeof r.sessionTimeout != "number" ? e.push("sessionTimeout must be a number") : r.sessionTimeout < z ? e.push("sessionTimeout must be at least 30 seconds (30000ms)") : r.sessionTimeout > G && t.push("sessionTimeout is very long (>24 hours), consider reducing it")), r.globalMetadata !== void 0 && (typeof r.globalMetadata != "object" || r.globalMetadata === null ? e.push("globalMetadata must be an object") : (JSON.stringify(r.globalMetadata).length > 10240 && e.push("globalMetadata is too large (max 10KB)"), Object.keys(r.globalMetadata).length > 12 && e.push("globalMetadata has too many keys (max 12)")));
370
- const n = Lt(r.samplingRate, e) ?? A;
371
- return r.tags !== void 0 && !Array.isArray(r.tags) && e.push("tags must be an array"), Nt(r.excludedUrlPaths, e), { errors: e, warnings: t, samplingRate: n };
372
- }, V = (r) => {
373
- const { errors: e, warnings: t, samplingRate: n } = Ct(r);
374
- return {
375
- config: {
376
- ...r,
377
- samplingRate: n
378
- },
379
- errors: e,
380
- warnings: t
381
- };
382
- }, Pe = (r) => {
330
+ }, Ce = (r) => {
383
331
  if (!r || typeof r != "string" || r.trim().length === 0)
384
332
  return a.debug("Sanitize", "String sanitization skipped - empty or invalid input", { value: r, type: typeof r }), "";
385
333
  const e = r.length;
@@ -390,7 +338,7 @@ const wt = (r) => {
390
338
  truncatedLength: t.length
391
339
  }));
392
340
  let n = 0;
393
- for (const i of xe) {
341
+ for (const i of He) {
394
342
  const o = t;
395
343
  t = t.replace(i, ""), o !== t && n++;
396
344
  }
@@ -406,36 +354,36 @@ const wt = (r) => {
406
354
  xssPatternMatches: n,
407
355
  wasTruncated: e > T
408
356
  }), s;
409
- }, Pt = (r) => {
357
+ }, Lt = (r) => {
410
358
  if (typeof r != "string")
411
359
  return "";
412
360
  r.length > T && (r = r.slice(0, Math.max(0, T)));
413
361
  let e = r;
414
- for (const t of xe)
362
+ for (const t of He)
415
363
  e = e.replace(t, "");
416
364
  return e = e.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#x27;"), e.trim();
417
- }, P = (r, e = 0) => {
418
- if (e > be)
365
+ }, U = (r, e = 0) => {
366
+ if (e > Ae)
419
367
  return a.warn("Sanitize", "Maximum object depth exceeded during sanitization", {
420
368
  depth: e,
421
- maxDepth: be
369
+ maxDepth: Ae
422
370
  }), null;
423
371
  if (r == null)
424
372
  return null;
425
373
  if (typeof r == "string")
426
- return Pe(r);
374
+ return Ce(r);
427
375
  if (typeof r == "number")
428
376
  return !Number.isFinite(r) || r < -Number.MAX_SAFE_INTEGER || r > Number.MAX_SAFE_INTEGER ? (a.warn("Sanitize", "Invalid number sanitized to 0", { value: r, isFinite: Number.isFinite(r) }), 0) : r;
429
377
  if (typeof r == "boolean")
430
378
  return r;
431
379
  if (Array.isArray(r)) {
432
- const t = r.length, n = r.slice(0, K);
433
- t > K && a.warn("Sanitize", "Array truncated due to length limit", {
380
+ const t = r.length, n = r.slice(0, q);
381
+ t > q && a.warn("Sanitize", "Array truncated due to length limit", {
434
382
  originalLength: t,
435
- maxLength: K,
383
+ maxLength: q,
436
384
  depth: e
437
385
  });
438
- const s = n.map((i) => P(i, e + 1)).filter((i) => i !== null);
386
+ const s = n.map((i) => U(i, e + 1)).filter((i) => i !== null);
439
387
  return t > 0 && s.length === 0 && a.warn("Sanitize", "All array items were filtered out during sanitization", { originalLength: t, depth: e }), s;
440
388
  }
441
389
  if (typeof r == "object") {
@@ -447,9 +395,9 @@ const wt = (r) => {
447
395
  });
448
396
  let o = 0;
449
397
  for (const [c, l] of i) {
450
- const u = Pe(c);
398
+ const u = Ce(c);
451
399
  if (u) {
452
- const h = P(l, e + 1);
400
+ const h = U(l, e + 1);
453
401
  h !== null ? t[u] = h : o++;
454
402
  } else
455
403
  o++;
@@ -461,7 +409,7 @@ const wt = (r) => {
461
409
  }), t;
462
410
  }
463
411
  return a.debug("Sanitize", "Unknown value type sanitized to null", { type: typeof r, depth: e }), null;
464
- }, Ot = (r) => {
412
+ }, Nt = (r) => {
465
413
  a.debug("Sanitize", "Starting API config sanitization");
466
414
  const e = {};
467
415
  if (typeof r != "object" || r === null)
@@ -470,11 +418,11 @@ const wt = (r) => {
470
418
  const t = Object.keys(r);
471
419
  let n = 0, s = 0;
472
420
  for (const i of t)
473
- if (ct.has(i)) {
421
+ if (lt.has(i)) {
474
422
  const o = r[i];
475
423
  if (i === "excludedUrlPaths") {
476
424
  const c = Array.isArray(o) ? o : typeof o == "string" ? [o] : [], l = c.length;
477
- e.excludedUrlPaths = c.map((h) => Pt(String(h))).filter(Boolean);
425
+ e.excludedUrlPaths = c.map((h) => Lt(String(h))).filter(Boolean);
478
426
  const u = l - e.excludedUrlPaths.length;
479
427
  u > 0 && a.warn("Sanitize", "Some excluded URL paths were filtered during sanitization", {
480
428
  originalCount: l,
@@ -483,10 +431,10 @@ const wt = (r) => {
483
431
  } else if (i === "tags")
484
432
  Array.isArray(o) ? (e.tags = o, a.debug("Sanitize", "Tags processed", { count: o.length })) : a.warn("Sanitize", "Tags value is not an array", { value: o, type: typeof o });
485
433
  else if (i === "samplingRate") {
486
- const c = P(o);
434
+ const c = U(o);
487
435
  typeof c == "number" && (e.samplingRate = c);
488
436
  } else {
489
- const c = P(o);
437
+ const c = U(o);
490
438
  c !== null ? e[i] = c : a.warn("Sanitize", "API config value sanitized to null", { key: i, originalValue: o });
491
439
  }
492
440
  n++;
@@ -504,14 +452,14 @@ const wt = (r) => {
504
452
  }), new Error(`API config sanitization failed: ${t instanceof Error ? t.message : "Unknown error"}`);
505
453
  }
506
454
  return e;
507
- }, Dt = (r) => {
455
+ }, Ct = (r) => {
508
456
  if (a.debug("Sanitize", "Starting metadata sanitization", { hasMetadata: r != null }), typeof r != "object" || r === null)
509
457
  return a.debug("Sanitize", "Metadata is not an object, returning empty object", {
510
458
  metadata: r,
511
459
  type: typeof r
512
460
  }), {};
513
461
  try {
514
- const e = Object.keys(r).length, t = P(r), n = typeof t == "object" && t !== null ? t : {}, s = Object.keys(n).length;
462
+ const e = Object.keys(r).length, t = U(r), n = typeof t == "object" && t !== null ? t : {}, s = Object.keys(n).length;
515
463
  return a.debug("Sanitize", "Metadata sanitization completed", {
516
464
  originalKeys: e,
517
465
  finalKeys: s,
@@ -522,7 +470,7 @@ const wt = (r) => {
522
470
  error: e instanceof Error ? e.message : e
523
471
  }), new Error(`Metadata sanitization failed: ${e instanceof Error ? e.message : "Unknown error"}`);
524
472
  }
525
- }, kt = (r) => {
473
+ }, Pt = (r) => {
526
474
  if (typeof r != "object" || r === null)
527
475
  return !1;
528
476
  for (const e of Object.values(r)) {
@@ -539,7 +487,7 @@ const wt = (r) => {
539
487
  }
540
488
  }
541
489
  return !0;
542
- }, Ut = (r) => typeof r != "string" ? {
490
+ }, Ot = (r) => typeof r != "string" ? {
543
491
  valid: !1,
544
492
  error: "Event name must be a string"
545
493
  } : r.length === 0 ? {
@@ -554,9 +502,9 @@ const wt = (r) => {
554
502
  } : ["constructor", "prototype", "__proto__", "eval", "function", "var", "let", "const"].includes(r.toLowerCase()) ? {
555
503
  valid: !1,
556
504
  error: "Event name cannot be a reserved word"
557
- } : { valid: !0 }, xt = (r, e, t) => {
558
- const n = Dt(e), s = `${t} "${r}" metadata error`;
559
- if (!kt(n))
505
+ } : { valid: !0 }, Pe = (r, e, t) => {
506
+ const n = Ct(e), s = `${t} "${r}" metadata error`;
507
+ if (!Pt(n))
560
508
  return {
561
509
  valid: !1,
562
510
  error: `${s}: object has invalid types. Valid types are string, number, boolean or string arrays.`
@@ -570,22 +518,22 @@ const wt = (r) => {
570
518
  error: `${s}: object contains circular references or cannot be serialized.`
571
519
  };
572
520
  }
573
- if (i.length > _e)
521
+ if (i.length > Te)
574
522
  return {
575
523
  valid: !1,
576
- error: `${s}: object is too large (max ${_e / 1024} KB).`
524
+ error: `${s}: object is too large (max ${Te / 1024} KB).`
577
525
  };
578
- if (Object.keys(n).length > we)
526
+ if (Object.keys(n).length > _e)
579
527
  return {
580
528
  valid: !1,
581
- error: `${s}: object has too many keys (max ${we} keys).`
529
+ error: `${s}: object has too many keys (max ${_e} keys).`
582
530
  };
583
531
  for (const [c, l] of Object.entries(n)) {
584
532
  if (Array.isArray(l)) {
585
- if (l.length > Ae)
533
+ if (l.length > we)
586
534
  return {
587
535
  valid: !1,
588
- error: `${s}: array property "${c}" is too large (max ${Ae} items).`
536
+ error: `${s}: array property "${c}" is too large (max ${we} items).`
589
537
  };
590
538
  for (const u of l)
591
539
  if (typeof u == "string" && u.length > 500)
@@ -604,13 +552,37 @@ const wt = (r) => {
604
552
  valid: !0,
605
553
  sanitizedMetadata: n
606
554
  };
607
- }, Ht = (r, e) => {
608
- const t = Ut(r);
555
+ }, Dt = (r, e, t) => {
556
+ if (Array.isArray(e)) {
557
+ const n = [], s = `${t} "${r}" metadata error`;
558
+ for (let i = 0; i < e.length; i++) {
559
+ const o = e[i];
560
+ if (typeof o != "object" || o === null || Array.isArray(o))
561
+ return {
562
+ valid: !1,
563
+ error: `${s}: array item at index ${i} must be an object.`
564
+ };
565
+ const c = Pe(r, o, t);
566
+ if (!c.valid)
567
+ return {
568
+ valid: !1,
569
+ error: `${s}: array item at index ${i} is invalid: ${c.error}`
570
+ };
571
+ c.sanitizedMetadata && n.push(c.sanitizedMetadata);
572
+ }
573
+ return {
574
+ valid: !0,
575
+ sanitizedMetadata: n
576
+ };
577
+ }
578
+ return Pe(r, e, t);
579
+ }, kt = (r, e) => {
580
+ const t = Ot(r);
609
581
  if (!t.valid)
610
582
  return a.clientError("EventValidation", "Event name validation failed", { eventName: r, error: t.error }), t;
611
583
  if (!e)
612
584
  return { valid: !0 };
613
- const n = xt(r, e, "customEvent");
585
+ const n = Dt(r, e, "customEvent");
614
586
  return n.valid || a.clientError("EventValidation", "Event metadata validation failed", {
615
587
  eventName: r,
616
588
  error: n.error
@@ -622,7 +594,7 @@ const wt = (r) => {
622
594
  } catch {
623
595
  return !1;
624
596
  }
625
- }, Vt = (r, e = !1) => {
597
+ }, xt = (r, e = !1) => {
626
598
  const t = new URL(window.location.href), n = t.hostname, s = n.split(".");
627
599
  if (s.length === 0)
628
600
  throw a.clientError("URLUtils", "Invalid hostname - no domain parts found", { hostname: n }), new Error("Invalid URL");
@@ -651,7 +623,7 @@ const wt = (r) => {
651
623
  error: t instanceof Error ? t.message : t
652
624
  }), r;
653
625
  }
654
- }, Ft = (r, e = []) => {
626
+ }, Ut = (r, e = []) => {
655
627
  if (e.length === 0)
656
628
  return !1;
657
629
  let t;
@@ -679,7 +651,7 @@ const wt = (r) => {
679
651
  }
680
652
  });
681
653
  };
682
- async function zt(r, e = {}) {
654
+ async function Ht(r, e = {}) {
683
655
  const { timeout: t = 1e4, ...n } = e, s = new AbortController(), i = setTimeout(() => {
684
656
  s.abort();
685
657
  }, t);
@@ -693,7 +665,7 @@ async function zt(r, e = {}) {
693
665
  throw clearTimeout(i), o instanceof Error && o.name === "AbortError" ? new Error(`Request timeout after ${t}ms`) : o;
694
666
  }
695
667
  }
696
- class Gt {
668
+ class Vt {
697
669
  listeners = /* @__PURE__ */ new Map();
698
670
  on(e, t) {
699
671
  this.listeners.has(e) || this.listeners.set(e, []), this.listeners.get(e).push(t);
@@ -713,15 +685,15 @@ class Gt {
713
685
  this.listeners.clear();
714
686
  }
715
687
  }
716
- function jt(r, e = !1) {
688
+ function Ft(r, e = !1) {
717
689
  try {
718
- if (r.startsWith(w.Localhost)) {
690
+ if (r === f.Localhost || r === f.Fail) {
719
691
  const n = `http://${r}`;
720
692
  if (!se(n, !0))
721
693
  throw new Error(`Invalid localhost URL format: ${r}`);
722
694
  return n;
723
695
  }
724
- const t = Vt(r, e);
696
+ const t = xt(r, e);
725
697
  if (!se(t, e))
726
698
  throw new Error(`Generated API URL failed validation: ${t}`);
727
699
  return t;
@@ -733,41 +705,121 @@ function jt(r, e = !1) {
733
705
  }), t;
734
706
  }
735
707
  }
736
- class he {
737
- static LOCALHOST_PATTERN = /^localhost:\d{1,5}$/;
708
+ class Oe {
709
+ /**
710
+ * Builds final configuration from app config and API config
711
+ * Applies clear precedence: API overrides client, with defaults as fallback
712
+ */
713
+ static build(e, t = {}) {
714
+ const n = this.resolveMode(e, t.mode), s = {
715
+ // Core identifiers
716
+ id: e.id,
717
+ // Session configuration
718
+ sessionTimeout: this.resolveSessionTimeout(e.sessionTimeout),
719
+ // Mode configuration (resolved first)
720
+ mode: n,
721
+ // Sampling configuration (depends on mode)
722
+ samplingRate: this.resolveSamplingRate(t.samplingRate, e.samplingRate),
723
+ errorSampling: this.resolveErrorSampling(e.errorSampling, n),
724
+ // Filtering configuration
725
+ excludedUrlPaths: t.excludedUrlPaths ?? e.excludedUrlPaths ?? [],
726
+ tags: t.tags ?? [],
727
+ ipExcluded: t.ipExcluded ?? !1,
728
+ // Client-only configuration
729
+ globalMetadata: e.globalMetadata ?? {},
730
+ scrollContainerSelectors: e.scrollContainerSelectors,
731
+ sensitiveQueryParams: e.sensitiveQueryParams ?? [],
732
+ integrations: e.integrations,
733
+ // Security configuration
734
+ allowHttp: e.allowHttp ?? !1
735
+ };
736
+ return a.debug("ConfigBuilder", "Configuration built", {
737
+ projectId: s.id,
738
+ mode: s.mode,
739
+ samplingRate: s.samplingRate,
740
+ errorSampling: s.errorSampling,
741
+ hasTags: !!s.tags?.length,
742
+ hasExclusions: !!s.excludedUrlPaths?.length
743
+ }), s;
744
+ }
745
+ /**
746
+ * Resolves session timeout with validation
747
+ * Returns default if undefined or out of valid range
748
+ */
749
+ static resolveSessionTimeout(e) {
750
+ return e === void 0 ? P : e < k || e > x ? (a.warn("ConfigBuilder", "Invalid session timeout, using default", {
751
+ provided: e,
752
+ min: k,
753
+ max: x,
754
+ default: P
755
+ }), P) : e;
756
+ }
757
+ /**
758
+ * Resolves sampling rate with validation
759
+ * Priority: API config > app config > default
760
+ */
761
+ static resolveSamplingRate(e, t) {
762
+ const n = e ?? t;
763
+ return n === void 0 ? M : n < nt || n > st ? (a.warn("ConfigBuilder", "Invalid sampling rate, using default", {
764
+ provided: n,
765
+ default: M
766
+ }), M) : n;
767
+ }
768
+ /**
769
+ * Resolves error sampling rate based on mode
770
+ * In debug/qa modes: uses provided value or defaults to full sampling (1.0)
771
+ * In production: uses provided value or defaults to 10% sampling (0.1)
772
+ */
773
+ static resolveErrorSampling(e, t) {
774
+ return t === O.DEBUG || t === O.QA ? e ?? 1 : e ?? 0.1;
775
+ }
776
+ /**
777
+ * Resolves mode with special project ID handling
778
+ * Priority: Special project ID > API mode > app mode
779
+ */
780
+ static resolveMode(e, t) {
781
+ return e.id === f.Skip || e.id === f.Fail || e.id.toLowerCase().startsWith("skip-") ? O.DEBUG : t ?? e.mode;
782
+ }
783
+ }
784
+ class zt {
738
785
  static PRODUCTION_DOMAINS = [/^https:\/\/.*\.tracelog\.app$/, /^https:\/\/.*\.tracelog\.dev$/];
739
786
  /**
740
- * Gets complete configuration by merging default, API, and app configurations.
787
+ * Gets complete configuration by loading API config and building final config.
741
788
  *
742
789
  * @param apiUrl - Base URL for the configuration API
743
790
  * @param appConfig - Client-side configuration from init()
744
791
  * @returns Promise<Config> - Merged configuration object
745
792
  */
746
793
  async get(e, t) {
747
- if (t.id === w.Skip)
794
+ if (t.id === f.Skip || t.id === f.Fail || t.id.toLowerCase().startsWith("skip-"))
748
795
  return this.createDefaultConfig(t);
749
- const n = await this.loadFromApi(e, t), { config: s } = V(n);
796
+ const n = await this.loadFromApi(e, t), s = this.applyQaModeIfEnabled(n), i = Oe.build(t, s);
750
797
  return a.info("ConfigManager", "Configuration loaded", {
751
- projectId: t.id,
752
- mode: s.mode,
753
- hasTags: !!s.tags?.length,
754
- hasExclusions: !!s.excludedUrlPaths?.length
755
- }), s;
798
+ projectId: i.id,
799
+ mode: i.mode,
800
+ hasTags: !!i.tags?.length,
801
+ hasExclusions: !!i.excludedUrlPaths?.length
802
+ }), i;
756
803
  }
757
804
  /**
758
- * Loads configuration from API and merges with app config.
805
+ * Loads configuration from API and returns sanitized API config.
806
+ * Only returns values explicitly provided by the API.
759
807
  */
760
808
  async loadFromApi(e, t) {
761
809
  try {
762
- const n = this.buildConfigUrl(e, t), s = this.buildHeaders(t), i = await zt(n, {
810
+ const n = this.buildConfigUrl(e, t), s = this.buildHeaders(t), i = await Ht(n, {
763
811
  method: "GET",
764
812
  headers: s,
765
813
  timeout: Ue
766
814
  });
767
815
  if (!i.ok)
768
816
  throw new Error(`HTTP ${i.status}: ${i.statusText}`);
769
- const o = await this.parseJsonResponse(i);
770
- return this.mergeConfigurations(o, t);
817
+ const o = await this.parseJsonResponse(i), c = Nt(o);
818
+ return {
819
+ ...c,
820
+ excludedUrlPaths: c.excludedUrlPaths ?? N.excludedUrlPaths,
821
+ tags: c.tags ?? N.tags
822
+ };
771
823
  } catch (n) {
772
824
  const s = n instanceof Error ? n.message : "Unknown error";
773
825
  throw a.error("ConfigManager", "Failed to load configuration", {
@@ -781,19 +833,20 @@ class he {
781
833
  * Builds the configuration URL based on project type and QA mode.
782
834
  */
783
835
  buildConfigUrl(e, t) {
784
- if (t.id.startsWith(w.Localhost))
785
- return this.validateLocalhostProjectId(t.id), `http://${t.id}/config`;
836
+ if (t.id === f.Localhost || t.id === f.Fail)
837
+ return `http://${t.id}/config`;
786
838
  const s = `${e}/config`;
787
839
  return this.isQaModeEnabled() ? `${s}?qaMode=true` : s;
788
840
  }
789
841
  /**
790
842
  * Builds request headers based on project configuration.
843
+ * Always includes X-TraceLog-Project header for consistent identification.
791
844
  */
792
845
  buildHeaders(e) {
793
- const t = {
794
- "Content-Type": "application/json"
846
+ return {
847
+ "Content-Type": "application/json",
848
+ "X-TraceLog-Project": e.id
795
849
  };
796
- return e.id.startsWith(w.Localhost) && (t["X-TraceLog-Project"] = e.id), t;
797
850
  }
798
851
  /**
799
852
  * Parses and validates JSON response from config API.
@@ -806,16 +859,6 @@ class he {
806
859
  throw new Error("Invalid response format, expected object");
807
860
  return n;
808
861
  }
809
- /**
810
- * Validates localhost project ID format and port range.
811
- */
812
- validateLocalhostProjectId(e) {
813
- if (!he.LOCALHOST_PATTERN.test(e))
814
- throw new Error(`Invalid localhost format. Expected 'localhost:PORT', got '${e}'`);
815
- const t = parseInt(e.split(":")[1], 10);
816
- if (t < 1 || t > 65535)
817
- throw new Error(`Port must be between 1 and 65535, got ${t}`);
818
- }
819
862
  /**
820
863
  * Checks if QA mode is enabled via URL parameter.
821
864
  */
@@ -823,27 +866,28 @@ class he {
823
866
  return new URLSearchParams(window.location.search).get("qaMode") === "true";
824
867
  }
825
868
  /**
826
- * Merges API configuration with app configuration and applies mode-specific settings.
869
+ * Applies QA mode to API config if enabled via URL parameter.
827
870
  */
828
- mergeConfigurations(e, t) {
829
- const n = Ot(e), s = { ...He, ...n }, i = Me({ ...t, ...s }), { config: o } = V(i);
830
- this.isQaModeEnabled() && !o.mode && (o.mode = H.QA, a.info("ConfigManager", "QA mode enabled via URL parameter"));
831
- const c = Object.values(H).includes(o.mode) ? 1 : o.errorSampling ?? 0.1;
832
- return { ...o, errorSampling: c };
871
+ applyQaModeIfEnabled(e) {
872
+ return this.isQaModeEnabled() && !e.mode ? (a.info("ConfigManager", "QA mode enabled via URL parameter"), { ...e, mode: O.QA }) : e;
833
873
  }
834
874
  /**
835
875
  * Creates default configuration for skip mode and fallback scenarios.
876
+ * Only uses API defaults for fields not provided by the app config.
836
877
  */
837
878
  createDefaultConfig(e) {
838
- const t = Me({
839
- ...e,
840
- errorSampling: 1,
841
- ...e.id === w.Skip && { mode: H.DEBUG }
842
- }), { config: n } = V(t);
843
- return n;
879
+ const t = {
880
+ // Only use defaults if app config doesn't provide these values
881
+ tags: N.tags,
882
+ ipExcluded: N.ipExcluded,
883
+ ...e.samplingRate === void 0 && { samplingRate: N.samplingRate }
884
+ // Don't override excludedUrlPaths if provided by app config
885
+ // ConfigBuilder will handle the fallback to [] if both are undefined
886
+ };
887
+ return Oe.build(e, t);
844
888
  }
845
889
  }
846
- class $t extends f {
890
+ class Gt extends m {
847
891
  storeManager;
848
892
  retryTimeoutId = null;
849
893
  retryCount = 0;
@@ -853,31 +897,23 @@ class $t extends f {
853
897
  }
854
898
  getQueueStorageKey() {
855
899
  const e = this.get("config")?.id || "default", t = this.get("userId") || "anonymous";
856
- return `${dt(e)}:${t}`;
900
+ return `${ut(e)}:${t}`;
857
901
  }
858
- /**
859
- * Send events synchronously using sendBeacon or XHR fallback
860
- * Used primarily for page unload scenarios
861
- */
862
902
  sendEventsQueueSync(e) {
863
903
  if (this.shouldSkipSend())
864
- return this.clearPersistedEvents(), this.resetRetryState(), !0;
865
- const t = this.sendQueueSyncInternal(e);
866
- return t && (this.clearPersistedEvents(), this.resetRetryState()), t;
904
+ return this.resetRetryState(), !0;
905
+ if (this.get("config")?.id === f.Fail)
906
+ return a.warn("SenderManager", "Fail mode: simulating network failure (sync)", {
907
+ events: e.events.length
908
+ }), !1;
909
+ const n = this.sendQueueSyncInternal(e);
910
+ return n && this.resetRetryState(), n;
867
911
  }
868
- /**
869
- * Send events asynchronously with persistence and retry logic
870
- * Main method for sending events during normal operation
871
- */
872
912
  async sendEventsQueue(e, t) {
873
913
  !this.persistEvents(e) && !this.shouldSkipSend() && a.warn("SenderManager", "Failed to persist events, attempting immediate send");
874
914
  const s = await this.send(e);
875
- return s ? (this.clearPersistedEvents(), this.resetRetryState(), t?.onSuccess?.(e.events.length)) : (this.scheduleRetry(e, t), t?.onFailure?.()), s;
915
+ return s ? (this.clearPersistedEvents(), this.resetRetryState(), t?.onSuccess?.(e.events.length, e.events, e)) : (this.scheduleRetry(e, t), t?.onFailure?.()), s;
876
916
  }
877
- /**
878
- * Recover and send previously persisted events
879
- * Called during initialization to handle events from previous session
880
- */
881
917
  async recoverPersistedEvents(e) {
882
918
  try {
883
919
  const t = this.getPersistedData();
@@ -886,91 +922,81 @@ class $t extends f {
886
922
  return;
887
923
  }
888
924
  const n = this.createRecoveryBody(t);
889
- await this.send(n) ? (this.clearPersistedEvents(), this.resetRetryState(), e?.onSuccess?.(t.events.length)) : (this.scheduleRetry(n, e), e?.onFailure?.());
925
+ await this.send(n) ? (this.clearPersistedEvents(), this.resetRetryState(), e?.onSuccess?.(t.events.length, t.events, n)) : (this.scheduleRetry(n, e), e?.onFailure?.());
890
926
  } catch (t) {
891
927
  a.error("SenderManager", "Failed to recover persisted events", { error: t }), this.clearPersistedEvents();
892
928
  }
893
929
  }
894
- /**
895
- * Persist events for recovery in case of failure
896
- */
897
930
  persistEventsForRecovery(e) {
898
931
  return this.persistEvents(e);
899
932
  }
900
- /**
901
- * Legacy method for backward compatibility
902
- * @deprecated Use sendEventsQueue instead
903
- */
904
933
  async sendEventsQueueAsync(e) {
905
934
  return this.sendEventsQueue(e);
906
935
  }
907
- /**
908
- * Stop the sender manager and clean up resources
909
- */
910
936
  stop() {
911
- this.clearRetryTimeout(), this.resetRetryState(), this.clearPersistedEvents();
937
+ this.clearRetryTimeout(), this.resetRetryState();
912
938
  }
913
939
  async send(e) {
914
940
  if (this.shouldSkipSend())
915
941
  return this.simulateSuccessfulSend();
916
- const { url: t, payload: n } = this.prepareRequest(e);
942
+ if (this.get("config")?.id === f.Fail)
943
+ return a.warn("SenderManager", "Fail mode: simulating network failure", {
944
+ events: e.events.length
945
+ }), !1;
946
+ const { url: n, payload: s } = this.prepareRequest(e);
917
947
  try {
918
- return (await this.sendWithTimeout(t, n)).ok;
919
- } catch (s) {
920
- const i = s instanceof Error ? s.message : String(s);
948
+ return (await this.sendWithTimeout(n, s)).ok;
949
+ } catch (i) {
950
+ const o = i instanceof Error ? i.message : String(i);
921
951
  return a.error("SenderManager", "Send request failed", {
922
- error: i,
952
+ error: o,
923
953
  events: e.events.length,
924
- url: t.replace(/\/\/[^/]+/, "//[DOMAIN]")
925
- // Hide domain for privacy
954
+ url: n.replace(/\/\/[^/]+/, "//[DOMAIN]")
926
955
  }), !1;
927
956
  }
928
957
  }
929
958
  async sendWithTimeout(e, t) {
930
- const n = new AbortController(), s = setTimeout(() => n.abort(), Ue);
959
+ const n = new AbortController(), s = setTimeout(() => n.abort(), Ue), i = this.get("config");
931
960
  try {
932
- const i = await fetch(e, {
961
+ const o = await fetch(e, {
933
962
  method: "POST",
934
963
  headers: {
935
- "Content-Type": "application/json"
964
+ "Content-Type": "application/json",
965
+ "X-TraceLog-Project": i?.id || "unknown"
936
966
  },
937
967
  body: t,
938
968
  keepalive: !0,
939
969
  credentials: "include",
940
970
  signal: n.signal
941
971
  });
942
- if (!i.ok)
943
- throw new Error(`HTTP ${i.status}: ${i.statusText}`);
944
- return i;
972
+ if (!o.ok)
973
+ throw new Error(`HTTP ${o.status}: ${o.statusText}`);
974
+ return o;
945
975
  } finally {
946
976
  clearTimeout(s);
947
977
  }
948
978
  }
949
979
  sendQueueSyncInternal(e) {
950
980
  const { url: t, payload: n } = this.prepareRequest(e), s = new Blob([n], { type: "application/json" });
951
- return this.isSendBeaconAvailable() && navigator.sendBeacon(t, s) ? !0 : this.sendSyncXHR(t, n);
952
- }
953
- sendSyncXHR(e, t) {
954
- const n = new XMLHttpRequest();
955
- try {
956
- n.open("POST", e, !1), n.setRequestHeader("Content-Type", "application/json"), n.withCredentials = !0, n.timeout = it, n.send(t);
957
- const s = n.status >= 200 && n.status < 300;
958
- return s || a.warn("SenderManager", "Sync XHR failed", {
959
- status: n.status,
960
- statusText: n.statusText || "Unknown error"
961
- }), s;
962
- } catch (s) {
963
- const i = s instanceof Error ? s.message : String(s);
964
- return a.warn("SenderManager", "Sync XHR error", {
965
- error: i,
966
- status: n.status || "unknown"
967
- }), !1;
968
- }
981
+ if (this.isSendBeaconAvailable()) {
982
+ if (navigator.sendBeacon(t, s))
983
+ return !0;
984
+ a.warn("SenderManager", "sendBeacon failed, persisting events for recovery");
985
+ } else
986
+ a.warn("SenderManager", "sendBeacon not available, persisting events for recovery");
987
+ return this.persistEventsForRecovery(e), !1;
969
988
  }
970
989
  prepareRequest(e) {
990
+ const t = `${this.get("apiUrl")}/collect`, n = {
991
+ ...e,
992
+ _metadata: {
993
+ referer: typeof window < "u" ? window.location.href : void 0,
994
+ timestamp: Date.now()
995
+ }
996
+ };
971
997
  return {
972
- url: `${this.get("apiUrl")}/collect`,
973
- payload: JSON.stringify(e)
998
+ url: t,
999
+ payload: JSON.stringify(n)
974
1000
  };
975
1001
  }
976
1002
  getPersistedData() {
@@ -1012,7 +1038,8 @@ class $t extends f {
1012
1038
  }
1013
1039
  clearPersistedEvents() {
1014
1040
  try {
1015
- this.storeManager.removeItem(this.getQueueStorageKey());
1041
+ const e = this.getQueueStorageKey();
1042
+ this.storeManager.removeItem(e);
1016
1043
  } catch (e) {
1017
1044
  a.warn("SenderManager", "Failed to clear persisted events", { error: e });
1018
1045
  }
@@ -1023,19 +1050,17 @@ class $t extends f {
1023
1050
  scheduleRetry(e, t) {
1024
1051
  if (this.retryTimeoutId !== null || this.isRetrying)
1025
1052
  return;
1026
- if (this.retryCount >= Ee) {
1053
+ if (this.retryCount >= Se) {
1027
1054
  a.warn("SenderManager", "Max retries reached, giving up", { retryCount: this.retryCount }), this.clearPersistedEvents(), this.resetRetryState(), t?.onFailure?.();
1028
1055
  return;
1029
1056
  }
1030
1057
  const n = tt * Math.pow(2, this.retryCount);
1031
- this.retryTimeoutId = window.setTimeout(async () => {
1032
- if (this.retryTimeoutId = null, !this.isRetrying) {
1033
- this.retryCount++, this.isRetrying = !0;
1034
- try {
1035
- await this.send(e) ? (this.clearPersistedEvents(), this.resetRetryState(), t?.onSuccess?.(e.events.length)) : this.retryCount >= Ee ? (this.clearPersistedEvents(), this.resetRetryState(), t?.onFailure?.()) : this.scheduleRetry(e, t);
1036
- } finally {
1037
- this.isRetrying = !1;
1038
- }
1058
+ this.isRetrying = !0, this.retryTimeoutId = window.setTimeout(async () => {
1059
+ this.retryTimeoutId = null, this.retryCount++;
1060
+ try {
1061
+ await this.send(e) ? (this.clearPersistedEvents(), this.resetRetryState(), t?.onSuccess?.(e.events.length)) : this.retryCount >= Se ? (this.clearPersistedEvents(), this.resetRetryState(), t?.onFailure?.()) : this.scheduleRetry(e, t);
1062
+ } finally {
1063
+ this.isRetrying = !1;
1039
1064
  }
1040
1065
  }, n), a.debug("SenderManager", "Retry scheduled", {
1041
1066
  attempt: this.retryCount + 1,
@@ -1045,12 +1070,8 @@ class $t extends f {
1045
1070
  }
1046
1071
  shouldSkipSend() {
1047
1072
  const e = this.get("config"), { id: t } = e || {};
1048
- return t === w.Skip;
1073
+ return t === f.Skip;
1049
1074
  }
1050
- /**
1051
- * Simulate a successful send operation for skip mode
1052
- * Provides realistic timing and behavior without making HTTP requests
1053
- */
1054
1075
  async simulateSuccessfulSend() {
1055
1076
  const e = Math.random() * 400 + 100;
1056
1077
  return await new Promise((t) => setTimeout(t, e)), !0;
@@ -1062,7 +1083,7 @@ class $t extends f {
1062
1083
  this.retryTimeoutId !== null && (clearTimeout(this.retryTimeoutId), this.retryTimeoutId = null);
1063
1084
  }
1064
1085
  }
1065
- class Qt extends f {
1086
+ class jt extends m {
1066
1087
  googleAnalytics;
1067
1088
  dataSender;
1068
1089
  emitter;
@@ -1071,18 +1092,14 @@ class Qt extends f {
1071
1092
  lastEventTime = 0;
1072
1093
  sendIntervalId = null;
1073
1094
  constructor(e, t = null, n = null) {
1074
- super(), this.googleAnalytics = t, this.dataSender = new $t(e), this.emitter = n;
1095
+ super(), this.googleAnalytics = t, this.dataSender = new Gt(e), this.emitter = n;
1075
1096
  }
1076
- /**
1077
- * Recovers persisted events from localStorage
1078
- * Should be called after initialization to recover any events that failed to send
1079
- */
1080
1097
  async recoverPersistedEvents() {
1081
1098
  await this.dataSender.recoverPersistedEvents({
1082
- onSuccess: (e, t) => {
1099
+ onSuccess: (e, t, n) => {
1083
1100
  if (t && t.length > 0) {
1084
- const n = t.map((s) => s.timestamp + "_" + s.type);
1085
- this.removeProcessedEvents(n);
1101
+ const s = t.map((i) => i.timestamp + "_" + i.type);
1102
+ this.removeProcessedEvents(s), n && this.emitEventsQueue(n);
1086
1103
  }
1087
1104
  },
1088
1105
  onFailure: async () => {
@@ -1090,9 +1107,6 @@ class Qt extends f {
1090
1107
  }
1091
1108
  });
1092
1109
  }
1093
- /**
1094
- * Track user events with automatic deduplication and queueing
1095
- */
1096
1110
  track({
1097
1111
  type: e,
1098
1112
  page_url: t,
@@ -1108,7 +1122,7 @@ class Qt extends f {
1108
1122
  a.warn("EventManager", "Event type is required");
1109
1123
  return;
1110
1124
  }
1111
- const h = e, L = h === d.SESSION_START, Ke = h === d.SESSION_END, Xe = L || Ke, qe = t || this.get("pageUrl"), B = this.buildEventPayload({
1125
+ const h = e, L = h === d.SESSION_START, Ke = h === d.SESSION_END, Xe = L || Ke, qe = t || this.get("pageUrl"), K = this.buildEventPayload({
1112
1126
  type: h,
1113
1127
  page_url: qe,
1114
1128
  from_page_url: n,
@@ -1119,58 +1133,46 @@ class Qt extends f {
1119
1133
  error_data: l,
1120
1134
  session_end_reason: u
1121
1135
  });
1122
- if (!this.isEventExcluded(B) && !(!Xe && !this.shouldSample())) {
1136
+ if (!this.isEventExcluded(K) && !(!Xe && !this.shouldSample())) {
1123
1137
  if (L) {
1124
- const pe = this.get("sessionId");
1125
- if (!pe) {
1138
+ const me = this.get("sessionId");
1139
+ if (!me) {
1126
1140
  a.warn("EventManager", "Session start event ignored: missing sessionId");
1127
1141
  return;
1128
1142
  }
1129
1143
  if (this.get("hasStartSession")) {
1130
1144
  a.warn("EventManager", "Duplicate session_start detected", {
1131
- sessionId: pe
1145
+ sessionId: me
1132
1146
  });
1133
1147
  return;
1134
1148
  }
1135
1149
  this.set("hasStartSession", !0);
1136
1150
  }
1137
- this.isDuplicateEvent(B) || this.addToQueue(B);
1151
+ this.isDuplicateEvent(K) || this.addToQueue(K);
1138
1152
  }
1139
1153
  }
1140
1154
  stop() {
1141
1155
  this.sendIntervalId && (clearInterval(this.sendIntervalId), this.sendIntervalId = null), this.eventsQueue = [], this.lastEventFingerprint = null, this.lastEventTime = 0, this.dataSender.stop();
1142
1156
  }
1143
- /**
1144
- * Flush all queued events immediately (async)
1145
- */
1146
1157
  async flushImmediately() {
1147
1158
  return this.flushEvents(!1);
1148
1159
  }
1149
- /**
1150
- * Flush all queued events immediately (sync)
1151
- */
1152
1160
  flushImmediatelySync() {
1153
1161
  return this.flushEvents(!0);
1154
1162
  }
1155
- /**
1156
- * Queue management and sending intervals
1157
- */
1158
1163
  getQueueLength() {
1159
1164
  return this.eventsQueue.length;
1160
1165
  }
1161
1166
  clearSendInterval() {
1162
1167
  this.sendIntervalId && (clearInterval(this.sendIntervalId), this.sendIntervalId = null);
1163
1168
  }
1164
- /**
1165
- * Shared flush implementation for both sync and async modes
1166
- */
1167
1169
  flushEvents(e) {
1168
1170
  if (this.eventsQueue.length === 0)
1169
1171
  return e ? !0 : Promise.resolve(!0);
1170
1172
  const t = this.buildEventsPayload(), n = [...this.eventsQueue], s = n.map((i) => `${i.timestamp}_${i.type}`);
1171
1173
  if (e) {
1172
1174
  const i = this.dataSender.sendEventsQueueSync(t);
1173
- return i && (this.removeProcessedEvents(s), this.clearSendInterval()), i;
1175
+ return i && (this.removeProcessedEvents(s), this.clearSendInterval(), this.emitEventsQueue(t)), i;
1174
1176
  } else
1175
1177
  return this.dataSender.sendEventsQueue(t, {
1176
1178
  onSuccess: () => {
@@ -1183,9 +1185,6 @@ class Qt extends f {
1183
1185
  }
1184
1186
  });
1185
1187
  }
1186
- /**
1187
- * Send queued events to the API
1188
- */
1189
1188
  async sendEventsQueue() {
1190
1189
  if (!this.get("sessionId") || this.eventsQueue.length === 0)
1191
1190
  return;
@@ -1201,10 +1200,6 @@ class Qt extends f {
1201
1200
  }
1202
1201
  });
1203
1202
  }
1204
- /**
1205
- * Build the payload for sending events to the API
1206
- * Includes basic deduplication and sorting
1207
- */
1208
1203
  buildEventsPayload() {
1209
1204
  const e = /* @__PURE__ */ new Map(), t = [];
1210
1205
  for (const s of this.eventsQueue) {
@@ -1220,9 +1215,6 @@ class Qt extends f {
1220
1215
  ...this.get("config")?.globalMetadata && { global_metadata: this.get("config")?.globalMetadata }
1221
1216
  };
1222
1217
  }
1223
- /**
1224
- * Helper methods for event processing
1225
- */
1226
1218
  buildEventPayload(e) {
1227
1219
  const t = e.type === d.SESSION_START, n = e.page_url ?? this.get("pageUrl"), s = {
1228
1220
  type: e.type,
@@ -1236,12 +1228,12 @@ class Qt extends f {
1236
1228
  ...e.web_vitals && { web_vitals: e.web_vitals },
1237
1229
  ...e.error_data && { error_data: e.error_data },
1238
1230
  ...e.session_end_reason && { session_end_reason: e.session_end_reason },
1239
- ...t && Ne() && { utm: Ne() }
1231
+ ...t && Le() && { utm: Le() }
1240
1232
  }, i = this.get("config")?.tags;
1241
1233
  return i?.length && (s.tags = i), s;
1242
1234
  }
1243
1235
  isEventExcluded(e) {
1244
- const t = this.get("config"), n = Ft(e.page_url, t?.excludedUrlPaths ?? []), s = this.get("hasStartSession"), i = e.type === d.SESSION_END, o = e.type === d.SESSION_START;
1236
+ const t = this.get("config"), n = Ut(e.page_url, t?.excludedUrlPaths ?? []), s = this.get("hasStartSession"), i = e.type === d.SESSION_END, o = e.type === d.SESSION_START;
1245
1237
  return n && !o && !(i && s) ? !0 : t?.ipExcluded === !0;
1246
1238
  }
1247
1239
  isDuplicateEvent(e) {
@@ -1254,18 +1246,21 @@ class Qt extends f {
1254
1246
  const n = Math.round((e.click_data.x || 0) / 10) * 10, s = Math.round((e.click_data.y || 0) / 10) * 10;
1255
1247
  t += `_click_${n}_${s}`;
1256
1248
  }
1257
- 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}`), t;
1249
+ 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;
1258
1250
  }
1259
1251
  createEventSignature(e) {
1260
1252
  return this.createEventFingerprint(e);
1261
1253
  }
1262
1254
  addToQueue(e) {
1263
- if (this.eventsQueue.push(e), a.info("EventManager", "Event added to queue", e), this.emitEvent(e), this.eventsQueue.length > Se) {
1264
- const t = this.eventsQueue.shift();
1265
- a.warn("EventManager", "Event queue overflow, oldest event removed", {
1266
- maxLength: Se,
1255
+ if (this.eventsQueue.push(e), this.emitEvent(e), this.eventsQueue.length > pe) {
1256
+ const t = this.eventsQueue.findIndex(
1257
+ (s) => s.type !== d.SESSION_START && s.type !== d.SESSION_END
1258
+ ), n = t >= 0 ? this.eventsQueue.splice(t, 1)[0] : this.eventsQueue.shift();
1259
+ a.warn("EventManager", "Event queue overflow, oldest non-critical event removed", {
1260
+ maxLength: pe,
1267
1261
  currentLength: this.eventsQueue.length,
1268
- removedEventType: t?.type
1262
+ removedEventType: n?.type,
1263
+ wasCritical: n?.type === d.SESSION_START || n?.type === d.SESSION_END
1269
1264
  });
1270
1265
  }
1271
1266
  this.sendIntervalId || this.startSendInterval(), this.handleGoogleAnalyticsIntegration(e);
@@ -1276,7 +1271,11 @@ class Qt extends f {
1276
1271
  }, Ze);
1277
1272
  }
1278
1273
  handleGoogleAnalyticsIntegration(e) {
1279
- this.googleAnalytics && e.type === d.CUSTOM && e.custom_event && (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug" || this.googleAnalytics.trackEvent(e.custom_event.name, e.custom_event.metadata ?? {}));
1274
+ if (this.googleAnalytics && e.type === d.CUSTOM && e.custom_event) {
1275
+ if (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug")
1276
+ return;
1277
+ this.googleAnalytics.trackEvent(e.custom_event.name, e.custom_event.metadata ?? {});
1278
+ }
1280
1279
  }
1281
1280
  shouldSample() {
1282
1281
  const e = this.get("config")?.samplingRate ?? 1;
@@ -1289,20 +1288,14 @@ class Qt extends f {
1289
1288
  return !t.has(s);
1290
1289
  });
1291
1290
  }
1292
- /**
1293
- * Emit event for external listeners
1294
- */
1295
1291
  emitEvent(e) {
1296
1292
  this.emitter && this.emitter.emit(re.EVENT, e);
1297
1293
  }
1298
- /**
1299
- * Emit events queue for external listeners
1300
- */
1301
1294
  emitEventsQueue(e) {
1302
1295
  this.emitter && this.emitter.emit(re.QUEUE, e);
1303
1296
  }
1304
1297
  }
1305
- class Wt {
1298
+ class $t {
1306
1299
  /**
1307
1300
  * Gets or creates a unique user ID for the given project.
1308
1301
  * The user ID is persisted in localStorage and reused across sessions.
@@ -1312,35 +1305,33 @@ class Wt {
1312
1305
  * @returns Persistent unique user ID
1313
1306
  */
1314
1307
  static getId(e, t) {
1315
- const n = ut(t ?? ""), s = e.getItem(n);
1308
+ const n = ct(t ?? ""), s = e.getItem(n);
1316
1309
  if (s)
1317
1310
  return s;
1318
1311
  const i = Et();
1319
1312
  return e.setItem(n, i), i;
1320
1313
  }
1321
1314
  }
1322
- class Bt extends f {
1315
+ class Qt extends m {
1323
1316
  storageManager;
1324
1317
  eventManager;
1318
+ projectId;
1325
1319
  sessionTimeoutId = null;
1326
1320
  broadcastChannel = null;
1327
1321
  activityHandler = null;
1328
1322
  visibilityChangeHandler = null;
1329
1323
  beforeUnloadHandler = null;
1330
1324
  isTracking = !1;
1331
- constructor(e, t) {
1332
- super(), this.storageManager = e, this.eventManager = t;
1325
+ constructor(e, t, n) {
1326
+ super(), this.storageManager = e, this.eventManager = t, this.projectId = n;
1333
1327
  }
1334
- /**
1335
- * Initialize cross-tab synchronization
1336
- */
1337
1328
  initCrossTabSync() {
1338
1329
  if (typeof BroadcastChannel > "u") {
1339
1330
  a.warn("SessionManager", "BroadcastChannel not supported");
1340
1331
  return;
1341
1332
  }
1342
1333
  const e = this.getProjectId();
1343
- this.broadcastChannel = new BroadcastChannel(gt(e)), this.broadcastChannel.onmessage = (t) => {
1334
+ this.broadcastChannel = new BroadcastChannel(ht(e)), this.broadcastChannel.onmessage = (t) => {
1344
1335
  const { action: n, sessionId: s, timestamp: i, projectId: o } = t.data ?? {};
1345
1336
  if (o === e) {
1346
1337
  if (n === "session_end") {
@@ -1351,11 +1342,8 @@ class Bt extends f {
1351
1342
  }
1352
1343
  };
1353
1344
  }
1354
- /**
1355
- * Share session with other tabs
1356
- */
1357
1345
  shareSession(e) {
1358
- this.broadcastChannel?.postMessage({
1346
+ this.broadcastChannel && typeof this.broadcastChannel.postMessage == "function" && this.broadcastChannel.postMessage({
1359
1347
  action: "session_start",
1360
1348
  projectId: this.getProjectId(),
1361
1349
  sessionId: e,
@@ -1363,7 +1351,7 @@ class Bt extends f {
1363
1351
  });
1364
1352
  }
1365
1353
  broadcastSessionEnd(e, t) {
1366
- e && this.broadcastChannel?.postMessage({
1354
+ e && this.broadcastChannel && typeof this.broadcastChannel.postMessage == "function" && this.broadcastChannel.postMessage({
1367
1355
  action: "session_end",
1368
1356
  projectId: this.getProjectId(),
1369
1357
  sessionId: e,
@@ -1371,25 +1359,16 @@ class Bt extends f {
1371
1359
  timestamp: Date.now()
1372
1360
  });
1373
1361
  }
1374
- /**
1375
- * Cleanup cross-tab sync
1376
- */
1377
1362
  cleanupCrossTabSync() {
1378
- this.broadcastChannel && (this.broadcastChannel.close(), this.broadcastChannel = null);
1363
+ this.broadcastChannel && (typeof this.broadcastChannel.close == "function" && this.broadcastChannel.close(), this.broadcastChannel = null);
1379
1364
  }
1380
- /**
1381
- * Recover session from localStorage if it exists and hasn't expired
1382
- */
1383
1365
  recoverSession() {
1384
1366
  const e = this.loadStoredSession();
1385
1367
  if (!e)
1386
1368
  return null;
1387
- const t = this.get("config")?.sessionTimeout ?? ee;
1369
+ const t = this.get("config")?.sessionTimeout ?? P;
1388
1370
  return Date.now() - e.lastActivity > t ? (a.debug("SessionManager", "Stored session expired"), this.clearStoredSession(), null) : (a.info("SessionManager", "Session recovered from storage", { sessionId: e.id }), e.id);
1389
1371
  }
1390
- /**
1391
- * Persist session data to localStorage
1392
- */
1393
1372
  persistSession(e, t = Date.now()) {
1394
1373
  this.saveStoredSession({
1395
1374
  id: e,
@@ -1416,14 +1395,11 @@ class Bt extends f {
1416
1395
  this.storageManager.setItem(t, JSON.stringify(e));
1417
1396
  }
1418
1397
  getSessionStorageKey() {
1419
- return ht(this.getProjectId());
1398
+ return dt(this.getProjectId());
1420
1399
  }
1421
1400
  getProjectId() {
1422
- return this.get("config")?.id ?? "";
1401
+ return this.projectId;
1423
1402
  }
1424
- /**
1425
- * Start session tracking
1426
- */
1427
1403
  async startTracking() {
1428
1404
  if (this.isTracking) {
1429
1405
  a.warn("SessionManager", "Session tracking already active");
@@ -1439,51 +1415,30 @@ class Bt extends f {
1439
1415
  throw this.isTracking = !1, this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupLifecycleListeners(), this.cleanupCrossTabSync(), this.set("sessionId", null), s;
1440
1416
  }
1441
1417
  }
1442
- /**
1443
- * Generate unique session ID
1444
- */
1445
1418
  generateSessionId() {
1446
1419
  return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
1447
1420
  }
1448
- /**
1449
- * Setup session timeout
1450
- */
1451
1421
  setupSessionTimeout() {
1452
1422
  this.clearSessionTimeout();
1453
- const e = this.get("config")?.sessionTimeout ?? ee;
1423
+ const e = this.get("config")?.sessionTimeout ?? P;
1454
1424
  this.sessionTimeoutId = setTimeout(() => {
1455
1425
  this.endSession("inactivity");
1456
1426
  }, e);
1457
1427
  }
1458
- /**
1459
- * Reset session timeout and update activity
1460
- */
1461
1428
  resetSessionTimeout() {
1462
1429
  this.setupSessionTimeout();
1463
1430
  const e = this.get("sessionId");
1464
1431
  e && this.persistSession(e);
1465
1432
  }
1466
- /**
1467
- * Clear session timeout
1468
- */
1469
1433
  clearSessionTimeout() {
1470
1434
  this.sessionTimeoutId && (clearTimeout(this.sessionTimeoutId), this.sessionTimeoutId = null);
1471
1435
  }
1472
- /**
1473
- * Setup activity listeners to track user engagement
1474
- */
1475
1436
  setupActivityListeners() {
1476
1437
  this.activityHandler = () => this.resetSessionTimeout(), document.addEventListener("click", this.activityHandler, { passive: !0 }), document.addEventListener("keydown", this.activityHandler, { passive: !0 }), document.addEventListener("scroll", this.activityHandler, { passive: !0 });
1477
1438
  }
1478
- /**
1479
- * Clean up activity listeners
1480
- */
1481
1439
  cleanupActivityListeners() {
1482
1440
  this.activityHandler && (document.removeEventListener("click", this.activityHandler), document.removeEventListener("keydown", this.activityHandler), document.removeEventListener("scroll", this.activityHandler), this.activityHandler = null);
1483
1441
  }
1484
- /**
1485
- * Setup page lifecycle listeners (visibility and unload)
1486
- */
1487
1442
  setupLifecycleListeners() {
1488
1443
  this.visibilityChangeHandler || this.beforeUnloadHandler || (this.visibilityChangeHandler = () => {
1489
1444
  document.hidden ? this.clearSessionTimeout() : this.get("sessionId") && this.setupSessionTimeout();
@@ -1494,13 +1449,10 @@ class Bt extends f {
1494
1449
  cleanupLifecycleListeners() {
1495
1450
  this.visibilityChangeHandler && (document.removeEventListener("visibilitychange", this.visibilityChangeHandler), this.visibilityChangeHandler = null), this.beforeUnloadHandler && (window.removeEventListener("beforeunload", this.beforeUnloadHandler), this.beforeUnloadHandler = null);
1496
1451
  }
1497
- /**
1498
- * End current session
1499
- */
1500
- endSession(e) {
1452
+ async endSession(e) {
1501
1453
  const t = this.get("sessionId");
1502
1454
  if (!t) {
1503
- a.warn("SessionManager", "endSession called without active session", { reason: e }), this.resetSessionState();
1455
+ a.warn("SessionManager", "endSession called without active session", { reason: e }), this.resetSessionState(e);
1504
1456
  return;
1505
1457
  }
1506
1458
  a.info("SessionManager", "Ending session", { sessionId: t, reason: e }), this.eventManager.track({
@@ -1508,35 +1460,31 @@ class Bt extends f {
1508
1460
  session_end_reason: e
1509
1461
  });
1510
1462
  const n = () => {
1511
- this.broadcastSessionEnd(t, e), this.resetSessionState();
1463
+ this.broadcastSessionEnd(t, e), this.resetSessionState(e);
1512
1464
  };
1513
1465
  if (this.eventManager.flushImmediatelySync()) {
1514
1466
  n();
1515
1467
  return;
1516
1468
  }
1517
- this.eventManager.flushImmediately().then(n).catch((i) => {
1469
+ try {
1470
+ await this.eventManager.flushImmediately(), n();
1471
+ } catch (i) {
1518
1472
  a.warn("SessionManager", "Async flush failed during session end", {
1519
1473
  error: i instanceof Error ? i.message : "Unknown error"
1520
1474
  }), n();
1521
- });
1475
+ }
1522
1476
  }
1523
- resetSessionState() {
1524
- this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupLifecycleListeners(), this.cleanupCrossTabSync(), this.clearStoredSession(), this.set("sessionId", null), this.set("hasStartSession", !1), this.isTracking = !1;
1477
+ resetSessionState(e) {
1478
+ this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupLifecycleListeners(), this.cleanupCrossTabSync(), e !== "page_unload" && this.clearStoredSession(), this.set("sessionId", null), this.set("hasStartSession", !1), this.isTracking = !1;
1525
1479
  }
1526
- /**
1527
- * Stop session tracking
1528
- */
1529
1480
  async stopTracking() {
1530
- this.endSession("manual_stop");
1481
+ await this.endSession("manual_stop");
1531
1482
  }
1532
- /**
1533
- * Clean up all resources
1534
- */
1535
1483
  destroy() {
1536
1484
  this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupCrossTabSync(), this.cleanupLifecycleListeners(), this.isTracking = !1, this.set("hasStartSession", !1);
1537
1485
  }
1538
1486
  }
1539
- class Yt extends f {
1487
+ class Bt extends m {
1540
1488
  eventManager;
1541
1489
  storageManager;
1542
1490
  sessionManager = null;
@@ -1545,25 +1493,28 @@ class Yt extends f {
1545
1493
  super(), this.eventManager = t, this.storageManager = e;
1546
1494
  }
1547
1495
  async startTracking() {
1548
- if (!this.isActive()) {
1549
- if (this.destroyed) {
1550
- a.warn("SessionHandler", "Cannot start tracking on destroyed handler");
1551
- return;
1552
- }
1553
- try {
1554
- this.sessionManager = new Bt(this.storageManager, this.eventManager), await this.sessionManager.startTracking();
1555
- } catch (e) {
1556
- if (this.sessionManager) {
1557
- try {
1558
- this.sessionManager.destroy();
1559
- } catch {
1560
- }
1561
- this.sessionManager = null;
1496
+ if (this.isActive())
1497
+ return;
1498
+ if (this.destroyed) {
1499
+ a.warn("SessionHandler", "Cannot start tracking on destroyed handler");
1500
+ return;
1501
+ }
1502
+ const e = this.get("config")?.id;
1503
+ if (!e)
1504
+ throw new Error("Cannot start session tracking: config not available");
1505
+ try {
1506
+ this.sessionManager = new Qt(this.storageManager, this.eventManager, e), await this.sessionManager.startTracking();
1507
+ } catch (t) {
1508
+ if (this.sessionManager) {
1509
+ try {
1510
+ this.sessionManager.destroy();
1511
+ } catch {
1562
1512
  }
1563
- throw a.error("SessionHandler", "Failed to start session tracking", {
1564
- error: e instanceof Error ? e.message : "Unknown error"
1565
- }), e;
1513
+ this.sessionManager = null;
1566
1514
  }
1515
+ throw a.error("SessionHandler", "Failed to start session tracking", {
1516
+ error: t instanceof Error ? t.message : "Unknown error"
1517
+ }), t;
1567
1518
  }
1568
1519
  }
1569
1520
  isActive() {
@@ -1579,7 +1530,7 @@ class Yt extends f {
1579
1530
  this.destroyed || (this.sessionManager && (this.sessionManager.destroy(), this.sessionManager = null), this.destroyed = !0, this.set("hasStartSession", !1));
1580
1531
  }
1581
1532
  }
1582
- class Kt extends f {
1533
+ class Wt extends m {
1583
1534
  eventManager;
1584
1535
  onTrack;
1585
1536
  originalPushState;
@@ -1633,7 +1584,7 @@ class Kt extends f {
1633
1584
  };
1634
1585
  }
1635
1586
  }
1636
- class Xt extends f {
1587
+ class Yt extends m {
1637
1588
  eventManager;
1638
1589
  clickHandler;
1639
1590
  constructor(e) {
@@ -1671,10 +1622,10 @@ class Xt extends f {
1671
1622
  this.clickHandler && (window.removeEventListener("click", this.clickHandler, !0), this.clickHandler = void 0);
1672
1623
  }
1673
1624
  findTrackingElement(e) {
1674
- return e.hasAttribute(`${k}-name`) ? e : e.closest(`[${k}-name]`) || void 0;
1625
+ return e.hasAttribute(`${F}-name`) ? e : e.closest(`[${F}-name]`) || void 0;
1675
1626
  }
1676
1627
  getRelevantClickElement(e) {
1677
- for (const t of at)
1628
+ for (const t of it)
1678
1629
  try {
1679
1630
  if (e.matches(t))
1680
1631
  return e;
@@ -1698,7 +1649,7 @@ class Xt extends f {
1698
1649
  return { x: s, y: i, relativeX: o, relativeY: c };
1699
1650
  }
1700
1651
  extractTrackingData(e) {
1701
- const t = e.getAttribute(`${k}-name`), n = e.getAttribute(`${k}-value`);
1652
+ const t = e.getAttribute(`${F}-name`), n = e.getAttribute(`${F}-value`);
1702
1653
  if (t)
1703
1654
  return {
1704
1655
  element: e,
@@ -1727,7 +1678,7 @@ class Xt extends f {
1727
1678
  }
1728
1679
  getRelevantText(e, t) {
1729
1680
  const n = e.textContent?.trim() ?? "", s = t.textContent?.trim() ?? "";
1730
- return !n && !s ? "" : n && n.length <= Y ? n : s.length <= Y ? s : s.slice(0, Y - 3) + "...";
1681
+ return !n && !s ? "" : n && n.length <= X ? n : s.length <= X ? s : s.slice(0, X - 3) + "...";
1731
1682
  }
1732
1683
  extractElementAttributes(e) {
1733
1684
  const t = [
@@ -1755,13 +1706,13 @@ class Xt extends f {
1755
1706
  };
1756
1707
  }
1757
1708
  }
1758
- class qt extends f {
1709
+ class Kt extends m {
1759
1710
  eventManager;
1760
1711
  containers = [];
1761
1712
  limitWarningLogged = !1;
1762
- minDepthChange = ve;
1763
- minIntervalMs = ye;
1764
- maxEventsPerSession = Te;
1713
+ minDepthChange = Ee;
1714
+ minIntervalMs = ve;
1715
+ maxEventsPerSession = ye;
1765
1716
  constructor(e) {
1766
1717
  super(), this.eventManager = e;
1767
1718
  }
@@ -1799,7 +1750,7 @@ class qt extends f {
1799
1750
  this.processScrollEvent(s, i, o);
1800
1751
  }
1801
1752
  s.debounceTimer = null;
1802
- }, ke));
1753
+ }, xe));
1803
1754
  }, n = this.getScrollTop(e), s = {
1804
1755
  element: e,
1805
1756
  lastScrollPos: n,
@@ -1808,7 +1759,7 @@ class qt extends f {
1808
1759
  this.getScrollHeight(e),
1809
1760
  this.getViewportHeight(e)
1810
1761
  ),
1811
- lastDirection: x.DOWN,
1762
+ lastDirection: j.DOWN,
1812
1763
  lastEventTime: 0,
1813
1764
  debounceTimer: null,
1814
1765
  listener: t
@@ -1843,7 +1794,7 @@ class qt extends f {
1843
1794
  }));
1844
1795
  }
1845
1796
  applyConfigOverrides() {
1846
- this.minDepthChange = ve, this.minIntervalMs = ye, this.maxEventsPerSession = Te;
1797
+ this.minDepthChange = Ee, this.minIntervalMs = ve, this.maxEventsPerSession = ye;
1847
1798
  }
1848
1799
  isWindowScrollable() {
1849
1800
  return document.documentElement.scrollHeight > window.innerHeight;
@@ -1852,7 +1803,7 @@ class qt extends f {
1852
1803
  e.debounceTimer !== null && (clearTimeout(e.debounceTimer), e.debounceTimer = null);
1853
1804
  }
1854
1805
  getScrollDirection(e, t) {
1855
- return e > t ? x.DOWN : x.UP;
1806
+ return e > t ? j.DOWN : j.UP;
1856
1807
  }
1857
1808
  calculateScrollDepth(e, t, n) {
1858
1809
  if (t <= n)
@@ -1891,7 +1842,7 @@ class qt extends f {
1891
1842
  }
1892
1843
  }
1893
1844
  }
1894
- class Jt extends f {
1845
+ class Xt extends m {
1895
1846
  isInitialized = !1;
1896
1847
  async initialize() {
1897
1848
  if (this.isInitialized)
@@ -1913,7 +1864,8 @@ class Jt extends f {
1913
1864
  trackEvent(e, t) {
1914
1865
  if (!(!e?.trim() || !this.isInitialized || typeof window.gtag != "function"))
1915
1866
  try {
1916
- window.gtag("event", e, t);
1867
+ const n = Array.isArray(t) ? { items: t } : t;
1868
+ window.gtag("event", e, n);
1917
1869
  } catch (n) {
1918
1870
  a.error("GoogleAnalyticsIntegration", "Event tracking failed", {
1919
1871
  error: n instanceof Error ? n.message : "Unknown error"
@@ -1946,9 +1898,10 @@ class Jt extends f {
1946
1898
  `, document.head.appendChild(n);
1947
1899
  }
1948
1900
  }
1949
- class Zt {
1901
+ class qt {
1950
1902
  storage;
1951
1903
  fallbackStorage = /* @__PURE__ */ new Map();
1904
+ hasQuotaExceededError = !1;
1952
1905
  constructor() {
1953
1906
  this.storage = this.initializeStorage(), this.storage || a.warn("StorageManager", "localStorage not available, using memory fallback");
1954
1907
  }
@@ -1972,7 +1925,10 @@ class Zt {
1972
1925
  return;
1973
1926
  }
1974
1927
  } catch (n) {
1975
- a.warn("StorageManager", "Failed to set item, using fallback", { key: e, error: n });
1928
+ n instanceof DOMException && n.name === "QuotaExceededError" ? (this.hasQuotaExceededError = !0, a.error("StorageManager", "localStorage quota exceeded - data will not persist after reload", {
1929
+ key: e,
1930
+ valueSize: t.length
1931
+ })) : a.warn("StorageManager", "Failed to set item, using fallback", { key: e, error: n });
1976
1932
  }
1977
1933
  this.fallbackStorage.set(e, t);
1978
1934
  }
@@ -2012,6 +1968,13 @@ class Zt {
2012
1968
  isAvailable() {
2013
1969
  return this.storage !== null;
2014
1970
  }
1971
+ /**
1972
+ * Checks if a QuotaExceededError has occurred
1973
+ * This indicates localStorage is full and data may not persist
1974
+ */
1975
+ hasQuotaError() {
1976
+ return this.hasQuotaExceededError;
1977
+ }
2015
1978
  /**
2016
1979
  * Initialize localStorage with feature detection
2017
1980
  */
@@ -2026,7 +1989,7 @@ class Zt {
2026
1989
  }
2027
1990
  }
2028
1991
  }
2029
- class er extends f {
1992
+ class Jt extends m {
2030
1993
  eventManager;
2031
1994
  reportedByNav = /* @__PURE__ */ new Map();
2032
1995
  observers = [];
@@ -2055,7 +2018,7 @@ class er extends f {
2055
2018
  "largest-contentful-paint",
2056
2019
  (n) => {
2057
2020
  const s = n.getEntries(), i = s[s.length - 1];
2058
- i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(_)) });
2021
+ i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(w)) });
2059
2022
  },
2060
2023
  { type: "largest-contentful-paint", buffered: !0 },
2061
2024
  !0
@@ -2073,14 +2036,14 @@ class er extends f {
2073
2036
  const c = typeof o.value == "number" ? o.value : 0;
2074
2037
  e += c;
2075
2038
  }
2076
- this.sendVital({ type: "CLS", value: Number(e.toFixed(_)) });
2039
+ this.sendVital({ type: "CLS", value: Number(e.toFixed(w)) });
2077
2040
  },
2078
2041
  { type: "layout-shift", buffered: !0 }
2079
2042
  ), this.safeObserve(
2080
2043
  "paint",
2081
2044
  (n) => {
2082
2045
  for (const s of n.getEntries())
2083
- s.name === "first-contentful-paint" && this.sendVital({ type: "FCP", value: Number(s.startTime.toFixed(_)) });
2046
+ s.name === "first-contentful-paint" && this.sendVital({ type: "FCP", value: Number(s.startTime.toFixed(w)) });
2084
2047
  },
2085
2048
  { type: "paint", buffered: !0 },
2086
2049
  !0
@@ -2093,15 +2056,15 @@ class er extends f {
2093
2056
  const c = (o.processingEnd ?? 0) - (o.startTime ?? 0);
2094
2057
  s = Math.max(s, c);
2095
2058
  }
2096
- s > 0 && this.sendVital({ type: "INP", value: Number(s.toFixed(_)) });
2059
+ s > 0 && this.sendVital({ type: "INP", value: Number(s.toFixed(w)) });
2097
2060
  },
2098
2061
  { type: "event", buffered: !0 }
2099
2062
  );
2100
2063
  }
2101
2064
  async initWebVitals() {
2102
2065
  try {
2103
- const { onLCP: e, onCLS: t, onFCP: n, onTTFB: s, onINP: i } = await Promise.resolve().then(() => yr), o = (c) => (l) => {
2104
- const u = Number(l.value.toFixed(_));
2066
+ const { onLCP: e, onCLS: t, onFCP: n, onTTFB: s, onINP: i } = await Promise.resolve().then(() => Er), o = (c) => (l) => {
2067
+ const u = Number(l.value.toFixed(w));
2105
2068
  this.sendVital({ type: c, value: u });
2106
2069
  };
2107
2070
  e(o("LCP")), t(o("CLS")), n(o("FCP")), s(o("TTFB")), i(o("INP"));
@@ -2117,7 +2080,7 @@ class er extends f {
2117
2080
  if (!e)
2118
2081
  return;
2119
2082
  const t = e.responseStart;
2120
- typeof t == "number" && Number.isFinite(t) && this.sendVital({ type: "TTFB", value: Number(t.toFixed(_)) });
2083
+ typeof t == "number" && Number.isFinite(t) && this.sendVital({ type: "TTFB", value: Number(t.toFixed(w)) });
2121
2084
  } catch (e) {
2122
2085
  a.warn("PerformanceHandler", "Failed to report TTFB", {
2123
2086
  error: e instanceof Error ? e.message : "Unknown error"
@@ -2130,8 +2093,8 @@ class er extends f {
2130
2093
  (e) => {
2131
2094
  const t = e.getEntries();
2132
2095
  for (const n of t) {
2133
- const s = Number(n.duration.toFixed(_)), i = Date.now();
2134
- i - this.lastLongTaskSentAt >= ft && (this.shouldSendVital("LONG_TASK", s) && this.trackWebVital("LONG_TASK", s), this.lastLongTaskSentAt = i);
2096
+ const s = Number(n.duration.toFixed(w)), i = Date.now();
2097
+ i - this.lastLongTaskSentAt >= gt && (this.shouldSendVital("LONG_TASK", s) && this.trackWebVital("LONG_TASK", s), this.lastLongTaskSentAt = i);
2135
2098
  }
2136
2099
  },
2137
2100
  { type: "longtask", buffered: !0 }
@@ -2218,7 +2181,7 @@ class er extends f {
2218
2181
  }), !1) : !0;
2219
2182
  }
2220
2183
  }
2221
- class tr extends f {
2184
+ class Zt extends m {
2222
2185
  eventManager;
2223
2186
  recentErrors = /* @__PURE__ */ new Map();
2224
2187
  constructor(e) {
@@ -2238,14 +2201,14 @@ class tr extends f {
2238
2201
  if (!this.shouldSample())
2239
2202
  return;
2240
2203
  const t = this.sanitize(e.message || "Unknown error");
2241
- this.shouldSuppressError(N.JS_ERROR, t) || (a.warn("ErrorHandler", "JS error captured", {
2204
+ this.shouldSuppressError(C.JS_ERROR, t) || (a.warn("ErrorHandler", "JS error captured", {
2242
2205
  message: t,
2243
2206
  filename: e.filename,
2244
2207
  line: e.lineno
2245
2208
  }), this.eventManager.track({
2246
2209
  type: d.ERROR,
2247
2210
  error_data: {
2248
- type: N.JS_ERROR,
2211
+ type: C.JS_ERROR,
2249
2212
  message: t,
2250
2213
  ...e.filename && { filename: e.filename },
2251
2214
  ...e.lineno && { line: e.lineno },
@@ -2257,10 +2220,10 @@ class tr extends f {
2257
2220
  if (!this.shouldSample())
2258
2221
  return;
2259
2222
  const t = this.extractRejectionMessage(e.reason), n = this.sanitize(t);
2260
- this.shouldSuppressError(N.PROMISE_REJECTION, n) || (a.warn("ErrorHandler", "Promise rejection captured", { message: n }), this.eventManager.track({
2223
+ this.shouldSuppressError(C.PROMISE_REJECTION, n) || (a.warn("ErrorHandler", "Promise rejection captured", { message: n }), this.eventManager.track({
2261
2224
  type: d.ERROR,
2262
2225
  error_data: {
2263
- type: N.PROMISE_REJECTION,
2226
+ type: C.PROMISE_REJECTION,
2264
2227
  message: n
2265
2228
  }
2266
2229
  }));
@@ -2279,7 +2242,7 @@ class tr extends f {
2279
2242
  }
2280
2243
  }
2281
2244
  sanitize(e) {
2282
- let t = e.length > Re ? e.slice(0, Re) + "..." : e;
2245
+ let t = e.length > be ? e.slice(0, be) + "..." : e;
2283
2246
  for (const n of Fe) {
2284
2247
  const s = new RegExp(n.source, n.flags);
2285
2248
  t = t.replace(s, "[REDACTED]");
@@ -2288,25 +2251,28 @@ class tr extends f {
2288
2251
  }
2289
2252
  shouldSuppressError(e, t) {
2290
2253
  const n = Date.now(), s = `${e}:${t}`, i = this.recentErrors.get(s);
2291
- return i && n - i < Le ? (this.recentErrors.set(s, n), !0) : (this.recentErrors.set(s, n), this.recentErrors.size > X && this.pruneOldErrors(), !1);
2254
+ return i && n - i < Me ? (this.recentErrors.set(s, n), !0) : (this.recentErrors.set(s, n), this.recentErrors.size > Re ? (a.warn("ErrorHandler", "Hard limit exceeded, clearing all tracked errors", {
2255
+ size: this.recentErrors.size,
2256
+ limit: Re
2257
+ }), this.recentErrors.clear(), this.recentErrors.set(s, n), !1) : (this.recentErrors.size > G && this.pruneOldErrors(), !1));
2292
2258
  }
2293
2259
  pruneOldErrors() {
2294
2260
  const e = Date.now();
2295
2261
  for (const [s, i] of this.recentErrors.entries())
2296
- e - i > Le && this.recentErrors.delete(s);
2297
- if (this.recentErrors.size <= X)
2262
+ e - i > Me && this.recentErrors.delete(s);
2263
+ if (this.recentErrors.size <= G)
2298
2264
  return;
2299
- const t = Array.from(this.recentErrors.entries()).sort((s, i) => s[1] - i[1]), n = this.recentErrors.size - X;
2265
+ const t = Array.from(this.recentErrors.entries()).sort((s, i) => s[1] - i[1]), n = this.recentErrors.size - G;
2300
2266
  for (let s = 0; s < n; s += 1) {
2301
2267
  const i = t[s];
2302
2268
  i && this.recentErrors.delete(i[0]);
2303
2269
  }
2304
2270
  }
2305
2271
  }
2306
- class rr extends f {
2272
+ class er extends m {
2307
2273
  isInitialized = !1;
2308
2274
  suppressNextScrollTimer = null;
2309
- emitter = new Gt();
2275
+ emitter = new Vt();
2310
2276
  managers = {};
2311
2277
  handlers = {};
2312
2278
  integrations = {};
@@ -2317,9 +2283,9 @@ class rr extends f {
2317
2283
  if (!this.isInitialized) {
2318
2284
  if (!e.id?.trim())
2319
2285
  throw new Error("Project ID is required");
2320
- this.managers.storage = new Zt();
2286
+ this.managers.storage = new qt();
2321
2287
  try {
2322
- await this.setupState(e), await this.setupIntegrations(), this.managers.event = new Qt(this.managers.storage, this.integrations.googleAnalytics, this.emitter), this.initializeHandlers(), await this.managers.event.recoverPersistedEvents().catch(() => {
2288
+ await this.setupState(e), await this.setupIntegrations(), this.managers.event = new jt(this.managers.storage, this.integrations.googleAnalytics, this.emitter), this.initializeHandlers(), await this.managers.event.recoverPersistedEvents().catch(() => {
2323
2289
  a.warn("App", "Failed to recover persisted events");
2324
2290
  }), this.isInitialized = !0;
2325
2291
  } catch (t) {
@@ -2330,7 +2296,7 @@ class rr extends f {
2330
2296
  sendCustomEvent(e, t) {
2331
2297
  if (!this.managers.event)
2332
2298
  return;
2333
- const { valid: n, error: s, sanitizedMetadata: i } = Ht(e, t);
2299
+ const { valid: n, error: s, sanitizedMetadata: i } = kt(e, t);
2334
2300
  if (!n) {
2335
2301
  const o = this.get("config");
2336
2302
  if (o?.mode === "qa" || o?.mode === "debug")
@@ -2362,29 +2328,29 @@ class rr extends f {
2362
2328
  a.warn("App", "Failed to stop tracking");
2363
2329
  }
2364
2330
  });
2365
- await Promise.allSettled(t), this.suppressNextScrollTimer && (clearTimeout(this.suppressNextScrollTimer), this.suppressNextScrollTimer = null), this.managers.event?.stop(), this.emitter.removeAllListeners(), this.set("hasStartSession", !1), this.set("suppressNextScroll", !1), this.set("sessionId", null), this.isInitialized = !1, this.handlers = {};
2331
+ await Promise.allSettled(t), 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 = {};
2366
2332
  }
2367
2333
  async setupState(e) {
2368
- const t = jt(e.id, e.allowHttp);
2334
+ const t = Ft(e.id, e.allowHttp);
2369
2335
  this.set("apiUrl", t);
2370
- const s = await new he().get(t, e), { config: i } = V(s);
2371
- this.set("config", i);
2372
- const o = Wt.getId(this.managers.storage, i.id);
2373
- this.set("userId", o), this.set("device", St());
2374
- const c = ie(window.location.href, i.sensitiveQueryParams);
2375
- this.set("pageUrl", c);
2336
+ const s = await new zt().get(t, e);
2337
+ this.set("config", s);
2338
+ const i = $t.getId(this.managers.storage, s.id);
2339
+ this.set("userId", i), this.set("device", St());
2340
+ const o = ie(window.location.href, s.sensitiveQueryParams);
2341
+ this.set("pageUrl", o);
2376
2342
  }
2377
2343
  async setupIntegrations() {
2378
2344
  const e = this.get("config"), t = e.integrations?.googleAnalytics?.measurementId;
2379
2345
  if (!e.ipExcluded && t?.trim())
2380
2346
  try {
2381
- this.integrations.googleAnalytics = new Jt(), await this.integrations.googleAnalytics.initialize();
2347
+ this.integrations.googleAnalytics = new Xt(), await this.integrations.googleAnalytics.initialize();
2382
2348
  } catch {
2383
2349
  this.integrations.googleAnalytics = void 0;
2384
2350
  }
2385
2351
  }
2386
2352
  initializeHandlers() {
2387
- this.handlers.session = new Yt(
2353
+ this.handlers.session = new Bt(
2388
2354
  this.managers.storage,
2389
2355
  this.managers.event
2390
2356
  ), this.handlers.session.startTracking().catch((t) => {
@@ -2395,15 +2361,15 @@ class rr extends f {
2395
2361
  const e = () => {
2396
2362
  this.set("suppressNextScroll", !0), this.suppressNextScrollTimer && clearTimeout(this.suppressNextScrollTimer), this.suppressNextScrollTimer = window.setTimeout(() => {
2397
2363
  this.set("suppressNextScroll", !1);
2398
- }, ke * lt);
2364
+ }, xe * ot);
2399
2365
  };
2400
- this.handlers.pageView = new Kt(this.managers.event, e), this.handlers.pageView.startTracking(), this.handlers.click = new Xt(this.managers.event), this.handlers.click.startTracking(), this.handlers.scroll = new qt(this.managers.event), this.handlers.scroll.startTracking(), this.handlers.performance = new er(this.managers.event), this.handlers.performance.startTracking().catch(() => {
2366
+ this.handlers.pageView = new Wt(this.managers.event, e), this.handlers.pageView.startTracking(), this.handlers.click = new Yt(this.managers.event), this.handlers.click.startTracking(), this.handlers.scroll = new Kt(this.managers.event), this.handlers.scroll.startTracking(), this.handlers.performance = new Jt(this.managers.event), this.handlers.performance.startTracking().catch(() => {
2401
2367
  a.warn("App", "Failed to start performance tracking");
2402
- }), this.handlers.error = new tr(this.managers.event), this.handlers.error.startTracking();
2368
+ }), this.handlers.error = new Zt(this.managers.event), this.handlers.error.startTracking();
2403
2369
  }
2404
2370
  }
2405
- let g = null, C = !1, q = !1;
2406
- const nr = async (r) => {
2371
+ let g = null, D = !1, J = !1;
2372
+ const tr = async (r) => {
2407
2373
  if (typeof window > "u" || typeof document > "u")
2408
2374
  throw new Error("This library can only be used in a browser environment");
2409
2375
  if (!window.__traceLogDisabled) {
@@ -2411,12 +2377,12 @@ const nr = async (r) => {
2411
2377
  a.debug("API", "Library already initialized, skipping duplicate initialization");
2412
2378
  return;
2413
2379
  }
2414
- if (C)
2380
+ if (D)
2415
2381
  throw a.warn("API", "Initialization already in progress"), new Error("Initialization already in progress");
2416
- C = !0;
2382
+ D = !0;
2417
2383
  try {
2418
2384
  a.info("API", "Initializing TraceLog", { projectId: r.id });
2419
- const e = Rt(r), t = new rr();
2385
+ const e = Rt(r), t = new er();
2420
2386
  try {
2421
2387
  await t.init(e), g = t, a.info("API", "TraceLog initialized successfully", { projectId: e.id });
2422
2388
  } catch (n) {
@@ -2430,10 +2396,10 @@ const nr = async (r) => {
2430
2396
  } catch (e) {
2431
2397
  throw g = null, a.error("API", "Initialization failed", { error: e }), e;
2432
2398
  } finally {
2433
- C = !1;
2399
+ D = !1;
2434
2400
  }
2435
2401
  }
2436
- }, sr = (r, e) => {
2402
+ }, rr = (r, e) => {
2437
2403
  if (!g)
2438
2404
  throw new Error("TraceLog not initialized. Please call init() first.");
2439
2405
  try {
@@ -2441,34 +2407,34 @@ const nr = async (r) => {
2441
2407
  } catch (t) {
2442
2408
  throw a.error("API", "Failed to send custom event", { eventName: r, error: t }), t;
2443
2409
  }
2444
- }, ir = (r, e) => {
2410
+ }, nr = (r, e) => {
2445
2411
  if (!g)
2446
2412
  throw new Error("TraceLog not initialized. Please call init() first.");
2447
2413
  g.on(r, e);
2448
- }, ar = (r, e) => {
2414
+ }, sr = (r, e) => {
2449
2415
  if (!g)
2450
2416
  throw new Error("TraceLog not initialized. Please call init() first.");
2451
2417
  g.off(r, e);
2452
- }, or = () => g !== null, lr = async () => {
2418
+ }, ir = () => g !== null, ar = async () => {
2453
2419
  if (!g)
2454
2420
  throw new Error("App not initialized");
2455
- if (q)
2421
+ if (J)
2456
2422
  throw new Error("Destroy operation already in progress");
2457
- q = !0;
2423
+ J = !0;
2458
2424
  try {
2459
- a.info("API", "Destroying TraceLog instance"), await g.destroy(), g = null, C = !1, a.info("API", "TraceLog destroyed successfully");
2425
+ a.info("API", "Destroying TraceLog instance"), await g.destroy(), g = null, D = !1, a.info("API", "TraceLog destroyed successfully");
2460
2426
  } catch (r) {
2461
- throw g = null, C = !1, a.error("API", "Error during destroy, forced cleanup", { error: r }), r;
2427
+ throw g = null, D = !1, a.error("API", "Error during destroy, forced cleanup", { error: r }), r;
2462
2428
  } finally {
2463
- q = !1;
2429
+ J = !1;
2464
2430
  }
2465
- }, Tr = {
2431
+ }, vr = {
2466
2432
  WEB_VITALS_THRESHOLDS: Ve
2467
2433
  // Business thresholds for performance analysis
2468
- }, Ir = {
2434
+ }, yr = {
2469
2435
  PII_PATTERNS: Fe
2470
2436
  // Patterns for sensitive data protection
2471
- }, _r = {
2437
+ }, Ir = {
2472
2438
  LOW_ACTIVITY_EVENT_COUNT: 50,
2473
2439
  HIGH_ACTIVITY_EVENT_COUNT: 1e3,
2474
2440
  MIN_EVENTS_FOR_DYNAMIC_CALCULATION: 100,
@@ -2478,7 +2444,7 @@ const nr = async (r) => {
2478
2444
  MIN_ENGAGED_SESSION_DURATION_MS: 30 * 1e3,
2479
2445
  MIN_SCROLL_DEPTH_ENGAGEMENT: 25
2480
2446
  // 25% scroll depth for engagement
2481
- }, wr = {
2447
+ }, Tr = {
2482
2448
  INACTIVITY_TIMEOUT_MS: 30 * 60 * 1e3,
2483
2449
  // 30min for analytics (vs 15min client)
2484
2450
  SHORT_SESSION_THRESHOLD_MS: 30 * 1e3,
@@ -2486,20 +2452,20 @@ const nr = async (r) => {
2486
2452
  LONG_SESSION_THRESHOLD_MS: 30 * 60 * 1e3,
2487
2453
  MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1e3
2488
2454
  // Filter outliers
2489
- }, Ar = {
2455
+ }, _r = {
2490
2456
  MOBILE_MAX_WIDTH: 768,
2491
2457
  TABLET_MAX_WIDTH: 1024,
2492
2458
  MOBILE_PERFORMANCE_FACTOR: 1.5,
2493
2459
  // Mobile typically 1.5x slower
2494
2460
  TABLET_PERFORMANCE_FACTOR: 1.2
2495
- }, br = {
2461
+ }, wr = {
2496
2462
  MIN_TEXT_LENGTH_FOR_ANALYSIS: 10,
2497
2463
  MIN_CLICKS_FOR_HOT_ELEMENT: 10,
2498
2464
  // Popular element threshold
2499
2465
  MIN_SCROLL_COMPLETION_PERCENT: 80,
2500
2466
  // Page consumption threshold
2501
2467
  MIN_TIME_ON_PAGE_FOR_READ_MS: 15 * 1e3
2502
- }, Mr = {
2468
+ }, Ar = {
2503
2469
  SIGNIFICANT_CHANGE_PERCENT: 20,
2504
2470
  MAJOR_CHANGE_PERCENT: 50,
2505
2471
  MIN_EVENTS_FOR_INSIGHT: 100,
@@ -2509,19 +2475,19 @@ const nr = async (r) => {
2509
2475
  LOW_ERROR_RATE_PERCENT: 1,
2510
2476
  HIGH_ERROR_RATE_PERCENT: 5,
2511
2477
  CRITICAL_ERROR_RATE_PERCENT: 10
2512
- }, Rr = {
2478
+ }, br = {
2513
2479
  SHORT_TERM_TREND_HOURS: 24,
2514
2480
  MEDIUM_TERM_TREND_DAYS: 7,
2515
2481
  LONG_TERM_TREND_DAYS: 30,
2516
2482
  MIN_DATA_POINTS_FOR_TREND: 5,
2517
2483
  WEEKLY_PATTERN_MIN_WEEKS: 4,
2518
2484
  DAILY_PATTERN_MIN_DAYS: 14
2519
- }, Lr = {
2485
+ }, Mr = {
2520
2486
  MIN_SEGMENT_SIZE: 10,
2521
2487
  MIN_COHORT_SIZE: 5,
2522
2488
  COHORT_ANALYSIS_DAYS: [1, 3, 7, 14, 30],
2523
2489
  MIN_FUNNEL_EVENTS: 20
2524
- }, Nr = {
2490
+ }, Rr = {
2525
2491
  DEFAULT_EVENTS_LIMIT: 5,
2526
2492
  DEFAULT_SESSIONS_LIMIT: 5,
2527
2493
  DEFAULT_PAGES_LIMIT: 5,
@@ -2529,38 +2495,38 @@ const nr = async (r) => {
2529
2495
  MAX_TIME_RANGE_DAYS: 365,
2530
2496
  ANALYTICS_BATCH_SIZE: 1e3
2531
2497
  // For historical analysis
2532
- }, Cr = {
2498
+ }, Lr = {
2533
2499
  ANOMALY_THRESHOLD_SIGMA: 2.5,
2534
2500
  STRONG_ANOMALY_THRESHOLD_SIGMA: 3,
2535
2501
  TRAFFIC_DROP_ALERT_PERCENT: -30,
2536
2502
  TRAFFIC_SPIKE_ALERT_PERCENT: 200,
2537
2503
  MIN_BASELINE_DAYS: 7,
2538
2504
  MIN_EVENTS_FOR_ANOMALY_DETECTION: 50
2539
- }, Pr = {
2505
+ }, Nr = {
2540
2506
  PAGE_URL_EXCLUDED: "excluded",
2541
2507
  PAGE_URL_UNKNOWN: "unknown"
2542
- }, Or = {
2543
- init: nr,
2544
- event: sr,
2545
- on: ir,
2546
- off: ar,
2547
- isInitialized: or,
2548
- destroy: lr
2508
+ }, Cr = {
2509
+ init: tr,
2510
+ event: rr,
2511
+ on: nr,
2512
+ off: sr,
2513
+ isInitialized: ir,
2514
+ destroy: ar
2549
2515
  };
2550
2516
  var ae, Ge = -1, R = function(r) {
2551
2517
  addEventListener("pageshow", function(e) {
2552
2518
  e.persisted && (Ge = e.timeStamp, r(e));
2553
2519
  }, !0);
2554
- }, ge = function() {
2520
+ }, he = function() {
2555
2521
  var r = self.performance && performance.getEntriesByType && performance.getEntriesByType("navigation")[0];
2556
2522
  if (r && r.responseStart > 0 && r.responseStart < performance.now()) return r;
2557
- }, $ = function() {
2558
- var r = ge();
2523
+ }, B = function() {
2524
+ var r = he();
2559
2525
  return r && r.activationStart || 0;
2560
- }, S = function(r, e) {
2561
- var t = ge(), n = "navigate";
2562
- return Ge >= 0 ? n = "back-forward-cache" : t && (document.prerendering || $() > 0 ? n = "prerender" : document.wasDiscarded ? n = "restore" : t.type && (n = t.type.replace(/_/g, "-"))), { name: r, value: e === void 0 ? -1 : e, rating: "good", delta: 0, entries: [], id: "v4-".concat(Date.now(), "-").concat(Math.floor(8999999999999 * Math.random()) + 1e12), navigationType: n };
2563
- }, D = function(r, e, t) {
2526
+ }, E = function(r, e) {
2527
+ var t = he(), n = "navigate";
2528
+ return Ge >= 0 ? n = "back-forward-cache" : t && (document.prerendering || B() > 0 ? n = "prerender" : document.wasDiscarded ? n = "restore" : t.type && (n = t.type.replace(/_/g, "-"))), { name: r, value: e === void 0 ? -1 : e, rating: "good", delta: 0, entries: [], id: "v4-".concat(Date.now(), "-").concat(Math.floor(8999999999999 * Math.random()) + 1e12), navigationType: n };
2529
+ }, V = function(r, e, t) {
2564
2530
  try {
2565
2531
  if (PerformanceObserver.supportedEntryTypes.includes(r)) {
2566
2532
  var n = new PerformanceObserver(function(s) {
@@ -2572,200 +2538,200 @@ var ae, Ge = -1, R = function(r) {
2572
2538
  }
2573
2539
  } catch {
2574
2540
  }
2575
- }, E = function(r, e, t, n) {
2541
+ }, v = function(r, e, t, n) {
2576
2542
  var s, i;
2577
2543
  return function(o) {
2578
2544
  e.value >= 0 && (o || n) && ((i = e.value - (s || 0)) || s === void 0) && (s = e.value, e.delta = i, e.rating = function(c, l) {
2579
2545
  return c > l[1] ? "poor" : c > l[0] ? "needs-improvement" : "good";
2580
2546
  }(e.value, t), r(e));
2581
2547
  };
2582
- }, fe = function(r) {
2548
+ }, ge = function(r) {
2583
2549
  requestAnimationFrame(function() {
2584
2550
  return requestAnimationFrame(function() {
2585
2551
  return r();
2586
2552
  });
2587
2553
  });
2588
- }, Q = function(r) {
2554
+ }, W = function(r) {
2589
2555
  document.addEventListener("visibilitychange", function() {
2590
2556
  document.visibilityState === "hidden" && r();
2591
2557
  });
2592
- }, me = function(r) {
2558
+ }, fe = function(r) {
2593
2559
  var e = !1;
2594
2560
  return function() {
2595
2561
  e || (r(), e = !0);
2596
2562
  };
2597
- }, M = -1, Oe = function() {
2563
+ }, b = -1, De = function() {
2598
2564
  return document.visibilityState !== "hidden" || document.prerendering ? 1 / 0 : 0;
2599
- }, j = function(r) {
2600
- document.visibilityState === "hidden" && M > -1 && (M = r.type === "visibilitychange" ? r.timeStamp : 0, cr());
2601
- }, De = function() {
2602
- addEventListener("visibilitychange", j, !0), addEventListener("prerenderingchange", j, !0);
2603
- }, cr = function() {
2604
- removeEventListener("visibilitychange", j, !0), removeEventListener("prerenderingchange", j, !0);
2565
+ }, Q = function(r) {
2566
+ document.visibilityState === "hidden" && b > -1 && (b = r.type === "visibilitychange" ? r.timeStamp : 0, or());
2567
+ }, ke = function() {
2568
+ addEventListener("visibilitychange", Q, !0), addEventListener("prerenderingchange", Q, !0);
2569
+ }, or = function() {
2570
+ removeEventListener("visibilitychange", Q, !0), removeEventListener("prerenderingchange", Q, !0);
2605
2571
  }, je = function() {
2606
- return M < 0 && (M = Oe(), De(), R(function() {
2572
+ return b < 0 && (b = De(), ke(), R(function() {
2607
2573
  setTimeout(function() {
2608
- M = Oe(), De();
2574
+ b = De(), ke();
2609
2575
  }, 0);
2610
2576
  })), { get firstHiddenTime() {
2611
- return M;
2577
+ return b;
2612
2578
  } };
2613
- }, W = function(r) {
2579
+ }, Y = function(r) {
2614
2580
  document.prerendering ? addEventListener("prerenderingchange", function() {
2615
2581
  return r();
2616
2582
  }, !0) : r();
2617
2583
  }, oe = [1800, 3e3], $e = function(r, e) {
2618
- e = e || {}, W(function() {
2619
- var t, n = je(), s = S("FCP"), i = D("paint", function(o) {
2584
+ e = e || {}, Y(function() {
2585
+ var t, n = je(), s = E("FCP"), i = V("paint", function(o) {
2620
2586
  o.forEach(function(c) {
2621
- c.name === "first-contentful-paint" && (i.disconnect(), c.startTime < n.firstHiddenTime && (s.value = Math.max(c.startTime - $(), 0), s.entries.push(c), t(!0)));
2587
+ c.name === "first-contentful-paint" && (i.disconnect(), c.startTime < n.firstHiddenTime && (s.value = Math.max(c.startTime - B(), 0), s.entries.push(c), t(!0)));
2622
2588
  });
2623
2589
  });
2624
- i && (t = E(r, s, oe, e.reportAllChanges), R(function(o) {
2625
- s = S("FCP"), t = E(r, s, oe, e.reportAllChanges), fe(function() {
2590
+ i && (t = v(r, s, oe, e.reportAllChanges), R(function(o) {
2591
+ s = E("FCP"), t = v(r, s, oe, e.reportAllChanges), ge(function() {
2626
2592
  s.value = performance.now() - o.timeStamp, t(!0);
2627
2593
  });
2628
2594
  }));
2629
2595
  });
2630
- }, le = [0.1, 0.25], ur = function(r, e) {
2631
- e = e || {}, $e(me(function() {
2632
- var t, n = S("CLS", 0), s = 0, i = [], o = function(l) {
2596
+ }, le = [0.1, 0.25], lr = function(r, e) {
2597
+ e = e || {}, $e(fe(function() {
2598
+ var t, n = E("CLS", 0), s = 0, i = [], o = function(l) {
2633
2599
  l.forEach(function(u) {
2634
2600
  if (!u.hadRecentInput) {
2635
2601
  var h = i[0], L = i[i.length - 1];
2636
2602
  s && u.startTime - L.startTime < 1e3 && u.startTime - h.startTime < 5e3 ? (s += u.value, i.push(u)) : (s = u.value, i = [u]);
2637
2603
  }
2638
2604
  }), s > n.value && (n.value = s, n.entries = i, t());
2639
- }, c = D("layout-shift", o);
2640
- c && (t = E(r, n, le, e.reportAllChanges), Q(function() {
2605
+ }, c = V("layout-shift", o);
2606
+ c && (t = v(r, n, le, e.reportAllChanges), W(function() {
2641
2607
  o(c.takeRecords()), t(!0);
2642
2608
  }), R(function() {
2643
- s = 0, n = S("CLS", 0), t = E(r, n, le, e.reportAllChanges), fe(function() {
2609
+ s = 0, n = E("CLS", 0), t = v(r, n, le, e.reportAllChanges), ge(function() {
2644
2610
  return t();
2645
2611
  });
2646
2612
  }), setTimeout(t, 0));
2647
2613
  }));
2648
- }, Qe = 0, J = 1 / 0, U = 0, dr = function(r) {
2614
+ }, Qe = 0, Z = 1 / 0, z = 0, cr = function(r) {
2649
2615
  r.forEach(function(e) {
2650
- e.interactionId && (J = Math.min(J, e.interactionId), U = Math.max(U, e.interactionId), Qe = U ? (U - J) / 7 + 1 : 0);
2616
+ e.interactionId && (Z = Math.min(Z, e.interactionId), z = Math.max(z, e.interactionId), Qe = z ? (z - Z) / 7 + 1 : 0);
2651
2617
  });
2652
- }, We = function() {
2618
+ }, Be = function() {
2653
2619
  return ae ? Qe : performance.interactionCount || 0;
2654
- }, hr = function() {
2655
- "interactionCount" in performance || ae || (ae = D("event", dr, { type: "event", buffered: !0, durationThreshold: 0 }));
2656
- }, m = [], F = /* @__PURE__ */ new Map(), Be = 0, gr = function() {
2657
- var r = Math.min(m.length - 1, Math.floor((We() - Be) / 50));
2658
- return m[r];
2659
- }, fr = [], mr = function(r) {
2660
- if (fr.forEach(function(s) {
2620
+ }, ur = function() {
2621
+ "interactionCount" in performance || ae || (ae = V("event", cr, { type: "event", buffered: !0, durationThreshold: 0 }));
2622
+ }, S = [], $ = /* @__PURE__ */ new Map(), We = 0, dr = function() {
2623
+ var r = Math.min(S.length - 1, Math.floor((Be() - We) / 50));
2624
+ return S[r];
2625
+ }, hr = [], gr = function(r) {
2626
+ if (hr.forEach(function(s) {
2661
2627
  return s(r);
2662
2628
  }), r.interactionId || r.entryType === "first-input") {
2663
- var e = m[m.length - 1], t = F.get(r.interactionId);
2664
- if (t || m.length < 10 || r.duration > e.latency) {
2629
+ var e = S[S.length - 1], t = $.get(r.interactionId);
2630
+ if (t || S.length < 10 || r.duration > e.latency) {
2665
2631
  if (t) r.duration > t.latency ? (t.entries = [r], t.latency = r.duration) : r.duration === t.latency && r.startTime === t.entries[0].startTime && t.entries.push(r);
2666
2632
  else {
2667
2633
  var n = { id: r.interactionId, latency: r.duration, entries: [r] };
2668
- F.set(n.id, n), m.push(n);
2634
+ $.set(n.id, n), S.push(n);
2669
2635
  }
2670
- m.sort(function(s, i) {
2636
+ S.sort(function(s, i) {
2671
2637
  return i.latency - s.latency;
2672
- }), m.length > 10 && m.splice(10).forEach(function(s) {
2673
- return F.delete(s.id);
2638
+ }), S.length > 10 && S.splice(10).forEach(function(s) {
2639
+ return $.delete(s.id);
2674
2640
  });
2675
2641
  }
2676
2642
  }
2677
2643
  }, Ye = function(r) {
2678
2644
  var e = self.requestIdleCallback || self.setTimeout, t = -1;
2679
- return r = me(r), document.visibilityState === "hidden" ? r() : (t = e(r), Q(r)), t;
2680
- }, ce = [200, 500], pr = function(r, e) {
2681
- "PerformanceEventTiming" in self && "interactionId" in PerformanceEventTiming.prototype && (e = e || {}, W(function() {
2645
+ return r = fe(r), document.visibilityState === "hidden" ? r() : (t = e(r), W(r)), t;
2646
+ }, ce = [200, 500], fr = function(r, e) {
2647
+ "PerformanceEventTiming" in self && "interactionId" in PerformanceEventTiming.prototype && (e = e || {}, Y(function() {
2682
2648
  var t;
2683
- hr();
2684
- var n, s = S("INP"), i = function(c) {
2649
+ ur();
2650
+ var n, s = E("INP"), i = function(c) {
2685
2651
  Ye(function() {
2686
- c.forEach(mr);
2687
- var l = gr();
2652
+ c.forEach(gr);
2653
+ var l = dr();
2688
2654
  l && l.latency !== s.value && (s.value = l.latency, s.entries = l.entries, n());
2689
2655
  });
2690
- }, o = D("event", i, { durationThreshold: (t = e.durationThreshold) !== null && t !== void 0 ? t : 40 });
2691
- n = E(r, s, ce, e.reportAllChanges), o && (o.observe({ type: "first-input", buffered: !0 }), Q(function() {
2656
+ }, o = V("event", i, { durationThreshold: (t = e.durationThreshold) !== null && t !== void 0 ? t : 40 });
2657
+ n = v(r, s, ce, e.reportAllChanges), o && (o.observe({ type: "first-input", buffered: !0 }), W(function() {
2692
2658
  i(o.takeRecords()), n(!0);
2693
2659
  }), R(function() {
2694
- Be = We(), m.length = 0, F.clear(), s = S("INP"), n = E(r, s, ce, e.reportAllChanges);
2660
+ We = Be(), S.length = 0, $.clear(), s = E("INP"), n = v(r, s, ce, e.reportAllChanges);
2695
2661
  }));
2696
2662
  }));
2697
- }, ue = [2500, 4e3], Z = {}, Sr = function(r, e) {
2698
- e = e || {}, W(function() {
2699
- var t, n = je(), s = S("LCP"), i = function(l) {
2663
+ }, ue = [2500, 4e3], ee = {}, mr = function(r, e) {
2664
+ e = e || {}, Y(function() {
2665
+ var t, n = je(), s = E("LCP"), i = function(l) {
2700
2666
  e.reportAllChanges || (l = l.slice(-1)), l.forEach(function(u) {
2701
- u.startTime < n.firstHiddenTime && (s.value = Math.max(u.startTime - $(), 0), s.entries = [u], t());
2667
+ u.startTime < n.firstHiddenTime && (s.value = Math.max(u.startTime - B(), 0), s.entries = [u], t());
2702
2668
  });
2703
- }, o = D("largest-contentful-paint", i);
2669
+ }, o = V("largest-contentful-paint", i);
2704
2670
  if (o) {
2705
- t = E(r, s, ue, e.reportAllChanges);
2706
- var c = me(function() {
2707
- Z[s.id] || (i(o.takeRecords()), o.disconnect(), Z[s.id] = !0, t(!0));
2671
+ t = v(r, s, ue, e.reportAllChanges);
2672
+ var c = fe(function() {
2673
+ ee[s.id] || (i(o.takeRecords()), o.disconnect(), ee[s.id] = !0, t(!0));
2708
2674
  });
2709
2675
  ["keydown", "click"].forEach(function(l) {
2710
2676
  addEventListener(l, function() {
2711
2677
  return Ye(c);
2712
2678
  }, { once: !0, capture: !0 });
2713
- }), Q(c), R(function(l) {
2714
- s = S("LCP"), t = E(r, s, ue, e.reportAllChanges), fe(function() {
2715
- s.value = performance.now() - l.timeStamp, Z[s.id] = !0, t(!0);
2679
+ }), W(c), R(function(l) {
2680
+ s = E("LCP"), t = v(r, s, ue, e.reportAllChanges), ge(function() {
2681
+ s.value = performance.now() - l.timeStamp, ee[s.id] = !0, t(!0);
2716
2682
  });
2717
2683
  });
2718
2684
  }
2719
2685
  });
2720
- }, de = [800, 1800], Er = function r(e) {
2721
- document.prerendering ? W(function() {
2686
+ }, de = [800, 1800], pr = function r(e) {
2687
+ document.prerendering ? Y(function() {
2722
2688
  return r(e);
2723
2689
  }) : document.readyState !== "complete" ? addEventListener("load", function() {
2724
2690
  return r(e);
2725
2691
  }, !0) : setTimeout(e, 0);
2726
- }, vr = function(r, e) {
2692
+ }, Sr = function(r, e) {
2727
2693
  e = e || {};
2728
- var t = S("TTFB"), n = E(r, t, de, e.reportAllChanges);
2729
- Er(function() {
2730
- var s = ge();
2731
- s && (t.value = Math.max(s.responseStart - $(), 0), t.entries = [s], n(!0), R(function() {
2732
- t = S("TTFB", 0), (n = E(r, t, de, e.reportAllChanges))(!0);
2694
+ var t = E("TTFB"), n = v(r, t, de, e.reportAllChanges);
2695
+ pr(function() {
2696
+ var s = he();
2697
+ s && (t.value = Math.max(s.responseStart - B(), 0), t.entries = [s], n(!0), R(function() {
2698
+ t = E("TTFB", 0), (n = v(r, t, de, e.reportAllChanges))(!0);
2733
2699
  }));
2734
2700
  });
2735
2701
  };
2736
- const yr = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2702
+ const Er = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2737
2703
  __proto__: null,
2738
2704
  CLSThresholds: le,
2739
2705
  FCPThresholds: oe,
2740
2706
  INPThresholds: ce,
2741
2707
  LCPThresholds: ue,
2742
2708
  TTFBThresholds: de,
2743
- onCLS: ur,
2709
+ onCLS: lr,
2744
2710
  onFCP: $e,
2745
- onINP: pr,
2746
- onLCP: Sr,
2747
- onTTFB: vr
2711
+ onINP: fr,
2712
+ onLCP: mr,
2713
+ onTTFB: Sr
2748
2714
  }, Symbol.toStringTag, { value: "Module" }));
2749
2715
  export {
2750
- Nr as ANALYTICS_QUERY_LIMITS,
2751
- Cr as ANOMALY_DETECTION,
2752
- br as CONTENT_ANALYTICS,
2753
- Ir as DATA_PROTECTION,
2754
- Ar as DEVICE_ANALYTICS,
2755
- y as DeviceType,
2756
- _r as ENGAGEMENT_THRESHOLDS,
2757
- N as ErrorType,
2716
+ Rr as ANALYTICS_QUERY_LIMITS,
2717
+ Lr as ANOMALY_DETECTION,
2718
+ wr as CONTENT_ANALYTICS,
2719
+ yr as DATA_PROTECTION,
2720
+ _r as DEVICE_ANALYTICS,
2721
+ I as DeviceType,
2722
+ Ir as ENGAGEMENT_THRESHOLDS,
2723
+ C as ErrorType,
2758
2724
  d as EventType,
2759
- Mr as INSIGHT_THRESHOLDS,
2760
- H as Mode,
2761
- Tr as PERFORMANCE_CONFIG,
2762
- Lr as SEGMENTATION_ANALYTICS,
2763
- wr as SESSION_ANALYTICS,
2764
- Pr as SPECIAL_PAGE_URLS,
2765
- x as ScrollDirection,
2766
- Rr as TEMPORAL_ANALYSIS,
2767
- Tt as TagConditionOperator,
2725
+ Ar as INSIGHT_THRESHOLDS,
2726
+ O as Mode,
2727
+ vr as PERFORMANCE_CONFIG,
2728
+ Mr as SEGMENTATION_ANALYTICS,
2729
+ Tr as SESSION_ANALYTICS,
2730
+ Nr as SPECIAL_PAGE_URLS,
2731
+ j as ScrollDirection,
2732
+ br as TEMPORAL_ANALYSIS,
2733
+ It as TagConditionOperator,
2768
2734
  yt as TagConditionType,
2769
2735
  vt as TagLogicalOperator,
2770
- Or as tracelog
2736
+ Cr as tracelog
2771
2737
  };