UNPKG

@braze/web-sdk

Version:

Braze SDK for web sites and other JS platforms.

401 lines (400 loc) 11.1 kB
import Ne from "../models/backend-errors.js"; import Ie from "../models/braze-event.js"; import { convertMsToSeconds as X, convertSecondsToMs as Xe, } from "../util/date-utils.js"; import v from "../common/event-logger.js"; import { isArray as g, isEqual as ni } from "../util/code-utils.js"; import { logger as E, EventTypes as p } from "../../shared-lib/index.js"; import { STORAGE_KEYS as s } from "./storage-manager.js"; import h from "../util/request-header-utils.js"; import { LAST_REQUEST_TO_ENDPOINT_MS_AGO_DEFAULT as Ke, MAX_RETRY_COUNT_PER_REQUEST as Pe, } from "../common/constants.js"; import { getAlias as He } from "./utils.js"; import { readResponseHeaders as Oe } from "../util/net.js"; export default class Vt { constructor(t, e, i, s, r, n, o, a, h, u, l, c) { (this.eu = t), (this.C = e), (this.Gh = i), (this.Ss = s), (this.j = r), (this.h = n), (this.tu = o), (this.Yh = a), (this.Vh = h), (this.Kh = u), (this.appVersion = l), (this.Ra = c), (this.$a = (t) => (null == t ? "" : `${t} `)), (this.eu = t), (this.C = e), (this.Gh = i), (this.Ss = s), (this.j = r), (this.h = n), (this.tu = o), (this.Yh = a), (this.Vh = h), (this.Kh = u), (this.appVersion = l), (this.Ra = c), (this.Xa = ["npm"]), (this.La = {}); } Z(t, e = !1, i = !1) { const r = this.eu.ve(!i), n = r.ta(), o = this.C.Rt(s.Tt.Ba); ni(o, n) || (t.device = n), (t.api_key = this.tu), (t.time = X(new Date().valueOf(), !0)); const a = this.C.Rt(s.Tt.Ka) || [], h = this.C.Rt(s.Tt.Pa) || ""; this.Xa.length > 0 && (!ni(a, this.Xa) || h !== this.j.kt()) && (t.sdk_metadata = this.Xa), (t.sdk_version = this.Vh), this.Kh && (t.sdk_flavor = this.Kh), (t.app_version = this.appVersion), (t.app_version_code = this.Ra), (t.device_id = r.id); const u = this.Ss.getUserId(); if ((e && null !== u && (t.user_id = u), !u && !this.Gh.Fh())) { const e = He(this.C); e && (t.alias = e); } return t; } ut(t, e, i) { const s = e.auth_error, r = e.error; if (!s && !r) return !0; if (s) { let e; this.Gh.Eh(); const r = { errorCode: s.error_code }; for (const t of i) g(t) && "X-Braze-Auth-Signature" === t[0] && (r.signature = t[1]); t.respond_with && t.respond_with.user_id ? (r.userId = t.respond_with.user_id) : t.user_id && (r.userId = t.user_id); const n = s.reason; return ( n ? ((r.reason = n), (e = `due to ${n}`)) : (e = `with error code ${s.error_code}.`), this.Gh.Fh() || (e += ' Please use the "enableSdkAuthentication" initialization option to enable authentication.'), E.error(`SDK Authentication failed ${e}`), this.Ua(t.events || [], t.attributes || []), this.Gh.Ch(r), !1 ); } if (r) { let i, s = r; switch (s) { case Ne.Wa: return ( (i = "Received successful response with empty body."), v.wt(p.Ya, { e: i }), E.info(i), !1 ); case Ne.Qa: return ( (i = "Received successful response with invalid JSON"), v.wt(p.Ya, { e: i + ": " + e.response }), E.info(i), !1 ); case Ne.Va: s = `The API key "${t.api_key}" is invalid for the baseUrl ${this.Yh}`; break; case Ne.Za: s = "Sorry, we are not currently accepting your requests. If you think this is in error, please contact us."; break; case Ne.dl: s = "No device identifier. Please contact support@braze.com"; } E.error("Backend error: " + s); } return !1; } fl(t, e, i) { return !!((t && 0 !== t.length) || (e && 0 !== e.length) || i); } ml(t, e, i, s = !1) { const r = [], n = (t) => t || "", o = n(this.Ss.getUserId()); let a = this.Zo(t); const u = [], l = []; let c, d = null; if (e.length > 0) { const t = []; for (const i of e) { if (((c = i.ta()), this.Gh.Fh())) { if (o && !c.user_id) { d || (d = {}), d.events || (d.events = []), d.events.push(c); continue; } if (n(c.user_id) !== o) { l.push(c); continue; } } t.push(c); } t.length > 0 && (a.events = t); } if (i.length > 0) { const t = []; for (const e of i) e && (this.Gh.Fh() && n(e.user_id) !== o ? u.push(e) : t.push(e)); t.length > 0 && (a.attributes = t); } if ((this.Ua(l, u), (a = this.Z(a, !1, s)), d)) { d = this.Z(d, !1, s); const t = { requestData: d, headers: this.tt(d, h.it.pn) }; r.push(t); } if (a && !this.fl(a.events, a.attributes, t)) return d ? r : null; const f = { requestData: a, headers: this.tt(a, h.it.pn) }; return r.push(f), r; } Ua(t, e) { if (t) { const e = []; for (const i of t) { const t = Ie.fromJson(i); (t.time = Xe(t.time)), e.push(t); } this.C.ol(e); } if (e) for (const t of e) this.C.vl(t); } dt(t, e) { let i = "HTTP error "; null != t && (i += t + " "), (i += e), E.error(i); } Rl(t) { return v.wt(p.gl, { n: t }); } Zo(t, e) { const i = {}; t && (i.triggers = !0); const s = null != e ? e : this.Ss.getUserId(); if ((s && (i.user_id = s), !i.user_id && !this.Gh.Fh())) { const t = He(this.C); t && (i.alias = t); } return (i.config = { config_time: this.h.Ot() }), { respond_with: i }; } bl(t) { const e = new Date().valueOf(); let i = Ke.toString(); const s = h.ql(this.C, t); if (-1 !== s) { i = (e - s).toString(); } return i; } tt(t, e, i = !1) { const s = [["X-Braze-Api-Key", this.tu]], r = this.bl(e); s.push(["X-Braze-Last-Req-Ms-Ago", r]); const n = h.Al(this.C, e).toString(); s.push(["X-Braze-Req-Attempt", n]); let o = !1; if ( (null != t.respond_with && t.respond_with.triggers && (s.push(["X-Braze-TriggersRequest", "true"]), (o = !0)), e === h.it.Ji) ) { s.push(["X-Braze-ContentCardsRequest", "true"]); let t = h.Al(this.C, h.it.Ji); (t && !i) || ((t = 1), h.Dl(this.C, h.it.Ji, t)); const e = Math.max(0, t - 1); s.push(["BRAZE-SYNC-RETRY-COUNT", e.toString()]), (o = !0); } if ( (e === h.it.Co && (s.push(["X-Braze-FeatureFlagsRequest", "true"]), (o = !0)), o && s.push(["X-Braze-DataRequest", "true"]), this.Gh.Fh()) ) { const t = this.Gh.kh(); null != t && s.push(["X-Braze-Auth-Signature", t]); } return s; } Tl(t, e, i, s) { if (this.La[s]) return; const r = window.setTimeout(() => { E.info(`Retrying rate limited ${this.$a(s)}SDK request.`), this.et(e, i, s); }, t); this.La[s] = r; } fo() { for (const t in this.La) { const e = this.La[t]; window.clearTimeout(e); } this.La = {}; } et(t, e, i, r) { if (!this.kl(i)) return ( E.info(`${this.$a(i)}SDK request being rate limited.`), void ("function" == typeof r && r()) ); const n = this.yl(); if (!n.wl) return ( this.Tl(n.Nl, t, e, i), void E.info( `${this.$a( i, )}SDK request being rate limited. Request will be retried in ${Math.trunc( n.Nl / 1e3, )} seconds.`, ) ); this.C.It(s.Tt.Cl, new Date().valueOf()); const o = t.device; o && o.os_version instanceof Promise ? o.os_version.then((i) => { (t.device.os_version = i), e(n.Sl); }) : e(n.Sl); } Bl(t) { const e = t ? Oe(t) : null; if (!e || !e["retry-after"]) return null; const i = e["retry-after"]; if (isNaN(i) && !isNaN(Date.parse(i))) return { type: "date", value: Date.parse(i) }; if (!isNaN(parseFloat(i.toString()))) return { type: "timestamp", value: 1e3 * parseFloat(i.toString()) }; { const t = "Received unexpected value for retry-after header in /sync response"; v.wt(p.Ya, { e: t + ": " + i }); } return null; } yt(t, e, i, s, r, n) { if (h.Al(this.C, i) >= Pe) return; let o; n = n || 0; const a = this.Bl(t); r(); const u = (t) => { const r = window.setTimeout(() => { e(); }, t); s(r), h.zl(this.C, i); }; if (a && !isNaN(a.value)) { switch (a.type) { case "date": (o = a.value - new Date().getTime() + n), o < 0 && e(); break; case "timestamp": o = a.value + n; } u(o); } else n ? u(n) : h.Li(this.C, i); } jl(t) { var e; null === (e = this.C) || void 0 === e || e.It(s.Tt.Ml, t); } $l(t, e) { let i = this.Xl(); null == i && (i = {}), (i[t] = e), this.C.It(s.Tt.Ll, i); } El() { var t; return null === (t = this.C) || void 0 === t ? void 0 : t.Rt(s.Tt.Ml); } Xl() { var t; return null === (t = this.C) || void 0 === t ? void 0 : t.Rt(s.Tt.Ll); } Fl(t, e, i, s, r = "") { let n; if (r) { const t = this.Xl(); n = null == t || isNaN(t[r]) ? e : t[r]; } else (n = this.El()), (null == n || isNaN(n)) && (n = e); const o = (t - s) / 1e3; return (n = Math.min(n + o / i, e)), n; } Kl(t, e) { return Math.max(0, (1 - t) * e * 1e3); } Il(t, e = "") { var i, r, n, o, a; const u = { wl: !0, Sl: -1, Nl: 0 }; if ((null == t && (t = !0), !t && !e)) return u; let l, c, d = null; if (t) d = null === (i = this.C) || void 0 === i ? void 0 : i.Rt(s.Tt.Cl); else { const t = h.Pl(this.C); if (null == t || null == t[e]) return u; d = t[e]; } if (null == d || isNaN(d)) return u; if ( (t ? ((l = (null === (r = this.h) || void 0 === r ? void 0 : r.Ul()) || -1), (c = (null === (n = this.h) || void 0 === n ? void 0 : n.xl()) || -1)) : ((l = (null === (o = this.h) || void 0 === o ? void 0 : o.Hl(e)) || -1), (c = (null === (a = this.h) || void 0 === a ? void 0 : a.Ol(e)) || -1)), -1 === l || -1 === c) ) return u; const f = new Date().valueOf(); let m = this.Fl(f, l, c, d, e); return m < 1 ? ((u.wl = !1), (u.Nl = this.Kl(m, c)), u) : ((m = Math.trunc(m) - 1), (u.Sl = m), t ? this.jl(m) : this.$l(e, m), u); } yl() { return this.Il(!0); } kl(t) { const e = this.Il(!1, t); return !(e && !e.wl); } ct() { this.Gh.ct(); } ht() { return this.Yh; } addSdkMetadata(t) { for (const e of t) -1 === this.Xa.indexOf(e) && this.Xa.push(e); } }