11/* eslint-disable max-lines */
22import type { Aggregate } from '~/aggregate' ;
33import type { EventDetail } from '~/event/eventDetail' ;
4- import type { EventType , EventTypeDetails } from '~/event/eventType' ;
4+ import type {
5+ EventDetailParser ,
6+ EventType ,
7+ EventTypeDetails ,
8+ } from '~/event/eventType' ;
59import { GroupedEvent } from '~/event/groupedEvent' ;
610import type { EventStorageAdapter } from '~/eventStorageAdapter' ;
711import type { $Contravariant } from '~/utils' ;
812
13+ import {
14+ EventDetailParserNotDefinedError ,
15+ EventDetailTypeDoesNotExistError ,
16+ } from './errors' ;
917import { AggregateNotFoundError } from './errors/aggregateNotFound' ;
1018import { UndefinedEventStorageAdapterError } from './errors/undefinedEventStorageAdapter' ;
1119import type {
@@ -20,6 +28,7 @@ import type {
2028 AggregateGetter ,
2129 AggregateSimulator ,
2230 Reducer ,
31+ ValidateEventDetail ,
2332} from './types' ;
2433
2534export class EventStore <
@@ -178,10 +187,58 @@ export class EventStore<
178187 */
179188 ) as Promise < { events : EVENT_DETAILS [ ] } > ;
180189
190+ const shouldValidateEventDetail = (
191+ validate : ValidateEventDetail ,
192+ eventDetailType : string ,
193+ eventType ?: EventType ,
194+ ) : eventType is EventType => {
195+ if ( validate === false ) {
196+ return false ;
197+ }
198+
199+ if ( eventType === undefined ) {
200+ throw new EventDetailTypeDoesNotExistError ( {
201+ type : eventDetailType ,
202+ allowedTypes : this . eventTypes . map ( ( { type } ) => type ) ,
203+ } ) ;
204+ }
205+
206+ if ( validate === 'auto' && eventType . parseEventDetail === undefined ) {
207+ return false ;
208+ }
209+
210+ return true ;
211+ } ;
212+
213+ const validateEventDetail = (
214+ eventDetail : EventDetail ,
215+ eventDetailParser ?: EventDetailParser ,
216+ ) => {
217+ if ( eventDetailParser === undefined ) {
218+ throw new EventDetailParserNotDefinedError ( eventDetail . type ) ;
219+ }
220+
221+ const { parsingErrors, isValid } = eventDetailParser ( eventDetail ) ;
222+
223+ if ( isValid ) {
224+ return ;
225+ }
226+
227+ throw new Error ( parsingErrors [ 0 ] . message ) ;
228+ } ;
229+
181230 this . pushEvent = async (
182231 eventDetail ,
183- { prevAggregate, force = false } = { } ,
232+ { prevAggregate, force = false , validate = 'auto' } = { } ,
184233 ) => {
234+ const eventType = this . eventTypes . find (
235+ ( { type } ) => type === eventDetail . type ,
236+ ) ;
237+
238+ if ( shouldValidateEventDetail ( validate , eventDetail . type , eventType ) ) {
239+ validateEventDetail ( eventDetail , eventType . parseEventDetail ) ;
240+ }
241+
185242 const eventStorageAdapter = this . getEventStorageAdapter ( ) ;
186243
187244 const { event } = ( await eventStorageAdapter . pushEvent ( eventDetail , {
0 commit comments