@tracelog/lib 0.4.0 → 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 +620 -658
- 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 +1 -46
- package/dist/cjs/managers/event.manager.js +15 -70
- 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 +42 -83
- 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 -4
- 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 +1 -46
- package/dist/esm/managers/event.manager.js +15 -70
- 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 +42 -83
- 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 -4
- 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, Ze = 1e3, et = 1e4, Ue = 250, tt = 24, Ee = 500, ve =
|
|
|
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",
|
|
@@ -61,28 +59,19 @@ const ee = 15 * 60 * 1e3, Ze = 1e3, et = 1e4, Ue = 250, tt = 24, Ee = 500, ve =
|
|
|
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
|
-
...Ve,
|
|
71
|
-
...r,
|
|
72
|
-
allowHttp: !1,
|
|
73
|
-
sessionTimeout: ee,
|
|
74
|
-
samplingRate: r.samplingRate && r.samplingRate > st && r.samplingRate <= it ? r.samplingRate : A,
|
|
75
|
-
excludedUrlPaths: r.excludedUrlPaths ?? [],
|
|
76
|
-
tags: r.tags ?? [],
|
|
77
|
-
ipExcluded: r.ipExcluded ?? !1
|
|
78
|
-
}), _ = "tl", dt = (r) => r ? `${_}:${r}:uid` : `${_}:uid`, ht = (r) => r ? `${_}:${r}:queue` : `${_}:queue`, gt = (r) => r ? `${_}:${r}:session` : `${_}:session`, ft = (r) => r ? `${_}:${r}:broadcast` : `${_}:broadcast`, Fe = {
|
|
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, Ze = 1e3, et = 1e4, Ue = 250, tt = 24, Ee = 500, ve =
|
|
|
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
|
|
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 pt 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);
|
|
@@ -169,11 +149,11 @@ class pt extends f {
|
|
|
169
149
|
return ["CLIENT_ERROR", "ERROR"].includes(e) ? "error" : ["CLIENT_WARN", "WARN"].includes(e) ? "warn" : "log";
|
|
170
150
|
}
|
|
171
151
|
}
|
|
172
|
-
const a = new
|
|
173
|
-
let te,
|
|
174
|
-
const
|
|
175
|
-
typeof window < "u" && !te && (te = window.matchMedia("(pointer: coarse)"),
|
|
176
|
-
},
|
|
152
|
+
const a = new mt();
|
|
153
|
+
let te, ze;
|
|
154
|
+
const pt = () => {
|
|
155
|
+
typeof window < "u" && !te && (te = window.matchMedia("(pointer: coarse)"), ze = window.matchMedia("(hover: none)"));
|
|
156
|
+
}, St = () => {
|
|
177
157
|
try {
|
|
178
158
|
a.debug("DeviceDetector", "Starting device detection");
|
|
179
159
|
const r = navigator;
|
|
@@ -182,12 +162,12 @@ const St = () => {
|
|
|
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
|
-
a.debug("DeviceDetector", "Using fallback detection methods"),
|
|
190
|
-
const e = window.innerWidth, t = te?.matches ?? !1, n =
|
|
169
|
+
a.debug("DeviceDetector", "Using fallback detection methods"), pt();
|
|
170
|
+
const e = window.innerWidth, t = te?.matches ?? !1, n = ze?.matches ?? !1, s = "ontouchstart" in window || navigator.maxTouchPoints > 0, i = navigator.userAgent.toLowerCase(), o = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(i), c = /tablet|ipad|android(?!.*mobile)/.test(i), l = {
|
|
191
171
|
width: e,
|
|
192
172
|
hasCoarsePointer: t,
|
|
193
173
|
hasNoHover: n,
|
|
@@ -196,19 +176,19 @@ const St = () => {
|
|
|
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];
|
|
@@ -220,81 +200,81 @@ const St = () => {
|
|
|
220
200
|
parameterCount: Object.keys(t).length,
|
|
221
201
|
parameters: Object.keys(t)
|
|
222
202
|
}) : a.debug("UTMParams", "No UTM parameters found in URL"), t;
|
|
223
|
-
},
|
|
203
|
+
}, Et = () => typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (r) => {
|
|
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
|
|
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
|
-
const
|
|
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
|
|
279
|
-
if (r.scrollContainerSelectors !== void 0 &&
|
|
258
|
+
}), new A(y.INVALID_GLOBAL_METADATA, "config");
|
|
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
|
|
297
|
-
},
|
|
276
|
+
}), new _t(y.INVALID_ERROR_SAMPLING_RATE, "config");
|
|
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;
|
|
300
280
|
let t = 0;
|
|
@@ -305,7 +285,7 @@ const At = (r) => {
|
|
|
305
285
|
for (const s of r)
|
|
306
286
|
if (s === "[" && n++, s === "]" && n--, n < 0) return !1;
|
|
307
287
|
return n === 0;
|
|
308
|
-
},
|
|
288
|
+
}, bt = (r) => {
|
|
309
289
|
const e = Array.isArray(r) ? r : [r];
|
|
310
290
|
for (const t of e) {
|
|
311
291
|
if (typeof t != "string" || t.trim() === "")
|
|
@@ -313,28 +293,28 @@ const At = (r) => {
|
|
|
313
293
|
selector: t,
|
|
314
294
|
type: typeof t,
|
|
315
295
|
isEmpty: t === "" || typeof t == "string" && t.trim() === ""
|
|
316
|
-
}), new
|
|
317
|
-
if (!
|
|
296
|
+
}), new A(y.INVALID_SCROLL_CONTAINER_SELECTORS, "config");
|
|
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) {
|
|
325
305
|
if (!r.googleAnalytics.measurementId || typeof r.googleAnalytics.measurementId != "string" || r.googleAnalytics.measurementId.trim() === "")
|
|
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
|
-
},
|
|
337
|
-
|
|
316
|
+
}, Rt = (r) => {
|
|
317
|
+
wt(r);
|
|
338
318
|
const e = {
|
|
339
319
|
...r,
|
|
340
320
|
id: r.id.trim(),
|
|
@@ -345,41 +325,9 @@ const At = (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
|
-
}, Ct = (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
|
-
}, Pt = (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 = Nt(r.samplingRate, e) ?? A;
|
|
371
|
-
return r.tags !== void 0 && !Array.isArray(r.tags) && e.push("tags must be an array"), Ct(r.excludedUrlPaths, e), { errors: e, warnings: t, samplingRate: n };
|
|
372
|
-
}, V = (r) => {
|
|
373
|
-
const { errors: e, warnings: t, samplingRate: n } = Pt(r);
|
|
374
|
-
return {
|
|
375
|
-
config: {
|
|
376
|
-
...r,
|
|
377
|
-
samplingRate: n
|
|
378
|
-
},
|
|
379
|
-
errors: e,
|
|
380
|
-
warnings: t
|
|
381
|
-
};
|
|
382
|
-
}, Oe = (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;
|
|
@@ -406,7 +354,7 @@ const At = (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)));
|
|
@@ -414,28 +362,28 @@ const At = (r) => {
|
|
|
414
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 At = (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 At = (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 At = (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 At = (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 At = (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 At = (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 At = (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 At = (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 At = (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 At = (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 At = (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 At = (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 At = (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 Gt(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 jt {
|
|
|
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 $t(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
|
-
timeout:
|
|
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 Qt 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 Qt 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(),
|
|
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() {
|
|
@@ -984,7 +1010,7 @@ class Qt extends f {
|
|
|
984
1010
|
return null;
|
|
985
1011
|
}
|
|
986
1012
|
isDataRecent(e) {
|
|
987
|
-
return !e.timestamp || typeof e.timestamp != "number" ? !1 : (Date.now() - e.timestamp) / (1e3 * 60 * 60) <
|
|
1013
|
+
return !e.timestamp || typeof e.timestamp != "number" ? !1 : (Date.now() - e.timestamp) / (1e3 * 60 * 60) < et;
|
|
988
1014
|
}
|
|
989
1015
|
createRecoveryBody(e) {
|
|
990
1016
|
return {
|
|
@@ -1012,7 +1038,8 @@ class Qt 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 Qt 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
|
-
const n =
|
|
1031
|
-
this.retryTimeoutId = window.setTimeout(async () => {
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
this.isRetrying = !1;
|
|
1038
|
-
}
|
|
1057
|
+
const n = tt * Math.pow(2, this.retryCount);
|
|
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 Qt 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 Qt 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 Wt 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 Wt 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,
|
|
@@ -1102,77 +1116,63 @@ class Wt extends f {
|
|
|
1102
1116
|
custom_event: o,
|
|
1103
1117
|
web_vitals: c,
|
|
1104
1118
|
error_data: l,
|
|
1105
|
-
session_end_reason: u
|
|
1106
|
-
session_start_recovered: h
|
|
1119
|
+
session_end_reason: u
|
|
1107
1120
|
}) {
|
|
1108
1121
|
if (!e) {
|
|
1109
1122
|
a.warn("EventManager", "Event type is required");
|
|
1110
1123
|
return;
|
|
1111
1124
|
}
|
|
1112
|
-
const
|
|
1113
|
-
type:
|
|
1114
|
-
page_url:
|
|
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({
|
|
1126
|
+
type: h,
|
|
1127
|
+
page_url: qe,
|
|
1115
1128
|
from_page_url: n,
|
|
1116
1129
|
scroll_data: s,
|
|
1117
1130
|
click_data: i,
|
|
1118
1131
|
custom_event: o,
|
|
1119
1132
|
web_vitals: c,
|
|
1120
1133
|
error_data: l,
|
|
1121
|
-
session_end_reason: u
|
|
1122
|
-
session_start_recovered: h
|
|
1134
|
+
session_end_reason: u
|
|
1123
1135
|
});
|
|
1124
|
-
if (!this.isEventExcluded(
|
|
1125
|
-
if (
|
|
1126
|
-
const
|
|
1127
|
-
if (!
|
|
1136
|
+
if (!this.isEventExcluded(K) && !(!Xe && !this.shouldSample())) {
|
|
1137
|
+
if (L) {
|
|
1138
|
+
const me = this.get("sessionId");
|
|
1139
|
+
if (!me) {
|
|
1128
1140
|
a.warn("EventManager", "Session start event ignored: missing sessionId");
|
|
1129
1141
|
return;
|
|
1130
1142
|
}
|
|
1131
1143
|
if (this.get("hasStartSession")) {
|
|
1132
1144
|
a.warn("EventManager", "Duplicate session_start detected", {
|
|
1133
|
-
sessionId:
|
|
1145
|
+
sessionId: me
|
|
1134
1146
|
});
|
|
1135
1147
|
return;
|
|
1136
1148
|
}
|
|
1137
1149
|
this.set("hasStartSession", !0);
|
|
1138
1150
|
}
|
|
1139
|
-
this.isDuplicateEvent(
|
|
1151
|
+
this.isDuplicateEvent(K) || this.addToQueue(K);
|
|
1140
1152
|
}
|
|
1141
1153
|
}
|
|
1142
1154
|
stop() {
|
|
1143
1155
|
this.sendIntervalId && (clearInterval(this.sendIntervalId), this.sendIntervalId = null), this.eventsQueue = [], this.lastEventFingerprint = null, this.lastEventTime = 0, this.dataSender.stop();
|
|
1144
1156
|
}
|
|
1145
|
-
/**
|
|
1146
|
-
* Flush all queued events immediately (async)
|
|
1147
|
-
*/
|
|
1148
1157
|
async flushImmediately() {
|
|
1149
1158
|
return this.flushEvents(!1);
|
|
1150
1159
|
}
|
|
1151
|
-
/**
|
|
1152
|
-
* Flush all queued events immediately (sync)
|
|
1153
|
-
*/
|
|
1154
1160
|
flushImmediatelySync() {
|
|
1155
1161
|
return this.flushEvents(!0);
|
|
1156
1162
|
}
|
|
1157
|
-
/**
|
|
1158
|
-
* Queue management and sending intervals
|
|
1159
|
-
*/
|
|
1160
1163
|
getQueueLength() {
|
|
1161
1164
|
return this.eventsQueue.length;
|
|
1162
1165
|
}
|
|
1163
1166
|
clearSendInterval() {
|
|
1164
1167
|
this.sendIntervalId && (clearInterval(this.sendIntervalId), this.sendIntervalId = null);
|
|
1165
1168
|
}
|
|
1166
|
-
/**
|
|
1167
|
-
* Shared flush implementation for both sync and async modes
|
|
1168
|
-
*/
|
|
1169
1169
|
flushEvents(e) {
|
|
1170
1170
|
if (this.eventsQueue.length === 0)
|
|
1171
1171
|
return e ? !0 : Promise.resolve(!0);
|
|
1172
1172
|
const t = this.buildEventsPayload(), n = [...this.eventsQueue], s = n.map((i) => `${i.timestamp}_${i.type}`);
|
|
1173
1173
|
if (e) {
|
|
1174
1174
|
const i = this.dataSender.sendEventsQueueSync(t);
|
|
1175
|
-
return i && (this.removeProcessedEvents(s), this.clearSendInterval()), i;
|
|
1175
|
+
return i && (this.removeProcessedEvents(s), this.clearSendInterval(), this.emitEventsQueue(t)), i;
|
|
1176
1176
|
} else
|
|
1177
1177
|
return this.dataSender.sendEventsQueue(t, {
|
|
1178
1178
|
onSuccess: () => {
|
|
@@ -1185,9 +1185,6 @@ class Wt extends f {
|
|
|
1185
1185
|
}
|
|
1186
1186
|
});
|
|
1187
1187
|
}
|
|
1188
|
-
/**
|
|
1189
|
-
* Send queued events to the API
|
|
1190
|
-
*/
|
|
1191
1188
|
async sendEventsQueue() {
|
|
1192
1189
|
if (!this.get("sessionId") || this.eventsQueue.length === 0)
|
|
1193
1190
|
return;
|
|
@@ -1203,10 +1200,6 @@ class Wt extends f {
|
|
|
1203
1200
|
}
|
|
1204
1201
|
});
|
|
1205
1202
|
}
|
|
1206
|
-
/**
|
|
1207
|
-
* Build the payload for sending events to the API
|
|
1208
|
-
* Includes basic deduplication and sorting
|
|
1209
|
-
*/
|
|
1210
1203
|
buildEventsPayload() {
|
|
1211
1204
|
const e = /* @__PURE__ */ new Map(), t = [];
|
|
1212
1205
|
for (const s of this.eventsQueue) {
|
|
@@ -1222,9 +1215,6 @@ class Wt extends f {
|
|
|
1222
1215
|
...this.get("config")?.globalMetadata && { global_metadata: this.get("config")?.globalMetadata }
|
|
1223
1216
|
};
|
|
1224
1217
|
}
|
|
1225
|
-
/**
|
|
1226
|
-
* Helper methods for event processing
|
|
1227
|
-
*/
|
|
1228
1218
|
buildEventPayload(e) {
|
|
1229
1219
|
const t = e.type === d.SESSION_START, n = e.page_url ?? this.get("pageUrl"), s = {
|
|
1230
1220
|
type: e.type,
|
|
@@ -1238,18 +1228,17 @@ class Wt extends f {
|
|
|
1238
1228
|
...e.web_vitals && { web_vitals: e.web_vitals },
|
|
1239
1229
|
...e.error_data && { error_data: e.error_data },
|
|
1240
1230
|
...e.session_end_reason && { session_end_reason: e.session_end_reason },
|
|
1241
|
-
...
|
|
1242
|
-
...t && Ce() && { utm: Ce() }
|
|
1231
|
+
...t && Le() && { utm: Le() }
|
|
1243
1232
|
}, i = this.get("config")?.tags;
|
|
1244
1233
|
return i?.length && (s.tags = i), s;
|
|
1245
1234
|
}
|
|
1246
1235
|
isEventExcluded(e) {
|
|
1247
|
-
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;
|
|
1248
1237
|
return n && !o && !(i && s) ? !0 : t?.ipExcluded === !0;
|
|
1249
1238
|
}
|
|
1250
1239
|
isDuplicateEvent(e) {
|
|
1251
1240
|
const t = Date.now(), n = this.createEventFingerprint(e);
|
|
1252
|
-
return this.lastEventFingerprint === n && t - this.lastEventTime <
|
|
1241
|
+
return this.lastEventFingerprint === n && t - this.lastEventTime < Je ? !0 : (this.lastEventFingerprint = n, this.lastEventTime = t, !1);
|
|
1253
1242
|
}
|
|
1254
1243
|
createEventFingerprint(e) {
|
|
1255
1244
|
let t = `${e.type}_${e.page_url}`;
|
|
@@ -1257,18 +1246,21 @@ class Wt extends f {
|
|
|
1257
1246
|
const n = Math.round((e.click_data.x || 0) / 10) * 10, s = Math.round((e.click_data.y || 0) / 10) * 10;
|
|
1258
1247
|
t += `_click_${n}_${s}`;
|
|
1259
1248
|
}
|
|
1260
|
-
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;
|
|
1261
1250
|
}
|
|
1262
1251
|
createEventSignature(e) {
|
|
1263
1252
|
return this.createEventFingerprint(e);
|
|
1264
1253
|
}
|
|
1265
1254
|
addToQueue(e) {
|
|
1266
|
-
if (this.eventsQueue.push(e),
|
|
1267
|
-
const t = this.eventsQueue.
|
|
1268
|
-
|
|
1269
|
-
|
|
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,
|
|
1270
1261
|
currentLength: this.eventsQueue.length,
|
|
1271
|
-
removedEventType:
|
|
1262
|
+
removedEventType: n?.type,
|
|
1263
|
+
wasCritical: n?.type === d.SESSION_START || n?.type === d.SESSION_END
|
|
1272
1264
|
});
|
|
1273
1265
|
}
|
|
1274
1266
|
this.sendIntervalId || this.startSendInterval(), this.handleGoogleAnalyticsIntegration(e);
|
|
@@ -1276,10 +1268,14 @@ class Wt extends f {
|
|
|
1276
1268
|
startSendInterval() {
|
|
1277
1269
|
this.sendIntervalId = window.setInterval(() => {
|
|
1278
1270
|
this.eventsQueue.length > 0 && this.sendEventsQueue();
|
|
1279
|
-
},
|
|
1271
|
+
}, Ze);
|
|
1280
1272
|
}
|
|
1281
1273
|
handleGoogleAnalyticsIntegration(e) {
|
|
1282
|
-
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
|
+
}
|
|
1283
1279
|
}
|
|
1284
1280
|
shouldSample() {
|
|
1285
1281
|
const e = this.get("config")?.samplingRate ?? 1;
|
|
@@ -1292,20 +1288,14 @@ class Wt extends f {
|
|
|
1292
1288
|
return !t.has(s);
|
|
1293
1289
|
});
|
|
1294
1290
|
}
|
|
1295
|
-
/**
|
|
1296
|
-
* Emit event for external listeners
|
|
1297
|
-
*/
|
|
1298
1291
|
emitEvent(e) {
|
|
1299
1292
|
this.emitter && this.emitter.emit(re.EVENT, e);
|
|
1300
1293
|
}
|
|
1301
|
-
/**
|
|
1302
|
-
* Emit events queue for external listeners
|
|
1303
|
-
*/
|
|
1304
1294
|
emitEventsQueue(e) {
|
|
1305
1295
|
this.emitter && this.emitter.emit(re.QUEUE, e);
|
|
1306
1296
|
}
|
|
1307
1297
|
}
|
|
1308
|
-
class
|
|
1298
|
+
class $t {
|
|
1309
1299
|
/**
|
|
1310
1300
|
* Gets or creates a unique user ID for the given project.
|
|
1311
1301
|
* The user ID is persisted in localStorage and reused across sessions.
|
|
@@ -1315,35 +1305,33 @@ class Bt {
|
|
|
1315
1305
|
* @returns Persistent unique user ID
|
|
1316
1306
|
*/
|
|
1317
1307
|
static getId(e, t) {
|
|
1318
|
-
const n =
|
|
1308
|
+
const n = ct(t ?? ""), s = e.getItem(n);
|
|
1319
1309
|
if (s)
|
|
1320
1310
|
return s;
|
|
1321
|
-
const i =
|
|
1311
|
+
const i = Et();
|
|
1322
1312
|
return e.setItem(n, i), i;
|
|
1323
1313
|
}
|
|
1324
1314
|
}
|
|
1325
|
-
class
|
|
1315
|
+
class Qt extends m {
|
|
1326
1316
|
storageManager;
|
|
1327
1317
|
eventManager;
|
|
1318
|
+
projectId;
|
|
1328
1319
|
sessionTimeoutId = null;
|
|
1329
1320
|
broadcastChannel = null;
|
|
1330
1321
|
activityHandler = null;
|
|
1331
1322
|
visibilityChangeHandler = null;
|
|
1332
1323
|
beforeUnloadHandler = null;
|
|
1333
1324
|
isTracking = !1;
|
|
1334
|
-
constructor(e, t) {
|
|
1335
|
-
super(), this.storageManager = e, this.eventManager = t;
|
|
1325
|
+
constructor(e, t, n) {
|
|
1326
|
+
super(), this.storageManager = e, this.eventManager = t, this.projectId = n;
|
|
1336
1327
|
}
|
|
1337
|
-
/**
|
|
1338
|
-
* Initialize cross-tab synchronization
|
|
1339
|
-
*/
|
|
1340
1328
|
initCrossTabSync() {
|
|
1341
1329
|
if (typeof BroadcastChannel > "u") {
|
|
1342
1330
|
a.warn("SessionManager", "BroadcastChannel not supported");
|
|
1343
1331
|
return;
|
|
1344
1332
|
}
|
|
1345
1333
|
const e = this.getProjectId();
|
|
1346
|
-
this.broadcastChannel = new BroadcastChannel(
|
|
1334
|
+
this.broadcastChannel = new BroadcastChannel(ht(e)), this.broadcastChannel.onmessage = (t) => {
|
|
1347
1335
|
const { action: n, sessionId: s, timestamp: i, projectId: o } = t.data ?? {};
|
|
1348
1336
|
if (o === e) {
|
|
1349
1337
|
if (n === "session_end") {
|
|
@@ -1354,11 +1342,8 @@ class Yt extends f {
|
|
|
1354
1342
|
}
|
|
1355
1343
|
};
|
|
1356
1344
|
}
|
|
1357
|
-
/**
|
|
1358
|
-
* Share session with other tabs
|
|
1359
|
-
*/
|
|
1360
1345
|
shareSession(e) {
|
|
1361
|
-
this.broadcastChannel
|
|
1346
|
+
this.broadcastChannel && typeof this.broadcastChannel.postMessage == "function" && this.broadcastChannel.postMessage({
|
|
1362
1347
|
action: "session_start",
|
|
1363
1348
|
projectId: this.getProjectId(),
|
|
1364
1349
|
sessionId: e,
|
|
@@ -1366,7 +1351,7 @@ class Yt extends f {
|
|
|
1366
1351
|
});
|
|
1367
1352
|
}
|
|
1368
1353
|
broadcastSessionEnd(e, t) {
|
|
1369
|
-
e && this.broadcastChannel
|
|
1354
|
+
e && this.broadcastChannel && typeof this.broadcastChannel.postMessage == "function" && this.broadcastChannel.postMessage({
|
|
1370
1355
|
action: "session_end",
|
|
1371
1356
|
projectId: this.getProjectId(),
|
|
1372
1357
|
sessionId: e,
|
|
@@ -1374,25 +1359,16 @@ class Yt extends f {
|
|
|
1374
1359
|
timestamp: Date.now()
|
|
1375
1360
|
});
|
|
1376
1361
|
}
|
|
1377
|
-
/**
|
|
1378
|
-
* Cleanup cross-tab sync
|
|
1379
|
-
*/
|
|
1380
1362
|
cleanupCrossTabSync() {
|
|
1381
|
-
this.broadcastChannel && (this.broadcastChannel.close(), this.broadcastChannel = null);
|
|
1363
|
+
this.broadcastChannel && (typeof this.broadcastChannel.close == "function" && this.broadcastChannel.close(), this.broadcastChannel = null);
|
|
1382
1364
|
}
|
|
1383
|
-
/**
|
|
1384
|
-
* Recover session from localStorage if it exists and hasn't expired
|
|
1385
|
-
*/
|
|
1386
1365
|
recoverSession() {
|
|
1387
1366
|
const e = this.loadStoredSession();
|
|
1388
1367
|
if (!e)
|
|
1389
1368
|
return null;
|
|
1390
|
-
const t = this.get("config")?.sessionTimeout ??
|
|
1369
|
+
const t = this.get("config")?.sessionTimeout ?? P;
|
|
1391
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);
|
|
1392
1371
|
}
|
|
1393
|
-
/**
|
|
1394
|
-
* Persist session data to localStorage
|
|
1395
|
-
*/
|
|
1396
1372
|
persistSession(e, t = Date.now()) {
|
|
1397
1373
|
this.saveStoredSession({
|
|
1398
1374
|
id: e,
|
|
@@ -1419,14 +1395,11 @@ class Yt extends f {
|
|
|
1419
1395
|
this.storageManager.setItem(t, JSON.stringify(e));
|
|
1420
1396
|
}
|
|
1421
1397
|
getSessionStorageKey() {
|
|
1422
|
-
return
|
|
1398
|
+
return dt(this.getProjectId());
|
|
1423
1399
|
}
|
|
1424
1400
|
getProjectId() {
|
|
1425
|
-
return this.
|
|
1401
|
+
return this.projectId;
|
|
1426
1402
|
}
|
|
1427
|
-
/**
|
|
1428
|
-
* Start session tracking
|
|
1429
|
-
*/
|
|
1430
1403
|
async startTracking() {
|
|
1431
1404
|
if (this.isTracking) {
|
|
1432
1405
|
a.warn("SessionManager", "Session tracking already active");
|
|
@@ -1435,59 +1408,37 @@ class Yt extends f {
|
|
|
1435
1408
|
const e = this.recoverSession(), t = e ?? this.generateSessionId(), n = !!e;
|
|
1436
1409
|
this.isTracking = !0;
|
|
1437
1410
|
try {
|
|
1438
|
-
this.set("sessionId", t), this.persistSession(t), this.eventManager.track({
|
|
1439
|
-
type: d.SESSION_START
|
|
1440
|
-
...n && { session_start_recovered: !0 }
|
|
1411
|
+
this.set("sessionId", t), this.persistSession(t), n || this.eventManager.track({
|
|
1412
|
+
type: d.SESSION_START
|
|
1441
1413
|
}), this.initCrossTabSync(), this.shareSession(t), this.setupSessionTimeout(), this.setupActivityListeners(), this.setupLifecycleListeners(), a.info("SessionManager", "Session tracking started", { sessionId: t, recovered: n });
|
|
1442
1414
|
} catch (s) {
|
|
1443
1415
|
throw this.isTracking = !1, this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupLifecycleListeners(), this.cleanupCrossTabSync(), this.set("sessionId", null), s;
|
|
1444
1416
|
}
|
|
1445
1417
|
}
|
|
1446
|
-
/**
|
|
1447
|
-
* Generate unique session ID
|
|
1448
|
-
*/
|
|
1449
1418
|
generateSessionId() {
|
|
1450
1419
|
return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
1451
1420
|
}
|
|
1452
|
-
/**
|
|
1453
|
-
* Setup session timeout
|
|
1454
|
-
*/
|
|
1455
1421
|
setupSessionTimeout() {
|
|
1456
1422
|
this.clearSessionTimeout();
|
|
1457
|
-
const e = this.get("config")?.sessionTimeout ??
|
|
1423
|
+
const e = this.get("config")?.sessionTimeout ?? P;
|
|
1458
1424
|
this.sessionTimeoutId = setTimeout(() => {
|
|
1459
1425
|
this.endSession("inactivity");
|
|
1460
1426
|
}, e);
|
|
1461
1427
|
}
|
|
1462
|
-
/**
|
|
1463
|
-
* Reset session timeout and update activity
|
|
1464
|
-
*/
|
|
1465
1428
|
resetSessionTimeout() {
|
|
1466
1429
|
this.setupSessionTimeout();
|
|
1467
1430
|
const e = this.get("sessionId");
|
|
1468
1431
|
e && this.persistSession(e);
|
|
1469
1432
|
}
|
|
1470
|
-
/**
|
|
1471
|
-
* Clear session timeout
|
|
1472
|
-
*/
|
|
1473
1433
|
clearSessionTimeout() {
|
|
1474
1434
|
this.sessionTimeoutId && (clearTimeout(this.sessionTimeoutId), this.sessionTimeoutId = null);
|
|
1475
1435
|
}
|
|
1476
|
-
/**
|
|
1477
|
-
* Setup activity listeners to track user engagement
|
|
1478
|
-
*/
|
|
1479
1436
|
setupActivityListeners() {
|
|
1480
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 });
|
|
1481
1438
|
}
|
|
1482
|
-
/**
|
|
1483
|
-
* Clean up activity listeners
|
|
1484
|
-
*/
|
|
1485
1439
|
cleanupActivityListeners() {
|
|
1486
1440
|
this.activityHandler && (document.removeEventListener("click", this.activityHandler), document.removeEventListener("keydown", this.activityHandler), document.removeEventListener("scroll", this.activityHandler), this.activityHandler = null);
|
|
1487
1441
|
}
|
|
1488
|
-
/**
|
|
1489
|
-
* Setup page lifecycle listeners (visibility and unload)
|
|
1490
|
-
*/
|
|
1491
1442
|
setupLifecycleListeners() {
|
|
1492
1443
|
this.visibilityChangeHandler || this.beforeUnloadHandler || (this.visibilityChangeHandler = () => {
|
|
1493
1444
|
document.hidden ? this.clearSessionTimeout() : this.get("sessionId") && this.setupSessionTimeout();
|
|
@@ -1498,13 +1449,10 @@ class Yt extends f {
|
|
|
1498
1449
|
cleanupLifecycleListeners() {
|
|
1499
1450
|
this.visibilityChangeHandler && (document.removeEventListener("visibilitychange", this.visibilityChangeHandler), this.visibilityChangeHandler = null), this.beforeUnloadHandler && (window.removeEventListener("beforeunload", this.beforeUnloadHandler), this.beforeUnloadHandler = null);
|
|
1500
1451
|
}
|
|
1501
|
-
|
|
1502
|
-
* End current session
|
|
1503
|
-
*/
|
|
1504
|
-
endSession(e) {
|
|
1452
|
+
async endSession(e) {
|
|
1505
1453
|
const t = this.get("sessionId");
|
|
1506
1454
|
if (!t) {
|
|
1507
|
-
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);
|
|
1508
1456
|
return;
|
|
1509
1457
|
}
|
|
1510
1458
|
a.info("SessionManager", "Ending session", { sessionId: t, reason: e }), this.eventManager.track({
|
|
@@ -1512,35 +1460,31 @@ class Yt extends f {
|
|
|
1512
1460
|
session_end_reason: e
|
|
1513
1461
|
});
|
|
1514
1462
|
const n = () => {
|
|
1515
|
-
this.broadcastSessionEnd(t, e), this.resetSessionState();
|
|
1463
|
+
this.broadcastSessionEnd(t, e), this.resetSessionState(e);
|
|
1516
1464
|
};
|
|
1517
1465
|
if (this.eventManager.flushImmediatelySync()) {
|
|
1518
1466
|
n();
|
|
1519
1467
|
return;
|
|
1520
1468
|
}
|
|
1521
|
-
|
|
1469
|
+
try {
|
|
1470
|
+
await this.eventManager.flushImmediately(), n();
|
|
1471
|
+
} catch (i) {
|
|
1522
1472
|
a.warn("SessionManager", "Async flush failed during session end", {
|
|
1523
1473
|
error: i instanceof Error ? i.message : "Unknown error"
|
|
1524
1474
|
}), n();
|
|
1525
|
-
}
|
|
1475
|
+
}
|
|
1526
1476
|
}
|
|
1527
|
-
resetSessionState() {
|
|
1528
|
-
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;
|
|
1529
1479
|
}
|
|
1530
|
-
/**
|
|
1531
|
-
* Stop session tracking
|
|
1532
|
-
*/
|
|
1533
1480
|
async stopTracking() {
|
|
1534
|
-
this.endSession("manual_stop");
|
|
1481
|
+
await this.endSession("manual_stop");
|
|
1535
1482
|
}
|
|
1536
|
-
/**
|
|
1537
|
-
* Clean up all resources
|
|
1538
|
-
*/
|
|
1539
1483
|
destroy() {
|
|
1540
1484
|
this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupCrossTabSync(), this.cleanupLifecycleListeners(), this.isTracking = !1, this.set("hasStartSession", !1);
|
|
1541
1485
|
}
|
|
1542
1486
|
}
|
|
1543
|
-
class
|
|
1487
|
+
class Bt extends m {
|
|
1544
1488
|
eventManager;
|
|
1545
1489
|
storageManager;
|
|
1546
1490
|
sessionManager = null;
|
|
@@ -1549,25 +1493,28 @@ class Kt extends f {
|
|
|
1549
1493
|
super(), this.eventManager = t, this.storageManager = e;
|
|
1550
1494
|
}
|
|
1551
1495
|
async startTracking() {
|
|
1552
|
-
if (
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
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 {
|
|
1566
1512
|
}
|
|
1567
|
-
|
|
1568
|
-
error: e instanceof Error ? e.message : "Unknown error"
|
|
1569
|
-
}), e;
|
|
1513
|
+
this.sessionManager = null;
|
|
1570
1514
|
}
|
|
1515
|
+
throw a.error("SessionHandler", "Failed to start session tracking", {
|
|
1516
|
+
error: t instanceof Error ? t.message : "Unknown error"
|
|
1517
|
+
}), t;
|
|
1571
1518
|
}
|
|
1572
1519
|
}
|
|
1573
1520
|
isActive() {
|
|
@@ -1583,7 +1530,7 @@ class Kt extends f {
|
|
|
1583
1530
|
this.destroyed || (this.sessionManager && (this.sessionManager.destroy(), this.sessionManager = null), this.destroyed = !0, this.set("hasStartSession", !1));
|
|
1584
1531
|
}
|
|
1585
1532
|
}
|
|
1586
|
-
class
|
|
1533
|
+
class Wt extends m {
|
|
1587
1534
|
eventManager;
|
|
1588
1535
|
onTrack;
|
|
1589
1536
|
originalPushState;
|
|
@@ -1637,7 +1584,7 @@ class Xt extends f {
|
|
|
1637
1584
|
};
|
|
1638
1585
|
}
|
|
1639
1586
|
}
|
|
1640
|
-
class
|
|
1587
|
+
class Yt extends m {
|
|
1641
1588
|
eventManager;
|
|
1642
1589
|
clickHandler;
|
|
1643
1590
|
constructor(e) {
|
|
@@ -1675,10 +1622,10 @@ class qt extends f {
|
|
|
1675
1622
|
this.clickHandler && (window.removeEventListener("click", this.clickHandler, !0), this.clickHandler = void 0);
|
|
1676
1623
|
}
|
|
1677
1624
|
findTrackingElement(e) {
|
|
1678
|
-
return e.hasAttribute(`${
|
|
1625
|
+
return e.hasAttribute(`${F}-name`) ? e : e.closest(`[${F}-name]`) || void 0;
|
|
1679
1626
|
}
|
|
1680
1627
|
getRelevantClickElement(e) {
|
|
1681
|
-
for (const t of
|
|
1628
|
+
for (const t of it)
|
|
1682
1629
|
try {
|
|
1683
1630
|
if (e.matches(t))
|
|
1684
1631
|
return e;
|
|
@@ -1702,7 +1649,7 @@ class qt extends f {
|
|
|
1702
1649
|
return { x: s, y: i, relativeX: o, relativeY: c };
|
|
1703
1650
|
}
|
|
1704
1651
|
extractTrackingData(e) {
|
|
1705
|
-
const t = e.getAttribute(`${
|
|
1652
|
+
const t = e.getAttribute(`${F}-name`), n = e.getAttribute(`${F}-value`);
|
|
1706
1653
|
if (t)
|
|
1707
1654
|
return {
|
|
1708
1655
|
element: e,
|
|
@@ -1731,7 +1678,7 @@ class qt extends f {
|
|
|
1731
1678
|
}
|
|
1732
1679
|
getRelevantText(e, t) {
|
|
1733
1680
|
const n = e.textContent?.trim() ?? "", s = t.textContent?.trim() ?? "";
|
|
1734
|
-
return !n && !s ? "" : n && n.length <=
|
|
1681
|
+
return !n && !s ? "" : n && n.length <= X ? n : s.length <= X ? s : s.slice(0, X - 3) + "...";
|
|
1735
1682
|
}
|
|
1736
1683
|
extractElementAttributes(e) {
|
|
1737
1684
|
const t = [
|
|
@@ -1759,13 +1706,13 @@ class qt extends f {
|
|
|
1759
1706
|
};
|
|
1760
1707
|
}
|
|
1761
1708
|
}
|
|
1762
|
-
class
|
|
1709
|
+
class Kt extends m {
|
|
1763
1710
|
eventManager;
|
|
1764
1711
|
containers = [];
|
|
1765
1712
|
limitWarningLogged = !1;
|
|
1766
|
-
minDepthChange =
|
|
1767
|
-
minIntervalMs =
|
|
1768
|
-
maxEventsPerSession =
|
|
1713
|
+
minDepthChange = Ee;
|
|
1714
|
+
minIntervalMs = ve;
|
|
1715
|
+
maxEventsPerSession = ye;
|
|
1769
1716
|
constructor(e) {
|
|
1770
1717
|
super(), this.eventManager = e;
|
|
1771
1718
|
}
|
|
@@ -1803,7 +1750,7 @@ class Jt extends f {
|
|
|
1803
1750
|
this.processScrollEvent(s, i, o);
|
|
1804
1751
|
}
|
|
1805
1752
|
s.debounceTimer = null;
|
|
1806
|
-
},
|
|
1753
|
+
}, xe));
|
|
1807
1754
|
}, n = this.getScrollTop(e), s = {
|
|
1808
1755
|
element: e,
|
|
1809
1756
|
lastScrollPos: n,
|
|
@@ -1812,7 +1759,7 @@ class Jt extends f {
|
|
|
1812
1759
|
this.getScrollHeight(e),
|
|
1813
1760
|
this.getViewportHeight(e)
|
|
1814
1761
|
),
|
|
1815
|
-
lastDirection:
|
|
1762
|
+
lastDirection: j.DOWN,
|
|
1816
1763
|
lastEventTime: 0,
|
|
1817
1764
|
debounceTimer: null,
|
|
1818
1765
|
listener: t
|
|
@@ -1847,7 +1794,7 @@ class Jt extends f {
|
|
|
1847
1794
|
}));
|
|
1848
1795
|
}
|
|
1849
1796
|
applyConfigOverrides() {
|
|
1850
|
-
this.minDepthChange =
|
|
1797
|
+
this.minDepthChange = Ee, this.minIntervalMs = ve, this.maxEventsPerSession = ye;
|
|
1851
1798
|
}
|
|
1852
1799
|
isWindowScrollable() {
|
|
1853
1800
|
return document.documentElement.scrollHeight > window.innerHeight;
|
|
@@ -1856,7 +1803,7 @@ class Jt extends f {
|
|
|
1856
1803
|
e.debounceTimer !== null && (clearTimeout(e.debounceTimer), e.debounceTimer = null);
|
|
1857
1804
|
}
|
|
1858
1805
|
getScrollDirection(e, t) {
|
|
1859
|
-
return e > t ?
|
|
1806
|
+
return e > t ? j.DOWN : j.UP;
|
|
1860
1807
|
}
|
|
1861
1808
|
calculateScrollDepth(e, t, n) {
|
|
1862
1809
|
if (t <= n)
|
|
@@ -1866,7 +1813,7 @@ class Jt extends f {
|
|
|
1866
1813
|
}
|
|
1867
1814
|
calculateScrollData(e) {
|
|
1868
1815
|
const { element: t, lastScrollPos: n } = e, s = this.getScrollTop(t);
|
|
1869
|
-
if (Math.abs(s - n) <
|
|
1816
|
+
if (Math.abs(s - n) < rt || t === window && !this.isWindowScrollable())
|
|
1870
1817
|
return null;
|
|
1871
1818
|
const o = this.getViewportHeight(t), c = this.getScrollHeight(t), l = this.getScrollDirection(s, n), u = this.calculateScrollDepth(s, c, o);
|
|
1872
1819
|
return e.lastScrollPos = s, { depth: u, direction: l };
|
|
@@ -1895,7 +1842,7 @@ class Jt extends f {
|
|
|
1895
1842
|
}
|
|
1896
1843
|
}
|
|
1897
1844
|
}
|
|
1898
|
-
class
|
|
1845
|
+
class Xt extends m {
|
|
1899
1846
|
isInitialized = !1;
|
|
1900
1847
|
async initialize() {
|
|
1901
1848
|
if (this.isInitialized)
|
|
@@ -1917,7 +1864,8 @@ class Zt extends f {
|
|
|
1917
1864
|
trackEvent(e, t) {
|
|
1918
1865
|
if (!(!e?.trim() || !this.isInitialized || typeof window.gtag != "function"))
|
|
1919
1866
|
try {
|
|
1920
|
-
|
|
1867
|
+
const n = Array.isArray(t) ? { items: t } : t;
|
|
1868
|
+
window.gtag("event", e, n);
|
|
1921
1869
|
} catch (n) {
|
|
1922
1870
|
a.error("GoogleAnalyticsIntegration", "Event tracking failed", {
|
|
1923
1871
|
error: n instanceof Error ? n.message : "Unknown error"
|
|
@@ -1950,9 +1898,10 @@ class Zt extends f {
|
|
|
1950
1898
|
`, document.head.appendChild(n);
|
|
1951
1899
|
}
|
|
1952
1900
|
}
|
|
1953
|
-
class
|
|
1901
|
+
class qt {
|
|
1954
1902
|
storage;
|
|
1955
1903
|
fallbackStorage = /* @__PURE__ */ new Map();
|
|
1904
|
+
hasQuotaExceededError = !1;
|
|
1956
1905
|
constructor() {
|
|
1957
1906
|
this.storage = this.initializeStorage(), this.storage || a.warn("StorageManager", "localStorage not available, using memory fallback");
|
|
1958
1907
|
}
|
|
@@ -1976,7 +1925,10 @@ class er {
|
|
|
1976
1925
|
return;
|
|
1977
1926
|
}
|
|
1978
1927
|
} catch (n) {
|
|
1979
|
-
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 });
|
|
1980
1932
|
}
|
|
1981
1933
|
this.fallbackStorage.set(e, t);
|
|
1982
1934
|
}
|
|
@@ -2016,6 +1968,13 @@ class er {
|
|
|
2016
1968
|
isAvailable() {
|
|
2017
1969
|
return this.storage !== null;
|
|
2018
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
|
+
}
|
|
2019
1978
|
/**
|
|
2020
1979
|
* Initialize localStorage with feature detection
|
|
2021
1980
|
*/
|
|
@@ -2030,12 +1989,12 @@ class er {
|
|
|
2030
1989
|
}
|
|
2031
1990
|
}
|
|
2032
1991
|
}
|
|
2033
|
-
class
|
|
1992
|
+
class Jt extends m {
|
|
2034
1993
|
eventManager;
|
|
2035
1994
|
reportedByNav = /* @__PURE__ */ new Map();
|
|
2036
1995
|
observers = [];
|
|
2037
1996
|
lastLongTaskSentAt = 0;
|
|
2038
|
-
vitalThresholds =
|
|
1997
|
+
vitalThresholds = Ve;
|
|
2039
1998
|
constructor(e) {
|
|
2040
1999
|
super(), this.eventManager = e;
|
|
2041
2000
|
}
|
|
@@ -2059,7 +2018,7 @@ class tr extends f {
|
|
|
2059
2018
|
"largest-contentful-paint",
|
|
2060
2019
|
(n) => {
|
|
2061
2020
|
const s = n.getEntries(), i = s[s.length - 1];
|
|
2062
|
-
i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(
|
|
2021
|
+
i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(w)) });
|
|
2063
2022
|
},
|
|
2064
2023
|
{ type: "largest-contentful-paint", buffered: !0 },
|
|
2065
2024
|
!0
|
|
@@ -2077,14 +2036,14 @@ class tr extends f {
|
|
|
2077
2036
|
const c = typeof o.value == "number" ? o.value : 0;
|
|
2078
2037
|
e += c;
|
|
2079
2038
|
}
|
|
2080
|
-
this.sendVital({ type: "CLS", value: Number(e.toFixed(
|
|
2039
|
+
this.sendVital({ type: "CLS", value: Number(e.toFixed(w)) });
|
|
2081
2040
|
},
|
|
2082
2041
|
{ type: "layout-shift", buffered: !0 }
|
|
2083
2042
|
), this.safeObserve(
|
|
2084
2043
|
"paint",
|
|
2085
2044
|
(n) => {
|
|
2086
2045
|
for (const s of n.getEntries())
|
|
2087
|
-
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)) });
|
|
2088
2047
|
},
|
|
2089
2048
|
{ type: "paint", buffered: !0 },
|
|
2090
2049
|
!0
|
|
@@ -2097,15 +2056,15 @@ class tr extends f {
|
|
|
2097
2056
|
const c = (o.processingEnd ?? 0) - (o.startTime ?? 0);
|
|
2098
2057
|
s = Math.max(s, c);
|
|
2099
2058
|
}
|
|
2100
|
-
s > 0 && this.sendVital({ type: "INP", value: Number(s.toFixed(
|
|
2059
|
+
s > 0 && this.sendVital({ type: "INP", value: Number(s.toFixed(w)) });
|
|
2101
2060
|
},
|
|
2102
2061
|
{ type: "event", buffered: !0 }
|
|
2103
2062
|
);
|
|
2104
2063
|
}
|
|
2105
2064
|
async initWebVitals() {
|
|
2106
2065
|
try {
|
|
2107
|
-
const { onLCP: e, onCLS: t, onFCP: n, onTTFB: s, onINP: i } = await Promise.resolve().then(() =>
|
|
2108
|
-
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));
|
|
2109
2068
|
this.sendVital({ type: c, value: u });
|
|
2110
2069
|
};
|
|
2111
2070
|
e(o("LCP")), t(o("CLS")), n(o("FCP")), s(o("TTFB")), i(o("INP"));
|
|
@@ -2121,7 +2080,7 @@ class tr extends f {
|
|
|
2121
2080
|
if (!e)
|
|
2122
2081
|
return;
|
|
2123
2082
|
const t = e.responseStart;
|
|
2124
|
-
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)) });
|
|
2125
2084
|
} catch (e) {
|
|
2126
2085
|
a.warn("PerformanceHandler", "Failed to report TTFB", {
|
|
2127
2086
|
error: e instanceof Error ? e.message : "Unknown error"
|
|
@@ -2134,8 +2093,8 @@ class tr extends f {
|
|
|
2134
2093
|
(e) => {
|
|
2135
2094
|
const t = e.getEntries();
|
|
2136
2095
|
for (const n of t) {
|
|
2137
|
-
const s = Number(n.duration.toFixed(
|
|
2138
|
-
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);
|
|
2139
2098
|
}
|
|
2140
2099
|
},
|
|
2141
2100
|
{ type: "longtask", buffered: !0 }
|
|
@@ -2222,7 +2181,7 @@ class tr extends f {
|
|
|
2222
2181
|
}), !1) : !0;
|
|
2223
2182
|
}
|
|
2224
2183
|
}
|
|
2225
|
-
class
|
|
2184
|
+
class Zt extends m {
|
|
2226
2185
|
eventManager;
|
|
2227
2186
|
recentErrors = /* @__PURE__ */ new Map();
|
|
2228
2187
|
constructor(e) {
|
|
@@ -2242,14 +2201,14 @@ class rr extends f {
|
|
|
2242
2201
|
if (!this.shouldSample())
|
|
2243
2202
|
return;
|
|
2244
2203
|
const t = this.sanitize(e.message || "Unknown error");
|
|
2245
|
-
this.shouldSuppressError(
|
|
2204
|
+
this.shouldSuppressError(C.JS_ERROR, t) || (a.warn("ErrorHandler", "JS error captured", {
|
|
2246
2205
|
message: t,
|
|
2247
2206
|
filename: e.filename,
|
|
2248
2207
|
line: e.lineno
|
|
2249
2208
|
}), this.eventManager.track({
|
|
2250
2209
|
type: d.ERROR,
|
|
2251
2210
|
error_data: {
|
|
2252
|
-
type:
|
|
2211
|
+
type: C.JS_ERROR,
|
|
2253
2212
|
message: t,
|
|
2254
2213
|
...e.filename && { filename: e.filename },
|
|
2255
2214
|
...e.lineno && { line: e.lineno },
|
|
@@ -2261,10 +2220,10 @@ class rr extends f {
|
|
|
2261
2220
|
if (!this.shouldSample())
|
|
2262
2221
|
return;
|
|
2263
2222
|
const t = this.extractRejectionMessage(e.reason), n = this.sanitize(t);
|
|
2264
|
-
this.shouldSuppressError(
|
|
2223
|
+
this.shouldSuppressError(C.PROMISE_REJECTION, n) || (a.warn("ErrorHandler", "Promise rejection captured", { message: n }), this.eventManager.track({
|
|
2265
2224
|
type: d.ERROR,
|
|
2266
2225
|
error_data: {
|
|
2267
|
-
type:
|
|
2226
|
+
type: C.PROMISE_REJECTION,
|
|
2268
2227
|
message: n
|
|
2269
2228
|
}
|
|
2270
2229
|
}));
|
|
@@ -2283,8 +2242,8 @@ class rr extends f {
|
|
|
2283
2242
|
}
|
|
2284
2243
|
}
|
|
2285
2244
|
sanitize(e) {
|
|
2286
|
-
let t = e.length >
|
|
2287
|
-
for (const n of
|
|
2245
|
+
let t = e.length > be ? e.slice(0, be) + "..." : e;
|
|
2246
|
+
for (const n of Fe) {
|
|
2288
2247
|
const s = new RegExp(n.source, n.flags);
|
|
2289
2248
|
t = t.replace(s, "[REDACTED]");
|
|
2290
2249
|
}
|
|
@@ -2292,25 +2251,28 @@ class rr extends f {
|
|
|
2292
2251
|
}
|
|
2293
2252
|
shouldSuppressError(e, t) {
|
|
2294
2253
|
const n = Date.now(), s = `${e}:${t}`, i = this.recentErrors.get(s);
|
|
2295
|
-
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));
|
|
2296
2258
|
}
|
|
2297
2259
|
pruneOldErrors() {
|
|
2298
2260
|
const e = Date.now();
|
|
2299
2261
|
for (const [s, i] of this.recentErrors.entries())
|
|
2300
|
-
e - i >
|
|
2301
|
-
if (this.recentErrors.size <=
|
|
2262
|
+
e - i > Me && this.recentErrors.delete(s);
|
|
2263
|
+
if (this.recentErrors.size <= G)
|
|
2302
2264
|
return;
|
|
2303
|
-
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;
|
|
2304
2266
|
for (let s = 0; s < n; s += 1) {
|
|
2305
2267
|
const i = t[s];
|
|
2306
2268
|
i && this.recentErrors.delete(i[0]);
|
|
2307
2269
|
}
|
|
2308
2270
|
}
|
|
2309
2271
|
}
|
|
2310
|
-
class
|
|
2272
|
+
class er extends m {
|
|
2311
2273
|
isInitialized = !1;
|
|
2312
2274
|
suppressNextScrollTimer = null;
|
|
2313
|
-
emitter = new
|
|
2275
|
+
emitter = new Vt();
|
|
2314
2276
|
managers = {};
|
|
2315
2277
|
handlers = {};
|
|
2316
2278
|
integrations = {};
|
|
@@ -2321,9 +2283,9 @@ class nr extends f {
|
|
|
2321
2283
|
if (!this.isInitialized) {
|
|
2322
2284
|
if (!e.id?.trim())
|
|
2323
2285
|
throw new Error("Project ID is required");
|
|
2324
|
-
this.managers.storage = new
|
|
2286
|
+
this.managers.storage = new qt();
|
|
2325
2287
|
try {
|
|
2326
|
-
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(() => {
|
|
2327
2289
|
a.warn("App", "Failed to recover persisted events");
|
|
2328
2290
|
}), this.isInitialized = !0;
|
|
2329
2291
|
} catch (t) {
|
|
@@ -2334,7 +2296,7 @@ class nr extends f {
|
|
|
2334
2296
|
sendCustomEvent(e, t) {
|
|
2335
2297
|
if (!this.managers.event)
|
|
2336
2298
|
return;
|
|
2337
|
-
const { valid: n, error: s, sanitizedMetadata: i } =
|
|
2299
|
+
const { valid: n, error: s, sanitizedMetadata: i } = kt(e, t);
|
|
2338
2300
|
if (!n) {
|
|
2339
2301
|
const o = this.get("config");
|
|
2340
2302
|
if (o?.mode === "qa" || o?.mode === "debug")
|
|
@@ -2366,29 +2328,29 @@ class nr extends f {
|
|
|
2366
2328
|
a.warn("App", "Failed to stop tracking");
|
|
2367
2329
|
}
|
|
2368
2330
|
});
|
|
2369
|
-
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 = {};
|
|
2370
2332
|
}
|
|
2371
2333
|
async setupState(e) {
|
|
2372
|
-
const t =
|
|
2334
|
+
const t = Ft(e.id, e.allowHttp);
|
|
2373
2335
|
this.set("apiUrl", t);
|
|
2374
|
-
const s = await new
|
|
2375
|
-
this.set("config",
|
|
2376
|
-
const
|
|
2377
|
-
this.set("userId",
|
|
2378
|
-
const
|
|
2379
|
-
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);
|
|
2380
2342
|
}
|
|
2381
2343
|
async setupIntegrations() {
|
|
2382
2344
|
const e = this.get("config"), t = e.integrations?.googleAnalytics?.measurementId;
|
|
2383
2345
|
if (!e.ipExcluded && t?.trim())
|
|
2384
2346
|
try {
|
|
2385
|
-
this.integrations.googleAnalytics = new
|
|
2347
|
+
this.integrations.googleAnalytics = new Xt(), await this.integrations.googleAnalytics.initialize();
|
|
2386
2348
|
} catch {
|
|
2387
2349
|
this.integrations.googleAnalytics = void 0;
|
|
2388
2350
|
}
|
|
2389
2351
|
}
|
|
2390
2352
|
initializeHandlers() {
|
|
2391
|
-
this.handlers.session = new
|
|
2353
|
+
this.handlers.session = new Bt(
|
|
2392
2354
|
this.managers.storage,
|
|
2393
2355
|
this.managers.event
|
|
2394
2356
|
), this.handlers.session.startTracking().catch((t) => {
|
|
@@ -2399,15 +2361,15 @@ class nr extends f {
|
|
|
2399
2361
|
const e = () => {
|
|
2400
2362
|
this.set("suppressNextScroll", !0), this.suppressNextScrollTimer && clearTimeout(this.suppressNextScrollTimer), this.suppressNextScrollTimer = window.setTimeout(() => {
|
|
2401
2363
|
this.set("suppressNextScroll", !1);
|
|
2402
|
-
},
|
|
2364
|
+
}, xe * ot);
|
|
2403
2365
|
};
|
|
2404
|
-
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(() => {
|
|
2405
2367
|
a.warn("App", "Failed to start performance tracking");
|
|
2406
|
-
}), this.handlers.error = new
|
|
2368
|
+
}), this.handlers.error = new Zt(this.managers.event), this.handlers.error.startTracking();
|
|
2407
2369
|
}
|
|
2408
2370
|
}
|
|
2409
|
-
let g = null,
|
|
2410
|
-
const
|
|
2371
|
+
let g = null, D = !1, J = !1;
|
|
2372
|
+
const tr = async (r) => {
|
|
2411
2373
|
if (typeof window > "u" || typeof document > "u")
|
|
2412
2374
|
throw new Error("This library can only be used in a browser environment");
|
|
2413
2375
|
if (!window.__traceLogDisabled) {
|
|
@@ -2415,12 +2377,12 @@ const sr = async (r) => {
|
|
|
2415
2377
|
a.debug("API", "Library already initialized, skipping duplicate initialization");
|
|
2416
2378
|
return;
|
|
2417
2379
|
}
|
|
2418
|
-
if (
|
|
2380
|
+
if (D)
|
|
2419
2381
|
throw a.warn("API", "Initialization already in progress"), new Error("Initialization already in progress");
|
|
2420
|
-
|
|
2382
|
+
D = !0;
|
|
2421
2383
|
try {
|
|
2422
2384
|
a.info("API", "Initializing TraceLog", { projectId: r.id });
|
|
2423
|
-
const e =
|
|
2385
|
+
const e = Rt(r), t = new er();
|
|
2424
2386
|
try {
|
|
2425
2387
|
await t.init(e), g = t, a.info("API", "TraceLog initialized successfully", { projectId: e.id });
|
|
2426
2388
|
} catch (n) {
|
|
@@ -2434,10 +2396,10 @@ const sr = async (r) => {
|
|
|
2434
2396
|
} catch (e) {
|
|
2435
2397
|
throw g = null, a.error("API", "Initialization failed", { error: e }), e;
|
|
2436
2398
|
} finally {
|
|
2437
|
-
|
|
2399
|
+
D = !1;
|
|
2438
2400
|
}
|
|
2439
2401
|
}
|
|
2440
|
-
},
|
|
2402
|
+
}, rr = (r, e) => {
|
|
2441
2403
|
if (!g)
|
|
2442
2404
|
throw new Error("TraceLog not initialized. Please call init() first.");
|
|
2443
2405
|
try {
|
|
@@ -2445,34 +2407,34 @@ const sr = async (r) => {
|
|
|
2445
2407
|
} catch (t) {
|
|
2446
2408
|
throw a.error("API", "Failed to send custom event", { eventName: r, error: t }), t;
|
|
2447
2409
|
}
|
|
2448
|
-
},
|
|
2410
|
+
}, nr = (r, e) => {
|
|
2449
2411
|
if (!g)
|
|
2450
2412
|
throw new Error("TraceLog not initialized. Please call init() first.");
|
|
2451
2413
|
g.on(r, e);
|
|
2452
|
-
},
|
|
2414
|
+
}, sr = (r, e) => {
|
|
2453
2415
|
if (!g)
|
|
2454
2416
|
throw new Error("TraceLog not initialized. Please call init() first.");
|
|
2455
2417
|
g.off(r, e);
|
|
2456
|
-
},
|
|
2418
|
+
}, ir = () => g !== null, ar = async () => {
|
|
2457
2419
|
if (!g)
|
|
2458
2420
|
throw new Error("App not initialized");
|
|
2459
|
-
if (
|
|
2421
|
+
if (J)
|
|
2460
2422
|
throw new Error("Destroy operation already in progress");
|
|
2461
|
-
|
|
2423
|
+
J = !0;
|
|
2462
2424
|
try {
|
|
2463
|
-
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");
|
|
2464
2426
|
} catch (r) {
|
|
2465
|
-
throw g = null,
|
|
2427
|
+
throw g = null, D = !1, a.error("API", "Error during destroy, forced cleanup", { error: r }), r;
|
|
2466
2428
|
} finally {
|
|
2467
|
-
|
|
2429
|
+
J = !1;
|
|
2468
2430
|
}
|
|
2469
|
-
},
|
|
2470
|
-
WEB_VITALS_THRESHOLDS:
|
|
2431
|
+
}, vr = {
|
|
2432
|
+
WEB_VITALS_THRESHOLDS: Ve
|
|
2471
2433
|
// Business thresholds for performance analysis
|
|
2472
|
-
},
|
|
2473
|
-
PII_PATTERNS:
|
|
2434
|
+
}, yr = {
|
|
2435
|
+
PII_PATTERNS: Fe
|
|
2474
2436
|
// Patterns for sensitive data protection
|
|
2475
|
-
},
|
|
2437
|
+
}, Ir = {
|
|
2476
2438
|
LOW_ACTIVITY_EVENT_COUNT: 50,
|
|
2477
2439
|
HIGH_ACTIVITY_EVENT_COUNT: 1e3,
|
|
2478
2440
|
MIN_EVENTS_FOR_DYNAMIC_CALCULATION: 100,
|
|
@@ -2482,7 +2444,7 @@ const sr = async (r) => {
|
|
|
2482
2444
|
MIN_ENGAGED_SESSION_DURATION_MS: 30 * 1e3,
|
|
2483
2445
|
MIN_SCROLL_DEPTH_ENGAGEMENT: 25
|
|
2484
2446
|
// 25% scroll depth for engagement
|
|
2485
|
-
},
|
|
2447
|
+
}, Tr = {
|
|
2486
2448
|
INACTIVITY_TIMEOUT_MS: 30 * 60 * 1e3,
|
|
2487
2449
|
// 30min for analytics (vs 15min client)
|
|
2488
2450
|
SHORT_SESSION_THRESHOLD_MS: 30 * 1e3,
|
|
@@ -2490,20 +2452,20 @@ const sr = async (r) => {
|
|
|
2490
2452
|
LONG_SESSION_THRESHOLD_MS: 30 * 60 * 1e3,
|
|
2491
2453
|
MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1e3
|
|
2492
2454
|
// Filter outliers
|
|
2493
|
-
},
|
|
2455
|
+
}, _r = {
|
|
2494
2456
|
MOBILE_MAX_WIDTH: 768,
|
|
2495
2457
|
TABLET_MAX_WIDTH: 1024,
|
|
2496
2458
|
MOBILE_PERFORMANCE_FACTOR: 1.5,
|
|
2497
2459
|
// Mobile typically 1.5x slower
|
|
2498
2460
|
TABLET_PERFORMANCE_FACTOR: 1.2
|
|
2499
|
-
},
|
|
2461
|
+
}, wr = {
|
|
2500
2462
|
MIN_TEXT_LENGTH_FOR_ANALYSIS: 10,
|
|
2501
2463
|
MIN_CLICKS_FOR_HOT_ELEMENT: 10,
|
|
2502
2464
|
// Popular element threshold
|
|
2503
2465
|
MIN_SCROLL_COMPLETION_PERCENT: 80,
|
|
2504
2466
|
// Page consumption threshold
|
|
2505
2467
|
MIN_TIME_ON_PAGE_FOR_READ_MS: 15 * 1e3
|
|
2506
|
-
},
|
|
2468
|
+
}, Ar = {
|
|
2507
2469
|
SIGNIFICANT_CHANGE_PERCENT: 20,
|
|
2508
2470
|
MAJOR_CHANGE_PERCENT: 50,
|
|
2509
2471
|
MIN_EVENTS_FOR_INSIGHT: 100,
|
|
@@ -2513,19 +2475,19 @@ const sr = async (r) => {
|
|
|
2513
2475
|
LOW_ERROR_RATE_PERCENT: 1,
|
|
2514
2476
|
HIGH_ERROR_RATE_PERCENT: 5,
|
|
2515
2477
|
CRITICAL_ERROR_RATE_PERCENT: 10
|
|
2516
|
-
},
|
|
2478
|
+
}, br = {
|
|
2517
2479
|
SHORT_TERM_TREND_HOURS: 24,
|
|
2518
2480
|
MEDIUM_TERM_TREND_DAYS: 7,
|
|
2519
2481
|
LONG_TERM_TREND_DAYS: 30,
|
|
2520
2482
|
MIN_DATA_POINTS_FOR_TREND: 5,
|
|
2521
2483
|
WEEKLY_PATTERN_MIN_WEEKS: 4,
|
|
2522
2484
|
DAILY_PATTERN_MIN_DAYS: 14
|
|
2523
|
-
},
|
|
2485
|
+
}, Mr = {
|
|
2524
2486
|
MIN_SEGMENT_SIZE: 10,
|
|
2525
2487
|
MIN_COHORT_SIZE: 5,
|
|
2526
2488
|
COHORT_ANALYSIS_DAYS: [1, 3, 7, 14, 30],
|
|
2527
2489
|
MIN_FUNNEL_EVENTS: 20
|
|
2528
|
-
},
|
|
2490
|
+
}, Rr = {
|
|
2529
2491
|
DEFAULT_EVENTS_LIMIT: 5,
|
|
2530
2492
|
DEFAULT_SESSIONS_LIMIT: 5,
|
|
2531
2493
|
DEFAULT_PAGES_LIMIT: 5,
|
|
@@ -2533,38 +2495,38 @@ const sr = async (r) => {
|
|
|
2533
2495
|
MAX_TIME_RANGE_DAYS: 365,
|
|
2534
2496
|
ANALYTICS_BATCH_SIZE: 1e3
|
|
2535
2497
|
// For historical analysis
|
|
2536
|
-
},
|
|
2498
|
+
}, Lr = {
|
|
2537
2499
|
ANOMALY_THRESHOLD_SIGMA: 2.5,
|
|
2538
2500
|
STRONG_ANOMALY_THRESHOLD_SIGMA: 3,
|
|
2539
2501
|
TRAFFIC_DROP_ALERT_PERCENT: -30,
|
|
2540
2502
|
TRAFFIC_SPIKE_ALERT_PERCENT: 200,
|
|
2541
2503
|
MIN_BASELINE_DAYS: 7,
|
|
2542
2504
|
MIN_EVENTS_FOR_ANOMALY_DETECTION: 50
|
|
2543
|
-
},
|
|
2505
|
+
}, Nr = {
|
|
2544
2506
|
PAGE_URL_EXCLUDED: "excluded",
|
|
2545
2507
|
PAGE_URL_UNKNOWN: "unknown"
|
|
2546
|
-
},
|
|
2547
|
-
init:
|
|
2548
|
-
event:
|
|
2549
|
-
on:
|
|
2550
|
-
off:
|
|
2551
|
-
isInitialized:
|
|
2552
|
-
destroy:
|
|
2508
|
+
}, Cr = {
|
|
2509
|
+
init: tr,
|
|
2510
|
+
event: rr,
|
|
2511
|
+
on: nr,
|
|
2512
|
+
off: sr,
|
|
2513
|
+
isInitialized: ir,
|
|
2514
|
+
destroy: ar
|
|
2553
2515
|
};
|
|
2554
|
-
var ae,
|
|
2516
|
+
var ae, Ge = -1, R = function(r) {
|
|
2555
2517
|
addEventListener("pageshow", function(e) {
|
|
2556
|
-
e.persisted && (
|
|
2518
|
+
e.persisted && (Ge = e.timeStamp, r(e));
|
|
2557
2519
|
}, !0);
|
|
2558
|
-
},
|
|
2520
|
+
}, he = function() {
|
|
2559
2521
|
var r = self.performance && performance.getEntriesByType && performance.getEntriesByType("navigation")[0];
|
|
2560
2522
|
if (r && r.responseStart > 0 && r.responseStart < performance.now()) return r;
|
|
2561
|
-
},
|
|
2562
|
-
var r =
|
|
2523
|
+
}, B = function() {
|
|
2524
|
+
var r = he();
|
|
2563
2525
|
return r && r.activationStart || 0;
|
|
2564
|
-
},
|
|
2565
|
-
var t =
|
|
2566
|
-
return
|
|
2567
|
-
},
|
|
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) {
|
|
2568
2530
|
try {
|
|
2569
2531
|
if (PerformanceObserver.supportedEntryTypes.includes(r)) {
|
|
2570
2532
|
var n = new PerformanceObserver(function(s) {
|
|
@@ -2576,200 +2538,200 @@ var ae, je = -1, L = function(r) {
|
|
|
2576
2538
|
}
|
|
2577
2539
|
} catch {
|
|
2578
2540
|
}
|
|
2579
|
-
},
|
|
2541
|
+
}, v = function(r, e, t, n) {
|
|
2580
2542
|
var s, i;
|
|
2581
2543
|
return function(o) {
|
|
2582
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) {
|
|
2583
2545
|
return c > l[1] ? "poor" : c > l[0] ? "needs-improvement" : "good";
|
|
2584
2546
|
}(e.value, t), r(e));
|
|
2585
2547
|
};
|
|
2586
|
-
},
|
|
2548
|
+
}, ge = function(r) {
|
|
2587
2549
|
requestAnimationFrame(function() {
|
|
2588
2550
|
return requestAnimationFrame(function() {
|
|
2589
2551
|
return r();
|
|
2590
2552
|
});
|
|
2591
2553
|
});
|
|
2592
|
-
},
|
|
2554
|
+
}, W = function(r) {
|
|
2593
2555
|
document.addEventListener("visibilitychange", function() {
|
|
2594
2556
|
document.visibilityState === "hidden" && r();
|
|
2595
2557
|
});
|
|
2596
|
-
},
|
|
2558
|
+
}, fe = function(r) {
|
|
2597
2559
|
var e = !1;
|
|
2598
2560
|
return function() {
|
|
2599
2561
|
e || (r(), e = !0);
|
|
2600
2562
|
};
|
|
2601
|
-
},
|
|
2563
|
+
}, b = -1, De = function() {
|
|
2602
2564
|
return document.visibilityState !== "hidden" || document.prerendering ? 1 / 0 : 0;
|
|
2603
|
-
},
|
|
2604
|
-
document.visibilityState === "hidden" &&
|
|
2565
|
+
}, Q = function(r) {
|
|
2566
|
+
document.visibilityState === "hidden" && b > -1 && (b = r.type === "visibilitychange" ? r.timeStamp : 0, or());
|
|
2605
2567
|
}, ke = function() {
|
|
2606
|
-
addEventListener("visibilitychange",
|
|
2607
|
-
},
|
|
2608
|
-
removeEventListener("visibilitychange",
|
|
2609
|
-
},
|
|
2610
|
-
return
|
|
2568
|
+
addEventListener("visibilitychange", Q, !0), addEventListener("prerenderingchange", Q, !0);
|
|
2569
|
+
}, or = function() {
|
|
2570
|
+
removeEventListener("visibilitychange", Q, !0), removeEventListener("prerenderingchange", Q, !0);
|
|
2571
|
+
}, je = function() {
|
|
2572
|
+
return b < 0 && (b = De(), ke(), R(function() {
|
|
2611
2573
|
setTimeout(function() {
|
|
2612
|
-
|
|
2574
|
+
b = De(), ke();
|
|
2613
2575
|
}, 0);
|
|
2614
2576
|
})), { get firstHiddenTime() {
|
|
2615
|
-
return
|
|
2577
|
+
return b;
|
|
2616
2578
|
} };
|
|
2617
|
-
},
|
|
2579
|
+
}, Y = function(r) {
|
|
2618
2580
|
document.prerendering ? addEventListener("prerenderingchange", function() {
|
|
2619
2581
|
return r();
|
|
2620
2582
|
}, !0) : r();
|
|
2621
|
-
}, oe = [1800, 3e3],
|
|
2622
|
-
e = e || {},
|
|
2623
|
-
var t, n =
|
|
2583
|
+
}, oe = [1800, 3e3], $e = function(r, e) {
|
|
2584
|
+
e = e || {}, Y(function() {
|
|
2585
|
+
var t, n = je(), s = E("FCP"), i = V("paint", function(o) {
|
|
2624
2586
|
o.forEach(function(c) {
|
|
2625
|
-
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)));
|
|
2626
2588
|
});
|
|
2627
2589
|
});
|
|
2628
|
-
i && (t =
|
|
2629
|
-
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() {
|
|
2630
2592
|
s.value = performance.now() - o.timeStamp, t(!0);
|
|
2631
2593
|
});
|
|
2632
2594
|
}));
|
|
2633
2595
|
});
|
|
2634
|
-
}, le = [0.1, 0.25],
|
|
2635
|
-
e = e || {},
|
|
2636
|
-
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) {
|
|
2637
2599
|
l.forEach(function(u) {
|
|
2638
2600
|
if (!u.hadRecentInput) {
|
|
2639
|
-
var h = i[0],
|
|
2640
|
-
s && u.startTime -
|
|
2601
|
+
var h = i[0], L = i[i.length - 1];
|
|
2602
|
+
s && u.startTime - L.startTime < 1e3 && u.startTime - h.startTime < 5e3 ? (s += u.value, i.push(u)) : (s = u.value, i = [u]);
|
|
2641
2603
|
}
|
|
2642
2604
|
}), s > n.value && (n.value = s, n.entries = i, t());
|
|
2643
|
-
}, c =
|
|
2644
|
-
c && (t =
|
|
2605
|
+
}, c = V("layout-shift", o);
|
|
2606
|
+
c && (t = v(r, n, le, e.reportAllChanges), W(function() {
|
|
2645
2607
|
o(c.takeRecords()), t(!0);
|
|
2646
|
-
}),
|
|
2647
|
-
s = 0, n =
|
|
2608
|
+
}), R(function() {
|
|
2609
|
+
s = 0, n = E("CLS", 0), t = v(r, n, le, e.reportAllChanges), ge(function() {
|
|
2648
2610
|
return t();
|
|
2649
2611
|
});
|
|
2650
2612
|
}), setTimeout(t, 0));
|
|
2651
2613
|
}));
|
|
2652
|
-
},
|
|
2614
|
+
}, Qe = 0, Z = 1 / 0, z = 0, cr = function(r) {
|
|
2653
2615
|
r.forEach(function(e) {
|
|
2654
|
-
e.interactionId && (
|
|
2616
|
+
e.interactionId && (Z = Math.min(Z, e.interactionId), z = Math.max(z, e.interactionId), Qe = z ? (z - Z) / 7 + 1 : 0);
|
|
2655
2617
|
});
|
|
2656
2618
|
}, Be = function() {
|
|
2657
|
-
return ae ?
|
|
2658
|
-
},
|
|
2659
|
-
"interactionCount" in performance || ae || (ae =
|
|
2660
|
-
},
|
|
2661
|
-
var r = Math.min(
|
|
2662
|
-
return
|
|
2663
|
-
},
|
|
2664
|
-
if (
|
|
2619
|
+
return ae ? Qe : performance.interactionCount || 0;
|
|
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) {
|
|
2665
2627
|
return s(r);
|
|
2666
2628
|
}), r.interactionId || r.entryType === "first-input") {
|
|
2667
|
-
var e =
|
|
2668
|
-
if (t ||
|
|
2629
|
+
var e = S[S.length - 1], t = $.get(r.interactionId);
|
|
2630
|
+
if (t || S.length < 10 || r.duration > e.latency) {
|
|
2669
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);
|
|
2670
2632
|
else {
|
|
2671
2633
|
var n = { id: r.interactionId, latency: r.duration, entries: [r] };
|
|
2672
|
-
|
|
2634
|
+
$.set(n.id, n), S.push(n);
|
|
2673
2635
|
}
|
|
2674
|
-
|
|
2636
|
+
S.sort(function(s, i) {
|
|
2675
2637
|
return i.latency - s.latency;
|
|
2676
|
-
}),
|
|
2677
|
-
return
|
|
2638
|
+
}), S.length > 10 && S.splice(10).forEach(function(s) {
|
|
2639
|
+
return $.delete(s.id);
|
|
2678
2640
|
});
|
|
2679
2641
|
}
|
|
2680
2642
|
}
|
|
2681
|
-
},
|
|
2643
|
+
}, Ye = function(r) {
|
|
2682
2644
|
var e = self.requestIdleCallback || self.setTimeout, t = -1;
|
|
2683
|
-
return r =
|
|
2684
|
-
}, ce = [200, 500],
|
|
2685
|
-
"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() {
|
|
2686
2648
|
var t;
|
|
2687
|
-
|
|
2688
|
-
var n, s =
|
|
2689
|
-
|
|
2690
|
-
c.forEach(
|
|
2691
|
-
var l =
|
|
2649
|
+
ur();
|
|
2650
|
+
var n, s = E("INP"), i = function(c) {
|
|
2651
|
+
Ye(function() {
|
|
2652
|
+
c.forEach(gr);
|
|
2653
|
+
var l = dr();
|
|
2692
2654
|
l && l.latency !== s.value && (s.value = l.latency, s.entries = l.entries, n());
|
|
2693
2655
|
});
|
|
2694
|
-
}, o =
|
|
2695
|
-
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() {
|
|
2696
2658
|
i(o.takeRecords()), n(!0);
|
|
2697
|
-
}),
|
|
2698
|
-
|
|
2659
|
+
}), R(function() {
|
|
2660
|
+
We = Be(), S.length = 0, $.clear(), s = E("INP"), n = v(r, s, ce, e.reportAllChanges);
|
|
2699
2661
|
}));
|
|
2700
2662
|
}));
|
|
2701
|
-
}, ue = [2500, 4e3],
|
|
2702
|
-
e = e || {},
|
|
2703
|
-
var t, n =
|
|
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) {
|
|
2704
2666
|
e.reportAllChanges || (l = l.slice(-1)), l.forEach(function(u) {
|
|
2705
|
-
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());
|
|
2706
2668
|
});
|
|
2707
|
-
}, o =
|
|
2669
|
+
}, o = V("largest-contentful-paint", i);
|
|
2708
2670
|
if (o) {
|
|
2709
|
-
t =
|
|
2710
|
-
var c =
|
|
2711
|
-
|
|
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));
|
|
2712
2674
|
});
|
|
2713
2675
|
["keydown", "click"].forEach(function(l) {
|
|
2714
2676
|
addEventListener(l, function() {
|
|
2715
|
-
return
|
|
2677
|
+
return Ye(c);
|
|
2716
2678
|
}, { once: !0, capture: !0 });
|
|
2717
|
-
}),
|
|
2718
|
-
s =
|
|
2719
|
-
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);
|
|
2720
2682
|
});
|
|
2721
2683
|
});
|
|
2722
2684
|
}
|
|
2723
2685
|
});
|
|
2724
|
-
}, de = [800, 1800],
|
|
2725
|
-
document.prerendering ?
|
|
2686
|
+
}, de = [800, 1800], pr = function r(e) {
|
|
2687
|
+
document.prerendering ? Y(function() {
|
|
2726
2688
|
return r(e);
|
|
2727
2689
|
}) : document.readyState !== "complete" ? addEventListener("load", function() {
|
|
2728
2690
|
return r(e);
|
|
2729
2691
|
}, !0) : setTimeout(e, 0);
|
|
2730
|
-
},
|
|
2692
|
+
}, Sr = function(r, e) {
|
|
2731
2693
|
e = e || {};
|
|
2732
|
-
var t =
|
|
2733
|
-
|
|
2734
|
-
var s =
|
|
2735
|
-
s && (t.value = Math.max(s.responseStart -
|
|
2736
|
-
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);
|
|
2737
2699
|
}));
|
|
2738
2700
|
});
|
|
2739
2701
|
};
|
|
2740
|
-
const
|
|
2702
|
+
const Er = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2741
2703
|
__proto__: null,
|
|
2742
2704
|
CLSThresholds: le,
|
|
2743
2705
|
FCPThresholds: oe,
|
|
2744
2706
|
INPThresholds: ce,
|
|
2745
2707
|
LCPThresholds: ue,
|
|
2746
2708
|
TTFBThresholds: de,
|
|
2747
|
-
onCLS:
|
|
2748
|
-
onFCP:
|
|
2749
|
-
onINP:
|
|
2750
|
-
onLCP:
|
|
2751
|
-
onTTFB:
|
|
2709
|
+
onCLS: lr,
|
|
2710
|
+
onFCP: $e,
|
|
2711
|
+
onINP: fr,
|
|
2712
|
+
onLCP: mr,
|
|
2713
|
+
onTTFB: Sr
|
|
2752
2714
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2753
2715
|
export {
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
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,
|
|
2762
2724
|
d as EventType,
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
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,
|
|
2734
|
+
yt as TagConditionType,
|
|
2735
|
+
vt as TagLogicalOperator,
|
|
2736
|
+
Cr as tracelog
|
|
2775
2737
|
};
|