befly 3.10.0 → 3.10.2

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 (79) hide show
  1. package/.gitignore +0 -0
  2. package/README.md +10 -13
  3. package/configs/presetFields.ts +10 -0
  4. package/configs/presetRegexp.ts +225 -0
  5. package/docs/README.md +17 -11
  6. package/docs/api/api.md +15 -1
  7. package/docs/guide/quickstart.md +19 -5
  8. package/docs/infra/redis.md +23 -11
  9. package/docs/quickstart.md +5 -335
  10. package/docs/reference/addon.md +0 -15
  11. package/docs/reference/config.md +1 -1
  12. package/docs/reference/logger.md +3 -3
  13. package/docs/reference/sync.md +99 -73
  14. package/docs/reference/table.md +1 -1
  15. package/package.json +15 -16
  16. package/docs/cipher.md +0 -582
  17. package/docs/database.md +0 -1176
  18. package/tests/_mocks/mockSqliteDb.ts +0 -204
  19. package/tests/addonHelper-cache.test.ts +0 -32
  20. package/tests/api-integration-array-number.test.ts +0 -282
  21. package/tests/apiHandler-routePath-only.test.ts +0 -32
  22. package/tests/befly-config-env.test.ts +0 -78
  23. package/tests/cacheHelper.test.ts +0 -323
  24. package/tests/cacheKeys.test.ts +0 -41
  25. package/tests/checkApi-routePath-strict.test.ts +0 -166
  26. package/tests/checkMenu.test.ts +0 -346
  27. package/tests/checkTable-smoke.test.ts +0 -157
  28. package/tests/cipher.test.ts +0 -249
  29. package/tests/dbDialect-cache.test.ts +0 -23
  30. package/tests/dbDialect.test.ts +0 -46
  31. package/tests/dbHelper-advanced.test.ts +0 -723
  32. package/tests/dbHelper-all-array-types.test.ts +0 -316
  33. package/tests/dbHelper-array-serialization.test.ts +0 -258
  34. package/tests/dbHelper-batch-write.test.ts +0 -90
  35. package/tests/dbHelper-columns.test.ts +0 -234
  36. package/tests/dbHelper-execute.test.ts +0 -187
  37. package/tests/dbHelper-joins.test.ts +0 -221
  38. package/tests/fields-redis-cache.test.ts +0 -127
  39. package/tests/fields-validate.test.ts +0 -99
  40. package/tests/fixtures/scanFilesAddon/node_modules/@befly-addon/demo/apis/sub/b.ts +0 -3
  41. package/tests/fixtures/scanFilesApis/a.ts +0 -3
  42. package/tests/fixtures/scanFilesApis/sub/b.ts +0 -3
  43. package/tests/getClientIp.test.ts +0 -54
  44. package/tests/integration.test.ts +0 -189
  45. package/tests/jwt.test.ts +0 -65
  46. package/tests/loadPlugins-order-smoke.test.ts +0 -75
  47. package/tests/logger.test.ts +0 -325
  48. package/tests/redisHelper.test.ts +0 -495
  49. package/tests/redisKeys.test.ts +0 -9
  50. package/tests/scanConfig.test.ts +0 -144
  51. package/tests/scanFiles-routePath.test.ts +0 -46
  52. package/tests/smoke-sql.test.ts +0 -24
  53. package/tests/sqlBuilder-advanced.test.ts +0 -608
  54. package/tests/sqlBuilder.test.ts +0 -209
  55. package/tests/sync-connection.test.ts +0 -183
  56. package/tests/sync-init-guard.test.ts +0 -105
  57. package/tests/syncApi-insBatch-fields-consistent.test.ts +0 -61
  58. package/tests/syncApi-obsolete-records.test.ts +0 -69
  59. package/tests/syncApi-type-compat.test.ts +0 -72
  60. package/tests/syncDev-permissions.test.ts +0 -81
  61. package/tests/syncMenu-disableMenus-hard-delete.test.ts +0 -88
  62. package/tests/syncMenu-duplicate-path.test.ts +0 -122
  63. package/tests/syncMenu-obsolete-records.test.ts +0 -161
  64. package/tests/syncMenu-parentPath-from-tree.test.ts +0 -75
  65. package/tests/syncMenu-paths.test.ts +0 -59
  66. package/tests/syncTable-apply.test.ts +0 -279
  67. package/tests/syncTable-array-number.test.ts +0 -160
  68. package/tests/syncTable-constants.test.ts +0 -101
  69. package/tests/syncTable-db-integration.test.ts +0 -237
  70. package/tests/syncTable-ddl.test.ts +0 -245
  71. package/tests/syncTable-helpers.test.ts +0 -99
  72. package/tests/syncTable-schema.test.ts +0 -99
  73. package/tests/syncTable-testkit.test.ts +0 -25
  74. package/tests/syncTable-types.test.ts +0 -122
  75. package/tests/tableRef-and-deserialize.test.ts +0 -67
  76. package/tests/util.test.ts +0 -100
  77. package/tests/validator-array-number.test.ts +0 -310
  78. package/tests/validator-default.test.ts +0 -373
  79. package/tests/validator.test.ts +0 -679
@@ -1,325 +0,0 @@
1
- import { describe, test, expect, beforeAll, afterAll } from "bun:test";
2
- import { existsSync, mkdirSync, rmSync } from "node:fs";
3
- import { join } from "node:path";
4
-
5
- import { withCtx } from "../lib/asyncContext";
6
- import { Logger } from "../lib/logger";
7
-
8
- const testLogDir = join(process.cwd(), "temp", "test-logs");
9
-
10
- beforeAll(() => {
11
- if (!existsSync(testLogDir)) {
12
- mkdirSync(testLogDir, { recursive: true });
13
- }
14
- Logger.configure({
15
- dir: testLogDir,
16
- console: 0,
17
- debug: 1,
18
- excludeFields: ["*Secret", "*nick*"]
19
- });
20
- });
21
-
22
- afterAll(async () => {
23
- // 延迟清理,等待 pino-roll 完成写入
24
- await new Promise((resolve) => setTimeout(resolve, 500));
25
- if (existsSync(testLogDir)) {
26
- rmSync(testLogDir, { recursive: true, force: true });
27
- }
28
- });
29
-
30
- describe("Logger - 纯字符串消息", () => {
31
- test("info(msg)", () => {
32
- Logger.info("Test info message");
33
- expect(true).toBe(true);
34
- });
35
-
36
- test("warn(msg)", () => {
37
- Logger.warn("Test warning");
38
- expect(true).toBe(true);
39
- });
40
-
41
- test("error(msg)", () => {
42
- Logger.error("Test error");
43
- expect(true).toBe(true);
44
- });
45
-
46
- test("debug(msg)", () => {
47
- Logger.debug("Test debug");
48
- expect(true).toBe(true);
49
- });
50
- });
51
-
52
- describe("Logger - 对象 + 消息 (pino 原生格式)", () => {
53
- test("info(obj, msg)", () => {
54
- Logger.info({ userId: 1, action: "login" }, "User action");
55
- expect(true).toBe(true);
56
- });
57
-
58
- test("warn(obj, msg)", () => {
59
- Logger.warn({ ip: "127.0.0.1", count: 100 }, "Rate limit warning");
60
- expect(true).toBe(true);
61
- });
62
-
63
- test("error(obj, msg)", () => {
64
- const err = new Error("Something went wrong");
65
- Logger.error({ err: err }, "Request failed");
66
- expect(true).toBe(true);
67
- });
68
-
69
- test("debug(obj, msg)", () => {
70
- Logger.debug({ key: "value", nested: { a: 1 } }, "Debug data");
71
- expect(true).toBe(true);
72
- });
73
- });
74
-
75
- describe("Logger - 仅对象", () => {
76
- test("info(obj)", () => {
77
- Logger.info({ event: "startup", port: 3000 });
78
- expect(true).toBe(true);
79
- });
80
-
81
- test("warn(obj)", () => {
82
- Logger.warn({ type: "deprecation", feature: "oldApi" });
83
- expect(true).toBe(true);
84
- });
85
-
86
- test("error(obj)", () => {
87
- Logger.error({ code: 500, message: "Internal error" });
88
- expect(true).toBe(true);
89
- });
90
-
91
- test("debug(obj)", () => {
92
- Logger.debug({ query: "SELECT * FROM users", duration: 15 });
93
- expect(true).toBe(true);
94
- });
95
- });
96
-
97
- describe("Logger - AsyncLocalStorage 注入", () => {
98
- test("无 store 时不注入", () => {
99
- const calls: any[] = [];
100
-
101
- const mock: any = {
102
- info(...args: any[]) {
103
- calls.push({ level: "info", args: args });
104
- },
105
- warn(...args: any[]) {
106
- calls.push({ level: "warn", args: args });
107
- },
108
- error(...args: any[]) {
109
- calls.push({ level: "error", args: args });
110
- },
111
- debug(...args: any[]) {
112
- calls.push({ level: "debug", args: args });
113
- }
114
- };
115
-
116
- Logger.setMock(mock);
117
- Logger.info({ foo: 1 }, "hello");
118
- Logger.setMock(null);
119
-
120
- expect(calls.length).toBe(1);
121
- expect(calls[0].level).toBe("info");
122
- expect(calls[0].args[0]).toEqual({ foo: 1 });
123
- });
124
-
125
- test("纯字符串消息会注入 meta", () => {
126
- const calls: any[] = [];
127
-
128
- const mock: any = {
129
- info(...args: any[]) {
130
- calls.push({ level: "info", args: args });
131
- },
132
- warn(...args: any[]) {
133
- calls.push({ level: "warn", args: args });
134
- },
135
- error(...args: any[]) {
136
- calls.push({ level: "error", args: args });
137
- },
138
- debug(...args: any[]) {
139
- calls.push({ level: "debug", args: args });
140
- }
141
- };
142
-
143
- Logger.setMock(mock);
144
- withCtx(
145
- {
146
- requestId: "rid_1",
147
- method: "POST",
148
- route: "/api/test",
149
- ip: "127.0.0.1",
150
- now: 123,
151
- userId: 9,
152
- roleCode: "admin"
153
- },
154
- () => {
155
- Logger.info("hello");
156
- }
157
- );
158
- Logger.setMock(null);
159
-
160
- expect(calls.length).toBe(1);
161
- expect(calls[0].args[0].requestId).toBe("rid_1");
162
- expect(calls[0].args[0].method).toBe("POST");
163
- expect(calls[0].args[0].route).toBe("/api/test");
164
- expect(calls[0].args[0].userId).toBe(9);
165
- expect(typeof calls[0].args[0].durationSinceNowMs).toBe("number");
166
- expect(calls[0].args[0].durationSinceNowMs).toBeGreaterThanOrEqual(0);
167
- expect(calls[0].args[1]).toBe("hello");
168
- });
169
-
170
- test("对象 + msg:meta 只补齐不覆盖", () => {
171
- const calls: any[] = [];
172
-
173
- const mock: any = {
174
- info(...args: any[]) {
175
- calls.push({ level: "info", args: args });
176
- },
177
- warn(...args: any[]) {
178
- calls.push({ level: "warn", args: args });
179
- },
180
- error(...args: any[]) {
181
- calls.push({ level: "error", args: args });
182
- },
183
- debug(...args: any[]) {
184
- calls.push({ level: "debug", args: args });
185
- }
186
- };
187
-
188
- Logger.setMock(mock);
189
- withCtx(
190
- {
191
- requestId: "rid_2",
192
- method: "POST",
193
- route: "/api/test",
194
- ip: "127.0.0.1",
195
- now: 456
196
- },
197
- () => {
198
- Logger.info({ requestId: "explicit", foo: 1 }, "m");
199
- }
200
- );
201
- Logger.setMock(null);
202
-
203
- expect(calls.length).toBe(1);
204
- expect(calls[0].args[0].requestId).toBe("explicit");
205
- expect(calls[0].args[0].route).toBe("/api/test");
206
- expect(calls[0].args[0].foo).toBe(1);
207
- expect(calls[0].args[1]).toBe("m");
208
- });
209
-
210
- test("兼容 Logger.error(msg, err)", () => {
211
- const calls: any[] = [];
212
-
213
- const mock: any = {
214
- info(...args: any[]) {
215
- calls.push({ level: "info", args: args });
216
- },
217
- warn(...args: any[]) {
218
- calls.push({ level: "warn", args: args });
219
- },
220
- error(...args: any[]) {
221
- calls.push({ level: "error", args: args });
222
- },
223
- debug(...args: any[]) {
224
- calls.push({ level: "debug", args: args });
225
- }
226
- };
227
-
228
- Logger.setMock(mock);
229
- withCtx(
230
- {
231
- requestId: "rid_3",
232
- method: "POST",
233
- route: "/api/test",
234
- ip: "127.0.0.1",
235
- now: 789
236
- },
237
- () => {
238
- const err = new Error("boom");
239
- Logger.error("Redis getObject 错误", err);
240
- }
241
- );
242
- Logger.setMock(null);
243
-
244
- expect(calls.length).toBe(1);
245
- expect(calls[0].args[0].requestId).toBe("rid_3");
246
- expect(calls[0].args[0].err.message).toBe("boom");
247
- expect(calls[0].args[1]).toBe("Redis getObject 错误");
248
- });
249
-
250
- test("对象裁剪:敏感 key 掩码 + 字符串截断 + 数组截断 + 统计字段", () => {
251
- const calls: any[] = [];
252
-
253
- const mock: any = {
254
- info(...args: any[]) {
255
- calls.push({ level: "info", args: args });
256
- },
257
- warn(...args: any[]) {
258
- calls.push({ level: "warn", args: args });
259
- },
260
- error(...args: any[]) {
261
- calls.push({ level: "error", args: args });
262
- },
263
- debug(...args: any[]) {
264
- calls.push({ level: "debug", args: args });
265
- }
266
- };
267
-
268
- const longStr = "x".repeat(150);
269
- const longArr: any[] = [];
270
- for (let i = 0; i < 130; i++) {
271
- longArr.push({ val: longStr, mySecret: "shouldMask" });
272
- }
273
-
274
- Logger.setMock(mock);
275
- withCtx(
276
- {
277
- requestId: "rid_trim",
278
- method: "POST",
279
- route: "/api/test",
280
- ip: "127.0.0.1",
281
- now: 1
282
- },
283
- () => {
284
- Logger.info(
285
- {
286
- password: "p".repeat(200),
287
- mySecret: "s".repeat(200),
288
- nickname: "n".repeat(200),
289
- normal: longStr,
290
- nested: {
291
- token: "t".repeat(200),
292
- a: longStr,
293
- deep: { b: longStr }
294
- },
295
- items: longArr,
296
- okNumber: 123,
297
- okBool: true
298
- },
299
- "trim"
300
- );
301
- }
302
- );
303
- Logger.setMock(null);
304
-
305
- expect(calls.length).toBe(1);
306
- const obj = calls[0].args[0];
307
- expect(obj.password).toBe("[MASKED]");
308
- expect(obj.mySecret).toBe("[MASKED]");
309
- expect(obj.nickname).toBe("[MASKED]");
310
- expect(obj.normal.length).toBe(100);
311
- expect(obj.nested.token).toBe("[MASKED]");
312
- expect(obj.nested.a.length).toBe(100);
313
- expect(Array.isArray(obj.items)).toBe(true);
314
- expect(obj.items.length).toBe(100);
315
- expect(obj.items[0].val.length).toBe(100);
316
- expect(obj.items[0].mySecret).toBe("[MASKED]");
317
- expect(obj.okNumber).toBe(123);
318
- expect(obj.okBool).toBe(true);
319
- expect(obj.logTrimStats).toBeTruthy();
320
- expect(obj.logTrimStats.maskedKeys).toBeGreaterThan(0);
321
- expect(obj.logTrimStats.truncatedStrings).toBeGreaterThan(0);
322
- expect(obj.logTrimStats.arraysTruncated).toBeGreaterThanOrEqual(1);
323
- expect(obj.logTrimStats.arrayItemsOmitted).toBeGreaterThanOrEqual(30);
324
- });
325
- });