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,61 @@
1
+ import path from "path"
2
+
3
+ /**
4
+ * 判断当前是否为调试环境
5
+ */
6
+ export function isDebug(): boolean {
7
+ let argv = new Set(process.argv)
8
+ if (argv.has("--env=debug")) {
9
+ return true
10
+ }
11
+ return false
12
+ }
13
+
14
+ /**
15
+ * 与 NODE_ENV 解耦的运行环境标识(日志/配置元数据等)
16
+ * - 启动参数含 `--env=debug` → development
17
+ * - 否则 → production(非 debug 即生产口径)
18
+ */
19
+ export function getRuntimeEnvironmentLabel(): 'development' | 'production' {
20
+ return isDebug() ? 'development' : 'production'
21
+ }
22
+
23
+
24
+ /**
25
+ * 根据文件夹获取项目目录的全路径
26
+ * @param relativePath
27
+ */
28
+ export function getFullPath(relativePath: string): string {
29
+ return path.join(process.cwd(), relativePath)
30
+ }
31
+
32
+ /**
33
+ * 休眠
34
+ * @param time 毫秒
35
+ */
36
+ export function sleep(time: number) {
37
+ return new Promise((resolve) => {
38
+ setTimeout(() => {
39
+ resolve("")
40
+ }, time);
41
+ })
42
+ }
43
+
44
+ /**
45
+ * 判断Promise
46
+ * @param obj
47
+ * @returns
48
+ */
49
+ export function isPromise(obj: any) {
50
+ return !!obj && typeof obj.then === 'function' && typeof obj.catch === 'function';
51
+ }
52
+
53
+
54
+ /**
55
+ * 生成一定范围内的随机数
56
+ * @param start
57
+ * @param end
58
+ */
59
+ export function getRandoNumer(start: number, end: number): number {
60
+ return Math.floor(Math.random() * (end - start + 1)) + start
61
+ }
@@ -0,0 +1,131 @@
1
+ import { closeServer } from '@src/framework/utils/bootstrap';
2
+
3
+ export type ShutdownReason = 'SIGTERM' | 'SIGINT' | 'uncaughtException' | 'unhandledRejection';
4
+
5
+ export type ShutdownHook = () => void | Promise<void>;
6
+
7
+ export interface ShutdownLogger {
8
+ // 兼容项目内 EnterpriseLogger(通常为 info(message, context?) / error(message, error?, context?))
9
+ info: (message: string, context?: any) => void;
10
+ warn?: (message: string, context?: any) => void;
11
+ error: (message: string, error?: Error, context?: any) => void;
12
+ }
13
+
14
+ export interface GracefulShutdownControllerOptions {
15
+ logger: ShutdownLogger;
16
+ /**
17
+ * 超时后强制退出,避免资源卡死导致进程无法停止
18
+ */
19
+ timeoutMs?: number;
20
+ /**
21
+ * 关闭 HTTP server(stop accepting new connections)
22
+ * 默认为 true
23
+ */
24
+ closeHttpServerFirst?: boolean;
25
+ }
26
+
27
+ type HookItem = { name: string; hook: ShutdownHook };
28
+
29
+ const toError = (value: unknown): Error => {
30
+ if (value instanceof Error) return value;
31
+ if (typeof value === 'string') return new Error(value);
32
+
33
+ if (value && typeof value === 'object') {
34
+ const maybeMessage = (value as any).message;
35
+ if (typeof maybeMessage === 'string' && maybeMessage.trim()) {
36
+ return new Error(maybeMessage);
37
+ }
38
+ }
39
+
40
+ try {
41
+ return new Error(JSON.stringify(value));
42
+ } catch {
43
+ return new Error(String(value));
44
+ }
45
+ };
46
+
47
+ /**
48
+ * 优雅关闭控制器:
49
+ * - 统一注册 SIGTERM/SIGINT/uncaughtException/unhandledRejection
50
+ * - 确保只触发一次
51
+ * - 按注册顺序依次执行 hook(可用于清理 db/cache/monitor 等)
52
+ */
53
+ export const createGracefulShutdownController = (options: GracefulShutdownControllerOptions) => {
54
+ const { logger, timeoutMs = 15_000, closeHttpServerFirst = true } = options;
55
+
56
+ let registered = false;
57
+ let shuttingDown = false;
58
+ const hooks: HookItem[] = [];
59
+
60
+ const addHook = (name: string, hook: ShutdownHook) => {
61
+ hooks.push({ name, hook });
62
+ };
63
+
64
+ const runHooks = async (reason: ShutdownReason, err?: unknown) => {
65
+ if (shuttingDown) return;
66
+ shuttingDown = true;
67
+
68
+ logger.info(`收到 ${reason} 信号,开始优雅关闭...`);
69
+ if (err) {
70
+ logger.error(`触发优雅关闭时携带异常(${reason})`, toError(err));
71
+ }
72
+
73
+ const timer = setTimeout(() => {
74
+ logger.error(`优雅关闭超时(${timeoutMs}ms),强制退出`);
75
+ // eslint-disable-next-line n/no-process-exit
76
+ process.exit(1);
77
+ }, timeoutMs);
78
+ // 让 timer 不阻止进程退出
79
+ timer.unref?.();
80
+
81
+ let exitCode = 0;
82
+
83
+ try {
84
+ if (closeHttpServerFirst) {
85
+ try {
86
+ await closeServer();
87
+ } catch (e) {
88
+ exitCode = 1;
89
+ logger.error('关闭 HTTP Server 失败', toError(e));
90
+ }
91
+ }
92
+
93
+ for (const item of hooks) {
94
+ try {
95
+ await item.hook();
96
+ } catch (e) {
97
+ exitCode = 1;
98
+ logger.error(`执行关闭钩子失败: ${item.name}`, toError(e));
99
+ }
100
+ }
101
+
102
+ logger.info('优雅关闭完成');
103
+ } finally {
104
+ clearTimeout(timer);
105
+ // eslint-disable-next-line n/no-process-exit
106
+ process.exit(exitCode);
107
+ }
108
+ };
109
+
110
+ const register = () => {
111
+ if (registered) return;
112
+ registered = true;
113
+
114
+ process.on('SIGTERM', () => runHooks('SIGTERM'));
115
+ process.on('SIGINT', () => runHooks('SIGINT'));
116
+
117
+ process.on('uncaughtException', (error) => {
118
+ logger.error('未捕获的异常:', error);
119
+ runHooks('uncaughtException', error);
120
+ });
121
+
122
+ process.on('unhandledRejection', (reason) => {
123
+ logger.error('未处理的 Promise 拒绝:', toError(reason));
124
+ runHooks('unhandledRejection', reason);
125
+ });
126
+ };
127
+
128
+ return { addHook, register };
129
+ };
130
+
131
+
@@ -0,0 +1,388 @@
1
+ import log4js from 'log4js'
2
+ import { getFullPath, isDebug, getRuntimeEnvironmentLabel } from '@src/framework/utils/function'
3
+ import { randomUUID } from 'crypto'
4
+
5
+ // 企业级日志配置
6
+ interface LogContext {
7
+ requestId?: string
8
+ userId?: string
9
+ sessionId?: string
10
+ traceId?: string
11
+ spanId?: string
12
+ service?: string
13
+ version?: string
14
+ environment?: string
15
+ [key: string]: any
16
+ }
17
+
18
+ // 敏感信息脱敏配置
19
+ const SENSITIVE_FIELDS = [
20
+ 'password', 'token', 'secret', 'key', 'auth', 'credential',
21
+ 'ssn', 'socialSecurityNumber', 'creditCard', 'cardNumber',
22
+ 'phone', 'email', 'address', 'ip', 'mac'
23
+ ]
24
+
25
+ // 自定义布局器 - 支持结构化日志
26
+ class EnterpriseLayout {
27
+ constructor(private config: any) {}
28
+
29
+ format(loggingEvent: any): string {
30
+ const timestamp = new Date(loggingEvent.startTime).toISOString()
31
+ const level = loggingEvent.level.levelStr
32
+ const category = loggingEvent.categoryName
33
+ const message = loggingEvent.data[0]
34
+ const context = loggingEvent.context || {}
35
+
36
+ // 构建结构化日志对象
37
+ const logEntry = {
38
+ timestamp,
39
+ level,
40
+ category,
41
+ message,
42
+ service: context.service || 'dp-koa-framework',
43
+ version: context.version || '1.0.0',
44
+ environment: context.environment || getRuntimeEnvironmentLabel(),
45
+ requestId: context.requestId,
46
+ userId: context.userId,
47
+ sessionId: context.sessionId,
48
+ traceId: context.traceId,
49
+ spanId: context.spanId,
50
+ pid: process.pid,
51
+ hostname: process.env.HOSTNAME || 'localhost',
52
+ ...this.extractAdditionalData(loggingEvent.data.slice(1))
53
+ }
54
+
55
+ // 脱敏处理
56
+ this.sanitizeSensitiveData(logEntry)
57
+
58
+ return JSON.stringify(logEntry)
59
+ }
60
+
61
+ private extractAdditionalData(data: any[]): any {
62
+ const additionalData: any = {}
63
+
64
+ data.forEach((item, index) => {
65
+ if (typeof item === 'object' && item !== null) {
66
+ Object.assign(additionalData, item)
67
+ } else {
68
+ additionalData[`param${index}`] = item
69
+ }
70
+ })
71
+
72
+ return additionalData
73
+ }
74
+
75
+ private sanitizeSensitiveData(obj: any): void {
76
+ const sanitize = (value: any): any => {
77
+ if (typeof value === 'string') {
78
+ return '***REDACTED***'
79
+ }
80
+ if (typeof value === 'object' && value !== null) {
81
+ const sanitized: any = {}
82
+ for (const [key, val] of Object.entries(value)) {
83
+ sanitized[key] = this.isSensitiveField(key) ? '***REDACTED***' : sanitize(val)
84
+ }
85
+ return sanitized
86
+ }
87
+ return value
88
+ }
89
+
90
+ for (const [key, value] of Object.entries(obj)) {
91
+ if (this.isSensitiveField(key)) {
92
+ obj[key] = '***REDACTED***'
93
+ } else if (typeof value === 'object' && value !== null) {
94
+ obj[key] = sanitize(value)
95
+ }
96
+ }
97
+ }
98
+
99
+ private isSensitiveField(fieldName: string): boolean {
100
+ return SENSITIVE_FIELDS.some(field =>
101
+ fieldName.toLowerCase().includes(field.toLowerCase())
102
+ )
103
+ }
104
+ }
105
+
106
+ // 企业级日志器类
107
+ class EnterpriseLogger {
108
+ private logger: log4js.Logger
109
+ private context: LogContext = {}
110
+ private isProduction: boolean
111
+
112
+ constructor() {
113
+ this.logger = log4js.getLogger()
114
+ this.isProduction = !isDebug()
115
+ this.setupContext()
116
+ }
117
+
118
+ private setupContext(): void {
119
+ this.context = {
120
+ service: 'dp-koa-framework',
121
+ version: process.env.npm_package_version || '1.0.0',
122
+ environment: getRuntimeEnvironmentLabel(),
123
+ pid: process.pid,
124
+ hostname: process.env.HOSTNAME || 'localhost'
125
+ }
126
+ }
127
+
128
+ // 设置请求上下文
129
+ setRequestContext(requestId: string, userId?: string, sessionId?: string): void {
130
+ this.context.requestId = requestId
131
+ this.context.userId = userId
132
+ this.context.sessionId = sessionId
133
+ }
134
+
135
+ // 设置追踪上下文
136
+ setTraceContext(traceId: string, spanId?: string): void {
137
+ this.context.traceId = traceId
138
+ this.context.spanId = spanId
139
+ }
140
+
141
+ // 清除上下文
142
+ clearContext(): void {
143
+ this.context = {
144
+ service: 'dp-koa-framework',
145
+ version: process.env.npm_package_version || '1.0.0',
146
+ environment: getRuntimeEnvironmentLabel(),
147
+ pid: process.pid,
148
+ hostname: process.env.HOSTNAME || 'localhost'
149
+ }
150
+ }
151
+
152
+ // 生成请求ID
153
+ generateRequestId(): string {
154
+ return randomUUID()
155
+ }
156
+
157
+ // 安全审计日志
158
+ audit(action: string, resource: string, details?: any): void {
159
+ // 审计日志写入文件,但不在控制台输出
160
+ const auditLogger = log4js.getLogger('audit')
161
+ auditLogger.info('AUDIT', {
162
+ ...this.context,
163
+ action,
164
+ resource,
165
+ details,
166
+ timestamp: new Date().toISOString()
167
+ })
168
+ }
169
+
170
+ // 性能监控日志 - 使用独立的category,不在控制台输出
171
+ performance(operation: string, duration: number, metrics?: any): void {
172
+ // 只在生产环境的慢请求时输出到控制台
173
+ if (this.isProduction && duration > 1000) {
174
+ this.logger.warn('慢请求警告', {
175
+ operation,
176
+ duration,
177
+ metrics
178
+ })
179
+ }
180
+ // 性能日志始终写入文件,但不会输出到控制台
181
+ const perfLogger = log4js.getLogger('performance')
182
+ perfLogger.info('PERFORMANCE', {
183
+ ...this.context,
184
+ operation,
185
+ duration,
186
+ metrics,
187
+ timestamp: new Date().toISOString()
188
+ })
189
+ }
190
+
191
+ // 安全事件日志
192
+ security(event: string, severity: 'low' | 'medium' | 'high' | 'critical', details?: any): void {
193
+ this.logger.warn('SECURITY', {
194
+ ...this.context,
195
+ event,
196
+ severity,
197
+ details,
198
+ timestamp: new Date().toISOString()
199
+ })
200
+ }
201
+
202
+ // 业务事件日志 - 不输出到控制台,只写入文件
203
+ business(event: string, data?: any): void {
204
+ // 业务日志不输出到控制台,会被 shouldFilterInfo 过滤掉
205
+ // 如果需要查看业务日志,请查看 logs/structured.log 文件
206
+ this.info('BUSINESS', {
207
+ ...this.context,
208
+ event,
209
+ data,
210
+ timestamp: new Date().toISOString()
211
+ })
212
+ }
213
+
214
+ // 错误日志增强
215
+ error(message: string, error?: Error, context?: any): void {
216
+ const errorDetails = error ? {
217
+ name: error.name,
218
+ message: error.message,
219
+ stack: error.stack,
220
+ code: (error as any).code
221
+ } : undefined
222
+
223
+ this.logger.error(message, {
224
+ ...this.context,
225
+ error: errorDetails,
226
+ context,
227
+ timestamp: new Date().toISOString()
228
+ })
229
+ }
230
+
231
+ // 标准日志方法 - 带智能过滤
232
+ info(message: string, ...args: any[]): void {
233
+ // 过滤掉冗余信息
234
+ if (this.shouldFilterInfo(message)) {
235
+ return
236
+ }
237
+ this.logger.info(message, ...args)
238
+ }
239
+
240
+ warn(message: string, ...args: any[]): void {
241
+ this.logger.warn(message, ...args)
242
+ }
243
+
244
+ debug(message: string, ...args: any[]): void {
245
+ // 只在调试模式下输出debug日志
246
+ if (!isDebug()) {
247
+ return
248
+ }
249
+ this.logger.debug(message, ...args)
250
+ }
251
+
252
+ trace(message: string, ...args: any[]): void {
253
+ // 只在调试模式下输出trace日志
254
+ if (!isDebug()) {
255
+ return
256
+ }
257
+ this.logger.trace(message, ...args)
258
+ }
259
+
260
+ // 判断是否应该过滤info级别的日志
261
+ private shouldFilterInfo(message: string): boolean {
262
+ const filterPatterns = [
263
+ '创建缓存',
264
+ '缓存命中',
265
+ '缓存未命中',
266
+ 'Request started',
267
+ 'Request completed',
268
+ '启动后执行',
269
+ '启动前初始化完毕',
270
+ '启动成功',
271
+ '[Logging]',
272
+ 'BUSINESS'
273
+ ]
274
+
275
+ return filterPatterns.some(pattern => message.includes(pattern))
276
+ }
277
+
278
+ // 获取当前上下文
279
+ getContext(): LogContext {
280
+ return { ...this.context }
281
+ }
282
+ }
283
+
284
+ // 注册自定义布局器
285
+ log4js.addLayout('enterprise', (config: any) => {
286
+ const layout = new EnterpriseLayout(config)
287
+ return (logEvent: any) => layout.format(logEvent)
288
+ })
289
+
290
+ // 配置log4js
291
+ log4js.configure({
292
+ pm2: true,
293
+ appenders: {
294
+ // 结构化日志文件
295
+ structured: {
296
+ type: 'dateFile',
297
+ filename: getFullPath("/logs/structured"),
298
+ pattern: 'yyyy-MM-dd.log',
299
+ alwaysIncludePattern: true,
300
+ maxLogSize: '50M',
301
+ backups: 30,
302
+ layout: {
303
+ type: 'enterprise'
304
+ },
305
+ },
306
+ // 错误日志文件
307
+ error: {
308
+ type: 'dateFile',
309
+ filename: getFullPath("/logs/error"),
310
+ pattern: 'yyyy-MM-dd.log',
311
+ alwaysIncludePattern: true,
312
+ maxLogSize: '20M',
313
+ backups: 15,
314
+ layout: {
315
+ type: 'enterprise'
316
+ },
317
+ },
318
+ // 审计日志文件
319
+ audit: {
320
+ type: 'dateFile',
321
+ filename: getFullPath("/logs/audit"),
322
+ pattern: 'yyyy-MM-dd.log',
323
+ alwaysIncludePattern: true,
324
+ maxLogSize: '30M',
325
+ backups: 20,
326
+ layout: {
327
+ type: 'enterprise'
328
+ },
329
+ },
330
+ // 性能日志文件
331
+ performance: {
332
+ type: 'dateFile',
333
+ filename: getFullPath("/logs/performance"),
334
+ pattern: 'yyyy-MM-dd.log',
335
+ alwaysIncludePattern: true,
336
+ maxLogSize: '25M',
337
+ backups: 15,
338
+ layout: {
339
+ type: 'enterprise'
340
+ },
341
+ // 不输出到控制台
342
+ suppressClustering: true
343
+ },
344
+ // 控制台输出 - 简化格式
345
+ console: {
346
+ type: 'console',
347
+ layout: {
348
+ type: 'colored',
349
+ pattern: isDebug()
350
+ ? '[%d{hh:mm:ss}] [%p] %c - %m'
351
+ : '[%d{hh:mm:ss}] [%p] %m'
352
+ }
353
+ }
354
+ },
355
+ categories: {
356
+ default: {
357
+ // 开发与生产均输出到控制台,便于查看启动与运行状态
358
+ appenders: ['console', 'structured'],
359
+ level: isDebug() ? 'debug' : 'info'
360
+ },
361
+ error: {
362
+ appenders: ['error', 'console'],
363
+ level: 'error'
364
+ },
365
+ audit: {
366
+ appenders: ['audit'],
367
+ level: 'info'
368
+ },
369
+ performance: {
370
+ appenders: ['performance'], // 只写入文件,不输出到控制台
371
+ level: 'info'
372
+ }
373
+ }
374
+ })
375
+
376
+ // 创建企业级日志器实例
377
+ export const logger = new EnterpriseLogger()
378
+
379
+ // 导出类型和工具函数
380
+ export { LogContext, EnterpriseLogger }
381
+ export const createRequestLogger = (requestId?: string) => {
382
+ const requestLogger = new EnterpriseLogger()
383
+ if (requestId) {
384
+ requestLogger.setRequestContext(requestId)
385
+ }
386
+ return requestLogger
387
+ }
388
+