befly 3.9.40 → 3.10.0
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 +39 -8
- package/befly.config.ts +19 -2
- package/checks/checkApi.ts +79 -77
- package/checks/checkHook.ts +48 -0
- package/checks/checkMenu.ts +168 -0
- package/checks/checkPlugin.ts +48 -0
- package/checks/checkTable.ts +137 -183
- package/docs/README.md +1 -1
- package/docs/api/api.md +1 -1
- package/docs/guide/quickstart.md +16 -9
- package/docs/hooks/hook.md +2 -2
- package/docs/hooks/rateLimit.md +1 -1
- package/docs/infra/redis.md +7 -7
- package/docs/plugins/plugin.md +23 -21
- package/docs/quickstart.md +16 -9
- package/docs/reference/addon.md +12 -1
- package/docs/reference/config.md +13 -30
- package/docs/reference/sync.md +62 -193
- package/docs/reference/table.md +27 -29
- package/hooks/auth.ts +3 -4
- package/hooks/cors.ts +4 -6
- package/hooks/parser.ts +3 -4
- package/hooks/permission.ts +3 -4
- package/hooks/validator.ts +3 -4
- package/lib/cacheHelper.ts +89 -153
- package/lib/cacheKeys.ts +1 -1
- package/lib/connect.ts +9 -13
- package/lib/dbDialect.ts +285 -0
- package/lib/dbHelper.ts +179 -507
- package/lib/dbUtils.ts +450 -0
- package/lib/logger.ts +41 -5
- package/lib/redisHelper.ts +1 -0
- package/lib/sqlBuilder.ts +358 -58
- package/lib/sqlCheck.ts +136 -0
- package/lib/validator.ts +1 -1
- package/loader/loadApis.ts +23 -126
- package/loader/loadHooks.ts +31 -46
- package/loader/loadPlugins.ts +37 -52
- package/main.ts +58 -19
- package/package.json +24 -25
- package/paths.ts +14 -14
- package/plugins/cache.ts +12 -6
- package/plugins/cipher.ts +2 -2
- package/plugins/config.ts +6 -8
- package/plugins/db.ts +14 -19
- package/plugins/jwt.ts +6 -7
- package/plugins/logger.ts +7 -9
- package/plugins/redis.ts +8 -10
- package/plugins/tool.ts +3 -4
- package/router/api.ts +3 -2
- package/router/static.ts +7 -5
- package/sync/syncApi.ts +80 -235
- package/sync/syncCache.ts +16 -0
- package/sync/syncDev.ts +167 -202
- package/sync/syncMenu.ts +230 -444
- package/sync/syncTable.ts +1247 -0
- package/tests/_mocks/mockSqliteDb.ts +204 -0
- package/tests/addonHelper-cache.test.ts +32 -0
- package/tests/apiHandler-routePath-only.test.ts +32 -0
- package/tests/cacheHelper.test.ts +16 -51
- package/tests/checkApi-routePath-strict.test.ts +166 -0
- package/tests/checkMenu.test.ts +346 -0
- package/tests/checkTable-smoke.test.ts +157 -0
- package/tests/dbDialect-cache.test.ts +23 -0
- package/tests/dbDialect.test.ts +46 -0
- package/tests/dbHelper-advanced.test.ts +1 -1
- package/tests/dbHelper-all-array-types.test.ts +15 -15
- package/tests/dbHelper-batch-write.test.ts +90 -0
- package/tests/dbHelper-columns.test.ts +36 -54
- package/tests/dbHelper-execute.test.ts +26 -26
- package/tests/dbHelper-joins.test.ts +85 -176
- package/tests/fixtures/scanFilesAddon/node_modules/@befly-addon/demo/apis/sub/b.ts +3 -0
- package/tests/fixtures/scanFilesApis/a.ts +3 -0
- package/tests/fixtures/scanFilesApis/sub/b.ts +3 -0
- package/tests/loadPlugins-order-smoke.test.ts +75 -0
- package/tests/logger.test.ts +6 -6
- package/tests/redisHelper.test.ts +6 -1
- package/tests/scanFiles-routePath.test.ts +46 -0
- package/tests/smoke-sql.test.ts +24 -0
- package/tests/sqlBuilder-advanced.test.ts +18 -5
- package/tests/sqlBuilder.test.ts +24 -0
- package/tests/sync-init-guard.test.ts +105 -0
- package/tests/syncApi-insBatch-fields-consistent.test.ts +61 -0
- package/tests/syncApi-obsolete-records.test.ts +69 -0
- package/tests/syncApi-type-compat.test.ts +72 -0
- package/tests/syncDev-permissions.test.ts +81 -0
- package/tests/syncMenu-disableMenus-hard-delete.test.ts +88 -0
- package/tests/syncMenu-duplicate-path.test.ts +122 -0
- package/tests/syncMenu-obsolete-records.test.ts +161 -0
- package/tests/syncMenu-parentPath-from-tree.test.ts +75 -0
- package/tests/syncMenu-paths.test.ts +0 -9
- package/tests/{syncDb-apply.test.ts → syncTable-apply.test.ts} +14 -24
- package/tests/{syncDb-array-number.test.ts → syncTable-array-number.test.ts} +31 -31
- package/tests/syncTable-constants.test.ts +101 -0
- package/tests/syncTable-db-integration.test.ts +237 -0
- package/tests/{syncDb-ddl.test.ts → syncTable-ddl.test.ts} +67 -53
- package/tests/{syncDb-helpers.test.ts → syncTable-helpers.test.ts} +12 -26
- package/tests/syncTable-schema.test.ts +99 -0
- package/tests/syncTable-testkit.test.ts +25 -0
- package/tests/syncTable-types.test.ts +122 -0
- package/tests/tableRef-and-deserialize.test.ts +67 -0
- package/tsconfig.json +1 -1
- package/types/api.d.ts +1 -1
- package/types/befly.d.ts +13 -12
- package/types/cache.d.ts +2 -2
- package/types/context.d.ts +1 -1
- package/types/database.d.ts +0 -5
- package/types/hook.d.ts +1 -10
- package/types/plugin.d.ts +2 -96
- package/types/sync.d.ts +19 -25
- package/utils/convertBigIntFields.ts +38 -0
- package/utils/disableMenusGlob.ts +85 -0
- package/utils/importDefault.ts +21 -0
- package/utils/isDirentDirectory.ts +23 -0
- package/utils/loadMenuConfigs.ts +145 -0
- package/utils/processFields.ts +25 -0
- package/utils/scanAddons.ts +72 -0
- package/utils/scanFiles.ts +129 -21
- package/utils/scanSources.ts +64 -0
- package/utils/sortModules.ts +137 -0
- package/checks/checkApp.ts +0 -55
- package/hooks/rateLimit.ts +0 -276
- package/sync/syncAll.ts +0 -35
- package/sync/syncDb/apply.ts +0 -192
- package/sync/syncDb/constants.ts +0 -119
- package/sync/syncDb/ddl.ts +0 -251
- package/sync/syncDb/helpers.ts +0 -84
- package/sync/syncDb/schema.ts +0 -202
- package/sync/syncDb/sqlite.ts +0 -48
- package/sync/syncDb/table.ts +0 -207
- package/sync/syncDb/tableCreate.ts +0 -163
- package/sync/syncDb/types.ts +0 -132
- package/sync/syncDb/version.ts +0 -69
- package/sync/syncDb.ts +0 -168
- package/tests/rateLimit-hook.test.ts +0 -477
- package/tests/syncDb-constants.test.ts +0 -130
- package/tests/syncDb-schema.test.ts +0 -179
- package/tests/syncDb-types.test.ts +0 -139
- package/utils/addonHelper.ts +0 -90
- package/utils/modules.ts +0 -98
- package/utils/route.ts +0 -23
package/docs/plugins/plugin.md
CHANGED
|
@@ -72,7 +72,7 @@ import type { Plugin } from "befly/types/plugin";
|
|
|
72
72
|
|
|
73
73
|
const plugin: Plugin = {
|
|
74
74
|
// 依赖的插件列表(可选)
|
|
75
|
-
|
|
75
|
+
deps: ["logger", "db"],
|
|
76
76
|
|
|
77
77
|
// 初始化函数(必填)
|
|
78
78
|
handler: (befly) => {
|
|
@@ -96,10 +96,10 @@ interface Plugin {
|
|
|
96
96
|
name?: string;
|
|
97
97
|
|
|
98
98
|
/** 依赖的插件列表(在这些插件之后执行) */
|
|
99
|
-
|
|
99
|
+
deps: string[];
|
|
100
100
|
|
|
101
101
|
/** 插件初始化函数 */
|
|
102
|
-
handler
|
|
102
|
+
handler: (context: BeflyContext) => any | Promise<any>;
|
|
103
103
|
|
|
104
104
|
/** 插件描述(可选) */
|
|
105
105
|
description?: string;
|
|
@@ -171,12 +171,12 @@ interface Plugin {
|
|
|
171
171
|
|
|
172
172
|
### 依赖排序
|
|
173
173
|
|
|
174
|
-
使用 `
|
|
174
|
+
使用 `deps` 属性声明依赖关系:
|
|
175
175
|
|
|
176
176
|
```typescript
|
|
177
177
|
// redis.ts - 依赖 logger
|
|
178
178
|
const plugin: Plugin = {
|
|
179
|
-
|
|
179
|
+
deps: ["logger"], // 在 logger 插件之后初始化
|
|
180
180
|
handler: () => {
|
|
181
181
|
/* ... */
|
|
182
182
|
}
|
|
@@ -199,7 +199,7 @@ const plugin: Plugin = {
|
|
|
199
199
|
```typescript
|
|
200
200
|
// 插件源码
|
|
201
201
|
const loggerPlugin: Plugin = {
|
|
202
|
-
|
|
202
|
+
deps: [],
|
|
203
203
|
async handler(): Promise<typeof Logger> {
|
|
204
204
|
if (beflyConfig.logger) {
|
|
205
205
|
Logger.configure(beflyConfig.logger);
|
|
@@ -250,10 +250,11 @@ const redisConfig = befly.config.redis;
|
|
|
250
250
|
```typescript
|
|
251
251
|
// 插件源码
|
|
252
252
|
const dbPlugin: Plugin = {
|
|
253
|
-
|
|
253
|
+
deps: ["logger", "redis"],
|
|
254
254
|
async handler(befly: BeflyContext): Promise<DbHelper> {
|
|
255
|
-
|
|
256
|
-
|
|
255
|
+
// 连接由启动期统一完成;插件仅消费已连接实例
|
|
256
|
+
const sql = Connect.getSql();
|
|
257
|
+
return new DbHelper({ redis: befly.redis, sql: sql, dialect: new MySqlDialect() });
|
|
257
258
|
}
|
|
258
259
|
};
|
|
259
260
|
```
|
|
@@ -285,9 +286,10 @@ await befly.db.delData({ table: "user", where: { id: 1 } });
|
|
|
285
286
|
```typescript
|
|
286
287
|
// 插件源码
|
|
287
288
|
const redisPlugin: Plugin = {
|
|
288
|
-
|
|
289
|
+
deps: ["logger"],
|
|
289
290
|
async handler(): Promise<RedisHelper | Record<string, never>> {
|
|
290
|
-
|
|
291
|
+
// 连接由启动期统一完成;插件仅校验连接存在
|
|
292
|
+
Connect.getRedis();
|
|
291
293
|
return new RedisHelper(redisConfig.prefix);
|
|
292
294
|
}
|
|
293
295
|
};
|
|
@@ -384,9 +386,9 @@ const decrypted = befly.cipher.decrypt(encrypted);
|
|
|
384
386
|
```typescript
|
|
385
387
|
// 插件源码
|
|
386
388
|
const cachePlugin: Plugin = {
|
|
387
|
-
|
|
389
|
+
deps: ["logger", "redis", "db"],
|
|
388
390
|
async handler(befly: BeflyContext): Promise<CacheHelper> {
|
|
389
|
-
return new CacheHelper(befly);
|
|
391
|
+
return new CacheHelper({ db: befly.db, redis: befly.redis });
|
|
390
392
|
}
|
|
391
393
|
};
|
|
392
394
|
```
|
|
@@ -473,7 +475,7 @@ import type { Plugin } from "befly/types/plugin";
|
|
|
473
475
|
import type { BeflyContext } from "befly/types/befly";
|
|
474
476
|
|
|
475
477
|
const plugin: Plugin = {
|
|
476
|
-
|
|
478
|
+
deps: ["db", "redis"], // 依赖数据库和 Redis
|
|
477
479
|
handler: (befly: BeflyContext) => {
|
|
478
480
|
return {
|
|
479
481
|
async getUser(id: number) {
|
|
@@ -513,7 +515,7 @@ import type { Plugin } from "befly/types/plugin";
|
|
|
513
515
|
import { Client } from "@elastic/elasticsearch";
|
|
514
516
|
|
|
515
517
|
const plugin: Plugin = {
|
|
516
|
-
|
|
518
|
+
deps: ["logger", "config"],
|
|
517
519
|
async handler(befly) {
|
|
518
520
|
const config = befly.config.elasticsearch || {};
|
|
519
521
|
|
|
@@ -580,7 +582,7 @@ class SmsHelper {
|
|
|
580
582
|
}
|
|
581
583
|
|
|
582
584
|
const plugin: Plugin = {
|
|
583
|
-
|
|
585
|
+
deps: ["logger", "config"],
|
|
584
586
|
handler: (befly: BeflyContext) => {
|
|
585
587
|
const smsConfig = befly.config.sms || {};
|
|
586
588
|
return new SmsHelper(befly, smsConfig);
|
|
@@ -688,7 +690,7 @@ class EmailHelper {
|
|
|
688
690
|
* 邮件插件
|
|
689
691
|
*/
|
|
690
692
|
const emailPlugin: Plugin = {
|
|
691
|
-
|
|
693
|
+
deps: ["db", "logger", "config"],
|
|
692
694
|
async handler(befly: BeflyContext): Promise<EmailHelper> {
|
|
693
695
|
const emailConfig = befly.config?.addons?.admin?.email || {};
|
|
694
696
|
return new EmailHelper(befly, emailConfig);
|
|
@@ -801,7 +803,7 @@ class WechatPayHelper {
|
|
|
801
803
|
}
|
|
802
804
|
|
|
803
805
|
const plugin: Plugin = {
|
|
804
|
-
|
|
806
|
+
deps: ["logger", "config"],
|
|
805
807
|
handler: (befly: BeflyContext) => {
|
|
806
808
|
return new WechatPayHelper(befly);
|
|
807
809
|
}
|
|
@@ -851,7 +853,7 @@ const plugin: Plugin = {
|
|
|
851
853
|
```typescript
|
|
852
854
|
// ✅ 推荐:明确声明所有依赖
|
|
853
855
|
const plugin: Plugin = {
|
|
854
|
-
|
|
856
|
+
deps: ["logger", "db", "redis"], // 声明所有使用的插件
|
|
855
857
|
handler: (befly) => {
|
|
856
858
|
/* ... */
|
|
857
859
|
}
|
|
@@ -929,7 +931,7 @@ class DatabasePool {
|
|
|
929
931
|
插件按以下顺序加载:
|
|
930
932
|
|
|
931
933
|
1. 核心插件 → Addon 插件 → 项目插件
|
|
932
|
-
2. 同一类型内根据 `
|
|
934
|
+
2. 同一类型内根据 `deps` 依赖关系排序
|
|
933
935
|
3. 无依赖的插件按文件名字母顺序
|
|
934
936
|
|
|
935
937
|
### Q2: 如何在插件中访问其他插件?
|
|
@@ -938,7 +940,7 @@ class DatabasePool {
|
|
|
938
940
|
|
|
939
941
|
```typescript
|
|
940
942
|
const plugin: Plugin = {
|
|
941
|
-
|
|
943
|
+
deps: ["db"], // 声明依赖
|
|
942
944
|
handler: (befly) => {
|
|
943
945
|
return {
|
|
944
946
|
async getUser(id: number) {
|
package/docs/quickstart.md
CHANGED
|
@@ -208,15 +208,24 @@ CREATE DATABASE my_api CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
208
208
|
|
|
209
209
|
## 同步数据库
|
|
210
210
|
|
|
211
|
-
###
|
|
211
|
+
### 自动同步
|
|
212
212
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
服务启动时会在**主进程**自动执行同步流程:
|
|
214
|
+
|
|
215
|
+
1. `syncTable()`:同步表结构
|
|
216
|
+
2. `syncData()`:固定顺序执行 `syncApi` → `syncMenu` → `syncDev`
|
|
216
217
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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();
|
|
220
229
|
```
|
|
221
230
|
|
|
222
231
|
### 验证同步结果
|
|
@@ -299,8 +308,6 @@ curl -X POST http://localhost:3000/api/user/login \
|
|
|
299
308
|
```bash
|
|
300
309
|
# 开发
|
|
301
310
|
bun run dev # 启动开发服务
|
|
302
|
-
bun befly sync # 同步数据库
|
|
303
|
-
bun befly sync:db # 只同步表结构
|
|
304
311
|
|
|
305
312
|
# 生产
|
|
306
313
|
bun run build # 构建
|
package/docs/reference/addon.md
CHANGED
|
@@ -467,7 +467,18 @@ A: 在配置文件中设置:
|
|
|
467
467
|
|
|
468
468
|
### Q: Addon 的表如何迁移?
|
|
469
469
|
|
|
470
|
-
A:
|
|
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
|
+
```
|
|
471
482
|
|
|
472
483
|
### Q: 如何在 Addon 中访问项目配置?
|
|
473
484
|
|
package/docs/reference/config.md
CHANGED
|
@@ -207,14 +207,14 @@ befly.development.json 或 befly.production.json(环境配置)
|
|
|
207
207
|
|
|
208
208
|
### Redis 配置 (redis)
|
|
209
209
|
|
|
210
|
-
| 配置项 | 类型 | 默认值
|
|
211
|
-
| ---------- | ------ |
|
|
212
|
-
| `host` | string | `'127.0.0.1'`
|
|
213
|
-
| `port` | number | `6379`
|
|
214
|
-
| `username` | string | `''`
|
|
215
|
-
| `password` | string | `''`
|
|
216
|
-
| `db` | number | `0`
|
|
217
|
-
| `prefix` | string | `'befly_demo
|
|
210
|
+
| 配置项 | 类型 | 默认值 | 说明 |
|
|
211
|
+
| ---------- | ------ | -------------- | ------------------------------------------------------ |
|
|
212
|
+
| `host` | string | `'127.0.0.1'` | Redis 主机 |
|
|
213
|
+
| `port` | number | `6379` | Redis 端口 |
|
|
214
|
+
| `username` | string | `''` | Redis 用户名 |
|
|
215
|
+
| `password` | string | `''` | Redis 密码 |
|
|
216
|
+
| `db` | number | `0` | Redis 数据库索引 |
|
|
217
|
+
| `prefix` | string | `'befly_demo'` | Redis Key 前缀(不允许包含 `:`,分隔符由系统自动拼接) |
|
|
218
218
|
|
|
219
219
|
```json
|
|
220
220
|
{
|
|
@@ -223,7 +223,7 @@ befly.development.json 或 befly.production.json(环境配置)
|
|
|
223
223
|
"port": 6379,
|
|
224
224
|
"password": "redis_password",
|
|
225
225
|
"db": 1,
|
|
226
|
-
"prefix": "myapp
|
|
226
|
+
"prefix": "myapp"
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
229
|
```
|
|
@@ -295,13 +295,11 @@ befly.development.json 或 befly.production.json(环境配置)
|
|
|
295
295
|
| ---------------- | -------- | ------ | -------------- |
|
|
296
296
|
| `disableHooks` | string[] | `[]` | 禁用的钩子列表 |
|
|
297
297
|
| `disablePlugins` | string[] | `[]` | 禁用的插件列表 |
|
|
298
|
-
| `hiddenMenus` | string[] | `[]` | 隐藏的菜单路径 |
|
|
299
298
|
|
|
300
299
|
```json
|
|
301
300
|
{
|
|
302
301
|
"disableHooks": ["requestLogger"],
|
|
303
|
-
"disablePlugins": ["redis"]
|
|
304
|
-
"hiddenMenus": ["/admin/debug", "/admin/test"]
|
|
302
|
+
"disablePlugins": ["redis"]
|
|
305
303
|
}
|
|
306
304
|
```
|
|
307
305
|
|
|
@@ -464,30 +462,15 @@ export default {
|
|
|
464
462
|
### 在插件中访问
|
|
465
463
|
|
|
466
464
|
```typescript
|
|
467
|
-
import { beflyConfig } from "../befly.config.js";
|
|
468
|
-
|
|
469
465
|
const plugin: Plugin = {
|
|
470
|
-
handler: () => {
|
|
471
|
-
const port =
|
|
472
|
-
const dbConfig =
|
|
466
|
+
handler: (context) => {
|
|
467
|
+
const port = context.config.appPort;
|
|
468
|
+
const dbConfig = context.config.db;
|
|
473
469
|
// ...
|
|
474
470
|
}
|
|
475
471
|
};
|
|
476
472
|
```
|
|
477
473
|
|
|
478
|
-
### 直接导入(仅 Befly 源码/单仓内)
|
|
479
|
-
|
|
480
|
-
> 说明:`befly` 包的 `exports` 仅暴露 `befly`、`befly/lib/*`、`befly/utils/*`、`befly/types/*`。
|
|
481
|
-
> 因此不支持 `befly/befly.config` 这种子路径导入。
|
|
482
|
-
|
|
483
|
-
如果你在 Befly 源码/单仓内开发(例如编写内置插件/命令),可以使用相对路径导入:
|
|
484
|
-
|
|
485
|
-
```typescript
|
|
486
|
-
import { beflyConfig } from "../befly.config.js";
|
|
487
|
-
|
|
488
|
-
console.log(beflyConfig.appName);
|
|
489
|
-
```
|
|
490
|
-
|
|
491
474
|
---
|
|
492
475
|
|
|
493
476
|
## 最佳实践
|
package/docs/reference/sync.md
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
# Sync
|
|
1
|
+
# Sync 同步流程
|
|
2
2
|
|
|
3
3
|
> 数据库结构、API路由、菜单配置、开发账户同步
|
|
4
4
|
|
|
5
5
|
## 目录
|
|
6
6
|
|
|
7
7
|
- [概述](#概述)
|
|
8
|
-
- [
|
|
9
|
-
- [syncDb 数据库同步](#syncdb-数据库同步)
|
|
8
|
+
- [syncTable 数据库同步](#synctable-数据库同步)
|
|
10
9
|
- [syncApi 接口同步](#syncapi-接口同步)
|
|
11
10
|
- [syncMenu 菜单同步](#syncmenu-菜单同步)
|
|
12
11
|
- [syncDev 开发账户同步](#syncdev-开发账户同步)
|
|
13
|
-
- [命令行使用](#命令行使用)
|
|
14
12
|
- [表名规则](#表名规则)
|
|
15
13
|
- [注意事项](#注意事项)
|
|
16
14
|
- [FAQ](#faq)
|
|
@@ -21,103 +19,52 @@
|
|
|
21
19
|
|
|
22
20
|
Sync 同步系统用于将代码定义同步到数据库,包括:
|
|
23
21
|
|
|
24
|
-
| 命令
|
|
25
|
-
|
|
|
26
|
-
| `
|
|
27
|
-
| `syncApi`
|
|
28
|
-
| `syncMenu`
|
|
29
|
-
| `syncDev`
|
|
30
|
-
| `syncAll` | 依次执行以上全部 | - |
|
|
22
|
+
| 命令 | 功能 | 目标表 |
|
|
23
|
+
| ----------- | ----------------- | --------------------------------------- |
|
|
24
|
+
| `syncTable` | 同步表结构定义 | 所有业务表 |
|
|
25
|
+
| `syncApi` | 同步 API 路由信息 | `addon_admin_api` |
|
|
26
|
+
| `syncMenu` | 同步菜单配置 | `addon_admin_menu` |
|
|
27
|
+
| `syncDev` | 创建开发者账户 | `addon_admin_role`, `addon_admin_admin` |
|
|
31
28
|
|
|
32
|
-
**执行顺序**:`
|
|
29
|
+
**执行顺序**:`syncTable` → `syncApi` → `syncMenu` → `syncDev`
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## syncAll 全量同步
|
|
37
|
-
|
|
38
|
-
一键执行所有同步命令:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
# 执行全量同步
|
|
42
|
-
befly sync
|
|
43
|
-
|
|
44
|
-
# 等同于依次执行:
|
|
45
|
-
# 1. checkApp - 检查应用配置
|
|
46
|
-
# 2. syncDb - 同步数据库表结构
|
|
47
|
-
# 3. syncApi - 同步 API 路由
|
|
48
|
-
# 4. syncMenu - 同步菜单配置
|
|
49
|
-
# 5. syncDev - 同步开发账户
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
**执行流程**:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
┌──────────────────────────────────────────────────┐
|
|
56
|
-
│ syncAll │
|
|
57
|
-
├──────────────────────────────────────────────────┤
|
|
58
|
-
│ 1. checkApp() 检查应用配置是否完整 │
|
|
59
|
-
│ ↓ │
|
|
60
|
-
│ 2. syncDbCommand() 同步数据库表结构 │
|
|
61
|
-
│ ↓ │
|
|
62
|
-
│ 3. syncApiCommand() 同步 API 路由到数据库 │
|
|
63
|
-
│ ↓ │
|
|
64
|
-
│ 4. syncMenuCommand() 同步菜单配置到数据库 │
|
|
65
|
-
│ ↓ │
|
|
66
|
-
│ 5. syncDevCommand() 创建/更新开发者账户 │
|
|
67
|
-
└──────────────────────────────────────────────────┘
|
|
68
|
-
```
|
|
31
|
+
> 说明:当前版本不提供 CLI 同步命令;同步逻辑在服务启动时由主进程自动执行(见 `packages/core/main.ts`)。
|
|
69
32
|
|
|
70
33
|
---
|
|
71
34
|
|
|
72
|
-
##
|
|
35
|
+
## syncTable 数据库同步
|
|
73
36
|
|
|
74
37
|
将 `tables/*.json` 表定义同步到数据库结构。
|
|
75
38
|
|
|
76
39
|
### 基本用法
|
|
77
40
|
|
|
78
|
-
|
|
79
|
-
# 同步所有表
|
|
80
|
-
befly sync:db
|
|
81
|
-
|
|
82
|
-
# 只同步指定表
|
|
83
|
-
befly sync:db --table user
|
|
41
|
+
默认会在服务启动时自动执行(仅主进程)。如需在代码中手动执行:
|
|
84
42
|
|
|
85
|
-
|
|
86
|
-
|
|
43
|
+
```typescript
|
|
44
|
+
import { syncTable } from "../sync/syncTable.js";
|
|
45
|
+
import { scanSources } from "../utils/scanSources.js";
|
|
87
46
|
|
|
88
|
-
|
|
89
|
-
|
|
47
|
+
// ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.config)
|
|
48
|
+
const sources = await scanSources();
|
|
49
|
+
await syncTable(ctx, sources.tables);
|
|
90
50
|
```
|
|
91
51
|
|
|
92
52
|
### 命令选项
|
|
93
53
|
|
|
94
|
-
|
|
95
|
-
| ----------- | ------- | ------ | -------------------- |
|
|
96
|
-
| `--table` | string | - | 只同步指定表 |
|
|
97
|
-
| `--force` | boolean | false | 强制模式,允许删除列 |
|
|
98
|
-
| `--dry-run` | boolean | false | 预览模式,不实际执行 |
|
|
54
|
+
无
|
|
99
55
|
|
|
100
56
|
### 同步逻辑
|
|
101
57
|
|
|
102
58
|
```
|
|
103
59
|
┌─────────────────────────────────────────────────────┐
|
|
104
|
-
│
|
|
60
|
+
│ syncTable │
|
|
105
61
|
├─────────────────────────────────────────────────────┤
|
|
106
|
-
│ 1.
|
|
107
|
-
│ 2.
|
|
108
|
-
│ 3.
|
|
109
|
-
│ 4. 确保版本表存在 (ensureDbVersion) │
|
|
110
|
-
│ ↓ │
|
|
111
|
-
│ 5. 扫描表定义文件: │
|
|
112
|
-
│ - 项目表:tpl/tables/*.json │
|
|
113
|
-
│ - Addon 表:addons/*/tables/*.json │
|
|
114
|
-
│ ↓ │
|
|
115
|
-
│ 6. 对每个表: │
|
|
62
|
+
│ 1. 校验 ctx.db / ctx.redis / ctx.config │
|
|
63
|
+
│ 2. 检查数据库版本 (ensureDbVersion) │
|
|
64
|
+
│ 3. 同步传入的表定义列表(通常来自 scanSources) │
|
|
116
65
|
│ ├── 表存在?→ modifyTable (修改) │
|
|
117
66
|
│ └── 表不存在?→ createTable (新建) │
|
|
118
|
-
│
|
|
119
|
-
│ 7. 清理 Redis 缓存 (tableColumns) │
|
|
120
|
-
│ 8. 关闭数据库连接 │
|
|
67
|
+
│ 4. 清理 Redis 缓存 (tableColumns) │
|
|
121
68
|
└─────────────────────────────────────────────────────┘
|
|
122
69
|
```
|
|
123
70
|
|
|
@@ -156,19 +103,15 @@ befly sync:db --dry-run
|
|
|
156
103
|
|
|
157
104
|
### 基本用法
|
|
158
105
|
|
|
159
|
-
|
|
160
|
-
# 同步 API 路由
|
|
161
|
-
befly sync:api
|
|
106
|
+
通常无需单独调用:`syncData()` 会按顺序执行 `syncApi` → `syncMenu` → `syncDev`。
|
|
162
107
|
|
|
163
|
-
|
|
164
|
-
befly sync:api --plan
|
|
165
|
-
```
|
|
108
|
+
如需在代码中手动触发整套数据同步:
|
|
166
109
|
|
|
167
|
-
|
|
110
|
+
```typescript
|
|
111
|
+
import { syncData } from "../sync/syncData.js";
|
|
168
112
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
| `--plan` | boolean | false | 预览模式,显示变更计划 |
|
|
113
|
+
await syncData();
|
|
114
|
+
```
|
|
172
115
|
|
|
173
116
|
### 同步逻辑
|
|
174
117
|
|
|
@@ -228,19 +171,7 @@ interface SyncApiStats {
|
|
|
228
171
|
|
|
229
172
|
### 基本用法
|
|
230
173
|
|
|
231
|
-
|
|
232
|
-
# 同步菜单
|
|
233
|
-
befly sync:menu
|
|
234
|
-
|
|
235
|
-
# 预览模式
|
|
236
|
-
befly sync:menu --plan
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### 命令选项
|
|
240
|
-
|
|
241
|
-
| 选项 | 类型 | 默认值 | 说明 |
|
|
242
|
-
| -------- | ------- | ------ | ---------------------- |
|
|
243
|
-
| `--plan` | boolean | false | 预览模式,显示变更计划 |
|
|
174
|
+
同 `syncApi`,通常由 `syncData()` 统一触发。
|
|
244
175
|
|
|
245
176
|
### 菜单配置文件
|
|
246
177
|
|
|
@@ -325,19 +256,7 @@ interface SyncMenuStats {
|
|
|
325
256
|
|
|
326
257
|
### 基本用法
|
|
327
258
|
|
|
328
|
-
|
|
329
|
-
# 同步开发账户
|
|
330
|
-
befly sync:dev
|
|
331
|
-
|
|
332
|
-
# 预览模式
|
|
333
|
-
befly sync:dev --plan
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
### 命令选项
|
|
337
|
-
|
|
338
|
-
| 选项 | 类型 | 默认值 | 说明 |
|
|
339
|
-
| -------- | ------- | ------ | ---------------------- |
|
|
340
|
-
| `--plan` | boolean | false | 预览模式,显示变更计划 |
|
|
259
|
+
同 `syncApi`,通常由 `syncData()` 统一触发。
|
|
341
260
|
|
|
342
261
|
### 同步逻辑
|
|
343
262
|
|
|
@@ -379,50 +298,24 @@ export default {
|
|
|
379
298
|
};
|
|
380
299
|
```
|
|
381
300
|
|
|
382
|
-
|
|
301
|
+
await syncTable(ctx, sources.tables);
|
|
383
302
|
|
|
384
303
|
---
|
|
385
304
|
|
|
386
|
-
##
|
|
387
|
-
|
|
388
|
-
### CLI 命令列表
|
|
305
|
+
## 代码调用
|
|
389
306
|
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
# 单独执行
|
|
395
|
-
befly sync:db # 同步数据库结构
|
|
396
|
-
befly sync:api # 同步 API 路由
|
|
397
|
-
befly sync:menu # 同步菜单配置
|
|
398
|
-
befly sync:dev # 同步开发账户
|
|
399
|
-
|
|
400
|
-
# 带参数
|
|
401
|
-
befly sync:db --table user # 只同步 user 表
|
|
402
|
-
befly sync:db --force # 强制模式
|
|
403
|
-
befly sync:db --dry-run # 预览模式
|
|
404
|
-
befly sync:api --plan # 预览 API 变更
|
|
405
|
-
befly sync:menu --plan # 预览菜单变更
|
|
406
|
-
befly sync:dev --plan # 预览开发账户变更
|
|
407
|
-
```
|
|
307
|
+
```typescript
|
|
308
|
+
import { syncTable } from "./sync/syncTable.js";
|
|
309
|
+
import { scanSources } from "./utils/scanSources.js";
|
|
310
|
+
import { syncData } from "./sync/syncData";
|
|
408
311
|
|
|
409
|
-
|
|
312
|
+
// 启动前/启动中手动触发同步
|
|
313
|
+
// ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.config)
|
|
314
|
+
const sources = await scanSources();
|
|
315
|
+
await syncTable(ctx, sources.tables);
|
|
316
|
+
await syncData();
|
|
410
317
|
|
|
411
|
-
|
|
412
|
-
import { syncAllCommand } from "./sync/syncAll";
|
|
413
|
-
import { syncDbCommand } from "./sync/syncDb";
|
|
414
|
-
import { syncApiCommand } from "./sync/syncApi";
|
|
415
|
-
import { syncMenuCommand } from "./sync/syncMenu";
|
|
416
|
-
import { syncDevCommand } from "./sync/syncDev";
|
|
417
|
-
|
|
418
|
-
// 全量同步
|
|
419
|
-
await syncAllCommand();
|
|
420
|
-
|
|
421
|
-
// 单独调用
|
|
422
|
-
await syncDbCommand({ table: "user" });
|
|
423
|
-
await syncApiCommand({ plan: true });
|
|
424
|
-
await syncMenuCommand({ plan: true });
|
|
425
|
-
await syncDevCommand({ plan: true });
|
|
318
|
+
// 说明:syncData 内部会固定顺序执行:syncApi → syncMenu → syncDev
|
|
426
319
|
```
|
|
427
320
|
|
|
428
321
|
---
|
|
@@ -464,29 +357,27 @@ addons/demo/tables/article.json → addon_demo_article
|
|
|
464
357
|
|
|
465
358
|
### 1. 执行顺序
|
|
466
359
|
|
|
467
|
-
**必须按顺序执行**:`
|
|
360
|
+
**必须按顺序执行**:`syncTable` → `syncApi` → `syncMenu` → `syncDev`
|
|
468
361
|
|
|
469
|
-
- `syncApi` 依赖 `addon_admin_api` 表(由 `
|
|
470
|
-
- `syncMenu` 依赖 `addon_admin_menu` 表(由 `
|
|
362
|
+
- `syncApi` 依赖 `addon_admin_api` 表(由 `syncTable` 创建)
|
|
363
|
+
- `syncMenu` 依赖 `addon_admin_menu` 表(由 `syncTable` 创建)
|
|
471
364
|
- `syncDev` 依赖角色表和权限数据(由前面命令创建)
|
|
472
365
|
|
|
473
366
|
### 2. 破坏性操作
|
|
474
367
|
|
|
475
|
-
默认模式下,`
|
|
368
|
+
默认模式下,`syncTable` **不会删除列**,只会:
|
|
476
369
|
|
|
477
370
|
- 新增缺失的列
|
|
478
371
|
- 修改现有列的类型/默认值
|
|
479
372
|
|
|
480
|
-
|
|
373
|
+
此外,`syncTable` **不会执行长度收缩等可能导致数据截断的危险变更**:
|
|
481
374
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
befly sync:db --force
|
|
485
|
-
```
|
|
375
|
+
- 例如:`VARCHAR(200)` → `VARCHAR(50)`
|
|
376
|
+
- 这类变更会被跳过,并输出告警;需要手动评估并处理
|
|
486
377
|
|
|
487
378
|
### 3. 缓存清理
|
|
488
379
|
|
|
489
|
-
`
|
|
380
|
+
`syncTable` 执行后会自动清理 Redis 中的表结构缓存:
|
|
490
381
|
|
|
491
382
|
```typescript
|
|
492
383
|
// 自动清理以下缓存键
|
|
@@ -501,23 +392,13 @@ Sync 命令会自动管理数据库和 Redis 连接:
|
|
|
501
392
|
- 执行后关闭连接
|
|
502
393
|
- 出错时正确清理资源
|
|
503
394
|
|
|
504
|
-
### 5. 预览模式
|
|
505
|
-
|
|
506
|
-
使用 `--dry-run` 或 `--plan` 参数可以预览变更而不实际执行:
|
|
507
|
-
|
|
508
|
-
```bash
|
|
509
|
-
befly sync:db --dry-run # 预览数据库结构变更
|
|
510
|
-
befly sync:api --plan # 预览 API 变更
|
|
511
|
-
befly sync:menu --plan # 预览菜单变更
|
|
512
|
-
```
|
|
513
|
-
|
|
514
395
|
---
|
|
515
396
|
|
|
516
397
|
## FAQ
|
|
517
398
|
|
|
518
399
|
### Q: sync 命令报错 "表不存在" 怎么办?
|
|
519
400
|
|
|
520
|
-
A:
|
|
401
|
+
A: 确保 `syncTable()` 已先执行(服务启动时会自动执行)。`syncApi/syncMenu/syncDev` 依赖对应的表结构存在。
|
|
521
402
|
|
|
522
403
|
### Q: 为什么修改了表定义但数据库没变化?
|
|
523
404
|
|
|
@@ -526,17 +407,11 @@ A: 检查以下几点:
|
|
|
526
407
|
1. JSON 文件语法是否正确
|
|
527
408
|
2. 字段定义格式是否正确
|
|
528
409
|
3. 是否保存了文件
|
|
529
|
-
4.
|
|
530
|
-
|
|
531
|
-
### Q: 如何删除数据库中不需要的列?
|
|
410
|
+
4. 确认表定义文件与配置已保存
|
|
532
411
|
|
|
533
|
-
|
|
412
|
+
### Q: 如何处理“字段长度收缩”这类危险变更?
|
|
534
413
|
|
|
535
|
-
|
|
536
|
-
befly sync:db --force
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
**警告**:这会删除表定义中不存在的列及其数据,请先备份。
|
|
414
|
+
A: `syncTable()` 会跳过长度收缩并告警;请手动评估并处理(例如先清理/截断数据,再手动执行 DDL),再重新启动服务或再次调用 `syncTable()`。
|
|
540
415
|
|
|
541
416
|
### Q: Addon 表名太长怎么办?
|
|
542
417
|
|
|
@@ -551,16 +426,13 @@ A: Addon 表名格式为 `addon_{addonName}_{tableName}`,建议:
|
|
|
551
426
|
A:
|
|
552
427
|
|
|
553
428
|
1. 检查错误日志确定失败原因
|
|
554
|
-
|
|
555
|
-
|
|
429
|
+
A: `syncTable()` 会跳过长度收缩并告警;请手动评估并处理(例如先清理/截断数据,再手动执行 DDL),再重新启动服务或再次调用 `syncTable()`。
|
|
430
|
+
2. sync 命令是幂等的,可以安全地多次执行
|
|
556
431
|
|
|
557
432
|
### Q: 如何只同步某个 Addon 的表?
|
|
558
433
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
```bash
|
|
562
|
-
befly sync:db --table addon_admin_role
|
|
563
|
-
```
|
|
434
|
+
await syncTable(ctx, sources.tables);
|
|
435
|
+
A: 当前不支持按 Addon 或单表筛选;会同步项目与所有 Addon 的表定义。
|
|
564
436
|
|
|
565
437
|
### Q: 开发账户密码在哪里配置?
|
|
566
438
|
|
|
@@ -576,8 +448,5 @@ export default {
|
|
|
576
448
|
};
|
|
577
449
|
```
|
|
578
450
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
```bash
|
|
582
|
-
DEV_PASSWORD=your_password befly sync:dev
|
|
583
|
-
```
|
|
451
|
+
(不再提供 CLI 参数/命令;按配置文件机制设置即可。)
|
|
452
|
+
await syncTable(ctx, sources.tables);
|