base-domain
Version:
simple module to help build Domain-Driven Design
399 lines (284 loc) • 7.7 kB
text/coffeescript
'use strict'
ValueObject = require './value-object'
EntityPool = require '../entity-pool'
BaseModel = require './base-model'
###*
collection model of one model
Collection
ValueObject
base-domain
###
class Collection extends ValueObject
###*
model name of the item
itemModelName
String
###
: null
###*
the number of items (or ids when is true)
{Number} length
###
Object.defineProperty @::, 'length',
get: ->
if
return .length
else
return
###*
items (submodel collection)
{Object} items
###
###*
{any} props
{RootInterface} root
###
constructor: (props = {}, root) ->
(root)
if not .itemModelName?
throw 'base-domain:itemModelNameRequired', "@itemModelName is not set, in class #{@constructor.name}"
_itemFactory = null
isItemEntity = ().getModel(.itemModelName).isEntity
Object.defineProperties @,
###*
item factory
Created only one time. Be careful that is not changed even the collection's root is changed.
{FactoryInterface} itemFactory
###
itemFactory:
get: -> _itemFactory ?= require('./general-factory').create(.itemModelName, )
isItemEntity:
value: isItemEntity, writable: false
()
if props.ids? and props.items
{ ids } = props
delete props.ids
super(props, root)
props.ids = ids
else
super(props, root)
###*
Get the copy of ids
{Array(String)} ids
###
getIds: ->
return undefined if not
return ?.slice()
###*
set value to prop
{BaseModel} this
###
set: (k, v) ->
switch k
when 'items'
v
when 'ids'
v
else
super
return @
###*
add new submodel to item(s)
add
{BaseModel|Object} ...items
###
add: (items...) ->
(items)
###*
addItems
{Object|Array(BaseModel|Object)} items
###
addItems: (items = []) ->
() if not ()
factory =
for key, item of items
(factory.createFromObject item)
if
= (item.id for item in ())
###*
add item to
addItem
{BaseModel} item
###
addItem: (item) ->
###*
clear and set ids.
setIds
{Array(String|Number)} ids
###
setIds: (ids = []) ->
return if not
return if not Array.isArray ids
()
= ids
###*
clear and add items
setItems
{Object|Array(BaseModel|Object)} items
###
setItems: (items = []) ->
()
(items)
return @
###*
removes all items and ids
clear
###
clear: ->
delete
if
= []
###*
export items to Array
toArray
{Array}
###
toArray: ->
###*
Execute given function for each item
forEach
{Function} fn
{Object} _this
###
forEach: (fn, _this) ->
(fn, _this)
return
###*
Execute given function for each item
returns an array of the result
map
{Function} fn
{Object} _this
{Array}
###
map: (fn, _this) ->
_this ?= @
return [] if typeof fn isnt 'function'
(fn.call(_this, item) for item in ())
###*
Filter items with given function
filter
{Function} fn
{Object} _this
{Array}
###
filter: (fn, _this) ->
_this ?= @
return () if typeof fn isnt 'function'
().filter(fn, _this)
###*
Returns if some items match the condition in given function
some
{Function} fn
{Object} _this
{Boolean}
###
some: (fn, _this) ->
_this ?= @
return false if typeof fn isnt 'function'
().some(fn, _this)
###*
Returns if every items match the condition in given function
every
{Function} fn
{Object} _this
{Boolean}
###
every: (fn, _this) ->
_this ?= @
return false if typeof fn isnt 'function'
().every(fn, _this)
initItems: ->
###*
include all relational models if not set
include
{Object} [options]
{Boolean} [options.recursive] recursively include models or not
{Boolean} [options.async=true] get async values
{Array(String)} [options.props] include only given props
{Promise(BaseModel)} self
###
include: (options = {}) ->
options.entityPool ?= new EntityPool
superResult = super(options)
if not
(options, superResult)
else
(options, superResult)
includeVOItems: (options, superResult) ->
return superResult if not options.recursive
Promise.all([
superResult
Promise.all (item) -> item.include(options)
]).then => @
includeEntityItems: (options, superResult) ->
EntityCollectionIncluder = require './entity-collection-includer'
Promise.all([
superResult
new EntityCollectionIncluder(@, options).include()
]).then => @
###*
create plain object.
if this dict contains entities, returns their ids
if this dict contains non-entity models, returns their plain objects
toPlainObject
{Object} plainObject
###
toPlainObject: ->
plain = super()
if
plain.ids = .slice()
delete plain.items
else if ()
plainItems = for key, item of
if typeof item.toPlainObject is 'function'
item.toPlainObject()
else
item
plain.items = plainItems
return plain
###*
clone the model as a plain object
clone
{BaseModel}
###
plainClone: ->
plain = super()
if ()
plain.items = for key, item of
if item instanceof BaseModel
item.plainClone()
else
item
return plain
###*
loaded
{Boolean}
###
loaded: -> ?
###*
get item model
getItemModelClass
{Function}
###
getItemModelClass: ->
().getModel(.itemModelName)
module.exports = Collection