@tracelog/lib 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/tracelog.js +458 -445
- package/dist/cjs/constants/api.constants.d.ts +0 -1
- package/dist/cjs/constants/api.constants.js +1 -2
- package/dist/cjs/managers/sender.manager.js +22 -5
- package/dist/esm/constants/api.constants.d.ts +0 -1
- package/dist/esm/constants/api.constants.js +0 -1
- package/dist/esm/managers/sender.manager.js +23 -6
- package/package.json +1 -1
package/dist/browser/tracelog.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var E = /* @__PURE__ */ ((
|
|
1
|
+
var E = /* @__PURE__ */ ((r) => (r.Mobile = "mobile", r.Tablet = "tablet", r.Desktop = "desktop", r.Unknown = "unknown", r))(E || {});
|
|
2
2
|
const q = {};
|
|
3
3
|
class p {
|
|
4
4
|
get(e) {
|
|
@@ -98,16 +98,16 @@ class Re extends p {
|
|
|
98
98
|
return "log";
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
logMessage(e, t, s,
|
|
101
|
+
logMessage(e, t, s, n) {
|
|
102
102
|
if (!this.shouldShowLog(e))
|
|
103
103
|
return;
|
|
104
104
|
const a = this.formatMessage(t, s), o = this.getConsoleMethod(e);
|
|
105
|
-
|
|
105
|
+
n !== void 0 ? console[o](a, n) : console[o](a);
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
108
|
* Dispatches tracelog:log events for E2E testing and development debugging
|
|
109
109
|
*/
|
|
110
|
-
dispatchEvent(e, t, s,
|
|
110
|
+
dispatchEvent(e, t, s, n) {
|
|
111
111
|
if (!(typeof window > "u" || typeof CustomEvent > "u"))
|
|
112
112
|
try {
|
|
113
113
|
const a = new CustomEvent("tracelog:log", {
|
|
@@ -116,12 +116,12 @@ class Re extends p {
|
|
|
116
116
|
level: e,
|
|
117
117
|
namespace: t,
|
|
118
118
|
message: s,
|
|
119
|
-
data:
|
|
119
|
+
data: n
|
|
120
120
|
}
|
|
121
121
|
});
|
|
122
122
|
window.dispatchEvent(a);
|
|
123
123
|
} catch {
|
|
124
|
-
console.log(`[TraceLog:${t}] ${s}`,
|
|
124
|
+
console.log(`[TraceLog:${t}] ${s}`, n);
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
}
|
|
@@ -132,39 +132,39 @@ const ke = () => {
|
|
|
132
132
|
}, we = () => {
|
|
133
133
|
try {
|
|
134
134
|
i.debug("DeviceDetector", "Starting device detection");
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
135
|
+
const r = navigator;
|
|
136
|
+
if (r.userAgentData && typeof r.userAgentData.mobile == "boolean") {
|
|
137
137
|
if (i.debug("DeviceDetector", "Using modern User-Agent Client Hints API", {
|
|
138
|
-
mobile:
|
|
139
|
-
platform:
|
|
140
|
-
}),
|
|
138
|
+
mobile: r.userAgentData.mobile,
|
|
139
|
+
platform: r.userAgentData.platform
|
|
140
|
+
}), r.userAgentData.platform && /ipad|tablet/i.test(r.userAgentData.platform))
|
|
141
141
|
return i.debug("DeviceDetector", "Device detected as tablet via platform hint"), E.Tablet;
|
|
142
|
-
const d =
|
|
142
|
+
const d = r.userAgentData.mobile ? E.Mobile : E.Desktop;
|
|
143
143
|
return i.debug("DeviceDetector", "Device detected via User-Agent hints", { result: d }), d;
|
|
144
144
|
}
|
|
145
145
|
i.debug("DeviceDetector", "Using fallback detection methods"), ke();
|
|
146
|
-
const e = window.innerWidth, t = J?.matches ?? !1, s = Ee?.matches ?? !1,
|
|
146
|
+
const e = window.innerWidth, t = J?.matches ?? !1, s = Ee?.matches ?? !1, n = "ontouchstart" in window || navigator.maxTouchPoints > 0, a = navigator.userAgent.toLowerCase(), o = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(a), l = /tablet|ipad|android(?!.*mobile)/.test(a), c = {
|
|
147
147
|
width: e,
|
|
148
148
|
hasCoarsePointer: t,
|
|
149
149
|
hasNoHover: s,
|
|
150
|
-
hasTouchSupport:
|
|
150
|
+
hasTouchSupport: n,
|
|
151
151
|
isMobileUA: o,
|
|
152
152
|
isTabletUA: l,
|
|
153
153
|
maxTouchPoints: navigator.maxTouchPoints
|
|
154
154
|
};
|
|
155
|
-
return e <= 767 || o &&
|
|
156
|
-
} catch (
|
|
155
|
+
return e <= 767 || o && n ? (i.debug("DeviceDetector", "Device detected as mobile", c), E.Mobile) : e >= 768 && e <= 1024 || l || t && s && n ? (i.debug("DeviceDetector", "Device detected as tablet", c), E.Tablet) : (i.debug("DeviceDetector", "Device detected as desktop", c), E.Desktop);
|
|
156
|
+
} catch (r) {
|
|
157
157
|
return i.warn("DeviceDetector", "Device detection failed, defaulting to desktop", {
|
|
158
|
-
error:
|
|
158
|
+
error: r instanceof Error ? r.message : r
|
|
159
159
|
}), E.Desktop;
|
|
160
160
|
}
|
|
161
|
-
}, Ne = 2, Ue = 10, Ie = 1, ne = 500, Z = 3e4, ee = 864e5, re = 120, ae = 8 * 1024, oe = 10, ce = 10, _ = 255, M = 1e3, W = 100, le = 3, N = 2, Pe = 4, He = 0.75, De = 0.2, xe = 2e3, Oe = 1e3, Fe = 10, F = 10, R = 15 * 60 * 1e3, ze = 3e4, Te = 1e3, Me = 250, Ve = 2e3, de = 1e3, $e = 1e4, je = 2500, he = 1e3, ue = 3e4, ge = 1e3, Ge = 24, Qe = 24 * 60 * 60 * 1e3, Be = Te, qe = 5e3, We = 2e3, Xe = 2, Ke = 3, X = 24 * 60 * 60 * 1e3, K = 2 * 60 * 1e3,
|
|
161
|
+
}, Ne = 2, Ue = 10, Ie = 1, ne = 500, Z = 3e4, ee = 864e5, re = 120, ae = 8 * 1024, oe = 10, ce = 10, _ = 255, M = 1e3, W = 100, le = 3, N = 2, Pe = 4, He = 0.75, De = 0.2, xe = 2e3, Oe = 1e3, Fe = 10, F = 10, R = 15 * 60 * 1e3, ze = 3e4, Te = 1e3, Me = 250, Ve = 2e3, de = 1e3, $e = 1e4, je = 2500, he = 1e3, ue = 3e4, ge = 1e3, Ge = 24, Qe = 24 * 60 * 60 * 1e3, Be = Te, qe = 5e3, We = 2e3, Xe = 2, Ke = 3, X = 24 * 60 * 60 * 1e3, K = 2 * 60 * 1e3, Ae = {
|
|
162
162
|
samplingRate: Ie,
|
|
163
163
|
tags: [],
|
|
164
164
|
excludedUrlPaths: []
|
|
165
|
-
},
|
|
165
|
+
}, Ye = (r) => ({
|
|
166
166
|
...Ae,
|
|
167
|
-
...
|
|
167
|
+
...r,
|
|
168
168
|
sessionTimeout: R,
|
|
169
169
|
allowHttp: !1
|
|
170
170
|
}), z = "data-tl", fe = [
|
|
@@ -199,7 +199,7 @@ const ke = () => {
|
|
|
199
199
|
".menu-item",
|
|
200
200
|
"[data-testid]",
|
|
201
201
|
'[tabindex="0"]'
|
|
202
|
-
],
|
|
202
|
+
], Je = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"], me = {
|
|
203
203
|
/** Maximum number of retries when waiting for concurrent initialization */
|
|
204
204
|
MAX_CONCURRENT_RETRIES: 20,
|
|
205
205
|
/** Delay between retries when waiting for concurrent initialization (ms) */
|
|
@@ -223,7 +223,7 @@ const ke = () => {
|
|
|
223
223
|
SYNC_TIMEOUT_MS: 2e3,
|
|
224
224
|
/** Maximum retry attempts for session operations */
|
|
225
225
|
MAX_RETRY_ATTEMPTS: 3
|
|
226
|
-
},
|
|
226
|
+
}, Ze = {
|
|
227
227
|
/** Multiplier for scroll debounce time when suppressing scroll events */
|
|
228
228
|
SUPPRESS_MULTIPLIER: 2
|
|
229
229
|
}, _e = [
|
|
@@ -233,7 +233,7 @@ const ke = () => {
|
|
|
233
233
|
/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,
|
|
234
234
|
/<embed\b[^>]*>/gi,
|
|
235
235
|
/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi
|
|
236
|
-
], S = "tl", ve = (
|
|
236
|
+
], S = "tl", ve = (r) => r ? `${S}:${r}:uid` : `${S}:uid`, et = (r) => r ? `${S}:${r}:queue` : `${S}:queue`, tt = (r) => r ? `${S}:${r}:session` : `${S}:session`, Y = (r) => r ? `${S}:${r}:cross_tab_session` : `${S}:cross_tab_session`, Se = (r, e) => `${S}:${r}:tab:${e}:info`, V = (r) => r ? `${S}:${r}:recovery` : `${S}:recovery`, st = (r) => r ? `${S}:${r}:broadcast` : `${S}:broadcast`, it = /* @__PURE__ */ new Set([
|
|
237
237
|
"mode",
|
|
238
238
|
"tags",
|
|
239
239
|
"samplingRate",
|
|
@@ -254,17 +254,17 @@ const ke = () => {
|
|
|
254
254
|
INVALID_GLOBAL_METADATA: "Global metadata must be an object",
|
|
255
255
|
// Array validation
|
|
256
256
|
INVALID_SENSITIVE_QUERY_PARAMS: "Sensitive query params must be an array of strings"
|
|
257
|
-
},
|
|
257
|
+
}, nt = () => {
|
|
258
258
|
i.debug("UTMParams", "Extracting UTM parameters from URL", {
|
|
259
259
|
url: window.location.href,
|
|
260
260
|
search: window.location.search
|
|
261
261
|
});
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
if (
|
|
262
|
+
const r = new URLSearchParams(window.location.search), e = {};
|
|
263
|
+
Je.forEach((s) => {
|
|
264
|
+
const n = r.get(s);
|
|
265
|
+
if (n) {
|
|
266
266
|
const a = s.split("utm_")[1];
|
|
267
|
-
e[a] =
|
|
267
|
+
e[a] = n, i.debug("UTMParams", "Found UTM parameter", { param: s, key: a, value: n });
|
|
268
268
|
}
|
|
269
269
|
});
|
|
270
270
|
const t = Object.keys(e).length ? e : void 0;
|
|
@@ -273,13 +273,13 @@ const ke = () => {
|
|
|
273
273
|
parameters: Object.keys(t)
|
|
274
274
|
}) : i.debug("UTMParams", "No UTM parameters found in URL"), t;
|
|
275
275
|
}, $ = () => {
|
|
276
|
-
const
|
|
276
|
+
const r = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (e) => {
|
|
277
277
|
const t = Math.random() * 16 | 0;
|
|
278
278
|
return (e === "x" ? t : t & 3 | 8).toString(16);
|
|
279
279
|
});
|
|
280
|
-
return i.verbose("UUIDUtils", "Generated new UUID", { uuid:
|
|
280
|
+
return i.verbose("UUIDUtils", "Generated new UUID", { uuid: r }), r;
|
|
281
281
|
};
|
|
282
|
-
var C = /* @__PURE__ */ ((
|
|
282
|
+
var C = /* @__PURE__ */ ((r) => (r.HttpSkip = "http-skip", r.HttpLocal = "http-local", r))(C || {}), h = /* @__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))(h || {}), j = /* @__PURE__ */ ((r) => (r.UP = "up", r.DOWN = "down", r))(j || {}), D = /* @__PURE__ */ ((r) => (r.JS_ERROR = "js_error", r.PROMISE_REJECTION = "promise_rejection", r.NETWORK_ERROR = "network_error", r))(D || {}), L = /* @__PURE__ */ ((r) => (r.QA = "qa", r.DEBUG = "debug", r))(L || {}), G = /* @__PURE__ */ ((r) => (r.AND = "AND", r.OR = "OR", r))(G || {}), m = /* @__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))(m || {}), f = /* @__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))(f || {});
|
|
283
283
|
class x extends Error {
|
|
284
284
|
constructor(e, t, s) {
|
|
285
285
|
super(e), this.errorCode = t, this.layer = s, this.name = this.constructor.name, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
|
|
@@ -295,12 +295,12 @@ class H extends x {
|
|
|
295
295
|
super(e, "APP_CONFIG_INVALID", t);
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
|
-
class
|
|
298
|
+
class rt extends x {
|
|
299
299
|
constructor(e, t = "config") {
|
|
300
300
|
super(e, "SESSION_TIMEOUT_INVALID", t);
|
|
301
301
|
}
|
|
302
302
|
}
|
|
303
|
-
class
|
|
303
|
+
class at extends x {
|
|
304
304
|
constructor(e, t = "config") {
|
|
305
305
|
super(e, "SAMPLING_RATE_INVALID", t);
|
|
306
306
|
}
|
|
@@ -310,47 +310,47 @@ class ye extends x {
|
|
|
310
310
|
super(e, "INTEGRATION_INVALID", t);
|
|
311
311
|
}
|
|
312
312
|
}
|
|
313
|
-
const
|
|
314
|
-
if (!
|
|
315
|
-
throw i.clientError("ConfigValidation", "Configuration must be an object", { config:
|
|
316
|
-
if (!("id" in
|
|
313
|
+
const ot = (r) => {
|
|
314
|
+
if (!r || typeof r != "object")
|
|
315
|
+
throw i.clientError("ConfigValidation", "Configuration must be an object", { config: r }), new H("Configuration must be an object", "config");
|
|
316
|
+
if (!("id" in r))
|
|
317
317
|
throw i.clientError("ConfigValidation", "Project ID is missing from configuration"), new Q(w.MISSING_PROJECT_ID, "config");
|
|
318
|
-
if (
|
|
318
|
+
if (r.id === null || r.id === void 0 || typeof r.id != "string")
|
|
319
319
|
throw i.clientError("ConfigValidation", "Project ID must be a non-empty string", {
|
|
320
|
-
providedId:
|
|
321
|
-
type: typeof
|
|
320
|
+
providedId: r.id,
|
|
321
|
+
type: typeof r.id
|
|
322
322
|
}), new Q(w.MISSING_PROJECT_ID, "config");
|
|
323
|
-
if (
|
|
323
|
+
if (r.sessionTimeout !== void 0 && (typeof r.sessionTimeout != "number" || r.sessionTimeout < Z || r.sessionTimeout > ee))
|
|
324
324
|
throw i.clientError("ConfigValidation", "Invalid session timeout", {
|
|
325
|
-
provided:
|
|
325
|
+
provided: r.sessionTimeout,
|
|
326
326
|
min: Z,
|
|
327
327
|
max: ee
|
|
328
|
-
}), new
|
|
329
|
-
if (
|
|
328
|
+
}), new rt(w.INVALID_SESSION_TIMEOUT, "config");
|
|
329
|
+
if (r.globalMetadata !== void 0 && (typeof r.globalMetadata != "object" || r.globalMetadata === null))
|
|
330
330
|
throw i.clientError("ConfigValidation", "Global metadata must be an object", {
|
|
331
|
-
provided:
|
|
332
|
-
type: typeof
|
|
331
|
+
provided: r.globalMetadata,
|
|
332
|
+
type: typeof r.globalMetadata
|
|
333
333
|
}), new H(w.INVALID_GLOBAL_METADATA, "config");
|
|
334
|
-
if (
|
|
335
|
-
if (!Array.isArray(
|
|
334
|
+
if (r.scrollContainerSelectors !== void 0 && ct(r.scrollContainerSelectors), r.integrations && lt(r.integrations), r.sensitiveQueryParams !== void 0) {
|
|
335
|
+
if (!Array.isArray(r.sensitiveQueryParams))
|
|
336
336
|
throw i.clientError("ConfigValidation", "Sensitive query params must be an array", {
|
|
337
|
-
provided:
|
|
338
|
-
type: typeof
|
|
337
|
+
provided: r.sensitiveQueryParams,
|
|
338
|
+
type: typeof r.sensitiveQueryParams
|
|
339
339
|
}), new H(w.INVALID_SENSITIVE_QUERY_PARAMS, "config");
|
|
340
|
-
for (const e of
|
|
340
|
+
for (const e of r.sensitiveQueryParams)
|
|
341
341
|
if (typeof e != "string")
|
|
342
342
|
throw i.clientError("ConfigValidation", "All sensitive query params must be strings", {
|
|
343
343
|
param: e,
|
|
344
344
|
type: typeof e
|
|
345
345
|
}), new H("All sensitive query params must be strings", "config");
|
|
346
346
|
}
|
|
347
|
-
if (
|
|
347
|
+
if (r.errorSampling !== void 0 && (typeof r.errorSampling != "number" || r.errorSampling < 0 || r.errorSampling > 1))
|
|
348
348
|
throw i.clientError("ConfigValidation", "Invalid error sampling rate", {
|
|
349
|
-
provided:
|
|
349
|
+
provided: r.errorSampling,
|
|
350
350
|
expected: "0-1"
|
|
351
|
-
}), new
|
|
352
|
-
},
|
|
353
|
-
const e = Array.isArray(
|
|
351
|
+
}), new at(w.INVALID_ERROR_SAMPLING_RATE, "config");
|
|
352
|
+
}, ct = (r) => {
|
|
353
|
+
const e = Array.isArray(r) ? r : [r];
|
|
354
354
|
for (const t of e) {
|
|
355
355
|
if (typeof t != "string" || t.trim() === "")
|
|
356
356
|
throw i.clientError("ConfigValidation", "Invalid scroll container selector", {
|
|
@@ -365,39 +365,39 @@ const ct = (n) => {
|
|
|
365
365
|
i.clientWarn("ConfigValidation", `Invalid CSS selector will be ignored: "${t}"`);
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
|
-
},
|
|
369
|
-
if (
|
|
370
|
-
if (!
|
|
368
|
+
}, lt = (r) => {
|
|
369
|
+
if (r && r.googleAnalytics) {
|
|
370
|
+
if (!r.googleAnalytics.measurementId || typeof r.googleAnalytics.measurementId != "string" || r.googleAnalytics.measurementId.trim() === "")
|
|
371
371
|
throw i.clientError("ConfigValidation", "Invalid Google Analytics measurement ID", {
|
|
372
|
-
provided:
|
|
373
|
-
type: typeof
|
|
372
|
+
provided: r.googleAnalytics.measurementId,
|
|
373
|
+
type: typeof r.googleAnalytics.measurementId
|
|
374
374
|
}), new ye(w.INVALID_GOOGLE_ANALYTICS_ID, "config");
|
|
375
|
-
const e =
|
|
375
|
+
const e = r.googleAnalytics.measurementId.trim();
|
|
376
376
|
if (!e.match(/^(G-|UA-)/))
|
|
377
377
|
throw i.clientError("ConfigValidation", 'Google Analytics measurement ID must start with "G-" or "UA-"', {
|
|
378
378
|
provided: e
|
|
379
379
|
}), new ye('Google Analytics measurement ID must start with "G-" or "UA-"', "config");
|
|
380
380
|
}
|
|
381
|
-
},
|
|
382
|
-
|
|
381
|
+
}, dt = (r) => {
|
|
382
|
+
ot(r);
|
|
383
383
|
const e = {
|
|
384
|
-
...
|
|
385
|
-
id:
|
|
386
|
-
globalMetadata:
|
|
387
|
-
sensitiveQueryParams:
|
|
384
|
+
...r,
|
|
385
|
+
id: r.id.trim(),
|
|
386
|
+
globalMetadata: r.globalMetadata ?? {},
|
|
387
|
+
sensitiveQueryParams: r.sensitiveQueryParams ?? []
|
|
388
388
|
};
|
|
389
389
|
if (!e.id)
|
|
390
390
|
throw i.clientError("ConfigValidation", "Project ID is empty after trimming whitespace", {
|
|
391
|
-
originalId:
|
|
391
|
+
originalId: r.id,
|
|
392
392
|
normalizedId: e.id
|
|
393
393
|
}), new Q(w.PROJECT_ID_EMPTY_AFTER_TRIM, "config");
|
|
394
394
|
return e;
|
|
395
|
-
}, be = (
|
|
396
|
-
if (!
|
|
397
|
-
return i.debug("Sanitize", "String sanitization skipped - empty or invalid input", { value:
|
|
398
|
-
const e =
|
|
399
|
-
let t =
|
|
400
|
-
|
|
395
|
+
}, be = (r) => {
|
|
396
|
+
if (!r || typeof r != "string" || r.trim().length === 0)
|
|
397
|
+
return i.debug("Sanitize", "String sanitization skipped - empty or invalid input", { value: r, type: typeof r }), "";
|
|
398
|
+
const e = r.length;
|
|
399
|
+
let t = r;
|
|
400
|
+
r.length > M && (t = r.slice(0, Math.max(0, M)), i.warn("Sanitize", "String truncated due to length limit", {
|
|
401
401
|
originalLength: e,
|
|
402
402
|
maxLength: M,
|
|
403
403
|
truncatedLength: t.length
|
|
@@ -409,52 +409,52 @@ const ct = (n) => {
|
|
|
409
409
|
}
|
|
410
410
|
s > 0 && i.warn("Sanitize", "XSS patterns detected and removed", {
|
|
411
411
|
patternMatches: s,
|
|
412
|
-
originalValue:
|
|
412
|
+
originalValue: r.slice(0, 100)
|
|
413
413
|
// Log first 100 chars for debugging
|
|
414
414
|
}), t = t.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'").replaceAll("/", "/");
|
|
415
|
-
const
|
|
415
|
+
const n = t.trim();
|
|
416
416
|
return (e > 50 || s > 0) && i.debug("Sanitize", "String sanitization completed", {
|
|
417
417
|
originalLength: e,
|
|
418
|
-
sanitizedLength:
|
|
418
|
+
sanitizedLength: n.length,
|
|
419
419
|
xssPatternMatches: s,
|
|
420
420
|
wasTruncated: e > M
|
|
421
|
-
}),
|
|
422
|
-
},
|
|
423
|
-
if (typeof
|
|
421
|
+
}), n;
|
|
422
|
+
}, ht = (r) => {
|
|
423
|
+
if (typeof r != "string")
|
|
424
424
|
return "";
|
|
425
|
-
|
|
426
|
-
let e =
|
|
425
|
+
r.length > M && (r = r.slice(0, Math.max(0, M)));
|
|
426
|
+
let e = r;
|
|
427
427
|
for (const t of _e)
|
|
428
428
|
e = e.replace(t, "");
|
|
429
429
|
return e = e.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'"), e.trim();
|
|
430
|
-
}, B = (
|
|
430
|
+
}, B = (r, e = 0) => {
|
|
431
431
|
if (e > le)
|
|
432
432
|
return i.warn("Sanitize", "Maximum object depth exceeded during sanitization", {
|
|
433
433
|
depth: e,
|
|
434
434
|
maxDepth: le
|
|
435
435
|
}), null;
|
|
436
|
-
if (
|
|
436
|
+
if (r == null)
|
|
437
437
|
return null;
|
|
438
|
-
if (typeof
|
|
439
|
-
return be(
|
|
440
|
-
if (typeof
|
|
441
|
-
return !Number.isFinite(
|
|
442
|
-
if (typeof
|
|
443
|
-
return
|
|
444
|
-
if (Array.isArray(
|
|
445
|
-
const t =
|
|
438
|
+
if (typeof r == "string")
|
|
439
|
+
return be(r);
|
|
440
|
+
if (typeof r == "number")
|
|
441
|
+
return !Number.isFinite(r) || r < -Number.MAX_SAFE_INTEGER || r > Number.MAX_SAFE_INTEGER ? (i.warn("Sanitize", "Invalid number sanitized to 0", { value: r, isFinite: Number.isFinite(r) }), 0) : r;
|
|
442
|
+
if (typeof r == "boolean")
|
|
443
|
+
return r;
|
|
444
|
+
if (Array.isArray(r)) {
|
|
445
|
+
const t = r.length, s = r.slice(0, W);
|
|
446
446
|
t > W && i.warn("Sanitize", "Array truncated due to length limit", {
|
|
447
447
|
originalLength: t,
|
|
448
448
|
maxLength: W,
|
|
449
449
|
depth: e
|
|
450
450
|
});
|
|
451
|
-
const
|
|
452
|
-
return t > 0 &&
|
|
451
|
+
const n = s.map((a) => B(a, e + 1)).filter((a) => a !== null);
|
|
452
|
+
return t > 0 && n.length === 0 && i.warn("Sanitize", "All array items were filtered out during sanitization", { originalLength: t, depth: e }), n;
|
|
453
453
|
}
|
|
454
|
-
if (typeof
|
|
455
|
-
const t = {}, s = Object.entries(
|
|
456
|
-
|
|
457
|
-
originalKeys:
|
|
454
|
+
if (typeof r == "object") {
|
|
455
|
+
const t = {}, s = Object.entries(r), n = s.length, a = s.slice(0, 20);
|
|
456
|
+
n > 20 && i.warn("Sanitize", "Object keys truncated due to limit", {
|
|
457
|
+
originalKeys: n,
|
|
458
458
|
maxKeys: 20,
|
|
459
459
|
depth: e
|
|
460
460
|
});
|
|
@@ -473,21 +473,21 @@ const ct = (n) => {
|
|
|
473
473
|
depth: e
|
|
474
474
|
}), t;
|
|
475
475
|
}
|
|
476
|
-
return i.debug("Sanitize", "Unknown value type sanitized to null", { type: typeof
|
|
477
|
-
},
|
|
476
|
+
return i.debug("Sanitize", "Unknown value type sanitized to null", { type: typeof r, depth: e }), null;
|
|
477
|
+
}, ut = (r) => {
|
|
478
478
|
i.debug("Sanitize", "Starting API config sanitization");
|
|
479
479
|
const e = {};
|
|
480
|
-
if (typeof
|
|
481
|
-
return i.warn("Sanitize", "API config data is not an object", { data:
|
|
480
|
+
if (typeof r != "object" || r === null)
|
|
481
|
+
return i.warn("Sanitize", "API config data is not an object", { data: r, type: typeof r }), e;
|
|
482
482
|
try {
|
|
483
|
-
const t = Object.keys(
|
|
484
|
-
let s = 0,
|
|
483
|
+
const t = Object.keys(r);
|
|
484
|
+
let s = 0, n = 0;
|
|
485
485
|
for (const a of t)
|
|
486
|
-
if (
|
|
487
|
-
const o =
|
|
486
|
+
if (it.has(a)) {
|
|
487
|
+
const o = r[a];
|
|
488
488
|
if (a === "excludedUrlPaths") {
|
|
489
489
|
const l = Array.isArray(o) ? o : typeof o == "string" ? [o] : [], c = l.length;
|
|
490
|
-
e.excludedUrlPaths = l.map((u) =>
|
|
490
|
+
e.excludedUrlPaths = l.map((u) => ht(String(u))).filter(Boolean);
|
|
491
491
|
const d = c - e.excludedUrlPaths.length;
|
|
492
492
|
d > 0 && i.warn("Sanitize", "Some excluded URL paths were filtered during sanitization", {
|
|
493
493
|
originalCount: c,
|
|
@@ -501,11 +501,11 @@ const ct = (n) => {
|
|
|
501
501
|
}
|
|
502
502
|
s++;
|
|
503
503
|
} else
|
|
504
|
-
|
|
504
|
+
n++, i.debug("Sanitize", "API config key not allowed", { key: a });
|
|
505
505
|
i.info("Sanitize", "API config sanitization completed", {
|
|
506
506
|
originalKeys: t.length,
|
|
507
507
|
processedKeys: s,
|
|
508
|
-
filteredKeys:
|
|
508
|
+
filteredKeys: n,
|
|
509
509
|
finalKeys: Object.keys(e).length
|
|
510
510
|
});
|
|
511
511
|
} catch (t) {
|
|
@@ -514,28 +514,28 @@ const ct = (n) => {
|
|
|
514
514
|
}), new Error(`API config sanitization failed: ${t instanceof Error ? t.message : "Unknown error"}`);
|
|
515
515
|
}
|
|
516
516
|
return e;
|
|
517
|
-
},
|
|
518
|
-
if (i.debug("Sanitize", "Starting metadata sanitization", { hasMetadata:
|
|
517
|
+
}, gt = (r) => {
|
|
518
|
+
if (i.debug("Sanitize", "Starting metadata sanitization", { hasMetadata: r != null }), typeof r != "object" || r === null)
|
|
519
519
|
return i.debug("Sanitize", "Metadata is not an object, returning empty object", {
|
|
520
|
-
metadata:
|
|
521
|
-
type: typeof
|
|
520
|
+
metadata: r,
|
|
521
|
+
type: typeof r
|
|
522
522
|
}), {};
|
|
523
523
|
try {
|
|
524
|
-
const e = Object.keys(
|
|
524
|
+
const e = Object.keys(r).length, t = B(r), s = typeof t == "object" && t !== null ? t : {}, n = Object.keys(s).length;
|
|
525
525
|
return i.debug("Sanitize", "Metadata sanitization completed", {
|
|
526
526
|
originalKeys: e,
|
|
527
|
-
finalKeys:
|
|
528
|
-
keysFiltered: e -
|
|
527
|
+
finalKeys: n,
|
|
528
|
+
keysFiltered: e - n
|
|
529
529
|
}), s;
|
|
530
530
|
} catch (e) {
|
|
531
531
|
throw i.error("Sanitize", "Metadata sanitization failed", {
|
|
532
532
|
error: e instanceof Error ? e.message : e
|
|
533
533
|
}), new Error(`Metadata sanitization failed: ${e instanceof Error ? e.message : "Unknown error"}`);
|
|
534
534
|
}
|
|
535
|
-
},
|
|
536
|
-
if (typeof
|
|
535
|
+
}, ft = (r) => {
|
|
536
|
+
if (typeof r != "object" || r === null)
|
|
537
537
|
return !1;
|
|
538
|
-
for (const e of Object.values(
|
|
538
|
+
for (const e of Object.values(r)) {
|
|
539
539
|
if (e == null)
|
|
540
540
|
continue;
|
|
541
541
|
const t = typeof e;
|
|
@@ -549,27 +549,27 @@ const ct = (n) => {
|
|
|
549
549
|
}
|
|
550
550
|
}
|
|
551
551
|
return !0;
|
|
552
|
-
},
|
|
552
|
+
}, mt = (r) => typeof r != "string" ? {
|
|
553
553
|
valid: !1,
|
|
554
554
|
error: "Event name must be a string"
|
|
555
|
-
} :
|
|
555
|
+
} : r.length === 0 ? {
|
|
556
556
|
valid: !1,
|
|
557
557
|
error: "Event name cannot be empty"
|
|
558
|
-
} :
|
|
558
|
+
} : r.length > re ? {
|
|
559
559
|
valid: !1,
|
|
560
560
|
error: `Event name is too long (max ${re} characters)`
|
|
561
|
-
} :
|
|
561
|
+
} : r.includes("<") || r.includes(">") || r.includes("&") ? {
|
|
562
562
|
valid: !1,
|
|
563
563
|
error: "Event name contains invalid characters"
|
|
564
|
-
} : ["constructor", "prototype", "__proto__", "eval", "function", "var", "let", "const"].includes(
|
|
564
|
+
} : ["constructor", "prototype", "__proto__", "eval", "function", "var", "let", "const"].includes(r.toLowerCase()) ? {
|
|
565
565
|
valid: !1,
|
|
566
566
|
error: "Event name cannot be a reserved word"
|
|
567
|
-
} : { valid: !0 },
|
|
568
|
-
const s =
|
|
569
|
-
if (!
|
|
567
|
+
} : { valid: !0 }, pt = (r, e, t) => {
|
|
568
|
+
const s = gt(e), n = `${t} "${r}" metadata error`;
|
|
569
|
+
if (!ft(s))
|
|
570
570
|
return {
|
|
571
571
|
valid: !1,
|
|
572
|
-
error: `${
|
|
572
|
+
error: `${n}: object has invalid types. Valid types are string, number, boolean or string arrays.`
|
|
573
573
|
};
|
|
574
574
|
let a;
|
|
575
575
|
try {
|
|
@@ -577,71 +577,71 @@ const ct = (n) => {
|
|
|
577
577
|
} catch {
|
|
578
578
|
return {
|
|
579
579
|
valid: !1,
|
|
580
|
-
error: `${
|
|
580
|
+
error: `${n}: object contains circular references or cannot be serialized.`
|
|
581
581
|
};
|
|
582
582
|
}
|
|
583
583
|
if (a.length > ae)
|
|
584
584
|
return {
|
|
585
585
|
valid: !1,
|
|
586
|
-
error: `${
|
|
586
|
+
error: `${n}: object is too large (max ${ae / 1024} KB).`
|
|
587
587
|
};
|
|
588
588
|
if (Object.keys(s).length > oe)
|
|
589
589
|
return {
|
|
590
590
|
valid: !1,
|
|
591
|
-
error: `${
|
|
591
|
+
error: `${n}: object has too many keys (max ${oe} keys).`
|
|
592
592
|
};
|
|
593
593
|
for (const [l, c] of Object.entries(s)) {
|
|
594
594
|
if (Array.isArray(c)) {
|
|
595
595
|
if (c.length > ce)
|
|
596
596
|
return {
|
|
597
597
|
valid: !1,
|
|
598
|
-
error: `${
|
|
598
|
+
error: `${n}: array property "${l}" is too large (max ${ce} items).`
|
|
599
599
|
};
|
|
600
600
|
for (const d of c)
|
|
601
601
|
if (typeof d == "string" && d.length > 500)
|
|
602
602
|
return {
|
|
603
603
|
valid: !1,
|
|
604
|
-
error: `${
|
|
604
|
+
error: `${n}: array property "${l}" contains strings that are too long (max 500 characters).`
|
|
605
605
|
};
|
|
606
606
|
}
|
|
607
607
|
if (typeof c == "string" && c.length > M)
|
|
608
608
|
return {
|
|
609
609
|
valid: !1,
|
|
610
|
-
error: `${
|
|
610
|
+
error: `${n}: property "${l}" is too long (max ${M} characters).`
|
|
611
611
|
};
|
|
612
612
|
}
|
|
613
613
|
return {
|
|
614
614
|
valid: !0,
|
|
615
615
|
sanitizedMetadata: s
|
|
616
616
|
};
|
|
617
|
-
},
|
|
618
|
-
const t =
|
|
617
|
+
}, vt = (r, e) => {
|
|
618
|
+
const t = mt(r);
|
|
619
619
|
if (!t.valid)
|
|
620
|
-
return i.clientError("EventValidation", "Event name validation failed", { eventName:
|
|
620
|
+
return i.clientError("EventValidation", "Event name validation failed", { eventName: r, error: t.error }), t;
|
|
621
621
|
if (!e)
|
|
622
622
|
return { valid: !0 };
|
|
623
|
-
const s =
|
|
623
|
+
const s = pt(r, e, "customEvent");
|
|
624
624
|
return s.valid || i.clientError("EventValidation", "Event metadata validation failed", {
|
|
625
|
-
eventName:
|
|
625
|
+
eventName: r,
|
|
626
626
|
error: s.error
|
|
627
627
|
}), s;
|
|
628
|
-
}, te = (
|
|
628
|
+
}, te = (r, e = !1) => {
|
|
629
629
|
try {
|
|
630
|
-
const t = new URL(
|
|
631
|
-
return s || e &&
|
|
630
|
+
const t = new URL(r), s = t.protocol === "https:", n = t.protocol === "http:";
|
|
631
|
+
return s || e && n;
|
|
632
632
|
} catch {
|
|
633
633
|
return !1;
|
|
634
634
|
}
|
|
635
|
-
},
|
|
636
|
-
i.debug("URLUtils", "Generating API URL", { projectId:
|
|
637
|
-
const t = new URL(window.location.href), s = t.hostname,
|
|
638
|
-
if (
|
|
635
|
+
}, St = (r, e = !1) => {
|
|
636
|
+
i.debug("URLUtils", "Generating API URL", { projectId: r, allowHttp: e });
|
|
637
|
+
const t = new URL(window.location.href), s = t.hostname, n = s.split(".");
|
|
638
|
+
if (n.length === 0)
|
|
639
639
|
throw i.clientError("URLUtils", "Invalid hostname - no domain parts found", { hostname: s }), new Error("Invalid URL");
|
|
640
|
-
const a =
|
|
640
|
+
const a = n.slice(-2).join("."), o = e && t.protocol === "http:" ? "http" : "https", l = `${o}://${r}.${a}`;
|
|
641
641
|
if (i.debug("URLUtils", "Generated API URL", {
|
|
642
642
|
originalUrl: window.location.href,
|
|
643
643
|
hostname: s,
|
|
644
|
-
domainParts:
|
|
644
|
+
domainParts: n.length,
|
|
645
645
|
cleanDomain: a,
|
|
646
646
|
protocol: o,
|
|
647
647
|
generatedUrl: l
|
|
@@ -651,53 +651,53 @@ const ct = (n) => {
|
|
|
651
651
|
allowHttp: e
|
|
652
652
|
}), new Error("Invalid URL");
|
|
653
653
|
return i.debug("URLUtils", "API URL generation completed successfully", { apiUrl: l }), l;
|
|
654
|
-
}, se = (
|
|
654
|
+
}, se = (r, e = []) => {
|
|
655
655
|
i.debug("URLUtils", "Normalizing URL", {
|
|
656
|
-
urlLength:
|
|
656
|
+
urlLength: r.length,
|
|
657
657
|
sensitiveParamsCount: e.length
|
|
658
658
|
});
|
|
659
659
|
try {
|
|
660
|
-
const t = new URL(
|
|
660
|
+
const t = new URL(r), s = t.searchParams, n = Array.from(s.keys()).length;
|
|
661
661
|
let a = !1;
|
|
662
662
|
const o = [];
|
|
663
663
|
if (e.forEach((c) => {
|
|
664
664
|
s.has(c) && (s.delete(c), a = !0, o.push(c));
|
|
665
665
|
}), a && i.debug("URLUtils", "Sensitive parameters removed from URL", {
|
|
666
666
|
removedParams: o,
|
|
667
|
-
originalParamCount:
|
|
667
|
+
originalParamCount: n,
|
|
668
668
|
finalParamCount: Array.from(s.keys()).length
|
|
669
|
-
}), !a &&
|
|
670
|
-
return i.debug("URLUtils", "URL normalization - no changes needed"),
|
|
669
|
+
}), !a && r.includes("?"))
|
|
670
|
+
return i.debug("URLUtils", "URL normalization - no changes needed"), r;
|
|
671
671
|
t.search = s.toString();
|
|
672
672
|
const l = t.toString();
|
|
673
673
|
return i.debug("URLUtils", "URL normalization completed", {
|
|
674
674
|
hasChanged: a,
|
|
675
|
-
originalLength:
|
|
675
|
+
originalLength: r.length,
|
|
676
676
|
normalizedLength: l.length
|
|
677
677
|
}), l;
|
|
678
678
|
} catch (t) {
|
|
679
679
|
return i.warn("URLUtils", "URL normalization failed, returning original", {
|
|
680
|
-
url:
|
|
680
|
+
url: r.slice(0, 100),
|
|
681
681
|
error: t instanceof Error ? t.message : t
|
|
682
|
-
}),
|
|
682
|
+
}), r;
|
|
683
683
|
}
|
|
684
|
-
},
|
|
684
|
+
}, yt = (r, e = []) => {
|
|
685
685
|
if (i.debug("URLUtils", "Checking if URL path is excluded", {
|
|
686
|
-
urlLength:
|
|
686
|
+
urlLength: r.length,
|
|
687
687
|
excludedPathsCount: e.length
|
|
688
688
|
}), e.length === 0)
|
|
689
689
|
return i.debug("URLUtils", "No excluded paths configured"), !1;
|
|
690
690
|
let t;
|
|
691
691
|
try {
|
|
692
|
-
t = new URL(
|
|
692
|
+
t = new URL(r, window.location.origin).pathname, i.debug("URLUtils", "Extracted path from URL", { path: t });
|
|
693
693
|
} catch (c) {
|
|
694
694
|
return i.warn("URLUtils", "Failed to parse URL for path exclusion check", {
|
|
695
|
-
url:
|
|
695
|
+
url: r.slice(0, 100),
|
|
696
696
|
error: c instanceof Error ? c.message : c
|
|
697
697
|
}), !1;
|
|
698
698
|
}
|
|
699
|
-
const s = (c) => typeof c == "object" && c !== void 0 && typeof c.test == "function",
|
|
700
|
-
"^" + c.split("*").map((d) =>
|
|
699
|
+
const s = (c) => typeof c == "object" && c !== void 0 && typeof c.test == "function", n = (c) => c.replaceAll(/[$()*+.?[\\\]^{|}]/g, "\\$&"), a = (c) => new RegExp(
|
|
700
|
+
"^" + c.split("*").map((d) => n(d)).join(".+") + "$"
|
|
701
701
|
), o = e.find((c) => {
|
|
702
702
|
try {
|
|
703
703
|
if (s(c)) {
|
|
@@ -725,15 +725,15 @@ const ct = (n) => {
|
|
|
725
725
|
totalPatternsChecked: e.length
|
|
726
726
|
}), l;
|
|
727
727
|
};
|
|
728
|
-
class
|
|
728
|
+
class bt {
|
|
729
729
|
getUrl(e, t = !1) {
|
|
730
|
-
const s =
|
|
730
|
+
const s = St(e, t);
|
|
731
731
|
if (!te(s, t))
|
|
732
732
|
throw new Error("Invalid URL");
|
|
733
733
|
return s;
|
|
734
734
|
}
|
|
735
735
|
}
|
|
736
|
-
class
|
|
736
|
+
class Et {
|
|
737
737
|
async get(e, t) {
|
|
738
738
|
if (t.id === C.HttpSkip)
|
|
739
739
|
return i.debug("ConfigManager", "Using special project id"), this.getDefaultConfig(t);
|
|
@@ -748,10 +748,10 @@ class wt {
|
|
|
748
748
|
}
|
|
749
749
|
async load(e, t, s) {
|
|
750
750
|
try {
|
|
751
|
-
const
|
|
752
|
-
if (!
|
|
751
|
+
const n = s ? `${window.location.origin}/config` : this.getUrl(e);
|
|
752
|
+
if (!n)
|
|
753
753
|
throw new Error("Config URL is not valid or not allowed");
|
|
754
|
-
const a = await fetch(
|
|
754
|
+
const a = await fetch(n, {
|
|
755
755
|
method: "GET",
|
|
756
756
|
headers: { "Content-Type": "application/json" }
|
|
757
757
|
});
|
|
@@ -760,7 +760,7 @@ class wt {
|
|
|
760
760
|
throw i.error("ConfigManager", "Config API request failed", {
|
|
761
761
|
status: a.status,
|
|
762
762
|
statusText: a.statusText,
|
|
763
|
-
configUrl:
|
|
763
|
+
configUrl: n
|
|
764
764
|
}), new Error(A);
|
|
765
765
|
}
|
|
766
766
|
const o = await a.json();
|
|
@@ -769,31 +769,31 @@ class wt {
|
|
|
769
769
|
responseType: typeof o,
|
|
770
770
|
isArray: Array.isArray(o)
|
|
771
771
|
}), new Error("Invalid config API response: expected object");
|
|
772
|
-
const l =
|
|
772
|
+
const l = ut(o), d = { ...{ ...Ae, ...l }, ...t };
|
|
773
773
|
new URLSearchParams(window.location.search).get("qaMode") === "true" && !d.mode && (d.mode = L.QA, i.info("ConfigManager", "QA mode enabled via URL parameter"));
|
|
774
774
|
const y = Object.values(L).includes(d.mode) ? 1 : d.errorSampling ?? 0.1;
|
|
775
775
|
return { ...d, errorSampling: y };
|
|
776
|
-
} catch (
|
|
777
|
-
const a =
|
|
776
|
+
} catch (n) {
|
|
777
|
+
const a = n instanceof Error ? n.message : "Unknown error";
|
|
778
778
|
throw i.error("ConfigManager", "Failed to load config", { error: a, apiUrl: e }), new Error(`Failed to load config: ${a}`);
|
|
779
779
|
}
|
|
780
780
|
}
|
|
781
781
|
getUrl(e) {
|
|
782
782
|
const s = new URLSearchParams(window.location.search).get("qaMode") === "true";
|
|
783
|
-
let
|
|
784
|
-
if (s && (
|
|
785
|
-
throw i.clientError("ConfigManager", "Invalid config URL provided", { configUrl:
|
|
786
|
-
return
|
|
783
|
+
let n = `${e}/config`;
|
|
784
|
+
if (s && (n += "?qaMode=true"), !te(n))
|
|
785
|
+
throw i.clientError("ConfigManager", "Invalid config URL provided", { configUrl: n }), new Error("Config URL is not valid or not allowed");
|
|
786
|
+
return n;
|
|
787
787
|
}
|
|
788
788
|
getDefaultConfig(e) {
|
|
789
|
-
return
|
|
789
|
+
return Ye({
|
|
790
790
|
...e,
|
|
791
791
|
errorSampling: 1,
|
|
792
792
|
...Object.values(C).includes(e.id) && { mode: L.DEBUG }
|
|
793
793
|
});
|
|
794
794
|
}
|
|
795
795
|
}
|
|
796
|
-
class
|
|
796
|
+
class wt extends p {
|
|
797
797
|
storeManager;
|
|
798
798
|
queueStorageKey;
|
|
799
799
|
retryDelay = he;
|
|
@@ -801,7 +801,7 @@ class It extends p {
|
|
|
801
801
|
lastAsyncSend = 0;
|
|
802
802
|
lastSyncSend = 0;
|
|
803
803
|
constructor(e) {
|
|
804
|
-
super(), this.storeManager = e, this.queueStorageKey = `${
|
|
804
|
+
super(), this.storeManager = e, this.queueStorageKey = `${et(this.get("config")?.id)}:${this.get("userId")}`, this.recoverPersistedEvents();
|
|
805
805
|
}
|
|
806
806
|
async sendEventsQueueAsync(e) {
|
|
807
807
|
return this.executeSend(e, () => this.sendQueueAsync(e));
|
|
@@ -858,13 +858,20 @@ class It extends p {
|
|
|
858
858
|
try {
|
|
859
859
|
return (await fetch(t, {
|
|
860
860
|
method: "POST",
|
|
861
|
+
mode: "cors",
|
|
862
|
+
credentials: "omit",
|
|
861
863
|
headers: {
|
|
862
864
|
"Content-Type": "application/json"
|
|
863
865
|
},
|
|
864
866
|
body: s
|
|
865
867
|
})).ok;
|
|
866
|
-
} catch (
|
|
867
|
-
|
|
868
|
+
} catch (n) {
|
|
869
|
+
const a = n instanceof Error ? n.message : String(n), o = a.includes("CORS") || a.includes("NotSameOrigin") || a.includes("blocked");
|
|
870
|
+
return i.error("SenderManager", "Failed to send events async", {
|
|
871
|
+
error: a,
|
|
872
|
+
isCorsError: o,
|
|
873
|
+
url: t.replace(/\/\/[^/]+/, "//[DOMAIN]")
|
|
874
|
+
}), !1;
|
|
868
875
|
}
|
|
869
876
|
}
|
|
870
877
|
sendQueueSync(e) {
|
|
@@ -878,16 +885,22 @@ class It extends p {
|
|
|
878
885
|
return navigator.sendBeacon(t, s);
|
|
879
886
|
}
|
|
880
887
|
sendSyncXHR(e, t) {
|
|
888
|
+
const s = new XMLHttpRequest();
|
|
881
889
|
try {
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
return i.error("SenderManager", "Sync XHR failed", {
|
|
890
|
+
return s.open("POST", e, !1), s.setRequestHeader("Content-Type", "application/json"), s.withCredentials = !1, s.timeout = xe, s.send(t), s.status >= 200 && s.status < 300;
|
|
891
|
+
} catch (n) {
|
|
892
|
+
const a = n instanceof Error ? n.message : String(n), o = a.includes("CORS") || a.includes("NotSameOrigin") || a.includes("blocked");
|
|
893
|
+
return i.error("SenderManager", "Sync XHR failed", {
|
|
894
|
+
error: a,
|
|
895
|
+
isCorsError: o,
|
|
896
|
+
status: s.status ?? "unknown",
|
|
897
|
+
url: e.replace(/\/\/[^/]+/, "//[DOMAIN]")
|
|
898
|
+
}), !1;
|
|
886
899
|
}
|
|
887
900
|
}
|
|
888
901
|
prepareRequest(e) {
|
|
889
902
|
return {
|
|
890
|
-
url: `${this.get("config").id === C.HttpLocal ? window.location.origin : this.get("apiUrl")
|
|
903
|
+
url: `${this.get("config").id === C.HttpLocal ? window.location.origin : this.get("apiUrl")}/collect`,
|
|
891
904
|
payload: JSON.stringify(e)
|
|
892
905
|
};
|
|
893
906
|
}
|
|
@@ -1006,7 +1019,7 @@ class It extends p {
|
|
|
1006
1019
|
this.retryTimeoutId !== null && (clearTimeout(this.retryTimeoutId), this.retryTimeoutId = null);
|
|
1007
1020
|
}
|
|
1008
1021
|
}
|
|
1009
|
-
class
|
|
1022
|
+
class It extends p {
|
|
1010
1023
|
shouldSampleEvent(e, t) {
|
|
1011
1024
|
return this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug" ? !0 : e === h.WEB_VITALS ? this.isWebVitalEventSampledIn(t?.type) : this.isSampledIn();
|
|
1012
1025
|
}
|
|
@@ -1018,19 +1031,19 @@ class Tt extends p {
|
|
|
1018
1031
|
const t = e === "LONG_TASK", s = t ? De : He;
|
|
1019
1032
|
if (s >= 1) return !0;
|
|
1020
1033
|
if (s <= 0) return !1;
|
|
1021
|
-
const
|
|
1022
|
-
return this.getHash(
|
|
1034
|
+
const n = `${this.get("userId")}|${t ? "long_task" : "web_vitals"}`;
|
|
1035
|
+
return this.getHash(n) % 100 / 100 < s;
|
|
1023
1036
|
}
|
|
1024
1037
|
getHash(e) {
|
|
1025
1038
|
let t = 0;
|
|
1026
1039
|
for (let s = 0; s < e.length; s++) {
|
|
1027
|
-
const
|
|
1028
|
-
t = (t << 5) - t +
|
|
1040
|
+
const n = e.charCodeAt(s);
|
|
1041
|
+
t = (t << 5) - t + n, t |= 0;
|
|
1029
1042
|
}
|
|
1030
1043
|
return Math.abs(t);
|
|
1031
1044
|
}
|
|
1032
1045
|
}
|
|
1033
|
-
class
|
|
1046
|
+
class Tt extends p {
|
|
1034
1047
|
getEventTagsIds(e, t) {
|
|
1035
1048
|
switch (e.type) {
|
|
1036
1049
|
case h.PAGE_VIEW:
|
|
@@ -1045,7 +1058,7 @@ class Mt extends p {
|
|
|
1045
1058
|
const s = this.get("config")?.tags?.filter((a) => a.triggerType === h.PAGE_VIEW) ?? [];
|
|
1046
1059
|
if (s.length === 0)
|
|
1047
1060
|
return [];
|
|
1048
|
-
const
|
|
1061
|
+
const n = [];
|
|
1049
1062
|
for (const a of s) {
|
|
1050
1063
|
const { id: o, logicalOperator: l, conditions: c } = a, d = [];
|
|
1051
1064
|
for (const g of c)
|
|
@@ -1072,15 +1085,15 @@ class Mt extends p {
|
|
|
1072
1085
|
}
|
|
1073
1086
|
}
|
|
1074
1087
|
let u = !1;
|
|
1075
|
-
u = l === G.AND ? d.every(Boolean) : d.some(Boolean), u &&
|
|
1088
|
+
u = l === G.AND ? d.every(Boolean) : d.some(Boolean), u && n.push(o);
|
|
1076
1089
|
}
|
|
1077
|
-
return
|
|
1090
|
+
return n;
|
|
1078
1091
|
}
|
|
1079
1092
|
checkEventTypeClick(e, t) {
|
|
1080
1093
|
const s = this.get("config")?.tags?.filter((a) => a.triggerType === h.CLICK) ?? [];
|
|
1081
1094
|
if (s.length === 0)
|
|
1082
1095
|
return [];
|
|
1083
|
-
const
|
|
1096
|
+
const n = [];
|
|
1084
1097
|
for (const a of s) {
|
|
1085
1098
|
const { id: o, logicalOperator: l, conditions: c } = a, d = [];
|
|
1086
1099
|
for (const g of c) {
|
|
@@ -1117,26 +1130,26 @@ class Mt extends p {
|
|
|
1117
1130
|
}
|
|
1118
1131
|
}
|
|
1119
1132
|
let u = !1;
|
|
1120
|
-
u = l === G.AND ? d.every(Boolean) : d.some(Boolean), u &&
|
|
1133
|
+
u = l === G.AND ? d.every(Boolean) : d.some(Boolean), u && n.push(o);
|
|
1121
1134
|
}
|
|
1122
|
-
return
|
|
1135
|
+
return n;
|
|
1123
1136
|
}
|
|
1124
1137
|
matchUrlMatches(e, t) {
|
|
1125
1138
|
if (e.type !== m.URL_MATCHES)
|
|
1126
1139
|
return !1;
|
|
1127
|
-
const s = e.value.toLowerCase(),
|
|
1140
|
+
const s = e.value.toLowerCase(), n = t.toLowerCase();
|
|
1128
1141
|
switch (e.operator) {
|
|
1129
1142
|
case f.EQUALS:
|
|
1130
|
-
return
|
|
1143
|
+
return n === s;
|
|
1131
1144
|
case f.CONTAINS:
|
|
1132
|
-
return
|
|
1145
|
+
return n.includes(s);
|
|
1133
1146
|
case f.STARTS_WITH:
|
|
1134
|
-
return
|
|
1147
|
+
return n.startsWith(s);
|
|
1135
1148
|
case f.ENDS_WITH:
|
|
1136
|
-
return
|
|
1149
|
+
return n.endsWith(s);
|
|
1137
1150
|
case f.REGEX:
|
|
1138
1151
|
try {
|
|
1139
|
-
return new RegExp(s, "gi").test(
|
|
1152
|
+
return new RegExp(s, "gi").test(n);
|
|
1140
1153
|
} catch {
|
|
1141
1154
|
return !1;
|
|
1142
1155
|
}
|
|
@@ -1147,19 +1160,19 @@ class Mt extends p {
|
|
|
1147
1160
|
matchDeviceType(e, t) {
|
|
1148
1161
|
if (e.type !== m.DEVICE_TYPE)
|
|
1149
1162
|
return !1;
|
|
1150
|
-
const s = e.value.toLowerCase(),
|
|
1163
|
+
const s = e.value.toLowerCase(), n = t.toLowerCase();
|
|
1151
1164
|
switch (e.operator) {
|
|
1152
1165
|
case f.EQUALS:
|
|
1153
|
-
return
|
|
1166
|
+
return n === s;
|
|
1154
1167
|
case f.CONTAINS:
|
|
1155
|
-
return
|
|
1168
|
+
return n.includes(s);
|
|
1156
1169
|
case f.STARTS_WITH:
|
|
1157
|
-
return
|
|
1170
|
+
return n.startsWith(s);
|
|
1158
1171
|
case f.ENDS_WITH:
|
|
1159
|
-
return
|
|
1172
|
+
return n.endsWith(s);
|
|
1160
1173
|
case f.REGEX:
|
|
1161
1174
|
try {
|
|
1162
|
-
return new RegExp(s, "gi").test(
|
|
1175
|
+
return new RegExp(s, "gi").test(n);
|
|
1163
1176
|
} catch {
|
|
1164
1177
|
return !1;
|
|
1165
1178
|
}
|
|
@@ -1181,19 +1194,19 @@ class Mt extends p {
|
|
|
1181
1194
|
t.role ?? "",
|
|
1182
1195
|
t.ariaLabel ?? "",
|
|
1183
1196
|
...Object.values(t.dataAttributes ?? {})
|
|
1184
|
-
].join(" "),
|
|
1197
|
+
].join(" "), n = e.value.toLowerCase(), a = s.toLowerCase();
|
|
1185
1198
|
switch (e.operator) {
|
|
1186
1199
|
case f.EQUALS:
|
|
1187
|
-
return this.checkElementFieldEquals(t,
|
|
1200
|
+
return this.checkElementFieldEquals(t, n);
|
|
1188
1201
|
case f.CONTAINS:
|
|
1189
|
-
return a.includes(
|
|
1202
|
+
return a.includes(n);
|
|
1190
1203
|
case f.STARTS_WITH:
|
|
1191
|
-
return a.startsWith(
|
|
1204
|
+
return a.startsWith(n);
|
|
1192
1205
|
case f.ENDS_WITH:
|
|
1193
|
-
return a.endsWith(
|
|
1206
|
+
return a.endsWith(n);
|
|
1194
1207
|
case f.REGEX:
|
|
1195
1208
|
try {
|
|
1196
|
-
return new RegExp(
|
|
1209
|
+
return new RegExp(n, "gi").test(a);
|
|
1197
1210
|
} catch {
|
|
1198
1211
|
return !1;
|
|
1199
1212
|
}
|
|
@@ -1206,19 +1219,19 @@ class Mt extends p {
|
|
|
1206
1219
|
e.type
|
|
1207
1220
|
))
|
|
1208
1221
|
return !1;
|
|
1209
|
-
const s = t ?? "",
|
|
1222
|
+
const s = t ?? "", n = e.value.toLowerCase(), a = s.toLowerCase();
|
|
1210
1223
|
switch (e.operator) {
|
|
1211
1224
|
case f.EQUALS:
|
|
1212
|
-
return a ===
|
|
1225
|
+
return a === n;
|
|
1213
1226
|
case f.CONTAINS:
|
|
1214
|
-
return a.includes(
|
|
1227
|
+
return a.includes(n);
|
|
1215
1228
|
case f.STARTS_WITH:
|
|
1216
|
-
return a.startsWith(
|
|
1229
|
+
return a.startsWith(n);
|
|
1217
1230
|
case f.ENDS_WITH:
|
|
1218
|
-
return a.endsWith(
|
|
1231
|
+
return a.endsWith(n);
|
|
1219
1232
|
case f.REGEX:
|
|
1220
1233
|
try {
|
|
1221
|
-
return new RegExp(
|
|
1234
|
+
return new RegExp(n, "gi").test(a);
|
|
1222
1235
|
} catch {
|
|
1223
1236
|
return !1;
|
|
1224
1237
|
}
|
|
@@ -1238,22 +1251,22 @@ class Mt extends p {
|
|
|
1238
1251
|
e.role,
|
|
1239
1252
|
e.ariaLabel
|
|
1240
1253
|
];
|
|
1241
|
-
for (const
|
|
1242
|
-
if (
|
|
1243
|
-
const a =
|
|
1254
|
+
for (const n of s)
|
|
1255
|
+
if (n) {
|
|
1256
|
+
const a = n.toLowerCase(), o = t.toLowerCase();
|
|
1244
1257
|
if (a === o)
|
|
1245
1258
|
return !0;
|
|
1246
1259
|
}
|
|
1247
1260
|
if (e.dataAttributes)
|
|
1248
|
-
for (const
|
|
1249
|
-
const a =
|
|
1261
|
+
for (const n of Object.values(e.dataAttributes)) {
|
|
1262
|
+
const a = n.toLowerCase(), o = t.toLowerCase();
|
|
1250
1263
|
if (a === o)
|
|
1251
1264
|
return !0;
|
|
1252
1265
|
}
|
|
1253
1266
|
return !1;
|
|
1254
1267
|
}
|
|
1255
1268
|
}
|
|
1256
|
-
class
|
|
1269
|
+
class Mt extends p {
|
|
1257
1270
|
googleAnalytics;
|
|
1258
1271
|
samplingManager;
|
|
1259
1272
|
tagsManager;
|
|
@@ -1275,7 +1288,7 @@ class At extends p {
|
|
|
1275
1288
|
// Persistence storage key
|
|
1276
1289
|
PERSISTENCE_KEY = "tl:circuit_breaker_events";
|
|
1277
1290
|
constructor(e, t = null) {
|
|
1278
|
-
super(), this.storageManager = e, this.googleAnalytics = t, this.samplingManager = new
|
|
1291
|
+
super(), this.storageManager = e, this.googleAnalytics = t, this.samplingManager = new It(), this.tagsManager = new Tt(), this.dataSender = new wt(e), this.restoreEventsFromStorage(), i.debug("EventManager", "EventManager initialized", {
|
|
1279
1292
|
hasGoogleAnalytics: !!t,
|
|
1280
1293
|
restoredEventsCount: this.eventsQueue.length
|
|
1281
1294
|
});
|
|
@@ -1284,7 +1297,7 @@ class At extends p {
|
|
|
1284
1297
|
type: e,
|
|
1285
1298
|
page_url: t,
|
|
1286
1299
|
from_page_url: s,
|
|
1287
|
-
scroll_data:
|
|
1300
|
+
scroll_data: n,
|
|
1288
1301
|
click_data: a,
|
|
1289
1302
|
custom_event: o,
|
|
1290
1303
|
web_vitals: l,
|
|
@@ -1296,7 +1309,7 @@ class At extends p {
|
|
|
1296
1309
|
page_url: t,
|
|
1297
1310
|
hasCustomEvent: !!o,
|
|
1298
1311
|
hasClickData: !!a,
|
|
1299
|
-
hasScrollData: !!
|
|
1312
|
+
hasScrollData: !!n,
|
|
1300
1313
|
hasWebVitals: !!l
|
|
1301
1314
|
}), !this.samplingManager.shouldSampleEvent(e, l)) {
|
|
1302
1315
|
i.debug("EventManager", "Event filtered by sampling", { type: e, samplingActive: !0 });
|
|
@@ -1305,7 +1318,7 @@ class At extends p {
|
|
|
1305
1318
|
if (this.isDuplicatedEvent({
|
|
1306
1319
|
type: e,
|
|
1307
1320
|
page_url: t,
|
|
1308
|
-
scroll_data:
|
|
1321
|
+
scroll_data: n,
|
|
1309
1322
|
click_data: a,
|
|
1310
1323
|
custom_event: o,
|
|
1311
1324
|
web_vitals: l,
|
|
@@ -1323,20 +1336,20 @@ class At extends p {
|
|
|
1323
1336
|
});
|
|
1324
1337
|
return;
|
|
1325
1338
|
}
|
|
1326
|
-
const g = t || this.get("pageUrl"), y =
|
|
1339
|
+
const g = t || this.get("pageUrl"), y = yt(g, this.get("config").excludedUrlPaths), I = this.get("hasStartSession"), A = e == h.SESSION_END;
|
|
1327
1340
|
if (y && (!A || A && !I)) {
|
|
1328
1341
|
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && i.debug("EventManager", `Event ${e} on excluded route: ${t}`);
|
|
1329
1342
|
return;
|
|
1330
1343
|
}
|
|
1331
1344
|
const U = e === h.SESSION_START;
|
|
1332
1345
|
U && this.set("hasStartSession", !0);
|
|
1333
|
-
const ie = U ?
|
|
1346
|
+
const ie = U ? nt() : void 0, O = {
|
|
1334
1347
|
type: e,
|
|
1335
1348
|
page_url: y ? "excluded" : g,
|
|
1336
1349
|
timestamp: Date.now(),
|
|
1337
1350
|
...U && { referrer: document.referrer || "Direct" },
|
|
1338
1351
|
...s && !y ? { from_page_url: s } : {},
|
|
1339
|
-
...
|
|
1352
|
+
...n && { scroll_data: n },
|
|
1340
1353
|
...a && { click_data: a },
|
|
1341
1354
|
...o && { custom_event: o },
|
|
1342
1355
|
...ie && { utm: ie },
|
|
@@ -1449,11 +1462,11 @@ class At extends p {
|
|
|
1449
1462
|
buildEventsPayload() {
|
|
1450
1463
|
const e = /* @__PURE__ */ new Map();
|
|
1451
1464
|
for (const s of this.eventsQueue) {
|
|
1452
|
-
let
|
|
1453
|
-
s.click_data && (
|
|
1465
|
+
let n = `${s.type}_${s.page_url}`;
|
|
1466
|
+
s.click_data && (n += `_${s.click_data.x}_${s.click_data.y}`), s.scroll_data && (n += `_${s.scroll_data.depth}_${s.scroll_data.direction}`), s.custom_event && (n += `_${s.custom_event.name}`), s.web_vitals && (n += `_${s.web_vitals.type}`), e.has(n) || e.set(n, s);
|
|
1454
1467
|
}
|
|
1455
1468
|
const t = [...e.values()];
|
|
1456
|
-
return t.sort((s,
|
|
1469
|
+
return t.sort((s, n) => s.timestamp - n.timestamp), {
|
|
1457
1470
|
user_id: this.get("userId"),
|
|
1458
1471
|
session_id: this.get("sessionId"),
|
|
1459
1472
|
device: this.get("device"),
|
|
@@ -1467,14 +1480,14 @@ class At extends p {
|
|
|
1467
1480
|
getEventFingerprint(e) {
|
|
1468
1481
|
const t = `${e.type}_${e.page_url}`;
|
|
1469
1482
|
if (e.click_data) {
|
|
1470
|
-
const s = Math.round((e.click_data.x || 0) / F) * F,
|
|
1471
|
-
return `${t}_${s}_${
|
|
1483
|
+
const s = Math.round((e.click_data.x || 0) / F) * F, n = Math.round((e.click_data.y || 0) / F) * F;
|
|
1484
|
+
return `${t}_${s}_${n}_${e.click_data.tag}_${e.click_data.id}`;
|
|
1472
1485
|
}
|
|
1473
1486
|
return e.scroll_data ? `${t}_${e.scroll_data.depth}_${e.scroll_data.direction}` : e.custom_event ? `${t}_${e.custom_event.name}` : e.web_vitals ? `${t}_${e.web_vitals.type}` : e.session_end_reason ? `${t}_${e.session_end_reason}` : e.session_start_recovered !== void 0 ? `${t}_${e.session_start_recovered}` : t;
|
|
1474
1487
|
}
|
|
1475
1488
|
isDuplicatedEvent(e) {
|
|
1476
|
-
const t = this.getEventFingerprint(e), s = this.eventFingerprints.get(t) ?? 0,
|
|
1477
|
-
return
|
|
1489
|
+
const t = this.getEventFingerprint(e), s = this.eventFingerprints.get(t) ?? 0, n = Date.now();
|
|
1490
|
+
return n - s < de ? !0 : (this.eventFingerprints.set(t, n), this.cleanupOldFingerprints(), !1);
|
|
1478
1491
|
}
|
|
1479
1492
|
/**
|
|
1480
1493
|
* Cleans up old fingerprints to prevent memory leaks
|
|
@@ -1483,10 +1496,10 @@ class At extends p {
|
|
|
1483
1496
|
if (this.eventFingerprints.size <= Oe)
|
|
1484
1497
|
return;
|
|
1485
1498
|
const e = Date.now(), t = de * Fe, s = [];
|
|
1486
|
-
for (const [
|
|
1487
|
-
e - a > t && s.push(
|
|
1488
|
-
for (const
|
|
1489
|
-
this.eventFingerprints.delete(
|
|
1499
|
+
for (const [n, a] of this.eventFingerprints)
|
|
1500
|
+
e - a > t && s.push(n);
|
|
1501
|
+
for (const n of s)
|
|
1502
|
+
this.eventFingerprints.delete(n);
|
|
1490
1503
|
i.debug("EventManager", "Cleaned up old event fingerprints", {
|
|
1491
1504
|
totalFingerprints: this.eventFingerprints.size + s.length,
|
|
1492
1505
|
cleanedCount: s.length,
|
|
@@ -1553,11 +1566,11 @@ class At extends p {
|
|
|
1553
1566
|
const e = this.storageManager.getItem(this.PERSISTENCE_KEY);
|
|
1554
1567
|
if (!e)
|
|
1555
1568
|
return;
|
|
1556
|
-
const t = JSON.parse(e), s = Date.now(),
|
|
1557
|
-
if (s - t.timestamp >
|
|
1569
|
+
const t = JSON.parse(e), s = Date.now(), n = Qe;
|
|
1570
|
+
if (s - t.timestamp > n) {
|
|
1558
1571
|
this.clearPersistedEvents(), i.debug("EventManager", "Cleared expired persisted events", {
|
|
1559
1572
|
age: s - t.timestamp,
|
|
1560
|
-
maxAge:
|
|
1573
|
+
maxAge: n
|
|
1561
1574
|
});
|
|
1562
1575
|
return;
|
|
1563
1576
|
}
|
|
@@ -1584,7 +1597,7 @@ class At extends p {
|
|
|
1584
1597
|
}
|
|
1585
1598
|
}
|
|
1586
1599
|
}
|
|
1587
|
-
class
|
|
1600
|
+
class At extends p {
|
|
1588
1601
|
storageManager;
|
|
1589
1602
|
constructor(e) {
|
|
1590
1603
|
super(), this.storageManager = e;
|
|
@@ -1597,7 +1610,7 @@ class _t extends p {
|
|
|
1597
1610
|
return this.storageManager.setItem(ve(this.get("config")?.id), t), t;
|
|
1598
1611
|
}
|
|
1599
1612
|
}
|
|
1600
|
-
class
|
|
1613
|
+
class _t {
|
|
1601
1614
|
onActivity;
|
|
1602
1615
|
options = { passive: !0 };
|
|
1603
1616
|
constructor(e) {
|
|
@@ -1618,7 +1631,7 @@ class Ct {
|
|
|
1618
1631
|
}
|
|
1619
1632
|
}
|
|
1620
1633
|
}
|
|
1621
|
-
class
|
|
1634
|
+
class Ct {
|
|
1622
1635
|
onActivity;
|
|
1623
1636
|
options = { passive: !0 };
|
|
1624
1637
|
motionThreshold;
|
|
@@ -1648,7 +1661,7 @@ class Lt {
|
|
|
1648
1661
|
}
|
|
1649
1662
|
};
|
|
1650
1663
|
}
|
|
1651
|
-
class
|
|
1664
|
+
class Lt {
|
|
1652
1665
|
onActivity;
|
|
1653
1666
|
options = { passive: !0 };
|
|
1654
1667
|
constructor(e) {
|
|
@@ -1669,7 +1682,7 @@ class Rt {
|
|
|
1669
1682
|
}
|
|
1670
1683
|
}
|
|
1671
1684
|
}
|
|
1672
|
-
class
|
|
1685
|
+
class Rt {
|
|
1673
1686
|
onActivity;
|
|
1674
1687
|
options = { passive: !0 };
|
|
1675
1688
|
constructor(e) {
|
|
@@ -1690,7 +1703,7 @@ class kt {
|
|
|
1690
1703
|
}
|
|
1691
1704
|
}
|
|
1692
1705
|
}
|
|
1693
|
-
class
|
|
1706
|
+
class kt {
|
|
1694
1707
|
onActivity;
|
|
1695
1708
|
onVisibilityChange;
|
|
1696
1709
|
isMobile;
|
|
@@ -1727,7 +1740,7 @@ class Nt {
|
|
|
1727
1740
|
}
|
|
1728
1741
|
}
|
|
1729
1742
|
}
|
|
1730
|
-
class
|
|
1743
|
+
class Nt {
|
|
1731
1744
|
onInactivity;
|
|
1732
1745
|
options = { passive: !0 };
|
|
1733
1746
|
constructor(e) {
|
|
@@ -1754,12 +1767,12 @@ class Ce extends p {
|
|
|
1754
1767
|
eventManager;
|
|
1755
1768
|
projectId;
|
|
1756
1769
|
debugMode;
|
|
1757
|
-
constructor(e, t, s,
|
|
1770
|
+
constructor(e, t, s, n) {
|
|
1758
1771
|
super(), this.storageManager = e, this.eventManager = s ?? null, this.projectId = t, this.debugMode = (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") ?? !1, this.config = {
|
|
1759
1772
|
recoveryWindowMs: this.calculateRecoveryWindow(),
|
|
1760
1773
|
maxRecoveryAttempts: Ke,
|
|
1761
1774
|
contextPreservation: !0,
|
|
1762
|
-
...
|
|
1775
|
+
...n
|
|
1763
1776
|
};
|
|
1764
1777
|
}
|
|
1765
1778
|
/**
|
|
@@ -1775,22 +1788,22 @@ class Ce extends p {
|
|
|
1775
1788
|
), {
|
|
1776
1789
|
recovered: !1
|
|
1777
1790
|
};
|
|
1778
|
-
const
|
|
1779
|
-
if (!
|
|
1791
|
+
const n = s?.context;
|
|
1792
|
+
if (!n)
|
|
1780
1793
|
return this.debugMode && i.debug("SessionRecovery", "No session context available for recovery"), {
|
|
1781
1794
|
recovered: !1
|
|
1782
1795
|
};
|
|
1783
1796
|
const a = Date.now();
|
|
1784
|
-
if (a -
|
|
1797
|
+
if (a - n.lastActivity > this.config.recoveryWindowMs)
|
|
1785
1798
|
return this.debugMode && i.debug("SessionRecovery", "Session recovery failed - outside recovery window"), {
|
|
1786
1799
|
recovered: !1
|
|
1787
1800
|
};
|
|
1788
|
-
const l =
|
|
1801
|
+
const l = n.sessionId, c = (s?.attempt ?? 0) + 1, d = {
|
|
1789
1802
|
sessionId: e ?? l,
|
|
1790
1803
|
timestamp: a,
|
|
1791
1804
|
attempt: c,
|
|
1792
1805
|
context: {
|
|
1793
|
-
...
|
|
1806
|
+
...n,
|
|
1794
1807
|
recoveryAttempts: c,
|
|
1795
1808
|
lastActivity: a
|
|
1796
1809
|
}
|
|
@@ -1835,8 +1848,8 @@ class Ce extends p {
|
|
|
1835
1848
|
context: e
|
|
1836
1849
|
};
|
|
1837
1850
|
t.push(s);
|
|
1838
|
-
const
|
|
1839
|
-
t.length >
|
|
1851
|
+
const n = 5;
|
|
1852
|
+
t.length > n && t.splice(0, t.length - n), this.storeRecoveryAttempts(t), this.debugMode && i.debug("SessionRecovery", `Stored session context for recovery: ${e.sessionId}`);
|
|
1840
1853
|
} catch (t) {
|
|
1841
1854
|
this.debugMode && i.warn("SessionRecovery", "Failed to store session context for recovery", { error: t });
|
|
1842
1855
|
}
|
|
@@ -1881,7 +1894,7 @@ class Ce extends p {
|
|
|
1881
1894
|
* Clean up old recovery attempts
|
|
1882
1895
|
*/
|
|
1883
1896
|
cleanupOldRecoveryAttempts() {
|
|
1884
|
-
const e = this.getStoredRecoveryAttempts(), t = Date.now(), s = e.filter((
|
|
1897
|
+
const e = this.getStoredRecoveryAttempts(), t = Date.now(), s = e.filter((n) => t - n.timestamp <= this.config.recoveryWindowMs);
|
|
1885
1898
|
s.length !== e.length && (this.storeRecoveryAttempts(s), this.debugMode && i.debug("SessionRecovery", `Cleaned up ${e.length - s.length} old recovery attempts`));
|
|
1886
1899
|
}
|
|
1887
1900
|
/**
|
|
@@ -1911,7 +1924,7 @@ class Ce extends p {
|
|
|
1911
1924
|
this.storageManager.removeItem(V(this.projectId)), this.debugMode && i.debug("SessionRecovery", "Cleared all recovery data");
|
|
1912
1925
|
}
|
|
1913
1926
|
}
|
|
1914
|
-
class
|
|
1927
|
+
class Ut extends p {
|
|
1915
1928
|
config;
|
|
1916
1929
|
eventManager = null;
|
|
1917
1930
|
storageManager = null;
|
|
@@ -1968,7 +1981,7 @@ class Pt extends p {
|
|
|
1968
1981
|
crossTabConflicts: 0,
|
|
1969
1982
|
lastHealthCheck: Date.now()
|
|
1970
1983
|
};
|
|
1971
|
-
constructor(e, t, s,
|
|
1984
|
+
constructor(e, t, s, n, a) {
|
|
1972
1985
|
super(), this.config = {
|
|
1973
1986
|
throttleDelay: Te,
|
|
1974
1987
|
visibilityTimeout: Ve,
|
|
@@ -1980,7 +1993,7 @@ class Pt extends p {
|
|
|
1980
1993
|
maxRetries: 2,
|
|
1981
1994
|
debugMode: !1,
|
|
1982
1995
|
...a
|
|
1983
|
-
}, this.onActivity = e, this.onInactivity = t, this.eventManager = s ?? null, this.storageManager =
|
|
1996
|
+
}, this.onActivity = e, this.onInactivity = t, this.eventManager = s ?? null, this.storageManager = n ?? null, this.deviceCapabilities = this.detectDeviceCapabilities(), this.initializeRecoveryManager(), this.initializeListenerManagers(), this.setupAllListeners(), this.sessionEndConfig.enablePageUnloadHandlers && this.setupPageUnloadHandlers(), i.debug("SessionManager", "SessionManager initialized", {
|
|
1984
1997
|
sessionTimeout: this.config.timeout,
|
|
1985
1998
|
deviceCapabilities: this.deviceCapabilities,
|
|
1986
1999
|
unloadHandlersEnabled: this.sessionEndConfig.enablePageUnloadHandlers
|
|
@@ -2024,8 +2037,8 @@ class Pt extends p {
|
|
|
2024
2037
|
const e = Date.now();
|
|
2025
2038
|
let t = "", s = !1;
|
|
2026
2039
|
if (this.recoveryManager?.hasRecoverableSession()) {
|
|
2027
|
-
const
|
|
2028
|
-
|
|
2040
|
+
const n = this.recoveryManager.attemptSessionRecovery();
|
|
2041
|
+
n.recovered && n.recoveredSessionId && (t = n.recoveredSessionId, s = !0, this.trackSessionHealth("recovery"), n.context ? (this.sessionStartTime = n.context.startTime, this.lastActivityTime = e) : (this.sessionStartTime = e, this.lastActivityTime = e), i.info("SessionManager", "Session successfully recovered", {
|
|
2029
2042
|
sessionId: t,
|
|
2030
2043
|
recoveryAttempts: this.sessionHealth.recoveryAttempts
|
|
2031
2044
|
}));
|
|
@@ -2048,13 +2061,13 @@ class Pt extends p {
|
|
|
2048
2061
|
}), this.recoveryManager && (this.recoveryManager.cleanupOldRecoveryAttempts(), this.recoveryManager = null);
|
|
2049
2062
|
}
|
|
2050
2063
|
detectDeviceCapabilities() {
|
|
2051
|
-
const e = "ontouchstart" in window || navigator.maxTouchPoints > 0, t = window.matchMedia("(pointer: fine)").matches, s = !window.matchMedia("(pointer: coarse)").matches,
|
|
2052
|
-
return { hasTouch: e, hasMouse: t, hasKeyboard: s, isMobile:
|
|
2064
|
+
const e = "ontouchstart" in window || navigator.maxTouchPoints > 0, t = window.matchMedia("(pointer: fine)").matches, s = !window.matchMedia("(pointer: coarse)").matches, n = we() === E.Mobile;
|
|
2065
|
+
return { hasTouch: e, hasMouse: t, hasKeyboard: s, isMobile: n };
|
|
2053
2066
|
}
|
|
2054
2067
|
initializeListenerManagers() {
|
|
2055
|
-
this.listenerManagers.push(new
|
|
2056
|
-
new
|
|
2057
|
-
), this.listenerManagers.push(new
|
|
2068
|
+
this.listenerManagers.push(new _t(this.handleActivity)), this.deviceCapabilities.hasTouch && this.listenerManagers.push(new Ct(this.handleActivity, this.config.motionThreshold)), this.deviceCapabilities.hasMouse && this.listenerManagers.push(new Lt(this.handleActivity)), this.deviceCapabilities.hasKeyboard && this.listenerManagers.push(new Rt(this.handleActivity)), this.listenerManagers.push(
|
|
2069
|
+
new kt(this.handleActivity, this.handleVisibilityChange, this.deviceCapabilities.isMobile)
|
|
2070
|
+
), this.listenerManagers.push(new Nt(this.handleInactivity));
|
|
2058
2071
|
}
|
|
2059
2072
|
setupAllListeners() {
|
|
2060
2073
|
this.listenerManagers.forEach((e) => e.setup());
|
|
@@ -2161,20 +2174,20 @@ class Pt extends p {
|
|
|
2161
2174
|
}
|
|
2162
2175
|
async performSessionEnd(e, t) {
|
|
2163
2176
|
const s = Date.now();
|
|
2164
|
-
let
|
|
2177
|
+
let n = 0;
|
|
2165
2178
|
try {
|
|
2166
2179
|
if (i.info("SessionManager", "Starting session end", { method: t, reason: e, timestamp: s }), this.eventManager) {
|
|
2167
2180
|
this.eventManager.track({
|
|
2168
2181
|
type: h.SESSION_END,
|
|
2169
2182
|
session_end_reason: e
|
|
2170
|
-
}),
|
|
2183
|
+
}), n = this.eventManager.getQueueLength();
|
|
2171
2184
|
const o = await this.eventManager.flushImmediately();
|
|
2172
2185
|
this.cleanupSession();
|
|
2173
2186
|
const l = {
|
|
2174
2187
|
success: o,
|
|
2175
2188
|
reason: e,
|
|
2176
2189
|
timestamp: s,
|
|
2177
|
-
eventsFlushed:
|
|
2190
|
+
eventsFlushed: n,
|
|
2178
2191
|
method: t
|
|
2179
2192
|
};
|
|
2180
2193
|
return o ? this.sessionEndStats.successfulEnds++ : this.sessionEndStats.failedEnds++, l;
|
|
@@ -2193,7 +2206,7 @@ class Pt extends p {
|
|
|
2193
2206
|
success: !1,
|
|
2194
2207
|
reason: e,
|
|
2195
2208
|
timestamp: s,
|
|
2196
|
-
eventsFlushed:
|
|
2209
|
+
eventsFlushed: n,
|
|
2197
2210
|
method: t
|
|
2198
2211
|
};
|
|
2199
2212
|
}
|
|
@@ -2241,16 +2254,16 @@ class Pt extends p {
|
|
|
2241
2254
|
return a ? this.sessionEndStats.successfulEnds++ : this.sessionEndStats.failedEnds++, o;
|
|
2242
2255
|
}
|
|
2243
2256
|
this.cleanupSession();
|
|
2244
|
-
const
|
|
2257
|
+
const n = {
|
|
2245
2258
|
success: !0,
|
|
2246
2259
|
reason: e,
|
|
2247
2260
|
timestamp: t,
|
|
2248
2261
|
eventsFlushed: 0,
|
|
2249
2262
|
method: "sync"
|
|
2250
2263
|
};
|
|
2251
|
-
return this.sessionEndStats.successfulEnds++,
|
|
2252
|
-
} catch (
|
|
2253
|
-
return this.sessionEndStats.failedEnds++, this.cleanupSession(), i.error("SessionManager", "Sync session end failed", { error:
|
|
2264
|
+
return this.sessionEndStats.successfulEnds++, n;
|
|
2265
|
+
} catch (n) {
|
|
2266
|
+
return this.sessionEndStats.failedEnds++, this.cleanupSession(), i.error("SessionManager", "Sync session end failed", { error: n, reason: e }), {
|
|
2254
2267
|
success: !1,
|
|
2255
2268
|
reason: e,
|
|
2256
2269
|
timestamp: t,
|
|
@@ -2265,16 +2278,16 @@ class Pt extends p {
|
|
|
2265
2278
|
e || !this.get("sessionId") || (e = !0, this.clearInactivityTimer(), this.endSessionSafely("page_unload", { forceSync: !0 }));
|
|
2266
2279
|
}, s = () => {
|
|
2267
2280
|
t();
|
|
2268
|
-
},
|
|
2281
|
+
}, n = (o) => {
|
|
2269
2282
|
o.persisted || t();
|
|
2270
2283
|
}, a = () => {
|
|
2271
2284
|
document.visibilityState === "hidden" && this.get("sessionId") && !e && (this.visibilityChangeTimeout = window.setTimeout(() => {
|
|
2272
2285
|
document.visibilityState === "hidden" && this.get("sessionId") && !e && t(), this.visibilityChangeTimeout = null;
|
|
2273
2286
|
}, 1e3));
|
|
2274
2287
|
};
|
|
2275
|
-
window.addEventListener("beforeunload", s), window.addEventListener("pagehide",
|
|
2288
|
+
window.addEventListener("beforeunload", s), window.addEventListener("pagehide", n), document.addEventListener("visibilitychange", a), this.cleanupHandlers.push(
|
|
2276
2289
|
() => window.removeEventListener("beforeunload", s),
|
|
2277
|
-
() => window.removeEventListener("pagehide",
|
|
2290
|
+
() => window.removeEventListener("pagehide", n),
|
|
2278
2291
|
() => document.removeEventListener("visibilitychange", a),
|
|
2279
2292
|
() => {
|
|
2280
2293
|
this.visibilityChangeTimeout && (clearTimeout(this.visibilityChangeTimeout), this.visibilityChangeTimeout = null);
|
|
@@ -2282,9 +2295,9 @@ class Pt extends p {
|
|
|
2282
2295
|
);
|
|
2283
2296
|
}
|
|
2284
2297
|
}
|
|
2285
|
-
class
|
|
2286
|
-
constructor(e, t, s,
|
|
2287
|
-
super(), this.callbacks =
|
|
2298
|
+
class Pt extends p {
|
|
2299
|
+
constructor(e, t, s, n) {
|
|
2300
|
+
super(), this.callbacks = n, this.storageManager = e, this.projectId = t, this.tabId = $(), this.config = {
|
|
2288
2301
|
tabHeartbeatIntervalMs: qe,
|
|
2289
2302
|
tabElectionTimeoutMs: We,
|
|
2290
2303
|
debugMode: (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") ?? !1,
|
|
@@ -2323,7 +2336,7 @@ class Ht extends p {
|
|
|
2323
2336
|
if (!this.isBroadcastChannelSupported())
|
|
2324
2337
|
return null;
|
|
2325
2338
|
try {
|
|
2326
|
-
const e = new BroadcastChannel(
|
|
2339
|
+
const e = new BroadcastChannel(st(this.projectId));
|
|
2327
2340
|
return this.setupBroadcastListeners(e), e;
|
|
2328
2341
|
} catch (e) {
|
|
2329
2342
|
return this.config.debugMode && i.warn("CrossTabSession", "Failed to initialize BroadcastChannel", { error: e }), null;
|
|
@@ -2445,10 +2458,10 @@ class Ht extends p {
|
|
|
2445
2458
|
if (!this.sessionEnded && this.leaderTabId && !this.isTabLeader) {
|
|
2446
2459
|
const s = this.getStoredSessionContext();
|
|
2447
2460
|
if (s) {
|
|
2448
|
-
const
|
|
2449
|
-
|
|
2461
|
+
const n = Date.now() - s.lastActivity, a = this.config.tabHeartbeatIntervalMs * 3;
|
|
2462
|
+
n > a && (this.config.debugMode && i.warn(
|
|
2450
2463
|
"CrossTabSession",
|
|
2451
|
-
`Leader tab appears inactive (${
|
|
2464
|
+
`Leader tab appears inactive (${n}ms), attempting to become leader`
|
|
2452
2465
|
), this.leaderTabId = null, this.startLeaderElection());
|
|
2453
2466
|
}
|
|
2454
2467
|
}
|
|
@@ -2583,13 +2596,13 @@ class Ht extends p {
|
|
|
2583
2596
|
const e = Date.now(), t = this.lastHeartbeatSent ?? 0, s = this.config.tabHeartbeatIntervalMs * 0.8;
|
|
2584
2597
|
if (!this.isTabLeader && e - t < s)
|
|
2585
2598
|
return;
|
|
2586
|
-
const
|
|
2599
|
+
const n = {
|
|
2587
2600
|
type: "heartbeat",
|
|
2588
2601
|
tabId: this.tabId,
|
|
2589
2602
|
sessionId: this.tabInfo.sessionId,
|
|
2590
2603
|
timestamp: e
|
|
2591
2604
|
};
|
|
2592
|
-
this.broadcastChannel.postMessage(
|
|
2605
|
+
this.broadcastChannel.postMessage(n), this.lastHeartbeatSent = e;
|
|
2593
2606
|
}
|
|
2594
2607
|
/**
|
|
2595
2608
|
* Update tab info with current timestamp
|
|
@@ -2712,8 +2725,8 @@ class Ht extends p {
|
|
|
2712
2725
|
const e = this.getStoredSessionContext();
|
|
2713
2726
|
if (!e)
|
|
2714
2727
|
return this.get("config")?.sessionTimeout ?? R;
|
|
2715
|
-
const s = Date.now() - e.lastActivity,
|
|
2716
|
-
return Math.max(0,
|
|
2728
|
+
const s = Date.now() - e.lastActivity, n = this.get("config")?.sessionTimeout ?? R;
|
|
2729
|
+
return Math.max(0, n - s);
|
|
2717
2730
|
}
|
|
2718
2731
|
/**
|
|
2719
2732
|
* Update session activity from any tab
|
|
@@ -2729,7 +2742,7 @@ class Ht extends p {
|
|
|
2729
2742
|
this.heartbeatInterval && (clearInterval(this.heartbeatInterval), this.heartbeatInterval = null), this.electionTimeout && (clearTimeout(this.electionTimeout), this.electionTimeout = null), this.cleanupTimeout && (clearTimeout(this.cleanupTimeout), this.cleanupTimeout = null), this.fallbackLeadershipTimeout && (clearTimeout(this.fallbackLeadershipTimeout), this.fallbackLeadershipTimeout = null), this.electionDelayTimeout && (clearTimeout(this.electionDelayTimeout), this.electionDelayTimeout = null), this.tabInfoCleanupTimeout && (clearTimeout(this.tabInfoCleanupTimeout), this.tabInfoCleanupTimeout = null), this.closingAnnouncementTimeout && (clearTimeout(this.closingAnnouncementTimeout), this.closingAnnouncementTimeout = null), this.leaderHealthCheckInterval && (clearInterval(this.leaderHealthCheckInterval), this.leaderHealthCheckInterval = null), this.endSession("manual_stop"), this.broadcastChannel && this.broadcastChannel.close();
|
|
2730
2743
|
}
|
|
2731
2744
|
}
|
|
2732
|
-
class
|
|
2745
|
+
class Ht extends p {
|
|
2733
2746
|
eventManager;
|
|
2734
2747
|
storageManager;
|
|
2735
2748
|
sessionStorageKey;
|
|
@@ -2758,7 +2771,7 @@ class Dt extends p {
|
|
|
2758
2771
|
return typeof BroadcastChannel < "u" && typeof navigator < "u" && "serviceWorker" in navigator;
|
|
2759
2772
|
}
|
|
2760
2773
|
constructor(e, t) {
|
|
2761
|
-
super(), this.eventManager = t, this.storageManager = e, this.sessionStorageKey =
|
|
2774
|
+
super(), this.eventManager = t, this.storageManager = e, this.sessionStorageKey = tt(this.get("config")?.id);
|
|
2762
2775
|
const s = this.get("config")?.id;
|
|
2763
2776
|
s && this.initializeSessionRecoveryManager(s);
|
|
2764
2777
|
}
|
|
@@ -2771,16 +2784,16 @@ class Dt extends p {
|
|
|
2771
2784
|
const e = async () => {
|
|
2772
2785
|
if (this.crossTabSessionManager && this.crossTabSessionManager.updateSessionActivity(), !this.get("sessionId"))
|
|
2773
2786
|
try {
|
|
2774
|
-
const
|
|
2775
|
-
this.set("sessionId",
|
|
2776
|
-
sessionId:
|
|
2777
|
-
recovered:
|
|
2787
|
+
const n = await this.createOrJoinSession();
|
|
2788
|
+
this.set("sessionId", n.sessionId), i.info("SessionHandler", "🏁 Session started", {
|
|
2789
|
+
sessionId: n.sessionId,
|
|
2790
|
+
recovered: n.recovered,
|
|
2778
2791
|
crossTabActive: !!this.crossTabSessionManager
|
|
2779
|
-
}), this.trackSession(h.SESSION_START,
|
|
2780
|
-
} catch (
|
|
2792
|
+
}), this.trackSession(h.SESSION_START, n.recovered), this.persistSession(n.sessionId), this.startHeartbeat();
|
|
2793
|
+
} catch (n) {
|
|
2781
2794
|
i.error(
|
|
2782
2795
|
"SessionHandler",
|
|
2783
|
-
`Session creation failed: ${
|
|
2796
|
+
`Session creation failed: ${n instanceof Error ? n.message : "Unknown error"}`
|
|
2784
2797
|
), this.forceCleanupSession();
|
|
2785
2798
|
}
|
|
2786
2799
|
}, t = () => {
|
|
@@ -2789,17 +2802,17 @@ class Dt extends p {
|
|
|
2789
2802
|
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && i.debug("SessionHandler", "Session kept alive by cross-tab activity");
|
|
2790
2803
|
return;
|
|
2791
2804
|
}
|
|
2792
|
-
this.sessionManager.endSessionManaged("inactivity").then((
|
|
2805
|
+
this.sessionManager.endSessionManaged("inactivity").then((n) => {
|
|
2793
2806
|
i.info("SessionHandler", "🛑 Session ended by inactivity", {
|
|
2794
2807
|
sessionId: this.get("sessionId"),
|
|
2795
|
-
reason:
|
|
2796
|
-
success:
|
|
2797
|
-
eventsFlushed:
|
|
2808
|
+
reason: n.reason,
|
|
2809
|
+
success: n.success,
|
|
2810
|
+
eventsFlushed: n.eventsFlushed
|
|
2798
2811
|
}), this.crossTabSessionManager && this.crossTabSessionManager.endSession("inactivity"), this.clearPersistedSession(), this.stopHeartbeat();
|
|
2799
|
-
}).catch((
|
|
2812
|
+
}).catch((n) => {
|
|
2800
2813
|
i.error(
|
|
2801
2814
|
"SessionHandler",
|
|
2802
|
-
`Session end failed: ${
|
|
2815
|
+
`Session end failed: ${n instanceof Error ? n.message : "Unknown error"}`
|
|
2803
2816
|
), this.forceCleanupSession();
|
|
2804
2817
|
});
|
|
2805
2818
|
}
|
|
@@ -2809,7 +2822,7 @@ class Dt extends p {
|
|
|
2809
2822
|
syncTimeoutMs: pe.SYNC_TIMEOUT_MS,
|
|
2810
2823
|
maxRetries: pe.MAX_RETRY_ATTEMPTS
|
|
2811
2824
|
};
|
|
2812
|
-
this.sessionManager = new
|
|
2825
|
+
this.sessionManager = new Ut(
|
|
2813
2826
|
e,
|
|
2814
2827
|
t,
|
|
2815
2828
|
this.eventManager,
|
|
@@ -2852,7 +2865,7 @@ class Dt extends p {
|
|
|
2852
2865
|
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && i.warn("SessionHandler", "Cross-tab conflict detected"), this.sessionManager && this.sessionManager.trackSessionHealth("conflict");
|
|
2853
2866
|
}
|
|
2854
2867
|
};
|
|
2855
|
-
this._crossTabSessionManager = new
|
|
2868
|
+
this._crossTabSessionManager = new Pt(this.storageManager, e, t, l), i.debug("SessionHandler", "Cross-tab session manager initialized", { projectId: e });
|
|
2856
2869
|
}
|
|
2857
2870
|
async createOrJoinSession() {
|
|
2858
2871
|
if (this.crossTabSessionManager) {
|
|
@@ -2913,8 +2926,8 @@ class Dt extends p {
|
|
|
2913
2926
|
const e = this.storageManager.getItem(this.sessionStorageKey);
|
|
2914
2927
|
if (e)
|
|
2915
2928
|
try {
|
|
2916
|
-
const t = JSON.parse(e),
|
|
2917
|
-
if (
|
|
2929
|
+
const t = JSON.parse(e), n = Date.now() - t.lastHeartbeat, a = this.get("config")?.sessionTimeout ?? R;
|
|
2930
|
+
if (n > a) {
|
|
2918
2931
|
const o = this.recoveryManager?.hasRecoverableSession();
|
|
2919
2932
|
if (o && this.recoveryManager) {
|
|
2920
2933
|
const l = {
|
|
@@ -2966,7 +2979,7 @@ class Dt extends p {
|
|
|
2966
2979
|
this.heartbeatInterval && (clearInterval(this.heartbeatInterval), this.heartbeatInterval = null);
|
|
2967
2980
|
}
|
|
2968
2981
|
}
|
|
2969
|
-
class
|
|
2982
|
+
class Dt extends p {
|
|
2970
2983
|
eventManager;
|
|
2971
2984
|
onTrack;
|
|
2972
2985
|
originalPushState;
|
|
@@ -3017,7 +3030,7 @@ class xt extends p {
|
|
|
3017
3030
|
return Object.values(t).some((s) => !!s) ? t : void 0;
|
|
3018
3031
|
}
|
|
3019
3032
|
}
|
|
3020
|
-
class
|
|
3033
|
+
class xt extends p {
|
|
3021
3034
|
eventManager;
|
|
3022
3035
|
clickHandler;
|
|
3023
3036
|
constructor(e) {
|
|
@@ -3029,17 +3042,17 @@ class Ot extends p {
|
|
|
3029
3042
|
return;
|
|
3030
3043
|
}
|
|
3031
3044
|
i.debug("ClickHandler", "Starting click tracking"), this.clickHandler = (e) => {
|
|
3032
|
-
const t = e, s = t.target,
|
|
3033
|
-
if (!
|
|
3045
|
+
const t = e, s = t.target, n = s instanceof HTMLElement ? s : s instanceof Node && s.parentElement instanceof HTMLElement ? s.parentElement : null;
|
|
3046
|
+
if (!n) {
|
|
3034
3047
|
i.warn("ClickHandler", "Click target not found or not an element");
|
|
3035
3048
|
return;
|
|
3036
3049
|
}
|
|
3037
3050
|
i.info("ClickHandler", "🖱️ Click detected on element", {
|
|
3038
|
-
tagName:
|
|
3039
|
-
className:
|
|
3040
|
-
textContent:
|
|
3051
|
+
tagName: n.tagName,
|
|
3052
|
+
className: n.className || "none",
|
|
3053
|
+
textContent: n.textContent?.slice(0, 50) ?? "empty"
|
|
3041
3054
|
});
|
|
3042
|
-
const a = this.findTrackingElement(
|
|
3055
|
+
const a = this.findTrackingElement(n), o = this.getRelevantClickElement(n), l = this.calculateClickCoordinates(t, n);
|
|
3043
3056
|
if (a) {
|
|
3044
3057
|
const d = this.extractTrackingData(a);
|
|
3045
3058
|
if (d) {
|
|
@@ -3053,7 +3066,7 @@ class Ot extends p {
|
|
|
3053
3066
|
});
|
|
3054
3067
|
}
|
|
3055
3068
|
}
|
|
3056
|
-
const c = this.generateClickData(
|
|
3069
|
+
const c = this.generateClickData(n, o, l);
|
|
3057
3070
|
this.eventManager.track({
|
|
3058
3071
|
type: h.CLICK,
|
|
3059
3072
|
click_data: c
|
|
@@ -3093,8 +3106,8 @@ class Ot extends p {
|
|
|
3093
3106
|
return e;
|
|
3094
3107
|
}
|
|
3095
3108
|
calculateClickCoordinates(e, t) {
|
|
3096
|
-
const s = t.getBoundingClientRect(),
|
|
3097
|
-
return { x:
|
|
3109
|
+
const s = t.getBoundingClientRect(), n = e.clientX, a = e.clientY, o = s.width > 0 ? Math.max(0, Math.min(1, Number(((n - s.left) / s.width).toFixed(3)))) : 0, l = s.height > 0 ? Math.max(0, Math.min(1, Number(((a - s.top) / s.height).toFixed(3)))) : 0;
|
|
3110
|
+
return { x: n, y: a, relativeX: o, relativeY: l };
|
|
3098
3111
|
}
|
|
3099
3112
|
extractTrackingData(e) {
|
|
3100
3113
|
const t = e.getAttribute(`${z}-name`), s = e.getAttribute(`${z}-value`);
|
|
@@ -3106,9 +3119,9 @@ class Ot extends p {
|
|
|
3106
3119
|
};
|
|
3107
3120
|
}
|
|
3108
3121
|
generateClickData(e, t, s) {
|
|
3109
|
-
const { x:
|
|
3122
|
+
const { x: n, y: a, relativeX: o, relativeY: l } = s, c = this.getRelevantText(e, t), d = this.extractElementAttributes(t), u = t.getAttribute("href"), g = t.getAttribute("title"), y = t.getAttribute("alt"), I = t.getAttribute("role"), A = t.getAttribute("aria-label"), U = typeof t.className == "string" ? t.className : String(t.className);
|
|
3110
3123
|
return {
|
|
3111
|
-
x:
|
|
3124
|
+
x: n,
|
|
3112
3125
|
y: a,
|
|
3113
3126
|
relativeX: o,
|
|
3114
3127
|
relativeY: l,
|
|
@@ -3125,19 +3138,19 @@ class Ot extends p {
|
|
|
3125
3138
|
};
|
|
3126
3139
|
}
|
|
3127
3140
|
getRelevantText(e, t) {
|
|
3128
|
-
const s = ["main", "section", "article", "body", "html", "header", "footer", "aside", "nav"],
|
|
3129
|
-
if (!
|
|
3141
|
+
const s = ["main", "section", "article", "body", "html", "header", "footer", "aside", "nav"], n = e.textContent?.trim() ?? "", a = t.textContent?.trim() ?? "";
|
|
3142
|
+
if (!n && !a)
|
|
3130
3143
|
return "";
|
|
3131
|
-
if (
|
|
3132
|
-
return
|
|
3144
|
+
if (n && n.length <= _)
|
|
3145
|
+
return n;
|
|
3133
3146
|
const o = s.includes(t.tagName.toLowerCase()), l = a.length > _ * 2;
|
|
3134
|
-
return o && l ?
|
|
3147
|
+
return o && l ? n && n.length <= _ ? n : "" : a.length <= _ ? a : n && n.length < a.length * 0.1 ? n.length <= _ ? n : n.slice(0, _ - 3) + "..." : a.slice(0, _ - 3) + "...";
|
|
3135
3148
|
}
|
|
3136
3149
|
extractElementAttributes(e) {
|
|
3137
3150
|
const t = ["id", "class", "data-testid", "aria-label", "title", "href", "type", "name"], s = {};
|
|
3138
|
-
for (const
|
|
3139
|
-
const a = e.getAttribute(
|
|
3140
|
-
a && (s[
|
|
3151
|
+
for (const n of t) {
|
|
3152
|
+
const a = e.getAttribute(n);
|
|
3153
|
+
a && (s[n] = a);
|
|
3141
3154
|
}
|
|
3142
3155
|
return s;
|
|
3143
3156
|
}
|
|
@@ -3148,7 +3161,7 @@ class Ot extends p {
|
|
|
3148
3161
|
};
|
|
3149
3162
|
}
|
|
3150
3163
|
}
|
|
3151
|
-
class
|
|
3164
|
+
class Ot extends p {
|
|
3152
3165
|
eventManager;
|
|
3153
3166
|
containers = [];
|
|
3154
3167
|
constructor(e) {
|
|
@@ -3157,10 +3170,10 @@ class Ft extends p {
|
|
|
3157
3170
|
startTracking() {
|
|
3158
3171
|
const e = this.get("config").scrollContainerSelectors, t = Array.isArray(e) ? e : typeof e == "string" ? [e] : [];
|
|
3159
3172
|
i.debug("ScrollHandler", "Starting scroll tracking", { selectorsCount: t.length });
|
|
3160
|
-
const s = t.map((
|
|
3173
|
+
const s = t.map((n) => this.safeQuerySelector(n)).filter((n) => n instanceof HTMLElement);
|
|
3161
3174
|
s.length === 0 && s.push(window);
|
|
3162
|
-
for (const
|
|
3163
|
-
this.setupScrollContainer(
|
|
3175
|
+
for (const n of s)
|
|
3176
|
+
this.setupScrollContainer(n);
|
|
3164
3177
|
}
|
|
3165
3178
|
stopTracking() {
|
|
3166
3179
|
i.debug("ScrollHandler", "Stopping scroll tracking", { containersCount: this.containers.length });
|
|
@@ -3183,21 +3196,21 @@ class Ft extends p {
|
|
|
3183
3196
|
return;
|
|
3184
3197
|
}
|
|
3185
3198
|
t.debounceTimer && clearTimeout(t.debounceTimer), t.debounceTimer = window.setTimeout(() => {
|
|
3186
|
-
const
|
|
3187
|
-
|
|
3199
|
+
const n = this.calculateScrollData(t);
|
|
3200
|
+
n && this.eventManager.track({
|
|
3188
3201
|
type: h.SCROLL,
|
|
3189
|
-
scroll_data:
|
|
3202
|
+
scroll_data: n
|
|
3190
3203
|
}), t.debounceTimer = null;
|
|
3191
3204
|
}, Me);
|
|
3192
3205
|
};
|
|
3193
3206
|
t.listener = s, this.containers.push(t), e instanceof Window ? window.addEventListener("scroll", s, { passive: !0 }) : e.addEventListener("scroll", s, { passive: !0 });
|
|
3194
3207
|
}
|
|
3195
3208
|
calculateScrollData(e) {
|
|
3196
|
-
const { element: t, lastScrollPos: s } = e,
|
|
3209
|
+
const { element: t, lastScrollPos: s } = e, n = this.getScrollTop(t), a = this.getViewportHeight(t), o = this.getScrollHeight(t);
|
|
3197
3210
|
if (t === window && o <= a)
|
|
3198
3211
|
return null;
|
|
3199
|
-
const l =
|
|
3200
|
-
return Math.abs(
|
|
3212
|
+
const l = n > s ? j.DOWN : j.UP, c = o > a ? Math.min(100, Math.max(0, Math.floor(n / (o - a) * 100))) : 0;
|
|
3213
|
+
return Math.abs(n - s) < Ue ? null : (e.lastScrollPos = n, { depth: c, direction: l });
|
|
3201
3214
|
}
|
|
3202
3215
|
getScrollTop(e) {
|
|
3203
3216
|
return e instanceof Window ? window.scrollY : e.scrollTop;
|
|
@@ -3209,8 +3222,8 @@ class Ft extends p {
|
|
|
3209
3222
|
return e instanceof Window ? document.documentElement.scrollHeight : e.scrollHeight;
|
|
3210
3223
|
}
|
|
3211
3224
|
isElementScrollable(e) {
|
|
3212
|
-
const t = getComputedStyle(e), s = t.overflowY === "auto" || t.overflowY === "scroll" || t.overflowX === "auto" || t.overflowX === "scroll" || t.overflow === "auto" || t.overflow === "scroll",
|
|
3213
|
-
return s &&
|
|
3225
|
+
const t = getComputedStyle(e), s = t.overflowY === "auto" || t.overflowY === "scroll" || t.overflowX === "auto" || t.overflowX === "scroll" || t.overflow === "auto" || t.overflow === "scroll", n = e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth;
|
|
3226
|
+
return s && n;
|
|
3214
3227
|
}
|
|
3215
3228
|
safeQuerySelector(e) {
|
|
3216
3229
|
try {
|
|
@@ -3223,7 +3236,7 @@ class Ft extends p {
|
|
|
3223
3236
|
}
|
|
3224
3237
|
}
|
|
3225
3238
|
}
|
|
3226
|
-
class
|
|
3239
|
+
class Ft extends p {
|
|
3227
3240
|
isInitialized = !1;
|
|
3228
3241
|
constructor() {
|
|
3229
3242
|
super();
|
|
@@ -3308,19 +3321,19 @@ class zt extends p {
|
|
|
3308
3321
|
async loadScript(e) {
|
|
3309
3322
|
return new Promise((t, s) => {
|
|
3310
3323
|
try {
|
|
3311
|
-
const
|
|
3312
|
-
|
|
3324
|
+
const n = document.createElement("script");
|
|
3325
|
+
n.id = "tracelog-ga-script", n.async = !0, n.src = `https://www.googletagmanager.com/gtag/js?id=${e}`, n.onload = () => {
|
|
3313
3326
|
t();
|
|
3314
|
-
},
|
|
3327
|
+
}, n.onerror = () => {
|
|
3315
3328
|
const a = new Error("Failed to load Google Analytics script");
|
|
3316
3329
|
i.error("GoogleAnalytics", "Google Analytics script load failed", {
|
|
3317
3330
|
measurementId: e,
|
|
3318
3331
|
error: a.message,
|
|
3319
|
-
scriptSrc:
|
|
3332
|
+
scriptSrc: n.src
|
|
3320
3333
|
}), s(a);
|
|
3321
|
-
}, document.head.appendChild(
|
|
3322
|
-
} catch (
|
|
3323
|
-
const a =
|
|
3334
|
+
}, document.head.appendChild(n);
|
|
3335
|
+
} catch (n) {
|
|
3336
|
+
const a = n instanceof Error ? n : new Error(String(n));
|
|
3324
3337
|
i.error("GoogleAnalytics", "Error creating Google Analytics script", {
|
|
3325
3338
|
measurementId: e,
|
|
3326
3339
|
error: a.message
|
|
@@ -3348,7 +3361,7 @@ class zt extends p {
|
|
|
3348
3361
|
}
|
|
3349
3362
|
}
|
|
3350
3363
|
}
|
|
3351
|
-
class
|
|
3364
|
+
class zt {
|
|
3352
3365
|
storage = null;
|
|
3353
3366
|
fallbackStorage = /* @__PURE__ */ new Map();
|
|
3354
3367
|
storageAvailable = !1;
|
|
@@ -3403,7 +3416,7 @@ class Vt {
|
|
|
3403
3416
|
}
|
|
3404
3417
|
}
|
|
3405
3418
|
}
|
|
3406
|
-
class
|
|
3419
|
+
class Vt extends p {
|
|
3407
3420
|
eventManager;
|
|
3408
3421
|
reportedByNav = /* @__PURE__ */ new Map();
|
|
3409
3422
|
observers = [];
|
|
@@ -3433,8 +3446,8 @@ class $t extends p {
|
|
|
3433
3446
|
this.reportTTFB(), this.safeObserve(
|
|
3434
3447
|
"largest-contentful-paint",
|
|
3435
3448
|
(t) => {
|
|
3436
|
-
const s = t.getEntries(),
|
|
3437
|
-
|
|
3449
|
+
const s = t.getEntries(), n = s[s.length - 1];
|
|
3450
|
+
n && this.sendVital({ type: "LCP", value: Number(n.startTime.toFixed(N)) });
|
|
3438
3451
|
},
|
|
3439
3452
|
{ type: "largest-contentful-paint", buffered: !0 },
|
|
3440
3453
|
!0
|
|
@@ -3444,10 +3457,10 @@ class $t extends p {
|
|
|
3444
3457
|
"layout-shift",
|
|
3445
3458
|
(t) => {
|
|
3446
3459
|
const s = t.getEntries();
|
|
3447
|
-
for (const
|
|
3448
|
-
if (
|
|
3460
|
+
for (const n of s) {
|
|
3461
|
+
if (n.hadRecentInput === !0)
|
|
3449
3462
|
continue;
|
|
3450
|
-
const a = typeof
|
|
3463
|
+
const a = typeof n.value == "number" ? n.value : 0;
|
|
3451
3464
|
e += a;
|
|
3452
3465
|
}
|
|
3453
3466
|
this.sendVital({ type: "CLS", value: Number(e.toFixed(Pe)) });
|
|
@@ -3465,8 +3478,8 @@ class $t extends p {
|
|
|
3465
3478
|
"event",
|
|
3466
3479
|
(t) => {
|
|
3467
3480
|
let s = 0;
|
|
3468
|
-
const
|
|
3469
|
-
for (const a of
|
|
3481
|
+
const n = t.getEntries();
|
|
3482
|
+
for (const a of n) {
|
|
3470
3483
|
const o = (a.processingEnd ?? 0) - (a.startTime ?? 0);
|
|
3471
3484
|
s = Math.max(s, o);
|
|
3472
3485
|
}
|
|
@@ -3477,11 +3490,11 @@ class $t extends p {
|
|
|
3477
3490
|
}
|
|
3478
3491
|
async initWebVitals() {
|
|
3479
3492
|
try {
|
|
3480
|
-
const { onLCP: e, onCLS: t, onFCP: s, onTTFB:
|
|
3493
|
+
const { onLCP: e, onCLS: t, onFCP: s, onTTFB: n, onINP: a } = await import("./web-vitals-CCnqwnC8.mjs"), o = (l) => (c) => {
|
|
3481
3494
|
const d = Number(c.value.toFixed(N));
|
|
3482
3495
|
this.sendVital({ type: l, value: d });
|
|
3483
3496
|
};
|
|
3484
|
-
e(o("LCP")), t(o("CLS")), s(o("FCP")),
|
|
3497
|
+
e(o("LCP")), t(o("CLS")), s(o("FCP")), n(o("TTFB")), a(o("INP"));
|
|
3485
3498
|
} catch (e) {
|
|
3486
3499
|
i.warn("PerformanceHandler", "Failed to load web-vitals library, using fallback", {
|
|
3487
3500
|
error: e instanceof Error ? e.message : "Unknown error"
|
|
@@ -3509,8 +3522,8 @@ class $t extends p {
|
|
|
3509
3522
|
(e) => {
|
|
3510
3523
|
const t = e.getEntries();
|
|
3511
3524
|
for (const s of t) {
|
|
3512
|
-
const
|
|
3513
|
-
a - this.lastLongTaskSentAt >= Be && (this.trackWebVital("LONG_TASK",
|
|
3525
|
+
const n = Number(s.duration.toFixed(N)), a = Date.now();
|
|
3526
|
+
a - this.lastLongTaskSentAt >= Be && (this.trackWebVital("LONG_TASK", n), this.lastLongTaskSentAt = a);
|
|
3514
3527
|
}
|
|
3515
3528
|
},
|
|
3516
3529
|
{ type: "longtask", buffered: !0 }
|
|
@@ -3520,10 +3533,10 @@ class $t extends p {
|
|
|
3520
3533
|
const t = this.getNavigationId(), s = `${e.type}`;
|
|
3521
3534
|
if (t) {
|
|
3522
3535
|
this.reportedByNav.has(t) || this.reportedByNav.set(t, /* @__PURE__ */ new Set());
|
|
3523
|
-
const
|
|
3524
|
-
if (
|
|
3536
|
+
const n = this.reportedByNav.get(t);
|
|
3537
|
+
if (n.has(s))
|
|
3525
3538
|
return;
|
|
3526
|
-
|
|
3539
|
+
n.add(s);
|
|
3527
3540
|
}
|
|
3528
3541
|
this.trackWebVital(e.type, e.value);
|
|
3529
3542
|
}
|
|
@@ -3550,19 +3563,19 @@ class $t extends p {
|
|
|
3550
3563
|
}), null;
|
|
3551
3564
|
}
|
|
3552
3565
|
}
|
|
3553
|
-
safeObserve(e, t, s,
|
|
3566
|
+
safeObserve(e, t, s, n = !1) {
|
|
3554
3567
|
try {
|
|
3555
3568
|
if (typeof PerformanceObserver > "u") return;
|
|
3556
3569
|
const a = PerformanceObserver.supportedEntryTypes;
|
|
3557
3570
|
if (a && !a.includes(e)) return;
|
|
3558
3571
|
const o = new PerformanceObserver((l, c) => {
|
|
3559
|
-
if (t(l, c),
|
|
3572
|
+
if (t(l, c), n)
|
|
3560
3573
|
try {
|
|
3561
3574
|
c.disconnect();
|
|
3562
3575
|
} catch {
|
|
3563
3576
|
}
|
|
3564
3577
|
});
|
|
3565
|
-
o.observe(s ?? { type: e, buffered: !0 }),
|
|
3578
|
+
o.observe(s ?? { type: e, buffered: !0 }), n || this.observers.push(o);
|
|
3566
3579
|
} catch (a) {
|
|
3567
3580
|
i.warn("PerformanceHandler", "Failed to create performance observer", {
|
|
3568
3581
|
type: e,
|
|
@@ -3571,7 +3584,7 @@ class $t extends p {
|
|
|
3571
3584
|
}
|
|
3572
3585
|
}
|
|
3573
3586
|
}
|
|
3574
|
-
class
|
|
3587
|
+
class $t extends p {
|
|
3575
3588
|
eventManager;
|
|
3576
3589
|
piiPatterns = [
|
|
3577
3590
|
/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
|
|
@@ -3648,7 +3661,7 @@ class jt extends p {
|
|
|
3648
3661
|
return Math.random() < e;
|
|
3649
3662
|
}
|
|
3650
3663
|
}
|
|
3651
|
-
class
|
|
3664
|
+
class jt extends p {
|
|
3652
3665
|
eventManager;
|
|
3653
3666
|
originalFetch;
|
|
3654
3667
|
originalXHROpen;
|
|
@@ -3664,17 +3677,17 @@ class Gt extends p {
|
|
|
3664
3677
|
}
|
|
3665
3678
|
interceptFetch() {
|
|
3666
3679
|
window.fetch = async (e, t) => {
|
|
3667
|
-
const s = Date.now(),
|
|
3680
|
+
const s = Date.now(), n = typeof e == "string" ? e : e.toString(), a = t?.method ?? "GET";
|
|
3668
3681
|
try {
|
|
3669
3682
|
const o = await this.originalFetch(e, t), l = Date.now() - s;
|
|
3670
3683
|
return o.ok || (i.debug("NetworkHandler", "Fetch error detected", {
|
|
3671
3684
|
method: a,
|
|
3672
|
-
url: this.normalizeUrlForTracking(
|
|
3685
|
+
url: this.normalizeUrlForTracking(n),
|
|
3673
3686
|
status: o.status,
|
|
3674
3687
|
statusText: o.statusText
|
|
3675
3688
|
}), this.trackNetworkError(
|
|
3676
3689
|
a.toUpperCase(),
|
|
3677
|
-
this.normalizeUrlForTracking(
|
|
3690
|
+
this.normalizeUrlForTracking(n),
|
|
3678
3691
|
o.status,
|
|
3679
3692
|
o.statusText,
|
|
3680
3693
|
l
|
|
@@ -3683,11 +3696,11 @@ class Gt extends p {
|
|
|
3683
3696
|
const l = Date.now() - s, c = o instanceof Error ? o.message : "Network Error";
|
|
3684
3697
|
throw i.debug("NetworkHandler", "Fetch exception caught", {
|
|
3685
3698
|
method: a,
|
|
3686
|
-
url: this.normalizeUrlForTracking(
|
|
3699
|
+
url: this.normalizeUrlForTracking(n),
|
|
3687
3700
|
error: c
|
|
3688
3701
|
}), this.trackNetworkError(
|
|
3689
3702
|
a.toUpperCase(),
|
|
3690
|
-
this.normalizeUrlForTracking(
|
|
3703
|
+
this.normalizeUrlForTracking(n),
|
|
3691
3704
|
void 0,
|
|
3692
3705
|
c,
|
|
3693
3706
|
l
|
|
@@ -3696,7 +3709,7 @@ class Gt extends p {
|
|
|
3696
3709
|
};
|
|
3697
3710
|
}
|
|
3698
3711
|
interceptXHR() {
|
|
3699
|
-
const e = this.trackNetworkError.bind(this), t = this.normalizeUrlForTracking.bind(this), s = this.originalXHROpen,
|
|
3712
|
+
const e = this.trackNetworkError.bind(this), t = this.normalizeUrlForTracking.bind(this), s = this.originalXHROpen, n = this.originalXHRSend;
|
|
3700
3713
|
XMLHttpRequest.prototype.open = function(a, o, l, c, d) {
|
|
3701
3714
|
const u = l ?? !0, g = this;
|
|
3702
3715
|
return g._tracelogStartTime = Date.now(), g._tracelogMethod = a.toUpperCase(), g._tracelogUrl = o.toString(), s.call(this, a, o, u, c, d);
|
|
@@ -3717,10 +3730,10 @@ class Gt extends p {
|
|
|
3717
3730
|
}
|
|
3718
3731
|
if (u)
|
|
3719
3732
|
return u.call(o, g);
|
|
3720
|
-
},
|
|
3733
|
+
}, n.call(this, a);
|
|
3721
3734
|
};
|
|
3722
3735
|
}
|
|
3723
|
-
trackNetworkError(e, t, s,
|
|
3736
|
+
trackNetworkError(e, t, s, n, a) {
|
|
3724
3737
|
const o = this.get("config");
|
|
3725
3738
|
if (!this.shouldSample(o?.errorSampling ?? 0.1)) {
|
|
3726
3739
|
i.debug(
|
|
@@ -3736,17 +3749,17 @@ class Gt extends p {
|
|
|
3736
3749
|
}
|
|
3737
3750
|
i.warn(
|
|
3738
3751
|
"NetworkHandler",
|
|
3739
|
-
`Network error tracked: ${e} ${t} (status: ${s}, statusText: ${
|
|
3740
|
-
{ method: e, url: t, status: s, statusText:
|
|
3752
|
+
`Network error tracked: ${e} ${t} (status: ${s}, statusText: ${n}, duration: ${a}ms)`,
|
|
3753
|
+
{ method: e, url: t, status: s, statusText: n, duration: a }
|
|
3741
3754
|
), this.eventManager.track({
|
|
3742
3755
|
type: h.ERROR,
|
|
3743
3756
|
error_data: {
|
|
3744
3757
|
type: D.NETWORK_ERROR,
|
|
3745
|
-
message:
|
|
3758
|
+
message: n,
|
|
3746
3759
|
method: e,
|
|
3747
3760
|
url: t,
|
|
3748
3761
|
status: s,
|
|
3749
|
-
statusText:
|
|
3762
|
+
statusText: n,
|
|
3750
3763
|
duration: a
|
|
3751
3764
|
}
|
|
3752
3765
|
});
|
|
@@ -3763,7 +3776,7 @@ class Gt extends p {
|
|
|
3763
3776
|
return Math.random() < e;
|
|
3764
3777
|
}
|
|
3765
3778
|
}
|
|
3766
|
-
class
|
|
3779
|
+
class Gt extends p {
|
|
3767
3780
|
isInitialized = !1;
|
|
3768
3781
|
googleAnalytics = null;
|
|
3769
3782
|
storageManager;
|
|
@@ -3815,7 +3828,7 @@ class Qt extends p {
|
|
|
3815
3828
|
i.warn("App", "Custom event attempted before eventManager initialization", { eventName: e });
|
|
3816
3829
|
return;
|
|
3817
3830
|
}
|
|
3818
|
-
const { valid: s, error:
|
|
3831
|
+
const { valid: s, error: n, sanitizedMetadata: a } = vt(e, t);
|
|
3819
3832
|
if (s)
|
|
3820
3833
|
i.debug("App", "Custom event validated and queued", { eventName: e, hasMetadata: !!a }), this.eventManager.track({
|
|
3821
3834
|
type: h.CUSTOM,
|
|
@@ -3826,14 +3839,14 @@ class Qt extends p {
|
|
|
3826
3839
|
});
|
|
3827
3840
|
else {
|
|
3828
3841
|
const o = this.get("config")?.mode;
|
|
3829
|
-
if (i.clientError("App", `Custom event validation failed: ${
|
|
3842
|
+
if (i.clientError("App", `Custom event validation failed: ${n ?? "unknown error"}`, {
|
|
3830
3843
|
eventName: e,
|
|
3831
|
-
validationError:
|
|
3844
|
+
validationError: n,
|
|
3832
3845
|
hasMetadata: !!t,
|
|
3833
3846
|
mode: o
|
|
3834
3847
|
}), o === "qa" || o === "debug")
|
|
3835
3848
|
throw new Error(
|
|
3836
|
-
`custom event "${e}" validation failed (${
|
|
3849
|
+
`custom event "${e}" validation failed (${n ?? "unknown error"}). Please, review your event data and try again.`
|
|
3837
3850
|
);
|
|
3838
3851
|
}
|
|
3839
3852
|
}
|
|
@@ -3848,15 +3861,15 @@ class Qt extends p {
|
|
|
3848
3861
|
this.setApiUrl(e.id, e.allowHttp), await this.setConfig(e), this.setUserId(), this.setDevice(), this.setPageUrl();
|
|
3849
3862
|
}
|
|
3850
3863
|
setApiUrl(e, t = !1) {
|
|
3851
|
-
const s = new
|
|
3864
|
+
const s = new bt();
|
|
3852
3865
|
this.set("apiUrl", s.getUrl(e, t));
|
|
3853
3866
|
}
|
|
3854
3867
|
async setConfig(e) {
|
|
3855
|
-
const s = await new
|
|
3868
|
+
const s = await new Et().get(this.get("apiUrl"), e);
|
|
3856
3869
|
this.set("config", s);
|
|
3857
3870
|
}
|
|
3858
3871
|
setUserId() {
|
|
3859
|
-
const t = new
|
|
3872
|
+
const t = new At(this.storageManager).getId();
|
|
3860
3873
|
this.set("userId", t);
|
|
3861
3874
|
}
|
|
3862
3875
|
setDevice() {
|
|
@@ -3869,7 +3882,7 @@ class Qt extends p {
|
|
|
3869
3882
|
}
|
|
3870
3883
|
async setIntegrations() {
|
|
3871
3884
|
const e = this.get("config").ipExcluded, t = this.get("config").integrations?.googleAnalytics?.measurementId;
|
|
3872
|
-
!e && t?.trim() && (this.googleAnalytics = new
|
|
3885
|
+
!e && t?.trim() && (this.googleAnalytics = new Ft(), await this.googleAnalytics.initialize());
|
|
3873
3886
|
}
|
|
3874
3887
|
async initHandlers() {
|
|
3875
3888
|
if (!this.eventManager)
|
|
@@ -3879,56 +3892,56 @@ class Qt extends p {
|
|
|
3879
3892
|
this.initSessionHandler(), this.initPageViewHandler(), this.initClickHandler(), this.initScrollHandler(), await this.initPerformanceHandler(), this.initErrorHandler(), this.initNetworkHandler();
|
|
3880
3893
|
}
|
|
3881
3894
|
initStorage() {
|
|
3882
|
-
this.storageManager = new
|
|
3895
|
+
this.storageManager = new zt();
|
|
3883
3896
|
}
|
|
3884
3897
|
setEventManager() {
|
|
3885
3898
|
if (!this.storageManager)
|
|
3886
3899
|
throw new Error("StorageManager must be initialized before EventManager");
|
|
3887
|
-
this.eventManager = new
|
|
3900
|
+
this.eventManager = new Mt(this.storageManager, this.googleAnalytics);
|
|
3888
3901
|
}
|
|
3889
3902
|
initSessionHandler() {
|
|
3890
3903
|
if (!this.storageManager || !this.eventManager)
|
|
3891
3904
|
throw new Error("StorageManager and EventManager must be initialized before SessionHandler");
|
|
3892
|
-
this.sessionHandler = new
|
|
3905
|
+
this.sessionHandler = new Ht(this.storageManager, this.eventManager), this.sessionHandler.startTracking();
|
|
3893
3906
|
}
|
|
3894
3907
|
initPageViewHandler() {
|
|
3895
3908
|
if (!this.eventManager)
|
|
3896
3909
|
throw new Error("EventManager must be initialized before PageViewHandler");
|
|
3897
3910
|
const e = () => this.onPageViewTrack();
|
|
3898
|
-
this.pageViewHandler = new
|
|
3911
|
+
this.pageViewHandler = new Dt(this.eventManager, e), this.pageViewHandler.startTracking();
|
|
3899
3912
|
}
|
|
3900
3913
|
onPageViewTrack() {
|
|
3901
3914
|
this.set("suppressNextScroll", !0), this.suppressNextScrollTimer && (clearTimeout(this.suppressNextScrollTimer), this.suppressNextScrollTimer = null), this.suppressNextScrollTimer = window.setTimeout(() => {
|
|
3902
3915
|
this.set("suppressNextScroll", !1);
|
|
3903
|
-
}, Me *
|
|
3916
|
+
}, Me * Ze.SUPPRESS_MULTIPLIER);
|
|
3904
3917
|
}
|
|
3905
3918
|
initClickHandler() {
|
|
3906
3919
|
if (!this.eventManager)
|
|
3907
3920
|
throw new Error("EventManager must be initialized before ClickHandler");
|
|
3908
|
-
this.clickHandler = new
|
|
3921
|
+
this.clickHandler = new xt(this.eventManager), this.clickHandler.startTracking();
|
|
3909
3922
|
}
|
|
3910
3923
|
initScrollHandler() {
|
|
3911
3924
|
if (!this.eventManager)
|
|
3912
3925
|
throw new Error("EventManager must be initialized before ScrollHandler");
|
|
3913
|
-
this.scrollHandler = new
|
|
3926
|
+
this.scrollHandler = new Ot(this.eventManager), this.scrollHandler.startTracking();
|
|
3914
3927
|
}
|
|
3915
3928
|
async initPerformanceHandler() {
|
|
3916
3929
|
if (!this.eventManager)
|
|
3917
3930
|
throw new Error("EventManager must be initialized before PerformanceHandler");
|
|
3918
|
-
this.performanceHandler = new
|
|
3931
|
+
this.performanceHandler = new Vt(this.eventManager), await this.performanceHandler.startTracking();
|
|
3919
3932
|
}
|
|
3920
3933
|
initErrorHandler() {
|
|
3921
3934
|
if (!this.eventManager)
|
|
3922
3935
|
throw new Error("EventManager must be initialized before ErrorHandler");
|
|
3923
|
-
this.errorHandler = new
|
|
3936
|
+
this.errorHandler = new $t(this.eventManager), this.errorHandler.startTracking();
|
|
3924
3937
|
}
|
|
3925
3938
|
initNetworkHandler() {
|
|
3926
3939
|
if (!this.eventManager)
|
|
3927
3940
|
throw new Error("EventManager must be initialized before NetworkHandler");
|
|
3928
|
-
this.networkHandler = new
|
|
3941
|
+
this.networkHandler = new jt(this.eventManager), this.networkHandler.startTracking();
|
|
3929
3942
|
}
|
|
3930
3943
|
}
|
|
3931
|
-
const
|
|
3944
|
+
const Qt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3932
3945
|
__proto__: null,
|
|
3933
3946
|
DeviceType: E,
|
|
3934
3947
|
ErrorType: D,
|
|
@@ -3938,14 +3951,14 @@ const Bt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
3938
3951
|
TagConditionOperator: f,
|
|
3939
3952
|
TagConditionType: m,
|
|
3940
3953
|
TagLogicalOperator: G
|
|
3941
|
-
}, Symbol.toStringTag, { value: "Module" })),
|
|
3954
|
+
}, Symbol.toStringTag, { value: "Module" })), Bt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3942
3955
|
__proto__: null,
|
|
3943
3956
|
DEFAULT_SESSION_TIMEOUT_MS: R
|
|
3944
3957
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
3945
3958
|
let v = null, T = !1;
|
|
3946
|
-
const
|
|
3959
|
+
const qt = async (r) => {
|
|
3947
3960
|
try {
|
|
3948
|
-
if (i.info("API", "Library initialization started", { id:
|
|
3961
|
+
if (i.info("API", "Library initialization started", { id: r.id }), typeof window > "u" || typeof document > "u")
|
|
3949
3962
|
throw i.clientError(
|
|
3950
3963
|
"API",
|
|
3951
3964
|
"Browser environment required - this library can only be used in a browser environment",
|
|
@@ -3956,34 +3969,34 @@ const Wt = async (n) => {
|
|
|
3956
3969
|
), new Error("This library can only be used in a browser environment");
|
|
3957
3970
|
if (v) {
|
|
3958
3971
|
i.debug("API", "Library already initialized, skipping duplicate initialization", {
|
|
3959
|
-
projectId:
|
|
3972
|
+
projectId: r.id
|
|
3960
3973
|
});
|
|
3961
3974
|
return;
|
|
3962
3975
|
}
|
|
3963
3976
|
if (T) {
|
|
3964
|
-
i.debug("API", "Concurrent initialization detected, waiting for completion", { projectId:
|
|
3977
|
+
i.debug("API", "Concurrent initialization detected, waiting for completion", { projectId: r.id });
|
|
3965
3978
|
let s = 0;
|
|
3966
|
-
const
|
|
3967
|
-
for (; T && s <
|
|
3979
|
+
const n = me.MAX_CONCURRENT_RETRIES, a = me.CONCURRENT_RETRY_DELAY_MS;
|
|
3980
|
+
for (; T && s < n; )
|
|
3968
3981
|
await new Promise((o) => setTimeout(o, a)), s++;
|
|
3969
3982
|
if (v) {
|
|
3970
3983
|
i.debug("API", "Concurrent initialization completed successfully", {
|
|
3971
|
-
projectId:
|
|
3984
|
+
projectId: r.id,
|
|
3972
3985
|
retriesUsed: s
|
|
3973
3986
|
});
|
|
3974
3987
|
return;
|
|
3975
3988
|
}
|
|
3976
3989
|
if (T)
|
|
3977
3990
|
throw i.error("API", "Initialization timeout - concurrent initialization took too long", {
|
|
3978
|
-
projectId:
|
|
3991
|
+
projectId: r.id,
|
|
3979
3992
|
retriesUsed: s,
|
|
3980
|
-
maxRetries:
|
|
3993
|
+
maxRetries: n
|
|
3981
3994
|
}), new Error("App initialization timeout - concurrent initialization took too long");
|
|
3982
3995
|
}
|
|
3983
|
-
T = !0, i.debug("API", "Validating and normalizing configuration", { projectId:
|
|
3984
|
-
const e =
|
|
3996
|
+
T = !0, i.debug("API", "Validating and normalizing configuration", { projectId: r.id });
|
|
3997
|
+
const e = dt(r);
|
|
3985
3998
|
i.debug("API", "Creating App instance", { projectId: e.id });
|
|
3986
|
-
const t = new
|
|
3999
|
+
const t = new Gt();
|
|
3987
4000
|
await t.init(e), v = t, i.info("API", "Library initialization completed successfully", {
|
|
3988
4001
|
projectId: e.id
|
|
3989
4002
|
});
|
|
@@ -3998,44 +4011,44 @@ const Wt = async (n) => {
|
|
|
3998
4011
|
} finally {
|
|
3999
4012
|
T = !1;
|
|
4000
4013
|
}
|
|
4001
|
-
},
|
|
4014
|
+
}, Wt = (r, e) => {
|
|
4002
4015
|
try {
|
|
4003
4016
|
if (!v)
|
|
4004
4017
|
throw i.clientError("API", "Custom event failed - Library not initialized. Please call TraceLog.init() first", {
|
|
4005
|
-
eventName:
|
|
4018
|
+
eventName: r,
|
|
4006
4019
|
hasMetadata: !!e
|
|
4007
4020
|
}), new Error("App not initialized");
|
|
4008
4021
|
i.debug("API", "Sending custom event", {
|
|
4009
|
-
eventName:
|
|
4022
|
+
eventName: r,
|
|
4010
4023
|
hasMetadata: !!e,
|
|
4011
4024
|
metadataKeys: e ? Object.keys(e) : []
|
|
4012
|
-
}), v.sendCustomEvent(
|
|
4025
|
+
}), v.sendCustomEvent(r, e);
|
|
4013
4026
|
} catch (t) {
|
|
4014
|
-
if (i.error("API", "Event tracking failed", { eventName:
|
|
4027
|
+
if (i.error("API", "Event tracking failed", { eventName: r, error: t, hasMetadata: !!e }), t instanceof Error && (t.message === "App not initialized" || t.message.includes("validation failed")))
|
|
4015
4028
|
throw t;
|
|
4016
4029
|
}
|
|
4017
|
-
},
|
|
4030
|
+
}, Xt = () => v !== null, Kt = () => ({
|
|
4018
4031
|
isInitialized: v !== null,
|
|
4019
4032
|
isInitializing: T,
|
|
4020
4033
|
hasInstance: v !== null
|
|
4021
|
-
}),
|
|
4034
|
+
}), Yt = () => {
|
|
4022
4035
|
try {
|
|
4023
4036
|
if (i.info("API", "Library cleanup initiated"), !v)
|
|
4024
4037
|
throw i.warn("API", "Cleanup called but Library was not initialized"), new Error("App not initialized");
|
|
4025
4038
|
v.destroy(), v = null, T = !1, i.info("API", "Library cleanup completed successfully");
|
|
4026
|
-
} catch (
|
|
4027
|
-
i.error("API", "Cleanup failed", { error:
|
|
4039
|
+
} catch (r) {
|
|
4040
|
+
i.error("API", "Cleanup failed", { error: r, hadApp: !!v, wasInitializing: T });
|
|
4028
4041
|
}
|
|
4029
|
-
},
|
|
4042
|
+
}, Jt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
4030
4043
|
__proto__: null,
|
|
4031
|
-
Constants:
|
|
4032
|
-
Types:
|
|
4033
|
-
destroy:
|
|
4034
|
-
event:
|
|
4035
|
-
getInitializationStatus:
|
|
4036
|
-
init:
|
|
4037
|
-
isInitialized:
|
|
4044
|
+
Constants: Bt,
|
|
4045
|
+
Types: Qt,
|
|
4046
|
+
destroy: Yt,
|
|
4047
|
+
event: Wt,
|
|
4048
|
+
getInitializationStatus: Kt,
|
|
4049
|
+
init: qt,
|
|
4050
|
+
isInitialized: Xt
|
|
4038
4051
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
4039
4052
|
export {
|
|
4040
|
-
|
|
4053
|
+
Jt as TraceLog
|
|
4041
4054
|
};
|