befly 3.10.0 → 3.10.1
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/README.md +10 -13
- 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 +3 -3
- package/docs/cipher.md +0 -582
- package/docs/database.md +0 -1176
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
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "befly",
|
|
3
|
-
"version": "3.10.
|
|
4
|
-
"gitHead": "
|
|
3
|
+
"version": "3.10.1",
|
|
4
|
+
"gitHead": "123125b9d7a6c26879a5b5c9d3ac05e2082141c6",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Befly - 为 Bun 专属打造的 TypeScript API 接口框架核心引擎",
|
|
7
7
|
"keywords": [
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"typecheck": "bunx tsgo --noEmit"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"befly-shared": "1.
|
|
66
|
+
"befly-shared": "1.3.0",
|
|
67
67
|
"chalk": "^5.6.2",
|
|
68
68
|
"es-toolkit": "^1.43.0",
|
|
69
69
|
"fast-jwt": "^6.1.0",
|