befly 3.9.38 → 3.9.40

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 (155) hide show
  1. package/README.md +37 -38
  2. package/befly.config.ts +62 -40
  3. package/checks/checkApi.ts +16 -16
  4. package/checks/checkApp.ts +19 -25
  5. package/checks/checkTable.ts +42 -42
  6. package/docs/README.md +42 -35
  7. package/docs/{api.md → api/api.md} +223 -231
  8. package/docs/cipher.md +71 -69
  9. package/docs/database.md +143 -141
  10. package/docs/{examples.md → guide/examples.md} +181 -181
  11. package/docs/guide/quickstart.md +331 -0
  12. package/docs/hooks/auth.md +38 -0
  13. package/docs/hooks/cors.md +28 -0
  14. package/docs/{hook.md → hooks/hook.md} +140 -57
  15. package/docs/hooks/parser.md +19 -0
  16. package/docs/hooks/rateLimit.md +47 -0
  17. package/docs/{redis.md → infra/redis.md} +84 -93
  18. package/docs/plugins/cipher.md +61 -0
  19. package/docs/plugins/database.md +128 -0
  20. package/docs/{plugin.md → plugins/plugin.md} +83 -81
  21. package/docs/quickstart.md +26 -26
  22. package/docs/{addon.md → reference/addon.md} +46 -46
  23. package/docs/{config.md → reference/config.md} +32 -80
  24. package/docs/{logger.md → reference/logger.md} +52 -52
  25. package/docs/{sync.md → reference/sync.md} +32 -35
  26. package/docs/{table.md → reference/table.md} +1 -1
  27. package/docs/{validator.md → reference/validator.md} +57 -57
  28. package/hooks/auth.ts +8 -4
  29. package/hooks/cors.ts +13 -13
  30. package/hooks/parser.ts +37 -17
  31. package/hooks/permission.ts +26 -14
  32. package/hooks/rateLimit.ts +276 -0
  33. package/hooks/validator.ts +8 -8
  34. package/lib/asyncContext.ts +43 -0
  35. package/lib/cacheHelper.ts +212 -77
  36. package/lib/cacheKeys.ts +38 -0
  37. package/lib/cipher.ts +30 -30
  38. package/lib/connect.ts +28 -28
  39. package/lib/dbHelper.ts +183 -102
  40. package/lib/jwt.ts +16 -16
  41. package/lib/logger.ts +610 -19
  42. package/lib/redisHelper.ts +185 -44
  43. package/lib/sqlBuilder.ts +90 -91
  44. package/lib/validator.ts +59 -39
  45. package/loader/loadApis.ts +48 -44
  46. package/loader/loadHooks.ts +40 -14
  47. package/loader/loadPlugins.ts +16 -17
  48. package/main.ts +57 -47
  49. package/package.json +47 -45
  50. package/paths.ts +15 -14
  51. package/plugins/cache.ts +5 -4
  52. package/plugins/cipher.ts +3 -3
  53. package/plugins/config.ts +2 -2
  54. package/plugins/db.ts +9 -9
  55. package/plugins/jwt.ts +3 -3
  56. package/plugins/logger.ts +8 -12
  57. package/plugins/redis.ts +8 -8
  58. package/plugins/tool.ts +6 -6
  59. package/router/api.ts +85 -56
  60. package/router/static.ts +12 -12
  61. package/sync/syncAll.ts +12 -12
  62. package/sync/syncApi.ts +55 -52
  63. package/sync/syncDb/apply.ts +20 -19
  64. package/sync/syncDb/constants.ts +25 -23
  65. package/sync/syncDb/ddl.ts +35 -36
  66. package/sync/syncDb/helpers.ts +6 -9
  67. package/sync/syncDb/schema.ts +10 -9
  68. package/sync/syncDb/sqlite.ts +7 -8
  69. package/sync/syncDb/table.ts +37 -35
  70. package/sync/syncDb/tableCreate.ts +21 -20
  71. package/sync/syncDb/types.ts +23 -20
  72. package/sync/syncDb/version.ts +10 -10
  73. package/sync/syncDb.ts +43 -36
  74. package/sync/syncDev.ts +74 -65
  75. package/sync/syncMenu.ts +190 -55
  76. package/tests/api-integration-array-number.test.ts +282 -0
  77. package/tests/befly-config-env.test.ts +78 -0
  78. package/tests/cacheHelper.test.ts +135 -104
  79. package/tests/cacheKeys.test.ts +41 -0
  80. package/tests/cipher.test.ts +90 -89
  81. package/tests/dbHelper-advanced.test.ts +140 -134
  82. package/tests/dbHelper-all-array-types.test.ts +316 -0
  83. package/tests/dbHelper-array-serialization.test.ts +258 -0
  84. package/tests/dbHelper-columns.test.ts +56 -55
  85. package/tests/dbHelper-execute.test.ts +45 -44
  86. package/tests/dbHelper-joins.test.ts +124 -119
  87. package/tests/fields-redis-cache.test.ts +29 -27
  88. package/tests/fields-validate.test.ts +38 -38
  89. package/tests/getClientIp.test.ts +54 -0
  90. package/tests/integration.test.ts +69 -67
  91. package/tests/jwt.test.ts +27 -26
  92. package/tests/logger.test.ts +267 -34
  93. package/tests/rateLimit-hook.test.ts +477 -0
  94. package/tests/redisHelper.test.ts +187 -188
  95. package/tests/redisKeys.test.ts +6 -73
  96. package/tests/scanConfig.test.ts +144 -0
  97. package/tests/sqlBuilder-advanced.test.ts +217 -215
  98. package/tests/sqlBuilder.test.ts +92 -91
  99. package/tests/sync-connection.test.ts +29 -29
  100. package/tests/syncDb-apply.test.ts +97 -96
  101. package/tests/syncDb-array-number.test.ts +160 -0
  102. package/tests/syncDb-constants.test.ts +48 -47
  103. package/tests/syncDb-ddl.test.ts +99 -98
  104. package/tests/syncDb-helpers.test.ts +29 -28
  105. package/tests/syncDb-schema.test.ts +61 -60
  106. package/tests/syncDb-types.test.ts +60 -59
  107. package/tests/syncMenu-paths.test.ts +68 -0
  108. package/tests/util.test.ts +42 -41
  109. package/tests/validator-array-number.test.ts +310 -0
  110. package/tests/validator-default.test.ts +373 -0
  111. package/tests/validator.test.ts +271 -266
  112. package/tsconfig.json +4 -5
  113. package/types/api.d.ts +7 -12
  114. package/types/befly.d.ts +60 -13
  115. package/types/cache.d.ts +8 -4
  116. package/types/common.d.ts +17 -9
  117. package/types/context.d.ts +2 -2
  118. package/types/crypto.d.ts +23 -0
  119. package/types/database.d.ts +19 -19
  120. package/types/hook.d.ts +2 -2
  121. package/types/jwt.d.ts +118 -0
  122. package/types/logger.d.ts +30 -0
  123. package/types/plugin.d.ts +4 -4
  124. package/types/redis.d.ts +7 -3
  125. package/types/roleApisCache.ts +23 -0
  126. package/types/sync.d.ts +10 -10
  127. package/types/table.d.ts +50 -9
  128. package/types/validate.d.ts +69 -0
  129. package/utils/addonHelper.ts +90 -0
  130. package/utils/arrayKeysToCamel.ts +18 -0
  131. package/utils/calcPerfTime.ts +13 -0
  132. package/utils/configTypes.ts +3 -0
  133. package/utils/cors.ts +19 -0
  134. package/utils/fieldClear.ts +75 -0
  135. package/utils/genShortId.ts +12 -0
  136. package/utils/getClientIp.ts +45 -0
  137. package/utils/keysToCamel.ts +22 -0
  138. package/utils/keysToSnake.ts +22 -0
  139. package/utils/modules.ts +98 -0
  140. package/utils/pickFields.ts +19 -0
  141. package/utils/process.ts +56 -0
  142. package/utils/regex.ts +225 -0
  143. package/utils/response.ts +115 -0
  144. package/utils/route.ts +23 -0
  145. package/utils/scanConfig.ts +142 -0
  146. package/utils/scanFiles.ts +48 -0
  147. package/.prettierignore +0 -2
  148. package/.prettierrc +0 -12
  149. package/docs/1-/345/237/272/346/234/254/344/273/213/347/273/215.md +0 -35
  150. package/docs/2-/345/210/235/346/255/245/344/275/223/351/252/214.md +0 -64
  151. package/docs/3-/347/254/254/344/270/200/344/270/252/346/216/245/345/217/243.md +0 -46
  152. package/docs/4-/346/223/215/344/275/234/346/225/260/346/215/256/345/272/223.md +0 -172
  153. package/hooks/requestLogger.ts +0 -84
  154. package/types/index.ts +0 -24
  155. package/util.ts +0 -283
@@ -1,76 +1,9 @@
1
1
  /**
2
- * RedisKeys RedisTTL 测试
2
+ * 已弃用:原文件内容与 cacheKeys.test.ts 重复。
3
+ *
4
+ * 说明:
5
+ * - 优先保留并维护 cacheKeys.test.ts
6
+ * - 这里保留空文件仅为兼容历史文件名(避免某些工具/脚本引用路径时报错)
3
7
  */
4
8
 
5
- import { describe, expect, test } from 'bun:test';
6
- import { RedisKeys, RedisTTL } from 'befly-shared/redisKeys';
7
-
8
- describe('RedisKeys - Key 生成函数', () => {
9
- test('apisAll - 返回固定的接口缓存键', () => {
10
- expect(RedisKeys.apisAll()).toBe('befly:apis:all');
11
- });
12
-
13
- test('menusAll - 返回固定的菜单缓存键', () => {
14
- expect(RedisKeys.menusAll()).toBe('befly:menus:all');
15
- });
16
-
17
- test('roleInfo - 返回带角色代码的缓存键', () => {
18
- expect(RedisKeys.roleInfo('admin')).toBe('befly:role:info:admin');
19
- expect(RedisKeys.roleInfo('user')).toBe('befly:role:info:user');
20
- });
21
-
22
- test('roleApis - 返回带角色代码的权限缓存键', () => {
23
- expect(RedisKeys.roleApis('admin')).toBe('befly:role:apis:admin');
24
- expect(RedisKeys.roleApis('guest')).toBe('befly:role:apis:guest');
25
- });
26
-
27
- test('tableColumns - 返回带表名的结构缓存键', () => {
28
- expect(RedisKeys.tableColumns('user')).toBe('befly:table:columns:user');
29
- expect(RedisKeys.tableColumns('addon_admin_role')).toBe('befly:table:columns:addon_admin_role');
30
- });
31
-
32
- test('roleInfo - 特殊字符处理', () => {
33
- expect(RedisKeys.roleInfo('super-admin')).toBe('befly:role:info:super-admin');
34
- expect(RedisKeys.roleInfo('role_1')).toBe('befly:role:info:role_1');
35
- });
36
-
37
- test('tableColumns - 空字符串', () => {
38
- expect(RedisKeys.tableColumns('')).toBe('befly:table:columns:');
39
- });
40
- });
41
-
42
- describe('RedisTTL - 过期时间常量', () => {
43
- test('tableColumns - 1小时 (3600秒)', () => {
44
- expect(RedisTTL.tableColumns).toBe(3600);
45
- });
46
-
47
- test('roleApis - 24小时 (86400秒)', () => {
48
- expect(RedisTTL.roleApis).toBe(86400);
49
- });
50
-
51
- test('roleInfo - 24小时 (86400秒)', () => {
52
- expect(RedisTTL.roleInfo).toBe(86400);
53
- });
54
-
55
- test('apisAll - 永久 (null)', () => {
56
- expect(RedisTTL.apisAll).toBeNull();
57
- });
58
-
59
- test('menusAll - 永久 (null)', () => {
60
- expect(RedisTTL.menusAll).toBeNull();
61
- });
62
-
63
- test('所有 TTL 值都是数字或 null', () => {
64
- for (const [key, value] of Object.entries(RedisTTL)) {
65
- expect(value === null || typeof value === 'number').toBe(true);
66
- }
67
- });
68
-
69
- test('数字类型的 TTL 都是正数', () => {
70
- for (const [key, value] of Object.entries(RedisTTL)) {
71
- if (typeof value === 'number') {
72
- expect(value).toBeGreaterThan(0);
73
- }
74
- }
75
- });
76
- });
9
+ export {};
@@ -0,0 +1,144 @@
1
+ import { describe, expect, test, beforeAll, afterAll, beforeEach } from "bun:test";
2
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+
5
+ import { scanConfig } from "../utils/scanConfig";
6
+
7
+ const tempRootDir = join(process.cwd(), "temp", "test-scan-config");
8
+
9
+ function writeJson(filePath: string, data: Record<string, any>) {
10
+ const json = JSON.stringify(data, null, 4);
11
+ writeFileSync(filePath, json, { encoding: "utf8" });
12
+ }
13
+
14
+ function createCaseDirs(): { caseRootDir: string; dirA: string; dirB: string } {
15
+ const caseRootDir = join(tempRootDir, `case-${Date.now()}-${Math.random().toString(16).slice(2)}`);
16
+ const dirA = join(caseRootDir, "a");
17
+ const dirB = join(caseRootDir, "b");
18
+
19
+ if (!existsSync(dirA)) {
20
+ mkdirSync(dirA, { recursive: true });
21
+ }
22
+ if (!existsSync(dirB)) {
23
+ mkdirSync(dirB, { recursive: true });
24
+ }
25
+
26
+ return {
27
+ caseRootDir: caseRootDir,
28
+ dirA: dirA,
29
+ dirB: dirB
30
+ };
31
+ }
32
+
33
+ afterAll(() => {
34
+ if (existsSync(tempRootDir)) {
35
+ rmSync(tempRootDir, { recursive: true, force: true });
36
+ }
37
+ });
38
+
39
+ describe("utils - scanConfig", () => {
40
+ beforeAll(() => {
41
+ if (!existsSync(tempRootDir)) {
42
+ mkdirSync(tempRootDir, { recursive: true });
43
+ }
44
+ });
45
+
46
+ beforeEach(() => {
47
+ // 无需清空:每个用例使用唯一目录,避免 import cache 干扰
48
+ });
49
+
50
+ test("mode=first:返回搜索到的第一个配置(按 dirs 顺序)", async () => {
51
+ const { caseRootDir, dirA, dirB } = createCaseDirs();
52
+
53
+ writeJson(join(dirA, "cfg.json"), {
54
+ foo: 1,
55
+ database: { host: "a" }
56
+ });
57
+ writeJson(join(dirB, "cfg.json"), {
58
+ foo: 2,
59
+ database: { host: "b" }
60
+ });
61
+
62
+ const config = await scanConfig({
63
+ cwd: caseRootDir,
64
+ dirs: ["a", "b"],
65
+ files: ["cfg"],
66
+ extensions: [".json"],
67
+ mode: "first"
68
+ });
69
+
70
+ expect(config).toEqual({
71
+ foo: 1,
72
+ database: { host: "a" }
73
+ });
74
+ });
75
+
76
+ test("mode=merge:按 defaults ← a ← b 合并(数组拼接,标量后者覆盖)", async () => {
77
+ const { caseRootDir, dirA, dirB } = createCaseDirs();
78
+
79
+ writeJson(join(dirA, "cfg.json"), {
80
+ foo: 1,
81
+ menus: ["a"],
82
+ database: { host: "a", port: 3306 },
83
+ nested: { a: 1 }
84
+ });
85
+ writeJson(join(dirB, "cfg.json"), {
86
+ foo: 2,
87
+ menus: ["b"],
88
+ database: { host: "b" },
89
+ nested: { b: 2 }
90
+ });
91
+
92
+ const config = await scanConfig({
93
+ cwd: caseRootDir,
94
+ dirs: ["a", "b"],
95
+ files: ["cfg"],
96
+ extensions: [".json"],
97
+ mode: "merge",
98
+ defaults: {
99
+ foo: 0,
100
+ menus: ["default"],
101
+ database: { host: "default", port: 1111 },
102
+ nested: { z: 9 }
103
+ }
104
+ });
105
+
106
+ // merge-anything 的 mergeAndConcat:数组拼接;对象深合并;标量后者覆盖
107
+ expect(config.foo).toBe(2);
108
+ expect(config.menus).toEqual(["default", "a", "b"]);
109
+ expect(config.database).toEqual({
110
+ host: "b",
111
+ port: 3306
112
+ });
113
+ expect(config.nested).toEqual({
114
+ z: 9,
115
+ a: 1,
116
+ b: 2
117
+ });
118
+ });
119
+
120
+ test("paths:只返回指定路径字段", async () => {
121
+ const { caseRootDir, dirA } = createCaseDirs();
122
+
123
+ writeJson(join(dirA, "cfg.json"), {
124
+ foo: 1,
125
+ menus: ["a"],
126
+ database: { host: "a", port: 3306 },
127
+ secret: "should-not-return"
128
+ });
129
+
130
+ const config = await scanConfig({
131
+ cwd: caseRootDir,
132
+ dirs: ["a"],
133
+ files: ["cfg"],
134
+ extensions: [".json"],
135
+ mode: "first",
136
+ paths: ["menus", "database.host", "not.exists"]
137
+ });
138
+
139
+ expect(config).toEqual({
140
+ menus: ["a"],
141
+ database: { host: "a" }
142
+ });
143
+ });
144
+ });