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.
Files changed (79) hide show
  1. package/.gitignore +0 -0
  2. package/README.md +10 -13
  3. package/configs/presetFields.ts +10 -0
  4. package/configs/presetRegexp.ts +225 -0
  5. package/docs/README.md +17 -11
  6. package/docs/api/api.md +15 -1
  7. package/docs/guide/quickstart.md +19 -5
  8. package/docs/infra/redis.md +23 -11
  9. package/docs/quickstart.md +5 -335
  10. package/docs/reference/addon.md +0 -15
  11. package/docs/reference/config.md +1 -1
  12. package/docs/reference/logger.md +3 -3
  13. package/docs/reference/sync.md +99 -73
  14. package/docs/reference/table.md +1 -1
  15. package/package.json +15 -16
  16. package/docs/cipher.md +0 -582
  17. package/docs/database.md +0 -1176
  18. package/tests/_mocks/mockSqliteDb.ts +0 -204
  19. package/tests/addonHelper-cache.test.ts +0 -32
  20. package/tests/api-integration-array-number.test.ts +0 -282
  21. package/tests/apiHandler-routePath-only.test.ts +0 -32
  22. package/tests/befly-config-env.test.ts +0 -78
  23. package/tests/cacheHelper.test.ts +0 -323
  24. package/tests/cacheKeys.test.ts +0 -41
  25. package/tests/checkApi-routePath-strict.test.ts +0 -166
  26. package/tests/checkMenu.test.ts +0 -346
  27. package/tests/checkTable-smoke.test.ts +0 -157
  28. package/tests/cipher.test.ts +0 -249
  29. package/tests/dbDialect-cache.test.ts +0 -23
  30. package/tests/dbDialect.test.ts +0 -46
  31. package/tests/dbHelper-advanced.test.ts +0 -723
  32. package/tests/dbHelper-all-array-types.test.ts +0 -316
  33. package/tests/dbHelper-array-serialization.test.ts +0 -258
  34. package/tests/dbHelper-batch-write.test.ts +0 -90
  35. package/tests/dbHelper-columns.test.ts +0 -234
  36. package/tests/dbHelper-execute.test.ts +0 -187
  37. package/tests/dbHelper-joins.test.ts +0 -221
  38. package/tests/fields-redis-cache.test.ts +0 -127
  39. package/tests/fields-validate.test.ts +0 -99
  40. package/tests/fixtures/scanFilesAddon/node_modules/@befly-addon/demo/apis/sub/b.ts +0 -3
  41. package/tests/fixtures/scanFilesApis/a.ts +0 -3
  42. package/tests/fixtures/scanFilesApis/sub/b.ts +0 -3
  43. package/tests/getClientIp.test.ts +0 -54
  44. package/tests/integration.test.ts +0 -189
  45. package/tests/jwt.test.ts +0 -65
  46. package/tests/loadPlugins-order-smoke.test.ts +0 -75
  47. package/tests/logger.test.ts +0 -325
  48. package/tests/redisHelper.test.ts +0 -495
  49. package/tests/redisKeys.test.ts +0 -9
  50. package/tests/scanConfig.test.ts +0 -144
  51. package/tests/scanFiles-routePath.test.ts +0 -46
  52. package/tests/smoke-sql.test.ts +0 -24
  53. package/tests/sqlBuilder-advanced.test.ts +0 -608
  54. package/tests/sqlBuilder.test.ts +0 -209
  55. package/tests/sync-connection.test.ts +0 -183
  56. package/tests/sync-init-guard.test.ts +0 -105
  57. package/tests/syncApi-insBatch-fields-consistent.test.ts +0 -61
  58. package/tests/syncApi-obsolete-records.test.ts +0 -69
  59. package/tests/syncApi-type-compat.test.ts +0 -72
  60. package/tests/syncDev-permissions.test.ts +0 -81
  61. package/tests/syncMenu-disableMenus-hard-delete.test.ts +0 -88
  62. package/tests/syncMenu-duplicate-path.test.ts +0 -122
  63. package/tests/syncMenu-obsolete-records.test.ts +0 -161
  64. package/tests/syncMenu-parentPath-from-tree.test.ts +0 -75
  65. package/tests/syncMenu-paths.test.ts +0 -59
  66. package/tests/syncTable-apply.test.ts +0 -279
  67. package/tests/syncTable-array-number.test.ts +0 -160
  68. package/tests/syncTable-constants.test.ts +0 -101
  69. package/tests/syncTable-db-integration.test.ts +0 -237
  70. package/tests/syncTable-ddl.test.ts +0 -245
  71. package/tests/syncTable-helpers.test.ts +0 -99
  72. package/tests/syncTable-schema.test.ts +0 -99
  73. package/tests/syncTable-testkit.test.ts +0 -25
  74. package/tests/syncTable-types.test.ts +0 -122
  75. package/tests/tableRef-and-deserialize.test.ts +0 -67
  76. package/tests/util.test.ts +0 -100
  77. package/tests/validator-array-number.test.ts +0 -310
  78. package/tests/validator-default.test.ts +0 -373
  79. package/tests/validator.test.ts +0 -679
@@ -1,338 +1,8 @@
1
- # Quickstart 快速入门
1
+ # Quickstart 快速入门(已迁移)
2
2
 
3
- > 5 分钟搭建你的第一个 Befly API 服务
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 规则等都以当前实现为准)。
@@ -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` 访问:
@@ -379,7 +379,7 @@ NODE_ENV=production bun run start
379
379
  },
380
380
 
381
381
  "redis": {
382
- "prefix": "myapp:"
382
+ "prefix": "myapp"
383
383
  },
384
384
 
385
385
  "cors": {
@@ -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: "deprecated" }, "配置项已弃用");
396
+ Logger.warn({ config: "invalidOption" }, "配置项不合法");
397
397
 
398
398
  // error: 操作失败
399
399
  Logger.error({ err: error }, "数据库连接失败");
@@ -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
- 通常无需单独调用:`syncData()` 会按顺序执行 `syncApi` → `syncMenu` → `syncDev`。
118
+ 通常无需单独调用:服务启动流程会按顺序执行 `syncTable` `syncApi` → `syncMenu` → `syncDev` → `syncCache`。
107
119
 
108
- 如需在代码中手动触发整套数据同步:
120
+ 如需在代码中手动调用:
109
121
 
110
122
  ```typescript
111
- import { syncData } from "../sync/syncData.js";
123
+ import { syncApi } from "../sync/syncApi.js";
124
+ import { scanSources } from "../utils/scanSources.js";
112
125
 
113
- await syncData();
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
- ### API 信息提取
154
+ ### 存储字段(重要)
141
155
 
142
- API 文件中提取以下信息:
156
+ `syncApi` 会把扫描到的 API 信息同步到 `addon_admin_api` 表,核心字段为:
143
157
 
144
- ```typescript
145
- interface ApiInfo {
146
- name: string; // 接口名称(name 属性)
147
- path: string; // 路由路径(由文件路径生成)
148
- method: string; // 请求方法(method 属性,默认 POST
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`,通常由 `syncData()` 统一触发。
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`,通常由 `syncData()` 统一触发。
280
+ 同 `syncApi`,通常由启动流程统一触发。
260
281
 
261
282
  ### 同步逻辑
262
283
 
263
284
  ```
264
285
  ┌─────────────────────────────────────────────────────┐
265
- syncDev
286
+ syncDev
266
287
  ├─────────────────────────────────────────────────────┤
267
- 1. 创建/更新开发角色:
268
- - 角色名称:开发者
269
- - 角色标识:dev
270
- - 权限:所有菜单 + 所有 API
271
-
272
- 2. 获取所有菜单 ID 列表
273
-
274
- 3. 获取所有 API ID 列表
275
-
276
- 4. 更新角色权限:
277
- - menus: 所有菜单 ID
278
- - apis: 所有 API ID │
279
-
280
- 5. 创建/更新开发管理员:
281
- - 用户名:dev
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
- ```typescript
292
- // befly.config.ts
293
- export default {
294
- dev: {
295
- username: "dev", // 开发账户用户名
296
- password: "dev123456" // 开发账户密码
297
- }
298
- };
312
+ ```json
313
+ {
314
+ "devEmail": "dev@qq.com",
315
+ "devPassword": "beflydev123456"
316
+ }
299
317
  ```
300
318
 
301
- await syncTable(ctx, sources.tables);
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 { syncData } from "./sync/syncData";
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 syncTable(ctx, sources.tables);
316
- await syncData();
347
+ const checkedMenus = await checkMenu(sources.addons, { disableMenus: ctx.config.disableMenus || [] });
317
348
 
318
- // 说明:syncData 内部会固定顺序执行:syncApi → syncMenu → syncDev
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
- Sync 命令会自动管理数据库和 Redis 连接:
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
- ```typescript
442
- // befly.config.ts
443
- export default {
444
- dev: {
445
- username: "dev",
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);
@@ -567,7 +567,7 @@ await syncTable(ctx, sources.tables);
567
567
 
568
568
  ### 安全机制
569
569
 
570
- 1. **禁止危险类型变更**:不允许从 `BIGINT` 改为 `VARCHAR` 等不兼容变更
570
+ 1. **禁止危险类型变更**:不允许从 `BIGINT` 改为 `VARCHAR` 等高风险变更
571
571
  2. **长度收缩保护**:默认跳过长度收缩,避免数据截断
572
572
  3. **保留字段保护**:不允许定义系统保留字段
573
573