1{{ reserveImport "context" }}
2{{ reserveImport "fmt" }}
3{{ reserveImport "io" }}
4{{ reserveImport "strconv" }}
5{{ reserveImport "time" }}
6{{ reserveImport "sync" }}
7{{ reserveImport "sync/atomic" }}
8{{ reserveImport "errors" }}
9{{ reserveImport "bytes" }}
10{{ reserveImport "embed" }}
11
12{{ reserveImport "github.com/vektah/gqlparser/v2" "gqlparser" }}
13{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }}
14{{ reserveImport "github.com/99designs/gqlgen/graphql" }}
15{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }}
16
17// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.
18func NewExecutableSchema(cfg Config) graphql.ExecutableSchema {
19 return &executableSchema{
20 schema: cfg.Schema,
21 resolvers: cfg.Resolvers,
22 directives: cfg.Directives,
23 complexity: cfg.Complexity,
24 }
25}
26
27type Config struct {
28 Schema *ast.Schema
29 Resolvers ResolverRoot
30 Directives DirectiveRoot
31 Complexity ComplexityRoot
32}
33
34type ResolverRoot interface {
35{{- range $object := .Objects -}}
36 {{ if $object.HasResolvers -}}
37 {{ucFirst $object.Name}}() {{ucFirst $object.Name}}Resolver
38 {{ end }}
39{{- end }}
40{{- range $object := .Inputs -}}
41 {{ if $object.HasResolvers -}}
42 {{ucFirst $object.Name}}() {{ucFirst $object.Name}}Resolver
43 {{ end }}
44{{- end }}
45}
46
47type DirectiveRoot struct {
48{{ range $directive := .Directives }}
49 {{- $directive.Declaration }}
50{{ end }}
51}
52
53type ComplexityRoot struct {
54{{- if not .Config.OmitComplexity }}
55{{ range $object := .Objects }}
56 {{ if not $object.IsReserved -}}
57 {{ ucFirst $object.Name }} struct {
58 {{ range $_, $fields := $object.UniqueFields }}
59 {{- $field := index $fields 0 -}}
60 {{ if not $field.IsReserved -}}
61 {{ $field.GoFieldName }} {{ $field.ComplexitySignature }}
62 {{ end }}
63 {{- end }}
64 }
65 {{- end }}
66{{ end }}
67{{- end }}
68}
69
70type executableSchema struct {
71 schema *ast.Schema
72 resolvers ResolverRoot
73 directives DirectiveRoot
74 complexity ComplexityRoot
75}
76
77func (e *executableSchema) Schema() *ast.Schema {
78 if e.schema != nil {
79 return e.schema
80 }
81 return parsedSchema
82}
83
84func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {
85 ec := executionContext{nil, e, 0, 0, nil}
86 _ = ec
87 {{- if not .Config.OmitComplexity }}
88 switch typeName + "." + field {
89 {{ range $object := .Objects }}
90 {{ if not $object.IsReserved }}
91 {{ range $_, $fields := $object.UniqueFields }}
92 {{- $len := len $fields }}
93 {{- range $i, $field := $fields }}
94 {{- $last := eq (add $i 1) $len }}
95 {{- if not $field.IsReserved }}
96 {{- if eq $i 0 }}case {{ end }}"{{$object.Name}}.{{$field.Name}}"{{ if not $last }},{{ else }}:
97 if e.complexity.{{ucFirst $object.Name }}.{{$field.GoFieldName}} == nil {
98 break
99 }
100 {{ if $field.Args }}
101 args, err := ec.{{ $field.ArgsFunc }}(context.TODO(),rawArgs)
102 if err != nil {
103 return 0, false
104 }
105 {{ end }}
106 return e.complexity.{{ucFirst $object.Name}}.{{$field.GoFieldName}}(childComplexity{{if $field.Args}}, {{$field.ComplexityArgs}} {{ end }}), true
107 {{ end }}
108 {{- end }}
109 {{- end }}
110 {{ end }}
111 {{ end }}
112 {{ end }}
113 }
114 {{- end }}
115 return 0, false
116}
117
118func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
119 rc := graphql.GetOperationContext(ctx)
120 ec := executionContext{rc, e, 0, 0, make(chan graphql.DeferredResult)}
121 inputUnmarshalMap := graphql.BuildUnmarshalerMap(
122 {{- range $input := .Inputs -}}
123 {{ if not $input.HasUnmarshal }}
124 ec.unmarshalInput{{ $input.Name }},
125 {{- end }}
126 {{- end }}
127 )
128 first := true
129
130 switch rc.Operation.Operation {
131 {{- if .QueryRoot }} case ast.Query:
132 return func(ctx context.Context) *graphql.Response {
133 var response graphql.Response
134 var data graphql.Marshaler
135 if first {
136 first = false
137 ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap)
138 {{ if .Directives.LocationDirectives "QUERY" -}}
139 data = ec._queryMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){
140 return ec._{{.QueryRoot.Name}}(ctx, rc.Operation.SelectionSet), nil
141 })
142 {{- else -}}
143 data = ec._{{.QueryRoot.Name}}(ctx, rc.Operation.SelectionSet)
144 {{- end }}
145 } else {
146 if atomic.LoadInt32(&ec.pendingDeferred) > 0 {
147 result := <-ec.deferredResults
148 atomic.AddInt32(&ec.pendingDeferred, -1)
149 data = result.Result
150 response.Path = result.Path
151 response.Label = result.Label
152 response.Errors = result.Errors
153 } else {
154 return nil
155 }
156 }
157 var buf bytes.Buffer
158 data.MarshalGQL(&buf)
159 response.Data = buf.Bytes()
160 if atomic.LoadInt32(&ec.deferred) > 0 {
161 hasNext := atomic.LoadInt32(&ec.pendingDeferred) > 0
162 response.HasNext = &hasNext
163 }
164
165 return &response
166 }
167 {{ end }}
168
169 {{- if .MutationRoot }} case ast.Mutation:
170 return func(ctx context.Context) *graphql.Response {
171 if !first { return nil }
172 first = false
173 ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap)
174 {{ if .Directives.LocationDirectives "MUTATION" -}}
175 data := ec._mutationMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){
176 return ec._{{.MutationRoot.Name}}(ctx, rc.Operation.SelectionSet), nil
177 })
178 {{- else -}}
179 data := ec._{{.MutationRoot.Name}}(ctx, rc.Operation.SelectionSet)
180 {{- end }}
181 var buf bytes.Buffer
182 data.MarshalGQL(&buf)
183
184 return &graphql.Response{
185 Data: buf.Bytes(),
186 }
187 }
188 {{ end }}
189
190 {{- if .SubscriptionRoot }} case ast.Subscription:
191 {{ if .Directives.LocationDirectives "SUBSCRIPTION" -}}
192 next := ec._subscriptionMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){
193 return ec._{{.SubscriptionRoot.Name}}(ctx, rc.Operation.SelectionSet),nil
194 })
195 {{- else -}}
196 next := ec._{{.SubscriptionRoot.Name}}(ctx, rc.Operation.SelectionSet)
197 {{- end }}
198
199 var buf bytes.Buffer
200 return func(ctx context.Context) *graphql.Response {
201 buf.Reset()
202 data := next(ctx)
203
204 if data == nil {
205 return nil
206 }
207 data.MarshalGQL(&buf)
208
209 return &graphql.Response{
210 Data: buf.Bytes(),
211 }
212 }
213 {{ end }}
214 default:
215 return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation"))
216 }
217}
218
219type executionContext struct {
220 *graphql.OperationContext
221 *executableSchema
222 deferred int32
223 pendingDeferred int32
224 deferredResults chan graphql.DeferredResult
225}
226
227func (ec *executionContext) processDeferredGroup(dg graphql.DeferredGroup) {
228 atomic.AddInt32(&ec.pendingDeferred, 1)
229 go func () {
230 ctx := graphql.WithFreshResponseContext(dg.Context)
231 dg.FieldSet.Dispatch(ctx)
232 ds := graphql.DeferredResult{
233 Path: dg.Path,
234 Label: dg.Label,
235 Result: dg.FieldSet,
236 Errors: graphql.GetErrors(ctx),
237 }
238 // null fields should bubble up
239 if dg.FieldSet.Invalids > 0 {
240 ds.Result = graphql.Null
241 }
242 ec.deferredResults <- ds
243 }()
244}
245
246func (ec *executionContext) introspectSchema() (*introspection.Schema, error) {
247 if ec.DisableIntrospection {
248 return nil, errors.New("introspection disabled")
249 }
250 return introspection.WrapSchema(ec.Schema()), nil
251}
252
253func (ec *executionContext) introspectType(name string) (*introspection.Type, error) {
254 if ec.DisableIntrospection {
255 return nil, errors.New("introspection disabled")
256 }
257 return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil
258}
259
260
261{{if .HasEmbeddableSources }}
262//go:embed{{- range $source := .AugmentedSources }}{{if $source.Embeddable}} {{$source.RelativePath|quote}}{{end}}{{- end }}
263var sourcesFS embed.FS
264
265func sourceData(filename string) string {
266 data, err := sourcesFS.ReadFile(filename)
267 if err != nil {
268 panic(fmt.Sprintf("codegen problem: %s not available", filename))
269 }
270 return string(data)
271}
272{{- end}}
273
274var sources = []*ast.Source{
275{{- range $source := .AugmentedSources }}
276 {Name: {{$source.RelativePath|quote}}, Input: {{if (not $source.Embeddable)}}{{$source.Source|rawQuote}}{{else}}sourceData({{$source.RelativePath|quote}}){{end}}, BuiltIn: {{$source.BuiltIn}}},
277{{- end }}
278}
279var parsedSchema = gqlparser.MustLoadSchema(sources...)
View as plain text