befly 3.10.0 → 3.10.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/.gitignore +0 -0
- package/README.md +10 -13
- package/configs/presetFields.ts +10 -0
- package/configs/presetRegexp.ts +225 -0
- package/docs/README.md +17 -11
- package/docs/api/api.md +15 -1
- package/docs/guide/quickstart.md +19 -5
- package/docs/infra/redis.md +23 -11
- package/docs/quickstart.md +5 -335
- package/docs/reference/addon.md +0 -15
- package/docs/reference/config.md +1 -1
- package/docs/reference/logger.md +3 -3
- package/docs/reference/sync.md +99 -73
- package/docs/reference/table.md +1 -1
- package/package.json +15 -16
- package/docs/cipher.md +0 -582
- package/docs/database.md +0 -1176
- package/tests/_mocks/mockSqliteDb.ts +0 -204
- package/tests/addonHelper-cache.test.ts +0 -32
- package/tests/api-integration-array-number.test.ts +0 -282
- package/tests/apiHandler-routePath-only.test.ts +0 -32
- package/tests/befly-config-env.test.ts +0 -78
- package/tests/cacheHelper.test.ts +0 -323
- package/tests/cacheKeys.test.ts +0 -41
- package/tests/checkApi-routePath-strict.test.ts +0 -166
- package/tests/checkMenu.test.ts +0 -346
- package/tests/checkTable-smoke.test.ts +0 -157
- package/tests/cipher.test.ts +0 -249
- package/tests/dbDialect-cache.test.ts +0 -23
- package/tests/dbDialect.test.ts +0 -46
- package/tests/dbHelper-advanced.test.ts +0 -723
- package/tests/dbHelper-all-array-types.test.ts +0 -316
- package/tests/dbHelper-array-serialization.test.ts +0 -258
- package/tests/dbHelper-batch-write.test.ts +0 -90
- package/tests/dbHelper-columns.test.ts +0 -234
- package/tests/dbHelper-execute.test.ts +0 -187
- package/tests/dbHelper-joins.test.ts +0 -221
- package/tests/fields-redis-cache.test.ts +0 -127
- package/tests/fields-validate.test.ts +0 -99
- package/tests/fixtures/scanFilesAddon/node_modules/@befly-addon/demo/apis/sub/b.ts +0 -3
- package/tests/fixtures/scanFilesApis/a.ts +0 -3
- package/tests/fixtures/scanFilesApis/sub/b.ts +0 -3
- package/tests/getClientIp.test.ts +0 -54
- package/tests/integration.test.ts +0 -189
- package/tests/jwt.test.ts +0 -65
- package/tests/loadPlugins-order-smoke.test.ts +0 -75
- package/tests/logger.test.ts +0 -325
- package/tests/redisHelper.test.ts +0 -495
- package/tests/redisKeys.test.ts +0 -9
- package/tests/scanConfig.test.ts +0 -144
- package/tests/scanFiles-routePath.test.ts +0 -46
- package/tests/smoke-sql.test.ts +0 -24
- package/tests/sqlBuilder-advanced.test.ts +0 -608
- package/tests/sqlBuilder.test.ts +0 -209
- package/tests/sync-connection.test.ts +0 -183
- package/tests/sync-init-guard.test.ts +0 -105
- package/tests/syncApi-insBatch-fields-consistent.test.ts +0 -61
- package/tests/syncApi-obsolete-records.test.ts +0 -69
- package/tests/syncApi-type-compat.test.ts +0 -72
- package/tests/syncDev-permissions.test.ts +0 -81
- package/tests/syncMenu-disableMenus-hard-delete.test.ts +0 -88
- package/tests/syncMenu-duplicate-path.test.ts +0 -122
- package/tests/syncMenu-obsolete-records.test.ts +0 -161
- package/tests/syncMenu-parentPath-from-tree.test.ts +0 -75
- package/tests/syncMenu-paths.test.ts +0 -59
- package/tests/syncTable-apply.test.ts +0 -279
- package/tests/syncTable-array-number.test.ts +0 -160
- package/tests/syncTable-constants.test.ts +0 -101
- package/tests/syncTable-db-integration.test.ts +0 -237
- package/tests/syncTable-ddl.test.ts +0 -245
- package/tests/syncTable-helpers.test.ts +0 -99
- package/tests/syncTable-schema.test.ts +0 -99
- package/tests/syncTable-testkit.test.ts +0 -25
- package/tests/syncTable-types.test.ts +0 -122
- package/tests/tableRef-and-deserialize.test.ts +0 -67
- package/tests/util.test.ts +0 -100
- package/tests/validator-array-number.test.ts +0 -310
- package/tests/validator-default.test.ts +0 -373
- package/tests/validator.test.ts +0 -679
package/docs/quickstart.md
CHANGED
|
@@ -1,338 +1,8 @@
|
|
|
1
|
-
# Quickstart
|
|
1
|
+
# Quickstart 快速入门(已迁移)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
为避免重复内容长期漂移,本 Quickstart 已迁移到权威入口:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- `packages/core/docs/guide/quickstart.md`
|
|
6
|
+
- 在线阅读:[`./guide/quickstart.md`](./guide/quickstart.md)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
- [项目结构](#项目结构)
|
|
9
|
-
- [第一个 API](#第一个-api)
|
|
10
|
-
- [配置数据库](#配置数据库)
|
|
11
|
-
- [定义表结构](#定义表结构)
|
|
12
|
-
- [同步数据库](#同步数据库)
|
|
13
|
-
- [启动服务](#启动服务)
|
|
14
|
-
- [下一步](#下一步)
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 环境准备
|
|
19
|
-
|
|
20
|
-
### 必需软件
|
|
21
|
-
|
|
22
|
-
| 软件 | 版本要求 | 说明 |
|
|
23
|
-
| ----- | -------- | ----------------- |
|
|
24
|
-
| Bun | >= 1.0 | JavaScript 运行时 |
|
|
25
|
-
| MySQL | >= 8.0 | 数据库 |
|
|
26
|
-
| Redis | >= 6.0 | 缓存(可选) |
|
|
27
|
-
|
|
28
|
-
### 安装 Bun
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
# Windows (PowerShell)
|
|
32
|
-
powershell -c "irm bun.sh/install.ps1 | iex"
|
|
33
|
-
|
|
34
|
-
# macOS / Linux
|
|
35
|
-
curl -fsSL https://bun.sh/install | bash
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### 创建项目
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
# 克隆模板项目
|
|
42
|
-
git clone https://github.com/chenbimo/befly-tpl.git my-api
|
|
43
|
-
cd my-api
|
|
44
|
-
|
|
45
|
-
# 安装依赖
|
|
46
|
-
bun install
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## 项目结构
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
my-api/
|
|
55
|
-
├── apis/ # API 接口目录
|
|
56
|
-
│ └── user/
|
|
57
|
-
│ └── login.ts # 用户登录接口
|
|
58
|
-
├── tables/ # 表定义目录
|
|
59
|
-
│ └── user.json # 用户表定义
|
|
60
|
-
├── configs/ # 配置文件目录
|
|
61
|
-
│ ├── befly.common.json # 公共配置
|
|
62
|
-
│ ├── befly.development.json # 开发环境配置
|
|
63
|
-
│ └── befly.production.json # 生产环境配置
|
|
64
|
-
├── main.ts # 入口文件
|
|
65
|
-
└── package.json
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## 第一个 API
|
|
71
|
-
|
|
72
|
-
### 创建 API 文件
|
|
73
|
-
|
|
74
|
-
在 `apis/user/` 目录下创建 `login.ts`:
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
import type { ApiRoute } from "befly/types/api";
|
|
78
|
-
|
|
79
|
-
export default {
|
|
80
|
-
name: "用户登录",
|
|
81
|
-
method: "POST",
|
|
82
|
-
auth: false, // 不需要登录
|
|
83
|
-
fields: {
|
|
84
|
-
email: { name: "邮箱", type: "string", min: 5, max: 100, regexp: "@email" },
|
|
85
|
-
password: { name: "密码", type: "string", min: 6, max: 100 }
|
|
86
|
-
},
|
|
87
|
-
required: ["email", "password"],
|
|
88
|
-
handler: async (befly, ctx) => {
|
|
89
|
-
// 查询用户
|
|
90
|
-
const user = await befly.db.getDetail({
|
|
91
|
-
table: "user",
|
|
92
|
-
columns: ["id", "email", "password", "nickname"],
|
|
93
|
-
where: { email: ctx.body.email }
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
if (!user?.id) {
|
|
97
|
-
return No("用户不存在");
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// 验证密码
|
|
101
|
-
const isValid = await befly.cipher.verifyPassword(ctx.body.password, user.password);
|
|
102
|
-
if (!isValid) {
|
|
103
|
-
return No("密码错误");
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// 签发令牌
|
|
107
|
-
const token = befly.jwt.sign({ userId: user.id });
|
|
108
|
-
|
|
109
|
-
return Yes("登录成功", { token: token, user: { id: user.id, nickname: user.nickname } });
|
|
110
|
-
}
|
|
111
|
-
} as ApiRoute;
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### API 路由规则
|
|
115
|
-
|
|
116
|
-
文件路径自动转换为路由:
|
|
117
|
-
|
|
118
|
-
| 文件路径 | 路由路径 |
|
|
119
|
-
| ----------------------- | ------------------------- |
|
|
120
|
-
| `apis/user/login.ts` | `POST /api/user/login` |
|
|
121
|
-
| `apis/user/register.ts` | `POST /api/user/register` |
|
|
122
|
-
| `apis/article/list.ts` | `POST /api/article/list` |
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## 配置数据库
|
|
127
|
-
|
|
128
|
-
### 编辑配置文件
|
|
129
|
-
|
|
130
|
-
修改 `configs/befly.development.json`:
|
|
131
|
-
|
|
132
|
-
```json
|
|
133
|
-
{
|
|
134
|
-
"db": {
|
|
135
|
-
"type": "mysql",
|
|
136
|
-
"host": "127.0.0.1",
|
|
137
|
-
"port": 3306,
|
|
138
|
-
"user": "root",
|
|
139
|
-
"password": "your_password",
|
|
140
|
-
"database": "my_api"
|
|
141
|
-
},
|
|
142
|
-
"redis": {
|
|
143
|
-
"host": "127.0.0.1",
|
|
144
|
-
"port": 6379,
|
|
145
|
-
"password": ""
|
|
146
|
-
},
|
|
147
|
-
"auth": {
|
|
148
|
-
"secret": "your-jwt-secret-change-in-production",
|
|
149
|
-
"expiresIn": "7d"
|
|
150
|
-
},
|
|
151
|
-
"logger": {
|
|
152
|
-
"debug": 1,
|
|
153
|
-
"console": 1
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### 创建数据库
|
|
159
|
-
|
|
160
|
-
```sql
|
|
161
|
-
CREATE DATABASE my_api CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
## 定义表结构
|
|
167
|
-
|
|
168
|
-
### 创建表定义文件
|
|
169
|
-
|
|
170
|
-
在 `tables/` 目录下创建 `user.json`:
|
|
171
|
-
|
|
172
|
-
```json
|
|
173
|
-
{
|
|
174
|
-
"email": "邮箱|string|5|100||true|^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$",
|
|
175
|
-
"password": "密码|string|6|100||true",
|
|
176
|
-
"nickname": "昵称|string|2|50|用户",
|
|
177
|
-
"avatar": "头像|string|0|500",
|
|
178
|
-
"phone": "手机号|string|0|20"
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### 字段定义格式
|
|
183
|
-
|
|
184
|
-
格式:`"字段标签|类型|最小|最大|默认|必填|正则"`
|
|
185
|
-
|
|
186
|
-
| 位置 | 说明 | 示例 |
|
|
187
|
-
| ---- | ----------- | --------------------- |
|
|
188
|
-
| 1 | 字段标签 | `邮箱` |
|
|
189
|
-
| 2 | 数据类型 | `string` / `number` |
|
|
190
|
-
| 3 | 最小值/长度 | `5` |
|
|
191
|
-
| 4 | 最大值/长度 | `100` |
|
|
192
|
-
| 5 | 默认值 | `用户` |
|
|
193
|
-
| 6 | 是否必填 | `true` / `false` |
|
|
194
|
-
| 7 | 正则验证 | `@email` 或自定义正则 |
|
|
195
|
-
|
|
196
|
-
### 自动字段
|
|
197
|
-
|
|
198
|
-
每个表自动添加:
|
|
199
|
-
|
|
200
|
-
| 字段 | 类型 | 说明 |
|
|
201
|
-
| ------------ | ------- | ------------------------------- |
|
|
202
|
-
| `id` | BIGINT | 主键,自增 |
|
|
203
|
-
| `created_at` | BIGINT | 创建时间戳 |
|
|
204
|
-
| `updated_at` | BIGINT | 更新时间戳 |
|
|
205
|
-
| `state` | TINYINT | 状态(1=正常,0=禁用,-1=删除) |
|
|
206
|
-
|
|
207
|
-
---
|
|
208
|
-
|
|
209
|
-
## 同步数据库
|
|
210
|
-
|
|
211
|
-
### 自动同步
|
|
212
|
-
|
|
213
|
-
服务启动时会在**主进程**自动执行同步流程:
|
|
214
|
-
|
|
215
|
-
1. `syncTable()`:同步表结构
|
|
216
|
-
2. `syncData()`:固定顺序执行 `syncApi` → `syncMenu` → `syncDev`
|
|
217
|
-
|
|
218
|
-
如需手动触发,可在代码中调用(一般不建议在请求路径中调用):
|
|
219
|
-
|
|
220
|
-
```typescript
|
|
221
|
-
import { syncData } from "../sync/syncData.js";
|
|
222
|
-
import { syncTable } from "../sync/syncTable.js";
|
|
223
|
-
import { scanSources } from "../utils/scanSources.js";
|
|
224
|
-
|
|
225
|
-
// ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.config)
|
|
226
|
-
const sources = await scanSources();
|
|
227
|
-
await syncTable(ctx, sources.tables);
|
|
228
|
-
await syncData();
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### 验证同步结果
|
|
232
|
-
|
|
233
|
-
```bash
|
|
234
|
-
# 查看数据库
|
|
235
|
-
mysql -u root -p my_api -e "SHOW TABLES;"
|
|
236
|
-
|
|
237
|
-
# 应该看到:
|
|
238
|
-
# +------------------+
|
|
239
|
-
# | Tables_in_my_api |
|
|
240
|
-
# +------------------+
|
|
241
|
-
# | user |
|
|
242
|
-
# +------------------+
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## 启动服务
|
|
248
|
-
|
|
249
|
-
### 开发模式
|
|
250
|
-
|
|
251
|
-
```bash
|
|
252
|
-
bun run dev
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
服务启动后:
|
|
256
|
-
|
|
257
|
-
```
|
|
258
|
-
🚀 Befly 服务已启动
|
|
259
|
-
📍 http://localhost:3000
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### 测试 API
|
|
263
|
-
|
|
264
|
-
```bash
|
|
265
|
-
# 测试登录接口
|
|
266
|
-
curl -X POST http://localhost:3000/api/user/login \
|
|
267
|
-
-H "Content-Type: application/json" \
|
|
268
|
-
-d '{"email":"test@example.com","password":"123456"}'
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
响应示例:
|
|
272
|
-
|
|
273
|
-
```json
|
|
274
|
-
{
|
|
275
|
-
"code": 0,
|
|
276
|
-
"msg": "登录成功",
|
|
277
|
-
"data": {
|
|
278
|
-
"token": "eyJhbGciOiJIUzI1NiIs...",
|
|
279
|
-
"user": {
|
|
280
|
-
"id": 1,
|
|
281
|
-
"nickname": "用户"
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
---
|
|
288
|
-
|
|
289
|
-
## 下一步
|
|
290
|
-
|
|
291
|
-
### 学习更多
|
|
292
|
-
|
|
293
|
-
| 主题 | 文档 | 说明 |
|
|
294
|
-
| ---------- | ------------------------------------ | -------------------- |
|
|
295
|
-
| API 开发 | [api.md](./api/api.md) | API 定义、字段、权限 |
|
|
296
|
-
| 表结构 | [table.md](./table.md) | 表定义格式详解 |
|
|
297
|
-
| 数据库操作 | [database.md](./plugins/database.md) | CRUD 操作 |
|
|
298
|
-
| 配置系统 | [config.md](./config.md) | 配置文件说明 |
|
|
299
|
-
| 插件开发 | [plugin.md](./plugins/plugin.md) | 自定义插件 |
|
|
300
|
-
| Hook 开发 | [hook.md](./hooks/hook.md) | 请求处理钩子 |
|
|
301
|
-
| 验证系统 | [validator.md](./validator.md) | 参数验证 |
|
|
302
|
-
| 日志系统 | [logger.md](./logger.md) | 日志配置 |
|
|
303
|
-
| 加密工具 | [cipher.md](./plugins/cipher.md) | 加密与 JWT |
|
|
304
|
-
| 同步命令 | [sync.md](./sync.md) | 数据库同步 |
|
|
305
|
-
|
|
306
|
-
### 常用命令
|
|
307
|
-
|
|
308
|
-
```bash
|
|
309
|
-
# 开发
|
|
310
|
-
bun run dev # 启动开发服务
|
|
311
|
-
|
|
312
|
-
# 生产
|
|
313
|
-
bun run build # 构建
|
|
314
|
-
bun run start # 启动生产服务
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
### 项目示例
|
|
318
|
-
|
|
319
|
-
```
|
|
320
|
-
apis/
|
|
321
|
-
├── user/
|
|
322
|
-
│ ├── login.ts # 登录
|
|
323
|
-
│ ├── register.ts # 注册
|
|
324
|
-
│ ├── info.ts # 获取信息
|
|
325
|
-
│ └── update.ts # 更新信息
|
|
326
|
-
├── article/
|
|
327
|
-
│ ├── list.ts # 文章列表
|
|
328
|
-
│ ├── detail.ts # 文章详情
|
|
329
|
-
│ ├── create.ts # 创建文章
|
|
330
|
-
│ └── delete.ts # 删除文章
|
|
331
|
-
└── common/
|
|
332
|
-
└── upload.ts # 文件上传
|
|
333
|
-
|
|
334
|
-
tables/
|
|
335
|
-
├── user.json # 用户表
|
|
336
|
-
├── article.json # 文章表
|
|
337
|
-
└── category.json # 分类表
|
|
338
|
-
```
|
|
8
|
+
如你从旧链接跳转到这里,请以 `guide/quickstart.md` 的内容为准(配置字段、同步流程、权限 pathname 规则等都以当前实现为准)。
|
package/docs/reference/addon.md
CHANGED
|
@@ -465,21 +465,6 @@ A: 在配置文件中设置:
|
|
|
465
465
|
}
|
|
466
466
|
```
|
|
467
467
|
|
|
468
|
-
### Q: Addon 的表如何迁移?
|
|
469
|
-
|
|
470
|
-
A: 服务启动时(主进程)会自动执行 `syncTable()`,会同步项目与所有 Addon 的表定义。
|
|
471
|
-
|
|
472
|
-
如需手动触发:
|
|
473
|
-
|
|
474
|
-
```typescript
|
|
475
|
-
import { syncTable } from "../../sync/syncTable.js";
|
|
476
|
-
import { scanSources } from "../../utils/scanSources.js";
|
|
477
|
-
|
|
478
|
-
// ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.config)
|
|
479
|
-
const sources = await scanSources();
|
|
480
|
-
await syncTable(ctx, sources.tables);
|
|
481
|
-
```
|
|
482
|
-
|
|
483
468
|
### Q: 如何在 Addon 中访问项目配置?
|
|
484
469
|
|
|
485
470
|
A: 通过 `befly.config` 访问:
|
package/docs/reference/config.md
CHANGED
package/docs/reference/logger.md
CHANGED
|
@@ -98,8 +98,8 @@ Logger.info("用户登录成功");
|
|
|
98
98
|
Logger.info({ userId: 123 }, "用户登录成功");
|
|
99
99
|
|
|
100
100
|
// 警告日志
|
|
101
|
-
Logger.warn("
|
|
102
|
-
Logger.warn({ config: "oldOption" }, "
|
|
101
|
+
Logger.warn("配置项不合法");
|
|
102
|
+
Logger.warn({ config: "oldOption" }, "配置项不合法");
|
|
103
103
|
|
|
104
104
|
// 错误日志
|
|
105
105
|
Logger.error("数据库连接失败");
|
|
@@ -393,7 +393,7 @@ Logger.debug({ sql: query, params: params }, "SQL 查询");
|
|
|
393
393
|
Logger.info({ userId: 123 }, "用户登录成功");
|
|
394
394
|
|
|
395
395
|
// warn: 潜在问题,但不影响功能
|
|
396
|
-
Logger.warn({ config: "
|
|
396
|
+
Logger.warn({ config: "invalidOption" }, "配置项不合法");
|
|
397
397
|
|
|
398
398
|
// error: 操作失败
|
|
399
399
|
Logger.error({ err: error }, "数据库连接失败");
|
package/docs/reference/sync.md
CHANGED
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
## 目录
|
|
6
6
|
|
|
7
7
|
- [概述](#概述)
|
|
8
|
+
- [强约束清单](#强约束清单)
|
|
8
9
|
- [syncTable 数据库同步](#synctable-数据库同步)
|
|
9
10
|
- [syncApi 接口同步](#syncapi-接口同步)
|
|
10
11
|
- [syncMenu 菜单同步](#syncmenu-菜单同步)
|
|
11
12
|
- [syncDev 开发账户同步](#syncdev-开发账户同步)
|
|
13
|
+
- [syncCache 缓存同步](#synccache-缓存同步)
|
|
12
14
|
- [表名规则](#表名规则)
|
|
13
15
|
- [注意事项](#注意事项)
|
|
14
16
|
- [FAQ](#faq)
|
|
@@ -25,8 +27,18 @@ Sync 同步系统用于将代码定义同步到数据库,包括:
|
|
|
25
27
|
| `syncApi` | 同步 API 路由信息 | `addon_admin_api` |
|
|
26
28
|
| `syncMenu` | 同步菜单配置 | `addon_admin_menu` |
|
|
27
29
|
| `syncDev` | 创建开发者账户 | `addon_admin_role`, `addon_admin_admin` |
|
|
30
|
+
| `syncCache` | 同步缓存 | Redis(apis/menu/role-permissions) |
|
|
28
31
|
|
|
29
|
-
**执行顺序**:`syncTable` → `syncApi` → `syncMenu` → `syncDev`
|
|
32
|
+
**执行顺序**:`syncTable` → `syncApi` → `syncMenu` → `syncDev` → `syncCache`
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 强约束清单
|
|
37
|
+
|
|
38
|
+
- **API routePath 必须是 pathname**:`syncApi` 写入数据库的 `routePath` 仅允许 `url.pathname`(例如 `/api/user/login`),禁止出现 method 前缀(`POST/api/...`、`POST /api/...`)。
|
|
39
|
+
- **角色权限 apis 仅允许 pathname 字符串数组**:`syncDev` 写入角色表的 `apis` 必须是 pathname 字符串数组(严格模式不允许 numeric id)。
|
|
40
|
+
- **权限缓存 Set member 仅允许 pathname**:角色接口权限缓存的 Set 成员为 pathname,与 method 无关。
|
|
41
|
+
- **Redis prefix 不允许包含冒号**:配置 `redis.prefix` 不要包含 `:`(系统会自动拼接分隔符)。例如写 `befly`,不要写 `befly:`。
|
|
30
42
|
|
|
31
43
|
> 说明:当前版本不提供 CLI 同步命令;同步逻辑在服务启动时由主进程自动执行(见 `packages/core/main.ts`)。
|
|
32
44
|
|
|
@@ -44,7 +56,7 @@ Sync 同步系统用于将代码定义同步到数据库,包括:
|
|
|
44
56
|
import { syncTable } from "../sync/syncTable.js";
|
|
45
57
|
import { scanSources } from "../utils/scanSources.js";
|
|
46
58
|
|
|
47
|
-
// ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.config)
|
|
59
|
+
// ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.cache / ctx.config)
|
|
48
60
|
const sources = await scanSources();
|
|
49
61
|
await syncTable(ctx, sources.tables);
|
|
50
62
|
```
|
|
@@ -103,14 +115,16 @@ await syncTable(ctx, sources.tables);
|
|
|
103
115
|
|
|
104
116
|
### 基本用法
|
|
105
117
|
|
|
106
|
-
|
|
118
|
+
通常无需单独调用:服务启动流程会按顺序执行 `syncTable` → `syncApi` → `syncMenu` → `syncDev` → `syncCache`。
|
|
107
119
|
|
|
108
|
-
|
|
120
|
+
如需在代码中手动调用:
|
|
109
121
|
|
|
110
122
|
```typescript
|
|
111
|
-
import {
|
|
123
|
+
import { syncApi } from "../sync/syncApi.js";
|
|
124
|
+
import { scanSources } from "../utils/scanSources.js";
|
|
112
125
|
|
|
113
|
-
await
|
|
126
|
+
const sources = await scanSources();
|
|
127
|
+
await syncApi(ctx, sources.apis as any);
|
|
114
128
|
```
|
|
115
129
|
|
|
116
130
|
### 同步逻辑
|
|
@@ -137,20 +151,15 @@ await syncData();
|
|
|
137
151
|
└─────────────────────────────────────────────────────┘
|
|
138
152
|
```
|
|
139
153
|
|
|
140
|
-
###
|
|
154
|
+
### 存储字段(重要)
|
|
141
155
|
|
|
142
|
-
|
|
156
|
+
`syncApi` 会把扫描到的 API 信息同步到 `addon_admin_api` 表,核心字段为:
|
|
143
157
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
description: string; // 接口描述(desc 属性)
|
|
150
|
-
addonName: string; // 所属 Addon 名称
|
|
151
|
-
addonTitle: string; // Addon 标题
|
|
152
|
-
}
|
|
153
|
-
```
|
|
158
|
+
- `routePath`:只存 `url.pathname`(例如 `/api/user/login`),与 method 无关
|
|
159
|
+
- `name`:接口名称
|
|
160
|
+
- `addonName`:所属 addon(无 addon 时为空字符串)
|
|
161
|
+
|
|
162
|
+
> 注意:`routePath` 必须是 pathname(以 `/` 开头),不允许写成 `POST /api/...` 或 `POST/api/...`。
|
|
154
163
|
|
|
155
164
|
### 统计信息
|
|
156
165
|
|
|
@@ -171,7 +180,19 @@ interface SyncApiStats {
|
|
|
171
180
|
|
|
172
181
|
### 基本用法
|
|
173
182
|
|
|
174
|
-
同 `syncApi
|
|
183
|
+
同 `syncApi`,通常由启动流程统一触发。
|
|
184
|
+
|
|
185
|
+
如需手动调用,需要先对菜单配置做校验/过滤(例如 disableMenus):
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import { checkMenu } from "../checks/checkMenu.js";
|
|
189
|
+
import { syncMenu } from "../sync/syncMenu.js";
|
|
190
|
+
import { scanSources } from "../utils/scanSources.js";
|
|
191
|
+
|
|
192
|
+
const sources = await scanSources();
|
|
193
|
+
const checkedMenus = await checkMenu(sources.addons, { disableMenus: ctx.config.disableMenus || [] });
|
|
194
|
+
await syncMenu(ctx, checkedMenus);
|
|
195
|
+
```
|
|
175
196
|
|
|
176
197
|
### 菜单配置文件
|
|
177
198
|
|
|
@@ -256,49 +277,56 @@ interface SyncMenuStats {
|
|
|
256
277
|
|
|
257
278
|
### 基本用法
|
|
258
279
|
|
|
259
|
-
同 `syncApi
|
|
280
|
+
同 `syncApi`,通常由启动流程统一触发。
|
|
260
281
|
|
|
261
282
|
### 同步逻辑
|
|
262
283
|
|
|
263
284
|
```
|
|
264
285
|
┌─────────────────────────────────────────────────────┐
|
|
265
|
-
│
|
|
286
|
+
│ syncDev │
|
|
266
287
|
├─────────────────────────────────────────────────────┤
|
|
267
|
-
│
|
|
268
|
-
│
|
|
269
|
-
│
|
|
270
|
-
│
|
|
271
|
-
│
|
|
272
|
-
│
|
|
273
|
-
│
|
|
274
|
-
│
|
|
275
|
-
│
|
|
276
|
-
│
|
|
277
|
-
│
|
|
278
|
-
│
|
|
279
|
-
│
|
|
280
|
-
│
|
|
281
|
-
│
|
|
282
|
-
│
|
|
283
|
-
│
|
|
288
|
+
│ 1. 创建/更新开发角色: │
|
|
289
|
+
│ - 角色名称:开发者 │
|
|
290
|
+
│ - 角色标识:dev │
|
|
291
|
+
│ - 权限:所有菜单 + 所有 API │
|
|
292
|
+
│ ↓ │
|
|
293
|
+
│ 2. 获取所有菜单 path 列表 │
|
|
294
|
+
│ ↓ │
|
|
295
|
+
│ 3. 获取所有 API routePath 列表 │
|
|
296
|
+
│ ↓ │
|
|
297
|
+
│ 4. 更新角色权限: │
|
|
298
|
+
│ - menus: 所有菜单 path(字符串数组) │
|
|
299
|
+
│ - apis: 所有 API routePath(pathname 字符串数组)│
|
|
300
|
+
│ ↓ │
|
|
301
|
+
│ 5. 创建/更新开发管理员: │
|
|
302
|
+
│ - 用户名:dev │
|
|
303
|
+
│ - 密码:从配置读取 │
|
|
304
|
+
│ - 角色:开发者角色 │
|
|
284
305
|
└─────────────────────────────────────────────────────┘
|
|
285
306
|
```
|
|
286
307
|
|
|
287
308
|
### 配置说明
|
|
288
309
|
|
|
289
|
-
开发账户配置在 `befly.config.ts`
|
|
310
|
+
开发账户配置在 `befly.config.ts` 或环境配置文件中(仅当 `devPassword` 有值时才会创建 dev 账号):
|
|
290
311
|
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
password: "dev123456" // 开发账户密码
|
|
297
|
-
}
|
|
298
|
-
};
|
|
312
|
+
```json
|
|
313
|
+
{
|
|
314
|
+
"devEmail": "dev@qq.com",
|
|
315
|
+
"devPassword": "beflydev123456"
|
|
316
|
+
}
|
|
299
317
|
```
|
|
300
318
|
|
|
301
|
-
|
|
319
|
+
> 注意:`syncDev` 会把 `menus/apis` 写入角色表,并且 `apis` 必须是 pathname 字符串数组(严格模式下不允许 numeric id)。
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## syncCache 缓存同步
|
|
324
|
+
|
|
325
|
+
同步缓存(统一收敛到启动流程末尾执行):
|
|
326
|
+
|
|
327
|
+
- `cacheApis()`:缓存接口列表
|
|
328
|
+
- `cacheMenus()`:缓存菜单列表
|
|
329
|
+
- `rebuildRoleApiPermissions()`:重建角色接口权限 Set(member 为 pathname,与 method 无关)
|
|
302
330
|
|
|
303
331
|
---
|
|
304
332
|
|
|
@@ -306,16 +334,23 @@ await syncTable(ctx, sources.tables);
|
|
|
306
334
|
|
|
307
335
|
```typescript
|
|
308
336
|
import { syncTable } from "./sync/syncTable.js";
|
|
337
|
+
import { syncApi } from "./sync/syncApi.js";
|
|
338
|
+
import { syncCache } from "./sync/syncCache.js";
|
|
339
|
+
import { syncDev } from "./sync/syncDev.js";
|
|
340
|
+
import { syncMenu } from "./sync/syncMenu.js";
|
|
309
341
|
import { scanSources } from "./utils/scanSources.js";
|
|
310
|
-
import {
|
|
342
|
+
import { checkMenu } from "./checks/checkMenu.js";
|
|
311
343
|
|
|
312
344
|
// 启动前/启动中手动触发同步
|
|
313
|
-
// ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.config)
|
|
345
|
+
// ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.cache / ctx.config)
|
|
314
346
|
const sources = await scanSources();
|
|
315
|
-
await
|
|
316
|
-
await syncData();
|
|
347
|
+
const checkedMenus = await checkMenu(sources.addons, { disableMenus: ctx.config.disableMenus || [] });
|
|
317
348
|
|
|
318
|
-
|
|
349
|
+
await syncTable(ctx, sources.tables);
|
|
350
|
+
await syncApi(ctx, sources.apis as any);
|
|
351
|
+
await syncMenu(ctx, checkedMenus);
|
|
352
|
+
await syncDev(ctx, { devEmail: ctx.config.devEmail, devPassword: ctx.config.devPassword });
|
|
353
|
+
await syncCache(ctx);
|
|
319
354
|
```
|
|
320
355
|
|
|
321
356
|
---
|
|
@@ -357,7 +392,7 @@ addons/demo/tables/article.json → addon_demo_article
|
|
|
357
392
|
|
|
358
393
|
### 1. 执行顺序
|
|
359
394
|
|
|
360
|
-
**必须按顺序执行**:`syncTable` → `syncApi` → `syncMenu` → `syncDev`
|
|
395
|
+
**必须按顺序执行**:`syncTable` → `syncApi` → `syncMenu` → `syncDev` → `syncCache`
|
|
361
396
|
|
|
362
397
|
- `syncApi` 依赖 `addon_admin_api` 表(由 `syncTable` 创建)
|
|
363
398
|
- `syncMenu` 依赖 `addon_admin_menu` 表(由 `syncTable` 创建)
|
|
@@ -386,11 +421,10 @@ CacheKeys.tableColumns(tableName); // table:columns:{tableName}
|
|
|
386
421
|
|
|
387
422
|
### 4. 连接管理
|
|
388
423
|
|
|
389
|
-
|
|
424
|
+
`sync*` 函数本身不会负责建立连接/加载插件:
|
|
390
425
|
|
|
391
|
-
-
|
|
392
|
-
-
|
|
393
|
-
- 出错时正确清理资源
|
|
426
|
+
- 你需要在调用前确保 `Connect.connect(...)` 已执行,并且 `Db/Redis/cache` 插件已注入到 `ctx`。
|
|
427
|
+
- 服务启动流程已内置这套顺序(见 `packages/core/main.ts`)。
|
|
394
428
|
|
|
395
429
|
---
|
|
396
430
|
|
|
@@ -425,28 +459,20 @@ A: Addon 表名格式为 `addon_{addonName}_{tableName}`,建议:
|
|
|
425
459
|
|
|
426
460
|
A:
|
|
427
461
|
|
|
428
|
-
1.
|
|
429
|
-
A: `syncTable()` 会跳过长度收缩并告警;请手动评估并处理(例如先清理/截断数据,再手动执行 DDL),再重新启动服务或再次调用 `syncTable()`。
|
|
462
|
+
1. 检查错误日志确定失败原因(例如表不存在、字段变更被跳过等)
|
|
430
463
|
2. sync 命令是幂等的,可以安全地多次执行
|
|
431
464
|
|
|
432
465
|
### Q: 如何只同步某个 Addon 的表?
|
|
433
466
|
|
|
434
|
-
await syncTable(ctx, sources.tables);
|
|
435
467
|
A: 当前不支持按 Addon 或单表筛选;会同步项目与所有 Addon 的表定义。
|
|
436
468
|
|
|
437
469
|
### Q: 开发账户密码在哪里配置?
|
|
438
470
|
|
|
439
|
-
A:
|
|
471
|
+
A: 在配置文件中设置(仅当 `devPassword` 有值时才会创建 dev 账号):
|
|
440
472
|
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
password: "your_password"
|
|
447
|
-
}
|
|
448
|
-
};
|
|
473
|
+
```json
|
|
474
|
+
{
|
|
475
|
+
"devEmail": "dev@qq.com",
|
|
476
|
+
"devPassword": "beflydev123456"
|
|
477
|
+
}
|
|
449
478
|
```
|
|
450
|
-
|
|
451
|
-
(不再提供 CLI 参数/命令;按配置文件机制设置即可。)
|
|
452
|
-
await syncTable(ctx, sources.tables);
|
package/docs/reference/table.md
CHANGED