befly 3.9.40 → 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.
Files changed (144) hide show
  1. package/README.md +47 -19
  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 +17 -11
  9. package/docs/api/api.md +16 -2
  10. package/docs/guide/quickstart.md +31 -10
  11. package/docs/hooks/hook.md +2 -2
  12. package/docs/hooks/rateLimit.md +1 -1
  13. package/docs/infra/redis.md +26 -14
  14. package/docs/plugins/plugin.md +23 -21
  15. package/docs/quickstart.md +5 -328
  16. package/docs/reference/addon.md +0 -4
  17. package/docs/reference/config.md +14 -31
  18. package/docs/reference/logger.md +3 -3
  19. package/docs/reference/sync.md +132 -237
  20. package/docs/reference/table.md +28 -30
  21. package/hooks/auth.ts +3 -4
  22. package/hooks/cors.ts +4 -6
  23. package/hooks/parser.ts +3 -4
  24. package/hooks/permission.ts +3 -4
  25. package/hooks/validator.ts +3 -4
  26. package/lib/cacheHelper.ts +89 -153
  27. package/lib/cacheKeys.ts +1 -1
  28. package/lib/connect.ts +9 -13
  29. package/lib/dbDialect.ts +285 -0
  30. package/lib/dbHelper.ts +179 -507
  31. package/lib/dbUtils.ts +450 -0
  32. package/lib/logger.ts +41 -5
  33. package/lib/redisHelper.ts +1 -0
  34. package/lib/sqlBuilder.ts +358 -58
  35. package/lib/sqlCheck.ts +136 -0
  36. package/lib/validator.ts +1 -1
  37. package/loader/loadApis.ts +23 -126
  38. package/loader/loadHooks.ts +31 -46
  39. package/loader/loadPlugins.ts +37 -52
  40. package/main.ts +58 -19
  41. package/package.json +24 -25
  42. package/paths.ts +14 -14
  43. package/plugins/cache.ts +12 -6
  44. package/plugins/cipher.ts +2 -2
  45. package/plugins/config.ts +6 -8
  46. package/plugins/db.ts +14 -19
  47. package/plugins/jwt.ts +6 -7
  48. package/plugins/logger.ts +7 -9
  49. package/plugins/redis.ts +8 -10
  50. package/plugins/tool.ts +3 -4
  51. package/router/api.ts +3 -2
  52. package/router/static.ts +7 -5
  53. package/sync/syncApi.ts +80 -235
  54. package/sync/syncCache.ts +16 -0
  55. package/sync/syncDev.ts +167 -202
  56. package/sync/syncMenu.ts +230 -444
  57. package/sync/syncTable.ts +1247 -0
  58. package/tests/_mocks/mockSqliteDb.ts +204 -0
  59. package/tests/addonHelper-cache.test.ts +32 -0
  60. package/tests/apiHandler-routePath-only.test.ts +32 -0
  61. package/tests/cacheHelper.test.ts +16 -51
  62. package/tests/checkApi-routePath-strict.test.ts +166 -0
  63. package/tests/checkMenu.test.ts +346 -0
  64. package/tests/checkTable-smoke.test.ts +157 -0
  65. package/tests/dbDialect-cache.test.ts +23 -0
  66. package/tests/dbDialect.test.ts +46 -0
  67. package/tests/dbHelper-advanced.test.ts +1 -1
  68. package/tests/dbHelper-all-array-types.test.ts +15 -15
  69. package/tests/dbHelper-batch-write.test.ts +90 -0
  70. package/tests/dbHelper-columns.test.ts +36 -54
  71. package/tests/dbHelper-execute.test.ts +26 -26
  72. package/tests/dbHelper-joins.test.ts +85 -176
  73. package/tests/fixtures/scanFilesAddon/node_modules/@befly-addon/demo/apis/sub/b.ts +3 -0
  74. package/tests/fixtures/scanFilesApis/a.ts +3 -0
  75. package/tests/fixtures/scanFilesApis/sub/b.ts +3 -0
  76. package/tests/loadPlugins-order-smoke.test.ts +75 -0
  77. package/tests/logger.test.ts +6 -6
  78. package/tests/redisHelper.test.ts +6 -1
  79. package/tests/scanFiles-routePath.test.ts +46 -0
  80. package/tests/smoke-sql.test.ts +24 -0
  81. package/tests/sqlBuilder-advanced.test.ts +18 -5
  82. package/tests/sqlBuilder.test.ts +24 -0
  83. package/tests/sync-init-guard.test.ts +105 -0
  84. package/tests/syncApi-insBatch-fields-consistent.test.ts +61 -0
  85. package/tests/syncApi-obsolete-records.test.ts +69 -0
  86. package/tests/syncApi-type-compat.test.ts +72 -0
  87. package/tests/syncDev-permissions.test.ts +81 -0
  88. package/tests/syncMenu-disableMenus-hard-delete.test.ts +88 -0
  89. package/tests/syncMenu-duplicate-path.test.ts +122 -0
  90. package/tests/syncMenu-obsolete-records.test.ts +161 -0
  91. package/tests/syncMenu-parentPath-from-tree.test.ts +75 -0
  92. package/tests/syncMenu-paths.test.ts +0 -9
  93. package/tests/{syncDb-apply.test.ts → syncTable-apply.test.ts} +14 -24
  94. package/tests/{syncDb-array-number.test.ts → syncTable-array-number.test.ts} +31 -31
  95. package/tests/syncTable-constants.test.ts +101 -0
  96. package/tests/syncTable-db-integration.test.ts +237 -0
  97. package/tests/{syncDb-ddl.test.ts → syncTable-ddl.test.ts} +67 -53
  98. package/tests/{syncDb-helpers.test.ts → syncTable-helpers.test.ts} +12 -26
  99. package/tests/syncTable-schema.test.ts +99 -0
  100. package/tests/syncTable-testkit.test.ts +25 -0
  101. package/tests/syncTable-types.test.ts +122 -0
  102. package/tests/tableRef-and-deserialize.test.ts +67 -0
  103. package/tsconfig.json +1 -1
  104. package/types/api.d.ts +1 -1
  105. package/types/befly.d.ts +13 -12
  106. package/types/cache.d.ts +2 -2
  107. package/types/context.d.ts +1 -1
  108. package/types/database.d.ts +0 -5
  109. package/types/hook.d.ts +1 -10
  110. package/types/plugin.d.ts +2 -96
  111. package/types/sync.d.ts +19 -25
  112. package/utils/convertBigIntFields.ts +38 -0
  113. package/utils/disableMenusGlob.ts +85 -0
  114. package/utils/importDefault.ts +21 -0
  115. package/utils/isDirentDirectory.ts +23 -0
  116. package/utils/loadMenuConfigs.ts +145 -0
  117. package/utils/processFields.ts +25 -0
  118. package/utils/scanAddons.ts +72 -0
  119. package/utils/scanFiles.ts +129 -21
  120. package/utils/scanSources.ts +64 -0
  121. package/utils/sortModules.ts +137 -0
  122. package/checks/checkApp.ts +0 -55
  123. package/docs/cipher.md +0 -582
  124. package/docs/database.md +0 -1176
  125. package/hooks/rateLimit.ts +0 -276
  126. package/sync/syncAll.ts +0 -35
  127. package/sync/syncDb/apply.ts +0 -192
  128. package/sync/syncDb/constants.ts +0 -119
  129. package/sync/syncDb/ddl.ts +0 -251
  130. package/sync/syncDb/helpers.ts +0 -84
  131. package/sync/syncDb/schema.ts +0 -202
  132. package/sync/syncDb/sqlite.ts +0 -48
  133. package/sync/syncDb/table.ts +0 -207
  134. package/sync/syncDb/tableCreate.ts +0 -163
  135. package/sync/syncDb/types.ts +0 -132
  136. package/sync/syncDb/version.ts +0 -69
  137. package/sync/syncDb.ts +0 -168
  138. package/tests/rateLimit-hook.test.ts +0 -477
  139. package/tests/syncDb-constants.test.ts +0 -130
  140. package/tests/syncDb-schema.test.ts +0 -179
  141. package/tests/syncDb-types.test.ts +0 -139
  142. package/utils/addonHelper.ts +0 -90
  143. package/utils/modules.ts +0 -98
  144. package/utils/route.ts +0 -23
@@ -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 }, "数据库连接失败");
@@ -1,16 +1,16 @@
1
- # Sync 同步命令
1
+ # Sync 同步流程
2
2
 
3
3
  > 数据库结构、API路由、菜单配置、开发账户同步
4
4
 
5
5
  ## 目录
6
6
 
7
7
  - [概述](#概述)
8
- - [syncAll 全量同步](#syncall-全量同步)
9
- - [syncDb 数据库同步](#syncdb-数据库同步)
8
+ - [强约束清单](#强约束清单)
9
+ - [syncTable 数据库同步](#synctable-数据库同步)
10
10
  - [syncApi 接口同步](#syncapi-接口同步)
11
11
  - [syncMenu 菜单同步](#syncmenu-菜单同步)
12
12
  - [syncDev 开发账户同步](#syncdev-开发账户同步)
13
- - [命令行使用](#命令行使用)
13
+ - [syncCache 缓存同步](#synccache-缓存同步)
14
14
  - [表名规则](#表名规则)
15
15
  - [注意事项](#注意事项)
16
16
  - [FAQ](#faq)
@@ -21,103 +21,62 @@
21
21
 
22
22
  Sync 同步系统用于将代码定义同步到数据库,包括:
23
23
 
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` | 依次执行以上全部 | - |
24
+ | 命令 | 功能 | 目标表 |
25
+ | ----------- | ----------------- | --------------------------------------- |
26
+ | `syncTable` | 同步表结构定义 | 所有业务表 |
27
+ | `syncApi` | 同步 API 路由信息 | `addon_admin_api` |
28
+ | `syncMenu` | 同步菜单配置 | `addon_admin_menu` |
29
+ | `syncDev` | 创建开发者账户 | `addon_admin_role`, `addon_admin_admin` |
30
+ | `syncCache` | 同步缓存 | Redis(apis/menu/role-permissions) |
31
31
 
32
- **执行顺序**:`checkApp` → `syncDb` → `syncApi` → `syncMenu` → `syncDev`
32
+ **执行顺序**:`syncTable` → `syncApi` → `syncMenu` → `syncDev` → `syncCache`
33
33
 
34
34
  ---
35
35
 
36
- ## syncAll 全量同步
36
+ ## 强约束清单
37
37
 
38
- 一键执行所有同步命令:
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:`。
39
42
 
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
- ```
43
+ > 说明:当前版本不提供 CLI 同步命令;同步逻辑在服务启动时由主进程自动执行(见 `packages/core/main.ts`)。
69
44
 
70
45
  ---
71
46
 
72
- ## syncDb 数据库同步
47
+ ## syncTable 数据库同步
73
48
 
74
49
  将 `tables/*.json` 表定义同步到数据库结构。
75
50
 
76
51
  ### 基本用法
77
52
 
78
- ```bash
79
- # 同步所有表
80
- befly sync:db
53
+ 默认会在服务启动时自动执行(仅主进程)。如需在代码中手动执行:
81
54
 
82
- # 只同步指定表
83
- befly sync:db --table user
84
-
85
- # 强制模式(允许破坏性操作)
86
- befly sync:db --force
55
+ ```typescript
56
+ import { syncTable } from "../sync/syncTable.js";
57
+ import { scanSources } from "../utils/scanSources.js";
87
58
 
88
- # 预览模式(仅显示变更,不执行)
89
- befly sync:db --dry-run
59
+ // ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.cache / ctx.config)
60
+ const sources = await scanSources();
61
+ await syncTable(ctx, sources.tables);
90
62
  ```
91
63
 
92
64
  ### 命令选项
93
65
 
94
- | 选项 | 类型 | 默认值 | 说明 |
95
- | ----------- | ------- | ------ | -------------------- |
96
- | `--table` | string | - | 只同步指定表 |
97
- | `--force` | boolean | false | 强制模式,允许删除列 |
98
- | `--dry-run` | boolean | false | 预览模式,不实际执行 |
66
+
99
67
 
100
68
  ### 同步逻辑
101
69
 
102
70
  ```
103
71
  ┌─────────────────────────────────────────────────────┐
104
- syncDb
72
+ syncTable
105
73
  ├─────────────────────────────────────────────────────┤
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. 对每个表: │
74
+ │ 1. 校验 ctx.db / ctx.redis / ctx.config
75
+ │ 2. 检查数据库版本 (ensureDbVersion)
76
+ │ 3. 同步传入的表定义列表(通常来自 scanSources)
116
77
  │ ├── 表存在?→ modifyTable (修改) │
117
78
  │ └── 表不存在?→ createTable (新建) │
118
-
119
- │ 7. 清理 Redis 缓存 (tableColumns) │
120
- │ 8. 关闭数据库连接 │
79
+ 4. 清理 Redis 缓存 (tableColumns)
121
80
  └─────────────────────────────────────────────────────┘
122
81
  ```
123
82
 
@@ -156,19 +115,17 @@ befly sync:db --dry-run
156
115
 
157
116
  ### 基本用法
158
117
 
159
- ```bash
160
- # 同步 API 路由
161
- befly sync:api
118
+ 通常无需单独调用:服务启动流程会按顺序执行 `syncTable` → `syncApi` → `syncMenu` → `syncDev` → `syncCache`。
162
119
 
163
- # 预览模式
164
- befly sync:api --plan
165
- ```
120
+ 如需在代码中手动调用:
166
121
 
167
- ### 命令选项
122
+ ```typescript
123
+ import { syncApi } from "../sync/syncApi.js";
124
+ import { scanSources } from "../utils/scanSources.js";
168
125
 
169
- | 选项 | 类型 | 默认值 | 说明 |
170
- | -------- | ------- | ------ | ---------------------- |
171
- | `--plan` | boolean | false | 预览模式,显示变更计划 |
126
+ const sources = await scanSources();
127
+ await syncApi(ctx, sources.apis as any);
128
+ ```
172
129
 
173
130
  ### 同步逻辑
174
131
 
@@ -194,20 +151,15 @@ befly sync:api --plan
194
151
  └─────────────────────────────────────────────────────┘
195
152
  ```
196
153
 
197
- ### API 信息提取
154
+ ### 存储字段(重要)
198
155
 
199
- API 文件中提取以下信息:
156
+ `syncApi` 会把扫描到的 API 信息同步到 `addon_admin_api` 表,核心字段为:
200
157
 
201
- ```typescript
202
- interface ApiInfo {
203
- name: string; // 接口名称(name 属性)
204
- path: string; // 路由路径(由文件路径生成)
205
- method: string; // 请求方法(method 属性,默认 POST
206
- description: string; // 接口描述(desc 属性)
207
- addonName: string; // 所属 Addon 名称
208
- addonTitle: string; // Addon 标题
209
- }
210
- ```
158
+ - `routePath`:只存 `url.pathname`(例如 `/api/user/login`),与 method 无关
159
+ - `name`:接口名称
160
+ - `addonName`:所属 addon(无 addon 时为空字符串)
161
+
162
+ > 注意:`routePath` 必须是 pathname(以 `/` 开头),不允许写成 `POST /api/...` 或 `POST/api/...`。
211
163
 
212
164
  ### 统计信息
213
165
 
@@ -228,19 +180,19 @@ interface SyncApiStats {
228
180
 
229
181
  ### 基本用法
230
182
 
231
- ```bash
232
- # 同步菜单
233
- befly sync:menu
183
+ 同 `syncApi`,通常由启动流程统一触发。
234
184
 
235
- # 预览模式
236
- befly sync:menu --plan
237
- ```
185
+ 如需手动调用,需要先对菜单配置做校验/过滤(例如 disableMenus):
238
186
 
239
- ### 命令选项
187
+ ```typescript
188
+ import { checkMenu } from "../checks/checkMenu.js";
189
+ import { syncMenu } from "../sync/syncMenu.js";
190
+ import { scanSources } from "../utils/scanSources.js";
240
191
 
241
- | 选项 | 类型 | 默认值 | 说明 |
242
- | -------- | ------- | ------ | ---------------------- |
243
- | `--plan` | boolean | false | 预览模式,显示变更计划 |
192
+ const sources = await scanSources();
193
+ const checkedMenus = await checkMenu(sources.addons, { disableMenus: ctx.config.disableMenus || [] });
194
+ await syncMenu(ctx, checkedMenus);
195
+ ```
244
196
 
245
197
  ### 菜单配置文件
246
198
 
@@ -325,104 +277,80 @@ interface SyncMenuStats {
325
277
 
326
278
  ### 基本用法
327
279
 
328
- ```bash
329
- # 同步开发账户
330
- befly sync:dev
331
-
332
- # 预览模式
333
- befly sync:dev --plan
334
- ```
335
-
336
- ### 命令选项
337
-
338
- | 选项 | 类型 | 默认值 | 说明 |
339
- | -------- | ------- | ------ | ---------------------- |
340
- | `--plan` | boolean | false | 预览模式,显示变更计划 |
280
+ 同 `syncApi`,通常由启动流程统一触发。
341
281
 
342
282
  ### 同步逻辑
343
283
 
344
284
  ```
345
285
  ┌─────────────────────────────────────────────────────┐
346
- syncDev
286
+ syncDev
347
287
  ├─────────────────────────────────────────────────────┤
348
- 1. 创建/更新开发角色:
349
- - 角色名称:开发者
350
- - 角色标识:dev
351
- - 权限:所有菜单 + 所有 API
352
-
353
- 2. 获取所有菜单 ID 列表
354
-
355
- 3. 获取所有 API ID 列表
356
-
357
- 4. 更新角色权限:
358
- - menus: 所有菜单 ID
359
- - apis: 所有 API ID │
360
-
361
- 5. 创建/更新开发管理员:
362
- - 用户名:dev
363
- - 密码:从配置读取
364
- - 角色:开发者角色
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
+ - 角色:开发者角色
365
305
  └─────────────────────────────────────────────────────┘
366
306
  ```
367
307
 
368
308
  ### 配置说明
369
309
 
370
- 开发账户配置在 `befly.config.ts` 或环境配置文件中:
310
+ 开发账户配置在 `befly.config.ts` 或环境配置文件中(仅当 `devPassword` 有值时才会创建 dev 账号):
371
311
 
372
- ```typescript
373
- // befly.config.ts
374
- export default {
375
- dev: {
376
- username: "dev", // 开发账户用户名
377
- password: "dev123456" // 开发账户密码
378
- }
379
- };
312
+ ```json
313
+ {
314
+ "devEmail": "dev@qq.com",
315
+ "devPassword": "beflydev123456"
316
+ }
380
317
  ```
381
318
 
382
- **注意**:此命令仅用于开发环境,生产环境应通过正式流程创建管理员。
319
+ > 注意:`syncDev` 会把 `menus/apis` 写入角色表,并且 `apis` 必须是 pathname 字符串数组(严格模式下不允许 numeric id)。
383
320
 
384
321
  ---
385
322
 
386
- ## 命令行使用
323
+ ## syncCache 缓存同步
387
324
 
388
- ### CLI 命令列表
325
+ 同步缓存(统一收敛到启动流程末尾执行):
389
326
 
390
- ```bash
391
- # 全量同步
392
- befly sync
327
+ - `cacheApis()`:缓存接口列表
328
+ - `cacheMenus()`:缓存菜单列表
329
+ - `rebuildRoleApiPermissions()`:重建角色接口权限 Set(member 为 pathname,与 method 无关)
393
330
 
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
- ```
331
+ ---
408
332
 
409
- ### 代码调用
333
+ ## 代码调用
410
334
 
411
335
  ```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 });
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";
341
+ import { scanSources } from "./utils/scanSources.js";
342
+ import { checkMenu } from "./checks/checkMenu.js";
343
+
344
+ // 启动前/启动中手动触发同步
345
+ // ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.cache / ctx.config)
346
+ const sources = await scanSources();
347
+ const checkedMenus = await checkMenu(sources.addons, { disableMenus: ctx.config.disableMenus || [] });
348
+
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);
426
354
  ```
427
355
 
428
356
  ---
@@ -464,29 +392,27 @@ addons/demo/tables/article.json → addon_demo_article
464
392
 
465
393
  ### 1. 执行顺序
466
394
 
467
- **必须按顺序执行**:`syncDb` → `syncApi` → `syncMenu` → `syncDev`
395
+ **必须按顺序执行**:`syncTable` → `syncApi` → `syncMenu` → `syncDev` → `syncCache`
468
396
 
469
- - `syncApi` 依赖 `addon_admin_api` 表(由 `syncDb` 创建)
470
- - `syncMenu` 依赖 `addon_admin_menu` 表(由 `syncDb` 创建)
397
+ - `syncApi` 依赖 `addon_admin_api` 表(由 `syncTable` 创建)
398
+ - `syncMenu` 依赖 `addon_admin_menu` 表(由 `syncTable` 创建)
471
399
  - `syncDev` 依赖角色表和权限数据(由前面命令创建)
472
400
 
473
401
  ### 2. 破坏性操作
474
402
 
475
- 默认模式下,`syncDb` **不会删除列**,只会:
403
+ 默认模式下,`syncTable` **不会删除列**,只会:
476
404
 
477
405
  - 新增缺失的列
478
406
  - 修改现有列的类型/默认值
479
407
 
480
- 使用 `--force` 参数允许删除列:
408
+ 此外,`syncTable` **不会执行长度收缩等可能导致数据截断的危险变更**:
481
409
 
482
- ```bash
483
- # 谨慎使用!会删除数据库中存在但定义中不存在的列
484
- befly sync:db --force
485
- ```
410
+ - 例如:`VARCHAR(200)` → `VARCHAR(50)`
411
+ - 这类变更会被跳过,并输出告警;需要手动评估并处理
486
412
 
487
413
  ### 3. 缓存清理
488
414
 
489
- `syncDb` 执行后会自动清理 Redis 中的表结构缓存:
415
+ `syncTable` 执行后会自动清理 Redis 中的表结构缓存:
490
416
 
491
417
  ```typescript
492
418
  // 自动清理以下缓存键
@@ -495,21 +421,10 @@ CacheKeys.tableColumns(tableName); // table:columns:{tableName}
495
421
 
496
422
  ### 4. 连接管理
497
423
 
498
- Sync 命令会自动管理数据库和 Redis 连接:
424
+ `sync*` 函数本身不会负责建立连接/加载插件:
499
425
 
500
- - 执行前建立连接
501
- - 执行后关闭连接
502
- - 出错时正确清理资源
503
-
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
- ```
426
+ - 你需要在调用前确保 `Connect.connect(...)` 已执行,并且 `Db/Redis/cache` 插件已注入到 `ctx`。
427
+ - 服务启动流程已内置这套顺序(见 `packages/core/main.ts`)。
513
428
 
514
429
  ---
515
430
 
@@ -517,7 +432,7 @@ befly sync:menu --plan # 预览菜单变更
517
432
 
518
433
  ### Q: sync 命令报错 "表不存在" 怎么办?
519
434
 
520
- A: 确保先执行 `befly sync:db` 创建表结构,再执行其他 sync 命令。或直接使用 `befly sync` 执行全量同步。
435
+ A: 确保 `syncTable()` 已先执行(服务启动时会自动执行)。`syncApi/syncMenu/syncDev` 依赖对应的表结构存在。
521
436
 
522
437
  ### Q: 为什么修改了表定义但数据库没变化?
523
438
 
@@ -526,17 +441,11 @@ A: 检查以下几点:
526
441
  1. JSON 文件语法是否正确
527
442
  2. 字段定义格式是否正确
528
443
  3. 是否保存了文件
529
- 4. 尝试使用 `--dry-run` 查看预期变更
530
-
531
- ### Q: 如何删除数据库中不需要的列?
444
+ 4. 确认表定义文件与配置已保存
532
445
 
533
- A: 使用 `--force` 参数:
534
-
535
- ```bash
536
- befly sync:db --force
537
- ```
446
+ ### Q: 如何处理“字段长度收缩”这类危险变更?
538
447
 
539
- **警告**:这会删除表定义中不存在的列及其数据,请先备份。
448
+ A: `syncTable()` 会跳过长度收缩并告警;请手动评估并处理(例如先清理/截断数据,再手动执行 DDL),再重新启动服务或再次调用 `syncTable()`。
540
449
 
541
450
  ### Q: Addon 表名太长怎么办?
542
451
 
@@ -550,34 +459,20 @@ A: Addon 表名格式为 `addon_{addonName}_{tableName}`,建议:
550
459
 
551
460
  A:
552
461
 
553
- 1. 检查错误日志确定失败原因
554
- 2. 修复问题后重新执行 sync 命令
555
- 3. sync 命令是幂等的,可以安全地多次执行
462
+ 1. 检查错误日志确定失败原因(例如表不存在、字段变更被跳过等)
463
+ 2. sync 命令是幂等的,可以安全地多次执行
556
464
 
557
465
  ### Q: 如何只同步某个 Addon 的表?
558
466
 
559
- A: 目前不支持按 Addon 筛选,可以使用 `--table` 参数同步单个表:
560
-
561
- ```bash
562
- befly sync:db --table addon_admin_role
563
- ```
467
+ A: 当前不支持按 Addon 或单表筛选;会同步项目与所有 Addon 的表定义。
564
468
 
565
469
  ### Q: 开发账户密码在哪里配置?
566
470
 
567
- A: 在配置文件中设置:
568
-
569
- ```typescript
570
- // befly.config.ts
571
- export default {
572
- dev: {
573
- username: "dev",
574
- password: "your_password"
575
- }
576
- };
577
- ```
578
-
579
- 或使用环境变量:
471
+ A: 在配置文件中设置(仅当 `devPassword` 有值时才会创建 dev 账号):
580
472
 
581
- ```bash
582
- DEV_PASSWORD=your_password befly sync:dev
473
+ ```json
474
+ {
475
+ "devEmail": "dev@qq.com",
476
+ "devPassword": "beflydev123456"
477
+ }
583
478
  ```
@@ -37,7 +37,7 @@
37
37
  - [字段名规范](#字段名规范)
38
38
  - [类型联动校验](#类型联动校验)
39
39
  - [数据库同步](#数据库同步)
40
- - [同步命令](#同步命令)
40
+ - [触发方式](#触发方式)
41
41
  - [同步流程](#同步流程)
42
42
  - [变更检测](#变更检测)
43
43
  - [安全机制](#安全机制)
@@ -429,13 +429,13 @@ interface FieldDefinition {
429
429
 
430
430
  以下字段由系统自动创建和管理,**不能**在表定义中使用:
431
431
 
432
- | 字段名 | 类型 | 说明 |
433
- | ------------ | --------- | ------------------------ |
434
- | `id` | `BIGINT` | 主键 ID,自增 |
435
- | `created_at` | `BIGINT` | 创建时间戳(毫秒) |
436
- | `updated_at` | `BIGINT` | 更新时间戳(毫秒) |
437
- | `deleted_at` | `BIGINT` | 删除时间戳(软删除标记) |
438
- | `state` | `TINYINT` | 状态字段 |
432
+ | 字段名 | 类型 | 说明 |
433
+ | ------------ | -------- | ------------------------ |
434
+ | `id` | `BIGINT` | 主键 ID,自增 |
435
+ | `created_at` | `BIGINT` | 创建时间戳(毫秒) |
436
+ | `updated_at` | `BIGINT` | 更新时间戳(毫秒) |
437
+ | `deleted_at` | `BIGINT` | 删除时间戳(软删除标记) |
438
+ | `state` | `BIGINT` | 状态字段 |
439
439
 
440
440
  **系统自动创建的索引:**
441
441
 
@@ -510,20 +510,19 @@ interface FieldDefinition {
510
510
 
511
511
  ## 数据库同步
512
512
 
513
- ### 同步命令
513
+ ### 触发方式
514
514
 
515
- ```bash
516
- # 同步所有表
517
- bun run sync:db
515
+ 服务启动时会在**主进程**自动执行 `syncTable()`。
518
516
 
519
- # 同步指定表
520
- bun run sync:db --table=user
517
+ 如需在代码中手动触发:
521
518
 
522
- # 计划模式(仅输出 SQL,不执行)
523
- bun run sync:db --plan
519
+ ```typescript
520
+ import { syncTable } from "../../sync/syncTable.js";
521
+ import { scanSources } from "../../utils/scanSources.js";
524
522
 
525
- # 强制模式(执行危险变更,如字段长度收缩)
526
- bun run sync:db --force
523
+ // ctx:BeflyContext(需已具备 ctx.db / ctx.redis / ctx.config)
524
+ const sources = await scanSources();
525
+ await syncTable(ctx, sources.tables);
527
526
  ```
528
527
 
529
528
  ### 同步流程
@@ -556,22 +555,21 @@ bun run sync:db --force
556
555
 
557
556
  同步时检测以下变更:
558
557
 
559
- | 变更类型 | 说明 | 自动执行 |
560
- | -------- | ---------------------------- | ---------- |
561
- | 长度扩展 | VARCHAR 长度增加 | ✓ |
562
- | 长度收缩 | VARCHAR 长度减少 | --force |
563
- | 类型宽化 | INT → BIGINT, VARCHAR → TEXT | ✓ |
564
- | 类型变更 | 其他类型变更 | ✗ 禁止 |
565
- | 默认值 | 默认值变更 | ✓ |
566
- | 注释 | 字段注释变更 | ✓ |
567
- | 索引 | 添加/删除索引 | ✓ |
558
+ | 变更类型 | 说明 | 自动执行 |
559
+ | -------- | ---------------------------- | -------------------- |
560
+ | 长度扩展 | VARCHAR 长度增加 | ✓ |
561
+ | 长度收缩 | VARCHAR 长度减少 | 跳过(需手动处理) |
562
+ | 类型宽化 | INT → BIGINT, VARCHAR → TEXT | ✓ |
563
+ | 类型变更 | 其他类型变更 | ✗ 禁止 |
564
+ | 默认值 | 默认值变更 | ✓ |
565
+ | 注释 | 字段注释变更 | ✓ |
566
+ | 索引 | 添加/删除索引 | ✓ |
568
567
 
569
568
  ### 安全机制
570
569
 
571
- 1. **禁止危险类型变更**:不允许从 `BIGINT` 改为 `VARCHAR` 等不兼容变更
570
+ 1. **禁止危险类型变更**:不允许从 `BIGINT` 改为 `VARCHAR` 等高风险变更
572
571
  2. **长度收缩保护**:默认跳过长度收缩,避免数据截断
573
- 3. **计划模式**:`--plan` 仅输出 SQL 不执行,用于审查
574
- 4. **保留字段保护**:不允许定义系统保留字段
572
+ 3. **保留字段保护**:不允许定义系统保留字段
575
573
 
576
574
  ---
577
575
 
package/hooks/auth.ts CHANGED
@@ -2,8 +2,8 @@ import type { Hook } from "../types/hook.js";
2
2
 
3
3
  import { setCtxUser } from "../lib/asyncContext.js";
4
4
 
5
- const hook: Hook = {
6
- order: 3,
5
+ export default {
6
+ deps: ["cors"],
7
7
  handler: async (befly, ctx) => {
8
8
  const authHeader = ctx.req.headers.get("authorization");
9
9
 
@@ -22,5 +22,4 @@ const hook: Hook = {
22
22
  ctx.user = {};
23
23
  }
24
24
  }
25
- };
26
- export default hook;
25
+ } satisfies Hook;