befly 3.5.0 → 3.5.2

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.
@@ -32,6 +32,13 @@ interface ApiInfo {
32
32
  addonTitle: string;
33
33
  }
34
34
 
35
+ export interface SyncApiStats {
36
+ totalApis: number;
37
+ created: number;
38
+ updated: number;
39
+ deleted: number;
40
+ }
41
+
35
42
  /**
36
43
  * 递归扫描目录下的所有 .ts 文件
37
44
  */
@@ -111,36 +118,29 @@ async function scanAllApis(projectRoot: string): Promise<ApiInfo[]> {
111
118
  const apis: ApiInfo[] = [];
112
119
 
113
120
  // 1. 扫描 Core 框架 API
114
- Logger.info('=== 扫描 Core 框架 API (core/apis) ===');
115
121
  const coreApisDir = join(dirname(projectRoot), 'core', 'apis');
116
122
  try {
117
123
  const coreApiFiles = scanTsFiles(coreApisDir);
118
- Logger.info(` 找到 ${coreApiFiles.length} 个核心 API 文件`);
119
124
 
120
125
  for (const filePath of coreApiFiles) {
121
126
  const apiInfo = await extractApiInfo(filePath, coreApisDir, 'core', '', '核心接口');
122
127
  if (apiInfo) {
123
128
  apis.push(apiInfo);
124
- Logger.info(` └ ${apiInfo.path} - ${apiInfo.name}`);
125
129
  }
126
130
  }
127
131
 
128
132
  // 2. 扫描项目 API
129
- Logger.info('\n=== 扫描项目 API (apis) ===');
130
133
  const projectApisDir = join(projectRoot, 'apis');
131
134
  const projectApiFiles = scanTsFiles(projectApisDir);
132
- Logger.info(` 找到 ${projectApiFiles.length} 个项目 API 文件`);
133
135
 
134
136
  for (const filePath of projectApiFiles) {
135
137
  const apiInfo = await extractApiInfo(filePath, projectApisDir, 'app', '', '项目接口');
136
138
  if (apiInfo) {
137
139
  apis.push(apiInfo);
138
- Logger.info(` └ ${apiInfo.path} - ${apiInfo.name}`);
139
140
  }
140
141
  }
141
142
 
142
143
  // 3. 扫描组件 API (node_modules/@befly-addon/*)
143
- Logger.info('\n=== 扫描组件 API (node_modules/@befly-addon/*) ===');
144
144
  const addonNames = scanAddons();
145
145
 
146
146
  for (const addonName of addonNames) {
@@ -148,7 +148,6 @@ async function scanAllApis(projectRoot: string): Promise<ApiInfo[]> {
148
148
 
149
149
  // 检查 apis 子目录是否存在
150
150
  if (!addonDirExists(addonName, 'apis')) {
151
- Logger.info(` [${addonName}] 无 apis 目录,跳过`);
152
151
  continue;
153
152
  }
154
153
 
@@ -162,17 +161,15 @@ async function scanAllApis(projectRoot: string): Promise<ApiInfo[]> {
162
161
  const config = await configFile.json();
163
162
  addonTitle = config.title || addonName;
164
163
  } catch (error) {
165
- Logger.debug(` [${addonName}] 无法读取配置文件,使用默认标题`);
164
+ // 忽略配置读取错误
166
165
  }
167
166
 
168
167
  const addonApiFiles = scanTsFiles(addonApisDir);
169
- Logger.info(` [${addonName}] 找到 ${addonApiFiles.length} 个 API 文件`);
170
168
 
171
169
  for (const filePath of addonApiFiles) {
172
170
  const apiInfo = await extractApiInfo(filePath, addonApisDir, 'addon', addonName, addonTitle);
173
171
  if (apiInfo) {
174
172
  apis.push(apiInfo);
175
- Logger.info(` └ ${apiInfo.path} - ${apiInfo.name}`);
176
173
  }
177
174
  }
178
175
  }
@@ -180,6 +177,7 @@ async function scanAllApis(projectRoot: string): Promise<ApiInfo[]> {
180
177
  return apis;
181
178
  } catch (error: any) {
182
179
  Logger.error(`接口扫描失败:`, error);
180
+ return apis;
183
181
  }
184
182
  }
185
183
 
@@ -191,6 +189,7 @@ async function syncApis(helper: any, apis: ApiInfo[]): Promise<{ created: number
191
189
 
192
190
  for (const api of apis) {
193
191
  try {
192
+ // 根据 path 查询是否存在
194
193
  const existing = await helper.getOne({
195
194
  table: 'core_api',
196
195
  where: { path: api.path }
@@ -209,7 +208,6 @@ async function syncApis(helper: any, apis: ApiInfo[]): Promise<{ created: number
209
208
  }
210
209
  });
211
210
  stats.updated++;
212
- Logger.info(` └ 更新接口: ${api.name} (ID: ${existing.id}, Path: ${api.path})`);
213
211
  } else {
214
212
  const id = await helper.insData({
215
213
  table: 'core_api',
@@ -223,7 +221,6 @@ async function syncApis(helper: any, apis: ApiInfo[]): Promise<{ created: number
223
221
  }
224
222
  });
225
223
  stats.created++;
226
- Logger.info(` └ 新增接口: ${api.name} (ID: ${id}, Path: ${api.path})`);
227
224
  }
228
225
  } catch (error: any) {
229
226
  Logger.error(`同步接口 "${api.name}" 失败:`, error);
@@ -237,8 +234,6 @@ async function syncApis(helper: any, apis: ApiInfo[]): Promise<{ created: number
237
234
  * 删除配置中不存在的记录
238
235
  */
239
236
  async function deleteObsoleteRecords(helper: any, apiPaths: Set<string>): Promise<number> {
240
- Logger.info(`\n=== 删除配置中不存在的记录 ===`);
241
-
242
237
  const allRecords = await helper.getAll({
243
238
  table: 'core_api',
244
239
  fields: ['id', 'path', 'name'],
@@ -253,34 +248,22 @@ async function deleteObsoleteRecords(helper: any, apiPaths: Set<string>): Promis
253
248
  where: { id: record.id }
254
249
  });
255
250
  deletedCount++;
256
- Logger.info(` └ 删除记录: ${record.name} (ID: ${record.id}, path: ${record.path})`);
257
251
  }
258
252
  }
259
253
 
260
- if (deletedCount === 0) {
261
- Logger.info(' ✅ 无需删除的记录');
262
- }
263
-
264
254
  return deletedCount;
265
255
  }
266
256
 
267
257
  /**
268
258
  * SyncApi 命令主函数
269
259
  */
270
- export async function syncApiCommand(options: SyncApiOptions = {}) {
260
+ export async function syncApiCommand(options: SyncApiOptions = {}): Promise<SyncApiStats> {
271
261
  try {
272
262
  if (options.plan) {
273
263
  Logger.info('[计划] 同步 API 接口到数据库(plan 模式不执行)');
274
- Logger.info('[计划] 1. 扫描 apis addons/*/apis 目录');
275
- Logger.info('[计划] 2. 提取每个 API 的配置信息');
276
- Logger.info('[计划] 3. 根据 path 检查接口是否存在');
277
- Logger.info('[计划] 4. 存在则更新,不存在则新增');
278
- Logger.info('[计划] 5. 删除文件中不存在的接口记录');
279
- return;
264
+ return { totalApis: 0, created: 0, updated: 0, deleted: 0 };
280
265
  }
281
266
 
282
- Logger.info('开始同步 API 接口到数据库...\n');
283
-
284
267
  const projectRoot = process.cwd();
285
268
 
286
269
  // 连接数据库(SQL + Redis)
@@ -289,7 +272,6 @@ export async function syncApiCommand(options: SyncApiOptions = {}) {
289
272
  const helper = Database.getDbHelper();
290
273
 
291
274
  // 1. 检查表是否存在
292
- Logger.info('=== 检查数据表 ===');
293
275
  const exists = await helper.tableExists('core_api');
294
276
 
295
277
  if (!exists) {
@@ -297,30 +279,17 @@ export async function syncApiCommand(options: SyncApiOptions = {}) {
297
279
  process.exit(1);
298
280
  }
299
281
 
300
- Logger.info(`✅ 表 core_api 存在\n`);
301
-
302
282
  // 2. 扫描所有 API 文件
303
- Logger.info('=== 步骤 2: 扫描 API 文件 ===');
304
283
  const apis = await scanAllApis(projectRoot);
305
284
  const apiPaths = new Set(apis.map((api) => api.path));
306
- Logger.info(`\n✅ 共扫描到 ${apis.length} 个 API 接口\n`);
307
285
 
308
286
  // 3. 同步 API 数据
309
- Logger.info('=== 步骤 3: 同步 API 数据(新增/更新) ===');
310
287
  const stats = await syncApis(helper, apis);
311
288
 
312
289
  // 4. 删除文件中不存在的接口
313
290
  const deletedCount = await deleteObsoleteRecords(helper, apiPaths);
314
291
 
315
- // 5. 输出统计信息
316
- Logger.info(`\n=== 接口同步完成 ===`);
317
- Logger.info(`新增接口: ${stats.created} 个`);
318
- Logger.info(`更新接口: ${stats.updated} 个`);
319
- Logger.info(`删除接口: ${deletedCount} 个`);
320
- Logger.info(`当前总接口数: ${apis.length} 个`);
321
-
322
- // 6. 缓存接口数据到 Redis
323
- Logger.info('\n=== 步骤 4: 缓存接口数据到 Redis ===');
292
+ // 5. 缓存接口数据到 Redis
324
293
  try {
325
294
  const apiList = await helper.getAll({
326
295
  table: 'core_api',
@@ -328,16 +297,17 @@ export async function syncApiCommand(options: SyncApiOptions = {}) {
328
297
  orderBy: ['addonName#ASC', 'path#ASC']
329
298
  });
330
299
 
331
- const result = await RedisHelper.setObject('apis:all', apiList);
332
-
333
- if (result === null) {
334
- Logger.warn('⚠️ 接口缓存失败');
335
- } else {
336
- Logger.info(`✅ 已缓存 ${apiList.length} 个接口到 Redis (Key: apis:all)`);
337
- }
300
+ await RedisHelper.setObject('apis:all', apiList);
338
301
  } catch (error: any) {
339
- Logger.error('⚠️ 接口缓存异常:', error);
302
+ // 忽略缓存错误
340
303
  }
304
+
305
+ return {
306
+ totalApis: apis.length,
307
+ created: stats.created,
308
+ updated: stats.updated,
309
+ deleted: deletedCount
310
+ };
341
311
  } catch (error: any) {
342
312
  Logger.error('API 同步失败:', error);
343
313
  process.exit(1);
@@ -41,6 +41,21 @@ const globalCount: Record<string, number> = {
41
41
  indexDrop: 0
42
42
  };
43
43
 
44
+ // 导出统计接口
45
+ export interface SyncDbStats {
46
+ processedTables: number;
47
+ createdTables: number;
48
+ modifiedTables: number;
49
+ addFields: number;
50
+ nameChanges: number;
51
+ typeChanges: number;
52
+ minChanges: number;
53
+ maxChanges: number;
54
+ defaultChanges: number;
55
+ indexCreate: number;
56
+ indexDrop: number;
57
+ }
58
+
44
59
  /**
45
60
  * 主同步函数
46
61
  *
@@ -49,15 +64,13 @@ const globalCount: Record<string, number> = {
49
64
  * 2. 建立数据库连接并检查版本
50
65
  * 3. 扫描表定义文件(核心表、项目表、addon表)
51
66
  * 4. 对比并应用表结构变更
52
- * 5. 输出统计信息
67
+ * 5. 返回统计信息
53
68
  */
54
- export const SyncDb = async (): Promise<void> => {
69
+ export const SyncDb = async (): Promise<SyncDbStats> => {
55
70
  const perfTracker = new PerformanceTracker();
56
71
  const progressLogger = new ProgressLogger();
57
72
 
58
73
  try {
59
- Logger.info('开始数据库表结构同步...');
60
-
61
74
  // 重置全局统计,避免多次调用累加
62
75
  for (const k of Object.keys(globalCount)) {
63
76
  if (typeof globalCount[k] === 'number') globalCount[k] = 0;
@@ -68,13 +81,11 @@ export const SyncDb = async (): Promise<void> => {
68
81
  if (!(await checkTable())) {
69
82
  throw new Error('表定义验证失败');
70
83
  }
71
- Logger.info(`✓ 表定义验证完成,耗时: ${perfTracker.getPhaseTime('表定义验证')}`);
72
84
 
73
85
  // 阶段2:建立数据库连接并检查版本
74
86
  perfTracker.markPhase('数据库连接');
75
87
  sql = await Database.connectSql({ max: 1 });
76
88
  await ensureDbVersion(sql);
77
- Logger.info(`✓ 数据库连接建立,耗时: ${perfTracker.getPhaseTime('数据库连接')}`);
78
89
 
79
90
  // 阶段3:扫描表定义文件
80
91
  perfTracker.markPhase('扫描表文件');
@@ -113,7 +124,6 @@ export const SyncDb = async (): Promise<void> => {
113
124
  }
114
125
  }
115
126
  perfTracker.finishPhase('扫描表文件');
116
- Logger.info(`✓ 扫描完成,发现 ${totalTables} 个表定义文件,耗时: ${perfTracker.getPhaseTime('扫描表文件')}`);
117
127
 
118
128
  // 阶段4:处理表文件
119
129
  perfTracker.markPhase('同步处理');
@@ -132,7 +142,6 @@ export const SyncDb = async (): Promise<void> => {
132
142
 
133
143
  // 跳过以下划线开头的文件(这些是公共字段规则,不是表定义)
134
144
  if (fileName.startsWith('_')) {
135
- Logger.info(`跳过非表定义文件: ${fileName}.json`);
136
145
  continue;
137
146
  }
138
147
 
@@ -155,7 +164,6 @@ export const SyncDb = async (): Promise<void> => {
155
164
  }
156
165
 
157
166
  processedCount++;
158
- progressLogger.logTableProgress(processedCount, totalTables, tableName, dirType);
159
167
 
160
168
  const tableDefinition = await Bun.file(file).json();
161
169
  const existsTable = await tableExists(sql!, tableName);
@@ -171,29 +179,21 @@ export const SyncDb = async (): Promise<void> => {
171
179
  }
172
180
 
173
181
  perfTracker.finishPhase('同步处理');
174
- Logger.info(`✓ 表处理完成,耗时: ${perfTracker.getPhaseTime('同步处理')}`);
175
-
176
- // 阶段5:显示统计信息
177
- Logger.info('\n=== 同步统计信息 ===');
178
- Logger.info(`总耗时: ${perfTracker.getTotalTime()}`);
179
- Logger.info(`处理表总数: ${globalCount.processedTables}`);
180
- Logger.info(`创建表: ${globalCount.createdTables}`);
181
- Logger.info(`修改表: ${globalCount.modifiedTables}`);
182
- Logger.info(`字段新增: ${globalCount.addFields}`);
183
- Logger.info(`字段名称变更: ${globalCount.nameChanges}`);
184
- Logger.info(`字段类型变更: ${globalCount.typeChanges}`);
185
- Logger.info(`字段最小值变更: ${globalCount.minChanges}`);
186
- Logger.info(`字段最大值变更: ${globalCount.maxChanges}`);
187
- Logger.info(`字段默认值变更: ${globalCount.defaultChanges}`);
188
- Logger.info(`索引新增: ${globalCount.indexCreate}`);
189
- Logger.info(`索引删除: ${globalCount.indexDrop}`);
190
-
191
- if (globalCount.processedTables === 0) {
192
- Logger.warn('没有找到任何表定义文件');
193
- }
194
182
 
195
- // 输出性能统计
196
- perfTracker.logStats();
183
+ // 返回统计信息
184
+ return {
185
+ processedTables: globalCount.processedTables,
186
+ createdTables: globalCount.createdTables,
187
+ modifiedTables: globalCount.modifiedTables,
188
+ addFields: globalCount.addFields,
189
+ nameChanges: globalCount.nameChanges,
190
+ typeChanges: globalCount.typeChanges,
191
+ minChanges: globalCount.minChanges,
192
+ maxChanges: globalCount.maxChanges,
193
+ defaultChanges: globalCount.defaultChanges,
194
+ indexCreate: globalCount.indexCreate,
195
+ indexDrop: globalCount.indexDrop
196
+ };
197
197
  } catch (error: any) {
198
198
  Logger.error(`数据库同步失败`, error);
199
199
  process.exit(1);
@@ -6,14 +6,14 @@ import { Command } from 'commander';
6
6
  import { join } from 'pathe';
7
7
  import { existsSync } from 'node:fs';
8
8
  import { Logger } from '../lib/logger.js';
9
- import { SyncDb } from './syncDb/index.js';
9
+ import { SyncDb, type SyncDbStats } from './syncDb/index.js';
10
10
 
11
11
  interface SyncDbOptions {
12
12
  table?: string;
13
13
  dryRun: boolean;
14
14
  }
15
15
 
16
- export async function syncDbCommand(options: SyncDbOptions) {
16
+ export async function syncDbCommand(options: SyncDbOptions): Promise<SyncDbStats> {
17
17
  try {
18
18
  // 设置环境变量
19
19
  if (options.dryRun) {
@@ -24,9 +24,9 @@ export async function syncDbCommand(options: SyncDbOptions) {
24
24
  process.env.SYNC_TABLE = options.table;
25
25
  }
26
26
 
27
- // 执行同步
28
- await SyncDb();
29
- Logger.info('数据库表结构同步完成');
27
+ // 执行同步并返回统计
28
+ const stats = await SyncDb();
29
+ return stats;
30
30
  } catch (error: any) {
31
31
  Logger.error('数据库同步失败:', error);
32
32
  process.exit(1);
@@ -16,23 +16,26 @@ interface SyncDevOptions {
16
16
  plan?: boolean;
17
17
  }
18
18
 
19
+ export interface SyncDevStats {
20
+ adminCount: number;
21
+ roleCount: number;
22
+ cachedRoles: number;
23
+ }
24
+
19
25
  /**
20
26
  * SyncDev 命令主函数
21
27
  */
22
- export async function syncDevCommand(options: SyncDevOptions = {}) {
28
+ export async function syncDevCommand(options: SyncDevOptions = {}): Promise<SyncDevStats> {
23
29
  try {
24
30
  if (options.plan) {
25
31
  Logger.info('[计划] 同步完成后将初始化/更新开发管理员账号(plan 模式不执行)');
26
- return;
32
+ return { adminCount: 0, roleCount: 0, cachedRoles: 0 };
27
33
  }
28
34
 
29
35
  if (!Env.DEV_PASSWORD) {
30
- Logger.warn('跳过开发管理员初始化:缺少 DEV_PASSWORD 配置');
31
- return;
36
+ return { adminCount: 0, roleCount: 0, cachedRoles: 0 };
32
37
  }
33
38
 
34
- Logger.info('开始同步开发管理员账号...\n');
35
-
36
39
  // 连接数据库(SQL + Redis)
37
40
  await Database.connect();
38
41
 
@@ -41,22 +44,19 @@ export async function syncDevCommand(options: SyncDevOptions = {}) {
41
44
  // 检查 core_admin 表是否存在
42
45
  const existAdmin = await helper.tableExists('core_admin');
43
46
  if (!existAdmin) {
44
- Logger.warn('跳过开发管理员初始化:未检测到 core_admin 表');
45
- return;
47
+ return { adminCount: 0, roleCount: 0, cachedRoles: 0 };
46
48
  }
47
49
 
48
50
  // 检查 core_role 表是否存在
49
51
  const existRole = await helper.tableExists('core_role');
50
52
  if (!existRole) {
51
- Logger.warn('跳过开发管理员初始化:未检测到 core_role 表');
52
- return;
53
+ return { adminCount: 0, roleCount: 0, cachedRoles: 0 };
53
54
  }
54
55
 
55
56
  // 检查 core_menu 表是否存在
56
57
  const existMenu = await helper.tableExists('core_menu');
57
58
  if (!existMenu) {
58
- Logger.warn('跳过开发管理员初始化:未检测到 core_menu 表');
59
- return;
59
+ return { adminCount: 0, roleCount: 0, cachedRoles: 0 };
60
60
  }
61
61
 
62
62
  // 查询所有菜单 ID
@@ -66,12 +66,10 @@ export async function syncDevCommand(options: SyncDevOptions = {}) {
66
66
  });
67
67
 
68
68
  if (!allMenus || !Array.isArray(allMenus)) {
69
- Logger.warn('查询菜单失败或菜单表为空');
70
- return;
69
+ return { adminCount: 0, roleCount: 0, cachedRoles: 0 };
71
70
  }
72
71
 
73
72
  const menuIds = allMenus.length > 0 ? allMenus.map((m: any) => m.id).join(',') : '';
74
- Logger.info(`查询到 ${allMenus.length} 个菜单,ID 列表: ${menuIds || '(空)'}`);
75
73
 
76
74
  // 查询所有接口 ID
77
75
  const existApi = await helper.tableExists('core_api');
@@ -84,12 +82,7 @@ export async function syncDevCommand(options: SyncDevOptions = {}) {
84
82
 
85
83
  if (allApis && Array.isArray(allApis) && allApis.length > 0) {
86
84
  apiIds = allApis.map((a: any) => a.id).join(',');
87
- Logger.info(`查询到 ${allApis.length} 个接口,ID 列表: ${apiIds}`);
88
- } else {
89
- Logger.info('未查询到接口数据');
90
85
  }
91
- } else {
92
- Logger.info('接口表不存在,跳过接口权限配置');
93
86
  }
94
87
 
95
88
  // 查询或创建 dev 角色
@@ -110,7 +103,6 @@ export async function syncDevCommand(options: SyncDevOptions = {}) {
110
103
  apis: apiIds
111
104
  }
112
105
  });
113
- Logger.info('dev 角色菜单和接口权限已更新');
114
106
  } else {
115
107
  // 创建 dev 角色
116
108
  const roleId = await helper.insData({
@@ -149,6 +141,7 @@ export async function syncDevCommand(options: SyncDevOptions = {}) {
149
141
  where: { email: Env.DEV_EMAIL }
150
142
  });
151
143
 
144
+ let isNew = false;
152
145
  if (existing) {
153
146
  // 更新现有账号
154
147
  await helper.updData({
@@ -156,26 +149,23 @@ export async function syncDevCommand(options: SyncDevOptions = {}) {
156
149
  where: { email: Env.DEV_EMAIL },
157
150
  data: devData
158
151
  });
159
- Logger.info(`✅ 开发管理员已更新:email=${Env.DEV_EMAIL}, username=dev, roleCode=dev, roleType=admin`);
160
152
  } else {
161
153
  // 插入新账号
162
154
  await helper.insData({
163
155
  table: 'core_admin',
164
156
  data: devData
165
157
  });
166
- Logger.info(`✅ 开发管理员已初始化:email=${Env.DEV_EMAIL}, username=dev, roleCode=dev, roleType=admin`);
158
+ isNew = true;
167
159
  }
168
160
 
169
161
  // 缓存角色权限数据到 Redis
170
- Logger.info('\n=== 缓存角色权限到 Redis ===');
162
+ let cachedRolesCount = 0;
171
163
  try {
172
164
  // 检查必要的表是否存在
173
165
  const apiTableExists = await helper.tableExists('core_api');
174
166
  const roleTableExists = await helper.tableExists('core_role');
175
167
 
176
- if (!apiTableExists || !roleTableExists) {
177
- Logger.warn('⚠️ 接口或角色表不存在,跳过角色权限缓存');
178
- } else {
168
+ if (apiTableExists && roleTableExists) {
179
169
  // 查询所有角色
180
170
  const roles = await helper.getAll({
181
171
  table: 'core_role',
@@ -189,7 +179,6 @@ export async function syncDevCommand(options: SyncDevOptions = {}) {
189
179
  });
190
180
 
191
181
  const redis = Database.getRedis();
192
- let cachedRoles = 0;
193
182
 
194
183
  // 为每个角色缓存接口权限
195
184
  for (const role of roles) {
@@ -212,20 +201,33 @@ export async function syncDevCommand(options: SyncDevOptions = {}) {
212
201
  // 先删除旧数据
213
202
  await redis.del(redisKey);
214
203
 
215
- // 批量添加到 Set
216
- const result = await redis.sadd(redisKey, roleApiPaths);
204
+ // 批量添加到 Set(使用扩展运算符展开数组)
205
+ const result = await redis.sadd(redisKey, ...roleApiPaths);
217
206
 
218
207
  if (result > 0) {
219
- cachedRoles++;
220
- Logger.debug(` └ 角色 ${role.code}: ${result} 个接口`);
208
+ cachedRolesCount++;
221
209
  }
222
210
  }
223
-
224
- Logger.info(`✅ 已缓存 ${cachedRoles} 个角色的接口权限`);
225
211
  }
226
212
  } catch (error: any) {
227
- Logger.error('⚠️ 角色权限缓存异常:', error);
213
+ // 忽略缓存错误
228
214
  }
215
+
216
+ // 获取统计数据
217
+ const allAdmins = await helper.getAll({
218
+ table: 'core_admin',
219
+ fields: ['id']
220
+ });
221
+ const allRoles = await helper.getAll({
222
+ table: 'core_role',
223
+ fields: ['id']
224
+ });
225
+
226
+ return {
227
+ adminCount: allAdmins.length,
228
+ roleCount: allRoles.length,
229
+ cachedRoles: cachedRolesCount
230
+ };
229
231
  } catch (error: any) {
230
232
  Logger.error('开发管理员同步失败:', error);
231
233
  process.exit(1);