refactor
This commit is contained in:
26
apps/api/src/domain/race/RaceController.ts
Normal file
26
apps/api/src/domain/race/RaceController.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Controller, Get, Post, Body, HttpCode, HttpStatus } from '@nestjs/common';
|
||||
import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger';
|
||||
import { RaceService } from './RaceService';
|
||||
import { AllRacesPageViewModel, RaceStatsDto } from './dto/RaceDto';
|
||||
|
||||
@ApiTags('races')
|
||||
@Controller('races')
|
||||
export class RaceController {
|
||||
constructor(private readonly raceService: RaceService) {}
|
||||
|
||||
@Get('all')
|
||||
@ApiOperation({ summary: 'Get all races' })
|
||||
@ApiResponse({ status: 200, description: 'List of all races', type: AllRacesPageViewModel })
|
||||
async getAllRaces(): Promise<AllRacesPageViewModel> {
|
||||
return this.raceService.getAllRaces();
|
||||
}
|
||||
|
||||
@Get('total-races')
|
||||
@ApiOperation({ summary: 'Get the total number of races' })
|
||||
@ApiResponse({ status: 200, description: 'Total number of races', type: RaceStatsDto })
|
||||
async getTotalRaces(): Promise<RaceStatsDto> {
|
||||
return this.raceService.getTotalRaces();
|
||||
}
|
||||
|
||||
// Add other Race endpoints here based on other presenters
|
||||
}
|
||||
11
apps/api/src/domain/race/RaceModule.ts
Normal file
11
apps/api/src/domain/race/RaceModule.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { RaceService } from './RaceService';
|
||||
import { RaceController } from './RaceController';
|
||||
import { RaceProviders } from './RaceProviders';
|
||||
|
||||
@Module({
|
||||
controllers: [RaceController],
|
||||
providers: RaceProviders,
|
||||
exports: [RaceService],
|
||||
})
|
||||
export class RaceModule {}
|
||||
52
apps/api/src/domain/race/RaceProviders.ts
Normal file
52
apps/api/src/domain/race/RaceProviders.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Provider } from '@nestjs/common';
|
||||
import { RaceService } from './RaceService';
|
||||
|
||||
// Import core interfaces
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
import { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepository';
|
||||
import { ILeagueRepository } from '@core/racing/domain/repositories/ILeagueRepository';
|
||||
|
||||
// Import concrete in-memory implementations
|
||||
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
|
||||
import { InMemoryLeagueRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
|
||||
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
|
||||
|
||||
// Import use cases
|
||||
import { GetAllRacesUseCase } from '@core/racing/application/use-cases/GetAllRacesUseCase';
|
||||
import { GetTotalRacesUseCase } from '@core/racing/application/use-cases/GetTotalRacesUseCase';
|
||||
import { ImportRaceResultsApiUseCase } from '@core/racing/application/use-cases/ImportRaceResultsApiUseCase';
|
||||
|
||||
// Define injection tokens
|
||||
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
|
||||
export const LEAGUE_REPOSITORY_TOKEN = 'ILeagueRepository';
|
||||
export const LOGGER_TOKEN = 'Logger';
|
||||
|
||||
export const RaceProviders: Provider[] = [
|
||||
RaceService,
|
||||
{
|
||||
provide: RACE_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryRaceRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: LEAGUE_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryLeagueRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: LOGGER_TOKEN,
|
||||
useClass: ConsoleLogger,
|
||||
},
|
||||
// Use cases
|
||||
{
|
||||
provide: GetAllRacesUseCase,
|
||||
useFactory: (raceRepo: IRaceRepository, leagueRepo: ILeagueRepository) => new GetAllRacesUseCase(raceRepo, leagueRepo),
|
||||
inject: [RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetTotalRacesUseCase,
|
||||
useFactory: (raceRepo: IRaceRepository) => new GetTotalRacesUseCase(raceRepo),
|
||||
inject: [RACE_REPOSITORY_TOKEN],
|
||||
},
|
||||
ImportRaceResultsApiUseCase,
|
||||
];
|
||||
50
apps/api/src/domain/race/RaceService.ts
Normal file
50
apps/api/src/domain/race/RaceService.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import { AllRacesPageViewModel, RaceStatsDto, ImportRaceResultsInput, ImportRaceResultsSummaryViewModel } from './dto/RaceDto';
|
||||
|
||||
// Core imports
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
|
||||
// Use cases
|
||||
import { GetAllRacesUseCase } from '@core/racing/application/use-cases/GetAllRacesUseCase';
|
||||
import { GetTotalRacesUseCase } from '@core/racing/application/use-cases/GetTotalRacesUseCase';
|
||||
import { ImportRaceResultsApiUseCase } from '@core/racing/application/use-cases/ImportRaceResultsApiUseCase';
|
||||
|
||||
// Presenters
|
||||
import { GetAllRacesPresenter } from './presenters/GetAllRacesPresenter';
|
||||
import { GetTotalRacesPresenter } from './presenters/GetTotalRacesPresenter';
|
||||
import { ImportRaceResultsApiPresenter } from './presenters/ImportRaceResultsApiPresenter';
|
||||
|
||||
// Tokens
|
||||
import { LOGGER_TOKEN } from './RaceProviders';
|
||||
|
||||
@Injectable()
|
||||
export class RaceService {
|
||||
constructor(
|
||||
private readonly getAllRacesUseCase: GetAllRacesUseCase,
|
||||
private readonly getTotalRacesUseCase: GetTotalRacesUseCase,
|
||||
private readonly importRaceResultsApiUseCase: ImportRaceResultsApiUseCase,
|
||||
@Inject(LOGGER_TOKEN) private readonly logger: Logger,
|
||||
) {}
|
||||
|
||||
async getAllRaces(): Promise<AllRacesPageViewModel> {
|
||||
this.logger.debug('[RaceService] Fetching all races.');
|
||||
|
||||
const presenter = new GetAllRacesPresenter();
|
||||
await this.getAllRacesUseCase.execute({}, presenter);
|
||||
return presenter.getViewModel()!;
|
||||
}
|
||||
|
||||
async getTotalRaces(): Promise<RaceStatsDto> {
|
||||
this.logger.debug('[RaceService] Fetching total races count.');
|
||||
const presenter = new GetTotalRacesPresenter();
|
||||
await this.getTotalRacesUseCase.execute({}, presenter);
|
||||
return presenter.getViewModel()!;
|
||||
}
|
||||
|
||||
async importRaceResults(input: ImportRaceResultsInput): Promise<ImportRaceResultsSummaryViewModel> {
|
||||
this.logger.debug('Importing race results:', input);
|
||||
const presenter = new ImportRaceResultsApiPresenter();
|
||||
await this.importRaceResultsApiUseCase.execute({ raceId: input.raceId, resultsFileContent: input.resultsFileContent }, presenter);
|
||||
return presenter.getViewModel()!;
|
||||
}
|
||||
}
|
||||
78
apps/api/src/domain/race/dto/RaceDto.ts
Normal file
78
apps/api/src/domain/race/dto/RaceDto.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty, IsBoolean, IsNumber } from 'class-validator';
|
||||
|
||||
export class RaceViewModel {
|
||||
@ApiProperty()
|
||||
id: string; // Assuming a race has an ID
|
||||
|
||||
@ApiProperty()
|
||||
name: string; // Assuming a race has a name
|
||||
|
||||
@ApiProperty()
|
||||
date: string; // Assuming a race has a date
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
leagueName?: string; // Assuming a race might belong to a league
|
||||
|
||||
// Add more race-related properties as needed based on the DTO from the application layer
|
||||
}
|
||||
|
||||
export class AllRacesPageViewModel {
|
||||
@ApiProperty({ type: [RaceViewModel] })
|
||||
races: RaceViewModel[];
|
||||
|
||||
@ApiProperty()
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export class RaceStatsDto {
|
||||
@ApiProperty()
|
||||
totalRaces: number;
|
||||
}
|
||||
|
||||
export class ImportRaceResultsInput {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
raceId: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
resultsFileContent: string;
|
||||
}
|
||||
|
||||
export class ImportRaceResultsSummaryViewModel {
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
success: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
raceId: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
driversProcessed: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
resultsRecorded: number;
|
||||
|
||||
@ApiProperty({ type: [String], required: false })
|
||||
errors?: string[];
|
||||
}
|
||||
|
||||
export class RaceDto {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
date: string;
|
||||
}
|
||||
17
apps/api/src/domain/race/presenters/GetAllRacesPresenter.ts
Normal file
17
apps/api/src/domain/race/presenters/GetAllRacesPresenter.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { IGetAllRacesPresenter, GetAllRacesResultDTO, AllRacesPageViewModel } from '@core/racing/application/presenters/IGetAllRacesPresenter';
|
||||
|
||||
export class GetAllRacesPresenter implements IGetAllRacesPresenter {
|
||||
private result: AllRacesPageViewModel | null = null;
|
||||
|
||||
reset() {
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
present(dto: GetAllRacesResultDTO) {
|
||||
this.result = dto;
|
||||
}
|
||||
|
||||
getViewModel(): AllRacesPageViewModel | null {
|
||||
return this.result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { IGetTotalRacesPresenter, GetTotalRacesResultDTO } from '@core/racing/application/presenters/IGetTotalRacesPresenter';
|
||||
import { RaceStatsDto } from '../dto/RaceDto';
|
||||
|
||||
export class GetTotalRacesPresenter implements IGetTotalRacesPresenter {
|
||||
private result: RaceStatsDto | null = null;
|
||||
|
||||
reset() {
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
present(dto: GetTotalRacesResultDTO) {
|
||||
this.result = {
|
||||
totalRaces: dto.totalRaces,
|
||||
};
|
||||
}
|
||||
|
||||
getViewModel(): RaceStatsDto | null {
|
||||
return this.result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { IImportRaceResultsApiPresenter, ImportRaceResultsApiResultDTO, ImportRaceResultsSummaryViewModel } from '@core/racing/application/presenters/IImportRaceResultsApiPresenter';
|
||||
|
||||
export class ImportRaceResultsApiPresenter implements IImportRaceResultsApiPresenter {
|
||||
private result: ImportRaceResultsSummaryViewModel | null = null;
|
||||
|
||||
reset() {
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
present(dto: ImportRaceResultsApiResultDTO) {
|
||||
this.result = dto;
|
||||
}
|
||||
|
||||
getViewModel(): ImportRaceResultsSummaryViewModel | null {
|
||||
return this.result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user