@rivium/push-web 0.1.4 → 0.1.6
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/README.md +55 -0
- package/dist/inbox.d.ts +180 -0
- package/dist/index.d.ts +51 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/internal.d.ts +46 -0
- package/dist/version.d.ts +2 -0
- package/package.json +5 -2
- package/service-worker.js +7 -2
- package/dist/test/__mocks__/pn-protocol.d.ts +0 -54
- package/dist/test/rivium-push.test.d.ts +0 -4
- package/dist/test/setup.d.ts +0 -5
package/README.md
CHANGED
|
@@ -89,9 +89,30 @@ const riviumPush = new RiviumPush({
|
|
|
89
89
|
mqttQos: 1, // Optional - MQTT QoS level (default: 1)
|
|
90
90
|
maxReconnectAttempts: 10, // Optional - max reconnect attempts (default: 10)
|
|
91
91
|
logLevel: RiviumPushLogLevel.ERROR, // Optional - log level
|
|
92
|
+
appVersion: '2.0.0', // Optional - your app version (segment filter)
|
|
93
|
+
autoRefresh: true, // Optional - background re-registration (default: true)
|
|
92
94
|
});
|
|
93
95
|
```
|
|
94
96
|
|
|
97
|
+
### Automatic refresh
|
|
98
|
+
|
|
99
|
+
With `autoRefresh` on (the default), a browser that has registered before is
|
|
100
|
+
silently re-registered on page load when its registration is likely stale: 24
|
|
101
|
+
hours have passed, the push subscription endpoint changed, or `appVersion`, the
|
|
102
|
+
SDK version or the user ID changed. It never shows a permission prompt (it only
|
|
103
|
+
runs when permission is already granted) and never throws. Calling `register()`
|
|
104
|
+
yourself still always registers.
|
|
105
|
+
|
|
106
|
+
### SDK version
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import { SDK_VERSION } from '@rivium/push-web';
|
|
110
|
+
console.log(SDK_VERSION); // "0.1.5"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The SDK reports `sdkName` / `sdkVersion`, the OS and the browser (as
|
|
114
|
+
`osVersion` / `deviceModel`) when registering, so they show up in the dashboard.
|
|
115
|
+
|
|
95
116
|
## Callbacks
|
|
96
117
|
|
|
97
118
|
All event handlers return an unsubscribe function.
|
|
@@ -246,6 +267,40 @@ await riviumPush.unregister();
|
|
|
246
267
|
</html>
|
|
247
268
|
```
|
|
248
269
|
|
|
270
|
+
## Message Inbox
|
|
271
|
+
|
|
272
|
+
Inbox messages are stored server-side and stay available until the user reads,
|
|
273
|
+
archives or deletes them. `riviumPush.inbox` needs a registered device.
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
// Live updates (an inbox message never shows a notification)
|
|
277
|
+
riviumPush.inbox.onMessage((message) => console.log(message.content.title));
|
|
278
|
+
riviumPush.inbox.onUnreadCountChange((count) => setBadge(count));
|
|
279
|
+
|
|
280
|
+
// Read
|
|
281
|
+
const { messages, total, unreadCount } = await riviumPush.inbox.getMessages({
|
|
282
|
+
status: 'unread',
|
|
283
|
+
limit: 20,
|
|
284
|
+
});
|
|
285
|
+
const cached = riviumPush.inbox.getCachedMessages(); // instant, no network
|
|
286
|
+
|
|
287
|
+
// Write
|
|
288
|
+
await riviumPush.inbox.markAsRead(messages[0].id);
|
|
289
|
+
await riviumPush.inbox.archiveMessage(messages[0].id);
|
|
290
|
+
await riviumPush.inbox.deleteMessage(messages[0].id);
|
|
291
|
+
await riviumPush.inbox.markMultiple(['id-1', 'id-2'], 'read');
|
|
292
|
+
await riviumPush.inbox.markAllAsRead();
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Messages are cached per device and restored on the next page load. The cache is
|
|
296
|
+
dropped when the user changes (`setUserId` / `clearUserId`).
|
|
297
|
+
|
|
298
|
+
## Delivery Tracking
|
|
299
|
+
|
|
300
|
+
Notifications are confirmed as `delivered` automatically: Web Push arrivals by
|
|
301
|
+
the service worker, and messages received over the real-time connection on an
|
|
302
|
+
open page by the SDK. No code needed.
|
|
303
|
+
|
|
249
304
|
## Browser Support
|
|
250
305
|
|
|
251
306
|
- Chrome 50+ (Desktop & Android)
|
package/dist/inbox.d.ts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Inbox for the RiviumPush Web SDK.
|
|
3
|
+
*
|
|
4
|
+
* An inbox message is a message that is stored server-side and stays
|
|
5
|
+
* available to the app until the user reads, archives or deletes it —
|
|
6
|
+
* independent of whether a notification was ever displayed.
|
|
7
|
+
*
|
|
8
|
+
* Reachable as `push.inbox` once the SDK is constructed; network calls need
|
|
9
|
+
* a registered device (`register()`).
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
/** Status of an inbox message. */
|
|
14
|
+
export type InboxMessageStatus = 'unread' | 'read' | 'archived' | 'deleted';
|
|
15
|
+
/** Content of an inbox message. */
|
|
16
|
+
export interface InboxContent {
|
|
17
|
+
/** Message title */
|
|
18
|
+
title: string;
|
|
19
|
+
/** Message body */
|
|
20
|
+
body: string;
|
|
21
|
+
/** Large image URL */
|
|
22
|
+
imageUrl?: string;
|
|
23
|
+
/** Icon/avatar URL */
|
|
24
|
+
iconUrl?: string;
|
|
25
|
+
/** Deep link URL */
|
|
26
|
+
deepLink?: string;
|
|
27
|
+
/** Custom data payload */
|
|
28
|
+
data?: Record<string, any>;
|
|
29
|
+
}
|
|
30
|
+
/** A single inbox message. */
|
|
31
|
+
export interface InboxMessage {
|
|
32
|
+
/** Server-side message id */
|
|
33
|
+
id: string;
|
|
34
|
+
/** User this message belongs to, when addressed by user */
|
|
35
|
+
userId?: string | null;
|
|
36
|
+
/** Device this message belongs to, when addressed by device */
|
|
37
|
+
deviceId?: string | null;
|
|
38
|
+
/** Message content */
|
|
39
|
+
content: InboxContent;
|
|
40
|
+
/** Current status (defaults to `unread`) */
|
|
41
|
+
status: InboxMessageStatus;
|
|
42
|
+
/** Optional category, e.g. "promotions" */
|
|
43
|
+
category?: string | null;
|
|
44
|
+
/** ISO date after which the message is no longer returned */
|
|
45
|
+
expiresAt?: string | null;
|
|
46
|
+
/** ISO date the message was marked read */
|
|
47
|
+
readAt?: string | null;
|
|
48
|
+
/** ISO date the message was created */
|
|
49
|
+
createdAt: string;
|
|
50
|
+
/** ISO date the message was last updated */
|
|
51
|
+
updatedAt?: string | null;
|
|
52
|
+
}
|
|
53
|
+
/** Filter options for {@link RiviumInbox.getMessages}. */
|
|
54
|
+
export interface InboxFilter {
|
|
55
|
+
/** Only messages with this status */
|
|
56
|
+
status?: InboxMessageStatus;
|
|
57
|
+
/** Only messages in this category */
|
|
58
|
+
category?: string;
|
|
59
|
+
/** Page size (default: 50) */
|
|
60
|
+
limit?: number;
|
|
61
|
+
/** Page offset (default: 0) */
|
|
62
|
+
offset?: number;
|
|
63
|
+
/** Preferred locale for localized content, e.g. "fr" */
|
|
64
|
+
locale?: string;
|
|
65
|
+
}
|
|
66
|
+
/** Response of {@link RiviumInbox.getMessages}. */
|
|
67
|
+
export interface InboxMessagesResponse {
|
|
68
|
+
/** The messages for this page */
|
|
69
|
+
messages: InboxMessage[];
|
|
70
|
+
/** Total number of messages matching the filter */
|
|
71
|
+
total: number;
|
|
72
|
+
/** Number of unread messages */
|
|
73
|
+
unreadCount: number;
|
|
74
|
+
}
|
|
75
|
+
/** Called when a new inbox message arrives in real time. */
|
|
76
|
+
export type OnInboxMessageCallback = (message: InboxMessage) => void;
|
|
77
|
+
/** Called when the status of a message changes. */
|
|
78
|
+
export type OnInboxStatusChangeCallback = (messageId: string, status: InboxMessageStatus) => void;
|
|
79
|
+
/** Called whenever the unread count changes. */
|
|
80
|
+
export type OnInboxUnreadCountCallback = (count: number) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Wiring the SDK passes to the inbox. Not part of the public API.
|
|
83
|
+
* @internal
|
|
84
|
+
*/
|
|
85
|
+
export interface InboxDependencies {
|
|
86
|
+
serverUrl: string;
|
|
87
|
+
getApiKey: () => string;
|
|
88
|
+
getDeviceId: () => string | null;
|
|
89
|
+
getUserId: () => string | null;
|
|
90
|
+
log: (level: number, message: string, ...args: any[]) => void;
|
|
91
|
+
createError: (kind: 'network' | 'server' | 'notRegistered', details: string) => Error;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Message Inbox client.
|
|
95
|
+
*
|
|
96
|
+
* ```typescript
|
|
97
|
+
* push.inbox.onMessage((message) => render(message));
|
|
98
|
+
* const { messages, unreadCount } = await push.inbox.getMessages({ status: 'unread' });
|
|
99
|
+
* await push.inbox.markAsRead(messages[0].id);
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare class RiviumInbox {
|
|
103
|
+
private readonly deps;
|
|
104
|
+
private cachedMessages;
|
|
105
|
+
private unreadCount;
|
|
106
|
+
/** Device the in-memory cache was loaded for, so identity changes reload. */
|
|
107
|
+
private loadedKey;
|
|
108
|
+
private onMessageCallback;
|
|
109
|
+
private onStatusChangeCallback;
|
|
110
|
+
private onUnreadCountCallback;
|
|
111
|
+
/** Real-time updates can arrive twice (socket + service worker). */
|
|
112
|
+
private handledIncomingIds;
|
|
113
|
+
/** @internal */
|
|
114
|
+
constructor(deps: InboxDependencies);
|
|
115
|
+
/**
|
|
116
|
+
* Listen for inbox messages arriving in real time.
|
|
117
|
+
* Returns a function that removes the listener.
|
|
118
|
+
*/
|
|
119
|
+
onMessage(callback: OnInboxMessageCallback): () => void;
|
|
120
|
+
/**
|
|
121
|
+
* Listen for status changes (read, archived, deleted).
|
|
122
|
+
* Returns a function that removes the listener.
|
|
123
|
+
*/
|
|
124
|
+
onStatusChange(callback: OnInboxStatusChangeCallback): () => void;
|
|
125
|
+
/**
|
|
126
|
+
* Listen for unread-count changes — useful to drive a badge.
|
|
127
|
+
* Returns a function that removes the listener.
|
|
128
|
+
*/
|
|
129
|
+
onUnreadCountChange(callback: OnInboxUnreadCountCallback): () => void;
|
|
130
|
+
/**
|
|
131
|
+
* Fetch inbox messages from the server. Messages are addressed by userId
|
|
132
|
+
* when one is set, otherwise by deviceId. The result is cached locally.
|
|
133
|
+
*/
|
|
134
|
+
getMessages(filter?: InboxFilter): Promise<InboxMessagesResponse>;
|
|
135
|
+
/** Fetch a single message by id. */
|
|
136
|
+
getMessage(messageId: string): Promise<InboxMessage>;
|
|
137
|
+
/** Messages cached locally — available immediately, no network call. */
|
|
138
|
+
getCachedMessages(): InboxMessage[];
|
|
139
|
+
/** The last known unread count, without a network call. */
|
|
140
|
+
getUnreadCount(): number;
|
|
141
|
+
/** Ask the server for the current unread count. */
|
|
142
|
+
fetchUnreadCount(): Promise<number>;
|
|
143
|
+
/** Mark a message as read. */
|
|
144
|
+
markAsRead(messageId: string): Promise<void>;
|
|
145
|
+
/** Archive a message. */
|
|
146
|
+
archiveMessage(messageId: string): Promise<void>;
|
|
147
|
+
/** Delete a message. */
|
|
148
|
+
deleteMessage(messageId: string): Promise<void>;
|
|
149
|
+
/** Apply a status to several messages at once. */
|
|
150
|
+
markMultiple(messageIds: string[], status: InboxMessageStatus): Promise<void>;
|
|
151
|
+
/** Mark every message in this inbox as read. */
|
|
152
|
+
markAllAsRead(): Promise<void>;
|
|
153
|
+
/** Drop the local cache (in memory and in storage). */
|
|
154
|
+
clearCache(): void;
|
|
155
|
+
/**
|
|
156
|
+
* Add a message that arrived in real time to the cache and notify listeners.
|
|
157
|
+
* Called by the SDK for `inbox_update` payloads; safe to call directly.
|
|
158
|
+
*/
|
|
159
|
+
handleIncomingMessage(message: InboxMessage): void;
|
|
160
|
+
/**
|
|
161
|
+
* Turn a raw `inbox_update` payload into an InboxMessage and handle it.
|
|
162
|
+
* @internal
|
|
163
|
+
*/
|
|
164
|
+
handleIncomingPayload(payload: Record<string, any>): void;
|
|
165
|
+
/**
|
|
166
|
+
* Point the inbox at a new identity. The cache belongs to the previous
|
|
167
|
+
* user, so it is dropped and listeners see an unread count of 0.
|
|
168
|
+
* @internal
|
|
169
|
+
*/
|
|
170
|
+
onIdentityChanged(): void;
|
|
171
|
+
private updateStatus;
|
|
172
|
+
/** Messages are addressed by user when one is known, by device otherwise. */
|
|
173
|
+
private identity;
|
|
174
|
+
private request;
|
|
175
|
+
private setUnreadCount;
|
|
176
|
+
private storageKey;
|
|
177
|
+
/** Restores the persisted cache the first time it is needed per device. */
|
|
178
|
+
private ensureLoaded;
|
|
179
|
+
private persist;
|
|
180
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @packageDocumentation
|
|
16
16
|
*/
|
|
17
|
+
import { SDK_NAME, SDK_VERSION } from './version';
|
|
18
|
+
import { RiviumInbox } from './inbox';
|
|
19
|
+
export { SDK_NAME, SDK_VERSION };
|
|
20
|
+
export { RiviumInbox } from './inbox';
|
|
21
|
+
export type { InboxContent, InboxFilter, InboxMessage, InboxMessagesResponse, InboxMessageStatus, OnInboxMessageCallback, OnInboxStatusChangeCallback, OnInboxUnreadCountCallback, } from './inbox';
|
|
17
22
|
/**
|
|
18
23
|
* Standardized error codes for RiviumPush SDK.
|
|
19
24
|
* These codes help developers identify and handle specific error scenarios.
|
|
@@ -198,6 +203,15 @@ export interface RiviumPushConfig {
|
|
|
198
203
|
* this at init time from your build config.
|
|
199
204
|
*/
|
|
200
205
|
appVersion?: string;
|
|
206
|
+
/**
|
|
207
|
+
* Keep the server-side registration fresh without calling register() on
|
|
208
|
+
* every page load (default: true). On startup, a browser that registered
|
|
209
|
+
* before is silently re-registered in the background when 24h have passed,
|
|
210
|
+
* the push subscription endpoint changed, or `appVersion`, the SDK version
|
|
211
|
+
* or the userId changed. Never prompts: it only runs when notification
|
|
212
|
+
* permission is already granted. Errors are logged, never thrown.
|
|
213
|
+
*/
|
|
214
|
+
autoRefresh?: boolean;
|
|
201
215
|
}
|
|
202
216
|
/**
|
|
203
217
|
* Notification action button
|
|
@@ -368,6 +382,14 @@ declare class RiviumPush {
|
|
|
368
382
|
private onReconnectingCallback;
|
|
369
383
|
private onNetworkStateCallback;
|
|
370
384
|
private onAppStateCallback;
|
|
385
|
+
private registerRequested;
|
|
386
|
+
private ackedMessageIds;
|
|
387
|
+
private receivedMessageIds;
|
|
388
|
+
/**
|
|
389
|
+
* Message Inbox. Listeners can be attached immediately; network calls need
|
|
390
|
+
* a registered device.
|
|
391
|
+
*/
|
|
392
|
+
readonly inbox: RiviumInbox;
|
|
371
393
|
constructor(config: RiviumPushConfig);
|
|
372
394
|
/**
|
|
373
395
|
* Fetch MQTT and VAPID configuration from server
|
|
@@ -451,8 +473,12 @@ declare class RiviumPush {
|
|
|
451
473
|
setUserId(userId: string): Promise<void>;
|
|
452
474
|
/**
|
|
453
475
|
* Clear user ID. Call this on logout.
|
|
476
|
+
*
|
|
477
|
+
* Also detaches the user on the server. Registration treats a missing
|
|
478
|
+
* userId as "keep the existing one", so clearing only local state would
|
|
479
|
+
* leave this browser receiving the logged-out user's notifications.
|
|
454
480
|
*/
|
|
455
|
-
clearUserId(): void
|
|
481
|
+
clearUserId(): Promise<void>;
|
|
456
482
|
/**
|
|
457
483
|
* Get the currently-stored userId, if any. Survives page reloads.
|
|
458
484
|
*/
|
|
@@ -569,9 +595,33 @@ declare class RiviumPush {
|
|
|
569
595
|
private disconnectFromGateway;
|
|
570
596
|
private scheduleReconnect;
|
|
571
597
|
private handleMqttMessage;
|
|
598
|
+
/**
|
|
599
|
+
* POST /receipts/delivered for a message received on this page. Deduped per
|
|
600
|
+
* messageId (the server is idempotent too) and retried a bounded number of
|
|
601
|
+
* times on network errors, 429 and 5xx. Never throws.
|
|
602
|
+
*/
|
|
603
|
+
private reportDelivered;
|
|
604
|
+
private saveRegistrationState;
|
|
605
|
+
/**
|
|
606
|
+
* Silently re-register a browser that registered before, when the server's
|
|
607
|
+
* copy is likely stale. Never prompts for permission and never throws.
|
|
608
|
+
*/
|
|
609
|
+
private maybeAutoRefresh;
|
|
572
610
|
private normalizeMessage;
|
|
573
611
|
private getLocalizedContent;
|
|
574
612
|
private handleBadge;
|
|
613
|
+
/**
|
|
614
|
+
* Records a messageId as handed to the app. Returns false if it already was.
|
|
615
|
+
* Messages without an id can't be deduped and always pass.
|
|
616
|
+
*/
|
|
617
|
+
private markReceived;
|
|
618
|
+
/**
|
|
619
|
+
* `inbox_update` payloads update the Message Inbox instead of being shown
|
|
620
|
+
* as a notification. Deduped by message id like delivery acks, so a payload
|
|
621
|
+
* arriving over both the real-time channel and the service worker counts
|
|
622
|
+
* once. Returns true when the payload was an inbox update.
|
|
623
|
+
*/
|
|
624
|
+
private routeInboxUpdate;
|
|
575
625
|
private handleServiceWorkerMessage;
|
|
576
626
|
private showRichNotification;
|
|
577
627
|
private updateFaviconBadge;
|