UNPKG

eventric-testing

Version:
1,464 lines (1,228 loc) 596 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__(2); __webpack_require__(4); __webpack_require__(5); __webpack_require__(6); __webpack_require__(7); __webpack_require__(8); __webpack_require__(16); __webpack_require__(9); __webpack_require__(17); module.exports = __webpack_require__(18); /***/ }, /* 1 */ /***/ function(module, exports) { var AggregateFactory; AggregateFactory = (function() { function AggregateFactory() {} AggregateFactory.prototype.createAggregate = function(eventric, AggregateClass, domainEvents) { var context; if (!eventric) { throw new Error('eventric instance missing'); } context = eventric.context("EventricTesting-" + (Math.random())); context.addAggregate('TestAggregate', this._createAggregateClassWithFakeCreateFunction(AggregateClass)); context.defineDomainEvents(domainEvents); context.addCommandHandlers({ CreateAggregate: function() { return this.$aggregate.create('TestAggregate'); } }); return context.initialize().then(function() { return context.command('CreateAggregate'); }).then(function(aggregate) { return context.destroy().then(function() { return aggregate; }); }); }; AggregateFactory.prototype._createAggregateClassWithFakeCreateFunction = function(AggregateClass) { var WrappedAggregateClass; WrappedAggregateClass = function() { var aggregateInstance, originalCreate; aggregateInstance = new AggregateClass; originalCreate = aggregateInstance.create; aggregateInstance.create = function() { return aggregateInstance.create = originalCreate; }; return aggregateInstance; }; return WrappedAggregateClass; }; return AggregateFactory; })(); module.exports = new AggregateFactory; /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { describe('aggregate factory', function() { var aggregateFactory, eventric; eventric = __webpack_require__(3); aggregateFactory = __webpack_require__(1); return describe('#createAggregate', function() { var ExampleAggregate, domainEvents, exampleAggregate; ExampleAggregate = (function() { function ExampleAggregate() {} ExampleAggregate.prototype.create = function(params) { return this.$emitDomainEvent('ExampleCreated', {}); }; ExampleAggregate.prototype.handleExampleCreated = function() { return this.created = true; }; return ExampleAggregate; })(); domainEvents = { ExampleCreated: function() {} }; exampleAggregate = null; beforeEach(function() { sandbox.spy(ExampleAggregate.prototype, 'create'); return aggregateFactory.createAggregate(eventric, ExampleAggregate, domainEvents).then(function(_exampleAggregate) { return exampleAggregate = _exampleAggregate; }); }); it('should throw an error given no eventric instance', function() { return expect(function() { return aggregateFactory.createAggregate(null); }).to["throw"](Error, /eventric instance missing/); }); it('should create an aggregate instance of the given type', function() { return expect(exampleAggregate).to.be.an.instanceOf(ExampleAggregate); }); it('should not call the original create function on the aggregate instance', function() { return expect(ExampleAggregate.prototype.create).not.to.have.been.called; }); it('should be possible to call the origial create function on the aggregate', function() { exampleAggregate.create(); return expect(ExampleAggregate.prototype.create).to.have.been.called; }); return it('should create an aggregate capable of emitting and handling domain events', function() { return aggregateFactory.createAggregate(eventric, ExampleAggregate, domainEvents).then(function(exampleAggregate) { exampleAggregate.create(); expect(exampleAggregate.$emitDomainEvent).to.be.a('function'); return expect(exampleAggregate.created).to.be["true"]; }); }); }); }); /***/ }, /* 3 */ /***/ 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"] = factory(); else root["eventric"] = 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 = __webpack_require__(1); /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { var Context, Eventric, Projection, Remote, remoteContextHash, uuidGenerator, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; Context = __webpack_require__(2); Remote = __webpack_require__(19); Projection = __webpack_require__(17); uuidGenerator = __webpack_require__(10); remoteContextHash = {}; Eventric = (function() { function Eventric() { this._handleRemoteRPCRequest = bind(this._handleRemoteRPCRequest, this); var GlobalContext, InmemoryStore, inmemoryRemote; this._logger = __webpack_require__(22); GlobalContext = __webpack_require__(24); inmemoryRemote = __webpack_require__(21); InmemoryStore = __webpack_require__(26); this._contexts = {}; this._params = {}; this._domainEventHandlers = {}; this._domainEventHandlersAll = []; this._storeDefinition = null; this._remoteEndpoints = []; this._globalProjections = []; this._globalContext = new GlobalContext; this.addRemoteEndpoint(inmemoryRemote.endpoint); this.setStore(InmemoryStore, {}); } Eventric.prototype.setLogger = function(logger) { return this._logger = logger; }; Eventric.prototype.getLogger = function() { return this._logger; }; Eventric.prototype.setLogLevel = function(logLevel) { return this._logger.setLogLevel(logLevel); }; Eventric.prototype.setStore = function(StoreClass, storeOptions) { if (storeOptions == null) { storeOptions = {}; } return this._storeDefinition = { Class: StoreClass, options: storeOptions }; }; Eventric.prototype.getStoreDefinition = function() { return this._storeDefinition; }; Eventric.prototype.context = function(name) { var context; if (!name) { throw new Error('Contexts must have a name'); } context = new Context(name); context.subscribeToAllDomainEvents((function(_this) { return function(domainEvent) { return _this._delegateDomainEventToRemoteEndpoints(domainEvent); }; })(this)); this._contexts[name] = context; return context; }; Eventric.prototype.initializeGlobalProjections = function() { var initializeGlobalProjectionsPromise; if (!this._projectionService) { this._projectionService = new Projection(this._globalContext); } initializeGlobalProjectionsPromise = Promise.resolve(); this._globalProjections.forEach((function(_this) { return function(globalProjection) { return initializeGlobalProjectionsPromise = initializeGlobalProjectionsPromise.then(function() { return _this._projectionService.initializeInstance(globalProjection, {}); }); }; })(this)); return initializeGlobalProjectionsPromise; }; Eventric.prototype.addGlobalProjection = function(projectionObject) { return this._globalProjections.push(projectionObject); }; Eventric.prototype.getRegisteredContextNames = function() { return Object.keys(this._contexts); }; Eventric.prototype.setDefaultRemoteClient = function(remoteClient) { return this._defaultRemoteClient = remoteClient; }; Eventric.prototype.remoteContext = function(contextName) { var remote; if (!contextName) { throw new Error('Missing context name'); } if (remoteContextHash[contextName]) { return remoteContextHash[contextName]; } remote = remoteContextHash[contextName] = new Remote(contextName); if (this._defaultRemoteClient) { remote.setClient(this._defaultRemoteClient); } return remote; }; Eventric.prototype.addRemoteEndpoint = function(remoteEndpoint) { this._remoteEndpoints.push(remoteEndpoint); return remoteEndpoint.setRPCHandler(this._handleRemoteRPCRequest); }; Eventric.prototype.generateUuid = function() { return uuidGenerator.generateUuid(); }; Eventric.prototype._handleRemoteRPCRequest = function(request, callback) { var context, error; context = this._contexts[request.contextName]; if (!context) { error = new Error("Tried to handle Remote RPC with not registered context " + request.contextName); this._logger.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"); this._logger.error(error.stack); callback(error, null); return; } if (!(request.functionName in context)) { error = new Error("Remote RPC function " + request.functionName + " not found on Context " + request.contextName); this._logger.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._delegateDomainEventToRemoteEndpoints = function(domainEvent) { return Promise.all(this._remoteEndpoints.map(function(remoteEndpoint) { var publishPromise; publishPromise = Promise.resolve().then(function() { return remoteEndpoint.publish(domainEvent.context, domainEvent.name, domainEvent); }); if (domainEvent.aggregate) { publishPromise = publishPromise.then(function() { return remoteEndpoint.publish(domainEvent.context, domainEvent.name, domainEvent.aggregate.id, domainEvent); }); } return publishPromise; })); }; return Eventric; })(); module.exports = new Eventric; /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(3); /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { var AggregateRepository, Context, domainEventService, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, slice = [].slice; AggregateRepository = __webpack_require__(4); domainEventService = __webpack_require__(12); Context = (function() { function Context(name) { var EventBus, Projection; this.name = name; this._getAggregateRepository = bind(this._getAggregateRepository, this); EventBus = __webpack_require__(14); Projection = __webpack_require__(17); this._logger = __webpack_require__(13).getLogger(); 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._domainEventPayloadConstructors = {}; this._domainEventHandlers = {}; this._projectionObjects = []; this._repositoryInstances = {}; this._storeInstance = null; this._pendingPromises = []; this._eventBus = new EventBus; this._projectionService = new Projection(this); } Context.prototype.initialize = function() { var startOfInitialization; startOfInitialization = new Date; this._logger.debug("eventric context \"" + this.name + "\" initializing"); return this._initializeStore().then((function(_this) { return function() { return _this._initializeProjections(); }; })(this)).then((function(_this) { return function() { var durationOfInitialization, endOfInitialization; endOfInitialization = new Date; durationOfInitialization = endOfInitialization - startOfInitialization; _this._logger.debug("eventric context \"" + _this.name + "\" initialized after " + durationOfInitialization + "ms"); return _this._isInitialized = true; }; })(this)); }; Context.prototype._initializeStore = function() { var eventric, initializeStorePromise, storeDefinition; eventric = __webpack_require__(1); storeDefinition = eventric.getStoreDefinition(); this._storeInstance = new storeDefinition.Class; initializeStorePromise = this._storeInstance.initialize(this, storeDefinition.options); return initializeStorePromise; }; Context.prototype._initializeProjections = function() { var initializeProjectionsPromise; initializeProjectionsPromise = Promise.resolve(); this._projectionObjects.forEach((function(_this) { return function(projectionObject) { return initializeProjectionsPromise = initializeProjectionsPromise.then(function() { return _this._projectionService.initializeInstance(projectionObject, {}); }); }; })(this)); return initializeProjectionsPromise; }; Context.prototype.defineDomainEvent = function(domainEventName, DomainEventPayloadConstructor) { this._domainEventPayloadConstructors[domainEventName] = DomainEventPayloadConstructor; return this; }; Context.prototype.defineDomainEvents = function(domainEventClassesObj) { var DomainEventPayloadConstructor, domainEventName; for (domainEventName in domainEventClassesObj) { DomainEventPayloadConstructor = domainEventClassesObj[domainEventName]; this.defineDomainEvent(domainEventName, DomainEventPayloadConstructor); } return this; }; Context.prototype.addCommandHandlers = function(commandHandlers) { var commandFunction, commandHandlerName; for (commandHandlerName in commandHandlers) { commandFunction = commandHandlers[commandHandlerName]; this._commandHandlers[commandHandlerName] = commandFunction; } return this; }; Context.prototype.addQueryHandlers = function(queryHandlers) { var queryFunction, queryHandlerName; for (queryHandlerName in queryHandlers) { queryFunction = queryHandlers[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.unsubscribeFromDomainEvent = function(subscriberId) { return this._eventBus.unsubscribe(subscriberId); }; Context.prototype.addProjection = function(projectionObject) { this._projectionObjects.push(projectionObject); return this; }; Context.prototype.destroyProjectionInstance = function(projectionId) { return this._projectionService.destroyInstance(projectionId, this); }; Context.prototype.getDomainEventPayloadConstructor = function(domainEventName) { return this._domainEventPayloadConstructors[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, domainEvents) { if (err) { return reject(err); } domainEvents = domainEventService.sortDomainEventsById(domainEvents); return resolve(domainEvents); }])); }; })(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, domainEvents) { if (err) { return reject(err); } domainEvents = domainEventService.sortDomainEventsById(domainEvents); return resolve(domainEvents); }])); }; })(this)); }; Context.prototype.command = function(commandName, params) { var executingCommand; if (this._isDestroyed) { return Promise.reject(new Error("Context " + this.name + " was destroyed, cannot execute command " + commandName + " with arguments " + (JSON.stringify(params)))); } 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().then(function() { return _this._commandHandlers[commandName].apply(commandServicesToInject, [params]); }).then(function(result) { _this._logger.debug('Completed Command', commandName); return resolve(result); })["catch"](function(error) { var commandErrorMessage; commandErrorMessage = "Command \"" + commandName + "\" with arguments " + (JSON.stringify(params)) + " of context \"" + _this.name + "\" rejects with an error"; if (!error) { reject(new Error(commandErrorMessage)); return; } error = _this._extendError(error, commandErrorMessage); return reject(error); }); }; })(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._extendError = function(error, additionalMessage) { error.originalErrorMessage = error.message; error.message = additionalMessage + " - original error message: " + error.originalErrorMessage; return error; }; Context.prototype._getAggregateRepository = function(aggregateName) { return new AggregateRepository({ aggregateName: aggregateName, AggregateClass: this._aggregateClasses[aggregateName], context: this }); }; 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) { _this._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().then(function() { return _this._queryHandlers[queryName].apply(_this._di, [params]); }).then(function(result) { _this._logger.debug("Completed Query " + queryName + " with Result " + result); return resolve(result); })["catch"](function(error) { var queryErrorMessage; queryErrorMessage = "Query \"" + queryName + "\" with arguments " + (JSON.stringify(params)) + " of context \"" + _this.name + "\" rejects with an error"; if (!error) { reject(new Error(queryErrorMessage)); return; } error = _this._extendError(error, queryErrorMessage); return reject(error); }); }; })(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(); }; })(this)).then((function(_this) { return function() { return _this._isDestroyed = true; }; })(this)); }; return Context; })(); module.exports = Context; /***/ }, /* 4 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(5); /***/ }, /* 5 */ /***/ function(module, exports, __webpack_require__) { var Aggregate, AggregateRepository, domainEventService, uuidGenerator, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; Aggregate = __webpack_require__(6); uuidGenerator = __webpack_require__(10); domainEventService = __webpack_require__(12); AggregateRepository = (function() { function AggregateRepository(params) { this.save = bind(this.save, this); this.create = bind(this.create, this); this.load = bind(this.load, this); this._logger = __webpack_require__(13).getLogger(); 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, aggregateDeletedEvent, domainEvent, i; if (error) { reject(error); return; } if (!(domainEvents != null ? domainEvents.length : void 0)) { reject(new Error("No domainEvents for aggregate of type " + _this._aggregateName + " with " + aggregateId + " available")); return; } domainEvents = domainEventService.sortDomainEventsById(domainEvents); aggregateDeletedEvent = null; for (i = domainEvents.length - 1; i >= 0; i += -1) { domainEvent = domainEvents[i]; if (domainEvent.name.indexOf(_this._aggregateName + "Deleted") > -1) { aggregateDeletedEvent = domainEvent; break; } } if (aggregateDeletedEvent != null) { reject(new Error("Aggregate of type " + _this._aggregateName + " with id " + aggregateId + " is marked as deleted because of domain event " + aggregateDeletedEvent.name + " with domain event id " + aggregateDeletedEvent.id)); return; } aggregate = new Aggregate(_this._context, _this._aggregateName, _this._AggregateClass); aggregate.setId(aggregateId); aggregate.applyDomainEvents(domainEvents); _this._installSaveFunctionOnAggregateInstance(aggregate); return resolve(aggregate.instance); }); }; })(this)); }; AggregateRepository.prototype.create = function(params) { return Promise.resolve().then((function(_this) { return function() { 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.setId(uuidGenerator.generateUuid()); _this._installSaveFunctionOnAggregateInstance(aggregate); return Promise.resolve(aggregate.instance.create(params)).then(function() { return aggregate.instance; }); }; })(this)); }; AggregateRepository.prototype._installSaveFunctionOnAggregateInstance = function(aggregate) { return aggregate.instance.$save = (function(_this) { return function() { return _this.save(aggregate); }; })(this); }; AggregateRepository.prototype.save = function(aggregate) { return Promise.resolve().then((function(_this) { return function() { var domainEvents, saveDomainEventQueue, savedDomainEvents; if (!aggregate) { throw new Error("Tried to save unknown aggregate " + _this._aggregateName); } domainEvents = aggregate.getNewDomainEvents(); if (!(domainEvents != null ? domainEvents.length : void 0)) { throw new Error("No new domain events to save for aggregate of type " + _this._aggregateName + " with id " + aggregate.id); } _this._logger.debug("Going to Save and Publish " + domainEvents.length + " DomainEvents from Aggregate " + _this._aggregateName); saveDomainEventQueue = Promise.resolve(); savedDomainEvents = []; domainEvents.forEach(function(domainEvent) { return saveDomainEventQueue = saveDomainEventQueue.then(function() { return _this._store.saveDomainEvent(domainEvent).then(function(domainEvent) { return savedDomainEvents.push(domainEvent); }); }); }); return saveDomainEventQueue.then(function() { savedDomainEvents.forEach(function(domainEvent) { return _this._context.getEventBus().publishDomainEvent(domainEvent)["catch"](function(error) { return _this._logger.error(error.stack || error); }); }); return aggregate.id; }); }; })(this)); }; return AggregateRepository; })(); module.exports = AggregateRepository; /***/ }, /* 6 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(7); /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { var Aggregate, DomainEvent, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; DomainEvent = __webpack_require__(8); Aggregate = (function() { function Aggregate(_context, _name, AggregateClass) { this._context = _context; this._name = _name; this.emitDomainEvent = bind(this.emitDomainEvent, this); this._newDomainEvents = []; this.instance = new AggregateClass; this.instance.$emitDomainEvent = this.emitDomainEvent; } Aggregate.prototype.setId = function(id) { this.id = id; return this.instance.$id = this.id; }; Aggregate.prototype.emitDomainEvent = function(domainEventName, domainEventPayload) { var aggregate, domainEvent; aggregate = { id: this.id, name: this._name }; domainEvent = this._createDomainEvent(domainEventName, domainEventPayload, aggregate); this._newDomainEvents.push(domainEvent); return this._handleDomainEvent(domainEventName, domainEvent); }; Aggregate.prototype._createDomainEvent = function(domainEventName, domainEventConstructorParams, aggregate) { var DomainEventPayloadConstructor, payload; DomainEventPayloadConstructor = this._context.getDomainEventPayloadConstructor(domainEventName); if (!DomainEventPayloadConstructor) { throw new Error("Tried to create domain event '" + domainEventName + "' which is not defined"); } payload = {}; DomainEventPayloadConstructor.apply(payload, [domainEventConstructorParams]); return new DomainEvent({ name: domainEventName, aggregate: aggregate, context: this._context.name, payload: payload }); }; Aggregate.prototype._handleDomainEvent = function(domainEventName, domainEvent) { if (this.instance["handle" + domainEventName]) { return this.instance["handle" + domainEventName](domainEvent); } }; Aggregate.prototype.getNewDomainEvents = function() { return this._newDomainEvents; }; 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; /***/ }, /* 8 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(9); /***/ }, /* 9 */ /***/ function(module, exports) { var DomainEvent; DomainEvent = (function() { function DomainEvent(params) { this.id = params.id; this.name = params.name; this.payload = params.payload; this.aggregate = params.aggregate; this.context = params.context; this.timestamp = new Date().getTime(); } return DomainEvent; })(); module.exports = DomainEvent; /***/ }, /* 10 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(11); /***/ }, /* 11 */ /***/ function(module, exports) { var UuidGenerator; UuidGenerator = (function() { function UuidGenerator() {} UuidGenerator.prototype._uuidTemplate = 'xxxxxxxx-xxxx-4xxx-vxxx-xxxxxxxxxxxx'; UuidGenerator.prototype.generateUuid = function() { var uuid; uuid = this._uuidTemplate.replace(/[xv]/g, function(characterToReplace) { var randomNumber, variant; randomNumber = Math.floor(Math.random() * 16); if (characterToReplace === 'x') { return randomNumber.toString(16); } else { variant = randomNumber & 0x3 | 0x8; return variant.toString(16); } }); return uuid; }; return UuidGenerator; })(); module.exports = new UuidGenerator; /***/ }, /* 12 */ /***/ function(module, exports) { var DomainEventService; DomainEventService = (function() { function DomainEventService() {} DomainEventService.prototype.sortDomainEventsById = function(domainEvents) { return domainEvents.sort(function(firstDomainEvent, secondDomainEvent) { return firstDomainEvent.id - secondDomainEvent.id; }); }; return DomainEventService; })(); module.exports = new DomainEventService; /***/ }, /* 13 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(1); /***/ }, /* 14 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(15); /***/ }, /* 15 */ /***/ function(module, exports, __webpack_require__) { var EventBus, Subscriber; Subscriber = __webpack_require__(16); 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({ eventName: eventName, subscriberFunction: subscriberFunction, subscriberId: _this._getNextSubscriberId() }); _this._subscribers.push(subscriber); return resolve(subscriber.subscriberId); }; })(this)); }; EventBus.prototype._getNextSubscriberId = function() { return this._subscriberId++; }; EventBus.prototype.publishDomainEvent = function(domainEvent) { return new Promise((function(_this) { return function(resolve, reject) { var publishOperation; _this._verifyPublishIsPossible(domainEvent); publishOperation = function() { return _this._notifySubscribers(domainEvent).then(resolve)["catch"](reject); }; return _this._enqueueEventPublishing(publishOperation); }; })(this)); }; EventBus.prototype._verifyPublishIsPossible = function(domainEvent) { var errorMessage, ref; if (this._isDestroyed) { errorMessage = "Event Bus was destroyed, cannot publish " + domainEvent.name + "\nwith payload " + (JSON.stringify(domainEvent.payload)); if ((ref = domainEvent.aggregate) != null ? ref.id : void 0) { errorMessage += " and aggregate id " + domainEvent.aggregate.id; } throw new Error(errorMessage); } }; EventBus.prototype._notifySubscribers = function(domainEvent) { return Promise.resolve().then((function(_this) { return function() { var subscribers; subscribers = _this._getSubscribersForDomainEvent(domainEvent); return Promise.all(subscribers.map(function(subscriber) { return subscriber.subscriberFunction(domainEvent); })); }; })(this)); }; EventBus.prototype._getSubscribersForDomainEvent = function(domainEvent) { var ref, subscribers; subscribers = this._subscribers.filter(function(subscriber) { return subscriber.eventName === '*'; }); subscribers = subscribers.concat(this._subscribers.filter(function(subscriber) { return subscriber.eventName === domainEvent.name; })); if ((ref = domainEvent.aggregate) != null ? ref.id : void 0) { subscribers = subscribers.concat(this._subscribers.filter(function(subscriber) { return subscriber.eventName === (domainEvent.name + "/" + domainEvent.aggregate.id); })); } return subscribers; }; EventBus.prototype._enqueueEventPublishing = function(publishOperation) { return this._eventPublishQueue = this._eventPublishQueue.then(publishOperation); }; EventBus.prototype.unsubscribe = function(subscriberId) { return Promise.resolve().then((function(_this) { return function() { return _this._subscribers = _this._subscribers.filter(function(subscriber) { return subscriber.subscriberId !== subscriberId; }); }; })(this)); }; EventBus.prototype.destroy = function() { return this._waitForEventPublishQueue().then((function(_this) { return function() { return _this._isDestroyed = true; }; })(this)); }; EventBus.prototype._waitForEventPublishQueue = function() { var currentEventPublishQueue; currentEventPublishQueue = this._eventPublishQueue; return currentEventPublishQueue.then((function(_this) { return function() { if (_this._eventPublishQueue !== currentEventPublishQueue) { return _this._waitForEventPublishQueue(); } }; })(this)); }; return EventBus; })(); module.exports = EventBus; /***/ }, /* 16 */ /***/ function(module, exports) { var Subscriber; Subscriber = (function() { function Subscriber(arg) { this.eventName = arg.eventName, this.subscriberFunction = arg.subscriberFunction, this.subscriberId = arg.subscriberId; } return Subscriber; })(); module.exports = Subscriber; /***/ }, /* 17 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(18); /***/ }, /* 18 */ /***/ function(module, exports, __webpack_require__) { var ProjectionService, uuidGenerator; uuidGenerator = __webpack_require__(10); ProjectionService = (function() { function ProjectionService(_context) { this._context = _context; this._logger = __webpack_require__(13).getLogger(); this._handlerFunctions = {}; this._projectionInstances = {}; } ProjectionService.prototype.initializeInstance = function(projectionInstance, params) { var aggregateId, diFn, diName, eventNames, projectionId, ref; if (this._context._di) { ref = this._context._di; for (diName in ref) { diFn = ref[diName]; projectionInstance[diName] = diFn; } } projectionId = uuidGenerator.generateUuid(); aggregateId = null; projectionInstance.$subscribeHandlersWithAggregateId = function(_aggregateId) { if (!_aggregateId) { throw new Error('Missing aggregate id'); } return aggregateId = _aggregateId; }; eventNames = null; return this._callInitializeOnProjection(projectionInstance, params).then((function(_this) { return function() { return _this._parseEventNamesFromProjection(projectionInstance); }; })(this)).then((function(_this) { return function(_eventNames) { eventNames = _eventNames; return _this._applyDomainEventsFromStoreToProjection(projectionInstance, eventNames, aggregateId); }; })(this)).then((function(_this) { return function() { return _this._subscribeProjectionToDomainEvents(projectionId, projectionInstance, eventNames, aggregateId); }; })(this)).then((function(_this) { return function() { return _this._projectionInstances[projectionId] = projectionInstance; }; })(this)).then(function() { return projectionInstance.isInitialized = true; }).then(function() { return projectionId; }); }; ProjectionService.prototype._callInitializeOnProjection = function(projection, params) { return new Promise(function(resolve) { if (!projection.initialize) { return resolve(projection); } return projection.initialize(params, function() { return resolve(projection); }); }); }; ProjectionService.prototype._parseEventNamesFromProjection = function(projection) { return new Promise(function(resolve) { 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); }); }; ProjectionService.prototype._applyDomainEventsFromStoreToProjection = function(projection, eventNames, aggregateId) { var findEvents; 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); }); }); return applyDomainEventsToProjectionPromise; }; })(this)); }; ProjectionService.prototype._subscribeProjectionToDomainEvents = function(projectionId, projection, eventNames, aggregateId) { var domainEventHandler, subscribeProjectionToDomainEventsPromise; domainEventHandler = (function(_this) { return function(domainEvent) { return _this._applyDomainEventToProjection(domainEvent, projection); }; })(this); this._handlerFunctions[projectionId] = []; 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) { return _this._handlerFunctions[projectionId].push(subscriberId); }); }; })(this)); return subscribeProjectionToDomainEventsPromise; }; ProjectionService.prototype._applyDomainEventToProjection = function(domainEvent, projection) { return Promise.resolve().then((function(_this) { return function() { if (!projection["handle" + domainEvent.name]) { _this._logger.warn("ProjectionService: handle" + domainEvent.name + " not defined"); } return projection["handle" + domainEvent.name](domainEvent); }; })(this)); }; ProjectionService.prototype.getInstance = function(projectionId) { return this._projectionInstances[projectionId]; }; ProjectionService.prototype.destroyInstance = function(projectionId) { var i, len, ref, subscriberId, unsubscribePromises; if (!projectionId) { return Promise.reject(new Error('Missing projection id')); } if (!this._handlerFunctions[projectionId]) { return Promise.reject(new Error("Projection with id \"" + projectionId + "\" is not initialized")); } 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 ProjectionService; })(); module.exports = ProjectionService; /***/ }, /* 19 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(20); /***/ }, /* 20 */ /***/ function(module, exports, __webpack_require__) { var Remote; Remote = (function() { Remote.ALLOWED_RPC_OPERATIONS = ['command', 'query', 'findDomainEventsByName', 'findDomainEventsByNameAndAggregateId']; function Remote(_co