feat(service): CardService générique sur l'abstraction CardRepository

This commit is contained in:
devcodetools committed 2026-09-21 17:58:59 +02:00
1 parent a3d9be86d8
commit 12670b7134
3 files changed
+83

No files matched your search

+25
View File
@@ -0,0 +1,25 @@
import { NextResponse, type NextRequest } from 'next/server'
import { ZodError } from 'zod'
import { AppError, ValidationError } from '@/domain/errors'
export function handleError(error: unknown): NextResponse {
if (error instanceof ZodError) {
return NextResponse.json(
{ error: 'ValidationError', message: 'Payload invalide', issues: error.flatten() },
{ status: 400 },
)
}
if (error instanceof AppError) {
return NextResponse.json({ error: error.name, message: error.message }, { status: error.status })
}
console.error(error)
return NextResponse.json({ error: 'InternalServerError', message: 'Erreur interne' }, { status: 500 })
}
export async function parseJsonBody(request: NextRequest): Promise<unknown> {
try {
return await request.json()
} catch {
throw new ValidationError('Corps de requête invalide (JSON attendu)')
}
}
+6
View File
@@ -0,0 +1,6 @@
import { getCardRepository } from '@/config/card-repository-factory'
import { CardService } from './card-service'
export function getCardService(): CardService {
return new CardService(getCardRepository())
}
+52
View File
@@ -0,0 +1,52 @@
import type { Card, CardInput } from '@/domain/card'
import type { CardRepository } from '@/domain/card-repository'
import { NotFoundError } from '@/domain/errors'
export class CardService {
constructor(private readonly repository: CardRepository) {}
async list(): Promise<Card[]> {
return this.repository.findAll()
}
async get(id: string): Promise<Card> {
const card = await this.repository.findById(id)
if (!card) {
throw new NotFoundError(`Carte ${id} introuvable`)
}
return card
}
async create(input: CardInput): Promise<Card> {
return this.repository.create(input)
}
async update(id: string, input: Partial<CardInput>): Promise<Card> {
const card = await this.repository.update(id, input)
if (!card) {
throw new NotFoundError(`Carte ${id} introuvable`)
}
return card
}
async remove(id: string): Promise<void> {
const deleted = await this.repository.delete(id)
if (!deleted) {
throw new NotFoundError(`Carte ${id} introuvable`)
}
}
async random(theme?: string): Promise<Card> {
const card = theme
? await this.repository.findRandomByTheme(theme)
: await this.repository.findRandom()
if (!card) {
throw new NotFoundError(theme ? `Aucune carte pour le thème ${theme}` : 'Aucune carte disponible')
}
return card
}
async themes(): Promise<string[]> {
return this.repository.findThemes()
}
}