mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 12:54:38 +03:00
Use vendor when building (#201)
* Use vendor code for all go calls * Add missing vendor dependencies * Add travis_retry to yarn install * Fix go test call
This commit is contained in:
committed by
StashAppDev
parent
3e13103264
commit
6a75d5551f
104
vendor/github.com/99designs/gqlgen/codegen/args.go
generated
vendored
Normal file
104
vendor/github.com/99designs/gqlgen/codegen/args.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type ArgSet struct {
|
||||
Args []*FieldArgument
|
||||
FuncDecl string
|
||||
}
|
||||
|
||||
type FieldArgument struct {
|
||||
*ast.ArgumentDefinition
|
||||
TypeReference *config.TypeReference
|
||||
VarName string // The name of the var in go
|
||||
Object *Object // A link back to the parent object
|
||||
Default interface{} // The default value
|
||||
Directives []*Directive
|
||||
Value interface{} // value set in Data
|
||||
}
|
||||
|
||||
func (f *FieldArgument) Stream() bool {
|
||||
return f.Object != nil && f.Object.Stream
|
||||
}
|
||||
|
||||
func (b *builder) buildArg(obj *Object, arg *ast.ArgumentDefinition) (*FieldArgument, error) {
|
||||
tr, err := b.Binder.TypeReference(arg.Type, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
argDirs, err := b.getDirectives(arg.Directives)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newArg := FieldArgument{
|
||||
ArgumentDefinition: arg,
|
||||
TypeReference: tr,
|
||||
Object: obj,
|
||||
VarName: templates.ToGoPrivate(arg.Name),
|
||||
Directives: argDirs,
|
||||
}
|
||||
|
||||
if arg.DefaultValue != nil {
|
||||
newArg.Default, err = arg.DefaultValue.Value(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("default value is not valid: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return &newArg, nil
|
||||
}
|
||||
|
||||
func (b *builder) bindArgs(field *Field, params *types.Tuple) error {
|
||||
var newArgs []*FieldArgument
|
||||
|
||||
nextArg:
|
||||
for j := 0; j < params.Len(); j++ {
|
||||
param := params.At(j)
|
||||
for _, oldArg := range field.Args {
|
||||
if strings.EqualFold(oldArg.Name, param.Name()) {
|
||||
tr, err := b.Binder.TypeReference(oldArg.Type, param.Type())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldArg.TypeReference = tr
|
||||
|
||||
newArgs = append(newArgs, oldArg)
|
||||
continue nextArg
|
||||
}
|
||||
}
|
||||
|
||||
// no matching arg found, abort
|
||||
return fmt.Errorf("arg %s not in schema", param.Name())
|
||||
}
|
||||
|
||||
field.Args = newArgs
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Data) Args() map[string][]*FieldArgument {
|
||||
ret := map[string][]*FieldArgument{}
|
||||
for _, o := range a.Objects {
|
||||
for _, f := range o.Fields {
|
||||
if len(f.Args) > 0 {
|
||||
ret[f.ArgsFunc()] = f.Args
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range a.Directives {
|
||||
if len(d.Args) > 0 {
|
||||
ret[d.ArgsFunc()] = d.Args
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
43
vendor/github.com/99designs/gqlgen/codegen/args.gotpl
generated
vendored
Normal file
43
vendor/github.com/99designs/gqlgen/codegen/args.gotpl
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
{{ range $name, $args := .Args }}
|
||||
func (ec *executionContext) {{ $name }}(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
{{- range $i, $arg := . }}
|
||||
var arg{{$i}} {{ $arg.TypeReference.GO | ref}}
|
||||
if tmp, ok := rawArgs[{{$arg.Name|quote}}]; ok {
|
||||
{{- if $arg.Directives }}
|
||||
getArg0 := func(ctx context.Context) (interface{}, error) { return ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, tmp) }
|
||||
|
||||
{{- range $i, $directive := $arg.Directives }}
|
||||
getArg{{add $i 1}} := func(ctx context.Context) (res interface{}, err error) {
|
||||
{{- range $dArg := $directive.Args }}
|
||||
{{- if and $dArg.TypeReference.IsPtr ( notNil "Value" $dArg ) }}
|
||||
{{ $dArg.VarName }} := {{ $dArg.Value | dump }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
n := getArg{{$i}}
|
||||
return ec.directives.{{$directive.Name|ucFirst}}({{$directive.ResolveArgs "tmp" "n" }})
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
tmp, err = getArg{{$arg.Directives|len}}(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data, ok := tmp.({{ $arg.TypeReference.GO | ref }}) ; ok {
|
||||
arg{{$i}} = data
|
||||
} else {
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be {{ $arg.TypeReference.GO }}`, tmp)
|
||||
}
|
||||
{{- else }}
|
||||
arg{{$i}}, err = ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
args[{{$arg.Name|quote}}] = arg{{$i}}
|
||||
{{- end }}
|
||||
return args, nil
|
||||
}
|
||||
{{ end }}
|
||||
11
vendor/github.com/99designs/gqlgen/codegen/complexity.go
generated
vendored
Normal file
11
vendor/github.com/99designs/gqlgen/codegen/complexity.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package codegen
|
||||
|
||||
func (o *Object) UniqueFields() map[string][]*Field {
|
||||
m := map[string][]*Field{}
|
||||
|
||||
for _, f := range o.Fields {
|
||||
m[f.GoFieldName] = append(m[f.GoFieldName], f)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
436
vendor/github.com/99designs/gqlgen/codegen/config/binder.go
generated
vendored
Normal file
436
vendor/github.com/99designs/gqlgen/codegen/config/binder.go
generated
vendored
Normal file
@@ -0,0 +1,436 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/99designs/gqlgen/internal/code"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
// Binder connects graphql types to golang types using static analysis
|
||||
type Binder struct {
|
||||
pkgs []*packages.Package
|
||||
schema *ast.Schema
|
||||
cfg *Config
|
||||
References []*TypeReference
|
||||
}
|
||||
|
||||
func (c *Config) NewBinder(s *ast.Schema) (*Binder, error) {
|
||||
pkgs, err := packages.Load(&packages.Config{Mode: packages.LoadTypes | packages.LoadSyntax}, c.Models.ReferencedPackages()...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, p := range pkgs {
|
||||
for _, e := range p.Errors {
|
||||
if e.Kind == packages.ListError {
|
||||
return nil, p.Errors[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &Binder{
|
||||
pkgs: pkgs,
|
||||
schema: s,
|
||||
cfg: c,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Binder) TypePosition(typ types.Type) token.Position {
|
||||
named, isNamed := typ.(*types.Named)
|
||||
if !isNamed {
|
||||
return token.Position{
|
||||
Filename: "unknown",
|
||||
}
|
||||
}
|
||||
|
||||
return b.ObjectPosition(named.Obj())
|
||||
}
|
||||
|
||||
func (b *Binder) ObjectPosition(typ types.Object) token.Position {
|
||||
if typ == nil {
|
||||
return token.Position{
|
||||
Filename: "unknown",
|
||||
}
|
||||
}
|
||||
pkg := b.getPkg(typ.Pkg().Path())
|
||||
return pkg.Fset.Position(typ.Pos())
|
||||
}
|
||||
|
||||
func (b *Binder) FindType(pkgName string, typeName string) (types.Type, error) {
|
||||
obj, err := b.FindObject(pkgName, typeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fun, isFunc := obj.(*types.Func); isFunc {
|
||||
return fun.Type().(*types.Signature).Params().At(0).Type(), nil
|
||||
}
|
||||
return obj.Type(), nil
|
||||
}
|
||||
|
||||
func (b *Binder) getPkg(find string) *packages.Package {
|
||||
for _, p := range b.pkgs {
|
||||
if code.NormalizeVendor(find) == code.NormalizeVendor(p.PkgPath) {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var MapType = types.NewMap(types.Typ[types.String], types.NewInterfaceType(nil, nil).Complete())
|
||||
var InterfaceType = types.NewInterfaceType(nil, nil)
|
||||
|
||||
func (b *Binder) DefaultUserObject(name string) (types.Type, error) {
|
||||
models := b.cfg.Models[name].Model
|
||||
if len(models) == 0 {
|
||||
return nil, fmt.Errorf(name + " not found in typemap")
|
||||
}
|
||||
|
||||
if models[0] == "map[string]interface{}" {
|
||||
return MapType, nil
|
||||
}
|
||||
|
||||
if models[0] == "interface{}" {
|
||||
return InterfaceType, nil
|
||||
}
|
||||
|
||||
pkgName, typeName := code.PkgAndType(models[0])
|
||||
if pkgName == "" {
|
||||
return nil, fmt.Errorf("missing package name for %s", name)
|
||||
}
|
||||
|
||||
obj, err := b.FindObject(pkgName, typeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.Type(), nil
|
||||
}
|
||||
|
||||
func (b *Binder) FindObject(pkgName string, typeName string) (types.Object, error) {
|
||||
if pkgName == "" {
|
||||
return nil, fmt.Errorf("package cannot be nil")
|
||||
}
|
||||
fullName := typeName
|
||||
if pkgName != "" {
|
||||
fullName = pkgName + "." + typeName
|
||||
}
|
||||
|
||||
pkg := b.getPkg(pkgName)
|
||||
if pkg == nil {
|
||||
return nil, errors.Errorf("required package was not loaded: %s", fullName)
|
||||
}
|
||||
|
||||
// function based marshalers take precedence
|
||||
for astNode, def := range pkg.TypesInfo.Defs {
|
||||
// only look at defs in the top scope
|
||||
if def == nil || def.Parent() == nil || def.Parent() != pkg.Types.Scope() {
|
||||
continue
|
||||
}
|
||||
|
||||
if astNode.Name == "Marshal"+typeName {
|
||||
return def, nil
|
||||
}
|
||||
}
|
||||
|
||||
// then look for types directly
|
||||
for astNode, def := range pkg.TypesInfo.Defs {
|
||||
// only look at defs in the top scope
|
||||
if def == nil || def.Parent() == nil || def.Parent() != pkg.Types.Scope() {
|
||||
continue
|
||||
}
|
||||
|
||||
if astNode.Name == typeName {
|
||||
return def, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.Errorf("unable to find type %s\n", fullName)
|
||||
}
|
||||
|
||||
func (b *Binder) PointerTo(ref *TypeReference) *TypeReference {
|
||||
newRef := &TypeReference{
|
||||
GO: types.NewPointer(ref.GO),
|
||||
GQL: ref.GQL,
|
||||
CastType: ref.CastType,
|
||||
Definition: ref.Definition,
|
||||
Unmarshaler: ref.Unmarshaler,
|
||||
Marshaler: ref.Marshaler,
|
||||
IsMarshaler: ref.IsMarshaler,
|
||||
}
|
||||
|
||||
b.References = append(b.References, newRef)
|
||||
return newRef
|
||||
}
|
||||
|
||||
// TypeReference is used by args and field types. The Definition can refer to both input and output types.
|
||||
type TypeReference struct {
|
||||
Definition *ast.Definition
|
||||
GQL *ast.Type
|
||||
GO types.Type
|
||||
CastType types.Type // Before calling marshalling functions cast from/to this base type
|
||||
Marshaler *types.Func // When using external marshalling functions this will point to the Marshal function
|
||||
Unmarshaler *types.Func // When using external marshalling functions this will point to the Unmarshal function
|
||||
IsMarshaler bool // Does the type implement graphql.Marshaler and graphql.Unmarshaler
|
||||
}
|
||||
|
||||
func (ref *TypeReference) Elem() *TypeReference {
|
||||
if p, isPtr := ref.GO.(*types.Pointer); isPtr {
|
||||
return &TypeReference{
|
||||
GO: p.Elem(),
|
||||
GQL: ref.GQL,
|
||||
CastType: ref.CastType,
|
||||
Definition: ref.Definition,
|
||||
Unmarshaler: ref.Unmarshaler,
|
||||
Marshaler: ref.Marshaler,
|
||||
IsMarshaler: ref.IsMarshaler,
|
||||
}
|
||||
}
|
||||
|
||||
if ref.IsSlice() {
|
||||
return &TypeReference{
|
||||
GO: ref.GO.(*types.Slice).Elem(),
|
||||
GQL: ref.GQL.Elem,
|
||||
CastType: ref.CastType,
|
||||
Definition: ref.Definition,
|
||||
Unmarshaler: ref.Unmarshaler,
|
||||
Marshaler: ref.Marshaler,
|
||||
IsMarshaler: ref.IsMarshaler,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsPtr() bool {
|
||||
_, isPtr := t.GO.(*types.Pointer)
|
||||
return isPtr
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsNilable() bool {
|
||||
_, isPtr := t.GO.(*types.Pointer)
|
||||
_, isMap := t.GO.(*types.Map)
|
||||
_, isInterface := t.GO.(*types.Interface)
|
||||
return isPtr || isMap || isInterface
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsSlice() bool {
|
||||
_, isSlice := t.GO.(*types.Slice)
|
||||
return t.GQL.Elem != nil && isSlice
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsNamed() bool {
|
||||
_, isSlice := t.GO.(*types.Named)
|
||||
return isSlice
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsStruct() bool {
|
||||
_, isStruct := t.GO.Underlying().(*types.Struct)
|
||||
return isStruct
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsScalar() bool {
|
||||
return t.Definition.Kind == ast.Scalar
|
||||
}
|
||||
|
||||
func (t *TypeReference) UniquenessKey() string {
|
||||
var nullability = "O"
|
||||
if t.GQL.NonNull {
|
||||
nullability = "N"
|
||||
}
|
||||
|
||||
return nullability + t.Definition.Name + "2" + templates.TypeIdentifier(t.GO)
|
||||
}
|
||||
|
||||
func (t *TypeReference) MarshalFunc() string {
|
||||
if t.Definition == nil {
|
||||
panic(errors.New("Definition missing for " + t.GQL.Name()))
|
||||
}
|
||||
|
||||
if t.Definition.Kind == ast.InputObject {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "marshal" + t.UniquenessKey()
|
||||
}
|
||||
|
||||
func (t *TypeReference) UnmarshalFunc() string {
|
||||
if t.Definition == nil {
|
||||
panic(errors.New("Definition missing for " + t.GQL.Name()))
|
||||
}
|
||||
|
||||
if !t.Definition.IsInputType() {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "unmarshal" + t.UniquenessKey()
|
||||
}
|
||||
|
||||
func (b *Binder) PushRef(ret *TypeReference) {
|
||||
b.References = append(b.References, ret)
|
||||
}
|
||||
|
||||
func isMap(t types.Type) bool {
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
_, ok := t.(*types.Map)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isIntf(t types.Type) bool {
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
_, ok := t.(*types.Interface)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret *TypeReference, err error) {
|
||||
var pkgName, typeName string
|
||||
def := b.schema.Types[schemaType.Name()]
|
||||
defer func() {
|
||||
if err == nil && ret != nil {
|
||||
b.PushRef(ret)
|
||||
}
|
||||
}()
|
||||
|
||||
if len(b.cfg.Models[schemaType.Name()].Model) == 0 {
|
||||
return nil, fmt.Errorf("%s was not found", schemaType.Name())
|
||||
}
|
||||
|
||||
for _, model := range b.cfg.Models[schemaType.Name()].Model {
|
||||
if model == "map[string]interface{}" {
|
||||
if !isMap(bindTarget) {
|
||||
continue
|
||||
}
|
||||
return &TypeReference{
|
||||
Definition: def,
|
||||
GQL: schemaType,
|
||||
GO: MapType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if model == "interface{}" {
|
||||
if !isIntf(bindTarget) {
|
||||
continue
|
||||
}
|
||||
return &TypeReference{
|
||||
Definition: def,
|
||||
GQL: schemaType,
|
||||
GO: InterfaceType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
pkgName, typeName = code.PkgAndType(model)
|
||||
if pkgName == "" {
|
||||
return nil, fmt.Errorf("missing package name for %s", schemaType.Name())
|
||||
}
|
||||
|
||||
ref := &TypeReference{
|
||||
Definition: def,
|
||||
GQL: schemaType,
|
||||
}
|
||||
|
||||
obj, err := b.FindObject(pkgName, typeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fun, isFunc := obj.(*types.Func); isFunc {
|
||||
ref.GO = fun.Type().(*types.Signature).Params().At(0).Type()
|
||||
ref.Marshaler = fun
|
||||
ref.Unmarshaler = types.NewFunc(0, fun.Pkg(), "Unmarshal"+typeName, nil)
|
||||
} else if hasMethod(obj.Type(), "MarshalGQL") && hasMethod(obj.Type(), "UnmarshalGQL") {
|
||||
ref.GO = obj.Type()
|
||||
ref.IsMarshaler = true
|
||||
} else if underlying := basicUnderlying(obj.Type()); def.IsLeafType() && underlying != nil && underlying.Kind() == types.String {
|
||||
// Special case for named types wrapping strings. Used by default enum implementations.
|
||||
|
||||
ref.GO = obj.Type()
|
||||
ref.CastType = underlying
|
||||
|
||||
underlyingRef, err := b.TypeReference(&ast.Type{NamedType: "String"}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ref.Marshaler = underlyingRef.Marshaler
|
||||
ref.Unmarshaler = underlyingRef.Unmarshaler
|
||||
} else {
|
||||
ref.GO = obj.Type()
|
||||
}
|
||||
|
||||
ref.GO = b.CopyModifiersFromAst(schemaType, ref.GO)
|
||||
|
||||
if bindTarget != nil {
|
||||
if err = code.CompatibleTypes(ref.GO, bindTarget); err != nil {
|
||||
continue
|
||||
}
|
||||
ref.GO = bindTarget
|
||||
}
|
||||
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%s has type compatible with %s", schemaType.Name(), bindTarget.String())
|
||||
}
|
||||
|
||||
func (b *Binder) CopyModifiersFromAst(t *ast.Type, base types.Type) types.Type {
|
||||
if t.Elem != nil {
|
||||
child := b.CopyModifiersFromAst(t.Elem, base)
|
||||
if _, isStruct := child.Underlying().(*types.Struct); isStruct {
|
||||
child = types.NewPointer(child)
|
||||
}
|
||||
return types.NewSlice(child)
|
||||
}
|
||||
|
||||
var isInterface bool
|
||||
if named, ok := base.(*types.Named); ok {
|
||||
_, isInterface = named.Underlying().(*types.Interface)
|
||||
}
|
||||
|
||||
if !isInterface && !t.NonNull {
|
||||
return types.NewPointer(base)
|
||||
}
|
||||
|
||||
return base
|
||||
}
|
||||
|
||||
func hasMethod(it types.Type, name string) bool {
|
||||
if ptr, isPtr := it.(*types.Pointer); isPtr {
|
||||
it = ptr.Elem()
|
||||
}
|
||||
namedType, ok := it.(*types.Named)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < namedType.NumMethods(); i++ {
|
||||
if namedType.Method(i).Name() == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func basicUnderlying(it types.Type) *types.Basic {
|
||||
if ptr, isPtr := it.(*types.Pointer); isPtr {
|
||||
it = ptr.Elem()
|
||||
}
|
||||
namedType, ok := it.(*types.Named)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if basic, ok := namedType.Underlying().(*types.Basic); ok {
|
||||
return basic
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
410
vendor/github.com/99designs/gqlgen/codegen/config/config.go
generated
vendored
Normal file
410
vendor/github.com/99designs/gqlgen/codegen/config/config.go
generated
vendored
Normal file
@@ -0,0 +1,410 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/internal/code"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
SchemaFilename StringList `yaml:"schema,omitempty"`
|
||||
Exec PackageConfig `yaml:"exec"`
|
||||
Model PackageConfig `yaml:"model"`
|
||||
Resolver PackageConfig `yaml:"resolver,omitempty"`
|
||||
Models TypeMap `yaml:"models,omitempty"`
|
||||
StructTag string `yaml:"struct_tag,omitempty"`
|
||||
}
|
||||
|
||||
var cfgFilenames = []string{".gqlgen.yml", "gqlgen.yml", "gqlgen.yaml"}
|
||||
|
||||
// DefaultConfig creates a copy of the default config
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
SchemaFilename: StringList{"schema.graphql"},
|
||||
Model: PackageConfig{Filename: "models_gen.go"},
|
||||
Exec: PackageConfig{Filename: "generated.go"},
|
||||
}
|
||||
}
|
||||
|
||||
// LoadConfigFromDefaultLocations looks for a config file in the current directory, and all parent directories
|
||||
// walking up the tree. The closest config file will be returned.
|
||||
func LoadConfigFromDefaultLocations() (*Config, error) {
|
||||
cfgFile, err := findCfg()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = os.Chdir(filepath.Dir(cfgFile))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to enter config dir")
|
||||
}
|
||||
return LoadConfig(cfgFile)
|
||||
}
|
||||
|
||||
// LoadConfig reads the gqlgen.yml config file
|
||||
func LoadConfig(filename string) (*Config, error) {
|
||||
config := DefaultConfig()
|
||||
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to read config")
|
||||
}
|
||||
|
||||
if err := yaml.UnmarshalStrict(b, config); err != nil {
|
||||
return nil, errors.Wrap(err, "unable to parse config")
|
||||
}
|
||||
|
||||
preGlobbing := config.SchemaFilename
|
||||
config.SchemaFilename = StringList{}
|
||||
for _, f := range preGlobbing {
|
||||
matches, err := filepath.Glob(f)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to glob schema filename %s", f)
|
||||
}
|
||||
|
||||
for _, m := range matches {
|
||||
if config.SchemaFilename.Has(m) {
|
||||
continue
|
||||
}
|
||||
config.SchemaFilename = append(config.SchemaFilename, m)
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type PackageConfig struct {
|
||||
Filename string `yaml:"filename,omitempty"`
|
||||
Package string `yaml:"package,omitempty"`
|
||||
Type string `yaml:"type,omitempty"`
|
||||
}
|
||||
|
||||
type TypeMapEntry struct {
|
||||
Model StringList `yaml:"model"`
|
||||
Fields map[string]TypeMapField `yaml:"fields,omitempty"`
|
||||
}
|
||||
|
||||
type TypeMapField struct {
|
||||
Resolver bool `yaml:"resolver"`
|
||||
FieldName string `yaml:"fieldName"`
|
||||
}
|
||||
|
||||
type StringList []string
|
||||
|
||||
func (a *StringList) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var single string
|
||||
err := unmarshal(&single)
|
||||
if err == nil {
|
||||
*a = []string{single}
|
||||
return nil
|
||||
}
|
||||
|
||||
var multi []string
|
||||
err = unmarshal(&multi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*a = multi
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a StringList) Has(file string) bool {
|
||||
for _, existing := range a {
|
||||
if existing == file {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *PackageConfig) normalize() error {
|
||||
if c.Filename == "" {
|
||||
return errors.New("Filename is required")
|
||||
}
|
||||
c.Filename = abs(c.Filename)
|
||||
// If Package is not set, first attempt to load the package at the output dir. If that fails
|
||||
// fallback to just the base dir name of the output filename.
|
||||
if c.Package == "" {
|
||||
c.Package = code.NameForDir(c.Dir())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *PackageConfig) ImportPath() string {
|
||||
return code.ImportPathForDir(c.Dir())
|
||||
}
|
||||
|
||||
func (c *PackageConfig) Dir() string {
|
||||
return filepath.Dir(c.Filename)
|
||||
}
|
||||
|
||||
func (c *PackageConfig) Check() error {
|
||||
if strings.ContainsAny(c.Package, "./\\") {
|
||||
return fmt.Errorf("package should be the output package name only, do not include the output filename")
|
||||
}
|
||||
if c.Filename != "" && !strings.HasSuffix(c.Filename, ".go") {
|
||||
return fmt.Errorf("filename should be path to a go source file")
|
||||
}
|
||||
|
||||
return c.normalize()
|
||||
}
|
||||
|
||||
func (c *PackageConfig) Pkg() *types.Package {
|
||||
return types.NewPackage(c.ImportPath(), c.Dir())
|
||||
}
|
||||
|
||||
func (c *PackageConfig) IsDefined() bool {
|
||||
return c.Filename != ""
|
||||
}
|
||||
|
||||
func (c *Config) Check() error {
|
||||
if err := c.Models.Check(); err != nil {
|
||||
return errors.Wrap(err, "config.models")
|
||||
}
|
||||
if err := c.Exec.Check(); err != nil {
|
||||
return errors.Wrap(err, "config.exec")
|
||||
}
|
||||
if err := c.Model.Check(); err != nil {
|
||||
return errors.Wrap(err, "config.model")
|
||||
}
|
||||
if c.Resolver.IsDefined() {
|
||||
if err := c.Resolver.Check(); err != nil {
|
||||
return errors.Wrap(err, "config.resolver")
|
||||
}
|
||||
}
|
||||
|
||||
// check packages names against conflict, if present in the same dir
|
||||
// and check filenames for uniqueness
|
||||
packageConfigList := []PackageConfig{
|
||||
c.Model,
|
||||
c.Exec,
|
||||
c.Resolver,
|
||||
}
|
||||
filesMap := make(map[string]bool)
|
||||
pkgConfigsByDir := make(map[string]PackageConfig)
|
||||
for _, current := range packageConfigList {
|
||||
_, fileFound := filesMap[current.Filename]
|
||||
if fileFound {
|
||||
return fmt.Errorf("filename %s defined more than once", current.Filename)
|
||||
}
|
||||
filesMap[current.Filename] = true
|
||||
previous, inSameDir := pkgConfigsByDir[current.Dir()]
|
||||
if inSameDir && current.Package != previous.Package {
|
||||
return fmt.Errorf("filenames %s and %s are in the same directory but have different package definitions", stripPath(current.Filename), stripPath(previous.Filename))
|
||||
}
|
||||
pkgConfigsByDir[current.Dir()] = current
|
||||
}
|
||||
|
||||
return c.normalize()
|
||||
}
|
||||
|
||||
func stripPath(path string) string {
|
||||
return filepath.Base(path)
|
||||
}
|
||||
|
||||
type TypeMap map[string]TypeMapEntry
|
||||
|
||||
func (tm TypeMap) Exists(typeName string) bool {
|
||||
_, ok := tm[typeName]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (tm TypeMap) UserDefined(typeName string) bool {
|
||||
m, ok := tm[typeName]
|
||||
return ok && len(m.Model) > 0
|
||||
}
|
||||
|
||||
func (tm TypeMap) Check() error {
|
||||
for typeName, entry := range tm {
|
||||
for _, model := range entry.Model {
|
||||
if strings.LastIndex(model, ".") < strings.LastIndex(model, "/") {
|
||||
return fmt.Errorf("model %s: invalid type specifier \"%s\" - you need to specify a struct to map to", typeName, entry.Model)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tm TypeMap) ReferencedPackages() []string {
|
||||
var pkgs []string
|
||||
|
||||
for _, typ := range tm {
|
||||
for _, model := range typ.Model {
|
||||
if model == "map[string]interface{}" || model == "interface{}" {
|
||||
continue
|
||||
}
|
||||
pkg, _ := code.PkgAndType(model)
|
||||
if pkg == "" || inStrSlice(pkgs, pkg) {
|
||||
continue
|
||||
}
|
||||
pkgs = append(pkgs, code.QualifyPackagePath(pkg))
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(pkgs, func(i, j int) bool {
|
||||
return pkgs[i] > pkgs[j]
|
||||
})
|
||||
return pkgs
|
||||
}
|
||||
|
||||
func (tm TypeMap) Add(Name string, goType string) {
|
||||
modelCfg := tm[Name]
|
||||
modelCfg.Model = append(modelCfg.Model, goType)
|
||||
tm[Name] = modelCfg
|
||||
}
|
||||
|
||||
func inStrSlice(haystack []string, needle string) bool {
|
||||
for _, v := range haystack {
|
||||
if needle == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// findCfg searches for the config file in this directory and all parents up the tree
|
||||
// looking for the closest match
|
||||
func findCfg() (string, error) {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "unable to get working dir to findCfg")
|
||||
}
|
||||
|
||||
cfg := findCfgInDir(dir)
|
||||
|
||||
for cfg == "" && dir != filepath.Dir(dir) {
|
||||
dir = filepath.Dir(dir)
|
||||
cfg = findCfgInDir(dir)
|
||||
}
|
||||
|
||||
if cfg == "" {
|
||||
return "", os.ErrNotExist
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func findCfgInDir(dir string) string {
|
||||
for _, cfgName := range cfgFilenames {
|
||||
path := filepath.Join(dir, cfgName)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return path
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *Config) normalize() error {
|
||||
if err := c.Model.normalize(); err != nil {
|
||||
return errors.Wrap(err, "model")
|
||||
}
|
||||
|
||||
if err := c.Exec.normalize(); err != nil {
|
||||
return errors.Wrap(err, "exec")
|
||||
}
|
||||
|
||||
if c.Resolver.IsDefined() {
|
||||
if err := c.Resolver.normalize(); err != nil {
|
||||
return errors.Wrap(err, "resolver")
|
||||
}
|
||||
}
|
||||
|
||||
if c.Models == nil {
|
||||
c.Models = TypeMap{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) InjectBuiltins(s *ast.Schema) {
|
||||
builtins := TypeMap{
|
||||
"__Directive": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Directive"}},
|
||||
"__DirectiveLocation": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}},
|
||||
"__Type": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Type"}},
|
||||
"__TypeKind": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}},
|
||||
"__Field": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Field"}},
|
||||
"__EnumValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.EnumValue"}},
|
||||
"__InputValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.InputValue"}},
|
||||
"__Schema": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Schema"}},
|
||||
"Float": {Model: StringList{"github.com/99designs/gqlgen/graphql.Float"}},
|
||||
"String": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}},
|
||||
"Boolean": {Model: StringList{"github.com/99designs/gqlgen/graphql.Boolean"}},
|
||||
"Int": {Model: StringList{
|
||||
"github.com/99designs/gqlgen/graphql.Int",
|
||||
"github.com/99designs/gqlgen/graphql.Int32",
|
||||
"github.com/99designs/gqlgen/graphql.Int64",
|
||||
}},
|
||||
"ID": {
|
||||
Model: StringList{
|
||||
"github.com/99designs/gqlgen/graphql.ID",
|
||||
"github.com/99designs/gqlgen/graphql.IntID",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for typeName, entry := range builtins {
|
||||
if !c.Models.Exists(typeName) {
|
||||
c.Models[typeName] = entry
|
||||
}
|
||||
}
|
||||
|
||||
// These are additional types that are injected if defined in the schema as scalars.
|
||||
extraBuiltins := TypeMap{
|
||||
"Time": {Model: StringList{"github.com/99designs/gqlgen/graphql.Time"}},
|
||||
"Map": {Model: StringList{"github.com/99designs/gqlgen/graphql.Map"}},
|
||||
"Upload": {Model: StringList{"github.com/99designs/gqlgen/graphql.Upload"}},
|
||||
"Any": {Model: StringList{"github.com/99designs/gqlgen/graphql.Any"}},
|
||||
}
|
||||
|
||||
for typeName, entry := range extraBuiltins {
|
||||
if t, ok := s.Types[typeName]; !c.Models.Exists(typeName) && ok && t.Kind == ast.Scalar {
|
||||
c.Models[typeName] = entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) LoadSchema() (*ast.Schema, map[string]string, error) {
|
||||
schemaStrings := map[string]string{}
|
||||
|
||||
var sources []*ast.Source
|
||||
|
||||
for _, filename := range c.SchemaFilename {
|
||||
filename = filepath.ToSlash(filename)
|
||||
var err error
|
||||
var schemaRaw []byte
|
||||
schemaRaw, err = ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
schemaStrings[filename] = string(schemaRaw)
|
||||
sources = append(sources, &ast.Source{Name: filename, Input: schemaStrings[filename]})
|
||||
}
|
||||
|
||||
schema, err := gqlparser.LoadSchema(sources...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return schema, schemaStrings, nil
|
||||
}
|
||||
|
||||
func abs(path string) string {
|
||||
absPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return filepath.ToSlash(absPath)
|
||||
}
|
||||
168
vendor/github.com/99designs/gqlgen/codegen/data.go
generated
vendored
Normal file
168
vendor/github.com/99designs/gqlgen/codegen/data.go
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
// Data is a unified model of the code to be generated. Plugins may modify this structure to do things like implement
|
||||
// resolvers or directives automatically (eg grpc, validation)
|
||||
type Data struct {
|
||||
Config *config.Config
|
||||
Schema *ast.Schema
|
||||
SchemaStr map[string]string
|
||||
Directives map[string]*Directive
|
||||
Objects Objects
|
||||
Inputs Objects
|
||||
Interfaces map[string]*Interface
|
||||
ReferencedTypes map[string]*config.TypeReference
|
||||
ComplexityRoots map[string]*Object
|
||||
|
||||
QueryRoot *Object
|
||||
MutationRoot *Object
|
||||
SubscriptionRoot *Object
|
||||
}
|
||||
|
||||
type builder struct {
|
||||
Config *config.Config
|
||||
Schema *ast.Schema
|
||||
SchemaStr map[string]string
|
||||
Binder *config.Binder
|
||||
Directives map[string]*Directive
|
||||
}
|
||||
|
||||
func BuildData(cfg *config.Config) (*Data, error) {
|
||||
b := builder{
|
||||
Config: cfg,
|
||||
}
|
||||
|
||||
var err error
|
||||
b.Schema, b.SchemaStr, err = cfg.LoadSchema()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cfg.Check()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg.InjectBuiltins(b.Schema)
|
||||
|
||||
b.Binder, err = b.Config.NewBinder(b.Schema)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.Directives, err = b.buildDirectives()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dataDirectives := make(map[string]*Directive)
|
||||
for name, d := range b.Directives {
|
||||
if !d.Builtin {
|
||||
dataDirectives[name] = d
|
||||
}
|
||||
}
|
||||
|
||||
s := Data{
|
||||
Config: cfg,
|
||||
Directives: dataDirectives,
|
||||
Schema: b.Schema,
|
||||
SchemaStr: b.SchemaStr,
|
||||
Interfaces: map[string]*Interface{},
|
||||
}
|
||||
|
||||
for _, schemaType := range b.Schema.Types {
|
||||
switch schemaType.Kind {
|
||||
case ast.Object:
|
||||
obj, err := b.buildObject(schemaType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to build object definition")
|
||||
}
|
||||
|
||||
s.Objects = append(s.Objects, obj)
|
||||
case ast.InputObject:
|
||||
input, err := b.buildObject(schemaType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to build input definition")
|
||||
}
|
||||
|
||||
s.Inputs = append(s.Inputs, input)
|
||||
|
||||
case ast.Union, ast.Interface:
|
||||
s.Interfaces[schemaType.Name] = b.buildInterface(schemaType)
|
||||
}
|
||||
}
|
||||
|
||||
if s.Schema.Query != nil {
|
||||
s.QueryRoot = s.Objects.ByName(s.Schema.Query.Name)
|
||||
} else {
|
||||
return nil, fmt.Errorf("query entry point missing")
|
||||
}
|
||||
|
||||
if s.Schema.Mutation != nil {
|
||||
s.MutationRoot = s.Objects.ByName(s.Schema.Mutation.Name)
|
||||
}
|
||||
|
||||
if s.Schema.Subscription != nil {
|
||||
s.SubscriptionRoot = s.Objects.ByName(s.Schema.Subscription.Name)
|
||||
}
|
||||
|
||||
if err := b.injectIntrospectionRoots(&s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.ReferencedTypes, err = b.buildTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Slice(s.Objects, func(i, j int) bool {
|
||||
return s.Objects[i].Definition.Name < s.Objects[j].Definition.Name
|
||||
})
|
||||
|
||||
sort.Slice(s.Inputs, func(i, j int) bool {
|
||||
return s.Inputs[i].Definition.Name < s.Inputs[j].Definition.Name
|
||||
})
|
||||
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
func (b *builder) injectIntrospectionRoots(s *Data) error {
|
||||
obj := s.Objects.ByName(b.Schema.Query.Name)
|
||||
if obj == nil {
|
||||
return fmt.Errorf("root query type must be defined")
|
||||
}
|
||||
|
||||
__type, err := b.buildField(obj, &ast.FieldDefinition{
|
||||
Name: "__type",
|
||||
Type: ast.NamedType("__Type", nil),
|
||||
Arguments: []*ast.ArgumentDefinition{
|
||||
{
|
||||
Name: "name",
|
||||
Type: ast.NonNullNamedType("String", nil),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
__schema, err := b.buildField(obj, &ast.FieldDefinition{
|
||||
Name: "__schema",
|
||||
Type: ast.NamedType("__Schema", nil),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
obj.Fields = append(obj.Fields, __type, __schema)
|
||||
|
||||
return nil
|
||||
}
|
||||
152
vendor/github.com/99designs/gqlgen/codegen/directive.go
generated
vendored
Normal file
152
vendor/github.com/99designs/gqlgen/codegen/directive.go
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type Directive struct {
|
||||
Name string
|
||||
Args []*FieldArgument
|
||||
Builtin bool
|
||||
}
|
||||
|
||||
func (b *builder) buildDirectives() (map[string]*Directive, error) {
|
||||
directives := make(map[string]*Directive, len(b.Schema.Directives))
|
||||
|
||||
for name, dir := range b.Schema.Directives {
|
||||
if _, ok := directives[name]; ok {
|
||||
return nil, errors.Errorf("directive with name %s already exists", name)
|
||||
}
|
||||
|
||||
var builtin bool
|
||||
if name == "skip" || name == "include" || name == "deprecated" {
|
||||
builtin = true
|
||||
}
|
||||
|
||||
var args []*FieldArgument
|
||||
for _, arg := range dir.Arguments {
|
||||
tr, err := b.Binder.TypeReference(arg.Type, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newArg := &FieldArgument{
|
||||
ArgumentDefinition: arg,
|
||||
TypeReference: tr,
|
||||
VarName: templates.ToGoPrivate(arg.Name),
|
||||
}
|
||||
|
||||
if arg.DefaultValue != nil {
|
||||
var err error
|
||||
newArg.Default, err = arg.DefaultValue.Value(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("default value for directive argument %s(%s) is not valid: %s", dir.Name, arg.Name, err.Error())
|
||||
}
|
||||
}
|
||||
args = append(args, newArg)
|
||||
}
|
||||
|
||||
directives[name] = &Directive{
|
||||
Name: name,
|
||||
Args: args,
|
||||
Builtin: builtin,
|
||||
}
|
||||
}
|
||||
|
||||
return directives, nil
|
||||
}
|
||||
|
||||
func (b *builder) getDirectives(list ast.DirectiveList) ([]*Directive, error) {
|
||||
dirs := make([]*Directive, len(list))
|
||||
for i, d := range list {
|
||||
argValues := make(map[string]interface{}, len(d.Arguments))
|
||||
for _, da := range d.Arguments {
|
||||
val, err := da.Value.Value(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
argValues[da.Name] = val
|
||||
}
|
||||
def, ok := b.Directives[d.Name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("directive %s not found", d.Name)
|
||||
}
|
||||
|
||||
var args []*FieldArgument
|
||||
for _, a := range def.Args {
|
||||
value := a.Default
|
||||
if argValue, ok := argValues[a.Name]; ok {
|
||||
value = argValue
|
||||
}
|
||||
args = append(args, &FieldArgument{
|
||||
ArgumentDefinition: a.ArgumentDefinition,
|
||||
Value: value,
|
||||
VarName: a.VarName,
|
||||
TypeReference: a.TypeReference,
|
||||
})
|
||||
}
|
||||
dirs[i] = &Directive{
|
||||
Name: d.Name,
|
||||
Args: args,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return dirs, nil
|
||||
}
|
||||
|
||||
func (d *Directive) ArgsFunc() string {
|
||||
if len(d.Args) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "dir_" + d.Name + "_args"
|
||||
}
|
||||
|
||||
func (d *Directive) CallArgs() string {
|
||||
args := []string{"ctx", "obj", "n"}
|
||||
|
||||
for _, arg := range d.Args {
|
||||
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||
}
|
||||
|
||||
return strings.Join(args, ", ")
|
||||
}
|
||||
|
||||
func (d *Directive) ResolveArgs(obj string, next string) string {
|
||||
args := []string{"ctx", obj, next}
|
||||
|
||||
for _, arg := range d.Args {
|
||||
dArg := "&" + arg.VarName
|
||||
if !arg.TypeReference.IsPtr() {
|
||||
if arg.Value != nil {
|
||||
dArg = templates.Dump(arg.Value)
|
||||
} else {
|
||||
dArg = templates.Dump(arg.Default)
|
||||
}
|
||||
} else if arg.Value == nil && arg.Default == nil {
|
||||
dArg = "nil"
|
||||
}
|
||||
|
||||
args = append(args, dArg)
|
||||
}
|
||||
|
||||
return strings.Join(args, ", ")
|
||||
}
|
||||
|
||||
func (d *Directive) Declaration() string {
|
||||
res := ucFirst(d.Name) + " func(ctx context.Context, obj interface{}, next graphql.Resolver"
|
||||
|
||||
for _, arg := range d.Args {
|
||||
res += fmt.Sprintf(", %s %s", arg.Name, templates.CurrentImports.LookupType(arg.TypeReference.GO))
|
||||
}
|
||||
|
||||
res += ") (res interface{}, err error)"
|
||||
return res
|
||||
}
|
||||
394
vendor/github.com/99designs/gqlgen/codegen/field.go
generated
vendored
Normal file
394
vendor/github.com/99designs/gqlgen/codegen/field.go
generated
vendored
Normal file
@@ -0,0 +1,394 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"log"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type Field struct {
|
||||
*ast.FieldDefinition
|
||||
|
||||
TypeReference *config.TypeReference
|
||||
GoFieldType GoFieldType // The field type in go, if any
|
||||
GoReceiverName string // The name of method & var receiver in go, if any
|
||||
GoFieldName string // The name of the method or var in go, if any
|
||||
IsResolver bool // Does this field need a resolver
|
||||
Args []*FieldArgument // A list of arguments to be passed to this field
|
||||
MethodHasContext bool // If this is bound to a go method, does the method also take a context
|
||||
NoErr bool // If this is bound to a go method, does that method have an error as the second argument
|
||||
Object *Object // A link back to the parent object
|
||||
Default interface{} // The default value
|
||||
Directives []*Directive
|
||||
}
|
||||
|
||||
func (b *builder) buildField(obj *Object, field *ast.FieldDefinition) (*Field, error) {
|
||||
dirs, err := b.getDirectives(field.Directives)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := Field{
|
||||
FieldDefinition: field,
|
||||
Object: obj,
|
||||
Directives: dirs,
|
||||
GoFieldName: templates.ToGo(field.Name),
|
||||
GoFieldType: GoFieldVariable,
|
||||
GoReceiverName: "obj",
|
||||
}
|
||||
|
||||
if field.DefaultValue != nil {
|
||||
var err error
|
||||
f.Default, err = field.DefaultValue.Value(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("default value %s is not valid: %s", field.Name, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
for _, arg := range field.Arguments {
|
||||
newArg, err := b.buildArg(obj, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.Args = append(f.Args, newArg)
|
||||
}
|
||||
|
||||
if err = b.bindField(obj, &f); err != nil {
|
||||
f.IsResolver = true
|
||||
log.Println(err.Error())
|
||||
}
|
||||
|
||||
if f.IsResolver && !f.TypeReference.IsPtr() && f.TypeReference.IsStruct() {
|
||||
f.TypeReference = b.Binder.PointerTo(f.TypeReference)
|
||||
}
|
||||
|
||||
return &f, nil
|
||||
}
|
||||
|
||||
func (b *builder) bindField(obj *Object, f *Field) error {
|
||||
defer func() {
|
||||
if f.TypeReference == nil {
|
||||
tr, err := b.Binder.TypeReference(f.Type, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
f.TypeReference = tr
|
||||
}
|
||||
}()
|
||||
|
||||
switch {
|
||||
case f.Name == "__schema":
|
||||
f.GoFieldType = GoFieldMethod
|
||||
f.GoReceiverName = "ec"
|
||||
f.GoFieldName = "introspectSchema"
|
||||
return nil
|
||||
case f.Name == "__type":
|
||||
f.GoFieldType = GoFieldMethod
|
||||
f.GoReceiverName = "ec"
|
||||
f.GoFieldName = "introspectType"
|
||||
return nil
|
||||
case obj.Root:
|
||||
f.IsResolver = true
|
||||
return nil
|
||||
case b.Config.Models[obj.Name].Fields[f.Name].Resolver:
|
||||
f.IsResolver = true
|
||||
return nil
|
||||
case obj.Type == config.MapType:
|
||||
f.GoFieldType = GoFieldMap
|
||||
return nil
|
||||
case b.Config.Models[obj.Name].Fields[f.Name].FieldName != "":
|
||||
f.GoFieldName = b.Config.Models[obj.Name].Fields[f.Name].FieldName
|
||||
}
|
||||
|
||||
target, err := b.findBindTarget(obj.Type.(*types.Named), f.GoFieldName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pos := b.Binder.ObjectPosition(target)
|
||||
|
||||
switch target := target.(type) {
|
||||
case nil:
|
||||
objPos := b.Binder.TypePosition(obj.Type)
|
||||
return fmt.Errorf(
|
||||
"%s:%d adding resolver method for %s.%s, nothing matched",
|
||||
objPos.Filename,
|
||||
objPos.Line,
|
||||
obj.Name,
|
||||
f.Name,
|
||||
)
|
||||
|
||||
case *types.Func:
|
||||
sig := target.Type().(*types.Signature)
|
||||
if sig.Results().Len() == 1 {
|
||||
f.NoErr = true
|
||||
} else if sig.Results().Len() != 2 {
|
||||
return fmt.Errorf("method has wrong number of args")
|
||||
}
|
||||
params := sig.Params()
|
||||
// If the first argument is the context, remove it from the comparison and set
|
||||
// the MethodHasContext flag so that the context will be passed to this model's method
|
||||
if params.Len() > 0 && params.At(0).Type().String() == "context.Context" {
|
||||
f.MethodHasContext = true
|
||||
vars := make([]*types.Var, params.Len()-1)
|
||||
for i := 1; i < params.Len(); i++ {
|
||||
vars[i-1] = params.At(i)
|
||||
}
|
||||
params = types.NewTuple(vars...)
|
||||
}
|
||||
|
||||
if err = b.bindArgs(f, params); err != nil {
|
||||
return errors.Wrapf(err, "%s:%d", pos.Filename, pos.Line)
|
||||
}
|
||||
|
||||
result := sig.Results().At(0)
|
||||
tr, err := b.Binder.TypeReference(f.Type, result.Type())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// success, args and return type match. Bind to method
|
||||
f.GoFieldType = GoFieldMethod
|
||||
f.GoReceiverName = "obj"
|
||||
f.GoFieldName = target.Name()
|
||||
f.TypeReference = tr
|
||||
|
||||
return nil
|
||||
|
||||
case *types.Var:
|
||||
tr, err := b.Binder.TypeReference(f.Type, target.Type())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// success, bind to var
|
||||
f.GoFieldType = GoFieldVariable
|
||||
f.GoReceiverName = "obj"
|
||||
f.GoFieldName = target.Name()
|
||||
f.TypeReference = tr
|
||||
|
||||
return nil
|
||||
default:
|
||||
panic(fmt.Errorf("unknown bind target %T for %s", target, f.Name))
|
||||
}
|
||||
}
|
||||
|
||||
// findField attempts to match the name to a struct field with the following
|
||||
// priorites:
|
||||
// 1. Any method with a matching name
|
||||
// 2. Any Fields with a struct tag (see config.StructTag)
|
||||
// 3. Any fields with a matching name
|
||||
// 4. Same logic again for embedded fields
|
||||
func (b *builder) findBindTarget(named *types.Named, name string) (types.Object, error) {
|
||||
for i := 0; i < named.NumMethods(); i++ {
|
||||
method := named.Method(i)
|
||||
if !method.Exported() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !strings.EqualFold(method.Name(), name) {
|
||||
continue
|
||||
}
|
||||
|
||||
return method, nil
|
||||
}
|
||||
|
||||
strukt, ok := named.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a struct")
|
||||
}
|
||||
return b.findBindStructTarget(strukt, name)
|
||||
}
|
||||
|
||||
func (b *builder) findBindStructTarget(strukt *types.Struct, name string) (types.Object, error) {
|
||||
// struct tags have the highest priority
|
||||
if b.Config.StructTag != "" {
|
||||
var foundField *types.Var
|
||||
for i := 0; i < strukt.NumFields(); i++ {
|
||||
field := strukt.Field(i)
|
||||
if !field.Exported() {
|
||||
continue
|
||||
}
|
||||
tags := reflect.StructTag(strukt.Tag(i))
|
||||
if val, ok := tags.Lookup(b.Config.StructTag); ok && equalFieldName(val, name) {
|
||||
if foundField != nil {
|
||||
return nil, errors.Errorf("tag %s is ambigious; multiple fields have the same tag value of %s", b.Config.StructTag, val)
|
||||
}
|
||||
|
||||
foundField = field
|
||||
}
|
||||
}
|
||||
if foundField != nil {
|
||||
return foundField, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Then matching field names
|
||||
for i := 0; i < strukt.NumFields(); i++ {
|
||||
field := strukt.Field(i)
|
||||
if !field.Exported() {
|
||||
continue
|
||||
}
|
||||
if equalFieldName(field.Name(), name) { // aqui!
|
||||
return field, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Then look in embedded structs
|
||||
for i := 0; i < strukt.NumFields(); i++ {
|
||||
field := strukt.Field(i)
|
||||
if !field.Exported() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !field.Anonymous() {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldType := field.Type()
|
||||
if ptr, ok := fieldType.(*types.Pointer); ok {
|
||||
fieldType = ptr.Elem()
|
||||
}
|
||||
|
||||
switch fieldType := fieldType.(type) {
|
||||
case *types.Named:
|
||||
f, err := b.findBindTarget(fieldType, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f != nil {
|
||||
return f, nil
|
||||
}
|
||||
case *types.Struct:
|
||||
f, err := b.findBindStructTarget(fieldType, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f != nil {
|
||||
return f, nil
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("unknown embedded field type %T", field.Type()))
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (f *Field) HasDirectives() bool {
|
||||
return len(f.Directives) > 0
|
||||
}
|
||||
|
||||
func (f *Field) IsReserved() bool {
|
||||
return strings.HasPrefix(f.Name, "__")
|
||||
}
|
||||
|
||||
func (f *Field) IsMethod() bool {
|
||||
return f.GoFieldType == GoFieldMethod
|
||||
}
|
||||
|
||||
func (f *Field) IsVariable() bool {
|
||||
return f.GoFieldType == GoFieldVariable
|
||||
}
|
||||
|
||||
func (f *Field) IsMap() bool {
|
||||
return f.GoFieldType == GoFieldMap
|
||||
}
|
||||
|
||||
func (f *Field) IsConcurrent() bool {
|
||||
if f.Object.DisableConcurrency {
|
||||
return false
|
||||
}
|
||||
return f.MethodHasContext || f.IsResolver
|
||||
}
|
||||
|
||||
func (f *Field) GoNameUnexported() string {
|
||||
return templates.ToGoPrivate(f.Name)
|
||||
}
|
||||
|
||||
func (f *Field) ShortInvocation() string {
|
||||
return fmt.Sprintf("%s().%s(%s)", f.Object.Definition.Name, f.GoFieldName, f.CallArgs())
|
||||
}
|
||||
|
||||
func (f *Field) ArgsFunc() string {
|
||||
if len(f.Args) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "field_" + f.Object.Definition.Name + "_" + f.Name + "_args"
|
||||
}
|
||||
|
||||
func (f *Field) ResolverType() string {
|
||||
if !f.IsResolver {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s().%s(%s)", f.Object.Definition.Name, f.GoFieldName, f.CallArgs())
|
||||
}
|
||||
|
||||
func (f *Field) ShortResolverDeclaration() string {
|
||||
res := "(ctx context.Context"
|
||||
|
||||
if !f.Object.Root {
|
||||
res += fmt.Sprintf(", obj *%s", templates.CurrentImports.LookupType(f.Object.Type))
|
||||
}
|
||||
for _, arg := range f.Args {
|
||||
res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO))
|
||||
}
|
||||
|
||||
result := templates.CurrentImports.LookupType(f.TypeReference.GO)
|
||||
if f.Object.Stream {
|
||||
result = "<-chan " + result
|
||||
}
|
||||
|
||||
res += fmt.Sprintf(") (%s, error)", result)
|
||||
return res
|
||||
}
|
||||
|
||||
func (f *Field) ComplexitySignature() string {
|
||||
res := fmt.Sprintf("func(childComplexity int")
|
||||
for _, arg := range f.Args {
|
||||
res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO))
|
||||
}
|
||||
res += ") int"
|
||||
return res
|
||||
}
|
||||
|
||||
func (f *Field) ComplexityArgs() string {
|
||||
var args []string
|
||||
for _, arg := range f.Args {
|
||||
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||
}
|
||||
|
||||
return strings.Join(args, ", ")
|
||||
}
|
||||
|
||||
func (f *Field) CallArgs() string {
|
||||
var args []string
|
||||
|
||||
if f.IsResolver {
|
||||
args = append(args, "rctx")
|
||||
|
||||
if !f.Object.Root {
|
||||
args = append(args, "obj")
|
||||
}
|
||||
} else {
|
||||
if f.MethodHasContext {
|
||||
args = append(args, "ctx")
|
||||
}
|
||||
}
|
||||
|
||||
for _, arg := range f.Args {
|
||||
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||
}
|
||||
|
||||
return strings.Join(args, ", ")
|
||||
}
|
||||
100
vendor/github.com/99designs/gqlgen/codegen/field.gotpl
generated
vendored
Normal file
100
vendor/github.com/99designs/gqlgen/codegen/field.gotpl
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
{{- range $object := .Objects }}{{- range $field := $object.Fields }}
|
||||
|
||||
{{- if $object.Stream }}
|
||||
func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField) func() graphql.Marshaler {
|
||||
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
|
||||
Field: field,
|
||||
Args: nil,
|
||||
})
|
||||
{{- if $field.Args }}
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.{{ $field.ArgsFunc }}(ctx,rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
// FIXME: subscriptions are missing request middleware stack https://github.com/99designs/gqlgen/issues/259
|
||||
// and Tracer stack
|
||||
rctx := ctx
|
||||
results, err := ec.resolvers.{{ $field.ShortInvocation }}
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return nil
|
||||
}
|
||||
return func() graphql.Marshaler {
|
||||
res, ok := <-results
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return graphql.WriterFunc(func(w io.Writer) {
|
||||
w.Write([]byte{'{'})
|
||||
graphql.MarshalString(field.Alias).MarshalGQL(w)
|
||||
w.Write([]byte{':'})
|
||||
ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res).MarshalGQL(w)
|
||||
w.Write([]byte{'}'})
|
||||
})
|
||||
}
|
||||
}
|
||||
{{ else }}
|
||||
func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField{{ if not $object.Root }}, obj {{$object.Reference | ref}}{{end}}) graphql.Marshaler {
|
||||
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||
defer func () { ec.Tracer.EndFieldExecution(ctx) }()
|
||||
rctx := &graphql.ResolverContext{
|
||||
Object: {{$object.Name|quote}},
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: {{or $field.IsMethod $field.IsResolver}},
|
||||
}
|
||||
ctx = graphql.WithResolverContext(ctx, rctx)
|
||||
{{- if $field.Args }}
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.{{ $field.ArgsFunc }}(ctx,rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
rctx.Args = args
|
||||
{{- end }}
|
||||
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
|
||||
resTmp := ec.FieldMiddleware(ctx, {{if $object.Root}}nil{{else}}obj{{end}}, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
{{- if $field.IsResolver }}
|
||||
return ec.resolvers.{{ $field.ShortInvocation }}
|
||||
{{- else if $field.IsMap }}
|
||||
switch v := {{$field.GoReceiverName}}[{{$field.Name|quote}}].(type) {
|
||||
case {{$field.TypeReference.GO | ref}}:
|
||||
return v, nil
|
||||
case {{$field.TypeReference.Elem.GO | ref}}:
|
||||
return &v, nil
|
||||
case nil:
|
||||
return ({{$field.TypeReference.GO | ref}})(nil), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected type %T for field %s", v, {{ $field.Name | quote}})
|
||||
}
|
||||
{{- else if $field.IsMethod }}
|
||||
{{- if $field.NoErr }}
|
||||
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }}), nil
|
||||
{{- else }}
|
||||
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }})
|
||||
{{- end }}
|
||||
{{- else if $field.IsVariable }}
|
||||
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}, nil
|
||||
{{- end }}
|
||||
})
|
||||
if resTmp == nil {
|
||||
{{- if $field.TypeReference.GQL.NonNull }}
|
||||
if !ec.HasError(rctx) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
{{- end }}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.({{$field.TypeReference.GO | ref}})
|
||||
rctx.Result = res
|
||||
ctx = ec.Tracer.StartFieldChildExecution(ctx)
|
||||
return ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res)
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{- end }}{{- end}}
|
||||
15
vendor/github.com/99designs/gqlgen/codegen/generate.go
generated
vendored
Normal file
15
vendor/github.com/99designs/gqlgen/codegen/generate.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
)
|
||||
|
||||
func GenerateCode(data *Data) error {
|
||||
return templates.Render(templates.Options{
|
||||
PackageName: data.Config.Exec.Package,
|
||||
Filename: data.Config.Exec.Filename,
|
||||
Data: data,
|
||||
RegionTags: true,
|
||||
GeneratedHeader: true,
|
||||
})
|
||||
}
|
||||
256
vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl
generated
vendored
Normal file
256
vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl
generated
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
{{ reserveImport "context" }}
|
||||
{{ reserveImport "fmt" }}
|
||||
{{ reserveImport "io" }}
|
||||
{{ reserveImport "strconv" }}
|
||||
{{ reserveImport "time" }}
|
||||
{{ reserveImport "sync" }}
|
||||
{{ reserveImport "sync/atomic" }}
|
||||
{{ reserveImport "errors" }}
|
||||
{{ reserveImport "bytes" }}
|
||||
|
||||
{{ reserveImport "github.com/vektah/gqlparser" }}
|
||||
{{ reserveImport "github.com/vektah/gqlparser/ast" }}
|
||||
{{ reserveImport "github.com/99designs/gqlgen/graphql" }}
|
||||
{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }}
|
||||
|
||||
|
||||
// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.
|
||||
func NewExecutableSchema(cfg Config) graphql.ExecutableSchema {
|
||||
return &executableSchema{
|
||||
resolvers: cfg.Resolvers,
|
||||
directives: cfg.Directives,
|
||||
complexity: cfg.Complexity,
|
||||
}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Resolvers ResolverRoot
|
||||
Directives DirectiveRoot
|
||||
Complexity ComplexityRoot
|
||||
}
|
||||
|
||||
type ResolverRoot interface {
|
||||
{{- range $object := .Objects -}}
|
||||
{{ if $object.HasResolvers -}}
|
||||
{{$object.Name}}() {{$object.Name}}Resolver
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
type DirectiveRoot struct {
|
||||
{{ range $directive := .Directives }}
|
||||
{{ $directive.Declaration }}
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
type ComplexityRoot struct {
|
||||
{{ range $object := .Objects }}
|
||||
{{ if not $object.IsReserved -}}
|
||||
{{ $object.Name|go }} struct {
|
||||
{{ range $_, $fields := $object.UniqueFields }}
|
||||
{{- $field := index $fields 0 -}}
|
||||
{{ if not $field.IsReserved -}}
|
||||
{{ $field.GoFieldName }} {{ $field.ComplexitySignature }}
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
{{ range $object := .Objects -}}
|
||||
{{ if $object.HasResolvers }}
|
||||
type {{$object.Name}}Resolver interface {
|
||||
{{ range $field := $object.Fields -}}
|
||||
{{- if $field.IsResolver }}
|
||||
{{- $field.GoFieldName}}{{ $field.ShortResolverDeclaration }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
type executableSchema struct {
|
||||
resolvers ResolverRoot
|
||||
directives DirectiveRoot
|
||||
complexity ComplexityRoot
|
||||
}
|
||||
|
||||
func (e *executableSchema) Schema() *ast.Schema {
|
||||
return parsedSchema
|
||||
}
|
||||
|
||||
func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {
|
||||
ec := executionContext{nil, e}
|
||||
_ = ec
|
||||
switch typeName + "." + field {
|
||||
{{ range $object := .Objects }}
|
||||
{{ if not $object.IsReserved }}
|
||||
{{ range $_, $fields := $object.UniqueFields }}
|
||||
{{- $len := len $fields }}
|
||||
{{- range $i, $field := $fields }}
|
||||
{{- $last := eq (add $i 1) $len }}
|
||||
{{- if not $field.IsReserved }}
|
||||
{{- if eq $i 0 }}case {{ end }}"{{$object.Name}}.{{$field.Name}}"{{ if not $last }},{{ else }}:
|
||||
if e.complexity.{{$object.Name|go}}.{{$field.GoFieldName}} == nil {
|
||||
break
|
||||
}
|
||||
{{ if $field.Args }}
|
||||
args, err := ec.{{ $field.ArgsFunc }}(context.TODO(),rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
{{ end }}
|
||||
return e.complexity.{{$object.Name|go}}.{{$field.GoFieldName}}(childComplexity{{if $field.Args}}, {{$field.ComplexityArgs}} {{ end }}), true
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||
{{- if .QueryRoot }}
|
||||
ec := executionContext{graphql.GetRequestContext(ctx), e}
|
||||
|
||||
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
|
||||
data := ec._{{.QueryRoot.Name}}(ctx, op.SelectionSet)
|
||||
var buf bytes.Buffer
|
||||
data.MarshalGQL(&buf)
|
||||
return buf.Bytes()
|
||||
})
|
||||
|
||||
return &graphql.Response{
|
||||
Data: buf,
|
||||
Errors: ec.Errors,
|
||||
Extensions: ec.Extensions,
|
||||
}
|
||||
{{- else }}
|
||||
return graphql.ErrorResponse(ctx, "queries are not supported")
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||
{{- if .MutationRoot }}
|
||||
ec := executionContext{graphql.GetRequestContext(ctx), e}
|
||||
|
||||
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
|
||||
data := ec._{{.MutationRoot.Name}}(ctx, op.SelectionSet)
|
||||
var buf bytes.Buffer
|
||||
data.MarshalGQL(&buf)
|
||||
return buf.Bytes()
|
||||
})
|
||||
|
||||
return &graphql.Response{
|
||||
Data: buf,
|
||||
Errors: ec.Errors,
|
||||
Extensions: ec.Extensions,
|
||||
}
|
||||
{{- else }}
|
||||
return graphql.ErrorResponse(ctx, "mutations are not supported")
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {
|
||||
{{- if .SubscriptionRoot }}
|
||||
ec := executionContext{graphql.GetRequestContext(ctx), e}
|
||||
|
||||
next := ec._{{.SubscriptionRoot.Name}}(ctx, op.SelectionSet)
|
||||
if ec.Errors != nil {
|
||||
return graphql.OneShot(&graphql.Response{Data: []byte("null"), Errors: ec.Errors})
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
return func() *graphql.Response {
|
||||
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
|
||||
buf.Reset()
|
||||
data := next()
|
||||
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
data.MarshalGQL(&buf)
|
||||
return buf.Bytes()
|
||||
})
|
||||
|
||||
if buf == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &graphql.Response{
|
||||
Data: buf,
|
||||
Errors: ec.Errors,
|
||||
Extensions: ec.Extensions,
|
||||
}
|
||||
}
|
||||
{{- else }}
|
||||
return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported"))
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
type executionContext struct {
|
||||
*graphql.RequestContext
|
||||
*executableSchema
|
||||
}
|
||||
|
||||
func (ec *executionContext) FieldMiddleware(ctx context.Context, obj interface{}, next graphql.Resolver) (ret interface{}) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
{{- if .Directives }}
|
||||
rctx := graphql.GetResolverContext(ctx)
|
||||
for _, d := range rctx.Field.Definition.Directives {
|
||||
switch d.Name {
|
||||
{{- range $directive := .Directives }}
|
||||
case "{{$directive.Name}}":
|
||||
if ec.directives.{{$directive.Name|ucFirst}} != nil {
|
||||
{{- if $directive.Args }}
|
||||
rawArgs := d.ArgumentMap(ec.Variables)
|
||||
args, err := ec.{{ $directive.ArgsFunc }}(ctx,rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
n := next
|
||||
next = func(ctx context.Context) (interface{}, error) {
|
||||
return ec.directives.{{$directive.Name|ucFirst}}({{$directive.CallArgs}})
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
res, err := ec.ResolverMiddleware(ctx, next)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return nil
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) introspectSchema() (*introspection.Schema, error) {
|
||||
if ec.DisableIntrospection {
|
||||
return nil, errors.New("introspection disabled")
|
||||
}
|
||||
return introspection.WrapSchema(parsedSchema), nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) introspectType(name string) (*introspection.Type, error) {
|
||||
if ec.DisableIntrospection {
|
||||
return nil, errors.New("introspection disabled")
|
||||
}
|
||||
return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil
|
||||
}
|
||||
|
||||
var parsedSchema = gqlparser.MustLoadSchema(
|
||||
{{- range $filename, $schema := .SchemaStr }}
|
||||
&ast.Source{Name: {{$filename|quote}}, Input: {{$schema|rawQuote}}},
|
||||
{{- end }}
|
||||
)
|
||||
56
vendor/github.com/99designs/gqlgen/codegen/input.gotpl
generated
vendored
Normal file
56
vendor/github.com/99designs/gqlgen/codegen/input.gotpl
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
{{- range $input := .Inputs }}
|
||||
{{- if not .HasUnmarshal }}
|
||||
func (ec *executionContext) unmarshalInput{{ .Name }}(ctx context.Context, v interface{}) ({{.Type | ref}}, error) {
|
||||
var it {{.Type | ref}}
|
||||
var asMap = v.(map[string]interface{})
|
||||
{{ range $field := .Fields}}
|
||||
{{- if $field.Default}}
|
||||
if _, present := asMap[{{$field.Name|quote}}] ; !present {
|
||||
asMap[{{$field.Name|quote}}] = {{ $field.Default | dump }}
|
||||
}
|
||||
{{- end}}
|
||||
{{- end }}
|
||||
|
||||
for k, v := range asMap {
|
||||
switch k {
|
||||
{{- range $field := .Fields }}
|
||||
case {{$field.Name|quote}}:
|
||||
var err error
|
||||
{{- if $field.Directives }}
|
||||
getField0 := func(ctx context.Context) (interface{}, error) { return ec.{{ $field.TypeReference.UnmarshalFunc }}(ctx, v) }
|
||||
|
||||
{{- range $i, $directive := $field.Directives }}
|
||||
getField{{add $i 1}} := func(ctx context.Context) (res interface{}, err error) {
|
||||
{{- range $dArg := $directive.Args }}
|
||||
{{- if and $dArg.TypeReference.IsPtr ( notNil "Value" $dArg ) }}
|
||||
{{ $dArg.VarName }} := {{ $dArg.Value | dump }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
n := getField{{$i}}
|
||||
return ec.directives.{{$directive.Name|ucFirst}}({{$directive.ResolveArgs "it" "n" }})
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
tmp, err := getField{{$field.Directives|len}}(ctx)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
if data, ok := tmp.({{ $field.TypeReference.GO | ref }}) ; ok {
|
||||
it.{{$field.GoFieldName}} = data
|
||||
} else {
|
||||
return it, fmt.Errorf(`unexpected type %T from directive, should be {{ $field.TypeReference.GO }}`, tmp)
|
||||
}
|
||||
{{- else }}
|
||||
it.{{$field.GoFieldName}}, err = ec.{{ $field.TypeReference.UnmarshalFunc }}(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
63
vendor/github.com/99designs/gqlgen/codegen/interface.go
generated
vendored
Normal file
63
vendor/github.com/99designs/gqlgen/codegen/interface.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type Interface struct {
|
||||
*ast.Definition
|
||||
Type types.Type
|
||||
Implementors []InterfaceImplementor
|
||||
InTypemap bool
|
||||
}
|
||||
|
||||
type InterfaceImplementor struct {
|
||||
*ast.Definition
|
||||
|
||||
Interface *Interface
|
||||
Type types.Type
|
||||
}
|
||||
|
||||
func (b *builder) buildInterface(typ *ast.Definition) *Interface {
|
||||
obj, err := b.Binder.DefaultUserObject(typ.Name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
i := &Interface{
|
||||
Definition: typ,
|
||||
Type: obj,
|
||||
InTypemap: b.Config.Models.UserDefined(typ.Name),
|
||||
}
|
||||
|
||||
for _, implementor := range b.Schema.GetPossibleTypes(typ) {
|
||||
obj, err := b.Binder.DefaultUserObject(implementor.Name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
i.Implementors = append(i.Implementors, InterfaceImplementor{
|
||||
Definition: implementor,
|
||||
Type: obj,
|
||||
Interface: i,
|
||||
})
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *InterfaceImplementor) ValueReceiver() bool {
|
||||
interfaceType, err := findGoInterface(i.Interface.Type)
|
||||
if interfaceType == nil || err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
implementorType, err := findGoNamedType(i.Type)
|
||||
if implementorType == nil || err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return types.Implements(implementorType, interfaceType)
|
||||
}
|
||||
20
vendor/github.com/99designs/gqlgen/codegen/interface.gotpl
generated
vendored
Normal file
20
vendor/github.com/99designs/gqlgen/codegen/interface.gotpl
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{{- range $interface := .Interfaces }}
|
||||
|
||||
func (ec *executionContext) _{{$interface.Name}}(ctx context.Context, sel ast.SelectionSet, obj *{{$interface.Type | ref}}) graphql.Marshaler {
|
||||
switch obj := (*obj).(type) {
|
||||
case nil:
|
||||
return graphql.Null
|
||||
{{- range $implementor := $interface.Implementors }}
|
||||
{{- if $implementor.ValueReceiver }}
|
||||
case {{$implementor.Type | ref}}:
|
||||
return ec._{{$implementor.Name}}(ctx, sel, &obj)
|
||||
{{- end}}
|
||||
case *{{$implementor.Type | ref}}:
|
||||
return ec._{{$implementor.Name}}(ctx, sel, obj)
|
||||
{{- end }}
|
||||
default:
|
||||
panic(fmt.Errorf("unexpected type %T", obj))
|
||||
}
|
||||
}
|
||||
|
||||
{{- end }}
|
||||
172
vendor/github.com/99designs/gqlgen/codegen/object.go
generated
vendored
Normal file
172
vendor/github.com/99designs/gqlgen/codegen/object.go
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type GoFieldType int
|
||||
|
||||
const (
|
||||
GoFieldUndefined GoFieldType = iota
|
||||
GoFieldMethod
|
||||
GoFieldVariable
|
||||
GoFieldMap
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
*ast.Definition
|
||||
|
||||
Type types.Type
|
||||
ResolverInterface types.Type
|
||||
Root bool
|
||||
Fields []*Field
|
||||
Implements []*ast.Definition
|
||||
DisableConcurrency bool
|
||||
Stream bool
|
||||
Directives []*Directive
|
||||
}
|
||||
|
||||
func (b *builder) buildObject(typ *ast.Definition) (*Object, error) {
|
||||
dirs, err := b.getDirectives(typ.Directives)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, typ.Name)
|
||||
}
|
||||
|
||||
obj := &Object{
|
||||
Definition: typ,
|
||||
Root: b.Schema.Query == typ || b.Schema.Mutation == typ || b.Schema.Subscription == typ,
|
||||
DisableConcurrency: typ == b.Schema.Mutation,
|
||||
Stream: typ == b.Schema.Subscription,
|
||||
Directives: dirs,
|
||||
ResolverInterface: types.NewNamed(
|
||||
types.NewTypeName(0, b.Config.Exec.Pkg(), typ.Name+"Resolver", nil),
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}
|
||||
|
||||
if !obj.Root {
|
||||
goObject, err := b.Binder.DefaultUserObject(typ.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj.Type = goObject
|
||||
}
|
||||
|
||||
for _, intf := range b.Schema.GetImplements(typ) {
|
||||
obj.Implements = append(obj.Implements, b.Schema.Types[intf.Name])
|
||||
}
|
||||
|
||||
for _, field := range typ.Fields {
|
||||
if strings.HasPrefix(field.Name, "__") {
|
||||
continue
|
||||
}
|
||||
|
||||
var f *Field
|
||||
f, err = b.buildField(obj, field)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj.Fields = append(obj.Fields, f)
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (o *Object) Reference() types.Type {
|
||||
switch o.Type.(type) {
|
||||
case *types.Pointer, *types.Slice, *types.Map:
|
||||
return o.Type
|
||||
}
|
||||
|
||||
return types.NewPointer(o.Type)
|
||||
}
|
||||
|
||||
type Objects []*Object
|
||||
|
||||
func (o *Object) Implementors() string {
|
||||
satisfiedBy := strconv.Quote(o.Name)
|
||||
for _, s := range o.Implements {
|
||||
satisfiedBy += ", " + strconv.Quote(s.Name)
|
||||
}
|
||||
return "[]string{" + satisfiedBy + "}"
|
||||
}
|
||||
|
||||
func (o *Object) HasResolvers() bool {
|
||||
for _, f := range o.Fields {
|
||||
if f.IsResolver {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *Object) HasUnmarshal() bool {
|
||||
if o.Type == config.MapType {
|
||||
return true
|
||||
}
|
||||
for i := 0; i < o.Type.(*types.Named).NumMethods(); i++ {
|
||||
switch o.Type.(*types.Named).Method(i).Name() {
|
||||
case "UnmarshalGQL":
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *Object) HasDirectives() bool {
|
||||
if len(o.Directives) > 0 {
|
||||
return true
|
||||
}
|
||||
for _, f := range o.Fields {
|
||||
if f.HasDirectives() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *Object) IsConcurrent() bool {
|
||||
for _, f := range o.Fields {
|
||||
if f.IsConcurrent() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *Object) IsReserved() bool {
|
||||
return strings.HasPrefix(o.Definition.Name, "__")
|
||||
}
|
||||
|
||||
func (o *Object) Description() string {
|
||||
return o.Definition.Description
|
||||
}
|
||||
|
||||
func (os Objects) ByName(name string) *Object {
|
||||
for i, o := range os {
|
||||
if strings.EqualFold(o.Definition.Name, name) {
|
||||
return os[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ucFirst(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
r := []rune(s)
|
||||
r[0] = unicode.ToUpper(r[0])
|
||||
return string(r)
|
||||
}
|
||||
85
vendor/github.com/99designs/gqlgen/codegen/object.gotpl
generated
vendored
Normal file
85
vendor/github.com/99designs/gqlgen/codegen/object.gotpl
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
{{- range $object := .Objects }}
|
||||
|
||||
var {{ $object.Name|lcFirst}}Implementors = {{$object.Implementors}}
|
||||
|
||||
{{- if .Stream }}
|
||||
func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.RequestContext, sel, {{$object.Name|lcFirst}}Implementors)
|
||||
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
|
||||
Object: {{$object.Name|quote}},
|
||||
})
|
||||
if len(fields) != 1 {
|
||||
ec.Errorf(ctx, "must subscribe to exactly one stream")
|
||||
return nil
|
||||
}
|
||||
|
||||
switch fields[0].Name {
|
||||
{{- range $field := $object.Fields }}
|
||||
case "{{$field.Name}}":
|
||||
return ec._{{$object.Name}}_{{$field.Name}}(ctx, fields[0])
|
||||
{{- end }}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(fields[0].Name))
|
||||
}
|
||||
}
|
||||
{{- else }}
|
||||
func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.SelectionSet{{ if not $object.Root }},obj {{$object.Reference | ref }}{{ end }}) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.RequestContext, sel, {{$object.Name|lcFirst}}Implementors)
|
||||
{{if $object.Root}}
|
||||
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
|
||||
Object: {{$object.Name|quote}},
|
||||
})
|
||||
{{end}}
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString({{$object.Name|quote}})
|
||||
{{- range $field := $object.Fields }}
|
||||
case "{{$field.Name}}":
|
||||
{{- if $field.IsConcurrent }}
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._{{$object.Name}}_{{$field.Name}}(ctx, field{{if not $object.Root}}, obj{{end}})
|
||||
{{- if $field.TypeReference.GQL.NonNull }}
|
||||
if res == graphql.Null {
|
||||
{{- if $object.IsConcurrent }}
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
{{- else }}
|
||||
invalids++
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
return res
|
||||
})
|
||||
{{- else }}
|
||||
out.Values[i] = ec._{{$object.Name}}_{{$field.Name}}(ctx, field{{if not $object.Root}}, obj{{end}})
|
||||
{{- if $field.TypeReference.GQL.NonNull }}
|
||||
if out.Values[i] == graphql.Null {
|
||||
{{- if $object.IsConcurrent }}
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
{{- else }}
|
||||
invalids++
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 { return graphql.Null }
|
||||
return out
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- end }}
|
||||
137
vendor/github.com/99designs/gqlgen/codegen/templates/import.go
generated
vendored
Normal file
137
vendor/github.com/99designs/gqlgen/codegen/templates/import.go
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"strconv"
|
||||
|
||||
"github.com/99designs/gqlgen/internal/code"
|
||||
)
|
||||
|
||||
type Import struct {
|
||||
Name string
|
||||
Path string
|
||||
Alias string
|
||||
}
|
||||
|
||||
type Imports struct {
|
||||
imports []*Import
|
||||
destDir string
|
||||
}
|
||||
|
||||
func (i *Import) String() string {
|
||||
if i.Alias == i.Name {
|
||||
return strconv.Quote(i.Path)
|
||||
}
|
||||
|
||||
return i.Alias + " " + strconv.Quote(i.Path)
|
||||
}
|
||||
|
||||
func (s *Imports) String() string {
|
||||
res := ""
|
||||
for i, imp := range s.imports {
|
||||
if i != 0 {
|
||||
res += "\n"
|
||||
}
|
||||
res += imp.String()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *Imports) Reserve(path string, aliases ...string) (string, error) {
|
||||
if path == "" {
|
||||
panic("empty ambient import")
|
||||
}
|
||||
|
||||
// if we are referencing our own package we dont need an import
|
||||
if code.ImportPathForDir(s.destDir) == path {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
name := code.NameForPackage(path)
|
||||
var alias string
|
||||
if len(aliases) != 1 {
|
||||
alias = name
|
||||
} else {
|
||||
alias = aliases[0]
|
||||
}
|
||||
|
||||
if existing := s.findByPath(path); existing != nil {
|
||||
if existing.Alias == alias {
|
||||
return "", nil
|
||||
}
|
||||
return "", fmt.Errorf("ambient import already exists")
|
||||
}
|
||||
|
||||
if alias := s.findByAlias(alias); alias != nil {
|
||||
return "", fmt.Errorf("ambient import collides on an alias")
|
||||
}
|
||||
|
||||
s.imports = append(s.imports, &Import{
|
||||
Name: name,
|
||||
Path: path,
|
||||
Alias: alias,
|
||||
})
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s *Imports) Lookup(path string) string {
|
||||
if path == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
path = code.NormalizeVendor(path)
|
||||
|
||||
// if we are referencing our own package we dont need an import
|
||||
if code.ImportPathForDir(s.destDir) == path {
|
||||
return ""
|
||||
}
|
||||
|
||||
if existing := s.findByPath(path); existing != nil {
|
||||
return existing.Alias
|
||||
}
|
||||
|
||||
imp := &Import{
|
||||
Name: code.NameForPackage(path),
|
||||
Path: path,
|
||||
}
|
||||
s.imports = append(s.imports, imp)
|
||||
|
||||
alias := imp.Name
|
||||
i := 1
|
||||
for s.findByAlias(alias) != nil {
|
||||
alias = imp.Name + strconv.Itoa(i)
|
||||
i++
|
||||
if i > 10 {
|
||||
panic(fmt.Errorf("too many collisions, last attempt was %s", alias))
|
||||
}
|
||||
}
|
||||
imp.Alias = alias
|
||||
|
||||
return imp.Alias
|
||||
}
|
||||
|
||||
func (s *Imports) LookupType(t types.Type) string {
|
||||
return types.TypeString(t, func(i *types.Package) string {
|
||||
return s.Lookup(i.Path())
|
||||
})
|
||||
}
|
||||
|
||||
func (s Imports) findByPath(importPath string) *Import {
|
||||
for _, imp := range s.imports {
|
||||
if imp.Path == importPath {
|
||||
return imp
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Imports) findByAlias(alias string) *Import {
|
||||
for _, imp := range s.imports {
|
||||
if imp.Alias == alias {
|
||||
return imp
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
570
vendor/github.com/99designs/gqlgen/codegen/templates/templates.go
generated
vendored
Normal file
570
vendor/github.com/99designs/gqlgen/codegen/templates/templates.go
generated
vendored
Normal file
@@ -0,0 +1,570 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
|
||||
"github.com/99designs/gqlgen/internal/imports"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// CurrentImports keeps track of all the import declarations that are needed during the execution of a plugin.
|
||||
// this is done with a global because subtemplates currently get called in functions. Lets aim to remove this eventually.
|
||||
var CurrentImports *Imports
|
||||
|
||||
// Options specify various parameters to rendering a template.
|
||||
type Options struct {
|
||||
// PackageName is a helper that specifies the package header declaration.
|
||||
// In other words, when you write the template you don't need to specify `package X`
|
||||
// at the top of the file. By providing PackageName in the Options, the Render
|
||||
// function will do that for you.
|
||||
PackageName string
|
||||
// Template is a string of the entire template that
|
||||
// will be parsed and rendered. If it's empty,
|
||||
// the plugin processor will look for .gotpl files
|
||||
// in the same directory of where you wrote the plugin.
|
||||
Template string
|
||||
// Filename is the name of the file that will be
|
||||
// written to the system disk once the template is rendered.
|
||||
Filename string
|
||||
RegionTags bool
|
||||
GeneratedHeader bool
|
||||
// Data will be passed to the template execution.
|
||||
Data interface{}
|
||||
Funcs template.FuncMap
|
||||
}
|
||||
|
||||
// Render renders a gql plugin template from the given Options. Render is an
|
||||
// abstraction of the text/template package that makes it easier to write gqlgen
|
||||
// plugins. If Options.Template is empty, the Render function will look for `.gotpl`
|
||||
// files inside the directory where you wrote the plugin.
|
||||
func Render(cfg Options) error {
|
||||
if CurrentImports != nil {
|
||||
panic(fmt.Errorf("recursive or concurrent call to RenderToFile detected"))
|
||||
}
|
||||
CurrentImports = &Imports{destDir: filepath.Dir(cfg.Filename)}
|
||||
|
||||
// load path relative to calling source file
|
||||
_, callerFile, _, _ := runtime.Caller(1)
|
||||
rootDir := filepath.Dir(callerFile)
|
||||
|
||||
funcs := Funcs()
|
||||
for n, f := range cfg.Funcs {
|
||||
funcs[n] = f
|
||||
}
|
||||
t := template.New("").Funcs(funcs)
|
||||
|
||||
var roots []string
|
||||
if cfg.Template != "" {
|
||||
var err error
|
||||
t, err = t.New("template.gotpl").Parse(cfg.Template)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error with provided template")
|
||||
}
|
||||
roots = append(roots, "template.gotpl")
|
||||
} else {
|
||||
// load all the templates in the directory
|
||||
err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name := filepath.ToSlash(strings.TrimPrefix(path, rootDir+string(os.PathSeparator)))
|
||||
if !strings.HasSuffix(info.Name(), ".gotpl") {
|
||||
return nil
|
||||
}
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t, err = t.New(name).Parse(string(b))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, cfg.Filename)
|
||||
}
|
||||
|
||||
roots = append(roots, name)
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "locating templates")
|
||||
}
|
||||
}
|
||||
|
||||
// then execute all the important looking ones in order, adding them to the same file
|
||||
sort.Slice(roots, func(i, j int) bool {
|
||||
// important files go first
|
||||
if strings.HasSuffix(roots[i], "!.gotpl") {
|
||||
return true
|
||||
}
|
||||
if strings.HasSuffix(roots[j], "!.gotpl") {
|
||||
return false
|
||||
}
|
||||
return roots[i] < roots[j]
|
||||
})
|
||||
var buf bytes.Buffer
|
||||
for _, root := range roots {
|
||||
if cfg.RegionTags {
|
||||
buf.WriteString("\n// region " + center(70, "*", " "+root+" ") + "\n")
|
||||
}
|
||||
err := t.Lookup(root).Execute(&buf, cfg.Data)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, root)
|
||||
}
|
||||
if cfg.RegionTags {
|
||||
buf.WriteString("\n// endregion " + center(70, "*", " "+root+" ") + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
var result bytes.Buffer
|
||||
if cfg.GeneratedHeader {
|
||||
result.WriteString("// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\n")
|
||||
}
|
||||
result.WriteString("package ")
|
||||
result.WriteString(cfg.PackageName)
|
||||
result.WriteString("\n\n")
|
||||
result.WriteString("import (\n")
|
||||
result.WriteString(CurrentImports.String())
|
||||
result.WriteString(")\n")
|
||||
_, err := buf.WriteTo(&result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
CurrentImports = nil
|
||||
|
||||
return write(cfg.Filename, result.Bytes())
|
||||
}
|
||||
|
||||
func center(width int, pad string, s string) string {
|
||||
if len(s)+2 > width {
|
||||
return s
|
||||
}
|
||||
lpad := (width - len(s)) / 2
|
||||
rpad := width - (lpad + len(s))
|
||||
return strings.Repeat(pad, lpad) + s + strings.Repeat(pad, rpad)
|
||||
}
|
||||
|
||||
func Funcs() template.FuncMap {
|
||||
return template.FuncMap{
|
||||
"ucFirst": ucFirst,
|
||||
"lcFirst": lcFirst,
|
||||
"quote": strconv.Quote,
|
||||
"rawQuote": rawQuote,
|
||||
"dump": Dump,
|
||||
"ref": ref,
|
||||
"ts": TypeIdentifier,
|
||||
"call": Call,
|
||||
"prefixLines": prefixLines,
|
||||
"notNil": notNil,
|
||||
"reserveImport": CurrentImports.Reserve,
|
||||
"lookupImport": CurrentImports.Lookup,
|
||||
"go": ToGo,
|
||||
"goPrivate": ToGoPrivate,
|
||||
"add": func(a, b int) int {
|
||||
return a + b
|
||||
},
|
||||
"render": func(filename string, tpldata interface{}) (*bytes.Buffer, error) {
|
||||
return render(resolveName(filename, 0), tpldata)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ucFirst(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
r := []rune(s)
|
||||
r[0] = unicode.ToUpper(r[0])
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func lcFirst(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
r := []rune(s)
|
||||
r[0] = unicode.ToLower(r[0])
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func isDelimiter(c rune) bool {
|
||||
return c == '-' || c == '_' || unicode.IsSpace(c)
|
||||
}
|
||||
|
||||
func ref(p types.Type) string {
|
||||
return CurrentImports.LookupType(p)
|
||||
}
|
||||
|
||||
var pkgReplacer = strings.NewReplacer(
|
||||
"/", "ᚋ",
|
||||
".", "ᚗ",
|
||||
"-", "ᚑ",
|
||||
)
|
||||
|
||||
func TypeIdentifier(t types.Type) string {
|
||||
res := ""
|
||||
for {
|
||||
switch it := t.(type) {
|
||||
case *types.Pointer:
|
||||
t.Underlying()
|
||||
res += "ᚖ"
|
||||
t = it.Elem()
|
||||
case *types.Slice:
|
||||
res += "ᚕ"
|
||||
t = it.Elem()
|
||||
case *types.Named:
|
||||
res += pkgReplacer.Replace(it.Obj().Pkg().Path())
|
||||
res += "ᚐ"
|
||||
res += it.Obj().Name()
|
||||
return res
|
||||
case *types.Basic:
|
||||
res += it.Name()
|
||||
return res
|
||||
case *types.Map:
|
||||
res += "map"
|
||||
return res
|
||||
case *types.Interface:
|
||||
res += "interface"
|
||||
return res
|
||||
default:
|
||||
panic(fmt.Errorf("unexpected type %T", it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Call(p *types.Func) string {
|
||||
pkg := CurrentImports.Lookup(p.Pkg().Path())
|
||||
|
||||
if pkg != "" {
|
||||
pkg += "."
|
||||
}
|
||||
|
||||
if p.Type() != nil {
|
||||
// make sure the returned type is listed in our imports.
|
||||
ref(p.Type().(*types.Signature).Results().At(0).Type())
|
||||
}
|
||||
|
||||
return pkg + p.Name()
|
||||
}
|
||||
|
||||
func ToGo(name string) string {
|
||||
runes := make([]rune, 0, len(name))
|
||||
|
||||
wordWalker(name, func(info *wordInfo) {
|
||||
word := info.Word
|
||||
if info.MatchCommonInitial {
|
||||
word = strings.ToUpper(word)
|
||||
} else if !info.HasCommonInitial {
|
||||
if strings.ToUpper(word) == word || strings.ToLower(word) == word {
|
||||
// FOO or foo → Foo
|
||||
// FOo → FOo
|
||||
word = ucFirst(strings.ToLower(word))
|
||||
}
|
||||
}
|
||||
runes = append(runes, []rune(word)...)
|
||||
})
|
||||
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
func ToGoPrivate(name string) string {
|
||||
runes := make([]rune, 0, len(name))
|
||||
|
||||
first := true
|
||||
wordWalker(name, func(info *wordInfo) {
|
||||
word := info.Word
|
||||
if first {
|
||||
if strings.ToUpper(word) == word || strings.ToLower(word) == word {
|
||||
// ID → id, CAMEL → camel
|
||||
word = strings.ToLower(info.Word)
|
||||
} else {
|
||||
// ITicket → iTicket
|
||||
word = lcFirst(info.Word)
|
||||
}
|
||||
first = false
|
||||
} else if info.MatchCommonInitial {
|
||||
word = strings.ToUpper(word)
|
||||
} else if !info.HasCommonInitial {
|
||||
word = ucFirst(strings.ToLower(word))
|
||||
}
|
||||
runes = append(runes, []rune(word)...)
|
||||
})
|
||||
|
||||
return sanitizeKeywords(string(runes))
|
||||
}
|
||||
|
||||
type wordInfo struct {
|
||||
Word string
|
||||
MatchCommonInitial bool
|
||||
HasCommonInitial bool
|
||||
}
|
||||
|
||||
// This function is based on the following code.
|
||||
// https://github.com/golang/lint/blob/06c8688daad7faa9da5a0c2f163a3d14aac986ca/lint.go#L679
|
||||
func wordWalker(str string, f func(*wordInfo)) {
|
||||
runes := []rune(str)
|
||||
w, i := 0, 0 // index of start of word, scan
|
||||
hasCommonInitial := false
|
||||
for i+1 <= len(runes) {
|
||||
eow := false // whether we hit the end of a word
|
||||
if i+1 == len(runes) {
|
||||
eow = true
|
||||
} else if isDelimiter(runes[i+1]) {
|
||||
// underscore; shift the remainder forward over any run of underscores
|
||||
eow = true
|
||||
n := 1
|
||||
for i+n+1 < len(runes) && isDelimiter(runes[i+n+1]) {
|
||||
n++
|
||||
}
|
||||
|
||||
// Leave at most one underscore if the underscore is between two digits
|
||||
if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) {
|
||||
n--
|
||||
}
|
||||
|
||||
copy(runes[i+1:], runes[i+n+1:])
|
||||
runes = runes[:len(runes)-n]
|
||||
} else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) {
|
||||
// lower->non-lower
|
||||
eow = true
|
||||
}
|
||||
i++
|
||||
|
||||
// [w,i) is a word.
|
||||
word := string(runes[w:i])
|
||||
if !eow && commonInitialisms[word] && !unicode.IsLower(runes[i]) {
|
||||
// through
|
||||
// split IDFoo → ID, Foo
|
||||
// but URLs → URLs
|
||||
} else if !eow {
|
||||
if commonInitialisms[word] {
|
||||
hasCommonInitial = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
matchCommonInitial := false
|
||||
if commonInitialisms[strings.ToUpper(word)] {
|
||||
hasCommonInitial = true
|
||||
matchCommonInitial = true
|
||||
}
|
||||
|
||||
f(&wordInfo{
|
||||
Word: word,
|
||||
MatchCommonInitial: matchCommonInitial,
|
||||
HasCommonInitial: hasCommonInitial,
|
||||
})
|
||||
hasCommonInitial = false
|
||||
w = i
|
||||
}
|
||||
}
|
||||
|
||||
var keywords = []string{
|
||||
"break",
|
||||
"default",
|
||||
"func",
|
||||
"interface",
|
||||
"select",
|
||||
"case",
|
||||
"defer",
|
||||
"go",
|
||||
"map",
|
||||
"struct",
|
||||
"chan",
|
||||
"else",
|
||||
"goto",
|
||||
"package",
|
||||
"switch",
|
||||
"const",
|
||||
"fallthrough",
|
||||
"if",
|
||||
"range",
|
||||
"type",
|
||||
"continue",
|
||||
"for",
|
||||
"import",
|
||||
"return",
|
||||
"var",
|
||||
"_",
|
||||
}
|
||||
|
||||
// sanitizeKeywords prevents collisions with go keywords for arguments to resolver functions
|
||||
func sanitizeKeywords(name string) string {
|
||||
for _, k := range keywords {
|
||||
if name == k {
|
||||
return name + "Arg"
|
||||
}
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// commonInitialisms is a set of common initialisms.
|
||||
// Only add entries that are highly unlikely to be non-initialisms.
|
||||
// For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
|
||||
var commonInitialisms = map[string]bool{
|
||||
"ACL": true,
|
||||
"API": true,
|
||||
"ASCII": true,
|
||||
"CPU": true,
|
||||
"CSS": true,
|
||||
"DNS": true,
|
||||
"EOF": true,
|
||||
"GUID": true,
|
||||
"HTML": true,
|
||||
"HTTP": true,
|
||||
"HTTPS": true,
|
||||
"ID": true,
|
||||
"IP": true,
|
||||
"JSON": true,
|
||||
"LHS": true,
|
||||
"QPS": true,
|
||||
"RAM": true,
|
||||
"RHS": true,
|
||||
"RPC": true,
|
||||
"SLA": true,
|
||||
"SMTP": true,
|
||||
"SQL": true,
|
||||
"SSH": true,
|
||||
"TCP": true,
|
||||
"TLS": true,
|
||||
"TTL": true,
|
||||
"UDP": true,
|
||||
"UI": true,
|
||||
"UID": true,
|
||||
"UUID": true,
|
||||
"URI": true,
|
||||
"URL": true,
|
||||
"UTF8": true,
|
||||
"VM": true,
|
||||
"XML": true,
|
||||
"XMPP": true,
|
||||
"XSRF": true,
|
||||
"XSS": true,
|
||||
}
|
||||
|
||||
func rawQuote(s string) string {
|
||||
return "`" + strings.Replace(s, "`", "`+\"`\"+`", -1) + "`"
|
||||
}
|
||||
|
||||
func notNil(field string, data interface{}) bool {
|
||||
v := reflect.ValueOf(data)
|
||||
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() != reflect.Struct {
|
||||
return false
|
||||
}
|
||||
val := v.FieldByName(field)
|
||||
|
||||
return val.IsValid() && !val.IsNil()
|
||||
}
|
||||
|
||||
func Dump(val interface{}) string {
|
||||
switch val := val.(type) {
|
||||
case int:
|
||||
return strconv.Itoa(val)
|
||||
case int64:
|
||||
return fmt.Sprintf("%d", val)
|
||||
case float64:
|
||||
return fmt.Sprintf("%f", val)
|
||||
case string:
|
||||
return strconv.Quote(val)
|
||||
case bool:
|
||||
return strconv.FormatBool(val)
|
||||
case nil:
|
||||
return "nil"
|
||||
case []interface{}:
|
||||
var parts []string
|
||||
for _, part := range val {
|
||||
parts = append(parts, Dump(part))
|
||||
}
|
||||
return "[]interface{}{" + strings.Join(parts, ",") + "}"
|
||||
case map[string]interface{}:
|
||||
buf := bytes.Buffer{}
|
||||
buf.WriteString("map[string]interface{}{")
|
||||
var keys []string
|
||||
for key := range val {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
data := val[key]
|
||||
|
||||
buf.WriteString(strconv.Quote(key))
|
||||
buf.WriteString(":")
|
||||
buf.WriteString(Dump(data))
|
||||
buf.WriteString(",")
|
||||
}
|
||||
buf.WriteString("}")
|
||||
return buf.String()
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %T", val))
|
||||
}
|
||||
}
|
||||
|
||||
func prefixLines(prefix, s string) string {
|
||||
return prefix + strings.Replace(s, "\n", "\n"+prefix, -1)
|
||||
}
|
||||
|
||||
func resolveName(name string, skip int) string {
|
||||
if name[0] == '.' {
|
||||
// load path relative to calling source file
|
||||
_, callerFile, _, _ := runtime.Caller(skip + 1)
|
||||
return filepath.Join(filepath.Dir(callerFile), name[1:])
|
||||
}
|
||||
|
||||
// load path relative to this directory
|
||||
_, callerFile, _, _ := runtime.Caller(0)
|
||||
return filepath.Join(filepath.Dir(callerFile), name)
|
||||
}
|
||||
|
||||
func render(filename string, tpldata interface{}) (*bytes.Buffer, error) {
|
||||
t := template.New("").Funcs(Funcs())
|
||||
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err = t.New(filepath.Base(filename)).Parse(string(b))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
return buf, t.Execute(buf, tpldata)
|
||||
}
|
||||
|
||||
func write(filename string, b []byte) error {
|
||||
err := os.MkdirAll(filepath.Dir(filename), 0755)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create directory")
|
||||
}
|
||||
|
||||
formatted, err := imports.Prune(filename, b)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "gofmt failed on %s: %s\n", filepath.Base(filename), err.Error())
|
||||
formatted = b
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filename, formatted, 0644)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to write %s", filename)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
18
vendor/github.com/99designs/gqlgen/codegen/type.go
generated
vendored
Normal file
18
vendor/github.com/99designs/gqlgen/codegen/type.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
)
|
||||
|
||||
func (b *builder) buildTypes() (map[string]*config.TypeReference, error) {
|
||||
ret := map[string]*config.TypeReference{}
|
||||
|
||||
for _, ref := range b.Binder.References {
|
||||
for ref != nil {
|
||||
ret[ref.UniquenessKey()] = ref
|
||||
|
||||
ref = ref.Elem()
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
130
vendor/github.com/99designs/gqlgen/codegen/type.gotpl
generated
vendored
Normal file
130
vendor/github.com/99designs/gqlgen/codegen/type.gotpl
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
{{- range $type := .ReferencedTypes }}
|
||||
{{ with $type.UnmarshalFunc }}
|
||||
func (ec *executionContext) {{ . }}(ctx context.Context, v interface{}) ({{ $type.GO | ref }}, error) {
|
||||
{{- if $type.IsNilable }}
|
||||
if v == nil { return nil, nil }
|
||||
{{- end }}
|
||||
{{- if $type.IsPtr }}
|
||||
res, err := ec.{{ $type.Elem.UnmarshalFunc }}(ctx, v)
|
||||
return &res, err
|
||||
{{- else if $type.IsSlice }}
|
||||
var vSlice []interface{}
|
||||
if v != nil {
|
||||
if tmp1, ok := v.([]interface{}); ok {
|
||||
vSlice = tmp1
|
||||
} else {
|
||||
vSlice = []interface{}{ v }
|
||||
}
|
||||
}
|
||||
var err error
|
||||
res := make([]{{$type.GO.Elem | ref}}, len(vSlice))
|
||||
for i := range vSlice {
|
||||
res[i], err = ec.{{ $type.Elem.UnmarshalFunc }}(ctx, vSlice[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
{{- else }}
|
||||
{{- if $type.Unmarshaler }}
|
||||
{{- if $type.CastType }}
|
||||
tmp, err := {{ $type.Unmarshaler | call }}(v)
|
||||
return {{ $type.GO | ref }}(tmp), err
|
||||
{{- else}}
|
||||
return {{ $type.Unmarshaler | call }}(v)
|
||||
{{- end }}
|
||||
{{- else if eq ($type.GO | ref) "map[string]interface{}" }}
|
||||
return v.(map[string]interface{}), nil
|
||||
{{- else if $type.IsMarshaler -}}
|
||||
var res {{ $type.GO | ref }}
|
||||
return res, res.UnmarshalGQL(v)
|
||||
{{- else }}
|
||||
return ec.unmarshalInput{{ $type.GQL.Name }}(ctx, v)
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ with $type.MarshalFunc }}
|
||||
func (ec *executionContext) {{ . }}(ctx context.Context, sel ast.SelectionSet, v {{ $type.GO | ref }}) graphql.Marshaler {
|
||||
{{- if $type.IsNilable }}
|
||||
if v == nil {
|
||||
{{- if $type.GQL.NonNull }}
|
||||
if !ec.HasError(graphql.GetResolverContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
{{- end }}
|
||||
return graphql.Null
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- if $type.IsSlice }}
|
||||
{{- if not $type.GQL.NonNull }}
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
{{- end }}
|
||||
ret := make(graphql.Array, len(v))
|
||||
{{- if not $type.IsScalar }}
|
||||
var wg sync.WaitGroup
|
||||
isLen1 := len(v) == 1
|
||||
if !isLen1 {
|
||||
wg.Add(len(v))
|
||||
}
|
||||
{{- end }}
|
||||
for i := range v {
|
||||
{{- if not $type.IsScalar }}
|
||||
i := i
|
||||
rctx := &graphql.ResolverContext{
|
||||
Index: &i,
|
||||
Result: &v[i],
|
||||
}
|
||||
ctx := graphql.WithResolverContext(ctx, rctx)
|
||||
f := func(i int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
if !isLen1 {
|
||||
defer wg.Done()
|
||||
}
|
||||
ret[i] = ec.{{ $type.Elem.MarshalFunc }}(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
} else {
|
||||
go f(i)
|
||||
}
|
||||
{{ else }}
|
||||
ret[i] = ec.{{ $type.Elem.MarshalFunc }}(ctx, sel, v[i])
|
||||
{{- end}}
|
||||
}
|
||||
{{ if not $type.IsScalar }} wg.Wait() {{ end }}
|
||||
return ret
|
||||
{{- else }}
|
||||
|
||||
{{- if $type.IsMarshaler }}
|
||||
return v
|
||||
{{- else if $type.Marshaler }}
|
||||
{{- if $type.IsPtr }}
|
||||
return ec.{{ $type.Elem.MarshalFunc }}(ctx, sel, *v)
|
||||
{{- else if $type.GQL.NonNull }}
|
||||
res := {{ $type.Marshaler | call }}({{- if $type.CastType }}{{ $type.CastType | ref }}(v){{else}}v{{- end }})
|
||||
if res == graphql.Null {
|
||||
if !ec.HasError(graphql.GetResolverContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
}
|
||||
return res
|
||||
{{- else }}
|
||||
return {{ $type.Marshaler | call }}({{- if $type.CastType }}{{ $type.CastType | ref }}(v){{else}}v{{- end }})
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
return ec._{{$type.Definition.Name}}(ctx, sel, {{ if not $type.IsNilable}}&{{end}} v)
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
47
vendor/github.com/99designs/gqlgen/codegen/util.go
generated
vendored
Normal file
47
vendor/github.com/99designs/gqlgen/codegen/util.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func findGoNamedType(def types.Type) (*types.Named, error) {
|
||||
if def == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
namedType, ok := def.(*types.Named)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("expected %s to be a named type, instead found %T\n", def.String(), def)
|
||||
}
|
||||
|
||||
return namedType, nil
|
||||
}
|
||||
|
||||
func findGoInterface(def types.Type) (*types.Interface, error) {
|
||||
if def == nil {
|
||||
return nil, nil
|
||||
}
|
||||
namedType, err := findGoNamedType(def)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if namedType == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
underlying, ok := namedType.Underlying().(*types.Interface)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("expected %s to be a named interface, instead found %s", def.String(), namedType.String())
|
||||
}
|
||||
|
||||
return underlying, nil
|
||||
}
|
||||
|
||||
func equalFieldName(source, target string) bool {
|
||||
source = strings.Replace(source, "_", "", -1)
|
||||
target = strings.Replace(target, "_", "", -1)
|
||||
return strings.EqualFold(source, target)
|
||||
}
|
||||
Reference in New Issue
Block a user