@markwharton/pwa-push 1.2.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 {
@@ -4,37 +4,85 @@
4
4
  import { Result } from '@markwharton/pwa-core/types';
5
5
  import { PushSubscription, SubscriptionRequest, PushPermissionState } from '../types';
6
6
  /**
7
- * 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
+ * }
8
14
  */
9
15
  export declare function getPermissionState(): PushPermissionState;
10
16
  /**
11
- * 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
+ * }
12
25
  */
13
26
  export declare function requestPermission(): Promise<PushPermissionState>;
14
27
  /**
15
- * 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
+ * }
16
36
  */
17
37
  export declare function isPushSupported(): boolean;
18
38
  /**
19
- * Convert browser PushSubscription to our format
20
- * 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) });
21
47
  */
22
48
  export declare function toPushSubscription(browserSub: globalThis.PushSubscription): PushSubscription;
23
49
  /**
24
- * Subscribe to push notifications
25
- *
26
- * @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
+ * }
27
63
  */
28
64
  export declare function subscribeToPush(vapidPublicKey: string, basePath?: string): Promise<Result<SubscriptionRequest>>;
29
65
  /**
30
- * Unsubscribe from push notifications
31
- *
32
- * @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
+ * }
33
74
  */
34
75
  export declare function unsubscribeFromPush(): Promise<Result<void>>;
35
76
  /**
36
- * Get current push subscription if exists
37
- *
38
- * @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
+ * }
39
87
  */
40
88
  export declare function getCurrentSubscription(): Promise<Result<PushSubscription>>;
@@ -15,27 +15,53 @@ const deviceId_1 = require("./deviceId");
15
15
  const indexedDb_1 = require("./indexedDb");
16
16
  const encoding_1 = require("./encoding");
17
17
  /**
18
- * 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
+ * }
19
25
  */
20
26
  function getPermissionState() {
21
27
  return Notification.permission;
22
28
  }
23
29
  /**
24
- * 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
+ * }
25
38
  */
26
39
  async function requestPermission() {
27
40
  const result = await Notification.requestPermission();
28
41
  return result;
29
42
  }
30
43
  /**
31
- * 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
+ * }
32
52
  */
33
53
  function isPushSupported() {
34
54
  return 'serviceWorker' in navigator && 'PushManager' in window;
35
55
  }
36
56
  /**
37
- * Convert browser PushSubscription to our format
38
- * 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) });
39
65
  */
40
66
  function toPushSubscription(browserSub) {
41
67
  const json = browserSub.toJSON();
@@ -48,9 +74,19 @@ function toPushSubscription(browserSub) {
48
74
  };
49
75
  }
50
76
  /**
51
- * Subscribe to push notifications
52
- *
53
- * @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
+ * }
54
90
  */
55
91
  async function subscribeToPush(vapidPublicKey, basePath = '/') {
56
92
  if (!isPushSupported()) {
@@ -87,9 +123,14 @@ async function subscribeToPush(vapidPublicKey, basePath = '/') {
87
123
  }
88
124
  }
89
125
  /**
90
- * Unsubscribe from push notifications
91
- *
92
- * @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
+ * }
93
134
  */
94
135
  async function unsubscribeFromPush() {
95
136
  try {
@@ -106,9 +147,16 @@ async function unsubscribeFromPush() {
106
147
  }
107
148
  }
108
149
  /**
109
- * Get current push subscription if exists
110
- *
111
- * @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
+ * }
112
160
  */
113
161
  async function getCurrentSubscription() {
114
162
  try {
@@ -1,8 +1,18 @@
1
1
  import { Result } from '@markwharton/pwa-core/types';
2
2
  import { PushSubscription, NotificationPayload } from '../types';
3
3
  /**
4
- * Initialize VAPID configuration - call once at startup
5
- * Fails fast if keys are missing
4
+ * Initializes VAPID configuration for Web Push. Call once at application startup.
5
+ * @param config - VAPID configuration
6
+ * @param config.publicKey - The VAPID public key
7
+ * @param config.privateKey - The VAPID private key
8
+ * @param config.subject - Contact email (mailto:) or URL
9
+ * @throws Error if any required configuration is missing
10
+ * @example
11
+ * initPush({
12
+ * publicKey: process.env.VAPID_PUBLIC_KEY,
13
+ * privateKey: process.env.VAPID_PRIVATE_KEY,
14
+ * subject: 'mailto:admin@example.com'
15
+ * });
6
16
  */
7
17
  export declare function initPush(config: {
8
18
  publicKey?: string;
@@ -10,30 +20,67 @@ export declare function initPush(config: {
10
20
  subject?: string;
11
21
  }): void;
12
22
  /**
13
- * Auto-initialize from environment variables
23
+ * Initializes VAPID from environment variables.
24
+ * Reads VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, and VAPID_SUBJECT.
25
+ * @throws Error if required environment variables are missing
26
+ * @example
27
+ * initPushFromEnv(); // Uses process.env automatically
14
28
  */
15
29
  export declare function initPushFromEnv(): void;
16
30
  /**
17
- * Get the VAPID public key (for client subscription)
31
+ * Gets the VAPID public key for client-side subscription.
32
+ * @returns The VAPID public key string
33
+ * @throws Error if initPush() has not been called
34
+ * @example
35
+ * // Server endpoint
36
+ * app.get('/api/vapid-key', (req, res) => {
37
+ * res.json({ publicKey: getVapidPublicKey() });
38
+ * });
18
39
  */
19
40
  export declare function getVapidPublicKey(): string;
20
41
  /**
21
- * Send a push notification to a single subscription
22
- *
23
- * @returns Result with ok status, or error details on failure
42
+ * Sends a push notification to a single subscription.
43
+ * @param subscription - The push subscription to send to
44
+ * @param payload - The notification payload (title, body, etc.)
45
+ * @returns Result with ok=true on success, or error message and statusCode on failure
46
+ * @example
47
+ * const result = await sendPushNotification(subscription, {
48
+ * title: 'New Message',
49
+ * body: 'You have a new message'
50
+ * });
24
51
  */
25
52
  export declare function sendPushNotification(subscription: PushSubscription, payload: NotificationPayload): Promise<Result<void>>;
26
53
  /**
27
- * Send a push notification to multiple subscriptions
28
- * Returns array of results, one per subscription
54
+ * Sends a push notification to multiple subscriptions in parallel.
55
+ * @param subscriptions - Array of push subscriptions
56
+ * @param payload - The notification payload (title, body, etc.)
57
+ * @returns Array of Results, one per subscription (in same order)
58
+ * @example
59
+ * const results = await sendPushToAll(subscriptions, { title: 'Alert', body: 'System update' });
60
+ * const failed = results.filter(r => !r.ok);
29
61
  */
30
62
  export declare function sendPushToAll(subscriptions: PushSubscription[], payload: NotificationPayload): Promise<Result<void>[]>;
31
63
  /**
32
- * Send push notification with detailed error information
33
- * Auto-injects basePath from subscription to payload if not already set
64
+ * Sends a push notification with detailed error information.
65
+ * Automatically injects basePath from subscription if not set in payload.
66
+ * @param subscription - The push subscription to send to
67
+ * @param payload - The notification payload
68
+ * @returns Result with ok=true on success, or error with statusCode on failure
69
+ * @example
70
+ * const result = await sendPushWithDetails(subscription, { title: 'Alert' });
71
+ * if (!result.ok && isSubscriptionExpired(result.statusCode)) {
72
+ * await deleteSubscription(subscription);
73
+ * }
34
74
  */
35
75
  export declare function sendPushWithDetails(subscription: PushSubscription, payload: NotificationPayload): Promise<Result<void>>;
36
76
  /**
37
- * Check if a subscription is expired (410 Gone)
77
+ * Checks if a status code indicates an expired subscription (410 Gone).
78
+ * Use this to clean up stale subscriptions from your database.
79
+ * @param statusCode - The HTTP status code from a failed push attempt
80
+ * @returns True if the subscription should be deleted
81
+ * @example
82
+ * if (!result.ok && isSubscriptionExpired(result.statusCode)) {
83
+ * await db.deleteSubscription(subscription.endpoint);
84
+ * }
38
85
  */
39
86
  export declare function isSubscriptionExpired(statusCode: number | undefined): boolean;
@@ -17,8 +17,18 @@ const types_1 = require("@markwharton/pwa-core/types");
17
17
  */
18
18
  let vapidConfig = null;
19
19
  /**
20
- * Initialize VAPID configuration - call once at startup
21
- * Fails fast if keys are missing
20
+ * Initializes VAPID configuration for Web Push. Call once at application startup.
21
+ * @param config - VAPID configuration
22
+ * @param config.publicKey - The VAPID public key
23
+ * @param config.privateKey - The VAPID private key
24
+ * @param config.subject - Contact email (mailto:) or URL
25
+ * @throws Error if any required configuration is missing
26
+ * @example
27
+ * initPush({
28
+ * publicKey: process.env.VAPID_PUBLIC_KEY,
29
+ * privateKey: process.env.VAPID_PRIVATE_KEY,
30
+ * subject: 'mailto:admin@example.com'
31
+ * });
22
32
  */
23
33
  function initPush(config) {
24
34
  const { publicKey, privateKey, subject } = config;
@@ -32,7 +42,11 @@ function initPush(config) {
32
42
  web_push_1.default.setVapidDetails(subject, publicKey, privateKey);
33
43
  }
34
44
  /**
35
- * Auto-initialize from environment variables
45
+ * Initializes VAPID from environment variables.
46
+ * Reads VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, and VAPID_SUBJECT.
47
+ * @throws Error if required environment variables are missing
48
+ * @example
49
+ * initPushFromEnv(); // Uses process.env automatically
36
50
  */
37
51
  function initPushFromEnv() {
38
52
  initPush({
@@ -42,7 +56,14 @@ function initPushFromEnv() {
42
56
  });
43
57
  }
44
58
  /**
45
- * Get the VAPID public key (for client subscription)
59
+ * Gets the VAPID public key for client-side subscription.
60
+ * @returns The VAPID public key string
61
+ * @throws Error if initPush() has not been called
62
+ * @example
63
+ * // Server endpoint
64
+ * app.get('/api/vapid-key', (req, res) => {
65
+ * res.json({ publicKey: getVapidPublicKey() });
66
+ * });
46
67
  */
47
68
  function getVapidPublicKey() {
48
69
  if (!vapidConfig) {
@@ -51,24 +72,43 @@ function getVapidPublicKey() {
51
72
  return vapidConfig.publicKey;
52
73
  }
53
74
  /**
54
- * Send a push notification to a single subscription
55
- *
56
- * @returns Result with ok status, or error details on failure
75
+ * Sends a push notification to a single subscription.
76
+ * @param subscription - The push subscription to send to
77
+ * @param payload - The notification payload (title, body, etc.)
78
+ * @returns Result with ok=true on success, or error message and statusCode on failure
79
+ * @example
80
+ * const result = await sendPushNotification(subscription, {
81
+ * title: 'New Message',
82
+ * body: 'You have a new message'
83
+ * });
57
84
  */
58
85
  async function sendPushNotification(subscription, payload) {
59
86
  return sendPushWithDetails(subscription, payload);
60
87
  }
61
88
  /**
62
- * Send a push notification to multiple subscriptions
63
- * Returns array of results, one per subscription
89
+ * Sends a push notification to multiple subscriptions in parallel.
90
+ * @param subscriptions - Array of push subscriptions
91
+ * @param payload - The notification payload (title, body, etc.)
92
+ * @returns Array of Results, one per subscription (in same order)
93
+ * @example
94
+ * const results = await sendPushToAll(subscriptions, { title: 'Alert', body: 'System update' });
95
+ * const failed = results.filter(r => !r.ok);
64
96
  */
65
97
  async function sendPushToAll(subscriptions, payload) {
66
98
  const results = await Promise.all(subscriptions.map(sub => sendPushWithDetails(sub, payload)));
67
99
  return results;
68
100
  }
69
101
  /**
70
- * Send push notification with detailed error information
71
- * Auto-injects basePath from subscription to payload if not already set
102
+ * Sends a push notification with detailed error information.
103
+ * Automatically injects basePath from subscription if not set in payload.
104
+ * @param subscription - The push subscription to send to
105
+ * @param payload - The notification payload
106
+ * @returns Result with ok=true on success, or error with statusCode on failure
107
+ * @example
108
+ * const result = await sendPushWithDetails(subscription, { title: 'Alert' });
109
+ * if (!result.ok && isSubscriptionExpired(result.statusCode)) {
110
+ * await deleteSubscription(subscription);
111
+ * }
72
112
  */
73
113
  async function sendPushWithDetails(subscription, payload) {
74
114
  if (!vapidConfig) {
@@ -89,7 +129,14 @@ async function sendPushWithDetails(subscription, payload) {
89
129
  }
90
130
  }
91
131
  /**
92
- * Check if a subscription is expired (410 Gone)
132
+ * Checks if a status code indicates an expired subscription (410 Gone).
133
+ * Use this to clean up stale subscriptions from your database.
134
+ * @param statusCode - The HTTP status code from a failed push attempt
135
+ * @returns True if the subscription should be deleted
136
+ * @example
137
+ * if (!result.ok && isSubscriptionExpired(result.statusCode)) {
138
+ * await db.deleteSubscription(subscription.endpoint);
139
+ * }
93
140
  */
94
141
  function isSubscriptionExpired(statusCode) {
95
142
  return statusCode === 410;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markwharton/pwa-push",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Web push notifications for Azure PWA projects",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",