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.

185 lines
5.6 KiB

6 months ago
// | ------------------------------------------------------------
// | @版本: version 0.1
// | @创建人: 【Nie-x7129】
// | @E-mail: x71291@outlook.com
// | @所在项目: 2160
// | @文件描述: app.js -
// | @创建时间: 2024-01-13 21:05
// | @更新时间: 2024-01-13 21:05
// | @修改记录:
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
// | =
// | ------------------------------------------------------------
// 加载时间工具
import '#tools/dateFormate.js';
// ! 读取ENV
const ENV = process.argv[2]?.trim().toLowerCase() || 'production';
// ! 是否为开发环境
const isDev = ENV == 'development' || ENV == 'dev' || ENV == 'develop';
// ! 导入环境标识
global.isDev = isDev;
// ! 加载配置文件
import {devConf, proConf} from '#config';
// ! 导入配置文件
global.conf = global.isDev ? devConf : proConf;
// * 加载核心框架
import Fastify from 'fastify';
// ! 加载路由
import routes from '#routes/index.js';
// ! 获取当前设备IP
import getLocalIPv4 from '#tools/getLocalIp.js';
// * ejs模板
import ejs from 'ejs';
// * ajv错误模板
import ajvErrors from 'ajv-errors';
// ! 自定义Ajv参数验证插件
import { isLowerCase, isTrim } from '#plugins/ajv/index.js';
async function start(){
// | 创建fastify实例
const fastify = new Fastify({
logger: {
level: 'debug',
serializers: {
req(request) {
// 不返回任何东西,实际上就是屏蔽了自动的请求日志
return {};
},
res(reply) {
// 同理,不返回任何东西以屏蔽响应日志
return {};
}
},
transport: {
target: 'pino-pretty',
options: {
level: 'error',
// 这个选项确保输出带颜色
colorize: true,
translateTime: 'yyyy-mm-dd HH:MM:ss',
// 对象信息打印在一行
singleLine: true
}
}
},
ajv: {
customOptions: {
removeAdditional: true,
useDefaults: true,
coerceTypes: true,
allErrors: true,
// 允许使用联合模式 严格模式下
allowUnionTypes: true
},
plugins: [
ajvErrors,
// 这种方式完美解决,开心, 实际上这是一个函数,会传进去ajv实例对象
isLowerCase,
isTrim,
]
}
});
// | 装饰器示例
// @ 配置文件
fastify.decorate('conf', global.conf);
fastify.decorate('authenticate', async function(request, reply) {
try {
// 校验token,并生成request的user参数
await request.jwtVerify();
} catch (err) {
// token校验未通过,记录错误
fastify.log.debug({ reqId: request.id, Auth: err.message });
reply.code(err.statusCode).send({
statusCode: err.statusCode,
message: err.message,
error: err.name
});
}
});
// | 生命周期
// @ 请求拦截
fastify.addHook('onRequest', async function (request, reply) {
return;
});
// @ 响应拦截
fastify.addHook('onResponse', async function (request, reply){
return;
});
// @ 发送消息拦截
fastify.addHook('onSend', async (request, reply, payload) => {
// fastify.log.info(reply.getHeader('content-type'));
if(reply.statusCode === 200 && !request.url.includes('/api/file') ){
return `{"statusCode": 200, "status": "success", "data": ${payload}}`;
}
return payload;
});
// @ 错误拦截
fastify.setErrorHandler(async (error, request, reply) => {
// 自定义错误处理逻辑
fastify.log.error(error);
reply
.code(error.statusCode)
.send({
statusCode: error.statusCode,
message: error.message,
error: error.name
});
});
// | 插件
// @ 注册防止恶意请求封ip
await fastify.register(import('@fastify/rate-limit'), global.conf.rateLimit);
// @ 注册html模板
fastify.register(import('@fastify/view'), {
engine: {ejs},
includeViewExtension: true,
root: 'views'
});
// @ 错误处理工具
fastify.register(import('@fastify/sensible'));
// @ 注册redis
await fastify.register(import('@fastify/redis'), {
// 配置文件基础redis配置 host,port,password
...global.conf.redis,
// fastify调用的名称空间
namespace: 'db1',
// 指向的redis数据库0-15
db: 1,
// 4 (IPv4) or 6 (IPv6)
family: 4,
// redis连接中的名字
connectionName: global.conf.projectName
});
// fastify.log.info(await fastify.redis.db1.set('name', 'xsx', 'EX', 60));
// @ 注册jwt
fastify.register(import('@fastify/jwt'), global.conf.jwt);
// @ 注册路由
await fastify.register(routes);
// | 监听指定端口
await fastify.listen(global.conf.listen);
// | 输出监听地址和端口
getLocalIPv4().map(i => isDev && fastify.log.info(`http://${i}:${fastify.conf.listen.port}`));
// console.log(fastify.printPlugins())
// console.log(fastify.printRoutes({ commonPrefix: false }));
// console.log(fastify.printRoutes({ method: 'GET' }));
}
start();