@sprig-technologies/sprig-browser
Version:
npm package for the sprig web sdk
367 lines (366 loc) • 14.4 kB
JavaScript
var T = Object.defineProperty;
var P = (e, t, s) => t in e ? T(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
var l = (e, t, s) => (P(e, typeof t != "symbol" ? t + "" : t, s), s);
var M = ((e) => (e.Closed = "close.click", e.Complete = "survey.completed", e.FeedbackClosed = "feedback.closed", e.PageChange = "page.change", e.API = "api", e.Override = "override", e))(M || {}), N = ((e) => (e.ReplayCapture = "replay.capture", e.FeedbackButtonLoaded = "feedback.button.loaded", e.SDKReady = "sdk.ready", e.SurveyAppeared = "survey.appeared", e.SurveyCloseRequested = "survey.closeRequested", e.SurveyClosed = "survey.closed", e.SurveyDimensions = "survey.dimensions", e.SurveyFadingOut = "survey.fadingOut", e.SurveyHeight = "survey.height", e.SurveyPresented = "survey.presented", e.SurveyLifeCycle = "survey.lifeCycle", e.SurveyWidth = "survey.width", e.SurveyWillClose = "survey.willClose", e.SurveyWillPresent = "survey.will.present", e.CloseSurveyOnOverlayClick = "close.survey.overlayClick", e.VisitorIDUpdated = "visitor.id.updated", e.QuestionAnswered = "question.answered", e))(N || {});
const X = { FEEDBACK_BUTTON_LOADED: "feedback.button.loaded", SDK_READY: "sdk.ready", SURVEY_APPEARED: "survey.appeared", SURVEY_CLOSED: "survey.closed", SURVEY_DIMENSIONS: "survey.dimensions", SURVEY_FADING_OUT: "survey.fadingOut", SURVEY_HEIGHT: "survey.height", SURVEY_WIDTH: "survey.width", SURVEY_PRESENTED: "survey.presented", SURVEY_LIFE_CYCLE: "survey.lifeCycle", SURVEY_WILL_CLOSE: "survey.willClose", SURVEY_WILL_PRESENT: "survey.will.present", QUESTION_ANSWERED: "question.answered", REPLAY_CAPTURE: "replay.capture", CLOSE_SURVEY_ON_OVERLAY_CLICK: "close.survey.overlayClick", VISITOR_ID_UPDATED: "visitor.id.updated", DATA: { DISMISS_REASONS: { API: "api", CLOSED: "close.click", COMPLETE: "survey.completed", PAGE_CHANGE: "page.change", OVERRIDE: "override" }, SURVEY_ID: "survey.id" } };
let m;
const V = new Uint8Array(16);
function W() {
if (!m && (m = typeof crypto < "u" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto), !m))
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
return m(V);
}
const a = [];
for (let e = 0; e < 256; ++e)
a.push((e + 256).toString(16).slice(1));
const f = { randomUUID: typeof crypto < "u" && crypto.randomUUID && crypto.randomUUID.bind(crypto) };
function Z(e, t, s) {
if (f.randomUUID && !t && !e)
return f.randomUUID();
const r = (e = e || {}).random || (e.rng || W)();
return r[6] = 15 & r[6] | 64, r[8] = 63 & r[8] | 128, function(n, i = 0) {
return a[n[i + 0]] + a[n[i + 1]] + a[n[i + 2]] + a[n[i + 3]] + "-" + a[n[i + 4]] + a[n[i + 5]] + "-" + a[n[i + 6]] + a[n[i + 7]] + "-" + a[n[i + 8]] + a[n[i + 9]] + "-" + a[n[i + 10]] + a[n[i + 11]] + a[n[i + 12]] + a[n[i + 13]] + a[n[i + 14]] + a[n[i + 15]];
}(r);
}
const Y = new class {
constructor() {
l(this, "breadcrumbs", []);
}
getTimeStamp() {
return (/* @__PURE__ */ new Date()).toISOString();
}
addBreadcrumb(e) {
this.breadcrumbs.push(e), this.breadcrumbs.length > 300 && this.breadcrumbs.shift();
}
debug(e, t = "debug") {
this.addBreadcrumb({ category: t, level: "info", message: e, timestamp: this.getTimeStamp(), type: "debug" });
}
error(e, t = {}) {
this.addBreadcrumb({ category: "error", data: t, level: "error", message: e, timestamp: this.getTimeStamp(), type: "error" });
}
http(e, t) {
this.addBreadcrumb({ category: "xhr", data: t, message: e, timestamp: this.getTimeStamp(), type: "http" });
}
info(e, t = {}) {
this.addBreadcrumb({ category: "info", data: t, level: "info", message: e, timestamp: this.getTimeStamp(), type: "info" });
}
navigation(e, t) {
this.addBreadcrumb({ category: "navigation", data: t, message: e, timestamp: this.getTimeStamp(), type: "navigation" });
}
}();
var j = class extends Error {
constructor(e, t, s) {
super(`Possible EventEmitter memory leak detected. ${s} ${t.toString()} listeners added. Use emitter.setMaxListeners() to increase limit`), this.emitter = e, this.type = t, this.count = s, this.name = "MaxListenersExceededWarning";
}
}, I = class {
static listenerCount(e, t) {
return e.listenerCount(t);
}
constructor() {
this.events = /* @__PURE__ */ new Map(), this.maxListeners = I.defaultMaxListeners, this.hasWarnedAboutPotentialMemoryLeak = !1;
}
_emitInternalEvent(e, t, s) {
this.emit(e, t, s);
}
_getListeners(e) {
return Array.prototype.concat.apply([], this.events.get(e)) || [];
}
_removeListener(e, t) {
const s = e.indexOf(t);
return s > -1 && e.splice(s, 1), [];
}
_wrapOnceListener(e, t) {
const s = (...r) => (this.removeListener(e, s), t.apply(this, r));
return Object.defineProperty(s, "name", { value: t.name }), s;
}
setMaxListeners(e) {
return this.maxListeners = e, this;
}
getMaxListeners() {
return this.maxListeners;
}
eventNames() {
return Array.from(this.events.keys());
}
emit(e, ...t) {
const s = this._getListeners(e);
return s.forEach((r) => {
r.apply(this, t);
}), s.length > 0;
}
addListener(e, t) {
this._emitInternalEvent("newListener", e, t);
const s = this._getListeners(e).concat(t);
if (this.events.set(e, s), this.maxListeners > 0 && this.listenerCount(e) > this.maxListeners && !this.hasWarnedAboutPotentialMemoryLeak) {
this.hasWarnedAboutPotentialMemoryLeak = !0;
const r = new j(this, e, this.listenerCount(e));
console.warn(r);
}
return this;
}
on(e, t) {
return this.addListener(e, t);
}
once(e, t) {
return this.addListener(e, this._wrapOnceListener(e, t));
}
prependListener(e, t) {
const s = this._getListeners(e);
if (s.length > 0) {
const r = [t].concat(s);
this.events.set(e, r);
} else
this.events.set(e, s.concat(t));
return this;
}
prependOnceListener(e, t) {
return this.prependListener(e, this._wrapOnceListener(e, t));
}
removeListener(e, t) {
const s = this._getListeners(e);
return s.length > 0 && (this._removeListener(s, t), this.events.set(e, s), this._emitInternalEvent("removeListener", e, t)), this;
}
off(e, t) {
return this.removeListener(e, t);
}
removeAllListeners(e) {
return e ? this.events.delete(e) : this.events.clear(), this;
}
listeners(e) {
return Array.from(this._getListeners(e));
}
listenerCount(e) {
return this._getListeners(e).length;
}
rawListeners(e) {
return this.listeners(e);
}
}, R = I;
R.defaultMaxListeners = 10;
const ee = new R(), L = async (e) => {
await new Promise((t) => {
setTimeout(t, e);
});
}, te = ({ "userleap-platform": e }) => {
var t;
return ((t = window.UserLeap) == null ? void 0 : t.forceDirectEmbed) || e !== "web";
};
class O {
constructor(t) {
l(this, "storage");
l(this, "tempStorage", {});
l(this, "isStorageAvailable");
try {
this.storage = window[t];
const s = "__storage_test__";
this.storage.setItem(s, s), this.storage.removeItem(s), this.isStorageAvailable = !0;
} catch {
this.isStorageAvailable = !1;
}
}
setItem(t, s) {
this.isStorageAvailable && this.storage ? this.storage.setItem(t, s) : this.tempStorage[t] = s;
}
setItemObject(t, s) {
try {
this.setItem(t, JSON.stringify(s));
} catch (r) {
r instanceof Error && (r.stack = t + ": " + s, window.UserLeap.reportError("Failed to save to local storage", r));
}
}
getItem(t) {
return this.isStorageAvailable && this.storage ? this.storage.getItem(t) : this.tempStorage[t];
}
getItemObject(t) {
const s = this.getItem(t);
if (s)
try {
return JSON.parse(s);
} catch (r) {
r instanceof Error && (r.stack = t + ": " + s, window.UserLeap.reportError("Failed to parse local storage", r));
}
return {};
}
removeItem(t) {
this.isStorageAvailable && this.storage ? this.storage.removeItem(t) : delete this.tempStorage[t];
}
clear() {
this.isStorageAvailable && this.storage ? this.storage.clear() : this.tempStorage = {};
}
}
const se = new O("sessionStorage"), re = new O("localStorage");
class q {
constructor(t) {
l(this, "payload");
l(this, "promise");
l(this, "reject", () => {
});
l(this, "resolve", () => {
});
this.payload = t, this.promise = new Promise((s, r) => {
this.reject = r, this.resolve = s;
});
}
resolveRequest(t) {
this.resolve(t);
}
}
const k = { replay: null }, ne = (e) => {
k.replay = e;
}, B = () => {
const e = [];
return k.replay && e.push("replay"), e.join(",");
}, F = 10;
let U = !1, A = "", y = !1, D = !1, g = [];
const J = (e) => e._config && e._config.installationMethod ? e._config.installationMethod : e._gtm ? "web-gtm" : e._segment ? "web-segment" : "web-snippet", ie = (e) => {
var t;
(t = e == null ? void 0 : e.blockedURI) != null && t.includes(window.UserLeap._API_URL) && (D = !0, console.warn(`[Sprig] ${e.blockedURI} is blocked by Content-Security-Policy`));
}, H = (e = "") => {
U = !0, A = e;
};
function ae(e = {}) {
const t = { "Content-Type": "application/json", "userleap-platform": "web", "x-ul-sdk-version": "2.33.1", "x-ul-installation-method": J(e), "sprig-modules": B() };
if (e.envId && (t["x-ul-environment-id"] = e.envId), e.token && (t.Authorization = "Bearer " + e.token), e.userId && (t["x-ul-user-id"] = e.userId), e.visitorId && (t["x-ul-visitor-id"] = e.visitorId), e.partnerAnonymousId && (t["x-ul-anonymous-id"] = e.partnerAnonymousId), e.mobileHeadersJSON) {
const s = JSON.parse(e.mobileHeadersJSON);
Object.assign(t, s);
}
return e.locale && (t["accept-language"] = e.locale), window.previewMode && (t["x-ul-preview-mode"] = "1"), t;
}
const w = async ({ shouldDropOnRateLimit: e, ...t }) => {
if (e)
return { status: 429 };
{
const s = new q(t);
return g.push(s), s.promise;
}
}, v = async (e, t) => {
const { retries: s = 0, shouldDropOnRateLimit: r = !1, shouldRetryRequest: n = !1, ...i } = t, d = { url: e, options: i, retries: s, shouldDropOnRateLimit: r };
if (y && !n)
return w(d);
const u = { ok: !1, reportError: !1 };
if (U)
return console.info(`UserLeap - ${A}`), u;
try {
const c = await fetch(e, i);
if (c.status === 429) {
if (!y && !r || n) {
y = !0;
const o = c.headers.has("ratelimit-reset") ? Number(c.headers.get("ratelimit-reset")) : F;
return await L(1e3 * o), v(e, { ...i, shouldDropOnRateLimit: r, shouldRetryRequest: !0 });
}
return w(d);
}
if (y = !1, g.length && (g.map((o) => {
const h = o.payload;
v(h.url, { ...h.options, retries: h.retries, shouldDropOnRateLimit: h.shouldDropOnRateLimit }).then((x) => {
o.resolveRequest(x);
});
}), g = []), c.ok) {
if (c.status === 249)
return H(), u;
const o = await c.text();
try {
return o && o !== "OK" && (c.json = JSON.parse(o)), c;
} catch {
return { ok: !1, reportError: !1, error: new Error(`failed parsing response json for ${e} - ${o}`) };
}
}
return c;
} catch (c) {
const o = s + 1;
return o > 5 || D ? { ok: !1, reportError: !1, error: c } : (await L(1e3 * Math.pow(2, s)), v(e, { ...i, retries: o }));
}
}, b = Object.freeze({ contains: (e, t) => t.includes(e), notContains: (e, t) => !t.includes(e), exactly: (e, t) => t === e, notExactly: (e, t) => t !== e, startsWith: (e, t) => t.startsWith(e), endsWith: (e, t) => t.endsWith(e), regex: (e, t) => new RegExp(e).test(t), legacy: (e, t) => new RegExp(e, "i").test(t) });
function $(e, t) {
const { matchType: s, pattern: r } = e, n = s ? b[s] : b.legacy;
let i = !1;
try {
i = n(r, t);
} catch (d) {
const u = `[Sprig] (ERR-445) Failed to check url match with pattern ${r}`;
d instanceof Error && (console.warn(u, d), d.stack = JSON.stringify(e), window.UserLeap.reportError(u, d));
}
return i;
}
const oe = (e) => {
const { pageUrlEvents: t } = window.UserLeap._config, s = t == null ? void 0 : t.find((r) => r.id === e);
return !!s && $(s, window.location.href);
};
let C = !0, S = !1;
const ce = () => S = !0, K = ["sdk_event_queue_latency_seconds", "sdk_replay_add_event_batch_seconds", "sdk_replay_cleanup_seconds", "sdk_replay_compression_seconds", "sdk_replay_get_events_between_seconds", "sdk_replay_snapshot_seconds", "sdk_mutations_nodes_added", "sdk_mutations_nodes_removed", "sdk_mutations_attributes_changed", "sdk_mutations_character_data", "sdk_dom_nodes_count", "sdk_page_html_characters"];
let _, p = {};
class G {
constructor(t) {
l(this, "_values", []);
l(this, "_isWebMetric");
this.name = t, this._isWebMetric = K.includes(this.name);
}
report(t) {
if (C && this._values.push({ time: Date.now(), value: t }), S || !this._isWebMetric)
return;
const s = this.findExceededThreshold(t);
s && _ && _(t, s);
}
collect() {
const t = this._values;
return this._values = [], t;
}
findExceededThreshold(t) {
const s = p[this.name];
if (s)
return s.find((r) => this.valueExceedsThreshold(t, r));
}
valueExceedsThreshold(t, s) {
return s.type === "max" ? t > s.value : s.type === "min" && t < s.value;
}
}
const le = (e, t) => {
p = {}, S = !1, e == null || e.forEach((s) => {
var r;
s.metric in p || (p[s.metric] = []), (r = p[s.metric]) == null || r.push(s);
}), _ = t;
}, E = {}, z = (e) => {
const t = new G(e);
return E[e] = t, t;
}, de = (e, t) => {
let s = E[e];
return s || (s = z(e)), s.report(t);
}, ue = ({ reportingIntervalSeconds: e, postMetrics: t }) => {
e ? setInterval(() => {
(async (s) => {
const r = Object.values(E).map((n) => ({ name: n.name, values: n.collect() }));
if (r.some((n) => n.values.length))
try {
await s(JSON.stringify(r));
} catch (n) {
n instanceof Error && Y.error("MetricsErr", { error: { message: n.message, name: n.name } });
}
})(t);
}, 1e3 * e) : C = !1;
};
export {
M as D,
X as E,
E as P,
N as S,
se as a,
Y as b,
oe as c,
de as d,
ee as e,
ne as f,
ae as g,
te as h,
le as i,
ue as j,
ce as k,
re as l,
k as m,
ie as n,
H as o,
$ as p,
L as q,
z as r,
v as s,
Z as v
};