befly 2.0.12 → 2.0.14

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.
@@ -0,0 +1,258 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFileSync, writeFileSync } from 'fs';
4
+ import { execSync } from 'child_process';
5
+ import { join } from 'path';
6
+ import { __filename, __dirname } from '../system.js';
7
+
8
+ // 获取 package.json 路径
9
+ const packagePath = join(__dirname, 'package.json');
10
+
11
+ /**
12
+ * 解析命令行参数
13
+ */
14
+ function parseArguments() {
15
+ const args = process.argv.slice(2);
16
+
17
+ if (args.includes('-h') || args.includes('--help')) {
18
+ console.log(`
19
+ 发布脚本使用说明:
20
+ bun run scripts/release.js -a 发布大版本 (major)
21
+ bun run scripts/release.js -b 发布次要版本 (minor)
22
+ bun run scripts/release.js -c 发布补丁版本 (patch)
23
+ bun run scripts/release.js -h 显示帮助信息
24
+
25
+ 或者使用快捷命令:
26
+ bun run ra 发布大版本
27
+ bun run rb 发布次要版本
28
+ bun run rc 发布补丁版本
29
+ `);
30
+ process.exit(0);
31
+ }
32
+
33
+ if (args.includes('-a')) return 'major';
34
+ if (args.includes('-b')) return 'minor';
35
+ if (args.includes('-c')) return 'patch';
36
+
37
+ console.error('错误: 请指定版本类型参数');
38
+ console.log('使用 -h 或 --help 查看帮助信息');
39
+ process.exit(1);
40
+ }
41
+
42
+ /**
43
+ * 读取 package.json
44
+ */
45
+ function readPackageJson() {
46
+ try {
47
+ const content = readFileSync(packagePath, 'utf8');
48
+ return JSON.parse(content);
49
+ } catch (error) {
50
+ console.error('错误: 无法读取 package.json:', error.message);
51
+ process.exit(1);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * 写入 package.json
57
+ */
58
+ function writePackageJson(packageData) {
59
+ try {
60
+ const content = JSON.stringify(packageData, null, 4);
61
+ writeFileSync(packagePath, content, 'utf8');
62
+ console.log('✓ package.json 已更新');
63
+ } catch (error) {
64
+ console.error('错误: 无法写入 package.json:', error.message);
65
+ process.exit(1);
66
+ }
67
+ }
68
+
69
+ /**
70
+ * 更新版本号
71
+ */
72
+ function updateVersion(currentVersion, type) {
73
+ const versionParts = currentVersion.split('.').map(Number);
74
+
75
+ if (versionParts.length !== 3) {
76
+ console.error('错误: 版本号格式不正确,应为 x.y.z 格式');
77
+ process.exit(1);
78
+ }
79
+
80
+ let [major, minor, patch] = versionParts;
81
+
82
+ switch (type) {
83
+ case 'major':
84
+ major += 1;
85
+ minor = 0;
86
+ patch = 0;
87
+ break;
88
+ case 'minor':
89
+ minor += 1;
90
+ patch = 0;
91
+ break;
92
+ case 'patch':
93
+ patch += 1;
94
+ break;
95
+ default:
96
+ console.error('错误: 未知的版本类型');
97
+ process.exit(1);
98
+ }
99
+
100
+ return `${major}.${minor}.${patch}`;
101
+ }
102
+
103
+ /**
104
+ * 执行 Git 命令(必须成功)
105
+ */
106
+ function executeGitCommand(command, description) {
107
+ try {
108
+ console.log(`正在执行: ${description}`);
109
+ console.log(`命令: ${command}`);
110
+
111
+ const result = execSync(command, {
112
+ encoding: 'utf8',
113
+ stdio: 'inherit',
114
+ cwd: __dirname
115
+ });
116
+
117
+ console.log(`✓ ${description} 完成`);
118
+ return result;
119
+ } catch (error) {
120
+ console.error(`错误: ${description} 失败:`, error.message);
121
+ console.error('Git 操作失败,发布已取消!');
122
+ process.exit(1);
123
+ }
124
+ }
125
+
126
+ /**
127
+ * 执行命令(必须成功)
128
+ */
129
+ function executeCommand(command, description) {
130
+ try {
131
+ console.log(`正在执行: ${description}`);
132
+ console.log(`命令: ${command}`);
133
+
134
+ const result = execSync(command, {
135
+ encoding: 'utf8',
136
+ stdio: 'inherit',
137
+ cwd: __dirname
138
+ });
139
+
140
+ console.log(`✓ ${description} 完成`);
141
+ return result;
142
+ } catch (error) {
143
+ console.error(`错误: ${description} 失败:`, error.message);
144
+ process.exit(1);
145
+ }
146
+ }
147
+
148
+ /**
149
+ * 检查 Git 状态
150
+ */
151
+ function checkGitStatus() {
152
+ try {
153
+ const status = execSync('git status --porcelain', {
154
+ encoding: 'utf8',
155
+ cwd: __dirname
156
+ });
157
+
158
+ if (status.trim()) {
159
+ console.error('错误: 工作目录有未提交的更改');
160
+ console.log('未提交的文件:');
161
+ console.log(status);
162
+ console.log('\n请先提交所有更改后再发布!');
163
+ return false;
164
+ }
165
+ return true;
166
+ } catch (error) {
167
+ console.error('错误: 无法检查 Git 状态:', error.message);
168
+ console.error('请确保当前目录是一个有效的 Git 仓库!');
169
+ return false;
170
+ }
171
+ }
172
+
173
+ /**
174
+ * 检查必要文件是否存在
175
+ */
176
+ function checkRequiredFiles() {
177
+ const requiredFiles = ['main.js', 'system.js', 'package.json', 'README.md', 'LICENSE'];
178
+
179
+ const missingFiles = [];
180
+
181
+ for (const file of requiredFiles) {
182
+ try {
183
+ const filePath = join(__dirname, file);
184
+ readFileSync(filePath);
185
+ } catch (error) {
186
+ missingFiles.push(file);
187
+ }
188
+ }
189
+
190
+ if (missingFiles.length > 0) {
191
+ console.error('错误: 以下必要文件缺失:');
192
+ missingFiles.forEach((file) => console.error(` - ${file}`));
193
+ return false;
194
+ }
195
+
196
+ console.log('✓ 所有必要文件检查通过');
197
+ return true;
198
+ }
199
+
200
+ /**
201
+ * 主函数
202
+ */
203
+ function main() {
204
+ // 解析参数(如果是帮助命令会直接退出)
205
+ const versionType = parseArguments();
206
+
207
+ console.log('🚀 开始发布流程...\n');
208
+ console.log(`版本类型: ${versionType}`);
209
+
210
+ // 检查必要文件
211
+ console.log('\n--- 检查必要文件 ---');
212
+ if (!checkRequiredFiles()) {
213
+ console.log('\n发布已取消');
214
+ process.exit(1);
215
+ }
216
+
217
+ // 检查 Git 状态
218
+ console.log('\n--- 检查 Git 状态 ---');
219
+ if (!checkGitStatus()) {
220
+ console.log('\n发布已取消');
221
+ process.exit(1);
222
+ }
223
+
224
+ // 读取当前版本
225
+ const packageData = readPackageJson();
226
+ const currentVersion = packageData.version;
227
+ console.log(`当前版本: ${currentVersion}`);
228
+
229
+ // 计算新版本
230
+ const newVersion = updateVersion(currentVersion, versionType);
231
+ console.log(`新版本: ${newVersion}\n`);
232
+
233
+ // 更新版本号
234
+ packageData.version = newVersion;
235
+ writePackageJson(packageData);
236
+
237
+ // 提交版本更新
238
+ console.log('\n--- Git 操作 ---');
239
+ executeGitCommand('git add package.json', '添加 package.json 到 Git');
240
+ executeGitCommand(`git commit -m "chore: bump version to ${newVersion}"`, '提交版本更新');
241
+ executeGitCommand(`git tag v${newVersion}`, '创建版本标签');
242
+
243
+ // 发布到 npm
244
+ console.log('\n--- NPM 发布 ---');
245
+ executeCommand('bun publish --registry=https://registry.npmjs.org --access=public', '发布到 npm');
246
+
247
+ // 推送到远程仓库
248
+ console.log('\n--- 推送到远程仓库 ---');
249
+ executeGitCommand('git push', '推送代码到远程仓库');
250
+ executeGitCommand('git push --tags', '推送标签到远程仓库');
251
+
252
+ console.log(`\n🎉 版本 ${newVersion} 发布成功!`);
253
+ console.log(`📦 包名: ${packageData.name}`);
254
+ console.log(`🔗 npm: https://www.npmjs.com/package/${packageData.name}`);
255
+ }
256
+
257
+ // 启动主函数
258
+ main();
package/system.js ADDED
@@ -0,0 +1,118 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import { dirname, join, resolve, relative } from 'node:path';
3
+
4
+ /**
5
+ * Befly 框架系统路径定义
6
+ * 提供统一的路径变量,供整个框架使用
7
+ */
8
+
9
+ // 当前文件的路径信息
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+
13
+ // Befly 框架根目录
14
+ const __dirroot = __dirname;
15
+
16
+ // 各个重要目录的路径
17
+ const __dirscript = join(__dirroot, 'scripts');
18
+ const __dirbin = join(__dirroot, 'bin');
19
+ const __dirutils = join(__dirroot, 'utils');
20
+ const __dirconfig = join(__dirroot, 'config');
21
+ const __dirtables = join(__dirroot, 'tables');
22
+ const __dirchecks = join(__dirroot, 'checks');
23
+ const __dirapis = join(__dirroot, 'apis');
24
+ const __dirplugins = join(__dirroot, 'plugins');
25
+ const __dirlibs = join(__dirroot, 'libs');
26
+ const __dirtests = join(__dirroot, 'tests');
27
+
28
+ // 获取项目根目录(befly 框架的使用方项目)
29
+ const getProjectRoot = () => {
30
+ return process.cwd();
31
+ };
32
+
33
+ // 获取项目中的特定目录
34
+ const getProjectDir = (subdir = '') => {
35
+ return subdir ? join(getProjectRoot(), subdir) : getProjectRoot();
36
+ };
37
+
38
+ // 创建路径解析器,基于 befly 根目录
39
+ const resolveBeflyPath = (...paths) => {
40
+ return resolve(__dirroot, ...paths);
41
+ };
42
+
43
+ // 创建路径解析器,基于项目根目录
44
+ const resolveProjectPath = (...paths) => {
45
+ return resolve(getProjectRoot(), ...paths);
46
+ };
47
+
48
+ // 获取相对于 befly 根目录的相对路径
49
+ const getRelativeBeflyPath = (targetPath) => {
50
+ return relative(__dirroot, targetPath);
51
+ };
52
+
53
+ // 获取相对于项目根目录的相对路径
54
+ const getRelativeProjectPath = (targetPath) => {
55
+ return relative(getProjectRoot(), targetPath);
56
+ };
57
+
58
+ // 导出所有路径变量和工具函数
59
+ export {
60
+ // 基础路径变量
61
+ __filename,
62
+ __dirname,
63
+ __dirroot,
64
+
65
+ // Befly 框架目录
66
+ __dirscript,
67
+ __dirbin,
68
+ __dirutils,
69
+ __dirconfig,
70
+ __dirtables,
71
+ __dirchecks,
72
+ __dirapis,
73
+ __dirplugins,
74
+ __dirlibs,
75
+ __dirtests,
76
+
77
+ // 项目路径工具函数
78
+ getProjectRoot,
79
+ getProjectDir,
80
+
81
+ // 路径解析工具函数
82
+ resolveBeflyPath,
83
+ resolveProjectPath,
84
+ getRelativeBeflyPath,
85
+ getRelativeProjectPath
86
+ };
87
+
88
+ // 默认导出包含所有路径信息的对象
89
+ export default {
90
+ // 基础路径变量
91
+ __filename,
92
+ __dirname,
93
+ __dirroot,
94
+
95
+ // Befly 框架目录
96
+ paths: {
97
+ script: __dirscript,
98
+ bin: __dirbin,
99
+ utils: __dirutils,
100
+ config: __dirconfig,
101
+ tables: __dirtables,
102
+ checks: __dirchecks,
103
+ apis: __dirapis,
104
+ plugins: __dirplugins,
105
+ libs: __dirlibs,
106
+ tests: __dirtests
107
+ },
108
+
109
+ // 工具函数
110
+ utils: {
111
+ getProjectRoot,
112
+ getProjectDir,
113
+ resolveBeflyPath,
114
+ resolveProjectPath,
115
+ getRelativeBeflyPath,
116
+ getRelativeProjectPath
117
+ }
118
+ };
@@ -0,0 +1,16 @@
1
+ {
2
+ "email": "邮箱|string|5|100|null|1|^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
3
+ "phone": "手机号|string|11|11|null|1|^1[3-9]\\d{9}$",
4
+ "page": "页码|number|1|9999|1|0|null",
5
+ "limit": "每页数量|number|1|100|10|0|null",
6
+ "title": "标题|string|1|200|null|0|null",
7
+ "description": "描述|string|0|500|null|0|null",
8
+ "keyword": "关键词|string|1|50|null|1|null",
9
+ "status": "状态|string|1|20|active|1|null",
10
+ "enabled": "启用状态|number|0|1|1|0|null",
11
+ "date": "日期|string|10|10|null|0|^\\d{4}-\\d{2}-\\d{2}$",
12
+ "datetime": "日期时间|string|19|25|null|0|^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}",
13
+ "filename": "文件名|string|1|255|null|0|null",
14
+ "url": "网址|string|5|500|null|0|^https?://",
15
+ "tag": "标签|array|0|10|[]|0|null"
16
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "filename": "文件名|string|1|255|null|1|null",
3
+ "content": "内容|string|0|1000000|null|0|null",
4
+ "type": "类型|string|0|50|file|1|null",
5
+ "path": "路径|string|1|500|null|0|null"
6
+ }
package/utils/util.js CHANGED
@@ -191,3 +191,28 @@ export const filterLogFields = (body, excludeFields = '') => {
191
191
  }
192
192
  return filtered;
193
193
  };
194
+
195
+ // 专门用于处理管道符分隔的字段规则
196
+ export const parseFieldRule = (rule) => {
197
+ const allParts = rule.split('|');
198
+
199
+ // 现在支持7个部分:显示名|类型|最小值|最大值|默认值|是否索引|正则约束
200
+ if (allParts.length <= 7) {
201
+ // 如果少于7个部分,补齐缺失的部分为 null
202
+ while (allParts.length < 7) {
203
+ allParts.push('null');
204
+ }
205
+ return allParts;
206
+ }
207
+
208
+ // 如果超过7个部分,保留前6个,剩余的合并为最后的正则约束部分
209
+ return [
210
+ allParts[0], // 显示名
211
+ allParts[1], // 类型
212
+ allParts[2], // 最小值
213
+ allParts[3], // 最大值
214
+ allParts[4], // 默认值
215
+ allParts[5], // 是否索引
216
+ allParts.slice(6).join('|') // 正则约束(可能包含管道符)
217
+ ];
218
+ };
package/utils/validate.js CHANGED
@@ -1,4 +1,29 @@
1
- import { ruleSplit, isType } from './util.js';
1
+ import { isType } from './util.js';
2
+
3
+ // 专门用于处理管道符分隔的字段规则
4
+ const parseFieldRule = (rule) => {
5
+ const allParts = rule.split('|');
6
+
7
+ // 现在支持7个部分:显示名|类型|最小值|最大值|默认值|是否索引|正则约束
8
+ if (allParts.length <= 7) {
9
+ // 如果少于7个部分,补齐缺失的部分为 null
10
+ while (allParts.length < 7) {
11
+ allParts.push('null');
12
+ }
13
+ return allParts;
14
+ }
15
+
16
+ // 如果超过7个部分,保留前6个,剩余的合并为最后的正则约束部分
17
+ return [
18
+ allParts[0], // 显示名
19
+ allParts[1], // 类型
20
+ allParts[2], // 最小值
21
+ allParts[3], // 最大值
22
+ allParts[4], // 默认值
23
+ allParts[5], // 是否索引
24
+ allParts.slice(6).join('|') // 正则约束(可能包含管道符)
25
+ ];
26
+ };
2
27
 
3
28
  /**
4
29
  * 验证器类
@@ -63,7 +88,7 @@ export class Validator {
63
88
  for (const fieldName of required) {
64
89
  if (!(fieldName in data) || data[fieldName] === undefined || data[fieldName] === null || data[fieldName] === '') {
65
90
  result.code = 1;
66
- const ruleParts = rules[fieldName]?.split(',') || [];
91
+ const ruleParts = parseFieldRule(rules[fieldName] || '');
67
92
  const fieldLabel = ruleParts[0] || fieldName;
68
93
  result.fields[fieldName] = `${fieldLabel}(${fieldName})为必填项`;
69
94
  }
@@ -99,16 +124,18 @@ export class Validator {
99
124
  * 验证单个字段的值
100
125
  */
101
126
  validateFieldValue(value, rule, fieldName) {
102
- const [name, type, minStr, maxStr, specStr] = ruleSplit(rule);
127
+ const [name, type, minStr, maxStr, defaultValue, isIndexStr, regexConstraint] = parseFieldRule(rule);
103
128
  const min = minStr === 'null' ? null : parseInt(minStr) || 0;
104
129
  const max = maxStr === 'null' ? null : parseInt(maxStr) || 0;
105
- const spec = specStr === 'null' ? null : specStr.trim();
130
+ const spec = regexConstraint === 'null' ? null : regexConstraint.trim();
106
131
 
107
132
  switch (type.toLowerCase()) {
108
133
  case 'number':
109
134
  return this.validateNumber(value, name, min, max, spec, fieldName);
110
135
  case 'string':
111
136
  return this.validateString(value, name, min, max, spec, fieldName);
137
+ case 'text':
138
+ return this.validateString(value, name, min, max, spec, fieldName);
112
139
  case 'array':
113
140
  return this.validateArray(value, name, min, max, spec, fieldName);
114
141
  default:
@@ -129,7 +156,7 @@ export class Validator {
129
156
  return `${name}(${fieldName})不能小于${min}`;
130
157
  }
131
158
 
132
- if (min !== null && max > 0 && value > max) {
159
+ if (max !== null && max > 0 && value > max) {
133
160
  return `${name}(${fieldName})不能大于${max}`;
134
161
  }
135
162
 
@@ -1,17 +0,0 @@
1
- {
2
- "id": "ID,number,1,999999999,x%2=0",
3
- "email": "邮箱,string,5,100,^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
4
- "phone": "手机号,string,11,11,^1[3-9]\\d{9}$",
5
- "page": "页码,number,1,9999,null",
6
- "limit": "每页数量,number,1,100,null",
7
- "title": "标题,string,1,200,null",
8
- "description": "描述,string,0,500,null",
9
- "keyword": "关键词,string,1,50,null",
10
- "status": "状态,string,1,20,null",
11
- "enabled": "启用状态,number,0,1,null",
12
- "date": "日期,string,10,10,^\\d{4}-\\d{2}-\\d{2}$",
13
- "datetime": "日期时间,string,19,25,^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}",
14
- "filename": "文件名,string,1,255,null",
15
- "url": "网址,string,5,500,^https?://",
16
- "tag": "标签,array,0,10,null"
17
- }
package/schema/debug.json DELETED
@@ -1 +0,0 @@
1
- {}
@@ -1 +0,0 @@
1
- {}
package/schema/tool.json DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "filename": "文件名,string,1,255,null",
3
- "content": "内容,string,0,1000000,null",
4
- "type": "类型,string,0,50,null",
5
- "path": "路径,string,1,500,null"
6
- }