/** * @module mongoRouter * * Backend module to store React-Redux components in MongoDB. */ import mongoose from 'mongoose' import { History } from './core/basicSchema' /** * Generates GET, POST, UPDATE and DELETE handlers which interact with * MongoDB. * * @param {object} Model - mongoose model to use * @param {boolean} versioned - use a revision control mechanism * @return {[type]} */ function routeGen (Model, versioned = true) { /** GET handler (request one item or a list of items) */ const get = (req, res) => { let { id } = req.params /** check whether an id was specified. */ if (typeof id === 'string' && id.length > 1) { try { // try to convert the id string to a valid ObjectId id = mongoose.Types.ObjectId(id) } catch (err) { // If id couldn't be converted, return an error message. res.status(422) res.send({error: err.message}) return } // if yes, return the one item Model.findOne({ _id: id }, function (err, item) { if (err) { res.status(404) res.send(err) return } res.json(item) }) } else { // if not, return a list of items // limit the number of returned items and use an offset const limit = req.query.limit ? Math.min(Math.max(parseInt(req.query.limit), 1), 100) : 20 const offset = req.query.offset ? Math.max(parseInt(req.query.offset), 0) : 0 Model.find({}, {limit: limit, skip: offset}, function (err, items) { if (err) { res.status(404) res.send(err) return } res.json(items) }) } } /** POST handler (insert a new item into the database) */ const post = (req, res) => { // create the new item const item = new Model(req.body) // Check, if the model supports revision control if (typeof Model.schema.obj.__history !== 'undefined') { item.__history = new History({ author: '', created: Date(), tag: '', reference: [], head: true }) } // save the item item.save(function (err) { if (err) { res.status(422) res.send(err) return } res.send({ success: `${Model.modelName} added.` }) }) } /** PUT handler (update existing project) */ const put = (req, res) => { let id = req.params['0'] /** check whether an id was specified. */ if (typeof id === 'string' && id.length > 1) { // remove leading slash id = id.substring(1) try { // try to convert the id string to a valid ObjectId id = mongoose.Types.ObjectId(req.params['1'].substring(1)) } catch (err) { // If id couldn't be converted, return an error message. res.status(422) res.send({error: err.message}) return } } // Find the object in the database Model.findOne({ _id: id }, function (err, item) { if (err) { res.status(404) res.send(err) } // Check, if the model supports revision control if (typeof Model.schema.obj.__history !== 'undefined') { // If yes, don't update the item, but create a new one based on the original const newItem = Model(item) // replace the requested elements for (let prop in req.body) { newItem[prop] = req.body[prop] } // give it a new history with updated reference array. Set the head-indicator to true newItem.__history = new History({ author: '', created: Date(), tag: '', reference: [ ...item.__history.reference, item._id ], head: true }) // set the original item's head indicator to false item.__history.head = false // save the documents newItem.save(function (err) { if (err) { res.status(422) res.send(err) } res.json({ message: `${Model.modelName} updated.` }) }) } else { for (let prop in req.body) { item[prop] = req.body[prop] } } item.save(function (err) { if (err) { res.status(422) res.send(err) } res.json({ message: `${Model.modelName} updated.` }) }) }) } /** DELETE handler (delete project) */ const del = (req, res) => { const id = mongoose.Types.ObjectId(req.params['0']) Model.remove({ _id: id }, function (err, project) { if (err) { res.send(err) } res.json({ message: 'Movie deleted.' }) }) } return { get, post, put, del } } export default routeGen