routeGen.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /**
  2. * @module mongoRouter
  3. *
  4. * Backend module to store React-Redux components in MongoDB.
  5. */
  6. import mongoose from 'mongoose'
  7. mongoose.Promise = global.Promise
  8. /**
  9. * Generates GET, POST, UPDATE and DELETE handlers which interact with
  10. * MongoDB.
  11. *
  12. * For versioned objects, allow querying for tags or for IDs. When querying
  13. * tags, return the head version, when querying for IDs, just return the
  14. * element.
  15. *
  16. * @param {object} Model - mongoose model to use
  17. * @param {boolean} versioned - use a revision control mechanism
  18. * @return {[type]}
  19. */
  20. function routeGen (Model, versioned = true) {
  21. /** GET handler (request one item or a list of items) */
  22. const get = (req, res) => {
  23. let { id } = req.params
  24. /** check whether an id was specified. */
  25. if (typeof id === 'string' && id.length > 1) {
  26. try {
  27. // try to convert the id string to a valid ObjectId
  28. const _id = mongoose.Types.ObjectId(id)
  29. // if yes, return the one item
  30. Model.findOne({ _id }, function (err, item) {
  31. console.log(item)
  32. if (err) {
  33. res.status(404)
  34. res.send(err)
  35. return
  36. }
  37. res.json(item)
  38. })
  39. } catch (err) {
  40. // If id couldn't be converted, assume it's a tag.
  41. const tag = id
  42. // if yes, return the one item
  43. Model.findOne({ tag, 'history.head': true }, function (err, item) {
  44. if (err) {
  45. res.status(404)
  46. res.send(err)
  47. return
  48. }
  49. res.json(item)
  50. })
  51. }
  52. } else {
  53. // if not, return a list of items
  54. // limit the number of returned items and use an offset
  55. const limit = req.query.limit ? Math.min(Math.max(parseInt(req.query.limit), 1), 100) : 20
  56. const offset = req.query.offset ? Math.max(parseInt(req.query.offset), 0) : 0
  57. Model.find({'history.head': true}, {limit: limit, skip: offset}, function (err, items) {
  58. console.log(err, items)
  59. if (err) {
  60. res.status(404)
  61. res.send(err)
  62. return
  63. }
  64. res.json(items)
  65. })
  66. }
  67. }
  68. /** POST handler (insert a new item into the database) */
  69. const post = (req, res) => {
  70. // create the new item
  71. console.log(req.body)
  72. const item = new Model(req.body)
  73. console.log(item)
  74. // Check, if the model supports revision control
  75. if (typeof Model.schema.obj.__history !== 'undefined') {
  76. console.log('creating new history')
  77. item.__history = {
  78. author: 'Tomi',
  79. created: new Date(),
  80. tag: 'myTag',
  81. reference: 'reference',
  82. head: true,
  83. comment: 'My Comment'
  84. }
  85. }
  86. console.log(item)
  87. // save the item
  88. console.log('before save')
  89. const p = item.save()
  90. console.log(p)
  91. p.then(savedItem => {
  92. console.log('in save', savedItem)
  93. res.status(200)
  94. res.send({ _id: savedItem._id })
  95. }, err => {
  96. console.log('in save', err)
  97. res.status(422)
  98. res.send(err)
  99. })
  100. console.log('after save', p)
  101. }
  102. /** PUT handler (update existing project) */
  103. const put = (req, res) => {
  104. let id = req.params['0']
  105. /** check whether an id was specified. */
  106. if (typeof id === 'string' && id.length > 1) {
  107. // remove leading slash
  108. id = id.substring(1)
  109. try {
  110. // try to convert the id string to a valid ObjectId
  111. id = mongoose.Types.ObjectId(req.params['1'].substring(1))
  112. } catch (err) {
  113. // If id couldn't be converted, return an error message.
  114. res.status(422)
  115. res.send({error: err.message})
  116. return
  117. }
  118. }
  119. // Find the object in the database
  120. Model.findOne({ _id: id }, function (err, item) {
  121. if (err) {
  122. res.status(404)
  123. res.send(err)
  124. }
  125. // Check, if the model supports revision control
  126. if (typeof Model.schema.obj.__history !== 'undefined') {
  127. // If yes, don't update the item, but create a new one based on the original
  128. const newItem = Model(item)
  129. // replace the requested elements
  130. for (let prop in req.body) {
  131. newItem[prop] = req.body[prop]
  132. }
  133. // give it a new history with updated reference array. Set the head-indicator to true
  134. newItem.__history.create({
  135. author: '',
  136. created: Date(),
  137. tag: '',
  138. reference: [ ...item.__history.reference, item._id ],
  139. head: true
  140. })
  141. // set the original item's head indicator to false
  142. item.__history.head = false
  143. // save the documents
  144. newItem.save(function (err) {
  145. if (err) {
  146. res.status(422)
  147. res.send(err)
  148. }
  149. res.json({ message: `${Model.modelName} updated.` })
  150. })
  151. } else {
  152. for (let prop in req.body) {
  153. item[prop] = req.body[prop]
  154. }
  155. }
  156. item.save(function (err) {
  157. if (err) {
  158. res.status(422)
  159. res.send(err)
  160. }
  161. res.json({ message: `${Model.modelName} updated.` })
  162. })
  163. })
  164. }
  165. /** DELETE handler (delete project) */
  166. const del = (req, res) => {
  167. const id = mongoose.Types.ObjectId(req.params['0'])
  168. Model.remove({ _id: id }, function (err, project) {
  169. if (err) {
  170. res.send(err)
  171. }
  172. res.json({ message: 'Movie deleted.' })
  173. })
  174. }
  175. return {
  176. get,
  177. post,
  178. put,
  179. del
  180. }
  181. }
  182. export default routeGen