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.
- package/README.md +50 -0
- package/index.mjs +97 -0
- package/package.json +33 -0
- package/template/.env.development +9 -0
- package/template/.env.production +12 -0
- package/template/.github/workflows/ci-cd.yml +182 -0
- package/template/.trae/documents/controller_development_plan.md +386 -0
- package/template/.trae/skills/00-backend-core.skill.md +50 -0
- package/template/.trae/skills/01-backend-skill-router.skill.md +55 -0
- package/template/.trae/skills/10-backend-api.skill.md +54 -0
- package/template/.trae/skills/11-backend-controller-recipes.skill.md +107 -0
- package/template/.trae/skills/20-backend-repository.skill.md +25 -0
- package/template/.trae/skills/21-backend-service.skill.md +135 -0
- package/template/.trae/skills/25-backend-comments-and-doc.skill.md +97 -0
- package/template/.trae/skills/30-backend-validation.skill.md +320 -0
- package/template/.trae/skills/40-backend-error-logging.skill.md +21 -0
- package/template/.trae/skills/50-backend-bootstrap-lifecycle.skill.md +90 -0
- package/template/.trae/skills/60-backend-router-registration.skill.md +71 -0
- package/template/.trae/skills/70-backend-middleware.skill.md +98 -0
- package/template/.trae/skills/80-backend-utils-and-libs.skill.md +90 -0
- package/template/.trae/skills/85-backend-plugins.rule.md +64 -0
- package/template/.trae/skills/90-backend-testing.skill.md +29 -0
- package/template/.trae/skills/README.md +49 -0
- package/template/.vscode/launch.json +38 -0
- package/template/.vscode/settings.json +1 -0
- package/template/Dockerfile +36 -0
- package/template/README.md +229 -0
- package/template/docker-compose.yml +135 -0
- package/template/docs/API_DOCUMENTATION.md +837 -0
- package/template/docs/ARCHITECTURE_REFACTOR.md +109 -0
- package/template/docs/CACHE_MIGRATION_GUIDE.md +142 -0
- package/template/docs/DEPLOYMENT_GUIDE.md +1062 -0
- package/template/docs/DEVELOPMENT_GUIDE.md +1097 -0
- package/template/docs/DOCUMENTATION_CLEANUP_REPORT.md +166 -0
- package/template/docs/DOCUMENTATION_COMPLETION_REPORT.md +223 -0
- package/template/docs/DOCUMENTATION_INDEX.md +294 -0
- package/template/docs/DOCUMENTATION_STRUCTURE.md +221 -0
- package/template/docs/ENTERPRISE_ANNOTATION_SYSTEM_GUIDE.md +2069 -0
- package/template/docs/ENTERPRISE_DATABASE_ARCHITECTURE.md +318 -0
- package/template/docs/ENTERPRISE_DEPLOYMENT_GUIDE.md +547 -0
- package/template/docs/ENTERPRISE_ERROR_HANDLING_GUIDE.md +357 -0
- package/template/docs/ENTERPRISE_LOGGING_SYSTEM_GUIDE.md +494 -0
- package/template/docs/ENVIRONMENT_CONFIG_EXAMPLE.md +69 -0
- package/template/docs/FINAL_IMPLEMENTATION_SUMMARY.md +206 -0
- package/template/docs/HEALTH_CHECK_ROUTE_FIX.md +134 -0
- package/template/docs/IMPLEMENTATION_CHECKLIST.md +204 -0
- package/template/docs/INSTALLATION_GUIDE.md +611 -0
- package/template/docs/INTERCEPTOR_TESTING_REPORT.md +226 -0
- package/template/docs/INTERCEPTOR_TESTING_SCRIPTS.md +143 -0
- package/template/docs/LOGGING_OPTIMIZATION_GUIDE.md +126 -0
- package/template/docs/MEMORY_DATABASE_GUIDE.md +212 -0
- package/template/docs/NEW_ROUTER_INTEGRATION_GUIDE.md +345 -0
- package/template/docs/NEW_ROUTER_INTEGRATION_SUMMARY.md +259 -0
- package/template/docs/NEW_ROUTER_USAGE_GUIDE.md +364 -0
- package/template/docs/QUICK_START.md +268 -0
- package/template/docs/ROUTE_SLASH_COMPATIBILITY_FIX.md +191 -0
- package/template/docs/SERVICE_INTERCEPTOR_GUIDE.md +243 -0
- package/template/docs/SERVICE_LAYER_INDEX.md +205 -0
- package/template/docs/SERVICE_PATTERN_GUIDE.md +270 -0
- package/template/docs/SERVICE_RETURN_VALUE_SPECIFICATION.md +466 -0
- package/template/docs/SWAGGER_DEBUG_MODE_GUIDE.md +80 -0
- package/template/docs/SWAGGER_INTEGRATION_GUIDE.md +416 -0
- package/template/docs/TRANSACTION_MANAGER_USAGE.md +360 -0
- package/template/docs/TROUBLESHOOTING.md +869 -0
- package/template/env.production.example +62 -0
- package/template/jest.config.js +34 -0
- package/template/package-lock.json +13240 -0
- package/template/package.json +119 -0
- package/template/patches/typeorm+0.3.25.patch +22 -0
- package/template/scripts/sync-template.mjs +84 -0
- package/template/scripts/test-annotation-system.sh +48 -0
- package/template/scripts/test-core-functionality.sh +28 -0
- package/template/src/annotations/decorators/ConfigManagement.ts +9 -0
- package/template/src/annotations/decorators/DistributedTracing.ts +9 -0
- package/template/src/annotations/decorators/EnterprisePerformance.ts +9 -0
- package/template/src/annotations/decorators/PerformanceMonitor.ts +32 -0
- package/template/src/annotations/decorators/SecurityAudit.ts +9 -0
- package/template/src/annotations/index.ts +50 -0
- package/template/src/annotations/processors/ConfigManagementProcessor.ts +369 -0
- package/template/src/annotations/processors/DistributedTracingProcessor.ts +288 -0
- package/template/src/annotations/processors/EnterprisePerformanceProcessor.ts +189 -0
- package/template/src/annotations/processors/PerformanceMonitorProcessor.ts +101 -0
- package/template/src/annotations/processors/SecurityAuditProcessor.ts +345 -0
- package/template/src/annotations/processors/SwaggerProcessor.ts +612 -0
- package/template/src/annotations/processors/index.ts +10 -0
- package/template/src/app.ts +123 -0
- package/template/src/controllers/base.controller.ts +41 -0
- package/template/src/controllers/cacheManagement.controller.ts +131 -0
- package/template/src/controllers/captcha.controller.ts +57 -0
- package/template/src/controllers/demo/AnnotationDemoController.ts +118 -0
- package/template/src/controllers/example/EnterpriseExampleController.ts +297 -0
- package/template/src/controllers/example/ExampleController.ts +110 -0
- package/template/src/controllers/example/NewAnnotationExampleController.ts +159 -0
- package/template/src/controllers/example/SwaggerExampleController.ts +205 -0
- package/template/src/controllers/example/TransactionExample.controller.ts +336 -0
- package/template/src/controllers/health.controller.ts +235 -0
- package/template/src/controllers/home/register.controller.ts +58 -0
- package/template/src/controllers/home/ytGoods.controller.ts +92 -0
- package/template/src/controllers/home/ytShop.controller.ts +135 -0
- package/template/src/controllers/home/ytUser.controller.ts +89 -0
- package/template/src/controllers/logManagement.controller.ts +396 -0
- package/template/src/controllers/public/emailSend.controller.ts +65 -0
- package/template/src/controllers/public/ytUserAuth.controller.ts +174 -0
- package/template/src/controllers/testData.controller.ts +253 -0
- package/template/src/dto/controller/example/NewAnnotationExampleController.dto.ts +73 -0
- package/template/src/dto/controller/home/emailSend.controller.dto.ts +40 -0
- package/template/src/dto/controller/home/register.controller.dto.ts +45 -0
- package/template/src/dto/controller/home/ytGoods.controller.dto.ts +55 -0
- package/template/src/dto/controller/home/ytShop.controller.dto.ts +69 -0
- package/template/src/dto/controller/home/ytUser.controller.dto.ts +44 -0
- package/template/src/dto/controller/public/ytUserAuth.controller.dto.ts +63 -0
- package/template/src/dto/goods.dto.ts +212 -0
- package/template/src/dto/service/ytService.dto.ts +13 -0
- package/template/src/dto/user.dto.ts +177 -0
- package/template/src/entity/base.entity.ts +13 -0
- package/template/src/entity/columnTypes.ts +13 -0
- package/template/src/entity/goodsImagesUnlockKey.entity.ts +33 -0
- package/template/src/entity/goodsUnlocker.entity.ts +34 -0
- package/template/src/entity/index.ts +15 -0
- package/template/src/entity/shop.entity.ts +52 -0
- package/template/src/entity/shopUser.entity.ts +41 -0
- package/template/src/entity/ytGoods.entity.ts +94 -0
- package/template/src/entity/ytUser.entity.ts +96 -0
- package/template/src/examples/InterceptorExampleRunner.ts +284 -0
- package/template/src/examples/ServiceInterceptorExample.ts +214 -0
- package/template/src/examples/SwaggerProcessorExample.ts +169 -0
- package/template/src/examples/TransactionManagerDemo.ts +377 -0
- package/template/src/examples/cacheExamples.ts +155 -0
- package/template/src/framework/decorator/controller.ts +311 -0
- package/template/src/framework/decorator/processor/AnnotationDecorators.ts +100 -0
- package/template/src/framework/decorator/processor/AnnotationProcessor.ts +156 -0
- package/template/src/framework/decorator/processor/AnnotationProcessorConfig.ts +45 -0
- package/template/src/framework/decorator/processor/AnnotationRegistry.ts +117 -0
- package/template/src/framework/decorator/processor/AnnotationSystemInitializer.ts +95 -0
- package/template/src/framework/decorator/processor/ProcessorManager.ts +76 -0
- package/template/src/framework/decorator/processor/processors/CustomProcessors.ts +126 -0
- package/template/src/framework/decorator/processor/processors/DefaultProcessors.ts +207 -0
- package/template/src/framework/decorator/refactored/DecoratorFactory.ts +99 -0
- package/template/src/framework/decorator/refactored/DecoratorMetadataManager.ts +125 -0
- package/template/src/framework/decorator/refactored/DecoratorValidator.ts +128 -0
- package/template/src/framework/decorator/refactored/TypeSafeDecorators.ts +139 -0
- package/template/src/framework/decorator/refactored/index.ts +98 -0
- package/template/src/framework/decorator/swagger.ts +150 -0
- package/template/src/framework/interceptors/AdvancedServiceCallInterceptor.ts +375 -0
- package/template/src/framework/interceptors/ServiceCallInterceptor.ts +348 -0
- package/template/src/framework/interceptors/index.ts +19 -0
- package/template/src/framework/plugins/registry.ts +63 -0
- package/template/src/framework/plugins/types.ts +15 -0
- package/template/src/framework/types/ServiceResult.ts +151 -0
- package/template/src/framework/types/index.ts +16 -0
- package/template/src/framework/utils/CacheManager.ts +430 -0
- package/template/src/framework/utils/CacheService.ts +248 -0
- package/template/src/framework/utils/DtoValidator.ts +164 -0
- package/template/src/framework/utils/MigrationHelper.ts +179 -0
- package/template/src/framework/utils/MigrationManager.ts +256 -0
- package/template/src/framework/utils/NewRouter.ts +207 -0
- package/template/src/framework/utils/TransactionManager.ts +172 -0
- package/template/src/framework/utils/bootstrap.ts +445 -0
- package/template/src/framework/utils/cache.ts +269 -0
- package/template/src/framework/utils/databaseConfig.ts +148 -0
- package/template/src/framework/utils/db.ts +39 -0
- package/template/src/framework/utils/dbMonitor.ts +106 -0
- package/template/src/framework/utils/dynamicSwagger.ts +410 -0
- package/template/src/framework/utils/function.ts +61 -0
- package/template/src/framework/utils/gracefulShutdown.ts +131 -0
- package/template/src/framework/utils/logger.ts +388 -0
- package/template/src/framework/utils/metrics.ts +182 -0
- package/template/src/framework/utils/router.ts +417 -0
- package/template/src/framework/utils/swagger.ts +184 -0
- package/template/src/framework/utils/testDb.ts +19 -0
- package/template/src/framework/utils/token.ts +23 -0
- package/template/src/framework/utils/transform.ts +17 -0
- package/template/src/libs/aokEmailSender.ts +42 -0
- package/template/src/libs/captcha.ts +37 -0
- package/template/src/libs/cos.ts +45 -0
- package/template/src/libs/mCache.ts +7 -0
- package/template/src/libs/serviceValidate.ts +3 -0
- package/template/src/libs/tecentSms.ts +51 -0
- package/template/src/middlewares/a.middleware.ts +6 -0
- package/template/src/middlewares/error.middleware.ts +14 -0
- package/template/src/middlewares/logging.middleware.ts +187 -0
- package/template/src/middlewares/static.middleware.ts +79 -0
- package/template/src/middlewares/swagger.middleware.ts +70 -0
- package/template/src/middlewares/token.middleware.ts +32 -0
- package/template/src/migrations/1700000000000-InitialDatabaseStructure.ts +172 -0
- package/template/src/migrations/index.ts +6 -0
- package/template/src/plugins/weboffice/core/context.ts +47 -0
- package/template/src/plugins/weboffice/core/errors.ts +51 -0
- package/template/src/plugins/weboffice/core/types.ts +63 -0
- package/template/src/plugins/weboffice/core/utils.ts +7 -0
- package/template/src/plugins/weboffice/entities/index.ts +3 -0
- package/template/src/plugins/weboffice/entities/webofficeFile.entity.ts +28 -0
- package/template/src/plugins/weboffice/entities/webofficeFileVersion.entity.ts +29 -0
- package/template/src/plugins/weboffice/http/routes.ts +179 -0
- package/template/src/plugins/weboffice/index.ts +23 -0
- package/template/src/plugins/weboffice/services/webofficeCallback.service.ts +274 -0
- package/template/src/repository/UserRepository.ts +122 -0
- package/template/src/repository/base/BaseRepository.ts +124 -0
- package/template/src/repository/interfaces/IBaseRepository.ts +67 -0
- package/template/src/routers/index.ts +49 -0
- package/template/src/service/base.service.ts +116 -0
- package/template/src/service/paramValidateTest.service.ts +139 -0
- package/template/src/service/ytGoods.service.ts +42 -0
- package/template/src/service/ytShop.service.ts +90 -0
- package/template/src/service/ytUser.service.ts +451 -0
- package/template/src/test/swaggerParameterTest.ts +90 -0
- package/template/src/utils/testDataInitializer.ts +296 -0
- package/template/static/output.json +15203 -0
- package/template/test/controllers/controllers.test.ts +173 -0
- package/template/test/controllers/example/ExampleController.test.ts +222 -0
- package/template/test/controllers/example/NewAnnotationExampleController.test.ts +200 -0
- package/template/test/framework/TransactionManagerDemo.test.ts +363 -0
- package/template/test/framework/annotation/AnnotationDecorators.test.ts +222 -0
- package/template/test/framework/annotation/AnnotationExecutor.test.ts +246 -0
- package/template/test/framework/annotation/AnnotationProcessor.test.ts +179 -0
- package/template/test/framework/annotation/CustomProcessors.test.ts +313 -0
- package/template/test/framework/annotation/DefaultProcessors.test.ts +371 -0
- package/template/test/framework/annotation/NewRouter.test.ts +272 -0
- package/template/test/framework/annotation/ProcessorManager.test.ts +248 -0
- package/template/test/framework/annotation/setup.ts +26 -0
- package/template/test/framework/cache.test.ts +101 -0
- package/template/test/framework/databaseConfig.test.ts +142 -0
- package/template/test/integration/integration.test.ts +153 -0
- package/template/test/plugins/weboffice/http.routes.int.test.ts +61 -0
- package/template/test/service/business.test.ts +87 -0
- package/template/test/service/paramValidateTest.service.test.ts +184 -0
- package/template/test/service/ytUser.service.test.ts +566 -0
- package/template/test/setup.ts +20 -0
- package/template/test/setupAfterEnv.ts +14 -0
- package/template/test/utils/testHelpers.ts +220 -0
- package/template/test_output.txt +0 -0
- package/template/tsconfig.build.json +17 -0
- package/template/tsconfig.json +31 -0
- package/template/webpack.config.js +71 -0
- package/template/yarn.lock +7354 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Repository, EntityTarget, FindManyOptions, FindOneOptions, UpdateResult, DeleteResult, ObjectLiteral } from 'typeorm';
|
|
2
|
+
import { IBaseRepository } from '@src/repository/interfaces/IBaseRepository';
|
|
3
|
+
import { logger } from '@src/framework/utils/logger';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 基础Repository实现
|
|
7
|
+
* 提供通用的数据访问操作
|
|
8
|
+
*/
|
|
9
|
+
export abstract class BaseRepository<T extends ObjectLiteral> implements IBaseRepository<T> {
|
|
10
|
+
protected repository: Repository<T>;
|
|
11
|
+
|
|
12
|
+
constructor(entity: EntityTarget<T>, repository: Repository<T>) {
|
|
13
|
+
this.repository = repository;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async findById(id: number): Promise<T | null> {
|
|
17
|
+
try {
|
|
18
|
+
return await this.repository.findOneBy({ id } as any);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
logger.error(`查找实体失败 (ID: ${id}):`, error as Error);
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async findAll(options?: FindManyOptions<T>): Promise<T[]> {
|
|
26
|
+
try {
|
|
27
|
+
return await this.repository.find(options);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
logger.error('查找所有实体失败:', error as Error);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async findOne(options: FindOneOptions<T>): Promise<T | null> {
|
|
35
|
+
try {
|
|
36
|
+
return await this.repository.findOne(options);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
logger.error('查找单个实体失败:', error as Error);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async findMany(options: FindManyOptions<T>): Promise<T[]> {
|
|
44
|
+
try {
|
|
45
|
+
return await this.repository.find(options);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
logger.error('查找多个实体失败:', error as Error);
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async save(entity: Partial<T>): Promise<T> {
|
|
53
|
+
try {
|
|
54
|
+
return await this.repository.save(entity as any);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
logger.error('保存实体失败:', error as Error);
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async saveMany(entities: Partial<T>[]): Promise<T[]> {
|
|
62
|
+
try {
|
|
63
|
+
return await this.repository.save(entities as any);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
logger.error('批量保存实体失败:', error as Error);
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async update(id: number, updateData: Partial<T>): Promise<UpdateResult> {
|
|
71
|
+
try {
|
|
72
|
+
return await this.repository.update(id, updateData as any);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
logger.error(`更新实体失败 (ID: ${id}):`, error as Error);
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async delete(id: number): Promise<DeleteResult> {
|
|
80
|
+
try {
|
|
81
|
+
return await this.repository.delete(id);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
logger.error(`删除实体失败 (ID: ${id}):`, error as Error);
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async softDelete(id: number): Promise<UpdateResult> {
|
|
89
|
+
try {
|
|
90
|
+
return await this.repository.softDelete(id);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
logger.error(`软删除实体失败 (ID: ${id}):`, error as Error);
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async exists(id: number): Promise<boolean> {
|
|
98
|
+
try {
|
|
99
|
+
const count = await this.repository.count({ where: { id } as any });
|
|
100
|
+
return count > 0;
|
|
101
|
+
} catch (error) {
|
|
102
|
+
logger.error(`检查实体存在性失败 (ID: ${id}):`, error as Error);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async count(options?: FindManyOptions<T>): Promise<number> {
|
|
108
|
+
try {
|
|
109
|
+
return await this.repository.count(options);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
logger.error('统计实体数量失败:', error as Error);
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async findAndCount(options: FindManyOptions<T>): Promise<[T[], number]> {
|
|
117
|
+
try {
|
|
118
|
+
return await this.repository.findAndCount(options);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
logger.error('分页查询失败:', error as Error);
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { EntityTarget, FindManyOptions, FindOneOptions, UpdateResult, DeleteResult } from 'typeorm';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 基础Repository接口
|
|
5
|
+
* 定义通用的数据访问操作
|
|
6
|
+
*/
|
|
7
|
+
export interface IBaseRepository<T> {
|
|
8
|
+
/**
|
|
9
|
+
* 根据ID查找实体
|
|
10
|
+
*/
|
|
11
|
+
findById(id: number): Promise<T | null>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 查找所有实体
|
|
15
|
+
*/
|
|
16
|
+
findAll(options?: FindManyOptions<T>): Promise<T[]>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 根据条件查找单个实体
|
|
20
|
+
*/
|
|
21
|
+
findOne(options: FindOneOptions<T>): Promise<T | null>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 根据条件查找多个实体
|
|
25
|
+
*/
|
|
26
|
+
findMany(options: FindManyOptions<T>): Promise<T[]>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 保存实体
|
|
30
|
+
*/
|
|
31
|
+
save(entity: Partial<T>): Promise<T>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 批量保存实体
|
|
35
|
+
*/
|
|
36
|
+
saveMany(entities: Partial<T>[]): Promise<T[]>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 更新实体
|
|
40
|
+
*/
|
|
41
|
+
update(id: number, updateData: Partial<T>): Promise<UpdateResult>;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 删除实体
|
|
45
|
+
*/
|
|
46
|
+
delete(id: number): Promise<DeleteResult>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 软删除实体
|
|
50
|
+
*/
|
|
51
|
+
softDelete(id: number): Promise<UpdateResult>;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 检查实体是否存在
|
|
55
|
+
*/
|
|
56
|
+
exists(id: number): Promise<boolean>;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 统计实体数量
|
|
60
|
+
*/
|
|
61
|
+
count(options?: FindManyOptions<T>): Promise<number>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 分页查询
|
|
65
|
+
*/
|
|
66
|
+
findAndCount(options: FindManyOptions<T>): Promise<[T[], number]>;
|
|
67
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// import { UserController } from "../controllers/user.controller";
|
|
2
|
+
import { logger } from "@src/framework/utils/logger";
|
|
3
|
+
import { bindRouter } from "@src/framework/utils/router";
|
|
4
|
+
import tokenMiddleware from "@src/middlewares/token.middleware";
|
|
5
|
+
import { EmailSendController } from "@src/controllers/public/emailSend.controller";
|
|
6
|
+
import { YtUserRegisterController } from "@src/controllers/home/register.controller";
|
|
7
|
+
import { YtUserAuthController } from "@src/controllers/public/ytUserAuth.controller";
|
|
8
|
+
import { YtUserController } from "@src/controllers/home/ytUser.controller";
|
|
9
|
+
import { YtShopController } from "@src/controllers/home/ytShop.controller";
|
|
10
|
+
import { YtGoodsController } from "@src/controllers/home/ytGoods.controller";
|
|
11
|
+
import { HealthController } from "@src/controllers/health.controller";
|
|
12
|
+
import { CacheManagementController } from "@src/controllers/cacheManagement.controller";
|
|
13
|
+
import { TestDataController } from "@src/controllers/testData.controller";
|
|
14
|
+
import { ExampleController } from "@src/controllers/example/ExampleController";
|
|
15
|
+
import { AnnotationDemoController } from "@src/controllers/demo/AnnotationDemoController";
|
|
16
|
+
import { EnterpriseExampleController } from "@src/controllers/example/EnterpriseExampleController";
|
|
17
|
+
import { LogManagementController } from "@src/controllers/logManagement.controller";
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
export default () => {
|
|
21
|
+
// bindRouter("/a", tokenMiddleware(), aMiddleware(), UserController);
|
|
22
|
+
bindRouter("/home/user/yt_user", tokenMiddleware(), YtUserController);
|
|
23
|
+
bindRouter("/home/shop/common", YtShopController);
|
|
24
|
+
bindRouter("/home/goods/common", tokenMiddleware(), YtGoodsController);
|
|
25
|
+
bindRouter("/home/register/yt_user", YtUserRegisterController);
|
|
26
|
+
bindRouter("/home/register/yt_user", YtUserRegisterController);
|
|
27
|
+
bindRouter("/public/auth/yt_user", YtUserAuthController);
|
|
28
|
+
bindRouter("/public/email", EmailSendController);
|
|
29
|
+
|
|
30
|
+
// 健康检查端点
|
|
31
|
+
bindRouter("/health", HealthController);
|
|
32
|
+
|
|
33
|
+
// 缓存管理端点
|
|
34
|
+
bindRouter("/admin/cache", CacheManagementController);
|
|
35
|
+
|
|
36
|
+
// 测试数据管理端点(仅在内存数据库模式下有效)
|
|
37
|
+
bindRouter("/test", TestDataController);
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
bindRouter("/example/", ExampleController);
|
|
41
|
+
bindRouter("/demo/", AnnotationDemoController);
|
|
42
|
+
bindRouter("/enterprise/", EnterpriseExampleController);
|
|
43
|
+
|
|
44
|
+
// 日志管理端点
|
|
45
|
+
bindRouter("/admin/logs", tokenMiddleware(), LogManagementController);
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
logger.info("路由绑定完成");
|
|
49
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Injectable } from "dp-ioc2";
|
|
2
|
+
import { getDataSource } from "@src/framework/utils/db"
|
|
3
|
+
import { ObjectLiteral, EntityTarget, Repository } from "typeorm"
|
|
4
|
+
import { CommonServiceResultCode, CommonServiceResult } from "@src/framework/types/ServiceResult"
|
|
5
|
+
|
|
6
|
+
@Injectable()
|
|
7
|
+
export class BaseService {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 获取数据仓库
|
|
11
|
+
* 延迟初始化,避免在数据库未初始化时出错
|
|
12
|
+
*/
|
|
13
|
+
getDataRepository<T extends ObjectLiteral>(entity: EntityTarget<T>): Repository<T> {
|
|
14
|
+
const dbDataSource = getDataSource();
|
|
15
|
+
if (!dbDataSource || !dbDataSource.isInitialized) {
|
|
16
|
+
throw new Error("数据库未初始化,请等待数据库初始化完成");
|
|
17
|
+
}
|
|
18
|
+
return dbDataSource.getRepository(entity);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 创建懒加载的 Repository Getter
|
|
23
|
+
* 通用方法,用于实例化自定义 Repository
|
|
24
|
+
*
|
|
25
|
+
* @template T Repository 类型
|
|
26
|
+
* @template R Repository 构造函数类型
|
|
27
|
+
* @param entity 实体类型
|
|
28
|
+
* @param RepositoryClass Repository 类
|
|
29
|
+
* @param cache Map 缓存对象
|
|
30
|
+
* @returns Getter 函数
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* export class YtUserService extends BaseService {
|
|
35
|
+
* private repositoryCache = new Map<string, any>();
|
|
36
|
+
*
|
|
37
|
+
* private get userRepository(): IUserRepository {
|
|
38
|
+
* return this.createLazyRepository(
|
|
39
|
+
* YtUserEntity,
|
|
40
|
+
* UserRepository,
|
|
41
|
+
* this.repositoryCache
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
protected createLazyRepository<T extends ObjectLiteral, R>(
|
|
48
|
+
entity: EntityTarget<T>,
|
|
49
|
+
RepositoryClass: new (repository: Repository<T>) => R,
|
|
50
|
+
cache: Map<string, R>
|
|
51
|
+
): R {
|
|
52
|
+
// 使用 RepositoryClass 名称作为缓存键
|
|
53
|
+
const cacheKey = RepositoryClass.name;
|
|
54
|
+
|
|
55
|
+
if (!cache.has(cacheKey)) {
|
|
56
|
+
const dataSource = getDataSource();
|
|
57
|
+
if (!dataSource || !dataSource.isInitialized) {
|
|
58
|
+
throw new Error("数据库未初始化,请等待数据库初始化完成");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const repository = dataSource.getRepository(entity);
|
|
62
|
+
const instance = new RepositoryClass(repository);
|
|
63
|
+
cache.set(cacheKey, instance);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return cache.get(cacheKey)!;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 获取数据库管理器
|
|
71
|
+
*/
|
|
72
|
+
getDbManager() {
|
|
73
|
+
const dbDataSource = getDataSource();
|
|
74
|
+
if (!dbDataSource || !dbDataSource.isInitialized) {
|
|
75
|
+
throw new Error("数据库未初始化,请等待数据库初始化完成");
|
|
76
|
+
}
|
|
77
|
+
return dbDataSource.manager;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async add<T>(data: T): Promise<T> {
|
|
81
|
+
return await this.getDbManager().save(data);
|
|
82
|
+
// return {
|
|
83
|
+
// code: CommonServiceResultCode.SUCCESS,
|
|
84
|
+
// data: result,
|
|
85
|
+
// }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async getById<T extends ObjectLiteral>(
|
|
89
|
+
entity: EntityTarget<T>,
|
|
90
|
+
id: number
|
|
91
|
+
): Promise<T | null> {
|
|
92
|
+
const repository: Repository<T> = this.getDataRepository(entity);
|
|
93
|
+
return await repository.findOneBy({ id } as any);
|
|
94
|
+
|
|
95
|
+
// if (!result) {
|
|
96
|
+
// return {
|
|
97
|
+
// code: CommonServiceResultCode.NOT_FOUND,
|
|
98
|
+
// data: null,
|
|
99
|
+
// message: "数据不存在"
|
|
100
|
+
// };
|
|
101
|
+
// }
|
|
102
|
+
|
|
103
|
+
// return {
|
|
104
|
+
// code: CommonServiceResultCode.SUCCESS,
|
|
105
|
+
// data: result
|
|
106
|
+
// };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 清理资源
|
|
111
|
+
* 在应用关闭时调用,防止内存泄漏
|
|
112
|
+
*/
|
|
113
|
+
cleanup(): void {
|
|
114
|
+
// BaseService 本身不需要清理,子类可以重写此方法
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 参数校验测试 Service
|
|
3
|
+
* 用于测试 dp-ioc2 的 @ParamValidate 装饰器功能
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Injectable, ParamValidate, IOCValidationError } from "dp-ioc2";
|
|
7
|
+
import { IsString, IsEmail, MinLength, IsNumber, Min, Max } from "class-validator";
|
|
8
|
+
import { BaseService } from "@src/service/base.service";
|
|
9
|
+
import { CommonServiceResult } from "@src/framework/types/ServiceResult";
|
|
10
|
+
import { logger } from "@src/framework/utils/logger";
|
|
11
|
+
import Joi from "joi";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 测试 DTO - 创建用户
|
|
15
|
+
*/
|
|
16
|
+
export class CreateTestUserDto {
|
|
17
|
+
@IsString({ message: '用户名必须是字符串' })
|
|
18
|
+
@MinLength(3, { message: '用户名长度不能少于3个字符' })
|
|
19
|
+
name!: string;
|
|
20
|
+
|
|
21
|
+
@IsEmail({}, { message: '邮箱格式不正确' })
|
|
22
|
+
email!: string;
|
|
23
|
+
|
|
24
|
+
@IsNumber({}, { message: '年龄必须是数字' })
|
|
25
|
+
@Min(18, { message: '年龄不能小于18岁' })
|
|
26
|
+
@Max(100, { message: '年龄不能大于100岁' })
|
|
27
|
+
age!: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 测试 DTO - 更新用户
|
|
32
|
+
*/
|
|
33
|
+
export class UpdateTestUserDto {
|
|
34
|
+
@IsString({ message: '用户名必须是字符串' })
|
|
35
|
+
@MinLength(3, { message: '用户名长度不能少于3个字符' })
|
|
36
|
+
name?: string;
|
|
37
|
+
|
|
38
|
+
@IsEmail({}, { message: '邮箱格式不正确' })
|
|
39
|
+
email?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 参数校验测试 Service
|
|
44
|
+
*/
|
|
45
|
+
@Injectable()
|
|
46
|
+
export class ParamValidateTestService extends BaseService {
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 测试1:对象参数校验(使用 class-validator)
|
|
50
|
+
*/
|
|
51
|
+
async createUser(@ParamValidate(CreateTestUserDto) dto: CreateTestUserDto): Promise<CommonServiceResult<{ id: number; name: string; email: string; age: number }>> {
|
|
52
|
+
try {
|
|
53
|
+
// 业务逻辑(校验已在方法调用前自动完成)
|
|
54
|
+
const user = {
|
|
55
|
+
id: Math.floor(Math.random() * 1000),
|
|
56
|
+
name: dto.name,
|
|
57
|
+
email: dto.email,
|
|
58
|
+
age: dto.age
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
logger.info(`创建用户成功: ${user.name}`);
|
|
62
|
+
return CommonServiceResult.success(user, "用户创建成功");
|
|
63
|
+
} catch (error) {
|
|
64
|
+
if (error instanceof IOCValidationError) {
|
|
65
|
+
return CommonServiceResult.validationError<{ id: number; name: string; email: string; age: number }>(
|
|
66
|
+
error.message || "参数校验失败",
|
|
67
|
+
null
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
logger.error("创建用户失败:", error as Error);
|
|
71
|
+
return CommonServiceResult.error("创建用户失败");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 测试2:基本类型参数校验(使用 Joi)
|
|
77
|
+
*/
|
|
78
|
+
async getUserById(@ParamValidate(undefined, Joi.number().integer().positive().required()) userId: number): Promise<CommonServiceResult<{ id: number; name: string }>> {
|
|
79
|
+
try {
|
|
80
|
+
// 业务逻辑
|
|
81
|
+
const user = {
|
|
82
|
+
id: userId,
|
|
83
|
+
name: `用户${userId}`
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return CommonServiceResult.success(user, "获取用户成功");
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (error instanceof IOCValidationError) {
|
|
89
|
+
return CommonServiceResult.validationError<{ id: number; name: string }>(
|
|
90
|
+
error.message || "参数校验失败",
|
|
91
|
+
null
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
logger.error("获取用户失败:", error as Error);
|
|
95
|
+
return CommonServiceResult.error("获取用户失败");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 测试3:混合参数校验(基本类型 + 对象)
|
|
101
|
+
*/
|
|
102
|
+
async updateUser(
|
|
103
|
+
@ParamValidate(undefined, Joi.number().integer().positive().required()) userId: number,
|
|
104
|
+
@ParamValidate(UpdateTestUserDto) dto: UpdateTestUserDto
|
|
105
|
+
): Promise<CommonServiceResult<{ id: number; name?: string; email?: string }>> {
|
|
106
|
+
try {
|
|
107
|
+
// 业务逻辑
|
|
108
|
+
const user = {
|
|
109
|
+
id: userId,
|
|
110
|
+
...dto
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return CommonServiceResult.success(user, "更新用户成功");
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (error instanceof IOCValidationError) {
|
|
116
|
+
return CommonServiceResult.validationError<{ id: number; name?: string; email?: string }>(
|
|
117
|
+
error.message || "参数校验失败",
|
|
118
|
+
null
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
logger.error("更新用户失败:", error as Error);
|
|
122
|
+
return CommonServiceResult.error("更新用户失败");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 测试4:无校验参数(用于对比)
|
|
128
|
+
*/
|
|
129
|
+
async getUserWithoutValidation(userId: number): Promise<CommonServiceResult<{ id: number; name: string }>> {
|
|
130
|
+
// 这个方法没有使用 @ParamValidate,用于对比测试
|
|
131
|
+
const user = {
|
|
132
|
+
id: userId,
|
|
133
|
+
name: `用户${userId}`
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
return CommonServiceResult.success(user, "获取用户成功");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BaseService } from "@src/service/base.service";
|
|
2
|
+
import { CommonServiceResult, CommonServiceResultCode } from "@src/framework/types/ServiceResult";
|
|
3
|
+
import { YtGoodsUnlockerEntity } from "@src/entity/goodsUnlocker.entity";
|
|
4
|
+
import { GoodsImagesUnlockKeyEntity } from "@src/entity/goodsImagesUnlockKey.entity";
|
|
5
|
+
|
|
6
|
+
export class YtGoodsService extends BaseService {
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async unlockGoodsImage(goodsId: number, userId: number, key: string): Promise<CommonServiceResult<boolean>> {
|
|
10
|
+
// 验证解锁key
|
|
11
|
+
const keyRepo = this.getDataRepository(GoodsImagesUnlockKeyEntity);
|
|
12
|
+
const unlockKey = await keyRepo.findOneBy({ key });
|
|
13
|
+
|
|
14
|
+
if (!unlockKey || unlockKey.isUse) {
|
|
15
|
+
return new CommonServiceResult(CommonServiceResultCode.FAIL, false, "无效的解锁key");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// 标记key为已使用
|
|
19
|
+
unlockKey.isUse = true;
|
|
20
|
+
await keyRepo.save(unlockKey);
|
|
21
|
+
|
|
22
|
+
// 创建解锁记录
|
|
23
|
+
const unlockRepo = this.getDataRepository(YtGoodsUnlockerEntity);
|
|
24
|
+
await unlockRepo.save({
|
|
25
|
+
goodsId,
|
|
26
|
+
ytUserId: userId
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return new CommonServiceResult(CommonServiceResultCode.SUCCESS, true);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 根据ID获取商品(兼容旧接口)
|
|
34
|
+
*/
|
|
35
|
+
async getById(entityClass: any, id: number): Promise<any> {
|
|
36
|
+
try {
|
|
37
|
+
return await this.getDataRepository(entityClass).findOne({ where: { id } });
|
|
38
|
+
} catch (error) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { YtGoodsEntity, YtGoodsStatusEnum } from "@src/entity/ytGoods.entity";
|
|
2
|
+
import { BaseService } from "@src/service/base.service";
|
|
3
|
+
import { CommonServiceResult, CommonServiceResultCode } from "@src/framework/types/ServiceResult";
|
|
4
|
+
import { YtUserEntity } from "@src/entity/ytUser.entity";
|
|
5
|
+
import { ShopAndUserEntity } from "@src/entity/shopUser.entity";
|
|
6
|
+
|
|
7
|
+
export class YtShopService extends BaseService {
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 获取店铺的商品列表
|
|
12
|
+
* @param shopId
|
|
13
|
+
* @param page
|
|
14
|
+
* @param pageSize
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
async getGoodsListByShopId(
|
|
18
|
+
shopId: number,
|
|
19
|
+
page: number,
|
|
20
|
+
pageSize: number
|
|
21
|
+
): Promise<CommonServiceResult<[YtGoodsEntity[], number]>> {
|
|
22
|
+
const ds = this.getDataRepository(YtGoodsEntity);
|
|
23
|
+
try {
|
|
24
|
+
const result = await ds.findAndCount({
|
|
25
|
+
where: { shopId, status: YtGoodsStatusEnum.NORMAL },
|
|
26
|
+
skip: (page - 1) * pageSize,
|
|
27
|
+
take: pageSize,
|
|
28
|
+
order: { id: "DESC" }
|
|
29
|
+
});
|
|
30
|
+
return new CommonServiceResult(CommonServiceResultCode.SUCCESS, result);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return new CommonServiceResult(CommonServiceResultCode.ERROR, [[], 0], "查询商品列表失败");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 读取店铺的用户基本信息
|
|
39
|
+
* @param shopId
|
|
40
|
+
*/
|
|
41
|
+
async getShopUserInfo(shopId: number): Promise<CommonServiceResult<YtUserEntity | null>> {
|
|
42
|
+
|
|
43
|
+
const relation = await this.getDataRepository(ShopAndUserEntity).findOne({
|
|
44
|
+
where: {
|
|
45
|
+
shopId,
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!relation) {
|
|
50
|
+
return new CommonServiceResult(CommonServiceResultCode.FAIL, null, "店铺未绑定用户")
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
const user = await this.getDataRepository(YtUserEntity).findOne({
|
|
56
|
+
where: {
|
|
57
|
+
id: relation.userId,
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
if (!user) {
|
|
61
|
+
return new CommonServiceResult(CommonServiceResultCode.FAIL, null, "用户不存在");
|
|
62
|
+
}
|
|
63
|
+
return new CommonServiceResult(CommonServiceResultCode.SUCCESS, user,);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 检测用户是否有店铺 如果有,则返回shop id
|
|
69
|
+
* @param userId
|
|
70
|
+
*/
|
|
71
|
+
async checkHasShop(userId: number): Promise<CommonServiceResult<number | null>> {
|
|
72
|
+
const result = await this.getDataRepository(ShopAndUserEntity).findOne({
|
|
73
|
+
where: {
|
|
74
|
+
userId,
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
return new CommonServiceResult(CommonServiceResultCode.SUCCESS, result?.shopId || null);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 根据ID获取店铺(兼容旧接口)
|
|
82
|
+
*/
|
|
83
|
+
async getById(entityClass: any, id: number): Promise<any> {
|
|
84
|
+
try {
|
|
85
|
+
return await this.getDataRepository(entityClass).findOne({ where: { id } });
|
|
86
|
+
} catch (error) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|