lowcode-controller
v1.0.8
Published
a low-code controller util, you can use json write your controller code
Downloads
1
Maintainers
Readme
lowcode-controller
lowcode-controller是一个可以用json来配置化的生成对应的controller逻辑的工具,它允许配置化的生成分页查询、查询单条、查询列表、新增、更新、删除逻辑,能够覆盖大部分crud场景 你也可以通过class的方法重写和定义自己的逻辑处理 它也提供了各个阶段的生命周期,你可以在对应的生命周期定义自己的逻辑
安装
npm install --save lowcode-controller
基本使用
//in your controller /controller/cats.js
const { LowCodeController } = require('lowcode-controller')
const cats_model = require('../model/cat_model')
const path = require('path')
LowCodeController.setGlobalDBPath(path.join(__dirname, '../db/mysql')) // 设置数据库文件
LowCodeController.setUserNameField('username') // 可以设置用户名的字段key
LowCodeController.setCustomResField('code', 'msg', 'data') // 允许自定义返回的字段key,默认是 { errno: 0, errmsg: 'success', data: null }
class CatsController extends LowCodeController {
constructor(model, config, db, extraOptions) {
super(model, config, null, extraOptions)
}
async sayHello(ctx) {
ctx.body = { errno: 0, message: 'hello world', data: 'hello world' }
}
}
const Cats = new CatsController(
cats_model,
{
pageQuery: {
query: {
cat_name: {
like: true,
value: 'cat_name',
},
age: {
type: 'constant',
value: 2,
},
},
extraOptions: {
order: [['cat_name', 'DESC']],
attributes: ['cat_name', 'age', 'job'],
},
beforeQueryHook: async function (ctx) {
console.log('before query hook')
return null
},
},
getList: {
extraOptions: {
order: [['cat_name', 'DESC']],
attributes: ['cat_name', 'age', 'job'],
},
afterQueryHook: async function (ctx, sourceResults) {
sourceResults.forEach(item => {
item.desc = 'cute cat'
})
return sourceResults
},
},
create: {
validate: {
cat_name: {
name: 'cat name',
rule: 'required',
},
},
constantCreate: {
age: 2,
},
enableBatch: true,
},
update: {
pick: ['job'],
query: {
job: 'student',
},
afterUpdateHook: async function (ctx, t, updateItem) {
if (updateItem.job === 'rollback') {
throw new Error('roll back')
}
},
},
},
null,
{
creatorField: 'creator',
updatorField: 'updator',
}
)
module.exports = Cats
//router.js
//you can choose the routing module you like
const router = require('koa-router')()
const Cat = require('./controller/cats')
router.get('/public/cats/hello', Cat.sayHello)
router.get('/api/cats', Cat.pageQuery)
router.post('/api/cats', Cat.create)
router.get('/api/cats/list', Cat.getList)
router.get('/api/cats/:id', Cat.getSingle)
router.put('/api/cats', Cat.update)
router.put('/api/cats/:id', Cat.update)
router.delete('/api/cats/:id', Cat.delete)
module.exports = router
//app.js
const Koa = require('koa')
const bodyParser = require('koa-bodyparser')
const router = require('./router')
const app = new Koa()
app.use(async (ctx, next) => {
ctx.username = 'admin'
await next()
})
//lowcode-controller need ctx.query and ctx.request.body
app.use(bodyParser())
//you can choose the routing module you like
app.use(router.routes()).use(router.allowedMethods())
const server = app.listen(3000, function () {
console.log('server is listen on 3000')
})
方法
构造函数
| 参数名 | 二级参数 | 说明 | | ------------ | ------------ | ----------------------- | | model | | 数据库model | | config | 参考二级参数 | 各个方法的配置 | | | pageQuery | | | | create | | | | update | | | | getSingle | | | | getList | | | | delete | | | db | | mysql sequelize实例 | | extraOptions | 参考二级参数 | | | | creatorField | String 创建人字段 | | | updatorField | String 创建人字段 | | | defaultQuery | Object 默认查询条件 | | | updateDelete | Object 逻辑删除更新字段 |
静态方法
setGlobalDBPath
| 参数名 | 说明 | | ------ | ------------------------------ | | dbPath | 设置全局db sequelize实例的路径 |
setUserNameField
| 参数名 | 说明 | | ------ | -------------------------------------------------- | | field | 设置从ctx里取出的用户唯一表示字段,支持xxx.xxx形式 |
setCustomResField
| 参数名 | 说明 | | ------ | ----------------- | | code | code对应的字段key | | msg | msg对应的字段key | | data | data对应的字段key |
实例方法
所有路由类实例方法参数都是ctx
pageQuery
对应到构造函数中的config.pageQuery,配置项说明如下
| 参数名 | 类型 | 说明 | | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | query | Object | 查询条件,具体字段见后面的说明 | | beforeQueryHook | function|async function(query, extraOptions, ctx) | 在执行数据库查询之前执行,函数里return将会阻断后续执行 | | afterQueryHook | function|async function(sourceResults, query, extraOptions, ctx) | 在执行数据库查询之后执行,函数里return的值将会作为最后的接口data的返回结果 sourceResults是从数据库查出来的数据 | | filter | function | 查询数据库后,将结果放到filter函数执行过滤操作 | | extraOptions | Object | 额外设置,会透传给sequelize执行 |
create
| 参数名 | 类型 | 说明 | | ---------------- | ------------------------------------------------------ | ------------------------------------------------------------ | | validate | Object | 参数验证配置 | | beforeInsertHook | function|async function(createItem, ctx) | 在执行数据库插入之前执行,createItem为插入数据库的实体对象 | | afterInsertHook | function|async function(insertItem, transaction, ctx) | 在执行数据库插入之后执行,insertItem为插入数据库的实体对象, transaction是sequelize事务标志 | | constantCreate | Object | 用该对象的字段覆盖插入的字段值 | | extraOptions | Object | 额外设置,会透传给sequelize执行 | | pickCreate | Object | 举例{age: 'newAge'} 从createItem中的newAge值覆盖到createItem中的age字段上 | | enbaleBatch | Boolean | 默认false,开启后,支持传数组,进行批量插入 |
update
| 参数名 | 类型 | 说明 | | ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | query | Object | 查询条件,具体字段见后面的说明 | | beforeUpdateHook | function|async function(updateItem, item, ctx) | 在执行数据库更新之前执行,updateItem为传参的更新内容,item为数据库查询的更新内容 | | afterUpdateHook | function|async function(updateItem, item, raw, transaction, ctx) | 在执行数据库更新之后执行,updateItem为传参的更新内容,item为数据库查询的更新内容,raw为数据库update返回值,t为事务标志 | | filter | function | 查询数据库后,将结果放到filter函数执行过滤操作 | | extraOptions | Object | 额外设置,会透传给sequelize执行 | | validate | Object | 参数验证配置 | | itemBlock | Object | 配置更新对象的字段,不符合预期直接返回错误,比如{age: { value: 12, message: 'wrong age' }} | | pick | Array | 从传参里提取哪些字段进行更新 |
getSingle
| 参数名 | 类型 | 说明 | | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | query | Object | 查询条件,具体字段见后面的说明 | | beforeQueryHook | function|async function(query, extraOptions, ctx) | 在执行数据库查询之前执行,函数里return将会阻断后续执行 | | afterQueryHook | function|async function(sourceResults, query, extraOptions, ctx) | 在执行数据库查询之后执行,函数里return的值将会作为最后的接口data的返回结果 sourceResults是从数据库查出来的数据 | | filter | function | 查询数据库后,将结果放到filter函数执行过滤操作 | | extraOptions | Object | 额外设置,会透传给sequelize执行 |
getList
| 参数名 | 类型 | 说明 | | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | query | Object | 查询条件,具体字段见后面的说明 | | beforeQueryHook | function|async function( query, extraOptions, ctx) | 在执行数据库查询之前执行,函数里return将会阻断后续执行 | | afterQueryHook | function|async function(sourceResults, query, extraOptions, ctx) | 在执行数据库查询之后执行,函数里return的值将会作为最后的接口data的返回结果 sourceResults是从数据库查出来的数据 | | filter | function | 查询数据库后,将结果放到filter函数执行过滤操作 | | extraOptions | Object | 额外设置,会透传给sequelize执行 |
delete
| 参数名 | 类型 | 说明 | | ---------------- | ------------------------------------------------------------ | ------------------------------------------------------ | | query | Object | 查询条件,具体字段见后面的说明 | | beforeDeleteHook | function|async function(query, extraOptions, ctx) | 在执行数据库查询之前执行,函数里return将会阻断后续执行 | | afterDeleteHook | function|async function(query, extraOptions, transaction, ctx) | 在执行数据库查询之后执行,t为事务标志 | | extraOptions | Object | 额外设置,会透传给sequelize执行 | | physicDelete | Boolean | 是否进行物理删除,true是,false否,默认false |
query
{
//比如请求传过来的cat_name为haha,就模糊查询数据库里cat_name为haha的内容
'cat_name': { //查询字段名cat_name
'like': true, //是否模糊查询
'value': 'cat_name', //从请求参数里取cat_name字段作为查询条件值
'require': true //请求参数里的cat_name字段必须有值
},
//查询数据库中age为2的内容
'age': {
'type': 'constant', //查询的value为一个常量
'value': 2 //常量值为2
},
//查询数据库字段cat_job里包含了请求传过来的job的内容
'cat_job': { //数据库字段为cat_job
'value': 'job', //从请求参数里取job字段作为查询条件值
'json': true //数据库cat_job是一个json类型,启用JSON_CONTAINS进行查询
},
//查询数据库字段creator的值为ctx里的username的内容
'creator': {
'type': 'constant',
'ctxField': 'username'
},
//查询数据库字段birthday,大于等于请求参数里的startTime,小于等于endTime的字段
'birthday': {
'type': 'varTime', //时间字段查询
'value': ['startTime', 'endTime'] //从请求参数里取数组第一个字段为开始时间值,第二个为结束时间值
}
//以上条件没加特殊操作符,默认都是and
//以下查询条件都是or
'$or': {
//从请求参数里取为color的字段比如['black', 'white'],然后查询数据库字段color为这两种颜色之一的内容
'color': {
'type': 'varArray', //表面查询条件是一个数组
'value': 'color'
},
//查询数据库字段height不等于30的内容
'height': {
'type': 'constant',//查询的value为一个常量
'operator': '$ne',
'value': 30 //常量值不等于30
},
//查询数据库字段weight为50或者100的内容
'weight': {
'type': 'constant',
'operator': '$in',
'value': [50, 100]
},
//查询数据库字段birthday小于等于2000-10-11的内容
'birthday': {
'type': 'constant',
'operator': '$time', //时间字段查询
'value': [null, '2000-10-11'] //数组第一项为空无开始时间,第二项作为结束时间
}
}
//以上条件总的为查询(cat_name、age、cat_job creator birthday) and (or (color height weight birthday))
}