create-dp-koa 1.0.1 → 1.0.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 (65) hide show
  1. package/package.json +1 -1
  2. package/template/.cursor/commands/cheatsheet-backend-controller.md +2 -2
  3. package/template/.cursor/commands/implement-backend-api-controller.md +6 -4
  4. package/template/.cursor/rules/11-backend-controller-recipes.skill.md +89 -10
  5. package/template/.trae/skills/11-backend-controller-recipes.skill.md +91 -10
  6. package/template/src/controllers/example/ExampleController.ts +14 -0
  7. package/template/src/entity/index.ts +1 -15
  8. package/template/src/framework/decorator/processor/AnnotationProcessor.ts +5 -1
  9. package/template/src/routers/index.ts +0 -35
  10. package/template/src/utils/testDataInitializer.ts +2 -269
  11. package/template/test/controllers/example/ExampleController.test.ts +29 -31
  12. package/template/test/framework/annotation/AnnotationDecorators.test.ts +15 -15
  13. package/template/test/framework/annotation/AnnotationExecutor.test.ts +27 -32
  14. package/template/test/framework/annotation/AnnotationProcessor.test.ts +25 -24
  15. package/template/test/framework/annotation/CustomProcessors.test.ts +15 -25
  16. package/template/test/framework/annotation/NewRouter.test.ts +9 -7
  17. package/template/test/framework/annotation/ProcessorManager.test.ts +14 -27
  18. package/template/test/framework/databaseConfig.test.ts +2 -2
  19. package/template/test/integration/integration.test.ts +15 -72
  20. package/template/src/controllers/cacheManagement.controller.ts +0 -131
  21. package/template/src/controllers/captcha.controller.ts +0 -57
  22. package/template/src/controllers/example/NewAnnotationExampleController.ts +0 -159
  23. package/template/src/controllers/example/SwaggerExampleController.ts +0 -205
  24. package/template/src/controllers/example/TransactionExample.controller.ts +0 -336
  25. package/template/src/controllers/health.controller.ts +0 -235
  26. package/template/src/controllers/home/register.controller.ts +0 -58
  27. package/template/src/controllers/home/ytGoods.controller.ts +0 -92
  28. package/template/src/controllers/home/ytShop.controller.ts +0 -135
  29. package/template/src/controllers/home/ytUser.controller.ts +0 -89
  30. package/template/src/controllers/logManagement.controller.ts +0 -396
  31. package/template/src/controllers/public/emailSend.controller.ts +0 -65
  32. package/template/src/controllers/public/ytUserAuth.controller.ts +0 -174
  33. package/template/src/controllers/testData.controller.ts +0 -253
  34. package/template/src/dto/controller/example/NewAnnotationExampleController.dto.ts +0 -73
  35. package/template/src/dto/controller/home/emailSend.controller.dto.ts +0 -40
  36. package/template/src/dto/controller/home/register.controller.dto.ts +0 -45
  37. package/template/src/dto/controller/home/ytGoods.controller.dto.ts +0 -55
  38. package/template/src/dto/controller/home/ytShop.controller.dto.ts +0 -69
  39. package/template/src/dto/controller/home/ytUser.controller.dto.ts +0 -44
  40. package/template/src/dto/controller/public/ytUserAuth.controller.dto.ts +0 -63
  41. package/template/src/dto/goods.dto.ts +0 -212
  42. package/template/src/dto/service/ytService.dto.ts +0 -13
  43. package/template/src/dto/user.dto.ts +0 -177
  44. package/template/src/entity/columnTypes.ts +0 -13
  45. package/template/src/entity/goodsImagesUnlockKey.entity.ts +0 -33
  46. package/template/src/entity/goodsUnlocker.entity.ts +0 -34
  47. package/template/src/entity/shop.entity.ts +0 -52
  48. package/template/src/entity/shopUser.entity.ts +0 -41
  49. package/template/src/entity/ytGoods.entity.ts +0 -94
  50. package/template/src/entity/ytUser.entity.ts +0 -96
  51. package/template/src/examples/SwaggerProcessorExample.ts +0 -169
  52. package/template/src/examples/TransactionManagerDemo.ts +0 -377
  53. package/template/src/framework/utils/dynamicSwagger.ts +0 -410
  54. package/template/src/repository/UserRepository.ts +0 -122
  55. package/template/src/service/paramValidateTest.service.ts +0 -139
  56. package/template/src/service/ytGoods.service.ts +0 -42
  57. package/template/src/service/ytShop.service.ts +0 -90
  58. package/template/src/service/ytUser.service.ts +0 -451
  59. package/template/src/test/swaggerParameterTest.ts +0 -90
  60. package/template/test/controllers/controllers.test.ts +0 -173
  61. package/template/test/controllers/example/NewAnnotationExampleController.test.ts +0 -200
  62. package/template/test/framework/TransactionManagerDemo.test.ts +0 -363
  63. package/template/test/service/business.test.ts +0 -87
  64. package/template/test/service/paramValidateTest.service.test.ts +0 -184
  65. package/template/test/service/ytUser.service.test.ts +0 -566
@@ -1,4 +1,5 @@
1
- import { AnnotationProcessor, AnnotationProcessorRegistry } from '../../../src/framework/decorator/processor/AnnotationProcessor';
1
+ import { AnnotationProcessor } from '../../../src/framework/decorator/processor/AnnotationProcessor';
2
+ import { annotationRegistry } from '../../../src/framework/decorator/processor/AnnotationRegistry';
2
3
  import { Context } from 'koa';
3
4
 
4
5
  // 模拟 Koa Context
@@ -72,14 +73,14 @@ describe('注解处理器系统测试', () => {
72
73
  beforeEach(() => {
73
74
  testProcessor = new TestProcessor();
74
75
  mockContext = createMockContext();
75
- AnnotationProcessorRegistry.clear();
76
+ annotationRegistry.clear();
76
77
  });
77
78
 
78
- describe('AnnotationProcessorRegistry', () => {
79
+ describe('annotationRegistry', () => {
79
80
  test('应该能够注册处理器', () => {
80
- AnnotationProcessorRegistry.register(testProcessor);
81
+ annotationRegistry.registerProcessor(testProcessor);
81
82
 
82
- const retrievedProcessor = AnnotationProcessorRegistry.getProcessor('TestProcessor');
83
+ const retrievedProcessor = annotationRegistry.getProcessor('TestProcessor');
83
84
  expect(retrievedProcessor).toBe(testProcessor);
84
85
  });
85
86
 
@@ -87,34 +88,34 @@ describe('注解处理器系统测试', () => {
87
88
  const processor1 = new ConfigurableTestProcessor('Processor1', 50);
88
89
  const processor2 = new ConfigurableTestProcessor('Processor2', 100);
89
90
 
90
- AnnotationProcessorRegistry.register(processor2);
91
- AnnotationProcessorRegistry.register(processor1);
91
+ annotationRegistry.registerProcessor(processor2);
92
+ annotationRegistry.registerProcessor(processor1);
92
93
 
93
- const allProcessors = AnnotationProcessorRegistry.getAllProcessors();
94
+ const allProcessors = annotationRegistry.getAllProcessors();
94
95
  expect(allProcessors).toHaveLength(2);
95
96
  expect(allProcessors[0]).toBe(processor1); // 优先级高的在前面
96
97
  expect(allProcessors[1]).toBe(processor2);
97
98
  });
98
99
 
99
100
  test('应该能够移除处理器', () => {
100
- AnnotationProcessorRegistry.register(testProcessor);
101
- expect(AnnotationProcessorRegistry.getProcessor('TestProcessor')).toBe(testProcessor);
101
+ annotationRegistry.registerProcessor(testProcessor);
102
+ expect(annotationRegistry.getProcessor('TestProcessor')).toBe(testProcessor);
102
103
 
103
- const removed = AnnotationProcessorRegistry.unregister('TestProcessor');
104
+ const removed = annotationRegistry.unregisterProcessor('TestProcessor');
104
105
  expect(removed).toBe(true);
105
- expect(AnnotationProcessorRegistry.getProcessor('TestProcessor')).toBeUndefined();
106
+ expect(annotationRegistry.getProcessor('TestProcessor')).toBeUndefined();
106
107
  });
107
108
 
108
109
  test('应该能够清空所有处理器', () => {
109
- AnnotationProcessorRegistry.register(testProcessor);
110
- expect(AnnotationProcessorRegistry.getAllProcessors()).toHaveLength(1);
110
+ annotationRegistry.registerProcessor(testProcessor);
111
+ expect(annotationRegistry.getAllProcessors()).toHaveLength(1);
111
112
 
112
- AnnotationProcessorRegistry.clear();
113
- expect(AnnotationProcessorRegistry.getAllProcessors()).toHaveLength(0);
113
+ annotationRegistry.clear();
114
+ expect(annotationRegistry.getAllProcessors()).toHaveLength(0);
114
115
  });
115
116
 
116
117
  test('移除不存在的处理器应该返回false', () => {
117
- const removed = AnnotationProcessorRegistry.unregister('NonExistentProcessor');
118
+ const removed = annotationRegistry.unregisterProcessor('NonExistentProcessor');
118
119
  expect(removed).toBe(false);
119
120
  });
120
121
  });
@@ -125,11 +126,11 @@ describe('注解处理器系统测试', () => {
125
126
  const processor2 = new ConfigurableTestProcessor('Processor2', 50);
126
127
  const processor3 = new ConfigurableTestProcessor('Processor3', 100);
127
128
 
128
- AnnotationProcessorRegistry.register(processor1);
129
- AnnotationProcessorRegistry.register(processor2);
130
- AnnotationProcessorRegistry.register(processor3);
129
+ annotationRegistry.registerProcessor(processor1);
130
+ annotationRegistry.registerProcessor(processor2);
131
+ annotationRegistry.registerProcessor(processor3);
131
132
 
132
- const allProcessors = AnnotationProcessorRegistry.getAllProcessors();
133
+ const allProcessors = annotationRegistry.getAllProcessors();
133
134
  expect(allProcessors[0]).toBe(processor2); // 优先级 50
134
135
  expect(allProcessors[1]).toBe(processor3); // 优先级 100
135
136
  expect(allProcessors[2]).toBe(processor1); // 优先级 200
@@ -138,7 +139,7 @@ describe('注解处理器系统测试', () => {
138
139
 
139
140
  describe('处理器执行', () => {
140
141
  test('应该能够执行处理器', async () => {
141
- AnnotationProcessorRegistry.register(testProcessor);
142
+ annotationRegistry.registerProcessor(testProcessor);
142
143
 
143
144
  const mockController = {
144
145
  $_Annotations: new Map([
@@ -148,7 +149,7 @@ describe('注解处理器系统测试', () => {
148
149
  ])
149
150
  };
150
151
 
151
- const result = await AnnotationProcessorRegistry.getAllProcessors()[0].process(
152
+ const result = await annotationRegistry.getAllProcessors()[0].process(
152
153
  mockContext,
153
154
  mockController,
154
155
  'testMethod',
@@ -163,7 +164,7 @@ describe('注解处理器系统测试', () => {
163
164
 
164
165
  test('处理器返回false应该中断执行', async () => {
165
166
  testProcessor.shouldReturn = false;
166
- AnnotationProcessorRegistry.register(testProcessor);
167
+ annotationRegistry.registerProcessor(testProcessor);
167
168
 
168
169
  const result = await testProcessor.process(
169
170
  mockContext,
@@ -1,6 +1,12 @@
1
1
  import { LoggingProcessor, PermissionProcessor, RateLimitProcessor } from '../../../src/framework/decorator/processor/processors/CustomProcessors';
2
2
  import { Context } from 'koa';
3
3
 
4
+ jest.mock('@src/framework/utils/logger', () => ({
5
+ logger: {
6
+ debug: jest.fn(),
7
+ }
8
+ }));
9
+
4
10
  // 模拟 Koa Context
5
11
  const createMockContext = (): Context => ({
6
12
  status: 200,
@@ -23,12 +29,6 @@ describe('自定义处理器测试', () => {
23
29
  beforeEach(() => {
24
30
  mockContext = createMockContext();
25
31
  jest.clearAllMocks();
26
- // 清空控制台输出
27
- jest.spyOn(console, 'log').mockImplementation(() => {});
28
- });
29
-
30
- afterEach(() => {
31
- jest.restoreAllMocks();
32
32
  });
33
33
 
34
34
  describe('LoggingProcessor', () => {
@@ -57,36 +57,26 @@ describe('自定义处理器测试', () => {
57
57
  );
58
58
 
59
59
  expect(result).toBe(true);
60
- expect(console.log).toHaveBeenCalledWith(
61
- '[Logging] 开始处理请求: TestController.testMethod'
62
- );
63
- expect(console.log).toHaveBeenCalledWith(
64
- '[Logging] 请求参数:',
65
- [{ id: 1 }]
66
- );
60
+ const { logger } = require('@src/framework/utils/logger');
61
+ expect(logger.debug).toHaveBeenCalledWith('[Logging] 开始处理请求: TestController.testMethod');
62
+ expect(logger.debug).toHaveBeenCalledWith('[Logging] 请求参数:', [{ id: 1 }]);
67
63
  expect(mockContext.state.loggingStartTime).toBeDefined();
68
64
  });
69
65
 
70
- test('logResponse静态方法应该记录响应日志', () => {
66
+ test('logResponse实例方法应该记录响应日志', async () => {
71
67
  mockContext.state.loggingStartTime = Date.now() - 100; // 100ms前
72
68
 
73
- LoggingProcessor.logResponse(
69
+ await processor.logResponse(
74
70
  mockContext,
75
71
  { constructor: { name: 'TestController' } },
76
72
  'testMethod',
77
73
  { data: 'test' }
78
74
  );
79
75
 
80
- expect(console.log).toHaveBeenCalledWith(
81
- '[Logging] 完成处理请求: TestController.testMethod'
82
- );
83
- expect(console.log).toHaveBeenCalledWith(
84
- '[Logging] 响应数据:',
85
- { data: 'test' }
86
- );
87
- expect(console.log).toHaveBeenCalledWith(
88
- expect.stringMatching(/\[Logging\] 处理耗时: \d+ms/)
89
- );
76
+ const { logger } = require('@src/framework/utils/logger');
77
+ expect(logger.debug).toHaveBeenCalledWith('[Logging] 完成处理请求: TestController.testMethod');
78
+ expect(logger.debug).toHaveBeenCalledWith('[Logging] 响应数据:', { data: 'test' });
79
+ expect(logger.debug).toHaveBeenCalledWith(expect.stringMatching(/\[Logging\] 处理耗时: \d+ms/));
90
80
  });
91
81
  });
92
82
 
@@ -7,6 +7,7 @@ import { Context } from 'koa';
7
7
  const createMockContext = (): Context => ({
8
8
  status: 200,
9
9
  body: null,
10
+ query: { id: '123' },
10
11
  request: {
11
12
  body: { name: 'test' },
12
13
  headers: { 'content-type': 'application/json' },
@@ -37,6 +38,9 @@ jest.mock('../../../src/framework/utils/cache', () => ({
37
38
  // 模拟日志
38
39
  jest.mock('../../../src/framework/utils/logger', () => ({
39
40
  logger: {
41
+ info: jest.fn(),
42
+ warn: jest.fn(),
43
+ debug: jest.fn(),
40
44
  error: jest.fn()
41
45
  }
42
46
  }));
@@ -137,7 +141,7 @@ describe('新路由系统集成测试', () => {
137
141
  await callControllerWithProcessors(mockContext, mockController, 'testMethod');
138
142
 
139
143
  expect(mockContext.status).toBe(400);
140
- expect(mockContext.body).toBe('接口testMethod返回数据参数校验异常');
144
+ expect(mockContext.body).toEqual({ data: '' });
141
145
  });
142
146
 
143
147
  test('应该能够处理缓存注解', async () => {
@@ -211,9 +215,8 @@ describe('新路由系统集成测试', () => {
211
215
 
212
216
  await callControllerWithProcessors(mockContext, mockController, 'testMethod');
213
217
 
214
- expect(console.log).toHaveBeenCalledWith(
215
- '[Logging] 开始处理请求: undefined.testMethod'
216
- );
218
+ const { logger } = require('../../../src/framework/utils/logger');
219
+ expect(logger.debug).toHaveBeenCalled();
217
220
  expect(mockContext.body).toEqual({ data: 'test' });
218
221
  });
219
222
 
@@ -260,9 +263,8 @@ describe('新路由系统集成测试', () => {
260
263
 
261
264
  await callControllerWithProcessors(mockContext, mockController, 'testMethod');
262
265
 
263
- expect(console.log).toHaveBeenCalledWith(
264
- '[Logging] 开始处理请求: undefined.testMethod'
265
- );
266
+ const { logger } = require('../../../src/framework/utils/logger');
267
+ expect(logger.debug).toHaveBeenCalled();
266
268
  expect(mockController.testMethod).toHaveBeenCalled();
267
269
  expect(mockContext.status).toBe(200);
268
270
  expect(mockContext.set).toHaveBeenCalledWith('Content-Type', 'application/json');
@@ -11,8 +11,13 @@ import { LoggingProcessor, PermissionProcessor, RateLimitProcessor } from '../..
11
11
 
12
12
  // 测试用的注解处理器
13
13
  class TestProcessor implements AnnotationProcessor {
14
- readonly name = 'TestProcessor';
15
- readonly priority = 100;
14
+ readonly name: string;
15
+ readonly priority: number;
16
+
17
+ constructor(name = 'TestProcessor', priority = 100) {
18
+ this.name = name;
19
+ this.priority = priority;
20
+ }
16
21
 
17
22
  async process(): Promise<boolean> {
18
23
  return true;
@@ -59,13 +64,8 @@ describe('处理器管理器测试', () => {
59
64
  });
60
65
 
61
66
  test('应该能够获取所有处理器', () => {
62
- const processor1 = new TestProcessor();
63
- processor1.name = 'Processor1';
64
- processor1.priority = 50;
65
-
66
- const processor2 = new TestProcessor();
67
- processor2.name = 'Processor2';
68
- processor2.priority = 100;
67
+ const processor1 = new TestProcessor('Processor1', 50);
68
+ const processor2 = new TestProcessor('Processor2', 100);
69
69
 
70
70
  ProcessorManager.registerProcessor(processor1);
71
71
  ProcessorManager.registerProcessor(processor2);
@@ -195,17 +195,9 @@ describe('处理器管理器测试', () => {
195
195
 
196
196
  describe('处理器优先级', () => {
197
197
  test('应该按优先级排序所有处理器', () => {
198
- const processor1 = new TestProcessor();
199
- processor1.name = 'Processor1';
200
- processor1.priority = 200;
201
-
202
- const processor2 = new TestProcessor();
203
- processor2.name = 'Processor2';
204
- processor2.priority = 50;
205
-
206
- const processor3 = new TestProcessor();
207
- processor3.name = 'Processor3';
208
- processor3.priority = 100;
198
+ const processor1 = new TestProcessor('Processor1', 200);
199
+ const processor2 = new TestProcessor('Processor2', 50);
200
+ const processor3 = new TestProcessor('Processor3', 100);
209
201
 
210
202
  ProcessorManager.registerProcessor(processor1);
211
203
  ProcessorManager.registerProcessor(processor2);
@@ -230,13 +222,8 @@ describe('处理器管理器测试', () => {
230
222
 
231
223
  describe('处理器覆盖', () => {
232
224
  test('注册同名处理器应该覆盖原有处理器', () => {
233
- const processor1 = new TestProcessor();
234
- processor1.name = 'TestProcessor';
235
- processor1.priority = 100;
236
-
237
- const processor2 = new TestProcessor();
238
- processor2.name = 'TestProcessor';
239
- processor2.priority = 200;
225
+ const processor1 = new TestProcessor('TestProcessor', 100);
226
+ const processor2 = new TestProcessor('TestProcessor', 200);
240
227
 
241
228
  ProcessorManager.registerProcessor(processor1);
242
229
  expect(ProcessorManager.getProcessor('TestProcessor')).toBe(processor1);
@@ -65,7 +65,7 @@ describe('数据库配置管理测试', () => {
65
65
  expect((config as any).password).toBe('testpass');
66
66
  expect((config as any).database).toBe('testdb');
67
67
  expect(config.entities).toEqual(entities);
68
- expect(config.synchronize).toBe(true);
68
+ expect(config.synchronize).toBe(false);
69
69
  });
70
70
 
71
71
  test('应该生成 MySQL 数据库配置', () => {
@@ -87,7 +87,7 @@ describe('数据库配置管理测试', () => {
87
87
  expect((config as any).password).toBe('testpass');
88
88
  expect((config as any).database).toBe('testdb');
89
89
  expect(config.entities).toEqual(entities);
90
- expect(config.synchronize).toBe(true);
90
+ expect(config.synchronize).toBe(false);
91
91
  });
92
92
 
93
93
  test('应该使用默认 PostgreSQL 配置(未设置 db_type 时)', () => {
@@ -16,62 +16,17 @@ describe('集成测试', () => {
16
16
 
17
17
  const dataSource = TestDatabaseHelper.getTestDataSource();
18
18
  expect(dataSource).toBeDefined();
19
-
20
- // 检查用户数据
21
- const users = await dataSource!.query('SELECT * FROM yt_user');
22
- expect(users.length).toBeGreaterThan(0);
23
- expect(users[0].nickName).toBe('测试用户1');
24
-
25
- // 检查店铺数据
26
- const shops = await dataSource!.query('SELECT * FROM shop');
27
- expect(shops.length).toBeGreaterThan(0);
28
- expect(shops[0].name).toBe('测试店铺1');
29
-
30
- // 检查商品数据
31
- const goods = await dataSource!.query('SELECT * FROM yt_goods');
32
- expect(goods.length).toBeGreaterThan(0);
33
- expect(goods[0].name).toBe('测试商品1');
34
-
35
- // 检查解锁密钥数据
36
- const unlockKeys = await dataSource!.query('SELECT * FROM goods_images_unlock_key');
37
- expect(unlockKeys.length).toBeGreaterThan(0);
38
- expect(unlockKeys[0].key).toBe('TEST_KEY_001');
19
+ // 精简模式下仅保证初始化调用可执行
20
+ await expect(testDataInitializer.initializeTestData()).resolves.toBeUndefined();
39
21
  });
40
22
 
41
23
  test('应该能够清空测试数据', async () => {
42
- await testDataInitializer.clearTestData();
43
-
44
- const dataSource = TestDatabaseHelper.getTestDataSource();
45
-
46
- // 检查所有表都应该为空
47
- const users = await dataSource!.query('SELECT COUNT(*) as count FROM yt_user');
48
- const shops = await dataSource!.query('SELECT COUNT(*) as count FROM shop');
49
- const goods = await dataSource!.query('SELECT COUNT(*) as count FROM yt_goods');
50
- const unlockKeys = await dataSource!.query('SELECT COUNT(*) as count FROM goods_images_unlock_key');
51
-
52
- expect(users[0].count).toBe(0);
53
- expect(shops[0].count).toBe(0);
54
- expect(goods[0].count).toBe(0);
55
- expect(unlockKeys[0].count).toBe(0);
24
+ await expect(testDataInitializer.clearTestData()).resolves.toBeUndefined();
56
25
  });
57
26
 
58
27
  test('应该能够重新初始化测试数据', async () => {
59
- // 先清空
60
28
  await testDataInitializer.clearTestData();
61
-
62
- // 再初始化
63
- await testDataInitializer.initializeTestData();
64
-
65
- const dataSource = TestDatabaseHelper.getTestDataSource();
66
-
67
- // 检查数据是否重新创建
68
- const users = await dataSource!.query('SELECT COUNT(*) as count FROM yt_user');
69
- const shops = await dataSource!.query('SELECT COUNT(*) as count FROM shop');
70
- const goods = await dataSource!.query('SELECT COUNT(*) as count FROM yt_goods');
71
-
72
- expect(users[0].count).toBeGreaterThan(0);
73
- expect(shops[0].count).toBeGreaterThan(0);
74
- expect(goods[0].count).toBeGreaterThan(0);
29
+ await expect(testDataInitializer.initializeTestData()).resolves.toBeUndefined();
75
30
  });
76
31
  });
77
32
 
@@ -91,22 +46,14 @@ describe('集成测试', () => {
91
46
 
92
47
  test('应该能够执行复杂查询', async () => {
93
48
  const dataSource = TestDatabaseHelper.getTestDataSource();
94
-
95
- // 查询用户和店铺的关联信息
96
49
  const result = await dataSource!.query(`
97
- SELECT
98
- u.nickName,
99
- s.name as shopName
100
- FROM yt_user u
101
- JOIN shop_and_user su ON u.id = su.userId
102
- JOIN shop s ON su.shopId = s.id
103
- WHERE u.id = 1
50
+ SELECT name
51
+ FROM sqlite_master
52
+ WHERE type = 'table'
104
53
  `);
105
54
 
106
55
  expect(result).toBeDefined();
107
- expect(result.length).toBeGreaterThan(0);
108
- expect(result[0].nickName).toBe('测试用户1');
109
- expect(result[0].shopName).toBe('测试店铺1');
56
+ expect(Array.isArray(result)).toBe(true);
110
57
  });
111
58
  });
112
59
 
@@ -115,19 +62,15 @@ describe('集成测试', () => {
115
62
  const { createCache, CacheType } = require('../../src/framework/utils/cache');
116
63
  const cache = createCache('integration-test', CacheType.TEMP);
117
64
 
118
- // 从数据库获取数据
119
- const dataSource = TestDatabaseHelper.getTestDataSource();
120
- const users = await dataSource!.query('SELECT * FROM yt_user LIMIT 1');
121
-
122
- // 将数据存入缓存
123
- const cacheKey = `user_${users[0].id}`;
124
- cache.set(cacheKey, users[0]);
65
+ const payload = { id: 1, nickName: 'cache-user' };
66
+ const cacheKey = `user_${payload.id}`;
67
+ cache.set(cacheKey, payload);
125
68
 
126
69
  // 从缓存获取数据
127
70
  const cachedUser = cache.get(cacheKey);
128
71
  expect(cachedUser).toBeDefined();
129
- expect(cachedUser.id).toBe(users[0].id);
130
- expect(cachedUser.nickName).toBe(users[0].nickName);
72
+ expect(cachedUser.id).toBe(payload.id);
73
+ expect(cachedUser.nickName).toBe(payload.nickName);
131
74
  });
132
75
  });
133
76
 
@@ -144,9 +87,9 @@ describe('集成测试', () => {
144
87
  test('应该能够处理无效的数据操作', async () => {
145
88
  const dataSource = TestDatabaseHelper.getTestDataSource();
146
89
 
147
- // 尝试插入无效数据
90
+ // sqlite 系统表写入应失败
148
91
  await expect(
149
- dataSource!.query('INSERT INTO yt_user (invalid_column) VALUES (?)', ['test'])
92
+ dataSource!.query('INSERT INTO sqlite_master (name) VALUES (?)', ['test'])
150
93
  ).rejects.toThrow();
151
94
  });
152
95
  });
@@ -1,131 +0,0 @@
1
- import { Get, Post } from '@src/framework/decorator/controller';
2
- import { Body } from '@src/framework/decorator/controller';
3
- import { BaseController } from '@src/controllers/base.controller';
4
- import { getCache, deleteCache, getCacheStats, getCacheMemoryUsage, clearAllCaches } from '@src/framework/utils/cache';
5
- import { logger } from '@src/framework/utils/logger';
6
-
7
- export class CacheManagementController extends BaseController {
8
-
9
- /**
10
- * 获取所有缓存统计信息
11
- */
12
- @Get('/cache/stats')
13
- async getCacheStats() {
14
- const stats = getCacheStats();
15
- const memory = getCacheMemoryUsage();
16
-
17
- return this.success({
18
- stats,
19
- memory,
20
- timestamp: new Date().toISOString()
21
- });
22
- }
23
-
24
- /**
25
- * 清理指定缓存
26
- */
27
- @Post('/cache/clear')
28
- async clearCache(@Body() body: { cacheName: string }) {
29
- const { cacheName } = body;
30
-
31
- if (!cacheName) {
32
- return this.fail(400, '缓存名称不能为空');
33
- }
34
-
35
- try {
36
- const cache = getCache(cacheName);
37
- if (!cache) {
38
- return this.fail(404, `缓存 ${cacheName} 不存在`);
39
- }
40
-
41
- // 清空缓存内容
42
- cache.flushAll();
43
- logger.info(`手动清理缓存: ${cacheName}`);
44
-
45
- return this.success({
46
- message: `缓存 ${cacheName} 已清理`,
47
- cacheName,
48
- timestamp: new Date().toISOString()
49
- });
50
- } catch (error) {
51
- logger.error(`清理缓存 ${cacheName} 失败:`, error as Error);
52
- return this.fail(500, `清理缓存失败: ${error instanceof Error ? error.message : '未知错误'}`);
53
- }
54
- }
55
-
56
- /**
57
- * 删除指定缓存实例
58
- */
59
- @Post('/cache/delete')
60
- async deleteCache(@Body() body: { cacheName: string }) {
61
- const { cacheName } = body;
62
-
63
- if (!cacheName) {
64
- return this.fail(400, '缓存名称不能为空');
65
- }
66
-
67
- try {
68
- deleteCache(cacheName);
69
- logger.info(`删除缓存实例: ${cacheName}`);
70
-
71
- return this.success({
72
- message: `缓存实例 ${cacheName} 已删除`,
73
- cacheName,
74
- timestamp: new Date().toISOString()
75
- });
76
- } catch (error) {
77
- logger.error(`删除缓存实例 ${cacheName} 失败:`, error as Error);
78
- return this.fail(500, `删除缓存实例失败: ${error instanceof Error ? error.message : '未知错误'}`);
79
- }
80
- }
81
-
82
- /**
83
- * 清理所有缓存
84
- */
85
- @Post('/cache/clear-all')
86
- async clearAllCache() {
87
- try {
88
- clearAllCaches();
89
- logger.info('手动清理所有缓存');
90
-
91
- return this.success({
92
- message: '所有缓存已清理',
93
- timestamp: new Date().toISOString()
94
- });
95
- } catch (error) {
96
- logger.error('清理所有缓存失败:', error as Error);
97
- return this.fail(500, `清理所有缓存失败: ${error instanceof Error ? error.message : '未知错误'}`);
98
- }
99
- }
100
-
101
- /**
102
- * 获取特定缓存的详细信息
103
- */
104
- @Get('/cache/info')
105
- async getCacheInfo(@Body() body: { cacheName: string }) {
106
- const { cacheName } = body;
107
-
108
- if (!cacheName) {
109
- return this.fail(400, '缓存名称不能为空');
110
- }
111
-
112
- const cache = getCache(cacheName);
113
- if (!cache) {
114
- return this.fail(404, `缓存 ${cacheName} 不存在`);
115
- }
116
-
117
- const keys = cache.keys();
118
- const stats = getCacheStats();
119
- const memory = getCacheMemoryUsage();
120
-
121
- return this.success({
122
- cacheName,
123
- keys: keys.slice(0, 10), // 只显示前10个键
124
- totalKeys: keys.length,
125
- stats: stats[cacheName] || null,
126
- memory: memory[cacheName] || null,
127
- config: cache.options,
128
- timestamp: new Date().toISOString()
129
- });
130
- }
131
- }
@@ -1,57 +0,0 @@
1
-
2
- import { Get, Post } from '@src/framework/decorator/controller';
3
- import { Body } from '@src/framework/decorator/controller';
4
- import { CaptchaGenerator } from '@src/libs/captcha';
5
- import { Inject } from 'dp-ioc2';
6
- import { createCache, CacheType } from '@src/framework/utils/cache';
7
-
8
- // 创建验证码缓存实例
9
- const captchaCache = createCache('captcha-controller', CacheType.CAPTCHA, {
10
- stdTTL: 300, // 5分钟过期
11
- maxKeys: 100 // 最多100个验证码
12
- });
13
-
14
- export class CaptchaController {
15
-
16
- // @Inject(CaptchaGenerator)
17
- // captchaGenerator: CaptchaGenerator;
18
-
19
- @Get('/captcha')
20
- async getCaptcha() {
21
- const { image, token } = CaptchaGenerator.generate();
22
- return {
23
- image,
24
- token,
25
- contentType: 'image/svg+xml'
26
- };
27
- }
28
-
29
- @Post('/captcha/verify')
30
- async verifyCaptcha(
31
- @Body() body: { captcha: string, token: string }
32
- ) {
33
- const { captcha, token } = body;
34
- if (!token) {
35
- return {
36
- status: 400,
37
- body: { success: false, message: 'Missing captcha token' }
38
- };
39
- }
40
-
41
- // 检查是否已经验证过(防止重复验证)
42
- const verifyKey = `verify_${token}`;
43
- if (captchaCache.get(verifyKey)) {
44
- return { success: false, message: '验证码已使用' };
45
- }
46
-
47
- const isValid = CaptchaGenerator.verify(token, captcha);
48
-
49
- if (isValid) {
50
- // 验证成功后标记为已使用,防止重复验证
51
- captchaCache.set(verifyKey, true, 300); // 5分钟内不能重复验证
52
- }
53
-
54
- return { success: isValid };
55
- }
56
-
57
- }