From 2d54538d8193475b07fcdbd961ca7feb0be3517b Mon Sep 17 00:00:00 2001 From: imfozilbek Date: Sun, 23 Nov 2025 21:43:38 +0500 Subject: [PATCH] feat(core): add application layer components Add application layer: - UseCase base class for use cases - ResponseDto for standardized responses - Mapper for domain-DTO conversion --- .../core/src/application/dtos/ResponseDto.ts | 31 +++++++++++++++++++ packages/core/src/application/index.ts | 3 ++ .../core/src/application/interfaces/.gitkeep | 0 .../core/src/application/mappers/Mapper.ts | 20 ++++++++++++ .../core/src/application/use-cases/UseCase.ts | 13 ++++++++ 5 files changed, 67 insertions(+) create mode 100644 packages/core/src/application/dtos/ResponseDto.ts create mode 100644 packages/core/src/application/index.ts create mode 100644 packages/core/src/application/interfaces/.gitkeep create mode 100644 packages/core/src/application/mappers/Mapper.ts create mode 100644 packages/core/src/application/use-cases/UseCase.ts diff --git a/packages/core/src/application/dtos/ResponseDto.ts b/packages/core/src/application/dtos/ResponseDto.ts new file mode 100644 index 0000000..1a1e587 --- /dev/null +++ b/packages/core/src/application/dtos/ResponseDto.ts @@ -0,0 +1,31 @@ +/** + * Standard response wrapper for use cases + */ +export interface IResponseDto { + success: boolean; + data?: T; + error?: string; + timestamp: Date; +} + +export class ResponseDto implements IResponseDto { + public readonly success: boolean; + public readonly data?: T; + public readonly error?: string; + public readonly timestamp: Date; + + private constructor(success: boolean, data?: T, error?: string) { + this.success = success; + this.data = data; + this.error = error; + this.timestamp = new Date(); + } + + public static ok(data: T): ResponseDto { + return new ResponseDto(true, data); + } + + public static fail(error: string): ResponseDto { + return new ResponseDto(false, undefined, error); + } +} \ No newline at end of file diff --git a/packages/core/src/application/index.ts b/packages/core/src/application/index.ts new file mode 100644 index 0000000..ea26bfd --- /dev/null +++ b/packages/core/src/application/index.ts @@ -0,0 +1,3 @@ +export * from './use-cases/UseCase'; +export * from './dtos/ResponseDto'; +export * from './mappers/Mapper'; diff --git a/packages/core/src/application/interfaces/.gitkeep b/packages/core/src/application/interfaces/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/packages/core/src/application/mappers/Mapper.ts b/packages/core/src/application/mappers/Mapper.ts new file mode 100644 index 0000000..40644a9 --- /dev/null +++ b/packages/core/src/application/mappers/Mapper.ts @@ -0,0 +1,20 @@ +/** + * Generic mapper interface for converting between domain entities and DTOs + */ +export interface IMapper { + toDto(domain: TDomain): TDto; + toDomain(dto: TDto): TDomain; +} + +export abstract class Mapper implements IMapper { + public abstract toDto(domain: TDomain): TDto; + public abstract toDomain(dto: TDto): TDomain; + + public toDtoList(domains: TDomain[]): TDto[] { + return domains.map((domain) => this.toDto(domain)); + } + + public toDomainList(dtos: TDto[]): TDomain[] { + return dtos.map((dto) => this.toDomain(dto)); + } +} diff --git a/packages/core/src/application/use-cases/UseCase.ts b/packages/core/src/application/use-cases/UseCase.ts new file mode 100644 index 0000000..6301e69 --- /dev/null +++ b/packages/core/src/application/use-cases/UseCase.ts @@ -0,0 +1,13 @@ +/** + * Base interface for all use cases + */ +export interface IUseCase { + execute(request: TRequest): Promise; +} + +/** + * Abstract base class for use cases + */ +export abstract class UseCase implements IUseCase { + public abstract execute(request: TRequest): Promise; +} \ No newline at end of file