befly-tpl 3.2.6 → 3.3.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.
Files changed (91) hide show
  1. package/.env.development +3 -3
  2. package/apis/article/articleDel.ts +2 -2
  3. package/apis/article/articleDetail.ts +2 -2
  4. package/apis/article/articleList.ts +2 -4
  5. package/apis/article/articleUpd.ts +2 -2
  6. package/apis/article/increment.ts +2 -2
  7. package/apis/user/login.ts +3 -3
  8. package/apis/user/userList.ts +3 -5
  9. package/package.json +6 -10
  10. package/pm2.config.cjs +3 -3
  11. package/tables/user.json +1 -1
  12. package/addons/_template/README.md +0 -123
  13. package/addons/_template/addon.config.json +0 -17
  14. package/addons/_template/apis/example.ts +0 -33
  15. package/addons/_template/checks/example.ts +0 -23
  16. package/addons/_template/config/default.ts +0 -12
  17. package/addons/_template/plugins/example.ts +0 -39
  18. package/addons/_template/tables/example.json +0 -7
  19. package/addons/_template/types/index.d.ts +0 -21
  20. package/addons/admin/README.md +0 -179
  21. package/addons/admin/addon.config.json +0 -13
  22. package/addons/admin/apis/adminDel.ts +0 -37
  23. package/addons/admin/apis/adminInfo.ts +0 -50
  24. package/addons/admin/apis/adminIns.ts +0 -70
  25. package/addons/admin/apis/adminList.ts +0 -24
  26. package/addons/admin/apis/adminRoleDetail.ts +0 -38
  27. package/addons/admin/apis/adminRoleSave.ts +0 -40
  28. package/addons/admin/apis/adminUpd.ts +0 -54
  29. package/addons/admin/apis/apiAll.ts +0 -38
  30. package/addons/admin/apis/cacheRefresh.ts +0 -36
  31. package/addons/admin/apis/dashboardAddonList.ts +0 -16
  32. package/addons/admin/apis/dashboardChangelog.ts +0 -41
  33. package/addons/admin/apis/dashboardConfigStatus.ts +0 -56
  34. package/addons/admin/apis/dashboardEnvironmentInfo.ts +0 -48
  35. package/addons/admin/apis/dashboardPerformanceMetrics.ts +0 -25
  36. package/addons/admin/apis/dashboardPermissionStats.ts +0 -33
  37. package/addons/admin/apis/dashboardServiceStatus.ts +0 -84
  38. package/addons/admin/apis/dashboardSystemInfo.ts +0 -34
  39. package/addons/admin/apis/dashboardSystemOverview.ts +0 -34
  40. package/addons/admin/apis/dashboardSystemResources.ts +0 -119
  41. package/addons/admin/apis/dictAll.ts +0 -26
  42. package/addons/admin/apis/dictDel.ts +0 -27
  43. package/addons/admin/apis/dictDetail.ts +0 -28
  44. package/addons/admin/apis/dictIns.ts +0 -38
  45. package/addons/admin/apis/dictList.ts +0 -27
  46. package/addons/admin/apis/dictUpd.ts +0 -44
  47. package/addons/admin/apis/login.ts +0 -123
  48. package/addons/admin/apis/logout.ts +0 -23
  49. package/addons/admin/apis/menuAll.ts +0 -70
  50. package/addons/admin/apis/menuDel.ts +0 -40
  51. package/addons/admin/apis/menuIns.ts +0 -31
  52. package/addons/admin/apis/menuList.ts +0 -26
  53. package/addons/admin/apis/menuUpd.ts +0 -41
  54. package/addons/admin/apis/register.ts +0 -50
  55. package/addons/admin/apis/roleApiDetail.ts +0 -34
  56. package/addons/admin/apis/roleApiSave.ts +0 -44
  57. package/addons/admin/apis/roleDel.ts +0 -48
  58. package/addons/admin/apis/roleDetail.ts +0 -28
  59. package/addons/admin/apis/roleIns.ts +0 -40
  60. package/addons/admin/apis/roleList.ts +0 -18
  61. package/addons/admin/apis/roleMenuDetail.ts +0 -33
  62. package/addons/admin/apis/roleMenuSave.ts +0 -39
  63. package/addons/admin/apis/roleSave.ts +0 -45
  64. package/addons/admin/apis/roleUpd.ts +0 -53
  65. package/addons/admin/apis/sendSmsCode.ts +0 -36
  66. package/addons/admin/checks/admin.ts +0 -36
  67. package/addons/admin/config/index.ts +0 -45
  68. package/addons/admin/config/menu.json +0 -44
  69. package/addons/admin/scripts/syncApi.ts +0 -285
  70. package/addons/admin/scripts/syncDev.ts +0 -203
  71. package/addons/admin/scripts/syncMenu.ts +0 -210
  72. package/addons/admin/tables/admin.json +0 -14
  73. package/addons/admin/tables/api.json +0 -8
  74. package/addons/admin/tables/dict.json +0 -8
  75. package/addons/admin/tables/menu.json +0 -8
  76. package/addons/admin/tables/role.json +0 -8
  77. package/addons/admin/types/index.ts +0 -44
  78. package/addons/admin/util.ts +0 -266
  79. package/addons/befly/addon.config.json +0 -13
  80. package/addons/befly/apis/health/info.ts +0 -77
  81. package/addons/befly/apis/tool/tokenCheck.ts +0 -52
  82. package/addons/demo/README.md +0 -62
  83. package/addons/demo/addon.config.json +0 -13
  84. package/addons/demo/apis/demoIns.ts +0 -36
  85. package/addons/demo/apis/demoList.ts +0 -36
  86. package/addons/demo/checks/demo.ts +0 -30
  87. package/addons/demo/config/default.ts +0 -17
  88. package/addons/demo/plugins/tool.ts +0 -61
  89. package/addons/demo/tables/todo.json +0 -6
  90. package/addons/demo/types/index.d.ts +0 -56
  91. package/tests/core.test.ts +0 -13
@@ -1,39 +0,0 @@
1
- /**
2
- * 保存角色的菜单权限
3
- */
4
-
5
- import { Yes, No, Fields } from 'befly';
6
- import adminRoleTable from '../tables/role.json';
7
-
8
- export default {
9
- name: '保存角色菜单权限',
10
- fields: {
11
- roleId: Fields._id,
12
- menuIds: adminRoleTable.menus
13
- },
14
- handler: async (befly, ctx) => {
15
- // 查询角色是否存在
16
- const role = await befly.db.getOne({
17
- table: 'addon_admin_role',
18
- where: { id: ctx.body.roleId }
19
- });
20
-
21
- if (!role) {
22
- return No('角色不存在');
23
- }
24
-
25
- // 将数组转为逗号分隔的字符串存储
26
- const menuIdsStr = Array.isArray(ctx.body.menuIds) ? ctx.body.menuIds.join(',') : '';
27
-
28
- // 更新角色的菜单权限
29
- await befly.db.updData({
30
- table: 'addon_admin_role',
31
- where: { id: ctx.body.roleId },
32
- data: {
33
- menus: menuIdsStr
34
- }
35
- });
36
-
37
- return Yes('操作成功');
38
- }
39
- };
@@ -1,45 +0,0 @@
1
- /**
2
- * 保存用户的角色(单角色模式)
3
- */
4
-
5
- import { Yes, No, Fields } from 'befly';
6
-
7
- export default {
8
- name: '保存用户角色',
9
- fields: {
10
- adminId: Fields._id,
11
- roleCode: '角色编码|string|2|50|null|1|^[a-zA-Z0-9_]+$'
12
- },
13
- handler: async (befly, ctx) => {
14
- try {
15
- // 查询角色是否存在(使用 roleCode 而非 roleId)
16
- const role = await befly.db.getOne({
17
- table: 'addon_admin_role',
18
- where: { code: ctx.body.roleCode }
19
- });
20
-
21
- if (!role) {
22
- return No('角色不存在');
23
- }
24
-
25
- // 根据角色编码判断角色类型(硬编码规则)
26
- const roleType = role.code === 'dev' || role.code === 'admin' ? 'admin' : 'user';
27
-
28
- // 更新管理员的角色ID、角色编码和角色类型
29
- await befly.db.updData({
30
- table: 'addon_admin_admin',
31
- where: { id: ctx.body.adminId },
32
- data: {
33
- roleId: role.id,
34
- roleCode: role.code,
35
- roleType: roleType
36
- }
37
- });
38
-
39
- return Yes('操作成功');
40
- } catch (error) {
41
- befly.logger.error('保存用户角色失败:', error);
42
- return No('操作失败');
43
- }
44
- }
45
- };
@@ -1,53 +0,0 @@
1
- import { Yes, No, Fields } from 'befly';
2
- import adminRoleTable from '../tables/role.json';
3
- import { cacheRolePermissions } from '../util';
4
-
5
- /**
6
- * 更新角色
7
- */
8
- export default {
9
- name: '更新角色',
10
- fields: {
11
- id: Fields._id,
12
- name: adminRoleTable.name,
13
- code: adminRoleTable.code,
14
- description: adminRoleTable.description,
15
- menus: adminRoleTable.menus,
16
- apis: adminRoleTable.apis,
17
- sort: adminRoleTable.sort
18
- // state 需要禁用时传 2,启用时传 1
19
- },
20
- handler: async (befly, ctx) => {
21
- // 检查角色代码是否被其他角色占用
22
- const existing = await befly.db.getList({
23
- table: 'addon_admin_role',
24
- where: {
25
- code: ctx.body.code,
26
- id$ne: ctx.body.id
27
- }
28
- });
29
-
30
- if (existing.total > 0) {
31
- return No('角色代码已被其他角色使用');
32
- }
33
-
34
- await befly.db.updData({
35
- table: 'addon_admin_role',
36
- where: { id: ctx.body.id },
37
- data: {
38
- name: ctx.body.name,
39
- code: ctx.body.code,
40
- description: ctx.body.description,
41
- menus: ctx.body.menus || '',
42
- apis: ctx.body.apis || '',
43
- sort: ctx.body.sort
44
- // state 字段不在此处更新,需要禁用/启用时单独处理
45
- }
46
- });
47
-
48
- // 增量更新角色权限缓存(先删除再重建)
49
- await cacheRolePermissions(befly, ctx.body.code, ctx.body.apis || '');
50
-
51
- return Yes('操作成功');
52
- }
53
- };
@@ -1,36 +0,0 @@
1
- /**
2
- * 发送短信验证码接口
3
- */
4
-
5
- import { Yes } from 'befly';
6
-
7
- import adminTable from '../tables/admin.json';
8
-
9
- export default {
10
- name: '发送短信验证码',
11
- auth: false,
12
- fields: {
13
- phone: adminTable.phone
14
- },
15
- required: ['phone'],
16
- handler: async (befly, ctx) => {
17
- // 生成6位数验证码
18
- const code = Math.floor(100000 + Math.random() * 900000).toString();
19
-
20
- // TODO: 调用短信服务发送验证码
21
- // 这里需要集成实际的短信服务提供商(如阿里云、腾讯云等)
22
- // await smsService.send(phone, code);
23
-
24
- // 将验证码存储到 Redis 中,有效期5分钟
25
- // 如果项目没有 Redis,也可以存储到数据库中
26
- if (befly.redis) {
27
- const key = `sms_code:${ctx.body.phone}`;
28
- await befly.redis.set(key, code, 'EX', 300); // 5分钟过期
29
- }
30
-
31
- // 开发环境下返回验证码(生产环境应该删除)
32
- const isDev = process.env.NODE_ENV === 'development';
33
-
34
- return Yes('验证码已发送', isDev ? { code } : null);
35
- }
36
- };
@@ -1,36 +0,0 @@
1
- /**
2
- * Admin Addon 启动检查
3
- * 验证组件配置和依赖
4
- */
5
-
6
- import { Logger } from 'befly';
7
-
8
- export default async function (): Promise<boolean> {
9
- try {
10
- // 检查组件是否启用
11
- const adminEnable = process.env.ADMIN_ENABLE;
12
-
13
- if (adminEnable === 'false') {
14
- Logger.info('[Admin] 组件已禁用');
15
- return true;
16
- }
17
-
18
- // 检查 JWT 密钥配置
19
- const jwtSecret = process.env.JWT_SECRET;
20
- if (!jwtSecret) {
21
- Logger.warn('[Admin] 未配置 JWT_SECRET 环境变量,将使用默认密钥(不建议用于生产环境)');
22
- }
23
-
24
- // 检查短信服务配置
25
- const smsProvider = process.env.SMS_PROVIDER;
26
- if (!smsProvider) {
27
- Logger.info('[Admin] 未配置短信服务,手机登录功能将使用测试验证码');
28
- }
29
-
30
- Logger.info('[Admin] 组件检查通过');
31
- return true;
32
- } catch (error: any) {
33
- Logger.error('[Admin] 组件检查失败:', error);
34
- return false;
35
- }
36
- }
@@ -1,45 +0,0 @@
1
- /**
2
- * Admin 插件配置
3
- */
4
-
5
- export default {
6
- // 插件名称
7
- name: 'admin',
8
-
9
- // 插件描述
10
- description: '管理后台基础功能',
11
-
12
- // 插件版本
13
- version: '1.0.0',
14
-
15
- // 是否启用
16
- enabled: true,
17
-
18
- // 配置选项
19
- config: {
20
- // JWT 密钥(建议从环境变量读取)
21
- jwtSecret: process.env.JWT_SECRET || 'your-secret-key',
22
-
23
- // Token 有效期(天)
24
- tokenExpireDays: 7,
25
-
26
- // 验证码有效期(秒)
27
- smsCodeExpire: 300,
28
-
29
- // 短信服务配置(需要根据实际使用的服务商配置)
30
- sms: {
31
- // 服务商: aliyun, tencent, etc.
32
- provider: 'aliyun',
33
-
34
- // 访问密钥
35
- accessKeyId: process.env.SMS_ACCESS_KEY_ID || '',
36
- accessKeySecret: process.env.SMS_ACCESS_KEY_SECRET || '',
37
-
38
- // 短信签名
39
- signName: '您的签名',
40
-
41
- // 模板代码
42
- templateCode: 'SMS_123456789'
43
- }
44
- }
45
- };
@@ -1,44 +0,0 @@
1
- [
2
- {
3
- "name": "首页",
4
- "path": "/",
5
- "icon": "Home",
6
- "sort": 1,
7
- "type": 1
8
- },
9
- {
10
- "name": "管理员管理",
11
- "path": "/admin",
12
- "icon": "Users",
13
- "sort": 2,
14
- "type": 1
15
- },
16
- {
17
- "name": "新闻管理",
18
- "path": "/news",
19
- "icon": "Newspaper",
20
- "sort": 3,
21
- "type": 1
22
- },
23
- {
24
- "name": "菜单管理",
25
- "path": "/menu",
26
- "icon": "Menu",
27
- "sort": 4,
28
- "type": 1
29
- },
30
- {
31
- "name": "角色管理",
32
- "path": "/role",
33
- "icon": "Users",
34
- "sort": 5,
35
- "type": 1
36
- },
37
- {
38
- "name": "字典管理",
39
- "path": "/dict",
40
- "icon": "BookOpen",
41
- "sort": 6,
42
- "type": 1
43
- }
44
- ]
@@ -1,285 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * 同步 API 接口数据到数据库
4
- * 说明:遍历所有 API 文件,收集接口路由信息并同步到 addon_admin_api 表
5
- *
6
- * 流程:
7
- * 1. 扫描 tpl/apis 目录下所有 API 文件
8
- * 2. 扫描 tpl/addons/组件/apis 目录下所有 API 文件
9
- * 3. 提取每个 API 的 name、method、auth 等信息
10
- * 4. 根据接口路径检查是否存在
11
- * 5. 存在则更新,不存在则新增
12
- * 6. 删除配置中不存在的接口记录
13
- */
14
-
15
- import { Env, Logger, initDatabase, closeDatabase } from 'befly';
16
- import path from 'node:path';
17
- import { fileURLToPath } from 'node:url';
18
- import { readdirSync, statSync } from 'node:fs';
19
- import { scanTsFiles, checkTableExists, deleteObsoleteRecords, logSyncStats, getAddonDirs } from '../util';
20
-
21
- // CLI 参数类型
22
- interface CliArgs {
23
- DRY_RUN: boolean;
24
- }
25
-
26
- // API 信息类型
27
- interface ApiInfo {
28
- name: string;
29
- path: string;
30
- method: string;
31
- description: string;
32
- addonName: string;
33
- addonTitle: string;
34
- }
35
-
36
- // 解析命令行参数
37
- const CLI: CliArgs = {
38
- DRY_RUN: process.argv.includes('--plan')
39
- };
40
-
41
- const __filename = fileURLToPath(import.meta.url);
42
- const __dirname = path.dirname(__filename);
43
- const tplDir = path.resolve(__dirname, '../../../');
44
-
45
- /**
46
- * 从 API 文件中提取接口信息
47
- * @param filePath - API 文件路径
48
- * @param addonName - 插件名称
49
- * @param addonTitle - 插件标题
50
- * @returns API 信息对象或 null
51
- */
52
- async function extractApiInfo(filePath: string, addonName: string = '', addonTitle: string = ''): Promise<ApiInfo | null> {
53
- try {
54
- // 动态导入 API 文件
55
- const apiModule = await import(filePath);
56
- const apiConfig = apiModule.default;
57
-
58
- if (!apiConfig || !apiConfig.name) {
59
- return null;
60
- }
61
-
62
- // 构建接口路径
63
- let apiPath = '';
64
- if (addonName) {
65
- // 插件接口:/addon/{addonName}/{fileName}
66
- const fileName = path.basename(filePath, '.ts');
67
- apiPath = `/addon/${addonName}/${fileName}`;
68
- } else {
69
- // 项目接口:/api/{dirName}/{fileName}
70
- const relativePath = path.relative(path.join(tplDir, 'apis'), filePath);
71
- const parts = relativePath.replace(/\\/g, '/').split('/');
72
- const dirName = parts[0];
73
- const fileName = path.basename(filePath, '.ts');
74
- apiPath = `/api/${dirName}/${fileName}`;
75
- }
76
-
77
- return {
78
- name: apiConfig.name || '',
79
- path: apiPath,
80
- method: apiConfig.method || 'POST',
81
- description: apiConfig.description || '',
82
- addonName: addonName,
83
- addonTitle: addonTitle || addonName
84
- };
85
- } catch (error: any) {
86
- Logger.warn(`解析 API 文件失败: ${filePath}`, error.message);
87
- return null;
88
- }
89
- }
90
-
91
- /**
92
- * 读取 Addon 配置文件(使用 Bun 原生方法)
93
- * @param addonDir - Addon 目录路径
94
- * @returns Addon 配置对象或 null
95
- */
96
- async function loadAddonConfig(addonDir: string): Promise<{ name: string; title: string } | null> {
97
- try {
98
- const configPath = path.join(addonDir, 'addon.config.json');
99
- const file = Bun.file(configPath);
100
- const config = await file.json();
101
- return {
102
- name: config.name || '',
103
- title: config.title || config.name || ''
104
- };
105
- } catch (error) {
106
- return null;
107
- }
108
- }
109
-
110
- /**
111
- * 扫描所有 API 文件
112
- * @returns API 信息数组
113
- */
114
- async function scanAllApis(): Promise<ApiInfo[]> {
115
- const apis: ApiInfo[] = [];
116
-
117
- // 1. 扫描项目 API (tpl/apis)
118
- Logger.info('=== 扫描项目 API (tpl/apis) ===');
119
- const projectApisDir = path.join(tplDir, 'apis');
120
- const projectApiFiles = scanTsFiles(projectApisDir);
121
- Logger.info(` 找到 ${projectApiFiles.length} 个项目 API 文件`);
122
-
123
- for (const filePath of projectApiFiles) {
124
- const apiInfo = await extractApiInfo(filePath, '', '项目接口');
125
- if (apiInfo) {
126
- apis.push(apiInfo);
127
- Logger.info(` └ ${apiInfo.path} - ${apiInfo.name}`);
128
- }
129
- }
130
-
131
- // 2. 扫描插件 API (tpl/addons/*/apis)
132
- Logger.info('\n=== 扫描插件 API (tpl/addons/*/apis) ===');
133
- const addonsDir = path.join(tplDir, 'addons');
134
- const addonDirs = getAddonDirs(addonsDir);
135
-
136
- for (const addonName of addonDirs) {
137
- const addonDir = path.join(addonsDir, addonName);
138
- const addonApisDir = path.join(addonDir, 'apis');
139
-
140
- // 读取 addon 配置(使用 Bun 原生方法)
141
- const addonConfig = await loadAddonConfig(addonDir);
142
- const addonTitle = addonConfig?.title || addonName;
143
-
144
- try {
145
- const addonApiFiles = scanTsFiles(addonApisDir);
146
- Logger.info(` [${addonName}] 找到 ${addonApiFiles.length} 个 API 文件`);
147
-
148
- for (const filePath of addonApiFiles) {
149
- const apiInfo = await extractApiInfo(filePath, addonName, addonTitle);
150
- if (apiInfo) {
151
- apis.push(apiInfo);
152
- Logger.info(` └ ${apiInfo.path} - ${apiInfo.name}`);
153
- }
154
- }
155
- } catch (error: any) {
156
- Logger.warn(` [${addonName}] 扫描失败:`, error.message);
157
- }
158
- }
159
-
160
- return apis;
161
- }
162
-
163
- /**
164
- * 同步 API 数据到数据库
165
- * @param helper - DbHelper 实例
166
- * @param apis - API 信息数组
167
- * @returns 同步统计信息
168
- */
169
- async function syncApis(helper: any, apis: ApiInfo[]): Promise<{ created: number; updated: number }> {
170
- const stats = { created: 0, updated: 0 };
171
-
172
- for (const api of apis) {
173
- try {
174
- const existing = await helper.getOne({
175
- table: 'addon_admin_api',
176
- where: { path: api.path }
177
- });
178
-
179
- if (existing) {
180
- // 存在则更新
181
- await helper.updData({
182
- table: 'addon_admin_api',
183
- where: { id: existing.id },
184
- data: {
185
- name: api.name,
186
- method: api.method,
187
- description: api.description,
188
- addonName: api.addonName,
189
- addonTitle: api.addonTitle
190
- }
191
- });
192
- stats.updated++;
193
- Logger.info(` └ 更新接口: ${api.name} (ID: ${existing.id}, Path: ${api.path})`);
194
- } else {
195
- // 不存在则新增
196
- const id = await helper.insData({
197
- table: 'addon_admin_api',
198
- data: {
199
- name: api.name,
200
- path: api.path,
201
- method: api.method,
202
- description: api.description,
203
- addonName: api.addonName,
204
- addonTitle: api.addonTitle
205
- }
206
- });
207
- stats.created++;
208
- Logger.info(` └ 新增接口: ${api.name} (ID: ${id}, Path: ${api.path})`);
209
- }
210
- } catch (error: any) {
211
- Logger.error(`同步接口 "${api.name}" 失败:`, error.message || String(error));
212
- }
213
- }
214
-
215
- return stats;
216
- }
217
-
218
- /**
219
- * 同步 API 主函数
220
- */
221
- async function syncApi(): Promise<boolean> {
222
- let dbInitialized = false;
223
-
224
- try {
225
- if (CLI.DRY_RUN) {
226
- Logger.info('[计划] 同步 API 接口到数据库(plan 模式不执行)');
227
- Logger.info('[计划] 1. 扫描 tpl/apis 和 tpl/addons/*/apis 目录');
228
- Logger.info('[计划] 2. 提取每个 API 的配置信息');
229
- Logger.info('[计划] 3. 根据 path 检查接口是否存在');
230
- Logger.info('[计划] 4. 存在则更新,不存在则新增');
231
- Logger.info('[计划] 5. 删除文件中不存在的接口记录');
232
- return true;
233
- }
234
-
235
- Logger.info('开始同步 API 接口到数据库...\n');
236
-
237
- // 初始化数据库连接
238
- const { helper } = await initDatabase({ max: 1 });
239
- dbInitialized = true;
240
-
241
- // 1. 检查表是否存在
242
- if (!(await checkTableExists(helper, 'addon_admin_api'))) {
243
- return false;
244
- }
245
-
246
- Logger.info('');
247
-
248
- // 2. 扫描所有 API 文件
249
- Logger.info('=== 步骤 2: 扫描 API 文件 ===');
250
- const apis = await scanAllApis();
251
- const apiPaths = new Set(apis.map((api) => api.path));
252
- Logger.info(`\n✅ 共扫描到 ${apis.length} 个 API 接口\n`);
253
-
254
- // 3. 同步 API 数据(新增和更新)
255
- Logger.info('=== 步骤 3: 同步 API 数据(新增/更新) ===');
256
- const stats = await syncApis(helper, apis);
257
-
258
- // 4. 删除文件中不存在的接口
259
- const deletedCount = await deleteObsoleteRecords(helper, 'addon_admin_api', apiPaths);
260
-
261
- // 5. 输出统计信息
262
- logSyncStats(stats, deletedCount, '接口');
263
- Logger.info(`当前总接口数: ${apis.length} 个`);
264
- Logger.info('提示: 接口缓存将在服务器启动时自动完成');
265
-
266
- return true;
267
- } catch (error: any) {
268
- Logger.error('API 同步失败:', { message: error.message, stack: error.stack });
269
- return false;
270
- } finally {
271
- if (dbInitialized) {
272
- await closeDatabase();
273
- }
274
- }
275
- }
276
-
277
- // 执行同步
278
- syncApi()
279
- .then((success) => {
280
- process.exit(success ? 0 : 1);
281
- })
282
- .catch((error) => {
283
- Logger.error('执行失败:', error);
284
- process.exit(1);
285
- });