@arsel.sa/web-sdk 1.0.0 → 1.2.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/CHANGELOG.md +103 -1
- package/dist/arsel.js +1068 -327
- package/dist/arsel.js.map +1 -1
- package/dist/arsel.umd.cjs +107 -1
- package/dist/arsel.umd.cjs.map +1 -1
- package/dist/events.d.ts +7 -0
- package/dist/inapp-view.d.ts +16 -0
- package/dist/inapp.d.ts +83 -0
- package/dist/index.d.ts +20 -9
- package/dist/install.d.ts +10 -0
- package/dist/push.d.ts +16 -0
- package/dist/session.d.ts +5 -1
- package/dist/store.d.ts +31 -4
- package/dist/transport.d.ts +1 -1
- package/dist/types.d.ts +32 -0
- package/dist/version.d.ts +1 -1
- package/package.json +2 -1
- package/sw/arsel-sw.js +27 -2
package/dist/arsel.js
CHANGED
|
@@ -1,51 +1,62 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
const Ye = "arsel";
|
|
2
|
+
const S = {
|
|
3
|
+
events: "events",
|
|
4
|
+
inAppBeacons: "inapp_beacons"
|
|
5
|
+
};
|
|
6
|
+
let H = null;
|
|
7
|
+
function Je() {
|
|
8
|
+
return H || (H = new Promise((e, t) => {
|
|
9
|
+
const n = indexedDB.open(Ye, 2);
|
|
7
10
|
n.onupgradeneeded = () => {
|
|
8
11
|
const i = n.result;
|
|
9
|
-
i.objectStoreNames.contains("kv") || i.createObjectStore("kv")
|
|
12
|
+
i.objectStoreNames.contains("kv") || i.createObjectStore("kv");
|
|
13
|
+
for (const r of Object.values(S))
|
|
14
|
+
i.objectStoreNames.contains(r) || i.createObjectStore(r, { keyPath: "id", autoIncrement: !0 });
|
|
10
15
|
}, n.onsuccess = () => e(n.result), n.onerror = () => t(n.error);
|
|
11
|
-
}),
|
|
16
|
+
}), H);
|
|
12
17
|
}
|
|
13
|
-
function
|
|
14
|
-
return
|
|
15
|
-
(i) => new Promise((
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
+
function P(e, t, n) {
|
|
19
|
+
return Je().then(
|
|
20
|
+
(i) => new Promise((r, s) => {
|
|
21
|
+
const a = n(i.transaction(e, t).objectStore(e));
|
|
22
|
+
a.onsuccess = () => r(a.result), a.onerror = () => s(a.error);
|
|
18
23
|
})
|
|
19
24
|
);
|
|
20
25
|
}
|
|
21
26
|
function c(e) {
|
|
22
|
-
return
|
|
27
|
+
return P("kv", "readonly", (t) => t.get(e)).then(
|
|
23
28
|
(t) => t ?? null
|
|
24
29
|
);
|
|
25
30
|
}
|
|
26
31
|
function u(e, t) {
|
|
27
|
-
return
|
|
32
|
+
return P("kv", "readwrite", (n) => n.put(t, e));
|
|
28
33
|
}
|
|
29
|
-
function
|
|
30
|
-
return
|
|
34
|
+
function L(e) {
|
|
35
|
+
return P("kv", "readwrite", (t) => t.delete(e));
|
|
31
36
|
}
|
|
32
|
-
function
|
|
33
|
-
return
|
|
34
|
-
|
|
37
|
+
function De(e, t, n = "") {
|
|
38
|
+
return P(
|
|
39
|
+
e,
|
|
35
40
|
"readwrite",
|
|
36
|
-
(
|
|
41
|
+
(i) => i.add({ body: t, idempotencyKey: n, createdAtMs: Date.now() })
|
|
37
42
|
);
|
|
38
43
|
}
|
|
39
|
-
function
|
|
40
|
-
return
|
|
44
|
+
function le(e) {
|
|
45
|
+
return P(e, "readonly", (t) => t.getAll());
|
|
41
46
|
}
|
|
42
|
-
function
|
|
43
|
-
return
|
|
47
|
+
function ue(e, t) {
|
|
48
|
+
return P(e, "readwrite", (n) => n.delete(t));
|
|
44
49
|
}
|
|
45
|
-
function
|
|
46
|
-
return
|
|
50
|
+
function Oe(e) {
|
|
51
|
+
return P(e, "readonly", (t) => t.count());
|
|
47
52
|
}
|
|
48
|
-
|
|
53
|
+
async function Ge(e, t) {
|
|
54
|
+
const n = await le(e);
|
|
55
|
+
if (!(n.length <= t))
|
|
56
|
+
for (const i of n.slice(0, n.length - t))
|
|
57
|
+
i.id !== void 0 && await ue(e, i.id);
|
|
58
|
+
}
|
|
59
|
+
const o = {
|
|
49
60
|
clientKey: "client_key",
|
|
50
61
|
baseUrl: "base_url",
|
|
51
62
|
anonymousId: "anonymous_id",
|
|
@@ -56,47 +67,59 @@ const r = {
|
|
|
56
67
|
deviceSecret: "device_secret",
|
|
57
68
|
vapidKeyVersion: "vapid_key_version",
|
|
58
69
|
endpoint: "endpoint",
|
|
70
|
+
subscriptionStatus: "subscription_status",
|
|
71
|
+
installReported: "install_reported",
|
|
59
72
|
sessionStartedAt: "session_started_at",
|
|
60
73
|
backgroundedAt: "backgrounded_at",
|
|
61
74
|
lastResponseCode: "last_response_code",
|
|
62
75
|
lastResponsePath: "last_response_path",
|
|
63
|
-
lastResponseAtMs: "last_response_at"
|
|
76
|
+
lastResponseAtMs: "last_response_at",
|
|
77
|
+
/** `{ bundleVersion, ttlSeconds, fetchedAtMs, messages }` — the cached bundle. */
|
|
78
|
+
inAppBundle: "inapp_bundle",
|
|
79
|
+
/** messageId -> lifetime counters. Survives `reset()`: it describes the device. */
|
|
80
|
+
inAppState: "inapp_state",
|
|
81
|
+
/**
|
|
82
|
+
* `{ startedAt, counts }`. Persisted rather than held in memory so
|
|
83
|
+
* `maxPerSession` survives a navigation — on a multi-page site an in-memory
|
|
84
|
+
* counter makes the cap per-page, which is not a cap at all.
|
|
85
|
+
*/
|
|
86
|
+
inAppSession: "inapp_session"
|
|
64
87
|
};
|
|
65
|
-
async function
|
|
66
|
-
const e = await c(
|
|
88
|
+
async function X() {
|
|
89
|
+
const e = await c(o.anonymousId);
|
|
67
90
|
if (e) return e;
|
|
68
91
|
const t = crypto.randomUUID();
|
|
69
|
-
return await u(
|
|
92
|
+
return await u(o.anonymousId, t), t;
|
|
70
93
|
}
|
|
71
|
-
async function
|
|
94
|
+
async function Ze() {
|
|
72
95
|
const e = crypto.randomUUID();
|
|
73
|
-
return await u(
|
|
96
|
+
return await u(o.anonymousId, e), e;
|
|
74
97
|
}
|
|
75
|
-
const
|
|
98
|
+
const j = "1.2.0", Re = { "X-Arsel-SDK": `web/${j}` }, y = {
|
|
76
99
|
success: "success",
|
|
77
100
|
retryable: "retryable",
|
|
78
101
|
permanent: "permanent",
|
|
79
102
|
reauth: "reauth"
|
|
80
|
-
},
|
|
81
|
-
function
|
|
82
|
-
return e >= 200 && e <= 299 ?
|
|
103
|
+
}, J = -1;
|
|
104
|
+
function Me(e, t) {
|
|
105
|
+
return e >= 200 && e <= 299 ? y.success : e === 408 || e === 429 || e >= 500 && e <= 599 ? y.retryable : t && (e === 401 || e === 403 || e === 404) ? y.reauth : e === 404 ? y.retryable : y.permanent;
|
|
83
106
|
}
|
|
84
|
-
async function
|
|
107
|
+
async function G(e, t) {
|
|
85
108
|
try {
|
|
86
109
|
await Promise.all([
|
|
87
|
-
u(
|
|
88
|
-
u(
|
|
89
|
-
u(
|
|
110
|
+
u(o.lastResponseCode, t),
|
|
111
|
+
u(o.lastResponsePath, e),
|
|
112
|
+
u(o.lastResponseAtMs, Date.now())
|
|
90
113
|
]);
|
|
91
114
|
} catch {
|
|
92
115
|
}
|
|
93
116
|
}
|
|
94
|
-
async function
|
|
95
|
-
let
|
|
117
|
+
async function z(e, t, n, i = {}, r = !1) {
|
|
118
|
+
let s;
|
|
96
119
|
try {
|
|
97
|
-
|
|
120
|
+
s = await fetch(e + t, {
|
|
98
121
|
method: "POST",
|
|
99
|
-
headers: { "Content-Type": "application/json", ...
|
|
122
|
+
headers: { "Content-Type": "application/json", ...Re, ...i },
|
|
100
123
|
body: JSON.stringify(n),
|
|
101
124
|
// The SDK never relies on cookies, and sending them would attach a
|
|
102
125
|
// first-party session to a cross-origin call for no reason.
|
|
@@ -104,30 +127,42 @@ async function R(e, t, n, i = {}, s = !1) {
|
|
|
104
127
|
keepalive: !0
|
|
105
128
|
});
|
|
106
129
|
} catch {
|
|
107
|
-
return await
|
|
130
|
+
return await G(t, J), { result: y.retryable, code: J, body: null };
|
|
108
131
|
}
|
|
109
|
-
await
|
|
110
|
-
const
|
|
132
|
+
await G(t, s.status);
|
|
133
|
+
const a = Me(s.status, r);
|
|
111
134
|
let l = null;
|
|
112
135
|
try {
|
|
113
|
-
l = await
|
|
136
|
+
l = await s.json();
|
|
114
137
|
} catch {
|
|
115
138
|
}
|
|
116
|
-
return { result:
|
|
139
|
+
return { result: a, code: s.status, body: l };
|
|
117
140
|
}
|
|
118
|
-
async function
|
|
141
|
+
async function de(e, t, n = {}, i = !1, r = {}) {
|
|
142
|
+
let s;
|
|
119
143
|
try {
|
|
120
|
-
|
|
144
|
+
s = await fetch(e + t, {
|
|
145
|
+
...r,
|
|
121
146
|
credentials: "omit",
|
|
122
|
-
headers:
|
|
147
|
+
headers: { ...Re, ...n }
|
|
123
148
|
});
|
|
124
|
-
return await N(t, n.status), n.ok ? await n.json() : null;
|
|
125
149
|
} catch {
|
|
126
|
-
return await
|
|
150
|
+
return await G(t, J), { result: y.retryable, code: J, body: null };
|
|
151
|
+
}
|
|
152
|
+
await G(t, s.status);
|
|
153
|
+
let a = null;
|
|
154
|
+
try {
|
|
155
|
+
a = await s.json();
|
|
156
|
+
} catch {
|
|
127
157
|
}
|
|
158
|
+
return {
|
|
159
|
+
result: Me(s.status, i),
|
|
160
|
+
code: s.status,
|
|
161
|
+
body: a
|
|
162
|
+
};
|
|
128
163
|
}
|
|
129
|
-
const
|
|
130
|
-
function
|
|
164
|
+
const Qe = "/v1/events/send", x = "arsel.", et = `${x}session_start`, tt = `${x}session_end`, nt = `${x}identify`, it = `${x}app_installed`, rt = `${x}screen_view`, ot = 80, st = 128, at = 255, ge = 50, ct = 8, ve = 64 * 1024;
|
|
165
|
+
function se(e, t) {
|
|
131
166
|
if (e === null) return null;
|
|
132
167
|
const n = typeof e;
|
|
133
168
|
if (n === "string" || n === "boolean") return e;
|
|
@@ -135,466 +170,1172 @@ function D(e, t) {
|
|
|
135
170
|
if (n === "bigint") return String(e);
|
|
136
171
|
if (e instanceof Date)
|
|
137
172
|
return Number.isNaN(e.getTime()) ? void 0 : e.toISOString();
|
|
138
|
-
if (n !== "object" || t >=
|
|
173
|
+
if (n !== "object" || t >= ct) return;
|
|
139
174
|
if (Array.isArray(e))
|
|
140
|
-
return e.map((
|
|
175
|
+
return e.map((r) => se(r, t + 1) ?? null);
|
|
141
176
|
const i = {};
|
|
142
|
-
for (const [
|
|
143
|
-
if (!
|
|
144
|
-
const
|
|
145
|
-
|
|
177
|
+
for (const [r, s] of Object.entries(e)) {
|
|
178
|
+
if (!r) continue;
|
|
179
|
+
const a = se(s, t + 1);
|
|
180
|
+
a !== void 0 && (i[r] = a);
|
|
146
181
|
}
|
|
147
182
|
return i;
|
|
148
183
|
}
|
|
149
|
-
function
|
|
184
|
+
function lt(e) {
|
|
150
185
|
const t = {};
|
|
151
186
|
let n = 2, i = !1;
|
|
152
|
-
for (const [
|
|
153
|
-
if (!
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
156
|
-
const l =
|
|
157
|
-
if (n + l >
|
|
187
|
+
for (const [r, s] of Object.entries(e ?? {})) {
|
|
188
|
+
if (!r) continue;
|
|
189
|
+
const a = se(s, 0);
|
|
190
|
+
if (a === void 0) continue;
|
|
191
|
+
const l = r.length + JSON.stringify(a).length + 6;
|
|
192
|
+
if (n + l > ve) {
|
|
158
193
|
i = !0;
|
|
159
194
|
continue;
|
|
160
195
|
}
|
|
161
|
-
n += l, t[
|
|
196
|
+
n += l, t[r] = a;
|
|
162
197
|
}
|
|
163
198
|
return i && console.warn(
|
|
164
|
-
`[arsel] event data exceeded ${
|
|
199
|
+
`[arsel] event data exceeded ${ve} serialized bytes — oversized properties were dropped`
|
|
165
200
|
), t;
|
|
166
201
|
}
|
|
167
|
-
async function
|
|
168
|
-
const [i, s, a
|
|
169
|
-
|
|
170
|
-
c(
|
|
171
|
-
c(
|
|
172
|
-
c(
|
|
202
|
+
async function ut(e, t, n) {
|
|
203
|
+
const [i, r, s, a] = await Promise.all([
|
|
204
|
+
X(),
|
|
205
|
+
c(o.externalId),
|
|
206
|
+
c(o.email),
|
|
207
|
+
c(o.phoneNumber)
|
|
173
208
|
]), l = {
|
|
174
|
-
event: e.slice(0,
|
|
209
|
+
event: e.slice(0, ot),
|
|
175
210
|
// Always sent, even once identified: it is what the backend merges FROM.
|
|
176
|
-
anonymous_id: i.slice(0,
|
|
177
|
-
data:
|
|
211
|
+
anonymous_id: i.slice(0, st),
|
|
212
|
+
data: lt(t),
|
|
178
213
|
timestamp: new Date(n).toISOString()
|
|
179
214
|
};
|
|
180
|
-
return
|
|
215
|
+
return r && (l.external_id = r.slice(0, at)), s && (l.email = s), a && (l.phone_number = a), JSON.stringify(l);
|
|
181
216
|
}
|
|
182
|
-
async function
|
|
183
|
-
await
|
|
217
|
+
async function k(e, t, n = Date.now()) {
|
|
218
|
+
await De(S.events, await ut(e, t, n), crypto.randomUUID()), V().catch(() => {
|
|
184
219
|
});
|
|
185
220
|
}
|
|
186
|
-
let
|
|
187
|
-
function
|
|
188
|
-
return
|
|
189
|
-
|
|
190
|
-
}),
|
|
221
|
+
let $ = null;
|
|
222
|
+
function V() {
|
|
223
|
+
return $ || ($ = pt().finally(() => {
|
|
224
|
+
$ = null;
|
|
225
|
+
}), $);
|
|
191
226
|
}
|
|
192
|
-
function
|
|
227
|
+
function dt(e) {
|
|
193
228
|
const t = e[0].idempotencyKey;
|
|
194
229
|
return e.length === 1 ? t : `${t}:${e[e.length - 1].idempotencyKey}:${e.length}`;
|
|
195
230
|
}
|
|
196
|
-
function
|
|
231
|
+
function ft(e, t, n) {
|
|
197
232
|
e.some(
|
|
198
|
-
(
|
|
233
|
+
(r) => r.external_id || r.email || r.phone_number
|
|
199
234
|
) && console.error(
|
|
200
235
|
`[arsel] ${e.length} event(s) carrying identifiers were rejected permanently (HTTP ${t}) and dropped. Response: ${JSON.stringify(n)}`
|
|
201
236
|
);
|
|
202
237
|
}
|
|
203
|
-
async function
|
|
238
|
+
async function pt() {
|
|
204
239
|
const [e, t] = await Promise.all([
|
|
205
|
-
c(
|
|
206
|
-
c(
|
|
240
|
+
c(o.clientKey),
|
|
241
|
+
c(o.baseUrl)
|
|
207
242
|
]);
|
|
208
243
|
if (!(!e || !t))
|
|
209
244
|
for (; ; ) {
|
|
210
|
-
const n = await
|
|
245
|
+
const n = await le(S.events);
|
|
211
246
|
if (n.length === 0) return;
|
|
212
|
-
for (let i = 0; i < n.length; i +=
|
|
213
|
-
const
|
|
247
|
+
for (let i = 0; i < n.length; i += ge) {
|
|
248
|
+
const r = n.slice(i, i + ge), s = r.map(
|
|
214
249
|
(l) => JSON.parse(l.body)
|
|
215
|
-
),
|
|
250
|
+
), a = await z(
|
|
216
251
|
t,
|
|
217
|
-
|
|
218
|
-
|
|
252
|
+
Qe,
|
|
253
|
+
r.length === 1 ? s[0] : { events: s },
|
|
219
254
|
{
|
|
220
255
|
Authorization: `Bearer ${e}`,
|
|
221
|
-
"Idempotency-Key":
|
|
256
|
+
"Idempotency-Key": dt(r)
|
|
222
257
|
}
|
|
223
258
|
);
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
for (const l of
|
|
227
|
-
l.id !== void 0 && await
|
|
259
|
+
if (a.result === y.retryable) return;
|
|
260
|
+
a.result !== y.success && ft(s, a.code, a.body);
|
|
261
|
+
for (const l of r)
|
|
262
|
+
l.id !== void 0 && await ue(S.events, l.id);
|
|
228
263
|
}
|
|
229
264
|
}
|
|
230
265
|
}
|
|
231
|
-
|
|
266
|
+
const ee = 1e3, mt = 720 * 60 * 60 * ee, yt = 500, Se = 50, bt = 86400, ht = 900, q = {
|
|
267
|
+
maxPerSession: 1,
|
|
268
|
+
maxLifetime: 3,
|
|
269
|
+
minSecondsBetween: 86400,
|
|
270
|
+
delaySeconds: 0
|
|
271
|
+
}, wt = [
|
|
272
|
+
"MODAL",
|
|
273
|
+
"BANNER_TOP",
|
|
274
|
+
"BANNER_BOTTOM",
|
|
275
|
+
"IMAGE_ONLY"
|
|
276
|
+
];
|
|
277
|
+
let fe = !1, d = null, h = {}, v = { startedAt: 0, counts: {} }, F = null, K = null, Be = !1, ie = null, _ = null, Ue = !1, Ae = !1;
|
|
278
|
+
function N(e) {
|
|
279
|
+
Ue && console.info(`[arsel] in-app: ${e}`);
|
|
280
|
+
}
|
|
281
|
+
async function gt(e) {
|
|
282
|
+
fe = !0, Ue = e;
|
|
283
|
+
const [t, n, i] = await Promise.all([
|
|
284
|
+
c(o.inAppBundle),
|
|
285
|
+
c(o.inAppState),
|
|
286
|
+
c(o.inAppSession)
|
|
287
|
+
]);
|
|
288
|
+
d = t, h = n ?? {}, v = i ?? { startedAt: 0, counts: {} }, await Ke(), await te();
|
|
289
|
+
}
|
|
290
|
+
function vt(e) {
|
|
291
|
+
_ = e;
|
|
292
|
+
}
|
|
293
|
+
function St(e) {
|
|
294
|
+
Be = e, e && ae();
|
|
295
|
+
}
|
|
296
|
+
function At() {
|
|
297
|
+
return {
|
|
298
|
+
messages: (d == null ? void 0 : d.messages.length) ?? 0,
|
|
299
|
+
bundleVersion: (d == null ? void 0 : d.bundleVersion) ?? null,
|
|
300
|
+
fetchedAtMs: (d == null ? void 0 : d.fetchedAtMs) ?? null
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function Et() {
|
|
304
|
+
return Oe(S.inAppBeacons);
|
|
305
|
+
}
|
|
306
|
+
async function Ce() {
|
|
307
|
+
d = null, await L(o.inAppBundle), fe && await te(!0);
|
|
308
|
+
}
|
|
309
|
+
function It() {
|
|
310
|
+
te(!0);
|
|
311
|
+
}
|
|
312
|
+
function te(e = !1) {
|
|
313
|
+
return ie ?? (ie = _t(e).finally(() => {
|
|
314
|
+
ie = null;
|
|
315
|
+
})), ie;
|
|
316
|
+
}
|
|
317
|
+
async function _t(e) {
|
|
318
|
+
if (!fe) return;
|
|
319
|
+
const t = Date.now();
|
|
320
|
+
if (!e && d && t - d.fetchedAtMs < d.ttlSeconds * ee)
|
|
321
|
+
return;
|
|
322
|
+
const n = await $e();
|
|
323
|
+
if (!n) return;
|
|
324
|
+
const i = Nt(n.clientKey, n.installationId), r = {
|
|
325
|
+
"X-Arsel-Device-Auth": n.deviceSecret
|
|
326
|
+
}, s = !!(d != null && d.bundleVersion);
|
|
327
|
+
s && (r["If-None-Match"] = `"${(d == null ? void 0 : d.bundleVersion) ?? ""}"`);
|
|
328
|
+
let a = await Ee(n.baseUrl, i, r);
|
|
329
|
+
if (a.code === Lt && s && Ae && (N("conditional request failed; retrying without If-None-Match"), delete r["If-None-Match"], a = await Ee(n.baseUrl, i, r)), a.code === Kt) {
|
|
330
|
+
d && (d = { ...d, fetchedAtMs: t }, await u(o.inAppBundle, d));
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (a.result !== y.success || !a.body)
|
|
334
|
+
return;
|
|
335
|
+
s || (Ae = !0);
|
|
336
|
+
const l = xt(a.body, t);
|
|
337
|
+
l && (d = l, await u(o.inAppBundle, d), await Ct(l, t));
|
|
338
|
+
}
|
|
339
|
+
function Ee(e, t, n) {
|
|
340
|
+
return de(e, t, n, !0, {
|
|
341
|
+
// Without no-store the browser revalidates on its own against the response's
|
|
342
|
+
// ETag + Cache-Control and hands back a synthesized 200; the manually-set
|
|
343
|
+
// If-None-Match never reaches the server and 304 never happens.
|
|
344
|
+
cache: "no-store"
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
function Nt(e, t) {
|
|
348
|
+
const n = encodeURIComponent(e), i = encodeURIComponent(t);
|
|
349
|
+
return `/api/v1/orgs/${n}/in-app/bundle?installationId=${i}`;
|
|
350
|
+
}
|
|
351
|
+
async function $e() {
|
|
352
|
+
const [e, t, n, i] = await Promise.all([
|
|
353
|
+
c(o.clientKey),
|
|
354
|
+
c(o.baseUrl),
|
|
355
|
+
c(o.installationId),
|
|
356
|
+
c(o.deviceSecret)
|
|
357
|
+
]);
|
|
358
|
+
return !e || !t || !n || !i ? null : { clientKey: e, baseUrl: t, installationId: n, deviceSecret: i };
|
|
359
|
+
}
|
|
360
|
+
function xt(e, t) {
|
|
361
|
+
if (typeof (e == null ? void 0 : e.bundleVersion) != "string")
|
|
362
|
+
return N("response carried no bundleVersion"), null;
|
|
363
|
+
e.contractVersion !== void 0 && e.contractVersion !== 1 && N(`unknown contractVersion ${String(e.contractVersion)}; proceeding`);
|
|
364
|
+
const n = Array.isArray(e.messages) ? e.messages : [], i = [];
|
|
365
|
+
for (const s of n) {
|
|
366
|
+
const a = kt(s);
|
|
367
|
+
a && i.push(a);
|
|
368
|
+
}
|
|
369
|
+
n.length !== i.length && N(`dropped ${n.length - i.length} unrenderable message(s)`);
|
|
370
|
+
const r = O(e.ttlSeconds);
|
|
371
|
+
return {
|
|
372
|
+
bundleVersion: e.bundleVersion,
|
|
373
|
+
ttlSeconds: r && r > 0 ? r : ht,
|
|
374
|
+
fetchedAtMs: t,
|
|
375
|
+
messages: i
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
function kt(e) {
|
|
379
|
+
if (!D(e)) return null;
|
|
380
|
+
const t = m(e.campaignId), n = m(e.messageId), i = m(e.layout), r = D(e.content) ? e.content : null, s = r ? m(r.headline) : void 0;
|
|
381
|
+
if (!t || !n || !i || !r || !s)
|
|
382
|
+
return N("message missing a required field"), null;
|
|
383
|
+
if (!wt.includes(i))
|
|
384
|
+
return N(`layout ${i} is not renderable on web`), null;
|
|
385
|
+
const a = D(e.trigger) ? e.trigger : {}, l = D(e.displayRules) ? e.displayRules : {};
|
|
386
|
+
return {
|
|
387
|
+
campaignId: t,
|
|
388
|
+
messageId: n,
|
|
389
|
+
variantKey: m(e.variantKey) ?? "default",
|
|
390
|
+
priority: O(e.priority) ?? 0,
|
|
391
|
+
expiresAtMs: $t(e.expiresAt),
|
|
392
|
+
triggerType: m(a.type) ?? "APP_OPEN",
|
|
393
|
+
triggerEventName: m(a.eventName) ?? null,
|
|
394
|
+
triggerProperties: D(a.properties) ? a.properties : null,
|
|
395
|
+
displayRules: {
|
|
396
|
+
maxPerSession: O(l.maxPerSession) ?? q.maxPerSession,
|
|
397
|
+
maxLifetime: O(l.maxLifetime) ?? q.maxLifetime,
|
|
398
|
+
minSecondsBetween: O(l.minSecondsBetween) ?? q.minSecondsBetween,
|
|
399
|
+
delaySeconds: O(l.delaySeconds) ?? q.delaySeconds
|
|
400
|
+
},
|
|
401
|
+
layout: i,
|
|
402
|
+
content: {
|
|
403
|
+
headline: s,
|
|
404
|
+
body: m(r.body) ?? "",
|
|
405
|
+
imageUrl: m(r.imageUrl),
|
|
406
|
+
backgroundColor: m(r.backgroundColor),
|
|
407
|
+
textColor: m(r.textColor),
|
|
408
|
+
// Absent means "not suppressed"; only an explicit false hides it.
|
|
409
|
+
showCloseButton: r.showCloseButton !== !1
|
|
410
|
+
},
|
|
411
|
+
// `buttons` arrives as null, not [], when a campaign has none.
|
|
412
|
+
buttons: Array.isArray(e.buttons) ? e.buttons.map(Pt).filter((w) => w !== null) : []
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
function Pt(e) {
|
|
416
|
+
if (!D(e)) return null;
|
|
417
|
+
const t = m(e.buttonId), n = m(e.label), i = m(e.action);
|
|
418
|
+
return !t || !n || !i ? null : {
|
|
419
|
+
buttonId: t,
|
|
420
|
+
label: n,
|
|
421
|
+
action: i,
|
|
422
|
+
value: m(e.value),
|
|
423
|
+
style: m(e.style) === "SECONDARY" ? "SECONDARY" : "PRIMARY"
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
function Tt(e, t, n, i) {
|
|
427
|
+
if (Be || F !== null || !d) return null;
|
|
428
|
+
for (const r of d.messages) {
|
|
429
|
+
if (r.triggerType !== t || t !== "APP_OPEN" && r.triggerEventName !== n || !Dt(r.triggerProperties, i)) continue;
|
|
430
|
+
const s = h[r.messageId];
|
|
431
|
+
if (r.expiresAtMs !== null && r.expiresAtMs <= e) {
|
|
432
|
+
Ut(r);
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
if (!(((s == null ? void 0 : s.shown) ?? 0) >= r.displayRules.maxLifetime) && !((v.counts[r.messageId] ?? 0) >= r.displayRules.maxPerSession) && !(s && e - s.lastShownAtMs < r.displayRules.minSecondsBetween * ee))
|
|
436
|
+
return r;
|
|
437
|
+
}
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
function Dt(e, t) {
|
|
441
|
+
if (!e) return !0;
|
|
442
|
+
const n = t;
|
|
443
|
+
for (const [i, r] of Object.entries(e))
|
|
444
|
+
if (String(n[i]) !== String(r)) return !1;
|
|
445
|
+
return !0;
|
|
446
|
+
}
|
|
447
|
+
function pe(e, t, n = {}) {
|
|
448
|
+
try {
|
|
449
|
+
const i = Tt(Date.now(), e, t, n);
|
|
450
|
+
if (!i) return;
|
|
451
|
+
F = i.messageId, Le = t;
|
|
452
|
+
const r = i.displayRules.delaySeconds * ee;
|
|
453
|
+
if (r <= 0) {
|
|
454
|
+
_ == null || _(i);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
K = setTimeout(() => {
|
|
458
|
+
K = null, _ == null || _(i);
|
|
459
|
+
}, r);
|
|
460
|
+
} catch (i) {
|
|
461
|
+
N(`observe failed: ${i instanceof Error ? i.message : "unknown"}`), F = null;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
let Le = null;
|
|
465
|
+
function Ot() {
|
|
466
|
+
return Le;
|
|
467
|
+
}
|
|
468
|
+
function Ie() {
|
|
469
|
+
Ke().then(() => {
|
|
470
|
+
pe("APP_OPEN", null, {});
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
function ae() {
|
|
474
|
+
K !== null && (clearTimeout(K), K = null, F = null);
|
|
475
|
+
}
|
|
476
|
+
function _e() {
|
|
477
|
+
F = null;
|
|
478
|
+
}
|
|
479
|
+
async function Rt(e, t) {
|
|
480
|
+
const n = Date.now(), i = h[e.messageId] ?? {
|
|
481
|
+
shown: 0,
|
|
482
|
+
lastShownAtMs: 0,
|
|
483
|
+
lastSeenInBundleAtMs: n
|
|
484
|
+
};
|
|
485
|
+
h = {
|
|
486
|
+
...h,
|
|
487
|
+
[e.messageId]: { ...i, shown: i.shown + 1, lastShownAtMs: n }
|
|
488
|
+
}, v = {
|
|
489
|
+
...v,
|
|
490
|
+
counts: {
|
|
491
|
+
...v.counts,
|
|
492
|
+
[e.messageId]: (v.counts[e.messageId] ?? 0) + 1
|
|
493
|
+
}
|
|
494
|
+
}, await Promise.all([
|
|
495
|
+
u(o.inAppState, h),
|
|
496
|
+
u(o.inAppSession, v)
|
|
497
|
+
]), await ne(e, "impression", { triggerEventName: t });
|
|
498
|
+
}
|
|
499
|
+
async function Mt(e, t) {
|
|
500
|
+
await ne(e, "clicked", { buttonId: t });
|
|
501
|
+
}
|
|
502
|
+
async function Bt(e, t) {
|
|
503
|
+
await ne(e, "dismissed", {
|
|
504
|
+
visibleSeconds: Math.max(
|
|
505
|
+
0,
|
|
506
|
+
Math.min(bt, Math.round(t))
|
|
507
|
+
)
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
function Ut(e) {
|
|
511
|
+
const t = h[e.messageId];
|
|
512
|
+
t != null && t.expiredReported || (h = {
|
|
513
|
+
...h,
|
|
514
|
+
[e.messageId]: {
|
|
515
|
+
shown: (t == null ? void 0 : t.shown) ?? 0,
|
|
516
|
+
lastShownAtMs: (t == null ? void 0 : t.lastShownAtMs) ?? 0,
|
|
517
|
+
lastSeenInBundleAtMs: (t == null ? void 0 : t.lastSeenInBundleAtMs) ?? Date.now(),
|
|
518
|
+
expiredReported: !0
|
|
519
|
+
}
|
|
520
|
+
}, u(o.inAppState, h), ne(e, "expired", {}));
|
|
521
|
+
}
|
|
522
|
+
async function ne(e, t, n) {
|
|
523
|
+
const i = {
|
|
524
|
+
messageId: e.messageId,
|
|
525
|
+
campaignId: e.campaignId,
|
|
526
|
+
eventType: t,
|
|
527
|
+
// Stamped when it HAPPENED, not at flush: a beacon that waits out an offline
|
|
528
|
+
// spell would otherwise land in the wrong hour bucket.
|
|
529
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
530
|
+
variantKey: e.variantKey
|
|
531
|
+
};
|
|
532
|
+
n.buttonId && (i.buttonId = n.buttonId), n.visibleSeconds !== void 0 && (i.visibleSeconds = n.visibleSeconds), n.triggerEventName && (i.triggerEventName = n.triggerEventName), await De(S.inAppBeacons, JSON.stringify(i)), await Ge(S.inAppBeacons, yt), Y();
|
|
533
|
+
}
|
|
534
|
+
async function Y() {
|
|
535
|
+
const e = await $e();
|
|
536
|
+
if (!e) return;
|
|
537
|
+
const t = await le(S.inAppBeacons);
|
|
538
|
+
if (t.length === 0) return;
|
|
539
|
+
const n = `/api/v1/orgs/${encodeURIComponent(e.clientKey)}/in-app/events`;
|
|
540
|
+
for (let i = 0; i < t.length; i += Se) {
|
|
541
|
+
const r = t.slice(i, i + Se);
|
|
542
|
+
if ((await z(
|
|
543
|
+
e.baseUrl,
|
|
544
|
+
n,
|
|
545
|
+
{
|
|
546
|
+
installationId: e.installationId,
|
|
547
|
+
events: r.map((a) => JSON.parse(a.body))
|
|
548
|
+
},
|
|
549
|
+
{ "X-Arsel-Device-Auth": e.deviceSecret },
|
|
550
|
+
!0
|
|
551
|
+
)).result === y.retryable) return;
|
|
552
|
+
for (const a of r)
|
|
553
|
+
a.id !== void 0 && await ue(S.inAppBeacons, a.id);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
async function Ct(e, t) {
|
|
557
|
+
const n = new Set(e.messages.map((r) => r.messageId)), i = {};
|
|
558
|
+
for (const [r, s] of Object.entries(h)) {
|
|
559
|
+
const a = n.has(r) ? t : s.lastSeenInBundleAtMs;
|
|
560
|
+
t - a > mt || (i[r] = { ...s, lastSeenInBundleAtMs: a });
|
|
561
|
+
}
|
|
562
|
+
h = i, await u(o.inAppState, h);
|
|
563
|
+
}
|
|
564
|
+
async function Ke() {
|
|
565
|
+
const e = await c(o.sessionStartedAt) ?? 0;
|
|
566
|
+
v.startedAt !== e && (v = { startedAt: e, counts: {} }, await u(o.inAppSession, v));
|
|
567
|
+
}
|
|
568
|
+
function D(e) {
|
|
569
|
+
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
570
|
+
}
|
|
571
|
+
function m(e) {
|
|
572
|
+
return typeof e == "string" && e.length > 0 ? e : void 0;
|
|
573
|
+
}
|
|
574
|
+
function O(e) {
|
|
575
|
+
return typeof e == "number" && Number.isFinite(e) ? e : void 0;
|
|
576
|
+
}
|
|
577
|
+
function $t(e) {
|
|
578
|
+
if (typeof e != "string") return null;
|
|
579
|
+
const t = Date.parse(e);
|
|
580
|
+
return Number.isNaN(t) ? null : t;
|
|
581
|
+
}
|
|
582
|
+
const Lt = -1, Kt = 304, Vt = 2147483e3, re = 44, Ne = /^#[0-9a-fA-F]{3,8}$/, Ft = 0.6;
|
|
583
|
+
let xe = null, Wt = 0;
|
|
584
|
+
function Xt(e, t, n) {
|
|
585
|
+
const i = e.layout === "MODAL", r = Date.now(), s = `arsel-iam-${Wt += 1}`, a = document.createElement("div");
|
|
586
|
+
a.setAttribute("data-arsel-inapp", "");
|
|
587
|
+
const l = a.attachShadow({ mode: "closed" });
|
|
588
|
+
tn(l), a.style.setProperty("z-index", String(t.zIndex || Vt)), a.style.setProperty("isolation", "isolate"), a.setAttribute("data-layout", e.layout), a.setAttribute("dir", Zt());
|
|
589
|
+
const w = document.activeElement instanceof HTMLElement ? document.activeElement : null, f = document.createElement("div");
|
|
590
|
+
f.className = "panel", f.tabIndex = -1, i ? (f.setAttribute("role", "dialog"), f.setAttribute("aria-modal", "true"), f.setAttribute("aria-labelledby", `${s}-h`), e.content.body && f.setAttribute("aria-describedby", `${s}-b`)) : (f.setAttribute("role", "status"), f.setAttribute("aria-live", "polite"));
|
|
591
|
+
const A = Qt(e);
|
|
592
|
+
A.background && f.style.setProperty("background", A.background), A.text && f.style.setProperty("color", A.text);
|
|
593
|
+
let C = !1;
|
|
594
|
+
const E = (p) => {
|
|
595
|
+
var g, we;
|
|
596
|
+
C || (C = !0, document.removeEventListener("keydown", T, !0), a.remove(), w != null && w.isConnected ? w.focus() : i && ((we = (g = document.body).focus) == null || we.call(g)), p === "dismiss" && n.onDismiss((Date.now() - r) / 1e3));
|
|
597
|
+
}, T = (p) => {
|
|
598
|
+
p.key === "Escape" && (p.stopPropagation(), E("dismiss"));
|
|
599
|
+
};
|
|
600
|
+
if (e.layout === "IMAGE_ONLY" && e.content.imageUrl)
|
|
601
|
+
f.append(zt(e, () => qe(e)));
|
|
602
|
+
else {
|
|
603
|
+
e.content.imageUrl && f.append(jt(e.content.imageUrl, e.content.headline));
|
|
604
|
+
const p = document.createElement("h2");
|
|
605
|
+
if (p.id = `${s}-h`, p.className = "headline", p.textContent = e.content.headline, f.append(p), e.content.body) {
|
|
606
|
+
const g = document.createElement("p");
|
|
607
|
+
g.id = `${s}-b`, g.className = "body", g.textContent = e.content.body, f.append(g);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
if (e.buttons.length > 0 && f.append(Ht(e, n, E)), (e.content.showCloseButton || !e.buttons.some((p) => p.action === "DISMISS")) && f.append(Jt(t.closeLabel, () => E("dismiss"))), i) {
|
|
611
|
+
const p = document.createElement("div");
|
|
612
|
+
p.className = "backdrop", e.content.showCloseButton && p.addEventListener("click", () => E("dismiss")), l.append(p);
|
|
613
|
+
}
|
|
614
|
+
l.append(f), document.body.append(a), i ? (f.focus({ preventScroll: !0 }), l.addEventListener("keydown", (p) => {
|
|
615
|
+
p instanceof KeyboardEvent && Gt(p, l);
|
|
616
|
+
})) : (f.textContent, f.setAttribute("aria-busy", "true"), requestAnimationFrame(() => {
|
|
617
|
+
f.removeAttribute("aria-busy");
|
|
618
|
+
})), document.addEventListener("keydown", T, !0), requestAnimationFrame(() => {
|
|
619
|
+
C || !a.isConnected || document.visibilityState === "visible" && n.onImpression();
|
|
620
|
+
});
|
|
621
|
+
function qe(p) {
|
|
622
|
+
const g = p.buttons[0];
|
|
623
|
+
if (!g) {
|
|
624
|
+
E("dismiss");
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
n.onButton(g), E("button");
|
|
628
|
+
}
|
|
629
|
+
return { close: E, root: l };
|
|
630
|
+
}
|
|
631
|
+
function jt(e, t) {
|
|
632
|
+
const n = document.createElement("figure");
|
|
633
|
+
n.className = "figure";
|
|
634
|
+
const i = document.createElement("img");
|
|
635
|
+
return i.src = e, i.alt = t, i.loading = "eager", i.decoding = "async", i.referrerPolicy = "no-referrer", i.addEventListener("error", () => n.remove()), n.append(i), n;
|
|
636
|
+
}
|
|
637
|
+
function zt(e, t) {
|
|
638
|
+
const n = document.createElement("button");
|
|
639
|
+
n.type = "button", n.className = "image-only";
|
|
640
|
+
const i = document.createElement("img");
|
|
641
|
+
return i.src = e.content.imageUrl ?? "", i.alt = e.content.headline, i.loading = "eager", i.decoding = "async", i.referrerPolicy = "no-referrer", n.append(i), n.addEventListener("click", t), n;
|
|
642
|
+
}
|
|
643
|
+
function Ht(e, t, n) {
|
|
644
|
+
const i = document.createElement("div");
|
|
645
|
+
i.className = "buttons";
|
|
646
|
+
for (const r of e.buttons) {
|
|
647
|
+
const s = r.action === "URL" && r.value ? qt(r) : Yt(r);
|
|
648
|
+
s.addEventListener("click", () => {
|
|
649
|
+
r.action !== "DISMISS" && t.onButton(r), n(r.action === "DISMISS" ? "dismiss" : "button"), r.action === "DEEP_LINK" && r.value && location.assign(r.value);
|
|
650
|
+
}), i.append(s);
|
|
651
|
+
}
|
|
652
|
+
return i;
|
|
653
|
+
}
|
|
654
|
+
function qt(e) {
|
|
655
|
+
const t = document.createElement("a");
|
|
656
|
+
return t.href = e.value ?? "#", t.target = "_blank", t.rel = "noopener noreferrer", t.className = `cta ${e.style.toLowerCase()}`, t.textContent = e.label, t;
|
|
657
|
+
}
|
|
658
|
+
function Yt(e) {
|
|
659
|
+
const t = document.createElement("button");
|
|
660
|
+
return t.type = "button", t.className = `cta ${e.style.toLowerCase()}`, t.textContent = e.label, t;
|
|
661
|
+
}
|
|
662
|
+
function Jt(e, t) {
|
|
663
|
+
const n = document.createElement("button");
|
|
664
|
+
return n.type = "button", n.className = "close", n.setAttribute("aria-label", e), n.textContent = "×", n.addEventListener("click", t), n;
|
|
665
|
+
}
|
|
666
|
+
function Gt(e, t) {
|
|
667
|
+
if (e.key !== "Tab") return;
|
|
668
|
+
const n = [
|
|
669
|
+
...t.querySelectorAll("button, a[href]")
|
|
670
|
+
].filter((a) => !a.hasAttribute("disabled"));
|
|
671
|
+
if (n.length === 0) return;
|
|
672
|
+
const i = n[0], r = n[n.length - 1];
|
|
673
|
+
if (!i || !r) return;
|
|
674
|
+
const s = t.activeElement;
|
|
675
|
+
if (e.shiftKey && s === i) {
|
|
676
|
+
e.preventDefault(), r.focus();
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
!e.shiftKey && s === r && (e.preventDefault(), i.focus());
|
|
680
|
+
}
|
|
681
|
+
function Zt() {
|
|
682
|
+
const e = document.documentElement.getAttribute("dir");
|
|
683
|
+
if (e) return e;
|
|
684
|
+
try {
|
|
685
|
+
return getComputedStyle(document.documentElement).direction || "ltr";
|
|
686
|
+
} catch {
|
|
687
|
+
return "ltr";
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
function Qt(e) {
|
|
691
|
+
const t = Ne.test(e.content.backgroundColor ?? "") ? e.content.backgroundColor : void 0, n = Ne.test(e.content.textColor ?? "") ? e.content.textColor : void 0;
|
|
692
|
+
return t && !n ? { background: t, text: en(t) > Ft ? "#101010" : "#FFFFFF" } : { background: t, text: n };
|
|
693
|
+
}
|
|
694
|
+
function en(e) {
|
|
695
|
+
const t = e.slice(1), n = t.length === 3 ? t.split("").map((a) => a + a).join("") : t.slice(0, 6), i = parseInt(n.slice(0, 2), 16) / 255, r = parseInt(n.slice(2, 4), 16) / 255, s = parseInt(n.slice(4, 6), 16) / 255;
|
|
696
|
+
return 0.2126 * i + 0.7152 * r + 0.0722 * s;
|
|
697
|
+
}
|
|
698
|
+
function tn(e) {
|
|
699
|
+
if ("adoptedStyleSheets" in Document.prototype && typeof CSSStyleSheet == "function")
|
|
700
|
+
try {
|
|
701
|
+
xe ?? (xe = nn()), e.adoptedStyleSheets = [xe];
|
|
702
|
+
return;
|
|
703
|
+
} catch {
|
|
704
|
+
}
|
|
705
|
+
const t = document.createElement("style");
|
|
706
|
+
t.textContent = Ve, e.append(t);
|
|
707
|
+
}
|
|
708
|
+
function nn() {
|
|
709
|
+
const e = new CSSStyleSheet();
|
|
710
|
+
return e.replaceSync(Ve), e;
|
|
711
|
+
}
|
|
712
|
+
const Ve = `
|
|
713
|
+
:host {
|
|
714
|
+
all: initial;
|
|
715
|
+
display: block;
|
|
716
|
+
position: fixed;
|
|
717
|
+
inset: 0;
|
|
718
|
+
pointer-events: none;
|
|
719
|
+
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
720
|
+
line-height: 1.5;
|
|
721
|
+
color: #101010;
|
|
722
|
+
}
|
|
723
|
+
.backdrop {
|
|
724
|
+
position: fixed;
|
|
725
|
+
inset: 0;
|
|
726
|
+
background: rgba(0, 0, 0, 0.45);
|
|
727
|
+
pointer-events: auto;
|
|
728
|
+
}
|
|
729
|
+
.panel {
|
|
730
|
+
position: fixed;
|
|
731
|
+
box-sizing: border-box;
|
|
732
|
+
pointer-events: auto;
|
|
733
|
+
background: #ffffff;
|
|
734
|
+
border-radius: 12px;
|
|
735
|
+
padding: 20px;
|
|
736
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
|
737
|
+
max-height: calc(100vh - 32px);
|
|
738
|
+
overflow-y: auto;
|
|
739
|
+
}
|
|
740
|
+
:host([data-layout="MODAL"]) .panel {
|
|
741
|
+
inset-inline-start: 50%;
|
|
742
|
+
top: 50%;
|
|
743
|
+
transform: translate(-50%, -50%);
|
|
744
|
+
width: min(calc(100vw - 32px), 420px);
|
|
745
|
+
}
|
|
746
|
+
:host([dir="rtl"][data-layout="MODAL"]) .panel {
|
|
747
|
+
transform: translate(50%, -50%);
|
|
748
|
+
}
|
|
749
|
+
:host([data-layout="BANNER_TOP"]) .panel,
|
|
750
|
+
:host([data-layout="BANNER_BOTTOM"]) .panel {
|
|
751
|
+
inset-inline: 16px;
|
|
752
|
+
margin-inline: auto;
|
|
753
|
+
max-width: min(calc(100vw - 32px), 560px);
|
|
754
|
+
}
|
|
755
|
+
:host([data-layout="BANNER_TOP"]) .panel {
|
|
756
|
+
top: 16px;
|
|
757
|
+
padding-top: calc(20px + env(safe-area-inset-top));
|
|
758
|
+
}
|
|
759
|
+
:host([data-layout="BANNER_BOTTOM"]) .panel {
|
|
760
|
+
bottom: 16px;
|
|
761
|
+
padding-bottom: calc(20px + env(safe-area-inset-bottom));
|
|
762
|
+
}
|
|
763
|
+
:host([data-layout="IMAGE_ONLY"]) .panel {
|
|
764
|
+
inset-inline-start: 50%;
|
|
765
|
+
top: 50%;
|
|
766
|
+
transform: translate(-50%, -50%);
|
|
767
|
+
padding: 0;
|
|
768
|
+
background: transparent;
|
|
769
|
+
box-shadow: none;
|
|
770
|
+
}
|
|
771
|
+
.figure { margin: 0 0 12px; }
|
|
772
|
+
.figure img, .image-only img {
|
|
773
|
+
display: block;
|
|
774
|
+
width: 100%;
|
|
775
|
+
height: auto;
|
|
776
|
+
border-radius: 8px;
|
|
777
|
+
}
|
|
778
|
+
.image-only {
|
|
779
|
+
display: block;
|
|
780
|
+
padding: 0;
|
|
781
|
+
border: 0;
|
|
782
|
+
background: none;
|
|
783
|
+
cursor: pointer;
|
|
784
|
+
width: min(calc(100vw - 32px), 420px);
|
|
785
|
+
}
|
|
786
|
+
.headline { margin: 0 0 8px; font-size: 18px; font-weight: 600; }
|
|
787
|
+
.body { margin: 0 0 16px; font-size: 15px; }
|
|
788
|
+
.buttons { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
789
|
+
.cta {
|
|
790
|
+
flex: 1 1 auto;
|
|
791
|
+
min-height: ${re}px;
|
|
792
|
+
padding: 10px 16px;
|
|
793
|
+
border-radius: 8px;
|
|
794
|
+
border: 1px solid currentColor;
|
|
795
|
+
font: inherit;
|
|
796
|
+
cursor: pointer;
|
|
797
|
+
text-align: center;
|
|
798
|
+
text-decoration: none;
|
|
799
|
+
}
|
|
800
|
+
.cta.primary { background: #101010; color: #ffffff; border-color: #101010; }
|
|
801
|
+
.cta.secondary { background: transparent; color: inherit; }
|
|
802
|
+
.close {
|
|
803
|
+
position: absolute;
|
|
804
|
+
top: 4px;
|
|
805
|
+
inset-inline-end: 4px;
|
|
806
|
+
min-width: ${re}px;
|
|
807
|
+
min-height: ${re}px;
|
|
808
|
+
border: 0;
|
|
809
|
+
background: none;
|
|
810
|
+
color: inherit;
|
|
811
|
+
font-size: 22px;
|
|
812
|
+
line-height: 1;
|
|
813
|
+
cursor: pointer;
|
|
814
|
+
}
|
|
815
|
+
@media (prefers-reduced-motion: reduce) {
|
|
816
|
+
.panel { animation: none; transition: none; }
|
|
817
|
+
}
|
|
818
|
+
`;
|
|
819
|
+
async function rn(e) {
|
|
820
|
+
await c(o.installReported) || (await u(o.installReported, !0), !e && await k(it, {
|
|
821
|
+
sdk_version: j,
|
|
822
|
+
platform: "web"
|
|
823
|
+
}));
|
|
824
|
+
}
|
|
825
|
+
async function on() {
|
|
826
|
+
const [e, t] = await Promise.all([
|
|
827
|
+
c(o.anonymousId),
|
|
828
|
+
c(o.installationId)
|
|
829
|
+
]);
|
|
830
|
+
return !!e || !!t;
|
|
831
|
+
}
|
|
832
|
+
const me = "REVOKED";
|
|
833
|
+
function sn(e) {
|
|
232
834
|
const t = e.replace(/-/g, "+").replace(/_/g, "/"), n = atob(t + "=".repeat((4 - t.length % 4) % 4)), i = new Uint8Array(n.length);
|
|
233
|
-
for (let
|
|
835
|
+
for (let r = 0; r < n.length; r += 1) i[r] = n.charCodeAt(r);
|
|
234
836
|
return i.buffer;
|
|
235
837
|
}
|
|
236
|
-
function
|
|
838
|
+
function B() {
|
|
237
839
|
return typeof navigator < "u" && "serviceWorker" in navigator && typeof PushManager < "u" && typeof Notification < "u";
|
|
238
840
|
}
|
|
239
|
-
function
|
|
841
|
+
function Fe(e) {
|
|
240
842
|
return `/api/v1/orgs/${e}/push/web/config`;
|
|
241
843
|
}
|
|
242
|
-
function
|
|
844
|
+
function ye(e) {
|
|
243
845
|
return `/api/v1/orgs/${e}/push/subscriptions`;
|
|
244
846
|
}
|
|
245
|
-
const
|
|
246
|
-
let
|
|
247
|
-
function
|
|
248
|
-
|
|
847
|
+
const We = 1e4;
|
|
848
|
+
let M = "none", W = null, Z = null;
|
|
849
|
+
function an() {
|
|
850
|
+
M = "external";
|
|
249
851
|
}
|
|
250
|
-
async function
|
|
251
|
-
if (
|
|
252
|
-
|
|
852
|
+
async function cn(e) {
|
|
853
|
+
if (B()) {
|
|
854
|
+
M = "managed";
|
|
253
855
|
try {
|
|
254
|
-
|
|
856
|
+
W = await navigator.serviceWorker.register(e), Z = null;
|
|
255
857
|
} catch (t) {
|
|
256
|
-
|
|
858
|
+
W = null, Z = `service worker registration failed for '${e}': ${String(t)}. Check that the file is deployed and served with a JavaScript content type.`;
|
|
257
859
|
}
|
|
258
860
|
}
|
|
259
861
|
}
|
|
260
|
-
function
|
|
862
|
+
function ln(e, t) {
|
|
261
863
|
return e.active ? Promise.resolve(e) : new Promise((n, i) => {
|
|
262
|
-
const
|
|
864
|
+
const r = setTimeout(() => {
|
|
263
865
|
i(
|
|
264
866
|
new Error(
|
|
265
867
|
`service worker did not activate within ${t}ms — check the worker script for load errors in DevTools → Application → Service Workers`
|
|
266
868
|
)
|
|
267
869
|
);
|
|
268
|
-
}, t),
|
|
870
|
+
}, t), s = (l) => {
|
|
269
871
|
l.addEventListener("statechange", () => {
|
|
270
|
-
l.state === "activated" ? (clearTimeout(
|
|
872
|
+
l.state === "activated" ? (clearTimeout(r), n(e)) : l.state === "redundant" && (clearTimeout(r), i(
|
|
271
873
|
new Error(
|
|
272
874
|
"service worker became redundant before activating — its script likely failed to parse"
|
|
273
875
|
)
|
|
274
876
|
));
|
|
275
877
|
});
|
|
276
|
-
},
|
|
277
|
-
|
|
278
|
-
e.installing &&
|
|
878
|
+
}, a = e.installing ?? e.waiting;
|
|
879
|
+
a ? s(a) : e.addEventListener("updatefound", () => {
|
|
880
|
+
e.installing && s(e.installing);
|
|
279
881
|
});
|
|
280
882
|
});
|
|
281
883
|
}
|
|
282
|
-
function
|
|
884
|
+
function un(e, t, n) {
|
|
283
885
|
return Promise.race([
|
|
284
886
|
e,
|
|
285
|
-
new Promise((i,
|
|
286
|
-
setTimeout(() =>
|
|
887
|
+
new Promise((i, r) => {
|
|
888
|
+
setTimeout(() => r(new Error(n)), t);
|
|
287
889
|
})
|
|
288
890
|
]);
|
|
289
891
|
}
|
|
290
|
-
async function
|
|
291
|
-
if (
|
|
892
|
+
async function be(e = We) {
|
|
893
|
+
if (M === "none")
|
|
292
894
|
throw new Error(
|
|
293
895
|
"push is not configured — pass serviceWorkerPath to init(), or serviceWorker: 'external' if your own service worker imports arsel-sw.js"
|
|
294
896
|
);
|
|
295
|
-
if (
|
|
296
|
-
return
|
|
897
|
+
if (M === "external")
|
|
898
|
+
return un(
|
|
297
899
|
navigator.serviceWorker.ready,
|
|
298
900
|
e,
|
|
299
901
|
`no service worker became active within ${e}ms — with serviceWorker: 'external', your own worker must be registered and must importScripts arsel-sw.js`
|
|
300
902
|
);
|
|
301
|
-
if (
|
|
302
|
-
if (!
|
|
903
|
+
if (Z) throw new Error(Z);
|
|
904
|
+
if (!W)
|
|
303
905
|
throw new Error("service worker registration has not completed");
|
|
304
|
-
return
|
|
906
|
+
return ln(W, e);
|
|
305
907
|
}
|
|
306
|
-
async function
|
|
908
|
+
async function dn(e = We) {
|
|
307
909
|
try {
|
|
308
|
-
return await
|
|
910
|
+
return await be(e), null;
|
|
309
911
|
} catch (t) {
|
|
310
912
|
return t instanceof Error ? t.message : String(t);
|
|
311
913
|
}
|
|
312
914
|
}
|
|
313
|
-
async function
|
|
915
|
+
async function Xe(e, t) {
|
|
916
|
+
try {
|
|
917
|
+
return await e.pushManager.subscribe({
|
|
918
|
+
// Non-negotiable: the Push API only accepts a userVisibleOnly subscription
|
|
919
|
+
// in Chrome, and silent push is what the restriction exists to prevent.
|
|
920
|
+
userVisibleOnly: !0,
|
|
921
|
+
applicationServerKey: sn(t)
|
|
922
|
+
});
|
|
923
|
+
} catch (n) {
|
|
924
|
+
return console.error(
|
|
925
|
+
`[arsel] push subscribe failed: ${n instanceof Error ? n.message : n}`
|
|
926
|
+
), null;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
async function fn() {
|
|
314
930
|
const [e, t] = await Promise.all([
|
|
315
|
-
c(
|
|
316
|
-
c(
|
|
931
|
+
c(o.clientKey),
|
|
932
|
+
c(o.baseUrl)
|
|
317
933
|
]);
|
|
318
|
-
if (!e || !t || !
|
|
319
|
-
const n = await
|
|
934
|
+
if (!e || !t || !B()) return !1;
|
|
935
|
+
const { body: n } = await de(
|
|
936
|
+
t,
|
|
937
|
+
Fe(e)
|
|
938
|
+
);
|
|
320
939
|
if (!(n != null && n.vapidPublicKey)) return !1;
|
|
321
940
|
let i;
|
|
322
941
|
try {
|
|
323
|
-
i = await
|
|
324
|
-
} catch (
|
|
325
|
-
return console.error(`[arsel] ${
|
|
326
|
-
}
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
var _;
|
|
337
|
-
const [n, i, s] = await Promise.all([
|
|
338
|
-
c(r.clientKey),
|
|
339
|
-
c(r.baseUrl),
|
|
340
|
-
T()
|
|
942
|
+
i = await be();
|
|
943
|
+
} catch (s) {
|
|
944
|
+
return console.error(`[arsel] ${s instanceof Error ? s.message : s}`), !1;
|
|
945
|
+
}
|
|
946
|
+
const r = await Xe(i, n.vapidPublicKey);
|
|
947
|
+
return r ? je(r, n.keyVersion) : !1;
|
|
948
|
+
}
|
|
949
|
+
async function je(e, t) {
|
|
950
|
+
var f, A;
|
|
951
|
+
const [n, i, r] = await Promise.all([
|
|
952
|
+
c(o.clientKey),
|
|
953
|
+
c(o.baseUrl),
|
|
954
|
+
X()
|
|
341
955
|
]);
|
|
342
956
|
if (!n || !i) return !1;
|
|
343
|
-
let
|
|
344
|
-
|
|
345
|
-
const
|
|
957
|
+
let s = await c(o.installationId);
|
|
958
|
+
s || (s = crypto.randomUUID(), await u(o.installationId, s));
|
|
959
|
+
const a = e.toJSON(), l = await z(
|
|
346
960
|
i,
|
|
347
|
-
|
|
961
|
+
ye(n),
|
|
348
962
|
{
|
|
349
|
-
installationId:
|
|
963
|
+
installationId: s,
|
|
350
964
|
platform: "web",
|
|
351
|
-
endpoint:
|
|
352
|
-
keys:
|
|
965
|
+
endpoint: a.endpoint,
|
|
966
|
+
keys: a.keys,
|
|
353
967
|
// The same id the events API sends — it is what binds this subscription
|
|
354
968
|
// to the contact the browser's events resolve to.
|
|
355
|
-
anonymousId:
|
|
969
|
+
anonymousId: r,
|
|
356
970
|
enablementStatus: Notification.permission === "granted" ? "AUTHORIZED" : "DENIED",
|
|
357
971
|
deviceTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
358
972
|
deviceLocale: navigator.language
|
|
359
973
|
}
|
|
360
974
|
);
|
|
361
|
-
|
|
975
|
+
if (l.result !== y.success) return !1;
|
|
976
|
+
(f = l.body) != null && f.deviceSecret && await u(o.deviceSecret, l.body.deviceSecret), await u(o.vapidKeyVersion, t), await u(o.endpoint, a.endpoint ?? null);
|
|
977
|
+
const w = ((A = l.body) == null ? void 0 : A.status) ?? null;
|
|
978
|
+
return await u(o.subscriptionStatus, w), w !== me;
|
|
362
979
|
}
|
|
363
|
-
async function
|
|
980
|
+
async function pn() {
|
|
364
981
|
const [e, t, n, i] = await Promise.all([
|
|
365
|
-
c(
|
|
366
|
-
c(
|
|
367
|
-
c(
|
|
368
|
-
c(
|
|
982
|
+
c(o.clientKey),
|
|
983
|
+
c(o.baseUrl),
|
|
984
|
+
c(o.installationId),
|
|
985
|
+
c(o.deviceSecret)
|
|
369
986
|
]);
|
|
370
|
-
return !e || !t || !n || !i
|
|
987
|
+
return !e || !t || !n || !i || (await z(
|
|
371
988
|
t,
|
|
372
|
-
`${
|
|
989
|
+
`${ye(e)}/unsubscribe`,
|
|
373
990
|
{ installationId: n },
|
|
374
991
|
{ "X-Arsel-Device-Auth": i },
|
|
375
992
|
!0
|
|
376
|
-
)).result
|
|
993
|
+
)).result !== y.success ? !1 : (await u(o.subscriptionStatus, me), !0);
|
|
377
994
|
}
|
|
378
|
-
async function
|
|
379
|
-
if (
|
|
995
|
+
async function mn() {
|
|
996
|
+
if (M === "none" || !B() || Notification.permission !== "granted") return;
|
|
380
997
|
const [e, t] = await Promise.all([
|
|
381
|
-
c(
|
|
382
|
-
c(
|
|
998
|
+
c(o.clientKey),
|
|
999
|
+
c(o.baseUrl)
|
|
383
1000
|
]);
|
|
384
1001
|
if (!e || !t) return;
|
|
385
|
-
const n = await
|
|
1002
|
+
const { body: n } = await de(
|
|
1003
|
+
t,
|
|
1004
|
+
Fe(e)
|
|
1005
|
+
);
|
|
386
1006
|
if (!(n != null && n.vapidPublicKey)) return;
|
|
387
1007
|
let i;
|
|
388
1008
|
try {
|
|
389
|
-
i = await
|
|
1009
|
+
i = await be();
|
|
390
1010
|
} catch {
|
|
391
1011
|
return;
|
|
392
1012
|
}
|
|
393
|
-
const
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
applicationServerKey: C(n.vapidPublicKey)
|
|
399
|
-
});
|
|
400
|
-
await L(o, n.keyVersion);
|
|
1013
|
+
const r = await i.pushManager.getSubscription(), s = await c(o.vapidKeyVersion);
|
|
1014
|
+
if (r && s === n.keyVersion) return;
|
|
1015
|
+
r && await r.unsubscribe().catch(() => !1);
|
|
1016
|
+
const a = await Xe(i, n.vapidPublicKey);
|
|
1017
|
+
a && await je(a, n.keyVersion);
|
|
401
1018
|
}
|
|
402
|
-
async function
|
|
403
|
-
if (!
|
|
1019
|
+
async function yn() {
|
|
1020
|
+
if (!B() || await c(o.subscriptionStatus) === me)
|
|
1021
|
+
return !1;
|
|
404
1022
|
try {
|
|
405
|
-
const e =
|
|
1023
|
+
const e = M === "managed" ? W : await navigator.serviceWorker.getRegistration();
|
|
406
1024
|
return e ? await e.pushManager.getSubscription() !== null : !1;
|
|
407
1025
|
} catch {
|
|
408
1026
|
return !1;
|
|
409
1027
|
}
|
|
410
1028
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
1029
|
+
function bn() {
|
|
1030
|
+
return oe ?? (oe = hn().finally(() => {
|
|
1031
|
+
oe = null;
|
|
1032
|
+
})), oe;
|
|
1033
|
+
}
|
|
1034
|
+
let oe = null;
|
|
1035
|
+
async function hn() {
|
|
1036
|
+
var s;
|
|
1037
|
+
const [e, t, n] = await Promise.all([
|
|
1038
|
+
c(o.clientKey),
|
|
1039
|
+
c(o.baseUrl),
|
|
1040
|
+
X()
|
|
1041
|
+
]);
|
|
1042
|
+
if (!e || !t) return !1;
|
|
1043
|
+
if (await c(o.deviceSecret)) return !0;
|
|
1044
|
+
let i = await c(o.installationId);
|
|
1045
|
+
i || (i = crypto.randomUUID(), await u(o.installationId, i));
|
|
1046
|
+
const r = await z(
|
|
1047
|
+
t,
|
|
1048
|
+
ye(e),
|
|
1049
|
+
{
|
|
1050
|
+
installationId: i,
|
|
1051
|
+
platform: "web",
|
|
1052
|
+
anonymousId: n,
|
|
1053
|
+
// Truthful: no prompt has been shown. Reporting DENIED would mark the
|
|
1054
|
+
// device unreachable for push it was never asked about.
|
|
1055
|
+
enablementStatus: "NOT_DETERMINED",
|
|
1056
|
+
deviceTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
1057
|
+
deviceLocale: navigator.language
|
|
1058
|
+
}
|
|
1059
|
+
);
|
|
1060
|
+
return r.code === 403 ? (console.error(
|
|
1061
|
+
"[arsel] this origin is not on the organization's allowed origins list — in-app messaging is disabled"
|
|
1062
|
+
), !1) : r.result !== y.success ? !1 : ((s = r.body) != null && s.deviceSecret && await u(o.deviceSecret, r.body.deviceSecret), !0);
|
|
1063
|
+
}
|
|
1064
|
+
const wn = 30 * 6e4;
|
|
1065
|
+
async function ze(e = Date.now()) {
|
|
1066
|
+
const t = await c(o.sessionStartedAt) ?? 0, n = await c(o.backgroundedAt) ?? 0;
|
|
414
1067
|
if (t !== 0) {
|
|
415
|
-
if (n === 0 || e - n <
|
|
416
|
-
await
|
|
417
|
-
|
|
1068
|
+
if (n === 0 || e - n < wn) return;
|
|
1069
|
+
await k(
|
|
1070
|
+
tt,
|
|
418
1071
|
{ duration_seconds: Math.round((n - t) / 1e3) },
|
|
419
1072
|
n
|
|
420
1073
|
);
|
|
421
1074
|
}
|
|
422
|
-
await u(
|
|
1075
|
+
await u(o.sessionStartedAt, e), await u(o.backgroundedAt, 0), await k(et, {}, e);
|
|
423
1076
|
}
|
|
424
|
-
async function
|
|
425
|
-
(await c(
|
|
1077
|
+
async function ke(e = Date.now()) {
|
|
1078
|
+
(await c(o.sessionStartedAt) ?? 0) !== 0 && await u(o.backgroundedAt, e);
|
|
426
1079
|
}
|
|
427
|
-
function
|
|
1080
|
+
function gn(e) {
|
|
428
1081
|
typeof document > "u" || (document.addEventListener("visibilitychange", () => {
|
|
429
|
-
document.visibilityState === "visible" ?
|
|
430
|
-
}), window.addEventListener("pagehide", () => void
|
|
1082
|
+
document.visibilityState === "visible" ? ze().then(() => e == null ? void 0 : e()) : ke();
|
|
1083
|
+
}), window.addEventListener("pagehide", () => void ke()));
|
|
431
1084
|
}
|
|
432
|
-
let
|
|
433
|
-
function
|
|
434
|
-
|
|
1085
|
+
let b = null, ce = !1, R = null;
|
|
1086
|
+
function I(e) {
|
|
1087
|
+
ce && console.info(`[arsel] ${e}`);
|
|
435
1088
|
}
|
|
436
|
-
const
|
|
437
|
-
let
|
|
438
|
-
function
|
|
439
|
-
typeof
|
|
1089
|
+
const vn = /^\+[1-9]\d{6,14}$/, Sn = /^[^\s@]+@[^\s@]+\.[^\s@]+$/, Pe = 100;
|
|
1090
|
+
let Q = [], Te = !1;
|
|
1091
|
+
function An() {
|
|
1092
|
+
typeof navigator < "u" && navigator.serviceWorker && navigator.serviceWorker.addEventListener("message", (e) => {
|
|
1093
|
+
const t = e.data;
|
|
1094
|
+
(t == null ? void 0 : t.type) === "arsel_iam_sync" && It();
|
|
1095
|
+
}), typeof window < "u" && (window.addEventListener("online", () => {
|
|
1096
|
+
V().catch(() => {
|
|
1097
|
+
}), Y().catch(() => {
|
|
1098
|
+
});
|
|
1099
|
+
}), window.addEventListener("pagehide", () => {
|
|
1100
|
+
ae(), Y().catch(() => {
|
|
1101
|
+
});
|
|
440
1102
|
})), typeof document < "u" && document.addEventListener("visibilitychange", () => {
|
|
441
|
-
document.visibilityState === "visible"
|
|
1103
|
+
if (document.visibilityState === "visible") {
|
|
1104
|
+
V().catch(() => {
|
|
1105
|
+
}), te().catch(() => {
|
|
1106
|
+
});
|
|
1107
|
+
return;
|
|
1108
|
+
}
|
|
1109
|
+
ae(), Y().catch(() => {
|
|
442
1110
|
});
|
|
443
1111
|
});
|
|
444
1112
|
}
|
|
445
|
-
function
|
|
446
|
-
return
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
);
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
1113
|
+
function U() {
|
|
1114
|
+
return R === null;
|
|
1115
|
+
}
|
|
1116
|
+
function En(e) {
|
|
1117
|
+
var n, i;
|
|
1118
|
+
if (!((n = e.clientKey) != null && n.trim()))
|
|
1119
|
+
return "clientKey is required (the org's publishable pub_… key)";
|
|
1120
|
+
if (!e.clientKey.startsWith("pub_"))
|
|
1121
|
+
return "clientKey should be the publishable pub_… key — never a secret API key";
|
|
1122
|
+
const t = /^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?(\/|$)/.test(
|
|
1123
|
+
e.baseUrl ?? ""
|
|
1124
|
+
);
|
|
1125
|
+
if (!((i = e.baseUrl) != null && i.startsWith("https://")) && !t)
|
|
1126
|
+
return "baseUrl must be HTTPS (http is allowed for localhost only)";
|
|
1127
|
+
try {
|
|
1128
|
+
new URL(e.baseUrl);
|
|
1129
|
+
} catch {
|
|
1130
|
+
return "baseUrl is not a valid URL";
|
|
1131
|
+
}
|
|
1132
|
+
return null;
|
|
1133
|
+
}
|
|
1134
|
+
function In(e) {
|
|
1135
|
+
return b || (b = (async () => {
|
|
1136
|
+
if (ce = e.debug ?? !1, R = En(e), R) {
|
|
1137
|
+
console.error(`[arsel] not started — ${R}`);
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
const t = e.baseUrl.replace(/\/+$/, "");
|
|
456
1141
|
await Promise.all([
|
|
457
|
-
u(
|
|
458
|
-
u(
|
|
459
|
-
])
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
1142
|
+
u(o.clientKey, e.clientKey),
|
|
1143
|
+
u(o.baseUrl, t)
|
|
1144
|
+
]);
|
|
1145
|
+
const n = await on();
|
|
1146
|
+
await X(), await rn(n);
|
|
1147
|
+
const i = Q;
|
|
1148
|
+
Q = [];
|
|
1149
|
+
for (const l of i)
|
|
1150
|
+
await k(l.name, l.properties, l.timestampMs);
|
|
1151
|
+
e.serviceWorker === "external" ? an() : e.serviceWorkerPath && await cn(e.serviceWorkerPath);
|
|
1152
|
+
const r = Mn(e.inApp);
|
|
1153
|
+
gn(r ? Ie : void 0), An();
|
|
1154
|
+
const s = typeof document < "u" ? document : void 0, a = (s == null ? void 0 : s.visibilityState) === "visible" && s.prerendering !== !0;
|
|
1155
|
+
a && await ze(), r && (vt(Bn(r)), await bn() && (await gt(ce), a && Ie())), V().catch(() => {
|
|
1156
|
+
}), mn().catch(() => {
|
|
1157
|
+
}), I(`initialized (sdk ${j})`);
|
|
1158
|
+
})(), b);
|
|
1159
|
+
}
|
|
1160
|
+
async function He(e, t = {}) {
|
|
470
1161
|
const n = e == null ? void 0 : e.trim();
|
|
471
1162
|
if (!n) {
|
|
472
|
-
|
|
1163
|
+
I("track() called with a blank event name — ignoring");
|
|
473
1164
|
return;
|
|
474
1165
|
}
|
|
475
|
-
if (n.startsWith(
|
|
476
|
-
|
|
1166
|
+
if (n.startsWith(x)) {
|
|
1167
|
+
I(`'${x}' is reserved for the SDK — ignoring '${n}'`);
|
|
477
1168
|
return;
|
|
478
1169
|
}
|
|
479
|
-
if (!
|
|
480
|
-
if (
|
|
481
|
-
|
|
482
|
-
`[arsel] more than ${
|
|
1170
|
+
if (!b) {
|
|
1171
|
+
if (Q.length >= Pe) {
|
|
1172
|
+
Te || (Te = !0, console.warn(
|
|
1173
|
+
`[arsel] more than ${Pe} events tracked before init() — dropping the rest. Call init() earlier.`
|
|
483
1174
|
));
|
|
484
1175
|
return;
|
|
485
1176
|
}
|
|
486
|
-
|
|
1177
|
+
Q.push({ name: n, properties: t, timestampMs: Date.now() });
|
|
487
1178
|
return;
|
|
488
1179
|
}
|
|
489
|
-
await
|
|
1180
|
+
await b, U() && (await k(n, t), pe("CUSTOM_EVENT", n, t));
|
|
1181
|
+
}
|
|
1182
|
+
async function _n(e, t = {}) {
|
|
1183
|
+
const n = e == null ? void 0 : e.trim();
|
|
1184
|
+
if (!n) {
|
|
1185
|
+
I("screen() called with a blank name — ignoring");
|
|
1186
|
+
return;
|
|
1187
|
+
}
|
|
1188
|
+
await b, await k(rt, { ...t, screen_name: n }), pe("SCREEN_VIEW", n, t);
|
|
1189
|
+
}
|
|
1190
|
+
function Nn(e) {
|
|
1191
|
+
St(e);
|
|
490
1192
|
}
|
|
491
|
-
async function
|
|
492
|
-
await
|
|
1193
|
+
async function xn(e) {
|
|
1194
|
+
if (await b, !U()) return;
|
|
493
1195
|
let { email: t, phoneNumber: n } = e ?? {};
|
|
494
1196
|
const i = e == null ? void 0 : e.externalId;
|
|
495
|
-
if (t && !
|
|
1197
|
+
if (t && !Sn.test(t) && (console.error(`[arsel] identify(): '${t}' is not a valid email address — ignored`), t = void 0), n && !vn.test(n) && (console.error(
|
|
496
1198
|
`[arsel] identify(): '${n}' is not E.164 (e.g. +966501234567) — ignored`
|
|
497
1199
|
), n = void 0), !i && !t && !n) {
|
|
498
|
-
|
|
1200
|
+
I("identify() needs at least one of externalId, email or phoneNumber");
|
|
499
1201
|
return;
|
|
500
1202
|
}
|
|
501
|
-
i && await u(
|
|
1203
|
+
i && await u(o.externalId, i), t && await u(o.email, t), n && await u(o.phoneNumber, n), await k(nt, {}), await Ce();
|
|
502
1204
|
}
|
|
503
|
-
async function
|
|
504
|
-
await
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
]), await
|
|
1205
|
+
async function kn() {
|
|
1206
|
+
await b, U() && (await Promise.all([
|
|
1207
|
+
L(o.externalId),
|
|
1208
|
+
L(o.email),
|
|
1209
|
+
L(o.phoneNumber),
|
|
1210
|
+
L(o.sessionStartedAt)
|
|
1211
|
+
]), await Ze(), await Ce(), I("identity reset"));
|
|
510
1212
|
}
|
|
511
|
-
async function
|
|
512
|
-
await
|
|
513
|
-
const e = await
|
|
514
|
-
return
|
|
1213
|
+
async function Pn() {
|
|
1214
|
+
if (await b, !U()) return !1;
|
|
1215
|
+
const e = await pn();
|
|
1216
|
+
return I(e ? "push opt-out recorded" : "push opt-out not sent — no registration to revoke"), e;
|
|
515
1217
|
}
|
|
516
|
-
async function
|
|
517
|
-
if (await
|
|
518
|
-
const e = await
|
|
1218
|
+
async function Tn() {
|
|
1219
|
+
if (await b, !U() || !B()) return !1;
|
|
1220
|
+
const e = await dn();
|
|
519
1221
|
if (e)
|
|
520
1222
|
return console.error(`[arsel] promptForPush(): ${e}`), !1;
|
|
521
1223
|
const t = await Notification.requestPermission();
|
|
522
|
-
return t !== "granted" ? (
|
|
1224
|
+
return t !== "granted" ? (I(`notification permission: ${t}`), !1) : fn();
|
|
523
1225
|
}
|
|
524
|
-
async function
|
|
525
|
-
return await
|
|
1226
|
+
async function Dn() {
|
|
1227
|
+
return await b, X();
|
|
526
1228
|
}
|
|
527
|
-
async function
|
|
1229
|
+
async function On() {
|
|
528
1230
|
const [
|
|
529
1231
|
e,
|
|
530
1232
|
t,
|
|
531
1233
|
n,
|
|
532
1234
|
i,
|
|
1235
|
+
r,
|
|
533
1236
|
s,
|
|
534
1237
|
a,
|
|
535
|
-
o,
|
|
536
1238
|
l,
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
1239
|
+
w,
|
|
1240
|
+
f,
|
|
1241
|
+
A,
|
|
1242
|
+
C,
|
|
1243
|
+
E
|
|
541
1244
|
] = await Promise.all([
|
|
542
|
-
c(
|
|
543
|
-
c(
|
|
544
|
-
c(
|
|
545
|
-
c(
|
|
546
|
-
c(
|
|
547
|
-
c(
|
|
548
|
-
c(
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
c(
|
|
552
|
-
c(
|
|
553
|
-
c(
|
|
554
|
-
|
|
1245
|
+
c(o.anonymousId),
|
|
1246
|
+
c(o.externalId),
|
|
1247
|
+
c(o.email),
|
|
1248
|
+
c(o.phoneNumber),
|
|
1249
|
+
c(o.installationId),
|
|
1250
|
+
c(o.deviceSecret),
|
|
1251
|
+
c(o.vapidKeyVersion),
|
|
1252
|
+
Oe(S.events),
|
|
1253
|
+
yn(),
|
|
1254
|
+
c(o.subscriptionStatus),
|
|
1255
|
+
c(o.lastResponseCode),
|
|
1256
|
+
c(o.lastResponsePath),
|
|
1257
|
+
c(o.lastResponseAtMs)
|
|
1258
|
+
]), T = At(), he = await Et().catch(() => 0);
|
|
555
1259
|
return {
|
|
556
|
-
sdkVersion:
|
|
557
|
-
initialized:
|
|
1260
|
+
sdkVersion: j,
|
|
1261
|
+
initialized: b !== null && R === null,
|
|
1262
|
+
configError: R,
|
|
1263
|
+
inAppMessages: T.messages,
|
|
1264
|
+
inAppBundleVersion: T.bundleVersion,
|
|
1265
|
+
inAppFetchedAtMs: T.fetchedAtMs,
|
|
1266
|
+
pendingInAppBeacons: he,
|
|
558
1267
|
anonymousId: e,
|
|
559
1268
|
hasAssertedIdentity: !!(t || n || i),
|
|
560
|
-
installationId:
|
|
561
|
-
hasDeviceSecret: !!
|
|
1269
|
+
installationId: r,
|
|
1270
|
+
hasDeviceSecret: !!s,
|
|
562
1271
|
pendingEvents: l,
|
|
563
|
-
permission:
|
|
564
|
-
isSubscribed:
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
1272
|
+
permission: B() ? Notification.permission : "unsupported",
|
|
1273
|
+
isSubscribed: w,
|
|
1274
|
+
subscriptionStatus: f,
|
|
1275
|
+
vapidKeyVersion: a,
|
|
1276
|
+
lastResponseCode: A,
|
|
1277
|
+
lastResponsePath: C,
|
|
1278
|
+
lastResponseAtMs: E
|
|
569
1279
|
};
|
|
570
1280
|
}
|
|
571
|
-
async function
|
|
572
|
-
await
|
|
573
|
-
}
|
|
574
|
-
const
|
|
575
|
-
init:
|
|
576
|
-
track:
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
1281
|
+
async function Rn() {
|
|
1282
|
+
await b, U() && await V();
|
|
1283
|
+
}
|
|
1284
|
+
const Cn = {
|
|
1285
|
+
init: In,
|
|
1286
|
+
track: He,
|
|
1287
|
+
screen: _n,
|
|
1288
|
+
suppressInAppMessages: Nn,
|
|
1289
|
+
identify: xn,
|
|
1290
|
+
reset: kn,
|
|
1291
|
+
optOut: Pn,
|
|
1292
|
+
promptForPush: Tn,
|
|
1293
|
+
getAnonymousId: Dn,
|
|
1294
|
+
diagnostics: On,
|
|
1295
|
+
flushNow: Rn,
|
|
1296
|
+
SDK_VERSION: j
|
|
585
1297
|
};
|
|
1298
|
+
function Mn(e) {
|
|
1299
|
+
if (e === !1) return;
|
|
1300
|
+
const t = typeof e == "object" && e !== null ? e : {};
|
|
1301
|
+
return {
|
|
1302
|
+
zIndex: t.zIndex ?? Un,
|
|
1303
|
+
closeLabel: t.closeLabel ?? "Close"
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
function Bn(e) {
|
|
1307
|
+
return (t) => {
|
|
1308
|
+
const n = Ot();
|
|
1309
|
+
try {
|
|
1310
|
+
Xt(t, e, {
|
|
1311
|
+
onImpression: () => void Rt(t, n),
|
|
1312
|
+
onButton: (i) => {
|
|
1313
|
+
Mt(t, i.buttonId), i.action === "CUSTOM_EVENT" && i.value && He(i.value);
|
|
1314
|
+
},
|
|
1315
|
+
onDismiss: (i) => {
|
|
1316
|
+
Bt(t, i), _e();
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
} catch (i) {
|
|
1320
|
+
I(`in-app render failed: ${i instanceof Error ? i.message : ""}`), _e();
|
|
1321
|
+
}
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
const Un = 2147483e3;
|
|
586
1325
|
export {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
1326
|
+
Cn as Arsel,
|
|
1327
|
+
j as SDK_VERSION,
|
|
1328
|
+
Cn as default,
|
|
1329
|
+
On as diagnostics,
|
|
1330
|
+
Rn as flushNow,
|
|
1331
|
+
Dn as getAnonymousId,
|
|
1332
|
+
xn as identify,
|
|
1333
|
+
In as init,
|
|
1334
|
+
Pn as optOut,
|
|
1335
|
+
Tn as promptForPush,
|
|
1336
|
+
kn as reset,
|
|
1337
|
+
_n as screen,
|
|
1338
|
+
Nn as suppressInAppMessages,
|
|
1339
|
+
He as track
|
|
599
1340
|
};
|
|
600
1341
|
//# sourceMappingURL=arsel.js.map
|