befly 3.2.0 → 3.3.0

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.
Files changed (73) hide show
  1. package/bin/index.ts +138 -0
  2. package/checks/conflict.ts +35 -25
  3. package/checks/table.ts +6 -6
  4. package/commands/addon.ts +57 -0
  5. package/commands/build.ts +74 -0
  6. package/commands/dev.ts +94 -0
  7. package/commands/index.ts +252 -0
  8. package/commands/script.ts +308 -0
  9. package/commands/start.ts +80 -0
  10. package/commands/syncApi.ts +328 -0
  11. package/{scripts → commands}/syncDb/apply.ts +2 -2
  12. package/{scripts → commands}/syncDb/constants.ts +13 -7
  13. package/{scripts → commands}/syncDb/ddl.ts +7 -5
  14. package/{scripts → commands}/syncDb/helpers.ts +18 -18
  15. package/{scripts → commands}/syncDb/index.ts +37 -23
  16. package/{scripts → commands}/syncDb/sqlite.ts +1 -1
  17. package/{scripts → commands}/syncDb/state.ts +10 -4
  18. package/{scripts → commands}/syncDb/table.ts +7 -7
  19. package/{scripts → commands}/syncDb/tableCreate.ts +7 -6
  20. package/{scripts → commands}/syncDb/types.ts +5 -5
  21. package/{scripts → commands}/syncDb/version.ts +1 -1
  22. package/commands/syncDb.ts +35 -0
  23. package/commands/syncDev.ts +174 -0
  24. package/commands/syncMenu.ts +368 -0
  25. package/config/env.ts +4 -4
  26. package/config/menu.json +67 -0
  27. package/{utils/crypto.ts → lib/cipher.ts} +16 -67
  28. package/lib/database.ts +296 -0
  29. package/{utils → lib}/dbHelper.ts +102 -56
  30. package/{utils → lib}/jwt.ts +124 -151
  31. package/{utils → lib}/logger.ts +47 -24
  32. package/lib/middleware.ts +271 -0
  33. package/{utils → lib}/redisHelper.ts +4 -4
  34. package/{utils/validate.ts → lib/validator.ts} +101 -78
  35. package/lifecycle/bootstrap.ts +63 -0
  36. package/lifecycle/checker.ts +165 -0
  37. package/lifecycle/cluster.ts +241 -0
  38. package/lifecycle/lifecycle.ts +139 -0
  39. package/lifecycle/loader.ts +513 -0
  40. package/main.ts +14 -12
  41. package/package.json +21 -9
  42. package/paths.ts +34 -0
  43. package/plugins/cache.ts +187 -0
  44. package/plugins/db.ts +4 -4
  45. package/plugins/logger.ts +1 -1
  46. package/plugins/redis.ts +4 -4
  47. package/router/api.ts +155 -0
  48. package/router/root.ts +53 -0
  49. package/router/static.ts +76 -0
  50. package/types/api.d.ts +0 -36
  51. package/types/befly.d.ts +8 -6
  52. package/types/common.d.ts +1 -1
  53. package/types/context.d.ts +3 -3
  54. package/types/util.d.ts +45 -0
  55. package/util.ts +301 -0
  56. package/config/fields.ts +0 -55
  57. package/config/regexAliases.ts +0 -51
  58. package/config/reserved.ts +0 -96
  59. package/scripts/syncDb/tests/constants.test.ts +0 -105
  60. package/scripts/syncDb/tests/ddl.test.ts +0 -134
  61. package/scripts/syncDb/tests/helpers.test.ts +0 -70
  62. package/scripts/syncDb.ts +0 -10
  63. package/types/index.d.ts +0 -450
  64. package/types/index.ts +0 -438
  65. package/types/validator.ts +0 -43
  66. package/utils/colors.ts +0 -221
  67. package/utils/database.ts +0 -348
  68. package/utils/helper.ts +0 -812
  69. package/utils/index.ts +0 -33
  70. package/utils/requestContext.ts +0 -167
  71. /package/{scripts → commands}/syncDb/schema.ts +0 -0
  72. /package/{utils → lib}/sqlBuilder.ts +0 -0
  73. /package/{utils → lib}/xml.ts +0 -0
@@ -0,0 +1,187 @@
1
+ /**
2
+ * 缓存插件 - TypeScript 版本
3
+ * 负责在服务器启动时缓存接口、菜单和角色权限到 Redis
4
+ */
5
+
6
+ import { Logger } from '../lib/logger.js';
7
+ import type { Plugin } from '../types/plugin.js';
8
+ import type { BeflyContext } from '../types/befly.js';
9
+ import type { ApiRoute } from '../types/api.js';
10
+
11
+ /**
12
+ * 缓存管理器类
13
+ */
14
+ class CacheManager {
15
+ private appContext: BeflyContext;
16
+
17
+ constructor(appContext: BeflyContext) {
18
+ this.appContext = appContext;
19
+ }
20
+
21
+ /**
22
+ * 缓存所有接口到 Redis
23
+ */
24
+ async cacheApis(): Promise<void> {
25
+ try {
26
+ // 检查表是否存在
27
+ const tableExists = await this.appContext.db.tableExists('core_api');
28
+ if (!tableExists) {
29
+ Logger.warn('⚠️ 接口表不存在,跳过接口缓存');
30
+ return;
31
+ }
32
+
33
+ // 从数据库查询所有接口(与 apiAll.ts 保持一致)
34
+ const apiList = await this.appContext.db.getAll({
35
+ table: 'core_api',
36
+ fields: ['id', 'name', 'path', 'method', 'description', 'addonName', 'addonTitle'],
37
+ orderBy: ['addonName#ASC', 'path#ASC']
38
+ });
39
+
40
+ // 缓存到 Redis
41
+ const result = await this.appContext.redis.setObject('apis:all', apiList);
42
+
43
+ if (result === null) {
44
+ Logger.warn('⚠️ 接口缓存失败');
45
+ } else {
46
+ Logger.info(`✅ 已缓存 ${apiList.length} 个接口到 Redis (Key: apis:all)`);
47
+ }
48
+ } catch (error: any) {
49
+ Logger.error('⚠️ 接口缓存异常:', error);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * 缓存所有菜单到 Redis(从数据库读取)
55
+ */
56
+ async cacheMenus(): Promise<void> {
57
+ try {
58
+ // 检查表是否存在
59
+ const tableExists = await this.appContext.db.tableExists('core_menu');
60
+ if (!tableExists) {
61
+ Logger.warn('⚠️ 菜单表不存在,跳过菜单缓存');
62
+ return;
63
+ }
64
+
65
+ // 从数据库查询所有菜单
66
+ const menus = await this.appContext.db.getAll({
67
+ table: 'core_menu',
68
+ fields: ['id', 'pid', 'name', 'path', 'icon', 'type', 'sort'],
69
+ orderBy: ['sort#ASC', 'id#ASC']
70
+ });
71
+
72
+ // 缓存到 Redis
73
+ const result = await this.appContext.redis.setObject('menus:all', menus);
74
+
75
+ if (result === null) {
76
+ Logger.warn('⚠️ 菜单缓存失败');
77
+ } else {
78
+ Logger.info(`✅ 已缓存 ${menus.length} 个菜单到 Redis (Key: menus:all)`);
79
+ }
80
+ } catch (error: any) {
81
+ const errorMessage = error?.message || error?.toString?.() || String(error);
82
+ Logger.warn('⚠️ 菜单缓存异常:', errorMessage);
83
+ }
84
+ }
85
+
86
+ /**
87
+ * 缓存所有角色的接口权限到 Redis
88
+ */
89
+ async cacheRolePermissions(): Promise<void> {
90
+ try {
91
+ // 检查表是否存在
92
+ const apiTableExists = await this.appContext.db.tableExists('core_api');
93
+ const roleTableExists = await this.appContext.db.tableExists('core_role');
94
+
95
+ if (!apiTableExists || !roleTableExists) {
96
+ Logger.warn('⚠️ 接口或角色表不存在,跳过角色权限缓存');
97
+ return;
98
+ }
99
+
100
+ // 查询所有角色
101
+ const roles = await this.appContext.db.getAll({
102
+ table: 'core_role',
103
+ fields: ['id', 'code', 'apis']
104
+ });
105
+
106
+ // 查询所有接口(用于权限映射)
107
+ const allApis = await this.appContext.db.getAll({
108
+ table: 'core_api',
109
+ fields: ['id', 'name', 'path', 'method', 'description', 'addonName']
110
+ });
111
+
112
+ // 为每个角色缓存接口权限
113
+ let cachedRoles = 0;
114
+ for (const role of roles) {
115
+ if (!role.apis) continue;
116
+
117
+ // 解析角色的接口 ID 列表
118
+ const apiIds = role.apis
119
+ .split(',')
120
+ .map((id: string) => parseInt(id.trim()))
121
+ .filter((id: number) => !isNaN(id));
122
+
123
+ // 根据 ID 过滤出接口路径
124
+ const roleApiPaths = allApis.filter((api: any) => apiIds.includes(api.id)).map((api: any) => `${api.method}${api.path}`);
125
+
126
+ if (roleApiPaths.length === 0) continue;
127
+
128
+ // 使用 Redis Set 缓存角色权限(性能优化:SADD + SISMEMBER)
129
+ const redisKey = `role:apis:${role.code}`;
130
+
131
+ // 先删除旧数据
132
+ await this.appContext.redis.del(redisKey);
133
+
134
+ // 批量添加到 Set
135
+ const result = await this.appContext.redis.sadd(redisKey, roleApiPaths);
136
+
137
+ if (result > 0) {
138
+ cachedRoles++;
139
+ Logger.debug(` └ 角色 ${role.code}: ${result} 个接口`);
140
+ }
141
+ }
142
+
143
+ Logger.info(`✅ 已缓存 ${cachedRoles} 个角色的接口权限`);
144
+ } catch (error: any) {
145
+ const errorMessage = error?.message || error?.toString?.() || String(error);
146
+ Logger.warn('⚠️ 角色权限缓存异常:', errorMessage);
147
+ }
148
+ }
149
+
150
+ /**
151
+ * 缓存所有数据
152
+ */
153
+ async cacheAll(): Promise<void> {
154
+ Logger.info('========== 开始缓存数据到 Redis ==========');
155
+
156
+ // 1. 缓存接口
157
+ await this.cacheApis();
158
+
159
+ // 2. 缓存菜单
160
+ await this.cacheMenus();
161
+
162
+ // 3. 缓存角色权限
163
+ await this.cacheRolePermissions();
164
+
165
+ Logger.info('========== 数据缓存完成 ==========\n');
166
+ }
167
+ }
168
+
169
+ /**
170
+ * 缓存插件
171
+ */
172
+ const cachePlugin: Plugin = {
173
+ name: '_cache',
174
+ after: ['_db', '_redis'],
175
+
176
+ async onInit(befly: BeflyContext): Promise<CacheManager> {
177
+ try {
178
+ const cacheManager = new CacheManager(befly);
179
+ Logger.info('缓存插件初始化成功');
180
+ return cacheManager;
181
+ } catch (error: any) {
182
+ throw error;
183
+ }
184
+ }
185
+ };
186
+
187
+ export default cachePlugin;
package/plugins/db.ts CHANGED
@@ -4,9 +4,9 @@
4
4
  */
5
5
 
6
6
  import { Env } from '../config/env.js';
7
- import { Logger } from '../utils/logger.js';
8
- import { createSqlClient } from '../utils/database.js';
9
- import { DbHelper } from '../utils/dbHelper.js';
7
+ import { Logger } from '../lib/logger.js';
8
+ import { Database } from '../lib/database.js';
9
+ import { DbHelper } from '../lib/dbHelper.js';
10
10
  import type { Plugin } from '../types/plugin.js';
11
11
  import type { BeflyContext } from '../types/befly.js';
12
12
 
@@ -26,7 +26,7 @@ const dbPlugin: Plugin = {
26
26
  // 从环境变量读取连接超时配置
27
27
  const connectionTimeout = process.env.DB_CONNECTION_TIMEOUT ? parseInt(process.env.DB_CONNECTION_TIMEOUT) : 5000;
28
28
 
29
- sql = await createSqlClient({
29
+ sql = await Database.connectSql({
30
30
  connectionTimeout
31
31
  });
32
32
 
package/plugins/logger.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * 提供全局日志功能
4
4
  */
5
5
 
6
- import { Logger } from '../utils/logger.js';
6
+ import { Logger } from '../lib/logger.js';
7
7
  import type { Plugin } from '../types/plugin.js';
8
8
  import type { BeflyContext } from '../types/befly.js';
9
9
 
package/plugins/redis.ts CHANGED
@@ -4,9 +4,9 @@
4
4
  */
5
5
 
6
6
  import { Env } from '../config/env.js';
7
- import { Logger } from '../utils/logger.js';
8
- import { RedisHelper } from '../utils/redisHelper.js';
9
- import { initRedisOnly } from '../utils/database.js';
7
+ import { Logger } from '../lib/logger.js';
8
+ import { RedisHelper } from '../lib/redisHelper.js';
9
+ import { Database } from '../lib/database.js';
10
10
  import type { Plugin } from '../types/plugin.js';
11
11
  import type { BeflyContext } from '../types/befly.js';
12
12
 
@@ -21,7 +21,7 @@ const redisPlugin: Plugin = {
21
21
  try {
22
22
  if (Env.REDIS_ENABLE === 1) {
23
23
  // 初始化 Redis 客户端(统一使用 database.ts 的连接管理)
24
- await initRedisOnly();
24
+ await Database.connectRedis();
25
25
 
26
26
  Logger.info('Redis 插件初始化成功', {
27
27
  host: Env.REDIS_HOST,
package/router/api.ts ADDED
@@ -0,0 +1,155 @@
1
+ /**
2
+ * API路由处理器
3
+ * 处理 /api/* 路径的请求
4
+ */
5
+
6
+ import { Logger } from '../lib/logger.js';
7
+ import { No } from '../util.js';
8
+ import { setCorsOptions, handleOptionsRequest, authenticate, parseGetParams, parsePostParams, checkPermission, validateParams, executePluginHooks, logRequest } from '../lib/middleware.js';
9
+ import { Env } from '../config/env.js';
10
+ import type { RequestContext } from '../util.js';
11
+ import type { ApiRoute } from '../types/api.js';
12
+ import type { Plugin } from '../types/plugin.js';
13
+ import type { BeflyContext } from '../types/befly.js';
14
+
15
+ /**
16
+ * API处理器工厂函数
17
+ * @param apiRoutes - API路由映射表
18
+ * @param pluginLists - 插件列表
19
+ * @param appContext - 应用上下文
20
+ */
21
+ export function apiHandler(apiRoutes: Map<string, ApiRoute>, pluginLists: Plugin[], appContext: BeflyContext) {
22
+ return async (req: Request): Promise<Response> => {
23
+ const corsOptions = setCorsOptions(req);
24
+ let ctx: RequestContext | null = null;
25
+ let api: ApiRoute | undefined;
26
+ let apiPath = '';
27
+
28
+ try {
29
+ // 1. OPTIONS预检请求
30
+ if (req.method === 'OPTIONS') {
31
+ return handleOptionsRequest(corsOptions);
32
+ }
33
+
34
+ // 2. 创建请求上下文
35
+ ctx = {
36
+ body: {},
37
+ user: {},
38
+ request: req,
39
+ startTime: Date.now()
40
+ };
41
+
42
+ // 3. 获取API路由
43
+ const url = new URL(req.url);
44
+ apiPath = `${req.method}${url.pathname}`;
45
+ api = apiRoutes.get(apiPath);
46
+
47
+ if (!api) {
48
+ return Response.json(No('接口不存在'), {
49
+ headers: corsOptions.headers
50
+ });
51
+ }
52
+
53
+ // 4. 用户认证
54
+ await authenticate(ctx);
55
+
56
+ // 5. 参数解析
57
+ if (req.method === 'GET') {
58
+ parseGetParams(api, ctx);
59
+ } else if (req.method === 'POST') {
60
+ const parseSuccess = await parsePostParams(api, ctx);
61
+ if (!parseSuccess) {
62
+ return Response.json(No('无效的请求参数格式'), {
63
+ headers: corsOptions.headers
64
+ });
65
+ }
66
+ }
67
+
68
+ // 6. 执行插件钩子
69
+ await executePluginHooks(pluginLists, appContext, ctx);
70
+
71
+ // 7. 记录请求日志
72
+ logRequest(apiPath, ctx);
73
+
74
+ // 8. 权限验证(使用 Redis Set SISMEMBER 直接判断,提升性能)
75
+ let hasPermission = false;
76
+ if (api.auth === true && ctx.user?.roleCode && ctx.user.roleCode !== 'dev') {
77
+ // 使用 Redis SISMEMBER 直接判断接口是否在角色权限集合中(O(1)复杂度)
78
+ const roleApisKey = `role:apis:${ctx.user.roleCode}`;
79
+ const isMember = await appContext.redis.sismember(roleApisKey, apiPath);
80
+ hasPermission = isMember === 1;
81
+ }
82
+
83
+ const permissionResult = checkPermission(api, ctx, hasPermission);
84
+ if (permissionResult.code !== 0) {
85
+ return Response.json(permissionResult, {
86
+ headers: corsOptions.headers
87
+ });
88
+ }
89
+
90
+ // 9. 参数验证
91
+ const validateResult = validateParams(api, ctx);
92
+ if (validateResult.code !== 0) {
93
+ return Response.json(No('无效的请求参数格式', validateResult.fields), {
94
+ headers: corsOptions.headers
95
+ });
96
+ }
97
+
98
+ // 10. 执行API处理器
99
+ const result = await api.handler(appContext, ctx, req);
100
+
101
+ // 11. 返回响应
102
+ if (result && typeof result === 'object' && 'code' in result) {
103
+ // 处理 BigInt 序列化问题
104
+ const jsonString = JSON.stringify(result, (key, value) => (typeof value === 'bigint' ? value.toString() : value));
105
+ return new Response(jsonString, {
106
+ headers: {
107
+ ...corsOptions.headers,
108
+ 'Content-Type': 'application/json'
109
+ }
110
+ });
111
+ } else {
112
+ return new Response(result, {
113
+ headers: corsOptions.headers
114
+ });
115
+ }
116
+ } catch (error: any) {
117
+ // 记录详细的错误日志
118
+ Logger.warn(api ? `接口 [${api.name}] 执行失败` : '处理接口请求时发生错误', error);
119
+
120
+ // 根据错误类型返回不同的错误信息
121
+ let errorMessage = '内部服务器错误';
122
+ let errorDetail = {};
123
+
124
+ // 数据库错误
125
+ if (error.message?.includes('ECONNREFUSED') || error.message?.includes('database')) {
126
+ errorMessage = '数据库连接失败';
127
+ }
128
+ // Redis错误
129
+ else if (error.message?.includes('Redis') || error.message?.includes('redis')) {
130
+ errorMessage = 'Redis服务异常';
131
+ }
132
+ // 权限错误
133
+ else if (error.message?.includes('permission') || error.message?.includes('权限')) {
134
+ errorMessage = '权限不足';
135
+ }
136
+ // 认证错误
137
+ else if (error.message?.includes('token') || error.message?.includes('认证')) {
138
+ errorMessage = '认证失败';
139
+ }
140
+
141
+ // 开发环境返回详细错误信息
142
+ if (Env.NODE_ENV === 'development') {
143
+ errorDetail = {
144
+ type: error.constructor?.name || 'Error',
145
+ message: error.message,
146
+ stack: error.stack
147
+ };
148
+ }
149
+
150
+ return Response.json(No(errorMessage, errorDetail), {
151
+ headers: corsOptions.headers
152
+ });
153
+ }
154
+ };
155
+ }
package/router/root.ts ADDED
@@ -0,0 +1,53 @@
1
+ /**
2
+ * 根路径路由处理器
3
+ * 处理 / 路径的请求
4
+ */
5
+
6
+ import { Env } from '../config/env.js';
7
+ import { setCorsOptions } from '../lib/middleware.js';
8
+ import { Logger } from '../lib/logger.js';
9
+ import { No } from '../util.js';
10
+
11
+ /**
12
+ * 根路径处理器
13
+ */
14
+ export async function rootHandler(req: Request): Promise<Response> {
15
+ const corsOptions = setCorsOptions(req);
16
+
17
+ try {
18
+ return Response.json(
19
+ {
20
+ code: 0,
21
+ msg: 'Befly 接口服务已启动',
22
+ data: {
23
+ mode: Env.NODE_ENV,
24
+ timestamp: Date.now()
25
+ }
26
+ },
27
+ {
28
+ headers: corsOptions.headers
29
+ }
30
+ );
31
+ } catch (error: any) {
32
+ // 记录详细的错误日志
33
+ Logger.error('根路径处理失败', error);
34
+
35
+ // 根据错误类型返回不同的错误信息
36
+ let errorMessage = '服务异常';
37
+ let errorDetail = {};
38
+
39
+ // 开发环境返回详细错误信息
40
+ if (Env.NODE_ENV === 'development') {
41
+ errorDetail = {
42
+ type: error.constructor?.name || 'Error',
43
+ message: error.message,
44
+ stack: error.stack
45
+ };
46
+ }
47
+
48
+ return Response.json(No(errorMessage, errorDetail), {
49
+ status: 500,
50
+ headers: corsOptions.headers
51
+ });
52
+ }
53
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * 静态文件路由处理器
3
+ * 处理 /* 路径的静态文件请求
4
+ */
5
+
6
+ import { join } from 'pathe';
7
+ import { paths } from '../paths.js';
8
+ import { No } from '../util.js';
9
+ import { setCorsOptions } from '../lib/middleware.js';
10
+ import { Logger } from '../lib/logger.js';
11
+ import { Env } from '../config/env.js';
12
+
13
+ /**
14
+ * 静态文件处理器
15
+ */
16
+ export async function staticHandler(req: Request): Promise<Response> {
17
+ const corsOptions = setCorsOptions(req);
18
+ const url = new URL(req.url);
19
+ const filePath = join(paths.projectDir, 'public', url.pathname);
20
+
21
+ try {
22
+ // OPTIONS预检请求
23
+ if (req.method === 'OPTIONS') {
24
+ return new Response(null, {
25
+ status: 204,
26
+ headers: corsOptions.headers
27
+ });
28
+ }
29
+
30
+ const file = Bun.file(filePath);
31
+ if (await file.exists()) {
32
+ return new Response(file, {
33
+ headers: {
34
+ 'Content-Type': file.type || 'application/octet-stream',
35
+ ...corsOptions.headers
36
+ }
37
+ });
38
+ } else {
39
+ return Response.json(No('文件未找到'), {
40
+ status: 404,
41
+ headers: corsOptions.headers
42
+ });
43
+ }
44
+ } catch (error: any) {
45
+ // 记录详细的错误日志
46
+ Logger.error('静态文件处理失败', error);
47
+
48
+ // 根据错误类型返回不同的错误信息
49
+ let errorMessage = '文件读取失败';
50
+ let errorDetail = {};
51
+
52
+ // 权限错误
53
+ if (error.message?.includes('EACCES') || error.message?.includes('permission')) {
54
+ errorMessage = '文件访问权限不足';
55
+ }
56
+ // 路径错误
57
+ else if (error.message?.includes('ENOENT') || error.message?.includes('not found')) {
58
+ errorMessage = '文件路径不存在';
59
+ }
60
+
61
+ // 开发环境返回详细错误信息
62
+ if (Env.NODE_ENV === 'development') {
63
+ errorDetail = {
64
+ type: error.constructor?.name || 'Error',
65
+ message: error.message,
66
+ stack: error.stack,
67
+ filePath: filePath
68
+ };
69
+ }
70
+
71
+ return Response.json(No(errorMessage, errorDetail), {
72
+ status: 500,
73
+ headers: corsOptions.headers
74
+ });
75
+ }
76
+ }
package/types/api.d.ts CHANGED
@@ -11,42 +11,6 @@ import type { RequestContext } from './context.js';
11
11
  */
12
12
  export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
13
13
 
14
- /**
15
- * 请求上下文类型(已废弃,使用 RequestContext 类)
16
- * @deprecated 使用 RequestContext 类替代
17
- */
18
- export interface RequestContext<T = any> {
19
- /** 请求对象 */
20
- request: Request;
21
-
22
- /** 请求体参数 */
23
- body: T;
24
-
25
- /** URL 参数 */
26
- query: KeyValue<string>;
27
-
28
- /** 路径参数 */
29
- pathParams: KeyValue<string>;
30
-
31
- /** 请求头 */
32
- headers: Headers;
33
-
34
- /** 用户信息(认证后) */
35
- user?: UserInfo;
36
-
37
- /** 客户端 IP */
38
- ip?: string;
39
-
40
- /** User-Agent */
41
- userAgent?: string;
42
-
43
- /** 请求 ID */
44
- requestId?: string;
45
-
46
- /** 开始时间 */
47
- startTime: number;
48
- }
49
-
50
14
  /**
51
15
  * 用户信息类型
52
16
  */
package/types/befly.d.ts CHANGED
@@ -5,11 +5,13 @@
5
5
  import type { Plugin } from './plugin.js';
6
6
  import type { ApiRoute, HttpMethod } from './api.js';
7
7
  import type { KeyValue } from './common.js';
8
- import type { Logger } from '../utils/logger.js';
9
- import type { Jwt } from '../utils/jwt.js';
10
- import type { Validator } from '../utils/validate.js';
11
- import type { DbHelper } from '../utils/dbHelper.js';
12
- import type { Crypto2 } from '../utils/crypto.js';
8
+ import type { Logger } from '../lib/logger.js';
9
+ import type { Jwt } from '../lib/jwt.js';
10
+ import type { Validator } from '../lib/validator.js';
11
+ import type { Database } from 'bun:sqlite';
12
+ import type { DbHelper } from '../lib/dbHelper.js';
13
+ import type { RedisHelper } from '../lib/redisHelper.js';
14
+ import type { Cipher } from '../lib/cipher.js';
13
15
 
14
16
  /**
15
17
  * Befly 应用选项
@@ -81,7 +83,7 @@ export interface Befly {
81
83
  sql: DbHelper;
82
84
 
83
85
  /** 加密工具 */
84
- crypto: Crypto2;
86
+ crypto: Cipher;
85
87
 
86
88
  /** 数据库连接 */
87
89
  db: any;
package/types/common.d.ts CHANGED
@@ -40,7 +40,7 @@ export type TableDefinition = Record<string, FieldRule>;
40
40
  */
41
41
  export interface ParsedFieldRule {
42
42
  name: string; // 字段名称
43
- type: 'string' | 'number' | 'text' | 'array';
43
+ type: 'string' | 'number' | 'text' | 'array_string' | 'array_text';
44
44
  min: number | null; // 最小值
45
45
  max: number | null; // 最大值
46
46
  default: any; // 默认值
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 请求上下文类型定义
3
- * 实现代码位于 utils/requestContext.ts
3
+ * 实现代码位于 util.ts,类型定义位于 types/util.d.ts
4
4
  */
5
5
 
6
- // 重新导出 RequestContext
7
- export { RequestContext } from '../utils/requestContext.js';
6
+ // 重新导出 RequestContext 接口
7
+ export type { RequestContext } from './util.js';
@@ -0,0 +1,45 @@
1
+ /**
2
+ * util.ts 相关类型定义
3
+ */
4
+
5
+ import type { RedisClient } from 'bun';
6
+ import type { DbHelper } from '../lib/dbHelper.js';
7
+
8
+ /**
9
+ * 数据清洗选项
10
+ */
11
+ export interface DataCleanOptions {
12
+ /** 排除的字段名 */
13
+ excludeKeys?: string[];
14
+ /** 包含的字段名(优先级高于 excludeKeys) */
15
+ includeKeys?: string[];
16
+ /** 要移除的值 */
17
+ removeValues?: any[];
18
+ /** 字符串最大长度(超出截断) */
19
+ maxLen?: number;
20
+ /** 是否深度处理嵌套对象 */
21
+ deep?: boolean;
22
+ }
23
+
24
+ /**
25
+ * 数据库连接集合(内部使用)
26
+ */
27
+ export interface DatabaseConnections {
28
+ redis: RedisClient | null;
29
+ sql: any;
30
+ helper: DbHelper | null;
31
+ }
32
+
33
+ /**
34
+ * 请求上下文接口
35
+ */
36
+ export interface RequestContext {
37
+ /** 请求体参数 */
38
+ body: Record<string, any>;
39
+ /** 用户信息 */
40
+ user: Record<string, any>;
41
+ /** 原始请求对象 */
42
+ request: Request;
43
+ /** 请求开始时间(毫秒) */
44
+ startTime: number;
45
+ }