@theshelf/notification 0.0.4 → 0.2.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 +20 -17
- package/dist/ConnectionManager.d.ts +9 -0
- package/dist/ConnectionManager.js +53 -0
- package/dist/NotificationService.d.ts +14 -0
- package/dist/NotificationService.js +34 -0
- package/dist/definitions/constants.d.ts +7 -0
- package/dist/definitions/constants.js +6 -0
- package/dist/definitions/interfaces.d.ts +1 -1
- package/dist/{implementations/memory → drivers}/Memory.d.ts +3 -2
- package/dist/drivers/Memory.js +43 -0
- package/dist/{implementations/webpush → drivers}/WebPush.d.ts +4 -4
- package/dist/{implementations/webpush → drivers}/WebPush.js +2 -2
- package/dist/errors/NotificationError.d.ts +1 -0
- package/dist/errors/NotificationError.js +7 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/errors/UnknownImplementation.d.ts +0 -4
- package/dist/errors/UnknownImplementation.js +0 -6
- package/dist/implementation.d.ts +0 -3
- package/dist/implementation.js +0 -14
- package/dist/implementations/memory/Memory.js +0 -46
- package/dist/implementations/memory/create.d.ts +0 -2
- package/dist/implementations/memory/create.js +0 -4
- package/dist/implementations/webpush/create.d.ts +0 -2
- package/dist/implementations/webpush/create.js +0 -7
package/README.md
CHANGED
|
@@ -11,37 +11,40 @@ This package is based on a push notification model.
|
|
|
11
11
|
npm install @theshelf/notification
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Drivers
|
|
15
15
|
|
|
16
|
-
Currently, there are two
|
|
16
|
+
Currently, there are two drivers available:
|
|
17
17
|
|
|
18
18
|
* **Memory** - non-persistent in memory notifications (suited for testing).
|
|
19
19
|
* **WebPush** - web browser based push notifications.
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## How to use
|
|
22
22
|
|
|
23
|
-
The
|
|
23
|
+
The basic set up looks like this.
|
|
24
24
|
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
```
|
|
25
|
+
```ts
|
|
26
|
+
import NotificationService, { MemoryDriver | WebPushDriver as SelectedDriver } from '@theshelf/notification';
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
const driver = new SelectedDriver(/* configuration */);
|
|
29
|
+
const notificationService = new NotificationService(driver);
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
WEBPUSH_VAPID_SUBJECT="..."
|
|
33
|
-
WEBPUSH_VAPID_PUBLIC_KEY="..."
|
|
34
|
-
WEBPUSH_VAPID_PRIVATE_KEY="..."
|
|
31
|
+
// Perform operations with the notificationService instance
|
|
35
32
|
```
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
### Configuration
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
#### Memory driver
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
import notificationService from '@theshelf/notification';
|
|
38
|
+
No configuration options.
|
|
43
39
|
|
|
44
|
-
|
|
40
|
+
#### WebPush driver
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
type WebPushConfiguration = { // Vapid details
|
|
44
|
+
subject: string;
|
|
45
|
+
publicKey: string;
|
|
46
|
+
privateKey: string;
|
|
47
|
+
};
|
|
45
48
|
```
|
|
46
49
|
|
|
47
50
|
### Operations
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ConnectionState } from './definitions/constants.js';
|
|
2
|
+
import type { Driver } from './definitions/interfaces.js';
|
|
3
|
+
export default class ConnectionManager {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(driver: Driver);
|
|
6
|
+
get state(): ConnectionState;
|
|
7
|
+
connect(): Promise<void>;
|
|
8
|
+
disconnect(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ConnectionStates } from './definitions/constants.js';
|
|
2
|
+
export default class ConnectionManager {
|
|
3
|
+
#driver;
|
|
4
|
+
#state = ConnectionStates.DISCONNECTED;
|
|
5
|
+
#connectPromise;
|
|
6
|
+
#disconnectPromise;
|
|
7
|
+
constructor(driver) {
|
|
8
|
+
this.#driver = driver;
|
|
9
|
+
}
|
|
10
|
+
get state() { return this.#state; }
|
|
11
|
+
async connect() {
|
|
12
|
+
if (this.#connectPromise !== undefined) {
|
|
13
|
+
return this.#connectPromise;
|
|
14
|
+
}
|
|
15
|
+
if (this.#state !== ConnectionStates.DISCONNECTED) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
this.#state = ConnectionStates.CONNECTING;
|
|
19
|
+
try {
|
|
20
|
+
this.#connectPromise = this.#driver.connect();
|
|
21
|
+
await this.#connectPromise;
|
|
22
|
+
this.#state = ConnectionStates.CONNECTED;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
this.#state = ConnectionStates.DISCONNECTED;
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
this.#connectPromise = undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async disconnect() {
|
|
33
|
+
if (this.#disconnectPromise !== undefined) {
|
|
34
|
+
return this.#disconnectPromise;
|
|
35
|
+
}
|
|
36
|
+
if (this.#state !== ConnectionStates.CONNECTED) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.#state = ConnectionStates.DISCONNECTING;
|
|
40
|
+
try {
|
|
41
|
+
this.#disconnectPromise = this.#driver.disconnect();
|
|
42
|
+
await this.#disconnectPromise;
|
|
43
|
+
this.#state = ConnectionStates.DISCONNECTED;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
this.#state = ConnectionStates.CONNECTED;
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
this.#disconnectPromise = undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ConnectionState } from './definitions/constants.js';
|
|
2
|
+
import type { Driver } from './definitions/interfaces.js';
|
|
3
|
+
export default class NotificationService implements Driver {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(driver: Driver);
|
|
6
|
+
get connectionState(): ConnectionState;
|
|
7
|
+
get connected(): boolean;
|
|
8
|
+
get subscriptions(): Map<string, unknown>;
|
|
9
|
+
connect(): Promise<void>;
|
|
10
|
+
disconnect(): Promise<void>;
|
|
11
|
+
subscribe(recipientId: string, subscription: unknown): Promise<void>;
|
|
12
|
+
unsubscribe(recipientId: string): Promise<void>;
|
|
13
|
+
sendNotification(recipientId: string, title: string, message: string): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ConnectionStates } from './definitions/constants.js';
|
|
2
|
+
import ConnectionManager from './ConnectionManager.js';
|
|
3
|
+
export default class NotificationService {
|
|
4
|
+
#driver;
|
|
5
|
+
#connectionManager;
|
|
6
|
+
constructor(driver) {
|
|
7
|
+
this.#driver = driver;
|
|
8
|
+
this.#connectionManager = new ConnectionManager(driver);
|
|
9
|
+
}
|
|
10
|
+
get connectionState() {
|
|
11
|
+
return this.#connectionManager.state;
|
|
12
|
+
}
|
|
13
|
+
get connected() {
|
|
14
|
+
return this.connectionState === ConnectionStates.CONNECTED;
|
|
15
|
+
}
|
|
16
|
+
get subscriptions() {
|
|
17
|
+
return new Map(this.#driver.subscriptions);
|
|
18
|
+
}
|
|
19
|
+
connect() {
|
|
20
|
+
return this.#connectionManager.connect();
|
|
21
|
+
}
|
|
22
|
+
disconnect() {
|
|
23
|
+
return this.#connectionManager.disconnect();
|
|
24
|
+
}
|
|
25
|
+
subscribe(recipientId, subscription) {
|
|
26
|
+
return this.#driver.subscribe(recipientId, subscription);
|
|
27
|
+
}
|
|
28
|
+
unsubscribe(recipientId) {
|
|
29
|
+
return this.#driver.unsubscribe(recipientId);
|
|
30
|
+
}
|
|
31
|
+
sendNotification(recipientId, title, message) {
|
|
32
|
+
return this.#driver.sendNotification(recipientId, title, message);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const ConnectionStates: {
|
|
2
|
+
readonly DISCONNECTED: "DISCONNECTED";
|
|
3
|
+
readonly DISCONNECTING: "DISCONNECTING";
|
|
4
|
+
readonly CONNECTING: "CONNECTING";
|
|
5
|
+
readonly CONNECTED: "CONNECTED";
|
|
6
|
+
};
|
|
7
|
+
export type ConnectionState = typeof ConnectionStates[keyof typeof ConnectionStates];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Driver } from '../definitions/interfaces.js';
|
|
2
2
|
type Notification = {
|
|
3
3
|
title: string;
|
|
4
4
|
body: string;
|
|
5
5
|
};
|
|
6
|
-
export default class Memory implements
|
|
6
|
+
export default class Memory implements Driver {
|
|
7
7
|
#private;
|
|
8
8
|
get connected(): boolean;
|
|
9
9
|
get subscriptions(): Map<string, Notification[]>;
|
|
@@ -12,5 +12,6 @@ export default class Memory implements NotificationService {
|
|
|
12
12
|
subscribe(recipientId: string): Promise<void>;
|
|
13
13
|
unsubscribe(recipientId: string): Promise<void>;
|
|
14
14
|
sendNotification(recipientId: string, title: string, body: string): Promise<void>;
|
|
15
|
+
clear(): void;
|
|
15
16
|
}
|
|
16
17
|
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import NotConnected from '../errors/NotConnected.js';
|
|
2
|
+
import SubscriptionNotFound from '../errors/SubscriptionNotFound.js';
|
|
3
|
+
export default class Memory {
|
|
4
|
+
#subscriptions = new Map();
|
|
5
|
+
#connected = false;
|
|
6
|
+
get connected() { return this.#connected; }
|
|
7
|
+
get subscriptions() {
|
|
8
|
+
if (this.#connected === false) {
|
|
9
|
+
throw new NotConnected();
|
|
10
|
+
}
|
|
11
|
+
return this.#subscriptions;
|
|
12
|
+
}
|
|
13
|
+
async connect() {
|
|
14
|
+
this.#connected = true;
|
|
15
|
+
}
|
|
16
|
+
async disconnect() {
|
|
17
|
+
this.#connected = false;
|
|
18
|
+
this.#subscriptions.clear();
|
|
19
|
+
}
|
|
20
|
+
async subscribe(recipientId) {
|
|
21
|
+
this.subscriptions.set(recipientId, []);
|
|
22
|
+
}
|
|
23
|
+
async unsubscribe(recipientId) {
|
|
24
|
+
if (this.subscriptions.has(recipientId) === false) {
|
|
25
|
+
throw new SubscriptionNotFound(recipientId);
|
|
26
|
+
}
|
|
27
|
+
this.subscriptions.delete(recipientId);
|
|
28
|
+
}
|
|
29
|
+
async sendNotification(recipientId, title, body) {
|
|
30
|
+
const subscription = this.#getSubscription(recipientId);
|
|
31
|
+
subscription.push({ title, body });
|
|
32
|
+
}
|
|
33
|
+
clear() {
|
|
34
|
+
this.subscriptions.clear();
|
|
35
|
+
}
|
|
36
|
+
#getSubscription(recipientId) {
|
|
37
|
+
const subscription = this.subscriptions.get(recipientId);
|
|
38
|
+
if (subscription === undefined) {
|
|
39
|
+
throw new SubscriptionNotFound(recipientId);
|
|
40
|
+
}
|
|
41
|
+
return subscription;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { PushSubscription } from 'web-push';
|
|
2
|
-
import type {
|
|
3
|
-
type
|
|
2
|
+
import type { Driver } from '../definitions/interfaces.js';
|
|
3
|
+
type WebPushConfiguration = {
|
|
4
4
|
subject: string;
|
|
5
5
|
publicKey: string;
|
|
6
6
|
privateKey: string;
|
|
7
7
|
};
|
|
8
|
-
export default class WebPush implements
|
|
8
|
+
export default class WebPush implements Driver {
|
|
9
9
|
#private;
|
|
10
|
-
constructor(configuration:
|
|
10
|
+
constructor(configuration: WebPushConfiguration);
|
|
11
11
|
get connected(): boolean;
|
|
12
12
|
get subscriptions(): Map<string, PushSubscription>;
|
|
13
13
|
connect(): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import webpush from 'web-push';
|
|
2
|
-
import NotConnected from '
|
|
3
|
-
import SubscriptionNotFound from '
|
|
2
|
+
import NotConnected from '../errors/NotConnected.js';
|
|
3
|
+
import SubscriptionNotFound from '../errors/SubscriptionNotFound.js';
|
|
4
4
|
export default class WebPush {
|
|
5
5
|
#configuration;
|
|
6
6
|
#subscriptions;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type * 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';
|
|
5
|
-
export { default as
|
|
6
|
-
export { default } from './
|
|
5
|
+
export { default as MemoryDriver } from './drivers/Memory.js';
|
|
6
|
+
export { default } from './NotificationService.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default as NotConnected } from './errors/NotConnected.js';
|
|
2
2
|
export { default as NotificationError } from './errors/NotificationError.js';
|
|
3
3
|
export { default as SubscriptionNotFound } from './errors/SubscriptionNotFound.js';
|
|
4
|
-
export { default as
|
|
5
|
-
export { default } from './
|
|
4
|
+
export { default as MemoryDriver } from './drivers/Memory.js';
|
|
5
|
+
export { default } from './NotificationService.js';
|
package/package.json
CHANGED
package/dist/implementation.d.ts
DELETED
package/dist/implementation.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import UnknownImplementation from './errors/UnknownImplementation.js';
|
|
2
|
-
import createMemory from './implementations/memory/create.js';
|
|
3
|
-
import createWebPush from './implementations/webpush/create.js';
|
|
4
|
-
const implementations = new Map([
|
|
5
|
-
['memory', createMemory],
|
|
6
|
-
['webpush', createWebPush],
|
|
7
|
-
]);
|
|
8
|
-
const DEFAULT_NOTIFICATION_IMPLEMENTATION = 'memory';
|
|
9
|
-
const implementationName = process.env.NOTIFICATION_IMPLEMENTATION ?? DEFAULT_NOTIFICATION_IMPLEMENTATION;
|
|
10
|
-
const creator = implementations.get(implementationName.toLowerCase());
|
|
11
|
-
if (creator === undefined) {
|
|
12
|
-
throw new UnknownImplementation(implementationName);
|
|
13
|
-
}
|
|
14
|
-
export default creator();
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import NotConnected from '../../errors/NotConnected.js';
|
|
2
|
-
import SubscriptionNotFound from '../../errors/SubscriptionNotFound.js';
|
|
3
|
-
export default class Memory {
|
|
4
|
-
#subscriptions;
|
|
5
|
-
get connected() {
|
|
6
|
-
return this.#subscriptions !== undefined;
|
|
7
|
-
}
|
|
8
|
-
get subscriptions() {
|
|
9
|
-
return this.#getSubscriptions();
|
|
10
|
-
}
|
|
11
|
-
async connect() {
|
|
12
|
-
this.#subscriptions = new Map();
|
|
13
|
-
}
|
|
14
|
-
async disconnect() {
|
|
15
|
-
this.#subscriptions = undefined;
|
|
16
|
-
}
|
|
17
|
-
async subscribe(recipientId) {
|
|
18
|
-
const subscriptions = this.#getSubscriptions();
|
|
19
|
-
subscriptions.set(recipientId, []);
|
|
20
|
-
}
|
|
21
|
-
async unsubscribe(recipientId) {
|
|
22
|
-
const subscriptions = this.#getSubscriptions();
|
|
23
|
-
if (subscriptions.has(recipientId) === false) {
|
|
24
|
-
throw new SubscriptionNotFound(recipientId);
|
|
25
|
-
}
|
|
26
|
-
subscriptions.delete(recipientId);
|
|
27
|
-
}
|
|
28
|
-
async sendNotification(recipientId, title, body) {
|
|
29
|
-
const subscription = this.#getSubscription(recipientId);
|
|
30
|
-
subscription.push({ title, body });
|
|
31
|
-
}
|
|
32
|
-
#getSubscriptions() {
|
|
33
|
-
if (this.#subscriptions === undefined) {
|
|
34
|
-
throw new NotConnected();
|
|
35
|
-
}
|
|
36
|
-
return this.#subscriptions;
|
|
37
|
-
}
|
|
38
|
-
#getSubscription(recipientId) {
|
|
39
|
-
const subscriptions = this.#getSubscriptions();
|
|
40
|
-
const subscription = subscriptions.get(recipientId);
|
|
41
|
-
if (subscription === undefined) {
|
|
42
|
-
throw new SubscriptionNotFound(recipientId);
|
|
43
|
-
}
|
|
44
|
-
return subscription;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import WebPush from './WebPush.js';
|
|
2
|
-
export default function create() {
|
|
3
|
-
const subject = process.env.WEBPUSH_SUBJECT ?? 'undefined';
|
|
4
|
-
const publicKey = process.env.WEBPUSH_PUBLIC_KEY ?? 'undefined';
|
|
5
|
-
const privateKey = process.env.WEBPUSH_PRIVATE_KEY ?? 'undefined';
|
|
6
|
-
return new WebPush({ subject, publicKey, privateKey });
|
|
7
|
-
}
|