befly 3.9.38 → 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 +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 +7 -7
  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
package/docs/database.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  > 本文档详细介绍 Befly 框架的数据库操作 API,包括 CRUD 操作、事务、条件查询等。
4
4
 
5
+ > 本文档已迁移到:[`./plugins/database.md`](./plugins/database.md)
6
+
5
7
  ## 目录
6
8
 
7
9
  - [Befly 数据库操作指南](#befly-数据库操作指南)
@@ -73,7 +75,7 @@
73
75
  // 在 API handler 中使用
74
76
  handler: async (befly, ctx) => {
75
77
  const user = await befly.db.getOne({
76
- table: 'user',
78
+ table: "user",
77
79
  where: { id: 1 }
78
80
  });
79
81
  };
@@ -100,13 +102,13 @@ handler: async (befly, ctx) => {
100
102
  ```typescript
101
103
  // 用户提交的数据可能部分字段为空
102
104
  await befly.db.insData({
103
- table: 'user',
105
+ table: "user",
104
106
  data: {
105
- username: 'john',
106
- email: 'john@example.com',
107
+ username: "john",
108
+ email: "john@example.com",
107
109
  phone: undefined, // ❌ 自动忽略,不会写入
108
110
  avatar: null, // ❌ 自动忽略,不会写入
109
- nickname: '' // ✅ 空字符串会写入(不是 null/undefined)
111
+ nickname: "" // ✅ 空字符串会写入(不是 null/undefined)
110
112
  }
111
113
  });
112
114
  // 实际 SQL: INSERT INTO user (username, email, nickname, ...) VALUES ('john', 'john@example.com', '', ...)
@@ -117,7 +119,7 @@ await befly.db.insData({
117
119
  ```typescript
118
120
  // 只更新用户提交的字段
119
121
  await befly.db.updData({
120
- table: 'user',
122
+ table: "user",
121
123
  data: {
122
124
  nickname: ctx.body.nickname, // 如果用户传了值,会更新
123
125
  avatar: ctx.body.avatar, // 如果为 undefined,自动忽略
@@ -133,7 +135,7 @@ await befly.db.updData({
133
135
  ```typescript
134
136
  // 条件筛选:用户可能只传部分筛选条件
135
137
  const result = await befly.db.getList({
136
- table: 'article',
138
+ table: "article",
137
139
  where: {
138
140
  categoryId: ctx.body.categoryId, // 如果未传,值为 undefined,自动忽略
139
141
  status: ctx.body.status, // 如果未传,值为 undefined,自动忽略
@@ -150,17 +152,17 @@ const result = await befly.db.getList({
150
152
  ```typescript
151
153
  // API: 用户列表(带可选筛选条件)
152
154
  export default {
153
- name: '用户列表',
155
+ name: "用户列表",
154
156
  fields: {
155
- keyword: { name: '关键词', type: 'string', max: 50 },
156
- status: { name: '状态', type: 'number' },
157
- state: { name: '状态', type: 'number' }
157
+ keyword: { name: "关键词", type: "string", max: 50 },
158
+ status: { name: "状态", type: "number" },
159
+ state: { name: "状态", type: "number" }
158
160
  },
159
161
  handler: async (befly, ctx) => {
160
162
  // 直接使用请求参数,无需判断是否存在
161
163
  // null/undefined 的条件会被自动过滤
162
164
  const result = await befly.db.getList({
163
- table: 'user',
165
+ table: "user",
164
166
  where: {
165
167
  status: ctx.body.status, // 未传时为 undefined,自动忽略
166
168
  state: ctx.body.state, // 未传时为 undefined,自动忽略
@@ -170,7 +172,7 @@ export default {
170
172
  limit: ctx.body.limit || 10
171
173
  });
172
174
 
173
- return befly.tool.Yes('查询成功', result);
175
+ return befly.tool.Yes("查询成功", result);
174
176
  }
175
177
  };
176
178
  ```
@@ -182,23 +184,23 @@ export default {
182
184
  ```typescript
183
185
  // 默认排除 null 和 undefined
184
186
  const cleanData = befly.db.cleanFields({
185
- name: 'John',
187
+ name: "John",
186
188
  age: null,
187
189
  email: undefined,
188
- phone: ''
190
+ phone: ""
189
191
  });
190
192
  // 结果: { name: 'John', phone: '' }
191
193
 
192
194
  // 自定义排除值(如同时排除空字符串)
193
195
  const cleanData2 = befly.db.cleanFields(
194
- { name: 'John', phone: '', age: null },
195
- [null, undefined, ''] // 排除这些值
196
+ { name: "John", phone: "", age: null },
197
+ [null, undefined, ""] // 排除这些值
196
198
  );
197
199
  // 结果: { name: 'John' }
198
200
 
199
201
  // 保留特定字段的特定值(即使在排除列表中)
200
202
  const cleanData3 = befly.db.cleanFields(
201
- { name: 'John', status: null, count: 0 },
203
+ { name: "John", status: null, count: 0 },
202
204
  [null, undefined], // 排除 null 和 undefined
203
205
  { status: null } // 但保留 status 字段的 null 值
204
206
  );
@@ -217,16 +219,16 @@ const cleanData3 = befly.db.cleanFields(
217
219
  ```typescript
218
220
  // 写入时使用小驼峰
219
221
  await befly.db.insData({
220
- table: 'user',
222
+ table: "user",
221
223
  data: {
222
- userName: 'John', // → user_name
224
+ userName: "John", // → user_name
223
225
  createdBy: 1 // → created_by
224
226
  }
225
227
  });
226
228
 
227
229
  // 查询返回小驼峰
228
230
  const user = await befly.db.getOne({
229
- table: 'user',
231
+ table: "user",
230
232
  where: { userId: 1 } // → WHERE user_id = 1
231
233
  });
232
234
  // 返回: { userId: 1, userName: 'John', createdBy: 1 }
@@ -253,21 +255,21 @@ interface QueryOptions {
253
255
  ```typescript
254
256
  // 基础查询
255
257
  const user = await befly.db.getOne({
256
- table: 'user',
258
+ table: "user",
257
259
  where: { id: 1 }
258
260
  });
259
261
 
260
262
  // 指定字段
261
263
  const user = await befly.db.getOne({
262
- table: 'user',
263
- fields: ['id', 'username', 'email'],
264
+ table: "user",
265
+ fields: ["id", "username", "email"],
264
266
  where: { id: 1 }
265
267
  });
266
268
 
267
269
  // 排除字段(使用 ! 前缀)
268
270
  const user = await befly.db.getOne({
269
- table: 'user',
270
- fields: ['!password', '!token'],
271
+ table: "user",
272
+ fields: ["!password", "!token"],
271
273
  where: { id: 1 }
272
274
  });
273
275
  ```
@@ -300,7 +302,7 @@ interface ListResult<T> {
300
302
  ```typescript
301
303
  // 基础分页
302
304
  const result = await befly.db.getList({
303
- table: 'user',
305
+ table: "user",
304
306
  page: 1,
305
307
  limit: 10
306
308
  });
@@ -308,10 +310,10 @@ const result = await befly.db.getList({
308
310
 
309
311
  // 带条件和排序
310
312
  const result = await befly.db.getList({
311
- table: 'user',
312
- fields: ['id', 'username', 'createdAt'],
313
+ table: "user",
314
+ fields: ["id", "username", "createdAt"],
313
315
  where: { state: 1 },
314
- orderBy: ['createdAt#DESC', 'id#ASC'],
316
+ orderBy: ["createdAt#DESC", "id#ASC"],
315
317
  page: 2,
316
318
  limit: 20
317
319
  });
@@ -329,16 +331,16 @@ const result = await befly.db.getList({
329
331
  ```typescript
330
332
  // 查询所有
331
333
  const result = await befly.db.getAll({
332
- table: 'user'
334
+ table: "user"
333
335
  });
334
336
  // result: { lists: [...], total: 实际总数 }
335
337
 
336
338
  // 带条件
337
339
  const activeResult = await befly.db.getAll({
338
- table: 'user',
339
- fields: ['id', 'username'],
340
+ table: "user",
341
+ fields: ["id", "username"],
340
342
  where: { state: 1 },
341
- orderBy: ['sort#ASC']
343
+ orderBy: ["sort#ASC"]
342
344
  });
343
345
 
344
346
  // 访问数据
@@ -362,12 +364,12 @@ console.log(activeResult.total); // 真实总数(如 100000)
362
364
  ```typescript
363
365
  // 查询总数
364
366
  const count = await befly.db.getCount({
365
- table: 'user'
367
+ table: "user"
366
368
  });
367
369
 
368
370
  // 条件计数
369
371
  const activeCount = await befly.db.getCount({
370
- table: 'user',
372
+ table: "user",
371
373
  where: { state: 1 }
372
374
  });
373
375
  ```
@@ -378,8 +380,8 @@ const activeCount = await befly.db.getCount({
378
380
 
379
381
  ```typescript
380
382
  const hasAdmin = await befly.db.exists({
381
- table: 'user',
382
- where: { roleCode: 'admin' }
383
+ table: "user",
384
+ where: { roleCode: "admin" }
383
385
  });
384
386
 
385
387
  if (hasAdmin) {
@@ -394,15 +396,15 @@ if (hasAdmin) {
394
396
  ```typescript
395
397
  // 查询用户名
396
398
  const username = await befly.db.getFieldValue({
397
- table: 'user',
398
- field: 'username',
399
+ table: "user",
400
+ field: "username",
399
401
  where: { id: 1 }
400
402
  });
401
403
 
402
404
  // 查询余额
403
405
  const balance = await befly.db.getFieldValue<number>({
404
- table: 'account',
405
- field: 'balance',
406
+ table: "account",
407
+ field: "balance",
406
408
  where: { userId: 1 }
407
409
  });
408
410
  ```
@@ -436,10 +438,10 @@ interface InsertOptions {
436
438
  ```typescript
437
439
  // 插入用户
438
440
  const userId = await befly.db.insData({
439
- table: 'user',
441
+ table: "user",
440
442
  data: {
441
- username: 'john',
442
- email: 'john@example.com',
443
+ username: "john",
444
+ email: "john@example.com",
443
445
  password: hashedPassword,
444
446
  categoryId: 1
445
447
  }
@@ -448,12 +450,12 @@ const userId = await befly.db.insData({
448
450
 
449
451
  // 系统字段不可覆盖
450
452
  await befly.db.insData({
451
- table: 'user',
453
+ table: "user",
452
454
  data: {
453
455
  id: 999, // ❌ 会被忽略,自动生成
454
456
  createdAt: 0, // ❌ 会被忽略,自动生成
455
457
  state: 2, // ❌ 会被忽略,强制设为 1
456
- username: 'john' // ✅ 正常写入
458
+ username: "john" // ✅ 正常写入
457
459
  }
458
460
  });
459
461
  ```
@@ -464,10 +466,10 @@ await befly.db.insData({
464
466
 
465
467
  ```typescript
466
468
  // 批量插入
467
- const ids = await befly.db.insBatch('user', [
468
- { username: 'user1', email: 'user1@example.com' },
469
- { username: 'user2', email: 'user2@example.com' },
470
- { username: 'user3', email: 'user3@example.com' }
469
+ const ids = await befly.db.insBatch("user", [
470
+ { username: "user1", email: "user1@example.com" },
471
+ { username: "user2", email: "user2@example.com" },
472
+ { username: "user3", email: "user3@example.com" }
471
473
  ]);
472
474
  // 返回: [id1, id2, id3]
473
475
  ```
@@ -489,10 +491,10 @@ interface UpdateOptions {
489
491
  ```typescript
490
492
  // 更新用户
491
493
  const affected = await befly.db.updData({
492
- table: 'user',
494
+ table: "user",
493
495
  data: {
494
- nickname: '新昵称',
495
- email: 'new@example.com'
496
+ nickname: "新昵称",
497
+ email: "new@example.com"
496
498
  },
497
499
  where: { id: 1 }
498
500
  });
@@ -500,7 +502,7 @@ const affected = await befly.db.updData({
500
502
 
501
503
  // 批量更新
502
504
  await befly.db.updData({
503
- table: 'user',
505
+ table: "user",
504
506
  data: { state: 2 },
505
507
  where: { status: 5 }
506
508
  });
@@ -519,7 +521,7 @@ await befly.db.updData({
519
521
  ```typescript
520
522
  // 软删除
521
523
  const affected = await befly.db.delData({
522
- table: 'user',
524
+ table: "user",
523
525
  where: { id: 1 }
524
526
  });
525
527
  ```
@@ -531,7 +533,7 @@ const affected = await befly.db.delData({
531
533
  ```typescript
532
534
  // 硬删除
533
535
  const affected = await befly.db.delForce({
534
- table: 'temp_data',
536
+ table: "temp_data",
535
537
  where: { expiredAt$lt: Date.now() }
536
538
  });
537
539
  ```
@@ -545,7 +547,7 @@ const affected = await befly.db.delForce({
545
547
  ```typescript
546
548
  // 禁用用户
547
549
  await befly.db.disableData({
548
- table: 'user',
550
+ table: "user",
549
551
  where: { id: 1 }
550
552
  });
551
553
  ```
@@ -557,7 +559,7 @@ await befly.db.disableData({
557
559
  ```typescript
558
560
  // 启用用户
559
561
  await befly.db.enableData({
560
- table: 'user',
562
+ table: "user",
561
563
  where: { id: 1 }
562
564
  });
563
565
  ```
@@ -572,10 +574,10 @@ await befly.db.enableData({
572
574
 
573
575
  ```typescript
574
576
  // 阅读数 +1
575
- await befly.db.increment('article', 'viewCount', { id: 1 });
577
+ await befly.db.increment("article", "viewCount", { id: 1 });
576
578
 
577
579
  // 阅读数 +10
578
- await befly.db.increment('article', 'viewCount', { id: 1 }, 10);
580
+ await befly.db.increment("article", "viewCount", { id: 1 }, 10);
579
581
  ```
580
582
 
581
583
  ### decrement - 自减
@@ -584,10 +586,10 @@ await befly.db.increment('article', 'viewCount', { id: 1 }, 10);
584
586
 
585
587
  ```typescript
586
588
  // 库存 -1
587
- await befly.db.decrement('product', 'stock', { id: 1 });
589
+ await befly.db.decrement("product", "stock", { id: 1 });
588
590
 
589
591
  // 余额 -100
590
- await befly.db.decrement('account', 'balance', { userId: 1 }, 100);
592
+ await befly.db.decrement("account", "balance", { userId: 1 }, 100);
591
593
  ```
592
594
 
593
595
  ---
@@ -600,14 +602,14 @@ await befly.db.decrement('account', 'balance', { userId: 1 }, 100);
600
602
  // 转账示例
601
603
  const result = await befly.db.trans(async (tx) => {
602
604
  // 扣除转出方余额
603
- await tx.decrement('account', 'balance', { userId: 1 }, 100);
605
+ await tx.decrement("account", "balance", { userId: 1 }, 100);
604
606
 
605
607
  // 增加转入方余额
606
- await tx.increment('account', 'balance', { userId: 2 }, 100);
608
+ await tx.increment("account", "balance", { userId: 2 }, 100);
607
609
 
608
610
  // 记录转账日志
609
611
  await tx.insData({
610
- table: 'transfer_log',
612
+ table: "transfer_log",
611
613
  data: {
612
614
  fromUserId: 1,
613
615
  toUserId: 2,
@@ -620,9 +622,9 @@ const result = await befly.db.trans(async (tx) => {
620
622
 
621
623
  // 事务中抛出异常会自动回滚
622
624
  await befly.db.trans(async (tx) => {
623
- await tx.updData({ table: 'user', data: { balance: 0 }, where: { id: 1 } });
625
+ await tx.updData({ table: "user", data: { balance: 0 }, where: { id: 1 } });
624
626
 
625
- throw new Error('业务校验失败'); // 自动回滚
627
+ throw new Error("业务校验失败"); // 自动回滚
626
628
  });
627
629
  ```
628
630
 
@@ -639,23 +641,23 @@ DbHelper 的查询方法(getOne、getList、getAll、getCount)支持通过 `
639
641
  ```typescript
640
642
  // 单条联查
641
643
  const order = await befly.db.getOne({
642
- table: 'order',
643
- joins: [{ table: 'user', on: 'order.user_id = user.id' }],
644
- fields: ['order.id', 'order.totalAmount', 'order.status', 'user.username', 'user.nickname'],
645
- where: { 'order.id': orderId }
644
+ table: "order",
645
+ joins: [{ table: "user", on: "order.user_id = user.id" }],
646
+ fields: ["order.id", "order.totalAmount", "order.status", "user.username", "user.nickname"],
647
+ where: { "order.id": orderId }
646
648
  });
647
649
  // 返回: { id: 1, totalAmount: 100, status: 'paid', username: 'john', nickname: '张三' }
648
650
 
649
651
  // 分页联查
650
652
  const result = await befly.db.getList({
651
- table: 'order',
653
+ table: "order",
652
654
  joins: [
653
- { table: 'user', on: 'order.userId = user.id' },
654
- { table: 'product', on: 'order.productId = product.id' }
655
+ { table: "user", on: "order.userId = user.id" },
656
+ { table: "product", on: "order.productId = product.id" }
655
657
  ],
656
- fields: ['order.id', 'order.totalAmount', 'user.username', 'product.name AS productName'],
657
- where: { 'order.status': 'paid' },
658
- orderBy: ['order.createdAt#DESC'],
658
+ fields: ["order.id", "order.totalAmount", "user.username", "product.name AS productName"],
659
+ where: { "order.status": "paid" },
660
+ orderBy: ["order.createdAt#DESC"],
659
661
  page: 1,
660
662
  limit: 10
661
663
  });
@@ -663,18 +665,18 @@ const result = await befly.db.getList({
663
665
 
664
666
  // 联查计数
665
667
  const count = await befly.db.getCount({
666
- table: 'order',
667
- joins: [{ table: 'user', on: 'order.userId = user.id' }],
668
- where: { 'order.state': 1, 'user.state': 1 }
668
+ table: "order",
669
+ joins: [{ table: "user", on: "order.userId = user.id" }],
670
+ where: { "order.state": 1, "user.state": 1 }
669
671
  });
670
672
 
671
673
  // 联查全部
672
674
  const allOrders = await befly.db.getAll({
673
- table: 'order',
674
- joins: [{ table: 'user', on: 'order.userId = user.id' }],
675
- fields: ['order.id', 'user.username'],
676
- where: { 'order.state': 1 },
677
- orderBy: ['order.id#DESC']
675
+ table: "order",
676
+ joins: [{ table: "user", on: "order.userId = user.id" }],
677
+ fields: ["order.id", "user.username"],
678
+ where: { "order.state": 1 },
679
+ orderBy: ["order.id#DESC"]
678
680
  });
679
681
  // 返回: { lists: [...最多10000条], total: 真实总数 }
680
682
  ```
@@ -684,7 +686,7 @@ const allOrders = await befly.db.getAll({
684
686
  ```typescript
685
687
  interface JoinOption {
686
688
  /** JOIN 类型:'left' | 'right' | 'inner',默认 'left' */
687
- type?: 'left' | 'right' | 'inner';
689
+ type?: "left" | "right" | "inner";
688
690
  /** 表名(不支持别名) */
689
691
  table: string;
690
692
  /** JOIN 条件(如 'order.user_id = user.id') */
@@ -696,10 +698,10 @@ interface JoinOption {
696
698
 
697
699
  ```typescript
698
700
  joins: [
699
- { table: 'user', on: 'order.userId = user.id' }, // LEFT JOIN(默认)
700
- { type: 'left', table: 'product', on: 'order.productId = product.id' }, // LEFT JOIN
701
- { type: 'inner', table: 'category', on: 'product.categoryId = category.id' }, // INNER JOIN
702
- { type: 'right', table: 'warehouse', on: 'product.warehouseId = warehouse.id' } // RIGHT JOIN
701
+ { table: "user", on: "order.userId = user.id" }, // LEFT JOIN(默认)
702
+ { type: "left", table: "product", on: "order.productId = product.id" }, // LEFT JOIN
703
+ { type: "inner", table: "category", on: "product.categoryId = category.id" }, // INNER JOIN
704
+ { type: "right", table: "warehouse", on: "product.warehouseId = warehouse.id" } // RIGHT JOIN
703
705
  ];
704
706
  ```
705
707
 
@@ -714,43 +716,43 @@ joins: [
714
716
 
715
717
  ```typescript
716
718
  export default {
717
- name: '订单列表',
719
+ name: "订单列表",
718
720
  fields: {
719
- keyword: { name: '关键词', type: 'string', max: 50 },
720
- status: { name: '状态', type: 'string' },
721
+ keyword: { name: "关键词", type: "string", max: 50 },
722
+ status: { name: "状态", type: "string" },
721
723
  page: Fields.page,
722
724
  limit: Fields.limit
723
725
  },
724
726
  handler: async (befly, ctx) => {
725
727
  const where: any = {
726
- 'order.state': 1,
727
- 'user.state': 1
728
+ "order.state": 1,
729
+ "user.state": 1
728
730
  };
729
731
 
730
732
  // 关键词搜索
731
733
  if (ctx.body.keyword) {
732
- where.$or = [{ 'user.username$like': `%${ctx.body.keyword}%` }, { 'user.nickname$like': `%${ctx.body.keyword}%` }, { 'product.name$like': `%${ctx.body.keyword}%` }];
734
+ where.$or = [{ "user.username$like": `%${ctx.body.keyword}%` }, { "user.nickname$like": `%${ctx.body.keyword}%` }, { "product.name$like": `%${ctx.body.keyword}%` }];
733
735
  }
734
736
 
735
737
  // 状态过滤
736
738
  if (ctx.body.status) {
737
- where['order.status'] = ctx.body.status;
739
+ where["order.status"] = ctx.body.status;
738
740
  }
739
741
 
740
742
  const result = await befly.db.getList({
741
- table: 'order',
743
+ table: "order",
742
744
  joins: [
743
- { table: 'user', on: 'order.userId = user.id' },
744
- { table: 'product', on: 'order.productId = product.id' }
745
+ { table: "user", on: "order.userId = user.id" },
746
+ { table: "product", on: "order.productId = product.id" }
745
747
  ],
746
- fields: ['order.id', 'order.quantity', 'order.totalAmount', 'order.status', 'order.createdAt', 'user.username', 'user.nickname', 'product.name AS productName', 'product.price AS productPrice'],
748
+ fields: ["order.id", "order.quantity", "order.totalAmount", "order.status", "order.createdAt", "user.username", "user.nickname", "product.name AS productName", "product.price AS productPrice"],
747
749
  where: where,
748
- orderBy: ['order.createdAt#DESC'],
750
+ orderBy: ["order.createdAt#DESC"],
749
751
  page: ctx.body.page,
750
752
  limit: ctx.body.limit
751
753
  });
752
754
 
753
- return befly.tool.Yes('查询成功', result);
755
+ return befly.tool.Yes("查询成功", result);
754
756
  }
755
757
  };
756
758
  ```
@@ -778,7 +780,7 @@ const usersWithOrderCount = await befly.db.query(
778
780
  );
779
781
 
780
782
  // 需要手动转换字段名
781
- import { arrayKeysToCamel } from 'befly-shared/arrayKeysToCamel';
783
+ import { arrayKeysToCamel } from "befly/lib/arrayKeysToCamel";
782
784
  const list = arrayKeysToCamel(usersWithOrderCount);
783
785
  ```
784
786
 
@@ -832,7 +834,7 @@ where: {
832
834
  ```typescript
833
835
  // 用户名或邮箱匹配
834
836
  where: {
835
- $or: [{ username: 'admin' }, { email: 'admin@example.com' }];
837
+ $or: [{ username: "admin" }, { email: "admin@example.com" }];
836
838
  }
837
839
  // → WHERE (username = 'admin' OR email = 'admin@example.com')
838
840
  ```
@@ -872,7 +874,7 @@ where: {
872
874
  // → WHERE category_id IN (1, 2, 3)
873
875
 
874
876
  where: {
875
- status$in: ['pending', 'processing'];
877
+ status$in: ["pending", "processing"];
876
878
  }
877
879
  // → WHERE status IN ('pending', 'processing')
878
880
  ```
@@ -936,19 +938,19 @@ where: {
936
938
  ```typescript
937
939
  // 包含
938
940
  where: {
939
- username$like: '%admin%';
941
+ username$like: "%admin%";
940
942
  }
941
943
  // → WHERE username LIKE '%admin%'
942
944
 
943
945
  // 以...开头
944
946
  where: {
945
- email$like: 'test%';
947
+ email$like: "test%";
946
948
  }
947
949
  // → WHERE email LIKE 'test%'
948
950
 
949
951
  // 以...结尾
950
952
  where: {
951
- phone$like: '%1234';
953
+ phone$like: "%1234";
952
954
  }
953
955
  // → WHERE phone LIKE '%1234'
954
956
  ```
@@ -957,7 +959,7 @@ where: {
957
959
 
958
960
  ```typescript
959
961
  where: {
960
- username$notLike: '%test%';
962
+ username$notLike: "%test%";
961
963
  }
962
964
  // → WHERE username NOT LIKE '%test%'
963
965
  ```
@@ -978,7 +980,7 @@ fields: undefined;
978
980
  ### 指定字段
979
981
 
980
982
  ```typescript
981
- fields: ['id', 'username', 'email'];
983
+ fields: ["id", "username", "email"];
982
984
  // → SELECT id, username, email
983
985
  ```
984
986
 
@@ -987,7 +989,7 @@ fields: ['id', 'username', 'email'];
987
989
  使用 `!` 前缀排除字段(查询除指定字段外的所有字段)。
988
990
 
989
991
  ```typescript
990
- fields: ['!password', '!token', '!salt'];
992
+ fields: ["!password", "!token", "!salt"];
991
993
  // → SELECT id, username, email, created_at, ... (除了 password, token, salt)
992
994
  ```
993
995
 
@@ -1001,11 +1003,11 @@ fields: ['!password', '!token', '!salt'];
1001
1003
 
1002
1004
  ```typescript
1003
1005
  // 单字段排序
1004
- orderBy: ['createdAt#DESC'];
1006
+ orderBy: ["createdAt#DESC"];
1005
1007
  // → ORDER BY created_at DESC
1006
1008
 
1007
1009
  // 多字段排序
1008
- orderBy: ['sort#ASC', 'id#DESC'];
1010
+ orderBy: ["sort#ASC", "id#DESC"];
1009
1011
  // → ORDER BY sort ASC, id DESC
1010
1012
  ```
1011
1013
 
@@ -1047,19 +1049,19 @@ orderBy: ['sort#ASC', 'id#DESC'];
1047
1049
 
1048
1050
  ```typescript
1049
1051
  // 默认查询:state > 0,包含正常和禁用数据
1050
- getOne({ table: 'user', where: { id: 1 } });
1052
+ getOne({ table: "user", where: { id: 1 } });
1051
1053
  // → WHERE id = 1 AND state > 0
1052
1054
 
1053
1055
  // 只查询正常状态的数据
1054
- getList({ table: 'user', where: { state: 1 } });
1056
+ getList({ table: "user", where: { state: 1 } });
1055
1057
  // → WHERE state = 1
1056
1058
 
1057
1059
  // 只查询禁用状态的数据
1058
- getList({ table: 'user', where: { state: 2 } });
1060
+ getList({ table: "user", where: { state: 2 } });
1059
1061
  // → WHERE state = 2
1060
1062
 
1061
1063
  // 查询所有状态(包括软删除)
1062
- getOne({ table: 'user', where: { id: 1, state$gte: 0 } });
1064
+ getOne({ table: "user", where: { id: 1, state$gte: 0 } });
1063
1065
  // → WHERE id = 1 AND state >= 0
1064
1066
  ```
1065
1067
 
@@ -1072,10 +1074,10 @@ getOne({ table: 'user', where: { id: 1, state$gte: 0 } });
1072
1074
  ```typescript
1073
1075
  // 用户列表
1074
1076
  export default {
1075
- name: '用户列表',
1077
+ name: "用户列表",
1076
1078
  fields: {
1077
- keyword: { name: '关键词', type: 'string', max: 50 },
1078
- departmentId: { name: '部门ID', type: 'number' },
1079
+ keyword: { name: "关键词", type: "string", max: 50 },
1080
+ departmentId: { name: "部门ID", type: "number" },
1079
1081
  page: Fields.page,
1080
1082
  limit: Fields.limit
1081
1083
  },
@@ -1093,15 +1095,15 @@ export default {
1093
1095
  }
1094
1096
 
1095
1097
  const result = await befly.db.getList({
1096
- table: 'user',
1097
- fields: ['!password', '!token'],
1098
+ table: "user",
1099
+ fields: ["!password", "!token"],
1098
1100
  where: where,
1099
- orderBy: ['createdAt#DESC'],
1101
+ orderBy: ["createdAt#DESC"],
1100
1102
  page: ctx.body.page,
1101
1103
  limit: ctx.body.limit
1102
1104
  });
1103
1105
 
1104
- return befly.tool.Yes('查询成功', result);
1106
+ return befly.tool.Yes("查询成功", result);
1105
1107
  }
1106
1108
  };
1107
1109
  ```
@@ -1110,47 +1112,47 @@ export default {
1110
1112
 
1111
1113
  ```typescript
1112
1114
  export default {
1113
- name: '创建订单',
1115
+ name: "创建订单",
1114
1116
  fields: {
1115
- productId: { name: '商品ID', type: 'number' },
1116
- quantity: { name: '数量', type: 'number', min: 1 }
1117
+ productId: { name: "商品ID", type: "number" },
1118
+ quantity: { name: "数量", type: "number", min: 1 }
1117
1119
  },
1118
- required: ['productId', 'quantity'],
1120
+ required: ["productId", "quantity"],
1119
1121
  handler: async (befly, ctx) => {
1120
1122
  const result = await befly.db.trans(async (tx) => {
1121
1123
  // 1. 查询商品
1122
1124
  const product = await tx.getOne({
1123
- table: 'product',
1125
+ table: "product",
1124
1126
  where: { id: ctx.body.productId }
1125
1127
  });
1126
1128
 
1127
1129
  if (!product) {
1128
- throw new Error('商品不存在');
1130
+ throw new Error("商品不存在");
1129
1131
  }
1130
1132
 
1131
1133
  if (product.stock < ctx.body.quantity) {
1132
- throw new Error('库存不足');
1134
+ throw new Error("库存不足");
1133
1135
  }
1134
1136
 
1135
1137
  // 2. 扣减库存
1136
- await tx.decrement('product', 'stock', { id: ctx.body.productId }, ctx.body.quantity);
1138
+ await tx.decrement("product", "stock", { id: ctx.body.productId }, ctx.body.quantity);
1137
1139
 
1138
1140
  // 3. 创建订单
1139
1141
  const orderId = await tx.insData({
1140
- table: 'order',
1142
+ table: "order",
1141
1143
  data: {
1142
1144
  userId: ctx.user.id,
1143
1145
  productId: ctx.body.productId,
1144
1146
  quantity: ctx.body.quantity,
1145
1147
  totalAmount: product.price * ctx.body.quantity,
1146
- status: 'pending'
1148
+ status: "pending"
1147
1149
  }
1148
1150
  });
1149
1151
 
1150
1152
  return { orderId: orderId };
1151
1153
  });
1152
1154
 
1153
- return befly.tool.Yes('订单创建成功', result);
1155
+ return befly.tool.Yes("订单创建成功", result);
1154
1156
  }
1155
1157
  };
1156
1158
  ```
@@ -1160,14 +1162,14 @@ export default {
1160
1162
  ```typescript
1161
1163
  // 查询最近7天内,状态为正常或待审核的文章
1162
1164
  const articles = await befly.db.getList({
1163
- table: 'article',
1164
- fields: ['id', 'title', 'authorId', 'viewCount', 'createdAt'],
1165
+ table: "article",
1166
+ fields: ["id", "title", "authorId", "viewCount", "createdAt"],
1165
1167
  where: {
1166
1168
  createdAt$gte: Date.now() - 7 * 24 * 60 * 60 * 1000,
1167
- $or: [{ status: 'published' }, { status: 'pending' }],
1169
+ $or: [{ status: "published" }, { status: "pending" }],
1168
1170
  categoryId$in: [1, 2, 3]
1169
1171
  },
1170
- orderBy: ['viewCount#DESC', 'createdAt#DESC'],
1172
+ orderBy: ["viewCount#DESC", "createdAt#DESC"],
1171
1173
  page: 1,
1172
1174
  limit: 20
1173
1175
  });