59 lines
1.4 KiB
Go
59 lines
1.4 KiB
Go
|
|
package presenter
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
"log/slog"
|
||
|
|
|
||
|
|
"github.com/99designs/gqlgen/graphql"
|
||
|
|
"github.com/vektah/gqlparser/v2/gqlerror"
|
||
|
|
)
|
||
|
|
|
||
|
|
func New[C ~string, E ~string](logger *slog.Logger, codes []C, entities []E, internalErrorCode C) func(ctx context.Context, e error) *gqlerror.Error {
|
||
|
|
return func(ctx context.Context, e error) *gqlerror.Error {
|
||
|
|
err := graphql.DefaultErrorPresenter(ctx, e)
|
||
|
|
var codedError CodedError
|
||
|
|
if errors.As(e, &codedError) {
|
||
|
|
code := toModelErrorCode(codedError.Code, codes, internalErrorCode)
|
||
|
|
errorEntity := toModelErrorEntity(codedError.Entity, entities)
|
||
|
|
extensions := map[string]interface{}{"code": code}
|
||
|
|
if len(errorEntity) > 0 {
|
||
|
|
extensions["errorEntity"] = errorEntity
|
||
|
|
}
|
||
|
|
if len(codedError.Params) > 0 {
|
||
|
|
extensions["params"] = codedError.Params
|
||
|
|
}
|
||
|
|
err.Extensions = extensions
|
||
|
|
} else {
|
||
|
|
err.Extensions = map[string]interface{}{"code": internalErrorCode}
|
||
|
|
}
|
||
|
|
if logError(e) {
|
||
|
|
logger.ErrorContext(ctx, fmt.Sprintf("%v", e))
|
||
|
|
}
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func logError(err error) bool {
|
||
|
|
return !errors.Is(err, context.Canceled)
|
||
|
|
}
|
||
|
|
|
||
|
|
func toModelErrorCode[C ~string](code Code, codes []C, internalErrorCode C) C {
|
||
|
|
for _, c := range codes {
|
||
|
|
if string(c) == string(code) {
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return internalErrorCode
|
||
|
|
}
|
||
|
|
|
||
|
|
func toModelErrorEntity[E ~string](entity Entity, entities []E) E {
|
||
|
|
for _, e := range entities {
|
||
|
|
if string(e) == string(entity) {
|
||
|
|
return e
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return ""
|
||
|
|
}
|