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.
- package/README.md +91 -6
- package/checks/checkApi.ts +2 -1
- package/checks/checkApp.ts +31 -1
- package/checks/checkTable.ts +3 -2
- package/hooks/cors.ts +3 -3
- package/hooks/parser.ts +8 -6
- package/hooks/permission.ts +12 -5
- package/hooks/validator.ts +1 -1
- package/lib/cacheHelper.ts +73 -65
- package/lib/cipher.ts +2 -1
- package/lib/connect.ts +23 -52
- package/lib/dbHelper.ts +14 -11
- package/lib/jwt.ts +58 -437
- package/lib/logger.ts +76 -197
- package/lib/redisHelper.ts +163 -1
- package/lib/sqlBuilder.ts +2 -1
- package/lib/validator.ts +150 -384
- package/loader/loadApis.ts +4 -7
- package/loader/loadHooks.ts +6 -5
- package/loader/loadPlugins.ts +11 -13
- package/main.ts +26 -53
- package/package.json +10 -8
- package/paths.ts +0 -6
- package/plugins/cipher.ts +1 -1
- package/plugins/config.ts +3 -4
- package/plugins/db.ts +6 -7
- package/plugins/jwt.ts +7 -6
- package/plugins/logger.ts +6 -6
- package/plugins/redis.ts +9 -13
- package/router/api.ts +2 -2
- package/router/static.ts +4 -8
- package/sync/syncAll.ts +8 -13
- package/sync/syncApi.ts +14 -10
- package/sync/syncDb/apply.ts +1 -2
- package/sync/syncDb.ts +12 -15
- package/sync/syncDev.ts +19 -56
- package/sync/syncMenu.ts +182 -137
- package/tests/cacheHelper.test.ts +327 -0
- package/tests/dbHelper-columns.test.ts +5 -20
- package/tests/dbHelper-execute.test.ts +14 -68
- package/tests/fields-redis-cache.test.ts +5 -3
- package/tests/integration.test.ts +17 -32
- package/tests/jwt.test.ts +36 -94
- package/tests/logger.test.ts +32 -34
- package/tests/redisHelper.test.ts +271 -2
- package/tests/redisKeys.test.ts +76 -0
- package/tests/sync-connection.test.ts +0 -6
- package/tests/syncDb-constants.test.ts +12 -12
- package/tests/util.test.ts +5 -1
- package/tests/validator.test.ts +611 -85
- package/types/befly.d.ts +9 -15
- package/types/cache.d.ts +73 -0
- package/types/common.d.ts +10 -128
- package/types/database.d.ts +221 -5
- package/types/index.ts +6 -5
- package/types/plugin.d.ts +1 -4
- package/types/redis.d.ts +37 -2
- package/types/table.d.ts +175 -0
- package/config.ts +0 -70
- package/hooks/_rateLimit.ts +0 -64
- package/lib/regexAliases.ts +0 -59
- package/lib/xml.ts +0 -383
- package/tests/validator-advanced.test.ts +0 -653
- package/tests/xml.test.ts +0 -101
- package/types/addon.d.ts +0 -50
- package/types/crypto.d.ts +0 -23
- package/types/jwt.d.ts +0 -99
- package/types/logger.d.ts +0 -43
- package/types/tool.d.ts +0 -67
- 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
|
-
*
|
|
32
|
+
* 配置从 beflyConfig.db 获取
|
|
34
33
|
* @returns SQL 客户端实例
|
|
35
34
|
*/
|
|
36
|
-
static async connectSql(
|
|
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 连接失败'
|
|
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 连接时出错'
|
|
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
|
-
*
|
|
140
|
+
* 配置从 beflyConfig.redis 获取
|
|
165
141
|
* @returns Redis 客户端实例
|
|
166
142
|
*/
|
|
167
|
-
static async connectRedis(
|
|
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 连接失败'
|
|
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 连接时出错'
|
|
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
|
-
*
|
|
238
|
-
* @param options - 连接选项
|
|
215
|
+
* 配置从 beflyConfig 自动获取
|
|
239
216
|
*/
|
|
240
|
-
static async connect(
|
|
217
|
+
static async connect(): Promise<void> {
|
|
241
218
|
try {
|
|
242
|
-
//
|
|
243
|
-
|
|
244
|
-
const sqlConfig = options?.db || {};
|
|
245
|
-
if (sqlConfig) {
|
|
246
|
-
await this.connectSql(sqlConfig);
|
|
247
|
-
}
|
|
219
|
+
// 连接 SQL
|
|
220
|
+
await this.connectSql();
|
|
248
221
|
|
|
249
|
-
//
|
|
250
|
-
|
|
251
|
-
await this.connectRedis(redisConfig);
|
|
222
|
+
// 连接 Redis
|
|
223
|
+
await this.connectRedis();
|
|
252
224
|
} catch (error: any) {
|
|
253
|
-
Logger.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
|
|
9
|
-
import {
|
|
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 =
|
|
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
|
|
102
|
-
await this.befly.redis.setObject(cacheKey, columns,
|
|
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(
|
|
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(
|
|
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('事务提交失败,正在回滚'
|
|
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('事务回滚失败'
|
|
778
|
+
Logger.error({ err: rollbackError }, '事务回滚失败');
|
|
776
779
|
}
|
|
777
780
|
}
|
|
778
781
|
throw error;
|