package response import ( "net/http" "time" apperrors "veza-backend-api/internal/errors" "github.com/gin-gonic/gin" ) // APIResponse is the unified response envelope type APIResponse struct { Success bool `json:"success"` Data interface{} `json:"data,omitempty"` Error interface{} `json:"error,omitempty"` } // Success sends a successful JSON response func Success(c *gin.Context, data interface{}, message ...string) { response := gin.H{ "success": true, "data": data, } if len(message) > 0 { response["message"] = message[0] } c.JSON(http.StatusOK, response) } // Created sends a 201 Created response func Created(c *gin.Context, data interface{}, message ...string) { response := gin.H{ "success": true, "data": data, } if len(message) > 0 { response["message"] = message[0] } c.JSON(http.StatusCreated, response) } // BadRequest sends a 400 Bad Request response // P0: Migré vers format AppError standardisé func BadRequest(c *gin.Context, message string) { Error(c, http.StatusBadRequest, message) } // Unauthorized sends a 401 Unauthorized response // P0: Migré vers format AppError standardisé func Unauthorized(c *gin.Context, message string) { Error(c, http.StatusUnauthorized, message) } // Forbidden sends a 403 Forbidden response // P0: Migré vers format AppError standardisé func Forbidden(c *gin.Context, message string) { Error(c, http.StatusForbidden, message) } // NotFound sends a 404 Not Found response // P0: Migré vers format AppError standardisé func NotFound(c *gin.Context, message string) { Error(c, http.StatusNotFound, message) } // InternalServerError sends a 500 Internal Server Error response // P0: Migré vers format AppError standardisé func InternalServerError(c *gin.Context, message string) { Error(c, http.StatusInternalServerError, message) } // Error sends a custom error response with specified status code // P0: Migré vers format AppError standardisé func Error(c *gin.Context, status int, message string) { // Convertir status HTTP vers ErrorCode var errorCode apperrors.ErrorCode switch status { case http.StatusBadRequest: errorCode = apperrors.ErrCodeValidation case http.StatusUnauthorized: errorCode = apperrors.ErrCodeInvalidCredentials case http.StatusForbidden: errorCode = apperrors.ErrCodeForbidden case http.StatusNotFound: errorCode = apperrors.ErrCodeNotFound case http.StatusConflict: errorCode = apperrors.ErrCodeConflict case http.StatusInternalServerError: errorCode = apperrors.ErrCodeInternal default: errorCode = apperrors.ErrCodeInternal } appErr := apperrors.New(errorCode, message) RespondWithAppError(c, status, appErr) } // RespondWithAppError répond avec une AppError au format standardisé // P0: Helper pour utiliser AppError depuis le package response func RespondWithAppError(c *gin.Context, statusCode int, appErr *apperrors.AppError) { errorData := struct { Code int `json:"code"` Message string `json:"message"` Details []apperrors.ErrorDetail `json:"details,omitempty"` RequestID string `json:"request_id,omitempty"` Timestamp string `json:"timestamp"` Context map[string]interface{} `json:"context,omitempty"` }{ Code: int(appErr.Code), Message: appErr.Message, Details: appErr.Details, RequestID: c.GetString("request_id"), Timestamp: time.Now().UTC().Format(time.RFC3339), Context: appErr.Context, } // Utiliser la structure APIResponse standardisée type APIResponse struct { Success bool `json:"success"` Data interface{} `json:"data,omitempty"` Error interface{} `json:"error,omitempty"` } c.JSON(statusCode, APIResponse{ Success: false, Data: nil, Error: errorData, }) } // ValidationError sends a 400 Bad Request response with detailed validation errors // P0: Migré vers format AppError standardisé func ValidationError(c *gin.Context, message string, details map[string]string) { errorDetails := make([]apperrors.ErrorDetail, 0, len(details)) for field, msg := range details { errorDetails = append(errorDetails, apperrors.ErrorDetail{ Field: field, Message: msg, }) } appErr := apperrors.NewValidationError(message, errorDetails...) RespondWithAppError(c, http.StatusBadRequest, appErr) }