github.com/niko0xdev/gqlgen@v0.17.55-0.20240120102243-2ecff98c3e37/codegen/root_.gotpl (about) 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/niko0xdev/gqlgen/graphql" }} 15 {{ reserveImport "github.com/niko0xdev/gqlgen/graphql/introspection" }} 16 17 // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. 18 func 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 27 type Config struct { 28 Schema *ast.Schema 29 Resolvers ResolverRoot 30 Directives DirectiveRoot 31 Complexity ComplexityRoot 32 } 33 34 type 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 47 type DirectiveRoot struct { 48 {{ range $directive := .Directives }} 49 {{- $directive.Declaration }} 50 {{ end }} 51 } 52 53 type 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 70 type executableSchema struct { 71 schema *ast.Schema 72 resolvers ResolverRoot 73 directives DirectiveRoot 74 complexity ComplexityRoot 75 } 76 77 func (e *executableSchema) Schema() *ast.Schema { 78 if e.schema != nil { 79 return e.schema 80 } 81 return parsedSchema 82 } 83 84 func (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 118 func (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 219 type executionContext struct { 220 *graphql.OperationContext 221 *executableSchema 222 deferred int32 223 pendingDeferred int32 224 deferredResults chan graphql.DeferredResult 225 } 226 227 func (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 246 func (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 253 func (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 }} 263 var sourcesFS embed.FS 264 265 func 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 274 var 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 } 279 var parsedSchema = gqlparser.MustLoadSchema(sources...)