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,184 @@
1
+ import swaggerJsdoc from 'swagger-jsdoc';
2
+ import { logger } from './logger';
3
+
4
+ /**
5
+ * Swagger配置
6
+ */
7
+ const swaggerOptions: swaggerJsdoc.Options = {
8
+ definition: {
9
+ openapi: '3.0.0',
10
+ info: {
11
+ title: 'DP Koa Framework API',
12
+ version: '1.0.0',
13
+ description: '基于Koa的企业级框架API文档',
14
+ contact: {
15
+ name: 'API Support',
16
+ email: 'support@example.com',
17
+ },
18
+ license: {
19
+ name: 'MIT',
20
+ url: 'https://opensource.org/licenses/MIT',
21
+ },
22
+ },
23
+ servers: [
24
+ {
25
+ url: process.env.API_BASE_URL || 'http://localhost:3000',
26
+ description: '开发环境',
27
+ },
28
+ ],
29
+ components: {
30
+ securitySchemes: {
31
+ bearerAuth: {
32
+ type: 'http',
33
+ scheme: 'bearer',
34
+ bearerFormat: 'JWT',
35
+ description: 'JWT授权',
36
+ },
37
+ },
38
+ },
39
+ tags: [
40
+ {
41
+ name: '示例',
42
+ description: '示例API接口',
43
+ },
44
+ {
45
+ name: '用户',
46
+ description: '用户相关接口',
47
+ },
48
+ {
49
+ name: '健康检查',
50
+ description: '系统健康检查接口',
51
+ },
52
+ ],
53
+ },
54
+ apis: [
55
+ './src/controllers/**/*.ts',
56
+ './src/dto/**/*.ts',
57
+ ],
58
+ };
59
+
60
+ /**
61
+ * 生成Swagger规范
62
+ */
63
+ export function getSwaggerSpec(): any {
64
+ const spec = swaggerJsdoc(swaggerOptions);
65
+ return spec;
66
+ }
67
+
68
+ /**
69
+ * 从Controller中提取Swagger信息
70
+ */
71
+ export function extractSwaggerFromController(controller: any, methodName: string, routePath: string, httpMethod: string) {
72
+ try {
73
+ // 获取方法的Swagger元数据
74
+ const metadata: any = {
75
+ operationId: `${methodName}`,
76
+ tags: [],
77
+ summary: '',
78
+ description: '',
79
+ parameters: [],
80
+ requestBody: null,
81
+ responses: {},
82
+ };
83
+
84
+ // 获取类级别的标签
85
+ if (controller.constructor.$_SwaggerTags) {
86
+ metadata.tags = controller.constructor.$_SwaggerTags;
87
+ }
88
+
89
+ // 获取方法级别的元数据
90
+ if (controller.$_SwaggerMethods && controller.$_SwaggerMethods.has(methodName)) {
91
+ const methodMeta = controller.$_SwaggerMethods.get(methodName);
92
+ metadata.summary = methodMeta.summary || methodName;
93
+ metadata.description = methodMeta.description || '';
94
+ metadata.operationId = methodMeta.operationId || methodName;
95
+ if (methodMeta.tags && methodMeta.tags.length > 0) {
96
+ metadata.tags = methodMeta.tags;
97
+ }
98
+ }
99
+
100
+ // 获取参数信息
101
+ if (controller.$_SwaggerParams && controller.$_SwaggerParams.has(methodName)) {
102
+ const params = controller.$_SwaggerParams.get(methodName);
103
+ metadata.parameters = params.map((param: any) => ({
104
+ name: param.name,
105
+ in: param.in,
106
+ description: param.description,
107
+ required: param.required || false,
108
+ schema: param.schema || { type: 'string' },
109
+ example: param.example,
110
+ }));
111
+ }
112
+
113
+ // 获取请求体信息
114
+ if (controller.$_SwaggerBodies && controller.$_SwaggerBodies.has(methodName)) {
115
+ const body = controller.$_SwaggerBodies.get(methodName);
116
+ metadata.requestBody = {
117
+ description: body.description || '',
118
+ required: body.required || false,
119
+ content: {
120
+ 'application/json': {
121
+ schema: body.schema,
122
+ examples: body.examples,
123
+ },
124
+ },
125
+ };
126
+ }
127
+
128
+ // 获取响应信息
129
+ if (controller.$_SwaggerResponses && controller.$_SwaggerResponses.has(methodName)) {
130
+ const responses = controller.$_SwaggerResponses.get(methodName);
131
+ responses.forEach((response: any) => {
132
+ metadata.responses[response.status] = {
133
+ description: response.description,
134
+ content: response.schema ? {
135
+ 'application/json': {
136
+ schema: response.schema,
137
+ examples: response.examples,
138
+ },
139
+ } : undefined,
140
+ };
141
+ });
142
+ } else {
143
+ // 默认成功响应
144
+ metadata.responses['200'] = {
145
+ description: '成功响应',
146
+ content: {
147
+ 'application/json': {
148
+ schema: {
149
+ type: 'object',
150
+ properties: {
151
+ code: { type: 'number' },
152
+ data: { type: 'object' },
153
+ message: { type: 'string' },
154
+ },
155
+ },
156
+ },
157
+ },
158
+ };
159
+ }
160
+
161
+ return metadata;
162
+ } catch (error) {
163
+ logger.error('提取Swagger信息失败:', error as Error);
164
+ return null;
165
+ }
166
+ }
167
+
168
+ /**
169
+ * 根据路径参数生成Swagger路径定义
170
+ */
171
+ export function generateSwaggerPath(path: string, httpMethod: string, swaggerData: any): string {
172
+ // 将路径参数转换为Swagger格式
173
+ let swaggerPath = path;
174
+ const params = swaggerData?.parameters || [];
175
+
176
+ params.forEach((param: any) => {
177
+ if (param.in === 'path') {
178
+ swaggerPath = swaggerPath.replace(`/${param.name}`, `/{${param.name}}`);
179
+ }
180
+ });
181
+
182
+ return swaggerPath;
183
+ }
184
+
@@ -0,0 +1,19 @@
1
+ import { DataSource } from "typeorm"
2
+ import "reflect-metadata"
3
+
4
+ export const createTestDataSource = async (entities: any[]) => {
5
+ return new DataSource({
6
+ type: "sqlite",
7
+ database: ":memory:",
8
+ dropSchema: true,
9
+ synchronize: true,
10
+ logging: false,
11
+ entities: entities
12
+ }).initialize()
13
+ }
14
+
15
+ export const closeTestDataSource = async (dataSource: DataSource) => {
16
+ if (dataSource.isInitialized) {
17
+ await dataSource.destroy()
18
+ }
19
+ }
@@ -0,0 +1,23 @@
1
+ import { Context } from "koa";
2
+
3
+ export function getTokenFromHeader(ctx: Context): string | null {
4
+ // 1. 从Authorization头获取token
5
+ const authHeader = ctx.headers.authorization || ctx.headers.Authorization;
6
+ if (!authHeader) {
7
+ return null;
8
+ }
9
+
10
+ // 2. 检查Bearer token格式
11
+ if (typeof authHeader === 'string') {
12
+ const parts = authHeader.split(' ');
13
+ if (parts.length === 2 && parts[0] === 'Bearer') {
14
+ return parts[1];
15
+ }
16
+ }
17
+
18
+ return null;
19
+ }
20
+
21
+ export function setTokenToHeader(ctx: Context, token: string): void {
22
+ ctx.set('Authorization', `Bearer ${token}`);
23
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 转为数字类型
3
+ * @param val
4
+ * @returns
5
+ */
6
+ export function ToNumber(val: any) {
7
+ return Number(val);
8
+ }
9
+
10
+ /**
11
+ * 去除多余的空格
12
+ * @param val
13
+ * @returns
14
+ */
15
+ export function Trim(val: string) {
16
+ return String(val).trim();
17
+ }
@@ -0,0 +1,42 @@
1
+
2
+ type EmailParams = {
3
+ to: string;
4
+ templateId: string;
5
+ templateData?: Record<string, string>;
6
+ };
7
+
8
+ export class AokEmailSender{
9
+ private apiKey: string;
10
+ private apiUrl: string;
11
+
12
+ constructor(apiKey: string, apiUrl = 'https://www.aoksend.com/index/api/send_email') {
13
+ this.apiKey = apiKey;
14
+ this.apiUrl = apiUrl;
15
+ }
16
+
17
+ async sendEmail(params: EmailParams): Promise<any> {
18
+ try {
19
+ const formData = new URLSearchParams();
20
+ formData.append('app_key', this.apiKey);
21
+ formData.append('to', params.to);
22
+ formData.append('template_id', params.templateId || '');
23
+ formData.append('data', JSON.stringify(params.templateData || {}));
24
+
25
+ const response = await fetch(this.apiUrl, {
26
+ method: 'POST',
27
+ headers: {
28
+ 'Content-Type': 'application/x-www-form-urlencoded'
29
+ },
30
+ body: formData.toString()
31
+ });
32
+ ``
33
+ if (!response.ok) {
34
+ const errorData = await response.json();
35
+ throw new Error(errorData.message || 'Failed to send email');
36
+ }
37
+ return await response.json();
38
+ } catch (error) {
39
+ throw new Error(error instanceof Error ? error.message : 'Failed to send email');
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,37 @@
1
+ import svgCaptcha from 'svg-captcha';
2
+ import jwt from 'jsonwebtoken';
3
+
4
+ export class CaptchaGenerator {
5
+ private static readonly JWT_SECRET = process.env.CAPTCHA_JWT_SECRET || 'captcha_secret';
6
+ private static readonly JWT_EXPIRES_IN = '5m';
7
+
8
+ static generate() {
9
+ const captcha = svgCaptcha.create({
10
+ size: 4,
11
+ ignoreChars: '0o1i',
12
+ noise: 2,
13
+ color: true,
14
+ background: '#f0f0f0'
15
+ });
16
+
17
+ const token = jwt.sign(
18
+ { captcha: captcha.text.toLowerCase() },
19
+ this.JWT_SECRET,
20
+ { expiresIn: this.JWT_EXPIRES_IN }
21
+ );
22
+
23
+ return {
24
+ image: captcha.data,
25
+ token
26
+ };
27
+ }
28
+
29
+ static verify(token: string, input: string): boolean {
30
+ try {
31
+ const decoded = jwt.verify(token, this.JWT_SECRET) as { captcha: string };
32
+ return decoded.captcha === input?.toLowerCase();
33
+ } catch {
34
+ return false;
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,45 @@
1
+ import COS from "cos-nodejs-sdk-v5";
2
+ import fs from "fs";
3
+
4
+ const SECRET_ID = process.env.COS_SECRET_ID || "";
5
+ const SECRET_KEY = process.env.COS_SECRET_KEY || "";
6
+ const BUCKET = process.env.COS_BUCKET || "";
7
+ const REGION = process.env.COS_REGION || "";
8
+ const FILES_HOST =
9
+ process.env.WEBOFFICE_FILES_HOST || process.env.FILES_HOST || "";
10
+
11
+ function getCosClient(): COS | null {
12
+ if (!SECRET_ID || !SECRET_KEY) return null;
13
+ return new COS({
14
+ SecretId: SECRET_ID,
15
+ SecretKey: SECRET_KEY,
16
+ });
17
+ }
18
+
19
+ export function isCosConfigured(): boolean {
20
+ return !!(SECRET_ID && SECRET_KEY && BUCKET && REGION);
21
+ }
22
+
23
+ export async function uploadToCos(localFilePath: string, key: string): Promise<void> {
24
+ const client = getCosClient();
25
+ if (!client) throw new Error("COS client not configured");
26
+ if (!BUCKET || !REGION) throw new Error("COS bucket/region not configured");
27
+ await client.putObject({
28
+ Bucket: BUCKET,
29
+ Region: REGION,
30
+ Key: key,
31
+ Body: fs.createReadStream(localFilePath),
32
+ });
33
+ }
34
+
35
+ export function getFilePublicUrl(key: string): string {
36
+ if (!FILES_HOST) return "";
37
+ const host = FILES_HOST.replace(/\/$/, "");
38
+ const k = key.replace(/^\//, "");
39
+ return `${host}/${k}`;
40
+ }
41
+
42
+ export function webofficeCosKey(fileId: string, version: number): string {
43
+ return `weboffice/files/${fileId}/v${version}`;
44
+ }
45
+
@@ -0,0 +1,7 @@
1
+ import { createCache, CacheType } from "@src/framework/utils/cache";
2
+
3
+ // 使用统一的缓存管理创建用户缓存
4
+ export const ytUserCache = createCache('yt-user', CacheType.USER, {
5
+ stdTTL: 600, // 10分钟过期
6
+ maxKeys: 500 // 用户缓存限制500个
7
+ });
@@ -0,0 +1,3 @@
1
+ export const ServiceValidate = (params: any, instance: any, fn: Function, done: (err: any, param: any) => void) => {
2
+ console.log(params, instance, fn, done, "seravice拦截器");
3
+ }
@@ -0,0 +1,51 @@
1
+ import * as tencentcloud from 'tencentcloud-sdk-nodejs';
2
+ import { config } from 'dotenv';
3
+
4
+ type SmsParams = {
5
+ PhoneNumberSet: string[];
6
+ TemplateId: string;
7
+ SignName: string;
8
+ TemplateParamSet?: string[];
9
+ SmsSdkAppId: string;
10
+ };
11
+
12
+ export class TencentSms {
13
+ private client: any;
14
+
15
+ constructor() {
16
+ config();
17
+ const SmsClient = tencentcloud.sms.v20210111.Client;
18
+
19
+ this.client = new SmsClient({
20
+ credential: {
21
+ secretId: process.env.TENCENT_SMS_SECRET_ID,
22
+ secretKey: process.env.TENCENT_SMS_SECRET_KEY,
23
+ },
24
+ region: process.env.TENCENT_SMS_REGION || 'ap-guangzhou',
25
+ profile: {
26
+ httpProfile: {
27
+ endpoint: 'sms.tencentcloudapi.com',
28
+ },
29
+ },
30
+ });
31
+ }
32
+
33
+ async sendSms(params: SmsParams): Promise<any> {
34
+ try {
35
+ const request = {
36
+ PhoneNumberSet: params.PhoneNumberSet,
37
+ TemplateId: params.TemplateId,
38
+ SignName: params.SignName,
39
+ TemplateParamSet: params.TemplateParamSet || [],
40
+ SmsSdkAppId: params.SmsSdkAppId,
41
+ };
42
+
43
+ return await this.client.SendSms(request);
44
+ } catch (error) {
45
+ throw error;
46
+ // throw new Error(`Failed to send SMS: ${error.message}`);
47
+ }
48
+ }
49
+ }
50
+
51
+ export const tencentSms = new TencentSms();
@@ -0,0 +1,6 @@
1
+ export default function () {
2
+ return async (ctx: any, next: Function) => {
3
+ // console.log("a middleware ");
4
+ await next()
5
+ }
6
+ }
@@ -0,0 +1,14 @@
1
+ import { logger } from "@src/framework/utils/logger";
2
+
3
+ export default function () {
4
+ return async (ctx: any, next: Function) => {
5
+ try {
6
+ await next();
7
+ } catch (err) {
8
+ const error = err as any;
9
+ ctx.status = 500;
10
+ logger.error((err as Error).message || 'Unknown error');
11
+ return ctx.body = error;
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,187 @@
1
+ import { Context, Next } from 'koa'
2
+ import { logger, createRequestLogger } from '@src/framework/utils/logger'
3
+ import { isDebug } from '@src/framework/utils/function'
4
+
5
+ /**
6
+ * 企业级日志中间件
7
+ * 提供请求追踪、性能监控、安全审计等功能
8
+ */
9
+ export const loggingMiddleware = () => {
10
+ return async (ctx: Context, next: Next) => {
11
+ const startTime = Date.now()
12
+ const requestId = logger.generateRequestId()
13
+
14
+ // 创建请求专用的日志器
15
+ const requestLogger = createRequestLogger(requestId)
16
+
17
+ // 设置请求上下文
18
+ requestLogger.setRequestContext(
19
+ requestId,
20
+ ctx.state.user?.id,
21
+ ctx.session?.id
22
+ )
23
+
24
+ // 设置追踪上下文(如果存在)
25
+ const traceId = ctx.get('X-Trace-ID') || ctx.get('X-Request-ID')
26
+ if (traceId) {
27
+ requestLogger.setTraceContext(traceId, requestId)
28
+ }
29
+
30
+ // 记录请求开始 - 只在调试模式下记录详细信息
31
+ if (isDebug()) {
32
+ requestLogger.debug('Request started', {
33
+ method: ctx.method,
34
+ url: ctx.url,
35
+ userAgent: ctx.get('User-Agent'),
36
+ ip: ctx.ip,
37
+ headers: sanitizeHeaders(ctx.headers)
38
+ })
39
+ }
40
+
41
+ // 审计日志 - 请求访问(只在调试模式下输出到控制台)
42
+ if (isDebug()) {
43
+ requestLogger.audit('REQUEST_ACCESS', ctx.url, {
44
+ method: ctx.method,
45
+ ip: ctx.ip,
46
+ userAgent: ctx.get('User-Agent'),
47
+ userId: ctx.state.user?.id
48
+ })
49
+ }
50
+
51
+ // 将日志器添加到上下文
52
+ ctx.logger = requestLogger
53
+ ctx.requestId = requestId
54
+
55
+ try {
56
+ await next()
57
+
58
+ const duration = Date.now() - startTime
59
+
60
+ // 记录请求完成 - 只在调试模式或慢请求时记录
61
+ if (isDebug() || duration > 1000) {
62
+ requestLogger.info('Request completed', {
63
+ method: ctx.method,
64
+ url: ctx.url,
65
+ status: ctx.status,
66
+ duration: `${duration}ms`,
67
+ responseSize: ctx.response.length || 0
68
+ })
69
+ }
70
+
71
+ // 性能监控日志 - 只在调试模式下输出到控制台
72
+ if (isDebug()) {
73
+ requestLogger.performance('HTTP_REQUEST', duration, {
74
+ method: ctx.method,
75
+ url: ctx.url,
76
+ status: ctx.status,
77
+ responseSize: ctx.response.length || 0
78
+ })
79
+ }
80
+
81
+ // 安全审计 - 响应状态
82
+ if (ctx.status >= 400) {
83
+ requestLogger.security('HTTP_ERROR_RESPONSE',
84
+ ctx.status >= 500 ? 'high' : 'medium',
85
+ {
86
+ status: ctx.status,
87
+ method: ctx.method,
88
+ url: ctx.url,
89
+ userId: ctx.state.user?.id
90
+ }
91
+ )
92
+ }
93
+
94
+ } catch (error) {
95
+ const duration = Date.now() - startTime
96
+
97
+ // 记录错误
98
+ requestLogger.error('Request failed', error as Error, {
99
+ method: ctx.method,
100
+ url: ctx.url,
101
+ duration: `${duration}ms`
102
+ })
103
+
104
+ // 安全审计 - 错误事件
105
+ requestLogger.security('REQUEST_ERROR', 'high', {
106
+ error: error instanceof Error ? error.message : 'Unknown error',
107
+ method: ctx.method,
108
+ url: ctx.url,
109
+ userId: ctx.state.user?.id
110
+ })
111
+
112
+ throw error
113
+ } finally {
114
+ // 清理上下文
115
+ requestLogger.clearContext()
116
+ }
117
+ }
118
+ }
119
+
120
+ /**
121
+ * 脱敏请求头
122
+ */
123
+ function sanitizeHeaders(headers: any): any {
124
+ const sanitized = { ...headers }
125
+ const sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-auth-token']
126
+
127
+ sensitiveHeaders.forEach(header => {
128
+ if (sanitized[header]) {
129
+ sanitized[header] = '***REDACTED***'
130
+ }
131
+ })
132
+
133
+ return sanitized
134
+ }
135
+
136
+ /**
137
+ * 业务日志中间件
138
+ * 用于记录业务操作
139
+ */
140
+ export const businessLoggingMiddleware = () => {
141
+ return async (ctx: Context, next: Next) => {
142
+ const originalBody = ctx.body
143
+
144
+ await next()
145
+
146
+ // 记录业务操作 - 注释掉,不在控制台输出
147
+ // 如果需要查看业务日志,请查看 logs/structured.log 文件
148
+ // if (ctx.logger && ctx.status < 400 && isDebug()) {
149
+ // ctx.logger.business('API_CALL', {
150
+ // method: ctx.method,
151
+ // url: ctx.url,
152
+ // status: ctx.status,
153
+ // userId: ctx.state.user?.id,
154
+ // timestamp: new Date().toISOString()
155
+ // })
156
+ // }
157
+ }
158
+ }
159
+
160
+ /**
161
+ * 数据库操作日志中间件
162
+ */
163
+ export const databaseLoggingMiddleware = () => {
164
+ return async (ctx: Context, next: Next) => {
165
+ const startTime = Date.now()
166
+
167
+ await next()
168
+
169
+ const duration = Date.now() - startTime
170
+
171
+ if (ctx.logger && duration > 100) { // 只记录超过100ms的数据库操作
172
+ ctx.logger.performance('DATABASE_OPERATION', duration, {
173
+ method: ctx.method,
174
+ url: ctx.url,
175
+ userId: ctx.state.user?.id
176
+ })
177
+ }
178
+ }
179
+ }
180
+
181
+ // 扩展Context类型
182
+ declare module 'koa' {
183
+ interface Context {
184
+ logger: any
185
+ requestId: string
186
+ }
187
+ }