package introspection
import (
"strings"
"github.com/vektah/gqlparser/ast"
)
type Type struct {
schema *ast.Schema
def *ast.Definition
typ *ast.Type
}
func WrapTypeFromDef(s *ast.Schema, def *ast.Definition) *Type {
if def == nil {
return nil
}
return &Type{schema: s, def: def}
}
func WrapTypeFromType(s *ast.Schema, typ *ast.Type) *Type {
if typ == nil {
return nil
}
if !typ.NonNull && typ.NamedType != "" {
return &Type{schema: s, def: s.Types[typ.NamedType]}
}
return &Type{schema: s, typ: typ}
}
func (t *Type) Kind() string {
if t.typ != nil {
if t.typ.NonNull {
return "NON_NULL"
}
if t.typ.Elem != nil {
return "LIST"
}
} else {
return string(t.def.Kind)
}
panic("UNKNOWN")
}
func (t *Type) Name() *string {
if t.def == nil {
return nil
}
return &t.def.Name
}
func (t *Type) Description() string {
if t.def == nil {
return ""
}
return t.def.Description
}
func (t *Type) Fields(includeDeprecated bool) []Field {
if t.def == nil || (t.def.Kind != ast.Object && t.def.Kind != ast.Interface) {
return nil
}
var fields []Field
for _, f := range t.def.Fields {
if strings.HasPrefix(f.Name, "__") {
continue
}
var args []InputValue
for _, arg := range f.Arguments {
args = append(args, InputValue{
Type: WrapTypeFromType(t.schema, arg.Type),
Name: arg.Name,
Description: arg.Description,
DefaultValue: defaultValue(arg.DefaultValue),
})
}
fields = append(fields, Field{
Name: f.Name,
Description: f.Description,
Args: args,
Type: WrapTypeFromType(t.schema, f.Type),
IsDeprecated: isDeprecated(f.Directives),
DeprecationReason: deprecationReason(f.Directives),
})
}
return fields
}
func (t *Type) InputFields() []InputValue {
if t.def == nil || t.def.Kind != ast.InputObject {
return nil
}
var res []InputValue
for _, f := range t.def.Fields {
res = append(res, InputValue{
Name: f.Name,
Description: f.Description,
Type: WrapTypeFromType(t.schema, f.Type),
DefaultValue: defaultValue(f.DefaultValue),
})
}
return res
}
func defaultValue(value *ast.Value) *string {
if value == nil {
return nil
}
val := value.String()
return &val
}
func (t *Type) Interfaces() []Type {
if t.def == nil || t.def.Kind != ast.Object {
return nil
}
var res []Type
for _, intf := range t.def.Interfaces {
res = append(res, *WrapTypeFromDef(t.schema, t.schema.Types[intf]))
}
return res
}
func (t *Type) PossibleTypes() []Type {
if t.def == nil || (t.def.Kind != ast.Interface && t.def.Kind != ast.Union) {
return nil
}
var res []Type
for _, pt := range t.schema.GetPossibleTypes(t.def) {
res = append(res, *WrapTypeFromDef(t.schema, pt))
}
return res
}
func (t *Type) EnumValues(includeDeprecated bool) []EnumValue {
if t.def == nil || t.def.Kind != ast.Enum {
return nil
}
var res []EnumValue
for _, val := range t.def.EnumValues {
res = append(res, EnumValue{
Name: val.Name,
Description: val.Description,
IsDeprecated: isDeprecated(val.Directives),
DeprecationReason: deprecationReason(val.Directives),
})
}
return res
}
func (t *Type) OfType() *Type {
if t.typ == nil {
return nil
}
if t.typ.NonNull {
// fake non null nodes
cpy := *t.typ
cpy.NonNull = false
return WrapTypeFromType(t.schema, &cpy)
}
return WrapTypeFromType(t.schema, t.typ.Elem)
}