base-domain
Version:
simple module to help build Domain-Driven Design
271 lines (191 loc) • 5.63 kB
text/coffeescript
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 () method.
BaseModel
Base
base-domain
###
class BaseModel extends Base
: false
###*
key-value pair representing typeName - type
use for definition of for each extender
TYPES
Object
###
: TypeInfo.TYPES
###*
key-value pair representing property's name - type of the model
firstName : .STRING
lastName : .STRING
age : .NUMBER
registeredAt : .DATE
team : .MODEL 'team'
hobbies : .MODEL_LIST 'hobby'
info : .ANY
see type-info.coffee for full options.
properties
Object
###
: {}
###*
get an instance of PropInfo, which summarizes properties of this class
getPropInfo
{PropInfo}
###
: null
: ->
?= new PropInfo , ()
###*
extend of Parent class
class Parent extends BaseModel
:
prop1: .STRING
class ChildModel extends ParentModel
:
prop2: .NUMBER
ChildModel.properties # prop1 and prop2
withParentProps
{Object}
###
: (props = {}) ->
props[k] ?= v for k, v of # === parent's properties
return props
###*
get list of properties which contains entity
getEntityProps
{Array}
###
: ->
().entityProps
###*
get list of properties which contains relational model
getModelProps
{Object} [options]
{Boolean} [options.includeList] include props of BaseList
{Array}
###
: (options = {}) ->
propInfo = ()
ret = propInfo.modelProps.slice()
ret.concat propInfo.listProps if options.includeList
return ret
###*
###
constructor: (obj) ->
obj if obj
getTypeInfo: (prop) ->
.getPropInfo().dic[prop]
isEntityProp: (prop) ->
.getPropInfo().isEntityProp prop
###*
set value to prop
{BaseModel} this
###
set: (prop, value) ->
if typeof prop is 'object'
(k, v) for k, v of prop
return @
typeInfo = prop
if typeInfo?.model and prop
(prop, value)
else
(prop, value)
return @
###*
set model prop
{BaseModel} this
###
setNonEntityProp: (prop, value) ->
@[prop] = value
###*
set related model(s)
setEntityProp
{String} prop property name of the related model
{Entity|Array<Entity>} submodel
{BaseModel} this
###
setEntityProp: (prop, submodel) ->
typeInfo = prop
modelName = typeInfo.model
@[prop] = submodel
idPropName = typeInfo.idPropName
@[idPropName] = submodel?.id
return @
###*
unset related model(s)
{String} prop property name of the related models
{BaseModel} this
unsetEntityProp
###
unsetEntityProp: (prop) ->
typeInfo = (prop)
@[prop] = undefined
@[typeInfo.idPropName] = undefined
return @
###*
inherit value of anotherModel
inherit
{BaseModel} anotherModel
{BaseModel} this
###
inherit: (anotherModel) ->
for own k, v of anotherModel
if v?
@[k] = v
return @
###*
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)
toPlainObject
{Object} plainObject
###
toPlainObject: ->
facade = ()
plainObject = {}
for own prop, value of @
# remove entities
if prop
continue
typeInfo = prop
continue if typeInfo?.tmp
# set non-model properties
if not typeInfo?.model?
plainObject[prop] = value
continue
# plainize submodels, lists
if typeof value?.toPlainObject is 'function'
plainObject[prop] = value.toPlainObject()
else
plainObject[prop] = value
return plainObject
###*
include all relational models if not set
include
{Object} [options]
{Boolean} [options.recursive] recursively include models or not
{Promise(BaseModel)} self
###
include: (options = {}) ->
new Includer(@).include(recursive: options.recursive)
module.exports = BaseModel