This commit is contained in:
2025-12-16 15:42:38 +01:00
parent 29410708c8
commit 362894d1a5
147 changed files with 780 additions and 375 deletions

View File

@@ -1,13 +1,19 @@
import { SignupWithEmailUseCase } from '@core/identity/application/use-cases/SignupWithEmailUseCase';
/** import { SignupWithEmailUseCase } from '@core/identity/application/use-cases/SignupWithEmailUseCase';
* EnsureInitialData - Bootstrap script to ensure initial data exists. import { CreateAchievementUseCase } from '@core/identity/application/use-cases/achievement/CreateAchievementUseCase';
* Idempotent: Can be run multiple times without issues. import type { Logger } from '@core/shared/application/Logger';
* Calls core use cases to create initial admin user if not exists. import {
*/ DRIVER_ACHIEVEMENTS,
STEWARD_ACHIEVEMENTS,
ADMIN_ACHIEVEMENTS,
COMMUNITY_ACHIEVEMENTS,
} from '@core/identity/domain/AchievementConstants';
export class EnsureInitialData { export class EnsureInitialData {
constructor( constructor(
private readonly signupUseCase: SignupWithEmailUseCase, private readonly signupUseCase: SignupWithEmailUseCase,
private readonly createAchievementUseCase: CreateAchievementUseCase,
private readonly logger: Logger,
) {} ) {}
async execute(): Promise<void> { async execute(): Promise<void> {
@@ -18,17 +24,38 @@ export class EnsureInitialData {
password: 'admin123', password: 'admin123',
displayName: 'Admin', displayName: 'Admin',
}); });
// User created successfully this.logger.info('[Bootstrap] Initial admin user created');
} catch (error) { } catch (error) {
if (error instanceof Error && error.message === 'An account with this email already exists') { if (error instanceof Error && error.message === 'An account with this email already exists') {
// User already exists, nothing to do // User already exists, nothing to do
return; this.logger.info('[Bootstrap] Admin user already exists');
} else {
// Re-throw other errors
throw error;
} }
// Re-throw other errors
throw error;
} }
// Future: Add more initial data creation here // Ensure initial achievements exist
// e.g., create default league, config, etc. const allAchievements = [
...DRIVER_ACHIEVEMENTS,
...STEWARD_ACHIEVEMENTS,
...ADMIN_ACHIEVEMENTS,
...COMMUNITY_ACHIEVEMENTS,
];
let createdCount = 0;
let existingCount = 0;
for (const achievementProps of allAchievements) {
try {
await this.createAchievementUseCase.execute(achievementProps);
createdCount++;
} catch {
// If achievement already exists, that's fine
existingCount++;
}
}
this.logger.info(`[Bootstrap] Achievements: ${createdCount} created, ${existingCount} already exist`);
} }
} }

View File

@@ -0,0 +1,19 @@
import { IAchievementRepository } from "@core/identity/application/use-cases/achievement/CreateAchievementUseCase";
import { Achievement } from "@core/identity/domain/entities/Achievement";
export class InMemoryAchievementRepository implements IAchievementRepository {
private readonly achievements: Map<string, Achievement> = new Map();
async save(achievement: Achievement): Promise<void> {
this.achievements.set(achievement.id, achievement);
}
async findById(id: string): Promise<Achievement | null> {
return this.achievements.get(id) || null;
}
async findAll(): Promise<Achievement[]> {
return Array.from(this.achievements.values());
}
}

View File

@@ -1,21 +1,12 @@
{ {
"extends": "../tsconfig.base.json", "extends": "../tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"rootDir": ".", "outDir": "../dist/adapters",
"outDir": "dist",
"baseUrl": ".",
"composite": true,
"declaration": true, "declaration": true,
"declarationMap": true, "declarationMap": true,
"sourceMap": true, "sourceMap": true,
"types": ["vitest/globals"], "types": ["vitest/globals"]
"paths": {
"@/*": ["./*"],
"@core/*": ["../core/*"],
"@adapters/*": ["./*"],
"@testing/*": ["../testing/*"]
}
}, },
"include": ["**/*.ts"], "include": ["**/*.ts", "../core/**/*.ts"],
"exclude": ["node_modules", "dist"] "exclude": ["node_modules", "dist"]
} }

View File

@@ -2,22 +2,24 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { HelloController } from './presentation/hello.controller'; import { HelloController } from './presentation/hello.controller';
import { HelloService } from './application/hello/hello.service'; import { HelloService } from './application/hello/hello.service';
import { AnalyticsModule } from './modules/analytics/AnalyticsModule'; import { AnalyticsModule } from './domain/analytics/AnalyticsModule';
import { DatabaseModule } from './infrastructure/database/database.module'; import { DatabaseModule } from './infrastructure/database/database.module';
import { LoggingModule } from './infrastructure/logging/LoggingModule'; import { LoggingModule } from './infrastructure/logging/LoggingModule';
import { AuthModule } from './modules/auth/AuthModule'; import { BootstrapModule } from './infrastructure/bootstrap/BootstrapModule';
import { LeagueModule } from './modules/league/LeagueModule'; import { AuthModule } from './domain/auth/AuthModule';
import { RaceModule } from './modules/race/RaceModule'; import { LeagueModule } from './domain/league/LeagueModule';
import { TeamModule } from './modules/team/TeamModule'; import { RaceModule } from './domain/race/RaceModule';
import { SponsorModule } from './modules/sponsor/SponsorModule'; import { TeamModule } from './domain/team/TeamModule';
import { DriverModule } from './modules/driver/DriverModule'; import { SponsorModule } from './domain/sponsor/SponsorModule';
import { MediaModule } from './modules/media/MediaModule'; import { DriverModule } from './domain/driver/DriverModule';
import { PaymentsModule } from './modules/payments/PaymentsModule'; import { MediaModule } from './domain/media/MediaModule';
import { PaymentsModule } from './domain/payments/PaymentsModule';
@Module({ @Module({
imports: [ imports: [
DatabaseModule, DatabaseModule,
LoggingModule, LoggingModule,
BootstrapModule,
AnalyticsModule, AnalyticsModule,
AuthModule, AuthModule,
LeagueModule, LeagueModule,

Some files were not shown because too many files have changed in this diff Show More