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