befly 3.5.1 → 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.
- package/bin/index.ts +17 -130
- package/checks/table.ts +5 -7
- package/commands/index.ts +1 -97
- package/commands/sync.ts +60 -28
- package/commands/syncApi.ts +22 -52
- package/commands/syncDb/index.ts +31 -31
- package/commands/syncDb.ts +5 -5
- package/commands/syncDev.ts +35 -33
- package/commands/syncMenu.ts +25 -76
- package/lib/database.ts +0 -9
- package/lib/logger.ts +7 -5
- package/lifecycle/checker.ts +8 -25
- package/lifecycle/lifecycle.ts +5 -34
- package/lifecycle/loader.ts +10 -100
- package/package.json +2 -4
- package/commands/build.ts +0 -62
package/lifecycle/checker.ts
CHANGED
|
@@ -46,20 +46,15 @@ export class Checker {
|
|
|
46
46
|
const conflictCheckTime = calcPerfTime(conflictCheckStart);
|
|
47
47
|
|
|
48
48
|
if (typeof conflictResult !== 'boolean') {
|
|
49
|
-
Logger.warn(`核心检查 conflict.ts 返回值必须为 true 或 false,当前为 ${typeof conflictResult}
|
|
49
|
+
Logger.warn(`核心检查 conflict.ts 返回值必须为 true 或 false,当前为 ${typeof conflictResult}`);
|
|
50
50
|
stats.failedChecks++;
|
|
51
51
|
} else if (conflictResult === true) {
|
|
52
52
|
stats.passedChecks++;
|
|
53
|
-
Logger.info(`核心检查 conflict.ts 通过,耗时: ${conflictCheckTime}`);
|
|
54
53
|
} else {
|
|
55
|
-
Logger.warn(`核心检查未通过: conflict.ts
|
|
54
|
+
Logger.warn(`核心检查未通过: conflict.ts`);
|
|
56
55
|
stats.failedChecks++;
|
|
57
56
|
// 资源冲突检测失败,立即终止
|
|
58
|
-
Logger.warn('资源冲突检测失败,无法继续启动'
|
|
59
|
-
totalChecks: stats.totalChecks,
|
|
60
|
-
passedChecks: stats.passedChecks,
|
|
61
|
-
failedChecks: stats.failedChecks
|
|
62
|
-
});
|
|
57
|
+
Logger.warn('资源冲突检测失败,无法继续启动');
|
|
63
58
|
process.exit(1);
|
|
64
59
|
}
|
|
65
60
|
}
|
|
@@ -88,8 +83,6 @@ export class Checker {
|
|
|
88
83
|
const { path: checkDir, type } = checkConfig;
|
|
89
84
|
const addonName = 'addonName' in checkConfig ? checkConfig.addonName : undefined;
|
|
90
85
|
const checkTypeLabel = type === 'core' ? '核心' : type === 'project' ? '项目' : `组件${addonName}`;
|
|
91
|
-
Logger.info(`开始执行${checkTypeLabel}检查,目录: ${checkDir}`);
|
|
92
|
-
|
|
93
86
|
for await (const file of glob.scan({
|
|
94
87
|
cwd: checkDir,
|
|
95
88
|
onlyFiles: true,
|
|
@@ -118,18 +111,16 @@ export class Checker {
|
|
|
118
111
|
|
|
119
112
|
// 检查返回值是否为 boolean
|
|
120
113
|
if (typeof checkResult !== 'boolean') {
|
|
121
|
-
Logger.warn(`${checkTypeLabel}检查 ${fileName} 返回值必须为 true 或 false,当前为 ${typeof checkResult}
|
|
114
|
+
Logger.warn(`${checkTypeLabel}检查 ${fileName} 返回值必须为 true 或 false,当前为 ${typeof checkResult}`);
|
|
122
115
|
stats.failedChecks++;
|
|
123
116
|
} else if (checkResult === true) {
|
|
124
117
|
stats.passedChecks++;
|
|
125
|
-
Logger.info(`${checkTypeLabel}检查 ${fileName} 通过,耗时: ${singleCheckTime}`);
|
|
126
118
|
} else {
|
|
127
|
-
Logger.warn(`${checkTypeLabel}检查未通过: ${fileName}
|
|
119
|
+
Logger.warn(`${checkTypeLabel}检查未通过: ${fileName}`);
|
|
128
120
|
stats.failedChecks++;
|
|
129
121
|
}
|
|
130
122
|
} else {
|
|
131
|
-
|
|
132
|
-
Logger.warn(`${checkTypeLabel}检查文件 ${fileName} 未找到 default 导出的检查函数,耗时: ${singleCheckTime}`);
|
|
123
|
+
Logger.warn(`${checkTypeLabel}检查文件 ${fileName} 未找到 default 导出的检查函数`);
|
|
133
124
|
stats.failedChecks++;
|
|
134
125
|
}
|
|
135
126
|
} catch (error: any) {
|
|
@@ -143,19 +134,11 @@ export class Checker {
|
|
|
143
134
|
const totalCheckTime = calcPerfTime(checkStartTime);
|
|
144
135
|
|
|
145
136
|
// 输出检查结果统计
|
|
146
|
-
Logger.info(`系统检查完成! 总耗时: ${totalCheckTime},总检查数: ${stats.totalChecks}, 通过: ${stats.passedChecks}, 失败: ${stats.failedChecks}`);
|
|
147
|
-
|
|
148
137
|
if (stats.failedChecks > 0) {
|
|
149
|
-
Logger.error(
|
|
150
|
-
totalChecks: stats.totalChecks,
|
|
151
|
-
passedChecks: stats.passedChecks,
|
|
152
|
-
failedChecks: stats.failedChecks
|
|
153
|
-
});
|
|
138
|
+
Logger.error(`✗ 系统检查失败: ${stats.failedChecks}/${stats.totalChecks},耗时: ${totalCheckTime}`);
|
|
154
139
|
process.exit(1);
|
|
155
140
|
} else if (stats.totalChecks > 0) {
|
|
156
|
-
Logger.info(
|
|
157
|
-
} else {
|
|
158
|
-
Logger.info(`未执行任何检查`);
|
|
141
|
+
Logger.info(`✓ 系统检查通过: ${stats.passedChecks}/${stats.totalChecks},耗时: ${totalCheckTime}`);
|
|
159
142
|
}
|
|
160
143
|
} catch (error: any) {
|
|
161
144
|
Logger.error('执行系统检查时发生错误', error);
|
package/lifecycle/lifecycle.ts
CHANGED
|
@@ -39,7 +39,6 @@ export class Lifecycle {
|
|
|
39
39
|
*/
|
|
40
40
|
async start(appContext: BeflyContext, callback?: (server: Server) => void): Promise<Server> {
|
|
41
41
|
const serverStartTime = Bun.nanoseconds();
|
|
42
|
-
Logger.info('开始启动 Befly 服务器...');
|
|
43
42
|
|
|
44
43
|
// 1. 执行系统检查
|
|
45
44
|
await Checker.run();
|
|
@@ -52,7 +51,7 @@ export class Lifecycle {
|
|
|
52
51
|
|
|
53
52
|
// 4. 启动 HTTP 服务器
|
|
54
53
|
const totalStartupTime = calcPerfTime(serverStartTime);
|
|
55
|
-
Logger.info(
|
|
54
|
+
Logger.info(`✓ 服务器启动准备完成,总耗时: ${totalStartupTime}`);
|
|
56
55
|
|
|
57
56
|
return await Bootstrap.start(
|
|
58
57
|
{
|
|
@@ -70,63 +69,35 @@ export class Lifecycle {
|
|
|
70
69
|
* 包括 core APIs、addon APIs 和 app APIs
|
|
71
70
|
*/
|
|
72
71
|
private async loadAllApis(): Promise<void> {
|
|
73
|
-
Logger.info('========== 开始加载所有 API 路由 ==========');
|
|
74
|
-
const totalLoadStart = Bun.nanoseconds();
|
|
75
|
-
|
|
76
72
|
// 1. 加载 Core APIs
|
|
77
|
-
Logger.info('========== 开始加载核心 APIs ==========');
|
|
78
|
-
const coreApiLoadStart = Bun.nanoseconds();
|
|
79
73
|
try {
|
|
80
74
|
await Loader.loadApis('core', this.apiRoutes, { where: 'core' });
|
|
81
|
-
const coreApiLoadTime = calcPerfTime(coreApiLoadStart);
|
|
82
|
-
Logger.info(`========== 核心 APIs 加载完成,耗时: ${coreApiLoadTime} ==========`);
|
|
83
75
|
} catch (error: any) {
|
|
84
|
-
|
|
85
|
-
Logger.error(`核心 APIs 加载失败,耗时: ${coreApiLoadTime}`, error);
|
|
76
|
+
Logger.error(`核心 APIs 加载失败`, error);
|
|
86
77
|
throw error;
|
|
87
78
|
}
|
|
88
79
|
|
|
89
80
|
// 2. 加载 addon APIs
|
|
90
81
|
const addons = scanAddons();
|
|
91
|
-
Logger.info(`扫描到 ${addons.length} 个 addon: ${addons.join(', ')}`);
|
|
92
82
|
|
|
93
83
|
for (const addon of addons) {
|
|
94
|
-
const addonLoadStart = Bun.nanoseconds();
|
|
95
84
|
const hasApis = addonDirExists(addon, 'apis');
|
|
96
|
-
Logger.info(`[组件 ${addon}] APIs 目录存在: ${hasApis}`);
|
|
97
|
-
|
|
98
85
|
if (hasApis) {
|
|
99
|
-
Logger.info(`[组件 ${addon}] ===== 开始加载 APIs =====`);
|
|
100
86
|
try {
|
|
101
87
|
await Loader.loadApis(addon, this.apiRoutes, { where: 'addon', addonName: addon });
|
|
102
|
-
const addonLoadTime = calcPerfTime(addonLoadStart);
|
|
103
|
-
Logger.info(`[组件 ${addon}] ===== APIs 加载完成,耗时: ${addonLoadTime} =====`);
|
|
104
88
|
} catch (error: any) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
throw error; // 重新抛出错误,让上层处理
|
|
89
|
+
Logger.error(`[组件 ${addon}] APIs 加载失败`, error);
|
|
90
|
+
throw error;
|
|
108
91
|
}
|
|
109
92
|
}
|
|
110
93
|
}
|
|
111
94
|
|
|
112
|
-
Logger.info('========== 组件 APIs 全部加载完成 ==========');
|
|
113
|
-
|
|
114
95
|
// 3. 加载用户 APIs
|
|
115
|
-
Logger.info('========== 开始加载用户 APIs ==========');
|
|
116
|
-
|
|
117
|
-
const userApiLoadStart = Bun.nanoseconds();
|
|
118
96
|
try {
|
|
119
|
-
// 加载 app APIs
|
|
120
97
|
await Loader.loadApis('app', this.apiRoutes, { where: 'app' });
|
|
121
|
-
const userApiLoadTime = calcPerfTime(userApiLoadStart);
|
|
122
|
-
Logger.info(`========== 用户 APIs 加载完成,耗时: ${userApiLoadTime} ==========`);
|
|
123
98
|
} catch (error: any) {
|
|
124
|
-
|
|
125
|
-
Logger.error(`用户 APIs 加载失败,耗时: ${userApiLoadTime}`, error);
|
|
99
|
+
Logger.error(`用户 APIs 加载失败`, error);
|
|
126
100
|
throw error;
|
|
127
101
|
}
|
|
128
|
-
|
|
129
|
-
const totalLoadTime = calcPerfTime(totalLoadStart);
|
|
130
|
-
Logger.info(`========== 所有 API 路由加载完成!总耗时: ${totalLoadTime} ==========`);
|
|
131
102
|
}
|
|
132
103
|
}
|
package/lifecycle/loader.ts
CHANGED
|
@@ -107,18 +107,11 @@ export class Loader {
|
|
|
107
107
|
if (fileName.startsWith('_')) continue;
|
|
108
108
|
|
|
109
109
|
try {
|
|
110
|
-
const importStart = Bun.nanoseconds();
|
|
111
|
-
Logger.debug(`准备导入核心插件: ${fileName}`);
|
|
112
110
|
const plugin = await importWithTimeout(file);
|
|
113
|
-
const importTime = calcPerfTime(importStart);
|
|
114
|
-
Logger.debug(`核心插件 ${fileName} 导入成功,耗时: ${importTime}`);
|
|
115
|
-
|
|
116
111
|
const pluginInstance = plugin.default;
|
|
117
112
|
pluginInstance.pluginName = fileName;
|
|
118
113
|
corePlugins.push(pluginInstance);
|
|
119
114
|
loadedPluginNames.add(fileName); // 记录已加载的核心插件名称
|
|
120
|
-
|
|
121
|
-
Logger.info(`核心插件 ${fileName} 导入耗时: ${importTime}`);
|
|
122
115
|
} catch (err: any) {
|
|
123
116
|
hadCorePluginError = true;
|
|
124
117
|
Logger.error(`核心插件 ${fileName} 导入失败`, error);
|
|
@@ -126,10 +119,6 @@ export class Loader {
|
|
|
126
119
|
}
|
|
127
120
|
}
|
|
128
121
|
const corePluginsScanTime = calcPerfTime(corePluginsScanStart);
|
|
129
|
-
Logger.info(`核心插件扫描完成,耗时: ${corePluginsScanTime},共找到 ${corePlugins.length} 个插件`);
|
|
130
|
-
|
|
131
|
-
Logger.debug(`调试模式已开启`);
|
|
132
|
-
Logger.debug(`开始排序核心插件,插件列表: ${corePlugins.map((p) => p.pluginName).join(', ')}`);
|
|
133
122
|
|
|
134
123
|
const sortedCorePlugins = sortPlugins(corePlugins);
|
|
135
124
|
if (sortedCorePlugins === false) {
|
|
@@ -137,42 +126,26 @@ export class Loader {
|
|
|
137
126
|
process.exit(1);
|
|
138
127
|
}
|
|
139
128
|
|
|
140
|
-
Logger.debug(`核心插件排序完成,顺序: ${sortedCorePlugins.map((p) => p.pluginName).join(' -> ')}`);
|
|
141
|
-
|
|
142
129
|
// 初始化核心插件
|
|
143
130
|
const corePluginsInitStart = Bun.nanoseconds();
|
|
144
|
-
Logger.info(`开始初始化核心插件...`);
|
|
145
131
|
for (const plugin of sortedCorePlugins) {
|
|
146
132
|
try {
|
|
147
|
-
Logger.debug(`准备初始化核心插件: ${plugin.pluginName}`);
|
|
148
|
-
|
|
149
133
|
befly.pluginLists.push(plugin);
|
|
150
|
-
|
|
151
|
-
Logger.debug(`检查插件 ${plugin.pluginName} 是否有 onInit 方法: ${typeof plugin?.onInit === 'function'}`);
|
|
152
|
-
|
|
153
134
|
if (typeof plugin?.onInit === 'function') {
|
|
154
|
-
Logger.debug(`开始执行插件 ${plugin.pluginName} 的 onInit 方法`);
|
|
155
|
-
|
|
156
135
|
const pluginInitStart = Bun.nanoseconds();
|
|
157
136
|
befly.appContext[plugin.pluginName] = await plugin?.onInit(befly.appContext);
|
|
158
137
|
const pluginInitTime = calcPerfTime(pluginInitStart);
|
|
159
|
-
|
|
160
|
-
Logger.debug(`插件 ${plugin.pluginName} 初始化完成,耗时: ${pluginInitTime}`);
|
|
161
138
|
} else {
|
|
162
139
|
befly.appContext[plugin.pluginName] = {};
|
|
163
|
-
Logger.debug(`插件 ${plugin.pluginName} 没有 onInit 方法,跳过初始化`);
|
|
164
140
|
}
|
|
165
|
-
|
|
166
|
-
Logger.info(`核心插件 ${plugin.pluginName} 初始化成功`);
|
|
167
141
|
} catch (error: any) {
|
|
168
142
|
hadCorePluginError = true;
|
|
169
143
|
Logger.error(`核心插件 ${plugin.pluginName} 初始化失败`, error);
|
|
170
|
-
|
|
171
144
|
process.exit(1);
|
|
172
145
|
}
|
|
173
146
|
}
|
|
174
147
|
const corePluginsInitTime = calcPerfTime(corePluginsInitStart);
|
|
175
|
-
Logger.info(
|
|
148
|
+
Logger.info(`✓ 核心插件加载完成: ${corePlugins.length} 个,耗时: ${corePluginsScanTime}`);
|
|
176
149
|
|
|
177
150
|
// 扫描 addon 插件目录
|
|
178
151
|
const addons = scanAddons();
|
|
@@ -194,23 +167,17 @@ export class Loader {
|
|
|
194
167
|
|
|
195
168
|
// 检查是否已经加载了同名插件
|
|
196
169
|
if (loadedPluginNames.has(pluginFullName)) {
|
|
197
|
-
Logger.info(`跳过组件插件 ${pluginFullName},因为同名插件已存在`);
|
|
198
170
|
continue;
|
|
199
171
|
}
|
|
200
172
|
|
|
201
173
|
try {
|
|
202
174
|
const importStart = Bun.nanoseconds();
|
|
203
|
-
Logger.debug(`准备导入 addon 插件: ${addon}.${fileName}`);
|
|
204
175
|
const plugin = await importWithTimeout(file);
|
|
205
176
|
const importTime = calcPerfTime(importStart);
|
|
206
|
-
Logger.debug(`Addon 插件 ${addon}.${fileName} 导入成功,耗时: ${importTime}`);
|
|
207
|
-
|
|
208
177
|
const pluginInstance = plugin.default;
|
|
209
178
|
pluginInstance.pluginName = pluginFullName;
|
|
210
179
|
addonPlugins.push(pluginInstance);
|
|
211
180
|
loadedPluginNames.add(pluginFullName);
|
|
212
|
-
|
|
213
|
-
Logger.info(`组件${addon} ${fileName} 导入耗时: ${importTime}`);
|
|
214
181
|
} catch (err: any) {
|
|
215
182
|
hadAddonPluginError = true;
|
|
216
183
|
Logger.error(`组件${addon} ${fileName} 导入失败`, error);
|
|
@@ -219,7 +186,6 @@ export class Loader {
|
|
|
219
186
|
}
|
|
220
187
|
}
|
|
221
188
|
const addonPluginsScanTime = calcPerfTime(addonPluginsScanStart);
|
|
222
|
-
Logger.info(`组件插件扫描完成,耗时: ${addonPluginsScanTime},共找到 ${addonPlugins.length} 个插件`);
|
|
223
189
|
|
|
224
190
|
const sortedAddonPlugins = sortPlugins(addonPlugins);
|
|
225
191
|
if (sortedAddonPlugins === false) {
|
|
@@ -230,39 +196,30 @@ export class Loader {
|
|
|
230
196
|
} else {
|
|
231
197
|
// 初始化组件插件
|
|
232
198
|
const addonPluginsInitStart = Bun.nanoseconds();
|
|
233
|
-
Logger.info(`开始初始化组件插件...`);
|
|
234
199
|
for (const plugin of sortedAddonPlugins) {
|
|
235
200
|
try {
|
|
236
|
-
Logger.debug(`准备初始化组件插件: ${plugin.pluginName}`);
|
|
237
|
-
|
|
238
201
|
befly.pluginLists.push(plugin);
|
|
239
202
|
|
|
240
203
|
if (typeof plugin?.onInit === 'function') {
|
|
241
|
-
Logger.debug(`开始执行组件插件 ${plugin.pluginName} 的 onInit 方法`);
|
|
242
|
-
|
|
243
204
|
const pluginInitStart = Bun.nanoseconds();
|
|
244
205
|
befly.appContext[plugin.pluginName] = await plugin?.onInit(befly.appContext);
|
|
245
206
|
const pluginInitTime = calcPerfTime(pluginInitStart);
|
|
246
|
-
|
|
247
|
-
Logger.debug(`组件插件 ${plugin.pluginName} 初始化完成,耗时: ${pluginInitTime}`);
|
|
248
207
|
} else {
|
|
249
208
|
befly.appContext[plugin.pluginName] = {};
|
|
250
209
|
}
|
|
251
|
-
|
|
252
|
-
Logger.info(`组件插件 ${plugin.pluginName} 初始化成功`);
|
|
253
210
|
} catch (error: any) {
|
|
254
211
|
hadAddonPluginError = true;
|
|
255
212
|
Logger.error(`组件插件 ${plugin.pluginName} 初始化失败`, error);
|
|
256
213
|
}
|
|
257
214
|
}
|
|
258
215
|
const addonPluginsInitTime = calcPerfTime(addonPluginsInitStart);
|
|
259
|
-
Logger.info(
|
|
216
|
+
Logger.info(`✓ 组件插件加载完成: ${addonPlugins.length} 个,耗时: ${addonPluginsScanTime}`);
|
|
260
217
|
}
|
|
261
218
|
}
|
|
262
219
|
|
|
263
220
|
// 扫描用户插件目录
|
|
264
221
|
if (!existsSync(projectPluginDir)) {
|
|
265
|
-
|
|
222
|
+
// 项目插件目录不存在,跳过
|
|
266
223
|
} else {
|
|
267
224
|
const userPluginsScanStart = Bun.nanoseconds();
|
|
268
225
|
for await (const file of glob.scan({
|
|
@@ -275,30 +232,20 @@ export class Loader {
|
|
|
275
232
|
|
|
276
233
|
// 检查是否已经加载了同名的核心插件
|
|
277
234
|
if (loadedPluginNames.has(fileName)) {
|
|
278
|
-
Logger.info(`跳过用户插件 ${fileName},因为同名的核心插件已存在`);
|
|
279
235
|
continue;
|
|
280
236
|
}
|
|
281
237
|
|
|
282
238
|
try {
|
|
283
|
-
const importStart = Bun.nanoseconds();
|
|
284
|
-
Logger.debug(`准备导入用户插件: ${fileName}`);
|
|
285
239
|
const plugin = await importWithTimeout(file);
|
|
286
|
-
const importTime = calcPerfTime(importStart);
|
|
287
|
-
Logger.debug(`用户插件 ${fileName} 导入成功,耗时: ${importTime}`);
|
|
288
|
-
|
|
289
240
|
const pluginInstance = plugin.default;
|
|
290
241
|
pluginInstance.pluginName = fileName;
|
|
291
242
|
userPlugins.push(pluginInstance);
|
|
292
|
-
|
|
293
|
-
Logger.info(`用户插件 ${fileName} 导入耗时: ${importTime}`);
|
|
294
243
|
} catch (err: any) {
|
|
295
244
|
hadUserPluginError = true;
|
|
296
245
|
Logger.error(`用户插件 ${fileName} 导入失败`, error);
|
|
297
246
|
process.exit(1);
|
|
298
247
|
}
|
|
299
248
|
}
|
|
300
|
-
const userPluginsScanTime = calcPerfTime(userPluginsScanStart);
|
|
301
|
-
Logger.info(`用户插件扫描完成,耗时: ${userPluginsScanTime},共找到 ${userPlugins.length} 个插件`);
|
|
302
249
|
}
|
|
303
250
|
|
|
304
251
|
const sortedUserPlugins = sortPlugins(userPlugins);
|
|
@@ -314,64 +261,42 @@ export class Loader {
|
|
|
314
261
|
// 初始化用户插件
|
|
315
262
|
if (userPlugins.length > 0) {
|
|
316
263
|
const userPluginsInitStart = Bun.nanoseconds();
|
|
317
|
-
Logger.info(`开始初始化用户插件...`);
|
|
318
264
|
for (const plugin of sortedUserPlugins) {
|
|
319
265
|
try {
|
|
320
|
-
Logger.debug(`准备初始化用户插件: ${plugin.pluginName}`);
|
|
321
|
-
|
|
322
266
|
befly.pluginLists.push(plugin);
|
|
323
267
|
|
|
324
268
|
if (typeof plugin?.onInit === 'function') {
|
|
325
|
-
Logger.debug(`开始执行用户插件 ${plugin.pluginName} 的 onInit 方法`);
|
|
326
|
-
|
|
327
|
-
const pluginInitStart = Bun.nanoseconds();
|
|
328
269
|
befly.appContext[plugin.pluginName] = await plugin?.onInit(befly.appContext);
|
|
329
|
-
const pluginInitTime = calcPerfTime(pluginInitStart);
|
|
330
|
-
|
|
331
|
-
Logger.debug(`用户插件 ${plugin.pluginName} 初始化完成,耗时: ${pluginInitTime}`);
|
|
332
270
|
} else {
|
|
333
271
|
befly.appContext[plugin.pluginName] = {};
|
|
334
272
|
}
|
|
335
|
-
|
|
336
|
-
Logger.info(`用户插件 ${plugin.pluginName} 初始化成功`);
|
|
337
273
|
} catch (error: any) {
|
|
338
274
|
hadUserPluginError = true;
|
|
339
275
|
Logger.error(`用户插件 ${plugin.pluginName} 初始化失败`, error);
|
|
340
276
|
}
|
|
341
277
|
}
|
|
342
278
|
const userPluginsInitTime = calcPerfTime(userPluginsInitStart);
|
|
343
|
-
Logger.info(
|
|
279
|
+
Logger.info(`✓ 用户插件加载完成: ${sortedUserPlugins.length} 个,耗时: ${userPluginsInitTime}`);
|
|
344
280
|
}
|
|
345
281
|
|
|
346
282
|
const totalLoadTime = calcPerfTime(loadStartTime);
|
|
347
283
|
const totalPluginCount = sortedCorePlugins.length + addonPlugins.length + sortedUserPlugins.length;
|
|
348
|
-
Logger.info(
|
|
284
|
+
Logger.info(`✓ 所有插件加载完成: ${totalPluginCount} 个,总耗时: ${totalLoadTime}`);
|
|
349
285
|
|
|
350
286
|
// 核心插件失败 → 关键错误,必须退出
|
|
351
287
|
if (hadCorePluginError) {
|
|
352
|
-
Logger.warn('核心插件加载失败,无法继续启动'
|
|
353
|
-
corePluginCount: sortedCorePlugins.length,
|
|
354
|
-
totalPluginCount
|
|
355
|
-
});
|
|
288
|
+
Logger.warn('核心插件加载失败,无法继续启动');
|
|
356
289
|
process.exit(1);
|
|
357
290
|
}
|
|
358
291
|
|
|
359
292
|
// Addon 插件失败 → 警告,可以继续运行
|
|
360
293
|
if (hadAddonPluginError) {
|
|
361
|
-
Logger.
|
|
362
|
-
level: 'INFO',
|
|
363
|
-
msg: '部分 Addon 插件加载失败,但不影响核心功能',
|
|
364
|
-
addonPluginCount: addonPlugins.length
|
|
365
|
-
});
|
|
294
|
+
Logger.warn('部分 Addon 插件加载失败,但不影响核心功能');
|
|
366
295
|
}
|
|
367
296
|
|
|
368
297
|
// 用户插件失败 → 警告,可以继续运行
|
|
369
298
|
if (hadUserPluginError) {
|
|
370
|
-
Logger.
|
|
371
|
-
level: 'INFO',
|
|
372
|
-
msg: '部分用户插件加载失败,但不影响核心功能',
|
|
373
|
-
userPluginCount: sortedUserPlugins.length
|
|
374
|
-
});
|
|
299
|
+
Logger.warn('部分用户插件加载失败,但不影响核心功能');
|
|
375
300
|
}
|
|
376
301
|
} catch (error: any) {
|
|
377
302
|
Logger.error('加载插件时发生错误', error);
|
|
@@ -407,7 +332,6 @@ export class Loader {
|
|
|
407
332
|
|
|
408
333
|
// 检查目录是否存在
|
|
409
334
|
if (!existsSync(apiDir)) {
|
|
410
|
-
Logger.info(`${dirDisplayName}接口目录不存在,跳过加载: ${apiDir}`);
|
|
411
335
|
return;
|
|
412
336
|
}
|
|
413
337
|
|
|
@@ -429,17 +353,9 @@ export class Loader {
|
|
|
429
353
|
const singleApiStart = Bun.nanoseconds();
|
|
430
354
|
|
|
431
355
|
try {
|
|
432
|
-
Logger.debug(`[${dirDisplayName}] 准备导入 API 文件: ${apiPath}`);
|
|
433
|
-
Logger.debug(`[${dirDisplayName}] 文件绝对路径: ${file}`);
|
|
434
|
-
|
|
435
356
|
const importStart = Bun.nanoseconds();
|
|
436
357
|
const api = (await importWithTimeout(file)).default;
|
|
437
358
|
const importTime = calcPerfTime(importStart);
|
|
438
|
-
|
|
439
|
-
Logger.debug(`[${dirDisplayName}] API 文件导入成功: ${apiPath},耗时: ${importTime}`);
|
|
440
|
-
|
|
441
|
-
Logger.debug(`[${dirDisplayName}] 开始验证 API 属性: ${apiPath}`);
|
|
442
|
-
|
|
443
359
|
// 验证必填属性:name 和 handler
|
|
444
360
|
if (typeof api.name !== 'string' || api.name.trim() === '') {
|
|
445
361
|
throw new Error(`接口 ${apiPath} 的 name 属性必须是非空字符串`);
|
|
@@ -472,9 +388,6 @@ export class Loader {
|
|
|
472
388
|
if (api.required && api.required.some((item: any) => typeof item !== 'string')) {
|
|
473
389
|
throw new Error(`接口 ${apiPath} 的 required 属性必须是字符串数组`);
|
|
474
390
|
}
|
|
475
|
-
|
|
476
|
-
Logger.debug(`[${dirDisplayName}] API 属性验证通过: ${apiPath}`);
|
|
477
|
-
|
|
478
391
|
// 构建路由:
|
|
479
392
|
// - core 接口: /api/core/{apiPath}
|
|
480
393
|
// - addon 接口: /api/addon/{addonName}/{apiPath}
|
|
@@ -488,22 +401,19 @@ export class Loader {
|
|
|
488
401
|
}
|
|
489
402
|
apiRoutes.set(api.route, api);
|
|
490
403
|
|
|
491
|
-
const singleApiTime = calcPerfTime(singleApiStart);
|
|
492
404
|
loadedApis++;
|
|
493
|
-
Logger.debug(`[${dirDisplayName}] API 注册成功 - 名称: ${api.name}, 路由: ${api.route}, 耗时: ${singleApiTime}`);
|
|
494
405
|
} catch (error: any) {
|
|
495
|
-
const singleApiTime = calcPerfTime(singleApiStart);
|
|
496
406
|
failedApis++;
|
|
497
407
|
|
|
498
408
|
// 记录详细错误信息
|
|
499
|
-
Logger.error(`[${dirDisplayName}] 接口 ${apiPath}
|
|
409
|
+
Logger.error(`[${dirDisplayName}] 接口 ${apiPath} 加载失败`, error);
|
|
500
410
|
|
|
501
411
|
process.exit(1);
|
|
502
412
|
}
|
|
503
413
|
}
|
|
504
414
|
|
|
505
415
|
const totalLoadTime = calcPerfTime(loadStartTime);
|
|
506
|
-
Logger.info(
|
|
416
|
+
Logger.info(`✓ ${dirDisplayName}接口加载完成: ${loadedApis}/${totalApis},耗时: ${totalLoadTime}`);
|
|
507
417
|
|
|
508
418
|
// 检查是否有加载失败的 API(理论上不会到达这里,因为上面已经 critical 退出)
|
|
509
419
|
if (failedApis > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "befly",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.2",
|
|
4
4
|
"description": "Befly - 为 Bun 专属打造的 TypeScript API 接口框架核心引擎",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -75,10 +75,8 @@
|
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
77
|
"chalk": "^5.6.2",
|
|
78
|
-
"commander": "^14.0.2",
|
|
79
78
|
"es-toolkit": "^1.41.0",
|
|
80
|
-
"inquirer": "^12.10.0",
|
|
81
79
|
"pathe": "^2.0.3"
|
|
82
80
|
},
|
|
83
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "0896911e340ee0e7ee9d65a28d0809a3365ee9f4"
|
|
84
82
|
}
|
package/commands/build.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build 命令 - 构建项目
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { join } from 'pathe';
|
|
6
|
-
import { existsSync } from 'node:fs';
|
|
7
|
-
import { Logger } from '../lib/logger.js';
|
|
8
|
-
import { getProjectRoot } from './util.js';
|
|
9
|
-
|
|
10
|
-
interface BuildOptions {
|
|
11
|
-
outdir: string;
|
|
12
|
-
minify: boolean;
|
|
13
|
-
sourcemap: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export async function buildCommand(options: BuildOptions) {
|
|
17
|
-
try {
|
|
18
|
-
const projectRoot = getProjectRoot();
|
|
19
|
-
|
|
20
|
-
// 验证是否在项目目录下
|
|
21
|
-
const packageJsonPath = join(projectRoot, 'package.json');
|
|
22
|
-
if (!existsSync(packageJsonPath)) {
|
|
23
|
-
Logger.error('未找到 package.json 文件,请确保在项目目录下');
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// 使用内置默认入口文件
|
|
28
|
-
const entryFile = join(import.meta.dir, '..', 'entry.ts');
|
|
29
|
-
|
|
30
|
-
Logger.info('正在构建项目...');
|
|
31
|
-
|
|
32
|
-
const args = ['build', entryFile, '--outdir', options.outdir, '--target', 'bun'];
|
|
33
|
-
|
|
34
|
-
if (options.minify) {
|
|
35
|
-
args.push('--minify');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (options.sourcemap) {
|
|
39
|
-
args.push('--sourcemap');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const proc = Bun.spawn(['bun', ...args], {
|
|
43
|
-
cwd: projectRoot,
|
|
44
|
-
stdout: 'pipe',
|
|
45
|
-
stderr: 'pipe'
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
await proc.exited;
|
|
49
|
-
|
|
50
|
-
if (proc.exitCode === 0) {
|
|
51
|
-
Logger.success('项目构建完成');
|
|
52
|
-
Logger.success(`输出目录: ${options.outdir}`);
|
|
53
|
-
} else {
|
|
54
|
-
Logger.error('项目构建失败');
|
|
55
|
-
process.exit(1);
|
|
56
|
-
}
|
|
57
|
-
} catch (error) {
|
|
58
|
-
Logger.error('构建失败:');
|
|
59
|
-
console.error(error);
|
|
60
|
-
process.exit(1);
|
|
61
|
-
}
|
|
62
|
-
}
|