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 }