123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- /**
- * @module mongoRouter
- *
- * Backend module to store React-Redux components in MongoDB.
- */
- import mongoose from 'mongoose'
- import { Router } from 'express'
- mongoose.Promise = Promise
- const MAX_RESULTS = 100
- class RESTController {
- constructor (model, key) {
- this.model = model
- this.modelName = model.modelName.toLowerCase()
- this.key = key
- }
- create (data) {
- return this.model
- .create(data)
- .then(instance => {
- const response = {}
- response[this.modelName] = instance
- return response
- })
- }
- read (id) {
- const filter = {}
- filter[this.key] = id
- return this.model
- .findOne(filter)
- .then(instance => {
- const response = {}
- response[this.modelName] = instance
- return response
- })
- }
- list () {
- return this.model
- .find({})
- .limit(MAX_RESULTS)
- .then(instance => {
- const response = {}
- response[this.modelName] = instance
- return response
- })
- }
- update (id, data) {
- const filter = {}
- filter[this.key] = id
- return this.model
- .findOne(filter)
- .then(instance => {
- for (let attribute in data) {
- if (data.hasOwnProperty(attribute) && attribute !== this.key && attribute !== '_id') {
- instance[attribute] = data[attribute]
- }
- }
- return instance.save()
- })
- .then(instance => {
- const response = {}
- response[this.modelName] = instance
- return response
- })
- }
- route () {
- const router = new Router()
- router.get('/', (req, res) => {
- this
- .list()
- .then(data => res.json(data))
- .then(null, error => res.status(404).send(error))
- })
- router.post('/', (req, res) => {
- this
- .create(req.body)
- .then(data => res.json(data))
- .then(null, error => res.status(404).send(error))
- })
- router.get('/:key', (req, res) => {
- this
- .read(req.params.key)
- .then(data => res.json(data))
- .then(null, error => res.status(404).send(error))
- })
- router.put('/:key', (req, res) => {
- this
- .update(req.params.key, req.body)
- .then(data => res.json(data))
- .then(null, error => res.status(404).send(error))
- })
- router.delete('/:key', (req, res) => {
- this
- .delete(req.params.key)
- .then(data => res.json(data))
- .then(null, error => res.status(404).send(error))
- })
- return router
- }
- }
- export default RESTController
- /**
- * 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 })
- }).catch(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 { routeGen }
|