UNPKG

evtstore

Version:

Event Sourcing with Node.JS

132 lines (131 loc) 5.05 kB
export type HandlerHooks = { preRun?: () => Promise<void>; postRun?: (events: number, handled: number) => Promise<void>; }; export type Event = { type: string; }; export type Command = { type: string; }; export type Aggregate = {}; export type StoreEvent<E = unknown, A = unknown> = EventMeta & { event: E & { __persisted?: A; }; }; export type ProviderBookmark = { readonly name: string; getPosition(): Promise<any>; setPosition(position: any): Promise<void>; }; export type DomainOptions<E extends Event, A extends Aggregate> = { aggregate: () => A; stream: string; fold: Fold<E, A>; provider: Provider<E> | Promise<Provider<E>>; useCache?: boolean; }; export type StreamsHandler<T extends { [key: string]: Event; }> = <TStream extends keyof T, TType extends T[TStream]['type']>(stream: TStream, type: TType, handler: (id: string, event: Ext<T[TStream], TType>, meta: EventMeta) => any) => void; export type HandlerBookmark = string | ProviderBookmark; export type EventMeta = { stream: string; position: any; version: number; timestamp: Date; aggregateId: string; }; export type ErrorCallback = (err: any, stream: string, bookmark: string, event?: Event & { [key: string]: any; }) => any; type ID = { aggregateId: string; }; export type BaseAggregate = { version: number; aggregateId: string; __pv?: string; }; export type Fold<E extends Event, A extends Aggregate> = (ev: E, agg: A & BaseAggregate, meta: EventMeta) => Partial<A>; export type Provider<Evt extends Event> = { driver: string; onError: ErrorCallback; getPosition(bookmark: string): Promise<any>; setPosition(bookmark: string, position: any): Promise<void>; getEventsFrom(stream: string | string[], position: any, limit?: number): Promise<Array<StoreEvent<Evt>>>; getEventsFor(stream: string, aggregateId: string, fromPosition?: any): Promise<Array<StoreEvent<Evt>>>; getLastEventFor(stream: string | string[], aggregateId?: string): Promise<StoreEvent<Evt & { __persisted?: any; }> | undefined>; createEvents(stream: string, aggregateId: string, version: number, event: Evt[]): Array<StoreEvent<Evt>>; append(stream: string, aggregateId: string, version: number, event: StoreEvent<Evt>[]): Promise<Array<StoreEvent<Evt>>>; limit?: number; }; export type Handler<E extends Event> = { start(): void; stop(): void; reset(): void; runOnce(): Promise<number>; handle: <T extends E['type']>(type: T, cb: (aggregateId: string, event: Ext<E, T>, meta: EventMeta) => Promise<any>) => void; handlers: (body: HandlerBody<E>) => void; name: string; }; export type Ext<E extends Event, T extends E['type']> = E extends { type: T; } ? E : never; export type CommandHandler<E extends Event, A extends Aggregate, C extends Command> = { [key in C['type']]: (cmd: OptCmd<C, key> & ID, agg: A & BaseAggregate) => Promise<E | E[] | void>; }; type OptCmd<C extends Command, T extends C['type']> = Omit<Ext<C, T>, 'type'> & { type: T; }; export type DomainHandlerOpts = { hooks?: HandlerHooks; /** Start handling events from the end of the stream */ tailStream?: boolean; /** Every time the handler starts, always start from the end of the stream */ alwaysTailStream?: boolean; /** When a handler throws, continue processing events */ continueOnError?: boolean; }; export type Domain<E extends Event, A extends Aggregate, C extends Command> = { handler(bookmark: string, options?: DomainHandlerOpts): Handler<E>; command: CmdBody<C, A>; getAggregate(id: string): Promise<ExecutableAggregate<C, A> & { aggregate: Readonly<A & BaseAggregate>; }>; retry?: boolean; }; export type CmdBody<C extends Command, A extends Aggregate> = { [cmd in C['type']]: (aggId: string, body: ExtCmd<C, cmd>) => Promise<A & BaseAggregate>; }; export type ExecutableAggregate<C extends Command, A extends Aggregate> = { [cmd in C['type']]: (body: ExtCmd<C, cmd>) => Promise<ExecutableAggregate<C, A> & { aggregate: Readonly<A & BaseAggregate>; }>; }; type ExtCmd<C extends Command, T extends C['type']> = Omit<Ext<C, T>, 'type'>; export type HandlerBody<E extends Event> = { [evt in E['type']]?: (id: string, evt: Ext<E, evt>, meta: EventMeta) => Promise<any>; }; export type StorableAggregate<E extends Event = any, A extends Aggregate = any, S extends string = string> = { stream: S; fold: Fold<E, A>; aggregate: () => A; version?: string; persistAggregate?: boolean; }; export type AggregateStore = { [key: string]: StorableAggregate; }; export type ProvidedAggregate<E extends Event, A extends Aggregate, S extends string = string> = { stream: S; provider: Provider<E> | Promise<Provider<E>>; getAggregate: (id: string) => Promise<A & BaseAggregate>; toNextAggregate: (prev: A & BaseAggregate, event: StoreEvent<E>) => A & BaseAggregate; version?: string; persistAggregate?: boolean; }; export {};