@tracelog/lib 0.0.6 → 0.0.7
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
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
var E = /* @__PURE__ */ ((r) => (r.Mobile = "mobile", r.Tablet = "tablet", r.Desktop = "desktop", r.Unknown = "unknown", r))(E || {});
|
|
2
|
-
const
|
|
2
|
+
const q = {};
|
|
3
3
|
class p {
|
|
4
4
|
get(e) {
|
|
5
|
-
return
|
|
5
|
+
return q[e];
|
|
6
6
|
}
|
|
7
7
|
set(e, t) {
|
|
8
|
-
const s =
|
|
9
|
-
|
|
8
|
+
const s = q[e];
|
|
9
|
+
q[e] = t, (e === "sessionId" || e === "config" || e === "hasStartSession") && n.debug("StateManager", "Critical state updated", {
|
|
10
10
|
key: e,
|
|
11
11
|
oldValue: e === "config" ? !!s : s,
|
|
12
12
|
newValue: e === "config" ? !!t : t
|
|
@@ -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, i) {
|
|
102
102
|
if (!this.shouldShowLog(e))
|
|
103
103
|
return;
|
|
104
104
|
const a = this.formatMessage(t, s), o = this.getConsoleMethod(e);
|
|
105
|
-
|
|
105
|
+
i !== void 0 ? console[o](a, i) : 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, i) {
|
|
111
111
|
if (!(typeof window > "u" || typeof CustomEvent > "u"))
|
|
112
112
|
try {
|
|
113
113
|
const a = new CustomEvent("tracelog:log", {
|
|
@@ -116,49 +116,49 @@ class Re extends p {
|
|
|
116
116
|
level: e,
|
|
117
117
|
namespace: t,
|
|
118
118
|
message: s,
|
|
119
|
-
data:
|
|
119
|
+
data: i
|
|
120
120
|
}
|
|
121
121
|
});
|
|
122
122
|
window.dispatchEvent(a);
|
|
123
123
|
} catch {
|
|
124
|
-
console.log(`[TraceLog:${t}] ${s}`,
|
|
124
|
+
console.log(`[TraceLog:${t}] ${s}`, i);
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
const
|
|
128
|
+
const n = new Re();
|
|
129
129
|
let J, Ee;
|
|
130
130
|
const ke = () => {
|
|
131
131
|
typeof window < "u" && !J && (J = window.matchMedia("(pointer: coarse)"), Ee = window.matchMedia("(hover: none)"));
|
|
132
132
|
}, we = () => {
|
|
133
133
|
try {
|
|
134
|
-
|
|
134
|
+
n.debug("DeviceDetector", "Starting device detection");
|
|
135
135
|
const r = navigator;
|
|
136
136
|
if (r.userAgentData && typeof r.userAgentData.mobile == "boolean") {
|
|
137
|
-
if (
|
|
137
|
+
if (n.debug("DeviceDetector", "Using modern User-Agent Client Hints API", {
|
|
138
138
|
mobile: r.userAgentData.mobile,
|
|
139
139
|
platform: r.userAgentData.platform
|
|
140
140
|
}), r.userAgentData.platform && /ipad|tablet/i.test(r.userAgentData.platform))
|
|
141
|
-
return
|
|
141
|
+
return n.debug("DeviceDetector", "Device detected as tablet via platform hint"), E.Tablet;
|
|
142
142
|
const d = r.userAgentData.mobile ? E.Mobile : E.Desktop;
|
|
143
|
-
return
|
|
143
|
+
return n.debug("DeviceDetector", "Device detected via User-Agent hints", { result: d }), d;
|
|
144
144
|
}
|
|
145
|
-
|
|
146
|
-
const e = window.innerWidth, t = J?.matches ?? !1, s = Ee?.matches ?? !1,
|
|
145
|
+
n.debug("DeviceDetector", "Using fallback detection methods"), ke();
|
|
146
|
+
const e = window.innerWidth, t = J?.matches ?? !1, s = Ee?.matches ?? !1, i = "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: i,
|
|
151
151
|
isMobileUA: o,
|
|
152
152
|
isTabletUA: l,
|
|
153
153
|
maxTouchPoints: navigator.maxTouchPoints
|
|
154
154
|
};
|
|
155
|
-
return e <= 767 || o &&
|
|
155
|
+
return e <= 767 || o && i ? (n.debug("DeviceDetector", "Device detected as mobile", c), E.Mobile) : e >= 768 && e <= 1024 || l || t && s && i ? (n.debug("DeviceDetector", "Device detected as tablet", c), E.Tablet) : (n.debug("DeviceDetector", "Device detected as desktop", c), E.Desktop);
|
|
156
156
|
} catch (r) {
|
|
157
|
-
return
|
|
157
|
+
return n.warn("DeviceDetector", "Device detection failed, defaulting to desktop", {
|
|
158
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, He = 4, Pe = 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,
|
|
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, He = 4, Pe = 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: []
|
|
@@ -255,29 +255,29 @@ const ke = () => {
|
|
|
255
255
|
// Array validation
|
|
256
256
|
INVALID_SENSITIVE_QUERY_PARAMS: "Sensitive query params must be an array of strings"
|
|
257
257
|
}, nt = () => {
|
|
258
|
-
|
|
258
|
+
n.debug("UTMParams", "Extracting UTM parameters from URL", {
|
|
259
259
|
url: window.location.href,
|
|
260
260
|
search: window.location.search
|
|
261
261
|
});
|
|
262
262
|
const r = new URLSearchParams(window.location.search), e = {};
|
|
263
263
|
Je.forEach((s) => {
|
|
264
|
-
const
|
|
265
|
-
if (
|
|
264
|
+
const i = r.get(s);
|
|
265
|
+
if (i) {
|
|
266
266
|
const a = s.split("utm_")[1];
|
|
267
|
-
e[a] =
|
|
267
|
+
e[a] = i, n.debug("UTMParams", "Found UTM parameter", { param: s, key: a, value: i });
|
|
268
268
|
}
|
|
269
269
|
});
|
|
270
270
|
const t = Object.keys(e).length ? e : void 0;
|
|
271
|
-
return t ?
|
|
271
|
+
return t ? n.debug("UTMParams", "UTM parameters extracted successfully", {
|
|
272
272
|
parameterCount: Object.keys(t).length,
|
|
273
273
|
parameters: Object.keys(t)
|
|
274
|
-
}) :
|
|
274
|
+
}) : n.debug("UTMParams", "No UTM parameters found in URL"), t;
|
|
275
275
|
}, $ = () => {
|
|
276
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
|
|
280
|
+
return n.verbose("UUIDUtils", "Generated new UUID", { uuid: r }), r;
|
|
281
281
|
};
|
|
282
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 {
|
|
@@ -312,40 +312,40 @@ class ye extends x {
|
|
|
312
312
|
}
|
|
313
313
|
const ot = (r) => {
|
|
314
314
|
if (!r || typeof r != "object")
|
|
315
|
-
throw
|
|
315
|
+
throw n.clientError("ConfigValidation", "Configuration must be an object", { config: r }), new P("Configuration must be an object", "config");
|
|
316
316
|
if (!("id" in r))
|
|
317
|
-
throw
|
|
317
|
+
throw n.clientError("ConfigValidation", "Project ID is missing from configuration"), new Q(w.MISSING_PROJECT_ID, "config");
|
|
318
318
|
if (r.id === null || r.id === void 0 || typeof r.id != "string")
|
|
319
|
-
throw
|
|
319
|
+
throw n.clientError("ConfigValidation", "Project ID must be a non-empty string", {
|
|
320
320
|
providedId: r.id,
|
|
321
321
|
type: typeof r.id
|
|
322
322
|
}), new Q(w.MISSING_PROJECT_ID, "config");
|
|
323
323
|
if (r.sessionTimeout !== void 0 && (typeof r.sessionTimeout != "number" || r.sessionTimeout < Z || r.sessionTimeout > ee))
|
|
324
|
-
throw
|
|
324
|
+
throw n.clientError("ConfigValidation", "Invalid session timeout", {
|
|
325
325
|
provided: r.sessionTimeout,
|
|
326
326
|
min: Z,
|
|
327
327
|
max: ee
|
|
328
328
|
}), new rt(w.INVALID_SESSION_TIMEOUT, "config");
|
|
329
329
|
if (r.globalMetadata !== void 0 && (typeof r.globalMetadata != "object" || r.globalMetadata === null))
|
|
330
|
-
throw
|
|
330
|
+
throw n.clientError("ConfigValidation", "Global metadata must be an object", {
|
|
331
331
|
provided: r.globalMetadata,
|
|
332
332
|
type: typeof r.globalMetadata
|
|
333
333
|
}), new P(w.INVALID_GLOBAL_METADATA, "config");
|
|
334
334
|
if (r.scrollContainerSelectors !== void 0 && ct(r.scrollContainerSelectors), r.integrations && lt(r.integrations), r.sensitiveQueryParams !== void 0) {
|
|
335
335
|
if (!Array.isArray(r.sensitiveQueryParams))
|
|
336
|
-
throw
|
|
336
|
+
throw n.clientError("ConfigValidation", "Sensitive query params must be an array", {
|
|
337
337
|
provided: r.sensitiveQueryParams,
|
|
338
338
|
type: typeof r.sensitiveQueryParams
|
|
339
339
|
}), new P(w.INVALID_SENSITIVE_QUERY_PARAMS, "config");
|
|
340
340
|
for (const e of r.sensitiveQueryParams)
|
|
341
341
|
if (typeof e != "string")
|
|
342
|
-
throw
|
|
342
|
+
throw n.clientError("ConfigValidation", "All sensitive query params must be strings", {
|
|
343
343
|
param: e,
|
|
344
344
|
type: typeof e
|
|
345
345
|
}), new P("All sensitive query params must be strings", "config");
|
|
346
346
|
}
|
|
347
347
|
if (r.errorSampling !== void 0 && (typeof r.errorSampling != "number" || r.errorSampling < 0 || r.errorSampling > 1))
|
|
348
|
-
throw
|
|
348
|
+
throw n.clientError("ConfigValidation", "Invalid error sampling rate", {
|
|
349
349
|
provided: r.errorSampling,
|
|
350
350
|
expected: "0-1"
|
|
351
351
|
}), new at(w.INVALID_ERROR_SAMPLING_RATE, "config");
|
|
@@ -353,7 +353,7 @@ const ot = (r) => {
|
|
|
353
353
|
const e = Array.isArray(r) ? r : [r];
|
|
354
354
|
for (const t of e) {
|
|
355
355
|
if (typeof t != "string" || t.trim() === "")
|
|
356
|
-
throw
|
|
356
|
+
throw n.clientError("ConfigValidation", "Invalid scroll container selector", {
|
|
357
357
|
selector: t,
|
|
358
358
|
type: typeof t,
|
|
359
359
|
isEmpty: t === "" || typeof t == "string" && t.trim() === ""
|
|
@@ -362,19 +362,19 @@ const ot = (r) => {
|
|
|
362
362
|
try {
|
|
363
363
|
document.querySelector(t);
|
|
364
364
|
} catch {
|
|
365
|
-
|
|
365
|
+
n.clientWarn("ConfigValidation", `Invalid CSS selector will be ignored: "${t}"`);
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
368
|
}, lt = (r) => {
|
|
369
369
|
if (r && r.googleAnalytics) {
|
|
370
370
|
if (!r.googleAnalytics.measurementId || typeof r.googleAnalytics.measurementId != "string" || r.googleAnalytics.measurementId.trim() === "")
|
|
371
|
-
throw
|
|
371
|
+
throw n.clientError("ConfigValidation", "Invalid Google Analytics measurement ID", {
|
|
372
372
|
provided: r.googleAnalytics.measurementId,
|
|
373
373
|
type: typeof r.googleAnalytics.measurementId
|
|
374
374
|
}), new ye(w.INVALID_GOOGLE_ANALYTICS_ID, "config");
|
|
375
375
|
const e = r.googleAnalytics.measurementId.trim();
|
|
376
376
|
if (!e.match(/^(G-|UA-)/))
|
|
377
|
-
throw
|
|
377
|
+
throw n.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
|
}
|
|
@@ -387,17 +387,17 @@ const ot = (r) => {
|
|
|
387
387
|
sensitiveQueryParams: r.sensitiveQueryParams ?? []
|
|
388
388
|
};
|
|
389
389
|
if (!e.id)
|
|
390
|
-
throw
|
|
390
|
+
throw n.clientError("ConfigValidation", "Project ID is empty after trimming whitespace", {
|
|
391
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
395
|
}, be = (r) => {
|
|
396
396
|
if (!r || typeof r != "string" || r.trim().length === 0)
|
|
397
|
-
return
|
|
397
|
+
return n.debug("Sanitize", "String sanitization skipped - empty or invalid input", { value: r, type: typeof r }), "";
|
|
398
398
|
const e = r.length;
|
|
399
399
|
let t = r;
|
|
400
|
-
r.length > M && (t = r.slice(0, Math.max(0, M)),
|
|
400
|
+
r.length > M && (t = r.slice(0, Math.max(0, M)), n.warn("Sanitize", "String truncated due to length limit", {
|
|
401
401
|
originalLength: e,
|
|
402
402
|
maxLength: M,
|
|
403
403
|
truncatedLength: t.length
|
|
@@ -407,18 +407,18 @@ const ot = (r) => {
|
|
|
407
407
|
const o = t;
|
|
408
408
|
t = t.replace(a, ""), o !== t && s++;
|
|
409
409
|
}
|
|
410
|
-
s > 0 &&
|
|
410
|
+
s > 0 && n.warn("Sanitize", "XSS patterns detected and removed", {
|
|
411
411
|
patternMatches: s,
|
|
412
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
|
|
416
|
-
return (e > 50 || s > 0) &&
|
|
415
|
+
const i = t.trim();
|
|
416
|
+
return (e > 50 || s > 0) && n.debug("Sanitize", "String sanitization completed", {
|
|
417
417
|
originalLength: e,
|
|
418
|
-
sanitizedLength:
|
|
418
|
+
sanitizedLength: i.length,
|
|
419
419
|
xssPatternMatches: s,
|
|
420
420
|
wasTruncated: e > M
|
|
421
|
-
}),
|
|
421
|
+
}), i;
|
|
422
422
|
}, ht = (r) => {
|
|
423
423
|
if (typeof r != "string")
|
|
424
424
|
return "";
|
|
@@ -427,9 +427,9 @@ const ot = (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
|
-
},
|
|
430
|
+
}, B = (r, e = 0) => {
|
|
431
431
|
if (e > le)
|
|
432
|
-
return
|
|
432
|
+
return n.warn("Sanitize", "Maximum object depth exceeded during sanitization", {
|
|
433
433
|
depth: e,
|
|
434
434
|
maxDepth: le
|
|
435
435
|
}), null;
|
|
@@ -438,23 +438,23 @@ const ot = (r) => {
|
|
|
438
438
|
if (typeof r == "string")
|
|
439
439
|
return be(r);
|
|
440
440
|
if (typeof r == "number")
|
|
441
|
-
return !Number.isFinite(r) || r < -Number.MAX_SAFE_INTEGER || r > Number.MAX_SAFE_INTEGER ? (
|
|
441
|
+
return !Number.isFinite(r) || r < -Number.MAX_SAFE_INTEGER || r > Number.MAX_SAFE_INTEGER ? (n.warn("Sanitize", "Invalid number sanitized to 0", { value: r, isFinite: Number.isFinite(r) }), 0) : r;
|
|
442
442
|
if (typeof r == "boolean")
|
|
443
443
|
return r;
|
|
444
444
|
if (Array.isArray(r)) {
|
|
445
445
|
const t = r.length, s = r.slice(0, W);
|
|
446
|
-
t > W &&
|
|
446
|
+
t > W && n.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 i = s.map((a) => B(a, e + 1)).filter((a) => a !== null);
|
|
452
|
+
return t > 0 && i.length === 0 && n.warn("Sanitize", "All array items were filtered out during sanitization", { originalLength: t, depth: e }), i;
|
|
453
453
|
}
|
|
454
454
|
if (typeof r == "object") {
|
|
455
|
-
const t = {}, s = Object.entries(r),
|
|
456
|
-
|
|
457
|
-
originalKeys:
|
|
455
|
+
const t = {}, s = Object.entries(r), i = s.length, a = s.slice(0, 20);
|
|
456
|
+
i > 20 && n.warn("Sanitize", "Object keys truncated due to limit", {
|
|
457
|
+
originalKeys: i,
|
|
458
458
|
maxKeys: 20,
|
|
459
459
|
depth: e
|
|
460
460
|
});
|
|
@@ -462,26 +462,26 @@ const ot = (r) => {
|
|
|
462
462
|
for (const [l, c] of a) {
|
|
463
463
|
const d = be(l);
|
|
464
464
|
if (d) {
|
|
465
|
-
const u =
|
|
465
|
+
const u = B(c, e + 1);
|
|
466
466
|
u !== null ? t[d] = u : o++;
|
|
467
467
|
} else
|
|
468
468
|
o++;
|
|
469
469
|
}
|
|
470
|
-
return o > 0 &&
|
|
470
|
+
return o > 0 && n.debug("Sanitize", "Object properties filtered during sanitization", {
|
|
471
471
|
filteredKeysCount: o,
|
|
472
472
|
remainingKeys: Object.keys(t).length,
|
|
473
473
|
depth: e
|
|
474
474
|
}), t;
|
|
475
475
|
}
|
|
476
|
-
return
|
|
476
|
+
return n.debug("Sanitize", "Unknown value type sanitized to null", { type: typeof r, depth: e }), null;
|
|
477
477
|
}, ut = (r) => {
|
|
478
|
-
|
|
478
|
+
n.debug("Sanitize", "Starting API config sanitization");
|
|
479
479
|
const e = {};
|
|
480
480
|
if (typeof r != "object" || r === null)
|
|
481
|
-
return
|
|
481
|
+
return n.warn("Sanitize", "API config data is not an object", { data: r, type: typeof r }), e;
|
|
482
482
|
try {
|
|
483
483
|
const t = Object.keys(r);
|
|
484
|
-
let s = 0,
|
|
484
|
+
let s = 0, i = 0;
|
|
485
485
|
for (const a of t)
|
|
486
486
|
if (it.has(a)) {
|
|
487
487
|
const o = r[a];
|
|
@@ -489,46 +489,46 @@ const ot = (r) => {
|
|
|
489
489
|
const l = Array.isArray(o) ? o : typeof o == "string" ? [o] : [], c = l.length;
|
|
490
490
|
e.excludedUrlPaths = l.map((u) => ht(String(u))).filter(Boolean);
|
|
491
491
|
const d = c - e.excludedUrlPaths.length;
|
|
492
|
-
d > 0 &&
|
|
492
|
+
d > 0 && n.warn("Sanitize", "Some excluded URL paths were filtered during sanitization", {
|
|
493
493
|
originalCount: c,
|
|
494
494
|
filteredCount: d
|
|
495
495
|
});
|
|
496
496
|
} else if (a === "tags")
|
|
497
|
-
Array.isArray(o) ? (e.tags = o,
|
|
497
|
+
Array.isArray(o) ? (e.tags = o, n.debug("Sanitize", "Tags processed", { count: o.length })) : n.warn("Sanitize", "Tags value is not an array", { value: o, type: typeof o });
|
|
498
498
|
else {
|
|
499
|
-
const l =
|
|
500
|
-
l !== null ? e[a] = l :
|
|
499
|
+
const l = B(o);
|
|
500
|
+
l !== null ? e[a] = l : n.warn("Sanitize", "API config value sanitized to null", { key: a, originalValue: o });
|
|
501
501
|
}
|
|
502
502
|
s++;
|
|
503
503
|
} else
|
|
504
|
-
|
|
505
|
-
|
|
504
|
+
i++, n.debug("Sanitize", "API config key not allowed", { key: a });
|
|
505
|
+
n.info("Sanitize", "API config sanitization completed", {
|
|
506
506
|
originalKeys: t.length,
|
|
507
507
|
processedKeys: s,
|
|
508
|
-
filteredKeys:
|
|
508
|
+
filteredKeys: i,
|
|
509
509
|
finalKeys: Object.keys(e).length
|
|
510
510
|
});
|
|
511
511
|
} catch (t) {
|
|
512
|
-
throw
|
|
512
|
+
throw n.error("Sanitize", "API config sanitization failed", {
|
|
513
513
|
error: t instanceof Error ? t.message : t
|
|
514
514
|
}), new Error(`API config sanitization failed: ${t instanceof Error ? t.message : "Unknown error"}`);
|
|
515
515
|
}
|
|
516
516
|
return e;
|
|
517
517
|
}, gt = (r) => {
|
|
518
|
-
if (
|
|
519
|
-
return
|
|
518
|
+
if (n.debug("Sanitize", "Starting metadata sanitization", { hasMetadata: r != null }), typeof r != "object" || r === null)
|
|
519
|
+
return n.debug("Sanitize", "Metadata is not an object, returning empty object", {
|
|
520
520
|
metadata: r,
|
|
521
521
|
type: typeof r
|
|
522
522
|
}), {};
|
|
523
523
|
try {
|
|
524
|
-
const e = Object.keys(r).length, t =
|
|
525
|
-
return
|
|
524
|
+
const e = Object.keys(r).length, t = B(r), s = typeof t == "object" && t !== null ? t : {}, i = Object.keys(s).length;
|
|
525
|
+
return n.debug("Sanitize", "Metadata sanitization completed", {
|
|
526
526
|
originalKeys: e,
|
|
527
|
-
finalKeys:
|
|
528
|
-
keysFiltered: e -
|
|
527
|
+
finalKeys: i,
|
|
528
|
+
keysFiltered: e - i
|
|
529
529
|
}), s;
|
|
530
530
|
} catch (e) {
|
|
531
|
-
throw
|
|
531
|
+
throw n.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
|
}
|
|
@@ -565,11 +565,11 @@ const ot = (r) => {
|
|
|
565
565
|
valid: !1,
|
|
566
566
|
error: "Event name cannot be a reserved word"
|
|
567
567
|
} : { valid: !0 }, pt = (r, e, t) => {
|
|
568
|
-
const s = gt(e),
|
|
568
|
+
const s = gt(e), i = `${t} "${r}" metadata error`;
|
|
569
569
|
if (!ft(s))
|
|
570
570
|
return {
|
|
571
571
|
valid: !1,
|
|
572
|
-
error: `${
|
|
572
|
+
error: `${i}: object has invalid types. Valid types are string, number, boolean or string arrays.`
|
|
573
573
|
};
|
|
574
574
|
let a;
|
|
575
575
|
try {
|
|
@@ -577,37 +577,37 @@ const ot = (r) => {
|
|
|
577
577
|
} catch {
|
|
578
578
|
return {
|
|
579
579
|
valid: !1,
|
|
580
|
-
error: `${
|
|
580
|
+
error: `${i}: 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: `${i}: 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: `${i}: 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: `${i}: 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: `${i}: 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: `${i}: property "${l}" is too long (max ${M} characters).`
|
|
611
611
|
};
|
|
612
612
|
}
|
|
613
613
|
return {
|
|
@@ -617,108 +617,108 @@ const ot = (r) => {
|
|
|
617
617
|
}, vt = (r, e) => {
|
|
618
618
|
const t = mt(r);
|
|
619
619
|
if (!t.valid)
|
|
620
|
-
return
|
|
620
|
+
return n.clientError("EventValidation", "Event name validation failed", { eventName: r, error: t.error }), t;
|
|
621
621
|
if (!e)
|
|
622
622
|
return { valid: !0 };
|
|
623
623
|
const s = pt(r, e, "customEvent");
|
|
624
|
-
return s.valid ||
|
|
624
|
+
return s.valid || n.clientError("EventValidation", "Event metadata validation failed", {
|
|
625
625
|
eventName: r,
|
|
626
626
|
error: s.error
|
|
627
627
|
}), s;
|
|
628
628
|
}, te = (r, e = !1) => {
|
|
629
629
|
try {
|
|
630
|
-
const t = new URL(r), s = t.protocol === "https:",
|
|
631
|
-
return s || e &&
|
|
630
|
+
const t = new URL(r), s = t.protocol === "https:", i = t.protocol === "http:";
|
|
631
|
+
return s || e && i;
|
|
632
632
|
} catch {
|
|
633
633
|
return !1;
|
|
634
634
|
}
|
|
635
635
|
}, St = (r, e = !1) => {
|
|
636
|
-
|
|
637
|
-
const t = new URL(window.location.href), s = t.hostname,
|
|
638
|
-
if (
|
|
639
|
-
throw
|
|
640
|
-
const a =
|
|
641
|
-
if (
|
|
636
|
+
n.debug("URLUtils", "Generating API URL", { projectId: r, allowHttp: e });
|
|
637
|
+
const t = new URL(window.location.href), s = t.hostname, i = s.split(".");
|
|
638
|
+
if (i.length === 0)
|
|
639
|
+
throw n.clientError("URLUtils", "Invalid hostname - no domain parts found", { hostname: s }), new Error("Invalid URL");
|
|
640
|
+
const a = i.slice(-2).join("."), o = e && t.protocol === "http:" ? "http" : "https", l = `${o}://${r}.${a}`;
|
|
641
|
+
if (n.debug("URLUtils", "Generated API URL", {
|
|
642
642
|
originalUrl: window.location.href,
|
|
643
643
|
hostname: s,
|
|
644
|
-
domainParts:
|
|
644
|
+
domainParts: i.length,
|
|
645
645
|
cleanDomain: a,
|
|
646
646
|
protocol: o,
|
|
647
647
|
generatedUrl: l
|
|
648
648
|
}), !te(l, e))
|
|
649
|
-
throw
|
|
649
|
+
throw n.clientError("URLUtils", "Generated API URL failed validation", {
|
|
650
650
|
apiUrl: l,
|
|
651
651
|
allowHttp: e
|
|
652
652
|
}), new Error("Invalid URL");
|
|
653
|
-
return
|
|
653
|
+
return n.debug("URLUtils", "API URL generation completed successfully", { apiUrl: l }), l;
|
|
654
654
|
}, se = (r, e = []) => {
|
|
655
|
-
|
|
655
|
+
n.debug("URLUtils", "Normalizing URL", {
|
|
656
656
|
urlLength: r.length,
|
|
657
657
|
sensitiveParamsCount: e.length
|
|
658
658
|
});
|
|
659
659
|
try {
|
|
660
|
-
const t = new URL(r), s = t.searchParams,
|
|
660
|
+
const t = new URL(r), s = t.searchParams, i = 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
|
-
}), a &&
|
|
665
|
+
}), a && n.debug("URLUtils", "Sensitive parameters removed from URL", {
|
|
666
666
|
removedParams: o,
|
|
667
|
-
originalParamCount:
|
|
667
|
+
originalParamCount: i,
|
|
668
668
|
finalParamCount: Array.from(s.keys()).length
|
|
669
669
|
}), !a && r.includes("?"))
|
|
670
|
-
return
|
|
670
|
+
return n.debug("URLUtils", "URL normalization - no changes needed"), r;
|
|
671
671
|
t.search = s.toString();
|
|
672
672
|
const l = t.toString();
|
|
673
|
-
return
|
|
673
|
+
return n.debug("URLUtils", "URL normalization completed", {
|
|
674
674
|
hasChanged: a,
|
|
675
675
|
originalLength: r.length,
|
|
676
676
|
normalizedLength: l.length
|
|
677
677
|
}), l;
|
|
678
678
|
} catch (t) {
|
|
679
|
-
return
|
|
679
|
+
return n.warn("URLUtils", "URL normalization failed, returning original", {
|
|
680
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
|
-
if (
|
|
685
|
+
if (n.debug("URLUtils", "Checking if URL path is excluded", {
|
|
686
686
|
urlLength: r.length,
|
|
687
687
|
excludedPathsCount: e.length
|
|
688
688
|
}), e.length === 0)
|
|
689
|
-
return
|
|
689
|
+
return n.debug("URLUtils", "No excluded paths configured"), !1;
|
|
690
690
|
let t;
|
|
691
691
|
try {
|
|
692
|
-
t = new URL(r, window.location.origin).pathname,
|
|
692
|
+
t = new URL(r, window.location.origin).pathname, n.debug("URLUtils", "Extracted path from URL", { path: t });
|
|
693
693
|
} catch (c) {
|
|
694
|
-
return
|
|
694
|
+
return n.warn("URLUtils", "Failed to parse URL for path exclusion check", {
|
|
695
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", i = (c) => c.replaceAll(/[$()*+.?[\\\]^{|}]/g, "\\$&"), a = (c) => new RegExp(
|
|
700
|
+
"^" + c.split("*").map((d) => i(d)).join(".+") + "$"
|
|
701
701
|
), o = e.find((c) => {
|
|
702
702
|
try {
|
|
703
703
|
if (s(c)) {
|
|
704
704
|
const u = c.test(t);
|
|
705
|
-
return u &&
|
|
705
|
+
return u && n.debug("URLUtils", "Path matched regex pattern", { path: t, pattern: c.toString() }), u;
|
|
706
706
|
}
|
|
707
707
|
if (c.includes("*")) {
|
|
708
708
|
const u = a(c), g = u.test(t);
|
|
709
|
-
return g &&
|
|
709
|
+
return g && n.debug("URLUtils", "Path matched wildcard pattern", { path: t, pattern: c, regex: u.toString() }), g;
|
|
710
710
|
}
|
|
711
711
|
const d = c === t;
|
|
712
|
-
return d &&
|
|
712
|
+
return d && n.debug("URLUtils", "Path matched exact pattern", { path: t, pattern: c }), d;
|
|
713
713
|
} catch (d) {
|
|
714
|
-
return
|
|
714
|
+
return n.warn("URLUtils", "Error testing exclusion pattern", {
|
|
715
715
|
pattern: c,
|
|
716
716
|
path: t,
|
|
717
717
|
error: d instanceof Error ? d.message : d
|
|
718
718
|
}), !1;
|
|
719
719
|
}
|
|
720
720
|
}), l = !!o;
|
|
721
|
-
return
|
|
721
|
+
return n.debug("URLUtils", "URL path exclusion check completed", {
|
|
722
722
|
path: t,
|
|
723
723
|
isExcluded: l,
|
|
724
724
|
matchedPattern: o ?? null,
|
|
@@ -736,10 +736,10 @@ class bt {
|
|
|
736
736
|
class Et {
|
|
737
737
|
async get(e, t) {
|
|
738
738
|
if (t.id === C.HttpSkip)
|
|
739
|
-
return
|
|
740
|
-
|
|
739
|
+
return n.debug("ConfigManager", "Using special project id"), this.getDefaultConfig(t);
|
|
740
|
+
n.debug("ConfigManager", "Loading config from API", { apiUrl: e, projectId: t.id });
|
|
741
741
|
const s = await this.load(e, t, t.id === C.HttpLocal);
|
|
742
|
-
return
|
|
742
|
+
return n.info("ConfigManager", "Config loaded successfully", {
|
|
743
743
|
projectId: t.id,
|
|
744
744
|
mode: s.mode,
|
|
745
745
|
hasExcludedPaths: !!s.excludedUrlPaths?.length,
|
|
@@ -748,42 +748,42 @@ class Et {
|
|
|
748
748
|
}
|
|
749
749
|
async load(e, t, s) {
|
|
750
750
|
try {
|
|
751
|
-
const
|
|
752
|
-
if (!
|
|
751
|
+
const i = s ? `${window.location.origin}/config` : this.getUrl(e);
|
|
752
|
+
if (!i)
|
|
753
753
|
throw new Error("Config URL is not valid or not allowed");
|
|
754
|
-
const a = await fetch(
|
|
754
|
+
const a = await fetch(i, {
|
|
755
755
|
method: "GET",
|
|
756
756
|
headers: { "Content-Type": "application/json" }
|
|
757
757
|
});
|
|
758
758
|
if (!a.ok) {
|
|
759
759
|
const A = `HTTP ${a.status}: ${a.statusText}`;
|
|
760
|
-
throw
|
|
760
|
+
throw n.error("ConfigManager", "Config API request failed", {
|
|
761
761
|
status: a.status,
|
|
762
762
|
statusText: a.statusText,
|
|
763
|
-
configUrl:
|
|
763
|
+
configUrl: i
|
|
764
764
|
}), new Error(A);
|
|
765
765
|
}
|
|
766
766
|
const o = await a.json();
|
|
767
767
|
if (o == null || typeof o != "object" || Array.isArray(o))
|
|
768
|
-
throw
|
|
768
|
+
throw n.error("ConfigManager", "Invalid config API response format", {
|
|
769
769
|
responseType: typeof o,
|
|
770
770
|
isArray: Array.isArray(o)
|
|
771
771
|
}), new Error("Invalid config API response: expected object");
|
|
772
772
|
const l = ut(o), d = { ...{ ...Ae, ...l }, ...t };
|
|
773
|
-
new URLSearchParams(window.location.search).get("qaMode") === "true" && !d.mode && (d.mode = L.QA,
|
|
773
|
+
new URLSearchParams(window.location.search).get("qaMode") === "true" && !d.mode && (d.mode = L.QA, n.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 =
|
|
778
|
-
throw
|
|
776
|
+
} catch (i) {
|
|
777
|
+
const a = i instanceof Error ? i.message : "Unknown error";
|
|
778
|
+
throw n.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
|
|
786
|
-
return
|
|
783
|
+
let i = `${e}/config`;
|
|
784
|
+
if (s && (i += "?qaMode=true"), !te(i))
|
|
785
|
+
throw n.clientError("ConfigManager", "Invalid config URL provided", { configUrl: i }), new Error("Config URL is not valid or not allowed");
|
|
786
|
+
return i;
|
|
787
787
|
}
|
|
788
788
|
getDefaultConfig(e) {
|
|
789
789
|
return Ye({
|
|
@@ -820,14 +820,14 @@ class wt extends p {
|
|
|
820
820
|
return;
|
|
821
821
|
}
|
|
822
822
|
const t = this.createRecoveryBody(e);
|
|
823
|
-
this.sendRecoveredEvents(t) ? (
|
|
823
|
+
this.sendRecoveredEvents(t) ? (n.info("SenderManager", "Persisted events recovered successfully", {
|
|
824
824
|
eventsCount: e.events.length,
|
|
825
825
|
sessionId: e.sessionId
|
|
826
|
-
}), this.clearPersistedEvents()) : (
|
|
826
|
+
}), this.clearPersistedEvents()) : (n.warn("SenderManager", "Failed to recover persisted events, scheduling retry", {
|
|
827
827
|
eventsCount: e.events.length
|
|
828
828
|
}), this.scheduleRetryForRecoveredEvents(t));
|
|
829
829
|
} catch (e) {
|
|
830
|
-
|
|
830
|
+
n.error("SenderManager", "Failed to recover persisted events", { error: e });
|
|
831
831
|
}
|
|
832
832
|
}
|
|
833
833
|
stop() {
|
|
@@ -867,9 +867,9 @@ class wt extends p {
|
|
|
867
867
|
Referer: window.location.href
|
|
868
868
|
}
|
|
869
869
|
})).ok;
|
|
870
|
-
} catch (
|
|
871
|
-
const a =
|
|
872
|
-
return
|
|
870
|
+
} catch (i) {
|
|
871
|
+
const a = i instanceof Error ? i.message : String(i), o = a.includes("CORS") || a.includes("NotSameOrigin") || a.includes("blocked");
|
|
872
|
+
return n.error("SenderManager", "Failed to send events async", {
|
|
873
873
|
error: a,
|
|
874
874
|
isCorsError: o,
|
|
875
875
|
url: t.replace(/\/\/[^/]+/, "//[DOMAIN]")
|
|
@@ -877,22 +877,22 @@ class wt extends p {
|
|
|
877
877
|
}
|
|
878
878
|
}
|
|
879
879
|
sendQueueSync(e) {
|
|
880
|
-
const { url: t, payload: s } = this.prepareRequest(e);
|
|
881
|
-
return this.isSendBeaconAvailable() && navigator.sendBeacon(t,
|
|
880
|
+
const { url: t, payload: s } = this.prepareRequest(e), i = new Blob([s], { type: "application/json" });
|
|
881
|
+
return this.isSendBeaconAvailable() && navigator.sendBeacon(t, i) ? !0 : this.sendSyncXHR(t, s);
|
|
882
882
|
}
|
|
883
883
|
sendQueue(e) {
|
|
884
884
|
if (!this.isSendBeaconAvailable())
|
|
885
885
|
return !1;
|
|
886
|
-
const { url: t, payload: s } = this.prepareRequest(e);
|
|
887
|
-
return navigator.sendBeacon(t,
|
|
886
|
+
const { url: t, payload: s } = this.prepareRequest(e), i = new Blob([s], { type: "application/json" });
|
|
887
|
+
return navigator.sendBeacon(t, i);
|
|
888
888
|
}
|
|
889
889
|
sendSyncXHR(e, t) {
|
|
890
890
|
const s = new XMLHttpRequest();
|
|
891
891
|
try {
|
|
892
892
|
return s.open("POST", e, !1), s.setRequestHeader("Content-Type", "application/json"), s.setRequestHeader("Origin", window.location.origin), s.setRequestHeader("Referer", window.location.href), s.withCredentials = !1, s.timeout = xe, s.send(t), s.status >= 200 && s.status < 300;
|
|
893
|
-
} catch (
|
|
894
|
-
const a =
|
|
895
|
-
return
|
|
893
|
+
} catch (i) {
|
|
894
|
+
const a = i instanceof Error ? i.message : String(i), o = a.includes("CORS") || a.includes("NotSameOrigin") || a.includes("blocked");
|
|
895
|
+
return n.error("SenderManager", "Sync XHR failed", {
|
|
896
896
|
error: a,
|
|
897
897
|
isCorsError: o,
|
|
898
898
|
status: s.status ?? "unknown",
|
|
@@ -923,7 +923,7 @@ class wt extends p {
|
|
|
923
923
|
};
|
|
924
924
|
}
|
|
925
925
|
logQueue(e) {
|
|
926
|
-
|
|
926
|
+
n.info("SenderManager", " ⏩ Queue snapshot", e);
|
|
927
927
|
}
|
|
928
928
|
handleSendFailure(e) {
|
|
929
929
|
this.persistFailedEvents(e), this.scheduleRetry(e);
|
|
@@ -940,7 +940,7 @@ class wt extends p {
|
|
|
940
940
|
};
|
|
941
941
|
this.storeManager.setItem(this.queueStorageKey, JSON.stringify(t));
|
|
942
942
|
} catch (t) {
|
|
943
|
-
|
|
943
|
+
n.error("SenderManager", "Failed to persist events", { error: t });
|
|
944
944
|
}
|
|
945
945
|
}
|
|
946
946
|
clearPersistedEvents() {
|
|
@@ -958,21 +958,21 @@ class wt extends p {
|
|
|
958
958
|
if (this.shouldSkipSend())
|
|
959
959
|
return this.logQueue(e), !0;
|
|
960
960
|
if (!this.canSendAsync())
|
|
961
|
-
return
|
|
961
|
+
return n.info("SenderManager", "⏱️ Rate limited - skipping async send", {
|
|
962
962
|
eventsCount: e.events.length,
|
|
963
963
|
timeSinceLastSend: Date.now() - this.lastAsyncSend
|
|
964
964
|
}), !1;
|
|
965
|
-
|
|
965
|
+
n.info("SenderManager", "🌐 Sending events to server (async)", {
|
|
966
966
|
eventsCount: e.events.length,
|
|
967
967
|
sessionId: e.session_id,
|
|
968
968
|
userId: e.user_id
|
|
969
969
|
}), this.lastAsyncSend = Date.now();
|
|
970
970
|
try {
|
|
971
971
|
const s = await t();
|
|
972
|
-
return s ? (
|
|
972
|
+
return s ? (n.info("SenderManager", "✅ Successfully sent events to server", {
|
|
973
973
|
eventsCount: e.events.length,
|
|
974
974
|
method: "async"
|
|
975
|
-
}), this.resetRetryState(), this.clearPersistedEvents()) : (
|
|
975
|
+
}), this.resetRetryState(), this.clearPersistedEvents()) : (n.warn("SenderManager", "Failed to send events", {
|
|
976
976
|
eventsCount: e.events.length,
|
|
977
977
|
method: "async"
|
|
978
978
|
}), this.handleSendFailure(e)), s;
|
|
@@ -984,11 +984,11 @@ class wt extends p {
|
|
|
984
984
|
if (this.shouldSkipSend())
|
|
985
985
|
return this.logQueue(e), !0;
|
|
986
986
|
if (!this.canSendSync())
|
|
987
|
-
return
|
|
987
|
+
return n.info("SenderManager", "⏱️ Rate limited - skipping sync send", {
|
|
988
988
|
eventsCount: e.events.length,
|
|
989
989
|
timeSinceLastSend: Date.now() - this.lastSyncSend
|
|
990
990
|
}), !1;
|
|
991
|
-
|
|
991
|
+
n.info("SenderManager", "🌐 Sending events to server (sync)", {
|
|
992
992
|
eventsCount: e.events.length,
|
|
993
993
|
sessionId: e.session_id,
|
|
994
994
|
userId: e.user_id,
|
|
@@ -996,15 +996,15 @@ class wt extends p {
|
|
|
996
996
|
}), this.lastSyncSend = Date.now();
|
|
997
997
|
try {
|
|
998
998
|
const s = t();
|
|
999
|
-
return s ? (
|
|
999
|
+
return s ? (n.info("SenderManager", "✅ Successfully sent events to server", {
|
|
1000
1000
|
eventsCount: e.events.length,
|
|
1001
1001
|
method: "sync"
|
|
1002
|
-
}), this.resetRetryState(), this.clearPersistedEvents()) : (
|
|
1002
|
+
}), this.resetRetryState(), this.clearPersistedEvents()) : (n.warn("SenderManager", "Failed to send events", {
|
|
1003
1003
|
eventsCount: e.events.length,
|
|
1004
1004
|
method: "sync"
|
|
1005
1005
|
}), this.handleSendFailure(e)), s;
|
|
1006
1006
|
} catch {
|
|
1007
|
-
return
|
|
1007
|
+
return n.info("SenderManager", "💥 Exception during event sending", {
|
|
1008
1008
|
eventsCount: e.events.length,
|
|
1009
1009
|
method: "sync"
|
|
1010
1010
|
}), this.handleSendFailure(e), !1;
|
|
@@ -1033,14 +1033,14 @@ class It extends p {
|
|
|
1033
1033
|
const t = e === "LONG_TASK", s = t ? De : Pe;
|
|
1034
1034
|
if (s >= 1) return !0;
|
|
1035
1035
|
if (s <= 0) return !1;
|
|
1036
|
-
const
|
|
1037
|
-
return this.getHash(
|
|
1036
|
+
const i = `${this.get("userId")}|${t ? "long_task" : "web_vitals"}`;
|
|
1037
|
+
return this.getHash(i) % 100 / 100 < s;
|
|
1038
1038
|
}
|
|
1039
1039
|
getHash(e) {
|
|
1040
1040
|
let t = 0;
|
|
1041
1041
|
for (let s = 0; s < e.length; s++) {
|
|
1042
|
-
const
|
|
1043
|
-
t = (t << 5) - t +
|
|
1042
|
+
const i = e.charCodeAt(s);
|
|
1043
|
+
t = (t << 5) - t + i, t |= 0;
|
|
1044
1044
|
}
|
|
1045
1045
|
return Math.abs(t);
|
|
1046
1046
|
}
|
|
@@ -1060,7 +1060,7 @@ class Tt extends p {
|
|
|
1060
1060
|
const s = this.get("config")?.tags?.filter((a) => a.triggerType === h.PAGE_VIEW) ?? [];
|
|
1061
1061
|
if (s.length === 0)
|
|
1062
1062
|
return [];
|
|
1063
|
-
const
|
|
1063
|
+
const i = [];
|
|
1064
1064
|
for (const a of s) {
|
|
1065
1065
|
const { id: o, logicalOperator: l, conditions: c } = a, d = [];
|
|
1066
1066
|
for (const g of c)
|
|
@@ -1087,15 +1087,15 @@ class Tt extends p {
|
|
|
1087
1087
|
}
|
|
1088
1088
|
}
|
|
1089
1089
|
let u = !1;
|
|
1090
|
-
u = l === G.AND ? d.every(Boolean) : d.some(Boolean), u &&
|
|
1090
|
+
u = l === G.AND ? d.every(Boolean) : d.some(Boolean), u && i.push(o);
|
|
1091
1091
|
}
|
|
1092
|
-
return
|
|
1092
|
+
return i;
|
|
1093
1093
|
}
|
|
1094
1094
|
checkEventTypeClick(e, t) {
|
|
1095
1095
|
const s = this.get("config")?.tags?.filter((a) => a.triggerType === h.CLICK) ?? [];
|
|
1096
1096
|
if (s.length === 0)
|
|
1097
1097
|
return [];
|
|
1098
|
-
const
|
|
1098
|
+
const i = [];
|
|
1099
1099
|
for (const a of s) {
|
|
1100
1100
|
const { id: o, logicalOperator: l, conditions: c } = a, d = [];
|
|
1101
1101
|
for (const g of c) {
|
|
@@ -1132,26 +1132,26 @@ class Tt extends p {
|
|
|
1132
1132
|
}
|
|
1133
1133
|
}
|
|
1134
1134
|
let u = !1;
|
|
1135
|
-
u = l === G.AND ? d.every(Boolean) : d.some(Boolean), u &&
|
|
1135
|
+
u = l === G.AND ? d.every(Boolean) : d.some(Boolean), u && i.push(o);
|
|
1136
1136
|
}
|
|
1137
|
-
return
|
|
1137
|
+
return i;
|
|
1138
1138
|
}
|
|
1139
1139
|
matchUrlMatches(e, t) {
|
|
1140
1140
|
if (e.type !== m.URL_MATCHES)
|
|
1141
1141
|
return !1;
|
|
1142
|
-
const s = e.value.toLowerCase(),
|
|
1142
|
+
const s = e.value.toLowerCase(), i = t.toLowerCase();
|
|
1143
1143
|
switch (e.operator) {
|
|
1144
1144
|
case f.EQUALS:
|
|
1145
|
-
return
|
|
1145
|
+
return i === s;
|
|
1146
1146
|
case f.CONTAINS:
|
|
1147
|
-
return
|
|
1147
|
+
return i.includes(s);
|
|
1148
1148
|
case f.STARTS_WITH:
|
|
1149
|
-
return
|
|
1149
|
+
return i.startsWith(s);
|
|
1150
1150
|
case f.ENDS_WITH:
|
|
1151
|
-
return
|
|
1151
|
+
return i.endsWith(s);
|
|
1152
1152
|
case f.REGEX:
|
|
1153
1153
|
try {
|
|
1154
|
-
return new RegExp(s, "gi").test(
|
|
1154
|
+
return new RegExp(s, "gi").test(i);
|
|
1155
1155
|
} catch {
|
|
1156
1156
|
return !1;
|
|
1157
1157
|
}
|
|
@@ -1162,19 +1162,19 @@ class Tt extends p {
|
|
|
1162
1162
|
matchDeviceType(e, t) {
|
|
1163
1163
|
if (e.type !== m.DEVICE_TYPE)
|
|
1164
1164
|
return !1;
|
|
1165
|
-
const s = e.value.toLowerCase(),
|
|
1165
|
+
const s = e.value.toLowerCase(), i = t.toLowerCase();
|
|
1166
1166
|
switch (e.operator) {
|
|
1167
1167
|
case f.EQUALS:
|
|
1168
|
-
return
|
|
1168
|
+
return i === s;
|
|
1169
1169
|
case f.CONTAINS:
|
|
1170
|
-
return
|
|
1170
|
+
return i.includes(s);
|
|
1171
1171
|
case f.STARTS_WITH:
|
|
1172
|
-
return
|
|
1172
|
+
return i.startsWith(s);
|
|
1173
1173
|
case f.ENDS_WITH:
|
|
1174
|
-
return
|
|
1174
|
+
return i.endsWith(s);
|
|
1175
1175
|
case f.REGEX:
|
|
1176
1176
|
try {
|
|
1177
|
-
return new RegExp(s, "gi").test(
|
|
1177
|
+
return new RegExp(s, "gi").test(i);
|
|
1178
1178
|
} catch {
|
|
1179
1179
|
return !1;
|
|
1180
1180
|
}
|
|
@@ -1196,19 +1196,19 @@ class Tt extends p {
|
|
|
1196
1196
|
t.role ?? "",
|
|
1197
1197
|
t.ariaLabel ?? "",
|
|
1198
1198
|
...Object.values(t.dataAttributes ?? {})
|
|
1199
|
-
].join(" "),
|
|
1199
|
+
].join(" "), i = e.value.toLowerCase(), a = s.toLowerCase();
|
|
1200
1200
|
switch (e.operator) {
|
|
1201
1201
|
case f.EQUALS:
|
|
1202
|
-
return this.checkElementFieldEquals(t,
|
|
1202
|
+
return this.checkElementFieldEquals(t, i);
|
|
1203
1203
|
case f.CONTAINS:
|
|
1204
|
-
return a.includes(
|
|
1204
|
+
return a.includes(i);
|
|
1205
1205
|
case f.STARTS_WITH:
|
|
1206
|
-
return a.startsWith(
|
|
1206
|
+
return a.startsWith(i);
|
|
1207
1207
|
case f.ENDS_WITH:
|
|
1208
|
-
return a.endsWith(
|
|
1208
|
+
return a.endsWith(i);
|
|
1209
1209
|
case f.REGEX:
|
|
1210
1210
|
try {
|
|
1211
|
-
return new RegExp(
|
|
1211
|
+
return new RegExp(i, "gi").test(a);
|
|
1212
1212
|
} catch {
|
|
1213
1213
|
return !1;
|
|
1214
1214
|
}
|
|
@@ -1221,19 +1221,19 @@ class Tt extends p {
|
|
|
1221
1221
|
e.type
|
|
1222
1222
|
))
|
|
1223
1223
|
return !1;
|
|
1224
|
-
const s = t ?? "",
|
|
1224
|
+
const s = t ?? "", i = e.value.toLowerCase(), a = s.toLowerCase();
|
|
1225
1225
|
switch (e.operator) {
|
|
1226
1226
|
case f.EQUALS:
|
|
1227
|
-
return a ===
|
|
1227
|
+
return a === i;
|
|
1228
1228
|
case f.CONTAINS:
|
|
1229
|
-
return a.includes(
|
|
1229
|
+
return a.includes(i);
|
|
1230
1230
|
case f.STARTS_WITH:
|
|
1231
|
-
return a.startsWith(
|
|
1231
|
+
return a.startsWith(i);
|
|
1232
1232
|
case f.ENDS_WITH:
|
|
1233
|
-
return a.endsWith(
|
|
1233
|
+
return a.endsWith(i);
|
|
1234
1234
|
case f.REGEX:
|
|
1235
1235
|
try {
|
|
1236
|
-
return new RegExp(
|
|
1236
|
+
return new RegExp(i, "gi").test(a);
|
|
1237
1237
|
} catch {
|
|
1238
1238
|
return !1;
|
|
1239
1239
|
}
|
|
@@ -1253,15 +1253,15 @@ class Tt extends p {
|
|
|
1253
1253
|
e.role,
|
|
1254
1254
|
e.ariaLabel
|
|
1255
1255
|
];
|
|
1256
|
-
for (const
|
|
1257
|
-
if (
|
|
1258
|
-
const a =
|
|
1256
|
+
for (const i of s)
|
|
1257
|
+
if (i) {
|
|
1258
|
+
const a = i.toLowerCase(), o = t.toLowerCase();
|
|
1259
1259
|
if (a === o)
|
|
1260
1260
|
return !0;
|
|
1261
1261
|
}
|
|
1262
1262
|
if (e.dataAttributes)
|
|
1263
|
-
for (const
|
|
1264
|
-
const a =
|
|
1263
|
+
for (const i of Object.values(e.dataAttributes)) {
|
|
1264
|
+
const a = i.toLowerCase(), o = t.toLowerCase();
|
|
1265
1265
|
if (a === o)
|
|
1266
1266
|
return !0;
|
|
1267
1267
|
}
|
|
@@ -1290,7 +1290,7 @@ class Mt extends p {
|
|
|
1290
1290
|
// Persistence storage key
|
|
1291
1291
|
PERSISTENCE_KEY = "tl:circuit_breaker_events";
|
|
1292
1292
|
constructor(e, t = null) {
|
|
1293
|
-
super(), this.storageManager = e, this.googleAnalytics = t, this.samplingManager = new It(), this.tagsManager = new Tt(), this.dataSender = new wt(e), this.restoreEventsFromStorage(),
|
|
1293
|
+
super(), this.storageManager = e, this.googleAnalytics = t, this.samplingManager = new It(), this.tagsManager = new Tt(), this.dataSender = new wt(e), this.restoreEventsFromStorage(), n.debug("EventManager", "EventManager initialized", {
|
|
1294
1294
|
hasGoogleAnalytics: !!t,
|
|
1295
1295
|
restoredEventsCount: this.eventsQueue.length
|
|
1296
1296
|
});
|
|
@@ -1299,28 +1299,28 @@ class Mt extends p {
|
|
|
1299
1299
|
type: e,
|
|
1300
1300
|
page_url: t,
|
|
1301
1301
|
from_page_url: s,
|
|
1302
|
-
scroll_data:
|
|
1302
|
+
scroll_data: i,
|
|
1303
1303
|
click_data: a,
|
|
1304
1304
|
custom_event: o,
|
|
1305
1305
|
web_vitals: l,
|
|
1306
1306
|
session_end_reason: c,
|
|
1307
1307
|
session_start_recovered: d
|
|
1308
1308
|
}) {
|
|
1309
|
-
if (
|
|
1309
|
+
if (n.info("EventManager", `📥 Event captured: ${e}`, {
|
|
1310
1310
|
type: e,
|
|
1311
1311
|
page_url: t,
|
|
1312
1312
|
hasCustomEvent: !!o,
|
|
1313
1313
|
hasClickData: !!a,
|
|
1314
|
-
hasScrollData: !!
|
|
1314
|
+
hasScrollData: !!i,
|
|
1315
1315
|
hasWebVitals: !!l
|
|
1316
1316
|
}), !this.samplingManager.shouldSampleEvent(e, l)) {
|
|
1317
|
-
|
|
1317
|
+
n.debug("EventManager", "Event filtered by sampling", { type: e, samplingActive: !0 });
|
|
1318
1318
|
return;
|
|
1319
1319
|
}
|
|
1320
1320
|
if (this.isDuplicatedEvent({
|
|
1321
1321
|
type: e,
|
|
1322
1322
|
page_url: t,
|
|
1323
|
-
scroll_data:
|
|
1323
|
+
scroll_data: i,
|
|
1324
1324
|
click_data: a,
|
|
1325
1325
|
custom_event: o,
|
|
1326
1326
|
web_vitals: l,
|
|
@@ -1332,7 +1332,7 @@ class Mt extends p {
|
|
|
1332
1332
|
const H = this.eventsQueue.at(-1);
|
|
1333
1333
|
H && (H.timestamp = k);
|
|
1334
1334
|
}
|
|
1335
|
-
this.lastEvent && (this.lastEvent.timestamp = k),
|
|
1335
|
+
this.lastEvent && (this.lastEvent.timestamp = k), n.debug("EventManager", "Duplicate event detected, timestamp updated", {
|
|
1336
1336
|
type: e,
|
|
1337
1337
|
queueLength: this.eventsQueue.length
|
|
1338
1338
|
});
|
|
@@ -1340,7 +1340,7 @@ class Mt extends p {
|
|
|
1340
1340
|
}
|
|
1341
1341
|
const g = t || this.get("pageUrl"), y = yt(g, this.get("config").excludedUrlPaths), I = this.get("hasStartSession"), A = e == h.SESSION_END;
|
|
1342
1342
|
if (y && (!A || A && !I)) {
|
|
1343
|
-
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
1343
|
+
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.debug("EventManager", `Event ${e} on excluded route: ${t}`);
|
|
1344
1344
|
return;
|
|
1345
1345
|
}
|
|
1346
1346
|
const U = e === h.SESSION_START;
|
|
@@ -1351,7 +1351,7 @@ class Mt extends p {
|
|
|
1351
1351
|
timestamp: Date.now(),
|
|
1352
1352
|
...U && { referrer: document.referrer || "Direct" },
|
|
1353
1353
|
...s && !y ? { from_page_url: s } : {},
|
|
1354
|
-
...
|
|
1354
|
+
...i && { scroll_data: i },
|
|
1355
1355
|
...a && { click_data: a },
|
|
1356
1356
|
...o && { custom_event: o },
|
|
1357
1357
|
...ie && { utm: ie },
|
|
@@ -1372,24 +1372,24 @@ class Mt extends p {
|
|
|
1372
1372
|
this.eventsQueueIntervalId && (clearInterval(this.eventsQueueIntervalId), this.eventsQueueIntervalId = null, this.intervalActive = !1), this.circuitResetTimeoutId && (clearTimeout(this.circuitResetTimeoutId), this.circuitResetTimeoutId = null), this.eventsQueue.length > 0 && this.persistEventsToStorage(), this.eventFingerprints.clear(), this.circuitOpen = !1, this.circuitOpenTime = 0, this.failureCount = 0, this.backoffDelay = b.INITIAL_BACKOFF_DELAY_MS, this.lastEvent = null, this.dataSender.stop();
|
|
1373
1373
|
}
|
|
1374
1374
|
processAndSend(e) {
|
|
1375
|
-
if (
|
|
1375
|
+
if (n.info("EventManager", `🔄 Event processed and queued: ${e.type}`, {
|
|
1376
1376
|
type: e.type,
|
|
1377
1377
|
timestamp: e.timestamp,
|
|
1378
1378
|
page_url: e.page_url,
|
|
1379
1379
|
queueLengthBefore: this.eventsQueue.length
|
|
1380
1380
|
}), this.get("config").ipExcluded) {
|
|
1381
|
-
|
|
1381
|
+
n.info("EventManager", "❌ Event blocked: IP excluded");
|
|
1382
1382
|
return;
|
|
1383
1383
|
}
|
|
1384
1384
|
if (this.eventsQueue.push(e), this.eventsQueue.length > ne) {
|
|
1385
1385
|
const t = this.eventsQueue.shift();
|
|
1386
|
-
|
|
1386
|
+
n.warn("EventManager", "Event queue overflow, oldest event removed", {
|
|
1387
1387
|
maxLength: ne,
|
|
1388
1388
|
currentLength: this.eventsQueue.length,
|
|
1389
1389
|
removedEventType: t?.type
|
|
1390
1390
|
});
|
|
1391
1391
|
}
|
|
1392
|
-
if (this.eventsQueueIntervalId || (this.initEventsQueueInterval(),
|
|
1392
|
+
if (this.eventsQueueIntervalId || (this.initEventsQueueInterval(), n.info("EventManager", "⏰ Event sender initialized - queue will be sent periodically", {
|
|
1393
1393
|
queueLength: this.eventsQueue.length
|
|
1394
1394
|
})), this.googleAnalytics && e.type === h.CUSTOM) {
|
|
1395
1395
|
const t = e.custom_event;
|
|
@@ -1397,7 +1397,7 @@ class Mt extends p {
|
|
|
1397
1397
|
}
|
|
1398
1398
|
}
|
|
1399
1399
|
trackGoogleAnalyticsEvent(e) {
|
|
1400
|
-
this.get("config").mode === "qa" || this.get("config").mode === "debug" ?
|
|
1400
|
+
this.get("config").mode === "qa" || this.get("config").mode === "debug" ? n.debug("EventManager", `Google Analytics event: ${JSON.stringify(e)}`) : this.googleAnalytics && this.googleAnalytics.trackEvent(e.name, e.metadata ?? {});
|
|
1401
1401
|
}
|
|
1402
1402
|
initEventsQueueInterval() {
|
|
1403
1403
|
if (this.eventsQueueIntervalId || this.intervalActive)
|
|
@@ -1425,19 +1425,19 @@ class Mt extends p {
|
|
|
1425
1425
|
sendEventsQueue() {
|
|
1426
1426
|
if (this.eventsQueue.length === 0)
|
|
1427
1427
|
return;
|
|
1428
|
-
if (
|
|
1428
|
+
if (n.info("EventManager", "📤 Preparing to send event queue", {
|
|
1429
1429
|
queueLength: this.eventsQueue.length,
|
|
1430
1430
|
hasSessionId: !!this.get("sessionId"),
|
|
1431
1431
|
circuitOpen: this.circuitOpen
|
|
1432
1432
|
}), this.circuitOpen) {
|
|
1433
1433
|
const s = Date.now() - this.circuitOpenTime;
|
|
1434
1434
|
if (s >= b.RECOVERY_TIME_MS)
|
|
1435
|
-
this.resetCircuitBreaker(),
|
|
1435
|
+
this.resetCircuitBreaker(), n.info("EventManager", "Circuit breaker reset after timeout", {
|
|
1436
1436
|
timeSinceOpen: s,
|
|
1437
1437
|
recoveryTime: b.RECOVERY_TIME_MS
|
|
1438
1438
|
});
|
|
1439
1439
|
else {
|
|
1440
|
-
|
|
1440
|
+
n.debug("EventManager", "Circuit breaker is open - skipping event sending", {
|
|
1441
1441
|
queueLength: this.eventsQueue.length,
|
|
1442
1442
|
failureCount: this.failureCount,
|
|
1443
1443
|
timeSinceOpen: s,
|
|
@@ -1447,15 +1447,15 @@ class Mt extends p {
|
|
|
1447
1447
|
}
|
|
1448
1448
|
}
|
|
1449
1449
|
if (!this.get("sessionId")) {
|
|
1450
|
-
|
|
1450
|
+
n.info("EventManager", `⏳ Queue waiting: ${this.eventsQueue.length} events waiting for active session`);
|
|
1451
1451
|
return;
|
|
1452
1452
|
}
|
|
1453
1453
|
const e = this.buildEventsPayload();
|
|
1454
|
-
this.dataSender.sendEventsQueue(e) ? (
|
|
1454
|
+
this.dataSender.sendEventsQueue(e) ? (n.info("EventManager", "✅ Event queue sent successfully", {
|
|
1455
1455
|
eventsCount: e.events.length,
|
|
1456
1456
|
sessionId: e.session_id,
|
|
1457
1457
|
uniqueEventsAfterDedup: e.events.length
|
|
1458
|
-
}), this.eventsQueue = [], this.failureCount = 0, this.backoffDelay = b.INITIAL_BACKOFF_DELAY_MS, this.clearPersistedEvents()) : (
|
|
1458
|
+
}), this.eventsQueue = [], this.failureCount = 0, this.backoffDelay = b.INITIAL_BACKOFF_DELAY_MS, this.clearPersistedEvents()) : (n.info("EventManager", "❌ Failed to send event queue", {
|
|
1459
1459
|
eventsCount: e.events.length,
|
|
1460
1460
|
failureCount: this.failureCount + 1,
|
|
1461
1461
|
willOpenCircuit: this.failureCount + 1 >= this.MAX_FAILURES
|
|
@@ -1464,11 +1464,11 @@ class Mt extends p {
|
|
|
1464
1464
|
buildEventsPayload() {
|
|
1465
1465
|
const e = /* @__PURE__ */ new Map();
|
|
1466
1466
|
for (const s of this.eventsQueue) {
|
|
1467
|
-
let
|
|
1468
|
-
s.click_data && (
|
|
1467
|
+
let i = `${s.type}_${s.page_url}`;
|
|
1468
|
+
s.click_data && (i += `_${s.click_data.x}_${s.click_data.y}`), s.scroll_data && (i += `_${s.scroll_data.depth}_${s.scroll_data.direction}`), s.custom_event && (i += `_${s.custom_event.name}`), s.web_vitals && (i += `_${s.web_vitals.type}`), e.has(i) || e.set(i, s);
|
|
1469
1469
|
}
|
|
1470
1470
|
const t = [...e.values()];
|
|
1471
|
-
return t.sort((s,
|
|
1471
|
+
return t.sort((s, i) => s.timestamp - i.timestamp), {
|
|
1472
1472
|
user_id: this.get("userId"),
|
|
1473
1473
|
session_id: this.get("sessionId"),
|
|
1474
1474
|
device: this.get("device"),
|
|
@@ -1482,14 +1482,14 @@ class Mt extends p {
|
|
|
1482
1482
|
getEventFingerprint(e) {
|
|
1483
1483
|
const t = `${e.type}_${e.page_url}`;
|
|
1484
1484
|
if (e.click_data) {
|
|
1485
|
-
const s = Math.round((e.click_data.x || 0) / F) * F,
|
|
1486
|
-
return `${t}_${s}_${
|
|
1485
|
+
const s = Math.round((e.click_data.x || 0) / F) * F, i = Math.round((e.click_data.y || 0) / F) * F;
|
|
1486
|
+
return `${t}_${s}_${i}_${e.click_data.tag}_${e.click_data.id}`;
|
|
1487
1487
|
}
|
|
1488
1488
|
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;
|
|
1489
1489
|
}
|
|
1490
1490
|
isDuplicatedEvent(e) {
|
|
1491
|
-
const t = this.getEventFingerprint(e), s = this.eventFingerprints.get(t) ?? 0,
|
|
1492
|
-
return
|
|
1491
|
+
const t = this.getEventFingerprint(e), s = this.eventFingerprints.get(t) ?? 0, i = Date.now();
|
|
1492
|
+
return i - s < de ? !0 : (this.eventFingerprints.set(t, i), this.cleanupOldFingerprints(), !1);
|
|
1493
1493
|
}
|
|
1494
1494
|
/**
|
|
1495
1495
|
* Cleans up old fingerprints to prevent memory leaks
|
|
@@ -1498,11 +1498,11 @@ class Mt extends p {
|
|
|
1498
1498
|
if (this.eventFingerprints.size <= Oe)
|
|
1499
1499
|
return;
|
|
1500
1500
|
const e = Date.now(), t = de * Fe, s = [];
|
|
1501
|
-
for (const [
|
|
1502
|
-
e - a > t && s.push(
|
|
1503
|
-
for (const
|
|
1504
|
-
this.eventFingerprints.delete(
|
|
1505
|
-
|
|
1501
|
+
for (const [i, a] of this.eventFingerprints)
|
|
1502
|
+
e - a > t && s.push(i);
|
|
1503
|
+
for (const i of s)
|
|
1504
|
+
this.eventFingerprints.delete(i);
|
|
1505
|
+
n.debug("EventManager", "Cleaned up old event fingerprints", {
|
|
1506
1506
|
totalFingerprints: this.eventFingerprints.size + s.length,
|
|
1507
1507
|
cleanedCount: s.length,
|
|
1508
1508
|
remainingCount: this.eventFingerprints.size,
|
|
@@ -1515,7 +1515,7 @@ class Mt extends p {
|
|
|
1515
1515
|
openCircuitBreaker() {
|
|
1516
1516
|
this.circuitOpen = !0, this.circuitOpenTime = Date.now(), this.persistEventsToStorage();
|
|
1517
1517
|
const e = this.eventsQueue.length;
|
|
1518
|
-
this.eventsQueue = [],
|
|
1518
|
+
this.eventsQueue = [], n.warn("EventManager", "Circuit breaker opened with time-based recovery", {
|
|
1519
1519
|
maxFailures: this.MAX_FAILURES,
|
|
1520
1520
|
persistedEvents: e,
|
|
1521
1521
|
failureCount: this.failureCount,
|
|
@@ -1530,9 +1530,9 @@ class Mt extends p {
|
|
|
1530
1530
|
* Resets the circuit breaker and attempts to restore persisted events
|
|
1531
1531
|
*/
|
|
1532
1532
|
resetCircuitBreaker() {
|
|
1533
|
-
this.circuitOpen = !1, this.circuitOpenTime = 0, this.failureCount = 0, this.circuitResetTimeoutId = null,
|
|
1533
|
+
this.circuitOpen = !1, this.circuitOpenTime = 0, this.failureCount = 0, this.circuitResetTimeoutId = null, n.info("EventManager", "Circuit breaker reset - attempting to restore events", {
|
|
1534
1534
|
currentQueueLength: this.eventsQueue.length
|
|
1535
|
-
}), this.restoreEventsFromStorage(),
|
|
1535
|
+
}), this.restoreEventsFromStorage(), n.info("EventManager", "Circuit breaker reset completed", {
|
|
1536
1536
|
restoredQueueLength: this.eventsQueue.length,
|
|
1537
1537
|
backoffDelay: this.backoffDelay
|
|
1538
1538
|
});
|
|
@@ -1549,12 +1549,12 @@ class Mt extends p {
|
|
|
1549
1549
|
timestamp: Date.now(),
|
|
1550
1550
|
failureCount: this.failureCount
|
|
1551
1551
|
};
|
|
1552
|
-
this.storageManager.setItem(this.PERSISTENCE_KEY, JSON.stringify(e)),
|
|
1552
|
+
this.storageManager.setItem(this.PERSISTENCE_KEY, JSON.stringify(e)), n.debug("EventManager", "Events persisted to storage for recovery", {
|
|
1553
1553
|
eventsCount: this.eventsQueue.length,
|
|
1554
1554
|
failureCount: this.failureCount
|
|
1555
1555
|
});
|
|
1556
1556
|
} catch (e) {
|
|
1557
|
-
|
|
1557
|
+
n.warn("EventManager", "Failed to persist events to storage", {
|
|
1558
1558
|
error: e instanceof Error ? e.message : "Unknown error",
|
|
1559
1559
|
eventsCount: this.eventsQueue.length
|
|
1560
1560
|
});
|
|
@@ -1568,20 +1568,20 @@ class Mt extends p {
|
|
|
1568
1568
|
const e = this.storageManager.getItem(this.PERSISTENCE_KEY);
|
|
1569
1569
|
if (!e)
|
|
1570
1570
|
return;
|
|
1571
|
-
const t = JSON.parse(e), s = Date.now(),
|
|
1572
|
-
if (s - t.timestamp >
|
|
1573
|
-
this.clearPersistedEvents(),
|
|
1571
|
+
const t = JSON.parse(e), s = Date.now(), i = Qe;
|
|
1572
|
+
if (s - t.timestamp > i) {
|
|
1573
|
+
this.clearPersistedEvents(), n.debug("EventManager", "Cleared expired persisted events", {
|
|
1574
1574
|
age: s - t.timestamp,
|
|
1575
|
-
maxAge:
|
|
1575
|
+
maxAge: i
|
|
1576
1576
|
});
|
|
1577
1577
|
return;
|
|
1578
1578
|
}
|
|
1579
|
-
Array.isArray(t.events) && t.events.length > 0 && this.eventsQueue.length === 0 && (this.eventsQueue = t.events,
|
|
1579
|
+
Array.isArray(t.events) && t.events.length > 0 && this.eventsQueue.length === 0 && (this.eventsQueue = t.events, n.info("EventManager", "Restored events from storage", {
|
|
1580
1580
|
restoredCount: t.events.length,
|
|
1581
1581
|
originalFailureCount: t.failureCount ?? 0
|
|
1582
1582
|
}));
|
|
1583
1583
|
} catch (e) {
|
|
1584
|
-
|
|
1584
|
+
n.warn("EventManager", "Failed to restore events from storage", {
|
|
1585
1585
|
error: e instanceof Error ? e.message : "Unknown error"
|
|
1586
1586
|
}), this.clearPersistedEvents();
|
|
1587
1587
|
}
|
|
@@ -1591,9 +1591,9 @@ class Mt extends p {
|
|
|
1591
1591
|
*/
|
|
1592
1592
|
clearPersistedEvents() {
|
|
1593
1593
|
try {
|
|
1594
|
-
this.storageManager.removeItem(this.PERSISTENCE_KEY),
|
|
1594
|
+
this.storageManager.removeItem(this.PERSISTENCE_KEY), n.debug("EventManager", "Cleared persisted events from storage");
|
|
1595
1595
|
} catch (e) {
|
|
1596
|
-
|
|
1596
|
+
n.warn("EventManager", "Failed to clear persisted events", {
|
|
1597
1597
|
error: e instanceof Error ? e.message : "Unknown error"
|
|
1598
1598
|
});
|
|
1599
1599
|
}
|
|
@@ -1622,14 +1622,14 @@ class _t {
|
|
|
1622
1622
|
try {
|
|
1623
1623
|
window.addEventListener("scroll", this.onActivity, this.options), window.addEventListener("resize", this.onActivity, this.options), window.addEventListener("focus", this.onActivity, this.options);
|
|
1624
1624
|
} catch (e) {
|
|
1625
|
-
throw
|
|
1625
|
+
throw n.error("ActivityListenerManager", "Failed to setup activity listeners", { error: e }), e;
|
|
1626
1626
|
}
|
|
1627
1627
|
}
|
|
1628
1628
|
cleanup() {
|
|
1629
1629
|
try {
|
|
1630
1630
|
window.removeEventListener("scroll", this.onActivity), window.removeEventListener("resize", this.onActivity), window.removeEventListener("focus", this.onActivity);
|
|
1631
1631
|
} catch (e) {
|
|
1632
|
-
|
|
1632
|
+
n.warn("ActivityListenerManager", "Error during activity listeners cleanup", { error: e });
|
|
1633
1633
|
}
|
|
1634
1634
|
}
|
|
1635
1635
|
}
|
|
@@ -1644,14 +1644,14 @@ class Ct {
|
|
|
1644
1644
|
try {
|
|
1645
1645
|
window.addEventListener("touchstart", this.onActivity, this.options), window.addEventListener("touchmove", this.onActivity, this.options), window.addEventListener("touchend", this.onActivity, this.options), window.addEventListener("orientationchange", this.onActivity, this.options), "DeviceMotionEvent" in window && window.addEventListener("devicemotion", this.handleDeviceMotion, this.options);
|
|
1646
1646
|
} catch (e) {
|
|
1647
|
-
throw
|
|
1647
|
+
throw n.error("TouchListenerManager", "Failed to setup touch listeners", { error: e }), e;
|
|
1648
1648
|
}
|
|
1649
1649
|
}
|
|
1650
1650
|
cleanup() {
|
|
1651
1651
|
try {
|
|
1652
1652
|
window.removeEventListener("touchstart", this.onActivity), window.removeEventListener("touchmove", this.onActivity), window.removeEventListener("touchend", this.onActivity), window.removeEventListener("orientationchange", this.onActivity), "DeviceMotionEvent" in window && window.removeEventListener("devicemotion", this.handleDeviceMotion);
|
|
1653
1653
|
} catch (e) {
|
|
1654
|
-
|
|
1654
|
+
n.warn("TouchListenerManager", "Error during touch listeners cleanup", { error: e });
|
|
1655
1655
|
}
|
|
1656
1656
|
}
|
|
1657
1657
|
handleDeviceMotion = (e) => {
|
|
@@ -1659,7 +1659,7 @@ class Ct {
|
|
|
1659
1659
|
const t = e.acceleration;
|
|
1660
1660
|
t && Math.abs(t.x ?? 0) + Math.abs(t.y ?? 0) + Math.abs(t.z ?? 0) > this.motionThreshold && this.onActivity();
|
|
1661
1661
|
} catch (t) {
|
|
1662
|
-
|
|
1662
|
+
n.warn("TouchListenerManager", "Error handling device motion event", { error: t });
|
|
1663
1663
|
}
|
|
1664
1664
|
};
|
|
1665
1665
|
}
|
|
@@ -1673,14 +1673,14 @@ class Lt {
|
|
|
1673
1673
|
try {
|
|
1674
1674
|
window.addEventListener("mousemove", this.onActivity, this.options), window.addEventListener("mousedown", this.onActivity, this.options), window.addEventListener("wheel", this.onActivity, this.options);
|
|
1675
1675
|
} catch (e) {
|
|
1676
|
-
throw
|
|
1676
|
+
throw n.error("MouseListenerManager", "Failed to setup mouse listeners", { error: e }), e;
|
|
1677
1677
|
}
|
|
1678
1678
|
}
|
|
1679
1679
|
cleanup() {
|
|
1680
1680
|
try {
|
|
1681
1681
|
window.removeEventListener("mousemove", this.onActivity), window.removeEventListener("mousedown", this.onActivity), window.removeEventListener("wheel", this.onActivity);
|
|
1682
1682
|
} catch (e) {
|
|
1683
|
-
|
|
1683
|
+
n.warn("MouseListenerManager", "Error during mouse listeners cleanup", { error: e });
|
|
1684
1684
|
}
|
|
1685
1685
|
}
|
|
1686
1686
|
}
|
|
@@ -1694,14 +1694,14 @@ class Rt {
|
|
|
1694
1694
|
try {
|
|
1695
1695
|
window.addEventListener("keydown", this.onActivity, this.options), window.addEventListener("keypress", this.onActivity, this.options);
|
|
1696
1696
|
} catch (e) {
|
|
1697
|
-
throw
|
|
1697
|
+
throw n.error("KeyboardListenerManager", "Failed to setup keyboard listeners", { error: e }), e;
|
|
1698
1698
|
}
|
|
1699
1699
|
}
|
|
1700
1700
|
cleanup() {
|
|
1701
1701
|
try {
|
|
1702
1702
|
window.removeEventListener("keydown", this.onActivity), window.removeEventListener("keypress", this.onActivity);
|
|
1703
1703
|
} catch (e) {
|
|
1704
|
-
|
|
1704
|
+
n.warn("KeyboardListenerManager", "Error during keyboard listeners cleanup", { error: e });
|
|
1705
1705
|
}
|
|
1706
1706
|
}
|
|
1707
1707
|
}
|
|
@@ -1717,28 +1717,28 @@ class kt {
|
|
|
1717
1717
|
try {
|
|
1718
1718
|
"visibilityState" in document && document.addEventListener("visibilitychange", this.onVisibilityChange, this.options), window.addEventListener("blur", this.onVisibilityChange, this.options), window.addEventListener("focus", this.onActivity, this.options), "onLine" in navigator && (window.addEventListener("online", this.onActivity, this.options), window.addEventListener("offline", this.onVisibilityChange, this.options)), this.isMobile && this.setupMobileEvents();
|
|
1719
1719
|
} catch (e) {
|
|
1720
|
-
throw
|
|
1720
|
+
throw n.error("VisibilityListenerManager", "Failed to setup visibility listeners", { error: e }), e;
|
|
1721
1721
|
}
|
|
1722
1722
|
}
|
|
1723
1723
|
cleanup() {
|
|
1724
1724
|
try {
|
|
1725
1725
|
"visibilityState" in document && document.removeEventListener("visibilitychange", this.onVisibilityChange), window.removeEventListener("blur", this.onVisibilityChange), window.removeEventListener("focus", this.onActivity), "onLine" in navigator && (window.removeEventListener("online", this.onActivity), window.removeEventListener("offline", this.onVisibilityChange)), this.isMobile && this.cleanupMobileEvents();
|
|
1726
1726
|
} catch (e) {
|
|
1727
|
-
|
|
1727
|
+
n.warn("VisibilityListenerManager", "Error during visibility listeners cleanup", { error: e });
|
|
1728
1728
|
}
|
|
1729
1729
|
}
|
|
1730
1730
|
setupMobileEvents() {
|
|
1731
1731
|
try {
|
|
1732
1732
|
document.addEventListener("pause", this.onVisibilityChange, this.options), document.addEventListener("resume", this.onActivity, this.options), "orientation" in screen && screen.orientation.addEventListener("change", this.onActivity, this.options), window.addEventListener("pageshow", this.onActivity, this.options), window.addEventListener("pagehide", this.onActivity, this.options);
|
|
1733
1733
|
} catch (e) {
|
|
1734
|
-
|
|
1734
|
+
n.warn("VisibilityListenerManager", "Failed to setup mobile listeners", { error: e });
|
|
1735
1735
|
}
|
|
1736
1736
|
}
|
|
1737
1737
|
cleanupMobileEvents() {
|
|
1738
1738
|
try {
|
|
1739
1739
|
document.removeEventListener("pause", this.onVisibilityChange), document.removeEventListener("resume", this.onActivity), "orientation" in screen && screen.orientation.removeEventListener("change", this.onActivity), window.removeEventListener("pageshow", this.onActivity), window.removeEventListener("pagehide", this.onActivity);
|
|
1740
1740
|
} catch (e) {
|
|
1741
|
-
|
|
1741
|
+
n.warn("VisibilityListenerManager", "Error during mobile listeners cleanup", { error: e });
|
|
1742
1742
|
}
|
|
1743
1743
|
}
|
|
1744
1744
|
}
|
|
@@ -1752,14 +1752,14 @@ class Nt {
|
|
|
1752
1752
|
try {
|
|
1753
1753
|
window.addEventListener("beforeunload", this.onInactivity, this.options), window.addEventListener("pagehide", this.onInactivity, this.options);
|
|
1754
1754
|
} catch (e) {
|
|
1755
|
-
throw
|
|
1755
|
+
throw n.error("UnloadListenerManager", "Failed to setup unload listeners", { error: e }), e;
|
|
1756
1756
|
}
|
|
1757
1757
|
}
|
|
1758
1758
|
cleanup() {
|
|
1759
1759
|
try {
|
|
1760
1760
|
window.removeEventListener("beforeunload", this.onInactivity), window.removeEventListener("pagehide", this.onInactivity);
|
|
1761
1761
|
} catch (e) {
|
|
1762
|
-
|
|
1762
|
+
n.warn("UnloadListenerManager", "Error during unload listeners cleanup", { error: e });
|
|
1763
1763
|
}
|
|
1764
1764
|
}
|
|
1765
1765
|
}
|
|
@@ -1769,48 +1769,48 @@ class Ce extends p {
|
|
|
1769
1769
|
eventManager;
|
|
1770
1770
|
projectId;
|
|
1771
1771
|
debugMode;
|
|
1772
|
-
constructor(e, t, s,
|
|
1772
|
+
constructor(e, t, s, i) {
|
|
1773
1773
|
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 = {
|
|
1774
1774
|
recoveryWindowMs: this.calculateRecoveryWindow(),
|
|
1775
1775
|
maxRecoveryAttempts: Ke,
|
|
1776
1776
|
contextPreservation: !0,
|
|
1777
|
-
...
|
|
1777
|
+
...i
|
|
1778
1778
|
};
|
|
1779
1779
|
}
|
|
1780
1780
|
/**
|
|
1781
1781
|
* Attempt to recover a session
|
|
1782
1782
|
*/
|
|
1783
1783
|
attemptSessionRecovery(e) {
|
|
1784
|
-
this.debugMode &&
|
|
1784
|
+
this.debugMode && n.debug("SessionRecovery", "Attempting session recovery");
|
|
1785
1785
|
const t = this.getStoredRecoveryAttempts(), s = this.getLastRecoveryAttempt();
|
|
1786
1786
|
if (!this.canAttemptRecovery(s))
|
|
1787
|
-
return this.debugMode &&
|
|
1787
|
+
return this.debugMode && n.debug(
|
|
1788
1788
|
"SessionRecovery",
|
|
1789
1789
|
"Session recovery not possible - outside recovery window or max attempts reached"
|
|
1790
1790
|
), {
|
|
1791
1791
|
recovered: !1
|
|
1792
1792
|
};
|
|
1793
|
-
const
|
|
1794
|
-
if (!
|
|
1795
|
-
return this.debugMode &&
|
|
1793
|
+
const i = s?.context;
|
|
1794
|
+
if (!i)
|
|
1795
|
+
return this.debugMode && n.debug("SessionRecovery", "No session context available for recovery"), {
|
|
1796
1796
|
recovered: !1
|
|
1797
1797
|
};
|
|
1798
1798
|
const a = Date.now();
|
|
1799
|
-
if (a -
|
|
1800
|
-
return this.debugMode &&
|
|
1799
|
+
if (a - i.lastActivity > this.config.recoveryWindowMs)
|
|
1800
|
+
return this.debugMode && n.debug("SessionRecovery", "Session recovery failed - outside recovery window"), {
|
|
1801
1801
|
recovered: !1
|
|
1802
1802
|
};
|
|
1803
|
-
const l =
|
|
1803
|
+
const l = i.sessionId, c = (s?.attempt ?? 0) + 1, d = {
|
|
1804
1804
|
sessionId: e ?? l,
|
|
1805
1805
|
timestamp: a,
|
|
1806
1806
|
attempt: c,
|
|
1807
1807
|
context: {
|
|
1808
|
-
...
|
|
1808
|
+
...i,
|
|
1809
1809
|
recoveryAttempts: c,
|
|
1810
1810
|
lastActivity: a
|
|
1811
1811
|
}
|
|
1812
1812
|
};
|
|
1813
|
-
return t.push(d), this.storeRecoveryAttempts(t), this.debugMode &&
|
|
1813
|
+
return t.push(d), this.storeRecoveryAttempts(t), this.debugMode && n.debug("SessionRecovery", `Session recovery successful: recovery of session ${l}`), {
|
|
1814
1814
|
recovered: !0,
|
|
1815
1815
|
recoveredSessionId: l,
|
|
1816
1816
|
context: d.context
|
|
@@ -1824,10 +1824,10 @@ class Ce extends p {
|
|
|
1824
1824
|
Math.min(t, X),
|
|
1825
1825
|
K
|
|
1826
1826
|
);
|
|
1827
|
-
return this.debugMode && (t > X ?
|
|
1827
|
+
return this.debugMode && (t > X ? n.warn(
|
|
1828
1828
|
"SessionRecovery",
|
|
1829
1829
|
`Recovery window capped at ${X}ms (24h). Calculated: ${t}ms`
|
|
1830
|
-
) : t < K &&
|
|
1830
|
+
) : t < K && n.warn(
|
|
1831
1831
|
"SessionRecovery",
|
|
1832
1832
|
`Recovery window increased to minimum ${K}ms (2min). Calculated: ${t}ms`
|
|
1833
1833
|
)), s;
|
|
@@ -1850,10 +1850,10 @@ class Ce extends p {
|
|
|
1850
1850
|
context: e
|
|
1851
1851
|
};
|
|
1852
1852
|
t.push(s);
|
|
1853
|
-
const
|
|
1854
|
-
t.length >
|
|
1853
|
+
const i = 5;
|
|
1854
|
+
t.length > i && t.splice(0, t.length - i), this.storeRecoveryAttempts(t), this.debugMode && n.debug("SessionRecovery", `Stored session context for recovery: ${e.sessionId}`);
|
|
1855
1855
|
} catch (t) {
|
|
1856
|
-
this.debugMode &&
|
|
1856
|
+
this.debugMode && n.warn("SessionRecovery", "Failed to store session context for recovery", { error: t });
|
|
1857
1857
|
}
|
|
1858
1858
|
}
|
|
1859
1859
|
/**
|
|
@@ -1866,7 +1866,7 @@ class Ce extends p {
|
|
|
1866
1866
|
} catch (e) {
|
|
1867
1867
|
if (this.debugMode) {
|
|
1868
1868
|
const t = this.storageManager.getItem(V(this.projectId));
|
|
1869
|
-
|
|
1869
|
+
n.warn(
|
|
1870
1870
|
"SessionRecovery",
|
|
1871
1871
|
`Failed to parse stored recovery attempts for projectId ${this.projectId}. Data: ${t}`,
|
|
1872
1872
|
{ error: e }
|
|
@@ -1882,7 +1882,7 @@ class Ce extends p {
|
|
|
1882
1882
|
try {
|
|
1883
1883
|
this.storageManager.setItem(V(this.projectId), JSON.stringify(e));
|
|
1884
1884
|
} catch (t) {
|
|
1885
|
-
this.debugMode &&
|
|
1885
|
+
this.debugMode && n.warn("SessionRecovery", "Failed to store recovery attempts", { error: t });
|
|
1886
1886
|
}
|
|
1887
1887
|
}
|
|
1888
1888
|
/**
|
|
@@ -1896,8 +1896,8 @@ class Ce extends p {
|
|
|
1896
1896
|
* Clean up old recovery attempts
|
|
1897
1897
|
*/
|
|
1898
1898
|
cleanupOldRecoveryAttempts() {
|
|
1899
|
-
const e = this.getStoredRecoveryAttempts(), t = Date.now(), s = e.filter((
|
|
1900
|
-
s.length !== e.length && (this.storeRecoveryAttempts(s), this.debugMode &&
|
|
1899
|
+
const e = this.getStoredRecoveryAttempts(), t = Date.now(), s = e.filter((i) => t - i.timestamp <= this.config.recoveryWindowMs);
|
|
1900
|
+
s.length !== e.length && (this.storeRecoveryAttempts(s), this.debugMode && n.debug("SessionRecovery", `Cleaned up ${e.length - s.length} old recovery attempts`));
|
|
1901
1901
|
}
|
|
1902
1902
|
/**
|
|
1903
1903
|
* Check if there's a recoverable session.
|
|
@@ -1923,7 +1923,7 @@ class Ce extends p {
|
|
|
1923
1923
|
* Clear all stored recovery data
|
|
1924
1924
|
*/
|
|
1925
1925
|
clearRecoveryData() {
|
|
1926
|
-
this.storageManager.removeItem(V(this.projectId)), this.debugMode &&
|
|
1926
|
+
this.storageManager.removeItem(V(this.projectId)), this.debugMode && n.debug("SessionRecovery", "Cleared all recovery data");
|
|
1927
1927
|
}
|
|
1928
1928
|
}
|
|
1929
1929
|
class Ut extends p {
|
|
@@ -1983,7 +1983,7 @@ class Ut extends p {
|
|
|
1983
1983
|
crossTabConflicts: 0,
|
|
1984
1984
|
lastHealthCheck: Date.now()
|
|
1985
1985
|
};
|
|
1986
|
-
constructor(e, t, s,
|
|
1986
|
+
constructor(e, t, s, i, a) {
|
|
1987
1987
|
super(), this.config = {
|
|
1988
1988
|
throttleDelay: Te,
|
|
1989
1989
|
visibilityTimeout: Ve,
|
|
@@ -1995,7 +1995,7 @@ class Ut extends p {
|
|
|
1995
1995
|
maxRetries: 2,
|
|
1996
1996
|
debugMode: !1,
|
|
1997
1997
|
...a
|
|
1998
|
-
}, this.onActivity = e, this.onInactivity = t, this.eventManager = s ?? null, this.storageManager =
|
|
1998
|
+
}, this.onActivity = e, this.onInactivity = t, this.eventManager = s ?? null, this.storageManager = i ?? null, this.deviceCapabilities = this.detectDeviceCapabilities(), this.initializeRecoveryManager(), this.initializeListenerManagers(), this.setupAllListeners(), this.sessionEndConfig.enablePageUnloadHandlers && this.setupPageUnloadHandlers(), n.debug("SessionManager", "SessionManager initialized", {
|
|
1999
1999
|
sessionTimeout: this.config.timeout,
|
|
2000
2000
|
deviceCapabilities: this.deviceCapabilities,
|
|
2001
2001
|
unloadHandlersEnabled: this.sessionEndConfig.enablePageUnloadHandlers
|
|
@@ -2009,9 +2009,9 @@ class Ut extends p {
|
|
|
2009
2009
|
const e = this.get("config")?.id;
|
|
2010
2010
|
if (e)
|
|
2011
2011
|
try {
|
|
2012
|
-
this.recoveryManager = new Ce(this.storageManager, e, this.eventManager ?? void 0),
|
|
2012
|
+
this.recoveryManager = new Ce(this.storageManager, e, this.eventManager ?? void 0), n.debug("SessionManager", "Recovery manager initialized", { projectId: e });
|
|
2013
2013
|
} catch (t) {
|
|
2014
|
-
|
|
2014
|
+
n.error("SessionManager", "Failed to initialize recovery manager", { error: t, projectId: e });
|
|
2015
2015
|
}
|
|
2016
2016
|
}
|
|
2017
2017
|
/**
|
|
@@ -2039,13 +2039,13 @@ class Ut extends p {
|
|
|
2039
2039
|
const e = Date.now();
|
|
2040
2040
|
let t = "", s = !1;
|
|
2041
2041
|
if (this.recoveryManager?.hasRecoverableSession()) {
|
|
2042
|
-
const
|
|
2043
|
-
|
|
2042
|
+
const i = this.recoveryManager.attemptSessionRecovery();
|
|
2043
|
+
i.recovered && i.recoveredSessionId && (t = i.recoveredSessionId, s = !0, this.trackSessionHealth("recovery"), i.context ? (this.sessionStartTime = i.context.startTime, this.lastActivityTime = e) : (this.sessionStartTime = e, this.lastActivityTime = e), n.info("SessionManager", "Session successfully recovered", {
|
|
2044
2044
|
sessionId: t,
|
|
2045
2045
|
recoveryAttempts: this.sessionHealth.recoveryAttempts
|
|
2046
2046
|
}));
|
|
2047
2047
|
}
|
|
2048
|
-
return s || (t = $(), this.sessionStartTime = e, this.lastActivityTime = e,
|
|
2048
|
+
return s || (t = $(), this.sessionStartTime = e, this.lastActivityTime = e, n.info("SessionManager", "New session started", { sessionId: t })), this.isSessionActive = !0, this.resetInactivityTimer(), this.storeSessionContextForRecovery(), { sessionId: t, recovered: s };
|
|
2049
2049
|
}
|
|
2050
2050
|
endSession() {
|
|
2051
2051
|
if (this.sessionStartTime === 0)
|
|
@@ -2063,8 +2063,8 @@ class Ut extends p {
|
|
|
2063
2063
|
}), this.recoveryManager && (this.recoveryManager.cleanupOldRecoveryAttempts(), this.recoveryManager = null);
|
|
2064
2064
|
}
|
|
2065
2065
|
detectDeviceCapabilities() {
|
|
2066
|
-
const e = "ontouchstart" in window || navigator.maxTouchPoints > 0, t = window.matchMedia("(pointer: fine)").matches, s = !window.matchMedia("(pointer: coarse)").matches,
|
|
2067
|
-
return { hasTouch: e, hasMouse: t, hasKeyboard: s, isMobile:
|
|
2066
|
+
const e = "ontouchstart" in window || navigator.maxTouchPoints > 0, t = window.matchMedia("(pointer: fine)").matches, s = !window.matchMedia("(pointer: coarse)").matches, i = we() === E.Mobile;
|
|
2067
|
+
return { hasTouch: e, hasMouse: t, hasKeyboard: s, isMobile: i };
|
|
2068
2068
|
}
|
|
2069
2069
|
initializeListenerManagers() {
|
|
2070
2070
|
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(
|
|
@@ -2118,9 +2118,9 @@ class Ut extends p {
|
|
|
2118
2118
|
async endSessionManaged(e) {
|
|
2119
2119
|
return this.sessionEndLock = this.sessionEndLock.then(async () => {
|
|
2120
2120
|
if (this.sessionEndStats.totalSessionEnds++, this.sessionEndStats.reasonCounts[e]++, this.pendingSessionEnd)
|
|
2121
|
-
return this.sessionEndStats.duplicatePrevented++,
|
|
2121
|
+
return this.sessionEndStats.duplicatePrevented++, n.debug("SessionManager", "Session end already pending, waiting for completion", { reason: e }), this.waitForCompletion();
|
|
2122
2122
|
if (!this.shouldProceedWithSessionEnd(e))
|
|
2123
|
-
return this.sessionEndConfig.debugMode &&
|
|
2123
|
+
return this.sessionEndConfig.debugMode && n.debug(
|
|
2124
2124
|
"SessionManager",
|
|
2125
2125
|
`Session end skipped due to lower priority. Current: ${this.sessionEndReason}, Requested: ${e}`
|
|
2126
2126
|
), {
|
|
@@ -2169,27 +2169,27 @@ class Ut extends p {
|
|
|
2169
2169
|
event_trigger: e
|
|
2170
2170
|
}
|
|
2171
2171
|
}
|
|
2172
|
-
}), this.sessionEndConfig.debugMode &&
|
|
2172
|
+
}), this.sessionEndConfig.debugMode && n.warn(
|
|
2173
2173
|
"SessionManager",
|
|
2174
2174
|
`Session health degraded: ${this.sessionHealth.recoveryAttempts} recovery attempts`
|
|
2175
|
-
)), this.sessionEndConfig.debugMode &&
|
|
2175
|
+
)), this.sessionEndConfig.debugMode && n.debug("SessionManager", `Session health event tracked: ${e}`);
|
|
2176
2176
|
}
|
|
2177
2177
|
async performSessionEnd(e, t) {
|
|
2178
2178
|
const s = Date.now();
|
|
2179
|
-
let
|
|
2179
|
+
let i = 0;
|
|
2180
2180
|
try {
|
|
2181
|
-
if (
|
|
2181
|
+
if (n.info("SessionManager", "Starting session end", { method: t, reason: e, timestamp: s }), this.eventManager) {
|
|
2182
2182
|
this.eventManager.track({
|
|
2183
2183
|
type: h.SESSION_END,
|
|
2184
2184
|
session_end_reason: e
|
|
2185
|
-
}),
|
|
2185
|
+
}), i = this.eventManager.getQueueLength();
|
|
2186
2186
|
const o = await this.eventManager.flushImmediately();
|
|
2187
2187
|
this.cleanupSession();
|
|
2188
2188
|
const l = {
|
|
2189
2189
|
success: o,
|
|
2190
2190
|
reason: e,
|
|
2191
2191
|
timestamp: s,
|
|
2192
|
-
eventsFlushed:
|
|
2192
|
+
eventsFlushed: i,
|
|
2193
2193
|
method: t
|
|
2194
2194
|
};
|
|
2195
2195
|
return o ? this.sessionEndStats.successfulEnds++ : this.sessionEndStats.failedEnds++, l;
|
|
@@ -2204,11 +2204,11 @@ class Ut extends p {
|
|
|
2204
2204
|
};
|
|
2205
2205
|
return this.sessionEndStats.successfulEnds++, a;
|
|
2206
2206
|
} catch (a) {
|
|
2207
|
-
return this.sessionEndStats.failedEnds++,
|
|
2207
|
+
return this.sessionEndStats.failedEnds++, n.error("SessionManager", "Session end failed", { error: a, reason: e, method: t }), this.cleanupSession(), {
|
|
2208
2208
|
success: !1,
|
|
2209
2209
|
reason: e,
|
|
2210
2210
|
timestamp: s,
|
|
2211
|
-
eventsFlushed:
|
|
2211
|
+
eventsFlushed: i,
|
|
2212
2212
|
method: t
|
|
2213
2213
|
};
|
|
2214
2214
|
}
|
|
@@ -2217,8 +2217,8 @@ class Ut extends p {
|
|
|
2217
2217
|
this.endSession(), this.clearTimers(), this.set("sessionId", null), this.set("hasStartSession", !1);
|
|
2218
2218
|
}
|
|
2219
2219
|
endSessionManagedSync(e) {
|
|
2220
|
-
if (this.sessionEndStats.totalSessionEnds++, this.sessionEndStats.reasonCounts[e]++, this.pendingSessionEnd && (this.sessionEndStats.duplicatePrevented++,
|
|
2221
|
-
return this.sessionEndConfig.debugMode &&
|
|
2220
|
+
if (this.sessionEndStats.totalSessionEnds++, this.sessionEndStats.reasonCounts[e]++, this.pendingSessionEnd && (this.sessionEndStats.duplicatePrevented++, n.warn("SessionManager", "Sync session end called while async end pending", { reason: e })), !this.shouldProceedWithSessionEnd(e))
|
|
2221
|
+
return this.sessionEndConfig.debugMode && n.debug(
|
|
2222
2222
|
"SessionManager",
|
|
2223
2223
|
`Sync session end skipped due to lower priority. Current: ${this.sessionEndReason}, Requested: ${e}`
|
|
2224
2224
|
), {
|
|
@@ -2256,16 +2256,16 @@ class Ut extends p {
|
|
|
2256
2256
|
return a ? this.sessionEndStats.successfulEnds++ : this.sessionEndStats.failedEnds++, o;
|
|
2257
2257
|
}
|
|
2258
2258
|
this.cleanupSession();
|
|
2259
|
-
const
|
|
2259
|
+
const i = {
|
|
2260
2260
|
success: !0,
|
|
2261
2261
|
reason: e,
|
|
2262
2262
|
timestamp: t,
|
|
2263
2263
|
eventsFlushed: 0,
|
|
2264
2264
|
method: "sync"
|
|
2265
2265
|
};
|
|
2266
|
-
return this.sessionEndStats.successfulEnds++,
|
|
2267
|
-
} catch (
|
|
2268
|
-
return this.sessionEndStats.failedEnds++, this.cleanupSession(),
|
|
2266
|
+
return this.sessionEndStats.successfulEnds++, i;
|
|
2267
|
+
} catch (i) {
|
|
2268
|
+
return this.sessionEndStats.failedEnds++, this.cleanupSession(), n.error("SessionManager", "Sync session end failed", { error: i, reason: e }), {
|
|
2269
2269
|
success: !1,
|
|
2270
2270
|
reason: e,
|
|
2271
2271
|
timestamp: t,
|
|
@@ -2280,16 +2280,16 @@ class Ut extends p {
|
|
|
2280
2280
|
e || !this.get("sessionId") || (e = !0, this.clearInactivityTimer(), this.endSessionSafely("page_unload", { forceSync: !0 }));
|
|
2281
2281
|
}, s = () => {
|
|
2282
2282
|
t();
|
|
2283
|
-
},
|
|
2283
|
+
}, i = (o) => {
|
|
2284
2284
|
o.persisted || t();
|
|
2285
2285
|
}, a = () => {
|
|
2286
2286
|
document.visibilityState === "hidden" && this.get("sessionId") && !e && (this.visibilityChangeTimeout = window.setTimeout(() => {
|
|
2287
2287
|
document.visibilityState === "hidden" && this.get("sessionId") && !e && t(), this.visibilityChangeTimeout = null;
|
|
2288
2288
|
}, 1e3));
|
|
2289
2289
|
};
|
|
2290
|
-
window.addEventListener("beforeunload", s), window.addEventListener("pagehide",
|
|
2290
|
+
window.addEventListener("beforeunload", s), window.addEventListener("pagehide", i), document.addEventListener("visibilitychange", a), this.cleanupHandlers.push(
|
|
2291
2291
|
() => window.removeEventListener("beforeunload", s),
|
|
2292
|
-
() => window.removeEventListener("pagehide",
|
|
2292
|
+
() => window.removeEventListener("pagehide", i),
|
|
2293
2293
|
() => document.removeEventListener("visibilitychange", a),
|
|
2294
2294
|
() => {
|
|
2295
2295
|
this.visibilityChangeTimeout && (clearTimeout(this.visibilityChangeTimeout), this.visibilityChangeTimeout = null);
|
|
@@ -2298,9 +2298,9 @@ class Ut extends p {
|
|
|
2298
2298
|
}
|
|
2299
2299
|
}
|
|
2300
2300
|
class Ht extends p {
|
|
2301
|
-
constructor(e, t, s,
|
|
2302
|
-
super(), this.callbacks =
|
|
2303
|
-
tabHeartbeatIntervalMs:
|
|
2301
|
+
constructor(e, t, s, i) {
|
|
2302
|
+
super(), this.callbacks = i, this.storageManager = e, this.projectId = t, this.tabId = $(), this.config = {
|
|
2303
|
+
tabHeartbeatIntervalMs: qe,
|
|
2304
2304
|
tabElectionTimeoutMs: We,
|
|
2305
2305
|
debugMode: (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") ?? !1,
|
|
2306
2306
|
...s
|
|
@@ -2341,7 +2341,7 @@ class Ht extends p {
|
|
|
2341
2341
|
const e = new BroadcastChannel(st(this.projectId));
|
|
2342
2342
|
return this.setupBroadcastListeners(e), e;
|
|
2343
2343
|
} catch (e) {
|
|
2344
|
-
return this.config.debugMode &&
|
|
2344
|
+
return this.config.debugMode && n.warn("CrossTabSession", "Failed to initialize BroadcastChannel", { error: e }), null;
|
|
2345
2345
|
}
|
|
2346
2346
|
}
|
|
2347
2347
|
/**
|
|
@@ -2359,7 +2359,7 @@ class Ht extends p {
|
|
|
2359
2359
|
* Check if this tab should be the session leader
|
|
2360
2360
|
*/
|
|
2361
2361
|
tryJoinExistingSession(e) {
|
|
2362
|
-
this.config.debugMode &&
|
|
2362
|
+
this.config.debugMode && n.debug("CrossTabSession", `Attempting to join existing session: ${e.sessionId}`), this.tabInfo.sessionId = e.sessionId, this.requestLeadershipStatus(), e.tabCount += 1, e.lastActivity = Date.now(), this.storeSessionContext(e), this.callbacks?.onTabActivity && this.callbacks.onTabActivity();
|
|
2363
2363
|
}
|
|
2364
2364
|
/**
|
|
2365
2365
|
* Request leadership status from other tabs
|
|
@@ -2384,10 +2384,10 @@ class Ht extends p {
|
|
|
2384
2384
|
*/
|
|
2385
2385
|
startLeaderElection() {
|
|
2386
2386
|
if (this.electionTimeout) {
|
|
2387
|
-
this.config.debugMode &&
|
|
2387
|
+
this.config.debugMode && n.debug("CrossTabSession", "Leader election already in progress, skipping");
|
|
2388
2388
|
return;
|
|
2389
2389
|
}
|
|
2390
|
-
this.config.debugMode &&
|
|
2390
|
+
this.config.debugMode && n.debug("CrossTabSession", "Starting leader election");
|
|
2391
2391
|
const e = Math.floor(Math.random() * 50) + 10;
|
|
2392
2392
|
this.electionTimeout = window.setTimeout(() => {
|
|
2393
2393
|
this.electionTimeout = null, this.requestLeadershipStatus();
|
|
@@ -2398,7 +2398,7 @@ class Ht extends p {
|
|
|
2398
2398
|
*/
|
|
2399
2399
|
becomeLeader() {
|
|
2400
2400
|
if (!this.isTabLeader) {
|
|
2401
|
-
if (this.isTabLeader = !0, this.tabInfo.isLeader = !0, this.leaderTabId = this.tabId, this.config.debugMode &&
|
|
2401
|
+
if (this.isTabLeader = !0, this.tabInfo.isLeader = !0, this.leaderTabId = this.tabId, this.config.debugMode && n.debug("CrossTabSession", `Tab ${this.tabId} became session leader`), this.electionTimeout && (clearTimeout(this.electionTimeout), this.electionTimeout = null), this.tabInfo.sessionId) {
|
|
2402
2402
|
const e = this.getStoredSessionContext();
|
|
2403
2403
|
e && (e.lastActivity = Date.now(), this.storeSessionContext(e));
|
|
2404
2404
|
} else {
|
|
@@ -2449,10 +2449,10 @@ class Ht extends p {
|
|
|
2449
2449
|
setupLeadershipFallback() {
|
|
2450
2450
|
const e = this.config.tabElectionTimeoutMs + 1500;
|
|
2451
2451
|
this.fallbackLeadershipTimeout = window.setTimeout(() => {
|
|
2452
|
-
!this.isTabLeader && !this.leaderTabId && (this.tabInfo.sessionId ? (this.config.debugMode &&
|
|
2452
|
+
!this.isTabLeader && !this.leaderTabId && (this.tabInfo.sessionId ? (this.config.debugMode && n.warn(
|
|
2453
2453
|
"CrossTabSession",
|
|
2454
2454
|
`No leader detected after ${e}ms, forcing leadership for tab ${this.tabId}`
|
|
2455
|
-
), this.becomeLeader()) : (this.config.debugMode &&
|
|
2455
|
+
), this.becomeLeader()) : (this.config.debugMode && n.warn(
|
|
2456
2456
|
"CrossTabSession",
|
|
2457
2457
|
`No session or leader detected after ${e}ms, starting new session for tab ${this.tabId}`
|
|
2458
2458
|
), this.becomeLeader())), this.fallbackLeadershipTimeout = null;
|
|
@@ -2460,10 +2460,10 @@ class Ht extends p {
|
|
|
2460
2460
|
if (!this.sessionEnded && this.leaderTabId && !this.isTabLeader) {
|
|
2461
2461
|
const s = this.getStoredSessionContext();
|
|
2462
2462
|
if (s) {
|
|
2463
|
-
const
|
|
2464
|
-
|
|
2463
|
+
const i = Date.now() - s.lastActivity, a = this.config.tabHeartbeatIntervalMs * 3;
|
|
2464
|
+
i > a && (this.config.debugMode && n.warn(
|
|
2465
2465
|
"CrossTabSession",
|
|
2466
|
-
`Leader tab appears inactive (${
|
|
2466
|
+
`Leader tab appears inactive (${i}ms), attempting to become leader`
|
|
2467
2467
|
), this.leaderTabId = null, this.startLeaderElection());
|
|
2468
2468
|
}
|
|
2469
2469
|
}
|
|
@@ -2486,7 +2486,7 @@ class Ht extends p {
|
|
|
2486
2486
|
* Handle cross-tab messages
|
|
2487
2487
|
*/
|
|
2488
2488
|
handleCrossTabMessage(e) {
|
|
2489
|
-
switch (this.config.debugMode &&
|
|
2489
|
+
switch (this.config.debugMode && n.debug("CrossTabSession", `Received cross-tab message: ${e.type} from ${e.tabId}`), e.type) {
|
|
2490
2490
|
case "heartbeat":
|
|
2491
2491
|
this.handleHeartbeatMessage(e);
|
|
2492
2492
|
break;
|
|
@@ -2531,13 +2531,13 @@ class Ht extends p {
|
|
|
2531
2531
|
*/
|
|
2532
2532
|
handleSessionEndMessage(e) {
|
|
2533
2533
|
if (this.isTabLeader) {
|
|
2534
|
-
this.config.debugMode &&
|
|
2534
|
+
this.config.debugMode && n.debug("CrossTabSession", `Ignoring session end message from ${e.tabId} (this tab is leader)`);
|
|
2535
2535
|
return;
|
|
2536
2536
|
}
|
|
2537
2537
|
if (!this.leaderTabId || e.tabId !== this.leaderTabId) {
|
|
2538
2538
|
if (this.config.debugMode) {
|
|
2539
2539
|
const s = this.leaderTabId ? `; leader is ${this.leaderTabId}` : "";
|
|
2540
|
-
|
|
2540
|
+
n.debug("CrossTabSession", `Ignoring session end message from ${e.tabId}${s}`);
|
|
2541
2541
|
}
|
|
2542
2542
|
return;
|
|
2543
2543
|
}
|
|
@@ -2550,10 +2550,10 @@ class Ht extends p {
|
|
|
2550
2550
|
const t = this.getStoredSessionContext();
|
|
2551
2551
|
if (t && e.sessionId === t.sessionId) {
|
|
2552
2552
|
const s = t.tabCount;
|
|
2553
|
-
t.tabCount = Math.max(1, t.tabCount - 1), t.lastActivity = Date.now(), this.storeSessionContext(t), this.config.debugMode &&
|
|
2553
|
+
t.tabCount = Math.max(1, t.tabCount - 1), t.lastActivity = Date.now(), this.storeSessionContext(t), this.config.debugMode && n.debug(
|
|
2554
2554
|
"CrossTabSession",
|
|
2555
2555
|
`Tab count updated from ${s} to ${t.tabCount} after tab ${e.tabId} closed`
|
|
2556
|
-
), (e.data?.isLeader ?? e.tabId === this.leaderTabId) && !this.isTabLeader && (this.config.debugMode &&
|
|
2556
|
+
), (e.data?.isLeader ?? e.tabId === this.leaderTabId) && !this.isTabLeader && (this.config.debugMode && n.debug("CrossTabSession", `Leader tab ${e.tabId} closed, starting leader election`), this.leaderTabId = null, this.electionDelayTimeout = window.setTimeout(() => {
|
|
2557
2557
|
this.startLeaderElection(), this.electionDelayTimeout = null;
|
|
2558
2558
|
}, 200));
|
|
2559
2559
|
}
|
|
@@ -2577,10 +2577,10 @@ class Ht extends p {
|
|
|
2577
2577
|
* Handle election response from another tab
|
|
2578
2578
|
*/
|
|
2579
2579
|
handleElectionResponse(e) {
|
|
2580
|
-
e.data?.isLeader && (this.isTabLeader ? this.config.debugMode && (
|
|
2580
|
+
e.data?.isLeader && (this.isTabLeader ? this.config.debugMode && (n.warn(
|
|
2581
2581
|
"CrossTabSession",
|
|
2582
2582
|
`Received leadership claim from ${e.tabId} but this tab is already leader`
|
|
2583
|
-
), this.callbacks?.onCrossTabConflict && this.callbacks.onCrossTabConflict()) : (this.isTabLeader = !1, this.tabInfo.isLeader = !1, this.leaderTabId = e.tabId, this.config.debugMode &&
|
|
2583
|
+
), this.callbacks?.onCrossTabConflict && this.callbacks.onCrossTabConflict()) : (this.isTabLeader = !1, this.tabInfo.isLeader = !1, this.leaderTabId = e.tabId, this.config.debugMode && n.debug("CrossTabSession", `Acknowledging tab ${e.tabId} as leader`), this.electionTimeout && (clearTimeout(this.electionTimeout), this.electionTimeout = null), e.sessionId && (this.tabInfo.sessionId = e.sessionId, this.storeTabInfo())));
|
|
2584
2584
|
}
|
|
2585
2585
|
/**
|
|
2586
2586
|
* Start heartbeat to keep session active
|
|
@@ -2598,13 +2598,13 @@ class Ht extends p {
|
|
|
2598
2598
|
const e = Date.now(), t = this.lastHeartbeatSent ?? 0, s = this.config.tabHeartbeatIntervalMs * 0.8;
|
|
2599
2599
|
if (!this.isTabLeader && e - t < s)
|
|
2600
2600
|
return;
|
|
2601
|
-
const
|
|
2601
|
+
const i = {
|
|
2602
2602
|
type: "heartbeat",
|
|
2603
2603
|
tabId: this.tabId,
|
|
2604
2604
|
sessionId: this.tabInfo.sessionId,
|
|
2605
2605
|
timestamp: e
|
|
2606
2606
|
};
|
|
2607
|
-
this.broadcastChannel.postMessage(
|
|
2607
|
+
this.broadcastChannel.postMessage(i), this.lastHeartbeatSent = e;
|
|
2608
2608
|
}
|
|
2609
2609
|
/**
|
|
2610
2610
|
* Update tab info with current timestamp
|
|
@@ -2616,7 +2616,7 @@ class Ht extends p {
|
|
|
2616
2616
|
* End session and notify other tabs
|
|
2617
2617
|
*/
|
|
2618
2618
|
endSession(e) {
|
|
2619
|
-
this.sessionEnded || (this.sessionEnded = !0, this.config.debugMode &&
|
|
2619
|
+
this.sessionEnded || (this.sessionEnded = !0, this.config.debugMode && n.debug(
|
|
2620
2620
|
"CrossTabSession",
|
|
2621
2621
|
`Ending cross-tab session: ${e} (tab: ${this.tabId}, isLeader: ${this.isTabLeader})`
|
|
2622
2622
|
), this.announceTabClosing(), this.isTabLeader && e !== "manual_stop" && this.announceSessionEnd(e), this.tabInfoCleanupTimeout = window.setTimeout(() => {
|
|
@@ -2636,7 +2636,7 @@ class Ht extends p {
|
|
|
2636
2636
|
data: { isLeader: this.isTabLeader }
|
|
2637
2637
|
};
|
|
2638
2638
|
this.broadcastChannel.postMessage(e), this.closingAnnouncementTimeout = window.setTimeout(() => {
|
|
2639
|
-
this.config.debugMode &&
|
|
2639
|
+
this.config.debugMode && n.debug("CrossTabSession", `Tab ${this.tabId} closing announcement sent`), this.closingAnnouncementTimeout = null;
|
|
2640
2640
|
}, 100);
|
|
2641
2641
|
}
|
|
2642
2642
|
/**
|
|
@@ -2679,7 +2679,7 @@ class Ht extends p {
|
|
|
2679
2679
|
const e = this.storageManager.getItem(Y(this.projectId));
|
|
2680
2680
|
return e ? JSON.parse(e) : null;
|
|
2681
2681
|
} catch (e) {
|
|
2682
|
-
return this.config.debugMode &&
|
|
2682
|
+
return this.config.debugMode && n.warn("CrossTabSession", "Failed to parse stored session context", { error: e }), null;
|
|
2683
2683
|
}
|
|
2684
2684
|
}
|
|
2685
2685
|
/**
|
|
@@ -2689,7 +2689,7 @@ class Ht extends p {
|
|
|
2689
2689
|
try {
|
|
2690
2690
|
this.storageManager.setItem(Y(this.projectId), JSON.stringify(e));
|
|
2691
2691
|
} catch (t) {
|
|
2692
|
-
this.config.debugMode &&
|
|
2692
|
+
this.config.debugMode && n.warn("CrossTabSession", "Failed to store session context", { error: t });
|
|
2693
2693
|
}
|
|
2694
2694
|
}
|
|
2695
2695
|
/**
|
|
@@ -2705,7 +2705,7 @@ class Ht extends p {
|
|
|
2705
2705
|
try {
|
|
2706
2706
|
this.storageManager.setItem(Se(this.projectId, this.tabId), JSON.stringify(this.tabInfo));
|
|
2707
2707
|
} catch (e) {
|
|
2708
|
-
this.config.debugMode &&
|
|
2708
|
+
this.config.debugMode && n.warn("CrossTabSession", "Failed to store tab info", { error: e });
|
|
2709
2709
|
}
|
|
2710
2710
|
}
|
|
2711
2711
|
/**
|
|
@@ -2727,8 +2727,8 @@ class Ht extends p {
|
|
|
2727
2727
|
const e = this.getStoredSessionContext();
|
|
2728
2728
|
if (!e)
|
|
2729
2729
|
return this.get("config")?.sessionTimeout ?? R;
|
|
2730
|
-
const s = Date.now() - e.lastActivity,
|
|
2731
|
-
return Math.max(0,
|
|
2730
|
+
const s = Date.now() - e.lastActivity, i = this.get("config")?.sessionTimeout ?? R;
|
|
2731
|
+
return Math.max(0, i - s);
|
|
2732
2732
|
}
|
|
2733
2733
|
/**
|
|
2734
2734
|
* Update session activity from any tab
|
|
@@ -2760,7 +2760,7 @@ class Pt extends p {
|
|
|
2760
2760
|
const e = this.get("config")?.id;
|
|
2761
2761
|
e && this.initializeCrossTabSessionManager(e);
|
|
2762
2762
|
} catch (e) {
|
|
2763
|
-
|
|
2763
|
+
n.error("SessionHandler", "Failed to initialize cross-tab session manager", {
|
|
2764
2764
|
error: e instanceof Error ? e.message : "Unknown error"
|
|
2765
2765
|
});
|
|
2766
2766
|
} finally {
|
|
@@ -2779,42 +2779,42 @@ class Pt extends p {
|
|
|
2779
2779
|
}
|
|
2780
2780
|
startTracking() {
|
|
2781
2781
|
if (this.sessionManager) {
|
|
2782
|
-
|
|
2782
|
+
n.debug("SessionHandler", "Session tracking already active");
|
|
2783
2783
|
return;
|
|
2784
2784
|
}
|
|
2785
|
-
|
|
2785
|
+
n.debug("SessionHandler", "Starting session tracking"), this.checkOrphanedSessions();
|
|
2786
2786
|
const e = async () => {
|
|
2787
2787
|
if (this.crossTabSessionManager && this.crossTabSessionManager.updateSessionActivity(), !this.get("sessionId"))
|
|
2788
2788
|
try {
|
|
2789
|
-
const
|
|
2790
|
-
this.set("sessionId",
|
|
2791
|
-
sessionId:
|
|
2792
|
-
recovered:
|
|
2789
|
+
const i = await this.createOrJoinSession();
|
|
2790
|
+
this.set("sessionId", i.sessionId), n.info("SessionHandler", "🏁 Session started", {
|
|
2791
|
+
sessionId: i.sessionId,
|
|
2792
|
+
recovered: i.recovered,
|
|
2793
2793
|
crossTabActive: !!this.crossTabSessionManager
|
|
2794
|
-
}), this.trackSession(h.SESSION_START,
|
|
2795
|
-
} catch (
|
|
2796
|
-
|
|
2794
|
+
}), this.trackSession(h.SESSION_START, i.recovered), this.persistSession(i.sessionId), this.startHeartbeat();
|
|
2795
|
+
} catch (i) {
|
|
2796
|
+
n.error(
|
|
2797
2797
|
"SessionHandler",
|
|
2798
|
-
`Session creation failed: ${
|
|
2798
|
+
`Session creation failed: ${i instanceof Error ? i.message : "Unknown error"}`
|
|
2799
2799
|
), this.forceCleanupSession();
|
|
2800
2800
|
}
|
|
2801
2801
|
}, t = () => {
|
|
2802
2802
|
if (this.get("sessionId")) {
|
|
2803
2803
|
if (this.crossTabSessionManager && this.crossTabSessionManager.getEffectiveSessionTimeout() > 0) {
|
|
2804
|
-
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2804
|
+
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.debug("SessionHandler", "Session kept alive by cross-tab activity");
|
|
2805
2805
|
return;
|
|
2806
2806
|
}
|
|
2807
|
-
this.sessionManager.endSessionManaged("inactivity").then((
|
|
2808
|
-
|
|
2807
|
+
this.sessionManager.endSessionManaged("inactivity").then((i) => {
|
|
2808
|
+
n.info("SessionHandler", "🛑 Session ended by inactivity", {
|
|
2809
2809
|
sessionId: this.get("sessionId"),
|
|
2810
|
-
reason:
|
|
2811
|
-
success:
|
|
2812
|
-
eventsFlushed:
|
|
2810
|
+
reason: i.reason,
|
|
2811
|
+
success: i.success,
|
|
2812
|
+
eventsFlushed: i.eventsFlushed
|
|
2813
2813
|
}), this.crossTabSessionManager && this.crossTabSessionManager.endSession("inactivity"), this.clearPersistedSession(), this.stopHeartbeat();
|
|
2814
|
-
}).catch((
|
|
2815
|
-
|
|
2814
|
+
}).catch((i) => {
|
|
2815
|
+
n.error(
|
|
2816
2816
|
"SessionHandler",
|
|
2817
|
-
`Session end failed: ${
|
|
2817
|
+
`Session end failed: ${i instanceof Error ? i.message : "Unknown error"}`
|
|
2818
2818
|
), this.forceCleanupSession();
|
|
2819
2819
|
});
|
|
2820
2820
|
}
|
|
@@ -2830,15 +2830,15 @@ class Pt extends p {
|
|
|
2830
2830
|
this.eventManager,
|
|
2831
2831
|
this.storageManager,
|
|
2832
2832
|
s
|
|
2833
|
-
),
|
|
2833
|
+
), n.debug("SessionHandler", "Session manager initialized"), this.startInitialSession();
|
|
2834
2834
|
}
|
|
2835
2835
|
stopTracking() {
|
|
2836
|
-
if (
|
|
2836
|
+
if (n.info("SessionHandler", "Stopping session tracking"), this.sessionManager) {
|
|
2837
2837
|
if (this.get("sessionId"))
|
|
2838
2838
|
try {
|
|
2839
2839
|
this.sessionManager.endSessionSafely("manual_stop", { forceSync: !0 }), this.clearPersistedSession(), this.stopHeartbeat();
|
|
2840
2840
|
} catch (e) {
|
|
2841
|
-
|
|
2841
|
+
n.error(
|
|
2842
2842
|
"SessionHandler",
|
|
2843
2843
|
`Manual session stop failed: ${e instanceof Error ? e.message : "Unknown error"}`
|
|
2844
2844
|
), this.forceCleanupSession();
|
|
@@ -2848,26 +2848,26 @@ class Pt extends p {
|
|
|
2848
2848
|
this._crossTabSessionManager && (this._crossTabSessionManager.destroy(), this._crossTabSessionManager = null), this._isInitializingCrossTab = !1, this.recoveryManager && (this.recoveryManager.cleanupOldRecoveryAttempts(), this.recoveryManager = null);
|
|
2849
2849
|
}
|
|
2850
2850
|
initializeSessionRecoveryManager(e) {
|
|
2851
|
-
this.recoveryManager = new Ce(this.storageManager, e, this.eventManager),
|
|
2851
|
+
this.recoveryManager = new Ce(this.storageManager, e, this.eventManager), n.debug("SessionHandler", "Session recovery manager initialized", { projectId: e });
|
|
2852
2852
|
}
|
|
2853
2853
|
initializeCrossTabSessionManager(e) {
|
|
2854
2854
|
const t = {
|
|
2855
2855
|
debugMode: (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") ?? !1
|
|
2856
2856
|
}, l = {
|
|
2857
2857
|
onSessionStart: (c) => {
|
|
2858
|
-
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2858
|
+
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.debug("SessionHandler", `Cross-tab session started: ${c}`), this.set("sessionId", c), this.trackSession(h.SESSION_START, !1), this.persistSession(c), this.startHeartbeat();
|
|
2859
2859
|
},
|
|
2860
2860
|
onSessionEnd: (c) => {
|
|
2861
|
-
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2861
|
+
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.debug("SessionHandler", `Cross-tab session ended: ${c}`), this.clearPersistedSession(), this.trackSession(h.SESSION_END, !1, c);
|
|
2862
2862
|
},
|
|
2863
2863
|
onTabActivity: () => {
|
|
2864
|
-
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2864
|
+
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.debug("SessionHandler", "Cross-tab activity detected");
|
|
2865
2865
|
},
|
|
2866
2866
|
onCrossTabConflict: () => {
|
|
2867
|
-
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2867
|
+
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.warn("SessionHandler", "Cross-tab conflict detected"), this.sessionManager && this.sessionManager.trackSessionHealth("conflict");
|
|
2868
2868
|
}
|
|
2869
2869
|
};
|
|
2870
|
-
this._crossTabSessionManager = new Ht(this.storageManager, e, t, l),
|
|
2870
|
+
this._crossTabSessionManager = new Ht(this.storageManager, e, t, l), n.debug("SessionHandler", "Cross-tab session manager initialized", { projectId: e });
|
|
2871
2871
|
}
|
|
2872
2872
|
async createOrJoinSession() {
|
|
2873
2873
|
if (this.crossTabSessionManager) {
|
|
@@ -2885,7 +2885,7 @@ class Pt extends p {
|
|
|
2885
2885
|
try {
|
|
2886
2886
|
this.crossTabSessionManager.endSession("orphaned_cleanup");
|
|
2887
2887
|
} catch (e) {
|
|
2888
|
-
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2888
|
+
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.warn(
|
|
2889
2889
|
"SessionHandler",
|
|
2890
2890
|
`Cross-tab cleanup failed during force cleanup: ${e instanceof Error ? e.message : "Unknown error"}`
|
|
2891
2891
|
);
|
|
@@ -2893,12 +2893,12 @@ class Pt extends p {
|
|
|
2893
2893
|
try {
|
|
2894
2894
|
this.trackSession(h.SESSION_END, !1, "orphaned_cleanup");
|
|
2895
2895
|
} catch (e) {
|
|
2896
|
-
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2896
|
+
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.warn(
|
|
2897
2897
|
"SessionHandler",
|
|
2898
2898
|
`Session tracking failed during force cleanup: ${e instanceof Error ? e.message : "Unknown error"}`
|
|
2899
2899
|
);
|
|
2900
2900
|
}
|
|
2901
|
-
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2901
|
+
(this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.debug("SessionHandler", "Forced session cleanup completed");
|
|
2902
2902
|
}
|
|
2903
2903
|
trackSession(e, t = !1, s) {
|
|
2904
2904
|
this.eventManager.track({
|
|
@@ -2909,10 +2909,10 @@ class Pt extends p {
|
|
|
2909
2909
|
}
|
|
2910
2910
|
startInitialSession() {
|
|
2911
2911
|
if (this.get("sessionId")) {
|
|
2912
|
-
|
|
2912
|
+
n.debug("SessionHandler", "Session already exists, skipping initial session creation");
|
|
2913
2913
|
return;
|
|
2914
2914
|
}
|
|
2915
|
-
if (
|
|
2915
|
+
if (n.debug("SessionHandler", "Starting initial session"), this.crossTabSessionManager) {
|
|
2916
2916
|
const t = this.crossTabSessionManager.getSessionId();
|
|
2917
2917
|
if (t) {
|
|
2918
2918
|
this.set("sessionId", t), this.persistSession(t), this.startHeartbeat();
|
|
@@ -2920,7 +2920,7 @@ class Pt extends p {
|
|
|
2920
2920
|
}
|
|
2921
2921
|
return;
|
|
2922
2922
|
}
|
|
2923
|
-
|
|
2923
|
+
n.debug("SessionHandler", "Starting regular session (no cross-tab)");
|
|
2924
2924
|
const e = this.sessionManager.startSession();
|
|
2925
2925
|
this.set("sessionId", e.sessionId), this.trackSession(h.SESSION_START, e.recovered), this.persistSession(e.sessionId), this.startHeartbeat();
|
|
2926
2926
|
}
|
|
@@ -2928,8 +2928,8 @@ class Pt extends p {
|
|
|
2928
2928
|
const e = this.storageManager.getItem(this.sessionStorageKey);
|
|
2929
2929
|
if (e)
|
|
2930
2930
|
try {
|
|
2931
|
-
const t = JSON.parse(e),
|
|
2932
|
-
if (
|
|
2931
|
+
const t = JSON.parse(e), i = Date.now() - t.lastHeartbeat, a = this.get("config")?.sessionTimeout ?? R;
|
|
2932
|
+
if (i > a) {
|
|
2933
2933
|
const o = this.recoveryManager?.hasRecoverableSession();
|
|
2934
2934
|
if (o && this.recoveryManager) {
|
|
2935
2935
|
const l = {
|
|
@@ -2943,9 +2943,9 @@ class Pt extends p {
|
|
|
2943
2943
|
pageUrl: this.get("pageUrl")
|
|
2944
2944
|
}
|
|
2945
2945
|
};
|
|
2946
|
-
this.recoveryManager.storeSessionContextForRecovery(l), (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2946
|
+
this.recoveryManager.storeSessionContextForRecovery(l), (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.debug("SessionHandler", `Orphaned session stored for recovery: ${t.sessionId}`);
|
|
2947
2947
|
}
|
|
2948
|
-
this.trackSession(h.SESSION_END), this.clearPersistedSession(), (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") &&
|
|
2948
|
+
this.trackSession(h.SESSION_END), this.clearPersistedSession(), (this.get("config")?.mode === "qa" || this.get("config")?.mode === "debug") && n.debug(
|
|
2949
2949
|
"SessionHandler",
|
|
2950
2950
|
`Orphaned session ended: ${t.sessionId}, recovery available: ${o}`
|
|
2951
2951
|
);
|
|
@@ -2990,10 +2990,10 @@ class Dt extends p {
|
|
|
2990
2990
|
super(), this.eventManager = e, this.onTrack = t;
|
|
2991
2991
|
}
|
|
2992
2992
|
startTracking() {
|
|
2993
|
-
|
|
2993
|
+
n.debug("PageViewHandler", "Starting page view tracking"), this.trackInitialPageView(), this.trackCurrentPage(), window.addEventListener("popstate", this.trackCurrentPage), window.addEventListener("hashchange", this.trackCurrentPage), this.patchHistory("pushState"), this.patchHistory("replaceState");
|
|
2994
2994
|
}
|
|
2995
2995
|
stopTracking() {
|
|
2996
|
-
|
|
2996
|
+
n.debug("PageViewHandler", "Stopping page view tracking"), window.removeEventListener("popstate", this.trackCurrentPage), window.removeEventListener("hashchange", this.trackCurrentPage), this.originalPushState && (window.history.pushState = this.originalPushState), this.originalReplaceState && (window.history.replaceState = this.originalReplaceState);
|
|
2997
2997
|
}
|
|
2998
2998
|
patchHistory(e) {
|
|
2999
2999
|
e === "pushState" && !this.originalPushState ? this.originalPushState = window.history.pushState : e === "replaceState" && !this.originalReplaceState && (this.originalReplaceState = window.history.replaceState);
|
|
@@ -3006,7 +3006,7 @@ class Dt extends p {
|
|
|
3006
3006
|
const e = window.location.href, t = se(e, this.get("config").sensitiveQueryParams);
|
|
3007
3007
|
if (this.get("pageUrl") !== t) {
|
|
3008
3008
|
const s = this.get("pageUrl");
|
|
3009
|
-
|
|
3009
|
+
n.debug("PageViewHandler", "Page navigation detected", { from: s, to: t }), this.set("pageUrl", t), this.eventManager.track({
|
|
3010
3010
|
type: h.PAGE_VIEW,
|
|
3011
3011
|
page_url: this.get("pageUrl"),
|
|
3012
3012
|
from_page_url: s,
|
|
@@ -3040,21 +3040,21 @@ class xt extends p {
|
|
|
3040
3040
|
}
|
|
3041
3041
|
startTracking() {
|
|
3042
3042
|
if (this.clickHandler) {
|
|
3043
|
-
|
|
3043
|
+
n.debug("ClickHandler", "Click tracking already active");
|
|
3044
3044
|
return;
|
|
3045
3045
|
}
|
|
3046
|
-
|
|
3047
|
-
const t = e, s = t.target,
|
|
3048
|
-
if (!
|
|
3049
|
-
|
|
3046
|
+
n.debug("ClickHandler", "Starting click tracking"), this.clickHandler = (e) => {
|
|
3047
|
+
const t = e, s = t.target, i = s instanceof HTMLElement ? s : s instanceof Node && s.parentElement instanceof HTMLElement ? s.parentElement : null;
|
|
3048
|
+
if (!i) {
|
|
3049
|
+
n.warn("ClickHandler", "Click target not found or not an element");
|
|
3050
3050
|
return;
|
|
3051
3051
|
}
|
|
3052
|
-
|
|
3053
|
-
tagName:
|
|
3054
|
-
className:
|
|
3055
|
-
textContent:
|
|
3052
|
+
n.info("ClickHandler", "🖱️ Click detected on element", {
|
|
3053
|
+
tagName: i.tagName,
|
|
3054
|
+
className: i.className || "none",
|
|
3055
|
+
textContent: i.textContent?.slice(0, 50) ?? "empty"
|
|
3056
3056
|
});
|
|
3057
|
-
const a = this.findTrackingElement(
|
|
3057
|
+
const a = this.findTrackingElement(i), o = this.getRelevantClickElement(i), l = this.calculateClickCoordinates(t, i);
|
|
3058
3058
|
if (a) {
|
|
3059
3059
|
const d = this.extractTrackingData(a);
|
|
3060
3060
|
if (d) {
|
|
@@ -3068,7 +3068,7 @@ class xt extends p {
|
|
|
3068
3068
|
});
|
|
3069
3069
|
}
|
|
3070
3070
|
}
|
|
3071
|
-
const c = this.generateClickData(
|
|
3071
|
+
const c = this.generateClickData(i, o, l);
|
|
3072
3072
|
this.eventManager.track({
|
|
3073
3073
|
type: h.CLICK,
|
|
3074
3074
|
click_data: c
|
|
@@ -3087,7 +3087,7 @@ class xt extends p {
|
|
|
3087
3087
|
if (e.matches(t))
|
|
3088
3088
|
return e;
|
|
3089
3089
|
} catch (s) {
|
|
3090
|
-
|
|
3090
|
+
n.warn("ClickHandler", "Invalid selector in interactive elements check", {
|
|
3091
3091
|
selector: t,
|
|
3092
3092
|
error: s instanceof Error ? s.message : "Unknown error"
|
|
3093
3093
|
});
|
|
@@ -3099,7 +3099,7 @@ class xt extends p {
|
|
|
3099
3099
|
if (s)
|
|
3100
3100
|
return s;
|
|
3101
3101
|
} catch (s) {
|
|
3102
|
-
|
|
3102
|
+
n.warn("ClickHandler", "Invalid selector in parent element search", {
|
|
3103
3103
|
selector: t,
|
|
3104
3104
|
error: s instanceof Error ? s.message : "Unknown error"
|
|
3105
3105
|
});
|
|
@@ -3108,8 +3108,8 @@ class xt extends p {
|
|
|
3108
3108
|
return e;
|
|
3109
3109
|
}
|
|
3110
3110
|
calculateClickCoordinates(e, t) {
|
|
3111
|
-
const s = t.getBoundingClientRect(),
|
|
3112
|
-
return { x:
|
|
3111
|
+
const s = t.getBoundingClientRect(), i = e.clientX, a = e.clientY, o = s.width > 0 ? Math.max(0, Math.min(1, Number(((i - 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;
|
|
3112
|
+
return { x: i, y: a, relativeX: o, relativeY: l };
|
|
3113
3113
|
}
|
|
3114
3114
|
extractTrackingData(e) {
|
|
3115
3115
|
const t = e.getAttribute(`${z}-name`), s = e.getAttribute(`${z}-value`);
|
|
@@ -3121,9 +3121,9 @@ class xt extends p {
|
|
|
3121
3121
|
};
|
|
3122
3122
|
}
|
|
3123
3123
|
generateClickData(e, t, s) {
|
|
3124
|
-
const { x:
|
|
3124
|
+
const { x: i, 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);
|
|
3125
3125
|
return {
|
|
3126
|
-
x:
|
|
3126
|
+
x: i,
|
|
3127
3127
|
y: a,
|
|
3128
3128
|
relativeX: o,
|
|
3129
3129
|
relativeY: l,
|
|
@@ -3140,19 +3140,19 @@ class xt extends p {
|
|
|
3140
3140
|
};
|
|
3141
3141
|
}
|
|
3142
3142
|
getRelevantText(e, t) {
|
|
3143
|
-
const s = ["main", "section", "article", "body", "html", "header", "footer", "aside", "nav"],
|
|
3144
|
-
if (!
|
|
3143
|
+
const s = ["main", "section", "article", "body", "html", "header", "footer", "aside", "nav"], i = e.textContent?.trim() ?? "", a = t.textContent?.trim() ?? "";
|
|
3144
|
+
if (!i && !a)
|
|
3145
3145
|
return "";
|
|
3146
|
-
if (
|
|
3147
|
-
return
|
|
3146
|
+
if (i && i.length <= _)
|
|
3147
|
+
return i;
|
|
3148
3148
|
const o = s.includes(t.tagName.toLowerCase()), l = a.length > _ * 2;
|
|
3149
|
-
return o && l ?
|
|
3149
|
+
return o && l ? i && i.length <= _ ? i : "" : a.length <= _ ? a : i && i.length < a.length * 0.1 ? i.length <= _ ? i : i.slice(0, _ - 3) + "..." : a.slice(0, _ - 3) + "...";
|
|
3150
3150
|
}
|
|
3151
3151
|
extractElementAttributes(e) {
|
|
3152
3152
|
const t = ["id", "class", "data-testid", "aria-label", "title", "href", "type", "name"], s = {};
|
|
3153
|
-
for (const
|
|
3154
|
-
const a = e.getAttribute(
|
|
3155
|
-
a && (s[
|
|
3153
|
+
for (const i of t) {
|
|
3154
|
+
const a = e.getAttribute(i);
|
|
3155
|
+
a && (s[i] = a);
|
|
3156
3156
|
}
|
|
3157
3157
|
return s;
|
|
3158
3158
|
}
|
|
@@ -3171,14 +3171,14 @@ class Ot extends p {
|
|
|
3171
3171
|
}
|
|
3172
3172
|
startTracking() {
|
|
3173
3173
|
const e = this.get("config").scrollContainerSelectors, t = Array.isArray(e) ? e : typeof e == "string" ? [e] : [];
|
|
3174
|
-
|
|
3175
|
-
const s = t.map((
|
|
3174
|
+
n.debug("ScrollHandler", "Starting scroll tracking", { selectorsCount: t.length });
|
|
3175
|
+
const s = t.map((i) => this.safeQuerySelector(i)).filter((i) => i instanceof HTMLElement);
|
|
3176
3176
|
s.length === 0 && s.push(window);
|
|
3177
|
-
for (const
|
|
3178
|
-
this.setupScrollContainer(
|
|
3177
|
+
for (const i of s)
|
|
3178
|
+
this.setupScrollContainer(i);
|
|
3179
3179
|
}
|
|
3180
3180
|
stopTracking() {
|
|
3181
|
-
|
|
3181
|
+
n.debug("ScrollHandler", "Stopping scroll tracking", { containersCount: this.containers.length });
|
|
3182
3182
|
for (const e of this.containers)
|
|
3183
3183
|
e.debounceTimer && clearTimeout(e.debounceTimer), e.element instanceof Window ? window.removeEventListener("scroll", e.listener) : e.element.removeEventListener("scroll", e.listener);
|
|
3184
3184
|
this.containers.length = 0;
|
|
@@ -3198,21 +3198,21 @@ class Ot extends p {
|
|
|
3198
3198
|
return;
|
|
3199
3199
|
}
|
|
3200
3200
|
t.debounceTimer && clearTimeout(t.debounceTimer), t.debounceTimer = window.setTimeout(() => {
|
|
3201
|
-
const
|
|
3202
|
-
|
|
3201
|
+
const i = this.calculateScrollData(t);
|
|
3202
|
+
i && this.eventManager.track({
|
|
3203
3203
|
type: h.SCROLL,
|
|
3204
|
-
scroll_data:
|
|
3204
|
+
scroll_data: i
|
|
3205
3205
|
}), t.debounceTimer = null;
|
|
3206
3206
|
}, Me);
|
|
3207
3207
|
};
|
|
3208
3208
|
t.listener = s, this.containers.push(t), e instanceof Window ? window.addEventListener("scroll", s, { passive: !0 }) : e.addEventListener("scroll", s, { passive: !0 });
|
|
3209
3209
|
}
|
|
3210
3210
|
calculateScrollData(e) {
|
|
3211
|
-
const { element: t, lastScrollPos: s } = e,
|
|
3211
|
+
const { element: t, lastScrollPos: s } = e, i = this.getScrollTop(t), a = this.getViewportHeight(t), o = this.getScrollHeight(t);
|
|
3212
3212
|
if (t === window && o <= a)
|
|
3213
3213
|
return null;
|
|
3214
|
-
const l =
|
|
3215
|
-
return Math.abs(
|
|
3214
|
+
const l = i > s ? j.DOWN : j.UP, c = o > a ? Math.min(100, Math.max(0, Math.floor(i / (o - a) * 100))) : 0;
|
|
3215
|
+
return Math.abs(i - s) < Ue ? null : (e.lastScrollPos = i, { depth: c, direction: l });
|
|
3216
3216
|
}
|
|
3217
3217
|
getScrollTop(e) {
|
|
3218
3218
|
return e instanceof Window ? window.scrollY : e.scrollTop;
|
|
@@ -3224,14 +3224,14 @@ class Ot extends p {
|
|
|
3224
3224
|
return e instanceof Window ? document.documentElement.scrollHeight : e.scrollHeight;
|
|
3225
3225
|
}
|
|
3226
3226
|
isElementScrollable(e) {
|
|
3227
|
-
const t = getComputedStyle(e), s = t.overflowY === "auto" || t.overflowY === "scroll" || t.overflowX === "auto" || t.overflowX === "scroll" || t.overflow === "auto" || t.overflow === "scroll",
|
|
3228
|
-
return s &&
|
|
3227
|
+
const t = getComputedStyle(e), s = t.overflowY === "auto" || t.overflowY === "scroll" || t.overflowX === "auto" || t.overflowX === "scroll" || t.overflow === "auto" || t.overflow === "scroll", i = e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth;
|
|
3228
|
+
return s && i;
|
|
3229
3229
|
}
|
|
3230
3230
|
safeQuerySelector(e) {
|
|
3231
3231
|
try {
|
|
3232
3232
|
return document.querySelector(e);
|
|
3233
3233
|
} catch (t) {
|
|
3234
|
-
return
|
|
3234
|
+
return n.clientWarn("ScrollHandler", "Invalid CSS selector", {
|
|
3235
3235
|
selector: e,
|
|
3236
3236
|
error: t instanceof Error ? t.message : "Unknown error"
|
|
3237
3237
|
}), null;
|
|
@@ -3248,7 +3248,7 @@ class Ft extends p {
|
|
|
3248
3248
|
return;
|
|
3249
3249
|
const e = this.get("config").integrations?.googleAnalytics?.measurementId;
|
|
3250
3250
|
if (!e?.trim()) {
|
|
3251
|
-
|
|
3251
|
+
n.clientWarn("GoogleAnalytics", "Google Analytics integration disabled - measurementId not configured", {
|
|
3252
3252
|
hasIntegrations: !!this.get("config").integrations,
|
|
3253
3253
|
hasGoogleAnalytics: !!this.get("config").integrations?.googleAnalytics
|
|
3254
3254
|
});
|
|
@@ -3256,22 +3256,22 @@ class Ft extends p {
|
|
|
3256
3256
|
}
|
|
3257
3257
|
const t = this.get("userId");
|
|
3258
3258
|
if (!t?.trim()) {
|
|
3259
|
-
|
|
3259
|
+
n.warn("GoogleAnalytics", "Google Analytics initialization delayed - userId not available", {
|
|
3260
3260
|
measurementId: e.substring(0, 8) + "..."
|
|
3261
3261
|
});
|
|
3262
3262
|
return;
|
|
3263
3263
|
}
|
|
3264
3264
|
try {
|
|
3265
3265
|
if (this.isScriptAlreadyLoaded()) {
|
|
3266
|
-
|
|
3266
|
+
n.info("GoogleAnalytics", "Google Analytics script already loaded", { measurementId: e }), this.isInitialized = !0;
|
|
3267
3267
|
return;
|
|
3268
3268
|
}
|
|
3269
|
-
await this.loadScript(e), this.configureGtag(e, t), this.isInitialized = !0,
|
|
3269
|
+
await this.loadScript(e), this.configureGtag(e, t), this.isInitialized = !0, n.info("GoogleAnalytics", "Google Analytics integration initialized successfully", {
|
|
3270
3270
|
measurementId: e,
|
|
3271
3271
|
userId: t
|
|
3272
3272
|
});
|
|
3273
3273
|
} catch (s) {
|
|
3274
|
-
|
|
3274
|
+
n.error("GoogleAnalytics", "Google Analytics initialization failed", {
|
|
3275
3275
|
error: s instanceof Error ? s.message : "Unknown error",
|
|
3276
3276
|
measurementId: e,
|
|
3277
3277
|
userId: t
|
|
@@ -3280,7 +3280,7 @@ class Ft extends p {
|
|
|
3280
3280
|
}
|
|
3281
3281
|
trackEvent(e, t) {
|
|
3282
3282
|
if (!e?.trim()) {
|
|
3283
|
-
|
|
3283
|
+
n.clientWarn("GoogleAnalytics", "Event tracking skipped - invalid event name provided", {
|
|
3284
3284
|
eventName: e,
|
|
3285
3285
|
hasMetadata: !!t && Object.keys(t).length > 0
|
|
3286
3286
|
});
|
|
@@ -3288,7 +3288,7 @@ class Ft extends p {
|
|
|
3288
3288
|
}
|
|
3289
3289
|
if (this.isInitialized) {
|
|
3290
3290
|
if (typeof window.gtag != "function") {
|
|
3291
|
-
|
|
3291
|
+
n.warn("GoogleAnalytics", "Event tracking failed - gtag function not available", {
|
|
3292
3292
|
eventName: e,
|
|
3293
3293
|
hasGtag: typeof window.gtag,
|
|
3294
3294
|
hasDataLayer: Array.isArray(window.dataLayer)
|
|
@@ -3298,7 +3298,7 @@ class Ft extends p {
|
|
|
3298
3298
|
try {
|
|
3299
3299
|
window.gtag("event", e, t);
|
|
3300
3300
|
} catch (s) {
|
|
3301
|
-
|
|
3301
|
+
n.error("GoogleAnalytics", "Event tracking failed", {
|
|
3302
3302
|
eventName: e,
|
|
3303
3303
|
error: s instanceof Error ? s.message : "Unknown error",
|
|
3304
3304
|
metadataKeys: Object.keys(t || {})
|
|
@@ -3309,13 +3309,13 @@ class Ft extends p {
|
|
|
3309
3309
|
cleanup() {
|
|
3310
3310
|
this.isInitialized = !1;
|
|
3311
3311
|
const e = document.getElementById("tracelog-ga-script");
|
|
3312
|
-
e && e.remove(),
|
|
3312
|
+
e && e.remove(), n.info("GoogleAnalytics", "Google Analytics integration cleanup completed");
|
|
3313
3313
|
}
|
|
3314
3314
|
isScriptAlreadyLoaded() {
|
|
3315
3315
|
if (document.getElementById("tracelog-ga-script"))
|
|
3316
3316
|
return !0;
|
|
3317
3317
|
const t = document.querySelector('script[src*="googletagmanager.com/gtag/js"]');
|
|
3318
|
-
return t ? (
|
|
3318
|
+
return t ? (n.clientWarn("GoogleAnalytics", "Google Analytics script already loaded from external source", {
|
|
3319
3319
|
scriptSrc: t.getAttribute("src"),
|
|
3320
3320
|
hasGtag: typeof window.gtag == "function"
|
|
3321
3321
|
}), !0) : !1;
|
|
@@ -3323,20 +3323,20 @@ class Ft extends p {
|
|
|
3323
3323
|
async loadScript(e) {
|
|
3324
3324
|
return new Promise((t, s) => {
|
|
3325
3325
|
try {
|
|
3326
|
-
const
|
|
3327
|
-
|
|
3326
|
+
const i = document.createElement("script");
|
|
3327
|
+
i.id = "tracelog-ga-script", i.async = !0, i.src = `https://www.googletagmanager.com/gtag/js?id=${e}`, i.onload = () => {
|
|
3328
3328
|
t();
|
|
3329
|
-
},
|
|
3329
|
+
}, i.onerror = () => {
|
|
3330
3330
|
const a = new Error("Failed to load Google Analytics script");
|
|
3331
|
-
|
|
3331
|
+
n.error("GoogleAnalytics", "Google Analytics script load failed", {
|
|
3332
3332
|
measurementId: e,
|
|
3333
3333
|
error: a.message,
|
|
3334
|
-
scriptSrc:
|
|
3334
|
+
scriptSrc: i.src
|
|
3335
3335
|
}), s(a);
|
|
3336
|
-
}, document.head.appendChild(
|
|
3337
|
-
} catch (
|
|
3338
|
-
const a =
|
|
3339
|
-
|
|
3336
|
+
}, document.head.appendChild(i);
|
|
3337
|
+
} catch (i) {
|
|
3338
|
+
const a = i instanceof Error ? i : new Error(String(i));
|
|
3339
|
+
n.error("GoogleAnalytics", "Error creating Google Analytics script", {
|
|
3340
3340
|
measurementId: e,
|
|
3341
3341
|
error: a.message
|
|
3342
3342
|
}), s(a);
|
|
@@ -3355,7 +3355,7 @@ class Ft extends p {
|
|
|
3355
3355
|
});
|
|
3356
3356
|
`, document.head.appendChild(s);
|
|
3357
3357
|
} catch (s) {
|
|
3358
|
-
throw
|
|
3358
|
+
throw n.error("GoogleAnalytics", "Failed to configure Google Analytics", {
|
|
3359
3359
|
measurementId: e,
|
|
3360
3360
|
userId: t,
|
|
3361
3361
|
error: s instanceof Error ? s.message : "Unknown error"
|
|
@@ -3368,7 +3368,7 @@ class zt {
|
|
|
3368
3368
|
fallbackStorage = /* @__PURE__ */ new Map();
|
|
3369
3369
|
storageAvailable = !1;
|
|
3370
3370
|
constructor() {
|
|
3371
|
-
this.storage = this.init(), this.storageAvailable = this.storage !== null, this.storageAvailable ||
|
|
3371
|
+
this.storage = this.init(), this.storageAvailable = this.storage !== null, this.storageAvailable || n.warn("StorageManager", "localStorage not available, using memory fallback");
|
|
3372
3372
|
}
|
|
3373
3373
|
getItem(e) {
|
|
3374
3374
|
if (!this.storageAvailable)
|
|
@@ -3376,7 +3376,7 @@ class zt {
|
|
|
3376
3376
|
try {
|
|
3377
3377
|
return this.storage ? this.storage.getItem(e) : this.fallbackStorage.get(e) ?? null;
|
|
3378
3378
|
} catch (t) {
|
|
3379
|
-
return
|
|
3379
|
+
return n.warn("StorageManager", "Storage getItem failed, using memory fallback", { key: e, error: t }), this.storageAvailable = !1, this.fallbackStorage.get(e) ?? null;
|
|
3380
3380
|
}
|
|
3381
3381
|
}
|
|
3382
3382
|
setItem(e, t) {
|
|
@@ -3391,7 +3391,7 @@ class zt {
|
|
|
3391
3391
|
}
|
|
3392
3392
|
this.fallbackStorage.set(e, t);
|
|
3393
3393
|
} catch (s) {
|
|
3394
|
-
|
|
3394
|
+
n.warn("StorageManager", "Storage setItem failed, using memory fallback", { key: e, error: s }), this.storageAvailable = !1, this.fallbackStorage.set(e, t);
|
|
3395
3395
|
}
|
|
3396
3396
|
}
|
|
3397
3397
|
removeItem(e) {
|
|
@@ -3406,7 +3406,7 @@ class zt {
|
|
|
3406
3406
|
}
|
|
3407
3407
|
this.fallbackStorage.delete(e);
|
|
3408
3408
|
} catch (t) {
|
|
3409
|
-
|
|
3409
|
+
n.warn("StorageManager", "Storage removeItem failed, using memory fallback", { key: e, error: t }), this.storageAvailable = !1, this.fallbackStorage.delete(e);
|
|
3410
3410
|
}
|
|
3411
3411
|
}
|
|
3412
3412
|
init() {
|
|
@@ -3427,19 +3427,19 @@ class Vt extends p {
|
|
|
3427
3427
|
super(), this.eventManager = e;
|
|
3428
3428
|
}
|
|
3429
3429
|
async startTracking() {
|
|
3430
|
-
|
|
3430
|
+
n.debug("PerformanceHandler", "Starting performance tracking"), await this.initWebVitals(), this.observeLongTasks(), this.reportTTFB();
|
|
3431
3431
|
}
|
|
3432
3432
|
stopTracking() {
|
|
3433
|
-
|
|
3433
|
+
n.debug("PerformanceHandler", "Stopping performance tracking", { observersCount: this.observers.length }), this.observers.forEach((e, t) => {
|
|
3434
3434
|
try {
|
|
3435
3435
|
e.disconnect();
|
|
3436
3436
|
} catch (s) {
|
|
3437
|
-
|
|
3437
|
+
n.warn("PerformanceHandler", "Failed to disconnect performance observer", {
|
|
3438
3438
|
error: s instanceof Error ? s.message : "Unknown error",
|
|
3439
3439
|
observerIndex: t
|
|
3440
3440
|
});
|
|
3441
3441
|
}
|
|
3442
|
-
}), this.observers.length = 0, this.reportedByNav.clear(),
|
|
3442
|
+
}), this.observers.length = 0, this.reportedByNav.clear(), n.debug("PerformanceHandler", "Performance tracking cleanup completed", {
|
|
3443
3443
|
remainingObservers: this.observers.length,
|
|
3444
3444
|
clearedNavReports: !0
|
|
3445
3445
|
});
|
|
@@ -3448,8 +3448,8 @@ class Vt extends p {
|
|
|
3448
3448
|
this.reportTTFB(), this.safeObserve(
|
|
3449
3449
|
"largest-contentful-paint",
|
|
3450
3450
|
(t) => {
|
|
3451
|
-
const s = t.getEntries(),
|
|
3452
|
-
|
|
3451
|
+
const s = t.getEntries(), i = s[s.length - 1];
|
|
3452
|
+
i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(N)) });
|
|
3453
3453
|
},
|
|
3454
3454
|
{ type: "largest-contentful-paint", buffered: !0 },
|
|
3455
3455
|
!0
|
|
@@ -3459,10 +3459,10 @@ class Vt extends p {
|
|
|
3459
3459
|
"layout-shift",
|
|
3460
3460
|
(t) => {
|
|
3461
3461
|
const s = t.getEntries();
|
|
3462
|
-
for (const
|
|
3463
|
-
if (
|
|
3462
|
+
for (const i of s) {
|
|
3463
|
+
if (i.hadRecentInput === !0)
|
|
3464
3464
|
continue;
|
|
3465
|
-
const a = typeof
|
|
3465
|
+
const a = typeof i.value == "number" ? i.value : 0;
|
|
3466
3466
|
e += a;
|
|
3467
3467
|
}
|
|
3468
3468
|
this.sendVital({ type: "CLS", value: Number(e.toFixed(He)) });
|
|
@@ -3480,8 +3480,8 @@ class Vt extends p {
|
|
|
3480
3480
|
"event",
|
|
3481
3481
|
(t) => {
|
|
3482
3482
|
let s = 0;
|
|
3483
|
-
const
|
|
3484
|
-
for (const a of
|
|
3483
|
+
const i = t.getEntries();
|
|
3484
|
+
for (const a of i) {
|
|
3485
3485
|
const o = (a.processingEnd ?? 0) - (a.startTime ?? 0);
|
|
3486
3486
|
s = Math.max(s, o);
|
|
3487
3487
|
}
|
|
@@ -3492,13 +3492,13 @@ class Vt extends p {
|
|
|
3492
3492
|
}
|
|
3493
3493
|
async initWebVitals() {
|
|
3494
3494
|
try {
|
|
3495
|
-
const { onLCP: e, onCLS: t, onFCP: s, onTTFB:
|
|
3495
|
+
const { onLCP: e, onCLS: t, onFCP: s, onTTFB: i, onINP: a } = await import("./web-vitals-CCnqwnC8.mjs"), o = (l) => (c) => {
|
|
3496
3496
|
const d = Number(c.value.toFixed(N));
|
|
3497
3497
|
this.sendVital({ type: l, value: d });
|
|
3498
3498
|
};
|
|
3499
|
-
e(o("LCP")), t(o("CLS")), s(o("FCP")),
|
|
3499
|
+
e(o("LCP")), t(o("CLS")), s(o("FCP")), i(o("TTFB")), a(o("INP"));
|
|
3500
3500
|
} catch (e) {
|
|
3501
|
-
|
|
3501
|
+
n.warn("PerformanceHandler", "Failed to load web-vitals library, using fallback", {
|
|
3502
3502
|
error: e instanceof Error ? e.message : "Unknown error"
|
|
3503
3503
|
}), this.observeWebVitalsFallback();
|
|
3504
3504
|
}
|
|
@@ -3507,13 +3507,13 @@ class Vt extends p {
|
|
|
3507
3507
|
try {
|
|
3508
3508
|
const e = performance.getEntriesByType("navigation")[0];
|
|
3509
3509
|
if (!e) {
|
|
3510
|
-
|
|
3510
|
+
n.debug("PerformanceHandler", "Navigation timing not available for TTFB");
|
|
3511
3511
|
return;
|
|
3512
3512
|
}
|
|
3513
3513
|
const t = e.responseStart;
|
|
3514
|
-
typeof t == "number" && Number.isFinite(t) ? this.sendVital({ type: "TTFB", value: Number(t.toFixed(N)) }) :
|
|
3514
|
+
typeof t == "number" && Number.isFinite(t) ? this.sendVital({ type: "TTFB", value: Number(t.toFixed(N)) }) : n.debug("PerformanceHandler", "TTFB value is not a valid number", { ttfb: t });
|
|
3515
3515
|
} catch (e) {
|
|
3516
|
-
|
|
3516
|
+
n.warn("PerformanceHandler", "Failed to report TTFB", {
|
|
3517
3517
|
error: e instanceof Error ? e.message : "Unknown error"
|
|
3518
3518
|
});
|
|
3519
3519
|
}
|
|
@@ -3524,8 +3524,8 @@ class Vt extends p {
|
|
|
3524
3524
|
(e) => {
|
|
3525
3525
|
const t = e.getEntries();
|
|
3526
3526
|
for (const s of t) {
|
|
3527
|
-
const
|
|
3528
|
-
a - this.lastLongTaskSentAt >=
|
|
3527
|
+
const i = Number(s.duration.toFixed(N)), a = Date.now();
|
|
3528
|
+
a - this.lastLongTaskSentAt >= Be && (this.trackWebVital("LONG_TASK", i), this.lastLongTaskSentAt = a);
|
|
3529
3529
|
}
|
|
3530
3530
|
},
|
|
3531
3531
|
{ type: "longtask", buffered: !0 }
|
|
@@ -3535,16 +3535,16 @@ class Vt extends p {
|
|
|
3535
3535
|
const t = this.getNavigationId(), s = `${e.type}`;
|
|
3536
3536
|
if (t) {
|
|
3537
3537
|
this.reportedByNav.has(t) || this.reportedByNav.set(t, /* @__PURE__ */ new Set());
|
|
3538
|
-
const
|
|
3539
|
-
if (
|
|
3538
|
+
const i = this.reportedByNav.get(t);
|
|
3539
|
+
if (i.has(s))
|
|
3540
3540
|
return;
|
|
3541
|
-
|
|
3541
|
+
i.add(s);
|
|
3542
3542
|
}
|
|
3543
3543
|
this.trackWebVital(e.type, e.value);
|
|
3544
3544
|
}
|
|
3545
3545
|
trackWebVital(e, t) {
|
|
3546
3546
|
if (typeof t != "number" || !Number.isFinite(t)) {
|
|
3547
|
-
|
|
3547
|
+
n.warn("PerformanceHandler", "Invalid web vital value", { type: e, value: t });
|
|
3548
3548
|
return;
|
|
3549
3549
|
}
|
|
3550
3550
|
this.eventManager.track({
|
|
@@ -3560,26 +3560,26 @@ class Vt extends p {
|
|
|
3560
3560
|
const e = performance.getEntriesByType("navigation")[0];
|
|
3561
3561
|
return e ? `${Math.round(e.startTime)}_${window.location.pathname}` : null;
|
|
3562
3562
|
} catch (e) {
|
|
3563
|
-
return
|
|
3563
|
+
return n.warn("PerformanceHandler", "Failed to get navigation ID", {
|
|
3564
3564
|
error: e instanceof Error ? e.message : "Unknown error"
|
|
3565
3565
|
}), null;
|
|
3566
3566
|
}
|
|
3567
3567
|
}
|
|
3568
|
-
safeObserve(e, t, s,
|
|
3568
|
+
safeObserve(e, t, s, i = !1) {
|
|
3569
3569
|
try {
|
|
3570
3570
|
if (typeof PerformanceObserver > "u") return;
|
|
3571
3571
|
const a = PerformanceObserver.supportedEntryTypes;
|
|
3572
3572
|
if (a && !a.includes(e)) return;
|
|
3573
3573
|
const o = new PerformanceObserver((l, c) => {
|
|
3574
|
-
if (t(l, c),
|
|
3574
|
+
if (t(l, c), i)
|
|
3575
3575
|
try {
|
|
3576
3576
|
c.disconnect();
|
|
3577
3577
|
} catch {
|
|
3578
3578
|
}
|
|
3579
3579
|
});
|
|
3580
|
-
o.observe(s ?? { type: e, buffered: !0 }),
|
|
3580
|
+
o.observe(s ?? { type: e, buffered: !0 }), i || this.observers.push(o);
|
|
3581
3581
|
} catch (a) {
|
|
3582
|
-
|
|
3582
|
+
n.warn("PerformanceHandler", "Failed to create performance observer", {
|
|
3583
3583
|
type: e,
|
|
3584
3584
|
error: a instanceof Error ? a.message : "Unknown error"
|
|
3585
3585
|
});
|
|
@@ -3598,10 +3598,10 @@ class $t extends p {
|
|
|
3598
3598
|
super(), this.eventManager = e;
|
|
3599
3599
|
}
|
|
3600
3600
|
startTracking() {
|
|
3601
|
-
|
|
3601
|
+
n.debug("ErrorHandler", "Starting error tracking"), this.setupErrorListener(), this.setupUnhandledRejectionListener();
|
|
3602
3602
|
}
|
|
3603
3603
|
stopTracking() {
|
|
3604
|
-
|
|
3604
|
+
n.debug("ErrorHandler", "Stopping error tracking"), window.removeEventListener("error", this.handleError), window.removeEventListener("unhandledrejection", this.handleUnhandledRejection);
|
|
3605
3605
|
}
|
|
3606
3606
|
setupErrorListener() {
|
|
3607
3607
|
window.addEventListener("error", this.handleError);
|
|
@@ -3612,12 +3612,12 @@ class $t extends p {
|
|
|
3612
3612
|
handleError = (e) => {
|
|
3613
3613
|
const t = this.get("config");
|
|
3614
3614
|
if (!this.shouldSample(t?.errorSampling ?? 0.1)) {
|
|
3615
|
-
|
|
3615
|
+
n.debug("ErrorHandler", `Error not sampled, skipping (errorSampling: ${t?.errorSampling})`, {
|
|
3616
3616
|
errorSampling: t?.errorSampling
|
|
3617
3617
|
});
|
|
3618
3618
|
return;
|
|
3619
3619
|
}
|
|
3620
|
-
|
|
3620
|
+
n.warn(
|
|
3621
3621
|
"ErrorHandler",
|
|
3622
3622
|
`JavaScript error captured: ${e.message} (filename: ${e.filename}, lineno: ${e.lineno})`,
|
|
3623
3623
|
{
|
|
@@ -3636,12 +3636,12 @@ class $t extends p {
|
|
|
3636
3636
|
handleUnhandledRejection = (e) => {
|
|
3637
3637
|
const t = this.get("config");
|
|
3638
3638
|
if (!this.shouldSample(t?.errorSampling ?? 0.1)) {
|
|
3639
|
-
|
|
3639
|
+
n.debug("ErrorHandler", "Promise rejection not sampled, skipping", {
|
|
3640
3640
|
errorSampling: t?.errorSampling
|
|
3641
3641
|
});
|
|
3642
3642
|
return;
|
|
3643
3643
|
}
|
|
3644
|
-
|
|
3644
|
+
n.warn("ErrorHandler", `Unhandled promise rejection captured (reason: ${typeof e.reason})`, {
|
|
3645
3645
|
reason: typeof e.reason
|
|
3646
3646
|
});
|
|
3647
3647
|
let s = "Unknown rejection";
|
|
@@ -3672,37 +3672,37 @@ class jt extends p {
|
|
|
3672
3672
|
super(), this.eventManager = e, this.originalFetch = window.fetch, this.originalXHROpen = XMLHttpRequest.prototype.open, this.originalXHRSend = XMLHttpRequest.prototype.send;
|
|
3673
3673
|
}
|
|
3674
3674
|
startTracking() {
|
|
3675
|
-
|
|
3675
|
+
n.debug("NetworkHandler", "Starting network error tracking"), this.interceptFetch(), this.interceptXHR();
|
|
3676
3676
|
}
|
|
3677
3677
|
stopTracking() {
|
|
3678
|
-
|
|
3678
|
+
n.debug("NetworkHandler", "Stopping network error tracking"), window.fetch = this.originalFetch, XMLHttpRequest.prototype.open = this.originalXHROpen, XMLHttpRequest.prototype.send = this.originalXHRSend;
|
|
3679
3679
|
}
|
|
3680
3680
|
interceptFetch() {
|
|
3681
3681
|
window.fetch = async (e, t) => {
|
|
3682
|
-
const s = Date.now(),
|
|
3682
|
+
const s = Date.now(), i = typeof e == "string" ? e : e.toString(), a = t?.method ?? "GET";
|
|
3683
3683
|
try {
|
|
3684
3684
|
const o = await this.originalFetch(e, t), l = Date.now() - s;
|
|
3685
|
-
return o.ok || (
|
|
3685
|
+
return o.ok || (n.debug("NetworkHandler", "Fetch error detected", {
|
|
3686
3686
|
method: a,
|
|
3687
|
-
url: this.normalizeUrlForTracking(
|
|
3687
|
+
url: this.normalizeUrlForTracking(i),
|
|
3688
3688
|
status: o.status,
|
|
3689
3689
|
statusText: o.statusText
|
|
3690
3690
|
}), this.trackNetworkError(
|
|
3691
3691
|
a.toUpperCase(),
|
|
3692
|
-
this.normalizeUrlForTracking(
|
|
3692
|
+
this.normalizeUrlForTracking(i),
|
|
3693
3693
|
o.status,
|
|
3694
3694
|
o.statusText,
|
|
3695
3695
|
l
|
|
3696
3696
|
)), o;
|
|
3697
3697
|
} catch (o) {
|
|
3698
3698
|
const l = Date.now() - s, c = o instanceof Error ? o.message : "Network Error";
|
|
3699
|
-
throw
|
|
3699
|
+
throw n.debug("NetworkHandler", "Fetch exception caught", {
|
|
3700
3700
|
method: a,
|
|
3701
|
-
url: this.normalizeUrlForTracking(
|
|
3701
|
+
url: this.normalizeUrlForTracking(i),
|
|
3702
3702
|
error: c
|
|
3703
3703
|
}), this.trackNetworkError(
|
|
3704
3704
|
a.toUpperCase(),
|
|
3705
|
-
this.normalizeUrlForTracking(
|
|
3705
|
+
this.normalizeUrlForTracking(i),
|
|
3706
3706
|
void 0,
|
|
3707
3707
|
c,
|
|
3708
3708
|
l
|
|
@@ -3711,7 +3711,7 @@ class jt extends p {
|
|
|
3711
3711
|
};
|
|
3712
3712
|
}
|
|
3713
3713
|
interceptXHR() {
|
|
3714
|
-
const e = this.trackNetworkError.bind(this), t = this.normalizeUrlForTracking.bind(this), s = this.originalXHROpen,
|
|
3714
|
+
const e = this.trackNetworkError.bind(this), t = this.normalizeUrlForTracking.bind(this), s = this.originalXHROpen, i = this.originalXHRSend;
|
|
3715
3715
|
XMLHttpRequest.prototype.open = function(a, o, l, c, d) {
|
|
3716
3716
|
const u = l ?? !0, g = this;
|
|
3717
3717
|
return g._tracelogStartTime = Date.now(), g._tracelogMethod = a.toUpperCase(), g._tracelogUrl = o.toString(), s.call(this, a, o, u, c, d);
|
|
@@ -3722,7 +3722,7 @@ class jt extends p {
|
|
|
3722
3722
|
const y = Date.now() - l;
|
|
3723
3723
|
if (o.status === 0 || o.status >= 400) {
|
|
3724
3724
|
const I = o.statusText || "Request Failed";
|
|
3725
|
-
|
|
3725
|
+
n.debug("NetworkHandler", "XHR error detected", {
|
|
3726
3726
|
method: c,
|
|
3727
3727
|
url: t(d),
|
|
3728
3728
|
status: o.status,
|
|
@@ -3732,13 +3732,13 @@ class jt extends p {
|
|
|
3732
3732
|
}
|
|
3733
3733
|
if (u)
|
|
3734
3734
|
return u.call(o, g);
|
|
3735
|
-
},
|
|
3735
|
+
}, i.call(this, a);
|
|
3736
3736
|
};
|
|
3737
3737
|
}
|
|
3738
|
-
trackNetworkError(e, t, s,
|
|
3738
|
+
trackNetworkError(e, t, s, i, a) {
|
|
3739
3739
|
const o = this.get("config");
|
|
3740
3740
|
if (!this.shouldSample(o?.errorSampling ?? 0.1)) {
|
|
3741
|
-
|
|
3741
|
+
n.debug(
|
|
3742
3742
|
"NetworkHandler",
|
|
3743
3743
|
`Network error not sampled, skipping (errorSampling: ${o?.errorSampling}, method: ${e}, url: ${t})`,
|
|
3744
3744
|
{
|
|
@@ -3749,19 +3749,19 @@ class jt extends p {
|
|
|
3749
3749
|
);
|
|
3750
3750
|
return;
|
|
3751
3751
|
}
|
|
3752
|
-
|
|
3752
|
+
n.warn(
|
|
3753
3753
|
"NetworkHandler",
|
|
3754
|
-
`Network error tracked: ${e} ${t} (status: ${s}, statusText: ${
|
|
3755
|
-
{ method: e, url: t, status: s, statusText:
|
|
3754
|
+
`Network error tracked: ${e} ${t} (status: ${s}, statusText: ${i}, duration: ${a}ms)`,
|
|
3755
|
+
{ method: e, url: t, status: s, statusText: i, duration: a }
|
|
3756
3756
|
), this.eventManager.track({
|
|
3757
3757
|
type: h.ERROR,
|
|
3758
3758
|
error_data: {
|
|
3759
3759
|
type: D.NETWORK_ERROR,
|
|
3760
|
-
message:
|
|
3760
|
+
message: i,
|
|
3761
3761
|
method: e,
|
|
3762
3762
|
url: t,
|
|
3763
3763
|
status: s,
|
|
3764
|
-
statusText:
|
|
3764
|
+
statusText: i,
|
|
3765
3765
|
duration: a
|
|
3766
3766
|
}
|
|
3767
3767
|
});
|
|
@@ -3800,16 +3800,16 @@ class Gt extends p {
|
|
|
3800
3800
|
}
|
|
3801
3801
|
async init(e) {
|
|
3802
3802
|
if (this.isInitialized) {
|
|
3803
|
-
|
|
3803
|
+
n.debug("App", "App already initialized, skipping re-initialization", { projectId: e.id });
|
|
3804
3804
|
return;
|
|
3805
3805
|
}
|
|
3806
|
-
|
|
3806
|
+
n.info("App", "App initialization started", { projectId: e.id }), this.validateAppReadiness(e);
|
|
3807
3807
|
try {
|
|
3808
|
-
this.initStorage(), await this.setState(e), await this.setIntegrations(), this.setEventManager(), await this.initHandlers(), this.isInitialized = !0,
|
|
3808
|
+
this.initStorage(), await this.setState(e), await this.setIntegrations(), this.setEventManager(), await this.initHandlers(), this.isInitialized = !0, n.info("App", "App initialization completed successfully", {
|
|
3809
3809
|
projectId: e.id
|
|
3810
3810
|
});
|
|
3811
3811
|
} catch (t) {
|
|
3812
|
-
throw this.isInitialized = !1,
|
|
3812
|
+
throw this.isInitialized = !1, n.error("App", "App initialization failed", { projectId: e.id, error: t }), t;
|
|
3813
3813
|
}
|
|
3814
3814
|
}
|
|
3815
3815
|
/**
|
|
@@ -3820,19 +3820,19 @@ class Gt extends p {
|
|
|
3820
3820
|
*/
|
|
3821
3821
|
validateAppReadiness(e) {
|
|
3822
3822
|
if (!e?.id)
|
|
3823
|
-
throw
|
|
3823
|
+
throw n.clientError("App", "Configuration integrity check failed - missing project ID", {
|
|
3824
3824
|
hasConfig: !!e,
|
|
3825
3825
|
hasId: !!e?.id
|
|
3826
3826
|
}), new Q("Configuration integrity check failed", "app");
|
|
3827
3827
|
}
|
|
3828
3828
|
sendCustomEvent(e, t) {
|
|
3829
3829
|
if (!this.eventManager) {
|
|
3830
|
-
|
|
3830
|
+
n.warn("App", "Custom event attempted before eventManager initialization", { eventName: e });
|
|
3831
3831
|
return;
|
|
3832
3832
|
}
|
|
3833
|
-
const { valid: s, error:
|
|
3833
|
+
const { valid: s, error: i, sanitizedMetadata: a } = vt(e, t);
|
|
3834
3834
|
if (s)
|
|
3835
|
-
|
|
3835
|
+
n.debug("App", "Custom event validated and queued", { eventName: e, hasMetadata: !!a }), this.eventManager.track({
|
|
3836
3836
|
type: h.CUSTOM,
|
|
3837
3837
|
custom_event: {
|
|
3838
3838
|
name: e,
|
|
@@ -3841,23 +3841,23 @@ class Gt extends p {
|
|
|
3841
3841
|
});
|
|
3842
3842
|
else {
|
|
3843
3843
|
const o = this.get("config")?.mode;
|
|
3844
|
-
if (
|
|
3844
|
+
if (n.clientError("App", `Custom event validation failed: ${i ?? "unknown error"}`, {
|
|
3845
3845
|
eventName: e,
|
|
3846
|
-
validationError:
|
|
3846
|
+
validationError: i,
|
|
3847
3847
|
hasMetadata: !!t,
|
|
3848
3848
|
mode: o
|
|
3849
3849
|
}), o === "qa" || o === "debug")
|
|
3850
3850
|
throw new Error(
|
|
3851
|
-
`custom event "${e}" validation failed (${
|
|
3851
|
+
`custom event "${e}" validation failed (${i ?? "unknown error"}). Please, review your event data and try again.`
|
|
3852
3852
|
);
|
|
3853
3853
|
}
|
|
3854
3854
|
}
|
|
3855
3855
|
destroy() {
|
|
3856
3856
|
if (!this.isInitialized) {
|
|
3857
|
-
|
|
3857
|
+
n.warn("App", "Destroy called but app was not initialized");
|
|
3858
3858
|
return;
|
|
3859
3859
|
}
|
|
3860
|
-
|
|
3860
|
+
n.info("App", "App cleanup started"), this.googleAnalytics && this.googleAnalytics.cleanup(), this.sessionHandler && this.sessionHandler.stopTracking(), this.pageViewHandler && this.pageViewHandler.stopTracking(), this.clickHandler && this.clickHandler.stopTracking(), this.scrollHandler && this.scrollHandler.stopTracking(), this.performanceHandler && this.performanceHandler.stopTracking(), this.errorHandler && this.errorHandler.stopTracking(), this.networkHandler && this.networkHandler.stopTracking(), this.suppressNextScrollTimer && (clearTimeout(this.suppressNextScrollTimer), this.suppressNextScrollTimer = null), this.eventManager && this.eventManager.stop(), this.set("hasStartSession", !1), this.set("suppressNextScroll", !1), this.set("sessionId", null), this.isInitialized = !1, n.info("App", "App cleanup completed successfully");
|
|
3861
3861
|
}
|
|
3862
3862
|
async setState(e) {
|
|
3863
3863
|
this.setApiUrl(e.id, e.allowHttp), await this.setConfig(e), this.setUserId(), this.setDevice(), this.setPageUrl();
|
|
@@ -3953,15 +3953,15 @@ const Qt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
3953
3953
|
TagConditionOperator: f,
|
|
3954
3954
|
TagConditionType: m,
|
|
3955
3955
|
TagLogicalOperator: G
|
|
3956
|
-
}, Symbol.toStringTag, { value: "Module" })),
|
|
3956
|
+
}, Symbol.toStringTag, { value: "Module" })), Bt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3957
3957
|
__proto__: null,
|
|
3958
3958
|
DEFAULT_SESSION_TIMEOUT_MS: R
|
|
3959
3959
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
3960
3960
|
let v = null, T = !1;
|
|
3961
|
-
const
|
|
3961
|
+
const qt = async (r) => {
|
|
3962
3962
|
try {
|
|
3963
|
-
if (
|
|
3964
|
-
throw
|
|
3963
|
+
if (n.info("API", "Library initialization started", { id: r.id }), typeof window > "u" || typeof document > "u")
|
|
3964
|
+
throw n.clientError(
|
|
3965
3965
|
"API",
|
|
3966
3966
|
"Browser environment required - this library can only be used in a browser environment",
|
|
3967
3967
|
{
|
|
@@ -3970,36 +3970,36 @@ const Bt = async (r) => {
|
|
|
3970
3970
|
}
|
|
3971
3971
|
), new Error("This library can only be used in a browser environment");
|
|
3972
3972
|
if (v) {
|
|
3973
|
-
|
|
3973
|
+
n.debug("API", "Library already initialized, skipping duplicate initialization", {
|
|
3974
3974
|
projectId: r.id
|
|
3975
3975
|
});
|
|
3976
3976
|
return;
|
|
3977
3977
|
}
|
|
3978
3978
|
if (T) {
|
|
3979
|
-
|
|
3979
|
+
n.debug("API", "Concurrent initialization detected, waiting for completion", { projectId: r.id });
|
|
3980
3980
|
let s = 0;
|
|
3981
|
-
const
|
|
3982
|
-
for (; T && s <
|
|
3981
|
+
const i = me.MAX_CONCURRENT_RETRIES, a = me.CONCURRENT_RETRY_DELAY_MS;
|
|
3982
|
+
for (; T && s < i; )
|
|
3983
3983
|
await new Promise((o) => setTimeout(o, a)), s++;
|
|
3984
3984
|
if (v) {
|
|
3985
|
-
|
|
3985
|
+
n.debug("API", "Concurrent initialization completed successfully", {
|
|
3986
3986
|
projectId: r.id,
|
|
3987
3987
|
retriesUsed: s
|
|
3988
3988
|
});
|
|
3989
3989
|
return;
|
|
3990
3990
|
}
|
|
3991
3991
|
if (T)
|
|
3992
|
-
throw
|
|
3992
|
+
throw n.error("API", "Initialization timeout - concurrent initialization took too long", {
|
|
3993
3993
|
projectId: r.id,
|
|
3994
3994
|
retriesUsed: s,
|
|
3995
|
-
maxRetries:
|
|
3995
|
+
maxRetries: i
|
|
3996
3996
|
}), new Error("App initialization timeout - concurrent initialization took too long");
|
|
3997
3997
|
}
|
|
3998
|
-
T = !0,
|
|
3998
|
+
T = !0, n.debug("API", "Validating and normalizing configuration", { projectId: r.id });
|
|
3999
3999
|
const e = dt(r);
|
|
4000
|
-
|
|
4000
|
+
n.debug("API", "Creating App instance", { projectId: e.id });
|
|
4001
4001
|
const t = new Gt();
|
|
4002
|
-
await t.init(e), v = t,
|
|
4002
|
+
await t.init(e), v = t, n.info("API", "Library initialization completed successfully", {
|
|
4003
4003
|
projectId: e.id
|
|
4004
4004
|
});
|
|
4005
4005
|
} catch (e) {
|
|
@@ -4007,26 +4007,26 @@ const Bt = async (r) => {
|
|
|
4007
4007
|
try {
|
|
4008
4008
|
v.destroy();
|
|
4009
4009
|
} catch (t) {
|
|
4010
|
-
|
|
4010
|
+
n.warn("API", "Failed to cleanup partially initialized app", { cleanupError: t });
|
|
4011
4011
|
}
|
|
4012
|
-
throw v = null,
|
|
4012
|
+
throw v = null, n.error("API", "Initialization failed", { error: e }), e;
|
|
4013
4013
|
} finally {
|
|
4014
4014
|
T = !1;
|
|
4015
4015
|
}
|
|
4016
4016
|
}, Wt = (r, e) => {
|
|
4017
4017
|
try {
|
|
4018
4018
|
if (!v)
|
|
4019
|
-
throw
|
|
4019
|
+
throw n.clientError("API", "Custom event failed - Library not initialized. Please call TraceLog.init() first", {
|
|
4020
4020
|
eventName: r,
|
|
4021
4021
|
hasMetadata: !!e
|
|
4022
4022
|
}), new Error("App not initialized");
|
|
4023
|
-
|
|
4023
|
+
n.debug("API", "Sending custom event", {
|
|
4024
4024
|
eventName: r,
|
|
4025
4025
|
hasMetadata: !!e,
|
|
4026
4026
|
metadataKeys: e ? Object.keys(e) : []
|
|
4027
4027
|
}), v.sendCustomEvent(r, e);
|
|
4028
4028
|
} catch (t) {
|
|
4029
|
-
if (
|
|
4029
|
+
if (n.error("API", "Event tracking failed", { eventName: r, error: t, hasMetadata: !!e }), t instanceof Error && (t.message === "App not initialized" || t.message.includes("validation failed")))
|
|
4030
4030
|
throw t;
|
|
4031
4031
|
}
|
|
4032
4032
|
}, Xt = () => v !== null, Kt = () => ({
|
|
@@ -4035,20 +4035,20 @@ const Bt = async (r) => {
|
|
|
4035
4035
|
hasInstance: v !== null
|
|
4036
4036
|
}), Yt = () => {
|
|
4037
4037
|
try {
|
|
4038
|
-
if (
|
|
4039
|
-
throw
|
|
4040
|
-
v.destroy(), v = null, T = !1,
|
|
4038
|
+
if (n.info("API", "Library cleanup initiated"), !v)
|
|
4039
|
+
throw n.warn("API", "Cleanup called but Library was not initialized"), new Error("App not initialized");
|
|
4040
|
+
v.destroy(), v = null, T = !1, n.info("API", "Library cleanup completed successfully");
|
|
4041
4041
|
} catch (r) {
|
|
4042
|
-
|
|
4042
|
+
n.error("API", "Cleanup failed", { error: r, hadApp: !!v, wasInitializing: T });
|
|
4043
4043
|
}
|
|
4044
4044
|
}, Jt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
4045
4045
|
__proto__: null,
|
|
4046
|
-
Constants:
|
|
4046
|
+
Constants: Bt,
|
|
4047
4047
|
Types: Qt,
|
|
4048
4048
|
destroy: Yt,
|
|
4049
4049
|
event: Wt,
|
|
4050
4050
|
getInitializationStatus: Kt,
|
|
4051
|
-
init:
|
|
4051
|
+
init: qt,
|
|
4052
4052
|
isInitialized: Xt
|
|
4053
4053
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
4054
4054
|
export {
|