@braze/web-sdk
Version:
Braze SDK for web sites and other JS platforms.
241 lines (240 loc) • 6.78 kB
JavaScript
const oe = self;
let te = null,
le = null,
ce = 0,
ae = null,
re = !1;
const ie = new Map();
let se = null,
ue = null,
me = null,
de = null,
pe = null;
const fe = { Tn: null, Ge: null };
function Te(e) {
ie.forEach((n, o) => {
try {
n.port.postMessage(e);
} catch (e) {
ie.delete(o);
}
});
}
function Re() {
if (de && ie.has(de)) return;
const e = ie.keys().next().value;
(de = e || null),
de && console.log("[Braze Real-Time] Elected leader port:", de);
}
function ge(e) {
if ((Re(), !de))
return void console.warn("[Braze Real-Time] No leader to send message to");
const n = ie.get(de);
if (n)
try {
n.port.postMessage(e);
} catch (n) {
ie.delete(de), (de = null), ge(e);
}
}
function he() {
(re = !1),
null !== ae && (clearTimeout(ae), (ae = null)),
null !== me && (clearTimeout(me), (me = null)),
null !== pe && (clearTimeout(pe), (pe = null)),
te && (te.close(), (te = null), Te({ type: "disconnected" }));
}
function ze() {
if (!le) return;
ce++;
const { yn: e, $n: n, Rn: o } = le.kn;
let t = se;
(null == t || t < e) && (t = e);
const l = Math.min(
n,
((c = e), (a = t * o), Math.floor(Math.random() * (a - c + 1)) + c),
);
var c, a;
(se = l),
console.log(
"[Braze Real-Time] Retrying in " + l + "ms (attempt " + ce + "/5)",
),
(ae = setTimeout(function () {
(ae = null), fe.Tn();
}, l));
}
function Be(e) {
if (!le) return;
if (te && !e)
return void console.warn("[Braze Real-Time] Connection already exists");
if (re && !e)
return void console.warn(
"[Braze Real-Time] Connection attempt already in progress",
);
re = !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)),
ue && (c += "&rcs=" + encodeURIComponent(ue));
const a = l + "/sse?" + c;
try {
const n = new EventSource(a);
(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),
(re = !1),
(ce = 0),
(se = null),
Te({ type: "connected" });
}),
n.addEventListener("msg", function (e) {
fe.Ge(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(),
(re = !1),
void (ce < 5 && ze())
);
he(),
ce < 5
? ze()
: (console.error("[Braze Real-Time] Max retries reached"),
Te({ type: "error", error: "Max retry attempts reached" }));
});
} catch (e) {
(re = !1),
console.error("[Braze Real-Time] Failed to create EventSource:", e),
Te({ type: "error", error: String(e) });
}
}
function ye(e, n, o) {
switch (o.type) {
case "connect":
!le ||
(le.mite === o.zn.mite && le.Wi === o.zn.Wi) ||
(console.log("[Braze Real-Time] Config changed, reconnecting"),
he(),
(ce = 0),
(se = null),
(ue = null)),
(le = o.zn),
Re(),
te || re ? te && e.postMessage({ type: "connected" }) : Be();
break;
case "disconnect":
ie.delete(n),
n === de && ((de = null), Re()),
0 === ie.size &&
(console.log("[Braze Real-Time] No more ports, closing connection"),
he(),
(le = null),
(ue = null),
(de = null));
break;
case "tab_active":
!(function (e) {
ie.has(e) &&
de !== e &&
((de = 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);
}
}
(fe.Tn = Be),
(fe.Ge = 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.on),
(o = t.body.hn),
void (
"number" == typeof n &&
("string" == typeof o && (ue = o),
console.log(
"[Braze Real-Time] TTL set to " +
n +
"ms, will perform gapless reconnection when expired",
),
null !== me && clearTimeout(me),
(me = setTimeout(function () {
(me = null),
console.log(
"[Braze Real-Time] TTL expired, performing gapless reconnection",
),
Be(te || void 0);
}, n)))
)
);
if ("ddr" === t.type && t.body)
return void (function (e, n) {
if ("number" != typeof e) return;
const o = Math.random() * e * 0.3,
t = Math.round(e + o),
l = n ? " (" + n + ")" : "";
console.log(
"[Braze Real-Time] Admin requested disconnect" +
l +
", reconnecting in " +
t +
"ms",
),
null !== pe && clearTimeout(pe),
he(),
(pe = setTimeout(function () {
(pe = null), fe.Tn();
}, t));
})(t.body._e, t.body.e);
console.log(
"[Braze Real-Time] Routing '" + t.type + "' message to leader",
),
ge({ 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);
ie.set(o, { port: n }),
(n.onmessage = function (e) {
try {
ye(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),
ie.delete(o);
}),
n.start();
});