befly 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apis/health/info.js +32 -23
- package/apis/tool/tokenCheck.js +26 -0
- package/main.js +20 -10
- package/package.json +2 -2
- package/utils/jwt.js +0 -65
package/apis/health/info.js
CHANGED
|
@@ -3,31 +3,40 @@ import { Api } from '../../utils/api.js';
|
|
|
3
3
|
import { RYes, RNo } from '../../utils/util.js';
|
|
4
4
|
|
|
5
5
|
export default Api.POST('健康检查', false, {}, [], async (befly, ctx) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
6
|
+
try {
|
|
7
|
+
const info = {
|
|
8
|
+
status: 'ok',
|
|
9
|
+
timestamp: new Date().toISOString(),
|
|
10
|
+
uptime: process.uptime(),
|
|
11
|
+
memory: process.memoryUsage(),
|
|
12
|
+
runtime: 'Bun',
|
|
13
|
+
version: Bun.version,
|
|
14
|
+
platform: process.platform,
|
|
15
|
+
arch: process.arch
|
|
16
|
+
};
|
|
17
|
+
// 检查 Redis 连接状态
|
|
18
|
+
if (Env.REDIS_ENABLE === 1) {
|
|
19
|
+
if (befly.redis) {
|
|
20
|
+
try {
|
|
21
|
+
await befly.redis.ping();
|
|
22
|
+
info.redis = '已连接';
|
|
23
|
+
} catch (error) {
|
|
24
|
+
info.redis = '未连接';
|
|
25
|
+
info.redisError = error.message;
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
info.redis = '未开启';
|
|
25
29
|
}
|
|
26
30
|
} else {
|
|
27
|
-
info.redis = '
|
|
31
|
+
info.redis = '禁用';
|
|
28
32
|
}
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
return RYes('健康检查成功', info);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
befly.logger.error({
|
|
36
|
+
msg: '健康检查失败',
|
|
37
|
+
error: error.message,
|
|
38
|
+
stack: error.stack
|
|
39
|
+
});
|
|
40
|
+
return RNo('健康检查失败');
|
|
31
41
|
}
|
|
32
|
-
return RYes('健康检查成功', info);
|
|
33
42
|
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Env } from '../../config/env.js';
|
|
2
|
+
import { Api } from '../../utils/api.js';
|
|
3
|
+
import { RYes, RNo } from '../../utils/util.js';
|
|
4
|
+
import { Jwt } from '../../utils/jwt.js';
|
|
5
|
+
|
|
6
|
+
export default Api.POST('令牌检测', false, {}, [], async (befly, ctx) => {
|
|
7
|
+
try {
|
|
8
|
+
const jwtData = await Jwt.verify(ctx.headers?.authorization?.split(' ')[1] || '');
|
|
9
|
+
return RYes(
|
|
10
|
+
'令牌有效',
|
|
11
|
+
{
|
|
12
|
+
state: 'yes'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
detail: jwtData
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
befly.logger.error({
|
|
20
|
+
msg: '令牌检测失败',
|
|
21
|
+
error: error.message,
|
|
22
|
+
stack: error.stack
|
|
23
|
+
});
|
|
24
|
+
return RNo('令牌检测失败', { state: 'no' });
|
|
25
|
+
}
|
|
26
|
+
});
|
package/main.js
CHANGED
|
@@ -319,13 +319,18 @@ class Befly {
|
|
|
319
319
|
hostname: Env.APP_HOST,
|
|
320
320
|
routes: {
|
|
321
321
|
'/': async (req) => {
|
|
322
|
-
return Response.json(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
322
|
+
return Response.json(
|
|
323
|
+
{
|
|
324
|
+
code: 0,
|
|
325
|
+
msg: 'Befly 接口服务已启动',
|
|
326
|
+
data: {
|
|
327
|
+
mode: Env.NODE_ENV
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
headers: corsOptions.headers
|
|
327
332
|
}
|
|
328
|
-
|
|
333
|
+
);
|
|
329
334
|
},
|
|
330
335
|
'/api/*': async (req) => {
|
|
331
336
|
try {
|
|
@@ -351,7 +356,10 @@ class Befly {
|
|
|
351
356
|
const api = this.apiRoutes.get(apiPath);
|
|
352
357
|
|
|
353
358
|
// 接口不存在
|
|
354
|
-
if (!api)
|
|
359
|
+
if (!api)
|
|
360
|
+
return Response.json(RNo('接口不存在'), {
|
|
361
|
+
headers: corsOptions.headers
|
|
362
|
+
});
|
|
355
363
|
|
|
356
364
|
const authHeader = req.headers.get('authorization');
|
|
357
365
|
if (authHeader && authHeader.startsWith('Bearer ')) {
|
|
@@ -403,7 +411,9 @@ class Befly {
|
|
|
403
411
|
stack: err.stack
|
|
404
412
|
});
|
|
405
413
|
|
|
406
|
-
return Response.json(RNo('无效的请求参数格式')
|
|
414
|
+
return Response.json(RNo('无效的请求参数格式'), {
|
|
415
|
+
headers: corsOptions.headers
|
|
416
|
+
});
|
|
407
417
|
}
|
|
408
418
|
}
|
|
409
419
|
|
|
@@ -515,8 +525,8 @@ class Befly {
|
|
|
515
525
|
});
|
|
516
526
|
|
|
517
527
|
const finalStartupTime = (Bun.nanoseconds() - serverStartTime) / 1_000_000;
|
|
518
|
-
Logger.info(
|
|
519
|
-
Logger.info(
|
|
528
|
+
Logger.info(`Befly 服务器启动成功! 完整启动耗时: ${finalStartupTime.toFixed(2)}ms`);
|
|
529
|
+
Logger.info(`服务器监听地址: http://${Env.APP_HOST}:${Env.APP_PORT}`);
|
|
520
530
|
|
|
521
531
|
if (callback && typeof callback === 'function') {
|
|
522
532
|
callback(server);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "befly",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Buma - 为 Bun 专属打造的 API 接口框架核心引擎",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"README.md",
|
|
50
50
|
"vitest.config.js"
|
|
51
51
|
],
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "2fc8a0aa987c42e983e0e2ce2e74cddbfed53a7f"
|
|
53
53
|
}
|
package/utils/jwt.js
CHANGED
|
@@ -50,35 +50,6 @@ export class Jwt {
|
|
|
50
50
|
return this.verifier(token);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
/**
|
|
54
|
-
* 创建自定义签名器
|
|
55
|
-
* @param {object} options - 签名选项
|
|
56
|
-
* @returns {Promise<Function>} 签名器函数
|
|
57
|
-
*/
|
|
58
|
-
static async createSigner(options = {}) {
|
|
59
|
-
const { createSigner } = await import('fast-jwt');
|
|
60
|
-
return createSigner({
|
|
61
|
-
key: options.key || Env.JWT_SECRET,
|
|
62
|
-
expiresIn: options.expiresIn || Env.JWT_EXPIRES_IN || '7d',
|
|
63
|
-
algorithm: options.algorithm || Env.JWT_ALGORITHM || 'HS256',
|
|
64
|
-
...options
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* 创建自定义验证器
|
|
70
|
-
* @param {object} options - 验证选项
|
|
71
|
-
* @returns {Promise<Function>} 验证器函数
|
|
72
|
-
*/
|
|
73
|
-
static async createVerifier(options = {}) {
|
|
74
|
-
const { createVerifier } = await import('fast-jwt');
|
|
75
|
-
return createVerifier({
|
|
76
|
-
key: options.key || Env.JWT_SECRET,
|
|
77
|
-
algorithms: options.algorithms || [Env.JWT_ALGORITHM || 'HS256'],
|
|
78
|
-
...options
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
53
|
/**
|
|
83
54
|
* 解码 JWT token (不验证签名)
|
|
84
55
|
* @param {string} token - JWT token
|
|
@@ -100,21 +71,6 @@ export class Jwt {
|
|
|
100
71
|
}
|
|
101
72
|
}
|
|
102
73
|
|
|
103
|
-
/**
|
|
104
|
-
* 检查 token 是否过期
|
|
105
|
-
* @param {string} token - JWT token
|
|
106
|
-
* @returns {boolean} 是否过期
|
|
107
|
-
*/
|
|
108
|
-
static isExpired(token) {
|
|
109
|
-
try {
|
|
110
|
-
const { payload } = this.decode(token);
|
|
111
|
-
if (!payload.exp) return false;
|
|
112
|
-
return Date.now() >= payload.exp * 1000;
|
|
113
|
-
} catch {
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
74
|
/**
|
|
119
75
|
* 获取 token 剩余有效时间 (秒)
|
|
120
76
|
* @param {string} token - JWT token
|
|
@@ -130,25 +86,4 @@ export class Jwt {
|
|
|
130
86
|
return -1;
|
|
131
87
|
}
|
|
132
88
|
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* 刷新 token (重新签名相同载荷)
|
|
136
|
-
* @param {string} token - 旧的 JWT token
|
|
137
|
-
* @returns {Promise<string>} 新的 JWT token
|
|
138
|
-
*/
|
|
139
|
-
static async refresh(token) {
|
|
140
|
-
const { payload } = this.decode(token);
|
|
141
|
-
// 移除时间相关的声明,让新 token 重新生成
|
|
142
|
-
delete payload.iat;
|
|
143
|
-
delete payload.exp;
|
|
144
|
-
delete payload.nbf;
|
|
145
|
-
return this.sign(payload);
|
|
146
|
-
}
|
|
147
89
|
}
|
|
148
|
-
|
|
149
|
-
// 使用示例:
|
|
150
|
-
// const token = await JWT.sign({ userId: 123, role: 'user' });
|
|
151
|
-
// const payload = await JWT.verify(token);
|
|
152
|
-
// const isExpired = JWT.isExpired(token);
|
|
153
|
-
// const remaining = JWT.getTimeToExpiry(token);
|
|
154
|
-
// const newToken = await JWT.refresh(token);
|