@theshelf/notification 0.3.2 → 0.4.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/README.md +18 -30
- package/dist/NotificationService.d.ts +3 -2
- package/dist/NotificationService.js +65 -11
- package/dist/definitions/interfaces.d.ts +1 -0
- package/dist/drivers/Memory.d.ts +1 -0
- package/dist/drivers/Memory.js +1 -0
- package/dist/index.d.ts +1 -1
- package/package.json +5 -4
- package/dist/drivers/WebPush.d.ts +0 -19
- package/dist/drivers/WebPush.js +0 -52
package/README.md
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
# Notification | The Shelf
|
|
2
|
+
# Notification core | The Shelf
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
This package is based on a push notification model.
|
|
4
|
+
This package contains the core implementation for the notification system.
|
|
7
5
|
|
|
8
6
|
## Installation
|
|
9
7
|
|
|
@@ -11,43 +9,20 @@ This package is based on a push notification model.
|
|
|
11
9
|
npm install @theshelf/notification
|
|
12
10
|
```
|
|
13
11
|
|
|
14
|
-
## Drivers
|
|
15
|
-
|
|
16
|
-
Currently, there are two drivers available:
|
|
17
|
-
|
|
18
|
-
* **Memory** - non-persistent in memory notifications (suited for testing).
|
|
19
|
-
* **WebPush** - web browser based push notifications.
|
|
20
|
-
|
|
21
12
|
## How to use
|
|
22
13
|
|
|
23
14
|
The basic set up looks like this.
|
|
24
15
|
|
|
25
16
|
```ts
|
|
26
|
-
import NotificationService, { MemoryDriver
|
|
17
|
+
import NotificationService, { MemoryDriver } from '@theshelf/notification';
|
|
27
18
|
|
|
28
|
-
const driver = new
|
|
19
|
+
const driver = new MemoryDriver();
|
|
29
20
|
const notificationService = new NotificationService(driver);
|
|
30
21
|
|
|
31
22
|
// Perform operations with the notificationService instance
|
|
32
23
|
```
|
|
33
24
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
#### Memory driver
|
|
37
|
-
|
|
38
|
-
No configuration options.
|
|
39
|
-
|
|
40
|
-
#### WebPush driver
|
|
41
|
-
|
|
42
|
-
```ts
|
|
43
|
-
type WebPushConfiguration = { // Vapid details
|
|
44
|
-
subject: string;
|
|
45
|
-
publicKey: string;
|
|
46
|
-
privateKey: string;
|
|
47
|
-
};
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### Operations
|
|
25
|
+
## Operations
|
|
51
26
|
|
|
52
27
|
```ts
|
|
53
28
|
// Open connection
|
|
@@ -67,3 +42,16 @@ await notificationService.unsubscribe(recipientId);
|
|
|
67
42
|
// Throws SubscriptionNotFound if subscription not found.
|
|
68
43
|
await notificationService.sendNotification(recipientId, title, body);
|
|
69
44
|
```
|
|
45
|
+
|
|
46
|
+
## Drivers
|
|
47
|
+
|
|
48
|
+
There is one driver included in this package. Other drivers are available in separate packages.
|
|
49
|
+
|
|
50
|
+
### Memory
|
|
51
|
+
|
|
52
|
+
This driver is a non-persistent in memory implementation (suitable for testing purposes). It doesn't have any configuration options, but has an additional operation.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// Clear the subscriptions
|
|
56
|
+
driver.clear();
|
|
57
|
+
```
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type Logger from '@theshelf/logging';
|
|
1
2
|
import type { Driver } from './definitions/interfaces.js';
|
|
2
|
-
export default class NotificationService
|
|
3
|
+
export default class NotificationService {
|
|
3
4
|
#private;
|
|
4
|
-
constructor(driver: Driver);
|
|
5
|
+
constructor(driver: Driver, logger?: Logger);
|
|
5
6
|
get connected(): boolean;
|
|
6
7
|
get subscriptions(): Map<string, unknown>;
|
|
7
8
|
connect(): Promise<void>;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import NotConnected from './errors/NotConnected.js';
|
|
1
2
|
export default class NotificationService {
|
|
2
3
|
#driver;
|
|
3
|
-
|
|
4
|
+
#logger;
|
|
5
|
+
#logPrefix;
|
|
6
|
+
constructor(driver, logger) {
|
|
4
7
|
this.#driver = driver;
|
|
8
|
+
this.#logger = logger?.for(NotificationService.name);
|
|
9
|
+
this.#logPrefix = `${this.#driver.name} ->`;
|
|
5
10
|
}
|
|
6
11
|
get connected() {
|
|
7
12
|
return this.#driver.connected;
|
|
@@ -9,19 +14,68 @@ export default class NotificationService {
|
|
|
9
14
|
get subscriptions() {
|
|
10
15
|
return new Map(this.#driver.subscriptions);
|
|
11
16
|
}
|
|
12
|
-
connect() {
|
|
13
|
-
|
|
17
|
+
async connect() {
|
|
18
|
+
if (this.connected === true) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
this.#logger?.debug(this.#logPrefix, 'Connecting');
|
|
22
|
+
try {
|
|
23
|
+
await this.#driver.connect();
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
this.#logger?.error(this.#logPrefix, 'Connect failed with error', error);
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
14
29
|
}
|
|
15
|
-
disconnect() {
|
|
16
|
-
|
|
30
|
+
async disconnect() {
|
|
31
|
+
if (this.connected === false) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.#logger?.debug(this.#logPrefix, 'Disconnecting');
|
|
35
|
+
try {
|
|
36
|
+
return await this.#driver.disconnect();
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
this.#logger?.error(this.#logPrefix, 'Disconnect failed with error', error);
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
17
42
|
}
|
|
18
|
-
subscribe(recipientId, subscription) {
|
|
19
|
-
|
|
43
|
+
async subscribe(recipientId, subscription) {
|
|
44
|
+
this.#logger?.debug(this.#logPrefix, 'Subscribing with id', recipientId);
|
|
45
|
+
try {
|
|
46
|
+
this.#validateConnection();
|
|
47
|
+
return await this.#driver.subscribe(recipientId, subscription);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
this.#logger?.error(this.#logPrefix, 'Subscribe with id', recipientId, 'failed with error', error);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
20
53
|
}
|
|
21
|
-
unsubscribe(recipientId) {
|
|
22
|
-
|
|
54
|
+
async unsubscribe(recipientId) {
|
|
55
|
+
this.#logger?.debug(this.#logPrefix, 'Unsubscribing with id', recipientId);
|
|
56
|
+
try {
|
|
57
|
+
this.#validateConnection();
|
|
58
|
+
return await this.#driver.unsubscribe(recipientId);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
this.#logger?.error(this.#logPrefix, 'Unsubscribe with id', recipientId, 'failed with error', error);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
23
64
|
}
|
|
24
|
-
sendNotification(recipientId, title, message) {
|
|
25
|
-
|
|
65
|
+
async sendNotification(recipientId, title, message) {
|
|
66
|
+
this.#logger?.debug(this.#logPrefix, 'Sending notification to id', recipientId);
|
|
67
|
+
try {
|
|
68
|
+
this.#validateConnection();
|
|
69
|
+
return await this.#driver.sendNotification(recipientId, title, message);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
this.#logger?.error(this.#logPrefix, 'Send notification to id', recipientId, 'failed with error', error);
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
#validateConnection() {
|
|
77
|
+
if (this.connected === false) {
|
|
78
|
+
throw new NotConnected();
|
|
79
|
+
}
|
|
26
80
|
}
|
|
27
81
|
}
|
package/dist/drivers/Memory.d.ts
CHANGED
package/dist/drivers/Memory.js
CHANGED
|
@@ -3,6 +3,7 @@ import SubscriptionNotFound from '../errors/SubscriptionNotFound.js';
|
|
|
3
3
|
export default class Memory {
|
|
4
4
|
#subscriptions = new Map();
|
|
5
5
|
#connected = false;
|
|
6
|
+
get name() { return Memory.name; }
|
|
6
7
|
get connected() { return this.#connected; }
|
|
7
8
|
get subscriptions() {
|
|
8
9
|
if (this.#connected === false) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type { Driver } from './definitions/interfaces.js';
|
|
2
2
|
export { default as NotConnected } from './errors/NotConnected.js';
|
|
3
3
|
export { default as NotificationError } from './errors/NotificationError.js';
|
|
4
4
|
export { default as SubscriptionNotFound } from './errors/SubscriptionNotFound.js';
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theshelf/notification",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "git+https://github.com/MaskingTechnology/theshelf.git"
|
|
8
8
|
},
|
|
9
|
+
"license": "MIT",
|
|
9
10
|
"scripts": {
|
|
10
11
|
"build": "tsc",
|
|
11
12
|
"clean": "rimraf dist",
|
|
@@ -19,9 +20,9 @@
|
|
|
19
20
|
"README.md",
|
|
20
21
|
"dist"
|
|
21
22
|
],
|
|
22
|
-
"types": "dist/index.d.ts",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
23
24
|
"exports": "./dist/index.js",
|
|
24
|
-
"
|
|
25
|
-
"
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@theshelf/logging": "^0.4.0"
|
|
26
27
|
}
|
|
27
28
|
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { PushSubscription } from 'web-push';
|
|
2
|
-
import type { Driver } from '../definitions/interfaces.js';
|
|
3
|
-
type WebPushConfiguration = {
|
|
4
|
-
subject: string;
|
|
5
|
-
publicKey: string;
|
|
6
|
-
privateKey: string;
|
|
7
|
-
};
|
|
8
|
-
export default class WebPush implements Driver {
|
|
9
|
-
#private;
|
|
10
|
-
constructor(configuration: WebPushConfiguration);
|
|
11
|
-
get connected(): boolean;
|
|
12
|
-
get subscriptions(): Map<string, PushSubscription>;
|
|
13
|
-
connect(): Promise<void>;
|
|
14
|
-
disconnect(): Promise<void>;
|
|
15
|
-
subscribe(recipientId: string, subscription: PushSubscription): Promise<void>;
|
|
16
|
-
unsubscribe(recipientId: string): Promise<void>;
|
|
17
|
-
sendNotification(recipientId: string, title: string, body: string): Promise<void>;
|
|
18
|
-
}
|
|
19
|
-
export {};
|
package/dist/drivers/WebPush.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import webpush from 'web-push';
|
|
2
|
-
import NotConnected from '../errors/NotConnected.js';
|
|
3
|
-
import SubscriptionNotFound from '../errors/SubscriptionNotFound.js';
|
|
4
|
-
export default class WebPush {
|
|
5
|
-
#configuration;
|
|
6
|
-
#subscriptions;
|
|
7
|
-
constructor(configuration) {
|
|
8
|
-
this.#configuration = configuration;
|
|
9
|
-
}
|
|
10
|
-
get connected() {
|
|
11
|
-
return this.#subscriptions !== undefined;
|
|
12
|
-
}
|
|
13
|
-
get subscriptions() {
|
|
14
|
-
return this.#getSubscriptions();
|
|
15
|
-
}
|
|
16
|
-
async connect() {
|
|
17
|
-
this.#subscriptions = new Map();
|
|
18
|
-
webpush.setVapidDetails(this.#configuration.subject, this.#configuration.publicKey, this.#configuration.privateKey);
|
|
19
|
-
}
|
|
20
|
-
async disconnect() {
|
|
21
|
-
this.#subscriptions = undefined;
|
|
22
|
-
}
|
|
23
|
-
async subscribe(recipientId, subscription) {
|
|
24
|
-
const subscriptions = this.#getSubscriptions();
|
|
25
|
-
subscriptions.set(recipientId, subscription);
|
|
26
|
-
}
|
|
27
|
-
async unsubscribe(recipientId) {
|
|
28
|
-
const subscriptions = this.#getSubscriptions();
|
|
29
|
-
if (subscriptions.has(recipientId) === false) {
|
|
30
|
-
throw new SubscriptionNotFound(recipientId);
|
|
31
|
-
}
|
|
32
|
-
subscriptions.delete(recipientId);
|
|
33
|
-
}
|
|
34
|
-
async sendNotification(recipientId, title, body) {
|
|
35
|
-
const subscription = this.#getSubscription(recipientId);
|
|
36
|
-
await webpush.sendNotification(subscription, JSON.stringify({ title, body }));
|
|
37
|
-
}
|
|
38
|
-
#getSubscriptions() {
|
|
39
|
-
if (this.#subscriptions === undefined) {
|
|
40
|
-
throw new NotConnected();
|
|
41
|
-
}
|
|
42
|
-
return this.#subscriptions;
|
|
43
|
-
}
|
|
44
|
-
#getSubscription(recipientId) {
|
|
45
|
-
const subscriptions = this.#getSubscriptions();
|
|
46
|
-
const subscription = subscriptions.get(recipientId);
|
|
47
|
-
if (subscription === undefined) {
|
|
48
|
-
throw new SubscriptionNotFound(recipientId);
|
|
49
|
-
}
|
|
50
|
-
return subscription;
|
|
51
|
-
}
|
|
52
|
-
}
|