You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
9.6 KiB
195 lines
9.6 KiB
// @ts-nocheck
|
|
|
|
import { walkDir, removeIndex, isIndexEnd } from "./util"
|
|
import * as Joi from "joi"
|
|
const path = require("path")
|
|
const fs = require("fs")
|
|
|
|
class routePlugin {
|
|
public name: string = "routePlugin"
|
|
public version: string = "0.0.1"
|
|
public register(server: any, opts: any) {
|
|
const sourceDir = opts.sourceDir
|
|
const type = opts.type || "jwt"
|
|
const auth = opts.auth || []
|
|
let array = []
|
|
for (let i = 0; i < sourceDir.length; i++) {
|
|
const dir = sourceDir[i]
|
|
console.log(dir)
|
|
array.push(dir.dir + "对应路径:")
|
|
array = array.concat(this.registerRoute(server, dir.dir, dir.prefix || "", auth, type))
|
|
}
|
|
fs.writeFileSync(path.resolve(process.cwd(), "route.txt"), array.join("\n"), {
|
|
encoding: "utf-8",
|
|
})
|
|
}
|
|
registerRoute(server, sourceDir, prefix, auth, type) {
|
|
const files = walkDir(sourceDir)
|
|
const routes = []
|
|
files.forEach(file => {
|
|
let filename = file.relativeFileNoExt
|
|
let array = filename.split(path.sep).slice(1)
|
|
let fileNoExt = removeIndex("/" + array.join("/"))
|
|
const moduleName = path.resolve(sourceDir, filename)
|
|
const obj = require(moduleName)
|
|
if (obj.default) {
|
|
const func = new (obj.default || obj)()
|
|
const prototype = Object.getPrototypeOf(func)
|
|
const keys = Reflect.ownKeys(prototype)
|
|
for (const key of keys) {
|
|
if (key !== "constructor") {
|
|
let ff = func[key]
|
|
let handler: () => void = undefined
|
|
// 默认方法
|
|
const method = ff.$method || "GET"
|
|
// 路由收集规则
|
|
let route = ""
|
|
if(ff.$route_path){
|
|
route = ff.$route_path
|
|
route = prefix ? route[0] + prefix + "/" + route.slice(1) : route
|
|
}else{
|
|
if (ff.$route) {
|
|
if (isIndexEnd(fileNoExt)) {
|
|
route = ff.$route
|
|
} else {
|
|
route = fileNoExt + ff.$route
|
|
}
|
|
} else {
|
|
if (isIndexEnd(fileNoExt)) {
|
|
route = fileNoExt + key.toString()
|
|
} else {
|
|
route = fileNoExt + "/" + key.toString()
|
|
}
|
|
}
|
|
route = removeIndex(route)
|
|
route = prefix ? route[0] + prefix + "/" + route.slice(1) : route
|
|
}
|
|
// 配置规则
|
|
const options = ff.$options ? ff.$options : {}
|
|
if (!options.auth) {
|
|
if (ff.$auth == undefined) {
|
|
if (auth && auth.length && auth.filter(v => route.startsWith(v)).length) {
|
|
options.auth = type
|
|
} else {
|
|
options.auth = false
|
|
}
|
|
} else if (ff.$auth) {
|
|
options.auth =
|
|
typeof ff.$auth === "boolean"
|
|
? type
|
|
: {
|
|
strategy: type,
|
|
mode: ff.$auth,
|
|
}
|
|
} else {
|
|
options.auth = false
|
|
}
|
|
}
|
|
if (!options.validate) {
|
|
let validateObj = ff.$validate || {}
|
|
if (options.auth && type === "jwt") {
|
|
if (validateObj.headers) {
|
|
validateObj.headers = validateObj.headers.keys({
|
|
Authorization: Joi.string(),
|
|
})
|
|
} else {
|
|
validateObj.headers = Joi.object({
|
|
headers: Joi.object({
|
|
Authorization: Joi.string(),
|
|
}).unknown(), // 注意加上这个
|
|
})
|
|
}
|
|
}
|
|
if (validateObj && !!Object.keys(validateObj).length) {
|
|
const failReason = validateObj.failReason
|
|
delete validateObj.failReason
|
|
if (validateObj.failAction === "log") {
|
|
if (!options.log) options.log = {}
|
|
options.log.collect = true
|
|
let errto = validateObj.$errto
|
|
handler = async function (...argus) {
|
|
const request = argus[0]
|
|
const h = argus[1]
|
|
if (request.logs && !!request.logs.length && errto) {
|
|
// request.yar.flash('error', request.logs.map((v: any)=>v.error.message));
|
|
request.yar.flash("error", failReason || request.logs.map((v: any)=>v.error.message))
|
|
return h.redirect(errto)
|
|
}
|
|
return await ff.call(this, ...argus)
|
|
}
|
|
}
|
|
if (validateObj.failAction === "function") {
|
|
let errto = validateObj.$errto
|
|
validateObj.failAction = async function (request, h, err) {
|
|
if (err.details) {
|
|
request.$joi_error = err.details.map(v => v.message)
|
|
}
|
|
return h.continue
|
|
}
|
|
handler = async function (...argus) {
|
|
const request = argus[0]
|
|
const h = argus[1]
|
|
if (request.$joi_error) {
|
|
loggerSite.debug("传输参数错误: ", request.$joi_error)
|
|
request.yar.flash("error", failReason || request.$joi_error)
|
|
delete request.$joi_error
|
|
return h.redirect(errto)
|
|
}
|
|
return await ff.call(this, ...argus)
|
|
}
|
|
}
|
|
options.validate = validateObj
|
|
}
|
|
}
|
|
// && route.startsWith("/api")
|
|
if (ff.$swagger) {
|
|
options.description = ff.$swagger[0]
|
|
options.notes = ff.$swagger[1]
|
|
options.tags = ff.$swagger[2]
|
|
}
|
|
let str = route
|
|
if (
|
|
(typeof options.auth === "string" && options.auth) ||
|
|
(typeof options.auth === "object" && options.auth.mode === "required")
|
|
) {
|
|
str = " 需要权限 : " + " " + full(method) + " " + str
|
|
} else if (typeof options.auth === "object" && options.auth.mode === "optional") {
|
|
str = " 不需权限(提供即需验证): " + " " + full(method) + " " + str
|
|
} else if (typeof options.auth === "object" && options.auth.mode === "try") {
|
|
str = " 不需权限(提供无需验证): " + " " + full(method) + " " + str
|
|
} else {
|
|
str = " 不需权限 : " + " " + full(method) + " " + str
|
|
}
|
|
routes.push(str)
|
|
|
|
if (options.validate && options.validate.$errto) {
|
|
delete options.validate.$errto
|
|
}
|
|
if (!handler) {
|
|
handler = ff
|
|
}
|
|
server.route({
|
|
method: method,
|
|
path: route,
|
|
handler: handler,
|
|
options: options,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
})
|
|
return routes
|
|
}
|
|
}
|
|
|
|
function full(str: string, length = 10) {
|
|
let len = str.length
|
|
let need = length - len
|
|
if (need <= 0) return str
|
|
return str + [...Array(need)].map((v, i) => " ").join("")
|
|
}
|
|
|
|
const plugin = new routePlugin()
|
|
|
|
export { plugin }
|
|
export * from "./util/decorators"
|
|
|