@rivium/push-web 0.1.7 → 0.1.8
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 +19 -0
- package/dist/index.d.ts +9 -0
- 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/version.d.ts +1 -1
- package/package.json +1 -1
- package/service-worker.js +150 -64
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const SDK_NAME = "web";
|
|
2
|
-
export declare const SDK_VERSION = "0.1.
|
|
2
|
+
export declare const SDK_VERSION = "0.1.8";
|
package/package.json
CHANGED
package/service-worker.js
CHANGED
|
@@ -6,30 +6,100 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
// Cache name for offline support
|
|
9
|
-
const CACHE_NAME = 'rivium-push-v0.1.
|
|
9
|
+
const CACHE_NAME = 'rivium-push-v0.1.8';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Where the worker gets its API key and device id.
|
|
13
13
|
*
|
|
14
|
-
* A service worker is terminated between pushes, so
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* A service worker is terminated between pushes, so nothing can be kept in
|
|
15
|
+
* memory. Two durable places hold the config, and both are read:
|
|
16
|
+
*
|
|
17
|
+
* 1. The registration URL's query string. The browser persists the script
|
|
18
|
+
* URL, so this is available immediately on every wake-up.
|
|
19
|
+
* 2. IndexedDB (`rivium-push` / `config`), written by the SDK on every load.
|
|
20
|
+
* This is the fallback for a worker registered WITHOUT the query string -
|
|
21
|
+
* an app (or another library, or a hot reload in development) that calls
|
|
22
|
+
* `navigator.serviceWorker.register('/rivium-push-sw.js')` itself. Such a
|
|
23
|
+
* worker still shows notifications, but used to silently stop confirming
|
|
24
|
+
* delivery and stop re-registering a changed subscription.
|
|
25
|
+
*
|
|
26
|
+
* The URL wins field by field, so an explicit registration still decides.
|
|
18
27
|
*/
|
|
19
|
-
const
|
|
28
|
+
const RIVIUM_DB_NAME = 'rivium-push';
|
|
29
|
+
const RIVIUM_DB_STORE = 'config';
|
|
30
|
+
const RIVIUM_DB_KEY = 'config';
|
|
31
|
+
const RIVIUM_DEFAULT_SERVER_URL = 'https://push-api.rivium.co';
|
|
32
|
+
|
|
33
|
+
function riviumConfigFromUrl() {
|
|
20
34
|
try {
|
|
21
35
|
const params = new URL(self.location.href).searchParams;
|
|
22
36
|
return {
|
|
23
37
|
apiKey: params.get('riviumApiKey') || null,
|
|
24
|
-
serverUrl: params.get('riviumServerUrl') ||
|
|
38
|
+
serverUrl: params.get('riviumServerUrl') || null,
|
|
25
39
|
deviceId: params.get('riviumDeviceId') || null,
|
|
26
40
|
// Added in 0.1.5. SDKs older than 0.1.5 don't pass it.
|
|
27
41
|
sdkVersion: params.get('riviumSdkVersion') || null,
|
|
28
42
|
};
|
|
29
43
|
} catch (e) {
|
|
30
|
-
return { apiKey: null, serverUrl:
|
|
44
|
+
return { apiKey: null, serverUrl: null, deviceId: null, sdkVersion: null };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** The SDK's last known config, or null. Never rejects: storage may be unavailable. */
|
|
49
|
+
function riviumConfigFromStorage() {
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
let request;
|
|
52
|
+
try {
|
|
53
|
+
request = indexedDB.open(RIVIUM_DB_NAME, 1);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
return resolve(null);
|
|
56
|
+
}
|
|
57
|
+
// The SDK creates the store; a worker that gets here first must not leave
|
|
58
|
+
// an empty database behind with a half-made schema.
|
|
59
|
+
request.onupgradeneeded = () => {
|
|
60
|
+
try {
|
|
61
|
+
request.result.createObjectStore(RIVIUM_DB_STORE);
|
|
62
|
+
} catch (e) {
|
|
63
|
+
/* already there */
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
request.onerror = () => resolve(null);
|
|
67
|
+
request.onsuccess = () => {
|
|
68
|
+
const db = request.result;
|
|
69
|
+
try {
|
|
70
|
+
const get = db.transaction(RIVIUM_DB_STORE, 'readonly').objectStore(RIVIUM_DB_STORE).get(RIVIUM_DB_KEY);
|
|
71
|
+
get.onsuccess = () => {
|
|
72
|
+
resolve(get.result || null);
|
|
73
|
+
db.close();
|
|
74
|
+
};
|
|
75
|
+
get.onerror = () => {
|
|
76
|
+
resolve(null);
|
|
77
|
+
db.close();
|
|
78
|
+
};
|
|
79
|
+
} catch (e) {
|
|
80
|
+
resolve(null);
|
|
81
|
+
db.close();
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let riviumConfigPromise = null;
|
|
88
|
+
|
|
89
|
+
/** Resolved config for this wake-up. Storage is read only when the URL is short of something. */
|
|
90
|
+
function riviumConfig() {
|
|
91
|
+
const fromUrl = riviumConfigFromUrl();
|
|
92
|
+
if (fromUrl.apiKey && fromUrl.deviceId) {
|
|
93
|
+
return Promise.resolve({ ...fromUrl, serverUrl: fromUrl.serverUrl || RIVIUM_DEFAULT_SERVER_URL });
|
|
31
94
|
}
|
|
32
|
-
|
|
95
|
+
riviumConfigPromise = riviumConfigPromise || riviumConfigFromStorage();
|
|
96
|
+
return riviumConfigPromise.then((stored) => ({
|
|
97
|
+
apiKey: fromUrl.apiKey || (stored && stored.apiKey) || null,
|
|
98
|
+
serverUrl: fromUrl.serverUrl || (stored && stored.serverUrl) || RIVIUM_DEFAULT_SERVER_URL,
|
|
99
|
+
deviceId: fromUrl.deviceId || (stored && stored.deviceId) || null,
|
|
100
|
+
sdkVersion: fromUrl.sdkVersion || (stored && stored.sdkVersion) || null,
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
33
103
|
|
|
34
104
|
/**
|
|
35
105
|
* Confirm delivery to Rivium Push.
|
|
@@ -42,38 +112,47 @@ const RIVIUM_CONFIG = (() => {
|
|
|
42
112
|
* Best-effort: a failure here must never stop the notification being shown.
|
|
43
113
|
*/
|
|
44
114
|
function riviumReportDelivered(messageId) {
|
|
45
|
-
if (!messageId
|
|
46
|
-
console.warn('[RiviumPush SW] Delivery ack skipped
|
|
47
|
-
messageId: messageId || null,
|
|
48
|
-
hasApiKey: !!RIVIUM_CONFIG.apiKey,
|
|
49
|
-
hasDeviceId: !!RIVIUM_CONFIG.deviceId,
|
|
50
|
-
});
|
|
115
|
+
if (!messageId) {
|
|
116
|
+
console.warn('[RiviumPush SW] Delivery ack skipped - the push carried no message id');
|
|
51
117
|
return Promise.resolve();
|
|
52
118
|
}
|
|
53
119
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
120
|
+
return riviumConfig().then((config) => {
|
|
121
|
+
if (!config.apiKey || !config.deviceId) {
|
|
122
|
+
console.warn(
|
|
123
|
+
'[RiviumPush SW] Delivery ack skipped - no SDK config in the worker URL or in storage: ' +
|
|
124
|
+
(!config.apiKey ? 'apiKey' : '') +
|
|
125
|
+
(!config.apiKey && !config.deviceId ? ' and ' : '') +
|
|
126
|
+
(!config.deviceId ? 'deviceId' : '') +
|
|
127
|
+
' missing. Register the worker through the SDK (init/register) so it can confirm delivery.',
|
|
128
|
+
);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// No `keepalive`: event.waitUntil already holds the worker open, and
|
|
133
|
+
// keepalive is unreliable for fetches issued from a service worker.
|
|
134
|
+
return fetch(`${config.serverUrl}/receipts/delivered`, {
|
|
135
|
+
method: 'POST',
|
|
136
|
+
headers: {
|
|
137
|
+
'Content-Type': 'application/json',
|
|
138
|
+
'x-api-key': config.apiKey,
|
|
139
|
+
},
|
|
140
|
+
body: JSON.stringify({ messageId, deviceId: config.deviceId }),
|
|
73
141
|
})
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
142
|
+
.then((res) => {
|
|
143
|
+
// A non-2xx is a failure - resolving on it would hide the problem the
|
|
144
|
+
// same way the server used to hide an ack for a receipt that did not
|
|
145
|
+
// exist yet.
|
|
146
|
+
if (!res.ok) {
|
|
147
|
+
console.warn('[RiviumPush SW] Delivery ack rejected', res.status);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
console.log('[RiviumPush SW] Delivery confirmed', messageId);
|
|
151
|
+
})
|
|
152
|
+
.catch((err) => {
|
|
153
|
+
console.warn('[RiviumPush SW] Delivery ack failed:', err && err.message);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
77
156
|
}
|
|
78
157
|
|
|
79
158
|
// Install event
|
|
@@ -237,36 +316,43 @@ self.addEventListener('pushsubscriptionchange', (event) => {
|
|
|
237
316
|
event.oldSubscription.options.applicationServerKey) ||
|
|
238
317
|
null;
|
|
239
318
|
|
|
240
|
-
if (!applicationServerKey
|
|
241
|
-
console.warn(
|
|
242
|
-
'[RiviumPush SW] Cannot re-subscribe: missing VAPID key or SDK config',
|
|
243
|
-
);
|
|
319
|
+
if (!applicationServerKey) {
|
|
320
|
+
console.warn('[RiviumPush SW] Cannot re-subscribe: the old subscription carried no VAPID key');
|
|
244
321
|
return;
|
|
245
322
|
}
|
|
246
323
|
|
|
247
324
|
event.waitUntil(
|
|
248
|
-
|
|
249
|
-
.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
325
|
+
riviumConfig()
|
|
326
|
+
.then((config) => {
|
|
327
|
+
if (!config.apiKey || !config.deviceId) {
|
|
328
|
+
console.warn(
|
|
329
|
+
'[RiviumPush SW] Cannot re-subscribe: no SDK config in the worker URL or in storage',
|
|
330
|
+
);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
return self.registration.pushManager
|
|
334
|
+
.subscribe({ userVisibleOnly: true, applicationServerKey })
|
|
335
|
+
.then((subscription) =>
|
|
336
|
+
fetch(`${config.serverUrl}/devices/register`, {
|
|
337
|
+
method: 'POST',
|
|
338
|
+
headers: {
|
|
339
|
+
'Content-Type': 'application/json',
|
|
340
|
+
'x-api-key': config.apiKey,
|
|
341
|
+
},
|
|
342
|
+
body: JSON.stringify({
|
|
343
|
+
deviceId: config.deviceId,
|
|
344
|
+
platform: 'web',
|
|
345
|
+
appIdentifier: self.location.origin,
|
|
346
|
+
webPushSubscription: subscription.toJSON(),
|
|
347
|
+
// 0.1.5: SDK identity (body, not header, to avoid a CORS preflight).
|
|
348
|
+
sdkName: 'web',
|
|
349
|
+
...(config.sdkVersion ? { sdkVersion: config.sdkVersion } : {}),
|
|
350
|
+
}),
|
|
351
|
+
}),
|
|
352
|
+
)
|
|
353
|
+
.then(() => {
|
|
354
|
+
console.log('[RiviumPush SW] Re-subscribed and re-registered');
|
|
355
|
+
});
|
|
270
356
|
})
|
|
271
357
|
.catch((err) => {
|
|
272
358
|
console.error('[RiviumPush SW] Re-subscribe failed:', err && err.message);
|