befly 2.0.12 → 2.1.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/.gitignore ADDED
@@ -0,0 +1,94 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ esdata
6
+ data
7
+ .cache
8
+ lab
9
+ labs
10
+ cache
11
+ .VSCodeCounter
12
+ oclif.manifest.json
13
+ dist
14
+ report.html
15
+ dist-ssr
16
+ *.local
17
+ .vscode-test/
18
+ *.vsix
19
+ out
20
+ CHANGELOG.md
21
+ note.md
22
+ .changeset
23
+ addons2
24
+ pnpm-lock.yaml
25
+ bun.lock
26
+ other
27
+
28
+ # Editor directories and files
29
+ .vscode/*
30
+ .cache
31
+ .yicode/auto-imports.d.ts
32
+ !.vscode/extensions.json
33
+ .idea
34
+ .DS_Store
35
+ *.suo
36
+ *.ntvs*
37
+ *.njsproj
38
+ *.sln
39
+ *.sw?
40
+
41
+ # Runtime data
42
+ pids
43
+ *.pid
44
+ *.seed
45
+
46
+ # Directory for instrumented libs generated by jscoverage/JSCover
47
+ lib-cov
48
+
49
+ # Coverage directory used by tools like istanbul
50
+ coverage
51
+
52
+ # nyc test coverage
53
+ .nyc_output
54
+
55
+ # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
56
+ .grunt
57
+
58
+ # node-waf configuration
59
+ .lock-wscript
60
+
61
+ # Compiled binary addons (http://nodejs.org/api/addons.html)
62
+ build/Release
63
+
64
+ # Dependency directories
65
+ node_modules
66
+ jspm_packages
67
+
68
+ # Optional npm cache directory
69
+ .npm
70
+
71
+ # Optional REPL history
72
+ .node_repl_history
73
+
74
+ # 0x
75
+ profile-*
76
+
77
+ # mac files
78
+ .DS_Store
79
+
80
+ # vim swap files
81
+ *.swp
82
+
83
+ # webstorm
84
+ .idea
85
+
86
+ # vscode
87
+ .vscode
88
+ *code-workspace
89
+
90
+ # clinic
91
+ profile*
92
+ *clinic*
93
+ *flamegraph*
94
+ logs
package/.npmrc ADDED
@@ -0,0 +1,3 @@
1
+ # registry=https://registry.npmmirror.com
2
+ registry=https://registry.npmjs.org
3
+ link-workspace-packages=true
@@ -0,0 +1,2 @@
1
+ LICENSE
2
+ LICENSE.md
package/.prettierrc ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "trailingComma": "none",
3
+ "tabWidth": 4,
4
+ "semi": true,
5
+ "singleQuote": true,
6
+ "printWidth": 1024,
7
+ "bracketSpacing": true,
8
+ "useTabs": false,
9
+ "arrowParens": "always",
10
+ "endOfLine": "lf"
11
+ }
package/README.md CHANGED
@@ -1,3 +1,3 @@
1
- # Befly
1
+ # Befly - 蜜蜂飞舞
2
2
 
3
- 自用框架,请勿使用。
3
+ 道生一,一生二,二生三,三生万物,v3版本发布后可才是公测版本。
@@ -0,0 +1,215 @@
1
+ import path from 'node:path';
2
+ import { Logger } from '../utils/logger.js';
3
+ import { parseFieldRule } from '../utils/util.js';
4
+ import { __dirtables, getProjectDir } from '../system.js';
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
+ };
47
+
48
+ export default async () => {
49
+ try {
50
+ const tablesGlob = new Bun.Glob('*.json');
51
+
52
+ // 统计信息
53
+ let totalFiles = 0;
54
+ let totalRules = 0;
55
+ let validFiles = 0;
56
+ let invalidFiles = 0;
57
+
58
+ // 收集所有表文件
59
+ const allTableFiles = [];
60
+ const coreTableNames = new Set(); // 存储内核表文件名
61
+
62
+ // 收集内核表字段定义文件
63
+ for await (const file of tablesGlob.scan({
64
+ cwd: __dirtables,
65
+ absolute: true,
66
+ onlyFiles: true
67
+ })) {
68
+ const fileName = path.basename(file, '.json');
69
+ coreTableNames.add(fileName);
70
+ allTableFiles.push({ file, type: 'core' });
71
+ }
72
+
73
+ // 收集项目表字段定义文件,并检查是否与内核表同名
74
+ for await (const file of tablesGlob.scan({
75
+ cwd: getProjectDir('tables'),
76
+ absolute: true,
77
+ onlyFiles: true
78
+ })) {
79
+ const fileName = path.basename(file, '.json');
80
+
81
+ // 检查项目表是否与内核表同名
82
+ if (coreTableNames.has(fileName)) {
83
+ Logger.error(`项目表 ${fileName}.json 与内核表同名,项目表不能与内核表定义文件同名`);
84
+ invalidFiles++;
85
+ totalFiles++;
86
+ continue;
87
+ }
88
+
89
+ allTableFiles.push({ file, type: 'project' });
90
+ }
91
+
92
+ // 保留字段列表
93
+ const reservedFields = ['id', 'created_at', 'updated_at', 'deleted_at', 'state'];
94
+
95
+ // 合并进行验证逻辑
96
+ for (const { file, type } of allTableFiles) {
97
+ totalFiles++;
98
+ const fileName = path.basename(file);
99
+ const fileType = type === 'core' ? '内核' : '项目';
100
+
101
+ try {
102
+ // 读取并解析 JSON 文件
103
+ const table = await Bun.file(file).json();
104
+ let fileValid = true;
105
+ let fileRules = 0;
106
+
107
+ // 检查 table 中的每个验证规则
108
+ for (const [fieldName, rule] of Object.entries(table)) {
109
+ fileRules++;
110
+ totalRules++;
111
+
112
+ // 检查是否使用了保留字段
113
+ if (reservedFields.includes(fieldName)) {
114
+ Logger.error(`${fileType}表 ${fileName} 文件包含保留字段 ${fieldName},不能在表定义中使用以下字段: ${reservedFields.join(', ')}`);
115
+ fileValid = false;
116
+ continue;
117
+ }
118
+
119
+ // 验证规则格式
120
+ try {
121
+ const ruleParts = parseFieldRule(rule);
122
+
123
+ if (ruleParts.length !== 7) {
124
+ Logger.warn(`${fileType}表 ${fileName} 文件 ${fieldName} 验证规则错误,应包含 7 个部分,但包含 ${ruleParts.length} 个部分`);
125
+ fileValid = false;
126
+ continue;
127
+ }
128
+
129
+ const [name, type, minStr, maxStr, defaultValue, isIndexStr, regexConstraint] = ruleParts;
130
+
131
+ // 使用新的验证函数进行严格验证
132
+ // 第1个值:名称必须为中文、数字、字母
133
+ if (!validateFieldName(name)) {
134
+ Logger.error(`${fileType}表 ${fileName} 文件 ${fieldName} 名称 "${name}" 格式错误,必须为中文、数字、字母`);
135
+ fileValid = false;
136
+ continue;
137
+ }
138
+
139
+ // 第2个值:字段类型必须为string,number,text,array之一
140
+ if (!validateFieldType(type)) {
141
+ Logger.error(`${fileType}表 ${fileName} 文件 ${fieldName} 类型 "${type}" 格式错误,必须为string、number、text、array之一`);
142
+ fileValid = false;
143
+ continue;
144
+ }
145
+
146
+ // 第3个值:最小值必须为null或数字
147
+ if (!validateMinMax(minStr)) {
148
+ Logger.error(`${fileType}表 ${fileName} 文件 ${fieldName} 最小值 "${minStr}" 格式错误,必须为null或数字`);
149
+ fileValid = false;
150
+ continue;
151
+ }
152
+
153
+ // 第4个值:当类型为 string/array 时,最大长度必须为数字且不可为 null;其他类型允许为 null 或数字
154
+ if (type === 'string' || type === 'array') {
155
+ if (maxStr === 'null' || !validateMinMax(maxStr)) {
156
+ Logger.error(`${fileType}表 ${fileName} 文件 ${fieldName} 最大长度 "${maxStr}" 格式错误,string/array 类型必须为具体数字`);
157
+ fileValid = false;
158
+ continue;
159
+ }
160
+ } else {
161
+ if (!validateMinMax(maxStr)) {
162
+ Logger.error(`${fileType}表 ${fileName} 文件 ${fieldName} 最大值 "${maxStr}" 格式错误,必须为null或数字`);
163
+ fileValid = false;
164
+ continue;
165
+ }
166
+ }
167
+
168
+ // 第5个值:默认值必须为null、字符串或数字
169
+ if (!validateDefaultValue(defaultValue)) {
170
+ Logger.error(`${fileType}表 ${fileName} 文件 ${fieldName} 默认值 "${defaultValue}" 格式错误,必须为null、字符串或数字`);
171
+ fileValid = false;
172
+ continue;
173
+ }
174
+
175
+ // 第6个值:是否创建索引必须为0或1
176
+ if (!validateIndex(isIndexStr)) {
177
+ Logger.error(`${fileType}表 ${fileName} 文件 ${fieldName} 索引标识 "${isIndexStr}" 格式错误,必须为0或1`);
178
+ fileValid = false;
179
+ continue;
180
+ }
181
+
182
+ // 第7个值:必须为null或正则表达式
183
+ if (!validateRegex(regexConstraint)) {
184
+ Logger.error(`${fileType}表 ${fileName} 文件 ${fieldName} 正则约束 "${regexConstraint}" 格式错误,必须为null或有效的正则表达式`);
185
+ fileValid = false;
186
+ continue;
187
+ }
188
+ } catch (error) {
189
+ Logger.error(`${fileType}表 ${fileName} 文件 ${fieldName} 验证规则解析失败: ${error.message}`);
190
+ fileValid = false;
191
+ continue;
192
+ }
193
+ }
194
+
195
+ if (fileValid) {
196
+ validFiles++;
197
+ } else {
198
+ invalidFiles++;
199
+ }
200
+ } catch (error) {
201
+ Logger.error(`${fileType}表 ${fileName} 解析失败: ${error.message}`);
202
+ invalidFiles++;
203
+ }
204
+ }
205
+
206
+ if (invalidFiles > 0) {
207
+ return false;
208
+ } else {
209
+ return true;
210
+ }
211
+ } catch (error) {
212
+ Logger.error(`Tables 检查过程中出错:`, error);
213
+ return false;
214
+ }
215
+ };
package/config/env.js CHANGED
@@ -25,6 +25,7 @@ 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,
28
29
  MYSQL_HOST: process.env.MYSQL_HOST,
29
30
  MYSQL_PORT: Number(process.env.MYSQL_PORT),
30
31
  MYSQL_DB: process.env.MYSQL_DB,
package/main.js CHANGED
@@ -1,27 +1,14 @@
1
1
  import path from 'node:path';
2
2
  import { Env } from './config/env.js';
3
-
4
- // 工具函数
5
3
  import { Api } from './utils/api.js';
6
4
  import { Logger } from './utils/logger.js';
7
5
  import { Jwt } from './utils/jwt.js';
8
6
  import { validator } from './utils/validate.js';
9
7
  import { Crypto2 } from './utils/crypto.js';
10
8
  import { Xml } from './libs/xml.js';
11
- import { isEmptyObject, isType, pickFields, sortPlugins, RYes, RNo, filename2, dirname2, filterLogFields } from './utils/util.js';
12
-
13
- const setCorsOptions = (req) => {
14
- return {
15
- headers: {
16
- 'Access-Control-Allow-Origin': Env.ALLOWED_ORIGIN || req.headers.get('origin') || '*',
17
- 'Access-Control-Allow-Methods': Env.ALLOWED_METHODS || 'GET, POST, PUT, DELETE, OPTIONS',
18
- 'Access-Control-Allow-Headers': Env.ALLOWED_HEADERS || 'Content-Type, Authorization, authorization, token',
19
- 'Access-Control-Expose-Headers': Env.EXPOSE_HEADERS || 'Content-Range, X-Content-Range, Authorization, authorization, token',
20
- 'Access-Control-Max-Age': Env.MAX_AGE || 86400,
21
- 'Access-Control-Allow-Credentials': Env.ALLOW_CREDENTIALS || 'true'
22
- }
23
- };
24
- };
9
+ import { SyncDb } from './scripts/syncDb.js';
10
+ import { __dirchecks, __dirplugins, __dirapis, getProjectDir } from './system.js';
11
+ import { isEmptyObject, isType, pickFields, sortPlugins, RYes, RNo, filterLogFields, setCorsOptions, calculateElapsedTime } from './utils/util.js';
25
12
 
26
13
  class Befly {
27
14
  constructor(options = {}) {
@@ -34,9 +21,7 @@ class Befly {
34
21
  async initCheck() {
35
22
  try {
36
23
  const checkStartTime = Bun.nanoseconds();
37
- Logger.info('开始执行系统检查...');
38
24
 
39
- const checksDir = path.join(dirname2(import.meta.url), 'checks');
40
25
  const glob = new Bun.Glob('*.js');
41
26
 
42
27
  // 统计信息
@@ -46,7 +31,7 @@ class Befly {
46
31
 
47
32
  // 扫描并执行检查函数
48
33
  for await (const file of glob.scan({
49
- cwd: checksDir,
34
+ cwd: __dirchecks,
50
35
  onlyFiles: true,
51
36
  absolute: true
52
37
  })) {
@@ -63,24 +48,24 @@ class Befly {
63
48
  // 执行默认导出的函数
64
49
  if (typeof check.default === 'function') {
65
50
  const checkResult = await check.default(this.appContext);
66
- const singleCheckTime = (Bun.nanoseconds() - singleCheckStart) / 1_000_000;
51
+ const singleCheckTime = calculateElapsedTime(singleCheckStart);
67
52
 
68
53
  if (checkResult === true) {
69
54
  passedChecks++;
70
- Logger.info(`检查 ${fileName} 通过,耗时: ${singleCheckTime.toFixed(2)}ms`);
55
+ Logger.info(`检查 ${fileName} 通过,耗时: ${singleCheckTime}`);
71
56
  } else {
72
- Logger.error(`检查未通过: ${fileName},耗时: ${singleCheckTime.toFixed(2)}ms`);
57
+ Logger.error(`检查未通过: ${fileName},耗时: ${singleCheckTime}`);
73
58
  failedChecks++;
74
59
  }
75
60
  } else {
76
- const singleCheckTime = (Bun.nanoseconds() - singleCheckStart) / 1_000_000;
77
- Logger.warn(`文件 ${fileName} 未导出默认函数,耗时: ${singleCheckTime.toFixed(2)}ms`);
61
+ const singleCheckTime = calculateElapsedTime(singleCheckStart);
62
+ Logger.warn(`文件 ${fileName} 未导出默认函数,耗时: ${singleCheckTime}`);
78
63
  failedChecks++;
79
64
  }
80
65
  } catch (error) {
81
- const singleCheckTime = (Bun.nanoseconds() - singleCheckStart) / 1_000_000;
66
+ const singleCheckTime = calculateElapsedTime(singleCheckStart);
82
67
  Logger.error({
83
- msg: `检查失败 ${fileName},耗时: ${singleCheckTime.toFixed(2)}ms`,
68
+ msg: `检查失败 ${fileName},耗时: ${singleCheckTime}`,
84
69
  error: error.message,
85
70
  stack: error.stack
86
71
  });
@@ -88,10 +73,10 @@ class Befly {
88
73
  }
89
74
  }
90
75
 
91
- const totalCheckTime = (Bun.nanoseconds() - checkStartTime) / 1_000_000;
76
+ const totalCheckTime = calculateElapsedTime(checkStartTime);
92
77
 
93
78
  // 输出检查结果统计
94
- Logger.info(`系统检查完成! 总耗时: ${totalCheckTime.toFixed(2)}ms,总检查数: ${totalChecks}, 通过: ${passedChecks}, 失败: ${failedChecks}`);
79
+ Logger.info(`系统检查完成! 总耗时: ${totalCheckTime},总检查数: ${totalChecks}, 通过: ${passedChecks}, 失败: ${failedChecks}`);
95
80
 
96
81
  if (failedChecks > 0) {
97
82
  process.exit();
@@ -122,7 +107,7 @@ class Befly {
122
107
  // 扫描核心插件目录
123
108
  const corePluginsScanStart = Bun.nanoseconds();
124
109
  for await (const file of glob.scan({
125
- cwd: path.join(dirname2(import.meta.url), 'plugins'),
110
+ cwd: __dirplugins,
126
111
  onlyFiles: true,
127
112
  absolute: true
128
113
  })) {
@@ -131,17 +116,17 @@ class Befly {
131
116
 
132
117
  const importStart = Bun.nanoseconds();
133
118
  const plugin = await import(file);
134
- const importTime = (Bun.nanoseconds() - importStart) / 1_000_000; // 转换为毫秒
119
+ const importTime = calculateElapsedTime(importStart);
135
120
 
136
121
  const pluginInstance = plugin.default;
137
122
  pluginInstance.pluginName = fileName;
138
123
  corePlugins.push(pluginInstance);
139
124
  loadedPluginNames.add(fileName); // 记录已加载的核心插件名称
140
125
 
141
- Logger.info(`核心插件 ${fileName} 导入耗时: ${importTime.toFixed(2)}ms`);
126
+ Logger.info(`核心插件 ${fileName} 导入耗时: ${importTime}`);
142
127
  }
143
- const corePluginsScanTime = (Bun.nanoseconds() - corePluginsScanStart) / 1_000_000;
144
- Logger.info(`核心插件扫描完成,耗时: ${corePluginsScanTime.toFixed(2)}ms,共找到 ${corePlugins.length} 个插件`);
128
+ const corePluginsScanTime = calculateElapsedTime(corePluginsScanStart);
129
+ Logger.info(`核心插件扫描完成,耗时: ${corePluginsScanTime},共找到 ${corePlugins.length} 个插件`);
145
130
 
146
131
  const sortedCorePlugins = sortPlugins(corePlugins);
147
132
  if (sortedCorePlugins === false) {
@@ -159,13 +144,13 @@ class Befly {
159
144
  Logger.warn(`插件 ${plugin.pluginName} 初始化失败:`, error.message);
160
145
  }
161
146
  }
162
- const corePluginsInitTime = (Bun.nanoseconds() - corePluginsInitStart) / 1_000_000;
163
- Logger.info(`核心插件初始化完成,耗时: ${corePluginsInitTime.toFixed(2)}ms`);
147
+ const corePluginsInitTime = calculateElapsedTime(corePluginsInitStart);
148
+ Logger.info(`核心插件初始化完成,耗时: ${corePluginsInitTime}`);
164
149
 
165
150
  // 扫描用户插件目录
166
151
  const userPluginsScanStart = Bun.nanoseconds();
167
152
  for await (const file of glob.scan({
168
- cwd: path.join(process.cwd(), 'plugins'),
153
+ cwd: getProjectDir('plugins'),
169
154
  onlyFiles: true,
170
155
  absolute: true
171
156
  })) {
@@ -180,16 +165,16 @@ class Befly {
180
165
 
181
166
  const importStart = Bun.nanoseconds();
182
167
  const plugin = await import(file);
183
- const importTime = (Bun.nanoseconds() - importStart) / 1_000_000; // 转换为毫秒
168
+ const importTime = calculateElapsedTime(importStart);
184
169
 
185
170
  const pluginInstance = plugin.default;
186
171
  pluginInstance.pluginName = fileName;
187
172
  userPlugins.push(pluginInstance);
188
173
 
189
- Logger.info(`用户插件 ${fileName} 导入耗时: ${importTime.toFixed(2)}ms`);
174
+ Logger.info(`用户插件 ${fileName} 导入耗时: ${importTime}`);
190
175
  }
191
- const userPluginsScanTime = (Bun.nanoseconds() - userPluginsScanStart) / 1_000_000;
192
- Logger.info(`用户插件扫描完成,耗时: ${userPluginsScanTime.toFixed(2)}ms,共找到 ${userPlugins.length} 个插件`);
176
+ const userPluginsScanTime = calculateElapsedTime(userPluginsScanStart);
177
+ Logger.info(`用户插件扫描完成,耗时: ${userPluginsScanTime},共找到 ${userPlugins.length} 个插件`);
193
178
 
194
179
  const sortedUserPlugins = sortPlugins(userPlugins);
195
180
  if (sortedUserPlugins === false) {
@@ -208,13 +193,13 @@ class Befly {
208
193
  Logger.warn(`插件 ${plugin.pluginName} 初始化失败:`, error.message);
209
194
  }
210
195
  }
211
- const userPluginsInitTime = (Bun.nanoseconds() - userPluginsInitStart) / 1_000_000;
212
- Logger.info(`用户插件初始化完成,耗时: ${userPluginsInitTime.toFixed(2)}ms`);
196
+ const userPluginsInitTime = calculateElapsedTime(userPluginsInitStart);
197
+ Logger.info(`用户插件初始化完成,耗时: ${userPluginsInitTime}`);
213
198
  }
214
199
 
215
- const totalLoadTime = (Bun.nanoseconds() - loadStartTime) / 1_000_000;
200
+ const totalLoadTime = calculateElapsedTime(loadStartTime);
216
201
  const totalPluginCount = sortedCorePlugins.length + sortedUserPlugins.length;
217
- Logger.info(`插件加载完成! 总耗时: ${totalLoadTime.toFixed(2)}ms,共加载 ${totalPluginCount} 个插件`);
202
+ Logger.info(`插件加载完成! 总耗时: ${totalLoadTime},共加载 ${totalPluginCount} 个插件`);
218
203
  } catch (error) {
219
204
  Logger.error({
220
205
  msg: '加载插件时发生错误',
@@ -228,10 +213,8 @@ class Befly {
228
213
  const loadStartTime = Bun.nanoseconds();
229
214
  const dirDisplayName = dirName === 'core' ? '核心' : '用户';
230
215
 
231
- const coreApisDir = path.join(dirname2(import.meta.url), 'apis');
232
- const userApisDir = path.join(process.cwd(), 'apis');
233
216
  const glob = new Bun.Glob('**/*.js');
234
- const apiDir = dirName === 'core' ? coreApisDir : userApisDir;
217
+ const apiDir = dirName === 'core' ? __dirapis : getProjectDir('apis');
235
218
 
236
219
  let totalApis = 0;
237
220
  let loadedApis = 0;
@@ -274,22 +257,22 @@ class Befly {
274
257
  api.route = `${api.method.toUpperCase()}/api/${dirName}/${apiPath}`;
275
258
  this.apiRoutes.set(api.route, api);
276
259
 
277
- const singleApiTime = (Bun.nanoseconds() - singleApiStart) / 1_000_000;
260
+ const singleApiTime = calculateElapsedTime(singleApiStart);
278
261
  loadedApis++;
279
- // Logger.info(`${dirDisplayName}接口 ${apiPath} 加载成功,耗时: ${singleApiTime.toFixed(2)}ms`);
262
+ // Logger.info(`${dirDisplayName}接口 ${apiPath} 加载成功,耗时: ${singleApiTime}`);
280
263
  } catch (error) {
281
- const singleApiTime = (Bun.nanoseconds() - singleApiStart) / 1_000_000;
264
+ const singleApiTime = calculateElapsedTime(singleApiStart);
282
265
  failedApis++;
283
266
  Logger.error({
284
- msg: `${dirDisplayName}接口 ${apiPath} 加载失败,耗时: ${singleApiTime.toFixed(2)}ms`,
267
+ msg: `${dirDisplayName}接口 ${apiPath} 加载失败,耗时: ${singleApiTime}`,
285
268
  error: error.message,
286
269
  stack: error.stack
287
270
  });
288
271
  }
289
272
  }
290
273
 
291
- const totalLoadTime = (Bun.nanoseconds() - loadStartTime) / 1_000_000;
292
- Logger.info(`${dirDisplayName}接口加载完成! 总耗时: ${totalLoadTime.toFixed(2)}ms,总数: ${totalApis}, 成功: ${loadedApis}, 失败: ${failedApis}`);
274
+ const totalLoadTime = calculateElapsedTime(loadStartTime);
275
+ Logger.info(`${dirDisplayName}接口加载完成! 总耗时: ${totalLoadTime},总数: ${totalApis}, 成功: ${loadedApis}, 失败: ${failedApis}`);
293
276
  } catch (error) {
294
277
  Logger.error({
295
278
  msg: '加载接口时发生错误',
@@ -311,8 +294,8 @@ class Befly {
311
294
  await this.loadApis('core');
312
295
  await this.loadApis('app');
313
296
 
314
- const totalStartupTime = (Bun.nanoseconds() - serverStartTime) / 1_000_000;
315
- Logger.info(`服务器启动准备完成,总耗时: ${totalStartupTime.toFixed(2)}ms`);
297
+ const totalStartupTime = calculateElapsedTime(serverStartTime);
298
+ Logger.info(`服务器启动准备完成,总耗时: ${totalStartupTime}`);
316
299
 
317
300
  const server = Bun.serve({
318
301
  port: Env.APP_PORT,
@@ -399,7 +382,7 @@ class Befly {
399
382
  } else if (contentType.indexOf('form-data') !== -1) {
400
383
  ctx.body = await req.formData();
401
384
  } else if (contentType.indexOf('x-www-form-urlencoded') !== -1) {
402
- const text = await clonedReq.text();
385
+ const text = await req.text();
403
386
  const formData = new URLSearchParams(text);
404
387
  ctx.body = Object.fromEntries(formData);
405
388
  } else {
@@ -511,7 +494,7 @@ class Befly {
511
494
  }
512
495
 
513
496
  const url = new URL(req.url);
514
- const filePath = path.join(process.cwd(), 'public', url.pathname);
497
+ const filePath = path.join(getProjectDir('public'), url.pathname);
515
498
 
516
499
  try {
517
500
  const file = await Bun.file(filePath);
@@ -545,8 +528,8 @@ class Befly {
545
528
  }
546
529
  });
547
530
 
548
- const finalStartupTime = (Bun.nanoseconds() - serverStartTime) / 1_000_000;
549
- Logger.info(`Befly 服务器启动成功! 完整启动耗时: ${finalStartupTime.toFixed(2)}ms`);
531
+ const finalStartupTime = calculateElapsedTime(serverStartTime);
532
+ Logger.info(`Befly 服务器启动成功! 完整启动耗时: ${finalStartupTime}`);
550
533
  Logger.info(`服务器监听地址: http://${Env.APP_HOST}:${Env.APP_PORT}`);
551
534
 
552
535
  if (callback && typeof callback === 'function') {
@@ -555,4 +538,4 @@ class Befly {
555
538
  }
556
539
  }
557
540
 
558
- export { Befly, Env, Api, Jwt, Crypto2, Logger, RYes, RNo };
541
+ export { Befly, Env, Api, Jwt, Crypto2, Logger, RYes, RNo, SyncDb };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "befly",
3
- "version": "2.0.12",
3
+ "version": "2.1.0",
4
4
  "description": "Buma - 为 Bun 专属打造的 API 接口框架核心引擎",
5
5
  "type": "module",
6
6
  "private": false,
@@ -13,9 +13,14 @@
13
13
  ".": "./main.js"
14
14
  },
15
15
  "scripts": {
16
- "r": "bun publish --registry=https://registry.npmjs.org --access=public",
16
+ "ra": "bun run release.js -a",
17
+ "rb": "bun run release.js -b",
18
+ "rc": "bun run release.js -c",
17
19
  "test": "bun test",
18
- "test:jwt": "bun test tests/jwt.test.js"
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"
19
24
  },
20
25
  "keywords": [
21
26
  "bun",
@@ -36,7 +41,8 @@
36
41
  "config/",
37
42
  "libs/",
38
43
  "plugins/",
39
- "schema/",
44
+ "scripts/",
45
+ "tables/",
40
46
  "utils/",
41
47
  ".gitignore",
42
48
  ".npmignore",
@@ -47,9 +53,23 @@
47
53
  ".prettierrc",
48
54
  "LICENSE",
49
55
  "main.js",
56
+ "system.js",
50
57
  "package.json",
51
58
  "README.md",
59
+ "USEAGE.md",
52
60
  "vitest.config.js"
53
61
  ],
54
- "gitHead": "0c177fe05242f6c798e9f85262ee92343dbc6c46"
62
+ "gitHead": "1dc5f118a723969456559e758e2ba889f4601224",
63
+ "dependencies": {},
64
+ "simple-git-hooks": {
65
+ "pre-commit": "bunx --bun lint-staged"
66
+ },
67
+ "lint-staged": {
68
+ "*.{js,css,scss,less,ts,jsx,vue,html,json,md,yaml}": "bunx --bun prettier --write --cache --ignore-unknown"
69
+ },
70
+ "devDependencies": {
71
+ "lint-staged": "^16.1.5",
72
+ "prettier": "^3.6.2",
73
+ "simple-git-hooks": "^2.13.1"
74
+ }
55
75
  }