@evyweb/simple-ddd-toolkit
Version:
A simple Typescript Domain Driven Design Toolkit to help you create your aggregates, domain events, command handlers and other stuff.
195 lines (165 loc) • 6.14 kB
text/typescript
type Message = {
__TAG: string;
};
type Metadata = Record<string, unknown>;
type Payload = Record<string, unknown>;
interface DomainEventData {
eventId: string;
occurredOn?: Date;
payload?: Payload;
metadata?: Metadata;
}
declare abstract class DomainEvent implements Message {
abstract readonly __TAG: string;
readonly eventId: string;
readonly occurredOn: Date;
readonly payload: Payload;
readonly metadata: Metadata;
constructor(eventData: DomainEventData);
}
declare abstract class ValueObject<ValueObjectData> {
private readonly data;
protected constructor(data: ValueObjectData);
equals(other: ValueObject<ValueObjectData>): boolean;
get<T extends keyof ValueObjectData>(key: T): ValueObjectData[T];
private reflectiveEqual;
private deepFreeze;
}
interface UUIDData {
value: string;
isNew: boolean;
}
declare class UUID extends ValueObject<UUIDData> {
static readonly UUID_PATTERN: RegExp;
static create(value: string, isNew?: boolean): UUID;
static createFrom(value: string): UUID;
equals(other: ValueObject<UUIDData>): boolean;
static isValid(uuid: string): boolean;
isNew(): boolean;
}
declare abstract class Entity<EntityData extends {
id: UUID;
}> {
private readonly data;
protected constructor(entityData: EntityData);
id(): string;
get<Key extends keyof EntityData>(key: Key): EntityData[Key];
protected set<Key extends keyof EntityData>(key: Key, value: EntityData[Key]): void;
equals(other: Entity<EntityData>): boolean;
isNew(): boolean;
toObject(): Readonly<EntityData>;
}
interface IEventHandler<T extends DomainEvent> {
readonly __TAG: string;
handle(event: T): Promise<void>;
}
interface IEventMiddleware {
execute(event: DomainEvent, next: (event: DomainEvent) => Promise<void>): Promise<void>;
}
interface EventBusPort {
use(middleware: IEventMiddleware): void;
on(eventType: string, handler: () => IEventHandler<DomainEvent>): void;
dispatch(domainEvent: DomainEvent): Promise<void>;
dispatchEvents(events: DomainEvent[]): Promise<void>;
dispatchEventsAsync(events: DomainEvent[]): void;
}
declare abstract class Aggregate<EntityData extends {
id: UUID;
}> extends Entity<EntityData> {
private domainEvents;
addEvent(domainEvent: DomainEvent): void;
clearEvents(): void;
dispatchEvents(bus: EventBusPort): Promise<void>;
dispatchEventsAsync(bus: EventBusPort): void;
getEvents(): DomainEvent[];
}
interface IMessageHandler<M extends Message, R = unknown> {
__TAG: string;
handle(message: M): Promise<R>;
}
interface Middleware<T> {
execute: <R>(message: T, next: (message: T) => Promise<R>) => Promise<R>;
}
declare class Bus<M extends Message> {
private handlers;
private middlewares;
register<R>(handlerFactory: () => IMessageHandler<M, R>): void;
use(middleware: Middleware<M>): void;
execute<R>(message: M): Promise<R>;
}
declare abstract class Command implements Message {
abstract readonly __TAG: string;
}
declare abstract class CommandHandler<TCommand extends Command, TResponse = void> {
abstract readonly __TAG: string;
abstract handle(command: TCommand): Promise<TResponse>;
}
interface Logger {
log: (message: string) => void;
}
declare class CommandLoggerMiddleware implements Middleware<Command> {
private readonly logger;
private readonly middlewareId;
constructor(logger: Logger, middlewareId: string);
execute<T>(command: Command, next: (command: Command) => Promise<T>): Promise<T>;
}
declare abstract class Query {
abstract readonly __TAG: string;
}
declare class QueryLoggerMiddleware implements Middleware<Query> {
private readonly logger;
private readonly middlewareId;
constructor(logger: Logger, middlewareId: string);
execute<T>(query: Query, next: (query: Query) => Promise<T>): Promise<T>;
}
declare abstract class QueryHandler<TQuery extends Query, TResponse> {
abstract readonly __TAG: string;
abstract handle(query: TQuery): Promise<TResponse>;
}
declare abstract class CustomError extends Error {
abstract readonly __TAG: string;
protected constructor(message?: string);
abstract isDomainError(): boolean;
abstract isTechnicalError(): boolean;
}
declare abstract class DomainError extends CustomError {
isDomainError(): boolean;
isTechnicalError(): boolean;
}
declare abstract class TechnicalError extends CustomError {
isDomainError(): boolean;
isTechnicalError(): boolean;
}
declare class EventBus implements EventBusPort {
private middlewares;
private readonly handlers;
use(middleware: IEventMiddleware): void;
on(eventType: string, handler: () => IEventHandler<DomainEvent>): void;
dispatch(domainEvent: DomainEvent): Promise<void>;
dispatchEvents(events: DomainEvent[]): Promise<void>;
dispatchEventsAsync(events: DomainEvent[]): void;
}
type Success<ValueType> = {
_tag: 'success';
value: ValueType;
};
type Failure<ErrorType extends Error> = {
_tag: 'failure';
error: ErrorType;
};
declare class Result<ValueType, ErrorType extends Error> {
private readonly result;
private constructor();
static ok<ValueType, ErrorType extends Error>(value: ValueType): Result<ValueType, ErrorType>;
static fail<ValueType, ErrorType extends Error>(error: ErrorType): Result<ValueType, ErrorType>;
isOk(): this is Success<ValueType>;
isFail(): this is Failure<ErrorType>;
getValue(): ValueType;
getError(): ErrorType;
}
interface IUseCase<Request> {
execute(request?: Request): Promise<void>;
}
declare function Uuid(value: string, isNew?: boolean): UUID;
declare function UuidFrom(value: string): UUID;
export { Aggregate, Bus, Command, CommandHandler, CommandLoggerMiddleware, CustomError, DomainError, DomainEvent, Entity, EventBus, type EventBusPort, type IEventHandler, type IUseCase, type Logger, type Message, type Metadata, type Payload, Query, QueryHandler, QueryLoggerMiddleware, Result, TechnicalError, UUID, type UUIDData, Uuid, UuidFrom, ValueObject };