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 🙏

© 2026 – Pkg Stats / Ryan Hefner

simple-cqrs

v2.1.0

Published

A simple CQRS implementation for node.

Readme

Simple, small and flexible CQRS for node.

NPM Version Downloads Build Status Coverage Status Known Vulnerabilities

Installation

$ npm install simple-cqrs

Quick Start

const cqrs = require('simple-cqrs')
const app = cqrs.createApp()

app.useCommandHandler('showMessageCommand', (command) => {
	app.publish({ type: 'messageDisplayedEvent', message: command.message })
})

app.useEventHandler((event) => {
	console.log(`Message ${event.message} displayed.`)
}, 'messageDisplayedEvent')


app.send({ type: 'showMessageCommand', message: 'Hello World!' })

Download the example at examples/simple-app

Introduction

There are two ways to use Simple-CQRS library. The easier, showed in Quick Start section above and the flexible that will be show in the Docs section. Both use a set of classes included in core module, but the easier uses a mediator cqrs.createApp() to coordinate the access of those core classes.

Contents

Docs

Commands

You can use a json-based style command or a type-based command, the only requirement is to set the type of command:

//json-based
const command = {type:'showMessageCommand', message:'Hello World!'};

When you use type-based command, you don't have to set the type manually. It's automatically set by Command class. The type will be the name of the subclass.

//type-based using Ecma6
const { Command } = require('simple-cqrs')

class ShowMessageCommand extends Command{
  get message(){return this._message;}
  set message(value){this._message=value;}
}

//the type of above class is "ShowMessageCommand"

CommandDispatcher as a default CommandBus

A command bus is responsible for routing the command to the handler that will execute it. The CommandBus class is just an abstraction of a command bus and mustn't be instantiated.

You can implement a command bus by extending it. e.g: You can send a command through an Azure Service Bus Queue following this documentation: How to use Service Bus queues

If you just want to handle/execute a command in the same proccess, you can use the CommandDispatcher class included in the core:

const { CommandDispatcher } = require('simple-cqrs')
const dispatcher = new CommandDispatcher();

The first thing you must do is register a handler for a command. You can register a function to handle the command, or a command handler type-based:

//Registering a function as a handler of the ShowMessageCommand. 
dispatcher.register('ShowMessageCommand', (command)=>{
  console.log(command);
});

//Registering a command handler as a handler of the ShowMessageCommand. 
dispatcher.register('ShowMessageCommand', {factory:()=> {
  return new ShowMessageCommandHandler();
	}
});

You can't register a command twice. But you can register multiple commands for a handler:

//Registering multiple commands for a function.
dispatcher.register(['ShowMessageCommand','ClearConsoleCommand'], (command)=>{
  switch(command.type){
    case 'ShowMessageCommand':
      console.log(command.message);
      break;
    case 'ClearConsoleCommand':
      console.clear();
      break;
    default:
      throw Error(`Command ${command.type} can\'t be handled.`)
  }
});

Events

Just as commands, events also can use a json-based style or a type-based, the only requirement is to set the type of event:

//json-based
const event = {type:'messageDisplayedEvent', message:'Hello World!'};

When you use type-based, you don't have to set the type manually. It's automatically set by Event class. The type will be the name of the subclass.

//type-based using Ecma6
const { Event } = require('simple-cqrs')

class MessageDisplayedEvent extends Event {
  get message(){return this._message;}
  set message(value){this._message=value;}
}

//the type of above class is "MessageDisplayedEvent"

EventDispatcher as a default EventBus

Event bus is responsible to distribute the events to their handlers/listeners. It's a publish/subscribe communication pattern. The EventBus class is just an abstraction of an event bus and mustn't be instantiated.

You can implement your own event bus by extending the EventBus class. Just like CommanbBus, you can listen an infrastructure messaging component as an Azure Service Bus or RabbitMQ.

If you just want to handle/listen events in the same proccess, you can use the EventDispatcher class included in the core.

const { EventDispatcher } = require('simple-cqrs')
const dispatcher = new EventDispatcher();

The first thing you must do is register a handler for an event. You can register a function to handles the events, or a event handler type-based:

//Registering a function as a handler of the MessageDisplayedEvent. 
dispatcher.register((event)=>{
  console.log(event);
}, 'MessageDisplayedEvent');

//Registering a event handler as a handler of the MessageDisplayedEvent. 
const MessageDisplayedEventHandler = class MessageDisplayedEventHandler extends EventHandler {
	constructor() {
		super()
		this.register('MessageDisplayedEvent', handler)
	}
	handle(event) {
		console.log(`Event ${event.type} handled`)
		}
}

const eventHandler = new MessageDisplayedEventHandler()

dispatcher.register(eventHandler, 'MessageDisplayedEvent');

Tests & Coverage

To run the test suite against simple-cqrs or check coverage, first install the dependencies, then run npm test:

$ npm install
$ npm test
$ npm run cover

We're using mocha, chai and sinon for testing and istanbul for coverage

Contributing

Feel free to make changes!

License

MIT License

Copyright (c) 2017 rmelo

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.