controller.js 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. const _ = require('lodash')
  2. const defaults = require('./defaults')
  3. const { Op } = require('sequelize')
  4. const crudController = (opts) => {
  5. opts = defaults(opts)
  6. const { Type } = opts
  7. const subset = async (req) => {
  8. const subset = {}
  9. const params = _.toPairs(req.params)
  10. .map(([key, value])=>({key, value}))
  11. .filter(({value}) => value !== opts.paramAll)
  12. for (let { key, value } of params) {
  13. const assoc = Type.associations[key]
  14. if (assoc) {
  15. subset[assoc.foreignKey] = (await assoc.target.findOne({
  16. parameters: ['id'],
  17. where: { key: value }
  18. })).id
  19. }
  20. }
  21. return subset
  22. }
  23. const list = async (req, res) => {
  24. // TODO Pagination (http://docs.sequelizejs.com/manual/tutorial/querying.html#pagination-limiting)
  25. if (req.query && req.query.q) {
  26. const fields = [Type.tableAttributes.name, Type.tableAttributes.tag].filter(x => x)
  27. if (!fields) throw new Error('Table has no searchable fields')
  28. const or = fields.map(field => ({
  29. [field.fieldName]: { [Op.like]: `%${req.query.q}%` }
  30. }))
  31. const where = { ...subset, [Op.or]: or }
  32. const data = (await Type.findAll({ where })).map(d => d.sanitize ? d.sanitize() : d)
  33. res.status(200).send(data)
  34. } else if (res.query && res.query.ids) {
  35. const ids = res.query.ids.split(',')
  36. const data = (await Type.findAll({where: { ...(await subset(req)), id: { [Op.in]: ids }}})).map(d => d.sanitize ? d.sanitize() : d)
  37. res.status(200).send(data)
  38. } else {
  39. const data = (await Type.findAll({where: { ...(await subset(req)) }})).map(d => d.sanitize ? d.sanitize() : d)
  40. res.status(200).send(data)
  41. }
  42. }
  43. const create = async (req, res) => {
  44. const record = { ...req.body, ...(await subset(req))}
  45. const data = (await Type.create(record))
  46. res.status(200).send(data && data.sanitize ? data.sanitize() : data)
  47. }
  48. const read = async (req, res) => {
  49. const data = (await Type.findOne({where: {id: req.params[opts.routeParam]}}))
  50. res.status(200).send(data && data.sanitize ? data.sanitize() : data)
  51. }
  52. const update = async (req, res) => {
  53. const record = _.omit(req.body, _.keys(await subset(req)))
  54. const data = (await Type.update(record, { where: { id: req.params[opts.routeParam] } }))
  55. res.status(200).send(data && data.sanitize ? data.sanitize() : data)
  56. }
  57. const $delete = async (req, res) => {
  58. const data = (await Type.destroy({ where: { id: req.params[opts.routeParam] } }))
  59. res.status(204).end()
  60. }
  61. const trash = async (req, res) => {
  62. const data = (await Type.findAll({
  63. model: Type,
  64. paranoid: false,
  65. where: {
  66. ...(await subset(req)),
  67. deletedAt: { [Op.ne]: null }
  68. }
  69. }))
  70. res.status(200).send(data && data.sanitize ? data.sanitize() : data)
  71. }
  72. const undelete = async (req, res) => {
  73. const data = (await Type.update({ deletedAt: null }, {
  74. paranoid: false,
  75. where: { id: req.params[opts.routeParam] }
  76. }))
  77. res.status(200).send(data && data.sanitize ? data.sanitize() : data)
  78. }
  79. // TODO: Create, Read, Update, Delete
  80. return {
  81. list,
  82. create,
  83. read,
  84. update,
  85. delete: $delete,
  86. trash,
  87. undelete
  88. }
  89. }
  90. module.exports = crudController