befly 3.76.1 → 3.76.3

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 (149) hide show
  1. package/Befly.js +159 -0
  2. package/README.md +50 -11
  3. package/apis/admin/delete.js +1 -3
  4. package/apis/admin/select.js +2 -7
  5. package/apis/admin/update.js +1 -5
  6. package/apis/api/select.js +2 -7
  7. package/apis/auth/login.js +16 -20
  8. package/apis/dict/delete.js +1 -1
  9. package/apis/dict/detail.js +1 -3
  10. package/apis/dict/select.js +1 -2
  11. package/apis/dict/update.js +1 -1
  12. package/apis/dictType/delete.js +1 -1
  13. package/apis/dictType/detail.js +1 -1
  14. package/apis/dictType/insert.js +1 -1
  15. package/apis/dictType/select.js +2 -7
  16. package/apis/dictType/update.js +2 -2
  17. package/apis/email/config.js +4 -7
  18. package/apis/email/logList.js +2 -7
  19. package/apis/email/send.js +1 -2
  20. package/apis/email/verify.js +1 -3
  21. package/apis/loginLog/select.js +2 -7
  22. package/apis/menu/select.js +2 -7
  23. package/apis/operateLog/select.js +2 -7
  24. package/apis/role/apiSave.js +2 -2
  25. package/apis/role/menuSave.js +2 -2
  26. package/apis/role/select.js +2 -7
  27. package/apis/source/imageList.js +2 -5
  28. package/apis/tongJi/dailyReport.js +12 -13
  29. package/apis/tongJi/dailyReportSelect.js +1 -2
  30. package/apis/tongJi/dailyStats.js +1 -1
  31. package/apis/tongJi/dailyStatsDistribution.js +2 -2
  32. package/apis/tongJi/errorList.js +1 -2
  33. package/apis/tongJi/errorReport.js +1 -2
  34. package/apis/tongJi/projectDelete.js +1 -3
  35. package/apis/tongJi/projectSelect.js +2 -4
  36. package/apis/tongJi/projectUpdate.js +2 -2
  37. package/apis/upload/file.js +7 -5
  38. package/checks/api.js +43 -66
  39. package/checks/config.js +17 -12
  40. package/checks/corns.js +28 -46
  41. package/checks/field.js +18 -0
  42. package/checks/items.js +16 -60
  43. package/checks/menu.js +28 -39
  44. package/checks/table.js +106 -26
  45. package/checks/validation.js +13 -0
  46. package/configs/beflyConfig.json +6 -6
  47. package/configs/constConfig.js +2 -63
  48. package/exports.js +2 -0
  49. package/hooks/auth.js +11 -7
  50. package/hooks/parser.js +55 -59
  51. package/hooks/permission.js +1 -0
  52. package/hooks/rateLimit.js +25 -62
  53. package/hooks/validator.js +43 -31
  54. package/index.js +43 -344
  55. package/{lib → libs}/cacheHelper.js +3 -8
  56. package/libs/cron.js +60 -0
  57. package/libs/logger/index.js +1 -0
  58. package/libs/logger/logger.js +245 -0
  59. package/libs/logger/sanitize.js +115 -0
  60. package/{lib → libs/mysql}/dbHelper.js +100 -73
  61. package/{lib → libs/mysql}/dbParse.js +16 -9
  62. package/{lib → libs/mysql}/dbUtil.js +15 -32
  63. package/libs/mysql/error.js +29 -0
  64. package/libs/mysql/index.js +6 -0
  65. package/libs/mysql/is.js +29 -0
  66. package/libs/mysql/mysql.js +43 -0
  67. package/libs/mysql/sql/identifier.js +85 -0
  68. package/libs/mysql/sql/index.js +2 -0
  69. package/{lib → libs/mysql/sql}/sqlBuilder.js +2 -3
  70. package/libs/mysql/util.js +44 -0
  71. package/libs/redis/index.js +2 -0
  72. package/libs/redis/redis.js +204 -0
  73. package/libs/redis/redisError.js +8 -0
  74. package/libs/tableModel.js +72 -0
  75. package/libs/tool.js +33 -0
  76. package/libs/validator/compiler.js +248 -0
  77. package/libs/validator/index.js +10 -0
  78. package/libs/validator/parser.js +173 -0
  79. package/libs/validator/util.js +5 -0
  80. package/package.json +10 -8
  81. package/paths.js +2 -3
  82. package/plugins/cache.js +2 -1
  83. package/plugins/email.js +4 -4
  84. package/plugins/mysql.js +5 -15
  85. package/plugins/redis.js +4 -12
  86. package/router/api.js +14 -10
  87. package/router/root.js +14 -0
  88. package/router/static.js +3 -3
  89. package/schemas/api.json +99 -0
  90. package/schemas/config.json +255 -0
  91. package/schemas/corn.json +39 -0
  92. package/schemas/item.json +43 -0
  93. package/schemas/menu.json +44 -0
  94. package/schemas/table.json +80 -0
  95. package/scripts/syncDb/apply.js +87 -0
  96. package/scripts/syncDb/ddl.js +43 -0
  97. package/scripts/syncDb/index.js +175 -30
  98. package/scripts/syncDb/model.js +60 -0
  99. package/scripts/syncDb/plan.js +160 -0
  100. package/scripts/syncDb/preflight.js +98 -0
  101. package/scripts/syncDb/report.js +177 -162
  102. package/scripts/syncDb/snapshot.js +118 -0
  103. package/tables/admin.json +51 -53
  104. package/tables/api.json +28 -39
  105. package/tables/dailyReport.json +85 -73
  106. package/tables/dict.json +27 -39
  107. package/tables/dictType.json +20 -34
  108. package/tables/emailLog.json +49 -47
  109. package/tables/errorReport.json +86 -60
  110. package/tables/file.json +47 -50
  111. package/tables/loginLog.json +68 -55
  112. package/tables/menu.json +20 -34
  113. package/tables/operateLog.json +53 -47
  114. package/tables/project.json +18 -30
  115. package/tables/role.json +33 -37
  116. package/utils/cors.js +37 -41
  117. package/utils/deepMerge.js +3 -1
  118. package/utils/error.js +1 -56
  119. package/utils/id.js +44 -0
  120. package/utils/is.js +6 -243
  121. package/utils/response.js +12 -1
  122. package/utils/scanFiles.js +13 -4
  123. package/utils/scanSources.js +58 -20
  124. package/utils/util.js +11 -163
  125. package/apis/_apis.js +0 -20
  126. package/apis/auth/sendSmsCode.js +0 -24
  127. package/configs/regexpAlias.json +0 -55
  128. package/lib/connect.js +0 -119
  129. package/lib/logger.js +0 -430
  130. package/lib/redisHelper.js +0 -399
  131. package/lib/validator.js +0 -274
  132. package/lib/xmlParse.js +0 -149
  133. package/plugins/config.js +0 -13
  134. package/plugins/cron.js +0 -115
  135. package/plugins/logger.js +0 -17
  136. package/plugins/tool.js +0 -131
  137. package/plugins/xmlParse.js +0 -10
  138. package/schemas/config.js +0 -67
  139. package/scripts/syncDb/context.js +0 -120
  140. package/scripts/syncDb/diff.js +0 -279
  141. package/scripts/syncDb/transform.js +0 -113
  142. package/sql/befly.sql +0 -271
  143. package/utils/email.js +0 -3
  144. package/utils/fieldClear.js +0 -22
  145. package/utils/formatValidationIssues.js +0 -28
  146. package/utils/getClientIp.js +0 -47
  147. package/utils/loggerUtils.js +0 -196
  148. package/utils/regexpUtil.js +0 -52
  149. /package/{lib → libs}/smtpText.js +0 -0
package/Befly.js ADDED
@@ -0,0 +1,159 @@
1
+ import { Logger } from "#befly/libs/logger/index.js";
2
+
3
+ import { BEFLY_ADMIN_TABLE, BEFLY_API_TABLE, BEFLY_MENU_TABLE, BEFLY_ROLE_TABLE } from "./configs/constConfig.js";
4
+ import { createCron, registerCorns } from "./libs/cron.js";
5
+ import { tool } from "./libs/tool.js";
6
+ import { apiHandler } from "./router/api.js";
7
+ import { rootHandler } from "./router/root.js";
8
+ import { staticHandler } from "./router/static.js";
9
+ import { syncApi } from "./sync/api.js";
10
+ import { syncCache } from "./sync/cache.js";
11
+ import { syncDev } from "./sync/dev.js";
12
+ import { syncMenu } from "./sync/menu.js";
13
+ import { calcPerfTime } from "./utils/calcPerfTime.js";
14
+ import { createError } from "./utils/error.js";
15
+ import { isPrimaryProcess } from "./utils/is.js";
16
+ import { waitFor } from "./utils/util.js";
17
+
18
+ const SYNC_READY_KEY = "befly:syncReady";
19
+
20
+ async function assertRuntimeReady(context) {
21
+ for (const key of ["redis", "mysql", "cache"]) {
22
+ if (!context[key]) throw createError(`启动失败:ctx.${key} 未初始化`, { code: "runtime", subsystem: "start", operation: "runtimeReady" });
23
+ }
24
+
25
+ const missingTables = [];
26
+ for (const table of [BEFLY_API_TABLE, BEFLY_MENU_TABLE, BEFLY_ADMIN_TABLE, BEFLY_ROLE_TABLE]) {
27
+ if (!(await context.mysql.tableExists(table)).data) missingTables.push(table);
28
+ }
29
+ if (missingTables.length > 0) throw createError(`同步依赖表缺失: ${missingTables.join("、")}`, { code: "runtime", subsystem: "start", operation: "tableExists", missingTables: missingTables });
30
+ }
31
+
32
+ export class Befly {
33
+ constructor(init = {}) {
34
+ this.context = {
35
+ config: init.config || {},
36
+ tables: init.tables || {},
37
+ logger: Logger,
38
+ tool: tool
39
+ };
40
+ this.menus = init.menus || [];
41
+ this.apis = init.apis || [];
42
+ this.hooks = init.hooks || [];
43
+ this.plugins = init.plugins || [];
44
+ this.corns = init.corns || [];
45
+ this.server = null;
46
+ this.started = false;
47
+ }
48
+
49
+ async start() {
50
+ if (this.started) throw createError("Befly 已启动", { code: "policy", subsystem: "start", operation: "duplicate" });
51
+
52
+ try {
53
+ const serverStartTime = Bun.nanoseconds();
54
+ const pluginsStartTime = Bun.nanoseconds();
55
+ for (const item of this.plugins.toSorted((a, b) => a.order - b.order)) {
56
+ const pluginStartTime = Bun.nanoseconds();
57
+ this.context[item.fileName] = await item.handler(this.context);
58
+ Logger.info(`启动 插件 ${item.fileName} 耗时 ${calcPerfTime(pluginStartTime)}`);
59
+ }
60
+ Logger.info(`启动 插件初始化完成,耗时 ${calcPerfTime(pluginsStartTime)}`);
61
+
62
+ const runtimeReadyStartTime = Bun.nanoseconds();
63
+ await assertRuntimeReady(this.context);
64
+ Logger.info(`启动 运行时依赖检查完成,耗时 ${calcPerfTime(runtimeReadyStartTime)}`);
65
+
66
+ if (isPrimaryProcess()) {
67
+ const syncApiStartTime = Bun.nanoseconds();
68
+ await syncApi(this.context, this.apis);
69
+ Logger.info(`启动 API 同步完成,耗时 ${calcPerfTime(syncApiStartTime)}`);
70
+
71
+ const syncMenuStartTime = Bun.nanoseconds();
72
+ await syncMenu(this.context, this.menus);
73
+ Logger.info(`启动 菜单同步完成,耗时 ${calcPerfTime(syncMenuStartTime)}`);
74
+
75
+ const syncDevStartTime = Bun.nanoseconds();
76
+ await syncDev(this.context);
77
+ Logger.info(`启动 开发者数据同步完成,耗时 ${calcPerfTime(syncDevStartTime)}`);
78
+
79
+ const syncCacheStartTime = Bun.nanoseconds();
80
+ await syncCache(this.context);
81
+ Logger.info(`启动 缓存同步完成,耗时 ${calcPerfTime(syncCacheStartTime)}`);
82
+
83
+ const syncReadyStartTime = Bun.nanoseconds();
84
+ await this.context.redis.setString(SYNC_READY_KEY, String(Date.now()), 300);
85
+ Logger.info(`启动 Redis 就绪标记完成,耗时 ${calcPerfTime(syncReadyStartTime)}`);
86
+ } else {
87
+ const syncWaitStartTime = Bun.nanoseconds();
88
+ const startAt = Date.now();
89
+ await waitFor({
90
+ label: "主进程同步完成",
91
+ check: async () => Number(await this.context.redis.getString(SYNC_READY_KEY)) > startAt
92
+ });
93
+ Logger.info(`启动 等待主进程同步完成,耗时 ${calcPerfTime(syncWaitStartTime)}`);
94
+ }
95
+
96
+ const routeStartTime = Bun.nanoseconds();
97
+ this.context.cron = createCron(this.context);
98
+ registerCorns(this.context, this.corns);
99
+ this.hooks = this.hooks.toSorted((a, b) => a.order - b.order);
100
+ const apiMap = Object.fromEntries(this.apis.map((api) => [api.apiPath, api]));
101
+
102
+ const apiFetch = apiHandler(apiMap, this.hooks, this.context);
103
+ const rootFetch = rootHandler(this.context.config);
104
+ const staticFetch = staticHandler(this.context.config.cors, this.context.config.upload);
105
+ Logger.info(`启动 路由构建完成,耗时 ${calcPerfTime(routeStartTime)}`);
106
+
107
+ const listenStartTime = Bun.nanoseconds();
108
+ this.server = Bun.serve({
109
+ port: this.context.config.appPort,
110
+ hostname: this.context.config.appHost,
111
+ development: this.context.config.runMode === "development",
112
+ maxRequestBodySize: Math.max(this.context.config.bodyLimit, this.context.config.upload.maxSize * 1024 * 1024),
113
+ fetch: async (req, server) => {
114
+ const pathname = new URL(req.url).pathname;
115
+ if (pathname.startsWith("/api/")) return apiFetch(req, server);
116
+ if (pathname.startsWith("/public/")) return staticFetch(req);
117
+ if (pathname === "/") return rootFetch();
118
+ return Response.json({ code: 1, msg: "路径不存在" }, { status: 404 });
119
+ },
120
+ error: (error) => {
121
+ Logger.error("服务运行错误", error);
122
+ return Response.json(
123
+ {
124
+ code: 1,
125
+ msg: "内部服务器错误",
126
+ ...(this.context.config.runMode === "development" ? { error: error.message, stack: error.stack } : {})
127
+ },
128
+ { status: 500 }
129
+ );
130
+ }
131
+ });
132
+
133
+ this.started = true;
134
+ Logger.info(`启动 Bun.serve 监听完成,耗时 ${calcPerfTime(listenStartTime)}`);
135
+ Logger.info(`启动总耗时 ${calcPerfTime(serverStartTime)}`);
136
+ Logger.info(`${this.context.config.appName} 启动成功`, { url: this.server.url, startupTime: calcPerfTime(serverStartTime) });
137
+ return this.server;
138
+ } catch (error) {
139
+ Logger.error("项目启动失败", error);
140
+ await this.stop();
141
+ throw createError("运行时错误", { cause: error, code: error?.code || "runtime", subsystem: "start", operation: "start" });
142
+ }
143
+ }
144
+
145
+ async stop() {
146
+ this.server?.stop();
147
+ this.server = null;
148
+ this.context.cron?.stopAll();
149
+
150
+ for (const item of this.plugins.toSorted((a, b) => b.order - a.order)) {
151
+ const resource = this.context[item.fileName];
152
+ if (resource?.close) await resource.close();
153
+ else if (resource?.stop) await resource.stop();
154
+ }
155
+
156
+ this.started = false;
157
+ await Logger.flush();
158
+ }
159
+ }
package/README.md CHANGED
@@ -1,18 +1,57 @@
1
- # Befly - 野蜂飞舞
1
+ # Befly Core
2
2
 
3
- ![野蜂飞舞](https://static.yicode.tech/befly.svg)
3
+ Befly Core 是面向 Bun 的 API 框架内核,负责项目启动、源码扫描、结构检查、插件与 Hook 生命周期、API 路由、参数解析验证、权限、缓存、静态文件和内置管理能力。
4
4
 
5
- > 道生一,一生二,二生三,三生万物
5
+ ## 使用
6
6
 
7
7
  ```js
8
- "bundle": "bun build ./index.js --outfile ./befly.js --target bun --format esm --packages bundle",
9
- "bundle:min": "bun build ./index.js --outfile ./befly.min.js --target bun --format esm --packages bundle --minify",
10
- "build": "rimraf befly.js befly.min.js && bun run bundle && bun run bundle:min"
8
+ import { createBefly } from "befly";
9
+
10
+ const app = await createBefly(config, menus);
11
+ await app.start();
12
+
13
+ // 关闭 HTTP、Cron、MySQL、Redis 等运行时资源
14
+ await app.stop();
15
+ ```
16
+
17
+ 接口 Handler 可直接使用上下文能力:
18
+
19
+ ```js
20
+ export default {
21
+ name: "示例接口",
22
+ method: "POST",
23
+ body: "none",
24
+ auth: false,
25
+ fields: {},
26
+ required: [],
27
+ handler: async (befly) => {
28
+ return befly.tool.Yes("操作成功", {
29
+ appName: befly.config.appName
30
+ });
31
+ }
32
+ };
11
33
  ```
12
34
 
13
- 我们把要求和实现对齐一下,要符合如下规范:
35
+ ## 主要目录
36
+
37
+ ```text
38
+ apis/ 内置 API
39
+ checks/ 启动期结构检查
40
+ configs/ 默认配置与固定常量
41
+ hooks/ 请求生命周期 Hook
42
+ lib/ 内核运行时实现
43
+ plugins/ 有状态服务插件
44
+ router/ API 与静态文件路由
45
+ schemas/ 启动检查 Schema
46
+ tables/ 内置 Table 定义
47
+ utils/ Core 基础工具
48
+ tests/ 单元与运行时测试
49
+ ```
14
50
 
15
- 1. 单表查询,不传fields或fields为空数组,表示查询所有字段。
16
- 2. 单表查询,fields指定查询字段,表示明确只查询这些字段。
17
- 3. 单表查询,fields用!感叹号开头,表示排除不查询这些字段。
18
- 4. 单表查询,不存在明确查询字段又排除某些字段的混合情况。
51
+ ## 质量验证
52
+
53
+ ```bash
54
+ bun run format -- opensource/core
55
+ bun run lint -- opensource/core
56
+ bun run test -- opensource/core
57
+ ```
@@ -1,12 +1,10 @@
1
- import adminTable from "#befly/tables/admin.json";
2
-
3
1
  export default {
4
2
  name: "删除管理员",
5
3
  method: "POST",
6
4
  body: "none",
7
5
  auth: true,
8
6
  fields: {
9
- id: adminTable.id
7
+ id: { name: "ID", paramType: "integer", minValue: 1 }
10
8
  },
11
9
  required: ["id"],
12
10
  handler: async (befly, ctx) => {
@@ -1,15 +1,10 @@
1
- import { queryFields } from "#befly/apis/_apis.js";
2
- import adminTable from "#befly/tables/admin.json";
3
-
4
1
  export default {
5
2
  name: "查询管理员列表",
3
+ category: "select",
6
4
  method: "POST",
7
5
  body: "none",
8
6
  auth: true,
9
- fields: {
10
- ...queryFields,
11
- state: adminTable.state
12
- },
7
+ fields: {},
13
8
  required: [],
14
9
  handler: async (befly, ctx) => {
15
10
  const result = await befly.mysql.getList({
@@ -7,14 +7,12 @@ export default {
7
7
  body: "none",
8
8
  auth: true,
9
9
  fields: {
10
- id: { name: "ID", input: "integer", min: 1, max: null },
10
+ id: { name: "ID", paramType: "integer", minValue: 1 },
11
11
  username: adminTable.username,
12
12
  nickname: adminTable.nickname,
13
13
  roleCode: adminTable.roleCode,
14
14
  avatar: adminTable.avatar,
15
15
  email: adminTable.email,
16
- lastLoginIp: adminTable.lastLoginIp,
17
- lastLoginTime: adminTable.lastLoginTime,
18
16
  password: adminTable.password,
19
17
  phone: adminTable.phone
20
18
  },
@@ -72,8 +70,6 @@ export default {
72
70
 
73
71
  if (ctx.body.avatar !== undefined) updateData.avatar = ctx.body.avatar;
74
72
  if (ctx.body.email !== undefined) updateData.email = ctx.body.email;
75
- if (ctx.body.lastLoginIp !== undefined) updateData.lastLoginIp = ctx.body.lastLoginIp;
76
- if (ctx.body.lastLoginTime !== undefined) updateData.lastLoginTime = ctx.body.lastLoginTime;
77
73
  if (ctx.body.password !== undefined) {
78
74
  updateData.password = await hashPassword(ctx.body.password);
79
75
  }
@@ -1,15 +1,10 @@
1
- import { queryFields } from "#befly/apis/_apis.js";
2
- import apiTable from "#befly/tables/api.json";
3
-
4
1
  export default {
5
2
  name: "获取接口列表",
3
+ category: "select",
6
4
  method: "POST",
7
5
  body: "none",
8
6
  auth: true,
9
- fields: {
10
- ...queryFields,
11
- state: apiTable.state
12
- },
7
+ fields: {},
13
8
  required: [],
14
9
  handler: async (befly, ctx) => {
15
10
  const result = await befly.mysql.getList({
@@ -11,17 +11,15 @@ export default {
11
11
  fields: {
12
12
  account: {
13
13
  name: "账号",
14
- input: "string",
15
- min: 1,
16
- max: 100
14
+ paramType: "string",
15
+ minValue: 1,
16
+ maxValue: 100
17
17
  },
18
18
  password: adminTable.password,
19
19
  loginType: {
20
20
  name: "登录类型",
21
- input: "enum",
22
- check: "username|email|phone",
23
- min: null,
24
- max: null
21
+ paramType: "string",
22
+ enum: ["username", "email", "phone"]
25
23
  },
26
24
  clientType: loginLogTable.clientType,
27
25
  productName: loginLogTable.productName,
@@ -35,22 +33,20 @@ export default {
35
33
  },
36
34
  required: ["account", "password", "loginType"],
37
35
  handler: async (befly, ctx) => {
38
- const body = ctx.body || {};
39
-
40
36
  const logData = {
41
37
  adminId: 0,
42
38
  username: ctx.body.account,
43
39
  nickname: "",
44
- ip: ctx.ip || "",
45
- clientType: body.clientType || "",
46
- productName: body.productName || "",
47
- productCode: body.productCode || "",
48
- productVersion: body.productVersion || "",
49
- clientVersion: body.clientVersion || "",
50
- os: body.os || "",
51
- system: body.system || "",
52
- brand: body.brand || "",
53
- model: body.model || "",
40
+ ip: ctx.ip,
41
+ clientType: ctx.body.clientType,
42
+ productName: ctx.body.productName,
43
+ productCode: ctx.body.productCode,
44
+ productVersion: ctx.body.productVersion,
45
+ clientVersion: ctx.body.clientVersion,
46
+ os: ctx.body.os,
47
+ system: ctx.body.system,
48
+ brand: ctx.body.brand,
49
+ model: ctx.body.model,
54
50
  loginTime: Date.now(),
55
51
  loginResult: 0,
56
52
  failReason: ""
@@ -95,7 +91,7 @@ export default {
95
91
  logData.loginResult = 1;
96
92
  await befly.mysql.insData({ table: "beflyLoginLog", data: logData });
97
93
 
98
- const ttlSeconds = toSessionTtlSeconds(befly.config?.session?.expireDays);
94
+ const ttlSeconds = toSessionTtlSeconds(befly.config.session.expireDays);
99
95
  const sid = Bun.randomUUIDv7();
100
96
  const sessionKey = `session:${sid}`;
101
97
 
@@ -4,7 +4,7 @@ export default {
4
4
  body: "none",
5
5
  auth: true,
6
6
  fields: {
7
- id: { name: "ID", input: "integer", min: 1, max: null }
7
+ id: { name: "ID", paramType: "integer", minValue: 1 }
8
8
  },
9
9
  required: ["id"],
10
10
  handler: async (befly, ctx) => {
@@ -1,5 +1,3 @@
1
- import dictTable from "#befly/tables/dict.json";
2
-
3
1
  import { dictReadFields, dictReadLeftJoin, dictReadTable } from "./_dict.js";
4
2
 
5
3
  export default {
@@ -8,7 +6,7 @@ export default {
8
6
  body: "none",
9
7
  auth: false,
10
8
  fields: {
11
- id: dictTable.id
9
+ id: { name: "ID", paramType: "integer", minValue: 1 }
12
10
  },
13
11
  required: ["id"],
14
12
  handler: async (befly, ctx) => {
@@ -1,15 +1,14 @@
1
- import { queryFields } from "#befly/apis/_apis.js";
2
1
  import dictTable from "#befly/tables/dict.json";
3
2
 
4
3
  import { dictReadFields, dictReadLeftJoin, dictReadOrderBy, dictReadTable } from "./_dict.js";
5
4
 
6
5
  export default {
7
6
  name: "获取字典列表",
7
+ category: "select",
8
8
  method: "POST",
9
9
  body: "none",
10
10
  auth: false,
11
11
  fields: {
12
- ...queryFields,
13
12
  typeCode: dictTable.typeCode
14
13
  },
15
14
  required: [],
@@ -8,7 +8,7 @@ export default {
8
8
  body: "none",
9
9
  auth: true,
10
10
  fields: {
11
- id: dictTable.id,
11
+ id: { name: "ID", paramType: "integer", minValue: 1 },
12
12
  typeCode: dictTable.typeCode,
13
13
  key: dictTable.key,
14
14
  label: dictTable.label,
@@ -4,7 +4,7 @@ export default {
4
4
  body: "none",
5
5
  auth: true,
6
6
  fields: {
7
- id: { name: "ID", input: "integer", min: 1, max: null }
7
+ id: { name: "ID", paramType: "integer", minValue: 1 }
8
8
  },
9
9
  required: ["id"],
10
10
  handler: async (befly, ctx) => {
@@ -3,7 +3,7 @@ export default {
3
3
  method: "POST",
4
4
  body: "none",
5
5
  auth: true,
6
- fields: { id: { name: "ID", input: "integer", min: 1, max: null } },
6
+ fields: { id: { name: "ID", paramType: "integer", minValue: 1 } },
7
7
  required: ["id"],
8
8
  handler: async (befly, ctx) => {
9
9
  const detail = await befly.mysql.getOne({
@@ -10,7 +10,7 @@ export default {
10
10
  name: dictTypeTable.name,
11
11
  description: dictTypeTable.description,
12
12
  sort: dictTypeTable.sort,
13
- state: dictTypeTable.state
13
+ state: { name: "状态", paramType: "integer" }
14
14
  },
15
15
  required: ["code", "name"],
16
16
  handler: async (befly, ctx) => {
@@ -1,15 +1,10 @@
1
- import { queryFields } from "#befly/apis/_apis.js";
2
- import dictTypeTable from "#befly/tables/dictType.json";
3
-
4
1
  export default {
5
2
  name: "获取字典类型列表",
3
+ category: "select",
6
4
  method: "POST",
7
5
  body: "none",
8
6
  auth: true,
9
- fields: {
10
- ...queryFields,
11
- state: dictTypeTable.state
12
- },
7
+ fields: {},
13
8
  required: [],
14
9
  handler: async (befly, ctx) => {
15
10
  const result = await befly.mysql.getList({
@@ -6,12 +6,12 @@ export default {
6
6
  body: "none",
7
7
  auth: true,
8
8
  fields: {
9
- id: { name: "ID", input: "integer", min: 1, max: null },
9
+ id: { name: "ID", paramType: "integer", minValue: 1 },
10
10
  code: dictTypeTable.code,
11
11
  name: dictTypeTable.name,
12
12
  description: dictTypeTable.description,
13
13
  sort: dictTypeTable.sort,
14
- state: dictTypeTable.state
14
+ state: { name: "状态", paramType: "integer" }
15
15
  },
16
16
  required: ["id"],
17
17
  handler: async (befly, ctx) => {
@@ -1,5 +1,3 @@
1
- import { hasEmailConfig } from "#befly/utils/email.js";
2
-
3
1
  export default {
4
2
  name: "获取邮件配置",
5
3
  method: "POST",
@@ -8,16 +6,15 @@ export default {
8
6
  fields: {},
9
7
  required: [],
10
8
  handler: async (befly) => {
11
- const config = befly?.config?.email || {};
9
+ const config = befly.config.email;
12
10
 
13
11
  return befly.tool.Yes("获取成功", {
14
12
  host: config.host || "",
15
13
  port: config.port || 0,
16
14
  secure: config.secure,
17
- user: config.user || "",
18
- pass: config.pass || "",
19
- label: config.label || "",
20
- configured: hasEmailConfig(config)
15
+ user: config.user,
16
+ label: config.label,
17
+ configured: !(!config.host || !config.user || !config.pass)
21
18
  });
22
19
  }
23
20
  };
@@ -1,15 +1,10 @@
1
- import { queryFields } from "#befly/apis/_apis.js";
2
- import emailLogTable from "#befly/tables/emailLog.json";
3
-
4
1
  export default {
5
2
  name: "邮件发送日志列表",
3
+ category: "select",
6
4
  method: "POST",
7
5
  body: "none",
8
6
  auth: true,
9
- fields: {
10
- ...queryFields,
11
- state: emailLogTable.state
12
- },
7
+ fields: {},
13
8
  required: [],
14
9
  handler: async (befly, ctx) => {
15
10
  const result = await befly.mysql.getList({
@@ -1,5 +1,4 @@
1
1
  import emailLogTable from "#befly/tables/emailLog.json";
2
- import { hasEmailConfig } from "#befly/utils/email.js";
3
2
 
4
3
  export default {
5
4
  name: "发送邮件",
@@ -17,7 +16,7 @@ export default {
17
16
  handler: async (befly, ctx) => {
18
17
  const emailConfig = befly.config.email || {};
19
18
 
20
- if (!hasEmailConfig(emailConfig)) {
19
+ if (!emailConfig.host || !emailConfig.user || !emailConfig.pass) {
21
20
  return befly.tool.No("邮件未配置,请检查 SMTP 配置");
22
21
  }
23
22
 
@@ -1,5 +1,3 @@
1
- import { hasEmailConfig } from "#befly/utils/email.js";
2
-
3
1
  export default {
4
2
  name: "验证邮件配置",
5
3
  method: "POST",
@@ -10,7 +8,7 @@ export default {
10
8
  handler: async (befly) => {
11
9
  const emailConfig = befly?.config?.email || {};
12
10
 
13
- if (!hasEmailConfig(emailConfig)) {
11
+ if (!emailConfig.host || !emailConfig.user || !emailConfig.pass) {
14
12
  return befly.tool.No("邮件未配置,请检查 SMTP 配置");
15
13
  }
16
14
 
@@ -1,15 +1,10 @@
1
- import { queryFields } from "#befly/apis/_apis.js";
2
- import loginLogTable from "#befly/tables/loginLog.json";
3
-
4
1
  export default {
5
2
  name: "获取登录日志列表",
3
+ category: "select",
6
4
  method: "POST",
7
5
  body: "none",
8
6
  auth: true,
9
- fields: {
10
- ...queryFields,
11
- state: loginLogTable.state
12
- },
7
+ fields: {},
13
8
  required: [],
14
9
  handler: async (befly, ctx) => {
15
10
  const result = await befly.mysql.getList({
@@ -1,15 +1,10 @@
1
- import { queryFields } from "#befly/apis/_apis.js";
2
- import menuTable from "#befly/tables/menu.json";
3
-
4
1
  export default {
5
2
  name: "获取菜单列表",
3
+ category: "select",
6
4
  method: "POST",
7
5
  body: "none",
8
6
  auth: true,
9
- fields: {
10
- ...queryFields,
11
- state: menuTable.state
12
- },
7
+ fields: {},
13
8
  required: [],
14
9
  handler: async (befly, ctx) => {
15
10
  const menus = await befly.mysql.getList({
@@ -1,15 +1,10 @@
1
- import { queryFields } from "#befly/apis/_apis.js";
2
- import operateLogTable from "#befly/tables/operateLog.json";
3
-
4
1
  export default {
5
2
  name: "获取操作日志列表",
3
+ category: "select",
6
4
  method: "POST",
7
5
  body: "none",
8
6
  auth: true,
9
- fields: {
10
- ...queryFields,
11
- state: operateLogTable.state
12
- },
7
+ fields: {},
13
8
  required: [],
14
9
  handler: async (befly, ctx) => {
15
10
  const result = await befly.mysql.getList({
@@ -11,9 +11,9 @@ export default {
11
11
  roleCode: roleTable.code,
12
12
  apiPaths: roleTable.apis
13
13
  },
14
- required: ["roleCode"],
14
+ required: ["roleCode", "apiPaths"],
15
15
  handler: async (befly, ctx) => {
16
- const apiPaths = ctx.body.apiPaths || [];
16
+ const apiPaths = ctx.body.apiPaths;
17
17
 
18
18
  const role = await getRoleByCode(befly, ctx.body.roleCode);
19
19
 
@@ -11,9 +11,9 @@ export default {
11
11
  roleCode: roleTable.code,
12
12
  menuPaths: roleTable.menus
13
13
  },
14
- required: ["roleCode"],
14
+ required: ["roleCode", "menuPaths"],
15
15
  handler: async (befly, ctx) => {
16
- const menuPaths = ctx.body.menuPaths || [];
16
+ const menuPaths = ctx.body.menuPaths;
17
17
 
18
18
  const role = await getRoleByCode(befly, ctx.body.roleCode);
19
19