UNPKG

@sprig-technologies/sprig-browser

Version:

npm package for the sprig web sdk

367 lines (366 loc) 14.4 kB
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 };