commit
8ad5d15a48
@ -0,0 +1,2 @@
|
||||
node_modules/*
|
||||
.env
|
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @module flitter-crud/CrudController
|
||||
*/
|
||||
|
||||
const status = require('http-status')
|
||||
|
||||
/**
|
||||
* A controller with built-in create, read, update, delete methods that references a specific model.
|
||||
*/
|
||||
class CrudController {
|
||||
|
||||
/**
|
||||
* Get the name of the resource managed by this controller. Should be a Flitter canonical name.
|
||||
* @returns {string|null} null
|
||||
*/
|
||||
name(){
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the registered model with the name of this controller's resource.
|
||||
* @returns {Mongoose/Model}
|
||||
*/
|
||||
model(){
|
||||
return _flitter.model(this.name())
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the registered validator with the name of this controller's resource.
|
||||
* @returns {module:flitter-forms/Validator~Validator}
|
||||
*/
|
||||
validator(){
|
||||
return _flitter.validator(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.validator().validate(req.body, (failed, data) => {
|
||||
if ( failed ){
|
||||
this.send(res, {
|
||||
status: 400,
|
||||
message: "invalid input for model: "+this.name(),
|
||||
data
|
||||
})
|
||||
}
|
||||
else {
|
||||
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.validator().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
|
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @module flitter-crud/CrudUnit
|
||||
*/
|
||||
|
||||
const Unit = require('libflitter/Unit')
|
||||
const path = require('path')
|
||||
const StopError = require('libflitter/errors/StopError')
|
||||
|
||||
/**
|
||||
* Unit to register functionality provided by the flitter-crud package.
|
||||
*/
|
||||
class CrudUnit extends Unit {
|
||||
|
||||
/**
|
||||
* Get the name of the unit.
|
||||
* @returns {string} "crud"
|
||||
*/
|
||||
name() {
|
||||
return "crud"
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap the unit's functionality.
|
||||
* @param {module:libflitter/app/FlitterApp~FlitterApp} app - the Flitter app
|
||||
* @param {module:libflitter/Context~Context} context
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async go(app, context) {
|
||||
|
||||
const required_services = ['forms', 'routing', 'database', 'controllers']
|
||||
if ( !app.has(required_services) ){
|
||||
throw (new StopError()).unit(this.name()).required(required_services)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the templates provided by this unit.
|
||||
* Currently, {@link module:flitter-crud/templates/crud} assigned as "crud".
|
||||
* @returns {{crud: {template: ((function(*, *=): string)|*), extension: string, directory: void | Promise<void> | Promise<any>}}}
|
||||
*/
|
||||
templates(){
|
||||
return {
|
||||
crud: {
|
||||
template: require('./templates/crud'),
|
||||
directory: path.resolve(_flitter.directories.models, 'crud'),
|
||||
extension: '.model.js'
|
||||
},
|
||||
'crud:controller': {
|
||||
template: require('./templates/controller'),
|
||||
directory: path.resolve(_flitter.directories.controllers, 'crud'),
|
||||
extension: '.controller.js'
|
||||
},
|
||||
'crud:router': {
|
||||
template: require('./templates/router'),
|
||||
directory: path.resolve(_flitter.directories.routers, 'crud'),
|
||||
extension: '.routes.js'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = CrudUnit
|
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "flitter-crud",
|
||||
"version": "0.1.0",
|
||||
"description": "A CRUD generator for Flitter.",
|
||||
"main": "index.js",
|
||||
"repository": "https://git.glmdev.tech/flitter/crud",
|
||||
"author": "glmdev <garrett@glmdev.tech>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"http-status": "^1.3.2",
|
||||
"libflitter": "0.*",
|
||||
"flitter-forms": "0.*"
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Get the contents of a new flitter-crud controller.
|
||||
* @type {function(*): string}
|
||||
* @returns {string}
|
||||
* @param {string} name - the name of the controller class
|
||||
*/
|
||||
module.exports = exports = (name) => {
|
||||
return `const CrudController = require('flitter-crud/CrudController')
|
||||
|
||||
class ${name}Controller extends CrudController {
|
||||
|
||||
name(){
|
||||
return "crud:${name}"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = ${name}Controller`
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Get the contents of a new Crud model, and create the corresponding controller, router, and validators.
|
||||
* @type {function(*=, *=): string}
|
||||
* @param {string} name - the name of the model class to be created
|
||||
* @param {string} original_name - the Flitter canonical name of the resource
|
||||
* @returns {string}
|
||||
*/
|
||||
module.exports = exports = (name, original_name) => {
|
||||
|
||||
// create the controller
|
||||
_flitter.daemon.cli.invoke('new', ['crud:controller', original_name])
|
||||
|
||||
// create the router
|
||||
_flitter.daemon.cli.invoke('new', ['crud:router', original_name])
|
||||
|
||||
// create the validator
|
||||
_flitter.daemon.cli.invoke('new', ['validator', 'crud:'+original_name])
|
||||
|
||||
// return contents of new model
|
||||
return _flitter.daemon.cli.templates.model.template(name, original_name)
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Get the contents of a new Crud router.
|
||||
* @param {string} name - the object name of the route definitions
|
||||
* @param {string} original_name - the original Flitter canonical name of the template
|
||||
* @returns {string}
|
||||
*/
|
||||
module.exports = exports = function router_template(name, original_name){
|
||||
return `/*
|
||||
* ${original_name} Routes
|
||||
* -------------------------------------------------------------
|
||||
* Put some description here!
|
||||
*/
|
||||
const ${name} = {
|
||||
|
||||
/*
|
||||
* Define the prefix applied to each of these routes.
|
||||
* For example, if prefix is '/auth':
|
||||
* '/' becomes '/auth'
|
||||
* '/login' becomes '/auth/login'
|
||||
*/
|
||||
prefix: '/crud/${name}',
|
||||
|
||||
/*
|
||||
* Define middleware that should be applied to all
|
||||
* routes defined in this file. Middleware should be
|
||||
* included using Flitter's global mw() function, but
|
||||
* it can also be added directly using require().
|
||||
*/
|
||||
middleware: [
|
||||
// mw('Middleware Name'),
|
||||
],
|
||||
|
||||
/*
|
||||
* Define GET routes.
|
||||
* These routes are registered as GET methods.
|
||||
* Handlers for these routes should be specified as
|
||||
* an array of functions that are applied in order.
|
||||
*
|
||||
* mw() calls apply Flitter middleware
|
||||
* controller() calls get methods in Flitter controllers
|
||||
*/
|
||||
get: {
|
||||
'/read/:id': [_flitter.controller('crud:${original_name}').read]
|
||||
},
|
||||
|
||||
/*
|
||||
* Define POST routes.
|
||||
* These routes are registered as POST methods.
|
||||
* Handlers for these routes should be specified as
|
||||
* an array of functions that are applied in order.
|
||||
*
|
||||
* mw() calls apply Flitter middleware
|
||||
* controller() calls get methods in Flitter controllers
|
||||
*/
|
||||
post: {
|
||||
'/create': [_flitter.controller('crud:${original_name}').create],
|
||||
'/delete/:id': [_flitter.controller('crud:${original_name}').delete],
|
||||
'/update/:id': [_flitter.controller('crud:${original_name}').update]
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = ${name}`
|
||||
}
|
Loading…
Reference in new issue