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,148 @@
1
+ import { DataSourceOptions } from "typeorm";
2
+ import { logger } from "@src/framework/utils/logger";
3
+ import { APP_MIGRATIONS } from "@src/migrations";
4
+ import { isDebug } from "@src/framework/utils/function";
5
+
6
+ /**
7
+ * 数据库配置工具
8
+ * 框架级别的数据库配置管理
9
+ */
10
+ export class DatabaseConfigManager {
11
+ private static instance: DatabaseConfigManager;
12
+
13
+ private constructor() {}
14
+
15
+ static getInstance(): DatabaseConfigManager {
16
+ if (!DatabaseConfigManager.instance) {
17
+ DatabaseConfigManager.instance = new DatabaseConfigManager();
18
+ }
19
+ return DatabaseConfigManager.instance;
20
+ }
21
+
22
+ /**
23
+ * 检查是否启用数据库
24
+ */
25
+ isDatabaseEnabled(): boolean {
26
+ // 在内存数据库模式下也启用数据库
27
+ if (this.isMemoryDatabaseMode()) {
28
+ return true;
29
+ }
30
+ return Number(process.env.db_enable) == 1;
31
+ }
32
+
33
+ /**
34
+ * 检查是否为内存数据库模式
35
+ */
36
+ isMemoryDatabaseMode(): boolean {
37
+ return Number(process.env.db_memory) == 1;
38
+ }
39
+
40
+ /**
41
+ * 获取数据库类型(postgres | mysql),仅非内存模式时有效
42
+ */
43
+ private getDbType(): 'postgres' | 'mysql' {
44
+ const t = (process.env.db_type || 'postgres').toLowerCase();
45
+ return t === 'mysql' ? 'mysql' : 'postgres';
46
+ }
47
+
48
+ /**
49
+ * 获取数据库配置
50
+ * @param entities 实体列表
51
+ * 内存模式:SQLite 内存(单元测试保持此方案);否则按 db_type 使用 PostgreSQL 或 MySQL
52
+ */
53
+ getDatabaseConfig(entities: any[]): DataSourceOptions {
54
+ if (this.isMemoryDatabaseMode()) {
55
+ logger.info("启用内存数据库模式(SQLite)");
56
+ return this.getMemoryDatabaseConfig(entities);
57
+ }
58
+ const dbType = this.getDbType();
59
+ if (dbType === 'postgres') {
60
+ logger.info("启用 PostgreSQL 数据库模式");
61
+ return this.getPostgresDatabaseConfig(entities);
62
+ }
63
+ logger.info("启用 MySQL 数据库模式");
64
+ return this.getMySQLDatabaseConfig(entities);
65
+ }
66
+
67
+ /**
68
+ * 获取内存数据库配置
69
+ * 使用 SQLite 内存数据库,适合开发和测试环境
70
+ */
71
+ private getMemoryDatabaseConfig(entities: any[]): DataSourceOptions {
72
+ // 使用 SQLite 内存数据库
73
+ return {
74
+ type: "sqlite",
75
+ database: ":memory:", // SQLite 内存数据库
76
+ entities: entities,
77
+ synchronize: true,
78
+ logging: false,
79
+ dropSchema: true, // 每次启动时重新创建表结构
80
+ };
81
+ }
82
+
83
+ /**
84
+ * 获取 PostgreSQL 数据库配置(dev/debug 推荐)
85
+ */
86
+ private getPostgresDatabaseConfig(entities: any[]): DataSourceOptions {
87
+ const debug = isDebug();
88
+ return {
89
+ type: "postgres",
90
+ host: process.env.db_host ?? "127.0.0.1",
91
+ port: parseInt(process.env.db_port || "5432", 10),
92
+ username: process.env.db_username ?? "admin",
93
+ password: process.env.db_password ?? "",
94
+ database: process.env.db_database ?? "mydb",
95
+ entities: entities,
96
+ // 非 debug(生产口径)关闭自动同步,避免与 migration 冲突
97
+ synchronize: debug,
98
+ logging: process.env.db_logging === "1",
99
+ migrations: APP_MIGRATIONS,
100
+ migrationsRun: false,
101
+ migrationsTableName: "migrations",
102
+ };
103
+ }
104
+
105
+ /**
106
+ * 获取 MySQL 数据库配置
107
+ */
108
+ private getMySQLDatabaseConfig(entities: any[]): DataSourceOptions {
109
+ const debug = isDebug();
110
+ return {
111
+ type: "mysql",
112
+ connectorPackage: "mysql2",
113
+ host: process.env?.db_host ?? "127.0.0.1",
114
+ port: parseInt(process.env.db_port || "3306", 10),
115
+ username: process.env?.db_username ?? "test",
116
+ password: process.env?.db_password ?? "test",
117
+ database: process.env?.db_database ?? "test",
118
+ entities: entities,
119
+ // 非 debug(生产口径)关闭自动同步,避免与 migration 冲突
120
+ synchronize: debug,
121
+ logging: false,
122
+ migrations: APP_MIGRATIONS,
123
+ migrationsRun: false,
124
+ migrationsTableName: "migrations",
125
+ };
126
+ }
127
+
128
+ /**
129
+ * 获取数据库类型描述
130
+ */
131
+ getDatabaseTypeDescription(): string {
132
+ if (this.isMemoryDatabaseMode()) {
133
+ return "内存数据库(SQLite)";
134
+ }
135
+ return this.getDbType() === "postgres" ? "PostgreSQL" : "MySQL";
136
+ }
137
+
138
+ /**
139
+ * 检查是否需要数据库监控
140
+ * 内存数据库不需要连接池监控
141
+ */
142
+ needsDatabaseMonitoring(): boolean {
143
+ return this.isDatabaseEnabled() && !this.isMemoryDatabaseMode();
144
+ }
145
+ }
146
+
147
+ // 导出单例实例
148
+ export const databaseConfigManager = DatabaseConfigManager.getInstance();
@@ -0,0 +1,39 @@
1
+ import { DataSource, DataSourceOptions } from "typeorm"
2
+ import { logger } from "@src/framework/utils/logger"
3
+
4
+ var _MysqlDataSource: DataSource | null = null;
5
+
6
+ export const initDb = async (option: DataSourceOptions) => {
7
+ _MysqlDataSource = new DataSource(option);
8
+ return _MysqlDataSource.initialize();
9
+ }
10
+
11
+ export const getDataSource = (): DataSource | null => {
12
+ return _MysqlDataSource
13
+ }
14
+
15
+ /**
16
+ * 关闭数据库连接
17
+ * 在应用关闭时调用,确保数据库连接池被正确释放
18
+ */
19
+ export const closeDb = async (): Promise<void> => {
20
+ if (_MysqlDataSource && _MysqlDataSource.isInitialized) {
21
+ try {
22
+ await _MysqlDataSource.destroy();
23
+ _MysqlDataSource = null;
24
+ logger.info("数据库连接已关闭");
25
+ } catch (error) {
26
+ logger.error("关闭数据库连接时发生错误:", error as Error);
27
+ throw error;
28
+ }
29
+ } else {
30
+ logger.info("数据库连接未初始化或已关闭");
31
+ }
32
+ }
33
+
34
+ /**
35
+ * 检查数据库连接状态
36
+ */
37
+ export const isDbConnected = (): boolean => {
38
+ return _MysqlDataSource !== null && _MysqlDataSource.isInitialized;
39
+ }
@@ -0,0 +1,106 @@
1
+ import { logger } from "@src/framework/utils/logger";
2
+ import { getDataSource, isDbConnected } from "@src/framework/utils/db";
3
+
4
+ /**
5
+ * 数据库连接监控工具
6
+ */
7
+ export class DbMonitor {
8
+ private static instance: DbMonitor;
9
+ private monitorInterval: NodeJS.Timeout | null = null;
10
+
11
+ private constructor() {}
12
+
13
+ static getInstance(): DbMonitor {
14
+ if (!DbMonitor.instance) {
15
+ DbMonitor.instance = new DbMonitor();
16
+ }
17
+ return DbMonitor.instance;
18
+ }
19
+
20
+ /**
21
+ * 开始监控数据库连接状态
22
+ * @param intervalMs 监控间隔(毫秒),默认30秒
23
+ */
24
+ startMonitoring(intervalMs: number = 30000): void {
25
+ if (this.monitorInterval) {
26
+ logger.warn("数据库监控已在运行中");
27
+ return;
28
+ }
29
+
30
+ this.monitorInterval = setInterval(async () => {
31
+ try {
32
+ const isConnected = isDbConnected();
33
+ const dataSource = getDataSource();
34
+
35
+ if (isConnected && dataSource) {
36
+ // 检查是否为内存数据库
37
+ const driver = (dataSource as any).driver;
38
+ if (driver && driver.options && driver.options.database === ':memory:') {
39
+ logger.debug("内存数据库连接正常");
40
+ } else {
41
+ await dataSource.query('SELECT 1');
42
+ const dbType = (dataSource as any).options?.type ?? 'mysql';
43
+ logger.debug(`${dbType} 数据库连接正常`);
44
+ }
45
+ } else {
46
+ logger.warn("数据库连接异常");
47
+ }
48
+ } catch (error) {
49
+ logger.error("数据库连接检查失败:", error as Error);
50
+ }
51
+ }, intervalMs);
52
+
53
+ logger.info(`数据库连接监控已启动,监控间隔: ${intervalMs}ms`);
54
+ }
55
+
56
+ /**
57
+ * 停止监控
58
+ */
59
+ stopMonitoring(): void {
60
+ if (this.monitorInterval) {
61
+ clearInterval(this.monitorInterval);
62
+ this.monitorInterval = null;
63
+ logger.info("数据库连接监控已停止");
64
+ }
65
+ }
66
+
67
+ /**
68
+ * 获取数据库连接池状态
69
+ */
70
+ async getConnectionPoolStatus(): Promise<any> {
71
+ const dataSource = getDataSource();
72
+ if (!dataSource || !dataSource.isInitialized) {
73
+ return { status: 'disconnected' };
74
+ }
75
+
76
+ try {
77
+ // 检查是否为内存数据库
78
+ const driver = (dataSource as any).driver;
79
+ if (driver && driver.options && driver.options.database === ':memory:') {
80
+ return {
81
+ status: 'connected',
82
+ type: 'memory',
83
+ message: '内存数据库模式'
84
+ };
85
+ }
86
+
87
+ const dbType = (dataSource as any).options?.type ?? 'mysql';
88
+ if (driver && driver.pool) {
89
+ return {
90
+ status: 'connected',
91
+ type: dbType,
92
+ totalConnections: driver.pool._allConnections?.length || 0,
93
+ freeConnections: driver.pool._freeConnections?.length || 0,
94
+ usedConnections: driver.pool._usedConnections?.length || 0
95
+ };
96
+ }
97
+ return { status: 'connected', type: dbType, poolInfo: 'unavailable' };
98
+ } catch (error) {
99
+ logger.error("获取连接池状态失败:", error as Error);
100
+ return { status: 'error', error: error instanceof Error ? error.message : '未知错误' };
101
+ }
102
+ }
103
+ }
104
+
105
+ // 导出单例实例
106
+ export const dbMonitor = DbMonitor.getInstance();
@@ -0,0 +1,410 @@
1
+ import { Provider } from "dp-ioc2";
2
+ import { SwaggerExampleController } from "@src/controllers/example/SwaggerExampleController";
3
+ import { logger } from "@src/framework/utils/logger";
4
+ import { swaggerProcessor } from "@src/annotations/processors/SwaggerProcessor";
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+
8
+ /**
9
+ * 动态检测 bindRouter 路径前缀
10
+ * 通过分析路由注册信息来确定实际的前缀路径
11
+ */
12
+ function getBindRouterPrefix(): string {
13
+ // 方法1: 从环境变量读取(推荐用于生产环境)
14
+ if (process.env.SWAGGER_ROUTE_PREFIX) {
15
+ const prefix = process.env.SWAGGER_ROUTE_PREFIX;
16
+ logger.info(`使用环境变量中的 Swagger 路径前缀: ${prefix}`);
17
+ return prefix.startsWith('/') ? prefix : `/${prefix}`;
18
+ }
19
+
20
+ // 方法2: 从路由文件中动态检测(开发环境和调试模式)
21
+ try {
22
+ const detectedPrefix = detectPrefixFromRouterFile();
23
+ if (detectedPrefix) {
24
+ logger.info(`从路由文件检测到 Swagger 路径前缀: ${detectedPrefix}`);
25
+ return detectedPrefix;
26
+ }
27
+
28
+ // 方法3: 使用默认值
29
+ const defaultPrefix = '/swagger/b';
30
+ logger.info(`使用默认 Swagger 路径前缀: ${defaultPrefix}`);
31
+ return defaultPrefix;
32
+ } catch (error) {
33
+ logger.warn('无法动态检测路由前缀,使用默认值');
34
+ return '/swagger/b';
35
+ }
36
+ }
37
+
38
+ /**
39
+ * 从路由文件中检测 SwaggerExampleController 的路径前缀
40
+ */
41
+ function detectPrefixFromRouterFile(): string | null {
42
+ try {
43
+ // 获取路由文件路径
44
+ const routerFilePath = path.join(process.cwd(), 'src/routers/index.ts');
45
+
46
+ if (!fs.existsSync(routerFilePath)) {
47
+ logger.warn('路由文件不存在');
48
+ return null;
49
+ }
50
+
51
+ // 读取路由文件内容
52
+ const content = fs.readFileSync(routerFilePath, 'utf8');
53
+
54
+ // 查找 SwaggerExampleController 的 bindRouter 调用
55
+ const regex = /bindRouter\s*\(\s*["']([^"']+)["']\s*,\s*SwaggerExampleController\s*\)/;
56
+ const match = content.match(regex);
57
+
58
+ if (match && match[1]) {
59
+ const detectedPrefix = match[1];
60
+ logger.info(`从路由文件检测到前缀: ${detectedPrefix}`);
61
+ return detectedPrefix;
62
+ } else {
63
+ logger.warn('未找到 SwaggerExampleController 的 bindRouter 调用');
64
+ return null;
65
+ }
66
+ } catch (error) {
67
+ logger.error('检测路由文件失败:', error as Error);
68
+ return null;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * 动态生成 Swagger 规范
74
+ * 使用新的Swagger处理器来生成更完整的API文档
75
+ */
76
+ export function generateDynamicSwaggerSpec() {
77
+ try {
78
+ logger.info('开始使用Swagger处理器生成API规范...');
79
+
80
+ // 获取 SwaggerExampleController 实例
81
+ const controller = Provider<any>(SwaggerExampleController);
82
+
83
+ // 使用Swagger处理器生成OpenAPI规范
84
+ const openAPISpec = swaggerProcessor.generateOpenAPISpec([controller]);
85
+
86
+ // 动态检测 bindRouter 路径前缀
87
+ const bindRouterPrefix = getBindRouterPrefix();
88
+
89
+ // 更新服务器URL
90
+ openAPISpec.servers = [
91
+ {
92
+ url: 'http://localhost:3000',
93
+ description: '开发环境',
94
+ },
95
+ ];
96
+
97
+ // 收集所有路由信息并更新路径
98
+ const routes: Array<{method: string, path: string, methodName: string}> = [];
99
+
100
+ // 收集 GET 方法
101
+ if (controller.$_GetMethods) {
102
+ const getMethods = Array.from(controller.$_GetMethods) as Array<{methodName: string, url: string}>;
103
+ getMethods.forEach(({ methodName, url }) => {
104
+ routes.push({ method: 'get', path: `${bindRouterPrefix}${url}`, methodName });
105
+ });
106
+ }
107
+
108
+ // 收集 POST 方法
109
+ if (controller.$_PostMethods) {
110
+ const postMethods = Array.from(controller.$_PostMethods) as Array<{methodName: string, url: string}>;
111
+ postMethods.forEach(({ methodName, url }) => {
112
+ routes.push({ method: 'post', path: `${bindRouterPrefix}${url}`, methodName });
113
+ });
114
+ }
115
+
116
+ // 收集 PUT 方法
117
+ if (controller.$_PutMethods) {
118
+ const putMethods = Array.from(controller.$_PutMethods) as Array<{methodName: string, url: string}>;
119
+ putMethods.forEach(({ methodName, url }) => {
120
+ routes.push({ method: 'put', path: `${bindRouterPrefix}${url}`, methodName });
121
+ });
122
+ }
123
+
124
+ // 收集 DELETE 方法
125
+ if (controller.$_DelMethods) {
126
+ const delMethods = Array.from(controller.$_DelMethods) as Array<{methodName: string, url: string}>;
127
+ delMethods.forEach(({ methodName, url }) => {
128
+ routes.push({ method: 'delete', path: `${bindRouterPrefix}${url}`, methodName });
129
+ });
130
+ }
131
+
132
+ // 更新OpenAPI规范中的路径
133
+ routes.forEach(({ method, path, methodName }) => {
134
+ const swaggerPath = path.replace(/:(\w+)/g, '{$1}');
135
+
136
+ if (!openAPISpec.paths[swaggerPath]) {
137
+ openAPISpec.paths[swaggerPath] = {};
138
+ }
139
+
140
+ // 获取方法的Swagger元数据
141
+ const methodMetadata = swaggerProcessor.processMethod(controller, methodName);
142
+
143
+ openAPISpec.paths[swaggerPath][method] = {
144
+ operationId: methodMetadata.operationId,
145
+ summary: methodMetadata.summary,
146
+ description: methodMetadata.description,
147
+ tags: methodMetadata.tags,
148
+ parameters: methodMetadata.parameters,
149
+ responses: methodMetadata.responses.reduce((acc, response) => {
150
+ acc[response.status.toString()] = {
151
+ description: response.description,
152
+ content: response.content
153
+ };
154
+ return acc;
155
+ }, {} as Record<string, any>)
156
+ };
157
+
158
+ // 添加请求体
159
+ if (methodMetadata.requestBody) {
160
+ openAPISpec.paths[swaggerPath][method].requestBody = methodMetadata.requestBody;
161
+ }
162
+ });
163
+
164
+ logger.info(`使用Swagger处理器生成API规范成功,包含 ${routes.length} 个路由`);
165
+ return openAPISpec;
166
+
167
+ } catch (error) {
168
+ logger.error('使用Swagger处理器生成API规范失败:', error as Error);
169
+ return getFallbackSwaggerSpec();
170
+ }
171
+ }
172
+
173
+ /**
174
+ * 获取方法的 Swagger 元数据
175
+ */
176
+ function getMethodSwaggerMetadata(controller: any, methodName: string) {
177
+ try {
178
+ // 尝试从控制器的元数据中获取 Swagger 注解信息
179
+ const metadata = Reflect.getMetadata('swagger:metadata', controller, methodName);
180
+
181
+ if (metadata) {
182
+ logger.info(`找到方法 ${methodName} 的 Swagger 元数据`);
183
+ return metadata;
184
+ }
185
+
186
+ // 如果没有找到元数据,返回默认值
187
+ return getDefaultMethodMetadata(methodName);
188
+ } catch (error) {
189
+ logger.warn(`获取方法 ${methodName} 的 Swagger 元数据失败:`, error as Error);
190
+ return getDefaultMethodMetadata(methodName);
191
+ }
192
+ }
193
+
194
+ /**
195
+ * 获取默认的方法元数据
196
+ */
197
+ function getDefaultMethodMetadata(methodName: string) {
198
+ const baseMetadata = {
199
+ responses: {
200
+ '200': {
201
+ description: '成功',
202
+ content: {
203
+ 'application/json': {
204
+ schema: {
205
+ type: 'object',
206
+ properties: {
207
+ code: { type: 'number', example: 0 },
208
+ data: { type: 'object' },
209
+ message: { type: 'string', example: '操作成功' }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ }
216
+ };
217
+
218
+ // 根据方法名添加特定的参数
219
+ if (methodName.includes('List') || methodName.includes('list')) {
220
+ return {
221
+ ...baseMetadata,
222
+ parameters: [
223
+ {
224
+ name: 'page',
225
+ in: 'query',
226
+ schema: { type: 'number', default: 1 },
227
+ description: '页码'
228
+ },
229
+ {
230
+ name: 'pageSize',
231
+ in: 'query',
232
+ schema: { type: 'number', default: 10 },
233
+ description: '每页数量'
234
+ },
235
+ {
236
+ name: 'keyword',
237
+ in: 'query',
238
+ schema: { type: 'string' },
239
+ description: '搜索关键词'
240
+ }
241
+ ]
242
+ };
243
+ }
244
+
245
+ if (methodName.includes('ById') || methodName.includes('ById')) {
246
+ return {
247
+ ...baseMetadata,
248
+ parameters: [
249
+ {
250
+ name: 'id',
251
+ in: 'path',
252
+ required: true,
253
+ schema: { type: 'number' },
254
+ description: 'ID'
255
+ }
256
+ ]
257
+ };
258
+ }
259
+
260
+ // DELETE 方法添加路径参数
261
+ if (methodName.includes('delete') || methodName.includes('Delete')) {
262
+ return {
263
+ ...baseMetadata,
264
+ parameters: [
265
+ {
266
+ name: 'id',
267
+ in: 'path',
268
+ required: true,
269
+ schema: { type: 'number' },
270
+ description: 'ID'
271
+ }
272
+ ]
273
+ };
274
+ }
275
+
276
+ // POST 方法添加请求体
277
+ if (methodName.includes('create') || methodName.includes('Create')) {
278
+ return {
279
+ ...baseMetadata,
280
+ requestBody: {
281
+ required: true,
282
+ content: {
283
+ 'application/json': {
284
+ schema: {
285
+ type: 'object',
286
+ required: ['name', 'email'],
287
+ properties: {
288
+ name: {
289
+ type: 'string',
290
+ description: '用户名',
291
+ example: '张三'
292
+ },
293
+ email: {
294
+ type: 'string',
295
+ format: 'email',
296
+ description: '邮箱',
297
+ example: 'zhang@example.com'
298
+ },
299
+ age: {
300
+ type: 'number',
301
+ description: '年龄',
302
+ example: 25
303
+ }
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+ };
310
+ }
311
+
312
+ // PUT 方法添加路径参数和请求体
313
+ if (methodName.includes('update') || methodName.includes('Update')) {
314
+ return {
315
+ ...baseMetadata,
316
+ parameters: [
317
+ {
318
+ name: 'id',
319
+ in: 'path',
320
+ required: true,
321
+ schema: { type: 'number' },
322
+ description: 'ID'
323
+ }
324
+ ],
325
+ requestBody: {
326
+ required: true,
327
+ content: {
328
+ 'application/json': {
329
+ schema: {
330
+ type: 'object',
331
+ properties: {
332
+ name: { type: 'string', description: '用户名' },
333
+ email: { type: 'string', format: 'email', description: '邮箱' },
334
+ age: { type: 'number', description: '年龄' }
335
+ }
336
+ }
337
+ }
338
+ }
339
+ }
340
+ };
341
+ }
342
+
343
+ return baseMetadata;
344
+ }
345
+
346
+ /**
347
+ * 获取默认摘要
348
+ */
349
+ function getDefaultSummary(method: string, path: string) {
350
+ const methodMap: {[key: string]: string} = {
351
+ 'get': '获取',
352
+ 'post': '创建',
353
+ 'put': '更新',
354
+ 'delete': '删除'
355
+ };
356
+
357
+ const action = methodMap[method] || '操作';
358
+ const resource = path.includes('list') ? '列表' :
359
+ path.includes('{id}') ? '详情' : '资源';
360
+
361
+ return `${action}${resource}`;
362
+ }
363
+
364
+ /**
365
+ * 获取默认描述
366
+ */
367
+ function getDefaultDescription(method: string, path: string) {
368
+ const descriptions: {[key: string]: string} = {
369
+ 'get': path.includes('list') ? '获取列表数据' : '获取详细信息',
370
+ 'post': '创建新资源',
371
+ 'put': '更新资源信息',
372
+ 'delete': '删除资源'
373
+ };
374
+
375
+ return descriptions[method] || 'API 操作';
376
+ }
377
+
378
+ /**
379
+ * 备用 Swagger 规范
380
+ */
381
+ function getFallbackSwaggerSpec() {
382
+ return {
383
+ openapi: '3.0.0',
384
+ info: {
385
+ title: 'DP Koa Framework API',
386
+ version: '1.0.0',
387
+ description: '基于Koa的企业级框架API文档',
388
+ },
389
+ servers: [
390
+ {
391
+ url: 'http://localhost:3000',
392
+ description: '开发环境',
393
+ },
394
+ ],
395
+ paths: {
396
+ '/swagger/user/list': {
397
+ get: {
398
+ tags: ['用户管理'],
399
+ summary: '获取用户列表',
400
+ description: '获取用户列表数据',
401
+ responses: {
402
+ '200': {
403
+ description: '成功返回用户列表',
404
+ },
405
+ },
406
+ },
407
+ },
408
+ },
409
+ };
410
+ }