create-dp-koa 1.1.1 → 1.1.3

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 (84) hide show
  1. package/package.json +1 -1
  2. package/template/scripts/sync-template.mjs +21 -0
  3. package/template/src/app.ts +1 -2
  4. package/template/src/{framework/plugins → plugins}/registry.ts +2 -2
  5. package/template/src/plugins/weboffice/http/routes.ts +2 -2
  6. package/template/src/plugins/weboffice/index.ts +3 -3
  7. package/template/src/plugins/weboffice/services/webofficeCallback.service.ts +3 -4
  8. package/template/src/utils/testDataInitializer.ts +1 -1
  9. package/template/tsconfig.json +6 -0
  10. package/template/src/annotations/decorators/ConfigManagement.ts +0 -9
  11. package/template/src/annotations/decorators/DistributedTracing.ts +0 -9
  12. package/template/src/annotations/decorators/EnterprisePerformance.ts +0 -9
  13. package/template/src/annotations/decorators/PerformanceMonitor.ts +0 -32
  14. package/template/src/annotations/decorators/SecurityAudit.ts +0 -9
  15. package/template/src/annotations/index.ts +0 -50
  16. package/template/src/annotations/processors/ConfigManagementProcessor.ts +0 -369
  17. package/template/src/annotations/processors/DistributedTracingProcessor.ts +0 -288
  18. package/template/src/annotations/processors/EnterprisePerformanceProcessor.ts +0 -189
  19. package/template/src/annotations/processors/PerformanceMonitorProcessor.ts +0 -101
  20. package/template/src/annotations/processors/SecurityAuditProcessor.ts +0 -345
  21. package/template/src/annotations/processors/SwaggerProcessor.ts +0 -612
  22. package/template/src/annotations/processors/index.ts +0 -10
  23. package/template/src/examples/InterceptorExampleRunner.ts +0 -284
  24. package/template/src/examples/ServiceInterceptorExample.ts +0 -214
  25. package/template/src/examples/cacheExamples.ts +0 -155
  26. package/template/src/framework/decorator/controller.ts +0 -311
  27. package/template/src/framework/decorator/processor/AnnotationDecorators.ts +0 -100
  28. package/template/src/framework/decorator/processor/AnnotationProcessor.ts +0 -160
  29. package/template/src/framework/decorator/processor/AnnotationProcessorConfig.ts +0 -45
  30. package/template/src/framework/decorator/processor/AnnotationRegistry.ts +0 -117
  31. package/template/src/framework/decorator/processor/AnnotationSystemInitializer.ts +0 -95
  32. package/template/src/framework/decorator/processor/ProcessorManager.ts +0 -76
  33. package/template/src/framework/decorator/processor/processors/CustomProcessors.ts +0 -126
  34. package/template/src/framework/decorator/processor/processors/DefaultProcessors.ts +0 -207
  35. package/template/src/framework/decorator/refactored/DecoratorFactory.ts +0 -99
  36. package/template/src/framework/decorator/refactored/DecoratorMetadataManager.ts +0 -125
  37. package/template/src/framework/decorator/refactored/DecoratorValidator.ts +0 -128
  38. package/template/src/framework/decorator/refactored/TypeSafeDecorators.ts +0 -139
  39. package/template/src/framework/decorator/refactored/index.ts +0 -98
  40. package/template/src/framework/decorator/swagger.ts +0 -150
  41. package/template/src/framework/interceptors/AdvancedServiceCallInterceptor.ts +0 -375
  42. package/template/src/framework/interceptors/ServiceCallInterceptor.ts +0 -348
  43. package/template/src/framework/interceptors/index.ts +0 -19
  44. package/template/src/framework/plugins/types.ts +0 -15
  45. package/template/src/framework/types/ServiceResult.ts +0 -151
  46. package/template/src/framework/types/index.ts +0 -16
  47. package/template/src/framework/utils/CacheManager.ts +0 -430
  48. package/template/src/framework/utils/CacheService.ts +0 -248
  49. package/template/src/framework/utils/DtoValidator.ts +0 -164
  50. package/template/src/framework/utils/MigrationHelper.ts +0 -179
  51. package/template/src/framework/utils/MigrationManager.ts +0 -256
  52. package/template/src/framework/utils/NewRouter.ts +0 -207
  53. package/template/src/framework/utils/TransactionManager.ts +0 -172
  54. package/template/src/framework/utils/bootstrap.ts +0 -445
  55. package/template/src/framework/utils/cache.ts +0 -269
  56. package/template/src/framework/utils/databaseConfig.ts +0 -148
  57. package/template/src/framework/utils/db.ts +0 -39
  58. package/template/src/framework/utils/dbMonitor.ts +0 -106
  59. package/template/src/framework/utils/function.ts +0 -61
  60. package/template/src/framework/utils/gracefulShutdown.ts +0 -131
  61. package/template/src/framework/utils/logger.ts +0 -388
  62. package/template/src/framework/utils/metrics.ts +0 -182
  63. package/template/src/framework/utils/router.ts +0 -417
  64. package/template/src/framework/utils/swagger.ts +0 -184
  65. package/template/src/framework/utils/testDb.ts +0 -19
  66. package/template/src/framework/utils/token.ts +0 -23
  67. package/template/src/framework/utils/transform.ts +0 -17
  68. package/template/src/libs/aokEmailSender.ts +0 -42
  69. package/template/src/libs/captcha.ts +0 -37
  70. package/template/src/libs/cos.ts +0 -45
  71. package/template/src/libs/mCache.ts +0 -7
  72. package/template/src/libs/serviceValidate.ts +0 -3
  73. package/template/src/libs/tecentSms.ts +0 -51
  74. package/template/src/middlewares/a.middleware.ts +0 -6
  75. package/template/src/middlewares/error.middleware.ts +0 -14
  76. package/template/src/middlewares/logging.middleware.ts +0 -187
  77. package/template/src/middlewares/static.middleware.ts +0 -79
  78. package/template/src/middlewares/swagger.middleware.ts +0 -70
  79. package/template/src/middlewares/token.middleware.ts +0 -32
  80. package/template/src/migrations/1700000000000-InitialDatabaseStructure.ts +0 -172
  81. package/template/src/migrations/index.ts +0 -6
  82. package/template/src/repository/base/BaseRepository.ts +0 -124
  83. package/template/src/repository/interfaces/IBaseRepository.ts +0 -67
  84. package/template/src/service/base.service.ts +0 -116
@@ -1,37 +0,0 @@
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
- }
@@ -1,45 +0,0 @@
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
-
@@ -1,7 +0,0 @@
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
- });
@@ -1,3 +0,0 @@
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
- }
@@ -1,51 +0,0 @@
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();
@@ -1,6 +0,0 @@
1
- export default function () {
2
- return async (ctx: any, next: Function) => {
3
- // console.log("a middleware ");
4
- await next()
5
- }
6
- }
@@ -1,14 +0,0 @@
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
- }
@@ -1,187 +0,0 @@
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
- }
@@ -1,79 +0,0 @@
1
- import path from "path";
2
- import mount from "koa-mount";
3
- import serve from "koa-static";
4
- import { isDebug } from "@src/framework/utils/function";
5
-
6
- export interface StaticMiddlewareOptions {
7
- /**
8
- * URL 前缀,例如:/static
9
- * - 不建议以 / 结尾
10
- */
11
- urlPrefix?: string;
12
- /**
13
- * 本地目录(相对项目根目录 process.cwd()),例如:assets / uploads
14
- */
15
- dir?: string;
16
- /**
17
- * 生产环境缓存秒数(Cache-Control max-age)
18
- */
19
- maxAgeSeconds?: number;
20
- /**
21
- * 访问前缀根路径时的默认文件,例如:index.html
22
- * - false 表示不提供默认文件
23
- */
24
- index?: string | false;
25
- /**
26
- * 是否在 next() 之后再尝试提供静态文件(默认 false,优先静态)
27
- */
28
- defer?: boolean;
29
- /**
30
- * 是否允许访问隐藏文件(默认 false)
31
- */
32
- hidden?: boolean;
33
- }
34
-
35
- function normalizePrefix(prefix: string): string {
36
- let p = prefix.trim();
37
- if (!p.startsWith("/")) p = `/${p}`;
38
- // 只保留末尾非根路径的前缀(避免 /static/ 和 /static 产生差异)
39
- if (p.length > 1 && p.endsWith("/")) p = p.slice(0, -1);
40
- return p;
41
- }
42
-
43
- /**
44
- * 静态文件映射中间件(基于 koa-static + koa-mount)
45
- * - 默认:/static -> ./static
46
- * - 支持环境变量覆盖:STATIC_URL_PREFIX、STATIC_DIR、STATIC_MAX_AGE_SECONDS、STATIC_INDEX
47
- */
48
- export default function staticMiddleware(options: StaticMiddlewareOptions = {}) {
49
- const urlPrefix = normalizePrefix(
50
- options.urlPrefix ?? process.env.STATIC_URL_PREFIX ?? "/static"
51
- );
52
- const dir = options.dir ?? process.env.STATIC_DIR ?? "static";
53
- const root = path.resolve(process.cwd(), dir);
54
- const index =
55
- options.index ??
56
- (typeof process.env.STATIC_INDEX === "string"
57
- ? process.env.STATIC_INDEX
58
- : false);
59
-
60
- const maxAgeSeconds =
61
- options.maxAgeSeconds ??
62
- (process.env.STATIC_MAX_AGE_SECONDS
63
- ? Number(process.env.STATIC_MAX_AGE_SECONDS)
64
- : !isDebug()
65
- ? 86400
66
- : 0);
67
-
68
- return mount(
69
- urlPrefix,
70
- serve(root, {
71
- maxage: Math.max(0, maxAgeSeconds) * 1000,
72
- index,
73
- defer: options.defer ?? false,
74
- hidden: options.hidden ?? false,
75
- })
76
- );
77
- }
78
-
79
-
@@ -1,70 +0,0 @@
1
- import { getSwaggerSpec } from '@src/framework/utils/swagger';
2
- import { logger } from '@src/framework/utils/logger';
3
-
4
- /**
5
- * Swagger UI中间件 - 简化版本
6
- */
7
- export function swaggerMiddleware() {
8
- logger.info('Swagger UI已配置');
9
-
10
- return async (ctx: any, next: any) => {
11
- if (ctx.path === '/swagger') {
12
- ctx.set('Content-Type', 'text/html');
13
- ctx.body = `
14
- <!DOCTYPE html>
15
- <html>
16
- <head>
17
- <title>DP Koa Framework API文档</title>
18
- <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3.25.0/swagger-ui.css" />
19
- <style>
20
- .topbar { display: none !important; }
21
- .swagger-ui .info { margin: 20px 0; }
22
- </style>
23
- </head>
24
- <body>
25
- <div id="swagger-ui"></div>
26
- <script src="https://unpkg.com/swagger-ui-dist@3.25.0/swagger-ui-bundle.js"></script>
27
- <script>
28
- SwaggerUIBundle({
29
- url: '/swagger.json',
30
- dom_id: '#swagger-ui',
31
- presets: [
32
- SwaggerUIBundle.presets.apis,
33
- SwaggerUIBundle.presets.standalone
34
- ],
35
- layout: "StandaloneLayout"
36
- });
37
- </script>
38
- </body>
39
- </html>
40
- `;
41
- return;
42
- }
43
- await next();
44
- };
45
- }
46
-
47
- /**
48
- * Swagger JSON端点
49
- */
50
- export async function swaggerJson(ctx: any, next: any) {
51
- if (ctx.path === '/swagger.json') {
52
- try {
53
- const swaggerSpec = getSwaggerSpec();
54
-
55
- // 动态从Controller中提取Swagger信息
56
- // 这里可以集成现有的路由系统来生成完整的文档
57
-
58
- ctx.set('Content-Type', 'application/json');
59
- ctx.body = swaggerSpec;
60
- } catch (error) {
61
- logger.error('生成Swagger文档失败:', error as Error);
62
- ctx.status = 500;
63
- ctx.body = { error: '无法生成Swagger文档' };
64
- }
65
- return;
66
- }
67
-
68
- await next();
69
- }
70
-
@@ -1,32 +0,0 @@
1
- import * as jwt from "jsonwebtoken";
2
- import { Context } from "koa";
3
- import { getTokenFromHeader } from "@src/framework/utils/token";
4
-
5
- export default function tokenMiddleware() {
6
-
7
- return async (ctx: Context, next: Function) => {
8
- // 1. 从请求头获取token
9
- const token = getTokenFromHeader(ctx);
10
- if (!token) {
11
- ctx.status = 401;
12
- ctx.body = { code: -1, message: "未提供认证token" };
13
- return;
14
- }
15
-
16
- try {
17
- // 2. 验证token
18
- const decoded = jwt.verify(token, process.env.jwt_secret ?? "123456") as any;
19
-
20
- // 3. 将用户信息挂载到ctx.state
21
- ctx.state.user = {
22
- userId: decoded.userId,
23
- type: decoded.type,
24
- };
25
-
26
- await next();
27
- } catch (err) {
28
- ctx.status = 401;
29
- ctx.body = { code: -1, message: "无效或过期的token" };
30
- }
31
- };
32
- }