Spaces:
Sleeping
Sleeping
File size: 3,847 Bytes
ba2906a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
import fs from 'node:fs'
import path from 'node:path'
import YAML from 'yaml'
import multer from 'multer'
import rateLimit from 'express-rate-limit'
export default class plugin {
/**
* @param {string} name 插件名称
* @param {string} [dsc] 插件描述
* @param {number} [priority] 插件优先级
* @param {string} [route] 请求路径前缀
* @param {string} rule.method 请求方法
* * rule.method可以是数组,method[ws]属于自定义方法不经过app.handle所以不支持通配符
* @param {string} rule.path 请求路径
* * 有route前缀时请求路径=route+rule.path
* @param {string} [rule.use] 中间件路由
* * 匹配到的路由会在rule.fnc方法之前按顺序执行一遍rule.use中间件
* * rule.use是string时fn需要返回中间件函数, rule.use是数组时则直接传入req,res对象
* @param {string} rule.fnc 请求默认方法
* * 每个请求都是一个实例,可以打印this查看默认对象
* * 方法执行完成之前必须结束与客户端的连接
* * 或者调用next()将控制权交给下一个路由,否则客户端请求会一直处于挂起状态
*/
constructor (data = {}) {
/** 插件名称 */
this.name = data.name || ''
/** 插件描述 */
this.dsc = data.dsc || ''
/** 插件优先级 */
this.priority = data.priority || 5
/** 请求路径前缀 */
this.route = data.route || ''
/** 路由规则 */
this.rule = data.rule || []
/** 定时任务,可以是数组 */
this.task = {
/** 任务名 */
name: '',
/** 任务方法名 */
fnc: data.task?.fnc || '',
/** 任务cron表达式 */
cron: data.task?.cron || ''
}
}
/** 读json */
readJson (filePath, format = 'json') {
try {
if (format == 'yaml') {
return YAML.parse(fs.readFileSync(filePath, 'utf8'))
}
return JSON.parse(fs.readFileSync(filePath, 'utf8'))
} catch (err) {
return false
}
}
/** 写json */
writeJson (savePath, data, format = 'json') {
this.mkdir(path.dirname(savePath))
if (format == 'yaml') return fs.writeFileSync(savePath, YAML.stringify(data))
return fs.writeFileSync(savePath, JSON.stringify(data, null, 2))
}
/** 创建文件夹 */
mkdir (dirname) {
if (fs.existsSync(dirname)) {
return true
} else {
if (this.mkdir(path.dirname(dirname))) {
fs.mkdirSync(dirname)
return true
}
}
}
/** 休眠函数 */
sleep (ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
/** 速率限制 */
limiter (limit = 15, cd = 60, options = {}) {
options = {
limit,
windowMs: cd * 1000,
legacyHeaders: false,
message: { status: 1, message: 'Frequent requests, please try again later' },
...options
}
return rateLimit(options)
}
/** 文件上传, single, array, any */
upload (savaPath = './public/upload', filename, options = {}) {
options = {
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, savaPath)
},
filename: filename || ((req, file, cb) => {
cb(null, Date.now() + path.extname(file.originalname))
})
}),
limits: { fileSize: 5 * 1024 * 1024, files: 1 },
...options
}
return multer(options)
}
/** CORS头部 */
cors () {
return (req, res, next) => {
res.set({
'Access-Control-Allow-Credentials': true,
'Access-Control-Max-Age': 1728000,
'Access-Control-Allow-Origin': req.headers.origin || '*',
'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type',
'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS'
})
req.method === 'OPTIONS' ? res.status(204).end() : next()
}
}
}
|