@tracelog/lib 0.6.1 → 0.6.3
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/README.md +8 -8
- package/dist/browser/tracelog.esm.js +483 -478
- package/dist/browser/tracelog.esm.js.map +1 -1
- package/dist/browser/tracelog.js +2 -2
- package/dist/browser/tracelog.js.map +1 -1
- package/dist/cjs/api.d.ts +1 -1
- package/dist/cjs/api.js +1 -1
- package/dist/cjs/app.d.ts +1 -1
- package/dist/cjs/app.js +4 -4
- package/dist/cjs/handlers/click.handler.js +2 -2
- package/dist/cjs/handlers/scroll.handler.js +1 -1
- package/dist/cjs/handlers/session.handler.js +1 -1
- package/dist/cjs/managers/sender.manager.js +4 -5
- package/dist/cjs/public-api.d.ts +1 -1
- package/dist/cjs/test-bridge.d.ts +1 -1
- package/dist/cjs/test-bridge.js +1 -1
- package/dist/cjs/types/config.types.d.ts +2 -2
- package/dist/cjs/types/state.types.d.ts +1 -1
- package/dist/cjs/types/test-bridge.types.d.ts +1 -1
- package/dist/cjs/utils/network/url.utils.d.ts +1 -1
- package/dist/cjs/utils/network/url.utils.js +10 -10
- package/dist/cjs/utils/validations/config-validations.utils.d.ts +2 -2
- package/dist/cjs/utils/validations/config-validations.utils.js +16 -13
- package/dist/esm/api.d.ts +1 -1
- package/dist/esm/api.js +1 -1
- package/dist/esm/app.d.ts +1 -1
- package/dist/esm/app.js +5 -5
- package/dist/esm/handlers/click.handler.js +2 -2
- package/dist/esm/handlers/scroll.handler.js +1 -1
- package/dist/esm/handlers/session.handler.js +1 -1
- package/dist/esm/managers/sender.manager.js +4 -5
- package/dist/esm/public-api.d.ts +1 -1
- package/dist/esm/test-bridge.d.ts +1 -1
- package/dist/esm/test-bridge.js +1 -1
- package/dist/esm/types/config.types.d.ts +2 -2
- package/dist/esm/types/state.types.d.ts +1 -1
- package/dist/esm/types/test-bridge.types.d.ts +1 -1
- package/dist/esm/utils/network/url.utils.d.ts +1 -1
- package/dist/esm/utils/network/url.utils.js +8 -8
- package/dist/esm/utils/validations/config-validations.utils.d.ts +2 -2
- package/dist/esm/utils/validations/config-validations.utils.js +16 -13
- package/package.json +6 -6
|
@@ -49,10 +49,10 @@ const m = {
|
|
|
49
49
|
/<embed\b[^>]*>/gi,
|
|
50
50
|
/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi
|
|
51
51
|
];
|
|
52
|
-
var j = /* @__PURE__ */ ((
|
|
52
|
+
var j = /* @__PURE__ */ ((r) => (r.Localhost = "localhost:8080", r.Fail = "localhost:9999", r))(j || {}), _ = /* @__PURE__ */ ((r) => (r.Mobile = "mobile", r.Tablet = "tablet", r.Desktop = "desktop", r.Unknown = "unknown", r))(_ || {}), X = /* @__PURE__ */ ((r) => (r.EVENT = "event", r.QUEUE = "queue", r))(X || {}), 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 || {}), D = /* @__PURE__ */ ((r) => (r.UP = "up", r.DOWN = "down", r))(D || {}), L = /* @__PURE__ */ ((r) => (r.JS_ERROR = "js_error", r.PROMISE_REJECTION = "promise_rejection", r))(L || {}), R = /* @__PURE__ */ ((r) => (r.QA = "qa", r))(R || {});
|
|
53
53
|
class C extends Error {
|
|
54
|
-
constructor(e, t,
|
|
55
|
-
super(e), this.errorCode = t, this.layer =
|
|
54
|
+
constructor(e, t, s) {
|
|
55
|
+
super(e), this.errorCode = t, this.layer = s, this.name = this.constructor.name, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
class y extends C {
|
|
@@ -76,31 +76,31 @@ class v extends C {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
class xt extends C {
|
|
79
|
-
constructor(e, t,
|
|
80
|
-
super(e, "INITIALIZATION_TIMEOUT",
|
|
79
|
+
constructor(e, t, s = "runtime") {
|
|
80
|
+
super(e, "INITIALIZATION_TIMEOUT", s), this.timeoutMs = t;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
const De = (
|
|
83
|
+
const De = (r, e) => {
|
|
84
84
|
if (e) {
|
|
85
85
|
if (e instanceof Error) {
|
|
86
86
|
const t = e.message.replace(/\s+at\s+.*$/gm, "").replace(/\(.*?:\d+:\d+\)/g, "");
|
|
87
|
-
return `[TraceLog] ${
|
|
87
|
+
return `[TraceLog] ${r}: ${t}`;
|
|
88
88
|
}
|
|
89
|
-
return `[TraceLog] ${
|
|
89
|
+
return `[TraceLog] ${r}: ${e instanceof Error ? e.message : "Unknown error"}`;
|
|
90
90
|
}
|
|
91
|
-
return `[TraceLog] ${
|
|
92
|
-
}, o = (
|
|
93
|
-
const { error:
|
|
94
|
-
if (!(
|
|
91
|
+
return `[TraceLog] ${r}`;
|
|
92
|
+
}, o = (r, e, t) => {
|
|
93
|
+
const { error: s, data: n, showToClient: i = !1 } = t ?? {}, a = s ? De(e, s) : `[TraceLog] ${e}`, l = r === "error" ? "error" : r === "warn" ? "warn" : "log";
|
|
94
|
+
if (!(r === "debug" || r === "info" && !i))
|
|
95
95
|
if (n !== void 0) {
|
|
96
|
-
const
|
|
97
|
-
console[
|
|
98
|
-
} else n !== void 0 ? console[
|
|
99
|
-
}, ke = (
|
|
96
|
+
const c = ke(n);
|
|
97
|
+
console[l](a, c);
|
|
98
|
+
} else n !== void 0 ? console[l](a, n) : console[l](a);
|
|
99
|
+
}, ke = (r) => {
|
|
100
100
|
const e = {}, t = ["token", "password", "secret", "key", "apikey", "api_key", "sessionid", "session_id"];
|
|
101
|
-
for (const [
|
|
102
|
-
const i =
|
|
103
|
-
t.some((a) => i.includes(a)) ? e[
|
|
101
|
+
for (const [s, n] of Object.entries(r)) {
|
|
102
|
+
const i = s.toLowerCase();
|
|
103
|
+
t.some((a) => i.includes(a)) ? e[s] = "[REDACTED]" : e[s] = n;
|
|
104
104
|
}
|
|
105
105
|
return e;
|
|
106
106
|
};
|
|
@@ -109,16 +109,16 @@ const Ue = () => {
|
|
|
109
109
|
typeof window < "u" && !W && (W = window.matchMedia("(pointer: coarse)"), pe = window.matchMedia("(hover: none)"));
|
|
110
110
|
}, He = () => {
|
|
111
111
|
try {
|
|
112
|
-
const
|
|
113
|
-
if (
|
|
114
|
-
return
|
|
112
|
+
const r = navigator;
|
|
113
|
+
if (r.userAgentData && typeof r.userAgentData.mobile == "boolean")
|
|
114
|
+
return r.userAgentData.platform && /ipad|tablet/i.test(r.userAgentData.platform) ? _.Tablet : r.userAgentData.mobile ? _.Mobile : _.Desktop;
|
|
115
115
|
Ue();
|
|
116
|
-
const e = window.innerWidth, t = W?.matches ?? !1,
|
|
117
|
-
return e <= 767 || a && n ? _.Mobile : e >= 768 && e <= 1024 ||
|
|
118
|
-
} catch (
|
|
119
|
-
return o("warn", "Device detection failed, defaulting to desktop", { error:
|
|
116
|
+
const e = window.innerWidth, t = W?.matches ?? !1, s = pe?.matches ?? !1, n = "ontouchstart" in window || navigator.maxTouchPoints > 0, i = navigator.userAgent.toLowerCase(), a = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(i), l = /tablet|ipad|android(?!.*mobile)/.test(i);
|
|
117
|
+
return e <= 767 || a && n ? _.Mobile : e >= 768 && e <= 1024 || l || t && s && n ? _.Tablet : _.Desktop;
|
|
118
|
+
} catch (r) {
|
|
119
|
+
return o("warn", "Device detection failed, defaulting to desktop", { error: r }), _.Desktop;
|
|
120
120
|
}
|
|
121
|
-
}, T = "tlog",
|
|
121
|
+
}, T = "tlog", le = `${T}:qa_mode`, xe = `${T}:uid`, Ve = (r) => r ? `${T}:${r}:queue` : `${T}:queue`, Fe = (r) => r ? `${T}:${r}:session` : `${T}:session`, Ge = (r) => r ? `${T}:${r}:broadcast` : `${T}:broadcast`, _e = {
|
|
122
122
|
LCP: 4e3,
|
|
123
123
|
FCP: 1800,
|
|
124
124
|
CLS: 0.25,
|
|
@@ -140,12 +140,12 @@ const Ue = () => {
|
|
|
140
140
|
/Bearer\s+[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)?(?:\.[A-Za-z0-9_-]+)?/gi,
|
|
141
141
|
// Passwords in connection strings (protocol://user:password@host)
|
|
142
142
|
/:\/\/[^:/]+:([^@]+)@/gi
|
|
143
|
-
],
|
|
144
|
-
if (sessionStorage.getItem(
|
|
143
|
+
], ce = 500, ue = 5e3, k = 50, $e = k * 2, de = "tlog_mode", Qe = "qa", Be = () => {
|
|
144
|
+
if (sessionStorage.getItem(le) === "true")
|
|
145
145
|
return !0;
|
|
146
|
-
const e = new URLSearchParams(window.location.search),
|
|
147
|
-
if (
|
|
148
|
-
sessionStorage.setItem(
|
|
146
|
+
const e = new URLSearchParams(window.location.search), s = e.get(de) === Qe;
|
|
147
|
+
if (s) {
|
|
148
|
+
sessionStorage.setItem(le, "true"), e.delete(de);
|
|
149
149
|
const n = e.toString(), i = `${window.location.pathname}${n ? "?" + n : ""}${window.location.hash}`;
|
|
150
150
|
try {
|
|
151
151
|
window.history.replaceState({}, "", i);
|
|
@@ -157,70 +157,71 @@ const Ue = () => {
|
|
|
157
157
|
"background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;"
|
|
158
158
|
);
|
|
159
159
|
}
|
|
160
|
-
return
|
|
160
|
+
return s;
|
|
161
161
|
}, he = () => {
|
|
162
|
-
const
|
|
163
|
-
return be.forEach((
|
|
164
|
-
const n =
|
|
162
|
+
const r = new URLSearchParams(window.location.search), e = {};
|
|
163
|
+
return be.forEach((s) => {
|
|
164
|
+
const n = r.get(s);
|
|
165
165
|
if (n) {
|
|
166
|
-
const i =
|
|
166
|
+
const i = s.split("utm_")[1];
|
|
167
167
|
e[i] = n;
|
|
168
168
|
}
|
|
169
169
|
}), Object.keys(e).length ? e : void 0;
|
|
170
|
-
}, je = () => typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (
|
|
170
|
+
}, je = () => typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (r) => {
|
|
171
171
|
const e = Math.random() * 16 | 0;
|
|
172
|
-
return (
|
|
172
|
+
return (r === "x" ? e : e & 3 | 8).toString(16);
|
|
173
173
|
}), Xe = () => {
|
|
174
|
-
const
|
|
174
|
+
const r = Date.now();
|
|
175
175
|
let e = "";
|
|
176
176
|
try {
|
|
177
177
|
if (typeof crypto < "u" && crypto.getRandomValues) {
|
|
178
178
|
const t = crypto.getRandomValues(new Uint8Array(4));
|
|
179
|
-
t && (e = Array.from(t, (
|
|
179
|
+
t && (e = Array.from(t, (s) => s.toString(16).padStart(2, "0")).join(""));
|
|
180
180
|
}
|
|
181
181
|
} catch {
|
|
182
182
|
}
|
|
183
|
-
return e || (e = Math.floor(Math.random() * 4294967295).toString(16).padStart(8, "0")), `${
|
|
184
|
-
}, fe = (
|
|
183
|
+
return e || (e = Math.floor(Math.random() * 4294967295).toString(16).padStart(8, "0")), `${r}-${e}`;
|
|
184
|
+
}, fe = (r, e = !1) => {
|
|
185
185
|
try {
|
|
186
|
-
const t = new URL(
|
|
187
|
-
return
|
|
186
|
+
const t = new URL(r), s = t.protocol === "https:", n = t.protocol === "http:";
|
|
187
|
+
return s || e && n;
|
|
188
188
|
} catch {
|
|
189
189
|
return !1;
|
|
190
190
|
}
|
|
191
|
-
}, We = (
|
|
192
|
-
if (
|
|
193
|
-
const
|
|
194
|
-
if (
|
|
191
|
+
}, We = (r) => {
|
|
192
|
+
if (r.integrations?.tracelog?.projectId) {
|
|
193
|
+
const n = new URL(window.location.href).hostname.split(".");
|
|
194
|
+
if (n.length === 0)
|
|
195
195
|
throw new Error("Invalid URL");
|
|
196
|
-
const
|
|
197
|
-
if (!fe(
|
|
196
|
+
const i = r.integrations.tracelog.projectId, a = n.slice(-2).join("."), l = `https://${i}.${a}/collect`;
|
|
197
|
+
if (!fe(l))
|
|
198
198
|
throw new Error("Invalid URL");
|
|
199
|
-
return
|
|
199
|
+
return l;
|
|
200
200
|
}
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
const e = r.integrations?.custom?.collectApiUrl;
|
|
202
|
+
if (e) {
|
|
203
|
+
const t = r.integrations?.custom?.allowHttp ?? !1;
|
|
203
204
|
if (!fe(e, t))
|
|
204
205
|
throw new Error("Invalid URL");
|
|
205
206
|
return e;
|
|
206
207
|
}
|
|
207
208
|
return "";
|
|
208
|
-
}, Y = (
|
|
209
|
+
}, Y = (r, e = []) => {
|
|
209
210
|
try {
|
|
210
|
-
const t = new URL(
|
|
211
|
+
const t = new URL(r), s = t.searchParams;
|
|
211
212
|
let n = !1;
|
|
212
213
|
const i = [];
|
|
213
|
-
return e.forEach((
|
|
214
|
-
|
|
215
|
-
}), !n &&
|
|
214
|
+
return e.forEach((l) => {
|
|
215
|
+
s.has(l) && (s.delete(l), n = !0, i.push(l));
|
|
216
|
+
}), !n && r.includes("?") ? r : (t.search = s.toString(), t.toString());
|
|
216
217
|
} catch (t) {
|
|
217
|
-
return o("warn", "URL normalization failed, returning original", { error: t, data: { url:
|
|
218
|
+
return o("warn", "URL normalization failed, returning original", { error: t, data: { url: r.slice(0, 100) } }), r;
|
|
218
219
|
}
|
|
219
|
-
}, ge = (
|
|
220
|
-
if (!
|
|
220
|
+
}, ge = (r) => {
|
|
221
|
+
if (!r || typeof r != "string" || r.trim().length === 0)
|
|
221
222
|
return "";
|
|
222
|
-
let e =
|
|
223
|
-
|
|
223
|
+
let e = r;
|
|
224
|
+
r.length > 1e3 && (e = r.slice(0, Math.max(0, 1e3)));
|
|
224
225
|
let t = 0;
|
|
225
226
|
for (const n of Oe) {
|
|
226
227
|
const i = e;
|
|
@@ -229,73 +230,75 @@ const Ue = () => {
|
|
|
229
230
|
return t > 0 && o("warn", "XSS patterns detected and removed", {
|
|
230
231
|
data: {
|
|
231
232
|
patternMatches: t,
|
|
232
|
-
originalValue:
|
|
233
|
+
originalValue: r.slice(0, 100)
|
|
233
234
|
}
|
|
234
235
|
}), e = e.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'").replaceAll("/", "/"), e.trim();
|
|
235
|
-
}, K = (
|
|
236
|
-
if (e > 3 ||
|
|
236
|
+
}, K = (r, e = 0) => {
|
|
237
|
+
if (e > 3 || r == null)
|
|
237
238
|
return null;
|
|
238
|
-
if (typeof
|
|
239
|
-
return ge(
|
|
240
|
-
if (typeof
|
|
241
|
-
return !Number.isFinite(
|
|
242
|
-
if (typeof
|
|
243
|
-
return
|
|
244
|
-
if (Array.isArray(
|
|
245
|
-
return
|
|
246
|
-
if (typeof
|
|
247
|
-
const t = {}, n = Object.entries(
|
|
239
|
+
if (typeof r == "string")
|
|
240
|
+
return ge(r);
|
|
241
|
+
if (typeof r == "number")
|
|
242
|
+
return !Number.isFinite(r) || r < -Number.MAX_SAFE_INTEGER || r > Number.MAX_SAFE_INTEGER ? 0 : r;
|
|
243
|
+
if (typeof r == "boolean")
|
|
244
|
+
return r;
|
|
245
|
+
if (Array.isArray(r))
|
|
246
|
+
return r.slice(0, 100).map((n) => K(n, e + 1)).filter((n) => n !== null);
|
|
247
|
+
if (typeof r == "object") {
|
|
248
|
+
const t = {}, n = Object.entries(r).slice(0, 20);
|
|
248
249
|
for (const [i, a] of n) {
|
|
249
|
-
const
|
|
250
|
-
if (
|
|
251
|
-
const
|
|
252
|
-
|
|
250
|
+
const l = ge(i);
|
|
251
|
+
if (l) {
|
|
252
|
+
const c = K(a, e + 1);
|
|
253
|
+
c !== null && (t[l] = c);
|
|
253
254
|
}
|
|
254
255
|
}
|
|
255
256
|
return t;
|
|
256
257
|
}
|
|
257
258
|
return null;
|
|
258
|
-
}, Ye = (
|
|
259
|
-
if (typeof
|
|
259
|
+
}, Ye = (r) => {
|
|
260
|
+
if (typeof r != "object" || r === null)
|
|
260
261
|
return {};
|
|
261
262
|
try {
|
|
262
|
-
const e = K(
|
|
263
|
+
const e = K(r);
|
|
263
264
|
return typeof e == "object" && e !== null ? e : {};
|
|
264
265
|
} catch (e) {
|
|
265
266
|
const t = e instanceof Error ? e.message : String(e);
|
|
266
267
|
throw new Error(`[TraceLog] Metadata sanitization failed: ${t}`);
|
|
267
268
|
}
|
|
268
|
-
}, Ke = (
|
|
269
|
-
if (
|
|
269
|
+
}, Ke = (r) => {
|
|
270
|
+
if (r !== void 0 && (r === null || typeof r != "object"))
|
|
270
271
|
throw new y("Configuration must be an object", "config");
|
|
271
|
-
if (
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
272
|
+
if (r) {
|
|
273
|
+
if (r.sessionTimeout !== void 0 && (typeof r.sessionTimeout != "number" || r.sessionTimeout < 3e4 || r.sessionTimeout > 864e5))
|
|
274
|
+
throw new Pe(m.INVALID_SESSION_TIMEOUT, "config");
|
|
275
|
+
if (r.globalMetadata !== void 0 && (typeof r.globalMetadata != "object" || r.globalMetadata === null))
|
|
276
|
+
throw new y(m.INVALID_GLOBAL_METADATA, "config");
|
|
277
|
+
if (r.scrollContainerSelectors !== void 0 && Ze(r.scrollContainerSelectors), r.integrations && Je(r.integrations), r.sensitiveQueryParams !== void 0) {
|
|
278
|
+
if (!Array.isArray(r.sensitiveQueryParams))
|
|
279
|
+
throw new y(m.INVALID_SENSITIVE_QUERY_PARAMS, "config");
|
|
280
|
+
for (const e of r.sensitiveQueryParams)
|
|
281
|
+
if (typeof e != "string")
|
|
282
|
+
throw new y("All sensitive query params must be strings", "config");
|
|
283
|
+
}
|
|
284
|
+
if (r.errorSampling !== void 0 && (typeof r.errorSampling != "number" || r.errorSampling < 0 || r.errorSampling > 1))
|
|
285
|
+
throw new oe(m.INVALID_ERROR_SAMPLING_RATE, "config");
|
|
286
|
+
if (r.samplingRate !== void 0 && (typeof r.samplingRate != "number" || r.samplingRate < 0 || r.samplingRate > 1))
|
|
287
|
+
throw new oe(m.INVALID_SAMPLING_RATE, "config");
|
|
288
|
+
}
|
|
289
|
+
}, qe = (r) => {
|
|
290
|
+
if (r.includes("<") || r.includes(">") || /on\w+\s*=/i.test(r) || !/^[a-zA-Z0-9\-_#.[\]="':, >+~*()]+$/.test(r))
|
|
288
291
|
return !1;
|
|
289
292
|
let t = 0;
|
|
290
|
-
for (const n of
|
|
293
|
+
for (const n of r)
|
|
291
294
|
if (n === "(" && t++, n === ")" && t--, t < 0) return !1;
|
|
292
295
|
if (t !== 0) return !1;
|
|
293
|
-
let
|
|
294
|
-
for (const n of
|
|
295
|
-
if (n === "[" &&
|
|
296
|
-
return
|
|
297
|
-
}, Ze = (
|
|
298
|
-
const e = Array.isArray(
|
|
296
|
+
let s = 0;
|
|
297
|
+
for (const n of r)
|
|
298
|
+
if (n === "[" && s++, n === "]" && s--, s < 0) return !1;
|
|
299
|
+
return s === 0;
|
|
300
|
+
}, Ze = (r) => {
|
|
301
|
+
const e = Array.isArray(r) ? r : [r];
|
|
299
302
|
for (const t of e) {
|
|
300
303
|
if (typeof t != "string" || t.trim() === "")
|
|
301
304
|
throw o("error", "Invalid scroll container selector", {
|
|
@@ -315,66 +318,66 @@ const Ue = () => {
|
|
|
315
318
|
}
|
|
316
319
|
}), new y("Invalid or potentially unsafe CSS selector", "config");
|
|
317
320
|
}
|
|
318
|
-
}, Je = (
|
|
319
|
-
if (
|
|
320
|
-
if (
|
|
321
|
+
}, Je = (r) => {
|
|
322
|
+
if (r) {
|
|
323
|
+
if (r.tracelog && (!r.tracelog.projectId || typeof r.tracelog.projectId != "string" || r.tracelog.projectId.trim() === ""))
|
|
321
324
|
throw new v(m.INVALID_TRACELOG_PROJECT_ID, "config");
|
|
322
|
-
if (
|
|
323
|
-
if (!
|
|
325
|
+
if (r.custom) {
|
|
326
|
+
if (!r.custom.collectApiUrl || typeof r.custom.collectApiUrl != "string" || r.custom.collectApiUrl.trim() === "")
|
|
324
327
|
throw new v(m.INVALID_CUSTOM_API_URL, "config");
|
|
325
|
-
if (
|
|
328
|
+
if (r.custom.allowHttp !== void 0 && typeof r.custom.allowHttp != "boolean")
|
|
326
329
|
throw new v("allowHttp must be a boolean", "config");
|
|
327
|
-
const e =
|
|
330
|
+
const e = r.custom.collectApiUrl.trim();
|
|
328
331
|
if (!e.startsWith("http://") && !e.startsWith("https://"))
|
|
329
332
|
throw new v('Custom API URL must start with "http://" or "https://"', "config");
|
|
330
|
-
if (!(
|
|
333
|
+
if (!(r.custom.allowHttp ?? !1) && e.startsWith("http://"))
|
|
331
334
|
throw new v(
|
|
332
335
|
"Custom API URL must use HTTPS in production. Set allowHttp: true in integration config to allow HTTP (not recommended)",
|
|
333
336
|
"config"
|
|
334
337
|
);
|
|
335
338
|
}
|
|
336
|
-
if (
|
|
337
|
-
if (!
|
|
339
|
+
if (r.googleAnalytics) {
|
|
340
|
+
if (!r.googleAnalytics.measurementId || typeof r.googleAnalytics.measurementId != "string" || r.googleAnalytics.measurementId.trim() === "")
|
|
338
341
|
throw new v(m.INVALID_GOOGLE_ANALYTICS_ID, "config");
|
|
339
|
-
if (!
|
|
342
|
+
if (!r.googleAnalytics.measurementId.trim().match(/^(G-|UA-)/))
|
|
340
343
|
throw new v('Google Analytics measurement ID must start with "G-" or "UA-"', "config");
|
|
341
344
|
}
|
|
342
345
|
}
|
|
343
|
-
}, et = (
|
|
344
|
-
Ke(
|
|
346
|
+
}, et = (r) => {
|
|
347
|
+
Ke(r);
|
|
345
348
|
const e = {
|
|
346
|
-
...
|
|
347
|
-
sessionTimeout:
|
|
348
|
-
globalMetadata:
|
|
349
|
-
sensitiveQueryParams:
|
|
350
|
-
errorSampling:
|
|
351
|
-
samplingRate:
|
|
349
|
+
...r ?? {},
|
|
350
|
+
sessionTimeout: r?.sessionTimeout ?? 9e5,
|
|
351
|
+
globalMetadata: r?.globalMetadata ?? {},
|
|
352
|
+
sensitiveQueryParams: r?.sensitiveQueryParams ?? [],
|
|
353
|
+
errorSampling: r?.errorSampling ?? 1,
|
|
354
|
+
samplingRate: r?.samplingRate ?? 1
|
|
352
355
|
};
|
|
353
356
|
return e.integrations?.custom && (e.integrations.custom = {
|
|
354
357
|
...e.integrations.custom,
|
|
355
358
|
allowHttp: e.integrations.custom.allowHttp ?? !1
|
|
356
359
|
}), e;
|
|
357
|
-
}, tt = (
|
|
358
|
-
if (typeof
|
|
360
|
+
}, tt = (r) => {
|
|
361
|
+
if (typeof r == "string")
|
|
359
362
|
return !0;
|
|
360
|
-
if (typeof
|
|
361
|
-
const e = Object.entries(
|
|
363
|
+
if (typeof r == "object" && r !== null && !Array.isArray(r)) {
|
|
364
|
+
const e = Object.entries(r);
|
|
362
365
|
if (e.length > 20)
|
|
363
366
|
return !1;
|
|
364
367
|
for (const [, t] of e) {
|
|
365
368
|
if (t == null)
|
|
366
369
|
continue;
|
|
367
|
-
const
|
|
368
|
-
if (
|
|
370
|
+
const s = typeof t;
|
|
371
|
+
if (s !== "string" && s !== "number" && s !== "boolean")
|
|
369
372
|
return !1;
|
|
370
373
|
}
|
|
371
374
|
return !0;
|
|
372
375
|
}
|
|
373
376
|
return !1;
|
|
374
|
-
}, rt = (
|
|
375
|
-
if (typeof
|
|
377
|
+
}, rt = (r) => {
|
|
378
|
+
if (typeof r != "object" || r === null)
|
|
376
379
|
return !1;
|
|
377
|
-
for (const e of Object.values(
|
|
380
|
+
for (const e of Object.values(r)) {
|
|
378
381
|
if (e == null)
|
|
379
382
|
continue;
|
|
380
383
|
const t = typeof e;
|
|
@@ -393,31 +396,31 @@ const Ue = () => {
|
|
|
393
396
|
}
|
|
394
397
|
}
|
|
395
398
|
return !0;
|
|
396
|
-
}, st = (
|
|
399
|
+
}, st = (r) => typeof r != "string" ? {
|
|
397
400
|
valid: !1,
|
|
398
401
|
error: "Event name must be a string"
|
|
399
|
-
} :
|
|
402
|
+
} : r.length === 0 ? {
|
|
400
403
|
valid: !1,
|
|
401
404
|
error: "Event name cannot be empty"
|
|
402
|
-
} :
|
|
405
|
+
} : r.length > 120 ? {
|
|
403
406
|
valid: !1,
|
|
404
407
|
error: "Event name is too long (max 120 characters)"
|
|
405
|
-
} :
|
|
408
|
+
} : r.includes("<") || r.includes(">") || r.includes("&") ? {
|
|
406
409
|
valid: !1,
|
|
407
410
|
error: "Event name contains invalid characters"
|
|
408
|
-
} : ["constructor", "prototype", "__proto__", "eval", "function", "var", "let", "const"].includes(
|
|
411
|
+
} : ["constructor", "prototype", "__proto__", "eval", "function", "var", "let", "const"].includes(r.toLowerCase()) ? {
|
|
409
412
|
valid: !1,
|
|
410
413
|
error: "Event name cannot be a reserved word"
|
|
411
|
-
} : { valid: !0 }, Se = (
|
|
412
|
-
const
|
|
413
|
-
if (!rt(
|
|
414
|
+
} : { valid: !0 }, Se = (r, e, t) => {
|
|
415
|
+
const s = Ye(e), n = `${t} "${r}" metadata error`;
|
|
416
|
+
if (!rt(s))
|
|
414
417
|
return {
|
|
415
418
|
valid: !1,
|
|
416
419
|
error: `${n}: object has invalid types. Valid types are string, number, boolean or string arrays.`
|
|
417
420
|
};
|
|
418
421
|
let i;
|
|
419
422
|
try {
|
|
420
|
-
i = JSON.stringify(
|
|
423
|
+
i = JSON.stringify(s);
|
|
421
424
|
} catch {
|
|
422
425
|
return {
|
|
423
426
|
valid: !1,
|
|
@@ -429,38 +432,38 @@ const Ue = () => {
|
|
|
429
432
|
valid: !1,
|
|
430
433
|
error: `${n}: object is too large (max ${8192 / 1024} KB).`
|
|
431
434
|
};
|
|
432
|
-
if (Object.keys(
|
|
435
|
+
if (Object.keys(s).length > 10)
|
|
433
436
|
return {
|
|
434
437
|
valid: !1,
|
|
435
438
|
error: `${n}: object has too many keys (max 10 keys).`
|
|
436
439
|
};
|
|
437
|
-
for (const [
|
|
438
|
-
if (Array.isArray(
|
|
439
|
-
if (
|
|
440
|
+
for (const [l, c] of Object.entries(s)) {
|
|
441
|
+
if (Array.isArray(c)) {
|
|
442
|
+
if (c.length > 10)
|
|
440
443
|
return {
|
|
441
444
|
valid: !1,
|
|
442
|
-
error: `${n}: array property "${
|
|
445
|
+
error: `${n}: array property "${l}" is too large (max 10 items).`
|
|
443
446
|
};
|
|
444
|
-
for (const u of
|
|
447
|
+
for (const u of c)
|
|
445
448
|
if (typeof u == "string" && u.length > 500)
|
|
446
449
|
return {
|
|
447
450
|
valid: !1,
|
|
448
|
-
error: `${n}: array property "${
|
|
451
|
+
error: `${n}: array property "${l}" contains strings that are too long (max 500 characters).`
|
|
449
452
|
};
|
|
450
453
|
}
|
|
451
|
-
if (typeof
|
|
454
|
+
if (typeof c == "string" && c.length > 1e3)
|
|
452
455
|
return {
|
|
453
456
|
valid: !1,
|
|
454
|
-
error: `${n}: property "${
|
|
457
|
+
error: `${n}: property "${l}" is too long (max 1000 characters).`
|
|
455
458
|
};
|
|
456
459
|
}
|
|
457
460
|
return {
|
|
458
461
|
valid: !0,
|
|
459
|
-
sanitizedMetadata:
|
|
462
|
+
sanitizedMetadata: s
|
|
460
463
|
};
|
|
461
|
-
}, nt = (
|
|
464
|
+
}, nt = (r, e, t) => {
|
|
462
465
|
if (Array.isArray(e)) {
|
|
463
|
-
const
|
|
466
|
+
const s = [], n = `${t} "${r}" metadata error`;
|
|
464
467
|
for (let i = 0; i < e.length; i++) {
|
|
465
468
|
const a = e[i];
|
|
466
469
|
if (typeof a != "object" || a === null || Array.isArray(a))
|
|
@@ -468,37 +471,37 @@ const Ue = () => {
|
|
|
468
471
|
valid: !1,
|
|
469
472
|
error: `${n}: array item at index ${i} must be an object.`
|
|
470
473
|
};
|
|
471
|
-
const
|
|
472
|
-
if (!
|
|
474
|
+
const l = Se(r, a, t);
|
|
475
|
+
if (!l.valid)
|
|
473
476
|
return {
|
|
474
477
|
valid: !1,
|
|
475
|
-
error: `${n}: array item at index ${i} is invalid: ${
|
|
478
|
+
error: `${n}: array item at index ${i} is invalid: ${l.error}`
|
|
476
479
|
};
|
|
477
|
-
|
|
480
|
+
l.sanitizedMetadata && s.push(l.sanitizedMetadata);
|
|
478
481
|
}
|
|
479
482
|
return {
|
|
480
483
|
valid: !0,
|
|
481
|
-
sanitizedMetadata:
|
|
484
|
+
sanitizedMetadata: s
|
|
482
485
|
};
|
|
483
486
|
}
|
|
484
|
-
return Se(
|
|
485
|
-
}, it = (
|
|
486
|
-
const t = st(
|
|
487
|
+
return Se(r, e, t);
|
|
488
|
+
}, it = (r, e) => {
|
|
489
|
+
const t = st(r);
|
|
487
490
|
if (!t.valid)
|
|
488
491
|
return o("error", "Event name validation failed", {
|
|
489
492
|
showToClient: !0,
|
|
490
|
-
data: { eventName:
|
|
493
|
+
data: { eventName: r, error: t.error }
|
|
491
494
|
}), t;
|
|
492
495
|
if (!e)
|
|
493
496
|
return { valid: !0 };
|
|
494
|
-
const
|
|
495
|
-
return
|
|
497
|
+
const s = nt(r, e, "customEvent");
|
|
498
|
+
return s.valid || o("error", "Event metadata validation failed", {
|
|
496
499
|
showToClient: !0,
|
|
497
500
|
data: {
|
|
498
|
-
eventName:
|
|
499
|
-
error:
|
|
501
|
+
eventName: r,
|
|
502
|
+
error: s.error
|
|
500
503
|
}
|
|
501
|
-
}),
|
|
504
|
+
}), s;
|
|
502
505
|
};
|
|
503
506
|
class at {
|
|
504
507
|
listeners = /* @__PURE__ */ new Map();
|
|
@@ -506,15 +509,15 @@ class at {
|
|
|
506
509
|
this.listeners.has(e) || this.listeners.set(e, []), this.listeners.get(e).push(t);
|
|
507
510
|
}
|
|
508
511
|
off(e, t) {
|
|
509
|
-
const
|
|
510
|
-
if (
|
|
511
|
-
const n =
|
|
512
|
-
n > -1 &&
|
|
512
|
+
const s = this.listeners.get(e);
|
|
513
|
+
if (s) {
|
|
514
|
+
const n = s.indexOf(t);
|
|
515
|
+
n > -1 && s.splice(n, 1);
|
|
513
516
|
}
|
|
514
517
|
}
|
|
515
518
|
emit(e, t) {
|
|
516
|
-
const
|
|
517
|
-
|
|
519
|
+
const s = this.listeners.get(e);
|
|
520
|
+
s && s.forEach((n) => n(t));
|
|
518
521
|
}
|
|
519
522
|
removeAllListeners() {
|
|
520
523
|
this.listeners.clear();
|
|
@@ -547,17 +550,17 @@ class ot extends f {
|
|
|
547
550
|
sendEventsQueueSync(e) {
|
|
548
551
|
if (this.shouldSkipSend())
|
|
549
552
|
return this.resetRetryState(), !0;
|
|
550
|
-
if (this.get("config")?.integrations?.custom?.
|
|
553
|
+
if (this.get("config")?.integrations?.custom?.collectApiUrl === j.Fail)
|
|
551
554
|
return o("warn", "Fail mode: simulating network failure (sync)", {
|
|
552
555
|
data: { events: e.events.length }
|
|
553
556
|
}), !1;
|
|
554
|
-
const
|
|
555
|
-
return
|
|
557
|
+
const s = this.sendQueueSyncInternal(e);
|
|
558
|
+
return s && this.resetRetryState(), s;
|
|
556
559
|
}
|
|
557
560
|
async sendEventsQueue(e, t) {
|
|
558
561
|
this.shouldSkipSend() || this.persistEvents(e) || o("warn", "Failed to persist events, attempting immediate send");
|
|
559
|
-
const
|
|
560
|
-
return
|
|
562
|
+
const s = await this.send(e);
|
|
563
|
+
return s ? (this.clearPersistedEvents(), this.resetRetryState(), t?.onSuccess?.(e.events.length, e.events, e)) : (this.scheduleRetry(e, t), t?.onFailure?.()), s;
|
|
561
564
|
}
|
|
562
565
|
async recoverPersistedEvents(e) {
|
|
563
566
|
try {
|
|
@@ -566,8 +569,8 @@ class ot extends f {
|
|
|
566
569
|
this.clearPersistedEvents();
|
|
567
570
|
return;
|
|
568
571
|
}
|
|
569
|
-
const
|
|
570
|
-
await this.send(
|
|
572
|
+
const s = this.createRecoveryBody(t);
|
|
573
|
+
await this.send(s) ? (this.clearPersistedEvents(), this.resetRetryState(), e?.onSuccess?.(t.events.length, t.events, s)) : (this.scheduleRetry(s, e), e?.onFailure?.());
|
|
571
574
|
} catch (t) {
|
|
572
575
|
o("error", "Failed to recover persisted events", { error: t }), this.clearPersistedEvents();
|
|
573
576
|
}
|
|
@@ -584,32 +587,32 @@ class ot extends f {
|
|
|
584
587
|
async send(e) {
|
|
585
588
|
if (this.shouldSkipSend())
|
|
586
589
|
return this.simulateSuccessfulSend();
|
|
587
|
-
if (this.get("config")?.integrations?.custom?.
|
|
590
|
+
if (this.get("config")?.integrations?.custom?.collectApiUrl === j.Fail)
|
|
588
591
|
return o("warn", "Fail mode: simulating network failure", {
|
|
589
592
|
data: { events: e.events.length }
|
|
590
593
|
}), !1;
|
|
591
|
-
const { url:
|
|
594
|
+
const { url: s, payload: n } = this.prepareRequest(e);
|
|
592
595
|
try {
|
|
593
|
-
return (await this.sendWithTimeout(
|
|
596
|
+
return (await this.sendWithTimeout(s, n)).ok;
|
|
594
597
|
} catch (i) {
|
|
595
598
|
return o("error", "Send request failed", {
|
|
596
599
|
error: i,
|
|
597
600
|
data: {
|
|
598
601
|
events: e.events.length,
|
|
599
|
-
url:
|
|
602
|
+
url: s.replace(/\/\/[^/]+/, "//[DOMAIN]")
|
|
600
603
|
}
|
|
601
604
|
}), !1;
|
|
602
605
|
}
|
|
603
606
|
}
|
|
604
607
|
async sendWithTimeout(e, t) {
|
|
605
|
-
const
|
|
608
|
+
const s = new AbortController(), n = setTimeout(() => s.abort(), 1e4);
|
|
606
609
|
try {
|
|
607
610
|
const i = await fetch(e, {
|
|
608
611
|
method: "POST",
|
|
609
612
|
body: t,
|
|
610
613
|
keepalive: !0,
|
|
611
614
|
credentials: "include",
|
|
612
|
-
signal:
|
|
615
|
+
signal: s.signal,
|
|
613
616
|
headers: {
|
|
614
617
|
"Content-Type": "application/json"
|
|
615
618
|
}
|
|
@@ -622,7 +625,7 @@ class ot extends f {
|
|
|
622
625
|
}
|
|
623
626
|
}
|
|
624
627
|
sendQueueSyncInternal(e) {
|
|
625
|
-
const { url: t, payload:
|
|
628
|
+
const { url: t, payload: s } = this.prepareRequest(e), n = new Blob([s], { type: "application/json" });
|
|
626
629
|
if (this.isSendBeaconAvailable()) {
|
|
627
630
|
if (navigator.sendBeacon(t, n))
|
|
628
631
|
return !0;
|
|
@@ -632,7 +635,7 @@ class ot extends f {
|
|
|
632
635
|
return this.persistEventsForRecovery(e), !1;
|
|
633
636
|
}
|
|
634
637
|
prepareRequest(e) {
|
|
635
|
-
const t =
|
|
638
|
+
const t = {
|
|
636
639
|
...e,
|
|
637
640
|
_metadata: {
|
|
638
641
|
referer: typeof window < "u" ? window.location.href : void 0,
|
|
@@ -640,8 +643,8 @@ class ot extends f {
|
|
|
640
643
|
}
|
|
641
644
|
};
|
|
642
645
|
return {
|
|
643
|
-
url:
|
|
644
|
-
payload: JSON.stringify(
|
|
646
|
+
url: this.get("collectApiUrl"),
|
|
647
|
+
payload: JSON.stringify(t)
|
|
645
648
|
};
|
|
646
649
|
}
|
|
647
650
|
getPersistedData() {
|
|
@@ -675,8 +678,8 @@ class ot extends f {
|
|
|
675
678
|
events: e.events,
|
|
676
679
|
timestamp: Date.now(),
|
|
677
680
|
...e.global_metadata && { global_metadata: e.global_metadata }
|
|
678
|
-
},
|
|
679
|
-
return this.storeManager.setItem(
|
|
681
|
+
}, s = this.getQueueStorageKey();
|
|
682
|
+
return this.storeManager.setItem(s, JSON.stringify(t)), !!this.storeManager.getItem(s);
|
|
680
683
|
} catch (t) {
|
|
681
684
|
return o("warn", "Failed to persist events", { error: t }), !1;
|
|
682
685
|
}
|
|
@@ -699,7 +702,7 @@ class ot extends f {
|
|
|
699
702
|
o("warn", "Max retries reached, giving up", { data: { retryCount: this.retryCount } }), this.clearPersistedEvents(), this.resetRetryState(), t?.onFailure?.();
|
|
700
703
|
return;
|
|
701
704
|
}
|
|
702
|
-
const
|
|
705
|
+
const s = 5e3 * Math.pow(2, this.retryCount);
|
|
703
706
|
this.isRetrying = !0, this.retryTimeoutId = window.setTimeout(async () => {
|
|
704
707
|
this.retryTimeoutId = null, this.retryCount++;
|
|
705
708
|
try {
|
|
@@ -707,10 +710,10 @@ class ot extends f {
|
|
|
707
710
|
} finally {
|
|
708
711
|
this.isRetrying = !1;
|
|
709
712
|
}
|
|
710
|
-
},
|
|
713
|
+
}, s);
|
|
711
714
|
}
|
|
712
715
|
shouldSkipSend() {
|
|
713
|
-
return !this.get("
|
|
716
|
+
return !this.get("collectApiUrl");
|
|
714
717
|
}
|
|
715
718
|
async simulateSuccessfulSend() {
|
|
716
719
|
const e = Math.random() * 400 + 100;
|
|
@@ -723,7 +726,7 @@ class ot extends f {
|
|
|
723
726
|
this.retryTimeoutId !== null && (clearTimeout(this.retryTimeoutId), this.retryTimeoutId = null);
|
|
724
727
|
}
|
|
725
728
|
}
|
|
726
|
-
class
|
|
729
|
+
class lt extends f {
|
|
727
730
|
googleAnalytics;
|
|
728
731
|
dataSender;
|
|
729
732
|
emitter;
|
|
@@ -734,15 +737,15 @@ class ct extends f {
|
|
|
734
737
|
sendIntervalId = null;
|
|
735
738
|
rateLimitCounter = 0;
|
|
736
739
|
rateLimitWindowStart = 0;
|
|
737
|
-
constructor(e, t = null,
|
|
738
|
-
super(), this.googleAnalytics = t, this.dataSender = new ot(e), this.emitter =
|
|
740
|
+
constructor(e, t = null, s = null) {
|
|
741
|
+
super(), this.googleAnalytics = t, this.dataSender = new ot(e), this.emitter = s;
|
|
739
742
|
}
|
|
740
743
|
async recoverPersistedEvents() {
|
|
741
744
|
await this.dataSender.recoverPersistedEvents({
|
|
742
|
-
onSuccess: (e, t,
|
|
745
|
+
onSuccess: (e, t, s) => {
|
|
743
746
|
if (t && t.length > 0) {
|
|
744
747
|
const n = t.map((i) => i.id);
|
|
745
|
-
this.removeProcessedEvents(n),
|
|
748
|
+
this.removeProcessedEvents(n), s && this.emitEventsQueue(s);
|
|
746
749
|
}
|
|
747
750
|
},
|
|
748
751
|
onFailure: async () => {
|
|
@@ -753,12 +756,12 @@ class ct extends f {
|
|
|
753
756
|
track({
|
|
754
757
|
type: e,
|
|
755
758
|
page_url: t,
|
|
756
|
-
from_page_url:
|
|
759
|
+
from_page_url: s,
|
|
757
760
|
scroll_data: n,
|
|
758
761
|
click_data: i,
|
|
759
762
|
custom_event: a,
|
|
760
|
-
web_vitals:
|
|
761
|
-
error_data:
|
|
763
|
+
web_vitals: l,
|
|
764
|
+
error_data: c,
|
|
762
765
|
session_end_reason: u
|
|
763
766
|
}) {
|
|
764
767
|
if (!e) {
|
|
@@ -771,12 +774,12 @@ class ct extends f {
|
|
|
771
774
|
})), this.pendingEventsBuffer.push({
|
|
772
775
|
type: e,
|
|
773
776
|
page_url: t,
|
|
774
|
-
from_page_url:
|
|
777
|
+
from_page_url: s,
|
|
775
778
|
scroll_data: n,
|
|
776
779
|
click_data: i,
|
|
777
780
|
custom_event: a,
|
|
778
|
-
web_vitals:
|
|
779
|
-
error_data:
|
|
781
|
+
web_vitals: l,
|
|
782
|
+
error_data: c,
|
|
780
783
|
session_end_reason: u
|
|
781
784
|
});
|
|
782
785
|
return;
|
|
@@ -787,12 +790,12 @@ class ct extends f {
|
|
|
787
790
|
const N = e, Le = N === d.SESSION_START, Re = t || this.get("pageUrl"), z = this.buildEventPayload({
|
|
788
791
|
type: N,
|
|
789
792
|
page_url: Re,
|
|
790
|
-
from_page_url:
|
|
793
|
+
from_page_url: s,
|
|
791
794
|
scroll_data: n,
|
|
792
795
|
click_data: i,
|
|
793
796
|
custom_event: a,
|
|
794
|
-
web_vitals:
|
|
795
|
-
error_data:
|
|
797
|
+
web_vitals: l,
|
|
798
|
+
error_data: c,
|
|
796
799
|
session_end_reason: u
|
|
797
800
|
});
|
|
798
801
|
if (!(!p && !this.shouldSample())) {
|
|
@@ -844,8 +847,8 @@ class ct extends f {
|
|
|
844
847
|
return;
|
|
845
848
|
}
|
|
846
849
|
const t = [...this.pendingEventsBuffer];
|
|
847
|
-
this.pendingEventsBuffer = [], t.forEach((
|
|
848
|
-
this.track(
|
|
850
|
+
this.pendingEventsBuffer = [], t.forEach((s) => {
|
|
851
|
+
this.track(s);
|
|
849
852
|
});
|
|
850
853
|
}
|
|
851
854
|
clearSendInterval() {
|
|
@@ -854,7 +857,7 @@ class ct extends f {
|
|
|
854
857
|
flushEvents(e) {
|
|
855
858
|
if (this.eventsQueue.length === 0)
|
|
856
859
|
return e ? !0 : Promise.resolve(!0);
|
|
857
|
-
const t = this.buildEventsPayload(),
|
|
860
|
+
const t = this.buildEventsPayload(), s = [...this.eventsQueue], n = s.map((i) => i.id);
|
|
858
861
|
if (e) {
|
|
859
862
|
const i = this.dataSender.sendEventsQueueSync(t);
|
|
860
863
|
return i && (this.removeProcessedEvents(n), this.clearSendInterval(), this.emitEventsQueue(t)), i;
|
|
@@ -865,7 +868,7 @@ class ct extends f {
|
|
|
865
868
|
},
|
|
866
869
|
onFailure: () => {
|
|
867
870
|
o("warn", "Async flush failed", {
|
|
868
|
-
data: { eventCount:
|
|
871
|
+
data: { eventCount: s.length }
|
|
869
872
|
});
|
|
870
873
|
}
|
|
871
874
|
});
|
|
@@ -873,10 +876,10 @@ class ct extends f {
|
|
|
873
876
|
async sendEventsQueue() {
|
|
874
877
|
if (!this.get("sessionId") || this.eventsQueue.length === 0)
|
|
875
878
|
return;
|
|
876
|
-
const e = this.buildEventsPayload(), t = [...this.eventsQueue],
|
|
879
|
+
const e = this.buildEventsPayload(), t = [...this.eventsQueue], s = t.map((n) => n.id);
|
|
877
880
|
await this.dataSender.sendEventsQueue(e, {
|
|
878
881
|
onSuccess: () => {
|
|
879
|
-
this.removeProcessedEvents(
|
|
882
|
+
this.removeProcessedEvents(s), this.emitEventsQueue(e);
|
|
880
883
|
},
|
|
881
884
|
onFailure: async () => {
|
|
882
885
|
o("warn", "Events send failed, keeping in queue", {
|
|
@@ -891,21 +894,21 @@ class ct extends f {
|
|
|
891
894
|
const i = this.createEventSignature(n);
|
|
892
895
|
e.has(i) || t.push(i), e.set(i, n);
|
|
893
896
|
}
|
|
894
|
-
const
|
|
897
|
+
const s = t.map((n) => e.get(n)).filter((n) => !!n).sort((n, i) => n.timestamp - i.timestamp);
|
|
895
898
|
return {
|
|
896
899
|
user_id: this.get("userId"),
|
|
897
900
|
session_id: this.get("sessionId"),
|
|
898
901
|
device: this.get("device"),
|
|
899
|
-
events:
|
|
902
|
+
events: s,
|
|
900
903
|
...this.get("config")?.globalMetadata && { global_metadata: this.get("config")?.globalMetadata }
|
|
901
904
|
};
|
|
902
905
|
}
|
|
903
906
|
buildEventPayload(e) {
|
|
904
|
-
const t = e.type === d.SESSION_START,
|
|
907
|
+
const t = e.type === d.SESSION_START, s = e.page_url ?? this.get("pageUrl");
|
|
905
908
|
return {
|
|
906
909
|
id: Xe(),
|
|
907
910
|
type: e.type,
|
|
908
|
-
page_url:
|
|
911
|
+
page_url: s,
|
|
909
912
|
timestamp: Date.now(),
|
|
910
913
|
...t && { referrer: document.referrer || "Direct" },
|
|
911
914
|
...e.from_page_url && { from_page_url: e.from_page_url },
|
|
@@ -919,14 +922,14 @@ class ct extends f {
|
|
|
919
922
|
};
|
|
920
923
|
}
|
|
921
924
|
isDuplicateEvent(e) {
|
|
922
|
-
const t = Date.now(),
|
|
923
|
-
return this.lastEventFingerprint ===
|
|
925
|
+
const t = Date.now(), s = this.createEventFingerprint(e);
|
|
926
|
+
return this.lastEventFingerprint === s && t - this.lastEventTime < 500 ? !0 : (this.lastEventFingerprint = s, this.lastEventTime = t, !1);
|
|
924
927
|
}
|
|
925
928
|
createEventFingerprint(e) {
|
|
926
929
|
let t = `${e.type}_${e.page_url}`;
|
|
927
930
|
if (e.click_data) {
|
|
928
|
-
const
|
|
929
|
-
t += `_click_${
|
|
931
|
+
const s = Math.round((e.click_data.x || 0) / 10) * 10, n = Math.round((e.click_data.y || 0) / 10) * 10;
|
|
932
|
+
t += `_click_${s}_${n}`;
|
|
930
933
|
}
|
|
931
934
|
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;
|
|
932
935
|
}
|
|
@@ -937,13 +940,13 @@ class ct extends f {
|
|
|
937
940
|
if (this.eventsQueue.push(e), this.emitEvent(e), this.eventsQueue.length > 100) {
|
|
938
941
|
const t = this.eventsQueue.findIndex(
|
|
939
942
|
(n) => n.type !== d.SESSION_START && n.type !== d.SESSION_END
|
|
940
|
-
),
|
|
943
|
+
), s = t >= 0 ? this.eventsQueue.splice(t, 1)[0] : this.eventsQueue.shift();
|
|
941
944
|
o("warn", "Event queue overflow, oldest non-critical event removed", {
|
|
942
945
|
data: {
|
|
943
946
|
maxLength: 100,
|
|
944
947
|
currentLength: this.eventsQueue.length,
|
|
945
|
-
removedEventType:
|
|
946
|
-
wasCritical:
|
|
948
|
+
removedEventType: s?.type,
|
|
949
|
+
wasCritical: s?.type === d.SESSION_START || s?.type === d.SESSION_END
|
|
947
950
|
}
|
|
948
951
|
});
|
|
949
952
|
}
|
|
@@ -971,7 +974,7 @@ class ct extends f {
|
|
|
971
974
|
}
|
|
972
975
|
removeProcessedEvents(e) {
|
|
973
976
|
const t = new Set(e);
|
|
974
|
-
this.eventsQueue = this.eventsQueue.filter((
|
|
977
|
+
this.eventsQueue = this.eventsQueue.filter((s) => !t.has(s.id));
|
|
975
978
|
}
|
|
976
979
|
emitEvent(e) {
|
|
977
980
|
this.emitter && this.emitter.emit(X.EVENT, e);
|
|
@@ -980,7 +983,7 @@ class ct extends f {
|
|
|
980
983
|
this.emitter && this.emitter.emit(X.QUEUE, e);
|
|
981
984
|
}
|
|
982
985
|
}
|
|
983
|
-
class
|
|
986
|
+
class ct {
|
|
984
987
|
/**
|
|
985
988
|
* Gets or creates a unique user ID for the given project.
|
|
986
989
|
* The user ID is persisted in localStorage and reused across sessions.
|
|
@@ -990,9 +993,9 @@ class lt {
|
|
|
990
993
|
* @returns Persistent unique user ID
|
|
991
994
|
*/
|
|
992
995
|
static getId(e) {
|
|
993
|
-
const t = xe,
|
|
994
|
-
if (
|
|
995
|
-
return
|
|
996
|
+
const t = xe, s = e.getItem(t);
|
|
997
|
+
if (s)
|
|
998
|
+
return s;
|
|
996
999
|
const n = je();
|
|
997
1000
|
return e.setItem(t, n), n;
|
|
998
1001
|
}
|
|
@@ -1007,8 +1010,8 @@ class ut extends f {
|
|
|
1007
1010
|
visibilityChangeHandler = null;
|
|
1008
1011
|
beforeUnloadHandler = null;
|
|
1009
1012
|
isTracking = !1;
|
|
1010
|
-
constructor(e, t,
|
|
1011
|
-
super(), this.storageManager = e, this.eventManager = t, this.projectId =
|
|
1013
|
+
constructor(e, t, s) {
|
|
1014
|
+
super(), this.storageManager = e, this.eventManager = t, this.projectId = s;
|
|
1012
1015
|
}
|
|
1013
1016
|
initCrossTabSync() {
|
|
1014
1017
|
if (typeof BroadcastChannel > "u") {
|
|
@@ -1017,9 +1020,9 @@ class ut extends f {
|
|
|
1017
1020
|
}
|
|
1018
1021
|
const e = this.getProjectId();
|
|
1019
1022
|
this.broadcastChannel = new BroadcastChannel(Ge(e)), this.broadcastChannel.onmessage = (t) => {
|
|
1020
|
-
const { action:
|
|
1023
|
+
const { action: s, sessionId: n, timestamp: i, projectId: a } = t.data ?? {};
|
|
1021
1024
|
if (a === e) {
|
|
1022
|
-
if (
|
|
1025
|
+
if (s === "session_end") {
|
|
1023
1026
|
this.resetSessionState();
|
|
1024
1027
|
return;
|
|
1025
1028
|
}
|
|
@@ -1069,8 +1072,8 @@ class ut extends f {
|
|
|
1069
1072
|
if (!t)
|
|
1070
1073
|
return null;
|
|
1071
1074
|
try {
|
|
1072
|
-
const
|
|
1073
|
-
return !
|
|
1075
|
+
const s = JSON.parse(t);
|
|
1076
|
+
return !s.id || typeof s.lastActivity != "number" ? null : s;
|
|
1074
1077
|
} catch {
|
|
1075
1078
|
return this.storageManager.removeItem(e), null;
|
|
1076
1079
|
}
|
|
@@ -1090,10 +1093,10 @@ class ut extends f {
|
|
|
1090
1093
|
o("warn", "Session tracking already active");
|
|
1091
1094
|
return;
|
|
1092
1095
|
}
|
|
1093
|
-
const e = this.recoverSession(), t = e ?? this.generateSessionId(),
|
|
1096
|
+
const e = this.recoverSession(), t = e ?? this.generateSessionId(), s = !!e;
|
|
1094
1097
|
this.isTracking = !0;
|
|
1095
1098
|
try {
|
|
1096
|
-
this.set("sessionId", t), this.persistSession(t),
|
|
1099
|
+
this.set("sessionId", t), this.persistSession(t), s || this.eventManager.track({
|
|
1097
1100
|
type: d.SESSION_START
|
|
1098
1101
|
}), this.initCrossTabSync(), this.shareSession(t), this.setupSessionTimeout(), this.setupActivityListeners(), this.setupLifecycleListeners();
|
|
1099
1102
|
} catch (n) {
|
|
@@ -1144,17 +1147,17 @@ class ut extends f {
|
|
|
1144
1147
|
type: d.SESSION_END,
|
|
1145
1148
|
session_end_reason: e
|
|
1146
1149
|
});
|
|
1147
|
-
const
|
|
1150
|
+
const s = () => {
|
|
1148
1151
|
this.broadcastSessionEnd(t, e), this.resetSessionState(e);
|
|
1149
1152
|
};
|
|
1150
1153
|
if (this.eventManager.flushImmediatelySync()) {
|
|
1151
|
-
|
|
1154
|
+
s();
|
|
1152
1155
|
return;
|
|
1153
1156
|
}
|
|
1154
1157
|
try {
|
|
1155
|
-
await this.eventManager.flushImmediately(),
|
|
1158
|
+
await this.eventManager.flushImmediately(), s();
|
|
1156
1159
|
} catch (i) {
|
|
1157
|
-
o("warn", "Async flush failed during session end", { error: i }),
|
|
1160
|
+
o("warn", "Async flush failed during session end", { error: i }), s();
|
|
1158
1161
|
}
|
|
1159
1162
|
}
|
|
1160
1163
|
resetSessionState(e) {
|
|
@@ -1182,12 +1185,12 @@ class dt extends f {
|
|
|
1182
1185
|
o("warn", "Cannot start tracking on destroyed handler");
|
|
1183
1186
|
return;
|
|
1184
1187
|
}
|
|
1185
|
-
const e = this.get("config"), t = e?.integrations?.tracelog?.projectId ?? e?.integrations?.custom?.
|
|
1188
|
+
const e = this.get("config"), t = e?.integrations?.tracelog?.projectId ?? e?.integrations?.custom?.collectApiUrl ?? "default";
|
|
1186
1189
|
if (!t)
|
|
1187
1190
|
throw new Error("Cannot start session tracking: config not available");
|
|
1188
1191
|
try {
|
|
1189
1192
|
this.sessionManager = new ut(this.storageManager, this.eventManager, t), await this.sessionManager.startTracking(), this.eventManager.flushPendingEvents();
|
|
1190
|
-
} catch (
|
|
1193
|
+
} catch (s) {
|
|
1191
1194
|
if (this.sessionManager) {
|
|
1192
1195
|
try {
|
|
1193
1196
|
this.sessionManager.destroy();
|
|
@@ -1195,7 +1198,7 @@ class dt extends f {
|
|
|
1195
1198
|
}
|
|
1196
1199
|
this.sessionManager = null;
|
|
1197
1200
|
}
|
|
1198
|
-
throw o("error", "Failed to start session tracking", { error:
|
|
1201
|
+
throw o("error", "Failed to start session tracking", { error: s }), s;
|
|
1199
1202
|
}
|
|
1200
1203
|
}
|
|
1201
1204
|
isActive() {
|
|
@@ -1227,8 +1230,8 @@ class ht extends f {
|
|
|
1227
1230
|
}
|
|
1228
1231
|
patchHistory(e) {
|
|
1229
1232
|
const t = window.history[e];
|
|
1230
|
-
e === "pushState" && !this.originalPushState ? this.originalPushState = t : e === "replaceState" && !this.originalReplaceState && (this.originalReplaceState = t), window.history[e] = (...
|
|
1231
|
-
t.apply(window.history,
|
|
1233
|
+
e === "pushState" && !this.originalPushState ? this.originalPushState = t : e === "replaceState" && !this.originalReplaceState && (this.originalReplaceState = t), window.history[e] = (...s) => {
|
|
1234
|
+
t.apply(window.history, s), this.trackCurrentPage();
|
|
1232
1235
|
};
|
|
1233
1236
|
}
|
|
1234
1237
|
trackCurrentPage = async () => {
|
|
@@ -1236,13 +1239,13 @@ class ht extends f {
|
|
|
1236
1239
|
if (this.get("pageUrl") === t)
|
|
1237
1240
|
return;
|
|
1238
1241
|
this.onTrack();
|
|
1239
|
-
const
|
|
1242
|
+
const s = this.get("pageUrl");
|
|
1240
1243
|
this.set("pageUrl", t);
|
|
1241
1244
|
const n = this.extractPageViewData();
|
|
1242
1245
|
this.eventManager.track({
|
|
1243
1246
|
type: d.PAGE_VIEW,
|
|
1244
1247
|
page_url: this.get("pageUrl"),
|
|
1245
|
-
from_page_url:
|
|
1248
|
+
from_page_url: s,
|
|
1246
1249
|
...n && { page_view: n }
|
|
1247
1250
|
});
|
|
1248
1251
|
};
|
|
@@ -1255,13 +1258,13 @@ class ht extends f {
|
|
|
1255
1258
|
}), this.onTrack();
|
|
1256
1259
|
}
|
|
1257
1260
|
extractPageViewData() {
|
|
1258
|
-
const { pathname: e, search: t, hash:
|
|
1259
|
-
return !n && !i && !e && !t && !
|
|
1261
|
+
const { pathname: e, search: t, hash: s } = window.location, { referrer: n } = document, { title: i } = document;
|
|
1262
|
+
return !n && !i && !e && !t && !s ? void 0 : {
|
|
1260
1263
|
...n && { referrer: n },
|
|
1261
1264
|
...i && { title: i },
|
|
1262
1265
|
...e && { pathname: e },
|
|
1263
1266
|
...t && { search: t },
|
|
1264
|
-
...
|
|
1267
|
+
...s && { hash: s }
|
|
1265
1268
|
};
|
|
1266
1269
|
}
|
|
1267
1270
|
}
|
|
@@ -1273,12 +1276,12 @@ class ft extends f {
|
|
|
1273
1276
|
}
|
|
1274
1277
|
startTracking() {
|
|
1275
1278
|
this.clickHandler || (this.clickHandler = (e) => {
|
|
1276
|
-
const t = e,
|
|
1279
|
+
const t = e, s = t.target, n = typeof HTMLElement < "u" && s instanceof HTMLElement ? s : typeof HTMLElement < "u" && s instanceof Node && s.parentElement instanceof HTMLElement ? s.parentElement : null;
|
|
1277
1280
|
if (!n) {
|
|
1278
1281
|
o("warn", "Click target not found or not an element");
|
|
1279
1282
|
return;
|
|
1280
1283
|
}
|
|
1281
|
-
const i = this.findTrackingElement(n), a = this.getRelevantClickElement(n),
|
|
1284
|
+
const i = this.findTrackingElement(n), a = this.getRelevantClickElement(n), l = this.calculateClickCoordinates(t, n);
|
|
1282
1285
|
if (i) {
|
|
1283
1286
|
const u = this.extractTrackingData(i);
|
|
1284
1287
|
if (u) {
|
|
@@ -1292,10 +1295,10 @@ class ft extends f {
|
|
|
1292
1295
|
});
|
|
1293
1296
|
}
|
|
1294
1297
|
}
|
|
1295
|
-
const
|
|
1298
|
+
const c = this.generateClickData(n, a, l);
|
|
1296
1299
|
this.eventManager.track({
|
|
1297
1300
|
type: d.CLICK,
|
|
1298
|
-
click_data:
|
|
1301
|
+
click_data: c
|
|
1299
1302
|
});
|
|
1300
1303
|
}, window.addEventListener("click", this.clickHandler, !0));
|
|
1301
1304
|
}
|
|
@@ -1310,11 +1313,11 @@ class ft extends f {
|
|
|
1310
1313
|
try {
|
|
1311
1314
|
if (e.matches(t))
|
|
1312
1315
|
return e;
|
|
1313
|
-
const
|
|
1314
|
-
if (
|
|
1315
|
-
return
|
|
1316
|
-
} catch (
|
|
1317
|
-
o("warn", "Invalid selector in element search", { error:
|
|
1316
|
+
const s = e.closest(t);
|
|
1317
|
+
if (s)
|
|
1318
|
+
return s;
|
|
1319
|
+
} catch (s) {
|
|
1320
|
+
o("warn", "Invalid selector in element search", { error: s, data: { selector: t } });
|
|
1318
1321
|
continue;
|
|
1319
1322
|
}
|
|
1320
1323
|
return e;
|
|
@@ -1323,29 +1326,29 @@ class ft extends f {
|
|
|
1323
1326
|
return Math.max(0, Math.min(1, Number(e.toFixed(3))));
|
|
1324
1327
|
}
|
|
1325
1328
|
calculateClickCoordinates(e, t) {
|
|
1326
|
-
const
|
|
1327
|
-
return { x: n, y: i, relativeX: a, relativeY:
|
|
1329
|
+
const s = t.getBoundingClientRect(), n = e.clientX, i = e.clientY, a = s.width > 0 ? this.clamp((n - s.left) / s.width) : 0, l = s.height > 0 ? this.clamp((i - s.top) / s.height) : 0;
|
|
1330
|
+
return { x: n, y: i, relativeX: a, relativeY: l };
|
|
1328
1331
|
}
|
|
1329
1332
|
extractTrackingData(e) {
|
|
1330
|
-
const t = e.getAttribute(`${O}-name`),
|
|
1333
|
+
const t = e.getAttribute(`${O}-name`), s = e.getAttribute(`${O}-value`);
|
|
1331
1334
|
if (t)
|
|
1332
1335
|
return {
|
|
1333
1336
|
element: e,
|
|
1334
1337
|
name: t,
|
|
1335
|
-
...
|
|
1338
|
+
...s && { value: s }
|
|
1336
1339
|
};
|
|
1337
1340
|
}
|
|
1338
|
-
generateClickData(e, t,
|
|
1339
|
-
const { x: n, y: i, relativeX: a, relativeY:
|
|
1341
|
+
generateClickData(e, t, s) {
|
|
1342
|
+
const { x: n, y: i, relativeX: a, relativeY: l } = s, c = this.getRelevantText(e, t), u = this.extractElementAttributes(t);
|
|
1340
1343
|
return {
|
|
1341
1344
|
x: n,
|
|
1342
1345
|
y: i,
|
|
1343
1346
|
relativeX: a,
|
|
1344
|
-
relativeY:
|
|
1347
|
+
relativeY: l,
|
|
1345
1348
|
tag: t.tagName.toLowerCase(),
|
|
1346
1349
|
...t.id && { id: t.id },
|
|
1347
1350
|
...t.className && { class: t.className },
|
|
1348
|
-
...
|
|
1351
|
+
...c && { text: c },
|
|
1349
1352
|
...u.href && { href: u.href },
|
|
1350
1353
|
...u.title && { title: u.title },
|
|
1351
1354
|
...u.alt && { alt: u.alt },
|
|
@@ -1355,8 +1358,8 @@ class ft extends f {
|
|
|
1355
1358
|
};
|
|
1356
1359
|
}
|
|
1357
1360
|
getRelevantText(e, t) {
|
|
1358
|
-
const
|
|
1359
|
-
return !
|
|
1361
|
+
const s = e.textContent?.trim() ?? "", n = t.textContent?.trim() ?? "";
|
|
1362
|
+
return !s && !n ? "" : s && s.length <= 255 ? s : n.length <= 255 ? n : n.slice(0, 252) + "...";
|
|
1360
1363
|
}
|
|
1361
1364
|
extractElementAttributes(e) {
|
|
1362
1365
|
const t = [
|
|
@@ -1370,12 +1373,12 @@ class ft extends f {
|
|
|
1370
1373
|
"name",
|
|
1371
1374
|
"alt",
|
|
1372
1375
|
"role"
|
|
1373
|
-
],
|
|
1376
|
+
], s = {};
|
|
1374
1377
|
for (const n of t) {
|
|
1375
1378
|
const i = e.getAttribute(n);
|
|
1376
|
-
i && (
|
|
1379
|
+
i && (s[n] = i);
|
|
1377
1380
|
}
|
|
1378
|
-
return
|
|
1381
|
+
return s;
|
|
1379
1382
|
}
|
|
1380
1383
|
createCustomEventData(e) {
|
|
1381
1384
|
return {
|
|
@@ -1405,9 +1408,11 @@ class gt extends f {
|
|
|
1405
1408
|
this.containers.length = 0, this.set("scrollEventCount", 0), this.limitWarningLogged = !1;
|
|
1406
1409
|
}
|
|
1407
1410
|
trySetupContainers(e, t) {
|
|
1408
|
-
const
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
+
const s = e.map((n) => this.safeQuerySelector(n)).filter(
|
|
1412
|
+
(n) => n != null && typeof HTMLElement < "u" && n instanceof HTMLElement
|
|
1413
|
+
);
|
|
1414
|
+
if (s.length > 0) {
|
|
1415
|
+
for (const n of s)
|
|
1411
1416
|
this.containers.some((a) => a.element === n) || this.setupScrollContainer(n);
|
|
1412
1417
|
return;
|
|
1413
1418
|
}
|
|
@@ -1429,11 +1434,11 @@ class gt extends f {
|
|
|
1429
1434
|
}
|
|
1430
1435
|
n.debounceTimer = null;
|
|
1431
1436
|
}, 250));
|
|
1432
|
-
},
|
|
1437
|
+
}, s = this.getScrollTop(e), n = {
|
|
1433
1438
|
element: e,
|
|
1434
|
-
lastScrollPos:
|
|
1439
|
+
lastScrollPos: s,
|
|
1435
1440
|
lastDepth: this.calculateScrollDepth(
|
|
1436
|
-
|
|
1441
|
+
s,
|
|
1437
1442
|
this.getScrollHeight(e),
|
|
1438
1443
|
this.getViewportHeight(e)
|
|
1439
1444
|
),
|
|
@@ -1444,18 +1449,18 @@ class gt extends f {
|
|
|
1444
1449
|
};
|
|
1445
1450
|
this.containers.push(n), e instanceof Window ? window.addEventListener("scroll", t, { passive: !0 }) : e.addEventListener("scroll", t, { passive: !0 });
|
|
1446
1451
|
}
|
|
1447
|
-
processScrollEvent(e, t,
|
|
1448
|
-
if (!this.shouldEmitScrollEvent(e, t,
|
|
1452
|
+
processScrollEvent(e, t, s) {
|
|
1453
|
+
if (!this.shouldEmitScrollEvent(e, t, s))
|
|
1449
1454
|
return;
|
|
1450
|
-
e.lastEventTime =
|
|
1455
|
+
e.lastEventTime = s, e.lastDepth = t.depth, e.lastDirection = t.direction;
|
|
1451
1456
|
const n = this.get("scrollEventCount") ?? 0;
|
|
1452
1457
|
this.set("scrollEventCount", n + 1), this.eventManager.track({
|
|
1453
1458
|
type: d.SCROLL,
|
|
1454
1459
|
scroll_data: t
|
|
1455
1460
|
});
|
|
1456
1461
|
}
|
|
1457
|
-
shouldEmitScrollEvent(e, t,
|
|
1458
|
-
return this.hasReachedSessionLimit() ? (this.logLimitOnce(), !1) : !(!this.hasElapsedMinimumInterval(e,
|
|
1462
|
+
shouldEmitScrollEvent(e, t, s) {
|
|
1463
|
+
return this.hasReachedSessionLimit() ? (this.logLimitOnce(), !1) : !(!this.hasElapsedMinimumInterval(e, s) || !this.hasSignificantDepthChange(e, t.depth));
|
|
1459
1464
|
}
|
|
1460
1465
|
hasReachedSessionLimit() {
|
|
1461
1466
|
return (this.get("scrollEventCount") ?? 0) >= this.maxEventsPerSession;
|
|
@@ -1483,18 +1488,18 @@ class gt extends f {
|
|
|
1483
1488
|
getScrollDirection(e, t) {
|
|
1484
1489
|
return e > t ? D.DOWN : D.UP;
|
|
1485
1490
|
}
|
|
1486
|
-
calculateScrollDepth(e, t,
|
|
1487
|
-
if (t <=
|
|
1491
|
+
calculateScrollDepth(e, t, s) {
|
|
1492
|
+
if (t <= s)
|
|
1488
1493
|
return 0;
|
|
1489
|
-
const n = t -
|
|
1494
|
+
const n = t - s;
|
|
1490
1495
|
return Math.min(100, Math.max(0, Math.floor(e / n * 100)));
|
|
1491
1496
|
}
|
|
1492
1497
|
calculateScrollData(e) {
|
|
1493
|
-
const { element: t, lastScrollPos:
|
|
1494
|
-
if (Math.abs(n -
|
|
1498
|
+
const { element: t, lastScrollPos: s } = e, n = this.getScrollTop(t);
|
|
1499
|
+
if (Math.abs(n - s) < 10 || t === window && !this.isWindowScrollable())
|
|
1495
1500
|
return null;
|
|
1496
|
-
const a = this.getViewportHeight(t),
|
|
1497
|
-
return e.lastScrollPos = n, { depth: u, direction:
|
|
1501
|
+
const a = this.getViewportHeight(t), l = this.getScrollHeight(t), c = this.getScrollDirection(n, s), u = this.calculateScrollDepth(n, l, a);
|
|
1502
|
+
return e.lastScrollPos = n, { depth: u, direction: c };
|
|
1498
1503
|
}
|
|
1499
1504
|
getScrollTop(e) {
|
|
1500
1505
|
return e instanceof Window ? window.scrollY : e.scrollTop;
|
|
@@ -1506,8 +1511,8 @@ class gt extends f {
|
|
|
1506
1511
|
return e instanceof Window ? document.documentElement.scrollHeight : e.scrollHeight;
|
|
1507
1512
|
}
|
|
1508
1513
|
isElementScrollable(e) {
|
|
1509
|
-
const t = getComputedStyle(e),
|
|
1510
|
-
return
|
|
1514
|
+
const t = getComputedStyle(e), s = t.overflowY === "auto" || t.overflowY === "scroll" || t.overflowX === "auto" || t.overflowX === "scroll" || t.overflow === "auto" || t.overflow === "scroll", n = e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth;
|
|
1515
|
+
return s && n;
|
|
1511
1516
|
}
|
|
1512
1517
|
safeQuerySelector(e) {
|
|
1513
1518
|
try {
|
|
@@ -1534,17 +1539,17 @@ class St extends f {
|
|
|
1534
1539
|
return;
|
|
1535
1540
|
}
|
|
1536
1541
|
await this.loadScript(e), this.configureGtag(e, t), this.isInitialized = !0;
|
|
1537
|
-
} catch (
|
|
1538
|
-
o("error", "Google Analytics initialization failed", { error:
|
|
1542
|
+
} catch (s) {
|
|
1543
|
+
o("error", "Google Analytics initialization failed", { error: s });
|
|
1539
1544
|
}
|
|
1540
1545
|
}
|
|
1541
1546
|
trackEvent(e, t) {
|
|
1542
1547
|
if (!(!e?.trim() || !this.isInitialized || typeof window.gtag != "function"))
|
|
1543
1548
|
try {
|
|
1544
|
-
const
|
|
1545
|
-
window.gtag("event", e,
|
|
1546
|
-
} catch (
|
|
1547
|
-
o("error", "Google Analytics event tracking failed", { error:
|
|
1549
|
+
const s = Array.isArray(t) ? { items: t } : t;
|
|
1550
|
+
window.gtag("event", e, s);
|
|
1551
|
+
} catch (s) {
|
|
1552
|
+
o("error", "Google Analytics event tracking failed", { error: s });
|
|
1548
1553
|
}
|
|
1549
1554
|
}
|
|
1550
1555
|
cleanup() {
|
|
@@ -1556,21 +1561,21 @@ class St extends f {
|
|
|
1556
1561
|
return document.getElementById("tracelog-ga-script") ? !0 : !!document.querySelector('script[src*="googletagmanager.com/gtag/js"]');
|
|
1557
1562
|
}
|
|
1558
1563
|
async loadScript(e) {
|
|
1559
|
-
return new Promise((t,
|
|
1564
|
+
return new Promise((t, s) => {
|
|
1560
1565
|
const n = document.createElement("script");
|
|
1561
|
-
n.id = "tracelog-ga-script", n.async = !0, n.src = `https://www.googletagmanager.com/gtag/js?id=${e}`, n.onload = () => t(), n.onerror = () =>
|
|
1566
|
+
n.id = "tracelog-ga-script", n.async = !0, n.src = `https://www.googletagmanager.com/gtag/js?id=${e}`, n.onload = () => t(), n.onerror = () => s(new Error("Failed to load Google Analytics script")), document.head.appendChild(n);
|
|
1562
1567
|
});
|
|
1563
1568
|
}
|
|
1564
1569
|
configureGtag(e, t) {
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1570
|
+
const s = document.createElement("script");
|
|
1571
|
+
s.innerHTML = `
|
|
1567
1572
|
window.dataLayer = window.dataLayer || [];
|
|
1568
1573
|
function gtag(){dataLayer.push(arguments);}
|
|
1569
1574
|
gtag('js', new Date());
|
|
1570
1575
|
gtag('config', '${e}', {
|
|
1571
1576
|
'user_id': '${t}'
|
|
1572
1577
|
});
|
|
1573
|
-
`, document.head.appendChild(
|
|
1578
|
+
`, document.head.appendChild(s);
|
|
1574
1579
|
}
|
|
1575
1580
|
}
|
|
1576
1581
|
class Et {
|
|
@@ -1602,8 +1607,8 @@ class Et {
|
|
|
1602
1607
|
this.storage.setItem(e, t);
|
|
1603
1608
|
return;
|
|
1604
1609
|
}
|
|
1605
|
-
} catch (
|
|
1606
|
-
if (
|
|
1610
|
+
} catch (s) {
|
|
1611
|
+
if (s instanceof DOMException && s.name === "QuotaExceededError")
|
|
1607
1612
|
if (this.hasQuotaExceededError = !0, o("warn", "localStorage quota exceeded, attempting cleanup", {
|
|
1608
1613
|
data: { key: e, valueSize: t.length }
|
|
1609
1614
|
}), this.cleanupOldData())
|
|
@@ -1620,7 +1625,7 @@ class Et {
|
|
|
1620
1625
|
}
|
|
1621
1626
|
else
|
|
1622
1627
|
o("error", "localStorage quota exceeded and no data to cleanup - data will not persist", {
|
|
1623
|
-
error:
|
|
1628
|
+
error: s,
|
|
1624
1629
|
data: { key: e, valueSize: t.length }
|
|
1625
1630
|
});
|
|
1626
1631
|
}
|
|
@@ -1646,8 +1651,8 @@ class Et {
|
|
|
1646
1651
|
try {
|
|
1647
1652
|
const e = [];
|
|
1648
1653
|
for (let t = 0; t < this.storage.length; t++) {
|
|
1649
|
-
const
|
|
1650
|
-
|
|
1654
|
+
const s = this.storage.key(t);
|
|
1655
|
+
s?.startsWith("tracelog_") && e.push(s);
|
|
1651
1656
|
}
|
|
1652
1657
|
e.forEach((t) => this.storage.removeItem(t)), this.fallbackStorage.clear();
|
|
1653
1658
|
} catch (e) {
|
|
@@ -1687,7 +1692,7 @@ class Et {
|
|
|
1687
1692
|
} catch {
|
|
1688
1693
|
}
|
|
1689
1694
|
}), !0;
|
|
1690
|
-
const
|
|
1695
|
+
const s = ["tracelog_session_", "tracelog_user_id", "tracelog_device_id", "tracelog_config"], n = e.filter((i) => !s.some((a) => i.startsWith(a)));
|
|
1691
1696
|
return n.length > 0 ? (n.slice(0, 5).forEach((a) => {
|
|
1692
1697
|
try {
|
|
1693
1698
|
this.storage.removeItem(a);
|
|
@@ -1705,8 +1710,8 @@ class Et {
|
|
|
1705
1710
|
if (typeof window > "u")
|
|
1706
1711
|
return null;
|
|
1707
1712
|
try {
|
|
1708
|
-
const t = e === "localStorage" ? window.localStorage : window.sessionStorage,
|
|
1709
|
-
return t.setItem(
|
|
1713
|
+
const t = e === "localStorage" ? window.localStorage : window.sessionStorage, s = "__tracelog_test__";
|
|
1714
|
+
return t.setItem(s, "test"), t.removeItem(s), t;
|
|
1710
1715
|
} catch {
|
|
1711
1716
|
return null;
|
|
1712
1717
|
}
|
|
@@ -1731,9 +1736,9 @@ class Et {
|
|
|
1731
1736
|
this.sessionStorageRef.setItem(e, t);
|
|
1732
1737
|
return;
|
|
1733
1738
|
}
|
|
1734
|
-
} catch (
|
|
1735
|
-
|
|
1736
|
-
error:
|
|
1739
|
+
} catch (s) {
|
|
1740
|
+
s instanceof DOMException && s.name === "QuotaExceededError" && o("error", "sessionStorage quota exceeded - data will not persist", {
|
|
1741
|
+
error: s,
|
|
1737
1742
|
data: { key: e, valueSize: t.length }
|
|
1738
1743
|
});
|
|
1739
1744
|
}
|
|
@@ -1765,16 +1770,16 @@ class mt extends f {
|
|
|
1765
1770
|
this.observers.forEach((e, t) => {
|
|
1766
1771
|
try {
|
|
1767
1772
|
e.disconnect();
|
|
1768
|
-
} catch (
|
|
1769
|
-
o("warn", "Failed to disconnect performance observer", { error:
|
|
1773
|
+
} catch (s) {
|
|
1774
|
+
o("warn", "Failed to disconnect performance observer", { error: s, data: { observerIndex: t } });
|
|
1770
1775
|
}
|
|
1771
1776
|
}), this.observers.length = 0, this.reportedByNav.clear();
|
|
1772
1777
|
}
|
|
1773
1778
|
observeWebVitalsFallback() {
|
|
1774
1779
|
this.reportTTFB(), this.safeObserve(
|
|
1775
1780
|
"largest-contentful-paint",
|
|
1776
|
-
(
|
|
1777
|
-
const n =
|
|
1781
|
+
(s) => {
|
|
1782
|
+
const n = s.getEntries(), i = n[n.length - 1];
|
|
1778
1783
|
i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(2)) });
|
|
1779
1784
|
},
|
|
1780
1785
|
{ type: "largest-contentful-paint", buffered: !0 },
|
|
@@ -1783,35 +1788,35 @@ class mt extends f {
|
|
|
1783
1788
|
let e = 0, t = this.getNavigationId();
|
|
1784
1789
|
this.safeObserve(
|
|
1785
1790
|
"layout-shift",
|
|
1786
|
-
(
|
|
1791
|
+
(s) => {
|
|
1787
1792
|
const n = this.getNavigationId();
|
|
1788
1793
|
n !== t && (e = 0, t = n);
|
|
1789
|
-
const i =
|
|
1794
|
+
const i = s.getEntries();
|
|
1790
1795
|
for (const a of i) {
|
|
1791
1796
|
if (a.hadRecentInput === !0)
|
|
1792
1797
|
continue;
|
|
1793
|
-
const
|
|
1794
|
-
e +=
|
|
1798
|
+
const l = typeof a.value == "number" ? a.value : 0;
|
|
1799
|
+
e += l;
|
|
1795
1800
|
}
|
|
1796
1801
|
this.sendVital({ type: "CLS", value: Number(e.toFixed(2)) });
|
|
1797
1802
|
},
|
|
1798
1803
|
{ type: "layout-shift", buffered: !0 }
|
|
1799
1804
|
), this.safeObserve(
|
|
1800
1805
|
"paint",
|
|
1801
|
-
(
|
|
1802
|
-
for (const n of
|
|
1806
|
+
(s) => {
|
|
1807
|
+
for (const n of s.getEntries())
|
|
1803
1808
|
n.name === "first-contentful-paint" && this.sendVital({ type: "FCP", value: Number(n.startTime.toFixed(2)) });
|
|
1804
1809
|
},
|
|
1805
1810
|
{ type: "paint", buffered: !0 },
|
|
1806
1811
|
!0
|
|
1807
1812
|
), this.safeObserve(
|
|
1808
1813
|
"event",
|
|
1809
|
-
(
|
|
1814
|
+
(s) => {
|
|
1810
1815
|
let n = 0;
|
|
1811
|
-
const i =
|
|
1816
|
+
const i = s.getEntries();
|
|
1812
1817
|
for (const a of i) {
|
|
1813
|
-
const
|
|
1814
|
-
n = Math.max(n,
|
|
1818
|
+
const l = (a.processingEnd ?? 0) - (a.startTime ?? 0);
|
|
1819
|
+
n = Math.max(n, l);
|
|
1815
1820
|
}
|
|
1816
1821
|
n > 0 && this.sendVital({ type: "INP", value: Number(n.toFixed(2)) });
|
|
1817
1822
|
},
|
|
@@ -1820,11 +1825,11 @@ class mt extends f {
|
|
|
1820
1825
|
}
|
|
1821
1826
|
async initWebVitals() {
|
|
1822
1827
|
try {
|
|
1823
|
-
const { onLCP: e, onCLS: t, onFCP:
|
|
1824
|
-
const u = Number(
|
|
1825
|
-
this.sendVital({ type:
|
|
1828
|
+
const { onLCP: e, onCLS: t, onFCP: s, onTTFB: n, onINP: i } = await Promise.resolve().then(() => Ht), a = (l) => (c) => {
|
|
1829
|
+
const u = Number(c.value.toFixed(2));
|
|
1830
|
+
this.sendVital({ type: l, value: u });
|
|
1826
1831
|
};
|
|
1827
|
-
e(a("LCP")), t(a("CLS")),
|
|
1832
|
+
e(a("LCP")), t(a("CLS")), s(a("FCP")), n(a("TTFB")), i(a("INP"));
|
|
1828
1833
|
} catch (e) {
|
|
1829
1834
|
o("warn", "Failed to load web-vitals library, using fallback", { error: e }), this.observeWebVitalsFallback();
|
|
1830
1835
|
}
|
|
@@ -1845,8 +1850,8 @@ class mt extends f {
|
|
|
1845
1850
|
"longtask",
|
|
1846
1851
|
(e) => {
|
|
1847
1852
|
const t = e.getEntries();
|
|
1848
|
-
for (const
|
|
1849
|
-
const n = Number(
|
|
1853
|
+
for (const s of t) {
|
|
1854
|
+
const n = Number(s.duration.toFixed(2)), i = Date.now();
|
|
1850
1855
|
i - this.lastLongTaskSentAt >= ze && (this.shouldSendVital("LONG_TASK", n) && this.trackWebVital("LONG_TASK", n), this.lastLongTaskSentAt = i);
|
|
1851
1856
|
}
|
|
1852
1857
|
},
|
|
@@ -1858,10 +1863,10 @@ class mt extends f {
|
|
|
1858
1863
|
return;
|
|
1859
1864
|
const t = this.getNavigationId();
|
|
1860
1865
|
if (t) {
|
|
1861
|
-
const
|
|
1862
|
-
if (
|
|
1866
|
+
const s = this.reportedByNav.get(t);
|
|
1867
|
+
if (s?.has(e.type))
|
|
1863
1868
|
return;
|
|
1864
|
-
|
|
1869
|
+
s ? s.add(e.type) : this.reportedByNav.set(t, /* @__PURE__ */ new Set([e.type]));
|
|
1865
1870
|
}
|
|
1866
1871
|
this.trackWebVital(e.type, e.value);
|
|
1867
1872
|
}
|
|
@@ -1883,8 +1888,8 @@ class mt extends f {
|
|
|
1883
1888
|
const e = performance.getEntriesByType("navigation")[0];
|
|
1884
1889
|
if (!e)
|
|
1885
1890
|
return null;
|
|
1886
|
-
const t = e.startTime || performance.now(),
|
|
1887
|
-
return `${t.toFixed(2)}_${window.location.pathname}_${
|
|
1891
|
+
const t = e.startTime || performance.now(), s = Math.random().toString(36).substr(2, 5);
|
|
1892
|
+
return `${t.toFixed(2)}_${window.location.pathname}_${s}`;
|
|
1888
1893
|
} catch (e) {
|
|
1889
1894
|
return o("warn", "Failed to get navigation ID", { error: e }), null;
|
|
1890
1895
|
}
|
|
@@ -1894,26 +1899,26 @@ class mt extends f {
|
|
|
1894
1899
|
const t = PerformanceObserver.supportedEntryTypes;
|
|
1895
1900
|
return !t || t.includes(e);
|
|
1896
1901
|
}
|
|
1897
|
-
safeObserve(e, t,
|
|
1902
|
+
safeObserve(e, t, s, n = !1) {
|
|
1898
1903
|
try {
|
|
1899
1904
|
if (!this.isObserverSupported(e))
|
|
1900
1905
|
return !1;
|
|
1901
|
-
const i = new PerformanceObserver((a,
|
|
1906
|
+
const i = new PerformanceObserver((a, l) => {
|
|
1902
1907
|
try {
|
|
1903
|
-
t(a,
|
|
1904
|
-
} catch (
|
|
1908
|
+
t(a, l);
|
|
1909
|
+
} catch (c) {
|
|
1905
1910
|
o("warn", "Observer callback failed", {
|
|
1906
|
-
error:
|
|
1911
|
+
error: c,
|
|
1907
1912
|
data: { type: e }
|
|
1908
1913
|
});
|
|
1909
1914
|
}
|
|
1910
1915
|
if (n)
|
|
1911
1916
|
try {
|
|
1912
|
-
|
|
1917
|
+
l.disconnect();
|
|
1913
1918
|
} catch {
|
|
1914
1919
|
}
|
|
1915
1920
|
});
|
|
1916
|
-
return i.observe(
|
|
1921
|
+
return i.observe(s ?? { type: e, buffered: !0 }), n || this.observers.push(i), !0;
|
|
1917
1922
|
} catch (i) {
|
|
1918
1923
|
return o("warn", "Failed to create performance observer", {
|
|
1919
1924
|
error: i,
|
|
@@ -1924,8 +1929,8 @@ class mt extends f {
|
|
|
1924
1929
|
shouldSendVital(e, t) {
|
|
1925
1930
|
if (typeof t != "number" || !Number.isFinite(t))
|
|
1926
1931
|
return o("warn", "Invalid web vital value", { data: { type: e, value: t } }), !1;
|
|
1927
|
-
const
|
|
1928
|
-
return !(typeof
|
|
1932
|
+
const s = this.vitalThresholds[e];
|
|
1933
|
+
return !(typeof s == "number" && t <= s);
|
|
1929
1934
|
}
|
|
1930
1935
|
}
|
|
1931
1936
|
class pt extends f {
|
|
@@ -1962,12 +1967,12 @@ class pt extends f {
|
|
|
1962
1967
|
handleRejection = (e) => {
|
|
1963
1968
|
if (!this.shouldSample())
|
|
1964
1969
|
return;
|
|
1965
|
-
const t = this.extractRejectionMessage(e.reason),
|
|
1966
|
-
this.shouldSuppressError(L.PROMISE_REJECTION,
|
|
1970
|
+
const t = this.extractRejectionMessage(e.reason), s = this.sanitize(t);
|
|
1971
|
+
this.shouldSuppressError(L.PROMISE_REJECTION, s) || this.eventManager.track({
|
|
1967
1972
|
type: d.ERROR,
|
|
1968
1973
|
error_data: {
|
|
1969
1974
|
type: L.PROMISE_REJECTION,
|
|
1970
|
-
message:
|
|
1975
|
+
message: s
|
|
1971
1976
|
}
|
|
1972
1977
|
});
|
|
1973
1978
|
};
|
|
@@ -1985,16 +1990,16 @@ class pt extends f {
|
|
|
1985
1990
|
}
|
|
1986
1991
|
}
|
|
1987
1992
|
sanitize(e) {
|
|
1988
|
-
let t = e.length >
|
|
1989
|
-
for (const
|
|
1990
|
-
const n = new RegExp(
|
|
1993
|
+
let t = e.length > ce ? e.slice(0, ce) + "..." : e;
|
|
1994
|
+
for (const s of Te) {
|
|
1995
|
+
const n = new RegExp(s.source, s.flags);
|
|
1991
1996
|
t = t.replace(n, "[REDACTED]");
|
|
1992
1997
|
}
|
|
1993
1998
|
return t;
|
|
1994
1999
|
}
|
|
1995
2000
|
shouldSuppressError(e, t) {
|
|
1996
|
-
const
|
|
1997
|
-
return i &&
|
|
2001
|
+
const s = Date.now(), n = `${e}:${t}`, i = this.recentErrors.get(n);
|
|
2002
|
+
return i && s - i < ue ? (this.recentErrors.set(n, s), !0) : (this.recentErrors.set(n, s), this.recentErrors.size > $e ? (this.recentErrors.clear(), this.recentErrors.set(n, s), !1) : (this.recentErrors.size > k && this.pruneOldErrors(), !1));
|
|
1998
2003
|
}
|
|
1999
2004
|
pruneOldErrors() {
|
|
2000
2005
|
const e = Date.now();
|
|
@@ -2002,8 +2007,8 @@ class pt extends f {
|
|
|
2002
2007
|
e - i > ue && this.recentErrors.delete(n);
|
|
2003
2008
|
if (this.recentErrors.size <= k)
|
|
2004
2009
|
return;
|
|
2005
|
-
const t = Array.from(this.recentErrors.entries()).sort((n, i) => n[1] - i[1]),
|
|
2006
|
-
for (let n = 0; n <
|
|
2010
|
+
const t = Array.from(this.recentErrors.entries()).sort((n, i) => n[1] - i[1]), s = this.recentErrors.size - k;
|
|
2011
|
+
for (let n = 0; n < s; n += 1) {
|
|
2007
2012
|
const i = t[n];
|
|
2008
2013
|
i && this.recentErrors.delete(i[0]);
|
|
2009
2014
|
}
|
|
@@ -2019,25 +2024,25 @@ class _t extends f {
|
|
|
2019
2024
|
get initialized() {
|
|
2020
2025
|
return this.isInitialized;
|
|
2021
2026
|
}
|
|
2022
|
-
async init(e) {
|
|
2027
|
+
async init(e = {}) {
|
|
2023
2028
|
if (!this.isInitialized) {
|
|
2024
2029
|
this.managers.storage = new Et();
|
|
2025
2030
|
try {
|
|
2026
|
-
this.setupState(e), await this.setupIntegrations(), this.managers.event = new
|
|
2031
|
+
this.setupState(e), await this.setupIntegrations(), this.managers.event = new lt(this.managers.storage, this.integrations.googleAnalytics, this.emitter), await this.initializeHandlers(), await this.managers.event.recoverPersistedEvents().catch((t) => {
|
|
2027
2032
|
o("warn", "Failed to recover persisted events", { error: t });
|
|
2028
2033
|
}), this.isInitialized = !0;
|
|
2029
2034
|
} catch (t) {
|
|
2030
2035
|
await this.destroy(!0);
|
|
2031
|
-
const
|
|
2032
|
-
throw new Error(`[TraceLog] TraceLog initialization failed: ${
|
|
2036
|
+
const s = t instanceof Error ? t.message : String(t);
|
|
2037
|
+
throw new Error(`[TraceLog] TraceLog initialization failed: ${s}`);
|
|
2033
2038
|
}
|
|
2034
2039
|
}
|
|
2035
2040
|
}
|
|
2036
2041
|
sendCustomEvent(e, t) {
|
|
2037
2042
|
if (!this.managers.event)
|
|
2038
2043
|
return;
|
|
2039
|
-
const { valid:
|
|
2040
|
-
if (!
|
|
2044
|
+
const { valid: s, error: n, sanitizedMetadata: i } = it(e, t);
|
|
2045
|
+
if (!s) {
|
|
2041
2046
|
if (this.get("mode") === R.QA)
|
|
2042
2047
|
throw new Error(`[TraceLog] Custom event "${e}" validation failed: ${n}`);
|
|
2043
2048
|
return;
|
|
@@ -2060,21 +2065,21 @@ class _t extends f {
|
|
|
2060
2065
|
if (!this.isInitialized && !e)
|
|
2061
2066
|
return;
|
|
2062
2067
|
this.integrations.googleAnalytics?.cleanup();
|
|
2063
|
-
const t = Object.values(this.handlers).filter(Boolean).map(async (
|
|
2068
|
+
const t = Object.values(this.handlers).filter(Boolean).map(async (s) => {
|
|
2064
2069
|
try {
|
|
2065
|
-
await
|
|
2070
|
+
await s.stopTracking();
|
|
2066
2071
|
} catch (n) {
|
|
2067
2072
|
o("warn", "Failed to stop tracking", { error: n });
|
|
2068
2073
|
}
|
|
2069
2074
|
});
|
|
2070
2075
|
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 = {};
|
|
2071
2076
|
}
|
|
2072
|
-
setupState(e) {
|
|
2077
|
+
setupState(e = {}) {
|
|
2073
2078
|
this.set("config", e);
|
|
2074
|
-
const t =
|
|
2079
|
+
const t = ct.getId(this.managers.storage);
|
|
2075
2080
|
this.set("userId", t);
|
|
2076
|
-
const
|
|
2077
|
-
this.set("
|
|
2081
|
+
const s = We(e);
|
|
2082
|
+
this.set("collectApiUrl", s);
|
|
2078
2083
|
const n = He();
|
|
2079
2084
|
this.set("device", n);
|
|
2080
2085
|
const i = Y(window.location.href, e.sensitiveQueryParams);
|
|
@@ -2107,30 +2112,30 @@ class _t extends f {
|
|
|
2107
2112
|
}
|
|
2108
2113
|
const I = [];
|
|
2109
2114
|
let h = null, w = !1, U = !1;
|
|
2110
|
-
const Tt = async (
|
|
2115
|
+
const Tt = async (r) => {
|
|
2111
2116
|
if (typeof window > "u" || typeof document > "u")
|
|
2112
2117
|
throw new Error("[TraceLog] This library can only be used in a browser environment");
|
|
2113
2118
|
if (!window.__traceLogDisabled && !h && !w) {
|
|
2114
2119
|
w = !0;
|
|
2115
2120
|
try {
|
|
2116
|
-
const e = et(
|
|
2121
|
+
const e = et(r ?? {}), t = new _t();
|
|
2117
2122
|
try {
|
|
2118
2123
|
I.forEach(({ event: i, callback: a }) => {
|
|
2119
2124
|
t.on(i, a);
|
|
2120
2125
|
}), I.length = 0;
|
|
2121
|
-
const
|
|
2126
|
+
const s = t.init(e), n = new Promise((i, a) => {
|
|
2122
2127
|
setTimeout(() => {
|
|
2123
2128
|
a(new Error("[TraceLog] Initialization timeout after 10000ms"));
|
|
2124
2129
|
}, 1e4);
|
|
2125
2130
|
});
|
|
2126
|
-
await Promise.race([
|
|
2127
|
-
} catch (
|
|
2131
|
+
await Promise.race([s, n]), h = t;
|
|
2132
|
+
} catch (s) {
|
|
2128
2133
|
try {
|
|
2129
2134
|
await t.destroy(!0);
|
|
2130
2135
|
} catch (n) {
|
|
2131
2136
|
o("error", "Failed to cleanup partially initialized app", { error: n });
|
|
2132
2137
|
}
|
|
2133
|
-
throw
|
|
2138
|
+
throw s;
|
|
2134
2139
|
}
|
|
2135
2140
|
} catch (e) {
|
|
2136
2141
|
throw h = null, e;
|
|
@@ -2138,25 +2143,25 @@ const Tt = async (s) => {
|
|
|
2138
2143
|
w = !1;
|
|
2139
2144
|
}
|
|
2140
2145
|
}
|
|
2141
|
-
}, vt = (
|
|
2146
|
+
}, vt = (r, e) => {
|
|
2142
2147
|
if (!h)
|
|
2143
2148
|
throw new Error("[TraceLog] TraceLog not initialized. Please call init() first.");
|
|
2144
2149
|
if (U)
|
|
2145
2150
|
throw new Error("[TraceLog] Cannot send events while TraceLog is being destroyed");
|
|
2146
|
-
h.sendCustomEvent(
|
|
2147
|
-
}, It = (
|
|
2151
|
+
h.sendCustomEvent(r, e);
|
|
2152
|
+
}, It = (r, e) => {
|
|
2148
2153
|
if (!h || w) {
|
|
2149
|
-
I.push({ event:
|
|
2154
|
+
I.push({ event: r, callback: e });
|
|
2150
2155
|
return;
|
|
2151
2156
|
}
|
|
2152
|
-
h.on(
|
|
2153
|
-
}, yt = (
|
|
2157
|
+
h.on(r, e);
|
|
2158
|
+
}, yt = (r, e) => {
|
|
2154
2159
|
if (!h) {
|
|
2155
|
-
const t = I.findIndex((
|
|
2160
|
+
const t = I.findIndex((s) => s.event === r && s.callback === e);
|
|
2156
2161
|
t !== -1 && I.splice(t, 1);
|
|
2157
2162
|
return;
|
|
2158
2163
|
}
|
|
2159
|
-
h.off(
|
|
2164
|
+
h.off(r, e);
|
|
2160
2165
|
}, At = () => h !== null, wt = async () => {
|
|
2161
2166
|
if (!h)
|
|
2162
2167
|
throw new Error("[TraceLog] App not initialized");
|
|
@@ -2165,8 +2170,8 @@ const Tt = async (s) => {
|
|
|
2165
2170
|
U = !0;
|
|
2166
2171
|
try {
|
|
2167
2172
|
await h.destroy(), h = null, w = !1, I.length = 0;
|
|
2168
|
-
} catch (
|
|
2169
|
-
h = null, w = !1, I.length = 0, o("warn", "Error during destroy, forced cleanup completed", { error:
|
|
2173
|
+
} catch (r) {
|
|
2174
|
+
h = null, w = !1, I.length = 0, o("warn", "Error during destroy, forced cleanup completed", { error: r });
|
|
2170
2175
|
} finally {
|
|
2171
2176
|
U = !1;
|
|
2172
2177
|
}
|
|
@@ -2255,57 +2260,57 @@ const Tt = async (s) => {
|
|
|
2255
2260
|
isInitialized: At,
|
|
2256
2261
|
destroy: wt
|
|
2257
2262
|
};
|
|
2258
|
-
var q, ve = -1, M = function(
|
|
2263
|
+
var q, ve = -1, M = function(r) {
|
|
2259
2264
|
addEventListener("pageshow", function(e) {
|
|
2260
|
-
e.persisted && (ve = e.timeStamp,
|
|
2265
|
+
e.persisted && (ve = e.timeStamp, r(e));
|
|
2261
2266
|
}, !0);
|
|
2262
2267
|
}, se = function() {
|
|
2263
|
-
var
|
|
2264
|
-
if (
|
|
2268
|
+
var r = self.performance && performance.getEntriesByType && performance.getEntriesByType("navigation")[0];
|
|
2269
|
+
if (r && r.responseStart > 0 && r.responseStart < performance.now()) return r;
|
|
2265
2270
|
}, V = function() {
|
|
2266
|
-
var
|
|
2267
|
-
return
|
|
2268
|
-
}, S = function(
|
|
2269
|
-
var t = se(),
|
|
2270
|
-
return ve >= 0 ?
|
|
2271
|
-
}, b = function(
|
|
2271
|
+
var r = se();
|
|
2272
|
+
return r && r.activationStart || 0;
|
|
2273
|
+
}, S = function(r, e) {
|
|
2274
|
+
var t = se(), s = "navigate";
|
|
2275
|
+
return ve >= 0 ? s = "back-forward-cache" : t && (document.prerendering || V() > 0 ? s = "prerender" : document.wasDiscarded ? s = "restore" : t.type && (s = 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: s };
|
|
2276
|
+
}, b = function(r, e, t) {
|
|
2272
2277
|
try {
|
|
2273
|
-
if (PerformanceObserver.supportedEntryTypes.includes(
|
|
2274
|
-
var
|
|
2278
|
+
if (PerformanceObserver.supportedEntryTypes.includes(r)) {
|
|
2279
|
+
var s = new PerformanceObserver(function(n) {
|
|
2275
2280
|
Promise.resolve().then(function() {
|
|
2276
2281
|
e(n.getEntries());
|
|
2277
2282
|
});
|
|
2278
2283
|
});
|
|
2279
|
-
return
|
|
2284
|
+
return s.observe(Object.assign({ type: r, buffered: !0 }, t || {})), s;
|
|
2280
2285
|
}
|
|
2281
2286
|
} catch {
|
|
2282
2287
|
}
|
|
2283
|
-
}, E = function(
|
|
2288
|
+
}, E = function(r, e, t, s) {
|
|
2284
2289
|
var n, i;
|
|
2285
2290
|
return function(a) {
|
|
2286
|
-
e.value >= 0 && (a ||
|
|
2287
|
-
return
|
|
2288
|
-
}(e.value, t),
|
|
2291
|
+
e.value >= 0 && (a || s) && ((i = e.value - (n || 0)) || n === void 0) && (n = e.value, e.delta = i, e.rating = function(l, c) {
|
|
2292
|
+
return l > c[1] ? "poor" : l > c[0] ? "needs-improvement" : "good";
|
|
2293
|
+
}(e.value, t), r(e));
|
|
2289
2294
|
};
|
|
2290
|
-
}, ne = function(
|
|
2295
|
+
}, ne = function(r) {
|
|
2291
2296
|
requestAnimationFrame(function() {
|
|
2292
2297
|
return requestAnimationFrame(function() {
|
|
2293
|
-
return
|
|
2298
|
+
return r();
|
|
2294
2299
|
});
|
|
2295
2300
|
});
|
|
2296
|
-
}, F = function(
|
|
2301
|
+
}, F = function(r) {
|
|
2297
2302
|
document.addEventListener("visibilitychange", function() {
|
|
2298
|
-
document.visibilityState === "hidden" &&
|
|
2303
|
+
document.visibilityState === "hidden" && r();
|
|
2299
2304
|
});
|
|
2300
|
-
}, ie = function(
|
|
2305
|
+
}, ie = function(r) {
|
|
2301
2306
|
var e = !1;
|
|
2302
2307
|
return function() {
|
|
2303
|
-
e || (
|
|
2308
|
+
e || (r(), e = !0);
|
|
2304
2309
|
};
|
|
2305
2310
|
}, A = -1, Ee = function() {
|
|
2306
2311
|
return document.visibilityState !== "hidden" || document.prerendering ? 1 / 0 : 0;
|
|
2307
|
-
}, x = function(
|
|
2308
|
-
document.visibilityState === "hidden" && A > -1 && (A =
|
|
2312
|
+
}, x = function(r) {
|
|
2313
|
+
document.visibilityState === "hidden" && A > -1 && (A = r.type === "visibilitychange" ? r.timeStamp : 0, Mt());
|
|
2309
2314
|
}, me = function() {
|
|
2310
2315
|
addEventListener("visibilitychange", x, !0), addEventListener("prerenderingchange", x, !0);
|
|
2311
2316
|
}, Mt = function() {
|
|
@@ -2318,43 +2323,43 @@ var q, ve = -1, M = function(s) {
|
|
|
2318
2323
|
})), { get firstHiddenTime() {
|
|
2319
2324
|
return A;
|
|
2320
2325
|
} };
|
|
2321
|
-
}, G = function(
|
|
2326
|
+
}, G = function(r) {
|
|
2322
2327
|
document.prerendering ? addEventListener("prerenderingchange", function() {
|
|
2323
|
-
return
|
|
2324
|
-
}, !0) :
|
|
2325
|
-
}, Z = [1800, 3e3], ye = function(
|
|
2328
|
+
return r();
|
|
2329
|
+
}, !0) : r();
|
|
2330
|
+
}, Z = [1800, 3e3], ye = function(r, e) {
|
|
2326
2331
|
e = e || {}, G(function() {
|
|
2327
|
-
var t,
|
|
2328
|
-
a.forEach(function(
|
|
2329
|
-
|
|
2332
|
+
var t, s = Ie(), n = S("FCP"), i = b("paint", function(a) {
|
|
2333
|
+
a.forEach(function(l) {
|
|
2334
|
+
l.name === "first-contentful-paint" && (i.disconnect(), l.startTime < s.firstHiddenTime && (n.value = Math.max(l.startTime - V(), 0), n.entries.push(l), t(!0)));
|
|
2330
2335
|
});
|
|
2331
2336
|
});
|
|
2332
|
-
i && (t = E(
|
|
2333
|
-
n = S("FCP"), t = E(
|
|
2337
|
+
i && (t = E(r, n, Z, e.reportAllChanges), M(function(a) {
|
|
2338
|
+
n = S("FCP"), t = E(r, n, Z, e.reportAllChanges), ne(function() {
|
|
2334
2339
|
n.value = performance.now() - a.timeStamp, t(!0);
|
|
2335
2340
|
});
|
|
2336
2341
|
}));
|
|
2337
2342
|
});
|
|
2338
|
-
}, J = [0.1, 0.25], Nt = function(
|
|
2343
|
+
}, J = [0.1, 0.25], Nt = function(r, e) {
|
|
2339
2344
|
e = e || {}, ye(ie(function() {
|
|
2340
|
-
var t,
|
|
2341
|
-
|
|
2345
|
+
var t, s = S("CLS", 0), n = 0, i = [], a = function(c) {
|
|
2346
|
+
c.forEach(function(u) {
|
|
2342
2347
|
if (!u.hadRecentInput) {
|
|
2343
2348
|
var p = i[0], N = i[i.length - 1];
|
|
2344
2349
|
n && u.startTime - N.startTime < 1e3 && u.startTime - p.startTime < 5e3 ? (n += u.value, i.push(u)) : (n = u.value, i = [u]);
|
|
2345
2350
|
}
|
|
2346
|
-
}), n >
|
|
2347
|
-
},
|
|
2348
|
-
|
|
2349
|
-
a(
|
|
2351
|
+
}), n > s.value && (s.value = n, s.entries = i, t());
|
|
2352
|
+
}, l = b("layout-shift", a);
|
|
2353
|
+
l && (t = E(r, s, J, e.reportAllChanges), F(function() {
|
|
2354
|
+
a(l.takeRecords()), t(!0);
|
|
2350
2355
|
}), M(function() {
|
|
2351
|
-
n = 0,
|
|
2356
|
+
n = 0, s = S("CLS", 0), t = E(r, s, J, e.reportAllChanges), ne(function() {
|
|
2352
2357
|
return t();
|
|
2353
2358
|
});
|
|
2354
2359
|
}), setTimeout(t, 0));
|
|
2355
2360
|
}));
|
|
2356
|
-
}, Ae = 0, Q = 1 / 0, P = 0, Lt = function(
|
|
2357
|
-
|
|
2361
|
+
}, Ae = 0, Q = 1 / 0, P = 0, Lt = function(r) {
|
|
2362
|
+
r.forEach(function(e) {
|
|
2358
2363
|
e.interactionId && (Q = Math.min(Q, e.interactionId), P = Math.max(P, e.interactionId), Ae = P ? (P - Q) / 7 + 1 : 0);
|
|
2359
2364
|
});
|
|
2360
2365
|
}, we = function() {
|
|
@@ -2362,18 +2367,18 @@ var q, ve = -1, M = function(s) {
|
|
|
2362
2367
|
}, Rt = function() {
|
|
2363
2368
|
"interactionCount" in performance || q || (q = b("event", Lt, { type: "event", buffered: !0, durationThreshold: 0 }));
|
|
2364
2369
|
}, g = [], H = /* @__PURE__ */ new Map(), Me = 0, Ct = function() {
|
|
2365
|
-
var
|
|
2366
|
-
return g[
|
|
2367
|
-
}, bt = [], Ot = function(
|
|
2370
|
+
var r = Math.min(g.length - 1, Math.floor((we() - Me) / 50));
|
|
2371
|
+
return g[r];
|
|
2372
|
+
}, bt = [], Ot = function(r) {
|
|
2368
2373
|
if (bt.forEach(function(n) {
|
|
2369
|
-
return n(
|
|
2370
|
-
}),
|
|
2371
|
-
var e = g[g.length - 1], t = H.get(
|
|
2372
|
-
if (t || g.length < 10 ||
|
|
2373
|
-
if (t)
|
|
2374
|
+
return n(r);
|
|
2375
|
+
}), r.interactionId || r.entryType === "first-input") {
|
|
2376
|
+
var e = g[g.length - 1], t = H.get(r.interactionId);
|
|
2377
|
+
if (t || g.length < 10 || r.duration > e.latency) {
|
|
2378
|
+
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);
|
|
2374
2379
|
else {
|
|
2375
|
-
var
|
|
2376
|
-
H.set(
|
|
2380
|
+
var s = { id: r.interactionId, latency: r.duration, entries: [r] };
|
|
2381
|
+
H.set(s.id, s), g.push(s);
|
|
2377
2382
|
}
|
|
2378
2383
|
g.sort(function(n, i) {
|
|
2379
2384
|
return i.latency - n.latency;
|
|
@@ -2382,62 +2387,62 @@ var q, ve = -1, M = function(s) {
|
|
|
2382
2387
|
});
|
|
2383
2388
|
}
|
|
2384
2389
|
}
|
|
2385
|
-
}, Ne = function(
|
|
2390
|
+
}, Ne = function(r) {
|
|
2386
2391
|
var e = self.requestIdleCallback || self.setTimeout, t = -1;
|
|
2387
|
-
return
|
|
2388
|
-
}, ee = [200, 500], Pt = function(
|
|
2392
|
+
return r = ie(r), document.visibilityState === "hidden" ? r() : (t = e(r), F(r)), t;
|
|
2393
|
+
}, ee = [200, 500], Pt = function(r, e) {
|
|
2389
2394
|
"PerformanceEventTiming" in self && "interactionId" in PerformanceEventTiming.prototype && (e = e || {}, G(function() {
|
|
2390
2395
|
var t;
|
|
2391
2396
|
Rt();
|
|
2392
|
-
var
|
|
2397
|
+
var s, n = S("INP"), i = function(l) {
|
|
2393
2398
|
Ne(function() {
|
|
2394
|
-
|
|
2395
|
-
var
|
|
2396
|
-
|
|
2399
|
+
l.forEach(Ot);
|
|
2400
|
+
var c = Ct();
|
|
2401
|
+
c && c.latency !== n.value && (n.value = c.latency, n.entries = c.entries, s());
|
|
2397
2402
|
});
|
|
2398
2403
|
}, a = b("event", i, { durationThreshold: (t = e.durationThreshold) !== null && t !== void 0 ? t : 40 });
|
|
2399
|
-
|
|
2400
|
-
i(a.takeRecords()),
|
|
2404
|
+
s = E(r, n, ee, e.reportAllChanges), a && (a.observe({ type: "first-input", buffered: !0 }), F(function() {
|
|
2405
|
+
i(a.takeRecords()), s(!0);
|
|
2401
2406
|
}), M(function() {
|
|
2402
|
-
Me = we(), g.length = 0, H.clear(), n = S("INP"),
|
|
2407
|
+
Me = we(), g.length = 0, H.clear(), n = S("INP"), s = E(r, n, ee, e.reportAllChanges);
|
|
2403
2408
|
}));
|
|
2404
2409
|
}));
|
|
2405
|
-
}, te = [2500, 4e3], B = {}, Dt = function(
|
|
2410
|
+
}, te = [2500, 4e3], B = {}, Dt = function(r, e) {
|
|
2406
2411
|
e = e || {}, G(function() {
|
|
2407
|
-
var t,
|
|
2408
|
-
e.reportAllChanges || (
|
|
2409
|
-
u.startTime <
|
|
2412
|
+
var t, s = Ie(), n = S("LCP"), i = function(c) {
|
|
2413
|
+
e.reportAllChanges || (c = c.slice(-1)), c.forEach(function(u) {
|
|
2414
|
+
u.startTime < s.firstHiddenTime && (n.value = Math.max(u.startTime - V(), 0), n.entries = [u], t());
|
|
2410
2415
|
});
|
|
2411
2416
|
}, a = b("largest-contentful-paint", i);
|
|
2412
2417
|
if (a) {
|
|
2413
|
-
t = E(
|
|
2414
|
-
var
|
|
2418
|
+
t = E(r, n, te, e.reportAllChanges);
|
|
2419
|
+
var l = ie(function() {
|
|
2415
2420
|
B[n.id] || (i(a.takeRecords()), a.disconnect(), B[n.id] = !0, t(!0));
|
|
2416
2421
|
});
|
|
2417
|
-
["keydown", "click"].forEach(function(
|
|
2418
|
-
addEventListener(
|
|
2419
|
-
return Ne(
|
|
2422
|
+
["keydown", "click"].forEach(function(c) {
|
|
2423
|
+
addEventListener(c, function() {
|
|
2424
|
+
return Ne(l);
|
|
2420
2425
|
}, { once: !0, capture: !0 });
|
|
2421
|
-
}), F(
|
|
2422
|
-
n = S("LCP"), t = E(
|
|
2423
|
-
n.value = performance.now() -
|
|
2426
|
+
}), F(l), M(function(c) {
|
|
2427
|
+
n = S("LCP"), t = E(r, n, te, e.reportAllChanges), ne(function() {
|
|
2428
|
+
n.value = performance.now() - c.timeStamp, B[n.id] = !0, t(!0);
|
|
2424
2429
|
});
|
|
2425
2430
|
});
|
|
2426
2431
|
}
|
|
2427
2432
|
});
|
|
2428
|
-
}, re = [800, 1800], kt = function
|
|
2433
|
+
}, re = [800, 1800], kt = function r(e) {
|
|
2429
2434
|
document.prerendering ? G(function() {
|
|
2430
|
-
return
|
|
2435
|
+
return r(e);
|
|
2431
2436
|
}) : document.readyState !== "complete" ? addEventListener("load", function() {
|
|
2432
|
-
return
|
|
2437
|
+
return r(e);
|
|
2433
2438
|
}, !0) : setTimeout(e, 0);
|
|
2434
|
-
}, Ut = function(
|
|
2439
|
+
}, Ut = function(r, e) {
|
|
2435
2440
|
e = e || {};
|
|
2436
|
-
var t = S("TTFB"),
|
|
2441
|
+
var t = S("TTFB"), s = E(r, t, re, e.reportAllChanges);
|
|
2437
2442
|
kt(function() {
|
|
2438
2443
|
var n = se();
|
|
2439
|
-
n && (t.value = Math.max(n.responseStart - V(), 0), t.entries = [n],
|
|
2440
|
-
t = S("TTFB", 0), (
|
|
2444
|
+
n && (t.value = Math.max(n.responseStart - V(), 0), t.entries = [n], s(!0), M(function() {
|
|
2445
|
+
t = S("TTFB", 0), (s = E(r, t, re, e.reportAllChanges))(!0);
|
|
2441
2446
|
}));
|
|
2442
2447
|
});
|
|
2443
2448
|
};
|