mirror of
https://github.com/zhigang1992/graphql-engine.git
synced 2026-05-12 17:48:12 +08:00
Co-authored-by: Rishichandra Wawhal <rishichandra.wawhal@gmail.com> Co-authored-by: Rikin Kachhia <54616969+rikinsk@users.noreply.github.com> Co-authored-by: Aravind <aravindkp@outlook.in> Co-authored-by: Anon Ray <ecthiender@users.noreply.github.com> Co-authored-by: Shahidh K Muhammed <muhammedshahid.k@gmail.com>
953 lines
29 KiB
Go
953 lines
29 KiB
Go
package printer
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"reflect"
|
|
|
|
"github.com/graphql-go/graphql/language/ast"
|
|
"github.com/graphql-go/graphql/language/visitor"
|
|
)
|
|
|
|
func getMapValue(m map[string]interface{}, key string) interface{} {
|
|
tokens := strings.Split(key, ".")
|
|
valMap := m
|
|
for _, token := range tokens {
|
|
v, ok := valMap[token]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
switch v := v.(type) {
|
|
case []interface{}:
|
|
return v
|
|
case map[string]interface{}:
|
|
valMap = v
|
|
continue
|
|
default:
|
|
return v
|
|
}
|
|
}
|
|
return valMap
|
|
}
|
|
func getMapSliceValue(m map[string]interface{}, key string) []interface{} {
|
|
tokens := strings.Split(key, ".")
|
|
valMap := m
|
|
for _, token := range tokens {
|
|
v, ok := valMap[token]
|
|
if !ok {
|
|
return []interface{}{}
|
|
}
|
|
switch v := v.(type) {
|
|
case []interface{}:
|
|
return v
|
|
default:
|
|
return []interface{}{}
|
|
}
|
|
}
|
|
return []interface{}{}
|
|
}
|
|
func getMapValueString(m map[string]interface{}, key string) string {
|
|
tokens := strings.Split(key, ".")
|
|
valMap := m
|
|
for _, token := range tokens {
|
|
v, ok := valMap[token]
|
|
if !ok {
|
|
return ""
|
|
}
|
|
if v == nil {
|
|
return ""
|
|
}
|
|
switch v := v.(type) {
|
|
case map[string]interface{}:
|
|
valMap = v
|
|
continue
|
|
case string:
|
|
return v
|
|
default:
|
|
return fmt.Sprintf("%v", v)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
func getDescription(raw interface{}) string {
|
|
var desc string
|
|
|
|
switch node := raw.(type) {
|
|
case ast.DescribableNode:
|
|
if sval := node.GetDescription(); sval != nil {
|
|
desc = sval.Value
|
|
}
|
|
case map[string]interface{}:
|
|
desc = getMapValueString(node, "Description.Value")
|
|
}
|
|
if desc != "" {
|
|
sep := ""
|
|
if strings.ContainsRune(desc, '\n') {
|
|
sep = "\n"
|
|
}
|
|
desc = join([]string{`"""`, desc, `"""`}, sep)
|
|
}
|
|
return desc
|
|
}
|
|
|
|
func toSliceString(slice interface{}) []string {
|
|
if slice == nil {
|
|
return []string{}
|
|
}
|
|
res := []string{}
|
|
switch reflect.TypeOf(slice).Kind() {
|
|
case reflect.Slice:
|
|
s := reflect.ValueOf(slice)
|
|
for i := 0; i < s.Len(); i++ {
|
|
elem := s.Index(i)
|
|
elemInterface := elem.Interface()
|
|
if elem, ok := elemInterface.(string); ok {
|
|
res = append(res, elem)
|
|
}
|
|
}
|
|
return res
|
|
default:
|
|
return res
|
|
}
|
|
}
|
|
|
|
func join(str []string, sep string) string {
|
|
ss := []string{}
|
|
// filter out empty strings
|
|
for _, s := range str {
|
|
if s == "" {
|
|
continue
|
|
}
|
|
ss = append(ss, s)
|
|
}
|
|
return strings.Join(ss, sep)
|
|
}
|
|
|
|
func wrap(start, maybeString, end string) string {
|
|
if maybeString == "" {
|
|
return maybeString
|
|
}
|
|
return start + maybeString + end
|
|
}
|
|
|
|
// Given array, print each item on its own line, wrapped in an indented "{ }" block.
|
|
func block(maybeArray interface{}) string {
|
|
s := toSliceString(maybeArray)
|
|
if len(s) == 0 {
|
|
return "{}"
|
|
}
|
|
return indent("{\n"+join(s, "\n")) + "\n}"
|
|
}
|
|
|
|
func indent(maybeString interface{}) string {
|
|
if maybeString == nil {
|
|
return ""
|
|
}
|
|
switch str := maybeString.(type) {
|
|
case string:
|
|
return strings.Replace(str, "\n", "\n ", -1)
|
|
}
|
|
return ""
|
|
}
|
|
|
|
var printDocASTReducer = map[string]visitor.VisitFunc{
|
|
"Name": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.Name:
|
|
return visitor.ActionUpdate, node.Value
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, getMapValue(node, "Value")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"Variable": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.Variable:
|
|
return visitor.ActionUpdate, fmt.Sprintf("$%v", node.Name)
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, "$" + getMapValueString(node, "Name")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
|
|
// Document
|
|
"Document": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.Document:
|
|
definitions := toSliceString(node.Definitions)
|
|
return visitor.ActionUpdate, join(definitions, "\n\n") + "\n"
|
|
case map[string]interface{}:
|
|
definitions := toSliceString(getMapValue(node, "Definitions"))
|
|
return visitor.ActionUpdate, join(definitions, "\n\n") + "\n"
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"OperationDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.OperationDefinition:
|
|
op := string(node.Operation)
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
|
|
varDefs := wrap("(", join(toSliceString(node.VariableDefinitions), ", "), ")")
|
|
directives := join(toSliceString(node.Directives), " ")
|
|
selectionSet := fmt.Sprintf("%v", node.SelectionSet)
|
|
// Anonymous queries with no directives or variable definitions can use
|
|
// the query short form.
|
|
str := ""
|
|
if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery {
|
|
str = selectionSet
|
|
} else {
|
|
str = join([]string{
|
|
op,
|
|
join([]string{name, varDefs}, ""),
|
|
directives,
|
|
selectionSet,
|
|
}, " ")
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
|
|
op := getMapValueString(node, "Operation")
|
|
name := getMapValueString(node, "Name")
|
|
|
|
varDefs := wrap("(", join(toSliceString(getMapValue(node, "VariableDefinitions")), ", "), ")")
|
|
directives := join(toSliceString(getMapValue(node, "Directives")), " ")
|
|
selectionSet := getMapValueString(node, "SelectionSet")
|
|
str := ""
|
|
if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery {
|
|
str = selectionSet
|
|
} else {
|
|
str = join([]string{
|
|
op,
|
|
join([]string{name, varDefs}, ""),
|
|
directives,
|
|
selectionSet,
|
|
}, " ")
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"VariableDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.VariableDefinition:
|
|
variable := fmt.Sprintf("%v", node.Variable)
|
|
ttype := fmt.Sprintf("%v", node.Type)
|
|
defaultValue := fmt.Sprintf("%v", node.DefaultValue)
|
|
|
|
return visitor.ActionUpdate, variable + ": " + ttype + wrap(" = ", defaultValue, "")
|
|
case map[string]interface{}:
|
|
|
|
variable := getMapValueString(node, "Variable")
|
|
ttype := getMapValueString(node, "Type")
|
|
defaultValue := getMapValueString(node, "DefaultValue")
|
|
|
|
return visitor.ActionUpdate, variable + ": " + ttype + wrap(" = ", defaultValue, "")
|
|
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"SelectionSet": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.SelectionSet:
|
|
str := block(node.Selections)
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
selections := getMapValue(node, "Selections")
|
|
str := block(selections)
|
|
return visitor.ActionUpdate, str
|
|
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"Field": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.Argument:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
value := fmt.Sprintf("%v", node.Value)
|
|
return visitor.ActionUpdate, name + ": " + value
|
|
case map[string]interface{}:
|
|
|
|
alias := getMapValueString(node, "Alias")
|
|
name := getMapValueString(node, "Name")
|
|
args := toSliceString(getMapValue(node, "Arguments"))
|
|
directives := toSliceString(getMapValue(node, "Directives"))
|
|
selectionSet := getMapValueString(node, "SelectionSet")
|
|
|
|
str := join(
|
|
[]string{
|
|
wrap("", alias, ": ") + name + wrap("(", join(args, ", "), ")"),
|
|
join(directives, " "),
|
|
selectionSet,
|
|
},
|
|
" ",
|
|
)
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"Argument": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.FragmentSpread:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
directives := toSliceString(node.Directives)
|
|
return visitor.ActionUpdate, "..." + name + wrap(" ", join(directives, " "), "")
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
value := getMapValueString(node, "Value")
|
|
return visitor.ActionUpdate, name + ": " + value
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
|
|
// Fragments
|
|
"FragmentSpread": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.InlineFragment:
|
|
typeCondition := fmt.Sprintf("%v", node.TypeCondition)
|
|
directives := toSliceString(node.Directives)
|
|
selectionSet := fmt.Sprintf("%v", node.SelectionSet)
|
|
return visitor.ActionUpdate, "... on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
directives := toSliceString(getMapValue(node, "Directives"))
|
|
return visitor.ActionUpdate, "..." + name + wrap(" ", join(directives, " "), "")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"InlineFragment": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case map[string]interface{}:
|
|
typeCondition := getMapValueString(node, "TypeCondition")
|
|
directives := toSliceString(getMapValue(node, "Directives"))
|
|
selectionSet := getMapValueString(node, "SelectionSet")
|
|
return visitor.ActionUpdate,
|
|
join([]string{
|
|
"...",
|
|
wrap("on ", typeCondition, ""),
|
|
join(directives, " "),
|
|
selectionSet,
|
|
}, " ")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"FragmentDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.FragmentDefinition:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
typeCondition := fmt.Sprintf("%v", node.TypeCondition)
|
|
directives := toSliceString(node.Directives)
|
|
selectionSet := fmt.Sprintf("%v", node.SelectionSet)
|
|
return visitor.ActionUpdate, "fragment " + name + " on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
typeCondition := getMapValueString(node, "TypeCondition")
|
|
directives := toSliceString(getMapValue(node, "Directives"))
|
|
selectionSet := getMapValueString(node, "SelectionSet")
|
|
return visitor.ActionUpdate, "fragment " + name + " on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
|
|
// Value
|
|
"IntValue": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.IntValue:
|
|
return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value)
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, getMapValueString(node, "Value")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"FloatValue": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.FloatValue:
|
|
return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value)
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, getMapValueString(node, "Value")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"StringValue": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.StringValue:
|
|
return visitor.ActionUpdate, `"` + fmt.Sprintf("%v", node.Value) + `"`
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, `"` + getMapValueString(node, "Value") + `"`
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"BooleanValue": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.BooleanValue:
|
|
return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value)
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, getMapValueString(node, "Value")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"EnumValue": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.EnumValue:
|
|
return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value)
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, getMapValueString(node, "Value")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"ListValue": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.ListValue:
|
|
return visitor.ActionUpdate, "[" + join(toSliceString(node.Values), ", ") + "]"
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, "[" + join(toSliceString(getMapValue(node, "Values")), ", ") + "]"
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"ObjectValue": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.ObjectValue:
|
|
return visitor.ActionUpdate, "{" + join(toSliceString(node.Fields), ", ") + "}"
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, "{" + join(toSliceString(getMapValue(node, "Fields")), ", ") + "}"
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"ObjectField": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.ObjectField:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
value := fmt.Sprintf("%v", node.Value)
|
|
return visitor.ActionUpdate, name + ": " + value
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
value := getMapValueString(node, "Value")
|
|
return visitor.ActionUpdate, name + ": " + value
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
|
|
// Directive
|
|
"Directive": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.Directive:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
args := toSliceString(node.Arguments)
|
|
return visitor.ActionUpdate, "@" + name + wrap("(", join(args, ", "), ")")
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
args := toSliceString(getMapValue(node, "Arguments"))
|
|
return visitor.ActionUpdate, "@" + name + wrap("(", join(args, ", "), ")")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
|
|
// Type
|
|
"Named": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.Named:
|
|
return visitor.ActionUpdate, fmt.Sprintf("%v", node.Name)
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, getMapValueString(node, "Name")
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"List": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.List:
|
|
return visitor.ActionUpdate, "[" + fmt.Sprintf("%v", node.Type) + "]"
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, "[" + getMapValueString(node, "Type") + "]"
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"NonNull": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.NonNull:
|
|
return visitor.ActionUpdate, fmt.Sprintf("%v", node.Type) + "!"
|
|
case map[string]interface{}:
|
|
return visitor.ActionUpdate, getMapValueString(node, "Type") + "!"
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
|
|
// Type System Definitions
|
|
"SchemaDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.SchemaDefinition:
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
str := join([]string{
|
|
"schema",
|
|
join(directives, " "),
|
|
block(node.OperationTypes),
|
|
}, " ")
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
operationTypes := toSliceString(getMapValue(node, "OperationTypes"))
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
str := join([]string{
|
|
"schema",
|
|
join(directives, " "),
|
|
block(operationTypes),
|
|
}, " ")
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"OperationTypeDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.OperationTypeDefinition:
|
|
str := fmt.Sprintf("%v: %v", node.Operation, node.Type)
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
operation := getMapValueString(node, "Operation")
|
|
ttype := getMapValueString(node, "Type")
|
|
str := fmt.Sprintf("%v: %v", operation, ttype)
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"ScalarDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.ScalarDefinition:
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
str := join([]string{
|
|
"scalar",
|
|
fmt.Sprintf("%v", node.Name),
|
|
join(directives, " "),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
str := join([]string{
|
|
"scalar",
|
|
name,
|
|
join(directives, " "),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"ObjectDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.ObjectDefinition:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
interfaces := toSliceString(node.Interfaces)
|
|
fields := node.Fields
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
str := join([]string{
|
|
"type",
|
|
name,
|
|
wrap("implements ", join(interfaces, " & "), ""),
|
|
join(directives, " "),
|
|
block(fields),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
interfaces := toSliceString(getMapValue(node, "Interfaces"))
|
|
fields := getMapValue(node, "Fields")
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
str := join([]string{
|
|
"type",
|
|
name,
|
|
wrap("implements ", join(interfaces, " & "), ""),
|
|
join(directives, " "),
|
|
block(fields),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"FieldDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.FieldDefinition:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
ttype := fmt.Sprintf("%v", node.Type)
|
|
args := toSliceString(node.Arguments)
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
hasArgDesc := false
|
|
for _, arg := range node.Arguments {
|
|
if arg.Description != nil && arg.Description.Value != "" {
|
|
hasArgDesc = true
|
|
break
|
|
}
|
|
}
|
|
var argsStr string
|
|
if hasArgDesc {
|
|
argsStr = wrap("(", indent("\n"+join(args, "\n")), "\n)")
|
|
} else {
|
|
argsStr = wrap("(", join(args, ", "), ")")
|
|
}
|
|
str := name + argsStr + ": " + ttype + wrap(" ", join(directives, " "), "")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
ttype := getMapValueString(node, "Type")
|
|
args := toSliceString(getMapValue(node, "Arguments"))
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
hasArgDesc := false
|
|
for _, arg := range args {
|
|
if strings.HasPrefix(strings.TrimSpace(arg), `"""`) {
|
|
hasArgDesc = true
|
|
break
|
|
}
|
|
}
|
|
var argsStr string
|
|
if hasArgDesc {
|
|
argsStr = wrap("(", indent("\n"+join(args, "\n")), "\n)")
|
|
} else {
|
|
argsStr = wrap("(", join(args, ", "), ")")
|
|
}
|
|
str := name + argsStr + ": " + ttype + wrap(" ", join(directives, " "), "")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"InputValueDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.InputValueDefinition:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
ttype := fmt.Sprintf("%v", node.Type)
|
|
defaultValue := fmt.Sprintf("%v", node.DefaultValue)
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
str := join([]string{
|
|
name + ": " + ttype,
|
|
wrap("= ", defaultValue, ""),
|
|
join(directives, " "),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("\n%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
ttype := getMapValueString(node, "Type")
|
|
defaultValue := getMapValueString(node, "DefaultValue")
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
str := join([]string{
|
|
name + ": " + ttype,
|
|
wrap("= ", defaultValue, ""),
|
|
join(directives, " "),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("\n%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"InterfaceDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.InterfaceDefinition:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
fields := node.Fields
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
str := join([]string{
|
|
"interface",
|
|
name,
|
|
join(directives, " "),
|
|
block(fields),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
fields := getMapValue(node, "Fields")
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
str := join([]string{
|
|
"interface",
|
|
name,
|
|
join(directives, " "),
|
|
block(fields),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"UnionDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.UnionDefinition:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
types := toSliceString(node.Types)
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
str := join([]string{
|
|
"union",
|
|
name,
|
|
join(directives, " "),
|
|
"= " + join(types, " | "),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
types := toSliceString(getMapValue(node, "Types"))
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
str := join([]string{
|
|
"union",
|
|
name,
|
|
join(directives, " "),
|
|
"= " + join(types, " | "),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"EnumDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.EnumDefinition:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
values := node.Values
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
str := join([]string{
|
|
"enum",
|
|
name,
|
|
join(directives, " "),
|
|
block(values),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
values := getMapValue(node, "Values")
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
str := join([]string{
|
|
"enum",
|
|
name,
|
|
join(directives, " "),
|
|
block(values),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"EnumValueDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.EnumValueDefinition:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
str := join([]string{
|
|
name,
|
|
join(directives, " "),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("\n%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
str := join([]string{
|
|
name,
|
|
join(directives, " "),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("\n%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"InputObjectDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.InputObjectDefinition:
|
|
name := fmt.Sprintf("%v", node.Name)
|
|
fields := node.Fields
|
|
directives := []string{}
|
|
for _, directive := range node.Directives {
|
|
directives = append(directives, fmt.Sprintf("%v", directive.Name))
|
|
}
|
|
str := join([]string{
|
|
"input",
|
|
name,
|
|
join(directives, " "),
|
|
block(fields),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
fields := getMapValue(node, "Fields")
|
|
directives := []string{}
|
|
for _, directive := range getMapSliceValue(node, "Directives") {
|
|
directives = append(directives, fmt.Sprintf("%v", directive))
|
|
}
|
|
str := join([]string{
|
|
"input",
|
|
name,
|
|
join(directives, " "),
|
|
block(fields),
|
|
}, " ")
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"TypeExtensionDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.TypeExtensionDefinition:
|
|
definition := fmt.Sprintf("%v", node.Definition)
|
|
str := "extend " + definition
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
definition := getMapValueString(node, "Definition")
|
|
str := "extend " + definition
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
"DirectiveDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
|
|
switch node := p.Node.(type) {
|
|
case *ast.DirectiveDefinition:
|
|
args := toSliceString(node.Arguments)
|
|
hasArgDesc := false
|
|
for _, arg := range node.Arguments {
|
|
if arg.Description != nil && arg.Description.Value != "" {
|
|
hasArgDesc = true
|
|
break
|
|
}
|
|
}
|
|
var argsStr string
|
|
if hasArgDesc {
|
|
argsStr = wrap("(", indent("\n"+join(args, "\n")), "\n)")
|
|
} else {
|
|
argsStr = wrap("(", join(args, ", "), ")")
|
|
}
|
|
str := fmt.Sprintf("directive @%v%v on %v", node.Name, argsStr, join(toSliceString(node.Locations), " | "))
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
case map[string]interface{}:
|
|
name := getMapValueString(node, "Name")
|
|
locations := toSliceString(getMapValue(node, "Locations"))
|
|
args := toSliceString(getMapValue(node, "Arguments"))
|
|
hasArgDesc := false
|
|
for _, arg := range args {
|
|
if strings.HasPrefix(strings.TrimSpace(arg), `"""`) {
|
|
hasArgDesc = true
|
|
break
|
|
}
|
|
}
|
|
var argsStr string
|
|
if hasArgDesc {
|
|
argsStr = wrap("(", indent("\n"+join(args, "\n")), "\n)")
|
|
} else {
|
|
argsStr = wrap("(", join(args, ", "), ")")
|
|
}
|
|
str := fmt.Sprintf("directive @%v%v on %v", name, argsStr, join(locations, " | "))
|
|
if desc := getDescription(node); desc != "" {
|
|
str = fmt.Sprintf("%s\n%s", desc, str)
|
|
}
|
|
return visitor.ActionUpdate, str
|
|
}
|
|
return visitor.ActionNoChange, nil
|
|
},
|
|
}
|
|
|
|
func Print(astNode ast.Node) (printed interface{}) {
|
|
defer func() interface{} {
|
|
if r := recover(); r != nil {
|
|
return fmt.Sprintf("%v", astNode)
|
|
}
|
|
return printed
|
|
}()
|
|
printed = visitor.Visit(astNode, &visitor.VisitorOptions{
|
|
LeaveKindMap: printDocASTReducer,
|
|
}, nil)
|
|
return printed
|
|
}
|