UNPKG

@orchestrated-io/cqrs-domain

Version:

Node-cqrs-domain is a node.js module based on node-eventstore. It can be very useful as domain component if you work with (d)ddd, cqrs, eventdenormalizer, host, etc.

140 lines (114 loc) 3.91 kB
var debug = require('debug')('domain:commandDispatcher'), _ = require('lodash'), dotty = require('dotty'), DuplicateCommandError = require('./errors/duplicateCommandError'); /** * CommandDispatcher constructor * @param {Object} tree The tree object. * @param {Object} definition The definition object. * @param {Object} commandBunper The commandBumper object. [optional] * @constructor */ function CommandDispatcher (tree, definition, commandBumper) { if (!tree || !_.isObject(tree) || !_.isFunction(tree.getCommandHandler)) { var err = new Error('Please pass a valid tree!'); debug(err); throw err; } if (!definition || !_.isObject(definition)) { var err = new Error('Please pass a valid command definition!'); debug(err); throw err; } this.tree = tree; this.definition = definition; this.commandBumper = commandBumper; } CommandDispatcher.prototype = { /** * Returns the target information of this command. * @param {Object} cmd The passed command. * @returns {{name: 'commandName', aggregateId: 'aggregateId', version: 0, aggregate: 'aggregateName', context: 'contextName'}} */ getTargetInformation: function (cmd) { if (!cmd || !_.isObject(cmd)) { var err = new Error('Please pass a valid command!'); debug(err); throw err; } var aggregateId = null; if (dotty.exists(cmd, this.definition.aggregateId)) { aggregateId = dotty.get(cmd, this.definition.aggregateId); } else { debug('no aggregateId found, seems to be for a new aggregate'); } var name = dotty.get(cmd, this.definition.name); var version = 0; if (dotty.exists(cmd, this.definition.version)) { version = dotty.get(cmd, this.definition.version); } else { debug('no version found, handling as version: 0'); } var aggregate = null; if (dotty.exists(cmd, this.definition.aggregate)) { aggregate = dotty.get(cmd, this.definition.aggregate); } else { debug('no aggregate found, will lookup in all aggregates'); } var context = null; if (dotty.exists(cmd, this.definition.context)) { context = dotty.get(cmd, this.definition.context); } else { debug('no aggregateName found, will lookup in all contexts'); } return { name: name, aggregateId: aggregateId, version: version, aggregate: aggregate, context: context }; }, /** * Dispatches a command. * @param {Object} cmd The passed command. * @param {Function} callback The function, that will be called when this action is completed. * `function(err, evts){}` */ dispatch: function (cmd, callback) { if (!cmd || !_.isObject(cmd)) { var err = new Error('Please pass a valid command!'); debug(err); throw err; } if (!callback || !_.isFunction(callback)) { var err = new Error('Please pass a valid callback!'); debug(err); throw err; } var target = this.getTargetInformation(cmd); var commandHandler = this.tree.getCommandHandler(target); // if (!commandHandler) { // commandHandler = this.tree.getCommandHandlerByOldTarget(target); // } if (!commandHandler) { var err = new Error('No command handler found for ' + target.name); debug(err); return callback(err); } if (!this.commandBumper) { return commandHandler.handle(cmd, callback); } var key = target.context + target.aggregate + target.aggregateId + dotty.get(cmd, this.definition.id); this.commandBumper.add(key, function (err, added) { if (err) { return callback(err); } if (!added) { return callback(new DuplicateCommandError('Command already seen!')); } commandHandler.handle(cmd, callback); }); } }; module.exports = CommandDispatcher;