@rineex/ddd 1.0.0 → 1.1.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,47 +27,6 @@ interface ApplicationServicePort<I, O> {
27
27
  execute: (args: I) => Promise<O>;
28
28
  }
29
29
 
30
- interface DomainErrorMetadata {
31
- cause?: {
32
- name: string;
33
- message: string;
34
- stack?: string;
35
- };
36
- [key: string]: unknown;
37
- }
38
- /**
39
- * Base class for all Domain Errors in the application.
40
- *
41
- * This class ensures:
42
- * 1. Serializable and structured for logs or API responses.
43
- * 2. Identifiable via stable error codes (not just class names).
44
- * 3. Contextual with optional structured metadata.
45
- * 4. Supports error chaining (cause) and stack trace preservation.
46
- *
47
- * @example
48
- * export class InsufficientFundsError extends DomainError {
49
- * constructor(accountId: string, currentBalance: number) {
50
- * super(
51
- * `Account ${accountId} has insufficient funds.`,
52
- * 'INSUFFICIENT_FUNDS',
53
- * { accountId, currentBalance }
54
- * );
55
- * }
56
- * }
57
- */
58
- declare abstract class DomainError extends Error {
59
- /** Stable, machine-readable error code */
60
- readonly code: string;
61
- /** Structured, immutable domain metadata */
62
- readonly metadata: Readonly<DomainErrorMetadata>;
63
- /**
64
- * @param message - Human-readable error message
65
- * @param code - Stable error code
66
- * @param metadata - Domain-specific structured data; optional `cause` can be included
67
- */
68
- protected constructor(message: string, code: string, metadata?: DomainErrorMetadata);
69
- }
70
-
71
30
  declare abstract class ValueObject<T> {
72
31
  get value(): T;
73
32
  protected readonly props: Readonly<T>;
@@ -91,17 +50,6 @@ declare abstract class ValueObject<T> {
91
50
  protected abstract validate(props: T): void;
92
51
  }
93
52
 
94
- /**
95
- * Custom error class for entity validation failures.
96
- */
97
- declare class EntityValidationError extends DomainError {
98
- constructor(message: string, cause?: Error);
99
- }
100
-
101
- declare class InvalidValueObjectError extends DomainError {
102
- constructor(message: string);
103
- }
104
-
105
53
  /**
106
54
  * AggregateId is a ValueObject that represents a unique identifier for an aggregate.
107
55
  */
@@ -143,6 +91,15 @@ declare class AggregateId extends ValueObject<string> {
143
91
  protected validate(value: string): void;
144
92
  }
145
93
 
94
+ /**
95
+ * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.
96
+ *
97
+ * @param obj - The object to be deeply frozen.
98
+ * @param seen - A WeakSet to track already processed objects (for circular references).
99
+ * @returns A deeply frozen version of the input object.
100
+ */
101
+ declare function deepFreeze<T>(obj: T, seen?: WeakSet<object>): Readonly<T>;
102
+
146
103
  /**
147
104
  * HTTP status code catalog.
148
105
  *
@@ -302,15 +259,6 @@ declare const HttpStatusMessage: {
302
259
  };
303
260
  type HttpStatusMessage = (typeof HttpStatusMessage)[keyof typeof HttpStatusMessage];
304
261
 
305
- /**
306
- * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.
307
- *
308
- * @param obj - The object to be deeply frozen.
309
- * @param seen - A WeakSet to track already processed objects (for circular references).
310
- * @returns A deeply frozen version of the input object.
311
- */
312
- declare function deepFreeze<T>(obj: T, seen?: WeakSet<object>): Readonly<T>;
313
-
314
262
  interface ErrorParams {
315
263
  message: string;
316
264
  code: HttpStatusMessage;
@@ -363,4 +311,245 @@ type UnwrapValueObject<T> = T extends ValueObject<infer V> ? UnwrapValueObject<V
363
311
  declare function unwrapValueObject<T>(input: T, seen?: WeakSet<object>): UnwrapValueObject<T>;
364
312
  declare function ensureObject<T>(input: UnwrapValueObject<T>): object;
365
313
 
366
- export { AggregateId, ApplicationError, type ApplicationServicePort, DomainError, type DomainErrorMetadata, EntityValidationError, HttpStatus, type HttpStatusCode, HttpStatusMessage, InvalidValueObjectError, type UnwrapValueObject, ValueObject, deepFreeze, ensureObject, unwrapValueObject };
314
+ interface EntityBaseInterface {
315
+ id: AggregateId;
316
+ equals: (entity: unknown) => boolean;
317
+ }
318
+ /**
319
+ * Base properties common to all entities, including ID and timestamps.
320
+ */
321
+ interface BaseEntityProps {
322
+ /** Unique identifier for the entity */
323
+ id?: AggregateId;
324
+ /** Date when the entity was created */
325
+ createdAt: Date;
326
+ }
327
+ /**
328
+ * Interface for constructing an entity with optional timestamps.
329
+ * @template Props - The specific props type for the entity
330
+ */
331
+ type CreateEntityProps<T> = BaseEntityProps & {
332
+ props: T;
333
+ };
334
+ /**
335
+ * Abstract base class for domain entities in a Domain-Driven Design (DDD) context.
336
+ * Provides common functionality for entity identification, equality comparison,
337
+ * immutability, and validation. Entities extending this class must implement
338
+ * the `validate` method to enforce domain invariants.
339
+ * @template EntityProps - The specific props type for the entity
340
+ */
341
+ declare abstract class Entity<EntityProps> {
342
+ #private;
343
+ /**
344
+ * Returns the creation timestamp.
345
+ * A new Date instance is returned to preserve immutability.
346
+ *
347
+ * @returns {Date} The creation date of the entity.
348
+ */
349
+ get createdAt(): Date;
350
+ /**
351
+ * Gets the entity's unique identifier.
352
+ * @returns The entity's ID
353
+ */
354
+ get id(): AggregateId;
355
+ get metadata(): Readonly<{
356
+ createdAt: string;
357
+ id: string;
358
+ }>;
359
+ /**
360
+ * Returns an immutable shallow copy of the entity's properties.
361
+ *
362
+ * @returns {Readonly<EntityProps>} The entity domain properties.
363
+ */
364
+ get props(): Readonly<EntityProps>;
365
+ /**
366
+ * Constructs an entity with the provided properties and timestamps.
367
+ * Ensures immutability by cloning props and validates the entity.
368
+ * @param params - Entity creation parameters
369
+ * @throws EntityValidationError if the ID is empty or validation fails
370
+ */
371
+ protected constructor({ createdAt, props, id, }: CreateEntityProps<EntityProps>);
372
+ /**
373
+ * Checks if the provided value is an instance of Entity.
374
+ * @param entity - The value to check
375
+ * @returns True if the value is an Entity instance
376
+ */
377
+ static isEntity(entity: unknown): entity is EntityBaseInterface;
378
+ /**
379
+ * Compares this entity with another to determine if they are the same.
380
+ * Equality is based on the entity ID.
381
+ * @param other - The entity to compare with
382
+ * @returns True if the entities have the same ID
383
+ */
384
+ equals(other?: Entity<EntityProps>): boolean;
385
+ /**
386
+ * Returns a frozen copy of the entity's properties, including base properties.
387
+ * Ensures immutability by returning a new object.
388
+ * @returns A frozen copy of the entity's properties
389
+ */
390
+ getPropsCopy(): Readonly<EntityProps>;
391
+ /**
392
+ * Determines if the entity is transient, i.e., it has not been persisted yet.
393
+ * By convention, an entity is considered transient if it lacks a valid identifier.
394
+ * This can be useful when performing logic that depends on persistence state,
395
+ * such as conditional inserts or validations that only apply to new entities.
396
+ *
397
+ * @returns True if the entity is transient (not persisted), otherwise false.
398
+ */
399
+ isPersisted(): boolean;
400
+ toJSON(): Record<string, unknown>;
401
+ toObject(): Readonly<UnwrapValueObject<EntityProps> & {
402
+ createdAt: string;
403
+ id: string;
404
+ }>;
405
+ /**
406
+ * Validates the entity's state to enforce domain invariants.
407
+ * Must be implemented by subclasses to define specific validation rules.
408
+ * @throws EntityValidationError if validation fails
409
+ */
410
+ abstract validate(): void;
411
+ }
412
+
413
+ type Primitive = boolean | number | string | null;
414
+ type Serializable = Primitive | Serializable[] | {
415
+ [key: string]: Serializable;
416
+ };
417
+ type DomainEventPayload = Record<string, Serializable>;
418
+ type DomainEventProps<T> = {
419
+ id: string;
420
+ aggregateId: string;
421
+ schemaVersion: number;
422
+ occurredAt: number;
423
+ payload: T;
424
+ };
425
+ declare abstract class DomainEvent<T extends DomainEventPayload = DomainEventPayload> {
426
+ abstract readonly eventName: string;
427
+ readonly id: string;
428
+ readonly aggregateId: string;
429
+ readonly schemaVersion: number;
430
+ readonly occurredAt: number;
431
+ readonly payload: Readonly<T>;
432
+ protected constructor(props: DomainEventProps<T>);
433
+ toPrimitives(): {
434
+ schemaVersion: number;
435
+ aggregateId: string;
436
+ occurredAt: number;
437
+ eventName: string;
438
+ payload: Readonly<T>;
439
+ id: string;
440
+ };
441
+ }
442
+
443
+ /**
444
+ * Interface for AggregateRoot to ensure type safety and extensibility.
445
+ */
446
+ interface AggregateRootInterface {
447
+ readonly id: AggregateId;
448
+ readonly domainEvents: readonly DomainEvent[];
449
+ /**
450
+ * Validates the aggregate's invariants.
451
+ * @throws {EntityValidationError} If validation fails.
452
+ */
453
+ validate: () => void;
454
+ /**
455
+ * Adds a domain event to the aggregate.
456
+ * @param event The domain event to add.
457
+ */
458
+ addEvent: (event: DomainEvent) => void;
459
+ /**
460
+ * Retrieves and clears all domain events recorded by this aggregate.
461
+ *
462
+ * Domain events represent facts that occurred as a result of state changes
463
+ * within the aggregate. This method transfers ownership of those events
464
+ * to the application layer for further processing (e.g. publishing).
465
+ *
466
+ * Calling this method has the side effect of clearing the aggregate's
467
+ * internal event collection to prevent duplicate handling.
468
+ *
469
+ * This method is intended to be invoked by application services
470
+ * after the aggregate has been successfully persisted.
471
+ *
472
+ * @returns A read-only list of domain events raised by this aggregate.
473
+ */
474
+ pullDomainEvents: () => readonly DomainEvent[];
475
+ }
476
+ /**
477
+ * Base class for aggregate roots in DDD, encapsulating domain events and validation.
478
+ * @template EntityProps The type of the entity's properties.
479
+ */
480
+ declare abstract class AggregateRoot<EntityProps> extends Entity<EntityProps> implements AggregateRootInterface {
481
+ /**
482
+ * Gets a read-only copy of the domain events.
483
+ */
484
+ get domainEvents(): readonly DomainEvent[];
485
+ /**
486
+ * Internal list of domain events.
487
+ */
488
+ private readonly _domainEvents;
489
+ /**
490
+ * Adds a domain event to the aggregate after validating invariants.
491
+ * @param domainEvent The domain event to add.
492
+ * @throws {EntityValidationError} If invariants are not met.
493
+ */
494
+ addEvent(domainEvent: DomainEvent): void;
495
+ pullDomainEvents(): readonly DomainEvent[];
496
+ /**
497
+ * Validates the entity's invariants.
498
+ * @throws {EntityValidationError} If validation fails.
499
+ */
500
+ abstract validate(): void;
501
+ }
502
+
503
+ interface DomainErrorMetadata {
504
+ cause?: {
505
+ name: string;
506
+ message: string;
507
+ stack?: string;
508
+ };
509
+ [key: string]: unknown;
510
+ }
511
+ /**
512
+ * Base class for all Domain Errors in the application.
513
+ *
514
+ * This class ensures:
515
+ * 1. Serializable and structured for logs or API responses.
516
+ * 2. Identifiable via stable error codes (not just class names).
517
+ * 3. Contextual with optional structured metadata.
518
+ * 4. Supports error chaining (cause) and stack trace preservation.
519
+ *
520
+ * @example
521
+ * export class InsufficientFundsError extends DomainError {
522
+ * constructor(accountId: string, currentBalance: number) {
523
+ * super(
524
+ * `Account ${accountId} has insufficient funds.`,
525
+ * 'INSUFFICIENT_FUNDS',
526
+ * { accountId, currentBalance }
527
+ * );
528
+ * }
529
+ * }
530
+ */
531
+ declare abstract class DomainError extends Error {
532
+ /** Stable, machine-readable error code */
533
+ readonly code: string;
534
+ /** Structured, immutable domain metadata */
535
+ readonly metadata: Readonly<DomainErrorMetadata>;
536
+ /**
537
+ * @param message - Human-readable error message
538
+ * @param code - Stable error code
539
+ * @param metadata - Domain-specific structured data; optional `cause` can be included
540
+ */
541
+ protected constructor(message: string, code: string, metadata?: DomainErrorMetadata);
542
+ }
543
+
544
+ /**
545
+ * Custom error class for entity validation failures.
546
+ */
547
+ declare class EntityValidationError extends DomainError {
548
+ constructor(message: string, cause?: Error);
549
+ }
550
+
551
+ declare class InvalidValueObjectError extends DomainError {
552
+ constructor(message: string);
553
+ }
554
+
555
+ 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, type UnwrapValueObject, ValueObject, deepFreeze, ensureObject, unwrapValueObject };
package/dist/index.d.ts CHANGED
@@ -27,47 +27,6 @@ interface ApplicationServicePort<I, O> {
27
27
  execute: (args: I) => Promise<O>;
28
28
  }
29
29
 
30
- interface DomainErrorMetadata {
31
- cause?: {
32
- name: string;
33
- message: string;
34
- stack?: string;
35
- };
36
- [key: string]: unknown;
37
- }
38
- /**
39
- * Base class for all Domain Errors in the application.
40
- *
41
- * This class ensures:
42
- * 1. Serializable and structured for logs or API responses.
43
- * 2. Identifiable via stable error codes (not just class names).
44
- * 3. Contextual with optional structured metadata.
45
- * 4. Supports error chaining (cause) and stack trace preservation.
46
- *
47
- * @example
48
- * export class InsufficientFundsError extends DomainError {
49
- * constructor(accountId: string, currentBalance: number) {
50
- * super(
51
- * `Account ${accountId} has insufficient funds.`,
52
- * 'INSUFFICIENT_FUNDS',
53
- * { accountId, currentBalance }
54
- * );
55
- * }
56
- * }
57
- */
58
- declare abstract class DomainError extends Error {
59
- /** Stable, machine-readable error code */
60
- readonly code: string;
61
- /** Structured, immutable domain metadata */
62
- readonly metadata: Readonly<DomainErrorMetadata>;
63
- /**
64
- * @param message - Human-readable error message
65
- * @param code - Stable error code
66
- * @param metadata - Domain-specific structured data; optional `cause` can be included
67
- */
68
- protected constructor(message: string, code: string, metadata?: DomainErrorMetadata);
69
- }
70
-
71
30
  declare abstract class ValueObject<T> {
72
31
  get value(): T;
73
32
  protected readonly props: Readonly<T>;
@@ -91,17 +50,6 @@ declare abstract class ValueObject<T> {
91
50
  protected abstract validate(props: T): void;
92
51
  }
93
52
 
94
- /**
95
- * Custom error class for entity validation failures.
96
- */
97
- declare class EntityValidationError extends DomainError {
98
- constructor(message: string, cause?: Error);
99
- }
100
-
101
- declare class InvalidValueObjectError extends DomainError {
102
- constructor(message: string);
103
- }
104
-
105
53
  /**
106
54
  * AggregateId is a ValueObject that represents a unique identifier for an aggregate.
107
55
  */
@@ -143,6 +91,15 @@ declare class AggregateId extends ValueObject<string> {
143
91
  protected validate(value: string): void;
144
92
  }
145
93
 
94
+ /**
95
+ * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.
96
+ *
97
+ * @param obj - The object to be deeply frozen.
98
+ * @param seen - A WeakSet to track already processed objects (for circular references).
99
+ * @returns A deeply frozen version of the input object.
100
+ */
101
+ declare function deepFreeze<T>(obj: T, seen?: WeakSet<object>): Readonly<T>;
102
+
146
103
  /**
147
104
  * HTTP status code catalog.
148
105
  *
@@ -302,15 +259,6 @@ declare const HttpStatusMessage: {
302
259
  };
303
260
  type HttpStatusMessage = (typeof HttpStatusMessage)[keyof typeof HttpStatusMessage];
304
261
 
305
- /**
306
- * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.
307
- *
308
- * @param obj - The object to be deeply frozen.
309
- * @param seen - A WeakSet to track already processed objects (for circular references).
310
- * @returns A deeply frozen version of the input object.
311
- */
312
- declare function deepFreeze<T>(obj: T, seen?: WeakSet<object>): Readonly<T>;
313
-
314
262
  interface ErrorParams {
315
263
  message: string;
316
264
  code: HttpStatusMessage;
@@ -363,4 +311,245 @@ type UnwrapValueObject<T> = T extends ValueObject<infer V> ? UnwrapValueObject<V
363
311
  declare function unwrapValueObject<T>(input: T, seen?: WeakSet<object>): UnwrapValueObject<T>;
364
312
  declare function ensureObject<T>(input: UnwrapValueObject<T>): object;
365
313
 
366
- export { AggregateId, ApplicationError, type ApplicationServicePort, DomainError, type DomainErrorMetadata, EntityValidationError, HttpStatus, type HttpStatusCode, HttpStatusMessage, InvalidValueObjectError, type UnwrapValueObject, ValueObject, deepFreeze, ensureObject, unwrapValueObject };
314
+ interface EntityBaseInterface {
315
+ id: AggregateId;
316
+ equals: (entity: unknown) => boolean;
317
+ }
318
+ /**
319
+ * Base properties common to all entities, including ID and timestamps.
320
+ */
321
+ interface BaseEntityProps {
322
+ /** Unique identifier for the entity */
323
+ id?: AggregateId;
324
+ /** Date when the entity was created */
325
+ createdAt: Date;
326
+ }
327
+ /**
328
+ * Interface for constructing an entity with optional timestamps.
329
+ * @template Props - The specific props type for the entity
330
+ */
331
+ type CreateEntityProps<T> = BaseEntityProps & {
332
+ props: T;
333
+ };
334
+ /**
335
+ * Abstract base class for domain entities in a Domain-Driven Design (DDD) context.
336
+ * Provides common functionality for entity identification, equality comparison,
337
+ * immutability, and validation. Entities extending this class must implement
338
+ * the `validate` method to enforce domain invariants.
339
+ * @template EntityProps - The specific props type for the entity
340
+ */
341
+ declare abstract class Entity<EntityProps> {
342
+ #private;
343
+ /**
344
+ * Returns the creation timestamp.
345
+ * A new Date instance is returned to preserve immutability.
346
+ *
347
+ * @returns {Date} The creation date of the entity.
348
+ */
349
+ get createdAt(): Date;
350
+ /**
351
+ * Gets the entity's unique identifier.
352
+ * @returns The entity's ID
353
+ */
354
+ get id(): AggregateId;
355
+ get metadata(): Readonly<{
356
+ createdAt: string;
357
+ id: string;
358
+ }>;
359
+ /**
360
+ * Returns an immutable shallow copy of the entity's properties.
361
+ *
362
+ * @returns {Readonly<EntityProps>} The entity domain properties.
363
+ */
364
+ get props(): Readonly<EntityProps>;
365
+ /**
366
+ * Constructs an entity with the provided properties and timestamps.
367
+ * Ensures immutability by cloning props and validates the entity.
368
+ * @param params - Entity creation parameters
369
+ * @throws EntityValidationError if the ID is empty or validation fails
370
+ */
371
+ protected constructor({ createdAt, props, id, }: CreateEntityProps<EntityProps>);
372
+ /**
373
+ * Checks if the provided value is an instance of Entity.
374
+ * @param entity - The value to check
375
+ * @returns True if the value is an Entity instance
376
+ */
377
+ static isEntity(entity: unknown): entity is EntityBaseInterface;
378
+ /**
379
+ * Compares this entity with another to determine if they are the same.
380
+ * Equality is based on the entity ID.
381
+ * @param other - The entity to compare with
382
+ * @returns True if the entities have the same ID
383
+ */
384
+ equals(other?: Entity<EntityProps>): boolean;
385
+ /**
386
+ * Returns a frozen copy of the entity's properties, including base properties.
387
+ * Ensures immutability by returning a new object.
388
+ * @returns A frozen copy of the entity's properties
389
+ */
390
+ getPropsCopy(): Readonly<EntityProps>;
391
+ /**
392
+ * Determines if the entity is transient, i.e., it has not been persisted yet.
393
+ * By convention, an entity is considered transient if it lacks a valid identifier.
394
+ * This can be useful when performing logic that depends on persistence state,
395
+ * such as conditional inserts or validations that only apply to new entities.
396
+ *
397
+ * @returns True if the entity is transient (not persisted), otherwise false.
398
+ */
399
+ isPersisted(): boolean;
400
+ toJSON(): Record<string, unknown>;
401
+ toObject(): Readonly<UnwrapValueObject<EntityProps> & {
402
+ createdAt: string;
403
+ id: string;
404
+ }>;
405
+ /**
406
+ * Validates the entity's state to enforce domain invariants.
407
+ * Must be implemented by subclasses to define specific validation rules.
408
+ * @throws EntityValidationError if validation fails
409
+ */
410
+ abstract validate(): void;
411
+ }
412
+
413
+ type Primitive = boolean | number | string | null;
414
+ type Serializable = Primitive | Serializable[] | {
415
+ [key: string]: Serializable;
416
+ };
417
+ type DomainEventPayload = Record<string, Serializable>;
418
+ type DomainEventProps<T> = {
419
+ id: string;
420
+ aggregateId: string;
421
+ schemaVersion: number;
422
+ occurredAt: number;
423
+ payload: T;
424
+ };
425
+ declare abstract class DomainEvent<T extends DomainEventPayload = DomainEventPayload> {
426
+ abstract readonly eventName: string;
427
+ readonly id: string;
428
+ readonly aggregateId: string;
429
+ readonly schemaVersion: number;
430
+ readonly occurredAt: number;
431
+ readonly payload: Readonly<T>;
432
+ protected constructor(props: DomainEventProps<T>);
433
+ toPrimitives(): {
434
+ schemaVersion: number;
435
+ aggregateId: string;
436
+ occurredAt: number;
437
+ eventName: string;
438
+ payload: Readonly<T>;
439
+ id: string;
440
+ };
441
+ }
442
+
443
+ /**
444
+ * Interface for AggregateRoot to ensure type safety and extensibility.
445
+ */
446
+ interface AggregateRootInterface {
447
+ readonly id: AggregateId;
448
+ readonly domainEvents: readonly DomainEvent[];
449
+ /**
450
+ * Validates the aggregate's invariants.
451
+ * @throws {EntityValidationError} If validation fails.
452
+ */
453
+ validate: () => void;
454
+ /**
455
+ * Adds a domain event to the aggregate.
456
+ * @param event The domain event to add.
457
+ */
458
+ addEvent: (event: DomainEvent) => void;
459
+ /**
460
+ * Retrieves and clears all domain events recorded by this aggregate.
461
+ *
462
+ * Domain events represent facts that occurred as a result of state changes
463
+ * within the aggregate. This method transfers ownership of those events
464
+ * to the application layer for further processing (e.g. publishing).
465
+ *
466
+ * Calling this method has the side effect of clearing the aggregate's
467
+ * internal event collection to prevent duplicate handling.
468
+ *
469
+ * This method is intended to be invoked by application services
470
+ * after the aggregate has been successfully persisted.
471
+ *
472
+ * @returns A read-only list of domain events raised by this aggregate.
473
+ */
474
+ pullDomainEvents: () => readonly DomainEvent[];
475
+ }
476
+ /**
477
+ * Base class for aggregate roots in DDD, encapsulating domain events and validation.
478
+ * @template EntityProps The type of the entity's properties.
479
+ */
480
+ declare abstract class AggregateRoot<EntityProps> extends Entity<EntityProps> implements AggregateRootInterface {
481
+ /**
482
+ * Gets a read-only copy of the domain events.
483
+ */
484
+ get domainEvents(): readonly DomainEvent[];
485
+ /**
486
+ * Internal list of domain events.
487
+ */
488
+ private readonly _domainEvents;
489
+ /**
490
+ * Adds a domain event to the aggregate after validating invariants.
491
+ * @param domainEvent The domain event to add.
492
+ * @throws {EntityValidationError} If invariants are not met.
493
+ */
494
+ addEvent(domainEvent: DomainEvent): void;
495
+ pullDomainEvents(): readonly DomainEvent[];
496
+ /**
497
+ * Validates the entity's invariants.
498
+ * @throws {EntityValidationError} If validation fails.
499
+ */
500
+ abstract validate(): void;
501
+ }
502
+
503
+ interface DomainErrorMetadata {
504
+ cause?: {
505
+ name: string;
506
+ message: string;
507
+ stack?: string;
508
+ };
509
+ [key: string]: unknown;
510
+ }
511
+ /**
512
+ * Base class for all Domain Errors in the application.
513
+ *
514
+ * This class ensures:
515
+ * 1. Serializable and structured for logs or API responses.
516
+ * 2. Identifiable via stable error codes (not just class names).
517
+ * 3. Contextual with optional structured metadata.
518
+ * 4. Supports error chaining (cause) and stack trace preservation.
519
+ *
520
+ * @example
521
+ * export class InsufficientFundsError extends DomainError {
522
+ * constructor(accountId: string, currentBalance: number) {
523
+ * super(
524
+ * `Account ${accountId} has insufficient funds.`,
525
+ * 'INSUFFICIENT_FUNDS',
526
+ * { accountId, currentBalance }
527
+ * );
528
+ * }
529
+ * }
530
+ */
531
+ declare abstract class DomainError extends Error {
532
+ /** Stable, machine-readable error code */
533
+ readonly code: string;
534
+ /** Structured, immutable domain metadata */
535
+ readonly metadata: Readonly<DomainErrorMetadata>;
536
+ /**
537
+ * @param message - Human-readable error message
538
+ * @param code - Stable error code
539
+ * @param metadata - Domain-specific structured data; optional `cause` can be included
540
+ */
541
+ protected constructor(message: string, code: string, metadata?: DomainErrorMetadata);
542
+ }
543
+
544
+ /**
545
+ * Custom error class for entity validation failures.
546
+ */
547
+ declare class EntityValidationError extends DomainError {
548
+ constructor(message: string, cause?: Error);
549
+ }
550
+
551
+ declare class InvalidValueObjectError extends DomainError {
552
+ constructor(message: string);
553
+ }
554
+
555
+ 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, type UnwrapValueObject, ValueObject, deepFreeze, ensureObject, unwrapValueObject };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var y=Object.create;var E=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames,A=Object.getOwnPropertySymbols,L=Object.getPrototypeOf,I=Object.prototype.hasOwnProperty,C=Object.prototype.propertyIsEnumerable;var N=(e,t,r)=>t in e?E(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,l=(e,t)=>{for(var r in t||(t={}))I.call(t,r)&&N(e,r,t[r]);if(A)for(var r of A(t))C.call(t,r)&&N(e,r,t[r]);return e};var P=(e,t)=>{for(var r in t)E(e,r,{get:t[r],enumerable:!0})},_=(e,t,r,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of w(t))!I.call(e,o)&&o!==r&&E(e,o,{get:()=>t[o],enumerable:!(a=b(t,o))||a.enumerable});return e};var m=(e,t,r)=>(r=e!=null?y(L(e)):{},_(t||!e||!e.__esModule?E(r,"default",{value:e,enumerable:!0}):r,e)),M=e=>_(E({},"__esModule",{value:!0}),e);var H={};P(H,{AggregateId:()=>p,ApplicationError:()=>f,DomainError:()=>n,EntityValidationError:()=>O,HttpStatus:()=>x,HttpStatusMessage:()=>R,InvalidValueObjectError:()=>d,ValueObject:()=>s,deepFreeze:()=>T,ensureObject:()=>h,unwrapValueObject:()=>c});module.exports=M(H);var V=e=>e instanceof Error?{cause:{message:e.message,stack:e.stack,name:e.name}}:e?{cause:e}:{},n=class extends Error{constructor(t,r,a={}){super(t,l({},V(a.cause))),Object.setPrototypeOf(this,new.target.prototype),this.name=new.target.name,this.code=r,this.metadata=Object.freeze(l({},a))}};var S=m(require("fast-deep-equal/es6"));function T(e,t=new WeakSet){if(e==null||typeof e!="object"&&!Array.isArray(e)||Object.isFrozen(e)||t.has(e))return e;if(t.add(e),Array.isArray(e))e.forEach(r=>T(r,t));else for(let r in e)Object.hasOwn(e,r)&&T(e[r],t);return Object.freeze(e)}var s=class e{get value(){return this.props}constructor(t){this.validate(t),this.props=T(t)}static is(t){return t instanceof e}equals(t){return!t||!(t instanceof this.constructor)?!1:(0,S.default)(this.props,t.props)}};var O=class extends n{constructor(t,r){super(t,"ENTITY_VALIDATION_ERROR",{cause:r})}};var d=class extends n{constructor(t){super(t,"INVALID_VALUE_OBJECT")}};var U=require("uuid"),D=m(require("zod"));var i=class i extends s{get uuid(){return this.value}static create(t){return new i(t)}static generate(){return new i((0,U.v4)())}isEmpty(){return!this.value}toString(){return this.value}validate(t){let r=i.schema.safeParse(t);if(!r.success)throw new d(`Invalid AggregateId: ${r.error.message}`)}};i.schema=D.default.uuid();var p=i;var x=Object.freeze({REQUEST_HEADER_FIELDS_TOO_LARGE:431,NETWORK_AUTHENTICATION_REQUIRED:511,NON_AUTHORITATIVE_INFORMATION:203,PROXY_AUTHENTICATION_REQUIRED:407,UNAVAILABLE_FOR_LEGAL_REASONS:451,HTTP_VERSION_NOT_SUPPORTED:505,BANDWIDTH_LIMIT_EXCEEDED:509,VARIANT_ALSO_NEGOTIATES:506,UNSUPPORTED_MEDIA_TYPE:415,RANGE_NOT_SATISFIABLE:416,PRECONDITION_REQUIRED:428,INTERNAL_SERVER_ERROR:500,UNPROCESSABLE_ENTITY:422,INSUFFICIENT_STORAGE:507,SWITCHING_PROTOCOLS:101,PRECONDITION_FAILED:412,MISDIRECTED_REQUEST:421,SERVICE_UNAVAILABLE:503,TEMPORARY_REDIRECT:307,PERMANENT_REDIRECT:308,METHOD_NOT_ALLOWED:405,EXPECTATION_FAILED:417,MOVED_PERMANENTLY:301,PAYLOAD_TOO_LARGE:413,FAILED_DEPENDENCY:424,TOO_MANY_REQUESTS:429,ALREADY_REPORTED:208,MULTIPLE_CHOICES:300,PAYMENT_REQUIRED:402,UPGRADE_REQUIRED:426,PARTIAL_CONTENT:206,REQUEST_TIMEOUT:408,LENGTH_REQUIRED:411,NOT_IMPLEMENTED:501,GATEWAY_TIMEOUT:504,NOT_ACCEPTABLE:406,RESET_CONTENT:205,LOOP_DETECTED:508,MULTI_STATUS:207,NOT_MODIFIED:304,UNAUTHORIZED:401,URI_TOO_LONG:414,NOT_EXTENDED:510,EARLY_HINTS:103,BAD_REQUEST:400,IM_A_TEAPOT:418,BAD_GATEWAY:502,PROCESSING:102,NO_CONTENT:204,SEE_OTHER:303,USE_PROXY:305,FORBIDDEN:403,NOT_FOUND:404,TOO_EARLY:425,CONTINUE:100,ACCEPTED:202,CONFLICT:409,CREATED:201,IM_USED:226,LOCKED:423,FOUND:302,GONE:410,OK:200}),R={431:"Request Header Fields Too Large",511:"Network Authentication Required",203:"Non-Authoritative Information",407:"Proxy Authentication Required",451:"Unavailable For Legal Reasons",505:"HTTP Version Not Supported",509:"Bandwidth Limit Exceeded",506:"Variant Also Negotiates",415:"Unsupported Media Type",416:"Range Not Satisfiable",428:"Precondition Required",500:"Internal Server Error",422:"Unprocessable Entity",507:"Insufficient Storage",101:"Switching Protocols",412:"Precondition Failed",421:"Misdirected Request",503:"Service Unavailable",307:"Temporary Redirect",308:"Permanent Redirect",405:"Method Not Allowed",417:"Expectation Failed",301:"Moved Permanently",413:"Payload Too Large",424:"Failed Dependency",429:"Too Many Requests",208:"Already Reported",300:"Multiple Choices",402:"Payment Required",426:"Upgrade Required",206:"Partial Content",408:"Request Timeout",411:"Length Required",501:"Not Implemented",504:"Gateway Timeout",406:"Not Acceptable",205:"Reset Content",508:"Loop Detected",207:"Multi-Status",304:"Not Modified",401:"Unauthorized",414:"URI Too Long",418:"I'm a Teapot",510:"Not Extended",103:"Early Hints",400:"Bad Request",502:"Bad Gateway",102:"Processing",204:"No Content",303:"See Other",305:"Use Proxy",403:"Forbidden",404:"Not Found",425:"Too Early",100:"Continue",202:"Accepted",226:"I'm Used",409:"Conflict",201:"Created",423:"Locked",302:"Found",410:"Gone",200:"OK"};var f=class extends Error{constructor({code:t=R[500],isOperational:r=!1,status:a=500,metadata:o,message:u,cause:g}){super(u),this.name=new.target.name,this.code=t,this.status=a,this.isOperational=r,this.metadata=o,this.cause=g,Error.captureStackTrace(this,new.target)}};function c(e,t=new WeakSet){if(e==null||typeof e!="object")return e;if(t.has(e))throw new Error("Circular reference detected in ValueObject unwrap");if(t.add(e),Array.isArray(e)){let a=e.map(o=>c(o,t));return t.delete(e),a}if(e instanceof s){let a=c(e.value,t);return t.delete(e),a}if(e instanceof Date)return t.delete(e),e.toISOString();if(e instanceof Map){let a=new Map;return e.forEach((o,u)=>{a.set(u,c(o,t))}),t.delete(e),a}if(e instanceof Set){let a=new Set(Array.from(e.values()).map(o=>c(o,t)));return t.delete(e),a}let r={};for(let a in e)Object.hasOwn(e,a)&&(r[a]=c(e[a],t));return t.delete(e),r}function h(e){return e==null?{}:typeof e=="object"?e:{value:e}}0&&(module.exports={AggregateId,ApplicationError,DomainError,EntityValidationError,HttpStatus,HttpStatusMessage,InvalidValueObjectError,ValueObject,deepFreeze,ensureObject,unwrapValueObject});
1
+ var k=Object.create;var T=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames,P=Object.getOwnPropertySymbols,z=Object.getPrototypeOf,v=Object.prototype.hasOwnProperty,B=Object.prototype.propertyIsEnumerable;var w=e=>{throw TypeError(e)};var U=(e,t,r)=>t in e?T(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,l=(e,t)=>{for(var r in t||(t={}))v.call(t,r)&&U(e,r,t[r]);if(P)for(var r of P(t))B.call(t,r)&&U(e,r,t[r]);return e};var G=(e,t)=>{for(var r in t)T(e,r,{get:t[r],enumerable:!0})},x=(e,t,r,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of q(t))!v.call(e,n)&&n!==r&&T(e,n,{get:()=>t[n],enumerable:!(a=F(t,n))||a.enumerable});return e};var V=(e,t,r)=>(r=e!=null?k(z(e)):{},x(t||!e||!e.__esModule?T(r,"default",{value:e,enumerable:!0}):r,e)),Y=e=>x(T({},"__esModule",{value:!0}),e);var C=(e,t,r)=>t.has(e)||w("Cannot "+r);var o=(e,t,r)=>(C(e,t,"read from private field"),r?r.call(e):t.get(e)),R=(e,t,r)=>t.has(e)?w("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),b=(e,t,r,a)=>(C(e,t,"write to private field"),a?a.call(e,r):t.set(e,r),r);var W={};G(W,{AggregateId:()=>f,AggregateRoot:()=>h,ApplicationError:()=>N,DomainError:()=>d,DomainEvent:()=>S,Entity:()=>y,EntityValidationError:()=>m,HttpStatus:()=>Q,HttpStatusMessage:()=>I,InvalidValueObjectError:()=>g,ValueObject:()=>c,deepFreeze:()=>O,ensureObject:()=>D,unwrapValueObject:()=>i});module.exports=Y(W);function O(e,t=new WeakSet){if(e==null||typeof e!="object"&&!Array.isArray(e)||Object.isFrozen(e)||t.has(e))return e;if(t.add(e),Array.isArray(e))e.forEach(r=>O(r,t));else for(let r in e)Object.hasOwn(e,r)&&O(e[r],t);return Object.freeze(e)}var Q=Object.freeze({REQUEST_HEADER_FIELDS_TOO_LARGE:431,NETWORK_AUTHENTICATION_REQUIRED:511,NON_AUTHORITATIVE_INFORMATION:203,PROXY_AUTHENTICATION_REQUIRED:407,UNAVAILABLE_FOR_LEGAL_REASONS:451,HTTP_VERSION_NOT_SUPPORTED:505,BANDWIDTH_LIMIT_EXCEEDED:509,VARIANT_ALSO_NEGOTIATES:506,UNSUPPORTED_MEDIA_TYPE:415,RANGE_NOT_SATISFIABLE:416,PRECONDITION_REQUIRED:428,INTERNAL_SERVER_ERROR:500,UNPROCESSABLE_ENTITY:422,INSUFFICIENT_STORAGE:507,SWITCHING_PROTOCOLS:101,PRECONDITION_FAILED:412,MISDIRECTED_REQUEST:421,SERVICE_UNAVAILABLE:503,TEMPORARY_REDIRECT:307,PERMANENT_REDIRECT:308,METHOD_NOT_ALLOWED:405,EXPECTATION_FAILED:417,MOVED_PERMANENTLY:301,PAYLOAD_TOO_LARGE:413,FAILED_DEPENDENCY:424,TOO_MANY_REQUESTS:429,ALREADY_REPORTED:208,MULTIPLE_CHOICES:300,PAYMENT_REQUIRED:402,UPGRADE_REQUIRED:426,PARTIAL_CONTENT:206,REQUEST_TIMEOUT:408,LENGTH_REQUIRED:411,NOT_IMPLEMENTED:501,GATEWAY_TIMEOUT:504,NOT_ACCEPTABLE:406,RESET_CONTENT:205,LOOP_DETECTED:508,MULTI_STATUS:207,NOT_MODIFIED:304,UNAUTHORIZED:401,URI_TOO_LONG:414,NOT_EXTENDED:510,EARLY_HINTS:103,BAD_REQUEST:400,IM_A_TEAPOT:418,BAD_GATEWAY:502,PROCESSING:102,NO_CONTENT:204,SEE_OTHER:303,USE_PROXY:305,FORBIDDEN:403,NOT_FOUND:404,TOO_EARLY:425,CONTINUE:100,ACCEPTED:202,CONFLICT:409,CREATED:201,IM_USED:226,LOCKED:423,FOUND:302,GONE:410,OK:200}),I={431:"Request Header Fields Too Large",511:"Network Authentication Required",203:"Non-Authoritative Information",407:"Proxy Authentication Required",451:"Unavailable For Legal Reasons",505:"HTTP Version Not Supported",509:"Bandwidth Limit Exceeded",506:"Variant Also Negotiates",415:"Unsupported Media Type",416:"Range Not Satisfiable",428:"Precondition Required",500:"Internal Server Error",422:"Unprocessable Entity",507:"Insufficient Storage",101:"Switching Protocols",412:"Precondition Failed",421:"Misdirected Request",503:"Service Unavailable",307:"Temporary Redirect",308:"Permanent Redirect",405:"Method Not Allowed",417:"Expectation Failed",301:"Moved Permanently",413:"Payload Too Large",424:"Failed Dependency",429:"Too Many Requests",208:"Already Reported",300:"Multiple Choices",402:"Payment Required",426:"Upgrade Required",206:"Partial Content",408:"Request Timeout",411:"Length Required",501:"Not Implemented",504:"Gateway Timeout",406:"Not Acceptable",205:"Reset Content",508:"Loop Detected",207:"Multi-Status",304:"Not Modified",401:"Unauthorized",414:"URI Too Long",418:"I'm a Teapot",510:"Not Extended",103:"Early Hints",400:"Bad Request",502:"Bad Gateway",102:"Processing",204:"No Content",303:"See Other",305:"Use Proxy",403:"Forbidden",404:"Not Found",425:"Too Early",100:"Continue",202:"Accepted",226:"I'm Used",409:"Conflict",201:"Created",423:"Locked",302:"Found",410:"Gone",200:"OK"};var N=class extends Error{constructor({code:t=I[500],isOperational:r=!1,status:a=500,metadata:n,message:A,cause:H}){super(A),this.name=new.target.name,this.code=t,this.status=a,this.isOperational=r,this.metadata=n,this.cause=H,Error.captureStackTrace(this,new.target)}};var L=V(require("fast-deep-equal/es6"));var c=class e{get value(){return this.props}constructor(t){this.validate(t),this.props=O(t)}static is(t){return t instanceof e}equals(t){return!t||!(t instanceof this.constructor)?!1:(0,L.default)(this.props,t.props)}};function i(e,t=new WeakSet){if(e==null||typeof e!="object")return e;if(t.has(e))throw new Error("Circular reference detected in ValueObject unwrap");if(t.add(e),Array.isArray(e)){let a=e.map(n=>i(n,t));return t.delete(e),a}if(e instanceof c){let a=i(e.value,t);return t.delete(e),a}if(e instanceof Date)return t.delete(e),e.toISOString();if(e instanceof Map){let a=new Map;return e.forEach((n,A)=>{a.set(A,i(n,t))}),t.delete(e),a}if(e instanceof Set){let a=new Set(Array.from(e.values()).map(n=>i(n,t)));return t.delete(e),a}let r={};for(let a in e)Object.hasOwn(e,a)&&(r[a]=i(e[a],t));return t.delete(e),r}function D(e){return e==null?{}:typeof e=="object"?e:{value:e}}var K=e=>e instanceof Error?{cause:{message:e.message,stack:e.stack,name:e.name}}:e?{cause:e}:{},d=class extends Error{constructor(t,r,a={}){super(t,l({},K(a.cause))),Object.setPrototypeOf(this,new.target.prototype),this.name=new.target.name,this.code=r,this.metadata=Object.freeze(l({},a))}};var m=class extends d{constructor(t,r){super(t,"ENTITY_VALIDATION_ERROR",{cause:r})}};var M=require("uuid"),j=V(require("zod"));var g=class extends d{constructor(t){super(t,"INVALID_VALUE_OBJECT")}};var E=class E extends c{get uuid(){return this.value}static create(t){return new E(t)}static generate(){return new E((0,M.v4)())}isEmpty(){return!this.value}toString(){return this.value}validate(t){let r=E.schema.safeParse(t);if(!r.success)throw new g(`Invalid AggregateId: ${r.error.message}`)}};E.schema=j.default.uuid();var f=E;var u,s,p,_=class _{constructor({createdAt:t,props:r,id:a}){R(this,u);R(this,s);R(this,p);if(!a)throw new m("Entity ID cannot be empty");b(this,s,a!=null?a:f.generate()),b(this,p,Object.freeze(r)),b(this,u,t?new Date(t):new Date)}get createdAt(){return new Date(o(this,u))}get id(){return o(this,s)}get metadata(){return Object.freeze({createdAt:o(this,u).toISOString(),id:o(this,s).uuid})}get props(){return o(this,p)}static isEntity(t){return typeof t=="object"&&t!==null&&"id"in t&&typeof t.equals=="function"}equals(t){return!t||!_.isEntity(t)?!1:o(this,s).equals(o(t,s))}getPropsCopy(){return Object.freeze(o(this,p))}isPersisted(){return o(this,s).isEmpty()}toJSON(){return this.toObject()}toObject(){let t=i(this.getPropsCopy()),r=D(t);return Object.freeze(l(l({},this.metadata),r))}};u=new WeakMap,s=new WeakMap,p=new WeakMap;var y=_;var h=class extends y{constructor(){super(...arguments);this._domainEvents=[]}get domainEvents(){return[...this._domainEvents]}addEvent(r){this.validate(),this._domainEvents.push(r)}pullDomainEvents(){let r=[...this._domainEvents];return this._domainEvents.length=0,r}};var S=class{constructor(t){this.id=t.id,this.aggregateId=t.aggregateId,this.schemaVersion=t.schemaVersion,this.occurredAt=t.occurredAt,this.payload=Object.freeze(t.payload)}toPrimitives(){return{schemaVersion:this.schemaVersion,aggregateId:this.aggregateId,occurredAt:this.occurredAt,eventName:this.eventName,payload:this.payload,id:this.id}}};0&&(module.exports={AggregateId,AggregateRoot,ApplicationError,DomainError,DomainEvent,Entity,EntityValidationError,HttpStatus,HttpStatusMessage,InvalidValueObjectError,ValueObject,deepFreeze,ensureObject,unwrapValueObject});
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/domain/base/domain.error.ts","../src/domain/base/vo.ts","../src/utils/deep-freeze.util.ts","../src/domain/errors/entity-validation.error.ts","../src/domain/errors/invalid-vo.error.ts","../src/domain/value-objects/aggregate-id.vo.ts","../src/gateway/constants/http-code.ts","../src/utils/errors/application.error.ts","../src/utils/unwrap-vo.util.ts"],"sourcesContent":["export * from './application';\nexport * from './domain/base/domain.error';\nexport * from './domain/base/vo';\nexport * from './domain/errors/entity-validation.error';\nexport * from './domain/errors/invalid-vo.error';\nexport * from './domain/value-objects/aggregate-id.vo';\nexport * from './gateway/constants/http-code';\nexport * from './utils';\n","export interface DomainErrorMetadata {\n cause?: { name: string; message: string; stack?: string };\n [key: string]: unknown;\n}\n\nconst getCauseInfo = (cause: Error | undefined) => {\n // 1. Handle Error objects specifically\n if (cause instanceof Error) {\n return {\n cause: {\n message: cause.message,\n stack: cause.stack,\n name: cause.name,\n },\n };\n }\n\n // 2. Handle other existing values\n if (cause) {\n return { cause };\n }\n\n // 3. Default to empty\n return {};\n};\n\n/**\n * Base class for all Domain Errors in the application.\n *\n * This class ensures:\n * 1. Serializable and structured for logs or API responses.\n * 2. Identifiable via stable error codes (not just class names).\n * 3. Contextual with optional structured metadata.\n * 4. Supports error chaining (cause) and stack trace preservation.\n *\n * @example\n * export class InsufficientFundsError extends DomainError {\n * constructor(accountId: string, currentBalance: number) {\n * super(\n * `Account ${accountId} has insufficient funds.`,\n * 'INSUFFICIENT_FUNDS',\n * { accountId, currentBalance }\n * );\n * }\n * }\n */\nexport abstract class DomainError extends Error {\n /** Stable, machine-readable error code */\n public readonly code: string;\n /** Structured, immutable domain metadata */\n public readonly metadata: Readonly<DomainErrorMetadata>;\n\n /**\n * @param message - Human-readable error message\n * @param code - Stable error code\n * @param metadata - Domain-specific structured data; optional `cause` can be included\n */\n protected constructor(\n message: string,\n code: string,\n metadata: DomainErrorMetadata = {},\n ) {\n super(message, { ...getCauseInfo(metadata.cause) });\n\n // Restore prototype chain for proper `instanceof` checks\n Object.setPrototypeOf(this, new.target.prototype);\n\n this.name = new.target.name;\n this.code = code;\n this.metadata = Object.freeze({ ...metadata });\n }\n}\n","import deepEqual from 'fast-deep-equal/es6';\n\nimport { deepFreeze } from '@/utils/deep-freeze.util';\n\nexport abstract class ValueObject<T> {\n get value(): T {\n return this.props;\n }\n\n protected readonly props: Readonly<T>;\n\n protected constructor(props: T) {\n this.validate(props);\n this.props = deepFreeze(props);\n }\n\n /**\n * Type guard to check if an unknown object is an instance of ValueObject.\n * This is useful for runtime type checking.\n *\n * @param vo The object to check.\n * @returns True if the object is a ValueObject instance, false otherwise.\n */\n public static is(vo: unknown): vo is ValueObject<unknown> {\n return vo instanceof ValueObject;\n }\n\n /**\n * Deep equality comparison of ValueObjects\n */\n public equals(other?: ValueObject<T>): boolean {\n if (\n !other ||\n !(other instanceof (this.constructor as typeof ValueObject))\n ) {\n return false;\n }\n\n return deepEqual(this.props, other.props);\n }\n\n /**\n * Validates the value object props\n * @throws InvalidValueObjectError if validation fails\n */\n protected abstract validate(props: T): void;\n}\n","/**\n * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.\n *\n * @param obj - The object to be deeply frozen.\n * @param seen - A WeakSet to track already processed objects (for circular references).\n * @returns A deeply frozen version of the input object.\n */\nexport function deepFreeze<T>(\n obj: T,\n seen = new WeakSet<object>(),\n): Readonly<T> {\n // Handle null, undefined, or non-object types\n if (obj == null || (typeof obj !== 'object' && !Array.isArray(obj))) {\n return obj;\n }\n\n // Skip if already frozen\n if (Object.isFrozen(obj)) {\n return obj as Readonly<T>;\n }\n\n // Handle circular references\n if (seen.has(obj as object)) {\n return obj as Readonly<T>;\n }\n\n seen.add(obj as object);\n\n // Handle arrays explicitly\n if (Array.isArray(obj)) {\n obj.forEach(item => deepFreeze(item, seen));\n } else {\n // Handle plain objects\n for (const key in obj) {\n if (Object.hasOwn(obj, key)) {\n deepFreeze((obj as Record<string, unknown>)[key], seen);\n }\n }\n }\n\n return Object.freeze(obj) as Readonly<T>;\n}\n","import { DomainError } from '../base/domain.error';\n\n/**\n * Custom error class for entity validation failures.\n */\nexport class EntityValidationError extends DomainError {\n constructor(message: string, cause?: Error) {\n super(message, 'ENTITY_VALIDATION_ERROR', { cause });\n }\n}\n","import { DomainError } from '../base/domain.error';\n\nexport class InvalidValueObjectError extends DomainError {\n constructor(message: string) {\n super(message, 'INVALID_VALUE_OBJECT');\n }\n}\n","import { v4 } from 'uuid';\nimport z from 'zod';\n\nimport { InvalidValueObjectError } from '../errors/invalid-vo.error';\nimport { ValueObject } from '../base/vo';\n\n/**\n * AggregateId is a ValueObject that represents a unique identifier for an aggregate.\n */\nexport class AggregateId extends ValueObject<string> {\n /**\n * The schema for the AggregateId\n */\n private static readonly schema = z.uuid();\n\n /**\n * Get the UUID of the AggregateId\n * @returns The UUID of the AggregateId\n */\n public get uuid(): string {\n return this.value;\n }\n\n /**\n * Create a new AggregateId\n * @param value The value to create the AggregateId from\n * @returns The new AggregateId\n */\n public static create(value: string): AggregateId {\n return new AggregateId(value);\n }\n\n /**\n * Create a new AggregateId with a random UUID v4\n */\n public static generate(): AggregateId {\n return new AggregateId(v4());\n }\n\n /**\n * Check if the AggregateId is empty\n * @returns True if the AggregateId is empty, false otherwise\n */\n public isEmpty(): boolean {\n return !this.value;\n }\n\n /**\n * Convert the AggregateId to a string\n * @returns The string representation of the AggregateId\n */\n public toString(): string {\n return this.value;\n }\n\n /**\n * Validate the AggregateId\n * @param value The value to validate\n * @throws InvalidValueObjectException if the value is invalid\n */\n protected validate(value: string): void {\n const result = AggregateId.schema.safeParse(value);\n\n if (!result.success) {\n throw new InvalidValueObjectError(\n `Invalid AggregateId: ${result.error.message}`,\n );\n }\n }\n}\n","/**\n * HTTP status code catalog.\n *\n * This object provides a typed, immutable map of standard HTTP status names\n * to their numeric codes. Designed for server-side frameworks such as Fastify.\n *\n * - All identifiers use clear, canonical semantic names.\n * - Values are numeric status codes.\n * - Frozen to prevent runtime mutation.\n * - Exporting `HttpStatus` ensures type-safe usage across the codebase.\n * Usage:\n * ```ts\n * import { HttpStatus } from 'path-to-this-file';\n *\n * function handleRequest() {\n * return {\n * statusCode: HttpStatus.OK,\n * body: 'Success',\n * };\n * }\n * ```\n */\nexport const HttpStatus = Object.freeze({\n REQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n NETWORK_AUTHENTICATION_REQUIRED: 511,\n NON_AUTHORITATIVE_INFORMATION: 203,\n PROXY_AUTHENTICATION_REQUIRED: 407,\n\n UNAVAILABLE_FOR_LEGAL_REASONS: 451,\n HTTP_VERSION_NOT_SUPPORTED: 505,\n BANDWIDTH_LIMIT_EXCEEDED: 509,\n VARIANT_ALSO_NEGOTIATES: 506,\n UNSUPPORTED_MEDIA_TYPE: 415,\n RANGE_NOT_SATISFIABLE: 416,\n PRECONDITION_REQUIRED: 428,\n INTERNAL_SERVER_ERROR: 500,\n UNPROCESSABLE_ENTITY: 422,\n INSUFFICIENT_STORAGE: 507,\n\n SWITCHING_PROTOCOLS: 101,\n PRECONDITION_FAILED: 412,\n MISDIRECTED_REQUEST: 421,\n SERVICE_UNAVAILABLE: 503,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n METHOD_NOT_ALLOWED: 405,\n EXPECTATION_FAILED: 417,\n\n MOVED_PERMANENTLY: 301,\n PAYLOAD_TOO_LARGE: 413,\n FAILED_DEPENDENCY: 424,\n TOO_MANY_REQUESTS: 429,\n ALREADY_REPORTED: 208,\n MULTIPLE_CHOICES: 300,\n PAYMENT_REQUIRED: 402,\n UPGRADE_REQUIRED: 426,\n PARTIAL_CONTENT: 206,\n REQUEST_TIMEOUT: 408,\n LENGTH_REQUIRED: 411,\n NOT_IMPLEMENTED: 501,\n GATEWAY_TIMEOUT: 504,\n NOT_ACCEPTABLE: 406,\n RESET_CONTENT: 205,\n LOOP_DETECTED: 508,\n MULTI_STATUS: 207,\n NOT_MODIFIED: 304,\n UNAUTHORIZED: 401,\n URI_TOO_LONG: 414,\n NOT_EXTENDED: 510,\n EARLY_HINTS: 103,\n BAD_REQUEST: 400,\n IM_A_TEAPOT: 418,\n BAD_GATEWAY: 502,\n PROCESSING: 102,\n NO_CONTENT: 204,\n SEE_OTHER: 303,\n USE_PROXY: 305,\n\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n TOO_EARLY: 425,\n CONTINUE: 100,\n ACCEPTED: 202,\n CONFLICT: 409,\n CREATED: 201,\n IM_USED: 226,\n LOCKED: 423,\n FOUND: 302,\n GONE: 410,\n OK: 200,\n} as const);\n\n/**\n * HTTP status messages mapped by numeric code.\n * Use for sending descriptive text in responses or logging.\n */\nexport const HttpStatusMessage = {\n 431: 'Request Header Fields Too Large',\n 511: 'Network Authentication Required',\n 203: 'Non-Authoritative Information',\n 407: 'Proxy Authentication Required',\n 451: 'Unavailable For Legal Reasons',\n 505: 'HTTP Version Not Supported',\n 509: 'Bandwidth Limit Exceeded',\n 506: 'Variant Also Negotiates',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 428: 'Precondition Required',\n 500: 'Internal Server Error',\n 422: 'Unprocessable Entity',\n 507: 'Insufficient Storage',\n 101: 'Switching Protocols',\n 412: 'Precondition Failed',\n 421: 'Misdirected Request',\n 503: 'Service Unavailable',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 405: 'Method Not Allowed',\n 417: 'Expectation Failed',\n 301: 'Moved Permanently',\n 413: 'Payload Too Large',\n 424: 'Failed Dependency',\n 429: 'Too Many Requests',\n 208: 'Already Reported',\n 300: 'Multiple Choices',\n 402: 'Payment Required',\n 426: 'Upgrade Required',\n 206: 'Partial Content',\n 408: 'Request Timeout',\n 411: 'Length Required',\n 501: 'Not Implemented',\n 504: 'Gateway Timeout',\n 406: 'Not Acceptable',\n 205: 'Reset Content',\n 508: 'Loop Detected',\n 207: 'Multi-Status',\n 304: 'Not Modified',\n 401: 'Unauthorized',\n 414: 'URI Too Long',\n 418: \"I'm a Teapot\",\n 510: 'Not Extended',\n 103: 'Early Hints',\n 400: 'Bad Request',\n 502: 'Bad Gateway',\n 102: 'Processing',\n 204: 'No Content',\n 303: 'See Other',\n 305: 'Use Proxy',\n 403: 'Forbidden',\n 404: 'Not Found',\n 425: 'Too Early',\n 100: 'Continue',\n 202: 'Accepted',\n 226: \"I'm Used\",\n 409: 'Conflict',\n 201: 'Created',\n 423: 'Locked',\n 302: 'Found',\n 410: 'Gone',\n 200: 'OK',\n} as const;\n\nexport type HttpStatusCode = keyof typeof HttpStatusMessage;\n\nexport type HttpStatusMessage =\n (typeof HttpStatusMessage)[keyof typeof HttpStatusMessage];\n","import {\n HttpStatusCode,\n HttpStatusMessage,\n} from '@/gateway/constants/http-code';\n\ninterface ErrorParams {\n message: string;\n code: HttpStatusMessage;\n status?: HttpStatusCode;\n metadata?: Record<string, unknown> | undefined;\n isOperational?: boolean;\n cause?: Error | undefined;\n}\n\n/**\n * Abstract base class for application-level errors with structured error handling.\n *\n * Extends the native Error class to provide machine-readable error codes, HTTP status codes,\n * operational error classification, and optional metadata for better error tracking and client communication.\n *\n * @abstract\n * @extends {Error}\n *\n * @example\n * ```typescript\n * class UserNotFoundError extends ApplicationError {\n * constructor(userId: string) {\n * super({\n * code: HttpStatusMessage['404'],\n * status: 404,\n * isOperational: true,\n * message: `User with id ${userId} not found`,\n * metadata: { userId }\n * });\n * }\n * }\n * ```\n */\nexport abstract class ApplicationError extends Error {\n /** Optional cause (linked error) */\n public readonly cause?: Error | undefined;\n /** Machine-readable error code (e.g. `OTP_LOCKED`, `USER_NOT_FOUND`) */\n public readonly code: HttpStatusMessage;\n /** Operational vs programmer error flag */\n public readonly isOperational: boolean;\n /** Optional structured metadata for debugging or clients */\n public readonly metadata?: Record<string, unknown> | undefined;\n /** HTTP status code intended for response layer */\n public readonly status: HttpStatusCode;\n\n constructor({\n code = HttpStatusMessage['500'],\n isOperational = false,\n status = 500,\n metadata,\n message,\n cause,\n }: ErrorParams) {\n super(message);\n\n this.name = new.target.name;\n this.code = code;\n this.status = status;\n this.isOperational = isOperational;\n this.metadata = metadata;\n this.cause = cause;\n\n Error.captureStackTrace(this, new.target);\n }\n}\n","import { ValueObject } from '@/domain/base/vo';\n\nexport type UnwrapValueObject<T> =\n T extends ValueObject<infer V>\n ? UnwrapValueObject<V>\n : T extends (infer U)[]\n ? UnwrapValueObject<U>[]\n : T extends Map<infer K, infer V>\n ? Map<K, UnwrapValueObject<V>>\n : T extends Set<infer V>\n ? Set<UnwrapValueObject<V>>\n : T extends Date\n ? string\n : T extends object\n ? { [K in keyof T]: UnwrapValueObject<T[K]> }\n : T;\n\nexport function unwrapValueObject<T>(\n input: T,\n seen = new WeakSet(),\n): UnwrapValueObject<T> {\n if (input === null || input === undefined) {\n return input as UnwrapValueObject<T>;\n }\n\n if (typeof input !== 'object') {\n return input as UnwrapValueObject<T>;\n }\n\n if (seen.has(input)) {\n // Prevent circular reference infinite recursion, just return input or throw\n throw new Error('Circular reference detected in ValueObject unwrap');\n }\n\n seen.add(input);\n\n if (Array.isArray(input)) {\n const result = input.map(item => unwrapValueObject(item, seen));\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof ValueObject) {\n const result = unwrapValueObject(input.value, seen);\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof Date) {\n seen.delete(input);\n return input.toISOString() as UnwrapValueObject<T>;\n }\n\n if (input instanceof Map) {\n const result = new Map();\n input.forEach((value, key) => {\n result.set(key, unwrapValueObject(value, seen));\n });\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof Set) {\n const result = new Set(\n Array.from(input.values()).map(v => unwrapValueObject(v, seen)),\n );\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n // generic object\n const result: Record<string, unknown> = {};\n\n for (const key in input) {\n if (Object.hasOwn(input, key)) {\n result[key] = unwrapValueObject((input as any)[key], seen);\n }\n }\n\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n}\n\nexport function ensureObject<T>(input: UnwrapValueObject<T>): object {\n if (input === null || input === undefined) {\n return {};\n }\n if (typeof input === 'object') {\n return input;\n }\n\n // for primitives, wrap inside object with default key (or throw)\n return { value: input };\n}\n"],"mappings":"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","names":["index_exports","__export","AggregateId","ApplicationError","DomainError","EntityValidationError","HttpStatus","HttpStatusMessage","InvalidValueObjectError","ValueObject","deepFreeze","ensureObject","unwrapValueObject","__toCommonJS","getCauseInfo","cause","DomainError","message","code","metadata","__spreadValues","import_es6","deepFreeze","obj","seen","item","key","ValueObject","_ValueObject","props","deepFreeze","vo","other","deepEqual","EntityValidationError","DomainError","message","cause","InvalidValueObjectError","DomainError","message","import_uuid","import_zod","_AggregateId","ValueObject","value","result","InvalidValueObjectError","z","AggregateId","HttpStatus","HttpStatusMessage","ApplicationError","code","HttpStatusMessage","isOperational","status","metadata","message","cause","unwrapValueObject","input","seen","result","item","ValueObject","value","key","v","ensureObject"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/utils/deep-freeze.util.ts","../src/gateway/constants/http-code.ts","../src/utils/errors/application.error.ts","../src/domain/base/vo.ts","../src/utils/unwrap-vo.util.ts","../src/domain/base/domain.error.ts","../src/domain/errors/entity-validation.error.ts","../src/domain/value-objects/aggregate-id.vo.ts","../src/domain/errors/invalid-vo.error.ts","../src/domain/entities/entity.ts","../src/domain/aggregates/aggregate-root.ts","../src/domain/events/domain.event.ts"],"sourcesContent":["export * from './application';\nexport * from './domain/aggregates';\nexport * from './domain/base/domain.error';\nexport * from './domain/base/vo';\nexport * from './domain/entities';\nexport * from './domain/errors/entity-validation.error';\nexport * from './domain/errors/invalid-vo.error';\nexport * from './domain/events';\nexport * from './domain/value-objects/aggregate-id.vo';\nexport * from './gateway/constants/http-code';\nexport * from './utils';\n","/**\n * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.\n *\n * @param obj - The object to be deeply frozen.\n * @param seen - A WeakSet to track already processed objects (for circular references).\n * @returns A deeply frozen version of the input object.\n */\nexport function deepFreeze<T>(\n obj: T,\n seen = new WeakSet<object>(),\n): Readonly<T> {\n // Handle null, undefined, or non-object types\n if (obj == null || (typeof obj !== 'object' && !Array.isArray(obj))) {\n return obj;\n }\n\n // Skip if already frozen\n if (Object.isFrozen(obj)) {\n return obj as Readonly<T>;\n }\n\n // Handle circular references\n if (seen.has(obj as object)) {\n return obj as Readonly<T>;\n }\n\n seen.add(obj as object);\n\n // Handle arrays explicitly\n if (Array.isArray(obj)) {\n obj.forEach(item => deepFreeze(item, seen));\n } else {\n // Handle plain objects\n for (const key in obj) {\n if (Object.hasOwn(obj, key)) {\n deepFreeze((obj as Record<string, unknown>)[key], seen);\n }\n }\n }\n\n return Object.freeze(obj) as Readonly<T>;\n}\n","/**\n * HTTP status code catalog.\n *\n * This object provides a typed, immutable map of standard HTTP status names\n * to their numeric codes. Designed for server-side frameworks such as Fastify.\n *\n * - All identifiers use clear, canonical semantic names.\n * - Values are numeric status codes.\n * - Frozen to prevent runtime mutation.\n * - Exporting `HttpStatus` ensures type-safe usage across the codebase.\n * Usage:\n * ```ts\n * import { HttpStatus } from 'path-to-this-file';\n *\n * function handleRequest() {\n * return {\n * statusCode: HttpStatus.OK,\n * body: 'Success',\n * };\n * }\n * ```\n */\nexport const HttpStatus = Object.freeze({\n REQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n NETWORK_AUTHENTICATION_REQUIRED: 511,\n NON_AUTHORITATIVE_INFORMATION: 203,\n PROXY_AUTHENTICATION_REQUIRED: 407,\n\n UNAVAILABLE_FOR_LEGAL_REASONS: 451,\n HTTP_VERSION_NOT_SUPPORTED: 505,\n BANDWIDTH_LIMIT_EXCEEDED: 509,\n VARIANT_ALSO_NEGOTIATES: 506,\n UNSUPPORTED_MEDIA_TYPE: 415,\n RANGE_NOT_SATISFIABLE: 416,\n PRECONDITION_REQUIRED: 428,\n INTERNAL_SERVER_ERROR: 500,\n UNPROCESSABLE_ENTITY: 422,\n INSUFFICIENT_STORAGE: 507,\n\n SWITCHING_PROTOCOLS: 101,\n PRECONDITION_FAILED: 412,\n MISDIRECTED_REQUEST: 421,\n SERVICE_UNAVAILABLE: 503,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n METHOD_NOT_ALLOWED: 405,\n EXPECTATION_FAILED: 417,\n\n MOVED_PERMANENTLY: 301,\n PAYLOAD_TOO_LARGE: 413,\n FAILED_DEPENDENCY: 424,\n TOO_MANY_REQUESTS: 429,\n ALREADY_REPORTED: 208,\n MULTIPLE_CHOICES: 300,\n PAYMENT_REQUIRED: 402,\n UPGRADE_REQUIRED: 426,\n PARTIAL_CONTENT: 206,\n REQUEST_TIMEOUT: 408,\n LENGTH_REQUIRED: 411,\n NOT_IMPLEMENTED: 501,\n GATEWAY_TIMEOUT: 504,\n NOT_ACCEPTABLE: 406,\n RESET_CONTENT: 205,\n LOOP_DETECTED: 508,\n MULTI_STATUS: 207,\n NOT_MODIFIED: 304,\n UNAUTHORIZED: 401,\n URI_TOO_LONG: 414,\n NOT_EXTENDED: 510,\n EARLY_HINTS: 103,\n BAD_REQUEST: 400,\n IM_A_TEAPOT: 418,\n BAD_GATEWAY: 502,\n PROCESSING: 102,\n NO_CONTENT: 204,\n SEE_OTHER: 303,\n USE_PROXY: 305,\n\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n TOO_EARLY: 425,\n CONTINUE: 100,\n ACCEPTED: 202,\n CONFLICT: 409,\n CREATED: 201,\n IM_USED: 226,\n LOCKED: 423,\n FOUND: 302,\n GONE: 410,\n OK: 200,\n} as const);\n\n/**\n * HTTP status messages mapped by numeric code.\n * Use for sending descriptive text in responses or logging.\n */\nexport const HttpStatusMessage = {\n 431: 'Request Header Fields Too Large',\n 511: 'Network Authentication Required',\n 203: 'Non-Authoritative Information',\n 407: 'Proxy Authentication Required',\n 451: 'Unavailable For Legal Reasons',\n 505: 'HTTP Version Not Supported',\n 509: 'Bandwidth Limit Exceeded',\n 506: 'Variant Also Negotiates',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 428: 'Precondition Required',\n 500: 'Internal Server Error',\n 422: 'Unprocessable Entity',\n 507: 'Insufficient Storage',\n 101: 'Switching Protocols',\n 412: 'Precondition Failed',\n 421: 'Misdirected Request',\n 503: 'Service Unavailable',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 405: 'Method Not Allowed',\n 417: 'Expectation Failed',\n 301: 'Moved Permanently',\n 413: 'Payload Too Large',\n 424: 'Failed Dependency',\n 429: 'Too Many Requests',\n 208: 'Already Reported',\n 300: 'Multiple Choices',\n 402: 'Payment Required',\n 426: 'Upgrade Required',\n 206: 'Partial Content',\n 408: 'Request Timeout',\n 411: 'Length Required',\n 501: 'Not Implemented',\n 504: 'Gateway Timeout',\n 406: 'Not Acceptable',\n 205: 'Reset Content',\n 508: 'Loop Detected',\n 207: 'Multi-Status',\n 304: 'Not Modified',\n 401: 'Unauthorized',\n 414: 'URI Too Long',\n 418: \"I'm a Teapot\",\n 510: 'Not Extended',\n 103: 'Early Hints',\n 400: 'Bad Request',\n 502: 'Bad Gateway',\n 102: 'Processing',\n 204: 'No Content',\n 303: 'See Other',\n 305: 'Use Proxy',\n 403: 'Forbidden',\n 404: 'Not Found',\n 425: 'Too Early',\n 100: 'Continue',\n 202: 'Accepted',\n 226: \"I'm Used\",\n 409: 'Conflict',\n 201: 'Created',\n 423: 'Locked',\n 302: 'Found',\n 410: 'Gone',\n 200: 'OK',\n} as const;\n\nexport type HttpStatusCode = keyof typeof HttpStatusMessage;\n\nexport type HttpStatusMessage =\n (typeof HttpStatusMessage)[keyof typeof HttpStatusMessage];\n","import {\n HttpStatusCode,\n HttpStatusMessage,\n} from '@/gateway/constants/http-code';\n\ninterface ErrorParams {\n message: string;\n code: HttpStatusMessage;\n status?: HttpStatusCode;\n metadata?: Record<string, unknown> | undefined;\n isOperational?: boolean;\n cause?: Error | undefined;\n}\n\n/**\n * Abstract base class for application-level errors with structured error handling.\n *\n * Extends the native Error class to provide machine-readable error codes, HTTP status codes,\n * operational error classification, and optional metadata for better error tracking and client communication.\n *\n * @abstract\n * @extends {Error}\n *\n * @example\n * ```typescript\n * class UserNotFoundError extends ApplicationError {\n * constructor(userId: string) {\n * super({\n * code: HttpStatusMessage['404'],\n * status: 404,\n * isOperational: true,\n * message: `User with id ${userId} not found`,\n * metadata: { userId }\n * });\n * }\n * }\n * ```\n */\nexport abstract class ApplicationError extends Error {\n /** Optional cause (linked error) */\n public readonly cause?: Error | undefined;\n /** Machine-readable error code (e.g. `OTP_LOCKED`, `USER_NOT_FOUND`) */\n public readonly code: HttpStatusMessage;\n /** Operational vs programmer error flag */\n public readonly isOperational: boolean;\n /** Optional structured metadata for debugging or clients */\n public readonly metadata?: Record<string, unknown> | undefined;\n /** HTTP status code intended for response layer */\n public readonly status: HttpStatusCode;\n\n constructor({\n code = HttpStatusMessage['500'],\n isOperational = false,\n status = 500,\n metadata,\n message,\n cause,\n }: ErrorParams) {\n super(message);\n\n this.name = new.target.name;\n this.code = code;\n this.status = status;\n this.isOperational = isOperational;\n this.metadata = metadata;\n this.cause = cause;\n\n Error.captureStackTrace(this, new.target);\n }\n}\n","import deepEqual from 'fast-deep-equal/es6';\n\nimport { deepFreeze } from '@/utils/deep-freeze.util';\n\nexport abstract class ValueObject<T> {\n get value(): T {\n return this.props;\n }\n\n protected readonly props: Readonly<T>;\n\n protected constructor(props: T) {\n this.validate(props);\n this.props = deepFreeze(props);\n }\n\n /**\n * Type guard to check if an unknown object is an instance of ValueObject.\n * This is useful for runtime type checking.\n *\n * @param vo The object to check.\n * @returns True if the object is a ValueObject instance, false otherwise.\n */\n public static is(vo: unknown): vo is ValueObject<unknown> {\n return vo instanceof ValueObject;\n }\n\n /**\n * Deep equality comparison of ValueObjects\n */\n public equals(other?: ValueObject<T>): boolean {\n if (\n !other ||\n !(other instanceof (this.constructor as typeof ValueObject))\n ) {\n return false;\n }\n\n return deepEqual(this.props, other.props);\n }\n\n /**\n * Validates the value object props\n * @throws InvalidValueObjectError if validation fails\n */\n protected abstract validate(props: T): void;\n}\n","import { ValueObject } from '@/domain/base/vo';\n\nexport type UnwrapValueObject<T> =\n T extends ValueObject<infer V>\n ? UnwrapValueObject<V>\n : T extends (infer U)[]\n ? UnwrapValueObject<U>[]\n : T extends Map<infer K, infer V>\n ? Map<K, UnwrapValueObject<V>>\n : T extends Set<infer V>\n ? Set<UnwrapValueObject<V>>\n : T extends Date\n ? string\n : T extends object\n ? { [K in keyof T]: UnwrapValueObject<T[K]> }\n : T;\n\nexport function unwrapValueObject<T>(\n input: T,\n seen = new WeakSet(),\n): UnwrapValueObject<T> {\n if (input === null || input === undefined) {\n return input as UnwrapValueObject<T>;\n }\n\n if (typeof input !== 'object') {\n return input as UnwrapValueObject<T>;\n }\n\n if (seen.has(input)) {\n // Prevent circular reference infinite recursion, just return input or throw\n throw new Error('Circular reference detected in ValueObject unwrap');\n }\n\n seen.add(input);\n\n if (Array.isArray(input)) {\n const result = input.map(item => unwrapValueObject(item, seen));\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof ValueObject) {\n const result = unwrapValueObject(input.value, seen);\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof Date) {\n seen.delete(input);\n return input.toISOString() as UnwrapValueObject<T>;\n }\n\n if (input instanceof Map) {\n const result = new Map();\n input.forEach((value, key) => {\n result.set(key, unwrapValueObject(value, seen));\n });\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof Set) {\n const result = new Set(\n Array.from(input.values()).map(v => unwrapValueObject(v, seen)),\n );\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n // generic object\n const result: Record<string, unknown> = {};\n\n for (const key in input) {\n if (Object.hasOwn(input, key)) {\n result[key] = unwrapValueObject((input as any)[key], seen);\n }\n }\n\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n}\n\nexport function ensureObject<T>(input: UnwrapValueObject<T>): object {\n if (input === null || input === undefined) {\n return {};\n }\n if (typeof input === 'object') {\n return input;\n }\n\n // for primitives, wrap inside object with default key (or throw)\n return { value: input };\n}\n","export interface DomainErrorMetadata {\n cause?: { name: string; message: string; stack?: string };\n [key: string]: unknown;\n}\n\nconst getCauseInfo = (cause: Error | undefined) => {\n // 1. Handle Error objects specifically\n if (cause instanceof Error) {\n return {\n cause: {\n message: cause.message,\n stack: cause.stack,\n name: cause.name,\n },\n };\n }\n\n // 2. Handle other existing values\n if (cause) {\n return { cause };\n }\n\n // 3. Default to empty\n return {};\n};\n\n/**\n * Base class for all Domain Errors in the application.\n *\n * This class ensures:\n * 1. Serializable and structured for logs or API responses.\n * 2. Identifiable via stable error codes (not just class names).\n * 3. Contextual with optional structured metadata.\n * 4. Supports error chaining (cause) and stack trace preservation.\n *\n * @example\n * export class InsufficientFundsError extends DomainError {\n * constructor(accountId: string, currentBalance: number) {\n * super(\n * `Account ${accountId} has insufficient funds.`,\n * 'INSUFFICIENT_FUNDS',\n * { accountId, currentBalance }\n * );\n * }\n * }\n */\nexport abstract class DomainError extends Error {\n /** Stable, machine-readable error code */\n public readonly code: string;\n /** Structured, immutable domain metadata */\n public readonly metadata: Readonly<DomainErrorMetadata>;\n\n /**\n * @param message - Human-readable error message\n * @param code - Stable error code\n * @param metadata - Domain-specific structured data; optional `cause` can be included\n */\n protected constructor(\n message: string,\n code: string,\n metadata: DomainErrorMetadata = {},\n ) {\n super(message, { ...getCauseInfo(metadata.cause) });\n\n // Restore prototype chain for proper `instanceof` checks\n Object.setPrototypeOf(this, new.target.prototype);\n\n this.name = new.target.name;\n this.code = code;\n this.metadata = Object.freeze({ ...metadata });\n }\n}\n","import { DomainError } from '../base/domain.error';\n\n/**\n * Custom error class for entity validation failures.\n */\nexport class EntityValidationError extends DomainError {\n constructor(message: string, cause?: Error) {\n super(message, 'ENTITY_VALIDATION_ERROR', { cause });\n }\n}\n","import { v4 } from 'uuid';\nimport z from 'zod';\n\nimport { InvalidValueObjectError } from '../errors/invalid-vo.error';\nimport { ValueObject } from '../base/vo';\n\n/**\n * AggregateId is a ValueObject that represents a unique identifier for an aggregate.\n */\nexport class AggregateId extends ValueObject<string> {\n /**\n * The schema for the AggregateId\n */\n private static readonly schema = z.uuid();\n\n /**\n * Get the UUID of the AggregateId\n * @returns The UUID of the AggregateId\n */\n public get uuid(): string {\n return this.value;\n }\n\n /**\n * Create a new AggregateId\n * @param value The value to create the AggregateId from\n * @returns The new AggregateId\n */\n public static create(value: string): AggregateId {\n return new AggregateId(value);\n }\n\n /**\n * Create a new AggregateId with a random UUID v4\n */\n public static generate(): AggregateId {\n return new AggregateId(v4());\n }\n\n /**\n * Check if the AggregateId is empty\n * @returns True if the AggregateId is empty, false otherwise\n */\n public isEmpty(): boolean {\n return !this.value;\n }\n\n /**\n * Convert the AggregateId to a string\n * @returns The string representation of the AggregateId\n */\n public toString(): string {\n return this.value;\n }\n\n /**\n * Validate the AggregateId\n * @param value The value to validate\n * @throws InvalidValueObjectException if the value is invalid\n */\n protected validate(value: string): void {\n const result = AggregateId.schema.safeParse(value);\n\n if (!result.success) {\n throw new InvalidValueObjectError(\n `Invalid AggregateId: ${result.error.message}`,\n );\n }\n }\n}\n","import { DomainError } from '../base/domain.error';\n\nexport class InvalidValueObjectError extends DomainError {\n constructor(message: string) {\n super(message, 'INVALID_VALUE_OBJECT');\n }\n}\n","import { ensureObject, UnwrapValueObject, unwrapValueObject } from '@/utils';\n\nimport { EntityValidationError } from '../errors/entity-validation.error';\nimport { AggregateId } from '../value-objects/aggregate-id.vo';\n\nexport interface EntityBaseInterface {\n id: AggregateId;\n equals: (entity: unknown) => boolean;\n}\n\n/**\n * Base properties common to all entities, including ID and timestamps.\n */\nexport interface BaseEntityProps {\n /** Unique identifier for the entity */\n id?: AggregateId;\n /** Date when the entity was created */\n createdAt: Date;\n}\n\n/**\n * Interface for constructing an entity with optional timestamps.\n * @template Props - The specific props type for the entity\n */\nexport type CreateEntityProps<T> = BaseEntityProps & {\n props: T;\n};\n\n/**\n * Abstract base class for domain entities in a Domain-Driven Design (DDD) context.\n * Provides common functionality for entity identification, equality comparison,\n * immutability, and validation. Entities extending this class must implement\n * the `validate` method to enforce domain invariants.\n * @template EntityProps - The specific props type for the entity\n */\nexport abstract class Entity<EntityProps> {\n /**\n * Returns the creation timestamp.\n * A new Date instance is returned to preserve immutability.\n *\n * @returns {Date} The creation date of the entity.\n */\n get createdAt(): Date {\n return new Date(this.#createdAt);\n }\n\n /**\n * Gets the entity's unique identifier.\n * @returns The entity's ID\n */\n get id(): AggregateId {\n return this.#id;\n }\n\n public get metadata() {\n return Object.freeze({\n createdAt: this.#createdAt.toISOString(),\n id: this.#id.uuid,\n });\n }\n\n /**\n * Returns an immutable shallow copy of the entity's properties.\n *\n * @returns {Readonly<EntityProps>} The entity domain properties.\n */\n get props(): Readonly<EntityProps> {\n return this.#props;\n }\n\n /** Private creation timestamp */\n #createdAt: Date;\n /** Private unique identifier for the entity */\n #id: AggregateId;\n /** Private entity-specific properties */\n #props: Readonly<EntityProps>;\n\n /**\n * Constructs an entity with the provided properties and timestamps.\n * Ensures immutability by cloning props and validates the entity.\n * @param params - Entity creation parameters\n * @throws EntityValidationError if the ID is empty or validation fails\n */\n protected constructor({\n createdAt,\n props,\n id,\n }: CreateEntityProps<EntityProps>) {\n if (!id) {\n throw new EntityValidationError('Entity ID cannot be empty');\n }\n\n this.#id = id ?? AggregateId.generate();\n this.#props = Object.freeze(props);\n const now = new Date();\n this.#createdAt = createdAt ? new Date(createdAt) : now;\n }\n\n /**\n * Checks if the provided value is an instance of Entity.\n * @param entity - The value to check\n * @returns True if the value is an Entity instance\n */\n static isEntity(entity: unknown): entity is EntityBaseInterface {\n return (\n typeof entity === 'object' &&\n entity !== null &&\n 'id' in entity &&\n typeof (entity as any).equals === 'function'\n );\n }\n\n /**\n * Compares this entity with another to determine if they are the same.\n * Equality is based on the entity ID.\n * @param other - The entity to compare with\n * @returns True if the entities have the same ID\n */\n public equals(other?: Entity<EntityProps>): boolean {\n if (!other || !Entity.isEntity(other)) {\n return false;\n }\n\n return this.#id.equals(other.#id);\n }\n\n /**\n * Returns a frozen copy of the entity's properties, including base properties.\n * Ensures immutability by returning a new object.\n * @returns A frozen copy of the entity's properties\n */\n public getPropsCopy(): Readonly<EntityProps> {\n return Object.freeze(this.#props);\n }\n\n /**\n * Determines if the entity is transient, i.e., it has not been persisted yet.\n * By convention, an entity is considered transient if it lacks a valid identifier.\n * This can be useful when performing logic that depends on persistence state,\n * such as conditional inserts or validations that only apply to new entities.\n *\n * @returns True if the entity is transient (not persisted), otherwise false.\n */\n public isPersisted(): boolean {\n return this.#id.isEmpty();\n }\n\n public toJSON(): Record<string, unknown> {\n return this.toObject();\n }\n\n public toObject(): Readonly<\n UnwrapValueObject<EntityProps> & { createdAt: string; id: string }\n > {\n const props = unwrapValueObject(this.getPropsCopy());\n const safeProps = ensureObject(props);\n return Object.freeze({\n ...this.metadata,\n ...safeProps,\n }) as Readonly<\n UnwrapValueObject<EntityProps> & { createdAt: string; id: string }\n >;\n }\n\n /**\n * Validates the entity's state to enforce domain invariants.\n * Must be implemented by subclasses to define specific validation rules.\n * @throws EntityValidationError if validation fails\n */\n public abstract validate(): void;\n}\n","import { AggregateId } from '../value-objects/aggregate-id.vo';\nimport { Entity } from '../entities/entity';\nimport { DomainEvent } from '../events';\n\n/**\n * Interface for AggregateRoot to ensure type safety and extensibility.\n */\nexport interface AggregateRootInterface {\n readonly id: AggregateId;\n readonly domainEvents: readonly DomainEvent[];\n /**\n * Validates the aggregate's invariants.\n * @throws {EntityValidationError} If validation fails.\n */\n validate: () => void;\n /**\n * Adds a domain event to the aggregate.\n * @param event The domain event to add.\n */\n addEvent: (event: DomainEvent) => void;\n\n /**\n * Retrieves and clears all domain events recorded by this aggregate.\n *\n * Domain events represent facts that occurred as a result of state changes\n * within the aggregate. This method transfers ownership of those events\n * to the application layer for further processing (e.g. publishing).\n *\n * Calling this method has the side effect of clearing the aggregate's\n * internal event collection to prevent duplicate handling.\n *\n * This method is intended to be invoked by application services\n * after the aggregate has been successfully persisted.\n *\n * @returns A read-only list of domain events raised by this aggregate.\n */\n pullDomainEvents: () => readonly DomainEvent[];\n}\n\n/**\n * Base class for aggregate roots in DDD, encapsulating domain events and validation.\n * @template EntityProps The type of the entity's properties.\n */\nexport abstract class AggregateRoot<EntityProps>\n extends Entity<EntityProps>\n implements AggregateRootInterface\n{\n /**\n * Gets a read-only copy of the domain events.\n */\n get domainEvents(): readonly DomainEvent[] {\n return [...this._domainEvents];\n }\n\n /**\n * Internal list of domain events.\n */\n private readonly _domainEvents: DomainEvent[] = [];\n\n /**\n * Adds a domain event to the aggregate after validating invariants.\n * @param domainEvent The domain event to add.\n * @throws {EntityValidationError} If invariants are not met.\n */\n addEvent(domainEvent: DomainEvent): void {\n this.validate(); // Ensure invariants before adding events\n this._domainEvents.push(domainEvent);\n }\n\n public pullDomainEvents(): readonly DomainEvent[] {\n const events = [...this._domainEvents];\n this._domainEvents.length = 0;\n return events;\n }\n\n /**\n * Validates the entity's invariants.\n * @throws {EntityValidationError} If validation fails.\n */\n abstract validate(): void;\n}\n","type Primitive = boolean | number | string | null;\n\ntype Serializable =\n | Primitive\n | Serializable[]\n | { [key: string]: Serializable };\n\nexport type DomainEventPayload = Record<string, Serializable>;\n\ntype DomainEventProps<T> = {\n id: string;\n aggregateId: string;\n schemaVersion: number;\n occurredAt: number;\n payload: T;\n};\n\n// Abstract base class for domain events\nexport abstract class DomainEvent<\n T extends DomainEventPayload = DomainEventPayload,\n> {\n public abstract readonly eventName: string;\n\n public readonly id: string;\n public readonly aggregateId: string;\n public readonly schemaVersion: number;\n public readonly occurredAt: number;\n public readonly payload: Readonly<T>;\n\n protected constructor(props: DomainEventProps<T>) {\n this.id = props.id;\n this.aggregateId = props.aggregateId;\n this.schemaVersion = props.schemaVersion;\n this.occurredAt = props.occurredAt;\n this.payload = Object.freeze(props.payload);\n }\n\n public toPrimitives() {\n return {\n schemaVersion: this.schemaVersion,\n aggregateId: this.aggregateId,\n occurredAt: this.occurredAt,\n eventName: this.eventName,\n payload: this.payload,\n id: this.id,\n };\n }\n}\n"],"mappings":"uoCAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,EAAA,kBAAAC,EAAA,qBAAAC,EAAA,gBAAAC,EAAA,gBAAAC,EAAA,WAAAC,EAAA,0BAAAC,EAAA,eAAAC,EAAA,sBAAAC,EAAA,4BAAAC,EAAA,gBAAAC,EAAA,eAAAC,EAAA,iBAAAC,EAAA,sBAAAC,IAAA,eAAAC,EAAAhB,GCOO,SAASiB,EACdC,EACAC,EAAO,IAAI,QACE,CAYb,GAVID,GAAO,MAAS,OAAOA,GAAQ,UAAY,CAAC,MAAM,QAAQA,CAAG,GAK7D,OAAO,SAASA,CAAG,GAKnBC,EAAK,IAAID,CAAa,EACxB,OAAOA,EAMT,GAHAC,EAAK,IAAID,CAAa,EAGlB,MAAM,QAAQA,CAAG,EACnBA,EAAI,QAAQE,GAAQH,EAAWG,EAAMD,CAAI,CAAC,MAG1C,SAAWE,KAAOH,EACZ,OAAO,OAAOA,EAAKG,CAAG,GACxBJ,EAAYC,EAAgCG,CAAG,EAAGF,CAAI,EAK5D,OAAO,OAAO,OAAOD,CAAG,CAC1B,CCnBO,IAAMI,EAAa,OAAO,OAAO,CACtC,gCAAiC,IACjC,gCAAiC,IACjC,8BAA+B,IAC/B,8BAA+B,IAE/B,8BAA+B,IAC/B,2BAA4B,IAC5B,yBAA0B,IAC1B,wBAAyB,IACzB,uBAAwB,IACxB,sBAAuB,IACvB,sBAAuB,IACvB,sBAAuB,IACvB,qBAAsB,IACtB,qBAAsB,IAEtB,oBAAqB,IACrB,oBAAqB,IACrB,oBAAqB,IACrB,oBAAqB,IACrB,mBAAoB,IACpB,mBAAoB,IACpB,mBAAoB,IACpB,mBAAoB,IAEpB,kBAAmB,IACnB,kBAAmB,IACnB,kBAAmB,IACnB,kBAAmB,IACnB,iBAAkB,IAClB,iBAAkB,IAClB,iBAAkB,IAClB,iBAAkB,IAClB,gBAAiB,IACjB,gBAAiB,IACjB,gBAAiB,IACjB,gBAAiB,IACjB,gBAAiB,IACjB,eAAgB,IAChB,cAAe,IACf,cAAe,IACf,aAAc,IACd,aAAc,IACd,aAAc,IACd,aAAc,IACd,aAAc,IACd,YAAa,IACb,YAAa,IACb,YAAa,IACb,YAAa,IACb,WAAY,IACZ,WAAY,IACZ,UAAW,IACX,UAAW,IAEX,UAAW,IACX,UAAW,IACX,UAAW,IACX,SAAU,IACV,SAAU,IACV,SAAU,IACV,QAAS,IACT,QAAS,IACT,OAAQ,IACR,MAAO,IACP,KAAM,IACN,GAAI,GACN,CAAU,EAMGC,EAAoB,CAC/B,IAAK,kCACL,IAAK,kCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,6BACL,IAAK,2BACL,IAAK,0BACL,IAAK,yBACL,IAAK,wBACL,IAAK,wBACL,IAAK,wBACL,IAAK,uBACL,IAAK,uBACL,IAAK,sBACL,IAAK,sBACL,IAAK,sBACL,IAAK,sBACL,IAAK,qBACL,IAAK,qBACL,IAAK,qBACL,IAAK,qBACL,IAAK,oBACL,IAAK,oBACL,IAAK,oBACL,IAAK,oBACL,IAAK,mBACL,IAAK,mBACL,IAAK,mBACL,IAAK,mBACL,IAAK,kBACL,IAAK,kBACL,IAAK,kBACL,IAAK,kBACL,IAAK,kBACL,IAAK,iBACL,IAAK,gBACL,IAAK,gBACL,IAAK,eACL,IAAK,eACL,IAAK,eACL,IAAK,eACL,IAAK,eACL,IAAK,eACL,IAAK,cACL,IAAK,cACL,IAAK,cACL,IAAK,aACL,IAAK,aACL,IAAK,YACL,IAAK,YACL,IAAK,YACL,IAAK,YACL,IAAK,YACL,IAAK,WACL,IAAK,WACL,IAAK,WACL,IAAK,WACL,IAAK,UACL,IAAK,SACL,IAAK,QACL,IAAK,OACL,IAAK,IACP,EC1HO,IAAeC,EAAf,cAAwC,KAAM,CAYnD,YAAY,CACV,KAAAC,EAAOC,EAAkB,GAAK,EAC9B,cAAAC,EAAgB,GAChB,OAAAC,EAAS,IACT,SAAAC,EACA,QAAAC,EACA,MAAAC,CACF,EAAgB,CACd,MAAMD,CAAO,EAEb,KAAK,KAAO,WAAW,KACvB,KAAK,KAAOL,EACZ,KAAK,OAASG,EACd,KAAK,cAAgBD,EACrB,KAAK,SAAWE,EAChB,KAAK,MAAQE,EAEb,MAAM,kBAAkB,KAAM,UAAU,CAC1C,CACF,ECrEA,IAAAC,EAAsB,kCAIf,IAAeC,EAAf,MAAeC,CAAe,CACnC,IAAI,OAAW,CACb,OAAO,KAAK,KACd,CAIU,YAAYC,EAAU,CAC9B,KAAK,SAASA,CAAK,EACnB,KAAK,MAAQC,EAAWD,CAAK,CAC/B,CASA,OAAc,GAAGE,EAAyC,CACxD,OAAOA,aAAcH,CACvB,CAKO,OAAOI,EAAiC,CAC7C,MACE,CAACA,GACD,EAAEA,aAAkB,KAAK,aAElB,MAGF,EAAAC,SAAU,KAAK,MAAOD,EAAM,KAAK,CAC1C,CAOF,EC7BO,SAASE,EACdC,EACAC,EAAO,IAAI,QACW,CAKtB,GAJID,GAAU,MAIV,OAAOA,GAAU,SACnB,OAAOA,EAGT,GAAIC,EAAK,IAAID,CAAK,EAEhB,MAAM,IAAI,MAAM,mDAAmD,EAKrE,GAFAC,EAAK,IAAID,CAAK,EAEV,MAAM,QAAQA,CAAK,EAAG,CACxB,IAAME,EAASF,EAAM,IAAIG,GAAQJ,EAAkBI,EAAMF,CAAI,CAAC,EAC9D,OAAAA,EAAK,OAAOD,CAAK,EACVE,CACT,CAEA,GAAIF,aAAiBI,EAAa,CAChC,IAAMF,EAASH,EAAkBC,EAAM,MAAOC,CAAI,EAClD,OAAAA,EAAK,OAAOD,CAAK,EACVE,CACT,CAEA,GAAIF,aAAiB,KACnB,OAAAC,EAAK,OAAOD,CAAK,EACVA,EAAM,YAAY,EAG3B,GAAIA,aAAiB,IAAK,CACxB,IAAME,EAAS,IAAI,IACnB,OAAAF,EAAM,QAAQ,CAACK,EAAOC,IAAQ,CAC5BJ,EAAO,IAAII,EAAKP,EAAkBM,EAAOJ,CAAI,CAAC,CAChD,CAAC,EACDA,EAAK,OAAOD,CAAK,EACVE,CACT,CAEA,GAAIF,aAAiB,IAAK,CACxB,IAAME,EAAS,IAAI,IACjB,MAAM,KAAKF,EAAM,OAAO,CAAC,EAAE,IAAIO,GAAKR,EAAkBQ,EAAGN,CAAI,CAAC,CAChE,EACA,OAAAA,EAAK,OAAOD,CAAK,EACVE,CACT,CAGA,IAAMA,EAAkC,CAAC,EAEzC,QAAWI,KAAON,EACZ,OAAO,OAAOA,EAAOM,CAAG,IAC1BJ,EAAOI,CAAG,EAAIP,EAAmBC,EAAcM,CAAG,EAAGL,CAAI,GAI7D,OAAAA,EAAK,OAAOD,CAAK,EACVE,CACT,CAEO,SAASM,EAAgBR,EAAqC,CACnE,OAAIA,GAAU,KACL,CAAC,EAEN,OAAOA,GAAU,SACZA,EAIF,CAAE,MAAOA,CAAM,CACxB,CCxFA,IAAMS,EAAgBC,GAEhBA,aAAiB,MACZ,CACL,MAAO,CACL,QAASA,EAAM,QACf,MAAOA,EAAM,MACb,KAAMA,EAAM,IACd,CACF,EAIEA,EACK,CAAE,MAAAA,CAAM,EAIV,CAAC,EAuBYC,EAAf,cAAmC,KAAM,CAWpC,YACRC,EACAC,EACAC,EAAgC,CAAC,EACjC,CACA,MAAMF,EAASG,EAAA,GAAKN,EAAaK,EAAS,KAAK,EAAG,EAGlD,OAAO,eAAe,KAAM,WAAW,SAAS,EAEhD,KAAK,KAAO,WAAW,KACvB,KAAK,KAAOD,EACZ,KAAK,SAAW,OAAO,OAAOE,EAAA,GAAKD,EAAU,CAC/C,CACF,EClEO,IAAME,EAAN,cAAoCC,CAAY,CACrD,YAAYC,EAAiBC,EAAe,CAC1C,MAAMD,EAAS,0BAA2B,CAAE,MAAAC,CAAM,CAAC,CACrD,CACF,ECTA,IAAAC,EAAmB,gBACnBC,EAAc,kBCCP,IAAMC,EAAN,cAAsCC,CAAY,CACvD,YAAYC,EAAiB,CAC3B,MAAMA,EAAS,sBAAsB,CACvC,CACF,EDGO,IAAMC,EAAN,MAAMA,UAAoBC,CAAoB,CAUnD,IAAW,MAAe,CACxB,OAAO,KAAK,KACd,CAOA,OAAc,OAAOC,EAA4B,CAC/C,OAAO,IAAIF,EAAYE,CAAK,CAC9B,CAKA,OAAc,UAAwB,CACpC,OAAO,IAAIF,KAAY,MAAG,CAAC,CAC7B,CAMO,SAAmB,CACxB,MAAO,CAAC,KAAK,KACf,CAMO,UAAmB,CACxB,OAAO,KAAK,KACd,CAOU,SAASE,EAAqB,CACtC,IAAMC,EAASH,EAAY,OAAO,UAAUE,CAAK,EAEjD,GAAI,CAACC,EAAO,QACV,MAAM,IAAIC,EACR,wBAAwBD,EAAO,MAAM,OAAO,EAC9C,CAEJ,CACF,EA5DaH,EAIa,OAAS,EAAAK,QAAE,KAAK,EAJnC,IAAMC,EAANN,EETP,IAAAO,EAAAC,EAAAC,EAmCsBC,EAAf,MAAeA,CAAoB,CAgD9B,YAAY,CACpB,UAAAC,EACA,MAAAC,EACA,GAAAC,CACF,EAAmC,CAhBnCC,EAAA,KAAAP,GAEAO,EAAA,KAAAN,GAEAM,EAAA,KAAAL,GAaE,GAAI,CAACI,EACH,MAAM,IAAIE,EAAsB,2BAA2B,EAG7DC,EAAA,KAAKR,EAAMK,GAAA,KAAAA,EAAMI,EAAY,SAAS,GACtCD,EAAA,KAAKP,EAAS,OAAO,OAAOG,CAAK,GAEjCI,EAAA,KAAKT,EAAaI,EAAY,IAAI,KAAKA,CAAS,EADpC,IAAI,KAElB,CAtDA,IAAI,WAAkB,CACpB,OAAO,IAAI,KAAKO,EAAA,KAAKX,EAAU,CACjC,CAMA,IAAI,IAAkB,CACpB,OAAOW,EAAA,KAAKV,EACd,CAEA,IAAW,UAAW,CACpB,OAAO,OAAO,OAAO,CACnB,UAAWU,EAAA,KAAKX,GAAW,YAAY,EACvC,GAAIW,EAAA,KAAKV,GAAI,IACf,CAAC,CACH,CAOA,IAAI,OAA+B,CACjC,OAAOU,EAAA,KAAKT,EACd,CAmCA,OAAO,SAASU,EAAgD,CAC9D,OACE,OAAOA,GAAW,UAClBA,IAAW,MACX,OAAQA,GACR,OAAQA,EAAe,QAAW,UAEtC,CAQO,OAAOC,EAAsC,CAClD,MAAI,CAACA,GAAS,CAACV,EAAO,SAASU,CAAK,EAC3B,GAGFF,EAAA,KAAKV,GAAI,OAAOU,EAAAE,EAAMZ,EAAG,CAClC,CAOO,cAAsC,CAC3C,OAAO,OAAO,OAAOU,EAAA,KAAKT,EAAM,CAClC,CAUO,aAAuB,CAC5B,OAAOS,EAAA,KAAKV,GAAI,QAAQ,CAC1B,CAEO,QAAkC,CACvC,OAAO,KAAK,SAAS,CACvB,CAEO,UAEL,CACA,IAAMI,EAAQS,EAAkB,KAAK,aAAa,CAAC,EAC7CC,EAAYC,EAAaX,CAAK,EACpC,OAAO,OAAO,OAAOY,IAAA,GAChB,KAAK,UACLF,EACJ,CAGH,CAQF,EAnGEf,EAAA,YAEAC,EAAA,YAEAC,EAAA,YAxCK,IAAegB,EAAff,ECQA,IAAegB,EAAf,cACGC,CAEV,CAHO,kCAcL,KAAiB,cAA+B,CAAC,EAPjD,IAAI,cAAuC,CACzC,MAAO,CAAC,GAAG,KAAK,aAAa,CAC/B,CAYA,SAASC,EAAgC,CACvC,KAAK,SAAS,EACd,KAAK,cAAc,KAAKA,CAAW,CACrC,CAEO,kBAA2C,CAChD,IAAMC,EAAS,CAAC,GAAG,KAAK,aAAa,EACrC,YAAK,cAAc,OAAS,EACrBA,CACT,CAOF,EC9DO,IAAeC,EAAf,KAEL,CASU,YAAYC,EAA4B,CAChD,KAAK,GAAKA,EAAM,GAChB,KAAK,YAAcA,EAAM,YACzB,KAAK,cAAgBA,EAAM,cAC3B,KAAK,WAAaA,EAAM,WACxB,KAAK,QAAU,OAAO,OAAOA,EAAM,OAAO,CAC5C,CAEO,cAAe,CACpB,MAAO,CACL,cAAe,KAAK,cACpB,YAAa,KAAK,YAClB,WAAY,KAAK,WACjB,UAAW,KAAK,UAChB,QAAS,KAAK,QACd,GAAI,KAAK,EACX,CACF,CACF","names":["index_exports","__export","AggregateId","AggregateRoot","ApplicationError","DomainError","DomainEvent","Entity","EntityValidationError","HttpStatus","HttpStatusMessage","InvalidValueObjectError","ValueObject","deepFreeze","ensureObject","unwrapValueObject","__toCommonJS","deepFreeze","obj","seen","item","key","HttpStatus","HttpStatusMessage","ApplicationError","code","HttpStatusMessage","isOperational","status","metadata","message","cause","import_es6","ValueObject","_ValueObject","props","deepFreeze","vo","other","deepEqual","unwrapValueObject","input","seen","result","item","ValueObject","value","key","v","ensureObject","getCauseInfo","cause","DomainError","message","code","metadata","__spreadValues","EntityValidationError","DomainError","message","cause","import_uuid","import_zod","InvalidValueObjectError","DomainError","message","_AggregateId","ValueObject","value","result","InvalidValueObjectError","z","AggregateId","_createdAt","_id","_props","_Entity","createdAt","props","id","__privateAdd","EntityValidationError","__privateSet","AggregateId","__privateGet","entity","other","unwrapValueObject","safeProps","ensureObject","__spreadValues","Entity","AggregateRoot","Entity","domainEvent","events","DomainEvent","props"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var I=Object.defineProperty;var l=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,m=Object.prototype.propertyIsEnumerable;var O=(e,t,r)=>t in e?I(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,u=(e,t)=>{for(var r in t||(t={}))_.call(t,r)&&O(e,r,t[r]);if(l)for(var r of l(t))m.call(t,r)&&O(e,r,t[r]);return e};var S=e=>e instanceof Error?{cause:{message:e.message,stack:e.stack,name:e.name}}:e?{cause:e}:{},n=class extends Error{constructor(t,r,a={}){super(t,u({},S(a.cause))),Object.setPrototypeOf(this,new.target.prototype),this.name=new.target.name,this.code=r,this.metadata=Object.freeze(u({},a))}};import U from"fast-deep-equal/es6";function E(e,t=new WeakSet){if(e==null||typeof e!="object"&&!Array.isArray(e)||Object.isFrozen(e)||t.has(e))return e;if(t.add(e),Array.isArray(e))e.forEach(r=>E(r,t));else for(let r in e)Object.hasOwn(e,r)&&E(e[r],t);return Object.freeze(e)}var s=class e{get value(){return this.props}constructor(t){this.validate(t),this.props=E(t)}static is(t){return t instanceof e}equals(t){return!t||!(t instanceof this.constructor)?!1:U(this.props,t.props)}};var p=class extends n{constructor(t,r){super(t,"ENTITY_VALIDATION_ERROR",{cause:r})}};var T=class extends n{constructor(t){super(t,"INVALID_VALUE_OBJECT")}};import{v4 as D}from"uuid";import g from"zod";var i=class i extends s{get uuid(){return this.value}static create(t){return new i(t)}static generate(){return new i(D())}isEmpty(){return!this.value}toString(){return this.value}validate(t){let r=i.schema.safeParse(t);if(!r.success)throw new T(`Invalid AggregateId: ${r.error.message}`)}};i.schema=g.uuid();var R=i;var Y=Object.freeze({REQUEST_HEADER_FIELDS_TOO_LARGE:431,NETWORK_AUTHENTICATION_REQUIRED:511,NON_AUTHORITATIVE_INFORMATION:203,PROXY_AUTHENTICATION_REQUIRED:407,UNAVAILABLE_FOR_LEGAL_REASONS:451,HTTP_VERSION_NOT_SUPPORTED:505,BANDWIDTH_LIMIT_EXCEEDED:509,VARIANT_ALSO_NEGOTIATES:506,UNSUPPORTED_MEDIA_TYPE:415,RANGE_NOT_SATISFIABLE:416,PRECONDITION_REQUIRED:428,INTERNAL_SERVER_ERROR:500,UNPROCESSABLE_ENTITY:422,INSUFFICIENT_STORAGE:507,SWITCHING_PROTOCOLS:101,PRECONDITION_FAILED:412,MISDIRECTED_REQUEST:421,SERVICE_UNAVAILABLE:503,TEMPORARY_REDIRECT:307,PERMANENT_REDIRECT:308,METHOD_NOT_ALLOWED:405,EXPECTATION_FAILED:417,MOVED_PERMANENTLY:301,PAYLOAD_TOO_LARGE:413,FAILED_DEPENDENCY:424,TOO_MANY_REQUESTS:429,ALREADY_REPORTED:208,MULTIPLE_CHOICES:300,PAYMENT_REQUIRED:402,UPGRADE_REQUIRED:426,PARTIAL_CONTENT:206,REQUEST_TIMEOUT:408,LENGTH_REQUIRED:411,NOT_IMPLEMENTED:501,GATEWAY_TIMEOUT:504,NOT_ACCEPTABLE:406,RESET_CONTENT:205,LOOP_DETECTED:508,MULTI_STATUS:207,NOT_MODIFIED:304,UNAUTHORIZED:401,URI_TOO_LONG:414,NOT_EXTENDED:510,EARLY_HINTS:103,BAD_REQUEST:400,IM_A_TEAPOT:418,BAD_GATEWAY:502,PROCESSING:102,NO_CONTENT:204,SEE_OTHER:303,USE_PROXY:305,FORBIDDEN:403,NOT_FOUND:404,TOO_EARLY:425,CONTINUE:100,ACCEPTED:202,CONFLICT:409,CREATED:201,IM_USED:226,LOCKED:423,FOUND:302,GONE:410,OK:200}),f={431:"Request Header Fields Too Large",511:"Network Authentication Required",203:"Non-Authoritative Information",407:"Proxy Authentication Required",451:"Unavailable For Legal Reasons",505:"HTTP Version Not Supported",509:"Bandwidth Limit Exceeded",506:"Variant Also Negotiates",415:"Unsupported Media Type",416:"Range Not Satisfiable",428:"Precondition Required",500:"Internal Server Error",422:"Unprocessable Entity",507:"Insufficient Storage",101:"Switching Protocols",412:"Precondition Failed",421:"Misdirected Request",503:"Service Unavailable",307:"Temporary Redirect",308:"Permanent Redirect",405:"Method Not Allowed",417:"Expectation Failed",301:"Moved Permanently",413:"Payload Too Large",424:"Failed Dependency",429:"Too Many Requests",208:"Already Reported",300:"Multiple Choices",402:"Payment Required",426:"Upgrade Required",206:"Partial Content",408:"Request Timeout",411:"Length Required",501:"Not Implemented",504:"Gateway Timeout",406:"Not Acceptable",205:"Reset Content",508:"Loop Detected",207:"Multi-Status",304:"Not Modified",401:"Unauthorized",414:"URI Too Long",418:"I'm a Teapot",510:"Not Extended",103:"Early Hints",400:"Bad Request",502:"Bad Gateway",102:"Processing",204:"No Content",303:"See Other",305:"Use Proxy",403:"Forbidden",404:"Not Found",425:"Too Early",100:"Continue",202:"Accepted",226:"I'm Used",409:"Conflict",201:"Created",423:"Locked",302:"Found",410:"Gone",200:"OK"};var A=class extends Error{constructor({code:t=f[500],isOperational:r=!1,status:a=500,metadata:o,message:d,cause:N}){super(d),this.name=new.target.name,this.code=t,this.status=a,this.isOperational=r,this.metadata=o,this.cause=N,Error.captureStackTrace(this,new.target)}};function c(e,t=new WeakSet){if(e==null||typeof e!="object")return e;if(t.has(e))throw new Error("Circular reference detected in ValueObject unwrap");if(t.add(e),Array.isArray(e)){let a=e.map(o=>c(o,t));return t.delete(e),a}if(e instanceof s){let a=c(e.value,t);return t.delete(e),a}if(e instanceof Date)return t.delete(e),e.toISOString();if(e instanceof Map){let a=new Map;return e.forEach((o,d)=>{a.set(d,c(o,t))}),t.delete(e),a}if(e instanceof Set){let a=new Set(Array.from(e.values()).map(o=>c(o,t)));return t.delete(e),a}let r={};for(let a in e)Object.hasOwn(e,a)&&(r[a]=c(e[a],t));return t.delete(e),r}function W(e){return e==null?{}:typeof e=="object"?e:{value:e}}export{R as AggregateId,A as ApplicationError,n as DomainError,p as EntityValidationError,Y as HttpStatus,f as HttpStatusMessage,T as InvalidValueObjectError,s as ValueObject,E as deepFreeze,W as ensureObject,c as unwrapValueObject};
1
+ var x=Object.defineProperty;var I=Object.getOwnPropertySymbols;var V=Object.prototype.hasOwnProperty,C=Object.prototype.propertyIsEnumerable;var D=e=>{throw TypeError(e)};var N=(e,t,r)=>t in e?x(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,c=(e,t)=>{for(var r in t||(t={}))V.call(t,r)&&N(e,r,t[r]);if(I)for(var r of I(t))C.call(t,r)&&N(e,r,t[r]);return e};var _=(e,t,r)=>t.has(e)||D("Cannot "+r);var n=(e,t,r)=>(_(e,t,"read from private field"),r?r.call(e):t.get(e)),T=(e,t,r)=>t.has(e)?D("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),O=(e,t,r,a)=>(_(e,t,"write to private field"),a?a.call(e,r):t.set(e,r),r);function m(e,t=new WeakSet){if(e==null||typeof e!="object"&&!Array.isArray(e)||Object.isFrozen(e)||t.has(e))return e;if(t.add(e),Array.isArray(e))e.forEach(r=>m(r,t));else for(let r in e)Object.hasOwn(e,r)&&m(e[r],t);return Object.freeze(e)}var q=Object.freeze({REQUEST_HEADER_FIELDS_TOO_LARGE:431,NETWORK_AUTHENTICATION_REQUIRED:511,NON_AUTHORITATIVE_INFORMATION:203,PROXY_AUTHENTICATION_REQUIRED:407,UNAVAILABLE_FOR_LEGAL_REASONS:451,HTTP_VERSION_NOT_SUPPORTED:505,BANDWIDTH_LIMIT_EXCEEDED:509,VARIANT_ALSO_NEGOTIATES:506,UNSUPPORTED_MEDIA_TYPE:415,RANGE_NOT_SATISFIABLE:416,PRECONDITION_REQUIRED:428,INTERNAL_SERVER_ERROR:500,UNPROCESSABLE_ENTITY:422,INSUFFICIENT_STORAGE:507,SWITCHING_PROTOCOLS:101,PRECONDITION_FAILED:412,MISDIRECTED_REQUEST:421,SERVICE_UNAVAILABLE:503,TEMPORARY_REDIRECT:307,PERMANENT_REDIRECT:308,METHOD_NOT_ALLOWED:405,EXPECTATION_FAILED:417,MOVED_PERMANENTLY:301,PAYLOAD_TOO_LARGE:413,FAILED_DEPENDENCY:424,TOO_MANY_REQUESTS:429,ALREADY_REPORTED:208,MULTIPLE_CHOICES:300,PAYMENT_REQUIRED:402,UPGRADE_REQUIRED:426,PARTIAL_CONTENT:206,REQUEST_TIMEOUT:408,LENGTH_REQUIRED:411,NOT_IMPLEMENTED:501,GATEWAY_TIMEOUT:504,NOT_ACCEPTABLE:406,RESET_CONTENT:205,LOOP_DETECTED:508,MULTI_STATUS:207,NOT_MODIFIED:304,UNAUTHORIZED:401,URI_TOO_LONG:414,NOT_EXTENDED:510,EARLY_HINTS:103,BAD_REQUEST:400,IM_A_TEAPOT:418,BAD_GATEWAY:502,PROCESSING:102,NO_CONTENT:204,SEE_OTHER:303,USE_PROXY:305,FORBIDDEN:403,NOT_FOUND:404,TOO_EARLY:425,CONTINUE:100,ACCEPTED:202,CONFLICT:409,CREATED:201,IM_USED:226,LOCKED:423,FOUND:302,GONE:410,OK:200}),h={431:"Request Header Fields Too Large",511:"Network Authentication Required",203:"Non-Authoritative Information",407:"Proxy Authentication Required",451:"Unavailable For Legal Reasons",505:"HTTP Version Not Supported",509:"Bandwidth Limit Exceeded",506:"Variant Also Negotiates",415:"Unsupported Media Type",416:"Range Not Satisfiable",428:"Precondition Required",500:"Internal Server Error",422:"Unprocessable Entity",507:"Insufficient Storage",101:"Switching Protocols",412:"Precondition Failed",421:"Misdirected Request",503:"Service Unavailable",307:"Temporary Redirect",308:"Permanent Redirect",405:"Method Not Allowed",417:"Expectation Failed",301:"Moved Permanently",413:"Payload Too Large",424:"Failed Dependency",429:"Too Many Requests",208:"Already Reported",300:"Multiple Choices",402:"Payment Required",426:"Upgrade Required",206:"Partial Content",408:"Request Timeout",411:"Length Required",501:"Not Implemented",504:"Gateway Timeout",406:"Not Acceptable",205:"Reset Content",508:"Loop Detected",207:"Multi-Status",304:"Not Modified",401:"Unauthorized",414:"URI Too Long",418:"I'm a Teapot",510:"Not Extended",103:"Early Hints",400:"Bad Request",502:"Bad Gateway",102:"Processing",204:"No Content",303:"See Other",305:"Use Proxy",403:"Forbidden",404:"Not Found",425:"Too Early",100:"Continue",202:"Accepted",226:"I'm Used",409:"Conflict",201:"Created",423:"Locked",302:"Found",410:"Gone",200:"OK"};var S=class extends Error{constructor({code:t=h[500],isOperational:r=!1,status:a=500,metadata:s,message:b,cause:w}){super(b),this.name=new.target.name,this.code=t,this.status=a,this.isOperational=r,this.metadata=s,this.cause=w,Error.captureStackTrace(this,new.target)}};import L from"fast-deep-equal/es6";var d=class e{get value(){return this.props}constructor(t){this.validate(t),this.props=m(t)}static is(t){return t instanceof e}equals(t){return!t||!(t instanceof this.constructor)?!1:L(this.props,t.props)}};function i(e,t=new WeakSet){if(e==null||typeof e!="object")return e;if(t.has(e))throw new Error("Circular reference detected in ValueObject unwrap");if(t.add(e),Array.isArray(e)){let a=e.map(s=>i(s,t));return t.delete(e),a}if(e instanceof d){let a=i(e.value,t);return t.delete(e),a}if(e instanceof Date)return t.delete(e),e.toISOString();if(e instanceof Map){let a=new Map;return e.forEach((s,b)=>{a.set(b,i(s,t))}),t.delete(e),a}if(e instanceof Set){let a=new Set(Array.from(e.values()).map(s=>i(s,t)));return t.delete(e),a}let r={};for(let a in e)Object.hasOwn(e,a)&&(r[a]=i(e[a],t));return t.delete(e),r}function P(e){return e==null?{}:typeof e=="object"?e:{value:e}}var M=e=>e instanceof Error?{cause:{message:e.message,stack:e.stack,name:e.name}}:e?{cause:e}:{},l=class extends Error{constructor(t,r,a={}){super(t,c({},M(a.cause))),Object.setPrototypeOf(this,new.target.prototype),this.name=new.target.name,this.code=r,this.metadata=Object.freeze(c({},a))}};var g=class extends l{constructor(t,r){super(t,"ENTITY_VALIDATION_ERROR",{cause:r})}};import{v4 as j}from"uuid";import H from"zod";var f=class extends l{constructor(t){super(t,"INVALID_VALUE_OBJECT")}};var E=class E extends d{get uuid(){return this.value}static create(t){return new E(t)}static generate(){return new E(j())}isEmpty(){return!this.value}toString(){return this.value}validate(t){let r=E.schema.safeParse(t);if(!r.success)throw new f(`Invalid AggregateId: ${r.error.message}`)}};E.schema=H.uuid();var y=E;var u,o,p,A=class A{constructor({createdAt:t,props:r,id:a}){T(this,u);T(this,o);T(this,p);if(!a)throw new g("Entity ID cannot be empty");O(this,o,a!=null?a:y.generate()),O(this,p,Object.freeze(r)),O(this,u,t?new Date(t):new Date)}get createdAt(){return new Date(n(this,u))}get id(){return n(this,o)}get metadata(){return Object.freeze({createdAt:n(this,u).toISOString(),id:n(this,o).uuid})}get props(){return n(this,p)}static isEntity(t){return typeof t=="object"&&t!==null&&"id"in t&&typeof t.equals=="function"}equals(t){return!t||!A.isEntity(t)?!1:n(this,o).equals(n(t,o))}getPropsCopy(){return Object.freeze(n(this,p))}isPersisted(){return n(this,o).isEmpty()}toJSON(){return this.toObject()}toObject(){let t=i(this.getPropsCopy()),r=P(t);return Object.freeze(c(c({},this.metadata),r))}};u=new WeakMap,o=new WeakMap,p=new WeakMap;var R=A;var U=class extends R{constructor(){super(...arguments);this._domainEvents=[]}get domainEvents(){return[...this._domainEvents]}addEvent(r){this.validate(),this._domainEvents.push(r)}pullDomainEvents(){let r=[...this._domainEvents];return this._domainEvents.length=0,r}};var v=class{constructor(t){this.id=t.id,this.aggregateId=t.aggregateId,this.schemaVersion=t.schemaVersion,this.occurredAt=t.occurredAt,this.payload=Object.freeze(t.payload)}toPrimitives(){return{schemaVersion:this.schemaVersion,aggregateId:this.aggregateId,occurredAt:this.occurredAt,eventName:this.eventName,payload:this.payload,id:this.id}}};export{y as AggregateId,U as AggregateRoot,S as ApplicationError,l as DomainError,v as DomainEvent,R as Entity,g as EntityValidationError,q as HttpStatus,h as HttpStatusMessage,f as InvalidValueObjectError,d as ValueObject,m as deepFreeze,P as ensureObject,i as unwrapValueObject};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/domain/base/domain.error.ts","../src/domain/base/vo.ts","../src/utils/deep-freeze.util.ts","../src/domain/errors/entity-validation.error.ts","../src/domain/errors/invalid-vo.error.ts","../src/domain/value-objects/aggregate-id.vo.ts","../src/gateway/constants/http-code.ts","../src/utils/errors/application.error.ts","../src/utils/unwrap-vo.util.ts"],"sourcesContent":["export interface DomainErrorMetadata {\n cause?: { name: string; message: string; stack?: string };\n [key: string]: unknown;\n}\n\nconst getCauseInfo = (cause: Error | undefined) => {\n // 1. Handle Error objects specifically\n if (cause instanceof Error) {\n return {\n cause: {\n message: cause.message,\n stack: cause.stack,\n name: cause.name,\n },\n };\n }\n\n // 2. Handle other existing values\n if (cause) {\n return { cause };\n }\n\n // 3. Default to empty\n return {};\n};\n\n/**\n * Base class for all Domain Errors in the application.\n *\n * This class ensures:\n * 1. Serializable and structured for logs or API responses.\n * 2. Identifiable via stable error codes (not just class names).\n * 3. Contextual with optional structured metadata.\n * 4. Supports error chaining (cause) and stack trace preservation.\n *\n * @example\n * export class InsufficientFundsError extends DomainError {\n * constructor(accountId: string, currentBalance: number) {\n * super(\n * `Account ${accountId} has insufficient funds.`,\n * 'INSUFFICIENT_FUNDS',\n * { accountId, currentBalance }\n * );\n * }\n * }\n */\nexport abstract class DomainError extends Error {\n /** Stable, machine-readable error code */\n public readonly code: string;\n /** Structured, immutable domain metadata */\n public readonly metadata: Readonly<DomainErrorMetadata>;\n\n /**\n * @param message - Human-readable error message\n * @param code - Stable error code\n * @param metadata - Domain-specific structured data; optional `cause` can be included\n */\n protected constructor(\n message: string,\n code: string,\n metadata: DomainErrorMetadata = {},\n ) {\n super(message, { ...getCauseInfo(metadata.cause) });\n\n // Restore prototype chain for proper `instanceof` checks\n Object.setPrototypeOf(this, new.target.prototype);\n\n this.name = new.target.name;\n this.code = code;\n this.metadata = Object.freeze({ ...metadata });\n }\n}\n","import deepEqual from 'fast-deep-equal/es6';\n\nimport { deepFreeze } from '@/utils/deep-freeze.util';\n\nexport abstract class ValueObject<T> {\n get value(): T {\n return this.props;\n }\n\n protected readonly props: Readonly<T>;\n\n protected constructor(props: T) {\n this.validate(props);\n this.props = deepFreeze(props);\n }\n\n /**\n * Type guard to check if an unknown object is an instance of ValueObject.\n * This is useful for runtime type checking.\n *\n * @param vo The object to check.\n * @returns True if the object is a ValueObject instance, false otherwise.\n */\n public static is(vo: unknown): vo is ValueObject<unknown> {\n return vo instanceof ValueObject;\n }\n\n /**\n * Deep equality comparison of ValueObjects\n */\n public equals(other?: ValueObject<T>): boolean {\n if (\n !other ||\n !(other instanceof (this.constructor as typeof ValueObject))\n ) {\n return false;\n }\n\n return deepEqual(this.props, other.props);\n }\n\n /**\n * Validates the value object props\n * @throws InvalidValueObjectError if validation fails\n */\n protected abstract validate(props: T): void;\n}\n","/**\n * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.\n *\n * @param obj - The object to be deeply frozen.\n * @param seen - A WeakSet to track already processed objects (for circular references).\n * @returns A deeply frozen version of the input object.\n */\nexport function deepFreeze<T>(\n obj: T,\n seen = new WeakSet<object>(),\n): Readonly<T> {\n // Handle null, undefined, or non-object types\n if (obj == null || (typeof obj !== 'object' && !Array.isArray(obj))) {\n return obj;\n }\n\n // Skip if already frozen\n if (Object.isFrozen(obj)) {\n return obj as Readonly<T>;\n }\n\n // Handle circular references\n if (seen.has(obj as object)) {\n return obj as Readonly<T>;\n }\n\n seen.add(obj as object);\n\n // Handle arrays explicitly\n if (Array.isArray(obj)) {\n obj.forEach(item => deepFreeze(item, seen));\n } else {\n // Handle plain objects\n for (const key in obj) {\n if (Object.hasOwn(obj, key)) {\n deepFreeze((obj as Record<string, unknown>)[key], seen);\n }\n }\n }\n\n return Object.freeze(obj) as Readonly<T>;\n}\n","import { DomainError } from '../base/domain.error';\n\n/**\n * Custom error class for entity validation failures.\n */\nexport class EntityValidationError extends DomainError {\n constructor(message: string, cause?: Error) {\n super(message, 'ENTITY_VALIDATION_ERROR', { cause });\n }\n}\n","import { DomainError } from '../base/domain.error';\n\nexport class InvalidValueObjectError extends DomainError {\n constructor(message: string) {\n super(message, 'INVALID_VALUE_OBJECT');\n }\n}\n","import { v4 } from 'uuid';\nimport z from 'zod';\n\nimport { InvalidValueObjectError } from '../errors/invalid-vo.error';\nimport { ValueObject } from '../base/vo';\n\n/**\n * AggregateId is a ValueObject that represents a unique identifier for an aggregate.\n */\nexport class AggregateId extends ValueObject<string> {\n /**\n * The schema for the AggregateId\n */\n private static readonly schema = z.uuid();\n\n /**\n * Get the UUID of the AggregateId\n * @returns The UUID of the AggregateId\n */\n public get uuid(): string {\n return this.value;\n }\n\n /**\n * Create a new AggregateId\n * @param value The value to create the AggregateId from\n * @returns The new AggregateId\n */\n public static create(value: string): AggregateId {\n return new AggregateId(value);\n }\n\n /**\n * Create a new AggregateId with a random UUID v4\n */\n public static generate(): AggregateId {\n return new AggregateId(v4());\n }\n\n /**\n * Check if the AggregateId is empty\n * @returns True if the AggregateId is empty, false otherwise\n */\n public isEmpty(): boolean {\n return !this.value;\n }\n\n /**\n * Convert the AggregateId to a string\n * @returns The string representation of the AggregateId\n */\n public toString(): string {\n return this.value;\n }\n\n /**\n * Validate the AggregateId\n * @param value The value to validate\n * @throws InvalidValueObjectException if the value is invalid\n */\n protected validate(value: string): void {\n const result = AggregateId.schema.safeParse(value);\n\n if (!result.success) {\n throw new InvalidValueObjectError(\n `Invalid AggregateId: ${result.error.message}`,\n );\n }\n }\n}\n","/**\n * HTTP status code catalog.\n *\n * This object provides a typed, immutable map of standard HTTP status names\n * to their numeric codes. Designed for server-side frameworks such as Fastify.\n *\n * - All identifiers use clear, canonical semantic names.\n * - Values are numeric status codes.\n * - Frozen to prevent runtime mutation.\n * - Exporting `HttpStatus` ensures type-safe usage across the codebase.\n * Usage:\n * ```ts\n * import { HttpStatus } from 'path-to-this-file';\n *\n * function handleRequest() {\n * return {\n * statusCode: HttpStatus.OK,\n * body: 'Success',\n * };\n * }\n * ```\n */\nexport const HttpStatus = Object.freeze({\n REQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n NETWORK_AUTHENTICATION_REQUIRED: 511,\n NON_AUTHORITATIVE_INFORMATION: 203,\n PROXY_AUTHENTICATION_REQUIRED: 407,\n\n UNAVAILABLE_FOR_LEGAL_REASONS: 451,\n HTTP_VERSION_NOT_SUPPORTED: 505,\n BANDWIDTH_LIMIT_EXCEEDED: 509,\n VARIANT_ALSO_NEGOTIATES: 506,\n UNSUPPORTED_MEDIA_TYPE: 415,\n RANGE_NOT_SATISFIABLE: 416,\n PRECONDITION_REQUIRED: 428,\n INTERNAL_SERVER_ERROR: 500,\n UNPROCESSABLE_ENTITY: 422,\n INSUFFICIENT_STORAGE: 507,\n\n SWITCHING_PROTOCOLS: 101,\n PRECONDITION_FAILED: 412,\n MISDIRECTED_REQUEST: 421,\n SERVICE_UNAVAILABLE: 503,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n METHOD_NOT_ALLOWED: 405,\n EXPECTATION_FAILED: 417,\n\n MOVED_PERMANENTLY: 301,\n PAYLOAD_TOO_LARGE: 413,\n FAILED_DEPENDENCY: 424,\n TOO_MANY_REQUESTS: 429,\n ALREADY_REPORTED: 208,\n MULTIPLE_CHOICES: 300,\n PAYMENT_REQUIRED: 402,\n UPGRADE_REQUIRED: 426,\n PARTIAL_CONTENT: 206,\n REQUEST_TIMEOUT: 408,\n LENGTH_REQUIRED: 411,\n NOT_IMPLEMENTED: 501,\n GATEWAY_TIMEOUT: 504,\n NOT_ACCEPTABLE: 406,\n RESET_CONTENT: 205,\n LOOP_DETECTED: 508,\n MULTI_STATUS: 207,\n NOT_MODIFIED: 304,\n UNAUTHORIZED: 401,\n URI_TOO_LONG: 414,\n NOT_EXTENDED: 510,\n EARLY_HINTS: 103,\n BAD_REQUEST: 400,\n IM_A_TEAPOT: 418,\n BAD_GATEWAY: 502,\n PROCESSING: 102,\n NO_CONTENT: 204,\n SEE_OTHER: 303,\n USE_PROXY: 305,\n\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n TOO_EARLY: 425,\n CONTINUE: 100,\n ACCEPTED: 202,\n CONFLICT: 409,\n CREATED: 201,\n IM_USED: 226,\n LOCKED: 423,\n FOUND: 302,\n GONE: 410,\n OK: 200,\n} as const);\n\n/**\n * HTTP status messages mapped by numeric code.\n * Use for sending descriptive text in responses or logging.\n */\nexport const HttpStatusMessage = {\n 431: 'Request Header Fields Too Large',\n 511: 'Network Authentication Required',\n 203: 'Non-Authoritative Information',\n 407: 'Proxy Authentication Required',\n 451: 'Unavailable For Legal Reasons',\n 505: 'HTTP Version Not Supported',\n 509: 'Bandwidth Limit Exceeded',\n 506: 'Variant Also Negotiates',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 428: 'Precondition Required',\n 500: 'Internal Server Error',\n 422: 'Unprocessable Entity',\n 507: 'Insufficient Storage',\n 101: 'Switching Protocols',\n 412: 'Precondition Failed',\n 421: 'Misdirected Request',\n 503: 'Service Unavailable',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 405: 'Method Not Allowed',\n 417: 'Expectation Failed',\n 301: 'Moved Permanently',\n 413: 'Payload Too Large',\n 424: 'Failed Dependency',\n 429: 'Too Many Requests',\n 208: 'Already Reported',\n 300: 'Multiple Choices',\n 402: 'Payment Required',\n 426: 'Upgrade Required',\n 206: 'Partial Content',\n 408: 'Request Timeout',\n 411: 'Length Required',\n 501: 'Not Implemented',\n 504: 'Gateway Timeout',\n 406: 'Not Acceptable',\n 205: 'Reset Content',\n 508: 'Loop Detected',\n 207: 'Multi-Status',\n 304: 'Not Modified',\n 401: 'Unauthorized',\n 414: 'URI Too Long',\n 418: \"I'm a Teapot\",\n 510: 'Not Extended',\n 103: 'Early Hints',\n 400: 'Bad Request',\n 502: 'Bad Gateway',\n 102: 'Processing',\n 204: 'No Content',\n 303: 'See Other',\n 305: 'Use Proxy',\n 403: 'Forbidden',\n 404: 'Not Found',\n 425: 'Too Early',\n 100: 'Continue',\n 202: 'Accepted',\n 226: \"I'm Used\",\n 409: 'Conflict',\n 201: 'Created',\n 423: 'Locked',\n 302: 'Found',\n 410: 'Gone',\n 200: 'OK',\n} as const;\n\nexport type HttpStatusCode = keyof typeof HttpStatusMessage;\n\nexport type HttpStatusMessage =\n (typeof HttpStatusMessage)[keyof typeof HttpStatusMessage];\n","import {\n HttpStatusCode,\n HttpStatusMessage,\n} from '@/gateway/constants/http-code';\n\ninterface ErrorParams {\n message: string;\n code: HttpStatusMessage;\n status?: HttpStatusCode;\n metadata?: Record<string, unknown> | undefined;\n isOperational?: boolean;\n cause?: Error | undefined;\n}\n\n/**\n * Abstract base class for application-level errors with structured error handling.\n *\n * Extends the native Error class to provide machine-readable error codes, HTTP status codes,\n * operational error classification, and optional metadata for better error tracking and client communication.\n *\n * @abstract\n * @extends {Error}\n *\n * @example\n * ```typescript\n * class UserNotFoundError extends ApplicationError {\n * constructor(userId: string) {\n * super({\n * code: HttpStatusMessage['404'],\n * status: 404,\n * isOperational: true,\n * message: `User with id ${userId} not found`,\n * metadata: { userId }\n * });\n * }\n * }\n * ```\n */\nexport abstract class ApplicationError extends Error {\n /** Optional cause (linked error) */\n public readonly cause?: Error | undefined;\n /** Machine-readable error code (e.g. `OTP_LOCKED`, `USER_NOT_FOUND`) */\n public readonly code: HttpStatusMessage;\n /** Operational vs programmer error flag */\n public readonly isOperational: boolean;\n /** Optional structured metadata for debugging or clients */\n public readonly metadata?: Record<string, unknown> | undefined;\n /** HTTP status code intended for response layer */\n public readonly status: HttpStatusCode;\n\n constructor({\n code = HttpStatusMessage['500'],\n isOperational = false,\n status = 500,\n metadata,\n message,\n cause,\n }: ErrorParams) {\n super(message);\n\n this.name = new.target.name;\n this.code = code;\n this.status = status;\n this.isOperational = isOperational;\n this.metadata = metadata;\n this.cause = cause;\n\n Error.captureStackTrace(this, new.target);\n }\n}\n","import { ValueObject } from '@/domain/base/vo';\n\nexport type UnwrapValueObject<T> =\n T extends ValueObject<infer V>\n ? UnwrapValueObject<V>\n : T extends (infer U)[]\n ? UnwrapValueObject<U>[]\n : T extends Map<infer K, infer V>\n ? Map<K, UnwrapValueObject<V>>\n : T extends Set<infer V>\n ? Set<UnwrapValueObject<V>>\n : T extends Date\n ? string\n : T extends object\n ? { [K in keyof T]: UnwrapValueObject<T[K]> }\n : T;\n\nexport function unwrapValueObject<T>(\n input: T,\n seen = new WeakSet(),\n): UnwrapValueObject<T> {\n if (input === null || input === undefined) {\n return input as UnwrapValueObject<T>;\n }\n\n if (typeof input !== 'object') {\n return input as UnwrapValueObject<T>;\n }\n\n if (seen.has(input)) {\n // Prevent circular reference infinite recursion, just return input or throw\n throw new Error('Circular reference detected in ValueObject unwrap');\n }\n\n seen.add(input);\n\n if (Array.isArray(input)) {\n const result = input.map(item => unwrapValueObject(item, seen));\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof ValueObject) {\n const result = unwrapValueObject(input.value, seen);\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof Date) {\n seen.delete(input);\n return input.toISOString() as UnwrapValueObject<T>;\n }\n\n if (input instanceof Map) {\n const result = new Map();\n input.forEach((value, key) => {\n result.set(key, unwrapValueObject(value, seen));\n });\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof Set) {\n const result = new Set(\n Array.from(input.values()).map(v => unwrapValueObject(v, seen)),\n );\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n // generic object\n const result: Record<string, unknown> = {};\n\n for (const key in input) {\n if (Object.hasOwn(input, key)) {\n result[key] = unwrapValueObject((input as any)[key], seen);\n }\n }\n\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n}\n\nexport function ensureObject<T>(input: UnwrapValueObject<T>): object {\n if (input === null || input === undefined) {\n return {};\n }\n if (typeof input === 'object') {\n return input;\n }\n\n // for primitives, wrap inside object with default key (or throw)\n return { value: input };\n}\n"],"mappings":"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","names":["getCauseInfo","cause","DomainError","message","code","metadata","__spreadValues","deepEqual","deepFreeze","obj","seen","item","key","ValueObject","_ValueObject","props","deepFreeze","vo","other","deepEqual","EntityValidationError","DomainError","message","cause","InvalidValueObjectError","DomainError","message","v4","z","_AggregateId","ValueObject","value","v4","result","InvalidValueObjectError","z","AggregateId","HttpStatus","HttpStatusMessage","ApplicationError","code","HttpStatusMessage","isOperational","status","metadata","message","cause","unwrapValueObject","input","seen","result","item","ValueObject","value","key","v","ensureObject"]}
1
+ {"version":3,"sources":["../src/utils/deep-freeze.util.ts","../src/gateway/constants/http-code.ts","../src/utils/errors/application.error.ts","../src/domain/base/vo.ts","../src/utils/unwrap-vo.util.ts","../src/domain/base/domain.error.ts","../src/domain/errors/entity-validation.error.ts","../src/domain/value-objects/aggregate-id.vo.ts","../src/domain/errors/invalid-vo.error.ts","../src/domain/entities/entity.ts","../src/domain/aggregates/aggregate-root.ts","../src/domain/events/domain.event.ts"],"sourcesContent":["/**\n * Utility to deeply freeze objects to ensure immutability - handles nested objects and arrays.\n *\n * @param obj - The object to be deeply frozen.\n * @param seen - A WeakSet to track already processed objects (for circular references).\n * @returns A deeply frozen version of the input object.\n */\nexport function deepFreeze<T>(\n obj: T,\n seen = new WeakSet<object>(),\n): Readonly<T> {\n // Handle null, undefined, or non-object types\n if (obj == null || (typeof obj !== 'object' && !Array.isArray(obj))) {\n return obj;\n }\n\n // Skip if already frozen\n if (Object.isFrozen(obj)) {\n return obj as Readonly<T>;\n }\n\n // Handle circular references\n if (seen.has(obj as object)) {\n return obj as Readonly<T>;\n }\n\n seen.add(obj as object);\n\n // Handle arrays explicitly\n if (Array.isArray(obj)) {\n obj.forEach(item => deepFreeze(item, seen));\n } else {\n // Handle plain objects\n for (const key in obj) {\n if (Object.hasOwn(obj, key)) {\n deepFreeze((obj as Record<string, unknown>)[key], seen);\n }\n }\n }\n\n return Object.freeze(obj) as Readonly<T>;\n}\n","/**\n * HTTP status code catalog.\n *\n * This object provides a typed, immutable map of standard HTTP status names\n * to their numeric codes. Designed for server-side frameworks such as Fastify.\n *\n * - All identifiers use clear, canonical semantic names.\n * - Values are numeric status codes.\n * - Frozen to prevent runtime mutation.\n * - Exporting `HttpStatus` ensures type-safe usage across the codebase.\n * Usage:\n * ```ts\n * import { HttpStatus } from 'path-to-this-file';\n *\n * function handleRequest() {\n * return {\n * statusCode: HttpStatus.OK,\n * body: 'Success',\n * };\n * }\n * ```\n */\nexport const HttpStatus = Object.freeze({\n REQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n NETWORK_AUTHENTICATION_REQUIRED: 511,\n NON_AUTHORITATIVE_INFORMATION: 203,\n PROXY_AUTHENTICATION_REQUIRED: 407,\n\n UNAVAILABLE_FOR_LEGAL_REASONS: 451,\n HTTP_VERSION_NOT_SUPPORTED: 505,\n BANDWIDTH_LIMIT_EXCEEDED: 509,\n VARIANT_ALSO_NEGOTIATES: 506,\n UNSUPPORTED_MEDIA_TYPE: 415,\n RANGE_NOT_SATISFIABLE: 416,\n PRECONDITION_REQUIRED: 428,\n INTERNAL_SERVER_ERROR: 500,\n UNPROCESSABLE_ENTITY: 422,\n INSUFFICIENT_STORAGE: 507,\n\n SWITCHING_PROTOCOLS: 101,\n PRECONDITION_FAILED: 412,\n MISDIRECTED_REQUEST: 421,\n SERVICE_UNAVAILABLE: 503,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n METHOD_NOT_ALLOWED: 405,\n EXPECTATION_FAILED: 417,\n\n MOVED_PERMANENTLY: 301,\n PAYLOAD_TOO_LARGE: 413,\n FAILED_DEPENDENCY: 424,\n TOO_MANY_REQUESTS: 429,\n ALREADY_REPORTED: 208,\n MULTIPLE_CHOICES: 300,\n PAYMENT_REQUIRED: 402,\n UPGRADE_REQUIRED: 426,\n PARTIAL_CONTENT: 206,\n REQUEST_TIMEOUT: 408,\n LENGTH_REQUIRED: 411,\n NOT_IMPLEMENTED: 501,\n GATEWAY_TIMEOUT: 504,\n NOT_ACCEPTABLE: 406,\n RESET_CONTENT: 205,\n LOOP_DETECTED: 508,\n MULTI_STATUS: 207,\n NOT_MODIFIED: 304,\n UNAUTHORIZED: 401,\n URI_TOO_LONG: 414,\n NOT_EXTENDED: 510,\n EARLY_HINTS: 103,\n BAD_REQUEST: 400,\n IM_A_TEAPOT: 418,\n BAD_GATEWAY: 502,\n PROCESSING: 102,\n NO_CONTENT: 204,\n SEE_OTHER: 303,\n USE_PROXY: 305,\n\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n TOO_EARLY: 425,\n CONTINUE: 100,\n ACCEPTED: 202,\n CONFLICT: 409,\n CREATED: 201,\n IM_USED: 226,\n LOCKED: 423,\n FOUND: 302,\n GONE: 410,\n OK: 200,\n} as const);\n\n/**\n * HTTP status messages mapped by numeric code.\n * Use for sending descriptive text in responses or logging.\n */\nexport const HttpStatusMessage = {\n 431: 'Request Header Fields Too Large',\n 511: 'Network Authentication Required',\n 203: 'Non-Authoritative Information',\n 407: 'Proxy Authentication Required',\n 451: 'Unavailable For Legal Reasons',\n 505: 'HTTP Version Not Supported',\n 509: 'Bandwidth Limit Exceeded',\n 506: 'Variant Also Negotiates',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 428: 'Precondition Required',\n 500: 'Internal Server Error',\n 422: 'Unprocessable Entity',\n 507: 'Insufficient Storage',\n 101: 'Switching Protocols',\n 412: 'Precondition Failed',\n 421: 'Misdirected Request',\n 503: 'Service Unavailable',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 405: 'Method Not Allowed',\n 417: 'Expectation Failed',\n 301: 'Moved Permanently',\n 413: 'Payload Too Large',\n 424: 'Failed Dependency',\n 429: 'Too Many Requests',\n 208: 'Already Reported',\n 300: 'Multiple Choices',\n 402: 'Payment Required',\n 426: 'Upgrade Required',\n 206: 'Partial Content',\n 408: 'Request Timeout',\n 411: 'Length Required',\n 501: 'Not Implemented',\n 504: 'Gateway Timeout',\n 406: 'Not Acceptable',\n 205: 'Reset Content',\n 508: 'Loop Detected',\n 207: 'Multi-Status',\n 304: 'Not Modified',\n 401: 'Unauthorized',\n 414: 'URI Too Long',\n 418: \"I'm a Teapot\",\n 510: 'Not Extended',\n 103: 'Early Hints',\n 400: 'Bad Request',\n 502: 'Bad Gateway',\n 102: 'Processing',\n 204: 'No Content',\n 303: 'See Other',\n 305: 'Use Proxy',\n 403: 'Forbidden',\n 404: 'Not Found',\n 425: 'Too Early',\n 100: 'Continue',\n 202: 'Accepted',\n 226: \"I'm Used\",\n 409: 'Conflict',\n 201: 'Created',\n 423: 'Locked',\n 302: 'Found',\n 410: 'Gone',\n 200: 'OK',\n} as const;\n\nexport type HttpStatusCode = keyof typeof HttpStatusMessage;\n\nexport type HttpStatusMessage =\n (typeof HttpStatusMessage)[keyof typeof HttpStatusMessage];\n","import {\n HttpStatusCode,\n HttpStatusMessage,\n} from '@/gateway/constants/http-code';\n\ninterface ErrorParams {\n message: string;\n code: HttpStatusMessage;\n status?: HttpStatusCode;\n metadata?: Record<string, unknown> | undefined;\n isOperational?: boolean;\n cause?: Error | undefined;\n}\n\n/**\n * Abstract base class for application-level errors with structured error handling.\n *\n * Extends the native Error class to provide machine-readable error codes, HTTP status codes,\n * operational error classification, and optional metadata for better error tracking and client communication.\n *\n * @abstract\n * @extends {Error}\n *\n * @example\n * ```typescript\n * class UserNotFoundError extends ApplicationError {\n * constructor(userId: string) {\n * super({\n * code: HttpStatusMessage['404'],\n * status: 404,\n * isOperational: true,\n * message: `User with id ${userId} not found`,\n * metadata: { userId }\n * });\n * }\n * }\n * ```\n */\nexport abstract class ApplicationError extends Error {\n /** Optional cause (linked error) */\n public readonly cause?: Error | undefined;\n /** Machine-readable error code (e.g. `OTP_LOCKED`, `USER_NOT_FOUND`) */\n public readonly code: HttpStatusMessage;\n /** Operational vs programmer error flag */\n public readonly isOperational: boolean;\n /** Optional structured metadata for debugging or clients */\n public readonly metadata?: Record<string, unknown> | undefined;\n /** HTTP status code intended for response layer */\n public readonly status: HttpStatusCode;\n\n constructor({\n code = HttpStatusMessage['500'],\n isOperational = false,\n status = 500,\n metadata,\n message,\n cause,\n }: ErrorParams) {\n super(message);\n\n this.name = new.target.name;\n this.code = code;\n this.status = status;\n this.isOperational = isOperational;\n this.metadata = metadata;\n this.cause = cause;\n\n Error.captureStackTrace(this, new.target);\n }\n}\n","import deepEqual from 'fast-deep-equal/es6';\n\nimport { deepFreeze } from '@/utils/deep-freeze.util';\n\nexport abstract class ValueObject<T> {\n get value(): T {\n return this.props;\n }\n\n protected readonly props: Readonly<T>;\n\n protected constructor(props: T) {\n this.validate(props);\n this.props = deepFreeze(props);\n }\n\n /**\n * Type guard to check if an unknown object is an instance of ValueObject.\n * This is useful for runtime type checking.\n *\n * @param vo The object to check.\n * @returns True if the object is a ValueObject instance, false otherwise.\n */\n public static is(vo: unknown): vo is ValueObject<unknown> {\n return vo instanceof ValueObject;\n }\n\n /**\n * Deep equality comparison of ValueObjects\n */\n public equals(other?: ValueObject<T>): boolean {\n if (\n !other ||\n !(other instanceof (this.constructor as typeof ValueObject))\n ) {\n return false;\n }\n\n return deepEqual(this.props, other.props);\n }\n\n /**\n * Validates the value object props\n * @throws InvalidValueObjectError if validation fails\n */\n protected abstract validate(props: T): void;\n}\n","import { ValueObject } from '@/domain/base/vo';\n\nexport type UnwrapValueObject<T> =\n T extends ValueObject<infer V>\n ? UnwrapValueObject<V>\n : T extends (infer U)[]\n ? UnwrapValueObject<U>[]\n : T extends Map<infer K, infer V>\n ? Map<K, UnwrapValueObject<V>>\n : T extends Set<infer V>\n ? Set<UnwrapValueObject<V>>\n : T extends Date\n ? string\n : T extends object\n ? { [K in keyof T]: UnwrapValueObject<T[K]> }\n : T;\n\nexport function unwrapValueObject<T>(\n input: T,\n seen = new WeakSet(),\n): UnwrapValueObject<T> {\n if (input === null || input === undefined) {\n return input as UnwrapValueObject<T>;\n }\n\n if (typeof input !== 'object') {\n return input as UnwrapValueObject<T>;\n }\n\n if (seen.has(input)) {\n // Prevent circular reference infinite recursion, just return input or throw\n throw new Error('Circular reference detected in ValueObject unwrap');\n }\n\n seen.add(input);\n\n if (Array.isArray(input)) {\n const result = input.map(item => unwrapValueObject(item, seen));\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof ValueObject) {\n const result = unwrapValueObject(input.value, seen);\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof Date) {\n seen.delete(input);\n return input.toISOString() as UnwrapValueObject<T>;\n }\n\n if (input instanceof Map) {\n const result = new Map();\n input.forEach((value, key) => {\n result.set(key, unwrapValueObject(value, seen));\n });\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n if (input instanceof Set) {\n const result = new Set(\n Array.from(input.values()).map(v => unwrapValueObject(v, seen)),\n );\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n }\n\n // generic object\n const result: Record<string, unknown> = {};\n\n for (const key in input) {\n if (Object.hasOwn(input, key)) {\n result[key] = unwrapValueObject((input as any)[key], seen);\n }\n }\n\n seen.delete(input);\n return result as UnwrapValueObject<T>;\n}\n\nexport function ensureObject<T>(input: UnwrapValueObject<T>): object {\n if (input === null || input === undefined) {\n return {};\n }\n if (typeof input === 'object') {\n return input;\n }\n\n // for primitives, wrap inside object with default key (or throw)\n return { value: input };\n}\n","export interface DomainErrorMetadata {\n cause?: { name: string; message: string; stack?: string };\n [key: string]: unknown;\n}\n\nconst getCauseInfo = (cause: Error | undefined) => {\n // 1. Handle Error objects specifically\n if (cause instanceof Error) {\n return {\n cause: {\n message: cause.message,\n stack: cause.stack,\n name: cause.name,\n },\n };\n }\n\n // 2. Handle other existing values\n if (cause) {\n return { cause };\n }\n\n // 3. Default to empty\n return {};\n};\n\n/**\n * Base class for all Domain Errors in the application.\n *\n * This class ensures:\n * 1. Serializable and structured for logs or API responses.\n * 2. Identifiable via stable error codes (not just class names).\n * 3. Contextual with optional structured metadata.\n * 4. Supports error chaining (cause) and stack trace preservation.\n *\n * @example\n * export class InsufficientFundsError extends DomainError {\n * constructor(accountId: string, currentBalance: number) {\n * super(\n * `Account ${accountId} has insufficient funds.`,\n * 'INSUFFICIENT_FUNDS',\n * { accountId, currentBalance }\n * );\n * }\n * }\n */\nexport abstract class DomainError extends Error {\n /** Stable, machine-readable error code */\n public readonly code: string;\n /** Structured, immutable domain metadata */\n public readonly metadata: Readonly<DomainErrorMetadata>;\n\n /**\n * @param message - Human-readable error message\n * @param code - Stable error code\n * @param metadata - Domain-specific structured data; optional `cause` can be included\n */\n protected constructor(\n message: string,\n code: string,\n metadata: DomainErrorMetadata = {},\n ) {\n super(message, { ...getCauseInfo(metadata.cause) });\n\n // Restore prototype chain for proper `instanceof` checks\n Object.setPrototypeOf(this, new.target.prototype);\n\n this.name = new.target.name;\n this.code = code;\n this.metadata = Object.freeze({ ...metadata });\n }\n}\n","import { DomainError } from '../base/domain.error';\n\n/**\n * Custom error class for entity validation failures.\n */\nexport class EntityValidationError extends DomainError {\n constructor(message: string, cause?: Error) {\n super(message, 'ENTITY_VALIDATION_ERROR', { cause });\n }\n}\n","import { v4 } from 'uuid';\nimport z from 'zod';\n\nimport { InvalidValueObjectError } from '../errors/invalid-vo.error';\nimport { ValueObject } from '../base/vo';\n\n/**\n * AggregateId is a ValueObject that represents a unique identifier for an aggregate.\n */\nexport class AggregateId extends ValueObject<string> {\n /**\n * The schema for the AggregateId\n */\n private static readonly schema = z.uuid();\n\n /**\n * Get the UUID of the AggregateId\n * @returns The UUID of the AggregateId\n */\n public get uuid(): string {\n return this.value;\n }\n\n /**\n * Create a new AggregateId\n * @param value The value to create the AggregateId from\n * @returns The new AggregateId\n */\n public static create(value: string): AggregateId {\n return new AggregateId(value);\n }\n\n /**\n * Create a new AggregateId with a random UUID v4\n */\n public static generate(): AggregateId {\n return new AggregateId(v4());\n }\n\n /**\n * Check if the AggregateId is empty\n * @returns True if the AggregateId is empty, false otherwise\n */\n public isEmpty(): boolean {\n return !this.value;\n }\n\n /**\n * Convert the AggregateId to a string\n * @returns The string representation of the AggregateId\n */\n public toString(): string {\n return this.value;\n }\n\n /**\n * Validate the AggregateId\n * @param value The value to validate\n * @throws InvalidValueObjectException if the value is invalid\n */\n protected validate(value: string): void {\n const result = AggregateId.schema.safeParse(value);\n\n if (!result.success) {\n throw new InvalidValueObjectError(\n `Invalid AggregateId: ${result.error.message}`,\n );\n }\n }\n}\n","import { DomainError } from '../base/domain.error';\n\nexport class InvalidValueObjectError extends DomainError {\n constructor(message: string) {\n super(message, 'INVALID_VALUE_OBJECT');\n }\n}\n","import { ensureObject, UnwrapValueObject, unwrapValueObject } from '@/utils';\n\nimport { EntityValidationError } from '../errors/entity-validation.error';\nimport { AggregateId } from '../value-objects/aggregate-id.vo';\n\nexport interface EntityBaseInterface {\n id: AggregateId;\n equals: (entity: unknown) => boolean;\n}\n\n/**\n * Base properties common to all entities, including ID and timestamps.\n */\nexport interface BaseEntityProps {\n /** Unique identifier for the entity */\n id?: AggregateId;\n /** Date when the entity was created */\n createdAt: Date;\n}\n\n/**\n * Interface for constructing an entity with optional timestamps.\n * @template Props - The specific props type for the entity\n */\nexport type CreateEntityProps<T> = BaseEntityProps & {\n props: T;\n};\n\n/**\n * Abstract base class for domain entities in a Domain-Driven Design (DDD) context.\n * Provides common functionality for entity identification, equality comparison,\n * immutability, and validation. Entities extending this class must implement\n * the `validate` method to enforce domain invariants.\n * @template EntityProps - The specific props type for the entity\n */\nexport abstract class Entity<EntityProps> {\n /**\n * Returns the creation timestamp.\n * A new Date instance is returned to preserve immutability.\n *\n * @returns {Date} The creation date of the entity.\n */\n get createdAt(): Date {\n return new Date(this.#createdAt);\n }\n\n /**\n * Gets the entity's unique identifier.\n * @returns The entity's ID\n */\n get id(): AggregateId {\n return this.#id;\n }\n\n public get metadata() {\n return Object.freeze({\n createdAt: this.#createdAt.toISOString(),\n id: this.#id.uuid,\n });\n }\n\n /**\n * Returns an immutable shallow copy of the entity's properties.\n *\n * @returns {Readonly<EntityProps>} The entity domain properties.\n */\n get props(): Readonly<EntityProps> {\n return this.#props;\n }\n\n /** Private creation timestamp */\n #createdAt: Date;\n /** Private unique identifier for the entity */\n #id: AggregateId;\n /** Private entity-specific properties */\n #props: Readonly<EntityProps>;\n\n /**\n * Constructs an entity with the provided properties and timestamps.\n * Ensures immutability by cloning props and validates the entity.\n * @param params - Entity creation parameters\n * @throws EntityValidationError if the ID is empty or validation fails\n */\n protected constructor({\n createdAt,\n props,\n id,\n }: CreateEntityProps<EntityProps>) {\n if (!id) {\n throw new EntityValidationError('Entity ID cannot be empty');\n }\n\n this.#id = id ?? AggregateId.generate();\n this.#props = Object.freeze(props);\n const now = new Date();\n this.#createdAt = createdAt ? new Date(createdAt) : now;\n }\n\n /**\n * Checks if the provided value is an instance of Entity.\n * @param entity - The value to check\n * @returns True if the value is an Entity instance\n */\n static isEntity(entity: unknown): entity is EntityBaseInterface {\n return (\n typeof entity === 'object' &&\n entity !== null &&\n 'id' in entity &&\n typeof (entity as any).equals === 'function'\n );\n }\n\n /**\n * Compares this entity with another to determine if they are the same.\n * Equality is based on the entity ID.\n * @param other - The entity to compare with\n * @returns True if the entities have the same ID\n */\n public equals(other?: Entity<EntityProps>): boolean {\n if (!other || !Entity.isEntity(other)) {\n return false;\n }\n\n return this.#id.equals(other.#id);\n }\n\n /**\n * Returns a frozen copy of the entity's properties, including base properties.\n * Ensures immutability by returning a new object.\n * @returns A frozen copy of the entity's properties\n */\n public getPropsCopy(): Readonly<EntityProps> {\n return Object.freeze(this.#props);\n }\n\n /**\n * Determines if the entity is transient, i.e., it has not been persisted yet.\n * By convention, an entity is considered transient if it lacks a valid identifier.\n * This can be useful when performing logic that depends on persistence state,\n * such as conditional inserts or validations that only apply to new entities.\n *\n * @returns True if the entity is transient (not persisted), otherwise false.\n */\n public isPersisted(): boolean {\n return this.#id.isEmpty();\n }\n\n public toJSON(): Record<string, unknown> {\n return this.toObject();\n }\n\n public toObject(): Readonly<\n UnwrapValueObject<EntityProps> & { createdAt: string; id: string }\n > {\n const props = unwrapValueObject(this.getPropsCopy());\n const safeProps = ensureObject(props);\n return Object.freeze({\n ...this.metadata,\n ...safeProps,\n }) as Readonly<\n UnwrapValueObject<EntityProps> & { createdAt: string; id: string }\n >;\n }\n\n /**\n * Validates the entity's state to enforce domain invariants.\n * Must be implemented by subclasses to define specific validation rules.\n * @throws EntityValidationError if validation fails\n */\n public abstract validate(): void;\n}\n","import { AggregateId } from '../value-objects/aggregate-id.vo';\nimport { Entity } from '../entities/entity';\nimport { DomainEvent } from '../events';\n\n/**\n * Interface for AggregateRoot to ensure type safety and extensibility.\n */\nexport interface AggregateRootInterface {\n readonly id: AggregateId;\n readonly domainEvents: readonly DomainEvent[];\n /**\n * Validates the aggregate's invariants.\n * @throws {EntityValidationError} If validation fails.\n */\n validate: () => void;\n /**\n * Adds a domain event to the aggregate.\n * @param event The domain event to add.\n */\n addEvent: (event: DomainEvent) => void;\n\n /**\n * Retrieves and clears all domain events recorded by this aggregate.\n *\n * Domain events represent facts that occurred as a result of state changes\n * within the aggregate. This method transfers ownership of those events\n * to the application layer for further processing (e.g. publishing).\n *\n * Calling this method has the side effect of clearing the aggregate's\n * internal event collection to prevent duplicate handling.\n *\n * This method is intended to be invoked by application services\n * after the aggregate has been successfully persisted.\n *\n * @returns A read-only list of domain events raised by this aggregate.\n */\n pullDomainEvents: () => readonly DomainEvent[];\n}\n\n/**\n * Base class for aggregate roots in DDD, encapsulating domain events and validation.\n * @template EntityProps The type of the entity's properties.\n */\nexport abstract class AggregateRoot<EntityProps>\n extends Entity<EntityProps>\n implements AggregateRootInterface\n{\n /**\n * Gets a read-only copy of the domain events.\n */\n get domainEvents(): readonly DomainEvent[] {\n return [...this._domainEvents];\n }\n\n /**\n * Internal list of domain events.\n */\n private readonly _domainEvents: DomainEvent[] = [];\n\n /**\n * Adds a domain event to the aggregate after validating invariants.\n * @param domainEvent The domain event to add.\n * @throws {EntityValidationError} If invariants are not met.\n */\n addEvent(domainEvent: DomainEvent): void {\n this.validate(); // Ensure invariants before adding events\n this._domainEvents.push(domainEvent);\n }\n\n public pullDomainEvents(): readonly DomainEvent[] {\n const events = [...this._domainEvents];\n this._domainEvents.length = 0;\n return events;\n }\n\n /**\n * Validates the entity's invariants.\n * @throws {EntityValidationError} If validation fails.\n */\n abstract validate(): void;\n}\n","type Primitive = boolean | number | string | null;\n\ntype Serializable =\n | Primitive\n | Serializable[]\n | { [key: string]: Serializable };\n\nexport type DomainEventPayload = Record<string, Serializable>;\n\ntype DomainEventProps<T> = {\n id: string;\n aggregateId: string;\n schemaVersion: number;\n occurredAt: number;\n payload: T;\n};\n\n// Abstract base class for domain events\nexport abstract class DomainEvent<\n T extends DomainEventPayload = DomainEventPayload,\n> {\n public abstract readonly eventName: string;\n\n public readonly id: string;\n public readonly aggregateId: string;\n public readonly schemaVersion: number;\n public readonly occurredAt: number;\n public readonly payload: Readonly<T>;\n\n protected constructor(props: DomainEventProps<T>) {\n this.id = props.id;\n this.aggregateId = props.aggregateId;\n this.schemaVersion = props.schemaVersion;\n this.occurredAt = props.occurredAt;\n this.payload = Object.freeze(props.payload);\n }\n\n public toPrimitives() {\n return {\n schemaVersion: this.schemaVersion,\n aggregateId: this.aggregateId,\n occurredAt: this.occurredAt,\n eventName: this.eventName,\n payload: this.payload,\n id: this.id,\n };\n }\n}\n"],"mappings":"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","names":["deepFreeze","obj","seen","item","key","HttpStatus","HttpStatusMessage","ApplicationError","code","HttpStatusMessage","isOperational","status","metadata","message","cause","deepEqual","ValueObject","_ValueObject","props","deepFreeze","vo","other","deepEqual","unwrapValueObject","input","seen","result","item","ValueObject","value","key","v","ensureObject","getCauseInfo","cause","DomainError","message","code","metadata","__spreadValues","EntityValidationError","DomainError","message","cause","v4","z","InvalidValueObjectError","DomainError","message","_AggregateId","ValueObject","value","v4","result","InvalidValueObjectError","z","AggregateId","_createdAt","_id","_props","_Entity","createdAt","props","id","__privateAdd","EntityValidationError","__privateSet","AggregateId","__privateGet","entity","other","unwrapValueObject","safeProps","ensureObject","__spreadValues","Entity","AggregateRoot","Entity","domainEvent","events","DomainEvent","props"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rineex/ddd",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Domain Driven Design package for Rineex core modules",
5
5
  "author": "Rineex Team",
6
6
  "main": "./dist/index.js",
@@ -24,8 +24,8 @@
24
24
  "vite-tsconfig-paths": "6.0.2",
25
25
  "vitest": "4.0.16",
26
26
  "zod": "4.2.1",
27
- "@rineex/eslint-config": "0.0.0",
28
- "@rineex/typescript-config": "0.0.0"
27
+ "@rineex/typescript-config": "0.0.0",
28
+ "@rineex/eslint-config": "0.0.0"
29
29
  },
30
30
  "keywords": [
31
31
  "rineex",
@@ -46,6 +46,7 @@
46
46
  "dependencies": {
47
47
  "fast-deep-equal": "3.1.3",
48
48
  "isbot": "5.1.32",
49
+ "rxjs": "7.8.2",
49
50
  "ua-parser-js": "2.0.7",
50
51
  "uuid": "13.0.0",
51
52
  "zod": "4.2.1"