befly 3.9.38 → 3.9.40

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 (155) hide show
  1. package/README.md +37 -38
  2. package/befly.config.ts +62 -40
  3. package/checks/checkApi.ts +16 -16
  4. package/checks/checkApp.ts +19 -25
  5. package/checks/checkTable.ts +42 -42
  6. package/docs/README.md +42 -35
  7. package/docs/{api.md → api/api.md} +223 -231
  8. package/docs/cipher.md +71 -69
  9. package/docs/database.md +143 -141
  10. package/docs/{examples.md → guide/examples.md} +181 -181
  11. package/docs/guide/quickstart.md +331 -0
  12. package/docs/hooks/auth.md +38 -0
  13. package/docs/hooks/cors.md +28 -0
  14. package/docs/{hook.md → hooks/hook.md} +140 -57
  15. package/docs/hooks/parser.md +19 -0
  16. package/docs/hooks/rateLimit.md +47 -0
  17. package/docs/{redis.md → infra/redis.md} +84 -93
  18. package/docs/plugins/cipher.md +61 -0
  19. package/docs/plugins/database.md +128 -0
  20. package/docs/{plugin.md → plugins/plugin.md} +83 -81
  21. package/docs/quickstart.md +26 -26
  22. package/docs/{addon.md → reference/addon.md} +46 -46
  23. package/docs/{config.md → reference/config.md} +32 -80
  24. package/docs/{logger.md → reference/logger.md} +52 -52
  25. package/docs/{sync.md → reference/sync.md} +32 -35
  26. package/docs/{table.md → reference/table.md} +1 -1
  27. package/docs/{validator.md → reference/validator.md} +57 -57
  28. package/hooks/auth.ts +8 -4
  29. package/hooks/cors.ts +13 -13
  30. package/hooks/parser.ts +37 -17
  31. package/hooks/permission.ts +26 -14
  32. package/hooks/rateLimit.ts +276 -0
  33. package/hooks/validator.ts +8 -8
  34. package/lib/asyncContext.ts +43 -0
  35. package/lib/cacheHelper.ts +212 -77
  36. package/lib/cacheKeys.ts +38 -0
  37. package/lib/cipher.ts +30 -30
  38. package/lib/connect.ts +28 -28
  39. package/lib/dbHelper.ts +183 -102
  40. package/lib/jwt.ts +16 -16
  41. package/lib/logger.ts +610 -19
  42. package/lib/redisHelper.ts +185 -44
  43. package/lib/sqlBuilder.ts +90 -91
  44. package/lib/validator.ts +59 -39
  45. package/loader/loadApis.ts +48 -44
  46. package/loader/loadHooks.ts +40 -14
  47. package/loader/loadPlugins.ts +16 -17
  48. package/main.ts +57 -47
  49. package/package.json +47 -45
  50. package/paths.ts +15 -14
  51. package/plugins/cache.ts +5 -4
  52. package/plugins/cipher.ts +3 -3
  53. package/plugins/config.ts +2 -2
  54. package/plugins/db.ts +9 -9
  55. package/plugins/jwt.ts +3 -3
  56. package/plugins/logger.ts +8 -12
  57. package/plugins/redis.ts +8 -8
  58. package/plugins/tool.ts +6 -6
  59. package/router/api.ts +85 -56
  60. package/router/static.ts +12 -12
  61. package/sync/syncAll.ts +12 -12
  62. package/sync/syncApi.ts +55 -52
  63. package/sync/syncDb/apply.ts +20 -19
  64. package/sync/syncDb/constants.ts +25 -23
  65. package/sync/syncDb/ddl.ts +35 -36
  66. package/sync/syncDb/helpers.ts +6 -9
  67. package/sync/syncDb/schema.ts +10 -9
  68. package/sync/syncDb/sqlite.ts +7 -8
  69. package/sync/syncDb/table.ts +37 -35
  70. package/sync/syncDb/tableCreate.ts +21 -20
  71. package/sync/syncDb/types.ts +23 -20
  72. package/sync/syncDb/version.ts +10 -10
  73. package/sync/syncDb.ts +43 -36
  74. package/sync/syncDev.ts +74 -65
  75. package/sync/syncMenu.ts +190 -55
  76. package/tests/api-integration-array-number.test.ts +282 -0
  77. package/tests/befly-config-env.test.ts +78 -0
  78. package/tests/cacheHelper.test.ts +135 -104
  79. package/tests/cacheKeys.test.ts +41 -0
  80. package/tests/cipher.test.ts +90 -89
  81. package/tests/dbHelper-advanced.test.ts +140 -134
  82. package/tests/dbHelper-all-array-types.test.ts +316 -0
  83. package/tests/dbHelper-array-serialization.test.ts +258 -0
  84. package/tests/dbHelper-columns.test.ts +56 -55
  85. package/tests/dbHelper-execute.test.ts +45 -44
  86. package/tests/dbHelper-joins.test.ts +124 -119
  87. package/tests/fields-redis-cache.test.ts +29 -27
  88. package/tests/fields-validate.test.ts +38 -38
  89. package/tests/getClientIp.test.ts +54 -0
  90. package/tests/integration.test.ts +69 -67
  91. package/tests/jwt.test.ts +27 -26
  92. package/tests/logger.test.ts +267 -34
  93. package/tests/rateLimit-hook.test.ts +477 -0
  94. package/tests/redisHelper.test.ts +187 -188
  95. package/tests/redisKeys.test.ts +6 -73
  96. package/tests/scanConfig.test.ts +144 -0
  97. package/tests/sqlBuilder-advanced.test.ts +217 -215
  98. package/tests/sqlBuilder.test.ts +92 -91
  99. package/tests/sync-connection.test.ts +29 -29
  100. package/tests/syncDb-apply.test.ts +97 -96
  101. package/tests/syncDb-array-number.test.ts +160 -0
  102. package/tests/syncDb-constants.test.ts +48 -47
  103. package/tests/syncDb-ddl.test.ts +99 -98
  104. package/tests/syncDb-helpers.test.ts +29 -28
  105. package/tests/syncDb-schema.test.ts +61 -60
  106. package/tests/syncDb-types.test.ts +60 -59
  107. package/tests/syncMenu-paths.test.ts +68 -0
  108. package/tests/util.test.ts +42 -41
  109. package/tests/validator-array-number.test.ts +310 -0
  110. package/tests/validator-default.test.ts +373 -0
  111. package/tests/validator.test.ts +271 -266
  112. package/tsconfig.json +4 -5
  113. package/types/api.d.ts +7 -12
  114. package/types/befly.d.ts +60 -13
  115. package/types/cache.d.ts +8 -4
  116. package/types/common.d.ts +17 -9
  117. package/types/context.d.ts +2 -2
  118. package/types/crypto.d.ts +23 -0
  119. package/types/database.d.ts +19 -19
  120. package/types/hook.d.ts +2 -2
  121. package/types/jwt.d.ts +118 -0
  122. package/types/logger.d.ts +30 -0
  123. package/types/plugin.d.ts +4 -4
  124. package/types/redis.d.ts +7 -3
  125. package/types/roleApisCache.ts +23 -0
  126. package/types/sync.d.ts +10 -10
  127. package/types/table.d.ts +50 -9
  128. package/types/validate.d.ts +69 -0
  129. package/utils/addonHelper.ts +90 -0
  130. package/utils/arrayKeysToCamel.ts +18 -0
  131. package/utils/calcPerfTime.ts +13 -0
  132. package/utils/configTypes.ts +3 -0
  133. package/utils/cors.ts +19 -0
  134. package/utils/fieldClear.ts +75 -0
  135. package/utils/genShortId.ts +12 -0
  136. package/utils/getClientIp.ts +45 -0
  137. package/utils/keysToCamel.ts +22 -0
  138. package/utils/keysToSnake.ts +22 -0
  139. package/utils/modules.ts +98 -0
  140. package/utils/pickFields.ts +19 -0
  141. package/utils/process.ts +56 -0
  142. package/utils/regex.ts +225 -0
  143. package/utils/response.ts +115 -0
  144. package/utils/route.ts +23 -0
  145. package/utils/scanConfig.ts +142 -0
  146. package/utils/scanFiles.ts +48 -0
  147. package/.prettierignore +0 -2
  148. package/.prettierrc +0 -12
  149. package/docs/1-/345/237/272/346/234/254/344/273/213/347/273/215.md +0 -35
  150. package/docs/2-/345/210/235/346/255/245/344/275/223/351/252/214.md +0 -64
  151. package/docs/3-/347/254/254/344/270/200/344/270/252/346/216/245/345/217/243.md +0 -46
  152. package/docs/4-/346/223/215/344/275/234/346/225/260/346/215/256/345/272/223.md +0 -172
  153. package/hooks/requestLogger.ts +0 -84
  154. package/types/index.ts +0 -24
  155. package/util.ts +0 -283
@@ -1,97 +1,98 @@
1
- /**
1
+ /**
2
2
  * Cipher 加密工具测试
3
3
  */
4
4
 
5
- import { describe, test, expect, beforeAll } from 'bun:test';
6
- import { Cipher } from '../lib/cipher';
7
- import { writeFileSync, unlinkSync, existsSync, mkdirSync } from 'node:fs';
8
- import { join } from 'node:path';
5
+ import { describe, test, expect, beforeAll } from "bun:test";
6
+ import { writeFileSync, existsSync, mkdirSync } from "node:fs";
7
+ import { join } from "node:path";
9
8
 
10
- describe('Cipher - 哈希功能', () => {
11
- const testData = 'hello world';
9
+ import { Cipher } from "../lib/cipher";
10
+
11
+ describe("Cipher - 哈希功能", () => {
12
+ const testData = "hello world";
12
13
  const testDataBytes = new TextEncoder().encode(testData);
13
14
 
14
- test('MD5 哈希 - 字符串输入', () => {
15
+ test("MD5 哈希 - 字符串输入", () => {
15
16
  const result = Cipher.md5(testData);
16
- expect(result).toBe('5eb63bbbe01eeed093cb22bb8f5acdc3');
17
+ expect(result).toBe("5eb63bbbe01eeed093cb22bb8f5acdc3");
17
18
  expect(result.length).toBe(32);
18
19
  });
19
20
 
20
- test('MD5 哈希 - Uint8Array 输入', () => {
21
+ test("MD5 哈希 - Uint8Array 输入", () => {
21
22
  const result = Cipher.md5(testDataBytes);
22
- expect(result).toBe('5eb63bbbe01eeed093cb22bb8f5acdc3');
23
+ expect(result).toBe("5eb63bbbe01eeed093cb22bb8f5acdc3");
23
24
  });
24
25
 
25
- test('MD5 哈希 - base64 编码', () => {
26
- const result = Cipher.md5(testData, 'base64');
27
- expect(typeof result).toBe('string');
26
+ test("MD5 哈希 - base64 编码", () => {
27
+ const result = Cipher.md5(testData, "base64");
28
+ expect(typeof result).toBe("string");
28
29
  expect(result.length).toBeGreaterThan(0);
29
30
  });
30
31
 
31
- test('SHA1 哈希', () => {
32
+ test("SHA1 哈希", () => {
32
33
  const result = Cipher.sha1(testData);
33
- expect(result).toBe('2aae6c35c94fcfb415dbe95f408b9ce91ee846ed');
34
+ expect(result).toBe("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed");
34
35
  expect(result.length).toBe(40);
35
36
  });
36
37
 
37
- test('SHA256 哈希', () => {
38
+ test("SHA256 哈希", () => {
38
39
  const result = Cipher.sha256(testData);
39
- expect(result).toBe('b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9');
40
+ expect(result).toBe("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9");
40
41
  expect(result.length).toBe(64);
41
42
  });
42
43
 
43
- test('SHA512 哈希', () => {
44
+ test("SHA512 哈希", () => {
44
45
  const result = Cipher.sha512(testData);
45
46
  expect(result.length).toBe(128);
46
- expect(typeof result).toBe('string');
47
+ expect(typeof result).toBe("string");
47
48
  });
48
49
 
49
- test('通用 hash 方法 - SHA256', () => {
50
- const result = Cipher.hash('sha256', testData);
51
- expect(result).toBe('b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9');
50
+ test("通用 hash 方法 - SHA256", () => {
51
+ const result = Cipher.hash("sha256", testData);
52
+ expect(result).toBe("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9");
52
53
  });
53
54
 
54
- test('通用 hash 方法 - MD5', () => {
55
- const result = Cipher.hash('md5', testData);
56
- expect(result).toBe('5eb63bbbe01eeed093cb22bb8f5acdc3');
55
+ test("通用 hash 方法 - MD5", () => {
56
+ const result = Cipher.hash("md5", testData);
57
+ expect(result).toBe("5eb63bbbe01eeed093cb22bb8f5acdc3");
57
58
  });
58
59
  });
59
60
 
60
- describe('Cipher - HMAC 签名', () => {
61
- const key = 'secret-key';
62
- const data = 'test data';
61
+ describe("Cipher - HMAC 签名", () => {
62
+ const key = "secret-key";
63
+ const data = "test data";
63
64
 
64
- test('HMAC-MD5', () => {
65
+ test("HMAC-MD5", () => {
65
66
  const result = Cipher.hmacMd5(key, data);
66
67
  expect(result.length).toBe(32);
67
- expect(typeof result).toBe('string');
68
+ expect(typeof result).toBe("string");
68
69
  });
69
70
 
70
- test('HMAC-SHA1', () => {
71
+ test("HMAC-SHA1", () => {
71
72
  const result = Cipher.hmacSha1(key, data);
72
73
  expect(result.length).toBe(40);
73
- expect(typeof result).toBe('string');
74
+ expect(typeof result).toBe("string");
74
75
  });
75
76
 
76
- test('HMAC-SHA256', () => {
77
+ test("HMAC-SHA256", () => {
77
78
  const result = Cipher.hmacSha256(key, data);
78
79
  expect(result.length).toBe(64);
79
- expect(typeof result).toBe('string');
80
+ expect(typeof result).toBe("string");
80
81
  });
81
82
 
82
- test('HMAC-SHA512', () => {
83
+ test("HMAC-SHA512", () => {
83
84
  const result = Cipher.hmacSha512(key, data);
84
85
  expect(result.length).toBe(128);
85
- expect(typeof result).toBe('string');
86
+ expect(typeof result).toBe("string");
86
87
  });
87
88
 
88
- test('通用 HMAC 方法', () => {
89
- const result1 = Cipher.hmac('sha256', key, data);
89
+ test("通用 HMAC 方法", () => {
90
+ const result1 = Cipher.hmac("sha256", key, data);
90
91
  const result2 = Cipher.hmacSha256(key, data);
91
92
  expect(result1).toBe(result2);
92
93
  });
93
94
 
94
- test('HMAC - Uint8Array 输入', () => {
95
+ test("HMAC - Uint8Array 输入", () => {
95
96
  const keyBytes = new TextEncoder().encode(key);
96
97
  const dataBytes = new TextEncoder().encode(data);
97
98
  const result = Cipher.hmacSha256(keyBytes, dataBytes);
@@ -99,150 +100,150 @@ describe('Cipher - HMAC 签名', () => {
99
100
  });
100
101
  });
101
102
 
102
- describe('Cipher - 密码加密', () => {
103
- const password = 'MySecurePassword123!';
103
+ describe("Cipher - 密码加密", () => {
104
+ const password = "MySecurePassword123!";
104
105
 
105
- test('密码哈希', async () => {
106
+ test("密码哈希", async () => {
106
107
  const hash = await Cipher.hashPassword(password);
107
108
  expect(hash).toBeDefined();
108
109
  expect(hash.length).toBeGreaterThan(0);
109
110
  expect(hash).not.toBe(password);
110
111
  });
111
112
 
112
- test('密码验证 - 正确密码', async () => {
113
+ test("密码验证 - 正确密码", async () => {
113
114
  const hash = await Cipher.hashPassword(password);
114
115
  const isValid = await Cipher.verifyPassword(password, hash);
115
116
  expect(isValid).toBe(true);
116
117
  });
117
118
 
118
- test('密码验证 - 错误密码', async () => {
119
+ test("密码验证 - 错误密码", async () => {
119
120
  const hash = await Cipher.hashPassword(password);
120
- const isValid = await Cipher.verifyPassword('wrong-password', hash);
121
+ const isValid = await Cipher.verifyPassword("wrong-password", hash);
121
122
  expect(isValid).toBe(false);
122
123
  });
123
124
 
124
- test('相同密码生成不同哈希', async () => {
125
+ test("相同密码生成不同哈希", async () => {
125
126
  const hash1 = await Cipher.hashPassword(password);
126
127
  const hash2 = await Cipher.hashPassword(password);
127
128
  expect(hash1).not.toBe(hash2);
128
129
  });
129
130
  });
130
131
 
131
- describe('Cipher - Base64 编码', () => {
132
- const original = 'Hello, 世界!';
132
+ describe("Cipher - Base64 编码", () => {
133
+ const original = "Hello, 世界!";
133
134
 
134
- test('Base64 编码', () => {
135
+ test("Base64 编码", () => {
135
136
  const encoded = Cipher.base64Encode(original);
136
- expect(encoded).toBe('SGVsbG8sIOS4lueVjCE=');
137
+ expect(encoded).toBe("SGVsbG8sIOS4lueVjCE=");
137
138
  });
138
139
 
139
- test('Base64 解码', () => {
140
- const encoded = 'SGVsbG8sIOS4lueVjCE=';
140
+ test("Base64 解码", () => {
141
+ const encoded = "SGVsbG8sIOS4lueVjCE=";
141
142
  const decoded = Cipher.base64Decode(encoded);
142
143
  expect(decoded).toBe(original);
143
144
  });
144
145
 
145
- test('Base64 编码解码循环', () => {
146
+ test("Base64 编码解码循环", () => {
146
147
  const encoded = Cipher.base64Encode(original);
147
148
  const decoded = Cipher.base64Decode(encoded);
148
149
  expect(decoded).toBe(original);
149
150
  });
150
151
 
151
- test('Base64 编码空字符串', () => {
152
- const encoded = Cipher.base64Encode('');
153
- expect(encoded).toBe('');
152
+ test("Base64 编码空字符串", () => {
153
+ const encoded = Cipher.base64Encode("");
154
+ expect(encoded).toBe("");
154
155
  });
155
156
  });
156
157
 
157
- describe('Cipher - 随机字符串', () => {
158
- test('生成指定长度的随机字符串', () => {
158
+ describe("Cipher - 随机字符串", () => {
159
+ test("生成指定长度的随机字符串", () => {
159
160
  const result = Cipher.randomString(16);
160
161
  expect(result.length).toBe(16);
161
162
  expect(/^[0-9a-f]+$/.test(result)).toBe(true);
162
163
  });
163
164
 
164
- test('生成不同的随机字符串', () => {
165
+ test("生成不同的随机字符串", () => {
165
166
  const result1 = Cipher.randomString(32);
166
167
  const result2 = Cipher.randomString(32);
167
168
  expect(result1).not.toBe(result2);
168
169
  });
169
170
 
170
- test('生成奇数长度的随机字符串', () => {
171
+ test("生成奇数长度的随机字符串", () => {
171
172
  const result = Cipher.randomString(15);
172
173
  expect(result.length).toBe(15);
173
174
  });
174
175
 
175
- test('生成 0 长度字符串', () => {
176
+ test("生成 0 长度字符串", () => {
176
177
  const result = Cipher.randomString(0);
177
- expect(result).toBe('');
178
+ expect(result).toBe("");
178
179
  });
179
180
  });
180
181
 
181
- describe('Cipher - 文件哈希', () => {
182
- const testFilePath = join(process.cwd(), 'temp', 'cipher-test-file.txt');
183
- const testContent = 'Test file content for hashing';
182
+ describe("Cipher - 文件哈希", () => {
183
+ const testFilePath = join(process.cwd(), "temp", "cipher-test-file.txt");
184
+ const testContent = "Test file content for hashing";
184
185
 
185
186
  beforeAll(() => {
186
- const tempDir = join(process.cwd(), 'temp');
187
+ const tempDir = join(process.cwd(), "temp");
187
188
  if (!existsSync(tempDir)) {
188
189
  mkdirSync(tempDir, { recursive: true });
189
190
  }
190
- writeFileSync(testFilePath, testContent, 'utf8');
191
+ writeFileSync(testFilePath, testContent, "utf8");
191
192
  });
192
193
 
193
- test('SHA256 文件哈希', async () => {
194
- const result = await Cipher.hashFile(testFilePath, 'sha256');
194
+ test("SHA256 文件哈希", async () => {
195
+ const result = await Cipher.hashFile(testFilePath, "sha256");
195
196
  expect(result.length).toBe(64);
196
- expect(typeof result).toBe('string');
197
+ expect(typeof result).toBe("string");
197
198
  });
198
199
 
199
- test('MD5 文件哈希', async () => {
200
- const result = await Cipher.hashFile(testFilePath, 'md5');
200
+ test("MD5 文件哈希", async () => {
201
+ const result = await Cipher.hashFile(testFilePath, "md5");
201
202
  expect(result.length).toBe(32);
202
203
  });
203
204
 
204
- test('文件哈希与内容哈希一致', async () => {
205
- const fileHash = await Cipher.hashFile(testFilePath, 'sha256');
205
+ test("文件哈希与内容哈希一致", async () => {
206
+ const fileHash = await Cipher.hashFile(testFilePath, "sha256");
206
207
  const contentHash = Cipher.sha256(testContent);
207
208
  expect(fileHash).toBe(contentHash);
208
209
  });
209
210
 
210
- test('文件哈希 - base64 编码', async () => {
211
- const result = await Cipher.hashFile(testFilePath, 'sha256', 'base64');
212
- expect(typeof result).toBe('string');
211
+ test("文件哈希 - base64 编码", async () => {
212
+ const result = await Cipher.hashFile(testFilePath, "sha256", "base64");
213
+ expect(typeof result).toBe("string");
213
214
  expect(result.length).toBeGreaterThan(0);
214
215
  });
215
216
  });
216
217
 
217
- describe('Cipher - 快速哈希', () => {
218
- const testData = 'quick hash test';
218
+ describe("Cipher - 快速哈希", () => {
219
+ const testData = "quick hash test";
219
220
 
220
- test('快速哈希 - 字符串输入', () => {
221
+ test("快速哈希 - 字符串输入", () => {
221
222
  const result = Cipher.fastHash(testData);
222
- expect(typeof result).toBe('number');
223
+ expect(typeof result).toBe("number");
223
224
  expect(result).toBeGreaterThan(0);
224
225
  });
225
226
 
226
- test('快速哈希 - Uint8Array 输入', () => {
227
+ test("快速哈希 - Uint8Array 输入", () => {
227
228
  const bytes = new TextEncoder().encode(testData);
228
229
  const result = Cipher.fastHash(bytes);
229
- expect(typeof result).toBe('number');
230
+ expect(typeof result).toBe("number");
230
231
  });
231
232
 
232
- test('快速哈希 - 相同输入产生相同哈希', () => {
233
+ test("快速哈希 - 相同输入产生相同哈希", () => {
233
234
  const result1 = Cipher.fastHash(testData);
234
235
  const result2 = Cipher.fastHash(testData);
235
236
  expect(result1).toBe(result2);
236
237
  });
237
238
 
238
- test('快速哈希 - 不同 seed 产生不同结果', () => {
239
+ test("快速哈希 - 不同 seed 产生不同结果", () => {
239
240
  const result1 = Cipher.fastHash(testData, 0);
240
241
  const result2 = Cipher.fastHash(testData, 1);
241
242
  expect(result1).not.toBe(result2);
242
243
  });
243
244
 
244
- test('快速哈希 - 空字符串', () => {
245
- const result = Cipher.fastHash('');
246
- expect(typeof result).toBe('number');
245
+ test("快速哈希 - 空字符串", () => {
246
+ const result = Cipher.fastHash("");
247
+ expect(typeof result).toBe("number");
247
248
  });
248
249
  });