UNPKG

nestjs-event-sourcing-lib

Version:

A comprehensive Event Sourcing and CQRS library for NestJS applications

131 lines 3.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AggregateRoot = exports.InvalidEventError = exports.AggregateNotFoundError = void 0; /** * Error thrown when aggregate is not found */ class AggregateNotFoundError extends Error { constructor(aggregateId, aggregateType) { super(`Aggregate ${aggregateType} with ID ${aggregateId} not found`); this.name = 'AggregateNotFoundError'; } } exports.AggregateNotFoundError = AggregateNotFoundError; /** * Error thrown when trying to apply wrong event to aggregate */ class InvalidEventError extends Error { constructor(eventType, aggregateType) { super(`Event ${eventType} cannot be applied to aggregate ${aggregateType}`); this.name = 'InvalidEventError'; } } exports.InvalidEventError = InvalidEventError; /** * Base class for all aggregates in Event Sourcing system */ class AggregateRoot { constructor(id) { /** * Current aggregate version */ this.version = 0; /** * List of uncommitted events */ this.uncommittedEvents = []; /** * Whether aggregate was loaded from Event Store */ this.isLoaded = false; if (id) { this.id = id; } } getId() { return this.id; } getVersion() { return this.version; } getIsLoaded() { return this.isLoaded; } /** * Applies new event to aggregate */ apply(event) { if (event.aggregateId !== this.id) { throw new InvalidEventError(event.eventType, this.constructor.name); } this.handleEvent(event); this.uncommittedEvents.push(event); this.version++; } /** * Restores aggregate from event history */ loadFromHistory(events) { for (const event of events) { this.handleEvent(event); this.version++; } this.isLoaded = true; } getUncommittedEvents() { return [...this.uncommittedEvents]; } markEventsAsCommitted() { this.uncommittedEvents = []; } hasUncommittedEvents() { return this.uncommittedEvents.length > 0; } getUncommittedEventsCount() { return this.uncommittedEvents.length; } /** * Creates aggregate snapshot for optimization */ createSnapshot() { return { id: this.id, version: this.version, aggregateType: this.constructor.name, timestamp: new Date(), data: this.getSnapshotData(), }; } /** * Restores aggregate from snapshot */ loadFromSnapshot(snapshot) { this.id = snapshot.id; this.version = snapshot.version; this.loadSnapshotData(snapshot.data); this.isLoaded = true; } /** * Gets data for snapshot (should be overridden in aggregate) */ getSnapshotData() { const { id, version, uncommittedEvents, isLoaded, ...data } = this; return data; } /** * Loads data from snapshot (should be overridden in aggregate) */ loadSnapshotData(data) { Object.assign(this, data); } /** * Validates aggregate state */ validateState() { if (!this.id) { throw new Error(`Aggregate ${this.constructor.name} must have an ID`); } } } exports.AggregateRoot = AggregateRoot; //# sourceMappingURL=aggregate-root.js.map