Not released yet. This hint will disappear with version 0.1.0.

eventric.js 
Build web applications based on Domain-driven Design and Layered Architecture.
Runs on NodeJS and modern Browsers. Therefore it's easy to share code between Server and Client. Information regarding the API and more can be found in the Wiki.
Why?
It is an alternative to MVC+CRUD Frameworks where you put a lot of effort into defining your data structure and so often end up with an anemic domain model on larger projects.
How?
Basically you define queries
and commands
on BoundedContexts
. The commands
can result in series of DomainEvents
consisting of properties that changed inside affected Aggregates
. These DomainEvents
represent the state of your domain model. DomainEvents
get either persisted directly into the EventStore
or send over a RemoteService
first. The RemoteService
can also be used to execute queries
and commands
remotely. This makes eventric.js really useful for distributed applications.
Philosophy
Quick Start
Having discussed the upcoming TodoApp Project with the Business-Experts and fellow Developers it got clear that we should start with a BoundedContext
named Collaboration
.
Hint: You should npm install eventric
and npm install eventric-store-mongodb
first.
Let's get right into it and create our BoundedContext
eventric = require('eventric');
collaborationContext = eventric.boundedContext();
Now that we created the collaborationContext
let's add our Todo
Aggregate, consisting of a simple changeDescription
method.
collaborationContext.addAggregate('Todo', {
changeDescription: function(description) {
this.description = description;
}
});
Hint: values assigned to this.
are automatically part of the generated DomainEvent
To actually work with the BoundedContext
from the outside world we need commands
and queries
. Let's start by adding a simple command
that will create an instance of our Todo
Aggregate.
collaborationContext.addCommand('createTodo', function(params, callback) {
this.aggregate.create('Todo', callback);
});
Hint: this.aggregate
is dependency injected
It would be nice if we could change the description of the Todo
, so let's add this command
too.
collaborationContext.addCommand('changeTodoDescription', function(params, callback) {
this.aggregate.command('Todo', params.id, 'changeDescription', params.description, callback);
});
Hint: If successful this will trigger a Todo:changeDescription DomainEvent
And last but not least we want the ability to query
for a Todo
by its id.
collaborationContext.addQuery('getTodoById', function(params, callback) {
this.repository('Todo').findById(params.id, callback);
});
Hint: this.repository
is dependency injected
Initialize the collaborationContext
, create a Todo
, change the description of it and finally query the description again.
collaborationContext.initialize(function() {
collaborationContext.command({
name: 'createTodo'
},
function(err, todoId) {
collaborationContext.command({
name: 'changeTodoDescription',
params: {
id: todoId,
description: 'Do something'
}
},
function(err, status) {
collaborationContext.query({
name: 'getTodoById',
params: {
id: todoId
}
},
function(err, readTodo) {
console.log(readTodo.description);
})
});
});
});
eventric
will implement promises to avoid such a "Pyramid of Doom" in the future.
This will output Do something
. Your Todo
Aggregate is now persisted using EventSourcing.
Congratulations, you have successfully applied DDD (tactical+technical) and CQRS! :)
Running Tests
To execute all (client+server) tests, use:
gulp spec
You can watch for file-changes with
NODE_ENV=workstation gulp watch
License
MIT
Copyright (c) 2013-2014 SixSteps Team, eFa GmbH