UNPKG

@braze/web-sdk

Version:

Braze SDK for web sites and other JS platforms.

235 lines (234 loc) 6.88 kB
const oe = self; let te = null, le = null, ce = 0, ae = null, ie = !1; const se = new Map(); let ue = null, me = null, de = null, fe = null, pe = null; const Te = { Tn: null, qe: null }; function Re(e) { se.forEach((n, o) => { try { n.port.postMessage(e); } catch (e) { se.delete(o); } }); } function a(e, n) { return Math.floor(Math.random() * (n - e + 1)) + e; } function ge() { if (fe && se.has(fe)) return; const e = se.keys().next().value; (fe = e || null), fe && console.log("[Braze Real-Time] Elected leader port:", fe); } function he(e) { if ((ge(), !fe)) return void console.warn("[Braze Real-Time] No leader to send message to"); const n = se.get(fe); if (n) try { n.port.postMessage(e); } catch (n) { se.delete(fe), (fe = null), he(e); } } function ze() { (ie = !1), null !== ae && (clearTimeout(ae), (ae = null)), null !== de && (clearTimeout(de), (de = null)), null !== pe && (clearTimeout(pe), (pe = null)), te && (te.close(), (te = null), Re({ type: "disconnected" })); } function Be() { if (!le) return; ce++; const { Rn: e, zn: n, Bn: o } = le.Mn; let t = ue; (null == t || t < e) && (t = e); const l = Math.min(n, a(e, t * o)); (ue = l), console.log(`[Braze Real-Time] Retrying in ${l}ms (attempt ${ce}/5)`), (ae = setTimeout(function () { (ae = null), Te.Tn(); }, l)); } function ye(e) { if (!le) return; if (te && !e) return void console.warn("[Braze Real-Time] Connection already exists"); if (ie && !e) return void console.warn( "[Braze Real-Time] Connection attempt already in progress", ); ie = !0; const { Wi: n, mite: o, auth: t } = le, l = /^https?:\/\//i.test(n) ? n : `https://${n}`; let c = `mite=${encodeURIComponent(o)}&attempts=${ce}`; t && (c += `&auth=${encodeURIComponent(t)}`), me && (c += `&rcs=${encodeURIComponent(me)}`); const r = `${l}/sse?${c}`; try { const n = new EventSource(r); (n.onopen = function () { e ? (console.log( "[Braze Real-Time] Gapless reconnection: new connection established, closing old connection", ), e.close()) : console.log("[Braze Real-Time] Connection established"), (te = n), (ie = !1), (ce = 0), (ue = null), Re({ type: "connected" }); }), n.addEventListener("msg", function (e) { Te.qe(e.data); }), (n.onerror = function () { if ( (0 === (n ? n.readyState : -1) ? console.log("[Braze Real-Time] Failed to connect") : console.log("[Braze Real-Time] Connection lost"), e && te !== n) ) return ( console.log( "[Braze Real-Time] Gapless reconnection failed, keeping old connection", ), n.close(), (ie = !1), void (ce < 5 && Be()) ); ze(), ce < 5 ? Be() : (console.error("[Braze Real-Time] Max retries reached"), Re({ type: "error", error: "Max retry attempts reached" })); }); } catch (e) { (ie = !1), console.error("[Braze Real-Time] Failed to create EventSource:", e), Re({ type: "error", error: String(e) }); } } function $e(e, n, o) { switch (o.type) { case "connect": !le || (le.mite === o.Cn.mite && le.Wi === o.Cn.Wi) || (console.log("[Braze Real-Time] Config changed, reconnecting"), ze(), (ce = 0), (ue = null), (me = null)), (le = o.Cn), se.has(n) || se.set(n, { port: e }), ge(), te || ie ? te && e.postMessage({ type: "connected" }) : ye(); break; case "disconnect": se.delete(n), n === fe && ((fe = null), ge()), 0 === se.size && (console.log("[Braze Real-Time] No more ports, closing connection"), ze(), (le = null), (me = null), (fe = null)); break; case "tab_active": !(function (e) { se.has(e) && fe !== e && ((fe = e), console.log( "[Braze Real-Time] Promoted to leader (tab became active):", e, )); })(n); break; case "ping": e.postMessage({ type: "pong" }); break; default: console.warn("[Braze Real-Time] Unknown message type:", o.type); } } (Te.Tn = ye), (Te.qe = function (e) { try { const t = JSON.parse(e); if (!t.type) return void console.warn("[Braze Real-Time] Message without type:", t); if ("ttl" === t.type && t.body) return ( (n = t.body.t_ms), (o = t.body.rcs), void ( "number" == typeof n && ("string" == typeof o && (me = o), console.log( `[Braze Real-Time] TTL set to ${n}ms, will perform gapless reconnection when expired`, ), null !== de && clearTimeout(de), (de = setTimeout(function () { (de = null), console.log( "[Braze Real-Time] TTL expired, performing gapless reconnection", ), ye(te || void 0); }, n))) ) ); if ("ddr" === t.type && t.body) return void (function (e, n) { if ("number" != typeof e) return; const o = null == le ? void 0 : le.Mn, t = (null == o ? void 0 : o.Rn) || 1e4, l = (null == o ? void 0 : o.Bn) || 3, c = (null == o ? void 0 : o.zn) || 3e5, r = Math.min(c, a(t, t * l)), i = Math.round(e + r), s = n ? ` (${n})` : ""; console.log( `[Braze Real-Time] Admin requested disconnect${s}, reconnecting in ${i}ms (r_ms=${e} + backoff=${r})`, ), null !== pe && clearTimeout(pe), ze(), (pe = setTimeout(function () { (pe = null), Te.Tn(); }, i)); })(t.body.r_ms, t.body.e); console.log(`[Braze Real-Time] Routing '${t.type}' message to leader`), he({ type: "message", data: t }); } catch (e) { console.warn("[Braze Real-Time] Failed to parse message:", e); } var n, o; }), (oe.onconnect = function (e) { const n = e.ports[0], o = `port-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; se.set(o, { port: n }), (n.onmessage = function (e) { try { $e(n, o, e.data); } catch (e) { console.error("[Braze Real-Time] Error handling message:", e); } }), (n.onmessageerror = function () { console.warn("[Braze Real-Time] Message error from port:", o), se.delete(o); }), n.start(); });