curli-bus
Version:
Simple Command Bus Implementation (CQRS) for NodeJS/Typescript.
309 lines (188 loc) • 6.9 kB
Markdown
[](https://travis-ci.com/github/CarlosCraviotto/curli-bus)
[](https://coveralls.io/github/CarlosCraviotto/curli-bus?branch=master)
Simple Command/Query/Event Bus Implementation to use with CQRS or DDD for NodeJS/Typescript.
There are a lot of bus CQRS libraries for JavaScript/Typescript out there, this is not new. The one thing we're trying to achieve here is the ability to take advantage of such a library but without coupling it into the application's domain. The main goal here is to create a library that you can use without using third part code into your domains.
Install by `npm`
```sh
npm install --save curli-bus
```
```typescript
import {CommandBusSync, CommandInstanceType} from "curli-bus";
class CommandTest {
public constructor (private name: string){
}
}
const commandBus = new CommandBusSync();
bus.registerHandler(CommandTest, function (command: CommandInstanceType): any {
container.get('useCase').execute(command);
});
const commandTest = new CommandTest('test');
bus.dispatch(commandTest);
```
```typescript
bus.registerHandler('CommandTest', function (command: CommandInstanceType): any {
container.get('useCase').execute(command);
});
const commandTest = new CommandTest('test');
bus.dispatch(commandTest);
```
We can send options to the handler through all the middleware.
```typescript
bus.registerHandler('CommandTest', function (command: CommandInstanceType, options?: any): any {
container.get('useCase').execute(command, options);
});
bus.dispatch(commandTest, {"dev": true});
```
```typescript
import {BusSync, CommandInstanceType, Middleware} from "curli-bus";
class CommandTest {
public constructor (private name: string){
}
public addToName (toAdd: string) {
this.name = this.name + ' - ' + toAdd + ' -';
}
}
class MiddlewareTest extends Middleware {
execute (command: CommandInstanceType, next: (a: any) => any): any {
command.addToName('preHandler');
command = next(command);
command.addToName('postHandler');
return command;
}
}
const bus = new BusSync();
const commandTest = new CommandTest('test');
bus.addMiddleware(new MiddlewareTest());
bus.registerHandler(CommandTest, function (command: CommandInstanceType): any {
command.addToName('hendler');
container.get('useCase').execute(command);
});
commandTest = bus.dispatch(commandTest);
console.log(commandTest.name);
//test - preHandler - hendler - postHandler -
```
```typescript
import {QueryBusSync, QueryInstanceType} from "curli-bus";
class QueryTest {
public constructor (private query: object){
}
}
const queryBus = new QueryBusSync();
bus.registerHandler(QueryTest, function (query: QueryInstanceType): any {
container.get('useCase').execute(query);
});
const queryTest = new QueryTest({'name': 'test'});
const result = bus.ask(queryTest);
```
```typescript
bus.registerHandler('QueryTest', function (query: QueryInstanceType): any {
container.get('useCase').execute(query);
});
const queryTest = new QueryTest({'name': 'test'});
const result = bus.ask(queryTest);
```
We can send options to the handler through all the middleware.
```typescript
bus.registerHandler('QueryTest', function (query: QueryInstanceType, options?: any): any {
container.get('useCase').execute(query, options);
});
const result = bus.ask(queryTest, {"dev": true});
```
```typescript
import {BusSync, QueryInstanceType, Middleware} from "curli-bus";
class QueryTest {
public constructor (private name: string){
}
public addToName (toAdd: string) {
this.name = this.name + ' - ' + toAdd + ' -';
}
}
class MiddlewareTest extends Middleware {
execute (query: QueryInstanceType, next: (a: any) => any): any {
query.addToName('preHandler');
query = next(query);
query.addToName('postHandler');
return query;
}
}
const bus = new BusSync();
const queryTest = new QueryTest('test');
bus.addMiddleware(new MiddlewareTest());
bus.registerHandler(QueryTest, function (query: QueryInstanceType): any {
query.addToName('hendler');
container.get('useCase').execute(query);
});
const result = bus.ask(queryTest);
console.log(result.name);
//test - preHandler - hendler - postHandler -
```
We can create an event bus and send events throw it.
```typescript
import {EventBus} from "curli-bus";
class UserCreatedEvent {
public eventName = 'user_created';
public dateTimeOccurred?: Date;
public constructor(public data: {[key:string]: any}) {
}
}
class OnUserCreatedEventSubscriber {
public getEventName(): string {
return 'user_created';
}
public handle (event: Event): any{
//... Do stuff with the event
}
}
const eventBus = new EventBus();
eventBus.register(new OnUserCreatedEventSubscriber());
const event = new UserCreatedEvent(
{userName: 'Josh', email:'josh@notexist.com'}
);
eventBus.publish(event);
```
- `npm run build`: Build the project (Bus).
- `npm run build:clean`: Delete first the dist folder and build it.
- `npm run clean`: Delete the dist folder.
- `npm run test`: Execute the tests.
- `npm run test:coverage`: Execute the tests and calculate the coverage.
- `npm run lint`: Check the code using the rules in .eslintre.js
- `npm run lint:fix`: Check the code and try to fix it.
#### Contributing
When submitting your pull-request try to follow those guides:
- https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github
- https://medium.com/@vadimdemedes/making-your-first-contribution-de6576ddb190
### Changelog
All notable changes to this project will be documented in this section.
### 0.2.1
#### Changed
- Expose Event interface and EventSubscriber type
### 0.2.0
#### Added
- Support publish multiple events (array) in event bus.
### 0.1.0
#### Added
- Event bus support
### 0.0.2
#### Added
- QueryBusSync support
#### Changed
- BusSync interface will be CommandBusSync
### 0.0.1
#### Added
- CommandBusSync support
#### License
MIT