@markwharton/pwa-push 2.0.1 → 3.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/dist/pwa-push-sw.js +4 -4
- package/dist/server.d.ts +32 -30
- package/dist/server.js +61 -38
- package/dist/shared.d.ts +8 -0
- package/package.json +3 -3
package/dist/pwa-push-sw.js
CHANGED
|
@@ -31,9 +31,9 @@ var PwaPush = (() => {
|
|
|
31
31
|
));
|
|
32
32
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
33
|
|
|
34
|
-
//
|
|
34
|
+
// ../core/dist/shared.js
|
|
35
35
|
var require_shared = __commonJS({
|
|
36
|
-
"
|
|
36
|
+
"../core/dist/shared.js"(exports) {
|
|
37
37
|
"use strict";
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.HTTP_STATUS = void 0;
|
|
@@ -50,8 +50,8 @@ var PwaPush = (() => {
|
|
|
50
50
|
function okVoid2() {
|
|
51
51
|
return { ok: true };
|
|
52
52
|
}
|
|
53
|
-
function err2(error,
|
|
54
|
-
return
|
|
53
|
+
function err2(error, status) {
|
|
54
|
+
return status !== void 0 ? { ok: false, error, status } : { ok: false, error };
|
|
55
55
|
}
|
|
56
56
|
function hasUsername(payload) {
|
|
57
57
|
return "username" in payload && typeof payload.username === "string";
|
package/dist/server.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Requires: web-push package
|
|
5
5
|
*/
|
|
6
|
-
import { Result, PushSubscription, NotificationPayload } from './shared';
|
|
6
|
+
import { Result, PushSubscription, NotificationPayload, BroadcastResult } from './shared';
|
|
7
7
|
/**
|
|
8
8
|
* Initializes VAPID configuration for Web Push. Call once at application startup.
|
|
9
9
|
* @param config - VAPID configuration
|
|
@@ -44,47 +44,49 @@ export declare function initPushFromEnv(): void;
|
|
|
44
44
|
export declare function getVapidPublicKey(): string;
|
|
45
45
|
/**
|
|
46
46
|
* Sends a push notification to a single subscription.
|
|
47
|
-
* @param subscription - The push subscription to send to
|
|
48
|
-
* @param payload - The notification payload (title, body, etc.)
|
|
49
|
-
* @returns Result with ok=true on success, or error message and statusCode on failure
|
|
50
|
-
* @example
|
|
51
|
-
* const result = await sendPushNotification(subscription, {
|
|
52
|
-
* title: 'New Message',
|
|
53
|
-
* body: 'You have a new message'
|
|
54
|
-
* });
|
|
55
|
-
*/
|
|
56
|
-
export declare function sendPushNotification(subscription: PushSubscription, payload: NotificationPayload): Promise<Result<void>>;
|
|
57
|
-
/**
|
|
58
|
-
* Sends a push notification to multiple subscriptions in parallel.
|
|
59
|
-
* @param subscriptions - Array of push subscriptions
|
|
60
|
-
* @param payload - The notification payload (title, body, etc.)
|
|
61
|
-
* @returns Array of Results, one per subscription (in same order)
|
|
62
|
-
* @example
|
|
63
|
-
* const results = await sendPushToAll(subscriptions, { title: 'Alert', body: 'System update' });
|
|
64
|
-
* const failed = results.filter(r => !r.ok);
|
|
65
|
-
*/
|
|
66
|
-
export declare function sendPushToAll(subscriptions: PushSubscription[], payload: NotificationPayload): Promise<Result<void>[]>;
|
|
67
|
-
/**
|
|
68
|
-
* Sends a push notification with detailed error information.
|
|
69
47
|
* Automatically injects basePath from subscription if not set in payload.
|
|
70
48
|
* @param subscription - The push subscription to send to
|
|
71
49
|
* @param payload - The notification payload
|
|
72
|
-
* @returns Result with ok=true on success, or error with
|
|
50
|
+
* @returns Result with ok=true on success, or error with status on failure
|
|
73
51
|
* @example
|
|
74
|
-
* const result = await
|
|
75
|
-
* if (!result.ok && isSubscriptionExpired(result.
|
|
52
|
+
* const result = await sendPush(subscription, { title: 'Alert', body: 'Update' });
|
|
53
|
+
* if (!result.ok && isSubscriptionExpired(result.status)) {
|
|
76
54
|
* await deleteSubscription(subscription);
|
|
77
55
|
* }
|
|
78
56
|
*/
|
|
79
|
-
export declare function
|
|
57
|
+
export declare function sendPush(subscription: PushSubscription, payload: NotificationPayload): Promise<Result<void>>;
|
|
58
|
+
/**
|
|
59
|
+
* Broadcasts a push notification to multiple subscriptions in parallel.
|
|
60
|
+
* Returns structured results with counts and invalid endpoint tracking.
|
|
61
|
+
* Generic `<TSub>` lets the payload callback receive app-extended subscription types.
|
|
62
|
+
* @typeParam TSub - Push subscription type (extends PushSubscription)
|
|
63
|
+
* @param subscriptions - Array of push subscriptions
|
|
64
|
+
* @param payload - Static payload or per-subscription callback
|
|
65
|
+
* @returns BroadcastResult with sent/failed counts and invalid endpoints
|
|
66
|
+
* @example
|
|
67
|
+
* const result = await broadcastPush(subscriptions, { title: 'Alert', body: 'Update' });
|
|
68
|
+
* await cleanupInvalid(result.invalidEndpoints);
|
|
69
|
+
*
|
|
70
|
+
* // Per-subscription payload:
|
|
71
|
+
* const result = await broadcastPush(subscriptions, (sub) => ({
|
|
72
|
+
* title: 'Alert', body: 'Update', basePath: sub.basePath
|
|
73
|
+
* }));
|
|
74
|
+
*/
|
|
75
|
+
export declare function broadcastPush<TSub extends PushSubscription>(subscriptions: TSub[], payload: NotificationPayload | ((subscription: TSub) => NotificationPayload)): Promise<BroadcastResult>;
|
|
80
76
|
/**
|
|
81
77
|
* Checks if a status code indicates an expired subscription (410 Gone).
|
|
82
78
|
* Use this to clean up stale subscriptions from your database.
|
|
83
|
-
* @param
|
|
79
|
+
* @param status - The HTTP status code from a failed push attempt
|
|
84
80
|
* @returns True if the subscription should be deleted
|
|
85
81
|
* @example
|
|
86
|
-
* if (!result.ok && isSubscriptionExpired(result.
|
|
82
|
+
* if (!result.ok && isSubscriptionExpired(result.status)) {
|
|
87
83
|
* await db.deleteSubscription(subscription.endpoint);
|
|
88
84
|
* }
|
|
89
85
|
*/
|
|
90
|
-
export declare function isSubscriptionExpired(
|
|
86
|
+
export declare function isSubscriptionExpired(status: number | undefined): boolean;
|
|
87
|
+
/** @deprecated Use `sendPush` instead */
|
|
88
|
+
export declare const sendPushNotification: typeof sendPush;
|
|
89
|
+
/** @deprecated Use `sendPush` instead */
|
|
90
|
+
export declare const sendPushWithDetails: typeof sendPush;
|
|
91
|
+
/** @deprecated Use `broadcastPush` instead */
|
|
92
|
+
export declare function sendPushToAll(subscriptions: PushSubscription[], payload: NotificationPayload): Promise<Result<void>[]>;
|
package/dist/server.js
CHANGED
|
@@ -8,13 +8,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
8
8
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
9
|
};
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.sendPushWithDetails = exports.sendPushNotification = void 0;
|
|
11
12
|
exports.initPush = initPush;
|
|
12
13
|
exports.initPushFromEnv = initPushFromEnv;
|
|
13
14
|
exports.getVapidPublicKey = getVapidPublicKey;
|
|
14
|
-
exports.
|
|
15
|
-
exports.
|
|
16
|
-
exports.sendPushWithDetails = sendPushWithDetails;
|
|
15
|
+
exports.sendPush = sendPush;
|
|
16
|
+
exports.broadcastPush = broadcastPush;
|
|
17
17
|
exports.isSubscriptionExpired = isSubscriptionExpired;
|
|
18
|
+
exports.sendPushToAll = sendPushToAll;
|
|
18
19
|
const web_push_1 = __importDefault(require("web-push"));
|
|
19
20
|
const shared_1 = require("./shared");
|
|
20
21
|
let vapidConfig = null;
|
|
@@ -75,44 +76,17 @@ function getVapidPublicKey() {
|
|
|
75
76
|
}
|
|
76
77
|
/**
|
|
77
78
|
* Sends a push notification to a single subscription.
|
|
78
|
-
* @param subscription - The push subscription to send to
|
|
79
|
-
* @param payload - The notification payload (title, body, etc.)
|
|
80
|
-
* @returns Result with ok=true on success, or error message and statusCode on failure
|
|
81
|
-
* @example
|
|
82
|
-
* const result = await sendPushNotification(subscription, {
|
|
83
|
-
* title: 'New Message',
|
|
84
|
-
* body: 'You have a new message'
|
|
85
|
-
* });
|
|
86
|
-
*/
|
|
87
|
-
async function sendPushNotification(subscription, payload) {
|
|
88
|
-
return sendPushWithDetails(subscription, payload);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Sends a push notification to multiple subscriptions in parallel.
|
|
92
|
-
* @param subscriptions - Array of push subscriptions
|
|
93
|
-
* @param payload - The notification payload (title, body, etc.)
|
|
94
|
-
* @returns Array of Results, one per subscription (in same order)
|
|
95
|
-
* @example
|
|
96
|
-
* const results = await sendPushToAll(subscriptions, { title: 'Alert', body: 'System update' });
|
|
97
|
-
* const failed = results.filter(r => !r.ok);
|
|
98
|
-
*/
|
|
99
|
-
async function sendPushToAll(subscriptions, payload) {
|
|
100
|
-
const results = await Promise.all(subscriptions.map(sub => sendPushWithDetails(sub, payload)));
|
|
101
|
-
return results;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Sends a push notification with detailed error information.
|
|
105
79
|
* Automatically injects basePath from subscription if not set in payload.
|
|
106
80
|
* @param subscription - The push subscription to send to
|
|
107
81
|
* @param payload - The notification payload
|
|
108
|
-
* @returns Result with ok=true on success, or error with
|
|
82
|
+
* @returns Result with ok=true on success, or error with status on failure
|
|
109
83
|
* @example
|
|
110
|
-
* const result = await
|
|
111
|
-
* if (!result.ok && isSubscriptionExpired(result.
|
|
84
|
+
* const result = await sendPush(subscription, { title: 'Alert', body: 'Update' });
|
|
85
|
+
* if (!result.ok && isSubscriptionExpired(result.status)) {
|
|
112
86
|
* await deleteSubscription(subscription);
|
|
113
87
|
* }
|
|
114
88
|
*/
|
|
115
|
-
async function
|
|
89
|
+
async function sendPush(subscription, payload) {
|
|
116
90
|
if (!vapidConfig) {
|
|
117
91
|
return (0, shared_1.err)('Push not initialized');
|
|
118
92
|
}
|
|
@@ -130,16 +104,65 @@ async function sendPushWithDetails(subscription, payload) {
|
|
|
130
104
|
return (0, shared_1.err)(webPushError.message || 'Unknown error', webPushError.statusCode);
|
|
131
105
|
}
|
|
132
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Broadcasts a push notification to multiple subscriptions in parallel.
|
|
109
|
+
* Returns structured results with counts and invalid endpoint tracking.
|
|
110
|
+
* Generic `<TSub>` lets the payload callback receive app-extended subscription types.
|
|
111
|
+
* @typeParam TSub - Push subscription type (extends PushSubscription)
|
|
112
|
+
* @param subscriptions - Array of push subscriptions
|
|
113
|
+
* @param payload - Static payload or per-subscription callback
|
|
114
|
+
* @returns BroadcastResult with sent/failed counts and invalid endpoints
|
|
115
|
+
* @example
|
|
116
|
+
* const result = await broadcastPush(subscriptions, { title: 'Alert', body: 'Update' });
|
|
117
|
+
* await cleanupInvalid(result.invalidEndpoints);
|
|
118
|
+
*
|
|
119
|
+
* // Per-subscription payload:
|
|
120
|
+
* const result = await broadcastPush(subscriptions, (sub) => ({
|
|
121
|
+
* title: 'Alert', body: 'Update', basePath: sub.basePath
|
|
122
|
+
* }));
|
|
123
|
+
*/
|
|
124
|
+
async function broadcastPush(subscriptions, payload) {
|
|
125
|
+
let sent = 0;
|
|
126
|
+
let failed = 0;
|
|
127
|
+
const invalidEndpoints = [];
|
|
128
|
+
await Promise.all(subscriptions.map(async (subscription) => {
|
|
129
|
+
const actualPayload = typeof payload === 'function'
|
|
130
|
+
? payload(subscription) : payload;
|
|
131
|
+
const result = await sendPush(subscription, actualPayload);
|
|
132
|
+
if (result.ok) {
|
|
133
|
+
sent++;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
failed++;
|
|
137
|
+
if (isSubscriptionExpired(result.status)) {
|
|
138
|
+
invalidEndpoints.push(subscription.endpoint);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}));
|
|
142
|
+
return { sent, failed, invalidEndpoints };
|
|
143
|
+
}
|
|
133
144
|
/**
|
|
134
145
|
* Checks if a status code indicates an expired subscription (410 Gone).
|
|
135
146
|
* Use this to clean up stale subscriptions from your database.
|
|
136
|
-
* @param
|
|
147
|
+
* @param status - The HTTP status code from a failed push attempt
|
|
137
148
|
* @returns True if the subscription should be deleted
|
|
138
149
|
* @example
|
|
139
|
-
* if (!result.ok && isSubscriptionExpired(result.
|
|
150
|
+
* if (!result.ok && isSubscriptionExpired(result.status)) {
|
|
140
151
|
* await db.deleteSubscription(subscription.endpoint);
|
|
141
152
|
* }
|
|
142
153
|
*/
|
|
143
|
-
function isSubscriptionExpired(
|
|
144
|
-
return
|
|
154
|
+
function isSubscriptionExpired(status) {
|
|
155
|
+
return status === 410;
|
|
156
|
+
}
|
|
157
|
+
// =============================================================================
|
|
158
|
+
// Deprecated aliases (remove in next major)
|
|
159
|
+
// =============================================================================
|
|
160
|
+
/** @deprecated Use `sendPush` instead */
|
|
161
|
+
exports.sendPushNotification = sendPush;
|
|
162
|
+
/** @deprecated Use `sendPush` instead */
|
|
163
|
+
exports.sendPushWithDetails = sendPush;
|
|
164
|
+
/** @deprecated Use `broadcastPush` instead */
|
|
165
|
+
async function sendPushToAll(subscriptions, payload) {
|
|
166
|
+
const results = await Promise.all(subscriptions.map(sub => sendPush(sub, payload)));
|
|
167
|
+
return results;
|
|
145
168
|
}
|
package/dist/shared.d.ts
CHANGED
|
@@ -57,3 +57,11 @@ export interface SubscriptionData {
|
|
|
57
57
|
* Browser notification permission state.
|
|
58
58
|
*/
|
|
59
59
|
export type PushPermissionState = 'granted' | 'denied' | 'default';
|
|
60
|
+
/**
|
|
61
|
+
* Result of broadcasting push notifications to multiple subscriptions.
|
|
62
|
+
*/
|
|
63
|
+
export interface BroadcastResult {
|
|
64
|
+
sent: number;
|
|
65
|
+
failed: number;
|
|
66
|
+
invalidEndpoints: string[];
|
|
67
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markwharton/pwa-push",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Web push notifications for Azure PWA projects",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"clean": "rm -rf dist"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@markwharton/pwa-core": "^2.0.0 || ^3.0.0",
|
|
33
|
+
"@markwharton/pwa-core": "^2.0.0 || ^3.0.0 || ^4.0.0",
|
|
34
34
|
"web-push": "^3.6.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@markwharton/pwa-core": "^
|
|
37
|
+
"@markwharton/pwa-core": "^4.0.0",
|
|
38
38
|
"@types/node": "^20.10.0",
|
|
39
39
|
"@types/web-push": "^3.6.4",
|
|
40
40
|
"esbuild": "^0.27.2",
|