UNPKG

base-domain

Version:

simple module to help build Domain-Driven Design

333 lines (253 loc) 7.03 kB
var Base, BaseModel, Includer, PropInfo, TypeInfo, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; TypeInfo = require('./type-info'); PropInfo = require('./prop-info'); Base = require('./base'); Includer = require('./includer'); /** Base model class of DDD pattern. the parent "Base" class just simply gives a @getFacade() method. @class BaseModel @extends Base @module base-domain */ BaseModel = (function(superClass) { extend(BaseModel, superClass); BaseModel.isEntity = false; /** key-value pair representing typeName - type use for definition of @properties for each extender @property TYPES @protected @final @static @type Object */ BaseModel.TYPES = TypeInfo.TYPES; /** key-value pair representing property's name - type of the model firstName : @TYPES.STRING lastName : @TYPES.STRING age : @TYPES.NUMBER registeredAt : @TYPES.DATE team : @TYPES.MODEL 'team' hobbies : @TYPES.MODEL_LIST 'hobby' info : @TYPES.ANY see type-info.coffee for full options. @property properties @abstract @static @protected @type Object */ BaseModel.properties = {}; /** get an instance of PropInfo, which summarizes properties of this class @method getPropInfo @public @return {PropInfo} */ BaseModel._pi = null; BaseModel.getPropInfo = function() { return this._pi != null ? this._pi : this._pi = new PropInfo(this.properties, this.getFacade()); }; /** extend @properties of Parent class @example class Parent extends BaseModel @properties: prop1: @TYPES.STRING class ChildModel extends ParentModel @properties: @withParentProps prop2: @TYPES.NUMBER ChildModel.properties # prop1 and prop2 @method withParentProps @protected @static @return {Object} */ BaseModel.withParentProps = function(props) { var k, ref, v; if (props == null) { props = {}; } ref = this.properties; for (k in ref) { v = ref[k]; if (props[k] == null) { props[k] = v; } } return props; }; /** get list of properties which contains entity @method getEntityProps @public @static @return {Array} */ BaseModel.getEntityProps = function() { return this.getPropInfo().entityProps; }; /** get list of properties which contains relational model @method getModelProps @public @static @param {Object} [options] @param {Boolean} [options.includeList] include props of BaseList @return {Array} */ BaseModel.getModelProps = function(options) { var propInfo, ret; if (options == null) { options = {}; } propInfo = this.getPropInfo(); ret = propInfo.modelProps.slice(); if (options.includeList) { ret.concat(propInfo.listProps); } return ret; }; /** @constructor */ function BaseModel(obj) { if (obj) { this.set(obj); } } BaseModel.prototype.getTypeInfo = function(prop) { return this.constructor.getPropInfo().dic[prop]; }; BaseModel.prototype.isEntityProp = function(prop) { return this.constructor.getPropInfo().isEntityProp(prop); }; /** set value to prop @return {BaseModel} this */ BaseModel.prototype.set = function(prop, value) { var k, typeInfo, v; if (typeof prop === 'object') { for (k in prop) { v = prop[k]; this.set(k, v); } return this; } typeInfo = this.getTypeInfo(prop); if ((typeInfo != null ? typeInfo.model : void 0) && this.isEntityProp(prop)) { this.setEntityProp(prop, value); } else { this.setNonEntityProp(prop, value); } return this; }; /** set model prop @return {BaseModel} this */ BaseModel.prototype.setNonEntityProp = function(prop, value) { return this[prop] = value; }; /** set related model(s) @method setEntityProp @param {String} prop property name of the related model @param {Entity|Array<Entity>} submodel @return {BaseModel} this */ BaseModel.prototype.setEntityProp = function(prop, submodel) { var idPropName, modelName, typeInfo; typeInfo = this.getTypeInfo(prop); modelName = typeInfo.model; this[prop] = submodel; idPropName = typeInfo.idPropName; this[idPropName] = submodel != null ? submodel.id : void 0; return this; }; /** unset related model(s) @param {String} prop property name of the related models @return {BaseModel} this @method unsetEntityProp */ BaseModel.prototype.unsetEntityProp = function(prop) { var typeInfo; typeInfo = this.getTypeInfo(prop); this[prop] = void 0; this[typeInfo.idPropName] = void 0; return this; }; /** inherit value of anotherModel @method inherit @param {BaseModel} anotherModel @return {BaseModel} this */ BaseModel.prototype.inherit = function(anotherModel) { var k, v; for (k in anotherModel) { if (!hasProp.call(anotherModel, k)) continue; v = anotherModel[k]; if (v != null) { this[k] = v; } } return this; }; /** create plain object without relational entities descendants of Entity are removed, but not descendants of BaseModel descendants of Entity in descendants of BaseModel are removed ( = recursive) @method toPlainObject @return {Object} plainObject */ BaseModel.prototype.toPlainObject = function() { var facade, plainObject, prop, typeInfo, value; facade = this.getFacade(); plainObject = {}; for (prop in this) { if (!hasProp.call(this, prop)) continue; value = this[prop]; if (this.isEntityProp(prop)) { continue; } typeInfo = this.getTypeInfo(prop); if (typeInfo != null ? typeInfo.tmp : void 0) { continue; } if ((typeInfo != null ? typeInfo.model : void 0) == null) { plainObject[prop] = value; continue; } if (typeof (value != null ? value.toPlainObject : void 0) === 'function') { plainObject[prop] = value.toPlainObject(); } else { plainObject[prop] = value; } } return plainObject; }; /** include all relational models if not set @method include @param {Object} [options] @param {Boolean} [options.recursive] recursively include models or not @return {Promise(BaseModel)} self */ BaseModel.prototype.include = function(options) { if (options == null) { options = {}; } return new Includer(this).include({ recursive: options.recursive }); }; return BaseModel; })(Base); module.exports = BaseModel;