@@ -367,9 +367,175 @@ console.log(result.toObject());
367367
368368```
369369
370- ---
371370
372- ### See also how to use Aggregate.
371+ ### Aggregate
372+
373+ Encapsulate and are composed of entity classes and value objects that change together in a business transaction
374+
375+ #### Create an aggregate to compose your context.
376+
377+ In my example, let's use the context of payment. All payment transactions are encapsulated by an order (payment order) that represents a user's purchasing context.
378+
379+ ``` ts
380+
381+ import { Aggregate , Ok , Fail , Result , UID , EventHandler } from ' types-ddd' ;
382+
383+ // Entities and VO that encapsulate context.
384+ interface Props {
385+ id? : UID ;
386+ payment: Payment ;
387+ items: List <Item >;
388+ status: OrderStatus ;
389+ customer: Customer ;
390+ }
391+
392+ // Simple example of an order aggregate encapsulating entities and
393+ // value objects for context.
394+ export default class Order extends Aggregate <Props > {
395+
396+ // Private constructor to ensure instances creation through static methods.
397+ private constructor (props : Props ){
398+ super (props );
399+ }
400+
401+ // Static method to begin a new order.
402+ // Takes a customer as parameter and returns an instance of Order.
403+ public static begin(customer : Customer ): Order {
404+ // Initialize the status of the order as "begin".
405+ const status = OrderStatus .begin ();
406+ // Initialize the list of items as empty.
407+ const items: List <Item > = List .empty ();
408+ // Initialize the payment as zero, since the order hasn't been paid yet.
409+ const payment = Payment .none ();
410+ // Create a new instance of Order with the provided parameters.
411+ const order = new Order ({ status , payment , items , customer });
412+
413+ // Add an event to indicate that the order has begun.
414+ order .addEvent (' ORDER_HAS_BEGUN' , (order ) => {
415+ // Perform some important operation when the order begins.
416+ console .log (' Do something important...' );
417+ });
418+
419+ // Alternatively, add an event by creating an
420+ // instance of a class that extends EventHandler.
421+ order .addEvent (new OrderBeganEventHandler ());
422+
423+ // Return the created order instance.
424+ return order ;
425+ }
426+
427+ // Method to add an item to the order.
428+ // Takes an item as parameter and returns the Order instance.
429+ addItem(item : Item ): Order {
430+ // Add the item to the order's items list.
431+ this .props .items .add (item );
432+ // Sum item price to payment amount
433+ this .props .payment .sum (item .price );
434+ // Return the Order instance itself to allow chained calls.
435+ return this ;
436+ }
437+
438+ // Method to perform the payment of the order.
439+ // Takes a payment object as parameter.
440+ pay(payment : Payment ): Order {
441+ // Set the status of the order to "paid".
442+ this .props .status = OrderStatus .paid ();
443+ // Set the provided payment object.
444+ this .props .payment = payment ;
445+ // Add an event to indicate that the order has been paid.
446+ // Assuming OrderPaidEvent is a class representing
447+ // the event of order payment.
448+ this .addEvent (new OrderPaidEventHandler ());
449+ return this ;
450+ }
451+
452+ // Static method to create an instance of Order.
453+ // Returns a Result, which can be Ok (success) or Fail (failure).
454+ // The value of the Result is an instance of Order,
455+ // if creation is successful.
456+ public static create(props : Props ): Result <Order > {
457+ return Ok (new Order (props ));
458+ }
459+ }
460+
461+ ```
462+
463+ #### How to use events
464+
465+ Event Handler
466+
467+ ``` ts
468+
469+ import { Context , EventHandler } from ' rich-domain' ;
470+
471+
472+ class OrderCreatedEvent extends EventHandler <Order > {
473+
474+ constructor () {
475+ super ({ eventName: ' OrderCreated' });
476+ }
477+
478+ dispatch(order : Order ): void {
479+ // dispatch event to another context
480+ order .context ().dispatchEvent (' Context:Event' , order .toObject ());
481+ };
482+ }
483+
484+ ```
485+
486+ Aggregates domain events
487+
488+
489+ ``` ts
490+
491+ order .addEvent (' Event' , (... args ) => {
492+ console .log (args );
493+ });
494+
495+ // Or add an EventHandler instance
496+ order .addEvent (new OrderCreatedEvent ());
497+
498+ order .dispatchEvent (' OrderBegun' );
499+
500+ // dispatch with args
501+ order .dispatchEvent (' Event' , { info: ' custom_args' });
502+
503+ // OR call all added events
504+ await order .dispatchAll ();
505+
506+
507+ ```
508+
509+ #### How to subscribe to a global event
510+
511+ ``` ts
512+
513+ import { Context } from ' rich-domain' ;
514+
515+ const context = Context .events ();
516+
517+ context .subscribe (' Context:Event' , (event ) => {
518+ const [model] = event .detail ;
519+ console .log (model );
520+ });
521+
522+ // dispatch an event to a context with args
523+ context .dispatchEvent (' Context:Event' , { name: ' Jane' });
524+
525+ // Dispatching events to specific contexts
526+ // Dispatches the SIGNUP event to Context-X
527+ context .dispatchEvent (' Context-X:Signup' );
528+
529+ // Dispatches the SIGNUP event to all contexts
530+ context .dispatchEvent (' *:Signup' );
531+
532+ // Dispatches all events to all contexts. Not recommended
533+ context .dispatchEvent (' *:*' );
534+
535+ // Dispatches all events under Context-Y
536+ context .dispatchEvent (' Context-Y:*' );
537+
538+ ```
373539
374540## Lib Full Documentation
375541
0 commit comments