@braze/web-sdk 6.3.1 → 6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/index.d.ts +38 -5
- package/package.json +1 -1
- package/shared-lib/encoding-utils.js +3 -3
- package/shared-lib/event-types.js +30 -30
- package/shared-lib/guid.js +1 -1
- package/shared-lib/indexed-db-adapter.js +60 -60
- package/shared-lib/logger.js +7 -7
- package/shared-lib/supported-options.js +24 -23
- package/src/Banner/banner-provider.js +95 -81
- package/src/Banner/banner.js +9 -9
- package/src/Banner/constants.js +4 -0
- package/src/Banner/display/banner-to-html.js +3 -3
- package/src/Banner/display/destroy-banner-html.js +3 -3
- package/src/Banner/display/detect-banner-impressions.js +16 -16
- package/src/Banner/get-all-banners.js +4 -4
- package/src/Banner/get-banner.js +5 -4
- package/src/Banner/index.js +2 -0
- package/src/Banner/log-banner-click.js +2 -2
- package/src/Banner/log-banner-impressions.js +6 -6
- package/src/Banner/request-banners-refresh.js +18 -20
- package/src/Banner/subscribe-to-banners-updates.js +5 -5
- package/src/Banner/ui/insert-banner.js +17 -14
- package/src/Card/card-manager-factory.js +6 -6
- package/src/Card/card-manager.js +28 -28
- package/src/Card/constants.js +1 -0
- package/src/Card/display/card-display.js +7 -7
- package/src/Card/log-card-dismissal.js +3 -3
- package/src/Card/log-content-card-click.js +3 -3
- package/src/Card/log-content-card-impressions.js +6 -6
- package/src/Card/models/captioned-image.js +3 -3
- package/src/Card/models/card.js +9 -9
- package/src/Card/models/classic-card.js +3 -3
- package/src/Card/models/control-card.js +3 -3
- package/src/Card/models/image-only.js +3 -3
- package/src/ContentCards/content-cards-provider-factory.js +6 -2
- package/src/ContentCards/content-cards-provider.js +101 -87
- package/src/ContentCards/content-cards.js +4 -4
- package/src/ContentCards/request-content-cards-refresh.js +1 -1
- package/src/ContentCards/subscribe-to-content-cards-updates.js +4 -4
- package/src/ContentCards/ui/show-content-cards.js +5 -5
- package/src/Core/add-sdk-metadata.js +2 -2
- package/src/Core/change-user.js +1 -1
- package/src/Core/disable-sdk.js +5 -5
- package/src/Core/enable-sdk.js +3 -3
- package/src/Core/get-device-id.js +2 -2
- package/src/Core/get-user.js +1 -1
- package/src/Core/handle-braze-action.js +3 -3
- package/src/Core/is-disabled.js +1 -1
- package/src/Core/log-custom-event.js +7 -7
- package/src/Core/log-purchase.js +4 -4
- package/src/Core/open-session.js +6 -6
- package/src/Core/wipe-data.js +3 -3
- package/src/DUST/dust-connection-core.js +23 -0
- package/src/DUST/dust-provider-factory.js +22 -0
- package/src/DUST/dust-provider.js +520 -0
- package/src/DUST/dust-shared-worker-code.js +2 -0
- package/src/DUST/dust-shared-worker-impl.js +240 -0
- package/src/DUST/dust-worker-bridge.js +136 -0
- package/src/DUST/index.js +13 -0
- package/src/DUST/subscribe-to-dust.js +24 -0
- package/src/DUST/types.js +1 -0
- package/src/FeatureFlags/feature-flag-factory.js +8 -8
- package/src/FeatureFlags/feature-flag.js +6 -6
- package/src/FeatureFlags/feature-flags-provider-factory.js +9 -9
- package/src/FeatureFlags/feature-flags-provider.js +98 -84
- package/src/FeatureFlags/get-all-feature-flags.js +3 -3
- package/src/FeatureFlags/get-feature-flag.js +3 -3
- package/src/FeatureFlags/log-feature-flag-impression.js +7 -7
- package/src/FeatureFlags/refresh-feature-flags.js +5 -5
- package/src/FeatureFlags/subscribe-to-feature-flags-updates.js +4 -4
- package/src/InAppMessage/constants.js +4 -0
- package/src/InAppMessage/defer-in-app-message.js +2 -2
- package/src/InAppMessage/display/get-animation-effect.js +1 -1
- package/src/InAppMessage/display/html-message-to-html.js +6 -6
- package/src/InAppMessage/display/in-app-message-to-html.js +34 -34
- package/src/InAppMessage/display/modal-utils.js +14 -14
- package/src/InAppMessage/get-deferred-in-app-message.js +2 -2
- package/src/InAppMessage/in-app-message-factory.js +4 -4
- package/src/InAppMessage/in-app-message-manager-factory.js +7 -7
- package/src/InAppMessage/in-app-message-manager.js +98 -98
- package/src/InAppMessage/log-in-app-message-button-click.js +12 -12
- package/src/InAppMessage/log-in-app-message-click.js +11 -11
- package/src/InAppMessage/log-in-app-message-html-click.js +9 -9
- package/src/InAppMessage/log-in-app-message-impression.js +8 -8
- package/src/InAppMessage/models/control-message.js +5 -5
- package/src/InAppMessage/models/full-screen-message.js +21 -21
- package/src/InAppMessage/models/html-message.js +18 -18
- package/src/InAppMessage/models/in-app-message-button.js +7 -7
- package/src/InAppMessage/models/in-app-message.js +145 -145
- package/src/InAppMessage/models/modal-message.js +21 -21
- package/src/InAppMessage/models/slide-up-message.js +27 -27
- package/src/InAppMessage/models/templated-in-app-message.js +8 -8
- package/src/InAppMessage/subscribe-to-in-app-message.js +2 -2
- package/src/InAppMessage/ui/automatically-show-in-app-messages.js +5 -5
- package/src/InAppMessage/ui/remove-all-visible-in-app-messages.js +18 -0
- package/src/InAppMessage/ui/show-in-app-message.js +36 -36
- package/src/Push/is-push-blocked.js +2 -2
- package/src/Push/is-push-permission-granted.js +2 -2
- package/src/Push/is-push-supported.js +2 -2
- package/src/Push/push-manager-factory.js +15 -15
- package/src/Push/push-manager.js +97 -97
- package/src/Push/request-push-permission.js +1 -1
- package/src/Push/unregister-push.js +1 -1
- package/src/Push/utils/push-utils.js +17 -17
- package/src/User/user-manager.js +24 -24
- package/src/User/user.js +55 -55
- package/src/common/constants.js +8 -10
- package/src/common/content-cards-display.js +40 -40
- package/src/common/event-logger.js +8 -8
- package/src/common/properties-base.js +16 -16
- package/src/l10n/l10n-manager-factory.js +11 -11
- package/src/l10n/l10n-manager.js +2 -2
- package/src/managers/auth-manager.js +30 -30
- package/src/managers/braze-instance.js +170 -162
- package/src/managers/device-manager.js +24 -24
- package/src/managers/network-manager.js +149 -149
- package/src/managers/server-config-manager.js +140 -95
- package/src/managers/session-manager.js +39 -39
- package/src/managers/storage-manager-factory.js +10 -10
- package/src/managers/storage-manager.js +145 -141
- package/src/managers/subscription-manager.js +11 -11
- package/src/managers/utils.js +1 -1
- package/src/models/backend-errors.js +5 -5
- package/src/models/braze-event.js +11 -11
- package/src/models/device.js +3 -3
- package/src/models/identifier.js +16 -16
- package/src/models/push-token.js +13 -13
- package/src/models/request-result.js +3 -3
- package/src/models/server-config.js +45 -37
- package/src/request-controller.js +163 -158
- package/src/triggers/models/custom-event-data.js +5 -5
- package/src/triggers/models/custom-event-property-data.js +6 -6
- package/src/triggers/models/filter-set.js +10 -10
- package/src/triggers/models/filter.js +27 -27
- package/src/triggers/models/in-app-message-click-data.js +13 -13
- package/src/triggers/models/purchase-data.js +2 -2
- package/src/triggers/models/purchase-property-data.js +6 -6
- package/src/triggers/models/push-click-data.js +6 -6
- package/src/triggers/models/trigger-condition.js +47 -47
- package/src/triggers/models/trigger-events.js +3 -3
- package/src/triggers/models/trigger.js +36 -36
- package/src/triggers/triggers-provider-factory.js +5 -5
- package/src/triggers/triggers-provider.js +63 -63
- package/src/ui/js/attach-css.js +3 -3
- package/src/ui/js/load-font-awesome.js +2 -2
- package/src/util/base-device-parser.js +9 -9
- package/src/util/braze-actions.js +5 -5
- package/src/util/browser-detector.js +37 -37
- package/src/util/client-hints-parser.js +11 -11
- package/src/util/component-utils.js +5 -5
- package/src/util/dom-utils.js +13 -13
- package/src/util/html-display-utils.js +7 -7
- package/src/util/key-codes.js +1 -1
- package/src/util/net.js +5 -5
- package/src/util/request-header-utils.js +27 -27
- package/src/util/user-agent-parser.js +21 -21
- package/src/util/validation-utils.js +17 -17
- package/src/util/window-utils.js +3 -3
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const MIN_BACKOFF_MS = 1e4;
|
|
2
|
+
export const MAX_BACKOFF_MS = 3e5;
|
|
3
|
+
export const BACKOFF_SCALE_FACTOR = 3;
|
|
4
|
+
export const MAX_RETRIES = 5;
|
|
5
|
+
export function randomInRange(t, e) {
|
|
6
|
+
return Math.floor(Math.random() * (e - t + 1)) + t;
|
|
7
|
+
}
|
|
8
|
+
export function calculateBackoff(t) {
|
|
9
|
+
let e = t;
|
|
10
|
+
return (
|
|
11
|
+
(null === e || e < 1e4) && (e = 1e4),
|
|
12
|
+
Math.min(3e5, randomInRange(1e4, 3 * e))
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
export function buildSseUrl(t, e, n, o, r) {
|
|
16
|
+
const c = /^https?:\/\//i.test(t) ? t : `https://${t}`;
|
|
17
|
+
let p = `mite=${encodeURIComponent(e)}&attempts=${n}`;
|
|
18
|
+
return (
|
|
19
|
+
o && (p += `&auth=${encodeURIComponent(o)}`),
|
|
20
|
+
r && (p += `&rcs=${encodeURIComponent(r)}`),
|
|
21
|
+
`${c}/sse?${p}`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import r from "../managers/braze-instance.js";
|
|
2
|
+
import tr from "./dust-provider.js";
|
|
3
|
+
const nr = {
|
|
4
|
+
i: !1,
|
|
5
|
+
provider: null,
|
|
6
|
+
o: () => {
|
|
7
|
+
if ((nr.t(), !nr.provider)) {
|
|
8
|
+
const t = r.re("dustHost");
|
|
9
|
+
(nr.provider = new tr(r.m(), r.p(), r.l(), t)),
|
|
10
|
+
r.v(nr.provider),
|
|
11
|
+
nr.provider.Hr();
|
|
12
|
+
}
|
|
13
|
+
return nr.provider;
|
|
14
|
+
},
|
|
15
|
+
t: () => {
|
|
16
|
+
nr.i || (r.g(nr), (nr.i = !0));
|
|
17
|
+
},
|
|
18
|
+
destroy: () => {
|
|
19
|
+
nr.provider && nr.provider.destroy(), (nr.provider = null), (nr.i = !1);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
export default nr;
|
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
import t from "../common/base-provider.js";
|
|
2
|
+
import r from "../managers/braze-instance.js";
|
|
3
|
+
import { STORAGE_KEYS as s } from "../managers/storage-manager.js";
|
|
4
|
+
import m from "../managers/subscription-manager.js";
|
|
5
|
+
import l from "../util/net.js";
|
|
6
|
+
import h from "../util/request-header-utils.js";
|
|
7
|
+
import { logger as E } from "../../shared-lib/index.js";
|
|
8
|
+
import {
|
|
9
|
+
REQUEST_BACKOFF_MAX_SLEEP_MS_DEFAULT as u,
|
|
10
|
+
REQUEST_BACKOFF_MIN_SLEEP_MS_DEFAULT as c,
|
|
11
|
+
REQUEST_BACKOFF_SCALE_FACTOR_DEFAULT as d,
|
|
12
|
+
} from "../common/constants.js";
|
|
13
|
+
import { randomInclusive as a } from "../util/math.js";
|
|
14
|
+
import {
|
|
15
|
+
MAX_RETRIES as ii,
|
|
16
|
+
buildSseUrl as ti,
|
|
17
|
+
} from "./dust-connection-core.js";
|
|
18
|
+
import {
|
|
19
|
+
DustWorkerBridge as si,
|
|
20
|
+
isSharedWorkerSupported as ei,
|
|
21
|
+
} from "./dust-worker-bridge.js";
|
|
22
|
+
export default class tr extends t {
|
|
23
|
+
constructor(i, t, s, e, n = !0) {
|
|
24
|
+
super(),
|
|
25
|
+
(this.j = i),
|
|
26
|
+
(this.B = t),
|
|
27
|
+
(this.h = s),
|
|
28
|
+
(this.j = i),
|
|
29
|
+
(this.B = t),
|
|
30
|
+
(this.h = s),
|
|
31
|
+
(this.mite = null),
|
|
32
|
+
(this.ki = null),
|
|
33
|
+
(this.yi = null),
|
|
34
|
+
(this.$i = null),
|
|
35
|
+
(this.Ri = e || null),
|
|
36
|
+
(this.Mi = null),
|
|
37
|
+
(this.xi = null),
|
|
38
|
+
(this.D = null),
|
|
39
|
+
(this.ji = 0),
|
|
40
|
+
(this.Wi = ii),
|
|
41
|
+
(this.Fi = null),
|
|
42
|
+
(this.Ui = null),
|
|
43
|
+
(this.zi = !0),
|
|
44
|
+
(this.Bi = null),
|
|
45
|
+
(this.Gi = null),
|
|
46
|
+
(this.Pi = null),
|
|
47
|
+
(this.qi = null),
|
|
48
|
+
(this.Hi = !1),
|
|
49
|
+
(this.Ji = new Map()),
|
|
50
|
+
(this.Li = null),
|
|
51
|
+
(this.Oi = null),
|
|
52
|
+
(this.Ki = null),
|
|
53
|
+
(this.Qi = this.Vi(n)),
|
|
54
|
+
(this.Xi = !1),
|
|
55
|
+
(this.Yi = 0),
|
|
56
|
+
this.Zi();
|
|
57
|
+
}
|
|
58
|
+
Vi(i) {
|
|
59
|
+
return i
|
|
60
|
+
? ei()
|
|
61
|
+
? "sharedworker"
|
|
62
|
+
: (E.info(
|
|
63
|
+
"SharedWorker not supported, using direct EventSource (multi-tab will gracefully degrade)",
|
|
64
|
+
),
|
|
65
|
+
"direct")
|
|
66
|
+
: (E.info("Shared connection disabled, using direct EventSource"),
|
|
67
|
+
"direct");
|
|
68
|
+
}
|
|
69
|
+
_i() {
|
|
70
|
+
this.Ki = new si({
|
|
71
|
+
we: (i) => {
|
|
72
|
+
this.Se(i);
|
|
73
|
+
},
|
|
74
|
+
ke: () => {
|
|
75
|
+
this.ye();
|
|
76
|
+
},
|
|
77
|
+
Re: () => {},
|
|
78
|
+
Me: (i) => {
|
|
79
|
+
E.error(`Real-time messaging SharedWorker error: ${i}`);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
this.Ki.initialize() ||
|
|
83
|
+
(E.info(
|
|
84
|
+
"SharedWorker initialization failed, falling back to direct EventSource",
|
|
85
|
+
),
|
|
86
|
+
(this.Qi = "direct"),
|
|
87
|
+
(this.Ki = null));
|
|
88
|
+
}
|
|
89
|
+
ye() {
|
|
90
|
+
(this.ji = 0),
|
|
91
|
+
(this.Bi = null),
|
|
92
|
+
(this.zi = !0),
|
|
93
|
+
(this.Xi = !1),
|
|
94
|
+
(this.Yi = 0);
|
|
95
|
+
}
|
|
96
|
+
Se(i) {
|
|
97
|
+
if (!i.type)
|
|
98
|
+
return void E.warn(
|
|
99
|
+
`Received real-time message without type: ${JSON.stringify(i)}`,
|
|
100
|
+
);
|
|
101
|
+
const t = "sharedworker" === this.Qi ? "SharedWorker" : "Direct";
|
|
102
|
+
E.info(`Received real-time message of type '${i.type}' via ${t}`);
|
|
103
|
+
const s = this.Ji.get(i.type);
|
|
104
|
+
if (s && s.De() > 0)
|
|
105
|
+
try {
|
|
106
|
+
s.L(i);
|
|
107
|
+
} catch (t) {
|
|
108
|
+
E.error(
|
|
109
|
+
`Error invoking subscription for message type '${i.type}': ${t}`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
else E.info(`No subscribers for real-time message type '${i.type}'`);
|
|
113
|
+
}
|
|
114
|
+
We() {
|
|
115
|
+
return "sharedworker" === this.Qi;
|
|
116
|
+
}
|
|
117
|
+
Fe() {
|
|
118
|
+
return this.Qi;
|
|
119
|
+
}
|
|
120
|
+
Zi() {
|
|
121
|
+
if (this.B) {
|
|
122
|
+
const i = this.B.dt(s.ft.Ue),
|
|
123
|
+
t = this.B.dt(s.ft.Ne),
|
|
124
|
+
e = this.B.dt(s.ft.Te),
|
|
125
|
+
n = this.B.dt(s.ft.ze);
|
|
126
|
+
i && t
|
|
127
|
+
? ((this.mite = i),
|
|
128
|
+
(this.ki = t),
|
|
129
|
+
(this.yi = e),
|
|
130
|
+
(this.$i = n),
|
|
131
|
+
E.info("Restored real-time messaging configuration from storage"))
|
|
132
|
+
: (i || t) &&
|
|
133
|
+
(E.warn(
|
|
134
|
+
"Incomplete real-time messaging configuration in storage, clearing",
|
|
135
|
+
),
|
|
136
|
+
this.Ae());
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
Hr() {
|
|
140
|
+
this.Li ||
|
|
141
|
+
this.Oi ||
|
|
142
|
+
((this.Li = this.Be("ddr", (i) => {
|
|
143
|
+
if (!i.body || "number" != typeof i.body.Ge) return;
|
|
144
|
+
const t = Math.random() * i.body.Ge * 0.3,
|
|
145
|
+
s = Math.round(i.body.Ge + t),
|
|
146
|
+
e = i.body.e ? ` (${i.body.e})` : "";
|
|
147
|
+
E.info(`Admin requested disconnect${e}, reconnecting in ${s}ms`),
|
|
148
|
+
this.Pe(),
|
|
149
|
+
setTimeout(() => this.qe(), s);
|
|
150
|
+
})),
|
|
151
|
+
(this.Oi = this.Be("ttl", (i) => {
|
|
152
|
+
if (!i.body || "number" != typeof i.body.He) return;
|
|
153
|
+
const t = i.body.He;
|
|
154
|
+
E.info(`Time to live set to ${t}ms, will reconnect when expired`),
|
|
155
|
+
"sharedworker" !== this.Qi &&
|
|
156
|
+
("string" == typeof i.body.Je && (this.Mi = i.body.Je),
|
|
157
|
+
null !== this.Ui && window.clearTimeout(this.Ui),
|
|
158
|
+
(this.Ui = window.setTimeout(() => {
|
|
159
|
+
(this.Ui = null),
|
|
160
|
+
E.info("Time to live expired, performing gapless reconnection"),
|
|
161
|
+
this.Le();
|
|
162
|
+
}, t)));
|
|
163
|
+
})));
|
|
164
|
+
}
|
|
165
|
+
Oe() {
|
|
166
|
+
this.Gi ||
|
|
167
|
+
this.Pi ||
|
|
168
|
+
((this.qi = () => {
|
|
169
|
+
(this.Hi = !0), (this.zi = !1);
|
|
170
|
+
}),
|
|
171
|
+
window.addEventListener("beforeunload", this.qi),
|
|
172
|
+
(this.Gi = () => {
|
|
173
|
+
var i;
|
|
174
|
+
this.Hi = !0;
|
|
175
|
+
(this.xi ||
|
|
176
|
+
(null === (i = this.Ki) || void 0 === i ? void 0 : i.Ie())) &&
|
|
177
|
+
(E.info("Page unloading, closing real-time connection gracefully"),
|
|
178
|
+
(this.zi = !1),
|
|
179
|
+
this.Pe());
|
|
180
|
+
}),
|
|
181
|
+
window.addEventListener("pagehide", this.Gi),
|
|
182
|
+
(this.Pi = (i) => {
|
|
183
|
+
var t;
|
|
184
|
+
const s =
|
|
185
|
+
this.xi || (null === (t = this.Ki) || void 0 === t ? void 0 : t.Ie());
|
|
186
|
+
i.persisted &&
|
|
187
|
+
this.Ke() &&
|
|
188
|
+
!s &&
|
|
189
|
+
(E.info("Page restored from bfcache, reconnecting"),
|
|
190
|
+
(this.Hi = !1),
|
|
191
|
+
this.ye(),
|
|
192
|
+
this.qe());
|
|
193
|
+
}),
|
|
194
|
+
window.addEventListener("pageshow", this.Pi));
|
|
195
|
+
}
|
|
196
|
+
St() {
|
|
197
|
+
return this.D;
|
|
198
|
+
}
|
|
199
|
+
wt(i) {
|
|
200
|
+
this.D = i;
|
|
201
|
+
}
|
|
202
|
+
Be(i, t) {
|
|
203
|
+
if ("function" != typeof t) return null;
|
|
204
|
+
let s = this.Ji.get(i);
|
|
205
|
+
return s || ((s = new m()), this.Ji.set(i, s), r.q(s)), s.Rt(t);
|
|
206
|
+
}
|
|
207
|
+
Qe(i, t) {
|
|
208
|
+
const s = this.Ji.get(i);
|
|
209
|
+
s && s.removeSubscription(t);
|
|
210
|
+
}
|
|
211
|
+
Ke() {
|
|
212
|
+
return Boolean(this.mite && this.ki);
|
|
213
|
+
}
|
|
214
|
+
Ve() {
|
|
215
|
+
if (!this.$i) return !1;
|
|
216
|
+
return Math.floor(new Date().valueOf() / 1e3) >= this.$i;
|
|
217
|
+
}
|
|
218
|
+
Ae() {
|
|
219
|
+
(this.mite = null),
|
|
220
|
+
(this.ki = null),
|
|
221
|
+
(this.yi = null),
|
|
222
|
+
(this.$i = null),
|
|
223
|
+
(this.Mi = null),
|
|
224
|
+
this.B &&
|
|
225
|
+
(this.B.zt(s.ft.Ue),
|
|
226
|
+
this.B.zt(s.ft.Ne),
|
|
227
|
+
this.B.zt(s.ft.Te),
|
|
228
|
+
this.B.zt(s.ft.ze));
|
|
229
|
+
}
|
|
230
|
+
Xe(i, t) {
|
|
231
|
+
const e = () => {
|
|
232
|
+
"function" == typeof t && t();
|
|
233
|
+
},
|
|
234
|
+
n = this.j,
|
|
235
|
+
r = this.B;
|
|
236
|
+
if (!n || !r)
|
|
237
|
+
return (
|
|
238
|
+
E.error("NetworkManager or StorageManager not available"), void e()
|
|
239
|
+
);
|
|
240
|
+
if (!this.h || !this.h.Ye())
|
|
241
|
+
return (
|
|
242
|
+
E.info("Real-time messaging is not enabled, skipping refresh"), void e()
|
|
243
|
+
);
|
|
244
|
+
this.Ke()
|
|
245
|
+
? E.info("Refreshing real-time messaging configuration")
|
|
246
|
+
: E.info("Fetching initial real-time messaging configuration");
|
|
247
|
+
const o = n.$({}, !0),
|
|
248
|
+
a = n.A(o, h.H.Ze, !1),
|
|
249
|
+
c = new Date().valueOf();
|
|
250
|
+
h.K(r, h.H.Ze, c),
|
|
251
|
+
l.O({
|
|
252
|
+
url: `${n.V()}/dust/config`,
|
|
253
|
+
headers: a,
|
|
254
|
+
data: o,
|
|
255
|
+
W: (t) => {
|
|
256
|
+
if (!n.Y(o, t, a))
|
|
257
|
+
return (
|
|
258
|
+
E.error(
|
|
259
|
+
"Failed to validate server response for real-time messaging configuration",
|
|
260
|
+
),
|
|
261
|
+
void e()
|
|
262
|
+
);
|
|
263
|
+
n.Z(),
|
|
264
|
+
t.mite && t.host
|
|
265
|
+
? ((this.mite = t.mite),
|
|
266
|
+
(this.ki = t.host),
|
|
267
|
+
(this.yi = t.auth || null),
|
|
268
|
+
(this.$i = t.expiration || null),
|
|
269
|
+
E.info(
|
|
270
|
+
"Received real-time messaging configuration from server",
|
|
271
|
+
),
|
|
272
|
+
r.bt(s.ft.Ue, t.mite),
|
|
273
|
+
r.bt(s.ft.Ne, t.host),
|
|
274
|
+
t.auth ? r.bt(s.ft.Te, t.auth) : r.zt(s.ft.Te),
|
|
275
|
+
t.expiration ? r.bt(s.ft.ze, t.expiration) : r.zt(s.ft.ze),
|
|
276
|
+
this.qe(),
|
|
277
|
+
"function" == typeof i && i())
|
|
278
|
+
: (E.info(
|
|
279
|
+
"Real-time messaging configuration not available - this SDK version may not be supported",
|
|
280
|
+
),
|
|
281
|
+
this.Ae(),
|
|
282
|
+
e());
|
|
283
|
+
},
|
|
284
|
+
error: (i) => {
|
|
285
|
+
n._(i, "retrieving DUST config"), e();
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
qe() {
|
|
290
|
+
if (!this.h || !this.h.Ye()) return;
|
|
291
|
+
if (!this.Ke())
|
|
292
|
+
return void E.error(
|
|
293
|
+
"Cannot start real-time subscription without configuration",
|
|
294
|
+
);
|
|
295
|
+
if (this.Ve())
|
|
296
|
+
return (
|
|
297
|
+
E.info(
|
|
298
|
+
"Real-time messaging auth token has expired, refreshing configuration",
|
|
299
|
+
),
|
|
300
|
+
void this.Xe(
|
|
301
|
+
() => {
|
|
302
|
+
this.qe();
|
|
303
|
+
},
|
|
304
|
+
() => {
|
|
305
|
+
E.error(
|
|
306
|
+
"Failed to refresh expired real-time messaging configuration",
|
|
307
|
+
);
|
|
308
|
+
},
|
|
309
|
+
)
|
|
310
|
+
);
|
|
311
|
+
const i = this.mite,
|
|
312
|
+
t = this.Ri || this.ki;
|
|
313
|
+
if (i && t)
|
|
314
|
+
switch (this.Qi) {
|
|
315
|
+
case "sharedworker":
|
|
316
|
+
this._e(i, t);
|
|
317
|
+
break;
|
|
318
|
+
case "direct":
|
|
319
|
+
this.xi &&
|
|
320
|
+
(E.info(
|
|
321
|
+
"Real-time connection already exists, closing before starting new subscription",
|
|
322
|
+
),
|
|
323
|
+
this.Pe()),
|
|
324
|
+
this.sn();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
en() {
|
|
328
|
+
const i = this.mite,
|
|
329
|
+
t = this.Ri || this.ki;
|
|
330
|
+
return i && t
|
|
331
|
+
? ti(t, i, this.ji, this.yi || void 0, this.Mi || void 0)
|
|
332
|
+
: null;
|
|
333
|
+
}
|
|
334
|
+
_e(i, t) {
|
|
335
|
+
var s, e, n;
|
|
336
|
+
if ((this.Ki || this._i(), !this.Ki))
|
|
337
|
+
return (
|
|
338
|
+
E.info(
|
|
339
|
+
"SharedWorker initialization failed, falling back to direct EventSource",
|
|
340
|
+
),
|
|
341
|
+
(this.Qi = "direct"),
|
|
342
|
+
void this.on()
|
|
343
|
+
);
|
|
344
|
+
this.Ri && E.info(`Using custom real-time messaging host: ${this.Ri}`),
|
|
345
|
+
E.info("Starting real-time subscription via SharedWorker");
|
|
346
|
+
const r = (null === (s = this.h) || void 0 === s ? void 0 : s.st()) || c,
|
|
347
|
+
o = (null === (e = this.h) || void 0 === e ? void 0 : e.nt()) || u,
|
|
348
|
+
h = (null === (n = this.h) || void 0 === n ? void 0 : n.it()) || d;
|
|
349
|
+
this.Ki.connect({
|
|
350
|
+
mite: i,
|
|
351
|
+
ki: t,
|
|
352
|
+
auth: this.yi || void 0,
|
|
353
|
+
hn: { an: r, ln: o, cn: h },
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
on() {
|
|
357
|
+
this.xi &&
|
|
358
|
+
(E.info(
|
|
359
|
+
"Real-time connection already exists, closing before starting new subscription",
|
|
360
|
+
),
|
|
361
|
+
this.un()),
|
|
362
|
+
this.sn();
|
|
363
|
+
}
|
|
364
|
+
sn(i) {
|
|
365
|
+
const t = this.en();
|
|
366
|
+
if (t) {
|
|
367
|
+
this.Ri && E.info(`Using custom real-time messaging host: ${this.Ri}`);
|
|
368
|
+
try {
|
|
369
|
+
const s = new EventSource(t);
|
|
370
|
+
(s.onopen = () => {
|
|
371
|
+
i
|
|
372
|
+
? (E.info(
|
|
373
|
+
"Gapless reconnection: new connection established, closing old connection",
|
|
374
|
+
),
|
|
375
|
+
i.close())
|
|
376
|
+
: E.info("Real-time messaging connection established"),
|
|
377
|
+
(this.xi = s),
|
|
378
|
+
(this.ji = 0),
|
|
379
|
+
(this.Bi = null),
|
|
380
|
+
(this.zi = !0),
|
|
381
|
+
(this.Xi = !0);
|
|
382
|
+
}),
|
|
383
|
+
s.addEventListener("msg", (i) => {
|
|
384
|
+
this.dn(i.data);
|
|
385
|
+
}),
|
|
386
|
+
(s.onerror = () => {
|
|
387
|
+
const t = s.readyState;
|
|
388
|
+
return (
|
|
389
|
+
this.Hi ||
|
|
390
|
+
(0 === t
|
|
391
|
+
? E.info("Real-time messaging failed to connect")
|
|
392
|
+
: E.info("Real-time messaging connection lost")),
|
|
393
|
+
i && this.xi !== s
|
|
394
|
+
? (E.info(
|
|
395
|
+
"Gapless reconnection failed, keeping old connection",
|
|
396
|
+
),
|
|
397
|
+
s.close(),
|
|
398
|
+
void (this.zi && this.ji < this.Wi && this.gn()))
|
|
399
|
+
: (this.un(),
|
|
400
|
+
this.Xi && (this.Yi++, this.Yi > 1)
|
|
401
|
+
? (E.info(
|
|
402
|
+
"Real-time messaging connection lost twice after successful connect (likely multi-tab conflict), yielding to other tab",
|
|
403
|
+
),
|
|
404
|
+
void (this.zi = !1))
|
|
405
|
+
: void (this.zi && this.ji < this.Wi
|
|
406
|
+
? this.gn()
|
|
407
|
+
: (this.ji >= this.Wi &&
|
|
408
|
+
E.error(
|
|
409
|
+
`Max retry attempts (${this.Wi}) reached for real-time messaging, giving up for current session`,
|
|
410
|
+
),
|
|
411
|
+
(this.zi = !1))))
|
|
412
|
+
);
|
|
413
|
+
});
|
|
414
|
+
} catch (i) {
|
|
415
|
+
E.error(
|
|
416
|
+
`Failed to create real-time messaging connection: ${
|
|
417
|
+
i instanceof Error ? i.message : String(i)
|
|
418
|
+
}`,
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
gn() {
|
|
424
|
+
var i, t, s;
|
|
425
|
+
this.ji++;
|
|
426
|
+
const e = (null === (i = this.h) || void 0 === i ? void 0 : i.st()) || c,
|
|
427
|
+
n = (null === (t = this.h) || void 0 === t ? void 0 : t.it()) || d,
|
|
428
|
+
r = (null === (s = this.h) || void 0 === s ? void 0 : s.nt()) || u;
|
|
429
|
+
let o = this.Bi;
|
|
430
|
+
(null == o || o < e) && (o = e);
|
|
431
|
+
const h = Math.min(r, a(e, o * n));
|
|
432
|
+
(this.Bi = h),
|
|
433
|
+
E.info(
|
|
434
|
+
`Retrying real-time messaging connection in ${h}ms (attempt ${this.ji}/${this.Wi})`,
|
|
435
|
+
),
|
|
436
|
+
(this.Fi = window.setTimeout(() => {
|
|
437
|
+
(this.Fi = null), this.qe();
|
|
438
|
+
}, h));
|
|
439
|
+
}
|
|
440
|
+
Le() {
|
|
441
|
+
if (this.Ke()) {
|
|
442
|
+
if (this.Ve())
|
|
443
|
+
return (
|
|
444
|
+
E.info(
|
|
445
|
+
"Auth token expired during gapless reconnection, falling back to regular reconnection",
|
|
446
|
+
),
|
|
447
|
+
this.Pe(),
|
|
448
|
+
void this.qe()
|
|
449
|
+
);
|
|
450
|
+
null !== this.Ui && (window.clearTimeout(this.Ui), (this.Ui = null)),
|
|
451
|
+
this.sn(this.xi || void 0);
|
|
452
|
+
} else E.error("Cannot perform gapless reconnection without configuration");
|
|
453
|
+
}
|
|
454
|
+
Pe() {
|
|
455
|
+
var i;
|
|
456
|
+
switch (this.Qi) {
|
|
457
|
+
case "sharedworker":
|
|
458
|
+
null === (i = this.Ki) || void 0 === i || i.disconnect();
|
|
459
|
+
break;
|
|
460
|
+
case "direct":
|
|
461
|
+
this.un();
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
un() {
|
|
465
|
+
null !== this.Fi && (window.clearTimeout(this.Fi), (this.Fi = null)),
|
|
466
|
+
null !== this.Ui && (window.clearTimeout(this.Ui), (this.Ui = null)),
|
|
467
|
+
this.xi &&
|
|
468
|
+
(this.xi.close(),
|
|
469
|
+
(this.xi = null),
|
|
470
|
+
E.info("Real-time messaging connection closed"));
|
|
471
|
+
}
|
|
472
|
+
dn(i) {
|
|
473
|
+
try {
|
|
474
|
+
const t = JSON.parse(i);
|
|
475
|
+
this.Se(t);
|
|
476
|
+
} catch (i) {
|
|
477
|
+
E.warn(
|
|
478
|
+
`Failed to parse real-time message: ${
|
|
479
|
+
i instanceof Error ? i.message : String(i)
|
|
480
|
+
}`,
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
changeUser(i = !1) {
|
|
485
|
+
this.Pe(),
|
|
486
|
+
i ||
|
|
487
|
+
(this.Ke() &&
|
|
488
|
+
E.info(
|
|
489
|
+
"Clearing cached real-time messaging configuration for user change",
|
|
490
|
+
),
|
|
491
|
+
this.Ae()),
|
|
492
|
+
this.ye();
|
|
493
|
+
}
|
|
494
|
+
clearData(i = !1) {
|
|
495
|
+
(this.zi = !1),
|
|
496
|
+
this.Pe(),
|
|
497
|
+
i &&
|
|
498
|
+
(this.Ke() &&
|
|
499
|
+
E.info(
|
|
500
|
+
"Clearing cached real-time messaging configuration (wipeData)",
|
|
501
|
+
),
|
|
502
|
+
this.Ae()),
|
|
503
|
+
this.ye();
|
|
504
|
+
}
|
|
505
|
+
destroy() {
|
|
506
|
+
(this.zi = !1),
|
|
507
|
+
this.Pe(),
|
|
508
|
+
this.Ae(),
|
|
509
|
+
this.Ki && (this.Ki.destroy(), (this.Ki = null)),
|
|
510
|
+
this.Li && (this.Qe("ddr", this.Li), (this.Li = null)),
|
|
511
|
+
this.Oi && (this.Qe("ttl", this.Oi), (this.Oi = null)),
|
|
512
|
+
this.qi &&
|
|
513
|
+
(window.removeEventListener("beforeunload", this.qi), (this.qi = null)),
|
|
514
|
+
this.Gi &&
|
|
515
|
+
(window.removeEventListener("pagehide", this.Gi), (this.Gi = null)),
|
|
516
|
+
this.Pi &&
|
|
517
|
+
(window.removeEventListener("pageshow", this.Pi), (this.Pi = null)),
|
|
518
|
+
this.D && (r.removeSubscription(this.D), (this.D = null));
|
|
519
|
+
}
|
|
520
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export const DUST_SHARED_WORKER_CODE =
|
|
2
|
+
'\n"use strict";\nconst workerSelf = self;\nlet eventSource = null;\nlet currentConfig = null;\nlet retryCount = 0;\nlet retryTimeoutId = null;\nlet connectionInProgress = false;\nconst maxRetries = 5;\nconst connectedPorts = new Map();\nlet lastSleepMs = null;\nlet currentRcs = null;\nlet ttlTimeoutId = null;\nlet leaderPortId = null;\nlet ddrTimeoutId = null;\nconst fn = {\n startConnection: null,\n handleMessage: null,\n};\nfunction broadcast(message) {\n connectedPorts.forEach((portInfo, portId) => {\n try {\n portInfo.port.postMessage(message);\n }\n catch (_a) {\n connectedPorts.delete(portId);\n }\n });\n}\nfunction randomInclusive(min, max) {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\nfunction electLeader() {\n if (leaderPortId && connectedPorts.has(leaderPortId)) {\n return;\n }\n const firstPortId = connectedPorts.keys().next().value;\n leaderPortId = firstPortId || null;\n if (leaderPortId) {\n console.log("[Braze Real-Time] Elected leader port:", leaderPortId);\n }\n}\nfunction promoteToLeader(portId) {\n if (connectedPorts.has(portId) && leaderPortId !== portId) {\n leaderPortId = portId;\n console.log("[Braze Real-Time] Promoted to leader (tab became active):", portId);\n }\n}\nfunction sendToLeader(message) {\n electLeader();\n if (!leaderPortId) {\n console.warn("[Braze Real-Time] No leader to send message to");\n return;\n }\n const leader = connectedPorts.get(leaderPortId);\n if (leader) {\n try {\n leader.port.postMessage(message);\n }\n catch (_a) {\n connectedPorts.delete(leaderPortId);\n leaderPortId = null;\n sendToLeader(message);\n }\n }\n}\nfunction closeConnection() {\n connectionInProgress = false;\n if (retryTimeoutId !== null) {\n clearTimeout(retryTimeoutId);\n retryTimeoutId = null;\n }\n if (ttlTimeoutId !== null) {\n clearTimeout(ttlTimeoutId);\n ttlTimeoutId = null;\n }\n if (ddrTimeoutId !== null) {\n clearTimeout(ddrTimeoutId);\n ddrTimeoutId = null;\n }\n if (eventSource) {\n eventSource.close();\n eventSource = null;\n broadcast({ type: "disconnected" });\n }\n}\nfunction retryWithBackoff() {\n if (!currentConfig) {\n return;\n }\n retryCount++;\n const { minSleepMs, maxSleepMs, scaleFactor } = currentConfig.backoff;\n let previousSleepMs = lastSleepMs;\n if (previousSleepMs == null || previousSleepMs < minSleepMs) {\n previousSleepMs = minSleepMs;\n }\n const backoffMs = Math.min(maxSleepMs, randomInclusive(minSleepMs, previousSleepMs * scaleFactor));\n lastSleepMs = backoffMs;\n console.log("[Braze Real-Time] Retrying in " + backoffMs + "ms (attempt " + retryCount + "/" + maxRetries + ")");\n retryTimeoutId = setTimeout(function () {\n retryTimeoutId = null;\n fn.startConnection();\n }, backoffMs);\n}\nfunction startConnection(oldEventSourceToClose) {\n if (!currentConfig) {\n return;\n }\n if (eventSource && !oldEventSourceToClose) {\n console.warn("[Braze Real-Time] Connection already exists");\n return;\n }\n if (connectionInProgress && !oldEventSourceToClose) {\n console.warn("[Braze Real-Time] Connection attempt already in progress");\n return;\n }\n connectionInProgress = true;\n const { dustHost, mite, auth } = currentConfig;\n const dustHostWithScheme = /^https?:\\/\\//i.test(dustHost) ? dustHost : "https://" + dustHost;\n let queryString = "mite=" + encodeURIComponent(mite) + "&attempts=" + retryCount;\n if (auth) {\n queryString += "&auth=" + encodeURIComponent(auth);\n }\n if (currentRcs) {\n queryString += "&rcs=" + encodeURIComponent(currentRcs);\n }\n const subscribeUrl = dustHostWithScheme + "/sse?" + queryString;\n try {\n const newEventSource = new EventSource(subscribeUrl);\n newEventSource.onopen = function () {\n if (oldEventSourceToClose) {\n console.log("[Braze Real-Time] Gapless reconnection: new connection established, closing old connection");\n oldEventSourceToClose.close();\n }\n else {\n console.log("[Braze Real-Time] Connection established");\n }\n eventSource = newEventSource;\n connectionInProgress = false;\n retryCount = 0;\n lastSleepMs = null;\n broadcast({ type: "connected" });\n };\n newEventSource.addEventListener("msg", function (event) {\n fn.handleMessage(event.data);\n });\n newEventSource.onerror = function () {\n const readyState = newEventSource ? newEventSource.readyState : -1;\n if (readyState === 0) {\n console.log("[Braze Real-Time] Failed to connect");\n }\n else {\n console.log("[Braze Real-Time] Connection lost");\n }\n if (oldEventSourceToClose && eventSource !== newEventSource) {\n console.log("[Braze Real-Time] Gapless reconnection failed, keeping old connection");\n newEventSource.close();\n connectionInProgress = false;\n if (retryCount < maxRetries) {\n retryWithBackoff();\n }\n return;\n }\n closeConnection();\n if (retryCount < maxRetries) {\n retryWithBackoff();\n }\n else {\n console.error("[Braze Real-Time] Max retries reached");\n broadcast({ type: "error", error: "Max retry attempts reached" });\n }\n };\n }\n catch (error) {\n connectionInProgress = false;\n console.error("[Braze Real-Time] Failed to create EventSource:", error);\n broadcast({ type: "error", error: String(error) });\n }\n}\nfunction handleTtlMessage(tMs, rcs) {\n if (typeof tMs !== "number") {\n return;\n }\n if (typeof rcs === "string") {\n currentRcs = rcs;\n }\n console.log("[Braze Real-Time] TTL set to " + tMs + "ms, will perform gapless reconnection when expired");\n if (ttlTimeoutId !== null) {\n clearTimeout(ttlTimeoutId);\n }\n ttlTimeoutId = setTimeout(function () {\n ttlTimeoutId = null;\n console.log("[Braze Real-Time] TTL expired, performing gapless reconnection");\n startConnection(eventSource || undefined);\n }, tMs);\n}\nfunction handleDdrMessage(rMs, reason) {\n if (typeof rMs !== "number") {\n return;\n }\n const jitter = Math.random() * rMs * 0.3;\n const waitMs = Math.round(rMs + jitter);\n const reasonStr = reason ? " (" + reason + ")" : "";\n console.log("[Braze Real-Time] Admin requested disconnect" + reasonStr + ", reconnecting in " + waitMs + "ms");\n if (ddrTimeoutId !== null) {\n clearTimeout(ddrTimeoutId);\n }\n closeConnection();\n ddrTimeoutId = setTimeout(function () {\n ddrTimeoutId = null;\n fn.startConnection();\n }, waitMs);\n}\nfunction handleMessage(data) {\n try {\n const message = JSON.parse(data);\n if (!message.type) {\n console.warn("[Braze Real-Time] Message without type:", message);\n return;\n }\n if (message.type === "ttl" && message.body) {\n handleTtlMessage(message.body.t_ms, message.body.rcs);\n return;\n }\n if (message.type === "ddr" && message.body) {\n handleDdrMessage(message.body.r_ms, message.body.e);\n return;\n }\n console.log("[Braze Real-Time] Routing \'" + message.type + "\' message to leader");\n sendToLeader({ type: "message", data: message });\n }\n catch (error) {\n console.warn("[Braze Real-Time] Failed to parse message:", error);\n }\n}\nfn.startConnection = startConnection;\nfn.handleMessage = handleMessage;\nfunction handlePortMessage(port, portId, message) {\n switch (message.type) {\n case "connect":\n if (currentConfig &&\n (currentConfig.mite !== message.config.mite || currentConfig.dustHost !== message.config.dustHost)) {\n console.log("[Braze Real-Time] Config changed, reconnecting");\n closeConnection();\n retryCount = 0;\n lastSleepMs = null;\n currentRcs = null;\n }\n currentConfig = message.config;\n electLeader();\n if (!eventSource && !connectionInProgress) {\n startConnection();\n }\n else if (eventSource) {\n port.postMessage({ type: "connected" });\n }\n break;\n case "disconnect":\n connectedPorts.delete(portId);\n if (portId === leaderPortId) {\n leaderPortId = null;\n electLeader();\n }\n if (connectedPorts.size === 0) {\n console.log("[Braze Real-Time] No more ports, closing connection");\n closeConnection();\n currentConfig = null;\n currentRcs = null;\n leaderPortId = null;\n }\n break;\n case "tab_active":\n promoteToLeader(portId);\n break;\n case "ping":\n port.postMessage({ type: "pong" });\n break;\n default:\n console.warn("[Braze Real-Time] Unknown message type:", message.type);\n }\n}\nworkerSelf.onconnect = function (event) {\n const port = event.ports[0];\n const portId = "port-" + Date.now() + "-" + Math.random().toString(36).substr(2, 9);\n connectedPorts.set(portId, { port: port });\n port.onmessage = function (messageEvent) {\n try {\n handlePortMessage(port, portId, messageEvent.data);\n }\n catch (error) {\n console.error("[Braze Real-Time] Error handling message:", error);\n }\n };\n port.onmessageerror = function () {\n console.warn("[Braze Real-Time] Message error from port:", portId);\n connectedPorts.delete(portId);\n };\n port.start();\n};\n';
|