@arts-n-crafts/ts 3.13.2 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -48,7 +48,7 @@ function isQuery(candidate) {
48
48
  }
49
49
 
50
50
  // src/domain/Specification/Specification.ts
51
- var Specification = class {
51
+ var CompositeSpecification = class {
52
52
  and(other) {
53
53
  return new AndSpecification(this, other);
54
54
  }
@@ -59,7 +59,7 @@ var Specification = class {
59
59
  return new NotSpecification(this);
60
60
  }
61
61
  };
62
- var AndSpecification = class extends Specification {
62
+ var AndSpecification = class extends CompositeSpecification {
63
63
  constructor(left, right) {
64
64
  super();
65
65
  this.left = left;
@@ -75,7 +75,7 @@ var AndSpecification = class extends Specification {
75
75
  };
76
76
  }
77
77
  };
78
- var OrSpecification = class extends Specification {
78
+ var OrSpecification = class extends CompositeSpecification {
79
79
  constructor(left, right) {
80
80
  super();
81
81
  this.left = left;
@@ -91,7 +91,7 @@ var OrSpecification = class extends Specification {
91
91
  };
92
92
  }
93
93
  };
94
- var NotSpecification = class extends Specification {
94
+ var NotSpecification = class extends CompositeSpecification {
95
95
  constructor(spec) {
96
96
  super();
97
97
  this.spec = spec;
@@ -123,7 +123,7 @@ function createQueryNode(type, field, value) {
123
123
  }
124
124
 
125
125
  // src/domain/Specification/implementations/FieldEquals.specification.ts
126
- var FieldEquals = class extends Specification {
126
+ var FieldEquals = class extends CompositeSpecification {
127
127
  constructor(field, value) {
128
128
  super();
129
129
  this.field = field;
@@ -151,7 +151,7 @@ function invariant(condition, onInvalid) {
151
151
  }
152
152
 
153
153
  // src/domain/Specification/implementations/FieldGreaterThan.specification.ts
154
- var FieldGreaterThan = class extends Specification {
154
+ var FieldGreaterThan = class extends CompositeSpecification {
155
155
  constructor(field, value) {
156
156
  super();
157
157
  this.field = field;
@@ -623,6 +623,7 @@ var ScenarioTest = class {
623
623
  };
624
624
 
625
625
  exports.AndSpecification = AndSpecification;
626
+ exports.CompositeSpecification = CompositeSpecification;
626
627
  exports.FieldEquals = FieldEquals;
627
628
  exports.FieldGreaterThan = FieldGreaterThan;
628
629
  exports.GenericOutboxWorker = GenericOutboxWorker;
@@ -637,7 +638,6 @@ exports.SimpleEventBus = SimpleEventBus;
637
638
  exports.SimpleEventStore = SimpleEventStore;
638
639
  exports.SimpleQueryBus = SimpleQueryBus;
639
640
  exports.SimpleRepository = SimpleRepository;
640
- exports.Specification = Specification;
641
641
  exports.createCommand = createCommand;
642
642
  exports.createDomainEvent = createDomainEvent;
643
643
  exports.createIntegrationEvent = createIntegrationEvent;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/utils/createCommand.ts","../src/core/utils/createQuery.ts","../src/core/utils/isCommand.ts","../src/core/utils/isQuery.ts","../src/domain/Specification/Specification.ts","../src/domain/Specification/utils/createQueryNode.ts","../src/domain/Specification/implementations/FieldEquals.specification.ts","../src/utils/fail/fail.ts","../src/utils/invariant/invariant.ts","../src/domain/Specification/implementations/FieldGreaterThan.specification.ts","../src/domain/utils/createDomainEvent.ts","../src/domain/utils/isEvent.ts","../src/domain/utils/isDomainEvent.ts","../src/infrastructure/CommandBus/implementations/SimpleCommandBus.ts","../src/infrastructure/Database/Database.ts","../src/infrastructure/Database/implementations/SimpleDatabase.exceptions.ts","../src/infrastructure/Database/implementations/SimpleDatabase.ts","../src/infrastructure/EventBus/implementations/SimpleEventBus.ts","../src/infrastructure/EventBus/utils/createIntegrationEvent.ts","../src/infrastructure/EventBus/utils/isIntegrationEvent.ts","../src/utils/isEqual/isEqual.ts","../src/utils/parseAsError/parseAsError.ts","../src/utils/streamKey/makeStreamKey.ts","../src/infrastructure/EventStore/utils/createStoredEvent.ts","../src/infrastructure/EventStore/implementations/SimpleEventStore.exceptions.ts","../src/infrastructure/EventStore/implementations/SimpleEventStore.ts","../src/infrastructure/Outbox/implementations/GenericOutboxWorker.ts","../src/infrastructure/Outbox/implementations/InMemoryOutbox.ts","../src/infrastructure/Outbox/utils/createOutboxEntry.ts","../src/infrastructure/QueryBus/implementations/SimpleQueryBus.ts","../src/infrastructure/Repository/implementations/SimpleRepository.ts","../src/infrastructure/ScenarioTest/ScenarioTest.ts"],"names":["randomUUID","Operation","event"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Command, CommandMetadata } from '@core/Command.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createCommand<TType extends string, TPayload>(type: TType, aggregateId: string, payload: TPayload, metadata: Partial<CommandMetadata> = {}): Command<TType, TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n aggregateId: String(aggregateId),\n payload,\n kind: 'command' as const,\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { Query, QueryMetadata } from '@core/Query.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createQuery<TType extends string, TPayload>(type: TType, payload: TPayload, metadata: QueryMetadata = {}): Query<TType, TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n payload,\n kind: 'query',\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { Command } from '@core/Command.ts'\n\nexport function isCommand(candidate: unknown): candidate is Command<string, unknown> {\n if (candidate === null)\n return false\n if (typeof candidate !== 'object')\n return false\n if (!('type' in candidate))\n return false\n return 'kind' in candidate && candidate.kind === 'command'\n}\n","import type { Query } from '@core/Query.ts'\n\nexport function isQuery(candidate: unknown): candidate is Query<unknown> {\n if (candidate === null)\n return false\n if (typeof candidate !== 'object')\n return false\n if (!('type' in candidate))\n return false\n return 'kind' in candidate && candidate.kind === 'query'\n}\n","import type { QueryNode } from './QueryNode.ts'\n\nexport abstract class Specification<T> {\n abstract isSatisfiedBy(entity: T): boolean\n abstract toQuery(): QueryNode\n\n and(other: Specification<T>): Specification<T> {\n return new AndSpecification(this, other)\n }\n\n or(other: Specification<T>): Specification<T> {\n return new OrSpecification(this, other)\n }\n\n not(): Specification<T> {\n return new NotSpecification(this)\n }\n}\n\nexport class AndSpecification<T> extends Specification<T> {\n constructor(private left: Specification<T>, private right: Specification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return this.left.isSatisfiedBy(entity) && this.right.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'and',\n nodes: [this.left.toQuery(), this.right.toQuery()],\n }\n }\n}\n\nexport class OrSpecification<T> extends Specification<T> {\n constructor(private left: Specification<T>, private right: Specification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return this.left.isSatisfiedBy(entity) || this.right.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'or',\n nodes: [this.left.toQuery(), this.right.toQuery()],\n }\n }\n}\n\nexport class NotSpecification<T> extends Specification<T> {\n constructor(private spec: Specification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return !this.spec.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'not',\n node: this.spec.toQuery(),\n }\n }\n}\n","import type { Primitive } from '@core/types/Primitive.ts'\nimport type { QueryNode } from '../QueryNode.ts'\n\nexport function createQueryNode(type: 'eq' | 'gt' | 'lt', field: string | number | symbol, value: Primitive): QueryNode\nexport function createQueryNode(type: 'and' | 'or', field: undefined, value: QueryNode[]): QueryNode\nexport function createQueryNode(type: 'not', field: undefined, value: QueryNode): QueryNode\nexport function createQueryNode(\n type: QueryNode['type'],\n field: string | number | symbol | undefined,\n value: Primitive | QueryNode | QueryNode[],\n): QueryNode {\n switch (type) {\n case 'eq':\n case 'gt':\n case 'lt':\n return { type, field: field as string, value: value as Primitive }\n case 'and':\n case 'or':\n return { type, nodes: value as QueryNode[] }\n case 'not':\n return { type, node: value as QueryNode }\n }\n}\n","import type { Primitive } from '@core/types/Primitive.ts'\nimport type { QueryNode } from '../QueryNode.ts'\nimport { Specification } from '../Specification.ts'\nimport { createQueryNode } from '../utils/createQueryNode.ts'\n\nexport class FieldEquals<T> extends Specification<T> {\n constructor(private field: keyof T, private value: Primitive) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return entity[this.field] === this.value\n }\n\n toQuery(): QueryNode {\n return createQueryNode('eq', this.field, this.value)\n }\n}\n","export function fail(anExpression: Error) {\n return () => {\n throw anExpression\n }\n}\n","export function invariant(condition: boolean, onInvalid: () => never): asserts condition {\n if (!condition)\n onInvalid()\n}\n","import type { QueryNode } from '../QueryNode.ts'\nimport { fail } from '@utils/fail/fail.ts'\nimport { invariant } from '@utils/invariant/invariant.ts'\nimport { Specification } from '../Specification.ts'\nimport { createQueryNode } from '../utils/createQueryNode.ts'\n\nexport class FieldGreaterThan<T> extends Specification<T> {\n constructor(\n private field: keyof T,\n private value: number,\n ) {\n super()\n }\n\n private isNumber(value: unknown): value is number {\n return typeof value === 'number'\n }\n\n isSatisfiedBy(entity: T): boolean {\n const field = entity[this.field]\n invariant(\n this.isNumber(field),\n fail(new TypeError(`Field ${String(this.field)} is not a number`),\n ),\n )\n return field > this.value\n }\n\n toQuery(): QueryNode {\n return createQueryNode('gt', this.field, this.value)\n }\n}\n","import type { DomainEvent, DomainEventMetadata } from '@domain/DomainEvent.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createDomainEvent<TPayload = unknown>(\n type: string,\n aggregateId: string,\n payload: TPayload,\n metadata: Partial<DomainEventMetadata> = {},\n): DomainEvent<TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n aggregateId,\n payload,\n source: 'internal',\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { BaseEvent } from '@domain/BaseEvent.ts'\n\nexport function isEvent(event: unknown): event is BaseEvent {\n if (typeof event !== 'object')\n return false\n if (event === null)\n return false\n if (!('type' in event))\n return false\n return 'source' in event\n}\n","import type { DomainEvent } from '../DomainEvent.ts'\nimport { isEvent } from './isEvent.ts'\n\nexport function isDomainEvent(event: unknown): event is DomainEvent {\n return isEvent(event)\n && 'aggregateId' in event\n && event.source === 'internal'\n}\n","import type { Command } from '@core/Command.ts'\nimport type { CommandHandler } from '@core/CommandHandler.ts'\nimport type { CommandBus } from '../CommandBus.ts'\n\nexport class SimpleCommandBus<TCommand extends Command> implements CommandBus<TCommand> {\n private handlers: Map<TCommand['type'], CommandHandler<TCommand>> = new Map()\n\n register(aTypeOfCommand: TCommand['type'], anHandler: CommandHandler<TCommand>): void {\n if (this.handlers.has(aTypeOfCommand)) {\n throw new Error(`Handler already registered for command type: ${aTypeOfCommand}`)\n }\n this.handlers.set(aTypeOfCommand, anHandler)\n }\n\n async execute(aCommand: TCommand): Promise<void> {\n const handler = this.handlers.get(aCommand.type)\n if (!handler) {\n throw new Error(`No handler found for command type: ${aCommand.type}`)\n }\n return handler.execute(aCommand)\n }\n}\n","import type { Specification } from '@domain/Specification/Specification.ts'\nimport type { WithIdentifier } from '../../core/types/WithIdentifier.ts'\n\nexport enum Operation {\n CREATE = 'CREATE',\n PUT = 'PUT',\n PATCH = 'PATCH',\n DELETE = 'DELETE',\n}\n\ninterface Statement<TModel> {\n operation: Operation\n payload: TModel\n}\n\nexport interface CreateStatement<TModel> extends Statement<TModel> {\n operation: Operation.CREATE\n payload: TModel\n}\n\nexport interface PutStatement<TModel> extends Statement<TModel> {\n operation: Operation.PUT\n payload: TModel\n}\n\nexport interface PatchStatement<TModel> extends Statement<Partial<TModel>> {\n operation: Operation.PATCH\n payload: WithIdentifier<Partial<TModel>>\n}\n\nexport interface DeleteStatement extends Statement<WithIdentifier> {\n operation: Operation.DELETE\n payload: WithIdentifier\n}\n\ninterface Executable<TModel, TReturnType = Promise<void>> {\n execute(tableName: string, statement: CreateStatement<TModel>): TReturnType\n execute(tableName: string, statement: PutStatement<TModel>): TReturnType\n execute(tableName: string, statement: PatchStatement<TModel>): TReturnType\n execute(tableName: string, statement: DeleteStatement): TReturnType\n}\n\ninterface QueryAble<TModel, TReturnType = Promise<TModel[]>> {\n query(collectionName: string, specification: Specification<TModel>): TReturnType\n}\n\nexport interface Database<TModel, TExecuteReturnType = Promise<void>, TQueryReturnType = Promise<TModel[]>>\n extends\n QueryAble<TModel, TQueryReturnType>,\n Executable<TModel, TExecuteReturnType> { }\n","export class RecordNotFoundException extends Error {\n constructor(id: string) {\n super(`Record not found for id: ${id}`)\n }\n}\n\nexport class DuplicateRecordException extends Error {\n constructor(id: string) {\n super(`Duplicate record found for id: ${id}`)\n }\n}\n\nexport class DatabaseOfflineException extends Error {\n constructor() {\n super(`Database is offline`)\n }\n}\n","import type { Specification } from '@domain/Specification/Specification.ts'\nimport type { WithIdentifier } from '../../../core/types/WithIdentifier.ts'\nimport type { CreateStatement, Database, DeleteStatement, PatchStatement, PutStatement } from '../Database.ts'\nimport { Operation } from '../Database.ts'\nimport { DatabaseOfflineException, DuplicateRecordException, RecordNotFoundException } from './SimpleDatabase.exceptions.ts'\n\nexport class SimpleDatabase<TModel extends WithIdentifier> implements Database<TModel, Promise<void>, Promise<TModel[]>> {\n private readonly datasource = new Map<string, TModel[]>()\n private simulateOffline = false\n\n async query(\n tableName: string,\n specification: Specification<TModel>,\n ): Promise<TModel[]> {\n if (this.simulateOffline)\n throw new DatabaseOfflineException()\n\n const tableRecords = (this.datasource.get(tableName) || [])\n return tableRecords\n .filter((record: TModel) => specification.isSatisfiedBy(record))\n }\n\n async execute(\n tableName: string,\n statement: CreateStatement<TModel> | PutStatement<TModel> | PatchStatement<TModel> | DeleteStatement,\n ): Promise<void> {\n if (this.simulateOffline)\n throw new DatabaseOfflineException()\n\n if (!this.datasource.has(tableName))\n this.datasource.set(tableName, [])\n const table = this.datasource.get(tableName)!\n\n switch (statement.operation) {\n case Operation.CREATE: {\n const isDuplicate = table.some(item => item.id === statement.payload.id)\n if (isDuplicate)\n throw new DuplicateRecordException(statement.payload.id)\n table.push(statement.payload)\n break\n }\n case Operation.PUT:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table[index] = statement.payload\n break\n }\n case Operation.PATCH:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table[index] = { ...table[index], ...statement.payload }\n break\n }\n case Operation.DELETE:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table.splice(index, 1)\n break\n }\n }\n }\n\n goOffline(): void {\n this.simulateOffline = true\n }\n}\n","import type { EventHandler } from '@core/EventHandler.ts'\nimport type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { EventConsumer, EventProducer } from '../EventBus.ts'\n\nexport class SimpleEventBus<TEvent extends BaseEvent>\nimplements EventConsumer<TEvent>, EventProducer<TEvent> {\n private handlers = new Map<string, EventHandler<TEvent>[]>()\n\n subscribe(\n stream: string,\n aHandler: EventHandler<TEvent>,\n ): void {\n const handlersForType = this.handlers.get(stream) ?? []\n handlersForType.push(aHandler)\n this.handlers.set(stream, handlersForType)\n }\n\n async consume(stream: string, anEvent: TEvent): Promise<void> {\n if (!this.handlers.has(stream))\n return\n const handlers = this.handlers.get(stream) as EventHandler<TEvent>[]\n await Promise.all(handlers.map(async (handler) => {\n return handler.handle(anEvent)\n }))\n }\n\n async publish(stream: string, anEvent: TEvent): Promise<void> {\n await this.consume(stream, anEvent)\n }\n}\n","import type { IntegrationEvent, IntegrationEventMetadata } from '../IntegrationEvent.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createIntegrationEvent<TPayload = unknown>(type: string, payload: TPayload, metadata?: Partial<IntegrationEventMetadata>): IntegrationEvent<TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n payload,\n source: 'external',\n timestamp: new Date().toISOString(),\n metadata: {\n ...metadata,\n },\n })\n}\n","import type { IntegrationEvent } from '../IntegrationEvent.ts'\nimport { isEvent } from '@domain/utils/isEvent.ts'\n\nexport function isIntegrationEvent<TPayload>(event: unknown): event is IntegrationEvent<TPayload> {\n return isEvent(event)\n && event.source === 'external'\n}\n","export function isEqual<T>(a: T, b: T): boolean {\n if (a === b) {\n return true\n }\n\n // eslint-disable-next-line ts/strict-boolean-expressions\n const bothAreObjects = a && b && typeof a === 'object' && typeof b === 'object'\n\n return Boolean(\n bothAreObjects\n && Object.keys(a).length === Object.keys(b).length\n && Object.entries(a).every(([k, v]) => isEqual(v, b[k as keyof T])),\n )\n}\n","export function parseAsError(value: unknown): Error {\n if (value instanceof Error)\n return value\n if (typeof value === 'string')\n return new Error(value)\n try {\n const json = JSON.stringify(value)\n return new Error(json ?? String(value))\n }\n catch {\n return new Error('Unknown error')\n }\n}\n","import type { StreamKey } from '@utils/streamKey/StreamKey.ts'\n\nexport function makeStreamKey(streamName: string, aggregateId: string): StreamKey {\n return `${streamName}#${aggregateId}`\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { StoredEvent } from '../StoredEvent.ts'\nimport { makeStreamKey } from '@utils/index.ts'\n\nexport function createStoredEvent<TEvent extends DomainEvent>(\n streamName: string,\n version: number,\n event: TEvent,\n): StoredEvent<TEvent> {\n return Object.freeze({\n id: event.id,\n streamKey: makeStreamKey(streamName, event.aggregateId),\n version,\n createdAt: new Date().toISOString(),\n event,\n })\n}\n","export class MultipleAggregatesException extends Error {\n constructor() {\n super('EventStore append does not support multiple aggregates to be stored')\n }\n}\n","import type { DomainEvent } from '@domain/index.ts'\nimport type { Database } from '@infrastructure/Database/Database.ts'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\nimport type { Outbox } from '@infrastructure/Outbox/Outbox.ts'\nimport type { StreamKey } from '@utils/index.ts'\nimport type { StoredEvent } from '../StoredEvent.ts'\nimport { FieldEquals } from '@domain/index.ts'\nimport { Operation } from '@infrastructure/Database/Database.ts'\nimport { makeStreamKey } from '@utils/index.ts'\nimport { createStoredEvent } from '../utils/createStoredEvent.ts'\nimport { MultipleAggregatesException } from './SimpleEventStore.exceptions.ts'\n\nexport class SimpleEventStore<TEvent extends DomainEvent> implements EventStore<TEvent, Promise<void>, Promise<TEvent[]>> {\n private readonly tableName: string = 'event_store'\n\n constructor(\n private readonly database: Database<StoredEvent<TEvent>, Promise<void>, Promise<StoredEvent<TEvent>[]>>,\n private readonly outbox?: Outbox,\n ) { }\n\n async load(streamName: string, aggregateId: string): Promise<TEvent[]> {\n const streamKey: StreamKey = makeStreamKey(streamName, aggregateId)\n const specification = new FieldEquals('streamKey', streamKey)\n const storedEvents = await this.database.query(this.tableName, specification)\n return storedEvents.map(storedEvent => storedEvent.event)\n }\n\n async append(streamName: string, events: TEvent[]): Promise<void> {\n const uniqueAggregateIds = new Set(events.map(event => event.aggregateId))\n if (uniqueAggregateIds.size > 1)\n throw new MultipleAggregatesException()\n\n const event = events[0]\n const currentStream = await this.load(streamName, event.aggregateId)\n const eventsToStore = events\n .map(event => createStoredEvent(streamName, currentStream.length + 1, event))\n await Promise.all(\n eventsToStore.map(async payload => this.database.execute(this.tableName, { operation: Operation.CREATE, payload }),\n ),\n )\n await Promise.all(events.map(async event => this.outbox?.enqueue(event)))\n }\n}\n","import type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { EventProducer } from '@infrastructure/EventBus/EventBus.js'\nimport type { OutboxWorker } from '@infrastructure/Outbox/OutboxWorker.ts'\nimport type { Outbox } from '../Outbox.ts'\n\nexport class GenericOutboxWorker implements OutboxWorker {\n constructor(\n protected outbox: Outbox,\n protected eventBus: EventProducer<BaseEvent>,\n protected stream: string,\n ) {}\n\n async runOnce(): Promise<void> {\n const pending = await this.outbox.getPending()\n\n await Promise.all(pending.map(async (entry) => {\n try {\n await this.eventBus.publish(this.stream, entry.event)\n await this.outbox.markAsPublished(entry.id)\n }\n catch {\n await this.outbox.markAsFailed(entry.id)\n }\n }))\n }\n\n async tick(): Promise<void> {\n await this.runOnce()\n }\n\n start(intervalMs: number): void {\n setInterval(() => {\n void this.tick().catch(console.error)\n }, intervalMs)\n }\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Outbox } from '../Outbox.ts'\nimport type { OutboxEntry } from '../OutboxEntry.ts'\n\nexport class InMemoryOutbox implements Outbox {\n protected entries: OutboxEntry[] = []\n protected idCounter = 0\n\n async enqueue(event: DomainEvent<unknown>): Promise<void> {\n this.entries.push({\n id: (this.idCounter++).toString(),\n event,\n published: false,\n retryCount: 0,\n })\n }\n\n async getPending(limit = 100): Promise<OutboxEntry[]> {\n return this.entries.filter(e => !e.published).slice(0, limit)\n }\n\n async markAsPublished(id: string): Promise<void> {\n const entry = this.entries.find(e => e.id === id)\n if (entry) {\n entry.published = true\n }\n }\n\n async markAsFailed(id: string): Promise<void> {\n const entry = this.entries.find(e => e.id === id)\n if (entry) {\n entry.retryCount += 1\n entry.lastAttemptAt = new Date().toISOString()\n }\n }\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { OutboxEntry } from '../OutboxEntry.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createOutboxEntry(\n event: DomainEvent<unknown>,\n): OutboxEntry {\n return Object.freeze({\n id: randomUUID(),\n event,\n published: false,\n retryCount: 0,\n lastAttemptAt: undefined,\n })\n}\n","import type { Query } from '@core/Query.ts'\nimport type { QueryHandler } from '@core/QueryHandler.ts'\nimport type { QueryBus } from '../QueryBus.ts'\n\nexport class SimpleQueryBus<TQuery extends Query, TProjection> implements QueryBus<TQuery, Promise<TProjection>> {\n private handlers: Map<TQuery['type'], QueryHandler<TQuery, Promise<TProjection>>> = new Map()\n\n register(\n aTypeOfQuery: TQuery['type'],\n anHandler: QueryHandler<TQuery, Promise<TProjection>>,\n ): void {\n if (this.handlers.has(aTypeOfQuery)) {\n throw new Error(`Handler already registered for query type: ${aTypeOfQuery}`)\n }\n this.handlers.set(aTypeOfQuery, anHandler)\n }\n\n async execute(aQuery: TQuery): Promise<TProjection> {\n const handler = this.handlers.get(aQuery.type)\n if (!handler) {\n throw new Error(`No handler found for query type: ${aQuery.type}`)\n }\n return handler.execute(aQuery)\n }\n}\n","import type { Decider } from '@domain/Decider.ts'\nimport type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Repository } from '@domain/Repository.ts'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\n\nexport class SimpleRepository<TState, TCommand, TEvent extends DomainEvent> implements Repository<TEvent, Promise<TState>, Promise<void>> {\n constructor(\n private readonly eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>,\n readonly streamName: string,\n private readonly evolveFn: Decider<TState, TCommand, TEvent>['evolve'],\n private readonly initialState: Decider<TState, TCommand, TEvent>['initialState'],\n ) {\n }\n\n async load(aggregateId: string): Promise<TState> {\n const pastEvents = await this.eventStore.load(this.streamName, aggregateId)\n return pastEvents\n .reduce<TState>(this.evolveFn, this.initialState(aggregateId))\n }\n\n async store(events: TEvent[]): Promise<void> {\n await Promise.all(\n events.map(\n async event => this.eventStore.append(\n this.streamName,\n [event],\n ),\n ),\n )\n }\n}\n","import type { Command } from '@core/Command.ts'\nimport type { Query } from '@core/Query.ts'\nimport type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Repository } from '@domain/Repository.ts'\nimport type { EventConsumer, EventProducer } from '@infrastructure/EventBus/EventBus.js'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\nimport type { OutboxWorker } from '@infrastructure/Outbox/OutboxWorker.ts'\nimport type { CommandBus } from '../CommandBus/CommandBus.ts'\nimport type { IntegrationEvent } from '../EventBus/IntegrationEvent.ts'\nimport type { QueryBus } from '../QueryBus/QueryBus.ts'\nimport { isCommand } from '@core/utils/isCommand.ts'\nimport { isQuery } from '@core/utils/isQuery.ts'\nimport { isDomainEvent } from '@domain/utils/isDomainEvent.ts'\nimport { isEvent } from '@domain/utils/isEvent.ts'\nimport { fail } from '@utils/fail/fail.ts'\nimport { invariant } from '@utils/invariant/invariant.ts'\nimport { isEqual } from '@utils/isEqual/isEqual.ts'\nimport { isIntegrationEvent } from '../EventBus/utils/isIntegrationEvent.ts'\n\ntype GivenInput = (DomainEvent | IntegrationEvent)[]\ntype WhenInput = Command | Query | DomainEvent | IntegrationEvent\ntype ThenInput = DomainEvent | Array<Record<string, unknown>>\n\nexport class ScenarioTest<TState, TEvent extends DomainEvent> {\n private givenInput: GivenInput = []\n private whenInput: WhenInput | undefined\n\n constructor(\n private readonly streamName: string,\n private readonly eventBus: EventProducer<BaseEvent> & EventConsumer<BaseEvent>,\n private readonly eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>,\n private readonly commandBus: CommandBus<Command>,\n private readonly queryBus: QueryBus<Query, Promise<Record<string, unknown>[]>>,\n private readonly repository: Repository<DomainEvent, Promise<TState>>,\n private readonly outboxWorker: OutboxWorker,\n ) {}\n\n given(...events: GivenInput): {\n when(action: WhenInput): ReturnType<ScenarioTest<TState, TEvent>['when']>\n then(outcome: ThenInput): Promise<void>\n } {\n this.givenInput = events\n return {\n when: this.when.bind(this),\n then: this.then.bind(this),\n }\n }\n\n when(action: WhenInput): {\n then(outcome: ThenInput): Promise<void>\n } {\n this.whenInput = action\n return {\n then: this.then.bind(this),\n }\n }\n\n async then(thenInput: ThenInput): Promise<void> {\n const domainEvents = this.givenInput\n .filter(isDomainEvent)\n const integrationEvents = this.givenInput\n .filter(isIntegrationEvent)\n\n await Promise.all([\n this.repository.store(domainEvents),\n integrationEvents.map(async event => this.eventBus.consume(this.streamName, event)),\n ])\n\n if (!this.whenInput) {\n throw new Error('In the ScenarioTest, the when-step cannot be empty')\n }\n\n if (isCommand(this.whenInput)) {\n invariant(isDomainEvent(thenInput), fail(new TypeError('When \\\"command\\\" expects a domain event in the then-step')))\n await this.handleCommand(this.whenInput, thenInput)\n }\n\n if (isQuery(this.whenInput)) {\n invariant(Array.isArray(thenInput), fail(new TypeError('When \\\"query\\\" expects an array of expected results in the then-step')))\n await this.handleQuery(this.whenInput, thenInput)\n }\n\n if (isDomainEvent(this.whenInput) || isIntegrationEvent(this.whenInput)) {\n invariant(isDomainEvent(thenInput), fail(new TypeError('When \\\"domain event\\\" or \\\"integration event\\\" expects a domain event in the then-step')))\n await this.handleEvent(this.whenInput, thenInput)\n }\n }\n\n private async handleCommand(command: Command, outcome: DomainEvent): Promise<void> {\n await this.commandBus.execute(command)\n const actualEvents = await this.eventStore.load(this.streamName, outcome.aggregateId)\n const foundEvent = actualEvents.findLast(\n event =>\n isDomainEvent(event)\n && event.aggregateId === outcome.aggregateId\n && event.type === outcome.type,\n )\n invariant(!!foundEvent, fail(new Error('ScenarioTest: event/command was not found')))\n invariant(\n outcome.type === foundEvent.type,\n fail(new Error('ScenarioTest: event/command type was not equal')),\n )\n invariant(\n outcome.aggregateId === foundEvent.aggregateId,\n fail(new Error('ScenarioTest: event/command aggregate id was not equal')),\n )\n invariant(\n isEqual(outcome.payload, foundEvent.payload),\n fail(new Error('ScenarioTest: event/command payload was not equal')),\n )\n }\n\n private async handleQuery(query: Query, expected: Array<Record<string, unknown>>): Promise<void> {\n await this.outboxWorker.tick()\n const actual = await this.queryBus.execute(query)\n invariant(\n isEqual(actual, expected),\n fail(new Error('ScenarioTest: a different query result was returned')),\n )\n }\n\n private async handleEvent(\n event: DomainEvent | IntegrationEvent,\n outcome: DomainEvent,\n ): Promise<void> {\n await this.eventBus.publish(this.streamName, event)\n const actualEvents = await this.eventStore.load(this.streamName, outcome.aggregateId)\n const foundEvent = actualEvents.findLast(\n event =>\n isEvent(event) && event.aggregateId === outcome.aggregateId && event.type === outcome.type,\n )\n invariant(!!foundEvent, fail(new Error('ScenarioTest: event was not found')))\n invariant(isEvent(foundEvent), fail(new Error('ScenarioTest: event is not of type event')))\n invariant(\n outcome.type === foundEvent.type,\n fail(new Error('ScenarioTest: event type was not equal')),\n )\n invariant(\n outcome.aggregateId === foundEvent.aggregateId,\n fail(new Error('ScenarioTest: event aggregate id was not equal')),\n )\n invariant(\n isEqual(outcome.payload, foundEvent.payload),\n fail(new Error('ScenarioTest: event payload was not equal')),\n )\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/core/utils/createCommand.ts","../src/core/utils/createQuery.ts","../src/core/utils/isCommand.ts","../src/core/utils/isQuery.ts","../src/domain/Specification/Specification.ts","../src/domain/Specification/utils/createQueryNode.ts","../src/domain/Specification/implementations/FieldEquals.specification.ts","../src/utils/fail/fail.ts","../src/utils/invariant/invariant.ts","../src/domain/Specification/implementations/FieldGreaterThan.specification.ts","../src/domain/utils/createDomainEvent.ts","../src/domain/utils/isEvent.ts","../src/domain/utils/isDomainEvent.ts","../src/infrastructure/CommandBus/implementations/SimpleCommandBus.ts","../src/infrastructure/Database/Database.ts","../src/infrastructure/Database/implementations/SimpleDatabase.exceptions.ts","../src/infrastructure/Database/implementations/SimpleDatabase.ts","../src/infrastructure/EventBus/implementations/SimpleEventBus.ts","../src/infrastructure/EventBus/utils/createIntegrationEvent.ts","../src/infrastructure/EventBus/utils/isIntegrationEvent.ts","../src/utils/isEqual/isEqual.ts","../src/utils/parseAsError/parseAsError.ts","../src/utils/streamKey/makeStreamKey.ts","../src/infrastructure/EventStore/utils/createStoredEvent.ts","../src/infrastructure/EventStore/implementations/SimpleEventStore.exceptions.ts","../src/infrastructure/EventStore/implementations/SimpleEventStore.ts","../src/infrastructure/Outbox/implementations/GenericOutboxWorker.ts","../src/infrastructure/Outbox/implementations/InMemoryOutbox.ts","../src/infrastructure/Outbox/utils/createOutboxEntry.ts","../src/infrastructure/QueryBus/implementations/SimpleQueryBus.ts","../src/infrastructure/Repository/implementations/SimpleRepository.ts","../src/infrastructure/ScenarioTest/ScenarioTest.ts"],"names":["randomUUID","Operation","event"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Command, CommandMetadata } from '@core/Command.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createCommand<TType extends string, TPayload>(type: TType, aggregateId: string, payload: TPayload, metadata: Partial<CommandMetadata> = {}): Command<TType, TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n aggregateId: String(aggregateId),\n payload,\n kind: 'command' as const,\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { Query, QueryMetadata } from '@core/Query.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createQuery<TType extends string, TPayload>(type: TType, payload: TPayload, metadata: QueryMetadata = {}): Query<TType, TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n payload,\n kind: 'query',\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { Command } from '@core/Command.ts'\n\nexport function isCommand(candidate: unknown): candidate is Command<string, unknown> {\n if (candidate === null)\n return false\n if (typeof candidate !== 'object')\n return false\n if (!('type' in candidate))\n return false\n return 'kind' in candidate && candidate.kind === 'command'\n}\n","import type { Query } from '@core/Query.ts'\n\nexport function isQuery(candidate: unknown): candidate is Query<unknown> {\n if (candidate === null)\n return false\n if (typeof candidate !== 'object')\n return false\n if (!('type' in candidate))\n return false\n return 'kind' in candidate && candidate.kind === 'query'\n}\n","import type { QueryNode } from './QueryNode.ts'\n\nexport interface Specification<T> {\n isSatisfiedBy(entity: T): boolean\n}\n\nexport abstract class CompositeSpecification<T> implements Specification<T> {\n abstract isSatisfiedBy(entity: T): boolean\n\n abstract toQuery(): QueryNode\n\n and(other: CompositeSpecification<T>): CompositeSpecification<T> {\n return new AndSpecification(this, other)\n }\n\n or(other: CompositeSpecification<T>): CompositeSpecification<T> {\n return new OrSpecification(this, other)\n }\n\n not(): CompositeSpecification<T> {\n return new NotSpecification(this)\n }\n}\n\nexport class AndSpecification<T> extends CompositeSpecification<T> {\n constructor(private left: CompositeSpecification<T>, private right: CompositeSpecification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return this.left.isSatisfiedBy(entity) && this.right.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'and',\n nodes: [this.left.toQuery(), this.right.toQuery()],\n }\n }\n}\n\nexport class OrSpecification<T> extends CompositeSpecification<T> {\n constructor(private left: CompositeSpecification<T>, private right: CompositeSpecification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return this.left.isSatisfiedBy(entity) || this.right.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'or',\n nodes: [this.left.toQuery(), this.right.toQuery()],\n }\n }\n}\n\nexport class NotSpecification<T> extends CompositeSpecification<T> {\n constructor(private spec: CompositeSpecification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return !this.spec.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'not',\n node: this.spec.toQuery(),\n }\n }\n}\n","import type { Primitive } from '@core/types/Primitive.ts'\nimport type { QueryNode } from '../QueryNode.ts'\n\nexport function createQueryNode(type: 'eq' | 'gt' | 'lt', field: string | number | symbol, value: Primitive): QueryNode\nexport function createQueryNode(type: 'and' | 'or', field: undefined, value: QueryNode[]): QueryNode\nexport function createQueryNode(type: 'not', field: undefined, value: QueryNode): QueryNode\nexport function createQueryNode(\n type: QueryNode['type'],\n field: string | number | symbol | undefined,\n value: Primitive | QueryNode | QueryNode[],\n): QueryNode {\n switch (type) {\n case 'eq':\n case 'gt':\n case 'lt':\n return { type, field: field as string, value: value as Primitive }\n case 'and':\n case 'or':\n return { type, nodes: value as QueryNode[] }\n case 'not':\n return { type, node: value as QueryNode }\n }\n}\n","import type { Primitive } from '@core/types/Primitive.ts'\nimport type { QueryNode } from '../QueryNode.ts'\nimport { CompositeSpecification } from '../Specification.ts'\nimport { createQueryNode } from '../utils/createQueryNode.ts'\n\nexport class FieldEquals<T> extends CompositeSpecification<T> {\n constructor(private field: keyof T, private value: Primitive) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return entity[this.field] === this.value\n }\n\n toQuery(): QueryNode {\n return createQueryNode('eq', this.field, this.value)\n }\n}\n","export function fail(anExpression: Error) {\n return () => {\n throw anExpression\n }\n}\n","export function invariant(condition: boolean, onInvalid: () => never): asserts condition {\n if (!condition)\n onInvalid()\n}\n","import type { QueryNode } from '../QueryNode.ts'\nimport { fail } from '@utils/fail/fail.ts'\nimport { invariant } from '@utils/invariant/invariant.ts'\nimport { CompositeSpecification } from '../Specification.ts'\nimport { createQueryNode } from '../utils/createQueryNode.ts'\n\nexport class FieldGreaterThan<T> extends CompositeSpecification<T> {\n constructor(\n private field: keyof T,\n private value: number,\n ) {\n super()\n }\n\n private isNumber(value: unknown): value is number {\n return typeof value === 'number'\n }\n\n isSatisfiedBy(entity: T): boolean {\n const field = entity[this.field]\n invariant(\n this.isNumber(field),\n fail(new TypeError(`Field ${String(this.field)} is not a number`),\n ),\n )\n return field > this.value\n }\n\n toQuery(): QueryNode {\n return createQueryNode('gt', this.field, this.value)\n }\n}\n","import type { DomainEvent, DomainEventMetadata } from '@domain/DomainEvent.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createDomainEvent<TPayload = unknown>(\n type: string,\n aggregateId: string,\n payload: TPayload,\n metadata: Partial<DomainEventMetadata> = {},\n): DomainEvent<TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n aggregateId,\n payload,\n source: 'internal',\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { BaseEvent } from '@domain/BaseEvent.ts'\n\nexport function isEvent(event: unknown): event is BaseEvent {\n if (typeof event !== 'object')\n return false\n if (event === null)\n return false\n if (!('type' in event))\n return false\n return 'source' in event\n}\n","import type { DomainEvent } from '../DomainEvent.ts'\nimport { isEvent } from './isEvent.ts'\n\nexport function isDomainEvent(event: unknown): event is DomainEvent {\n return isEvent(event)\n && 'aggregateId' in event\n && event.source === 'internal'\n}\n","import type { Command } from '@core/Command.ts'\nimport type { CommandHandler } from '@core/CommandHandler.ts'\nimport type { CommandBus } from '../CommandBus.ts'\n\nexport class SimpleCommandBus<TCommand extends Command> implements CommandBus<TCommand> {\n private handlers: Map<TCommand['type'], CommandHandler<TCommand>> = new Map()\n\n register(aTypeOfCommand: TCommand['type'], anHandler: CommandHandler<TCommand>): void {\n if (this.handlers.has(aTypeOfCommand)) {\n throw new Error(`Handler already registered for command type: ${aTypeOfCommand}`)\n }\n this.handlers.set(aTypeOfCommand, anHandler)\n }\n\n async execute(aCommand: TCommand): Promise<void> {\n const handler = this.handlers.get(aCommand.type)\n if (!handler) {\n throw new Error(`No handler found for command type: ${aCommand.type}`)\n }\n return handler.execute(aCommand)\n }\n}\n","import type { CompositeSpecification } from '@domain/Specification/Specification.ts'\nimport type { WithIdentifier } from '../../core/types/WithIdentifier.ts'\n\nexport enum Operation {\n CREATE = 'CREATE',\n PUT = 'PUT',\n PATCH = 'PATCH',\n DELETE = 'DELETE',\n}\n\ninterface Statement<TModel> {\n operation: Operation\n payload: TModel\n}\n\nexport interface CreateStatement<TModel> extends Statement<TModel> {\n operation: Operation.CREATE\n payload: TModel\n}\n\nexport interface PutStatement<TModel> extends Statement<TModel> {\n operation: Operation.PUT\n payload: TModel\n}\n\nexport interface PatchStatement<TModel> extends Statement<Partial<TModel>> {\n operation: Operation.PATCH\n payload: WithIdentifier<Partial<TModel>>\n}\n\nexport interface DeleteStatement extends Statement<WithIdentifier> {\n operation: Operation.DELETE\n payload: WithIdentifier\n}\n\ninterface Executable<TModel, TReturnType = Promise<void>> {\n execute(tableName: string, statement: CreateStatement<TModel>): TReturnType\n execute(tableName: string, statement: PutStatement<TModel>): TReturnType\n execute(tableName: string, statement: PatchStatement<TModel>): TReturnType\n execute(tableName: string, statement: DeleteStatement): TReturnType\n}\n\ninterface QueryAble<TModel, TReturnType = Promise<TModel[]>> {\n query(collectionName: string, specification: CompositeSpecification<TModel>): TReturnType\n}\n\nexport interface Database<TModel, TExecuteReturnType = Promise<void>, TQueryReturnType = Promise<TModel[]>>\n extends\n QueryAble<TModel, TQueryReturnType>,\n Executable<TModel, TExecuteReturnType> { }\n","export class RecordNotFoundException extends Error {\n constructor(id: string) {\n super(`Record not found for id: ${id}`)\n }\n}\n\nexport class DuplicateRecordException extends Error {\n constructor(id: string) {\n super(`Duplicate record found for id: ${id}`)\n }\n}\n\nexport class DatabaseOfflineException extends Error {\n constructor() {\n super(`Database is offline`)\n }\n}\n","import type { CompositeSpecification } from '@domain/Specification/Specification.ts'\nimport type { WithIdentifier } from '../../../core/types/WithIdentifier.ts'\nimport type { CreateStatement, Database, DeleteStatement, PatchStatement, PutStatement } from '../Database.ts'\nimport { Operation } from '../Database.ts'\nimport { DatabaseOfflineException, DuplicateRecordException, RecordNotFoundException } from './SimpleDatabase.exceptions.ts'\n\nexport class SimpleDatabase<TModel extends WithIdentifier> implements Database<TModel, Promise<void>, Promise<TModel[]>> {\n private readonly datasource = new Map<string, TModel[]>()\n private simulateOffline = false\n\n async query(\n tableName: string,\n specification: CompositeSpecification<TModel>,\n ): Promise<TModel[]> {\n if (this.simulateOffline)\n throw new DatabaseOfflineException()\n\n const tableRecords = (this.datasource.get(tableName) || [])\n return tableRecords\n .filter((record: TModel) => specification.isSatisfiedBy(record))\n }\n\n async execute(\n tableName: string,\n statement: CreateStatement<TModel> | PutStatement<TModel> | PatchStatement<TModel> | DeleteStatement,\n ): Promise<void> {\n if (this.simulateOffline)\n throw new DatabaseOfflineException()\n\n if (!this.datasource.has(tableName))\n this.datasource.set(tableName, [])\n const table = this.datasource.get(tableName)!\n\n switch (statement.operation) {\n case Operation.CREATE: {\n const isDuplicate = table.some(item => item.id === statement.payload.id)\n if (isDuplicate)\n throw new DuplicateRecordException(statement.payload.id)\n table.push(statement.payload)\n break\n }\n case Operation.PUT:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table[index] = statement.payload\n break\n }\n case Operation.PATCH:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table[index] = { ...table[index], ...statement.payload }\n break\n }\n case Operation.DELETE:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table.splice(index, 1)\n break\n }\n }\n }\n\n goOffline(): void {\n this.simulateOffline = true\n }\n}\n","import type { EventHandler } from '@core/EventHandler.ts'\nimport type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { EventConsumer, EventProducer } from '../EventBus.ts'\n\nexport class SimpleEventBus<TEvent extends BaseEvent>\nimplements EventConsumer<TEvent>, EventProducer<TEvent> {\n private handlers = new Map<string, EventHandler<TEvent>[]>()\n\n subscribe(\n stream: string,\n aHandler: EventHandler<TEvent>,\n ): void {\n const handlersForType = this.handlers.get(stream) ?? []\n handlersForType.push(aHandler)\n this.handlers.set(stream, handlersForType)\n }\n\n async consume(stream: string, anEvent: TEvent): Promise<void> {\n if (!this.handlers.has(stream))\n return\n const handlers = this.handlers.get(stream) as EventHandler<TEvent>[]\n await Promise.all(handlers.map(async (handler) => {\n return handler.handle(anEvent)\n }))\n }\n\n async publish(stream: string, anEvent: TEvent): Promise<void> {\n await this.consume(stream, anEvent)\n }\n}\n","import type { IntegrationEvent, IntegrationEventMetadata } from '../IntegrationEvent.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createIntegrationEvent<TPayload = unknown>(type: string, payload: TPayload, metadata?: Partial<IntegrationEventMetadata>): IntegrationEvent<TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n payload,\n source: 'external',\n timestamp: new Date().toISOString(),\n metadata: {\n ...metadata,\n },\n })\n}\n","import type { IntegrationEvent } from '../IntegrationEvent.ts'\nimport { isEvent } from '@domain/utils/isEvent.ts'\n\nexport function isIntegrationEvent<TPayload>(event: unknown): event is IntegrationEvent<TPayload> {\n return isEvent(event)\n && event.source === 'external'\n}\n","export function isEqual<T>(a: T, b: T): boolean {\n if (a === b) {\n return true\n }\n\n // eslint-disable-next-line ts/strict-boolean-expressions\n const bothAreObjects = a && b && typeof a === 'object' && typeof b === 'object'\n\n return Boolean(\n bothAreObjects\n && Object.keys(a).length === Object.keys(b).length\n && Object.entries(a).every(([k, v]) => isEqual(v, b[k as keyof T])),\n )\n}\n","export function parseAsError(value: unknown): Error {\n if (value instanceof Error)\n return value\n if (typeof value === 'string')\n return new Error(value)\n try {\n const json = JSON.stringify(value)\n return new Error(json ?? String(value))\n }\n catch {\n return new Error('Unknown error')\n }\n}\n","import type { StreamKey } from '@utils/streamKey/StreamKey.ts'\n\nexport function makeStreamKey(streamName: string, aggregateId: string): StreamKey {\n return `${streamName}#${aggregateId}`\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { StoredEvent } from '../StoredEvent.ts'\nimport { makeStreamKey } from '@utils/index.ts'\n\nexport function createStoredEvent<TEvent extends DomainEvent>(\n streamName: string,\n version: number,\n event: TEvent,\n): StoredEvent<TEvent> {\n return Object.freeze({\n id: event.id,\n streamKey: makeStreamKey(streamName, event.aggregateId),\n version,\n createdAt: new Date().toISOString(),\n event,\n })\n}\n","export class MultipleAggregatesException extends Error {\n constructor() {\n super('EventStore append does not support multiple aggregates to be stored')\n }\n}\n","import type { DomainEvent } from '@domain/index.ts'\nimport type { Database } from '@infrastructure/Database/Database.ts'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\nimport type { Outbox } from '@infrastructure/Outbox/Outbox.ts'\nimport type { StreamKey } from '@utils/index.ts'\nimport type { StoredEvent } from '../StoredEvent.ts'\nimport { FieldEquals } from '@domain/index.ts'\nimport { Operation } from '@infrastructure/Database/Database.ts'\nimport { makeStreamKey } from '@utils/index.ts'\nimport { createStoredEvent } from '../utils/createStoredEvent.ts'\nimport { MultipleAggregatesException } from './SimpleEventStore.exceptions.ts'\n\nexport class SimpleEventStore<TEvent extends DomainEvent> implements EventStore<TEvent, Promise<void>, Promise<TEvent[]>> {\n private readonly tableName: string = 'event_store'\n\n constructor(\n private readonly database: Database<StoredEvent<TEvent>, Promise<void>, Promise<StoredEvent<TEvent>[]>>,\n private readonly outbox?: Outbox,\n ) { }\n\n async load(streamName: string, aggregateId: string): Promise<TEvent[]> {\n const streamKey: StreamKey = makeStreamKey(streamName, aggregateId)\n const specification = new FieldEquals('streamKey', streamKey)\n const storedEvents = await this.database.query(this.tableName, specification)\n return storedEvents.map(storedEvent => storedEvent.event)\n }\n\n async append(streamName: string, events: TEvent[]): Promise<void> {\n const uniqueAggregateIds = new Set(events.map(event => event.aggregateId))\n if (uniqueAggregateIds.size > 1)\n throw new MultipleAggregatesException()\n\n const event = events[0]\n const currentStream = await this.load(streamName, event.aggregateId)\n const eventsToStore = events\n .map(event => createStoredEvent(streamName, currentStream.length + 1, event))\n await Promise.all(\n eventsToStore.map(async payload => this.database.execute(this.tableName, { operation: Operation.CREATE, payload }),\n ),\n )\n await Promise.all(events.map(async event => this.outbox?.enqueue(event)))\n }\n}\n","import type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { EventProducer } from '@infrastructure/EventBus/EventBus.js'\nimport type { OutboxWorker } from '@infrastructure/Outbox/OutboxWorker.ts'\nimport type { Outbox } from '../Outbox.ts'\n\nexport class GenericOutboxWorker implements OutboxWorker {\n constructor(\n protected outbox: Outbox,\n protected eventBus: EventProducer<BaseEvent>,\n protected stream: string,\n ) {}\n\n async runOnce(): Promise<void> {\n const pending = await this.outbox.getPending()\n\n await Promise.all(pending.map(async (entry) => {\n try {\n await this.eventBus.publish(this.stream, entry.event)\n await this.outbox.markAsPublished(entry.id)\n }\n catch {\n await this.outbox.markAsFailed(entry.id)\n }\n }))\n }\n\n async tick(): Promise<void> {\n await this.runOnce()\n }\n\n start(intervalMs: number): void {\n setInterval(() => {\n void this.tick().catch(console.error)\n }, intervalMs)\n }\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Outbox } from '../Outbox.ts'\nimport type { OutboxEntry } from '../OutboxEntry.ts'\n\nexport class InMemoryOutbox implements Outbox {\n protected entries: OutboxEntry[] = []\n protected idCounter = 0\n\n async enqueue(event: DomainEvent<unknown>): Promise<void> {\n this.entries.push({\n id: (this.idCounter++).toString(),\n event,\n published: false,\n retryCount: 0,\n })\n }\n\n async getPending(limit = 100): Promise<OutboxEntry[]> {\n return this.entries.filter(e => !e.published).slice(0, limit)\n }\n\n async markAsPublished(id: string): Promise<void> {\n const entry = this.entries.find(e => e.id === id)\n if (entry) {\n entry.published = true\n }\n }\n\n async markAsFailed(id: string): Promise<void> {\n const entry = this.entries.find(e => e.id === id)\n if (entry) {\n entry.retryCount += 1\n entry.lastAttemptAt = new Date().toISOString()\n }\n }\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { OutboxEntry } from '../OutboxEntry.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createOutboxEntry(\n event: DomainEvent<unknown>,\n): OutboxEntry {\n return Object.freeze({\n id: randomUUID(),\n event,\n published: false,\n retryCount: 0,\n lastAttemptAt: undefined,\n })\n}\n","import type { Query } from '@core/Query.ts'\nimport type { QueryHandler } from '@core/QueryHandler.ts'\nimport type { QueryBus } from '../QueryBus.ts'\n\nexport class SimpleQueryBus<TQuery extends Query, TProjection> implements QueryBus<TQuery, Promise<TProjection>> {\n private handlers: Map<TQuery['type'], QueryHandler<TQuery, Promise<TProjection>>> = new Map()\n\n register(\n aTypeOfQuery: TQuery['type'],\n anHandler: QueryHandler<TQuery, Promise<TProjection>>,\n ): void {\n if (this.handlers.has(aTypeOfQuery)) {\n throw new Error(`Handler already registered for query type: ${aTypeOfQuery}`)\n }\n this.handlers.set(aTypeOfQuery, anHandler)\n }\n\n async execute(aQuery: TQuery): Promise<TProjection> {\n const handler = this.handlers.get(aQuery.type)\n if (!handler) {\n throw new Error(`No handler found for query type: ${aQuery.type}`)\n }\n return handler.execute(aQuery)\n }\n}\n","import type { Decider } from '@domain/Decider.ts'\nimport type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Repository } from '@domain/Repository.ts'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\n\nexport class SimpleRepository<TState, TCommand, TEvent extends DomainEvent> implements Repository<TEvent, Promise<TState>, Promise<void>> {\n constructor(\n private readonly eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>,\n readonly streamName: string,\n private readonly evolveFn: Decider<TState, TCommand, TEvent>['evolve'],\n private readonly initialState: Decider<TState, TCommand, TEvent>['initialState'],\n ) {\n }\n\n async load(aggregateId: string): Promise<TState> {\n const pastEvents = await this.eventStore.load(this.streamName, aggregateId)\n return pastEvents\n .reduce<TState>(this.evolveFn, this.initialState(aggregateId))\n }\n\n async store(events: TEvent[]): Promise<void> {\n await Promise.all(\n events.map(\n async event => this.eventStore.append(\n this.streamName,\n [event],\n ),\n ),\n )\n }\n}\n","import type { Command } from '@core/Command.ts'\nimport type { Query } from '@core/Query.ts'\nimport type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Repository } from '@domain/Repository.ts'\nimport type { EventConsumer, EventProducer } from '@infrastructure/EventBus/EventBus.js'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\nimport type { OutboxWorker } from '@infrastructure/Outbox/OutboxWorker.ts'\nimport type { CommandBus } from '../CommandBus/CommandBus.ts'\nimport type { IntegrationEvent } from '../EventBus/IntegrationEvent.ts'\nimport type { QueryBus } from '../QueryBus/QueryBus.ts'\nimport { isCommand } from '@core/utils/isCommand.ts'\nimport { isQuery } from '@core/utils/isQuery.ts'\nimport { isDomainEvent } from '@domain/utils/isDomainEvent.ts'\nimport { isEvent } from '@domain/utils/isEvent.ts'\nimport { fail } from '@utils/fail/fail.ts'\nimport { invariant } from '@utils/invariant/invariant.ts'\nimport { isEqual } from '@utils/isEqual/isEqual.ts'\nimport { isIntegrationEvent } from '../EventBus/utils/isIntegrationEvent.ts'\n\ntype GivenInput = (DomainEvent | IntegrationEvent)[]\ntype WhenInput = Command | Query | DomainEvent | IntegrationEvent\ntype ThenInput = DomainEvent | Array<Record<string, unknown>>\n\nexport class ScenarioTest<TState, TEvent extends DomainEvent> {\n private givenInput: GivenInput = []\n private whenInput: WhenInput | undefined\n\n constructor(\n private readonly streamName: string,\n private readonly eventBus: EventProducer<BaseEvent> & EventConsumer<BaseEvent>,\n private readonly eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>,\n private readonly commandBus: CommandBus<Command>,\n private readonly queryBus: QueryBus<Query, Promise<Record<string, unknown>[]>>,\n private readonly repository: Repository<DomainEvent, Promise<TState>>,\n private readonly outboxWorker: OutboxWorker,\n ) {}\n\n given(...events: GivenInput): {\n when(action: WhenInput): ReturnType<ScenarioTest<TState, TEvent>['when']>\n then(outcome: ThenInput): Promise<void>\n } {\n this.givenInput = events\n return {\n when: this.when.bind(this),\n then: this.then.bind(this),\n }\n }\n\n when(action: WhenInput): {\n then(outcome: ThenInput): Promise<void>\n } {\n this.whenInput = action\n return {\n then: this.then.bind(this),\n }\n }\n\n async then(thenInput: ThenInput): Promise<void> {\n const domainEvents = this.givenInput\n .filter(isDomainEvent)\n const integrationEvents = this.givenInput\n .filter(isIntegrationEvent)\n\n await Promise.all([\n this.repository.store(domainEvents),\n integrationEvents.map(async event => this.eventBus.consume(this.streamName, event)),\n ])\n\n if (!this.whenInput) {\n throw new Error('In the ScenarioTest, the when-step cannot be empty')\n }\n\n if (isCommand(this.whenInput)) {\n invariant(isDomainEvent(thenInput), fail(new TypeError('When \\\"command\\\" expects a domain event in the then-step')))\n await this.handleCommand(this.whenInput, thenInput)\n }\n\n if (isQuery(this.whenInput)) {\n invariant(Array.isArray(thenInput), fail(new TypeError('When \\\"query\\\" expects an array of expected results in the then-step')))\n await this.handleQuery(this.whenInput, thenInput)\n }\n\n if (isDomainEvent(this.whenInput) || isIntegrationEvent(this.whenInput)) {\n invariant(isDomainEvent(thenInput), fail(new TypeError('When \\\"domain event\\\" or \\\"integration event\\\" expects a domain event in the then-step')))\n await this.handleEvent(this.whenInput, thenInput)\n }\n }\n\n private async handleCommand(command: Command, outcome: DomainEvent): Promise<void> {\n await this.commandBus.execute(command)\n const actualEvents = await this.eventStore.load(this.streamName, outcome.aggregateId)\n const foundEvent = actualEvents.findLast(\n event =>\n isDomainEvent(event)\n && event.aggregateId === outcome.aggregateId\n && event.type === outcome.type,\n )\n invariant(!!foundEvent, fail(new Error('ScenarioTest: event/command was not found')))\n invariant(\n outcome.type === foundEvent.type,\n fail(new Error('ScenarioTest: event/command type was not equal')),\n )\n invariant(\n outcome.aggregateId === foundEvent.aggregateId,\n fail(new Error('ScenarioTest: event/command aggregate id was not equal')),\n )\n invariant(\n isEqual(outcome.payload, foundEvent.payload),\n fail(new Error('ScenarioTest: event/command payload was not equal')),\n )\n }\n\n private async handleQuery(query: Query, expected: Array<Record<string, unknown>>): Promise<void> {\n await this.outboxWorker.tick()\n const actual = await this.queryBus.execute(query)\n invariant(\n isEqual(actual, expected),\n fail(new Error('ScenarioTest: a different query result was returned')),\n )\n }\n\n private async handleEvent(\n event: DomainEvent | IntegrationEvent,\n outcome: DomainEvent,\n ): Promise<void> {\n await this.eventBus.publish(this.streamName, event)\n const actualEvents = await this.eventStore.load(this.streamName, outcome.aggregateId)\n const foundEvent = actualEvents.findLast(\n event =>\n isEvent(event) && event.aggregateId === outcome.aggregateId && event.type === outcome.type,\n )\n invariant(!!foundEvent, fail(new Error('ScenarioTest: event was not found')))\n invariant(isEvent(foundEvent), fail(new Error('ScenarioTest: event is not of type event')))\n invariant(\n outcome.type === foundEvent.type,\n fail(new Error('ScenarioTest: event type was not equal')),\n )\n invariant(\n outcome.aggregateId === foundEvent.aggregateId,\n fail(new Error('ScenarioTest: event aggregate id was not equal')),\n )\n invariant(\n isEqual(outcome.payload, foundEvent.payload),\n fail(new Error('ScenarioTest: event payload was not equal')),\n )\n }\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -140,35 +140,38 @@ type QueryNode = {
140
140
  node: QueryNode;
141
141
  };
142
142
 
143
- declare abstract class Specification<T> {
143
+ interface Specification<T> {
144
+ isSatisfiedBy(entity: T): boolean;
145
+ }
146
+ declare abstract class CompositeSpecification<T> implements Specification<T> {
144
147
  abstract isSatisfiedBy(entity: T): boolean;
145
148
  abstract toQuery(): QueryNode;
146
- and(other: Specification<T>): Specification<T>;
147
- or(other: Specification<T>): Specification<T>;
148
- not(): Specification<T>;
149
+ and(other: CompositeSpecification<T>): CompositeSpecification<T>;
150
+ or(other: CompositeSpecification<T>): CompositeSpecification<T>;
151
+ not(): CompositeSpecification<T>;
149
152
  }
150
- declare class AndSpecification<T> extends Specification<T> {
153
+ declare class AndSpecification<T> extends CompositeSpecification<T> {
151
154
  private left;
152
155
  private right;
153
- constructor(left: Specification<T>, right: Specification<T>);
156
+ constructor(left: CompositeSpecification<T>, right: CompositeSpecification<T>);
154
157
  isSatisfiedBy(entity: T): boolean;
155
158
  toQuery(): QueryNode;
156
159
  }
157
- declare class OrSpecification<T> extends Specification<T> {
160
+ declare class OrSpecification<T> extends CompositeSpecification<T> {
158
161
  private left;
159
162
  private right;
160
- constructor(left: Specification<T>, right: Specification<T>);
163
+ constructor(left: CompositeSpecification<T>, right: CompositeSpecification<T>);
161
164
  isSatisfiedBy(entity: T): boolean;
162
165
  toQuery(): QueryNode;
163
166
  }
164
- declare class NotSpecification<T> extends Specification<T> {
167
+ declare class NotSpecification<T> extends CompositeSpecification<T> {
165
168
  private spec;
166
- constructor(spec: Specification<T>);
169
+ constructor(spec: CompositeSpecification<T>);
167
170
  isSatisfiedBy(entity: T): boolean;
168
171
  toQuery(): QueryNode;
169
172
  }
170
173
 
171
- declare class FieldEquals<T> extends Specification<T> {
174
+ declare class FieldEquals<T> extends CompositeSpecification<T> {
172
175
  private field;
173
176
  private value;
174
177
  constructor(field: keyof T, value: Primitive);
@@ -176,7 +179,7 @@ declare class FieldEquals<T> extends Specification<T> {
176
179
  toQuery(): QueryNode;
177
180
  }
178
181
 
179
- declare class FieldGreaterThan<T> extends Specification<T> {
182
+ declare class FieldGreaterThan<T> extends CompositeSpecification<T> {
180
183
  private field;
181
184
  private value;
182
185
  constructor(field: keyof T, value: number);
@@ -198,10 +201,10 @@ declare function isEvent(event: unknown): event is BaseEvent;
198
201
  interface Registerable$1<TCommand extends Command, TResult = void> {
199
202
  register(aTypeOfCommand: TCommand['type'], anHandler: CommandHandler<TCommand>): TResult;
200
203
  }
201
- interface Executable$2<TCommand extends Command, TResult = Promise<void>> {
204
+ interface Executable$3<TCommand extends Command, TResult = Promise<void>> {
202
205
  execute(aCommand: TCommand): TResult;
203
206
  }
204
- interface CommandBus<TCommand extends Command, TExecutionResult = Promise<void>, TRegisterResult = void> extends Executable$2<TCommand, TExecutionResult>, Registerable$1<TCommand, TRegisterResult> {
207
+ interface CommandBus<TCommand extends Command, TExecutionResult = Promise<void>, TRegisterResult = void> extends Executable$3<TCommand, TExecutionResult>, Registerable$1<TCommand, TRegisterResult> {
205
208
  }
206
209
 
207
210
  declare class SimpleCommandBus<TCommand extends Command> implements CommandBus<TCommand> {
@@ -236,26 +239,32 @@ interface DeleteStatement extends Statement<WithIdentifier> {
236
239
  operation: Operation.DELETE;
237
240
  payload: WithIdentifier;
238
241
  }
239
- interface Executable$1<TModel, TReturnType = Promise<void>> {
242
+ interface Executable$2<TModel, TReturnType = Promise<void>> {
240
243
  execute(tableName: string, statement: CreateStatement<TModel>): TReturnType;
241
244
  execute(tableName: string, statement: PutStatement<TModel>): TReturnType;
242
245
  execute(tableName: string, statement: PatchStatement<TModel>): TReturnType;
243
246
  execute(tableName: string, statement: DeleteStatement): TReturnType;
244
247
  }
245
248
  interface QueryAble<TModel, TReturnType = Promise<TModel[]>> {
246
- query(collectionName: string, specification: Specification<TModel>): TReturnType;
249
+ query(collectionName: string, specification: CompositeSpecification<TModel>): TReturnType;
247
250
  }
248
- interface Database<TModel, TExecuteReturnType = Promise<void>, TQueryReturnType = Promise<TModel[]>> extends QueryAble<TModel, TQueryReturnType>, Executable$1<TModel, TExecuteReturnType> {
251
+ interface Database<TModel, TExecuteReturnType = Promise<void>, TQueryReturnType = Promise<TModel[]>> extends QueryAble<TModel, TQueryReturnType>, Executable$2<TModel, TExecuteReturnType> {
249
252
  }
250
253
 
251
254
  declare class SimpleDatabase<TModel extends WithIdentifier> implements Database<TModel, Promise<void>, Promise<TModel[]>> {
252
255
  private readonly datasource;
253
256
  private simulateOffline;
254
- query(tableName: string, specification: Specification<TModel>): Promise<TModel[]>;
257
+ query(tableName: string, specification: CompositeSpecification<TModel>): Promise<TModel[]>;
255
258
  execute(tableName: string, statement: CreateStatement<TModel> | PutStatement<TModel> | PatchStatement<TModel> | DeleteStatement): Promise<void>;
256
259
  goOffline(): void;
257
260
  }
258
261
 
262
+ interface Executable$1<TInput, TResult> {
263
+ execute(input: TInput): TResult;
264
+ }
265
+ interface Directive<TInput, TResult = void> extends Executable$1<TInput, TResult> {
266
+ }
267
+
259
268
  interface EventProducer<TEvent extends BaseEvent, TReturnType = Promise<void>> {
260
269
  publish(stream: string, anEvent: TEvent): TReturnType;
261
270
  }
@@ -417,4 +426,4 @@ declare class ScenarioTest<TState, TEvent extends DomainEvent> {
417
426
  private handleEvent;
418
427
  }
419
428
 
420
- export { type AggregateRoot, AndSpecification, type BaseEvent, type Command, type CommandBus, type CommandHandler, type CommandMetadata, type CreateStatement, type Database, type Decider, type DeleteStatement, type DomainEvent, type DomainEventMetadata, type EventBasedAggregateRoot, type EventConsumer, type EventHandler, type EventProducer, type EventStore, FieldEquals, FieldGreaterThan, type FilledArray, GenericOutboxWorker, InMemoryOutbox, type IntegrationEvent, type IntegrationEventMetadata, type Maybe, type Module, NotSpecification, type Nullable, Operation, OrSpecification, type Outbox, type OutboxEntry, type OutboxWorker, type PatchStatement, type Primitive, type PutStatement, type Query, type QueryBus, type QueryHandler, type QueryMetadata, type QueryNode, type Repository, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, Specification, type StoredEvent, type StreamKey, type WithIdentifier, createCommand, createDomainEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createStoredEvent, fail, invariant, isCommand, isDomainEvent, isEqual, isEvent, isIntegrationEvent, isQuery, makeStreamKey, parseAsError };
429
+ export { type AggregateRoot, AndSpecification, type BaseEvent, type Command, type CommandBus, type CommandHandler, type CommandMetadata, CompositeSpecification, type CreateStatement, type Database, type Decider, type DeleteStatement, type Directive, type DomainEvent, type DomainEventMetadata, type EventBasedAggregateRoot, type EventConsumer, type EventHandler, type EventProducer, type EventStore, FieldEquals, FieldGreaterThan, type FilledArray, GenericOutboxWorker, InMemoryOutbox, type IntegrationEvent, type IntegrationEventMetadata, type Maybe, type Module, NotSpecification, type Nullable, Operation, OrSpecification, type Outbox, type OutboxEntry, type OutboxWorker, type PatchStatement, type Primitive, type PutStatement, type Query, type QueryBus, type QueryHandler, type QueryMetadata, type QueryNode, type Repository, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, type Specification, type StoredEvent, type StreamKey, type WithIdentifier, createCommand, createDomainEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createStoredEvent, fail, invariant, isCommand, isDomainEvent, isEqual, isEvent, isIntegrationEvent, isQuery, makeStreamKey, parseAsError };
package/dist/index.d.ts CHANGED
@@ -140,35 +140,38 @@ type QueryNode = {
140
140
  node: QueryNode;
141
141
  };
142
142
 
143
- declare abstract class Specification<T> {
143
+ interface Specification<T> {
144
+ isSatisfiedBy(entity: T): boolean;
145
+ }
146
+ declare abstract class CompositeSpecification<T> implements Specification<T> {
144
147
  abstract isSatisfiedBy(entity: T): boolean;
145
148
  abstract toQuery(): QueryNode;
146
- and(other: Specification<T>): Specification<T>;
147
- or(other: Specification<T>): Specification<T>;
148
- not(): Specification<T>;
149
+ and(other: CompositeSpecification<T>): CompositeSpecification<T>;
150
+ or(other: CompositeSpecification<T>): CompositeSpecification<T>;
151
+ not(): CompositeSpecification<T>;
149
152
  }
150
- declare class AndSpecification<T> extends Specification<T> {
153
+ declare class AndSpecification<T> extends CompositeSpecification<T> {
151
154
  private left;
152
155
  private right;
153
- constructor(left: Specification<T>, right: Specification<T>);
156
+ constructor(left: CompositeSpecification<T>, right: CompositeSpecification<T>);
154
157
  isSatisfiedBy(entity: T): boolean;
155
158
  toQuery(): QueryNode;
156
159
  }
157
- declare class OrSpecification<T> extends Specification<T> {
160
+ declare class OrSpecification<T> extends CompositeSpecification<T> {
158
161
  private left;
159
162
  private right;
160
- constructor(left: Specification<T>, right: Specification<T>);
163
+ constructor(left: CompositeSpecification<T>, right: CompositeSpecification<T>);
161
164
  isSatisfiedBy(entity: T): boolean;
162
165
  toQuery(): QueryNode;
163
166
  }
164
- declare class NotSpecification<T> extends Specification<T> {
167
+ declare class NotSpecification<T> extends CompositeSpecification<T> {
165
168
  private spec;
166
- constructor(spec: Specification<T>);
169
+ constructor(spec: CompositeSpecification<T>);
167
170
  isSatisfiedBy(entity: T): boolean;
168
171
  toQuery(): QueryNode;
169
172
  }
170
173
 
171
- declare class FieldEquals<T> extends Specification<T> {
174
+ declare class FieldEquals<T> extends CompositeSpecification<T> {
172
175
  private field;
173
176
  private value;
174
177
  constructor(field: keyof T, value: Primitive);
@@ -176,7 +179,7 @@ declare class FieldEquals<T> extends Specification<T> {
176
179
  toQuery(): QueryNode;
177
180
  }
178
181
 
179
- declare class FieldGreaterThan<T> extends Specification<T> {
182
+ declare class FieldGreaterThan<T> extends CompositeSpecification<T> {
180
183
  private field;
181
184
  private value;
182
185
  constructor(field: keyof T, value: number);
@@ -198,10 +201,10 @@ declare function isEvent(event: unknown): event is BaseEvent;
198
201
  interface Registerable$1<TCommand extends Command, TResult = void> {
199
202
  register(aTypeOfCommand: TCommand['type'], anHandler: CommandHandler<TCommand>): TResult;
200
203
  }
201
- interface Executable$2<TCommand extends Command, TResult = Promise<void>> {
204
+ interface Executable$3<TCommand extends Command, TResult = Promise<void>> {
202
205
  execute(aCommand: TCommand): TResult;
203
206
  }
204
- interface CommandBus<TCommand extends Command, TExecutionResult = Promise<void>, TRegisterResult = void> extends Executable$2<TCommand, TExecutionResult>, Registerable$1<TCommand, TRegisterResult> {
207
+ interface CommandBus<TCommand extends Command, TExecutionResult = Promise<void>, TRegisterResult = void> extends Executable$3<TCommand, TExecutionResult>, Registerable$1<TCommand, TRegisterResult> {
205
208
  }
206
209
 
207
210
  declare class SimpleCommandBus<TCommand extends Command> implements CommandBus<TCommand> {
@@ -236,26 +239,32 @@ interface DeleteStatement extends Statement<WithIdentifier> {
236
239
  operation: Operation.DELETE;
237
240
  payload: WithIdentifier;
238
241
  }
239
- interface Executable$1<TModel, TReturnType = Promise<void>> {
242
+ interface Executable$2<TModel, TReturnType = Promise<void>> {
240
243
  execute(tableName: string, statement: CreateStatement<TModel>): TReturnType;
241
244
  execute(tableName: string, statement: PutStatement<TModel>): TReturnType;
242
245
  execute(tableName: string, statement: PatchStatement<TModel>): TReturnType;
243
246
  execute(tableName: string, statement: DeleteStatement): TReturnType;
244
247
  }
245
248
  interface QueryAble<TModel, TReturnType = Promise<TModel[]>> {
246
- query(collectionName: string, specification: Specification<TModel>): TReturnType;
249
+ query(collectionName: string, specification: CompositeSpecification<TModel>): TReturnType;
247
250
  }
248
- interface Database<TModel, TExecuteReturnType = Promise<void>, TQueryReturnType = Promise<TModel[]>> extends QueryAble<TModel, TQueryReturnType>, Executable$1<TModel, TExecuteReturnType> {
251
+ interface Database<TModel, TExecuteReturnType = Promise<void>, TQueryReturnType = Promise<TModel[]>> extends QueryAble<TModel, TQueryReturnType>, Executable$2<TModel, TExecuteReturnType> {
249
252
  }
250
253
 
251
254
  declare class SimpleDatabase<TModel extends WithIdentifier> implements Database<TModel, Promise<void>, Promise<TModel[]>> {
252
255
  private readonly datasource;
253
256
  private simulateOffline;
254
- query(tableName: string, specification: Specification<TModel>): Promise<TModel[]>;
257
+ query(tableName: string, specification: CompositeSpecification<TModel>): Promise<TModel[]>;
255
258
  execute(tableName: string, statement: CreateStatement<TModel> | PutStatement<TModel> | PatchStatement<TModel> | DeleteStatement): Promise<void>;
256
259
  goOffline(): void;
257
260
  }
258
261
 
262
+ interface Executable$1<TInput, TResult> {
263
+ execute(input: TInput): TResult;
264
+ }
265
+ interface Directive<TInput, TResult = void> extends Executable$1<TInput, TResult> {
266
+ }
267
+
259
268
  interface EventProducer<TEvent extends BaseEvent, TReturnType = Promise<void>> {
260
269
  publish(stream: string, anEvent: TEvent): TReturnType;
261
270
  }
@@ -417,4 +426,4 @@ declare class ScenarioTest<TState, TEvent extends DomainEvent> {
417
426
  private handleEvent;
418
427
  }
419
428
 
420
- export { type AggregateRoot, AndSpecification, type BaseEvent, type Command, type CommandBus, type CommandHandler, type CommandMetadata, type CreateStatement, type Database, type Decider, type DeleteStatement, type DomainEvent, type DomainEventMetadata, type EventBasedAggregateRoot, type EventConsumer, type EventHandler, type EventProducer, type EventStore, FieldEquals, FieldGreaterThan, type FilledArray, GenericOutboxWorker, InMemoryOutbox, type IntegrationEvent, type IntegrationEventMetadata, type Maybe, type Module, NotSpecification, type Nullable, Operation, OrSpecification, type Outbox, type OutboxEntry, type OutboxWorker, type PatchStatement, type Primitive, type PutStatement, type Query, type QueryBus, type QueryHandler, type QueryMetadata, type QueryNode, type Repository, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, Specification, type StoredEvent, type StreamKey, type WithIdentifier, createCommand, createDomainEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createStoredEvent, fail, invariant, isCommand, isDomainEvent, isEqual, isEvent, isIntegrationEvent, isQuery, makeStreamKey, parseAsError };
429
+ export { type AggregateRoot, AndSpecification, type BaseEvent, type Command, type CommandBus, type CommandHandler, type CommandMetadata, CompositeSpecification, type CreateStatement, type Database, type Decider, type DeleteStatement, type Directive, type DomainEvent, type DomainEventMetadata, type EventBasedAggregateRoot, type EventConsumer, type EventHandler, type EventProducer, type EventStore, FieldEquals, FieldGreaterThan, type FilledArray, GenericOutboxWorker, InMemoryOutbox, type IntegrationEvent, type IntegrationEventMetadata, type Maybe, type Module, NotSpecification, type Nullable, Operation, OrSpecification, type Outbox, type OutboxEntry, type OutboxWorker, type PatchStatement, type Primitive, type PutStatement, type Query, type QueryBus, type QueryHandler, type QueryMetadata, type QueryNode, type Repository, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, type Specification, type StoredEvent, type StreamKey, type WithIdentifier, createCommand, createDomainEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createStoredEvent, fail, invariant, isCommand, isDomainEvent, isEqual, isEvent, isIntegrationEvent, isQuery, makeStreamKey, parseAsError };
package/dist/index.js CHANGED
@@ -46,7 +46,7 @@ function isQuery(candidate) {
46
46
  }
47
47
 
48
48
  // src/domain/Specification/Specification.ts
49
- var Specification = class {
49
+ var CompositeSpecification = class {
50
50
  and(other) {
51
51
  return new AndSpecification(this, other);
52
52
  }
@@ -57,7 +57,7 @@ var Specification = class {
57
57
  return new NotSpecification(this);
58
58
  }
59
59
  };
60
- var AndSpecification = class extends Specification {
60
+ var AndSpecification = class extends CompositeSpecification {
61
61
  constructor(left, right) {
62
62
  super();
63
63
  this.left = left;
@@ -73,7 +73,7 @@ var AndSpecification = class extends Specification {
73
73
  };
74
74
  }
75
75
  };
76
- var OrSpecification = class extends Specification {
76
+ var OrSpecification = class extends CompositeSpecification {
77
77
  constructor(left, right) {
78
78
  super();
79
79
  this.left = left;
@@ -89,7 +89,7 @@ var OrSpecification = class extends Specification {
89
89
  };
90
90
  }
91
91
  };
92
- var NotSpecification = class extends Specification {
92
+ var NotSpecification = class extends CompositeSpecification {
93
93
  constructor(spec) {
94
94
  super();
95
95
  this.spec = spec;
@@ -121,7 +121,7 @@ function createQueryNode(type, field, value) {
121
121
  }
122
122
 
123
123
  // src/domain/Specification/implementations/FieldEquals.specification.ts
124
- var FieldEquals = class extends Specification {
124
+ var FieldEquals = class extends CompositeSpecification {
125
125
  constructor(field, value) {
126
126
  super();
127
127
  this.field = field;
@@ -149,7 +149,7 @@ function invariant(condition, onInvalid) {
149
149
  }
150
150
 
151
151
  // src/domain/Specification/implementations/FieldGreaterThan.specification.ts
152
- var FieldGreaterThan = class extends Specification {
152
+ var FieldGreaterThan = class extends CompositeSpecification {
153
153
  constructor(field, value) {
154
154
  super();
155
155
  this.field = field;
@@ -620,6 +620,6 @@ var ScenarioTest = class {
620
620
  }
621
621
  };
622
622
 
623
- export { AndSpecification, FieldEquals, FieldGreaterThan, GenericOutboxWorker, InMemoryOutbox, NotSpecification, Operation, OrSpecification, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, Specification, createCommand, createDomainEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createStoredEvent, fail, invariant, isCommand, isDomainEvent, isEqual, isEvent, isIntegrationEvent, isQuery, makeStreamKey, parseAsError };
623
+ export { AndSpecification, CompositeSpecification, FieldEquals, FieldGreaterThan, GenericOutboxWorker, InMemoryOutbox, NotSpecification, Operation, OrSpecification, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, createCommand, createDomainEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createStoredEvent, fail, invariant, isCommand, isDomainEvent, isEqual, isEvent, isIntegrationEvent, isQuery, makeStreamKey, parseAsError };
624
624
  //# sourceMappingURL=index.js.map
625
625
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/utils/createCommand.ts","../src/core/utils/createQuery.ts","../src/core/utils/isCommand.ts","../src/core/utils/isQuery.ts","../src/domain/Specification/Specification.ts","../src/domain/Specification/utils/createQueryNode.ts","../src/domain/Specification/implementations/FieldEquals.specification.ts","../src/utils/fail/fail.ts","../src/utils/invariant/invariant.ts","../src/domain/Specification/implementations/FieldGreaterThan.specification.ts","../src/domain/utils/createDomainEvent.ts","../src/domain/utils/isEvent.ts","../src/domain/utils/isDomainEvent.ts","../src/infrastructure/CommandBus/implementations/SimpleCommandBus.ts","../src/infrastructure/Database/Database.ts","../src/infrastructure/Database/implementations/SimpleDatabase.exceptions.ts","../src/infrastructure/Database/implementations/SimpleDatabase.ts","../src/infrastructure/EventBus/implementations/SimpleEventBus.ts","../src/infrastructure/EventBus/utils/createIntegrationEvent.ts","../src/infrastructure/EventBus/utils/isIntegrationEvent.ts","../src/utils/isEqual/isEqual.ts","../src/utils/parseAsError/parseAsError.ts","../src/utils/streamKey/makeStreamKey.ts","../src/infrastructure/EventStore/utils/createStoredEvent.ts","../src/infrastructure/EventStore/implementations/SimpleEventStore.exceptions.ts","../src/infrastructure/EventStore/implementations/SimpleEventStore.ts","../src/infrastructure/Outbox/implementations/GenericOutboxWorker.ts","../src/infrastructure/Outbox/implementations/InMemoryOutbox.ts","../src/infrastructure/Outbox/utils/createOutboxEntry.ts","../src/infrastructure/QueryBus/implementations/SimpleQueryBus.ts","../src/infrastructure/Repository/implementations/SimpleRepository.ts","../src/infrastructure/ScenarioTest/ScenarioTest.ts"],"names":["randomUUID","Operation","event"],"mappings":"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","file":"index.js","sourcesContent":["import type { Command, CommandMetadata } from '@core/Command.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createCommand<TType extends string, TPayload>(type: TType, aggregateId: string, payload: TPayload, metadata: Partial<CommandMetadata> = {}): Command<TType, TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n aggregateId: String(aggregateId),\n payload,\n kind: 'command' as const,\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { Query, QueryMetadata } from '@core/Query.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createQuery<TType extends string, TPayload>(type: TType, payload: TPayload, metadata: QueryMetadata = {}): Query<TType, TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n payload,\n kind: 'query',\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { Command } from '@core/Command.ts'\n\nexport function isCommand(candidate: unknown): candidate is Command<string, unknown> {\n if (candidate === null)\n return false\n if (typeof candidate !== 'object')\n return false\n if (!('type' in candidate))\n return false\n return 'kind' in candidate && candidate.kind === 'command'\n}\n","import type { Query } from '@core/Query.ts'\n\nexport function isQuery(candidate: unknown): candidate is Query<unknown> {\n if (candidate === null)\n return false\n if (typeof candidate !== 'object')\n return false\n if (!('type' in candidate))\n return false\n return 'kind' in candidate && candidate.kind === 'query'\n}\n","import type { QueryNode } from './QueryNode.ts'\n\nexport abstract class Specification<T> {\n abstract isSatisfiedBy(entity: T): boolean\n abstract toQuery(): QueryNode\n\n and(other: Specification<T>): Specification<T> {\n return new AndSpecification(this, other)\n }\n\n or(other: Specification<T>): Specification<T> {\n return new OrSpecification(this, other)\n }\n\n not(): Specification<T> {\n return new NotSpecification(this)\n }\n}\n\nexport class AndSpecification<T> extends Specification<T> {\n constructor(private left: Specification<T>, private right: Specification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return this.left.isSatisfiedBy(entity) && this.right.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'and',\n nodes: [this.left.toQuery(), this.right.toQuery()],\n }\n }\n}\n\nexport class OrSpecification<T> extends Specification<T> {\n constructor(private left: Specification<T>, private right: Specification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return this.left.isSatisfiedBy(entity) || this.right.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'or',\n nodes: [this.left.toQuery(), this.right.toQuery()],\n }\n }\n}\n\nexport class NotSpecification<T> extends Specification<T> {\n constructor(private spec: Specification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return !this.spec.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'not',\n node: this.spec.toQuery(),\n }\n }\n}\n","import type { Primitive } from '@core/types/Primitive.ts'\nimport type { QueryNode } from '../QueryNode.ts'\n\nexport function createQueryNode(type: 'eq' | 'gt' | 'lt', field: string | number | symbol, value: Primitive): QueryNode\nexport function createQueryNode(type: 'and' | 'or', field: undefined, value: QueryNode[]): QueryNode\nexport function createQueryNode(type: 'not', field: undefined, value: QueryNode): QueryNode\nexport function createQueryNode(\n type: QueryNode['type'],\n field: string | number | symbol | undefined,\n value: Primitive | QueryNode | QueryNode[],\n): QueryNode {\n switch (type) {\n case 'eq':\n case 'gt':\n case 'lt':\n return { type, field: field as string, value: value as Primitive }\n case 'and':\n case 'or':\n return { type, nodes: value as QueryNode[] }\n case 'not':\n return { type, node: value as QueryNode }\n }\n}\n","import type { Primitive } from '@core/types/Primitive.ts'\nimport type { QueryNode } from '../QueryNode.ts'\nimport { Specification } from '../Specification.ts'\nimport { createQueryNode } from '../utils/createQueryNode.ts'\n\nexport class FieldEquals<T> extends Specification<T> {\n constructor(private field: keyof T, private value: Primitive) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return entity[this.field] === this.value\n }\n\n toQuery(): QueryNode {\n return createQueryNode('eq', this.field, this.value)\n }\n}\n","export function fail(anExpression: Error) {\n return () => {\n throw anExpression\n }\n}\n","export function invariant(condition: boolean, onInvalid: () => never): asserts condition {\n if (!condition)\n onInvalid()\n}\n","import type { QueryNode } from '../QueryNode.ts'\nimport { fail } from '@utils/fail/fail.ts'\nimport { invariant } from '@utils/invariant/invariant.ts'\nimport { Specification } from '../Specification.ts'\nimport { createQueryNode } from '../utils/createQueryNode.ts'\n\nexport class FieldGreaterThan<T> extends Specification<T> {\n constructor(\n private field: keyof T,\n private value: number,\n ) {\n super()\n }\n\n private isNumber(value: unknown): value is number {\n return typeof value === 'number'\n }\n\n isSatisfiedBy(entity: T): boolean {\n const field = entity[this.field]\n invariant(\n this.isNumber(field),\n fail(new TypeError(`Field ${String(this.field)} is not a number`),\n ),\n )\n return field > this.value\n }\n\n toQuery(): QueryNode {\n return createQueryNode('gt', this.field, this.value)\n }\n}\n","import type { DomainEvent, DomainEventMetadata } from '@domain/DomainEvent.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createDomainEvent<TPayload = unknown>(\n type: string,\n aggregateId: string,\n payload: TPayload,\n metadata: Partial<DomainEventMetadata> = {},\n): DomainEvent<TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n aggregateId,\n payload,\n source: 'internal',\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { BaseEvent } from '@domain/BaseEvent.ts'\n\nexport function isEvent(event: unknown): event is BaseEvent {\n if (typeof event !== 'object')\n return false\n if (event === null)\n return false\n if (!('type' in event))\n return false\n return 'source' in event\n}\n","import type { DomainEvent } from '../DomainEvent.ts'\nimport { isEvent } from './isEvent.ts'\n\nexport function isDomainEvent(event: unknown): event is DomainEvent {\n return isEvent(event)\n && 'aggregateId' in event\n && event.source === 'internal'\n}\n","import type { Command } from '@core/Command.ts'\nimport type { CommandHandler } from '@core/CommandHandler.ts'\nimport type { CommandBus } from '../CommandBus.ts'\n\nexport class SimpleCommandBus<TCommand extends Command> implements CommandBus<TCommand> {\n private handlers: Map<TCommand['type'], CommandHandler<TCommand>> = new Map()\n\n register(aTypeOfCommand: TCommand['type'], anHandler: CommandHandler<TCommand>): void {\n if (this.handlers.has(aTypeOfCommand)) {\n throw new Error(`Handler already registered for command type: ${aTypeOfCommand}`)\n }\n this.handlers.set(aTypeOfCommand, anHandler)\n }\n\n async execute(aCommand: TCommand): Promise<void> {\n const handler = this.handlers.get(aCommand.type)\n if (!handler) {\n throw new Error(`No handler found for command type: ${aCommand.type}`)\n }\n return handler.execute(aCommand)\n }\n}\n","import type { Specification } from '@domain/Specification/Specification.ts'\nimport type { WithIdentifier } from '../../core/types/WithIdentifier.ts'\n\nexport enum Operation {\n CREATE = 'CREATE',\n PUT = 'PUT',\n PATCH = 'PATCH',\n DELETE = 'DELETE',\n}\n\ninterface Statement<TModel> {\n operation: Operation\n payload: TModel\n}\n\nexport interface CreateStatement<TModel> extends Statement<TModel> {\n operation: Operation.CREATE\n payload: TModel\n}\n\nexport interface PutStatement<TModel> extends Statement<TModel> {\n operation: Operation.PUT\n payload: TModel\n}\n\nexport interface PatchStatement<TModel> extends Statement<Partial<TModel>> {\n operation: Operation.PATCH\n payload: WithIdentifier<Partial<TModel>>\n}\n\nexport interface DeleteStatement extends Statement<WithIdentifier> {\n operation: Operation.DELETE\n payload: WithIdentifier\n}\n\ninterface Executable<TModel, TReturnType = Promise<void>> {\n execute(tableName: string, statement: CreateStatement<TModel>): TReturnType\n execute(tableName: string, statement: PutStatement<TModel>): TReturnType\n execute(tableName: string, statement: PatchStatement<TModel>): TReturnType\n execute(tableName: string, statement: DeleteStatement): TReturnType\n}\n\ninterface QueryAble<TModel, TReturnType = Promise<TModel[]>> {\n query(collectionName: string, specification: Specification<TModel>): TReturnType\n}\n\nexport interface Database<TModel, TExecuteReturnType = Promise<void>, TQueryReturnType = Promise<TModel[]>>\n extends\n QueryAble<TModel, TQueryReturnType>,\n Executable<TModel, TExecuteReturnType> { }\n","export class RecordNotFoundException extends Error {\n constructor(id: string) {\n super(`Record not found for id: ${id}`)\n }\n}\n\nexport class DuplicateRecordException extends Error {\n constructor(id: string) {\n super(`Duplicate record found for id: ${id}`)\n }\n}\n\nexport class DatabaseOfflineException extends Error {\n constructor() {\n super(`Database is offline`)\n }\n}\n","import type { Specification } from '@domain/Specification/Specification.ts'\nimport type { WithIdentifier } from '../../../core/types/WithIdentifier.ts'\nimport type { CreateStatement, Database, DeleteStatement, PatchStatement, PutStatement } from '../Database.ts'\nimport { Operation } from '../Database.ts'\nimport { DatabaseOfflineException, DuplicateRecordException, RecordNotFoundException } from './SimpleDatabase.exceptions.ts'\n\nexport class SimpleDatabase<TModel extends WithIdentifier> implements Database<TModel, Promise<void>, Promise<TModel[]>> {\n private readonly datasource = new Map<string, TModel[]>()\n private simulateOffline = false\n\n async query(\n tableName: string,\n specification: Specification<TModel>,\n ): Promise<TModel[]> {\n if (this.simulateOffline)\n throw new DatabaseOfflineException()\n\n const tableRecords = (this.datasource.get(tableName) || [])\n return tableRecords\n .filter((record: TModel) => specification.isSatisfiedBy(record))\n }\n\n async execute(\n tableName: string,\n statement: CreateStatement<TModel> | PutStatement<TModel> | PatchStatement<TModel> | DeleteStatement,\n ): Promise<void> {\n if (this.simulateOffline)\n throw new DatabaseOfflineException()\n\n if (!this.datasource.has(tableName))\n this.datasource.set(tableName, [])\n const table = this.datasource.get(tableName)!\n\n switch (statement.operation) {\n case Operation.CREATE: {\n const isDuplicate = table.some(item => item.id === statement.payload.id)\n if (isDuplicate)\n throw new DuplicateRecordException(statement.payload.id)\n table.push(statement.payload)\n break\n }\n case Operation.PUT:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table[index] = statement.payload\n break\n }\n case Operation.PATCH:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table[index] = { ...table[index], ...statement.payload }\n break\n }\n case Operation.DELETE:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table.splice(index, 1)\n break\n }\n }\n }\n\n goOffline(): void {\n this.simulateOffline = true\n }\n}\n","import type { EventHandler } from '@core/EventHandler.ts'\nimport type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { EventConsumer, EventProducer } from '../EventBus.ts'\n\nexport class SimpleEventBus<TEvent extends BaseEvent>\nimplements EventConsumer<TEvent>, EventProducer<TEvent> {\n private handlers = new Map<string, EventHandler<TEvent>[]>()\n\n subscribe(\n stream: string,\n aHandler: EventHandler<TEvent>,\n ): void {\n const handlersForType = this.handlers.get(stream) ?? []\n handlersForType.push(aHandler)\n this.handlers.set(stream, handlersForType)\n }\n\n async consume(stream: string, anEvent: TEvent): Promise<void> {\n if (!this.handlers.has(stream))\n return\n const handlers = this.handlers.get(stream) as EventHandler<TEvent>[]\n await Promise.all(handlers.map(async (handler) => {\n return handler.handle(anEvent)\n }))\n }\n\n async publish(stream: string, anEvent: TEvent): Promise<void> {\n await this.consume(stream, anEvent)\n }\n}\n","import type { IntegrationEvent, IntegrationEventMetadata } from '../IntegrationEvent.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createIntegrationEvent<TPayload = unknown>(type: string, payload: TPayload, metadata?: Partial<IntegrationEventMetadata>): IntegrationEvent<TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n payload,\n source: 'external',\n timestamp: new Date().toISOString(),\n metadata: {\n ...metadata,\n },\n })\n}\n","import type { IntegrationEvent } from '../IntegrationEvent.ts'\nimport { isEvent } from '@domain/utils/isEvent.ts'\n\nexport function isIntegrationEvent<TPayload>(event: unknown): event is IntegrationEvent<TPayload> {\n return isEvent(event)\n && event.source === 'external'\n}\n","export function isEqual<T>(a: T, b: T): boolean {\n if (a === b) {\n return true\n }\n\n // eslint-disable-next-line ts/strict-boolean-expressions\n const bothAreObjects = a && b && typeof a === 'object' && typeof b === 'object'\n\n return Boolean(\n bothAreObjects\n && Object.keys(a).length === Object.keys(b).length\n && Object.entries(a).every(([k, v]) => isEqual(v, b[k as keyof T])),\n )\n}\n","export function parseAsError(value: unknown): Error {\n if (value instanceof Error)\n return value\n if (typeof value === 'string')\n return new Error(value)\n try {\n const json = JSON.stringify(value)\n return new Error(json ?? String(value))\n }\n catch {\n return new Error('Unknown error')\n }\n}\n","import type { StreamKey } from '@utils/streamKey/StreamKey.ts'\n\nexport function makeStreamKey(streamName: string, aggregateId: string): StreamKey {\n return `${streamName}#${aggregateId}`\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { StoredEvent } from '../StoredEvent.ts'\nimport { makeStreamKey } from '@utils/index.ts'\n\nexport function createStoredEvent<TEvent extends DomainEvent>(\n streamName: string,\n version: number,\n event: TEvent,\n): StoredEvent<TEvent> {\n return Object.freeze({\n id: event.id,\n streamKey: makeStreamKey(streamName, event.aggregateId),\n version,\n createdAt: new Date().toISOString(),\n event,\n })\n}\n","export class MultipleAggregatesException extends Error {\n constructor() {\n super('EventStore append does not support multiple aggregates to be stored')\n }\n}\n","import type { DomainEvent } from '@domain/index.ts'\nimport type { Database } from '@infrastructure/Database/Database.ts'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\nimport type { Outbox } from '@infrastructure/Outbox/Outbox.ts'\nimport type { StreamKey } from '@utils/index.ts'\nimport type { StoredEvent } from '../StoredEvent.ts'\nimport { FieldEquals } from '@domain/index.ts'\nimport { Operation } from '@infrastructure/Database/Database.ts'\nimport { makeStreamKey } from '@utils/index.ts'\nimport { createStoredEvent } from '../utils/createStoredEvent.ts'\nimport { MultipleAggregatesException } from './SimpleEventStore.exceptions.ts'\n\nexport class SimpleEventStore<TEvent extends DomainEvent> implements EventStore<TEvent, Promise<void>, Promise<TEvent[]>> {\n private readonly tableName: string = 'event_store'\n\n constructor(\n private readonly database: Database<StoredEvent<TEvent>, Promise<void>, Promise<StoredEvent<TEvent>[]>>,\n private readonly outbox?: Outbox,\n ) { }\n\n async load(streamName: string, aggregateId: string): Promise<TEvent[]> {\n const streamKey: StreamKey = makeStreamKey(streamName, aggregateId)\n const specification = new FieldEquals('streamKey', streamKey)\n const storedEvents = await this.database.query(this.tableName, specification)\n return storedEvents.map(storedEvent => storedEvent.event)\n }\n\n async append(streamName: string, events: TEvent[]): Promise<void> {\n const uniqueAggregateIds = new Set(events.map(event => event.aggregateId))\n if (uniqueAggregateIds.size > 1)\n throw new MultipleAggregatesException()\n\n const event = events[0]\n const currentStream = await this.load(streamName, event.aggregateId)\n const eventsToStore = events\n .map(event => createStoredEvent(streamName, currentStream.length + 1, event))\n await Promise.all(\n eventsToStore.map(async payload => this.database.execute(this.tableName, { operation: Operation.CREATE, payload }),\n ),\n )\n await Promise.all(events.map(async event => this.outbox?.enqueue(event)))\n }\n}\n","import type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { EventProducer } from '@infrastructure/EventBus/EventBus.js'\nimport type { OutboxWorker } from '@infrastructure/Outbox/OutboxWorker.ts'\nimport type { Outbox } from '../Outbox.ts'\n\nexport class GenericOutboxWorker implements OutboxWorker {\n constructor(\n protected outbox: Outbox,\n protected eventBus: EventProducer<BaseEvent>,\n protected stream: string,\n ) {}\n\n async runOnce(): Promise<void> {\n const pending = await this.outbox.getPending()\n\n await Promise.all(pending.map(async (entry) => {\n try {\n await this.eventBus.publish(this.stream, entry.event)\n await this.outbox.markAsPublished(entry.id)\n }\n catch {\n await this.outbox.markAsFailed(entry.id)\n }\n }))\n }\n\n async tick(): Promise<void> {\n await this.runOnce()\n }\n\n start(intervalMs: number): void {\n setInterval(() => {\n void this.tick().catch(console.error)\n }, intervalMs)\n }\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Outbox } from '../Outbox.ts'\nimport type { OutboxEntry } from '../OutboxEntry.ts'\n\nexport class InMemoryOutbox implements Outbox {\n protected entries: OutboxEntry[] = []\n protected idCounter = 0\n\n async enqueue(event: DomainEvent<unknown>): Promise<void> {\n this.entries.push({\n id: (this.idCounter++).toString(),\n event,\n published: false,\n retryCount: 0,\n })\n }\n\n async getPending(limit = 100): Promise<OutboxEntry[]> {\n return this.entries.filter(e => !e.published).slice(0, limit)\n }\n\n async markAsPublished(id: string): Promise<void> {\n const entry = this.entries.find(e => e.id === id)\n if (entry) {\n entry.published = true\n }\n }\n\n async markAsFailed(id: string): Promise<void> {\n const entry = this.entries.find(e => e.id === id)\n if (entry) {\n entry.retryCount += 1\n entry.lastAttemptAt = new Date().toISOString()\n }\n }\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { OutboxEntry } from '../OutboxEntry.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createOutboxEntry(\n event: DomainEvent<unknown>,\n): OutboxEntry {\n return Object.freeze({\n id: randomUUID(),\n event,\n published: false,\n retryCount: 0,\n lastAttemptAt: undefined,\n })\n}\n","import type { Query } from '@core/Query.ts'\nimport type { QueryHandler } from '@core/QueryHandler.ts'\nimport type { QueryBus } from '../QueryBus.ts'\n\nexport class SimpleQueryBus<TQuery extends Query, TProjection> implements QueryBus<TQuery, Promise<TProjection>> {\n private handlers: Map<TQuery['type'], QueryHandler<TQuery, Promise<TProjection>>> = new Map()\n\n register(\n aTypeOfQuery: TQuery['type'],\n anHandler: QueryHandler<TQuery, Promise<TProjection>>,\n ): void {\n if (this.handlers.has(aTypeOfQuery)) {\n throw new Error(`Handler already registered for query type: ${aTypeOfQuery}`)\n }\n this.handlers.set(aTypeOfQuery, anHandler)\n }\n\n async execute(aQuery: TQuery): Promise<TProjection> {\n const handler = this.handlers.get(aQuery.type)\n if (!handler) {\n throw new Error(`No handler found for query type: ${aQuery.type}`)\n }\n return handler.execute(aQuery)\n }\n}\n","import type { Decider } from '@domain/Decider.ts'\nimport type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Repository } from '@domain/Repository.ts'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\n\nexport class SimpleRepository<TState, TCommand, TEvent extends DomainEvent> implements Repository<TEvent, Promise<TState>, Promise<void>> {\n constructor(\n private readonly eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>,\n readonly streamName: string,\n private readonly evolveFn: Decider<TState, TCommand, TEvent>['evolve'],\n private readonly initialState: Decider<TState, TCommand, TEvent>['initialState'],\n ) {\n }\n\n async load(aggregateId: string): Promise<TState> {\n const pastEvents = await this.eventStore.load(this.streamName, aggregateId)\n return pastEvents\n .reduce<TState>(this.evolveFn, this.initialState(aggregateId))\n }\n\n async store(events: TEvent[]): Promise<void> {\n await Promise.all(\n events.map(\n async event => this.eventStore.append(\n this.streamName,\n [event],\n ),\n ),\n )\n }\n}\n","import type { Command } from '@core/Command.ts'\nimport type { Query } from '@core/Query.ts'\nimport type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Repository } from '@domain/Repository.ts'\nimport type { EventConsumer, EventProducer } from '@infrastructure/EventBus/EventBus.js'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\nimport type { OutboxWorker } from '@infrastructure/Outbox/OutboxWorker.ts'\nimport type { CommandBus } from '../CommandBus/CommandBus.ts'\nimport type { IntegrationEvent } from '../EventBus/IntegrationEvent.ts'\nimport type { QueryBus } from '../QueryBus/QueryBus.ts'\nimport { isCommand } from '@core/utils/isCommand.ts'\nimport { isQuery } from '@core/utils/isQuery.ts'\nimport { isDomainEvent } from '@domain/utils/isDomainEvent.ts'\nimport { isEvent } from '@domain/utils/isEvent.ts'\nimport { fail } from '@utils/fail/fail.ts'\nimport { invariant } from '@utils/invariant/invariant.ts'\nimport { isEqual } from '@utils/isEqual/isEqual.ts'\nimport { isIntegrationEvent } from '../EventBus/utils/isIntegrationEvent.ts'\n\ntype GivenInput = (DomainEvent | IntegrationEvent)[]\ntype WhenInput = Command | Query | DomainEvent | IntegrationEvent\ntype ThenInput = DomainEvent | Array<Record<string, unknown>>\n\nexport class ScenarioTest<TState, TEvent extends DomainEvent> {\n private givenInput: GivenInput = []\n private whenInput: WhenInput | undefined\n\n constructor(\n private readonly streamName: string,\n private readonly eventBus: EventProducer<BaseEvent> & EventConsumer<BaseEvent>,\n private readonly eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>,\n private readonly commandBus: CommandBus<Command>,\n private readonly queryBus: QueryBus<Query, Promise<Record<string, unknown>[]>>,\n private readonly repository: Repository<DomainEvent, Promise<TState>>,\n private readonly outboxWorker: OutboxWorker,\n ) {}\n\n given(...events: GivenInput): {\n when(action: WhenInput): ReturnType<ScenarioTest<TState, TEvent>['when']>\n then(outcome: ThenInput): Promise<void>\n } {\n this.givenInput = events\n return {\n when: this.when.bind(this),\n then: this.then.bind(this),\n }\n }\n\n when(action: WhenInput): {\n then(outcome: ThenInput): Promise<void>\n } {\n this.whenInput = action\n return {\n then: this.then.bind(this),\n }\n }\n\n async then(thenInput: ThenInput): Promise<void> {\n const domainEvents = this.givenInput\n .filter(isDomainEvent)\n const integrationEvents = this.givenInput\n .filter(isIntegrationEvent)\n\n await Promise.all([\n this.repository.store(domainEvents),\n integrationEvents.map(async event => this.eventBus.consume(this.streamName, event)),\n ])\n\n if (!this.whenInput) {\n throw new Error('In the ScenarioTest, the when-step cannot be empty')\n }\n\n if (isCommand(this.whenInput)) {\n invariant(isDomainEvent(thenInput), fail(new TypeError('When \\\"command\\\" expects a domain event in the then-step')))\n await this.handleCommand(this.whenInput, thenInput)\n }\n\n if (isQuery(this.whenInput)) {\n invariant(Array.isArray(thenInput), fail(new TypeError('When \\\"query\\\" expects an array of expected results in the then-step')))\n await this.handleQuery(this.whenInput, thenInput)\n }\n\n if (isDomainEvent(this.whenInput) || isIntegrationEvent(this.whenInput)) {\n invariant(isDomainEvent(thenInput), fail(new TypeError('When \\\"domain event\\\" or \\\"integration event\\\" expects a domain event in the then-step')))\n await this.handleEvent(this.whenInput, thenInput)\n }\n }\n\n private async handleCommand(command: Command, outcome: DomainEvent): Promise<void> {\n await this.commandBus.execute(command)\n const actualEvents = await this.eventStore.load(this.streamName, outcome.aggregateId)\n const foundEvent = actualEvents.findLast(\n event =>\n isDomainEvent(event)\n && event.aggregateId === outcome.aggregateId\n && event.type === outcome.type,\n )\n invariant(!!foundEvent, fail(new Error('ScenarioTest: event/command was not found')))\n invariant(\n outcome.type === foundEvent.type,\n fail(new Error('ScenarioTest: event/command type was not equal')),\n )\n invariant(\n outcome.aggregateId === foundEvent.aggregateId,\n fail(new Error('ScenarioTest: event/command aggregate id was not equal')),\n )\n invariant(\n isEqual(outcome.payload, foundEvent.payload),\n fail(new Error('ScenarioTest: event/command payload was not equal')),\n )\n }\n\n private async handleQuery(query: Query, expected: Array<Record<string, unknown>>): Promise<void> {\n await this.outboxWorker.tick()\n const actual = await this.queryBus.execute(query)\n invariant(\n isEqual(actual, expected),\n fail(new Error('ScenarioTest: a different query result was returned')),\n )\n }\n\n private async handleEvent(\n event: DomainEvent | IntegrationEvent,\n outcome: DomainEvent,\n ): Promise<void> {\n await this.eventBus.publish(this.streamName, event)\n const actualEvents = await this.eventStore.load(this.streamName, outcome.aggregateId)\n const foundEvent = actualEvents.findLast(\n event =>\n isEvent(event) && event.aggregateId === outcome.aggregateId && event.type === outcome.type,\n )\n invariant(!!foundEvent, fail(new Error('ScenarioTest: event was not found')))\n invariant(isEvent(foundEvent), fail(new Error('ScenarioTest: event is not of type event')))\n invariant(\n outcome.type === foundEvent.type,\n fail(new Error('ScenarioTest: event type was not equal')),\n )\n invariant(\n outcome.aggregateId === foundEvent.aggregateId,\n fail(new Error('ScenarioTest: event aggregate id was not equal')),\n )\n invariant(\n isEqual(outcome.payload, foundEvent.payload),\n fail(new Error('ScenarioTest: event payload was not equal')),\n )\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/core/utils/createCommand.ts","../src/core/utils/createQuery.ts","../src/core/utils/isCommand.ts","../src/core/utils/isQuery.ts","../src/domain/Specification/Specification.ts","../src/domain/Specification/utils/createQueryNode.ts","../src/domain/Specification/implementations/FieldEquals.specification.ts","../src/utils/fail/fail.ts","../src/utils/invariant/invariant.ts","../src/domain/Specification/implementations/FieldGreaterThan.specification.ts","../src/domain/utils/createDomainEvent.ts","../src/domain/utils/isEvent.ts","../src/domain/utils/isDomainEvent.ts","../src/infrastructure/CommandBus/implementations/SimpleCommandBus.ts","../src/infrastructure/Database/Database.ts","../src/infrastructure/Database/implementations/SimpleDatabase.exceptions.ts","../src/infrastructure/Database/implementations/SimpleDatabase.ts","../src/infrastructure/EventBus/implementations/SimpleEventBus.ts","../src/infrastructure/EventBus/utils/createIntegrationEvent.ts","../src/infrastructure/EventBus/utils/isIntegrationEvent.ts","../src/utils/isEqual/isEqual.ts","../src/utils/parseAsError/parseAsError.ts","../src/utils/streamKey/makeStreamKey.ts","../src/infrastructure/EventStore/utils/createStoredEvent.ts","../src/infrastructure/EventStore/implementations/SimpleEventStore.exceptions.ts","../src/infrastructure/EventStore/implementations/SimpleEventStore.ts","../src/infrastructure/Outbox/implementations/GenericOutboxWorker.ts","../src/infrastructure/Outbox/implementations/InMemoryOutbox.ts","../src/infrastructure/Outbox/utils/createOutboxEntry.ts","../src/infrastructure/QueryBus/implementations/SimpleQueryBus.ts","../src/infrastructure/Repository/implementations/SimpleRepository.ts","../src/infrastructure/ScenarioTest/ScenarioTest.ts"],"names":["randomUUID","Operation","event"],"mappings":"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","file":"index.js","sourcesContent":["import type { Command, CommandMetadata } from '@core/Command.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createCommand<TType extends string, TPayload>(type: TType, aggregateId: string, payload: TPayload, metadata: Partial<CommandMetadata> = {}): Command<TType, TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n aggregateId: String(aggregateId),\n payload,\n kind: 'command' as const,\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { Query, QueryMetadata } from '@core/Query.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createQuery<TType extends string, TPayload>(type: TType, payload: TPayload, metadata: QueryMetadata = {}): Query<TType, TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n payload,\n kind: 'query',\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { Command } from '@core/Command.ts'\n\nexport function isCommand(candidate: unknown): candidate is Command<string, unknown> {\n if (candidate === null)\n return false\n if (typeof candidate !== 'object')\n return false\n if (!('type' in candidate))\n return false\n return 'kind' in candidate && candidate.kind === 'command'\n}\n","import type { Query } from '@core/Query.ts'\n\nexport function isQuery(candidate: unknown): candidate is Query<unknown> {\n if (candidate === null)\n return false\n if (typeof candidate !== 'object')\n return false\n if (!('type' in candidate))\n return false\n return 'kind' in candidate && candidate.kind === 'query'\n}\n","import type { QueryNode } from './QueryNode.ts'\n\nexport interface Specification<T> {\n isSatisfiedBy(entity: T): boolean\n}\n\nexport abstract class CompositeSpecification<T> implements Specification<T> {\n abstract isSatisfiedBy(entity: T): boolean\n\n abstract toQuery(): QueryNode\n\n and(other: CompositeSpecification<T>): CompositeSpecification<T> {\n return new AndSpecification(this, other)\n }\n\n or(other: CompositeSpecification<T>): CompositeSpecification<T> {\n return new OrSpecification(this, other)\n }\n\n not(): CompositeSpecification<T> {\n return new NotSpecification(this)\n }\n}\n\nexport class AndSpecification<T> extends CompositeSpecification<T> {\n constructor(private left: CompositeSpecification<T>, private right: CompositeSpecification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return this.left.isSatisfiedBy(entity) && this.right.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'and',\n nodes: [this.left.toQuery(), this.right.toQuery()],\n }\n }\n}\n\nexport class OrSpecification<T> extends CompositeSpecification<T> {\n constructor(private left: CompositeSpecification<T>, private right: CompositeSpecification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return this.left.isSatisfiedBy(entity) || this.right.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'or',\n nodes: [this.left.toQuery(), this.right.toQuery()],\n }\n }\n}\n\nexport class NotSpecification<T> extends CompositeSpecification<T> {\n constructor(private spec: CompositeSpecification<T>) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return !this.spec.isSatisfiedBy(entity)\n }\n\n toQuery(): QueryNode {\n return {\n type: 'not',\n node: this.spec.toQuery(),\n }\n }\n}\n","import type { Primitive } from '@core/types/Primitive.ts'\nimport type { QueryNode } from '../QueryNode.ts'\n\nexport function createQueryNode(type: 'eq' | 'gt' | 'lt', field: string | number | symbol, value: Primitive): QueryNode\nexport function createQueryNode(type: 'and' | 'or', field: undefined, value: QueryNode[]): QueryNode\nexport function createQueryNode(type: 'not', field: undefined, value: QueryNode): QueryNode\nexport function createQueryNode(\n type: QueryNode['type'],\n field: string | number | symbol | undefined,\n value: Primitive | QueryNode | QueryNode[],\n): QueryNode {\n switch (type) {\n case 'eq':\n case 'gt':\n case 'lt':\n return { type, field: field as string, value: value as Primitive }\n case 'and':\n case 'or':\n return { type, nodes: value as QueryNode[] }\n case 'not':\n return { type, node: value as QueryNode }\n }\n}\n","import type { Primitive } from '@core/types/Primitive.ts'\nimport type { QueryNode } from '../QueryNode.ts'\nimport { CompositeSpecification } from '../Specification.ts'\nimport { createQueryNode } from '../utils/createQueryNode.ts'\n\nexport class FieldEquals<T> extends CompositeSpecification<T> {\n constructor(private field: keyof T, private value: Primitive) {\n super()\n }\n\n isSatisfiedBy(entity: T): boolean {\n return entity[this.field] === this.value\n }\n\n toQuery(): QueryNode {\n return createQueryNode('eq', this.field, this.value)\n }\n}\n","export function fail(anExpression: Error) {\n return () => {\n throw anExpression\n }\n}\n","export function invariant(condition: boolean, onInvalid: () => never): asserts condition {\n if (!condition)\n onInvalid()\n}\n","import type { QueryNode } from '../QueryNode.ts'\nimport { fail } from '@utils/fail/fail.ts'\nimport { invariant } from '@utils/invariant/invariant.ts'\nimport { CompositeSpecification } from '../Specification.ts'\nimport { createQueryNode } from '../utils/createQueryNode.ts'\n\nexport class FieldGreaterThan<T> extends CompositeSpecification<T> {\n constructor(\n private field: keyof T,\n private value: number,\n ) {\n super()\n }\n\n private isNumber(value: unknown): value is number {\n return typeof value === 'number'\n }\n\n isSatisfiedBy(entity: T): boolean {\n const field = entity[this.field]\n invariant(\n this.isNumber(field),\n fail(new TypeError(`Field ${String(this.field)} is not a number`),\n ),\n )\n return field > this.value\n }\n\n toQuery(): QueryNode {\n return createQueryNode('gt', this.field, this.value)\n }\n}\n","import type { DomainEvent, DomainEventMetadata } from '@domain/DomainEvent.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createDomainEvent<TPayload = unknown>(\n type: string,\n aggregateId: string,\n payload: TPayload,\n metadata: Partial<DomainEventMetadata> = {},\n): DomainEvent<TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n aggregateId,\n payload,\n source: 'internal',\n timestamp: new Date().toISOString(),\n metadata,\n })\n}\n","import type { BaseEvent } from '@domain/BaseEvent.ts'\n\nexport function isEvent(event: unknown): event is BaseEvent {\n if (typeof event !== 'object')\n return false\n if (event === null)\n return false\n if (!('type' in event))\n return false\n return 'source' in event\n}\n","import type { DomainEvent } from '../DomainEvent.ts'\nimport { isEvent } from './isEvent.ts'\n\nexport function isDomainEvent(event: unknown): event is DomainEvent {\n return isEvent(event)\n && 'aggregateId' in event\n && event.source === 'internal'\n}\n","import type { Command } from '@core/Command.ts'\nimport type { CommandHandler } from '@core/CommandHandler.ts'\nimport type { CommandBus } from '../CommandBus.ts'\n\nexport class SimpleCommandBus<TCommand extends Command> implements CommandBus<TCommand> {\n private handlers: Map<TCommand['type'], CommandHandler<TCommand>> = new Map()\n\n register(aTypeOfCommand: TCommand['type'], anHandler: CommandHandler<TCommand>): void {\n if (this.handlers.has(aTypeOfCommand)) {\n throw new Error(`Handler already registered for command type: ${aTypeOfCommand}`)\n }\n this.handlers.set(aTypeOfCommand, anHandler)\n }\n\n async execute(aCommand: TCommand): Promise<void> {\n const handler = this.handlers.get(aCommand.type)\n if (!handler) {\n throw new Error(`No handler found for command type: ${aCommand.type}`)\n }\n return handler.execute(aCommand)\n }\n}\n","import type { CompositeSpecification } from '@domain/Specification/Specification.ts'\nimport type { WithIdentifier } from '../../core/types/WithIdentifier.ts'\n\nexport enum Operation {\n CREATE = 'CREATE',\n PUT = 'PUT',\n PATCH = 'PATCH',\n DELETE = 'DELETE',\n}\n\ninterface Statement<TModel> {\n operation: Operation\n payload: TModel\n}\n\nexport interface CreateStatement<TModel> extends Statement<TModel> {\n operation: Operation.CREATE\n payload: TModel\n}\n\nexport interface PutStatement<TModel> extends Statement<TModel> {\n operation: Operation.PUT\n payload: TModel\n}\n\nexport interface PatchStatement<TModel> extends Statement<Partial<TModel>> {\n operation: Operation.PATCH\n payload: WithIdentifier<Partial<TModel>>\n}\n\nexport interface DeleteStatement extends Statement<WithIdentifier> {\n operation: Operation.DELETE\n payload: WithIdentifier\n}\n\ninterface Executable<TModel, TReturnType = Promise<void>> {\n execute(tableName: string, statement: CreateStatement<TModel>): TReturnType\n execute(tableName: string, statement: PutStatement<TModel>): TReturnType\n execute(tableName: string, statement: PatchStatement<TModel>): TReturnType\n execute(tableName: string, statement: DeleteStatement): TReturnType\n}\n\ninterface QueryAble<TModel, TReturnType = Promise<TModel[]>> {\n query(collectionName: string, specification: CompositeSpecification<TModel>): TReturnType\n}\n\nexport interface Database<TModel, TExecuteReturnType = Promise<void>, TQueryReturnType = Promise<TModel[]>>\n extends\n QueryAble<TModel, TQueryReturnType>,\n Executable<TModel, TExecuteReturnType> { }\n","export class RecordNotFoundException extends Error {\n constructor(id: string) {\n super(`Record not found for id: ${id}`)\n }\n}\n\nexport class DuplicateRecordException extends Error {\n constructor(id: string) {\n super(`Duplicate record found for id: ${id}`)\n }\n}\n\nexport class DatabaseOfflineException extends Error {\n constructor() {\n super(`Database is offline`)\n }\n}\n","import type { CompositeSpecification } from '@domain/Specification/Specification.ts'\nimport type { WithIdentifier } from '../../../core/types/WithIdentifier.ts'\nimport type { CreateStatement, Database, DeleteStatement, PatchStatement, PutStatement } from '../Database.ts'\nimport { Operation } from '../Database.ts'\nimport { DatabaseOfflineException, DuplicateRecordException, RecordNotFoundException } from './SimpleDatabase.exceptions.ts'\n\nexport class SimpleDatabase<TModel extends WithIdentifier> implements Database<TModel, Promise<void>, Promise<TModel[]>> {\n private readonly datasource = new Map<string, TModel[]>()\n private simulateOffline = false\n\n async query(\n tableName: string,\n specification: CompositeSpecification<TModel>,\n ): Promise<TModel[]> {\n if (this.simulateOffline)\n throw new DatabaseOfflineException()\n\n const tableRecords = (this.datasource.get(tableName) || [])\n return tableRecords\n .filter((record: TModel) => specification.isSatisfiedBy(record))\n }\n\n async execute(\n tableName: string,\n statement: CreateStatement<TModel> | PutStatement<TModel> | PatchStatement<TModel> | DeleteStatement,\n ): Promise<void> {\n if (this.simulateOffline)\n throw new DatabaseOfflineException()\n\n if (!this.datasource.has(tableName))\n this.datasource.set(tableName, [])\n const table = this.datasource.get(tableName)!\n\n switch (statement.operation) {\n case Operation.CREATE: {\n const isDuplicate = table.some(item => item.id === statement.payload.id)\n if (isDuplicate)\n throw new DuplicateRecordException(statement.payload.id)\n table.push(statement.payload)\n break\n }\n case Operation.PUT:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table[index] = statement.payload\n break\n }\n case Operation.PATCH:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table[index] = { ...table[index], ...statement.payload }\n break\n }\n case Operation.DELETE:{\n const index = table.findIndex(item => item.id === statement.payload.id)\n if (index === -1)\n throw new RecordNotFoundException(statement.payload.id)\n table.splice(index, 1)\n break\n }\n }\n }\n\n goOffline(): void {\n this.simulateOffline = true\n }\n}\n","import type { EventHandler } from '@core/EventHandler.ts'\nimport type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { EventConsumer, EventProducer } from '../EventBus.ts'\n\nexport class SimpleEventBus<TEvent extends BaseEvent>\nimplements EventConsumer<TEvent>, EventProducer<TEvent> {\n private handlers = new Map<string, EventHandler<TEvent>[]>()\n\n subscribe(\n stream: string,\n aHandler: EventHandler<TEvent>,\n ): void {\n const handlersForType = this.handlers.get(stream) ?? []\n handlersForType.push(aHandler)\n this.handlers.set(stream, handlersForType)\n }\n\n async consume(stream: string, anEvent: TEvent): Promise<void> {\n if (!this.handlers.has(stream))\n return\n const handlers = this.handlers.get(stream) as EventHandler<TEvent>[]\n await Promise.all(handlers.map(async (handler) => {\n return handler.handle(anEvent)\n }))\n }\n\n async publish(stream: string, anEvent: TEvent): Promise<void> {\n await this.consume(stream, anEvent)\n }\n}\n","import type { IntegrationEvent, IntegrationEventMetadata } from '../IntegrationEvent.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createIntegrationEvent<TPayload = unknown>(type: string, payload: TPayload, metadata?: Partial<IntegrationEventMetadata>): IntegrationEvent<TPayload> {\n return Object.freeze({\n id: randomUUID(),\n type,\n payload,\n source: 'external',\n timestamp: new Date().toISOString(),\n metadata: {\n ...metadata,\n },\n })\n}\n","import type { IntegrationEvent } from '../IntegrationEvent.ts'\nimport { isEvent } from '@domain/utils/isEvent.ts'\n\nexport function isIntegrationEvent<TPayload>(event: unknown): event is IntegrationEvent<TPayload> {\n return isEvent(event)\n && event.source === 'external'\n}\n","export function isEqual<T>(a: T, b: T): boolean {\n if (a === b) {\n return true\n }\n\n // eslint-disable-next-line ts/strict-boolean-expressions\n const bothAreObjects = a && b && typeof a === 'object' && typeof b === 'object'\n\n return Boolean(\n bothAreObjects\n && Object.keys(a).length === Object.keys(b).length\n && Object.entries(a).every(([k, v]) => isEqual(v, b[k as keyof T])),\n )\n}\n","export function parseAsError(value: unknown): Error {\n if (value instanceof Error)\n return value\n if (typeof value === 'string')\n return new Error(value)\n try {\n const json = JSON.stringify(value)\n return new Error(json ?? String(value))\n }\n catch {\n return new Error('Unknown error')\n }\n}\n","import type { StreamKey } from '@utils/streamKey/StreamKey.ts'\n\nexport function makeStreamKey(streamName: string, aggregateId: string): StreamKey {\n return `${streamName}#${aggregateId}`\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { StoredEvent } from '../StoredEvent.ts'\nimport { makeStreamKey } from '@utils/index.ts'\n\nexport function createStoredEvent<TEvent extends DomainEvent>(\n streamName: string,\n version: number,\n event: TEvent,\n): StoredEvent<TEvent> {\n return Object.freeze({\n id: event.id,\n streamKey: makeStreamKey(streamName, event.aggregateId),\n version,\n createdAt: new Date().toISOString(),\n event,\n })\n}\n","export class MultipleAggregatesException extends Error {\n constructor() {\n super('EventStore append does not support multiple aggregates to be stored')\n }\n}\n","import type { DomainEvent } from '@domain/index.ts'\nimport type { Database } from '@infrastructure/Database/Database.ts'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\nimport type { Outbox } from '@infrastructure/Outbox/Outbox.ts'\nimport type { StreamKey } from '@utils/index.ts'\nimport type { StoredEvent } from '../StoredEvent.ts'\nimport { FieldEquals } from '@domain/index.ts'\nimport { Operation } from '@infrastructure/Database/Database.ts'\nimport { makeStreamKey } from '@utils/index.ts'\nimport { createStoredEvent } from '../utils/createStoredEvent.ts'\nimport { MultipleAggregatesException } from './SimpleEventStore.exceptions.ts'\n\nexport class SimpleEventStore<TEvent extends DomainEvent> implements EventStore<TEvent, Promise<void>, Promise<TEvent[]>> {\n private readonly tableName: string = 'event_store'\n\n constructor(\n private readonly database: Database<StoredEvent<TEvent>, Promise<void>, Promise<StoredEvent<TEvent>[]>>,\n private readonly outbox?: Outbox,\n ) { }\n\n async load(streamName: string, aggregateId: string): Promise<TEvent[]> {\n const streamKey: StreamKey = makeStreamKey(streamName, aggregateId)\n const specification = new FieldEquals('streamKey', streamKey)\n const storedEvents = await this.database.query(this.tableName, specification)\n return storedEvents.map(storedEvent => storedEvent.event)\n }\n\n async append(streamName: string, events: TEvent[]): Promise<void> {\n const uniqueAggregateIds = new Set(events.map(event => event.aggregateId))\n if (uniqueAggregateIds.size > 1)\n throw new MultipleAggregatesException()\n\n const event = events[0]\n const currentStream = await this.load(streamName, event.aggregateId)\n const eventsToStore = events\n .map(event => createStoredEvent(streamName, currentStream.length + 1, event))\n await Promise.all(\n eventsToStore.map(async payload => this.database.execute(this.tableName, { operation: Operation.CREATE, payload }),\n ),\n )\n await Promise.all(events.map(async event => this.outbox?.enqueue(event)))\n }\n}\n","import type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { EventProducer } from '@infrastructure/EventBus/EventBus.js'\nimport type { OutboxWorker } from '@infrastructure/Outbox/OutboxWorker.ts'\nimport type { Outbox } from '../Outbox.ts'\n\nexport class GenericOutboxWorker implements OutboxWorker {\n constructor(\n protected outbox: Outbox,\n protected eventBus: EventProducer<BaseEvent>,\n protected stream: string,\n ) {}\n\n async runOnce(): Promise<void> {\n const pending = await this.outbox.getPending()\n\n await Promise.all(pending.map(async (entry) => {\n try {\n await this.eventBus.publish(this.stream, entry.event)\n await this.outbox.markAsPublished(entry.id)\n }\n catch {\n await this.outbox.markAsFailed(entry.id)\n }\n }))\n }\n\n async tick(): Promise<void> {\n await this.runOnce()\n }\n\n start(intervalMs: number): void {\n setInterval(() => {\n void this.tick().catch(console.error)\n }, intervalMs)\n }\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Outbox } from '../Outbox.ts'\nimport type { OutboxEntry } from '../OutboxEntry.ts'\n\nexport class InMemoryOutbox implements Outbox {\n protected entries: OutboxEntry[] = []\n protected idCounter = 0\n\n async enqueue(event: DomainEvent<unknown>): Promise<void> {\n this.entries.push({\n id: (this.idCounter++).toString(),\n event,\n published: false,\n retryCount: 0,\n })\n }\n\n async getPending(limit = 100): Promise<OutboxEntry[]> {\n return this.entries.filter(e => !e.published).slice(0, limit)\n }\n\n async markAsPublished(id: string): Promise<void> {\n const entry = this.entries.find(e => e.id === id)\n if (entry) {\n entry.published = true\n }\n }\n\n async markAsFailed(id: string): Promise<void> {\n const entry = this.entries.find(e => e.id === id)\n if (entry) {\n entry.retryCount += 1\n entry.lastAttemptAt = new Date().toISOString()\n }\n }\n}\n","import type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { OutboxEntry } from '../OutboxEntry.ts'\nimport { randomUUID } from 'node:crypto'\n\nexport function createOutboxEntry(\n event: DomainEvent<unknown>,\n): OutboxEntry {\n return Object.freeze({\n id: randomUUID(),\n event,\n published: false,\n retryCount: 0,\n lastAttemptAt: undefined,\n })\n}\n","import type { Query } from '@core/Query.ts'\nimport type { QueryHandler } from '@core/QueryHandler.ts'\nimport type { QueryBus } from '../QueryBus.ts'\n\nexport class SimpleQueryBus<TQuery extends Query, TProjection> implements QueryBus<TQuery, Promise<TProjection>> {\n private handlers: Map<TQuery['type'], QueryHandler<TQuery, Promise<TProjection>>> = new Map()\n\n register(\n aTypeOfQuery: TQuery['type'],\n anHandler: QueryHandler<TQuery, Promise<TProjection>>,\n ): void {\n if (this.handlers.has(aTypeOfQuery)) {\n throw new Error(`Handler already registered for query type: ${aTypeOfQuery}`)\n }\n this.handlers.set(aTypeOfQuery, anHandler)\n }\n\n async execute(aQuery: TQuery): Promise<TProjection> {\n const handler = this.handlers.get(aQuery.type)\n if (!handler) {\n throw new Error(`No handler found for query type: ${aQuery.type}`)\n }\n return handler.execute(aQuery)\n }\n}\n","import type { Decider } from '@domain/Decider.ts'\nimport type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Repository } from '@domain/Repository.ts'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\n\nexport class SimpleRepository<TState, TCommand, TEvent extends DomainEvent> implements Repository<TEvent, Promise<TState>, Promise<void>> {\n constructor(\n private readonly eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>,\n readonly streamName: string,\n private readonly evolveFn: Decider<TState, TCommand, TEvent>['evolve'],\n private readonly initialState: Decider<TState, TCommand, TEvent>['initialState'],\n ) {\n }\n\n async load(aggregateId: string): Promise<TState> {\n const pastEvents = await this.eventStore.load(this.streamName, aggregateId)\n return pastEvents\n .reduce<TState>(this.evolveFn, this.initialState(aggregateId))\n }\n\n async store(events: TEvent[]): Promise<void> {\n await Promise.all(\n events.map(\n async event => this.eventStore.append(\n this.streamName,\n [event],\n ),\n ),\n )\n }\n}\n","import type { Command } from '@core/Command.ts'\nimport type { Query } from '@core/Query.ts'\nimport type { BaseEvent } from '@domain/BaseEvent.ts'\nimport type { DomainEvent } from '@domain/DomainEvent.ts'\nimport type { Repository } from '@domain/Repository.ts'\nimport type { EventConsumer, EventProducer } from '@infrastructure/EventBus/EventBus.js'\nimport type { EventStore } from '@infrastructure/EventStore/EventStore.ts'\nimport type { OutboxWorker } from '@infrastructure/Outbox/OutboxWorker.ts'\nimport type { CommandBus } from '../CommandBus/CommandBus.ts'\nimport type { IntegrationEvent } from '../EventBus/IntegrationEvent.ts'\nimport type { QueryBus } from '../QueryBus/QueryBus.ts'\nimport { isCommand } from '@core/utils/isCommand.ts'\nimport { isQuery } from '@core/utils/isQuery.ts'\nimport { isDomainEvent } from '@domain/utils/isDomainEvent.ts'\nimport { isEvent } from '@domain/utils/isEvent.ts'\nimport { fail } from '@utils/fail/fail.ts'\nimport { invariant } from '@utils/invariant/invariant.ts'\nimport { isEqual } from '@utils/isEqual/isEqual.ts'\nimport { isIntegrationEvent } from '../EventBus/utils/isIntegrationEvent.ts'\n\ntype GivenInput = (DomainEvent | IntegrationEvent)[]\ntype WhenInput = Command | Query | DomainEvent | IntegrationEvent\ntype ThenInput = DomainEvent | Array<Record<string, unknown>>\n\nexport class ScenarioTest<TState, TEvent extends DomainEvent> {\n private givenInput: GivenInput = []\n private whenInput: WhenInput | undefined\n\n constructor(\n private readonly streamName: string,\n private readonly eventBus: EventProducer<BaseEvent> & EventConsumer<BaseEvent>,\n private readonly eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>,\n private readonly commandBus: CommandBus<Command>,\n private readonly queryBus: QueryBus<Query, Promise<Record<string, unknown>[]>>,\n private readonly repository: Repository<DomainEvent, Promise<TState>>,\n private readonly outboxWorker: OutboxWorker,\n ) {}\n\n given(...events: GivenInput): {\n when(action: WhenInput): ReturnType<ScenarioTest<TState, TEvent>['when']>\n then(outcome: ThenInput): Promise<void>\n } {\n this.givenInput = events\n return {\n when: this.when.bind(this),\n then: this.then.bind(this),\n }\n }\n\n when(action: WhenInput): {\n then(outcome: ThenInput): Promise<void>\n } {\n this.whenInput = action\n return {\n then: this.then.bind(this),\n }\n }\n\n async then(thenInput: ThenInput): Promise<void> {\n const domainEvents = this.givenInput\n .filter(isDomainEvent)\n const integrationEvents = this.givenInput\n .filter(isIntegrationEvent)\n\n await Promise.all([\n this.repository.store(domainEvents),\n integrationEvents.map(async event => this.eventBus.consume(this.streamName, event)),\n ])\n\n if (!this.whenInput) {\n throw new Error('In the ScenarioTest, the when-step cannot be empty')\n }\n\n if (isCommand(this.whenInput)) {\n invariant(isDomainEvent(thenInput), fail(new TypeError('When \\\"command\\\" expects a domain event in the then-step')))\n await this.handleCommand(this.whenInput, thenInput)\n }\n\n if (isQuery(this.whenInput)) {\n invariant(Array.isArray(thenInput), fail(new TypeError('When \\\"query\\\" expects an array of expected results in the then-step')))\n await this.handleQuery(this.whenInput, thenInput)\n }\n\n if (isDomainEvent(this.whenInput) || isIntegrationEvent(this.whenInput)) {\n invariant(isDomainEvent(thenInput), fail(new TypeError('When \\\"domain event\\\" or \\\"integration event\\\" expects a domain event in the then-step')))\n await this.handleEvent(this.whenInput, thenInput)\n }\n }\n\n private async handleCommand(command: Command, outcome: DomainEvent): Promise<void> {\n await this.commandBus.execute(command)\n const actualEvents = await this.eventStore.load(this.streamName, outcome.aggregateId)\n const foundEvent = actualEvents.findLast(\n event =>\n isDomainEvent(event)\n && event.aggregateId === outcome.aggregateId\n && event.type === outcome.type,\n )\n invariant(!!foundEvent, fail(new Error('ScenarioTest: event/command was not found')))\n invariant(\n outcome.type === foundEvent.type,\n fail(new Error('ScenarioTest: event/command type was not equal')),\n )\n invariant(\n outcome.aggregateId === foundEvent.aggregateId,\n fail(new Error('ScenarioTest: event/command aggregate id was not equal')),\n )\n invariant(\n isEqual(outcome.payload, foundEvent.payload),\n fail(new Error('ScenarioTest: event/command payload was not equal')),\n )\n }\n\n private async handleQuery(query: Query, expected: Array<Record<string, unknown>>): Promise<void> {\n await this.outboxWorker.tick()\n const actual = await this.queryBus.execute(query)\n invariant(\n isEqual(actual, expected),\n fail(new Error('ScenarioTest: a different query result was returned')),\n )\n }\n\n private async handleEvent(\n event: DomainEvent | IntegrationEvent,\n outcome: DomainEvent,\n ): Promise<void> {\n await this.eventBus.publish(this.streamName, event)\n const actualEvents = await this.eventStore.load(this.streamName, outcome.aggregateId)\n const foundEvent = actualEvents.findLast(\n event =>\n isEvent(event) && event.aggregateId === outcome.aggregateId && event.type === outcome.type,\n )\n invariant(!!foundEvent, fail(new Error('ScenarioTest: event was not found')))\n invariant(isEvent(foundEvent), fail(new Error('ScenarioTest: event is not of type event')))\n invariant(\n outcome.type === foundEvent.type,\n fail(new Error('ScenarioTest: event type was not equal')),\n )\n invariant(\n outcome.aggregateId === foundEvent.aggregateId,\n fail(new Error('ScenarioTest: event aggregate id was not equal')),\n )\n invariant(\n isEqual(outcome.payload, foundEvent.payload),\n fail(new Error('ScenarioTest: event payload was not equal')),\n )\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arts-n-crafts/ts",
3
- "version": "3.13.2",
3
+ "version": "3.14.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/arts-n-crafts/typescript.git"