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/tests/xml.test.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from 'bun:test';
|
|
2
|
-
import { Xml } from '../lib/xml';
|
|
3
|
-
|
|
4
|
-
describe('Xml - 基本解析', () => {
|
|
5
|
-
test('解析简单元素', () => {
|
|
6
|
-
const xml = new Xml();
|
|
7
|
-
const result = xml.parse('<root>Hello</root>');
|
|
8
|
-
expect(result).toBe('Hello');
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
test('解析嵌套元素', () => {
|
|
12
|
-
const xml = new Xml();
|
|
13
|
-
const result = xml.parse('<root><child>Value</child></root>');
|
|
14
|
-
expect(result).toEqual({ child: 'Value' });
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test('解析多个同名元素', () => {
|
|
18
|
-
const xml = new Xml();
|
|
19
|
-
const result = xml.parse('<root><item>A</item><item>B</item></root>');
|
|
20
|
-
expect(result).toEqual({ item: ['A', 'B'] });
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('解析空元素', () => {
|
|
24
|
-
const xml = new Xml();
|
|
25
|
-
const result = xml.parse('<root></root>');
|
|
26
|
-
expect(result).toBe('');
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test('解析自闭合标签', () => {
|
|
30
|
-
const xml = new Xml();
|
|
31
|
-
const result = xml.parse('<root><item/></root>');
|
|
32
|
-
expect(result).toEqual({ item: '' });
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
describe('Xml - 属性解析', () => {
|
|
37
|
-
test('解析元素属性', () => {
|
|
38
|
-
const xml = new Xml();
|
|
39
|
-
const result = xml.parse('<root id="1">Value</root>') as any;
|
|
40
|
-
expect(result['@id']).toBe('1');
|
|
41
|
-
expect(result['#text']).toBe('Value');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('解析多个属性', () => {
|
|
45
|
-
const xml = new Xml();
|
|
46
|
-
const result = xml.parse('<user id="123" name="John">Content</user>') as any;
|
|
47
|
-
expect(result['@id']).toBe('123');
|
|
48
|
-
expect(result['@name']).toBe('John');
|
|
49
|
-
expect(result['#text']).toBe('Content');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('忽略属性', () => {
|
|
53
|
-
const xml = new Xml({ ignoreAttributes: true });
|
|
54
|
-
const result = xml.parse('<root id="1">Value</root>');
|
|
55
|
-
expect(result).toBe('Value');
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
describe('Xml - 数值解析', () => {
|
|
60
|
-
test('自动解析数字', () => {
|
|
61
|
-
const xml = new Xml();
|
|
62
|
-
const result = xml.parse('<root>123</root>');
|
|
63
|
-
expect(result).toBe(123);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test('自动解析布尔值', () => {
|
|
67
|
-
const xml = new Xml();
|
|
68
|
-
const result1 = xml.parse('<root>true</root>');
|
|
69
|
-
const result2 = xml.parse('<root>false</root>');
|
|
70
|
-
expect(result1).toBe(true);
|
|
71
|
-
expect(result2).toBe(false);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test('禁用数字解析', () => {
|
|
75
|
-
const xml = new Xml({ parseNumbers: false });
|
|
76
|
-
const result = xml.parse('<root>123</root>');
|
|
77
|
-
expect(result).toBe('123');
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
describe('Xml - 错误处理', () => {
|
|
82
|
-
test('拒绝非字符串输入', () => {
|
|
83
|
-
const xml = new Xml();
|
|
84
|
-
expect(() => xml.parse(123 as any)).toThrow('无效的 XML 数据');
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test('拒绝空字符串', () => {
|
|
88
|
-
const xml = new Xml();
|
|
89
|
-
expect(() => xml.parse('')).toThrow('非空字符串');
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test('拒绝只有空格的字符串', () => {
|
|
93
|
-
const xml = new Xml();
|
|
94
|
-
expect(() => xml.parse(' ')).toThrow('非空字符串');
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test('检测未闭合标签', () => {
|
|
98
|
-
const xml = new Xml();
|
|
99
|
-
expect(() => xml.parse('<root><item>')).toThrow('未找到结束标签');
|
|
100
|
-
});
|
|
101
|
-
});
|
package/types/addon.d.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Addon 配置类型定义
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Addon 作者信息
|
|
7
|
-
*/
|
|
8
|
-
export interface AddonAuthor {
|
|
9
|
-
/** 作者名称 */
|
|
10
|
-
name: string;
|
|
11
|
-
/** 作者邮箱 */
|
|
12
|
-
email?: string;
|
|
13
|
-
/** 作者网站 */
|
|
14
|
-
url?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Addon 配置
|
|
19
|
-
*/
|
|
20
|
-
export interface AddonConfig {
|
|
21
|
-
/** Addon 唯一标识(小写、短横线或下划线),例如 "admin"、"demo" */
|
|
22
|
-
name: string;
|
|
23
|
-
|
|
24
|
-
/** Addon 人类可读名称,例如 "管理后台" */
|
|
25
|
-
title: string;
|
|
26
|
-
|
|
27
|
-
/** 版本号(语义化版本),例如 "1.0.0" */
|
|
28
|
-
version?: string;
|
|
29
|
-
|
|
30
|
-
/** 简短描述 */
|
|
31
|
-
description?: string;
|
|
32
|
-
|
|
33
|
-
/** 作者信息 */
|
|
34
|
-
author?: AddonAuthor | string;
|
|
35
|
-
|
|
36
|
-
/** 源码仓库链接 */
|
|
37
|
-
repo?: string;
|
|
38
|
-
|
|
39
|
-
/** 关键词(用于搜索和分类) */
|
|
40
|
-
keywords?: string[];
|
|
41
|
-
|
|
42
|
-
/** 主入口文件路径(相对于 addon 目录),例如 "index.ts" */
|
|
43
|
-
entry?: string;
|
|
44
|
-
|
|
45
|
-
/** 依赖的其他 addon 或核心包 */
|
|
46
|
-
dependencies?: Record<string, string>;
|
|
47
|
-
|
|
48
|
-
/** 许可证 */
|
|
49
|
-
license?: string;
|
|
50
|
-
}
|
package/types/crypto.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 加密相关类型定义
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 编码类型
|
|
7
|
-
*/
|
|
8
|
-
export type EncodingType = 'hex' | 'base64' | 'base64url';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 哈希算法类型
|
|
12
|
-
*/
|
|
13
|
-
export type HashAlgorithm = 'md5' | 'sha1' | 'sha256' | 'sha512' | 'sha384' | 'sha224';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 密码哈希选项
|
|
17
|
-
*/
|
|
18
|
-
export interface PasswordHashOptions {
|
|
19
|
-
algorithm?: 'argon2' | 'bcrypt';
|
|
20
|
-
memoryCost?: number;
|
|
21
|
-
timeCost?: number;
|
|
22
|
-
[key: string]: any;
|
|
23
|
-
}
|
package/types/jwt.d.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JWT 相关类型定义
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* JWT 算法类型
|
|
7
|
-
*/
|
|
8
|
-
export type JwtAlgorithm = 'HS256' | 'HS384' | 'HS512';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* JWT Header 接口
|
|
12
|
-
*/
|
|
13
|
-
export interface JwtHeader {
|
|
14
|
-
alg: JwtAlgorithm;
|
|
15
|
-
typ: 'JWT';
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* JWT 完整解码结果
|
|
20
|
-
*/
|
|
21
|
-
export interface JwtDecoded {
|
|
22
|
-
header: JwtHeader;
|
|
23
|
-
payload: JwtPayload;
|
|
24
|
-
signature: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* JWT 载荷
|
|
29
|
-
*/
|
|
30
|
-
export interface JwtPayload {
|
|
31
|
-
/** 用户 ID */
|
|
32
|
-
userId?: string;
|
|
33
|
-
/** 用户名 */
|
|
34
|
-
username?: string;
|
|
35
|
-
/** 角色 */
|
|
36
|
-
role?: string;
|
|
37
|
-
/** 角色列表 */
|
|
38
|
-
roles?: string[];
|
|
39
|
-
/** 权限列表 */
|
|
40
|
-
permissions?: string[];
|
|
41
|
-
/** 签发时间 */
|
|
42
|
-
iat?: number;
|
|
43
|
-
/** 过期时间 */
|
|
44
|
-
exp?: number;
|
|
45
|
-
/** 主题 */
|
|
46
|
-
sub?: string;
|
|
47
|
-
/** 签发者 */
|
|
48
|
-
iss?: string;
|
|
49
|
-
/** 受众 */
|
|
50
|
-
aud?: string | string[];
|
|
51
|
-
/** JWT ID */
|
|
52
|
-
jti?: string;
|
|
53
|
-
/** 生效时间 */
|
|
54
|
-
nbf?: number;
|
|
55
|
-
/** 其他自定义字段 */
|
|
56
|
-
[key: string]: any;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* JWT 签名选项
|
|
61
|
-
*/
|
|
62
|
-
export interface JwtSignOptions {
|
|
63
|
-
/** 密钥 */
|
|
64
|
-
secret?: string;
|
|
65
|
-
/** 算法 */
|
|
66
|
-
algorithm?: JwtAlgorithm;
|
|
67
|
-
/** 过期时间 */
|
|
68
|
-
expiresIn?: string | number;
|
|
69
|
-
/** 签发者 */
|
|
70
|
-
issuer?: string;
|
|
71
|
-
/** 受众 */
|
|
72
|
-
audience?: string;
|
|
73
|
-
/** 主题 */
|
|
74
|
-
subject?: string;
|
|
75
|
-
/** 生效时间 */
|
|
76
|
-
notBefore?: string | number;
|
|
77
|
-
/** JWT ID */
|
|
78
|
-
jwtId?: string;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* JWT 验证选项
|
|
83
|
-
*/
|
|
84
|
-
export interface JwtVerifyOptions {
|
|
85
|
-
/** 密钥 */
|
|
86
|
-
secret?: string;
|
|
87
|
-
/** 算法列表 */
|
|
88
|
-
algorithms?: JwtAlgorithm[];
|
|
89
|
-
/** 签发者 */
|
|
90
|
-
issuer?: string;
|
|
91
|
-
/** 受众 */
|
|
92
|
-
audience?: string;
|
|
93
|
-
/** 主题 */
|
|
94
|
-
subject?: string;
|
|
95
|
-
/** 是否忽略过期 */
|
|
96
|
-
ignoreExpiration?: boolean;
|
|
97
|
-
/** 是否忽略生效时间 */
|
|
98
|
-
ignoreNotBefore?: boolean;
|
|
99
|
-
}
|
package/types/logger.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
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;
|
|
43
|
-
}
|
package/types/tool.d.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 工具函数相关类型定义
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 日期格式化类型
|
|
7
|
-
*/
|
|
8
|
-
export type DateFormat = 'YYYY-MM-DD' | 'YYYY-MM-DD HH:mm:ss' | 'HH:mm:ss' | 'YYYY/MM/DD' | 'MM-DD' | string;
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 颜色代码
|
|
12
|
-
*/
|
|
13
|
-
export type ColorCode = 'reset' | 'bright' | 'dim' | 'underscore' | 'blink' | 'reverse' | 'hidden' | 'black' | 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 分页参数
|
|
17
|
-
*/
|
|
18
|
-
export interface PaginationParams {
|
|
19
|
-
/** 页码(从 1 开始) */
|
|
20
|
-
page?: number;
|
|
21
|
-
/** 每页数量 */
|
|
22
|
-
limit?: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 分页结果
|
|
27
|
-
*/
|
|
28
|
-
export interface PaginationResult<T = any> {
|
|
29
|
-
/** 数据列表 */
|
|
30
|
-
list: T[];
|
|
31
|
-
/** 总条数 */
|
|
32
|
-
total: number;
|
|
33
|
-
/** 当前页码 */
|
|
34
|
-
page: number;
|
|
35
|
-
/** 每页数量 */
|
|
36
|
-
limit: number;
|
|
37
|
-
/** 总页数 */
|
|
38
|
-
pages: number;
|
|
39
|
-
/** 是否有下一页 */
|
|
40
|
-
hasNext: boolean;
|
|
41
|
-
/** 是否有上一页 */
|
|
42
|
-
hasPrev: boolean;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* 文件类型
|
|
47
|
-
*/
|
|
48
|
-
export type FileType = 'image' | 'video' | 'audio' | 'document' | 'archive' | 'other';
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* MIME 类型
|
|
52
|
-
*/
|
|
53
|
-
export type MimeType = string;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 文件上传选项
|
|
57
|
-
*/
|
|
58
|
-
export interface FileUploadOptions {
|
|
59
|
-
/** 允许的文件类型 */
|
|
60
|
-
allowedTypes?: string[];
|
|
61
|
-
/** 最大文件大小(字节) */
|
|
62
|
-
maxSize?: number;
|
|
63
|
-
/** 保存目录 */
|
|
64
|
-
saveDir?: string;
|
|
65
|
-
/** 文件名生成函数 */
|
|
66
|
-
filename?: (originalName: string) => string;
|
|
67
|
-
}
|
package/types/validator.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 验证器相关类型定义
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 字段验证错误信息
|
|
7
|
-
*/
|
|
8
|
-
export type ValidationError = string | null;
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 字段类型
|
|
12
|
-
*/
|
|
13
|
-
export type FieldType = 'string' | 'number' | 'text' | 'array';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 验证结果
|
|
17
|
-
*/
|
|
18
|
-
export interface ValidationResult {
|
|
19
|
-
/** 验证状态码:0=成功,1=失败 */
|
|
20
|
-
code: 0 | 1;
|
|
21
|
-
/** 字段验证结果 */
|
|
22
|
-
fields: Record<string, any>;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 字段规则
|
|
27
|
-
*/
|
|
28
|
-
export interface FieldRule {
|
|
29
|
-
/** 字段名 */
|
|
30
|
-
name: string;
|
|
31
|
-
/** 字段类型 */
|
|
32
|
-
type: FieldType;
|
|
33
|
-
/** 最小值/长度 */
|
|
34
|
-
min: number | null;
|
|
35
|
-
/** 最大值/长度 */
|
|
36
|
-
max: number | null;
|
|
37
|
-
/** 默认值 */
|
|
38
|
-
default: any;
|
|
39
|
-
/** 是否索引 */
|
|
40
|
-
index: 0 | 1;
|
|
41
|
-
/** 正则约束 */
|
|
42
|
-
regex: string | null;
|
|
43
|
-
}
|