| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- const _ = require('lodash')
- const defaults = require('./defaults')
- const { Op } = require('sequelize')
- const { diffBy, sanitize } = require('../util')
- const { sequelize } = require('../database')
- const crudController = (opts) => {
- opts = defaults(opts)
- const { Type } = opts
- const options = Object.assign({}, opts.options)
- const subset = async (req) => {
- const subset = {}
- const params = _.toPairs(req.params)
- .map(([key, value])=>({key, value}))
- .filter(({value}) => value !== opts.paramAll)
- for (let { key, value } of params) {
- const assoc = Type.associations[key]
- if (assoc) {
- subset[assoc.foreignKey] = (await assoc.target.findOne({
- parameters: ['id'],
- where: { key: value }
- })).id
- }
- }
- return subset
- }
- const list = async (req, res) => {
- // TODO Pagination (http://docs.sequelizejs.com/manual/tutorial/querying.html#pagination-limiting)
- if (req.query && req.query.q) {
- const fields = [Type.tableAttributes.name, Type.tableAttributes.tag].filter(x => x)
- if (!fields) throw new Error('Table has no searchable fields')
- const or = fields.map(field => ({
- [field.fieldName]: { [Op.like]: `%${req.query.q}%` }
- }))
- const where = { ...subset, [Op.or]: or }
- const data = await sanitize(req, await Type.findAll({ ...options, where }))
- res.status(200).send(data)
- } else if (res.query && res.query.ids) {
- const ids = res.query.ids.split(',')
- const data = await sanitize(req, await Type.findAll({ ...options, where: { ...(await subset(req)), id: { [Op.in]: ids }}}))
- res.status(200).send(data)
- } else {
- const data = await sanitize(req, await Type.findAll({ ...options, where: { ...(await subset(req)) }}))
- res.status(200).send(data)
- }
- }
- const setAssociations = async (record, data, transaction) => {
- for (let [key, assoc] of _.toPairs(Type.associations)) {
- if (record[key] && assoc.associationType === 'BelongsToMany' && assoc.target.attributes.key) {
- await assoc.set(
- data,
- await assoc.target.findAll({
- attributes: ['id'],
- where: {
- key: {
- [Op.in]: record[key]
- }
- }
- }),
- {transaction}
- )
- }
- }
- }
-
- const getAssociations = async (data, json) => {
- for (let [key, assoc] of _.toPairs(Type.associations)) {
- if (assoc.associationType === 'BelongsToMany' && assoc.target.attributes.key) {
- json[key] = (await assoc.get(data, {
- attributes: ['id', 'key']
- })).map(x => x.key)
- }
- }
- }
- const create = async (req, res) => {
- const transaction = await sequelize.transaction()
- try {
- const record = { ...req.body, ...(await subset(req))}
- const data = (await Type.create(record, {transaction}))
- await setAssociations(record, data, transaction)
- await transaction.commit()
- res.status(200).send(await sanitize(req, data))
- } catch (err) {
- await transaction.rollback()
- throw err
- }
- }
- const read = async (req, res) => {
- const data = (await Type.findOne({where: {id: req.params[opts.routeParam]}}))
- const json = await sanitize(req, data)
- await getAssociations(data, json)
- res.status(200).send(json)
- }
- const update = async (req, res) => {
- const transaction = await sequelize.transaction()
- try {
- const record = _.omit(req.body, _.keys(await subset(req)))
- const updated = (await Type.update(record, { where: { id: req.params[opts.routeParam] }, transaction }))
- const data = (await Type.findOne({where: { id: req.params[opts.routeParam] }}))
- const json = await sanitize(req, data)
- await setAssociations(record, data, transaction)
- await transaction.commit()
- await getAssociations(data, json)
- res.status(200).send(json)
- } catch (err) {
- await transaction.rollback()
- throw err
- }
- }
- const $delete = async (req, res) => {
- const data = (await Type.destroy({ where: { id: req.params[opts.routeParam] } }))
- res.status(204).end()
- }
- const trash = async (req, res) => {
- const data = (await Type.findAll({
- model: Type,
- paranoid: false,
- where: {
- ...(await subset(req)),
- deletedAt: { [Op.ne]: null }
- }
- }))
- res.status(200).send(await sanitize(req, data))
- }
- const undelete = async (req, res) => {
- const data = (await Type.update({ deletedAt: null }, {
- paranoid: false,
- where: { id: req.params[opts.routeParam] }
- }))
- res.status(200).send(await sanitize(req, data))
- }
- // TODO: Create, Read, Update, Delete
- return {
- list,
- create,
- read,
- update,
- delete: $delete,
- trash,
- undelete
- }
- }
- module.exports = crudController
|