UNPKG

base-domain

Version:

simple module to help build Domain-Driven Design

436 lines (347 loc) 8.53 kB
var BaseDict, BaseModel, 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, slice = [].slice; BaseModel = require('./base-model'); /** dictionary-structured data model @class BaseDict @extends BaseModel @module base-domain */ BaseDict = (function(superClass) { extend(BaseDict, superClass); /** model name of the item @property itemModelName @static @protected @type String */ BaseDict.itemModelName = ''; /** get unique key from item @method key @static @protected */ BaseDict.key = function(item) { return item.id; }; /** creates child class of BaseDict @method getAnonymousClass @params {String} itemModelName @return {Function} child class of BaseDict */ BaseDict.getAnonymousClass = function(itemModelName) { var AnonymousDict; AnonymousDict = (function(superClass1) { extend(AnonymousDict, superClass1); function AnonymousDict() { return AnonymousDict.__super__.constructor.apply(this, arguments); } AnonymousDict.itemModelName = itemModelName; AnonymousDict.isAnonymous = true; return AnonymousDict; })(BaseDict); return AnonymousDict; }; /** ids: get ids of items @property ids @type Array @public */ Object.defineProperty(BaseDict.prototype, 'ids', { get: function() { var item, key; if (!this.constructor.containsEntity()) { return null; } return (function() { var ref, results; ref = this.items; results = []; for (key in ref) { item = ref[key]; results.push(item.id); } return results; }).call(this); } }); /** 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 */ function BaseDict(props) { var _itemFactory; if (props == null) { props = {}; } _itemFactory = null; Object.defineProperties(this, { items: { value: {}, enumerable: true }, loaded: { value: false, writable: true }, listeners: { value: [] }, itemFactory: { get: function() { return _itemFactory != null ? _itemFactory : _itemFactory = this.getFacade().createFactory(this.constructor.itemModelName, true); } } }); if (props.items) { this.setItems(props.items); } if (props.ids) { this.setIds(props.ids); } BaseDict.__super__.constructor.call(this, props); } /** check if the model has submodel of the given key or not @method has @public @param {String|Number} key @return {Boolean} */ BaseDict.prototype.has = function(key) { return this.items[key] != null; }; /** check if the model contains the given submodel or not @method contains @public @param {BaseModel} item @return {Boolean} */ BaseDict.prototype.contains = function(item) { var key, sameKeyItem; key = this.constructor.key(item); sameKeyItem = this.get(key); return item === sameKeyItem; }; /** return submodel of the given key @method get @public @param {String|Number} key @return {BaseModel} */ BaseDict.prototype.get = function(key) { return this.items[key]; }; /** add new submodel to item(s) @method get @public @param {BaseModel} item */ BaseDict.prototype.add = function() { var ItemClass, item, items, key, prevKey, results; items = 1 <= arguments.length ? slice.call(arguments, 0) : []; ItemClass = this.getFacade().getModel(this.constructor.itemModelName); results = []; for (prevKey in items) { item = items[prevKey]; if (!(item instanceof ItemClass)) { continue; } key = this.constructor.key(item); results.push(this.items[key] = item); } return results; }; /** remove submodel from items both acceptable, keys and submodels @method remove @public @param {BaseModel|String|Number} item */ BaseDict.prototype.remove = function() { var ItemClass, arg, args, i, key, len; args = 1 <= arguments.length ? slice.call(arguments, 0) : []; ItemClass = this.getFacade().getModel(this.constructor.itemModelName); for (i = 0, len = args.length; i < len; i++) { arg = args[i]; if (arg instanceof ItemClass) { key = this.constructor.key(arg); } else { key = arg; } delete this.items[key]; } }; /** set ids. @method setIds @param {Array(String|Number)} ids */ BaseDict.prototype.setIds = function(ids) { var ItemRepository, id, repo, subModels; if (ids == null) { ids = []; } if (!this.constructor.containsEntity()) { return; } this.loaded = false; ItemRepository = this.getFacade().getRepository(this.constructor.itemModelName); repo = new ItemRepository(); if (ItemRepository.storeMasterTable && ItemRepository.loaded()) { subModels = (function() { var i, len, results; results = []; for (i = 0, len = ids.length; i < len; i++) { id = ids[i]; results.push(repo.getByIdSync(id)); } return results; })(); this.setItems(subModels); } else { repo.query({ where: { id: { inq: ids } } }).then((function(_this) { return function(subModels) { return _this.setItems(subModels); }; })(this)); } return this; }; /** set items from dic object update to new key @method setItems @param {Object|Array} models */ BaseDict.prototype.setItems = function(models) { var item, items, prevKey; if (models == null) { models = {}; } items = (function() { var results; results = []; for (prevKey in models) { item = models[prevKey]; results.push(item); } return results; })(); this.add.apply(this, items); this.loaded = true; this.emitLoaded(); return this; }; /** returns item is Entity @method containsEntity @static @public @return {Boolean} */ BaseDict.containsEntity = function() { return this.getFacade().getModel(this.itemModelName).isEntity; }; /** export models to Array @method toArray @public */ BaseDict.prototype.toArray = function() { var item, key, ref, results; ref = this.items; results = []; for (key in ref) { item = ref[key]; results.push(item); } return results; }; /** 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 */ BaseDict.prototype.toPlainObject = function() { var item, key, plain, plainItems, ref; plain = BaseDict.__super__.toPlainObject.call(this); if (this.constructor.containsEntity()) { plain.ids = this.ids; delete plain.items; } else { plainItems = []; ref = this.items; for (key in ref) { item = ref[key]; if (typeof item.toPlainObject === 'function') { plainItems[key] = item.toPlainObject(); } else { plainItems[key] = item; } } plain.items = plainItems; } return plain; }; /** on addEventlisteners for 'loaded' @method on @public */ BaseDict.prototype.on = function(evtname, fn) { if (evtname !== 'loaded') { return; } if (this.loaded) { process.nextTick(fn); } else if (typeof fn === 'function') { this.listeners.push(fn); } }; /** tell listeners emit loaded @method emitLoaded @private */ BaseDict.prototype.emitLoaded = function() { var fn; while (fn = this.listeners.shift()) { process.nextTick(fn); } }; return BaseDict; })(BaseModel); module.exports = BaseDict;