befly 3.9.37 → 3.9.39

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 +38 -39
  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} +225 -235
  8. package/docs/cipher.md +71 -69
  9. package/docs/database.md +155 -153
  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} +7 -7
  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 +15 -7
  34. package/lib/asyncContext.ts +43 -0
  35. package/lib/cacheHelper.ts +212 -81
  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 +211 -109
  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 +53 -47
  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 -54
  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 -66
  75. package/sync/syncMenu.ts +190 -57
  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
@@ -3,9 +3,10 @@
3
3
  * 测试表字段查询、Redis 缓存、SQL 语法修复等功能
4
4
  */
5
5
 
6
- import { test, expect, mock } from 'bun:test';
7
- import { DbHelper } from '../lib/dbHelper.js';
8
- import { RedisKeys } from 'befly-shared/redisKeys';
6
+ import { test, expect, mock } from "bun:test";
7
+
8
+ import { CacheKeys } from "../lib/cacheKeys.js";
9
+ import { DbHelper } from "../lib/dbHelper.js";
9
10
 
10
11
  // 创建 Mock Befly 上下文
11
12
  function createMockBefly(sqlMock: any, redisMock?: any) {
@@ -19,13 +20,13 @@ function createMockBefly(sqlMock: any, redisMock?: any) {
19
20
  };
20
21
  }
21
22
 
22
- test('getTableColumns - 正常查询表字段', async () => {
23
- const mockColumns = [{ Field: 'id' }, { Field: 'username' }, { Field: 'email' }, { Field: 'created_at' }];
23
+ test("getTableColumns - 正常查询表字段", async () => {
24
+ const mockColumns = [{ Field: "id" }, { Field: "username" }, { Field: "email" }, { Field: "created_at" }];
24
25
 
25
26
  const sqlMock = {
26
27
  unsafe: mock(async (sql: string) => {
27
28
  // 验证 SQL 语法正确(使用反引号)
28
- expect(sql).toBe('SHOW COLUMNS FROM `users`');
29
+ expect(sql).toBe("SHOW COLUMNS FROM `users`");
29
30
  return mockColumns;
30
31
  })
31
32
  };
@@ -39,16 +40,16 @@ test('getTableColumns - 正常查询表字段', async () => {
39
40
  const befly = createMockBefly(sqlMock, redisMock);
40
41
  const dbHelper = new DbHelper(befly as any, sqlMock);
41
42
 
42
- const columns = await (dbHelper as any).getTableColumns('users');
43
+ const columns = await (dbHelper as any).getTableColumns("users");
43
44
 
44
- expect(columns).toEqual(['id', 'username', 'email', 'created_at']);
45
+ expect(columns).toEqual(["id", "username", "email", "created_at"]);
45
46
  expect(sqlMock.unsafe).toHaveBeenCalledTimes(1);
46
- expect(redisMock.getObject).toHaveBeenCalledWith(RedisKeys.tableColumns('users'));
47
+ expect(redisMock.getObject).toHaveBeenCalledWith(CacheKeys.tableColumns("users"));
47
48
  expect(redisMock.setObject).toHaveBeenCalled();
48
49
  });
49
50
 
50
- test('getTableColumns - Redis 缓存命中', async () => {
51
- const cachedColumns = ['id', 'name', 'email'];
51
+ test("getTableColumns - Redis 缓存命中", async () => {
52
+ const cachedColumns = ["id", "name", "email"];
52
53
  const redisMock = {
53
54
  getObject: mock(async () => cachedColumns),
54
55
  setObject: mock(async () => true),
@@ -57,22 +58,22 @@ test('getTableColumns - Redis 缓存命中', async () => {
57
58
 
58
59
  const sqlMock = {
59
60
  unsafe: mock(async () => {
60
- throw new Error('不应该执行 SQL 查询');
61
+ throw new Error("不应该执行 SQL 查询");
61
62
  })
62
63
  };
63
64
 
64
65
  const befly = createMockBefly(sqlMock, redisMock);
65
66
  const dbHelper = new DbHelper(befly as any, sqlMock);
66
67
 
67
- const columns = await (dbHelper as any).getTableColumns('users');
68
+ const columns = await (dbHelper as any).getTableColumns("users");
68
69
 
69
70
  expect(columns).toEqual(cachedColumns);
70
- expect(redisMock.getObject).toHaveBeenCalledWith(RedisKeys.tableColumns('users'));
71
+ expect(redisMock.getObject).toHaveBeenCalledWith(CacheKeys.tableColumns("users"));
71
72
  expect(sqlMock.unsafe).not.toHaveBeenCalled(); // SQL 不应该被调用
72
73
  expect(redisMock.setObject).not.toHaveBeenCalled(); // 不需要写缓存
73
74
  });
74
75
 
75
- test('getTableColumns - 表不存在错误', async () => {
76
+ test("getTableColumns - 表不存在错误", async () => {
76
77
  const sqlMock = {
77
78
  unsafe: mock(async () => []) // 返回空结果
78
79
  };
@@ -87,16 +88,16 @@ test('getTableColumns - 表不存在错误', async () => {
87
88
  const dbHelper = new DbHelper(befly as any, sqlMock);
88
89
 
89
90
  try {
90
- await (dbHelper as any).getTableColumns('non_existent_table');
91
+ await (dbHelper as any).getTableColumns("non_existent_table");
91
92
  expect(true).toBe(false); // 不应该执行到这里
92
93
  } catch (error: any) {
93
- expect(error.message).toContain('表 non_existent_table 不存在或没有字段');
94
+ expect(error.message).toContain("表 non_existent_table 不存在或没有字段");
94
95
  }
95
96
  });
96
97
 
97
- test('getTableColumns - SQL 语法使用反引号', async () => {
98
- const mockColumns = [{ Field: 'id' }];
99
- let capturedSql = '';
98
+ test("getTableColumns - SQL 语法使用反引号", async () => {
99
+ const mockColumns = [{ Field: "id" }];
100
+ let capturedSql = "";
100
101
 
101
102
  const sqlMock = {
102
103
  unsafe: mock(async (sql: string) => {
@@ -108,16 +109,16 @@ test('getTableColumns - SQL 语法使用反引号', async () => {
108
109
  const befly = createMockBefly(sqlMock);
109
110
  const dbHelper = new DbHelper(befly as any, sqlMock);
110
111
 
111
- await (dbHelper as any).getTableColumns('addon_admin_user');
112
+ await (dbHelper as any).getTableColumns("addon_admin_user");
112
113
 
113
114
  // 验证 SQL 语法
114
- expect(capturedSql).toBe('SHOW COLUMNS FROM `addon_admin_user`');
115
- expect(capturedSql).not.toContain('??'); // 不应该包含占位符
116
- expect(capturedSql).toContain('`'); // 应该使用反引号
115
+ expect(capturedSql).toBe("SHOW COLUMNS FROM `addon_admin_user`");
116
+ expect(capturedSql).not.toContain("??"); // 不应该包含占位符
117
+ expect(capturedSql).toContain("`"); // 应该使用反引号
117
118
  });
118
119
 
119
- test('getTableColumns - 表名特殊字符处理', async () => {
120
- const mockColumns = [{ Field: 'id' }];
120
+ test("getTableColumns - 表名特殊字符处理", async () => {
121
+ const mockColumns = [{ Field: "id" }];
121
122
  const sqlMock = {
122
123
  unsafe: mock(async () => mockColumns)
123
124
  };
@@ -126,16 +127,16 @@ test('getTableColumns - 表名特殊字符处理', async () => {
126
127
  const dbHelper = new DbHelper(befly as any, sqlMock);
127
128
 
128
129
  // 测试下划线表名
129
- await (dbHelper as any).getTableColumns('addon_admin_user');
130
- expect(sqlMock.unsafe).toHaveBeenLastCalledWith('SHOW COLUMNS FROM `addon_admin_user`');
130
+ await (dbHelper as any).getTableColumns("addon_admin_user");
131
+ expect(sqlMock.unsafe).toHaveBeenLastCalledWith("SHOW COLUMNS FROM `addon_admin_user`");
131
132
 
132
133
  // 测试普通表名
133
- await (dbHelper as any).getTableColumns('users');
134
- expect(sqlMock.unsafe).toHaveBeenLastCalledWith('SHOW COLUMNS FROM `users`');
134
+ await (dbHelper as any).getTableColumns("users");
135
+ expect(sqlMock.unsafe).toHaveBeenLastCalledWith("SHOW COLUMNS FROM `users`");
135
136
  });
136
137
 
137
- test('getTableColumns - 缓存键格式正确', async () => {
138
- const mockColumns = [{ Field: 'id' }];
138
+ test("getTableColumns - 缓存键格式正确", async () => {
139
+ const mockColumns = [{ Field: "id" }];
139
140
  const sqlMock = {
140
141
  unsafe: mock(async () => mockColumns)
141
142
  };
@@ -144,7 +145,7 @@ test('getTableColumns - 缓存键格式正确', async () => {
144
145
  getObject: mock(async () => null),
145
146
  setObject: mock(async (key: string, value: any, seconds: number) => {
146
147
  // 验证缓存键格式
147
- expect(key).toBe(RedisKeys.tableColumns('test_table'));
148
+ expect(key).toBe(CacheKeys.tableColumns("test_table"));
148
149
  // 验证缓存值格式
149
150
  expect(Array.isArray(value)).toBe(true);
150
151
  // 验证过期时间
@@ -157,13 +158,13 @@ test('getTableColumns - 缓存键格式正确', async () => {
157
158
  const befly = createMockBefly(sqlMock, redisMock);
158
159
  const dbHelper = new DbHelper(befly as any, sqlMock);
159
160
 
160
- await (dbHelper as any).getTableColumns('test_table');
161
+ await (dbHelper as any).getTableColumns("test_table");
161
162
 
162
163
  expect(redisMock.setObject).toHaveBeenCalled();
163
164
  });
164
165
 
165
- test('getTableColumns - 多次调用相同表(缓存效果)', async () => {
166
- const mockColumns = [{ Field: 'id' }, { Field: 'name' }];
166
+ test("getTableColumns - 多次调用相同表(缓存效果)", async () => {
167
+ const mockColumns = [{ Field: "id" }, { Field: "name" }];
167
168
  let sqlCallCount = 0;
168
169
 
169
170
  const sqlMock = {
@@ -187,30 +188,30 @@ test('getTableColumns - 多次调用相同表(缓存效果)', async () => {
187
188
  const dbHelper = new DbHelper(befly as any, sqlMock);
188
189
 
189
190
  // 第一次调用 - 应该查询数据库
190
- const columns1 = await (dbHelper as any).getTableColumns('users');
191
- expect(columns1).toEqual(['id', 'name']);
191
+ const columns1 = await (dbHelper as any).getTableColumns("users");
192
+ expect(columns1).toEqual(["id", "name"]);
192
193
  expect(sqlCallCount).toBe(1);
193
194
 
194
195
  // 第二次调用 - 应该从缓存读取
195
- const columns2 = await (dbHelper as any).getTableColumns('users');
196
- expect(columns2).toEqual(['id', 'name']);
196
+ const columns2 = await (dbHelper as any).getTableColumns("users");
197
+ expect(columns2).toEqual(["id", "name"]);
197
198
  expect(sqlCallCount).toBe(1); // SQL 调用次数不变
198
199
 
199
200
  // 第三次调用 - 仍然从缓存读取
200
- const columns3 = await (dbHelper as any).getTableColumns('users');
201
- expect(columns3).toEqual(['id', 'name']);
201
+ const columns3 = await (dbHelper as any).getTableColumns("users");
202
+ expect(columns3).toEqual(["id", "name"]);
202
203
  expect(sqlCallCount).toBe(1);
203
204
  });
204
205
 
205
- test('getTableColumns - Redis 错误处理', async () => {
206
- const mockColumns = [{ Field: 'id' }];
206
+ test("getTableColumns - Redis 错误处理", async () => {
207
+ const mockColumns = [{ Field: "id" }];
207
208
  const sqlMock = {
208
209
  unsafe: mock(async () => mockColumns)
209
210
  };
210
211
 
211
212
  const redisMock = {
212
213
  getObject: mock(async () => {
213
- throw new Error('Redis 连接失败');
214
+ throw new Error("Redis 连接失败");
214
215
  }),
215
216
  setObject: mock(async () => true),
216
217
  del: mock(async () => 1)
@@ -220,19 +221,19 @@ test('getTableColumns - Redis 错误处理', async () => {
220
221
  const dbHelper = new DbHelper(befly as any, sqlMock);
221
222
 
222
223
  try {
223
- await (dbHelper as any).getTableColumns('users');
224
+ await (dbHelper as any).getTableColumns("users");
224
225
  expect(true).toBe(false); // 不应该执行到这里
225
226
  } catch (error: any) {
226
- expect(error.message).toContain('Redis 连接失败');
227
+ expect(error.message).toContain("Redis 连接失败");
227
228
  }
228
229
  });
229
230
 
230
- test('getTableColumns - 字段映射正确性', async () => {
231
+ test("getTableColumns - 字段映射正确性", async () => {
231
232
  const mockColumns = [
232
- { Field: 'id', Type: 'int' },
233
- { Field: 'user_name', Type: 'varchar' },
234
- { Field: 'created_at', Type: 'timestamp' },
235
- { Field: 'is_active', Type: 'tinyint' }
233
+ { Field: "id", Type: "int" },
234
+ { Field: "user_name", Type: "varchar" },
235
+ { Field: "created_at", Type: "timestamp" },
236
+ { Field: "is_active", Type: "tinyint" }
236
237
  ];
237
238
 
238
239
  const sqlMock = {
@@ -242,10 +243,10 @@ test('getTableColumns - 字段映射正确性', async () => {
242
243
  const befly = createMockBefly(sqlMock);
243
244
  const dbHelper = new DbHelper(befly as any, sqlMock);
244
245
 
245
- const columns = await (dbHelper as any).getTableColumns('users');
246
+ const columns = await (dbHelper as any).getTableColumns("users");
246
247
 
247
248
  // 验证只提取 Field 字段
248
- expect(columns).toEqual(['id', 'user_name', 'created_at', 'is_active']);
249
+ expect(columns).toEqual(["id", "user_name", "created_at", "is_active"]);
249
250
  expect(columns.length).toBe(4);
250
- expect(columns.every((col: string) => typeof col === 'string')).toBe(true);
251
+ expect(columns.every((col: string) => typeof col === "string")).toBe(true);
251
252
  });
@@ -3,11 +3,12 @@
3
3
  * 测试 SQL 执行、错误处理等功能
4
4
  */
5
5
 
6
- import { test, expect, mock } from 'bun:test';
7
- import { DbHelper } from '../lib/dbHelper.js';
6
+ import { test, expect, mock } from "bun:test";
7
+
8
+ import { DbHelper } from "../lib/dbHelper.js";
8
9
 
9
10
  // 创建 Mock Befly 上下文
10
- function createMockBefly(sqlMock: any) {
11
+ function createMockBefly() {
11
12
  return {
12
13
  redis: {
13
14
  get: mock(async () => null),
@@ -18,73 +19,73 @@ function createMockBefly(sqlMock: any) {
18
19
  };
19
20
  }
20
21
 
21
- test('executeWithConn - 正常执行(无参数)', async () => {
22
- const mockResult = [{ id: 1, name: 'test' }];
22
+ test("executeWithConn - 正常执行(无参数)", async () => {
23
+ const mockResult = [{ id: 1, name: "test" }];
23
24
  const sqlMock = {
24
25
  unsafe: mock(async () => mockResult)
25
26
  };
26
27
 
27
- const befly = createMockBefly(sqlMock);
28
+ const befly = createMockBefly();
28
29
  const dbHelper = new DbHelper(befly as any, sqlMock);
29
30
 
30
31
  // 使用反射访问私有方法
31
- const result = await (dbHelper as any).executeWithConn('SELECT * FROM users');
32
+ const result = await (dbHelper as any).executeWithConn("SELECT * FROM users");
32
33
 
33
34
  expect(result).toEqual(mockResult);
34
- expect(sqlMock.unsafe).toHaveBeenCalledWith('SELECT * FROM users');
35
+ expect(sqlMock.unsafe).toHaveBeenCalledWith("SELECT * FROM users");
35
36
  });
36
37
 
37
- test('executeWithConn - 正常执行(带参数)', async () => {
38
- const mockResult = [{ id: 1, email: 'test@example.com' }];
38
+ test("executeWithConn - 正常执行(带参数)", async () => {
39
+ const mockResult = [{ id: 1, email: "test@example.com" }];
39
40
  const sqlMock = {
40
41
  unsafe: mock(async () => mockResult)
41
42
  };
42
43
 
43
- const befly = createMockBefly(sqlMock);
44
+ const befly = createMockBefly();
44
45
  const dbHelper = new DbHelper(befly as any, sqlMock);
45
46
 
46
- const result = await (dbHelper as any).executeWithConn('SELECT * FROM users WHERE id = ?', [1]);
47
+ const result = await (dbHelper as any).executeWithConn("SELECT * FROM users WHERE id = ?", [1]);
47
48
 
48
49
  expect(result).toEqual(mockResult);
49
- expect(sqlMock.unsafe).toHaveBeenCalledWith('SELECT * FROM users WHERE id = ?', [1]);
50
+ expect(sqlMock.unsafe).toHaveBeenCalledWith("SELECT * FROM users WHERE id = ?", [1]);
50
51
  });
51
52
 
52
- test('executeWithConn - SQL 错误捕获', async () => {
53
- const sqlError = new Error('You have an error in your SQL syntax');
53
+ test("executeWithConn - SQL 错误捕获", async () => {
54
+ const sqlError = new Error("You have an error in your SQL syntax");
54
55
  const sqlMock = {
55
56
  unsafe: mock(async () => {
56
57
  throw sqlError;
57
58
  })
58
59
  };
59
60
 
60
- const befly = createMockBefly(sqlMock);
61
+ const befly = createMockBefly();
61
62
  const dbHelper = new DbHelper(befly as any, sqlMock);
62
63
 
63
64
  try {
64
- await (dbHelper as any).executeWithConn('SELECT * FROM invalid_table');
65
+ await (dbHelper as any).executeWithConn("SELECT * FROM invalid_table");
65
66
  expect(true).toBe(false); // 不应该执行到这里
66
67
  } catch (error: any) {
67
68
  // 验证错误信息
68
- expect(error.message).toContain('SQL执行失败');
69
+ expect(error.message).toContain("SQL执行失败");
69
70
  expect(error.originalError).toBe(sqlError);
70
- expect(error.sql).toBe('SELECT * FROM invalid_table');
71
+ expect(error.sql).toBe("SELECT * FROM invalid_table");
71
72
  expect(error.params).toEqual([]);
72
73
  expect(error.duration).toBeGreaterThanOrEqual(0);
73
74
  }
74
75
  });
75
76
 
76
- test('executeWithConn - 错误信息包含完整信息', async () => {
77
+ test("executeWithConn - 错误信息包含完整信息", async () => {
77
78
  const sqlMock = {
78
79
  unsafe: mock(async () => {
79
80
  throw new Error('Syntax error near "??"');
80
81
  })
81
82
  };
82
83
 
83
- const befly = createMockBefly(sqlMock);
84
+ const befly = createMockBefly();
84
85
  const dbHelper = new DbHelper(befly as any, sqlMock);
85
86
 
86
- const testSql = 'SHOW COLUMNS FROM ??';
87
- const testParams = ['users'];
87
+ const testSql = "SHOW COLUMNS FROM ??";
88
+ const testParams = ["users"];
88
89
 
89
90
  try {
90
91
  await (dbHelper as any).executeWithConn(testSql, testParams);
@@ -92,20 +93,20 @@ test('executeWithConn - 错误信息包含完整信息', async () => {
92
93
  // 验证增强的错误对象
93
94
  expect(error.sql).toBe(testSql);
94
95
  expect(error.params).toEqual(testParams);
95
- expect(typeof error.duration).toBe('number');
96
+ expect(typeof error.duration).toBe("number");
96
97
  expect(error.originalError.message).toBe('Syntax error near "??"');
97
98
  }
98
99
  });
99
100
 
100
- test('executeWithConn - 超长 SQL 保留在错误对象中', async () => {
101
- const longSql = 'SELECT * FROM users WHERE ' + 'id = ? AND '.repeat(50) + 'name = ?';
101
+ test("executeWithConn - 超长 SQL 保留在错误对象中", async () => {
102
+ const longSql = "SELECT * FROM users WHERE " + "id = ? AND ".repeat(50) + "name = ?";
102
103
  const sqlMock = {
103
104
  unsafe: mock(async () => {
104
- throw new Error('Test error');
105
+ throw new Error("Test error");
105
106
  })
106
107
  };
107
108
 
108
- const befly = createMockBefly(sqlMock);
109
+ const befly = createMockBefly();
109
110
  const dbHelper = new DbHelper(befly as any, sqlMock);
110
111
 
111
112
  try {
@@ -117,7 +118,7 @@ test('executeWithConn - 超长 SQL 保留在错误对象中', async () => {
117
118
  }
118
119
  });
119
120
 
120
- test('executeWithConn - 慢查询检测(>1000ms)', async () => {
121
+ test("executeWithConn - 慢查询检测(>1000ms)", async () => {
121
122
  const mockResult = [{ id: 1 }];
122
123
  const sqlMock = {
123
124
  unsafe: mock(async () => {
@@ -127,60 +128,60 @@ test('executeWithConn - 慢查询检测(>1000ms)', async () => {
127
128
  })
128
129
  };
129
130
 
130
- const befly = createMockBefly(sqlMock);
131
+ const befly = createMockBefly();
131
132
  const dbHelper = new DbHelper(befly as any, sqlMock);
132
133
 
133
- const result = await (dbHelper as any).executeWithConn('SELECT SLEEP(1)');
134
+ const result = await (dbHelper as any).executeWithConn("SELECT SLEEP(1)");
134
135
 
135
136
  // 功能仍正常返回结果
136
137
  expect(result).toEqual(mockResult);
137
138
  });
138
139
 
139
- test('executeWithConn - 数据库未连接错误', async () => {
140
+ test("executeWithConn - 数据库未连接错误", async () => {
140
141
  const befly = createMockBefly(null);
141
142
  const dbHelper = new DbHelper(befly as any, null); // 没有 sql 实例
142
143
 
143
144
  try {
144
- await (dbHelper as any).executeWithConn('SELECT * FROM users');
145
+ await (dbHelper as any).executeWithConn("SELECT * FROM users");
145
146
  expect(true).toBe(false); // 不应该执行到这里
146
147
  } catch (error: any) {
147
- expect(error.message).toBe('数据库连接未初始化');
148
+ expect(error.message).toBe("数据库连接未初始化");
148
149
  }
149
150
  });
150
151
 
151
- test('executeWithConn - 空参数数组', async () => {
152
+ test("executeWithConn - 空参数数组", async () => {
152
153
  const mockResult = [{ count: 10 }];
153
154
  const sqlMock = {
154
155
  unsafe: mock(async () => mockResult)
155
156
  };
156
157
 
157
- const befly = createMockBefly(sqlMock);
158
+ const befly = createMockBefly();
158
159
  const dbHelper = new DbHelper(befly as any, sqlMock);
159
160
 
160
- const result = await (dbHelper as any).executeWithConn('SELECT COUNT(*) as count FROM users', []);
161
+ const result = await (dbHelper as any).executeWithConn("SELECT COUNT(*) as count FROM users", []);
161
162
 
162
163
  expect(result).toEqual(mockResult);
163
164
  // 空数组应该走 else 分支(不传参数)
164
- expect(sqlMock.unsafe).toHaveBeenCalledWith('SELECT COUNT(*) as count FROM users');
165
+ expect(sqlMock.unsafe).toHaveBeenCalledWith("SELECT COUNT(*) as count FROM users");
165
166
  });
166
167
 
167
- test('executeWithConn - 复杂参数处理', async () => {
168
+ test("executeWithConn - 复杂参数处理", async () => {
168
169
  const sqlMock = {
169
170
  unsafe: mock(async () => {
170
- throw new Error('Test error');
171
+ throw new Error("Test error");
171
172
  })
172
173
  };
173
174
 
174
- const befly = createMockBefly(sqlMock);
175
+ const befly = createMockBefly();
175
176
  const dbHelper = new DbHelper(befly as any, sqlMock);
176
177
 
177
- const complexParams = [1, 'test', { nested: 'object' }, [1, 2, 3], null, undefined];
178
+ const complexParams = [1, "test", { nested: "object" }, [1, 2, 3], null, undefined];
178
179
 
179
180
  try {
180
- await (dbHelper as any).executeWithConn('SELECT ?', complexParams);
181
+ await (dbHelper as any).executeWithConn("SELECT ?", complexParams);
181
182
  } catch (error: any) {
182
183
  // 验证参数被正确保存
183
184
  expect(error.params).toEqual(complexParams);
184
- expect(error.sql).toBe('SELECT ?');
185
+ expect(error.sql).toBe("SELECT ?");
185
186
  }
186
187
  });