@markwharton/pwa-push 1.1.0 → 1.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.
@@ -11,7 +11,9 @@ const DB_NAME = 'PushSubscriptionDB';
11
11
  const STORE_NAME = 'subscriptionData';
12
12
  const DATA_KEY = 'current';
13
13
  /**
14
- * Open the IndexedDB database
14
+ * Opens the IndexedDB database, creating the object store if needed.
15
+ * Internal helper for subscription data persistence.
16
+ * @returns Promise resolving to the opened database
15
17
  */
16
18
  function openDatabase() {
17
19
  return new Promise((resolve, reject) => {
@@ -27,7 +29,12 @@ function openDatabase() {
27
29
  });
28
30
  }
29
31
  /**
30
- * Execute an IndexedDB operation within a transaction
32
+ * Executes an IndexedDB operation within a transaction.
33
+ * Handles database opening, transaction management, and cleanup.
34
+ * @typeParam T - The expected result type from the operation
35
+ * @param mode - Transaction mode ('readonly' or 'readwrite')
36
+ * @param operation - Function that performs the IndexedDB operation
37
+ * @returns Promise resolving to the operation result
31
38
  */
32
39
  async function withTransaction(mode, operation) {
33
40
  const db = await openDatabase();
@@ -41,20 +48,41 @@ async function withTransaction(mode, operation) {
41
48
  });
42
49
  }
43
50
  /**
44
- * Save subscription data to IndexedDB (for service worker access)
51
+ * Saves subscription data to IndexedDB for service worker access.
52
+ * This data is used for subscription renewal when the browser rotates keys.
53
+ * @param data - The subscription data to persist (VAPID key, deviceId, basePath)
54
+ * @returns Promise that resolves when data is saved
55
+ * @example
56
+ * await saveSubscriptionData({
57
+ * publicKey: vapidPublicKey,
58
+ * deviceId: getDeviceId(),
59
+ * basePath: '/app'
60
+ * });
45
61
  */
46
62
  function saveSubscriptionData(data) {
47
63
  return withTransaction('readwrite', (store) => store.put(data, DATA_KEY));
48
64
  }
49
65
  /**
50
- * Get subscription data from IndexedDB
66
+ * Retrieves subscription data from IndexedDB.
67
+ * Used by service workers during subscription renewal.
68
+ * @returns The stored subscription data, or null if not found
69
+ * @example
70
+ * const data = await getSubscriptionData();
71
+ * if (data) {
72
+ * console.log('Device ID:', data.deviceId);
73
+ * }
51
74
  */
52
75
  async function getSubscriptionData() {
53
76
  const result = await withTransaction('readonly', (store) => store.get(DATA_KEY));
54
77
  return result || null;
55
78
  }
56
79
  /**
57
- * Clear subscription data from IndexedDB
80
+ * Clears subscription data from IndexedDB.
81
+ * Call when unsubscribing or during cleanup.
82
+ * @returns Promise that resolves when data is cleared
83
+ * @example
84
+ * await unsubscribeFromPush();
85
+ * await clearSubscriptionData();
58
86
  */
59
87
  function clearSubscriptionData() {
60
88
  return withTransaction('readwrite', (store) => store.delete(DATA_KEY));
@@ -4,22 +4,27 @@
4
4
  */
5
5
  import { PushSubscription } from '../types';
6
6
  /**
7
- * Handle pushsubscriptionchange event in service worker
8
- * Call this from your service worker's event listener
9
- *
10
- * Usage in sw.js:
11
- * ```
7
+ * Handles the pushsubscriptionchange event in a service worker.
8
+ * Call this from your service worker's event listener when the browser
9
+ * rotates push subscriptions (typically for security reasons).
10
+ * @param event - The pushsubscriptionchange event from the service worker
11
+ * @param renewEndpoint - The backend endpoint to send the renewal request to
12
+ * @returns True if renewal succeeded, false otherwise
13
+ * @example
14
+ * // In your service worker (sw.js):
12
15
  * self.addEventListener('pushsubscriptionchange', (event) => {
13
- * event.waitUntil(handleSubscriptionChange(event, '/api/push/renew'));
16
+ * event.waitUntil(handleSubscriptionChange(event, '/api/push/renew'));
14
17
  * });
15
- * ```
16
18
  */
17
19
  export declare function handleSubscriptionChange(event: PushSubscriptionChangeEvent, renewEndpoint: string): Promise<boolean>;
18
20
  /**
19
- * Type for pushsubscriptionchange event
21
+ * Type definition for the pushsubscriptionchange event.
22
+ * Fired when the browser rotates push subscriptions.
20
23
  */
21
24
  interface PushSubscriptionChangeEvent extends ExtendableEvent {
25
+ /** The old subscription that is being replaced (may be null) */
22
26
  oldSubscription?: PushSubscription;
27
+ /** The new subscription (may be null if unsubscribed) */
23
28
  newSubscription?: PushSubscription;
24
29
  }
25
30
  export {};
@@ -9,15 +9,17 @@ const encoding_1 = require("./encoding");
9
9
  const indexedDb_1 = require("./indexedDb");
10
10
  const subscribe_1 = require("./subscribe");
11
11
  /**
12
- * Handle pushsubscriptionchange event in service worker
13
- * Call this from your service worker's event listener
14
- *
15
- * Usage in sw.js:
16
- * ```
12
+ * Handles the pushsubscriptionchange event in a service worker.
13
+ * Call this from your service worker's event listener when the browser
14
+ * rotates push subscriptions (typically for security reasons).
15
+ * @param event - The pushsubscriptionchange event from the service worker
16
+ * @param renewEndpoint - The backend endpoint to send the renewal request to
17
+ * @returns True if renewal succeeded, false otherwise
18
+ * @example
19
+ * // In your service worker (sw.js):
17
20
  * self.addEventListener('pushsubscriptionchange', (event) => {
18
- * event.waitUntil(handleSubscriptionChange(event, '/api/push/renew'));
21
+ * event.waitUntil(handleSubscriptionChange(event, '/api/push/renew'));
19
22
  * });
20
- * ```
21
23
  */
22
24
  async function handleSubscriptionChange(event, renewEndpoint) {
23
25
  try {
@@ -58,7 +60,10 @@ async function handleSubscriptionChange(event, renewEndpoint) {
58
60
  }
59
61
  }
60
62
  /**
61
- * Resubscribe to push with stored VAPID key
63
+ * Resubscribes to push notifications using stored VAPID key.
64
+ * Internal helper for subscription renewal in service worker context.
65
+ * @param data - The stored subscription data containing VAPID key
66
+ * @returns The new PushSubscription, or null on failure
62
67
  */
63
68
  async function resubscribe(data) {
64
69
  try {
@@ -1,39 +1,88 @@
1
1
  /**
2
2
  * Push subscription helpers for main thread
3
3
  */
4
- import { PushSubscription, SubscriptionRequest, PushPermissionState, ClientResult } from '../types';
4
+ import { Result } from '@markwharton/pwa-core/types';
5
+ import { PushSubscription, SubscriptionRequest, PushPermissionState } from '../types';
5
6
  /**
6
- * Check current notification permission state
7
+ * Gets the current notification permission state.
8
+ * @returns The current permission state ('granted', 'denied', or 'default')
9
+ * @example
10
+ * const state = getPermissionState();
11
+ * if (state === 'granted') {
12
+ * // Can show notifications
13
+ * }
7
14
  */
8
15
  export declare function getPermissionState(): PushPermissionState;
9
16
  /**
10
- * Request notification permission from user
17
+ * Requests notification permission from the user.
18
+ * Shows browser permission dialog if not already granted/denied.
19
+ * @returns The resulting permission state
20
+ * @example
21
+ * const permission = await requestPermission();
22
+ * if (permission === 'granted') {
23
+ * await subscribeToPush(vapidKey);
24
+ * }
11
25
  */
12
26
  export declare function requestPermission(): Promise<PushPermissionState>;
13
27
  /**
14
- * Check if push notifications are supported
28
+ * Checks if push notifications are supported in the current browser.
29
+ * Requires both Service Worker and Push API support.
30
+ * @returns True if push notifications are supported
31
+ * @example
32
+ * if (!isPushSupported()) {
33
+ * console.log('Push not supported on this browser');
34
+ * return;
35
+ * }
15
36
  */
16
37
  export declare function isPushSupported(): boolean;
17
38
  /**
18
- * Convert browser PushSubscription to our format
19
- * Works in both main thread and service worker contexts
39
+ * Converts a browser PushSubscription to the simplified format for backend storage.
40
+ * Works in both main thread and service worker contexts.
41
+ * @param browserSub - The native browser PushSubscription object
42
+ * @returns A simplified PushSubscription with endpoint and keys
43
+ * @example
44
+ * const browserSub = await registration.pushManager.subscribe({ ... });
45
+ * const subscription = toPushSubscription(browserSub);
46
+ * await fetch('/api/subscribe', { body: JSON.stringify(subscription) });
20
47
  */
21
48
  export declare function toPushSubscription(browserSub: globalThis.PushSubscription): PushSubscription;
22
49
  /**
23
- * Subscribe to push notifications
24
- *
25
- * @returns Result with subscription request ready to send to backend
50
+ * Subscribes to push notifications and prepares a request for backend registration.
51
+ * Handles permission request, service worker subscription, and data persistence.
52
+ * @param vapidPublicKey - The VAPID public key from your server
53
+ * @param basePath - Optional base path for notification click handling (default: '/')
54
+ * @returns Result with subscription request on success, or error message on failure
55
+ * @example
56
+ * const result = await subscribeToPush(vapidPublicKey);
57
+ * if (result.ok) {
58
+ * await fetch('/api/push/subscribe', {
59
+ * method: 'POST',
60
+ * body: JSON.stringify(result.data)
61
+ * });
62
+ * }
26
63
  */
27
- export declare function subscribeToPush(vapidPublicKey: string, basePath?: string): Promise<ClientResult<SubscriptionRequest>>;
64
+ export declare function subscribeToPush(vapidPublicKey: string, basePath?: string): Promise<Result<SubscriptionRequest>>;
28
65
  /**
29
- * Unsubscribe from push notifications
30
- *
31
- * @returns Result indicating success or failure
66
+ * Unsubscribes from push notifications.
67
+ * Removes the browser push subscription if one exists.
68
+ * @returns Result with ok=true on success, or error message on failure
69
+ * @example
70
+ * const result = await unsubscribeFromPush();
71
+ * if (result.ok) {
72
+ * await fetch('/api/push/unsubscribe', { method: 'POST' });
73
+ * }
32
74
  */
33
- export declare function unsubscribeFromPush(): Promise<ClientResult<void>>;
75
+ export declare function unsubscribeFromPush(): Promise<Result<void>>;
34
76
  /**
35
- * Get current push subscription if exists
36
- *
37
- * @returns Result with current subscription, or error if not subscribed
77
+ * Gets the current push subscription if one exists.
78
+ * Useful for checking subscription status or syncing with backend.
79
+ * @returns Result with the current subscription, or error if not subscribed
80
+ * @example
81
+ * const result = await getCurrentSubscription();
82
+ * if (result.ok) {
83
+ * console.log('Endpoint:', result.data.endpoint);
84
+ * } else {
85
+ * console.log('Not subscribed:', result.error);
86
+ * }
38
87
  */
39
- export declare function getCurrentSubscription(): Promise<ClientResult<PushSubscription>>;
88
+ export declare function getCurrentSubscription(): Promise<Result<PushSubscription>>;
@@ -10,31 +10,58 @@ exports.toPushSubscription = toPushSubscription;
10
10
  exports.subscribeToPush = subscribeToPush;
11
11
  exports.unsubscribeFromPush = unsubscribeFromPush;
12
12
  exports.getCurrentSubscription = getCurrentSubscription;
13
+ const types_1 = require("@markwharton/pwa-core/types");
13
14
  const deviceId_1 = require("./deviceId");
14
15
  const indexedDb_1 = require("./indexedDb");
15
16
  const encoding_1 = require("./encoding");
16
17
  /**
17
- * Check current notification permission state
18
+ * Gets the current notification permission state.
19
+ * @returns The current permission state ('granted', 'denied', or 'default')
20
+ * @example
21
+ * const state = getPermissionState();
22
+ * if (state === 'granted') {
23
+ * // Can show notifications
24
+ * }
18
25
  */
19
26
  function getPermissionState() {
20
27
  return Notification.permission;
21
28
  }
22
29
  /**
23
- * Request notification permission from user
30
+ * Requests notification permission from the user.
31
+ * Shows browser permission dialog if not already granted/denied.
32
+ * @returns The resulting permission state
33
+ * @example
34
+ * const permission = await requestPermission();
35
+ * if (permission === 'granted') {
36
+ * await subscribeToPush(vapidKey);
37
+ * }
24
38
  */
25
39
  async function requestPermission() {
26
40
  const result = await Notification.requestPermission();
27
41
  return result;
28
42
  }
29
43
  /**
30
- * Check if push notifications are supported
44
+ * Checks if push notifications are supported in the current browser.
45
+ * Requires both Service Worker and Push API support.
46
+ * @returns True if push notifications are supported
47
+ * @example
48
+ * if (!isPushSupported()) {
49
+ * console.log('Push not supported on this browser');
50
+ * return;
51
+ * }
31
52
  */
32
53
  function isPushSupported() {
33
54
  return 'serviceWorker' in navigator && 'PushManager' in window;
34
55
  }
35
56
  /**
36
- * Convert browser PushSubscription to our format
37
- * Works in both main thread and service worker contexts
57
+ * Converts a browser PushSubscription to the simplified format for backend storage.
58
+ * Works in both main thread and service worker contexts.
59
+ * @param browserSub - The native browser PushSubscription object
60
+ * @returns A simplified PushSubscription with endpoint and keys
61
+ * @example
62
+ * const browserSub = await registration.pushManager.subscribe({ ... });
63
+ * const subscription = toPushSubscription(browserSub);
64
+ * await fetch('/api/subscribe', { body: JSON.stringify(subscription) });
38
65
  */
39
66
  function toPushSubscription(browserSub) {
40
67
  const json = browserSub.toJSON();
@@ -47,17 +74,27 @@ function toPushSubscription(browserSub) {
47
74
  };
48
75
  }
49
76
  /**
50
- * Subscribe to push notifications
51
- *
52
- * @returns Result with subscription request ready to send to backend
77
+ * Subscribes to push notifications and prepares a request for backend registration.
78
+ * Handles permission request, service worker subscription, and data persistence.
79
+ * @param vapidPublicKey - The VAPID public key from your server
80
+ * @param basePath - Optional base path for notification click handling (default: '/')
81
+ * @returns Result with subscription request on success, or error message on failure
82
+ * @example
83
+ * const result = await subscribeToPush(vapidPublicKey);
84
+ * if (result.ok) {
85
+ * await fetch('/api/push/subscribe', {
86
+ * method: 'POST',
87
+ * body: JSON.stringify(result.data)
88
+ * });
89
+ * }
53
90
  */
54
91
  async function subscribeToPush(vapidPublicKey, basePath = '/') {
55
92
  if (!isPushSupported()) {
56
- return { ok: false, error: 'Push notifications not supported' };
93
+ return (0, types_1.err)('Push notifications not supported');
57
94
  }
58
95
  const permission = await requestPermission();
59
96
  if (permission !== 'granted') {
60
- return { ok: false, error: 'Push permission denied' };
97
+ return (0, types_1.err)('Push permission denied');
61
98
  }
62
99
  try {
63
100
  const registration = await navigator.serviceWorker.ready;
@@ -74,24 +111,26 @@ async function subscribeToPush(vapidPublicKey, basePath = '/') {
74
111
  deviceId,
75
112
  basePath
76
113
  });
77
- return {
78
- ok: true,
79
- data: {
80
- subscription: toPushSubscription(browserSub),
81
- deviceId,
82
- basePath
83
- }
84
- };
114
+ return (0, types_1.ok)({
115
+ subscription: toPushSubscription(browserSub),
116
+ deviceId,
117
+ basePath
118
+ });
85
119
  }
86
120
  catch (error) {
87
121
  const message = error instanceof Error ? error.message : 'Subscription failed';
88
- return { ok: false, error: message };
122
+ return (0, types_1.err)(message);
89
123
  }
90
124
  }
91
125
  /**
92
- * Unsubscribe from push notifications
93
- *
94
- * @returns Result indicating success or failure
126
+ * Unsubscribes from push notifications.
127
+ * Removes the browser push subscription if one exists.
128
+ * @returns Result with ok=true on success, or error message on failure
129
+ * @example
130
+ * const result = await unsubscribeFromPush();
131
+ * if (result.ok) {
132
+ * await fetch('/api/push/unsubscribe', { method: 'POST' });
133
+ * }
95
134
  */
96
135
  async function unsubscribeFromPush() {
97
136
  try {
@@ -100,29 +139,36 @@ async function unsubscribeFromPush() {
100
139
  if (subscription) {
101
140
  await subscription.unsubscribe();
102
141
  }
103
- return { ok: true };
142
+ return (0, types_1.okVoid)();
104
143
  }
105
144
  catch (error) {
106
145
  const message = error instanceof Error ? error.message : 'Unsubscribe failed';
107
- return { ok: false, error: message };
146
+ return (0, types_1.err)(message);
108
147
  }
109
148
  }
110
149
  /**
111
- * Get current push subscription if exists
112
- *
113
- * @returns Result with current subscription, or error if not subscribed
150
+ * Gets the current push subscription if one exists.
151
+ * Useful for checking subscription status or syncing with backend.
152
+ * @returns Result with the current subscription, or error if not subscribed
153
+ * @example
154
+ * const result = await getCurrentSubscription();
155
+ * if (result.ok) {
156
+ * console.log('Endpoint:', result.data.endpoint);
157
+ * } else {
158
+ * console.log('Not subscribed:', result.error);
159
+ * }
114
160
  */
115
161
  async function getCurrentSubscription() {
116
162
  try {
117
163
  const registration = await navigator.serviceWorker.ready;
118
164
  const subscription = await registration.pushManager.getSubscription();
119
165
  if (!subscription) {
120
- return { ok: false, error: 'No active subscription' };
166
+ return (0, types_1.err)('No active subscription');
121
167
  }
122
- return { ok: true, data: toPushSubscription(subscription) };
168
+ return (0, types_1.ok)(toPushSubscription(subscription));
123
169
  }
124
170
  catch (error) {
125
171
  const message = error instanceof Error ? error.message : 'Failed to get subscription';
126
- return { ok: false, error: message };
172
+ return (0, types_1.err)(message);
127
173
  }
128
174
  }
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ var PwaPush = (() => {
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
+
34
+ // ../core/dist/types.js
35
+ var require_types = __commonJS({
36
+ "../core/dist/types.js"(exports) {
37
+ "use strict";
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ok = ok2;
40
+ exports.okVoid = okVoid2;
41
+ exports.err = err2;
42
+ function ok2(data) {
43
+ return { ok: true, data };
44
+ }
45
+ function okVoid2() {
46
+ return { ok: true };
47
+ }
48
+ function err2(error, statusCode) {
49
+ return statusCode !== void 0 ? { ok: false, error, statusCode } : { ok: false, error };
50
+ }
51
+ }
52
+ });
53
+
54
+ // src/sw.ts
55
+ var sw_exports = {};
56
+ __export(sw_exports, {
57
+ handleSubscriptionChange: () => handleSubscriptionChange
58
+ });
59
+
60
+ // src/client/encoding.ts
61
+ function urlBase64ToUint8Array(base64String) {
62
+ const padding = "=".repeat((4 - base64String.length % 4) % 4);
63
+ const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
64
+ const rawData = atob(base64);
65
+ const buffer = new ArrayBuffer(rawData.length);
66
+ const outputArray = new Uint8Array(buffer);
67
+ for (let i = 0; i < rawData.length; ++i) {
68
+ outputArray[i] = rawData.charCodeAt(i);
69
+ }
70
+ return outputArray;
71
+ }
72
+
73
+ // src/client/indexedDb.ts
74
+ var DB_NAME = "PushSubscriptionDB";
75
+ var STORE_NAME = "subscriptionData";
76
+ var DATA_KEY = "current";
77
+ function openDatabase() {
78
+ return new Promise((resolve, reject) => {
79
+ const request = indexedDB.open(DB_NAME, 1);
80
+ request.onerror = () => reject(request.error);
81
+ request.onsuccess = () => resolve(request.result);
82
+ request.onupgradeneeded = (event) => {
83
+ const db = event.target.result;
84
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
85
+ db.createObjectStore(STORE_NAME);
86
+ }
87
+ };
88
+ });
89
+ }
90
+ async function withTransaction(mode, operation) {
91
+ const db = await openDatabase();
92
+ return new Promise((resolve, reject) => {
93
+ const transaction = db.transaction(STORE_NAME, mode);
94
+ const store = transaction.objectStore(STORE_NAME);
95
+ const request = operation(store);
96
+ request.onerror = () => reject(request.error);
97
+ request.onsuccess = () => resolve(request.result);
98
+ transaction.oncomplete = () => db.close();
99
+ });
100
+ }
101
+ async function getSubscriptionData() {
102
+ const result = await withTransaction(
103
+ "readonly",
104
+ (store) => store.get(DATA_KEY)
105
+ );
106
+ return result || null;
107
+ }
108
+
109
+ // src/client/subscribe.ts
110
+ var import_types = __toESM(require_types());
111
+ function toPushSubscription(browserSub) {
112
+ const json = browserSub.toJSON();
113
+ return {
114
+ endpoint: browserSub.endpoint,
115
+ keys: {
116
+ p256dh: json.keys?.p256dh || "",
117
+ auth: json.keys?.auth || ""
118
+ }
119
+ };
120
+ }
121
+
122
+ // src/client/renewal.ts
123
+ async function handleSubscriptionChange(event, renewEndpoint) {
124
+ try {
125
+ const data = await getSubscriptionData();
126
+ if (!data) {
127
+ console.error("No subscription data found for renewal");
128
+ return false;
129
+ }
130
+ const newSubscription = await resubscribe(data);
131
+ if (!newSubscription) {
132
+ console.error("Failed to create new subscription");
133
+ return false;
134
+ }
135
+ const renewalRequest = {
136
+ subscription: newSubscription,
137
+ deviceId: data.deviceId,
138
+ basePath: data.basePath
139
+ };
140
+ const response = await fetch(renewEndpoint, {
141
+ method: "POST",
142
+ headers: { "Content-Type": "application/json" },
143
+ body: JSON.stringify(renewalRequest)
144
+ });
145
+ if (!response.ok) {
146
+ console.error("Renewal request failed:", response.status);
147
+ return false;
148
+ }
149
+ console.log("Push subscription renewed successfully");
150
+ return true;
151
+ } catch (error) {
152
+ console.error("Subscription renewal failed:", error);
153
+ return false;
154
+ }
155
+ }
156
+ async function resubscribe(data) {
157
+ try {
158
+ const self = globalThis;
159
+ const registration = self.registration;
160
+ const applicationServerKey = urlBase64ToUint8Array(data.publicKey);
161
+ const subscription = await registration.pushManager.subscribe({
162
+ userVisibleOnly: true,
163
+ applicationServerKey
164
+ });
165
+ return toPushSubscription(subscription);
166
+ } catch (error) {
167
+ console.error("Resubscribe failed:", error);
168
+ return null;
169
+ }
170
+ }
171
+ return __toCommonJS(sw_exports);
172
+ })();