@event-nest/core 1.0.0 → 1.0.2

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,6 +1,10 @@
1
1
  # Event Nest
2
2
  A collection of [nest.js](https://nestjs.com/) libraries to help you build applications based on event sourcing architecture.
3
3
 
4
+ ![build status](https://github.com/NickTsitlakidis/event-nest/actions/workflows/checks.yml/badge.svg)
5
+ [![npm version](https://badge.fury.io/js/@event-nest%2Fcore.svg)](https://badge.fury.io/js/@event-nest%2Fcore)
6
+ [![Coverage Status](https://coveralls.io/repos/github/NickTsitlakidis/event-nest/badge.svg?branch=master)](https://coveralls.io/github/NickTsitlakidis/event-nest?branch=master)
7
+
4
8
  ## Description
5
9
  Event Nest is a collection of libraries based on nest.js that assists in implementing the core concepts of event sourcing:
6
10
  * Saving events in a persistent storage
@@ -56,18 +60,39 @@ Use any collection you want but be sure to create it before running the applicat
56
60
 
57
61
 
58
62
  ## Concepts
59
- ### Aggregate Root
60
- An [aggregate root](https://stackoverflow.com/questions/1958621/whats-an-aggregate-root) is a concept from Domain Driven Design. It is a domain object that is responsible for maintaining the consistency of the aggregate.
61
- To achieve this, the aggregate root should expose methods which encapsulate its behaviour. Any method that needs to update the state, should also append an event to the aggregate root's event stream.
62
-
63
63
  ### Event
64
64
  An event is a representation of something that has happened in the past. It is identified by a unique name, and it may contain additional data that will be persisted with the event.
65
65
 
66
- Each event can be used for three purposes :
66
+ Each event serves three purposes :
67
67
  * It will be persisted so that it can be used to reconstruct the state of an aggregate root
68
68
  * It will be passed to any internal subscribers that need to react to this event (e.g. updating the read model)
69
69
  * When it's time to recreate the aggregate root, the event will be processed by the correct method in the aggregate root
70
70
 
71
+ There is no specific requirement for the structure of an event, but it is recommended to keep it simple and immutable. The [class-transformer](https://github.com/typestack/class-transformer) library is utilized under the hood to save and read the events from the database. Therefore, your event classes should adhere to the rules of class-transformer to be properly serialized and deserialized.
72
+
73
+ To register a class as an event, use the `@RegisteredEvent` decorator. The decorator accepts a string parameter which is the unique name of the event.
74
+
75
+
76
+ ### Aggregate Root
77
+ An [aggregate root](https://stackoverflow.com/questions/1958621/whats-an-aggregate-root) is a fundamental concept in Domain-Driven Design (DDD).
78
+ It represents a cluster of domain objects that are treated as a single unit. The aggregate root is responsible for maintaining the consistency and enforcing business rules within the aggregate.
79
+ While explaining the concept of an aggregate root in depth is beyond the scope of this documentation, it's important to understand how such an object interacts with the event sourcing system.
80
+
81
+ In the context of event sourcing, the aggregate root plays a crucial role. Each aggregate root maintains its own set of events, forming an event stream.
82
+ These events capture the changes or actions that have occurred within the aggregate. The event stream serves as the historical record of what has happened to the aggregate over time.
83
+
84
+ Let's consider an example to illustrate the concept of an aggregate root. Suppose we have a user management system where we need to create new users and update existing users. In this case, the `User` entity serves as the aggregate root.
85
+
86
+ The `User` class encapsulates the user-specific behavior and maintains the internal state of a user. It provides methods for creating a new user, updating user details, and performing any other operations relevant to the user domain. These methods are called from Nest.js services or other parts of the application responsible for user-related operations.
87
+
88
+ Each instance of the `User` class has its own event stream, which records the events specific to that user. For example, when a new user is created, an event called `UserCreatedEvent` is appended to the event stream. Similarly, when a user's details are updated, an event called `UserUpdatedEvent` is appended.
89
+
90
+ When loading a user from the event store, the event stream is replayed, and each event is processed by the corresponding method in the `User` class. This allows the user object to be reconstructed and updated to its most recent state based on the events.
91
+
92
+ To ensure that all modifications to the user's state are properly recorded, any method that changes the state should also append the corresponding event to the event stream. By doing so, the event is persisted and can be used for reconstructing the state in the future.
93
+ If an event is not appended, the changes will not be saved in the database, and the consistency of the user object will be compromised.
94
+
95
+
71
96
  Enough with the theory, let's see an example that includes all of the above.
72
97
 
73
98
  #### Example
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@event-nest/core",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "license": "MIT",
5
5
  "author": "Nick Tsitlakidis",
6
- "description": "Event sourcing module for NestJS. It provides a set of decorators and interfaces to help you build your event sourcing application.",
6
+ "description": "Event sourcing module for NestJS. It provides a set of decorators and classes to build an application based on event sourcing.",
7
7
  "keywords": [
8
8
  "nestjs",
9
9
  "event sourcing",
@@ -23,7 +23,7 @@
23
23
  "@nestjs/core": "^9.0.0",
24
24
  "reflect-metadata": "0.1.13",
25
25
  "rxjs": "^7.2.0",
26
- "tslib": "2.5.3"
26
+ "tslib": "^2.3.0"
27
27
  },
28
28
  "dependencies": {
29
29
  "class-transformer": "^0.5.1"
@@ -2,10 +2,11 @@ import { Module } from "@nestjs/core/injector/module";
2
2
  import { AggregateRootAwareEvent } from "./aggregate-root-aware-event";
3
3
  import { OnModuleDestroy } from "@nestjs/common";
4
4
  export declare class DomainEventEmitter implements OnModuleDestroy {
5
- private _runParallelSubscriptions;
6
- private _handlers;
7
- private _logger;
5
+ private readonly _runParallelSubscriptions;
6
+ private readonly _handlers;
7
+ private readonly _logger;
8
8
  constructor(_runParallelSubscriptions?: boolean);
9
+ get runsParallelSubscriptions(): boolean;
9
10
  onModuleDestroy(): void;
10
11
  bindSubscriptions(injectorModules: Map<string, Module>): void;
11
12
  emit(withAggregate: AggregateRootAwareEvent<object>): Promise<unknown>;
@@ -11,6 +11,9 @@ class DomainEventEmitter {
11
11
  this._handlers = new Map();
12
12
  this._logger = new common_1.Logger(DomainEventEmitter.name);
13
13
  }
14
+ get runsParallelSubscriptions() {
15
+ return this._runParallelSubscriptions;
16
+ }
14
17
  onModuleDestroy() {
15
18
  this._handlers.clear();
16
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"domain-event-emitter.js","sourceRoot":"","sources":["../../../../../libs/core/src/lib/domain-event-emitter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"domain-event-emitter.js","sourceRoot":"","sources":["../../../../../libs/core/src/lib/domain-event-emitter.ts"],"names":[],"mappings":";;;AACA,2EAIqC;AAErC,mDAA2C;AAC3C,2CAAyD;AAEzD,+BAAiE;AAEjE,MAAa,kBAAkB;IAI3B,YAA6B,4BAAqC,KAAK;QAA1C,8BAAyB,GAAzB,yBAAyB,CAAiB;QACnE,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,EAAwC,CAAC;QACjE,IAAI,CAAC,OAAO,GAAG,IAAI,eAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,yBAAyB;QACzB,OAAO,IAAI,CAAC,yBAAyB,CAAC;IAC1C,CAAC;IAED,eAAe;QACX,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED,iBAAiB,CAAC,eAAoC;QAClD,eAAe,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YAC/B,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAClC,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE;oBACtD,OAAO;iBACV;gBAED,IAAI,IAAA,qDAAyB,EAAC,QAAQ,CAAC,QAAkB,CAAC,EAAE;oBACxD,MAAM,MAAM,GAAG,IAAA,gEAAoC,EAAC,QAAQ,CAAC,QAAkC,CAAC,CAAC;oBACjG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;wBACrB,MAAM,OAAO,GAAG,IAAA,sCAAU,EAAC,KAAK,CAAW,CAAC;wBAC5C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;4BAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;yBACnC;wBAED,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,IAAI,aAAa,OAAO,EAAE,CAAC,CAAC;wBACzF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,QAA8B,CAAC,CAAC;oBAC/E,CAAC,CAAC,CAAC;iBACN;YACL,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAI,CAAC,aAA8C;QAC/C,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;YAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,CACb,SAAS,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,6FAA6F,CAC/I,CAAC;YACF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;SAC5B;QACD,MAAM,OAAO,GAAG,IAAA,sCAAU,EAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9D,IAAI,IAAA,kBAAK,EAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;YAChD,IAAI,CAAC,OAAO,CAAC,IAAI,CACb,SAAS,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,6FAA6F,CAC/I,CAAC;YACF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;SAC5B;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;QACrG,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,YAAY,CAAC,aAAgD;QACzD,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE;YACjC,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;SAC9E;QAED,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,YAAK,EAAC,GAAG,EAAE,CAAC,IAAA,WAAI,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,OAAO,IAAA,qBAAc,EAAC,IAAA,aAAM,EAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAA,WAAI,GAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;CACJ;AAnED,gDAmEC"}