befly 3.10.17 → 3.10.19
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 +83 -307
- package/dist/befly.config.d.ts +7 -0
- package/{befly.config.ts → dist/befly.config.js} +8 -31
- package/dist/checks/checkApi.d.ts +1 -0
- package/{checks/checkApi.ts → dist/checks/checkApi.js} +10 -27
- package/dist/checks/checkHook.d.ts +1 -0
- package/{checks/checkHook.ts → dist/checks/checkHook.js} +10 -19
- package/dist/checks/checkMenu.d.ts +7 -0
- package/{checks/checkMenu.ts → dist/checks/checkMenu.js} +15 -50
- package/dist/checks/checkPlugin.d.ts +1 -0
- package/{checks/checkPlugin.ts → dist/checks/checkPlugin.js} +10 -19
- package/dist/checks/checkTable.d.ts +6 -0
- package/{checks/checkTable.ts → dist/checks/checkTable.js} +16 -40
- package/dist/configs/presetFields.d.ts +4 -0
- package/{configs/presetFields.ts → dist/configs/presetFields.js} +1 -1
- package/dist/configs/presetRegexp.d.ts +145 -0
- package/{utils/regex.ts → dist/configs/presetRegexp.js} +8 -31
- package/dist/hooks/auth.d.ts +5 -0
- package/{hooks/auth.ts → dist/hooks/auth.js} +5 -9
- package/dist/hooks/cors.d.ts +9 -0
- package/{hooks/cors.ts → dist/hooks/cors.js} +2 -12
- package/dist/hooks/parser.d.ts +12 -0
- package/{hooks/parser.ts → dist/hooks/parser.js} +27 -42
- package/dist/hooks/permission.d.ts +12 -0
- package/{hooks/permission.ts → dist/hooks/permission.js} +11 -22
- package/dist/hooks/validator.d.ts +9 -0
- package/{hooks/validator.ts → dist/hooks/validator.js} +5 -12
- package/dist/lib/asyncContext.d.ts +21 -0
- package/dist/lib/asyncContext.js +27 -0
- package/dist/lib/cacheHelper.d.ts +95 -0
- package/{lib/cacheHelper.ts → dist/lib/cacheHelper.js} +43 -103
- package/dist/lib/cacheKeys.d.ts +23 -0
- package/{lib/cacheKeys.ts → dist/lib/cacheKeys.js} +5 -10
- package/dist/lib/cipher.d.ts +153 -0
- package/{lib/cipher.ts → dist/lib/cipher.js} +23 -44
- package/dist/lib/connect.d.ts +91 -0
- package/{lib/connect.ts → dist/lib/connect.js} +46 -87
- package/dist/lib/dbDialect.d.ts +87 -0
- package/{lib/dbDialect.ts → dist/lib/dbDialect.js} +32 -112
- package/dist/lib/dbHelper.d.ts +204 -0
- package/{lib/dbHelper.ts → dist/lib/dbHelper.js} +73 -230
- package/dist/lib/dbUtils.d.ts +68 -0
- package/{lib/dbUtils.ts → dist/lib/dbUtils.js} +49 -123
- package/dist/lib/jwt.d.ts +13 -0
- package/{lib/jwt.ts → dist/lib/jwt.js} +11 -32
- package/dist/lib/logger.d.ts +32 -0
- package/{lib/logger.ts → dist/lib/logger.js} +201 -278
- package/dist/lib/redisHelper.d.ts +185 -0
- package/{lib/redisHelper.ts → dist/lib/redisHelper.js} +95 -139
- package/dist/lib/sqlBuilder.d.ts +160 -0
- package/{lib/sqlBuilder.ts → dist/lib/sqlBuilder.js} +131 -277
- package/dist/lib/sqlCheck.d.ts +23 -0
- package/{lib/sqlCheck.ts → dist/lib/sqlCheck.js} +24 -41
- package/dist/lib/validator.d.ts +45 -0
- package/{lib/validator.ts → dist/lib/validator.js} +43 -60
- package/dist/loader/loadApis.d.ts +12 -0
- package/{loader/loadApis.ts → dist/loader/loadApis.js} +7 -17
- package/dist/loader/loadHooks.d.ts +8 -0
- package/{loader/loadHooks.ts → dist/loader/loadHooks.js} +5 -19
- package/dist/loader/loadPlugins.d.ts +8 -0
- package/{loader/loadPlugins.ts → dist/loader/loadPlugins.js} +8 -20
- package/dist/main.d.ts +26 -0
- package/{main.ts → dist/main.js} +39 -78
- package/dist/paths.d.ts +93 -0
- package/{paths.ts → dist/paths.js} +6 -19
- package/dist/plugins/cache.d.ts +14 -0
- package/{plugins/cache.ts → dist/plugins/cache.js} +4 -11
- package/dist/plugins/cipher.d.ts +10 -0
- package/{plugins/cipher.ts → dist/plugins/cipher.js} +1 -5
- package/dist/plugins/config.d.ts +10 -0
- package/dist/plugins/config.js +6 -0
- package/dist/plugins/db.d.ts +14 -0
- package/{plugins/db.ts → dist/plugins/db.js} +5 -13
- package/dist/plugins/jwt.d.ts +10 -0
- package/{plugins/jwt.ts → dist/plugins/jwt.js} +2 -7
- package/dist/plugins/logger.d.ts +28 -0
- package/{plugins/logger.ts → dist/plugins/logger.js} +2 -7
- package/dist/plugins/redis.d.ts +14 -0
- package/{plugins/redis.ts → dist/plugins/redis.js} +4 -9
- package/dist/plugins/tool.d.ts +79 -0
- package/{plugins/tool.ts → dist/plugins/tool.js} +7 -30
- package/dist/router/api.d.ts +14 -0
- package/dist/router/api.js +107 -0
- package/dist/router/static.d.ts +9 -0
- package/{router/static.ts → dist/router/static.js} +17 -31
- package/dist/scripts/ensureDist.d.ts +1 -0
- package/dist/scripts/ensureDist.js +80 -0
- package/dist/sync/syncApi.d.ts +3 -0
- package/{sync/syncApi.ts → dist/sync/syncApi.js} +33 -53
- package/dist/sync/syncCache.d.ts +2 -0
- package/{sync/syncCache.ts → dist/sync/syncCache.js} +1 -6
- package/dist/sync/syncDev.d.ts +6 -0
- package/{sync/syncDev.ts → dist/sync/syncDev.js} +27 -60
- package/dist/sync/syncMenu.d.ts +14 -0
- package/{sync/syncMenu.ts → dist/sync/syncMenu.js} +61 -121
- package/dist/sync/syncTable.d.ts +151 -0
- package/{sync/syncTable.ts → dist/sync/syncTable.js} +168 -375
- package/{types → dist/types}/api.d.ts +12 -51
- package/dist/types/api.js +4 -0
- package/{types → dist/types}/befly.d.ts +32 -223
- package/dist/types/befly.js +4 -0
- package/{types → dist/types}/cache.d.ts +7 -15
- package/dist/types/cache.js +4 -0
- package/dist/types/cipher.d.ts +27 -0
- package/dist/types/cipher.js +7 -0
- package/{types → dist/types}/common.d.ts +8 -33
- package/dist/types/common.js +5 -0
- package/{types → dist/types}/context.d.ts +3 -5
- package/dist/types/context.js +4 -0
- package/{types → dist/types}/crypto.d.ts +0 -3
- package/dist/types/crypto.js +4 -0
- package/dist/types/database.d.ts +138 -0
- package/dist/types/database.js +4 -0
- package/dist/types/hook.d.ts +15 -0
- package/dist/types/hook.js +6 -0
- package/dist/types/jwt.d.ts +75 -0
- package/dist/types/jwt.js +4 -0
- package/dist/types/logger.d.ts +47 -0
- package/dist/types/logger.js +6 -0
- package/dist/types/plugin.d.ts +14 -0
- package/dist/types/plugin.js +6 -0
- package/dist/types/redis.d.ts +71 -0
- package/dist/types/redis.js +4 -0
- package/{types/roleApisCache.ts → dist/types/roleApisCache.d.ts} +0 -2
- package/dist/types/roleApisCache.js +8 -0
- package/dist/types/sync.d.ts +92 -0
- package/dist/types/sync.js +4 -0
- package/dist/types/table.d.ts +34 -0
- package/dist/types/table.js +4 -0
- package/dist/types/validate.d.ts +67 -0
- package/dist/types/validate.js +4 -0
- package/dist/utils/arrayKeysToCamel.d.ts +13 -0
- package/{utils/arrayKeysToCamel.ts → dist/utils/arrayKeysToCamel.js} +4 -4
- package/dist/utils/calcPerfTime.d.ts +4 -0
- package/{utils/calcPerfTime.ts → dist/utils/calcPerfTime.js} +3 -3
- package/dist/utils/configTypes.d.ts +1 -0
- package/dist/utils/configTypes.js +1 -0
- package/dist/utils/convertBigIntFields.d.ts +11 -0
- package/{utils/convertBigIntFields.ts → dist/utils/convertBigIntFields.js} +5 -9
- package/dist/utils/cors.d.ts +8 -0
- package/{utils/cors.ts → dist/utils/cors.js} +1 -3
- package/dist/utils/disableMenusGlob.d.ts +13 -0
- package/{utils/disableMenusGlob.ts → dist/utils/disableMenusGlob.js} +9 -29
- package/dist/utils/fieldClear.d.ts +11 -0
- package/{utils/fieldClear.ts → dist/utils/fieldClear.js} +15 -33
- package/dist/utils/genShortId.d.ts +10 -0
- package/{utils/genShortId.ts → dist/utils/genShortId.js} +1 -1
- package/dist/utils/getClientIp.d.ts +6 -0
- package/{utils/getClientIp.ts → dist/utils/getClientIp.js} +1 -7
- package/dist/utils/importDefault.d.ts +1 -0
- package/dist/utils/importDefault.js +29 -0
- package/dist/utils/isDirentDirectory.d.ts +2 -0
- package/{utils/isDirentDirectory.ts → dist/utils/isDirentDirectory.js} +3 -8
- package/dist/utils/keysToCamel.d.ts +10 -0
- package/{utils/keysToCamel.ts → dist/utils/keysToCamel.js} +4 -5
- package/dist/utils/keysToSnake.d.ts +10 -0
- package/{utils/keysToSnake.ts → dist/utils/keysToSnake.js} +4 -5
- package/dist/utils/loadMenuConfigs.d.ts +5 -0
- package/{utils/loadMenuConfigs.ts → dist/utils/loadMenuConfigs.js} +22 -49
- package/dist/utils/pickFields.d.ts +4 -0
- package/{utils/pickFields.ts → dist/utils/pickFields.js} +2 -5
- package/dist/utils/process.d.ts +24 -0
- package/{utils/process.ts → dist/utils/process.js} +2 -18
- package/dist/utils/processFields.d.ts +4 -0
- package/{utils/processFields.ts → dist/utils/processFields.js} +4 -8
- package/dist/utils/regex.d.ts +145 -0
- package/{configs/presetRegexp.ts → dist/utils/regex.js} +8 -31
- package/dist/utils/response.d.ts +20 -0
- package/{utils/response.ts → dist/utils/response.js} +27 -48
- package/dist/utils/scanAddons.d.ts +17 -0
- package/{utils/scanAddons.ts → dist/utils/scanAddons.js} +4 -38
- package/dist/utils/scanConfig.d.ts +26 -0
- package/{utils/scanConfig.ts → dist/utils/scanConfig.js} +22 -59
- package/dist/utils/scanFiles.d.ts +30 -0
- package/{utils/scanFiles.ts → dist/utils/scanFiles.js} +25 -65
- package/dist/utils/scanSources.d.ts +10 -0
- package/{utils/scanSources.ts → dist/utils/scanSources.js} +16 -39
- package/dist/utils/sortModules.d.ts +28 -0
- package/{utils/sortModules.ts → dist/utils/sortModules.js} +24 -64
- package/dist/utils/sqlLog.d.ts +14 -0
- package/{utils/sqlLog.ts → dist/utils/sqlLog.js} +2 -14
- package/package.json +15 -32
- package/.gitignore +0 -0
- package/bunfig.toml +0 -3
- package/docs/README.md +0 -98
- package/docs/api/api.md +0 -1921
- package/docs/guide/examples.md +0 -926
- package/docs/guide/quickstart.md +0 -354
- package/docs/hooks/auth.md +0 -38
- package/docs/hooks/cors.md +0 -28
- package/docs/hooks/hook.md +0 -838
- package/docs/hooks/parser.md +0 -19
- package/docs/hooks/rateLimit.md +0 -47
- package/docs/infra/redis.md +0 -628
- package/docs/plugins/cipher.md +0 -61
- package/docs/plugins/database.md +0 -189
- package/docs/plugins/plugin.md +0 -986
- package/docs/reference/addon.md +0 -510
- package/docs/reference/config.md +0 -573
- package/docs/reference/logger.md +0 -495
- package/docs/reference/sync.md +0 -478
- package/docs/reference/table.md +0 -763
- package/docs/reference/validator.md +0 -620
- package/lib/asyncContext.ts +0 -43
- package/plugins/config.ts +0 -13
- package/router/api.ts +0 -130
- package/tsconfig.json +0 -54
- package/types/database.d.ts +0 -541
- package/types/hook.d.ts +0 -25
- package/types/jwt.d.ts +0 -118
- package/types/logger.d.ts +0 -65
- package/types/plugin.d.ts +0 -19
- package/types/redis.d.ts +0 -83
- package/types/sync.d.ts +0 -398
- package/types/table.d.ts +0 -216
- package/types/validate.d.ts +0 -69
- package/utils/configTypes.ts +0 -3
- package/utils/importDefault.ts +0 -21
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
* 加密工具类 - TypeScript 版本
|
|
3
3
|
* 提供各种哈希、HMAC、密码加密等功能
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
import type { EncodingType, HashAlgorithm, PasswordHashOptions } from "../types/crypto.js";
|
|
7
|
-
|
|
8
5
|
import { createSign } from "node:crypto";
|
|
9
|
-
|
|
10
6
|
/**
|
|
11
7
|
* 加密工具类
|
|
12
8
|
*/
|
|
@@ -17,12 +13,11 @@ export class Cipher {
|
|
|
17
13
|
* @param encoding - 输出编码
|
|
18
14
|
* @returns MD5 哈希值
|
|
19
15
|
*/
|
|
20
|
-
static md5(data
|
|
16
|
+
static md5(data, encoding = "hex") {
|
|
21
17
|
const hasher = new Bun.CryptoHasher("md5");
|
|
22
18
|
hasher.update(data);
|
|
23
19
|
return hasher.digest(encoding);
|
|
24
20
|
}
|
|
25
|
-
|
|
26
21
|
/**
|
|
27
22
|
* HMAC-MD5 签名
|
|
28
23
|
* @param key - 密钥
|
|
@@ -30,24 +25,22 @@ export class Cipher {
|
|
|
30
25
|
* @param encoding - 输出编码
|
|
31
26
|
* @returns HMAC-MD5 签名
|
|
32
27
|
*/
|
|
33
|
-
static hmacMd5(key
|
|
28
|
+
static hmacMd5(key, data, encoding = "hex") {
|
|
34
29
|
const hasher = new Bun.CryptoHasher("md5", key);
|
|
35
30
|
hasher.update(data);
|
|
36
31
|
return hasher.digest(encoding);
|
|
37
32
|
}
|
|
38
|
-
|
|
39
33
|
/**
|
|
40
34
|
* SHA-1 哈希
|
|
41
35
|
* @param data - 要哈希的数据
|
|
42
36
|
* @param encoding - 输出编码
|
|
43
37
|
* @returns SHA-1 哈希值
|
|
44
38
|
*/
|
|
45
|
-
static sha1(data
|
|
39
|
+
static sha1(data, encoding = "hex") {
|
|
46
40
|
const hasher = new Bun.CryptoHasher("sha1");
|
|
47
41
|
hasher.update(data);
|
|
48
42
|
return hasher.digest(encoding);
|
|
49
43
|
}
|
|
50
|
-
|
|
51
44
|
/**
|
|
52
45
|
* HMAC-SHA1 签名
|
|
53
46
|
* @param key - 密钥
|
|
@@ -55,24 +48,22 @@ export class Cipher {
|
|
|
55
48
|
* @param encoding - 输出编码
|
|
56
49
|
* @returns HMAC-SHA1 签名
|
|
57
50
|
*/
|
|
58
|
-
static hmacSha1(key
|
|
51
|
+
static hmacSha1(key, data, encoding = "hex") {
|
|
59
52
|
const hasher = new Bun.CryptoHasher("sha1", key);
|
|
60
53
|
hasher.update(data);
|
|
61
54
|
return hasher.digest(encoding);
|
|
62
55
|
}
|
|
63
|
-
|
|
64
56
|
/**
|
|
65
57
|
* SHA-256 哈希
|
|
66
58
|
* @param data - 要哈希的数据
|
|
67
59
|
* @param encoding - 输出编码
|
|
68
60
|
* @returns SHA-256 哈希值
|
|
69
61
|
*/
|
|
70
|
-
static sha256(data
|
|
62
|
+
static sha256(data, encoding = "hex") {
|
|
71
63
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
72
64
|
hasher.update(data);
|
|
73
65
|
return hasher.digest(encoding);
|
|
74
66
|
}
|
|
75
|
-
|
|
76
67
|
/**
|
|
77
68
|
* RSA-SHA256 签名
|
|
78
69
|
* @param data - 要签名的数据
|
|
@@ -80,13 +71,12 @@ export class Cipher {
|
|
|
80
71
|
* @param encoding - 输出编码('hex' | 'base64' | 'base64url')
|
|
81
72
|
* @returns RSA-SHA256 签名
|
|
82
73
|
*/
|
|
83
|
-
static rsaSha256(data
|
|
74
|
+
static rsaSha256(data, privateKey, encoding = "hex") {
|
|
84
75
|
const sign = createSign("RSA-SHA256");
|
|
85
76
|
sign.update(data);
|
|
86
77
|
const signature = sign.sign(privateKey, encoding);
|
|
87
78
|
return signature;
|
|
88
79
|
}
|
|
89
|
-
|
|
90
80
|
/**
|
|
91
81
|
* HMAC-SHA256 签名
|
|
92
82
|
* @param key - 密钥
|
|
@@ -94,24 +84,22 @@ export class Cipher {
|
|
|
94
84
|
* @param encoding - 输出编码
|
|
95
85
|
* @returns HMAC-SHA256 签名
|
|
96
86
|
*/
|
|
97
|
-
static hmacSha256(key
|
|
87
|
+
static hmacSha256(key, data, encoding = "hex") {
|
|
98
88
|
const hasher = new Bun.CryptoHasher("sha256", key);
|
|
99
89
|
hasher.update(data);
|
|
100
90
|
return hasher.digest(encoding);
|
|
101
91
|
}
|
|
102
|
-
|
|
103
92
|
/**
|
|
104
93
|
* SHA-512 哈希
|
|
105
94
|
* @param data - 要哈希的数据
|
|
106
95
|
* @param encoding - 输出编码
|
|
107
96
|
* @returns SHA-512 哈希值
|
|
108
97
|
*/
|
|
109
|
-
static sha512(data
|
|
98
|
+
static sha512(data, encoding = "hex") {
|
|
110
99
|
const hasher = new Bun.CryptoHasher("sha512");
|
|
111
100
|
hasher.update(data);
|
|
112
101
|
return hasher.digest(encoding);
|
|
113
102
|
}
|
|
114
|
-
|
|
115
103
|
/**
|
|
116
104
|
* HMAC-SHA512 签名
|
|
117
105
|
* @param key - 密钥
|
|
@@ -119,12 +107,11 @@ export class Cipher {
|
|
|
119
107
|
* @param encoding - 输出编码
|
|
120
108
|
* @returns HMAC-SHA512 签名
|
|
121
109
|
*/
|
|
122
|
-
static hmacSha512(key
|
|
110
|
+
static hmacSha512(key, data, encoding = "hex") {
|
|
123
111
|
const hasher = new Bun.CryptoHasher("sha512", key);
|
|
124
112
|
hasher.update(data);
|
|
125
113
|
return hasher.digest(encoding);
|
|
126
114
|
}
|
|
127
|
-
|
|
128
115
|
/**
|
|
129
116
|
* 通用哈希方法
|
|
130
117
|
* @param algorithm - 算法名称
|
|
@@ -132,12 +119,11 @@ export class Cipher {
|
|
|
132
119
|
* @param encoding - 输出编码
|
|
133
120
|
* @returns 哈希值
|
|
134
121
|
*/
|
|
135
|
-
static hash(algorithm
|
|
122
|
+
static hash(algorithm, data, encoding = "hex") {
|
|
136
123
|
const hasher = new Bun.CryptoHasher(algorithm);
|
|
137
124
|
hasher.update(data);
|
|
138
125
|
return hasher.digest(encoding);
|
|
139
126
|
}
|
|
140
|
-
|
|
141
127
|
/**
|
|
142
128
|
* 通用 HMAC 方法
|
|
143
129
|
* @param algorithm - 算法名称
|
|
@@ -146,12 +132,11 @@ export class Cipher {
|
|
|
146
132
|
* @param encoding - 输出编码
|
|
147
133
|
* @returns HMAC 签名
|
|
148
134
|
*/
|
|
149
|
-
static hmac(algorithm
|
|
135
|
+
static hmac(algorithm, key, data, encoding = "hex") {
|
|
150
136
|
const hasher = new Bun.CryptoHasher(algorithm, key);
|
|
151
137
|
hasher.update(data);
|
|
152
138
|
return hasher.digest(encoding);
|
|
153
139
|
}
|
|
154
|
-
|
|
155
140
|
/**
|
|
156
141
|
* 文件哈希
|
|
157
142
|
* @param filePath - 文件路径
|
|
@@ -159,25 +144,24 @@ export class Cipher {
|
|
|
159
144
|
* @param encoding - 输出编码
|
|
160
145
|
* @returns 文件哈希值
|
|
161
146
|
*/
|
|
162
|
-
static async hashFile(filePath
|
|
147
|
+
static async hashFile(filePath, algorithm = "sha256", encoding = "hex") {
|
|
163
148
|
const file = Bun.file(filePath);
|
|
164
149
|
const hasher = new Bun.CryptoHasher(algorithm);
|
|
165
|
-
|
|
166
150
|
const stream = file.stream();
|
|
167
151
|
const reader = stream.getReader();
|
|
168
|
-
|
|
169
152
|
try {
|
|
170
153
|
while (true) {
|
|
171
154
|
const { done, value } = await reader.read();
|
|
172
|
-
if (done)
|
|
155
|
+
if (done)
|
|
156
|
+
break;
|
|
173
157
|
hasher.update(value);
|
|
174
158
|
}
|
|
175
159
|
return hasher.digest(encoding);
|
|
176
|
-
}
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
177
162
|
reader.releaseLock();
|
|
178
163
|
}
|
|
179
164
|
}
|
|
180
|
-
|
|
181
165
|
/**
|
|
182
166
|
* 密码哈希(使用 bcrypt 算法)
|
|
183
167
|
* @param password - 密码
|
|
@@ -190,14 +174,13 @@ export class Cipher {
|
|
|
190
174
|
* // 自定义强度(可选)
|
|
191
175
|
* const hash = await Cipher.hashPassword('123456', { cost: 12 });
|
|
192
176
|
*/
|
|
193
|
-
static async hashPassword(password
|
|
177
|
+
static async hashPassword(password, options = {}) {
|
|
194
178
|
const finalOptions = {
|
|
195
179
|
algorithm: "bcrypt",
|
|
196
180
|
...options
|
|
197
|
-
}
|
|
181
|
+
};
|
|
198
182
|
return await Bun.password.hash(password, finalOptions);
|
|
199
183
|
}
|
|
200
|
-
|
|
201
184
|
/**
|
|
202
185
|
* 验证密码
|
|
203
186
|
* @param password - 原始密码
|
|
@@ -209,34 +192,31 @@ export class Cipher {
|
|
|
209
192
|
* // 密码正确
|
|
210
193
|
* }
|
|
211
194
|
*/
|
|
212
|
-
static async verifyPassword(password
|
|
195
|
+
static async verifyPassword(password, hash) {
|
|
213
196
|
return await Bun.password.verify(password, hash);
|
|
214
197
|
}
|
|
215
|
-
|
|
216
198
|
/**
|
|
217
199
|
* Base64 编码
|
|
218
200
|
* @param data - 要编码的数据
|
|
219
201
|
* @returns Base64 编码的字符串
|
|
220
202
|
*/
|
|
221
|
-
static base64Encode(data
|
|
203
|
+
static base64Encode(data) {
|
|
222
204
|
return Buffer.from(data, "utf8").toString("base64");
|
|
223
205
|
}
|
|
224
|
-
|
|
225
206
|
/**
|
|
226
207
|
* Base64 解码
|
|
227
208
|
* @param data - Base64 编码的字符串
|
|
228
209
|
* @returns 解码后的字符串
|
|
229
210
|
*/
|
|
230
|
-
static base64Decode(data
|
|
211
|
+
static base64Decode(data) {
|
|
231
212
|
return Buffer.from(data, "base64").toString("utf8");
|
|
232
213
|
}
|
|
233
|
-
|
|
234
214
|
/**
|
|
235
215
|
* 生成随机十六进制字符串
|
|
236
216
|
* @param length - 字符串长度
|
|
237
217
|
* @returns 随机十六进制字符串
|
|
238
218
|
*/
|
|
239
|
-
static randomString(length
|
|
219
|
+
static randomString(length) {
|
|
240
220
|
const bytes = Math.ceil(length / 2);
|
|
241
221
|
const randomBytes = crypto.getRandomValues(new Uint8Array(bytes));
|
|
242
222
|
let result = "";
|
|
@@ -245,14 +225,13 @@ export class Cipher {
|
|
|
245
225
|
}
|
|
246
226
|
return result.slice(0, length);
|
|
247
227
|
}
|
|
248
|
-
|
|
249
228
|
/**
|
|
250
229
|
* 快速哈希 (非密码学)
|
|
251
230
|
* @param data - 数据
|
|
252
231
|
* @param seed - 种子值
|
|
253
232
|
* @returns 64位哈希值
|
|
254
233
|
*/
|
|
255
|
-
static fastHash(data
|
|
234
|
+
static fastHash(data, seed = 0) {
|
|
256
235
|
const result = Bun.hash(data, seed);
|
|
257
236
|
return typeof result === "bigint" ? Number(result) : result;
|
|
258
237
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数据库连接管理器
|
|
3
|
+
* 统一管理 SQL 和 Redis 连接
|
|
4
|
+
*/
|
|
5
|
+
import type { DatabaseConfig, RedisConfig } from "../types/befly.ts";
|
|
6
|
+
import { SQL, RedisClient } from "bun";
|
|
7
|
+
/**
|
|
8
|
+
* 数据库连接管理器
|
|
9
|
+
* 使用静态方法管理全局单例连接
|
|
10
|
+
*/
|
|
11
|
+
export declare class Connect {
|
|
12
|
+
private static sqlClient;
|
|
13
|
+
private static redisClient;
|
|
14
|
+
private static sqlConnectedAt;
|
|
15
|
+
private static redisConnectedAt;
|
|
16
|
+
private static sqlPoolMax;
|
|
17
|
+
/**
|
|
18
|
+
* 连接 SQL 数据库
|
|
19
|
+
* @returns SQL 客户端实例
|
|
20
|
+
*/
|
|
21
|
+
static connectSql(dbConfig: DatabaseConfig): Promise<SQL>;
|
|
22
|
+
/**
|
|
23
|
+
* 断开 SQL 连接
|
|
24
|
+
*/
|
|
25
|
+
static disconnectSql(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* 获取 SQL 客户端实例
|
|
28
|
+
* @throws 如果未连接则抛出错误
|
|
29
|
+
*/
|
|
30
|
+
static getSql(): SQL;
|
|
31
|
+
/**
|
|
32
|
+
* 连接 Redis
|
|
33
|
+
* @returns Redis 客户端实例
|
|
34
|
+
*/
|
|
35
|
+
static connectRedis(redisConfig: RedisConfig): Promise<RedisClient>;
|
|
36
|
+
/**
|
|
37
|
+
* 断开 Redis 连接
|
|
38
|
+
*/
|
|
39
|
+
static disconnectRedis(): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* 获取 Redis 客户端实例
|
|
42
|
+
* @throws 如果未连接则抛出错误
|
|
43
|
+
*/
|
|
44
|
+
static getRedis(): RedisClient;
|
|
45
|
+
/**
|
|
46
|
+
* 连接所有数据库(SQL + Redis)
|
|
47
|
+
*/
|
|
48
|
+
static connect(config: {
|
|
49
|
+
db: DatabaseConfig;
|
|
50
|
+
redis: RedisConfig;
|
|
51
|
+
}): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* 断开所有数据库连接
|
|
54
|
+
*/
|
|
55
|
+
static disconnect(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* 检查连接状态
|
|
58
|
+
*/
|
|
59
|
+
static isConnected(): {
|
|
60
|
+
sql: boolean;
|
|
61
|
+
redis: boolean;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* 获取连接状态详细信息(用于监控和调试)
|
|
65
|
+
*/
|
|
66
|
+
static getStatus(): {
|
|
67
|
+
sql: {
|
|
68
|
+
connected: boolean;
|
|
69
|
+
connectedAt: number | null;
|
|
70
|
+
uptime: number | null;
|
|
71
|
+
poolMax: number;
|
|
72
|
+
};
|
|
73
|
+
redis: {
|
|
74
|
+
connected: boolean;
|
|
75
|
+
connectedAt: number | null;
|
|
76
|
+
uptime: number | null;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* 设置 mock SQL 客户端(仅用于测试)
|
|
81
|
+
*/
|
|
82
|
+
static __setMockSql(mockClient: SQL): void;
|
|
83
|
+
/**
|
|
84
|
+
* 设置 mock Redis 客户端(仅用于测试)
|
|
85
|
+
*/
|
|
86
|
+
static __setMockRedis(mockClient: RedisClient): void;
|
|
87
|
+
/**
|
|
88
|
+
* 重置所有连接状态(仅用于测试)
|
|
89
|
+
*/
|
|
90
|
+
static __reset(): void;
|
|
91
|
+
}
|
|
@@ -2,37 +2,28 @@
|
|
|
2
2
|
* 数据库连接管理器
|
|
3
3
|
* 统一管理 SQL 和 Redis 连接
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
import type { DatabaseConfig, RedisConfig } from "../types/befly.js";
|
|
7
|
-
|
|
8
5
|
import { SQL, RedisClient } from "bun";
|
|
9
|
-
|
|
10
6
|
import { Logger } from "./logger.js";
|
|
11
|
-
|
|
12
7
|
/**
|
|
13
8
|
* 数据库连接管理器
|
|
14
9
|
* 使用静态方法管理全局单例连接
|
|
15
10
|
*/
|
|
16
11
|
export class Connect {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
static sqlClient = null;
|
|
13
|
+
static redisClient = null;
|
|
20
14
|
// 连接统计信息
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
static sqlConnectedAt = null;
|
|
16
|
+
static redisConnectedAt = null;
|
|
17
|
+
static sqlPoolMax = 1;
|
|
25
18
|
// ========================================
|
|
26
19
|
// SQL 连接管理
|
|
27
20
|
// ========================================
|
|
28
|
-
|
|
29
21
|
/**
|
|
30
22
|
* 连接 SQL 数据库
|
|
31
23
|
* @returns SQL 客户端实例
|
|
32
24
|
*/
|
|
33
|
-
static async connectSql(dbConfig
|
|
25
|
+
static async connectSql(dbConfig) {
|
|
34
26
|
const config = dbConfig || {};
|
|
35
|
-
|
|
36
27
|
// 构建数据库连接字符串
|
|
37
28
|
const type = config.type || "mysql";
|
|
38
29
|
const host = config.host || "127.0.0.1";
|
|
@@ -40,106 +31,99 @@ export class Connect {
|
|
|
40
31
|
const user = encodeURIComponent(config.username || "root");
|
|
41
32
|
const password = encodeURIComponent(config.password || "root");
|
|
42
33
|
const database = encodeURIComponent(config.database || "befly_demo");
|
|
43
|
-
|
|
44
|
-
let finalUrl: string;
|
|
34
|
+
let finalUrl;
|
|
45
35
|
if (type === "sqlite") {
|
|
46
36
|
finalUrl = database;
|
|
47
|
-
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
48
39
|
if (!host || !database) {
|
|
49
40
|
throw new Error("数据库配置不完整,请检查配置参数");
|
|
50
41
|
}
|
|
51
42
|
finalUrl = `${type}://${user}:${password}@${host}:${port}/${database}`;
|
|
52
43
|
}
|
|
53
|
-
|
|
54
|
-
let sql: SQL;
|
|
55
|
-
|
|
44
|
+
let sql;
|
|
56
45
|
if (type === "sqlite") {
|
|
57
46
|
sql = new SQL(finalUrl);
|
|
58
|
-
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
59
49
|
sql = new SQL({
|
|
60
50
|
url: finalUrl,
|
|
61
51
|
max: config.poolMax ?? 1,
|
|
62
52
|
bigint: false
|
|
63
53
|
});
|
|
64
54
|
}
|
|
65
|
-
|
|
66
55
|
try {
|
|
67
56
|
const timeout = 30000;
|
|
68
|
-
|
|
69
57
|
const healthCheckPromise = (async () => {
|
|
70
58
|
let version = "";
|
|
71
59
|
if (type === "sqlite") {
|
|
72
|
-
const v = await sql`SELECT sqlite_version() AS version`;
|
|
60
|
+
const v = await sql `SELECT sqlite_version() AS version`;
|
|
73
61
|
version = v?.[0]?.version;
|
|
74
|
-
}
|
|
75
|
-
|
|
62
|
+
}
|
|
63
|
+
else if (type === "postgresql" || type === "postgres") {
|
|
64
|
+
const v = await sql `SELECT version() AS version`;
|
|
76
65
|
version = v?.[0]?.version;
|
|
77
|
-
}
|
|
78
|
-
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const v = await sql `SELECT VERSION() AS version`;
|
|
79
69
|
version = v?.[0]?.version;
|
|
80
70
|
}
|
|
81
71
|
return version;
|
|
82
72
|
})();
|
|
83
|
-
|
|
84
|
-
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
73
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
85
74
|
setTimeout(() => {
|
|
86
75
|
reject(new Error(`数据库连接超时 (${timeout}ms)`));
|
|
87
76
|
}, timeout);
|
|
88
77
|
});
|
|
89
|
-
|
|
90
78
|
await Promise.race([healthCheckPromise, timeoutPromise]);
|
|
91
|
-
|
|
92
79
|
this.sqlClient = sql;
|
|
93
80
|
this.sqlConnectedAt = Date.now();
|
|
94
81
|
this.sqlPoolMax = config.poolMax ?? 1;
|
|
95
82
|
return sql;
|
|
96
|
-
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
97
85
|
Logger.error({ err: error }, "[Connect] SQL 连接失败");
|
|
98
86
|
try {
|
|
99
87
|
await sql?.close();
|
|
100
|
-
}
|
|
101
|
-
|
|
88
|
+
}
|
|
89
|
+
catch { }
|
|
102
90
|
throw error;
|
|
103
91
|
}
|
|
104
92
|
}
|
|
105
|
-
|
|
106
93
|
/**
|
|
107
94
|
* 断开 SQL 连接
|
|
108
95
|
*/
|
|
109
|
-
static async disconnectSql()
|
|
96
|
+
static async disconnectSql() {
|
|
110
97
|
if (this.sqlClient) {
|
|
111
98
|
try {
|
|
112
99
|
await this.sqlClient.close();
|
|
113
|
-
}
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
114
102
|
Logger.error({ err: error }, "[Connect] 关闭 SQL 连接时出错");
|
|
115
103
|
}
|
|
116
104
|
this.sqlClient = null;
|
|
117
105
|
this.sqlConnectedAt = null;
|
|
118
106
|
}
|
|
119
107
|
}
|
|
120
|
-
|
|
121
108
|
/**
|
|
122
109
|
* 获取 SQL 客户端实例
|
|
123
110
|
* @throws 如果未连接则抛出错误
|
|
124
111
|
*/
|
|
125
|
-
static getSql()
|
|
112
|
+
static getSql() {
|
|
126
113
|
if (!this.sqlClient) {
|
|
127
114
|
throw new Error("SQL 客户端未连接,请先调用 Connect.connectSql()");
|
|
128
115
|
}
|
|
129
116
|
return this.sqlClient;
|
|
130
117
|
}
|
|
131
|
-
|
|
132
118
|
// ========================================
|
|
133
119
|
// Redis 连接管理
|
|
134
120
|
// ========================================
|
|
135
|
-
|
|
136
121
|
/**
|
|
137
122
|
* 连接 Redis
|
|
138
123
|
* @returns Redis 客户端实例
|
|
139
124
|
*/
|
|
140
|
-
static async connectRedis(redisConfig
|
|
125
|
+
static async connectRedis(redisConfig) {
|
|
141
126
|
const config = redisConfig || {};
|
|
142
|
-
|
|
143
127
|
try {
|
|
144
128
|
// 构建 Redis URL
|
|
145
129
|
const host = config.host || "127.0.0.1";
|
|
@@ -147,16 +131,14 @@ export class Connect {
|
|
|
147
131
|
const username = config.username || "";
|
|
148
132
|
const password = config.password || "";
|
|
149
133
|
const db = config.db || 0;
|
|
150
|
-
|
|
151
134
|
let auth = "";
|
|
152
135
|
if (username && password) {
|
|
153
136
|
auth = `${username}:${password}@`;
|
|
154
|
-
}
|
|
137
|
+
}
|
|
138
|
+
else if (password) {
|
|
155
139
|
auth = `:${password}@`;
|
|
156
140
|
}
|
|
157
|
-
|
|
158
141
|
const url = `redis://${auth}${host}:${port}/${db}`;
|
|
159
|
-
|
|
160
142
|
const redis = new RedisClient(url, {
|
|
161
143
|
connectionTimeout: 30000,
|
|
162
144
|
idleTimeout: 0,
|
|
@@ -165,99 +147,80 @@ export class Connect {
|
|
|
165
147
|
enableOfflineQueue: true,
|
|
166
148
|
enableAutoPipelining: true
|
|
167
149
|
});
|
|
168
|
-
|
|
169
150
|
await redis.ping();
|
|
170
|
-
|
|
171
151
|
this.redisClient = redis;
|
|
172
152
|
this.redisConnectedAt = Date.now();
|
|
173
153
|
return redis;
|
|
174
|
-
}
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
175
156
|
Logger.error({ err: error }, "[Connect] Redis 连接失败");
|
|
176
157
|
throw new Error(`Redis 连接失败: ${error.message}`);
|
|
177
158
|
}
|
|
178
159
|
}
|
|
179
|
-
|
|
180
160
|
/**
|
|
181
161
|
* 断开 Redis 连接
|
|
182
162
|
*/
|
|
183
|
-
static async disconnectRedis()
|
|
163
|
+
static async disconnectRedis() {
|
|
184
164
|
if (this.redisClient) {
|
|
185
165
|
try {
|
|
186
166
|
this.redisClient.close();
|
|
187
167
|
this.redisConnectedAt = null;
|
|
188
|
-
}
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
189
170
|
Logger.error({ err: error }, "[Connect] 关闭 Redis 连接时出错");
|
|
190
171
|
}
|
|
191
172
|
this.redisClient = null;
|
|
192
173
|
}
|
|
193
174
|
}
|
|
194
|
-
|
|
195
175
|
/**
|
|
196
176
|
* 获取 Redis 客户端实例
|
|
197
177
|
* @throws 如果未连接则抛出错误
|
|
198
178
|
*/
|
|
199
|
-
static getRedis()
|
|
179
|
+
static getRedis() {
|
|
200
180
|
if (!this.redisClient) {
|
|
201
181
|
throw new Error("Redis 客户端未连接,请先调用 Connect.connectRedis()");
|
|
202
182
|
}
|
|
203
183
|
return this.redisClient;
|
|
204
184
|
}
|
|
205
|
-
|
|
206
185
|
// ========================================
|
|
207
186
|
// 统一连接管理
|
|
208
187
|
// ========================================
|
|
209
|
-
|
|
210
188
|
/**
|
|
211
189
|
* 连接所有数据库(SQL + Redis)
|
|
212
190
|
*/
|
|
213
|
-
static async connect(config
|
|
191
|
+
static async connect(config) {
|
|
214
192
|
try {
|
|
215
193
|
// 连接 SQL
|
|
216
194
|
await this.connectSql(config.db || {});
|
|
217
|
-
|
|
218
195
|
// 连接 Redis
|
|
219
196
|
await this.connectRedis(config.redis || {});
|
|
220
|
-
}
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
221
199
|
Logger.error({ err: error }, "数据库初始化失败");
|
|
222
200
|
await this.disconnect();
|
|
223
201
|
throw error;
|
|
224
202
|
}
|
|
225
203
|
}
|
|
226
|
-
|
|
227
204
|
/**
|
|
228
205
|
* 断开所有数据库连接
|
|
229
206
|
*/
|
|
230
|
-
static async disconnect()
|
|
207
|
+
static async disconnect() {
|
|
231
208
|
await this.disconnectSql();
|
|
232
209
|
await this.disconnectRedis();
|
|
233
210
|
}
|
|
234
|
-
|
|
235
211
|
/**
|
|
236
212
|
* 检查连接状态
|
|
237
213
|
*/
|
|
238
|
-
static isConnected()
|
|
214
|
+
static isConnected() {
|
|
239
215
|
return {
|
|
240
216
|
sql: this.sqlClient !== null,
|
|
241
217
|
redis: this.redisClient !== null
|
|
242
218
|
};
|
|
243
219
|
}
|
|
244
|
-
|
|
245
220
|
/**
|
|
246
221
|
* 获取连接状态详细信息(用于监控和调试)
|
|
247
222
|
*/
|
|
248
|
-
static getStatus()
|
|
249
|
-
sql: {
|
|
250
|
-
connected: boolean;
|
|
251
|
-
connectedAt: number | null;
|
|
252
|
-
uptime: number | null;
|
|
253
|
-
poolMax: number;
|
|
254
|
-
};
|
|
255
|
-
redis: {
|
|
256
|
-
connected: boolean;
|
|
257
|
-
connectedAt: number | null;
|
|
258
|
-
uptime: number | null;
|
|
259
|
-
};
|
|
260
|
-
} {
|
|
223
|
+
static getStatus() {
|
|
261
224
|
const now = Date.now();
|
|
262
225
|
return {
|
|
263
226
|
sql: {
|
|
@@ -273,29 +236,25 @@ export class Connect {
|
|
|
273
236
|
}
|
|
274
237
|
};
|
|
275
238
|
}
|
|
276
|
-
|
|
277
239
|
// ========================================
|
|
278
240
|
// 测试辅助方法
|
|
279
241
|
// ========================================
|
|
280
|
-
|
|
281
242
|
/**
|
|
282
243
|
* 设置 mock SQL 客户端(仅用于测试)
|
|
283
244
|
*/
|
|
284
|
-
static __setMockSql(mockClient
|
|
245
|
+
static __setMockSql(mockClient) {
|
|
285
246
|
this.sqlClient = mockClient;
|
|
286
247
|
}
|
|
287
|
-
|
|
288
248
|
/**
|
|
289
249
|
* 设置 mock Redis 客户端(仅用于测试)
|
|
290
250
|
*/
|
|
291
|
-
static __setMockRedis(mockClient
|
|
251
|
+
static __setMockRedis(mockClient) {
|
|
292
252
|
this.redisClient = mockClient;
|
|
293
253
|
}
|
|
294
|
-
|
|
295
254
|
/**
|
|
296
255
|
* 重置所有连接状态(仅用于测试)
|
|
297
256
|
*/
|
|
298
|
-
static __reset()
|
|
257
|
+
static __reset() {
|
|
299
258
|
this.sqlClient = null;
|
|
300
259
|
this.redisClient = null;
|
|
301
260
|
this.sqlConnectedAt = null;
|