@rineex/ddd 1.5.0 → 1.6.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.d.mts CHANGED
@@ -27,6 +27,190 @@ interface ApplicationServicePort<I, O> {
27
27
  execute: (args: I) => Promise<O>;
28
28
  }
29
29
 
30
+ /**
31
+ * Interface for Identity Value Objects.
32
+ * Enables the Entity to remain agnostic of the underlying ID implementation
33
+ * (e.g., UUID, ULID, or Database Sequence).
34
+ * @template T - The underlying primitive type of the ID (usually string or number).
35
+ */
36
+ interface EntityId<T = string> {
37
+ equals: (other?: EntityId<T> | null | undefined) => boolean;
38
+ toString: () => string;
39
+ }
40
+
41
+ /**
42
+ * Configuration for the base Entity constructor.
43
+ * Forces a single-object argument pattern to avoid positional argument errors.
44
+ * @template ID - A type satisfying the EntityId interface.
45
+ */
46
+ interface EntityProps<ID extends EntityId, Props> {
47
+ /** The unique identity of the entity */
48
+ readonly id: ID;
49
+ /** Optional creation timestamp; defaults to 'now' if not provided */
50
+ readonly createdAt?: Date;
51
+ readonly props: Props;
52
+ }
53
+ /**
54
+ * Abstract Base Entity for Domain-Driven Design (DDD).
55
+ * This class provides the standard contract for entity equality and identity.
56
+ * It intentionally avoids "magic" property bags to ensure V8 engine optimization
57
+ * and better IDE intellisense.
58
+ * @template ID - The specific Identity Value Object type.
59
+ */
60
+ declare abstract class Entity<ID extends EntityId, Props> {
61
+ /** The immutable unique identifier for this entity */
62
+ readonly id: ID;
63
+ /** The timestamp when this entity was first instantiated/created */
64
+ readonly createdAt: Date;
65
+ /**
66
+ * Protected constructor to be called by subclasses.
67
+ * @param props - Initial identity and metadata.
68
+ */
69
+ protected constructor(props: EntityProps<ID, Props>);
70
+ /**
71
+ * Compares entities by identity.
72
+ * In DDD, two entities are considered equal if their IDs match,
73
+ * regardless of their other properties.
74
+ * @param other - The entity to compare against.
75
+ * @returns True if IDs are equal.
76
+ */
77
+ equals(other?: Entity<ID, Props>): boolean;
78
+ /**
79
+ * Validates the current state of the entity against domain invariants.
80
+ * This method should be called after construction and any mutation.
81
+ * @throws {Error} Should throw a specific DomainError if validation fails.
82
+ */
83
+ abstract validate(): void;
84
+ /**
85
+ * Converts the Entity into a plain Javascript object.
86
+ * Subclasses must implement this to explicitly control serialization,
87
+ * @returns A plain object representation of the entity.
88
+ */
89
+ abstract toObject(): Record<string, unknown>;
90
+ }
91
+
92
+ type Primitive$1 = boolean | number | string | null;
93
+ type Serializable = Primitive$1 | Serializable[] | {
94
+ [key: string]: Serializable;
95
+ };
96
+ type DomainEventPayload = Record<string, Serializable>;
97
+ type UnixTimestampMillis = number;
98
+ type DomainEventProps<AggregateId extends EntityId, Payload> = {
99
+ id?: string;
100
+ aggregateId: AggregateId;
101
+ schemaVersion: number;
102
+ occurredAt: UnixTimestampMillis;
103
+ payload: Payload;
104
+ };
105
+ declare abstract class DomainEvent<AggregateId extends EntityId = EntityId, T extends DomainEventPayload = DomainEventPayload> {
106
+ abstract readonly eventName: string;
107
+ readonly id: string;
108
+ readonly aggregateId: AggregateId;
109
+ readonly schemaVersion: number;
110
+ readonly occurredAt: number;
111
+ readonly payload: Readonly<T>;
112
+ protected constructor(props: DomainEventProps<AggregateId, T>);
113
+ toPrimitives(): Readonly<{
114
+ id: string;
115
+ eventName: string;
116
+ aggregateId: string;
117
+ schemaVersion: number;
118
+ occurredAt: UnixTimestampMillis;
119
+ payload: T;
120
+ }>;
121
+ }
122
+
123
+ /**
124
+ * Interface for AggregateRoot to ensure type safety and extensibility.
125
+ */
126
+ interface Props<P> extends EntityProps<EntityId, P> {
127
+ readonly domainEvents: readonly DomainEvent[];
128
+ /**
129
+ * Adds a domain event to the aggregate.
130
+ * @param event The domain event to add.
131
+ */
132
+ addEvent: (event: DomainEvent) => void;
133
+ /**
134
+ * Retrieves and clears all domain events recorded by this aggregate.
135
+ *
136
+ * Domain events represent facts that occurred as a result of state changes
137
+ * within the aggregate. This method transfers ownership of those events
138
+ * to the application layer for further processing (e.g. publishing).
139
+ *
140
+ * Calling this method has the side effect of clearing the aggregate's
141
+ * internal event collection to prevent duplicate handling.
142
+ *
143
+ * This method is intended to be invoked by application services
144
+ * after the aggregate has been successfully persisted.
145
+ *
146
+ * @returns A read-only list of domain events raised by this aggregate.
147
+ */
148
+ pullDomainEvents: () => readonly DomainEvent[];
149
+ }
150
+ /**
151
+ * Base class for aggregate roots in DDD, encapsulating domain events and validation.
152
+ * @template EntityProps The type of the entity's properties.
153
+ */
154
+ declare abstract class AggregateRoot<ID extends EntityId, P> extends Entity<ID, P> {
155
+ /**
156
+ * Gets a read-only copy of the domain events.
157
+ */
158
+ get domainEvents(): readonly DomainEvent[];
159
+ /**
160
+ * Internal list of domain events.
161
+ */
162
+ private readonly _domainEvents;
163
+ /**
164
+ * Adds a domain event to the aggregate after validating invariants.
165
+ * @param domainEvent The domain event to add.
166
+ * @throws {EntityValidationError} If invariants are not met.
167
+ */
168
+ addEvent(domainEvent: DomainEvent): void;
169
+ pullDomainEvents(): readonly DomainEvent[];
170
+ }
171
+
172
+ interface DomainErrorMetadata {
173
+ cause?: {
174
+ name: string;
175
+ message: string;
176
+ stack?: string;
177
+ };
178
+ [key: string]: unknown;
179
+ }
180
+ /**
181
+ * Base class for all Domain Errors in the application.
182
+ *
183
+ * This class ensures:
184
+ * 1. Serializable and structured for logs or API responses.
185
+ * 2. Identifiable via stable error codes (not just class names).
186
+ * 3. Contextual with optional structured metadata.
187
+ * 4. Supports error chaining (cause) and stack trace preservation.
188
+ *
189
+ * @example
190
+ * export class InsufficientFundsError extends DomainError {
191
+ * constructor(accountId: string, currentBalance: number) {
192
+ * super(
193
+ * `Account ${accountId} has insufficient funds.`,
194
+ * 'INSUFFICIENT_FUNDS',
195
+ * { accountId, currentBalance }
196
+ * );
197
+ * }
198
+ * }
199
+ */
200
+ declare abstract class DomainError extends Error {
201
+ /** Stable, machine-readable error code */
202
+ readonly code: string;
203
+ /** Structured, immutable domain metadata */
204
+ readonly metadata: Readonly<DomainErrorMetadata>;
205
+ /**
206
+ * @param message - Human-readable error message
207
+ * @param code - Stable error code
208
+ * @param metadata - Domain-specific structured data; optional `cause` can be included
209
+ */
210
+ protected constructor(message: string, code: string, metadata?: DomainErrorMetadata);
211
+ }
212
+
213
+ type Primitive = boolean | number | string;
30
214
  /**
31
215
  * Base class for primitive-based Value Objects.
32
216
  *
@@ -45,7 +229,7 @@ interface ApplicationServicePort<I, O> {
45
229
  * - Username
46
230
  * - Slug
47
231
  */
48
- declare abstract class PrimitiveValueObject<T extends boolean | number | string> {
232
+ declare abstract class PrimitiveValueObject<T extends Primitive> implements EntityId {
49
233
  /**
50
234
  * The underlying primitive value.
51
235
  * Guaranteed to be valid after construction.
@@ -72,7 +256,7 @@ declare abstract class PrimitiveValueObject<T extends boolean | number | string>
72
256
  *
73
257
  * @param other - Another Value Object
74
258
  */
75
- equals(other?: PrimitiveValueObject<T>): boolean;
259
+ equals(other?: PrimitiveValueObject<T> | null | undefined): boolean;
76
260
  /**
77
261
  * JSON serialization hook.
78
262
  * Produces the raw primitive value.
@@ -92,6 +276,48 @@ declare abstract class PrimitiveValueObject<T extends boolean | number | string>
92
276
  protected abstract validate(value: T): void;
93
277
  }
94
278
 
279
+ declare abstract class ValueObject<T> {
280
+ get value(): T;
281
+ protected readonly props: Readonly<T>;
282
+ protected constructor(props: T);
283
+ /**
284
+ * Standard for clean API integration and logging.
285
+ */
286
+ toJSON(): T;
287
+ /**
288
+ * Useful for debugging and string-based indexing.
289
+ */
290
+ toString(): string;
291
+ /**
292
+ * Type guard to check if an unknown object is an instance of ValueObject.
293
+ * This is useful for runtime type checking.
294
+ *
295
+ * @param vo The object to check.
296
+ * @returns True if the object is a ValueObject instance, false otherwise.
297
+ */
298
+ static is(vo: unknown): vo is ValueObject<unknown>;
299
+ /**
300
+ * Deep equality comparison of ValueObjects
301
+ */
302
+ equals(other?: ValueObject<T>): boolean;
303
+ /**
304
+ * Validates the value object props
305
+ * @throws InvalidValueObjectError if validation fails
306
+ */
307
+ protected abstract validate(props: T): void;
308
+ }
309
+
310
+ /**
311
+ * Custom error class for entity validation failures.
312
+ */
313
+ declare class EntityValidationError extends DomainError {
314
+ constructor(message: string, cause?: Error);
315
+ }
316
+
317
+ declare class InvalidValueObjectError extends DomainError {
318
+ constructor(message: string);
319
+ }
320
+
95
321
  /**
96
322
  * Represents a UUID (Universally Unique Identifier) value object.
97
323
  *
@@ -136,15 +362,6 @@ declare class UUID extends PrimitiveValueObject<string> {
136
362
  declare class AggregateId extends UUID {
137
363
  }
138
364
 
139
- /**
140
- * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.
141
- *
142
- * @param obj - The object to be deeply frozen.
143
- * @param seen - A WeakSet to track already processed objects (for circular references).
144
- * @returns A deeply frozen version of the input object.
145
- */
146
- declare function deepFreeze<T>(obj: T, seen?: WeakSet<object>): Readonly<T>;
147
-
148
365
  /**
149
366
  * HTTP status code catalog.
150
367
  *
@@ -304,6 +521,150 @@ declare const HttpStatusMessage: {
304
521
  };
305
522
  type HttpStatusMessage = (typeof HttpStatusMessage)[keyof typeof HttpStatusMessage];
306
523
 
524
+ /**
525
+ * Base class for Domain violations.
526
+ * Purposely does NOT extend native Error to avoid stack trace overhead in the domain.
527
+ */
528
+ declare abstract class DomainViolation {
529
+ abstract readonly code: string;
530
+ abstract readonly message: string;
531
+ readonly metadata: Readonly<Record<string, unknown>>;
532
+ protected constructor(metadata?: Record<string, unknown>);
533
+ }
534
+
535
+ /**
536
+ * Represents the outcome of an operation that can either succeed or fail,
537
+ * without relying on exceptions for control flow.
538
+ *
539
+ * This pattern is commonly used in domain and application layers to make
540
+ * success and failure states explicit, predictable, and type-safe.
541
+ *
542
+ * ## Design guarantees
543
+ * - A `Result` is **immutable** once created.
544
+ * - A `Result` is **exactly one of**:
545
+ * - Success → contains a value
546
+ * - Failure → contains an error
547
+ * - Accessing the wrong side throws immediately (fail-fast).
548
+ *
549
+ * @typeParam T - Type of the success value
550
+ * @typeParam E - Type of the failure error
551
+ *
552
+ * @example
553
+ * ```ts
554
+ * function parseNumber(input: string): Result<number, string> {
555
+ * const value = Number(input);
556
+ *
557
+ * if (Number.isNaN(value)) {
558
+ * return Result.fail('Invalid number');
559
+ * }
560
+ *
561
+ * return Result.ok(value);
562
+ * }
563
+ *
564
+ * const result = parseNumber('42');
565
+ *
566
+ * if (result.isSuccess) {
567
+ * console.log(result.getValue()); // 42
568
+ * } else {
569
+ * console.error(result.getError());
570
+ * }
571
+ * ```
572
+ */
573
+ declare class Result<T, E> {
574
+ private readonly _value?;
575
+ private readonly _error?;
576
+ /**
577
+ * Indicates whether the result represents a successful outcome.
578
+ *
579
+ * This flag is mutually exclusive with {@link isFailure}.
580
+ */
581
+ readonly isSuccess: boolean;
582
+ /**
583
+ * Indicates whether the result represents a failed outcome.
584
+ *
585
+ * This flag is mutually exclusive with {@link isSuccess}.
586
+ */
587
+ readonly isFailure: boolean;
588
+ /**
589
+ * Creates a new {@link Result} instance.
590
+ *
591
+ * This constructor is private to enforce the use of
592
+ * {@link Result.ok} and {@link Result.fail} factory methods,
593
+ * preserving the success/failure invariants.
594
+ *
595
+ * @param _value - Success value (defined only for success results)
596
+ * @param _error - Failure error (defined only for failure results)
597
+ */
598
+ private constructor();
599
+ /**
600
+ * Creates a successful {@link Result}.
601
+ *
602
+ * @param value - Value representing a successful outcome
603
+ * @returns A success {@link Result} containing the provided value
604
+ *
605
+ * @example
606
+ * ```ts
607
+ * return Result.ok(user);
608
+ * ```
609
+ */
610
+ static ok<T, E>(value: T): Result<T, E>;
611
+ /**
612
+ * Creates a failed {@link Result}.
613
+ *
614
+ * @param error - Error describing the failure
615
+ * @returns A failure {@link Result} containing the provided error
616
+ *
617
+ * @example
618
+ * ```ts
619
+ * return Result.fail(new ValidationError('Email is invalid'));
620
+ * ```
621
+ */
622
+ static fail<T, E>(error: E): Result<T, E>;
623
+ /**
624
+ * Returns the success value.
625
+ *
626
+ * @returns The value associated with a successful result
627
+ *
628
+ * @throws {Error}
629
+ * Thrown if this result represents a failure.
630
+ * This is a fail-fast guard against incorrect usage.
631
+ *
632
+ * @example
633
+ * ```ts
634
+ * if (result.isSuccess) {
635
+ * const value = result.getValue();
636
+ * }
637
+ * ```
638
+ */
639
+ getValue(): T;
640
+ /**
641
+ * Returns the failure error.
642
+ *
643
+ * @returns The error associated with a failed result
644
+ *
645
+ * @throws {Error}
646
+ * Thrown if this result represents a success.
647
+ * This is a fail-fast guard against incorrect usage.
648
+ *
649
+ * @example
650
+ * ```ts
651
+ * if (result.isFailure) {
652
+ * const error = result.getError();
653
+ * }
654
+ * ```
655
+ */
656
+ getError(): E;
657
+ }
658
+
659
+ /**
660
+ * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.
661
+ *
662
+ * @param obj - The object to be deeply frozen.
663
+ * @param seen - A WeakSet to track already processed objects (for circular references).
664
+ * @returns A deeply frozen version of the input object.
665
+ */
666
+ declare function deepFreeze<T>(obj: T, seen?: WeakSet<object>): Readonly<T>;
667
+
307
668
  interface ErrorParams {
308
669
  message: string;
309
670
  code: HttpStatusMessage;
@@ -350,287 +711,10 @@ declare abstract class ApplicationError extends Error {
350
711
  constructor({ code, isOperational, status, metadata, message, cause, }: ErrorParams);
351
712
  }
352
713
 
353
- declare abstract class ValueObject<T> {
354
- get value(): T;
355
- protected readonly props: Readonly<T>;
356
- protected constructor(props: T);
357
- /**
358
- * Standard for clean API integration and logging.
359
- */
360
- toJSON(): T;
361
- /**
362
- * Useful for debugging and string-based indexing.
363
- */
364
- toString(): string;
365
- /**
366
- * Type guard to check if an unknown object is an instance of ValueObject.
367
- * This is useful for runtime type checking.
368
- *
369
- * @param vo The object to check.
370
- * @returns True if the object is a ValueObject instance, false otherwise.
371
- */
372
- static is(vo: unknown): vo is ValueObject<unknown>;
373
- /**
374
- * Deep equality comparison of ValueObjects
375
- */
376
- equals(other?: ValueObject<T>): boolean;
377
- /**
378
- * Validates the value object props
379
- * @throws InvalidValueObjectError if validation fails
380
- */
381
- protected abstract validate(props: T): void;
382
- }
383
-
384
714
  type UnwrapValueObject<T> = T extends ValueObject<infer V> ? UnwrapValueObject<V> : T extends (infer U)[] ? UnwrapValueObject<U>[] : T extends Map<infer K, infer V> ? Map<K, UnwrapValueObject<V>> : T extends Set<infer V> ? Set<UnwrapValueObject<V>> : T extends Date ? string : T extends object ? {
385
715
  [K in keyof T]: UnwrapValueObject<T[K]>;
386
716
  } : T;
387
717
  declare function unwrapValueObject<T>(input: T, seen?: WeakSet<object>): UnwrapValueObject<T>;
388
718
  declare function ensureObject<T>(input: UnwrapValueObject<T>): object;
389
719
 
390
- interface EntityBaseInterface {
391
- id: AggregateId;
392
- equals: (entity: unknown) => boolean;
393
- }
394
- /**
395
- * Base properties common to all entities, including ID and timestamps.
396
- */
397
- interface BaseEntityProps {
398
- /** Unique identifier for the entity */
399
- id?: AggregateId;
400
- /** Date when the entity was created */
401
- createdAt: Date;
402
- }
403
- /**
404
- * Interface for constructing an entity with optional timestamps.
405
- * @template Props - The specific props type for the entity
406
- */
407
- type CreateEntityProps<T> = BaseEntityProps & {
408
- props: T;
409
- };
410
- /**
411
- * Abstract base class for domain entities in a Domain-Driven Design (DDD) context.
412
- * Provides common functionality for entity identification, equality comparison,
413
- * immutability, and validation. Entities extending this class must implement
414
- * the `validate` method to enforce domain invariants.
415
- * @template EntityProps - The specific props type for the entity
416
- */
417
- declare abstract class Entity<EntityProps> {
418
- #private;
419
- /**
420
- * Returns the creation timestamp.
421
- * A new Date instance is returned to preserve immutability.
422
- *
423
- * @returns {Date} The creation date of the entity.
424
- */
425
- get createdAt(): Date;
426
- /**
427
- * Gets the entity's unique identifier.
428
- * @returns The entity's ID
429
- */
430
- get id(): AggregateId;
431
- get metadata(): Readonly<{
432
- createdAt: string;
433
- id: AggregateId;
434
- }>;
435
- /**
436
- * Returns an immutable shallow copy of the entity's properties.
437
- *
438
- * @returns {Readonly<EntityProps>} The entity domain properties.
439
- */
440
- get props(): Readonly<EntityProps>;
441
- /**
442
- * Constructs an entity with the provided properties and timestamps.
443
- * Ensures immutability by cloning props and validates the entity.
444
- * @param params - Entity creation parameters
445
- * @throws EntityValidationError if the ID is empty or validation fails
446
- */
447
- protected constructor(args: CreateEntityProps<EntityProps>);
448
- /**
449
- * Checks if the provided value is an instance of Entity.
450
- * @param entity - The value to check
451
- * @returns True if the value is an Entity instance
452
- */
453
- static isEntity(entity: unknown): entity is EntityBaseInterface;
454
- /**
455
- * Compares this entity with another to determine if they are the same.
456
- * Equality is based on the entity ID.
457
- * @param other - The entity to compare with
458
- * @returns True if the entities have the same ID
459
- */
460
- equals(other?: Entity<unknown>): boolean;
461
- /**
462
- * Returns a frozen copy of the entity's properties, including base properties.
463
- * Ensures immutability by returning a new object.
464
- * @returns A frozen copy of the entity's properties
465
- */
466
- getPropsCopy(): Readonly<EntityProps>;
467
- /**
468
- * Determines if the entity is transient, i.e., it has not been persisted yet.
469
- * By convention, an entity is considered transient if it lacks a valid identifier.
470
- * This can be useful when performing logic that depends on persistence state,
471
- * such as conditional inserts or validations that only apply to new entities.
472
- *
473
- * @returns True if the entity is transient (not persisted), otherwise false.
474
- */
475
- toJSON(): Record<string, unknown>;
476
- /**
477
- * Internal mutation hook.
478
- * Must be followed by validation by caller.
479
- */
480
- protected updateProps(updater: (current: EntityProps) => EntityProps): void;
481
- toObject(): Readonly<UnwrapValueObject<EntityProps> & {
482
- createdAt: string;
483
- id: string;
484
- }>;
485
- /**
486
- * Validates the entity's state to enforce domain invariants.
487
- * Must be implemented by subclasses to define specific validation rules.
488
- * @implements Must be called by concrete factories and mutators.
489
- * @throws EntityValidationError if validation fails
490
- */
491
- abstract validate(): void;
492
- }
493
-
494
- type Primitive = boolean | number | string | null;
495
- type Serializable = Primitive | Serializable[] | {
496
- [key: string]: Serializable;
497
- };
498
- type DomainEventPayload = Record<string, Serializable>;
499
- type DomainEventProps<T> = {
500
- id: string;
501
- aggregateId: string;
502
- schemaVersion: number;
503
- occurredAt: number;
504
- payload: T;
505
- };
506
- declare abstract class DomainEvent<T extends DomainEventPayload = DomainEventPayload> {
507
- abstract readonly eventName: string;
508
- readonly id: string;
509
- readonly aggregateId: string;
510
- readonly schemaVersion: number;
511
- readonly occurredAt: number;
512
- readonly payload: Readonly<T>;
513
- protected constructor(props: DomainEventProps<T>);
514
- toPrimitives(): {
515
- schemaVersion: number;
516
- aggregateId: string;
517
- occurredAt: number;
518
- eventName: string;
519
- payload: Readonly<T>;
520
- id: string;
521
- };
522
- }
523
-
524
- /**
525
- * Interface for AggregateRoot to ensure type safety and extensibility.
526
- */
527
- interface AggregateRootInterface {
528
- readonly id: AggregateId;
529
- readonly domainEvents: readonly DomainEvent[];
530
- /**
531
- * Validates the aggregate's invariants.
532
- * @throws {EntityValidationError} If validation fails.
533
- */
534
- validate: () => void;
535
- /**
536
- * Adds a domain event to the aggregate.
537
- * @param event The domain event to add.
538
- */
539
- addEvent: (event: DomainEvent) => void;
540
- /**
541
- * Retrieves and clears all domain events recorded by this aggregate.
542
- *
543
- * Domain events represent facts that occurred as a result of state changes
544
- * within the aggregate. This method transfers ownership of those events
545
- * to the application layer for further processing (e.g. publishing).
546
- *
547
- * Calling this method has the side effect of clearing the aggregate's
548
- * internal event collection to prevent duplicate handling.
549
- *
550
- * This method is intended to be invoked by application services
551
- * after the aggregate has been successfully persisted.
552
- *
553
- * @returns A read-only list of domain events raised by this aggregate.
554
- */
555
- pullDomainEvents: () => readonly DomainEvent[];
556
- }
557
- /**
558
- * Base class for aggregate roots in DDD, encapsulating domain events and validation.
559
- * @template EntityProps The type of the entity's properties.
560
- */
561
- declare abstract class AggregateRoot<EntityProps> extends Entity<EntityProps> implements AggregateRootInterface {
562
- /**
563
- * Gets a read-only copy of the domain events.
564
- */
565
- get domainEvents(): readonly DomainEvent[];
566
- /**
567
- * Internal list of domain events.
568
- */
569
- private readonly _domainEvents;
570
- /**
571
- * Adds a domain event to the aggregate after validating invariants.
572
- * @param domainEvent The domain event to add.
573
- * @throws {EntityValidationError} If invariants are not met.
574
- */
575
- addEvent(domainEvent: DomainEvent): void;
576
- pullDomainEvents(): readonly DomainEvent[];
577
- /**
578
- * Validates the entity's invariants.
579
- * @throws {EntityValidationError} If validation fails.
580
- */
581
- abstract validate(): void;
582
- }
583
-
584
- interface DomainErrorMetadata {
585
- cause?: {
586
- name: string;
587
- message: string;
588
- stack?: string;
589
- };
590
- [key: string]: unknown;
591
- }
592
- /**
593
- * Base class for all Domain Errors in the application.
594
- *
595
- * This class ensures:
596
- * 1. Serializable and structured for logs or API responses.
597
- * 2. Identifiable via stable error codes (not just class names).
598
- * 3. Contextual with optional structured metadata.
599
- * 4. Supports error chaining (cause) and stack trace preservation.
600
- *
601
- * @example
602
- * export class InsufficientFundsError extends DomainError {
603
- * constructor(accountId: string, currentBalance: number) {
604
- * super(
605
- * `Account ${accountId} has insufficient funds.`,
606
- * 'INSUFFICIENT_FUNDS',
607
- * { accountId, currentBalance }
608
- * );
609
- * }
610
- * }
611
- */
612
- declare abstract class DomainError extends Error {
613
- /** Stable, machine-readable error code */
614
- readonly code: string;
615
- /** Structured, immutable domain metadata */
616
- readonly metadata: Readonly<DomainErrorMetadata>;
617
- /**
618
- * @param message - Human-readable error message
619
- * @param code - Stable error code
620
- * @param metadata - Domain-specific structured data; optional `cause` can be included
621
- */
622
- protected constructor(message: string, code: string, metadata?: DomainErrorMetadata);
623
- }
624
-
625
- /**
626
- * Custom error class for entity validation failures.
627
- */
628
- declare class EntityValidationError extends DomainError {
629
- constructor(message: string, cause?: Error);
630
- }
631
-
632
- declare class InvalidValueObjectError extends DomainError {
633
- constructor(message: string);
634
- }
635
-
636
- export { AggregateId, AggregateRoot, type AggregateRootInterface, ApplicationError, type ApplicationServicePort, type BaseEntityProps, type CreateEntityProps, DomainError, type DomainErrorMetadata, DomainEvent, type DomainEventPayload, Entity, type EntityBaseInterface, EntityValidationError, HttpStatus, type HttpStatusCode, HttpStatusMessage, InvalidValueObjectError, PrimitiveValueObject, type UnwrapValueObject, ValueObject, deepFreeze, ensureObject, unwrapValueObject };
720
+ export { AggregateId, AggregateRoot, ApplicationError, type ApplicationServicePort, DomainError, type DomainErrorMetadata, DomainEvent, type DomainEventPayload, DomainViolation, Entity, type EntityId, type EntityProps, EntityValidationError, HttpStatus, type HttpStatusCode, HttpStatusMessage, InvalidValueObjectError, PrimitiveValueObject, type Props, Result, UUID, type UnixTimestampMillis, type UnwrapValueObject, ValueObject, deepFreeze, ensureObject, unwrapValueObject };