[INT-API-003] Standardize error handling across all services

This commit is contained in:
senke 2025-12-25 22:42:07 +01:00
parent 4c98715877
commit c2af450fd5
2 changed files with 38 additions and 63 deletions

View file

@ -500,7 +500,8 @@
"description": "Tous les services API doivent utiliser la même méthode de gestion d'erreurs.",
"priority": "P1",
"priority_rank": 14,
"status": "todo",
"status": "completed",
"completed_at": "2025-01-27T15:00:00Z",
"estimated_hours": 2,
"side": "frontend_only",
"files_to_modify": [
@ -1095,13 +1096,13 @@
},
"progress_tracking": {
"total_tasks": 32,
"completed": 13,
"completed": 14,
"in_progress": 0,
"todo": 19,
"todo": 18,
"blocked": 0,
"completion_percentage": 41,
"last_updated": "2025-01-27T14:45:00Z",
"completion_percentage": 44,
"last_updated": "2025-01-27T15:00:00Z",
"estimated_completion_date": null,
"estimated_hours_remaining": 29.5
"estimated_hours_remaining": 27.5
}
}

View file

@ -1,5 +1,5 @@
import { apiClient } from '@/services/api/client';
import axios, { AxiosError } from 'axios';
import { handleApiServiceError } from '@/utils/serviceErrorHandler';
import type {
LoginFormData,
RegisterFormData,
@ -23,65 +23,25 @@ export interface AuthResponse {
requires_2fa?: boolean; // BE-API-001: Flag indicating 2FA is required
}
export interface ApiError {
message: string;
code?: string;
details?: Record<string, unknown>;
}
/**
* Gère les erreurs API de manière standardisée
*/
function handleApiError(error: unknown): never {
if (axios.isAxiosError(error)) {
const axiosError = error as AxiosError<{
error?: string;
message?: string;
}>;
if (axiosError.response) {
// Erreur de réponse du serveur
const errorMessage =
axiosError.response.data?.error ||
axiosError.response.data?.message ||
'An error occurred';
const apiError: ApiError = {
message: errorMessage,
code: axiosError.response.status.toString(),
details: axiosError.response.data as Record<string, unknown>,
};
throw apiError;
} else if (axiosError.request) {
// Requête envoyée mais pas de réponse
throw {
message: 'Network error: Unable to connect to server',
code: 'NETWORK_ERROR',
} as ApiError;
}
}
// Erreur inconnue
throw {
message:
error instanceof Error ? error.message : 'An unexpected error occurred',
code: 'UNKNOWN_ERROR',
} as ApiError;
}
/**
* Authentifie un utilisateur avec email et mot de passe
* @param data - Données de connexion (email, password)
* @returns Promise avec les tokens et les informations utilisateur
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
export async function login(data: LoginFormData): Promise<AuthResponse> {
try {
const response = await apiClient.post<AuthResponse>('/auth/login', data);
return response.data;
} catch (error) {
return handleApiError(error);
handleApiServiceError(error, {
context: 'auth',
customMessages: {
401: 'Email ou mot de passe incorrect',
403: 'Votre compte n\'est pas vérifié. Veuillez vérifier votre email.',
},
});
}
}
@ -91,6 +51,7 @@ export async function login(data: LoginFormData): Promise<AuthResponse> {
* @returns Promise avec les tokens et les informations utilisateur
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
export async function register(data: RegisterFormData): Promise<AuthResponse> {
try {
const response = await apiClient.post<AuthResponse>('/auth/register', {
@ -101,7 +62,13 @@ export async function register(data: RegisterFormData): Promise<AuthResponse> {
});
return response.data;
} catch (error) {
return handleApiError(error);
handleApiServiceError(error, {
context: 'auth',
customMessages: {
409: 'Cet email ou ce nom d\'utilisateur est déjà utilisé',
400: 'Les données fournies sont invalides',
},
});
}
}
@ -109,11 +76,12 @@ export async function register(data: RegisterFormData): Promise<AuthResponse> {
* Déconnecte l'utilisateur actuel
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
export async function logout(): Promise<void> {
try {
await apiClient.post('/auth/logout');
} catch (error) {
return handleApiError(error);
handleApiServiceError(error, { context: 'auth' });
}
}
@ -123,6 +91,7 @@ export async function logout(): Promise<void> {
* @returns Promise avec les nouveaux tokens et les informations utilisateur
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
export async function refreshToken(
refreshToken: string,
): Promise<AuthResponse> {
@ -132,7 +101,7 @@ export async function refreshToken(
});
return response.data;
} catch (error) {
return handleApiError(error);
handleApiServiceError(error, { context: 'auth' });
}
}
@ -141,13 +110,14 @@ export async function refreshToken(
* @param data - Données contenant l'email
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
export async function requestPasswordReset(
data: ForgotPasswordFormData,
): Promise<void> {
try {
await apiClient.post('/auth/password/reset-request', data);
} catch (error) {
return handleApiError(error);
handleApiServiceError(error, { context: 'auth' });
}
}
@ -156,6 +126,7 @@ export async function requestPasswordReset(
* @param data - Données contenant le token et le nouveau mot de passe
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
export async function resetPassword(
data: ResetPasswordFormData,
): Promise<void> {
@ -165,7 +136,7 @@ export async function resetPassword(
password: data.password,
});
} catch (error) {
return handleApiError(error);
handleApiServiceError(error, { context: 'auth' });
}
}
@ -174,11 +145,12 @@ export async function resetPassword(
* @param token - Token de vérification
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
export async function verifyEmail(token: string): Promise<void> {
try {
await apiClient.get(`/auth/verify-email?token=${token}`);
} catch (error) {
return handleApiError(error);
handleApiServiceError(error, { context: 'auth' });
}
}
@ -187,11 +159,12 @@ export async function verifyEmail(token: string): Promise<void> {
* @param email - Email de l'utilisateur
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
export async function resendVerificationEmail(email: string): Promise<void> {
try {
await apiClient.post('/auth/resend-verification', { email });
} catch (error) {
return handleApiError(error);
handleApiServiceError(error, { context: 'auth' });
}
}
@ -201,6 +174,7 @@ export async function resendVerificationEmail(email: string): Promise<void> {
* @returns Promise avec true si disponible, false sinon
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
export async function checkUsernameAvailability(
username: string,
): Promise<boolean> {
@ -210,6 +184,6 @@ export async function checkUsernameAvailability(
);
return response.data.available;
} catch (error) {
return handleApiError(error);
handleApiServiceError(error, { context: 'auth' });
}
}