eventric
Version:
Build JavaScript applications with Behaviour-driven Domain Design. Based on DDD, BDD, CQRS and EventSourcing.
256 lines (225 loc) • 8.26 kB
JavaScript
var Eventric, promise,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__slice = [].slice;
promise = require('es6-promise');
if ((typeof module !== 'undefined') && (typeof process !== 'undefined')) {
global.Promise = promise.Promise;
}
Eventric = (function() {
function Eventric() {
this._handleRemoteRPCRequest = __bind(this._handleRemoteRPCRequest, this);
this._contexts = {};
this._params = {};
this._domainEventHandlers = {};
this._domainEventHandlersAll = [];
this._processManagerService = require('eventric/src/process_manager');
this._processManagerInstances = {};
this._storeClasses = {};
this._remoteEndpoints = [];
this.log = require('eventric/src/logger');
this.addRemoteEndpoint('inmemory', (require('eventric/src/remote/inmemory')).endpoint);
this.addStore('inmemory', require('eventric/src/store_inmemory'));
this.set('default domain events store', 'inmemory');
}
Eventric.prototype.set = function(key, value) {
return this._params[key] = value;
};
Eventric.prototype.get = function(key) {
if (!key) {
return this._params;
} else {
return this._params[key];
}
};
Eventric.prototype.addStore = function(storeName, StoreClass, storeOptions) {
if (storeOptions == null) {
storeOptions = {};
}
return this._storeClasses[storeName] = {
Class: StoreClass,
options: storeOptions
};
};
Eventric.prototype.getStores = function() {
return this._storeClasses;
};
/**
*
* @description Get a new context instance.
*
* @param {String} name Name of the context
*/
Eventric.prototype.context = function(name) {
var Context, context, err;
if (!name) {
err = 'Contexts must have a name';
this.log.error(err);
throw new Error(err);
}
Context = require('eventric/src/context');
context = new Context(name);
this._delegateAllDomainEventsToGlobalHandlers(context);
this._delegateAllDomainEventsToRemoteEndpoints(context);
this._contexts[name] = context;
return context;
};
Eventric.prototype.getContext = function(name) {
return this._contexts[name];
};
Eventric.prototype.remote = function(contextName) {
var Remote, err, remote;
if (!contextName) {
err = 'Missing context name';
this.log.error(err);
throw new Error(err);
}
Remote = require('eventric/src/remote');
remote = new Remote(contextName);
return remote;
};
Eventric.prototype.addRemoteEndpoint = function(remoteName, remoteEndpoint) {
this._remoteEndpoints.push(remoteEndpoint);
return remoteEndpoint.setRPCHandler(this._handleRemoteRPCRequest);
};
Eventric.prototype._handleRemoteRPCRequest = function(request, callback) {
var context, err;
context = this.getContext(request.contextName);
if (!context) {
err = "Tried to handle Remote RPC with not registered context " + request.contextName;
this.log.error(err);
return callback(err, null);
}
if (!(request.method in context)) {
err = "Remote RPC method " + request.method + " not found on Context " + request.contextName;
this.log.error(err);
return callback(err, null);
}
return context[request.method].apply(context, request.params).then(function(result) {
return callback(null, result);
})["catch"](function(error) {
return callback(error);
});
};
Eventric.prototype._delegateAllDomainEventsToGlobalHandlers = function(context) {
return context.subscribeToAllDomainEvents((function(_this) {
return function(domainEvent) {
var eventHandler, eventHandlers, _i, _len, _results;
eventHandlers = _this.getDomainEventHandlers(context.name, domainEvent.name);
_results = [];
for (_i = 0, _len = eventHandlers.length; _i < _len; _i++) {
eventHandler = eventHandlers[_i];
_results.push(eventHandler(domainEvent));
}
return _results;
};
})(this));
};
Eventric.prototype._delegateAllDomainEventsToRemoteEndpoints = function(context) {
return context.subscribeToAllDomainEvents((function(_this) {
return function(domainEvent) {
return _this._remoteEndpoints.forEach(function(remoteEndpoint) {
remoteEndpoint.publish(context.name, domainEvent.name, domainEvent);
if (domainEvent.aggregate) {
return remoteEndpoint.publish(context.name, domainEvent.name, domainEvent.aggregate.id, domainEvent);
}
});
};
})(this));
};
/**
*
* @description Global DomainEvent Handlers
*
* @param {String} contextName Name of the context or 'all'
* @param {String} eventName Name of the Event or 'all'
* @param {Function} eventHandler Function which handles the DomainEvent
*/
Eventric.prototype.subscribeToDomainEvent = function() {
var contextName, eventHandler, eventName, _arg, _base, _base1, _i;
_arg = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), eventHandler = arguments[_i++];
contextName = _arg[0], eventName = _arg[1];
if (contextName == null) {
contextName = 'all';
}
if (eventName == null) {
eventName = 'all';
}
if (contextName === 'all' && eventName === 'all') {
return this._domainEventHandlersAll.push(eventHandler);
} else {
if ((_base = this._domainEventHandlers)[contextName] == null) {
_base[contextName] = {};
}
if ((_base1 = this._domainEventHandlers[contextName])[eventName] == null) {
_base1[eventName] = [];
}
return this._domainEventHandlers[contextName][eventName].push(eventHandler);
}
};
Eventric.prototype.getDomainEventHandlers = function(contextName, domainEventName) {
var _ref, _ref1, _ref2, _ref3, _ref4;
return [].concat((_ref = (_ref1 = this._domainEventHandlers[contextName]) != null ? _ref1[domainEventName] : void 0) != null ? _ref : [], (_ref2 = (_ref3 = this._domainEventHandlers[contextName]) != null ? _ref3.all : void 0) != null ? _ref2 : [], (_ref4 = this._domainEventHandlersAll) != null ? _ref4 : []);
};
Eventric.prototype.generateUid = function(separator) {
var S4, delim;
S4 = function() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
};
delim = separator || "-";
return S4() + S4() + delim + S4() + delim + S4() + delim + S4() + delim + S4() + S4() + S4();
};
/**
*
* @description Global Process Manager
*
* @param {String} processManagerName Name of the ProcessManager
* @param {Object} processManagerObject Object containing `initializeWhen` and `class`
*/
Eventric.prototype.addProcessManager = function(processManagerName, processManagerObj) {
return this._processManagerService.add(processManagerName, processManagerObj, this);
};
Eventric.prototype.nextTick = function(next) {
var nextTick, _ref;
nextTick = (_ref = typeof process !== "undefined" && process !== null ? process.nextTick : void 0) != null ? _ref : setTimeout;
return nextTick(function() {
return next();
});
};
Eventric.prototype.defaults = function(options, optionDefaults) {
var allKeys, key, _i, _len;
allKeys = [].concat(Object.keys(options), Object.keys(optionDefaults));
for (_i = 0, _len = allKeys.length; _i < _len; _i++) {
key = allKeys[_i];
if (!options[key] && optionDefaults[key]) {
options[key] = optionDefaults[key];
}
}
return options;
};
Eventric.prototype.eachSeries = function(arr, iterator, callback) {
var completed, iterate;
callback = callback || function() {};
if (!Array.isArray(arr) || !arr.length) {
return callback();
}
completed = 0;
iterate = function() {
iterator(arr[completed], function(err) {
if (err) {
callback(err);
callback = function() {};
} else {
++completed;
if (completed >= arr.length) {
callback();
} else {
iterate();
}
}
});
};
return iterate();
};
return Eventric;
})();
module.exports = new Eventric;