npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@alejandrodk/nestjs-event-bus

v1.0.3

Published

A simple and lightweight event bus module for Nest Framework

Downloads

9

Readme

Nestjs Event-Driven Bus module

Simple, easy and lightweight package for implement Event-Driven bus in a NestJs Project using reactive programming (RxJs) 🚀

npm package

Usage

1- Install package

npm install nestjs-event-driven-bus
# or
yarn add nestjs-event-driven-bus

2- Import EventBusModule

Import the EventBusModule in the module where you want to dispatch events.

@Module({
  imports: [EventBusModule],
  ...
})

For example, assuming you are making a products application.

@Module({
  imports: [EventBusModule],
  controllers: [ProductsController],
  providers: [ProductsService],
  exports: [ProductsService]
})
export class ProductsModule {}

3- Define Events

Following the previous example, we create an event to update the stock of a product with each sale.

# src/events/products.events.ts

export class UpdateStockEvent {
  constructor(public product: string, public quantity: number) {}
}

4- Define Event handler

The event handler is a class in charge of reacting to events of a specific type, it must implement the methods defined in the IEventHandler interface. *The event handler class must extends the IEventHandler interface

class UpdateStockEventHandler implements IEventHandler

An event handler must have two required methods (handle, error) and one optional method (complete). The handle method will be in charge of receiving the event, as you should imagine, the error method will receive events if an error occurs, this will allow you to apply certain logic to handle certain cases. The complete method is optional, as it is only executed once the event transmission is complete.

interface IEventHandler {
  handle: (event: any) => void;
  error: (event: any) => void;
  complete?: () => void;
}

To link an event handler with an event, we apply the HandleEvent decorator on the class, it receives the class of the event it wants to react to.

@HandleEvent(UpdateStockEvent)

The event handlers be Dependency Injection friendly, so you can import injected dependencies into the class constructor as always.

constructor(private productsService: ProductsService){}
# or
constructor(@Inject() someDependency: SomeDependency) {}

Finally, our Event handler class must looks like

# src/handlers/products.handlers.ts

@HandleEvent(UpdateStockEvent)
export class UpdateStockEventHandler implements IEventHandler {
  constructor(private productsService: ProductsService){}
  handle(event: UpdateStockEvent) {
    console.log('Hello from handler!!!', UpdateStockEventHandler.name)
    this.productsService.someMethod()...
    #do something business logic...
  }
  error(error: any) {
     #do something...
  }
}

5- Import Event Handlers in your module

In your events handlers file, you must to export and array with all handlers, or if you preferred, import all of then in the target module, but the first option is the cleanest and easiest way.

# src/handlers/products.handlers.ts

export const ProductsEventsHandlers = [
  UpdateStockEventHandler, 
  someEventHandler, 
  AnotherEventHandler
]

then, simply import the array of Event Handlers in providers array.

@Module({
  imports: [EventBusModule],
  controllers: [ProductsController],
  providers: [ProductsRepository, ProductsService, ...ProductsEventsHandlers],
  exports: [ProductsService]
})
export class ProductsModule {}

6- Dispatch events 🚀

In our controller (or wherever you need to produce events), you only need to import the EventBus class, the EventBus class has the Publish, PublishError and Complete methods, which we will use to produce new events.

# src/controllers/products.controller.ts

@Controller('products')
export class ProductsController {
  constructor(private service: ProductsService, private eventBus: EventBus) {}
}

To produce a new event, all we have to do is publish a new event using the Publish method. *The publish method receives an event instance and its name.

 @Get('sell/:id')
  sellProduct(@Param('id') id: string, @Query() queryParams: any): void {
    const { client, quantity } = queryParams;
    this.eventBus.publish(new UpdateStockEvent(id, client, +quantity))
  }

To inform our event handler of an error, we can do so using the PublishError method.

 @Get('sell/:id')
  sellProduct(@Param('id') id: string, @Query() queryParams: any): void {
    const { client, quantity } = queryParams;
    try {
        # some logic here....
        this.eventBus.publish(new UpdateStockEvent(id, client, +quantity))
        # more logic....
    } catch (err) {
        this.eventBus.publishError(error, UpdateStockEvent.name)
    }
  }

One event, many handlers

By implementing an event architecture, your application will be able to react to different events, keeping the components of your application completely decoupled.

Going back to the example of a product store, you could have an event called SellProductEvent, and for the same event have different event handlers, for example:

starting from the event:

# src/events/products.events.ts

export class SellProductEvent {
  constructor(public productID: string, public quantity: number, public client: string) {}
}

we can have these different event handlers:

# src/handlers/products.handlers.ts

@HandleEvent(SellProductEvent)
export class SellProductEventHandler implements IEventHandler {
  constructor(private productsService: ProductsService){}
  handle(event: SellProductEvent) {
    #process sell...
  }
}

@HandleEvent(SellProductEvent)
export class SendEmailToClient implements IEventHandler {
  constructor(private emailTransport: EmailTransport){}
  handle({ client }: SellProductEvent) {
    #send email to client...
    this.emailTransport.newSellEmail(client)...
  }
}

@HandleEvent(SellProductEvent)
export class UpdateStock implements IEventHandler {
  constructor(private productsService: ProductsService){}
  handle({ productID, quantity }: SellProductEvent) {
    #update product stock...
    this.productsService.updateProductStock(productID, quantity)...
  }
}

Look how each event is independent of the others.

TEST

Disable the event bus in test environments with DISABLE_EVENT_HANDLING env variable.