export interface FieldValidationError { field: string; code: string; } export interface SaveFailure { message: string; fieldErrors: FieldValidationError[]; } export function httpErrorMessage(error: unknown, fallback: string): string { return typeof error === 'object' && error !== null && 'error' in error && typeof error.error === 'object' && error.error !== null && 'message' in error.error && typeof error.error.message === 'string' ? error.error.message : fallback; } export function saveFailure(error: unknown, fallback: string): SaveFailure { const validationErrors = validationErrorsFrom(error); if (validationErrors) { return { message: 'Veuillez corriger les champs signalés.', fieldErrors: validationErrors, }; } return { message: isConflict(error) ? httpErrorMessage(error, fallback) : fallback, fieldErrors: [], }; } function validationErrorsFrom(error: unknown): FieldValidationError[] | null { if ( typeof error !== 'object' || error === null || !('error' in error) || typeof error.error !== 'object' || error.error === null || !('code' in error.error) || error.error.code !== 'validation_failed' || !('errors' in error.error) || !Array.isArray(error.error.errors) ) { return null; } const fieldErrors = error.error.errors.filter( (fieldError): fieldError is FieldValidationError => typeof fieldError === 'object' && fieldError !== null && 'field' in fieldError && typeof fieldError.field === 'string' && 'code' in fieldError && typeof fieldError.code === 'string', ); return fieldErrors.length === error.error.errors.length ? fieldErrors : null; } function isConflict(error: unknown): error is { status: number } { return typeof error === 'object' && error !== null && 'status' in error && error.status === 409; }