befly 3.8.29 → 3.8.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/checks/checkApi.ts +2 -1
- package/checks/checkTable.ts +3 -2
- package/hooks/parser.ts +5 -3
- package/hooks/permission.ts +12 -5
- package/lib/cacheHelper.ts +76 -62
- package/lib/connect.ts +8 -35
- package/lib/dbHelper.ts +14 -11
- package/lib/jwt.ts +58 -437
- package/lib/logger.ts +76 -197
- package/lib/redisHelper.ts +163 -1
- package/lib/sqlBuilder.ts +2 -1
- package/lib/validator.ts +9 -8
- package/loader/loadApis.ts +4 -7
- package/loader/loadHooks.ts +2 -2
- package/loader/loadPlugins.ts +4 -4
- package/main.ts +4 -17
- package/package.json +9 -8
- package/paths.ts +0 -6
- package/plugins/db.ts +2 -2
- package/plugins/jwt.ts +5 -5
- package/plugins/redis.ts +1 -1
- package/router/api.ts +2 -2
- package/router/static.ts +1 -2
- package/sync/syncAll.ts +2 -2
- package/sync/syncApi.ts +10 -7
- package/sync/syncDb/apply.ts +1 -2
- package/sync/syncDb.ts +6 -10
- package/sync/syncDev.ts +10 -48
- package/sync/syncMenu.ts +11 -8
- package/tests/cacheHelper.test.ts +327 -0
- package/tests/dbHelper-columns.test.ts +5 -20
- package/tests/dbHelper-execute.test.ts +14 -68
- package/tests/fields-redis-cache.test.ts +5 -3
- package/tests/integration.test.ts +15 -26
- package/tests/jwt.test.ts +36 -94
- package/tests/logger.test.ts +32 -34
- package/tests/redisHelper.test.ts +270 -0
- package/tests/redisKeys.test.ts +76 -0
- package/tests/sync-connection.test.ts +0 -6
- package/tests/syncDb-constants.test.ts +12 -12
- package/tests/util.test.ts +5 -1
- package/types/befly.d.ts +2 -15
- package/types/common.d.ts +11 -93
- package/types/database.d.ts +216 -5
- package/types/index.ts +1 -0
- package/types/logger.d.ts +11 -41
- package/types/table.d.ts +213 -0
- package/hooks/_rateLimit.ts +0 -64
- package/lib/regexAliases.ts +0 -59
- package/lib/xml.ts +0 -383
- package/tests/xml.test.ts +0 -101
package/main.ts
CHANGED
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// ========== 外部依赖 ==========
|
|
7
|
-
import { calcPerfTime } from 'befly-
|
|
7
|
+
import { calcPerfTime } from 'befly-shared/calcPerfTime';
|
|
8
8
|
|
|
9
9
|
// ========== 相对导入 ==========
|
|
10
10
|
import { Logger } from './lib/logger.js';
|
|
11
11
|
import { Cipher } from './lib/cipher.js';
|
|
12
|
-
import { Jwt } from './lib/jwt.js';
|
|
13
12
|
import { Connect } from './lib/connect.js';
|
|
14
13
|
import { DbHelper } from './lib/dbHelper.js';
|
|
15
14
|
import { RedisHelper } from './lib/redisHelper.js';
|
|
@@ -103,7 +102,7 @@ export class Befly {
|
|
|
103
102
|
'/*': staticHandler(this.config)
|
|
104
103
|
},
|
|
105
104
|
error: (error: Error) => {
|
|
106
|
-
Logger.error('服务启动时发生错误'
|
|
105
|
+
Logger.error({ err: error }, '服务启动时发生错误');
|
|
107
106
|
return Response.json({ code: 1, msg: '内部服务器错误' });
|
|
108
107
|
}
|
|
109
108
|
});
|
|
@@ -128,7 +127,7 @@ export class Befly {
|
|
|
128
127
|
await Connect.disconnect();
|
|
129
128
|
Logger.info('数据库连接已关闭');
|
|
130
129
|
} catch (error: any) {
|
|
131
|
-
Logger.error('
|
|
130
|
+
Logger.error({ err: error }, '关闭数据库连接时出错');
|
|
132
131
|
}
|
|
133
132
|
|
|
134
133
|
Logger.info('服务器已优雅关闭');
|
|
@@ -140,20 +139,8 @@ export class Befly {
|
|
|
140
139
|
|
|
141
140
|
return server;
|
|
142
141
|
} catch (error: any) {
|
|
143
|
-
Logger.error('项目启动失败'
|
|
142
|
+
Logger.error({ err: error }, '项目启动失败');
|
|
144
143
|
process.exit(1);
|
|
145
144
|
}
|
|
146
145
|
}
|
|
147
146
|
}
|
|
148
|
-
|
|
149
|
-
// 核心类和工具导出
|
|
150
|
-
export {
|
|
151
|
-
// 配置
|
|
152
|
-
Logger,
|
|
153
|
-
Cipher,
|
|
154
|
-
Jwt,
|
|
155
|
-
Database,
|
|
156
|
-
DbHelper,
|
|
157
|
-
RedisHelper,
|
|
158
|
-
coreDir
|
|
159
|
-
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "befly",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.30",
|
|
4
4
|
"description": "Befly - 为 Bun 专属打造的 TypeScript API 接口框架核心引擎",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -15,10 +15,7 @@
|
|
|
15
15
|
"types": "./main.ts",
|
|
16
16
|
"default": "./main.ts"
|
|
17
17
|
},
|
|
18
|
-
"
|
|
19
|
-
"types": "./types/index.ts",
|
|
20
|
-
"default": "./types/index.ts"
|
|
21
|
-
}
|
|
18
|
+
"./*": "./*"
|
|
22
19
|
},
|
|
23
20
|
"scripts": {
|
|
24
21
|
"bundler": "bun build ./main.ts --outfile ./main.single.ts --minify --target bun"
|
|
@@ -66,12 +63,16 @@
|
|
|
66
63
|
"bun": ">=1.3.0"
|
|
67
64
|
},
|
|
68
65
|
"dependencies": {
|
|
69
|
-
"befly-
|
|
66
|
+
"befly-shared": "^1.1.1",
|
|
70
67
|
"chalk": "^5.6.2",
|
|
71
68
|
"es-toolkit": "^1.42.0",
|
|
72
|
-
"
|
|
69
|
+
"fast-jwt": "^6.0.2",
|
|
70
|
+
"fast-xml-parser": "^5.3.2",
|
|
71
|
+
"pathe": "^2.0.3",
|
|
72
|
+
"pino": "^10.1.0",
|
|
73
|
+
"pino-roll": "^4.0.0"
|
|
73
74
|
},
|
|
74
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "2031550167896390ac58c50aeb52b8c23426844e",
|
|
75
76
|
"devDependencies": {
|
|
76
77
|
"typescript": "^5.9.3"
|
|
77
78
|
}
|
package/paths.ts
CHANGED
|
@@ -46,9 +46,6 @@ export const corePluginDir = join(__dirname, 'plugins');
|
|
|
46
46
|
*/
|
|
47
47
|
export const coreHookDir = join(__dirname, 'hooks');
|
|
48
48
|
|
|
49
|
-
/**
|
|
50
|
-
* Core 框架 API 目录
|
|
51
|
-
|
|
52
49
|
/**
|
|
53
50
|
* Core 框架 API 目录
|
|
54
51
|
* @description packages/core/apis/
|
|
@@ -93,9 +90,6 @@ export const projectPluginDir = join(projectDir, 'plugins');
|
|
|
93
90
|
*/
|
|
94
91
|
export const projectHookDir = join(projectDir, 'hooks');
|
|
95
92
|
|
|
96
|
-
/**
|
|
97
|
-
* 项目 API 目录
|
|
98
|
-
|
|
99
93
|
/**
|
|
100
94
|
* 项目 API 目录
|
|
101
95
|
* @description {projectDir}/apis/
|
package/plugins/db.ts
CHANGED
|
@@ -26,14 +26,14 @@ const dbPlugin: Plugin = {
|
|
|
26
26
|
|
|
27
27
|
return dbManager;
|
|
28
28
|
} catch (error: any) {
|
|
29
|
-
Logger.error('数据库初始化失败'
|
|
29
|
+
Logger.error({ err: error }, '数据库初始化失败');
|
|
30
30
|
|
|
31
31
|
// 清理资源
|
|
32
32
|
if (sql) {
|
|
33
33
|
try {
|
|
34
34
|
await sql.close();
|
|
35
35
|
} catch (cleanupError: any) {
|
|
36
|
-
Logger.error('
|
|
36
|
+
Logger.error({ err: cleanupError }, '清理连接池失败');
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
package/plugins/jwt.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JWT 插件
|
|
3
|
-
* 提供 JSON Web Token 签名和验证功能
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
import { Jwt } from '../lib/jwt.js';
|
|
7
6
|
|
|
8
7
|
import type { Plugin } from '../types/plugin.js';
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
name: 'jwt',
|
|
9
|
+
const jwtPlugin: Plugin = {
|
|
12
10
|
handler: (context, config) => {
|
|
13
|
-
return Jwt;
|
|
11
|
+
return new Jwt(config?.auth);
|
|
14
12
|
}
|
|
15
|
-
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default jwtPlugin;
|
package/plugins/redis.ts
CHANGED
package/router/api.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// 外部依赖
|
|
7
|
-
import { genShortId } from 'befly-
|
|
7
|
+
import { genShortId } from 'befly-shared/genShortId';
|
|
8
8
|
|
|
9
9
|
// 相对导入
|
|
10
10
|
import { FinalResponse } from '../util.js';
|
|
@@ -88,7 +88,7 @@ export function apiHandler(apis: Map<string, ApiRoute>, hooks: Hook[], context:
|
|
|
88
88
|
} catch (err: any) {
|
|
89
89
|
// 全局错误处理
|
|
90
90
|
const errorPath = ctx.api ? apiPath : req.url;
|
|
91
|
-
Logger.error(
|
|
91
|
+
Logger.error({ err: err, path: errorPath }, '请求错误');
|
|
92
92
|
ctx.result = {
|
|
93
93
|
code: 1,
|
|
94
94
|
msg: '内部服务错误'
|
package/router/static.ts
CHANGED
package/sync/syncAll.ts
CHANGED
|
@@ -32,9 +32,9 @@ export async function syncAllCommand(config: BeflyOptions, options: SyncOptions
|
|
|
32
32
|
|
|
33
33
|
// 输出总结
|
|
34
34
|
const totalTimeSeconds = ((Date.now() - startTime) / 1000).toFixed(2);
|
|
35
|
-
Logger.info(
|
|
35
|
+
Logger.info({ duration: totalTimeSeconds }, '同步完成');
|
|
36
36
|
} catch (error: any) {
|
|
37
|
-
Logger.error('同步过程中发生错误'
|
|
37
|
+
Logger.error({ err: error }, '同步过程中发生错误');
|
|
38
38
|
throw error;
|
|
39
39
|
}
|
|
40
40
|
}
|
package/sync/syncApi.ts
CHANGED
|
@@ -13,8 +13,11 @@
|
|
|
13
13
|
import { readdirSync, statSync } from 'node:fs';
|
|
14
14
|
import { join, dirname, relative, basename } from 'pathe';
|
|
15
15
|
import { Connect } from '../lib/connect.js';
|
|
16
|
+
import { DbHelper } from '../lib/dbHelper.js';
|
|
16
17
|
import { RedisHelper } from '../lib/redisHelper.js';
|
|
17
|
-
import {
|
|
18
|
+
import { RedisKeys } from 'befly-shared/redisKeys';
|
|
19
|
+
import { scanFiles } from 'befly-shared/scanFiles';
|
|
20
|
+
import { scanAddons, addonDirExists, getAddonDir } from 'befly-shared/addonHelper';
|
|
18
21
|
|
|
19
22
|
import { Logger } from '../lib/logger.js';
|
|
20
23
|
import { projectDir } from '../paths.js';
|
|
@@ -59,7 +62,7 @@ async function extractApiInfo(filePath: string, apiRoot: string, type: 'app' | '
|
|
|
59
62
|
addonTitle: addonTitle || addonName
|
|
60
63
|
};
|
|
61
64
|
} catch (error: any) {
|
|
62
|
-
Logger.error('同步 API
|
|
65
|
+
Logger.error({ err: error }, '同步 API 失败');
|
|
63
66
|
throw error;
|
|
64
67
|
}
|
|
65
68
|
}
|
|
@@ -136,7 +139,7 @@ async function scanAllApis(projectRoot: string): Promise<ApiInfo[]> {
|
|
|
136
139
|
|
|
137
140
|
return apis;
|
|
138
141
|
} catch (error: any) {
|
|
139
|
-
Logger.error(
|
|
142
|
+
Logger.error({ err: error }, '接口扫描失败');
|
|
140
143
|
return apis;
|
|
141
144
|
}
|
|
142
145
|
}
|
|
@@ -184,7 +187,7 @@ async function syncApis(helper: any, apis: ApiInfo[]): Promise<void> {
|
|
|
184
187
|
});
|
|
185
188
|
}
|
|
186
189
|
} catch (error: any) {
|
|
187
|
-
Logger.error(
|
|
190
|
+
Logger.error({ err: error, api: api.name }, '同步接口失败');
|
|
188
191
|
}
|
|
189
192
|
}
|
|
190
193
|
}
|
|
@@ -222,7 +225,7 @@ export async function syncApiCommand(config: BeflyOptions, options: SyncApiOptio
|
|
|
222
225
|
// 连接数据库(SQL + Redis)
|
|
223
226
|
await Connect.connect(config);
|
|
224
227
|
|
|
225
|
-
const helper = Connect.
|
|
228
|
+
const helper = new DbHelper({ redis: new RedisHelper() } as any, Connect.getSql());
|
|
226
229
|
|
|
227
230
|
// 1. 检查表是否存在(addon_admin_api 来自 addon-admin 组件)
|
|
228
231
|
const exists = await helper.tableExists('addon_admin_api');
|
|
@@ -251,12 +254,12 @@ export async function syncApiCommand(config: BeflyOptions, options: SyncApiOptio
|
|
|
251
254
|
});
|
|
252
255
|
|
|
253
256
|
const redisHelper = new RedisHelper();
|
|
254
|
-
await redisHelper.setObject(
|
|
257
|
+
await redisHelper.setObject(RedisKeys.apisAll(), apiList);
|
|
255
258
|
} catch (error: any) {
|
|
256
259
|
// 忽略缓存错误
|
|
257
260
|
}
|
|
258
261
|
} catch (error: any) {
|
|
259
|
-
Logger.error('API
|
|
262
|
+
Logger.error({ err: error }, 'API 同步失败');
|
|
260
263
|
throw error;
|
|
261
264
|
} finally {
|
|
262
265
|
await Connect.disconnect();
|
package/sync/syncDb/apply.ts
CHANGED
|
@@ -175,8 +175,7 @@ export async function applyTablePlan(sql: SQL, tableName: string, fields: Record
|
|
|
175
175
|
Logger.debug(`[索引变化] 删除索引 ${tableName}.${act.indexName} (${act.fieldName})`);
|
|
176
176
|
}
|
|
177
177
|
} catch (error: any) {
|
|
178
|
-
Logger.error(`${act.action === 'create' ? '创建' : '删除'}
|
|
179
|
-
Logger.warn(`表名: ${tableName}, 索引名: ${act.indexName}, 字段: ${act.fieldName}`);
|
|
178
|
+
Logger.error({ err: error, table: tableName, index: act.indexName, field: act.fieldName }, `${act.action === 'create' ? '创建' : '删除'}索引失败`);
|
|
180
179
|
throw error;
|
|
181
180
|
}
|
|
182
181
|
}
|
package/sync/syncDb.ts
CHANGED
|
@@ -13,7 +13,9 @@ import { snakeCase } from 'es-toolkit/string';
|
|
|
13
13
|
import { Connect } from '../lib/connect.js';
|
|
14
14
|
import { RedisHelper } from '../lib/redisHelper.js';
|
|
15
15
|
import { checkTable } from '../checks/checkTable.js';
|
|
16
|
-
import { scanFiles
|
|
16
|
+
import { scanFiles } from 'befly-shared/scanFiles';
|
|
17
|
+
import { scanAddons, addonDirExists, getAddonDir } from 'befly-shared/addonHelper';
|
|
18
|
+
import { RedisKeys } from 'befly-shared/redisKeys';
|
|
17
19
|
import { Logger } from '../lib/logger.js';
|
|
18
20
|
import { projectDir } from '../paths.js';
|
|
19
21
|
|
|
@@ -134,17 +136,11 @@ export async function syncDbCommand(config: BeflyOptions, options: SyncDbOptions
|
|
|
134
136
|
// 清理 Redis 缓存(如果有表被处理)
|
|
135
137
|
if (processedTables.length > 0) {
|
|
136
138
|
const redisHelper = new RedisHelper();
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
await redisHelper.del(cacheKey);
|
|
141
|
-
} catch (error: any) {
|
|
142
|
-
Logger.warn(`清理表 ${tableName} 的缓存失败: ${error.message}`);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
139
|
+
const cacheKeys = processedTables.map((tableName) => RedisKeys.tableColumns(tableName));
|
|
140
|
+
await redisHelper.delBatch(cacheKeys);
|
|
145
141
|
}
|
|
146
142
|
} catch (error: any) {
|
|
147
|
-
Logger.error('数据库同步失败'
|
|
143
|
+
Logger.error({ err: error }, '数据库同步失败');
|
|
148
144
|
throw error;
|
|
149
145
|
} finally {
|
|
150
146
|
if (sql) {
|
package/sync/syncDev.ts
CHANGED
|
@@ -7,12 +7,15 @@
|
|
|
7
7
|
* - 表名: addon_admin_admin
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { scanAddons, getAddonDir, normalizeModuleForSync } from 'befly-
|
|
10
|
+
import { scanAddons, getAddonDir, normalizeModuleForSync } from 'befly-shared/addonHelper';
|
|
11
11
|
|
|
12
12
|
import { Logger } from '../lib/logger.js';
|
|
13
13
|
import { Cipher } from '../lib/cipher.js';
|
|
14
14
|
import { Connect } from '../lib/connect.js';
|
|
15
15
|
import { DbHelper } from '../lib/dbHelper.js';
|
|
16
|
+
import { RedisHelper } from '../lib/redisHelper.js';
|
|
17
|
+
import { CacheHelper } from '../lib/cacheHelper.js';
|
|
18
|
+
|
|
16
19
|
import type { SyncDevOptions, SyncDevStats, BeflyOptions } from '../types/index.js';
|
|
17
20
|
|
|
18
21
|
/**
|
|
@@ -33,7 +36,7 @@ export async function syncDevCommand(config: BeflyOptions, options: SyncDevOptio
|
|
|
33
36
|
// 连接数据库(SQL + Redis)
|
|
34
37
|
await Connect.connect(config);
|
|
35
38
|
|
|
36
|
-
const helper = Connect.
|
|
39
|
+
const helper = new DbHelper({ redis: new RedisHelper() } as any, Connect.getSql());
|
|
37
40
|
|
|
38
41
|
// 检查 addon_admin_admin 表是否存在
|
|
39
42
|
const existAdmin = await helper.tableExists('addon_admin_admin');
|
|
@@ -152,57 +155,16 @@ export async function syncDevCommand(config: BeflyOptions, options: SyncDevOptio
|
|
|
152
155
|
});
|
|
153
156
|
}
|
|
154
157
|
|
|
155
|
-
// 缓存角色权限数据到 Redis
|
|
158
|
+
// 缓存角色权限数据到 Redis(复用 CacheHelper 逻辑)
|
|
156
159
|
try {
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (apiTableExists && roleTableExists) {
|
|
162
|
-
// 查询所有角色
|
|
163
|
-
const roles = await helper.getAll({
|
|
164
|
-
table: 'addon_admin_role',
|
|
165
|
-
fields: ['id', 'code', 'apis']
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// 查询所有接口
|
|
169
|
-
const allApis = await helper.getAll({
|
|
170
|
-
table: 'addon_admin_api',
|
|
171
|
-
fields: ['id', 'name', 'path', 'method', 'description', 'addonName']
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
const redis = Connect.getRedis();
|
|
175
|
-
|
|
176
|
-
// 为每个角色缓存接口权限
|
|
177
|
-
for (const role of roles) {
|
|
178
|
-
if (!role.apis) continue;
|
|
179
|
-
|
|
180
|
-
// 解析角色的接口 ID 列表
|
|
181
|
-
const apiIds = role.apis
|
|
182
|
-
.split(',')
|
|
183
|
-
.map((id: string) => parseInt(id.trim()))
|
|
184
|
-
.filter((id: number) => !isNaN(id));
|
|
185
|
-
|
|
186
|
-
// 根据 ID 过滤出接口路径
|
|
187
|
-
const roleApiPaths = allApis.filter((api: any) => apiIds.includes(api.id)).map((api: any) => `${api.method}${api.path}`);
|
|
188
|
-
|
|
189
|
-
if (roleApiPaths.length === 0) continue;
|
|
190
|
-
|
|
191
|
-
// 使用 Redis Set 缓存角色权限
|
|
192
|
-
const redisKey = `role:apis:${role.code}`;
|
|
193
|
-
|
|
194
|
-
// 先删除旧数据
|
|
195
|
-
await redis.del(redisKey);
|
|
196
|
-
|
|
197
|
-
// 批量添加到 Set(使用扩展运算符展开数组)
|
|
198
|
-
await redis.sadd(redisKey, ...roleApiPaths);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
160
|
+
const tempBefly = { db: helper, redis: new RedisHelper() } as any;
|
|
161
|
+
const cacheHelper = new CacheHelper(tempBefly);
|
|
162
|
+
await cacheHelper.cacheRolePermissions();
|
|
201
163
|
} catch (error: any) {
|
|
202
164
|
// 忽略缓存错误
|
|
203
165
|
}
|
|
204
166
|
} catch (error: any) {
|
|
205
|
-
Logger.error('同步开发者管理员失败'
|
|
167
|
+
Logger.error({ err: error }, '同步开发者管理员失败');
|
|
206
168
|
throw error;
|
|
207
169
|
} finally {
|
|
208
170
|
await Connect.disconnect();
|
package/sync/syncMenu.ts
CHANGED
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
import { join } from 'pathe';
|
|
18
18
|
import { cloneDeep } from 'es-toolkit';
|
|
19
19
|
import { Connect } from '../lib/connect.js';
|
|
20
|
+
import { DbHelper } from '../lib/dbHelper.js';
|
|
20
21
|
import { RedisHelper } from '../lib/redisHelper.js';
|
|
21
|
-
import {
|
|
22
|
+
import { RedisKeys } from 'befly-shared/redisKeys';
|
|
23
|
+
import { scanAddons, getAddonDir } from 'befly-shared/addonHelper';
|
|
24
|
+
import { scanConfig } from 'befly-shared/scanConfig';
|
|
22
25
|
import { Logger } from '../lib/logger.js';
|
|
23
26
|
import { projectDir } from '../paths.js';
|
|
24
27
|
|
|
@@ -204,7 +207,7 @@ async function syncMenus(helper: any, menus: MenuConfig[]): Promise<void> {
|
|
|
204
207
|
try {
|
|
205
208
|
await syncMenuRecursive(helper, menu, 0, existingMenuMap, 1);
|
|
206
209
|
} catch (error: any) {
|
|
207
|
-
Logger.error(
|
|
210
|
+
Logger.error({ err: error, menu: menu.name }, '同步菜单失败');
|
|
208
211
|
throw error;
|
|
209
212
|
}
|
|
210
213
|
}
|
|
@@ -257,7 +260,7 @@ async function loadMenuConfigs(): Promise<Array<{ menus: MenuConfig[]; addonName
|
|
|
257
260
|
allMenus.push({ menus: menusWithPrefix, addonName: addonName });
|
|
258
261
|
}
|
|
259
262
|
} catch (error: any) {
|
|
260
|
-
Logger.warn(
|
|
263
|
+
Logger.warn({ err: error, addon: addonName }, '读取 addon 配置失败');
|
|
261
264
|
}
|
|
262
265
|
}
|
|
263
266
|
|
|
@@ -276,7 +279,7 @@ async function loadMenuConfigs(): Promise<Array<{ menus: MenuConfig[]; addonName
|
|
|
276
279
|
allMenus.push({ menus: appMenus, addonName: 'app' });
|
|
277
280
|
}
|
|
278
281
|
} catch (error: any) {
|
|
279
|
-
Logger.warn(
|
|
282
|
+
Logger.warn({ err: error }, '读取项目配置失败');
|
|
280
283
|
}
|
|
281
284
|
|
|
282
285
|
return allMenus;
|
|
@@ -301,7 +304,7 @@ export async function syncMenuCommand(config: BeflyOptions, options: SyncMenuOpt
|
|
|
301
304
|
// 连接数据库(SQL + Redis)
|
|
302
305
|
await Connect.connect(config);
|
|
303
306
|
|
|
304
|
-
const helper = Connect.
|
|
307
|
+
const helper = new DbHelper({ redis: new RedisHelper() } as any, Connect.getSql());
|
|
305
308
|
|
|
306
309
|
// 3. 检查表是否存在(addon_admin_menu 来自 addon-admin 组件)
|
|
307
310
|
const exists = await helper.tableExists('addon_admin_menu');
|
|
@@ -330,12 +333,12 @@ export async function syncMenuCommand(config: BeflyOptions, options: SyncMenuOpt
|
|
|
330
333
|
// 8. 缓存菜单数据到 Redis
|
|
331
334
|
try {
|
|
332
335
|
const redisHelper = new RedisHelper();
|
|
333
|
-
await redisHelper.setObject(
|
|
336
|
+
await redisHelper.setObject(RedisKeys.menusAll(), allMenusData);
|
|
334
337
|
} catch (error: any) {
|
|
335
|
-
Logger.warn(
|
|
338
|
+
Logger.warn({ err: error }, 'Redis 缓存菜单数据失败');
|
|
336
339
|
}
|
|
337
340
|
} catch (error: any) {
|
|
338
|
-
Logger.error('菜单同步失败'
|
|
341
|
+
Logger.error({ err: error }, '菜单同步失败');
|
|
339
342
|
throw error;
|
|
340
343
|
} finally {
|
|
341
344
|
await Connect.disconnect();
|