befly 3.9.39 → 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.
Files changed (141) hide show
  1. package/README.md +39 -8
  2. package/befly.config.ts +19 -2
  3. package/checks/checkApi.ts +79 -77
  4. package/checks/checkHook.ts +48 -0
  5. package/checks/checkMenu.ts +168 -0
  6. package/checks/checkPlugin.ts +48 -0
  7. package/checks/checkTable.ts +137 -183
  8. package/docs/README.md +1 -1
  9. package/docs/api/api.md +1 -1
  10. package/docs/guide/quickstart.md +16 -9
  11. package/docs/hooks/hook.md +2 -2
  12. package/docs/hooks/rateLimit.md +1 -1
  13. package/docs/infra/redis.md +7 -7
  14. package/docs/plugins/plugin.md +23 -21
  15. package/docs/quickstart.md +16 -9
  16. package/docs/reference/addon.md +12 -1
  17. package/docs/reference/config.md +13 -30
  18. package/docs/reference/sync.md +62 -193
  19. package/docs/reference/table.md +27 -29
  20. package/hooks/auth.ts +3 -4
  21. package/hooks/cors.ts +4 -6
  22. package/hooks/parser.ts +3 -4
  23. package/hooks/permission.ts +3 -4
  24. package/hooks/validator.ts +4 -5
  25. package/lib/cacheHelper.ts +89 -153
  26. package/lib/cacheKeys.ts +1 -1
  27. package/lib/connect.ts +9 -13
  28. package/lib/dbDialect.ts +285 -0
  29. package/lib/dbHelper.ts +179 -507
  30. package/lib/dbUtils.ts +450 -0
  31. package/lib/logger.ts +41 -5
  32. package/lib/redisHelper.ts +1 -0
  33. package/lib/sqlBuilder.ts +358 -58
  34. package/lib/sqlCheck.ts +136 -0
  35. package/lib/validator.ts +1 -1
  36. package/loader/loadApis.ts +23 -126
  37. package/loader/loadHooks.ts +31 -46
  38. package/loader/loadPlugins.ts +37 -52
  39. package/main.ts +58 -19
  40. package/package.json +24 -25
  41. package/paths.ts +14 -14
  42. package/plugins/cache.ts +12 -6
  43. package/plugins/cipher.ts +2 -2
  44. package/plugins/config.ts +6 -8
  45. package/plugins/db.ts +14 -19
  46. package/plugins/jwt.ts +6 -7
  47. package/plugins/logger.ts +7 -9
  48. package/plugins/redis.ts +8 -10
  49. package/plugins/tool.ts +3 -4
  50. package/router/api.ts +3 -2
  51. package/router/static.ts +7 -5
  52. package/sync/syncApi.ts +80 -235
  53. package/sync/syncCache.ts +16 -0
  54. package/sync/syncDev.ts +167 -202
  55. package/sync/syncMenu.ts +230 -444
  56. package/sync/syncTable.ts +1247 -0
  57. package/tests/_mocks/mockSqliteDb.ts +204 -0
  58. package/tests/addonHelper-cache.test.ts +32 -0
  59. package/tests/apiHandler-routePath-only.test.ts +32 -0
  60. package/tests/cacheHelper.test.ts +16 -51
  61. package/tests/checkApi-routePath-strict.test.ts +166 -0
  62. package/tests/checkMenu.test.ts +346 -0
  63. package/tests/checkTable-smoke.test.ts +157 -0
  64. package/tests/dbDialect-cache.test.ts +23 -0
  65. package/tests/dbDialect.test.ts +46 -0
  66. package/tests/dbHelper-advanced.test.ts +1 -1
  67. package/tests/dbHelper-all-array-types.test.ts +15 -15
  68. package/tests/dbHelper-batch-write.test.ts +90 -0
  69. package/tests/dbHelper-columns.test.ts +36 -54
  70. package/tests/dbHelper-execute.test.ts +26 -26
  71. package/tests/dbHelper-joins.test.ts +85 -176
  72. package/tests/fixtures/scanFilesAddon/node_modules/@befly-addon/demo/apis/sub/b.ts +3 -0
  73. package/tests/fixtures/scanFilesApis/a.ts +3 -0
  74. package/tests/fixtures/scanFilesApis/sub/b.ts +3 -0
  75. package/tests/loadPlugins-order-smoke.test.ts +75 -0
  76. package/tests/logger.test.ts +6 -6
  77. package/tests/redisHelper.test.ts +6 -1
  78. package/tests/scanFiles-routePath.test.ts +46 -0
  79. package/tests/smoke-sql.test.ts +24 -0
  80. package/tests/sqlBuilder-advanced.test.ts +18 -5
  81. package/tests/sqlBuilder.test.ts +24 -0
  82. package/tests/sync-init-guard.test.ts +105 -0
  83. package/tests/syncApi-insBatch-fields-consistent.test.ts +61 -0
  84. package/tests/syncApi-obsolete-records.test.ts +69 -0
  85. package/tests/syncApi-type-compat.test.ts +72 -0
  86. package/tests/syncDev-permissions.test.ts +81 -0
  87. package/tests/syncMenu-disableMenus-hard-delete.test.ts +88 -0
  88. package/tests/syncMenu-duplicate-path.test.ts +122 -0
  89. package/tests/syncMenu-obsolete-records.test.ts +161 -0
  90. package/tests/syncMenu-parentPath-from-tree.test.ts +75 -0
  91. package/tests/syncMenu-paths.test.ts +0 -9
  92. package/tests/{syncDb-apply.test.ts → syncTable-apply.test.ts} +14 -24
  93. package/tests/{syncDb-array-number.test.ts → syncTable-array-number.test.ts} +31 -31
  94. package/tests/syncTable-constants.test.ts +101 -0
  95. package/tests/syncTable-db-integration.test.ts +237 -0
  96. package/tests/{syncDb-ddl.test.ts → syncTable-ddl.test.ts} +67 -53
  97. package/tests/{syncDb-helpers.test.ts → syncTable-helpers.test.ts} +12 -26
  98. package/tests/syncTable-schema.test.ts +99 -0
  99. package/tests/syncTable-testkit.test.ts +25 -0
  100. package/tests/syncTable-types.test.ts +122 -0
  101. package/tests/tableRef-and-deserialize.test.ts +67 -0
  102. package/tsconfig.json +1 -1
  103. package/types/api.d.ts +1 -1
  104. package/types/befly.d.ts +13 -12
  105. package/types/cache.d.ts +2 -2
  106. package/types/context.d.ts +1 -1
  107. package/types/database.d.ts +0 -5
  108. package/types/hook.d.ts +1 -10
  109. package/types/plugin.d.ts +2 -96
  110. package/types/sync.d.ts +19 -25
  111. package/utils/convertBigIntFields.ts +38 -0
  112. package/utils/disableMenusGlob.ts +85 -0
  113. package/utils/importDefault.ts +21 -0
  114. package/utils/isDirentDirectory.ts +23 -0
  115. package/utils/loadMenuConfigs.ts +145 -0
  116. package/utils/processFields.ts +25 -0
  117. package/utils/scanAddons.ts +72 -0
  118. package/utils/scanFiles.ts +129 -21
  119. package/utils/scanSources.ts +64 -0
  120. package/utils/sortModules.ts +137 -0
  121. package/checks/checkApp.ts +0 -55
  122. package/hooks/rateLimit.ts +0 -276
  123. package/sync/syncAll.ts +0 -35
  124. package/sync/syncDb/apply.ts +0 -192
  125. package/sync/syncDb/constants.ts +0 -119
  126. package/sync/syncDb/ddl.ts +0 -251
  127. package/sync/syncDb/helpers.ts +0 -84
  128. package/sync/syncDb/schema.ts +0 -202
  129. package/sync/syncDb/sqlite.ts +0 -48
  130. package/sync/syncDb/table.ts +0 -207
  131. package/sync/syncDb/tableCreate.ts +0 -163
  132. package/sync/syncDb/types.ts +0 -132
  133. package/sync/syncDb/version.ts +0 -69
  134. package/sync/syncDb.ts +0 -168
  135. package/tests/rateLimit-hook.test.ts +0 -477
  136. package/tests/syncDb-constants.test.ts +0 -130
  137. package/tests/syncDb-schema.test.ts +0 -179
  138. package/tests/syncDb-types.test.ts +0 -139
  139. package/utils/addonHelper.ts +0 -90
  140. package/utils/modules.ts +0 -98
  141. package/utils/route.ts +0 -23
@@ -72,7 +72,7 @@ import type { Plugin } from "befly/types/plugin";
72
72
 
73
73
  const plugin: Plugin = {
74
74
  // 依赖的插件列表(可选)
75
- after: ["logger", "db"],
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
- after?: string[];
99
+ deps: string[];
100
100
 
101
101
  /** 插件初始化函数 */
102
- handler?: (context: BeflyContext) => any | Promise<any>;
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
- 使用 `after` 属性声明依赖关系:
174
+ 使用 `deps` 属性声明依赖关系:
175
175
 
176
176
  ```typescript
177
177
  // redis.ts - 依赖 logger
178
178
  const plugin: Plugin = {
179
- after: ["logger"], // 在 logger 插件之后初始化
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
- after: [],
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
- after: ["logger"],
253
+ deps: ["logger", "redis"],
254
254
  async handler(befly: BeflyContext): Promise<DbHelper> {
255
- const sql = await Connect.connectSql();
256
- return new DbHelper(befly, sql);
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
- after: ["logger"],
289
+ deps: ["logger"],
289
290
  async handler(): Promise<RedisHelper | Record<string, never>> {
290
- await Connect.connectRedis();
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
- after: [],
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
- after: ["db", "redis"], // 依赖数据库和 Redis
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
- after: ["logger", "config"],
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
- after: ["logger", "config"],
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
- after: ["db", "logger", "config"],
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
- after: ["logger", "config"],
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
- after: ["logger", "db", "redis"], // 声明所有使用的插件
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. 同一类型内根据 `after` 依赖关系排序
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
- after: ["db"], // 声明依赖
943
+ deps: ["db"], // 声明依赖
942
944
  handler: (befly) => {
943
945
  return {
944
946
  async getUser(id: number) {
@@ -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
- ```bash
214
- # 全量同步(表结构 + API + 菜单 + 开发账户)
215
- bun befly sync
213
+ 服务启动时会在**主进程**自动执行同步流程:
214
+
215
+ 1. `syncTable()`:同步表结构
216
+ 2. `syncData()`:固定顺序执行 `syncApi` → `syncMenu` → `syncDev`
216
217
 
217
- # 或单独同步
218
- bun befly sync:db # 只同步表结构
219
- bun befly sync:api # 只同步 API 路由
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 # 构建
@@ -467,7 +467,18 @@ A: 在配置文件中设置:
467
467
 
468
468
  ### Q: Addon 的表如何迁移?
469
469
 
470
- A: 使用 `befly sync:db` 命令,会自动同步所有 Addon 的表定义。
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
 
@@ -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'` | 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 前缀 |
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 = beflyConfig.appPort;
472
- const dbConfig = beflyConfig.db;
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
  ## 最佳实践
@@ -1,16 +1,14 @@
1
- # Sync 同步命令
1
+ # Sync 同步流程
2
2
 
3
3
  > 数据库结构、API路由、菜单配置、开发账户同步
4
4
 
5
5
  ## 目录
6
6
 
7
7
  - [概述](#概述)
8
- - [syncAll 全量同步](#syncall-全量同步)
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
- | `syncDb` | 同步表结构定义 | 所有业务表 |
27
- | `syncApi` | 同步 API 路由信息 | `addon_admin_api` |
28
- | `syncMenu` | 同步菜单配置 | `addon_admin_menu` |
29
- | `syncDev` | 创建开发者账户 | `addon_admin_role`, `addon_admin_admin` |
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
- **执行顺序**:`checkApp` → `syncDb` → `syncApi` → `syncMenu` → `syncDev`
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
- ## syncDb 数据库同步
35
+ ## syncTable 数据库同步
73
36
 
74
37
  将 `tables/*.json` 表定义同步到数据库结构。
75
38
 
76
39
  ### 基本用法
77
40
 
78
- ```bash
79
- # 同步所有表
80
- befly sync:db
81
-
82
- # 只同步指定表
83
- befly sync:db --table user
41
+ 默认会在服务启动时自动执行(仅主进程)。如需在代码中手动执行:
84
42
 
85
- # 强制模式(允许破坏性操作)
86
- befly sync:db --force
43
+ ```typescript
44
+ import { syncTable } from "../sync/syncTable.js";
45
+ import { scanSources } from "../utils/scanSources.js";
87
46
 
88
- # 预览模式(仅显示变更,不执行)
89
- befly sync:db --dry-run
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
- syncDb
60
+ syncTable
105
61
  ├─────────────────────────────────────────────────────┤
106
- │ 1. 设置数据库类型 (setDbType)
107
- │ 2. 检查表定义完整性 (checkTable)
108
- │ 3. 连接数据库 (Connect.connectSql)
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
- ```bash
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
- ```bash
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
- ```bash
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
- ```bash
391
- # 全量同步
392
- befly sync
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
- ```typescript
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
- **必须按顺序执行**:`syncDb` → `syncApi` → `syncMenu` → `syncDev`
360
+ **必须按顺序执行**:`syncTable` → `syncApi` → `syncMenu` → `syncDev`
468
361
 
469
- - `syncApi` 依赖 `addon_admin_api` 表(由 `syncDb` 创建)
470
- - `syncMenu` 依赖 `addon_admin_menu` 表(由 `syncDb` 创建)
362
+ - `syncApi` 依赖 `addon_admin_api` 表(由 `syncTable` 创建)
363
+ - `syncMenu` 依赖 `addon_admin_menu` 表(由 `syncTable` 创建)
471
364
  - `syncDev` 依赖角色表和权限数据(由前面命令创建)
472
365
 
473
366
  ### 2. 破坏性操作
474
367
 
475
- 默认模式下,`syncDb` **不会删除列**,只会:
368
+ 默认模式下,`syncTable` **不会删除列**,只会:
476
369
 
477
370
  - 新增缺失的列
478
371
  - 修改现有列的类型/默认值
479
372
 
480
- 使用 `--force` 参数允许删除列:
373
+ 此外,`syncTable` **不会执行长度收缩等可能导致数据截断的危险变更**:
481
374
 
482
- ```bash
483
- # 谨慎使用!会删除数据库中存在但定义中不存在的列
484
- befly sync:db --force
485
- ```
375
+ - 例如:`VARCHAR(200)` → `VARCHAR(50)`
376
+ - 这类变更会被跳过,并输出告警;需要手动评估并处理
486
377
 
487
378
  ### 3. 缓存清理
488
379
 
489
- `syncDb` 执行后会自动清理 Redis 中的表结构缓存:
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: 确保先执行 `befly sync:db` 创建表结构,再执行其他 sync 命令。或直接使用 `befly sync` 执行全量同步。
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. 尝试使用 `--dry-run` 查看预期变更
530
-
531
- ### Q: 如何删除数据库中不需要的列?
410
+ 4. 确认表定义文件与配置已保存
532
411
 
533
- A: 使用 `--force` 参数:
412
+ ### Q: 如何处理“字段长度收缩”这类危险变更?
534
413
 
535
- ```bash
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
- 2. 修复问题后重新执行 sync 命令
555
- 3. sync 命令是幂等的,可以安全地多次执行
429
+ A: `syncTable()` 会跳过长度收缩并告警;请手动评估并处理(例如先清理/截断数据,再手动执行 DDL),再重新启动服务或再次调用 `syncTable()`。
430
+ 2. sync 命令是幂等的,可以安全地多次执行
556
431
 
557
432
  ### Q: 如何只同步某个 Addon 的表?
558
433
 
559
- A: 目前不支持按 Addon 筛选,可以使用 `--table` 参数同步单个表:
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);