4lessandrodev / rich-domain

A lib to help you create a robust project based on domain driven-design (ddd) principles with typescript and zero dependencies.
https://www.npmjs.com/package/rich-domain
MIT License
122 stars 5 forks source link

Example: Domain Event Subscriptions with new TsEvents #134

Closed mmmoli closed 4 months ago

mmmoli commented 6 months ago

Playing with the new TsEvent api.

Looks like it supersedes your finance-app example.

Any tips for how to make subscriptions with the new API?

Thanks!

4lessandrodev commented 6 months ago

Hey @mmmoli , thanks for reaching out! Since the "finance project", the library has undergone several upgrades, particularly in event handling. Take a look at the new approach for the eventHandler in this example. There are various ways to add an event to the aggregate, but instead of dealing with global events, I suggest utilizing events directly within the aggregate instance. Check out this example to see how to add an event to an aggregate instance.

I hope this clears things up a bit. Feel free to ask if you have any further questions.

mmmoli commented 6 months ago

Buddy, I've studied your examples at length… 👀😄

They've been a huge help.

I'm looking for advice for subscribing to these Domain Events within a different bounded context/module. Hoping to set-up a "pull" mechanism rather than "push"

Do I need to add an external event Bus? Should I dispatch these event inside the dispatch of the Event handler? 🙃

4lessandrodev commented 6 months ago

Absolutely, glad to hear the examples have been helpful!

For subscribing to Domain Events across different bounded contexts/modules with a "pull" mechanism, you typically need to establish communication between these contexts.

For handling events across different modules with a "pull" mechanism, consider leveraging the Node.js Event emitter. Similar to how events are handled in browser-based JavaScript, Node.js offers the EventEmitter class within its events module.

4lessandrodev commented 6 months ago

Testing something new

@mmmoli Your question made me think a lot about the need for a tool that facilitates communication between contexts. Currently, the way it is structured, it is not possible to meet this requirement. That's why I'm thinking about implementing something similar to the draft below


import { Aggregate, Ok, Result, Context } from "rich-domain";

type Props = { name: string };

class User extends Aggregate<Props>{
    private constructor(props: Props) {
        super(props);
    }

    public static signUp(name: string): User {
        return new User({ name });
    }

    public static create(props: Props): Result<User> {
        return Ok(new User(props));
    }
}

// ------------
// Any Context - Subscribe
const context = Context.events();

type Model = { id: string; name: string; createdAt: Date; updatedAt: Date };

context.subscribe('signUp', (user: Model) => {
    console.log(user));
});

// ------------
// Account Context - Dispatch to Global Event
const user = User.signUp('Jane Doe');

context.dispatchEvent('signUp', user.toObject());
image

Challenges

mmmoli commented 6 months ago

Love this. It's easy to see how I'd use it in the projects I'm building.

Definitely keep me posted on this.

4lessandrodev commented 6 months ago

Some Points

For browser the lib add a CustomEvent to dom as global identified by provided name.

the aggregate continues to have event management methods, these must be used for business rules of the context in which the aggregate is inserted

when triggering the event by the aggregate, the event for the global context will not be triggered automatically, it must be triggered by the handler or directly by the context event manually

the type of object to be sent in the parameters will be dynamic, and it is up to the developer to decide which type to send

I'm still going to investigate

4lessandrodev commented 6 months ago

Testing version 1.20.3-beta.1

Browser Support:

164c85ba-91b4-4711-bdf5-d1ae2343b244

Github Project Sample

4lessandrodev commented 6 months ago

Testing version 1.20.3-beta.1

Server NodeJS support

image

GIthub Project Sample