UNPKG

base-domain

Version:

simple module to help build Domain-Driven Design

301 lines (220 loc) 5.86 kB
BaseModel = require './base-model' ###* dictionary-structured data model @class BaseDict @extends BaseModel @module base-domain ### class BaseDict extends BaseModel ###* model name of the item @property itemModelName @static @protected @type String ### @itemModelName: '' ###* get unique key from item @method key @static @protected ### @key: (item) -> item.id ###* creates child class of BaseDict @method getAnonymousClass @params {String} itemModelName @return {Function} child class of BaseDict ### @getAnonymousClass: (itemModelName) -> class AnonymousDict extends BaseDict @itemModelName: itemModelName @isAnonymous: true return AnonymousDict ###* ids: get ids of items @property ids @type Array @public ### Object.defineProperty @::, 'ids', get: -> return null if not @constructor.containsEntity() return (item.id for key, item of @items) ###* items: dictionary of keys - models @property items @type Objects ### ###* loaded: is data loaded or not @property loaded @type Boolean ### ###* itemFactory: instance of factory which creates item models @property itemFactory @type BaseFactory ### ###* @constructor ### constructor: (props = {}) -> # loaded and listeners are hidden properties _itemFactory = null Object.defineProperties @, items : value: {}, enumerable: true loaded : value: false, writable: true listeners : value: [] itemFactory : get: -> _itemFactory ?= @getFacade().createFactory(@constructor.itemModelName, true) if props.items @setItems props.items if props.ids @setIds props.ids super(props) ###* check if the model has submodel of the given key or not @method has @public @param {String|Number} key @return {Boolean} ### has: (key) -> @items[key]? ###* check if the model contains the given submodel or not @method contains @public @param {BaseModel} item @return {Boolean} ### contains: (item) -> key = @constructor.key item sameKeyItem = @get(key) item is sameKeyItem ###* return submodel of the given key @method get @public @param {String|Number} key @return {BaseModel} ### get: (key) -> @items[key] ###* add new submodel to item(s) @method get @public @param {BaseModel} item ### add: (items...) -> ItemClass = @getFacade().getModel @constructor.itemModelName for prevKey, item of items when item instanceof ItemClass key = @constructor.key item @items[key] = item ###* remove submodel from items both acceptable, keys and submodels @method remove @public @param {BaseModel|String|Number} item ### remove: (args...) -> ItemClass = @getFacade().getModel @constructor.itemModelName for arg in args if arg instanceof ItemClass key = @constructor.key(arg) else key = arg delete @items[key] return ###* set ids. @method setIds @param {Array(String|Number)} ids ### setIds: (ids = []) -> return if not @constructor.containsEntity() @loaded = false ItemRepository = @getFacade().getRepository(@constructor.itemModelName) repo = new ItemRepository() if ItemRepository.storeMasterTable and ItemRepository.loaded() subModels = (repo.getByIdSync(id) for id in ids) @setItems(subModels) else repo.query(where: id: inq: ids).then (subModels) => @setItems(subModels) return @ ###* set items from dic object update to new key @method setItems @param {Object|Array} models ### setItems: (models = {}) -> items = (item for prevKey, item of models) @add items... @loaded = true @emitLoaded() return @ ###* returns item is Entity @method containsEntity @static @public @return {Boolean} ### @containsEntity: -> return @getFacade().getModel(@itemModelName).isEntity ###* export models to Array @method toArray @public ### toArray: -> (item for key, item of @items) ###* create plain dict. if this dict contains entities, returns their ids if this dict contains non-entity models, returns their plain objects @method toPlainObject @return {Object} plainObject ### toPlainObject: -> plain = super() if @constructor.containsEntity() plain.ids = @ids delete plain.items else plainItems = [] for key, item of @items if typeof item.toPlainObject is 'function' plainItems[key] = item.toPlainObject() else plainItems[key] = item plain.items = plainItems return plain ###* on addEventlisteners for 'loaded' @method on @public ### on: (evtname, fn) -> return if evtname isnt 'loaded' if @loaded process.nextTick fn else if typeof fn is 'function' @listeners.push fn return ###* tell listeners emit loaded @method emitLoaded @private ### emitLoaded: -> while fn = @listeners.shift() process.nextTick fn return module.exports = BaseDict