befly 2.1.0 → 2.2.0

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 CHANGED
@@ -1,3 +1,3 @@
1
1
  # Befly - 蜜蜂飞舞
2
2
 
3
- 道生一,一生二,二生三,三生万物,v3版本发布后可才是公测版本。
3
+ 道生一,一生二,二生三,三生万物,v3 版本发布后可才是公测版本。
@@ -1,6 +1,6 @@
1
1
  import { Env } from '../../config/env.js';
2
2
  import { Api } from '../../utils/api.js';
3
- import { RYes, RNo } from '../../utils/util.js';
3
+ import { RYes, RNo } from '../../utils/index.js';
4
4
 
5
5
  export default Api.POST(
6
6
  //
@@ -1,6 +1,6 @@
1
1
  import { Env } from '../../config/env.js';
2
2
  import { Api } from '../../utils/api.js';
3
- import { RYes, RNo } from '../../utils/util.js';
3
+ import { RYes, RNo } from '../../utils/index.js';
4
4
  import { Jwt } from '../../utils/jwt.js';
5
5
 
6
6
  export default Api.POST(
package/bunfig.toml ADDED
@@ -0,0 +1,3 @@
1
+ [install]
2
+ linker = "isolated"
3
+ node-gyp = "bun x node-gyp"
package/checks/table.js CHANGED
@@ -1,51 +1,11 @@
1
1
  import path from 'node:path';
2
2
  import { Logger } from '../utils/logger.js';
3
- import { parseFieldRule } from '../utils/util.js';
3
+ import { parseFieldRule, validateFieldName, validateFieldType, validateMinMax, validateDefaultValue, validateIndex, validateRegex } from '../utils/index.js';
4
4
  import { __dirtables, getProjectDir } from '../system.js';
5
5
 
6
- // 验证字段名称是否为中文、数字、字母
7
- const validateFieldName = (name) => {
8
- const nameRegex = /^[\u4e00-\u9fa5a-zA-Z0-9]+$/;
9
- return nameRegex.test(name);
10
- };
11
-
12
- // 验证字段类型是否为指定的四种类型之一
13
- const validateFieldType = (type) => {
14
- const validTypes = ['string', 'number', 'text', 'array'];
15
- return validTypes.includes(type);
16
- };
17
-
18
- // 验证最小值/最大值是否为null或数字
19
- const validateMinMax = (value) => {
20
- return value === 'null' || (!isNaN(parseFloat(value)) && isFinite(parseFloat(value)));
21
- };
22
-
23
- // 验证默认值是否为null、字符串或数字
24
- const validateDefaultValue = (value) => {
25
- if (value === 'null') return true;
26
- // 检查是否为数字
27
- if (!isNaN(parseFloat(value)) && isFinite(parseFloat(value))) return true;
28
- // 其他情况视为字符串,都是有效的
29
- return true;
30
- };
31
-
32
- // 验证索引标识是否为0或1
33
- const validateIndex = (value) => {
34
- return value === '0' || value === '1';
35
- };
36
-
37
- // 验证正则表达式是否有效
38
- const validateRegex = (value) => {
39
- if (value === 'null') return true;
40
- try {
41
- new RegExp(value);
42
- return true;
43
- } catch (e) {
44
- return false;
45
- }
46
- };
6
+ // 所有校验函数均复用 utils/index.js 导出的实现
47
7
 
48
- export default async () => {
8
+ export const checkTable = async () => {
49
9
  try {
50
10
  const tablesGlob = new Bun.Glob('*.json');
51
11
 
package/config/env.js CHANGED
@@ -25,14 +25,12 @@ export const Env = {
25
25
  TZ: process.env.TZ,
26
26
  // 数据库配置
27
27
  MYSQL_ENABLE: Number(process.env.MYSQL_ENABLE),
28
- MYSQL_URL: process.env.MYSQL_URL,
29
28
  MYSQL_HOST: process.env.MYSQL_HOST,
30
29
  MYSQL_PORT: Number(process.env.MYSQL_PORT),
31
30
  MYSQL_DB: process.env.MYSQL_DB,
32
31
  MYSQL_USER: process.env.MYSQL_USER,
33
32
  MYSQL_PASSWORD: process.env.MYSQL_PASSWORD,
34
33
  MYSQL_DEBUG: Number(process.env.MYSQL_DEBUG),
35
- MYSQL_POOL_TIMEOUT: Number(process.env.MYSQL_POOL_TIMEOUT),
36
34
  MYSQL_POOL_MAX: Number(process.env.MYSQL_POOL_MAX),
37
35
  // Redis配置
38
36
  REDIS_URL: process.env.REDIS_URL,
package/main.js CHANGED
@@ -5,10 +5,10 @@ import { Logger } from './utils/logger.js';
5
5
  import { Jwt } from './utils/jwt.js';
6
6
  import { validator } from './utils/validate.js';
7
7
  import { Crypto2 } from './utils/crypto.js';
8
- import { Xml } from './libs/xml.js';
8
+ import { Xml } from './utils/xml.js';
9
9
  import { SyncDb } from './scripts/syncDb.js';
10
10
  import { __dirchecks, __dirplugins, __dirapis, getProjectDir } from './system.js';
11
- import { isEmptyObject, isType, pickFields, sortPlugins, RYes, RNo, filterLogFields, setCorsOptions, calculateElapsedTime } from './utils/util.js';
11
+ import { isEmptyObject, isType, pickFields, sortPlugins, RYes, RNo, filterLogFields, setCorsOptions, calcPerfTime } from './utils/index.js';
12
12
 
13
13
  class Befly {
14
14
  constructor(options = {}) {
@@ -48,7 +48,7 @@ class Befly {
48
48
  // 执行默认导出的函数
49
49
  if (typeof check.default === 'function') {
50
50
  const checkResult = await check.default(this.appContext);
51
- const singleCheckTime = calculateElapsedTime(singleCheckStart);
51
+ const singleCheckTime = calcPerfTime(singleCheckStart);
52
52
 
53
53
  if (checkResult === true) {
54
54
  passedChecks++;
@@ -58,12 +58,12 @@ class Befly {
58
58
  failedChecks++;
59
59
  }
60
60
  } else {
61
- const singleCheckTime = calculateElapsedTime(singleCheckStart);
61
+ const singleCheckTime = calcPerfTime(singleCheckStart);
62
62
  Logger.warn(`文件 ${fileName} 未导出默认函数,耗时: ${singleCheckTime}`);
63
63
  failedChecks++;
64
64
  }
65
65
  } catch (error) {
66
- const singleCheckTime = calculateElapsedTime(singleCheckStart);
66
+ const singleCheckTime = calcPerfTime(singleCheckStart);
67
67
  Logger.error({
68
68
  msg: `检查失败 ${fileName},耗时: ${singleCheckTime}`,
69
69
  error: error.message,
@@ -73,7 +73,7 @@ class Befly {
73
73
  }
74
74
  }
75
75
 
76
- const totalCheckTime = calculateElapsedTime(checkStartTime);
76
+ const totalCheckTime = calcPerfTime(checkStartTime);
77
77
 
78
78
  // 输出检查结果统计
79
79
  Logger.info(`系统检查完成! 总耗时: ${totalCheckTime},总检查数: ${totalChecks}, 通过: ${passedChecks}, 失败: ${failedChecks}`);
@@ -103,6 +103,7 @@ class Befly {
103
103
  const corePlugins = [];
104
104
  const userPlugins = [];
105
105
  const loadedPluginNames = new Set(); // 用于跟踪已加载的插件名称
106
+ let hadPluginError = false; // 统一记录插件阶段是否有错误
106
107
 
107
108
  // 扫描核心插件目录
108
109
  const corePluginsScanStart = Bun.nanoseconds();
@@ -114,18 +115,27 @@ class Befly {
114
115
  const fileName = path.basename(file, '.js');
115
116
  if (fileName.startsWith('_')) continue;
116
117
 
117
- const importStart = Bun.nanoseconds();
118
- const plugin = await import(file);
119
- const importTime = calculateElapsedTime(importStart);
120
-
121
- const pluginInstance = plugin.default;
122
- pluginInstance.pluginName = fileName;
123
- corePlugins.push(pluginInstance);
124
- loadedPluginNames.add(fileName); // 记录已加载的核心插件名称
125
-
126
- Logger.info(`核心插件 ${fileName} 导入耗时: ${importTime}`);
118
+ try {
119
+ const importStart = Bun.nanoseconds();
120
+ const plugin = await import(file);
121
+ const importTime = calcPerfTime(importStart);
122
+
123
+ const pluginInstance = plugin.default;
124
+ pluginInstance.pluginName = fileName;
125
+ corePlugins.push(pluginInstance);
126
+ loadedPluginNames.add(fileName); // 记录已加载的核心插件名称
127
+
128
+ Logger.info(`核心插件 ${fileName} 导入耗时: ${importTime}`);
129
+ } catch (err) {
130
+ hadPluginError = true;
131
+ Logger.error({
132
+ msg: `核心插件 ${fileName} 导入失败`,
133
+ error: err.message,
134
+ stack: err.stack
135
+ });
136
+ }
127
137
  }
128
- const corePluginsScanTime = calculateElapsedTime(corePluginsScanStart);
138
+ const corePluginsScanTime = calcPerfTime(corePluginsScanStart);
129
139
  Logger.info(`核心插件扫描完成,耗时: ${corePluginsScanTime},共找到 ${corePlugins.length} 个插件`);
130
140
 
131
141
  const sortedCorePlugins = sortPlugins(corePlugins);
@@ -141,10 +151,11 @@ class Befly {
141
151
  this.pluginLists.push(plugin);
142
152
  this.appContext[plugin.pluginName] = typeof plugin?.onInit === 'function' ? await plugin?.onInit(this.appContext) : {};
143
153
  } catch (error) {
144
- Logger.warn(`插件 ${plugin.pluginName} 初始化失败:`, error.message);
154
+ hadPluginError = true;
155
+ Logger.warn(`插件 ${plugin.pluginName} 初始化失败: ${error.message}`);
145
156
  }
146
157
  }
147
- const corePluginsInitTime = calculateElapsedTime(corePluginsInitStart);
158
+ const corePluginsInitTime = calcPerfTime(corePluginsInitStart);
148
159
  Logger.info(`核心插件初始化完成,耗时: ${corePluginsInitTime}`);
149
160
 
150
161
  // 扫描用户插件目录
@@ -163,17 +174,26 @@ class Befly {
163
174
  continue;
164
175
  }
165
176
 
166
- const importStart = Bun.nanoseconds();
167
- const plugin = await import(file);
168
- const importTime = calculateElapsedTime(importStart);
177
+ try {
178
+ const importStart = Bun.nanoseconds();
179
+ const plugin = await import(file);
180
+ const importTime = calcPerfTime(importStart);
169
181
 
170
- const pluginInstance = plugin.default;
171
- pluginInstance.pluginName = fileName;
172
- userPlugins.push(pluginInstance);
182
+ const pluginInstance = plugin.default;
183
+ pluginInstance.pluginName = fileName;
184
+ userPlugins.push(pluginInstance);
173
185
 
174
- Logger.info(`用户插件 ${fileName} 导入耗时: ${importTime}`);
186
+ Logger.info(`用户插件 ${fileName} 导入耗时: ${importTime}`);
187
+ } catch (err) {
188
+ hadPluginError = true;
189
+ Logger.error({
190
+ msg: `用户插件 ${fileName} 导入失败`,
191
+ error: err.message,
192
+ stack: err.stack
193
+ });
194
+ }
175
195
  }
176
- const userPluginsScanTime = calculateElapsedTime(userPluginsScanStart);
196
+ const userPluginsScanTime = calcPerfTime(userPluginsScanStart);
177
197
  Logger.info(`用户插件扫描完成,耗时: ${userPluginsScanTime},共找到 ${userPlugins.length} 个插件`);
178
198
 
179
199
  const sortedUserPlugins = sortPlugins(userPlugins);
@@ -190,22 +210,31 @@ class Befly {
190
210
  this.pluginLists.push(plugin);
191
211
  this.appContext[plugin.pluginName] = typeof plugin?.onInit === 'function' ? await plugin?.onInit(this.appContext) : {};
192
212
  } catch (error) {
193
- Logger.warn(`插件 ${plugin.pluginName} 初始化失败:`, error.message);
213
+ hadPluginError = true;
214
+ Logger.warn(`插件 ${plugin.pluginName} 初始化失败: ${error.message}`);
194
215
  }
195
216
  }
196
- const userPluginsInitTime = calculateElapsedTime(userPluginsInitStart);
217
+ const userPluginsInitTime = calcPerfTime(userPluginsInitStart);
197
218
  Logger.info(`用户插件初始化完成,耗时: ${userPluginsInitTime}`);
198
219
  }
199
220
 
200
- const totalLoadTime = calculateElapsedTime(loadStartTime);
221
+ const totalLoadTime = calcPerfTime(loadStartTime);
201
222
  const totalPluginCount = sortedCorePlugins.length + sortedUserPlugins.length;
202
223
  Logger.info(`插件加载完成! 总耗时: ${totalLoadTime},共加载 ${totalPluginCount} 个插件`);
224
+
225
+ // 如果任意插件导入或初始化失败,统一退出进程
226
+ if (hadPluginError) {
227
+ Logger.error('检测到插件导入或初始化失败,进程即将退出');
228
+ process.exit(1);
229
+ }
203
230
  } catch (error) {
204
231
  Logger.error({
205
232
  msg: '加载插件时发生错误',
206
233
  error: error.message,
207
234
  stack: error.stack
208
235
  });
236
+ // 兜底退出,避免服务在插件阶段异常后继续运行
237
+ process.exit(1);
209
238
  }
210
239
  }
211
240
  async loadApis(dirName) {
@@ -257,11 +286,11 @@ class Befly {
257
286
  api.route = `${api.method.toUpperCase()}/api/${dirName}/${apiPath}`;
258
287
  this.apiRoutes.set(api.route, api);
259
288
 
260
- const singleApiTime = calculateElapsedTime(singleApiStart);
289
+ const singleApiTime = calcPerfTime(singleApiStart);
261
290
  loadedApis++;
262
291
  // Logger.info(`${dirDisplayName}接口 ${apiPath} 加载成功,耗时: ${singleApiTime}`);
263
292
  } catch (error) {
264
- const singleApiTime = calculateElapsedTime(singleApiStart);
293
+ const singleApiTime = calcPerfTime(singleApiStart);
265
294
  failedApis++;
266
295
  Logger.error({
267
296
  msg: `${dirDisplayName}接口 ${apiPath} 加载失败,耗时: ${singleApiTime}`,
@@ -271,7 +300,7 @@ class Befly {
271
300
  }
272
301
  }
273
302
 
274
- const totalLoadTime = calculateElapsedTime(loadStartTime);
303
+ const totalLoadTime = calcPerfTime(loadStartTime);
275
304
  Logger.info(`${dirDisplayName}接口加载完成! 总耗时: ${totalLoadTime},总数: ${totalApis}, 成功: ${loadedApis}, 失败: ${failedApis}`);
276
305
  } catch (error) {
277
306
  Logger.error({
@@ -294,7 +323,7 @@ class Befly {
294
323
  await this.loadApis('core');
295
324
  await this.loadApis('app');
296
325
 
297
- const totalStartupTime = calculateElapsedTime(serverStartTime);
326
+ const totalStartupTime = calcPerfTime(serverStartTime);
298
327
  Logger.info(`服务器启动准备完成,总耗时: ${totalStartupTime}`);
299
328
 
300
329
  const server = Bun.serve({
@@ -528,7 +557,7 @@ class Befly {
528
557
  }
529
558
  });
530
559
 
531
- const finalStartupTime = calculateElapsedTime(serverStartTime);
560
+ const finalStartupTime = calcPerfTime(serverStartTime);
532
561
  Logger.info(`Befly 服务器启动成功! 完整启动耗时: ${finalStartupTime}`);
533
562
  Logger.info(`服务器监听地址: http://${Env.APP_HOST}:${Env.APP_PORT}`);
534
563
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "befly",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Buma - 为 Bun 专属打造的 API 接口框架核心引擎",
5
5
  "type": "module",
6
6
  "private": false,
@@ -15,12 +15,7 @@
15
15
  "scripts": {
16
16
  "ra": "bun run release.js -a",
17
17
  "rb": "bun run release.js -b",
18
- "rc": "bun run release.js -c",
19
- "test": "bun test",
20
- "test:jwt": "bun test tests/jwt.test.js",
21
- "dev": "bun run project/main.js",
22
- "server": "bunx --bun pm2 start pm2.config.cjs -a",
23
- "syncDb": "bun run scripts/syncDb.js"
18
+ "rc": "bun run release.js -c"
24
19
  },
25
20
  "keywords": [
26
21
  "bun",
@@ -39,7 +34,6 @@
39
34
  "apis/",
40
35
  "checks/",
41
36
  "config/",
42
- "libs/",
43
37
  "plugins/",
44
38
  "scripts/",
45
39
  "tables/",
@@ -51,25 +45,18 @@
51
45
  ".npmrc",
52
46
  ".prettierignore",
53
47
  ".prettierrc",
48
+ "bunfig.toml",
54
49
  "LICENSE",
55
50
  "main.js",
56
51
  "system.js",
57
52
  "package.json",
58
- "README.md",
59
- "USEAGE.md",
60
- "vitest.config.js"
53
+ "README.md"
61
54
  ],
62
- "gitHead": "1dc5f118a723969456559e758e2ba889f4601224",
63
- "dependencies": {},
64
55
  "simple-git-hooks": {
65
56
  "pre-commit": "bunx --bun lint-staged"
66
57
  },
67
58
  "lint-staged": {
68
59
  "*.{js,css,scss,less,ts,jsx,vue,html,json,md,yaml}": "bunx --bun prettier --write --cache --ignore-unknown"
69
60
  },
70
- "devDependencies": {
71
- "lint-staged": "^16.1.5",
72
- "prettier": "^3.6.2",
73
- "simple-git-hooks": "^2.13.1"
74
- }
61
+ "gitHead": "1dc5f118a723969456559e758e2ba889f4601224"
75
62
  }