diff --git a/src/lib/application/eventsourcing-aggregate.spec.ts b/src/lib/application/eventsourcing-aggregate.spec.ts index 6923c1d..c5e3a58 100644 --- a/src/lib/application/eventsourcing-aggregate.spec.ts +++ b/src/lib/application/eventsourcing-aggregate.spec.ts @@ -239,17 +239,18 @@ class EventRepositoryImpl } async save( - eList: readonly (Evt & CmdMetadata)[], + eList: readonly Evt[], + commandMetadata: CmdMetadata, versionProvider: (e: Evt) => Promise ): Promise { //mapping the Commands metadata into Events metadata !!! const savedEvents: readonly (Evt & Version & EvtMetadata)[] = await Promise.all( - eList.map(async (e: Evt & CmdMetadata, index) => ({ + eList.map(async (e: Evt, index) => ({ kind: e.kind, value: e.value, version: ((await versionProvider(e))?.version ?? 0) + index + 1, - traceId: e.traceId, + traceId: commandMetadata.traceId, })) ); storage.concat(savedEvents); diff --git a/src/lib/application/eventsourcing-aggregate.ts b/src/lib/application/eventsourcing-aggregate.ts index 0456d07..33eaeca 100644 --- a/src/lib/application/eventsourcing-aggregate.ts +++ b/src/lib/application/eventsourcing-aggregate.ts @@ -49,12 +49,14 @@ export interface IEventRepository { /** * Save events * - * @param events - list of Events with Command Metadata + * @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 & CM)[], + events: readonly E[], + commandMetadata: CM, versionProvider: (e: E) => Promise ) => Promise; } @@ -231,20 +233,19 @@ export class EventSourcingAggregate } async save( - events: readonly (E & CM)[], + events: readonly E[], + commandMetadata: CM, versionProvider: (e: E) => Promise ): Promise { - return this.eventRepository.save(events, versionProvider); + return this.eventRepository.save(events, commandMetadata, versionProvider); } async handle(command: C & CM): Promise { const currentEvents = await this.eventRepository.fetch(command); return this.eventRepository.save( - this.computeNewEvents(currentEvents, command).map((evt) => ({ - ...evt, - ...command, - })), + this.computeNewEvents(currentEvents, command), + command, async () => currentEvents[currentEvents.length - 1] ); } @@ -288,25 +289,22 @@ export class EventSourcingOrchestratingAggregate } async save( - events: readonly (E & CM)[], + events: readonly E[], + commandMetadata: CM, versionProvider: (e: E) => Promise ): Promise { - return this.eventRepository.save(events, versionProvider); + return this.eventRepository.save(events, commandMetadata, versionProvider); } async handle(command: C & CM): Promise { const currentEvents = await this.eventRepository.fetch(command); return this.eventRepository.save( - ( - await this.computeNewEvents( - currentEvents, - command, - async (cmd: C & CM) => await this.eventRepository.fetch(cmd) - ) - ).map((event) => ({ - ...event, - ...command, - })), + await this.computeNewEvents( + currentEvents, + command, + async (cmd: C & CM) => await this.eventRepository.fetch(cmd) + ), + command, this.versionProvider.bind(this) ); } diff --git a/src/lib/application/materialized-view.spec.ts b/src/lib/application/materialized-view.spec.ts index 414f788..f7fb223 100644 --- a/src/lib/application/materialized-view.spec.ts +++ b/src/lib/application/materialized-view.spec.ts @@ -133,7 +133,8 @@ class ViewStateRepositoryImpl return storage; } async save( - s: ViewState & EventMetadata, + s: ViewState, + _: EventMetadata, v: Version | null ): Promise { storage = { diff --git a/src/lib/application/materialized-view.ts b/src/lib/application/materialized-view.ts index d7b51bc..5a48ed4 100644 --- a/src/lib/application/materialized-view.ts +++ b/src/lib/application/materialized-view.ts @@ -38,10 +38,15 @@ export interface IViewStateRepository { * Save state * * @param state - State and Event Metadata of type `S & EM` + * @param eventMetadata - Event Metadata of type `EM` * @param version - State version of type `V | null` * @return newly saved State and Version of type `S` & `V` */ - readonly save: (state: S & EM, version: V | null) => Promise; + readonly save: ( + state: S, + eventMetadata: EM, + version: V | null + ) => Promise; } /** @@ -97,8 +102,8 @@ export class MaterializedView return this.viewStateRepository.fetch(event); } - async save(state: S & EM, version: V | null): Promise { - return this.viewStateRepository.save(state, version); + async save(state: S, eventMetadata: EM, version: V | null): Promise { + return this.viewStateRepository.save(state, eventMetadata, version); } async handle(event: E & EM): Promise { @@ -108,7 +113,8 @@ export class MaterializedView event ); return this.viewStateRepository.save( - { ...(newState as S), ...(event as EM) }, + newState, + event as EM, currentStateAndVersion as V ); } diff --git a/src/lib/application/statestored-aggregate.spec.ts b/src/lib/application/statestored-aggregate.spec.ts index 334d485..ffc60ac 100644 --- a/src/lib/application/statestored-aggregate.spec.ts +++ b/src/lib/application/statestored-aggregate.spec.ts @@ -247,7 +247,7 @@ class StateRepositoryImpl async fetch(_c: Cmd): Promise<(State & Version) | null> { return stateStorage; } - async save(s: State & Cmd): Promise { + async save(s: State, _: Cmd): Promise { stateStorage = { evenNumber: s.evenNumber, oddNumber: s.oddNumber, @@ -269,12 +269,15 @@ class StateAndMetadataRepositoryImpl async fetch(_c: Cmd): Promise<(State & Version & StateMetadata) | null> { return stateAndMetadataStorage; } - async save(s: State & CmdMetadata): Promise { + async save( + s: State, + cm: CmdMetadata + ): Promise { stateAndMetadataStorage = { evenNumber: s.evenNumber, oddNumber: s.oddNumber, version: stateAndMetadataStorage.version + 1, - traceId: s.traceId, + traceId: cm.traceId, }; return stateAndMetadataStorage; } diff --git a/src/lib/application/statestored-aggregate.ts b/src/lib/application/statestored-aggregate.ts index 3f320f9..4c7ff12 100644 --- a/src/lib/application/statestored-aggregate.ts +++ b/src/lib/application/statestored-aggregate.ts @@ -42,10 +42,15 @@ export interface IStateRepository { * You can update/save the item/state, but only if the `version` number in the storage has not changed. * * @param state - State with Command Metadata of type `S & CM` + * @param commandMetadata - Command Metadata of the command that initiated the `state` * @param version - The current version of the state * @return newly saved State of type `S & V & SM` */ - readonly save: (state: S & CM, version: V | null) => Promise; + readonly save: ( + state: S, + commandMetadata: CM, + version: V | null + ) => Promise; } /** @@ -175,8 +180,12 @@ export class StateStoredAggregate return this.stateRepository.fetch(command); } - async save(state: S & CM, version: V | null): Promise { - return this.stateRepository.save(state, version); + async save( + state: S, + commandMetadata: CM, + version: V | null + ): Promise { + return this.stateRepository.save(state, commandMetadata, version); } async handle(command: C & CM): Promise { @@ -186,7 +195,8 @@ export class StateStoredAggregate command ); return this.stateRepository.save( - { ...newState, ...(command as CM) }, + newState, + command as CM, currentState as V ); } @@ -224,8 +234,12 @@ export class StateStoredOrchestratingAggregate return this.stateRepository.fetch(command); } - async save(state: S & CM, version: V | null): Promise { - return this.stateRepository.save(state, version); + async save( + state: S, + commandMetadata: CM, + version: V | null + ): Promise { + return this.stateRepository.save(state, commandMetadata, version); } async handle(command: C & CM): Promise { @@ -235,7 +249,8 @@ export class StateStoredOrchestratingAggregate command ); return this.stateRepository.save( - { ...newState, ...(command as CM) }, + newState, + command as CM, currentState as V ); }