package gqlerror import ( "bytes" "fmt" "strconv" "github.com/vektah/gqlparser/ast" ) // Error is the standard graphql error type described in https://facebook.github.io/graphql/draft/#sec-Errors type Error struct { Message string `json:"message"` Path []interface{} `json:"path,omitempty"` Locations []Location `json:"locations,omitempty"` Extensions map[string]interface{} `json:"extensions,omitempty"` Rule string `json:"-"` } func (err *Error) SetFile(file string) { if file == "" { return } if err.Extensions == nil { err.Extensions = map[string]interface{}{} } err.Extensions["file"] = file } type Location struct { Line int `json:"line,omitempty"` Column int `json:"column,omitempty"` } type List []*Error func (err *Error) Error() string { var res bytes.Buffer if err == nil { return "" } filename, _ := err.Extensions["file"].(string) if filename == "" { filename = "input" } res.WriteString(filename) if len(err.Locations) > 0 { res.WriteByte(':') res.WriteString(strconv.Itoa(err.Locations[0].Line)) } res.WriteString(": ") if ps := err.pathString(); ps != "" { res.WriteString(ps) res.WriteByte(' ') } res.WriteString(err.Message) return res.String() } func (err Error) pathString() string { var str bytes.Buffer for i, v := range err.Path { switch v := v.(type) { case int, int64: str.WriteString(fmt.Sprintf("[%d]", v)) default: if i != 0 { str.WriteByte('.') } str.WriteString(fmt.Sprint(v)) } } return str.String() } func (errs List) Error() string { var buf bytes.Buffer for _, err := range errs { buf.WriteString(err.Error()) buf.WriteByte('\n') } return buf.String() } func WrapPath(path []interface{}, err error) *Error { return &Error{ Message: err.Error(), Path: path, } } func Errorf(message string, args ...interface{}) *Error { return &Error{ Message: fmt.Sprintf(message, args...), } } func ErrorPathf(path []interface{}, message string, args ...interface{}) *Error { return &Error{ Message: fmt.Sprintf(message, args...), Path: path, } } func ErrorPosf(pos *ast.Position, message string, args ...interface{}) *Error { return ErrorLocf( pos.Src.Name, pos.Line, pos.Column, message, args..., ) } func ErrorLocf(file string, line int, col int, message string, args ...interface{}) *Error { var extensions map[string]interface{} if file != "" { extensions = map[string]interface{}{"file": file} } return &Error{ Message: fmt.Sprintf(message, args...), Extensions: extensions, Locations: []Location{ {Line: line, Column: col}, }, } }