RESTController.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /**
  2. * @module RESTController
  3. */
  4. import * as debugStuff from 'debug'
  5. const debug = debugStuff.debug('dbApiRESTCtrl')
  6. import mongoose from 'mongoose'
  7. mongoose.Promise = Promise
  8. import { Router } from 'express'
  9. const MAX_RESULTS = 100
  10. /**
  11. * REST controller for MongoDB backend.
  12. */
  13. class RESTController {
  14. /**
  15. * Generates a controller for a model type.
  16. *
  17. * @param {mongoose.Model} mongoose model to use
  18. * @param {key} Key to use as index. Default is '_id'
  19. * @return {null}
  20. */
  21. constructor (model, key = '_id', subDocuments = {}) {
  22. this.model = model
  23. this.modelName = model.modelName.toLowerCase()
  24. this.key = key
  25. this.findOptions = {}
  26. this.findCriteria = {}
  27. this.extendData = (data) => data
  28. this.updateExtendedData = (data) => data
  29. this.subDocuments = subDocuments
  30. debug('created RESTController', this.modelName)
  31. }
  32. /**
  33. * Creates a DB item.
  34. *
  35. * @param {object} data object
  36. * @return {Promise}
  37. */
  38. create (data) {
  39. debug('create data item', data)
  40. const newData = this.extendData(data)
  41. const p = this.model
  42. .create(newData)
  43. .then(instance => {
  44. debug('created instance', instance)
  45. return instance
  46. })
  47. // debug('create return value', p)
  48. return p
  49. }
  50. /**
  51. * Read a DB item.
  52. *
  53. * @param {String} id
  54. * @return {Promise}
  55. */
  56. read (id) {
  57. debug('reading data item', id)
  58. const filter = {}
  59. filter[this.key] = id
  60. const p = this.model
  61. .findOne(filter)
  62. .then(instance => {
  63. debug('read instance', instance)
  64. return instance
  65. })
  66. // debug('read return value', p)
  67. return p
  68. }
  69. /**
  70. * Get a list of all DB items.
  71. *
  72. * @return {Promise}
  73. */
  74. list () {
  75. debug('reading data list')
  76. const p = this.model
  77. .find({})
  78. .limit(MAX_RESULTS)
  79. .then(instance => {
  80. debug('read list instance', instance)
  81. return instance
  82. })
  83. // debug('read return value', p)
  84. return p
  85. }
  86. /**
  87. * Update a DB item.
  88. *
  89. * @param {String} id
  90. * @param {String} data
  91. * @return {Promise}
  92. */
  93. update (id, data) {
  94. debug('update data item', id, data)
  95. const filter = {}
  96. filter[this.key] = id
  97. const p = this.model
  98. .findOne(filter)
  99. .then(instance => {
  100. debug('found data instance', instance)
  101. for (let attribute in data) {
  102. if (data.hasOwnProperty(attribute) && attribute !== this.key && attribute !== '_id') {
  103. instance[attribute] = data[attribute]
  104. }
  105. }
  106. return instance.save()
  107. })
  108. .then(instance => {
  109. debug('updated data instance', instance)
  110. return instance
  111. })
  112. // debug('read return value', p)
  113. return p
  114. }
  115. /**
  116. * Delete a DB item.
  117. *
  118. * @param {String} id
  119. * @return {Promise}
  120. */
  121. delete (id) {
  122. debug('delete data item')
  123. const filter = {}
  124. filter[this.key] = id
  125. const p = this.model
  126. .remove(filter)
  127. .then(() => {
  128. return {}
  129. })
  130. // debug('read return value', p)
  131. return p
  132. }
  133. route (parent = undefined) {
  134. const router = new Router({mergeParams: true})
  135. router.get('/', (req, res) => {
  136. this
  137. .list()
  138. .then(data => {
  139. debug('params, query', parent, req.params, req.query)
  140. res.json(data)
  141. })
  142. .catch(error => res.status(404).send(error))
  143. })
  144. router.post('/', (req, res) => {
  145. this
  146. .create(req.body)
  147. .then(data => res.json(data))
  148. .catch(error => res.status(404).send(error))
  149. })
  150. router.get('/:key', (req, res) => {
  151. this
  152. .read(req.params.key)
  153. .then(data => {
  154. debug('params, query', parent, req.params, req.query)
  155. res.json(data)
  156. })
  157. .catch(error => res.status(404).send(error))
  158. })
  159. router.put('/:key', (req, res) => {
  160. this
  161. .update(req.params.key, req.body)
  162. .then(data => res.json(data))
  163. .catch(error => res.status(404).send(error))
  164. })
  165. router.delete('/:key', (req, res) => {
  166. this
  167. .delete(req.params.key)
  168. .then(data => res.json(data))
  169. .catch(error => res.status(404).send(error))
  170. })
  171. Object.keys(this.subDocuments).forEach(key => {
  172. router.use(`/:pKey/${key}`, this.subDocuments[key].route())
  173. })
  174. return router
  175. }
  176. }
  177. export default RESTController