github.com/niko0xdev/gqlgen@v0.17.55-0.20240120102243-2ecff98c3e37/graphql/introspection/type.go (about)

     1  package introspection
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/vektah/gqlparser/v2/ast"
     7  )
     8  
     9  type Type struct {
    10  	schema *ast.Schema
    11  	def    *ast.Definition
    12  	typ    *ast.Type
    13  }
    14  
    15  func WrapTypeFromDef(s *ast.Schema, def *ast.Definition) *Type {
    16  	if def == nil {
    17  		return nil
    18  	}
    19  	return &Type{schema: s, def: def}
    20  }
    21  
    22  func WrapTypeFromType(s *ast.Schema, typ *ast.Type) *Type {
    23  	if typ == nil {
    24  		return nil
    25  	}
    26  
    27  	if !typ.NonNull && typ.NamedType != "" {
    28  		return &Type{schema: s, def: s.Types[typ.NamedType]}
    29  	}
    30  	return &Type{schema: s, typ: typ}
    31  }
    32  
    33  func (t *Type) Kind() string {
    34  	if t.typ != nil {
    35  		if t.typ.NonNull {
    36  			return "NON_NULL"
    37  		}
    38  
    39  		if t.typ.Elem != nil {
    40  			return "LIST"
    41  		}
    42  	} else {
    43  		return string(t.def.Kind)
    44  	}
    45  
    46  	panic("UNKNOWN")
    47  }
    48  
    49  func (t *Type) Name() *string {
    50  	if t.def == nil {
    51  		return nil
    52  	}
    53  	return &t.def.Name
    54  }
    55  
    56  func (t *Type) Description() *string {
    57  	if t.def == nil || t.def.Description == "" {
    58  		return nil
    59  	}
    60  	return &t.def.Description
    61  }
    62  
    63  func (t *Type) Fields(includeDeprecated bool) []Field {
    64  	if t.def == nil || (t.def.Kind != ast.Object && t.def.Kind != ast.Interface) {
    65  		return []Field{}
    66  	}
    67  	fields := []Field{}
    68  	for _, f := range t.def.Fields {
    69  		if strings.HasPrefix(f.Name, "__") {
    70  			continue
    71  		}
    72  
    73  		if !includeDeprecated && f.Directives.ForName("deprecated") != nil {
    74  			continue
    75  		}
    76  
    77  		var args []InputValue
    78  		for _, arg := range f.Arguments {
    79  			args = append(args, InputValue{
    80  				Type:         WrapTypeFromType(t.schema, arg.Type),
    81  				Name:         arg.Name,
    82  				description:  arg.Description,
    83  				DefaultValue: defaultValue(arg.DefaultValue),
    84  			})
    85  		}
    86  
    87  		fields = append(fields, Field{
    88  			Name:        f.Name,
    89  			description: f.Description,
    90  			Args:        args,
    91  			Type:        WrapTypeFromType(t.schema, f.Type),
    92  			deprecation: f.Directives.ForName("deprecated"),
    93  		})
    94  	}
    95  	return fields
    96  }
    97  
    98  func (t *Type) InputFields() []InputValue {
    99  	if t.def == nil || t.def.Kind != ast.InputObject {
   100  		return []InputValue{}
   101  	}
   102  
   103  	res := []InputValue{}
   104  	for _, f := range t.def.Fields {
   105  		res = append(res, InputValue{
   106  			Name:         f.Name,
   107  			description:  f.Description,
   108  			Type:         WrapTypeFromType(t.schema, f.Type),
   109  			DefaultValue: defaultValue(f.DefaultValue),
   110  		})
   111  	}
   112  	return res
   113  }
   114  
   115  func defaultValue(value *ast.Value) *string {
   116  	if value == nil {
   117  		return nil
   118  	}
   119  	val := value.String()
   120  	return &val
   121  }
   122  
   123  func (t *Type) Interfaces() []Type {
   124  	if t.def == nil || t.def.Kind != ast.Object {
   125  		return []Type{}
   126  	}
   127  
   128  	res := []Type{}
   129  	for _, intf := range t.def.Interfaces {
   130  		res = append(res, *WrapTypeFromDef(t.schema, t.schema.Types[intf]))
   131  	}
   132  
   133  	return res
   134  }
   135  
   136  func (t *Type) PossibleTypes() []Type {
   137  	if t.def == nil || (t.def.Kind != ast.Interface && t.def.Kind != ast.Union) {
   138  		return []Type{}
   139  	}
   140  
   141  	res := []Type{}
   142  	for _, pt := range t.schema.GetPossibleTypes(t.def) {
   143  		res = append(res, *WrapTypeFromDef(t.schema, pt))
   144  	}
   145  	return res
   146  }
   147  
   148  func (t *Type) EnumValues(includeDeprecated bool) []EnumValue {
   149  	if t.def == nil || t.def.Kind != ast.Enum {
   150  		return []EnumValue{}
   151  	}
   152  
   153  	res := []EnumValue{}
   154  	for _, val := range t.def.EnumValues {
   155  		if !includeDeprecated && val.Directives.ForName("deprecated") != nil {
   156  			continue
   157  		}
   158  
   159  		res = append(res, EnumValue{
   160  			Name:        val.Name,
   161  			description: val.Description,
   162  			deprecation: val.Directives.ForName("deprecated"),
   163  		})
   164  	}
   165  	return res
   166  }
   167  
   168  func (t *Type) OfType() *Type {
   169  	if t.typ == nil {
   170  		return nil
   171  	}
   172  	if t.typ.NonNull {
   173  		// fake non null nodes
   174  		cpy := *t.typ
   175  		cpy.NonNull = false
   176  
   177  		return WrapTypeFromType(t.schema, &cpy)
   178  	}
   179  	return WrapTypeFromType(t.schema, t.typ.Elem)
   180  }
   181  
   182  func (t *Type) SpecifiedByURL() *string {
   183  	directive := t.def.Directives.ForName("specifiedBy")
   184  	if t.def.Kind != ast.Scalar || directive == nil {
   185  		return nil
   186  	}
   187  	// def: directive @specifiedBy(url: String!) on SCALAR
   188  	// the argument "url" is required.
   189  	url := directive.Arguments.ForName("url")
   190  	return &url.Value.Raw
   191  }