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