/** * @module mongoRouter * * Backend module to store React-Redux components in MongoDB. */ import mongoose from 'mongoose' mongoose.Promise = global.Promise /** * Generates GET, POST, UPDATE and DELETE handlers which interact with * MongoDB. * * For versioned objects, allow querying for tags or for IDs. When querying * tags, return the head version, when querying for IDs, just return the * element. * * @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 const _id = mongoose.Types.ObjectId(id) // if yes, return the one item Model.findOne({ _id }, function (err, item) { console.log(item) if (err) { res.status(404) res.send(err) return } res.json(item) }) } catch (err) { // If id couldn't be converted, assume it's a tag. const tag = id // if yes, return the one item Model.findOne({ tag, 'history.head': true }, 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({'history.head': true}, {limit: limit, skip: offset}, function (err, items) { console.log(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 console.log(req.body) const item = new Model(req.body) console.log(item) // Check, if the model supports revision control if (typeof Model.schema.obj.__history !== 'undefined') { console.log('creating new history') item.__history = { author: 'Tomi', created: new Date(), tag: 'myTag', reference: 'reference', head: true, comment: 'My Comment' } } console.log(item) // save the item console.log('before save') const p = item.save() console.log(p) p.then(savedItem => { console.log('in save', savedItem) res.status(200) res.send({ _id: savedItem._id }) }, err => { console.log('in save', err) res.status(422) res.send(err) }) console.log('after save', p) } /** 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.create({ 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