/**
* @module flitter-crud/CrudController
*/
const status = require('http-status')
const Controller = require('libflitter/controller/Controller')
const ImplementationError = require('libflitter/errors/ImplementationError')
/**
* A controller with built-in create, read, update, delete methods that references a specific model.
* @extends module:libflitter/controller/Controller
*/
class CrudController extends Controller {
/**
* Defines the services required by this controller.
* @returns {Array<string>}
*/
static get services() {
return [...super.services, 'models', 'forms']
}
/**
* Get the name of the resource managed by this controller. Should be a Flitter canonical name.
* @returns {string|null} null
*/
name(){
throw new ImplementationError()
}
/**
* Get the registered model CLASS with the name of this controller's resource.
* @returns {module:flitter-orm/src/model/Model~Model}
*/
model(){
return this.models.get(this.name())
}
/**
* Get the registered validator with the name of this controller's resource.
* @returns {module:flitter-forms/Validator~Validator}
*/
form(){
return this.forms.get(this.name())
}
/**
* Send a JSON formatted, API-style response.
* @param {Express/Response} res - the Express response
* @param {object} [body = {}] - the response information. Accepts the following fields, optionally: "status", "message", and "data"
*/
send(res, body = {}){
const code = body.status ? body.status : 200
res.status(code)
res.send({
status: code,
message: body.messageTest ? body.message : status[code],
data: body.data ? body.data : {}
})
}
/**
* Create a new instance of the resource managed by this controller. Input taken from req.body is validated
* before the resource is created.
* @param {Express/Request} req - the Express request
* @param {Express/Response} res - the Express response
* @param {function} next - the error handler
*/
create(req, res, next){
this.form().validate(req.body, (failed, data) => {
if ( failed ){
this.send(res, {
status: 400,
message: "Invalid input for model: "+this.name(),
data
})
}
else {
console.log('validation success!')
const instance = new (this.model())(data)
instance.save().then(() => {
this.send(res, {data: instance})
})
}
})
}
/**
* Retrieve an instance of the resource managed by this controller with the ID "req.params.id".
* @param {Express/Request} req - the Express request
* @param {Express/Response} res - the Express response
* @param {function} next - the error handler
*/
read(req, res, next){
const id = req.params.id
this.model().findById(id, (error, instance) => {
if ( error ){
this.send(res, {
status: 500,
data:error,
})
}
else if ( instance ){
this.send(res, {data:instance})
}
else {
this.send(res, {status:404})
}
})
}
/**
* Delete an instance of the resource managed by this controller with the ID "req.params.id".
* @param {Express/Request} req - the Express request
* @param {Express/Response} res - the Express response
* @param {function} next - the error handler
*/
delete(req, res, next){
const id = req.params.id
this.model().findById(id, (error, instance) => {
if ( error ){
this.send(res, {
status: 500,
data:error,
})
}
else if ( instance ){
instance.delete().then(() => {
this.send(res, {status:200, message: "Deleted"})
})
}
else {
this.send(res, {status:404})
}
})
}
/**
* Update an instance of the resource managed by this controller with the ID "req.params.id". Any input taken from
* req.body is validated before updating.
* @param {Express/Request} req - the Express request
* @param {Express/Response} res - the Express response
* @param {function} next - the error handler
*/
update(req, res, next){
const id = req.params.id
this.model().findById(id, (error, instance) => {
if ( error ) this.send(res, {status:500, data:error})
else if ( !instance ) this.send(res, {status:404})
else {
this.form().validate({...instance.toObject(), ...req.body}, (failed, data) => {
if ( failed ) this.send(res, {status:400, message:"Invalid input data to update "+this.name(), data})
else {
instance.update(data).then(() => {
this.send(res, {message: "Updated"})
})
}
})
}
})
}
}
module.exports = exports = CrudController