@theshelf/eventbroker 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 CHANGED
@@ -11,36 +11,37 @@ This package is based on a publish / subscribe model.
11
11
  npm install @theshelf/eventbroker
12
12
  ```
13
13
 
14
- ## Implementations
14
+ ## Driver
15
15
 
16
- Currently, there is only one implementation:
16
+ Currently, there is only one driver available:
17
17
 
18
18
  * **Memory** - non-persistent event broker based on the Node.js `EventEmitter`.
19
19
 
20
- We have plans to add a Kafka implementation later on.
21
-
22
- ## Configuration
23
-
24
- The used implementation needs to be configured in the `.env` file.
25
-
26
- ```env
27
- EVENT_BROKER_IMPLEMENTATION="memory"
28
- ```
20
+ We have plans to add a Kafka driver later on.
29
21
 
30
22
  ## How to use
31
23
 
32
- An instance of the configured event broker implementation can be imported for performing event operations.
24
+ The basic set up looks like this.
33
25
 
34
26
  ```ts
35
- import eventBroker from '@theshelf/eventbroker';
27
+ import EventBroker, { MemoryDriver as SelectedDriver } from '@theshelf/eventbroker';
28
+
29
+ const driver = new SelectedDriver(/* configuration */);
30
+ const eventBroker = new EventBroker(driver);
36
31
 
37
32
  // Perform operations with the eventBroker instance
38
33
  ```
39
34
 
35
+ ### Configuration
36
+
37
+ #### Memory driver
38
+
39
+ No configuration options.
40
+
40
41
  ### Operations
41
42
 
42
43
  ```ts
43
- import eventBroker, { Publication, Subscription } from '@theshelf/eventbroker';
44
+ import { Publication, Subscription } from '@theshelf/eventbroker';
44
45
 
45
46
  // Open connection
46
47
  await eventBroker.connect();
@@ -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
+ }
@@ -1,13 +1,14 @@
1
+ import type { ConnectionState } from './definitions/constants.js';
1
2
  import type { Driver } from './definitions/interfaces.js';
2
3
  import type { Publication, Subscription } from './definitions/types.js';
3
4
  export default class EventBroker implements Driver {
4
5
  #private;
5
6
  constructor(driver: Driver);
7
+ get connectionState(): ConnectionState;
6
8
  get connected(): boolean;
7
9
  connect(): Promise<void>;
8
10
  disconnect(): Promise<void>;
9
11
  publish<T>(publication: Publication<T>): Promise<void>;
10
12
  subscribe<T>(subscription: Subscription<T>): Promise<void>;
11
13
  unsubscribe<T>(subscription: Subscription<T>): Promise<void>;
12
- clear(): Promise<void>;
13
14
  }
@@ -1,14 +1,23 @@
1
+ import { ConnectionStates } from './definitions/constants.js';
2
+ import ConnectionManager from './ConnectionManager.js';
1
3
  export default class EventBroker {
2
4
  #driver;
5
+ #connectionManager;
3
6
  constructor(driver) {
4
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;
5
15
  }
6
- get connected() { return this.#driver.connected; }
7
16
  connect() {
8
- return this.#driver.connect();
17
+ return this.#connectionManager.connect();
9
18
  }
10
19
  disconnect() {
11
- return this.#driver.disconnect();
20
+ return this.#connectionManager.disconnect();
12
21
  }
13
22
  publish(publication) {
14
23
  return this.#driver.publish(publication);
@@ -19,7 +28,4 @@ export default class EventBroker {
19
28
  unsubscribe(subscription) {
20
29
  return this.#driver.unsubscribe(subscription);
21
30
  }
22
- clear() {
23
- return this.#driver.clear();
24
- }
25
31
  }
@@ -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];
@@ -0,0 +1,6 @@
1
+ export const ConnectionStates = {
2
+ DISCONNECTED: 'DISCONNECTED',
3
+ DISCONNECTING: 'DISCONNECTING',
4
+ CONNECTING: 'CONNECTING',
5
+ CONNECTED: 'CONNECTED'
6
+ };
@@ -6,5 +6,4 @@ export interface Driver {
6
6
  publish<T>(publication: Publication<T>): Promise<void>;
7
7
  subscribe<T>(subscription: Subscription<T>): Promise<void>;
8
8
  unsubscribe<T>(subscription: Subscription<T>): Promise<void>;
9
- clear(): Promise<void>;
10
9
  }
@@ -1,12 +1,14 @@
1
- import type { Driver } from '../../definitions/interfaces.js';
2
- import type { Publication, Subscription } from '../../definitions/types.js';
1
+ import { EventEmitter } from 'node:events';
2
+ import type { Driver } from '../definitions/interfaces.js';
3
+ import type { Publication, Subscription } from '../definitions/types.js';
3
4
  export default class Memory implements Driver {
4
5
  #private;
5
6
  get connected(): boolean;
7
+ get emitters(): Map<string, EventEmitter>;
6
8
  connect(): Promise<void>;
7
9
  disconnect(): Promise<void>;
8
10
  publish<T>(publication: Publication<T>): Promise<void>;
9
11
  subscribe<T>(subscription: Subscription<T>): Promise<void>;
10
12
  unsubscribe<T>(subscription: Subscription<T>): Promise<void>;
11
- clear(): Promise<void>;
13
+ clear(): void;
12
14
  }
@@ -1,13 +1,21 @@
1
1
  import { EventEmitter } from 'node:events';
2
+ import NotConnected from '../errors/NotConnected.js';
2
3
  export default class Memory {
3
4
  #emitters = new Map();
4
5
  #connected = false;
5
6
  get connected() { return this.#connected; }
7
+ get emitters() {
8
+ if (this.#connected === false) {
9
+ throw new NotConnected();
10
+ }
11
+ return this.#emitters;
12
+ }
6
13
  async connect() {
7
14
  this.#connected = true;
8
15
  }
9
16
  async disconnect() {
10
17
  this.#connected = false;
18
+ this.#emitters.clear();
11
19
  }
12
20
  async publish(publication) {
13
21
  const emitter = this.#getEmitter(publication);
@@ -21,13 +29,14 @@ export default class Memory {
21
29
  const emitter = this.#getEmitter(subscription);
22
30
  emitter.off(subscription.name, subscription.handler);
23
31
  }
24
- async clear() {
25
- this.#emitters.clear();
32
+ clear() {
33
+ this.emitters.clear();
26
34
  }
27
35
  #getEmitter(event) {
28
- if (this.#emitters.has(event.channel) === false) {
29
- this.#emitters.set(event.channel, new EventEmitter());
36
+ const emitters = this.emitters;
37
+ if (emitters.has(event.channel) === false) {
38
+ emitters.set(event.channel, new EventEmitter());
30
39
  }
31
- return this.#emitters.get(event.channel);
40
+ return emitters.get(event.channel);
32
41
  }
33
42
  }
@@ -1,2 +1,3 @@
1
1
  export default class EventBrokerError extends Error {
2
+ constructor(message?: string);
2
3
  }
@@ -1,2 +1,9 @@
1
1
  export default class EventBrokerError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = this.constructor.name;
5
+ if (Error.captureStackTrace) {
6
+ Error.captureStackTrace(this, this.constructor);
7
+ }
8
+ }
2
9
  }
@@ -0,0 +1,4 @@
1
+ import EventBrokerError from './EventBrokerError.js';
2
+ export default class NotConnected extends EventBrokerError {
3
+ constructor();
4
+ }
@@ -0,0 +1,6 @@
1
+ import EventBrokerError from './EventBrokerError.js';
2
+ export default class NotConnected extends EventBrokerError {
3
+ constructor() {
4
+ super('Event broker not connected');
5
+ }
6
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import EventBroker from './EventBroker.js';
2
- declare const eventBroker: EventBroker;
3
- export * from './definitions/types.js';
4
- export type { EventBroker };
5
- export default eventBroker;
1
+ export type * from './definitions/interfaces.js';
2
+ export type * from './definitions/types.js';
3
+ export { default as MemoryDriver } from './drivers/Memory.js';
4
+ export { default } from './EventBroker.js';
package/dist/index.js CHANGED
@@ -1,5 +1,2 @@
1
- import EventBroker from './EventBroker.js';
2
- import implementation from './implementation.js';
3
- const eventBroker = new EventBroker(implementation);
4
- export * from './definitions/types.js';
5
- export default eventBroker;
1
+ export { default as MemoryDriver } from './drivers/Memory.js';
2
+ export { default } from './EventBroker.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@theshelf/eventbroker",
3
3
  "private": false,
4
- "version": "0.0.4",
4
+ "version": "0.2.0",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "url": "https://github.com/MaskingTechnology/theshelf"
@@ -1,4 +0,0 @@
1
- import EventBrokerError from './EventBrokerError.js';
2
- export default class UnknownImplementation extends EventBrokerError {
3
- constructor(name: string);
4
- }
@@ -1,6 +0,0 @@
1
- import EventBrokerError from './EventBrokerError.js';
2
- export default class UnknownImplementation extends EventBrokerError {
3
- constructor(name) {
4
- super(`Unknown event broker implementation: ${name}`);
5
- }
6
- }
@@ -1,3 +0,0 @@
1
- import type { Driver } from './definitions/interfaces.js';
2
- declare const _default: Driver;
3
- export default _default;
@@ -1,12 +0,0 @@
1
- import UnknownImplementation from './errors/UnknownImplementation.js';
2
- import createMemoryBroker from './implementations/memory/create.js';
3
- const implementations = new Map([
4
- ['memory', createMemoryBroker]
5
- ]);
6
- const DEFAULT_BROKER_IMPLEMENTATION = 'memory';
7
- const implementationName = process.env.EVENT_BROKER_IMPLEMENTATION ?? DEFAULT_BROKER_IMPLEMENTATION;
8
- const creator = implementations.get(implementationName.toLowerCase());
9
- if (creator === undefined) {
10
- throw new UnknownImplementation(implementationName);
11
- }
12
- export default creator();
@@ -1,2 +0,0 @@
1
- import Memory from './Memory.js';
2
- export default function create(): Memory;
@@ -1,4 +0,0 @@
1
- import Memory from './Memory.js';
2
- export default function create() {
3
- return new Memory();
4
- }