befly 3.16.10 → 3.17.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 (184) hide show
  1. package/README.md +0 -129
  2. package/befly.js +16413 -0
  3. package/befly.min.js +72 -0
  4. package/package.json +19 -29
  5. package/scripts/syncDb/context.js +99 -0
  6. package/scripts/syncDb/diff.js +133 -0
  7. package/scripts/syncDb/index.js +70 -0
  8. package/scripts/syncDb/query.js +26 -0
  9. package/scripts/syncDb/report.js +190 -0
  10. package/scripts/syncDb/transform.js +111 -0
  11. package/dist/befly.config.d.ts +0 -7
  12. package/dist/befly.config.js +0 -128
  13. package/dist/befly.js +0 -17348
  14. package/dist/befly.min.js +0 -23
  15. package/dist/checks/checkApi.d.ts +0 -1
  16. package/dist/checks/checkApi.js +0 -139
  17. package/dist/checks/checkConfig.d.ts +0 -9
  18. package/dist/checks/checkConfig.js +0 -255
  19. package/dist/checks/checkHook.d.ts +0 -1
  20. package/dist/checks/checkHook.js +0 -132
  21. package/dist/checks/checkMenu.d.ts +0 -3
  22. package/dist/checks/checkMenu.js +0 -106
  23. package/dist/checks/checkPlugin.d.ts +0 -1
  24. package/dist/checks/checkPlugin.js +0 -132
  25. package/dist/checks/checkTable.d.ts +0 -7
  26. package/dist/checks/checkTable.js +0 -431
  27. package/dist/configs/presetRegexp.d.ts +0 -145
  28. package/dist/configs/presetRegexp.js +0 -218
  29. package/dist/hooks/auth.d.ts +0 -3
  30. package/dist/hooks/auth.js +0 -24
  31. package/dist/hooks/cors.d.ts +0 -7
  32. package/dist/hooks/cors.js +0 -36
  33. package/dist/hooks/parser.d.ts +0 -10
  34. package/dist/hooks/parser.js +0 -76
  35. package/dist/hooks/permission.d.ts +0 -11
  36. package/dist/hooks/permission.js +0 -78
  37. package/dist/hooks/validator.d.ts +0 -7
  38. package/dist/hooks/validator.js +0 -52
  39. package/dist/index.d.ts +0 -28
  40. package/dist/index.js +0 -316
  41. package/dist/lib/asyncContext.d.ts +0 -21
  42. package/dist/lib/asyncContext.js +0 -27
  43. package/dist/lib/cacheHelper.d.ts +0 -128
  44. package/dist/lib/cacheHelper.js +0 -477
  45. package/dist/lib/cacheKeys.d.ts +0 -27
  46. package/dist/lib/cacheKeys.js +0 -37
  47. package/dist/lib/cipher.d.ts +0 -153
  48. package/dist/lib/cipher.js +0 -237
  49. package/dist/lib/connect.d.ts +0 -95
  50. package/dist/lib/connect.js +0 -313
  51. package/dist/lib/dbHelper.d.ts +0 -229
  52. package/dist/lib/dbHelper.js +0 -1099
  53. package/dist/lib/dbUtils.d.ts +0 -91
  54. package/dist/lib/dbUtils.js +0 -544
  55. package/dist/lib/jwt.d.ts +0 -13
  56. package/dist/lib/jwt.js +0 -77
  57. package/dist/lib/logger.d.ts +0 -46
  58. package/dist/lib/logger.js +0 -731
  59. package/dist/lib/redisHelper.d.ts +0 -193
  60. package/dist/lib/redisHelper.js +0 -598
  61. package/dist/lib/sqlBuilder.d.ts +0 -160
  62. package/dist/lib/sqlBuilder.js +0 -837
  63. package/dist/lib/sqlCheck.d.ts +0 -23
  64. package/dist/lib/sqlCheck.js +0 -119
  65. package/dist/lib/validator.d.ts +0 -45
  66. package/dist/lib/validator.js +0 -424
  67. package/dist/loader/loadApis.d.ts +0 -12
  68. package/dist/loader/loadApis.js +0 -71
  69. package/dist/loader/loadHooks.d.ts +0 -7
  70. package/dist/loader/loadHooks.js +0 -50
  71. package/dist/loader/loadPlugins.d.ts +0 -8
  72. package/dist/loader/loadPlugins.js +0 -69
  73. package/dist/paths.d.ts +0 -93
  74. package/dist/paths.js +0 -100
  75. package/dist/plugins/cache.d.ts +0 -10
  76. package/dist/plugins/cache.js +0 -24
  77. package/dist/plugins/cipher.d.ts +0 -7
  78. package/dist/plugins/cipher.js +0 -14
  79. package/dist/plugins/config.d.ts +0 -3
  80. package/dist/plugins/config.js +0 -9
  81. package/dist/plugins/db.d.ts +0 -10
  82. package/dist/plugins/db.js +0 -48
  83. package/dist/plugins/jwt.d.ts +0 -6
  84. package/dist/plugins/jwt.js +0 -13
  85. package/dist/plugins/logger.d.ts +0 -10
  86. package/dist/plugins/logger.js +0 -21
  87. package/dist/plugins/redis.d.ts +0 -10
  88. package/dist/plugins/redis.js +0 -40
  89. package/dist/plugins/tool.d.ts +0 -75
  90. package/dist/plugins/tool.js +0 -105
  91. package/dist/router/api.d.ts +0 -14
  92. package/dist/router/api.js +0 -109
  93. package/dist/router/static.d.ts +0 -9
  94. package/dist/router/static.js +0 -56
  95. package/dist/scripts/ensureDist.d.ts +0 -1
  96. package/dist/scripts/ensureDist.js +0 -296
  97. package/dist/sync/syncApi.d.ts +0 -3
  98. package/dist/sync/syncApi.js +0 -163
  99. package/dist/sync/syncCache.d.ts +0 -2
  100. package/dist/sync/syncCache.js +0 -14
  101. package/dist/sync/syncDev.d.ts +0 -6
  102. package/dist/sync/syncDev.js +0 -166
  103. package/dist/sync/syncMenu.d.ts +0 -14
  104. package/dist/sync/syncMenu.js +0 -308
  105. package/dist/sync/syncTable.d.ts +0 -126
  106. package/dist/sync/syncTable.js +0 -1129
  107. package/dist/types/api.d.ts +0 -177
  108. package/dist/types/api.js +0 -4
  109. package/dist/types/befly.d.ts +0 -231
  110. package/dist/types/befly.js +0 -4
  111. package/dist/types/cache.d.ts +0 -96
  112. package/dist/types/cache.js +0 -4
  113. package/dist/types/cipher.d.ts +0 -27
  114. package/dist/types/cipher.js +0 -7
  115. package/dist/types/common.d.ts +0 -127
  116. package/dist/types/common.js +0 -5
  117. package/dist/types/context.d.ts +0 -39
  118. package/dist/types/context.js +0 -4
  119. package/dist/types/coreError.d.ts +0 -31
  120. package/dist/types/coreError.js +0 -38
  121. package/dist/types/crypto.d.ts +0 -20
  122. package/dist/types/crypto.js +0 -4
  123. package/dist/types/database.d.ts +0 -182
  124. package/dist/types/database.js +0 -4
  125. package/dist/types/hook.d.ts +0 -30
  126. package/dist/types/hook.js +0 -19
  127. package/dist/types/jwt.d.ts +0 -76
  128. package/dist/types/jwt.js +0 -4
  129. package/dist/types/logger.d.ts +0 -95
  130. package/dist/types/logger.js +0 -6
  131. package/dist/types/plugin.d.ts +0 -27
  132. package/dist/types/plugin.js +0 -17
  133. package/dist/types/redis.d.ts +0 -80
  134. package/dist/types/redis.js +0 -4
  135. package/dist/types/roleApisCache.d.ts +0 -21
  136. package/dist/types/roleApisCache.js +0 -8
  137. package/dist/types/sync.d.ts +0 -93
  138. package/dist/types/sync.js +0 -4
  139. package/dist/types/table.d.ts +0 -34
  140. package/dist/types/table.js +0 -4
  141. package/dist/types/validate.d.ts +0 -113
  142. package/dist/types/validate.js +0 -4
  143. package/dist/utils/calcPerfTime.d.ts +0 -4
  144. package/dist/utils/calcPerfTime.js +0 -13
  145. package/dist/utils/cors.d.ts +0 -8
  146. package/dist/utils/cors.js +0 -17
  147. package/dist/utils/dbFieldRules.d.ts +0 -31
  148. package/dist/utils/dbFieldRules.js +0 -94
  149. package/dist/utils/fieldClear.d.ts +0 -11
  150. package/dist/utils/fieldClear.js +0 -57
  151. package/dist/utils/formatYmdHms.d.ts +0 -1
  152. package/dist/utils/formatYmdHms.js +0 -20
  153. package/dist/utils/getClientIp.d.ts +0 -6
  154. package/dist/utils/getClientIp.js +0 -39
  155. package/dist/utils/importDefault.d.ts +0 -1
  156. package/dist/utils/importDefault.js +0 -53
  157. package/dist/utils/isDirentDirectory.d.ts +0 -3
  158. package/dist/utils/isDirentDirectory.js +0 -18
  159. package/dist/utils/loadMenuConfigs.d.ts +0 -11
  160. package/dist/utils/loadMenuConfigs.js +0 -130
  161. package/dist/utils/loggerUtils.d.ts +0 -18
  162. package/dist/utils/loggerUtils.js +0 -171
  163. package/dist/utils/mergeAndConcat.d.ts +0 -7
  164. package/dist/utils/mergeAndConcat.js +0 -77
  165. package/dist/utils/normalizeFieldDefinition.d.ts +0 -18
  166. package/dist/utils/normalizeFieldDefinition.js +0 -27
  167. package/dist/utils/processInfo.d.ts +0 -26
  168. package/dist/utils/processInfo.js +0 -41
  169. package/dist/utils/response.d.ts +0 -20
  170. package/dist/utils/response.js +0 -96
  171. package/dist/utils/scanAddons.d.ts +0 -15
  172. package/dist/utils/scanAddons.js +0 -35
  173. package/dist/utils/scanCoreBuiltins.d.ts +0 -3
  174. package/dist/utils/scanCoreBuiltins.js +0 -72
  175. package/dist/utils/scanFiles.d.ts +0 -32
  176. package/dist/utils/scanFiles.js +0 -124
  177. package/dist/utils/scanSources.d.ts +0 -10
  178. package/dist/utils/scanSources.js +0 -46
  179. package/dist/utils/sortModules.d.ts +0 -28
  180. package/dist/utils/sortModules.js +0 -105
  181. package/dist/utils/sqlUtil.d.ts +0 -33
  182. package/dist/utils/sqlUtil.js +0 -146
  183. package/dist/utils/util.d.ts +0 -172
  184. package/dist/utils/util.js +0 -517
@@ -1,477 +0,0 @@
1
- /**
2
- * 缓存助手 - TypeScript 版本
3
- * 负责在服务器启动时缓存接口、菜单和角色权限到 Redis
4
- */
5
- import { CoreError } from "../types/coreError";
6
- import { CacheKeys } from "./cacheKeys";
7
- import { Logger } from "./logger";
8
- /**
9
- * 缓存助手类
10
- */
11
- export class CacheHelper {
12
- db;
13
- redis;
14
- constructor(deps) {
15
- this.db = deps.db;
16
- this.redis = deps.redis;
17
- }
18
- assertApiPathname(value, errorPrefix) {
19
- if (typeof value !== "string") {
20
- throw new Error(`${errorPrefix} 必须是字符串`);
21
- }
22
- const trimmed = value.trim();
23
- if (!trimmed) {
24
- throw new Error(`${errorPrefix} 不允许为空字符串`);
25
- }
26
- if (/^(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\b/i.test(trimmed)) {
27
- throw new Error(`${errorPrefix} 不允许包含 method 前缀,应为 url.pathname(例如 /api/app/xxx)`);
28
- }
29
- if (!trimmed.startsWith("/")) {
30
- throw new Error(`${errorPrefix} 必须是 pathname(以 / 开头)`);
31
- }
32
- if (trimmed.includes(" ")) {
33
- throw new Error(`${errorPrefix} 不允许包含空格`);
34
- }
35
- return trimmed;
36
- }
37
- assertMenuPathname(value, errorPrefix) {
38
- if (typeof value !== "string") {
39
- throw new Error(`${errorPrefix} 必须是字符串`);
40
- }
41
- const trimmed = value.trim();
42
- if (!trimmed) {
43
- throw new Error(`${errorPrefix} 不允许为空字符串`);
44
- }
45
- if (!trimmed.startsWith("/")) {
46
- throw new Error(`${errorPrefix} 必须是 pathname(以 / 开头)`);
47
- }
48
- if (trimmed.includes(" ")) {
49
- throw new Error(`${errorPrefix} 不允许包含空格`);
50
- }
51
- if (trimmed.length > 1 && trimmed.endsWith("/")) {
52
- throw new Error(`${errorPrefix} 不允许以 / 结尾`);
53
- }
54
- return trimmed;
55
- }
56
- assertApiPathList(value, roleCode) {
57
- if (value === null || value === undefined)
58
- return [];
59
- let list = value;
60
- // 兼容历史/手工数据:apis 可能被存成 JSON 字符串或 "null"
61
- if (typeof list === "string") {
62
- const trimmed = list.trim();
63
- // TEXT 字段常见历史值:"null"(表示空)
64
- if (trimmed === "" || trimmed === "null") {
65
- return [];
66
- }
67
- if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
68
- try {
69
- list = JSON.parse(trimmed);
70
- }
71
- catch {
72
- throw new Error(`角色权限数据不合法:addon_admin_role.apis JSON 解析失败,roleCode=${roleCode}`);
73
- }
74
- }
75
- }
76
- if (!Array.isArray(list)) {
77
- const typeLabel = typeof list;
78
- throw new Error(`角色权限数据不合法:addon_admin_role.apis 必须是字符串数组或 JSON 数组字符串,roleCode=${roleCode},type=${typeLabel}`);
79
- }
80
- const out = [];
81
- for (const item of list) {
82
- out.push(this.assertApiPathname(item, `角色权限数据不合法:addon_admin_role.apis 元素,roleCode=${roleCode}`));
83
- }
84
- return out;
85
- }
86
- assertMenuPathList(value, roleCode) {
87
- if (value === null || value === undefined)
88
- return [];
89
- let list = value;
90
- // 兼容历史/手工数据:menus 可能被存成 JSON 字符串或 "null"
91
- if (typeof list === "string") {
92
- const trimmed = list.trim();
93
- if (trimmed === "" || trimmed === "null") {
94
- return [];
95
- }
96
- if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
97
- try {
98
- list = JSON.parse(trimmed);
99
- }
100
- catch {
101
- throw new Error(`角色菜单权限数据不合法:addon_admin_role.menus JSON 解析失败,roleCode=${roleCode}`);
102
- }
103
- }
104
- }
105
- if (!Array.isArray(list)) {
106
- const typeLabel = typeof list;
107
- throw new Error(`角色菜单权限数据不合法:addon_admin_role.menus 必须是字符串数组或 JSON 数组字符串,roleCode=${roleCode},type=${typeLabel}`);
108
- }
109
- const out = [];
110
- for (const item of list) {
111
- out.push(this.assertMenuPathname(item, `角色菜单权限数据不合法:addon_admin_role.menus 元素,roleCode=${roleCode}`));
112
- }
113
- return out;
114
- }
115
- /**
116
- * 缓存所有接口到 Redis
117
- */
118
- async cacheApis() {
119
- try {
120
- // 检查表是否存在
121
- const tableExists = await this.db.tableExists("addon_admin_api");
122
- if (!tableExists.data) {
123
- Logger.warn("⚠️ 接口表不存在,跳过接口缓存");
124
- return;
125
- }
126
- // 从数据库查询所有接口
127
- const apiList = await this.db.getAll({
128
- table: "addon_admin_api"
129
- });
130
- // 缓存到 Redis
131
- const result = await this.redis.setObject(CacheKeys.apisAll(), apiList.data.lists);
132
- if (result === null) {
133
- Logger.warn("⚠️ 接口缓存失败");
134
- }
135
- }
136
- catch (error) {
137
- Logger.error({ err: error, msg: "⚠️ 接口缓存异常" });
138
- }
139
- }
140
- /**
141
- * 缓存所有菜单到 Redis(从数据库读取)
142
- */
143
- async cacheMenus() {
144
- try {
145
- // 检查表是否存在
146
- const tableExists = await this.db.tableExists("addon_admin_menu");
147
- if (!tableExists.data) {
148
- Logger.warn("⚠️ 菜单表不存在,跳过菜单缓存");
149
- return;
150
- }
151
- // 从数据库查询所有菜单
152
- const menus = await this.db.getAll({
153
- table: "addon_admin_menu"
154
- });
155
- // 缓存到 Redis
156
- const result = await this.redis.setObject(CacheKeys.menusAll(), menus.data.lists);
157
- if (result === null) {
158
- Logger.warn("⚠️ 菜单缓存失败");
159
- }
160
- }
161
- catch (error) {
162
- Logger.warn({ err: error, msg: "⚠️ 菜单缓存异常" });
163
- }
164
- }
165
- /**
166
- * 缓存所有角色的接口权限到 Redis
167
- * 全量重建:清理所有角色权限缓存并重建
168
- * - 极简方案:每个角色一个 Set,直接覆盖更新(DEL + SADD)
169
- */
170
- async rebuildRoleApiPermissions() {
171
- try {
172
- // 检查表是否存在
173
- const roleTableExists = await this.db.tableExists("addon_admin_role");
174
- if (!roleTableExists.data) {
175
- Logger.warn("⚠️ 角色表不存在,跳过角色权限缓存");
176
- return;
177
- }
178
- // 查询所有角色(仅取必要字段)
179
- const roles = await this.db.getAll({
180
- table: "addon_admin_role",
181
- fields: ["code", "apis"]
182
- });
183
- const roleApiPathsMap = new Map();
184
- for (const role of roles.data.lists) {
185
- if (!role?.code)
186
- continue;
187
- const apiPaths = this.assertApiPathList(role.apis, role.code);
188
- roleApiPathsMap.set(role.code, apiPaths);
189
- }
190
- const roleCodes = Array.from(roleApiPathsMap.keys());
191
- if (roleCodes.length === 0) {
192
- Logger.info("✅ 没有需要缓存的角色权限");
193
- return;
194
- }
195
- // 清理所有角色的缓存 key(保证幂等)
196
- const roleKeys = roleCodes.map((code) => CacheKeys.roleApis(code));
197
- await this.redis.delBatch(roleKeys);
198
- // 批量写入新缓存(只写入非空权限)
199
- const items = [];
200
- for (const roleCode of roleCodes) {
201
- const apiPaths = roleApiPathsMap.get(roleCode) || [];
202
- const members = Array.from(new Set(apiPaths)).sort();
203
- if (members.length > 0) {
204
- items.push({ key: CacheKeys.roleApis(roleCode), members: members });
205
- }
206
- }
207
- if (items.length > 0) {
208
- await this.redis.saddBatch(items);
209
- }
210
- // 极简方案不做版本/ready/meta:重建完成即生效
211
- }
212
- catch (error) {
213
- Logger.error({ err: error, msg: "⚠️ 角色权限缓存异常(将阻断启动)" });
214
- throw new CoreError({
215
- kind: "runtime",
216
- message: "⚠️ 角色权限缓存异常(将阻断启动)",
217
- logged: true,
218
- cause: error,
219
- meta: {
220
- subsystem: "cache",
221
- operation: "rebuildRoleApiPermissions"
222
- }
223
- });
224
- }
225
- }
226
- /**
227
- * 缓存所有角色的菜单权限到 Redis
228
- * 全量重建:清理所有角色菜单权限缓存并重建
229
- * - 每个角色一个 Set,直接覆盖更新(DEL + SADD)
230
- */
231
- async rebuildRoleMenuPermissions() {
232
- try {
233
- // 检查表是否存在
234
- const roleTableExists = await this.db.tableExists("addon_admin_role");
235
- if (!roleTableExists.data) {
236
- Logger.warn("⚠️ 角色表不存在,跳过角色菜单权限缓存");
237
- return;
238
- }
239
- // 查询所有角色(仅取必要字段)
240
- const roles = await this.db.getAll({
241
- table: "addon_admin_role",
242
- fields: ["code", "menus"]
243
- });
244
- const roleMenuPathsMap = new Map();
245
- for (const role of roles.data.lists) {
246
- if (!role?.code)
247
- continue;
248
- const menuPaths = this.assertMenuPathList(role.menus, role.code);
249
- roleMenuPathsMap.set(role.code, menuPaths);
250
- }
251
- const roleCodes = Array.from(roleMenuPathsMap.keys());
252
- if (roleCodes.length === 0) {
253
- Logger.info("✅ 没有需要缓存的角色菜单权限");
254
- return;
255
- }
256
- // 清理所有角色的缓存 key(保证幂等)
257
- const roleKeys = roleCodes.map((code) => CacheKeys.roleMenus(code));
258
- await this.redis.delBatch(roleKeys);
259
- // 批量写入新缓存(只写入非空权限)
260
- const items = [];
261
- for (const roleCode of roleCodes) {
262
- const menuPaths = roleMenuPathsMap.get(roleCode) || [];
263
- const members = Array.from(new Set(menuPaths)).sort();
264
- if (members.length > 0) {
265
- items.push({ key: CacheKeys.roleMenus(roleCode), members: members });
266
- }
267
- }
268
- if (items.length > 0) {
269
- await this.redis.saddBatch(items);
270
- }
271
- }
272
- catch (error) {
273
- Logger.error({ err: error, msg: "⚠️ 角色菜单权限缓存异常(将阻断启动)" });
274
- throw new CoreError({
275
- kind: "runtime",
276
- message: "⚠️ 角色菜单权限缓存异常(将阻断启动)",
277
- logged: true,
278
- cause: error,
279
- meta: {
280
- subsystem: "cache",
281
- operation: "rebuildRoleMenuPermissions"
282
- }
283
- });
284
- }
285
- }
286
- /**
287
- * 增量刷新单个角色的接口权限缓存
288
- * - apiIds 为空数组:仅清理缓存(防止残留)
289
- * - apiIds 非空:使用 $in 最小查询,DEL 后 SADD
290
- */
291
- async refreshRoleApiPermissions(roleCode, apiPaths) {
292
- if (!roleCode || typeof roleCode !== "string") {
293
- throw new Error("roleCode 必须是非空字符串");
294
- }
295
- if (!Array.isArray(apiPaths)) {
296
- throw new Error("apiPaths 必须是数组");
297
- }
298
- const normalizedPaths = apiPaths.map((p) => this.assertApiPathname(p, `refreshRoleApiPermissions: apiPaths 元素,roleCode=${roleCode}`));
299
- const roleKey = CacheKeys.roleApis(roleCode);
300
- // 空数组短路:保证清理残留
301
- if (normalizedPaths.length === 0) {
302
- await this.redis.del(roleKey);
303
- return;
304
- }
305
- const members = Array.from(new Set(normalizedPaths));
306
- await this.redis.del(roleKey);
307
- if (members.length > 0) {
308
- await this.redis.sadd(roleKey, members);
309
- }
310
- }
311
- /**
312
- * 增量刷新单个角色的菜单权限缓存
313
- * - menuPaths 为空数组:仅清理缓存(防止残留)
314
- * - menuPaths 非空:DEL 后 SADD
315
- */
316
- async refreshRoleMenuPermissions(roleCode, menuPaths) {
317
- if (!roleCode || typeof roleCode !== "string") {
318
- throw new Error("roleCode 必须是非空字符串");
319
- }
320
- if (!Array.isArray(menuPaths)) {
321
- throw new Error("menuPaths 必须是数组");
322
- }
323
- const normalizedPaths = menuPaths.map((p) => this.assertMenuPathname(p, `refreshRoleMenuPermissions: menuPaths 元素,roleCode=${roleCode}`));
324
- const roleKey = CacheKeys.roleMenus(roleCode);
325
- // 空数组短路:保证清理残留
326
- if (normalizedPaths.length === 0) {
327
- await this.redis.del(roleKey);
328
- return;
329
- }
330
- const members = Array.from(new Set(normalizedPaths));
331
- await this.redis.del(roleKey);
332
- if (members.length > 0) {
333
- await this.redis.sadd(roleKey, members);
334
- }
335
- }
336
- /**
337
- * 缓存所有数据
338
- */
339
- async cacheAll() {
340
- // 1. 缓存接口
341
- await this.cacheApis();
342
- // 2. 缓存菜单
343
- await this.cacheMenus();
344
- // 3. 缓存角色权限
345
- await this.rebuildRoleApiPermissions();
346
- // 4. 缓存角色菜单权限
347
- await this.rebuildRoleMenuPermissions();
348
- }
349
- /**
350
- * 获取缓存的所有接口
351
- * @returns 接口列表
352
- */
353
- async getApis() {
354
- try {
355
- const apis = await this.redis.getObject(CacheKeys.apisAll());
356
- return apis || [];
357
- }
358
- catch (error) {
359
- Logger.error({ err: error, msg: "获取接口缓存失败" });
360
- return [];
361
- }
362
- }
363
- /**
364
- * 获取缓存的所有菜单
365
- * @returns 菜单列表
366
- */
367
- async getMenus() {
368
- try {
369
- const menus = await this.redis.getObject(CacheKeys.menusAll());
370
- return menus || [];
371
- }
372
- catch (error) {
373
- Logger.error({ err: error, msg: "获取菜单缓存失败" });
374
- return [];
375
- }
376
- }
377
- /**
378
- * 获取角色的接口权限
379
- * @param roleCode - 角色代码
380
- * @returns 接口路径列表
381
- */
382
- async getRolePermissions(roleCode) {
383
- try {
384
- const permissions = await this.redis.smembers(CacheKeys.roleApis(roleCode));
385
- return permissions || [];
386
- }
387
- catch (error) {
388
- Logger.error({ err: error, roleCode: roleCode, msg: "获取角色权限缓存失败" });
389
- return [];
390
- }
391
- }
392
- /**
393
- * 获取角色的菜单权限
394
- * @param roleCode - 角色代码
395
- * @returns 菜单路径列表(menu.path)
396
- */
397
- async getRoleMenuPermissions(roleCode) {
398
- try {
399
- const permissions = await this.redis.smembers(CacheKeys.roleMenus(roleCode));
400
- return permissions || [];
401
- }
402
- catch (error) {
403
- Logger.error({ err: error, roleCode: roleCode, msg: "获取角色菜单权限缓存失败" });
404
- return [];
405
- }
406
- }
407
- /**
408
- * 检查角色是否有指定接口权限
409
- * @param roleCode - 角色代码
410
- * @param apiPath - 接口路径(url.pathname,例如 /api/user/login;与 method 无关)
411
- * @returns 是否有权限
412
- */
413
- async checkRolePermission(roleCode, apiPath) {
414
- try {
415
- const pathname = this.assertApiPathname(apiPath, "checkRolePermission: apiPath");
416
- return await this.redis.sismember(CacheKeys.roleApis(roleCode), pathname);
417
- }
418
- catch (error) {
419
- Logger.error({ err: error, roleCode: roleCode, msg: "检查角色权限失败" });
420
- return false;
421
- }
422
- }
423
- /**
424
- * 检查角色是否有指定菜单权限
425
- * @param roleCode - 角色代码
426
- * @param menuPath - 菜单路径(menu.path)
427
- * @returns 是否有权限
428
- */
429
- async checkRoleMenuPermission(roleCode, menuPath) {
430
- try {
431
- const pathname = this.assertMenuPathname(menuPath, "checkRoleMenuPermission: menuPath");
432
- return await this.redis.sismember(CacheKeys.roleMenus(roleCode), pathname);
433
- }
434
- catch (error) {
435
- Logger.error({ err: error, roleCode: roleCode, msg: "检查角色菜单权限失败" });
436
- return false;
437
- }
438
- }
439
- /**
440
- * 删除角色的接口权限缓存
441
- * @param roleCode - 角色代码
442
- * @returns 是否删除成功
443
- */
444
- async deleteRolePermissions(roleCode) {
445
- try {
446
- const result = await this.redis.del(CacheKeys.roleApis(roleCode));
447
- if (result > 0) {
448
- Logger.info(`✅ 已删除角色 ${roleCode} 的权限缓存`);
449
- return true;
450
- }
451
- return false;
452
- }
453
- catch (error) {
454
- Logger.error({ err: error, roleCode: roleCode, msg: "删除角色权限缓存失败" });
455
- return false;
456
- }
457
- }
458
- /**
459
- * 删除角色的菜单权限缓存
460
- * @param roleCode - 角色代码
461
- * @returns 是否删除成功
462
- */
463
- async deleteRoleMenuPermissions(roleCode) {
464
- try {
465
- const result = await this.redis.del(CacheKeys.roleMenus(roleCode));
466
- if (result > 0) {
467
- Logger.info(`✅ 已删除角色 ${roleCode} 的菜单权限缓存`);
468
- return true;
469
- }
470
- return false;
471
- }
472
- catch (error) {
473
- Logger.error({ err: error, roleCode: roleCode, msg: "删除角色菜单权限缓存失败" });
474
- return false;
475
- }
476
- }
477
- }
@@ -1,27 +0,0 @@
1
- /**
2
- * Cache Key 统一管理
3
- * 所有缓存键在此统一定义,避免硬编码分散
4
- */
5
- /**
6
- * Cache Key 生成函数集合
7
- */
8
- export declare class CacheKeys {
9
- /** 所有接口缓存2 */
10
- static apisAll(): string;
11
- /** 所有菜单缓存 */
12
- static menusAll(): string;
13
- /** 角色信息缓存(完整角色对象) */
14
- static roleInfo(roleCode: string): string;
15
- /**
16
- * 角色菜单权限缓存(Set 集合)
17
- * - key: role:menus:${roleCode}
18
- * - member: menu.path(例如 /permission/role)
19
- */
20
- static roleMenus(roleCode: string): string;
21
- /**
22
- * 角色接口权限缓存(Set 集合)
23
- * - key: role:apis:${roleCode}
24
- * - member: url.pathname(例如 /api/user/login;与 method 无关)
25
- */
26
- static roleApis(roleCode: string): string;
27
- }
@@ -1,37 +0,0 @@
1
- /**
2
- * Cache Key 统一管理
3
- * 所有缓存键在此统一定义,避免硬编码分散
4
- */
5
- /**
6
- * Cache Key 生成函数集合
7
- */
8
- export class CacheKeys {
9
- /** 所有接口缓存2 */
10
- static apisAll() {
11
- return "apis:all";
12
- }
13
- /** 所有菜单缓存 */
14
- static menusAll() {
15
- return "menus:all";
16
- }
17
- /** 角色信息缓存(完整角色对象) */
18
- static roleInfo(roleCode) {
19
- return `role:info:${roleCode}`;
20
- }
21
- /**
22
- * 角色菜单权限缓存(Set 集合)
23
- * - key: role:menus:${roleCode}
24
- * - member: menu.path(例如 /permission/role)
25
- */
26
- static roleMenus(roleCode) {
27
- return `role:menus:${roleCode}`;
28
- }
29
- /**
30
- * 角色接口权限缓存(Set 集合)
31
- * - key: role:apis:${roleCode}
32
- * - member: url.pathname(例如 /api/user/login;与 method 无关)
33
- */
34
- static roleApis(roleCode) {
35
- return `role:apis:${roleCode}`;
36
- }
37
- }
@@ -1,153 +0,0 @@
1
- /**
2
- * 加密工具类 - TypeScript 版本
3
- * 提供各种哈希、HMAC、密码加密等功能
4
- */
5
- import type { EncodingType, HashAlgorithm, PasswordHashOptions } from "../types/crypto";
6
- /**
7
- * 加密工具类
8
- */
9
- export declare class Cipher {
10
- /**
11
- * MD5 哈希
12
- * @param data - 要哈希的数据
13
- * @param encoding - 输出编码
14
- * @returns MD5 哈希值
15
- */
16
- static md5(data: string | Uint8Array, encoding?: EncodingType): string;
17
- /**
18
- * HMAC-MD5 签名
19
- * @param key - 密钥
20
- * @param data - 要签名的数据
21
- * @param encoding - 输出编码
22
- * @returns HMAC-MD5 签名
23
- */
24
- static hmacMd5(key: string | Uint8Array, data: string | Uint8Array, encoding?: EncodingType): string;
25
- /**
26
- * SHA-1 哈希
27
- * @param data - 要哈希的数据
28
- * @param encoding - 输出编码
29
- * @returns SHA-1 哈希值
30
- */
31
- static sha1(data: string | Uint8Array, encoding?: EncodingType): string;
32
- /**
33
- * HMAC-SHA1 签名
34
- * @param key - 密钥
35
- * @param data - 要签名的数据
36
- * @param encoding - 输出编码
37
- * @returns HMAC-SHA1 签名
38
- */
39
- static hmacSha1(key: string | Uint8Array, data: string | Uint8Array, encoding?: EncodingType): string;
40
- /**
41
- * SHA-256 哈希
42
- * @param data - 要哈希的数据
43
- * @param encoding - 输出编码
44
- * @returns SHA-256 哈希值
45
- */
46
- static sha256(data: string | Uint8Array, encoding?: EncodingType): string;
47
- /**
48
- * RSA-SHA256 签名
49
- * @param data - 要签名的数据
50
- * @param privateKey - 私钥
51
- * @param encoding - 输出编码('hex' | 'base64' | 'base64url')
52
- * @returns RSA-SHA256 签名
53
- */
54
- static rsaSha256(data: string, privateKey: string | Buffer, encoding?: "hex" | "base64" | "base64url"): string;
55
- /**
56
- * HMAC-SHA256 签名
57
- * @param key - 密钥
58
- * @param data - 要签名的数据
59
- * @param encoding - 输出编码
60
- * @returns HMAC-SHA256 签名
61
- */
62
- static hmacSha256(key: string | Uint8Array, data: string | Uint8Array, encoding?: EncodingType): string;
63
- /**
64
- * SHA-512 哈希
65
- * @param data - 要哈希的数据
66
- * @param encoding - 输出编码
67
- * @returns SHA-512 哈希值
68
- */
69
- static sha512(data: string | Uint8Array, encoding?: EncodingType): string;
70
- /**
71
- * HMAC-SHA512 签名
72
- * @param key - 密钥
73
- * @param data - 要签名的数据
74
- * @param encoding - 输出编码
75
- * @returns HMAC-SHA512 签名
76
- */
77
- static hmacSha512(key: string | Uint8Array, data: string | Uint8Array, encoding?: EncodingType): string;
78
- /**
79
- * 通用哈希方法
80
- * @param algorithm - 算法名称
81
- * @param data - 要哈希的数据
82
- * @param encoding - 输出编码
83
- * @returns 哈希值
84
- */
85
- static hash(algorithm: HashAlgorithm, data: string | Uint8Array, encoding?: EncodingType): string;
86
- /**
87
- * 通用 HMAC 方法
88
- * @param algorithm - 算法名称
89
- * @param key - 密钥
90
- * @param data - 要签名的数据
91
- * @param encoding - 输出编码
92
- * @returns HMAC 签名
93
- */
94
- static hmac(algorithm: HashAlgorithm, key: string | Uint8Array, data: string | Uint8Array, encoding?: EncodingType): string;
95
- /**
96
- * 文件哈希
97
- * @param filePath - 文件路径
98
- * @param algorithm - 算法名称
99
- * @param encoding - 输出编码
100
- * @returns 文件哈希值
101
- */
102
- static hashFile(filePath: string, algorithm?: HashAlgorithm, encoding?: EncodingType): Promise<string>;
103
- /**
104
- * 密码哈希(使用 bcrypt 算法)
105
- * @param password - 密码
106
- * @param options - 选项(可选,支持自定义 cost 参数)
107
- * @returns 哈希后的密码(固定 60 字符)
108
- * @example
109
- * // 默认配置(推荐)
110
- * const hash = await Cipher.hashPassword('123456');
111
- *
112
- * // 自定义强度(可选)
113
- * const hash = await Cipher.hashPassword('123456', { cost: 12 });
114
- */
115
- static hashPassword(password: string, options?: PasswordHashOptions): Promise<string>;
116
- /**
117
- * 验证密码
118
- * @param password - 原始密码
119
- * @param hash - 存储的哈希值(自动识别算法和提取盐值)
120
- * @returns 验证结果
121
- * @example
122
- * const isValid = await Cipher.verifyPassword('123456', storedHash);
123
- * if (isValid) {
124
- * // 密码正确
125
- * }
126
- */
127
- static verifyPassword(password: string, hash: string): Promise<boolean>;
128
- /**
129
- * Base64 编码
130
- * @param data - 要编码的数据
131
- * @returns Base64 编码的字符串
132
- */
133
- static base64Encode(data: string): string;
134
- /**
135
- * Base64 解码
136
- * @param data - Base64 编码的字符串
137
- * @returns 解码后的字符串
138
- */
139
- static base64Decode(data: string): string;
140
- /**
141
- * 生成随机十六进制字符串
142
- * @param length - 字符串长度
143
- * @returns 随机十六进制字符串
144
- */
145
- static randomString(length: number): string;
146
- /**
147
- * 快速哈希 (非密码学)
148
- * @param data - 数据
149
- * @param seed - 种子值
150
- * @returns 64位哈希值
151
- */
152
- static fastHash(data: string | Uint8Array, seed?: number): number;
153
- }