@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.
172 lines (150 loc) • 4.43 kB
JavaScript
var debug = require('debug')('domain:aggregate'),
dotty = require('dotty'),
_ = require('lodash'),
jsondate = require('jsondate');
/**
* Aggregate constructor
* @param {String} id The aggregate id.
* @param {Object} modelInitValues Initialization values for model like: { emails: [] } [optional]
* @constructor
*/
function AggregateModel (id, modelInitValues) {
if (!id || !_.isString(id)) {
var err = new Error('No id injected!');
debug(err);
throw err;
}
this.id = id;
if (modelInitValues instanceof AggregateModel) {
this.attributes = modelInitValues.toJSON();
} else {
this.attributes = _.cloneDeep(modelInitValues || {});
}
this.attributes.id = this.id;
this.attributes._destroyed = this.attributes._destroyed || false;
this.attributes._revisions = this.attributes._revisions || {};
this.attributes._revision = this.attributes._revision || 0;
this.uncommittedEvents = [];
}
AggregateModel.prototype = {
/**
* Marks this aggregate as destroyed.
*/
destroy: function () {
this.set('_destroyed', true);
},
/**
* Returns true if this aggregate is destroyed.
* @returns {boolean}
*/
isDestroyed: function () {
return !!this.get('_destroyed');
},
/**
* Sets the revision for this aggregate.
* @param {Object} streamInfo The stream info.
* @param {Number} rev The revision number.
*/
setRevision: function (streamInfo, rev) {
this.set('_revision', rev);
streamInfo.context = streamInfo.context || '_general';
this.get('_revisions')[streamInfo.context + '_' + streamInfo.aggregate + '_' + streamInfo.aggregateId] = rev;
},
/**
* Returns the revision of this aggregate.
* @param {Object} streamInfo The stream info.
* @returns {Number}
*/
getRevision: function (streamInfo) {
if (!streamInfo) {
return this.get('_revision');
}
streamInfo.context = streamInfo.context || '_general';
return this.get('_revisions')[streamInfo.context + '_' + streamInfo.aggregate + '_' + streamInfo.aggregateId] || 0;
},
/**
* Returns all uncommitted events.
* @returns {Array}
*/
getUncommittedEvents: function () {
return this.uncommittedEvents;
},
/**
* Adds/Saves an uncommitted event.
* @param {Object} evt The event object.
*/
addUncommittedEvent: function (evt) {
this.uncommittedEvents.push(evt);
},
/**
* Clears the internal uncomitted event list.
*/
clearUncommittedEvents: function () {
this.uncommittedEvents = [];
},
/**
* The toJSON function will be called when JSON.stringify().
* @return {Object} A clean Javascript object containing all attributes.
*/
toJSON: function () {
return jsondate.parse(JSON.stringify(this.attributes));
// return _.cloneDeep(this.attributes);
},
/**
* Sets attributes for the aggregate.
*
* @example:
* aggregate.set('firstname', 'Jack');
* // or
* aggregate.set({
* firstname: 'Jack',
* lastname: 'X-Man'
* });
*/
set: function (data) {
if (arguments.length === 2) {
dotty.put(this.attributes, arguments[0], arguments[1]);
} else if (_.isObject(data)) {
for (var m in data) {
dotty.put(this.attributes, m, data[m]);
}
}
},
/**
* Gets an attribute of the vm.
* @param {String} attr The attribute name.
* @return {Object} The result value.
*
* @example:
* aggregate.get('firstname'); // returns 'Jack'
*/
get: function (attr) {
return dotty.get(this.attributes, attr);
},
/**
* Returns `true` if the attribute contains a value that is not null
* or undefined.
* @param {String} attr The attribute name.
* @return {Boolean} The result value.
*
* @example:
* aggregate.has('firstname'); // returns true or false
*/
has: function (attr) {
return (this.get(attr) !== null && this.get(attr) !== undefined);
},
/**
* Resets the attributes for the aggregate.
*/
reset: function (data) {
if (data instanceof AggregateModel) {
this.attributes = data.toJSON();
} else {
this.attributes = _.cloneDeep(data || {});
}
this.attributes.id = this.id;
this.attributes._destroyed = this.attributes._destroyed || false;
this.attributes._revision = this.attributes._revision || 0;
}
};
module.exports = AggregateModel;