befly 3.9.23 → 3.9.27
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/docs/api.md +16 -6
- package/docs/database.md +21 -3
- package/docs/redis.md +4 -3
- package/lib/cacheHelper.ts +4 -4
- package/lib/dbHelper.ts +36 -10
- package/package.json +2 -2
- package/sync/syncApi.ts +3 -3
- package/sync/syncDev.ts +4 -4
- package/sync/syncMenu.ts +8 -8
- package/tests/cacheHelper.test.ts +11 -11
- package/types/database.d.ts +12 -2
package/docs/api.md
CHANGED
|
@@ -1430,7 +1430,7 @@ export default {
|
|
|
1430
1430
|
}
|
|
1431
1431
|
|
|
1432
1432
|
// 查询订单明细
|
|
1433
|
-
const
|
|
1433
|
+
const itemsResult = await befly.db.getAll({
|
|
1434
1434
|
table: 'order_item',
|
|
1435
1435
|
where: { orderId: order.id }
|
|
1436
1436
|
});
|
|
@@ -1438,6 +1438,14 @@ export default {
|
|
|
1438
1438
|
// 查询用户信息
|
|
1439
1439
|
const user = await befly.db.getOne({
|
|
1440
1440
|
table: 'user',
|
|
1441
|
+
where: { id: order.userId }
|
|
1442
|
+
});
|
|
1443
|
+
|
|
1444
|
+
return befly.tool.Yes('查询成功', {
|
|
1445
|
+
order: order,
|
|
1446
|
+
items: itemsResult.lists, // 订单明细列表
|
|
1447
|
+
user: user
|
|
1448
|
+
});
|
|
1441
1449
|
where: { id: order.userId },
|
|
1442
1450
|
columns: ['id', 'username', 'nickname', 'phone']
|
|
1443
1451
|
});
|
|
@@ -1494,11 +1502,13 @@ export default {
|
|
|
1494
1502
|
|
|
1495
1503
|
if (!config) {
|
|
1496
1504
|
// 缓存不存在,从数据库查询
|
|
1497
|
-
|
|
1505
|
+
const result = await befly.db.getAll({
|
|
1498
1506
|
table: 'sys_config',
|
|
1499
1507
|
where: { state: 1 }
|
|
1500
1508
|
});
|
|
1501
1509
|
|
|
1510
|
+
config = result.lists; // 获取配置列表
|
|
1511
|
+
|
|
1502
1512
|
// 写入缓存
|
|
1503
1513
|
await befly.redis.set(cacheKey, JSON.stringify(config), 'EX', 300);
|
|
1504
1514
|
} else {
|
|
@@ -1546,8 +1556,8 @@ export default {
|
|
|
1546
1556
|
export default {
|
|
1547
1557
|
name: '导出用户数据',
|
|
1548
1558
|
handler: async (befly, ctx) => {
|
|
1549
|
-
//
|
|
1550
|
-
const
|
|
1559
|
+
// 查询所有用户(不分页,注意上限 10000 条)
|
|
1560
|
+
const result = await befly.db.getAll({
|
|
1551
1561
|
table: 'user',
|
|
1552
1562
|
columns: ['id', 'username', 'nickname', 'email', 'phone', 'createdAt'],
|
|
1553
1563
|
where: { state: 1 },
|
|
@@ -1556,11 +1566,11 @@ export default {
|
|
|
1556
1566
|
|
|
1557
1567
|
// 转换为 CSV 格式
|
|
1558
1568
|
const headers = ['ID', '用户名', '昵称', '邮箱', '手机', '注册时间'];
|
|
1559
|
-
const rows =
|
|
1569
|
+
const rows = result.lists.map((u: any) => [u.id, u.username, u.nickname, u.email, u.phone, new Date(u.createdAt).toLocaleString()]);
|
|
1560
1570
|
|
|
1561
1571
|
const csv = [headers.join(','), ...rows.map((r: any[]) => r.join(','))].join('\n');
|
|
1562
1572
|
|
|
1563
|
-
// 返回 CSV
|
|
1573
|
+
// 返回 CSV 文件(注意:如果 total > 10000,只会导出前 10000 条)
|
|
1564
1574
|
return new Response(csv, {
|
|
1565
1575
|
headers: {
|
|
1566
1576
|
'Content-Type': 'text/csv; charset=utf-8',
|
package/docs/database.md
CHANGED
|
@@ -321,22 +321,39 @@ const result = await befly.db.getList({
|
|
|
321
321
|
|
|
322
322
|
查询所有满足条件的记录(有上限保护,最多 10000 条)。
|
|
323
323
|
|
|
324
|
+
**返回值**:`{ lists: T[], total: number }`
|
|
325
|
+
|
|
326
|
+
- `lists`:数据数组(受 MAX_LIMIT 保护,最多 10000 条)
|
|
327
|
+
- `total`:真实总记录数(不受 MAX_LIMIT 限制)
|
|
328
|
+
|
|
324
329
|
```typescript
|
|
325
330
|
// 查询所有
|
|
326
|
-
const
|
|
331
|
+
const result = await befly.db.getAll({
|
|
327
332
|
table: 'user'
|
|
328
333
|
});
|
|
334
|
+
// result: { lists: [...], total: 实际总数 }
|
|
329
335
|
|
|
330
336
|
// 带条件
|
|
331
|
-
const
|
|
337
|
+
const activeResult = await befly.db.getAll({
|
|
332
338
|
table: 'user',
|
|
333
339
|
fields: ['id', 'username'],
|
|
334
340
|
where: { state: 1 },
|
|
335
341
|
orderBy: ['sort#ASC']
|
|
336
342
|
});
|
|
343
|
+
|
|
344
|
+
// 访问数据
|
|
345
|
+
console.log(activeResult.lists); // 数据数组(最多 10000 条)
|
|
346
|
+
console.log(activeResult.total); // 真实总数(如 100000)
|
|
337
347
|
```
|
|
338
348
|
|
|
339
|
-
|
|
349
|
+
**重要说明**:
|
|
350
|
+
|
|
351
|
+
- `total` 是查询满足条件的真实总记录数
|
|
352
|
+
- `lists` 受 `MAX_LIMIT = 10000` 保护,最多返回 10000 条
|
|
353
|
+
- 如果总数超过 10000,`lists.length < total`
|
|
354
|
+
- 建议使用 `getList` 进行分页查询
|
|
355
|
+
|
|
356
|
+
> ⚠️ **警告**:此方法可能返回大量数据。超过 1000 条会输出警告日志,达到 10000 条会提示只返回部分数据。
|
|
340
357
|
|
|
341
358
|
### getCount - 查询数量
|
|
342
359
|
|
|
@@ -659,6 +676,7 @@ const allOrders = await befly.db.getAll({
|
|
|
659
676
|
where: { 'order.state': 1 },
|
|
660
677
|
orderBy: ['order.id#DESC']
|
|
661
678
|
});
|
|
679
|
+
// 返回: { lists: [...最多10000条], total: 真实总数 }
|
|
662
680
|
```
|
|
663
681
|
|
|
664
682
|
### JoinOption 参数说明
|
package/docs/redis.md
CHANGED
|
@@ -438,13 +438,14 @@ let articles = await befly.redis.getObject(cacheKey);
|
|
|
438
438
|
|
|
439
439
|
if (!articles) {
|
|
440
440
|
// 缓存未命中,查询数据库
|
|
441
|
-
|
|
441
|
+
const result = await befly.db.getAll({
|
|
442
442
|
table: 'article',
|
|
443
443
|
fields: ['id', 'title', 'viewCount'],
|
|
444
|
-
orderBy: ['viewCount#DESC']
|
|
445
|
-
limit: 10
|
|
444
|
+
orderBy: ['viewCount#DESC']
|
|
446
445
|
});
|
|
447
446
|
|
|
447
|
+
articles = result.lists; // 获取数据列表(最多 10000 条)
|
|
448
|
+
|
|
448
449
|
// 写入缓存,5分钟过期
|
|
449
450
|
await befly.redis.setObject(cacheKey, articles, 300);
|
|
450
451
|
}
|
package/lib/cacheHelper.ts
CHANGED
|
@@ -42,7 +42,7 @@ export class CacheHelper {
|
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
// 缓存到 Redis
|
|
45
|
-
const result = await this.befly.redis.setObject(RedisKeys.apisAll(), apiList);
|
|
45
|
+
const result = await this.befly.redis.setObject(RedisKeys.apisAll(), apiList.lists);
|
|
46
46
|
|
|
47
47
|
if (result === null) {
|
|
48
48
|
Logger.warn('⚠️ 接口缓存失败');
|
|
@@ -72,7 +72,7 @@ export class CacheHelper {
|
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
// 缓存到 Redis
|
|
75
|
-
const result = await this.befly.redis.setObject(RedisKeys.menusAll(), menus);
|
|
75
|
+
const result = await this.befly.redis.setObject(RedisKeys.menusAll(), menus.lists);
|
|
76
76
|
|
|
77
77
|
if (result === null) {
|
|
78
78
|
Logger.warn('⚠️ 菜单缓存失败');
|
|
@@ -111,14 +111,14 @@ export class CacheHelper {
|
|
|
111
111
|
|
|
112
112
|
// 构建接口 ID -> 路径的映射(避免重复过滤)
|
|
113
113
|
const apiMap = new Map<number, string>();
|
|
114
|
-
for (const api of allApis) {
|
|
114
|
+
for (const api of allApis.lists) {
|
|
115
115
|
apiMap.set(api.id, `${api.method}${api.path}`);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
// 收集需要缓存的角色权限
|
|
119
119
|
const cacheOperations: Array<{ roleCode: string; apiPaths: string[] }> = [];
|
|
120
120
|
|
|
121
|
-
for (const role of roles) {
|
|
121
|
+
for (const role of roles.lists) {
|
|
122
122
|
if (!role.apis) continue;
|
|
123
123
|
|
|
124
124
|
// 解析角色的接口 ID 列表并映射到路径
|
package/lib/dbHelper.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { RedisTTL, RedisKeys } from 'befly-shared/redisKeys';
|
|
|
13
13
|
import { Logger } from './logger.js';
|
|
14
14
|
import type { WhereConditions, JoinOption } from '../types/common.js';
|
|
15
15
|
import type { BeflyContext } from '../types/befly.js';
|
|
16
|
-
import type { QueryOptions, InsertOptions, UpdateOptions, DeleteOptions, ListResult, TransactionCallback } from '../types/database.js';
|
|
16
|
+
import type { QueryOptions, InsertOptions, UpdateOptions, DeleteOptions, ListResult, AllResult, TransactionCallback } from '../types/database.js';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* 数据库助手类
|
|
@@ -691,40 +691,66 @@ export class DbHelper {
|
|
|
691
691
|
* where: { 'o.state': 1 }
|
|
692
692
|
* })
|
|
693
693
|
*/
|
|
694
|
-
async getAll<T extends Record<string, any> = Record<string, any>>(options: Omit<QueryOptions, 'page' | 'limit'>): Promise<T
|
|
694
|
+
async getAll<T extends Record<string, any> = Record<string, any>>(options: Omit<QueryOptions, 'page' | 'limit'>): Promise<AllResult<T>> {
|
|
695
695
|
// 添加硬性上限保护,防止内存溢出
|
|
696
696
|
const MAX_LIMIT = 10000;
|
|
697
697
|
const WARNING_LIMIT = 1000;
|
|
698
698
|
|
|
699
699
|
const prepared = await this.prepareQueryOptions({ ...options, page: 1, limit: 10 });
|
|
700
700
|
|
|
701
|
-
const
|
|
701
|
+
const whereFiltered = this.addDefaultStateFilter(prepared.where);
|
|
702
|
+
|
|
703
|
+
// 查询真实总数
|
|
704
|
+
const countBuilder = new SqlBuilder().select(['COUNT(*) as total']).from(prepared.table).where(whereFiltered);
|
|
705
|
+
|
|
706
|
+
// 添加 JOIN(计数也需要)
|
|
707
|
+
this.applyJoins(countBuilder, prepared.joins);
|
|
708
|
+
|
|
709
|
+
const { sql: countSql, params: countParams } = countBuilder.toSelectSql();
|
|
710
|
+
const countResult = await this.executeWithConn(countSql, countParams);
|
|
711
|
+
const total = countResult?.[0]?.total || 0;
|
|
712
|
+
|
|
713
|
+
// 如果总数为 0,直接返回
|
|
714
|
+
if (total === 0) {
|
|
715
|
+
return {
|
|
716
|
+
lists: [],
|
|
717
|
+
total: 0
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// 查询数据(受上限保护)
|
|
722
|
+
const dataBuilder = new SqlBuilder().select(prepared.fields).from(prepared.table).where(whereFiltered).limit(MAX_LIMIT);
|
|
702
723
|
|
|
703
724
|
// 添加 JOIN
|
|
704
|
-
this.applyJoins(
|
|
725
|
+
this.applyJoins(dataBuilder, prepared.joins);
|
|
705
726
|
|
|
706
727
|
if (prepared.orderBy && prepared.orderBy.length > 0) {
|
|
707
|
-
|
|
728
|
+
dataBuilder.orderBy(prepared.orderBy);
|
|
708
729
|
}
|
|
709
730
|
|
|
710
|
-
const { sql, params } =
|
|
711
|
-
const result = (await this.executeWithConn(
|
|
731
|
+
const { sql: dataSql, params: dataParams } = dataBuilder.toSelectSql();
|
|
732
|
+
const result = (await this.executeWithConn(dataSql, dataParams)) || [];
|
|
712
733
|
|
|
713
734
|
// 警告日志:返回数据超过警告阈值
|
|
714
735
|
if (result.length >= WARNING_LIMIT) {
|
|
715
|
-
Logger.warn({ table: options.table, count: result.length }, 'getAll 返回数据过多,建议使用 getList 分页查询');
|
|
736
|
+
Logger.warn({ table: options.table, count: result.length, total: total }, 'getAll 返回数据过多,建议使用 getList 分页查询');
|
|
716
737
|
}
|
|
717
738
|
|
|
718
739
|
// 如果达到上限,额外警告
|
|
719
740
|
if (result.length >= MAX_LIMIT) {
|
|
720
|
-
Logger.warn({ table: options.table, limit: MAX_LIMIT },
|
|
741
|
+
Logger.warn({ table: options.table, limit: MAX_LIMIT, total: total }, `getAll 达到最大限制 ${MAX_LIMIT},实际总数 ${total},只返回前 ${MAX_LIMIT} 条`);
|
|
721
742
|
}
|
|
722
743
|
|
|
723
744
|
// 字段名转换:下划线 → 小驼峰
|
|
724
745
|
const camelResult = arrayKeysToCamel<T>(result);
|
|
725
746
|
|
|
726
747
|
// 转换 BIGINT 字段(id, pid 等)为数字类型
|
|
727
|
-
|
|
748
|
+
const lists = this.convertBigIntFields<T>(camelResult);
|
|
749
|
+
|
|
750
|
+
return {
|
|
751
|
+
lists: lists,
|
|
752
|
+
total: total
|
|
753
|
+
};
|
|
728
754
|
}
|
|
729
755
|
|
|
730
756
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "befly",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.27",
|
|
4
4
|
"description": "Befly - 为 Bun 专属打造的 TypeScript API 接口框架核心引擎",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"pino": "^10.1.0",
|
|
75
75
|
"pino-roll": "^4.0.0"
|
|
76
76
|
},
|
|
77
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "1f449cb3921fc8536f7392f039a6655b1b07b5e5",
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"typescript": "^5.9.3"
|
|
80
80
|
}
|
package/sync/syncApi.ts
CHANGED
|
@@ -199,11 +199,11 @@ async function syncApis(helper: any, apis: ApiInfo[]): Promise<void> {
|
|
|
199
199
|
async function deleteObsoleteRecords(helper: any, apiPaths: Set<string>): Promise<void> {
|
|
200
200
|
const allRecords = await helper.getAll({
|
|
201
201
|
table: 'addon_admin_api',
|
|
202
|
-
fields: ['id', 'path'],
|
|
202
|
+
fields: ['id', 'addonName', 'path', 'method'],
|
|
203
203
|
where: { state$gte: 0 }
|
|
204
204
|
});
|
|
205
205
|
|
|
206
|
-
for (const record of allRecords) {
|
|
206
|
+
for (const record of allRecords.lists) {
|
|
207
207
|
if (record.path && !apiPaths.has(record.path)) {
|
|
208
208
|
await helper.delForce({
|
|
209
209
|
table: 'addon_admin_api',
|
|
@@ -255,7 +255,7 @@ export async function syncApiCommand(options: SyncApiOptions = {}): Promise<void
|
|
|
255
255
|
});
|
|
256
256
|
|
|
257
257
|
const redisHelper = new RedisHelper();
|
|
258
|
-
await redisHelper.setObject(RedisKeys.apisAll(), apiList);
|
|
258
|
+
await redisHelper.setObject(RedisKeys.apisAll(), apiList.lists);
|
|
259
259
|
} catch (error: any) {
|
|
260
260
|
// 忽略缓存错误
|
|
261
261
|
}
|
package/sync/syncDev.ts
CHANGED
|
@@ -64,12 +64,12 @@ export async function syncDevCommand(options: SyncDevOptions = {}): Promise<void
|
|
|
64
64
|
fields: ['id']
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
-
if (!allMenus || !Array.isArray(allMenus)) {
|
|
67
|
+
if (!allMenus || !Array.isArray(allMenus.lists)) {
|
|
68
68
|
Logger.debug('[SyncDev] 菜单数据为空,跳过开发者账号同步');
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
const menuIds = allMenus.length > 0 ? allMenus.map((m: any) => m.id).join(',') : '';
|
|
72
|
+
const menuIds = allMenus.lists.length > 0 ? allMenus.lists.map((m: any) => m.id).join(',') : '';
|
|
73
73
|
|
|
74
74
|
// 查询所有接口 ID
|
|
75
75
|
const existApi = await helper.tableExists('addon_admin_api');
|
|
@@ -80,8 +80,8 @@ export async function syncDevCommand(options: SyncDevOptions = {}): Promise<void
|
|
|
80
80
|
fields: ['id']
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
if (allApis && Array.isArray(allApis) && allApis.length > 0) {
|
|
84
|
-
apiIds = allApis.map((a: any) => a.id).join(',');
|
|
83
|
+
if (allApis && Array.isArray(allApis.lists) && allApis.lists.length > 0) {
|
|
84
|
+
apiIds = allApis.lists.map((a: any) => a.id).join(',');
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
package/sync/syncMenu.ts
CHANGED
|
@@ -91,7 +91,7 @@ async function scanViewsDir(viewsDir: string, prefix: string, parentPath: string
|
|
|
91
91
|
const menu: MenuConfig = {
|
|
92
92
|
name: meta.name,
|
|
93
93
|
path: fullPath,
|
|
94
|
-
sort: meta.order ||
|
|
94
|
+
sort: meta.order || 1
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
// 递归扫描子目录
|
|
@@ -104,7 +104,7 @@ async function scanViewsDir(viewsDir: string, prefix: string, parentPath: string
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
// 按 sort 排序
|
|
107
|
-
menus.sort((a, b) => (a.sort ||
|
|
107
|
+
menus.sort((a, b) => (a.sort || 1) - (b.sort || 1));
|
|
108
108
|
|
|
109
109
|
return menus;
|
|
110
110
|
}
|
|
@@ -192,7 +192,7 @@ async function syncMenuRecursive(helper: any, menu: MenuConfig, pid: number, exi
|
|
|
192
192
|
if (existing) {
|
|
193
193
|
menuId = existing.id;
|
|
194
194
|
|
|
195
|
-
const needUpdate = existing.pid !== pid || existing.name !== menu.name || existing.sort !== (menu.sort ||
|
|
195
|
+
const needUpdate = existing.pid !== pid || existing.name !== menu.name || existing.sort !== (menu.sort || 1);
|
|
196
196
|
|
|
197
197
|
if (needUpdate) {
|
|
198
198
|
await helper.updData({
|
|
@@ -201,7 +201,7 @@ async function syncMenuRecursive(helper: any, menu: MenuConfig, pid: number, exi
|
|
|
201
201
|
data: {
|
|
202
202
|
pid: pid,
|
|
203
203
|
name: menu.name,
|
|
204
|
-
sort: menu.sort ||
|
|
204
|
+
sort: menu.sort || 1
|
|
205
205
|
}
|
|
206
206
|
});
|
|
207
207
|
}
|
|
@@ -212,7 +212,7 @@ async function syncMenuRecursive(helper: any, menu: MenuConfig, pid: number, exi
|
|
|
212
212
|
pid: pid,
|
|
213
213
|
name: menu.name,
|
|
214
214
|
path: menu.path || '',
|
|
215
|
-
sort: menu.sort ||
|
|
215
|
+
sort: menu.sort || 1
|
|
216
216
|
}
|
|
217
217
|
});
|
|
218
218
|
}
|
|
@@ -235,7 +235,7 @@ async function syncMenus(helper: any, menus: MenuConfig[]): Promise<void> {
|
|
|
235
235
|
fields: ['id', 'pid', 'name', 'path', 'sort']
|
|
236
236
|
});
|
|
237
237
|
const existingMenuMap = new Map<string, any>();
|
|
238
|
-
for (const menu of allExistingMenus) {
|
|
238
|
+
for (const menu of allExistingMenus.lists) {
|
|
239
239
|
if (menu.path) {
|
|
240
240
|
existingMenuMap.set(menu.path, menu);
|
|
241
241
|
}
|
|
@@ -261,7 +261,7 @@ async function deleteObsoleteRecords(helper: any, configPaths: Set<string>): Pro
|
|
|
261
261
|
where: { state$gte: 0 }
|
|
262
262
|
});
|
|
263
263
|
|
|
264
|
-
for (const record of allRecords) {
|
|
264
|
+
for (const record of allRecords.lists) {
|
|
265
265
|
if (record.path && !configPaths.has(record.path)) {
|
|
266
266
|
await helper.delForce({
|
|
267
267
|
table: 'addon_admin_menu',
|
|
@@ -375,7 +375,7 @@ export async function syncMenuCommand(options: SyncMenuOptions = {}): Promise<vo
|
|
|
375
375
|
// 8. 缓存菜单数据到 Redis
|
|
376
376
|
try {
|
|
377
377
|
const redisHelper = new RedisHelper();
|
|
378
|
-
await redisHelper.setObject(RedisKeys.menusAll(), allMenusData);
|
|
378
|
+
await redisHelper.setObject(RedisKeys.menusAll(), allMenusData.lists);
|
|
379
379
|
} catch (error: any) {
|
|
380
380
|
Logger.warn({ err: error }, 'Redis 缓存菜单数据失败');
|
|
381
381
|
}
|
|
@@ -76,7 +76,7 @@ describe('CacheHelper', () => {
|
|
|
76
76
|
{ id: 1, name: '登录', path: '/api/login', method: 'POST' },
|
|
77
77
|
{ id: 2, name: '用户列表', path: '/api/user/list', method: 'GET' }
|
|
78
78
|
];
|
|
79
|
-
mockDb.getAll = mock(() => Promise.resolve(apis));
|
|
79
|
+
mockDb.getAll = mock(() => Promise.resolve({ lists: apis, total: apis.length }));
|
|
80
80
|
|
|
81
81
|
await cacheHelper.cacheApis();
|
|
82
82
|
|
|
@@ -115,7 +115,7 @@ describe('CacheHelper', () => {
|
|
|
115
115
|
{ id: 1, pid: 0, name: '首页', path: '/home', sort: 1 },
|
|
116
116
|
{ id: 2, pid: 0, name: '用户管理', path: '/user', sort: 2 }
|
|
117
117
|
];
|
|
118
|
-
mockDb.getAll = mock(() => Promise.resolve(menus));
|
|
118
|
+
mockDb.getAll = mock(() => Promise.resolve({ lists: menus, total: menus.length }));
|
|
119
119
|
|
|
120
120
|
await cacheHelper.cacheMenus();
|
|
121
121
|
|
|
@@ -148,9 +148,9 @@ describe('CacheHelper', () => {
|
|
|
148
148
|
];
|
|
149
149
|
|
|
150
150
|
mockDb.getAll = mock((opts: any) => {
|
|
151
|
-
if (opts.table === 'addon_admin_role') return Promise.resolve(roles);
|
|
152
|
-
if (opts.table === 'addon_admin_api') return Promise.resolve(apis);
|
|
153
|
-
return Promise.resolve([]);
|
|
151
|
+
if (opts.table === 'addon_admin_role') return Promise.resolve({ lists: roles, total: roles.length });
|
|
152
|
+
if (opts.table === 'addon_admin_api') return Promise.resolve({ lists: apis, total: apis.length });
|
|
153
|
+
return Promise.resolve({ lists: [], total: 0 });
|
|
154
154
|
});
|
|
155
155
|
|
|
156
156
|
await cacheHelper.cacheRolePermissions();
|
|
@@ -169,9 +169,9 @@ describe('CacheHelper', () => {
|
|
|
169
169
|
const apis = [{ id: 1, path: '/api/login', method: 'POST' }];
|
|
170
170
|
|
|
171
171
|
mockDb.getAll = mock((opts: any) => {
|
|
172
|
-
if (opts.table === 'addon_admin_role') return Promise.resolve(roles);
|
|
173
|
-
if (opts.table === 'addon_admin_api') return Promise.resolve(apis);
|
|
174
|
-
return Promise.resolve([]);
|
|
172
|
+
if (opts.table === 'addon_admin_role') return Promise.resolve({ lists: roles, total: roles.length });
|
|
173
|
+
if (opts.table === 'addon_admin_api') return Promise.resolve({ lists: apis, total: apis.length });
|
|
174
|
+
return Promise.resolve({ lists: [], total: 0 });
|
|
175
175
|
});
|
|
176
176
|
|
|
177
177
|
await cacheHelper.cacheRolePermissions();
|
|
@@ -188,9 +188,9 @@ describe('CacheHelper', () => {
|
|
|
188
188
|
const apis = [{ id: 1, path: '/api/test', method: 'GET' }];
|
|
189
189
|
|
|
190
190
|
mockDb.getAll = mock((opts: any) => {
|
|
191
|
-
if (opts.table === 'addon_admin_role') return Promise.resolve(roles);
|
|
192
|
-
if (opts.table === 'addon_admin_api') return Promise.resolve(apis);
|
|
193
|
-
return Promise.resolve([]);
|
|
191
|
+
if (opts.table === 'addon_admin_role') return Promise.resolve({ lists: roles, total: roles.length });
|
|
192
|
+
if (opts.table === 'addon_admin_api') return Promise.resolve({ lists: apis, total: apis.length });
|
|
193
|
+
return Promise.resolve({ lists: [], total: 0 });
|
|
194
194
|
});
|
|
195
195
|
|
|
196
196
|
await cacheHelper.cacheRolePermissions();
|
package/types/database.d.ts
CHANGED
|
@@ -163,6 +163,16 @@ export interface ListResult<T = any> {
|
|
|
163
163
|
pages: number;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
/**
|
|
167
|
+
* 全部查询结果
|
|
168
|
+
*/
|
|
169
|
+
export interface AllResult<T = any> {
|
|
170
|
+
/** 数据列表 */
|
|
171
|
+
lists: T[];
|
|
172
|
+
/** 总条数 */
|
|
173
|
+
total: number;
|
|
174
|
+
}
|
|
175
|
+
|
|
166
176
|
/**
|
|
167
177
|
* 事务回调函数
|
|
168
178
|
*/
|
|
@@ -269,7 +279,7 @@ export interface DbHelper {
|
|
|
269
279
|
* @template K - 表名类型
|
|
270
280
|
* @returns 返回类型自动推断为对应表的记录数组
|
|
271
281
|
*/
|
|
272
|
-
getAll<K extends TableName>(options: Omit<TypedQueryOptions<K>, 'page' | 'limit'>): Promise<TableType<K
|
|
282
|
+
getAll<K extends TableName>(options: Omit<TypedQueryOptions<K>, 'page' | 'limit'>): Promise<AllResult<TableType<K>>>;
|
|
273
283
|
|
|
274
284
|
/**
|
|
275
285
|
* 插入数据(类型安全版本)
|
|
@@ -314,7 +324,7 @@ export interface DbHelper {
|
|
|
314
324
|
* 查询所有数据(兼容版本,需手动指定泛型)
|
|
315
325
|
* @template T - 返回类型
|
|
316
326
|
*/
|
|
317
|
-
getAll<T = any>(options: Omit<QueryOptions, 'page' | 'limit'>): Promise<T
|
|
327
|
+
getAll<T = any>(options: Omit<QueryOptions, 'page' | 'limit'>): Promise<AllResult<T>>;
|
|
318
328
|
|
|
319
329
|
/**
|
|
320
330
|
* 插入数据(兼容版本)
|