UNPKG

eventric

Version:

Build JavaScript applications with Behaviour-driven Domain Design. Based on DDD, BDD, CQRS and EventSourcing.

1,683 lines (1,436 loc) 176 kB
(function() { 'use strict'; var globals = typeof window === 'undefined' ? global : window; if (typeof globals.require === 'function') return; var _definedModules = {}; var _aliases = {}; var Module = { _load: function(request, parent) { var name = Module._resolveFilename(request, parent); var definition = _definedModules[name]; if (!definition) throw new Error('Cannot find module "' + name + '" from '+ '"' + parent + '"'); if (Module._cache[name]) return Module._cache[name].exports; var localRequire = createLocalRequire(name); var module = {id: name, exports: {}}; Module._cache[name] = module; definition.call(module.exports, module.exports, localRequire, module); return module.exports; }, _cache: {}, // TODO: Implement this to behave more like the Node environment _resolveFilename: function(request, parent) { var path = expand(dirname(parent), request); if (_definedModules.hasOwnProperty(path)) return path; path = expand(path, './index'); if (_definedModules.hasOwnProperty(path)) return path; return request; } }; var require = function(name, loaderPath) { return Module._load(name, loaderPath); }; var expand = (function() { var reg = /^\.\.?(\/|$)/; return function(root, name) { var results = [], parts, part; parts = (reg.test(name) ? root + '/' + name : name).split('/'); for (var i = 0, length = parts.length; i < length; i++) { part = parts[i]; if (part === '..') { results.pop(); } else if (part !== '.' && part !== '') { results.push(part); } } return results.join('/'); }; })(); var createLocalRequire = function(parent) { return function(name) { return globals.require(name, parent); }; }; var dirname = function(path) { if (!path) return ''; return path.split('/').slice(0, -1).join('/'); }; require.register = require.define = function(bundle, fn) { if (typeof bundle === 'object') { for (var key in bundle) { if (bundle.hasOwnProperty(key)) { _definedModules[key] = bundle[key]; } } } else { _definedModules[bundle] = fn; } }; require.list = function() { var result = []; for (var item in _definedModules) { if (_definedModules.hasOwnProperty(item)) { result.push(item); } } return result; }; globals.require = require; require.define('module', function(exports, require, module) { module.exports = Module; }); })(); require.register("eventric/index", function(exports, require, module){ module.exports = require('./src'); }); require.register("es6-promise", function(exports, require, module){ (function() { var define, requireModule, require, requirejs; (function() { var registry = {}, seen = {}; define = function(name, deps, callback) { registry[name] = { deps: deps, callback: callback }; }; requirejs = require = requireModule = function(name) { requirejs._eak_seen = registry; if (seen[name]) { return seen[name]; } seen[name] = {}; if (!registry[name]) { throw new Error("Could not find module " + name); } var mod = registry[name], deps = mod.deps, callback = mod.callback, reified = [], exports; for (var i=0, l=deps.length; i<l; i++) { if (deps[i] === 'exports') { reified.push(exports = {}); } else { reified.push(requireModule(resolve(deps[i]))); } } var value = callback.apply(this, reified); return seen[name] = exports || value; function resolve(child) { if (child.charAt(0) !== '.') { return child; } var parts = child.split("/"); var parentBase = name.split("/").slice(0, -1); for (var i=0, l=parts.length; i<l; i++) { var part = parts[i]; if (part === '..') { parentBase.pop(); } else if (part === '.') { continue; } else { parentBase.push(part); } } return parentBase.join("/"); } }; })(); define("promise/all", ["./utils","exports"], function(__dependency1__, __exports__) { "use strict"; /* global toString */ var isArray = __dependency1__.isArray; var isFunction = __dependency1__.isFunction; /** Returns a promise that is fulfilled when all the given promises have been fulfilled, or rejected if any of them become rejected. The return promise is fulfilled with an array that gives all the values in the order they were passed in the `promises` array argument. Example: ```javascript var promise1 = RSVP.resolve(1); var promise2 = RSVP.resolve(2); var promise3 = RSVP.resolve(3); var promises = [ promise1, promise2, promise3 ]; RSVP.all(promises).then(function(array){ // The array here would be [ 1, 2, 3 ]; }); ``` If any of the `promises` given to `RSVP.all` are rejected, the first promise that is rejected will be given as an argument to the returned promises's rejection handler. For example: Example: ```javascript var promise1 = RSVP.resolve(1); var promise2 = RSVP.reject(new Error("2")); var promise3 = RSVP.reject(new Error("3")); var promises = [ promise1, promise2, promise3 ]; RSVP.all(promises).then(function(array){ // Code here never runs because there are rejected promises! }, function(error) { // error.message === "2" }); ``` @method all @for RSVP @param {Array} promises @param {String} label @return {Promise} promise that is fulfilled when all `promises` have been fulfilled, or rejected if any of them become rejected. */ function all(promises) { /*jshint validthis:true */ var Promise = this; if (!isArray(promises)) { throw new TypeError('You must pass an array to all.'); } return new Promise(function(resolve, reject) { var results = [], remaining = promises.length, promise; if (remaining === 0) { resolve([]); } function resolver(index) { return function(value) { resolveAll(index, value); }; } function resolveAll(index, value) { results[index] = value; if (--remaining === 0) { resolve(results); } } for (var i = 0; i < promises.length; i++) { promise = promises[i]; if (promise && isFunction(promise.then)) { promise.then(resolver(i), reject); } else { resolveAll(i, promise); } } }); } __exports__.all = all; }); define("promise/asap", ["exports"], function(__exports__) { "use strict"; var browserGlobal = (typeof window !== 'undefined') ? window : {}; var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; var local = (typeof global !== 'undefined') ? global : (this === undefined? window:this); // node function useNextTick() { return function() { process.nextTick(flush); }; } function useMutationObserver() { var iterations = 0; var observer = new BrowserMutationObserver(flush); var node = document.createTextNode(''); observer.observe(node, { characterData: true }); return function() { node.data = (iterations = ++iterations % 2); }; } function useSetTimeout() { return function() { local.setTimeout(flush, 1); }; } var queue = []; function flush() { for (var i = 0; i < queue.length; i++) { var tuple = queue[i]; var callback = tuple[0], arg = tuple[1]; callback(arg); } queue = []; } var scheduleFlush; // Decide what async method to use to triggering processing of queued callbacks: if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') { scheduleFlush = useNextTick(); } else if (BrowserMutationObserver) { scheduleFlush = useMutationObserver(); } else { scheduleFlush = useSetTimeout(); } function asap(callback, arg) { var length = queue.push([callback, arg]); if (length === 1) { // If length is 1, that means that we need to schedule an async flush. // If additional callbacks are queued before the queue is flushed, they // will be processed by this flush that we are scheduling. scheduleFlush(); } } __exports__.asap = asap; }); define("promise/config", ["exports"], function(__exports__) { "use strict"; var config = { instrument: false }; function configure(name, value) { if (arguments.length === 2) { config[name] = value; } else { return config[name]; } } __exports__.config = config; __exports__.configure = configure; }); define("promise/polyfill", ["./promise","./utils","exports"], function(__dependency1__, __dependency2__, __exports__) { "use strict"; /*global self*/ var RSVPPromise = __dependency1__.Promise; var isFunction = __dependency2__.isFunction; function polyfill() { var local; if (typeof global !== 'undefined') { local = global; } else if (typeof window !== 'undefined' && window.document) { local = window; } else { local = self; } var es6PromiseSupport = "Promise" in local && // Some of these methods are missing from // Firefox/Chrome experimental implementations "resolve" in local.Promise && "reject" in local.Promise && "all" in local.Promise && "race" in local.Promise && // Older version of the spec had a resolver object // as the arg rather than a function (function() { var resolve; new local.Promise(function(r) { resolve = r; }); return isFunction(resolve); }()); if (!es6PromiseSupport) { local.Promise = RSVPPromise; } } __exports__.polyfill = polyfill; }); define("promise/promise", ["./config","./utils","./all","./race","./resolve","./reject","./asap","exports"], function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { "use strict"; var config = __dependency1__.config; var configure = __dependency1__.configure; var objectOrFunction = __dependency2__.objectOrFunction; var isFunction = __dependency2__.isFunction; var now = __dependency2__.now; var all = __dependency3__.all; var race = __dependency4__.race; var staticResolve = __dependency5__.resolve; var staticReject = __dependency6__.reject; var asap = __dependency7__.asap; var counter = 0; config.async = asap; // default async is asap; function Promise(resolver) { if (!isFunction(resolver)) { throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); } if (!(this instanceof Promise)) { throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); } this._subscribers = []; invokeResolver(resolver, this); } function invokeResolver(resolver, promise) { function resolvePromise(value) { resolve(promise, value); } function rejectPromise(reason) { reject(promise, reason); } try { resolver(resolvePromise, rejectPromise); } catch(e) { rejectPromise(e); } } function invokeCallback(settled, promise, callback, detail) { var hasCallback = isFunction(callback), value, error, succeeded, failed; if (hasCallback) { try { value = callback(detail); succeeded = true; } catch(e) { failed = true; error = e; } } else { value = detail; succeeded = true; } if (handleThenable(promise, value)) { return; } else if (hasCallback && succeeded) { resolve(promise, value); } else if (failed) { reject(promise, error); } else if (settled === FULFILLED) { resolve(promise, value); } else if (settled === REJECTED) { reject(promise, value); } } var PENDING = void 0; var SEALED = 0; var FULFILLED = 1; var REJECTED = 2; function subscribe(parent, child, onFulfillment, onRejection) { var subscribers = parent._subscribers; var length = subscribers.length; subscribers[length] = child; subscribers[length + FULFILLED] = onFulfillment; subscribers[length + REJECTED] = onRejection; } function publish(promise, settled) { var child, callback, subscribers = promise._subscribers, detail = promise._detail; for (var i = 0; i < subscribers.length; i += 3) { child = subscribers[i]; callback = subscribers[i + settled]; invokeCallback(settled, child, callback, detail); } promise._subscribers = null; } Promise.prototype = { constructor: Promise, _state: undefined, _detail: undefined, _subscribers: undefined, then: function(onFulfillment, onRejection) { var promise = this; var thenPromise = new this.constructor(function() {}); if (this._state) { var callbacks = arguments; config.async(function invokePromiseCallback() { invokeCallback(promise._state, thenPromise, callbacks[promise._state - 1], promise._detail); }); } else { subscribe(this, thenPromise, onFulfillment, onRejection); } return thenPromise; }, 'catch': function(onRejection) { return this.then(null, onRejection); } }; Promise.all = all; Promise.race = race; Promise.resolve = staticResolve; Promise.reject = staticReject; function handleThenable(promise, value) { var then = null, resolved; try { if (promise === value) { throw new TypeError("A promises callback cannot return that same promise."); } if (objectOrFunction(value)) { then = value.then; if (isFunction(then)) { then.call(value, function(val) { if (resolved) { return true; } resolved = true; if (value !== val) { resolve(promise, val); } else { fulfill(promise, val); } }, function(val) { if (resolved) { return true; } resolved = true; reject(promise, val); }); return true; } } } catch (error) { if (resolved) { return true; } reject(promise, error); return true; } return false; } function resolve(promise, value) { if (promise === value) { fulfill(promise, value); } else if (!handleThenable(promise, value)) { fulfill(promise, value); } } function fulfill(promise, value) { if (promise._state !== PENDING) { return; } promise._state = SEALED; promise._detail = value; config.async(publishFulfillment, promise); } function reject(promise, reason) { if (promise._state !== PENDING) { return; } promise._state = SEALED; promise._detail = reason; config.async(publishRejection, promise); } function publishFulfillment(promise) { publish(promise, promise._state = FULFILLED); } function publishRejection(promise) { publish(promise, promise._state = REJECTED); } __exports__.Promise = Promise; }); define("promise/race", ["./utils","exports"], function(__dependency1__, __exports__) { "use strict"; /* global toString */ var isArray = __dependency1__.isArray; /** `RSVP.race` allows you to watch a series of promises and act as soon as the first promise given to the `promises` argument fulfills or rejects. Example: ```javascript var promise1 = new RSVP.Promise(function(resolve, reject){ setTimeout(function(){ resolve("promise 1"); }, 200); }); var promise2 = new RSVP.Promise(function(resolve, reject){ setTimeout(function(){ resolve("promise 2"); }, 100); }); RSVP.race([promise1, promise2]).then(function(result){ // result === "promise 2" because it was resolved before promise1 // was resolved. }); ``` `RSVP.race` is deterministic in that only the state of the first completed promise matters. For example, even if other promises given to the `promises` array argument are resolved, but the first completed promise has become rejected before the other promises became fulfilled, the returned promise will become rejected: ```javascript var promise1 = new RSVP.Promise(function(resolve, reject){ setTimeout(function(){ resolve("promise 1"); }, 200); }); var promise2 = new RSVP.Promise(function(resolve, reject){ setTimeout(function(){ reject(new Error("promise 2")); }, 100); }); RSVP.race([promise1, promise2]).then(function(result){ // Code here never runs because there are rejected promises! }, function(reason){ // reason.message === "promise2" because promise 2 became rejected before // promise 1 became fulfilled }); ``` @method race @for RSVP @param {Array} promises array of promises to observe @param {String} label optional string for describing the promise returned. Useful for tooling. @return {Promise} a promise that becomes fulfilled with the value the first completed promises is resolved with if the first completed promise was fulfilled, or rejected with the reason that the first completed promise was rejected with. */ function race(promises) { /*jshint validthis:true */ var Promise = this; if (!isArray(promises)) { throw new TypeError('You must pass an array to race.'); } return new Promise(function(resolve, reject) { var results = [], promise; for (var i = 0; i < promises.length; i++) { promise = promises[i]; if (promise && typeof promise.then === 'function') { promise.then(resolve, reject); } else { resolve(promise); } } }); } __exports__.race = race; }); define("promise/reject", ["exports"], function(__exports__) { "use strict"; /** `RSVP.reject` returns a promise that will become rejected with the passed `reason`. `RSVP.reject` is essentially shorthand for the following: ```javascript var promise = new RSVP.Promise(function(resolve, reject){ reject(new Error('WHOOPS')); }); promise.then(function(value){ // Code here doesn't run because the promise is rejected! }, function(reason){ // reason.message === 'WHOOPS' }); ``` Instead of writing the above, your code now simply becomes the following: ```javascript var promise = RSVP.reject(new Error('WHOOPS')); promise.then(function(value){ // Code here doesn't run because the promise is rejected! }, function(reason){ // reason.message === 'WHOOPS' }); ``` @method reject @for RSVP @param {Any} reason value that the returned promise will be rejected with. @param {String} label optional string for identifying the returned promise. Useful for tooling. @return {Promise} a promise that will become rejected with the given `reason`. */ function reject(reason) { /*jshint validthis:true */ var Promise = this; return new Promise(function (resolve, reject) { reject(reason); }); } __exports__.reject = reject; }); define("promise/resolve", ["exports"], function(__exports__) { "use strict"; function resolve(value) { /*jshint validthis:true */ if (value && typeof value === 'object' && value.constructor === this) { return value; } var Promise = this; return new Promise(function(resolve) { resolve(value); }); } __exports__.resolve = resolve; }); define("promise/utils", ["exports"], function(__exports__) { "use strict"; function objectOrFunction(x) { return isFunction(x) || (typeof x === "object" && x !== null); } function isFunction(x) { return typeof x === "function"; } function isArray(x) { return Object.prototype.toString.call(x) === "[object Array]"; } // Date.now is not available in browsers < IE9 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility var now = Date.now || function() { return new Date().getTime(); }; __exports__.objectOrFunction = objectOrFunction; __exports__.isFunction = isFunction; __exports__.isArray = isArray; __exports__.now = now; }); requireModule('promise/polyfill').polyfill(); }()); }); require.register("eventric/src/index", function(exports, require, module){ 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; }); require.register("eventric/src/index.spec", function(exports, require, module){ describe('Index', function() { describe('#context', function() { var contextInstance, contextStub; contextInstance = null; contextStub = null; beforeEach(function() { contextInstance = { subscribeToAllDomainEvents: sandbox.stub() }; contextStub = sandbox.stub().returns(contextInstance); return mockery.registerMock('eventric/src/context', contextStub); }); it('should throw an error if no name given for the context', function() { return expect(function() { return new eventric.context; }).to["throw"](Error); }); it('should create a context instance', function() { var someContext; someContext = eventric.context('someContext'); return expect(contextStub).to.have.been.calledWithNew; }); return it('should register global domain event handlers on the context', function() { var someContext; someContext = eventric.context('someContext'); return expect(contextInstance.subscribeToAllDomainEvents).to.have.been.called; }); }); return describe('#set/#get', function() { it('should save given key/value pairs', function() { var key, value; key = Math.random(); value = Math.random(); eventric.set(key, value); return expect(eventric.get(key)).to.equal(value); }); it('should return undefined for a not set key', function() { var key; key = Math.random(); return expect(eventric.get(key)).to.not.exist; }); return it('should overwrite already defined values', function() { var key; key = Math.random(); eventric.set(key, '1'); eventric.set(key, '2'); return expect(eventric.get(key)).to.equal('2'); }); }); }); }); require.register("eventric/src/logger", function(exports, require, module){ module.exports = { _logLevel: 1, setLogLevel: function(logLevel) { return this._logLevel = (function() { switch (logLevel) { case 'debug': return 0; case 'warn': return 1; case 'info': return 2; case 'error': return 3; } })(); }, debug: function() { if (this._logLevel > 0) { return; } return console.log.apply(console, arguments); }, warn: function() { if (this._logLevel > 1) { return; } return console.log.apply(console, arguments); }, info: function() { if (this._logLevel > 2) { return; } return console.log.apply(console, arguments); }, error: function() { if (this._logLevel > 3) { return; } return console.log.apply(console, arguments); } }; }); require.register("eventric/src/store_inmemory", function(exports, require, module){ var InMemoryStore, STORE_SUPPORTS, __slice = [].slice; STORE_SUPPORTS = ['domain_events', 'projections']; InMemoryStore = (function() { function InMemoryStore() {} InMemoryStore.prototype._domainEvents = {}; InMemoryStore.prototype._projections = {}; InMemoryStore.prototype.initialize = function() { var callback, options, _arg, _contextName, _i; _contextName = arguments[0], _arg = 3 <= arguments.length ? __slice.call(arguments, 1, _i = arguments.length - 1) : (_i = 1, []), callback = arguments[_i++]; this._contextName = _contextName; options = _arg[0]; this._domainEventsCollectionName = "" + this._contextName + ".DomainEvents"; this._projectionCollectionName = "" + this._contextName + ".Projections"; this._domainEvents[this._domainEventsCollectionName] = []; return callback(); }; InMemoryStore.prototype.saveDomainEvent = function(domainEvent, callback) { this._domainEvents[this._domainEventsCollectionName].push(domainEvent); return callback(null, domainEvent); }; InMemoryStore.prototype.findAllDomainEvents = function(callback) { return callback(null, this._domainEvents[this._domainEventsCollectionName]); }; InMemoryStore.prototype.findDomainEventsByName = function(name, callback) { var checkFn, events; if (name instanceof Array) { checkFn = function(eventName) { return (name.indexOf(eventName)) > -1; }; } else { checkFn = function(eventName) { return eventName === name; }; } events = this._domainEvents[this._domainEventsCollectionName].filter(function(event) { return checkFn(event.name); }); return callback(null, events); }; InMemoryStore.prototype.findDomainEventsByNameAndAggregateId = function(name, aggregateId, callback) { var checkAggregateIdFn, checkNameFn, events; if (name instanceof Array) { checkNameFn = function(eventName) { return (name.indexOf(eventName)) > -1; }; } else { checkNameFn = function(eventName) { return eventName === name; }; } if (aggregateId instanceof Array) { checkAggregateIdFn = function(eventAggregateId) { return (aggregateId.indexOf(eventAggregateId)) > -1; }; } else { checkAggregateIdFn = function(eventAggregateId) { return eventAggregateId === aggregateId; }; } events = this._domainEvents[this._domainEventsCollectionName].filter(function(event) { var _ref; return (checkNameFn(event.name)) && (checkAggregateIdFn((_ref = event.aggregate) != null ? _ref.id : void 0)); }); return callback(null, events); }; InMemoryStore.prototype.findDomainEventsByAggregateId = function(aggregateId, callback) { var checkFn, events; if (aggregateId instanceof Array) { checkFn = function(eventAggregateId) { return (aggregateId.indexOf(eventAggregateId)) > -1; }; } else { checkFn = function(eventAggregateId) { return eventAggregateId === aggregateId; }; } events = this._domainEvents[this._domainEventsCollectionName].filter(function(event) { var _ref; return checkFn((_ref = event.aggregate) != null ? _ref.id : void 0); }); return callback(null, events); }; InMemoryStore.prototype.findDomainEventsByAggregateName = function(aggregateName, callback) { var checkFn, events; if (aggregateName instanceof Array) { checkFn = function(eventAggregateName) { return (aggregateName.indexOf(eventAggregateName)) > -1; }; } else { checkFn = function(eventAggregateName) { return eventAggregateName === aggregateName; }; } events = this._domainEvents[this._domainEventsCollectionName].filter(function(event) { var _ref; return checkFn((_ref = event.aggregate) != null ? _ref.name : void 0); }); return callback(null, events); }; InMemoryStore.prototype.getProjectionStore = function(projectionName, callback) { var _base, _base1, _name; if ((_base = this._projections)[_name = this._projectionCollectionName] == null) { _base[_name] = {}; } if ((_base1 = this._projections[this._projectionCollectionName])[projectionName] == null) { _base1[projectionName] = {}; } return callback(null, this._projections[this._projectionCollectionName][projectionName]); }; InMemoryStore.prototype.clearProjectionStore = function(projectionName, callback) { var _base, _base1, _name; if ((_base = this._projections)[_name = this._projectionCollectionName] == null) { _base[_name] = {}; } if ((_base1 = this._projections[this._projectionCollectionName])[projectionName] == null) { _base1[projectionName] = {}; } delete this._projections[this._projectionCollectionName][projectionName]; return callback(null, null); }; InMemoryStore.prototype.checkSupport = function(check) { return (STORE_SUPPORTS.indexOf(check)) > -1; }; return InMemoryStore; })(); module.exports = InMemoryStore; }); require.register("eventric/src/context/context", function(exports, require, module){ var Context, DomainEvent, EventBus, PubSub, Repository, eventric, projectionService, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; eventric = require('eventric'); Repository = require('eventric/src/context/repository'); DomainEvent = require('eventric/src/context/domain_event'); EventBus = require('eventric/src/event_bus'); PubSub = require('eventric/src/pub_sub'); projectionService = require('eventric/src/projection'); Context = (function(_super) { __extends(Context, _super); function Context(name) { this.name = name; this.clearProjectionStore = __bind(this.clearProjectionStore, this); this.getProjectionStore = __bind(this.getProjectionStore, this); this.publishDomainEvent = __bind(this.publishDomainEvent, this); this.emitDomainEvent = __bind(this.emitDomainEvent, this); Context.__super__.constructor.apply(this, arguments); this._initialized = false; this._params = eventric.get(); this._di = {}; this._aggregateRootClasses = {}; this._adapterClasses = {}; this._adapterInstances = {}; this._commandHandlers = {}; this._queryHandlers = {}; this._domainEventClasses = {}; this._domainEventHandlers = {}; this._projectionClasses = []; this._repositoryInstances = {}; this._domainServices = {}; this._storeClasses = {}; this._storeInstances = {}; this._eventBus = new EventBus; } Context.prototype.log = eventric.log; /** * @name set * * @module Context * * @description * > Use as: set(key, value) * Configure settings for the `context`. * * @example exampleContext.set 'store', StoreAdapter * * @param {Object} key * Available keys are: `store` Eventric Store Adapter */ Context.prototype.set = function(key, value) { this._params[key] = value; return this; }; Context.prototype.get = function(key) { return this._params[key]; }; /** * @name emitDomainEvent * * @module Context * * @description emit Domain Event in the context * * @param {String} domainEventName Name of the DomainEvent * @param {Object} domainEventPayload payload for the DomainEvent */ Context.prototype.emitDomainEvent = function(domainEventName, domainEventPayload) { var DomainEventClass, domainEvent; DomainEventClass = this.getDomainEvent(domainEventName); if (!DomainEventClass) { throw new Error("Tried to emitDomainEvent '" + domainEventName + "' which is not defined"); } domainEvent = this._createDomainEvent(domainEventName, DomainEventClass, domainEventPayload); return this.getDomainEventsStore().saveDomainEvent(domainEvent, (function(_this) { return function() { return _this.publishDomainEvent(domainEvent, function() {}); }; })(this)); }; Context.prototype.publishDomainEvent = function(domainEvent, callback) { if (callback == null) { callback = function() {}; } return this._eventBus.publishDomainEvent(domainEvent, callback); }; Context.prototype._createDomainEvent = function(domainEventName, DomainEventClass, domainEventPayload) { return new DomainEvent({ id: eventric.generateUid(), name: domainEventName, context: this.name, payload: new DomainEventClass(domainEventPayload) }); }; Context.prototype.addStore = function(storeName, StoreClass, storeOptions) { if (storeOptions == null) { storeOptions = {}; } this._storeClasses[storeName] = { Class: StoreClass, options: storeOptions }; return this; }; /** * @name defineDomainEvent * * @module Context * * @description * Adds a DomainEvent Class which will be used when emitting or handling DomainEvents inside of Aggregates, Projectionpr or ProcessManagers * * @param {String} domainEventName Name of the DomainEvent * @param {Function} DomainEventClass DomainEventClass */ Context.prototype.defineDomainEvent = function(domainEventName, DomainEventClass) { this._domainEventClasses[domainEventName] = DomainEventClass; return this; }; Context.prototype.defineDomainEvents = function(domainEventClassesObj) { var DomainEventClass, domainEventName; for (domainEventName in domainEventClassesObj) { DomainEventClass = domainEventClassesObj[domainEventName]; this.defineDomainEvent(domainEventName, DomainEventClass); } return this; }; /** * @name addCommandHandler * * @module Context * * @dscription * Use as: addCommandHandler(commandName, commandFunction) * * Add Commands to the `context`. These will be available to the `command` method after calling `initialize`. * * @example ```javascript exampleContext.addCommandHandler('someCommand', function(params, callback) { // ... }); ``` * @param {String} commandName Name of the command * * @param {String} commandFunction Gets `this.aggregate` dependency injected * `this.aggregate.command(params)` Execute command on Aggregate * * `params.name` Name of the Aggregate * * `params.id` Id of the Aggregate * * `params.methodName` MethodName inside the Aggregate * * `params.methodParams` Array of params which the specified AggregateMethod will get as function signature using a [splat](http://stackoverflow.com/questions/6201657/what-does-splats-mean-in-the-coffeescript-tutorial) * * `this.aggregate.create(params)` Execute command on Aggregate * * `params.name` Name of the Aggregate to be created * * `params.props` Initial properties so be set on the Aggregate or handed to the Aggregates create() method */ Context.prototype.addCommandHandler = function(commandHandlerName, commandHandlerFn) { this._commandHandlers[commandHandlerName] = (function(_this) { return function() { var command, diFn, diFnName, repositoryCache, _di, _ref, _ref1; command = { id: eventric.generateUid(), name: commandHandlerName, params: (_ref = arguments[0]) != null ? _ref : null }; _di = {}; _ref1 = _this._di; for (diFnName in _ref1) { diFn = _ref1[diFnName]; _di[diFnName] = diFn; } repositoryCache = null; _di.$repository = function(aggregateName) { var AggregateRoot, repository; if (!repositoryCache) { AggregateRoot = _this._aggregateRootClasses[aggregateName]; repository = new Repository({ aggregateName: aggregateName, AggregateRoot: AggregateRoot, context: _this }); repositoryCache = repository; } repositoryCache.setCommand(command); return repositoryCache; }; return commandHandlerFn.apply(_di, arguments); }; })(this); return this; }; Context.prototype.addCommandHandlers = function(commandObj) { var commandFunction, commandHandlerName; for (commandHandlerName in commandObj) { commandFunction = commandObj[commandHandlerName]; this.addCommandHandler(commandHandlerName, commandFunction); } return this; }; /** * @name addQueryHandler * * @module Context * * @dscription * Use as: addQueryHandler(queryHandler, queryFunction) * * Add Commands to the `context`. These will be available to the `query` method after calling `initialize`. * * @example ```javascript exampleContext.addQueryHandler('SomeQuery', function(params, callback) { // ... }); ``` * @param {String} queryHandler Name of the query * * @param {String} queryFunction Function to execute on query */ Context.prototype.addQueryHandler = function(queryHandlerName, queryHandlerFn) { this._queryHandlers[queryHandlerName] = (function(_this) { return function() { return queryHandlerFn.apply(_this._di, arguments); }; })(this); return this; }; Context.prototype.addQueryHandlers = function(commandObj) { var queryFunction, queryHandlerName; for (queryHandlerName in commandObj) { queryFunction = commandObj[queryHandlerName]; this.addQueryHandler(queryHandlerName, queryFunction); } return this; }; /** * @name addAggregate * * @module Context * * @description * * Use as: addAggregate(aggregateName, aggregateDefinition) * * Add [Aggregates](https://github.com/efacilitation/eventric/wiki/BuildingBlocks#aggregateroot) to the `context`. It takes an AggregateDefinition as argument. The AggregateDefinition must at least consists of one AggregateRoot and can optionally have multiple named AggregateEntities. The Root and Entities itself are completely vanilla since eventric follows the philosophy that your DomainModel-Code should be technology-agnostic. * * @example ```javascript exampleContext.addAggregate('Example', { root: function(){ this.doSomething = function(description) { // ... } }, entities: { 'ExampleEntityOne': function() {}, 'ExampleEntityTwo': function() {} } }); ``` * * @param {String} aggregateName Name of the Aggregate * @param {String} aggregateDefinition Definition containing root and entities */ Context.prototype.addAggregate = function(aggregateName, AggregateRootClass) { this._aggregateRootClasses[aggregateName] = AggregateRootClass; return this; }; Context.prototype.addAggregates = function(aggregatesObj) { var AggregateRootClass, aggregateName; for (aggregateName in aggregatesObj) { AggregateRootClass = aggregatesObj[aggregateName]; this.addAggregate(aggregateName, AggregateRootClass); } return this; }; /** * @name subscribeToDomainEvent * * @module Context * * @description * Use as: subscribeToDomainEvent(domainEventName, domainEventHandlerFunction) * * Add handler function which gets called when a specific `DomainEvent` gets triggered * * @example ```javascript exampleContext.subscribeToDomainEvent('Example:create', function(domainEvent) { // ... }); ``` * * @param {String} domainEventName Name of the `DomainEvent` * * @param {Function} Function which gets called with `domainEvent` as argument * - `domainEvent` Instance of [[DomainEvent]] * */ Context.prototype.subscribeToDomainEvent = function(domainEventName, handlerFn, options) { var domainEventHandler; if (options == null) { options = {}; } domainEventHandler = (function(_this) { return function() { return handlerFn.apply(_this._di, arguments); }; })(this); this._eventBus.subscribeToDomainEvent(domainEventName, domainEventHandler, options); return this; }; /** * @name subscribeToDomainEventWithAggregateId * * @module Context * */ Context.prototype.subscribeToDomainEventWithAggregateId = function(domainEventName, aggregateId, handlerFn, options) { var domainEventHandler; if (options == null) { options = {}; } domainEventHandler = (function(_this) { return function() { return handlerFn.apply(_this._di, arguments); }; })(this); return this._eventBus.subscribeToDomainEventWithAggregateId(domainEventName, aggregateId, domainEventHandler, options); }; Context.prototype.subscribeToAllDomainEvents = function(handlerFn, op