befly 3.9.14 → 3.9.23
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/checks/checkTable.ts +18 -0
- package/docs/1-/345/237/272/346/234/254/344/273/213/347/273/215.md +35 -0
- package/docs/2-/345/210/235/346/255/245/344/275/223/351/252/214.md +64 -0
- package/docs/3-/347/254/254/344/270/200/344/270/252/346/216/245/345/217/243.md +46 -0
- package/docs/4-/346/223/215/344/275/234/346/225/260/346/215/256/345/272/223.md +172 -0
- package/docs/README.md +2 -2
- package/docs/addon.md +4 -4
- package/docs/api.md +4 -4
- package/docs/config.md +1 -1
- package/docs/examples.md +14 -14
- package/docs/hook.md +9 -9
- package/docs/plugin.md +12 -12
- package/docs/quickstart.md +2 -2
- package/lib/dbHelper.ts +2 -2
- package/package.json +2 -2
- package/sync/syncDb/table.ts +2 -1
- package/types/database.d.ts +1 -1
package/checks/checkTable.ts
CHANGED
|
@@ -37,6 +37,11 @@ const RESERVED_FIELDS = ['id', 'created_at', 'updated_at', 'deleted_at', 'state'
|
|
|
37
37
|
*/
|
|
38
38
|
const FIELD_TYPES = ['string', 'number', 'text', 'array_string', 'array_text'] as const;
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* 允许的字段属性列表
|
|
42
|
+
*/
|
|
43
|
+
const ALLOWED_FIELD_PROPERTIES = ['name', 'type', 'min', 'max', 'default', 'detail', 'index', 'unique', 'nullable', 'unsigned', 'regexp'] as const;
|
|
44
|
+
|
|
40
45
|
/**
|
|
41
46
|
* 小驼峰命名正则
|
|
42
47
|
* 可选:以下划线开头(用于特殊文件,如通用字段定义)
|
|
@@ -133,6 +138,14 @@ export async function checkTable(): Promise<void> {
|
|
|
133
138
|
// 直接使用字段对象
|
|
134
139
|
const field = fieldDef as FieldDefinition;
|
|
135
140
|
|
|
141
|
+
// 检查是否存在非法属性
|
|
142
|
+
const fieldKeys = Object.keys(field);
|
|
143
|
+
const illegalProps = fieldKeys.filter((key) => !ALLOWED_FIELD_PROPERTIES.includes(key as any));
|
|
144
|
+
if (illegalProps.length > 0) {
|
|
145
|
+
Logger.warn(`${item.typeName}表 ${fileName} 文件 ${colKey} 包含非法属性: ${illegalProps.join(', ')},` + `允许的属性为: ${ALLOWED_FIELD_PROPERTIES.join(', ')}`);
|
|
146
|
+
hasError = true;
|
|
147
|
+
}
|
|
148
|
+
|
|
136
149
|
// 检查必填字段:name, type
|
|
137
150
|
if (!field.name || typeof field.name !== 'string') {
|
|
138
151
|
Logger.warn(`${item.typeName}表 ${fileName} 文件 ${colKey} 缺少必填字段 name 或类型错误`);
|
|
@@ -193,6 +206,11 @@ export async function checkTable(): Promise<void> {
|
|
|
193
206
|
hasError = true;
|
|
194
207
|
}
|
|
195
208
|
|
|
209
|
+
// 检查 unique 和 index 冲突(警告但不阻断)
|
|
210
|
+
if (field.unique && field.index) {
|
|
211
|
+
Logger.warn(`${item.typeName}表 ${fileName} 文件 ${colKey} 同时设置了 unique=true 和 index=true,` + `unique 约束会自动创建唯一索引,index=true 将被忽略以避免重复索引`);
|
|
212
|
+
}
|
|
213
|
+
|
|
196
214
|
// 约束:当最小值与最大值均为数字时,要求最小值 <= 最大值
|
|
197
215
|
if (fieldMin !== undefined && fieldMax !== undefined && fieldMin !== null && fieldMax !== null) {
|
|
198
216
|
if (fieldMin > fieldMax) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Befly - 野蜂飞舞
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Befly 是专为 Bun 运行时设计的快速开发 API 框架,并配套一个完整的后台管理系统。
|
|
6
|
+
|
|
7
|
+
## 🎯 特性
|
|
8
|
+
|
|
9
|
+
- ⚡ **原生 TypeScript 支持** - 完整的类型定义和智能提示
|
|
10
|
+
- 🚀 **高性能** - 基于 Bun 运行时,超快的启动和执行速度
|
|
11
|
+
- 🔌 **插件化架构** - 灵活的插件系统,轻松扩展功能
|
|
12
|
+
- 🗄️ **多数据库支持** - MySQL、PostgreSQL、SQLite 统一接口
|
|
13
|
+
- 📝 **自动化表管理** - 基于 JSON 的表定义,自动同步数据库结构
|
|
14
|
+
- 🔐 **内置身份验证** - JWT 认证,角色权限管理
|
|
15
|
+
- 📊 **完整日志系统** - 结构化日志,敏感字段过滤
|
|
16
|
+
|
|
17
|
+
## 📦 限制
|
|
18
|
+
|
|
19
|
+
- 为单机部署,单数据库,单缓存,小系统,小项目而设计。
|
|
20
|
+
- 大型项目,多数据库,复杂系统请勿用本项目。
|
|
21
|
+
|
|
22
|
+
## 🤝 贡献
|
|
23
|
+
|
|
24
|
+
- [github👉https://github.com/chenbimo/befly](https://github.com/chenbimo/befly)
|
|
25
|
+
- [gitee👉https://gitee.com/chenbimo/befly](https://gitee.com/chenbimo/befly)
|
|
26
|
+
|
|
27
|
+
欢迎提交 Issue 和 Pull Request!
|
|
28
|
+
|
|
29
|
+
## 📄 许可
|
|
30
|
+
|
|
31
|
+
MIT License
|
|
32
|
+
|
|
33
|
+
## 🌟 致谢
|
|
34
|
+
|
|
35
|
+
感谢所有为 Befly 做出贡献的开发者!
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
> 注意:befly 开发后端服务统一使用`.ts`文件和`TypeScript`写法。
|
|
2
|
+
|
|
3
|
+
由于 Befly 只支持 `Bun` 环境,所以我们可以在一个空目录下,用 `bun init` 命令创建一个新项目。
|
|
4
|
+
|
|
5
|
+
创建的初始项目结构如下:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
befly-demo/
|
|
9
|
+
├── node_modules
|
|
10
|
+
├── bun.lock
|
|
11
|
+
├── index.ts
|
|
12
|
+
├── package.json
|
|
13
|
+
└── tsconfig.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
下一步,使用 `bun add befly` 安装 `befly` 依赖。
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"name": "befly-demo",
|
|
21
|
+
"module": "index.ts",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"private": true,
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/bun": "latest"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"typescript": "^5.9.3"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"befly": "^3.8.14"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
接下来,在 `index.ts` 文件中,导入 `befly` 并运行。
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
import { Befly } from 'befly';
|
|
40
|
+
|
|
41
|
+
const app = new Befly();
|
|
42
|
+
await app.listen();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
最后,在终端执行 `bun run index.ts`,运行后端服务。
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
D:\codes\_test\t10>bun run main.ts
|
|
49
|
+
[2025-11-19 20:08:31] WARN - 数据库未启用,跳过初始化
|
|
50
|
+
[2025-11-19 20:08:31] WARN - Redis 未启用,跳过初始化
|
|
51
|
+
[2025-11-19 20:08:31] INFO - 野蜂飞舞开发环境 启动成功!
|
|
52
|
+
[2025-11-19 20:08:31] INFO - 服务器启动耗时: 2.06 毫秒
|
|
53
|
+
[2025-11-19 20:08:31] INFO - 服务器监听地址: http://127.0.0.1:3000
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`befly` 默认监听 `3000` 端口,如果显示以上信息,则表示接口服务启动了。
|
|
57
|
+
|
|
58
|
+
服务启动后,在浏览器访问 `http://127.0.0.1:3000`,将会看到如下信息。
|
|
59
|
+
|
|
60
|
+

|
|
61
|
+
|
|
62
|
+
由于 `数据库` 和 `Redis` 默认为关闭状态,所以此时的服务是纯接口服务,可以用来写一些不需要数据库,不需要缓存的接口功能。
|
|
63
|
+
|
|
64
|
+
后续文章,我们将会详细了解到`接口开发`、`数据定义`、`增删改查` 等等。
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
`befly` 采用的是 `约定大于配置` 的思路,所有项目相关的接口都要按照约定放在 `apis` 目录下。
|
|
2
|
+
|
|
3
|
+
接下来我们实现一个简单的 `复读机` 接口 `apis/echo.ts`,文件结构如下:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
befly-demo/
|
|
7
|
+
├── apis
|
|
8
|
+
│ ├── echo.ts # 复读机接口
|
|
9
|
+
├── node_modules
|
|
10
|
+
├── bun.lock
|
|
11
|
+
├── index.ts
|
|
12
|
+
├── package.json
|
|
13
|
+
└── tsconfig.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
接口文件的写法如下:
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { Yes } from 'befly';
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
name: '复读机接口',
|
|
23
|
+
method: 'get',
|
|
24
|
+
auth: false,
|
|
25
|
+
fields: {
|
|
26
|
+
words: {
|
|
27
|
+
name: '文字内容',
|
|
28
|
+
type: 'string',
|
|
29
|
+
min: 0,
|
|
30
|
+
max: 999
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
handler: async (befly, ctx) => {
|
|
34
|
+
return Yes(ctx.body.words, {
|
|
35
|
+
timestamp: Date.now(),
|
|
36
|
+
message: '欢迎使用 Befly 框架'
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
访问:`http://127.0.0.1:3001/api/echo?words=我是复读机`,将会看到如下内容:
|
|
43
|
+
|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
这就是接口的定义和写法。
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
要操作数据,需要在项目中创建一个`env.ts` 或 `env.js` 文件,示例如下:
|
|
2
|
+
|
|
3
|
+
```js
|
|
4
|
+
import type { EnvConfig } from './types/env.js';
|
|
5
|
+
|
|
6
|
+
export const Env: Partial<EnvConfig> = {
|
|
7
|
+
// 启用数据库
|
|
8
|
+
DATABASE_ENABLE: 1,
|
|
9
|
+
// 数据库配置
|
|
10
|
+
DB_TYPE: 'mysql',
|
|
11
|
+
DB_HOST: '127.0.0.1',
|
|
12
|
+
DB_PORT: 3306,
|
|
13
|
+
DB_USER: 'root',
|
|
14
|
+
DB_PASS: 'root',
|
|
15
|
+
DB_NAME: 'befly_demo',
|
|
16
|
+
// Redis 配置
|
|
17
|
+
REDIS_HOST: '127.0.0.1',
|
|
18
|
+
REDIS_PORT: 6379,
|
|
19
|
+
REDIS_USERNAME: '',
|
|
20
|
+
REDIS_PASSWORD: '',
|
|
21
|
+
REDIS_DB: 0,
|
|
22
|
+
REDIS_KEY_PREFIX: 'befly_demo'
|
|
23
|
+
};
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
需要注意的是,数据库配置和 Redis 缓存配置都要设置,不能只设置一个,`DATABASE_ENABLE` 设置为 `1` 后,将会开启数据库功能,如果配置错误则会报错,配置正确再次运行 `bun run main.ts` 则会显示如下信息:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
D:\codes\_test\t10>bun run index.ts
|
|
30
|
+
[2025-11-19 20:33:09] INFO - 野蜂飞舞开发环境 服务器启动成功!
|
|
31
|
+
[2025-11-19 20:33:09] INFO - 服务器启动耗时: 2.04 毫秒
|
|
32
|
+
[2025-11-19 20:33:09] INFO - 服务器监听地址: http://127.0.0.1:3000
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
可以看到,没有 `数据库未启用,跳过初始化` 和 `Redis 未启用,跳过初始化` 的提示信息了。
|
|
36
|
+
|
|
37
|
+
正确配置和连接数据库后,下一步就是设计`数据库表结构了`,同样也是 `约定大于配置` 的思路,`数据库字段` 全部在 根目录下的 `tables` 目录下创建和定义。
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
befly-demo/
|
|
41
|
+
├── apis
|
|
42
|
+
│ ├── echo.ts # 复读机接口
|
|
43
|
+
│ └── save.ts # 保存接口
|
|
44
|
+
├── tables
|
|
45
|
+
│ └── info.json # 信息表
|
|
46
|
+
├── node_modules
|
|
47
|
+
├── bun.lock
|
|
48
|
+
├── index.ts
|
|
49
|
+
├── package.json
|
|
50
|
+
└── tsconfig.json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
如上,在 `tables` 目录下创建了一个 `info.json` 表,定义如下:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"name": {
|
|
58
|
+
"name": "姓名",
|
|
59
|
+
"type": "string",
|
|
60
|
+
"min": 2,
|
|
61
|
+
"max": 50
|
|
62
|
+
},
|
|
63
|
+
"code": {
|
|
64
|
+
"name": "年龄",
|
|
65
|
+
"type": "number",
|
|
66
|
+
"min": 0,
|
|
67
|
+
"max": 120
|
|
68
|
+
},
|
|
69
|
+
"value": {
|
|
70
|
+
"name": "身高",
|
|
71
|
+
"type": "number",
|
|
72
|
+
"min": 0,
|
|
73
|
+
"max": 300
|
|
74
|
+
},
|
|
75
|
+
"sort": {
|
|
76
|
+
"name": "体重",
|
|
77
|
+
"type": "number",
|
|
78
|
+
"min": 0,
|
|
79
|
+
"max": 9999
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`befly` 的表结构定义全部在文件中定义即可,那么要同步到数据库中,需要用到 `befly-cli` 依赖,使用 `bun add befly-cli` 安装即可。
|
|
85
|
+
|
|
86
|
+
安装完毕后,执行 `bunx befly sync` 命令,同步数据库字段到真实数据库中,终端显示的内容如下:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
D:\codes\_test\t10>bunx befly sync
|
|
90
|
+
========================================
|
|
91
|
+
开始执行完整同步流程
|
|
92
|
+
当前环境: development
|
|
93
|
+
项目名称: 野蜂飞舞开发环境
|
|
94
|
+
数据库地址: 127.0.0.1
|
|
95
|
+
数据库名称: befly_demo
|
|
96
|
+
========================================
|
|
97
|
+
|
|
98
|
+
🔍 正在检查项目结构...
|
|
99
|
+
✓ 项目结构检查完成
|
|
100
|
+
|
|
101
|
+
开始执行同步任务...
|
|
102
|
+
|
|
103
|
+
📦 正在同步数据库...
|
|
104
|
+
MySQL 版本: 8.0.31
|
|
105
|
+
🧹 清理 1 个表的字段缓存...
|
|
106
|
+
✓ 已清理表字段缓存
|
|
107
|
+
✓ 数据库同步完成
|
|
108
|
+
|
|
109
|
+
🔌 正在同步接口...
|
|
110
|
+
表 addon_admin_api 不存在,跳过 API 同步(需要安装 addon-admin 组件)
|
|
111
|
+
✓ 接口同步完成
|
|
112
|
+
|
|
113
|
+
📋 正在同步菜单...
|
|
114
|
+
表 addon_admin_menu 不存在,跳过菜单同步(需要安装 addon-admin 组件)
|
|
115
|
+
✓ 菜单同步完成
|
|
116
|
+
|
|
117
|
+
👤 正在同步开发账号...
|
|
118
|
+
✓ 开发账号同步完成
|
|
119
|
+
|
|
120
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
121
|
+
✅ 同步完成!总耗时: 0.08 秒
|
|
122
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
同步完毕后,使用数据库工具查看,我这里使用的是 `HeidiSQL`,如下图。
|
|
126
|
+
|
|
127
|
+

|
|
128
|
+
|
|
129
|
+
需要注意,改动数据库定义后,都要执行 `bunx befly sync` 命令同步到实际数据库结构中才会生效。
|
|
130
|
+
|
|
131
|
+
数据库同步完毕,下一步就是写保存信息接口 `apis/save.ts`,接收从客户端传入的参数,并保存到数据库中,如下:
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
import { Yes } from 'befly';
|
|
135
|
+
import infoTable from '../tables/info.json';
|
|
136
|
+
|
|
137
|
+
export default {
|
|
138
|
+
name: '保存信息接口',
|
|
139
|
+
method: 'get',
|
|
140
|
+
auth: false,
|
|
141
|
+
fields: infoTable,
|
|
142
|
+
handler: async (befly, ctx) => {
|
|
143
|
+
const res = await befly.db.insData({
|
|
144
|
+
table: 'info',
|
|
145
|
+
data: {
|
|
146
|
+
name: ctx.body.name,
|
|
147
|
+
age: ctx.body.age,
|
|
148
|
+
height: ctx.body.height,
|
|
149
|
+
weight: ctx.body.weight
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
return Yes('信息保存成功', {
|
|
153
|
+
id: 17635656770001
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
在浏览器访问 `http://127.0.0.1:3000/api/save?name=张三&age=18&height=160&weight=70`,返回内容如下图。
|
|
160
|
+
|
|
161
|
+

|
|
162
|
+
|
|
163
|
+
同时呢,查看数据库的 `info` 表数据库,如下图,可以看到数据已经正确保存到了数据库中。
|
|
164
|
+
|
|
165
|
+

|
|
166
|
+
|
|
167
|
+
这就是使用`Befly`框架来写接口,操作数据库的基本流程,简单来说其实只有 2 个主要步骤。
|
|
168
|
+
|
|
169
|
+
1. 定义数据库表,同步表结构。
|
|
170
|
+
2. 写增删改查接口,操作数据库。
|
|
171
|
+
|
|
172
|
+
这就是 `Belfy` 的极简主义,没有那么多花里胡哨的概念,当然更多使用和配置细节,将在后续文章一一说明。
|
package/docs/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Befly Core 文档
|
|
1
|
+
# Befly Core 文档
|
|
2
2
|
|
|
3
3
|
> Befly 是基于 Bun 的高性能 API 框架
|
|
4
4
|
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
## 常用链接
|
|
76
76
|
|
|
77
77
|
- [GitHub](https://github.com/chenbimo/befly)
|
|
78
|
-
- [npm](https://www.npmjs.com/package/befly
|
|
78
|
+
- [npm](https://www.npmjs.com/package/befly)
|
|
79
79
|
|
|
80
80
|
## 版本信息
|
|
81
81
|
|
package/docs/addon.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Addon 插件包开发
|
|
1
|
+
# Addon 插件包开发
|
|
2
2
|
|
|
3
3
|
> 可复用的功能模块,包含 API、表、插件、视图
|
|
4
4
|
|
|
@@ -127,7 +127,7 @@ bun init
|
|
|
127
127
|
`apis/hello/world.ts`:
|
|
128
128
|
|
|
129
129
|
```typescript
|
|
130
|
-
import type { ApiRoute } from 'befly
|
|
130
|
+
import type { ApiRoute } from 'befly/types/api.js';
|
|
131
131
|
|
|
132
132
|
export default {
|
|
133
133
|
name: 'Hello World',
|
|
@@ -267,7 +267,7 @@ apis/
|
|
|
267
267
|
### API 定义示例
|
|
268
268
|
|
|
269
269
|
```typescript
|
|
270
|
-
import type { ApiRoute } from 'befly
|
|
270
|
+
import type { ApiRoute } from 'befly/types/api.js';
|
|
271
271
|
|
|
272
272
|
export default {
|
|
273
273
|
name: '管理员登录',
|
|
@@ -339,7 +339,7 @@ await befly.db.getList({
|
|
|
339
339
|
`plugins/email.ts`:
|
|
340
340
|
|
|
341
341
|
```typescript
|
|
342
|
-
import type { Plugin } from 'befly
|
|
342
|
+
import type { Plugin } from 'befly/types/plugin.js';
|
|
343
343
|
|
|
344
344
|
export interface EmailConfig {
|
|
345
345
|
host: string;
|
package/docs/api.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Befly API 接口文档
|
|
1
|
+
# Befly API 接口文档
|
|
2
2
|
|
|
3
3
|
> 本文档详细介绍 Befly 框架的 API 接口开发规范,包括路由定义、参数验证、权限控制、请求处理流程等。
|
|
4
4
|
|
|
@@ -123,7 +123,7 @@ addonAdmin/apis/
|
|
|
123
123
|
### 基础结构
|
|
124
124
|
|
|
125
125
|
```typescript
|
|
126
|
-
import type { ApiRoute } from 'befly
|
|
126
|
+
import type { ApiRoute } from 'befly/types/api';
|
|
127
127
|
|
|
128
128
|
export default {
|
|
129
129
|
// 必填字段
|
|
@@ -294,7 +294,7 @@ befly.tool.No(msg: string, data?: any, other?: Record<string, any>)
|
|
|
294
294
|
在 Hook 中使用,用于提前拦截请求:
|
|
295
295
|
|
|
296
296
|
```typescript
|
|
297
|
-
import { ErrorResponse } from 'befly
|
|
297
|
+
import { ErrorResponse } from 'befly/util';
|
|
298
298
|
|
|
299
299
|
// 在 Hook 中使用
|
|
300
300
|
ctx.response = ErrorResponse(ctx, '未授权', 1, null);
|
|
@@ -1208,7 +1208,7 @@ handler: async (befly, ctx) => {
|
|
|
1208
1208
|
|
|
1209
1209
|
```typescript
|
|
1210
1210
|
// tpl/hooks/requestLog.ts
|
|
1211
|
-
import type { Hook } from 'befly
|
|
1211
|
+
import type { Hook } from 'befly/types/hook';
|
|
1212
1212
|
|
|
1213
1213
|
const hook: Hook = {
|
|
1214
1214
|
order: 100, // 执行顺序
|
package/docs/config.md
CHANGED
package/docs/examples.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 实战示例
|
|
1
|
+
# 实战示例
|
|
2
2
|
|
|
3
3
|
> 完整的 CRUD 模块开发示例
|
|
4
4
|
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
`apis/user/register.ts`:
|
|
41
41
|
|
|
42
42
|
```typescript
|
|
43
|
-
import type { ApiRoute } from 'befly
|
|
43
|
+
import type { ApiRoute } from 'befly/types';
|
|
44
44
|
|
|
45
45
|
export default {
|
|
46
46
|
name: '用户注册',
|
|
@@ -87,7 +87,7 @@ export default {
|
|
|
87
87
|
`apis/user/login.ts`:
|
|
88
88
|
|
|
89
89
|
```typescript
|
|
90
|
-
import type { ApiRoute } from 'befly
|
|
90
|
+
import type { ApiRoute } from 'befly/types';
|
|
91
91
|
|
|
92
92
|
export default {
|
|
93
93
|
name: '用户登录',
|
|
@@ -155,7 +155,7 @@ export default {
|
|
|
155
155
|
`apis/user/info.ts`:
|
|
156
156
|
|
|
157
157
|
```typescript
|
|
158
|
-
import type { ApiRoute } from 'befly
|
|
158
|
+
import type { ApiRoute } from 'befly/types';
|
|
159
159
|
|
|
160
160
|
export default {
|
|
161
161
|
name: '获取用户信息',
|
|
@@ -182,7 +182,7 @@ export default {
|
|
|
182
182
|
`apis/user/update.ts`:
|
|
183
183
|
|
|
184
184
|
```typescript
|
|
185
|
-
import type { ApiRoute } from 'befly
|
|
185
|
+
import type { ApiRoute } from 'befly/types';
|
|
186
186
|
|
|
187
187
|
export default {
|
|
188
188
|
name: '更新用户信息',
|
|
@@ -227,7 +227,7 @@ export default {
|
|
|
227
227
|
`apis/user/changePassword.ts`:
|
|
228
228
|
|
|
229
229
|
```typescript
|
|
230
|
-
import type { ApiRoute } from 'befly
|
|
230
|
+
import type { ApiRoute } from 'befly/types';
|
|
231
231
|
|
|
232
232
|
export default {
|
|
233
233
|
name: '修改密码',
|
|
@@ -276,7 +276,7 @@ export default {
|
|
|
276
276
|
`apis/user/list.ts`:
|
|
277
277
|
|
|
278
278
|
```typescript
|
|
279
|
-
import type { ApiRoute } from 'befly
|
|
279
|
+
import type { ApiRoute } from 'befly/types';
|
|
280
280
|
|
|
281
281
|
export default {
|
|
282
282
|
name: '用户列表',
|
|
@@ -368,7 +368,7 @@ export default {
|
|
|
368
368
|
`apis/article/create.ts`:
|
|
369
369
|
|
|
370
370
|
```typescript
|
|
371
|
-
import type { ApiRoute } from 'befly
|
|
371
|
+
import type { ApiRoute } from 'befly/types';
|
|
372
372
|
|
|
373
373
|
export default {
|
|
374
374
|
name: '发布文章',
|
|
@@ -422,7 +422,7 @@ export default {
|
|
|
422
422
|
`apis/article/update.ts`:
|
|
423
423
|
|
|
424
424
|
```typescript
|
|
425
|
-
import type { ApiRoute } from 'befly
|
|
425
|
+
import type { ApiRoute } from 'befly/types';
|
|
426
426
|
|
|
427
427
|
export default {
|
|
428
428
|
name: '编辑文章',
|
|
@@ -503,7 +503,7 @@ export default {
|
|
|
503
503
|
`apis/article/delete.ts`:
|
|
504
504
|
|
|
505
505
|
```typescript
|
|
506
|
-
import type { ApiRoute } from 'befly
|
|
506
|
+
import type { ApiRoute } from 'befly/types';
|
|
507
507
|
|
|
508
508
|
export default {
|
|
509
509
|
name: '删除文章',
|
|
@@ -554,7 +554,7 @@ export default {
|
|
|
554
554
|
`apis/article/list.ts`:
|
|
555
555
|
|
|
556
556
|
```typescript
|
|
557
|
-
import type { ApiRoute } from 'befly
|
|
557
|
+
import type { ApiRoute } from 'befly/types';
|
|
558
558
|
|
|
559
559
|
export default {
|
|
560
560
|
name: '文章列表',
|
|
@@ -608,7 +608,7 @@ export default {
|
|
|
608
608
|
`apis/article/detail.ts`:
|
|
609
609
|
|
|
610
610
|
```typescript
|
|
611
|
-
import type { ApiRoute } from 'befly
|
|
611
|
+
import type { ApiRoute } from 'befly/types';
|
|
612
612
|
|
|
613
613
|
export default {
|
|
614
614
|
name: '文章详情',
|
|
@@ -673,7 +673,7 @@ export default {
|
|
|
673
673
|
```typescript
|
|
674
674
|
import { join } from 'pathe';
|
|
675
675
|
import { existsSync, mkdirSync } from 'node:fs';
|
|
676
|
-
import type { ApiRoute } from 'befly
|
|
676
|
+
import type { ApiRoute } from 'befly/types';
|
|
677
677
|
|
|
678
678
|
export default {
|
|
679
679
|
name: '文件上传',
|
|
@@ -735,7 +735,7 @@ export default {
|
|
|
735
735
|
`apis/user/export.ts`:
|
|
736
736
|
|
|
737
737
|
```typescript
|
|
738
|
-
import type { ApiRoute } from 'befly
|
|
738
|
+
import type { ApiRoute } from 'befly/types';
|
|
739
739
|
|
|
740
740
|
export default {
|
|
741
741
|
name: '导出用户',
|
package/docs/hook.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Hook 钩子开发指南
|
|
1
|
+
# Hook 钩子开发指南
|
|
2
2
|
|
|
3
3
|
> 本文档详细介绍 Befly 框架的 Hook 钩子系统,包括钩子结构、执行顺序、内置钩子及自定义钩子开发。
|
|
4
4
|
|
|
@@ -72,7 +72,7 @@ Befly Hook 系统是请求处理的中间件机制,采用串联模式依次执
|
|
|
72
72
|
### 基础结构
|
|
73
73
|
|
|
74
74
|
```typescript
|
|
75
|
-
import type { Hook } from 'befly
|
|
75
|
+
import type { Hook } from 'befly/types/hook';
|
|
76
76
|
|
|
77
77
|
const hook: Hook = {
|
|
78
78
|
// 执行顺序(数字越小越先执行)
|
|
@@ -462,7 +462,7 @@ const hook: Hook = {
|
|
|
462
462
|
|
|
463
463
|
```typescript
|
|
464
464
|
// hooks/myHook.ts(项目钩子名:app_myHook)
|
|
465
|
-
import type { Hook } from 'befly
|
|
465
|
+
import type { Hook } from 'befly/types/hook';
|
|
466
466
|
|
|
467
467
|
const hook: Hook = {
|
|
468
468
|
order: 10,
|
|
@@ -482,8 +482,8 @@ export default hook;
|
|
|
482
482
|
|
|
483
483
|
```typescript
|
|
484
484
|
// hooks/blacklist.ts
|
|
485
|
-
import type { Hook } from 'befly
|
|
486
|
-
import { ErrorResponse } from 'befly
|
|
485
|
+
import type { Hook } from 'befly/types/hook';
|
|
486
|
+
import { ErrorResponse } from 'befly/util';
|
|
487
487
|
|
|
488
488
|
const hook: Hook = {
|
|
489
489
|
order: 1, // 最先执行
|
|
@@ -509,8 +509,8 @@ export default hook;
|
|
|
509
509
|
|
|
510
510
|
```typescript
|
|
511
511
|
// hooks/rateLimit.ts
|
|
512
|
-
import type { Hook } from 'befly
|
|
513
|
-
import { ErrorResponse } from 'befly
|
|
512
|
+
import type { Hook } from 'befly/types/hook';
|
|
513
|
+
import { ErrorResponse } from 'befly/util';
|
|
514
514
|
|
|
515
515
|
const hook: Hook = {
|
|
516
516
|
order: 7,
|
|
@@ -551,7 +551,7 @@ export default hook;
|
|
|
551
551
|
|
|
552
552
|
```typescript
|
|
553
553
|
// hooks/audit.ts
|
|
554
|
-
import type { Hook } from 'befly
|
|
554
|
+
import type { Hook } from 'befly/types/hook';
|
|
555
555
|
|
|
556
556
|
const hook: Hook = {
|
|
557
557
|
order: 100, // 在 handler 执行后
|
|
@@ -590,7 +590,7 @@ export default hook;
|
|
|
590
590
|
设置 `ctx.response` 可以中断后续 Hook 和 API Handler 的执行:
|
|
591
591
|
|
|
592
592
|
```typescript
|
|
593
|
-
import { ErrorResponse } from 'befly
|
|
593
|
+
import { ErrorResponse } from 'befly/util';
|
|
594
594
|
|
|
595
595
|
const hook: Hook = {
|
|
596
596
|
order: 5,
|
package/docs/plugin.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 插件开发指南
|
|
1
|
+
# 插件开发指南
|
|
2
2
|
|
|
3
3
|
> 本文档详细介绍 Befly 框架的插件系统,包括插件结构、生命周期、内置插件及自定义插件开发。
|
|
4
4
|
|
|
@@ -68,7 +68,7 @@ Befly 插件系统是框架的核心扩展机制,允许开发者封装和复
|
|
|
68
68
|
### 基础结构
|
|
69
69
|
|
|
70
70
|
```typescript
|
|
71
|
-
import type { Plugin } from 'befly
|
|
71
|
+
import type { Plugin } from 'befly/types/plugin';
|
|
72
72
|
|
|
73
73
|
const plugin: Plugin = {
|
|
74
74
|
// 依赖的插件列表(可选)
|
|
@@ -440,7 +440,7 @@ return befly.tool.No('操作失败');
|
|
|
440
440
|
|
|
441
441
|
```typescript
|
|
442
442
|
// plugins/hello.ts
|
|
443
|
-
import type { Plugin } from 'befly
|
|
443
|
+
import type { Plugin } from 'befly/types/plugin';
|
|
444
444
|
|
|
445
445
|
const plugin: Plugin = {
|
|
446
446
|
handler: () => {
|
|
@@ -467,8 +467,8 @@ const greeting = befly.app_hello.sayHello('World');
|
|
|
467
467
|
|
|
468
468
|
```typescript
|
|
469
469
|
// plugins/userService.ts
|
|
470
|
-
import type { Plugin } from 'befly
|
|
471
|
-
import type { BeflyContext } from 'befly
|
|
470
|
+
import type { Plugin } from 'befly/types/plugin';
|
|
471
|
+
import type { BeflyContext } from 'befly/types/befly';
|
|
472
472
|
|
|
473
473
|
const plugin: Plugin = {
|
|
474
474
|
after: ['db', 'redis'], // 依赖数据库和 Redis
|
|
@@ -507,7 +507,7 @@ export default plugin;
|
|
|
507
507
|
|
|
508
508
|
```typescript
|
|
509
509
|
// plugins/elastic.ts
|
|
510
|
-
import type { Plugin } from 'befly
|
|
510
|
+
import type { Plugin } from 'befly/types/plugin';
|
|
511
511
|
import { Client } from '@elastic/elasticsearch';
|
|
512
512
|
|
|
513
513
|
const plugin: Plugin = {
|
|
@@ -550,8 +550,8 @@ export default plugin;
|
|
|
550
550
|
|
|
551
551
|
```typescript
|
|
552
552
|
// plugins/sms.ts
|
|
553
|
-
import type { Plugin } from 'befly
|
|
554
|
-
import type { BeflyContext } from 'befly
|
|
553
|
+
import type { Plugin } from 'befly/types/plugin';
|
|
554
|
+
import type { BeflyContext } from 'befly/types/befly';
|
|
555
555
|
|
|
556
556
|
interface SmsConfig {
|
|
557
557
|
accessKeyId: string;
|
|
@@ -598,8 +598,8 @@ export default plugin;
|
|
|
598
598
|
// addonAdmin/plugins/email.ts
|
|
599
599
|
import nodemailer from 'nodemailer';
|
|
600
600
|
import type { Transporter } from 'nodemailer';
|
|
601
|
-
import type { Plugin } from 'befly
|
|
602
|
-
import type { BeflyContext } from 'befly
|
|
601
|
+
import type { Plugin } from 'befly/types/plugin';
|
|
602
|
+
import type { BeflyContext } from 'befly/types/befly';
|
|
603
603
|
|
|
604
604
|
/** 邮件配置 */
|
|
605
605
|
interface EmailConfig {
|
|
@@ -767,8 +767,8 @@ Addon 插件是组件包中的扩展功能,用于为 Addon 提供特定的服
|
|
|
767
767
|
|
|
768
768
|
```typescript
|
|
769
769
|
// packages/addonPay/plugins/wechat.ts
|
|
770
|
-
import type { Plugin } from 'befly
|
|
771
|
-
import type { BeflyContext } from 'befly
|
|
770
|
+
import type { Plugin } from 'befly/types/plugin';
|
|
771
|
+
import type { BeflyContext } from 'befly/types/befly';
|
|
772
772
|
|
|
773
773
|
class WechatPayHelper {
|
|
774
774
|
private befly: BeflyContext;
|
package/docs/quickstart.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Quickstart 快速入门
|
|
1
|
+
# Quickstart 快速入门
|
|
2
2
|
|
|
3
3
|
> 5 分钟搭建你的第一个 Befly API 服务
|
|
4
4
|
|
|
@@ -74,7 +74,7 @@ my-api/
|
|
|
74
74
|
在 `apis/user/` 目录下创建 `login.ts`:
|
|
75
75
|
|
|
76
76
|
```typescript
|
|
77
|
-
import type { ApiRoute } from 'befly
|
|
77
|
+
import type { ApiRoute } from 'befly/types';
|
|
78
78
|
|
|
79
79
|
export default {
|
|
80
80
|
name: '用户登录',
|
package/lib/dbHelper.ts
CHANGED
|
@@ -638,7 +638,7 @@ export class DbHelper {
|
|
|
638
638
|
// 如果总数为 0,直接返回,不执行第二次查询
|
|
639
639
|
if (total === 0) {
|
|
640
640
|
return {
|
|
641
|
-
|
|
641
|
+
lists: [],
|
|
642
642
|
total: 0,
|
|
643
643
|
page: prepared.page,
|
|
644
644
|
limit: prepared.limit,
|
|
@@ -666,7 +666,7 @@ export class DbHelper {
|
|
|
666
666
|
|
|
667
667
|
// 转换 BIGINT 字段(id, pid 等)为数字类型
|
|
668
668
|
return {
|
|
669
|
-
|
|
669
|
+
lists: this.convertBigIntFields<T>(camelList),
|
|
670
670
|
total: total,
|
|
671
671
|
page: prepared.page,
|
|
672
672
|
limit: prepared.limit,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "befly",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.23",
|
|
4
4
|
"description": "Befly - 为 Bun 专属打造的 TypeScript API 接口框架核心引擎",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"pino": "^10.1.0",
|
|
75
75
|
"pino-roll": "^4.0.0"
|
|
76
76
|
},
|
|
77
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "9b5f1999ae83f1f0842f763845ec9d3e80e01f19",
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"typescript": "^5.9.3"
|
|
80
80
|
}
|
package/sync/syncDb/table.ts
CHANGED
|
@@ -161,7 +161,8 @@ export async function modifyTable(sql: SQL, tableName: string, fields: Record<st
|
|
|
161
161
|
const dbFieldName = snakeCase(fieldKey);
|
|
162
162
|
|
|
163
163
|
const indexName = `idx_${dbFieldName}`;
|
|
164
|
-
|
|
164
|
+
// 如果字段有 unique 约束,跳过创建普通索引(unique 会自动创建唯一索引)
|
|
165
|
+
if (fieldDef.index && !fieldDef.unique && !existingIndexes[indexName]) {
|
|
165
166
|
indexActions.push({ action: 'create', indexName: indexName, fieldName: dbFieldName });
|
|
166
167
|
changed = true;
|
|
167
168
|
} else if (!fieldDef.index && existingIndexes[indexName] && existingIndexes[indexName].length === 1) {
|