befly 3.8.29 → 3.8.31

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 (70) hide show
  1. package/README.md +91 -6
  2. package/checks/checkApi.ts +2 -1
  3. package/checks/checkApp.ts +31 -1
  4. package/checks/checkTable.ts +3 -2
  5. package/hooks/cors.ts +3 -3
  6. package/hooks/parser.ts +8 -6
  7. package/hooks/permission.ts +12 -5
  8. package/hooks/validator.ts +1 -1
  9. package/lib/cacheHelper.ts +73 -65
  10. package/lib/cipher.ts +2 -1
  11. package/lib/connect.ts +23 -52
  12. package/lib/dbHelper.ts +14 -11
  13. package/lib/jwt.ts +58 -437
  14. package/lib/logger.ts +76 -197
  15. package/lib/redisHelper.ts +163 -1
  16. package/lib/sqlBuilder.ts +2 -1
  17. package/lib/validator.ts +150 -384
  18. package/loader/loadApis.ts +4 -7
  19. package/loader/loadHooks.ts +6 -5
  20. package/loader/loadPlugins.ts +11 -13
  21. package/main.ts +26 -53
  22. package/package.json +10 -8
  23. package/paths.ts +0 -6
  24. package/plugins/cipher.ts +1 -1
  25. package/plugins/config.ts +3 -4
  26. package/plugins/db.ts +6 -7
  27. package/plugins/jwt.ts +7 -6
  28. package/plugins/logger.ts +6 -6
  29. package/plugins/redis.ts +9 -13
  30. package/router/api.ts +2 -2
  31. package/router/static.ts +4 -8
  32. package/sync/syncAll.ts +8 -13
  33. package/sync/syncApi.ts +14 -10
  34. package/sync/syncDb/apply.ts +1 -2
  35. package/sync/syncDb.ts +12 -15
  36. package/sync/syncDev.ts +19 -56
  37. package/sync/syncMenu.ts +182 -137
  38. package/tests/cacheHelper.test.ts +327 -0
  39. package/tests/dbHelper-columns.test.ts +5 -20
  40. package/tests/dbHelper-execute.test.ts +14 -68
  41. package/tests/fields-redis-cache.test.ts +5 -3
  42. package/tests/integration.test.ts +17 -32
  43. package/tests/jwt.test.ts +36 -94
  44. package/tests/logger.test.ts +32 -34
  45. package/tests/redisHelper.test.ts +271 -2
  46. package/tests/redisKeys.test.ts +76 -0
  47. package/tests/sync-connection.test.ts +0 -6
  48. package/tests/syncDb-constants.test.ts +12 -12
  49. package/tests/util.test.ts +5 -1
  50. package/tests/validator.test.ts +611 -85
  51. package/types/befly.d.ts +9 -15
  52. package/types/cache.d.ts +73 -0
  53. package/types/common.d.ts +10 -128
  54. package/types/database.d.ts +221 -5
  55. package/types/index.ts +6 -5
  56. package/types/plugin.d.ts +1 -4
  57. package/types/redis.d.ts +37 -2
  58. package/types/table.d.ts +175 -0
  59. package/config.ts +0 -70
  60. package/hooks/_rateLimit.ts +0 -64
  61. package/lib/regexAliases.ts +0 -59
  62. package/lib/xml.ts +0 -383
  63. package/tests/validator-advanced.test.ts +0 -653
  64. package/tests/xml.test.ts +0 -101
  65. package/types/addon.d.ts +0 -50
  66. package/types/crypto.d.ts +0 -23
  67. package/types/jwt.d.ts +0 -99
  68. package/types/logger.d.ts +0 -43
  69. package/types/tool.d.ts +0 -67
  70. package/types/validator.d.ts +0 -43
package/lib/connect.ts CHANGED
@@ -1,23 +1,22 @@
1
1
  /**
2
2
  * 数据库连接管理器
3
3
  * 统一管理 SQL 和 Redis 连接
4
+ * 配置从 beflyConfig 全局对象获取
4
5
  */
5
6
 
6
7
  import { SQL, RedisClient } from 'bun';
8
+
9
+ import { beflyConfig } from '../befly.config.js';
7
10
  import { Logger } from './logger.js';
8
- import { DbHelper } from './dbHelper.js';
9
- import { RedisHelper } from './redisHelper.js';
10
- import type { BeflyContext, BeflyOptions, DatabaseConfig, RedisConfig } from '../types/befly.js';
11
- import type { SqlClientOptions } from '../types/database.js';
12
11
 
13
12
  /**
14
13
  * 数据库连接管理器
15
14
  * 使用静态方法管理全局单例连接
15
+ * 所有配置从 beflyConfig 自动获取
16
16
  */
17
17
  export class Connect {
18
18
  private static sqlClient: SQL | null = null;
19
19
  private static redisClient: RedisClient | null = null;
20
- private static dbHelper: DbHelper | null = null;
21
20
 
22
21
  // 连接统计信息
23
22
  private static sqlConnectedAt: number | null = null;
@@ -30,10 +29,12 @@ export class Connect {
30
29
 
31
30
  /**
32
31
  * 连接 SQL 数据库
33
- * @param config - 数据库配置
32
+ * 配置从 beflyConfig.db 获取
34
33
  * @returns SQL 客户端实例
35
34
  */
36
- static async connectSql(config: DatabaseConfig): Promise<SQL> {
35
+ static async connectSql(): Promise<SQL> {
36
+ const config = beflyConfig.db || {};
37
+
37
38
  // 构建数据库连接字符串
38
39
  const type = config.type || 'mysql';
39
40
  const host = config.host || '127.0.0.1';
@@ -95,7 +96,7 @@ export class Connect {
95
96
  this.sqlPoolMax = config.poolMax ?? 1;
96
97
  return sql;
97
98
  } catch (error: any) {
98
- Logger.error('[Connect] SQL 连接失败', error);
99
+ Logger.error({ err: error }, '[Connect] SQL 连接失败');
99
100
  try {
100
101
  await sql?.close();
101
102
  } catch (cleanupError) {}
@@ -112,15 +113,11 @@ export class Connect {
112
113
  try {
113
114
  await this.sqlClient.close();
114
115
  } catch (error: any) {
115
- Logger.error('[Connect] 关闭 SQL 连接时出错', error);
116
+ Logger.error({ err: error }, '[Connect] 关闭 SQL 连接时出错');
116
117
  }
117
118
  this.sqlClient = null;
118
119
  this.sqlConnectedAt = null;
119
120
  }
120
-
121
- if (this.dbHelper) {
122
- this.dbHelper = null;
123
- }
124
121
  }
125
122
 
126
123
  /**
@@ -134,37 +131,18 @@ export class Connect {
134
131
  return this.sqlClient;
135
132
  }
136
133
 
137
- /**
138
- * 获取 DbHelper 实例
139
- * @throws 如果未连接则抛出错误
140
- */
141
- static getDbHelper(befly?: BeflyContext): DbHelper {
142
- if (!this.dbHelper) {
143
- if (!this.sqlClient) {
144
- throw new Error('SQL 客户端未连接,请先调用 Connect.connectSql()');
145
- }
146
- // 创建临时 befly 上下文(仅用于 DbHelper)
147
- const ctx = befly || {
148
- redis: new RedisHelper(),
149
- db: null as any,
150
- tool: null as any,
151
- logger: null as any
152
- };
153
- this.dbHelper = new DbHelper(ctx, this.sqlClient);
154
- }
155
- return this.dbHelper;
156
- }
157
-
158
134
  // ========================================
159
135
  // Redis 连接管理
160
136
  // ========================================
161
137
 
162
138
  /**
163
139
  * 连接 Redis
164
- * @param config - Redis 配置
140
+ * 配置从 beflyConfig.redis 获取
165
141
  * @returns Redis 客户端实例
166
142
  */
167
- static async connectRedis(config: RedisConfig = {}): Promise<RedisClient> {
143
+ static async connectRedis(): Promise<RedisClient> {
144
+ const config = beflyConfig.redis || {};
145
+
168
146
  try {
169
147
  // 构建 Redis URL
170
148
  const host = config.host || '127.0.0.1';
@@ -197,7 +175,7 @@ export class Connect {
197
175
  this.redisConnectedAt = Date.now();
198
176
  return redis;
199
177
  } catch (error: any) {
200
- Logger.error('[Connect] Redis 连接失败', error);
178
+ Logger.error({ err: error }, '[Connect] Redis 连接失败');
201
179
  throw new Error(`Redis 连接失败: ${error.message}`);
202
180
  }
203
181
  }
@@ -211,7 +189,7 @@ export class Connect {
211
189
  this.redisClient.close();
212
190
  this.redisConnectedAt = null;
213
191
  } catch (error: any) {
214
- Logger.error('[Connect] 关闭 Redis 连接时出错', error);
192
+ Logger.error({ err: error }, '[Connect] 关闭 Redis 连接时出错');
215
193
  }
216
194
  this.redisClient = null;
217
195
  }
@@ -234,23 +212,17 @@ export class Connect {
234
212
 
235
213
  /**
236
214
  * 连接所有数据库(SQL + Redis)
237
- * @param config - Befly 配置对象(可选)
238
- * @param options - 连接选项
215
+ * 配置从 beflyConfig 自动获取
239
216
  */
240
- static async connect(config?: BeflyOptions, options?: { sql?: SqlClientOptions; redis?: boolean }): Promise<void> {
217
+ static async connect(): Promise<void> {
241
218
  try {
242
- // 如果 sql 参数不是 false,则连接 SQL
243
- // 优先级:options.sql > config.db > 跳过
244
- const sqlConfig = options?.db || {};
245
- if (sqlConfig) {
246
- await this.connectSql(sqlConfig);
247
- }
219
+ // 连接 SQL
220
+ await this.connectSql();
248
221
 
249
- // 如果 redis 参数不是 false,则连接 Redis
250
- const redisConfig = config?.redis || {};
251
- await this.connectRedis(redisConfig);
222
+ // 连接 Redis
223
+ await this.connectRedis();
252
224
  } catch (error: any) {
253
- Logger.error('数据库初始化失败', error);
225
+ Logger.error({ err: error }, '数据库初始化失败');
254
226
  await this.disconnect();
255
227
  throw error;
256
228
  }
@@ -330,7 +302,6 @@ export class Connect {
330
302
  static __reset(): void {
331
303
  this.sqlClient = null;
332
304
  this.redisClient = null;
333
- this.dbHelper = null;
334
305
  this.sqlConnectedAt = null;
335
306
  this.redisConnectedAt = null;
336
307
  this.sqlPoolMax = 1;
package/lib/dbHelper.ts CHANGED
@@ -5,8 +5,12 @@
5
5
 
6
6
  import { snakeCase } from 'es-toolkit/string';
7
7
  import { SqlBuilder } from './sqlBuilder.js';
8
- import { keysToCamel, arrayKeysToCamel, keysToSnake, fieldClear } from 'befly-util';
9
- import { Logger } from '../lib/logger.js';
8
+ import { keysToCamel } from 'befly-shared/keysToCamel';
9
+ import { arrayKeysToCamel } from 'befly-shared/arrayKeysToCamel';
10
+ import { keysToSnake } from 'befly-shared/keysToSnake';
11
+ import { fieldClear } from 'befly-shared/fieldClear';
12
+ import { RedisTTL, RedisKeys } from 'befly-shared/redisKeys';
13
+ import { Logger } from './logger.js';
10
14
  import type { WhereConditions } from '../types/common.js';
11
15
  import type { BeflyContext } from '../types/befly.js';
12
16
  import type { QueryOptions, InsertOptions, UpdateOptions, DeleteOptions, ListResult, TransactionCallback } from '../types/database.js';
@@ -81,7 +85,7 @@ export class DbHelper {
81
85
  */
82
86
  private async getTableColumns(table: string): Promise<string[]> {
83
87
  // 1. 先查 Redis 缓存
84
- const cacheKey = `table:columns:${table}`;
88
+ const cacheKey = RedisKeys.tableColumns(table);
85
89
  let columns = await this.befly.redis.getObject<string[]>(cacheKey);
86
90
 
87
91
  if (columns && columns.length > 0) {
@@ -98,8 +102,8 @@ export class DbHelper {
98
102
 
99
103
  columns = result.map((row: any) => row.Field);
100
104
 
101
- // 3. 写入 Redis 缓存(1小时过期)
102
- await this.befly.redis.setObject(cacheKey, columns, 3600);
105
+ // 3. 写入 Redis 缓存
106
+ await this.befly.redis.setObject(cacheKey, columns, RedisTTL.tableColumns);
103
107
 
104
108
  return columns;
105
109
  }
@@ -507,12 +511,12 @@ export class DbHelper {
507
511
 
508
512
  // 警告日志:返回数据超过警告阈值
509
513
  if (result.length >= WARNING_LIMIT) {
510
- Logger.warn(`⚠️ getAll 从表 \`${options.table}\` 返回了 ${result.length} 行数据,建议使用 getList 分页查询以获得更好的性能。`);
514
+ Logger.warn({ table: options.table, count: result.length }, 'getAll 返回数据过多,建议使用 getList 分页查询');
511
515
  }
512
516
 
513
517
  // 如果达到上限,额外警告
514
518
  if (result.length >= MAX_LIMIT) {
515
- Logger.warn(`🚨 getAll 达到了最大限制 (${MAX_LIMIT}),可能还有更多数据。请使用 getList 分页查询。`);
519
+ Logger.warn({ table: options.table, limit: MAX_LIMIT }, 'getAll 达到最大限制,可能还有更多数据');
516
520
  }
517
521
 
518
522
  // 字段名转换:下划线 → 小驼峰
@@ -625,8 +629,7 @@ export class DbHelper {
625
629
  await this.executeWithConn(sql, params);
626
630
  return ids;
627
631
  } catch (error: any) {
628
- // 批量插入失败,记录错误
629
- Logger.error(`表 \`${table}\` 批量插入失败`, error);
632
+ Logger.error({ err: error, table: table }, '批量插入失败');
630
633
  throw error;
631
634
  }
632
635
  }
@@ -759,7 +762,7 @@ export class DbHelper {
759
762
  await conn.query('COMMIT');
760
763
  committed = true;
761
764
  } catch (commitError: any) {
762
- Logger.error('事务提交失败,正在回滚', commitError);
765
+ Logger.error({ err: commitError }, '事务提交失败,正在回滚');
763
766
  await conn.query('ROLLBACK');
764
767
  throw new Error(`事务提交失败: ${commitError.message}`);
765
768
  }
@@ -772,7 +775,7 @@ export class DbHelper {
772
775
  await conn.query('ROLLBACK');
773
776
  Logger.warn('事务已回滚');
774
777
  } catch (rollbackError: any) {
775
- Logger.error('事务回滚失败', rollbackError);
778
+ Logger.error({ err: rollbackError }, '事务回滚失败');
776
779
  }
777
780
  }
778
781
  throw error;