UNPKG

eventric

Version:

behavior-first application development

1,617 lines (1,356 loc) 97 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/eventric", function(exports, require, module){ var Eventric, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __slice = [].slice; Eventric = (function() { function Eventric() { this._handleRemoteRPCRequest = __bind(this._handleRemoteRPCRequest, this); this.PubSub = require('./pub_sub'); this.EventBus = require('./event_bus'); this.Remote = require('./remote'); this.Context = require('./context'); this.DomainEvent = require('./domain_event'); this.Aggregate = require('./aggregate'); this.Repository = require('./repository'); this.Projection = require('./projection'); this.Logger = require('./logger'); this.RemoteInMemory = require('./remote/inmemory'); this.StoreInMemory = require('./store/inmemory'); this.log = this.Logger; this._contexts = {}; this._params = {}; this._domainEventHandlers = {}; this._domainEventHandlersAll = []; this._storeClasses = {}; this._remoteEndpoints = []; this.addRemoteEndpoint('inmemory', this.RemoteInMemory.endpoint); this.addStore('inmemory', this.StoreInMemory); 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; }; Eventric.prototype.context = function(name) { var context, err, pubsub; if (!name) { err = 'Contexts must have a name'; this.log.error(err); throw new Error(err); } pubsub = new this.PubSub; context = new this.Context(name, this); this.mixin(context, pubsub); 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 err, pubsub, remote; if (!contextName) { err = 'Missing context name'; this.log.error(err); throw new Error(err); } pubsub = new this.PubSub; remote = new this.Remote(contextName, this); this.mixin(remote, pubsub); 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, error; context = this.getContext(request.contextName); if (!context) { error = "Tried to handle Remote RPC with not registered context " + request.contextName; this.log.error(error); return callback(error, null); } if (this.Remote.ALLOWED_RPC_OPERATIONS.indexOf(request.method) === -1) { error = "RPC operation '" + request.method + "' not allowed"; this.log.error(error); return callback(error, null); } if (!(request.method in context)) { error = "Remote RPC method " + request.method + " not found on Context " + request.contextName; this.log.error(error); return callback(error, 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)); }; 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(); }; 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); } else { ++completed; if (completed >= arr.length) { callback(); } else { iterate(); } } }); }; return iterate(); }; Eventric.prototype.mixin = function(destination, source) { var prop, _results; _results = []; for (prop in source) { _results.push(destination[prop] = source[prop]); } return _results; }; return Eventric; })(); module.exports = Eventric; }); require.register("es6-promise", function(exports, require, module){ /*! * @overview es6-promise - a tiny implementation of Promises/A+. * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) * @license Licensed under MIT license * See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE * @version 2.0.1 */ (function() { "use strict"; function $$utils$$objectOrFunction(x) { return typeof x === 'function' || (typeof x === 'object' && x !== null); } function $$utils$$isFunction(x) { return typeof x === 'function'; } function $$utils$$isMaybeThenable(x) { return typeof x === 'object' && x !== null; } var $$utils$$_isArray; if (!Array.isArray) { $$utils$$_isArray = function (x) { return Object.prototype.toString.call(x) === '[object Array]'; }; } else { $$utils$$_isArray = Array.isArray; } var $$utils$$isArray = $$utils$$_isArray; var $$utils$$now = Date.now || function() { return new Date().getTime(); }; function $$utils$$F() { } var $$utils$$o_create = (Object.create || function (o) { if (arguments.length > 1) { throw new Error('Second argument not supported'); } if (typeof o !== 'object') { throw new TypeError('Argument must be an object'); } $$utils$$F.prototype = o; return new $$utils$$F(); }); var $$asap$$len = 0; var $$asap$$default = function asap(callback, arg) { $$asap$$queue[$$asap$$len] = callback; $$asap$$queue[$$asap$$len + 1] = arg; $$asap$$len += 2; if ($$asap$$len === 2) { // If len 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. $$asap$$scheduleFlush(); } }; var $$asap$$browserGlobal = (typeof window !== 'undefined') ? window : {}; var $$asap$$BrowserMutationObserver = $$asap$$browserGlobal.MutationObserver || $$asap$$browserGlobal.WebKitMutationObserver; // test for web worker but not in IE10 var $$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; // node function $$asap$$useNextTick() { return function() { process.nextTick($$asap$$flush); }; } function $$asap$$useMutationObserver() { var iterations = 0; var observer = new $$asap$$BrowserMutationObserver($$asap$$flush); var node = document.createTextNode(''); observer.observe(node, { characterData: true }); return function() { node.data = (iterations = ++iterations % 2); }; } // web worker function $$asap$$useMessageChannel() { var channel = new MessageChannel(); channel.port1.onmessage = $$asap$$flush; return function () { channel.port2.postMessage(0); }; } function $$asap$$useSetTimeout() { return function() { setTimeout($$asap$$flush, 1); }; } var $$asap$$queue = new Array(1000); function $$asap$$flush() { for (var i = 0; i < $$asap$$len; i+=2) { var callback = $$asap$$queue[i]; var arg = $$asap$$queue[i+1]; callback(arg); $$asap$$queue[i] = undefined; $$asap$$queue[i+1] = undefined; } $$asap$$len = 0; } var $$asap$$scheduleFlush; // Decide what async method to use to triggering processing of queued callbacks: if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') { $$asap$$scheduleFlush = $$asap$$useNextTick(); } else if ($$asap$$BrowserMutationObserver) { $$asap$$scheduleFlush = $$asap$$useMutationObserver(); } else if ($$asap$$isWorker) { $$asap$$scheduleFlush = $$asap$$useMessageChannel(); } else { $$asap$$scheduleFlush = $$asap$$useSetTimeout(); } function $$$internal$$noop() {} var $$$internal$$PENDING = void 0; var $$$internal$$FULFILLED = 1; var $$$internal$$REJECTED = 2; var $$$internal$$GET_THEN_ERROR = new $$$internal$$ErrorObject(); function $$$internal$$selfFullfillment() { return new TypeError("You cannot resolve a promise with itself"); } function $$$internal$$cannotReturnOwn() { return new TypeError('A promises callback cannot return that same promise.') } function $$$internal$$getThen(promise) { try { return promise.then; } catch(error) { $$$internal$$GET_THEN_ERROR.error = error; return $$$internal$$GET_THEN_ERROR; } } function $$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) { try { then.call(value, fulfillmentHandler, rejectionHandler); } catch(e) { return e; } } function $$$internal$$handleForeignThenable(promise, thenable, then) { $$asap$$default(function(promise) { var sealed = false; var error = $$$internal$$tryThen(then, thenable, function(value) { if (sealed) { return; } sealed = true; if (thenable !== value) { $$$internal$$resolve(promise, value); } else { $$$internal$$fulfill(promise, value); } }, function(reason) { if (sealed) { return; } sealed = true; $$$internal$$reject(promise, reason); }, 'Settle: ' + (promise._label || ' unknown promise')); if (!sealed && error) { sealed = true; $$$internal$$reject(promise, error); } }, promise); } function $$$internal$$handleOwnThenable(promise, thenable) { if (thenable._state === $$$internal$$FULFILLED) { $$$internal$$fulfill(promise, thenable._result); } else if (promise._state === $$$internal$$REJECTED) { $$$internal$$reject(promise, thenable._result); } else { $$$internal$$subscribe(thenable, undefined, function(value) { $$$internal$$resolve(promise, value); }, function(reason) { $$$internal$$reject(promise, reason); }); } } function $$$internal$$handleMaybeThenable(promise, maybeThenable) { if (maybeThenable.constructor === promise.constructor) { $$$internal$$handleOwnThenable(promise, maybeThenable); } else { var then = $$$internal$$getThen(maybeThenable); if (then === $$$internal$$GET_THEN_ERROR) { $$$internal$$reject(promise, $$$internal$$GET_THEN_ERROR.error); } else if (then === undefined) { $$$internal$$fulfill(promise, maybeThenable); } else if ($$utils$$isFunction(then)) { $$$internal$$handleForeignThenable(promise, maybeThenable, then); } else { $$$internal$$fulfill(promise, maybeThenable); } } } function $$$internal$$resolve(promise, value) { if (promise === value) { $$$internal$$reject(promise, $$$internal$$selfFullfillment()); } else if ($$utils$$objectOrFunction(value)) { $$$internal$$handleMaybeThenable(promise, value); } else { $$$internal$$fulfill(promise, value); } } function $$$internal$$publishRejection(promise) { if (promise._onerror) { promise._onerror(promise._result); } $$$internal$$publish(promise); } function $$$internal$$fulfill(promise, value) { if (promise._state !== $$$internal$$PENDING) { return; } promise._result = value; promise._state = $$$internal$$FULFILLED; if (promise._subscribers.length === 0) { } else { $$asap$$default($$$internal$$publish, promise); } } function $$$internal$$reject(promise, reason) { if (promise._state !== $$$internal$$PENDING) { return; } promise._state = $$$internal$$REJECTED; promise._result = reason; $$asap$$default($$$internal$$publishRejection, promise); } function $$$internal$$subscribe(parent, child, onFulfillment, onRejection) { var subscribers = parent._subscribers; var length = subscribers.length; parent._onerror = null; subscribers[length] = child; subscribers[length + $$$internal$$FULFILLED] = onFulfillment; subscribers[length + $$$internal$$REJECTED] = onRejection; if (length === 0 && parent._state) { $$asap$$default($$$internal$$publish, parent); } } function $$$internal$$publish(promise) { var subscribers = promise._subscribers; var settled = promise._state; if (subscribers.length === 0) { return; } var child, callback, detail = promise._result; for (var i = 0; i < subscribers.length; i += 3) { child = subscribers[i]; callback = subscribers[i + settled]; if (child) { $$$internal$$invokeCallback(settled, child, callback, detail); } else { callback(detail); } } promise._subscribers.length = 0; } function $$$internal$$ErrorObject() { this.error = null; } var $$$internal$$TRY_CATCH_ERROR = new $$$internal$$ErrorObject(); function $$$internal$$tryCatch(callback, detail) { try { return callback(detail); } catch(e) { $$$internal$$TRY_CATCH_ERROR.error = e; return $$$internal$$TRY_CATCH_ERROR; } } function $$$internal$$invokeCallback(settled, promise, callback, detail) { var hasCallback = $$utils$$isFunction(callback), value, error, succeeded, failed; if (hasCallback) { value = $$$internal$$tryCatch(callback, detail); if (value === $$$internal$$TRY_CATCH_ERROR) { failed = true; error = value.error; value = null; } else { succeeded = true; } if (promise === value) { $$$internal$$reject(promise, $$$internal$$cannotReturnOwn()); return; } } else { value = detail; succeeded = true; } if (promise._state !== $$$internal$$PENDING) { // noop } else if (hasCallback && succeeded) { $$$internal$$resolve(promise, value); } else if (failed) { $$$internal$$reject(promise, error); } else if (settled === $$$internal$$FULFILLED) { $$$internal$$fulfill(promise, value); } else if (settled === $$$internal$$REJECTED) { $$$internal$$reject(promise, value); } } function $$$internal$$initializePromise(promise, resolver) { try { resolver(function resolvePromise(value){ $$$internal$$resolve(promise, value); }, function rejectPromise(reason) { $$$internal$$reject(promise, reason); }); } catch(e) { $$$internal$$reject(promise, e); } } function $$$enumerator$$makeSettledResult(state, position, value) { if (state === $$$internal$$FULFILLED) { return { state: 'fulfilled', value: value }; } else { return { state: 'rejected', reason: value }; } } function $$$enumerator$$Enumerator(Constructor, input, abortOnReject, label) { this._instanceConstructor = Constructor; this.promise = new Constructor($$$internal$$noop, label); this._abortOnReject = abortOnReject; if (this._validateInput(input)) { this._input = input; this.length = input.length; this._remaining = input.length; this._init(); if (this.length === 0) { $$$internal$$fulfill(this.promise, this._result); } else { this.length = this.length || 0; this._enumerate(); if (this._remaining === 0) { $$$internal$$fulfill(this.promise, this._result); } } } else { $$$internal$$reject(this.promise, this._validationError()); } } $$$enumerator$$Enumerator.prototype._validateInput = function(input) { return $$utils$$isArray(input); }; $$$enumerator$$Enumerator.prototype._validationError = function() { return new Error('Array Methods must be provided an Array'); }; $$$enumerator$$Enumerator.prototype._init = function() { this._result = new Array(this.length); }; var $$$enumerator$$default = $$$enumerator$$Enumerator; $$$enumerator$$Enumerator.prototype._enumerate = function() { var length = this.length; var promise = this.promise; var input = this._input; for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { this._eachEntry(input[i], i); } }; $$$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) { var c = this._instanceConstructor; if ($$utils$$isMaybeThenable(entry)) { if (entry.constructor === c && entry._state !== $$$internal$$PENDING) { entry._onerror = null; this._settledAt(entry._state, i, entry._result); } else { this._willSettleAt(c.resolve(entry), i); } } else { this._remaining--; this._result[i] = this._makeResult($$$internal$$FULFILLED, i, entry); } }; $$$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) { var promise = this.promise; if (promise._state === $$$internal$$PENDING) { this._remaining--; if (this._abortOnReject && state === $$$internal$$REJECTED) { $$$internal$$reject(promise, value); } else { this._result[i] = this._makeResult(state, i, value); } } if (this._remaining === 0) { $$$internal$$fulfill(promise, this._result); } }; $$$enumerator$$Enumerator.prototype._makeResult = function(state, i, value) { return value; }; $$$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) { var enumerator = this; $$$internal$$subscribe(promise, undefined, function(value) { enumerator._settledAt($$$internal$$FULFILLED, i, value); }, function(reason) { enumerator._settledAt($$$internal$$REJECTED, i, reason); }); }; var $$promise$all$$default = function all(entries, label) { return new $$$enumerator$$default(this, entries, true /* abort on reject */, label).promise; }; var $$promise$race$$default = function race(entries, label) { /*jshint validthis:true */ var Constructor = this; var promise = new Constructor($$$internal$$noop, label); if (!$$utils$$isArray(entries)) { $$$internal$$reject(promise, new TypeError('You must pass an array to race.')); return promise; } var length = entries.length; function onFulfillment(value) { $$$internal$$resolve(promise, value); } function onRejection(reason) { $$$internal$$reject(promise, reason); } for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { $$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); } return promise; }; var $$promise$resolve$$default = function resolve(object, label) { /*jshint validthis:true */ var Constructor = this; if (object && typeof object === 'object' && object.constructor === Constructor) { return object; } var promise = new Constructor($$$internal$$noop, label); $$$internal$$resolve(promise, object); return promise; }; var $$promise$reject$$default = function reject(reason, label) { /*jshint validthis:true */ var Constructor = this; var promise = new Constructor($$$internal$$noop, label); $$$internal$$reject(promise, reason); return promise; }; var $$es6$promise$promise$$counter = 0; function $$es6$promise$promise$$needsResolver() { throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); } function $$es6$promise$promise$$needsNew() { throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); } var $$es6$promise$promise$$default = $$es6$promise$promise$$Promise; /** Promise objects represent the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its `then` method, which registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled. Terminology ----------- - `promise` is an object or function with a `then` method whose behavior conforms to this specification. - `thenable` is an object or function that defines a `then` method. - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). - `exception` is a value that is thrown using the throw statement. - `reason` is a value that indicates why a promise was rejected. - `settled` the final resting state of a promise, fulfilled or rejected. A promise can be in one of three states: pending, fulfilled, or rejected. Promises that are fulfilled have a fulfillment value and are in the fulfilled state. Promises that are rejected have a rejection reason and are in the rejected state. A fulfillment value is never a thenable. Promises can also be said to *resolve* a value. If this value is also a promise, then the original promise's settled state will match the value's settled state. So a promise that *resolves* a promise that rejects will itself reject, and a promise that *resolves* a promise that fulfills will itself fulfill. Basic Usage: ------------ ```js var promise = new Promise(function(resolve, reject) { // on success resolve(value); // on failure reject(reason); }); promise.then(function(value) { // on fulfillment }, function(reason) { // on rejection }); ``` Advanced Usage: --------------- Promises shine when abstracting away asynchronous interactions such as `XMLHttpRequest`s. ```js function getJSON(url) { return new Promise(function(resolve, reject){ var xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onreadystatechange = handler; xhr.responseType = 'json'; xhr.setRequestHeader('Accept', 'application/json'); xhr.send(); function handler() { if (this.readyState === this.DONE) { if (this.status === 200) { resolve(this.response); } else { reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); } } }; }); } getJSON('/posts.json').then(function(json) { // on fulfillment }, function(reason) { // on rejection }); ``` Unlike callbacks, promises are great composable primitives. ```js Promise.all([ getJSON('/posts'), getJSON('/comments') ]).then(function(values){ values[0] // => postsJSON values[1] // => commentsJSON return values; }); ``` @class Promise @param {function} resolver Useful for tooling. @constructor */ function $$es6$promise$promise$$Promise(resolver) { this._id = $$es6$promise$promise$$counter++; this._state = undefined; this._result = undefined; this._subscribers = []; if ($$$internal$$noop !== resolver) { if (!$$utils$$isFunction(resolver)) { $$es6$promise$promise$$needsResolver(); } if (!(this instanceof $$es6$promise$promise$$Promise)) { $$es6$promise$promise$$needsNew(); } $$$internal$$initializePromise(this, resolver); } } $$es6$promise$promise$$Promise.all = $$promise$all$$default; $$es6$promise$promise$$Promise.race = $$promise$race$$default; $$es6$promise$promise$$Promise.resolve = $$promise$resolve$$default; $$es6$promise$promise$$Promise.reject = $$promise$reject$$default; $$es6$promise$promise$$Promise.prototype = { constructor: $$es6$promise$promise$$Promise, /** The primary way of interacting with a promise is through its `then` method, which registers callbacks to receive either a promise's eventual value or the reason why the promise cannot be fulfilled. ```js findUser().then(function(user){ // user is available }, function(reason){ // user is unavailable, and you are given the reason why }); ``` Chaining -------- The return value of `then` is itself a promise. This second, 'downstream' promise is resolved with the return value of the first promise's fulfillment or rejection handler, or rejected if the handler throws an exception. ```js findUser().then(function (user) { return user.name; }, function (reason) { return 'default name'; }).then(function (userName) { // If `findUser` fulfilled, `userName` will be the user's name, otherwise it // will be `'default name'` }); findUser().then(function (user) { throw new Error('Found user, but still unhappy'); }, function (reason) { throw new Error('`findUser` rejected and we're unhappy'); }).then(function (value) { // never reached }, function (reason) { // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. }); ``` If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. ```js findUser().then(function (user) { throw new PedagogicalException('Upstream error'); }).then(function (value) { // never reached }).then(function (value) { // never reached }, function (reason) { // The `PedgagocialException` is propagated all the way down to here }); ``` Assimilation ------------ Sometimes the value you want to propagate to a downstream promise can only be retrieved asynchronously. This can be achieved by returning a promise in the fulfillment or rejection handler. The downstream promise will then be pending until the returned promise is settled. This is called *assimilation*. ```js findUser().then(function (user) { return findCommentsByAuthor(user); }).then(function (comments) { // The user's comments are now available }); ``` If the assimliated promise rejects, then the downstream promise will also reject. ```js findUser().then(function (user) { return findCommentsByAuthor(user); }).then(function (comments) { // If `findCommentsByAuthor` fulfills, we'll have the value here }, function (reason) { // If `findCommentsByAuthor` rejects, we'll have the reason here }); ``` Simple Example -------------- Synchronous Example ```javascript var result; try { result = findResult(); // success } catch(reason) { // failure } ``` Errback Example ```js findResult(function(result, err){ if (err) { // failure } else { // success } }); ``` Promise Example; ```javascript findResult().then(function(result){ // success }, function(reason){ // failure }); ``` Advanced Example -------------- Synchronous Example ```javascript var author, books; try { author = findAuthor(); books = findBooksByAuthor(author); // success } catch(reason) { // failure } ``` Errback Example ```js function foundBooks(books) { } function failure(reason) { } findAuthor(function(author, err){ if (err) { failure(err); // failure } else { try { findBoooksByAuthor(author, function(books, err) { if (err) { failure(err); } else { try { foundBooks(books); } catch(reason) { failure(reason); } } }); } catch(error) { failure(err); } // success } }); ``` Promise Example; ```javascript findAuthor(). then(findBooksByAuthor). then(function(books){ // found books }).catch(function(reason){ // something went wrong }); ``` @method then @param {Function} onFulfilled @param {Function} onRejected Useful for tooling. @return {Promise} */ then: function(onFulfillment, onRejection) { var parent = this; var state = parent._state; if (state === $$$internal$$FULFILLED && !onFulfillment || state === $$$internal$$REJECTED && !onRejection) { return this; } var child = new this.constructor($$$internal$$noop); var result = parent._result; if (state) { var callback = arguments[state - 1]; $$asap$$default(function(){ $$$internal$$invokeCallback(state, child, callback, result); }); } else { $$$internal$$subscribe(parent, child, onFulfillment, onRejection); } return child; }, /** `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same as the catch block of a try/catch statement. ```js function findAuthor(){ throw new Error('couldn't find that author'); } // synchronous try { findAuthor(); } catch(reason) { // something went wrong } // async with promises findAuthor().catch(function(reason){ // something went wrong }); ``` @method catch @param {Function} onRejection Useful for tooling. @return {Promise} */ 'catch': function(onRejection) { return this.then(null, onRejection); } }; var $$es6$promise$polyfill$$default = 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 $$utils$$isFunction(resolve); }()); if (!es6PromiseSupport) { local.Promise = $$es6$promise$promise$$default; } }; var es6$promise$umd$$ES6Promise = { 'Promise': $$es6$promise$promise$$default, 'polyfill': $$es6$promise$polyfill$$default }; /* global define:true module:true window: true */ if (typeof define === 'function' && define['amd']) { define(function() { return es6$promise$umd$$ES6Promise; }); } else if (typeof module !== 'undefined' && module['exports']) { module['exports'] = es6$promise$umd$$ES6Promise; } else if (typeof this !== 'undefined') { this['ES6Promise'] = es6$promise$umd$$ES6Promise; } }).call(this); }); require.register("eventric/index", function(exports, require, module){ require('es6-promise').polyfill(); module.exports = new (require('./eventric')); }); require.register("eventric/aggregate/aggregate", function(exports, require, module){ var Aggregate, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; Aggregate = (function() { function Aggregate(_context, _eventric, _name, Root) { this._context = _context; this._eventric = _eventric; this._name = _name; this.getDomainEvents = __bind(this.getDomainEvents, this); this.emitDomainEvent = __bind(this.emitDomainEvent, this); this._domainEvents = []; if (!Root) { this.root = {}; } else { this.root = new Root; } this.root.$emitDomainEvent = this.emitDomainEvent; } Aggregate.prototype.emitDomainEvent = function(domainEventName, domainEventPayload) { var DomainEventClass, domainEvent, err; DomainEventClass = this._context.getDomainEvent(domainEventName); if (!DomainEventClass) { err = "Tried to emitDomainEvent '" + domainEventName + "' which is not defined"; this._eventric.log.error(err); throw new Error(err); } domainEvent = this._createDomainEvent(domainEventName, DomainEventClass, domainEventPayload); this._domainEvents.push(domainEvent); this._handleDomainEvent(domainEventName, domainEvent); return this._eventric.log.debug("Created and Handled DomainEvent in Aggregate", domainEvent); }; Aggregate.prototype._createDomainEvent = function(domainEventName, DomainEventClass, domainEventPayload) { var payload; payload = {}; DomainEventClass.apply(payload, [domainEventPayload]); return new this._eventric.DomainEvent({ id: this._eventric.generateUid(), name: domainEventName, aggregate: { id: this.id, name: this._name }, context: this._context.name, payload: payload }); }; Aggregate.prototype._handleDomainEvent = function(domainEventName, domainEvent) { if (this.root["handle" + domainEventName]) { return this.root["handle" + domainEventName](domainEvent, function() {}); } else { return this._eventric.log.debug("Tried to handle the DomainEvent '" + domainEventName + "' without a matching handle method"); } }; Aggregate.prototype.getDomainEvents = function() { return this._domainEvents; }; Aggregate.prototype.applyDomainEvents = function(domainEvents) { var domainEvent, _i, _len, _results; _results = []; for (_i = 0, _len = domainEvents.length; _i < _len; _i++) { domainEvent = domainEvents[_i]; _results.push(this._applyDomainEvent(domainEvent)); } return _results; }; Aggregate.prototype._applyDomainEvent = function(domainEvent) { return this._handleDomainEvent(domainEvent.name, domainEvent); }; return Aggregate; })(); module.exports = Aggregate; }); require.register("eventric/aggregate/index", function(exports, require, module){ module.exports = require('./aggregate'); }); require.register("eventric/context/context", function(exports, require, module){ var Context, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __slice = [].slice; Context = (function() { function Context(name, _eventric) { this.name = name; this._eventric = _eventric; this.clearProjectionStore = __bind(this.clearProjectionStore, this); this.getProjectionStore = __bind(this.getProjectionStore, this); this._getAggregateRepository = __bind(this._getAggregateRepository, this); this.publishDomainEvent = __bind(this.publishDomainEvent, this); this.emitDomainEvent = __bind(this.emitDomainEvent, this); this._initialized = false; this._params = this._eventric.get(); this._di = {}; this._aggregateRootClasses = {}; this._commandHandlers = {}; this._queryHandlers = {}; this._domainEventClasses = {}; this._domainEventHandlers = {}; this._projectionClasses = {}; this._domainEventStreamClasses = {}; this._domainEventStreamInstances = {}; this._repositoryInstances = {}; this._storeClasses = {}; this._storeInstances = {}; this._eventBus = new this._eventric.EventBus(this._eventric); this.projectionService = new this._eventric.Projection(this._eventric); this.log = this._eventric.log; } Context.prototype.set = function(key, value) { this._params[key] = value; return this; }; Context.prototype.get = function(key) { return this._params[key]; }; 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.saveAndPublishDomainEvent(domainEvent).then((function(_this) { return function() { return _this._eventric.log.debug("Created and Handled DomainEvent in Context", domainEvent); }; })(this)); }; Context.prototype.publishDomainEvent = function(domainEvent) { return this._eventBus.publishDomainEvent(domainEvent); }; Context.prototype._createDomainEvent = function(domainEventName, DomainEventClass, domainEventPayload) { return new this._eventric.DomainEvent({ id: this._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; }; 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; }; Context.prototype.addCommandHandler = function(commandHandlerName, commandHandlerFn) { this._commandHandlers[commandHandlerName] = commandHandlerFn; return this; }; Context.prototype._getAggregateRepository = function(aggregateName, command) { var AggregateRoot, repositoriesCache, repository; if (!repositoriesCache) { repositoriesCache = {}; } if (!repositoriesCache[aggregateName]) { AggregateRoot = this._aggregateRootClasses[aggregateName]; repository = new this._eventric.Repository({ aggregateName: aggregateName, AggregateRoot: AggregateRoot, context: this, eventric: this._eventric }); repositoriesCache[aggregateName] = repository; } repositoriesCache[aggregateName].setCommand(command); return repositoriesCache[aggregateName]; }; Context.prototype.addCommandHandlers = function(commandObj) { var commandFunction, commandHandlerName; for (commandHandlerName in commandObj) { commandFunction = commandObj[commandHandlerName]; this.addCommandHandler(commandHandlerName, commandFunction); } return this; }; Context.prototype.addQueryHandler = function(queryHandlerName, queryHandlerFn) { this._queryHandlers[queryHandlerName] = queryHandlerFn; return this; }; Context.prototype.addQueryHandlers = function(queryObj) { var queryFunction, queryHandlerName; for (queryHandlerName in queryObj) { queryFunction = queryObj[queryHandlerName]; this.addQueryHandler(queryHandlerName, queryFunction); } return this; }; 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; }; Context.prototype.subscribeToDomainEvent = function(domainEventName, handlerFn) { var domainEventHandler; domainEventHandler = (function(_this) { return function() { return handlerFn.apply(_this._di, arguments); }; })(this); return this._eventBus.subscribeToDomainEvent(domainEventName, domainEventHandler); }; Context.prototype.subscribeToDomainEvents = function(domainEventHandlersObj) { var domainEventName, handlerFn, _results; _results = []; for (domainEventName in domainEventHandlersObj) { handlerFn = domainEventHandlersObj[domainEventName]; _results.push(this.subscribeToDomainEvent(domainEventName, handlerFn)); } return _results; }; Context.prototype.subscribeToDomainEventWithAggregateId = function(domainEventName, aggregateId, handlerFn) { var domainEventHandler; domainEventHandler = (function(_this) { return function() { return handlerFn.apply(_this._di, arguments); }; })(this); return this._eventBus.subscribeToDomainEventWithAggregateId(domainEventName, aggregateId, domainEventHandler); }; Context.prototype.subscribeToAllDomainEvents = function(handlerFn) { var domainEventHandler; domainEventHandler = (function(_this) { return function() { return handlerFn.apply(_this._di, arguments); }; })(this); return this._eventBus.subscribeToAllDomainEvents(domainEventHandler); }; Context.prototype.addProjection = function(projectionName, ProjectionClass) { this._projectionClasses[projectionName] = ProjectionClass; return this; }; Context.prototype.addProjections = function(viewsObj) { var ProjectionClass, projectionName; for (projectionName in viewsObj) { ProjectionClass = viewsObj[projectionName]; this.addProjection(projectionName, ProjectionClass); } return this; }; Context.prototype.getProjectionInstance = function(projectionId) { return this.projectionService.getInstance(projectionId); }; Context.prototype.destroyProjectionInstance = function(projectionId) { return this.projectionService.destroyInstance(projectionId, this); }; Context.prototype.initializeProjectionInstance = function(projectionName, params)