Coder Social home page Coder Social logo

michalpaszkiewicz / cqrs-react-router Goto Github PK

View Code? Open in Web Editor NEW
84.0 7.0 4.0 123 KB

A cqrs/event sourcing library built directly into a router you can use in your react application

Home Page: http://www.michalpaszkiewicz.co.uk/cqrs-react-router/

License: MIT License

JavaScript 0.52% TypeScript 99.48%
cqrs router typescript frontend react ddd ddd-patterns event-sourcing

cqrs-react-router's Introduction

cqrs-react-router

cqrs-react-router is a library that will help you easily set up a CQRS/event sourcing system

Build Status npm version

typescript support

cqrs-react-router is written in typescript and therefore will always support typescript

how to contribute

feel free to submit pull requests, just please provide clear notes as to what your update will change. Pull requests that cause tests to fail will not be accepted.

how to install

you will need npm. Then install this library with

npm install cqrs-react-router

cqrs

to start writing your own typescript cqrs application, you will need an application service, to which you register command handlers and views

import {ApplicationService, IAmACommandHandler, DomainService, IAmACommand, View, AggregateRoot} from "cqrs-react-router";

class SomeView extends View{
    name = "SomeView"; // subscribers can get updates for this view

    stuff = 0;

    handle(event: IAmADomainEvent){
        var self = this;
        switch(event.name){
            case "SomeEvent":
                self.stuff++;
                return;
        }
    }
}

export class SomeAggregateRoot extends AggregateRoot{
    doStuff(command){
        //do something
    }

    applyEvent(event){
        switch(event.Name){
            //when action applied, do something here
            default:
                return;
        }
    }
}

class SomeCommandHandler implements IAmACommandHandler{

    commandNames = ["SomeCommand"]; // this handler will handle commands with these names

    handle(command, domainService: DomainService, callback: () => void){
        domainService.getAggregateRoot(SomeAggregateRoot, (someAggregateRoot: SomeAggregateRoot) => {
            someAggregateRoot.doStuff(command);
        }, "someAggregateID");
    }
}

var appService = ApplicationService.Instance;

appService.registerCommandHandler(SomeCommandHandler);
appService.registerView(SomeView);

To subscriber to a view

appService.subscribe("SomeView", (view: SomeView) => {
    //do something with the new view;
});

To handle a command

appService.handleCommand(new SomeCommand())

To validate a command from views

class TestCommandValidator extends CommandValidator{

    commandNames = [COMMAND_NAME];

    validate(command: IAmACommand){
        // getViewByName fetches view from application service
        this.getViewByName(viewName, (view: TestView)=> {
            if(view.hasSomeUnexpectedValue){
                throw new DomainError("oh noes, I didn't expect that!");
            }
        });
    }
}
ApplicationService.Instance.registerCommandValidator(TestCommandValidator);

router

use just like react-router, only it will inject an application service that you can subscribe to.

import {Router, Route, ApplicationService, Page} from "cqrs-react-router";

class SomePage extends Page<any, any>{
    render(){
        return (
            <div>
                Some stuff
            </div>
        )
    }
}

export class App extends React.Component<AppProps, AppState>{
    render(){
        return (
            <Router applicationService={new ApplicationService()}>
                <Route path="/" component={SomePage} />
            </Router>
        )
    }
}

replay events!

testApplicationService.replayEvents();

apply events from external sources

testApplicationService.storeEvent(new TestEvent("123"));

latest changes

The latest changes can be found in the Wiki.

cqrs-react-router's People

Contributors

michalpaszkiewicz avatar sdaves avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

cqrs-react-router's Issues

'event' not defined for Link

export class Link extends React.Component<LinkProps, null>{
    private _handleClick = (e) => {
        var self = this;
        if(self.props.onClick){
            self.props.onClick(e);
        }
        event.preventDefault()
        if(self.props.to){
            ApplicationService.Instance.handleCommand(new NavigateToPageCommand(self.props.to));
        }
    }
    render(){
        const {to, children} = this.props;

        return (
            <a className={this.props.className + " cqrs-link"} style={{cursor:"pointer"}} onClick={(e) => this._handleClick(e)}>
                {children}
            </a>
        )
    }
}

should be e.preventDefault

Allow handling of domain errors if they occur in aggregate root

It should be possible to handle errors that occur in aggregate root e.g. via

ApplicationService.Instance.onDomainError(callback: (error: DomainError) => void);

If this method has not been called, the service should still throw an error, but once there is a handler, this should process all domain errors.

Allow unsubscribe from view

When a component is unmounted, the update of a view should no longer try to set state on that component.

It should therefore be possible to unsubscribe from a view

Reset events in eventStore on hard replay

When hardReplay is triggered in the Application Service, AggregateRoots are reset, but the eventStore's list of events remains unchanged.

A hard replay should force the event store to only contain the replayed events.

Initial call of subscribe should trigger the callback

When someone is subscribing to a view, the callback should be called straight away after subscription is done.

If the user has subscribed to a view before the view has been registered, there should be no trigger.

If there are subscribers for a view before the view has been registered, at the time that the view is registered, the subscribers should have their callback triggered.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.