/** * @module RESTControllerVersioned */ import * as debugStuff from 'debug' const debug = debugStuff.debug('dbApiRESTCtrlVer') import RESTController from './RESTController' const MAX_RESULTS = 100 /** * REST controller for MongoDB backend. */ class RESTControllerVersioned extends RESTController { constructor (model, key = '_id', subDocuments = {}) { super(model, key, subDocuments) this.filterOptions = { limit: MAX_RESULTS, skip: 0 } this.filterCriteria = { '_history.head': true } debug('created RESTControllerVersioned', this.modelName) } /** * Override create function to support versioning. * * This function generates a history object to allow revision control * of the data elements. * * @param {object} data object * @return {Promise} */ create (data) { debug('create data item', data) const { author, version, comment, ...newData } = data const history = { author, created: new Date(), version, comment, head: true, reference: [] } newData._history = history const p = this.model .create(newData) .then(instance => { debug('created instance', instance) return instance }) // debug('create return value', p) return p } /** * Override read to search by default for head version of given tag. * * @param {[type]} * @return {[type]} */ read (tag) { if (typeof tag === 'string') { tag = { tag: tag } } debug('reading data item', tag) const filter = { ...this.filterCriteria, ...tag } const p = this.model .findOne(filter) .then(instance => { debug('read instance', instance) return instance }) // debug('read return value', p) return p } /** * Get a list of all DB items. * * @return {Promise} */ list (filter = this.filterCriteria) { debug('reading data list') const p = this.model .find(filter) .limit(MAX_RESULTS) .then(instance => { debug('read list instance', instance) return instance }) // debug('read return value', p) return p } /** * Override update to support versioning. * * @param {String} id * @param {String} data * @return {Promise} */ update (tag, data) { if (typeof tag === 'string') { tag = { tag: tag } } debug('update data item', tag, data) const filter = { ...this.filterCriteria, ...tag } const p = this.model .findOne(filter) .then(instance => { debug('found data instance', instance) instance._history.head = false return instance.save() }) .then(instance => { const { _id, __v, _history, ...oldData } = instance._doc debug('creating new data instance', oldData) const { author, version, comment, ...newItems } = data const newData = { ...oldData, ...newItems } newData._history = { author, created: new Date(), version, comment, head: true, reference: [ _id, ..._history.reference ] } return this.model .create(newData) .then(instance => { debug('created instance', instance) return instance }) }) // debug('read return value', p) return p } /** * Override delete. We don't delete. Just not our thing... * * @param {String} id * @return {Promise} */ delete (tag) { if (typeof tag === 'string') { tag = { tag: tag } } debug('delete data item', tag) const filter = { ...this.filterCriteria, ...tag } const p = this.model .findOne(filter) .then(instance => { instance._history.head = false return instance.save() }) // debug('read return value', p) return p } } export default RESTControllerVersioned