fix seeds

This commit is contained in:
2025-12-27 01:25:56 +01:00
parent b68405aa46
commit 9a74e16f11
23 changed files with 405 additions and 564 deletions

View File

@@ -20,21 +20,23 @@ export class EnsureInitialData {
async execute(): Promise<void> {
// Ensure initial admin user exists
try {
await this.signupUseCase.execute({
email: 'admin@gridpilot.local',
password: 'admin123',
displayName: 'Admin',
});
const signupResult = await this.signupUseCase.execute({
email: 'admin@gridpilot.local',
password: 'admin123',
displayName: 'Admin',
});
if (signupResult.isOk()) {
this.logger.info('[Bootstrap] Initial admin user created');
} catch (error) {
if (error instanceof Error && error.message === 'An account with this email already exists') {
// User already exists, nothing to do
this.logger.info('[Bootstrap] Admin user already exists');
} else {
// Re-throw other errors
throw error;
}
} else if (signupResult.error?.code === 'EMAIL_ALREADY_EXISTS') {
this.logger.info('[Bootstrap] Admin user already exists');
} else {
const detailsMessage =
signupResult.error && typeof signupResult.error === 'object' && 'details' in signupResult.error
? (signupResult.error as { details?: { message?: string } }).details?.message
: undefined;
throw new Error(detailsMessage ?? 'Failed to ensure initial admin user');
}
// Ensure initial achievements exist

View File

@@ -5,7 +5,6 @@ import { AuthModule } from './domain/auth/AuthModule';
import { BootstrapModule } from './domain/bootstrap/BootstrapModule';
import { DashboardModule } from './domain/dashboard/DashboardModule';
import { DatabaseModule } from './domain/database/DatabaseModule';
import { InMemoryPersistenceModule } from './domain/persistence/InMemoryPersistenceModule';
import { DriverModule } from './domain/driver/DriverModule';
import { HelloModule } from './domain/hello/HelloModule';
import { LeagueModule } from './domain/league/LeagueModule';
@@ -31,7 +30,6 @@ const ENABLE_BOOTSTRAP = getEnableBootstrap();
imports: [
HelloModule,
...(USE_DATABASE ? [DatabaseModule] : []),
...(!USE_DATABASE ? [InMemoryPersistenceModule] : []),
LoggingModule,
...(ENABLE_BOOTSTRAP ? [BootstrapModule] : []),
AnalyticsModule,

View File

@@ -1,18 +1,21 @@
import type { Logger } from '@core/shared/application';
import { EnsureInitialData } from '../../../../../adapters/bootstrap/EnsureInitialData';
import type { EnsureInitialData } from '../../../../../adapters/bootstrap/EnsureInitialData';
import { SeedRacingData, type RacingSeedDependencies } from '../../../../../adapters/bootstrap/SeedRacingData';
import { Module, OnModuleInit } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { Inject, Module, OnModuleInit } from '@nestjs/common';
import { getApiPersistence } from '../../env';
import { BootstrapProviders } from './BootstrapProviders';
import { InMemoryRacingPersistenceModule } from '../../persistence/inmemory/InMemoryRacingPersistenceModule';
import { InMemorySocialPersistenceModule } from '../../persistence/inmemory/InMemorySocialPersistenceModule';
import { BootstrapProviders, ENSURE_INITIAL_DATA_TOKEN } from './BootstrapProviders';
@Module({
imports: [InMemoryRacingPersistenceModule, InMemorySocialPersistenceModule],
providers: BootstrapProviders,
})
export class BootstrapModule implements OnModuleInit {
constructor(
private readonly ensureInitialData: EnsureInitialData,
private readonly moduleRef: ModuleRef,
@Inject(ENSURE_INITIAL_DATA_TOKEN) private readonly ensureInitialData: EnsureInitialData,
@Inject('Logger') private readonly logger: Logger,
@Inject('RacingSeedDependencies') private readonly seedDeps: RacingSeedDependencies,
) {}
async onModuleInit() {
@@ -21,14 +24,7 @@ export class BootstrapModule implements OnModuleInit {
await this.ensureInitialData.execute();
if (this.shouldSeedRacingData()) {
const logger = this.tryGet<Logger>('Logger');
const seedDeps = this.tryGetSeedDeps();
if (!logger || !seedDeps) {
console.log('[Bootstrap] Racing seed skipped (missing providers)');
} else {
await new SeedRacingData(logger, seedDeps).execute();
}
await new SeedRacingData(this.logger, this.seedDeps).execute();
}
console.log('[Bootstrap] Application data initialized successfully');
@@ -41,62 +37,4 @@ export class BootstrapModule implements OnModuleInit {
private shouldSeedRacingData(): boolean {
return getApiPersistence() === 'inmemory';
}
private tryGet<T>(token: string): T | undefined {
try {
return this.moduleRef.get(token, { strict: false });
} catch {
return undefined;
}
}
private tryGetSeedDeps(): RacingSeedDependencies | undefined {
const driverRepository = this.tryGet<RacingSeedDependencies['driverRepository']>('IDriverRepository');
const leagueRepository = this.tryGet<RacingSeedDependencies['leagueRepository']>('ILeagueRepository');
const raceRepository = this.tryGet<RacingSeedDependencies['raceRepository']>('IRaceRepository');
const resultRepository = this.tryGet<RacingSeedDependencies['resultRepository']>('IResultRepository');
const standingRepository = this.tryGet<RacingSeedDependencies['standingRepository']>('IStandingRepository');
const leagueMembershipRepository = this.tryGet<RacingSeedDependencies['leagueMembershipRepository']>(
'ILeagueMembershipRepository',
);
const raceRegistrationRepository = this.tryGet<RacingSeedDependencies['raceRegistrationRepository']>(
'IRaceRegistrationRepository',
);
const teamRepository = this.tryGet<RacingSeedDependencies['teamRepository']>('ITeamRepository');
const teamMembershipRepository = this.tryGet<RacingSeedDependencies['teamMembershipRepository']>(
'ITeamMembershipRepository',
);
const feedRepository = this.tryGet<RacingSeedDependencies['feedRepository']>('IFeedRepository');
const socialGraphRepository = this.tryGet<RacingSeedDependencies['socialGraphRepository']>('ISocialGraphRepository');
if (
!driverRepository ||
!leagueRepository ||
!raceRepository ||
!resultRepository ||
!standingRepository ||
!leagueMembershipRepository ||
!raceRegistrationRepository ||
!teamRepository ||
!teamMembershipRepository ||
!feedRepository ||
!socialGraphRepository
) {
return undefined;
}
return {
driverRepository,
leagueRepository,
raceRepository,
resultRepository,
standingRepository,
leagueMembershipRepository,
raceRegistrationRepository,
teamRepository,
teamMembershipRepository,
feedRepository,
socialGraphRepository,
};
}
}

View File

@@ -1,5 +1,6 @@
import { Provider } from '@nestjs/common';
import { EnsureInitialData } from '../../../../../adapters/bootstrap/EnsureInitialData';
import type { RacingSeedDependencies } from '../../../../../adapters/bootstrap/SeedRacingData';
import { SignupWithEmailUseCase, type SignupWithEmailResult } from '@core/identity/application/use-cases/SignupWithEmailUseCase';
import {
CreateAchievementUseCase,
@@ -21,6 +22,9 @@ export const IDENTITY_SESSION_PORT_TOKEN = 'IdentitySessionPort_Bootstrap';
export const SIGNUP_USE_CASE_TOKEN = 'SignupWithEmailUseCase_Bootstrap';
export const CREATE_ACHIEVEMENT_USE_CASE_TOKEN = 'CreateAchievementUseCase_Bootstrap';
export const RACING_SEED_DEPENDENCIES_TOKEN = 'RacingSeedDependencies';
export const ENSURE_INITIAL_DATA_TOKEN = 'EnsureInitialData_Bootstrap';
// Adapter classes for output ports
class SignupWithEmailOutputAdapter implements UseCaseOutputPort<SignupWithEmailResult> {
present(result: SignupWithEmailResult): void {
@@ -37,6 +41,47 @@ class CreateAchievementOutputAdapter implements UseCaseOutputPort<CreateAchievem
}
export const BootstrapProviders: Provider[] = [
{
provide: RACING_SEED_DEPENDENCIES_TOKEN,
useFactory: (
driverRepository: RacingSeedDependencies['driverRepository'],
leagueRepository: RacingSeedDependencies['leagueRepository'],
raceRepository: RacingSeedDependencies['raceRepository'],
resultRepository: RacingSeedDependencies['resultRepository'],
standingRepository: RacingSeedDependencies['standingRepository'],
leagueMembershipRepository: RacingSeedDependencies['leagueMembershipRepository'],
raceRegistrationRepository: RacingSeedDependencies['raceRegistrationRepository'],
teamRepository: RacingSeedDependencies['teamRepository'],
teamMembershipRepository: RacingSeedDependencies['teamMembershipRepository'],
feedRepository: RacingSeedDependencies['feedRepository'],
socialGraphRepository: RacingSeedDependencies['socialGraphRepository'],
): RacingSeedDependencies => ({
driverRepository,
leagueRepository,
raceRepository,
resultRepository,
standingRepository,
leagueMembershipRepository,
raceRegistrationRepository,
teamRepository,
teamMembershipRepository,
feedRepository,
socialGraphRepository,
}),
inject: [
'IDriverRepository',
'ILeagueRepository',
'IRaceRepository',
'IResultRepository',
'IStandingRepository',
'ILeagueMembershipRepository',
'IRaceRegistrationRepository',
'ITeamRepository',
'ITeamMembershipRepository',
'IFeedRepository',
'ISocialGraphRepository',
],
},
{
provide: USER_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryUserRepository(logger),
@@ -82,7 +127,7 @@ export const BootstrapProviders: Provider[] = [
inject: [ACHIEVEMENT_REPOSITORY_TOKEN, 'Logger'],
},
{
provide: EnsureInitialData,
provide: ENSURE_INITIAL_DATA_TOKEN,
useFactory: (
signupUseCase: SignupWithEmailUseCase,
createAchievementUseCase: CreateAchievementUseCase,
@@ -90,10 +135,6 @@ export const BootstrapProviders: Provider[] = [
) => {
return new EnsureInitialData(signupUseCase, createAchievementUseCase, logger);
},
inject: [
SIGNUP_USE_CASE_TOKEN,
CREATE_ACHIEVEMENT_USE_CASE_TOKEN,
'Logger',
],
inject: [SIGNUP_USE_CASE_TOKEN, CREATE_ACHIEVEMENT_USE_CASE_TOKEN, 'Logger'],
},
];

View File

@@ -0,0 +1,52 @@
import 'reflect-metadata';
import { Test } from '@nestjs/testing';
import type { TestingModule } from '@nestjs/testing';
import request from 'supertest';
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
describe('Bootstrap seeding (HTTP, inmemory)', () => {
const originalEnv = { ...process.env };
let module: TestingModule | undefined;
let app: any;
beforeAll(async () => {
vi.resetModules();
process.env.GRIDPILOT_API_PERSISTENCE = 'inmemory';
process.env.GRIDPILOT_API_BOOTSTRAP = 'true';
delete process.env.DATABASE_URL;
const { AppModule } = await import('../../app.module');
module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = module.createNestApplication();
await app.init();
}, 20_000);
afterAll(async () => {
await app?.close();
await module?.close();
process.env = originalEnv;
vi.restoreAllMocks();
});
it('exposes seeded leagues via HTTP (regression for repo instance mismatch)', async () => {
const leaguesRes = await request(app.getHttpServer()).get('/leagues/total-leagues').expect(200);
expect(leaguesRes.body).toBeDefined();
expect(typeof leaguesRes.body.totalLeagues).toBe('number');
expect(leaguesRes.body.totalLeagues).toBeGreaterThan(0);
const racesRes = await request(app.getHttpServer()).get('/races/total-races').expect(200);
expect(racesRes.body).toBeDefined();
expect(typeof racesRes.body.totalRaces).toBe('number');
expect(racesRes.body.totalRaces).toBeGreaterThan(0);
});
});

View File

@@ -1,9 +1,12 @@
import { Module } from '@nestjs/common';
import { InMemoryRacingPersistenceModule } from '../../persistence/inmemory/InMemoryRacingPersistenceModule';
import { InMemorySocialPersistenceModule } from '../../persistence/inmemory/InMemorySocialPersistenceModule';
import { DashboardService } from './DashboardService';
import { DashboardController } from './DashboardController';
import { DashboardProviders } from './DashboardProviders';
@Module({
imports: [InMemoryRacingPersistenceModule, InMemorySocialPersistenceModule],
controllers: [DashboardController],
providers: [DashboardService, ...DashboardProviders],
exports: [DashboardService],

View File

@@ -16,43 +16,9 @@ import { DashboardOverviewUseCase } from '@core/racing/application/use-cases/Das
// Import concrete implementations
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
import { InMemoryResultRepository } from '@adapters/racing/persistence/inmemory/InMemoryResultRepository';
import { InMemoryLeagueRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
import { InMemoryStandingRepository } from '@adapters/racing/persistence/inmemory/InMemoryStandingRepository';
import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
import { InMemoryRaceRegistrationRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRegistrationRepository';
import { InMemoryImageServiceAdapter } from '@adapters/media/ports/InMemoryImageServiceAdapter';
import { DashboardOverviewPresenter } from './presenters/DashboardOverviewPresenter';
// Simple mock implementations for missing adapters
class MockFeedRepository implements IFeedRepository {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getFeedForDriver(_driverId: string, _limit?: number) {
return [];
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getGlobalFeed(_limit?: number) {
return [];
}
}
class MockSocialGraphRepository implements ISocialGraphRepository {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getFriends(_driverId: string) {
return [];
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getFriendIds(_driverId: string) {
return [];
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getSuggestedFriends(_driverId: string, _limit?: number) {
return [];
}
}
// Define injection tokens
export const LOGGER_TOKEN = 'Logger';
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
@@ -74,49 +40,6 @@ export const DashboardProviders: Provider[] = [
provide: LOGGER_TOKEN,
useClass: ConsoleLogger,
},
{
provide: DRIVER_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryDriverRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: RACE_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryRaceRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: RESULT_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryResultRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: STANDING_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryStandingRepository(logger, {}),
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueMembershipRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: RACE_REGISTRATION_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryRaceRegistrationRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: FEED_REPOSITORY_TOKEN,
useFactory: () => new MockFeedRepository(),
},
{
provide: SOCIAL_GRAPH_REPOSITORY_TOKEN,
useFactory: () => new MockSocialGraphRepository(),
},
{
provide: IMAGE_SERVICE_TOKEN,
useFactory: (logger: Logger) => new InMemoryImageServiceAdapter(logger),

View File

@@ -1,9 +1,12 @@
import { Module } from '@nestjs/common';
import { InMemoryRacingPersistenceModule } from '../../persistence/inmemory/InMemoryRacingPersistenceModule';
import { InMemorySocialPersistenceModule } from '../../persistence/inmemory/InMemorySocialPersistenceModule';
import { DriverService } from './DriverService';
import { DriverController } from './DriverController';
import { DriverProviders } from './DriverProviders';
@Module({
imports: [InMemoryRacingPersistenceModule, InMemorySocialPersistenceModule],
controllers: [DriverController],
providers: [DriverService, ...DriverProviders],
exports: [DriverService],

View File

@@ -23,16 +23,11 @@ import { UpdateDriverProfileUseCase } from '@core/racing/application/use-cases/U
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
import { InMemoryImageServiceAdapter } from '@adapters/media/ports/InMemoryImageServiceAdapter';
import { InMemoryNotificationPreferenceRepository } from '@adapters/notifications/persistence/inmemory/InMemoryNotificationPreferenceRepository';
import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryRaceRegistrationRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRegistrationRepository';
import { InMemoryTeamMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamMembershipRepository';
import { InMemoryTeamRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamRepository';
import { InMemoryDriverExtendedProfileProvider } from '@adapters/racing/ports/InMemoryDriverExtendedProfileProvider';
import { InMemoryDriverRatingProvider } from '@adapters/racing/ports/InMemoryDriverRatingProvider';
import { InMemoryDriverStatsService } from '@adapters/racing/services/InMemoryDriverStatsService';
import { InMemoryRankingService } from '@adapters/racing/services/InMemoryRankingService';
import { IImageServicePort } from '@core/racing/application/ports/IImageServicePort';
import { InMemorySocialGraphRepository } from '@adapters/social/persistence/inmemory/InMemorySocialAndFeed';
// Import presenters
import { CompleteOnboardingPresenter } from './presenters/CompleteOnboardingPresenter';
@@ -113,12 +108,7 @@ export const DriverProviders: Provider[] = [
useClass: ConsoleLogger,
},
// Repositories
{
provide: DRIVER_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryDriverRepository(logger),
inject: [LOGGER_TOKEN],
},
// Repositories (racing + social repos are provided by imported persistence modules)
{
provide: RANKING_SERVICE_TOKEN,
useFactory: (logger: Logger) => new InMemoryRankingService(logger),
@@ -144,32 +134,11 @@ export const DriverProviders: Provider[] = [
useFactory: (logger: Logger) => new InMemoryImageServiceAdapter(logger),
inject: [LOGGER_TOKEN],
},
{
provide: RACE_REGISTRATION_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryRaceRegistrationRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: NOTIFICATION_PREFERENCE_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryNotificationPreferenceRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: TEAM_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryTeamRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: TEAM_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryTeamMembershipRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: SOCIAL_GRAPH_REPOSITORY_TOKEN,
useFactory: (logger: Logger) =>
new InMemorySocialGraphRepository(logger, { drivers: [], friendships: [], feedEvents: [] }),
inject: [LOGGER_TOKEN],
},
// Use cases
{

View File

@@ -1,9 +1,11 @@
import { Module } from '@nestjs/common';
import { InMemoryRacingPersistenceModule } from '../../persistence/inmemory/InMemoryRacingPersistenceModule';
import { LeagueService } from './LeagueService';
import { LeagueController } from './LeagueController';
import { LeagueProviders } from './LeagueProviders';
@Module({
imports: [InMemoryRacingPersistenceModule],
controllers: [LeagueController],
providers: LeagueProviders,
exports: [LeagueService],

View File

@@ -16,21 +16,10 @@ import type { Logger } from '@core/shared/application/Logger';
import type { ILeagueWalletRepository } from "@core/racing/domain/repositories/ILeagueWalletRepository";
import type { ITransactionRepository } from "@core/racing/domain/repositories/ITransactionRepository";
import { listLeagueScoringPresets } from '@adapters/bootstrap/LeagueScoringPresets';
import { getPointsSystems } from '@adapters/bootstrap/PointsSystems';
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryGameRepository } from '@adapters/racing/persistence/inmemory/InMemoryGameRepository';
import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
import { InMemoryLeagueRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
import { InMemoryLeagueScoringConfigRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueScoringConfigRepository';
import { InMemoryLeagueStandingsRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueStandingsRepository';
import { InMemoryLeagueWalletRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueWalletRepository';
import { InMemoryProtestRepository } from '@adapters/racing/persistence/inmemory/InMemoryProtestRepository';
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
import { InMemorySeasonRepository } from '@adapters/racing/persistence/inmemory/InMemorySeasonRepository';
import { InMemorySeasonSponsorshipRepository } from '@adapters/racing/persistence/inmemory/InMemorySeasonSponsorshipRepository';
import { InMemoryStandingRepository } from '@adapters/racing/persistence/inmemory/InMemoryStandingRepository';
import { InMemoryTransactionRepository } from '@adapters/racing/persistence/inmemory/InMemoryTransactionRepository';
// Import use cases
import { ApproveLeagueJoinRequestUseCase } from '@core/racing/application/use-cases/ApproveLeagueJoinRequestUseCase';
@@ -149,37 +138,12 @@ export const GET_LEAGUE_WALLET_OUTPUT_PORT_TOKEN = 'GetLeagueWalletOutputPort_TO
export const WITHDRAW_FROM_LEAGUE_WALLET_OUTPUT_PORT_TOKEN = 'WithdrawFromLeagueWalletOutputPort_TOKEN';
export const LeagueProviders: Provider[] = [
LeagueService, // Provide the service itself
{
provide: LEAGUE_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueRepository(logger), // Factory for InMemoryLeagueRepository
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueMembershipRepository(logger), // Factory for InMemoryLeagueMembershipRepository
inject: [LOGGER_TOKEN],
},
LeagueService,
{
provide: LEAGUE_STANDINGS_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueStandingsRepository(logger), // Factory for InMemoryLeagueStandingsRepository
inject: [LOGGER_TOKEN],
},
{
provide: STANDING_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryStandingRepository(logger, getPointsSystems()), // Factory for InMemoryStandingRepository
inject: [LOGGER_TOKEN],
},
{
provide: SEASON_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemorySeasonRepository(logger), // Factory for InMemorySeasonRepository
inject: [LOGGER_TOKEN],
},
{
provide: 'ISeasonSponsorshipRepository',
useFactory: (logger: Logger) => new InMemorySeasonSponsorshipRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_SCORING_CONFIG_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueScoringConfigRepository(logger), // Factory for InMemoryLeagueScoringConfigRepository
@@ -190,31 +154,6 @@ export const LeagueProviders: Provider[] = [
useFactory: (logger: Logger) => new InMemoryGameRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: PROTEST_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryProtestRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: RACE_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryRaceRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: DRIVER_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryDriverRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_WALLET_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueWalletRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: TRANSACTION_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryTransactionRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LOGGER_TOKEN,
useClass: ConsoleLogger,
@@ -376,7 +315,9 @@ export const LeagueProviders: Provider[] = [
},
{
provide: GET_TOTAL_LEAGUES_USE_CASE,
useClass: GetTotalLeaguesUseCase,
useFactory: (leagueRepo: ILeagueRepository, output: TotalLeaguesPresenter) =>
new GetTotalLeaguesUseCase(leagueRepo, output),
inject: [LEAGUE_REPOSITORY_TOKEN, TOTAL_LEAGUES_OUTPUT_PORT_TOKEN],
},
{
provide: GET_LEAGUE_JOIN_REQUESTS_USE_CASE,

View File

@@ -1,129 +1,19 @@
import { Global, Module } from '@nestjs/common';
import { Module } from '@nestjs/common';
import type { Logger } from '@core/shared/application/Logger';
import { InMemoryRacingPersistenceModule } from '../../persistence/inmemory/InMemoryRacingPersistenceModule';
import { InMemorySocialPersistenceModule } from '../../persistence/inmemory/InMemorySocialPersistenceModule';
import type { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepository';
import type { ILeagueRepository } from '@core/racing/domain/repositories/ILeagueRepository';
import type { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepository';
import type { IResultRepository } from '@core/racing/domain/repositories/IResultRepository';
import type { IStandingRepository } from '@core/racing/domain/repositories/IStandingRepository';
import type { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
import type { IRaceRegistrationRepository } from '@core/racing/domain/repositories/IRaceRegistrationRepository';
import type { ITeamRepository } from '@core/racing/domain/repositories/ITeamRepository';
import type { ITeamMembershipRepository } from '@core/racing/domain/repositories/ITeamMembershipRepository';
import type { IFeedRepository } from '@core/social/domain/repositories/IFeedRepository';
import type { ISocialGraphRepository } from '@core/social/domain/repositories/ISocialGraphRepository';
import { getPointsSystems } from '@adapters/bootstrap/PointsSystems';
import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryLeagueRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
import { InMemoryResultRepository } from '@adapters/racing/persistence/inmemory/InMemoryResultRepository';
import { InMemoryStandingRepository } from '@adapters/racing/persistence/inmemory/InMemoryStandingRepository';
import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
import { InMemoryRaceRegistrationRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRegistrationRepository';
import { InMemoryTeamRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamRepository';
import { InMemoryTeamMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamMembershipRepository';
import {
InMemoryFeedRepository,
InMemorySocialGraphRepository,
} from '@adapters/social/persistence/inmemory/InMemorySocialAndFeed';
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
export const LEAGUE_REPOSITORY_TOKEN = 'ILeagueRepository';
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
export const RESULT_REPOSITORY_TOKEN = 'IResultRepository';
export const STANDING_REPOSITORY_TOKEN = 'IStandingRepository';
export const LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN = 'ILeagueMembershipRepository';
export const RACE_REGISTRATION_REPOSITORY_TOKEN = 'IRaceRegistrationRepository';
export const TEAM_REPOSITORY_TOKEN = 'ITeamRepository';
export const TEAM_MEMBERSHIP_REPOSITORY_TOKEN = 'ITeamMembershipRepository';
export const FEED_REPOSITORY_TOKEN = 'IFeedRepository';
export const SOCIAL_GRAPH_REPOSITORY_TOKEN = 'ISocialGraphRepository';
@Global()
/**
* @deprecated Legacy compatibility module.
*
* The real in-memory persistence wiring lives in bounded, non-global modules:
* - `InMemoryRacingPersistenceModule`
* - `InMemorySocialPersistenceModule`
*
* This module intentionally does not define providers itself (to avoid competing instances).
*/
@Module({
providers: [
{
provide: DRIVER_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IDriverRepository => new InMemoryDriverRepository(logger),
inject: ['Logger'],
},
{
provide: LEAGUE_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ILeagueRepository => new InMemoryLeagueRepository(logger),
inject: ['Logger'],
},
{
provide: RACE_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IRaceRepository => new InMemoryRaceRepository(logger),
inject: ['Logger'],
},
{
provide: RESULT_REPOSITORY_TOKEN,
useFactory: (logger: Logger, raceRepo: IRaceRepository): IResultRepository =>
new InMemoryResultRepository(logger, raceRepo),
inject: ['Logger', RACE_REPOSITORY_TOKEN],
},
{
provide: STANDING_REPOSITORY_TOKEN,
useFactory: (
logger: Logger,
resultRepo: IResultRepository,
raceRepo: IRaceRepository,
leagueRepo: ILeagueRepository,
): IStandingRepository => new InMemoryStandingRepository(logger, getPointsSystems(), resultRepo, raceRepo, leagueRepo),
inject: ['Logger', RESULT_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
},
{
provide: LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ILeagueMembershipRepository => new InMemoryLeagueMembershipRepository(logger),
inject: ['Logger'],
},
{
provide: RACE_REGISTRATION_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IRaceRegistrationRepository => new InMemoryRaceRegistrationRepository(logger),
inject: ['Logger'],
},
{
provide: TEAM_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ITeamRepository => new InMemoryTeamRepository(logger),
inject: ['Logger'],
},
{
provide: TEAM_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ITeamMembershipRepository => new InMemoryTeamMembershipRepository(logger),
inject: ['Logger'],
},
{
provide: FEED_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IFeedRepository =>
new InMemoryFeedRepository(logger, { drivers: [], friendships: [], feedEvents: [] }),
inject: ['Logger'],
},
{
provide: SOCIAL_GRAPH_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ISocialGraphRepository =>
new InMemorySocialGraphRepository(logger, { drivers: [], friendships: [], feedEvents: [] }),
inject: ['Logger'],
},
],
exports: [
DRIVER_REPOSITORY_TOKEN,
LEAGUE_REPOSITORY_TOKEN,
RACE_REPOSITORY_TOKEN,
RESULT_REPOSITORY_TOKEN,
STANDING_REPOSITORY_TOKEN,
LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
RACE_REGISTRATION_REPOSITORY_TOKEN,
TEAM_REPOSITORY_TOKEN,
TEAM_MEMBERSHIP_REPOSITORY_TOKEN,
FEED_REPOSITORY_TOKEN,
SOCIAL_GRAPH_REPOSITORY_TOKEN,
],
imports: [InMemoryRacingPersistenceModule, InMemorySocialPersistenceModule],
exports: [InMemoryRacingPersistenceModule, InMemorySocialPersistenceModule],
})
export class InMemoryPersistenceModule {}

View File

@@ -1,9 +1,11 @@
import { Module } from '@nestjs/common';
import { InMemoryRacingPersistenceModule } from '../../persistence/inmemory/InMemoryRacingPersistenceModule';
import { ProtestsController } from './ProtestsController';
import { ProtestsService } from './ProtestsService';
import { ProtestsProviders } from './ProtestsProviders';
@Module({
imports: [InMemoryRacingPersistenceModule],
providers: [ProtestsService, ...ProtestsProviders],
controllers: [ProtestsController],
})

View File

@@ -7,9 +7,6 @@ import type { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepo
import type { Logger } from '@core/shared/application/Logger';
// Import concrete in-memory implementations
import { InMemoryProtestRepository } from '@adapters/racing/persistence/inmemory/InMemoryProtestRepository';
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
// Import use cases
@@ -26,21 +23,6 @@ export const LOGGER_TOKEN = 'Logger';
export const REVIEW_PROTEST_PRESENTER_TOKEN = 'ReviewProtestPresenter';
export const ProtestsProviders: Provider[] = [
{
provide: PROTEST_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryProtestRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: RACE_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryRaceRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueMembershipRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LOGGER_TOKEN,
useClass: ConsoleLogger,

View File

@@ -1,9 +1,11 @@
import { Module } from '@nestjs/common';
import { InMemoryRacingPersistenceModule } from '../../persistence/inmemory/InMemoryRacingPersistenceModule';
import { RaceService } from './RaceService';
import { RaceController } from './RaceController';
import { RaceProviders } from './RaceProviders';
@Module({
imports: [InMemoryRacingPersistenceModule],
controllers: [RaceController],
providers: [RaceService, ...RaceProviders],
exports: [RaceService],

View File

@@ -16,18 +16,8 @@ import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPo
import { Result } from '@core/shared/application/Result';
// Import concrete in-memory implementations
import { getPointsSystems } from '@adapters/bootstrap/PointsSystems';
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
import { InMemoryImageServiceAdapter } from '@adapters/media/ports/InMemoryImageServiceAdapter';
import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
import { InMemoryLeagueRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
import { InMemoryPenaltyRepository } from '@adapters/racing/persistence/inmemory/InMemoryPenaltyRepository';
import { InMemoryProtestRepository } from '@adapters/racing/persistence/inmemory/InMemoryProtestRepository';
import { InMemoryRaceRegistrationRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRegistrationRepository';
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
import { InMemoryResultRepository } from '@adapters/racing/persistence/inmemory/InMemoryResultRepository';
import { InMemoryStandingRepository } from '@adapters/racing/persistence/inmemory/InMemoryStandingRepository';
import { InMemoryDriverRatingProvider } from '@adapters/racing/ports/InMemoryDriverRatingProvider';
// Import use cases
@@ -295,51 +285,6 @@ class ReviewProtestOutputAdapter implements UseCaseOutputPort<ReviewProtestResul
}
export const RaceProviders: Provider[] = [
{
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: DRIVER_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryDriverRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: RACE_REGISTRATION_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryRaceRegistrationRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: RESULT_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryResultRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueMembershipRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: PENALTY_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryPenaltyRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: PROTEST_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryProtestRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: STANDING_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryStandingRepository(logger, getPointsSystems()),
inject: [LOGGER_TOKEN],
},
{
provide: DRIVER_RATING_PROVIDER_TOKEN,
useFactory: (logger: Logger) => new InMemoryDriverRatingProvider(logger),

View File

@@ -79,26 +79,26 @@ import { penaltyTypeRequiresValue } from '@core/racing/domain/entities/penalty/P
@Injectable()
export class RaceService {
constructor(
private readonly getAllRacesUseCase: GetAllRacesUseCase,
private readonly getTotalRacesUseCase: GetTotalRacesUseCase,
private readonly importRaceResultsApiUseCase: ImportRaceResultsApiUseCase,
private readonly getRaceDetailUseCase: GetRaceDetailUseCase,
private readonly getRacesPageDataUseCase: GetRacesPageDataUseCase,
private readonly getAllRacesPageDataUseCase: GetAllRacesPageDataUseCase,
private readonly getRaceResultsDetailUseCase: GetRaceResultsDetailUseCase,
private readonly getRaceWithSOFUseCase: GetRaceWithSOFUseCase,
private readonly getRaceProtestsUseCase: GetRaceProtestsUseCase,
private readonly getRacePenaltiesUseCase: GetRacePenaltiesUseCase,
private readonly registerForRaceUseCase: RegisterForRaceUseCase,
private readonly withdrawFromRaceUseCase: WithdrawFromRaceUseCase,
private readonly cancelRaceUseCase: CancelRaceUseCase,
private readonly completeRaceUseCase: CompleteRaceUseCase,
private readonly fileProtestUseCase: FileProtestUseCase,
private readonly quickPenaltyUseCase: QuickPenaltyUseCase,
private readonly applyPenaltyUseCase: ApplyPenaltyUseCase,
private readonly requestProtestDefenseUseCase: RequestProtestDefenseUseCase,
private readonly reviewProtestUseCase: ReviewProtestUseCase,
private readonly reopenRaceUseCase: ReopenRaceUseCase,
@Inject(GetAllRacesUseCase) private readonly getAllRacesUseCase: GetAllRacesUseCase,
@Inject(GetTotalRacesUseCase) private readonly getTotalRacesUseCase: GetTotalRacesUseCase,
@Inject(ImportRaceResultsApiUseCase) private readonly importRaceResultsApiUseCase: ImportRaceResultsApiUseCase,
@Inject(GetRaceDetailUseCase) private readonly getRaceDetailUseCase: GetRaceDetailUseCase,
@Inject(GetRacesPageDataUseCase) private readonly getRacesPageDataUseCase: GetRacesPageDataUseCase,
@Inject(GetAllRacesPageDataUseCase) private readonly getAllRacesPageDataUseCase: GetAllRacesPageDataUseCase,
@Inject(GetRaceResultsDetailUseCase) private readonly getRaceResultsDetailUseCase: GetRaceResultsDetailUseCase,
@Inject(GetRaceWithSOFUseCase) private readonly getRaceWithSOFUseCase: GetRaceWithSOFUseCase,
@Inject(GetRaceProtestsUseCase) private readonly getRaceProtestsUseCase: GetRaceProtestsUseCase,
@Inject(GetRacePenaltiesUseCase) private readonly getRacePenaltiesUseCase: GetRacePenaltiesUseCase,
@Inject(RegisterForRaceUseCase) private readonly registerForRaceUseCase: RegisterForRaceUseCase,
@Inject(WithdrawFromRaceUseCase) private readonly withdrawFromRaceUseCase: WithdrawFromRaceUseCase,
@Inject(CancelRaceUseCase) private readonly cancelRaceUseCase: CancelRaceUseCase,
@Inject(CompleteRaceUseCase) private readonly completeRaceUseCase: CompleteRaceUseCase,
@Inject(FileProtestUseCase) private readonly fileProtestUseCase: FileProtestUseCase,
@Inject(QuickPenaltyUseCase) private readonly quickPenaltyUseCase: QuickPenaltyUseCase,
@Inject(ApplyPenaltyUseCase) private readonly applyPenaltyUseCase: ApplyPenaltyUseCase,
@Inject(RequestProtestDefenseUseCase) private readonly requestProtestDefenseUseCase: RequestProtestDefenseUseCase,
@Inject(ReviewProtestUseCase) private readonly reviewProtestUseCase: ReviewProtestUseCase,
@Inject(ReopenRaceUseCase) private readonly reopenRaceUseCase: ReopenRaceUseCase,
@Inject(LOGGER_TOKEN) private readonly logger: Logger,
// Injected presenters
@Inject(GET_ALL_RACES_PRESENTER_TOKEN) private readonly getAllRacesPresenter: GetAllRacesPresenter,

View File

@@ -1,4 +1,5 @@
import { Module } from '@nestjs/common';
import { InMemoryRacingPersistenceModule } from '../../persistence/inmemory/InMemoryRacingPersistenceModule';
import { AuthModule } from '../auth/AuthModule';
import { PolicyModule } from '../policy/PolicyModule';
import { SponsorService } from './SponsorService';
@@ -6,7 +7,7 @@ import { SponsorController } from './SponsorController';
import { SponsorProviders } from './SponsorProviders';
@Module({
imports: [AuthModule, PolicyModule],
imports: [InMemoryRacingPersistenceModule, AuthModule, PolicyModule],
controllers: [SponsorController],
providers: SponsorProviders,
exports: [SponsorService],

View File

@@ -34,15 +34,6 @@ import { RejectSponsorshipRequestUseCase } from '@core/racing/application/use-ca
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
import { InMemoryPaymentRepository } from '@adapters/payments/persistence/inmemory/InMemoryPaymentRepository';
import { InMemoryWalletRepository } from '@adapters/payments/persistence/inmemory/InMemoryWalletRepository';
import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
import { InMemoryLeagueRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
import { InMemoryLeagueWalletRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueWalletRepository';
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
import { InMemorySeasonRepository } from '@adapters/racing/persistence/inmemory/InMemorySeasonRepository';
import { InMemorySeasonSponsorshipRepository } from '@adapters/racing/persistence/inmemory/InMemorySeasonSponsorshipRepository';
import { InMemorySponsorRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorRepository';
import { InMemorySponsorshipPricingRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorshipPricingRepository';
import { InMemorySponsorshipRequestRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorshipRequestRepository';
// Import presenters
import { GetEntitySponsorshipPricingPresenter } from './presenters/GetEntitySponsorshipPricingPresenter';
@@ -111,47 +102,7 @@ export const GET_SPONSOR_BILLING_OUTPUT_PORT_TOKEN = 'GetSponsorBillingOutputPor
export const SponsorProviders: Provider[] = [
SponsorService,
// Repositories
{
provide: SPONSOR_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemorySponsorRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: SEASON_SPONSORSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemorySeasonSponsorshipRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: SEASON_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemorySeasonRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueMembershipRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: RACE_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryRaceRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: SPONSORSHIP_PRICING_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemorySponsorshipPricingRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: SPONSORSHIP_REQUEST_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemorySponsorshipRequestRepository(logger),
inject: [LOGGER_TOKEN],
},
// Repositories (payments repos are local to this module; racing repos come from InMemoryRacingPersistenceModule)
{
provide: PAYMENT_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryPaymentRepository(logger),
@@ -162,11 +113,6 @@ export const SponsorProviders: Provider[] = [
useFactory: (logger: Logger) => new InMemoryWalletRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: LEAGUE_WALLET_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryLeagueWalletRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: NOTIFICATION_SERVICE_TOKEN,
useFactory: (logger: Logger): NotificationService => ({

View File

@@ -1,9 +1,11 @@
import { Module } from '@nestjs/common';
import { InMemoryRacingPersistenceModule } from '../../persistence/inmemory/InMemoryRacingPersistenceModule';
import { TeamService } from './TeamService';
import { TeamController } from './TeamController';
import { TeamProviders } from './TeamProviders';
@Module({
imports: [InMemoryRacingPersistenceModule],
controllers: [TeamController],
providers: [TeamService, ...TeamProviders],
exports: [TeamService],

View File

@@ -1,12 +1,6 @@
import { Provider } from '@nestjs/common';
import {
TEAM_REPOSITORY_TOKEN,
TEAM_MEMBERSHIP_REPOSITORY_TOKEN,
DRIVER_REPOSITORY_TOKEN,
IMAGE_SERVICE_TOKEN,
LOGGER_TOKEN,
} from './TeamTokens';
import { IMAGE_SERVICE_TOKEN, LOGGER_TOKEN } from './TeamTokens';
export {
TEAM_REPOSITORY_TOKEN,
@@ -20,30 +14,12 @@ export {
import type { Logger } from '@core/shared/application/Logger';
// Import concrete in-memory implementations
import { InMemoryTeamRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamRepository';
import { InMemoryTeamMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamMembershipRepository';
import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryImageServiceAdapter } from '@adapters/media/ports/InMemoryImageServiceAdapter';
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
// Use cases are imported and used directly in the service
export const TeamProviders: Provider[] = [
{
provide: TEAM_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryTeamRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: TEAM_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryTeamMembershipRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: DRIVER_REPOSITORY_TOKEN,
useFactory: (logger: Logger) => new InMemoryDriverRepository(logger),
inject: [LOGGER_TOKEN],
},
{
provide: IMAGE_SERVICE_TOKEN,
useFactory: (logger: Logger) => new InMemoryImageServiceAdapter(logger),

View File

@@ -0,0 +1,187 @@
import { Module } from '@nestjs/common';
import { LoggingModule } from '../../domain/logging/LoggingModule';
import type { Logger } from '@core/shared/application/Logger';
import type { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepository';
import type { ILeagueRepository } from '@core/racing/domain/repositories/ILeagueRepository';
import type { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepository';
import type { IResultRepository } from '@core/racing/domain/repositories/IResultRepository';
import type { IStandingRepository } from '@core/racing/domain/repositories/IStandingRepository';
import type { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
import type { IRaceRegistrationRepository } from '@core/racing/domain/repositories/IRaceRegistrationRepository';
import type { IPenaltyRepository } from '@core/racing/domain/repositories/IPenaltyRepository';
import type { IProtestRepository } from '@core/racing/domain/repositories/IProtestRepository';
import type { ISeasonRepository } from '@core/racing/domain/repositories/ISeasonRepository';
import type { ISeasonSponsorshipRepository } from '@core/racing/domain/repositories/ISeasonSponsorshipRepository';
import type { ILeagueWalletRepository } from '@core/racing/domain/repositories/ILeagueWalletRepository';
import type { ITransactionRepository } from '@core/racing/domain/repositories/ITransactionRepository';
import type { ISponsorRepository } from '@core/racing/domain/repositories/ISponsorRepository';
import type { ISponsorshipPricingRepository } from '@core/racing/domain/repositories/ISponsorshipPricingRepository';
import type { ISponsorshipRequestRepository } from '@core/racing/domain/repositories/ISponsorshipRequestRepository';
import type { ITeamRepository } from '@core/racing/domain/repositories/ITeamRepository';
import type { ITeamMembershipRepository } from '@core/racing/domain/repositories/ITeamMembershipRepository';
import { getPointsSystems } from '@adapters/bootstrap/PointsSystems';
import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryLeagueRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
import { InMemoryResultRepository } from '@adapters/racing/persistence/inmemory/InMemoryResultRepository';
import { InMemoryStandingRepository } from '@adapters/racing/persistence/inmemory/InMemoryStandingRepository';
import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
import { InMemoryRaceRegistrationRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRegistrationRepository';
import { InMemoryTeamRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamRepository';
import { InMemoryTeamMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamMembershipRepository';
import { InMemoryPenaltyRepository } from '@adapters/racing/persistence/inmemory/InMemoryPenaltyRepository';
import { InMemoryProtestRepository } from '@adapters/racing/persistence/inmemory/InMemoryProtestRepository';
import { InMemorySeasonRepository } from '@adapters/racing/persistence/inmemory/InMemorySeasonRepository';
import { InMemorySeasonSponsorshipRepository } from '@adapters/racing/persistence/inmemory/InMemorySeasonSponsorshipRepository';
import { InMemoryLeagueWalletRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueWalletRepository';
import { InMemoryTransactionRepository } from '@adapters/racing/persistence/inmemory/InMemoryTransactionRepository';
import { InMemorySponsorRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorRepository';
import { InMemorySponsorshipPricingRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorshipPricingRepository';
import { InMemorySponsorshipRequestRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorshipRequestRepository';
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
export const LEAGUE_REPOSITORY_TOKEN = 'ILeagueRepository';
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
export const RESULT_REPOSITORY_TOKEN = 'IResultRepository';
export const STANDING_REPOSITORY_TOKEN = 'IStandingRepository';
export const LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN = 'ILeagueMembershipRepository';
export const RACE_REGISTRATION_REPOSITORY_TOKEN = 'IRaceRegistrationRepository';
export const TEAM_REPOSITORY_TOKEN = 'ITeamRepository';
export const TEAM_MEMBERSHIP_REPOSITORY_TOKEN = 'ITeamMembershipRepository';
export const PENALTY_REPOSITORY_TOKEN = 'IPenaltyRepository';
export const PROTEST_REPOSITORY_TOKEN = 'IProtestRepository';
export const SEASON_REPOSITORY_TOKEN = 'ISeasonRepository';
export const SEASON_SPONSORSHIP_REPOSITORY_TOKEN = 'ISeasonSponsorshipRepository';
export const LEAGUE_WALLET_REPOSITORY_TOKEN = 'ILeagueWalletRepository';
export const TRANSACTION_REPOSITORY_TOKEN = 'ITransactionRepository';
export const SPONSOR_REPOSITORY_TOKEN = 'ISponsorRepository';
export const SPONSORSHIP_PRICING_REPOSITORY_TOKEN = 'ISponsorshipPricingRepository';
export const SPONSORSHIP_REQUEST_REPOSITORY_TOKEN = 'ISponsorshipRequestRepository';
@Module({
imports: [LoggingModule],
providers: [
{
provide: DRIVER_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IDriverRepository => new InMemoryDriverRepository(logger),
inject: ['Logger'],
},
{
provide: LEAGUE_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ILeagueRepository => new InMemoryLeagueRepository(logger),
inject: ['Logger'],
},
{
provide: RACE_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IRaceRepository => new InMemoryRaceRepository(logger),
inject: ['Logger'],
},
{
provide: RESULT_REPOSITORY_TOKEN,
useFactory: (logger: Logger, raceRepo: IRaceRepository): IResultRepository =>
new InMemoryResultRepository(logger, raceRepo),
inject: ['Logger', RACE_REPOSITORY_TOKEN],
},
{
provide: STANDING_REPOSITORY_TOKEN,
useFactory: (
logger: Logger,
resultRepo: IResultRepository,
raceRepo: IRaceRepository,
leagueRepo: ILeagueRepository,
): IStandingRepository => new InMemoryStandingRepository(logger, getPointsSystems(), resultRepo, raceRepo, leagueRepo),
inject: ['Logger', RESULT_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
},
{
provide: LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ILeagueMembershipRepository => new InMemoryLeagueMembershipRepository(logger),
inject: ['Logger'],
},
{
provide: RACE_REGISTRATION_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IRaceRegistrationRepository => new InMemoryRaceRegistrationRepository(logger),
inject: ['Logger'],
},
{
provide: TEAM_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ITeamRepository => new InMemoryTeamRepository(logger),
inject: ['Logger'],
},
{
provide: TEAM_MEMBERSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ITeamMembershipRepository => new InMemoryTeamMembershipRepository(logger),
inject: ['Logger'],
},
{
provide: PENALTY_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IPenaltyRepository => new InMemoryPenaltyRepository(logger),
inject: ['Logger'],
},
{
provide: PROTEST_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IProtestRepository => new InMemoryProtestRepository(logger),
inject: ['Logger'],
},
{
provide: SEASON_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ISeasonRepository => new InMemorySeasonRepository(logger),
inject: ['Logger'],
},
{
provide: SEASON_SPONSORSHIP_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ISeasonSponsorshipRepository => new InMemorySeasonSponsorshipRepository(logger),
inject: ['Logger'],
},
{
provide: LEAGUE_WALLET_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ILeagueWalletRepository => new InMemoryLeagueWalletRepository(logger),
inject: ['Logger'],
},
{
provide: TRANSACTION_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ITransactionRepository => new InMemoryTransactionRepository(logger),
inject: ['Logger'],
},
{
provide: SPONSOR_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ISponsorRepository => new InMemorySponsorRepository(logger),
inject: ['Logger'],
},
{
provide: SPONSORSHIP_PRICING_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ISponsorshipPricingRepository => new InMemorySponsorshipPricingRepository(logger),
inject: ['Logger'],
},
{
provide: SPONSORSHIP_REQUEST_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ISponsorshipRequestRepository => new InMemorySponsorshipRequestRepository(logger),
inject: ['Logger'],
},
],
exports: [
DRIVER_REPOSITORY_TOKEN,
LEAGUE_REPOSITORY_TOKEN,
RACE_REPOSITORY_TOKEN,
RESULT_REPOSITORY_TOKEN,
STANDING_REPOSITORY_TOKEN,
LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
RACE_REGISTRATION_REPOSITORY_TOKEN,
TEAM_REPOSITORY_TOKEN,
TEAM_MEMBERSHIP_REPOSITORY_TOKEN,
PENALTY_REPOSITORY_TOKEN,
PROTEST_REPOSITORY_TOKEN,
SEASON_REPOSITORY_TOKEN,
SEASON_SPONSORSHIP_REPOSITORY_TOKEN,
LEAGUE_WALLET_REPOSITORY_TOKEN,
TRANSACTION_REPOSITORY_TOKEN,
SPONSOR_REPOSITORY_TOKEN,
SPONSORSHIP_PRICING_REPOSITORY_TOKEN,
SPONSORSHIP_REQUEST_REPOSITORY_TOKEN,
],
})
export class InMemoryRacingPersistenceModule {}

View File

@@ -0,0 +1,36 @@
import { Module } from '@nestjs/common';
import { LoggingModule } from '../../domain/logging/LoggingModule';
import type { Logger } from '@core/shared/application/Logger';
import type { IFeedRepository } from '@core/social/domain/repositories/IFeedRepository';
import type { ISocialGraphRepository } from '@core/social/domain/repositories/ISocialGraphRepository';
import {
InMemoryFeedRepository,
InMemorySocialGraphRepository,
} from '@adapters/social/persistence/inmemory/InMemorySocialAndFeed';
export const FEED_REPOSITORY_TOKEN = 'IFeedRepository';
export const SOCIAL_GRAPH_REPOSITORY_TOKEN = 'ISocialGraphRepository';
@Module({
imports: [LoggingModule],
providers: [
{
provide: FEED_REPOSITORY_TOKEN,
useFactory: (logger: Logger): IFeedRepository =>
new InMemoryFeedRepository(logger, { drivers: [], friendships: [], feedEvents: [] }),
inject: ['Logger'],
},
{
provide: SOCIAL_GRAPH_REPOSITORY_TOKEN,
useFactory: (logger: Logger): ISocialGraphRepository =>
new InMemorySocialGraphRepository(logger, { drivers: [], friendships: [], feedEvents: [] }),
inject: ['Logger'],
},
],
exports: [FEED_REPOSITORY_TOKEN, SOCIAL_GRAPH_REPOSITORY_TOKEN],
})
export class InMemorySocialPersistenceModule {}