package graphql import ( "context" "errors" "tercul/internal/domain" "github.com/99designs/gqlgen/graphql" "github.com/vektah/gqlparser/v2/gqlerror" ) // NewErrorPresenter creates a custom error presenter for gqlgen. func NewErrorPresenter() graphql.ErrorPresenterFunc { return func(ctx context.Context, e error) *gqlerror.Error { gqlErr := graphql.DefaultErrorPresenter(ctx, e) // Unwrap the error to find the root cause. originalErr := errors.Unwrap(e) if originalErr == nil { originalErr = e } // Check for custom application errors and format them. switch { case errors.Is(originalErr, domain.ErrNotFound): gqlErr.Message = "The requested resource was not found." gqlErr.Extensions = map[string]interface{}{"code": "NOT_FOUND"} case errors.Is(originalErr, domain.ErrUnauthorized): gqlErr.Message = "You must be logged in to perform this action." gqlErr.Extensions = map[string]interface{}{"code": "UNAUTHENTICATED"} case errors.Is(originalErr, domain.ErrForbidden): gqlErr.Message = "You are not authorized to perform this action." gqlErr.Extensions = map[string]interface{}{"code": "FORBIDDEN"} case errors.Is(originalErr, domain.ErrValidation): // Keep the detailed message from the validation error. gqlErr.Message = originalErr.Error() gqlErr.Extensions = map[string]interface{}{"code": "VALIDATION_FAILED"} case errors.Is(originalErr, domain.ErrConflict): gqlErr.Message = "A conflict occurred with the current state of the resource." gqlErr.Extensions = map[string]interface{}{"code": "CONFLICT"} default: // For all other errors, return a generic message to avoid leaking implementation details. gqlErr.Message = "An unexpected internal error occurred." gqlErr.Extensions = map[string]interface{}{"code": "INTERNAL_SERVER_ERROR"} } return gqlErr } }