This commit is contained in:
robin
2022-05-21 06:48:12 +08:00
parent b5f918776e
commit 96333ae7a9
45 changed files with 650 additions and 64 deletions
+123
View File
@@ -0,0 +1,123 @@
const Koa = require("koa")
const load = require("./load")
const path = require('path')
const xe = require("xe-utils")
const EventEmitter = require('events');
const Router = require("koa-router");
const Parameter = require('parameter');
const error = require('./errorException');
const log4js = require("log4js");
const Smf = require('./smf/smf');
module.exports = class Bamboo extends Koa {
constructor() {
super();
this.init()
}
path(args) {
return this.isPath + '/' + (args || "")
}
isPath(args) {
return path.resolve('./' + (args || ""))
}
get xe() {
return xe
}
async init() {
this.config = {}
await this.loadConfig()
this.event = new EventEmitter()
this.parameter = new Parameter();
this.error = error;
this.smf = new Smf()
log4js.configure(this.config['log']);
this.logger = log4js.getLogger();
// await this.loadEvent()
// await this.loadStatus()
// await this.loadMiddleware()
// await this.loadController()
}
/**
* 加载配置
*/
async loadConfig() {
this.config = {}
const config = await load(this.isPath(), "config")
config.forEach(item => {
this.config[item.file_name] = item.res
})
}
//
// /**
// * 加载事件
// */
// async loadEvent() {
// const event = await load(this.isPath(), "event")
// event.forEach(item => {
// Object.keys(item.res).forEach(key => {
// this.event.on(key, item.res[key])
// })
// })
// }
//
// /**
// * 加载状态
// */
// async loadStatus() {
// const status = await load(this.isPath(), "status")
// const setSmfDataList = []
// status.forEach(item => {
// setSmfDataList.push(item.res)
// })
// this.smf.setSmfDataList(setSmfDataList)
// //监听流程变更
// this.smf.on((e, paras) => {
// this.event.emit(e.currentState, paras)
// })
// }
//
// /**
// * 加载控制器路由
// */
// async loadController() {
// const controller = await load(this.isPath(), "controller")
// const router = new Router();
// controller.forEach(item => {
// item.res.method.forEach(method => {
// router[method](item.res.path, async (ctx, next) => {
// const validate = this.parameter.validate(item.res.params, ctx.request.body);
// if (validate) {
// console.error(validate);
// this.error.ParameterException(validate);
// }
// else {
// await item.res.fun(ctx, this.application)
// await next();
// }
// })
// })
// })
// }
//
// /**
// * 加载中间件
// */
// async loadMiddleware() {
// const middleware = await load(this.isPath(), "middleware")
// let hashList = xe.toArray(middleware)
// hashList = xe.orderBy(hashList, "fun.sort")
// hashList = hashList.filter(item => item.res.use)
// hashList.forEach(item => {
// this.use(async (ctx, next) => {
// ctx['logger'] = this.logger
// return await item.res.fun(ctx, next, this.application)
// })
// })
// }
}
+53
View File
@@ -0,0 +1,53 @@
class HttpException extends Error {
// message为异常信息,code 为错误码(开发人员内部约定),status 为HTTP状态码
constructor(message, code, status) {
super()
this.status = status || 500
this.code = code || 500
this.message = message || '服务器异常'
}
}
class ParameterException extends HttpException {
constructor(message, code, status) {
super()
this.status = status || 402
this.code = code
this.message = message || '参数错误'
}
}
class NotFound extends HttpException {
constructor(message, code, status) {
super()
this.status = status || 404
this.code = 404
this.message = message || '资源未找到'
}
}
class AuthFailed extends HttpException {
constructor(message, code, status) {
super()
this.status = status || 401
this.message = message || '授权失败'
this.code = 401
}
}
class Forbidden extends HttpException {
constructor(message, code, status) {
super()
this.status = status || 403
this.message = message || '禁止访问'
this.code = 403
}
}
module.exports = {
HttpException: (message, code, status) => {throw new HttpException(message, code, status)},
ParameterException: (message, code, status) => {throw new ParameterException(message, code, status)},
NotFound: (message, code, status) => {throw new NotFound(message, code, status)},
AuthFailed: (message, code, status) => {throw new AuthFailed(message, code, status)},
Forbidden: (message, code, status) => {throw new Forbidden(message, code, status)},
}
+22 -14
View File
@@ -92,7 +92,7 @@ module.exports = class Bamboo extends Koa {
registeredError() {
console.log('注册 错误');
this.errorException = {}
const hash = requireDirectory(module, this.path('app/err'), {
const hash = requireDirectory(module, this.path('lib/bamboo/err'), {
visit: (obj) => {
for (let key of Object.keys(obj)) {
this.errorException[key] = (message, code) => {
@@ -308,9 +308,8 @@ module.exports = class Bamboo extends Koa {
const parse = path.parse(filename);
// super.on(parse.name, obj);
for (let key of Object.keys(obj)) {
this.event.on(`${parse.name}.${key}`, obj[key]);
this.event.on(`${parse.name}.${key}`, e[key]);
}
return obj
}
});
@@ -338,18 +337,27 @@ module.exports = class Bamboo extends Koa {
console.log('注册 middleware');
const hash = requireDirectory(module, this.path('app/middleware'), {
visit: (obj, joined, filename) => {
console.log(obj, joined, filename);
const parse = path.parse(filename);
const config = this.config.middleware[parse.name]
// super.use(obj(config || {}))
super.use(async (ctx, next) => {
ctx['logger'] = this.logger
return await obj(ctx, next, this.application)
})
// console.log(obj, joined, filename);
// const parse = path.parse(filename);
// const config = this.config.middleware[parse.name]
// // super.use(obj(config || {}))
// super.use(async (ctx, next) => {
// ctx['logger'] = this.logger
// return await obj.fun(ctx, next, this.application)
// })
return obj
}
});
// console.log(hash);
let hashList = xe.toArray(hash)
hashList = xe.orderBy(hashList,"sort")
hashList = hashList.filter(item=>item.use)
hashList.forEach(item=>{
super.use(async (ctx, next) => {
ctx['logger'] = this.logger
return await item.fun(ctx, next, this.application)
})
})
console.log(hashList);
}
//注册 utils
@@ -938,7 +946,7 @@ module.exports = class Bamboo extends Koa {
const tkKeys = Object.keys(tk)
for (let key of tkKeys) {
if (key === "as") { continue; }
if (key === "where"||key === "data") {
if (key === "where" || key === "data") {
const findJsonRes = this.findJsonValue(tk[key], (n) => {
if (typeof n === "string") {
// console.log(tk[key],n);
@@ -996,7 +1004,7 @@ module.exports = class Bamboo extends Koa {
}
path = path || []
// 获取所有的子节点,并遍历
if (typeof n ==="object") {
if (typeof n === "object") {
const nkeys = Object.keys(n)
for (let k of nkeys) {
// concat() 方法用于连接两个或多个数组
+41
View File
@@ -0,0 +1,41 @@
const glob = require("glob")
const path = require('path')
/**
* 项目文件加载
*/
const list = {
"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",
}
module.exports = function load(directory, key) {
return new Promise((resolve, reject) => {
const options = {
root: directory
}
glob(list[key], options, function (er, files) {
if (er) { reject(er) }
console.log(files);
files = files.map(item => {
const parse = path.parse(item);
return {
dir : parse.dir,
file_name: parse.name,
res : require(path.resolve(directory + "/" + item))
}
})
resolve(files)
})
})
}
+227
View File
@@ -0,0 +1,227 @@
const xe = require("xe-utils")
/**
* 状态机-编排复杂的流程状态业务
* @param {string} listName 列名.
*/
module.exports = class Status {
constructor(listName, status, data) {
this.data = data
this.status = status
this.listName = listName
this.list = []
}
/**
* 返回上个状态
*/
back() {
let index = this.getStatusIndex(this.listName, this.status)
const res = this.getList(this.listName)
if ((index - 1) < 0) {
return null
}
const status = res.status[index - 1]
if (res.listName && status.name) {
this.go(res.listName, status.name)
}
return this
}
/**
* 下一个状态
*/
next() {
let index = this.getStatusIndex(this.listName, this.status)
const res = this.getList(this.listName)
if (res.status.length <= (index + 1)) {
return null
}
const status = res.status[index + 1]
if (res.listName && status.name) {
this.go(res.listName, status.name)
}
return this
}
/**
* 触发成功事件
*/
success() {
const index = this.getStatusIndex(this.listName, this.status)
const res = this.getList(this.listName)
const status = res.status[index]
if (status.success.event) { this.emitEvent(status.success.event) }
if (status.success.listName && status.success.status) {
this.go(status.success.listName, status.success.status)
}
return this
}
emitEvent(eventName) {
console.log("emitEvent:", eventName);
}
fail() {
const index = this.getStatusIndex(this.listName, this.status)
const res = this.getList(this.listName)
const status = res.status[index]
if (status.fail.event) { this.emitEvent(status.fail.event) }
if (status.fail.listName && status.fail.status) {
this.go(status.fail.listName, status.fail.status)
}
return this
}
go(listName, status) {
this.status = status
this.listName = listName
return this
}
getStatusIndex(listName, status) {
const res = this.getList(listName)
let index = xe.findKey(res.status, item => item.name === status)
return index ? Number(index) : null
}
getList(listName) {
const res = this.list.filter(item => item.listName === listName)
if (res.length <= 0) { return false }
return res[0]
}
push({status, success, fail}) {
const res = this.getList(this.listName)
if (res) {
success = success || {}
success["listName"] = success["listName"] || ""
success["status"] = success["status"] || ""
success["event"] = success["event"] || ""
fail = fail || {}
fail["listName"] = fail["listName"] || ""
fail["status"] = fail["status"] || ""
fail["event"] = fail["event"] || ""
res.status.push({
name : status,
success: success,
fail : fail,
})
}
else {return false}
return this
}
create(listName) {
if (!listName) { return false }
const res = this.getList(listName)
if (res) { return false }
this.list.push({
listName: listName,
status : []
})
this.listName = listName
return this
}
}
//
// const s = new Status()
//
// s.create("ord")
// .push({
// status : "start",
// success: {
// listName: "ord", //成功后切换到的listName
// status : "pay", //成功后切换到的status
// event : "ord.start",
// },
// fail : {
// listName: "", //失败后切换到的listName
// status : "", //失败后切换到的status
// event : "",
// },
// })
// .push({
// status : "pay",
// success: {
// listName: "ord", //成功后切换到的listName
// status : "end", //成功后切换到的status
// event : "ord.pay",
// },
// fail : {
// listName: "refund", //失败后切换到的listName
// status : "start", //失败后切换到的status
// event : "",
// },
// })
// .push({
// status : "end",
// success: {
// listName: "", //成功后切换到的listName
// status : "", //成功后切换到的status
// event : "ord.end",
// },
// fail : {
// listName: "", //失败后切换到的listName
// status : "", //失败后切换到的status
// event : "",
// },
// })
// s.create("refund")
// .push({
// status : "start",
// success: {
// listName: "refund", //成功后切换到的listName
// status : "ret", //成功后切换到的status
// event : "refund.start",
// },
// fail : {
// listName: "", //失败后切换到的listName
// status : "", //失败后切换到的status
// event : "",
// },
// })
// .push({
// status : "ret",
// success: {
// listName: "refund", //成功后切换到的listName
// status : "end", //成功后切换到的status
// event : "refund.ret",
// },
// fail : {
// listName: "", //失败后切换到的listName
// status : "", //失败后切换到的status
// event : "",
// },
// })
// .push({
// status : "end",
// success: {
// listName: "", //成功后切换到的listName
// status : "", //成功后切换到的status
// event : "refund.end",
// },
// fail : {
// listName: "", //失败后切换到的listName
// status : "", //失败后切换到的status
// event : "",
// },
// })
// // console.log(s);
//
// s.go("ord", "start")
// console.log(s.listName, s.status);
// s.success()
// console.log(s.listName, s.status);
// s.fail()
// console.log(s.listName, s.status);
// s.success()
// console.log(s.listName, s.status);
// s.success()
// console.log(s.listName, s.status);
// s.success()
// console.log(s.listName, s.status);
// s.next()
// console.log(s.listName, s.status);
+1 -1
View File
@@ -13,6 +13,6 @@ require('@babel/register')({
]
})
require('@babel/polyfill')
const bamboo = require('./bamboo/index')
const bamboo = require('./bamboo/bamboo')
const app = new bamboo();
// app.listen(3000);