befly 3.8.29 → 3.8.30

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 (52) hide show
  1. package/README.md +8 -6
  2. package/checks/checkApi.ts +2 -1
  3. package/checks/checkTable.ts +3 -2
  4. package/hooks/parser.ts +5 -3
  5. package/hooks/permission.ts +12 -5
  6. package/lib/cacheHelper.ts +76 -62
  7. package/lib/connect.ts +8 -35
  8. package/lib/dbHelper.ts +14 -11
  9. package/lib/jwt.ts +58 -437
  10. package/lib/logger.ts +76 -197
  11. package/lib/redisHelper.ts +163 -1
  12. package/lib/sqlBuilder.ts +2 -1
  13. package/lib/validator.ts +9 -8
  14. package/loader/loadApis.ts +4 -7
  15. package/loader/loadHooks.ts +2 -2
  16. package/loader/loadPlugins.ts +4 -4
  17. package/main.ts +4 -17
  18. package/package.json +9 -8
  19. package/paths.ts +0 -6
  20. package/plugins/db.ts +2 -2
  21. package/plugins/jwt.ts +5 -5
  22. package/plugins/redis.ts +1 -1
  23. package/router/api.ts +2 -2
  24. package/router/static.ts +1 -2
  25. package/sync/syncAll.ts +2 -2
  26. package/sync/syncApi.ts +10 -7
  27. package/sync/syncDb/apply.ts +1 -2
  28. package/sync/syncDb.ts +6 -10
  29. package/sync/syncDev.ts +10 -48
  30. package/sync/syncMenu.ts +11 -8
  31. package/tests/cacheHelper.test.ts +327 -0
  32. package/tests/dbHelper-columns.test.ts +5 -20
  33. package/tests/dbHelper-execute.test.ts +14 -68
  34. package/tests/fields-redis-cache.test.ts +5 -3
  35. package/tests/integration.test.ts +15 -26
  36. package/tests/jwt.test.ts +36 -94
  37. package/tests/logger.test.ts +32 -34
  38. package/tests/redisHelper.test.ts +270 -0
  39. package/tests/redisKeys.test.ts +76 -0
  40. package/tests/sync-connection.test.ts +0 -6
  41. package/tests/syncDb-constants.test.ts +12 -12
  42. package/tests/util.test.ts +5 -1
  43. package/types/befly.d.ts +2 -15
  44. package/types/common.d.ts +11 -93
  45. package/types/database.d.ts +216 -5
  46. package/types/index.ts +1 -0
  47. package/types/logger.d.ts +11 -41
  48. package/types/table.d.ts +213 -0
  49. package/hooks/_rateLimit.ts +0 -64
  50. package/lib/regexAliases.ts +0 -59
  51. package/lib/xml.ts +0 -383
  52. package/tests/xml.test.ts +0 -101
@@ -108,25 +108,25 @@ describe('MYSQL_TABLE_CONFIG', () => {
108
108
  });
109
109
  });
110
110
 
111
- describe('typeMapping (MySQL)', () => {
111
+ describe('getTypeMapping (MySQL)', () => {
112
112
  test('number 映射为 BIGINT', () => {
113
- expect(constants.typeMapping.number).toBe('BIGINT');
113
+ expect(constants.getTypeMapping().number).toBe('BIGINT');
114
114
  });
115
115
 
116
116
  test('string 映射为 VARCHAR', () => {
117
- expect(constants.typeMapping.string).toBe('VARCHAR');
117
+ expect(constants.getTypeMapping().string).toBe('VARCHAR');
118
118
  });
119
119
 
120
120
  test('text 映射为 MEDIUMTEXT', () => {
121
- expect(constants.typeMapping.text).toBe('MEDIUMTEXT');
121
+ expect(constants.getTypeMapping().text).toBe('MEDIUMTEXT');
122
122
  });
123
123
 
124
124
  test('array_string 映射为 VARCHAR', () => {
125
- expect(constants.typeMapping.array_string).toBe('VARCHAR');
125
+ expect(constants.getTypeMapping().array_string).toBe('VARCHAR');
126
126
  });
127
127
 
128
128
  test('array_text 映射为 MEDIUMTEXT', () => {
129
- expect(constants.typeMapping.array_text).toBe('MEDIUMTEXT');
129
+ expect(constants.getTypeMapping().array_text).toBe('MEDIUMTEXT');
130
130
  });
131
131
  });
132
132
 
@@ -137,15 +137,15 @@ describe('IS_PLAN', () => {
137
137
  });
138
138
 
139
139
  describe('数据库类型判断 (MySQL)', () => {
140
- test('IS_MYSQL 为 true', () => {
141
- expect(constants.IS_MYSQL).toBe(true);
140
+ test('isMySQL 为 true', () => {
141
+ expect(constants.isMySQL()).toBe(true);
142
142
  });
143
143
 
144
- test('IS_PG 为 false', () => {
145
- expect(constants.IS_PG).toBe(false);
144
+ test('isPG 为 false', () => {
145
+ expect(constants.isPG()).toBe(false);
146
146
  });
147
147
 
148
- test('IS_SQLITE 为 false', () => {
149
- expect(constants.IS_SQLITE).toBe(false);
148
+ test('isSQLite 为 false', () => {
149
+ expect(constants.isSQLite()).toBe(false);
150
150
  });
151
151
  });
@@ -1,5 +1,9 @@
1
1
  import { describe, test, expect } from 'bun:test';
2
- import { keysToCamel, keysToSnake, arrayKeysToCamel, calcPerfTime, fieldClear } from 'befly-util';
2
+ import { keysToCamel } from 'befly-shared/keysToCamel';
3
+ import { keysToSnake } from 'befly-shared/keysToSnake';
4
+ import { arrayKeysToCamel } from 'befly-shared/arrayKeysToCamel';
5
+ import { calcPerfTime } from 'befly-shared/calcPerfTime';
6
+ import { fieldClear } from 'befly-shared/fieldClear';
3
7
 
4
8
  describe('Util - keysToCamel', () => {
5
9
  test('转换对象键名为驼峰', () => {
package/types/befly.d.ts CHANGED
@@ -5,6 +5,7 @@
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 { LoggerConfig } from './logger.js';
8
9
  import type { Logger } from '../lib/logger.js';
9
10
  import type { Jwt } from '../lib/jwt.js';
10
11
  import type { Validator } from '../lib/validator.js';
@@ -14,21 +15,7 @@ import type { RedisHelper } from '../lib/redisHelper.js';
14
15
  import type { Cipher } from '../lib/cipher.js';
15
16
  import type { CacheHelper } from '../lib/cacheHelper.js';
16
17
 
17
- /**
18
- * 日志配置
19
- */
20
- export interface LoggerConfig {
21
- /** 是否开启调试模式 (0: 关闭, 1: 开启) @default 1 */
22
- debug?: number;
23
- /** 日志排除字段 (逗号分隔) @default 'password,token,secret' */
24
- excludeFields?: string;
25
- /** 日志目录 @default './logs' */
26
- dir?: string;
27
- /** 是否输出到控制台 (0: 关闭, 1: 开启) @default 1 */
28
- console?: number;
29
- /** 单个日志文件最大大小 (字节) @default 10485760 (10MB) */
30
- maxSize?: number;
31
- }
18
+ export type { LoggerConfig };
32
19
 
33
20
  /**
34
21
  * 数据库配置
package/types/common.d.ts CHANGED
@@ -1,47 +1,13 @@
1
1
  /**
2
2
  * Befly 框架通用类型定义
3
+ * Core 专用类型,befly-shared 的类型请直接从 befly-shared 导入
3
4
  */
4
5
 
5
- /**
6
- * 响应结果类型
7
- */
8
- export interface ResponseResult<T = any> {
9
- code: number;
10
- msg: string;
11
- data?: T;
12
- error?: any;
13
- }
6
+ import type { SqlValue } from 'befly-shared/types';
14
7
 
15
- /**
16
- * 验证结果类型
17
- */
18
- export interface ValidationResult {
19
- code: 0 | 1;
20
- fields: Record<string, any>;
21
- }
22
-
23
- /**
24
- * 字段定义类型(对象格式)
25
- */
26
- export interface FieldDefinition {
27
- name: string; // 字段标签/描述
28
- detail: string; // 字段详细说明
29
- type: 'string' | 'number' | 'text' | 'array_string' | 'array_text';
30
- min: number | null; // 最小值/最小长度
31
- max: number | null; // 最大值/最大长度
32
- default: any; // 默认值
33
- index: boolean; // 是否创建索引
34
- unique: boolean; // 是否唯一
35
- comment: string; // 字段注释
36
- nullable: boolean; // 是否允许为空
37
- unsigned: boolean; // 是否无符号(仅number类型)
38
- regexp: string | null; // 正则验证
39
- }
40
-
41
- /**
42
- * 表定义类型(对象格式)
43
- */
44
- export type TableDefinition = Record<string, FieldDefinition>;
8
+ // ============================================
9
+ // Core 专用类型(不适合放在 shared 中的类型)
10
+ // ============================================
45
11
 
46
12
  /**
47
13
  * 字段规则字符串(已废弃,保留用于兼容)
@@ -60,26 +26,15 @@ export type FieldRule = string;
60
26
  * @deprecated 请使用 FieldDefinition 对象格式
61
27
  */
62
28
  export interface ParsedFieldRule {
63
- name: string; // 字段名称
29
+ name: string;
64
30
  type: 'string' | 'number' | 'text' | 'array_string' | 'array_text';
65
- min: number | null; // 最小值
66
- max: number | null; // 最大值
67
- default: any; // 默认值
68
- index: 0 | 1; // 是否索引
69
- regex: string | null; // 正则约束
31
+ min: number | null;
32
+ max: number | null;
33
+ default: any;
34
+ index: 0 | 1;
35
+ regex: string | null;
70
36
  }
71
37
 
72
- /**
73
- * SQL 查询参数类型
74
- */
75
- export type SqlValue = string | number | boolean | null | Date;
76
- export type SqlParams = SqlValue[];
77
-
78
- /**
79
- * 排序方向
80
- */
81
- export type OrderDirection = 'ASC' | 'DESC' | 'asc' | 'desc';
82
-
83
38
  /**
84
39
  * 比较运算符
85
40
  */
@@ -90,28 +45,6 @@ export type ComparisonOperator = '=' | '>' | '<' | '>=' | '<=' | '!=' | '<>' | '
90
45
  */
91
46
  export type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
92
47
 
93
- /**
94
- * 数据库配置类型
95
- */
96
- export interface DatabaseConfig {
97
- host: string;
98
- port: number;
99
- user: string;
100
- password: string;
101
- database: string;
102
- connectionLimit?: number;
103
- }
104
-
105
- /**
106
- * Redis 配置类型
107
- */
108
- export interface RedisConfig {
109
- host: string;
110
- port: number;
111
- password?: string;
112
- db?: number;
113
- }
114
-
115
48
  /**
116
49
  * 日志级别
117
50
  */
@@ -145,21 +78,6 @@ export interface PaginationParams {
145
78
  limit: number;
146
79
  }
147
80
 
148
- /**
149
- * 分页结果
150
- */
151
- export interface PaginatedResult<T = any> {
152
- total: number;
153
- page: number;
154
- limit: number;
155
- data: T[];
156
- }
157
-
158
- /**
159
- * 通用键值对
160
- */
161
- export type KeyValue<T = any> = Record<string, T>;
162
-
163
81
  /**
164
82
  * 可选字段
165
83
  */
@@ -2,13 +2,80 @@
2
2
  * 数据库相关类型定义
3
3
  */
4
4
 
5
- import type { SqlValue, WhereConditions } from './common';
5
+ import type { SqlValue } from 'befly-shared/types';
6
+ import type { WhereConditions } from './common';
7
+ import type { DatabaseTables, TableName, TableType, TableInsertType, TableUpdateType, TypedWhereConditions } from './table';
6
8
 
7
9
  // 重新导出 WhereOperator 和 WhereConditions,供其他模块使用
8
10
  export type { WhereOperator, WhereConditions } from './index';
9
11
 
12
+ // 重新导出表类型工具
13
+ export type { DatabaseTables, TableName, TableType, TableInsertType, TableUpdateType, SystemFields, BaseTable, InsertType, UpdateType, SelectType, TypedWhereConditions } from './table';
14
+
15
+ // ============================================
16
+ // 泛型查询选项(类型安全版本)
17
+ // ============================================
18
+
19
+ /**
20
+ * 泛型查询选项 - 支持类型推断
21
+ * @template K - 表名类型
22
+ */
23
+ export interface TypedQueryOptions<K extends TableName> {
24
+ /** 表名 */
25
+ table: K;
26
+ /** 查询字段(表字段的子集) */
27
+ fields?: (keyof TableType<K>)[] | string[];
28
+ /** WHERE 条件(类型安全) */
29
+ where?: TypedWhereConditions<TableType<K>> | WhereConditions;
30
+ /** 排序(格式:["字段#ASC", "字段#DESC"]) */
31
+ orderBy?: string[];
32
+ /** 页码(从 1 开始) */
33
+ page?: number;
34
+ /** 每页数量 */
35
+ limit?: number;
36
+ }
37
+
38
+ /**
39
+ * 泛型插入选项 - 支持类型推断
40
+ * @template K - 表名类型
41
+ */
42
+ export interface TypedInsertOptions<K extends TableName> {
43
+ /** 表名 */
44
+ table: K;
45
+ /** 插入数据(ID、时间戳、state 会自动生成) */
46
+ data: TableInsertType<K> | Record<string, any>;
47
+ }
48
+
49
+ /**
50
+ * 泛型更新选项 - 支持类型推断
51
+ * @template K - 表名类型
52
+ */
53
+ export interface TypedUpdateOptions<K extends TableName> {
54
+ /** 表名 */
55
+ table: K;
56
+ /** 更新数据(updated_at 会自动更新) */
57
+ data: TableUpdateType<K> | Record<string, any>;
58
+ /** WHERE 条件 */
59
+ where: TypedWhereConditions<TableType<K>> | WhereConditions;
60
+ }
61
+
62
+ /**
63
+ * 泛型删除选项 - 支持类型推断
64
+ * @template K - 表名类型
65
+ */
66
+ export interface TypedDeleteOptions<K extends TableName> {
67
+ /** 表名 */
68
+ table: K;
69
+ /** WHERE 条件 */
70
+ where: TypedWhereConditions<TableType<K>> | WhereConditions;
71
+ }
72
+
73
+ // ============================================
74
+ // 兼容旧版查询选项(非类型安全版本)
75
+ // ============================================
76
+
10
77
  /**
11
- * 查询选项
78
+ * 查询选项(兼容旧版,不进行类型检查)
12
79
  */
13
80
  export interface QueryOptions {
14
81
  /** 表名 */
@@ -26,7 +93,7 @@ export interface QueryOptions {
26
93
  }
27
94
 
28
95
  /**
29
- * 插入选项
96
+ * 插入选项(兼容旧版)
30
97
  */
31
98
  export interface InsertOptions {
32
99
  /** 表名 */
@@ -36,7 +103,7 @@ export interface InsertOptions {
36
103
  }
37
104
 
38
105
  /**
39
- * 更新选项
106
+ * 更新选项(兼容旧版)
40
107
  */
41
108
  export interface UpdateOptions {
42
109
  /** 表名 */
@@ -48,7 +115,7 @@ export interface UpdateOptions {
48
115
  }
49
116
 
50
117
  /**
51
- * 删除选项
118
+ * 删除选项(兼容旧版)
52
119
  */
53
120
  export interface DeleteOptions {
54
121
  /** 表名 */
@@ -147,17 +214,161 @@ export interface SyncStats {
147
214
 
148
215
  /**
149
216
  * DbHelper 接口(前向声明)
217
+ * 支持两种使用方式:
218
+ * 1. 类型安全模式:使用 TypedQueryOptions 等泛型接口,获得完整类型推断
219
+ * 2. 兼容模式:使用 QueryOptions 等非泛型接口,行为与之前一致
150
220
  */
151
221
  export interface DbHelper {
222
+ // ============================================
223
+ // 类型安全方法(推荐)
224
+ // ============================================
225
+
226
+ /**
227
+ * 查询记录数(类型安全版本)
228
+ * @template K - 表名类型
229
+ */
230
+ getCount<K extends TableName>(options: Omit<TypedQueryOptions<K>, 'fields' | 'page' | 'limit' | 'orderBy'>): Promise<number>;
231
+
232
+ /**
233
+ * 查询单条数据(类型安全版本)
234
+ * @template K - 表名类型
235
+ * @returns 返回类型自动推断为对应表的记录类型
236
+ */
237
+ getOne<K extends TableName>(options: TypedQueryOptions<K>): Promise<TableType<K> | null>;
238
+
239
+ /**
240
+ * 查询列表(类型安全版本)
241
+ * @template K - 表名类型
242
+ * @returns 返回类型自动推断为对应表的记录列表
243
+ */
244
+ getList<K extends TableName>(options: TypedQueryOptions<K>): Promise<ListResult<TableType<K>>>;
245
+
246
+ /**
247
+ * 查询所有数据(类型安全版本)
248
+ * @template K - 表名类型
249
+ * @returns 返回类型自动推断为对应表的记录数组
250
+ */
251
+ getAll<K extends TableName>(options: Omit<TypedQueryOptions<K>, 'page' | 'limit'>): Promise<TableType<K>[]>;
252
+
253
+ /**
254
+ * 插入数据(类型安全版本)
255
+ * @template K - 表名类型
256
+ */
257
+ insData<K extends TableName>(options: TypedInsertOptions<K>): Promise<number>;
258
+
259
+ /**
260
+ * 更新数据(类型安全版本)
261
+ * @template K - 表名类型
262
+ */
263
+ updData<K extends TableName>(options: TypedUpdateOptions<K>): Promise<number>;
264
+
265
+ /**
266
+ * 删除数据(类型安全版本)
267
+ * @template K - 表名类型
268
+ */
269
+ delData<K extends TableName>(options: TypedDeleteOptions<K>): Promise<number>;
270
+
271
+ // ============================================
272
+ // 兼容旧版方法(手动指定返回类型)
273
+ // ============================================
274
+
275
+ /**
276
+ * 查询记录数(兼容版本)
277
+ */
152
278
  getCount(options: Omit<QueryOptions, 'fields' | 'page' | 'limit' | 'orderBy'>): Promise<number>;
279
+
280
+ /**
281
+ * 查询单条数据(兼容版本,需手动指定泛型)
282
+ * @template T - 返回类型
283
+ */
153
284
  getOne<T = any>(options: QueryOptions): Promise<T | null>;
285
+
286
+ /**
287
+ * 查询列表(兼容版本,需手动指定泛型)
288
+ * @template T - 列表项类型
289
+ */
154
290
  getList<T = any>(options: QueryOptions): Promise<ListResult<T>>;
291
+
292
+ /**
293
+ * 查询所有数据(兼容版本,需手动指定泛型)
294
+ * @template T - 返回类型
295
+ */
155
296
  getAll<T = any>(options: Omit<QueryOptions, 'page' | 'limit'>): Promise<T[]>;
297
+
298
+ /**
299
+ * 插入数据(兼容版本)
300
+ */
156
301
  insData(options: InsertOptions): Promise<number>;
302
+
303
+ /**
304
+ * 更新数据(兼容版本)
305
+ */
157
306
  updData(options: UpdateOptions): Promise<number>;
307
+
308
+ /**
309
+ * 删除数据(兼容版本)
310
+ */
158
311
  delData(options: DeleteOptions): Promise<number>;
312
+
313
+ // ============================================
314
+ // 通用方法
315
+ // ============================================
316
+
317
+ /**
318
+ * 执行事务
319
+ * @template T - 事务返回类型
320
+ */
159
321
  trans<T = any>(callback: TransactionCallback<T>): Promise<T>;
322
+
323
+ /**
324
+ * 执行原始 SQL
325
+ */
160
326
  query(sql: string, params?: any[]): Promise<any>;
327
+
328
+ /**
329
+ * 检查数据是否存在
330
+ */
331
+ exists(options: Omit<QueryOptions, 'fields' | 'orderBy' | 'page' | 'limit'>): Promise<boolean>;
332
+
333
+ /**
334
+ * 检查表是否存在
335
+ */
336
+ tableExists(tableName: string): Promise<boolean>;
337
+
338
+ /**
339
+ * 批量插入数据
340
+ */
341
+ insBatch(table: string, dataList: Record<string, any>[]): Promise<number[]>;
342
+
343
+ /**
344
+ * 禁用数据(设置 state=2)
345
+ */
346
+ disableData(options: Omit<DeleteOptions, 'hard'>): Promise<number>;
347
+
348
+ /**
349
+ * 启用数据(设置 state=1)
350
+ */
351
+ enableData(options: Omit<DeleteOptions, 'hard'>): Promise<number>;
352
+
353
+ /**
354
+ * 硬删除数据(物理删除)
355
+ */
356
+ delForce(options: Omit<DeleteOptions, 'hard'>): Promise<number>;
357
+
358
+ /**
359
+ * 自增字段
360
+ */
361
+ increment(table: string, field: string, where: WhereConditions, value?: number): Promise<number>;
362
+
363
+ /**
364
+ * 自减字段
365
+ */
366
+ decrement(table: string, field: string, where: WhereConditions, value?: number): Promise<number>;
367
+
368
+ /**
369
+ * 查询单个字段值
370
+ */
371
+ getFieldValue<T = any>(options: Omit<QueryOptions, 'fields'> & { field: string }): Promise<T | null>;
161
372
  }
162
373
 
163
374
  /**
package/types/index.ts CHANGED
@@ -13,6 +13,7 @@ export * from './jwt.js';
13
13
  export * from './logger.js';
14
14
  export * from './plugin.js';
15
15
  export * from './redis.js';
16
+ export * from './table.js';
16
17
  export * from './tool.js';
17
18
  export * from './validator.js';
18
19
  export * from './sync.js';
package/types/logger.d.ts CHANGED
@@ -1,43 +1,13 @@
1
1
  /**
2
- * 日志相关类型定义
3
- */
4
-
5
- /**
6
- * 日志级别
7
- */
8
- export type LogLevel = 'info' | 'warn' | 'error' | 'debug' | 'trace';
9
-
10
- /**
11
- * 日志消息
12
- */
13
- export type LogMessage = string | Record<string, any>;
14
-
15
- /**
16
- * 日志选项
17
- */
18
- export interface LogOptions {
19
- /** 日志级别 */
20
- level?: LogLevel;
21
- /** 是否输出到控制台 */
22
- console?: boolean;
23
- /** 是否写入文件 */
24
- file?: boolean;
25
- /** 日志文件路径 */
26
- filePath?: string;
27
- /** 敏感字段列表 */
28
- sensitiveFields?: string[];
29
- }
30
-
31
- /**
32
- * 日志记录器接口
33
- */
34
- export interface Logger {
35
- /** 记录信息日志 */
36
- info(message: LogMessage): void;
37
- /** 记录警告日志 */
38
- warn(message: LogMessage): void;
39
- /** 记录错误日志 */
40
- error(message: LogMessage): void;
41
- /** 记录调试日志 */
42
- debug(message: LogMessage): void;
2
+ * 日志配置
3
+ */
4
+ export interface LoggerConfig {
5
+ /** 是否开启调试模式 (0: 关闭, 1: 开启) @default 0 */
6
+ debug?: number;
7
+ /** 日志目录 @default './logs' */
8
+ dir?: string;
9
+ /** 是否输出到控制台 (0: 关闭, 1: 开启) @default 1 */
10
+ console?: number;
11
+ /** 单个日志文件最大大小 (MB) @default 10 */
12
+ maxSize?: number;
43
13
  }