code quality
Some checks failed
CI / lint-typecheck (pull_request) Failing after 12s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped

This commit is contained in:
2026-01-26 12:52:24 +01:00
parent f877f821ef
commit cfc30c79a8
62 changed files with 227 additions and 173 deletions

View File

@@ -1,7 +1,7 @@
import { MediaReference } from '@core/domain/media/MediaReference';
import { Driver } from '@core/racing/domain/entities/Driver';
import { DriverRepository } from '@core/racing/domain/repositories/DriverRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemoryDriverRepository implements DriverRepository {
private drivers: Map<string, Driver> = new Map();

View File

@@ -1,6 +1,6 @@
import { Game } from '@core/racing/domain/entities/Game';
import { GameRepository } from '@core/racing/domain/repositories/GameRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemoryGameRepository implements GameRepository {
private games: Map<string, Game> = new Map();

View File

@@ -1,7 +1,7 @@
import { JoinRequest } from '@core/racing/domain/entities/JoinRequest';
import { LeagueMembership } from '@core/racing/domain/entities/LeagueMembership';
import { LeagueMembershipRepository } from '@core/racing/domain/repositories/LeagueMembershipRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemoryLeagueMembershipRepository implements LeagueMembershipRepository {
private memberships: Map<string, LeagueMembership> = new Map(); // Key: `${leagueId}:${driverId}`

View File

@@ -1,7 +1,7 @@
import { MediaReference } from '@core/domain/media/MediaReference';
import { League } from '@core/racing/domain/entities/League';
import { LeagueRepository } from '@core/racing/domain/repositories/LeagueRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemoryLeagueRepository implements LeagueRepository {
private leagues: Map<string, League> = new Map();

View File

@@ -1,6 +1,6 @@
import { LeagueScoringConfig } from '@core/racing/domain/entities/LeagueScoringConfig';
import { LeagueScoringConfigRepository } from '@core/racing/domain/repositories/LeagueScoringConfigRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemoryLeagueScoringConfigRepository implements LeagueScoringConfigRepository {
private configs: Map<string, LeagueScoringConfig> = new Map(); // Key: seasonId

View File

@@ -1,5 +1,5 @@
import { LeagueStandingsRepository, RawStanding } from '@core/league/application/ports/LeagueStandingsRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemoryLeagueStandingsRepository implements LeagueStandingsRepository {
private standings: Map<string, RawStanding[]> = new Map(); // Key: leagueId

View File

@@ -1,6 +1,6 @@
import { Protest } from '@core/racing/domain/entities/Protest';
import { ProtestRepository } from '@core/racing/domain/repositories/ProtestRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemoryProtestRepository implements ProtestRepository {
private protests: Map<string, Protest> = new Map();

View File

@@ -1,6 +1,6 @@
import { RaceRegistration } from '@core/racing/domain/entities/RaceRegistration';
import { RaceRegistrationRepository } from '@core/racing/domain/repositories/RaceRegistrationRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemoryRaceRegistrationRepository implements RaceRegistrationRepository {
private registrations: Map<string, RaceRegistration> = new Map(); // Key: `${raceId}:${driverId}`

View File

@@ -1,6 +1,6 @@
import { Race, type RaceStatusValue } from '@core/racing/domain/entities/Race';
import { RaceRepository } from '@core/racing/domain/repositories/RaceRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemoryRaceRepository implements RaceRepository {
private races: Map<string, Race> = new Map();

View File

@@ -1,6 +1,6 @@
import { Season } from '@core/racing/domain/entities/season/Season';
import { SeasonRepository } from '@core/racing/domain/repositories/SeasonRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemorySeasonRepository implements SeasonRepository {
private seasons: Map<string, Season> = new Map(); // Key: seasonId

View File

@@ -1,6 +1,6 @@
import { Sponsor } from '@core/racing/domain/entities/sponsor/Sponsor';
import { SponsorRepository } from '@core/racing/domain/repositories/SponsorRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemorySponsorRepository implements SponsorRepository {
private sponsors: Map<string, Sponsor> = new Map();

View File

@@ -1,6 +1,6 @@
import { SponsorableEntityType, SponsorshipRequest, SponsorshipRequestStatus } from '@core/racing/domain/entities/SponsorshipRequest';
import { SponsorshipRequestRepository } from '@core/racing/domain/repositories/SponsorshipRequestRepository';
import { Logger } from '@core/shared/domain';
import { Logger } from '@core/shared/domain/Logger';
export class InMemorySponsorshipRequestRepository implements SponsorshipRequestRepository {
private requests: Map<string, SponsorshipRequest> = new Map();

View File

@@ -22,4 +22,7 @@ export class ResultOrmEntity {
@Column({ type: 'int' })
startPosition!: number;
@Column({ type: 'int', default: 0 })
points!: number;
}

View File

@@ -29,11 +29,11 @@ describe('LeagueOrmMapper', () => {
entity.youtubeUrl = null;
entity.websiteUrl = null;
if (typeof (League as any).rehydrate !== 'function') {
if (typeof (League as unknown as { rehydrate: unknown }).rehydrate !== 'function') {
throw new Error('rehydrate-missing');
}
const rehydrateSpy = vi.spyOn(League as any, 'rehydrate');
const rehydrateSpy = vi.spyOn(League as unknown as { rehydrate: () => void }, 'rehydrate');
const createSpy = vi.spyOn(League, 'create').mockImplementation(() => {
throw new Error('create-called');
});

View File

@@ -24,11 +24,11 @@ describe('RaceOrmMapper', () => {
entity.registeredCount = null;
entity.maxParticipants = null;
if (typeof (Race as any).rehydrate !== 'function') {
if (typeof (Race as unknown as { rehydrate: unknown }).rehydrate !== 'function') {
throw new Error('rehydrate-missing');
}
const rehydrateSpy = vi.spyOn(Race as any, 'rehydrate');
const rehydrateSpy = vi.spyOn(Race as unknown as { rehydrate: () => void }, 'rehydrate');
const createSpy = vi.spyOn(Race, 'create').mockImplementation(() => {
throw new Error('create-called');
});

View File

@@ -15,6 +15,7 @@ export class ResultOrmMapper {
entity.fastestLap = domain.fastestLap.toNumber();
entity.incidents = domain.incidents.toNumber();
entity.startPosition = domain.startPosition.toNumber();
entity.points = domain.points;
return entity;
}
@@ -29,6 +30,7 @@ export class ResultOrmMapper {
assertInteger(entityName, 'fastestLap', entity.fastestLap);
assertInteger(entityName, 'incidents', entity.incidents);
assertInteger(entityName, 'startPosition', entity.startPosition);
assertInteger(entityName, 'points', entity.points);
} catch (error) {
if (error instanceof TypeOrmPersistenceSchemaError) {
throw new InvalidResultSchemaError({
@@ -49,6 +51,7 @@ export class ResultOrmMapper {
fastestLap: entity.fastestLap,
incidents: entity.incidents,
startPosition: entity.startPosition,
points: entity.points,
});
} catch (error) {
const message = error instanceof Error ? error.message : 'Invalid persisted Result';

View File

@@ -28,11 +28,11 @@ describe('SeasonOrmMapper', () => {
entity.maxDrivers = null;
entity.participantCount = 3;
if (typeof (Season as any).rehydrate !== 'function') {
if (typeof (Season as unknown as { rehydrate: unknown }).rehydrate !== 'function') {
throw new Error('rehydrate-missing');
}
const rehydrateSpy = vi.spyOn(Season as any, 'rehydrate');
const rehydrateSpy = vi.spyOn(Season as unknown as { rehydrate: () => void }, 'rehydrate');
const createSpy = vi.spyOn(Season, 'create').mockImplementation(() => {
throw new Error('create-called');
});

View File

@@ -93,7 +93,7 @@ describe('TeamRatingEventOrmMapper', () => {
it('should handle domain entity without weight', () => {
const props = { ...validDomainProps };
delete (props as any).weight;
delete (props as unknown as { weight: unknown }).weight;
const domain = TeamRatingEvent.create(props);
const entity = TeamRatingEventOrmMapper.toOrmEntity(domain);

View File

@@ -1,4 +1,5 @@
import { describe, expect, it, vi } from 'vitest';
import type { Repository } from 'typeorm';
import {
TypeOrmGameRepository,
@@ -6,6 +7,8 @@ import {
TypeOrmSponsorRepository,
TypeOrmTransactionRepository,
} from './CommerceTypeOrmRepositories';
import type { GameOrmEntity, LeagueWalletOrmEntity, SponsorOrmEntity, TransactionOrmEntity } from '../entities/CommerceOrmEntities';
import type { GameOrmMapper, LeagueWalletOrmMapper, SponsorOrmMapper, TransactionOrmMapper } from '../mappers/CommerceOrmMappers';
describe('TypeOrmGameRepository', () => {
it('findAll maps entities to domain using injected mapper (DB-free)', async () => {
@@ -17,10 +20,10 @@ describe('TypeOrmGameRepository', () => {
};
const mapper = {
toDomain: vi.fn().mockImplementation((e: any) => ({ id: `domain-${e.id}` })),
toDomain: vi.fn().mockImplementation((e: unknown) => ({ id: `domain-${(e as { id: string }).id}` })),
};
const gameRepo = new TypeOrmGameRepository(repo as any, mapper as any);
const gameRepo = new TypeOrmGameRepository(repo as unknown as Repository<GameOrmEntity>, mapper as unknown as GameOrmMapper);
const games = await gameRepo.findAll();
@@ -44,7 +47,7 @@ describe('TypeOrmLeagueWalletRepository', () => {
toOrmEntity: vi.fn(),
};
const walletRepo = new TypeOrmLeagueWalletRepository(repo as any, mapper as any);
const walletRepo = new TypeOrmLeagueWalletRepository(repo as unknown as Repository<LeagueWalletOrmEntity>, mapper as unknown as LeagueWalletOrmMapper);
await expect(walletRepo.exists('w1')).resolves.toBe(true);
expect(repo.count).toHaveBeenCalledWith({ where: { id: 'w1' } });

View File

@@ -1,6 +1,10 @@
import { describe, expect, it, vi } from 'vitest';
import type { Repository } from 'typeorm';
import { TypeOrmPenaltyRepository, TypeOrmProtestRepository } from './StewardingTypeOrmRepositories';
import type { PenaltyOrmEntity, ProtestOrmEntity } from '../entities/MissingRacingOrmEntities';
import type { PenaltyOrmMapper, ProtestOrmMapper } from '../mappers/StewardingOrmMappers';
import type { Penalty } from '@core/racing/domain/entities/Penalty';
describe('TypeOrmPenaltyRepository', () => {
it('findById returns mapped domain when found (DB-free)', async () => {
@@ -19,7 +23,7 @@ describe('TypeOrmPenaltyRepository', () => {
toOrmEntity: vi.fn(),
};
const penaltyRepo = new TypeOrmPenaltyRepository(repo as any, mapper as any);
const penaltyRepo = new TypeOrmPenaltyRepository(repo as unknown as Repository<PenaltyOrmEntity>, mapper as unknown as PenaltyOrmMapper);
const result = await penaltyRepo.findById('p1');
@@ -37,9 +41,9 @@ describe('TypeOrmPenaltyRepository', () => {
toOrmEntity: vi.fn().mockReturnValue({ id: 'p1-orm' }),
};
const penaltyRepo = new TypeOrmPenaltyRepository(repo as any, mapper as any);
const penaltyRepo = new TypeOrmPenaltyRepository(repo as unknown as Repository<PenaltyOrmEntity>, mapper as unknown as PenaltyOrmMapper);
await penaltyRepo.create({ id: 'p1' } as any);
await penaltyRepo.create({ id: 'p1' } as unknown as Penalty);
expect(mapper.toOrmEntity).toHaveBeenCalled();
expect(repo.save).toHaveBeenCalledWith({ id: 'p1-orm' });

View File

@@ -1,6 +1,11 @@
import { describe, expect, it, vi } from 'vitest';
import type { Repository } from 'typeorm';
import { TypeOrmTeamMembershipRepository, TypeOrmTeamRepository } from './TeamTypeOrmRepositories';
import type { TeamOrmEntity, TeamMembershipOrmEntity, TeamJoinRequestOrmEntity } from '../entities/TeamOrmEntities';
import type { TeamOrmMapper, TeamMembershipOrmMapper } from '../mappers/TeamOrmMappers';
import type { Team } from '@core/racing/domain/entities/Team';
import type { TeamMembership } from '@core/racing/domain/entities/TeamMembership';
describe('TypeOrmTeamRepository', () => {
it('uses injected repo + mapper (DB-free)', async () => {
@@ -20,7 +25,7 @@ describe('TypeOrmTeamRepository', () => {
toOrmEntity: vi.fn().mockReturnValue({ id: 'team-1-orm' }),
};
const teamRepo = new TypeOrmTeamRepository(repo as any, mapper as any);
const teamRepo = new TypeOrmTeamRepository(repo as unknown as Repository<TeamOrmEntity>, mapper as unknown as TeamOrmMapper);
const team = await teamRepo.findById('550e8400-e29b-41d4-a716-446655440000');
@@ -38,11 +43,11 @@ describe('TypeOrmTeamRepository', () => {
toOrmEntity: vi.fn().mockReturnValue({ id: 'team-1-orm' }),
};
const teamRepo = new TypeOrmTeamRepository(repo as any, mapper as any);
const teamRepo = new TypeOrmTeamRepository(repo as unknown as Repository<TeamOrmEntity>, mapper as unknown as TeamOrmMapper);
const domainTeam = { id: 'team-1' };
const domainTeam = { id: 'team-1' } as unknown as Team;
await expect(teamRepo.create(domainTeam as any)).resolves.toBe(domainTeam);
await expect(teamRepo.create(domainTeam)).resolves.toBe(domainTeam);
expect(mapper.toOrmEntity).toHaveBeenCalledWith(domainTeam);
expect(repo.save).toHaveBeenCalledWith({ id: 'team-1-orm' });

View File

@@ -47,10 +47,10 @@ describe('TypeOrmDriverRepository', () => {
avatarRef: MediaReference.createUploaded('media-abc-123'),
});
const savedEntities: any[] = [];
const savedEntities: unknown[] = [];
const repo = {
save: async (entity: any) => {
save: async (entity: unknown) => {
savedEntities.push(entity);
return entity;
},
@@ -68,7 +68,7 @@ describe('TypeOrmDriverRepository', () => {
await typeOrmRepo.create(driver);
expect(savedEntities).toHaveLength(1);
expect(savedEntities[0].avatarRef).toEqual({ type: 'uploaded', mediaId: 'media-abc-123' });
expect((savedEntities[0] as { avatarRef: unknown }).avatarRef).toEqual({ type: 'uploaded', mediaId: 'media-abc-123' });
// Test load
const loaded = await typeOrmRepo.findById(driverId);
@@ -87,10 +87,10 @@ describe('TypeOrmDriverRepository', () => {
avatarRef: MediaReference.createSystemDefault('avatar'),
});
const savedEntities: any[] = [];
const savedEntities: unknown[] = [];
const repo = {
save: async (entity: any) => {
save: async (entity: unknown) => {
savedEntities.push(entity);
return entity;
},

View File

@@ -16,7 +16,7 @@ export class TypeOrmDriverStatsRepository implements DriverStatsRepository {
return entity ? this.mapper.toDomain(entity) : null;
}
getDriverStatsSync(_driverId: string): DriverStats | null {
getDriverStatsSync(): DriverStats | null {
// TypeORM repositories don't support synchronous operations
// This method is provided for interface compatibility but should not be used
// with TypeORM implementations. Return null to indicate it's not supported.

View File

@@ -1,6 +1,8 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import type { DataSource } from 'typeorm';
import { describe, expect, it, vi } from 'vitest';
import type { LeagueOrmMapper } from '../mappers/LeagueOrmMapper';
import { TypeOrmLeagueRepository } from './TypeOrmLeagueRepository';
@@ -31,7 +33,7 @@ describe('TypeOrmLeagueRepository', () => {
toOrmEntity: vi.fn(),
};
const repo = new TypeOrmLeagueRepository(dataSource as any, mapper as any);
const repo = new TypeOrmLeagueRepository(dataSource as unknown as DataSource, mapper as unknown as LeagueOrmMapper);
const league = await repo.findById('l1');

View File

@@ -1,6 +1,8 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import type { DataSource } from 'typeorm';
import { describe, expect, it, vi } from 'vitest';
import type { RaceOrmMapper } from '../mappers/RaceOrmMapper';
import { TypeOrmRaceRepository } from './TypeOrmRaceRepository';
@@ -31,7 +33,7 @@ describe('TypeOrmRaceRepository', () => {
toOrmEntity: vi.fn(),
};
const repo = new TypeOrmRaceRepository(dataSource as any, mapper as any);
const repo = new TypeOrmRaceRepository(dataSource as unknown as DataSource, mapper as unknown as RaceOrmMapper);
const race = await repo.findById('r1');

View File

@@ -1,6 +1,8 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import type { DataSource } from 'typeorm';
import { describe, expect, it, vi } from 'vitest';
import type { SeasonOrmMapper } from '../mappers/SeasonOrmMapper';
import { TypeOrmSeasonRepository } from './TypeOrmSeasonRepository';
@@ -31,7 +33,7 @@ describe('TypeOrmSeasonRepository', () => {
toOrmEntity: vi.fn(),
};
const repo = new TypeOrmSeasonRepository(dataSource as any, mapper as any);
const repo = new TypeOrmSeasonRepository(dataSource as unknown as DataSource, mapper as unknown as SeasonOrmMapper);
const season = await repo.findById('s1');