@braze/web-sdk
Version:
Braze SDK for web sites and other JS platforms.
401 lines (400 loc) • 11.1 kB
JavaScript
import Xt from "../models/backend-errors.js";
import ue from "../models/braze-event.js";
import {
convertMsToSeconds as X,
convertSecondsToMs as Yt,
} from "../util/date-utils.js";
import c from "../common/event-logger.js";
import { isArray as D, isEqual as ii } from "../util/code-utils.js";
import { logger as E, EventTypes as m } 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 Zt,
MAX_RETRY_COUNT_PER_REQUEST as he,
} from "../common/constants.js";
import { getAlias as ce } from "./utils.js";
import { readResponseHeaders as ve } from "../util/net.js";
export default class Mt {
constructor(t, e, i, s, r, n, o, a, h, u, l, c) {
(this.on = t),
(this.j = e),
(this.Qh = i),
(this.Cs = s),
(this.C = r),
(this.h = n),
(this.sn = o),
(this.Ea = a),
(this.Xh = h),
(this.Zh = u),
(this.appVersion = l),
(this.$a = c),
(this.Xa = (t) => (null == t ? "" : `${t} `)),
(this.on = t),
(this.j = e),
(this.Qh = i),
(this.Cs = s),
(this.C = r),
(this.h = n),
(this.sn = o),
(this.Ea = a),
(this.Xh = h),
(this.Zh = u),
(this.appVersion = l),
(this.$a = c),
(this.Ya = ["npm"]),
(this.Za = {});
}
$(t, e = !1, i = !1) {
const r = this.on.fe(!i),
n = r.Ar(),
o = this.j.lt(s.ct.Qa);
ii(o, n) || (t.device = n),
(t.api_key = this.sn),
(t.time = X(new Date().valueOf(), !0));
const a = this.j.lt(s.ct.au) || [],
h = this.j.lt(s.ct.du) || "";
this.Ya.length > 0 &&
(!ii(a, this.Ya) || h !== this.C.bt()) &&
(t.sdk_metadata = this.Ya),
(t.sdk_version = this.Xh),
this.Zh && (t.sdk_flavor = this.Zh),
(t.app_version = this.appVersion),
(t.app_version_code = this.$a),
(t.device_id = r.id);
const u = this.Cs.getUserId();
if ((e && null !== u && (t.user_id = u), !u && !this.Qh.fh())) {
const e = ce(this.j);
e && (t.alias = e);
}
return t;
}
Y(t, e, i) {
const s = e.auth_error,
r = e.error;
if (!s && !r) return !0;
if (s) {
let e;
this.Qh.Gh();
const r = { errorCode: s.error_code };
for (const t of i)
D(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.Qh.fh() ||
(e +=
' Please use the "enableSdkAuthentication" initialization option to enable authentication.'),
E.error(`SDK Authentication failed ${e}`),
this.fu(t.events || [], t.attributes || []),
this.Qh.yh(r),
!1
);
}
if (r) {
let i,
s = r;
switch (s) {
case Xt.vu:
return (
(i = "Received successful response with empty body."),
c.rt(m.pu, { e: i }),
E.info(i),
!1
);
case Xt.Ru:
return (
(i = "Received successful response with invalid JSON"),
c.rt(m.pu, { e: i + ": " + e.response }),
E.info(i),
!1
);
case Xt.gu:
s = `The API key "${t.api_key}" is invalid for the baseUrl ${this.Ea}`;
break;
case Xt.bu:
s =
"Sorry, we are not currently accepting your requests. If you think this is in error, please contact us.";
break;
case Xt.qu:
s = "No device identifier. Please contact support@braze.com";
}
E.error("Backend error: " + s);
}
return !1;
}
Au(t, e, i) {
return !!((t && 0 !== t.length) || (e && 0 !== e.length) || i);
}
Du(t, e, i, s = !1) {
const r = [],
n = (t) => t || "",
o = n(this.Cs.getUserId());
let a = this.Mr(t);
const u = [],
l = [];
let c,
d = null;
if (e.length > 0) {
const t = [];
for (const i of e) {
if (((c = i.Ar()), this.Qh.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.Qh.fh() && n(e.user_id) !== o ? u.push(e) : t.push(e));
t.length > 0 && (a.attributes = t);
}
if ((this.fu(l, u), (a = this.$(a, !1, s)), d)) {
d = this.$(d, !1, s);
const t = { requestData: d, headers: this.A(d, h.H.Tu) };
r.push(t);
}
if (a && !this.Au(a.events, a.attributes, t)) return d ? r : null;
const f = { requestData: a, headers: this.A(a, h.H.Tu) };
return r.push(f), r;
}
fu(t, e) {
if (t) {
const e = [];
for (const i of t) {
const t = ue.fromJson(i);
(t.time = Yt(t.time)), e.push(t);
}
this.j.Eo(e);
}
if (e) for (const t of e) this.j.ku(t);
}
_(t, e) {
let i = "HTTP error ";
null != t && (i += t + " "), (i += e), E.error(i);
}
yu(t) {
return c.rt(m.wu, { n: t });
}
Mr(t, e) {
const i = {};
t && (i.triggers = !0);
const s = null != e ? e : this.Cs.getUserId();
if ((s && (i.user_id = s), !i.user_id && !this.Qh.fh())) {
const t = ce(this.j);
t && (i.alias = t);
}
return (i.config = { config_time: this.h.Ft() }), { respond_with: i };
}
Nu(t) {
const e = new Date().valueOf();
let i = Zt.toString();
const s = h.Cu(this.j, t);
if (-1 !== s) {
i = (e - s).toString();
}
return i;
}
A(t, e, i = !1) {
const s = [["X-Braze-Api-Key", this.sn]],
r = this.Nu(e);
s.push(["X-Braze-Last-Req-Ms-Ago", r]);
const n = h.Su(this.j, 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.H.bi)
) {
s.push(["X-Braze-ContentCardsRequest", "true"]);
let t = h.Su(this.j, h.H.bi);
(t && !i) || ((t = 1), h.Bu(this.j, h.H.bi, t));
const e = Math.max(0, t - 1);
s.push(["BRAZE-SYNC-RETRY-COUNT", e.toString()]), (o = !0);
}
if (
(e === h.H.$e &&
(s.push(["X-Braze-FeatureFlagsRequest", "true"]), (o = !0)),
o && s.push(["X-Braze-DataRequest", "true"]),
this.Qh.fh())
) {
const t = this.Qh.wh();
null != t && s.push(["X-Braze-Auth-Signature", t]);
}
return s;
}
zu(t, e, i, s) {
if (this.Za[s]) return;
const r = window.setTimeout(() => {
E.info(`Retrying rate limited ${this.Xa(s)}SDK request.`),
this.J(e, i, s);
}, t);
this.Za[s] = r;
}
fo() {
for (const t in this.Za) {
const e = this.Za[t];
window.clearTimeout(e);
}
this.Za = {};
}
J(t, e, i, r) {
if (!this.ju(i))
return (
E.info(`${this.Xa(i)}SDK request being rate limited.`),
void ("function" == typeof r && r())
);
const n = this.Mu();
if (!n.$u)
return (
this.zu(n.Xu, t, e, i),
void E.info(
`${this.Xa(
i,
)}SDK request being rate limited. Request will be retried in ${Math.trunc(
n.Xu / 1e3,
)} seconds.`,
)
);
this.j.ft(s.ct.Lu, 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.Eu);
})
: e(n.Eu);
}
Fu(t) {
const e = t ? ve(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";
c.rt(m.pu, { e: t + ": " + i });
}
return null;
}
st(t, e, i, s, r, n) {
if (h.Su(this.j, i) >= he) return;
let o;
n = n || 0;
const a = this.Fu(t);
r();
const u = (t) => {
const r = window.setTimeout(() => {
e();
}, t);
s(r), h.Ku(this.j, 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.Ci(this.j, i);
}
Iu(t) {
var e;
null === (e = this.j) || void 0 === e || e.ft(s.ct.Pu, t);
}
Uu(t, e) {
let i = this.xu();
null == i && (i = {}), (i[t] = e), this.j.ft(s.ct.Hu, i);
}
Ou() {
var t;
return null === (t = this.j) || void 0 === t ? void 0 : t.lt(s.ct.Pu);
}
xu() {
var t;
return null === (t = this.j) || void 0 === t ? void 0 : t.lt(s.ct.Hu);
}
Gu(t, e, i, s, r = "") {
let n;
if (r) {
const t = this.xu();
n = null == t || isNaN(t[r]) ? e : t[r];
} else (n = this.Ou()), (null == n || isNaN(n)) && (n = e);
const o = (t - s) / 1e3;
return (n = Math.min(n + o / i, e)), n;
}
_u(t, e) {
return Math.max(0, (1 - t) * e * 1e3);
}
Wu(t, e = "") {
var i, r, n, o, a;
const u = { $u: !0, Eu: -1, Xu: 0 };
if ((null == t && (t = !0), !t && !e)) return u;
let l,
c,
d = null;
if (t) d = null === (i = this.j) || void 0 === i ? void 0 : i.lt(s.ct.Lu);
else {
const t = h.Yu(this.j);
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.Ju()) || -1),
(c = (null === (n = this.h) || void 0 === n ? void 0 : n.Qu()) || -1))
: ((l =
(null === (o = this.h) || void 0 === o ? void 0 : o.Vu(e)) || -1),
(c =
(null === (a = this.h) || void 0 === a ? void 0 : a.Zu(e)) || -1)),
-1 === l || -1 === c)
)
return u;
const f = new Date().valueOf();
let m = this.Gu(f, l, c, d, e);
return m < 1
? ((u.$u = !1), (u.Xu = this._u(m, c)), u)
: ((m = Math.trunc(m) - 1),
(u.Eu = m),
t ? this.Iu(m) : this.Uu(e, m),
u);
}
Mu() {
return this.Wu(!0);
}
ju(t) {
const e = this.Wu(!1, t);
return !(e && !e.$u);
}
Z() {
this.Qh.Z();
}
V() {
return this.Ea;
}
addSdkMetadata(t) {
for (const e of t) -1 === this.Ya.indexOf(e) && this.Ya.push(e);
}
}