github.com/dgraph-io/dgraph@v1.2.8/graphql/schema/errors.go (about)

     1  /*
     2   * Copyright 2019 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package schema
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/dgraph-io/dgraph/x"
    23  	"github.com/vektah/gqlparser/gqlerror"
    24  )
    25  
    26  // AsGQLErrors formats an error as a list of GraphQL errors.
    27  // A []*x.GqlError (x.GqlErrorList) gets returned as is, an x.GqlError gets returned as a one
    28  // item list, and all other errors get printed into a x.GqlError .  A nil input results
    29  // in nil output.
    30  func AsGQLErrors(err error) x.GqlErrorList {
    31  	if err == nil {
    32  		return nil
    33  	}
    34  
    35  	switch e := err.(type) {
    36  	case *gqlerror.Error:
    37  		return x.GqlErrorList{toGqlError(e)}
    38  	case *x.GqlError:
    39  		return x.GqlErrorList{e}
    40  	case gqlerror.List:
    41  		return toGqlErrorList(e)
    42  	case x.GqlErrorList:
    43  		return e
    44  	default:
    45  		return x.GqlErrorList{&x.GqlError{Message: e.Error()}}
    46  	}
    47  }
    48  
    49  func toGqlError(err *gqlerror.Error) *x.GqlError {
    50  	return &x.GqlError{
    51  		Message:   err.Message,
    52  		Locations: convertLocations(err.Locations),
    53  		Path:      err.Path,
    54  	}
    55  }
    56  
    57  func toGqlErrorList(errs gqlerror.List) x.GqlErrorList {
    58  	var result x.GqlErrorList
    59  	for _, err := range errs {
    60  		result = append(result, toGqlError(err))
    61  	}
    62  	return result
    63  }
    64  
    65  func convertLocations(locs []gqlerror.Location) []x.Location {
    66  	var result []x.Location
    67  	for _, loc := range locs {
    68  		result = append(result, x.Location{Line: loc.Line, Column: loc.Column})
    69  	}
    70  	return result
    71  }
    72  
    73  // GQLWrapf takes an existing error and wraps it as a GraphQL error.
    74  // If err is already a GraphQL error, any location information is kept in the
    75  // new error.  If err is nil, GQLWrapf returns nil.
    76  //
    77  // Wrapping GraphQL errors like this allows us to bubble errors up the stack
    78  // and add context, location and path info to them as we go.
    79  func GQLWrapf(err error, format string, args ...interface{}) error {
    80  	if err == nil {
    81  		return nil
    82  	}
    83  
    84  	switch err := err.(type) {
    85  	case *x.GqlError:
    86  		return x.GqlErrorf("%s because %s", fmt.Sprintf(format, args...), err.Message).
    87  			WithLocations(err.Locations...).
    88  			WithPath(err.Path)
    89  	case x.GqlErrorList:
    90  		var errs x.GqlErrorList
    91  		for _, e := range err {
    92  			errs = append(errs, GQLWrapf(e, format, args...).(*x.GqlError))
    93  		}
    94  		return errs
    95  	default:
    96  		return x.GqlErrorf("%s because %s", fmt.Sprintf(format, args...), err.Error())
    97  	}
    98  }
    99  
   100  // GQLWrapLocationf wraps an error as a GraphQL error and includes location
   101  // information in the GraphQL error.
   102  func GQLWrapLocationf(err error, loc x.Location, format string, args ...interface{}) error {
   103  	wrapped := GQLWrapf(err, format, args...)
   104  	if wrapped == nil {
   105  		return nil
   106  	}
   107  
   108  	switch wrapped := wrapped.(type) {
   109  	case *x.GqlError:
   110  		return wrapped.WithLocations(loc)
   111  	case x.GqlErrorList:
   112  		for _, e := range wrapped {
   113  			_ = e.WithLocations(loc)
   114  		}
   115  	}
   116  	return wrapped
   117  }
   118  
   119  // AppendGQLErrs builds a list of GraphQL errors from err1 and err2, if both
   120  // are nil, the result is nil.
   121  func AppendGQLErrs(err1, err2 error) error {
   122  	if err1 == nil && err2 == nil {
   123  		return nil
   124  	}
   125  	if err1 == nil {
   126  		return AsGQLErrors(err2)
   127  	}
   128  	if err2 == nil {
   129  		return AsGQLErrors(err1)
   130  	}
   131  	return append(AsGQLErrors(err1), AsGQLErrors(err2)...)
   132  }