github.com/99designs/gqlgen@v0.17.45/graphql/context_path.go (about) 1 package graphql 2 3 import ( 4 "context" 5 6 "github.com/vektah/gqlparser/v2/ast" 7 ) 8 9 const fieldInputCtx key = "path_context" 10 11 type PathContext struct { 12 ParentField *FieldContext 13 Parent *PathContext 14 Field *string 15 Index *int 16 } 17 18 func (fic *PathContext) Path() ast.Path { 19 var path ast.Path 20 for it := fic; it != nil; it = it.Parent { 21 if it.Index != nil { 22 path = append(path, ast.PathIndex(*it.Index)) 23 } else if it.Field != nil { 24 path = append(path, ast.PathName(*it.Field)) 25 } 26 } 27 28 // because we are walking up the chain, all the elements are backwards, do an inplace flip. 29 for i := len(path)/2 - 1; i >= 0; i-- { 30 opp := len(path) - 1 - i 31 path[i], path[opp] = path[opp], path[i] 32 } 33 34 if fic.ParentField != nil { 35 fieldPath := fic.ParentField.Path() 36 return append(fieldPath, path...) 37 38 } 39 40 return path 41 } 42 43 func NewPathWithField(field string) *PathContext { 44 return &PathContext{Field: &field} 45 } 46 47 func NewPathWithIndex(index int) *PathContext { 48 return &PathContext{Index: &index} 49 } 50 51 func WithPathContext(ctx context.Context, fic *PathContext) context.Context { 52 if fieldContext := GetFieldContext(ctx); fieldContext != nil { 53 fic.ParentField = fieldContext 54 } 55 if fieldInputContext := GetPathContext(ctx); fieldInputContext != nil { 56 fic.Parent = fieldInputContext 57 } 58 59 return context.WithValue(ctx, fieldInputCtx, fic) 60 } 61 62 func GetPathContext(ctx context.Context) *PathContext { 63 if val, ok := ctx.Value(fieldInputCtx).(*PathContext); ok { 64 return val 65 } 66 return nil 67 } 68 69 func GetPath(ctx context.Context) ast.Path { 70 if pc := GetPathContext(ctx); pc != nil { 71 return pc.Path() 72 } 73 if fc := GetFieldContext(ctx); fc != nil { 74 return fc.Path() 75 } 76 return nil 77 }