@webmobix/pulse-leo-sdk 0.0.1 → 0.2.1

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/dist/index.js CHANGED
@@ -1,125 +1,491 @@
1
- function o(n) {
2
- const e = "=".repeat((4 - n.length % 4) % 4), i = (n + e).replace(/-/g, "+").replace(/_/g, "/"), r = atob(i), s = new Uint8Array(r.length);
3
- for (let t = 0; t < r.length; ++t)
4
- s[t] = r.charCodeAt(t);
5
- return s;
6
- }
7
- function a(n) {
8
- const e = new Uint8Array(n);
9
- let i = "";
10
- for (let r = 0; r < e.byteLength; r++)
11
- i += String.fromCharCode(e[r]);
12
- return btoa(i).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1
+ var y = /* @__PURE__ */ ((i) => (i.PERMISSION_DENIED = "PERMISSION_DENIED", i.SUBSCRIPTION_FAILED = "SUBSCRIPTION_FAILED", i.INVALID_VAPID_KEY = "INVALID_VAPID_KEY", i.UNSUBSCRIPTION_FAILED = "UNSUBSCRIPTION_FAILED", i.BACKEND_REGISTRATION_FAILED = "BACKEND_REGISTRATION_FAILED", i.CHECKIN_CONFIG_MISSING = "CHECKIN_CONFIG_MISSING", i.NOT_SUPPORTED = "NOT_SUPPORTED", i))(y || {});
2
+ class o extends Error {
3
+ code;
4
+ constructor(e, t, r) {
5
+ super(t, r), this.name = "PushClientError", this.code = e, Object.setPrototypeOf(this, o.prototype);
6
+ }
13
7
  }
14
- class c {
15
- config;
8
+ class f extends o {
9
+ constructor(e = "Notification permission was denied", t) {
10
+ super("PERMISSION_DENIED", e, t), this.name = "PermissionDeniedError", Object.setPrototypeOf(this, f.prototype);
11
+ }
12
+ }
13
+ class u extends o {
14
+ constructor(e, t) {
15
+ super("SUBSCRIPTION_FAILED", e, t), this.name = "SubscriptionError", Object.setPrototypeOf(this, u.prototype);
16
+ }
17
+ }
18
+ class g extends o {
19
+ constructor(e, t) {
20
+ super("INVALID_VAPID_KEY", e, t), this.name = "ValidationError", Object.setPrototypeOf(this, g.prototype);
21
+ }
22
+ }
23
+ class P extends o {
24
+ constructor(e, t) {
25
+ super("UNSUBSCRIPTION_FAILED", e, t), this.name = "UnsubscriptionError", Object.setPrototypeOf(this, P.prototype);
26
+ }
27
+ }
28
+ class b extends o {
16
29
  /**
17
- * Creates an instance of PushClient.
18
- * @param config - The configuration options for the client.
30
+ * HTTP status code of the last failed relay response, or `undefined` when
31
+ * the last failure was not an HTTP response (network error, timeout).
19
32
  */
33
+ status;
34
+ constructor(e, t) {
35
+ super("BACKEND_REGISTRATION_FAILED", e, t), this.name = "BackendRegistrationError", this.status = t?.status, Object.setPrototypeOf(this, b.prototype);
36
+ }
37
+ }
38
+ class d extends o {
39
+ constructor(e = "backendCheckinUrl is required for check-in analytics", t) {
40
+ super("CHECKIN_CONFIG_MISSING", e, t), this.name = "CheckinConfigError", Object.setPrototypeOf(this, d.prototype);
41
+ }
42
+ }
43
+ class p extends o {
44
+ constructor(e = "Push notifications are not supported in this browser", t) {
45
+ super("NOT_SUPPORTED", e, t), this.name = "NotSupportedError", Object.setPrototypeOf(this, p.prototype);
46
+ }
47
+ }
48
+ function R() {
49
+ return typeof window < "u" && typeof navigator < "u" && "serviceWorker" in navigator && !!navigator.serviceWorker && "PushManager" in window && "Notification" in window;
50
+ }
51
+ const E = /^[A-Za-z0-9_-]+$/;
52
+ function N(i) {
53
+ if (!i || i.length === 0 || !E.test(i))
54
+ return !1;
55
+ const e = (4 - i.length % 4) % 4, t = i.length + e;
56
+ return !(t < 87 || t > 256);
57
+ }
58
+ function T(i) {
59
+ return !!i && i.length > 0 && E.test(i);
60
+ }
61
+ function F(i) {
62
+ if (!N(i))
63
+ throw new g(
64
+ "Invalid VAPID key format. Expected base64url-encoded string between 87 and 256 characters."
65
+ );
66
+ }
67
+ function I(i) {
68
+ if (!T(i))
69
+ throw new g(
70
+ "Invalid VAPID key format. Expected base64url-encoded string between 1 and 256 characters."
71
+ );
72
+ const e = "=".repeat((4 - i.length % 4) % 4), t = (i + e).replace(/-/g, "+").replace(/_/g, "/"), r = atob(t), n = new Uint8Array(r.length);
73
+ for (let s = 0; s < r.length; ++s)
74
+ n[s] = r.charCodeAt(s);
75
+ return n;
76
+ }
77
+ function A(i) {
78
+ const e = new Uint8Array(i);
79
+ let t = "";
80
+ for (let r = 0; r < e.byteLength; r++)
81
+ t += String.fromCharCode(e[r]);
82
+ return btoa(t).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
83
+ }
84
+ const w = "pulseleo-checkin", k = "https://pulseleo.internal/checkin-config.json", D = 360 * 60 * 1e3;
85
+ function C() {
86
+ return typeof caches < "u";
87
+ }
88
+ async function U() {
89
+ if (!C())
90
+ return null;
91
+ const e = await (await caches.open(w)).match(k);
92
+ if (!e)
93
+ return null;
94
+ try {
95
+ return await e.json();
96
+ } catch {
97
+ return null;
98
+ }
99
+ }
100
+ async function O(i) {
101
+ if (!C())
102
+ return;
103
+ await (await caches.open(w)).put(
104
+ k,
105
+ new Response(JSON.stringify(i), {
106
+ headers: { "Content-Type": "application/json" }
107
+ })
108
+ );
109
+ }
110
+ async function _() {
111
+ if (!C())
112
+ return;
113
+ await (await caches.open(w)).delete(k);
114
+ }
115
+ function K(i, e = Date.now()) {
116
+ if (!i.lastCheckinAt)
117
+ return !1;
118
+ const t = Date.parse(i.lastCheckinAt);
119
+ return Number.isNaN(t) ? !1 : e - t < D;
120
+ }
121
+ async function v(i, e = Date.now()) {
122
+ try {
123
+ return (await fetch(i.checkinUrl, {
124
+ method: "POST",
125
+ headers: { "Content-Type": "application/json" },
126
+ body: JSON.stringify({ endpoint: i.endpoint })
127
+ })).ok ? (await O({
128
+ ...i,
129
+ lastCheckinAt: new Date(e).toISOString()
130
+ }), !0) : !1;
131
+ } catch {
132
+ return !1;
133
+ }
134
+ }
135
+ async function B(i = Date.now()) {
136
+ const e = await U();
137
+ return !e || K(e, i) ? !1 : v(e, i);
138
+ }
139
+ class M {
140
+ listeners = /* @__PURE__ */ new Map();
141
+ on(e, t) {
142
+ this.listeners.has(e) || this.listeners.set(e, /* @__PURE__ */ new Set()), this.listeners.get(e).add(t);
143
+ }
144
+ off(e, t) {
145
+ const r = this.listeners.get(e);
146
+ r && r.delete(t);
147
+ }
148
+ emit(e, t) {
149
+ const r = this.listeners.get(e);
150
+ r && r.forEach((n) => n(t));
151
+ }
152
+ removeAllListeners(e) {
153
+ e ? this.listeners.delete(e) : this.listeners.clear();
154
+ }
155
+ }
156
+ async function L() {
157
+ const i = await crypto.subtle.generateKey(
158
+ {
159
+ name: "ECDSA",
160
+ namedCurve: "P-256"
161
+ },
162
+ !0,
163
+ ["sign", "verify"]
164
+ ), e = await crypto.subtle.exportKey("raw", i.publicKey), t = A(e), r = await crypto.subtle.exportKey("jwk", i.privateKey);
165
+ if (!r.d)
166
+ throw new Error("Failed to export private key");
167
+ return {
168
+ publicKey: t,
169
+ privateKey: r.d
170
+ };
171
+ }
172
+ function x(i) {
173
+ return i === void 0 ? !0 : i === 408 || i === 425 || i === 429 || i >= 500;
174
+ }
175
+ const l = {
176
+ maxAttempts: 3,
177
+ delayMs: 1e3,
178
+ backoffMultiplier: 2,
179
+ shouldRetry: x
180
+ };
181
+ class W extends M {
182
+ config;
183
+ retryConfig;
184
+ checkinTimer = null;
20
185
  constructor(e) {
21
- console.debug("PushClient initialized"), this.config = e;
186
+ super(), console.debug("PushClient initialized"), this.config = e;
187
+ const t = e.retry?.maxAttempts ?? l.maxAttempts, r = e.retry?.delayMs ?? l.delayMs, n = e.retry?.backoffMultiplier ?? l.backoffMultiplier;
188
+ this.retryConfig = {
189
+ maxAttempts: t < 1 ? 1 : t,
190
+ delayMs: r < 1 ? 1 : r,
191
+ backoffMultiplier: n < 1 ? 1 : n,
192
+ shouldRetry: e.retry?.shouldRetry ?? l.shouldRetry
193
+ };
194
+ }
195
+ on(e, t) {
196
+ super.on(e, t);
197
+ }
198
+ off(e, t) {
199
+ super.off(e, t);
22
200
  }
23
- /**
24
- * Checks if the client is already subscribed to push notifications.
25
- * @returns A promise that resolves to true if subscribed, false otherwise.
26
- */
27
201
  async isSubscribed() {
28
202
  if (!this.isSupported())
29
203
  return !1;
30
204
  const e = await navigator.serviceWorker.getRegistration();
31
205
  return e ? !!await e.pushManager.getSubscription() : !1;
32
206
  }
33
- /**
34
- * Registers the client for push notifications.
35
- * Checks support, config, and existing subscription.
36
- * Requests permission and registers with backend if necessary.
37
- * @returns A promise that resolves to true if registration is successful (or already exists), false otherwise.
38
- */
39
- async register() {
40
- console.debug("Registering push notifications...");
207
+ getPermissionState() {
208
+ return this.isSupported() ? Notification.permission : "unsupported";
209
+ }
210
+ async register(e = {}) {
41
211
  try {
42
212
  if (!this.isSupported())
43
- return console.warn("Push notifications are not supported in this browser."), !1;
213
+ throw new p();
44
214
  if (!this.validateConfig())
45
- return console.error("Invalid PushClient configuration."), !1;
46
- const e = await this.registerServiceWorker();
47
- if (await e.pushManager.getSubscription())
48
- return !0;
49
- const r = await Notification.requestPermission();
50
- if (console.debug(`Notification permission: ${r}`), r !== "granted")
51
- return console.warn("Notification permission denied."), !1;
52
- const s = o(
53
- this.config.vapidPublicKey
54
- ), t = await e.pushManager.subscribe({
215
+ throw new o(
216
+ y.NOT_SUPPORTED,
217
+ "Invalid PushClient configuration"
218
+ );
219
+ if (!N(this.config.vapidPublicKey))
220
+ throw new u("Invalid VAPID key format");
221
+ this.assertCheckinConfigured();
222
+ const t = await this.registerServiceWorker(), r = await t.pushManager.getSubscription();
223
+ if (r)
224
+ return e.force && await this.sendToBackendWithRetry(r), await this.persistCheckinConfig(r), !0;
225
+ const n = this.getPermissionState();
226
+ if (n === "denied")
227
+ throw new f();
228
+ if (n === "default") {
229
+ const c = await Notification.requestPermission();
230
+ if (console.debug(`Notification permission: ${c}`), c !== "granted")
231
+ throw new f();
232
+ this.emit("permissionChange", { permission: "granted" });
233
+ }
234
+ const s = I(this.config.vapidPublicKey), a = await t.pushManager.subscribe({
55
235
  userVisibleOnly: !0,
56
236
  applicationServerKey: s
57
237
  });
58
- return await this.sendToBackend(t), !0;
238
+ return await this.sendToBackendWithRetry(a), await this.persistCheckinConfig(a), this.emit("subscriptionChange", { subscribed: !0 }), !0;
239
+ } catch (t) {
240
+ throw t instanceof o ? t : (console.error("Failed to register push client:", t), new u(
241
+ t instanceof Error ? t.message : "Unknown error"
242
+ ));
243
+ }
244
+ }
245
+ async unsubscribe(e = {}) {
246
+ console.debug("Unsubscribing from push notifications...");
247
+ try {
248
+ if (!this.isSupported())
249
+ return !1;
250
+ const t = await navigator.serviceWorker.getRegistration();
251
+ if (!t)
252
+ return !1;
253
+ const r = await t.pushManager.getSubscription();
254
+ if (!r)
255
+ return !1;
256
+ if (!await r.unsubscribe())
257
+ throw new u("Failed to unsubscribe from push manager");
258
+ return this.stopPeriodicCheckin(), await _(), this.getUnregisterUrl() && e.notifyBackend !== !1 && await this.sendUnregisterToBackendWithRetry(r), this.emit("subscriptionChange", { subscribed: !1 }), !0;
259
+ } catch (t) {
260
+ throw t instanceof o ? t : (console.error("Failed to unsubscribe:", t), new u(
261
+ t instanceof Error ? t.message : "Unknown error during unsubscription"
262
+ ));
263
+ }
264
+ }
265
+ async updateSubscription() {
266
+ console.debug("Updating push subscription...");
267
+ try {
268
+ if (!this.isSupported())
269
+ throw new p();
270
+ if (!this.validateConfig())
271
+ throw new o(
272
+ y.NOT_SUPPORTED,
273
+ "Invalid PushClient configuration"
274
+ );
275
+ const e = await navigator.serviceWorker.getRegistration();
276
+ if (!e)
277
+ throw new u("No service worker registration found");
278
+ const t = await e.pushManager.getSubscription();
279
+ if (!t)
280
+ return console.debug("No existing subscription, creating new one"), await this.register();
281
+ const r = I(this.config.vapidPublicKey);
282
+ await t.unsubscribe();
283
+ const n = await e.pushManager.subscribe({
284
+ userVisibleOnly: !0,
285
+ applicationServerKey: r
286
+ });
287
+ return await this.sendToBackendWithRetry(n), await this.persistCheckinConfig(n), this.emit("subscriptionChange", { subscribed: !0 }), !0;
59
288
  } catch (e) {
60
- return console.error("Failed to register push client:", e), !1;
289
+ throw e instanceof o ? e : (console.error("Failed to update subscription:", e), new u(
290
+ e instanceof Error ? e.message : "Unknown error during subscription update"
291
+ ));
61
292
  }
62
293
  }
63
294
  /**
64
- * Checks if push notifications are supported in the browser.
65
- * @returns True if supported, false otherwise.
295
+ * Whether this browser supports Web Push (service worker, PushManager and
296
+ * Notification). Same result as {@link isPushSupported}, which needs no client.
66
297
  */
67
298
  isSupported() {
68
- return typeof window < "u" && "serviceWorker" in navigator && !!navigator.serviceWorker && "PushManager" in window && "Notification" in window;
299
+ return R();
300
+ }
301
+ validateConfig() {
302
+ return this.config.endpoints?.register ? !!this.config.vapidPublicKey : !!this.config.vapidPublicKey && !!this.config.backendRegisterUrl;
303
+ }
304
+ getRegisterUrl() {
305
+ return this.config.endpoints?.register ? this.config.endpoints.register : this.config.backendRegisterUrl || "/api/register";
306
+ }
307
+ getUnregisterUrl() {
308
+ if (this.config.endpoints?.unregister)
309
+ return this.config.endpoints.unregister;
310
+ if (this.config.backendUnregisterUrl)
311
+ return this.config.backendUnregisterUrl;
312
+ const e = this.getRegisterUrl();
313
+ return e.endsWith("/register") ? e.slice(0, -9) + "/unregister" : null;
69
314
  }
70
315
  /**
71
- * Validates the configuration.
72
- * @returns True if valid, false otherwise.
316
+ * Requires an explicit `backendCheckinUrl`; throws {@link CheckinConfigError}
317
+ * instead of silently skipping check-ins, so a misconfigured integration
318
+ * fails loudly before any subscription is created or reused.
319
+ *
320
+ * @throws {CheckinConfigError} When `backendCheckinUrl` is not configured.
73
321
  */
74
- validateConfig() {
75
- return !!(this.config.vapidPublicKey && this.config.backendRegisterUrl);
322
+ assertCheckinConfigured() {
323
+ if (!this.config.backendCheckinUrl)
324
+ throw new d(
325
+ "backendCheckinUrl is required: set it to your backend check-in relay URL so push receipts and periodic pings can record subscriber liveness. Without it, activity analytics decay to registration-time check-ins only."
326
+ );
76
327
  }
77
328
  /**
78
- * Registers the service worker.
79
- * @returns A promise that resolves with the ServiceWorkerRegistration.
329
+ * Cache the check-in configuration for the service worker so received
330
+ * pushes can report liveness.
331
+ *
332
+ * @param subscription - The push subscription being registered.
333
+ * @throws {CheckinConfigError} When `backendCheckinUrl` is not configured.
80
334
  */
335
+ async persistCheckinConfig(e) {
336
+ this.assertCheckinConfigured(), await O({
337
+ checkinUrl: this.config.backendCheckinUrl,
338
+ endpoint: e.endpoint
339
+ });
340
+ }
341
+ /**
342
+ * Opt-in periodic check-in: reports liveness immediately and then every
343
+ * `intervalMs` while the page stays open, in addition to the automatic
344
+ * push-driven check-ins. Intended for quota-accurate monthly actives.
345
+ *
346
+ * @param intervalMs - Check-in interval in milliseconds (default 6h).
347
+ * @throws {CheckinConfigError} When `backendCheckinUrl` is not configured —
348
+ * periodic check-ins would silently do nothing, which must fail loudly.
349
+ */
350
+ startPeriodicCheckin(e = 360 * 60 * 1e3) {
351
+ if (!this.config.backendCheckinUrl)
352
+ throw new d(
353
+ "startPeriodicCheckin() requires backendCheckinUrl to be configured: set it to your backend check-in relay URL so periodic pings can record subscriber liveness."
354
+ );
355
+ this.stopPeriodicCheckin();
356
+ const t = async () => {
357
+ const r = await U();
358
+ r && await v(r);
359
+ };
360
+ t(), this.checkinTimer = setInterval(() => {
361
+ t();
362
+ }, e);
363
+ }
364
+ /** Stop the periodic check-in started by startPeriodicCheckin. */
365
+ stopPeriodicCheckin() {
366
+ this.checkinTimer !== null && (clearInterval(this.checkinTimer), this.checkinTimer = null);
367
+ }
368
+ async getHeaders() {
369
+ const e = {
370
+ "Content-Type": "application/json"
371
+ };
372
+ if (this.config.headers)
373
+ return { ...e, ...this.config.headers };
374
+ if (this.config.getHeaders) {
375
+ const t = await this.config.getHeaders();
376
+ return { ...e, ...t };
377
+ }
378
+ return e;
379
+ }
81
380
  async registerServiceWorker() {
82
381
  const e = this.config.serviceWorkerPath || "/sw.js";
83
- console.debug(`[PushClient] Registering service worker at: ${e}`);
84
382
  try {
85
- const i = await navigator.serviceWorker.register(e, {
86
- scope: "/"
383
+ const t = await navigator.serviceWorker.register(e, {
384
+ scope: "/",
385
+ type: "module"
87
386
  });
88
- console.debug("[PushClient] Service Worker registered:", i), console.debug(
89
- `[PushClient] SW state: ${i.installing ? "installing" : i.waiting ? "waiting" : i.active ? "active" : "unknown"}`
90
- );
387
+ console.debug("[PushClient] Service Worker registered:", t);
91
388
  const r = await navigator.serviceWorker.ready;
92
389
  return console.debug("[PushClient] Service Worker ready"), r;
93
- } catch (i) {
94
- throw console.error("[PushClient] Failed to register service worker:", i), i;
390
+ } catch (t) {
391
+ throw console.error("[PushClient] Failed to register service worker:", t), new u(
392
+ `Failed to register service worker: ${t instanceof Error ? t.message : "Unknown error"}`
393
+ );
95
394
  }
96
395
  }
97
- /**
98
- * Sends the subscription to the backend.
99
- * @param subscription - The push subscription object.
100
- * @returns A promise that resolves when the subscription is sent.
101
- * @throws Will throw an error if the backend request fails.
102
- */
103
- async sendToBackend(e) {
104
- console.debug("[PushClient] Sending subscription to backend", e);
105
- const i = {
396
+ async sleep(e) {
397
+ return new Promise((t) => setTimeout(t, e));
398
+ }
399
+ backoffDelay(e) {
400
+ return this.retryConfig.delayMs * Math.pow(this.retryConfig.backoffMultiplier, e - 1);
401
+ }
402
+ async sendToBackendWithRetry(e) {
403
+ const t = this.getRegisterUrl(), r = await this.getHeaders(), n = {
106
404
  ...e.toJSON(),
107
405
  tags: this.config.tags
108
- }, r = await fetch(this.config.backendRegisterUrl, {
109
- method: "POST",
110
- headers: {
111
- "Content-Type": "application/json"
112
- },
113
- body: JSON.stringify(i)
114
- });
115
- if (!r.ok)
116
- throw new Error(
117
- `Failed to register push subscription: ${r.statusText}`
118
- );
406
+ };
407
+ for (let s = 1; s <= this.retryConfig.maxAttempts; s++) {
408
+ console.debug(`[PushClient] Sending subscription to backend (attempt ${s})`, e);
409
+ let a, c, m;
410
+ try {
411
+ const h = await fetch(t, {
412
+ method: "POST",
413
+ headers: r,
414
+ body: JSON.stringify(n)
415
+ });
416
+ if (h.ok)
417
+ return;
418
+ a = h.status, c = h.statusText || `HTTP ${h.status}`;
419
+ } catch (h) {
420
+ c = h instanceof Error ? h.message : "Unknown error", m = h;
421
+ }
422
+ if (s === this.retryConfig.maxAttempts || !this.retryConfig.shouldRetry(a))
423
+ throw new b(
424
+ `Failed to register push subscription after ${s} attempt${s === 1 ? "" : "s"}: ${c}`,
425
+ { status: a, cause: m }
426
+ );
427
+ const S = this.backoffDelay(s);
428
+ console.debug(`[PushClient] Backend registration failed, retrying in ${S}ms`), await this.sleep(S);
429
+ }
430
+ }
431
+ async sendUnregisterToBackendWithRetry(e) {
432
+ const t = this.getUnregisterUrl();
433
+ if (!t)
434
+ return;
435
+ const r = await this.getHeaders(), n = {
436
+ ...e.toJSON(),
437
+ action: "unsubscribe"
438
+ };
439
+ for (let s = 1; s <= this.retryConfig.maxAttempts; s++) {
440
+ console.debug(`[PushClient] Sending unregistration to backend (attempt ${s})`);
441
+ let a;
442
+ try {
443
+ const c = await fetch(t, {
444
+ method: "POST",
445
+ headers: r,
446
+ body: JSON.stringify(n)
447
+ });
448
+ if (c.ok)
449
+ return;
450
+ a = c.status;
451
+ } catch {
452
+ a = void 0;
453
+ }
454
+ if (s === this.retryConfig.maxAttempts || !this.retryConfig.shouldRetry(a)) {
455
+ console.warn("[PushClient] Failed to notify backend of unsubscription, but local unsubscribe succeeded");
456
+ return;
457
+ }
458
+ await this.sleep(this.backoffDelay(s));
459
+ }
119
460
  }
120
461
  }
121
462
  export {
122
- c as PushClient,
123
- a as arrayBufferToUrlBase64,
124
- o as urlBase64ToUint8Array
463
+ b as BackendRegistrationError,
464
+ w as CHECKIN_CACHE_NAME,
465
+ k as CHECKIN_CONFIG_URL,
466
+ D as CHECKIN_THROTTLE_MS,
467
+ d as CheckinConfigError,
468
+ p as NotSupportedError,
469
+ f as PermissionDeniedError,
470
+ W as PushClient,
471
+ o as PushClientError,
472
+ y as PushClientErrorCode,
473
+ M as PushClientEventEmitter,
474
+ u as SubscriptionError,
475
+ P as UnsubscriptionError,
476
+ g as ValidationError,
477
+ A as arrayBufferToUrlBase64,
478
+ _ as clearCheckinConfig,
479
+ x as defaultShouldRetry,
480
+ L as generateVapidKeys,
481
+ C as isCacheStorageAvailable,
482
+ K as isCheckinThrottled,
483
+ R as isPushSupported,
484
+ N as isValidVapidKey,
485
+ B as maybeCheckin,
486
+ v as performCheckin,
487
+ U as readCheckinConfig,
488
+ I as urlBase64ToUint8Array,
489
+ F as validateVapidKey,
490
+ O as writeCheckinConfig
125
491
  };