UNPKG

eventric

Version:

behavior-first application development

1,536 lines (1,277 loc) 466 kB
/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { __webpack_require__(1); __webpack_require__(26); __webpack_require__(27); __webpack_require__(28); __webpack_require__(18); __webpack_require__(17); __webpack_require__(16); __webpack_require__(15); __webpack_require__(103); __webpack_require__(14); __webpack_require__(104); __webpack_require__(13); __webpack_require__(105); __webpack_require__(23); __webpack_require__(22); __webpack_require__(20); __webpack_require__(106); __webpack_require__(19); __webpack_require__(21); __webpack_require__(4); __webpack_require__(3); __webpack_require__(7); __webpack_require__(8); __webpack_require__(107); __webpack_require__(108); __webpack_require__(9); __webpack_require__(10); __webpack_require__(109); __webpack_require__(5); __webpack_require__(6); __webpack_require__(110); __webpack_require__(111); __webpack_require__(11); __webpack_require__(12); __webpack_require__(24); module.exports = __webpack_require__(25); /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { var Context, Eventric, GlobalContext, Projection, Remote, StoreInMemory, remoteInmemory, uidGenerator, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; remoteInmemory = __webpack_require__(2); GlobalContext = __webpack_require__(3); Remote = __webpack_require__(5); Projection = __webpack_require__(9); Context = __webpack_require__(13); StoreInMemory = __webpack_require__(24); uidGenerator = __webpack_require__(11); Eventric = (function() { function Eventric() { this._handleRemoteRPCRequest = bind(this._handleRemoteRPCRequest, this); this._contexts = {}; this._params = {}; this._domainEventHandlers = {}; this._domainEventHandlersAll = []; this._storeDefintion = null; this._remoteEndpoints = []; this._globalProjectionClasses = []; this._globalContext = new GlobalContext; this._projectionService = new Projection(this._globalContext); this.setRemoteEndpoint(remoteInmemory.endpoint); this.setStore(StoreInMemory, {}); } Eventric.prototype.setStore = function(StoreClass, storeOptions) { if (storeOptions == null) { storeOptions = {}; } return this._storeDefintion = { Class: StoreClass, options: storeOptions }; }; Eventric.prototype.context = function(name) { var context, error; if (!name) { error = 'Contexts must have a name'; this.log.error(error); throw new Error(error); } context = new Context(name, this._storeDefintion); this._delegateAllDomainEventsToRemoteEndpoint(context); this._contexts[name] = context; return context; }; Eventric.prototype.initializeGlobalProjections = function() { return Promise.all(this._globalProjectionClasses.map((function(_this) { return function(GlobalProjectionClass) { return _this._projectionService.initializeInstance('', new GlobalProjectionClass, {}); }; })(this))); }; Eventric.prototype.addGlobalProjection = function(ProjectionClass) { return this._globalProjectionClasses.push(ProjectionClass); }; Eventric.prototype.getRegisteredContextNames = function() { return Object.keys(this._contexts); }; Eventric.prototype.getContext = function(name) { return this._contexts[name]; }; Eventric.prototype.remote = function(contextName) { var error; if (!contextName) { error = 'Missing context name'; this.log.error(error); throw new Error(error); } return new Remote(contextName); }; Eventric.prototype.setRemoteEndpoint = function(remoteEndpoint) { this._remoteEndpoint = remoteEndpoint; return this._remoteEndpoint.setRPCHandler(this._handleRemoteRPCRequest); }; Eventric.prototype.generateUid = function() { return uidGenerator.generateUid(); }; Eventric.prototype._handleRemoteRPCRequest = function(request, callback) { var context, error; context = this.getContext(request.contextName); if (!context) { error = new Error("Tried to handle Remote RPC with not registered context " + request.contextName); this.log.error(error.stack); callback(error, null); return; } if (Remote.ALLOWED_RPC_OPERATIONS.indexOf(request.functionName) === -1) { error = new Error("RPC operation '" + request.functionName + "' not allowed"); callback(error, null); return; } if (!(request.functionName in context)) { error = new Error("Remote RPC function " + request.functionName + " not found on Context " + request.contextName); this.log.error(error.stack); callback(error, null); return; } return context[request.functionName].apply(context, request.args).then(function(result) { return callback(null, result); })["catch"](function(error) { return callback(error); }); }; Eventric.prototype._delegateAllDomainEventsToRemoteEndpoint = function(context) { return context.subscribeToAllDomainEvents((function(_this) { return function(domainEvent) { _this._remoteEndpoint.publish(context.name, domainEvent.name, domainEvent); if (domainEvent.aggregate) { return _this._remoteEndpoint.publish(context.name, domainEvent.name, domainEvent.aggregate.id, domainEvent); } }; })(this)); }; return Eventric; })(); module.exports = new Eventric; /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { (function webpackUniversalModuleDefinition(root, factory) { if(true) module.exports = factory(); else if(typeof define === 'function' && define.amd) define(factory); else if(typeof exports === 'object') exports["eventric-remote-inmemory"] = factory(); else root["eventric-remote-inmemory"] = factory(); })(this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { module.exports = { endpoint: __webpack_require__(1), client: __webpack_require__(3) }; /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { var InMemoryRemoteEndpoint, pubSub, slice = [].slice; pubSub = __webpack_require__(2); InMemoryRemoteEndpoint = (function() { function InMemoryRemoteEndpoint() {} InMemoryRemoteEndpoint.prototype.setRPCHandler = function(handleRPCRequest) { this.handleRPCRequest = handleRPCRequest; }; InMemoryRemoteEndpoint.prototype.publish = function() { var aggregateId, arg, contextName, domainEventName, fullEventName, i, payload; contextName = arguments[0], arg = 3 <= arguments.length ? slice.call(arguments, 1, i = arguments.length - 1) : (i = 1, []), payload = arguments[i++]; domainEventName = arg[0], aggregateId = arg[1]; fullEventName = pubSub.getFullEventName(contextName, domainEventName, aggregateId); return pubSub.publish(fullEventName, payload); }; return InMemoryRemoteEndpoint; })(); module.exports = new InMemoryRemoteEndpoint; /***/ }, /* 2 */ /***/ function(module, exports) { var PubSub, slice = [].slice; PubSub = (function() { function PubSub() { this._subscribers = []; this._subscriberId = 0; } PubSub.prototype.subscribe = function(eventName, subscriberFunction) { return new Promise((function(_this) { return function(resolve) { var subscriber; subscriber = { eventName: eventName, subscriberFunction: subscriberFunction, subscriberId: _this._getNextSubscriberId() }; _this._subscribers.push(subscriber); return resolve(subscriber.subscriberId); }; })(this)); }; PubSub.prototype.publish = function(eventName, payload) { var subscribers; subscribers = this._getRelevantSubscribers(eventName); return Promise.all(subscribers.map(function(subscriber) { return subscriber.subscriberFunction(payload); })); }; PubSub.prototype._getRelevantSubscribers = function(eventName) { if (eventName) { return this._subscribers.filter(function(subscriber) { return subscriber.eventName === eventName; }); } else { return this._subscribers; } }; PubSub.prototype.unsubscribe = function(subscriberId) { return new Promise((function(_this) { return function(resolve) { _this._subscribers = _this._subscribers.filter(function(subscriber) { return subscriber.subscriberId !== subscriberId; }); return resolve(); }; })(this)); }; PubSub.prototype._getNextSubscriberId = function() { return this._subscriberId++; }; PubSub.prototype.getFullEventName = function() { var eventParts; eventParts = 1 <= arguments.length ? slice.call(arguments, 0) : []; eventParts = eventParts.filter(function(eventPart) { return eventPart != null; }); return eventParts.join('/'); }; return PubSub; })(); module.exports = new PubSub; /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { var InMemoryRemoteClient, endpoint, pubSub, slice = [].slice; endpoint = __webpack_require__(1); pubSub = __webpack_require__(2); InMemoryRemoteClient = (function() { function InMemoryRemoteClient() {} InMemoryRemoteClient.prototype.rpc = function(rpcRequest) { return new Promise((function(_this) { return function(resolve, reject) { return endpoint.handleRPCRequest(rpcRequest, function(error, result) { if (error) { return reject(error); } else { return resolve(result); } }); }; })(this)); }; InMemoryRemoteClient.prototype.subscribe = function() { var aggregateId, arg, contextName, domainEventName, fullEventName, handlerFunction, i; contextName = arguments[0], arg = 3 <= arguments.length ? slice.call(arguments, 1, i = arguments.length - 1) : (i = 1, []), handlerFunction = arguments[i++]; domainEventName = arg[0], aggregateId = arg[1]; fullEventName = pubSub.getFullEventName(contextName, domainEventName, aggregateId); return pubSub.subscribe(fullEventName, handlerFunction); }; InMemoryRemoteClient.prototype.unsubscribe = function(subscriberId) { return pubSub.unsubscribe(subscriberId); }; return InMemoryRemoteClient; })(); module.exports = new InMemoryRemoteClient; /***/ } /******/ ]) }); ; /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(4); /***/ }, /* 4 */ /***/ function(module, exports, __webpack_require__) { var GlobalContext, slice = [].slice; GlobalContext = (function() { function GlobalContext() { this.name = 'Global'; } GlobalContext.prototype.findDomainEventsByName = function() { var findArguments, findDomainEventsByName; findArguments = 1 <= arguments.length ? slice.call(arguments, 0) : []; findDomainEventsByName = this._getAllContexts().map(function(context) { return context.findDomainEventsByName.apply(context, findArguments); }); return Promise.all(findDomainEventsByName).then((function(_this) { return function(domainEventsByContext) { var domainEvents; domainEvents = _this._combineDomainEventsByContext(domainEventsByContext); _this._sortDomainEventsByTimestamp(domainEvents); return domainEvents; }; })(this)); }; GlobalContext.prototype.subscribeToDomainEvent = function(eventName, domainEventHandler) { var subscribeToDomainEvents; subscribeToDomainEvents = this._getAllContexts().map(function(context) { return context.subscribeToDomainEvent(eventName, domainEventHandler); }); return Promise.all(subscribeToDomainEvents); }; GlobalContext.prototype._getAllContexts = function() { var contextNames, eventric; eventric = __webpack_require__(1); contextNames = eventric.getRegisteredContextNames(); return contextNames.map((function(_this) { return function(contextName) { return eventric.remote(contextName); }; })(this)); }; GlobalContext.prototype._combineDomainEventsByContext = function(domainEventsByContext) { return domainEventsByContext.reduce(function(allDomainEvents, contextDomainEvents) { return allDomainEvents.concat(contextDomainEvents); }, []); }; GlobalContext.prototype._sortDomainEventsByTimestamp = function(domainEvents) { return domainEvents.sort(function(firstEvent, secondEvent) { return firstEvent.timestamp - secondEvent.timestamp; }); }; return GlobalContext; })(); module.exports = GlobalContext; /***/ }, /* 5 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(6); /***/ }, /* 6 */ /***/ function(module, exports, __webpack_require__) { var Projection, Remote, logger, remoteInmemory; remoteInmemory = __webpack_require__(2); logger = __webpack_require__(7); Projection = __webpack_require__(9); Remote = (function() { Remote.ALLOWED_RPC_OPERATIONS = ['command', 'query', 'findDomainEventsByName', 'findDomainEventsByNameAndAggregateId']; function Remote(_contextName) { this._contextName = _contextName; this.name = this._contextName; this._params = {}; this._projectionClasses = {}; this._projectionInstances = {}; this._handlerFunctions = {}; this.projectionService = new Projection(this); this.setClient(remoteInmemory.client); this._exposeRpcOperationsAsMemberFunctions(); } Remote.prototype._exposeRpcOperationsAsMemberFunctions = function() { return Remote.ALLOWED_RPC_OPERATIONS.forEach((function(_this) { return function(rpcOperation) { return _this[rpcOperation] = function() { return _this._rpc(rpcOperation, arguments); }; }; })(this)); }; Remote.prototype.subscribeToAllDomainEvents = function(handlerFn) { return this._client.subscribe(this._contextName, handlerFn); }; Remote.prototype.subscribeToDomainEvent = function(domainEventName, handlerFn) { return this._client.subscribe(this._contextName, domainEventName, handlerFn); }; Remote.prototype.subscribeToDomainEventWithAggregateId = function(domainEventName, aggregateId, handlerFn) { return this._client.subscribe(this._contextName, domainEventName, aggregateId, handlerFn); }; Remote.prototype.unsubscribeFromDomainEvent = function(subscriberId) { return this._client.unsubscribe(subscriberId); }; Remote.prototype._rpc = function(functionName, args) { return this._client.rpc({ contextName: this._contextName, functionName: functionName, args: Array.prototype.slice.call(args) }); }; Remote.prototype.setClient = function(client) { this._client = client; return this; }; Remote.prototype.addProjection = function(projectionName, projectionClass) { this._projectionClasses[projectionName] = projectionClass; return this; }; Remote.prototype.initializeProjection = function(projectionObject, params) { return this.projectionService.initializeInstance('', projectionObject, params); }; Remote.prototype.initializeProjectionInstance = function(projectionName, params) { if (!this._projectionClasses[projectionName]) { return Promise.reject(new Error("Given projection " + projectionName + " not registered on remote")); } return this.projectionService.initializeInstance(projectionName, this._projectionClasses[projectionName], params); }; Remote.prototype.getProjectionInstance = function(projectionId) { return this.projectionService.getInstance(projectionId); }; Remote.prototype.destroyProjectionInstance = function(projectionId) { return this.projectionService.destroyInstance(projectionId, this); }; return Remote; })(); module.exports = Remote; /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(8); /***/ }, /* 8 */ /***/ function(module, exports) { 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); } }; /***/ }, /* 9 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(10); /***/ }, /* 10 */ /***/ function(module, exports, __webpack_require__) { var Projection, logger, uidGenerator, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; logger = __webpack_require__(7); uidGenerator = __webpack_require__(11); Projection = (function() { function Projection(_context) { this._context = _context; this._applyDomainEventToProjection = bind(this._applyDomainEventToProjection, this); this._handlerFunctions = {}; this._projectionInstances = {}; this._domainEventsApplied = {}; } Projection.prototype.initializeInstance = function(projectionName, Projection, params) { var aggregateId, diFn, diName, eventNames, projection, projectionId, ref; if (typeof Projection === 'function') { projection = new Projection; } else { projection = Projection; } if (this._context._di) { ref = this._context._di; for (diName in ref) { diFn = ref[diName]; projection[diName] = diFn; } } projectionId = uidGenerator.generateUid(); aggregateId = null; projection.$subscribeHandlersWithAggregateId = function(_aggregateId) { return aggregateId = _aggregateId; }; eventNames = null; return this._callInitializeOnProjection(projectionName, projection, params).then((function(_this) { return function() { return _this._parseEventNamesFromProjection(projection); }; })(this)).then((function(_this) { return function(_eventNames) { eventNames = _eventNames; return _this._applyDomainEventsFromStoreToProjection(projectionId, projection, eventNames, aggregateId); }; })(this)).then((function(_this) { return function() { return _this._subscribeProjectionToDomainEvents(projectionId, projectionName, projection, eventNames, aggregateId); }; })(this)).then((function(_this) { return function() { return _this._projectionInstances[projectionId] = projection; }; })(this)).then(function() { return projection.isInitialized = true; }).then(function() { return projectionId; }); }; Projection.prototype._callInitializeOnProjection = function(projectionName, projection, params) { return new Promise((function(_this) { return function(resolve, reject) { if (!projection.initialize) { logger.debug("[" + _this._context.name + "] No initialize function on Projection " + projectionName + " given, skipping"); return resolve(projection); } logger.debug("[" + _this._context.name + "] Calling initialize on Projection " + projectionName); return projection.initialize(params, function() { logger.debug("[" + _this._context.name + "] Finished initialize call on Projection " + projectionName); return resolve(projection); }); }; })(this)); }; Projection.prototype._parseEventNamesFromProjection = function(projection) { return new Promise(function(resolve, reject) { var eventName, eventNames, key, value; eventNames = []; for (key in projection) { value = projection[key]; if ((key.indexOf('handle')) === 0 && (typeof value === 'function')) { eventName = key.replace(/^handle/, ''); eventNames.push(eventName); } } return resolve(eventNames); }); }; Projection.prototype._applyDomainEventsFromStoreToProjection = function(projectionId, projection, eventNames, aggregateId) { var findEvents; this._domainEventsApplied[projectionId] = {}; if (aggregateId) { findEvents = this._context.findDomainEventsByNameAndAggregateId(eventNames, aggregateId); } else { findEvents = this._context.findDomainEventsByName(eventNames); } return findEvents.then((function(_this) { return function(domainEvents) { var applyDomainEventsToProjectionPromise; if (!domainEvents || domainEvents.length === 0) { return; } applyDomainEventsToProjectionPromise = Promise.resolve(); domainEvents.forEach(function(domainEvent) { return applyDomainEventsToProjectionPromise = applyDomainEventsToProjectionPromise.then(function() { return _this._applyDomainEventToProjection(domainEvent, projection); }).then(function() { return _this._domainEventsApplied[projectionId][domainEvent.id] = true; }); }); return applyDomainEventsToProjectionPromise; }; })(this)); }; Projection.prototype._subscribeProjectionToDomainEvents = function(projectionId, projectionName, projection, eventNames, aggregateId) { var domainEventHandler, subscribeProjectionToDomainEventsPromise; domainEventHandler = (function(_this) { return function(domainEvent) { if (_this._domainEventsApplied[projectionId][domainEvent.id]) { return; } return _this._applyDomainEventToProjection(domainEvent, projection).then(function() { _this._domainEventsApplied[projectionId][domainEvent.id] = true; }); }; })(this); subscribeProjectionToDomainEventsPromise = Promise.resolve(); eventNames.forEach((function(_this) { return function(eventName) { return subscribeProjectionToDomainEventsPromise = subscribeProjectionToDomainEventsPromise.then(function() { if (aggregateId) { return _this._context.subscribeToDomainEventWithAggregateId(eventName, aggregateId, domainEventHandler); } else { return _this._context.subscribeToDomainEvent(eventName, domainEventHandler); } }).then(function(subscriberId) { var base; if ((base = _this._handlerFunctions)[projectionId] == null) { base[projectionId] = []; } return _this._handlerFunctions[projectionId].push(subscriberId); }); }; })(this)); return subscribeProjectionToDomainEventsPromise; }; Projection.prototype._applyDomainEventToProjection = function(domainEvent, projection) { return Promise.resolve().then((function(_this) { return function() { if (!projection["handle" + domainEvent.name]) { logger.debug("Tried to apply DomainEvent '" + domainEvent.name + "' to Projection without a matching handle method"); return; } return projection["handle" + domainEvent.name](domainEvent); }; })(this)); }; Projection.prototype.getInstance = function(projectionId) { return this._projectionInstances[projectionId]; }; Projection.prototype.destroyInstance = function(projectionId) { var i, len, ref, subscriberId, unsubscribePromises; if (!this._handlerFunctions[projectionId]) { return Promise.reject(new Error('Missing attribute projectionId')); } unsubscribePromises = []; ref = this._handlerFunctions[projectionId]; for (i = 0, len = ref.length; i < len; i++) { subscriberId = ref[i]; unsubscribePromises.push(this._context.unsubscribeFromDomainEvent(subscriberId)); } delete this._handlerFunctions[projectionId]; delete this._projectionInstances[projectionId]; return Promise.all(unsubscribePromises); }; return Projection; })(); module.exports = Projection; /***/ }, /* 11 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(12); /***/ }, /* 12 */ /***/ function(module, exports) { var UidGenerator; UidGenerator = (function() { function UidGenerator() {} UidGenerator.prototype.generateUid = function(delimiter) { if (delimiter == null) { delimiter = "-"; } return this._s4() + this._s4() + delimiter + this._s4() + delimiter + this._s4() + delimiter + this._s4() + delimiter + this._s4() + this._s4() + this._s4(); }; UidGenerator.prototype._s4 = function() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); }; return UidGenerator; })(); module.exports = new UidGenerator; /***/ }, /* 13 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(14); /***/ }, /* 14 */ /***/ function(module, exports, __webpack_require__) { var AggregateRepository, Context, DomainEvent, EventBus, Projection, logger, uidGenerator, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, slice = [].slice; EventBus = __webpack_require__(19); Projection = __webpack_require__(9); DomainEvent = __webpack_require__(22); AggregateRepository = __webpack_require__(15); logger = __webpack_require__(7); uidGenerator = __webpack_require__(11); Context = (function() { function Context(name, _storeDefinition) { this.name = name; this._storeDefinition = _storeDefinition; this._getAggregateRepository = bind(this._getAggregateRepository, this); this._isInitialized = false; this._isDestroyed = false; this._di = { $query: (function(_this) { return function() { return _this.query.apply(_this, arguments); }; })(this) }; this._aggregateClasses = {}; this._commandHandlers = {}; this._queryHandlers = {}; this._domainEventClasses = {}; this._domainEventHandlers = {}; this._projectionClasses = {}; this._repositoryInstances = {}; this._storeInstance = null; this._pendingPromises = []; this._eventBus = new EventBus; this.projectionService = new Projection(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.addCommandHandlers = function(commands) { var commandFunction, commandHandlerName; for (commandHandlerName in commands) { commandFunction = commands[commandHandlerName]; this._commandHandlers[commandHandlerName] = commandFunction; } return this; }; Context.prototype.addQueryHandlers = function(queries) { var queryFunction, queryHandlerName; for (queryHandlerName in queries) { queryFunction = queries[queryHandlerName]; this._queryHandlers[queryHandlerName] = queryFunction; } return this; }; Context.prototype.addAggregate = function(aggregateName, AggregateClass) { this._aggregateClasses[aggregateName] = AggregateClass; return this; }; 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.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.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.initialize = function() { logger.debug("[" + this.name + "] Initializing"); logger.debug("[" + this.name + "] Initializing Store"); return this._initializeStore().then((function(_this) { return function() { logger.debug("[" + _this.name + "] Initializing Projections"); return _this._initializeProjections(); }; })(this)).then((function(_this) { return function() { return _this._isInitialized = true; }; })(this)); }; Context.prototype._initializeStore = function() { var initializeStorePromise; this._storeInstance = new this._storeDefinition.Class; initializeStorePromise = this._storeInstance.initialize(this, this._storeDefinition.options); return initializeStorePromise; }; Context.prototype._initializeProjections = function() { var ProjectionClass, initializeProjectionsPromise, projectionName, ref; initializeProjectionsPromise = Promise.resolve(); ref = this._projectionClasses; for (projectionName in ref) { ProjectionClass = ref[projectionName]; logger.debug("[" + this.name + "] Initializing Projection " + projectionName); initializeProjectionsPromise = initializeProjectionsPromise.then((function(_this) { return function() { return _this.projectionService.initializeInstance(projectionName, ProjectionClass, {}); }; })(this)).then((function(_this) { return function(projectionId) { return logger.debug("[" + _this.name + "] Finished initializing Projection " + projectionName); }; })(this)); } return initializeProjectionsPromise; }; Context.prototype.createDomainEvent = function(domainEventName, DomainEventClass, domainEventPayload, aggregate) { var payload; payload = {}; DomainEventClass.apply(payload, [domainEventPayload]); return new DomainEvent({ id: uidGenerator.generateUid(), name: domainEventName, aggregate: aggregate, context: this.name, payload: payload }); }; Context.prototype.initializeProjectionInstance = function(projectionName, params) { if (!this._projectionClasses[projectionName]) { return Promise.reject(new Error("Given projection " + projectionName + " not registered on context")); } return this.projectionService.initializeInstance(projectionName, this._projectionClasses[projectionName], params); }; Context.prototype.getProjection = function(projectionId) { return this.projectionService.getInstance(projectionId); }; Context.prototype.getDomainEvent = function(domainEventName) { return this._domainEventClasses[domainEventName]; }; Context.prototype.getDomainEventsStore = function() { return this._storeInstance; }; Context.prototype.getEventBus = function() { return this._eventBus; }; Context.prototype.findDomainEventsByName = function() { var findArguments; findArguments = 1 <= arguments.length ? slice.call(arguments, 0) : []; return new Promise((function(_this) { return function(resolve, reject) { var ref; return (ref = _this.getDomainEventsStore()).findDomainEventsByName.apply(ref, slice.call(findArguments).concat([function(err, events) { if (err) { return reject(err); } return resolve(events); }])); }; })(this)); }; Context.prototype.findDomainEventsByNameAndAggregateId = function() { var findArguments; findArguments = 1 <= arguments.length ? slice.call(arguments, 0) : []; return new Promise((function(_this) { return function(resolve, reject) { var ref; return (ref = _this.getDomainEventsStore()).findDomainEventsByNameAndAggregateId.apply(ref, slice.call(findArguments).concat([function(err, events) { if (err) { return reject(err); } return resolve(events); }])); }; })(this)); }; Context.prototype.command = function(commandName, params) { var executingCommand; if (this._isDestroyed) { Promise.reject(new Error("Context " + this.name + " was destroyed, cannot execute command " + commandName + " with arguments " + (JSON.stringify(params)))); return; } executingCommand = new Promise((function(_this) { return function(resolve, reject) { var commandServicesToInject; _this._verifyContextIsInitialized(commandName); if (!_this._commandHandlers[commandName]) { throw new Error("Given command " + commandName + " not registered on context"); } commandServicesToInject = _this._getCommandServicesToInject(); return Promise.resolve(_this._commandHandlers[commandName].apply(commandServicesToInject, [params])).then(function(result) { logger.debug('Completed Command', commandName); return resolve(result); })["catch"](reject); }; })(this)); this._addPendingPromise(executingCommand); return executingCommand; }; Context.prototype._getCommandServicesToInject = function() { var diFn, diFnName, ref, servicesToInject; servicesToInject = {}; ref = this._di; for (diFnName in ref) { diFn = ref[diFnName]; servicesToInject[diFnName] = diFn; } servicesToInject.$aggregate = { create: (function(_this) { return function() { var aggregateName, aggregateParams, aggregateRepository; aggregateName = arguments[0], aggregateParams = 2 <= arguments.length ? slice.call(arguments, 1) : []; aggregateRepository = _this._getAggregateRepository(aggregateName); return aggregateRepository.create.apply(aggregateRepository, aggregateParams); }; })(this), load: (function(_this) { return function(aggregateName, aggregateId) { var aggregateRepository; aggregateRepository = _this._getAggregateRepository(aggregateName); return aggregateRepository.load(aggregateId); }; })(this) }; return servicesToInject; }; Context.prototype._getAggregateRepository = function(aggregateName) { var AggregateClass, aggregateRepositoriesCache, aggregateRepository; if (!aggregateRepositoriesCache) { aggregateRepositoriesCache = {}; } if (!aggregateRepositoriesCache[aggregateName]) { AggregateClass = this._aggregateClasses[aggregateName]; aggregateRepository = new AggregateRepository({ aggregateName: aggregateName, AggregateClass: AggregateClass, context: this }); aggregateRepositoriesCache[aggregateName] = aggregateRepository; } return aggregateRepositoriesCache[aggregateName]; }; Context.prototype._addPendingPromise = function(pendingPromise) { var alwaysResolvingPromise; alwaysResolvingPromise = pendingPromise["catch"](function() {}); this._pendingPromises.push(alwaysResolvingPromise); return alwaysResolvingPromise.then((function(_this) { return function() { return _this._pendingPromises.splice(_this._pendingPromises.indexOf(alwaysResolvingPromise), 1); }; })(this)); }; Context.prototype.query = function(queryName, params) { return new Promise((function(_this) { return function(resolve, reject) { logger.debug('Got Query', queryName); _this._verifyContextIsInitialized(queryName); if (!_this._queryHandlers[queryName]) { reject(new Error("Given query " + queryName + " not registered on context")); return; } return Promise.resolve(_this._queryHandlers[queryName].apply(_this._di, [params])).then(function(result) { logger.debug("Completed Query " + queryName + " with Result " + result); return resolve(result); })["catch"](reject); }; })(this)); }; Context.prototype._verifyContextIsInitialized = function(methodName) { if (!this._isInitialized) { throw new Error("Context " + this.name + " not initialized yet, cannot execute " + methodName); } }; Context.prototype.destroy = function() { return Promise.all(this._pendingPromises).then((function(_this) { return function() { return _this._eventBus.destroy().then(function() { return _this._isDestroyed = true; }); }; })(this)); }; return Context; })(); module.exports = Context; /***/ }, /* 15 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(16); /***/ }, /* 16 */ /***/ function(module, exports, __webpack_require__) { var Aggregate, AggregateRepository, logger, uidGenerator, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; Aggregate = __webpack_require__(17); logger = __webpack_require__(7); uidGenerator = __webpack_require__(11); AggregateRepository = (function() { function AggregateRepository(params) { this.save = bind(this.save, this); this.create = bind(this.create, this); this.load = bind(this.load, this); this._aggregateName = params.aggregateName; this._AggregateClass = params.AggregateClass; this._context = params.context; this._store = this._context.getDomainEventsStore(); } AggregateRepository.prototype.load = function(aggregateId) { return new Promise((function(_this) { return function(resolve, reject) { return _this._store.findDomainEventsByAggregateId(aggregateId, function(error, domainEvents) { var aggregate; if (error) { reject(error); return; } if (!domainEvents.length) { reject(new Error("No domainEvents for " + _this._aggregateName + " Aggregate with " + aggregateId + " available")); return; } aggregate = new Aggregate(_this._context, _this._aggregateName, _this._AggregateClass); aggregate.applyDomainEvents(domainEvents); aggregate.id = aggregate.instance.$id = aggregateId; aggregate.instance.$save = function() { return _this.save(aggregate); }; return resolve(aggregate.instance); }); }; })(this)); }; AggregateRepository.prototype.create = function(params) { return new Promise((function(_this) { return function(resolve, reject) { var aggregate; aggregate = new Aggregate(_this._context, _this._aggregateName, _this._AggregateClass); if (typeof aggregate.instance.create !== 'function') { throw new Error("No create function on aggregate"); } aggregate.id = aggregate.instance.$id = uidGenerator.generateUid(); aggregate.instance.$save = function() { return _this.save(aggregate); }; return Promise.resolve(aggregate.instance.create(params)).then(function() { return resolve(aggregate.instance); })["catch"](reject); }; })(this)); }; AggregateRepository.prototype.save = function(aggregate) { return new Promise((function(_this) { return function(resolve, reject) { var domainEvents, saveDomainEventQueue; if (!aggregate) { throw new Error("Tried to save unknown aggregate " + _this._aggregateName); } domainEvents = aggregate.getDomainEvents(); if (domainEvents.length < 1) { throw new Error("Tried to save 0 DomainEvents from Aggregate " + _this._aggregateName); } logger.debug("Going to Save and Publish " + domainEvents.length + " DomainEvents from Aggregate " + _this._aggregateName); saveDomainEventQueue = Promise.resolve(); domainEvents.forEach(function(domainEvent) { return saveDomainEventQueue = saveDomainEventQueue.then(function() { return _this._store.saveDomainEvent(domainEvent); }).then(function() { return logger.debug("Saved DomainEvent", domainEvent); }); }); return saveDomainEventQueue.then(function() { return domainEvents.forEach(function(domainEvent) { logger.debug("Publishing DomainEvent", domainEvent); return _this._context.getEventBus().publishDomainEvent(domainEvent)["catch"](function(error) { return logger.error(error.stack || error); }); }); }).then(function() { return resolve(aggregate.id); })["catch"](reject); }; })(this)); }; return AggregateRepository; })(); module.exports = AggregateRepository; /***/ }, /* 17 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(18); /***/ }, /* 18 */ /***/ function(module, exports, __webpack_require__) { var Aggregate, logger, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; logger = __webpack_require__(7); Aggregate = (function() { function Aggregate(_context, _name, AggregateClass) { this._context = _context; this._name = _name; this.getDomainEvents = bind(this.getDomainEvents, this); this.emitDomainEvent = bind(this.emitDomainEvent, this); this._domainEvents = []; this.instance = new AggregateClass; this.instance.$emitDomainEvent = this.emitDomainEvent; } Aggregate.prototype.emitDomainEvent = function(domainEventName, domainEventPayload) { var DomainEventClass, aggregate, domainEvent; DomainEventClass = this._context.getDomainEvent(domainEventName); if (!DomainEventClass) { throw new Error("Tried to emitDomainEvent '" + domainEventName + "' which is not defined"); } aggregate = { id: this.id, name: this._name }; domainEvent = this._context.createDomainEvent(domainEventName, DomainEventClass, domainEventPayload, aggregate); this._domainEvents.push(domainEvent); this._handleDomainEvent(domainEventName, domainEvent); return logger.debug("Created and Handled DomainEvent in Aggregate", domainEvent); }; Aggregate.prototype._handleDomainEvent = function(domainEventName, domainEvent) { if (this.instance["handle" + domainEventName]) { return this.instance["handle" + domainEventName](domainEvent); } else { return logger.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; /***/ }, /* 19 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(20); /***/ }, /* 20 */ /***/ function(module, exports, __webpack_require__) { var EventBus, Subscriber; Subscriber = __webpack_require__(21); EventBus = (function() { function EventBus() { this._subscribers = []; this._subscriberId = 0; this._eventPublishQueue = Promise.resolve(); this._isDestroyed = false; } EventBus.prototype.subscribeToAllDomainEvents = function(subscriberFunction) { return this._subscribe('*', subscriberFunction); }; EventBus.prototype.subscribeToDomainEvent = function(eventName, subscriberFunction) { return this._subscribe(eventName, subscriberFunction); }; EventBus.prototype.subscribeToDomainEventWithAggregateId = function(eventName, aggregateId, subscriberFunction) { return this._subscribe(eventName + "/" + aggregateId, subscriberFunction); }; EventBus.prototype._subscribe = function(eventName, subscriberFunction) { return new Promise((function(_this) { return function(resolve) { var subscriber; subscriber = new Subscriber({