@sprig-technologies/sprig-browser 2.33.3 → 2.34.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/{core-DLrmR9wp.js → core-DE6rbUl1.js} +420 -408
- package/dist/core-i4jnjCfb.cjs +12 -0
- package/dist/core.cjs +1 -1
- package/dist/core.d.ts +20 -0
- package/dist/core.js +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +20 -0
- package/dist/index.js +2 -2
- package/dist/{metricsReporter-qetrFwEv.js → metricsReporter-CEzz54S2.js} +2 -2
- package/dist/{metricsReporter-DNdFkQ0C.cjs → metricsReporter-Cc-ZSIZD.cjs} +1 -1
- package/dist/replay.cjs +1 -1
- package/dist/replay.js +342 -338
- package/dist/{view-Bd-x6oh5.cjs → view-Bze4Vd-1.cjs} +2 -2
- package/dist/{view-Bml35A_s.js → view-C3KUMRoa.js} +3 -3
- package/package.json +1 -1
- package/dist/core-nhbrlHf1.cjs +0 -12
package/dist/replay.js
CHANGED
|
@@ -1,98 +1,98 @@
|
|
|
1
1
|
var st = Object.defineProperty;
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { b as d, s as
|
|
5
|
-
var B = ((e) => (e[e.DomContentLoaded = 0] = "DomContentLoaded", e[e.Load = 1] = "Load", e[e.FullSnapshot = 2] = "FullSnapshot", e[e.IncrementalSnapshot = 3] = "IncrementalSnapshot", e[e.Meta = 4] = "Meta", e[e.Custom = 5] = "Custom", e[e.Plugin = 6] = "Plugin", e))(B || {}),
|
|
6
|
-
const
|
|
7
|
-
let
|
|
8
|
-
const
|
|
9
|
-
let
|
|
2
|
+
var it = (e, t, n) => t in e ? st(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
|
|
3
|
+
var X = (e, t, n) => it(e, typeof t != "symbol" ? t + "" : t, n);
|
|
4
|
+
import { b as d, s as z, a as m, v as q, c as dt, g as lt, P as ke, r as Ue, d as ut, e as H, S as Z, f as ct } from "./metricsReporter-CEzz54S2.js";
|
|
5
|
+
var B = ((e) => (e[e.DomContentLoaded = 0] = "DomContentLoaded", e[e.Load = 1] = "Load", e[e.FullSnapshot = 2] = "FullSnapshot", e[e.IncrementalSnapshot = 3] = "IncrementalSnapshot", e[e.Meta = 4] = "Meta", e[e.Custom = 5] = "Custom", e[e.Plugin = 6] = "Plugin", e))(B || {}), U = ((e) => (e[e.Mutation = 0] = "Mutation", e[e.MouseMove = 1] = "MouseMove", e[e.MouseInteraction = 2] = "MouseInteraction", e[e.Scroll = 3] = "Scroll", e[e.ViewportResize = 4] = "ViewportResize", e[e.Input = 5] = "Input", e[e.TouchMove = 6] = "TouchMove", e[e.MediaInteraction = 7] = "MediaInteraction", e[e.StyleSheetRule = 8] = "StyleSheetRule", e[e.CanvasMutation = 9] = "CanvasMutation", e[e.Font = 10] = "Font", e[e.Log = 11] = "Log", e[e.Drag = 12] = "Drag", e[e.StyleDeclaration = 13] = "StyleDeclaration", e[e.Selection = 14] = "Selection", e[e.AdoptedStyleSheet = 15] = "AdoptedStyleSheet", e[e.CustomElement = 16] = "CustomElement", e))(U || {});
|
|
6
|
+
const ae = (e, t) => t.some((n) => e instanceof n);
|
|
7
|
+
let ve, Se;
|
|
8
|
+
const re = /* @__PURE__ */ new WeakMap(), Y = /* @__PURE__ */ new WeakMap(), $ = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
let oe = { get(e, t, n) {
|
|
10
10
|
if (e instanceof IDBTransaction) {
|
|
11
|
-
if (t === "done") return
|
|
11
|
+
if (t === "done") return re.get(e);
|
|
12
12
|
if (t === "store") return n.objectStoreNames[1] ? void 0 : n.objectStore(n.objectStoreNames[0]);
|
|
13
13
|
}
|
|
14
|
-
return
|
|
14
|
+
return M(e[t]);
|
|
15
15
|
}, set: (e, t, n) => (e[t] = n, !0), has: (e, t) => e instanceof IDBTransaction && (t === "done" || t === "store") || t in e };
|
|
16
|
-
function
|
|
17
|
-
|
|
16
|
+
function xe(e) {
|
|
17
|
+
oe = e(oe);
|
|
18
18
|
}
|
|
19
|
-
function
|
|
20
|
-
return (
|
|
21
|
-
return e.apply(se(this), t),
|
|
19
|
+
function pt(e) {
|
|
20
|
+
return (Se || (Se = [IDBCursor.prototype.advance, IDBCursor.prototype.continue, IDBCursor.prototype.continuePrimaryKey])).includes(e) ? function(...t) {
|
|
21
|
+
return e.apply(se(this), t), M(this.request);
|
|
22
22
|
} : function(...t) {
|
|
23
|
-
return
|
|
23
|
+
return M(e.apply(se(this), t));
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
-
function
|
|
27
|
-
return typeof e == "function" ?
|
|
28
|
-
if (
|
|
26
|
+
function gt(e) {
|
|
27
|
+
return typeof e == "function" ? pt(e) : (e instanceof IDBTransaction && function(t) {
|
|
28
|
+
if (re.has(t)) return;
|
|
29
29
|
const n = new Promise((a, r) => {
|
|
30
|
-
const
|
|
30
|
+
const o = () => {
|
|
31
31
|
r(t.error || new DOMException("AbortError", "AbortError"));
|
|
32
32
|
};
|
|
33
33
|
t.oncomplete = () => {
|
|
34
34
|
a();
|
|
35
|
-
}, t.onerror =
|
|
35
|
+
}, t.onerror = o, t.onabort = o;
|
|
36
36
|
});
|
|
37
|
-
|
|
38
|
-
}(e),
|
|
37
|
+
re.set(t, n);
|
|
38
|
+
}(e), ae(e, ve || (ve = [IDBDatabase, IDBObjectStore, IDBIndex, IDBCursor, IDBTransaction])) ? new Proxy(e, oe) : e);
|
|
39
39
|
}
|
|
40
|
-
function
|
|
40
|
+
function M(e) {
|
|
41
41
|
if (e instanceof IDBRequest) return function(n) {
|
|
42
|
-
const a = new Promise((r,
|
|
42
|
+
const a = new Promise((r, o) => {
|
|
43
43
|
n.onsuccess = () => {
|
|
44
|
-
r(
|
|
44
|
+
r(M(n.result));
|
|
45
45
|
}, n.onerror = () => {
|
|
46
|
-
|
|
46
|
+
o(n.error);
|
|
47
47
|
};
|
|
48
48
|
});
|
|
49
49
|
return $.set(a, n), a;
|
|
50
50
|
}(e);
|
|
51
|
-
if (
|
|
52
|
-
const t =
|
|
53
|
-
return t !== e && (
|
|
51
|
+
if (Y.has(e)) return Y.get(e);
|
|
52
|
+
const t = gt(e);
|
|
53
|
+
return t !== e && (Y.set(e, t), $.set(t, e)), t;
|
|
54
54
|
}
|
|
55
55
|
const se = (e) => $.get(e);
|
|
56
|
-
function
|
|
56
|
+
function ie(e, { blocked: t } = {}) {
|
|
57
57
|
const n = indexedDB.deleteDatabase(e);
|
|
58
|
-
return t && (n.onblocked = (a) => t(a.oldVersion, a)),
|
|
58
|
+
return t && (n.onblocked = (a) => t(a.oldVersion, a)), M(n).then(() => {
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
|
-
const
|
|
62
|
-
function
|
|
61
|
+
const mt = ["get", "getKey", "getAll", "getAllKeys", "count"], wt = ["put", "add", "delete", "clear"], ee = /* @__PURE__ */ new Map();
|
|
62
|
+
function De(e, t) {
|
|
63
63
|
if (!(e instanceof IDBDatabase) || t in e || typeof t != "string") return;
|
|
64
|
-
if (
|
|
65
|
-
const n = t.replace(/FromIndex$/, ""), a = t !== n, r =
|
|
66
|
-
if (!(n in (a ? IDBIndex : IDBObjectStore).prototype) || !r && !
|
|
67
|
-
const
|
|
68
|
-
const i = this.transaction(
|
|
69
|
-
let
|
|
70
|
-
return a && (
|
|
64
|
+
if (ee.get(t)) return ee.get(t);
|
|
65
|
+
const n = t.replace(/FromIndex$/, ""), a = t !== n, r = wt.includes(n);
|
|
66
|
+
if (!(n in (a ? IDBIndex : IDBObjectStore).prototype) || !r && !mt.includes(n)) return;
|
|
67
|
+
const o = async function(s, ...l) {
|
|
68
|
+
const i = this.transaction(s, r ? "readwrite" : "readonly");
|
|
69
|
+
let u = i.store;
|
|
70
|
+
return a && (u = u.index(l.shift())), (await Promise.all([u[n](...l), r && i.done]))[0];
|
|
71
71
|
};
|
|
72
|
-
return
|
|
72
|
+
return ee.set(t, o), o;
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
if (!
|
|
77
|
-
let n =
|
|
78
|
-
return n || (n =
|
|
79
|
-
|
|
74
|
+
xe((e) => ({ ...e, get: (t, n, a) => De(t, n) || e.get(t, n, a), has: (t, n) => !!De(t, n) || e.has(t, n) }));
|
|
75
|
+
const yt = ["continue", "continuePrimaryKey", "advance"], be = {}, de = /* @__PURE__ */ new WeakMap(), Te = /* @__PURE__ */ new WeakMap(), ft = { get(e, t) {
|
|
76
|
+
if (!yt.includes(t)) return e[t];
|
|
77
|
+
let n = be[t];
|
|
78
|
+
return n || (n = be[t] = function(...a) {
|
|
79
|
+
de.set(this, Te.get(this)[t](...a));
|
|
80
80
|
}), n;
|
|
81
81
|
} };
|
|
82
|
-
async function*
|
|
82
|
+
async function* ht(...e) {
|
|
83
83
|
let t = this;
|
|
84
84
|
if (t instanceof IDBCursor || (t = await t.openCursor(...e)), !t) return;
|
|
85
|
-
const n = new Proxy(t,
|
|
86
|
-
for (
|
|
85
|
+
const n = new Proxy(t, ft);
|
|
86
|
+
for (Te.set(n, t), $.set(n, se(t)); t; ) yield n, t = await (de.get(n) || t.continue()), de.delete(n);
|
|
87
87
|
}
|
|
88
|
-
function
|
|
89
|
-
return t === Symbol.asyncIterator &&
|
|
88
|
+
function Ee(e, t) {
|
|
89
|
+
return t === Symbol.asyncIterator && ae(e, [IDBIndex, IDBObjectStore, IDBCursor]) || t === "iterate" && ae(e, [IDBIndex, IDBObjectStore]);
|
|
90
90
|
}
|
|
91
|
-
|
|
92
|
-
const
|
|
91
|
+
xe((e) => ({ ...e, get: (t, n, a) => Ee(t, n) ? ht : e.get(t, n, a), has: (t, n) => Ee(t, n) || e.has(t, n) }));
|
|
92
|
+
const It = "sprigReplayIframeLoaded", vt = "sprigReplayIframeSettings", St = "sprigReplayIframeTakeFullSnapshot", Dt = "sprigReplayTeardown", ye = [], Be = new class {
|
|
93
93
|
constructor(e) {
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
X(this, "awaitingResolvers", []);
|
|
95
|
+
X(this, "activeCount", 0);
|
|
96
96
|
this.capacity = e;
|
|
97
97
|
}
|
|
98
98
|
async acquire() {
|
|
@@ -115,18 +115,18 @@ const ht = "sprigReplayIframeLoaded", It = "sprigReplayIframeSettings", vt = "sp
|
|
|
115
115
|
setLimit(e) {
|
|
116
116
|
this.capacity = e;
|
|
117
117
|
}
|
|
118
|
-
}(2),
|
|
119
|
-
var
|
|
118
|
+
}(2), Me = async ({ apiUrl: e, surveyId: t, uploadId: n, etags: a, headers: r, responseGroupUuid: o, replayDuration: s, eventDigest: l }, i = !1) => {
|
|
119
|
+
var y;
|
|
120
120
|
if (!i && !n && !a) return void d.error("UploadErr", { isMobile: i, uploadId: n, etags: a });
|
|
121
121
|
d.info("MarkUploadComplete", { surveyId: t });
|
|
122
|
-
const
|
|
123
|
-
return d.info("MarkUploadDone", { surveyId: t }),
|
|
124
|
-
},
|
|
122
|
+
const u = await z(`${e}/sdk/1/completeSessionReplay`, { method: "POST", body: JSON.stringify({ etags: a, uploadId: n, responseGroupUuid: o, surveyId: t, replayDuration: s, eventDigest: l, userAgent: (y = window == null ? void 0 : window.navigator) == null ? void 0 : y.userAgent }), headers: r, shouldRetryRequest: !0 });
|
|
123
|
+
return d.info("MarkUploadDone", { surveyId: t }), u;
|
|
124
|
+
}, bt = (e) => {
|
|
125
125
|
if (e instanceof Attr) return null;
|
|
126
126
|
let t = 1;
|
|
127
127
|
for (let n = e.previousSibling; n; n = n.previousSibling) n.nodeName === e.nodeName && ++t;
|
|
128
128
|
return t;
|
|
129
|
-
},
|
|
129
|
+
}, Ae = (e) => {
|
|
130
130
|
if (e === null) return "";
|
|
131
131
|
const t = [];
|
|
132
132
|
if (e instanceof Document) return "/";
|
|
@@ -148,12 +148,12 @@ const ht = "sprigReplayIframeLoaded", It = "sprigReplayIframeSettings", vt = "sp
|
|
|
148
148
|
case Node.ELEMENT_NODE:
|
|
149
149
|
a.name = n.nodeName;
|
|
150
150
|
}
|
|
151
|
-
a.position =
|
|
151
|
+
a.position = bt(n);
|
|
152
152
|
}
|
|
153
153
|
return "/" + t.reverse().map((n) => n.position !== null ? `/${n.name}[${n.position}]` : `/${n.name}`).join("");
|
|
154
|
-
},
|
|
154
|
+
}, fe = (e) => e && e.trim().substring(0, 500).replace(/\s\s+/g, " ").replace(/\r?\n|\r/g, " ").substring(0, 250), C = { capture: !0, passive: !0 }, Et = ["a", "button", "input", "option", "li", "link"], Rt = ["Escape", "Enter", "Backspace", "F5", "Tab"];
|
|
155
155
|
let K = !1, b = null, j = null;
|
|
156
|
-
const
|
|
156
|
+
const Re = (e) => {
|
|
157
157
|
var n;
|
|
158
158
|
if (((n = e.tagName) == null ? void 0 : n.toLowerCase()) === "html") return { element: "html" };
|
|
159
159
|
const t = {};
|
|
@@ -165,27 +165,27 @@ const be = (e) => {
|
|
|
165
165
|
}, Ct = (e) => {
|
|
166
166
|
var a;
|
|
167
167
|
if (!e) return {};
|
|
168
|
-
const t = { ...
|
|
169
|
-
if (n &&
|
|
170
|
-
const r =
|
|
168
|
+
const t = { ...Re(e) }, n = e.parentElement;
|
|
169
|
+
if (n && Et.includes((a = n.tagName) == null ? void 0 : a.toLowerCase())) {
|
|
170
|
+
const r = Re(n);
|
|
171
171
|
Object.assign(t, r);
|
|
172
172
|
}
|
|
173
173
|
return t;
|
|
174
|
-
},
|
|
175
|
-
var r,
|
|
174
|
+
}, _e = (e, t) => {
|
|
175
|
+
var r, o;
|
|
176
176
|
let n = t.target;
|
|
177
177
|
var a;
|
|
178
|
-
t.target === ((r = window.document) == null ? void 0 : r.body) && window.Sprig.pointerDownTarget && (n = window.Sprig.pointerDownTarget), a = { x: t.x, y: t.y, type: e, elementAttributes: Ct(n), windowHeight: window.innerHeight, windowWidth: window.innerWidth, ...n instanceof HTMLElement ? { rect: n == null ? void 0 : n.getBoundingClientRect(), xPath:
|
|
179
|
-
},
|
|
178
|
+
t.target === ((r = window.document) == null ? void 0 : r.body) && window.Sprig.pointerDownTarget && (n = window.Sprig.pointerDownTarget), a = { x: t.x, y: t.y, type: e, elementAttributes: Ct(n), windowHeight: window.innerHeight, windowWidth: window.innerWidth, ...n instanceof HTMLElement ? { rect: n == null ? void 0 : n.getBoundingClientRect(), xPath: Ae(n) } : {} }, (o = a == null ? void 0 : a.elementAttributes) != null && o.text && (a.elementAttributes.text = fe(a.elementAttributes.text)), b == null || b("Sprig_Click", a);
|
|
179
|
+
}, Ne = (e) => {
|
|
180
180
|
var t;
|
|
181
|
-
|
|
182
|
-
},
|
|
181
|
+
Rt.includes(e.key) && (t = { key: e.key }, b == null || b("Sprig_Keystroke", t));
|
|
182
|
+
}, Pt = () => {
|
|
183
183
|
var e;
|
|
184
184
|
window.performance.getEntriesByType("navigation").map((t) => t.type).includes("reload") && (e = { url: window.location.href, currentPageTitle: document.title }, b == null || b("Sprig_Refresh", e));
|
|
185
|
-
},
|
|
185
|
+
}, kt = () => {
|
|
186
186
|
var e;
|
|
187
|
-
window.performance.getEntriesByType("navigation").map((t) => t.type).includes("back_forward") && ((e = { curUrl: window.location.href, fromUrl: document.referrer, currentPageTitle: document.title }).currentPageTitle && (e.currentPageTitle =
|
|
188
|
-
},
|
|
187
|
+
window.performance.getEntriesByType("navigation").map((t) => t.type).includes("back_forward") && ((e = { curUrl: window.location.href, fromUrl: document.referrer, currentPageTitle: document.title }).currentPageTitle && (e.currentPageTitle = fe(e.currentPageTitle)), b == null || b("Sprig_BackForward", e));
|
|
188
|
+
}, Le = /* @__PURE__ */ ((e, t) => {
|
|
189
189
|
let n;
|
|
190
190
|
return (a) => {
|
|
191
191
|
clearTimeout(n), n = window.setTimeout(() => e(a), t);
|
|
@@ -193,90 +193,90 @@ const be = (e) => {
|
|
|
193
193
|
})((e) => {
|
|
194
194
|
if (!(e.target instanceof HTMLElement || e.target instanceof Document)) return;
|
|
195
195
|
let t = e.target;
|
|
196
|
-
"scrollTop" in t || (t = t.documentElement), j == null || j({ xPath:
|
|
197
|
-
}, 750),
|
|
198
|
-
var
|
|
199
|
-
const
|
|
200
|
-
e.button === 2 &&
|
|
201
|
-
},
|
|
196
|
+
"scrollTop" in t || (t = t.documentElement), j == null || j({ xPath: Ae(t), x: t.scrollLeft, y: t.scrollTop, elementAttributes: { targetScrollWidth: t.scrollWidth, targetClientWidth: t.clientWidth, targetScrollHeight: t.scrollHeight, targetClientHeight: t.clientHeight } });
|
|
197
|
+
}, 750), Oe = (Ce = "left_click", (e) => _e(Ce, e));
|
|
198
|
+
var Ce;
|
|
199
|
+
const Fe = (e) => {
|
|
200
|
+
e.button === 2 && _e("right_click", e);
|
|
201
|
+
}, He = (e) => {
|
|
202
202
|
window.Sprig && (window.Sprig.pointerDownTarget = e.target);
|
|
203
203
|
}, g = { isRecording: !1, scrollEventUuids: {}, stopRecording: () => {
|
|
204
|
-
} },
|
|
205
|
-
const e =
|
|
206
|
-
if (e) return d.info("SessionIDFound", { savedSessionId: e }),
|
|
207
|
-
const t =
|
|
204
|
+
} }, je = () => window.indexedDB && window.IDBKeyRange && window.CompressionStream, I = (() => {
|
|
205
|
+
const e = m.getItem("sprig.sessionId");
|
|
206
|
+
if (e) return d.info("SessionIDFound", { savedSessionId: e }), m.removeItem("sprig.sessionId"), e;
|
|
207
|
+
const t = q();
|
|
208
208
|
return d.info("GeneratedSessionID", { uuid: t }), t;
|
|
209
|
-
})(),
|
|
210
|
-
|
|
211
|
-
},
|
|
209
|
+
})(), le = () => {
|
|
210
|
+
m.setItem("sprig.disableReplayRecording", "disabled");
|
|
211
|
+
}, P = () => !!m.getItem("sprig.disableReplayRecording"), W = () => !!m.getItem("sprig.isReplayPaused");
|
|
212
212
|
window.addEventListener("beforeunload", () => {
|
|
213
|
-
d.info("BeforeUnload", { sessionId: I }),
|
|
213
|
+
d.info("BeforeUnload", { sessionId: I }), m.setItem("sprig.sessionId", I);
|
|
214
214
|
});
|
|
215
|
-
const
|
|
215
|
+
const x = (e, t) => {
|
|
216
216
|
var n, a;
|
|
217
|
-
if (!
|
|
217
|
+
if (!P() && g.isRecording && !W()) try {
|
|
218
218
|
(a = (n = window.rrwebRecord) == null ? void 0 : n.addCustomEvent) == null || a.call(n, e, t);
|
|
219
219
|
} catch (r) {
|
|
220
|
-
|
|
220
|
+
Q("Error recording custom event", r);
|
|
221
221
|
}
|
|
222
222
|
}, Ut = async (e) => {
|
|
223
223
|
const { x: t, xPath: n, y: a } = e, r = g.scrollEventUuids[n];
|
|
224
224
|
if (r) return D(async () => {
|
|
225
|
-
var
|
|
226
|
-
const
|
|
227
|
-
if (
|
|
228
|
-
const p = JSON.parse(
|
|
229
|
-
if (!h && !
|
|
230
|
-
h && (p.data.payload.x = t),
|
|
231
|
-
} else
|
|
225
|
+
var l, i, u, y;
|
|
226
|
+
const o = await c.openDB(), s = await o.get("events", r);
|
|
227
|
+
if (s != null && s.event) {
|
|
228
|
+
const p = JSON.parse(s.event), h = t > ((i = (l = p.data) == null ? void 0 : l.payload) == null ? void 0 : i.x), w = a > ((y = (u = p.data) == null ? void 0 : u.payload) == null ? void 0 : y.y);
|
|
229
|
+
if (!h && !w) return null;
|
|
230
|
+
h && (p.data.payload.x = t), w && (p.data.payload.y = a), p.data.payload.elementAttributes = e.elementAttributes, s.event = JSON.stringify(p), await o.put("events", s);
|
|
231
|
+
} else x("Sprig_Scroll", e);
|
|
232
232
|
}, "Error updating scroll event");
|
|
233
|
-
|
|
234
|
-
},
|
|
233
|
+
x("Sprig_Scroll", e);
|
|
234
|
+
}, Ve = () => {
|
|
235
235
|
g.stopRecording && (g.stopRecording(), g.stopRecording = void 0), g.isRecording = !1, ["cleanupInterval", "inactivityInterval", "pendingCheckInterval"].forEach((e) => {
|
|
236
236
|
g[e] && (clearInterval(g[e]), g[e] = void 0);
|
|
237
|
-
}), K && (window.removeEventListener("click",
|
|
237
|
+
}), K && (window.removeEventListener("click", Oe, C), window.removeEventListener("pointerdown", He, C), window.removeEventListener("mousedown", Fe, C), window.removeEventListener("keydown", Ne, C), window.removeEventListener("scroll", Le, C), K = !1), ye.forEach((e) => {
|
|
238
238
|
var t;
|
|
239
|
-
(t = e.source) == null || t.postMessage({ type:
|
|
239
|
+
(t = e.source) == null || t.postMessage({ type: Dt }, { targetOrigin: e.origin });
|
|
240
240
|
});
|
|
241
|
-
},
|
|
242
|
-
if (!
|
|
243
|
-
if (
|
|
241
|
+
}, xt = ["did not allow mutations", "called in an invalid security context"], Tt = (e, t, { reportError: n = !0, extraInfo: a = {} }) => {
|
|
242
|
+
if (!P() && t instanceof Error) {
|
|
243
|
+
if (le(), t.name === "VersionError") return d.error("VersionErr", { message: e }), void c.deleteDB();
|
|
244
244
|
((r) => {
|
|
245
245
|
if (!r) return !0;
|
|
246
|
-
for (const
|
|
246
|
+
for (const o of xt) if (r.toLowerCase().includes(o)) return !1;
|
|
247
247
|
return !0;
|
|
248
|
-
})(t == null ? void 0 : t.message) && (n && window.UserLeap.reportError(e, t, a),
|
|
248
|
+
})(t == null ? void 0 : t.message) && (n && window.UserLeap.reportError(e, t, a), c.clearAll());
|
|
249
249
|
}
|
|
250
|
-
},
|
|
251
|
-
|
|
250
|
+
}, Q = (e, t, { reportError: n } = { reportError: !0 }) => {
|
|
251
|
+
Ve(), d.error("ReplayErr", { code: t.code, name: t.name }), Tt(e, t, { reportError: n });
|
|
252
252
|
}, D = async (e, t) => {
|
|
253
253
|
try {
|
|
254
254
|
return await e();
|
|
255
255
|
} catch (n) {
|
|
256
|
-
|
|
256
|
+
Q(t, n);
|
|
257
257
|
}
|
|
258
|
-
},
|
|
258
|
+
}, ue = () => {
|
|
259
259
|
g.isRecording && (D(() => {
|
|
260
260
|
var e, t;
|
|
261
261
|
return (t = (e = window.rrwebRecord) == null ? void 0 : e.takeFullSnapshot) == null ? void 0 : t.call(e, !0);
|
|
262
|
-
}, "Error recording full snapshot"),
|
|
262
|
+
}, "Error recording full snapshot"), ye.forEach((e) => {
|
|
263
263
|
var t;
|
|
264
|
-
(t = e.source) == null || t.postMessage({ type:
|
|
264
|
+
(t = e.source) == null || t.postMessage({ type: St }, { targetOrigin: e.origin });
|
|
265
265
|
}));
|
|
266
266
|
};
|
|
267
|
-
(async () =>
|
|
268
|
-
const
|
|
267
|
+
(async () => je() && Promise.allSettled([ie("replayStorage"), ie("sprig.replay")]))();
|
|
268
|
+
const c = new class {
|
|
269
269
|
openDB() {
|
|
270
|
-
return function(e, t, { blocked: n, upgrade: a, blocking: r, terminated:
|
|
271
|
-
const
|
|
272
|
-
return a && (
|
|
273
|
-
a(
|
|
274
|
-
}), n && (
|
|
275
|
-
|
|
270
|
+
return function(e, t, { blocked: n, upgrade: a, blocking: r, terminated: o } = {}) {
|
|
271
|
+
const s = indexedDB.open(e, t), l = M(s);
|
|
272
|
+
return a && (s.onupgradeneeded = (i) => {
|
|
273
|
+
a(M(s.result), i.oldVersion, i.newVersion, M(s.transaction), i);
|
|
274
|
+
}), n && (s.onblocked = (i) => n(i.oldVersion, i.newVersion, i)), l.then((i) => {
|
|
275
|
+
o && (i.onclose = () => o()), r && (i.onversionchange = (u) => r(u.oldVersion, u.newVersion, u));
|
|
276
276
|
}).catch(() => {
|
|
277
|
-
}),
|
|
277
|
+
}), l;
|
|
278
278
|
}("sprigReplay", 1, { upgrade: (e, t, n) => {
|
|
279
|
-
if (n === 0 &&
|
|
279
|
+
if (n === 0 && m.setItem("sprig.pendingCount", "0"), !e.objectStoreNames.contains("events")) {
|
|
280
280
|
const a = e.createObjectStore("events", { keyPath: "uuid" });
|
|
281
281
|
a.createIndex("sessionId", "sessionId"), a.createIndex("timestamp", "timestamp"), a.createIndex("[sessionId+timestamp]", ["sessionId", "timestamp"]);
|
|
282
282
|
}
|
|
@@ -292,7 +292,7 @@ const u = new class {
|
|
|
292
292
|
}
|
|
293
293
|
async deleteDB() {
|
|
294
294
|
try {
|
|
295
|
-
await
|
|
295
|
+
await ie("sprigReplay");
|
|
296
296
|
} catch {
|
|
297
297
|
}
|
|
298
298
|
}
|
|
@@ -306,7 +306,7 @@ const u = new class {
|
|
|
306
306
|
}
|
|
307
307
|
async deleteBySessionId(e, t) {
|
|
308
308
|
const n = IDBKeyRange.only(t), a = (await this.openDB()).transaction(e, "readwrite"), r = a.store.index("sessionId");
|
|
309
|
-
for await (const
|
|
309
|
+
for await (const o of r.iterate(n)) await o.delete();
|
|
310
310
|
await a.done;
|
|
311
311
|
}
|
|
312
312
|
async updatePartial(e, t, n) {
|
|
@@ -314,8 +314,8 @@ const u = new class {
|
|
|
314
314
|
r && await a.store.put({ ...r, ...n }), await a.done;
|
|
315
315
|
}
|
|
316
316
|
async deleteRowsBefore(e, t, n = () => !0) {
|
|
317
|
-
const a = IDBKeyRange.upperBound(t, !0), r = (await this.openDB()).transaction(e, "readwrite"),
|
|
318
|
-
for await (const
|
|
317
|
+
const a = IDBKeyRange.upperBound(t, !0), r = (await this.openDB()).transaction(e, "readwrite"), o = r.store.index("timestamp");
|
|
318
|
+
for await (const s of o.iterate(a)) n(s.value) && await s.delete();
|
|
319
319
|
await r.done;
|
|
320
320
|
}
|
|
321
321
|
async getEventsBetween(e, t = Date.now()) {
|
|
@@ -324,19 +324,19 @@ const u = new class {
|
|
|
324
324
|
return (await this.openDB()).getAllFromIndex("events", "[sessionId+timestamp]", n);
|
|
325
325
|
}
|
|
326
326
|
async updateEventsExpiredAt(e, t, n = 30) {
|
|
327
|
-
const a = /* @__PURE__ */ new Date(), r = a.setMinutes(a.getMinutes() + (n ?? 30)),
|
|
328
|
-
for await (const i of
|
|
329
|
-
await
|
|
327
|
+
const a = /* @__PURE__ */ new Date(), r = a.setMinutes(a.getMinutes() + (n ?? 30)), o = (await this.openDB()).transaction("events", "readwrite"), s = o.store.index("[sessionId+timestamp]"), l = IDBKeyRange.bound([I, e], [I, t], !1, !0);
|
|
328
|
+
for await (const i of s.iterate(l)) await i.update({ ...i.value, expiredAt: r });
|
|
329
|
+
await o.done;
|
|
330
330
|
}
|
|
331
331
|
async deleteChunkUploads(e, t) {
|
|
332
332
|
const n = IDBKeyRange.only([t, e]), a = (await this.openDB()).transaction("chunkUploads", "readwrite");
|
|
333
|
-
let
|
|
334
|
-
for (;
|
|
333
|
+
let o = await a.store.index("[uploadId+status]").openCursor(n);
|
|
334
|
+
for (; o; ) o.delete(), o = await o.continue();
|
|
335
335
|
await a.done;
|
|
336
336
|
}
|
|
337
337
|
async getChunkUploadsByStatus({ sessionId: e, status: t, uploadId: n }) {
|
|
338
|
-
const a = (await this.openDB()).transaction("chunkUploads", "readonly"), r = n ? a.store.index("[uploadId+status]") : a.store.index("[sessionId+status]"),
|
|
339
|
-
return r.getAll(
|
|
338
|
+
const a = (await this.openDB()).transaction("chunkUploads", "readonly"), r = n ? a.store.index("[uploadId+status]") : a.store.index("[sessionId+status]"), o = n ? IDBKeyRange.only([n, t]) : IDBKeyRange.only([e, t]);
|
|
339
|
+
return r.getAll(o);
|
|
340
340
|
}
|
|
341
341
|
async getPendingCaptures(e = {}) {
|
|
342
342
|
return (await (await this.openDB()).getAllFromIndex("pendingCaptures", "sessionId", I)).filter((n) => !e.beforePresent || n.targetTimestamp < Date.now()).filter((n) => !e.isBeforeType || n.captureParams.replayParams.replayDurationType === "before").filter((n) => !e.isHeatmap || (n.captureParams.isHeatmap ?? !1));
|
|
@@ -350,43 +350,43 @@ const u = new class {
|
|
|
350
350
|
await t.done;
|
|
351
351
|
}
|
|
352
352
|
async markPendingHeatmapsReady(e) {
|
|
353
|
-
if (parseInt(
|
|
353
|
+
if (parseInt(m.getItem("sprig.pendingCount") ?? "0") === 0) return null;
|
|
354
354
|
const t = Date.now(), n = (await this.openDB()).transaction("pendingCaptures", "readwrite"), a = n.store.index("sessionId");
|
|
355
355
|
for await (const r of a.iterate(I)) {
|
|
356
|
-
const
|
|
357
|
-
!
|
|
356
|
+
const o = r.value;
|
|
357
|
+
!o.captureParams.isHeatmap || e && !e.includes(o.uuid) || await r.update({ ...o, targetTimestamp: t, captureParams: { ...o.captureParams, triggerTimestamp: t, replayParams: { ...o.captureParams.replayParams, replayDurationSeconds: Math.floor((t - o.timestamp) / 1e3) } } });
|
|
358
358
|
}
|
|
359
359
|
await n.done;
|
|
360
360
|
}
|
|
361
|
-
}(),
|
|
362
|
-
let F,
|
|
363
|
-
const O = () => G && !L && Date.now() <=
|
|
364
|
-
G && !a || (
|
|
365
|
-
},
|
|
366
|
-
if (!O()) return void window.clearInterval(
|
|
367
|
-
if (
|
|
368
|
-
const e =
|
|
361
|
+
}(), T = [];
|
|
362
|
+
let F, Ge, J, $e, V, Ke, _ = [], L = !1, N = 0, G = !1, We = !1, he = [], te = !1;
|
|
363
|
+
const O = () => G && !L && Date.now() <= J, Bt = ({ apiUrl: e, config: t, triggerSnapshot: n, forceInit: a = !1 }) => {
|
|
364
|
+
G && !a || (m.isStorageAvailable ? (_ = [], he.splice(0), T.splice(0), N = 0, V = n, Ge = e, F = { responseGroupUuid: t.responseGroupUuid, surveyId: t.surveyId, userAgent: t.userAgent, sdkVersion: t.sdkVersion }, $e = t.maxDurationSeconds, Nt(), G || (Ke = window.setInterval(_t, 500)), G = !0) : L = !0);
|
|
365
|
+
}, Mt = [U.Drag, U.Input, U.MediaInteraction, U.MouseInteraction, U.MouseMove, U.Scroll, U.Selection, U.TouchMove], At = (e) => e.type === B.Custom || e.type === B.IncrementalSnapshot && Mt.includes(e.data.source), Ie = (e) => e.some(At), _t = async () => {
|
|
366
|
+
if (!O()) return void window.clearInterval(Ke);
|
|
367
|
+
if (Je(), !Ie(T)) return;
|
|
368
|
+
const e = T[0].timestamp;
|
|
369
369
|
Date.now() - e > 35e3 && (V == null || V());
|
|
370
|
-
},
|
|
371
|
-
if (_.length ||
|
|
372
|
-
|
|
373
|
-
const e = await
|
|
370
|
+
}, Je = async () => {
|
|
371
|
+
if (_.length || te) return;
|
|
372
|
+
te = !0;
|
|
373
|
+
const e = await Ot();
|
|
374
374
|
if (!e) return void (L = !0);
|
|
375
|
-
|
|
376
|
-
},
|
|
377
|
-
const e =
|
|
375
|
+
he.splice(0, e.length).forEach((t) => t(e.shift())), e.forEach((t) => _.push(t)), te = !1;
|
|
376
|
+
}, Nt = () => {
|
|
377
|
+
const e = m.getItem("sprig.alwayson.info");
|
|
378
378
|
if (e) {
|
|
379
379
|
d.info("Read stored session state", e);
|
|
380
380
|
const t = JSON.parse(e);
|
|
381
|
-
L = t.disabled, F = t.metadata, _ = t.uploadUrls, N = t.currentIndex,
|
|
382
|
-
} else
|
|
383
|
-
},
|
|
384
|
-
const t = Date.now(), n = (await
|
|
385
|
-
if (!
|
|
386
|
-
|
|
387
|
-
const a = await
|
|
388
|
-
a && await
|
|
389
|
-
},
|
|
381
|
+
L = t.disabled, F = t.metadata, _ = t.uploadUrls, N = t.currentIndex, J = t.expirationTimestamp, t.pendingEventTimestamp && (d.info(`Uploading with pending timestamp: ${t.pendingEventTimestamp}`), Lt(t.pendingEventTimestamp));
|
|
382
|
+
} else J = 1e3 * $e + Date.now();
|
|
383
|
+
}, Lt = async (e) => {
|
|
384
|
+
const t = Date.now(), n = (await c.getEventsBetween(e, t)).map((r) => JSON.parse(r.event));
|
|
385
|
+
if (!Ie(n)) return;
|
|
386
|
+
Xe(n);
|
|
387
|
+
const a = await Qe();
|
|
388
|
+
a && await qe(a, n);
|
|
389
|
+
}, ze = async (e, t) => {
|
|
390
390
|
try {
|
|
391
391
|
const n = await e();
|
|
392
392
|
if (!n.ok) throw new Error(`Error ${t}`);
|
|
@@ -394,300 +394,304 @@ const O = () => G && !L && Date.now() <= W, Bt = ({ apiUrl: e, config: t, trigge
|
|
|
394
394
|
} catch {
|
|
395
395
|
L = !0;
|
|
396
396
|
}
|
|
397
|
-
},
|
|
397
|
+
}, qe = async (e, t) => {
|
|
398
398
|
if (!O() || !e) return;
|
|
399
399
|
const n = await (async (a) => {
|
|
400
|
-
const r = new TextEncoder(),
|
|
401
|
-
return
|
|
400
|
+
const r = new TextEncoder(), o = new CompressionStream("gzip"), s = o.writable.getWriter(), l = r.encode(JSON.stringify(a));
|
|
401
|
+
return s.write(l), s.close(), new Uint8Array(await new Response(o.readable).arrayBuffer());
|
|
402
402
|
})(t);
|
|
403
|
-
d.info("Uploading always-on events with presigned url"), await
|
|
404
|
-
},
|
|
403
|
+
d.info("Uploading always-on events with presigned url"), await ze(() => z(e, { body: n, method: "PUT" }), "uploading always-on with presigned url");
|
|
404
|
+
}, Ot = async () => {
|
|
405
405
|
if (!O()) return;
|
|
406
406
|
const { surveyId: e, responseGroupUuid: t } = F, n = { responseGroupUuid: t, surveyId: e, index: N + 1 };
|
|
407
407
|
d.info("Fetching always-on upload urls", n);
|
|
408
|
-
const a = await
|
|
408
|
+
const a = await ze(() => z(`${Ge}/sdk/1/replayUrls`, { method: "POST", body: JSON.stringify(n), headers: lt(window.UserLeap) }), "fetching always-on signed urls");
|
|
409
409
|
if (!a) return;
|
|
410
410
|
const r = a.json.signedUrls;
|
|
411
411
|
return d.info("Fetched more always-on upload urls", { body: n, urls: r }), r;
|
|
412
|
-
},
|
|
412
|
+
}, Qe = async () => {
|
|
413
413
|
if (_.length) return _.shift();
|
|
414
414
|
const e = new Promise((t) => {
|
|
415
|
-
|
|
415
|
+
he.push(t);
|
|
416
416
|
});
|
|
417
|
-
return
|
|
418
|
-
},
|
|
419
|
-
var r,
|
|
420
|
-
const t = e.length ? e[e.length - 1].timestamp : Date.now(), n = N, a = ((
|
|
417
|
+
return Je(), e;
|
|
418
|
+
}, Xe = (e) => {
|
|
419
|
+
var r, o, s;
|
|
420
|
+
const t = e.length ? e[e.length - 1].timestamp : Date.now(), n = N, a = ((o = (r = window.UserLeap) == null ? void 0 : r.config) == null ? void 0 : o.customMetadata) ?? ((s = window.__cfg) == null ? void 0 : s.customMetadata);
|
|
421
421
|
N++, e.push({ timestamp: t, type: B.Custom, data: { tag: "Sprig_Meta", payload: { ...F, index: n, visitorId: window.UserLeap.visitorId ?? "", timestamp: t, customMetadata: a } } });
|
|
422
|
-
},
|
|
423
|
-
O() && !
|
|
424
|
-
const n =
|
|
425
|
-
if (!
|
|
426
|
-
d.info("Capturing always-on event array to upload"),
|
|
427
|
-
const a = await
|
|
428
|
-
a && await
|
|
429
|
-
})(),
|
|
422
|
+
}, Ft = (e, t) => {
|
|
423
|
+
O() && !We && (e || T.length) && (e && T.length && (async () => {
|
|
424
|
+
const n = T.splice(0);
|
|
425
|
+
if (!Ie(n)) return;
|
|
426
|
+
d.info("Capturing always-on event array to upload"), Xe(n);
|
|
427
|
+
const a = await Qe();
|
|
428
|
+
a && await qe(a, n);
|
|
429
|
+
})(), T.push(t));
|
|
430
430
|
};
|
|
431
431
|
window.addEventListener("beforeunload", async () => {
|
|
432
|
-
|
|
432
|
+
We = !0, O() && (d.info("Always On handle page unload"), (() => {
|
|
433
433
|
let e;
|
|
434
|
-
|
|
435
|
-
const t = { disabled: L, metadata: F, uploadUrls: _, currentIndex: N, pendingEventTimestamp: e, expirationTimestamp:
|
|
436
|
-
d.info("Storing session state on unload", t),
|
|
434
|
+
T.length && (e = T[0].timestamp);
|
|
435
|
+
const t = { disabled: L, metadata: F, uploadUrls: _, currentIndex: N, pendingEventTimestamp: e, expirationTimestamp: J };
|
|
436
|
+
d.info("Storing session state on unload", t), m.setItem("sprig.alwayson.info", JSON.stringify(t));
|
|
437
437
|
})());
|
|
438
438
|
});
|
|
439
|
-
const
|
|
439
|
+
const Ze = async (e, t) => {
|
|
440
440
|
const n = performance.now();
|
|
441
441
|
let a;
|
|
442
442
|
try {
|
|
443
443
|
a = await e();
|
|
444
444
|
} finally {
|
|
445
445
|
const r = performance.now() - n;
|
|
446
|
-
let
|
|
447
|
-
|
|
446
|
+
let o = ke[t];
|
|
447
|
+
o || (o = Ue(t)), o.report(r / 1e3);
|
|
448
448
|
}
|
|
449
449
|
return a;
|
|
450
|
-
},
|
|
450
|
+
}, Ye = (e, t) => {
|
|
451
451
|
const n = performance.now();
|
|
452
452
|
try {
|
|
453
453
|
e();
|
|
454
454
|
} finally {
|
|
455
455
|
const a = performance.now() - n;
|
|
456
456
|
let r = ke[t];
|
|
457
|
-
r || (r =
|
|
457
|
+
r || (r = Ue(t)), r.report(a / 1e3);
|
|
458
458
|
}
|
|
459
459
|
};
|
|
460
|
-
let
|
|
461
|
-
const
|
|
460
|
+
let et = 5e3, ce = 6e4, pe = 0, A, ge = !1, me = [];
|
|
461
|
+
const Ht = (e) => {
|
|
462
462
|
var t, n, a, r;
|
|
463
463
|
if ((t = e.event) != null && t.includes("Sprig_Scroll")) {
|
|
464
|
-
const
|
|
465
|
-
if (!
|
|
466
|
-
g.scrollEventUuids[
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
},
|
|
470
|
-
|
|
471
|
-
if (
|
|
472
|
-
const e =
|
|
473
|
-
|
|
464
|
+
const o = (r = (a = (n = JSON.parse(e.event)) == null ? void 0 : n.data) == null ? void 0 : a.payload) == null ? void 0 : r.xPath;
|
|
465
|
+
if (!o) return;
|
|
466
|
+
g.scrollEventUuids[o] = e.uuid;
|
|
467
|
+
}
|
|
468
|
+
me.push(e), ge || jt();
|
|
469
|
+
}, jt = () => {
|
|
470
|
+
ge = !0, setTimeout(async () => {
|
|
471
|
+
if (P() || W()) return;
|
|
472
|
+
const e = me;
|
|
473
|
+
me = [], ge = !1, Ye(async () => {
|
|
474
474
|
await (async (t) => {
|
|
475
475
|
const n = t.map((a) => ({ ...a, sessionId: a.sessionId ?? I }));
|
|
476
|
-
if (n.length !== 0) return D(() =>
|
|
476
|
+
if (n.length !== 0) return D(() => c.bulkAdd("events", n), "Error storing replay events");
|
|
477
477
|
})(e);
|
|
478
478
|
}, "sdk_replay_add_event_batch_seconds");
|
|
479
479
|
}, 500);
|
|
480
|
-
},
|
|
480
|
+
}, Vt = (e, t, n) => {
|
|
481
481
|
g.cleanupInterval = window.setInterval(() => {
|
|
482
482
|
const a = Date.now();
|
|
483
|
-
|
|
484
|
-
|
|
483
|
+
Ze(() => D(async () => {
|
|
484
|
+
P() || await Promise.all([c.deleteRowsBefore("events", a - 1e3 * e, (r) => r.expiredAt === void 0 || r.expiredAt < a - 1e3 * e), c.deleteRowsBefore("chunkUploads", a - 1e3 * t), c.deleteRowsBefore("pendingCaptures", a - 1e3 * n, (r) => !r.canUpload)]);
|
|
485
485
|
}, "Error deleting table rows"), "sdk_replay_cleanup_seconds"), d.debug("CleanupComplete");
|
|
486
486
|
}, 3e4);
|
|
487
|
-
},
|
|
487
|
+
}, Gt = () => {
|
|
488
488
|
g.pendingCheckInterval = window.setInterval(async () => {
|
|
489
489
|
D(async () => {
|
|
490
|
-
await
|
|
490
|
+
await we();
|
|
491
491
|
}, "Error initiating pending captures");
|
|
492
492
|
}, 5e3);
|
|
493
493
|
};
|
|
494
|
-
let
|
|
495
|
-
const
|
|
496
|
-
if (!
|
|
497
|
-
|
|
498
|
-
const t = parseInt(
|
|
494
|
+
let ne = !1;
|
|
495
|
+
const we = async (e = !1) => {
|
|
496
|
+
if (!ne) try {
|
|
497
|
+
ne = !0;
|
|
498
|
+
const t = parseInt(A ?? "0");
|
|
499
499
|
if (t === 0) return;
|
|
500
|
-
const n = await
|
|
501
|
-
await Promise.all(n.map(async (r) => (await a.delete("pendingCaptures", r.uuid),
|
|
500
|
+
const n = await c.getPendingCaptures({ beforePresent: !0, isBeforeType: e }), a = await c.openDB();
|
|
501
|
+
await Promise.all(n.map(async (r) => (await a.delete("pendingCaptures", r.uuid), at(r.captureParams, r.canUpload)))), A = (t - n.length).toString(), m.setItem("sprig.pendingCount", A);
|
|
502
502
|
} finally {
|
|
503
|
-
|
|
503
|
+
ne = !1;
|
|
504
504
|
}
|
|
505
|
-
},
|
|
506
|
-
const
|
|
507
|
-
if (!(
|
|
505
|
+
}, $t = async (e, t, n, a, r) => {
|
|
506
|
+
const o = Math.min(e + r, n), s = await Ze(() => c.getEventsBetween(e, o), "sdk_replay_get_events_between_seconds");
|
|
507
|
+
if (!(s != null && s.length)) return d.debug("NoEventsFound"), { validStartFound: a, events: [] };
|
|
508
508
|
if (!a) {
|
|
509
509
|
d.debug("ValidStartSearch");
|
|
510
|
-
let
|
|
511
|
-
return
|
|
510
|
+
let l = -1;
|
|
511
|
+
return s == null || s.forEach((i, u) => {
|
|
512
512
|
if (!i.isValidStart) return;
|
|
513
|
-
const
|
|
514
|
-
(
|
|
515
|
-
}),
|
|
516
|
-
}
|
|
517
|
-
return { validStartFound: a, events:
|
|
518
|
-
},
|
|
519
|
-
const n = await (async (a) =>
|
|
520
|
-
var
|
|
513
|
+
const y = i.timestamp <= t;
|
|
514
|
+
(l < 0 || y) && (l = u);
|
|
515
|
+
}), l < 0 ? (d.debug("ValidStartNotFound"), { validStartFound: a, events: [] }) : { validStartFound: !0, events: s == null ? void 0 : s.slice(l) };
|
|
516
|
+
}
|
|
517
|
+
return { validStartFound: a, events: s };
|
|
518
|
+
}, tt = (e) => Promise.all(e.map(async (t) => {
|
|
519
|
+
const n = await (async (a) => Be.execute(async () => {
|
|
520
|
+
var s;
|
|
521
521
|
d.info("UploadChunkStart", { chunkIndex: a.chunkIndex, surveyId: a.surveyId });
|
|
522
|
-
const r = await
|
|
522
|
+
const r = await z(a.uploadUrl, { body: a.data, method: "PUT" });
|
|
523
523
|
d.http("UploadChunkEnd", { url: a.uploadUrl, method: "PUT", status_code: r.status, reason: r.statusText ?? "OK", chunkIndex: a.chunkIndex, surveyId: a.surveyId });
|
|
524
|
-
const
|
|
525
|
-
if (!
|
|
526
|
-
return
|
|
524
|
+
const o = (s = r.headers) == null ? void 0 : s.get("ETag");
|
|
525
|
+
if (!o) throw new Error(`Upload response did not include etag for upload ${a.uploadId}, part ${a.chunkIndex}`);
|
|
526
|
+
return o;
|
|
527
527
|
}))(t);
|
|
528
|
-
return await
|
|
529
|
-
})),
|
|
530
|
-
const t = await
|
|
528
|
+
return await c.updatePartial("chunkUploads", t.uuid, { data: null, etag: n, status: "UploadComplete" }), t.uploadId;
|
|
529
|
+
})), nt = async (e) => {
|
|
530
|
+
const t = await c.getChunkUploadsByStatus({ status: "UploadComplete", uploadId: e });
|
|
531
531
|
if (!(t != null && t.length)) return void d.info("NoChunksForUpload", { uploadId: e });
|
|
532
|
-
const n = t.reduce((
|
|
533
|
-
n.sort((
|
|
534
|
-
const a = n.map((
|
|
535
|
-
await
|
|
536
|
-
},
|
|
532
|
+
const n = t.reduce((o, s) => (o.find((l) => l.chunkIndex === s.chunkIndex) || o.push(s), o), []);
|
|
533
|
+
n.sort((o, s) => o.chunkIndex - s.chunkIndex);
|
|
534
|
+
const a = n.map((o) => ({ ETag: o.etag, PartNumber: o.chunkIndex })).filter((o) => o.ETag !== null), r = n[0];
|
|
535
|
+
await Me({ apiUrl: r.apiUrl, surveyId: r.surveyId, uploadId: e, responseGroupUuid: r.responseGroupId, etags: a, headers: r.completeUploadHeaders, replayDuration: r.replayDuration }), await c.deleteChunkUploads("UploadComplete", e);
|
|
536
|
+
}, Kt = () => {
|
|
537
537
|
D(async () => {
|
|
538
|
-
const e = await
|
|
538
|
+
const e = await c.getChunkUploadsByStatus({ sessionId: I, status: "ReadyForUpload" });
|
|
539
539
|
if (!(e != null && e.length)) return;
|
|
540
|
-
const t = await
|
|
540
|
+
const t = await tt(e);
|
|
541
541
|
t != null && t.length && await Promise.all(t.map((n) => {
|
|
542
|
-
if (n) return
|
|
542
|
+
if (n) return nt(n);
|
|
543
543
|
}));
|
|
544
544
|
}, "Error uploading unfinished chunks");
|
|
545
|
-
},
|
|
545
|
+
}, Wt = async (e, t) => {
|
|
546
546
|
const n = t ?? Date.now();
|
|
547
547
|
return (async (a, r) => {
|
|
548
|
-
const
|
|
549
|
-
let
|
|
550
|
-
const
|
|
551
|
-
let
|
|
552
|
-
for (let
|
|
553
|
-
if ({ validStartFound:
|
|
548
|
+
const o = new TextEncoder();
|
|
549
|
+
let s = null;
|
|
550
|
+
const l = new CompressionStream("gzip"), i = l.writable.getWriter();
|
|
551
|
+
let u = !1, y = !1, [p, h] = [0, 0], w = [];
|
|
552
|
+
for (let k = a - 35e3; k < r; k += ce) {
|
|
553
|
+
if ({ validStartFound: y, events: w } = await $t(k, a, r, y, ce), !(w != null && w.length)) {
|
|
554
554
|
d.debug("NoEventsFound");
|
|
555
555
|
continue;
|
|
556
556
|
}
|
|
557
|
-
p === 0 && (p =
|
|
558
|
-
const f =
|
|
557
|
+
p === 0 && (p = w[0].timestamp), h = w[w.length - 1].timestamp;
|
|
558
|
+
const f = w.map((R) => R.event);
|
|
559
559
|
f.push(`{"timestamp":${r}}`);
|
|
560
|
-
const v = `${
|
|
561
|
-
|
|
560
|
+
const v = `${u ? "," : "["}${f}`, S = o.encode(v);
|
|
561
|
+
Ye(() => {
|
|
562
562
|
i.write(S);
|
|
563
|
-
}, "sdk_replay_compression_seconds"),
|
|
563
|
+
}, "sdk_replay_compression_seconds"), u = !0;
|
|
564
564
|
}
|
|
565
|
-
if (h - p <
|
|
566
|
-
const E =
|
|
567
|
-
return i.write(E), i.close(),
|
|
565
|
+
if (h - p < et) return d.debug("ReplayTooShort"), null;
|
|
566
|
+
const E = o.encode("]");
|
|
567
|
+
return i.write(E), i.close(), s = new Uint8Array(await new Response(l.readable).arrayBuffer()), s;
|
|
568
568
|
})(n - e, n);
|
|
569
|
-
},
|
|
570
|
-
const { surveyId: t, responseGroupId: n, visitorId: a, apiUrl: r, completeUploadHeaders:
|
|
569
|
+
}, Pe = async (e) => {
|
|
570
|
+
const { surveyId: t, responseGroupId: n, visitorId: a, apiUrl: r, completeUploadHeaders: o, replayParams: s, triggerTimestamp: l } = e, i = await Wt(1e3 * s.replayDurationSeconds, l);
|
|
571
571
|
if (!(i != null && i.length)) return void d.info("FileDataEmpty", { surveyId: t });
|
|
572
|
-
const
|
|
573
|
-
const E = p.length,
|
|
574
|
-
let
|
|
575
|
-
for (;
|
|
572
|
+
const u = ((p, h, w) => {
|
|
573
|
+
const E = p.length, k = 1024 * h * 1024, f = Math.ceil(E / w), v = Math.max(k, f), S = [];
|
|
574
|
+
let R = 0;
|
|
575
|
+
for (; R < E; ) S.push(p.slice(R, R + v)), R += v;
|
|
576
576
|
return S;
|
|
577
|
-
})(i,
|
|
578
|
-
const
|
|
579
|
-
return await (await
|
|
577
|
+
})(i, s.minimumChunkSizeMb, s.signedUrls.length), y = await Promise.all(u.map(async (p, h) => {
|
|
578
|
+
const w = q(), E = { apiUrl: r, chunkIndex: h + 1, completeUploadHeaders: o, etag: null, responseGroupId: n, status: "ReadyForUpload", surveyId: t, timestamp: l, totalChunks: u.length, data: p, uploadId: s.uploadId, uploadUrl: s.signedUrls[h].url, uuid: w, visitorId: a };
|
|
579
|
+
return await (await c.openDB()).add("chunkUploads", { ...E, sessionId: E.sessionId ?? I }), E;
|
|
580
580
|
}));
|
|
581
581
|
await (async (p, h) => {
|
|
582
|
-
await
|
|
583
|
-
})([
|
|
584
|
-
},
|
|
585
|
-
if (
|
|
586
|
-
const { isHeatmap: n, isStandalone: a, replayParams: r, triggerTimestamp:
|
|
587
|
-
setTimeout(() => H.removeListener(
|
|
588
|
-
r.replayDurationType === "before" ? await
|
|
582
|
+
await tt(h), await Promise.all(p.map((w) => nt(w)));
|
|
583
|
+
})([s.uploadId], y);
|
|
584
|
+
}, at = async (e, t) => {
|
|
585
|
+
if (P()) return d.debug("ReplayDisabled-ScheduleOrCapture");
|
|
586
|
+
const { isHeatmap: n, isStandalone: a, replayParams: r, triggerTimestamp: o, responseGroupId: s } = e, l = async () => {
|
|
587
|
+
setTimeout(() => H.removeListener(Z.QuestionAnswered, l), 0), D(async () => {
|
|
588
|
+
r.replayDurationType === "before" ? await Pe(e) : await c.markPendingCaptureToCanUpload(s);
|
|
589
589
|
}, "Error in schedule/capture callback");
|
|
590
590
|
};
|
|
591
591
|
D(async () => {
|
|
592
592
|
if (r.replayDurationType === "after" || r.replayDurationType === "beforeAndAfter")
|
|
593
|
-
return !a && !n && H.on(
|
|
594
|
-
if (a || n || t) await
|
|
593
|
+
return !a && !n && H.on(Z.QuestionAnswered, l), void await ot(e);
|
|
594
|
+
if (a || n || t) await Pe(e), n && Jt();
|
|
595
595
|
else {
|
|
596
|
-
const i = 35 + r.replayDurationSeconds,
|
|
597
|
-
await
|
|
596
|
+
const i = 35 + r.replayDurationSeconds, u = o - 1e3 * i, y = o;
|
|
597
|
+
await c.updateEventsExpiredAt(u, y, r.expirationTimeLimitMinutes), H.on(Z.QuestionAnswered, l);
|
|
598
598
|
}
|
|
599
599
|
}, "Error in scheduling/capturing replay");
|
|
600
|
-
},
|
|
601
|
-
parseInt(
|
|
602
|
-
},
|
|
603
|
-
|
|
604
|
-
}),
|
|
605
|
-
if (
|
|
606
|
-
const { isHeatmap: t, surveyId: n } = e, a = await
|
|
600
|
+
}, Jt = async () => {
|
|
601
|
+
parseInt(A ?? "0") || m.removeItem("sprig.isCapturingHeatmap"), m.getItem("sprig.teardownAfterCapture") && (Ve(), rt(), m.removeItem("sprig.teardownAfterCapture"));
|
|
602
|
+
}, rt = async () => P() ? d.debug("ReplayDisabled-ClearData") : Promise.all([c.deleteBySessionId("events", I), c.deleteBySessionId("pendingCaptures", I)]).catch((e) => {
|
|
603
|
+
Q("Error clearing user replay data", e);
|
|
604
|
+
}), ot = async (e) => {
|
|
605
|
+
if (P()) return;
|
|
606
|
+
const { isHeatmap: t, surveyId: n } = e, a = await c.getPendingCaptures(), r = a == null ? void 0 : a.filter((i) => i.captureParams.surveyId === n);
|
|
607
607
|
if (r != null && r.length) return void d.info("PendingCaptureExists", { surveyId: n });
|
|
608
|
-
t && (
|
|
608
|
+
t && (ue(), m.setItem("sprig.isCapturingHeatmap", "true"), pe = Date.now(), g.inactivityInterval || (g.inactivityInterval = window.setInterval(() => {
|
|
609
609
|
var i;
|
|
610
|
-
i =
|
|
610
|
+
i = pe, Date.now() - i >= 3e4 && D(() => c.markPendingHeatmapsReady(), "Error in heatmap inactivity");
|
|
611
611
|
}, 1e3)));
|
|
612
|
-
const
|
|
613
|
-
e.replayParams.replayDurationType === "beforeAndAfter" && (
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
},
|
|
617
|
-
|
|
612
|
+
const o = { ...e, replayParams: { ...e.replayParams } };
|
|
613
|
+
e.replayParams.replayDurationType === "beforeAndAfter" && (o.replayParams.replayDurationSeconds *= 2), o.replayParams.replayDurationType = "before";
|
|
614
|
+
const s = e.triggerTimestamp + 1e3 * e.replayParams.replayDurationSeconds;
|
|
615
|
+
o.triggerTimestamp = s, A = (parseInt(A ?? "0") + 1).toString(), m.setItem("sprig.pendingCount", A), await (await c.openDB()).add("pendingCaptures", { canUpload: !1, captureParams: o, sessionId: I, targetTimestamp: s, timestamp: Date.now(), uuid: q() });
|
|
616
|
+
}, zt = Object.freeze(Object.defineProperty({ __proto__: null, RecordEvent: (e) => {
|
|
617
|
+
x("Sprig_TrackEvent", e);
|
|
618
618
|
}, RecordPageView: (e) => {
|
|
619
|
-
e.description && (e.description =
|
|
619
|
+
e.description && (e.description = fe(e.description)), x("Sprig_PageView", e);
|
|
620
620
|
}, RecordSurveyShown: (e) => {
|
|
621
|
-
|
|
621
|
+
x("Sprig_ShowSurvey", e);
|
|
622
622
|
}, _completeSessionReplay: async ({ surveyId: e, responseGroupUuid: t, eventDigest: n, headers: a }) => {
|
|
623
623
|
if (!e || !t) return !1;
|
|
624
|
-
const r = window.UserLeap._API_URL,
|
|
625
|
-
return !(
|
|
626
|
-
}, checkPendingHeatmapsUrl: () =>
|
|
627
|
-
const e = (await
|
|
628
|
-
return d.info("PendingHeatmapsToComplete", { count: e.length }), e.length && (await
|
|
629
|
-
}, "Error marking pending heatmaps ready"), clearUserReplayData:
|
|
630
|
-
if (
|
|
631
|
-
|
|
632
|
-
} }),
|
|
633
|
-
if (a &&
|
|
624
|
+
const r = window.UserLeap._API_URL, o = await Me({ surveyId: e, responseGroupUuid: t, eventDigest: n, apiUrl: r, headers: a }, !0);
|
|
625
|
+
return !(o != null && o.error);
|
|
626
|
+
}, checkPendingHeatmapsUrl: () => P() ? d.debug("ReplayDisabled-PendingHeatmaps") : D(async () => {
|
|
627
|
+
const e = (await c.getPendingCaptures({ isHeatmap: !0 })).map((t) => ({ eventId: t.captureParams.eventId, uuid: t.uuid })).filter(({ eventId: t }) => !dt(t)).map(({ uuid: t }) => t);
|
|
628
|
+
return d.info("PendingHeatmapsToComplete", { count: e.length }), e.length && (await c.markPendingHeatmapsReady(e), d.info("MarkedPendingHeatmapsReady")), e.length;
|
|
629
|
+
}, "Error marking pending heatmaps ready"), clearUserReplayData: rt, disableRecording: Q, initializeReplay: async ({ maxReplayDurationSeconds: e, maxInflightRequests: t = 2, replaySettings: n, teardownAfter: a = !1, apiUrl: r, alwaysOnConfig: o }) => {
|
|
630
|
+
if (o && Bt({ apiUrl: r, config: o, triggerSnapshot: () => {
|
|
631
|
+
ue();
|
|
632
|
+
} }), A = m.getItem("sprig.pendingCount"), g.isRecording) return;
|
|
633
|
+
if (a && m.setItem("sprig.teardownAfterCapture", "true"), P()) return d.debug("ReplayDisabled");
|
|
634
634
|
if (await (async () => {
|
|
635
635
|
var i;
|
|
636
|
-
if (!
|
|
636
|
+
if (!je()) return !0;
|
|
637
637
|
if ((i = window.navigator.storage) != null && i.estimate) try {
|
|
638
|
-
const { quota:
|
|
638
|
+
const { quota: u = 0, usage: y = 0 } = await window.navigator.storage.estimate(), p = (u - y) / 1024 ** 3;
|
|
639
639
|
return d.info("Storage", { availableGb: p }), p < 0.5;
|
|
640
640
|
} catch {
|
|
641
641
|
return !0;
|
|
642
642
|
}
|
|
643
643
|
return !1;
|
|
644
|
-
})()) return d.debug("IDBNotSupported"),
|
|
644
|
+
})()) return d.debug("IDBNotSupported"), le();
|
|
645
645
|
try {
|
|
646
|
-
const i = await
|
|
646
|
+
const i = await c.openDB();
|
|
647
647
|
d.info("DBVersion", { version: i.version });
|
|
648
648
|
} catch (i) {
|
|
649
|
-
return d.error("ReplayOpenErr", { name: i.name }), i.name === "VersionError" &&
|
|
649
|
+
return d.error("ReplayOpenErr", { name: i.name }), i.name === "VersionError" && c.deleteDB(), le();
|
|
650
650
|
}
|
|
651
651
|
D(async () => {
|
|
652
|
-
await
|
|
652
|
+
await we(!0);
|
|
653
653
|
}, "Error uploading ready pending captures");
|
|
654
|
-
const
|
|
655
|
-
if (!
|
|
654
|
+
const s = O() ? 30 : 0, l = Math.max(e ?? 0, s);
|
|
655
|
+
if (!l) return d.debug("MissingDuration");
|
|
656
656
|
d.debug("ReplayInit"), await D(async () => {
|
|
657
657
|
var i;
|
|
658
|
-
n != null && n.minDuration && (
|
|
659
|
-
const
|
|
658
|
+
n != null && n.minDuration && (et = n.minDuration), n != null && n.batchDuration && (ce = n.batchDuration), i = t, Be.setLimit(i), Kt(), Vt(l + 35, 1800, l + 35), Gt();
|
|
659
|
+
const u = window.UserLeap.replayLibraryURL ?? "https://cdn.sprig.com/dependencies/record-2.0.0-alpha.17.min.js";
|
|
660
660
|
if (!window.rrwebRecord) {
|
|
661
661
|
const { record: f } = await import(
|
|
662
662
|
/* webpackIgnore: true */
|
|
663
663
|
/* @vite-ignore */
|
|
664
|
-
|
|
664
|
+
u
|
|
665
665
|
);
|
|
666
666
|
window.rrwebRecord = f;
|
|
667
667
|
}
|
|
668
|
-
const
|
|
669
|
-
if (!
|
|
668
|
+
const y = window.rrwebRecord;
|
|
669
|
+
if (!y) return d.error("RecordScriptFailed");
|
|
670
670
|
let p = !0, h = 0;
|
|
671
|
-
const
|
|
672
|
-
var E,
|
|
673
|
-
g.stopRecording =
|
|
674
|
-
if (f.type === B.Custom && (
|
|
671
|
+
const w = { checkoutEveryNms: 3e4, sampling: { input: "last", scroll: 250, media: 800 }, ...n };
|
|
672
|
+
var E, k;
|
|
673
|
+
g.stopRecording = y({ emit: (f, v) => {
|
|
674
|
+
if (f.type === B.Custom && (pe = Date.now()), P() || W()) return;
|
|
675
675
|
if (v && f.type === B.Meta) h = performance.now();
|
|
676
676
|
else if (v && h && f.type === B.FullSnapshot) {
|
|
677
|
-
const
|
|
678
|
-
|
|
677
|
+
const R = performance.now() - h;
|
|
678
|
+
ut("sdk_replay_snapshot_seconds", R / 1e3);
|
|
679
679
|
}
|
|
680
680
|
const S = p || !!v && f.type === B.Meta;
|
|
681
|
-
p = !1,
|
|
682
|
-
}, ...
|
|
681
|
+
p = !1, Ft(S, f), Ht({ uuid: q(), event: JSON.stringify(f), isValidStart: S, timestamp: Date.now() });
|
|
682
|
+
}, ...w }), g.isRecording = !!g.stopRecording, g.isRecording && (((f, v) => {
|
|
683
683
|
window.addEventListener("message", (S) => {
|
|
684
|
-
var
|
|
685
|
-
S.data.type ===
|
|
684
|
+
var R;
|
|
685
|
+
S.data.type === It && (ye.push({ source: S.source, origin: S.origin }), (R = S.source) == null || R.postMessage({ type: vt, settings: f, replayLibraryUrl: v }, { targetOrigin: S.origin }));
|
|
686
686
|
});
|
|
687
|
-
})(
|
|
687
|
+
})(w, u), H.on("survey.complete", (f) => {
|
|
688
688
|
var v;
|
|
689
|
-
v = { id: f, userAgent: window.navigator.userAgent },
|
|
690
|
-
}), E =
|
|
689
|
+
v = { id: f, userAgent: window.navigator.userAgent }, x("Sprig_SubmitSurvey", v);
|
|
690
|
+
}), E = x, k = Ut, K || (b = E, j = k, window.addEventListener("click", Oe, C), window.addEventListener("pointerdown", He, C), window.addEventListener("mousedown", Fe, C), window.addEventListener("keydown", Ne, C), window.addEventListener("scroll", Le, C), K = !0, Pt(), kt()));
|
|
691
691
|
}, "Error initializing replay");
|
|
692
|
-
}, isReplayRecording: () => g.isRecording,
|
|
693
|
-
|
|
692
|
+
}, isReplayPaused: W, isReplayRecording: () => g.isRecording, recordFullSnapshot: ue, recordReplayPaused: () => {
|
|
693
|
+
x("Sprig_ReplayPaused", { timestamp: Date.now() }), m.setItem("sprig.isReplayPaused", "true");
|
|
694
|
+
}, recordReplayResumed: () => {
|
|
695
|
+
m.removeItem("sprig.isReplayPaused"), x("Sprig_ReplayResumed", { timestamp: Date.now() });
|
|
696
|
+
}, scheduleCapture: ot, scheduleOrCaptureReplay: at, tryReplayAction: D, uploadReadyPendingCaptures: we }, Symbol.toStringTag, { value: "Module" }));
|
|
697
|
+
ct(zt);
|