v2.1.0
Fmodel
provides just enough tactical Domain-Driven Design patterns, optimized for Event Sourcing and CQRS.
The domain
components are fully isolated from the application layer and API-related concerns.
It represents a pure declaration (pure functions) of the program logic.
Decider
, View
, and Saga
The application
components orchestrate the execution of the logic by loading the state, executing domain components, and storing a new state.
EventSourcingAggregate
, StateStoredAggregate
, MaterializedView
, and SagaManager
Install
npm i @fraktalio/fmodel-ts
Available on https://www.npmjs.com/package/@fraktalio/fmodel-ts
Learn more
What's Changed
Lowering down the responsibility of the Metadata types in the Application layer.
For example, the EventRepository interface:
export interface IEventRepository<C, E, V, CM, EM> {
/**
* Fetch events
*
* @param command - Command of type `C`
*
* @return list of Events with Version and Event Metadata
*/
readonly fetch: (command: C) => Promise<readonly (E & V & EM)[]>;
/**
* Get the event stream version / sequence
*
* @param event - Event of type `E`
*
* @return the version / sequence of the event stream that this event belongs to.
*/
readonly versionProvider: (event: E & EM) => Promise<V | null>;
/**
* Save events
*
* @param events - list of Events
* @param commandMetadata - Command Metadata of the command that initiated `events`
* @param versionProvider - A provider for the Latest Event in this stream and its Version/Sequence
* @return a list of newly saved Event(s) of type `E` with Version of type `V` and with Event Metadata of type `EM`
*/
readonly save: (
events: readonly E[],
commandMetadata: CM,
versionProvider: (e: E) => Promise<V | null>
) => Promise<readonly (E & V & EM)[]>;
}
Old interface:
export interface IEventRepository<C, E, V, CM, EM> {
/**
* Fetch events
*
* @param command - Command of type `C` with metadata of type `CM`
*
* @return list of Events with Version and Event Metadata
*/
readonly fetch: (command: C & CM) => Promise<readonly (E & V & EM)[]>;
/**
* Get the latest event stream version / sequence
*
* @param event - Event of type `E`
*
* @return the latest version / sequence of the event stream that this event belongs to.
*/
readonly versionProvider: (event: E) => Promise<V | null>;
/**
* Save events
*
* @param events - list of Events
* @param commandMetadata - Command Metadata of the command that initiated `events`
* @param versionProvider - A provider for the Latest Event in this stream and its Version/Sequence
* @return a list of newly saved Event(s) of type `E` with Version of type `V` and with Event Metadata of type `EM`
*/
readonly save: (
events: readonly E[],
commandMetadata: CM,
versionProvider: (e: E) => Promise<V | null>
) => Promise<readonly (E & V & EM)[]>;
}
The interface used CM
as the param of fetch
method, and EM
in the versionProvider
. This could lead to problems, for example, the C
lost the relation with the list of E/Events it produced, as CM
could be used to identify the events it needs to fetch.
The relation between:
- C and the E/Events it can produce
- E and the Commands we can trigger next
- List of E and the S/state they can evolve to
is the concern of domain layer, not of the application layer.
Full Changelog: v2.0.1...v2.1.0