/** * @module RESTController */ import * as debugStuff from 'debug' const debug = debugStuff.debug('dbApiRESTCtrl') import { Router } from 'express' const MAX_RESULTS = 100 /** * REST controller for MongoDB backend. */ class RESTController { /** * Generates a controller for a model type. * * @param {mongoose.Model} mongoose model to use * @param {key} Key to use as index. Default is '_id' * @return {null} */ constructor (model, key = '_id', subDocuments = {}) { this.model = model this.modelName = model.modelName.toLowerCase() this.key = key this.findOptions = {} this.findCriteria = {} this.extendData = (data) => data this.updateExtendedData = (data) => data this.subDocuments = subDocuments debug('created RESTController', this.modelName) } /** * Creates a DB item. * * @param {object} data object * @return {Promise} */ create (data) { debug('create data item', data) const newData = this.extendData(data) const p = this.model .create(newData) .then(instance => { debug('created instance', instance) return instance }) // debug('create return value', p) return p } /** * Read a DB item. * * @param {String} id * @return {Promise} */ read (id) { debug('reading data item', id) const filter = {} filter[this.key] = id 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 () { debug('reading data list') const p = this.model .find({}) .limit(MAX_RESULTS) .then(instance => { debug('read list instance', instance) return instance }) // debug('read return value', p) return p } /** * Update a DB item. * * @param {String} id * @param {String} data * @return {Promise} */ update (id, data) { debug('update data item', id, data) const filter = {} filter[this.key] = id const p = this.model .findOne(filter) .then(instance => { debug('found data instance', instance) for (let attribute in data) { if (data.hasOwnProperty(attribute) && attribute !== this.key && attribute !== '_id') { instance[attribute] = data[attribute] } } return instance.save() }) .then(instance => { debug('updated data instance', instance) return instance }) // debug('read return value', p) return p } /** * Delete a DB item. * * @param {String} id * @return {Promise} */ delete (id) { debug('delete data item') const filter = {} filter[this.key] = id const p = this.model .remove(filter) .then(() => { return {} }) // debug('read return value', p) return p } route (parent = undefined) { const router = new Router({mergeParams: true}) router.get('/', (req, res) => { this .list() .then(data => res.json(data)) .catch(error => res.status(404).send(error)) }) router.post('/', (req, res) => { this .create(req.body) .then(data => res.json(data)) .catch(error => res.status(404).send(error)) }) router.get('/:key', (req, res) => { this .read(req.params.key) .then(data => res.json(data)) .catch(error => res.status(404).send(error)) }) router.put('/:key', (req, res) => { this .update(req.params.key, req.body) .then(data => res.json(data)) .catch(error => res.status(404).send(error)) }) router.delete('/:key', (req, res) => { this .delete(req.params.key) .then(data => res.json(data)) .catch(error => res.status(404).send(error)) }) Object.keys(this.subDocuments).forEach(key => { router.use(`/:parentKey/${key}`, this.subDocuments[key].route()) }) return router } } export default RESTController