@theshelf/eventbroker 0.3.2 → 0.4.1

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 CHANGED
@@ -1,9 +1,7 @@
1
1
 
2
- # Event Broker | The Shelf
2
+ # Event Broker core | The Shelf
3
3
 
4
- The event broker package provides a universal interaction layer with an actual event broker solution.
5
-
6
- This package is based on a publish / subscribe model.
4
+ This package contains the publication / subscription model. It uses a interchangeable driver system for performing the actual operations. An in-memory driver is included.
7
5
 
8
6
  ## Installation
9
7
 
@@ -11,37 +9,23 @@ This package is based on a publish / subscribe model.
11
9
  npm install @theshelf/eventbroker
12
10
  ```
13
11
 
14
- ## Driver
15
-
16
- Currently, there is only one driver available:
17
-
18
- * **Memory** - non-persistent event broker based on the Node.js `EventEmitter`.
19
-
20
- We have plans to add a Kafka driver later on.
21
-
22
12
  ## How to use
23
13
 
24
14
  The basic set up looks like this.
25
15
 
26
16
  ```ts
27
- import EventBroker, { MemoryDriver as SelectedDriver } from '@theshelf/eventbroker';
17
+ import EventBroker, { MemoryDriver } from '@theshelf/eventbroker';
28
18
 
29
- const driver = new SelectedDriver(/* configuration */);
19
+ const driver = new MemoryDriver();
30
20
  const eventBroker = new EventBroker(driver);
31
21
 
32
22
  // Perform operations with the eventBroker instance
33
23
  ```
34
24
 
35
- ### Configuration
36
-
37
- #### Memory driver
38
-
39
- No configuration options.
40
-
41
- ### Operations
25
+ ## Operations
42
26
 
43
27
  ```ts
44
- import { Publication, Subscription } from '@theshelf/eventbroker';
28
+ import type { Publication, Subscription } from '@theshelf/eventbroker';
45
29
 
46
30
  // Open connection
47
31
  await eventBroker.connect();
@@ -60,3 +44,42 @@ await eventBroker.publish(publication);
60
44
  // Unsubscribe from an event
61
45
  await eventBroker.unsubscribe(subscription);
62
46
  ```
47
+
48
+ ## Types
49
+
50
+ The publication has the following structure.
51
+
52
+ ```ts
53
+ type Publication<T> = {
54
+ channel: string;
55
+ name: string;
56
+ data?: T
57
+ }
58
+ ```
59
+
60
+ The subscription has the following structure.
61
+
62
+ ```ts
63
+ type Subscription<T> = {
64
+ channel: string;
65
+ name: string;
66
+ handler: EventHandler<T>;
67
+ }
68
+ ```
69
+
70
+ Where the event handler performs an operation on the data of the publication.
71
+
72
+ ```ts
73
+ type EventHandler<T> = (data: T) => void;
74
+ ```
75
+
76
+ ## Drivers
77
+
78
+ ### Memory
79
+
80
+ In-memory event broker (suited for testing). It doesn't have any configuration options, but has an additional operation.
81
+
82
+ ```ts
83
+ // Clear the memory
84
+ driver.clear();
85
+ ```
@@ -1,8 +1,9 @@
1
+ import type Logger from '@theshelf/logging';
1
2
  import type { Driver } from './definitions/interfaces.js';
2
3
  import type { Publication, Subscription } from './definitions/types.js';
3
- export default class EventBroker implements Driver {
4
+ export default class EventBroker {
4
5
  #private;
5
- constructor(driver: Driver);
6
+ constructor(driver: Driver, logger?: Logger);
6
7
  get connected(): boolean;
7
8
  connect(): Promise<void>;
8
9
  disconnect(): Promise<void>;
@@ -1,24 +1,78 @@
1
+ import NotConnected from './errors/NotConnected.js';
1
2
  export default class EventBroker {
2
3
  #driver;
3
- constructor(driver) {
4
+ #logger;
5
+ #logPrefix;
6
+ constructor(driver, logger) {
4
7
  this.#driver = driver;
8
+ this.#logger = logger?.for(EventBroker.name);
9
+ this.#logPrefix = `${this.#driver.name} ->`;
5
10
  }
6
11
  get connected() {
7
12
  return this.#driver.connected;
8
13
  }
9
- connect() {
10
- return this.#driver.connect();
14
+ async connect() {
15
+ if (this.connected === true) {
16
+ return;
17
+ }
18
+ this.#logger?.debug(this.#logPrefix, 'Connecting');
19
+ try {
20
+ await this.#driver.connect();
21
+ }
22
+ catch (error) {
23
+ this.#logger?.error(this.#logPrefix, 'Connect failed with error', error);
24
+ throw error;
25
+ }
11
26
  }
12
- disconnect() {
13
- return this.#driver.disconnect();
27
+ async disconnect() {
28
+ if (this.connected === false) {
29
+ return;
30
+ }
31
+ this.#logger?.debug(this.#logPrefix, 'Disconnecting');
32
+ try {
33
+ return await this.#driver.disconnect();
34
+ }
35
+ catch (error) {
36
+ this.#logger?.error(this.#logPrefix, 'Disconnect failed with error', error);
37
+ throw error;
38
+ }
14
39
  }
15
- publish(publication) {
16
- return this.#driver.publish(publication);
40
+ async publish(publication) {
41
+ this.#logger?.debug(this.#logPrefix, 'Publishing to', publication.channel, '->', publication.name);
42
+ try {
43
+ this.#validateConnection();
44
+ return await this.#driver.publish(publication);
45
+ }
46
+ catch (error) {
47
+ this.#logger?.error(this.#logPrefix, 'Publish to', publication.channel, '->', publication.name, 'failed with error', error);
48
+ throw error;
49
+ }
17
50
  }
18
- subscribe(subscription) {
19
- return this.#driver.subscribe(subscription);
51
+ async subscribe(subscription) {
52
+ this.#logger?.debug(this.#logPrefix, 'Subscribing to', subscription.channel, '->', subscription.name);
53
+ try {
54
+ this.#validateConnection();
55
+ return await this.#driver.subscribe(subscription);
56
+ }
57
+ catch (error) {
58
+ this.#logger?.error(this.#logPrefix, 'Subscribe to', subscription.channel, '->', subscription.name, 'failed with error', error);
59
+ throw error;
60
+ }
20
61
  }
21
- unsubscribe(subscription) {
22
- return this.#driver.unsubscribe(subscription);
62
+ async unsubscribe(subscription) {
63
+ this.#logger?.debug(this.#logPrefix, 'Unsubscribing from', subscription.channel, '->', subscription.name);
64
+ try {
65
+ this.#validateConnection();
66
+ return await this.#driver.unsubscribe(subscription);
67
+ }
68
+ catch (error) {
69
+ this.#logger?.error(this.#logPrefix, 'Unsubscribe from', subscription.channel, '->', subscription.name, 'failed with error', error);
70
+ throw error;
71
+ }
72
+ }
73
+ #validateConnection() {
74
+ if (this.connected === false) {
75
+ throw new NotConnected();
76
+ }
23
77
  }
24
78
  }
@@ -1,5 +1,6 @@
1
1
  import type { Publication, Subscription } from './types.js';
2
2
  export interface Driver {
3
+ get name(): string;
3
4
  get connected(): boolean;
4
5
  connect(): Promise<void>;
5
6
  disconnect(): Promise<void>;
@@ -3,6 +3,7 @@ import type { Driver } from '../definitions/interfaces.js';
3
3
  import type { Publication, Subscription } from '../definitions/types.js';
4
4
  export default class Memory implements Driver {
5
5
  #private;
6
+ get name(): string;
6
7
  get connected(): boolean;
7
8
  get emitters(): Map<string, EventEmitter>;
8
9
  connect(): Promise<void>;
@@ -3,6 +3,7 @@ import NotConnected from '../errors/NotConnected.js';
3
3
  export default class Memory {
4
4
  #emitters = new Map();
5
5
  #connected = false;
6
+ get name() { return Memory.name; }
6
7
  get connected() { return this.#connected; }
7
8
  get emitters() {
8
9
  if (this.#connected === false) {
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@theshelf/eventbroker",
3
3
  "private": false,
4
- "version": "0.3.2",
4
+ "version": "0.4.1",
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,6 +20,6 @@
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
  }