create-dp-koa 1.0.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 (235) hide show
  1. package/README.md +50 -0
  2. package/index.mjs +97 -0
  3. package/package.json +33 -0
  4. package/template/.env.development +9 -0
  5. package/template/.env.production +12 -0
  6. package/template/.github/workflows/ci-cd.yml +182 -0
  7. package/template/.trae/documents/controller_development_plan.md +386 -0
  8. package/template/.trae/skills/00-backend-core.skill.md +50 -0
  9. package/template/.trae/skills/01-backend-skill-router.skill.md +55 -0
  10. package/template/.trae/skills/10-backend-api.skill.md +54 -0
  11. package/template/.trae/skills/11-backend-controller-recipes.skill.md +107 -0
  12. package/template/.trae/skills/20-backend-repository.skill.md +25 -0
  13. package/template/.trae/skills/21-backend-service.skill.md +135 -0
  14. package/template/.trae/skills/25-backend-comments-and-doc.skill.md +97 -0
  15. package/template/.trae/skills/30-backend-validation.skill.md +320 -0
  16. package/template/.trae/skills/40-backend-error-logging.skill.md +21 -0
  17. package/template/.trae/skills/50-backend-bootstrap-lifecycle.skill.md +90 -0
  18. package/template/.trae/skills/60-backend-router-registration.skill.md +71 -0
  19. package/template/.trae/skills/70-backend-middleware.skill.md +98 -0
  20. package/template/.trae/skills/80-backend-utils-and-libs.skill.md +90 -0
  21. package/template/.trae/skills/85-backend-plugins.rule.md +64 -0
  22. package/template/.trae/skills/90-backend-testing.skill.md +29 -0
  23. package/template/.trae/skills/README.md +49 -0
  24. package/template/.vscode/launch.json +38 -0
  25. package/template/.vscode/settings.json +1 -0
  26. package/template/Dockerfile +36 -0
  27. package/template/README.md +229 -0
  28. package/template/docker-compose.yml +135 -0
  29. package/template/docs/API_DOCUMENTATION.md +837 -0
  30. package/template/docs/ARCHITECTURE_REFACTOR.md +109 -0
  31. package/template/docs/CACHE_MIGRATION_GUIDE.md +142 -0
  32. package/template/docs/DEPLOYMENT_GUIDE.md +1062 -0
  33. package/template/docs/DEVELOPMENT_GUIDE.md +1097 -0
  34. package/template/docs/DOCUMENTATION_CLEANUP_REPORT.md +166 -0
  35. package/template/docs/DOCUMENTATION_COMPLETION_REPORT.md +223 -0
  36. package/template/docs/DOCUMENTATION_INDEX.md +294 -0
  37. package/template/docs/DOCUMENTATION_STRUCTURE.md +221 -0
  38. package/template/docs/ENTERPRISE_ANNOTATION_SYSTEM_GUIDE.md +2069 -0
  39. package/template/docs/ENTERPRISE_DATABASE_ARCHITECTURE.md +318 -0
  40. package/template/docs/ENTERPRISE_DEPLOYMENT_GUIDE.md +547 -0
  41. package/template/docs/ENTERPRISE_ERROR_HANDLING_GUIDE.md +357 -0
  42. package/template/docs/ENTERPRISE_LOGGING_SYSTEM_GUIDE.md +494 -0
  43. package/template/docs/ENVIRONMENT_CONFIG_EXAMPLE.md +69 -0
  44. package/template/docs/FINAL_IMPLEMENTATION_SUMMARY.md +206 -0
  45. package/template/docs/HEALTH_CHECK_ROUTE_FIX.md +134 -0
  46. package/template/docs/IMPLEMENTATION_CHECKLIST.md +204 -0
  47. package/template/docs/INSTALLATION_GUIDE.md +611 -0
  48. package/template/docs/INTERCEPTOR_TESTING_REPORT.md +226 -0
  49. package/template/docs/INTERCEPTOR_TESTING_SCRIPTS.md +143 -0
  50. package/template/docs/LOGGING_OPTIMIZATION_GUIDE.md +126 -0
  51. package/template/docs/MEMORY_DATABASE_GUIDE.md +212 -0
  52. package/template/docs/NEW_ROUTER_INTEGRATION_GUIDE.md +345 -0
  53. package/template/docs/NEW_ROUTER_INTEGRATION_SUMMARY.md +259 -0
  54. package/template/docs/NEW_ROUTER_USAGE_GUIDE.md +364 -0
  55. package/template/docs/QUICK_START.md +268 -0
  56. package/template/docs/ROUTE_SLASH_COMPATIBILITY_FIX.md +191 -0
  57. package/template/docs/SERVICE_INTERCEPTOR_GUIDE.md +243 -0
  58. package/template/docs/SERVICE_LAYER_INDEX.md +205 -0
  59. package/template/docs/SERVICE_PATTERN_GUIDE.md +270 -0
  60. package/template/docs/SERVICE_RETURN_VALUE_SPECIFICATION.md +466 -0
  61. package/template/docs/SWAGGER_DEBUG_MODE_GUIDE.md +80 -0
  62. package/template/docs/SWAGGER_INTEGRATION_GUIDE.md +416 -0
  63. package/template/docs/TRANSACTION_MANAGER_USAGE.md +360 -0
  64. package/template/docs/TROUBLESHOOTING.md +869 -0
  65. package/template/env.production.example +62 -0
  66. package/template/jest.config.js +34 -0
  67. package/template/package-lock.json +13240 -0
  68. package/template/package.json +119 -0
  69. package/template/patches/typeorm+0.3.25.patch +22 -0
  70. package/template/scripts/sync-template.mjs +84 -0
  71. package/template/scripts/test-annotation-system.sh +48 -0
  72. package/template/scripts/test-core-functionality.sh +28 -0
  73. package/template/src/annotations/decorators/ConfigManagement.ts +9 -0
  74. package/template/src/annotations/decorators/DistributedTracing.ts +9 -0
  75. package/template/src/annotations/decorators/EnterprisePerformance.ts +9 -0
  76. package/template/src/annotations/decorators/PerformanceMonitor.ts +32 -0
  77. package/template/src/annotations/decorators/SecurityAudit.ts +9 -0
  78. package/template/src/annotations/index.ts +50 -0
  79. package/template/src/annotations/processors/ConfigManagementProcessor.ts +369 -0
  80. package/template/src/annotations/processors/DistributedTracingProcessor.ts +288 -0
  81. package/template/src/annotations/processors/EnterprisePerformanceProcessor.ts +189 -0
  82. package/template/src/annotations/processors/PerformanceMonitorProcessor.ts +101 -0
  83. package/template/src/annotations/processors/SecurityAuditProcessor.ts +345 -0
  84. package/template/src/annotations/processors/SwaggerProcessor.ts +612 -0
  85. package/template/src/annotations/processors/index.ts +10 -0
  86. package/template/src/app.ts +123 -0
  87. package/template/src/controllers/base.controller.ts +41 -0
  88. package/template/src/controllers/cacheManagement.controller.ts +131 -0
  89. package/template/src/controllers/captcha.controller.ts +57 -0
  90. package/template/src/controllers/demo/AnnotationDemoController.ts +118 -0
  91. package/template/src/controllers/example/EnterpriseExampleController.ts +297 -0
  92. package/template/src/controllers/example/ExampleController.ts +110 -0
  93. package/template/src/controllers/example/NewAnnotationExampleController.ts +159 -0
  94. package/template/src/controllers/example/SwaggerExampleController.ts +205 -0
  95. package/template/src/controllers/example/TransactionExample.controller.ts +336 -0
  96. package/template/src/controllers/health.controller.ts +235 -0
  97. package/template/src/controllers/home/register.controller.ts +58 -0
  98. package/template/src/controllers/home/ytGoods.controller.ts +92 -0
  99. package/template/src/controllers/home/ytShop.controller.ts +135 -0
  100. package/template/src/controllers/home/ytUser.controller.ts +89 -0
  101. package/template/src/controllers/logManagement.controller.ts +396 -0
  102. package/template/src/controllers/public/emailSend.controller.ts +65 -0
  103. package/template/src/controllers/public/ytUserAuth.controller.ts +174 -0
  104. package/template/src/controllers/testData.controller.ts +253 -0
  105. package/template/src/dto/controller/example/NewAnnotationExampleController.dto.ts +73 -0
  106. package/template/src/dto/controller/home/emailSend.controller.dto.ts +40 -0
  107. package/template/src/dto/controller/home/register.controller.dto.ts +45 -0
  108. package/template/src/dto/controller/home/ytGoods.controller.dto.ts +55 -0
  109. package/template/src/dto/controller/home/ytShop.controller.dto.ts +69 -0
  110. package/template/src/dto/controller/home/ytUser.controller.dto.ts +44 -0
  111. package/template/src/dto/controller/public/ytUserAuth.controller.dto.ts +63 -0
  112. package/template/src/dto/goods.dto.ts +212 -0
  113. package/template/src/dto/service/ytService.dto.ts +13 -0
  114. package/template/src/dto/user.dto.ts +177 -0
  115. package/template/src/entity/base.entity.ts +13 -0
  116. package/template/src/entity/columnTypes.ts +13 -0
  117. package/template/src/entity/goodsImagesUnlockKey.entity.ts +33 -0
  118. package/template/src/entity/goodsUnlocker.entity.ts +34 -0
  119. package/template/src/entity/index.ts +15 -0
  120. package/template/src/entity/shop.entity.ts +52 -0
  121. package/template/src/entity/shopUser.entity.ts +41 -0
  122. package/template/src/entity/ytGoods.entity.ts +94 -0
  123. package/template/src/entity/ytUser.entity.ts +96 -0
  124. package/template/src/examples/InterceptorExampleRunner.ts +284 -0
  125. package/template/src/examples/ServiceInterceptorExample.ts +214 -0
  126. package/template/src/examples/SwaggerProcessorExample.ts +169 -0
  127. package/template/src/examples/TransactionManagerDemo.ts +377 -0
  128. package/template/src/examples/cacheExamples.ts +155 -0
  129. package/template/src/framework/decorator/controller.ts +311 -0
  130. package/template/src/framework/decorator/processor/AnnotationDecorators.ts +100 -0
  131. package/template/src/framework/decorator/processor/AnnotationProcessor.ts +156 -0
  132. package/template/src/framework/decorator/processor/AnnotationProcessorConfig.ts +45 -0
  133. package/template/src/framework/decorator/processor/AnnotationRegistry.ts +117 -0
  134. package/template/src/framework/decorator/processor/AnnotationSystemInitializer.ts +95 -0
  135. package/template/src/framework/decorator/processor/ProcessorManager.ts +76 -0
  136. package/template/src/framework/decorator/processor/processors/CustomProcessors.ts +126 -0
  137. package/template/src/framework/decorator/processor/processors/DefaultProcessors.ts +207 -0
  138. package/template/src/framework/decorator/refactored/DecoratorFactory.ts +99 -0
  139. package/template/src/framework/decorator/refactored/DecoratorMetadataManager.ts +125 -0
  140. package/template/src/framework/decorator/refactored/DecoratorValidator.ts +128 -0
  141. package/template/src/framework/decorator/refactored/TypeSafeDecorators.ts +139 -0
  142. package/template/src/framework/decorator/refactored/index.ts +98 -0
  143. package/template/src/framework/decorator/swagger.ts +150 -0
  144. package/template/src/framework/interceptors/AdvancedServiceCallInterceptor.ts +375 -0
  145. package/template/src/framework/interceptors/ServiceCallInterceptor.ts +348 -0
  146. package/template/src/framework/interceptors/index.ts +19 -0
  147. package/template/src/framework/plugins/registry.ts +63 -0
  148. package/template/src/framework/plugins/types.ts +15 -0
  149. package/template/src/framework/types/ServiceResult.ts +151 -0
  150. package/template/src/framework/types/index.ts +16 -0
  151. package/template/src/framework/utils/CacheManager.ts +430 -0
  152. package/template/src/framework/utils/CacheService.ts +248 -0
  153. package/template/src/framework/utils/DtoValidator.ts +164 -0
  154. package/template/src/framework/utils/MigrationHelper.ts +179 -0
  155. package/template/src/framework/utils/MigrationManager.ts +256 -0
  156. package/template/src/framework/utils/NewRouter.ts +207 -0
  157. package/template/src/framework/utils/TransactionManager.ts +172 -0
  158. package/template/src/framework/utils/bootstrap.ts +445 -0
  159. package/template/src/framework/utils/cache.ts +269 -0
  160. package/template/src/framework/utils/databaseConfig.ts +148 -0
  161. package/template/src/framework/utils/db.ts +39 -0
  162. package/template/src/framework/utils/dbMonitor.ts +106 -0
  163. package/template/src/framework/utils/dynamicSwagger.ts +410 -0
  164. package/template/src/framework/utils/function.ts +61 -0
  165. package/template/src/framework/utils/gracefulShutdown.ts +131 -0
  166. package/template/src/framework/utils/logger.ts +388 -0
  167. package/template/src/framework/utils/metrics.ts +182 -0
  168. package/template/src/framework/utils/router.ts +417 -0
  169. package/template/src/framework/utils/swagger.ts +184 -0
  170. package/template/src/framework/utils/testDb.ts +19 -0
  171. package/template/src/framework/utils/token.ts +23 -0
  172. package/template/src/framework/utils/transform.ts +17 -0
  173. package/template/src/libs/aokEmailSender.ts +42 -0
  174. package/template/src/libs/captcha.ts +37 -0
  175. package/template/src/libs/cos.ts +45 -0
  176. package/template/src/libs/mCache.ts +7 -0
  177. package/template/src/libs/serviceValidate.ts +3 -0
  178. package/template/src/libs/tecentSms.ts +51 -0
  179. package/template/src/middlewares/a.middleware.ts +6 -0
  180. package/template/src/middlewares/error.middleware.ts +14 -0
  181. package/template/src/middlewares/logging.middleware.ts +187 -0
  182. package/template/src/middlewares/static.middleware.ts +79 -0
  183. package/template/src/middlewares/swagger.middleware.ts +70 -0
  184. package/template/src/middlewares/token.middleware.ts +32 -0
  185. package/template/src/migrations/1700000000000-InitialDatabaseStructure.ts +172 -0
  186. package/template/src/migrations/index.ts +6 -0
  187. package/template/src/plugins/weboffice/core/context.ts +47 -0
  188. package/template/src/plugins/weboffice/core/errors.ts +51 -0
  189. package/template/src/plugins/weboffice/core/types.ts +63 -0
  190. package/template/src/plugins/weboffice/core/utils.ts +7 -0
  191. package/template/src/plugins/weboffice/entities/index.ts +3 -0
  192. package/template/src/plugins/weboffice/entities/webofficeFile.entity.ts +28 -0
  193. package/template/src/plugins/weboffice/entities/webofficeFileVersion.entity.ts +29 -0
  194. package/template/src/plugins/weboffice/http/routes.ts +179 -0
  195. package/template/src/plugins/weboffice/index.ts +23 -0
  196. package/template/src/plugins/weboffice/services/webofficeCallback.service.ts +274 -0
  197. package/template/src/repository/UserRepository.ts +122 -0
  198. package/template/src/repository/base/BaseRepository.ts +124 -0
  199. package/template/src/repository/interfaces/IBaseRepository.ts +67 -0
  200. package/template/src/routers/index.ts +49 -0
  201. package/template/src/service/base.service.ts +116 -0
  202. package/template/src/service/paramValidateTest.service.ts +139 -0
  203. package/template/src/service/ytGoods.service.ts +42 -0
  204. package/template/src/service/ytShop.service.ts +90 -0
  205. package/template/src/service/ytUser.service.ts +451 -0
  206. package/template/src/test/swaggerParameterTest.ts +90 -0
  207. package/template/src/utils/testDataInitializer.ts +296 -0
  208. package/template/static/output.json +15203 -0
  209. package/template/test/controllers/controllers.test.ts +173 -0
  210. package/template/test/controllers/example/ExampleController.test.ts +222 -0
  211. package/template/test/controllers/example/NewAnnotationExampleController.test.ts +200 -0
  212. package/template/test/framework/TransactionManagerDemo.test.ts +363 -0
  213. package/template/test/framework/annotation/AnnotationDecorators.test.ts +222 -0
  214. package/template/test/framework/annotation/AnnotationExecutor.test.ts +246 -0
  215. package/template/test/framework/annotation/AnnotationProcessor.test.ts +179 -0
  216. package/template/test/framework/annotation/CustomProcessors.test.ts +313 -0
  217. package/template/test/framework/annotation/DefaultProcessors.test.ts +371 -0
  218. package/template/test/framework/annotation/NewRouter.test.ts +272 -0
  219. package/template/test/framework/annotation/ProcessorManager.test.ts +248 -0
  220. package/template/test/framework/annotation/setup.ts +26 -0
  221. package/template/test/framework/cache.test.ts +101 -0
  222. package/template/test/framework/databaseConfig.test.ts +142 -0
  223. package/template/test/integration/integration.test.ts +153 -0
  224. package/template/test/plugins/weboffice/http.routes.int.test.ts +61 -0
  225. package/template/test/service/business.test.ts +87 -0
  226. package/template/test/service/paramValidateTest.service.test.ts +184 -0
  227. package/template/test/service/ytUser.service.test.ts +566 -0
  228. package/template/test/setup.ts +20 -0
  229. package/template/test/setupAfterEnv.ts +14 -0
  230. package/template/test/utils/testHelpers.ts +220 -0
  231. package/template/test_output.txt +0 -0
  232. package/template/tsconfig.build.json +17 -0
  233. package/template/tsconfig.json +31 -0
  234. package/template/webpack.config.js +71 -0
  235. package/template/yarn.lock +7354 -0
@@ -0,0 +1,142 @@
1
+ import { databaseConfigManager } from '../../src/framework/utils/databaseConfig';
2
+
3
+ describe('数据库配置管理测试', () => {
4
+ beforeEach(() => {
5
+ // 重置环境变量
6
+ delete process.env.db_enable;
7
+ delete process.env.db_memory;
8
+ });
9
+
10
+ describe('数据库启用检查', () => {
11
+ test('应该正确检测数据库是否启用', () => {
12
+ process.env.db_enable = '1';
13
+ expect(databaseConfigManager.isDatabaseEnabled()).toBe(true);
14
+
15
+ process.env.db_enable = '0';
16
+ expect(databaseConfigManager.isDatabaseEnabled()).toBe(false);
17
+
18
+ delete process.env.db_enable;
19
+ expect(databaseConfigManager.isDatabaseEnabled()).toBe(false);
20
+ });
21
+ });
22
+
23
+ describe('内存数据库模式检查', () => {
24
+ test('应该正确检测内存数据库模式', () => {
25
+ process.env.db_memory = '1';
26
+ expect(databaseConfigManager.isMemoryDatabaseMode()).toBe(true);
27
+
28
+ process.env.db_memory = '0';
29
+ expect(databaseConfigManager.isMemoryDatabaseMode()).toBe(false);
30
+
31
+ delete process.env.db_memory;
32
+ expect(databaseConfigManager.isMemoryDatabaseMode()).toBe(false);
33
+ });
34
+ });
35
+
36
+ describe('数据库配置生成', () => {
37
+ test('应该生成内存数据库配置', () => {
38
+ process.env.db_memory = '1';
39
+ const entities = [{ name: 'TestEntity' }];
40
+ const config = databaseConfigManager.getDatabaseConfig(entities);
41
+
42
+ expect(config.type).toBe('sqlite');
43
+ expect(config.database).toBe(':memory:');
44
+ expect(config.entities).toEqual(entities);
45
+ expect(config.synchronize).toBe(true);
46
+ expect(config.dropSchema).toBe(true);
47
+ });
48
+
49
+ test('应该生成 PostgreSQL 数据库配置', () => {
50
+ process.env.db_memory = '0';
51
+ process.env.db_type = 'postgres';
52
+ process.env.db_host = 'localhost';
53
+ process.env.db_port = '5432';
54
+ process.env.db_username = 'testuser';
55
+ process.env.db_password = 'testpass';
56
+ process.env.db_database = 'testdb';
57
+
58
+ const entities = [{ name: 'TestEntity' }];
59
+ const config = databaseConfigManager.getDatabaseConfig(entities);
60
+
61
+ expect(config.type).toBe('postgres');
62
+ expect((config as any).host).toBe('localhost');
63
+ expect((config as any).port).toBe(5432);
64
+ expect((config as any).username).toBe('testuser');
65
+ expect((config as any).password).toBe('testpass');
66
+ expect((config as any).database).toBe('testdb');
67
+ expect(config.entities).toEqual(entities);
68
+ expect(config.synchronize).toBe(true);
69
+ });
70
+
71
+ test('应该生成 MySQL 数据库配置', () => {
72
+ process.env.db_memory = '0';
73
+ process.env.db_type = 'mysql';
74
+ process.env.db_host = 'localhost';
75
+ process.env.db_port = '3306';
76
+ process.env.db_username = 'testuser';
77
+ process.env.db_password = 'testpass';
78
+ process.env.db_database = 'testdb';
79
+
80
+ const entities = [{ name: 'TestEntity' }];
81
+ const config = databaseConfigManager.getDatabaseConfig(entities);
82
+
83
+ expect(config.type).toBe('mysql');
84
+ expect((config as any).host).toBe('localhost');
85
+ expect((config as any).port).toBe(3306);
86
+ expect((config as any).username).toBe('testuser');
87
+ expect((config as any).password).toBe('testpass');
88
+ expect((config as any).database).toBe('testdb');
89
+ expect(config.entities).toEqual(entities);
90
+ expect(config.synchronize).toBe(true);
91
+ });
92
+
93
+ test('应该使用默认 PostgreSQL 配置(未设置 db_type 时)', () => {
94
+ process.env.db_memory = '0';
95
+ delete process.env.db_type;
96
+ delete process.env.db_host;
97
+ delete process.env.db_port;
98
+ delete process.env.db_username;
99
+ delete process.env.db_password;
100
+ delete process.env.db_database;
101
+
102
+ const entities = [{ name: 'TestEntity' }];
103
+ const config = databaseConfigManager.getDatabaseConfig(entities);
104
+
105
+ expect(config.type).toBe('postgres');
106
+ expect((config as any).host).toBe('127.0.0.1');
107
+ expect((config as any).port).toBe(5432);
108
+ expect((config as any).username).toBe('admin');
109
+ expect((config as any).database).toBe('mydb');
110
+ });
111
+ });
112
+
113
+ describe('数据库类型描述', () => {
114
+ test('应该返回正确的数据库类型描述', () => {
115
+ process.env.db_memory = '1';
116
+ expect(databaseConfigManager.getDatabaseTypeDescription()).toBe('内存数据库(SQLite)');
117
+
118
+ process.env.db_memory = '0';
119
+ process.env.db_type = 'postgres';
120
+ expect(databaseConfigManager.getDatabaseTypeDescription()).toBe('PostgreSQL');
121
+
122
+ process.env.db_type = 'mysql';
123
+ expect(databaseConfigManager.getDatabaseTypeDescription()).toBe('MySQL');
124
+ });
125
+ });
126
+
127
+ describe('数据库监控检查', () => {
128
+ test('应该正确判断是否需要数据库监控', () => {
129
+ process.env.db_enable = '1';
130
+ process.env.db_memory = '1';
131
+ expect(databaseConfigManager.needsDatabaseMonitoring()).toBe(false);
132
+
133
+ process.env.db_enable = '1';
134
+ process.env.db_memory = '0';
135
+ expect(databaseConfigManager.needsDatabaseMonitoring()).toBe(true);
136
+
137
+ process.env.db_enable = '0';
138
+ process.env.db_memory = '0';
139
+ expect(databaseConfigManager.needsDatabaseMonitoring()).toBe(false);
140
+ });
141
+ });
142
+ });
@@ -0,0 +1,153 @@
1
+ import { TestDatabaseHelper, TestUtils } from '../utils/testHelpers';
2
+ import { testDataInitializer } from '../../src/utils/testDataInitializer';
3
+
4
+ describe('集成测试', () => {
5
+ beforeAll(async () => {
6
+ await TestDatabaseHelper.initTestDatabase();
7
+ });
8
+
9
+ afterAll(async () => {
10
+ await TestDatabaseHelper.cleanupTestDatabase();
11
+ });
12
+
13
+ describe('测试数据初始化测试', () => {
14
+ test('应该能够初始化测试数据', async () => {
15
+ await TestDatabaseHelper.resetTestData();
16
+
17
+ const dataSource = TestDatabaseHelper.getTestDataSource();
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');
39
+ });
40
+
41
+ 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);
56
+ });
57
+
58
+ test('应该能够重新初始化测试数据', async () => {
59
+ // 先清空
60
+ 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);
75
+ });
76
+ });
77
+
78
+ describe('数据库连接测试', () => {
79
+ test('应该能够建立数据库连接', () => {
80
+ const dataSource = TestDatabaseHelper.getTestDataSource();
81
+ expect(dataSource).toBeDefined();
82
+ expect(dataSource!.isInitialized).toBe(true);
83
+ });
84
+
85
+ test('应该能够执行SQL查询', async () => {
86
+ const dataSource = TestDatabaseHelper.getTestDataSource();
87
+ const result = await dataSource!.query('SELECT 1 as test');
88
+ expect(result).toBeDefined();
89
+ expect(result[0].test).toBe(1);
90
+ });
91
+
92
+ test('应该能够执行复杂查询', async () => {
93
+ const dataSource = TestDatabaseHelper.getTestDataSource();
94
+
95
+ // 查询用户和店铺的关联信息
96
+ 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
104
+ `);
105
+
106
+ expect(result).toBeDefined();
107
+ expect(result.length).toBeGreaterThan(0);
108
+ expect(result[0].nickName).toBe('测试用户1');
109
+ expect(result[0].shopName).toBe('测试店铺1');
110
+ });
111
+ });
112
+
113
+ describe('缓存集成测试', () => {
114
+ test('应该能够与数据库配合使用缓存', async () => {
115
+ const { createCache, CacheType } = require('../../src/framework/utils/cache');
116
+ const cache = createCache('integration-test', CacheType.TEMP);
117
+
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]);
125
+
126
+ // 从缓存获取数据
127
+ const cachedUser = cache.get(cacheKey);
128
+ expect(cachedUser).toBeDefined();
129
+ expect(cachedUser.id).toBe(users[0].id);
130
+ expect(cachedUser.nickName).toBe(users[0].nickName);
131
+ });
132
+ });
133
+
134
+ describe('错误处理测试', () => {
135
+ test('应该能够处理数据库错误', async () => {
136
+ const dataSource = TestDatabaseHelper.getTestDataSource();
137
+
138
+ // 尝试执行无效的SQL
139
+ await expect(
140
+ dataSource!.query('SELECT * FROM non_existent_table')
141
+ ).rejects.toThrow();
142
+ });
143
+
144
+ test('应该能够处理无效的数据操作', async () => {
145
+ const dataSource = TestDatabaseHelper.getTestDataSource();
146
+
147
+ // 尝试插入无效数据
148
+ await expect(
149
+ dataSource!.query('INSERT INTO yt_user (invalid_column) VALUES (?)', ['test'])
150
+ ).rejects.toThrow();
151
+ });
152
+ });
153
+ });
@@ -0,0 +1,61 @@
1
+ jest.mock("uuid", () => ({ v4: () => "test-uuid" }));
2
+
3
+ import Koa from "koa";
4
+ import Router from "koa-router";
5
+ import request from "supertest";
6
+ import { TestDatabaseHelper } from "../../utils/testHelpers";
7
+ import { plugin as webofficePlugin } from "@src/plugins/weboffice";
8
+ import { WebofficeFileEntity, WebofficeFileVersionEntity } from "@src/plugins/weboffice/entities";
9
+
10
+ describe("weboffice http/routes (integration)", () => {
11
+ beforeAll(async () => {
12
+ await TestDatabaseHelper.initTestDatabase({
13
+ extraEntities: [WebofficeFileEntity, WebofficeFileVersionEntity],
14
+ });
15
+ });
16
+
17
+ afterAll(async () => {
18
+ await TestDatabaseHelper.cleanupTestDatabase();
19
+ });
20
+
21
+ it("GET /v3/3rd/files/:file_id/permission should return permissions", async () => {
22
+ const ds = TestDatabaseHelper.getTestDataSource();
23
+ if (!ds) throw new Error("test datasource not initialized");
24
+
25
+ const fileRepo = ds.getRepository(WebofficeFileEntity);
26
+ const versionRepo = ds.getRepository(WebofficeFileVersionEntity);
27
+
28
+ const file = await fileRepo.save({
29
+ fileId: "testfile01",
30
+ name: "测试文档.docx",
31
+ creatorId: "seed",
32
+ modifierId: "seed",
33
+ currentVersion: 1,
34
+ projectId: null,
35
+ });
36
+ await versionRepo.save({
37
+ webofficeFileId: file.id,
38
+ version: 1,
39
+ size: 0,
40
+ digest: "",
41
+ cosKey: "",
42
+ creatorId: "seed",
43
+ });
44
+
45
+ const app = new Koa();
46
+ const router = new Router();
47
+ webofficePlugin.registerRoutes?.(router);
48
+ app.use(router.routes()).use(router.allowedMethods());
49
+
50
+ const res = await request(app.callback())
51
+ .get("/v3/3rd/files/testfile01/permission")
52
+ .set("X-WebOffice-Token", "test-token")
53
+ .set("X-App-ID", "app");
54
+
55
+ expect(res.status).toBe(200);
56
+ expect(res.body.code).toBe(0);
57
+ expect(res.body.data.user_id).toBe("test_token");
58
+ expect(res.body.data.read).toBe(1);
59
+ });
60
+ });
61
+
@@ -0,0 +1,87 @@
1
+ import { TestDatabaseHelper, TestUtils } from '../utils/testHelpers';
2
+ import { YtUserService } from '../../src/service/ytUser.service';
3
+ import { YtShopService } from '../../src/service/ytShop.service';
4
+ import { YtGoodsService } from '../../src/service/ytGoods.service';
5
+ import { Provider } from 'dp-ioc2';
6
+
7
+ describe('业务服务测试', () => {
8
+ beforeAll(async () => {
9
+ await TestDatabaseHelper.initTestDatabase();
10
+ });
11
+
12
+ afterAll(async () => {
13
+ await TestDatabaseHelper.cleanupTestDatabase();
14
+ });
15
+
16
+ beforeEach(async () => {
17
+ await TestDatabaseHelper.resetTestData();
18
+ });
19
+
20
+ describe('店铺服务测试', () => {
21
+ let shopService: YtShopService;
22
+
23
+ beforeEach(() => {
24
+ shopService = Provider(YtShopService);
25
+ });
26
+
27
+ test('应该能够获取店铺商品列表', async () => {
28
+ const result = await shopService.getGoodsListByShopId(1, 1, 10);
29
+ expect(result.code).toBe('SUCCESS');
30
+ expect(result.data).toBeDefined();
31
+ expect(Array.isArray(result.data?.[0])).toBe(true);
32
+ expect(typeof result.data?.[1]).toBe('number');
33
+ });
34
+
35
+ test('应该能够获取店铺用户信息', async () => {
36
+ const result = await shopService.getShopUserInfo(1);
37
+ expect(result.code).toBe('SUCCESS');
38
+ expect(result.data).toBeDefined();
39
+ expect(result.data?.id).toBeDefined();
40
+ expect(result.data?.nickName).toBeDefined();
41
+ });
42
+
43
+ test('应该能够检查用户是否有店铺', async () => {
44
+ const result = await shopService.checkHasShop(1);
45
+ expect(result.code).toBe('SUCCESS');
46
+ expect(result.data).toBeDefined();
47
+ expect(typeof result.data).toBe('number');
48
+ });
49
+
50
+ test('应该返回null当用户没有店铺时', async () => {
51
+ const result = await shopService.checkHasShop(999);
52
+ expect(result.code).toBe('SUCCESS');
53
+ expect(result.data).toBeNull();
54
+ });
55
+ });
56
+
57
+ describe('商品服务测试', () => {
58
+ let goodsService: YtGoodsService;
59
+
60
+ beforeEach(() => {
61
+ goodsService = Provider(YtGoodsService);
62
+ });
63
+
64
+ test('应该能够解锁商品图片', async () => {
65
+ const result = await goodsService.unlockGoodsImage(1, 1, 'TEST_KEY_001');
66
+ expect(result.code).toBe('SUCCESS');
67
+ expect(result.data).toBe(true);
68
+ });
69
+
70
+ test('应该拒绝无效的解锁密钥', async () => {
71
+ const result = await goodsService.unlockGoodsImage(1, 1, 'INVALID_KEY');
72
+ expect(result.code).toBe('FAIL');
73
+ expect(result.data).toBe(false);
74
+ expect(result.message).toBe('无效的解锁key');
75
+ });
76
+
77
+ test('应该拒绝已使用的解锁密钥', async () => {
78
+ // 先使用一次密钥
79
+ await goodsService.unlockGoodsImage(3, 1, 'USED_KEY_001');
80
+
81
+ // 再次使用应该失败
82
+ const result = await goodsService.unlockGoodsImage(3, 1, 'USED_KEY_001');
83
+ expect(result.code).toBe('FAIL');
84
+ expect(result.data).toBe(false);
85
+ });
86
+ });
87
+ });
@@ -0,0 +1,184 @@
1
+ /**
2
+ * 参数校验测试
3
+ * 测试 dp-ioc2 的 @ParamValidate 装饰器功能
4
+ */
5
+
6
+ import { Provider } from 'dp-ioc2';
7
+ import { ParamValidateTestService, CreateTestUserDto, UpdateTestUserDto } from '../../src/service/paramValidateTest.service';
8
+ import { TestDatabaseHelper } from '../utils/testHelpers';
9
+ import { IOCValidationError } from 'dp-ioc2';
10
+
11
+ describe('ParamValidate 参数校验测试', () => {
12
+ let service: ParamValidateTestService;
13
+
14
+ beforeAll(async () => {
15
+ // 初始化测试数据库
16
+ await TestDatabaseHelper.initTestDatabase();
17
+
18
+ // 使用 Provider 实例化 Service(dp-ioc2 要求)
19
+ service = Provider<ParamValidateTestService>(ParamValidateTestService);
20
+ });
21
+
22
+ afterAll(async () => {
23
+ await TestDatabaseHelper.cleanupTestDatabase();
24
+ });
25
+
26
+ describe('测试1:对象参数校验(class-validator)', () => {
27
+ test('应该能够成功创建用户(参数有效)', async () => {
28
+ const dto: CreateTestUserDto = {
29
+ name: '测试用户',
30
+ email: 'test@example.com',
31
+ age: 25
32
+ };
33
+
34
+ const result = await service.createUser(dto);
35
+
36
+ expect(result.code).toBe('SUCCESS');
37
+ expect(result.data).toBeDefined();
38
+ expect(result.data?.name).toBe('测试用户');
39
+ expect(result.data?.email).toBe('test@example.com');
40
+ expect(result.data?.age).toBe(25);
41
+ });
42
+
43
+ test('应该拒绝无效的用户名(长度不足)', async () => {
44
+ const dto: CreateTestUserDto = {
45
+ name: 'ab', // 长度不足3
46
+ email: 'test@example.com',
47
+ age: 25
48
+ };
49
+
50
+ // @ParamValidate 在方法调用前就抛出异常,需要在调用方捕获
51
+ await expect(service.createUser(dto)).rejects.toThrow(IOCValidationError);
52
+ });
53
+
54
+ test('应该拒绝无效的邮箱格式', async () => {
55
+ const dto: CreateTestUserDto = {
56
+ name: '测试用户',
57
+ email: 'invalid-email', // 无效邮箱
58
+ age: 25
59
+ };
60
+
61
+ await expect(service.createUser(dto)).rejects.toThrow(IOCValidationError);
62
+ });
63
+
64
+ test('应该拒绝年龄小于18', async () => {
65
+ const dto: CreateTestUserDto = {
66
+ name: '测试用户',
67
+ email: 'test@example.com',
68
+ age: 17 // 小于18
69
+ };
70
+
71
+ await expect(service.createUser(dto)).rejects.toThrow(IOCValidationError);
72
+ });
73
+
74
+ test('应该拒绝年龄大于100', async () => {
75
+ const dto: CreateTestUserDto = {
76
+ name: '测试用户',
77
+ email: 'test@example.com',
78
+ age: 101 // 大于100
79
+ };
80
+
81
+ await expect(service.createUser(dto)).rejects.toThrow(IOCValidationError);
82
+ });
83
+
84
+ test('应该支持普通对象自动转换为 DTO 实例', async () => {
85
+ // 传入普通对象,dp-ioc2 会自动转换为 DTO 实例
86
+ const plainObject = {
87
+ name: '测试用户',
88
+ email: 'test@example.com',
89
+ age: 25
90
+ };
91
+
92
+ const result = await service.createUser(plainObject as any);
93
+
94
+ expect(result.code).toBe('SUCCESS');
95
+ expect(result.data).toBeDefined();
96
+ });
97
+ });
98
+
99
+ describe('测试2:基本类型参数校验(Joi)', () => {
100
+ test('应该能够成功获取用户(有效ID)', async () => {
101
+ const result = await service.getUserById(123);
102
+
103
+ expect(result.code).toBe('SUCCESS');
104
+ expect(result.data).toBeDefined();
105
+ expect(result.data?.id).toBe(123);
106
+ });
107
+
108
+ test('应该拒绝负数ID', async () => {
109
+ await expect(service.getUserById(-1)).rejects.toThrow(IOCValidationError);
110
+ });
111
+
112
+ test('应该拒绝零值ID', async () => {
113
+ await expect(service.getUserById(0)).rejects.toThrow(IOCValidationError);
114
+ });
115
+
116
+ test('应该拒绝非整数ID', async () => {
117
+ // TypeScript 类型检查会阻止传入非数字,但运行时可能传入
118
+ await expect(service.getUserById(1.5 as any)).rejects.toThrow(IOCValidationError);
119
+ });
120
+ });
121
+
122
+ describe('测试3:混合参数校验', () => {
123
+ test('应该能够成功更新用户(所有参数有效)', async () => {
124
+ const dto: UpdateTestUserDto = {
125
+ name: '更新后的用户名',
126
+ email: 'updated@example.com'
127
+ };
128
+
129
+ const result = await service.updateUser(123, dto);
130
+
131
+ expect(result.code).toBe('SUCCESS');
132
+ expect(result.data).toBeDefined();
133
+ expect(result.data?.id).toBe(123);
134
+ expect(result.data?.name).toBe('更新后的用户名');
135
+ expect(result.data?.email).toBe('updated@example.com');
136
+ });
137
+
138
+ test('应该拒绝无效的用户ID(负数)', async () => {
139
+ const dto: UpdateTestUserDto = {
140
+ name: '更新后的用户名'
141
+ };
142
+
143
+ await expect(service.updateUser(-1, dto)).rejects.toThrow(IOCValidationError);
144
+ });
145
+
146
+ test('应该拒绝无效的邮箱格式', async () => {
147
+ const dto: UpdateTestUserDto = {
148
+ email: 'invalid-email'
149
+ };
150
+
151
+ await expect(service.updateUser(123, dto)).rejects.toThrow(IOCValidationError);
152
+ });
153
+ });
154
+
155
+ describe('测试4:无校验参数(对比测试)', () => {
156
+ test('无校验的方法应该接受任何参数', async () => {
157
+ // 这个方法没有 @ParamValidate,所以不会进行校验
158
+ const result = await service.getUserWithoutValidation(-1);
159
+
160
+ expect(result.code).toBe('SUCCESS');
161
+ // 即使传入负数,方法也会执行(因为没有校验)
162
+ expect(result.data?.id).toBe(-1);
163
+ });
164
+ });
165
+
166
+ describe('测试5:异常信息验证', () => {
167
+ test('应该包含详细的校验错误信息', async () => {
168
+ const invalidDto = {
169
+ name: 'ab', // 无效
170
+ email: 'invalid',
171
+ age: 10
172
+ };
173
+
174
+ try {
175
+ await service.createUser(invalidDto as any);
176
+ fail('应该抛出 IOCValidationError');
177
+ } catch (error) {
178
+ expect(error).toBeInstanceOf(IOCValidationError);
179
+ expect((error as IOCValidationError).message).toContain('Validation failed');
180
+ }
181
+ });
182
+ });
183
+ });
184
+