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