...
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
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
188
189 url := directive.Arguments.ForName("url")
190 return &url.Value.Raw
191 }
192
View as plain text