更新
This commit is contained in:
+55
@@ -0,0 +1,55 @@
|
|||||||
|
// https://molunerfinn.com/Use-Jest-To-Test-Vue-Koa/#Koa%E5%90%8E%E7%AB%AFApi%E6%B5%8B%E8%AF%95
|
||||||
|
//https://jestjs.io/docs/api#testeachtablename-fn-timeout
|
||||||
|
//Jest CLI选项 : https://runebook.dev/zh-CN/docs/jest/cli#--forceexit
|
||||||
|
//匹配器:https://www.jianshu.com/p/c1b5676c1edd
|
||||||
|
const bamboo = require('./lib/main')
|
||||||
|
const glob = require("glob")
|
||||||
|
const path = require('path')
|
||||||
|
import request from 'supertest';
|
||||||
|
|
||||||
|
let server = ""
|
||||||
|
let list = []
|
||||||
|
|
||||||
|
/*当前根目录*/
|
||||||
|
function isPath(args) {
|
||||||
|
return path.resolve('./' + (args || ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
function load(directory) {
|
||||||
|
const path_root = isPath()
|
||||||
|
let files = glob.sync(directory)
|
||||||
|
files = files.map(item => {
|
||||||
|
const parse = path.parse(item);
|
||||||
|
parse.father = path.basename(path.resolve(parse.dir, '..'))
|
||||||
|
parse.file_father = path.basename(path.resolve(parse.dir + '/' + parse.name, '..'))
|
||||||
|
return {
|
||||||
|
parse,
|
||||||
|
res: require(path.resolve(path_root + "/" + item))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
|
list = load("app/*/test/*.js")
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
bamboo.fullList.push(async (app) => {
|
||||||
|
server = app.server
|
||||||
|
//回复测试数据镜像sql文件
|
||||||
|
await app.db.tool.reduction()
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
afterAll(() => {
|
||||||
|
server.close();
|
||||||
|
console.log('服务器关闭!');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe.each(list)('测试清单名称:$res.describe_name', (testDescribe) => {
|
||||||
|
test.each(testDescribe.res.testList)('测试名称:$test_name', async (o) => await o.fun(request, server));
|
||||||
|
});
|
||||||
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
/*系统启动后要做初始化*/
|
|
||||||
module.exports = (app) => {
|
|
||||||
console.log("启动完成");
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
doc: "用户",
|
|
||||||
api: true,//是否需要生成api接口
|
|
||||||
model: {
|
|
||||||
uid: {type: "STRING", comment: '用户id'},
|
|
||||||
age: {type: "INTEGER", comment: '年龄', defaultValue: 0},
|
|
||||||
age2: {type: "INTEGER", comment: '年龄', defaultValue: 0},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
doc : "用户信息表",
|
|
||||||
model: {
|
|
||||||
uid : {type: "STRING", comment: '用户id'},
|
|
||||||
phone: {type: "STRING", comment: '手机号', defaultValue: null,},
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// path : "cms/api/index",//可以覆盖自动生成的路由地址
|
||||||
|
params: {
|
||||||
|
"age": "int?"
|
||||||
|
},
|
||||||
|
fun : async (ctx, app) => {
|
||||||
|
|
||||||
|
const body = ctx.params
|
||||||
|
const User = await app.db.table("User").find()
|
||||||
|
//成功返回的2种方式
|
||||||
|
// ctx.body = app.res.success(User,"success",200)//"success",200可以省略
|
||||||
|
return User
|
||||||
|
|
||||||
|
//异常返回的2种方式
|
||||||
|
// ctx.body = app.res.error(User, "error", 400)//"error",400可以省略
|
||||||
|
// return false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:"加入房间",
|
||||||
|
doc:``,
|
||||||
|
params: {
|
||||||
|
"type": ["accountPassword"],//登录类型
|
||||||
|
"data": "object",//数据
|
||||||
|
},
|
||||||
|
fun : async (ctx, app) => {
|
||||||
|
const {type, data} = ctx.params
|
||||||
|
if (await $components.login[type](data)) {
|
||||||
|
return $res.success({
|
||||||
|
token: await $components.jwt.sign({})
|
||||||
|
}, "登录成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $res.error({}, "登录失败")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
module.exports = {
|
||||||
|
name : "离开房间",
|
||||||
|
doc : ``,
|
||||||
|
params: {
|
||||||
|
// "room_name": 'string',//房间
|
||||||
|
// "uid" : 'string',//用户id
|
||||||
|
},
|
||||||
|
fun : (socket, {msg, onname, callback}) => {
|
||||||
|
console.log('断线:', socket.id);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
module.exports = {
|
||||||
|
name : "加入房间",
|
||||||
|
doc : ``,
|
||||||
|
params: {
|
||||||
|
"room_name": 'string',//房间
|
||||||
|
"uid" : 'string',//用户id
|
||||||
|
},
|
||||||
|
fun : (socket, {msg, onname, callback}) => {
|
||||||
|
console.log('加入房间:', msg);
|
||||||
|
socket.join(msg.room_name)//加入房间
|
||||||
|
socket.emit('success', {
|
||||||
|
event: onname,
|
||||||
|
res : app.res.success(""),
|
||||||
|
})
|
||||||
|
socket.to(msg.room_name).emit('success', {
|
||||||
|
event: onname,
|
||||||
|
res : app.res.success(msg, "有人加入房间"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
module.exports = {
|
||||||
|
name : "离开房间",
|
||||||
|
doc : ``,
|
||||||
|
params: {
|
||||||
|
// "room_name": 'string',//房间
|
||||||
|
// "uid" : 'string',//用户id
|
||||||
|
},
|
||||||
|
fun : (socket, {msg, onname, callback}) => {
|
||||||
|
console.log('离开房间:', socket.id);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
module.exports = (app, msg, callback) => {
|
|
||||||
console.log('接收到的消息:', msg);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "联系人表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
uid: {type: "STRING", comment: '用户id/群id'},
|
||||||
|
to_uid: {type: "STRING", comment: '接收人用户id'},
|
||||||
|
type: {type: "STRING", comment: '类型,单人/群:one/group'},
|
||||||
|
status: {type: "STRING", comment: '状态:已结束/未结束:y/n'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "消息表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
uid: {type: "STRING", comment: '发送人用户id'},
|
||||||
|
name: {type: "STRING", comment: '发送人名称'},
|
||||||
|
avatar: {type: "STRING", comment: '发送人头像'},
|
||||||
|
to_uid: {type: "STRING", comment: '接收人用户id'},
|
||||||
|
to_name: {type: "STRING", comment: '接收人名称'},
|
||||||
|
to_avatar: {type: "STRING", comment: '接收人头像'},
|
||||||
|
status: {type: "STRING", comment: '状态:已读/未读:y/n'},
|
||||||
|
type: {type: "STRING", comment: '消息类型:file / image / text / event'},
|
||||||
|
sendTime: {type: "STRING", comment: '消息发送时间'},
|
||||||
|
content: {type: "STRING", comment: '消息内容,如果type=file,此属性表示文件的URL地址'},
|
||||||
|
fileSize: {type: "STRING", comment: '文件大小'},
|
||||||
|
fileName: {type: "STRING", comment: '文件名称'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "自动回复表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
type: {type: "STRING", comment: '类型,自动回复/问候语:auto/hello'},
|
||||||
|
status: {type: "STRING", comment: '状态:显示/隐藏:y/n'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
module.exports = {
|
||||||
|
describe_name: "permission/权限管理",
|
||||||
|
testList : [
|
||||||
|
{
|
||||||
|
test_name: "账号密码注册",
|
||||||
|
fun : async (request, server) => {
|
||||||
|
const response = await request(server)
|
||||||
|
.post('/permission/api/registered')
|
||||||
|
.send({
|
||||||
|
type: "accountPassword",
|
||||||
|
data: {
|
||||||
|
account : "test",
|
||||||
|
password: "123456",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// expect(response.status).toEqual(200)
|
||||||
|
expect(response.body.status).toEqual(200)
|
||||||
|
expect(response.body.data).toHaveProperty('token')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test_name: "账号密码登录",
|
||||||
|
fun : async (request, server) => {
|
||||||
|
const response = await request(server)
|
||||||
|
.post('/permission/api/login')
|
||||||
|
.send({
|
||||||
|
type: "accountPassword",
|
||||||
|
data: {
|
||||||
|
account : "test",
|
||||||
|
password: "123456",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// expect(response.status).toEqual(200)
|
||||||
|
expect(response.body.status).toEqual(200)
|
||||||
|
expect(response.body.data).toHaveProperty('token')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
params: {
|
||||||
|
"type": ["accountPassword"],//登录类型
|
||||||
|
"data": "object",//数据
|
||||||
|
},
|
||||||
|
fun : async (ctx, app) => {
|
||||||
|
const {type, data} = ctx.params
|
||||||
|
if (await $components.login[type](data)) {
|
||||||
|
return $res.success({
|
||||||
|
token: await $components.jwt.sign({})
|
||||||
|
}, "登录成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $res.error({}, "登录失败")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
params: {
|
||||||
|
"type": ["accountPassword"],//注册类型
|
||||||
|
"data": "object",//数据
|
||||||
|
},
|
||||||
|
fun : async (ctx, app) => {
|
||||||
|
const {type, data} = ctx.params
|
||||||
|
if (await $components.registered[type](data)) {
|
||||||
|
return $res.success({
|
||||||
|
token: await $components.jwt.sign({})
|
||||||
|
}, "注册成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res.error({}, "登录失败")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
module.exports = {
|
||||||
|
//获取用户所属组织信息
|
||||||
|
async getUserToOrg(uid) {
|
||||||
|
|
||||||
|
},
|
||||||
|
//获取用户所属分组信息
|
||||||
|
async getUserToGroup(uid) {
|
||||||
|
|
||||||
|
},
|
||||||
|
//获取用户权限
|
||||||
|
async getUserToPermission(uid) {
|
||||||
|
|
||||||
|
},
|
||||||
|
//获取用户角色信息
|
||||||
|
async getUserToRole(uid) {
|
||||||
|
|
||||||
|
},
|
||||||
|
//获取用户组织/分组/角色/权限
|
||||||
|
async getUserAll(uid) {
|
||||||
|
|
||||||
|
},
|
||||||
|
//获取组织下全部分组
|
||||||
|
async getOrgToGroupAll(uid) {
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
const crypto = require('crypto');
|
||||||
|
module.exports = {
|
||||||
|
// 随机数(盐值)
|
||||||
|
getRandomSalt() {
|
||||||
|
return Math.random().toString().slice(2, 5);
|
||||||
|
},
|
||||||
|
// 加密用户密码(原始密码,盐值)
|
||||||
|
// 密码同样是123456,由于采用了随机盐值,前后运算得出的结果是不同的。
|
||||||
|
// 这样带来的好处是,多个用户,同样的密码,攻击者需要进行多次运算才能够完全破解。
|
||||||
|
// 同样是纯数字3位短盐值,随机盐值破解所需的运算量,是固定盐值的1000倍。
|
||||||
|
cryptPwd(password, salt) {
|
||||||
|
|
||||||
|
// 密码“加盐”
|
||||||
|
const saltPassword = password + ':' + salt;
|
||||||
|
// 加盐密码的md5值
|
||||||
|
const md5 = crypto.createHash('md5');
|
||||||
|
return md5.update(saltPassword).digest('hex');
|
||||||
|
},
|
||||||
|
// 密码验证,如果验证通过 返回 true
|
||||||
|
cryptPwdVerification(password, salt, user_password_md5) {
|
||||||
|
return this.cryptPwd(password, salt) === user_password_md5;
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
secret : 'sQ6CIfqS4SqF1zZqRZbCDAT5@T]X4fCD',//秘钥
|
||||||
|
algorithm: 'HS256',//数字签名或 MAC 算法
|
||||||
|
expiresIn: "7d",//有效期:例如:1000, "2 days", "10h", "7d". 数值被解释为秒数。如果使用字符串,请确保提供时间单位(天、小时等),否则默认使用毫秒单位("120"等于"120ms")。
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
const jwt = require("jsonwebtoken");
|
||||||
|
const config = require("./config.js");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/**
|
||||||
|
* 签发token
|
||||||
|
* @param {object} data 加入到签名里的数据.
|
||||||
|
* @return {string} token 令牌.
|
||||||
|
*/
|
||||||
|
sign: (data) => jwt.sign(data, config.secret, {algorithm: config.algorithm, expiresIn: config.expiresIn}),
|
||||||
|
/**
|
||||||
|
* 验证token
|
||||||
|
* @param {string} token 令牌.
|
||||||
|
* @return {boolean} 验证通过返回true.
|
||||||
|
*/
|
||||||
|
verify: (token) => jwt.verify(token, config.secret, {algorithm: config.algorithm, expiresIn: config.expiresIn}),
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* app.components.login.accountPassword
|
||||||
|
* 账号密码登陆
|
||||||
|
* @param {string} data.account 账号.
|
||||||
|
* @param {string} data.password 密码.
|
||||||
|
* @return {object} res 验证是否通过.
|
||||||
|
*/
|
||||||
|
module.exports = async (data) => {
|
||||||
|
const {account, password} = data
|
||||||
|
const User = await app.db.table("User").where({account}).find()
|
||||||
|
if (!User) return false
|
||||||
|
const {salt} = User
|
||||||
|
const ver = app.components.encrypt.cryptPwdVerification(password, salt, User.password)
|
||||||
|
return ver
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* app.components.registered.accountPassword
|
||||||
|
* 账号密码注册
|
||||||
|
* @param {string} data.account 账号.
|
||||||
|
* @param {string} data.password 密码.
|
||||||
|
* @return {boolean} 注册 是否 成功.
|
||||||
|
*/
|
||||||
|
module.exports = async (data) => {
|
||||||
|
const {account, password} = data
|
||||||
|
const salt = app.components.encrypt.getRandomSalt()
|
||||||
|
const md5 = app.components.encrypt.cryptPwd(password, salt)
|
||||||
|
await app.db.table("User").data({account, password: md5, salt}).save()
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
path : "app/*/api/*.js",
|
||||||
|
prefix : "",//接口前缀
|
||||||
|
statusTobody: true,//是否跟随body结果(如需接口报错也返回200,那么设置为false)
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use strict';
|
||||||
|
/**
|
||||||
|
* RBAC用户、角色、权限、组设
|
||||||
|
* saas的权限验证
|
||||||
|
*/
|
||||||
|
const config = require("./config")
|
||||||
|
|
||||||
|
// 错误处理
|
||||||
|
module.exports = {
|
||||||
|
sort : 1, //排序
|
||||||
|
use : true, // 是否使用
|
||||||
|
fun : async (ctx, next, app) => {
|
||||||
|
|
||||||
|
|
||||||
|
await next()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "分组表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
gid: {type: "STRING", comment: '分组id'},
|
||||||
|
name: {type: "STRING", comment: '分组名称'},
|
||||||
|
to_gid: {type: "STRING", comment: '上级分组id'},
|
||||||
|
to_oid: {type: "STRING", comment: '所属组织id'},
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "组织表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
oid: {type: "STRING", comment: '组织id'},
|
||||||
|
name: {type: "STRING", comment: '组织名称'},
|
||||||
|
general_management: {type: "STRING", comment: '是否为总管理平台(可以管理所有组织)'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "权限列表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
pid: {type: "STRING", comment: '权限id'},
|
||||||
|
to_pccode: {type: "STRING", comment: '所属权限分类码'},
|
||||||
|
name: {type: "STRING", comment: '权限名称'},
|
||||||
|
code: {type: "STRING", comment: '权限识别码'},
|
||||||
|
value: {type: "STRING", comment: '权限值'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "权限分类表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
name: {type: "STRING", comment: '权限分类名称'},
|
||||||
|
pccode: {type: "STRING", comment: '权限分类识别码'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "角色表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
rid: {type: "STRING", comment: '角色id'},
|
||||||
|
name: {type: "STRING", comment: '角色名称'},
|
||||||
|
to_rid: {type: "STRING", comment: '上级角色id'},
|
||||||
|
to_oid: {type: "STRING", comment: '所属组织id'},
|
||||||
|
to_gid: {type: "STRING", comment: '所属分组id'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "角色拥有的权限",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
rpid: {type: "STRING", comment: '角色权限id'},
|
||||||
|
to_rid: {type: "STRING", comment: '角色id'},
|
||||||
|
to_pid: {type: "STRING", comment: '权限id'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "用户表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
uid: {type: "STRING", comment: '用户id'},
|
||||||
|
account: {type: "STRING", comment: '用户账号'},
|
||||||
|
password: {type: "STRING", comment: '用户加密密码'},
|
||||||
|
salt: {type: "STRING", comment: '用户加密随机数'},
|
||||||
|
to_oid: {type: "STRING", comment: '所属组织id'},
|
||||||
|
to_gid: {type: "STRING", comment: '所属分组id'},
|
||||||
|
to_rid: {type: "STRING", comment: '所属角色id'},
|
||||||
|
to_uid: {type: "STRING", comment: '上级用户id'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
module.exports = {
|
||||||
|
doc: "用户资料表",
|
||||||
|
api: true,//是否需要生成api接口
|
||||||
|
model: {
|
||||||
|
uid: {type: "STRING", comment: '用户id'},
|
||||||
|
account: {type: "STRING", comment: '用户账号'},
|
||||||
|
name: {type: "STRING", comment: '名称'},
|
||||||
|
avatar: {type: "STRING", comment: '头像'},
|
||||||
|
wechat_openid: {type: "STRING", comment: '微信openid'},
|
||||||
|
phone_number: {type: "STRING", comment: '手机号'},
|
||||||
|
age: {type: "STRING", comment: '年龄'},
|
||||||
|
sex: {type: "STRING", comment: '性别'},
|
||||||
|
province: {type: "STRING", comment: '省份'},
|
||||||
|
city: {type: "STRING", comment: '城市'},
|
||||||
|
area: {type: "STRING", comment: '地区'},
|
||||||
|
address: {type: "STRING", comment: '详细地址'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
module.exports = {
|
||||||
|
describe_name: "permission/权限管理",
|
||||||
|
testList : [
|
||||||
|
{
|
||||||
|
test_name: "账号密码注册",
|
||||||
|
fun : async (request, server) => {
|
||||||
|
const response = await request(server)
|
||||||
|
.post('/permission/api/registered')
|
||||||
|
.send({
|
||||||
|
type: "accountPassword",
|
||||||
|
data: {
|
||||||
|
account : "test",
|
||||||
|
password: "123456",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// expect(response.status).toEqual(200)
|
||||||
|
expect(response.body.status).toEqual(200)
|
||||||
|
expect(response.body.data).toHaveProperty('token')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test_name: "账号密码登录",
|
||||||
|
fun : async (request, server) => {
|
||||||
|
const response = await request(server)
|
||||||
|
.post('/permission/api/login')
|
||||||
|
.send({
|
||||||
|
type: "accountPassword",
|
||||||
|
data: {
|
||||||
|
account : "test",
|
||||||
|
password: "123456",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// expect(response.status).toEqual(200)
|
||||||
|
expect(response.body.status).toEqual(200)
|
||||||
|
expect(response.body.data).toHaveProperty('token')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
/*应用配置*/
|
|
||||||
module.exports = {
|
|
||||||
port: 3000,
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/*缓存配置*/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/*控制台配置*/
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*数据库配置*/
|
|
||||||
module.exports = {
|
|
||||||
mysql : {
|
|
||||||
database: "bamboo",
|
|
||||||
username: "bamboo",
|
|
||||||
password: "bamboo",
|
|
||||||
options : {
|
|
||||||
dialect: 'mysql',
|
|
||||||
host : "192.168.1.26",
|
|
||||||
port : 3306,
|
|
||||||
// 禁用日志记录或提供自定义日志记录功能;默认值:console.log
|
|
||||||
// logging: false,
|
|
||||||
// model的全局配置
|
|
||||||
define: {
|
|
||||||
// 添加create,update,delete时间戳
|
|
||||||
timestamps: true,
|
|
||||||
// 添加软删除
|
|
||||||
paranoid: false,
|
|
||||||
// 防止修改表名为复数
|
|
||||||
freezeTableName: true,
|
|
||||||
// 防止驼峰式字段被默认转为下划线
|
|
||||||
underscored: false,
|
|
||||||
},
|
|
||||||
// 由于orm用的UTC时间,这里必须加上东八区,否则取出来的时间相差8小时
|
|
||||||
timezone: '+08:00',
|
|
||||||
// 连接数 = ((核心数 * 2) + 有效磁盘数)
|
|
||||||
pool : {// 连接池
|
|
||||||
max : require('os').cpus().length * 2 + 1,
|
|
||||||
min : 0,
|
|
||||||
acquire: 60000,
|
|
||||||
idle : 100000,
|
|
||||||
},
|
|
||||||
dialectOptions: {
|
|
||||||
charset : "utf8mb4",
|
|
||||||
collate : "utf8mb4_general_ci",
|
|
||||||
supportBigNumbers: true,
|
|
||||||
bigNumberStrings : true,
|
|
||||||
dateStrings : true,
|
|
||||||
typeCast(field, next) {// 让读取date类型数据时返回字符串而不是UTC时间
|
|
||||||
if (field.type === 'DATETIME') {
|
|
||||||
// console.log(field);
|
|
||||||
return field.string();
|
|
||||||
}
|
|
||||||
return next();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
redis : {},
|
|
||||||
sqlite: {
|
|
||||||
dialect: 'sqlite',
|
|
||||||
storage: 'app/sqlite/database.sqlite',
|
|
||||||
logging: false,
|
|
||||||
// model的全局配置
|
|
||||||
define : {
|
|
||||||
// 添加create,update,delete时间戳
|
|
||||||
timestamps: true,
|
|
||||||
// 添加软删除
|
|
||||||
paranoid: false,
|
|
||||||
// 防止修改表名为复数
|
|
||||||
freezeTableName: true,
|
|
||||||
// 防止驼峰式字段被默认转为下划线
|
|
||||||
underscored: false,
|
|
||||||
},
|
|
||||||
dialectOptions: {
|
|
||||||
typeCast(field, next) {// 让读取date类型数据时返回字符串而不是UTC时间
|
|
||||||
if (field.type === 'DATETIME') {
|
|
||||||
// console.log(field);
|
|
||||||
return field.string();
|
|
||||||
}
|
|
||||||
return next();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
dir: {
|
|
||||||
"event" : "app/*/event/*.js",
|
|
||||||
"status" : "app/*/status/*.js",
|
|
||||||
"controller": "app/*/controller/*.js",
|
|
||||||
"model" : "app/*/model/*.js",
|
|
||||||
"middleware": "middleware/*.js",
|
|
||||||
"extend" : "extend/*.js",
|
|
||||||
"schedule" : "schedule/*.js",
|
|
||||||
"sqlite" : "sqlite/model/*.js",
|
|
||||||
"config" : "config/*.js",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/*文件磁盘配置*/
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
//全局配置,权重大于中间件配置与插件配置
|
||||||
|
// 如果设置了全局配置,会覆盖中间件配置与插件配置
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*日志配置*/
|
|
||||||
'use strict';
|
|
||||||
module.exports = {
|
|
||||||
replaceConsole: true,
|
|
||||||
pm2 : true,
|
|
||||||
appenders : {
|
|
||||||
stdout: {//控制台输出
|
|
||||||
type: 'console'
|
|
||||||
},
|
|
||||||
req : { //请求转发日志
|
|
||||||
type : 'dateFile', //指定日志文件按时间打印
|
|
||||||
filename : 'logs/req/req', //指定输出文件路径
|
|
||||||
pattern : 'yyyy-MM-dd.log',
|
|
||||||
alwaysIncludePattern: true
|
|
||||||
},
|
|
||||||
err : { //错误日志
|
|
||||||
type : 'dateFile',
|
|
||||||
filename : 'logs/err/err',
|
|
||||||
pattern : 'yyyy-MM-dd.log',
|
|
||||||
alwaysIncludePattern: true
|
|
||||||
},
|
|
||||||
oth : { //其他日志
|
|
||||||
type : 'dateFile',
|
|
||||||
filename : 'logs/oth/oth',
|
|
||||||
pattern : 'yyyy-MM-dd.log',
|
|
||||||
alwaysIncludePattern: true
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
categories : {
|
|
||||||
//appenders:采用的appender,取appenders项,level:设置级别
|
|
||||||
default: {appenders: ['stdout', 'req'], level: 'debug'},
|
|
||||||
err : {appenders: ['stdout', 'err'], level: 'error'},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
routerPlus: {
|
|
||||||
enable: true,
|
|
||||||
package: 'egg-router-plus',
|
|
||||||
},
|
|
||||||
jwt: {
|
|
||||||
enable: true,
|
|
||||||
package: "egg-jwt"
|
|
||||||
},
|
|
||||||
cors: {
|
|
||||||
enable: true,
|
|
||||||
package: 'egg-cors',
|
|
||||||
},
|
|
||||||
validate: {
|
|
||||||
enable: true,
|
|
||||||
package: 'egg-validate',
|
|
||||||
},
|
|
||||||
sequelize:{
|
|
||||||
enable: true,
|
|
||||||
package: 'egg-sequelize',
|
|
||||||
},
|
|
||||||
axiosPlus: {
|
|
||||||
enable: true,
|
|
||||||
package: 'egg-axios-plus',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/*URL和路由配置*/
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
//更多配置:http://axios-js.com/zh-cn/docs/index.html#%E8%AF%B7%E6%B1%82%E9%85%8D%E7%BD%AE
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
|
||||||
|
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
|
||||||
|
baseURL: 'https://some-domain.com/api/',
|
||||||
|
// `headers` 是即将被发送的自定义请求头
|
||||||
|
headers: {'X-Requested-With': 'XMLHttpRequest'},
|
||||||
|
// `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
|
||||||
|
// 如果请求话费了超过 `timeout` 的时间,请求将被中断
|
||||||
|
timeout: 30 * 1000,
|
||||||
|
|
||||||
|
// `withCredentials` 表示跨域请求时是否需要使用凭证
|
||||||
|
withCredentials: false, // default
|
||||||
|
|
||||||
|
// `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
|
||||||
|
responseType: 'json', // default
|
||||||
|
|
||||||
|
// `responseEncoding` indicates encoding to use for decoding responses
|
||||||
|
// Note: Ignored for `responseType` of 'stream' or client-side requests
|
||||||
|
responseEncoding: 'utf8', // default
|
||||||
|
|
||||||
|
// `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
|
||||||
|
xsrfCookieName: 'XSRF-TOKEN', // default
|
||||||
|
|
||||||
|
// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
|
||||||
|
xsrfHeaderName: 'X-XSRF-TOKEN', // default
|
||||||
|
|
||||||
|
// `maxContentLength` 定义允许的响应内容的最大尺寸
|
||||||
|
// maxContentLength: 2000,
|
||||||
|
|
||||||
|
// `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
|
||||||
|
// 如果设置为0,将不会 follow 任何重定向
|
||||||
|
// maxRedirects: 5, // default
|
||||||
|
|
||||||
|
// 'proxy' 定义代理服务器的主机名称和端口
|
||||||
|
// `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
|
||||||
|
// 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
|
||||||
|
// proxy: {
|
||||||
|
// host: '127.0.0.1',
|
||||||
|
// port: 9000,
|
||||||
|
// auth: {
|
||||||
|
// username: 'mikeymike',
|
||||||
|
// password: 'rapunz3l'
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Axios 是一个基于 promise 的 HTTP 库
|
||||||
|
*/
|
||||||
|
const config = require("./config")
|
||||||
|
const axios = require('axios');
|
||||||
|
const request = require('./request');
|
||||||
|
const requestError = require('./request.error');
|
||||||
|
const response = require('./response');
|
||||||
|
const responseError = require('./response.error');
|
||||||
|
module.exports = async (app) => {
|
||||||
|
Object.assign(axios.defaults, config)
|
||||||
|
axios.interceptors.request.use(request,requestError)
|
||||||
|
axios.interceptors.response.use(response,responseError)
|
||||||
|
app.axios = axios
|
||||||
|
app.alias["$axios"] = app.axios
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
//请求拦截器错误时
|
||||||
|
module.exports = (error) => {
|
||||||
|
// 对请求错误做些什么
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
//请求拦截器
|
||||||
|
module.exports = (config) => {
|
||||||
|
// 在发送请求之前做些什么
|
||||||
|
return config;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
//响应拦截器错误时
|
||||||
|
module.exports = (error) => {
|
||||||
|
// 对请求错误做些什么
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
//响应拦截器
|
||||||
|
module.exports = (response) => {
|
||||||
|
// 对响应数据做点什么
|
||||||
|
return response;
|
||||||
|
}
|
||||||
+2
-2
@@ -1,14 +1,14 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
success: (body, msg, status) => {
|
success: (body, msg, status) => {
|
||||||
return {
|
return {
|
||||||
res : body || null,
|
data : body || null,
|
||||||
status: status || 200,
|
status: status || 200,
|
||||||
message : msg || "success"
|
message : msg || "success"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error : (body, msg, status) => {
|
error : (body, msg, status) => {
|
||||||
return {
|
return {
|
||||||
res : body || null,
|
data : body || null,
|
||||||
status: status || 400,
|
status: status || 400,
|
||||||
message : msg || "error"
|
message : msg || "error"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ const body = require("./body")
|
|||||||
|
|
||||||
module.exports = async (app) => {
|
module.exports = async (app) => {
|
||||||
app.res = body
|
app.res = body
|
||||||
|
app.alias["$res"] = app.res
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const config = require("./config")
|
|||||||
const mq = require("./queue")
|
const mq = require("./queue")
|
||||||
module.exports = async (app) => {
|
module.exports = async (app) => {
|
||||||
app.mq = mq
|
app.mq = mq
|
||||||
|
app.alias["$mq"] = app.mq
|
||||||
|
|
||||||
const queueName = "boobam_schedule"
|
const queueName = "boobam_schedule"
|
||||||
const queue = mq.Queue(queueName);
|
const queue = mq.Queue(queueName);
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
path : "components/*/*.js",
|
||||||
|
app_path: "app/*/components/*/*.js",
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* 通用组件
|
||||||
|
* 加载components文件夹下的函数
|
||||||
|
*/
|
||||||
|
const config = require("./config")
|
||||||
|
module.exports = async (app) => {
|
||||||
|
const list = await app.load(config.path)
|
||||||
|
Object.assign(list, await app.load(config.app_path))
|
||||||
|
app.components = {}
|
||||||
|
list.forEach(item => {
|
||||||
|
if (!app.components[item.parse.file_father]) {
|
||||||
|
app.components[item.parse.file_father] = {}
|
||||||
|
}
|
||||||
|
if (item.parse.name==='index') {
|
||||||
|
Object.assign(app.components[item.parse.file_father],item.res)
|
||||||
|
}else {
|
||||||
|
app.components[item.parse.file_father][item.parse.name] = item.res
|
||||||
|
}
|
||||||
|
})
|
||||||
|
app.alias["$components"] = app.components
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ const config = require("./config")
|
|||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
module.exports = async (app) => {
|
module.exports = async (app) => {
|
||||||
app.event = new EventEmitter()
|
app.event = new EventEmitter()
|
||||||
|
app.alias["$event"] = app.event
|
||||||
const list = await app.load(config.path)
|
const list = await app.load(config.path)
|
||||||
list.forEach(item => {
|
list.forEach(item => {
|
||||||
Object.keys(item.res).forEach(key => {
|
Object.keys(item.res).forEach(key => {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
path:"middleware/*/index.js"
|
path:"middleware/*/index.js",
|
||||||
|
app_path: "app/*/middleware/*/index.js",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,23 @@
|
|||||||
* 加载中间件
|
* 加载中间件
|
||||||
* 加载app/middleware文件夹下的中间件
|
* 加载app/middleware文件夹下的中间件
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const config = require("./config")
|
const config = require("./config")
|
||||||
module.exports = async (app) => {
|
module.exports = async (app) => {
|
||||||
let list = await app.load(config.path)
|
let list = await app.load(config.path)
|
||||||
|
let list2 = await app.load(config.app_path)
|
||||||
|
list=[...list,...list2]
|
||||||
|
// Object.assign(list, list2)
|
||||||
list = app.xe.orderBy(list, "res.sort")
|
list = app.xe.orderBy(list, "res.sort")
|
||||||
list = list.filter(item => item.res.use)
|
list = list.filter(item => item.res.use)
|
||||||
list.forEach(async item => {
|
list.forEach(async item => {
|
||||||
|
console.log('加载的中间件:',item.parse.dir);
|
||||||
if (item.res.loadFun) {
|
if (item.res.loadFun) {
|
||||||
//如果中间件定义了特殊加载方法
|
//如果中间件定义了特殊加载方法
|
||||||
await item.res.loadFun(app, item.res.fun)
|
await item.res.loadFun(app, item.res.fun)
|
||||||
} else {
|
} else {
|
||||||
app.use(async (ctx, next) => {
|
app.use(async (ctx, next) => {
|
||||||
|
|
||||||
return await item.res.fun(ctx, next, app)
|
return await item.res.fun(ctx, next, app)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -9,15 +9,15 @@ module.exports = class Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.tableName = ""
|
this.tableName = null
|
||||||
this.tableWhere = ""
|
this.tableWhere = null
|
||||||
this.tableData = ""
|
this.tableData = null
|
||||||
this.tablePage = ""
|
this.tablePage = null
|
||||||
this.tableLimit = ""
|
this.tableLimit = null
|
||||||
this.tableOrder = ""
|
this.tableOrder = null
|
||||||
this.tableGroup = ""
|
this.tableGroup = null
|
||||||
this.tableAttributes = ""
|
this.tableAttributes = null
|
||||||
this.t = ""
|
this.t = null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
-4
@@ -1,11 +1,11 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
database: "bamboo",
|
database: "bamboo",
|
||||||
username: "bamboo",
|
username: "root",
|
||||||
password: "bamboo",
|
password: "123456",
|
||||||
options: {
|
options: {
|
||||||
dialect: 'mysql',
|
dialect: 'mysql',
|
||||||
host: "192.168.1.26",
|
host: "127.0.0.1",
|
||||||
port: 3306,
|
port: 3357,
|
||||||
// 禁用日志记录或提供自定义日志记录功能;默认值:console.log
|
// 禁用日志记录或提供自定义日志记录功能;默认值:console.log
|
||||||
// logging: false,
|
// logging: false,
|
||||||
// model的全局配置
|
// model的全局配置
|
||||||
@@ -44,4 +44,16 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
path:"app/*/model/*.js",
|
path:"app/*/model/*.js",
|
||||||
|
sqlite:{
|
||||||
|
host: 'localhost',
|
||||||
|
dialect: 'sqlite',
|
||||||
|
pool: {
|
||||||
|
max: 5,
|
||||||
|
min: 0,
|
||||||
|
acquire: 30000,
|
||||||
|
idle: 10000
|
||||||
|
},
|
||||||
|
storage: './database.sqlite',
|
||||||
|
operatorsAliases: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* mysql/sequelize
|
* mysql/sequelize
|
||||||
*
|
*
|
||||||
* 参考文档:
|
* 参考文档:
|
||||||
|
* https://demopark.github.io/sequelize-docs-Zh-CN/
|
||||||
* https://sequelize.org/
|
* https://sequelize.org/
|
||||||
* https://sequelize.org/api/v6/identifiers
|
* https://sequelize.org/api/v6/identifiers
|
||||||
* https://www.sequelize.com.cn/
|
* https://www.sequelize.com.cn/
|
||||||
@@ -10,6 +11,7 @@ const config = require("./config")
|
|||||||
const Sequelize = require("sequelize");
|
const Sequelize = require("sequelize");
|
||||||
const operatorsAliases = require("./operatorsAliases");
|
const operatorsAliases = require("./operatorsAliases");
|
||||||
const Api = require("./api");
|
const Api = require("./api");
|
||||||
|
const Tool = require("./tool.js");
|
||||||
module.exports = async (app) => {
|
module.exports = async (app) => {
|
||||||
const {database, username, password, options,} = config
|
const {database, username, password, options,} = config
|
||||||
const sequelize = new Sequelize(database, username, password, {
|
const sequelize = new Sequelize(database, username, password, {
|
||||||
@@ -41,6 +43,10 @@ module.exports = async (app) => {
|
|||||||
app.models = sequelize.models
|
app.models = sequelize.models
|
||||||
const api = new Api(sequelize, sequelize.models)
|
const api = new Api(sequelize, sequelize.models)
|
||||||
app.db = api
|
app.db = api
|
||||||
|
app.db.tool = new Tool(app, sequelize)
|
||||||
|
//全局变量
|
||||||
|
app.alias["$db"] = app.db
|
||||||
|
|
||||||
// console.log(api);
|
// console.log(api);
|
||||||
// console.log(await app.db.table("User").find());
|
// console.log(await app.db.table("User").find());
|
||||||
|
|
||||||
@@ -60,6 +66,7 @@ module.exports = async (app) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
// await app.db.tool.reduction()
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
const config = require("./config")
|
||||||
|
import mysqldump from 'mysqldump';
|
||||||
|
|
||||||
|
const Importer = require('mysql-import');
|
||||||
|
|
||||||
|
module.exports = class {
|
||||||
|
constructor(app, sequelize) {
|
||||||
|
this.app = app
|
||||||
|
this.sequelize = sequelize
|
||||||
|
this.file = this.app.root + '/' + config.database + '.sql'
|
||||||
|
}
|
||||||
|
|
||||||
|
//备份数据库所有表
|
||||||
|
async backup(file) {
|
||||||
|
this.file = file || this.app.root + '/' + config.database + '.sql'
|
||||||
|
console.log('备份数据库中...');
|
||||||
|
await mysqldump({
|
||||||
|
connection: {
|
||||||
|
host : config.options.host,
|
||||||
|
port : config.options.port,
|
||||||
|
user : config.username,
|
||||||
|
password: config.password,
|
||||||
|
database: config.database,
|
||||||
|
|
||||||
|
},
|
||||||
|
dumpToFile: this.file,
|
||||||
|
});
|
||||||
|
console.log('备份数据库完成:', this.file);
|
||||||
|
}
|
||||||
|
//还原备份sql文件
|
||||||
|
async reduction() {
|
||||||
|
console.time("reduction")
|
||||||
|
//先备份旧数据
|
||||||
|
await this.backup(this.app.root + '/' + 'extend/mysql/backup/' + Date.now() + '.sql')
|
||||||
|
//清空数据库
|
||||||
|
await this.sequelize.drop()
|
||||||
|
//导入sql文件
|
||||||
|
const importer = new Importer({
|
||||||
|
host : config.options.host,
|
||||||
|
port : config.options.port,
|
||||||
|
user : config.username,
|
||||||
|
password: config.password,
|
||||||
|
database: config.database,
|
||||||
|
});
|
||||||
|
this.file = this.app.root + '/' + config.database + '.sql'
|
||||||
|
await importer.import(this.file)
|
||||||
|
console.timeEnd("reduction")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,2 @@
|
|||||||
'use strict';
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* 参数验证插件
|
||||||
|
*/
|
||||||
|
const config = require("./config")
|
||||||
|
const Parameter = require('parameter');
|
||||||
|
const parameter = new Parameter();
|
||||||
|
module.exports = async (app) => {
|
||||||
|
app.parameter = parameter
|
||||||
|
app.alias["$parameter"] = app.parameter
|
||||||
|
}
|
||||||
@@ -11,5 +11,7 @@ module.exports = async (app) => {
|
|||||||
const redis = new Redis(config);
|
const redis = new Redis(config);
|
||||||
app.redis = redis
|
app.redis = redis
|
||||||
app.Redis = Redis
|
app.Redis = Redis
|
||||||
|
//全局变量
|
||||||
|
app.alias["$redis"] = app.redis
|
||||||
|
app.alias["$Redis"] = app.Redis
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
path: "app/*/io/*.js",
|
path: "app/*/io/*.js",
|
||||||
|
port: 3210,
|
||||||
|
test_port: 3211,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,16 @@
|
|||||||
*/
|
*/
|
||||||
const config = require("./config")
|
const config = require("./config")
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const uuid = require("uuid");
|
||||||
module.exports = async (app) => {
|
module.exports = async (app) => {
|
||||||
|
const parameter = app.parameter
|
||||||
const server = require('http').createServer(app.callback());
|
const server = require('http').createServer(app.callback());
|
||||||
const io = require('socket.io')(server);
|
const io = require('socket.io')(server, {cors: true});
|
||||||
|
// let leaveRoom = () => {
|
||||||
|
// }
|
||||||
let list = await app.load(config.path)
|
let list = await app.load(config.path)
|
||||||
app.io = io
|
app.io = io
|
||||||
|
app.alias["$io"] = app.io
|
||||||
//等待所有插件载入完成后
|
//等待所有插件载入完成后
|
||||||
app.willReadyList.push(async () => {
|
app.willReadyList.push(async () => {
|
||||||
//默认命名空间
|
//默认命名空间
|
||||||
@@ -24,17 +29,35 @@ module.exports = async (app) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log('连接=>', "id:" + socket.id);
|
console.log('连接=>', "id:" + socket.id);
|
||||||
|
|
||||||
//监听disconnect事件
|
//监听disconnect事件
|
||||||
socket.on('disconnect', (eventName, callback) => {
|
// socket.on('disconnect', (eventName, callback) => {
|
||||||
console.log('断开=X', "id:" + socket.id)
|
// console.log('断开=X', "id:" + socket.id)
|
||||||
})
|
// leaveRoom(socket, {msg: '', onname: 'leaveRoom', callback})
|
||||||
|
// })
|
||||||
for (let el of list) {
|
for (let el of list) {
|
||||||
//空间名称
|
//空间名称
|
||||||
// const namespace = path.basename(path.resolve(el.parse.dir, '..'))
|
// const namespace = path.basename(path.resolve(el.parse.dir, '..'))
|
||||||
//事件名称
|
//事件名称
|
||||||
const onname = el.parse.name
|
const onname = el.parse.name
|
||||||
socket.on(onname, (msg, callback) => {
|
// if (onname === 'leaveRoom') {
|
||||||
el.res(app, msg, callback)
|
// //离开房间处理
|
||||||
|
// leaveRoom = (socket, {msg, onname, callback}) => el.res.fun(socket, {msg, onname, callback})
|
||||||
|
// }
|
||||||
|
socket.on(onname, (msg, callback, anotherSocketId) => {
|
||||||
|
console.log('anotherSocketId', socket.id);
|
||||||
|
const validate = parameter.validate(el.res.params, msg);
|
||||||
|
if (validate) {
|
||||||
|
socket.emit('error', {
|
||||||
|
event: onname,
|
||||||
|
res : app.res.error(validate, "参数验证不通过", 204)
|
||||||
|
})
|
||||||
|
console.error('socket', socket.id, msg, onname, app.res.error(validate, "参数验证不通过", 204));
|
||||||
|
// ctx.body = app.res.error(validate, "参数验证不通过", 204)
|
||||||
|
} else {
|
||||||
|
el.res.fun(socket, {msg, onname, callback})
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -45,9 +68,15 @@ module.exports = async (app) => {
|
|||||||
//覆盖启动方法
|
//覆盖启动方法
|
||||||
app.startServer = () => {
|
app.startServer = () => {
|
||||||
// 监听端口
|
// 监听端口
|
||||||
app.startServer = server.listen(3000, () => {
|
const port = (process.env.NODE_ENV === 'test' && config.test_port) || config.port || 3000
|
||||||
console.log('listening on *:3000');
|
const baseURL = "http://127.0.0.1"
|
||||||
|
app.config.port = port
|
||||||
|
app.config.baseURL = baseURL
|
||||||
|
app.server = server.listen(port, () => {
|
||||||
|
console.log(`http 服务: ${baseURL}:${port}`);
|
||||||
|
console.log(`socket 服务: ${baseURL}:${port}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+195
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* For a detailed explanation regarding each configuration property, visit:
|
||||||
|
* https://jestjs.io/docs/configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// 测试中所有导入的模块都应该自动模拟
|
||||||
|
// automock: false,
|
||||||
|
|
||||||
|
// `n` 次失败后停止运行测试
|
||||||
|
// bail: 0,
|
||||||
|
|
||||||
|
// TJest 应该存储其缓存依赖信息的目录
|
||||||
|
// 缓存目录:“privatevarfolderscdm9j91n110831mbzcxnqtlz700000gnTjest_dx”,
|
||||||
|
|
||||||
|
// 每次测试前自动清除模拟调用、实例、上下文和结果
|
||||||
|
clearMocks: true,
|
||||||
|
|
||||||
|
// 指示是否应在执行测试时收集覆盖率信息
|
||||||
|
collectCoverage: false,
|
||||||
|
|
||||||
|
// 一组 glob 模式,指示应为其收集覆盖信息的一组文件
|
||||||
|
// collectCoverageFrom: undefined,
|
||||||
|
|
||||||
|
// Jest 应该输出其覆盖文件的目录
|
||||||
|
coverageDirectory: "coverage",
|
||||||
|
|
||||||
|
// 用于跳过覆盖收集的正则表达式模式字符串数组
|
||||||
|
coveragePathIgnorePatterns: [
|
||||||
|
"/node_modules/"
|
||||||
|
],
|
||||||
|
|
||||||
|
// 指示应使用哪个提供程序来检测代码以进行覆盖
|
||||||
|
coverageProvider: "v8",
|
||||||
|
|
||||||
|
// Jest 在编写报道报告时使用的记者姓名列表
|
||||||
|
// coverageReporters: [
|
||||||
|
// "json",
|
||||||
|
// "text",
|
||||||
|
// "lcov",
|
||||||
|
// "clover"
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// 为覆盖结果配置最小阈值强制执行的对象
|
||||||
|
// coverageThreshold: undefined,
|
||||||
|
|
||||||
|
// 自定义依赖项提取器的路径
|
||||||
|
// dependencyExtractor: undefined,
|
||||||
|
|
||||||
|
// 调用已弃用的 API 会引发有用的错误消息
|
||||||
|
// errorOnDeprecated: false,
|
||||||
|
|
||||||
|
// 假定时器的默认配置
|
||||||
|
// fakeTimers: {
|
||||||
|
// "enableGlobally": false
|
||||||
|
// },
|
||||||
|
|
||||||
|
// 使用 glob 模式数组强制从被忽略的文件中收集覆盖率
|
||||||
|
// forceCoverageMatch: [],
|
||||||
|
|
||||||
|
// 导出异步函数的模块的路径,该函数在所有测试套件之前触发一次
|
||||||
|
// globalSetup: undefined,
|
||||||
|
|
||||||
|
// 导出所有测试套件后触发一次的异步函数的模块的路径
|
||||||
|
// globalTeardown: undefined,
|
||||||
|
|
||||||
|
// 一组需要在所有测试环境中可用的全局变量
|
||||||
|
// globals: {},
|
||||||
|
|
||||||
|
// 用于运行测试的最大工作人员数量。可以指定为 % 或数字。例如。 maxWorkers: 10% 将使用 CPU 数量的 10% + 1 作为最大工作线程数。 maxWorkers: 2 将使用最多 2 个工人。
|
||||||
|
// maxWorkers: "50%",
|
||||||
|
|
||||||
|
// 从需要模块的位置递归搜索的目录名称数组
|
||||||
|
// moduleDirectories: [
|
||||||
|
// "node_modules"
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// 您的模块使用的一系列文件扩展名
|
||||||
|
// moduleFileExtensions: [
|
||||||
|
// "js",
|
||||||
|
// "mjs",
|
||||||
|
// "cjs",
|
||||||
|
// "jsx",
|
||||||
|
// "ts",
|
||||||
|
// "tsx",
|
||||||
|
// "json",
|
||||||
|
// "node"
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// 从正则表达式到模块名称或模块名称数组的映射,允许使用单个模块存根资源
|
||||||
|
// moduleNameMapper: {},
|
||||||
|
|
||||||
|
// 一个正则表达式模式字符串数组,在被认为对模块加载器“可见”之前与所有模块路径匹配
|
||||||
|
// modulePathIgnorePatterns: [],
|
||||||
|
|
||||||
|
// 激活测试结果通知
|
||||||
|
// notify: false,
|
||||||
|
|
||||||
|
// 一个指定通知模式的枚举。需要 { 通知:真 }
|
||||||
|
// notifyMode: "failure-change",
|
||||||
|
|
||||||
|
// A preset that is used as a base for Jest's configuration
|
||||||
|
// preset: undefined,
|
||||||
|
|
||||||
|
// Run tests from one or more projects
|
||||||
|
// projects: undefined,
|
||||||
|
|
||||||
|
// Use this configuration option to add custom reporters to Jest
|
||||||
|
// reporters: undefined,
|
||||||
|
|
||||||
|
// Automatically reset mock state before every test
|
||||||
|
// resetMocks: false,
|
||||||
|
|
||||||
|
// Reset the module registry before running each individual test
|
||||||
|
// resetModules: false,
|
||||||
|
|
||||||
|
// A path to a custom resolver
|
||||||
|
// resolver: undefined,
|
||||||
|
|
||||||
|
// Automatically restore mock state and implementation before every test
|
||||||
|
// restoreMocks: false,
|
||||||
|
|
||||||
|
// The root directory that Jest should scan for tests and modules within
|
||||||
|
// rootDir: undefined,
|
||||||
|
|
||||||
|
// A list of paths to directories that Jest should use to search for files in
|
||||||
|
// roots: [
|
||||||
|
// "<rootDir>"
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// Allows you to use a custom runner instead of Jest's default test runner
|
||||||
|
// runner: "jest-runner",
|
||||||
|
|
||||||
|
// The paths to modules that run some code to configure or set up the testing environment before each test
|
||||||
|
// setupFiles: [],
|
||||||
|
|
||||||
|
// A list of paths to modules that run some code to configure or set up the testing framework before each test
|
||||||
|
// setupFilesAfterEnv: [],
|
||||||
|
|
||||||
|
// The number of seconds after which a test is considered as slow and reported as such in the results.
|
||||||
|
// slowTestThreshold: 5,
|
||||||
|
|
||||||
|
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
|
||||||
|
// snapshotSerializers: [],
|
||||||
|
|
||||||
|
// The test environment that will be used for testing
|
||||||
|
// testEnvironment: "jest-environment-node",
|
||||||
|
|
||||||
|
// Options that will be passed to the testEnvironment
|
||||||
|
// testEnvironmentOptions: {},
|
||||||
|
|
||||||
|
// Adds a location field to test results
|
||||||
|
// testLocationInResults: false,
|
||||||
|
|
||||||
|
//Jest 用于检测测试文件的 glob 模式
|
||||||
|
testMatch: ["**/+(*.)+(spec|test).+(ts|js)?(x)"],
|
||||||
|
|
||||||
|
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
|
||||||
|
// testPathIgnorePatterns: [
|
||||||
|
// "/node_modules/"
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// The regexp pattern or array of patterns that Jest uses to detect test files
|
||||||
|
// testRegex: [],
|
||||||
|
|
||||||
|
// This option allows the use of a custom results processor
|
||||||
|
// testResultsProcessor: undefined,
|
||||||
|
|
||||||
|
// This option allows use of a custom test runner
|
||||||
|
// testRunner: "jest-circus/runner",
|
||||||
|
|
||||||
|
// 从正则表达式到转换器路径的映射
|
||||||
|
// transform: undefined,
|
||||||
|
|
||||||
|
// 与所有源文件路径匹配的正则表达式模式字符串数组,匹配的文件将跳过转换
|
||||||
|
// transformIgnorePatterns: [
|
||||||
|
// "/node_modules/",
|
||||||
|
// "\\.pnp\\.[^\\/]+$"
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
|
||||||
|
// unmockedModulePathPatterns: undefined,
|
||||||
|
|
||||||
|
// Indicates whether each individual test should be reported during the run
|
||||||
|
// verbose: undefined,
|
||||||
|
|
||||||
|
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
|
||||||
|
// watchPathIgnorePatterns: [],
|
||||||
|
|
||||||
|
// Whether to use watchman for file crawling
|
||||||
|
// watchman: true,
|
||||||
|
|
||||||
|
|
||||||
|
"testTimeout": 1000000
|
||||||
|
};
|
||||||
+38
-8
@@ -11,12 +11,25 @@ module.exports = class Bamboo extends Koa {
|
|||||||
/*初始化业务目录*/
|
/*初始化业务目录*/
|
||||||
constructor(extend_directory, root) {
|
constructor(extend_directory, root) {
|
||||||
super();
|
super();
|
||||||
|
//全局配置
|
||||||
|
this.config = {}
|
||||||
|
//xe-utils工具
|
||||||
this.xe = xe
|
this.xe = xe
|
||||||
|
//根目录
|
||||||
this.root = this.isPath() || root;
|
this.root = this.isPath() || root;
|
||||||
|
//插件路径
|
||||||
this.extend_directory = extend_directory || `extend/*/index.js`
|
this.extend_directory = extend_directory || `extend/*/index.js`
|
||||||
|
//等待扩展已经加载完成后立即执行的任务列表
|
||||||
this.willReadyList = []
|
this.willReadyList = []
|
||||||
console.log(`当前根目录${this.root}`);
|
//全局别名,推荐命名规则,$+全局变量名,如$db
|
||||||
console.log(`当前插件目录${this.extend_directory}`);
|
this.alias = {
|
||||||
|
"app": this,
|
||||||
|
"$": this,
|
||||||
|
}
|
||||||
|
//等待启动完成后立即执行的任务列表
|
||||||
|
this.fullList = []
|
||||||
|
// console.log(`当前根目录${this.root}`);
|
||||||
|
// console.log(`当前插件目录${this.extend_directory}`);
|
||||||
this.loadEvent()
|
this.loadEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,17 +39,33 @@ module.exports = class Bamboo extends Koa {
|
|||||||
for (let listElement of list) {
|
for (let listElement of list) {
|
||||||
await listElement.res(this)
|
await listElement.res(this)
|
||||||
}
|
}
|
||||||
this.willReadyList.push(() => {
|
await this.loadAlias()
|
||||||
this.startServer()
|
|
||||||
})
|
|
||||||
await this.willReady()
|
await this.willReady()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*加载别名到全局变量,注意只有完成加载扩展后才能使用*/
|
||||||
|
async loadAlias() {
|
||||||
|
for (let key of Object.keys(this.alias)) {
|
||||||
|
global[key] = this.alias[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*扩展已经加载完成触发*/
|
/*扩展已经加载完成触发*/
|
||||||
async willReady() {
|
async willReady() {
|
||||||
|
this.willReadyList.push(async () => {
|
||||||
|
await this.startServer()
|
||||||
|
await this.full()
|
||||||
|
})
|
||||||
for (let WRL of this.willReadyList) {
|
for (let WRL of this.willReadyList) {
|
||||||
await WRL()
|
await WRL(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*启动完成*/
|
||||||
|
async full() {
|
||||||
|
for (let ful of this.fullList) {
|
||||||
|
await ful(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +89,7 @@ module.exports = class Bamboo extends Koa {
|
|||||||
files = files.map(item => {
|
files = files.map(item => {
|
||||||
const parse = path.parse(item);
|
const parse = path.parse(item);
|
||||||
parse.father = path.basename(path.resolve(parse.dir, '..'))
|
parse.father = path.basename(path.resolve(parse.dir, '..'))
|
||||||
|
parse.file_father = path.basename(path.resolve(parse.dir + '/' + parse.name, '..'))
|
||||||
return {
|
return {
|
||||||
parse,
|
parse,
|
||||||
res: require(path.resolve(path_root + "/" + item))
|
res: require(path.resolve(path_root + "/" + item))
|
||||||
@@ -73,7 +103,7 @@ module.exports = class Bamboo extends Koa {
|
|||||||
|
|
||||||
/*启动服务*/
|
/*启动服务*/
|
||||||
startServer(prod) {
|
startServer(prod) {
|
||||||
this.listen(prod || 3000)
|
app.server = this.listen(prod || 3000)
|
||||||
console.log('启动服务:3000');
|
console.log(`http服务:http://127.0.0.1:${prod || 3000}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -12,7 +12,8 @@ require('@babel/register')({
|
|||||||
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
require('@babel/polyfill')
|
// require('@babel/polyfill')
|
||||||
const bamboo = require('./bamboo/index')
|
const bamboo = require('./bamboo/index')
|
||||||
const app = new bamboo();
|
const app = new bamboo();
|
||||||
// app.listen(3000);
|
// app.listen(3000);
|
||||||
|
module.exports = app
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const bodyParser = require('koa-bodyparser')
|
const bodyParser = require('koa-bodyparser')
|
||||||
// 错误处理
|
// 解析json的入参
|
||||||
module.exports = {
|
module.exports = {
|
||||||
sort: 4, //排序
|
sort: 2, //排序
|
||||||
use : true, // 是否使用
|
use : true, // 是否使用
|
||||||
fun : bodyParser()
|
fun : bodyParser()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
'use strict';
|
||||||
|
const cors = require('@koa/cors')
|
||||||
|
// 跨域
|
||||||
|
module.exports = {
|
||||||
|
sort: 0, //排序
|
||||||
|
use : true, // 是否使用
|
||||||
|
fun : cors()
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ const error = require('koa-json-error')
|
|||||||
// 错误处理
|
// 错误处理
|
||||||
module.exports = {
|
module.exports = {
|
||||||
sort: 3, //排序
|
sort: 3, //排序
|
||||||
use : true, // 是否使用
|
use : false, // 是否使用
|
||||||
fun : error((err) => {
|
fun : error((err) => {
|
||||||
return {
|
return {
|
||||||
status : err.status,
|
status : err.status,
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
path : "app/*/model/*.js",
|
||||||
|
prefix : "auto",//接口前缀
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
'use strict';
|
||||||
|
/**
|
||||||
|
* 加载模型到路由
|
||||||
|
* 加载app/api目录下的文件到路由
|
||||||
|
*/
|
||||||
|
const Router = require('koa-router')
|
||||||
|
const config = require("./config")
|
||||||
|
|
||||||
|
// 错误处理
|
||||||
|
module.exports = {
|
||||||
|
sort : 999, //排序
|
||||||
|
use : false, // 是否使用
|
||||||
|
loadFun: async (app, fun) => { // 自行定义中间件的加载方式,将覆盖默认加载方法
|
||||||
|
const router = await fun(app)
|
||||||
|
app.use(router.routes()).use(router.allowedMethods())
|
||||||
|
},
|
||||||
|
fun : async (app) => {
|
||||||
|
const router = new Router({ //设置前缀
|
||||||
|
prefix: config.prefix
|
||||||
|
});
|
||||||
|
let list = await app.load(config.path)
|
||||||
|
list.forEach(item => {
|
||||||
|
|
||||||
|
})
|
||||||
|
return router
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/*封装入参*/
|
/*封装入参*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
sort: 3, //排序
|
sort: 5, //排序
|
||||||
use : true, // 是否使用
|
use : true, // 是否使用
|
||||||
fun : async (ctx, next, app) => {
|
fun : async (ctx, next, app) => {
|
||||||
|
|
||||||
ctx.params = ctx.request.body || ctx.query
|
ctx.params = ctx.request.body || ctx.query
|
||||||
|
|
||||||
await next()
|
await next()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
path : "app/*/api/*.js",
|
path : "app/*/api/*.js",
|
||||||
prefix : "",//接口前缀
|
prefix : "",//接口前缀
|
||||||
statusTobody: true,//是否跟随body结果(如需接口报错也返回200,那么设置为false)
|
statusTobody: false,//是否跟随body结果(如需接口报错也返回200,那么设置为false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
const Router = require('koa-router')
|
const Router = require('koa-router')
|
||||||
const config = require("./config")
|
const config = require("./config")
|
||||||
|
// const parameter = require('./parameter');
|
||||||
// 错误处理
|
// 错误处理
|
||||||
module.exports = {
|
module.exports = {
|
||||||
sort : 999, //排序
|
sort : 999, //排序
|
||||||
@@ -15,36 +15,56 @@ module.exports = {
|
|||||||
app.use(router.routes()).use(router.allowedMethods())
|
app.use(router.routes()).use(router.allowedMethods())
|
||||||
},
|
},
|
||||||
fun : async (app) => {
|
fun : async (app) => {
|
||||||
|
const parameter = app.parameter
|
||||||
const router = new Router({ //设置前缀
|
const router = new Router({ //设置前缀
|
||||||
prefix: config.prefix
|
prefix: config.prefix
|
||||||
});
|
});
|
||||||
let list = await app.load(config.path)
|
let list = await app.load(config.path)
|
||||||
list.forEach(item => {
|
list.forEach(item => {
|
||||||
const url = item.res.path ? item.res.path : '/' + item.parse.father + '/api/' + item.parse.name
|
const url = item.res.path ? item.res.path : '/' + item.parse.father + '/api/' + item.parse.name
|
||||||
|
console.log(url);
|
||||||
router.all(url, async (ctx, next) => {
|
router.all(url, async (ctx, next) => {
|
||||||
|
await next();
|
||||||
|
const validate = parameter.validate(item.res.params, ctx.params);
|
||||||
|
let res = null
|
||||||
|
if (validate) {
|
||||||
|
ctx.body = app.res.error(validate, "参数验证不通过", 204)
|
||||||
|
} else {
|
||||||
/*处理body结果*/
|
/*处理body结果*/
|
||||||
try {
|
try {
|
||||||
const res = await item.res.fun(ctx, app)
|
res = await item.res.fun(ctx, app)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
ctx.body = app.res.error(null, "系统错误", 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!ctx.body) {
|
if (!ctx.body) {
|
||||||
if (res) {
|
if (res) {
|
||||||
|
if (res.status&&res.message) {
|
||||||
|
ctx.body = res
|
||||||
|
}else{
|
||||||
ctx.body = app.res.success(res)
|
ctx.body = app.res.success(res)
|
||||||
|
}
|
||||||
} else if (res === false) {
|
} else if (res === false) {
|
||||||
ctx.body = app.res.error()
|
ctx.body = app.res.error()
|
||||||
} else {
|
} else {
|
||||||
ctx.body = app.res.success()
|
ctx.body = app.res.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
ctx.body = app.res.error(null, "系统错误", 500)
|
|
||||||
ctx.status = 500
|
|
||||||
}
|
|
||||||
|
|
||||||
//是否跟随body结果
|
//是否跟随body结果
|
||||||
ctx.status = config.statusTobody ? ctx.body.status || 400 : 200
|
ctx.status = config.statusTobody ? ctx.body.status || 400 : 200
|
||||||
await next();
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.all('/', async (ctx, next) => {
|
||||||
|
|
||||||
|
ctx.body = app.res.success("ok")
|
||||||
|
ctx.status = 200
|
||||||
|
await next();
|
||||||
|
})
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
const Parameter = require('parameter');
|
||||||
|
const parameter = new Parameter();
|
||||||
|
|
||||||
|
//添加规则
|
||||||
|
// parameter.addRule('123', (rule, value) => {
|
||||||
|
// if (value !== '123') {
|
||||||
|
// return 'must be 123';
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
module.exports = parameter
|
||||||
+1
-1
@@ -5,5 +5,5 @@
|
|||||||
".idea",
|
".idea",
|
||||||
"node_modules/**/node_modules"
|
"node_modules/**/node_modules"
|
||||||
],
|
],
|
||||||
"exec": "node lib/main.js"
|
"exec": "npm run start"
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-11
@@ -6,24 +6,30 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nodemon",
|
"dev": "nodemon",
|
||||||
"start": "node lib/main.js",
|
"start": "node lib/main.js",
|
||||||
"server": "cross-env NODE_ENV=development nodemon bin/main.js"
|
"server": "cross-env NODE_ENV=development nodemon bin/main.js",
|
||||||
|
"test": "jest --forceExit"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.5.5",
|
"@babel/cli": "^7.18.6",
|
||||||
|
"@babel/core": "^7.18.6",
|
||||||
|
"@babel/node": "^7.18.6",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.16.7",
|
"@babel/plugin-proposal-class-properties": "^7.16.7",
|
||||||
"@babel/plugin-proposal-decorators": "^7.17.9",
|
"@babel/plugin-proposal-decorators": "^7.17.9",
|
||||||
"@babel/plugin-transform-runtime": "^7.5.5",
|
"@babel/plugin-transform-runtime": "^7.5.5",
|
||||||
"@babel/preset-env": "^7.5.5",
|
"@babel/preset-env": "^7.18.6",
|
||||||
"@babel/register": "^7.5.5",
|
"@babel/register": "^7.18.6",
|
||||||
|
"@babel/runtime": "^7.18.6",
|
||||||
"art-template": "^4.13.2",
|
"art-template": "^4.13.2",
|
||||||
"babel-plugin-webpack-alias": "^2.1.2",
|
"babel-plugin-webpack-alias": "^2.1.2",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"babel-register": "^6.26.0",
|
"babel-register": "^6.26.0",
|
||||||
"cross-env": "^5.2.0",
|
"chai": "^4.3.6",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
"ejs": "^2.6.2",
|
"ejs": "^2.6.2",
|
||||||
|
"jest": "^28.1.1",
|
||||||
"koa": "^2.7.0",
|
"koa": "^2.7.0",
|
||||||
"koa-art-template": "^1.1.1",
|
"koa-art-template": "^1.1.1",
|
||||||
"koa-bodyparser": "^4.2.1",
|
"koa-bodyparser": "^4.2.1",
|
||||||
@@ -33,24 +39,28 @@
|
|||||||
"koa-views": "^6.2.0",
|
"koa-views": "^6.2.0",
|
||||||
"koa-webpack": "^6.0.0",
|
"koa-webpack": "^6.0.0",
|
||||||
"koa-webpack-middleware": "^1.0.7",
|
"koa-webpack-middleware": "^1.0.7",
|
||||||
|
"mocha": "^10.0.0",
|
||||||
|
"mysql-import": "^5.0.21",
|
||||||
"nodeenv": "^1.0.0",
|
"nodeenv": "^1.0.0",
|
||||||
"nodemon": "^1.19.1"
|
"nodemon": "^1.19.4",
|
||||||
|
"sequelize-mock": "^0.10.2",
|
||||||
|
"supertest": "^6.2.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.16.7",
|
|
||||||
"@babel/node": "^7.16.8",
|
|
||||||
"@babel/plugin-proposal-decorators": "^7.18.2",
|
"@babel/plugin-proposal-decorators": "^7.18.2",
|
||||||
"@babel/polyfill": "^7.4.4",
|
"@babel/polyfill": "^7.4.4",
|
||||||
"@babel/preset-env": "^7.16.8",
|
"@koa/cors": "^3.3.0",
|
||||||
"@babel/runtime": "^7.5.5",
|
|
||||||
"ajv": "^8.11.0",
|
"ajv": "^8.11.0",
|
||||||
|
"axios": "^0.27.2",
|
||||||
"babel-loader": "^8.2.3",
|
"babel-loader": "^8.2.3",
|
||||||
"bamboo_smf": "^1.0.5",
|
"bamboo_smf": "^1.0.5",
|
||||||
"bullmq": "^1.85.1",
|
"bullmq": "^1.85.1",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"cross-env": "^7.0.3",
|
"crypto": "^1.0.1",
|
||||||
"glob": "^8.0.1",
|
"glob": "^8.0.1",
|
||||||
"ioredis": "^5.0.5",
|
"ioredis": "^5.0.5",
|
||||||
|
"jest": "^28.1.1",
|
||||||
|
"jsonwebtoken": "^8.5.1",
|
||||||
"koa-bodyparser": "^4.3.0",
|
"koa-bodyparser": "^4.3.0",
|
||||||
"koa-json-error": "^3.1.2",
|
"koa-json-error": "^3.1.2",
|
||||||
"koa-logger": "^2.0.1",
|
"koa-logger": "^2.0.1",
|
||||||
@@ -58,6 +68,7 @@
|
|||||||
"koa-router": "^7.4.0",
|
"koa-router": "^7.4.0",
|
||||||
"log4js": "^6.4.4",
|
"log4js": "^6.4.4",
|
||||||
"mysql2": "^2.3.3",
|
"mysql2": "^2.3.3",
|
||||||
|
"mysqldump": "^3.2.0",
|
||||||
"node-schedule": "^2.1.0",
|
"node-schedule": "^2.1.0",
|
||||||
"object-path": "^0.11.8",
|
"object-path": "^0.11.8",
|
||||||
"parameter": "^3.6.0",
|
"parameter": "^3.6.0",
|
||||||
@@ -68,6 +79,8 @@
|
|||||||
"shelljs": "^0.8.5",
|
"shelljs": "^0.8.5",
|
||||||
"socket.io": "^4.5.1",
|
"socket.io": "^4.5.1",
|
||||||
"sqlite3": "^5.0.2",
|
"sqlite3": "^5.0.2",
|
||||||
|
"supertest": "^6.2.3",
|
||||||
|
"uuid": "^8.3.2",
|
||||||
"webpack": "^4.41.5",
|
"webpack": "^4.41.5",
|
||||||
"webpack-cli": "3.3.10",
|
"webpack-cli": "3.3.10",
|
||||||
"webpack-node-externals": "^3.0.0",
|
"webpack-node-externals": "^3.0.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user