master
glmdev 5 years ago
commit 8ad5d15a48

2
.gitignore vendored

@ -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…
Cancel
Save